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
39 changes: 18 additions & 21 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,22 @@ namespace gpgmm::d3d12 {
*/
virtual RESIDENCY_HEAP_INFO GetInfo() const = 0;

/** \brief Locks the specified heap.

Locking a heap means the residency manager will never evict it when over budget.

\return S_OK if locking was successful.
*/
virtual HRESULT Lock() = 0;

/** \brief Unlocks the specified heap.

Unlocking a heap allows the residency manager will evict it when over budget.

\return S_OK if unlocking was successful or S_FALSE if a lock remains.
*/
virtual HRESULT Unlock() = 0;

/** \brief Get the residency manager that manages this heap.

@param[out] ppResidencyManagerOut Pointer to a memory block that receives a pointer to the
Expand Down Expand Up @@ -285,9 +301,8 @@ namespace gpgmm::d3d12 {
IResourceAllocation::GetMemory, into the list. Once IResidencyManager::ExecuteCommandLists is
called, the list can be reset or cleared for the next frame or compute job.

Without IResidencyList, the application would need to call IResidencyManager::LockHeap and
IResidencyManager::UnlockHeap for each heap before and after every GPU command or command-list
being executed.
Without IResidencyList, the application would need to lock and unlock each heap before and
after every GPU command or command-list being executed.
*/
GPGMM_INTERFACE IResidencyList : public IUnknown {
/** \brief Adds a heap to the residency list.
Expand Down Expand Up @@ -569,24 +584,6 @@ namespace gpgmm::d3d12 {
**/
GPGMM_INTERFACE IResidencyManager : public IDebugObject {
public:
/** \brief Locks the specified heap.

Locking a heap means the residency manager will never evict it when over budget.

@param pHeap A pointer to the heap being locked.
*/
virtual HRESULT LockHeap(IResidencyHeap * pHeap) = 0;

/** \brief Unlocks the specified heap.

Unlocking a heap allows the residency manager will evict it when over budget.

@param pHeap A pointer to the heap being unlocked.

\return S_OK if unlocking was successful or S_FALSE if a lock remains.
*/
virtual HRESULT UnlockHeap(IResidencyHeap * pHeap) = 0;

/** \brief Execute command lists using residency managed heaps or E_OUTOFMEMORY.

Submits an array of command lists and residency lists for the specified command queue.
Expand Down
12 changes: 8 additions & 4 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ namespace gpgmm::d3d12 {
}

std::unique_ptr<ResidencyHeap> heap(
new ResidencyHeap(pResidencyManager, pPageable, newDescriptor, isResidencyDisabled));
new ResidencyHeap(residencyManager, pPageable, newDescriptor, isResidencyDisabled));

if (!isResidencyDisabled) {
// Check if the underlying memory was implicitly made resident.
Expand Down Expand Up @@ -280,7 +280,7 @@ namespace gpgmm::d3d12 {
ppResidencyHeapOut);
}

ResidencyHeap::ResidencyHeap(ComPtr<IResidencyManager> residencyManager,
ResidencyHeap::ResidencyHeap(ComPtr<ResidencyManager> residencyManager,
ComPtr<ID3D12Pageable> pageable,
const RESIDENCY_HEAP_DESC& descriptor,
bool isResidencyDisabled)
Expand Down Expand Up @@ -382,12 +382,16 @@ namespace gpgmm::d3d12 {
}

HRESULT ResidencyHeap::Lock() {
ASSERT(mResidencyManager != nullptr);
if (mResidencyManager == nullptr) {
return S_FALSE;
}
return mResidencyManager->LockHeap(this);
}

HRESULT ResidencyHeap::Unlock() {
ASSERT(mResidencyManager != nullptr);
if (mResidencyManager == nullptr) {
return S_FALSE;
}
return mResidencyManager->UnlockHeap(this);
}

Expand Down
9 changes: 4 additions & 5 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ namespace gpgmm::d3d12 {

// IResidencyHeap interface
RESIDENCY_HEAP_INFO GetInfo() const override;
HRESULT Lock() override;
HRESULT Unlock() override;
HRESULT GetResidencyManager(IResidencyManager** ppResidencyManagerOut) const override;

// IUnknown interface
Expand All @@ -65,13 +67,10 @@ namespace gpgmm::d3d12 {
LPCWSTR GetDebugName() const override;
HRESULT SetDebugName(LPCWSTR Name) override;

HRESULT Lock();
HRESULT Unlock();

private:
friend ResidencyManager;

ResidencyHeap(ComPtr<IResidencyManager> residencyManager,
ResidencyHeap(ComPtr<ResidencyManager> residencyManager,
ComPtr<ID3D12Pageable> pageable,
const RESIDENCY_HEAP_DESC& descriptor,
bool isResidencyDisabled);
Expand Down Expand Up @@ -100,7 +99,7 @@ namespace gpgmm::d3d12 {
void AddResidencyLockRef();
void ReleaseResidencyLock();

ComPtr<IResidencyManager> mResidencyManager;
ComPtr<ResidencyManager> mResidencyManager;
ComPtr<ID3D12Pageable> mPageable;

DXGI_MEMORY_SEGMENT_GROUP mHeapSegment;
Expand Down
4 changes: 2 additions & 2 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ namespace gpgmm::d3d12 {
}

// Increments number of locks on a heap to ensure the heap remains resident.
HRESULT ResidencyManager::LockHeap(IResidencyHeap* pHeap) {
HRESULT ResidencyManager::LockHeap(ResidencyHeap* pHeap) {
GPGMM_RETURN_IF_NULL(pHeap);

std::lock_guard<std::mutex> lock(mMutex);
Expand Down Expand Up @@ -234,7 +234,7 @@ namespace gpgmm::d3d12 {

// Decrements number of locks on a heap. When the number of locks becomes zero, the heap is
// inserted into the LRU cache and becomes eligible for eviction.
HRESULT ResidencyManager::UnlockHeap(IResidencyHeap* pHeap) {
HRESULT ResidencyManager::UnlockHeap(ResidencyHeap* pHeap) {
GPGMM_RETURN_IF_NULL(pHeap);

std::lock_guard<std::mutex> lock(mMutex);
Expand Down
5 changes: 3 additions & 2 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ namespace gpgmm::d3d12 {
~ResidencyManager() override;

// IResidencyManager interface
HRESULT LockHeap(IResidencyHeap* pHeap) override;
HRESULT UnlockHeap(IResidencyHeap* pHeap) override;
HRESULT ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
IResidencyList* const* ppResidencyLists,
Expand All @@ -74,6 +72,9 @@ namespace gpgmm::d3d12 {
LPCWSTR GetDebugName() const override;
HRESULT SetDebugName(LPCWSTR Name) override;

HRESULT LockHeap(ResidencyHeap* pHeap);
HRESULT UnlockHeap(ResidencyHeap* pHeap);

private:
friend ResidencyHeap;
friend ResourceAllocator;
Expand Down
16 changes: 8 additions & 8 deletions src/mvi/gpgmm_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ namespace gpgmm::d3d12 {
return {GetSize(), GetAlignment(), false, RESIDENCY_HEAP_STATUS_UNKNOWN};
}

HRESULT ResidencyHeap::Lock() {
return S_OK;
}

HRESULT ResidencyHeap::Unlock() {
return S_OK;
}

HRESULT ResidencyHeap::GetResidencyManager(IResidencyManager** ppResidencyManagerOut) const {
return E_NOTIMPL;
}
Expand Down Expand Up @@ -176,14 +184,6 @@ namespace gpgmm::d3d12 {

ResidencyManager::~ResidencyManager() = default;

HRESULT ResidencyManager::LockHeap(IResidencyHeap* pHeap) {
return S_OK;
}

HRESULT ResidencyManager::UnlockHeap(IResidencyHeap* pHeap) {
return S_OK;
}

HRESULT ResidencyManager::ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
IResidencyList* const* ppResidencyLists,
Expand Down
4 changes: 2 additions & 2 deletions src/mvi/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ namespace gpgmm::d3d12 {

// IResidencyHeap interface
RESIDENCY_HEAP_INFO GetInfo() const override;
HRESULT Lock() override;
HRESULT Unlock() override;
HRESULT GetResidencyManager(IResidencyManager** ppResidencyManagerOut) const override;

// IUnknown interface
Expand Down Expand Up @@ -114,8 +116,6 @@ namespace gpgmm::d3d12 {
~ResidencyManager() override;

// IResidencyManager interface
HRESULT LockHeap(IResidencyHeap* pHeap) override;
HRESULT UnlockHeap(IResidencyHeap* pHeap) override;
HRESULT ExecuteCommandLists(ID3D12CommandQueue* pQueue,
ID3D12CommandList* const* ppCommandLists,
IResidencyList* const* ppResidencyLists,
Expand Down
26 changes: 13 additions & 13 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,14 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeapLocked) {
CreateResourceHeapCallbackContext::CreateHeap,
&createHeapContext, nullptr));

ASSERT_SUCCEEDED(residencyManager->LockHeap(resourceHeap.Get()));
ASSERT_SUCCEEDED(resourceHeap->Lock());

// Unlocking a heap with another lock must return S_FALSE.
EXPECT_EQ(residencyManager->UnlockHeap(resourceHeap.Get()), S_FALSE);
EXPECT_EQ(resourceHeap->Unlock(), S_FALSE);
EXPECT_TRUE(resourceHeap->GetInfo().IsLocked);

// But unlocking the last lock must return S_OK.
EXPECT_EQ(residencyManager->UnlockHeap(resourceHeap.Get()), S_OK);
EXPECT_EQ(resourceHeap->Unlock(), S_OK);
EXPECT_FALSE(resourceHeap->GetInfo().IsLocked);
}

Expand Down Expand Up @@ -333,15 +333,15 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {
ASSERT_SUCCEEDED(resourceHeap.As(&heap));
EXPECT_NE(heap, nullptr);

ASSERT_SUCCEEDED(residencyManager->LockHeap(resourceHeap.Get()));
ASSERT_SUCCEEDED(resourceHeap->Lock());

EXPECT_EQ(resourceHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_RESIDENT);
EXPECT_EQ(resourceHeap->GetInfo().IsLocked, true);

EXPECT_EQ(GetStats(residencyManager).CurrentHeapUsage, heapDesc.SizeInBytes);
EXPECT_EQ(GetStats(residencyManager).CurrentHeapCount, 1u);

ASSERT_SUCCEEDED(residencyManager->UnlockHeap(resourceHeap.Get()));
ASSERT_SUCCEEDED(resourceHeap->Unlock());

EXPECT_EQ(resourceHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_RESIDENT);
EXPECT_EQ(resourceHeap->GetInfo().IsLocked, false);
Expand All @@ -350,7 +350,7 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {
EXPECT_EQ(GetStats(residencyManager).CurrentHeapUsage, heapDesc.SizeInBytes);
EXPECT_EQ(GetStats(residencyManager).CurrentHeapCount, 1u);

ASSERT_SUCCEEDED(residencyManager->UnlockHeap(resourceHeap.Get())); // Not locked
ASSERT_SUCCEEDED(resourceHeap->Unlock()); // Not locked
}

TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeap) {
Expand Down Expand Up @@ -387,15 +387,15 @@ TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeap) {
EXPECT_EQ(GetStats(residencyManager).CurrentHeapUsage, 0u);
EXPECT_EQ(GetStats(residencyManager).CurrentHeapCount, 0u);

ASSERT_SUCCEEDED(residencyManager->LockHeap(descriptorHeap.Get()));
ASSERT_SUCCEEDED(descriptorHeap->Lock());

EXPECT_EQ(descriptorHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_RESIDENT);
EXPECT_EQ(descriptorHeap->GetInfo().IsLocked, true);

EXPECT_EQ(GetStats(residencyManager).CurrentHeapUsage, descriptorHeapDesc.SizeInBytes);
EXPECT_EQ(GetStats(residencyManager).CurrentHeapCount, 1u);

ASSERT_SUCCEEDED(residencyManager->UnlockHeap(descriptorHeap.Get()));
ASSERT_SUCCEEDED(descriptorHeap->Unlock());

EXPECT_EQ(descriptorHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_RESIDENT);
EXPECT_EQ(descriptorHeap->GetInfo().IsLocked, false);
Expand All @@ -404,7 +404,7 @@ TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeap) {
EXPECT_EQ(GetStats(residencyManager).CurrentHeapUsage, descriptorHeapDesc.SizeInBytes);
EXPECT_EQ(GetStats(residencyManager).CurrentHeapCount, 1u);

ASSERT_SUCCEEDED(residencyManager->UnlockHeap(descriptorHeap.Get()));
ASSERT_SUCCEEDED(descriptorHeap->Unlock());
}

TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeapResident) {
Expand Down Expand Up @@ -571,8 +571,8 @@ TEST_F(D3D12ResidencyManagerTests, GetResidencyManager) {
EXPECT_REFCOUNT_EQ(residencyManager.Get(), 4);

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

// Getting a NULL pointer to a residency manager cannot claim ownership.
EXPECT_SUCCEEDED(allocationWithResidency->GetMemory()->GetResidencyManager(nullptr));
Expand Down Expand Up @@ -811,7 +811,7 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetWithLockedHeaps) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
bufferAllocationDesc, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));

ASSERT_SUCCEEDED(residencyManager->LockHeap(allocation->GetMemory()));
ASSERT_SUCCEEDED(allocation->GetMemory()->Lock());

allocationsBelowBudget.push_back(std::move(allocation));
}
Expand All @@ -834,7 +834,7 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetWithLockedHeaps) {

// Unlocked allocations should be always eligable for eviction.
for (auto& allocation : allocationsBelowBudget) {
ASSERT_SUCCEEDED(residencyManager->UnlockHeap(allocation->GetMemory()));
ASSERT_SUCCEEDED(allocation->GetMemory()->Unlock());
}

ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
Expand Down