Convert LayoutBindingInfo to an array of BindingInfos

This makes accessing per-index data simpler, and now that dynamic
buffer bindings are packed at the front, the old IterateBitset on
the dynamic buffer binding mask can be replaced with a simple loop
over the beginning bindings.

Bug: dawn:354
Change-Id: I1adf371c3228690758f90ab1f0de88ad8d0f950d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/17681
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2020-03-26 17:22:14 +00:00 committed by Commit Bot service account
parent d5db214564
commit 0847cb4637
19 changed files with 221 additions and 234 deletions

View File

@ -64,10 +64,7 @@ namespace dawn_native {
MaybeError ValidateTextureBinding(const DeviceBase* device,
const BindGroupBinding& binding,
wgpu::TextureUsage requiredUsage,
bool multisampledBinding,
wgpu::TextureComponentType requiredComponentType,
wgpu::TextureViewDimension requiredDimension,
wgpu::TextureFormat requiredStorageTextureFormat) {
const BindGroupLayoutBase::BindingInfo& bindingInfo) {
if (binding.textureView == nullptr || binding.sampler != nullptr ||
binding.buffer != nullptr) {
return DAWN_VALIDATION_ERROR("expected texture binding");
@ -80,18 +77,18 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("texture binding usage mismatch");
}
if (texture->IsMultisampledTexture() != multisampledBinding) {
if (texture->IsMultisampledTexture() != bindingInfo.multisampled) {
return DAWN_VALIDATION_ERROR("texture multisampling mismatch");
}
switch (requiredUsage) {
case wgpu::TextureUsage::Sampled: {
if (!texture->GetFormat().HasComponentType(requiredComponentType)) {
if (!texture->GetFormat().HasComponentType(bindingInfo.textureComponentType)) {
return DAWN_VALIDATION_ERROR("texture component type usage mismatch");
}
} break;
case wgpu::TextureUsage::Storage: {
if (texture->GetFormat().format != requiredStorageTextureFormat) {
if (texture->GetFormat().format != bindingInfo.storageTextureFormat) {
return DAWN_VALIDATION_ERROR("storage texture format mismatch");
}
} break;
@ -100,7 +97,7 @@ namespace dawn_native {
break;
}
if (binding.textureView->GetDimension() != requiredDimension) {
if (binding.textureView->GetDimension() != bindingInfo.textureDimension) {
return DAWN_VALIDATION_ERROR("texture view dimension mismatch");
}
@ -127,16 +124,12 @@ namespace dawn_native {
}
DAWN_TRY(device->ValidateObject(descriptor->layout));
const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo =
descriptor->layout->GetBindingInfo();
const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap();
if (descriptor->bindingCount != bindingMap.size()) {
if (descriptor->bindingCount != descriptor->layout->GetBindingCount()) {
return DAWN_VALIDATION_ERROR("numBindings mismatch");
}
const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap();
std::bitset<kMaxBindingsPerGroup> bindingsSet;
for (uint32_t i = 0; i < descriptor->bindingCount; ++i) {
const BindGroupBinding& binding = descriptor->bindings[i];
@ -146,15 +139,18 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("setting non-existent binding");
}
BindingIndex bindingIndex = it->second;
ASSERT(bindingIndex < layoutInfo.bindingCount);
ASSERT(bindingIndex < descriptor->layout->GetBindingCount());
if (bindingsSet[bindingIndex]) {
return DAWN_VALIDATION_ERROR("binding set twice");
}
bindingsSet.set(bindingIndex);
const BindGroupLayoutBase::BindingInfo& bindingInfo =
descriptor->layout->GetBindingInfo(bindingIndex);
// Perform binding-type specific validation.
switch (layoutInfo.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
DAWN_TRY(ValidateBufferBinding(device, binding, wgpu::BufferUsage::Uniform));
break;
@ -163,12 +159,8 @@ namespace dawn_native {
DAWN_TRY(ValidateBufferBinding(device, binding, wgpu::BufferUsage::Storage));
break;
case wgpu::BindingType::SampledTexture:
DAWN_TRY(
ValidateTextureBinding(device, binding, wgpu::TextureUsage::Sampled,
layoutInfo.multisampled[bindingIndex],
layoutInfo.textureComponentTypes[bindingIndex],
layoutInfo.textureDimensions[bindingIndex],
layoutInfo.storageTextureFormats[bindingIndex]));
DAWN_TRY(ValidateTextureBinding(device, binding, wgpu::TextureUsage::Sampled,
bindingInfo));
break;
case wgpu::BindingType::Sampler:
DAWN_TRY(ValidateSamplerBinding(device, binding));
@ -177,12 +169,8 @@ namespace dawn_native {
// write-only storage textures.
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
DAWN_TRY(
ValidateTextureBinding(device, binding, wgpu::TextureUsage::Storage,
layoutInfo.multisampled[bindingIndex],
layoutInfo.textureComponentTypes[bindingIndex],
layoutInfo.textureDimensions[bindingIndex],
layoutInfo.storageTextureFormats[bindingIndex]));
DAWN_TRY(ValidateTextureBinding(device, binding, wgpu::TextureUsage::Storage,
bindingInfo));
break;
case wgpu::BindingType::StorageTexture:
UNREACHABLE();
@ -274,9 +262,9 @@ namespace dawn_native {
BufferBinding BindGroupBase::GetBindingAsBufferBinding(BindingIndex bindingIndex) {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo().types[bindingIndex] == wgpu::BindingType::UniformBuffer ||
mLayout->GetBindingInfo().types[bindingIndex] == wgpu::BindingType::StorageBuffer ||
mLayout->GetBindingInfo().types[bindingIndex] ==
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::UniformBuffer ||
mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::StorageBuffer ||
mLayout->GetBindingInfo(bindingIndex).type ==
wgpu::BindingType::ReadonlyStorageBuffer);
BufferBase* buffer = static_cast<BufferBase*>(mBindingData.bindings[bindingIndex].Get());
return {buffer, mBindingData.bufferData[bindingIndex].offset,
@ -286,14 +274,14 @@ namespace dawn_native {
SamplerBase* BindGroupBase::GetBindingAsSampler(BindingIndex bindingIndex) {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo().types[bindingIndex] == wgpu::BindingType::Sampler);
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::Sampler);
return static_cast<SamplerBase*>(mBindingData.bindings[bindingIndex].Get());
}
TextureViewBase* BindGroupBase::GetBindingAsTextureView(BindingIndex bindingIndex) {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo().types[bindingIndex] == wgpu::BindingType::SampledTexture);
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::SampledTexture);
return static_cast<TextureViewBase*>(mBindingData.bindings[bindingIndex].Get());
}

View File

@ -38,16 +38,18 @@ namespace dawn_native {
mBuffersNeedingBarrier[index] = {};
const BindGroupLayoutBase* layout = bindGroup->GetLayout();
const BindGroupLayoutBase::LayoutBindingInfo& info = layout->GetBindingInfo();
for (BindingIndex bindingIndex = 0; bindingIndex < info.bindingCount;
for (BindingIndex bindingIndex = 0; bindingIndex < layout->GetBindingCount();
++bindingIndex) {
if ((info.visibilities[bindingIndex] & wgpu::ShaderStage::Compute) == 0) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
layout->GetBindingInfo(bindingIndex);
if ((bindingInfo.visibility & wgpu::ShaderStage::Compute) == 0) {
continue;
}
mBindingTypes[index][bindingIndex] = info.types[bindingIndex];
switch (info.types[bindingIndex]) {
mBindingTypes[index][bindingIndex] = bindingInfo.type;
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::Sampler:

View File

@ -167,39 +167,25 @@ namespace dawn_native {
}
return {};
} // namespace dawn_native
}
namespace {
size_t HashBindingInfo(const BindGroupLayoutBase::LayoutBindingInfo& info) {
size_t hash = 0;
HashCombine(&hash, info.hasDynamicOffset, info.multisampled);
for (BindingIndex i = 0; i < info.bindingCount; ++i) {
HashCombine(&hash, info.visibilities[i], info.types[i],
info.textureComponentTypes[i], info.textureDimensions[i],
info.storageTextureFormats[i]);
}
return hash;
void HashCombineBindingInfo(size_t* hash, const BindGroupLayoutBase::BindingInfo& info) {
HashCombine(hash, info.hasDynamicOffset, info.multisampled, info.visibility, info.type,
info.textureComponentType, info.textureDimension,
info.storageTextureFormat);
}
bool operator==(const BindGroupLayoutBase::LayoutBindingInfo& a,
const BindGroupLayoutBase::LayoutBindingInfo& b) {
if (a.bindingCount != b.bindingCount || a.hasDynamicOffset != b.hasDynamicOffset ||
a.multisampled != b.multisampled) {
return false;
}
for (BindingIndex i = 0; i < a.bindingCount; ++i) {
if ((a.visibilities[i] != b.visibilities[i]) || (a.types[i] != b.types[i]) ||
(a.textureComponentTypes[i] != b.textureComponentTypes[i]) ||
(a.textureDimensions[i] != b.textureDimensions[i]) ||
(a.storageTextureFormats[i] != b.storageTextureFormats[i])) {
return false;
}
}
return true;
bool operator!=(const BindGroupLayoutBase::BindingInfo& a,
const BindGroupLayoutBase::BindingInfo& b) {
return a.hasDynamicOffset != b.hasDynamicOffset || //
a.multisampled != b.multisampled || //
a.visibility != b.visibility || //
a.type != b.type || //
a.textureComponentType != b.textureComponentType || //
a.textureDimension != b.textureDimension || //
a.storageTextureFormat != b.storageTextureFormat;
}
bool SortBindingsCompare(const BindGroupLayoutBinding& a, const BindGroupLayoutBinding& b) {
@ -233,7 +219,8 @@ namespace dawn_native {
// This is a utility function to help ASSERT that the BGL-binding comparator places buffers
// first.
bool CheckBufferBindingsFirst(const BindGroupLayoutBinding* bindings, size_t count) {
bool CheckBufferBindingsFirst(const BindGroupLayoutBase::BindingInfo* bindings,
BindingIndex count) {
ASSERT(count <= kMaxBindingsPerGroup);
BindingIndex lastBufferIndex = 0;
@ -269,21 +256,18 @@ namespace dawn_native {
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device,
const BindGroupLayoutDescriptor* descriptor)
: CachedObject(device) {
mBindingInfo.bindingCount = descriptor->bindingCount;
: CachedObject(device), mBindingCount(descriptor->bindingCount) {
std::vector<BindGroupLayoutBinding> sortedBindings(
descriptor->bindings, descriptor->bindings + descriptor->bindingCount);
std::sort(sortedBindings.begin(), sortedBindings.end(), SortBindingsCompare);
ASSERT(CheckBufferBindingsFirst(sortedBindings.data(), sortedBindings.size()));
for (BindingIndex i = 0; i < mBindingInfo.bindingCount; ++i) {
for (BindingIndex i = 0; i < mBindingCount; ++i) {
const BindGroupLayoutBinding& binding = sortedBindings[i];
mBindingInfo.types[i] = binding.type;
mBindingInfo.visibilities[i] = binding.visibility;
mBindingInfo.textureComponentTypes[i] = binding.textureComponentType;
mBindingInfo.storageTextureFormats[i] = binding.storageTextureFormat;
mBindingInfo[i].type = binding.type;
mBindingInfo[i].visibility = binding.visibility;
mBindingInfo[i].textureComponentType = binding.textureComponentType;
mBindingInfo[i].storageTextureFormat = binding.storageTextureFormat;
switch (binding.type) {
case wgpu::BindingType::UniformBuffer:
@ -298,13 +282,14 @@ namespace dawn_native {
}
if (binding.textureDimension == wgpu::TextureViewDimension::Undefined) {
mBindingInfo.textureDimensions[i] = wgpu::TextureViewDimension::e2D;
mBindingInfo[i].textureDimension = wgpu::TextureViewDimension::e2D;
} else {
mBindingInfo.textureDimensions[i] = binding.textureDimension;
mBindingInfo[i].textureDimension = binding.textureDimension;
}
mBindingInfo[i].multisampled = binding.multisampled;
mBindingInfo[i].hasDynamicOffset = binding.hasDynamicOffset;
if (binding.hasDynamicOffset) {
mBindingInfo.hasDynamicOffset.set(i);
switch (binding.type) {
case wgpu::BindingType::UniformBuffer:
++mDynamicUniformBufferCount;
@ -322,11 +307,11 @@ namespace dawn_native {
break;
}
}
mBindingInfo.multisampled.set(i, binding.multisampled);
const auto& it = mBindingMap.emplace(BindingNumber(binding.binding), i);
ASSERT(it.second);
}
ASSERT(CheckBufferBindingsFirst(mBindingInfo.data(), mBindingCount));
}
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
@ -345,11 +330,6 @@ namespace dawn_native {
return new BindGroupLayoutBase(device, ObjectBase::kError);
}
const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBase::GetBindingInfo() const {
ASSERT(!IsError());
return mBindingInfo;
}
const BindGroupLayoutBase::BindingMap& BindGroupLayoutBase::GetBindingMap() const {
ASSERT(!IsError());
return mBindingMap;
@ -363,22 +343,31 @@ namespace dawn_native {
}
size_t BindGroupLayoutBase::HashFunc::operator()(const BindGroupLayoutBase* bgl) const {
size_t hash = HashBindingInfo(bgl->mBindingInfo);
size_t hash = 0;
// std::map is sorted by key, so two BGLs constructed in different orders
// will still hash the same.
for (const auto& it : bgl->mBindingMap) {
HashCombine(&hash, it.first, it.second);
HashCombineBindingInfo(&hash, bgl->mBindingInfo[it.second]);
}
return hash;
}
bool BindGroupLayoutBase::EqualityFunc::operator()(const BindGroupLayoutBase* a,
const BindGroupLayoutBase* b) const {
return a->mBindingInfo == b->mBindingInfo && a->mBindingMap == b->mBindingMap;
if (a->GetBindingCount() != b->GetBindingCount()) {
return false;
}
for (BindingIndex i = 0; i < a->GetBindingCount(); ++i) {
if (a->mBindingInfo[i] != b->mBindingInfo[i]) {
return false;
}
}
return a->mBindingMap == b->mBindingMap;
}
BindingIndex BindGroupLayoutBase::GetBindingCount() const {
return mBindingInfo.bindingCount;
return mBindingCount;
}
BindingIndex BindGroupLayoutBase::GetDynamicBufferCount() const {
@ -398,7 +387,7 @@ namespace dawn_native {
// | --- offsets + sizes -------------| --------------- Ref<ObjectBase> ----------|
size_t objectPointerStart = mBufferCount * sizeof(BufferBindingData);
ASSERT(IsAligned(objectPointerStart, alignof(Ref<ObjectBase>)));
return objectPointerStart + mBindingInfo.bindingCount * sizeof(Ref<ObjectBase>);
return objectPointerStart + mBindingCount * sizeof(Ref<ObjectBase>);
}
BindGroupLayoutBase::BindingDataPointers BindGroupLayoutBase::ComputeBindingDataPointers(

View File

@ -51,22 +51,24 @@ namespace dawn_native {
~BindGroupLayoutBase() override;
static BindGroupLayoutBase* MakeError(DeviceBase* device);
struct LayoutBindingInfo {
std::array<wgpu::ShaderStage, kMaxBindingsPerGroup> visibilities;
std::array<wgpu::BindingType, kMaxBindingsPerGroup> types;
std::array<wgpu::TextureComponentType, kMaxBindingsPerGroup> textureComponentTypes;
std::array<wgpu::TextureViewDimension, kMaxBindingsPerGroup> textureDimensions;
std::array<wgpu::TextureFormat, kMaxBindingsPerGroup> storageTextureFormats;
std::bitset<kMaxBindingsPerGroup> hasDynamicOffset;
std::bitset<kMaxBindingsPerGroup> multisampled;
BindingIndex bindingCount;
struct BindingInfo {
wgpu::ShaderStage visibility;
wgpu::BindingType type;
wgpu::TextureComponentType textureComponentType;
wgpu::TextureViewDimension textureDimension;
wgpu::TextureFormat storageTextureFormat;
bool hasDynamicOffset;
bool multisampled;
};
// A map from the BindingNumber to its packed BindingIndex.
using BindingMap = std::map<BindingNumber, BindingIndex>;
const LayoutBindingInfo& GetBindingInfo() const;
const BindingInfo& GetBindingInfo(BindingIndex bindingIndex) const {
ASSERT(!IsError());
ASSERT(bindingIndex < kMaxBindingsPerGroup);
return mBindingInfo[bindingIndex];
}
const BindingMap& GetBindingMap() const;
BindingIndex GetBindingIndex(BindingNumber bindingNumber) const;
@ -117,10 +119,12 @@ namespace dawn_native {
private:
BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
BindingIndex mBindingCount;
BindingIndex mBufferCount = 0; // |BindingIndex| because buffers are packed at the front.
uint32_t mDynamicUniformBufferCount = 0;
uint32_t mDynamicStorageBufferCount = 0;
LayoutBindingInfo mBindingInfo;
std::array<BindingInfo, kMaxBindingsPerGroup> mBindingInfo;
// Map from BindGroupLayoutEntry.binding to packed indices.
BindingMap mBindingMap;

View File

@ -29,11 +29,9 @@ namespace dawn_native {
namespace {
void TrackBindGroupResourceUsage(PassResourceUsageTracker* usageTracker,
BindGroupBase* group) {
const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo =
group->GetLayout()->GetBindingInfo();
for (BindingIndex bindingIndex = 0; bindingIndex < layoutInfo.bindingCount;
++bindingIndex) {
wgpu::BindingType type = layoutInfo.types[bindingIndex];
for (BindingIndex bindingIndex = 0;
bindingIndex < group->GetLayout()->GetBindingCount(); ++bindingIndex) {
wgpu::BindingType type = group->GetLayout()->GetBindingInfo(bindingIndex).type;
switch (type) {
case wgpu::BindingType::UniformBuffer: {
@ -133,12 +131,13 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("dynamicOffset count mismatch");
}
const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo = layout->GetBindingInfo();
for (BindingIndex i = 0; i < dynamicOffsetCount; ++i) {
const BindGroupLayoutBase::BindingInfo& bindingInfo = layout->GetBindingInfo(i);
// BGL creation sorts bindings such that the dynamic buffer bindings are first.
// ASSERT that this true.
ASSERT(layoutInfo.hasDynamicOffset[i]);
switch (layoutInfo.types[i]) {
ASSERT(bindingInfo.hasDynamicOffset);
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:

View File

@ -741,7 +741,6 @@ namespace dawn_native {
const BindGroupLayoutBase* layout) const {
ASSERT(!IsError());
const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo = layout->GetBindingInfo();
const BindGroupLayoutBase::BindingMap& bindingMap = layout->GetBindingMap();
// Iterate over all bindings used by this group in the shader, and find the
@ -756,7 +755,9 @@ namespace dawn_native {
}
BindingIndex bindingIndex(bindingIt->second);
const auto& layoutBindingType = layoutInfo.types[bindingIndex];
const BindGroupLayoutBase::BindingInfo& bindingInfo =
layout->GetBindingInfo(bindingIndex);
const auto& layoutBindingType = bindingInfo.type;
if (layoutBindingType != moduleInfo.type) {
// Binding mismatch between shader and bind group is invalid. For example, a
@ -771,34 +772,31 @@ namespace dawn_native {
}
}
if ((layoutInfo.visibilities[bindingIndex] & StageBit(mExecutionModel)) == 0) {
if ((bindingInfo.visibility & StageBit(mExecutionModel)) == 0) {
return false;
}
switch (layoutBindingType) {
case wgpu::BindingType::SampledTexture: {
Format::Type layoutTextureComponentType =
Format::TextureComponentTypeToFormatType(
layoutInfo.textureComponentTypes[bindingIndex]);
Format::TextureComponentTypeToFormatType(bindingInfo.textureComponentType);
if (layoutTextureComponentType != moduleInfo.textureComponentType) {
return false;
}
if (layoutInfo.textureDimensions[bindingIndex] != moduleInfo.textureDimension) {
if (bindingInfo.textureDimension != moduleInfo.textureDimension) {
return false;
}
} break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
ASSERT(layoutInfo.storageTextureFormats[bindingIndex] !=
wgpu::TextureFormat::Undefined);
ASSERT(bindingInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
ASSERT(moduleInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
if (layoutInfo.storageTextureFormats[bindingIndex] !=
moduleInfo.storageTextureFormat) {
if (bindingInfo.storageTextureFormat != moduleInfo.storageTextureFormat) {
return false;
}
if (layoutInfo.textureDimensions[bindingIndex] != moduleInfo.textureDimension) {
if (bindingInfo.textureDimension != moduleInfo.textureDimension) {
return false;
}
} break;

View File

@ -81,21 +81,21 @@ namespace dawn_native { namespace d3d12 {
mLastUsageSerial = pendingSerial;
mHeapSerial = allocator->GetShaderVisibleHeapsSerial();
const BindGroupLayoutBase::LayoutBindingInfo& layout = bgl->GetBindingInfo();
const auto& bindingOffsets = bgl->GetBindingOffsets();
ID3D12Device* d3d12Device = device->GetD3D12Device().Get();
for (BindingIndex bindingIndex = 0; bindingIndex < layout.bindingCount; ++bindingIndex) {
for (BindingIndex bindingIndex = 0; bindingIndex < bgl->GetBindingCount(); ++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
// 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.hasDynamicOffset[bindingIndex]) {
if (bindingInfo.hasDynamicOffset) {
continue;
}
switch (layout.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);

View File

@ -45,18 +45,17 @@ namespace dawn_native { namespace d3d12 {
: BindGroupLayoutBase(device, descriptor),
mDescriptorCounts{},
mBindGroupAllocator(MakeFrontendBindGroupAllocator<BindGroup>(4096)) {
const BindGroupLayoutBase::LayoutBindingInfo& groupInfo = GetBindingInfo();
for (BindingIndex bindingIndex = GetDynamicBufferCount(); bindingIndex < GetBindingCount();
++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount; ++bindingIndex) {
// For dynamic resources, Dawn uses root descriptor in D3D12 backend.
// So there is no need to allocate the descriptor from descriptor heap. Skip counting
// dynamic resources for calculating size of descriptor heap.
if (groupInfo.hasDynamicOffset[bindingIndex]) {
continue;
}
// So there is no need to allocate the descriptor from descriptor heap.
// This loop starts after the dynamic buffer indices to skip counting
// dynamic resources in calculating the size of the descriptor heap.
ASSERT(!bindingInfo.hasDynamicOffset);
DescriptorType descriptorType =
WGPUBindingTypeToDescriptorType(groupInfo.types[bindingIndex]);
DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
mBindingOffsets[bindingIndex] = mDescriptorCounts[descriptorType]++;
}
@ -101,12 +100,14 @@ namespace dawn_native { namespace d3d12 {
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER);
descriptorOffsets[Sampler] = 0;
for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount; ++bindingIndex) {
if (groupInfo.hasDynamicOffset[bindingIndex]) {
for (BindingIndex bindingIndex = 0; bindingIndex < GetBindingCount(); ++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
if (bindingInfo.hasDynamicOffset) {
// Dawn is using values in mBindingOffsets to decide register number in HLSL.
// Root descriptor needs to set this value to set correct register number in
// generated HLSL shader.
switch (groupInfo.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
@ -124,8 +125,7 @@ namespace dawn_native { namespace d3d12 {
}
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
DescriptorType descriptorType =
WGPUBindingTypeToDescriptorType(groupInfo.types[bindingIndex]);
DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
mBindingOffsets[bindingIndex] += descriptorOffsets[descriptorType];
}
}

View File

@ -196,28 +196,27 @@ namespace dawn_native { namespace d3d12 {
BindGroup* group,
uint32_t dynamicOffsetCount,
const uint64_t* dynamicOffsets) {
ASSERT(dynamicOffsetCount == group->GetLayout()->GetDynamicBufferCount());
// Usually, the application won't set the same offsets many times,
// so always try to apply dynamic offsets even if the offsets stay the same
if (dynamicOffsetCount) {
// Update dynamic offsets
const BindGroupLayout::LayoutBindingInfo& layout =
group->GetLayout()->GetBindingInfo();
uint32_t currentDynamicBufferIndex = 0;
for (uint32_t bindingIndex : IterateBitSet(layout.hasDynamicOffset)) {
ASSERT(dynamicOffsetCount > 0);
if (dynamicOffsetCount != 0) {
// Update dynamic offsets.
// Dynamic buffer bindings are packed at the beginning of the layout.
for (BindingIndex bindingIndex = 0; bindingIndex < dynamicOffsetCount;
++bindingIndex) {
uint32_t parameterIndex =
pipelineLayout->GetDynamicRootParameterIndex(index, bindingIndex);
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
// Calculate buffer locations that root descriptors links to. The location
// is (base buffer location + initial offset + dynamic offset)
uint64_t dynamicOffset = dynamicOffsets[currentDynamicBufferIndex];
uint64_t dynamicOffset = dynamicOffsets[bindingIndex];
uint64_t offset = binding.offset + dynamicOffset;
D3D12_GPU_VIRTUAL_ADDRESS bufferLocation =
ToBackend(binding.buffer)->GetVA() + offset;
switch (layout.types[bindingIndex]) {
switch (group->GetLayout()->GetBindingInfo(bindingIndex).type) {
case wgpu::BindingType::UniformBuffer:
if (mInCompute) {
commandList->SetComputeRootConstantBufferView(parameterIndex,
@ -253,8 +252,6 @@ namespace dawn_native { namespace d3d12 {
UNREACHABLE();
break;
}
++currentDynamicBufferIndex;
}
}

View File

@ -89,7 +89,6 @@ namespace dawn_native { namespace d3d12 {
for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group));
const BindGroupLayout::LayoutBindingInfo& groupInfo = bindGroupLayout->GetBindingInfo();
// Set the root descriptor table parameter and copy ranges. Ranges are offset by the
// bind group index Returns whether or not the parameter was set. A root parameter is
@ -129,25 +128,30 @@ namespace dawn_native { namespace d3d12 {
// Get calculated shader register for root descriptors
const auto& shaderRegisters = bindGroupLayout->GetBindingOffsets();
// Init root descriptors in root signatures.
for (uint32_t dynamicBinding : IterateBitSet(groupInfo.hasDynamicOffset)) {
// Init root descriptors in root signatures for dynamic buffer bindings.
// These are packed at the beginning of the layout binding info.
for (BindingIndex dynamicBindingIndex = 0;
dynamicBindingIndex < bindGroupLayout->GetDynamicBufferCount();
++dynamicBindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
bindGroupLayout->GetBindingInfo(dynamicBindingIndex);
D3D12_ROOT_PARAMETER* rootParameter = &rootParameters[parameterIndex];
// Setup root descriptor.
D3D12_ROOT_DESCRIPTOR rootDescriptor;
rootDescriptor.ShaderRegister = shaderRegisters[dynamicBinding];
rootDescriptor.ShaderRegister = shaderRegisters[dynamicBindingIndex];
rootDescriptor.RegisterSpace = group;
// Set root descriptors in root signatures.
rootParameter->Descriptor = rootDescriptor;
mDynamicRootParameterIndices[group][dynamicBinding] = parameterIndex++;
mDynamicRootParameterIndices[group][dynamicBindingIndex] = parameterIndex++;
// Set parameter types according to bind group layout descriptor.
rootParameter->ParameterType = RootParameterType(groupInfo.types[dynamicBinding]);
rootParameter->ParameterType = RootParameterType(bindingInfo.type);
// Set visibilities according to bind group layout descriptor.
rootParameter->ShaderVisibility =
ShaderVisibilityType(groupInfo.visibilities[dynamicBinding]);
rootParameter->ShaderVisibility = ShaderVisibilityType(bindingInfo.visibility);
}
}
@ -186,10 +190,11 @@ namespace dawn_native { namespace d3d12 {
return mRootSignature;
}
uint32_t PipelineLayout::GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const {
uint32_t PipelineLayout::GetDynamicRootParameterIndex(uint32_t group,
BindingIndex bindingIndex) const {
ASSERT(group < kMaxBindGroups);
ASSERT(binding < kMaxBindingsPerGroup);
ASSERT(GetBindGroupLayout(group)->GetBindingInfo().hasDynamicOffset[binding]);
return mDynamicRootParameterIndices[group][binding];
ASSERT(bindingIndex < kMaxBindingsPerGroup);
ASSERT(GetBindGroupLayout(group)->GetBindingInfo(bindingIndex).hasDynamicOffset);
return mDynamicRootParameterIndices[group][bindingIndex];
}
}} // namespace dawn_native::d3d12

View File

@ -15,8 +15,8 @@
#ifndef DAWNNATIVE_D3D12_PIPELINELAYOUTD3D12_H_
#define DAWNNATIVE_D3D12_PIPELINELAYOUTD3D12_H_
#include "dawn_native/IntegerTypes.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 {
@ -32,7 +32,7 @@ namespace dawn_native { namespace d3d12 {
uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
// Returns the index of the root parameter reserved for a dynamic buffer binding
uint32_t GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const;
uint32_t GetDynamicRootParameterIndex(uint32_t group, BindingIndex bindingIndex) const;
ComPtr<ID3D12RootSignature> GetRootSignature() const;

View File

@ -493,19 +493,22 @@ namespace dawn_native { namespace metal {
uint32_t dynamicOffsetCount,
uint64_t* dynamicOffsets,
PipelineLayout* pipelineLayout) {
const BindGroupLayoutBase::LayoutBindingInfo& layout =
group->GetLayout()->GetBindingInfo();
uint32_t currentDynamicBufferIndex = 0;
// TODO(kainino@chromium.org): Maintain buffers and offsets arrays in BindGroup
// so that we only have to do one setVertexBuffers and one setFragmentBuffers
// call here.
for (BindingIndex bindingIndex = 0; bindingIndex < layout.bindingCount;
++bindingIndex) {
auto stage = layout.visibilities[bindingIndex];
bool hasVertStage = stage & wgpu::ShaderStage::Vertex && render != nil;
bool hasFragStage = stage & wgpu::ShaderStage::Fragment && render != nil;
bool hasComputeStage = stage & wgpu::ShaderStage::Compute && compute != nil;
for (BindingIndex bindingIndex = 0;
bindingIndex < group->GetLayout()->GetBindingCount(); ++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
group->GetLayout()->GetBindingInfo(bindingIndex);
bool hasVertStage =
bindingInfo.visibility & wgpu::ShaderStage::Vertex && render != nil;
bool hasFragStage =
bindingInfo.visibility & wgpu::ShaderStage::Fragment && render != nil;
bool hasComputeStage =
bindingInfo.visibility & wgpu::ShaderStage::Compute && compute != nil;
uint32_t vertIndex = 0;
uint32_t fragIndex = 0;
@ -524,7 +527,7 @@ namespace dawn_native { namespace metal {
SingleShaderStage::Compute)[index][bindingIndex];
}
switch (layout.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
@ -535,7 +538,7 @@ namespace dawn_native { namespace metal {
// TODO(shaobo.yan@intel.com): Record bound buffer status to use
// setBufferOffset to achieve better performance.
if (layout.hasDynamicOffset[bindingIndex]) {
if (bindingInfo.hasDynamicOffset) {
offset += dynamicOffsets[currentDynamicBufferIndex];
currentDynamicBufferIndex++;
}

View File

@ -29,15 +29,15 @@ namespace dawn_native { namespace metal {
uint32_t textureIndex = 0;
for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayoutBase::LayoutBindingInfo& groupInfo =
GetBindGroupLayout(group)->GetBindingInfo();
for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount;
++bindingIndex) {
if (!(groupInfo.visibilities[bindingIndex] & StageBit(stage))) {
for (BindingIndex bindingIndex = 0;
bindingIndex < GetBindGroupLayout(group)->GetBindingCount(); ++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
GetBindGroupLayout(group)->GetBindingInfo(bindingIndex);
if (!(bindingInfo.visibility & StageBit(stage))) {
continue;
}
switch (groupInfo.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:

View File

@ -131,22 +131,23 @@ namespace dawn_native { namespace metal {
// Create one resource binding entry per stage per binding.
for (uint32_t group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
const BindGroupLayoutBase::LayoutBindingInfo& bgInfo =
layout->GetBindGroupLayout(group)->GetBindingInfo();
const BindGroupLayoutBase::BindingMap& bindingMap =
layout->GetBindGroupLayout(group)->GetBindingMap();
for (const auto& it : bindingMap) {
uint32_t binding = it.first;
BindingNumber bindingNumber = it.first;
BindingIndex bindingIndex = it.second;
for (auto stage : IterateStages(bgInfo.visibilities[bindingIndex])) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
layout->GetBindGroupLayout(group)->GetBindingInfo(bindingIndex);
for (auto stage : IterateStages(bindingInfo.visibility)) {
uint32_t shaderIndex = layout->GetBindingIndexInfo(stage)[group][bindingIndex];
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvc)) {
shaderc_spvc_msl_resource_binding mslBinding;
mslBinding.stage = ToSpvcExecutionModel(stage);
mslBinding.desc_set = group;
mslBinding.binding = binding;
mslBinding.binding = bindingNumber;
mslBinding.msl_buffer = mslBinding.msl_texture = mslBinding.msl_sampler =
shaderIndex;
DAWN_TRY(CheckSpvcSuccess(mSpvcContext.AddMSLResourceBinding(mslBinding),
@ -155,7 +156,7 @@ namespace dawn_native { namespace metal {
spirv_cross::MSLResourceBinding mslBinding;
mslBinding.stage = SpirvExecutionModelForStage(stage);
mslBinding.desc_set = group;
mslBinding.binding = binding;
mslBinding.binding = bindingNumber;
mslBinding.msl_buffer = mslBinding.msl_texture = mslBinding.msl_sampler =
shaderIndex;

View File

@ -239,28 +239,45 @@ namespace dawn_native { namespace opengl {
uint32_t dynamicOffsetCount,
uint64_t* dynamicOffsets) {
const auto& indices = ToBackend(mPipelineLayout)->GetBindingIndexInfo()[index];
const BindGroupLayoutBase::LayoutBindingInfo& layout =
group->GetLayout()->GetBindingInfo();
uint32_t currentDynamicIndex = 0;
uint32_t currentDynamicOffsetIndex = 0;
for (BindingIndex bindingIndex = 0; bindingIndex < layout.bindingCount;
++bindingIndex) {
switch (layout.types[bindingIndex]) {
for (BindingIndex bindingIndex = 0;
bindingIndex < group->GetLayout()->GetBindingCount(); ++bindingIndex) {
const BindGroupLayoutBase::BindingInfo& bindingInfo =
group->GetLayout()->GetBindingInfo(bindingIndex);
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
if (layout.hasDynamicOffset[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
if (bindingInfo.hasDynamicOffset) {
offset += dynamicOffsets[currentDynamicOffsetIndex];
++currentDynamicOffsetIndex;
}
gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset,
binding.size);
} break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
if (bindingInfo.hasDynamicOffset) {
offset += dynamicOffsets[currentDynamicOffsetIndex];
++currentDynamicOffsetIndex;
}
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
binding.size);
} break;
case wgpu::BindingType::Sampler: {
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
GLuint samplerIndex = indices[bindingIndex];
@ -290,22 +307,6 @@ namespace dawn_native { namespace opengl {
}
} break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
GLuint offset = binding.offset;
if (layout.hasDynamicOffset[bindingIndex]) {
offset += dynamicOffsets[currentDynamicIndex];
++currentDynamicIndex;
}
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
binding.size);
} break;
case wgpu::BindingType::StorageTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:

View File

@ -107,15 +107,14 @@ namespace dawn_native { namespace opengl {
const auto& indices = layout->GetBindingIndexInfo();
for (uint32_t group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
const BindGroupLayoutBase::LayoutBindingInfo& groupInfo =
layout->GetBindGroupLayout(group)->GetBindingInfo();
const BindGroupLayoutBase* bgl = layout->GetBindGroupLayout(group);
for (const auto& it : layout->GetBindGroupLayout(group)->GetBindingMap()) {
for (const auto& it : bgl->GetBindingMap()) {
BindingNumber bindingNumber = it.first;
BindingIndex bindingIndex = it.second;
std::string name = GetBindingName(group, bindingNumber);
switch (groupInfo.types[bindingIndex]) {
switch (bgl->GetBindingInfo(bindingIndex).type) {
case wgpu::BindingType::UniformBuffer: {
GLint location = gl.GetUniformBlockIndex(mProgram, name.c_str());
if (location != -1) {
@ -178,10 +177,11 @@ namespace dawn_native { namespace opengl {
indices[combined.textureLocation.group][combined.textureLocation.binding];
mUnitsForTextures[textureIndex].push_back(textureUnit);
const BindGroupLayoutBase* bgl =
layout->GetBindGroupLayout(combined.textureLocation.group);
wgpu::TextureComponentType componentType =
layout->GetBindGroupLayout(combined.textureLocation.group)
->GetBindingInfo()
.textureComponentTypes[combined.textureLocation.binding];
bgl->GetBindingInfo(bgl->GetBindingIndex(combined.textureLocation.binding))
.textureComponentType;
bool shouldUseFiltering = componentType == wgpu::TextureComponentType::Float;
GLuint samplerIndex =

View File

@ -28,12 +28,11 @@ namespace dawn_native { namespace opengl {
GLuint ssboIndex = 0;
for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayoutBase::LayoutBindingInfo& groupInfo =
GetBindGroupLayout(group)->GetBindingInfo();
const BindGroupLayoutBase* bgl = GetBindGroupLayout(group);
for (BindingIndex bindingIndex = 0; bindingIndex < groupInfo.bindingCount;
for (BindingIndex bindingIndex = 0; bindingIndex < bgl->GetBindingCount();
++bindingIndex) {
switch (groupInfo.types[bindingIndex]) {
switch (bgl->GetBindingInfo(bindingIndex).type) {
case wgpu::BindingType::UniformBuffer:
mIndexInfo[group][bindingIndex] = uboIndex;
uboIndex++;

View File

@ -82,8 +82,6 @@ namespace dawn_native { namespace vulkan {
}
MaybeError BindGroupLayout::Initialize() {
const LayoutBindingInfo& info = GetBindingInfo();
// Compute the bindings that will be chained in the DescriptorSetLayout create info. We add
// one entry per binding set. This might be optimized by computing continuous ranges of
// bindings of the same type.
@ -92,13 +90,14 @@ namespace dawn_native { namespace vulkan {
for (const auto& it : GetBindingMap()) {
BindingNumber bindingNumber = it.first;
BindingIndex bindingIndex = it.second;
const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
VkDescriptorSetLayoutBinding* vkBinding = &bindings[numBindings];
vkBinding->binding = bindingNumber;
vkBinding->descriptorType =
VulkanDescriptorType(info.types[bindingIndex], info.hasDynamicOffset[bindingIndex]);
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
vkBinding->descriptorCount = 1;
vkBinding->stageFlags = VulkanShaderStageFlags(info.visibilities[bindingIndex]);
vkBinding->stageFlags = VulkanShaderStageFlags(bindingInfo.visibility);
vkBinding->pImmutableSamplers = nullptr;
numBindings++;
@ -119,9 +118,10 @@ namespace dawn_native { namespace vulkan {
// Compute the size of descriptor pools used for this layout.
std::map<VkDescriptorType, uint32_t> descriptorCountPerType;
for (BindingIndex bindingIndex = 0; bindingIndex < info.bindingCount; ++bindingIndex) {
for (BindingIndex bindingIndex = 0; bindingIndex < GetBindingCount(); ++bindingIndex) {
const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
VkDescriptorType vulkanType =
VulkanDescriptorType(info.types[bindingIndex], info.hasDynamicOffset[bindingIndex]);
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
// map::operator[] will return 0 if the key doesn't exist.
descriptorCountPerType[vulkanType]++;

View File

@ -43,10 +43,11 @@ namespace dawn_native { namespace vulkan {
std::array<VkDescriptorBufferInfo, kMaxBindingsPerGroup> writeBufferInfo;
std::array<VkDescriptorImageInfo, kMaxBindingsPerGroup> writeImageInfo;
const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo = GetLayout()->GetBindingInfo();
for (const auto& it : GetLayout()->GetBindingMap()) {
BindingNumber bindingNumber = it.first;
BindingIndex bindingIndex = it.second;
const BindGroupLayoutBase::BindingInfo& bindingInfo =
GetLayout()->GetBindingInfo(bindingIndex);
auto& write = writes[numWrites];
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@ -55,10 +56,10 @@ namespace dawn_native { namespace vulkan {
write.dstBinding = bindingNumber;
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType = VulkanDescriptorType(layoutInfo.types[bindingIndex],
layoutInfo.hasDynamicOffset[bindingIndex]);
write.descriptorType =
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
switch (layoutInfo.types[bindingIndex]) {
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {