diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp index a96843c848..4242c725f7 100644 --- a/src/dawn/native/BindGroup.cpp +++ b/src/dawn/native/BindGroup.cpp @@ -269,9 +269,10 @@ namespace dawn::native { DAWN_INVALID_IF( descriptor->entryCount != descriptor->layout->GetUnexpandedBindingCount(), - "Number of entries (%u) did not match the number of entries (%u) specified in %s", + "Number of entries (%u) did not match the number of entries (%u) specified in %s." + "\nExpected layout: %s", descriptor->entryCount, static_cast(descriptor->layout->GetBindingCount()), - descriptor->layout); + descriptor->layout, descriptor->layout->EntriesToString()); const BindGroupLayoutBase::BindingMap& bindingMap = descriptor->layout->GetBindingMap(); ASSERT(bindingMap.size() <= kMaxBindingsPerPipelineLayout); @@ -282,8 +283,9 @@ namespace dawn::native { const auto& it = bindingMap.find(BindingNumber(entry.binding)); DAWN_INVALID_IF(it == bindingMap.end(), - "In entries[%u], binding index %u not present in the bind group layout", - i, entry.binding); + "In entries[%u], binding index %u not present in the bind group layout." + "\nExpected layout: %s", + i, entry.binding, descriptor->layout->EntriesToString()); BindingIndex bindingIndex = it->second; ASSERT(bindingIndex < descriptor->layout->GetBindingCount()); @@ -315,16 +317,22 @@ namespace dawn::native { switch (bindingInfo.bindingType) { case BindingInfoType::Buffer: DAWN_TRY_CONTEXT(ValidateBufferBinding(device, entry, bindingInfo), - "validating entries[%u] as a Buffer", i); + "validating entries[%u] as a Buffer." + "\nExpected entry layout: %s", + i, bindingInfo); break; case BindingInfoType::Texture: case BindingInfoType::StorageTexture: DAWN_TRY_CONTEXT(ValidateTextureBinding(device, entry, bindingInfo), - "validating entries[%u] as a Texture", i); + "validating entries[%u] as a Texture." + "\nExpected entry layout: %s", + i, bindingInfo); break; case BindingInfoType::Sampler: DAWN_TRY_CONTEXT(ValidateSamplerBinding(device, entry, bindingInfo), - "validating entries[%u] as a Sampler", i); + "validating entries[%u] as a Sampler." + "\nExpected entry layout: %s", + i, bindingInfo); break; case BindingInfoType::ExternalTexture: UNREACHABLE(); diff --git a/src/dawn/native/BindGroupLayout.cpp b/src/dawn/native/BindGroupLayout.cpp index a7378abc4b..9f5e151f5c 100644 --- a/src/dawn/native/BindGroupLayout.cpp +++ b/src/dawn/native/BindGroupLayout.cpp @@ -656,4 +656,15 @@ namespace dawn::native { } } + std::string BindGroupLayoutBase::EntriesToString() const { + std::string entries = " ["; + const BindGroupLayoutBase::BindingMap& bindingMap = GetBindingMap(); + for (const auto [bindingNumber, bindingIndex] : bindingMap) { + const BindingInfo& bindingInfo = GetBindingInfo(bindingIndex); + entries += absl::StrFormat("%s, ", bindingInfo); + } + entries += "]"; + return entries; + } + } // namespace dawn::native diff --git a/src/dawn/native/BindGroupLayout.h b/src/dawn/native/BindGroupLayout.h index 2dfb846cd1..5b91a2fd4e 100644 --- a/src/dawn/native/BindGroupLayout.h +++ b/src/dawn/native/BindGroupLayout.h @@ -130,6 +130,9 @@ namespace dawn::native { bool IsStorageBufferBinding(BindingIndex bindingIndex) const; + // Returns a detailed string representation of the layout entries for use in error messages. + std::string EntriesToString() const; + protected: // Constructor used only for mocking and testing. BindGroupLayoutBase(DeviceBase* device); diff --git a/src/dawn/native/BindingInfo.cpp b/src/dawn/native/BindingInfo.cpp index ce4632c903..af4905a18f 100644 --- a/src/dawn/native/BindingInfo.cpp +++ b/src/dawn/native/BindingInfo.cpp @@ -44,6 +44,51 @@ namespace dawn::native { return {true}; } + absl::FormatConvertResult AbslFormatConvert( + const BindingInfo& value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s) { + s->Append(absl::StrFormat("{\n binding: %u\n visibility: %s\n %s: {\n", + static_cast(value.binding), value.visibility, + value.bindingType)); + + switch (value.bindingType) { + case BindingInfoType::Buffer: + s->Append(absl::StrFormat(" type: %s\n", value.buffer.type)); + if (value.buffer.hasDynamicOffset) { + s->Append(" hasDynamicOffset: true\n"); + } + if (value.buffer.minBindingSize != 0) { + s->Append( + absl::StrFormat(" minBindingSize: %u\n", value.buffer.minBindingSize)); + } + break; + case BindingInfoType::Sampler: + s->Append(absl::StrFormat(" type: %s\n", value.sampler.type)); + break; + case BindingInfoType::Texture: + s->Append(absl::StrFormat(" sampleType: %s\n", value.texture.sampleType)); + s->Append(absl::StrFormat(" viewDimension: %s\n", value.texture.viewDimension)); + if (value.texture.multisampled) { + s->Append(" multisampled: true\n"); + } else { + s->Append(" multisampled: false\n"); + } + break; + case BindingInfoType::StorageTexture: + s->Append(absl::StrFormat(" access: %s\n", value.storageTexture.access)); + s->Append(absl::StrFormat(" format: %s\n", value.storageTexture.format)); + s->Append( + absl::StrFormat(" viewDimension: %s\n", value.storageTexture.viewDimension)); + break; + case BindingInfoType::ExternalTexture: + break; + } + + s->Append(" }\n}"); + return {true}; + } + void IncrementBindingCounts(BindingCounts* bindingCounts, const BindGroupLayoutEntry& entry) { bindingCounts->totalCount += 1; diff --git a/src/dawn/native/BindingInfo.h b/src/dawn/native/BindingInfo.h index 24676c840e..8e4f8c3fb5 100644 --- a/src/dawn/native/BindingInfo.h +++ b/src/dawn/native/BindingInfo.h @@ -68,6 +68,11 @@ namespace dawn::native { StorageTextureBindingLayout storageTexture; }; + absl::FormatConvertResult AbslFormatConvert( + const BindingInfo& value, + const absl::FormatConversionSpec& spec, + absl::FormatSink* s); + struct BindingSlot { BindGroupIndex group; BindingNumber binding;