D3D12: Enable sub-allocation for RTV/DSV heaps.

Uses the staging descriptor allocator to enable
sub-allocation for RTV/DSVs.

This change also simplifies CPU descriptor heap
 management for render-passes:
- Allocating slot-by-slot removes extra attachment
 pass.
- No need for the slower direct allocation allocator.
- Move RP creation of view handles into RP builder.

BUG=dawn:155

Change-Id: I508492a2e56a897bf8c85f9a45cd13f62fa0a2ef
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/20042
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Bryan Bernhart 2020-04-22 23:57:30 +00:00 committed by Commit Bot service account
parent 96c4019214
commit 7434b2c67d
13 changed files with 130 additions and 325 deletions

View File

@ -301,8 +301,6 @@ source_set("dawn_native_sources") {
"d3d12/D3D12Info.h", "d3d12/D3D12Info.h",
"d3d12/DescriptorHeapAllocationD3D12.cpp", "d3d12/DescriptorHeapAllocationD3D12.cpp",
"d3d12/DescriptorHeapAllocationD3D12.h", "d3d12/DescriptorHeapAllocationD3D12.h",
"d3d12/DescriptorHeapAllocator.cpp",
"d3d12/DescriptorHeapAllocator.h",
"d3d12/DeviceD3D12.cpp", "d3d12/DeviceD3D12.cpp",
"d3d12/DeviceD3D12.h", "d3d12/DeviceD3D12.h",
"d3d12/Forward.h", "d3d12/Forward.h",

View File

@ -182,8 +182,6 @@ if (DAWN_ENABLE_D3D12)
"d3d12/D3D12Info.h" "d3d12/D3D12Info.h"
"d3d12/DescriptorHeapAllocationD3D12.cpp" "d3d12/DescriptorHeapAllocationD3D12.cpp"
"d3d12/DescriptorHeapAllocationD3D12.h" "d3d12/DescriptorHeapAllocationD3D12.h"
"d3d12/DescriptorHeapAllocator.cpp"
"d3d12/DescriptorHeapAllocator.h"
"d3d12/DeviceD3D12.cpp" "d3d12/DeviceD3D12.cpp"
"d3d12/DeviceD3D12.h" "d3d12/DeviceD3D12.h"
"d3d12/Forward.h" "d3d12/Forward.h"

View File

@ -24,7 +24,6 @@
#include "dawn_native/d3d12/BufferD3D12.h" #include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/ComputePipelineD3D12.h" #include "dawn_native/d3d12/ComputePipelineD3D12.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/PipelineLayoutD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h"
#include "dawn_native/d3d12/PlatformFunctions.h" #include "dawn_native/d3d12/PlatformFunctions.h"
@ -32,6 +31,7 @@
#include "dawn_native/d3d12/RenderPipelineD3D12.h" #include "dawn_native/d3d12/RenderPipelineD3D12.h"
#include "dawn_native/d3d12/SamplerD3D12.h" #include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.h" #include "dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h" #include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/TextureD3D12.h" #include "dawn_native/d3d12/TextureD3D12.h"
#include "dawn_native/d3d12/UtilsD3D12.h" #include "dawn_native/d3d12/UtilsD3D12.h"
@ -296,53 +296,6 @@ namespace dawn_native { namespace d3d12 {
}; };
namespace { namespace {
// TODO(jiawei.shao@intel.com): use hash map <RenderPass, OMSetRenderTargetArgs> as
// cache to avoid redundant RTV and DSV memory allocations.
ResultOrError<OMSetRenderTargetArgs> GetSubpassOMSetRenderTargetArgs(
BeginRenderPassCmd* renderPass,
Device* device) {
OMSetRenderTargetArgs args = {};
uint32_t rtvCount = static_cast<uint32_t>(
renderPass->attachmentState->GetColorAttachmentsMask().count());
DescriptorHeapAllocator* allocator = device->GetDescriptorHeapAllocator();
DescriptorHeapHandle rtvHeap;
DAWN_TRY_ASSIGN(rtvHeap,
allocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, rtvCount));
ASSERT(rtvHeap.Get() != nullptr);
ID3D12Device* d3dDevice = device->GetD3D12Device();
unsigned int rtvIndex = 0;
for (uint32_t i :
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
ASSERT(rtvIndex < rtvCount);
TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(rtvIndex);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor();
d3dDevice->CreateRenderTargetView(ToBackend(view->GetTexture())->GetD3D12Resource(),
&rtvDesc, rtvHandle);
args.RTVs[rtvIndex] = rtvHandle;
++rtvIndex;
}
args.numRTVs = rtvCount;
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
DescriptorHeapHandle dsvHeap;
DAWN_TRY_ASSIGN(dsvHeap,
allocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1));
ASSERT(dsvHeap.Get() != nullptr);
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = view->GetDSVDescriptor();
d3dDevice->CreateDepthStencilView(ToBackend(view->GetTexture())->GetD3D12Resource(),
&dsvDesc, dsvHandle);
args.dsv = dsvHandle;
}
return args;
}
class VertexBufferTracker { class VertexBufferTracker {
public: public:
void OnSetVertexBuffer(uint32_t slot, Buffer* buffer, uint64_t offset) { void OnSetVertexBuffer(uint32_t slot, Buffer* buffer, uint64_t offset) {
@ -839,13 +792,29 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
void CommandBuffer::SetupRenderPass(CommandRecordingContext* commandContext, MaybeError CommandBuffer::SetupRenderPass(CommandRecordingContext* commandContext,
BeginRenderPassCmd* renderPass, BeginRenderPassCmd* renderPass,
RenderPassBuilder* renderPassBuilder) { RenderPassBuilder* renderPassBuilder) {
Device* device = ToBackend(GetDevice());
for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) { for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
RenderPassColorAttachmentInfo& attachmentInfo = renderPass->colorAttachments[i]; RenderPassColorAttachmentInfo& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get()); TextureView* view = ToBackend(attachmentInfo.view.Get());
// Set view attachment.
CPUDescriptorHeapAllocation rtvAllocation;
DAWN_TRY_ASSIGN(
rtvAllocation,
device->GetRenderTargetViewAllocator()->AllocateTransientCPUDescriptors());
const D3D12_RENDER_TARGET_VIEW_DESC viewDesc = view->GetRTVDescriptor();
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor = rtvAllocation.GetBaseDescriptor();
device->GetD3D12Device()->CreateRenderTargetView(
ToBackend(view->GetTexture())->GetD3D12Resource(), &viewDesc, baseDescriptor);
renderPassBuilder->SetRenderTargetView(i, baseDescriptor);
// Set color load operation. // Set color load operation.
renderPassBuilder->SetRenderTargetBeginningAccess( renderPassBuilder->SetRenderTargetBeginningAccess(
i, attachmentInfo.loadOp, attachmentInfo.clearColor, view->GetD3D12Format()); i, attachmentInfo.loadOp, attachmentInfo.clearColor, view->GetD3D12Format());
@ -871,6 +840,20 @@ namespace dawn_native { namespace d3d12 {
renderPass->depthStencilAttachment; renderPass->depthStencilAttachment;
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view.Get()); TextureView* view = ToBackend(renderPass->depthStencilAttachment.view.Get());
// Set depth attachment.
CPUDescriptorHeapAllocation dsvAllocation;
DAWN_TRY_ASSIGN(
dsvAllocation,
device->GetDepthStencilViewAllocator()->AllocateTransientCPUDescriptors());
const D3D12_DEPTH_STENCIL_VIEW_DESC viewDesc = view->GetDSVDescriptor();
const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor = dsvAllocation.GetBaseDescriptor();
device->GetD3D12Device()->CreateDepthStencilView(
ToBackend(view->GetTexture())->GetD3D12Resource(), &viewDesc, baseDescriptor);
renderPassBuilder->SetDepthStencilView(baseDescriptor);
const bool hasDepth = view->GetTexture()->GetFormat().HasDepth(); const bool hasDepth = view->GetTexture()->GetFormat().HasDepth();
const bool hasStencil = view->GetTexture()->GetFormat().HasStencil(); const bool hasStencil = view->GetTexture()->GetFormat().HasStencil();
@ -894,6 +877,8 @@ namespace dawn_native { namespace d3d12 {
} else { } else {
renderPassBuilder->SetDepthStencilNoAccess(); renderPassBuilder->SetDepthStencilNoAccess();
} }
return {};
} }
void CommandBuffer::EmulateBeginRenderPass(CommandRecordingContext* commandContext, void CommandBuffer::EmulateBeginRenderPass(CommandRecordingContext* commandContext,
@ -958,17 +943,14 @@ namespace dawn_native { namespace d3d12 {
BeginRenderPassCmd* renderPass, BeginRenderPassCmd* renderPass,
const bool passHasUAV) { const bool passHasUAV) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
OMSetRenderTargetArgs args;
DAWN_TRY_ASSIGN(args, GetSubpassOMSetRenderTargetArgs(renderPass, device));
const bool useRenderPass = device->IsToggleEnabled(Toggle::UseD3D12RenderPass); const bool useRenderPass = device->IsToggleEnabled(Toggle::UseD3D12RenderPass);
// renderPassBuilder must be scoped to RecordRenderPass because any underlying // renderPassBuilder must be scoped to RecordRenderPass because any underlying
// D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS structs must remain // D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS structs must remain
// valid until after EndRenderPass() has been called. // valid until after EndRenderPass() has been called.
RenderPassBuilder renderPassBuilder(args, passHasUAV); RenderPassBuilder renderPassBuilder(passHasUAV);
SetupRenderPass(commandContext, renderPass, &renderPassBuilder); DAWN_TRY(SetupRenderPass(commandContext, renderPass, &renderPassBuilder));
// Use D3D12's native render pass API if it's available, otherwise emulate the // Use D3D12's native render pass API if it's available, otherwise emulate the
// beginning and ending access operations. // beginning and ending access operations.

View File

@ -19,9 +19,7 @@
#include "dawn_native/CommandAllocator.h" #include "dawn_native/CommandAllocator.h"
#include "dawn_native/CommandBuffer.h" #include "dawn_native/CommandBuffer.h"
#include "dawn_native/Error.h" #include "dawn_native/Error.h"
#include "dawn_native/d3d12/Forward.h" #include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/d3d12_platform.h"
#include <array> #include <array>
@ -31,12 +29,6 @@ namespace dawn_native {
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
struct OMSetRenderTargetArgs {
unsigned int numRTVs = 0;
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {};
D3D12_CPU_DESCRIPTOR_HANDLE dsv = {};
};
class BindGroupStateTracker; class BindGroupStateTracker;
class CommandRecordingContext; class CommandRecordingContext;
class Device; class Device;
@ -58,9 +50,9 @@ namespace dawn_native { namespace d3d12 {
BindGroupStateTracker* bindingTracker, BindGroupStateTracker* bindingTracker,
BeginRenderPassCmd* renderPass, BeginRenderPassCmd* renderPass,
bool passHasUAV); bool passHasUAV);
void SetupRenderPass(CommandRecordingContext* commandContext, MaybeError SetupRenderPass(CommandRecordingContext* commandContext,
BeginRenderPassCmd* renderPass, BeginRenderPassCmd* renderPass,
RenderPassBuilder* renderPassBuilder); RenderPassBuilder* renderPassBuilder);
void EmulateBeginRenderPass(CommandRecordingContext* commandContext, void EmulateBeginRenderPass(CommandRecordingContext* commandContext,
const RenderPassBuilder* renderPassBuilder) const; const RenderPassBuilder* renderPassBuilder) const;

View File

@ -1,134 +0,0 @@
// Copyright 2017 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/DescriptorHeapAllocator.h"
#include "common/Assert.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
namespace dawn_native { namespace d3d12 {
DescriptorHeapHandle::DescriptorHeapHandle()
: mDescriptorHeap(nullptr), mSizeIncrement(0), mOffset(0) {
}
DescriptorHeapHandle::DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap,
uint32_t sizeIncrement,
uint64_t offset)
: mDescriptorHeap(descriptorHeap), mSizeIncrement(sizeIncrement), mOffset(offset) {
}
ID3D12DescriptorHeap* DescriptorHeapHandle::Get() const {
return mDescriptorHeap.Get();
}
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetCPUHandle(uint32_t index) const {
ASSERT(mDescriptorHeap);
auto handle = mDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += mSizeIncrement * (index + mOffset);
return handle;
}
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeapHandle::GetGPUHandle(uint32_t index) const {
ASSERT(mDescriptorHeap);
auto handle = mDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
handle.ptr += mSizeIncrement * (index + mOffset);
return handle;
}
DescriptorHeapAllocator::DescriptorHeapAllocator(Device* device)
: mDevice(device),
mSizeIncrements{
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
D3D12_DESCRIPTOR_HEAP_TYPE_RTV),
device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV),
} {
}
ResultOrError<DescriptorHeapHandle> DescriptorHeapAllocator::Allocate(
D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count,
uint32_t allocationSize,
DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags) {
const Serial pendingSerial = mDevice->GetPendingCommandSerial();
uint64_t startOffset = (heapInfo->heap == nullptr)
? RingBufferAllocator::kInvalidOffset
: heapInfo->allocator.Allocate(count, pendingSerial);
if (startOffset != RingBufferAllocator::kInvalidOffset) {
return DescriptorHeapHandle{heapInfo->heap, mSizeIncrements[type], startOffset};
}
// If the pool has no more space, replace the pool with a new one of the specified size
D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor;
heapDescriptor.Type = type;
heapDescriptor.NumDescriptors = allocationSize;
heapDescriptor.Flags = flags;
heapDescriptor.NodeMask = 0;
ComPtr<ID3D12DescriptorHeap> heap;
DAWN_TRY(CheckHRESULT(
mDevice->GetD3D12Device()->CreateDescriptorHeap(&heapDescriptor, IID_PPV_ARGS(&heap)),
"ID3D12Device::CreateDescriptorHeap"));
mDevice->ReferenceUntilUnused(heap);
*heapInfo = {heap, RingBufferAllocator(allocationSize)};
startOffset = heapInfo->allocator.Allocate(count, pendingSerial);
ASSERT(startOffset != RingBufferAllocator::kInvalidOffset);
return DescriptorHeapHandle(heap, mSizeIncrements[type], startOffset);
}
ResultOrError<DescriptorHeapHandle> DescriptorHeapAllocator::AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count) {
return Allocate(type, count, count, &mCpuDescriptorHeapInfos[type],
D3D12_DESCRIPTOR_HEAP_FLAG_NONE);
}
ResultOrError<DescriptorHeapHandle> DescriptorHeapAllocator::AllocateGPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count) {
ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
unsigned int heapSize = (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
? D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1
: D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE);
return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type],
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
}
void DescriptorHeapAllocator::Deallocate(uint64_t lastCompletedSerial) {
for (uint32_t i = 0; i < mCpuDescriptorHeapInfos.size(); i++) {
if (mCpuDescriptorHeapInfos[i].heap != nullptr) {
mCpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial);
}
}
for (uint32_t i = 0; i < mGpuDescriptorHeapInfos.size(); i++) {
if (mGpuDescriptorHeapInfos[i].heap != nullptr) {
mGpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial);
}
}
}
}} // namespace dawn_native::d3d12

