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>
This commit is contained in:
Bryan Bernhart 2019-08-27 23:36:26 +00:00 committed by Commit Bot service account
parent f0b17d00b9
commit 7ffd2346f8
17 changed files with 442 additions and 31 deletions

View File

@ -204,6 +204,9 @@ source_set("libdawn_native_sources") {
"src/dawn_native/RenderPassEncoder.h",
"src/dawn_native/RenderPipeline.cpp",
"src/dawn_native/RenderPipeline.h",
"src/dawn_native/ResourceHeap.h",
"src/dawn_native/ResourceMemoryAllocation.cpp",
"src/dawn_native/ResourceMemoryAllocation.h",
"src/dawn_native/RingBuffer.cpp",
"src/dawn_native/RingBuffer.h",
"src/dawn_native/Sampler.cpp",
@ -239,6 +242,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/d3d12/CommandAllocatorManager.h",
"src/dawn_native/d3d12/CommandBufferD3D12.cpp",
"src/dawn_native/d3d12/CommandBufferD3D12.h",
"src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp",
"src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h",
"src/dawn_native/d3d12/ComputePipelineD3D12.cpp",
"src/dawn_native/d3d12/ComputePipelineD3D12.h",
"src/dawn_native/d3d12/D3D12Info.cpp",
@ -260,6 +265,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/d3d12/RenderPipelineD3D12.h",
"src/dawn_native/d3d12/ResourceAllocator.cpp",
"src/dawn_native/d3d12/ResourceAllocator.h",
"src/dawn_native/d3d12/ResourceHeapD3D12.cpp",
"src/dawn_native/d3d12/ResourceHeapD3D12.h",
"src/dawn_native/d3d12/SamplerD3D12.cpp",
"src/dawn_native/d3d12/SamplerD3D12.h",
"src/dawn_native/d3d12/ShaderModuleD3D12.cpp",

View File

@ -36,6 +36,7 @@ namespace dawn_native {
class RenderBundleEncoderBase;
class RenderPassEncoderBase;
class RenderPipelineBase;
class ResourceHeapBase;
class SamplerBase;
class ShaderModuleBase;
class StagingBufferBase;

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -73,6 +73,11 @@ namespace dawn_native {
using BackendType = typename BackendTraits::RenderPipelineType;
};
template <typename BackendTraits>
struct ToBackendTraits<ResourceHeapBase, BackendTraits> {
using BackendType = typename BackendTraits::ResourceHeapType;
};
template <typename BackendTraits>
struct ToBackendTraits<SamplerBase, BackendTraits> {
using BackendType = typename BackendTraits::SamplerType;

View File

@ -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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
}
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
}
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) {

View File

@ -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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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;

View File

@ -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

View File

@ -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_

View File

@ -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"
@ -116,6 +117,11 @@ namespace dawn_native { namespace d3d12 {
// 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 @@ namespace dawn_native { namespace d3d12 {
::CloseHandle(mFenceEvent);
}
mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
ASSERT(mUsedComObjectRefs.Empty());
ASSERT(mPendingCommands.commandList == nullptr);
}
@ -264,7 +272,9 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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

View File

@ -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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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;
};

View File

@ -29,6 +29,7 @@ namespace dawn_native { namespace d3d12 {
class PipelineLayout;
class Queue;
class RenderPipeline;
class ResourceHeap;
class Sampler;
class ShaderModule;
class StagingBuffer;
@ -47,6 +48,7 @@ namespace dawn_native { namespace d3d12 {
using PipelineLayoutType = PipelineLayout;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
using ResourceHeapType = ResourceHeap;
using SamplerType = Sampler;
using ShaderModuleType = ShaderModule;
using StagingBufferType = StagingBuffer;

View File

@ -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

View File

@ -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_

View File

@ -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 @@ namespace dawn_native { namespace d3d12 {
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 @@ namespace dawn_native { namespace d3d12 {
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

View File

@ -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 @@ namespace dawn_native { namespace d3d12 {
private:
Device* mDevice;
ComPtr<ID3D12Resource> mUploadHeap;
ResourceMemoryAllocation mUploadHeap;
};
}} // namespace dawn_native::d3d12