summaryrefslogtreecommitdiff
path: root/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp')
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
new file mode 100644
index 00000000000..101ca4b190c
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
@@ -0,0 +1,206 @@
+// Copyright 2020 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/ShaderVisibleDescriptorAllocatorD3D12.h"
+#include "dawn_native/d3d12/D3D12Error.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ // Check that d3d heap type enum correctly mirrors the type index used by the static arrays.
+ static_assert(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == 0, "");
+ static_assert(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER == 1, "");
+
+ // Thresholds should be adjusted (lower == faster) to avoid tests taking too long to complete.
+ static constexpr const uint32_t kShaderVisibleSmallHeapSizes[] = {1024, 512};
+
+ uint32_t GetD3D12ShaderVisibleHeapSize(D3D12_DESCRIPTOR_HEAP_TYPE heapType, bool useSmallSize) {
+ if (useSmallSize) {
+ return kShaderVisibleSmallHeapSizes[heapType];
+ }
+
+ switch (heapType) {
+ case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
+ return D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1;
+ case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
+ return D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ D3D12_DESCRIPTOR_HEAP_FLAGS GetD3D12HeapFlags(D3D12_DESCRIPTOR_HEAP_TYPE heapType) {
+ switch (heapType) {
+ case D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV:
+ case D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER:
+ return D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ ShaderVisibleDescriptorAllocator::ShaderVisibleDescriptorAllocator(Device* device)
+ : mDevice(device),
+ mSizeIncrements{
+ device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
+ device->GetD3D12Device()->GetDescriptorHandleIncrementSize(
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
+ } {
+ }
+
+ MaybeError ShaderVisibleDescriptorAllocator::Initialize() {
+ ASSERT(mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap.Get() == nullptr);
+ mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heapType =
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+
+ ASSERT(mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER].heap.Get() == nullptr);
+ mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER].heapType =
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
+
+ DAWN_TRY(AllocateAndSwitchShaderVisibleHeaps());
+
+ return {};
+ }
+
+ MaybeError ShaderVisibleDescriptorAllocator::AllocateAndSwitchShaderVisibleHeaps() {
+ DAWN_TRY(AllocateGPUHeap(&mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]));
+ DAWN_TRY(AllocateGPUHeap(&mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]));
+
+ // Invalidate all bindgroup allocations on previously bound heaps by incrementing the heap
+ // serial. When a bindgroup attempts to re-populate, it will compare with its recorded
+ // heap serial.
+ mShaderVisibleHeapsSerial++;
+
+ return {};
+ }
+
+ ResultOrError<DescriptorHeapAllocation>
+ ShaderVisibleDescriptorAllocator::AllocateGPUDescriptors(uint32_t descriptorCount,
+ Serial pendingSerial,
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType) {
+ ASSERT(heapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
+ heapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ ASSERT(mShaderVisibleBuffers[heapType].heap != nullptr);
+ const uint64_t startOffset =
+ mShaderVisibleBuffers[heapType].allocator.Allocate(descriptorCount, pendingSerial);
+ if (startOffset == RingBufferAllocator::kInvalidOffset) {
+ return DescriptorHeapAllocation{}; // Invalid
+ }
+
+ ID3D12DescriptorHeap* descriptorHeap = mShaderVisibleBuffers[heapType].heap.Get();
+
+ D3D12_CPU_DESCRIPTOR_HANDLE baseCPUDescriptor =
+ descriptorHeap->GetCPUDescriptorHandleForHeapStart();
+ baseCPUDescriptor.ptr += mSizeIncrements[heapType] * startOffset;
+
+ D3D12_GPU_DESCRIPTOR_HANDLE baseGPUDescriptor =
+ descriptorHeap->GetGPUDescriptorHandleForHeapStart();
+ baseGPUDescriptor.ptr += mSizeIncrements[heapType] * startOffset;
+
+ return DescriptorHeapAllocation{mSizeIncrements[heapType], baseCPUDescriptor,
+ baseGPUDescriptor};
+ }
+
+ std::array<ID3D12DescriptorHeap*, 2> ShaderVisibleDescriptorAllocator::GetShaderVisibleHeaps()
+ const {
+ return {mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV].heap.Get(),
+ mShaderVisibleBuffers[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER].heap.Get()};
+ }
+
+ void ShaderVisibleDescriptorAllocator::Tick(uint64_t completedSerial) {
+ for (uint32_t i = 0; i < mShaderVisibleBuffers.size(); i++) {
+ ASSERT(mShaderVisibleBuffers[i].heap != nullptr);
+ mShaderVisibleBuffers[i].allocator.Deallocate(completedSerial);
+ }
+ }
+
+ // Creates a GPU descriptor heap that manages descriptors in a FIFO queue.
+ MaybeError ShaderVisibleDescriptorAllocator::AllocateGPUHeap(
+ ShaderVisibleBuffer* shaderVisibleBuffer) {
+ ComPtr<ID3D12DescriptorHeap> heap;
+ // Return the switched out heap to the pool and retrieve the oldest heap that is no longer
+ // used by GPU. This maintains a heap buffer to avoid frequently re-creating heaps for heavy
+ // users.
+ // TODO(dawn:256): Consider periodically triming to avoid OOM.
+ if (shaderVisibleBuffer->heap != nullptr) {
+ shaderVisibleBuffer->pool.push_back(
+ {mDevice->GetPendingCommandSerial(), std::move(shaderVisibleBuffer->heap)});
+ }
+
+ // Recycle existing heap if possible.
+ if (!shaderVisibleBuffer->pool.empty() &&
+ shaderVisibleBuffer->pool.front().heapSerial <= mDevice->GetCompletedCommandSerial()) {
+ heap = std::move(shaderVisibleBuffer->pool.front().heap);
+ shaderVisibleBuffer->pool.pop_front();
+ }
+
+ const D3D12_DESCRIPTOR_HEAP_TYPE heapType = shaderVisibleBuffer->heapType;
+
+ // TODO(bryan.bernhart@intel.com): Allocating to max heap size wastes memory
+ // should the developer not allocate any bindings for the heap type.
+ // Consider dynamically re-sizing GPU heaps.
+ const uint32_t descriptorCount = GetD3D12ShaderVisibleHeapSize(
+ heapType, mDevice->IsToggleEnabled(Toggle::UseD3D12SmallShaderVisibleHeapForTesting));
+
+ if (heap == nullptr) {
+ D3D12_DESCRIPTOR_HEAP_DESC heapDescriptor;
+ heapDescriptor.Type = heapType;
+ heapDescriptor.NumDescriptors = descriptorCount;
+ heapDescriptor.Flags = GetD3D12HeapFlags(heapType);
+ heapDescriptor.NodeMask = 0;
+ DAWN_TRY(CheckOutOfMemoryHRESULT(mDevice->GetD3D12Device()->CreateDescriptorHeap(
+ &heapDescriptor, IID_PPV_ARGS(&heap)),
+ "ID3D12Device::CreateDescriptorHeap"));
+ }
+
+ // Create a FIFO buffer from the recently created heap.
+ shaderVisibleBuffer->heap = std::move(heap);
+ shaderVisibleBuffer->allocator = RingBufferAllocator(descriptorCount);
+ return {};
+ }
+
+ Serial ShaderVisibleDescriptorAllocator::GetShaderVisibleHeapsSerial() const {
+ return mShaderVisibleHeapsSerial;
+ }
+
+ uint64_t ShaderVisibleDescriptorAllocator::GetShaderVisibleHeapSizeForTesting(
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType) const {
+ ASSERT(heapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
+ heapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ return mShaderVisibleBuffers[heapType].allocator.GetSize();
+ }
+
+ ComPtr<ID3D12DescriptorHeap> ShaderVisibleDescriptorAllocator::GetShaderVisibleHeapForTesting(
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType) const {
+ ASSERT(heapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
+ heapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ return mShaderVisibleBuffers[heapType].heap;
+ }
+
+ uint64_t ShaderVisibleDescriptorAllocator::GetShaderVisiblePoolSizeForTesting(
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType) const {
+ ASSERT(heapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
+ heapType == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+ return mShaderVisibleBuffers[heapType].pool.size();
+ }
+
+ bool ShaderVisibleDescriptorAllocator::IsAllocationStillValid(Serial lastUsageSerial,
+ Serial heapSerial) const {
+ // Consider valid if allocated for the pending submit and the shader visible heaps
+ // have not switched over.
+ return (lastUsageSerial > mDevice->GetCompletedCommandSerial() &&
+ heapSerial == mShaderVisibleHeapsSerial);
+ }
+}} // namespace dawn_native::d3d12 \ No newline at end of file