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));