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: 7 additions & 1 deletion src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -879,8 +879,11 @@ namespace gpgmm::d3d12 {
return E_INVALIDARG;
}

// Check memory requirements.
// Resource is always committed when heaps flags are incompatible with the resource heap
// type or if specified by the flag.
bool isAlwaysCommitted = mIsAlwaysCommitted;

// Check memory requirements.
D3D12_HEAP_FLAGS heapFlags = GetHeapFlags(resourceHeapType, IsCreateHeapNotResident());
if (!HasAllFlags(heapFlags, allocationDescriptor.ExtraRequiredHeapFlags)) {
DebugEvent(GetTypename())
Expand Down Expand Up @@ -1107,6 +1110,9 @@ namespace gpgmm::d3d12 {
}

if (!isAlwaysCommitted) {
if (allocationDescriptor.Flags & ALLOCATION_FLAG_NEVER_FALLBACK) {
return E_FAIL;
}
InfoEvent(GetTypename(), EventMessageId::AllocatorFailed)
<< "Unable to allocate by using a heap, falling back to a committed resource.";
}
Expand Down
10 changes: 10 additions & 0 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,16 @@ namespace gpgmm::d3d12 {
D3D12_HEAP_TYPE_READBACK, or the adapter is not cache-coherent UMA, this flag has no effect.
*/
ALLOCATION_FLAG_ALWAYS_ATTRIBUTE_HEAPS = 0x20,

/** \brief Forces the allocator allocation algorithm to be used or E_FAIL.

By default, the allocation method used may not be used due to incompatible constraints. This
flag will disable the default fall-back behavior of using the safest allocation method
possible.

Mostly used for debug and testing when certain allocation methods unexpectedly fail.
*/
ALLOCATION_FLAG_NEVER_FALLBACK = 0x40,
};

DEFINE_ENUM_FLAG_OPERATORS(ALLOCATION_FLAGS)
Expand Down
1 change: 1 addition & 0 deletions src/include/min/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ namespace gpgmm::d3d12 {
ALLOCATION_FLAG_ALWAYS_PREFETCH_MEMORY = 0x8,
ALLOCATION_FLAG_ALWAYS_CACHE_SIZE = 0x10,
ALLOCATION_FLAG_ALWAYS_ATTRIBUTE_HEAPS = 0x20,
ALLOCATION_FLAG_NEVER_FALLBACK = 0x40,
};

DEFINE_ENUM_FLAG_OPERATORS(ALLOCATION_FLAGS)
Expand Down
22 changes: 12 additions & 10 deletions src/tests/GPGMMTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "tests/GPGMMTest.h"

#include "gpgmm/common/SizeClass.h"

#include <iostream>

static GPGMMTestEnvironment* gTestEnv = nullptr;
Expand Down Expand Up @@ -61,20 +63,20 @@ std::vector<MEMORY_ALLOCATION_EXPECT> GPGMMTestBase::GenerateTestAllocations(uin

// Common small sizes, likely sub-allocated.
{256, alignment, true},
{1 * 1024, alignment, true},
{4 * 1024, alignment, true},
{GPGMM_KB_TO_BYTES(1), alignment, true},
{GPGMM_KB_TO_BYTES(4), alignment, true},

// Common large sizes, likely standalone.
{16 * 1024 * 1024, 0, true},
{64 * 1024 * 1024, 0, true},
{GPGMM_MB_TO_BYTES(16), 0, true},
{GPGMM_MB_TO_BYTES(64), 0, true},

// Mixed sizes, any method.
{1 * 1024, 1, true},
{64 * 1024 * 1024, 0, true},
{1 * 1024, 1, true},
{64 * 1024 * 1024, 0, true},
{1 * 1024, 1, true},
{64 * 1024 * 1024, 0, true},
{GPGMM_KB_TO_BYTES(1), 1, true},
{GPGMM_MB_TO_BYTES(64), 0, true},
{GPGMM_KB_TO_BYTES(1), 1, true},
{GPGMM_MB_TO_BYTES(64), 0, true},
{GPGMM_KB_TO_BYTES(1), 1, true},
{GPGMM_MB_TO_BYTES(64), 0, true},

// Increasing sizes, any method.
{alignment * 1, 0, true},
Expand Down
81 changes: 66 additions & 15 deletions src/tests/end2end/D3D12ResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,40 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferOversized) {
TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
ALLOCATOR_DESC allocatorDesc = CreateBasicAllocatorDesc();

// ALLOCATOR_ALGORITHM_SLAB
// Ensure the underlying memory size is large enough so all buffer allocation can fit.
allocatorDesc.PreferredResourceHeapSize = GPGMM_MB_TO_BYTES(64);

// Ensure the allocation will never fall-back to use any method other than the one being tested.
ALLOCATION_DESC allocationDesc = {};
allocationDesc.Flags = ALLOCATION_FLAG_NEVER_FALLBACK;

// ALLOCATOR_ALGORITHM_BUDDY_SYSTEM
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_SLAB;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_BUDDY_SYSTEM;

ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
EXPECT_EQ(SUCCEEDED(resourceAllocator->CreateResource(
allocationDesc, CreateBasicBufferDesc(alloc.size, alloc.alignment),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation)),
alloc.succeeds);
}
}

