From 645600d141e2f5302523bd59d5147ea52412f6f1 Mon Sep 17 00:00:00 2001 From: Fabian Zwolinski Date: Tue, 13 Sep 2022 14:26:03 +0000 Subject: [PATCH] Return error when there is no memory to evict We want to return error code to the application instead of aborting when we are not able to make more memory resident. Related-To: NEO-7289 Signed-off-by: Fabian Zwolinski --- ...nd_stream_receiver_with_aub_dump_tests.cpp | 3 +- .../linux/drm_command_stream_tests_2.cpp | 24 ++++++------ .../os_interface/windows/wddm20_tests.cpp | 11 ++++++ .../aub_command_stream_receiver_hw.h | 2 +- .../aub_command_stream_receiver_hw_base.inl | 5 ++- .../command_stream/command_stream_receiver.h | 2 +- .../tbx_command_stream_receiver_hw.h | 2 +- .../tbx_command_stream_receiver_hw.inl | 3 +- .../os_interface/linux/drm_command_stream.h | 4 +- .../os_interface/linux/drm_command_stream.inl | 16 ++++---- .../drm_command_stream_bdw_and_later.inl | 13 +++++-- .../drm_command_stream_xehp_and_later.inl | 14 ++++--- .../source/os_interface/windows/wddm/wddm.cpp | 7 ++-- .../windows/wddm_device_command_stream.h | 2 +- .../windows/wddm_device_command_stream.inl | 15 +++++--- .../linux/mock_drm_command_stream_receiver.h | 22 ++++++++++- .../linux/drm_command_stream_tests_1.cpp | 38 +++++++++++++++++++ ...and_stream_xehp_and_later_prelim_tests.cpp | 11 ++++-- ...rm_command_stream_xehp_and_later_tests.cpp | 4 +- .../windows/device_command_stream_tests.cpp | 16 ++++++++ 20 files changed, 159 insertions(+), 55 deletions(-) diff --git a/opencl/test/unit_test/command_stream/command_stream_receiver_with_aub_dump_tests.cpp b/opencl/test/unit_test/command_stream/command_stream_receiver_with_aub_dump_tests.cpp index 077d804021..4ad93c6ba0 100644 --- a/opencl/test/unit_test/command_stream/command_stream_receiver_with_aub_dump_tests.cpp +++ b/opencl/test/unit_test/command_stream/command_stream_receiver_with_aub_dump_tests.cpp @@ -58,9 +58,10 @@ struct MyMockCsr : UltCommandStreamReceiver { gfxAllocation.updateResidencyTaskCount(1, osContext->getContextId()); } - void processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override { + bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override { processResidencyParameterization.wasCalled = true; processResidencyParameterization.receivedAllocationsForResidency = &allocationsForResidency; + return true; } void makeNonResident(GraphicsAllocation &gfxAllocation) override { diff --git a/opencl/test/unit_test/os_interface/linux/drm_command_stream_tests_2.cpp b/opencl/test/unit_test/os_interface/linux/drm_command_stream_tests_2.cpp index 8e8c5ea8ff..56e7f36e05 100644 --- a/opencl/test/unit_test/os_interface/linux/drm_command_stream_tests_2.cpp +++ b/opencl/test/unit_test/os_interface/linux/drm_command_stream_tests_2.cpp @@ -1403,8 +1403,8 @@ struct MockMergeResidencyContainerMemoryOperationsHandler : public DrmMemoryOper HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMakeResidentWithinOsContextFailsThenFlushReturnsError) { struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { - return 0; + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + return SubmissionStatus::SUCCESS; } }; @@ -1435,8 +1435,8 @@ HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMakeResidentWithinOsContex HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMakeResidentWithinOsContextOutOfMemoryThenFlushReturnsError) { struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { - return 0; + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + return SubmissionStatus::SUCCESS; } }; @@ -1467,8 +1467,8 @@ HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMakeResidentWithinOsContex HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMergeWithResidencyContainerFailsThenFlushReturnsError) { struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { - return 0; + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + return SubmissionStatus::SUCCESS; } }; @@ -1498,8 +1498,8 @@ HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMergeWithResidencyContaine HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenMergeWithResidencyContainerReturnsOutOfMemoryThenFlushReturnsError) { struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { - return 0; + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + return SubmissionStatus::SUCCESS; } }; @@ -1533,11 +1533,11 @@ HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenNoAllocsInMemoryOperationH struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { auto memoryOperationsInterface = static_cast(this->executionEnvironment.rootDeviceEnvironments[this->rootDeviceIndex]->memoryOperationsInterface.get()); EXPECT_TRUE(memoryOperationsInterface->mutex.try_lock()); memoryOperationsInterface->mutex.unlock(); - return 0; + return SubmissionStatus::SUCCESS; } }; @@ -1565,10 +1565,10 @@ HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenAllocsInMemoryOperationHan struct MockDrmCsr : public DrmCommandStreamReceiver { using DrmCommandStreamReceiver::DrmCommandStreamReceiver; - int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { + SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) override { auto memoryOperationsInterface = static_cast(this->executionEnvironment.rootDeviceEnvironments[this->rootDeviceIndex]->memoryOperationsInterface.get()); EXPECT_FALSE(memoryOperationsInterface->mutex.try_lock()); - return 0; + return SubmissionStatus::SUCCESS; } }; diff --git a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp index 00cabf0558..3be05e39d4 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -1599,6 +1599,17 @@ TEST_F(WddmTest, GivenResidencyLoggingEnabledWhenMakeResidentFailThenExpectTrimR EXPECT_FALSE(logger->makeResidentCall); } +TEST_F(WddmTest, GivenInvalidHandleAndCantTrimFurtherSetToTrueWhenCallingMakeResidentThenFalseIsReturned) { + wddm->callBaseMakeResident = true; + + D3DKMT_HANDLE handle = INVALID_HANDLE; + uint64_t bytesToTrim = 4 * 4096; + + bool retVal = wddm->makeResident(&handle, 1, true, &bytesToTrim, 0x1000); + + EXPECT_FALSE(retVal); +} + TEST_F(WddmTest, GivenResidencyLoggingEnabledWhenEnterWaitCalledThenExpectInternalFlagOn) { if (!NEO::wddmResidencyLoggingAvailable) { GTEST_SKIP(); diff --git a/shared/source/command_stream/aub_command_stream_receiver_hw.h b/shared/source/command_stream/aub_command_stream_receiver_hw.h index 469328dea6..142988a6fa 100644 --- a/shared/source/command_stream/aub_command_stream_receiver_hw.h +++ b/shared/source/command_stream/aub_command_stream_receiver_hw.h @@ -42,7 +42,7 @@ class AUBCommandStreamReceiverHw : public CommandStreamReceiverSimulatedHw::expectMemory(const void *gfxAddress, } template -void AUBCommandStreamReceiverHw::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { +bool AUBCommandStreamReceiverHw::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { if (subCaptureManager->isSubCaptureMode()) { if (!subCaptureManager->isSubCaptureEnabled()) { - return; + return true; } } @@ -761,6 +761,7 @@ void AUBCommandStreamReceiverHw::processResidency(const ResidencyCont } dumpAubNonWritable = false; + return true; } template diff --git a/shared/source/command_stream/command_stream_receiver.h b/shared/source/command_stream/command_stream_receiver.h index 30174f2c68..45d6bf0586 100644 --- a/shared/source/command_stream/command_stream_receiver.h +++ b/shared/source/command_stream/command_stream_receiver.h @@ -99,7 +99,7 @@ class CommandStreamReceiver { MOCKABLE_VIRTUAL void makeResident(GraphicsAllocation &gfxAllocation); virtual void makeNonResident(GraphicsAllocation &gfxAllocation); MOCKABLE_VIRTUAL void makeSurfacePackNonResident(ResidencyContainer &allocationsForResidency, bool clearAllocations); - virtual void processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) {} + virtual bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { return true; } virtual void processEviction(); void makeResidentHostPtrAllocation(GraphicsAllocation *gfxAllocation); diff --git a/shared/source/command_stream/tbx_command_stream_receiver_hw.h b/shared/source/command_stream/tbx_command_stream_receiver_hw.h index 5a5cbd1fcd..ab1b32fca2 100644 --- a/shared/source/command_stream/tbx_command_stream_receiver_hw.h +++ b/shared/source/command_stream/tbx_command_stream_receiver_hw.h @@ -50,7 +50,7 @@ class TbxCommandStreamReceiverHw : public CommandStreamReceiverSimulatedHw::processEviction() { } template -void TbxCommandStreamReceiverHw::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { +bool TbxCommandStreamReceiverHw::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { for (auto &gfxAllocation : allocationsForResidency) { if (dumpTbxNonWritable) { this->setTbxWritable(true, *gfxAllocation); @@ -529,6 +529,7 @@ void TbxCommandStreamReceiverHw::processResidency(const ResidencyCont } dumpTbxNonWritable = false; + return true; } template diff --git a/shared/source/os_interface/linux/drm_command_stream.h b/shared/source/os_interface/linux/drm_command_stream.h index e76da69d2a..e7a5104076 100644 --- a/shared/source/os_interface/linux/drm_command_stream.h +++ b/shared/source/os_interface/linux/drm_command_stream.h @@ -45,7 +45,7 @@ class DrmCommandStreamReceiver : public DeviceCommandStreamReceiver { ~DrmCommandStreamReceiver() override; SubmissionStatus flush(BatchBuffer &batchBuffer, ResidencyContainer &allocationsForResidency) override; - void processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override; + bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override; void makeNonResident(GraphicsAllocation &gfxAllocation) override; bool waitForFlushStamp(FlushStamp &flushStampToWait) override; bool isKmdWaitModeActive() override; @@ -66,7 +66,7 @@ class DrmCommandStreamReceiver : public DeviceCommandStreamReceiver { using CommandStreamReceiver::pageTableManager; protected: - MOCKABLE_VIRTUAL int flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency); + MOCKABLE_VIRTUAL SubmissionStatus flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency); MOCKABLE_VIRTUAL int exec(const BatchBuffer &batchBuffer, uint32_t vmHandleId, uint32_t drmContextId, uint32_t index); MOCKABLE_VIRTUAL int waitUserFence(uint32_t waitValue); MOCKABLE_VIRTUAL void readBackAllocation(void *source); diff --git a/shared/source/os_interface/linux/drm_command_stream.inl b/shared/source/os_interface/linux/drm_command_stream.inl index f0a7f76698..2aab66e5cf 100644 --- a/shared/source/os_interface/linux/drm_command_stream.inl +++ b/shared/source/os_interface/linux/drm_command_stream.inl @@ -171,11 +171,7 @@ SubmissionStatus DrmCommandStreamReceiver::flush(BatchBuffer &batchBu this->getMemoryManager()->peekGemCloseWorker()->push(bb); } - if (ret) { - return SubmissionStatus::FAILED; - } - - return SubmissionStatus::SUCCESS; + return ret; } template @@ -246,14 +242,18 @@ int DrmCommandStreamReceiver::exec(const BatchBuffer &batchBuffer, ui } template -void DrmCommandStreamReceiver::processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) { - +bool DrmCommandStreamReceiver::processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) { + bool ret = 0; if ((!drm->isVmBindAvailable()) || (DebugManager.flags.PassBoundBOToExec.get() == 1)) { for (auto &alloc : inputAllocationsForResidency) { auto drmAlloc = static_cast(alloc); - drmAlloc->makeBOsResident(osContext, handleId, &this->residency, false); + ret = drmAlloc->makeBOsResident(osContext, handleId, &this->residency, false); + if (ret != 0) { + break; + } } } + return ret == 0; } template diff --git a/shared/source/os_interface/linux/drm_command_stream_bdw_and_later.inl b/shared/source/os_interface/linux/drm_command_stream_bdw_and_later.inl index fb182273f0..d34e4d3aaa 100644 --- a/shared/source/os_interface/linux/drm_command_stream_bdw_and_later.inl +++ b/shared/source/os_interface/linux/drm_command_stream_bdw_and_later.inl @@ -11,11 +11,18 @@ namespace NEO { template -int DrmCommandStreamReceiver::flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) { - this->processResidency(allocationsForResidency, 0u); +SubmissionStatus DrmCommandStreamReceiver::flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) { + bool processResidencySuccess = this->processResidency(allocationsForResidency, 0u); + if (processResidencySuccess == false) { + return SubmissionStatus::OUT_OF_MEMORY; + } + int ret = this->exec(batchBuffer, 0u, static_cast(osContext)->getDrmContextIds()[0], 0); - return ret; + if (ret) { + return SubmissionStatus::FAILED; + } + return SubmissionStatus::SUCCESS; } template diff --git a/shared/source/os_interface/linux/drm_command_stream_xehp_and_later.inl b/shared/source/os_interface/linux/drm_command_stream_xehp_and_later.inl index 00c9948452..0d7a30b286 100644 --- a/shared/source/os_interface/linux/drm_command_stream_xehp_and_later.inl +++ b/shared/source/os_interface/linux/drm_command_stream_xehp_and_later.inl @@ -13,7 +13,7 @@ namespace NEO { template -int DrmCommandStreamReceiver::flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) { +SubmissionStatus DrmCommandStreamReceiver::flushInternal(const BatchBuffer &batchBuffer, const ResidencyContainer &allocationsForResidency) { if (drm->useVMBindImmediate()) { auto osContextLinux = static_cast(this->osContext); osContextLinux->waitForPagingFence(); @@ -28,25 +28,29 @@ int DrmCommandStreamReceiver::flushInternal(const BatchBuffer &batchB tileIterator = contextIndex = DebugManager.flags.ForceExecutionTile.get(); } - this->processResidency(allocationsForResidency, tileIterator); + bool processResidencySuccess = this->processResidency(allocationsForResidency, tileIterator); + if (processResidencySuccess == false) { + return SubmissionStatus::OUT_OF_MEMORY; + } + if (DebugManager.flags.PrintDeviceAndEngineIdOnSubmission.get()) { printf("%u: Drm Submission of contextIndex: %u, with context id %u\n", SysCalls::getProcessId(), contextIndex, drmContextIds[contextIndex]); } int ret = this->exec(batchBuffer, tileIterator, drmContextIds[contextIndex], contextIndex); if (ret) { - return ret; + return SubmissionStatus::FAILED; } contextIndex++; if (DebugManager.flags.EnableWalkerPartition.get() == 0 || batchBuffer.useSingleSubdevice) { - return 0; + return SubmissionStatus::SUCCESS; } } } - return 0; + return SubmissionStatus::SUCCESS; } template diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index bee1ee3bba..02b96bb931 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -485,7 +485,7 @@ bool Wddm::makeResident(const D3DKMT_HANDLE *handles, uint32_t count, bool cantT makeResident.NumAllocations = count; makeResident.PriorityList = &priority; makeResident.Flags.CantTrimFurther = cantTrimFurther ? 1 : 0; - makeResident.Flags.MustSucceed = cantTrimFurther ? 1 : 0; + makeResident.Flags.MustSucceed = 0; status = getGdi()->makeResident(&makeResident); if (status == STATUS_PENDING) { @@ -498,9 +498,10 @@ bool Wddm::makeResident(const D3DKMT_HANDLE *handles, uint32_t count, bool cantT } else { DEBUG_BREAK_IF(true); perfLogResidencyTrimRequired(residencyLogger.get(), makeResident.NumBytesToTrim); - if (numberOfBytesToTrim != nullptr) + if (numberOfBytesToTrim != nullptr) { *numberOfBytesToTrim = makeResident.NumBytesToTrim; - UNRECOVERABLE_IF(cantTrimFurther); + } + return false; } kmDafListener->notifyMakeResident(featureTable->flags.ftrKmdDaf, getAdapter(), device, handles, count, getGdi()->escape); diff --git a/shared/source/os_interface/windows/wddm_device_command_stream.h b/shared/source/os_interface/windows/wddm_device_command_stream.h index bca2753929..dbd7e15441 100644 --- a/shared/source/os_interface/windows/wddm_device_command_stream.h +++ b/shared/source/os_interface/windows/wddm_device_command_stream.h @@ -26,7 +26,7 @@ class WddmCommandStreamReceiver : public DeviceCommandStreamReceiver ~WddmCommandStreamReceiver() override; SubmissionStatus flush(BatchBuffer &batchBuffer, ResidencyContainer &allocationsForResidency) override; - void processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override; + bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override; void processEviction() override; bool waitForFlushStamp(FlushStamp &flushStampToWait) override; diff --git a/shared/source/os_interface/windows/wddm_device_command_stream.inl b/shared/source/os_interface/windows/wddm_device_command_stream.inl index 5c94e1ed26..36e1d98f76 100644 --- a/shared/source/os_interface/windows/wddm_device_command_stream.inl +++ b/shared/source/os_interface/windows/wddm_device_command_stream.inl @@ -76,16 +76,20 @@ SubmissionStatus WddmCommandStreamReceiver::flush(BatchBuffer &batchB allocationsForResidency.push_back(batchBuffer.commandBufferAllocation); batchBuffer.commandBufferAllocation->updateResidencyTaskCount(this->taskCount, this->osContext->getContextId()); perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "Wddm CSR processing residency set: %zu\n", allocationsForResidency.size()); - this->processResidency(allocationsForResidency, 0u); + + bool ret = this->processResidency(allocationsForResidency, 0u); + if (ret == false) { + return SubmissionStatus::OUT_OF_MEMORY; + } if (this->directSubmission.get()) { - bool ret = this->directSubmission->dispatchCommandBuffer(batchBuffer, *(this->flushStamp.get())); + ret = this->directSubmission->dispatchCommandBuffer(batchBuffer, *(this->flushStamp.get())); if (ret == false) { return SubmissionStatus::FAILED; } return SubmissionStatus::SUCCESS; } if (this->blitterDirectSubmission.get()) { - bool ret = this->blitterDirectSubmission->dispatchCommandBuffer(batchBuffer, *(this->flushStamp.get())); + ret = this->blitterDirectSubmission->dispatchCommandBuffer(batchBuffer, *(this->flushStamp.get())); if (ret == false) { return SubmissionStatus::FAILED; } @@ -129,9 +133,8 @@ SubmissionStatus WddmCommandStreamReceiver::flush(BatchBuffer &batchB } template -void WddmCommandStreamReceiver::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { - [[maybe_unused]] bool success = static_cast(this->osContext)->getResidencyController().makeResidentResidencyAllocations(allocationsForResidency); - DEBUG_BREAK_IF(!success); +bool WddmCommandStreamReceiver::processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) { + return static_cast(this->osContext)->getResidencyController().makeResidentResidencyAllocations(allocationsForResidency); } template diff --git a/shared/test/common/mocks/linux/mock_drm_command_stream_receiver.h b/shared/test/common/mocks/linux/mock_drm_command_stream_receiver.h index 7662b47026..ddc9cb6279 100644 --- a/shared/test/common/mocks/linux/mock_drm_command_stream_receiver.h +++ b/shared/test/common/mocks/linux/mock_drm_command_stream_receiver.h @@ -73,6 +73,20 @@ class TestedDrmCommandStreamReceiver : public DrmCommandStreamReceiversubmissionAggregator.get(); } + bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override { + if (callBaseProcessResidency) { + return DrmCommandStreamReceiver::processResidency(allocationsForResidency, handleId); + } + return processResidencyResult; + } + + int exec(const BatchBuffer &batchBuffer, uint32_t vmHandleId, uint32_t drmContextId, uint32_t index) override { + if (callBaseExec) { + return DrmCommandStreamReceiver::exec(batchBuffer, vmHandleId, drmContextId, index); + } + return execResult; + } + void overrideSubmissionAggregator(SubmissionAggregator *newSubmissionsAggregator) { this->submissionAggregator.reset(newSubmissionsAggregator); } @@ -105,11 +119,11 @@ class TestedDrmCommandStreamReceiver : public DrmCommandStreamReceiver::flushInternal(batchBuffer, allocationsForResidency); } - return 0; + return SubmissionStatus::SUCCESS; } void readBackAllocation(void *source) override { @@ -119,6 +133,10 @@ class TestedDrmCommandStreamReceiver : public DrmCommandStreamReceiver diff --git a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp index 2396eae9bf..1236512872 100644 --- a/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_command_stream_tests_1.cpp @@ -599,6 +599,44 @@ HWTEST_TEMPLATED_F(DrmCommandStreamBatchingTests, givenRecordedCommandBufferWhen mm->freeGraphicsMemory(commandBuffer); } +HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenFailingProcessResidencyWhenFlushingThenFlushReturnsOutOfMemory) { + auto commandBuffer = mm->allocateGraphicsMemoryWithProperties(MockAllocationProperties{csr->getRootDeviceIndex(), MemoryConstants::pageSize}); + LinearStream cs(commandBuffer); + CommandStreamReceiverHw::addBatchBufferEnd(cs, nullptr); + EncodeNoop::alignToCacheLine(cs); + BatchBuffer batchBuffer{cs.getGraphicsAllocation(), 0, 0, nullptr, false, false, QueueThrottle::MEDIUM, QueueSliceCount::defaultSliceCount, cs.getUsed(), &cs, nullptr, false}; + + auto allocation = mm->allocateGraphicsMemoryWithProperties(MockAllocationProperties{csr->getRootDeviceIndex(), MemoryConstants::pageSize}); + executionEnvironment->rootDeviceEnvironments[csr->getRootDeviceIndex()]->memoryOperationsInterface->makeResident(device.get(), ArrayRef(&allocation, 1)); + + static_cast *>(csr)->callBaseProcessResidency = false; + static_cast *>(csr)->processResidencyResult = false; + + SubmissionStatus ret = csr->flush(batchBuffer, csr->getResidencyAllocations()); + EXPECT_EQ(SubmissionStatus::OUT_OF_MEMORY, ret); + mm->freeGraphicsMemory(allocation); + mm->freeGraphicsMemory(commandBuffer); +} + +HWTEST_TEMPLATED_F(DrmCommandStreamEnhancedTest, givenFailingExecWhenFlushingThenFlushReturnsFailed) { + auto commandBuffer = mm->allocateGraphicsMemoryWithProperties(MockAllocationProperties{csr->getRootDeviceIndex(), MemoryConstants::pageSize}); + LinearStream cs(commandBuffer); + CommandStreamReceiverHw::addBatchBufferEnd(cs, nullptr); + EncodeNoop::alignToCacheLine(cs); + BatchBuffer batchBuffer{cs.getGraphicsAllocation(), 0, 0, nullptr, false, false, QueueThrottle::MEDIUM, QueueSliceCount::defaultSliceCount, cs.getUsed(), &cs, nullptr, false}; + + auto allocation = mm->allocateGraphicsMemoryWithProperties(MockAllocationProperties{csr->getRootDeviceIndex(), MemoryConstants::pageSize}); + executionEnvironment->rootDeviceEnvironments[csr->getRootDeviceIndex()]->memoryOperationsInterface->makeResident(device.get(), ArrayRef(&allocation, 1)); + + static_cast *>(csr)->callBaseExec = false; + static_cast *>(csr)->execResult = -1; + + SubmissionStatus ret = csr->flush(batchBuffer, csr->getResidencyAllocations()); + EXPECT_EQ(SubmissionStatus::FAILED, ret); + mm->freeGraphicsMemory(allocation); + mm->freeGraphicsMemory(commandBuffer); +} + struct DrmCommandStreamDirectSubmissionTest : public DrmCommandStreamEnhancedTest { template void setUpT() { diff --git a/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_prelim_tests.cpp index e594d95428..8bd4253259 100644 --- a/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_prelim_tests.cpp @@ -275,7 +275,7 @@ class DrmCommandStreamForceTileTest : public ::testing::Test { : DrmCommandStreamReceiver(executionEnvironment, rootDeviceIndex, deviceBitfield, mode), expectedHandleId(inputHandleId) { } - void processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override { + bool processResidency(const ResidencyContainer &allocationsForResidency, uint32_t handleId) override { EXPECT_EQ(handleId, expectedHandleId); return DrmCommandStreamReceiver::processResidency(allocationsForResidency, handleId); } @@ -587,10 +587,11 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, DrmImplicitScalingCommandStreamTest, givenUseSingle execCalled++; return 0; } - void processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { + bool processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { EXPECT_EQ(0u, processResidencyCalled); EXPECT_EQ(0u, handleId); processResidencyCalled++; + return true; } uint32_t execCalled = 0; @@ -627,10 +628,11 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, DrmImplicitScalingCommandStreamTest, givenDisabledI execCalled++; return 0; } - void processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { + bool processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { EXPECT_EQ(0u, processResidencyCalled); EXPECT_EQ(0u, handleId); processResidencyCalled++; + return true; } uint32_t execCalled = 0; @@ -663,8 +665,9 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, DrmImplicitScalingCommandStreamTest, givenMultiTile execCalled++; return 0; } - void processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { + bool processResidency(const ResidencyContainer &inputAllocationsForResidency, uint32_t handleId) override { EXPECT_EQ(execCalled, handleId); + return true; } uint32_t execCalled = 0; diff --git a/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_tests.cpp index df2df15f9c..0a2afe3296 100644 --- a/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_command_stream_xehp_and_later_tests.cpp @@ -101,8 +101,8 @@ HWCMDTEST_F(IGFX_XE_HP_CORE, DrmCommandStreamMultiTileMemExecTest, GivenDrmSuppo uint64_t expectedCompletionGpuAddress = testCsr->getTagAllocation()->getGpuAddress() + Drm::completionFenceOffset + testCsr->postSyncWriteOffset; - int ret = testCsr->flushInternal(batchBuffer, testCsr->getResidencyAllocations()); - EXPECT_EQ(0, ret); + SubmissionStatus ret = testCsr->flushInternal(batchBuffer, testCsr->getResidencyAllocations()); + EXPECT_EQ(SubmissionStatus::SUCCESS, ret); EXPECT_EQ(expectedCompletionGpuAddress, bo.receivedCompletionGpuAddress); EXPECT_EQ(testCsr->latestSentTaskCount, bo.receivedCompletionValue); diff --git a/shared/test/unit_test/os_interface/windows/device_command_stream_tests.cpp b/shared/test/unit_test/os_interface/windows/device_command_stream_tests.cpp index a91b0da16b..7361d4d824 100644 --- a/shared/test/unit_test/os_interface/windows/device_command_stream_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/device_command_stream_tests.cpp @@ -306,6 +306,22 @@ TEST_F(WddmCommandStreamTest, givenWdmmWhenSubmitIsCalledThenCoherencyRequiredFl memoryManager->freeGraphicsMemory(commandBuffer); } +TEST_F(WddmCommandStreamTest, givenFailureFromMakeResidentWhenFlushingThenOutOfMemoryIsReturned) { + GraphicsAllocation *commandBuffer = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{csr->getRootDeviceIndex(), MemoryConstants::pageSize}); + ASSERT_NE(nullptr, commandBuffer); + LinearStream cs(commandBuffer); + + wddm->makeResidentNumberOfBytesToTrim = 4 * 4096; + wddm->makeResidentStatus = false; + + BatchBuffer batchBuffer{cs.getGraphicsAllocation(), 0, 0, nullptr, false, false, QueueThrottle::MEDIUM, QueueSliceCount::defaultSliceCount, cs.getUsed(), &cs, nullptr, false}; + SubmissionStatus retVal = csr->flush(batchBuffer, csr->getResidencyAllocations()); + + EXPECT_EQ(SubmissionStatus::OUT_OF_MEMORY, retVal); + + memoryManager->freeGraphicsMemory(commandBuffer); +} + struct WddmPreemptionHeaderFixture { void setUp() { executionEnvironment = getExecutionEnvironmentImpl(hwInfo, 1);