mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-13 10:51:35 +00:00
Begins including the expected BindGroupLayout in validation messages where a BindGroup descriptor does not match the BindGroupLayout. This is especially helpful in cases where the BindGroupLayout was implicitly created by the pipeline. Bug: dawn:1258 Change-Id: Icbf27b4a2ac9b4dc1716feed47e3e63cf99929a7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/80380 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Brandon Jones <bajones@chromium.org>
267 lines
12 KiB
C++
267 lines
12 KiB
C++
// Copyright 2020 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/BindingInfo.h"
|
|
|
|
#include "dawn/native/ChainUtils_autogen.h"
|
|
|
|
namespace dawn::native {
|
|
|
|
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
|
|
BindingInfoType value,
|
|
const absl::FormatConversionSpec& spec,
|
|
absl::FormatSink* s) {
|
|
switch (value) {
|
|
case BindingInfoType::Buffer:
|
|
s->Append("Buffer");
|
|
break;
|
|
case BindingInfoType::Sampler:
|
|
s->Append("Sampler");
|
|
break;
|
|
case BindingInfoType::Texture:
|
|
s->Append("Texture");
|
|
break;
|
|
case BindingInfoType::StorageTexture:
|
|
s->Append("StorageTexture");
|
|
break;
|
|
case BindingInfoType::ExternalTexture:
|
|
s->Append("ExternalTexture");
|
|
break;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
return {true};
|
|
}
|
|
|
|
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
|
|
const BindingInfo& value,
|
|
const absl::FormatConversionSpec& spec,
|
|
absl::FormatSink* s) {
|
|
s->Append(absl::StrFormat("{\n binding: %u\n visibility: %s\n %s: {\n",
|
|
static_cast<uint32_t>(value.binding), value.visibility,
|
|
value.bindingType));
|
|
|
|
switch (value.bindingType) {
|
|
case BindingInfoType::Buffer:
|
|
s->Append(absl::StrFormat(" type: %s\n", value.buffer.type));
|
|
if (value.buffer.hasDynamicOffset) {
|
|
s->Append(" hasDynamicOffset: true\n");
|
|
}
|
|
if (value.buffer.minBindingSize != 0) {
|
|
s->Append(
|
|
absl::StrFormat(" minBindingSize: %u\n", value.buffer.minBindingSize));
|
|
}
|
|
break;
|
|
case BindingInfoType::Sampler:
|
|
s->Append(absl::StrFormat(" type: %s\n", value.sampler.type));
|
|
break;
|
|
case BindingInfoType::Texture:
|
|
s->Append(absl::StrFormat(" sampleType: %s\n", value.texture.sampleType));
|
|
s->Append(absl::StrFormat(" viewDimension: %s\n", value.texture.viewDimension));
|
|
if (value.texture.multisampled) {
|
|
s->Append(" multisampled: true\n");
|
|
} else {
|
|
s->Append(" multisampled: false\n");
|
|
}
|
|
break;
|
|
case BindingInfoType::StorageTexture:
|
|
s->Append(absl::StrFormat(" access: %s\n", value.storageTexture.access));
|
|
s->Append(absl::StrFormat(" format: %s\n", value.storageTexture.format));
|
|
s->Append(
|
|
absl::StrFormat(" viewDimension: %s\n", value.storageTexture.viewDimension));
|
|
break;
|
|
case BindingInfoType::ExternalTexture:
|
|
break;
|
|
}
|
|
|
|
s->Append(" }\n}");
|
|
return {true};
|
|
}
|
|
|
|
void IncrementBindingCounts(BindingCounts* bindingCounts, const BindGroupLayoutEntry& entry) {
|
|
bindingCounts->totalCount += 1;
|
|
|
|
uint32_t PerStageBindingCounts::*perStageBindingCountMember = nullptr;
|
|
|
|
if (entry.buffer.type != wgpu::BufferBindingType::Undefined) {
|
|
++bindingCounts->bufferCount;
|
|
const BufferBindingLayout& buffer = entry.buffer;
|
|
|
|
if (buffer.minBindingSize == 0) {
|
|
++bindingCounts->unverifiedBufferCount;
|
|
}
|
|
|
|
switch (buffer.type) {
|
|
case wgpu::BufferBindingType::Uniform:
|
|
if (buffer.hasDynamicOffset) {
|
|
++bindingCounts->dynamicUniformBufferCount;
|
|
}
|
|
perStageBindingCountMember = &PerStageBindingCounts::uniformBufferCount;
|
|
break;
|
|
|
|
case wgpu::BufferBindingType::Storage:
|
|
case kInternalStorageBufferBinding:
|
|
case wgpu::BufferBindingType::ReadOnlyStorage:
|
|
if (buffer.hasDynamicOffset) {
|
|
++bindingCounts->dynamicStorageBufferCount;
|
|
}
|
|
perStageBindingCountMember = &PerStageBindingCounts::storageBufferCount;
|
|
break;
|
|
|
|
case wgpu::BufferBindingType::Undefined:
|
|
// Can't get here due to the enclosing if statement.
|
|
UNREACHABLE();
|
|
break;
|
|
}
|
|
} else if (entry.sampler.type != wgpu::SamplerBindingType::Undefined) {
|
|
perStageBindingCountMember = &PerStageBindingCounts::samplerCount;
|
|
} else if (entry.texture.sampleType != wgpu::TextureSampleType::Undefined) {
|
|
perStageBindingCountMember = &PerStageBindingCounts::sampledTextureCount;
|
|
} else if (entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
|
|
perStageBindingCountMember = &PerStageBindingCounts::storageTextureCount;
|
|
} else {
|
|
const ExternalTextureBindingLayout* externalTextureBindingLayout;
|
|
FindInChain(entry.nextInChain, &externalTextureBindingLayout);
|
|
if (externalTextureBindingLayout != nullptr) {
|
|
perStageBindingCountMember = &PerStageBindingCounts::externalTextureCount;
|
|
}
|
|
}
|
|
|
|
ASSERT(perStageBindingCountMember != nullptr);
|
|
for (SingleShaderStage stage : IterateStages(entry.visibility)) {
|
|
++(bindingCounts->perStage[stage].*perStageBindingCountMember);
|
|
}
|
|
}
|
|
|
|
void AccumulateBindingCounts(BindingCounts* bindingCounts, const BindingCounts& rhs) {
|
|
bindingCounts->totalCount += rhs.totalCount;
|
|
bindingCounts->bufferCount += rhs.bufferCount;
|
|
bindingCounts->unverifiedBufferCount += rhs.unverifiedBufferCount;
|
|
bindingCounts->dynamicUniformBufferCount += rhs.dynamicUniformBufferCount;
|
|
bindingCounts->dynamicStorageBufferCount += rhs.dynamicStorageBufferCount;
|
|
|
|
for (SingleShaderStage stage : IterateStages(kAllStages)) {
|
|
bindingCounts->perStage[stage].sampledTextureCount +=
|
|
rhs.perStage[stage].sampledTextureCount;
|
|
bindingCounts->perStage[stage].samplerCount += rhs.perStage[stage].samplerCount;
|
|
bindingCounts->perStage[stage].storageBufferCount +=
|
|
rhs.perStage[stage].storageBufferCount;
|
|
bindingCounts->perStage[stage].storageTextureCount +=
|
|
rhs.perStage[stage].storageTextureCount;
|
|
bindingCounts->perStage[stage].uniformBufferCount +=
|
|
rhs.perStage[stage].uniformBufferCount;
|
|
bindingCounts->perStage[stage].externalTextureCount +=
|
|
rhs.perStage[stage].externalTextureCount;
|
|
}
|
|
}
|
|
|
|
MaybeError ValidateBindingCounts(const BindingCounts& bindingCounts) {
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.dynamicUniformBufferCount > kMaxDynamicUniformBuffersPerPipelineLayout,
|
|
"The number of dynamic uniform buffers (%u) exceeds the maximum per-pipeline-layout "
|
|
"limit (%u).",
|
|
bindingCounts.dynamicUniformBufferCount, kMaxDynamicUniformBuffersPerPipelineLayout);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.dynamicStorageBufferCount > kMaxDynamicStorageBuffersPerPipelineLayout,
|
|
"The number of dynamic storage buffers (%u) exceeds the maximum per-pipeline-layout "
|
|
"limit (%u).",
|
|
bindingCounts.dynamicStorageBufferCount, kMaxDynamicStorageBuffersPerPipelineLayout);
|
|
|
|
for (SingleShaderStage stage : IterateStages(kAllStages)) {
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].sampledTextureCount >
|
|
kMaxSampledTexturesPerShaderStage,
|
|
"The number of sampled textures (%u) in the %s stage exceeds the maximum "
|
|
"per-stage limit (%u).",
|
|
bindingCounts.perStage[stage].sampledTextureCount, stage,
|
|
kMaxSampledTexturesPerShaderStage);
|
|
|
|
// The per-stage number of external textures is bound by the maximum sampled textures
|
|
// per stage.
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].externalTextureCount >
|
|
kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture,
|
|
"The number of external textures (%u) in the %s stage exceeds the maximum "
|
|
"per-stage limit (%u).",
|
|
bindingCounts.perStage[stage].externalTextureCount, stage,
|
|
kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].sampledTextureCount +
|
|
(bindingCounts.perStage[stage].externalTextureCount *
|
|
kSampledTexturesPerExternalTexture) >
|
|
kMaxSampledTexturesPerShaderStage,
|
|
"The combination of sampled textures (%u) and external textures (%u) in the %s "
|
|
"stage exceeds the maximum per-stage limit (%u).",
|
|
bindingCounts.perStage[stage].sampledTextureCount,
|
|
bindingCounts.perStage[stage].externalTextureCount, stage,
|
|
kMaxSampledTexturesPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].samplerCount > kMaxSamplersPerShaderStage,
|
|
"The number of samplers (%u) in the %s stage exceeds the maximum per-stage limit "
|
|
"(%u).",
|
|
bindingCounts.perStage[stage].samplerCount, stage, kMaxSamplersPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].samplerCount +
|
|
(bindingCounts.perStage[stage].externalTextureCount *
|
|
kSamplersPerExternalTexture) >
|
|
kMaxSamplersPerShaderStage,
|
|
"The combination of samplers (%u) and external textures (%u) in the %s stage "
|
|
"exceeds the maximum per-stage limit (%u).",
|
|
bindingCounts.perStage[stage].samplerCount,
|
|
bindingCounts.perStage[stage].externalTextureCount, stage,
|
|
kMaxSamplersPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].storageBufferCount > kMaxStorageBuffersPerShaderStage,
|
|
"The number of storage buffers (%u) in the %s stage exceeds the maximum per-stage "
|
|
"limit (%u).",
|
|
bindingCounts.perStage[stage].storageBufferCount, stage,
|
|
kMaxStorageBuffersPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].storageTextureCount >
|
|
kMaxStorageTexturesPerShaderStage,
|
|
"The number of storage textures (%u) in the %s stage exceeds the maximum per-stage "
|
|
"limit (%u).",
|
|
bindingCounts.perStage[stage].storageTextureCount, stage,
|
|
kMaxStorageTexturesPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].uniformBufferCount > kMaxUniformBuffersPerShaderStage,
|
|
"The number of uniform buffers (%u) in the %s stage exceeds the maximum per-stage "
|
|
"limit (%u).",
|
|
bindingCounts.perStage[stage].uniformBufferCount, stage,
|
|
kMaxUniformBuffersPerShaderStage);
|
|
|
|
DAWN_INVALID_IF(
|
|
bindingCounts.perStage[stage].uniformBufferCount +
|
|
(bindingCounts.perStage[stage].externalTextureCount *
|
|
kUniformsPerExternalTexture) >
|
|
kMaxUniformBuffersPerShaderStage,
|
|
"The combination of uniform buffers (%u) and external textures (%u) in the %s "
|
|
"stage exceeds the maximum per-stage limit (%u).",
|
|
bindingCounts.perStage[stage].uniformBufferCount,
|
|
bindingCounts.perStage[stage].externalTextureCount, stage,
|
|
kMaxUniformBuffersPerShaderStage);
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
} // namespace dawn::native
|