// ALLOCATOR_ALGORITHM_BUDDY_SYSTEM + ALLOCATOR_ALGORITHM_FIXED_POOL
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_BUDDY_SYSTEM;
newAllocatorDesc.PoolAlgorithm = ALLOCATOR_ALGORITHM_FIXED_POOL;

ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
Expand All @@ -177,17 +200,33 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
}
}

// ALLOCATOR_ALGORITHM_BUDDY_SYSTEM
// ALLOCATOR_ALGORITHM_BUDDY_SYSTEM + ALLOCATOR_ALGORITHM_SEGMENTED_POOL
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_BUDDY_SYSTEM;
newAllocatorDesc.PoolAlgorithm = ALLOCATOR_ALGORITHM_SEGMENTED_POOL;

ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
EXPECT_EQ(SUCCEEDED(resourceAllocator->CreateResource(
allocationDesc, CreateBasicBufferDesc(alloc.size, alloc.alignment),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation)),
alloc.succeeds);
}
}

// ALLOCATOR_ALGORITHM_SLAB
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_SLAB;

ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
Expand All @@ -208,8 +247,24 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

ALLOCATION_DESC allocationDesc = {};
allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
EXPECT_EQ(SUCCEEDED(resourceAllocator->CreateResource(
allocationDesc, CreateBasicBufferDesc(alloc.size, alloc.alignment),
D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation)),
alloc.succeeds);
}
}

// ALLOCATOR_ALGORITHM_SLAB + ALLOCATOR_ALGORITHM_SEGMENTED_POOL
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_SLAB;
newAllocatorDesc.PoolAlgorithm = ALLOCATOR_ALGORITHM_SEGMENTED_POOL;

ComPtr<ResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
Expand All @@ -229,9 +284,6 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

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

for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
EXPECT_EQ(SUCCEEDED(resourceAllocator->CreateResource(
Expand All @@ -240,6 +292,8 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
alloc.succeeds);
}
}

// ALLOCATOR_ALGORITHM_DEDICATED
{
ALLOCATOR_DESC newAllocatorDesc = allocatorDesc;
newAllocatorDesc.SubAllocationAlgorithm = ALLOCATOR_ALGORITHM_DEDICATED;
Expand All @@ -248,9 +302,6 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferSubAllocated) {
ASSERT_SUCCEEDED(ResourceAllocator::CreateAllocator(newAllocatorDesc, &resourceAllocator));
ASSERT_NE(resourceAllocator, nullptr);

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

for (auto& alloc : GenerateBufferAllocations()) {
ComPtr<ResourceAllocation> allocation;
EXPECT_EQ(SUCCEEDED(resourceAllocator->CreateResource(
Expand Down