Updating BindGroupLayoutEntry interface to match latest spec

Updates BindGroupLayoutEntry to allow for the newly split-up descriptors
that define each binding type in it's own member (buffer, texture, etc.)
The previous style of descriptor is still supported but is deprecated.

For the sake of keeping the scope reasonable, this change does not alter
the BindingInfo structure that's used internally by the various
backends. That will come as a followup.

Bug: dawn:527
Change-Id: I2f301f5f36fa2ce7ff15126ac90dc4c19d5e32ca
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/34921
Commit-Queue: Brandon Jones <bajones@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Brandon Jones 2020-12-12 02:09:56 +00:00 committed by Commit Bot service account
parent ed883bc1d9
commit 9c52c2997c
29 changed files with 742 additions and 178 deletions

103
dawn.json
View File

@ -85,18 +85,100 @@
"bind group layout": {
"category": "object"
},
"buffer binding type": {
"category": "enum",
"values": [
{"value": 0, "name": "undefined", "jsrepr": "undefined", "valid": false},
{"value": 1, "name": "uniform"},
{"value": 2, "name": "storage"},
{"value": 3, "name": "read only storage", "jsrepr": "readonly-storage"}
]
},
"buffer binding layout": {
"category": "structure",
"extensible": true,
"members": [
{"name": "type", "type": "buffer binding type", "default": "undefined"},
{"name": "has dynamic offset", "type": "bool", "default": "false"},
{"name": "min binding size", "type": "uint64_t", "default": "0"}
]
},
"sampler binding type": {
"category": "enum",
"values": [
{"value": 0, "name": "undefined", "jsrepr": "undefined", "valid": false},
{"value": 1, "name": "filtering"},
{"value": 2, "name": "non filtering"},
{"value": 3, "name": "comparison"}
]
},
"sampler binding layout": {
"category": "structure",
"extensible": true,
"members": [
{"name": "type", "type": "sampler binding type", "default": "undefined"}
]
},
"texture sample type": {
"category": "enum",
"values": [
{"value": 0, "name": "undefined", "jsrepr": "undefined", "valid": false},
{"value": 1, "name": "float"},
{"value": 2, "name": "unfilterable float"},
{"value": 3, "name": "depth"},
{"value": 4, "name": "sint"},
{"value": 5, "name": "uint"}
]
},
"texture binding layout": {
"category": "structure",
"extensible": true,
"members": [
{"name": "sample type", "type": "texture sample type", "default": "undefined"},
{"name": "view dimension", "type": "texture view dimension", "default": "undefined"},
{"name": "multisampled", "type": "bool", "default": "false"}
]
},
"storage texture access": {
"category": "enum",
"values": [
{"value": 0, "name": "undefined", "jsrepr": "undefined", "valid": false},
{"value": 1, "name": "read only", "jsrepr": "readonly"},
{"value": 2, "name": "write only", "jsrepr": "writeonly"}
]
},
"storage texture binding layout": {
"category": "structure",
"extensible": true,
"members": [
{"name": "access", "type": "storage texture access", "default": "undefined"},
{"name": "format", "type": "texture format", "default": "undefined"},
{"name": "view dimension", "type": "texture view dimension", "default": "undefined"}
]
},
"bind group layout entry": {
"category": "structure",
"extensible": false,
"members": [
{"name": "binding", "type": "uint32_t"},
{"name": "visibility", "type": "shader stage"},
{"name": "type", "type": "binding type"},
{"name": "has dynamic offset", "type": "bool", "default": "false"},
{"name": "min buffer binding size", "type": "uint64_t", "default": "0"},
{"name": "view dimension", "type": "texture view dimension", "default": "undefined"},
{"name": "texture component type", "type": "texture component type", "default": "float"},
{"name": "storage texture format", "type": "texture format", "default": "undefined"}
{"name": "storage texture format", "type": "texture format", "default": "undefined"},
{"name": "buffer", "type": "buffer binding layout"},
{"name": "sampler", "type": "sampler binding layout"},
{"name": "texture", "type": "texture binding layout"},
{"name": "storage texture", "type": "storage texture binding layout"}
]
},
"bind group layout descriptor": {
@ -111,15 +193,16 @@
"binding type": {
"category": "enum",
"values": [
{"value": 0, "name": "uniform buffer"},
{"value": 1, "name": "storage buffer"},
{"value": 2, "name": "readonly storage buffer"},
{"value": 3, "name": "sampler"},
{"value": 4, "name": "comparison sampler"},
{"value": 5, "name": "sampled texture"},
{"value": 6, "name": "multisampled texture"},
{"value": 7, "name": "readonly storage texture"},
{"value": 8, "name": "writeonly storage texture"}
{"value": 0, "name": "undefined", "jsrepr": "undefined", "valid": false},
{"value": 1, "name": "uniform buffer"},
{"value": 2, "name": "storage buffer"},
{"value": 3, "name": "readonly storage buffer"},
{"value": 4, "name": "sampler"},
{"value": 5, "name": "comparison sampler"},
{"value": 6, "name": "sampled texture"},
{"value": 7, "name": "multisampled texture"},
{"value": 8, "name": "readonly storage texture"},
{"value": 9, "name": "writeonly storage texture"}
]
},
"blend descriptor": {

View File

@ -240,6 +240,9 @@ namespace dawn_native {
DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Storage,
false, bindingInfo));
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
break;
}
}

View File

