• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Dawn Authors
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 
15 #include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
16 
17 #include "common/BitSetIterator.h"
18 #include "dawn_native/d3d12/BindGroupD3D12.h"
19 #include "dawn_native/d3d12/DeviceD3D12.h"
20 #include "dawn_native/d3d12/SamplerHeapCacheD3D12.h"
21 #include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
22 
23 namespace dawn_native { namespace d3d12 {
24     namespace {
WGPUBindingInfoToDescriptorRangeType(const BindingInfo & bindingInfo)25         D3D12_DESCRIPTOR_RANGE_TYPE WGPUBindingInfoToDescriptorRangeType(
26             const BindingInfo& bindingInfo) {
27             switch (bindingInfo.bindingType) {
28                 case BindingInfoType::Buffer:
29                     switch (bindingInfo.buffer.type) {
30                         case wgpu::BufferBindingType::Uniform:
31                             return D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
32                         case wgpu::BufferBindingType::Storage:
33                         case kInternalStorageBufferBinding:
34                             return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
35                         case wgpu::BufferBindingType::ReadOnlyStorage:
36                             return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
37                         case wgpu::BufferBindingType::Undefined:
38                             UNREACHABLE();
39                     }
40 
41                 case BindingInfoType::Sampler:
42                     return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
43 
44                 case BindingInfoType::Texture:
45                 case BindingInfoType::ExternalTexture:
46                     return D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
47 
48                 case BindingInfoType::StorageTexture:
49                     switch (bindingInfo.storageTexture.access) {
50                         case wgpu::StorageTextureAccess::WriteOnly:
51                             return D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
52                         case wgpu::StorageTextureAccess::Undefined:
53                             UNREACHABLE();
54                     }
55             }
56         }
57     }  // anonymous namespace
58 
59     // static
Create(Device * device,const BindGroupLayoutDescriptor * descriptor,PipelineCompatibilityToken pipelineCompatibilityToken)60     Ref<BindGroupLayout> BindGroupLayout::Create(
61         Device* device,
62         const BindGroupLayoutDescriptor* descriptor,
63         PipelineCompatibilityToken pipelineCompatibilityToken) {
64         return AcquireRef(new BindGroupLayout(device, descriptor, pipelineCompatibilityToken));
65     }
66 
BindGroupLayout(Device * device,const BindGroupLayoutDescriptor * descriptor,PipelineCompatibilityToken pipelineCompatibilityToken)67     BindGroupLayout::BindGroupLayout(Device* device,
68                                      const BindGroupLayoutDescriptor* descriptor,
69                                      PipelineCompatibilityToken pipelineCompatibilityToken)
70         : BindGroupLayoutBase(device, descriptor, pipelineCompatibilityToken),
71           mDescriptorHeapOffsets(GetBindingCount()),
72           mShaderRegisters(GetBindingCount()),
73           mCbvUavSrvDescriptorCount(0),
74           mSamplerDescriptorCount(0),
75           mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
76         for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) {
77             const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
78 
79             D3D12_DESCRIPTOR_RANGE_TYPE descriptorRangeType =
80                 WGPUBindingInfoToDescriptorRangeType(bindingInfo);
81 
82             // TODO(dawn:728) In the future, special handling will be needed for external textures
83             // here because they encompass multiple views.
84             mShaderRegisters[bindingIndex] = uint32_t(bindingInfo.binding);
85 
86             if (bindingIndex < GetDynamicBufferCount()) {
87                 continue;
88             }
89 
90             // For dynamic resources, Dawn uses root descriptor in D3D12 backend. So there is no
91             // need to allocate the descriptor from descriptor heap or create descriptor ranges.
92             ASSERT(!bindingInfo.buffer.hasDynamicOffset);
93 
94             // TODO(dawn:728) In the future, special handling will be needed for external textures
95             // here because they encompass multiple views.
96             mDescriptorHeapOffsets[bindingIndex] =
97                 descriptorRangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER
98                     ? mSamplerDescriptorCount++
99                     : mCbvUavSrvDescriptorCount++;
100 
101             D3D12_DESCRIPTOR_RANGE range;
102             range.RangeType = descriptorRangeType;
103             range.NumDescriptors = 1;
104             range.BaseShaderRegister = GetShaderRegister(bindingIndex);
105             range.RegisterSpace = kRegisterSpacePlaceholder;
106             range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
107 
108             std::vector<D3D12_DESCRIPTOR_RANGE>& descriptorRanges =
109                 descriptorRangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER
110                     ? mSamplerDescriptorRanges
111                     : mCbvUavSrvDescriptorRanges;
112 
113             // Try to join this range with the previous one, if the current range is a continuation
114             // of the previous. This is possible because the binding infos in the base type are
115             // sorted.
116             if (descriptorRanges.size() >= 2) {
117                 D3D12_DESCRIPTOR_RANGE& previous = descriptorRanges.back();
118                 if (previous.RangeType == range.RangeType &&
119                     previous.BaseShaderRegister + previous.NumDescriptors ==
120                         range.BaseShaderRegister) {
121                     previous.NumDescriptors += range.NumDescriptors;
122                     continue;
123                 }
124             }
125 
126             descriptorRanges.push_back(range);
127         }
128 
129         mViewAllocator = device->GetViewStagingDescriptorAllocator(GetCbvUavSrvDescriptorCount());
130         mSamplerAllocator =
131             device->GetSamplerStagingDescriptorAllocator(GetSamplerDescriptorCount());
132     }
133 
AllocateBindGroup(Device * device,const BindGroupDescriptor * descriptor)134     ResultOrError<Ref<BindGroup>> BindGroupLayout::AllocateBindGroup(
135         Device* device,
136         const BindGroupDescriptor* descriptor) {
137         uint32_t viewSizeIncrement = 0;
138         CPUDescriptorHeapAllocation viewAllocation;
139         if (GetCbvUavSrvDescriptorCount() > 0) {
140             DAWN_TRY_ASSIGN(viewAllocation, mViewAllocator->AllocateCPUDescriptors());
141             viewSizeIncrement = mViewAllocator->GetSizeIncrement();
142         }
143 
144         Ref<BindGroup> bindGroup = AcquireRef<BindGroup>(
145             mBindGroupAllocator.Allocate(device, descriptor, viewSizeIncrement, viewAllocation));
146 
147         if (GetSamplerDescriptorCount() > 0) {
148             Ref<SamplerHeapCacheEntry> samplerHeapCacheEntry;
149             DAWN_TRY_ASSIGN(samplerHeapCacheEntry, device->GetSamplerHeapCache()->GetOrCreate(
150                                                        bindGroup.Get(), mSamplerAllocator));
151             bindGroup->SetSamplerAllocationEntry(std::move(samplerHeapCacheEntry));
152         }
153 
154         return bindGroup;
155     }
156 
DeallocateBindGroup(BindGroup * bindGroup,CPUDescriptorHeapAllocation * viewAllocation)157     void BindGroupLayout::DeallocateBindGroup(BindGroup* bindGroup,
158                                               CPUDescriptorHeapAllocation* viewAllocation) {
159         if (viewAllocation->IsValid()) {
160             mViewAllocator->Deallocate(viewAllocation);
161         }
162 
163         mBindGroupAllocator.Deallocate(bindGroup);
164     }
165 
GetDescriptorHeapOffsets() const166     ityp::span<BindingIndex, const uint32_t> BindGroupLayout::GetDescriptorHeapOffsets() const {
167         return {mDescriptorHeapOffsets.data(), mDescriptorHeapOffsets.size()};
168     }
169 
GetShaderRegister(BindingIndex bindingIndex) const170     uint32_t BindGroupLayout::GetShaderRegister(BindingIndex bindingIndex) const {
171         return mShaderRegisters[bindingIndex];
172     }
173 
GetCbvUavSrvDescriptorCount() const174     uint32_t BindGroupLayout::GetCbvUavSrvDescriptorCount() const {
175         return mCbvUavSrvDescriptorCount;
176     }
177 
GetSamplerDescriptorCount() const178     uint32_t BindGroupLayout::GetSamplerDescriptorCount() const {
179         return mSamplerDescriptorCount;
180     }
181 
GetCbvUavSrvDescriptorRanges() const182     const std::vector<D3D12_DESCRIPTOR_RANGE>& BindGroupLayout::GetCbvUavSrvDescriptorRanges()
183         const {
184         return mCbvUavSrvDescriptorRanges;
185     }
186 
GetSamplerDescriptorRanges() const187     const std::vector<D3D12_DESCRIPTOR_RANGE>& BindGroupLayout::GetSamplerDescriptorRanges() const {
188         return mSamplerDescriptorRanges;
189     }
190 
191 }}  // namespace dawn_native::d3d12
192