mirror of
https://github.com/RPCSX/SPIRV-Tools.git
synced 2024-12-11 21:23:52 +00:00
Adding validation code for more data rules.
These rules are under "Data Rules" in 2.16.1 (Universal Validation Rules) part of the SPIR-V 1.1 Specification document: * Scalar floating-point types can be parameterized only as 32 bit, plus any additional sizes enabled by capabilities. * Scalar integer types can be parameterized only as 32 bit, plus any additional sizes enabled by capabilities. * Vector types can only be parameterized with numerical types or the OpTypeBool type. * Matrix types can only be parameterized with floating-point types. * Matrix types can only be parameterized as having only 2, 3, or 4 columns. * Specialization constants (see Specialization) are limited to integers, Booleans, floating-point numbers, and vectors of these.
This commit is contained in:
parent
38036a7203
commit
d0620061c7
@ -23,6 +23,7 @@
|
||||
#include "diagnostic.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "val/instruction.h"
|
||||
#include "val/validation_state.h"
|
||||
|
||||
using libspirv::CapabilitySet;
|
||||
@ -31,32 +32,161 @@ using libspirv::ValidationState_t;
|
||||
|
||||
namespace {
|
||||
|
||||
// Validates that the number of components in the vector type is legal.
|
||||
// Validates that the number of components in the vector is valid.
|
||||
// Vector types can only be parameterized as having 2, 3, or 4 components.
|
||||
// If the Vector16 capability is added, 8 and 16 components are also allowed.
|
||||
spv_result_t ValidateNumVecComponents(ValidationState_t& _,
|
||||
spv_result_t ValidateVecNumComponents(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
if (inst->opcode == SpvOpTypeVector) {
|
||||
// operand 2 specifies the number of components in the vector.
|
||||
const uint32_t num_components = inst->words[inst->operands[2].offset];
|
||||
if (num_components == 2 || num_components == 3 || num_components == 4) {
|
||||
// Operand 2 specifies the number of components in the vector.
|
||||
const uint32_t num_components = inst->words[inst->operands[2].offset];
|
||||
if (num_components == 2 || num_components == 3 || num_components == 4) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
if (num_components == 8 || num_components == 16) {
|
||||
if (_.HasCapability(SpvCapabilityVector16)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
if (num_components == 8 || num_components == 16) {
|
||||
if (_.HasCapability(SpvCapabilityVector16)) {
|
||||
return SPV_SUCCESS;
|
||||
} else {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Having " << num_components << " components for "
|
||||
<< spvOpcodeString(static_cast<SpvOp>(inst->opcode))
|
||||
<< " requires the Vector16 capability";
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Having " << num_components << " components for "
|
||||
<< spvOpcodeString(static_cast<SpvOp>(inst->opcode))
|
||||
<< " requires the Vector16 capability";
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Illegal number of components (" << num_components << ") for "
|
||||
<< spvOpcodeString(static_cast<SpvOp>(inst->opcode));
|
||||
}
|
||||
|
||||
// Validates that the number of bits specifed for a float type is valid.
|
||||
// Scalar floating-point types can be parameterized only with 32-bits.
|
||||
// Float16 capability allows using a 16-bit OpTypeFloat.
|
||||
// Float16Buffer capability allows creation of a 16-bit OpTypeFloat.
|
||||
// Float64 capability allows using a 64-bit OpTypeFloat.
|
||||
spv_result_t ValidateFloatSize(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Operand 1 is the number of bits for this float
|
||||
const uint32_t num_bits = inst->words[inst->operands[1].offset];
|
||||
if (num_bits == 32) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
if (num_bits == 16) {
|
||||
if (_.HasCapability(SpvCapabilityFloat16) ||
|
||||
_.HasCapability(SpvCapabilityFloat16Buffer)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Illegal number of components (" << num_components << ") for "
|
||||
<< spvOpcodeString(static_cast<SpvOp>(inst->opcode));
|
||||
<< "Using a 16-bit floating point "
|
||||
<< "type requires the Float16 or Float16Buffer capability.";
|
||||
}
|
||||
if (num_bits == 64) {
|
||||
if (_.HasCapability(SpvCapabilityFloat64)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Using a 64-bit floating point "
|
||||
<< "type requires the Float64 capability.";
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Invalid number of bits (" << num_bits << ") used for OpTypeFloat.";
|
||||
}
|
||||
|
||||
// Validates that the number of bits specified for an Int type is valid.
|
||||
// Scalar integer types can be parameterized only with 32-bits.
|
||||
// Int8, Int16, and Int64 capabilities allow using 8-bit, 16-bit, and 64-bit
|
||||
// integers, respectively.
|
||||
spv_result_t ValidateIntSize(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Operand 1 is the number of bits for this integer.
|
||||
const uint32_t num_bits = inst->words[inst->operands[1].offset];
|
||||
if (num_bits == 32) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
if (num_bits == 8) {
|
||||
if (_.HasCapability(SpvCapabilityInt8)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Using an 8-bit integer type requires the Int8 capability.";
|
||||
}
|
||||
if (num_bits == 16) {
|
||||
if (_.HasCapability(SpvCapabilityInt16)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Using a 16-bit integer type requires the Int16 capability.";
|
||||
}
|
||||
if (num_bits == 64) {
|
||||
if (_.HasCapability(SpvCapabilityInt64)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA)
|
||||
<< "Using a 64-bit integer type requires the Int64 capability.";
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_DATA) << "Invalid number of bits ("
|
||||
<< num_bits << ") used for OpTypeInt.";
|
||||
}
|
||||
|
||||
// Validates that the matrix is parameterized with floating-point types.
|
||||
spv_result_t ValidateMatrixColumnType(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Find the component type of matrix columns (must be vector).
|
||||
// Operand 1 is the <id> of the type specified for matrix columns.
|
||||
auto type_id = inst->words[inst->operands[1].offset];
|
||||
auto col_type_instr = _.FindDef(type_id);
|
||||
if (col_type_instr->opcode() != SpvOpTypeVector) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID)
|
||||
<< "Columns in a matrix must be of type vector.";
|
||||
}
|
||||
|
||||
// Trace back once more to find out the type of components in the vector.
|
||||
// Operand 1 is the <id> of the type of data in the vector.
|
||||
auto comp_type_id =
|
||||
col_type_instr->words()[col_type_instr->operands()[1].offset];
|
||||
auto comp_type_instruction = _.FindDef(comp_type_id);
|
||||
if (comp_type_instruction->opcode() != SpvOpTypeFloat) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA) << "Matrix types can only be "
|
||||
"parameterized with "
|
||||
"floating-point types.";
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Validates that the matrix has 2,3, or 4 columns.
|
||||
spv_result_t ValidateMatrixNumCols(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Operand 2 is the number of columns in the matrix.
|
||||
const uint32_t num_cols = inst->words[inst->operands[2].offset];
|
||||
if (num_cols != 2 && num_cols != 3 && num_cols != 4) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA) << "Matrix types can only be "
|
||||
"parameterized as having only 2, "
|
||||
"3, or 4 columns.";
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Validates that OpSpecConstant specializes to either int or float type.
|
||||
spv_result_t ValidateSpecConstNumerical(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Operand 0 is the <id> of the type that we're specializing to.
|
||||
auto type_id = inst->words[inst->operands[0].offset];
|
||||
auto type_instruction = _.FindDef(type_id);
|
||||
auto type_opcode = type_instruction->opcode();
|
||||
if (type_opcode != SpvOpTypeInt && type_opcode != SpvOpTypeFloat) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA) << "Specialization constant must be "
|
||||
"an integer or floating-point "
|
||||
"number.";
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Validates that OpSpecConstantTrue and OpSpecConstantFalse specialize to bool.
|
||||
spv_result_t ValidateSpecConstBoolean(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
// Find out the type that we're specializing to.
|
||||
auto type_instruction = _.FindDef(inst->type_id);
|
||||
if (type_instruction->opcode() != SpvOpTypeBool) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID) << "Specialization constant must be "
|
||||
"a boolean type.";
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
@ -68,9 +198,38 @@ namespace libspirv {
|
||||
// (Data Rules subsection of 2.16.1 Universal Validation Rules)
|
||||
spv_result_t DataRulesPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
if (auto error = ValidateNumVecComponents(_, inst)) return error;
|
||||
|
||||
// TODO(ehsan): add more data rules validation here.
|
||||
switch (inst->opcode) {
|
||||
case SpvOpTypeVector: {
|
||||
if (auto error = ValidateVecNumComponents(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
case SpvOpTypeFloat: {
|
||||
if (auto error = ValidateFloatSize(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
case SpvOpTypeInt: {
|
||||
if (auto error = ValidateIntSize(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
case SpvOpTypeMatrix: {
|
||||
if (auto error = ValidateMatrixColumnType(_, inst)) return error;
|
||||
if (auto error = ValidateMatrixNumCols(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
// TODO(ehsan): Add OpSpecConstantComposite validation code.
|
||||
// TODO(ehsan): Add OpSpecConstantOp validation code (if any).
|
||||
case SpvOpSpecConstant: {
|
||||
if (auto error = ValidateSpecConstNumerical(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstantTrue: {
|
||||
if (auto error = ValidateSpecConstBoolean(_, inst)) return error;
|
||||
break;
|
||||
}
|
||||
// TODO(ehsan): add more data rules validation here.
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
@ -114,8 +114,8 @@ TEST_F(ValidateCapability, Default) {
|
||||
OpCapability Kernel
|
||||
OpCapability Matrix
|
||||
OpMemoryModel Logical OpenCL
|
||||
%intt = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %intt 3
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
)";
|
||||
|
||||
@ -1098,8 +1098,8 @@ INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateCapability,
|
||||
ValuesIn(AllCapabilities()),
|
||||
Values(
|
||||
make_pair(string(kOpenCLMemoryModel) +
|
||||
"%intt = OpTypeInt 32 1\n"
|
||||
"%vec3 = OpTypeVector %intt 3\n"
|
||||
"%f32 = OpTypeFloat 32\n"
|
||||
"%vec3 = OpTypeVector %f32 3\n"
|
||||
"%mat33 = OpTypeMatrix %vec3 3\n", MatrixDependencies()))),);
|
||||
// clang-format on
|
||||
|
||||
|
@ -42,9 +42,45 @@ string header_with_vec16_cap = R"(
|
||||
OpMemoryModel Logical GLSL450
|
||||
%1 = OpTypeFloat 32
|
||||
)";
|
||||
|
||||
string header_with_int8 = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int8
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string header_with_int16 = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int16
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string header_with_int64 = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int64
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string header_with_float16 = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Float16
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string header_with_float16_buffer = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Float16Buffer
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string header_with_float64 = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Float64
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
string invalid_comp_error = "Illegal number of components";
|
||||
string missing_cap_error = "requires the Vector16 capability";
|
||||
string missing_int8_cap_error = "requires the Int8 capability";
|
||||
string missing_int16_cap_error = "requires the Int16 capability";
|
||||
string missing_int64_cap_error = "requires the Int64 capability";
|
||||
string missing_float16_cap_error =
|
||||
"requires the Float16 or Float16Buffer capability.";
|
||||
string missing_float64_cap_error = "requires the Float64 capability";
|
||||
string invalid_num_bits_error = "Invalid number of bits";
|
||||
|
||||
TEST_F(ValidateData, vec0) {
|
||||
string str = header + "%2 = OpTypeVector %1 0";
|
||||
@ -117,3 +153,240 @@ TEST_F(ValidateData, vec15) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int8_good) {
|
||||
string str = header_with_int8 + "%2 = OpTypeInt 8 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int8_bad) {
|
||||
string str = header + "%2 = OpTypeInt 8 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int16_good) {
|
||||
string str = header_with_int16 + "%2 = OpTypeInt 16 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int16_bad) {
|
||||
string str = header + "%2 = OpTypeInt 16 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int64_good) {
|
||||
string str = header_with_int64 + "%2 = OpTypeInt 64 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, int64_bad) {
|
||||
string str = header + "%2 = OpTypeInt 64 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
|
||||
}
|
||||
|
||||
// Number of bits in an integer may be only one of: {8,16,32,64}
|
||||
TEST_F(ValidateData, int_invalid_num_bits) {
|
||||
string str = header + "%2 = OpTypeInt 48 1";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, float16_good) {
|
||||
string str = header_with_float16 + "%2 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, float16_buffer_good) {
|
||||
string str = header_with_float16_buffer + "%2 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, float16_bad) {
|
||||
string str = header + "%2 = OpTypeFloat 16";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, float64_good) {
|
||||
string str = header_with_float64 + "%2 = OpTypeFloat 64";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, float64_bad) {
|
||||
string str = header + "%2 = OpTypeFloat 64";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
|
||||
}
|
||||
|
||||
// Number of bits in a float may be only one of: {16,32,64}
|
||||
TEST_F(ValidateData, float_invalid_num_bits) {
|
||||
string str = header + "%2 = OpTypeFloat 48";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_data_type_float) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_bad_column_type) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%mat33 = OpTypeMatrix %f32 3
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Columns in a matrix must be of type vector"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_data_type_int) {
|
||||
string str = header + R"(
|
||||
%int32 = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %int32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("can only be parameterized with floating-point types"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_data_type_bool) {
|
||||
string str = header + R"(
|
||||
%boolt = OpTypeBool
|
||||
%vec3 = OpTypeVector %boolt 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("can only be parameterized with floating-point types"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_0_columns) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 0
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_1_column) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 1
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_2_columns) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 2
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_3_columns) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_4_columns) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 4
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, matrix_with_5_column) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 5
|
||||
)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, specialize_int) {
|
||||
string str = header + R"(
|
||||
%i32 = OpTypeInt 32 1
|
||||
%len = OpSpecConstant %i32 2)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, specialize_float) {
|
||||
string str = header + R"(
|
||||
%f32 = OpTypeFloat 32
|
||||
%len = OpSpecConstant %f32 2)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, specialize_boolean) {
|
||||
string str = header + R"(
|
||||
%2 = OpTypeBool
|
||||
%3 = OpSpecConstantTrue %2
|
||||
%4 = OpSpecConstantFalse %2)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateData, specialize_boolean_to_int) {
|
||||
string str = header + R"(
|
||||
%2 = OpTypeInt 32 1
|
||||
%3 = OpSpecConstantTrue %2
|
||||
%4 = OpSpecConstantFalse %2)";
|
||||
CompileSuccessfully(str.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Specialization constant must be a boolean"));
|
||||
}
|
||||
|
@ -45,6 +45,10 @@ const char kGLSL450MemoryModel[] = R"(
|
||||
OpCapability LiteralSampler
|
||||
OpCapability DeviceEnqueue
|
||||
OpCapability Vector16
|
||||
OpCapability Int8
|
||||
OpCapability Int16
|
||||
OpCapability Int64
|
||||
OpCapability Float64
|
||||
OpMemoryModel Logical GLSL450
|
||||
)";
|
||||
|
||||
@ -343,7 +347,7 @@ TEST_F(ValidateID, OpTypeVectorComponentTypeBad) {
|
||||
|
||||
TEST_F(ValidateID, OpTypeMatrixGood) {
|
||||
const char* spirv = R"(
|
||||
%1 = OpTypeInt 32 0
|
||||
%1 = OpTypeFloat 32
|
||||
%2 = OpTypeVector %1 2
|
||||
%3 = OpTypeMatrix %2 3)";
|
||||
CHECK(spirv, SPV_SUCCESS);
|
||||
@ -460,8 +464,9 @@ TEST_P(OpTypeArrayLengthTest, LengthNegative) {
|
||||
Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width))));
|
||||
}
|
||||
|
||||
// The only valid widths for integers are 8, 16, 32, and 64.
|
||||
INSTANTIATE_TEST_CASE_P(Widths, OpTypeArrayLengthTest,
|
||||
ValuesIn(vector<int>{8, 16, 32, 48, 64}));
|
||||
ValuesIn(vector<int>{8, 16, 32, 64}));
|
||||
|
||||
TEST_F(ValidateID, OpTypeArrayLengthNull) {
|
||||
const char* spirv = R"(
|
||||
@ -844,7 +849,7 @@ TEST_F(ValidateID, OpConstantNullGood) {
|
||||
%14 = OpConstantNull %13
|
||||
%15 = OpTypeQueue
|
||||
%16 = OpConstantNull %15
|
||||
%17 = OpTypeVector %3 2
|
||||
%17 = OpTypeVector %5 2
|
||||
%18 = OpConstantNull %17
|
||||
%19 = OpTypeMatrix %17 2
|
||||
%20 = OpConstantNull %19
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "source/diagnostic.h"
|
||||
#include "unit_spirv.h"
|
||||
#include "val_fixtures.h"
|
||||
@ -95,8 +94,8 @@ const vector<string>& getInstructions() {
|
||||
"%floatt = OpTypeFloat 32",
|
||||
"%voidt = OpTypeVoid",
|
||||
"%boolt = OpTypeBool",
|
||||
"%vec4 = OpTypeVector %intt 4",
|
||||
"%vec3 = OpTypeVector %intt 3",
|
||||
"%vec4 = OpTypeVector %floatt 4",
|
||||
"%vec3 = OpTypeVector %floatt 3",
|
||||
"%mat33 = OpTypeMatrix %vec3 3",
|
||||
"%mat44 = OpTypeMatrix %vec4 4",
|
||||
"%struct = OpTypeStruct %intt %mat33",
|
||||
@ -150,9 +149,9 @@ INSTANTIATE_TEST_CASE_P(InstructionsOrder,
|
||||
, make_tuple(string("OpDecorationGroup") , Range<13, 16>() , Range<0, 15>())
|
||||
, make_tuple(string("OpTypeBool") , Range<17, 30>() , All)
|
||||
, make_tuple(string("OpTypeVoid") , Range<17, 30>() , Range<0, 25>())
|
||||
, make_tuple(string("OpTypeFloat") , Range<17, 30>() , All)
|
||||
, make_tuple(string("OpTypeFloat") , Range<17, 30>() , Range<0,20>())
|
||||
, make_tuple(string("OpTypeInt") , Range<17, 30>() , Range<0, 20>())
|
||||
, make_tuple(string("OpTypeVector %intt 4") , Range<17, 30>() , Range<18, 23>())
|
||||
, make_tuple(string("OpTypeVector %floatt 4") , Range<17, 30>() , Range<19, 23>())
|
||||
, make_tuple(string("OpTypeMatrix %vec4 4") , Range<17, 30>() , Range<22, kRangeEnd>())
|
||||
, make_tuple(string("OpTypeStruct") , Range<17, 30>() , Range<24, kRangeEnd>())
|
||||
, make_tuple(string("%vfunct = OpTypeFunction"), Range<17, 30>() , Range<20, 30>())
|
||||
|
@ -234,7 +234,8 @@ TEST_F(ValidateSSA, ForwardMemberDecorateGood) {
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpMemberDecorate %struct 1 RowMajor
|
||||
%intt = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %intt 3
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
%struct = OpTypeStruct %intt %mat33
|
||||
)";
|
||||
@ -249,7 +250,8 @@ TEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) {
|
||||
OpName %missing "missing"
|
||||
OpMemberDecorate %missing 1 RowMajor ; Target not defined
|
||||
%intt = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %intt 3
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
%struct = OpTypeStruct %intt %mat33
|
||||
)";
|
||||
@ -265,9 +267,9 @@ TEST_F(ValidateSSA, ForwardGroupDecorateGood) {
|
||||
OpDecorate %dgrp RowMajor
|
||||
%dgrp = OpDecorationGroup
|
||||
OpGroupDecorate %dgrp %mat33 %mat44
|
||||
%intt = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %intt 3
|
||||
%vec4 = OpTypeVector %intt 4
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%vec4 = OpTypeVector %f32 4
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
%mat44 = OpTypeMatrix %vec4 4
|
||||
)";
|
||||
@ -302,9 +304,9 @@ TEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) {
|
||||
OpDecorate %dgrp RowMajor
|
||||
%dgrp = OpDecorationGroup
|
||||
OpGroupDecorate %dgrp %missing %mat44 ; Target not defined
|
||||
%intt = OpTypeInt 32 1
|
||||
%vec3 = OpTypeVector %intt 3
|
||||
%vec4 = OpTypeVector %intt 4
|
||||
%f32 = OpTypeFloat 32
|
||||
%vec3 = OpTypeVector %f32 3
|
||||
%vec4 = OpTypeVector %f32 4
|
||||
%mat33 = OpTypeMatrix %vec3 3
|
||||
%mat44 = OpTypeMatrix %vec4 4
|
||||
)";
|
||||
@ -1241,10 +1243,8 @@ TEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) {
|
||||
"definition does not dominate its parent .\\[if_false\\]"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateSSA,
|
||||
PhiVariableDefDominatesButNotDefinedInParentBlock) {
|
||||
string str = kHeader + "OpName %if_true \"if_true\"\n" +
|
||||
kBasicTypes +
|
||||
TEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) {
|
||||
string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes +
|
||||
R"(
|
||||
%func = OpFunction %voidt None %vfunct
|
||||
%entry = OpLabel
|
||||
|
Loading…
Reference in New Issue
Block a user