View File

@ -1,81 +0,0 @@
// Copyright 2017 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_DESCRIPTORHEAPALLOCATOR_H_
#define DAWNNATIVE_D3D12_DESCRIPTORHEAPALLOCATOR_H_
#include "dawn_native/d3d12/d3d12_platform.h"
#include <array>
#include <vector>
#include "common/SerialQueue.h"
#include "dawn_native/Error.h"
#include "dawn_native/RingBufferAllocator.h"
namespace dawn_native { namespace d3d12 {
class Device;
class DescriptorHeapHandle {
public:
DescriptorHeapHandle();
DescriptorHeapHandle(ComPtr<ID3D12DescriptorHeap> descriptorHeap,
uint32_t sizeIncrement,
uint64_t offset);
ID3D12DescriptorHeap* Get() const;
D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(uint32_t index) const;
D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(uint32_t index) const;
private:
ComPtr<ID3D12DescriptorHeap> mDescriptorHeap;
uint32_t mSizeIncrement;
uint64_t mOffset;
};
class DescriptorHeapAllocator {
public:
DescriptorHeapAllocator(Device* device);
ResultOrError<DescriptorHeapHandle> AllocateGPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count);
ResultOrError<DescriptorHeapHandle> AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count);
void Deallocate(uint64_t lastCompletedSerial);
private:
struct DescriptorHeapInfo {
ComPtr<ID3D12DescriptorHeap> heap;
RingBufferAllocator allocator;
};
ResultOrError<DescriptorHeapHandle> Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count,
uint32_t allocationSize,
DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags);
Device* mDevice;
std::array<uint32_t, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES> mSizeIncrements;
std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
mCpuDescriptorHeapInfos;
std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
mGpuDescriptorHeapInfos;
};
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_DESCRIPTORHEAPALLOCATOR_H_

