Corentin Wallez | 4a9ef4e | 2018-07-18 11:40:26 +0200 | [diff] [blame] | 1 | // Copyright 2017 The Dawn Authors |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 2 | // |
| 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 Wallez | d37523f | 2018-07-24 13:53:51 +0200 | [diff] [blame] | 15 | #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 16 | |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 17 | #include "common/BitSetIterator.h" |
Austin Eng | ae96f04 | 2020-03-13 23:34:40 +0000 | [diff] [blame] | 18 | #include "dawn_native/d3d12/BindGroupD3D12.h" |
Corentin Wallez | d37523f | 2018-07-24 13:53:51 +0200 | [diff] [blame] | 19 | #include "dawn_native/d3d12/DeviceD3D12.h" |
Bryan Bernhart | e25ee25 | 2020-05-18 23:25:31 +0000 | [diff] [blame] | 20 | #include "dawn_native/d3d12/SamplerHeapCacheD3D12.h" |
Bryan Bernhart | 4f86505 | 2020-04-10 18:43:22 +0000 | [diff] [blame] | 21 | #include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h" |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 22 | |
Corentin Wallez | 49a65d0 | 2018-07-24 16:45:45 +0200 | [diff] [blame] | 23 | namespace dawn_native { namespace d3d12 { |
Jiawei Shao | 1a56ce5 | 2020-03-16 10:53:36 +0000 | [diff] [blame] | 24 | namespace { |
Brandon Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 25 | 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 Shao | 1a56ce5 | 2020-03-16 10:53:36 +0000 | [diff] [blame] | 41 | return BindGroupLayout::DescriptorType::Sampler; |
Brandon Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 42 | |
| 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 Shao | 1a56ce5 | 2020-03-16 10:53:36 +0000 | [diff] [blame] | 55 | } |
| 56 | } |
| 57 | } // anonymous namespace |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 58 | |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 59 | // static |
| 60 | Ref<BindGroupLayout> BindGroupLayout::Create(Device* device, |
| 61 | const BindGroupLayoutDescriptor* descriptor) { |
| 62 | return AcquireRef(new BindGroupLayout(device, descriptor)); |
| 63 | } |
| 64 | |
Corentin Wallez | 36afbb6 | 2018-07-25 17:03:23 +0200 | [diff] [blame] | 65 | BindGroupLayout::BindGroupLayout(Device* device, const BindGroupLayoutDescriptor* descriptor) |
Austin Eng | ae96f04 | 2020-03-13 23:34:40 +0000 | [diff] [blame] | 66 | : BindGroupLayoutBase(device, descriptor), |
Austin Eng | b31f5e7 | 2020-07-14 22:20:35 +0000 | [diff] [blame] | 67 | mBindingOffsets(GetBindingCount()), |
Austin Eng | ae96f04 | 2020-03-13 23:34:40 +0000 | [diff] [blame] | 68 | mDescriptorCounts{}, |
| 69 | mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) { |
Austin Eng | 0847cb4 | 2020-03-26 17:22:14 +0000 | [diff] [blame] | 70 | for (BindingIndex bindingIndex = GetDynamicBufferCount(); bindingIndex < GetBindingCount(); |
| 71 | ++bindingIndex) { |
Austin Eng | 0650811 | 2020-03-27 18:54:03 +0000 | [diff] [blame] | 72 | const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex); |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 73 | |
Yan, Shaobo | 351ea23 | 2019-07-31 01:29:42 +0000 | [diff] [blame] | 74 | // For dynamic resources, Dawn uses root descriptor in D3D12 backend. |
Austin Eng | 0847cb4 | 2020-03-26 17:22:14 +0000 | [diff] [blame] | 75 | // 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 Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 78 | ASSERT(!bindingInfo.buffer.hasDynamicOffset); |
Yan, Shaobo | 351ea23 | 2019-07-31 01:29:42 +0000 | [diff] [blame] | 79 | |
Brandon Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 80 | DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo); |
Austin Eng | a80993d | 2020-03-20 21:56:30 +0000 | [diff] [blame] | 81 | mBindingOffsets[bindingIndex] = mDescriptorCounts[descriptorType]++; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 82 | } |
| 83 | |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 84 | auto SetDescriptorRange = [&](uint32_t index, uint32_t count, uint32_t* baseRegister, |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 85 | D3D12_DESCRIPTOR_RANGE_TYPE type) -> bool { |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 86 | if (count == 0) { |
| 87 | return false; |
| 88 | } |
| 89 | |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 90 | auto& range = mRanges[index]; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 91 | range.RangeType = type; |
| 92 | range.NumDescriptors = count; |
| 93 | range.RegisterSpace = 0; |
| 94 | range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 95 | range.BaseShaderRegister = *baseRegister; |
| 96 | *baseRegister += count; |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 97 | // These ranges will be copied and range.BaseShaderRegister will be set in |
| 98 | // d3d12::PipelineLayout to account for bind group register offsets |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 99 | return true; |
| 100 | }; |
| 101 | |
| 102 | uint32_t rangeIndex = 0; |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 103 | uint32_t baseRegister = 0; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 104 | |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 105 | std::array<uint32_t, DescriptorType::Count> descriptorOffsets; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 106 | // 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 White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 108 | if (SetDescriptorRange(rangeIndex, mDescriptorCounts[CBV], &baseRegister, |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 109 | D3D12_DESCRIPTOR_RANGE_TYPE_CBV)) { |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 110 | descriptorOffsets[CBV] = mRanges[rangeIndex++].BaseShaderRegister; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 111 | } |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 112 | if (SetDescriptorRange(rangeIndex, mDescriptorCounts[UAV], &baseRegister, |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 113 | D3D12_DESCRIPTOR_RANGE_TYPE_UAV)) { |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 114 | descriptorOffsets[UAV] = mRanges[rangeIndex++].BaseShaderRegister; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 115 | } |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 116 | if (SetDescriptorRange(rangeIndex, mDescriptorCounts[SRV], &baseRegister, |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 117 | D3D12_DESCRIPTOR_RANGE_TYPE_SRV)) { |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 118 | descriptorOffsets[SRV] = mRanges[rangeIndex++].BaseShaderRegister; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 119 | } |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 120 | uint32_t zero = 0; |
| 121 | SetDescriptorRange(Sampler, mDescriptorCounts[Sampler], &zero, |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 122 | D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); |
Stephen White | 4408b7f | 2018-11-01 13:59:19 +0000 | [diff] [blame] | 123 | descriptorOffsets[Sampler] = 0; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 124 | |
Austin Eng | 7a4685f | 2020-06-17 22:35:19 +0000 | [diff] [blame] | 125 | for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) { |
Austin Eng | 0650811 | 2020-03-27 18:54:03 +0000 | [diff] [blame] | 126 | const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex); |
Austin Eng | 0847cb4 | 2020-03-26 17:22:14 +0000 | [diff] [blame] | 127 | |
Brandon Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 128 | if (bindingInfo.bindingType == BindingInfoType::Buffer && |
| 129 | bindingInfo.buffer.hasDynamicOffset) { |
Yan, Shaobo | 351ea23 | 2019-07-31 01:29:42 +0000 | [diff] [blame] | 130 | // 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 Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 133 | mBindingOffsets[bindingIndex] = baseRegister++; |
Yan, Shaobo | 351ea23 | 2019-07-31 01:29:42 +0000 | [diff] [blame] | 134 | continue; |
| 135 | } |
| 136 | |
Jiawei Shao | 1a56ce5 | 2020-03-16 10:53:36 +0000 | [diff] [blame] | 137 | // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset. |
Brandon Jones | 3af532b | 2020-12-21 20:14:26 +0000 | [diff] [blame] | 138 | DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo); |
Austin Eng | a80993d | 2020-03-20 21:56:30 +0000 | [diff] [blame] | 139 | mBindingOffsets[bindingIndex] += descriptorOffsets[descriptorType]; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 140 | } |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 141 | |
Bryan Bernhart | 4f86505 | 2020-04-10 18:43:22 +0000 | [diff] [blame] | 142 | mViewAllocator = device->GetViewStagingDescriptorAllocator(GetCbvUavSrvDescriptorCount()); |
| 143 | mSamplerAllocator = |
| 144 | device->GetSamplerStagingDescriptorAllocator(GetSamplerDescriptorCount()); |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 145 | } |
| 146 | |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 147 | ResultOrError<Ref<BindGroup>> BindGroupLayout::AllocateBindGroup( |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 148 | 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 Bernhart | e25ee25 | 2020-05-18 23:25:31 +0000 | [diff] [blame] | 157 | Ref<BindGroup> bindGroup = AcquireRef<BindGroup>( |
| 158 | mBindGroupAllocator.Allocate(device, descriptor, viewSizeIncrement, viewAllocation)); |
| 159 | |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 160 | if (GetSamplerDescriptorCount() > 0) { |
Bryan Bernhart | e25ee25 | 2020-05-18 23:25:31 +0000 | [diff] [blame] | 161 | Ref<SamplerHeapCacheEntry> samplerHeapCacheEntry; |
| 162 | DAWN_TRY_ASSIGN(samplerHeapCacheEntry, device->GetSamplerHeapCache()->GetOrCreate( |
| 163 | bindGroup.Get(), mSamplerAllocator)); |
| 164 | bindGroup->SetSamplerAllocationEntry(std::move(samplerHeapCacheEntry)); |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 165 | } |
| 166 | |
Corentin Wallez | 50f9958 | 2021-03-31 18:36:32 +0000 | [diff] [blame] | 167 | return bindGroup; |
Austin Eng | ae96f04 | 2020-03-13 23:34:40 +0000 | [diff] [blame] | 168 | } |
| 169 | |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 170 | void BindGroupLayout::DeallocateBindGroup(BindGroup* bindGroup, |
Bryan Bernhart | e25ee25 | 2020-05-18 23:25:31 +0000 | [diff] [blame] | 171 | CPUDescriptorHeapAllocation* viewAllocation) { |
Bryan Bernhart | cb859a2 | 2020-04-06 22:07:42 +0000 | [diff] [blame] | 172 | if (viewAllocation->IsValid()) { |
| 173 | mViewAllocator->Deallocate(viewAllocation); |
| 174 | } |
| 175 | |
Austin Eng | ae96f04 | 2020-03-13 23:34:40 +0000 | [diff] [blame] | 176 | mBindGroupAllocator.Deallocate(bindGroup); |
| 177 | } |
| 178 | |
Austin Eng | b31f5e7 | 2020-07-14 22:20:35 +0000 | [diff] [blame] | 179 | ityp::span<BindingIndex, const uint32_t> BindGroupLayout::GetBindingOffsets() const { |
| 180 | return {mBindingOffsets.data(), mBindingOffsets.size()}; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | uint32_t BindGroupLayout::GetCbvUavSrvDescriptorTableSize() const { |
Corentin Wallez | 2d62a37 | 2017-11-24 14:04:22 -0500 | [diff] [blame] | 184 | 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 Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | uint32_t BindGroupLayout::GetSamplerDescriptorTableSize() const { |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 190 | return mDescriptorCounts[Sampler] > 0; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 191 | } |
| 192 | |
| 193 | uint32_t BindGroupLayout::GetCbvUavSrvDescriptorCount() const { |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 194 | return mDescriptorCounts[CBV] + mDescriptorCounts[UAV] + mDescriptorCounts[SRV]; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | uint32_t BindGroupLayout::GetSamplerDescriptorCount() const { |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 198 | return mDescriptorCounts[Sampler]; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetCbvUavSrvDescriptorRanges() const { |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 202 | return mRanges; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetSamplerDescriptorRanges() const { |
Corentin Wallez | e00385a | 2017-11-23 11:14:03 -0800 | [diff] [blame] | 206 | return &mRanges[Sampler]; |
Austin Eng | 036f76f | 2017-06-29 14:11:43 -0400 | [diff] [blame] | 207 | } |
| 208 | |
Corentin Wallez | 49a65d0 | 2018-07-24 16:45:45 +0200 | [diff] [blame] | 209 | }} // namespace dawn_native::d3d12 |