Residency 2: Create a d3d12::Heap During Direct Allocations
When creating a directly allocated resource in D3D12, also create a dawn_native::d3d12::Heap to represent that allocation alongside the ResourceHeapAllocation. This matches D3D12's allocation model when using CreateCommittedResource and makes residency management much easier. Bug: dawn:193 Change-Id: I2280863dcfca57bad72962a2b097f8f2d4cc7dad Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/16381 Commit-Queue: Brandon Jones <brandon1.jones@intel.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
be6cd51888
commit
f3bb4f4f32
|
@ -31,6 +31,9 @@ namespace dawn_native {
|
||||||
// Memory sub-divided using one or more blocks of various sizes.
|
// Memory sub-divided using one or more blocks of various sizes.
|
||||||
kSubAllocated,
|
kSubAllocated,
|
||||||
|
|
||||||
|
// Memory was allocated outside of Dawn.
|
||||||
|
kExternal,
|
||||||
|
|
||||||
// Memory not allocated or freed.
|
// Memory not allocated or freed.
|
||||||
kInvalid
|
kInvalid
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
class CommandBuffer;
|
class CommandBuffer;
|
||||||
class ComputePipeline;
|
class ComputePipeline;
|
||||||
class Device;
|
class Device;
|
||||||
|
class Heap;
|
||||||
class PipelineLayout;
|
class PipelineLayout;
|
||||||
class Queue;
|
class Queue;
|
||||||
class RenderPipeline;
|
class RenderPipeline;
|
||||||
|
@ -47,6 +48,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
using PipelineLayoutType = PipelineLayout;
|
using PipelineLayoutType = PipelineLayout;
|
||||||
using QueueType = Queue;
|
using QueueType = Queue;
|
||||||
using RenderPipelineType = RenderPipeline;
|
using RenderPipelineType = RenderPipeline;
|
||||||
|
using ResourceHeapType = Heap;
|
||||||
using SamplerType = Sampler;
|
using SamplerType = Sampler;
|
||||||
using ShaderModuleType = ShaderModule;
|
using ShaderModuleType = ShaderModule;
|
||||||
using StagingBufferType = StagingBuffer;
|
using StagingBufferType = StagingBuffer;
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
mDevice->GetD3D12Device()->CreateHeap(&heapDesc, IID_PPV_ARGS(&heap)),
|
mDevice->GetD3D12Device()->CreateHeap(&heapDesc, IID_PPV_ARGS(&heap)),
|
||||||
"ID3D12Device::CreateHeap"));
|
"ID3D12Device::CreateHeap"));
|
||||||
|
|
||||||
return {std::make_unique<Heap>(std::move(heap))};
|
return {std::make_unique<Heap>(std::move(heap), size)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeapAllocator::DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> heap) {
|
void HeapAllocator::DeallocateResourceHeap(std::unique_ptr<ResourceHeapBase> heap) {
|
||||||
|
|
|
@ -15,11 +15,25 @@
|
||||||
#include "dawn_native/d3d12/HeapD3D12.h"
|
#include "dawn_native/d3d12/HeapD3D12.h"
|
||||||
|
|
||||||
namespace dawn_native { namespace d3d12 {
|
namespace dawn_native { namespace d3d12 {
|
||||||
|
Heap::Heap(ComPtr<ID3D12Pageable> d3d12Pageable, uint64_t size)
|
||||||
Heap::Heap(ComPtr<ID3D12Heap> heap) : mHeap(std::move(heap)) {
|
: mD3d12Pageable(std::move(d3d12Pageable)), mSize(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function should only be used when mD3D12Pageable was initialized from a ID3D12Pageable
|
||||||
|
// that was initially created as an ID3D12Heap (i.e. SubAllocation). If the ID3D12Pageable was
|
||||||
|
// initially created as an ID3D12Resource (i.e. DirectAllocation), then use GetD3D12Pageable().
|
||||||
ComPtr<ID3D12Heap> Heap::GetD3D12Heap() const {
|
ComPtr<ID3D12Heap> Heap::GetD3D12Heap() const {
|
||||||
return mHeap;
|
ComPtr<ID3D12Heap> heap;
|
||||||
|
HRESULT result = mD3d12Pageable.As(&heap);
|
||||||
|
ASSERT(SUCCEEDED(result));
|
||||||
|
return heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<ID3D12Pageable> Heap::GetD3D12Pageable() const {
|
||||||
|
return mD3d12Pageable;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Heap::GetSize() const {
|
||||||
|
return mSize;
|
||||||
}
|
}
|
||||||
}} // namespace dawn_native::d3d12
|
}} // namespace dawn_native::d3d12
|
|
@ -22,13 +22,17 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
class Heap : public ResourceHeapBase {
|
class Heap : public ResourceHeapBase {
|
||||||
public:
|
public:
|
||||||
Heap(ComPtr<ID3D12Heap> heap);
|
Heap(ComPtr<ID3D12Pageable> d3d12Pageable, uint64_t size);
|
||||||
~Heap() = default;
|
~Heap() = default;
|
||||||
|
|
||||||
ComPtr<ID3D12Heap> GetD3D12Heap() const;
|
ComPtr<ID3D12Heap> GetD3D12Heap() const;
|
||||||
|
ComPtr<ID3D12Pageable> GetD3D12Pageable() const;
|
||||||
|
|
||||||
|
uint64_t GetSize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ComPtr<ID3D12Heap> mHeap;
|
ComPtr<ID3D12Pageable> mD3d12Pageable;
|
||||||
|
uint64_t mSize = 0;
|
||||||
};
|
};
|
||||||
}} // namespace dawn_native::d3d12
|
}} // namespace dawn_native::d3d12
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,13 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
mAllocationsToDelete.Enqueue(allocation, mDevice->GetPendingCommandSerial());
|
mAllocationsToDelete.Enqueue(allocation, mDevice->GetPendingCommandSerial());
|
||||||
|
|
||||||
|
// Directly allocated ResourceHeapAllocations are created with a heap object that must be
|
||||||
|
// manually deleted upon deallocation. See ResourceAllocatorManager::CreateCommittedResource
|
||||||
|
// for more information.
|
||||||
|
if (allocation.GetInfo().mMethod == AllocationMethod::kDirect) {
|
||||||
|
delete allocation.GetResourceHeap();
|
||||||
|
}
|
||||||
|
|
||||||
// Invalidate the allocation immediately in case one accidentally
|
// Invalidate the allocation immediately in case one accidentally
|
||||||
// calls DeallocateMemory again using the same allocation.
|
// calls DeallocateMemory again using the same allocation.
|
||||||
allocation.Invalidate();
|
allocation.Invalidate();
|
||||||
|
@ -246,7 +253,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
return ResourceHeapAllocation{}; // invalid
|
return ResourceHeapAllocation{}; // invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Heap* heap = static_cast<Heap*>(allocation.GetResourceHeap())->GetD3D12Heap().Get();
|
Heap* heap = ToBackend(allocation.GetResourceHeap());
|
||||||
|
|
||||||
// With placed resources, a single heap can be reused.
|
// With placed resources, a single heap can be reused.
|
||||||
// The resource placed at an offset is only reclaimed
|
// The resource placed at an offset is only reclaimed
|
||||||
|
@ -256,13 +263,14 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// barrier).
|
// barrier).
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createplacedresource
|
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createplacedresource
|
||||||
ComPtr<ID3D12Resource> placedResource;
|
ComPtr<ID3D12Resource> placedResource;
|
||||||
DAWN_TRY(CheckOutOfMemoryHRESULT(mDevice->GetD3D12Device()->CreatePlacedResource(
|
DAWN_TRY(CheckOutOfMemoryHRESULT(
|
||||||
heap, allocation.GetOffset(), &resourceDescriptor,
|
mDevice->GetD3D12Device()->CreatePlacedResource(
|
||||||
initialUsage, nullptr, IID_PPV_ARGS(&placedResource)),
|
heap->GetD3D12Heap().Get(), allocation.GetOffset(), &resourceDescriptor,
|
||||||
"ID3D12Device::CreatePlacedResource"));
|
initialUsage, nullptr, IID_PPV_ARGS(&placedResource)),
|
||||||
|
"ID3D12Device::CreatePlacedResource"));
|
||||||
|
|
||||||
return ResourceHeapAllocation{allocation.GetInfo(), allocation.GetOffset(),
|
return ResourceHeapAllocation{allocation.GetInfo(), allocation.GetOffset(),
|
||||||
std::move(placedResource)};
|
std::move(placedResource), heap};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<ResourceHeapAllocation> ResourceAllocatorManager::CreateCommittedResource(
|
ResultOrError<ResourceHeapAllocation> ResourceAllocatorManager::CreateCommittedResource(
|
||||||
|
@ -297,11 +305,18 @@ namespace dawn_native { namespace d3d12 {
|
||||||
initialUsage, nullptr, IID_PPV_ARGS(&committedResource)),
|
initialUsage, nullptr, IID_PPV_ARGS(&committedResource)),
|
||||||
"ID3D12Device::CreateCommittedResource"));
|
"ID3D12Device::CreateCommittedResource"));
|
||||||
|
|
||||||
|
// When using CreateCommittedResource, D3D12 creates an implicit heap that contains the
|
||||||
|
// resource allocation. Because Dawn's memory residency management occurs at the resource
|
||||||
|
// heap granularity, every directly allocated ResourceHeapAllocation also stores a Heap
|
||||||
|
// object. This object is created manually, and must be deleted manually upon deallocation
|
||||||
|
// of the committed resource.
|
||||||
|
Heap* heap = new Heap(committedResource, resourceInfo.SizeInBytes);
|
||||||
|
|
||||||
AllocationInfo info;
|
AllocationInfo info;
|
||||||
info.mMethod = AllocationMethod::kDirect;
|
info.mMethod = AllocationMethod::kDirect;
|
||||||
|
|
||||||
return ResourceHeapAllocation{info,
|
return ResourceHeapAllocation{info,
|
||||||
/*offset*/ 0, std::move(committedResource)};
|
/*offset*/ 0, std::move(committedResource), heap};
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace dawn_native::d3d12
|
}} // namespace dawn_native::d3d12
|
||||||
|
|
|
@ -14,13 +14,17 @@
|
||||||
|
|
||||||
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
|
||||||
|
|
||||||
|
#include "dawn_native/d3d12/HeapD3D12.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace dawn_native { namespace d3d12 {
|
namespace dawn_native { namespace d3d12 {
|
||||||
ResourceHeapAllocation::ResourceHeapAllocation(const AllocationInfo& info,
|
ResourceHeapAllocation::ResourceHeapAllocation(const AllocationInfo& info,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
ComPtr<ID3D12Resource> resource)
|
ComPtr<ID3D12Resource> resource,
|
||||||
: ResourceMemoryAllocation(info, offset, nullptr), mResource(std::move(resource)) {
|
Heap* heap)
|
||||||
|
: ResourceMemoryAllocation(info, offset, heap), mResource(std::move(resource)) {
|
||||||
|
ASSERT((info.mMethod == AllocationMethod::kExternal) == (heap == nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceHeapAllocation::Invalidate() {
|
void ResourceHeapAllocation::Invalidate() {
|
||||||
|
|
|
@ -20,12 +20,15 @@
|
||||||
|
|
||||||
namespace dawn_native { namespace d3d12 {
|
namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
|
class Heap;
|
||||||
|
|
||||||
class ResourceHeapAllocation : public ResourceMemoryAllocation {
|
class ResourceHeapAllocation : public ResourceMemoryAllocation {
|
||||||
public:
|
public:
|
||||||
ResourceHeapAllocation() = default;
|
ResourceHeapAllocation() = default;
|
||||||
ResourceHeapAllocation(const AllocationInfo& info,
|
ResourceHeapAllocation(const AllocationInfo& info,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
ComPtr<ID3D12Resource> resource);
|
ComPtr<ID3D12Resource> resource,
|
||||||
|
Heap* heap);
|
||||||
~ResourceHeapAllocation() override = default;
|
~ResourceHeapAllocation() override = default;
|
||||||
|
|
||||||
void Invalidate() override;
|
void Invalidate() override;
|
||||||
|
|
|
@ -322,8 +322,11 @@ namespace dawn_native { namespace d3d12 {
|
||||||
mDxgiKeyedMutex = std::move(dxgiKeyedMutex);
|
mDxgiKeyedMutex = std::move(dxgiKeyedMutex);
|
||||||
|
|
||||||
AllocationInfo info;
|
AllocationInfo info;
|
||||||
info.mMethod = AllocationMethod::kDirect;
|
info.mMethod = AllocationMethod::kExternal;
|
||||||
mResourceAllocation = {info, 0, std::move(d3d12Resource)};
|
// When creating the ResourceHeapAllocation, the resource heap is set to nullptr because the
|
||||||
|
// texture is owned externally. The texture's owning entity must remain responsible for
|
||||||
|
// memory management.
|
||||||
|
mResourceAllocation = {info, 0, std::move(d3d12Resource), nullptr};
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -370,8 +373,11 @@ namespace dawn_native { namespace d3d12 {
|
||||||
ComPtr<ID3D12Resource> nativeTexture)
|
ComPtr<ID3D12Resource> nativeTexture)
|
||||||
: TextureBase(device, descriptor, TextureState::OwnedExternal) {
|
: TextureBase(device, descriptor, TextureState::OwnedExternal) {
|
||||||
AllocationInfo info;
|
AllocationInfo info;
|
||||||
info.mMethod = AllocationMethod::kDirect;
|
info.mMethod = AllocationMethod::kExternal;
|
||||||
mResourceAllocation = {info, 0, std::move(nativeTexture)};
|
// When creating the ResourceHeapAllocation, the resource heap is set to nullptr because the
|
||||||
|
// texture is owned externally. The texture's owning entity must remain responsible for
|
||||||
|
// memory management.
|
||||||
|
mResourceAllocation = {info, 0, std::move(nativeTexture), nullptr};
|
||||||
|
|
||||||
SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
|
SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
|
||||||
descriptor->arrayLayerCount);
|
descriptor->arrayLayerCount);
|
||||||
|
|
Loading…
Reference in New Issue