blob: c5151664ee015032f3f30638c1c1936029fd2ca6 [file] [log] [blame]
Corentin Wallez4a9ef4e2018-07-18 11:40:26 +02001// Copyright 2017 The Dawn Authors
Austin Eng036f76f2017-06-29 14:11:43 -04002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Corentin Wallezd37523f2018-07-24 13:53:51 +020015#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
Austin Eng036f76f2017-06-29 14:11:43 -040016
Corentin Wallez2d62a372017-11-24 14:04:22 -050017#include "common/BitSetIterator.h"
Austin Engae96f042020-03-13 23:34:40 +000018#include "dawn_native/d3d12/BindGroupD3D12.h"
Corentin Wallezd37523f2018-07-24 13:53:51 +020019#include "dawn_native/d3d12/DeviceD3D12.h"
Bryan Bernharte25ee252020-05-18 23:25:31 +000020#include "dawn_native/d3d12/SamplerHeapCacheD3D12.h"
Bryan Bernhart4f865052020-04-10 18:43:22 +000021#include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
Austin Eng036f76f2017-06-29 14:11:43 -040022
Corentin Wallez49a65d02018-07-24 16:45:45 +020023namespace dawn_native { namespace d3d12 {
Jiawei Shao1a56ce52020-03-16 10:53:36 +000024 namespace {
Brandon Jones3af532b2020-12-21 20:14:26 +000025 BindGroupLayout::DescriptorType WGPUBindingInfoToDescriptorType(
26 const BindingInfo& bindingInfo) {
27 switch (bindingInfo.bindingType) {
28 case BindingInfoType::Buffer:
29 switch (bindingInfo.buffer.type) {
30 case wgpu::BufferBindingType::Uniform:
31 return BindGroupLayout::DescriptorType::CBV;
32 case wgpu::BufferBindingType::Storage:
33 return BindGroupLayout::DescriptorType::UAV;
34 case wgpu::BufferBindingType::ReadOnlyStorage:
35 return BindGroupLayout::DescriptorType::SRV;
36 case wgpu::BufferBindingType::Undefined:
37 UNREACHABLE();
38 }
39
40 case BindingInfoType::Sampler:
Jiawei Shao1a56ce52020-03-16 10:53:36 +000041 return BindGroupLayout::DescriptorType::Sampler;
Brandon Jones3af532b2020-12-21 20:14:26 +000042
43 case BindingInfoType::Texture:
44 return BindGroupLayout::DescriptorType::SRV;
45
46 case BindingInfoType::StorageTexture:
47 switch (bindingInfo.storageTexture.access) {
48 case wgpu::StorageTextureAccess::ReadOnly:
49 return BindGroupLayout::DescriptorType::SRV;
50 case wgpu::StorageTextureAccess::WriteOnly:
51 return BindGroupLayout::DescriptorType::UAV;
52 case wgpu::StorageTextureAccess::Undefined:
53 UNREACHABLE();
54 }
Jiawei Shao1a56ce52020-03-16 10:53:36 +000055 }
56 }
57 } // anonymous namespace
Austin Eng036f76f2017-06-29 14:11:43 -040058
Corentin Wallez50f99582021-03-31 18:36:32 +000059 // static
60 Ref<BindGroupLayout> BindGroupLayout::Create(Device* device,
61 const BindGroupLayoutDescriptor* descriptor) {
62 return AcquireRef(new BindGroupLayout(device, descriptor));
63 }
64
Corentin Wallez36afbb62018-07-25 17:03:23 +020065 BindGroupLayout::BindGroupLayout(Device* device, const BindGroupLayoutDescriptor* descriptor)
Austin Engae96f042020-03-13 23:34:40 +000066 : BindGroupLayoutBase(device, descriptor),
Austin Engb31f5e72020-07-14 22:20:35 +000067 mBindingOffsets(GetBindingCount()),
Austin Engae96f042020-03-13 23:34:40 +000068 mDescriptorCounts{},
69 mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
Austin Eng0847cb42020-03-26 17:22:14 +000070 for (BindingIndex bindingIndex = GetDynamicBufferCount(); bindingIndex < GetBindingCount();
71 ++bindingIndex) {
Austin Eng06508112020-03-27 18:54:03 +000072 const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
Austin Eng036f76f2017-06-29 14:11:43 -040073
Yan, Shaobo351ea232019-07-31 01:29:42 +000074 // For dynamic resources, Dawn uses root descriptor in D3D12 backend.
Austin Eng0847cb42020-03-26 17:22:14 +000075 // So there is no need to allocate the descriptor from descriptor heap.
76 // This loop starts after the dynamic buffer indices to skip counting
77 // dynamic resources in calculating the size of the descriptor heap.
Brandon Jones3af532b2020-12-21 20:14:26 +000078 ASSERT(!bindingInfo.buffer.hasDynamicOffset);
Yan, Shaobo351ea232019-07-31 01:29:42 +000079
Brandon Jones3af532b2020-12-21 20:14:26 +000080 DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo);
Austin Enga80993d2020-03-20 21:56:30 +000081 mBindingOffsets[bindingIndex] = mDescriptorCounts[descriptorType]++;
Austin Eng036f76f2017-06-29 14:11:43 -040082 }
83
Stephen White4408b7f2018-11-01 13:59:19 +000084 auto SetDescriptorRange = [&](uint32_t index, uint32_t count, uint32_t* baseRegister,
Corentin Wallez2d62a372017-11-24 14:04:22 -050085 D3D12_DESCRIPTOR_RANGE_TYPE type) -> bool {
Austin Eng036f76f2017-06-29 14:11:43 -040086 if (count == 0) {
87 return false;
88 }
89
Corentin Walleze00385a2017-11-23 11:14:03 -080090 auto& range = mRanges[index];
Austin Eng036f76f2017-06-29 14:11:43 -040091 range.RangeType = type;
92 range.NumDescriptors = count;
93 range.RegisterSpace = 0;
94 range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
Stephen White4408b7f2018-11-01 13:59:19 +000095 range.BaseShaderRegister = *baseRegister;
96 *baseRegister += count;
Corentin Wallez2d62a372017-11-24 14:04:22 -050097 // These ranges will be copied and range.BaseShaderRegister will be set in
98 // d3d12::PipelineLayout to account for bind group register offsets
Austin Eng036f76f2017-06-29 14:11:43 -040099 return true;
100 };
101
102 uint32_t rangeIndex = 0;
Stephen White4408b7f2018-11-01 13:59:19 +0000103 uint32_t baseRegister = 0;
Austin Eng036f76f2017-06-29 14:11:43 -0400104
Stephen White4408b7f2018-11-01 13:59:19 +0000105 std::array<uint32_t, DescriptorType::Count> descriptorOffsets;
Austin Eng036f76f2017-06-29 14:11:43 -0400106 // Ranges 0-2 contain the CBV, UAV, and SRV ranges, if they exist, tightly packed
107 // Range 3 contains the Sampler range, if there is one
Stephen White4408b7f2018-11-01 13:59:19 +0000108 if (SetDescriptorRange(rangeIndex, mDescriptorCounts[CBV], &baseRegister,
Corentin Wallez2d62a372017-11-24 14:04:22 -0500109 D3D12_DESCRIPTOR_RANGE_TYPE_CBV)) {
Stephen White4408b7f2018-11-01 13:59:19 +0000110 descriptorOffsets[CBV] = mRanges[rangeIndex++].BaseShaderRegister;
Austin Eng036f76f2017-06-29 14:11:43 -0400111 }
Stephen White4408b7f2018-11-01 13:59:19 +0000112 if (SetDescriptorRange(rangeIndex, mDescriptorCounts[UAV], &baseRegister,
Corentin Wallez2d62a372017-11-24 14:04:22 -0500113 D3D12_DESCRIPTOR_RANGE_TYPE_UAV)) {
Stephen White4408b7f2018-11-01 13:59:19 +0000114 descriptorOffsets[UAV] = mRanges[rangeIndex++].BaseShaderRegister;
Austin Eng036f76f2017-06-29 14:11:43 -0400115 }
Stephen White4408b7f2018-11-01 13:59:19 +0000116 if (SetDescriptorRange(rangeIndex, mDescriptorCounts[SRV], &baseRegister,
Corentin Wallez2d62a372017-11-24 14:04:22 -0500117 D3D12_DESCRIPTOR_RANGE_TYPE_SRV)) {
Stephen White4408b7f2018-11-01 13:59:19 +0000118 descriptorOffsets[SRV] = mRanges[rangeIndex++].BaseShaderRegister;
Austin Eng036f76f2017-06-29 14:11:43 -0400119 }
Stephen White4408b7f2018-11-01 13:59:19 +0000120 uint32_t zero = 0;
121 SetDescriptorRange(Sampler, mDescriptorCounts[Sampler], &zero,
Corentin Wallez2d62a372017-11-24 14:04:22 -0500122 D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER);
Stephen White4408b7f2018-11-01 13:59:19 +0000123 descriptorOffsets[Sampler] = 0;
Austin Eng036f76f2017-06-29 14:11:43 -0400124
Austin Eng7a4685f2020-06-17 22:35:19 +0000125 for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) {
Austin Eng06508112020-03-27 18:54:03 +0000126 const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
Austin Eng0847cb42020-03-26 17:22:14 +0000127
Brandon Jones3af532b2020-12-21 20:14:26 +0000128 if (bindingInfo.bindingType == BindingInfoType::Buffer &&
129 bindingInfo.buffer.hasDynamicOffset) {
Yan, Shaobo351ea232019-07-31 01:29:42 +0000130 // Dawn is using values in mBindingOffsets to decide register number in HLSL.
131 // Root descriptor needs to set this value to set correct register number in
132 // generated HLSL shader.
Brandon Jones3af532b2020-12-21 20:14:26 +0000133 mBindingOffsets[bindingIndex] = baseRegister++;
Yan, Shaobo351ea232019-07-31 01:29:42 +0000134 continue;
135 }
136
Jiawei Shao1a56ce52020-03-16 10:53:36 +0000137 // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
Brandon Jones3af532b2020-12-21 20:14:26 +0000138 DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo);
Austin Enga80993d2020-03-20 21:56:30 +0000139 mBindingOffsets[bindingIndex] += descriptorOffsets[descriptorType];
Austin Eng036f76f2017-06-29 14:11:43 -0400140 }
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000141
Bryan Bernhart4f865052020-04-10 18:43:22 +0000142 mViewAllocator = device->GetViewStagingDescriptorAllocator(GetCbvUavSrvDescriptorCount());
143 mSamplerAllocator =
144 device->GetSamplerStagingDescriptorAllocator(GetSamplerDescriptorCount());
Austin Eng036f76f2017-06-29 14:11:43 -0400145 }
146
Corentin Wallez50f99582021-03-31 18:36:32 +0000147 ResultOrError<Ref<BindGroup>> BindGroupLayout::AllocateBindGroup(
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000148 Device* device,
149 const BindGroupDescriptor* descriptor) {
150 uint32_t viewSizeIncrement = 0;
151 CPUDescriptorHeapAllocation viewAllocation;
152 if (GetCbvUavSrvDescriptorCount() > 0) {
153 DAWN_TRY_ASSIGN(viewAllocation, mViewAllocator->AllocateCPUDescriptors());
154 viewSizeIncrement = mViewAllocator->GetSizeIncrement();
155 }
156
Bryan Bernharte25ee252020-05-18 23:25:31 +0000157 Ref<BindGroup> bindGroup = AcquireRef<BindGroup>(
158 mBindGroupAllocator.Allocate(device, descriptor, viewSizeIncrement, viewAllocation));
159
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000160 if (GetSamplerDescriptorCount() > 0) {
Bryan Bernharte25ee252020-05-18 23:25:31 +0000161 Ref<SamplerHeapCacheEntry> samplerHeapCacheEntry;
162 DAWN_TRY_ASSIGN(samplerHeapCacheEntry, device->GetSamplerHeapCache()->GetOrCreate(
163 bindGroup.Get(), mSamplerAllocator));
164 bindGroup->SetSamplerAllocationEntry(std::move(samplerHeapCacheEntry));
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000165 }
166
Corentin Wallez50f99582021-03-31 18:36:32 +0000167 return bindGroup;
Austin Engae96f042020-03-13 23:34:40 +0000168 }
169
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000170 void BindGroupLayout::DeallocateBindGroup(BindGroup* bindGroup,
Bryan Bernharte25ee252020-05-18 23:25:31 +0000171 CPUDescriptorHeapAllocation* viewAllocation) {
Bryan Bernhartcb859a22020-04-06 22:07:42 +0000172 if (viewAllocation->IsValid()) {
173 mViewAllocator->Deallocate(viewAllocation);
174 }
175
Austin Engae96f042020-03-13 23:34:40 +0000176 mBindGroupAllocator.Deallocate(bindGroup);
177 }
178
Austin Engb31f5e72020-07-14 22:20:35 +0000179 ityp::span<BindingIndex, const uint32_t> BindGroupLayout::GetBindingOffsets() const {
180 return {mBindingOffsets.data(), mBindingOffsets.size()};
Austin Eng036f76f2017-06-29 14:11:43 -0400181 }
182
183 uint32_t BindGroupLayout::GetCbvUavSrvDescriptorTableSize() const {
Corentin Wallez2d62a372017-11-24 14:04:22 -0500184 return (static_cast<uint32_t>(mDescriptorCounts[CBV] > 0) +
185 static_cast<uint32_t>(mDescriptorCounts[UAV] > 0) +
186 static_cast<uint32_t>(mDescriptorCounts[SRV] > 0));
Austin Eng036f76f2017-06-29 14:11:43 -0400187 }
188
189 uint32_t BindGroupLayout::GetSamplerDescriptorTableSize() const {
Corentin Walleze00385a2017-11-23 11:14:03 -0800190 return mDescriptorCounts[Sampler] > 0;
Austin Eng036f76f2017-06-29 14:11:43 -0400191 }
192
193 uint32_t BindGroupLayout::GetCbvUavSrvDescriptorCount() const {
Corentin Walleze00385a2017-11-23 11:14:03 -0800194 return mDescriptorCounts[CBV] + mDescriptorCounts[UAV] + mDescriptorCounts[SRV];
Austin Eng036f76f2017-06-29 14:11:43 -0400195 }
196
197 uint32_t BindGroupLayout::GetSamplerDescriptorCount() const {
Corentin Walleze00385a2017-11-23 11:14:03 -0800198 return mDescriptorCounts[Sampler];
Austin Eng036f76f2017-06-29 14:11:43 -0400199 }
200
201 const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetCbvUavSrvDescriptorRanges() const {
Corentin Walleze00385a2017-11-23 11:14:03 -0800202 return mRanges;
Austin Eng036f76f2017-06-29 14:11:43 -0400203 }
204
205 const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetSamplerDescriptorRanges() const {
Corentin Walleze00385a2017-11-23 11:14:03 -0800206 return &mRanges[Sampler];
Austin Eng036f76f2017-06-29 14:11:43 -0400207 }
208
Corentin Wallez49a65d02018-07-24 16:45:45 +0200209}} // namespace dawn_native::d3d12