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
34 changes: 21 additions & 13 deletions src/gpgmm/d3d12/HeapD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,27 @@ namespace gpgmm::d3d12 {

// static
HRESULT Heap::CreateHeap(const HEAP_DESC& descriptor,
ResidencyManager* const residencyManager,
ResidencyManager* const pResidencyManager,
CreateHeapFn&& createHeapFn,
Heap** heapOut) {
Heap** ppHeapOut) {
// Always use the memory segment specified.
DXGI_MEMORY_SEGMENT_GROUP memorySegmentGroup = {};
if (residencyManager != nullptr) {
if (descriptor.MemorySegment == RESIDENCY_SEGMENT_LOCAL) {
memorySegmentGroup = DXGI_MEMORY_SEGMENT_GROUP_LOCAL;
} else if (descriptor.MemorySegment == RESIDENCY_SEGMENT_NON_LOCAL) {
memorySegmentGroup = DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL;
}

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

// Ensure enough free memory exists before allocating to avoid an out-of-memory error
// when over budget.
if (descriptor.AlwaysInBudget) {
ReturnIfFailed(residencyManager->Evict(descriptor.SizeInBytes, memorySegmentGroup));
}
// Ensure enough free memory exists before allocating to avoid an out-of-memory error
// when over budget.
if (pResidencyManager != nullptr && descriptor.AlwaysInBudget) {
ReturnIfFailed(pResidencyManager->Evict(descriptor.SizeInBytes, memorySegmentGroup));
}

ComPtr<ID3D12Pageable> pageable;
Expand All @@ -50,15 +58,15 @@ namespace gpgmm::d3d12 {
descriptor.SizeInBytes, descriptor.Alignment,
descriptor.IsExternal));

if (residencyManager != nullptr) {
ReturnIfFailed(residencyManager->InsertHeap(heap.get()));
if (pResidencyManager != nullptr) {
ReturnIfFailed(pResidencyManager->InsertHeap(heap.get()));
}

ReturnIfFailed(heap->SetDebugName(descriptor.DebugName));
GPGMM_TRACE_EVENT_OBJECT_SNAPSHOT(heap.get(), descriptor);

if (heapOut != nullptr) {
*heapOut = heap.release();
if (ppHeapOut != nullptr) {
*ppHeapOut = heap.release();
}

return S_OK;
Expand Down
26 changes: 22 additions & 4 deletions src/gpgmm/d3d12/HeapD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ namespace gpgmm::d3d12 {
class ResidencyManager;
class ResourceAllocator;

/** \enum RESIDENCY_SEGMENT
Specifies which type of segment the heap belongs to.

RESIDENCY_SEGMENT is equivelent to DXGI_MEMORY_SEGMENT_GROUP but also has
RESIDENCY_SEGMENT_UNKNOWN.
*/
enum RESIDENCY_SEGMENT {
RESIDENCY_SEGMENT_UNKNOWN,
RESIDENCY_SEGMENT_LOCAL,
RESIDENCY_SEGMENT_NON_LOCAL,
};

/** \struct HEAP_INFO
Additional information about the heap.
*/
Expand Down Expand Up @@ -85,6 +97,12 @@ namespace gpgmm::d3d12 {
*/
bool IsExternal;

/** \brief Specifies the memory segment to use for residency.

Allows any heap to specify a segment which does not have a attributed heap type.
*/
RESIDENCY_SEGMENT MemorySegment;

/** \brief Debug name associated with the heap.
*/
std::string DebugName;
Expand Down Expand Up @@ -121,15 +139,15 @@ namespace gpgmm::d3d12 {
implicit D3D12 heap OR 2) an explicit D3D12 heap used with placed resources.

@param descriptor A reference to HEAP_DESC structure that describes the heap.
@param residencyManager A pointer to the ResidencyManager used to manage this heap.
@param pResidencyManager A pointer to the ResidencyManager used to manage this heap.
@param createHeapFn A callback function which creates a ID3D12Pageable derived type.
@param[out] heapOut Pointer to a memory block that recieves a pointer to the
@param[out] ppHeapOut Pointer to a memory block that recieves a pointer to the
heap.
*/
static HRESULT CreateHeap(const HEAP_DESC& descriptor,
ResidencyManager* const residencyManager,
ResidencyManager* const pResidencyManager,
CreateHeapFn&& createHeapFn,
Heap** heapOut);
Heap** ppHeapOut);

// TODO: Make private.
Heap(ComPtr<ID3D12Pageable> pageable,
Expand Down
1 change: 1 addition & 0 deletions src/gpgmm/d3d12/JSONSerializerD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ namespace gpgmm::d3d12 {
dict.AddItem("HeapType", desc.HeapType);
dict.AddItem("AlwaysInBudget", desc.AlwaysInBudget);
dict.AddItem("IsExternal", desc.IsExternal);
dict.AddItem("MemorySegment", desc.MemorySegment);
dict.AddItem("DebugName", desc.DebugName);
return dict;
}
Expand Down
33 changes: 33 additions & 0 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,39 @@ class D3D12ResidencyManagerTests : public D3D12TestBase, public ::testing::Test
}
};

TEST_F(D3D12ResidencyManagerTests, CreateResourceHeap) {
ComPtr<ResidencyManager> residencyManager;
ASSERT_SUCCEEDED(ResidencyManager::CreateResidencyManager(
CreateBasicResidencyDesc(kDefaultBudget), &residencyManager));

constexpr uint64_t kHeapSize = GPGMM_MB_TO_BYTES(10);

auto createResourceHeapFn = [&](ID3D12Pageable** ppPageableOut) -> HRESULT {
D3D12_HEAP_PROPERTIES heapProperties = {};
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;

D3D12_HEAP_DESC heapDesc = {};
heapDesc.Properties = heapProperties;
heapDesc.SizeInBytes = kHeapSize;

ComPtr<ID3D12Heap> heap;
if (FAILED(mDevice->CreateHeap(&heapDesc, IID_PPV_ARGS(&heap)))) {
return E_FAIL;
}
*ppPageableOut = heap.Detach();
return S_OK;
};

HEAP_DESC resourceHeapDesc = {};
resourceHeapDesc.SizeInBytes = kHeapSize;
resourceHeapDesc.DebugName = "Resource heap";
resourceHeapDesc.AlwaysInBudget = true;
resourceHeapDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ASSERT_SUCCEEDED(
Heap::CreateHeap(resourceHeapDesc, residencyManager.Get(), createResourceHeapFn, nullptr));
}

TEST_F(D3D12ResidencyManagerTests, CreateResidencySet) {
ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(CreateBasicAllocatorDesc(),
Expand Down