Simplify the BindGroupLayout validation code.

It was using a lot of calls to helper functions full of switches that
were hiding the logic that's relatively simple.

Bug: dawn:527
Change-Id: Iaf2603efa255df5ba2f44989b5375d433f04d5df
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/28561
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Corentin Wallez 2020-09-22 13:47:05 +00:00 committed by Commit Bot service account
parent aeda49ba50
commit 5b4e5fbe1f
1 changed files with 64 additions and 179 deletions

View File

@ -26,163 +26,38 @@
namespace dawn_native { namespace dawn_native {
MaybeError ValidateBindingTypeWithShaderStageVisibility( namespace {
wgpu::BindingType bindingType, MaybeError ValidateStorageTextureFormat(DeviceBase* device,
wgpu::ShaderStage shaderStageVisibility) { wgpu::TextureFormat storageTextureFormat) {
// TODO(jiawei.shao@intel.com): support read-write storage textures. const Format* format = nullptr;
switch (bindingType) { DAWN_TRY_ASSIGN(format, device->GetInternalFormat(storageTextureFormat));
case wgpu::BindingType::StorageBuffer: {
if ((shaderStageVisibility & wgpu::ShaderStage::Vertex) != 0) { ASSERT(format != nullptr);
if (!format->supportsStorageUsage) {
return DAWN_VALIDATION_ERROR("Texture format does not support storage textures");
}
return {};
}
MaybeError ValidateStorageTextureViewDimension(wgpu::TextureViewDimension dimension) {
switch (dimension) {
case wgpu::TextureViewDimension::Cube:
case wgpu::TextureViewDimension::CubeArray:
return DAWN_VALIDATION_ERROR( return DAWN_VALIDATION_ERROR(
"storage buffer binding is not supported in vertex shader"); "Cube map and cube map texture views cannot be used as storage textures");
}
break; case wgpu::TextureViewDimension::e1D:
case wgpu::TextureViewDimension::e2D:
case wgpu::TextureViewDimension::e2DArray:
case wgpu::TextureViewDimension::e3D:
return {};
case wgpu::TextureViewDimension::Undefined:
UNREACHABLE();
} }
case wgpu::BindingType::WriteonlyStorageTexture: {
if ((shaderStageVisibility & wgpu::ShaderStage::Vertex) != 0) {
return DAWN_VALIDATION_ERROR(
"write-only storage texture binding is not supported in vertex shader");
}
break;
}
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
break;
} }
} // anonymous namespace
return {};
}
MaybeError ValidateStorageTextureFormat(DeviceBase* device,
wgpu::BindingType bindingType,
wgpu::TextureFormat storageTextureFormat) {
switch (bindingType) {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
if (storageTextureFormat == wgpu::TextureFormat::Undefined) {
return DAWN_VALIDATION_ERROR("Storage texture format is missing");
}
DAWN_TRY(ValidateTextureFormat(storageTextureFormat));
const Format* format = nullptr;
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(storageTextureFormat));
ASSERT(format != nullptr);
if (!format->supportsStorageUsage) {
return DAWN_VALIDATION_ERROR("The storage texture format is not supported");
}
break;
}
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::SampledTexture:
break;
default:
UNREACHABLE();
break;
}
return {};
}
MaybeError ValidateStorageTextureViewDimension(wgpu::BindingType bindingType,
wgpu::TextureViewDimension dimension) {
switch (bindingType) {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
break;
}
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::SampledTexture:
return {};
default:
UNREACHABLE();
return {};
}
switch (dimension) {
case wgpu::TextureViewDimension::Cube:
case wgpu::TextureViewDimension::CubeArray:
return DAWN_VALIDATION_ERROR(
"Cube map and cube map texture views cannot be used as storage textures");
case wgpu::TextureViewDimension::e1D:
case wgpu::TextureViewDimension::e2D:
case wgpu::TextureViewDimension::e2DArray:
case wgpu::TextureViewDimension::e3D:
return {};
case wgpu::TextureViewDimension::Undefined:
default:
UNREACHABLE();
return {};
}
}
MaybeError ValidateBindingCanBeMultisampled(wgpu::BindingType bindingType,
wgpu::TextureViewDimension viewDimension) {
switch (bindingType) {
case wgpu::BindingType::SampledTexture:
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
return DAWN_VALIDATION_ERROR("Storage texture bindings may not be multisampled");
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
return DAWN_VALIDATION_ERROR("Buffer bindings may not be multisampled");
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
return DAWN_VALIDATION_ERROR("Sampler bindings may not be multisampled");
default:
UNREACHABLE();
return {};
}
switch (viewDimension) {
case wgpu::TextureViewDimension::e2D:
break;
case wgpu::TextureViewDimension::e2DArray:
return DAWN_VALIDATION_ERROR("2D array texture bindings may not be multisampled");
case wgpu::TextureViewDimension::Cube:
case wgpu::TextureViewDimension::CubeArray:
return DAWN_VALIDATION_ERROR("Cube texture bindings may not be multisampled");
case wgpu::TextureViewDimension::e3D:
return DAWN_VALIDATION_ERROR("3D texture bindings may not be multisampled");
case wgpu::TextureViewDimension::e1D:
return DAWN_VALIDATION_ERROR("1D texture bindings may not be multisampled");
case wgpu::TextureViewDimension::Undefined:
default:
UNREACHABLE();
return {};
}
return {};
}
MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase* device, MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase* device,
const BindGroupLayoutDescriptor* descriptor) { const BindGroupLayoutDescriptor* descriptor) {
@ -210,43 +85,53 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("some binding index was specified more than once"); return DAWN_VALIDATION_ERROR("some binding index was specified more than once");
} }
DAWN_TRY(ValidateBindingTypeWithShaderStageVisibility(entry.type, entry.visibility)); bool canBeDynamic = false;
bool canBeMultisampled = false;
DAWN_TRY(ValidateStorageTextureFormat(device, entry.type, entry.storageTextureFormat)); wgpu::ShaderStage allowedStages = kAllStages;
DAWN_TRY(ValidateStorageTextureViewDimension(entry.type, viewDimension));
if (entry.multisampled) {
DAWN_TRY(ValidateBindingCanBeMultisampled(entry.type, viewDimension));
}
switch (entry.type) { switch (entry.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer: case wgpu::BindingType::StorageBuffer:
allowedStages &= ~wgpu::ShaderStage::Vertex;
DAWN_FALLTHROUGH;
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: case wgpu::BindingType::ReadonlyStorageBuffer:
canBeDynamic = true;
break; break;
case wgpu::BindingType::SampledTexture: case wgpu::BindingType::SampledTexture:
if (entry.hasDynamicOffset) { canBeMultisampled = true;
return DAWN_VALIDATION_ERROR("Sampled textures cannot be dynamic");
}
break; break;
case wgpu::BindingType::WriteonlyStorageTexture:
allowedStages &= ~wgpu::ShaderStage::Vertex;
DAWN_FALLTHROUGH;
case wgpu::BindingType::ReadonlyStorageTexture:
DAWN_TRY(ValidateStorageTextureFormat(device, entry.storageTextureFormat));
DAWN_TRY(ValidateStorageTextureViewDimension(viewDimension));
break;
case wgpu::BindingType::Sampler: case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler: case wgpu::BindingType::ComparisonSampler:
if (entry.hasDynamicOffset) {
return DAWN_VALIDATION_ERROR("Samplers cannot be dynamic");
}
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
if (entry.hasDynamicOffset) {
return DAWN_VALIDATION_ERROR("Storage textures cannot be dynamic");
}
break;
default:
UNREACHABLE();
break; break;
} }
if (entry.multisampled) {
if (!canBeMultisampled) {
return DAWN_VALIDATION_ERROR("Binding type cannot be multisampled.");
}
if (viewDimension != wgpu::TextureViewDimension::e2D) {
return DAWN_VALIDATION_ERROR("Multisampled binding must be 2D.");
}
}
if (entry.hasDynamicOffset && !canBeDynamic) {
return DAWN_VALIDATION_ERROR("Binding type cannot be dynamic.");
}
if ((entry.visibility & allowedStages) != entry.visibility) {
return DAWN_VALIDATION_ERROR("Binding type cannot be used with this visibility.");
}
IncrementBindingCounts(&bindingCounts, entry); IncrementBindingCounts(&bindingCounts, entry);
bindingsSet.insert(bindingNumber); bindingsSet.insert(bindingNumber);