mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Validator pass for image instructions
Includes validation rules for OpImageXXX and ImageOperand. Doesn't include OpTypeImage and OpImageSparseXXX. Disabled an invalid test.
This commit is contained in:
parent
e28edd458b
commit
f407ae2b50
@ -41,6 +41,7 @@ SPVTOOLS_SRC_FILES := \
|
|||||||
source/validate_datarules.cpp \
|
source/validate_datarules.cpp \
|
||||||
source/validate_decorations.cpp \
|
source/validate_decorations.cpp \
|
||||||
source/validate_id.cpp \
|
source/validate_id.cpp \
|
||||||
|
source/validate_image.cpp \
|
||||||
source/validate_instruction.cpp \
|
source/validate_instruction.cpp \
|
||||||
source/validate_layout.cpp \
|
source/validate_layout.cpp \
|
||||||
source/validate_logicals.cpp \
|
source/validate_logicals.cpp \
|
||||||
|
@ -261,6 +261,7 @@ set(SPIRV_SOURCES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_decorations.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_decorations.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_image.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_logicals.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/validate_logicals.cpp
|
||||||
|
@ -438,8 +438,12 @@ bool ValidationState_t::RegisterUniqueTypeDeclaration(
|
|||||||
|
|
||||||
uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
|
uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
|
||||||
const Instruction* inst = FindDef(id);
|
const Instruction* inst = FindDef(id);
|
||||||
assert(inst);
|
return inst ? inst->type_id() : 0;
|
||||||
return inst->type_id();
|
}
|
||||||
|
|
||||||
|
SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
|
||||||
|
const Instruction* inst = FindDef(id);
|
||||||
|
return inst ? inst->opcode() : SpvOpNop;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
|
uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
|
||||||
@ -523,6 +527,21 @@ bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
|
||||||
|
const Instruction* inst = FindDef(id);
|
||||||
|
assert(inst);
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeFloat) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeVector) {
|
||||||
|
return IsFloatScalarType(GetComponentType(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ValidationState_t::IsIntScalarType(uint32_t id) const {
|
bool ValidationState_t::IsIntScalarType(uint32_t id) const {
|
||||||
const Instruction* inst = FindDef(id);
|
const Instruction* inst = FindDef(id);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
@ -540,6 +559,21 @@ bool ValidationState_t::IsIntVectorType(uint32_t id) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
|
||||||
|
const Instruction* inst = FindDef(id);
|
||||||
|
assert(inst);
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeInt) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeVector) {
|
||||||
|
return IsIntScalarType(GetComponentType(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
|
bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
|
||||||
const Instruction* inst = FindDef(id);
|
const Instruction* inst = FindDef(id);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
@ -591,6 +625,21 @@ bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
|
||||||
|
const Instruction* inst = FindDef(id);
|
||||||
|
assert(inst);
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeBool) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->opcode() == SpvOpTypeVector) {
|
||||||
|
return IsBoolScalarType(GetComponentType(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
|
bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
|
||||||
const Instruction* inst = FindDef(id);
|
const Instruction* inst = FindDef(id);
|
||||||
assert(inst);
|
assert(inst);
|
||||||
@ -673,4 +722,27 @@ uint32_t ValidationState_t::GetOperandTypeId(
|
|||||||
return GetTypeId(inst->words[operand.offset]);
|
return GetTypeId(inst->words[operand.offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
|
||||||
|
const Instruction* inst = FindDef(id);
|
||||||
|
if (!inst) {
|
||||||
|
assert(0 && "Instruction not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!IsIntScalarType(inst->type_id()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (inst->words().size() == 4) {
|
||||||
|
*val = inst->word(3);
|
||||||
|
} else {
|
||||||
|
assert(inst->words().size() == 5);
|
||||||
|
*val = inst->word(3);
|
||||||
|
*val |= uint64_t(inst->word(4)) << 32;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace libspirv
|
} // namespace libspirv
|
||||||
|
@ -371,20 +371,31 @@ class ValidationState_t {
|
|||||||
// Only works for types not for objects.
|
// Only works for types not for objects.
|
||||||
bool IsFloatScalarType(uint32_t id) const;
|
bool IsFloatScalarType(uint32_t id) const;
|
||||||
bool IsFloatVectorType(uint32_t id) const;
|
bool IsFloatVectorType(uint32_t id) const;
|
||||||
|
bool IsFloatScalarOrVectorType(uint32_t id) const;
|
||||||
bool IsFloatMatrixType(uint32_t id) const;
|
bool IsFloatMatrixType(uint32_t id) const;
|
||||||
bool IsIntScalarType(uint32_t id) const;
|
bool IsIntScalarType(uint32_t id) const;
|
||||||
bool IsIntVectorType(uint32_t id) const;
|
bool IsIntVectorType(uint32_t id) const;
|
||||||
|
bool IsIntScalarOrVectorType(uint32_t id) const;
|
||||||
bool IsUnsignedIntScalarType(uint32_t id) const;
|
bool IsUnsignedIntScalarType(uint32_t id) const;
|
||||||
bool IsUnsignedIntVectorType(uint32_t id) const;
|
bool IsUnsignedIntVectorType(uint32_t id) const;
|
||||||
bool IsSignedIntScalarType(uint32_t id) const;
|
bool IsSignedIntScalarType(uint32_t id) const;
|
||||||
bool IsSignedIntVectorType(uint32_t id) const;
|
bool IsSignedIntVectorType(uint32_t id) const;
|
||||||
bool IsBoolScalarType(uint32_t id) const;
|
bool IsBoolScalarType(uint32_t id) const;
|
||||||
bool IsBoolVectorType(uint32_t id) const;
|
bool IsBoolVectorType(uint32_t id) const;
|
||||||
|
bool IsBoolScalarOrVectorType(uint32_t id) const;
|
||||||
bool IsPointerType(uint32_t id) const;
|
bool IsPointerType(uint32_t id) const;
|
||||||
|
|
||||||
|
// Gets value from OpConstant and OpSpecConstant as uint64.
|
||||||
|
// Returns false on failure (no instruction, wrong instruction, not int).
|
||||||
|
bool GetConstantValUint64(uint32_t id, uint64_t* val) const;
|
||||||
|
|
||||||
// Returns type_id if id has type or zero otherwise.
|
// Returns type_id if id has type or zero otherwise.
|
||||||
uint32_t GetTypeId(uint32_t id) const;
|
uint32_t GetTypeId(uint32_t id) const;
|
||||||
|
|
||||||
|
// Returns opcode of the instruction which issued the id or OpNop if the
|
||||||
|
// instruction is not registered.
|
||||||
|
SpvOp GetIdOpcode(uint32_t id) const;
|
||||||
|
|
||||||
// Returns type_id for given id operand if it has a type or zero otherwise.
|
// Returns type_id for given id operand if it has a type or zero otherwise.
|
||||||
// |operand_index| is expected to be pointing towards an operand which is an
|
// |operand_index| is expected to be pointing towards an operand which is an
|
||||||
// id.
|
// id.
|
||||||
|
@ -183,6 +183,7 @@ spv_result_t ProcessInstruction(void* user_data,
|
|||||||
if (auto error = ConversionPass(_, inst)) return error;
|
if (auto error = ConversionPass(_, inst)) return error;
|
||||||
if (auto error = LogicalsPass(_, inst)) return error;
|
if (auto error = LogicalsPass(_, inst)) return error;
|
||||||
if (auto error = BitwisePass(_, inst)) return error;
|
if (auto error = BitwisePass(_, inst)) return error;
|
||||||
|
if (auto error = ImagePass(_, inst)) return error;
|
||||||
|
|
||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,10 @@ spv_result_t LogicalsPass(ValidationState_t& _,
|
|||||||
spv_result_t BitwisePass(ValidationState_t& _,
|
spv_result_t BitwisePass(ValidationState_t& _,
|
||||||
const spv_parsed_instruction_t* inst);
|
const spv_parsed_instruction_t* inst);
|
||||||
|
|
||||||
|
/// Validates correctness of image instructions.
|
||||||
|
spv_result_t ImagePass(ValidationState_t& _,
|
||||||
|
const spv_parsed_instruction_t* inst);
|
||||||
|
|
||||||
// Validates that capability declarations use operands allowed in the current
|
// Validates that capability declarations use operands allowed in the current
|
||||||
// context.
|
// context.
|
||||||
spv_result_t CapabilityPass(ValidationState_t& _,
|
spv_result_t CapabilityPass(ValidationState_t& _,
|
||||||
|
1389
source/validate_image.cpp
Normal file
1389
source/validate_image.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -98,6 +98,12 @@ add_spvtools_unittest(TARGET val_bitwise
|
|||||||
LIBS ${SPIRV_TOOLS}
|
LIBS ${SPIRV_TOOLS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_spvtools_unittest(TARGET val_image
|
||||||
|
SRCS val_image_test.cpp
|
||||||
|
${VAL_TEST_COMMON_SRCS}
|
||||||
|
LIBS ${SPIRV_TOOLS}
|
||||||
|
)
|
||||||
|
|
||||||
add_spvtools_unittest(TARGET val_limits
|
add_spvtools_unittest(TARGET val_limits
|
||||||
SRCS val_limits_test.cpp
|
SRCS val_limits_test.cpp
|
||||||
${VAL_TEST_COMMON_SRCS}
|
${VAL_TEST_COMMON_SRCS}
|
||||||
|
@ -1402,6 +1402,10 @@ make_pair(string(kOpenCLMemoryModel) +
|
|||||||
MatrixDependencies()))),);
|
MatrixDependencies()))),);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO(atgoo@github.com) The following test is not valid as it generates
|
||||||
|
// invalid combinations of images, instructions and image operands.
|
||||||
|
//
|
||||||
// Creates assembly containing an OpImageFetch instruction using operands for
|
// Creates assembly containing an OpImageFetch instruction using operands for
|
||||||
// the image-operands part. The assembly defines constants %fzero and %izero
|
// the image-operands part. The assembly defines constants %fzero and %izero
|
||||||
// that can be used for operands where IDs are required. The assembly is valid,
|
// that can be used for operands where IDs are required. The assembly is valid,
|
||||||
@ -1448,6 +1452,7 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
vector<string>{"MinLod"}),
|
vector<string>{"MinLod"}),
|
||||||
make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"),
|
make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"),
|
||||||
AllCapabilities()))), );
|
AllCapabilities()))), );
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO(umar): Instruction capability checks
|
// TODO(umar): Instruction capability checks
|
||||||
|
|
||||||
|
3040
test/val/val_image_test.cpp
Normal file
3040
test/val/val_image_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user