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
37 changes: 17 additions & 20 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,33 +68,30 @@ namespace gpgmm::d3d12 {
};

/** \enum RESIDENCY_HEAP_STATUS
Additional information about the heap residency status.

D3D12 allows heaps to be explicitly created resident or not. This means the expected
residency status of the heap cannot be solely determined by checking for the existence in a
residency cache.

Heaps are in one of three exclusive states: never made resident or unknown, about to become
resident or pending residency, and currently resident. When a heap gets evicted or paged-out,
it transitions from currently resident to pending residency. Paged-in is the reverse of this,
pending residency to currently resident. If the heap was known to be created resident by
D3D12, it will immediately become currently resident. If the heap becomes locked, it will
stay currently resident until it is evicted, then back to pending residency.
D3D12 heaps are in one of three exclusive states: never made resident or unknown, about to
become resident or evicted, and resident. When a heap gets paged-out, it transitions from
being resident to evicted. Paged-in is the reverse of this, evicted to resident. If the heap
was known to be created resident by D3D12, it will immediately become resident. If the heap
becomes locked, it will stay resident until unlocked, then back to evicted.
*/
enum RESIDENCY_HEAP_STATUS {
/** \brief Heap residency status is not known and cannot be made resident.
Heap must become locked to be managed for residency.
*/
/** \brief Heap residency status is not known.

Unknown heaps must become locked to be managed for residency.
*/
RESIDENCY_HEAP_STATUS_UNKNOWN = 0,

/** \brief Heap is about to be made resident.
Heap must be previously locked, evicted, or currently resident at creation.
/** \brief Heap is evicted or about to be made resident.
Evicted heaps must be previously locked, resident, or D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT.
*/
RESIDENCY_HEAP_STATUS_PENDING = 1,
RESIDENCY_HEAP_STATUS_EVICTED = 1,

/** \brief Heap was made resident and can be evicted.
Heaps that stay locked will always be currently resident.
/** \brief Heap is resident and can be evicted.
Heaps that stay locked will always be resident.
*/
RESIDENCY_HEAP_STATUS_CURRENT = 2,
RESIDENCY_HEAP_STATUS_RESIDENT = 2,
};

/** \struct RESIDENCY_HEAP_INFO
Expand All @@ -119,7 +116,7 @@ namespace gpgmm::d3d12 {
*/
bool IsLocked;

/** \brief Check if the heap was made resident or not.
/** \brief Determine if the heap is resident or not.
*/
RESIDENCY_HEAP_STATUS Status;
};
Expand Down
8 changes: 4 additions & 4 deletions src/gpgmm/d3d12/ResidencyHeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ namespace gpgmm::d3d12 {
// Resource heaps created without the "create not resident" flag are always
// resident.
if (!(resourceHeapFlags & D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT)) {
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_CURRENT);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_RESIDENT);
} else {
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_PENDING);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_EVICTED);
}
}

// Heap created not resident requires no budget to be created.
if (heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_PENDING &&
if (heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_EVICTED &&
(descriptor.Flags & RESIDENCY_HEAP_FLAG_CREATE_IN_BUDGET)) {
ErrorLog(heap.get(), MessageId::kInvalidArgument)
<< "Creating a heap always in budget cannot be used with "
Expand All @@ -123,7 +123,7 @@ namespace gpgmm::d3d12 {
GetDevice(pPageable));
GPGMM_RETURN_IF_FAILED(residencyManager->UnlockHeap(heap.get()),
GetDevice(pPageable));
ASSERT(heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_CURRENT);
ASSERT(heap->GetInfo().Status == RESIDENCY_HEAP_STATUS_RESIDENT);
}
}
} else {
Expand Down
12 changes: 6 additions & 6 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ namespace gpgmm::d3d12 {
GPGMM_RETURN_IF_FAILED(
MakeResident(heap->GetHeapSegment(), heap->GetSize(), 1, pageable.GetAddressOf()),
mDevice);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_CURRENT);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_RESIDENT);

