diff --git a/shared/source/direct_submission/direct_submission_hw.h b/shared/source/direct_submission/direct_submission_hw.h index ec337519bb..e71ec606e1 100644 --- a/shared/source/direct_submission/direct_submission_hw.h +++ b/shared/source/direct_submission/direct_submission_hw.h @@ -114,8 +114,8 @@ class DirectSubmissionHw { virtual uint64_t switchRingBuffers(); virtual void handleSwitchRingBuffers() = 0; GraphicsAllocation *switchRingBuffersAllocations(); - virtual uint64_t updateTagValue(bool hasStallingCmds) = 0; - virtual bool dispatchMonitorFenceRequired(bool hasStallingCmds); + virtual uint64_t updateTagValue(bool requireMonitorFence) = 0; + virtual bool dispatchMonitorFenceRequired(bool requireMonitorFence); virtual void getTagAddressValue(TagData &tagData) = 0; void unblockGpu(); bool copyCommandBufferIntoRing(BatchBuffer &batchBuffer); diff --git a/shared/source/direct_submission/direct_submission_hw.inl b/shared/source/direct_submission/direct_submission_hw.inl index 17624f63f1..067c39513b 100644 --- a/shared/source/direct_submission/direct_submission_hw.inl +++ b/shared/source/direct_submission/direct_submission_hw.inl @@ -938,7 +938,7 @@ bool DirectSubmissionHw::dispatchCommandBuffer(BatchBuffe this->startRingBuffer(); bool relaxedOrderingSchedulerWillBeNeeded = (this->relaxedOrderingSchedulerRequired || batchBuffer.hasRelaxedOrderingDependencies); - bool dispatchMonitorFence = this->dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds); + bool dispatchMonitorFence = this->dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence); size_t dispatchSize = getSizeDispatch(relaxedOrderingSchedulerWillBeNeeded, batchBuffer.hasRelaxedOrderingDependencies, dispatchMonitorFence); @@ -980,7 +980,7 @@ bool DirectSubmissionHw::dispatchCommandBuffer(BatchBuffe currentQueueWorkCount++; DirectSubmissionDiagnostics::diagnosticModeOneSubmit(diagnostic.get()); - uint64_t flushValue = updateTagValue(batchBuffer.hasStallingCmds); + uint64_t flushValue = updateTagValue(batchBuffer.dispatchMonitorFence); flushStamp.setStamp(flushValue); return ringStart; @@ -1087,7 +1087,7 @@ inline GraphicsAllocation *DirectSubmissionHw::switchRing } template -bool DirectSubmissionHw::dispatchMonitorFenceRequired(bool hasStallingCmds) { +bool DirectSubmissionHw::dispatchMonitorFenceRequired(bool requireMonitorFence) { return !this->disableMonitorFence; } diff --git a/shared/source/direct_submission/linux/drm_direct_submission.h b/shared/source/direct_submission/linux/drm_direct_submission.h index 4b1f1260a9..8dafa7fe91 100644 --- a/shared/source/direct_submission/linux/drm_direct_submission.h +++ b/shared/source/direct_submission/linux/drm_direct_submission.h @@ -31,7 +31,7 @@ class DrmDirectSubmission : public DirectSubmissionHw { void ensureRingCompletion() override; void handleSwitchRingBuffers() override; - uint64_t updateTagValue(bool hasStallingCmds) override; + uint64_t updateTagValue(bool requireMonitorFence) override; void getTagAddressValue(TagData &tagData) override; bool isCompleted(uint32_t ringBufferIndex) override; bool isCompletionFenceSupported(); diff --git a/shared/source/direct_submission/linux/drm_direct_submission.inl b/shared/source/direct_submission/linux/drm_direct_submission.inl index af7895136d..446ab5e31c 100644 --- a/shared/source/direct_submission/linux/drm_direct_submission.inl +++ b/shared/source/direct_submission/linux/drm_direct_submission.inl @@ -211,7 +211,7 @@ void DrmDirectSubmission::handleSwitchRingBuffers() { } template -uint64_t DrmDirectSubmission::updateTagValue(bool hasStallingCmds) { +uint64_t DrmDirectSubmission::updateTagValue(bool requireMonitorFence) { if (!this->disableMonitorFence) { this->currentTagData.tagValue++; this->ringBuffers[this->currentRingBuffer].completionFence = this->currentTagData.tagValue; diff --git a/shared/source/direct_submission/windows/wddm_direct_submission.h b/shared/source/direct_submission/windows/wddm_direct_submission.h index 572d194ce8..306f4390a0 100644 --- a/shared/source/direct_submission/windows/wddm_direct_submission.h +++ b/shared/source/direct_submission/windows/wddm_direct_submission.h @@ -34,8 +34,8 @@ class WddmDirectSubmission : public DirectSubmissionHw { void ensureRingCompletion() override; void handleSwitchRingBuffers() override; void handleStopRingBuffer() override; - uint64_t updateTagValue(bool hasStallingCmds) override; - bool dispatchMonitorFenceRequired(bool hasStallingCmds) override; + uint64_t updateTagValue(bool requireMonitorFence) override; + bool dispatchMonitorFenceRequired(bool requireMonitorFence) override; uint64_t updateTagValueImpl(); void getTagAddressValue(TagData &tagData) override; bool isCompleted(uint32_t ringBufferIndex) override; diff --git a/shared/source/direct_submission/windows/wddm_direct_submission.inl b/shared/source/direct_submission/windows/wddm_direct_submission.inl index 3c0a336ef2..024c0d6701 100644 --- a/shared/source/direct_submission/windows/wddm_direct_submission.inl +++ b/shared/source/direct_submission/windows/wddm_direct_submission.inl @@ -142,16 +142,16 @@ void WddmDirectSubmission::handleSwitchRingBuffers() { } template -uint64_t WddmDirectSubmission::updateTagValue(bool hasStallingCmds) { - if (!this->disableMonitorFence || hasStallingCmds) { +uint64_t WddmDirectSubmission::updateTagValue(bool requireMonitorFence) { + if (!this->disableMonitorFence || requireMonitorFence) { return this->updateTagValueImpl(); } return 0ull; } template -bool WddmDirectSubmission::dispatchMonitorFenceRequired(bool hasStallingCmds) { - return !this->disableMonitorFence || hasStallingCmds; +bool WddmDirectSubmission::dispatchMonitorFenceRequired(bool requireMonitorFence) { + return !this->disableMonitorFence || requireMonitorFence; } template diff --git a/shared/test/common/mock_gdi/mock_gdi.cpp b/shared/test/common/mock_gdi/mock_gdi.cpp index 33b7c5dfa0..2e41464c93 100644 --- a/shared/test/common/mock_gdi/mock_gdi.cpp +++ b/shared/test/common/mock_gdi/mock_gdi.cpp @@ -493,7 +493,10 @@ uint64_t cpuFence = 0; static bool createSynchronizationObject2FailCall = false; +static D3DGPU_VIRTUAL_ADDRESS monitorFenceGpuAddress = 0x0; + NTSTATUS __stdcall mockD3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *synchObject) { + constexpr D3DGPU_VIRTUAL_ADDRESS monitorFenceGpuNextAddressOffset = 0x2000; if (synchObject == nullptr) { return STATUS_INVALID_PARAMETER; } @@ -502,8 +505,10 @@ NTSTATUS __stdcall mockD3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESY return STATUS_INVALID_PARAMETER; } + monitorFenceGpuAddress += monitorFenceGpuNextAddressOffset; + synchObject->Info.MonitoredFence.FenceValueCPUVirtualAddress = &cpuFence; - synchObject->Info.MonitoredFence.FenceValueGPUVirtualAddress = 3; + synchObject->Info.MonitoredFence.FenceValueGPUVirtualAddress = monitorFenceGpuAddress; synchObject->hSyncObject = 4; return STATUS_SUCCESS; } diff --git a/shared/test/common/mocks/mock_direct_submission_hw.h b/shared/test/common/mocks/mock_direct_submission_hw.h index d225268e41..7837e07594 100644 --- a/shared/test/common/mocks/mock_direct_submission_hw.h +++ b/shared/test/common/mocks/mock_direct_submission_hw.h @@ -147,7 +147,7 @@ struct MockDirectSubmissionHw : public DirectSubmissionHw void handleSwitchRingBuffers() override {} - uint64_t updateTagValue(bool hasStallingCmds) override { + uint64_t updateTagValue(bool requireMonitorFence) override { return updateTagValueReturn; } diff --git a/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp b/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp index 268300991a..e7b47302c0 100644 --- a/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp +++ b/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp @@ -430,7 +430,7 @@ HWTEST_F(DirectSubmissionDispatchBufferTest, directSubmission.tagValueSetValue = 0x4343123ull; directSubmission.tagAddressSetValue = 0xBEEF00000ull; - directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds)); + directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence)); size_t expectedDispatchSize = disabledSizeDispatch - directSubmission.getSizeNewResourceHandler(); EXPECT_EQ(expectedDispatchSize, directSubmission.ringCommandStream.getUsed()); @@ -477,7 +477,7 @@ HWTEST_F(DirectSubmissionDispatchBufferTest, size_t disabledSizeDispatch = directSubmission.getSizeDispatch(false, false, directSubmission.dispatchMonitorFenceRequired(false)); EXPECT_EQ(disabledSizeDispatch, (regularSizeDispatch - flushSize)); - directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds)); + directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence)); size_t expectedDispatchSize = disabledSizeDispatch - directSubmission.getSizeNewResourceHandler(); EXPECT_EQ(expectedDispatchSize, directSubmission.ringCommandStream.getUsed()); @@ -569,7 +569,7 @@ HWTEST_F(DirectSubmissionDispatchBufferTest, EXPECT_EQ(debugSizeDispatch, (regularSizeDispatch - startSize)); directSubmission.currentQueueWorkCount = 0x40u; - directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds)); + directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence)); size_t expectedDispatchSize = debugSizeDispatch - directSubmission.getSizeNewResourceHandler(); EXPECT_EQ(expectedDispatchSize, directSubmission.ringCommandStream.getUsed()); @@ -2265,7 +2265,7 @@ HWTEST2_F(DirectSubmissionRelaxedOrderingTests, whenDispatchingWorkloadSectionTh auto originalBbStart = *reinterpret_cast(batchBuffer.endCmdPtr); batchBuffer.hasRelaxedOrderingDependencies = true; - directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds)); + directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence)); uint64_t returnPtr = directSubmission.ringCommandStream.getGpuBase() + offset + (4 * sizeof(MI_LOAD_REGISTER_IMM)) + directSubmission.getSizeStartSection(); @@ -2289,7 +2289,7 @@ HWTEST2_F(DirectSubmissionRelaxedOrderingTests, givenBbWithoutRelaxedOrderingDep auto offset = directSubmission.ringCommandStream.getUsed(); batchBuffer.hasRelaxedOrderingDependencies = false; - directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds)); + directSubmission.dispatchWorkloadSection(batchBuffer, directSubmission.dispatchMonitorFenceRequired(batchBuffer.dispatchMonitorFence)); auto lriCmd = genCmdCast(ptrOffset(directSubmission.ringCommandStream.getCpuBase(), offset)); EXPECT_EQ(nullptr, lriCmd); diff --git a/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp b/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp index 6369747ec9..8e587c9c59 100644 --- a/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp +++ b/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp @@ -5,13 +5,17 @@ * */ +#include "shared/source/command_stream/submissions_aggregator.h" #include "shared/source/direct_submission/dispatchers/render_dispatcher.h" #include "shared/source/gmm_helper/gmm_helper.h" +#include "shared/source/helpers/flush_stamp.h" #include "shared/source/memory_manager/allocation_properties.h" #include "shared/source/os_interface/windows/wddm/wddm_residency_logger.h" #include "shared/source/os_interface/windows/wddm_memory_manager.h" +#include "shared/source/os_interface/windows/wddm_residency_controller.h" #include "shared/test/common/cmd_parse/hw_parse.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/unit_test_helper.h" #include "shared/test/common/mocks/mock_io_functions.h" #include "shared/test/common/os_interface/windows/wddm_fixture.h" #include "shared/test/common/test_macros/hw_test.h" @@ -42,7 +46,8 @@ struct WddmDirectSubmissionFixture : public WddmFixture { } DebugManagerStateRestore restorer; - WddmMockInterface20 *wddmMockInterface; + + WddmMockInterface20 *wddmMockInterface = nullptr; OsContextWin *osContext = nullptr; std::unique_ptr device; }; @@ -622,3 +627,108 @@ HWTEST_F(WddmDirectSubmissionTest, givenMiMemFenceRequiredThenGpuVaForAdditional EXPECT_EQ(0u, wddmDirectSubmission.gpuVaForAdditionalSynchronizationWA); } } + +HWTEST_F(WddmDirectSubmissionTest, + givenRenderDirectSubmissionWithDisabledMonitorFenceWhenMonitrFenceExplicitlyRequiredThenDispatchPostSyncOperation) { + using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL; + using POST_SYNC_OPERATION = typename PIPE_CONTROL::POST_SYNC_OPERATION; + using Dispatcher = RenderDispatcher; + + BatchBuffer batchBuffer; + GraphicsAllocation *clientCommandBuffer = nullptr; + std::unique_ptr clientStream; + + auto memoryManager = executionEnvironment->memoryManager.get(); + const AllocationProperties commandBufferProperties{device->getRootDeviceIndex(), 0x1000, + AllocationType::COMMAND_BUFFER, device->getDeviceBitfield()}; + clientCommandBuffer = memoryManager->allocateGraphicsMemoryWithProperties(commandBufferProperties); + ASSERT_NE(nullptr, clientCommandBuffer); + + clientStream = std::make_unique(clientCommandBuffer); + clientStream->getSpace(0x40); + + memset(clientStream->getCpuBase(), 0, 0x20); + + batchBuffer.endCmdPtr = ptrOffset(clientStream->getCpuBase(), 0x20); + batchBuffer.commandBufferAllocation = clientCommandBuffer; + batchBuffer.usedSize = 0x40; + batchBuffer.taskStartAddress = clientCommandBuffer->getGpuAddress(); + batchBuffer.stream = clientStream.get(); + batchBuffer.dispatchMonitorFence = true; + + FlushStampTracker flushStamp(true); + + MockWddmDirectSubmission wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + wddmDirectSubmission.disableMonitorFence = false; + + bool ret = wddmDirectSubmission.initialize(true, true); + EXPECT_TRUE(ret); + EXPECT_TRUE(wddmDirectSubmission.useNotifyForPostSync); + + size_t sizeUsedBefore = wddmDirectSubmission.ringCommandStream.getUsed(); + ret = wddmDirectSubmission.dispatchCommandBuffer(batchBuffer, flushStamp); + EXPECT_TRUE(ret); + + HardwareParse hwParse; + hwParse.parsePipeControl = true; + hwParse.parseCommands(wddmDirectSubmission.ringCommandStream, sizeUsedBefore); + hwParse.findHardwareCommands(); + + auto &monitorFence = osContext->getResidencyController().getMonitoredFence(); + + bool foundFenceUpdate = false; + for (auto it = hwParse.pipeControlList.begin(); it != hwParse.pipeControlList.end(); it++) { + auto pipeControl = genCmdCast(*it); + if (pipeControl->getPostSyncOperation() == POST_SYNC_OPERATION::POST_SYNC_OPERATION_WRITE_IMMEDIATE_DATA) { + uint64_t pipeControlPostSyncAddress = UnitTestHelper::getPipeControlPostSyncAddress(*pipeControl); + if (pipeControlPostSyncAddress == monitorFence.gpuAddress) { + foundFenceUpdate = true; + EXPECT_TRUE(pipeControl->getNotifyEnable()); + break; + } + } + } + EXPECT_TRUE(foundFenceUpdate); + + memoryManager->freeGraphicsMemory(clientCommandBuffer); +} + +HWTEST_F(WddmDirectSubmissionTest, + givenDisableMonitorFenceIsFalseWhenDispatchArgumentIsFalseThenDispatchMonitorFenceReturnsTrue) { + using Dispatcher = RenderDispatcher; + + MockWddmDirectSubmission wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + wddmDirectSubmission.disableMonitorFence = false; + + EXPECT_TRUE(wddmDirectSubmission.dispatchMonitorFenceRequired(false)); +} + +HWTEST_F(WddmDirectSubmissionTest, + givenDisableMonitorFenceIsFalseWhenDispatchArgumentIsTrueThenDispatchMonitorFenceReturnsTrue) { + using Dispatcher = RenderDispatcher; + + MockWddmDirectSubmission wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + wddmDirectSubmission.disableMonitorFence = false; + + EXPECT_TRUE(wddmDirectSubmission.dispatchMonitorFenceRequired(true)); +} + +HWTEST_F(WddmDirectSubmissionTest, + givenDisableMonitorFenceIsTrueWhenDispatchArgumentIsFalseThenDispatchMonitorFenceReturnsFalse) { + using Dispatcher = RenderDispatcher; + + MockWddmDirectSubmission wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + wddmDirectSubmission.disableMonitorFence = true; + + EXPECT_FALSE(wddmDirectSubmission.dispatchMonitorFenceRequired(false)); +} + +HWTEST_F(WddmDirectSubmissionTest, + givenDisableMonitorFenceIsTrueWhenDispatchArgumentIsTrueThenDispatchMonitorFenceReturnsTrue) { + using Dispatcher = RenderDispatcher; + + MockWddmDirectSubmission wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + wddmDirectSubmission.disableMonitorFence = true; + + EXPECT_TRUE(wddmDirectSubmission.dispatchMonitorFenceRequired(true)); +}