mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-26 05:25:53 +00:00
In a typical graphics application it is a common usage to update some uniforms once per draw, and such uniforms include the word positions, orientations, and so on. In the current state of WebGPU, this means that for each draw call we have to create a new bind group to set the right uniform values. Bind group creation is expected to be more expensive than recording draws because a memory allocation is required. The functionality of dynamic buffer offset is to reduce the number of bind groups that need to be created. The patch implements dynamic buffer offset on D3D backend using root descriptor. Bug=dawn:55 Change-Id: Ia713a4edb3c0ab8f3bba048d7813f343e9dee166 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9040 Commit-Queue: Shaobo Yan <shaobo.yan@intel.com> Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
135 lines
6.4 KiB
C++
135 lines
6.4 KiB
C++
// Copyright 2017 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/BindGroupD3D12.h"
|
|
#include "common/BitSetIterator.h"
|
|
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
|
|
#include "dawn_native/d3d12/BufferD3D12.h"
|
|
#include "dawn_native/d3d12/SamplerD3D12.h"
|
|
#include "dawn_native/d3d12/TextureD3D12.h"
|
|
|
|
#include "dawn_native/d3d12/DeviceD3D12.h"
|
|
|
|
namespace dawn_native { namespace d3d12 {
|
|
|
|
BindGroup::BindGroup(Device* device, const BindGroupDescriptor* descriptor)
|
|
: BindGroupBase(device, descriptor) {
|
|
}
|
|
|
|
void BindGroup::AllocateDescriptors(const DescriptorHeapHandle& cbvUavSrvHeapStart,
|
|
uint32_t* cbvUavSrvHeapOffset,
|
|
const DescriptorHeapHandle& samplerHeapStart,
|
|
uint32_t* samplerHeapOffset) {
|
|
const auto* bgl = ToBackend(GetLayout());
|
|
const auto& layout = bgl->GetBindingInfo();
|
|
|
|
// Save the offset to the start of the descriptor table in the heap
|
|
mCbvUavSrvHeapOffset = *cbvUavSrvHeapOffset;
|
|
mSamplerHeapOffset = *samplerHeapOffset;
|
|
|
|
const auto& bindingOffsets = bgl->GetBindingOffsets();
|
|
|
|
auto d3d12Device = ToBackend(GetDevice())->GetD3D12Device();
|
|
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
|
|
// It's not necessary to create descriptors in descriptor heap for dynamic resources.
|
|
// So skip allocating descriptors in descriptor heaps for dynamic buffers.
|
|
if (layout.dynamic[bindingIndex]) {
|
|
continue;
|
|
}
|
|
|
|
switch (layout.types[bindingIndex]) {
|
|
case dawn::BindingType::UniformBuffer: {
|
|
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
|
|
|
|
D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
|
|
// TODO(enga@google.com): investigate if this needs to be a constraint at the
|
|
// API level
|
|
desc.SizeInBytes = Align(binding.size, 256);
|
|
desc.BufferLocation = ToBackend(binding.buffer)->GetVA() + binding.offset;
|
|
|
|
d3d12Device->CreateConstantBufferView(
|
|
&desc, cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
|
|
bindingOffsets[bindingIndex]));
|
|
} break;
|
|
case dawn::BindingType::StorageBuffer: {
|
|
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
|
|
|
|
// Since SPIRV-Cross outputs HLSL shaders with RWByteAddressBuffer,
|
|
// we must use D3D12_BUFFER_UAV_FLAG_RAW when making the
|
|
// UNORDERED_ACCESS_VIEW_DESC. Using D3D12_BUFFER_UAV_FLAG_RAW requires
|
|
// that we use DXGI_FORMAT_R32_TYPELESS as the format of the view.
|
|
// DXGI_FORMAT_R32_TYPELESS requires that the element size be 4
|
|
// byte aligned. Since binding.size and binding.offset are in bytes,
|
|
// we need to divide by 4 to obtain the element size.
|
|
D3D12_UNORDERED_ACCESS_VIEW_DESC desc;
|
|
desc.Buffer.NumElements = binding.size / 4;
|
|
desc.Format = DXGI_FORMAT_R32_TYPELESS;
|
|
desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
|
|
desc.Buffer.FirstElement = binding.offset / 4;
|
|
desc.Buffer.StructureByteStride = 0;
|
|
desc.Buffer.CounterOffsetInBytes = 0;
|
|
desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
|
|
|
|
d3d12Device->CreateUnorderedAccessView(
|
|
ToBackend(binding.buffer)->GetD3D12Resource().Get(), nullptr, &desc,
|
|
cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
|
|
bindingOffsets[bindingIndex]));
|
|
} break;
|
|
case dawn::BindingType::SampledTexture: {
|
|
auto* view = ToBackend(GetBindingAsTextureView(bindingIndex));
|
|
auto& srv = view->GetSRVDescriptor();
|
|
d3d12Device->CreateShaderResourceView(
|
|
ToBackend(view->GetTexture())->GetD3D12Resource(), &srv,
|
|
cbvUavSrvHeapStart.GetCPUHandle(*cbvUavSrvHeapOffset +
|
|
bindingOffsets[bindingIndex]));
|
|
} break;
|
|
case dawn::BindingType::Sampler: {
|
|
auto* sampler = ToBackend(GetBindingAsSampler(bindingIndex));
|
|
auto& samplerDesc = sampler->GetSamplerDescriptor();
|
|
d3d12Device->CreateSampler(
|
|
&samplerDesc, samplerHeapStart.GetCPUHandle(*samplerHeapOffset +
|
|
bindingOffsets[bindingIndex]));
|
|
} break;
|
|
|
|
case dawn::BindingType::StorageTexture:
|
|
case dawn::BindingType::ReadonlyStorageBuffer:
|
|
UNREACHABLE();
|
|
break;
|
|
|
|
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
|
|
}
|
|
}
|
|
|
|
// Offset by the number of descriptors created
|
|
*cbvUavSrvHeapOffset += bgl->GetCbvUavSrvDescriptorCount();
|
|
*samplerHeapOffset += bgl->GetSamplerDescriptorCount();
|
|
}
|
|
|
|
uint32_t BindGroup::GetCbvUavSrvHeapOffset() const {
|
|
return mCbvUavSrvHeapOffset;
|
|
}
|
|
|
|
uint32_t BindGroup::GetSamplerHeapOffset() const {
|
|
return mSamplerHeapOffset;
|
|
}
|
|
|
|
bool BindGroup::TestAndSetCounted(uint64_t heapSerial, uint32_t indexInSubmit) {
|
|
bool isCounted = (mHeapSerial == heapSerial && mIndexInSubmit == indexInSubmit);
|
|
mHeapSerial = heapSerial;
|
|
mIndexInSubmit = indexInSubmit;
|
|
return isCounted;
|
|
}
|
|
|
|
}} // namespace dawn_native::d3d12
|