diff --git a/runtime/command_stream/aub_command_stream_receiver_hw.inl b/runtime/command_stream/aub_command_stream_receiver_hw.inl index b1951f9e43..579a1fcb64 100644 --- a/runtime/command_stream/aub_command_stream_receiver_hw.inl +++ b/runtime/command_stream/aub_command_stream_receiver_hw.inl @@ -418,19 +418,29 @@ bool AUBCommandStreamReceiverHw::writeMemory(GraphicsAllocation &gfxA stream.addComment(str.str().c_str()); } + if (cpuAddress == nullptr) { + DEBUG_BREAK_IF(gfxAllocation.isLocked()); + cpuAddress = this->getMemoryManager()->lockResource(&gfxAllocation); + gfxAllocation.setLocked(true); + } + PageWalker walker = [&](uint64_t physAddress, size_t size, size_t offset) { static const size_t pageSize = 4096; auto vmAddr = (static_cast(gpuAddress) + offset) & ~(pageSize - 1); auto pAddr = physAddress & ~(pageSize - 1); AUB::reserveAddressPPGTT(stream, vmAddr, pageSize, pAddr); - AUB::addMemoryWrite(stream, physAddress, reinterpret_cast(reinterpret_cast(cpuAddress) + offset), size, AubMemDump::AddressSpaceValues::TraceNonlocal); }; ppgtt.pageWalk(static_cast(gpuAddress), size, 0, walker); + if (gfxAllocation.isLocked()) { + this->getMemoryManager()->unlockResource(&gfxAllocation); + gfxAllocation.setLocked(false); + } + if (!!(allocType & GraphicsAllocation::ALLOCATION_TYPE_BUFFER) || !!(allocType & GraphicsAllocation::ALLOCATION_TYPE_IMAGE)) gfxAllocation.setAllocationType(allocType | GraphicsAllocation::ALLOCATION_TYPE_NON_AUB_WRITABLE); diff --git a/unit_tests/command_stream/aub_command_stream_receiver_tests.cpp b/unit_tests/command_stream/aub_command_stream_receiver_tests.cpp index cedb760857..5288b99b25 100644 --- a/unit_tests/command_stream/aub_command_stream_receiver_tests.cpp +++ b/unit_tests/command_stream/aub_command_stream_receiver_tests.cpp @@ -27,6 +27,7 @@ #include "test.h" #include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/helpers/debug_manager_state_restore.h" +#include "unit_tests/mocks/mock_gmm.h" using OCLRT::AUBCommandStreamReceiver; using OCLRT::AUBCommandStreamReceiverHw; @@ -303,3 +304,70 @@ HWTEST_F(AubCommandStreamReceiverTests, givenAubCommandStreamReceiverInNoneStand memoryManager->freeGraphicsMemoryImpl(commandBuffer); aubCsr->setMemoryManager(nullptr); } + +class OsAgnosticMemoryManagerForImagesWithNoHostPtr : public OsAgnosticMemoryManager { + public: + GraphicsAllocation *allocateGraphicsMemoryForImage(ImageInfo &imgInfo, Gmm *gmm) override { + auto imageAllocation = OsAgnosticMemoryManager::allocateGraphicsMemoryForImage(imgInfo, gmm); + cpuPtr = imageAllocation->getUnderlyingBuffer(); + imageAllocation->setCpuPtrAndGpuAddress(nullptr, imageAllocation->getGpuAddress()); + return imageAllocation; + }; + void freeGraphicsMemoryImpl(GraphicsAllocation *imageAllocation) override { + imageAllocation->setCpuPtrAndGpuAddress(lockResourceParam.retCpuPtr, imageAllocation->getGpuAddress()); + OsAgnosticMemoryManager::freeGraphicsMemoryImpl(imageAllocation); + }; + void *lockResource(GraphicsAllocation *imageAllocation) override { + lockResourceParam.wasCalled = true; + lockResourceParam.inImageAllocation = imageAllocation; + lockResourceParam.retCpuPtr = cpuPtr; + return lockResourceParam.retCpuPtr; + }; + void unlockResource(GraphicsAllocation *imageAllocation) override { + unlockResourceParam.wasCalled = true; + unlockResourceParam.inImageAllocation = imageAllocation; + }; + + struct LockResourceParam { + bool wasCalled = false; + GraphicsAllocation *inImageAllocation = nullptr; + void *retCpuPtr = nullptr; + } lockResourceParam; + struct UnlockResourceParam { + bool wasCalled = false; + GraphicsAllocation *inImageAllocation = nullptr; + } unlockResourceParam; + + protected: + void *cpuPtr = nullptr; +}; + +HWTEST_F(AubCommandStreamReceiverTests, givenAubCommandStreamReceiverWhenWriteMemoryIsCalledOnImageWithNoHostPtrThenResourceShouldBeLockedToGetCpuAddress) { + std::unique_ptr> aubCsr(new AUBCommandStreamReceiverHw(*platformDevices[0], true)); + std::unique_ptr memoryManager(new OsAgnosticMemoryManagerForImagesWithNoHostPtr); + aubCsr->setMemoryManager(memoryManager.get()); + + cl_image_desc imgDesc = {}; + imgDesc.image_width = 512; + imgDesc.image_height = 1; + imgDesc.image_type = CL_MEM_OBJECT_IMAGE2D; + + auto imgInfo = MockGmm::initImgInfo(imgDesc, 0, nullptr); + auto queryGmm = MockGmm::queryImgParams(imgInfo); + + auto imageAllocation = memoryManager->allocateGraphicsMemoryForImage(imgInfo, queryGmm.get()); + ASSERT_NE(nullptr, imageAllocation); + + EXPECT_TRUE(aubCsr->writeMemory(*imageAllocation)); + + EXPECT_TRUE(memoryManager->lockResourceParam.wasCalled); + EXPECT_EQ(imageAllocation, memoryManager->lockResourceParam.inImageAllocation); + EXPECT_NE(nullptr, memoryManager->lockResourceParam.retCpuPtr); + + EXPECT_TRUE(memoryManager->unlockResourceParam.wasCalled); + EXPECT_EQ(imageAllocation, memoryManager->unlockResourceParam.inImageAllocation); + + queryGmm.release(); + memoryManager->freeGraphicsMemoryImpl(imageAllocation); + aubCsr->setMemoryManager(nullptr); +}