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
10 changes: 8 additions & 2 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,13 @@ namespace gpgmm::d3d12 {
ReturnIfFailed(GetHeapType(initialResourceState, &heapType));
}

// Attribution of heaps may be abandoned but the original heap type is needed to
// check if sub-allocation within is allowed. Since default heaps do not require a
// persistent resource state once created, they are disallowed.
const bool isCreatedResourceStateRequired =
(heapType != D3D12_HEAP_TYPE_DEFAULT) &&
(GetInitialResourceState(heapType) == initialResourceState);

// Abandon the attribution of heaps when isCacheCoherentUMA is true by always using the
// custom equivelent of upload heap everywhere. This optimizes resource allocation by
// allowing the same resource allocator to be used, improving heap reuse. However, CPU
Expand Down Expand Up @@ -947,8 +954,7 @@ namespace gpgmm::d3d12 {
if (allocationDescriptor.Flags & ALLOCATION_FLAG_ALLOW_SUBALLOCATE_WITHIN_RESOURCE &&
resourceInfo.Alignment > newResourceDesc.Width &&
newResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
GetInitialResourceState(heapType) == initialResourceState && !isAlwaysCommitted &&
!neverSubAllocate) {
isCreatedResourceStateRequired && !isAlwaysCommitted && !neverSubAllocate) {
allocator = mSmallBufferAllocatorOfType[static_cast<size_t>(resourceHeapType)].get();

// GetResourceAllocationInfo() always rejects alignments smaller than 64KB. So if the
Expand Down
63 changes: 58 additions & 5 deletions src/tests/end2end/D3D12ResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithin) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferDesc, CreateBasicBufferDesc(4u, 1), D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, &smallBuffer));
ASSERT_NE(smallBuffer, nullptr);

EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
EXPECT_EQ(smallBuffer->GetSize(), 4u);
EXPECT_EQ(smallBuffer->GetOffsetFromResource(), 0u);
Expand All @@ -683,7 +683,7 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithin) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferWithinDesc, CreateBasicBufferDesc(4u, 16), D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, &smallBuffer));
ASSERT_NE(smallBuffer, nullptr);

EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
EXPECT_EQ(smallBuffer->GetSize(), 16u);
EXPECT_EQ(smallBuffer->GetOffsetFromResource(), 0u);
Expand All @@ -701,7 +701,7 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithin) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferWithinDesc, CreateBasicBufferDesc(4u), D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr, &smallBuffer));
ASSERT_NE(smallBuffer, nullptr);

EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
EXPECT_EQ(smallBuffer->GetSize(), 256u);
EXPECT_EQ(smallBuffer->GetOffsetFromResource(), 0u);
Expand All @@ -719,7 +719,7 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithin) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferWithinDesc, CreateBasicBufferDesc(4u), D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, &smallBuffer));
ASSERT_NE(smallBuffer, nullptr);

EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
EXPECT_EQ(smallBuffer->GetSize(), 4u);
EXPECT_EQ(smallBuffer->GetOffsetFromResource(), 0u);
Expand All @@ -733,12 +733,65 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithin) {
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferWithinDesc, CreateBasicBufferDesc(3u), D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, &smallBuffer));
ASSERT_NE(smallBuffer, nullptr);

EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
EXPECT_EQ(smallBuffer->GetSize(), 4u);
EXPECT_EQ(smallBuffer->GetOffsetFromResource(), 0u);
EXPECT_EQ(smallBuffer->GetAlignment(), 4u); // Re-align
}

// Default heap using a required resource state of another compatible heap type is not allowed.
{
ALLOCATION_DESC invalidSmallBufferWithinDesc = baseAllocationDesc;
invalidSmallBufferWithinDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<ResourceAllocation> smallBuffer;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
invalidSmallBufferWithinDesc, CreateBasicBufferDesc(3u), D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, &smallBuffer));
EXPECT_NE(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
}

// Non-compatible heap type is not allowed reguardless of resource state specified.
{
ALLOCATION_DESC invalidSmallBufferWithinDesc = baseAllocationDesc;
invalidSmallBufferWithinDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<ResourceAllocation> smallBuffer;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
invalidSmallBufferWithinDesc, CreateBasicBufferDesc(3u), D3D12_RESOURCE_STATE_COMMON,
nullptr, &smallBuffer));
EXPECT_NE(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
}

// Custom heaps should use a heap type inferred by the resource state required.
{
ALLOCATION_DESC smallBufferWithinDesc = baseAllocationDesc;
smallBufferWithinDesc.HeapType = D3D12_HEAP_TYPE_CUSTOM;

ComPtr<ResourceAllocation> smallBuffer;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
smallBufferWithinDesc, CreateBasicBufferDesc(3u), D3D12_RESOURCE_STATE_COPY_DEST,
nullptr, &smallBuffer));
EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
}

// Unspecified heap type should use the heap type inferred by the resource state
// required.
{
ComPtr<ResourceAllocation> smallBuffer;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
baseAllocationDesc, CreateBasicBufferDesc(3u), D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
&smallBuffer));
EXPECT_EQ(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
}
{
ComPtr<ResourceAllocation> smallBuffer;
ASSERT_SUCCEEDED(
resourceAllocator->CreateResource(baseAllocationDesc, CreateBasicBufferDesc(3u),
D3D12_RESOURCE_STATE_COMMON, nullptr, &smallBuffer));
EXPECT_NE(smallBuffer->GetMethod(), gpgmm::AllocationMethod::kSubAllocatedWithin);
}
}

TEST_F(D3D12ResourceAllocatorTests, CreateBufferWithinMany) {
Expand Down