SpirvShader: Don't abort for unused, unbound UniformConstants
Bug: b/126330097
Tests: dEQP-VK.glsl.discard.*
Change-Id: I17632f68705aa8f0c8c607b5ec469272a58047db
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29908
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 073f0da..60ba39b 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -1345,6 +1345,7 @@
auto set = routine->getPointer(id);
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
+ ASSERT_MSG(setLayout->hasBinding(d.Binding), "Descriptor set %d does not contain binding %d", int(d.DescriptorSet), int(d.Binding));
int bindingOffset = static_cast<int>(setLayout->getBindingOffset(d.Binding, arrayIndex));
Pointer<Byte> descriptor = set.base + bindingOffset; // BufferDescriptor*
@@ -2501,11 +2502,20 @@
uint32_t arrayIndex = 0; // TODO(b/129523279)
auto setLayout = routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
- size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
- Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
- Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // vk::SampledImageDescriptor*
- auto size = 0; // Not required as this pointer is not directly used by SIMD::Read or SIMD::Write.
- routine->createPointer(resultId, SIMD::Pointer(binding, size));
+ if (setLayout->hasBinding(d.Binding))
+ {
+ size_t bindingOffset = setLayout->getBindingOffset(d.Binding, arrayIndex);
+ Pointer<Byte> set = routine->descriptorSets[d.DescriptorSet]; // DescriptorSet*
+ Pointer<Byte> binding = Pointer<Byte>(set + bindingOffset); // vk::SampledImageDescriptor*
+ auto size = 0; // Not required as this pointer is not directly used by SIMD::Read or SIMD::Write.
+ routine->createPointer(resultId, SIMD::Pointer(binding, size));
+ }
+ else
+ {
+ // TODO: Error if the variable with the non-existant binding is
+ // used? Or perhaps strip these unused variable declarations as
+ // a preprocess on the SPIR-V?
+ }
break;
}
case spv::StorageClassUniform:
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index da86116..b84079c 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -175,6 +175,18 @@
return bindingCount;
}
+bool DescriptorSetLayout::hasBinding(uint32_t binding) const
+{
+ for(uint32_t i = 0; i < bindingCount; i++)
+ {
+ if(binding == bindings[i].binding)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
size_t DescriptorSetLayout::getBindingStride(uint32_t binding) const
{
uint32_t index = getBindingIndex(binding);
diff --git a/src/Vulkan/VkDescriptorSetLayout.hpp b/src/Vulkan/VkDescriptorSetLayout.hpp
index be92b4e..627922a 100644
--- a/src/Vulkan/VkDescriptorSetLayout.hpp
+++ b/src/Vulkan/VkDescriptorSetLayout.hpp
@@ -78,6 +78,9 @@
// Returns the number of bindings in the descriptor set.
size_t getBindingCount() const;
+ // Returns true iff the given binding exists.
+ bool hasBinding(uint32_t binding) const;
+
// Returns the byte offset from the base address of the descriptor set for
// the given binding and array element within that binding.
size_t getBindingOffset(uint32_t binding, size_t arrayElement) const;