mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-27 02:10:15 +00:00
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.
This commit is contained in:
parent
fa981bc245
commit
51b0d5ce50
@ -201,20 +201,21 @@ bool FactManager::ConstantUniformFacts::FloatingPointValueIsSuitable(
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
if (SpvOpVariable != should_be_uniform_variable->opcode()) {
|
||||
return false;
|
||||
}
|
||||
if (SpvStorageClassUniform !=
|
||||
should_be_uniform_variable->GetSingleWordInOperand(0)) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
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 @@ bool FactManager::ConstantUniformFacts::AddFact(
|
||||
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);
|
||||
|
||||
|
@ -64,8 +64,9 @@ message UniformBufferElementDescriptor {
|
||||
// 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 @@ message UniformBufferElementDescriptor {
|
||||
// };
|
||||
//
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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 @@ std::unique_ptr<opt::Instruction> MakeAccessChainInstruction(
|
||||
// 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;
|
||||
|
@ -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 @@ protobufs::UniformBufferElementDescriptor MakeUniformBufferElementDescriptor(
|
||||
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
|
||||
|
@ -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 @@ namespace fuzz {
|
||||
// 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 @@ struct UniformBufferElementDescriptorEquals {
|
||||
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
|
||||
|
||||
|
@ -31,7 +31,8 @@ if (${SPIRV_BUILD_FUZZER})
|
||||
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}
|
||||
|
@ -58,6 +58,44 @@ TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
|
||||
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 @@ TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
|
||||
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 @@ TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
|
||||
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 @@ TEST(FactManagerTest, ConstantsAvailableViaUniforms) {
|
||||
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 @@ TEST(FactManagerTest, TwoConstantsWithSameValue) {
|
||||
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 @@ TEST(FactManagerTest, NonFiniteFactsAreNotValid) {
|
||||
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, NonFiniteFactsAreNotValid) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -180,30 +180,30 @@ TEST(FuzzerPassAddUsefulConstructsTest,
|
||||
|
||||
// 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
|
||||
|
@ -951,7 +951,7 @@ TEST(FuzzerReplayerTest, Miscellaneous3) {
|
||||
{
|
||||
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 @@ TEST(FuzzerReplayerTest, Miscellaneous3) {
|
||||
{
|
||||
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;
|
||||
|
@ -104,11 +104,11 @@ TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
|
||||
// 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 @@ TEST(TransformationReplaceConstantWithUniformTest, NestedStruct) {
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest, NoUniformIntPointerPresent) {
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest, NoConstantPresentForIndex) {
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest,
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest,
|
||||
|
||||
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 @@ TEST(TransformationReplaceConstantWithUniformTest, ComplexReplacements) {
|
||||
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));
|
||||
|
84
test/fuzz/uniform_buffer_element_descriptor_test.cpp
Normal file
84
test/fuzz/uniform_buffer_element_descriptor_test.cpp
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user