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,95 +26,21 @@
namespace dawn_native { namespace dawn_native {
MaybeError ValidateBindingTypeWithShaderStageVisibility( namespace {
wgpu::BindingType bindingType,
wgpu::ShaderStage shaderStageVisibility) {
// TODO(jiawei.shao@intel.com): support read-write storage textures.
switch (bindingType) {
case wgpu::BindingType::StorageBuffer: {
if ((shaderStageVisibility & wgpu::ShaderStage::Vertex) != 0) {
return DAWN_VALIDATION_ERROR(
"storage buffer binding is not supported in vertex shader");
}
break;
}
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;
}
return {};
}
MaybeError ValidateStorageTextureFormat(DeviceBase* device, MaybeError ValidateStorageTextureFormat(DeviceBase* device,
wgpu::BindingType bindingType,
wgpu::TextureFormat storageTextureFormat) { 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; const Format* format = nullptr;
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(storageTextureFormat)); DAWN_TRY_ASSIGN(format, device->GetInternalFormat(storageTextureFormat));
ASSERT(format != nullptr); ASSERT(format != nullptr);
if (!format->supportsStorageUsage) { if (!format->supportsStorageUsage) {
return DAWN_VALIDATION_ERROR("The storage texture format is not supported"); return DAWN_VALIDATION_ERROR("Texture format does not support storage textures");
}
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 {}; return {};
} }
MaybeError ValidateStorageTextureViewDimension(wgpu::BindingType bindingType, MaybeError ValidateStorageTextureViewDimension(wgpu::TextureViewDimension dimension) {
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) { switch (dimension) {
case wgpu::TextureViewDimension::Cube: case wgpu::TextureViewDimension::Cube:
case wgpu::TextureViewDimension::CubeArray: case wgpu::TextureViewDimension::CubeArray:
@ -128,61 +54,10 @@ namespace dawn_native {
return {}; return {};
case wgpu::TextureViewDimension::Undefined: case wgpu::TextureViewDimension::Undefined:
default:
UNREACHABLE(); UNREACHABLE();
return {};
} }
} }
} // anonymous namespace
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,41 +85,51 @@ 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) { break;
return DAWN_VALIDATION_ERROR("Samplers cannot be dynamic");
} }
break;
case wgpu::BindingType::ReadonlyStorageTexture: if (entry.multisampled) {
case wgpu::BindingType::WriteonlyStorageTexture: if (!canBeMultisampled) {
if (entry.hasDynamicOffset) { return DAWN_VALIDATION_ERROR("Binding type cannot be multisampled.");
return DAWN_VALIDATION_ERROR("Storage textures cannot be dynamic");
} }
break; if (viewDimension != wgpu::TextureViewDimension::e2D) {
default: return DAWN_VALIDATION_ERROR("Multisampled binding must be 2D.");
UNREACHABLE(); }
break; }
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);