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
2 changes: 1 addition & 1 deletion .github/workflows/.patches/dawn.diff
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ index 214fa67f8..d909d4d2a 100644
+ResultOrError<ComPtr<gpgmm::d3d12::IResourceAllocation>> Device::CreateExternalAllocation(
+ ComPtr<ID3D12Resource> texture) {
+ ComPtr<gpgmm::d3d12::IResourceAllocation> allocation;
+ DAWN_TRY(CheckHRESULT(mResourceAllocator->CreateResource(texture.Get(), &allocation),
+ DAWN_TRY(CheckHRESULT(mResourceAllocator->CreateResource({}, texture.Get(), &allocation),
+ "CreateResource failed"));
+ return allocation;
+}
Expand Down
15 changes: 12 additions & 3 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,14 @@ namespace gpgmm::d3d12 {
Mostly used for debug and testing when certain allocation methods unexpectedly fail.
*/
ALLOCATION_FLAG_NEVER_FALLBACK = 0x40,

/** \brief Disable residency management for the resource allocation.

The flag disables residency management for the resource allocation.

Mostly used when external resources are residency managed elsewhere.
*/
ALLOCATION_FLAG_DISABLE_RESIDENCY = 0x80,
};

DEFINE_ENUM_FLAG_OPERATORS(ALLOCATION_FLAGS)
Expand Down Expand Up @@ -1190,15 +1198,16 @@ namespace gpgmm::d3d12 {

Allows externally created D3D12 resources to be used as a ResourceAllocation.

Residency is not supported for imported resources.

@param allocationDescriptor A reference to ALLOCATION_DESC structure that provides
properties for the resource allocation.
@param pCommittedResource A pointer to a committed ID3D12Resource.
@param[out] ppResourceAllocationOut Pointer to a memory block that receives a pointer to the
resource allocation. Pass NULL to test if resource allocation creation would succeed, but
not actually create the resource allocation. If NULL is passed and resource allocation
creation would succeed, S_FALSE is returned.
*/
virtual HRESULT CreateResource(ID3D12Resource* pCommittedResource,
virtual HRESULT CreateResource(const ALLOCATION_DESC& allocationDescriptor,
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) = 0;

/** \brief Return free memory back to the OS.
Expand Down
14 changes: 9 additions & 5 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1224,7 +1224,8 @@ namespace gpgmm::d3d12 {
return S_OK;
}

HRESULT ResourceAllocator::CreateResource(ID3D12Resource* pCommittedResource,
HRESULT ResourceAllocator::CreateResource(const ALLOCATION_DESC& allocationDescriptor,
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) {
std::lock_guard<std::mutex> lock(mMutex);

Expand All @@ -1248,9 +1249,13 @@ namespace gpgmm::d3d12 {
ImportResourceCallbackContext importResourceCallbackContext(resource);

ComPtr<IHeap> resourceHeap;
ReturnIfFailed(Heap::CreateHeap(resourceHeapDesc, /*residencyManager*/ nullptr,
ImportResourceCallbackContext::CreateHeap,
&importResourceCallbackContext, &resourceHeap));
ReturnIfFailed(
Heap::CreateHeap(resourceHeapDesc,
(allocationDescriptor.Flags & ALLOCATION_FLAG_DISABLE_RESIDENCY)
? nullptr
: mResidencyManager.Get(),
ImportResourceCallbackContext::CreateHeap,
&importResourceCallbackContext, &resourceHeap));

const uint64_t& allocationSize = resourceInfo.SizeInBytes;
mStats.UsedMemoryUsage += allocationSize;
Expand All @@ -1261,7 +1266,6 @@ namespace gpgmm::d3d12 {
allocationDesc.HeapOffset = kInvalidSize;
allocationDesc.SizeInBytes = allocationSize;
allocationDesc.Method = AllocationMethod::kStandalone;
allocationDesc.OffsetFromResource = 0;

if (ppResourceAllocationOut != nullptr) {
*ppResourceAllocationOut = new ResourceAllocation(
Expand Down
3 changes: 2 additions & 1 deletion src/gpgmm/d3d12/ResourceAllocatorD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ namespace gpgmm::d3d12 {
D3D12_RESOURCE_STATES initialResourceState,
const D3D12_CLEAR_VALUE* pClearValue,
IResourceAllocation** ppResourceAllocationOut) override;
HRESULT CreateResource(ID3D12Resource* pCommittedResource,
HRESULT CreateResource(const ALLOCATION_DESC& allocationDescriptor,
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) override;
uint64_t ReleaseMemory(uint64_t bytesToRelease) override;
RESOURCE_ALLOCATOR_STATS GetStats() const override;
Expand Down
6 changes: 3 additions & 3 deletions src/mvi/gpgmm_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,9 @@ namespace gpgmm::d3d12 {
return S_OK;
}

HRESULT ResourceAllocator::CreateResource(
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) {
HRESULT ResourceAllocator::CreateResource(const ALLOCATION_DESC& allocationDescriptor,
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) {
return E_NOTIMPL;
}

Expand Down
3 changes: 2 additions & 1 deletion src/mvi/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ namespace gpgmm::d3d12 {
D3D12_RESOURCE_STATES initialResourceState,
const D3D12_CLEAR_VALUE* pClearValue,
IResourceAllocation** ppResourceAllocationOut) override;
HRESULT CreateResource(ID3D12Resource* pCommittedResource,
HRESULT CreateResource(const ALLOCATION_DESC& allocationDescriptor,
ID3D12Resource* pCommittedResource,
IResourceAllocation** ppResourceAllocationOut) override;
uint64_t ReleaseMemory(uint64_t bytesToRelease) override;
RESOURCE_ALLOCATOR_STATS GetStats() const override;
Expand Down
60 changes: 60 additions & 0 deletions src/tests/end2end/D3D12ResidencyManagerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,4 +691,64 @@ TEST_F(D3D12ResidencyManagerTests, ExecuteCommandListOverBudget) {
for (auto& allocation : secondSetOfHeaps) {
EXPECT_EQ(allocation->GetMemory()->GetInfo().Status, RESIDENCY_STATUS_CURRENT_RESIDENT);
}
}

TEST_F(D3D12ResidencyManagerTests, OverBudgetImported) {
RESIDENCY_DESC residencyDesc = CreateBasicResidencyDesc(kDefaultBudget);

ComPtr<IResidencyManager> residencyManager;
ASSERT_SUCCEEDED(CreateResidencyManager(residencyDesc, &residencyManager));

ComPtr<IResourceAllocator> resourceAllocator;
ASSERT_SUCCEEDED(CreateResourceAllocator(CreateBasicAllocatorDesc(), residencyManager.Get(),
&resourceAllocator));

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

// Keep importing externally allocated resources until we reach the budget.
std::vector<ComPtr<IResourceAllocation>> allocationsBelowBudget = {};
while (resourceAllocator->GetStats().UsedMemoryUsage + kBufferMemorySize <= kDefaultBudget) {
D3D12_HEAP_PROPERTIES heapProperties = {};
heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;

ComPtr<ID3D12Resource> resource;
ASSERT_SUCCEEDED(mDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE,
&bufferDesc, D3D12_RESOURCE_STATE_COMMON,
nullptr, IID_PPV_ARGS(&resource)));

ComPtr<IResourceAllocation> allocation;
ASSERT_SUCCEEDED(
resourceAllocator->CreateResource({}, resource.Detach(), &allocation)); // import
allocationsBelowBudget.push_back(std::move(allocation));
}

// Created allocations below the budget should become resident.
for (auto& allocation : allocationsBelowBudget) {
EXPECT_TRUE(allocation->GetMemory()->GetInfo().IsCachedForResidency);
}

// Keep allocating |kMemoryOverBudget| over the budget.
constexpr uint64_t kMemoryOverBudget = GPGMM_MB_TO_BYTES(10);

// Allocating the same amount over budget, where older allocations will be evicted.
std::vector<ComPtr<IResourceAllocation>> allocationsAboveBudget = {};
const uint64_t currentMemoryUsage = resourceAllocator->GetStats().UsedMemoryUsage;

while (currentMemoryUsage + kMemoryOverBudget > resourceAllocator->GetStats().UsedMemoryUsage) {
ComPtr<IResourceAllocation> allocation;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(
{}, bufferDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &allocation));
allocationsAboveBudget.push_back(std::move(allocation));
}

// Created allocations above the budget should become resident.
for (auto& allocation : allocationsAboveBudget) {
EXPECT_TRUE(allocation->GetMemory()->GetInfo().IsCachedForResidency);
}

// Created allocations below the budget should NOT become resident.
for (auto& allocation : allocationsBelowBudget) {
EXPECT_FALSE(allocation->GetMemory()->GetInfo().IsCachedForResidency);
}
}
11 changes: 6 additions & 5 deletions src/tests/end2end/D3D12ResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferImported) {

// Importing a non-existent buffer should always fail.
ComPtr<IResourceAllocation> externalAllocation;
ASSERT_FAILED(resourceAllocator->CreateResource(nullptr, &externalAllocation));
ASSERT_FAILED(resourceAllocator->CreateResource({}, nullptr, &externalAllocation));
ASSERT_EQ(externalAllocation, nullptr);

ALLOCATION_DESC allocationDesc = {};
Expand All @@ -830,19 +830,20 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBufferImported) {
ASSERT_NE(externalAllocation, nullptr);

ComPtr<IResourceAllocation> internalAllocation;
ASSERT_SUCCEEDED(
resourceAllocator->CreateResource(externalAllocation->GetResource(), &internalAllocation));
ASSERT_SUCCEEDED(resourceAllocator->CreateResource({}, externalAllocation->GetResource(),
&internalAllocation));
ASSERT_NE(internalAllocation, nullptr);

// Underlying resource must stay the same.
ASSERT_EQ(internalAllocation->GetResource(), externalAllocation->GetResource());

// Importing a buffer without creating an allocation should always succeed.
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(externalAllocation->GetResource(), nullptr));
ASSERT_SUCCEEDED(
resourceAllocator->CreateResource({}, externalAllocation->GetResource(), nullptr));

// Re-importing a buffer should create another allocation from the same resource.
ComPtr<IResourceAllocation> internalAllocationAgain;
ASSERT_SUCCEEDED(resourceAllocator->CreateResource(externalAllocation->GetResource(),
ASSERT_SUCCEEDED(resourceAllocator->CreateResource({}, externalAllocation->GetResource(),
&internalAllocationAgain));

// Underlying resource must stay the same.
Expand Down