Update BindingInfo to reflect new BindGroupLayoutEntry structure

Changes the internal BindingInfo structure and any references to it. The
BindGroupLayoutEntry information is normalized when converting it into
the internal representation, but still accepted as either the old or
new layout. A "bindingType" member is added to the BindingInfo that's
not present in the BindGroupLayoutEntry itself to indicate which of
buffer, sampler, texture, or storageTexture is populated. This proves
useful for a myriad of switch statements in the various backends.

Bug: dawn:527
Change-Id: I6ae65adae61d0005fc50ed6d1bc2ec9b2a1295ad
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/35862
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Auto-Submit: Brandon Jones <bajones@chromium.org>
This commit is contained in:
Brandon Jones 2020-12-21 20:14:26 +00:00 committed by Commit Bot service account
parent ec56b90cea
commit 3af532b8a8
29 changed files with 812 additions and 778 deletions

View File

@ -31,15 +31,31 @@ namespace dawn_native {
MaybeError ValidateBufferBinding(const DeviceBase* device,
const BindGroupEntry& entry,
wgpu::BufferUsage requiredUsage,
const BindingInfo& bindingInfo,
const uint64_t maxBindingSize) {
const BindingInfo& bindingInfo) {
if (entry.buffer == nullptr || entry.sampler != nullptr ||
entry.textureView != nullptr) {
return DAWN_VALIDATION_ERROR("Expected buffer binding");
}
DAWN_TRY(device->ValidateObject(entry.buffer));
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
wgpu::BufferUsage requiredUsage;
uint64_t maxBindingSize;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
requiredUsage = wgpu::BufferUsage::Uniform;
maxBindingSize = kMaxUniformBufferBindingSize;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
requiredUsage = wgpu::BufferUsage::Storage;
maxBindingSize = std::numeric_limits<uint64_t>::max();
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
uint64_t bufferSize = entry.buffer->GetSize();
// Handle wgpu::WholeSize, avoiding overflows.
@ -72,11 +88,11 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("buffer binding usage mismatch");
}
if (bindingSize < bindingInfo.minBufferBindingSize) {
if (bindingSize < bindingInfo.buffer.minBindingSize) {
return DAWN_VALIDATION_ERROR(
"Binding size smaller than minimum buffer size: binding " +
std::to_string(entry.binding) + " given " + std::to_string(bindingSize) +
" bytes, required " + std::to_string(bindingInfo.minBufferBindingSize) +
" bytes, required " + std::to_string(bindingInfo.buffer.minBindingSize) +
" bytes");
}
@ -93,8 +109,6 @@ namespace dawn_native {
MaybeError ValidateTextureBinding(const DeviceBase* device,
const BindGroupEntry& entry,
wgpu::TextureUsage requiredUsage,
bool multisampled,
const BindingInfo& bindingInfo) {
if (entry.textureView == nullptr || entry.sampler != nullptr ||
entry.buffer != nullptr) {
@ -110,30 +124,44 @@ namespace dawn_native {
}
TextureBase* texture = view->GetTexture();
if (!(texture->GetUsage() & requiredUsage)) {
return DAWN_VALIDATION_ERROR("Texture binding usage mismatch");
}
if (texture->IsMultisampledTexture() != multisampled) {
return DAWN_VALIDATION_ERROR("Texture multisampling mismatch");
}
switch (requiredUsage) {
case wgpu::TextureUsage::Sampled: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Texture: {
ComponentTypeBit supportedTypes =
texture->GetFormat().GetAspectInfo(aspect).supportedComponentTypes;
ComponentTypeBit requiredType =
ToComponentTypeBit(bindingInfo.textureComponentType);
SampleTypeToComponentTypeBit(bindingInfo.texture.sampleType);
if (!(texture->GetUsage() & wgpu::TextureUsage::Sampled)) {
return DAWN_VALIDATION_ERROR("Texture binding usage mismatch");
}
if (texture->IsMultisampledTexture() != bindingInfo.texture.multisampled) {
return DAWN_VALIDATION_ERROR("Texture multisampling mismatch");
}
if ((supportedTypes & requiredType) == 0) {
return DAWN_VALIDATION_ERROR("Texture component type usage mismatch");
}
if (entry.textureView->GetDimension() != bindingInfo.texture.viewDimension) {
return DAWN_VALIDATION_ERROR("Texture view dimension mismatch");
}
break;
}
case wgpu::TextureUsage::Storage: {
if (texture->GetFormat().format != bindingInfo.storageTextureFormat) {
case BindingInfoType::StorageTexture: {
ASSERT(!texture->IsMultisampledTexture());
if (!(texture->GetUsage() & wgpu::TextureUsage::Storage)) {
return DAWN_VALIDATION_ERROR("Storage Texture binding usage mismatch");
}
if (texture->GetFormat().format != bindingInfo.storageTexture.format) {
return DAWN_VALIDATION_ERROR("Storage texture format mismatch");
}
if (entry.textureView->GetDimension() !=
bindingInfo.storageTexture.viewDimension) {
return DAWN_VALIDATION_ERROR("Storage texture view dimension mismatch");
}
break;
}
default:
@ -141,29 +169,28 @@ namespace dawn_native {
break;
}
if (entry.textureView->GetDimension() != bindingInfo.viewDimension) {
return DAWN_VALIDATION_ERROR("Texture view dimension mismatch");
}
return {};
}
MaybeError ValidateSamplerBinding(const DeviceBase* device,
const BindGroupEntry& entry,
wgpu::BindingType bindingType) {
const BindingInfo& bindingInfo) {
if (entry.sampler == nullptr || entry.textureView != nullptr ||
entry.buffer != nullptr) {
return DAWN_VALIDATION_ERROR("Expected sampler binding");
}
DAWN_TRY(device->ValidateObject(entry.sampler));
switch (bindingType) {
case wgpu::BindingType::Sampler:
ASSERT(bindingInfo.bindingType == BindingInfoType::Sampler);
switch (bindingInfo.sampler.type) {
case wgpu::SamplerBindingType::Filtering:
case wgpu::SamplerBindingType::NonFiltering:
if (entry.sampler->HasCompareFunction()) {
return DAWN_VALIDATION_ERROR("Did not expect comparison sampler");
}
break;
case wgpu::BindingType::ComparisonSampler:
case wgpu::SamplerBindingType::Comparison:
if (!entry.sampler->HasCompareFunction()) {
return DAWN_VALIDATION_ERROR("Expected comparison sampler");
}
@ -212,36 +239,16 @@ namespace dawn_native {
const BindingInfo& bindingInfo = descriptor->layout->GetBindingInfo(bindingIndex);
// Perform binding-type specific validation.
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
DAWN_TRY(ValidateBufferBinding(device, entry, wgpu::BufferUsage::Uniform,
bindingInfo, kMaxUniformBufferBindingSize));
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
DAWN_TRY(ValidateBufferBinding(device, entry, bindingInfo));
break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
DAWN_TRY(ValidateBufferBinding(device, entry, wgpu::BufferUsage::Storage,
bindingInfo,
std::numeric_limits<uint64_t>::max()));
case BindingInfoType::Texture:
case BindingInfoType::StorageTexture:
DAWN_TRY(ValidateTextureBinding(device, entry, bindingInfo));
break;
case wgpu::BindingType::SampledTexture:
DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Sampled,
false, bindingInfo));
break;
case wgpu::BindingType::MultisampledTexture:
DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Sampled,
true, bindingInfo));
break;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
DAWN_TRY(ValidateSamplerBinding(device, entry, bindingInfo.type));
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
DAWN_TRY(ValidateTextureBinding(device, entry, wgpu::TextureUsage::Storage,
false, bindingInfo));
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
case BindingInfoType::Sampler:
DAWN_TRY(ValidateSamplerBinding(device, entry, bindingInfo));
break;
}
}
@ -307,7 +314,7 @@ namespace dawn_native {
uint32_t packedIdx = 0;
for (BindingIndex bindingIndex{0}; bindingIndex < descriptor->layout->GetBufferCount();
++bindingIndex) {
if (descriptor->layout->GetBindingInfo(bindingIndex).minBufferBindingSize == 0) {
if (descriptor->layout->GetBindingInfo(bindingIndex).buffer.minBindingSize == 0) {
mBindingData.unverifiedBufferSizes[packedIdx] =
mBindingData.bufferData[bindingIndex].size;
++packedIdx;
@ -359,10 +366,7 @@ namespace dawn_native {
BufferBinding BindGroupBase::GetBindingAsBufferBinding(BindingIndex bindingIndex) {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::UniformBuffer ||
mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::StorageBuffer ||
mLayout->GetBindingInfo(bindingIndex).type ==
wgpu::BindingType::ReadonlyStorageBuffer);
ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Buffer);
BufferBase* buffer = static_cast<BufferBase*>(mBindingData.bindings[bindingIndex].Get());
return {buffer, mBindingData.bufferData[bindingIndex].offset,
mBindingData.bufferData[bindingIndex].size};
@ -371,21 +375,16 @@ namespace dawn_native {
SamplerBase* BindGroupBase::GetBindingAsSampler(BindingIndex bindingIndex) const {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::Sampler ||
mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::ComparisonSampler);
ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Sampler);
return static_cast<SamplerBase*>(mBindingData.bindings[bindingIndex].Get());
}
TextureViewBase* BindGroupBase::GetBindingAsTextureView(BindingIndex bindingIndex) {
ASSERT(!IsError());
ASSERT(bindingIndex < mLayout->GetBindingCount());
ASSERT(mLayout->GetBindingInfo(bindingIndex).type == wgpu::BindingType::SampledTexture ||
mLayout->GetBindingInfo(bindingIndex).type ==
wgpu::BindingType::MultisampledTexture ||
mLayout->GetBindingInfo(bindingIndex).type ==
wgpu::BindingType::ReadonlyStorageTexture ||
mLayout->GetBindingInfo(bindingIndex).type ==
wgpu::BindingType::WriteonlyStorageTexture);
ASSERT(mLayout->GetBindingInfo(bindingIndex).bindingType == BindingInfoType::Texture ||
mLayout->GetBindingInfo(bindingIndex).bindingType ==
BindingInfoType::StorageTexture);
return static_cast<TextureViewBase*>(mBindingData.bindings[bindingIndex].Get());
}

View File

@ -248,17 +248,43 @@ namespace dawn_native {
bool operator!=(const BindingInfo& a, const BindingInfo& b) {
return a.hasDynamicOffset != b.hasDynamicOffset || //
a.visibility != b.visibility || //
a.type != b.type || //
a.textureComponentType != b.textureComponentType || //
a.viewDimension != b.viewDimension || //
a.storageTextureFormat != b.storageTextureFormat || //
a.minBufferBindingSize != b.minBufferBindingSize;
if (a.visibility != b.visibility || a.bindingType != b.bindingType) {
return true;
}
switch (a.bindingType) {
case BindingInfoType::Buffer:
return a.buffer.type != b.buffer.type ||
a.buffer.hasDynamicOffset != b.buffer.hasDynamicOffset ||
a.buffer.minBindingSize != b.buffer.minBindingSize;
case BindingInfoType::Sampler:
return a.sampler.type != b.sampler.type;
case BindingInfoType::Texture:
return a.texture.sampleType != b.texture.sampleType ||
a.texture.viewDimension != b.texture.viewDimension ||
a.texture.multisampled != b.texture.multisampled;
case BindingInfoType::StorageTexture:
return a.storageTexture.access != b.storageTexture.access ||
a.storageTexture.viewDimension != b.storageTexture.viewDimension ||
a.storageTexture.format != b.storageTexture.format;
}
}
bool IsBufferBindingType(wgpu::BindingType type) {
switch (type) {
// TODO(dawn:527): Once the deprecated BindGroupLayoutEntry path has been removed, this can
// turn into a simple `binding.buffer.type != wgpu::BufferBindingType::Undefined` check.
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;
}
// Deprecated path
switch (binding.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
@ -274,20 +300,6 @@ namespace dawn_native {
}
}
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;
@ -357,7 +369,7 @@ namespace dawn_native {
BindingIndex lastBufferIndex{0};
BindingIndex firstNonBufferIndex = std::numeric_limits<BindingIndex>::max();
for (BindingIndex i{0}; i < bindings.size(); ++i) {
if (IsBufferBindingType(bindings[i].type)) {
if (bindings[i].bindingType == BindingInfoType::Buffer) {
lastBufferIndex = std::max(i, lastBufferIndex);
} else {
firstNonBufferIndex = std::min(i, firstNonBufferIndex);
@ -369,6 +381,120 @@ namespace dawn_native {
return firstNonBufferIndex >= lastBufferIndex;
}
BindingInfo CreateBindGroupLayoutInfo(const BindGroupLayoutEntry& binding) {
BindingInfo bindingInfo;
bindingInfo.binding = BindingNumber(binding.binding);
bindingInfo.visibility = binding.visibility;
if (binding.buffer.type != wgpu::BufferBindingType::Undefined) {
bindingInfo.bindingType = BindingInfoType::Buffer;
bindingInfo.buffer = binding.buffer;
} else if (binding.sampler.type != wgpu::SamplerBindingType::Undefined) {
bindingInfo.bindingType = BindingInfoType::Sampler;
bindingInfo.sampler = binding.sampler;
} else if (binding.texture.sampleType != wgpu::TextureSampleType::Undefined) {
bindingInfo.bindingType = BindingInfoType::Texture;
bindingInfo.texture = binding.texture;
if (binding.texture.viewDimension == wgpu::TextureViewDimension::Undefined) {
bindingInfo.texture.viewDimension = wgpu::TextureViewDimension::e2D;
}
} else if (binding.storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
bindingInfo.bindingType = BindingInfoType::StorageTexture;
bindingInfo.storageTexture = binding.storageTexture;
if (binding.storageTexture.viewDimension == wgpu::TextureViewDimension::Undefined) {
bindingInfo.storageTexture.viewDimension = wgpu::TextureViewDimension::e2D;
}
} else {
// Deprecated entry layout.
switch (binding.type) {
case wgpu::BindingType::UniformBuffer:
bindingInfo.bindingType = BindingInfoType::Buffer;
bindingInfo.buffer.type = wgpu::BufferBindingType::Uniform;
bindingInfo.buffer.hasDynamicOffset = binding.hasDynamicOffset;
bindingInfo.buffer.minBindingSize = binding.minBufferBindingSize;
break;
case wgpu::BindingType::StorageBuffer:
bindingInfo.bindingType = BindingInfoType::Buffer;
bindingInfo.buffer.type = wgpu::BufferBindingType::Storage;
bindingInfo.buffer.hasDynamicOffset = binding.hasDynamicOffset;
bindingInfo.buffer.minBindingSize = binding.minBufferBindingSize;
break;
case wgpu::BindingType::ReadonlyStorageBuffer:
bindingInfo.bindingType = BindingInfoType::Buffer;
bindingInfo.buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
bindingInfo.buffer.hasDynamicOffset = binding.hasDynamicOffset;
bindingInfo.buffer.minBindingSize = binding.minBufferBindingSize;
break;
case wgpu::BindingType::Sampler:
bindingInfo.bindingType = BindingInfoType::Sampler;
bindingInfo.sampler.type = wgpu::SamplerBindingType::Filtering;
break;
case wgpu::BindingType::ComparisonSampler:
bindingInfo.bindingType = BindingInfoType::Sampler;
bindingInfo.sampler.type = wgpu::SamplerBindingType::Comparison;
break;
case wgpu::BindingType::MultisampledTexture:
bindingInfo.texture.multisampled = true;
DAWN_FALLTHROUGH;
case wgpu::BindingType::SampledTexture:
bindingInfo.bindingType = BindingInfoType::Texture;
bindingInfo.texture.viewDimension = binding.viewDimension;
if (binding.texture.viewDimension ==
wgpu::TextureViewDimension::Undefined) {
bindingInfo.texture.viewDimension = wgpu::TextureViewDimension::e2D;
}
switch (binding.textureComponentType) {
case wgpu::TextureComponentType::Float:
bindingInfo.texture.sampleType = wgpu::TextureSampleType::Float;
break;
case wgpu::TextureComponentType::Uint:
bindingInfo.texture.sampleType = wgpu::TextureSampleType::Uint;
break;
case wgpu::TextureComponentType::Sint:
bindingInfo.texture.sampleType = wgpu::TextureSampleType::Sint;
break;
case wgpu::TextureComponentType::DepthComparison:
bindingInfo.texture.sampleType = wgpu::TextureSampleType::Depth;
break;
}
break;
case wgpu::BindingType::ReadonlyStorageTexture:
bindingInfo.bindingType = BindingInfoType::StorageTexture;
bindingInfo.storageTexture.access = wgpu::StorageTextureAccess::ReadOnly;
bindingInfo.storageTexture.format = binding.storageTextureFormat;
bindingInfo.storageTexture.viewDimension = binding.viewDimension;
if (binding.storageTexture.viewDimension ==
wgpu::TextureViewDimension::Undefined) {
bindingInfo.storageTexture.viewDimension =
wgpu::TextureViewDimension::e2D;
}
break;
case wgpu::BindingType::WriteonlyStorageTexture:
bindingInfo.bindingType = BindingInfoType::StorageTexture;
bindingInfo.storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
bindingInfo.storageTexture.format = binding.storageTextureFormat;
bindingInfo.storageTexture.viewDimension = binding.viewDimension;
if (binding.storageTexture.viewDimension ==
wgpu::TextureViewDimension::Undefined) {
bindingInfo.storageTexture.viewDimension =
wgpu::TextureViewDimension::e2D;
}
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
return bindingInfo;
}
} // namespace
// BindGroupLayoutBase
@ -384,106 +510,7 @@ namespace dawn_native {
for (BindingIndex i{0}; i < mBindingInfo.size(); ++i) {
const BindGroupLayoutEntry& binding = sortedBindings[static_cast<uint32_t>(i)];
// 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 {
// 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] = CreateBindGroupLayoutInfo(binding);
if (IsBufferBinding(binding)) {
// Buffers must be contiguously packed at the start of the binding info.
@ -534,9 +561,12 @@ namespace dawn_native {
recorder.Record(it.first, it.second);
const BindingInfo& info = mBindingInfo[it.second];
recorder.Record(info.hasDynamicOffset, info.visibility, info.type,
info.textureComponentType, info.viewDimension,
info.storageTextureFormat, info.minBufferBindingSize);
recorder.Record(info.buffer.hasDynamicOffset, info.visibility, info.bindingType,
info.buffer.type, info.buffer.minBindingSize, info.sampler.type,
info.texture.sampleType, info.texture.viewDimension,
info.texture.multisampled, info.storageTexture.access,
info.storageTexture.format, info.storageTexture.viewDimension);
}
return recorder.GetContentHash();

View File

@ -48,15 +48,24 @@ namespace dawn_native {
// TODO(enga): Figure out a good number for this.
static constexpr uint32_t kMaxOptimalBindingsPerGroup = 32;
enum class BindingInfoType {
Buffer,
Sampler,
Texture,
StorageTexture,
};
struct BindingInfo {
BindingNumber binding;
wgpu::ShaderStage visibility;
wgpu::BindingType type;
wgpu::TextureComponentType textureComponentType = wgpu::TextureComponentType::Float;
wgpu::TextureViewDimension viewDimension = wgpu::TextureViewDimension::Undefined;
wgpu::TextureFormat storageTextureFormat = wgpu::TextureFormat::Undefined;
bool hasDynamicOffset = false;
uint64_t minBufferBindingSize = 0;
BindingInfoType bindingType;
// TODO(dawn:527): These four values could be made into a union.
BufferBindingLayout buffer;
SamplerBindingLayout sampler;
TextureBindingLayout texture;
StorageTextureBindingLayout storageTexture;
};
struct PerStageBindingCounts {

View File

@ -31,6 +31,7 @@ namespace dawn_native {
// Format
// TODO(dawn:527): Remove when unused.
ComponentTypeBit ToComponentTypeBit(wgpu::TextureComponentType type) {
switch (type) {
case wgpu::TextureComponentType::Float:
@ -64,6 +65,24 @@ namespace dawn_native {
return static_cast<ComponentTypeBit>(1 << static_cast<uint32_t>(type));
}
ComponentTypeBit SampleTypeToComponentTypeBit(wgpu::TextureSampleType sampleType) {
switch (sampleType) {
case wgpu::TextureSampleType::Float:
case wgpu::TextureSampleType::UnfilterableFloat:
return ComponentTypeBit::Float;
case wgpu::TextureSampleType::Sint:
return ComponentTypeBit::Sint;
case wgpu::TextureSampleType::Uint:
return ComponentTypeBit::Uint;
case wgpu::TextureSampleType::Depth:
return ComponentTypeBit::DepthComparison;
case wgpu::TextureSampleType::Undefined:
UNREACHABLE();
}
// TODO(dawn:527): Ideally we can get this path to use that static_cast method as well.
}
bool Format::IsColor() const {
return aspects == Aspect::Color;
}

View File

@ -39,6 +39,8 @@ namespace dawn_native {
// Converts an wgpu::TextureComponentType to its bitmask representation.
ComponentTypeBit ToComponentTypeBit(wgpu::TextureComponentType type);
// Converts an wgpu::TextureSampleType to its bitmask representation.
ComponentTypeBit SampleTypeToComponentTypeBit(wgpu::TextureSampleType sampleType);
struct TexelBlockInfo {
uint32_t byteSize;

View File

@ -83,14 +83,34 @@ namespace dawn_native {
// Merges two entries at the same location, if they are allowed to be merged.
auto MergeEntries = [](BindGroupLayoutEntry* modifiedEntry,
const BindGroupLayoutEntry& mergedEntry) -> MaybeError {
// Minimum buffer binding size excluded because we take the maximum seen across stages.
// Visibility is excluded because we take the OR across stages.
bool compatible =
modifiedEntry->binding == mergedEntry.binding && //
modifiedEntry->type == mergedEntry.type && //
modifiedEntry->hasDynamicOffset == mergedEntry.hasDynamicOffset && //
modifiedEntry->viewDimension == mergedEntry.viewDimension && //
modifiedEntry->textureComponentType == mergedEntry.textureComponentType;
modifiedEntry->binding == mergedEntry.binding &&
modifiedEntry->buffer.type == mergedEntry.buffer.type &&
modifiedEntry->sampler.type == mergedEntry.sampler.type &&
modifiedEntry->texture.sampleType == mergedEntry.texture.sampleType &&
modifiedEntry->storageTexture.access == mergedEntry.storageTexture.access;
// Minimum buffer binding size excluded because we take the maximum seen across stages.
if (modifiedEntry->buffer.type != wgpu::BufferBindingType::Undefined) {
compatible = compatible && modifiedEntry->buffer.hasDynamicOffset ==
mergedEntry.buffer.hasDynamicOffset;
}
if (modifiedEntry->texture.sampleType != wgpu::TextureSampleType::Undefined) {
compatible =
compatible &&
modifiedEntry->texture.viewDimension == mergedEntry.texture.viewDimension &&
modifiedEntry->texture.multisampled == mergedEntry.texture.multisampled;
}
if (modifiedEntry->storageTexture.access != wgpu::StorageTextureAccess::Undefined) {
compatible =
compatible &&
modifiedEntry->storageTexture.format == mergedEntry.storageTexture.format &&
modifiedEntry->storageTexture.viewDimension ==
mergedEntry.storageTexture.viewDimension;
}
// Check if any properties are incompatible with existing entry
// If compatible, we will merge some properties
@ -101,8 +121,8 @@ namespace dawn_native {
}
// Use the max |minBufferBindingSize| we find.
modifiedEntry->minBufferBindingSize =
std::max(modifiedEntry->minBufferBindingSize, mergedEntry.minBufferBindingSize);
modifiedEntry->buffer.minBindingSize =
std::max(modifiedEntry->buffer.minBindingSize, mergedEntry.buffer.minBindingSize);
// Use the OR of all the stages at which we find this binding.
modifiedEntry->visibility |= mergedEntry.visibility;
@ -114,12 +134,20 @@ namespace dawn_native {
auto ConvertMetadataToEntry =
[](const EntryPointMetadata::ShaderBindingInfo& shaderBinding) -> BindGroupLayoutEntry {
BindGroupLayoutEntry entry = {};
entry.type = shaderBinding.type;
entry.hasDynamicOffset = false;
entry.viewDimension = shaderBinding.viewDimension;
entry.textureComponentType = shaderBinding.textureComponentType;
entry.storageTextureFormat = shaderBinding.storageTextureFormat;
entry.minBufferBindingSize = shaderBinding.minBufferBindingSize;
switch (shaderBinding.bindingType) {
case BindingInfoType::Buffer:
entry.buffer = shaderBinding.buffer;
break;
case BindingInfoType::Sampler:
entry.sampler = shaderBinding.sampler;
break;
case BindingInfoType::Texture:
entry.texture = shaderBinding.texture;
break;
case BindingInfoType::StorageTexture:
entry.storageTexture = shaderBinding.storageTexture;
break;
}
return entry;
};

View File

@ -32,52 +32,50 @@ namespace dawn_native {
BindGroupBase* group) {
for (BindingIndex bindingIndex{0}; bindingIndex < group->GetLayout()->GetBindingCount();
++bindingIndex) {
wgpu::BindingType type = group->GetLayout()->GetBindingInfo(bindingIndex).type;
const BindingInfo& bindingInfo = group->GetLayout()->GetBindingInfo(bindingIndex);
switch (type) {
case wgpu::BindingType::UniformBuffer: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(bindingIndex).buffer;
usageTracker->BufferUsedAs(buffer, wgpu::BufferUsage::Uniform);
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
usageTracker->BufferUsedAs(buffer, wgpu::BufferUsage::Uniform);
break;
case wgpu::BufferBindingType::Storage:
usageTracker->BufferUsedAs(buffer, wgpu::BufferUsage::Storage);
break;
case wgpu::BufferBindingType::ReadOnlyStorage:
usageTracker->BufferUsedAs(buffer, kReadOnlyStorageBuffer);
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
break;
}
case wgpu::BindingType::StorageBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(bindingIndex).buffer;
usageTracker->BufferUsedAs(buffer, wgpu::BufferUsage::Storage);
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
case BindingInfoType::Texture: {
TextureViewBase* view = group->GetBindingAsTextureView(bindingIndex);
usageTracker->TextureViewUsedAs(view, wgpu::TextureUsage::Sampled);
break;
}
case wgpu::BindingType::ReadonlyStorageBuffer: {
BufferBase* buffer = group->GetBindingAsBufferBinding(bindingIndex).buffer;
usageTracker->BufferUsedAs(buffer, kReadOnlyStorageBuffer);
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::ReadonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
TextureViewBase* view = group->GetBindingAsTextureView(bindingIndex);
usageTracker->TextureViewUsedAs(view, kReadonlyStorageTexture);
switch (bindingInfo.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly:
usageTracker->TextureViewUsedAs(view, kReadonlyStorageTexture);
break;
case wgpu::StorageTextureAccess::WriteOnly:
usageTracker->TextureViewUsedAs(view, wgpu::TextureUsage::Storage);
break;
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
break;
}
case wgpu::BindingType::WriteonlyStorageTexture: {
TextureViewBase* view = group->GetBindingAsTextureView(bindingIndex);
usageTracker->TextureViewUsedAs(view, wgpu::TextureUsage::Storage);
case BindingInfoType::Sampler:
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}
@ -158,16 +156,8 @@ namespace dawn_native {
// BGL creation sorts bindings such that the dynamic buffer bindings are first.
// ASSERT that this true.
ASSERT(bindingInfo.hasDynamicOffset);
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
break;
default:
UNREACHABLE();
break;
}
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
ASSERT(bindingInfo.buffer.hasDynamicOffset);
if (dynamicOffsets[i] % kMinDynamicBufferOffsetAlignment != 0) {
return DAWN_VALIDATION_ERROR("Dynamic Buffer Offset need to be aligned");

View File

@ -261,7 +261,7 @@ namespace dawn_native {
for (BindingIndex bindingIndex{0}; bindingIndex < layout->GetBufferCount();
++bindingIndex) {
const BindingInfo& bindingInfo = layout->GetBindingInfo(bindingIndex);
if (bindingInfo.minBufferBindingSize != 0) {
if (bindingInfo.buffer.minBindingSize != 0) {
// Skip bindings that have minimum buffer size set in the layout
continue;
}
@ -269,7 +269,7 @@ namespace dawn_native {
ASSERT(packedIdx < requiredBufferSizes.size());
const auto& shaderInfo = shaderBindings.find(bindingInfo.binding);
if (shaderInfo != shaderBindings.end()) {
requiredBufferSizes[packedIdx] = shaderInfo->second.minBufferBindingSize;
requiredBufferSizes[packedIdx] = shaderInfo->second.buffer.minBindingSize;
} else {
// We have to include buffers if they are included in the bind group's
// packed vector. We don't actually need to check these at draw time, so
@ -340,30 +340,10 @@ namespace dawn_native {
BindingIndex bindingIndex(bindingIt->second);
const BindingInfo& layoutInfo = layout->GetBindingInfo(bindingIndex);
if (layoutInfo.type != shaderInfo.type) {
// Binding mismatch between shader and bind group is invalid. For example, a
// writable binding in the shader with a readonly storage buffer in the bind
// group layout is invalid. However, a readonly binding in the shader with a
// writable storage buffer in the bind group layout is valid.
bool validBindingConversion =
layoutInfo.type == wgpu::BindingType::StorageBuffer &&
shaderInfo.type == wgpu::BindingType::ReadonlyStorageBuffer;
// TODO(crbug.com/dawn/367): Temporarily allow using either a sampler or a
// comparison sampler until we can perform the proper shader analysis of what
// type is used in the shader module.
validBindingConversion |=
(layoutInfo.type == wgpu::BindingType::Sampler &&
shaderInfo.type == wgpu::BindingType::ComparisonSampler);
validBindingConversion |=
(layoutInfo.type == wgpu::BindingType::ComparisonSampler &&
shaderInfo.type == wgpu::BindingType::Sampler);
if (!validBindingConversion) {
return DAWN_VALIDATION_ERROR(
"The binding type of the bind group layout entry conflicts " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.bindingType != shaderInfo.bindingType) {
return DAWN_VALIDATION_ERROR(
"The binding type of the bind group layout entry conflicts " +
GetShaderDeclarationString(group, bindingNumber));
}
if ((layoutInfo.visibility & StageBit(entryPoint.stage)) == 0) {
@ -372,49 +352,77 @@ namespace dawn_native {
" is not visible for the shader stage");
}
switch (layoutInfo.type) {
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
if (layoutInfo.textureComponentType != shaderInfo.textureComponentType) {
switch (layoutInfo.bindingType) {
case BindingInfoType::Texture: {
if (layoutInfo.texture.multisampled != shaderInfo.texture.multisampled) {
return DAWN_VALIDATION_ERROR(
"The textureComponentType of the bind group layout entry is "
"The texture multisampled flag of the bind group layout entry is "
"different from " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.viewDimension != shaderInfo.viewDimension) {
if (layoutInfo.texture.sampleType != shaderInfo.texture.sampleType) {
return DAWN_VALIDATION_ERROR(
"The viewDimension of the bind group layout entry is different "
"The texture sampleType of the bind group layout entry is "
"different from " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.texture.viewDimension != shaderInfo.texture.viewDimension) {
return DAWN_VALIDATION_ERROR(
"The texture viewDimension of the bind group layout entry is "
"different "
"from " +
GetShaderDeclarationString(group, bindingNumber));
}
break;
}
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
ASSERT(layoutInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
ASSERT(shaderInfo.storageTextureFormat != wgpu::TextureFormat::Undefined);
if (layoutInfo.storageTextureFormat != shaderInfo.storageTextureFormat) {
case BindingInfoType::StorageTexture: {
ASSERT(layoutInfo.storageTexture.format != wgpu::TextureFormat::Undefined);
ASSERT(shaderInfo.storageTexture.format != wgpu::TextureFormat::Undefined);
if (layoutInfo.storageTexture.access != shaderInfo.storageTexture.access) {
return DAWN_VALIDATION_ERROR(
"The storageTextureFormat of the bind group layout entry is "
"The storageTexture access mode of the bind group layout entry is "
"different from " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.viewDimension != shaderInfo.viewDimension) {
if (layoutInfo.storageTexture.format != shaderInfo.storageTexture.format) {
return DAWN_VALIDATION_ERROR(
"The viewDimension of the bind group layout entry is different "
"from " +
"The storageTexture format of the bind group layout entry is "
"different from " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.storageTexture.viewDimension !=
shaderInfo.storageTexture.viewDimension) {
return DAWN_VALIDATION_ERROR(
"The storageTexture viewDimension of the bind group layout entry "
"is different from " +
GetShaderDeclarationString(group, bindingNumber));
}
break;
}
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::StorageBuffer: {
if (layoutInfo.minBufferBindingSize != 0 &&
shaderInfo.minBufferBindingSize > layoutInfo.minBufferBindingSize) {
case BindingInfoType::Buffer: {
// Binding mismatch between shader and bind group is invalid. For example, a
// writable binding in the shader with a readonly storage buffer in the bind
// group layout is invalid. However, a readonly binding in the shader with a
// writable storage buffer in the bind group layout is valid.
bool validBindingConversion =
layoutInfo.buffer.type == wgpu::BufferBindingType::Storage &&
shaderInfo.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage;
if (layoutInfo.buffer.type != shaderInfo.buffer.type &&
!validBindingConversion) {
return DAWN_VALIDATION_ERROR(
"The buffer type of the bind group layout entry conflicts " +
GetShaderDeclarationString(group, bindingNumber));
}
if (layoutInfo.buffer.minBindingSize != 0 &&
shaderInfo.buffer.minBindingSize > layoutInfo.buffer.minBindingSize) {
return DAWN_VALIDATION_ERROR(
"The minimum buffer size of the bind group layout entry is smaller "
"than " +
@ -422,12 +430,12 @@ namespace dawn_native {
}
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
case BindingInfoType::Sampler:
// TODO(crbug.com/dawn/367): Temporarily allow using either a sampler or a
// comparison sampler until we can perform the proper shader analysis of
// what type is used in the shader module.
break;
}
}
@ -458,8 +466,9 @@ namespace dawn_native {
auto ExtractResourcesBinding =
[](const DeviceBase* device,
const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
const spirv_cross::Compiler& compiler, wgpu::BindingType bindingType,
EntryPointMetadata::BindingInfo* metadataBindings) -> MaybeError {
const spirv_cross::Compiler& compiler, BindingInfoType bindingType,
EntryPointMetadata::BindingInfo* metadataBindings,
bool isStorageBuffer = false) -> MaybeError {
for (const auto& resource : resources) {
if (!compiler.get_decoration_bitset(resource.id).get(spv::DecorationBinding)) {
return DAWN_VALIDATION_ERROR("No Binding decoration set for resource");
@ -488,67 +497,64 @@ namespace dawn_native {
EntryPointMetadata::ShaderBindingInfo* info = &it.first->second;
info->id = resource.id;
info->base_type_id = resource.base_type_id;
if (bindingType == wgpu::BindingType::UniformBuffer ||
bindingType == wgpu::BindingType::StorageBuffer ||
bindingType == wgpu::BindingType::ReadonlyStorageBuffer) {
// Determine buffer size, with a minimum of 1 element in the runtime array
spirv_cross::SPIRType type = compiler.get_type(info->base_type_id);
info->minBufferBindingSize =
compiler.get_declared_struct_size_runtime_array(type, 1);
}
info->bindingType = bindingType;
switch (bindingType) {
case wgpu::BindingType::SampledTexture: {
case BindingInfoType::Texture: {
spirv_cross::SPIRType::ImageType imageType =
compiler.get_type(info->base_type_id).image;
spirv_cross::SPIRType::BaseType textureComponentType =
compiler.get_type(imageType.type).basetype;
info->viewDimension =
info->texture.viewDimension =
SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
info->textureComponentType =
SpirvBaseTypeToTextureComponentType(textureComponentType);
if (imageType.ms) {
info->type = wgpu::BindingType::MultisampledTexture;
} else {
info->type = wgpu::BindingType::SampledTexture;
}
info->texture.sampleType =
SpirvBaseTypeToTextureSampleType(textureComponentType);
info->texture.multisampled = imageType.ms;
if (imageType.depth) {
if (imageType.ms) {
return DAWN_VALIDATION_ERROR(
"Multisampled depth textures aren't supported");
}
if (info->textureComponentType !=
wgpu::TextureComponentType::Float) {
if (info->texture.sampleType != wgpu::TextureSampleType::Float) {
return DAWN_VALIDATION_ERROR(
"Depth textures must have a float type");
}
info->textureComponentType =
wgpu::TextureComponentType::DepthComparison;
info->texture.sampleType = wgpu::TextureSampleType::Depth;
}
break;
}
case wgpu::BindingType::StorageBuffer: {
case BindingInfoType::Buffer: {
// Determine buffer size, with a minimum of 1 element in the runtime
// array
spirv_cross::SPIRType type = compiler.get_type(info->base_type_id);
info->buffer.minBindingSize =
compiler.get_declared_struct_size_runtime_array(type, 1);
// Differentiate between readonly storage bindings and writable ones
// based on the NonWritable decoration
spirv_cross::Bitset flags =
compiler.get_buffer_block_flags(resource.id);
if (flags.get(spv::DecorationNonWritable)) {
info->type = wgpu::BindingType::ReadonlyStorageBuffer;
// based on the NonWritable decoration.
// TODO(dawn:527): Could isStorageBuffer be determined by calling
// compiler.get_storage_class(resource.id)?
if (isStorageBuffer) {
spirv_cross::Bitset flags =
compiler.get_buffer_block_flags(resource.id);
if (flags.get(spv::DecorationNonWritable)) {
info->buffer.type = wgpu::BufferBindingType::ReadOnlyStorage;
} else {
info->buffer.type = wgpu::BufferBindingType::Storage;
}
} else {
info->type = wgpu::BindingType::StorageBuffer;
info->buffer.type = wgpu::BufferBindingType::Uniform;
}
break;
}
case wgpu::BindingType::ReadonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
spirv_cross::Bitset flags = compiler.get_decoration_bitset(resource.id);
if (flags.get(spv::DecorationNonReadable)) {
info->type = wgpu::BindingType::WriteonlyStorageTexture;
info->storageTexture.access = wgpu::StorageTextureAccess::WriteOnly;
} else if (flags.get(spv::DecorationNonWritable)) {
info->type = wgpu::BindingType::ReadonlyStorageTexture;
info->storageTexture.access = wgpu::StorageTextureAccess::ReadOnly;
} else {
return DAWN_VALIDATION_ERROR(
"Read-write storage textures are not supported");
@ -576,33 +582,30 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR(
"Depth storage textures aren't supported");
}
info->storageTextureFormat = storageTextureFormat;
info->viewDimension =
info->storageTexture.format = storageTextureFormat;
info->storageTexture.viewDimension =
SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed);
break;
}
default:
info->type = bindingType;
case BindingInfoType::Sampler: {
info->sampler.type = wgpu::SamplerBindingType::Filtering;
}
}
}
return {};
};
DAWN_TRY(ExtractResourcesBinding(device, resources.uniform_buffers, compiler,
wgpu::BindingType::UniformBuffer,
&metadata->bindings));
BindingInfoType::Buffer, &metadata->bindings));
DAWN_TRY(ExtractResourcesBinding(device, resources.separate_images, compiler,
wgpu::BindingType::SampledTexture,
&metadata->bindings));
BindingInfoType::Texture, &metadata->bindings));
DAWN_TRY(ExtractResourcesBinding(device, resources.separate_samplers, compiler,
wgpu::BindingType::Sampler, &metadata->bindings));
BindingInfoType::Sampler, &metadata->bindings));
DAWN_TRY(ExtractResourcesBinding(device, resources.storage_buffers, compiler,
wgpu::BindingType::StorageBuffer,
&metadata->bindings));
BindingInfoType::Buffer, &metadata->bindings, true));
// ReadonlyStorageTexture is used as a tag to do general storage texture handling.
DAWN_TRY(ExtractResourcesBinding(device, resources.storage_images, compiler,
wgpu::BindingType::ReadonlyStorageTexture,
&metadata->bindings));
BindingInfoType::StorageTexture, &metadata->bindings));
// Extract the vertex attributes
if (stage == SingleShaderStage::Vertex) {

View File

@ -101,7 +101,6 @@ namespace dawn_native {
private:
// Disallow access to unused members.
using BindingInfo::hasDynamicOffset;
using BindingInfo::visibility;
};

View File

@ -148,4 +148,18 @@ namespace dawn_native {
}
}
wgpu::TextureSampleType SpirvBaseTypeToTextureSampleType(
spirv_cross::SPIRType::BaseType spirvBaseType) {
switch (spirvBaseType) {
case spirv_cross::SPIRType::Float:
return wgpu::TextureSampleType::Float;
case spirv_cross::SPIRType::Int:
return wgpu::TextureSampleType::Sint;
case spirv_cross::SPIRType::UInt:
return wgpu::TextureSampleType::Uint;
default:
UNREACHABLE();
}
}
} // namespace dawn_native

View File

@ -39,6 +39,8 @@ namespace dawn_native {
// Returns the format "component type" corresponding to the SPIRV base type.
wgpu::TextureComponentType SpirvBaseTypeToTextureComponentType(
spirv_cross::SPIRType::BaseType spirvBaseType);
wgpu::TextureSampleType SpirvBaseTypeToTextureSampleType(
spirv_cross::SPIRType::BaseType spirvBaseType);
} // namespace dawn_native

View File

@ -53,71 +53,74 @@ namespace dawn_native { namespace d3d12 {
// Increment size does not need to be stored and is only used to get a handle
// local to the allocation with OffsetFrom().
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
// TODO(enga@google.com): investigate if this needs to be a constraint at
// the API level
desc.SizeInBytes = Align(binding.size, 256);
desc.BufferLocation = ToBackend(binding.buffer)->GetVA() + binding.offset;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform: {
D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
// TODO(enga@google.com): investigate if this needs to be a constraint
// at the API level
desc.SizeInBytes = Align(binding.size, 256);
desc.BufferLocation =
ToBackend(binding.buffer)->GetVA() + binding.offset;
d3d12Device->CreateConstantBufferView(
&desc,
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::StorageBuffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
d3d12Device->CreateConstantBufferView(
&desc, viewAllocation.OffsetFrom(viewSizeIncrement,
bindingOffsets[bindingIndex]));
break;
}
case wgpu::BufferBindingType::Storage: {
// Since SPIRV-Cross outputs HLSL shaders with RWByteAddressBuffer,
// we must use D3D12_BUFFER_UAV_FLAG_RAW when making the
// UNORDERED_ACCESS_VIEW_DESC. Using D3D12_BUFFER_UAV_FLAG_RAW requires
// that we use DXGI_FORMAT_R32_TYPELESS as the format of the view.
// DXGI_FORMAT_R32_TYPELESS requires that the element size be 4
// byte aligned. Since binding.size and binding.offset are in bytes,
// we need to divide by 4 to obtain the element size.
D3D12_UNORDERED_ACCESS_VIEW_DESC desc;
desc.Buffer.NumElements = binding.size / 4;
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = binding.offset / 4;
desc.Buffer.StructureByteStride = 0;
desc.Buffer.CounterOffsetInBytes = 0;
desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
// Since SPIRV-Cross outputs HLSL shaders with RWByteAddressBuffer,
// we must use D3D12_BUFFER_UAV_FLAG_RAW when making the
// UNORDERED_ACCESS_VIEW_DESC. Using D3D12_BUFFER_UAV_FLAG_RAW requires
// that we use DXGI_FORMAT_R32_TYPELESS as the format of the view.
// DXGI_FORMAT_R32_TYPELESS requires that the element size be 4
// byte aligned. Since binding.size and binding.offset are in bytes,
// we need to divide by 4 to obtain the element size.
D3D12_UNORDERED_ACCESS_VIEW_DESC desc;
desc.Buffer.NumElements = binding.size / 4;
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = binding.offset / 4;
desc.Buffer.StructureByteStride = 0;
desc.Buffer.CounterOffsetInBytes = 0;
desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
d3d12Device->CreateUnorderedAccessView(
ToBackend(binding.buffer)->GetD3D12Resource(), nullptr, &desc,
viewAllocation.OffsetFrom(viewSizeIncrement,
bindingOffsets[bindingIndex]));
break;
}
case wgpu::BufferBindingType::ReadOnlyStorage: {
// Like StorageBuffer, SPIRV-Cross outputs HLSL shaders for readonly
// storage buffer with ByteAddressBuffer. So we must use
// D3D12_BUFFER_SRV_FLAG_RAW when making the SRV descriptor. And it has
// similar requirement for format, element size, etc.
D3D12_SHADER_RESOURCE_VIEW_DESC desc;
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.Buffer.FirstElement = binding.offset / 4;
desc.Buffer.NumElements = binding.size / 4;
desc.Buffer.StructureByteStride = 0;
desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
d3d12Device->CreateShaderResourceView(
ToBackend(binding.buffer)->GetD3D12Resource(), &desc,
viewAllocation.OffsetFrom(viewSizeIncrement,
bindingOffsets[bindingIndex]));
break;
}
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
d3d12Device->CreateUnorderedAccessView(
ToBackend(binding.buffer)->GetD3D12Resource(), nullptr, &desc,
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::ReadonlyStorageBuffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
// Like StorageBuffer, SPIRV-Cross outputs HLSL shaders for readonly storage
// buffer with ByteAddressBuffer. So we must use D3D12_BUFFER_SRV_FLAG_RAW
// when making the SRV descriptor. And it has similar requirement for
// format, element size, etc.
D3D12_SHADER_RESOURCE_VIEW_DESC desc;
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.Buffer.FirstElement = binding.offset / 4;
desc.Buffer.NumElements = binding.size / 4;
desc.Buffer.StructureByteStride = 0;
desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
d3d12Device->CreateShaderResourceView(
ToBackend(binding.buffer)->GetD3D12Resource(), &desc,
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
// Readonly storage is implemented as SRV so it can be used at the same time as a
// sampled texture.
case wgpu::BindingType::ReadonlyStorageTexture: {
case BindingInfoType::Texture: {
auto* view = ToBackend(GetBindingAsTextureView(bindingIndex));
auto& srv = view->GetSRVDescriptor();
d3d12Device->CreateShaderResourceView(
@ -125,23 +128,42 @@ namespace dawn_native { namespace d3d12 {
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler: {
case BindingInfoType::StorageTexture: {
TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
switch (bindingInfo.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly: {
// Readonly storage is implemented as SRV so it can be used at the same
// time as a sampled texture.
auto& srv = view->GetSRVDescriptor();
d3d12Device->CreateShaderResourceView(
ToBackend(view->GetTexture())->GetD3D12Resource(), &srv,
viewAllocation.OffsetFrom(viewSizeIncrement,
bindingOffsets[bindingIndex]));
break;
}
case wgpu::StorageTextureAccess::WriteOnly: {
D3D12_UNORDERED_ACCESS_VIEW_DESC uav = view->GetUAVDescriptor();
d3d12Device->CreateUnorderedAccessView(
ToBackend(view->GetTexture())->GetD3D12Resource(), nullptr, &uav,
viewAllocation.OffsetFrom(viewSizeIncrement,
bindingOffsets[bindingIndex]));
break;
}
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
break;
}
case BindingInfoType::Sampler: {
// No-op as samplers will be later initialized by CreateSamplers().
break;
}
case wgpu::BindingType::WriteonlyStorageTexture: {
TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
D3D12_UNORDERED_ACCESS_VIEW_DESC uav = view->GetUAVDescriptor();
d3d12Device->CreateUnorderedAccessView(
ToBackend(view->GetTexture())->GetD3D12Resource(), nullptr, &uav,
viewAllocation.OffsetFrom(viewSizeIncrement, bindingOffsets[bindingIndex]));
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -22,24 +22,36 @@
namespace dawn_native { namespace d3d12 {
namespace {
BindGroupLayout::DescriptorType WGPUBindingTypeToDescriptorType(
wgpu::BindingType bindingType) {
switch (bindingType) {
case wgpu::BindingType::UniformBuffer:
return BindGroupLayout::DescriptorType::CBV;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::WriteonlyStorageTexture:
return BindGroupLayout::DescriptorType::UAV;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::ReadonlyStorageTexture:
return BindGroupLayout::DescriptorType::SRV;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
BindGroupLayout::DescriptorType WGPUBindingInfoToDescriptorType(
const BindingInfo& bindingInfo) {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
return BindGroupLayout::DescriptorType::CBV;
case wgpu::BufferBindingType::Storage:
return BindGroupLayout::DescriptorType::UAV;
case wgpu::BufferBindingType::ReadOnlyStorage:
return BindGroupLayout::DescriptorType::SRV;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
case BindingInfoType::Sampler:
return BindGroupLayout::DescriptorType::Sampler;
case wgpu::BindingType::Undefined:
UNREACHABLE();
case BindingInfoType::Texture:
return BindGroupLayout::DescriptorType::SRV;
case BindingInfoType::StorageTexture:
switch (bindingInfo.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly:
return BindGroupLayout::DescriptorType::SRV;
case wgpu::StorageTextureAccess::WriteOnly:
return BindGroupLayout::DescriptorType::UAV;
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
}
}
} // anonymous namespace
@ -57,9 +69,9 @@ namespace dawn_native { namespace d3d12 {
// 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);
ASSERT(!bindingInfo.buffer.hasDynamicOffset);
DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo);
mBindingOffsets[bindingIndex] = mDescriptorCounts[descriptorType]++;
}
@ -107,31 +119,17 @@ namespace dawn_native { namespace d3d12 {
for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) {
const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
if (bindingInfo.hasDynamicOffset) {
if (bindingInfo.bindingType == BindingInfoType::Buffer &&
bindingInfo.buffer.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 (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
mBindingOffsets[bindingIndex] = baseRegister++;
break;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
UNREACHABLE();
break;
}
mBindingOffsets[bindingIndex] = baseRegister++;
continue;
}
// TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
DescriptorType descriptorType = WGPUBindingTypeToDescriptorType(bindingInfo.type);
DescriptorType descriptorType = WGPUBindingInfoToDescriptorType(bindingInfo);
mBindingOffsets[bindingIndex] += descriptorOffsets[descriptorType];
}

View File

@ -223,51 +223,57 @@ namespace dawn_native { namespace d3d12 {
for (BindGroupIndex index : IterateBitSet(mBindGroupLayoutsMask)) {
BindGroupLayoutBase* layout = mBindGroups[index]->GetLayout();
for (BindingIndex binding{0}; binding < layout->GetBindingCount(); ++binding) {
switch (layout->GetBindingInfo(binding).type) {
case wgpu::BindingType::StorageBuffer: {
const BindingInfo& bindingInfo = layout->GetBindingInfo(binding);
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
D3D12_RESOURCE_BARRIER barrier;
wgpu::BufferUsage usage;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
usage = wgpu::BufferUsage::Uniform;
break;
case wgpu::BufferBindingType::Storage:
usage = wgpu::BufferUsage::Storage;
break;
case wgpu::BufferBindingType::ReadOnlyStorage:
usage = kReadOnlyStorageBuffer;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
if (ToBackend(mBindGroups[index]
->GetBindingAsBufferBinding(binding)
.buffer)
->TrackUsageAndGetResourceBarrier(
commandContext, &barrier, wgpu::BufferUsage::Storage)) {
->TrackUsageAndGetResourceBarrier(commandContext, &barrier,
usage)) {
barriers.push_back(barrier);
}
break;
}
case wgpu::BindingType::ReadonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
TextureViewBase* view =
mBindGroups[index]->GetBindingAsTextureView(binding);
ToBackend(view->GetTexture())
->TransitionUsageAndGetResourceBarrier(
commandContext, &barriers, kReadonlyStorageTexture,
view->GetSubresourceRange());
break;
}
case wgpu::BindingType::WriteonlyStorageTexture: {
TextureViewBase* view =
mBindGroups[index]->GetBindingAsTextureView(binding);
ToBackend(view->GetTexture())
->TransitionUsageAndGetResourceBarrier(
commandContext, &barriers, wgpu::TextureUsage::Storage,
view->GetSubresourceRange());
break;
}
case wgpu::BindingType::ReadonlyStorageBuffer: {
D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(mBindGroups[index]
->GetBindingAsBufferBinding(binding)
.buffer)
->TrackUsageAndGetResourceBarrier(commandContext, &barrier,
kReadOnlyStorageBuffer)) {
barriers.push_back(barrier);
wgpu::TextureUsage usage;
switch (bindingInfo.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly:
usage = kReadonlyStorageTexture;
break;
case wgpu::StorageTextureAccess::WriteOnly:
usage = wgpu::TextureUsage::Storage;
break;
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
ToBackend(view->GetTexture())
->TransitionUsageAndGetResourceBarrier(
commandContext, &barriers, usage,
view->GetSubresourceRange());
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
TextureViewBase* view =
case BindingInfoType::Texture: {
TextureViewBase* view =
mBindGroups[index]->GetBindingAsTextureView(binding);
ToBackend(view->GetTexture())
->TransitionUsageAndGetResourceBarrier(
@ -275,25 +281,10 @@ namespace dawn_native { namespace d3d12 {
view->GetSubresourceRange());
break;
}
case wgpu::BindingType::UniformBuffer: {
D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(mBindGroups[index]
->GetBindingAsBufferBinding(binding)
.buffer)
->TrackUsageAndGetResourceBarrier(
commandContext, &barrier, wgpu::BufferUsage::Uniform)) {
barriers.push_back(barrier);
}
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case BindingInfoType::Sampler:
// Don't require barriers.
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}
@ -353,8 +344,9 @@ namespace dawn_native { namespace d3d12 {
D3D12_GPU_VIRTUAL_ADDRESS bufferLocation =
ToBackend(binding.buffer)->GetVA() + offset;
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
ASSERT(bindingInfo.bindingType == BindingInfoType::Buffer);
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
if (mInCompute) {
commandList->SetComputeRootConstantBufferView(parameterIndex,
bufferLocation);
@ -363,7 +355,7 @@ namespace dawn_native { namespace d3d12 {
bufferLocation);
}
break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BufferBindingType::Storage:
if (mInCompute) {
commandList->SetComputeRootUnorderedAccessView(parameterIndex,
bufferLocation);
@ -372,7 +364,7 @@ namespace dawn_native { namespace d3d12 {
bufferLocation);
}
break;
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BufferBindingType::ReadOnlyStorage:
if (mInCompute) {
commandList->SetComputeRootShaderResourceView(parameterIndex,
bufferLocation);
@ -381,13 +373,7 @@ namespace dawn_native { namespace d3d12 {
bufferLocation);
}
break;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
}

View File

@ -40,21 +40,15 @@ namespace dawn_native { namespace d3d12 {
return D3D12_SHADER_VISIBILITY_ALL;
}
D3D12_ROOT_PARAMETER_TYPE RootParameterType(wgpu::BindingType type) {
D3D12_ROOT_PARAMETER_TYPE RootParameterType(wgpu::BufferBindingType type) {
switch (type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BufferBindingType::Uniform:
return D3D12_ROOT_PARAMETER_TYPE_CBV;
case wgpu::BindingType::StorageBuffer:
case wgpu::BufferBindingType::Storage:
return D3D12_ROOT_PARAMETER_TYPE_UAV;
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BufferBindingType::ReadOnlyStorage:
return D3D12_ROOT_PARAMETER_TYPE_SRV;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::BindingType::Undefined:
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
}
@ -148,7 +142,7 @@ namespace dawn_native { namespace d3d12 {
mDynamicRootParameterIndices[group][dynamicBindingIndex] = rootParameters.size();
// Set parameter types according to bind group layout descriptor.
rootParameter.ParameterType = RootParameterType(bindingInfo.type);
rootParameter.ParameterType = RootParameterType(bindingInfo.buffer.type);
// Set visibilities according to bind group layout descriptor.
rootParameter.ShaderVisibility = ShaderVisibilityType(bindingInfo.visibility);
@ -196,7 +190,7 @@ namespace dawn_native { namespace d3d12 {
BindingIndex bindingIndex) const {
ASSERT(group < kMaxBindGroupsTyped);
ASSERT(bindingIndex < kMaxDynamicBuffersPerPipelineLayoutTyped);
ASSERT(GetBindGroupLayout(group)->GetBindingInfo(bindingIndex).hasDynamicOffset);
ASSERT(GetBindGroupLayout(group)->GetBindingInfo(bindingIndex).buffer.hasDynamicOffset);
ASSERT(GetBindGroupLayout(group)->GetBindingInfo(bindingIndex).visibility !=
wgpu::ShaderStage::None);
return mDynamicRootParameterIndices[group][bindingIndex];

View File

@ -103,8 +103,7 @@ namespace dawn_native { namespace d3d12 {
for (BindingIndex bindingIndex = bgl->GetDynamicBufferCount();
bindingIndex < bgl->GetBindingCount(); ++bindingIndex) {
const BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
if (bindingInfo.type == wgpu::BindingType::Sampler ||
bindingInfo.type == wgpu::BindingType::ComparisonSampler) {
if (bindingInfo.bindingType == BindingInfoType::Sampler) {
samplers.push_back(ToBackend(group->GetBindingAsSampler(bindingIndex)));
}
}

View File

@ -277,8 +277,9 @@ namespace dawn_native { namespace d3d12 {
// the BGL produces the wrong output. Force read-only storage buffer bindings to
// be treated as UAV instead of SRV.
const bool forceStorageBufferAsUAV =
(bindingInfo.type == wgpu::BindingType::ReadonlyStorageBuffer &&
bgl->GetBindingInfo(bindingIndex).type == wgpu::BindingType::StorageBuffer);
(bindingInfo.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage &&
bgl->GetBindingInfo(bindingIndex).buffer.type ==
wgpu::BufferBindingType::Storage);
uint32_t bindingOffset = bindingOffsets[bindingIndex];
compiler.set_decoration(bindingInfo.id, spv::DecorationBinding, bindingOffset);

View File

@ -379,10 +379,8 @@ namespace dawn_native { namespace metal {
SingleShaderStage::Compute)[index][bindingIndex];
}
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
const BufferBinding& binding =
group->GetBindingAsBufferBinding(bindingIndex);
const id<MTLBuffer> buffer = ToBackend(binding.buffer)->GetMTLBuffer();
@ -390,7 +388,7 @@ namespace dawn_native { namespace metal {
// TODO(shaobo.yan@intel.com): Record bound buffer status to use
// setBufferOffset to achieve better performance.
if (bindingInfo.hasDynamicOffset) {
if (bindingInfo.buffer.hasDynamicOffset) {
offset += dynamicOffsets[currentDynamicBufferIndex];
currentDynamicBufferIndex++;
}
@ -423,8 +421,7 @@ namespace dawn_native { namespace metal {
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler: {
case BindingInfoType::Sampler: {
auto sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
if (hasVertStage) {
[render setVertexSamplerState:sampler->GetMTLSamplerState()
@ -441,10 +438,8 @@ namespace dawn_native { namespace metal {
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
case BindingInfoType::Texture:
case BindingInfoType::StorageTexture: {
auto textureView =
ToBackend(group->GetBindingAsTextureView(bindingIndex));
if (hasVertStage) {
@ -461,9 +456,6 @@ namespace dawn_native { namespace metal {
}
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -39,27 +39,22 @@ namespace dawn_native { namespace metal {
continue;
}
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
mIndexInfo[stage][group][bindingIndex] = bufferIndex;
bufferIndex++;
break;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case BindingInfoType::Sampler:
mIndexInfo[stage][group][bindingIndex] = samplerIndex;
samplerIndex++;
break;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case BindingInfoType::Texture:
case BindingInfoType::StorageTexture:
mIndexInfo[stage][group][bindingIndex] = textureIndex;
textureIndex++;
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -30,31 +30,15 @@ namespace dawn_native { namespace opengl {
ASSERT(bindingIndex < descriptor->layout->GetBindingCount());
const BindingInfo& bindingInfo = descriptor->layout->GetBindingInfo(bindingIndex);
switch (bindingInfo.type) {
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
ASSERT(entry.textureView != nullptr);
const uint32_t textureViewLayerCount = entry.textureView->GetLayerCount();
if (textureViewLayerCount != 1 &&
textureViewLayerCount !=
entry.textureView->GetTexture()->GetArrayLayers()) {
return DAWN_VALIDATION_ERROR(
"Currently the OpenGL backend only supports either binding a layer or "
"the entire texture as storage texture.");
}
} break;
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
if (bindingInfo.bindingType == BindingInfoType::StorageTexture) {
ASSERT(entry.textureView != nullptr);
const uint32_t textureViewLayerCount = entry.textureView->GetLayerCount();
if (textureViewLayerCount != 1 &&
textureViewLayerCount != entry.textureView->GetTexture()->GetArrayLayers()) {
return DAWN_VALIDATION_ERROR(
"Currently the OpenGL backend only supports either binding a layer or "
"the entire texture as storage texture.");
}
}
}

View File

@ -243,49 +243,43 @@ namespace dawn_native { namespace opengl {
const BindingInfo& bindingInfo =
group->GetLayout()->GetBindingInfo(bindingIndex);
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
GLuint index = indices[bindingIndex];
GLuint offset = binding.offset;
if (bindingInfo.hasDynamicOffset) {
if (bindingInfo.buffer.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;
GLenum target;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
target = GL_UNIFORM_BUFFER;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
target = GL_SHADER_STORAGE_BUFFER;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
binding.size);
gl.BindBufferRange(target, index, buffer, offset, binding.size);
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler: {
case BindingInfoType::Sampler: {
Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
GLuint samplerIndex = indices[bindingIndex];
for (PipelineGL::SamplerUnit unit :
mPipeline->GetTextureUnitsForSampler(samplerIndex)) {
// Only use filtering for certain texture units, because int and
// uint texture are only complete without filtering
// Only use filtering for certain texture units, because int
// and uint texture are only complete without filtering
if (unit.shouldUseFiltering) {
gl.BindSampler(unit.unit, sampler->GetFilteringHandle());
} else {
@ -295,8 +289,7 @@ namespace dawn_native { namespace opengl {
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
case BindingInfoType::Texture: {
TextureView* view =
ToBackend(group->GetBindingAsTextureView(bindingIndex));
GLuint handle = view->GetHandle();
@ -328,8 +321,7 @@ namespace dawn_native { namespace opengl {
break;
}
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
TextureView* view =
ToBackend(group->GetBindingAsTextureView(bindingIndex));
Texture* texture = ToBackend(view->GetTexture());
@ -337,20 +329,19 @@ namespace dawn_native { namespace opengl {
GLuint imageIndex = indices[bindingIndex];
GLenum access;
switch (bindingInfo.type) {
case wgpu::BindingType::ReadonlyStorageTexture:
switch (bindingInfo.storageTexture.access) {
case wgpu::StorageTextureAccess::ReadOnly:
access = GL_READ_ONLY;
break;
case wgpu::BindingType::WriteonlyStorageTexture:
case wgpu::StorageTextureAccess::WriteOnly:
access = GL_WRITE_ONLY;
break;
default:
case wgpu::StorageTextureAccess::Undefined:
UNREACHABLE();
}
// OpenGL ES only supports either binding a layer or the entire texture
// in glBindImageTexture().
// OpenGL ES only supports either binding a layer or the entire
// texture in glBindImageTexture().
GLboolean isLayered;
if (view->GetLayerCount() == 1) {
isLayered = GL_FALSE;
@ -365,9 +356,6 @@ namespace dawn_native { namespace opengl {
texture->GetGLFormat().internalFormat);
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -132,53 +132,53 @@ namespace dawn_native { namespace opengl {
BindingIndex bindingIndex = it.second;
std::string name = GetBindingName(group, bindingNumber);
switch (bgl->GetBindingInfo(bindingIndex).type) {
case wgpu::BindingType::UniformBuffer: {
GLint location = gl.GetUniformBlockIndex(mProgram, name.c_str());
if (location != -1) {
gl.UniformBlockBinding(mProgram, location,
indices[group][bindingIndex]);
}
break;
}
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
// Since glShaderStorageBlockBinding doesn't exist in OpenGL ES, we skip
// that call and handle it during shader translation by modifying the
// location decoration.
// Contrary to all other binding types, OpenGL ES's SSBO binding index in
// the SSBO table is the value of the location= decoration in GLSL.
if (gl.GetVersion().IsDesktop()) {
GLuint location = gl.GetProgramResourceIndex(
mProgram, GL_SHADER_STORAGE_BLOCK, name.c_str());
if (location != GL_INVALID_INDEX) {
gl.ShaderStorageBlockBinding(mProgram, location,
indices[group][bindingIndex]);
const BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform: {
GLint location = gl.GetUniformBlockIndex(mProgram, name.c_str());
if (location != -1) {
gl.UniformBlockBinding(mProgram, location,
indices[group][bindingIndex]);
}
break;
}
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage: {
// Since glShaderStorageBlockBinding doesn't exist in OpenGL ES, we
// skip that call and handle it during shader translation by
// modifying the location decoration. Contrary to all other binding
// types, OpenGL ES's SSBO binding index in the SSBO table is the
// value of the location= decoration in GLSL.
if (gl.GetVersion().IsDesktop()) {
GLuint location = gl.GetProgramResourceIndex(
mProgram, GL_SHADER_STORAGE_BLOCK, name.c_str());
if (location != GL_INVALID_INDEX) {
gl.ShaderStorageBlockBinding(mProgram, location,
indices[group][bindingIndex]);
}
}
break;
}
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case BindingInfoType::Sampler:
case BindingInfoType::Texture:
// These binding types are handled in the separate sampler and texture
// emulation
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
GLint location = gl.GetUniformLocation(mProgram, name.c_str());
if (location != -1) {
gl.Uniform1i(location, indices[group][bindingIndex]);
}
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}
@ -216,8 +216,8 @@ namespace dawn_native { namespace opengl {
GLuint textureIndex = indices[combined.textureLocation.group][bindingIndex];
mUnitsForTextures[textureIndex].push_back(textureUnit);
shouldUseFiltering = bgl->GetBindingInfo(bindingIndex).textureComponentType ==
wgpu::TextureComponentType::Float;
shouldUseFiltering = bgl->GetBindingInfo(bindingIndex).texture.sampleType ==
wgpu::TextureSampleType::Float;
}
{
if (combined.useDummySampler) {

View File

@ -34,36 +34,38 @@ namespace dawn_native { namespace opengl {
for (BindingIndex bindingIndex{0}; bindingIndex < bgl->GetBindingCount();
++bindingIndex) {
switch (bgl->GetBindingInfo(bindingIndex).type) {
case wgpu::BindingType::UniformBuffer:
mIndexInfo[group][bindingIndex] = uboIndex;
uboIndex++;
const BindingInfo& bindingInfo = bgl->GetBindingInfo(bindingIndex);
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
mIndexInfo[group][bindingIndex] = uboIndex;
uboIndex++;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
mIndexInfo[group][bindingIndex] = ssboIndex;
ssboIndex++;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
break;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case BindingInfoType::Sampler:
mIndexInfo[group][bindingIndex] = samplerIndex;
samplerIndex++;
break;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case BindingInfoType::Texture:
mIndexInfo[group][bindingIndex] = sampledTextureIndex;
sampledTextureIndex++;
break;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
mIndexInfo[group][bindingIndex] = ssboIndex;
ssboIndex++;
break;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case BindingInfoType::StorageTexture:
mIndexInfo[group][bindingIndex] = storageTextureIndex;
storageTextureIndex++;
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -180,12 +180,10 @@ namespace dawn_native { namespace opengl {
const auto& info = it.second;
uint32_t resourceId;
switch (info.type) {
switch (info.bindingType) {
// When the resource is a uniform or shader storage block, we should change the
// block name instead of the instance name.
case wgpu::BindingType::ReadonlyStorageBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::UniformBuffer:
case BindingInfoType::Buffer:
resourceId = info.base_type_id;
break;
default:
@ -197,8 +195,9 @@ namespace dawn_native { namespace opengl {
compiler.unset_decoration(info.id, spv::DecorationDescriptorSet);
// OpenGL ES has no glShaderStorageBlockBinding call, so we adjust the SSBO binding
// decoration here instead.
if (version.IsES() && (info.type == wgpu::BindingType::StorageBuffer ||
info.type == wgpu::BindingType::ReadonlyStorageBuffer)) {
if (version.IsES() && info.bindingType == BindingInfoType::Buffer &&
(info.buffer.type == wgpu::BufferBindingType::Storage ||
info.buffer.type == wgpu::BufferBindingType::ReadOnlyStorage)) {
const auto& indices = layout->GetBindingIndexInfo();
BindingIndex bindingIndex =
layout->GetBindGroupLayout(group)->GetBindingIndex(bindingNumber);

View File

@ -46,30 +46,30 @@ namespace dawn_native { namespace vulkan {
} // anonymous namespace
VkDescriptorType VulkanDescriptorType(wgpu::BindingType type, bool isDynamic) {
switch (type) {
case wgpu::BindingType::UniformBuffer:
if (isDynamic) {
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
VkDescriptorType VulkanDescriptorType(const BindingInfo& bindingInfo) {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
if (bindingInfo.buffer.hasDynamicOffset) {
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
}
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
if (bindingInfo.buffer.hasDynamicOffset) {
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
}
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case BindingInfoType::Sampler:
return VK_DESCRIPTOR_TYPE_SAMPLER;
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture:
case BindingInfoType::Texture:
return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer:
if (isDynamic) {
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
}
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture:
case BindingInfoType::StorageTexture:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
@ -96,8 +96,7 @@ namespace dawn_native { namespace vulkan {
VkDescriptorSetLayoutBinding vkBinding;
vkBinding.binding = static_cast<uint32_t>(bindingNumber);
vkBinding.descriptorType =
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
vkBinding.descriptorType = VulkanDescriptorType(bindingInfo);
vkBinding.descriptorCount = 1;
vkBinding.stageFlags = VulkanShaderStageFlags(bindingInfo.visibility);
vkBinding.pImmutableSamplers = nullptr;
@ -121,9 +120,7 @@ namespace dawn_native { namespace vulkan {
std::map<VkDescriptorType, uint32_t> descriptorCountPerType;
for (BindingIndex bindingIndex{0}; bindingIndex < GetBindingCount(); ++bindingIndex) {
const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex);
VkDescriptorType vulkanType =
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
VkDescriptorType vulkanType = VulkanDescriptorType(GetBindingInfo(bindingIndex));
// map::operator[] will return 0 if the key doesn't exist.
descriptorCountPerType[vulkanType]++;

View File

@ -29,7 +29,7 @@ namespace dawn_native { namespace vulkan {
class DescriptorSetAllocator;
class Device;
VkDescriptorType VulkanDescriptorType(wgpu::BindingType type, bool isDynamic);
VkDescriptorType VulkanDescriptorType(const BindingInfo& bindingInfo);
// In Vulkan descriptor pools have to be sized to an exact number of descriptors. This means
// it's hard to have something where we can mix different types of descriptor sets because

View File

@ -60,13 +60,10 @@ namespace dawn_native { namespace vulkan {
write.dstBinding = static_cast<uint32_t>(bindingNumber);
write.dstArrayElement = 0;
write.descriptorCount = 1;
write.descriptorType =
VulkanDescriptorType(bindingInfo.type, bindingInfo.hasDynamicOffset);
write.descriptorType = VulkanDescriptorType(bindingInfo);
switch (bindingInfo.type) {
case wgpu::BindingType::UniformBuffer:
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
writeBufferInfo[numWrites].buffer = ToBackend(binding.buffer)->GetHandle();
@ -76,16 +73,14 @@ namespace dawn_native { namespace vulkan {
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler: {
case BindingInfoType::Sampler: {
Sampler* sampler = ToBackend(GetBindingAsSampler(bindingIndex));
writeImageInfo[numWrites].sampler = sampler->GetHandle();
write.pImageInfo = &writeImageInfo[numWrites];
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
case BindingInfoType::Texture: {
TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
writeImageInfo[numWrites].imageView = view->GetHandle();
@ -98,8 +93,7 @@ namespace dawn_native { namespace vulkan {
break;
}
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
TextureView* view = ToBackend(GetBindingAsTextureView(bindingIndex));
writeImageInfo[numWrites].imageView = view->GetHandle();
@ -108,9 +102,6 @@ namespace dawn_native { namespace vulkan {
write.pImageInfo = &writeImageInfo[numWrites];
break;
}
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
numWrites++;

View File

@ -155,23 +155,35 @@ namespace dawn_native { namespace vulkan {
for (BindGroupIndex index : IterateBitSet(mBindGroupLayoutsMask)) {
BindGroupLayoutBase* layout = mBindGroups[index]->GetLayout();
for (BindingIndex binding{0}; binding < layout->GetBindingCount(); ++binding) {
switch (layout->GetBindingInfo(binding).type) {
case wgpu::BindingType::StorageBuffer:
case wgpu::BindingType::ReadonlyStorageBuffer: {
const BindingInfo& bindingInfo = layout->GetBindingInfo(binding);
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer: {
wgpu::BufferUsage usage;
switch (bindingInfo.buffer.type) {
case wgpu::BufferBindingType::Uniform:
usage = wgpu::BufferUsage::Uniform;
break;
case wgpu::BufferBindingType::Storage:
case wgpu::BufferBindingType::ReadOnlyStorage:
usage = wgpu::BufferUsage::Storage;
break;
case wgpu::BufferBindingType::Undefined:
UNREACHABLE();
}
VkBufferMemoryBarrier bufferBarrier;
if (ToBackend(mBindGroups[index]
->GetBindingAsBufferBinding(binding)
.buffer)
->TransitionUsageAndGetResourceBarrier(
wgpu::BufferUsage::Storage, &bufferBarrier, &srcStages,
&dstStages)) {
usage, &bufferBarrier, &srcStages, &dstStages)) {
bufferBarriers.push_back(bufferBarrier);
}
break;
}
case wgpu::BindingType::ReadonlyStorageTexture:
case wgpu::BindingType::WriteonlyStorageTexture: {
case BindingInfoType::StorageTexture: {
TextureViewBase* view =
mBindGroups[index]->GetBindingAsTextureView(binding);
ToBackend(view->GetTexture())
@ -180,21 +192,8 @@ namespace dawn_native { namespace vulkan {
&imageBarriers, &srcStages, &dstStages);
break;
}
case wgpu::BindingType::UniformBuffer: {
VkBufferMemoryBarrier bufferBarrier;
if (ToBackend(mBindGroups[index]
->GetBindingAsBufferBinding(binding)
.buffer)
->TransitionUsageAndGetResourceBarrier(
wgpu::BufferUsage::Uniform, &bufferBarrier, &srcStages,
&dstStages)) {
bufferBarriers.push_back(bufferBarrier);
}
break;
}
case wgpu::BindingType::SampledTexture:
case wgpu::BindingType::MultisampledTexture: {
case BindingInfoType::Texture: {
TextureViewBase* view =
mBindGroups[index]->GetBindingAsTextureView(binding);
ToBackend(view->GetTexture())
@ -204,13 +203,9 @@ namespace dawn_native { namespace vulkan {
break;
}
case wgpu::BindingType::Sampler:
case wgpu::BindingType::ComparisonSampler:
case BindingInfoType::Sampler:
// Don't require barriers.
break;
case wgpu::BindingType::Undefined:
UNREACHABLE();
}
}
}

View File

@ -414,13 +414,19 @@ TEST_F(StorageTextureValidationTests, UnsupportedTextureViewDimensionInBindGroup
// render and compute pipeline, the binding type in the bind group layout must match the
// declaration in the shader.
TEST_F(StorageTextureValidationTests, BindGroupLayoutEntryTypeMatchesShaderDeclaration) {
constexpr std::array<wgpu::BindingType, 7> kSupportedBindingTypes = {
wgpu::BindingType::UniformBuffer, wgpu::BindingType::StorageBuffer,
wgpu::BindingType::ReadonlyStorageBuffer, wgpu::BindingType::Sampler,
wgpu::BindingType::SampledTexture, wgpu::BindingType::ReadonlyStorageTexture,
wgpu::BindingType::WriteonlyStorageTexture};
constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Float;
std::initializer_list<utils::BindingLayoutEntryInitializationHelper> kSupportedBindingTypes = {
{0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Uniform},
{0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage},
{0, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::ReadOnlyStorage},
{0, wgpu::ShaderStage::Compute, wgpu::SamplerBindingType::Filtering},
{0, wgpu::ShaderStage::Compute, wgpu::TextureSampleType::Float},
{0, wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadOnly,
kStorageTextureFormat},
{0, wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::WriteOnly,
kStorageTextureFormat}};
for (wgpu::StorageTextureAccess bindingTypeInShader : kSupportedStorageTextureAccess) {
// Create the compute shader with the given binding type.
std::string computeShader =
@ -433,30 +439,20 @@ TEST_F(StorageTextureValidationTests, BindGroupLayoutEntryTypeMatchesShaderDecla
defaultComputePipelineDescriptor.computeStage.module = csModule;
defaultComputePipelineDescriptor.computeStage.entryPoint = "main";
// Set common fileds of bind group layout binding.
wgpu::BindGroupLayoutEntry defaultBindGroupLayoutEntry;
defaultBindGroupLayoutEntry.binding = 0;
defaultBindGroupLayoutEntry.visibility = wgpu::ShaderStage::Compute;
defaultBindGroupLayoutEntry.storageTextureFormat = kStorageTextureFormat;
for (wgpu::BindingType bindingTypeInBindgroupLayout : kSupportedBindingTypes) {
for (utils::BindingLayoutEntryInitializationHelper bindingLayoutEntry :
kSupportedBindingTypes) {
wgpu::ComputePipelineDescriptor computePipelineDescriptor =
defaultComputePipelineDescriptor;
// Create bind group layout with different binding types.
wgpu::BindGroupLayoutEntry bindGroupLayoutBinding = defaultBindGroupLayoutEntry;
bindGroupLayoutBinding.type = bindingTypeInBindgroupLayout;
wgpu::BindGroupLayout bindGroupLayout =
utils::MakeBindGroupLayout(device, {bindGroupLayoutBinding});
utils::MakeBindGroupLayout(device, {bindingLayoutEntry});
computePipelineDescriptor.layout =
utils::MakeBasicPipelineLayout(device, &bindGroupLayout);
// The binding type in the bind group layout must the same as the related image object
// declared in shader.
if ((bindingTypeInBindgroupLayout == wgpu::BindingType::ReadonlyStorageTexture &&
bindingTypeInShader == wgpu::StorageTextureAccess::ReadOnly) ||
(bindingTypeInBindgroupLayout == wgpu::BindingType::WriteonlyStorageTexture &&
bindingTypeInShader == wgpu::StorageTextureAccess::WriteOnly)) {
if (bindingLayoutEntry.storageTexture.access == bindingTypeInShader) {
device.CreateComputePipeline(&computePipelineDescriptor);
} else {
ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&computePipelineDescriptor));