// Untracked heaps, created not resident, are not already attributed toward residency
// usage because they are not in the residency cache.
Expand All @@ -220,7 +220,7 @@ namespace gpgmm::d3d12 {

// Untracked heaps, previously made resident, are not attributed toward residency usage
// because they will be removed from the residency cache.
if (heap->mState == RESIDENCY_HEAP_STATUS_CURRENT) {
if (heap->mState == RESIDENCY_HEAP_STATUS_RESIDENT) {
mStats.CurrentHeapCount++;
mStats.CurrentHeapUsage += heap->GetSize();
}
Expand Down Expand Up @@ -564,7 +564,7 @@ namespace gpgmm::d3d12 {
GPGMM_RETURN_IF_FAILED(mResidencyFence->WaitFor(lastUsedFenceValue), mDevice);

heap->RemoveFromList();
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_PENDING);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_EVICTED);

bytesEvicted += heap->GetSize();

Expand Down Expand Up @@ -702,7 +702,7 @@ namespace gpgmm::d3d12 {
// Once MakeResident succeeds, we must assume the heaps are resident since D3D12 provides
// no way of knowing for certain.
for (ResidencyHeap* heap : heapsToMakeResident) {
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_CURRENT);
heap->SetResidencyStatus(RESIDENCY_HEAP_STATUS_RESIDENT);
}

GPGMM_TRACE_EVENT_METRIC(
Expand Down Expand Up @@ -803,14 +803,14 @@ namespace gpgmm::d3d12 {
RESIDENCY_MANAGER_STATS result = mStats;

for (const auto& entry : mLocalVideoMemorySegment.cache) {
if (entry.value()->GetInfo().Status == RESIDENCY_HEAP_STATUS_CURRENT) {
if (entry.value()->GetInfo().Status == RESIDENCY_HEAP_STATUS_RESIDENT) {
result.CurrentHeapUsage += entry.value()->GetSize();
result.CurrentHeapCount++;
}
}

for (const auto& entry : mNonLocalVideoMemorySegment.cache) {
if (entry.value()->GetInfo().Status == RESIDENCY_HEAP_STATUS_CURRENT) {
if (entry.value()->GetInfo().Status == RESIDENCY_HEAP_STATUS_RESIDENT) {
result.CurrentHeapUsage += entry.value()->GetSize();
result.CurrentHeapCount++;
}
Expand Down
28 changes: 14 additions & 14 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class D3D12ResidencyManagerTests : public D3D12TestBase, public ::testing::Test

bool IsResident(IResourceAllocation* pAllocation) const {
ASSERT(pAllocation != nullptr);
return pAllocation->GetMemory()->GetInfo().Status == RESIDENCY_HEAP_STATUS_CURRENT;
return pAllocation->GetMemory()->GetInfo().Status == RESIDENCY_HEAP_STATUS_RESIDENT;
}

class CreateDescHeapCallbackContext {
Expand Down Expand Up @@ -219,7 +219,7 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {

// Ensure the unmanaged resource heap state is always unknown. Even though D3D12 implicitly
// creates heaps as resident, untrack resource heaps would never transition out from
// RESIDENCY_HEAP_STATUS_CURRENT and must be left RESIDENCY_HEAP_STATUS_UNKNOWN.
// RESIDENCY_HEAP_STATUS_RESIDENT and must be left RESIDENCY_HEAP_STATUS_UNKNOWN.
EXPECT_EQ(resourceHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_UNKNOWN);
EXPECT_EQ(resourceHeap->GetInfo().IsLocked, false);

Expand All @@ -229,7 +229,7 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {
&createHeapContext, &resourceHeap));
ASSERT_NE(resourceHeap, nullptr);

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

// Residency status of resource heap types is always known.
Expand All @@ -242,15 +242,15 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {

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

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

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

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

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

// Unlocking a heap does not evict it, the memory usage should not change.
Expand Down Expand Up @@ -296,15 +296,15 @@ TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeap) {

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

EXPECT_EQ(descriptorHeap->GetInfo().Status, gpgmm::d3d12::RESIDENCY_HEAP_STATUS_CURRENT);
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()));

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

// Unlocking a heap does not evict it, the memory usage should not change.
Expand Down Expand Up @@ -337,7 +337,7 @@ TEST_F(D3D12ResidencyManagerTests, CreateDescriptorHeapResident) {
CreateDescHeapCallbackContext::CreateResidencyHeap,
&createDescHeapCallbackContext, &descriptorHeap));

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

Expand Down Expand Up @@ -715,7 +715,7 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetExecuteCommandList) {
ComPtr<IResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_CURRENT);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_RESIDENT);
firstSetOfHeaps.push_back(std::move(allocation));
}

Expand All @@ -725,7 +725,7 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetExecuteCommandList) {
ComPtr<IResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_CURRENT);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_RESIDENT);
secondSetOfHeaps.push_back(std::move(allocation));
}

Expand Down Expand Up @@ -765,12 +765,12 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetExecuteCommandList) {

// Everything below the budget should now be resident.
for (auto& allocation : firstSetOfHeaps) {
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_CURRENT);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_RESIDENT);
}

// Everything above the budget should now be evicted.
for (auto& allocation : secondSetOfHeaps) {
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_PENDING);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_EVICTED);
}

// Page-in the second set of heaps using ExecuteCommandLists (and page-out the first set).
Expand All @@ -790,12 +790,12 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetExecuteCommandList) {

// Everything below the budget should now be evicted.
for (auto& allocation : firstSetOfHeaps) {
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_PENDING);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_EVICTED);
}

// Everything above the budget should now be resident.
for (auto& allocation : secondSetOfHeaps) {
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_CURRENT);
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_HEAP_STATUS_RESIDENT);
}
}

Expand Down