View File

@ -26,7 +26,6 @@
#include "dawn_native/d3d12/CommandBufferD3D12.h" #include "dawn_native/d3d12/CommandBufferD3D12.h"
#include "dawn_native/d3d12/ComputePipelineD3D12.h" #include "dawn_native/d3d12/ComputePipelineD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/PipelineLayoutD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h"
#include "dawn_native/d3d12/PlatformFunctions.h" #include "dawn_native/d3d12/PlatformFunctions.h"
#include "dawn_native/d3d12/QueueD3D12.h" #include "dawn_native/d3d12/QueueD3D12.h"
@ -43,8 +42,9 @@
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
// TODO(dawn:155): Figure out this value. // TODO(dawn:155): Figure out these values.
static constexpr uint16_t kStagingDescriptorHeapSize = 1024; static constexpr uint16_t kShaderVisibleDescriptorHeapSize = 1024;
static constexpr uint8_t kAttachmentDescriptorHeapSize = 64;
// static // static
ResultOrError<Device*> Device::Create(Adapter* adapter, const DeviceDescriptor* descriptor) { ResultOrError<Device*> Device::Create(Adapter* adapter, const DeviceDescriptor* descriptor) {
@ -81,7 +81,6 @@ namespace dawn_native { namespace d3d12 {
// Initialize backend services // Initialize backend services
mCommandAllocatorManager = std::make_unique<CommandAllocatorManager>(this); mCommandAllocatorManager = std::make_unique<CommandAllocatorManager>(this);
mDescriptorHeapAllocator = std::make_unique<DescriptorHeapAllocator>(this);
mShaderVisibleDescriptorAllocator = mShaderVisibleDescriptorAllocator =
std::make_unique<ShaderVisibleDescriptorAllocator>(this); std::make_unique<ShaderVisibleDescriptorAllocator>(this);
@ -91,13 +90,20 @@ namespace dawn_native { namespace d3d12 {
for (uint32_t countIndex = 1; countIndex < kNumOfStagingDescriptorAllocators; for (uint32_t countIndex = 1; countIndex < kNumOfStagingDescriptorAllocators;
countIndex++) { countIndex++) {
mViewAllocators[countIndex] = std::make_unique<StagingDescriptorAllocator>( mViewAllocators[countIndex] = std::make_unique<StagingDescriptorAllocator>(
this, countIndex, kStagingDescriptorHeapSize, this, countIndex, kShaderVisibleDescriptorHeapSize,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
mSamplerAllocators[countIndex] = std::make_unique<StagingDescriptorAllocator>( mSamplerAllocators[countIndex] = std::make_unique<StagingDescriptorAllocator>(
this, countIndex, kStagingDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); this, countIndex, kShaderVisibleDescriptorHeapSize,
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
} }
mRenderTargetViewAllocator = std::make_unique<StagingDescriptorAllocator>(
this, 1, kAttachmentDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
mDepthStencilViewAllocator = std::make_unique<StagingDescriptorAllocator>(
this, 1, kAttachmentDescriptorHeapSize, D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
mMapRequestTracker = std::make_unique<MapRequestTracker>(this); mMapRequestTracker = std::make_unique<MapRequestTracker>(this);
mResidencyManager = std::make_unique<ResidencyManager>(this); mResidencyManager = std::make_unique<ResidencyManager>(this);
mResourceAllocatorManager = std::make_unique<ResourceAllocatorManager>(this); mResourceAllocatorManager = std::make_unique<ResourceAllocatorManager>(this);
@ -159,10 +165,6 @@ namespace dawn_native { namespace d3d12 {
return mDrawIndexedIndirectSignature; return mDrawIndexedIndirectSignature;
} }
DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() const {
return mDescriptorHeapAllocator.get();
}
ComPtr<IDXGIFactory4> Device::GetFactory() const { ComPtr<IDXGIFactory4> Device::GetFactory() const {
return ToBackend(GetAdapter())->GetBackend()->GetFactory(); return ToBackend(GetAdapter())->GetBackend()->GetFactory();
} }
@ -211,6 +213,8 @@ namespace dawn_native { namespace d3d12 {
mResourceAllocatorManager->Tick(mCompletedSerial); mResourceAllocatorManager->Tick(mCompletedSerial);
DAWN_TRY(mCommandAllocatorManager->Tick(mCompletedSerial)); DAWN_TRY(mCommandAllocatorManager->Tick(mCompletedSerial));
mShaderVisibleDescriptorAllocator->Tick(mCompletedSerial); mShaderVisibleDescriptorAllocator->Tick(mCompletedSerial);
mRenderTargetViewAllocator->Tick(mCompletedSerial);
mDepthStencilViewAllocator->Tick(mCompletedSerial);
mMapRequestTracker->Tick(mCompletedSerial); mMapRequestTracker->Tick(mCompletedSerial);
mUsedComObjectRefs.ClearUpTo(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
DAWN_TRY(ExecutePendingCommandContext()); DAWN_TRY(ExecutePendingCommandContext());
@ -482,4 +486,13 @@ namespace dawn_native { namespace d3d12 {
ASSERT(descriptorCount < kNumOfStagingDescriptorAllocators); ASSERT(descriptorCount < kNumOfStagingDescriptorAllocators);
return mSamplerAllocators[descriptorCount].get(); return mSamplerAllocators[descriptorCount].get();
} }
StagingDescriptorAllocator* Device::GetRenderTargetViewAllocator() const {
return mRenderTargetViewAllocator.get();
}
StagingDescriptorAllocator* Device::GetDepthStencilViewAllocator() const {
return mDepthStencilViewAllocator.get();
}
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -67,7 +67,6 @@ namespace dawn_native { namespace d3d12 {
ComPtr<ID3D12CommandSignature> GetDrawIndirectSignature() const; ComPtr<ID3D12CommandSignature> GetDrawIndirectSignature() const;
ComPtr<ID3D12CommandSignature> GetDrawIndexedIndirectSignature() const; ComPtr<ID3D12CommandSignature> GetDrawIndexedIndirectSignature() const;
DescriptorHeapAllocator* GetDescriptorHeapAllocator() const;
MapRequestTracker* GetMapRequestTracker() const; MapRequestTracker* GetMapRequestTracker() const;
CommandAllocatorManager* GetCommandAllocatorManager() const; CommandAllocatorManager* GetCommandAllocatorManager() const;
ResidencyManager* GetResidencyManager() const; ResidencyManager* GetResidencyManager() const;
@ -110,6 +109,10 @@ namespace dawn_native { namespace d3d12 {
StagingDescriptorAllocator* GetSamplerStagingDescriptorAllocator( StagingDescriptorAllocator* GetSamplerStagingDescriptorAllocator(
uint32_t descriptorCount) const; uint32_t descriptorCount) const;
StagingDescriptorAllocator* GetRenderTargetViewAllocator() const;
StagingDescriptorAllocator* GetDepthStencilViewAllocator() const;
TextureBase* WrapSharedHandle(const ExternalImageDescriptor* descriptor, TextureBase* WrapSharedHandle(const ExternalImageDescriptor* descriptor,
HANDLE sharedHandle, HANDLE sharedHandle,
uint64_t acquireMutexKey, uint64_t acquireMutexKey,
@ -173,7 +176,6 @@ namespace dawn_native { namespace d3d12 {
SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs; SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs;
std::unique_ptr<CommandAllocatorManager> mCommandAllocatorManager; std::unique_ptr<CommandAllocatorManager> mCommandAllocatorManager;
std::unique_ptr<DescriptorHeapAllocator> mDescriptorHeapAllocator;
std::unique_ptr<MapRequestTracker> mMapRequestTracker; std::unique_ptr<MapRequestTracker> mMapRequestTracker;
std::unique_ptr<ResourceAllocatorManager> mResourceAllocatorManager; std::unique_ptr<ResourceAllocatorManager> mResourceAllocatorManager;
std::unique_ptr<ResidencyManager> mResidencyManager; std::unique_ptr<ResidencyManager> mResidencyManager;
@ -187,6 +189,10 @@ namespace dawn_native { namespace d3d12 {
std::array<std::unique_ptr<StagingDescriptorAllocator>, kNumOfStagingDescriptorAllocators> std::array<std::unique_ptr<StagingDescriptorAllocator>, kNumOfStagingDescriptorAllocators>
mSamplerAllocators; mSamplerAllocators;
std::unique_ptr<StagingDescriptorAllocator> mRenderTargetViewAllocator;
std::unique_ptr<StagingDescriptorAllocator> mDepthStencilViewAllocator;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -102,19 +102,24 @@ namespace dawn_native { namespace d3d12 {
} }
} // anonymous namespace } // anonymous namespace
RenderPassBuilder::RenderPassBuilder(const OMSetRenderTargetArgs& args, bool hasUAV) RenderPassBuilder::RenderPassBuilder(bool hasUAV) {
: mColorAttachmentCount(args.numRTVs), mRenderTargetViews(args.RTVs.data()) {
for (uint32_t i = 0; i < mColorAttachmentCount; i++) {
mRenderPassRenderTargetDescriptors[i].cpuDescriptor = args.RTVs[i];
}
mRenderPassDepthStencilDesc.cpuDescriptor = args.dsv;
if (hasUAV) { if (hasUAV) {
mRenderPassFlags = D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; mRenderPassFlags = D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES;
} }
} }
void RenderPassBuilder::SetRenderTargetView(uint32_t attachmentIndex,
D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor) {
ASSERT(mColorAttachmentCount < kMaxColorAttachments);
mRenderTargetViews[attachmentIndex] = baseDescriptor;
mRenderPassRenderTargetDescriptors[attachmentIndex].cpuDescriptor = baseDescriptor;
mColorAttachmentCount++;
}
void RenderPassBuilder::SetDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor) {
mRenderPassDepthStencilDesc.cpuDescriptor = baseDescriptor;
}
uint32_t RenderPassBuilder::GetColorAttachmentCount() const { uint32_t RenderPassBuilder::GetColorAttachmentCount() const {
return mColorAttachmentCount; return mColorAttachmentCount;
} }
@ -138,7 +143,7 @@ namespace dawn_native { namespace d3d12 {
} }
const D3D12_CPU_DESCRIPTOR_HANDLE* RenderPassBuilder::GetRenderTargetViews() const { const D3D12_CPU_DESCRIPTOR_HANDLE* RenderPassBuilder::GetRenderTargetViews() const {
return mRenderTargetViews; return mRenderTargetViews.data();
} }
void RenderPassBuilder::SetRenderTargetBeginningAccess(uint32_t attachment, void RenderPassBuilder::SetRenderTargetBeginningAccess(uint32_t attachment,

View File

@ -25,8 +25,6 @@ namespace dawn_native { namespace d3d12 {
class TextureView; class TextureView;
struct OMSetRenderTargetArgs;
// RenderPassBuilder stores parameters related to render pass load and store operations. // RenderPassBuilder stores parameters related to render pass load and store operations.
// When the D3D12 render pass API is available, the needed descriptors can be fetched // When the D3D12 render pass API is available, the needed descriptors can be fetched
// directly from the RenderPassBuilder. When the D3D12 render pass API is not available, the // directly from the RenderPassBuilder. When the D3D12 render pass API is not available, the
@ -34,7 +32,7 @@ namespace dawn_native { namespace d3d12 {
// operations is extracted from the descriptors. // operations is extracted from the descriptors.
class RenderPassBuilder { class RenderPassBuilder {
public: public:
RenderPassBuilder(const OMSetRenderTargetArgs& args, bool hasUAV); RenderPassBuilder(bool hasUAV);
uint32_t GetColorAttachmentCount() const; uint32_t GetColorAttachmentCount() const;
@ -72,6 +70,10 @@ namespace dawn_native { namespace d3d12 {
DXGI_FORMAT format); DXGI_FORMAT format);
void SetStencilNoAccess(); void SetStencilNoAccess();
void SetRenderTargetView(uint32_t attachmentIndex,
D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor);
void SetDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor);
private: private:
uint32_t mColorAttachmentCount = 0; uint32_t mColorAttachmentCount = 0;
bool mHasDepth = false; bool mHasDepth = false;
@ -79,7 +81,7 @@ namespace dawn_native { namespace d3d12 {
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC mRenderPassDepthStencilDesc; D3D12_RENDER_PASS_DEPTH_STENCIL_DESC mRenderPassDepthStencilDesc;
std::array<D3D12_RENDER_PASS_RENDER_TARGET_DESC, kMaxColorAttachments> std::array<D3D12_RENDER_PASS_RENDER_TARGET_DESC, kMaxColorAttachments>
mRenderPassRenderTargetDescriptors; mRenderPassRenderTargetDescriptors;
const D3D12_CPU_DESCRIPTOR_HANDLE* mRenderTargetViews; std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> mRenderTargetViews;
std::array<D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS, std::array<D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS,
kMaxColorAttachments> kMaxColorAttachments>
mSubresourceParams; mSubresourceParams;

View File

@ -29,8 +29,6 @@ namespace dawn_native { namespace d3d12 {
mBlockSize(descriptorCount * mSizeIncrement), mBlockSize(descriptorCount * mSizeIncrement),
mHeapSize(RoundUp(heapSize, descriptorCount)), mHeapSize(RoundUp(heapSize, descriptorCount)),
mHeapType(heapType) { mHeapType(heapType) {
ASSERT(heapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
heapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
ASSERT(descriptorCount <= heapSize); ASSERT(descriptorCount <= heapSize);
} }
@ -98,6 +96,8 @@ namespace dawn_native { namespace d3d12 {
} }
void StagingDescriptorAllocator::Deallocate(CPUDescriptorHeapAllocation* allocation) { void StagingDescriptorAllocator::Deallocate(CPUDescriptorHeapAllocation* allocation) {
ASSERT(allocation->IsValid());
const uint32_t heapIndex = allocation->GetHeapIndex(); const uint32_t heapIndex = allocation->GetHeapIndex();
ASSERT(heapIndex < mPool.size()); ASSERT(heapIndex < mPool.size());
@ -132,4 +132,21 @@ namespace dawn_native { namespace d3d12 {
return ((mHeapSize * mSizeIncrement) / mBlockSize); return ((mHeapSize * mSizeIncrement) / mBlockSize);
} }
ResultOrError<CPUDescriptorHeapAllocation>
StagingDescriptorAllocator::AllocateTransientCPUDescriptors() {
CPUDescriptorHeapAllocation allocation;
DAWN_TRY_ASSIGN(allocation, AllocateCPUDescriptors());
mAllocationsToDelete.Enqueue(allocation, mDevice->GetPendingCommandSerial());
return allocation;
}
void StagingDescriptorAllocator::Tick(Serial completedSerial) {
for (CPUDescriptorHeapAllocation& allocation :
mAllocationsToDelete.IterateUpTo(completedSerial)) {
Deallocate(&allocation);
}
mAllocationsToDelete.ClearUpTo(completedSerial);
}
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -45,10 +45,15 @@ namespace dawn_native { namespace d3d12 {
ResultOrError<CPUDescriptorHeapAllocation> AllocateCPUDescriptors(); ResultOrError<CPUDescriptorHeapAllocation> AllocateCPUDescriptors();
// Will call Deallocate when the serial is passed.
ResultOrError<CPUDescriptorHeapAllocation> AllocateTransientCPUDescriptors();
void Deallocate(CPUDescriptorHeapAllocation* allocation); void Deallocate(CPUDescriptorHeapAllocation* allocation);
uint32_t GetSizeIncrement() const; uint32_t GetSizeIncrement() const;
void Tick(Serial completedSerial);
private: private:
using Index = uint16_t; using Index = uint16_t;
@ -71,6 +76,8 @@ namespace dawn_native { namespace d3d12 {
uint32_t mHeapSize; // Size of the heap (in number of descriptors). uint32_t mHeapSize; // Size of the heap (in number of descriptors).
D3D12_DESCRIPTOR_HEAP_TYPE mHeapType; D3D12_DESCRIPTOR_HEAP_TYPE mHeapType;
SerialQueue<CPUDescriptorHeapAllocation> mAllocationsToDelete;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -21,11 +21,11 @@
#include "dawn_native/d3d12/BufferD3D12.h" #include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/CommandRecordingContext.h" #include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h" #include "dawn_native/d3d12/HeapD3D12.h"
#include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h" #include "dawn_native/d3d12/ResourceAllocatorManagerD3D12.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h" #include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h" #include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/UtilsD3D12.h" #include "dawn_native/d3d12/UtilsD3D12.h"
@ -622,7 +622,6 @@ namespace dawn_native { namespace d3d12 {
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList(); ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1; uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f; float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;
@ -642,13 +641,14 @@ namespace dawn_native { namespace d3d12 {
continue; continue;
} }
DescriptorHeapHandle dsvHeap; CPUDescriptorHeapAllocation dsvHandle;
DAWN_TRY_ASSIGN(dsvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(dsvHandle, device->GetDepthStencilViewAllocator()
D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1)); ->AllocateTransientCPUDescriptors());
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0); const D3D12_CPU_DESCRIPTOR_HANDLE baseDescriptor =
dsvHandle.GetBaseDescriptor();
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(), device->GetD3D12Device()->CreateDepthStencilView(GetD3D12Resource(),
&dsvDesc, dsvHandle); &dsvDesc, baseDescriptor);
if (GetFormat().HasDepth()) { if (GetFormat().HasDepth()) {
clearFlags |= D3D12_CLEAR_FLAG_DEPTH; clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
@ -657,7 +657,7 @@ namespace dawn_native { namespace d3d12 {
clearFlags |= D3D12_CLEAR_FLAG_STENCIL; clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
} }
commandList->ClearDepthStencilView(dsvHandle, clearFlags, fClearColor, commandList->ClearDepthStencilView(baseDescriptor, clearFlags, fClearColor,
clearColor, 0, nullptr); clearColor, 0, nullptr);
} }
} }
@ -676,10 +676,10 @@ namespace dawn_native { namespace d3d12 {
continue; continue;
} }
DescriptorHeapHandle rtvHeap; CPUDescriptorHeapAllocation rtvHeap;
DAWN_TRY_ASSIGN(rtvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(rtvHeap, device->GetRenderTargetViewAllocator()
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1)); ->AllocateTransientCPUDescriptors());
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0); const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetBaseDescriptor();
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1); D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = GetRTVDescriptor(level, layer, 1);
device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(), device->GetD3D12Device()->CreateRenderTargetView(GetD3D12Resource(),