Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,14 @@ namespace gpgmm::d3d12 {
\return A pointer to the IResidencyHeap used by this resource allocation.
*/
virtual IResidencyHeap* GetMemory() const = 0;

/** \brief Get the residency manager that manages the memory for this resource allocation.

@param[out] ppResidencyManagerOut Pointer to a memory block that receives a pointer to the
residency manager. Pass NULL to test if the residency manager exists.
\return S_OK when exists else S_FALSE if NULL was passed to test.
*/
virtual HRESULT GetResidencyManager(IResidencyManager * *ppResidencyManagerOut) const = 0;
};

/** \enum RESOURCE_ALLOCATOR_FLAGS
Expand Down
15 changes: 15 additions & 0 deletions src/gpgmm/d3d12/ResourceAllocationD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,4 +197,19 @@ namespace gpgmm::d3d12 {
return DebugObject::SetDebugName(Name);
}

HRESULT ResourceAllocation::GetResidencyManager(
IResidencyManager** ppResidencyManagerOut) const {
ResidencyHeap* residencyHeap = static_cast<ResidencyHeap*>(GetMemory());
ASSERT(residencyHeap != nullptr);

ComPtr<IResidencyManager> residencyManager(residencyHeap->GetResidencyManager());
if (ppResidencyManagerOut != nullptr) {
*ppResidencyManagerOut = residencyManager.Detach();
} else {
return S_FALSE;
}

return S_OK;
}

} // namespace gpgmm::d3d12
1 change: 1 addition & 0 deletions src/gpgmm/d3d12/ResourceAllocationD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace gpgmm::d3d12 {
uint64_t GetOffsetFromResource() const override;
RESOURCE_ALLOCATION_INFO GetInfo() const override;
IResidencyHeap* GetMemory() const override;
HRESULT GetResidencyManager(IResidencyManager** ppResidencyManagerOut) const override;

DEFINE_UNKNOWN_OVERRIDES()

Expand Down
5 changes: 5 additions & 0 deletions src/mvi/gpgmm_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ namespace gpgmm::d3d12 {
return E_NOTIMPL;
}

HRESULT ResourceAllocation::GetResidencyManager(
IResidencyManager** ppResidencyManagerOut) const {
return E_NOTIMPL;
}

// ResourceAllocator

HRESULT CreateResourceAllocator(const RESOURCE_ALLOCATOR_DESC& allocatorDescriptor,
Expand Down
1 change: 1 addition & 0 deletions src/mvi/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ namespace gpgmm::d3d12 {
uint64_t GetOffsetFromResource() const override;
RESOURCE_ALLOCATION_INFO GetInfo() const override;
IResidencyHeap* GetMemory() const override;
HRESULT GetResidencyManager(IResidencyManager** ppResidencyManagerOut) const override;

// IUnknown interface
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override;
Expand Down
55 changes: 55 additions & 0 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ TEST_F(D3D12ResidencyManagerTests, CreateResidencyManager) {
&residencyManager));
EXPECT_NE(resourceAllocator, nullptr);
EXPECT_NE(residencyManager, nullptr);

// Both the resource allocator and |residencyManager| have ownership.
EXPECT_EQ(GetRefCount(residencyManager.Get()), 2);
}

// Create allocator with residency, seperately, but no adapter should fail.
Expand All @@ -521,9 +524,61 @@ TEST_F(D3D12ResidencyManagerTests, CreateResidencyManager) {
&resourceAllocator));
EXPECT_NE(resourceAllocator, nullptr);
EXPECT_NE(residencyManager, nullptr);

// Both the resource allocator and |residencyManager| have ownership.
EXPECT_EQ(GetRefCount(residencyManager.Get()), 2);
}
}

// Verify getting the residency manager from the allocation doesn't destroy it.
TEST_F(D3D12ResidencyManagerTests, GetResidencyManager) {
ComPtr<IResidencyManager> residencyManager;
ComPtr<IResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(CreateResourceAllocator(CreateBasicAllocatorDesc(), mDevice.Get(),
mAdapter.Get(), &resourceAllocator,
&residencyManager));

// Resource allocator must have ownership of the |residencyManager| object.
EXPECT_EQ(GetRefCount(residencyManager.Get()), 2);

ComPtr<IResourceAllocation> allocationWithResidency;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource({}, CreateBasicBufferDesc(1),
D3D12_RESOURCE_STATE_COMMON, nullptr,
&allocationWithResidency));

// Each allocation must have ownership of the |residencyManager| object.
EXPECT_EQ(GetRefCount(residencyManager.Get()), 3);

// Ownership must remain unchanged if no residency manager pointer was specified.
EXPECT_SUCCEEDED(allocationWithResidency->GetResidencyManager(nullptr));
EXPECT_EQ(GetRefCount(residencyManager.Get()), 3);

ComPtr<IResidencyManager> residencyManagerAgain;
EXPECT_SUCCEEDED(
allocationWithResidency->GetResidencyManager(residencyManagerAgain.GetAddressOf()));

// Creating a pointer to residency manager must claim ownership.
EXPECT_EQ(GetRefCount(residencyManager.Get()), 4);

// Use the resource manager object from the new pointer.
EXPECT_SUCCEEDED(residencyManagerAgain->LockHeap(allocationWithResidency->GetMemory()));
EXPECT_SUCCEEDED(residencyManagerAgain->UnlockHeap(allocationWithResidency->GetMemory()));

// Getting a NULL pointer to a residency manager cannot claim ownership.
EXPECT_SUCCEEDED(allocationWithResidency->GetResidencyManager(nullptr));
EXPECT_EQ(GetRefCount(residencyManager.Get()), 4);

// Release the allocator (and allocation), relinquishing ownership.
allocationWithResidency = nullptr;
resourceAllocator = nullptr;

EXPECT_EQ(GetRefCount(residencyManager.Get()), 2);

// Releasing the residency manager cannot destroy the |residencyManager| object.
residencyManager = nullptr;
EXPECT_EQ(GetRefCount(residencyManagerAgain.Get()), 1);
}

// Verify the residency manager will not increment the device refcount upon creation.
TEST_F(D3D12ResidencyManagerTests, CreateResidencyManagerWithoutDeviceAddRef) {
const uint32_t beforeDeviceRefCount = GetRefCount(mDevice.Get());
Expand Down