From 0b0d975363eabf5b6f6457e253f7eb44daf3e88f Mon Sep 17 00:00:00 2001 From: Pankaj Mistry Date: Tue, 25 May 2021 14:56:23 -0700 Subject: [PATCH] Implement SPV_NV_bindless_texture related changes --- source/val/validate.cpp | 5 + source/val/validate_cfg.cpp | 3 +- source/val/validate_decorations.cpp | 17 +++ source/val/validate_image.cpp | 9 +- source/val/validate_instruction.cpp | 15 +++ source/val/validate_layout.cpp | 1 + source/val/validate_logicals.cpp | 10 ++ source/val/validate_type.cpp | 45 +++---- source/val/validation_state.cpp | 13 ++ source/val/validation_state.h | 46 ++++--- test/val/val_decoration_test.cpp | 41 +++++++ test/val/val_id_test.cpp | 29 +++++ test/val/val_image_test.cpp | 130 ++++++++++++++++++++ test/val/val_layout_test.cpp | 75 +++++++++++- test/val/val_logicals_test.cpp | 55 +++++++++ utils/vscode/src/schema/schema.go | 179 ++++++++++++++++++++++++++++ 16 files changed, 625 insertions(+), 48 deletions(-) diff --git a/source/val/validate.cpp b/source/val/validate.cpp index ecc9fdb6394..f2cab8e05c0 100644 --- a/source/val/validate.cpp +++ b/source/val/validate.cpp @@ -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; diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp index d4ca20e5d76..52cce7c4ced 100644 --- a/source/val/validate_cfg.cpp +++ b/source/val/validate_cfg.cpp @@ -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))) { diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp index 986f32953cd..30a119ab7c2 100644 --- a/source/val/validate_decorations.cpp +++ b/source/val/validate_decorations.cpp @@ -190,6 +190,12 @@ 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)) + baseAlignment = vstate.samplerimage_variable_address_mode()/8; + break; case SpvOpTypeInt: case SpvOpTypeFloat: baseAlignment = words[2] / 8; @@ -256,6 +262,12 @@ 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; + break; case SpvOpTypeInt: case SpvOpTypeFloat: return words[2] / 8; @@ -296,6 +308,11 @@ 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; case SpvOpTypeInt: case SpvOpTypeFloat: return words[2] / 8; diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp index f6d7d103c72..fad32bdacc5 100644 --- a/source/val/validate_image.cpp +++ b/source/val/validate_image.cpp @@ -927,7 +927,8 @@ 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 +951,10 @@ bool IsAllowedSampledImageOperand(SpvOp opcode) { case SpvOpImageSparseDrefGather: case SpvOpCopyObject: return true; + case SpvOpStore: + if(_.HasCapability(SpvCapabilityBindlessTextureNV)) + return true; + return false; default: return false; } @@ -1035,7 +1040,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 from OpSampledImage instruction must not appear " "as operand for Op" diff --git a/source/val/validate_instruction.cpp b/source/val/validate_instruction.cpp index 3edf1637977..95f94aaefeb 100644 --- a/source/val/validate_instruction.cpp +++ b/source/val/validate_instruction.cpp @@ -483,6 +483,21 @@ 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(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; diff --git a/source/val/validate_layout.cpp b/source/val/validate_layout.cpp index d5823219d93..6f9513523ef 100644 --- a/source/val/validate_layout.cpp +++ b/source/val/validate_layout.cpp @@ -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: diff --git a/source/val/validate_logicals.cpp b/source/val/validate_logicals.cpp index 5307988e395..ec1e207be1f 100644 --- a/source/val/validate_logicals.cpp +++ b/source/val/validate_logicals.cpp @@ -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; diff --git a/source/val/validate_type.cpp b/source/val/validate_type.cpp index 2aded61658c..7101ed048bb 100644 --- a/source/val/validate_type.cpp +++ b/source/val/validate_type.cpp @@ -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(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(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(0); for (size_t member_type_index = 1; @@ -425,8 +396,22 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) { _.RegisterStructTypeWithBuiltInMember(struct_id); } + const auto isOpaqueType = [&_](const Instruction *inst) { + auto opcode = 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) diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index 77e1573f79b..91fa937a6e8 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -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,16 @@ 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) { diff --git a/source/val/validation_state.h b/source/val/validation_state.h index 217804644f5..56b7a193368 100644 --- a/source/val/validation_state.h +++ b/source/val/validation_state.h @@ -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. @@ -862,7 +877,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 diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp index e117e6f8c53..fd8d9cdfcc1 100644 --- a/test/val/val_decoration_test.cpp +++ b/test/val/val_decoration_test.cpp @@ -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 diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp index 69257a58759..b7e504227ae 100644 --- a/test/val/val_id_test.cpp +++ b/test/val/val_id_test.cpp @@ -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 diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp index 76af29ccb75..764df241ca4 100644 --- a/test/val/val_image_test.cpp +++ b/test/val/val_image_test.cpp @@ -6248,6 +6248,136 @@ 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 diff --git a/test/val/val_layout_test.cpp b/test/val/val_layout_test.cpp index 7ebd7c0084b..13cd66bd3d3 100644 --- a/test/val/val_layout_test.cpp +++ b/test/val/val_layout_test.cpp @@ -203,7 +203,7 @@ TEST_P(ValidateLayout, Layout) { std::ostream_iterator(ss, "\n")); const auto env = SPV_ENV_UNIVERSAL_1_3; - // printf("code: \n%s\n", ss.str().c_str()); + //printf("code: \n%s\n", ss.str().c_str()); CompileSuccessfully(ss.str(), env); spv_result_t result; // clang-format off @@ -667,6 +667,79 @@ 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_1)); + 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_1)); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("Missing required OpSamplerImageAddressingModeNV instruction")); +} + } // namespace } // namespace val } // namespace spvtools diff --git a/test/val/val_logicals_test.cpp b/test/val/val_logicals_test.cpp index 1b76c8533ed..c1406728a04 100644 --- a/test/val/val_logicals_test.cpp +++ b/test/val/val_logicals_test.cpp @@ -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 diff --git a/utils/vscode/src/schema/schema.go b/utils/vscode/src/schema/schema.go index ed02de4e3a3..5433b4346ba 100755 --- a/utils/vscode/src/schema/schema.go +++ b/utils/vscode/src/schema/schema.go @@ -11617,6 +11617,150 @@ var ( }, }, } + OpConvertUToImageNV = &Opcode { + Opname: "OpConvertUToImageNV", + Class: "Reserved", + Opcode: 5391, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpConvertUToSamplerNV = &Opcode { + Opname: "OpConvertUToSamplerNV", + Class: "Reserved", + Opcode: 5392, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpConvertImageToUNV = &Opcode { + Opname: "OpConvertImageToUNV", + Class: "Reserved", + Opcode: 5393, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpConvertSamplerToUNV = &Opcode { + Opname: "OpConvertSamplerToUNV", + Class: "Reserved", + Opcode: 5394, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpConvertSamplerToUNV = &Opcode { + Opname: "OpConvertUToSampledImageNV", + Class: "Reserved", + Opcode: 5395, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpConvertSamplerToUNV = &Opcode { + Opname: "OpConvertSampledImageToUNV", + Class: "Reserved", + Opcode: 5396, + Operands: []Operand { + Operand { + Kind: OperandKindIdResultType, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdResult, + Name: "", + Quantifier: "", + }, + Operand { + Kind: OperandKindIdRef, + Name: "'Operand'", + Quantifier: "", + }, + }, + } + OpMemoryModel = &Opcode { + Opname: "OpSamplerImageAddressingModeNV", + Class: "Reserved", + Opcode: 5397, + Operands: []Operand { + Operand { + Kind: OperandKindLiteralInteger, + Name: "'bit width'", + Quantifier: "", + }, + }, + } OpSubgroupShuffleINTEL = &Opcode { Opname: "OpSubgroupShuffleINTEL", Class: "Group", @@ -22420,6 +22564,34 @@ var ( Parameters: []Parameter{}, Version: "1.5", }, + Enumerant{ + Enumerant: "BindlessSamplerNV", + Value: 5398, + Capabilities: []string{"BindlessTextureNV",}, + Parameters: []Parameter{}, + Version: "None", + }, + Enumerant{ + Enumerant: "BindlessImageNV", + Value: 5399, + Capabilities: []string{"BindlessTextureNV",}, + Parameters: []Parameter{}, + Version: "None", + }, + Enumerant{ + Enumerant: "BoundSamplerNV", + Value: 5400, + Capabilities: []string{"BindlessTextureNV",}, + Parameters: []Parameter{}, + Version: "None", + }, + Enumerant{ + Enumerant: "BoundImageNV", + Value: 5401, + Capabilities: []string{"BindlessTextureNV",}, + Parameters: []Parameter{}, + Version: "None", + }, Enumerant{ Enumerant: "CounterBuffer", Value: 5634, @@ -24513,6 +24685,13 @@ var ( Parameters: []Parameter{}, Version: "None", }, + Enumerant{ + Enumerant: "BindlessTextureNV", + Value: 5390, + Capabilities: []string{}, + Parameters: []Parameter{}, + Version: "None", + }, Enumerant{ Enumerant: "SubgroupShuffleINTEL", Value: 5568,