@ -71,75 +71,169 @@ namespace dawn_native {
const BindGroupLayoutEntry& entry = descriptor->entries[i];
BindingNumber bindingNumber = BindingNumber(entry.binding);
DAWN_TRY(ValidateShaderStage(entry.visibility));
DAWN_TRY(ValidateBindingType(entry.type));
DAWN_TRY(ValidateTextureComponentType(entry.textureComponentType));
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D;
if (entry.viewDimension != wgpu::TextureViewDimension::Undefined) {
DAWN_TRY(ValidateTextureViewDimension(entry.viewDimension));
viewDimension = entry.viewDimension;
}
if (bindingsSet.count(bindingNumber) != 0) {
return DAWN_VALIDATION_ERROR("some binding index was specified more than once");
}
bool canBeDynamic = false;
DAWN_TRY(ValidateShaderStage(entry.visibility));
int bindingMemberCount = 0;
wgpu::ShaderStage allowedStages = kAllStages;
switch (entry.type) {
case wgpu::BindingType::StorageBuffer:
if (entry.buffer.type != wgpu::BufferBindingType::Undefined) {
bindingMemberCount++;
const BufferBindingLayout& buffer = entry.buffer;
DAWN_TRY(ValidateBufferBindingType(buffer.type));
// TODO(dawn:527): ReadOnlyStorage should have the same limits as Storage
// regarding use with Vertex shaders.
if (buffer.type == wgpu::BufferBindingType::Storage) {
allowedStages &= ~wgpu::ShaderStage::Vertex;
DAWN_FALLTHROUGH;
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
canBeDynamic = true;
break;
case wgpu::BindingType::SampledTexture:
break;
case wgpu::BindingType::MultisampledTexture:
if (viewDimension != wgpu::TextureViewDimension::e2D) {
return DAWN_VALIDATION_ERROR("Multisampled binding must be 2D.");
}
if (entry.textureComponentType == wgpu::TextureComponentType::DepthComparison) {
// Dynamic storage buffers aren't bounds checked properly in D3D12. Disallow
// them as unsafe until the bounds checks are implemented.
if (device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) &&
buffer.hasDynamicOffset) {
return DAWN_VALIDATION_ERROR(
"Multisampled binding must not be DepthComparison.");
"Dynamic storage buffers are disallowed because they aren't secure "
"yet. See https://crbug.com/dawn/429");
}
break;
}
}
if (entry.sampler.type != wgpu::SamplerBindingType::Undefined) {
bindingMemberCount++;
DAWN_TRY(ValidateSamplerBindingType(entry.sampler.type));
}
if (entry.texture.sampleType != wgpu::TextureSampleType::Undefined) {
bindingMemberCount++;
const TextureBindingLayout& texture = entry.texture;
DAWN_TRY(ValidateTextureSampleType(texture.sampleType));
case wgpu::BindingType::WriteonlyStorageTexture:
// viewDimension defaults to 2D if left undefined, needs validation otherwise.
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D;
if (texture.viewDimension != wgpu::TextureViewDimension::Undefined) {
DAWN_TRY(ValidateTextureViewDimension(texture.viewDimension));
viewDimension = texture.viewDimension;
}
if (texture.multisampled) {
if (viewDimension != wgpu::TextureViewDimension::e2D) {
return DAWN_VALIDATION_ERROR("Multisampled texture bindings must be 2D.");
}
// TODO: This check should eventually become obsolete. According to the spec,
// depth can be used with both regular and comparison sampling. As such, during
// pipeline creation we have to check that if a comparison sampler is used
// with a texture, that texture must be both depth and not multisampled.
if (texture.sampleType == wgpu::TextureSampleType::Depth) {
return DAWN_VALIDATION_ERROR(
"Multisampled texture bindings must not be Depth.");
}
}
}
if (entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
bindingMemberCount++;
const StorageTextureBindingLayout& storageTexture = entry.storageTexture;
DAWN_TRY(ValidateStorageTextureAccess(storageTexture.access));
DAWN_TRY(ValidateStorageTextureFormat(device, storageTexture.format));
// viewDimension defaults to 2D if left undefined, needs validation otherwise.
if (storageTexture.viewDimension != wgpu::TextureViewDimension::Undefined) {
DAWN_TRY(ValidateTextureViewDimension(storageTexture.viewDimension));
DAWN_TRY(ValidateStorageTextureViewDimension(storageTexture.viewDimension));
}
if (storageTexture.access == wgpu::StorageTextureAccess::WriteOnly) {
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::ComparisonSampler:
break;
}
}
if (entry.hasDynamicOffset && !canBeDynamic) {
return DAWN_VALIDATION_ERROR("Binding type cannot be dynamic.");
if (bindingMemberCount > 1) {
return DAWN_VALIDATION_ERROR(
"Only one of buffer, sampler, texture, or storageTexture may be set for each "
"BindGroupLayoutEntry");
} else if (bindingMemberCount > 1) {
if (entry.type != wgpu::BindingType::Undefined) {
return DAWN_VALIDATION_ERROR(
"BindGroupLayoutEntry type must be undefined if any of buffer, sampler, "
"texture, or storageTexture are set");
}
} else if (bindingMemberCount == 0) {
// TODO(dawn:527): Raising this warning breaks a ton of validation tests.
// Deprecated validation path
/*device->EmitDeprecationWarning(
"The format of BindGroupLayoutEntry has changed, and will soon require the "
"buffer, sampler, texture, or storageTexture members be set rather than "
"setting type, etc. on the entry directly.");*/
DAWN_TRY(ValidateBindingType(entry.type));
DAWN_TRY(ValidateTextureComponentType(entry.textureComponentType));
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D;
if (entry.viewDimension != wgpu::TextureViewDimension::Undefined) {
DAWN_TRY(ValidateTextureViewDimension(entry.viewDimension));
viewDimension = entry.viewDimension;
}
bool canBeDynamic = false;
switch (entry.type) {
case wgpu::BindingType::StorageBuffer:
allowedStages &= ~wgpu::ShaderStage::Vertex;
DAWN_FALLTHROUGH;
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
canBeDynamic = true;
break;
case wgpu::BindingType::SampledTexture:
break;
case wgpu::BindingType::MultisampledTexture:
if (viewDimension != wgpu::TextureViewDimension::e2D) {
return DAWN_VALIDATION_ERROR("Multisampled binding must be 2D.");
}
if (entry.textureComponentType ==
wgpu::TextureComponentType::DepthComparison) {
return DAWN_VALIDATION_ERROR(
"Multisampled binding must not be DepthComparison.");
}
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::ComparisonSampler:
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
if (entry.hasDynamicOffset && !canBeDynamic) {
return DAWN_VALIDATION_ERROR("Binding type cannot be dynamic.");
}
// Dynamic storage buffers aren't bounds checked properly in D3D12. Disallow them as
// unsafe until the bounds checks are implemented.
if (device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) && entry.hasDynamicOffset &&
(entry.type == wgpu::BindingType::StorageBuffer ||
entry.type == wgpu::BindingType::ReadonlyStorageBuffer)) {
return DAWN_VALIDATION_ERROR(
"Dynamic storage buffers are disallowed because they aren't secure yet. "
"See https://crbug.com/dawn/429");
}
}
if (!IsSubset(entry.visibility, allowedStages)) {
return DAWN_VALIDATION_ERROR("Binding type cannot be used with this visibility.");
}
// Dynamic storage buffers aren't bounds checked properly in D3D12. Disallow them as
// unsafe until the bounds checks are implemented.
if (device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) &&
entry.type == wgpu::BindingType::StorageBuffer && entry.hasDynamicOffset) {
return DAWN_VALIDATION_ERROR(
"Dynamic storage buffers are disallowed because they aren't secure yet. See "
"https://crbug.com/dawn/429");
}
IncrementBindingCounts(&bindingCounts, entry);
bindingsSet.insert(bindingNumber);
@ -163,8 +257,8 @@ namespace dawn_native {
a.minBufferBindingSize != b.minBufferBindingSize;
}
bool IsBufferBinding(wgpu::BindingType bindingType) {
switch (bindingType) {
bool IsBufferBindingType(wgpu::BindingType type) {
switch (type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
@ -175,27 +269,58 @@ namespace dawn_native {
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
return false;
}
}
bool IsBufferBinding(const BindGroupLayoutEntry& binding) {
if (binding.buffer.type != wgpu::BufferBindingType::Undefined) {
return true;
} else if (binding.sampler.type != wgpu::SamplerBindingType::Undefined) {
return false;
} else if (binding.texture.sampleType != wgpu::TextureSampleType::Undefined) {
return false;
} else if (binding.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
return false;
}
return IsBufferBindingType(binding.type);
}
bool BindingHasDynamicOffset(const BindGroupLayoutEntry& binding) {
if (binding.buffer.type != wgpu::BufferBindingType::Undefined) {
return binding.buffer.hasDynamicOffset;
} else if (binding.sampler.type != wgpu::SamplerBindingType::Undefined) {
return false;
} else if (binding.texture.sampleType != wgpu::TextureSampleType::Undefined) {
return false;
} else if (binding.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
return false;
}
return binding.hasDynamicOffset;
}
bool SortBindingsCompare(const BindGroupLayoutEntry& a, const BindGroupLayoutEntry& b) {
const bool aIsBuffer = IsBufferBinding(a.type);
const bool bIsBuffer = IsBufferBinding(b.type);
const bool aIsBuffer = IsBufferBinding(a);
const bool bIsBuffer = IsBufferBinding(b);
if (aIsBuffer != bIsBuffer) {
// Always place buffers first.
return aIsBuffer;
} else {
if (aIsBuffer) {
bool aHasDynamicOffset = BindingHasDynamicOffset(a);
bool bHasDynamicOffset = BindingHasDynamicOffset(b);
ASSERT(bIsBuffer);
if (a.hasDynamicOffset != b.hasDynamicOffset) {
if (aHasDynamicOffset != bHasDynamicOffset) {
// Buffers with dynamic offsets should come before those without.
// This makes it easy to iterate over the dynamic buffer bindings
// [0, dynamicBufferCount) during validation.
return a.hasDynamicOffset;
return aHasDynamicOffset;
}
if (a.hasDynamicOffset) {
ASSERT(b.hasDynamicOffset);
if (aHasDynamicOffset) {
ASSERT(bHasDynamicOffset);
ASSERT(a.binding != b.binding);
// Above, we ensured that dynamic buffers are first. Now, ensure that
// dynamic buffer bindings are in increasing order. This is because dynamic
@ -232,7 +357,7 @@ namespace dawn_native {
BindingIndex lastBufferIndex{0};
BindingIndex firstNonBufferIndex = std::numeric_limits<BindingIndex>::max();
for (BindingIndex i{0}; i < bindings.size(); ++i) {
if (IsBufferBinding(bindings[i].type)) {
if (IsBufferBindingType(bindings[i].type)) {
lastBufferIndex = std::max(i, lastBufferIndex);
} else {
firstNonBufferIndex = std::min(i, firstNonBufferIndex);
@ -258,22 +383,109 @@ namespace dawn_native {
for (BindingIndex i{0}; i < mBindingInfo.size(); ++i) {
const BindGroupLayoutEntry& binding = sortedBindings[static_cast<uint32_t>(i)];
mBindingInfo[i].binding = BindingNumber(binding.binding);
mBindingInfo[i].type = binding.type;
mBindingInfo[i].visibility = binding.visibility;
mBindingInfo[i].textureComponentType = binding.textureComponentType;
mBindingInfo[i].storageTextureFormat = binding.storageTextureFormat;
mBindingInfo[i].minBufferBindingSize = binding.minBufferBindingSize;
if (binding.viewDimension == wgpu::TextureViewDimension::Undefined) {
mBindingInfo[i].viewDimension = wgpu::TextureViewDimension::e2D;
// TODO(dawn:527): This code currently converts the new-style BindGroupLayoutEntry
// definitions into the older-style BindingInfo. This is to allow for a staggered
// conversion, but it means that there's some combinations that the more expressive new
// style can handle that will be lost in the translation. The solution is to update
// BindingInfo to only reflect the new-style entry layout and convert the old-style
// entry layout into it instead.
mBindingInfo[i].binding = BindingNumber(binding.binding);
mBindingInfo[i].visibility = binding.visibility;
if (binding.buffer.type != wgpu::BufferBindingType::Undefined) {
switch (binding.buffer.type) {
case wgpu::BufferBindingType::Uniform:
mBindingInfo[i].type = wgpu::BindingType::UniformBuffer;
break;
case wgpu::BufferBindingType::Storage:
mBindingInfo[i].type = wgpu::BindingType::StorageBuffer;
break;
case wgpu::BufferBindingType::ReadOnlyStorage:
mBindingInfo[i].type = wgpu::BindingType::ReadonlyStorageBuffer;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
mBindingInfo[i].minBufferBindingSize = binding.buffer.minBindingSize;
mBindingInfo[i].hasDynamicOffset = binding.buffer.hasDynamicOffset;
} else if (binding.sampler.type != wgpu::SamplerBindingType::Undefined) {
switch (binding.sampler.type) {
case wgpu::SamplerBindingType::Filtering:
case wgpu::SamplerBindingType::NonFiltering:
mBindingInfo[i].type = wgpu::BindingType::Sampler;
break;
case wgpu::SamplerBindingType::Comparison:
mBindingInfo[i].type = wgpu::BindingType::ComparisonSampler;
break;
case wgpu::SamplerBindingType::Undefined:
UNREACHABLE();
}
} else if (binding.texture.sampleType != wgpu::TextureSampleType::Undefined) {
mBindingInfo[i].type = binding.texture.multisampled
? wgpu::BindingType::MultisampledTexture
: wgpu::BindingType::SampledTexture;
switch (binding.texture.sampleType) {
case wgpu::TextureSampleType::Float:
case wgpu::TextureSampleType::UnfilterableFloat:
mBindingInfo[i].textureComponentType = wgpu::TextureComponentType::Float;
break;
case wgpu::TextureSampleType::Sint:
mBindingInfo[i].textureComponentType = wgpu::TextureComponentType::Sint;
break;
case wgpu::TextureSampleType::Uint:
mBindingInfo[i].textureComponentType = wgpu::TextureComponentType::Uint;
break;
case wgpu::TextureSampleType::Depth:
mBindingInfo[i].textureComponentType =
wgpu::TextureComponentType::DepthComparison;
break;
case wgpu::TextureSampleType::Undefined:
UNREACHABLE();
}
if (binding.texture.viewDimension == wgpu::TextureViewDimension::Undefined) {
mBindingInfo[i].viewDimension = wgpu::TextureViewDimension::e2D;
} else {
mBindingInfo[i].viewDimension = binding.texture.viewDimension;
}
} else if (binding.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
switch (binding.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly:
mBindingInfo[i].type = wgpu::BindingType::ReadonlyStorageTexture;
break;
case wgpu::StorageTextureAccess::WriteOnly:
mBindingInfo[i].type = wgpu::BindingType::WriteonlyStorageTexture;
break;
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
mBindingInfo[i].storageTextureFormat = binding.storageTexture.format;
if (binding.storageTexture.viewDimension == wgpu::TextureViewDimension::Undefined) {
mBindingInfo[i].viewDimension = wgpu::TextureViewDimension::e2D;
} else {
mBindingInfo[i].viewDimension = binding.storageTexture.viewDimension;
}
} else {
mBindingInfo[i].viewDimension = binding.viewDimension;
// Deprecated entry layout. As noted above, though, this is currently the only
// lossless path.
mBindingInfo[i].type = binding.type;
mBindingInfo[i].textureComponentType = binding.textureComponentType;
mBindingInfo[i].storageTextureFormat = binding.storageTextureFormat;
mBindingInfo[i].minBufferBindingSize = binding.minBufferBindingSize;
if (binding.viewDimension == wgpu::TextureViewDimension::Undefined) {
mBindingInfo[i].viewDimension = wgpu::TextureViewDimension::e2D;
} else {
mBindingInfo[i].viewDimension = binding.viewDimension;
}
mBindingInfo[i].hasDynamicOffset = binding.hasDynamicOffset;
}
mBindingInfo[i].hasDynamicOffset = binding.hasDynamicOffset;
if (IsBufferBinding(binding.type)) {
if (IsBufferBinding(binding)) {
// Buffers must be contiguously packed at the start of the binding info.
ASSERT(GetBufferCount() == i);
}

View File

@ -20,44 +20,86 @@ namespace dawn_native {
bindingCounts->totalCount += 1;
uint32_t PerStageBindingCounts::*perStageBindingCountMember = nullptr;
switch (entry.type) {
case wgpu::BindingType::UniformBuffer:
++bindingCounts->bufferCount;
if (entry.hasDynamicOffset) {
++bindingCounts->dynamicUniformBufferCount;
}
if (entry.minBufferBindingSize == 0) {
++bindingCounts->unverifiedBufferCount;
}
perStageBindingCountMember = &PerStageBindingCounts::uniformBufferCount;
break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
++bindingCounts->bufferCount;
if (entry.hasDynamicOffset) {
++bindingCounts->dynamicStorageBufferCount;
}
if (entry.minBufferBindingSize == 0) {
++bindingCounts->unverifiedBufferCount;
}
perStageBindingCountMember = &PerStageBindingCounts::storageBufferCount;
break;
if (entry.buffer.type != wgpu::BufferBindingType::Undefined) {
++bindingCounts->bufferCount;
const BufferBindingLayout& buffer = entry.buffer;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
perStageBindingCountMember = &PerStageBindingCounts::sampledTextureCount;
break;
if (buffer.minBindingSize == 0) {
++bindingCounts->unverifiedBufferCount;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
perStageBindingCountMember = &PerStageBindingCounts::samplerCount;
break;
switch (buffer.type) {
case wgpu::BufferBindingType::Uniform:
if (buffer.hasDynamicOffset) {
++bindingCounts->dynamicUniformBufferCount;
}
perStageBindingCountMember = &PerStageBindingCounts::uniformBufferCount;
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
perStageBindingCountMember = &PerStageBindingCounts::storageTextureCount;
break;
case wgpu::BufferBindingType::Storage:
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 {
// Deprecated path.
switch (entry.type) {
case wgpu::BindingType::UniformBuffer:
++bindingCounts->bufferCount;
if (entry.hasDynamicOffset) {
++bindingCounts->dynamicUniformBufferCount;
}
if (entry.minBufferBindingSize == 0) {
++bindingCounts->unverifiedBufferCount;
}
perStageBindingCountMember = &PerStageBindingCounts::uniformBufferCount;
break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
++bindingCounts->bufferCount;
if (entry.hasDynamicOffset) {
++bindingCounts->dynamicStorageBufferCount;
}
if (entry.minBufferBindingSize == 0) {
++bindingCounts->unverifiedBufferCount;
}
perStageBindingCountMember = &PerStageBindingCounts::storageBufferCount;
break;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
perStageBindingCountMember = &PerStageBindingCounts::sampledTextureCount;
break;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
perStageBindingCountMember = &PerStageBindingCounts::samplerCount;
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
perStageBindingCountMember = &PerStageBindingCounts::storageTextureCount;
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
ASSERT(perStageBindingCountMember != nullptr);

View File

@ -75,6 +75,9 @@ namespace dawn_native {
usageTracker->TextureViewUsedAs(view, wgpu::TextureUsage::Storage);
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -425,6 +425,9 @@ namespace dawn_native {
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -139,6 +139,9 @@ namespace dawn_native { namespace d3d12 {
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -38,6 +38,8 @@ namespace dawn_native { namespace d3d12 {
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
return BindGroupLayout::DescriptorType::Sampler;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
} // anonymous namespace
@ -121,6 +123,7 @@ namespace dawn_native { namespace d3d12 {
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
UNREACHABLE();
break;
}

View File

@ -291,6 +291,9 @@ namespace dawn_native { namespace d3d12 {
case wgpu::BindingType::ComparisonSampler:
// Don't require barriers.
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}
@ -384,6 +387,7 @@ namespace dawn_native { namespace d3d12 {
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -54,6 +54,7 @@ namespace dawn_native { namespace d3d12 {
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -461,6 +461,9 @@ namespace dawn_native { namespace metal {
}
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -58,6 +58,8 @@ namespace dawn_native { namespace metal {
mIndexInfo[stage][group][bindingIndex] = textureIndex;
textureIndex++;
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -52,6 +52,9 @@ namespace dawn_native { namespace opengl {
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -365,6 +365,9 @@ namespace dawn_native { namespace opengl {
texture->GetGLFormat().internalFormat);
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -176,6 +176,9 @@ namespace dawn_native { namespace opengl {
}
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -61,6 +61,9 @@ namespace dawn_native { namespace opengl {
mIndexInfo[group][bindingIndex] = storageTextureIndex;
storageTextureIndex++;
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -68,6 +68,8 @@ namespace dawn_native { namespace vulkan {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -108,6 +108,9 @@ namespace dawn_native { namespace vulkan {
write.pImageInfo = &writeImageInfo[numWrites];
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
numWrites++;

View File

@ -208,6 +208,9 @@ namespace dawn_native { namespace vulkan {
case wgpu::BindingType::ComparisonSampler:
// Don't require barriers.
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -850,8 +850,10 @@ TEST_P(BindGroupTests, DynamicOffsetOrder) {
TEST_P(BindGroupTests, BindGroupLayoutVisibilityCanBeNone) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::None,
wgpu::BindingType::UniformBuffer};
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::None;
entry.buffer.type = wgpu::BufferBindingType::Uniform;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &entry;
@ -880,8 +882,11 @@ TEST_P(BindGroupTests, BindGroupLayoutVisibilityCanBeNone) {
TEST_P(BindGroupTests, DynamicBindingNoneVisibility) {
utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::None,
wgpu::BindingType::UniformBuffer, true};
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::None;
entry.buffer.type = wgpu::BufferBindingType::Uniform;
entry.buffer.hasDynamicOffset = true;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &entry;

View File

@ -100,8 +100,10 @@ TEST_P(DeviceLostTest, SubmitFails) {
TEST_P(DeviceLostTest, CreateBindGroupLayoutFails) {
SetCallbackAndLoseForTesting();
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::None,
wgpu::BindingType::UniformBuffer};
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::None;
entry.buffer.type = wgpu::BufferBindingType::Uniform;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &entry;

View File

@ -29,8 +29,13 @@ TEST_P(PipelineLayoutTests, DynamicBuffersOverflow) {
{
std::vector<wgpu::BindGroupLayoutEntry> entries;
for (uint32_t i = 0; i < kMaxDynamicStorageBuffersPerPipelineLayout; i++) {
entries.push_back(
{i, wgpu::ShaderStage::Compute, wgpu::BindingType::StorageBuffer, true});
wgpu::BindGroupLayoutEntry entry;
entry.binding = i;
entry.visibility = wgpu::ShaderStage::Compute;
entry.buffer.type = wgpu::BufferBindingType::Storage;
entry.buffer.hasDynamicOffset = true;
entries.push_back(entry);
}
wgpu::BindGroupLayoutDescriptor descriptor;
@ -44,8 +49,11 @@ TEST_P(PipelineLayoutTests, DynamicBuffersOverflow) {
wgpu::BindGroupLayout bglB;
{
wgpu::BindGroupLayoutDescriptor descriptor;
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::Fragment,
wgpu::BindingType::StorageBuffer, false};
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::Fragment;
entry.buffer.type = wgpu::BufferBindingType::Storage;
descriptor.entryCount = 1;
descriptor.entries = &entry;
bglB = device.CreateBindGroupLayout(&descriptor);

View File

@ -687,9 +687,11 @@ TEST_P(StorageTextureTests, BindGroupLayoutWithStorageTextureBindingType) {
// wgpu::BindingType::ReadonlyStorageTexture is a valid binding type to create a bind group
// layout.
{
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::Compute,
wgpu::BindingType::ReadonlyStorageTexture};
entry.storageTextureFormat = wgpu::TextureFormat::R32Float;
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::Compute;
entry.storageTexture.access = wgpu::StorageTextureAccess::ReadOnly;
entry.storageTexture.format = wgpu::TextureFormat::R32Float;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &entry;
@ -699,9 +701,11 @@ TEST_P(StorageTextureTests, BindGroupLayoutWithStorageTextureBindingType) {
// wgpu::BindingType::WriteonlyStorageTexture is a valid binding type to create a bind group
// layout.
{
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::Compute,
wgpu::BindingType::WriteonlyStorageTexture};
entry.storageTextureFormat = wgpu::TextureFormat::R32Float;
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::Compute;
entry.storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
entry.storageTexture.format = wgpu::TextureFormat::R32Float;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &entry;

View File

@ -345,10 +345,8 @@ TEST_F(BindGroupValidationTest, SamplingDepthStencilTexture) {
viewDesc.aspect = wgpu::TextureAspect::DepthOnly;
utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&viewDesc)}});
wgpu::BindGroupLayoutEntry entry = {0, wgpu::ShaderStage::Fragment,
wgpu::BindingType::SampledTexture};
entry.textureComponentType = wgpu::TextureComponentType::Uint;
layout = utils::MakeBindGroupLayout(device, {entry});
layout = utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Uint}});
viewDesc.aspect = wgpu::TextureAspect::StencilOnly;
utils::MakeBindGroup(device, layout, {{0, texture.CreateView(&viewDesc)}});
@ -645,16 +643,16 @@ class BindGroupLayoutValidationTest : public ValidationTest {
TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutStorageBindingsInVertexShader) {
// Checks that storage buffer binding is not supported in vertex shader.
ASSERT_DEVICE_ERROR(utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Vertex, wgpu::BindingType::StorageBuffer}}));
device, {{0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Storage}}));
utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Vertex, wgpu::BindingType::ReadonlyStorageBuffer}});
device, {{0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::ReadOnlyStorage}});
utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::StorageBuffer}});
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::Storage}});
utils::MakeBindGroupLayout(
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BindingType::ReadonlyStorageBuffer}});
device, {{0, wgpu::ShaderStage::Fragment, wgpu::BufferBindingType::ReadOnlyStorage}});
}
// Tests setting that bind group layout bindings numbers may be very large.
@ -710,11 +708,13 @@ TEST_F(BindGroupLayoutValidationTest, BindGroupLayoutVisibilityNone) {
{0, wgpu::ShaderStage::Vertex, wgpu::BindingType::UniformBuffer},
});
wgpu::BindGroupLayoutEntry binding = {0, wgpu::ShaderStage::None,
wgpu::BindingType::UniformBuffer};
wgpu::BindGroupLayoutEntry entry;
entry.binding = 0;
entry.visibility = wgpu::ShaderStage::None;
entry.buffer.type = wgpu::BufferBindingType::Uniform;
wgpu::BindGroupLayoutDescriptor descriptor;
descriptor.entryCount = 1;
descriptor.entries = &binding;
descriptor.entries = &entry;
device.CreateBindGroupLayout(&descriptor);
}
@ -761,9 +761,9 @@ TEST_F(BindGroupLayoutValidationTest, PerStageLimits) {
for (TestInfo info : kTestInfos) {
wgpu::BindGroupLayout bgl[2];
std::vector<wgpu::BindGroupLayoutEntry> maxBindings;
std::vector<utils::BindingLayoutEntryInitializationHelper> maxBindings;
auto PopulateEntry = [](wgpu::BindGroupLayoutEntry entry) {
auto PopulateEntry = [](utils::BindingLayoutEntryInitializationHelper entry) {
switch (entry.type) {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
@ -772,6 +772,7 @@ TEST_F(BindGroupLayoutValidationTest, PerStageLimits) {
default:
break;
}
return entry;
};
@ -784,7 +785,7 @@ TEST_F(BindGroupLayoutValidationTest, PerStageLimits) {
// Adding an extra binding of a different type works.
{
std::vector<wgpu::BindGroupLayoutEntry> bindings = maxBindings;
std::vector<utils::BindingLayoutEntryInitializationHelper> bindings = maxBindings;
bindings.push_back(
PopulateEntry({info.maxCount, wgpu::ShaderStage::Compute, info.otherBindingType}));
MakeBindGroupLayout(bindings.data(), bindings.size());
@ -792,7 +793,7 @@ TEST_F(BindGroupLayoutValidationTest, PerStageLimits) {
// Adding an extra binding of the maxed type in a different stage works
{
std::vector<wgpu::BindGroupLayoutEntry> bindings = maxBindings;
std::vector<utils::BindingLayoutEntryInitializationHelper> bindings = maxBindings;
bindings.push_back(
PopulateEntry({info.maxCount, wgpu::ShaderStage::Fragment, info.bindingType}));
MakeBindGroupLayout(bindings.data(), bindings.size());
@ -800,7 +801,7 @@ TEST_F(BindGroupLayoutValidationTest, PerStageLimits) {
// Adding an extra binding of the maxed type and stage exceeds the per stage limit.
{
std::vector<wgpu::BindGroupLayoutEntry> bindings = maxBindings;
std::vector<utils::BindingLayoutEntryInitializationHelper> bindings = maxBindings;
bindings.push_back(
PopulateEntry({info.maxCount, wgpu::ShaderStage::Compute, info.bindingType}));
ASSERT_DEVICE_ERROR(MakeBindGroupLayout(bindings.data(), bindings.size()));
@ -841,18 +842,18 @@ TEST_F(BindGroupLayoutValidationTest, DynamicBufferNumberLimit) {
"");
for (uint32_t i = 0; i < kMaxDynamicUniformBuffersPerPipelineLayout; ++i) {
maxUniformDB.push_back(
{i, wgpu::ShaderStage::Compute, wgpu::BindingType::UniformBuffer, true});
maxUniformDB.push_back(utils::BindingLayoutEntryInitializationHelper(
i, wgpu::ShaderStage::Compute, wgpu::BindingType::UniformBuffer, true));
}
for (uint32_t i = 0; i < kMaxDynamicStorageBuffersPerPipelineLayout; ++i) {
maxStorageDB.push_back(
{i, wgpu::ShaderStage::Compute, wgpu::BindingType::StorageBuffer, true});
maxStorageDB.push_back(utils::BindingLayoutEntryInitializationHelper(
i, wgpu::ShaderStage::Compute, wgpu::BindingType::StorageBuffer, true));
}
for (uint32_t i = 0; i < kMaxDynamicStorageBuffersPerPipelineLayout; ++i) {
maxReadonlyStorageDB.push_back(
{i, wgpu::ShaderStage::Compute, wgpu::BindingType::ReadonlyStorageBuffer, true});
maxReadonlyStorageDB.push_back(utils::BindingLayoutEntryInitializationHelper(
i, wgpu::ShaderStage::Compute, wgpu::BindingType::ReadonlyStorageBuffer, true));
}
// Test creating with the maxes works
@ -919,25 +920,25 @@ TEST_F(BindGroupLayoutValidationTest, DynamicBufferNumberLimit) {
// Check dynamic uniform buffers exceed maximum in bind group layout.
{
maxUniformDB.push_back({kMaxDynamicUniformBuffersPerPipelineLayout,
wgpu::ShaderStage::Fragment, wgpu::BindingType::UniformBuffer,
true});
maxUniformDB.push_back(utils::BindingLayoutEntryInitializationHelper(
kMaxDynamicUniformBuffersPerPipelineLayout, wgpu::ShaderStage::Fragment,
wgpu::BindingType::UniformBuffer, true));
TestCreateBindGroupLayout(maxUniformDB.data(), maxUniformDB.size(), false);
}
// Check dynamic storage buffers exceed maximum in bind group layout.
{
maxStorageDB.push_back({kMaxDynamicStorageBuffersPerPipelineLayout,
wgpu::ShaderStage::Fragment, wgpu::BindingType::StorageBuffer,
true});
maxStorageDB.push_back(utils::BindingLayoutEntryInitializationHelper(
kMaxDynamicStorageBuffersPerPipelineLayout, wgpu::ShaderStage::Fragment,
wgpu::BindingType::StorageBuffer, true));
TestCreateBindGroupLayout(maxStorageDB.data(), maxStorageDB.size(), false);
}
// Check dynamic readonly storage buffers exceed maximum in bind group layout.
{
maxReadonlyStorageDB.push_back({kMaxDynamicStorageBuffersPerPipelineLayout,
wgpu::ShaderStage::Fragment,
wgpu::BindingType::ReadonlyStorageBuffer, true});
maxReadonlyStorageDB.push_back(utils::BindingLayoutEntryInitializationHelper(
kMaxDynamicStorageBuffersPerPipelineLayout, wgpu::ShaderStage::Fragment,
wgpu::BindingType::ReadonlyStorageBuffer, true));
TestCreateBindGroupLayout(maxReadonlyStorageDB.data(), maxReadonlyStorageDB.size(), false);
}
}
@ -1491,7 +1492,8 @@ class SetBindGroupPersistenceValidationTest : public ValidationTest {
// Iterate through binding types and populate a list of BindGroupLayoutEntrys.
for (uint32_t b = 0; b < layout.size(); ++b) {
bindings[b] = {b, wgpu::ShaderStage::Fragment, layout[b], false};
bindings[b] = utils::BindingLayoutEntryInitializationHelper(
b, wgpu::ShaderStage::Fragment, layout[b], false);
}
// Create the bind group layout.

View File

@ -297,7 +297,8 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingTy
{wgpu::ShaderStage::Compute, wgpu::BindingType::WriteonlyStorageTexture, true}}};
for (const auto& testSpec : kTestSpecs) {
wgpu::BindGroupLayoutEntry entry = {0, testSpec.stage, testSpec.type};
wgpu::BindGroupLayoutEntry entry =
utils::BindingLayoutEntryInitializationHelper(0, testSpec.stage, testSpec.type);
entry.storageTextureFormat = wgpu::TextureFormat::R32Uint;
wgpu::BindGroupLayoutDescriptor descriptor;
@ -525,8 +526,8 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutStorageTextureFormatMatches
defaultComputePipelineDescriptor.computeStage.entryPoint = "main";
// Set common fileds of bind group layout binding.
wgpu::BindGroupLayoutEntry defaultBindGroupLayoutEntry = {0, wgpu::ShaderStage::Compute,
bindingType};
utils::BindingLayoutEntryInitializationHelper defaultBindGroupLayoutEntry = {
0, wgpu::ShaderStage::Compute, bindingType};
for (wgpu::TextureFormat storageTextureFormatInBindGroupLayout :
utils::kAllTextureFormats) {
@ -581,8 +582,8 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutViewDimensionMatchesShaderD
defaultComputePipelineDescriptor.computeStage.entryPoint = "main";
// Set common fileds of bind group layout binding.
wgpu::BindGroupLayoutEntry defaultBindGroupLayoutEntry = {0, wgpu::ShaderStage::Compute,
bindingType};
utils::BindingLayoutEntryInitializationHelper defaultBindGroupLayoutEntry = {
0, wgpu::ShaderStage::Compute, bindingType};
defaultBindGroupLayoutEntry.storageTextureFormat = kStorageTextureFormat;
for (wgpu::TextureViewDimension dimensionInBindGroupLayout : kSupportedDimensions) {

View File

@ -148,7 +148,6 @@ TEST_F(UnsafeAPIValidationTest, DispatchIndirectDisallowed) {
// Check that dynamic storage buffers are disallowed.
TEST_F(UnsafeAPIValidationTest, DynamicStorageBuffer) {
wgpu::BindGroupLayoutEntry entry;
entry.type = wgpu::BindingType::StorageBuffer;
entry.visibility = wgpu::ShaderStage::Fragment;
wgpu::BindGroupLayoutDescriptor desc;
@ -157,12 +156,28 @@ TEST_F(UnsafeAPIValidationTest, DynamicStorageBuffer) {
// Control case: storage buffer without a dynamic offset is allowed.
{
entry.type = wgpu::BindingType::StorageBuffer;
entry.hasDynamicOffset = false;
device.CreateBindGroupLayout(&desc);
}
// Control case: readonly storage buffer without a dynamic offset is allowed.
{
entry.type = wgpu::BindingType::ReadonlyStorageBuffer;
entry.hasDynamicOffset = false;
device.CreateBindGroupLayout(&desc);
}
// Control case: storage buffer with a dynamic offset is disallowed.
{
entry.type = wgpu::BindingType::StorageBuffer;
entry.hasDynamicOffset = true;
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
}
// Control case: readonly storage buffer with a dynamic offset is disallowed.
{
entry.type = wgpu::BindingType::ReadonlyStorageBuffer;
entry.hasDynamicOffset = true;
ASSERT_DEVICE_ERROR(device.CreateBindGroupLayout(&desc));
}

View File

@ -307,13 +307,42 @@ TEST_F(WireArgumentTests, StructureOfObjectArrayArgument) {
TEST_F(WireArgumentTests, StructureOfStructureArrayArgument) {
static constexpr int NUM_BINDINGS = 3;
WGPUBindGroupLayoutEntry entries[NUM_BINDINGS]{
{0, WGPUShaderStage_Vertex, WGPUBindingType_Sampler, false, 0, WGPUTextureViewDimension_2D,
WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
{1, WGPUShaderStage_Vertex, WGPUBindingType_SampledTexture, false, 0,
WGPUTextureViewDimension_2D, WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
{2, static_cast<WGPUShaderStage>(WGPUShaderStage_Vertex | WGPUShaderStage_Fragment),
WGPUBindingType_UniformBuffer, false, 0, WGPUTextureViewDimension_2D,
WGPUTextureComponentType_Float, WGPUTextureFormat_RGBA8Unorm},
{0,
WGPUShaderStage_Vertex,
WGPUBindingType_Sampler,
false,
0,
WGPUTextureViewDimension_2D,
WGPUTextureComponentType_Float,
WGPUTextureFormat_RGBA8Unorm,
{},
{},
{},
{}},
{1,
WGPUShaderStage_Vertex,
WGPUBindingType_SampledTexture,
false,
0,
WGPUTextureViewDimension_2D,
WGPUTextureComponentType_Float,
WGPUTextureFormat_RGBA8Unorm,
{},
{},
{},
{}},
{2,
static_cast<WGPUShaderStage>(WGPUShaderStage_Vertex | WGPUShaderStage_Fragment),
WGPUBindingType_UniformBuffer,
false,
0,
WGPUTextureViewDimension_2D,
WGPUTextureComponentType_Float,
WGPUTextureFormat_RGBA8Unorm,
{},
{},
{},
{}},
};
WGPUBindGroupLayoutDescriptor bglDescriptor = {};
bglDescriptor.entryCount = NUM_BINDINGS;

View File

@ -331,9 +331,9 @@ namespace utils {
wgpu::BindGroupLayout MakeBindGroupLayout(
const wgpu::Device& device,
std::initializer_list<wgpu::BindGroupLayoutEntry> entriesInitializer) {
std::initializer_list<BindingLayoutEntryInitializationHelper> entriesInitializer) {
std::vector<wgpu::BindGroupLayoutEntry> entries;
for (const wgpu::BindGroupLayoutEntry& entry : entriesInitializer) {
for (const BindingLayoutEntryInitializationHelper& entry : entriesInitializer) {
entries.push_back(entry);
}
@ -343,6 +343,78 @@ namespace utils {
return device.CreateBindGroupLayout(&descriptor);
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::BufferBindingType bufferType,
bool bufferHasDynamicOffset,
uint64_t bufferMinBindingSize) {
binding = entryBinding;
visibility = entryVisibility;
buffer.type = bufferType;
buffer.hasDynamicOffset = bufferHasDynamicOffset;
buffer.minBindingSize = bufferMinBindingSize;
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::SamplerBindingType samplerType) {
binding = entryBinding;
visibility = entryVisibility;
sampler.type = samplerType;
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::TextureSampleType textureSampleType,
wgpu::TextureViewDimension textureViewDimension,
bool textureMultisampled) {
binding = entryBinding;
visibility = entryVisibility;
texture.sampleType = textureSampleType;
texture.viewDimension = textureViewDimension;
texture.multisampled = textureMultisampled;
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::StorageTextureAccess storageTextureAccess,
wgpu::TextureFormat format,
wgpu::TextureViewDimension textureViewDimension) {
binding = entryBinding;
visibility = entryVisibility;
storageTexture.access = storageTextureAccess;
storageTexture.format = format;
storageTexture.viewDimension = textureViewDimension;
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::BindingType entryType,
bool bufferHasDynamicOffset,
uint64_t bufferMinBindingSize,
wgpu::TextureViewDimension textureViewDimension,
wgpu::TextureComponentType textureComponent,
wgpu::TextureFormat storageFormat) {
binding = entryBinding;
visibility = entryVisibility;
type = entryType;
hasDynamicOffset = bufferHasDynamicOffset;
minBufferBindingSize = bufferMinBindingSize;
viewDimension = textureViewDimension;
textureComponentType = textureComponent;
storageTextureFormat = storageFormat;
}
BindingLayoutEntryInitializationHelper::BindingLayoutEntryInitializationHelper(
const wgpu::BindGroupLayoutEntry& entry)
: wgpu::BindGroupLayoutEntry(entry) {
}
BindingInitializationHelper::BindingInitializationHelper(uint32_t binding,
const wgpu::Sampler& sampler)
: binding(binding), sampler(sampler) {

View File

@ -100,9 +100,53 @@ namespace utils {
wgpu::SamplerDescriptor GetDefaultSamplerDescriptor();
wgpu::PipelineLayout MakeBasicPipelineLayout(const wgpu::Device& device,
const wgpu::BindGroupLayout* bindGroupLayout);
// Helpers to make creating bind group layouts look nicer:
//
// utils::MakeBindGroupLayout(device, {
// {0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform},
// {1, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::Filtering},
// {3, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Float}
// });
struct BindingLayoutEntryInitializationHelper : wgpu::BindGroupLayoutEntry {
BindingLayoutEntryInitializationHelper(uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::BufferBindingType bufferType,
bool bufferHasDynamicOffset = false,
uint64_t bufferMinBindingSize = 0);
BindingLayoutEntryInitializationHelper(uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::SamplerBindingType samplerType);
BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::TextureSampleType textureSampleType,
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D,
bool textureMultisampled = false);
BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::StorageTextureAccess storageTextureAccess,
wgpu::TextureFormat format,
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::e2D);
// Backwards compat support for the deprecated path
BindingLayoutEntryInitializationHelper(
uint32_t entryBinding,
wgpu::ShaderStage entryVisibility,
wgpu::BindingType entryType,
bool bufferHasDynamicOffset = false,
uint64_t bufferMinBindingSize = 0,
wgpu::TextureViewDimension textureViewDimension = wgpu::TextureViewDimension::Undefined,
wgpu::TextureComponentType textureComponent = wgpu::TextureComponentType::Float,
wgpu::TextureFormat storageFormat = wgpu::TextureFormat::Undefined);
BindingLayoutEntryInitializationHelper(const wgpu::BindGroupLayoutEntry& entry);
};
wgpu::BindGroupLayout MakeBindGroupLayout(
const wgpu::Device& device,
std::initializer_list<wgpu::BindGroupLayoutEntry> entriesInitializer);
std::initializer_list<BindingLayoutEntryInitializationHelper> entriesInitializer);
// Helpers to make creating bind groups look nicer:
//