mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-29 14:31:04 +00:00
Allow relaxing validation of pointers in logical addressing mode
In HLSL structured buffer legalization, pointer to pointer types are emitted to indicate a structured buffer variable should be treated as an alias of some other variable. We need an option to relax the check of pointer types in logical addressing mode to catch other validation errors.
This commit is contained in:
parent
e8ad02f3dd
commit
44f27f9289
@ -441,6 +441,15 @@ void spvValidatorOptionsSetUniversalLimit(spv_validator_options options,
|
|||||||
void spvValidatorOptionsSetRelaxStoreStruct(spv_validator_options options,
|
void spvValidatorOptionsSetRelaxStoreStruct(spv_validator_options options,
|
||||||
bool val);
|
bool val);
|
||||||
|
|
||||||
|
// Records whether or not the validator should relax the rules on pointer usage
|
||||||
|
// in logical addressing mode.
|
||||||
|
//
|
||||||
|
// When relaxed, it will allow the following usage cases of pointers:
|
||||||
|
// 1) OpVariable allocating an object whose type is a pointer type
|
||||||
|
// 2) OpReturnValue returning a pointer value
|
||||||
|
void spvValidatorOptionsSetRelaxLogicalPointer(spv_validator_options options,
|
||||||
|
bool val);
|
||||||
|
|
||||||
// Encodes the given SPIR-V assembly text to its binary representation. The
|
// Encodes the given SPIR-V assembly text to its binary representation. The
|
||||||
// length parameter specifies the number of bytes for text. Encoded binary will
|
// length parameter specifies the number of bytes for text. Encoded binary will
|
||||||
// be stored into *binary. Any error will be written into *diagnostic if
|
// be stored into *binary. Any error will be written into *diagnostic if
|
||||||
|
@ -81,6 +81,16 @@ class ValidatorOptions {
|
|||||||
spvValidatorOptionsSetRelaxStoreStruct(options_, val);
|
spvValidatorOptionsSetRelaxStoreStruct(options_, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Records whether or not the validator should relax the rules on pointer
|
||||||
|
// usage in logical addressing mode.
|
||||||
|
//
|
||||||
|
// When relaxed, it will allow the following usage cases of pointers:
|
||||||
|
// 1) OpVariable allocating an object whose type is a pointer type
|
||||||
|
// 2) OpReturnValue returning a pointer value
|
||||||
|
void SetRelaxLogicalPointer(bool val) {
|
||||||
|
spvValidatorOptionsSetRelaxLogicalPointer(options_, val);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spv_validator_options options_;
|
spv_validator_options options_;
|
||||||
};
|
};
|
||||||
|
@ -81,3 +81,8 @@ void spvValidatorOptionsSetRelaxStoreStruct(spv_validator_options options,
|
|||||||
bool val) {
|
bool val) {
|
||||||
options->relax_struct_store = val;
|
options->relax_struct_store = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void spvValidatorOptionsSetRelaxLogicalPointer(spv_validator_options options,
|
||||||
|
bool val) {
|
||||||
|
options->relax_logcial_pointer = val;
|
||||||
|
}
|
||||||
|
@ -37,10 +37,14 @@ struct validator_universal_limits_t {
|
|||||||
// Manages command line options passed to the SPIR-V Validator. New struct
|
// Manages command line options passed to the SPIR-V Validator. New struct
|
||||||
// members may be added for any new option.
|
// members may be added for any new option.
|
||||||
struct spv_validator_options_t {
|
struct spv_validator_options_t {
|
||||||
spv_validator_options_t() : universal_limits_(), relax_struct_store(false) {}
|
spv_validator_options_t()
|
||||||
|
: universal_limits_(),
|
||||||
|
relax_struct_store(false),
|
||||||
|
relax_logcial_pointer(false) {}
|
||||||
|
|
||||||
validator_universal_limits_t universal_limits_;
|
validator_universal_limits_t universal_limits_;
|
||||||
bool relax_struct_store;
|
bool relax_struct_store;
|
||||||
|
bool relax_logcial_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIBSPIRV_SPIRV_VALIDATOR_OPTIONS_H_
|
#endif // LIBSPIRV_SPIRV_VALIDATOR_OPTIONS_H_
|
||||||
|
@ -1879,16 +1879,20 @@ bool idUsage::isValid<SpvOpReturnValue>(const spv_instruction_t* inst,
|
|||||||
<< "' is missing or void.";
|
<< "' is missing or void.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool uses_variable_pointer =
|
const bool uses_variable_pointer =
|
||||||
module_.features().variable_pointers ||
|
module_.features().variable_pointers ||
|
||||||
module_.features().variable_pointers_storage_buffer;
|
module_.features().variable_pointers_storage_buffer;
|
||||||
|
|
||||||
if (addressingModel == SpvAddressingModelLogical &&
|
if (addressingModel == SpvAddressingModelLogical &&
|
||||||
SpvOpTypePointer == valueType->opcode() && !uses_variable_pointer) {
|
SpvOpTypePointer == valueType->opcode() && !uses_variable_pointer &&
|
||||||
|
!module_.options()->relax_logcial_pointer) {
|
||||||
DIAG(valueIndex)
|
DIAG(valueIndex)
|
||||||
<< "OpReturnValue value's type <id> '" << value->type_id()
|
<< "OpReturnValue value's type <id> '" << value->type_id()
|
||||||
<< "' is a pointer, which is invalid in the Logical addressing model.";
|
<< "' is a pointer, which is invalid in the Logical addressing model.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Find OpFunction
|
// NOTE: Find OpFunction
|
||||||
const spv_instruction_t* function = inst - 1;
|
const spv_instruction_t* function = inst - 1;
|
||||||
while (firstInst != function) {
|
while (firstInst != function) {
|
||||||
|
@ -2426,6 +2426,48 @@ TEST_F(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) {
|
|||||||
"<id> '16's layout."));
|
"<id> '16's layout."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) {
|
||||||
|
const string spirv = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability Linkage
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
%1 = OpTypeInt 32 1
|
||||||
|
%2 = OpTypePointer Function %1
|
||||||
|
%3 = OpTypeFunction %2 %2
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpFunctionParameter %2
|
||||||
|
%6 = OpLabel
|
||||||
|
OpReturnValue %5
|
||||||
|
OpFunctionEnd)";
|
||||||
|
|
||||||
|
spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
|
||||||
|
CompileSuccessfully(spirv.c_str());
|
||||||
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) {
|
||||||
|
const string spirv = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability Linkage
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
%1 = OpTypeVoid
|
||||||
|
%2 = OpTypeInt 32 1
|
||||||
|
%3 = OpTypeFunction %1 ; void(void)
|
||||||
|
%4 = OpTypePointer Uniform %2 ; int*
|
||||||
|
%5 = OpTypePointer Private %4 ; int** (Private)
|
||||||
|
%6 = OpTypePointer Function %4 ; int** (Function)
|
||||||
|
%7 = OpVariable %5 Private
|
||||||
|
%8 = OpFunction %1 None %3
|
||||||
|
%9 = OpLabel
|
||||||
|
%10 = OpVariable %6 Function
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd)";
|
||||||
|
|
||||||
|
spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
|
||||||
|
CompileSuccessfully(spirv.c_str());
|
||||||
|
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ValidateIdWithMessage, OpStoreVoid) {
|
TEST_F(ValidateIdWithMessage, OpStoreVoid) {
|
||||||
string spirv = kGLSL450MemoryModel + R"(
|
string spirv = kGLSL450MemoryModel + R"(
|
||||||
%1 = OpTypeVoid
|
%1 = OpTypeVoid
|
||||||
|
@ -44,6 +44,8 @@ Options:
|
|||||||
--max-function-args <maximum number arguments allowed per function>
|
--max-function-args <maximum number arguments allowed per function>
|
||||||
--max-control-flow-nesting-depth <maximum Control Flow nesting depth allowed>
|
--max-control-flow-nesting-depth <maximum Control Flow nesting depth allowed>
|
||||||
--max-access-chain-indexes <maximum number of indexes allowed to use for Access Chain instructions>
|
--max-access-chain-indexes <maximum number of indexes allowed to use for Access Chain instructions>
|
||||||
|
--relax-logcial-pointer Allow allocating an object of a pointer type and returning
|
||||||
|
a pointer value from a function in logical addressing mode
|
||||||
--relax-struct-store Allow store from one struct type to a
|
--relax-struct-store Allow store from one struct type to a
|
||||||
different type with compatible layout and
|
different type with compatible layout and
|
||||||
members.
|
members.
|
||||||
@ -112,6 +114,8 @@ int main(int argc, char** argv) {
|
|||||||
continue_processing = false;
|
continue_processing = false;
|
||||||
return_code = 1;
|
return_code = 1;
|
||||||
}
|
}
|
||||||
|
} else if (0 == strcmp(cur_arg, "--relax-logical-pointer")) {
|
||||||
|
options.SetRelaxLogicalPointer(true);
|
||||||
} else if (0 == strcmp(cur_arg, "--relax-struct-store")) {
|
} else if (0 == strcmp(cur_arg, "--relax-struct-store")) {
|
||||||
options.SetRelaxStructStore(true);
|
options.SetRelaxStructStore(true);
|
||||||
} else if (0 == cur_arg[1]) {
|
} else if (0 == cur_arg[1]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user