Resource Management 5: D3D support for resource allocation.
Refactor existing resource allocators by adding a memory type
and memory handle.
BUG=dawn:27, dawn:153
Change-Id: I090b6ab40e7eaa0d7ea5ce1e8b760e961be9b559
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9420
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/dawn_native/Forward.h b/src/dawn_native/Forward.h
index 1ba29da..ad73bef 100644
--- a/src/dawn_native/Forward.h
+++ b/src/dawn_native/Forward.h
@@ -36,6 +36,7 @@
class RenderBundleEncoderBase;
class RenderPassEncoderBase;
class RenderPipelineBase;
+ class ResourceHeapBase;
class SamplerBase;
class ShaderModuleBase;
class StagingBufferBase;
diff --git a/src/dawn_native/ResourceHeap.h b/src/dawn_native/ResourceHeap.h
new file mode 100644
index 0000000..c4d6707
--- /dev/null
+++ b/src/dawn_native/ResourceHeap.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_RESOURCEHEAP_H_
+#define DAWNNATIVE_RESOURCEHEAP_H_
+
+#include "dawn_native/Error.h"
+
+namespace dawn_native {
+
+ // Wrapper for a resource backed by a heap.
+ class ResourceHeapBase {
+ protected:
+ ResourceHeapBase() = default;
+ virtual ~ResourceHeapBase() = default;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RESOURCEHEAP_H_
\ No newline at end of file
diff --git a/src/dawn_native/ResourceMemoryAllocation.cpp b/src/dawn_native/ResourceMemoryAllocation.cpp
new file mode 100644
index 0000000..1ace4d4
--- /dev/null
+++ b/src/dawn_native/ResourceMemoryAllocation.cpp
@@ -0,0 +1,53 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/ResourceMemoryAllocation.h"
+#include "common/Assert.h"
+
+#include <limits>
+
+namespace dawn_native {
+
+ static constexpr uint64_t INVALID_OFFSET = std::numeric_limits<uint64_t>::max();
+
+ ResourceMemoryAllocation::ResourceMemoryAllocation()
+ : mMethod(AllocationMethod::kInvalid), mOffset(INVALID_OFFSET), mResourceHeap(nullptr) {
+ }
+
+ ResourceMemoryAllocation::ResourceMemoryAllocation(uint64_t offset,
+ ResourceHeapBase* resourceHeap,
+ AllocationMethod method)
+ : mMethod(method), mOffset(offset), mResourceHeap(resourceHeap) {
+ }
+
+ ResourceHeapBase* ResourceMemoryAllocation::GetResourceHeap() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mResourceHeap;
+ }
+
+ uint64_t ResourceMemoryAllocation::GetOffset() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mOffset;
+ }
+
+ AllocationMethod ResourceMemoryAllocation::GetAllocationMethod() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mMethod;
+ }
+
+ void ResourceMemoryAllocation::Invalidate() {
+ mResourceHeap = nullptr;
+ mMethod = AllocationMethod::kInvalid;
+ }
+} // namespace dawn_native
\ No newline at end of file
diff --git a/src/dawn_native/ResourceMemoryAllocation.h b/src/dawn_native/ResourceMemoryAllocation.h
new file mode 100644
index 0000000..4e69a22
--- /dev/null
+++ b/src/dawn_native/ResourceMemoryAllocation.h
@@ -0,0 +1,60 @@
+// Copyright 2018 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
+#define DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
+
+#include <cstdint>
+
+namespace dawn_native {
+
+ class ResourceHeapBase;
+
+ // Allocation method determines how memory was sub-divided.
+ // Used by the device to get the allocator that was responsible for the allocation.
+ enum class AllocationMethod {
+
+ // Memory not sub-divided.
+ kDirect,
+
+ // Memory sub-divided using one or more blocks of various sizes.
+ kSubAllocated,
+
+ // Memory not allocated or freed.
+ kInvalid
+ };
+
+ // Handle into a resource heap pool.
+ class ResourceMemoryAllocation {
+ public:
+ ResourceMemoryAllocation();
+ ResourceMemoryAllocation(uint64_t offset,
+ ResourceHeapBase* resourceHeap,
+ AllocationMethod method);
+ ~ResourceMemoryAllocation() = default;
+
+ ResourceHeapBase* GetResourceHeap() const;
+ uint64_t GetOffset() const;
+ AllocationMethod GetAllocationMethod() const;
+
+ void Invalidate();
+
+ private:
+ AllocationMethod mMethod;
+ uint64_t mOffset;
+ ResourceHeapBase* mResourceHeap;
+ };
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
\ No newline at end of file
diff --git a/src/dawn_native/ToBackend.h b/src/dawn_native/ToBackend.h
index 4f11fd4..b9940ab 100644
--- a/src/dawn_native/ToBackend.h
+++ b/src/dawn_native/ToBackend.h
@@ -74,6 +74,11 @@
};
template <typename BackendTraits>
+ struct ToBackendTraits<ResourceHeapBase, BackendTraits> {
+ using BackendType = typename BackendTraits::ResourceHeapType;
+ };
+
+ template <typename BackendTraits>
struct ToBackendTraits<SamplerBase, BackendTraits> {
using BackendType = typename BackendTraits::SamplerType;
};
diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp
index 585c24f..148a740 100644
--- a/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -18,7 +18,7 @@
#include "common/Constants.h"
#include "common/Math.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
namespace dawn_native { namespace d3d12 {
@@ -71,6 +71,9 @@
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
+ }
+
+ MaybeError Buffer::Initialize() {
D3D12_RESOURCE_DESC resourceDescriptor;
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resourceDescriptor.Alignment = 0;
@@ -105,8 +108,11 @@
mLastUsage = dawn::BufferUsage::CopySrc;
}
- mResource =
- device->GetResourceAllocator()->Allocate(heapType, resourceDescriptor, bufferUsage);
+ DAWN_TRY_ASSIGN(
+ mResourceAllocation,
+ ToBackend(GetDevice())
+ ->AllocateMemory(heapType, resourceDescriptor, bufferUsage, D3D12_HEAP_FLAG_NONE));
+ return {};
}
Buffer::~Buffer() {
@@ -118,8 +124,8 @@
return Align(GetSize(), 256);
}
- ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() {
- return mResource;
+ ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() const {
+ return ToBackend(mResourceAllocation.GetResourceHeap())->GetD3D12Resource();
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
@@ -174,7 +180,7 @@
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrier->Transition.pResource = mResource.Get();
+ barrier->Transition.pResource = GetD3D12Resource().Get();
barrier->Transition.StateBefore = lastState;
barrier->Transition.StateAfter = newState;
barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
@@ -192,7 +198,7 @@
}
D3D12_GPU_VIRTUAL_ADDRESS Buffer::GetVA() const {
- return mResource->GetGPUVirtualAddress();
+ return ToBackend(mResourceAllocation.GetResourceHeap())->GetGPUPointer();
}
void Buffer::OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite) {
@@ -210,8 +216,8 @@
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
mWrittenMappedRange = {0, GetSize()};
- ASSERT_SUCCESS(
- mResource->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(mappedPointer)));
+ ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &mWrittenMappedRange,
+ reinterpret_cast<void**>(mappedPointer)));
return {};
}
@@ -219,8 +225,7 @@
mWrittenMappedRange = {};
D3D12_RANGE readRange = {0, GetSize()};
char* data = nullptr;
- ASSERT_SUCCESS(mResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
-
+ ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &readRange, reinterpret_cast<void**>(&data)));
// There is no need to transition the resource to a new state: D3D12 seems to make the GPU
// writes available when the fence is passed.
MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker();
@@ -231,8 +236,8 @@
MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) {
mWrittenMappedRange = {0, GetSize()};
char* data = nullptr;
- ASSERT_SUCCESS(mResource->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(&data)));
-
+ ASSERT_SUCCESS(
+ GetD3D12Resource()->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(&data)));
// There is no need to transition the resource to a new state: D3D12 seems to make the CPU
// writes available on queue submission.
MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker();
@@ -241,14 +246,12 @@
}
void Buffer::UnmapImpl() {
- mResource->Unmap(0, &mWrittenMappedRange);
- ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
+ GetD3D12Resource()->Unmap(0, &mWrittenMappedRange);
mWrittenMappedRange = {};
}
void Buffer::DestroyImpl() {
- ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
- mResource = nullptr;
+ ToBackend(GetDevice())->DeallocateMemory(mResourceAllocation);
}
MapRequestTracker::MapRequestTracker(Device* device) : mDevice(device) {
diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h
index 1b8b177..7a9b433 100644
--- a/src/dawn_native/d3d12/BufferD3D12.h
+++ b/src/dawn_native/d3d12/BufferD3D12.h
@@ -18,6 +18,7 @@
#include "common/SerialQueue.h"
#include "dawn_native/Buffer.h"
+#include "dawn_native/ResourceMemoryAllocation.h"
#include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 {
@@ -29,8 +30,10 @@
Buffer(Device* device, const BufferDescriptor* descriptor);
~Buffer();
+ MaybeError Initialize();
+
uint32_t GetD3D12Size() const;
- ComPtr<ID3D12Resource> GetD3D12Resource();
+ ComPtr<ID3D12Resource> GetD3D12Resource() const;
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite);
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier,
@@ -48,7 +51,7 @@
bool IsMapWritable() const override;
virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
- ComPtr<ID3D12Resource> mResource;
+ ResourceMemoryAllocation mResourceAllocation;
bool mFixedResourceState = false;
dawn::BufferUsage mLastUsage = dawn::BufferUsage::None;
Serial mLastUsedSerial = UINT64_MAX;
diff --git a/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp b/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp
new file mode 100644
index 0000000..772f5d2
--- /dev/null
+++ b/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp
@@ -0,0 +1,52 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/d3d12/CommittedResourceAllocatorD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ CommittedResourceAllocator::CommittedResourceAllocator(Device* device, D3D12_HEAP_TYPE heapType)
+ : mDevice(device), mHeapType(heapType) {
+ }
+
+ ResultOrError<ResourceMemoryAllocation> CommittedResourceAllocator::Allocate(
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags) {
+ D3D12_HEAP_PROPERTIES heapProperties;
+ heapProperties.Type = mHeapType;
+ heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProperties.CreationNodeMask = 0;
+ heapProperties.VisibleNodeMask = 0;
+
+ ComPtr<ID3D12Resource> committedResource;
+ if (FAILED(mDevice->GetD3D12Device()->CreateCommittedResource(
+ &heapProperties, heapFlags, &resourceDescriptor, initialUsage, nullptr,
+ IID_PPV_ARGS(&committedResource)))) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate resource");
+ }
+
+ return ResourceMemoryAllocation(
+ /*offset*/ 0, new ResourceHeap(std::move(committedResource)),
+ AllocationMethod::kDirect);
+ }
+
+ void CommittedResourceAllocator::Deallocate(ResourceMemoryAllocation& allocation) {
+ std::unique_ptr<ResourceHeap> resourceHeap(ToBackend(allocation.GetResourceHeap()));
+ mDevice->ReferenceUntilUnused(resourceHeap->GetD3D12Resource());
+ }
+}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h b/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h
new file mode 100644
index 0000000..419d1c6
--- /dev/null
+++ b/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
+#define DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
+
+#include "common/SerialQueue.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/ResourceMemoryAllocation.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ class Device;
+
+ // Wrapper to allocate D3D12 committed resource.
+ // Committed resources are implicitly backed by a D3D12 heap.
+ class CommittedResourceAllocator {
+ public:
+ CommittedResourceAllocator(Device* device, D3D12_HEAP_TYPE heapType);
+ ~CommittedResourceAllocator() = default;
+
+ ResultOrError<ResourceMemoryAllocation> Allocate(
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags);
+ void Deallocate(ResourceMemoryAllocation& allocation);
+
+ private:
+ Device* mDevice;
+ D3D12_HEAP_TYPE mHeapType;
+ };
+
+}} // namespace dawn_native::d3d12
+
+#endif // DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index 1f23108..16554b8 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -31,6 +31,7 @@
#include "dawn_native/d3d12/QueueD3D12.h"
#include "dawn_native/d3d12/RenderPipelineD3D12.h"
#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
#include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/ShaderModuleD3D12.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h"
@@ -110,12 +111,17 @@
}
NextSerial();
WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing
- TickImpl(); // Call tick one last time so resources are cleaned up
+ TickImpl(); // Call tick one last time so resources are cleaned up
// Free services explicitly so that they can free D3D12 resources before destruction of the
// device.
mDynamicUploader = nullptr;
+ // GPU is no longer executing commands. Existing objects do not get freed until the device
+ // is destroyed. To ensure objects are always released, force the completed serial to be
+ // MAX.
+ mCompletedSerial = std::numeric_limits<Serial>::max();
+
// Releasing the uploader enqueues buffers to be released.
// Call Tick() again to clear them before releasing the allocator.
mResourceAllocator->Tick(mCompletedSerial);
@@ -124,6 +130,8 @@
::CloseHandle(mFenceEvent);
}
+ mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
+
ASSERT(mUsedComObjectRefs.Empty());
ASSERT(mPendingCommands.commandList == nullptr);
}
@@ -264,7 +272,9 @@
return new BindGroupLayout(this, descriptor);
}
ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
- return new Buffer(this, descriptor);
+ std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(this, descriptor);
+ DAWN_TRY(buffer->Initialize());
+ return buffer.release();
}
CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor) {
@@ -326,4 +336,48 @@
return {};
}
+ size_t Device::GetD3D12HeapTypeToIndex(D3D12_HEAP_TYPE heapType) const {
+ ASSERT(heapType > 0);
+ ASSERT(heapType <= kNumHeapTypes);
+ return heapType - 1;
+ }
+
+ void Device::DeallocateMemory(ResourceMemoryAllocation& allocation) {
+ CommittedResourceAllocator* allocator = nullptr;
+ D3D12_HEAP_PROPERTIES heapProp;
+ ToBackend(allocation.GetResourceHeap())
+ ->GetD3D12Resource()
+ ->GetHeapProperties(&heapProp, nullptr);
+ const size_t heapTypeIndex = GetD3D12HeapTypeToIndex(heapProp.Type);
+ ASSERT(heapTypeIndex < kNumHeapTypes);
+ allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ allocator->Deallocate(allocation);
+
+ // Invalidate the underlying resource heap in case the client accidentally
+ // calls DeallocateMemory again using the same allocation.
+ allocation.Invalidate();
+ }
+
+ ResultOrError<ResourceMemoryAllocation> Device::AllocateMemory(
+ D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags) {
+ const size_t heapTypeIndex = GetD3D12HeapTypeToIndex(heapType);
+ ASSERT(heapTypeIndex < kNumHeapTypes);
+
+ // Get the direct allocator using a tightly sized heap (aka CreateCommittedResource).
+ CommittedResourceAllocator* allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ if (allocator == nullptr) {
+ mDirectResourceAllocators[heapTypeIndex] =
+ std::make_unique<CommittedResourceAllocator>(this, heapType);
+ allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ }
+
+ ResourceMemoryAllocation allocation;
+ DAWN_TRY_ASSIGN(allocation,
+ allocator->Allocate(resourceDescriptor, initialUsage, heapFlags));
+
+ return allocation;
+ }
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index e45e811..847fe35 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -19,6 +19,7 @@
#include "common/SerialQueue.h"
#include "dawn_native/Device.h"
+#include "dawn_native/d3d12/CommittedResourceAllocatorD3D12.h"
#include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/d3d12_platform.h"
@@ -81,6 +82,14 @@
uint64_t destinationOffset,
uint64_t size) override;
+ ResultOrError<ResourceMemoryAllocation> AllocateMemory(
+ D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags);
+
+ void DeallocateMemory(ResourceMemoryAllocation& allocation);
+
private:
ResultOrError<BindGroupBase*> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
@@ -104,6 +113,8 @@
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
+ size_t GetD3D12HeapTypeToIndex(D3D12_HEAP_TYPE heapType) const;
+
Serial mCompletedSerial = 0;
Serial mLastSubmittedSerial = 0;
ComPtr<ID3D12Fence> mFence;
@@ -128,6 +139,20 @@
std::unique_ptr<MapRequestTracker> mMapRequestTracker;
std::unique_ptr<ResourceAllocator> mResourceAllocator;
+ static constexpr uint32_t kNumHeapTypes = 4u; // Number of D3D12_HEAP_TYPE
+
+ static_assert(D3D12_HEAP_TYPE_READBACK <= kNumHeapTypes,
+ "Readback heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_UPLOAD <= kNumHeapTypes,
+ "Upload heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_DEFAULT <= kNumHeapTypes,
+ "Default heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_CUSTOM <= kNumHeapTypes,
+ "Custom heap type enum exceeds max heap types");
+
+ std::array<std::unique_ptr<CommittedResourceAllocator>, kNumHeapTypes>
+ mDirectResourceAllocators;
+
dawn_native::PCIInfo mPCIInfo;
};
diff --git a/src/dawn_native/d3d12/Forward.h b/src/dawn_native/d3d12/Forward.h
index ade12e3..f42f824 100644
--- a/src/dawn_native/d3d12/Forward.h
+++ b/src/dawn_native/d3d12/Forward.h
@@ -29,6 +29,7 @@
class PipelineLayout;
class Queue;
class RenderPipeline;
+ class ResourceHeap;
class Sampler;
class ShaderModule;
class StagingBuffer;
@@ -47,6 +48,7 @@
using PipelineLayoutType = PipelineLayout;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
+ using ResourceHeapType = ResourceHeap;
using SamplerType = Sampler;
using ShaderModuleType = ShaderModule;
using StagingBufferType = StagingBuffer;
diff --git a/src/dawn_native/d3d12/ResourceHeapD3D12.cpp b/src/dawn_native/d3d12/ResourceHeapD3D12.cpp
new file mode 100644
index 0000000..5aec4b3
--- /dev/null
+++ b/src/dawn_native/d3d12/ResourceHeapD3D12.cpp
@@ -0,0 +1,30 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ ResourceHeap::ResourceHeap(ComPtr<ID3D12Resource> resource) : mResource(resource) {
+ }
+
+ ComPtr<ID3D12Resource> ResourceHeap::GetD3D12Resource() const {
+ return mResource;
+ }
+
+ D3D12_GPU_VIRTUAL_ADDRESS ResourceHeap::GetGPUPointer() const {
+ return mResource->GetGPUVirtualAddress();
+ }
+}} // namespace dawn_native::d3d12
\ No newline at end of file
diff --git a/src/dawn_native/d3d12/ResourceHeapD3D12.h b/src/dawn_native/d3d12/ResourceHeapD3D12.h
new file mode 100644
index 0000000..18b342a
--- /dev/null
+++ b/src/dawn_native/d3d12/ResourceHeapD3D12.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_
+#define DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_
+
+#include "dawn_native/ResourceHeap.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ // Wrapper for physical memory used with or without a resource object.
+ class ResourceHeap : public ResourceHeapBase {
+ public:
+ ResourceHeap(ComPtr<ID3D12Resource> resource);
+
+ ~ResourceHeap() = default;
+
+ ComPtr<ID3D12Resource> GetD3D12Resource() const;
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUPointer() const;
+
+ private:
+ ComPtr<ID3D12Resource> mResource;
+ };
+}} // namespace dawn_native::d3d12
+
+#endif // DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_
\ No newline at end of file
diff --git a/src/dawn_native/d3d12/StagingBufferD3D12.cpp b/src/dawn_native/d3d12/StagingBufferD3D12.cpp
index 6b6adfa..cab3a18 100644
--- a/src/dawn_native/d3d12/StagingBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/StagingBufferD3D12.cpp
@@ -14,7 +14,7 @@
#include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
namespace dawn_native { namespace d3d12 {
@@ -36,12 +36,11 @@
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE;
- mUploadHeap = mDevice->GetResourceAllocator()->Allocate(
- D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor, D3D12_RESOURCE_STATE_GENERIC_READ);
+ DAWN_TRY_ASSIGN(mUploadHeap, mDevice->AllocateMemory(
+ D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor,
+ D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_FLAG_NONE));
- // TODO(bryan.bernhart@intel.com): Record the GPU pointer for generic non-upload usage.
-
- if (FAILED(mUploadHeap->Map(0, nullptr, &mMappedPointer))) {
+ if (FAILED(GetResource()->Map(0, nullptr, &mMappedPointer))) {
return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer.");
}
@@ -50,14 +49,14 @@
StagingBuffer::~StagingBuffer() {
// Invalidate the CPU virtual address & flush cache (if needed).
- mUploadHeap->Unmap(0, nullptr);
+ GetResource()->Unmap(0, nullptr);
mMappedPointer = nullptr;
- mDevice->GetResourceAllocator()->Release(mUploadHeap);
+ mDevice->DeallocateMemory(mUploadHeap);
}
ID3D12Resource* StagingBuffer::GetResource() const {
- return mUploadHeap.Get();
+ return ToBackend(mUploadHeap.GetResourceHeap())->GetD3D12Resource().Get();
}
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/StagingBufferD3D12.h b/src/dawn_native/d3d12/StagingBufferD3D12.h
index b689df4..633be53 100644
--- a/src/dawn_native/d3d12/StagingBufferD3D12.h
+++ b/src/dawn_native/d3d12/StagingBufferD3D12.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_STAGINGBUFFERD3D12_H_
#define DAWNNATIVE_STAGINGBUFFERD3D12_H_
+#include "dawn_native/ResourceMemoryAllocation.h"
#include "dawn_native/StagingBuffer.h"
#include "dawn_native/d3d12/d3d12_platform.h"
@@ -33,7 +34,7 @@
private:
Device* mDevice;
- ComPtr<ID3D12Resource> mUploadHeap;
+ ResourceMemoryAllocation mUploadHeap;
};
}} // namespace dawn_native::d3d12