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
3 changes: 1 addition & 2 deletions src/gpgmm/d3d12/HeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ namespace gpgmm::d3d12 {

// Else, infer the memory segment using the heap type.
if (pResidencyManager != nullptr && descriptor.MemorySegment == RESIDENCY_SEGMENT_UNKNOWN) {
memorySegmentGroup =
pResidencyManager->GetPreferredMemorySegmentGroup(descriptor.HeapType);
memorySegmentGroup = pResidencyManager->GetMemorySegmentGroup(descriptor.HeapType);
}

// Ensure enough free memory exists before allocating to avoid an out-of-memory error
Expand Down
18 changes: 9 additions & 9 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ namespace gpgmm::d3d12 {
heap->RemoveFromList();

// Untracked heaps are not attributed toward residency usage.
mInfo.MemoryCount++;
mInfo.MemoryUsage += heap->GetSize();
mInfo.ResidentMemoryCount++;
mInfo.ResidentMemoryUsage += heap->GetSize();
}

heap->AddResidencyLockRef();
Expand Down Expand Up @@ -302,8 +302,8 @@ namespace gpgmm::d3d12 {
ReturnIfFailed(InsertHeapInternal(heap));

// Heaps tracked for residency are always attributed in residency usage.
mInfo.MemoryCount--;
mInfo.MemoryUsage -= heap->GetSize();
mInfo.ResidentMemoryCount--;
mInfo.ResidentMemoryUsage -= heap->GetSize();

return S_OK;
}
Expand Down Expand Up @@ -692,13 +692,13 @@ namespace gpgmm::d3d12 {
RESIDENCY_INFO ResidencyManager::GetInfo() const {
RESIDENCY_INFO info = mInfo;
for (const auto& node : mLocalVideoMemorySegment.cache) {
info.MemoryUsage += node.value()->GetSize();
info.MemoryCount++;
info.ResidentMemoryUsage += node.value()->GetSize();
info.ResidentMemoryCount++;
}

for (const auto& node : mNonLocalVideoMemorySegment.cache) {
info.MemoryUsage += node.value()->GetSize();
info.MemoryCount++;
info.ResidentMemoryUsage += node.value()->GetSize();
info.ResidentMemoryCount++;
}

return info;
Expand Down Expand Up @@ -736,7 +736,7 @@ namespace gpgmm::d3d12 {
mBudgetNotificationUpdateEvent = nullptr;
}

DXGI_MEMORY_SEGMENT_GROUP ResidencyManager::GetPreferredMemorySegmentGroup(
DXGI_MEMORY_SEGMENT_GROUP ResidencyManager::GetMemorySegmentGroup(
D3D12_HEAP_TYPE heapType) const {
if (mIsUMA) {
return DXGI_MEMORY_SEGMENT_GROUP_LOCAL;
Expand Down
16 changes: 12 additions & 4 deletions src/gpgmm/d3d12/ResidencyManagerD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ namespace gpgmm::d3d12 {
struct RESIDENCY_INFO {
/** \brief Amount of memory, in bytes, being made resident.
*/
uint64_t MemoryUsage = 0;
uint64_t ResidentMemoryUsage = 0;

/** \brief Number of heaps currently being made resident.
*/
uint64_t MemoryCount = 0;
uint64_t ResidentMemoryCount = 0;
};

class BudgetUpdateEvent;
Expand Down Expand Up @@ -243,6 +243,16 @@ namespace gpgmm::d3d12 {
*/
RESIDENCY_INFO GetInfo() const;

/** \brief Divugles the memory segment used for the specified heap type.

@param heapType A D3D12_HEAP_TYPE-typed value that specifies the heap to get the memory
segment for.

\return A DXGI_MEMORY_SEGMENT_GROUP that provides the memory segment for the specified heap
type.
*/
DXGI_MEMORY_SEGMENT_GROUP GetMemorySegmentGroup(D3D12_HEAP_TYPE heapType) const;

private:
friend Heap;
friend ResourceAllocator;
Expand All @@ -269,8 +279,6 @@ namespace gpgmm::d3d12 {
uint32_t numberOfObjectsToMakeResident,
ID3D12Pageable** allocations);

DXGI_MEMORY_SEGMENT_GROUP GetPreferredMemorySegmentGroup(D3D12_HEAP_TYPE heapType) const;

LRUCache* GetVideoMemorySegmentCache(const DXGI_MEMORY_SEGMENT_GROUP& memorySegmentGroup);

HRESULT QueryVideoMemoryInfo(const DXGI_MEMORY_SEGMENT_GROUP& memorySegmentGroup,
Expand Down
2 changes: 1 addition & 1 deletion src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ namespace gpgmm::d3d12 {
// Limit available memory to unused budget when residency is enabled.
if (mResidencyManager != nullptr) {
const DXGI_MEMORY_SEGMENT_GROUP segment =
mResidencyManager->GetPreferredMemorySegmentGroup(allocationDescriptor.HeapType);
mResidencyManager->GetMemorySegmentGroup(allocationDescriptor.HeapType);
DXGI_QUERY_VIDEO_MEMORY_INFO* currentVideoInfo =
mResidencyManager->GetVideoMemoryInfo(segment);

Expand Down
81 changes: 46 additions & 35 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,12 @@ class D3D12ResidencyManagerTests : public D3D12TestBase, public ::testing::Test
return residencyDesc;
}

bool IsOverBudget(ResidencyManager* residencyManager) const {
ASSERT(residencyManager != nullptr);

DXGI_QUERY_VIDEO_MEMORY_INFO* local =
residencyManager->GetVideoMemoryInfo(DXGI_MEMORY_SEGMENT_GROUP_LOCAL);

DXGI_QUERY_VIDEO_MEMORY_INFO* nonLocal =
residencyManager->GetVideoMemoryInfo(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL);

return local->Budget <= local->CurrentUsage && nonLocal->Budget <= nonLocal->CurrentUsage;
uint64_t GetBudgetLeft(ResidencyManager* residencyManager,
const DXGI_MEMORY_SEGMENT_GROUP& memorySegmentGroup) {
DXGI_QUERY_VIDEO_MEMORY_INFO* segment =
residencyManager->GetVideoMemoryInfo(memorySegmentGroup);
return (segment->Budget > segment->CurrentUsage) ? (segment->Budget - segment->CurrentUsage)
: 0;
}
};

Expand Down Expand Up @@ -127,8 +123,8 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {
Heap::CreateHeap(resourceHeapDesc, residencyManager.Get(), createHeapFn, &resourceHeap));
ASSERT_NE(resourceHeap, nullptr);

EXPECT_EQ(residencyManager->GetInfo().MemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().MemoryCount, 1u);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryCount, 1u);

ComPtr<ID3D12Heap> heap;
resourceHeap->As(&heap);
Expand All @@ -137,13 +133,13 @@ TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {

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

EXPECT_EQ(residencyManager->GetInfo().MemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().MemoryCount, 1u);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryCount, 1u);

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

EXPECT_EQ(residencyManager->GetInfo().MemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().MemoryCount, 1u);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryUsage, kHeapSize);
EXPECT_EQ(residencyManager->GetInfo().ResidentMemoryCount, 1u);

ASSERT_FAILED(residencyManager->UnlockHeap(resourceHeap.Get())); // Not locked
}
Expand Down Expand Up @@ -243,18 +239,23 @@ TEST_F(D3D12ResidencyManagerTests, OverBudget) {
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(
CreateBasicAllocatorDesc(), residencyManager.Get(), &resourceAllocator));

const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(GPGMM_MB_TO_BYTES(1));
constexpr uint64_t kBufferMemorySize = GPGMM_MB_TO_BYTES(1);
const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(kBufferMemorySize);

ALLOCATION_DESC bufferAllocationDesc = {};
bufferAllocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

const DXGI_MEMORY_SEGMENT_GROUP bufferMemorySegment =
residencyManager->GetMemorySegmentGroup(bufferAllocationDesc.HeapType);
const uint64_t memoryUnderBudget = GetBudgetLeft(residencyManager.Get(), bufferMemorySegment);

// Keep allocating until we reach the budget.
std::vector<ComPtr<ResourceAllocation>> allocationsBelowBudget = {};
while (!IsOverBudget(residencyManager.Get())) {
while (resourceAllocator->GetInfo().UsedMemoryUsage + kBufferMemorySize < memoryUnderBudget) {
ComPtr<ResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
allocationsBelowBudget.push_back(std::move(allocation));

// Prevent the first created resources from being evicted once over budget.
ASSERT_SUCCEEDED(residencyManager->UpdateVideoMemorySegments());
}

// Created allocations below the budget should be resident.
Expand Down Expand Up @@ -300,14 +301,24 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetUsingBudgetNotifications) {
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(
CreateBasicAllocatorDesc(), residencyManager.Get(), &resourceAllocator));

const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(GPGMM_MB_TO_BYTES(1));
constexpr uint64_t kBufferMemorySize = GPGMM_MB_TO_BYTES(1);
const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(kBufferMemorySize);

ALLOCATION_DESC bufferAllocationDesc = {};
bufferAllocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

const DXGI_MEMORY_SEGMENT_GROUP bufferMemorySegment =
residencyManager->GetMemorySegmentGroup(bufferAllocationDesc.HeapType);

const uint64_t memoryUnderBudget = GetBudgetLeft(residencyManager.Get(), bufferMemorySegment);

// Keep allocating until we reach the budget.
std::vector<ComPtr<ResourceAllocation>> allocations = {};
while (!IsOverBudget(residencyManager.Get())) {
while (resourceAllocator->GetInfo().UsedMemoryUsage + kBufferMemorySize < memoryUnderBudget) {
ComPtr<ResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
bufferAllocationDesc, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));

allocations.push_back(std::move(allocation));
}

Expand All @@ -334,23 +345,23 @@ TEST_F(D3D12ResidencyManagerTests, OverBudgetWithGrowth) {
std::vector<ComPtr<ResourceAllocation>> allocations = {};
std::vector<Heap*> resourceHeaps = {};

const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(GPGMM_MB_TO_BYTES(1));
constexpr uint64_t kBufferMemorySize = GPGMM_MB_TO_BYTES(1);
const D3D12_RESOURCE_DESC bufferDesc = CreateBasicBufferDesc(kBufferMemorySize);

ALLOCATION_DESC bufferAllocationDesc = {};
bufferAllocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

const DXGI_MEMORY_SEGMENT_GROUP bufferMemorySegment =
residencyManager->GetMemorySegmentGroup(bufferAllocationDesc.HeapType);
const uint64_t memoryUnderBudget = GetBudgetLeft(residencyManager.Get(), bufferMemorySegment);

while (!IsOverBudget(residencyManager.Get())) {
while (resourceAllocator->GetInfo().UsedMemoryUsage + kBufferMemorySize < memoryUnderBudget) {
ComPtr<ResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
bufferAllocationDesc, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));

resourceHeaps.push_back(allocation->GetMemory());
allocations.push_back(std::move(allocation));

// Prevent the first created resources from being evicted once over budget.
ASSERT_SUCCEEDED(residencyManager->UpdateVideoMemorySegments());
}

// Created allocations above the budget should be resident.
for (auto& allocation : allocations) {
EXPECT_TRUE(allocation->IsResident());
}

// Check growth occured
Expand Down