diff --git a/runtime/os_interface/windows/wddm_memory_manager.cpp b/runtime/os_interface/windows/wddm_memory_manager.cpp index 8ca4447719..bb6a48ee2d 100644 --- a/runtime/os_interface/windows/wddm_memory_manager.cpp +++ b/runtime/os_interface/windows/wddm_memory_manager.cpp @@ -412,9 +412,27 @@ void WddmMemoryManager::cleanOsHandles(OsHandleStorage &handleStorage) { } } +void WddmMemoryManager::obtainGpuAddresFromFragments(WddmAllocation *allocation, OsHandleStorage &handleStorage) { + if (this->force32bitAllocations && (handleStorage.fragmentCount > 0)) { + auto hostPtr = allocation->getUnderlyingBuffer(); + auto fragment = hostPtrManager.getFragment(hostPtr); + if (fragment && fragment->driverAllocation) { + auto gpuPtr = handleStorage.fragmentStorageData[0].osHandleStorage->gpuPtr; + for (uint32_t i = 1; i < handleStorage.fragmentCount; i++) { + if (handleStorage.fragmentStorageData[i].osHandleStorage->gpuPtr < gpuPtr) { + gpuPtr = handleStorage.fragmentStorageData[i].osHandleStorage->gpuPtr; + } + } + allocation->allocationOffset = reinterpret_cast(hostPtr) & MemoryConstants::pageMask; + allocation->setGpuAddress(gpuPtr); + } + } +} + GraphicsAllocation *WddmMemoryManager::createGraphicsAllocation(OsHandleStorage &handleStorage, size_t hostPtrSize, const void *hostPtr) { auto allocation = new WddmAllocation(const_cast(hostPtr), hostPtrSize, const_cast(hostPtr), hostPtrSize, nullptr); allocation->fragmentsStorage = handleStorage; + obtainGpuAddresFromFragments(allocation, handleStorage); return allocation; } diff --git a/runtime/os_interface/windows/wddm_memory_manager.h b/runtime/os_interface/windows/wddm_memory_manager.h index 78d83a2103..5593d3516f 100644 --- a/runtime/os_interface/windows/wddm_memory_manager.h +++ b/runtime/os_interface/windows/wddm_memory_manager.h @@ -64,6 +64,8 @@ class WddmMemoryManager : public MemoryManager { AllocationStatus populateOsHandles(OsHandleStorage &handleStorage) override; void cleanOsHandles(OsHandleStorage &handleStorage) override; + void obtainGpuAddresFromFragments(WddmAllocation *allocation, OsHandleStorage &handleStorage); + GraphicsAllocation *createGraphicsAllocation(OsHandleStorage &handleStorage, size_t hostPtrSize, const void *hostPtr) override; static const D3DGPU_VIRTUAL_ADDRESS minimumAddress = static_cast(0x0); diff --git a/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp b/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp index 4fc332cd2b..a309415771 100644 --- a/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp @@ -1574,6 +1574,73 @@ HWTEST_F(BufferWithWddmMemory, GivenPointerAndSizeWhenAskedToCreateGrahicsAlloca memoryManager->freeGraphicsMemory(allocation); } +HWTEST_F(BufferWithWddmMemory, givenFragmentsThatAreNotInOrderWhenGraphicsAllocationIsBeingCreatedThenGraphicsAddressIsPopulatedFromProperFragment) { + SetUpMm(); + memoryManager->setForce32bitAllocations(true); + OsHandleStorage handleStorage = {}; + D3DGPU_VIRTUAL_ADDRESS gpuAdress = MemoryConstants::pageSize * 1; + auto ptr = reinterpret_cast(wddm->virtualAllocAddress + MemoryConstants::pageSize); + auto size = MemoryConstants::pageSize * 2; + + handleStorage.fragmentStorageData[0].cpuPtr = ptr; + handleStorage.fragmentStorageData[0].fragmentSize = size; + handleStorage.fragmentStorageData[0].osHandleStorage = new OsHandle(); + handleStorage.fragmentStorageData[0].residency = new ResidencyData(); + handleStorage.fragmentStorageData[0].freeTheFragment = true; + handleStorage.fragmentStorageData[0].osHandleStorage->gmm = new MockGmm(); + handleStorage.fragmentCount = 1; + + FragmentStorage fragment = {}; + fragment.driverAllocation = true; + fragment.fragmentCpuPointer = ptr; + fragment.fragmentSize = size; + fragment.osInternalStorage = handleStorage.fragmentStorageData[0].osHandleStorage; + fragment.osInternalStorage->gpuPtr = gpuAdress; + memoryManager->hostPtrManager.storeFragment(fragment); + + auto allocation = memoryManager->createGraphicsAllocation(handleStorage, size, ptr); + EXPECT_EQ(ptr, allocation->getUnderlyingBuffer()); + EXPECT_EQ(size, allocation->getUnderlyingBufferSize()); + EXPECT_EQ(gpuAdress, allocation->getGpuAddress()); + EXPECT_EQ(0ULL, allocation->allocationOffset); + memoryManager->freeGraphicsMemory(allocation); +} + +HWTEST_F(BufferWithWddmMemory, givenFragmentsThatAreNotInOrderWhenGraphicsAllocationIsBeingCreatedNotAllignedToPageThenGraphicsAddressIsPopulatedFromProperFragmentAndOffsetisAssigned) { + SetUpMm(); + memoryManager->setForce32bitAllocations(true); + OsHandleStorage handleStorage = {}; + D3DGPU_VIRTUAL_ADDRESS gpuAdress = MemoryConstants::pageSize * 1; + auto ptr = reinterpret_cast(wddm->virtualAllocAddress + MemoryConstants::pageSize); + auto size = MemoryConstants::pageSize * 2; + + handleStorage.fragmentStorageData[0].cpuPtr = ptr; + handleStorage.fragmentStorageData[0].fragmentSize = size; + handleStorage.fragmentStorageData[0].osHandleStorage = new OsHandle(); + handleStorage.fragmentStorageData[0].residency = new ResidencyData(); + handleStorage.fragmentStorageData[0].freeTheFragment = true; + handleStorage.fragmentStorageData[0].osHandleStorage->gmm = new MockGmm(); + handleStorage.fragmentCount = 1; + + FragmentStorage fragment = {}; + fragment.driverAllocation = true; + fragment.fragmentCpuPointer = ptr; + fragment.fragmentSize = size; + fragment.osInternalStorage = handleStorage.fragmentStorageData[0].osHandleStorage; + fragment.osInternalStorage->gpuPtr = gpuAdress; + memoryManager->hostPtrManager.storeFragment(fragment); + + auto offset = 80; + auto allocationPtr = reinterpret_cast(reinterpret_cast(ptr) + offset); + auto allocation = memoryManager->createGraphicsAllocation(handleStorage, size, allocationPtr); + + EXPECT_EQ(allocationPtr, allocation->getUnderlyingBuffer()); + EXPECT_EQ(size, allocation->getUnderlyingBufferSize()); + EXPECT_EQ(gpuAdress + offset, allocation->getGpuAddress()); // getGpuAddress returns gpuAddress + allocationOffset + EXPECT_EQ(offset, allocation->allocationOffset); + memoryManager->freeGraphicsMemory(allocation); +} + HWTEST_F(WddmMemoryManagerTest2, makeResidentResidencyAllocationsDoesNotMarkAllocationsResidentWhenMakeResidentFails) { SetUpMm(); WddmAllocation allocation1, allocation2, allocation3, allocation4;