Represent uniform facts via descriptor set and binding. (#2681)
* Represent uniform facts via descriptor set and binding.
Previously uniform facts were expressed with resepect to the id of a
uniform variable. Describing them with respect to a descriptor set
and binding is more convenient from the point of view of expressing
facts about a shader without requiring analysis of its SPIR-V.
* Fix equality testing for uniform buffer element descriptors.
The equality test now checks that the lengths of the index vectors
match. Added a test that exposes the previous omission.
diff --git a/source/fuzz/fact_manager.cpp b/source/fuzz/fact_manager.cpp
index 407881b..9cb6896 100644
--- a/source/fuzz/fact_manager.cpp
+++ b/source/fuzz/fact_manager.cpp
@@ -201,20 +201,21 @@
bool FactManager::ConstantUniformFacts::AddFact(
const protobufs::FactConstantUniform& fact, opt::IRContext* context) {
- auto should_be_uniform_variable = context->get_def_use_mgr()->GetDef(
- fact.uniform_buffer_element_descriptor().uniform_variable_id());
- if (!should_be_uniform_variable) {
+ // Try to find a unique instruction that declares a variable such that the
+ // variable is decorated with the descriptor set and binding associated with
+ // the constant uniform fact.
+ opt::Instruction* uniform_variable = FindUniformVariable(
+ fact.uniform_buffer_element_descriptor(), context, true);
+
+ if (!uniform_variable) {
return false;
}
- if (SpvOpVariable != should_be_uniform_variable->opcode()) {
- return false;
- }
- if (SpvStorageClassUniform !=
- should_be_uniform_variable->GetSingleWordInOperand(0)) {
- return false;
- }
+
+ assert(SpvOpVariable == uniform_variable->opcode());
+ assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0));
+
auto should_be_uniform_pointer_type =
- context->get_type_mgr()->GetType(should_be_uniform_variable->type_id());
+ context->get_type_mgr()->GetType(uniform_variable->type_id());
if (!should_be_uniform_pointer_type->AsPointer()) {
return false;
}
@@ -223,7 +224,7 @@
return false;
}
auto should_be_uniform_pointer_instruction =
- context->get_def_use_mgr()->GetDef(should_be_uniform_variable->type_id());
+ context->get_def_use_mgr()->GetDef(uniform_variable->type_id());
auto element_type =
should_be_uniform_pointer_instruction->GetSingleWordInOperand(1);
diff --git a/source/fuzz/protobufs/spvtoolsfuzz.proto b/source/fuzz/protobufs/spvtoolsfuzz.proto
index 941a2ca..aecd4c7 100644
--- a/source/fuzz/protobufs/spvtoolsfuzz.proto
+++ b/source/fuzz/protobufs/spvtoolsfuzz.proto
@@ -64,8 +64,9 @@
// is contained, and (b) a series of indices that need to be followed to get
// to the element (via fields and array/vector indices).
//
- // Example: suppose %42 is the id of a uniform variable, and that the uniform
- // variable has the following type (using GLSL-like syntax):
+ // Example: suppose there is a uniform variable with descriptor set 7 and
+ // binding 9, and that the uniform variable has the following type (using
+ // GLSL-like syntax):
//
// struct S {
// float f;
@@ -74,16 +75,17 @@
// };
//
// Then:
- // - 42[0] describes the 'f' field.
- // - 42[1,1] describes the y component of the 'g' field.
- // - 42[2,7,3] describes the w component of element 7 of the 'h' field
+ // - (7, 9, [0]) describes the 'f' field.
+ // - (7, 9, [1,1]) describes the y component of the 'g' field.
+ // - (7, 9, [2,7,3]) describes the w component of element 7 of the 'h' field
- // The result id of a uniform variable.
- uint32 uniform_variable_id = 1;
+ // The descriptor set and binding associated with a uniform variable.
+ uint32 descriptor_set = 1;
+ uint32 binding = 2;
// An ordered sequence of indices through composite structures in the
// uniform buffer.
- repeated uint32 index = 2;
+ repeated uint32 index = 3;
}
diff --git a/source/fuzz/transformation_replace_constant_with_uniform.cpp b/source/fuzz/transformation_replace_constant_with_uniform.cpp
index fce458c..cc6e137 100644
--- a/source/fuzz/transformation_replace_constant_with_uniform.cpp
+++ b/source/fuzz/transformation_replace_constant_with_uniform.cpp
@@ -15,6 +15,7 @@
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/uniform_buffer_element_descriptor.h"
namespace spvtools {
namespace fuzz {
@@ -28,10 +29,12 @@
// The input operands for the access chain.
opt::Instruction::OperandList operands_for_access_chain;
+ opt::Instruction* uniform_variable =
+ FindUniformVariable(message.uniform_descriptor(), context, false);
+
// The first input operand is the id of the uniform variable.
operands_for_access_chain.push_back(
- {SPV_OPERAND_TYPE_ID,
- {message.uniform_descriptor().uniform_variable_id()}});
+ {SPV_OPERAND_TYPE_ID, {uniform_variable->result_id()}});
// The other input operands are the ids of the constants used to index into
// the uniform. The uniform buffer descriptor specifies a series of literals;
diff --git a/source/fuzz/uniform_buffer_element_descriptor.cpp b/source/fuzz/uniform_buffer_element_descriptor.cpp
index cd840d3..8c758e4 100644
--- a/source/fuzz/uniform_buffer_element_descriptor.cpp
+++ b/source/fuzz/uniform_buffer_element_descriptor.cpp
@@ -14,13 +14,17 @@
#include "source/fuzz/uniform_buffer_element_descriptor.h"
+#include <source/opt/instruction.h>
+
namespace spvtools {
namespace fuzz {
protobufs::UniformBufferElementDescriptor MakeUniformBufferElementDescriptor(
- uint32_t uniform_variable_id, std::vector<uint32_t>&& indices) {
+ uint32_t descriptor_set, uint32_t binding,
+ std::vector<uint32_t>&& indices) {
protobufs::UniformBufferElementDescriptor result;
- result.set_uniform_variable_id(uniform_variable_id);
+ result.set_descriptor_set(descriptor_set);
+ result.set_binding(binding);
for (auto index : indices) {
result.add_index(index);
}
@@ -30,10 +34,85 @@
bool UniformBufferElementDescriptorEquals::operator()(
const protobufs::UniformBufferElementDescriptor* first,
const protobufs::UniformBufferElementDescriptor* second) const {
- return first->uniform_variable_id() == second->uniform_variable_id() &&
+ return first->descriptor_set() == second->descriptor_set() &&
+ first->binding() == second->binding() &&
+ first->index().size() == second->index().size() &&
std::equal(first->index().begin(), first->index().end(),
second->index().begin());
}
+opt::Instruction* FindUniformVariable(
+ const protobufs::UniformBufferElementDescriptor&
+ uniform_buffer_element_descriptor,
+ opt::IRContext* context, bool check_unique) {
+ opt::Instruction* result = nullptr;
+
+ for (auto& inst : context->types_values()) {
+ // Consider all global variables with uniform storage class.
+ if (inst.opcode() != SpvOpVariable) {
+ continue;
+ }
+ if (inst.GetSingleWordInOperand(0) != SpvStorageClassUniform) {
+ continue;
+ }
+
+ // Determine whether the variable is decorated with a descriptor set
+ // matching that in |uniform_buffer_element|.
+ bool descriptor_set_matches = false;
+ context->get_decoration_mgr()->ForEachDecoration(
+ inst.result_id(), SpvDecorationDescriptorSet,
+ [&descriptor_set_matches, &uniform_buffer_element_descriptor](
+ const opt::Instruction& decoration_inst) {
+ const uint32_t kDescriptorSetOperandIndex = 2;
+ if (decoration_inst.GetSingleWordInOperand(
+ kDescriptorSetOperandIndex) ==
+ uniform_buffer_element_descriptor.descriptor_set()) {
+ descriptor_set_matches = true;
+ }
+ });
+ if (!descriptor_set_matches) {
+ // Descriptor set does not match.
+ continue;
+ }
+
+ // Determine whether the variable is decorated with a binding matching that
+ // in |uniform_buffer_element|.
+ bool binding_matches = false;
+ context->get_decoration_mgr()->ForEachDecoration(
+ inst.result_id(), SpvDecorationBinding,
+ [&binding_matches, &uniform_buffer_element_descriptor](
+ const opt::Instruction& decoration_inst) {
+ const uint32_t kBindingOperandIndex = 2;
+ if (decoration_inst.GetSingleWordInOperand(kBindingOperandIndex) ==
+ uniform_buffer_element_descriptor.binding()) {
+ binding_matches = true;
+ }
+ });
+ if (!binding_matches) {
+ // Binding does not match.
+ continue;
+ }
+
+ // This instruction is a uniform variable with the right descriptor set and
+ // binding.
+ if (!check_unique) {
+ // If we aren't checking uniqueness, return it.
+ return &inst;
+ }
+
+ if (result) {
+ // More than one uniform variable is decorated with the given descriptor
+ // set and binding. This means the fact is ambiguous.
+ return nullptr;
+ }
+ result = &inst;
+ }
+
+ // We get here either if no match was found, or if |check_unique| holds and
+ // exactly one match was found.
+ assert(result == nullptr || check_unique);
+ return result;
+}
+
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/uniform_buffer_element_descriptor.h b/source/fuzz/uniform_buffer_element_descriptor.h
index b2e5962..23a16f0 100644
--- a/source/fuzz/uniform_buffer_element_descriptor.h
+++ b/source/fuzz/uniform_buffer_element_descriptor.h
@@ -19,6 +19,8 @@
#include <vector>
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/opt/instruction.h"
+#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
@@ -26,7 +28,7 @@
// Factory method to create a uniform buffer element descriptor message from an
// id and list of indices.
protobufs::UniformBufferElementDescriptor MakeUniformBufferElementDescriptor(
- uint32_t uniform_variable_id, std::vector<uint32_t>&& indices);
+ uint32_t descriptor_set, uint32_t binding, std::vector<uint32_t>&& indices);
// Equality function for uniform buffer element descriptors.
struct UniformBufferElementDescriptorEquals {
@@ -35,6 +37,16 @@
const protobufs::UniformBufferElementDescriptor* second) const;
};
+// Returns a pointer to an OpVariable in |context| that is decorated with the
+// descriptor set and binding associated with |uniform_buffer_element|. Returns
+// nullptr if no such variable exists. If multiple such variables exist, a
+// pointer to an arbitrary one of the associated instructions is returned if
+// |check_unique| is false, and nullptr is returned if |check_unique| is true.
+opt::Instruction* FindUniformVariable(
+ const protobufs::UniformBufferElementDescriptor&
+ uniform_buffer_element_descriptor,
+ opt::IRContext* context, bool check_unique);
+
} // namespace fuzz
} // namespace spvtools
diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt
index 454206c..7b47b55 100644
--- a/test/fuzz/CMakeLists.txt
+++ b/test/fuzz/CMakeLists.txt
@@ -31,7 +31,8 @@
transformation_move_block_down_test.cpp
transformation_replace_boolean_constant_with_constant_binary_test.cpp
transformation_replace_constant_with_uniform_test.cpp
- transformation_split_block_test.cpp)
+ transformation_split_block_test.cpp
+ uniform_buffer_element_descriptor_test.cpp)
add_spvtools_unittest(TARGET fuzz
SRCS ${SOURCES}
diff --git a/test/fuzz/fact_manager_test.cpp b/test/fuzz/fact_manager_test.cpp
index bf07f35..738f8c9 100644
--- a/test/fuzz/fact_manager_test.cpp
+++ b/test/fuzz/fact_manager_test.cpp
@@ -58,6 +58,44 @@
OpExecutionMode %4 OriginUpperLeft
OpSource GLSL 450
OpName %4 "main"
+ OpDecorate %100 DescriptorSet 0
+ OpDecorate %100 Binding 0
+ OpDecorate %200 DescriptorSet 0
+ OpDecorate %200 Binding 1
+ OpDecorate %300 DescriptorSet 0
+ OpDecorate %300 Binding 2
+ OpDecorate %400 DescriptorSet 0
+ OpDecorate %400 Binding 3
+ OpDecorate %500 DescriptorSet 0
+ OpDecorate %500 Binding 4
+ OpDecorate %600 DescriptorSet 0
+ OpDecorate %600 Binding 5
+ OpDecorate %700 DescriptorSet 0
+ OpDecorate %700 Binding 6
+ OpDecorate %800 DescriptorSet 1
+ OpDecorate %800 Binding 0
+ OpDecorate %900 DescriptorSet 1
+ OpDecorate %900 Binding 1
+ OpDecorate %1000 DescriptorSet 1
+ OpDecorate %1000 Binding 2
+ OpDecorate %1100 DescriptorSet 1
+ OpDecorate %1100 Binding 3
+ OpDecorate %1200 DescriptorSet 1
+ OpDecorate %1200 Binding 4
+ OpDecorate %1300 DescriptorSet 1
+ OpDecorate %1300 Binding 5
+ OpDecorate %1400 DescriptorSet 1
+ OpDecorate %1400 Binding 6
+ OpDecorate %1500 DescriptorSet 2
+ OpDecorate %1500 Binding 0
+ OpDecorate %1600 DescriptorSet 2
+ OpDecorate %1600 Binding 1
+ OpDecorate %1700 DescriptorSet 2
+ OpDecorate %1700 Binding 2
+ OpDecorate %1800 DescriptorSet 2
+ OpDecorate %1800 Binding 3
+ OpDecorate %1900 DescriptorSet 2
+ OpDecorate %1900 Binding 4
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%10 = OpTypeInt 32 0
@@ -231,94 +269,98 @@
type_uint32_id)
.empty());
+ // In the comments that follow we write v[...][...] to refer to uniform
+ // variable v indexed with some given indices, when in practice v is
+ // identified via a (descriptor set, binding) pair.
+
// 100[2][3] == int(1)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(100, {2, 3})));
+ MakeUniformBufferElementDescriptor(0, 0, {2, 3})));
// 200[1][2][3] == int(1)
ASSERT_TRUE(
AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(200, {1, 2, 3})));
+ MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3})));
// 300[1][0][2][3] == int(1)
ASSERT_TRUE(
AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(300, {1, 0, 2, 3})));
+ MakeUniformBufferElementDescriptor(0, 2, {1, 0, 2, 3})));
// 400[2][3] = int32_min
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]},
- MakeUniformBufferElementDescriptor(400, {2, 3})));
+ MakeUniformBufferElementDescriptor(0, 3, {2, 3})));
// 500[1][2][3] = int32_min
ASSERT_TRUE(
AddFactHelper(&fact_manager, context.get(), {buffer_int32_min[0]},
- MakeUniformBufferElementDescriptor(500, {1, 2, 3})));
+ MakeUniformBufferElementDescriptor(0, 4, {1, 2, 3})));
// 600[1][2][3] = int64_max
ASSERT_TRUE(AddFactHelper(
&fact_manager, context.get(), {buffer_int64_max[0], buffer_int64_max[1]},
- MakeUniformBufferElementDescriptor(600, {1, 2, 3})));
+ MakeUniformBufferElementDescriptor(0, 5, {1, 2, 3})));
// 700[1][1] = int64_max
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
{buffer_int64_max[0], buffer_int64_max[1]},
- MakeUniformBufferElementDescriptor(700, {1, 1})));
+ MakeUniformBufferElementDescriptor(0, 6, {1, 1})));
// 800[2][3] = uint(1)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(800, {2, 3})));
+ MakeUniformBufferElementDescriptor(1, 0, {2, 3})));
// 900[1][2][3] = uint(1)
ASSERT_TRUE(
AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(900, {1, 2, 3})));
+ MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3})));
// 1000[1][0][2][3] = uint(1)
ASSERT_TRUE(
AddFactHelper(&fact_manager, context.get(), {1},
- MakeUniformBufferElementDescriptor(1000, {1, 0, 2, 3})));
+ MakeUniformBufferElementDescriptor(1, 2, {1, 0, 2, 3})));
// 1100[0] = uint64(1)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
{buffer_uint64_1[0], buffer_uint64_1[1]},
- MakeUniformBufferElementDescriptor(1100, {0})));
+ MakeUniformBufferElementDescriptor(1, 3, {0})));
// 1200[0][0] = uint64_max
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
{buffer_uint64_max[0], buffer_uint64_max[1]},
- MakeUniformBufferElementDescriptor(1200, {0, 0})));
+ MakeUniformBufferElementDescriptor(1, 4, {0, 0})));
// 1300[1][0] = uint64_max
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(),
{buffer_uint64_max[0], buffer_uint64_max[1]},
- MakeUniformBufferElementDescriptor(1300, {1, 0})));
+ MakeUniformBufferElementDescriptor(1, 5, {1, 0})));
// 1400[6] = float(10.0)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(1400, {6})));
+ MakeUniformBufferElementDescriptor(1, 6, {6})));
// 1500[7] = float(10.0)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(1500, {7})));
+ MakeUniformBufferElementDescriptor(2, 0, {7})));
// 1600[9][9] = float(10.0)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {buffer_float_10[0]},
- MakeUniformBufferElementDescriptor(1600, {9, 9})));
+ MakeUniformBufferElementDescriptor(2, 1, {9, 9})));
// 1700[9][9][1] = double(10.0)
ASSERT_TRUE(AddFactHelper(
&fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]},
- MakeUniformBufferElementDescriptor(1700, {9, 9, 1})));
+ MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1})));
// 1800[9][9][2] = double(10.0)
ASSERT_TRUE(AddFactHelper(
&fact_manager, context.get(), {buffer_double_10[0], buffer_double_10[1]},
- MakeUniformBufferElementDescriptor(1800, {9, 9, 2})));
+ MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2})));
// 1900[0][0][0][0][0] = double(20.0)
ASSERT_TRUE(AddFactHelper(
&fact_manager, context.get(), {buffer_double_20[0], buffer_double_20[1]},
- MakeUniformBufferElementDescriptor(1900, {0, 0, 0, 0, 0})));
+ MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0})));
opt::Instruction::OperandList operands = {
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
@@ -429,12 +471,12 @@
context.get(), double_constant_ids[0]);
ASSERT_EQ(2, descriptors_for_double_10.size());
{
- auto temp = MakeUniformBufferElementDescriptor(1700, {9, 9, 1});
+ auto temp = MakeUniformBufferElementDescriptor(2, 2, {9, 9, 1});
ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
&temp, &descriptors_for_double_10[0]));
}
{
- auto temp = MakeUniformBufferElementDescriptor(1800, {9, 9, 2});
+ auto temp = MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2});
ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
&temp, &descriptors_for_double_10[1]));
}
@@ -443,17 +485,17 @@
context.get(), double_constant_ids[1]);
ASSERT_EQ(1, descriptors_for_double_20.size());
{
- auto temp = MakeUniformBufferElementDescriptor(1900, {0, 0, 0, 0, 0});
+ auto temp = MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0});
ASSERT_TRUE(UniformBufferElementDescriptorEquals()(
&temp, &descriptors_for_double_20[0]));
}
auto constant_1_id = fact_manager.GetConstantFromUniformDescriptor(
- context.get(), MakeUniformBufferElementDescriptor(1800, {9, 9, 2}));
+ context.get(), MakeUniformBufferElementDescriptor(2, 3, {9, 9, 2}));
ASSERT_TRUE(constant_1_id);
auto constant_2_id = fact_manager.GetConstantFromUniformDescriptor(
- context.get(), MakeUniformBufferElementDescriptor(1900, {0, 0, 0, 0, 0}));
+ context.get(), MakeUniformBufferElementDescriptor(2, 4, {0, 0, 0, 0, 0}));
ASSERT_TRUE(constant_2_id);
ASSERT_EQ(double_constant_ids[0], constant_1_id);
@@ -505,9 +547,9 @@
FactManager fact_manager;
auto uniform_buffer_element_descriptor =
- MakeUniformBufferElementDescriptor(12, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
- // 12[0] = int(1)
+ // (0, 0, [0]) = int(1)
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), {1},
uniform_buffer_element_descriptor));
auto constants =
@@ -569,12 +611,11 @@
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
-
auto uniform_buffer_element_descriptor_f =
- MakeUniformBufferElementDescriptor(9, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
auto uniform_buffer_element_descriptor_d =
- MakeUniformBufferElementDescriptor(9, {1});
+ MakeUniformBufferElementDescriptor(0, 0, {1});
if (std::numeric_limits<float>::has_infinity) {
// f == +inf
@@ -626,6 +667,77 @@
}
}
+TEST(FactManagerTest, AmbiguousFact) {
+ // This test came from the following GLSL:
+ //
+ // #version 310 es
+ //
+ // precision highp float;
+ //
+ // layout(set = 0, binding = 0) uniform buf {
+ // float f;
+ // };
+ //
+ // layout(set = 0, binding = 0) uniform buf2 {
+ // float g;
+ // };
+ //
+ // void main() {
+ //
+ // }
+
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "buf"
+ OpMemberName %7 0 "f"
+ OpName %9 ""
+ OpName %10 "buf2"
+ OpMemberName %10 0 "g"
+ OpName %12 ""
+ OpMemberDecorate %7 0 Offset 0
+ OpDecorate %7 Block
+ OpDecorate %9 DescriptorSet 0
+ OpDecorate %9 Binding 0
+ OpMemberDecorate %10 0 Offset 0
+ OpDecorate %10 Block
+ OpDecorate %12 DescriptorSet 0
+ OpDecorate %12 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6
+ %8 = OpTypePointer Uniform %7
+ %9 = OpVariable %8 Uniform
+ %10 = OpTypeStruct %6
+ %11 = OpTypePointer Uniform %10
+ %12 = OpVariable %11 Uniform
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ ASSERT_TRUE(IsValid(env, context.get()));
+
+ FactManager fact_manager;
+ auto uniform_buffer_element_descriptor =
+ MakeUniformBufferElementDescriptor(0, 0, {0});
+
+ // The fact cannot be added because it is ambiguous: there are two uniforms
+ // with descriptor set 0 and binding 0.
+ ASSERT_FALSE(AddFactHelper(&fact_manager, context.get(), {1},
+ uniform_buffer_element_descriptor));
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools
diff --git a/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp b/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
index 3cea325..89f006e 100644
--- a/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
+++ b/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
@@ -180,30 +180,30 @@
// buf.s.x == 200
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200,
- MakeUniformBufferElementDescriptor(14, {0, 0})));
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0})));
// buf.s.y == 0.5
const float float_value = 0.5;
uint32_t float_value_as_uint;
memcpy(&float_value_as_uint, &float_value, sizeof(float_value));
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_value_as_uint,
- MakeUniformBufferElementDescriptor(14, {0, 1})));
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1})));
// buf.s.z == 300
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 300,
- MakeUniformBufferElementDescriptor(14, {0, 2})));
+ MakeUniformBufferElementDescriptor(0, 0, {0, 2})));
// buf.s.w == 400
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 400,
- MakeUniformBufferElementDescriptor(14, {0, 3})));
+ MakeUniformBufferElementDescriptor(0, 0, {0, 3})));
// buf.w[6] = 22
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22,
- MakeUniformBufferElementDescriptor(14, {1, 6})));
+ MakeUniformBufferElementDescriptor(0, 0, {1, 6})));
// buf.w[8] = 23
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 23,
- MakeUniformBufferElementDescriptor(14, {1, 8})));
+ MakeUniformBufferElementDescriptor(0, 0, {1, 8})));
// Assert some things about the module that are not true prior to adding the
// pass
diff --git a/test/fuzz/fuzzer_replayer_test.cpp b/test/fuzz/fuzzer_replayer_test.cpp
index bd753af..8b3775b 100644
--- a/test/fuzz/fuzzer_replayer_test.cpp
+++ b/test/fuzz/fuzzer_replayer_test.cpp
@@ -951,7 +951,7 @@
{
protobufs::FactConstantUniform resolution_x_eq_250;
*resolution_x_eq_250.mutable_uniform_buffer_element_descriptor() =
- MakeUniformBufferElementDescriptor(24, {0, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0});
*resolution_x_eq_250.mutable_constant_word()->Add() = 250;
protobufs::Fact temp;
*temp.mutable_constant_uniform_fact() = resolution_x_eq_250;
@@ -960,7 +960,7 @@
{
protobufs::FactConstantUniform resolution_y_eq_100;
*resolution_y_eq_100.mutable_uniform_buffer_element_descriptor() =
- MakeUniformBufferElementDescriptor(24, {0, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1});
*resolution_y_eq_100.mutable_constant_word()->Add() = 100;
protobufs::Fact temp;
*temp.mutable_constant_uniform_fact() = resolution_y_eq_100;
diff --git a/test/fuzz/transformation_replace_constant_with_uniform_test.cpp b/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
index b3a0ccd..5a10173 100644
--- a/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
+++ b/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
@@ -104,11 +104,11 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_a =
- MakeUniformBufferElementDescriptor(18, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
protobufs::UniformBufferElementDescriptor blockname_b =
- MakeUniformBufferElementDescriptor(18, {1});
+ MakeUniformBufferElementDescriptor(0, 0, {1});
protobufs::UniformBufferElementDescriptor blockname_c =
- MakeUniformBufferElementDescriptor(18, {2});
+ MakeUniformBufferElementDescriptor(0, 0, {2});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_a));
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_b));
@@ -157,9 +157,9 @@
// The following transformations do not apply because the uniform descriptors
// are not sensible.
protobufs::UniformBufferElementDescriptor nonsense_uniform_descriptor1 =
- MakeUniformBufferElementDescriptor(19, {0});
+ MakeUniformBufferElementDescriptor(1, 2, {0});
protobufs::UniformBufferElementDescriptor nonsense_uniform_descriptor2 =
- MakeUniformBufferElementDescriptor(18, {5});
+ MakeUniformBufferElementDescriptor(0, 0, {5});
ASSERT_FALSE(transformation::IsApplicable(
transformation::MakeTransformationReplaceConstantWithUniform(
use_of_9_in_store, nonsense_uniform_descriptor1, 101, 102),
@@ -473,13 +473,13 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_1 =
- MakeUniformBufferElementDescriptor(28, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
protobufs::UniformBufferElementDescriptor blockname_2 =
- MakeUniformBufferElementDescriptor(28, {1, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {1, 1});
protobufs::UniformBufferElementDescriptor blockname_3 =
- MakeUniformBufferElementDescriptor(28, {1, 0, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {1, 0, 0});
protobufs::UniformBufferElementDescriptor blockname_4 =
- MakeUniformBufferElementDescriptor(28, {1, 0, 1, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {1, 0, 1, 0});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_1));
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_2));
@@ -712,7 +712,7 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_0 =
- MakeUniformBufferElementDescriptor(12, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 0, blockname_0));
@@ -786,9 +786,9 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_0 =
- MakeUniformBufferElementDescriptor(12, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
protobufs::UniformBufferElementDescriptor blockname_9 =
- MakeUniformBufferElementDescriptor(12, {1});
+ MakeUniformBufferElementDescriptor(0, 0, {1});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9));
@@ -859,7 +859,7 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_3 =
- MakeUniformBufferElementDescriptor(12, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
uint32_t float_data[1];
float temp = 3.0;
@@ -946,9 +946,9 @@
FactManager fact_manager;
protobufs::UniformBufferElementDescriptor blockname_9 =
- MakeUniformBufferElementDescriptor(14, {0});
+ MakeUniformBufferElementDescriptor(0, 0, {0});
protobufs::UniformBufferElementDescriptor blockname_10 =
- MakeUniformBufferElementDescriptor(14, {1});
+ MakeUniformBufferElementDescriptor(0, 0, {1});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9));
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 10, blockname_10));
@@ -1172,42 +1172,42 @@
memcpy(&float_vector_data, &float_vector_values, sizeof(float_vector_values));
protobufs::UniformBufferElementDescriptor uniform_f_a_0 =
- MakeUniformBufferElementDescriptor(65, {0, 0, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0, 0});
protobufs::UniformBufferElementDescriptor uniform_f_a_1 =
- MakeUniformBufferElementDescriptor(65, {0, 0, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0, 1});
protobufs::UniformBufferElementDescriptor uniform_f_a_2 =
- MakeUniformBufferElementDescriptor(65, {0, 0, 2});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0, 2});
protobufs::UniformBufferElementDescriptor uniform_f_a_3 =
- MakeUniformBufferElementDescriptor(65, {0, 0, 3});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0, 3});
protobufs::UniformBufferElementDescriptor uniform_f_a_4 =
- MakeUniformBufferElementDescriptor(65, {0, 0, 4});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 0, 4});
protobufs::UniformBufferElementDescriptor uniform_f_b_x =
- MakeUniformBufferElementDescriptor(65, {0, 1, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1, 0});
protobufs::UniformBufferElementDescriptor uniform_f_b_y =
- MakeUniformBufferElementDescriptor(65, {0, 1, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1, 1});
protobufs::UniformBufferElementDescriptor uniform_f_b_z =
- MakeUniformBufferElementDescriptor(65, {0, 1, 2});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1, 2});
protobufs::UniformBufferElementDescriptor uniform_f_b_w =
- MakeUniformBufferElementDescriptor(65, {0, 1, 3});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 1, 3});
protobufs::UniformBufferElementDescriptor uniform_f_c_x =
- MakeUniformBufferElementDescriptor(65, {0, 2, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 2, 0});
protobufs::UniformBufferElementDescriptor uniform_f_c_y =
- MakeUniformBufferElementDescriptor(65, {0, 2, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 2, 1});
protobufs::UniformBufferElementDescriptor uniform_f_c_z =
- MakeUniformBufferElementDescriptor(65, {0, 2, 2});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 2, 2});
protobufs::UniformBufferElementDescriptor uniform_f_d =
- MakeUniformBufferElementDescriptor(65, {0, 3});
+ MakeUniformBufferElementDescriptor(0, 0, {0, 3});
protobufs::UniformBufferElementDescriptor uniform_g =
- MakeUniformBufferElementDescriptor(65, {1});
+ MakeUniformBufferElementDescriptor(0, 0, {1});
protobufs::UniformBufferElementDescriptor uniform_h_x =
- MakeUniformBufferElementDescriptor(65, {2, 0});
+ MakeUniformBufferElementDescriptor(0, 0, {2, 0});
protobufs::UniformBufferElementDescriptor uniform_h_y =
- MakeUniformBufferElementDescriptor(65, {2, 1});
+ MakeUniformBufferElementDescriptor(0, 0, {2, 1});
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[0],
uniform_f_a_0));
diff --git a/test/fuzz/uniform_buffer_element_descriptor_test.cpp b/test/fuzz/uniform_buffer_element_descriptor_test.cpp
new file mode 100644
index 0000000..6c6d52a
--- /dev/null
+++ b/test/fuzz/uniform_buffer_element_descriptor_test.cpp
@@ -0,0 +1,84 @@
+// Copyright (c) 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "source/fuzz/uniform_buffer_element_descriptor.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(UniformBufferElementDescriptorTest, TestEquality) {
+ // Test that equality works as expected for various buffer element
+ // descriptors.
+
+ protobufs::UniformBufferElementDescriptor descriptor1 =
+ MakeUniformBufferElementDescriptor(0, 0, {1, 2, 3});
+ protobufs::UniformBufferElementDescriptor descriptor2 =
+ MakeUniformBufferElementDescriptor(0, 0, {1, 2, 3});
+ protobufs::UniformBufferElementDescriptor descriptor3 =
+ MakeUniformBufferElementDescriptor(0, 1, {1, 2, 3});
+ protobufs::UniformBufferElementDescriptor descriptor4 =
+ MakeUniformBufferElementDescriptor(1, 0, {1, 2, 3});
+ protobufs::UniformBufferElementDescriptor descriptor5 =
+ MakeUniformBufferElementDescriptor(1, 1, {1, 2, 3});
+ protobufs::UniformBufferElementDescriptor descriptor6 =
+ MakeUniformBufferElementDescriptor(0, 0, {1, 2, 4});
+ protobufs::UniformBufferElementDescriptor descriptor7 =
+ MakeUniformBufferElementDescriptor(0, 0, {1, 2});
+
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor1));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor2));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor3, &descriptor3));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor4, &descriptor4));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor5, &descriptor5));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor6, &descriptor6));
+ ASSERT_TRUE(
+ UniformBufferElementDescriptorEquals()(&descriptor7, &descriptor7));
+
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor3));
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor3, &descriptor1));
+
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor4));
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor4, &descriptor1));
+
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor5));
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor5, &descriptor1));
+
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor6));
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor6, &descriptor1));
+
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor1, &descriptor7));
+ ASSERT_FALSE(
+ UniformBufferElementDescriptorEquals()(&descriptor7, &descriptor1));
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools