mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Implement SPV_NV_bindless_texture related changes (#4847)
* Add validation for SPV_NV_bindless_texture
This commit is contained in:
parent
93ebf698a0
commit
60615b8ec6
@ -293,6 +293,11 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
||||
return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
|
||||
<< "Missing OpFunctionEnd at end of module.";
|
||||
|
||||
if (vstate->HasCapability(SpvCapabilityBindlessTextureNV) &&
|
||||
!vstate->has_samplerimage_variable_address_mode_specified())
|
||||
return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
|
||||
<< "Missing required OpSamplerImageAddressingModeNV instruction.";
|
||||
|
||||
// Catch undefined forward references before performing further checks.
|
||||
if (auto error = ValidateForwardDecls(*vstate)) return error;
|
||||
|
||||
|
@ -66,7 +66,8 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
|
||||
assert(type_inst);
|
||||
const SpvOp type_opcode = type_inst->opcode();
|
||||
|
||||
if (!_.options()->before_hlsl_legalization) {
|
||||
if (!_.options()->before_hlsl_legalization &&
|
||||
!_.HasCapability(SpvCapabilityBindlessTextureNV)) {
|
||||
if (type_opcode == SpvOpTypeSampledImage ||
|
||||
(_.HasCapability(SpvCapabilityShader) &&
|
||||
(type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) {
|
||||
|
@ -190,6 +190,13 @@ uint32_t getBaseAlignment(uint32_t member_id, bool roundUp,
|
||||
// Minimal alignment is byte-aligned.
|
||||
uint32_t baseAlignment = 1;
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeImage:
|
||||
if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
|
||||
return baseAlignment = vstate.samplerimage_variable_address_mode() / 8;
|
||||
assert(0);
|
||||
return 0;
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
baseAlignment = words[2] / 8;
|
||||
@ -256,6 +263,13 @@ uint32_t getScalarAlignment(uint32_t type_id, ValidationState_t& vstate) {
|
||||
const auto inst = vstate.FindDef(type_id);
|
||||
const auto& words = inst->words();
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeImage:
|
||||
if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
|
||||
return vstate.samplerimage_variable_address_mode() / 8;
|
||||
assert(0);
|
||||
return 0;
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
return words[2] / 8;
|
||||
@ -296,6 +310,13 @@ uint32_t getSize(uint32_t member_id, const LayoutConstraints& inherited,
|
||||
const auto inst = vstate.FindDef(member_id);
|
||||
const auto& words = inst->words();
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeImage:
|
||||
if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
|
||||
return vstate.samplerimage_variable_address_mode() / 8;
|
||||
assert(0);
|
||||
return 0;
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
return words[2] / 8;
|
||||
|
@ -927,7 +927,7 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool IsAllowedSampledImageOperand(SpvOp opcode) {
|
||||
bool IsAllowedSampledImageOperand(SpvOp opcode, ValidationState_t& _) {
|
||||
switch (opcode) {
|
||||
case SpvOpSampledImage:
|
||||
case SpvOpImageSampleImplicitLod:
|
||||
@ -950,6 +950,9 @@ bool IsAllowedSampledImageOperand(SpvOp opcode) {
|
||||
case SpvOpImageSparseDrefGather:
|
||||
case SpvOpCopyObject:
|
||||
return true;
|
||||
case SpvOpStore:
|
||||
if (_.HasCapability(SpvCapabilityBindlessTextureNV)) return true;
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -1035,7 +1038,7 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
|
||||
<< _.getIdName(consumer_instr->id()) << "'.";
|
||||
}
|
||||
|
||||
if (!IsAllowedSampledImageOperand(consumer_opcode)) {
|
||||
if (!IsAllowedSampledImageOperand(consumer_opcode, _)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Result <id> from OpSampledImage instruction must not appear "
|
||||
"as operand for Op"
|
||||
|
@ -483,6 +483,22 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
|
||||
if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
|
||||
return error;
|
||||
}
|
||||
} else if (opcode == SpvOpSamplerImageAddressingModeNV) {
|
||||
if (!_.HasCapability(SpvCapabilityBindlessTextureNV)) {
|
||||
return _.diag(SPV_ERROR_MISSING_EXTENSION, inst)
|
||||
<< "OpSamplerImageAddressingModeNV supported only with extension "
|
||||
"SPV_NV_bindless_texture";
|
||||
}
|
||||
uint32_t bitwidth = inst->GetOperandAs<uint32_t>(0);
|
||||
if (_.samplerimage_variable_address_mode() != 0) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
|
||||
<< "OpSamplerImageAddressingModeNV should only be provided once";
|
||||
}
|
||||
if (bitwidth != 32 && bitwidth != 64) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "OpSamplerImageAddressingModeNV bitwidth should be 64 or 32";
|
||||
}
|
||||
_.set_samplerimage_variable_address_mode(bitwidth);
|
||||
}
|
||||
|
||||
if (auto error = ReservedCheck(_, inst)) return error;
|
||||
|
@ -363,6 +363,7 @@ spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
|
||||
case kLayoutExtensions:
|
||||
case kLayoutExtInstImport:
|
||||
case kLayoutMemoryModel:
|
||||
case kLayoutSamplerImageAddressMode:
|
||||
case kLayoutEntryPoint:
|
||||
case kLayoutExecutionMode:
|
||||
case kLayoutDebug1:
|
||||
|
@ -170,6 +170,16 @@ spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) {
|
||||
break;
|
||||
}
|
||||
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler: {
|
||||
if (!_.HasCapability(SpvCapabilityBindlessTextureNV))
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "Using image/sampler with OpSelect requires capability "
|
||||
<< "BindlessTextureNV";
|
||||
break;
|
||||
}
|
||||
|
||||
case SpvOpTypeVector: {
|
||||
dimension = type_inst->word(3);
|
||||
break;
|
||||
|
@ -306,35 +306,6 @@ spv_result_t ValidateTypeRuntimeArray(ValidationState_t& _,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool ContainsOpaqueType(ValidationState_t& _, const Instruction* str) {
|
||||
const size_t elem_type_index = 1;
|
||||
uint32_t elem_type_id;
|
||||
Instruction* elem_type;
|
||||
|
||||
if (spvOpcodeIsBaseOpaqueType(str->opcode())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (str->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
elem_type_id = str->GetOperandAs<uint32_t>(elem_type_index);
|
||||
elem_type = _.FindDef(elem_type_id);
|
||||
return ContainsOpaqueType(_, elem_type);
|
||||
case SpvOpTypeStruct:
|
||||
for (size_t member_type_index = 1;
|
||||
member_type_index < str->operands().size(); ++member_type_index) {
|
||||
auto member_type_id = str->GetOperandAs<uint32_t>(member_type_index);
|
||||
auto member_type = _.FindDef(member_type_id);
|
||||
if (ContainsOpaqueType(_, member_type)) return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) {
|
||||
const uint32_t struct_id = inst->GetOperandAs<uint32_t>(0);
|
||||
for (size_t member_type_index = 1;
|
||||
@ -425,8 +396,21 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) {
|
||||
_.RegisterStructTypeWithBuiltInMember(struct_id);
|
||||
}
|
||||
|
||||
const auto isOpaqueType = [&_](const Instruction* opaque_inst) {
|
||||
auto opcode = opaque_inst->opcode();
|
||||
if (_.HasCapability(SpvCapabilityBindlessTextureNV) &&
|
||||
(opcode == SpvOpTypeImage || opcode == SpvOpTypeSampler ||
|
||||
opcode == SpvOpTypeSampledImage)) {
|
||||
return false;
|
||||
} else if (spvOpcodeIsBaseOpaqueType(opcode)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (spvIsVulkanEnv(_.context()->target_env) &&
|
||||
!_.options()->before_hlsl_legalization && ContainsOpaqueType(_, inst)) {
|
||||
!_.options()->before_hlsl_legalization &&
|
||||
_.ContainsType(inst->id(), isOpaqueType)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< _.VkErrorID(4667) << "In "
|
||||
<< spvLogStringForEnv(_.context()->target_env)
|
||||
|
@ -90,6 +90,8 @@ ModuleLayoutSection InstructionLayoutSection(
|
||||
if (current_section == kLayoutFunctionDeclarations)
|
||||
return kLayoutFunctionDeclarations;
|
||||
return kLayoutFunctionDefinitions;
|
||||
case SpvOpSamplerImageAddressingModeNV:
|
||||
return kLayoutSamplerImageAddressMode;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -161,6 +163,7 @@ ValidationState_t::ValidationState_t(const spv_const_context ctx,
|
||||
addressing_model_(SpvAddressingModelMax),
|
||||
memory_model_(SpvMemoryModelMax),
|
||||
pointer_size_and_alignment_(0),
|
||||
sampler_image_addressing_mode_(0),
|
||||
in_function_(false),
|
||||
num_of_warnings_(0),
|
||||
max_num_of_warnings_(max_warnings) {
|
||||
@ -473,6 +476,15 @@ void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
|
||||
|
||||
SpvMemoryModel ValidationState_t::memory_model() const { return memory_model_; }
|
||||
|
||||
void ValidationState_t::set_samplerimage_variable_address_mode(
|
||||
uint32_t bit_width) {
|
||||
sampler_image_addressing_mode_ = bit_width;
|
||||
}
|
||||
|
||||
uint32_t ValidationState_t::samplerimage_variable_address_mode() const {
|
||||
return sampler_image_addressing_mode_;
|
||||
}
|
||||
|
||||
spv_result_t ValidationState_t::RegisterFunction(
|
||||
uint32_t id, uint32_t ret_type_id, SpvFunctionControlMask function_control,
|
||||
uint32_t function_type_id) {
|
||||
|
@ -44,19 +44,20 @@ namespace val {
|
||||
/// of the SPIRV spec for additional details of the order. The enumerant values
|
||||
/// are in the same order as the vector returned by GetModuleOrder
|
||||
enum ModuleLayoutSection {
|
||||
kLayoutCapabilities, /// < Section 2.4 #1
|
||||
kLayoutExtensions, /// < Section 2.4 #2
|
||||
kLayoutExtInstImport, /// < Section 2.4 #3
|
||||
kLayoutMemoryModel, /// < Section 2.4 #4
|
||||
kLayoutEntryPoint, /// < Section 2.4 #5
|
||||
kLayoutExecutionMode, /// < Section 2.4 #6
|
||||
kLayoutDebug1, /// < Section 2.4 #7 > 1
|
||||
kLayoutDebug2, /// < Section 2.4 #7 > 2
|
||||
kLayoutDebug3, /// < Section 2.4 #7 > 3
|
||||
kLayoutAnnotations, /// < Section 2.4 #8
|
||||
kLayoutTypes, /// < Section 2.4 #9
|
||||
kLayoutFunctionDeclarations, /// < Section 2.4 #10
|
||||
kLayoutFunctionDefinitions /// < Section 2.4 #11
|
||||
kLayoutCapabilities, /// < Section 2.4 #1
|
||||
kLayoutExtensions, /// < Section 2.4 #2
|
||||
kLayoutExtInstImport, /// < Section 2.4 #3
|
||||
kLayoutMemoryModel, /// < Section 2.4 #4
|
||||
kLayoutSamplerImageAddressMode, /// < Section 2.4 #5
|
||||
kLayoutEntryPoint, /// < Section 2.4 #6
|
||||
kLayoutExecutionMode, /// < Section 2.4 #7
|
||||
kLayoutDebug1, /// < Section 2.4 #8 > 1
|
||||
kLayoutDebug2, /// < Section 2.4 #8 > 2
|
||||
kLayoutDebug3, /// < Section 2.4 #8 > 3
|
||||
kLayoutAnnotations, /// < Section 2.4 #9
|
||||
kLayoutTypes, /// < Section 2.4 #10
|
||||
kLayoutFunctionDeclarations, /// < Section 2.4 #11
|
||||
kLayoutFunctionDefinitions /// < Section 2.4 #12
|
||||
};
|
||||
|
||||
/// This class manages the state of the SPIR-V validation as it is being parsed.
|
||||
@ -360,6 +361,20 @@ class ValidationState_t {
|
||||
/// Returns the memory model of this module, or Simple if uninitialized.
|
||||
SpvMemoryModel memory_model() const;
|
||||
|
||||
/// Sets the bit width for sampler/image type variables. If not set, they are
|
||||
/// considered opaque
|
||||
void set_samplerimage_variable_address_mode(uint32_t bit_width);
|
||||
|
||||
/// Get the addressing mode currently set. If 0, it means addressing mode is
|
||||
/// invalid Sampler/Image type variables must be considered opaque This mode
|
||||
/// is only valid after the instruction has been read
|
||||
uint32_t samplerimage_variable_address_mode() const;
|
||||
|
||||
/// Returns true if the OpSamplerImageAddressingModeNV was found.
|
||||
bool has_samplerimage_variable_address_mode_specified() const {
|
||||
return sampler_image_addressing_mode_ != 0;
|
||||
}
|
||||
|
||||
const AssemblyGrammar& grammar() const { return grammar_; }
|
||||
|
||||
/// Inserts the instruction into the list of ordered instructions in the file.
|
||||
@ -864,7 +879,10 @@ class ValidationState_t {
|
||||
// have the same pointer size (for physical pointer types).
|
||||
uint32_t pointer_size_and_alignment_;
|
||||
|
||||
/// NOTE: See corresponding getter functions
|
||||
/// bit width of sampler/image type variables. Valid values are 32 and 64
|
||||
uint32_t sampler_image_addressing_mode_;
|
||||
|
||||
/// NOTE: See correspoding getter functions
|
||||
bool in_function_;
|
||||
|
||||
/// The state of optional features. These are determined by capabilities
|
||||
|
@ -8695,6 +8695,47 @@ INSTANTIATE_TEST_SUITE_P(FragmentInputInterface, ValidateDecorationString,
|
||||
::testing::Values("Flat", "NoPerspective", "Sample",
|
||||
"Centroid"));
|
||||
|
||||
TEST_F(ValidateDecorations, NVBindlessSamplerArrayInBlock) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %UBO "UBO"
|
||||
OpMemberName %UBO 0 "uboSampler"
|
||||
OpName %_ ""
|
||||
OpDecorate %array ArrayStride 16
|
||||
OpMemberDecorate %UBO 0 Offset 0
|
||||
OpDecorate %UBO Block
|
||||
OpDecorate %_ DescriptorSet 0
|
||||
OpDecorate %_ Binding 2
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%8 = OpTypeSampledImage %7
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%array = OpTypeArray %8 %uint_3
|
||||
%UBO = OpTypeStruct %array
|
||||
%pointer = OpTypePointer Uniform %UBO
|
||||
%_ = OpVariable %pointer Uniform
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -6570,6 +6570,35 @@ TEST_F(ValidateIdWithMessage, MissingForwardPointer) {
|
||||
"Operand 3[%_ptr_Uniform__struct_2] requires a previous definition"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateIdWithMessage, NVBindlessSamplerInStruct) {
|
||||
std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%8 = OpTypeSampledImage %7
|
||||
%9 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
|
||||
%10 = OpTypeSampler
|
||||
%UBO = OpTypeStruct %8 %9 %10
|
||||
%_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
|
||||
%_ = OpVariable %_ptr_Uniform_UBO Uniform
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -6248,6 +6248,138 @@ OpFunctionEnd
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, NVBindlessSamplerBuiltins) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int64
|
||||
OpCapability Image1D
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %s2D "s2D"
|
||||
OpName %textureHandle "textureHandle"
|
||||
OpName %i1D "i1D"
|
||||
OpName %s "s"
|
||||
OpName %temp "temp"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%8 = OpTypeSampledImage %7
|
||||
%_ptr_Function_8 = OpTypePointer Function %8
|
||||
%ulong = OpTypeInt 64 0
|
||||
%_ptr_Private_ulong = OpTypePointer Private %ulong
|
||||
%textureHandle = OpVariable %_ptr_Private_ulong Private
|
||||
%16 = OpTypeImage %float 1D 0 0 0 2 Rgba32f
|
||||
%_ptr_Function_16 = OpTypePointer Function %16
|
||||
%21 = OpTypeSampler
|
||||
%_ptr_Function_21 = OpTypePointer Function %21
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%s2D = OpVariable %_ptr_Function_8 Function
|
||||
%i1D = OpVariable %_ptr_Function_16 Function
|
||||
%s = OpVariable %_ptr_Function_21 Function
|
||||
%temp = OpVariable %_ptr_Function_ulong Function
|
||||
%14 = OpLoad %ulong %textureHandle
|
||||
%15 = OpConvertUToSampledImageNV %8 %14
|
||||
OpStore %s2D %15
|
||||
%19 = OpLoad %ulong %textureHandle
|
||||
%20 = OpConvertUToImageNV %16 %19
|
||||
OpStore %i1D %20
|
||||
%24 = OpLoad %ulong %textureHandle
|
||||
%25 = OpConvertUToSamplerNV %21 %24
|
||||
OpStore %s %25
|
||||
%28 = OpLoad %8 %s2D
|
||||
%29 = OpConvertSampledImageToUNV %ulong %28
|
||||
OpStore %temp %29
|
||||
%30 = OpLoad %16 %i1D
|
||||
%31 = OpConvertImageToUNV %ulong %30
|
||||
OpStore %temp %31
|
||||
%32 = OpLoad %21 %s
|
||||
%33 = OpConvertSamplerToUNV %ulong %32
|
||||
OpStore %temp %33
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, NVBindlessAddressingMode64) {
|
||||
std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, NVBindlessAddressingMode32) {
|
||||
std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 32
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, NVBindlessInvalidAddressingMode) {
|
||||
std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 0
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("OpSamplerImageAddressingModeNV bitwidth should be 64 or 32"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -667,6 +667,98 @@ TEST_F(ValidateLayout, ModuleProcessedInvalidInBasicBlock) {
|
||||
|
||||
// TODO(umar): Test optional instructions
|
||||
|
||||
TEST_F(ValidateLayout, ValidNVBindlessTexturelayout) {
|
||||
std::string str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateLayout, InvalidValidNVBindlessTexturelayout) {
|
||||
std::string str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"SamplerImageAddressingModeNV is in an invalid layout section"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateLayout, MissingNVBindlessAddressModeFromLayout) {
|
||||
std::string str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %func "main"
|
||||
%voidt = OpTypeVoid
|
||||
%uintt = OpTypeInt 32 0
|
||||
%funct = OpTypeFunction %voidt
|
||||
%func = OpFunction %voidt None %funct
|
||||
%entry = OpLabel
|
||||
%udef = OpUndef %uintt
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Missing required OpSamplerImageAddressingModeNV instruction"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateLayout, NVBindlessAddressModeFromLayoutSpecifiedTwice) {
|
||||
std::string str = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT,
|
||||
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("OpSamplerImageAddressingModeNV should only be provided once"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
@ -1159,6 +1159,61 @@ OpFunctionEnd
|
||||
"condition to be equal: Select"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateLogicals, SelectNVBindlessSamplers) {
|
||||
const std::string spirv = R"(
|
||||
OpCapability Shader
|
||||
OpCapability BindlessTextureNV
|
||||
OpExtension "SPV_NV_bindless_texture"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpSamplerImageAddressingModeNV 64
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpSourceExtension "GL_NV_bindless_texture"
|
||||
OpName %main "main"
|
||||
OpName %s2D "s2D"
|
||||
OpName %pickhandle "pickhandle"
|
||||
OpName %Sampler1 "Sampler1"
|
||||
OpName %Sampler2 "Sampler2"
|
||||
OpDecorate %pickhandle Flat
|
||||
OpDecorate %Sampler1 DescriptorSet 0
|
||||
OpDecorate %Sampler1 Binding 0
|
||||
OpDecorate %Sampler1 BindlessSamplerNV
|
||||
OpDecorate %Sampler2 DescriptorSet 0
|
||||
OpDecorate %Sampler2 Binding 1
|
||||
OpDecorate %Sampler2 BindlessSamplerNV
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%7 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%8 = OpTypeSampledImage %7
|
||||
%_ptr_Function_8 = OpTypePointer Function %8
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_0 = OpConstant %int 0
|
||||
%bool = OpTypeBool
|
||||
%_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
|
||||
%Sampler1 = OpVariable %_ptr_UniformConstant_8 UniformConstant
|
||||
%Sampler2 = OpVariable %_ptr_UniformConstant_8 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%s2D = OpVariable %_ptr_Function_8 Function
|
||||
%pickhandle = OpVariable %_ptr_Function_int Function
|
||||
%14 = OpLoad %int %pickhandle
|
||||
%17 = OpIEqual %bool %14 %int_0
|
||||
%20 = OpLoad %8 %Sampler1
|
||||
%22 = OpLoad %8 %Sampler2
|
||||
%23 = OpSelect %8 %17 %20 %22
|
||||
OpStore %s2D %23
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user