| // Copyright 2017 The NXT 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 "backend/d3d12/BindGroupLayoutD3D12.h" |
| |
| #include "common/BitSetIterator.h" |
| #include "backend/d3d12/D3D12Backend.h" |
| |
| namespace backend { |
| namespace d3d12 { |
| |
| BindGroupLayout::BindGroupLayout(Device* device, BindGroupLayoutBuilder* builder) |
| : BindGroupLayoutBase(builder), device(device), descriptorCounts {} { |
| |
| const auto& groupInfo = GetBindingInfo(); |
| |
| for (uint32_t binding : IterateBitSet(groupInfo.mask)) { |
| switch (groupInfo.types[binding]) { |
| case nxt::BindingType::UniformBuffer: |
| bindingOffsets[binding] = descriptorCounts[CBV]++; |
| break; |
| case nxt::BindingType::StorageBuffer: |
| bindingOffsets[binding] = descriptorCounts[UAV]++; |
| break; |
| case nxt::BindingType::SampledTexture: |
| bindingOffsets[binding] = descriptorCounts[SRV]++; |
| break; |
| case nxt::BindingType::Sampler: |
| bindingOffsets[binding] = descriptorCounts[Sampler]++; |
| break; |
| } |
| } |
| |
| auto SetDescriptorRange = [&](uint32_t index, uint32_t count, D3D12_DESCRIPTOR_RANGE_TYPE type) -> bool { |
| if (count == 0) { |
| return false; |
| } |
| |
| auto& range = ranges[index]; |
| range.RangeType = type; |
| range.NumDescriptors = count; |
| range.RegisterSpace = 0; |
| range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; |
| // These ranges will be copied and range.BaseShaderRegister will be set in d3d12::PipelineLayout to account for bind group register offsets |
| return true; |
| }; |
| |
| uint32_t rangeIndex = 0; |
| |
| // Ranges 0-2 contain the CBV, UAV, and SRV ranges, if they exist, tightly packed |
| // Range 3 contains the Sampler range, if there is one |
| if (SetDescriptorRange(rangeIndex, descriptorCounts[CBV], D3D12_DESCRIPTOR_RANGE_TYPE_CBV)) { |
| rangeIndex++; |
| } |
| if (SetDescriptorRange(rangeIndex, descriptorCounts[UAV], D3D12_DESCRIPTOR_RANGE_TYPE_UAV)) { |
| rangeIndex++; |
| } |
| if (SetDescriptorRange(rangeIndex, descriptorCounts[SRV], D3D12_DESCRIPTOR_RANGE_TYPE_SRV)) { |
| rangeIndex++; |
| } |
| SetDescriptorRange(Sampler, descriptorCounts[Sampler], D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); |
| |
| // descriptors ranges are offset by the offset + size of the previous range |
| std::array<uint32_t, DescriptorType::Count> descriptorOffsets; |
| descriptorOffsets[CBV] = 0; |
| descriptorOffsets[UAV] = descriptorOffsets[CBV] + descriptorCounts[CBV]; |
| descriptorOffsets[SRV] = descriptorOffsets[UAV] + descriptorCounts[UAV]; |
| descriptorOffsets[Sampler] = 0; // samplers are in a different heap |
| |
| for (uint32_t binding : IterateBitSet(groupInfo.mask)) { |
| switch (groupInfo.types[binding]) { |
| case nxt::BindingType::UniformBuffer: |
| bindingOffsets[binding] += descriptorOffsets[CBV]; |
| break; |
| case nxt::BindingType::StorageBuffer: |
| bindingOffsets[binding] += descriptorOffsets[UAV]; |
| break; |
| case nxt::BindingType::SampledTexture: |
| bindingOffsets[binding] += descriptorOffsets[SRV]; |
| break; |
| case nxt::BindingType::Sampler: |
| bindingOffsets[binding] += descriptorOffsets[Sampler]; |
| break; |
| } |
| } |
| } |
| |
| const std::array<uint32_t, kMaxBindingsPerGroup>& BindGroupLayout::GetBindingOffsets() const { |
| return bindingOffsets; |
| } |
| |
| uint32_t BindGroupLayout::GetCbvUavSrvDescriptorTableSize() const { |
| return ( |
| static_cast<uint32_t>(descriptorCounts[CBV] > 0) + |
| static_cast<uint32_t>(descriptorCounts[UAV] > 0) + |
| static_cast<uint32_t>(descriptorCounts[SRV] > 0) |
| ); |
| } |
| |
| uint32_t BindGroupLayout::GetSamplerDescriptorTableSize() const { |
| return descriptorCounts[Sampler] > 0; |
| } |
| |
| uint32_t BindGroupLayout::GetCbvUavSrvDescriptorCount() const { |
| return descriptorCounts[CBV] + descriptorCounts[UAV] + descriptorCounts[SRV]; |
| } |
| |
| uint32_t BindGroupLayout::GetSamplerDescriptorCount() const { |
| return descriptorCounts[Sampler]; |
| } |
| |
| const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetCbvUavSrvDescriptorRanges() const { |
| return ranges; |
| } |
| |
| const D3D12_DESCRIPTOR_RANGE* BindGroupLayout::GetSamplerDescriptorRanges() const { |
| return &ranges[Sampler]; |
| } |
| |
| } |
| } |