diff --git a/runtime/os_interface/windows/wddm.cpp b/runtime/os_interface/windows/wddm.cpp index e383f5b07f..debc628b50 100644 --- a/runtime/os_interface/windows/wddm.cpp +++ b/runtime/os_interface/windows/wddm.cpp @@ -695,6 +695,10 @@ bool Wddm::openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) { auto status = gdi->queryResourceInfo(&QueryResourceInfo); DEBUG_BREAK_IF(status != STATUS_SUCCESS); + if (QueryResourceInfo.NumAllocations == 0) { + return false; + } + std::unique_ptr allocPrivateData(new char[QueryResourceInfo.TotalPrivateDriverDataSize]); std::unique_ptr resPrivateData(new char[QueryResourceInfo.ResourcePrivateDriverDataSize]); std::unique_ptr resPrivateRuntimeData(new char[QueryResourceInfo.PrivateRuntimeDataSize]); @@ -721,7 +725,7 @@ bool Wddm::openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) { alloc->gmm = Gmm::create((PGMM_RESOURCE_INFO)(allocationInfo[0].pPrivateDriverData)); - return STATUS_SUCCESS; + return true; } bool Wddm::openNTHandle(HANDLE handle, WddmAllocation *alloc) { @@ -757,7 +761,7 @@ bool Wddm::openNTHandle(HANDLE handle, WddmAllocation *alloc) { alloc->gmm = Gmm::create((PGMM_RESOURCE_INFO)(allocationInfo2[0].pPrivateDriverData)); - return STATUS_SUCCESS; + return true; } void *Wddm::lockResource(WddmAllocation *wddmAllocation) { diff --git a/runtime/os_interface/windows/wddm.h b/runtime/os_interface/windows/wddm.h index d2ef65d969..34526dac95 100644 --- a/runtime/os_interface/windows/wddm.h +++ b/runtime/os_interface/windows/wddm.h @@ -83,7 +83,7 @@ class Wddm { MOCKABLE_VIRTUAL bool createAllocation64k(WddmAllocation *alloc); bool createAllocationsAndMapGpuVa(OsHandleStorage &osHandles); MOCKABLE_VIRTUAL bool destroyAllocations(D3DKMT_HANDLE *handles, uint32_t allocationCount, uint64_t lastFenceValue, D3DKMT_HANDLE resourceHandle); - bool openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc); + MOCKABLE_VIRTUAL bool openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc); bool openNTHandle(HANDLE handle, WddmAllocation *alloc); MOCKABLE_VIRTUAL void *lockResource(WddmAllocation *wddmAllocation); MOCKABLE_VIRTUAL void unlockResource(WddmAllocation *wddmAllocation); diff --git a/runtime/os_interface/windows/wddm_memory_manager.cpp b/runtime/os_interface/windows/wddm_memory_manager.cpp index 64542546ce..ad4f6fab34 100644 --- a/runtime/os_interface/windows/wddm_memory_manager.cpp +++ b/runtime/os_interface/windows/wddm_memory_manager.cpp @@ -211,7 +211,9 @@ GraphicsAllocation *WddmMemoryManager::createAllocationFromHandle(osHandle handl if (ntHandle) { wddm->openNTHandle((HANDLE)((UINT_PTR)handle), &allocation); } else { - wddm->openSharedHandle(handle, &allocation); + if (wddm->openSharedHandle(handle, &allocation) == false) { + return nullptr; + } } // Shared objects are passed without size @@ -230,8 +232,7 @@ GraphicsAllocation *WddmMemoryManager::createAllocationFromHandle(osHandle handl allocation.setGpuAddress(allocation.gpuPtr); - auto *wddmAllocation = new WddmAllocation(allocation); - return wddmAllocation; + return new WddmAllocation(allocation); } GraphicsAllocation *WddmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, bool requireSpecificBitness, bool /*isReused*/) { diff --git a/unit_tests/os_interface/windows/wddm_fixture.h b/unit_tests/os_interface/windows/wddm_fixture.h index 5e8716da26..3f0152a98b 100644 --- a/unit_tests/os_interface/windows/wddm_fixture.h +++ b/unit_tests/os_interface/windows/wddm_fixture.h @@ -142,6 +142,15 @@ class WddmMock : public Wddm { releaseGpuPtr(gpuPtr); return success; } + + bool openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) { + if (failOpenSharedHandle) { + return false; + } else { + return Wddm::openSharedHandle(handle, alloc); + } + } + D3DKMT_HANDLE createContext() override { createContextResult.called++; D3DKMT_HANDLE context = Wddm::createContext(); @@ -238,6 +247,7 @@ class WddmMock : public Wddm { CallResult waitFromCpuResult; CallResult releaseGpuPtrResult; bool callBaseDestroyAllocations = true; + bool failOpenSharedHandle = false; }; class WddmFixture { 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 64664c71ca..8ccfdf5140 100644 --- a/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_memory_manager_tests.cpp @@ -227,6 +227,21 @@ HWTEST_F(WddmMemoryManagerTest, givenWddmMemoryManagerSizeZeroWhenCreateFromShar mm->freeGraphicsMemory(gpuAllocation); } +HWTEST_F(WddmMemoryManagerTest, givenWddmMemoryManagerWhenCreateFromSharedHandleFailsThenReturnNull) { + SetUpMm(); + auto osHandle = 1u; + auto size = 4096u; + void *pSysMem = (void *)0x1000; + + std::unique_ptr gmm(Gmm::create(pSysMem, size)); + auto status = setSizesFunction(gmm->gmmResourceInfo.get(), 1u, 1024u, 1u); + + mockWddm->failOpenSharedHandle = true; + + auto *gpuAllocation = mm->createGraphicsAllocationFromSharedHandle(osHandle, false); + EXPECT_EQ(nullptr, gpuAllocation); +} + HWTEST_F(WddmMemoryManagerTest, givenWddmMemoryManagerWhenTiledImageIsBeingCreatedThenallocateGraphicsMemoryForImageIsUsed) { SetUpMm(); MockContext context; diff --git a/unit_tests/os_interface/windows/wddm_tests.cpp b/unit_tests/os_interface/windows/wddm_tests.cpp index 8bd13219da..2315cfde67 100644 --- a/unit_tests/os_interface/windows/wddm_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_tests.cpp @@ -744,3 +744,24 @@ HWTEST_F(WddmWithMockGdiTest, createMonitoredFenceIsInitializedWithFenceValueZer EXPECT_EQ(0u, gdi.getCreateSynchronizationObject2Arg().Info.MonitoredFence.InitialFenceValue); EXPECT_EQ(1u, wddm.getMonitoredFence().currentFenceValue); } + +NTSTATUS queryResourceInfoMock(D3DKMT_QUERYRESOURCEINFO *pData) { + pData->NumAllocations = 0; + return 0; +} + +HWTEST_F(WddmWithMockGdiTest, givenOpenSharedHandleWhenZeroAllocationsThenReturnNull) { + + MockGdi gdi; + WddmMock wddm(&gdi); + + wddm.init(); + + D3DKMT_HANDLE handle = 0; + WddmAllocation *alloc = nullptr; + + gdi.queryResourceInfo = reinterpret_cast(queryResourceInfoMock); + auto ret = wddm.openSharedHandle(handle, alloc); + + EXPECT_EQ(false, ret); +}