From 3af532b8a8302e063847c5d1a5ca210b0170d182 Mon Sep 17 00:00:00 2001 From: Brandon Jones Date: Mon, 21 Dec 2020 20:14:26 +0000 Subject: [PATCH] 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 Reviewed-by: Corentin Wallez Reviewed-by: Austin Eng Auto-Submit: Brandon Jones --- src/dawn_native/BindGroup.cpp | 139 +++++---- src/dawn_native/BindGroupLayout.cpp | 284 ++++++++++-------- src/dawn_native/BindingInfo.h | 21 +- src/dawn_native/Format.cpp | 19 ++ src/dawn_native/Format.h | 2 + src/dawn_native/PipelineLayout.cpp | 56 +++- src/dawn_native/ProgrammablePassEncoder.cpp | 72 ++--- src/dawn_native/ShaderModule.cpp | 203 +++++++------ src/dawn_native/ShaderModule.h | 1 - src/dawn_native/SpirvUtils.cpp | 14 + src/dawn_native/SpirvUtils.h | 2 + src/dawn_native/d3d12/BindGroupD3D12.cpp | 164 +++++----- .../d3d12/BindGroupLayoutD3D12.cpp | 72 +++-- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 102 +++---- src/dawn_native/d3d12/PipelineLayoutD3D12.cpp | 20 +- .../d3d12/SamplerHeapCacheD3D12.cpp | 3 +- src/dawn_native/d3d12/ShaderModuleD3D12.cpp | 5 +- src/dawn_native/metal/CommandBufferMTL.mm | 20 +- src/dawn_native/metal/PipelineLayoutMTL.mm | 19 +- src/dawn_native/opengl/BindGroupGL.cpp | 34 +-- src/dawn_native/opengl/CommandBufferGL.cpp | 66 ++-- src/dawn_native/opengl/PipelineGL.cpp | 70 ++--- src/dawn_native/opengl/PipelineLayoutGL.cpp | 40 +-- src/dawn_native/opengl/ShaderModuleGL.cpp | 11 +- src/dawn_native/vulkan/BindGroupLayoutVk.cpp | 47 ++- src/dawn_native/vulkan/BindGroupLayoutVk.h | 2 +- src/dawn_native/vulkan/BindGroupVk.cpp | 21 +- src/dawn_native/vulkan/CommandBufferVk.cpp | 47 ++- .../StorageTextureValidationTests.cpp | 34 +-- 29 files changed, 812 insertions(+), 778 deletions(-) diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp index 96c4921a22..c84d578272 100644 --- a/src/dawn_native/BindGroup.cpp +++ b/src/dawn_native/BindGroup.cpp @@ -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::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::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(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(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(mBindingData.bindings[bindingIndex].Get()); } diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp index 4f34921310..3d95e3bef4 100644 --- a/src/dawn_native/BindGroupLayout.cpp +++ b/src/dawn_native/BindGroupLayout.cpp @@ -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::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(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(); diff --git a/src/dawn_native/BindingInfo.h b/src/dawn_native/BindingInfo.h index 58247812d3..ef3c7ac1aa 100644 --- a/src/dawn_native/BindingInfo.h +++ b/src/dawn_native/BindingInfo.h @@ -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 { diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp index f57b7b4178..f1d7d163a0 100644 --- a/src/dawn_native/Format.cpp +++ b/src/dawn_native/Format.cpp @@ -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(1 << static_cast(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; } diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h index ec4d6b44ff..fe0c41fc45 100644 --- a/src/dawn_native/Format.h +++ b/src/dawn_native/Format.h @@ -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; diff --git a/src/dawn_native/PipelineLayout.cpp b/src/dawn_native/PipelineLayout.cpp index 75839c7b6a..b1317ae817 100644 --- a/src/dawn_native/PipelineLayout.cpp +++ b/src/dawn_native/PipelineLayout.cpp @@ -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; }; diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp index 9044ff101a..20762962c7 100644 --- a/src/dawn_native/ProgrammablePassEncoder.cpp +++ b/src/dawn_native/ProgrammablePassEncoder.cpp @@ -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"); diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp index ecd7454120..df68e3c643 100644 --- a/src/dawn_native/ShaderModule.cpp +++ b/src/dawn_native/ShaderModule.cpp @@ -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& 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) { diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h index 2126ddad3b..bedeb22227 100644 --- a/src/dawn_native/ShaderModule.h +++ b/src/dawn_native/ShaderModule.h @@ -101,7 +101,6 @@ namespace dawn_native { private: // Disallow access to unused members. - using BindingInfo::hasDynamicOffset; using BindingInfo::visibility; }; diff --git a/src/dawn_native/SpirvUtils.cpp b/src/dawn_native/SpirvUtils.cpp index 511bade1cc..fafd6c2247 100644 --- a/src/dawn_native/SpirvUtils.cpp +++ b/src/dawn_native/SpirvUtils.cpp @@ -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 diff --git a/src/dawn_native/SpirvUtils.h b/src/dawn_native/SpirvUtils.h index cd39c04985..9ed94a5f8d 100644 --- a/src/dawn_native/SpirvUtils.h +++ b/src/dawn_native/SpirvUtils.h @@ -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 diff --git a/src/dawn_native/d3d12/BindGroupD3D12.cpp b/src/dawn_native/d3d12/BindGroupD3D12.cpp index 9370dc361b..a410807861 100644 --- a/src/dawn_native/d3d12/BindGroupD3D12.cpp +++ b/src/dawn_native/d3d12/BindGroupD3D12.cpp @@ -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(); } } } diff --git a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp index dae4786446..449a07a5ff 100644 --- a/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp +++ b/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp @@ -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]; } diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 02a2c18868..2191665c50 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -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(); } } diff --git a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp index bf5c039d22..f5e21dba74 100644 --- a/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp +++ b/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp @@ -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]; diff --git a/src/dawn_native/d3d12/SamplerHeapCacheD3D12.cpp b/src/dawn_native/d3d12/SamplerHeapCacheD3D12.cpp index 8ba3aab319..d1d6f3f011 100644 --- a/src/dawn_native/d3d12/SamplerHeapCacheD3D12.cpp +++ b/src/dawn_native/d3d12/SamplerHeapCacheD3D12.cpp @@ -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))); } } diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp index 8daf85484d..3c34203b5d 100644 --- a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp +++ b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp @@ -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); diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index 2e3c58bf58..aaf250e4e8 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm @@ -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 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(); } } } diff --git a/src/dawn_native/metal/PipelineLayoutMTL.mm b/src/dawn_native/metal/PipelineLayoutMTL.mm index f7efd8f794..3951ef539a 100644 --- a/src/dawn_native/metal/PipelineLayoutMTL.mm +++ b/src/dawn_native/metal/PipelineLayoutMTL.mm @@ -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(); } } } diff --git a/src/dawn_native/opengl/BindGroupGL.cpp b/src/dawn_native/opengl/BindGroupGL.cpp index 02c1af4564..486eb2c51b 100644 --- a/src/dawn_native/opengl/BindGroupGL.cpp +++ b/src/dawn_native/opengl/BindGroupGL.cpp @@ -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."); + } } } diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index fd5b00a199..7d1a274a16 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -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(); } } } diff --git a/src/dawn_native/opengl/PipelineGL.cpp b/src/dawn_native/opengl/PipelineGL.cpp index 562f2562a2..0039c1eb5c 100644 --- a/src/dawn_native/opengl/PipelineGL.cpp +++ b/src/dawn_native/opengl/PipelineGL.cpp @@ -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) { diff --git a/src/dawn_native/opengl/PipelineLayoutGL.cpp b/src/dawn_native/opengl/PipelineLayoutGL.cpp index 7161bfb431..088eaf38a9 100644 --- a/src/dawn_native/opengl/PipelineLayoutGL.cpp +++ b/src/dawn_native/opengl/PipelineLayoutGL.cpp @@ -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(); } } } diff --git a/src/dawn_native/opengl/ShaderModuleGL.cpp b/src/dawn_native/opengl/ShaderModuleGL.cpp index 647ce4957a..b3bcfb22ab 100644 --- a/src/dawn_native/opengl/ShaderModuleGL.cpp +++ b/src/dawn_native/opengl/ShaderModuleGL.cpp @@ -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); diff --git a/src/dawn_native/vulkan/BindGroupLayoutVk.cpp b/src/dawn_native/vulkan/BindGroupLayoutVk.cpp index 24f49cfe4f..9bb379bde0 100644 --- a/src/dawn_native/vulkan/BindGroupLayoutVk.cpp +++ b/src/dawn_native/vulkan/BindGroupLayoutVk.cpp @@ -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(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 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]++; diff --git a/src/dawn_native/vulkan/BindGroupLayoutVk.h b/src/dawn_native/vulkan/BindGroupLayoutVk.h index 33f3e662ad..394cfab162 100644 --- a/src/dawn_native/vulkan/BindGroupLayoutVk.h +++ b/src/dawn_native/vulkan/BindGroupLayoutVk.h @@ -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 diff --git a/src/dawn_native/vulkan/BindGroupVk.cpp b/src/dawn_native/vulkan/BindGroupVk.cpp index 3fec844254..b99309089c 100644 --- a/src/dawn_native/vulkan/BindGroupVk.cpp +++ b/src/dawn_native/vulkan/BindGroupVk.cpp @@ -60,13 +60,10 @@ namespace dawn_native { namespace vulkan { write.dstBinding = static_cast(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++; diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index b2a90b89a4..6acab4dee3 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -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(); } } } diff --git a/src/tests/unittests/validation/StorageTextureValidationTests.cpp b/src/tests/unittests/validation/StorageTextureValidationTests.cpp index 38897d46be..c3433cf18a 100644 --- a/src/tests/unittests/validation/StorageTextureValidationTests.cpp +++ b/src/tests/unittests/validation/StorageTextureValidationTests.cpp @@ -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 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 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));