Improve runtime minBindingSize validation message The message now reports the group/number of the binding that failed validation, as well as the buffer. Bug: dawn:1604 Change-Id: Ib08a3eace5ec5ebaf9eecce01eb397b5c0681bd1 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131843 Reviewed-by: Brandon Jones <bajones@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp index c1345ca..47c6929 100644 --- a/src/dawn/native/BindGroup.cpp +++ b/src/dawn/native/BindGroup.cpp
@@ -253,6 +253,16 @@ return {}; } +template <typename F> +void ForEachUnverifiedBufferBindingIndexImpl(const BindGroupLayoutBase* bgl, F&& f) { + uint32_t packedIndex = 0; + for (BindingIndex bindingIndex{0}; bindingIndex < bgl->GetBufferCount(); ++bindingIndex) { + if (bgl->GetBindingInfo(bindingIndex).buffer.minBindingSize == 0) { + f(bindingIndex, packedIndex++); + } + } +} + } // anonymous namespace MaybeError ValidateBindGroupDescriptor(DeviceBase* device, @@ -351,7 +361,7 @@ ASSERT(bindingsSet.count() == descriptor->layout->GetUnexpandedBindingCount()); return {}; -} // anonymous namespace +} // BindGroup @@ -443,15 +453,11 @@ } } - uint32_t packedIdx = 0; - for (BindingIndex bindingIndex{0}; bindingIndex < descriptor->layout->GetBufferCount(); - ++bindingIndex) { - if (descriptor->layout->GetBindingInfo(bindingIndex).buffer.minBindingSize == 0) { - mBindingData.unverifiedBufferSizes[packedIdx] = - mBindingData.bufferData[bindingIndex].size; - ++packedIdx; - } - } + ForEachUnverifiedBufferBindingIndexImpl(mLayout.Get(), + [&](BindingIndex bindingIndex, uint32_t packedIndex) { + mBindingData.unverifiedBufferSizes[packedIndex] = + mBindingData.bufferData[bindingIndex].size; + }); GetObjectTrackingList()->Track(this); } @@ -530,4 +536,9 @@ return mBoundExternalTextures; } +void BindGroupBase::ForEachUnverifiedBufferBindingIndex( + std::function<void(BindingIndex, uint32_t)> fn) const { + ForEachUnverifiedBufferBindingIndexImpl(mLayout.Get(), fn); +} + } // namespace dawn::native
diff --git a/src/dawn/native/BindGroup.h b/src/dawn/native/BindGroup.h index c8a2c4f..922d813 100644 --- a/src/dawn/native/BindGroup.h +++ b/src/dawn/native/BindGroup.h
@@ -56,6 +56,8 @@ const ityp::span<uint32_t, uint64_t>& GetUnverifiedBufferSizes() const; const std::vector<Ref<ExternalTextureBase>>& GetBoundExternalTextures() const; + void ForEachUnverifiedBufferBindingIndex(std::function<void(BindingIndex, uint32_t)> fn) const; + protected: // To save memory, the size of a bind group is dynamically determined and the bind group is // placement-allocated into memory big enough to hold the bind group with its
diff --git a/src/dawn/native/CommandBufferStateTracker.cpp b/src/dawn/native/CommandBufferStateTracker.cpp index 8f018da..fae24bd 100644 --- a/src/dawn/native/CommandBufferStateTracker.cpp +++ b/src/dawn/native/CommandBufferStateTracker.cpp
@@ -14,6 +14,7 @@ #include "dawn/native/CommandBufferStateTracker.h" +#include <limits> #include <optional> #include <type_traits> #include <utility> @@ -573,22 +574,40 @@ requiredBGL, mLastPipelineLayout, currentBGL, mBindgroups[i], static_cast<uint32_t>(i)); - // TODO(dawn:563): Report which buffer bindings are failing. This requires the ability - // to look up the binding index from the packed index. std::optional<uint32_t> packedIndex = FindFirstUndersizedBuffer( mBindgroups[i]->GetUnverifiedBufferSizes(), (*mMinBufferSizes)[i]); if (packedIndex.has_value()) { + // Find the binding index for this packed index. + BindingIndex bindingIndex{std::numeric_limits<uint32_t>::max()}; + mBindgroups[i]->ForEachUnverifiedBufferBindingIndex( + [&](BindingIndex candidateBindingIndex, uint32_t candidatePackedIndex) { + if (candidatePackedIndex == *packedIndex) { + bindingIndex = candidateBindingIndex; + } + }); + ASSERT(static_cast<uint32_t>(bindingIndex) != std::numeric_limits<uint32_t>::max()); + + const auto& bindingInfo = mBindgroups[i]->GetLayout()->GetBindingInfo(bindingIndex); + const BufferBinding& bufferBinding = + mBindgroups[i]->GetBindingAsBufferBinding(bindingIndex); + + BindingNumber bindingNumber = bindingInfo.binding; + const BufferBase* buffer = bufferBinding.buffer; + uint64_t bufferSize = mBindgroups[i]->GetUnverifiedBufferSizes()[packedIndex.value()]; uint64_t minBufferSize = (*mMinBufferSizes)[i][packedIndex.value()]; + return DAWN_VALIDATION_ERROR( - "Binding sizes are too small for %s set at group index %u. A bound buffer " - "contained %u bytes, but the current pipeline (%s) requires a buffer which is " - "at least %u bytes. (Note that uniform buffer bindings must be a multiple of " - "16 bytes, and as a result may be larger than the associated data in the " - "shader source.)", - mBindgroups[i], static_cast<uint32_t>(i), bufferSize, mLastPipeline, - minBufferSize); + "%s bound with size %u at group %u, binding %u is too small. The pipeline (%s) " + "requires a buffer binding which is at least %u bytes.%s", + buffer, bufferSize, static_cast<uint32_t>(i), + static_cast<uint32_t>(bindingNumber), mLastPipeline, minBufferSize, + (bindingInfo.buffer.type == wgpu::BufferBindingType::Uniform + ? " This binding is a uniform buffer binding. It is padded to a multiple " + "of 16 bytes, and as a result may be larger than the associated data in " + "the shader source." + : "")); } }