diff --git a/.versions/spirv-tools b/.versions/spirv-tools index 55bbc79..67c516a 100644 --- a/.versions/spirv-tools +++ b/.versions/spirv-tools @@ -1 +1 @@ -vulkan-sdk-1.3.280.0 +v2024.2.rc1 diff --git a/spirv-tools/source/ext_inst.cpp b/spirv-tools/source/ext_inst.cpp index 4e27954..9a5ba84 100644 --- a/spirv-tools/source/ext_inst.cpp +++ b/spirv-tools/source/ext_inst.cpp @@ -30,6 +30,7 @@ #include "glsl.std.450.insts.inc" #include "nonsemantic.clspvreflection.insts.inc" #include "nonsemantic.shader.debuginfo.100.insts.inc" +#include "nonsemantic.vkspreflection.insts.inc" #include "opencl.debuginfo.100.insts.inc" #include "opencl.std.insts.inc" @@ -62,6 +63,9 @@ static const spv_ext_inst_group_t kGroups_1_0[] = { {SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION, ARRAY_SIZE(nonsemantic_clspvreflection_entries), nonsemantic_clspvreflection_entries}, + {SPV_EXT_INST_TYPE_NONSEMANTIC_VKSPREFLECTION, + ARRAY_SIZE(nonsemantic_vkspreflection_entries), + nonsemantic_vkspreflection_entries}, }; static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0), @@ -138,6 +142,9 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) { if (!strncmp("NonSemantic.ClspvReflection.", name, 28)) { return SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION; } + if (!strncmp("NonSemantic.VkspReflection.", name, 27)) { + return SPV_EXT_INST_TYPE_NONSEMANTIC_VKSPREFLECTION; + } // ensure to add any known non-semantic extended instruction sets // above this point, and update spvExtInstIsNonSemantic() if (!strncmp("NonSemantic.", name, 12)) { @@ -149,7 +156,8 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) { bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type) { if (type == SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN || type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100 || - type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) { + type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION || + type == SPV_EXT_INST_TYPE_NONSEMANTIC_VKSPREFLECTION) { return true; } return false; diff --git a/spirv-tools/source/opcode.cpp b/spirv-tools/source/opcode.cpp index 38d1a1b..787dbb3 100644 --- a/spirv-tools/source/opcode.cpp +++ b/spirv-tools/source/opcode.cpp @@ -295,6 +295,7 @@ bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) { case spv::Op::OpPtrAccessChain: case spv::Op::OpLoad: case spv::Op::OpConstantNull: + case spv::Op::OpRawAccessChainNV: return true; default: return false; @@ -309,6 +310,7 @@ int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode) { case spv::Op::OpFunctionParameter: case spv::Op::OpImageTexelPointer: case spv::Op::OpCopyObject: + case spv::Op::OpRawAccessChainNV: return true; default: return false; @@ -754,6 +756,7 @@ bool spvOpcodeIsAccessChain(spv::Op opcode) { case spv::Op::OpInBoundsAccessChain: case spv::Op::OpPtrAccessChain: case spv::Op::OpInBoundsPtrAccessChain: + case spv::Op::OpRawAccessChainNV: return true; default: return false; diff --git a/spirv-tools/source/opt/constants.cpp b/spirv-tools/source/opt/constants.cpp index a487a45..6eebbb5 100644 --- a/spirv-tools/source/opt/constants.cpp +++ b/spirv-tools/source/opt/constants.cpp @@ -498,7 +498,7 @@ const Constant* ConstantManager::GetIntConst(uint64_t val, int32_t bitWidth, int32_t num_of_bit_to_ignore = 64 - bitWidth; val = static_cast(val << num_of_bit_to_ignore) >> num_of_bit_to_ignore; - } else { + } else if (bitWidth < 64) { // Clear the upper bit that are not used. uint64_t mask = ((1ull << bitWidth) - 1); val &= mask; @@ -511,7 +511,7 @@ const Constant* ConstantManager::GetIntConst(uint64_t val, int32_t bitWidth, // If the value is more than 32-bit, we need to split the operands into two // 32-bit integers. return GetConstant( - int_type, {static_cast(val >> 32), static_cast(val)}); + int_type, {static_cast(val), static_cast(val >> 32)}); } uint32_t ConstantManager::GetUIntConstId(uint32_t val) { diff --git a/spirv-tools/source/opt/inline_pass.cpp b/spirv-tools/source/opt/inline_pass.cpp index 3f160b2..3186433 100644 --- a/spirv-tools/source/opt/inline_pass.cpp +++ b/spirv-tools/source/opt/inline_pass.cpp @@ -213,6 +213,19 @@ uint32_t InlinePass::CreateReturnVar( {(uint32_t)spv::StorageClass::Function}}})); new_vars->push_back(std::move(var_inst)); get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId); + + // Decorate the return var with AliasedPointer if the storage class of the + // pointee type is PhysicalStorageBuffer. + auto const pointee_type = + type_mgr->GetType(returnVarTypeId)->AsPointer()->pointee_type(); + if (pointee_type->AsPointer() != nullptr) { + if (pointee_type->AsPointer()->storage_class() == + spv::StorageClass::PhysicalStorageBuffer) { + get_decoration_mgr()->AddDecoration( + returnVarId, uint32_t(spv::Decoration::AliasedPointer)); + } + } + return returnVarId; } diff --git a/spirv-tools/source/opt/ir_context.cpp b/spirv-tools/source/opt/ir_context.cpp index 239d316..d864b7c 100644 --- a/spirv-tools/source/opt/ir_context.cpp +++ b/spirv-tools/source/opt/ir_context.cpp @@ -88,6 +88,9 @@ void IRContext::BuildInvalidAnalyses(IRContext::Analysis set) { if (set & kAnalysisDebugInfo) { BuildDebugInfoManager(); } + if (set & kAnalysisLiveness) { + BuildLivenessManager(); + } } void IRContext::InvalidateAnalysesExceptFor( diff --git a/spirv-tools/source/opt/ir_context.h b/spirv-tools/source/opt/ir_context.h index 5685db8..ef7c458 100644 --- a/spirv-tools/source/opt/ir_context.h +++ b/spirv-tools/source/opt/ir_context.h @@ -84,7 +84,7 @@ class IRContext { kAnalysisTypes = 1 << 15, kAnalysisDebugInfo = 1 << 16, kAnalysisLiveness = 1 << 17, - kAnalysisEnd = 1 << 17 + kAnalysisEnd = 1 << 18 }; using ProcessFunction = std::function; diff --git a/spirv-tools/source/opt/trim_capabilities_pass.h b/spirv-tools/source/opt/trim_capabilities_pass.h index 3a8460f..81c07b8 100644 --- a/spirv-tools/source/opt/trim_capabilities_pass.h +++ b/spirv-tools/source/opt/trim_capabilities_pass.h @@ -98,7 +98,8 @@ class TrimCapabilitiesPass : public Pass { spv::Capability::StoragePushConstant16, spv::Capability::StorageUniform16, spv::Capability::StorageUniformBufferBlock16, - spv::Capability::VulkanMemoryModelDeviceScope + spv::Capability::VulkanMemoryModelDeviceScope, + spv::Capability::GroupNonUniformPartitionedNV // clang-format on }; diff --git a/spirv-tools/source/opt/type_manager.cpp b/spirv-tools/source/opt/type_manager.cpp index ae32077..7b609bc 100644 --- a/spirv-tools/source/opt/type_manager.cpp +++ b/spirv-tools/source/opt/type_manager.cpp @@ -517,13 +517,24 @@ void TypeManager::CreateDecoration(uint32_t target, context()->get_def_use_mgr()->AnalyzeInstUse(inst); } -Type* TypeManager::RebuildType(const Type& type) { +Type* TypeManager::RebuildType(uint32_t type_id, const Type& type) { + assert(type_id != 0); + // The comparison and hash on the type pool will avoid inserting the rebuilt // type if an equivalent type already exists. The rebuilt type will be deleted // when it goes out of scope at the end of the function in that case. Repeated // insertions of the same Type will, at most, keep one corresponding object in // the type pool. std::unique_ptr rebuilt_ty; + + // If |type_id| is already present in the type pool, return the existing type. + // This saves extra work in the type builder and prevents running into + // circular issues (https://github.com/KhronosGroup/SPIRV-Tools/issues/5623). + Type* pool_ty = GetType(type_id); + if (pool_ty != nullptr) { + return pool_ty; + } + switch (type.kind()) { #define DefineNoSubtypeCase(kind) \ case Type::k##kind: \ @@ -550,43 +561,46 @@ Type* TypeManager::RebuildType(const Type& type) { case Type::kVector: { const Vector* vec_ty = type.AsVector(); const Type* ele_ty = vec_ty->element_type(); - rebuilt_ty = - MakeUnique(RebuildType(*ele_ty), vec_ty->element_count()); + rebuilt_ty = MakeUnique(RebuildType(GetId(ele_ty), *ele_ty), + vec_ty->element_count()); break; } case Type::kMatrix: { const Matrix* mat_ty = type.AsMatrix(); const Type* ele_ty = mat_ty->element_type(); - rebuilt_ty = - MakeUnique(RebuildType(*ele_ty), mat_ty->element_count()); + rebuilt_ty = MakeUnique(RebuildType(GetId(ele_ty), *ele_ty), + mat_ty->element_count()); break; } case Type::kImage: { const Image* image_ty = type.AsImage(); const Type* ele_ty = image_ty->sampled_type(); - rebuilt_ty = - MakeUnique(RebuildType(*ele_ty), image_ty->dim(), - image_ty->depth(), image_ty->is_arrayed(), - image_ty->is_multisampled(), image_ty->sampled(), - image_ty->format(), image_ty->access_qualifier()); + rebuilt_ty = MakeUnique( + RebuildType(GetId(ele_ty), *ele_ty), image_ty->dim(), + image_ty->depth(), image_ty->is_arrayed(), + image_ty->is_multisampled(), image_ty->sampled(), image_ty->format(), + image_ty->access_qualifier()); break; } case Type::kSampledImage: { const SampledImage* image_ty = type.AsSampledImage(); const Type* ele_ty = image_ty->image_type(); - rebuilt_ty = MakeUnique(RebuildType(*ele_ty)); + rebuilt_ty = + MakeUnique(RebuildType(GetId(ele_ty), *ele_ty)); break; } case Type::kArray: { const Array* array_ty = type.AsArray(); - rebuilt_ty = - MakeUnique(array_ty->element_type(), array_ty->length_info()); + const Type* ele_ty = array_ty->element_type(); + rebuilt_ty = MakeUnique(RebuildType(GetId(ele_ty), *ele_ty), + array_ty->length_info()); break; } case Type::kRuntimeArray: { const RuntimeArray* array_ty = type.AsRuntimeArray(); const Type* ele_ty = array_ty->element_type(); - rebuilt_ty = MakeUnique(RebuildType(*ele_ty)); + rebuilt_ty = + MakeUnique(RebuildType(GetId(ele_ty), *ele_ty)); break; } case Type::kStruct: { @@ -594,7 +608,7 @@ Type* TypeManager::RebuildType(const Type& type) { std::vector subtypes; subtypes.reserve(struct_ty->element_types().size()); for (const auto* ele_ty : struct_ty->element_types()) { - subtypes.push_back(RebuildType(*ele_ty)); + subtypes.push_back(RebuildType(GetId(ele_ty), *ele_ty)); } rebuilt_ty = MakeUnique(subtypes); Struct* rebuilt_struct = rebuilt_ty->AsStruct(); @@ -611,7 +625,7 @@ Type* TypeManager::RebuildType(const Type& type) { case Type::kPointer: { const Pointer* pointer_ty = type.AsPointer(); const Type* ele_ty = pointer_ty->pointee_type(); - rebuilt_ty = MakeUnique(RebuildType(*ele_ty), + rebuilt_ty = MakeUnique(RebuildType(GetId(ele_ty), *ele_ty), pointer_ty->storage_class()); break; } @@ -621,9 +635,10 @@ Type* TypeManager::RebuildType(const Type& type) { std::vector param_types; param_types.reserve(function_ty->param_types().size()); for (const auto* param_ty : function_ty->param_types()) { - param_types.push_back(RebuildType(*param_ty)); + param_types.push_back(RebuildType(GetId(param_ty), *param_ty)); } - rebuilt_ty = MakeUnique(RebuildType(*ret_ty), param_types); + rebuilt_ty = MakeUnique(RebuildType(GetId(ret_ty), *ret_ty), + param_types); break; } case Type::kForwardPointer: { @@ -633,7 +648,7 @@ Type* TypeManager::RebuildType(const Type& type) { const Pointer* target_ptr = forward_ptr_ty->target_pointer(); if (target_ptr) { rebuilt_ty->AsForwardPointer()->SetTargetPointer( - RebuildType(*target_ptr)->AsPointer()); + RebuildType(GetId(target_ptr), *target_ptr)->AsPointer()); } break; } @@ -641,16 +656,17 @@ Type* TypeManager::RebuildType(const Type& type) { const CooperativeMatrixNV* cm_type = type.AsCooperativeMatrixNV(); const Type* component_type = cm_type->component_type(); rebuilt_ty = MakeUnique( - RebuildType(*component_type), cm_type->scope_id(), cm_type->rows_id(), - cm_type->columns_id()); + RebuildType(GetId(component_type), *component_type), + cm_type->scope_id(), cm_type->rows_id(), cm_type->columns_id()); break; } case Type::kCooperativeMatrixKHR: { const CooperativeMatrixKHR* cm_type = type.AsCooperativeMatrixKHR(); const Type* component_type = cm_type->component_type(); rebuilt_ty = MakeUnique( - RebuildType(*component_type), cm_type->scope_id(), cm_type->rows_id(), - cm_type->columns_id(), cm_type->use_id()); + RebuildType(GetId(component_type), *component_type), + cm_type->scope_id(), cm_type->rows_id(), cm_type->columns_id(), + cm_type->use_id()); break; } default: @@ -669,7 +685,7 @@ Type* TypeManager::RebuildType(const Type& type) { void TypeManager::RegisterType(uint32_t id, const Type& type) { // Rebuild |type| so it and all its constituent types are owned by the type // pool. - Type* rebuilt = RebuildType(type); + Type* rebuilt = RebuildType(id, type); assert(rebuilt->IsSame(&type)); id_to_type_[id] = rebuilt; if (GetId(rebuilt) == 0) { diff --git a/spirv-tools/source/opt/type_manager.h b/spirv-tools/source/opt/type_manager.h index a70c371..948b691 100644 --- a/spirv-tools/source/opt/type_manager.h +++ b/spirv-tools/source/opt/type_manager.h @@ -260,7 +260,9 @@ class TypeManager { // Returns an equivalent pointer to |type| built in terms of pointers owned by // |type_pool_|. For example, if |type| is a vec3 of bool, it will be rebuilt // replacing the bool subtype with one owned by |type_pool_|. - Type* RebuildType(const Type& type); + // + // The re-built type will have ID |type_id|. + Type* RebuildType(uint32_t type_id, const Type& type); // Completes the incomplete type |type|, by replaces all references to // ForwardPointer by the defining Pointer. diff --git a/spirv-tools/source/table.h b/spirv-tools/source/table.h index 8097f13..4f1dc1f 100644 --- a/spirv-tools/source/table.h +++ b/spirv-tools/source/table.h @@ -74,7 +74,7 @@ typedef struct spv_ext_inst_desc_t { const uint32_t ext_inst; const uint32_t numCapabilities; const spv::Capability* capabilities; - const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger? + const spv_operand_type_t operandTypes[40]; // vksp needs at least 40 } spv_ext_inst_desc_t; typedef struct spv_ext_inst_group_t { diff --git a/spirv-tools/source/val/validate.cpp b/spirv-tools/source/val/validate.cpp index ccf26fb..3236807 100644 --- a/spirv-tools/source/val/validate.cpp +++ b/spirv-tools/source/val/validate.cpp @@ -144,6 +144,9 @@ spv_result_t ValidateEntryPoints(ValidationState_t& _) { if (auto error = ValidateFloatControls2(_)) { return error; } + if (auto error = ValidateDuplicateExecutionModes(_)) { + return error; + } return SPV_SUCCESS; } diff --git a/spirv-tools/source/val/validate.h b/spirv-tools/source/val/validate.h index 52267c8..78093ce 100644 --- a/spirv-tools/source/val/validate.h +++ b/spirv-tools/source/val/validate.h @@ -94,6 +94,13 @@ spv_result_t ValidateInterfaces(ValidationState_t& _); /// @return SPV_SUCCESS if no errors are found. spv_result_t ValidateFloatControls2(ValidationState_t& _); +/// @brief Validates duplicated execution modes for each entry point. +/// +/// @param[in] _ the validation state of the module +/// +/// @return SPV_SUCCESS if no errors are found. +spv_result_t ValidateDuplicateExecutionModes(ValidationState_t& _); + /// @brief Validates memory instructions /// /// @param[in] _ the validation state of the module diff --git a/spirv-tools/source/val/validate_annotation.cpp b/spirv-tools/source/val/validate_annotation.cpp index 106004d..dac3585 100644 --- a/spirv-tools/source/val/validate_annotation.cpp +++ b/spirv-tools/source/val/validate_annotation.cpp @@ -161,7 +161,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec, case spv::Decoration::RestrictPointer: case spv::Decoration::AliasedPointer: if (target->opcode() != spv::Op::OpVariable && - target->opcode() != spv::Op::OpFunctionParameter) { + target->opcode() != spv::Op::OpFunctionParameter && + target->opcode() != spv::Op::OpRawAccessChainNV) { return fail(0) << "must be a memory object declaration"; } if (_.GetIdOpcode(target->type_id()) != spv::Op::OpTypePointer) { diff --git a/spirv-tools/source/val/validate_decorations.cpp b/spirv-tools/source/val/validate_decorations.cpp index caa4a6f..0a7df65 100644 --- a/spirv-tools/source/val/validate_decorations.cpp +++ b/spirv-tools/source/val/validate_decorations.cpp @@ -1325,21 +1325,14 @@ spv_result_t CheckDecorationsOfBuffers(ValidationState_t& vstate) { // Returns true if |decoration| cannot be applied to the same id more than once. bool AtMostOncePerId(spv::Decoration decoration) { - return decoration == spv::Decoration::ArrayStride; + return decoration != spv::Decoration::UserSemantic && + decoration != spv::Decoration::FuncParamAttr; } // Returns true if |decoration| cannot be applied to the same member more than // once. bool AtMostOncePerMember(spv::Decoration decoration) { - switch (decoration) { - case spv::Decoration::Offset: - case spv::Decoration::MatrixStride: - case spv::Decoration::RowMajor: - case spv::Decoration::ColMajor: - return true; - default: - return false; - } + return decoration != spv::Decoration::UserSemantic; } spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { @@ -1556,7 +1549,8 @@ spv_result_t CheckNonWritableDecoration(ValidationState_t& vstate, const auto opcode = inst.opcode(); const auto type_id = inst.type_id(); if (opcode != spv::Op::OpVariable && - opcode != spv::Op::OpFunctionParameter) { + opcode != spv::Op::OpFunctionParameter && + opcode != spv::Op::OpRawAccessChainNV) { return vstate.diag(SPV_ERROR_INVALID_ID, &inst) << "Target of NonWritable decoration must be a memory object " "declaration (a variable or a function parameter)"; @@ -1569,10 +1563,11 @@ spv_result_t CheckNonWritableDecoration(ValidationState_t& vstate, vstate.features().nonwritable_var_in_function_or_private) { // New permitted feature in SPIR-V 1.4. } else if ( - // It may point to a UBO, SSBO, or storage image. + // It may point to a UBO, SSBO, storage image, or raw access chain. vstate.IsPointerToUniformBlock(type_id) || vstate.IsPointerToStorageBuffer(type_id) || - vstate.IsPointerToStorageImage(type_id)) { + vstate.IsPointerToStorageImage(type_id) || + opcode == spv::Op::OpRawAccessChainNV) { } else { return vstate.diag(SPV_ERROR_INVALID_ID, &inst) << "Target of NonWritable decoration is invalid: must point to a " diff --git a/spirv-tools/source/val/validate_image.cpp b/spirv-tools/source/val/validate_image.cpp index f62c3a2..a1a76ea 100644 --- a/spirv-tools/source/val/validate_image.cpp +++ b/spirv-tools/source/val/validate_image.cpp @@ -914,7 +914,15 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) { if (info.dim == spv::Dim::SubpassData && info.arrayed != 0) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << _.VkErrorID(6214) << "Dim SubpassData requires Arrayed to be 0"; + << _.VkErrorID(6214) + << "Dim SubpassData requires Arrayed to be 0 in the Vulkan " + "environment"; + } + + if (info.dim == spv::Dim::Rect) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << _.VkErrorID(9638) + << "Dim must not be Rect in the Vulkan environment"; } } @@ -2161,7 +2169,8 @@ spv_result_t ValidateImageProcessingQCOMDecoration(ValidationState_t& _, int id, spv::Decoration decor) { const Instruction* si_inst = nullptr; const Instruction* ld_inst = _.FindDef(id); - if (ld_inst->opcode() == spv::Op::OpSampledImage) { + bool is_intf_obj = (ld_inst->opcode() == spv::Op::OpSampledImage); + if (is_intf_obj == true) { si_inst = ld_inst; int t_idx = si_inst->GetOperandAs(2); // texture ld_inst = _.FindDef(t_idx); @@ -2178,6 +2187,56 @@ spv_result_t ValidateImageProcessingQCOMDecoration(ValidationState_t& _, int id, return SPV_SUCCESS; } +spv_result_t ValidateImageProcessing2QCOMWindowDecoration(ValidationState_t& _, + int id) { + const Instruction* ld_inst = _.FindDef(id); + bool is_intf_obj = (ld_inst->opcode() != spv::Op::OpSampledImage); + if (is_intf_obj == true) { + if (ld_inst->opcode() != spv::Op::OpLoad) { + return _.diag(SPV_ERROR_INVALID_DATA, ld_inst) << "Expect to see OpLoad"; + } + int texture_id = ld_inst->GetOperandAs(2); // variable to load + spv::Decoration decor = spv::Decoration::BlockMatchTextureQCOM; + if (!_.HasDecoration(texture_id, decor)) { + return _.diag(SPV_ERROR_INVALID_DATA, ld_inst) + << "Missing decoration " << _.SpvDecorationString(decor); + } + decor = spv::Decoration::BlockMatchSamplerQCOM; + if (!_.HasDecoration(texture_id, decor)) { + return _.diag(SPV_ERROR_INVALID_DATA, ld_inst) + << "Missing decoration " << _.SpvDecorationString(decor); + } + } else { + const Instruction* si_inst = ld_inst; + int t_idx = si_inst->GetOperandAs(2); // texture + const Instruction* t_ld_inst = _.FindDef(t_idx); + if (t_ld_inst->opcode() != spv::Op::OpLoad) { + return _.diag(SPV_ERROR_INVALID_DATA, t_ld_inst) + << "Expect to see OpLoad"; + } + int texture_id = t_ld_inst->GetOperandAs(2); // variable to load + spv::Decoration decor = spv::Decoration::BlockMatchTextureQCOM; + if (!_.HasDecoration(texture_id, decor)) { + return _.diag(SPV_ERROR_INVALID_DATA, ld_inst) + << "Missing decoration " << _.SpvDecorationString(decor); + } + int s_idx = si_inst->GetOperandAs(3); // sampler + const Instruction* s_ld_inst = _.FindDef(s_idx); + if (s_ld_inst->opcode() != spv::Op::OpLoad) { + return _.diag(SPV_ERROR_INVALID_DATA, s_ld_inst) + << "Expect to see OpLoad"; + } + int sampler_id = s_ld_inst->GetOperandAs(2); // variable to load + decor = spv::Decoration::BlockMatchSamplerQCOM; + if (!_.HasDecoration(sampler_id, decor)) { + return _.diag(SPV_ERROR_INVALID_DATA, ld_inst) + << "Missing decoration " << _.SpvDecorationString(decor); + } + } + + return SPV_SUCCESS; +} + spv_result_t ValidateImageProcessingQCOM(ValidationState_t& _, const Instruction* inst) { spv_result_t res = SPV_SUCCESS; @@ -2203,18 +2262,10 @@ spv_result_t ValidateImageProcessingQCOM(ValidationState_t& _, case spv::Op::OpImageBlockMatchWindowSSDQCOM: case spv::Op::OpImageBlockMatchWindowSADQCOM: { int tgt_idx = inst->GetOperandAs(2); // target - res = ValidateImageProcessingQCOMDecoration( - _, tgt_idx, spv::Decoration::BlockMatchTextureQCOM); - if (res != SPV_SUCCESS) break; - res = ValidateImageProcessingQCOMDecoration( - _, tgt_idx, spv::Decoration::BlockMatchSamplerQCOM); + res = ValidateImageProcessing2QCOMWindowDecoration(_, tgt_idx); if (res != SPV_SUCCESS) break; int ref_idx = inst->GetOperandAs(4); // reference - res = ValidateImageProcessingQCOMDecoration( - _, ref_idx, spv::Decoration::BlockMatchTextureQCOM); - if (res != SPV_SUCCESS) break; - res = ValidateImageProcessingQCOMDecoration( - _, ref_idx, spv::Decoration::BlockMatchSamplerQCOM); + res = ValidateImageProcessing2QCOMWindowDecoration(_, ref_idx); break; } case spv::Op::OpImageBlockMatchGatherSSDQCOM: diff --git a/spirv-tools/source/val/validate_interfaces.cpp b/spirv-tools/source/val/validate_interfaces.cpp index 54ebfd7..ace548a 100644 --- a/spirv-tools/source/val/validate_interfaces.cpp +++ b/spirv-tools/source/val/validate_interfaces.cpp @@ -254,37 +254,24 @@ spv_result_t GetLocationsForVariable( // equal. Also track Patch and PerTaskNV decorations. bool has_location = false; uint32_t location = 0; - bool has_component = false; uint32_t component = 0; bool has_index = false; uint32_t index = 0; bool has_patch = false; bool has_per_task_nv = false; bool has_per_vertex_khr = false; + // Duplicate Location, Component, Index are checked elsewhere. for (auto& dec : _.id_decorations(variable->id())) { if (dec.dec_type() == spv::Decoration::Location) { - if (has_location && dec.params()[0] != location) { - return _.diag(SPV_ERROR_INVALID_DATA, variable) - << "Variable has conflicting location decorations"; - } has_location = true; location = dec.params()[0]; } else if (dec.dec_type() == spv::Decoration::Component) { - if (has_component && dec.params()[0] != component) { - return _.diag(SPV_ERROR_INVALID_DATA, variable) - << "Variable has conflicting component decorations"; - } - has_component = true; component = dec.params()[0]; } else if (dec.dec_type() == spv::Decoration::Index) { if (!is_output || !is_fragment) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << "Index can only be applied to Fragment output variables"; } - if (has_index && dec.params()[0] != index) { - return _.diag(SPV_ERROR_INVALID_DATA, variable) - << "Variable has conflicting index decorations"; - } has_index = true; index = dec.params()[0]; } else if (dec.dec_type() == spv::Decoration::BuiltIn) { diff --git a/spirv-tools/source/val/validate_memory.cpp b/spirv-tools/source/val/validate_memory.cpp index c9ecf51..2d6715f 100644 --- a/spirv-tools/source/val/validate_memory.cpp +++ b/spirv-tools/source/val/validate_memory.cpp @@ -1427,6 +1427,126 @@ spv_result_t ValidateAccessChain(ValidationState_t& _, return SPV_SUCCESS; } +spv_result_t ValidateRawAccessChain(ValidationState_t& _, + const Instruction* inst) { + std::string instr_name = "Op" + std::string(spvOpcodeString(inst->opcode())); + + // The result type must be OpTypePointer. + const auto result_type = _.FindDef(inst->type_id()); + if (spv::Op::OpTypePointer != result_type->opcode()) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The Result Type of " << instr_name << " " + << _.getIdName(inst->id()) << " must be OpTypePointer. Found Op" + << spvOpcodeString(result_type->opcode()) << '.'; + } + + // The pointed storage class must be valid. + const auto storage_class = result_type->GetOperandAs(1); + if (storage_class != spv::StorageClass::StorageBuffer && + storage_class != spv::StorageClass::PhysicalStorageBuffer && + storage_class != spv::StorageClass::Uniform) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The Result Type of " << instr_name << " " + << _.getIdName(inst->id()) + << " must point to a storage class of " + "StorageBuffer, PhysicalStorageBuffer, or Uniform."; + } + + // The pointed type must not be one in the list below. + const auto result_type_pointee = + _.FindDef(result_type->GetOperandAs(2)); + if (result_type_pointee->opcode() == spv::Op::OpTypeArray || + result_type_pointee->opcode() == spv::Op::OpTypeMatrix || + result_type_pointee->opcode() == spv::Op::OpTypeStruct) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The Result Type of " << instr_name << " " + << _.getIdName(inst->id()) + << " must not point to " + "OpTypeArray, OpTypeMatrix, or OpTypeStruct."; + } + + // Validate Stride is a OpConstant. + const auto stride = _.FindDef(inst->GetOperandAs(3)); + if (stride->opcode() != spv::Op::OpConstant) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The Stride of " << instr_name << " " + << _.getIdName(inst->id()) << " must be OpConstant. Found Op" + << spvOpcodeString(stride->opcode()) << '.'; + } + // Stride type must be OpTypeInt + const auto stride_type = _.FindDef(stride->type_id()); + if (stride_type->opcode() != spv::Op::OpTypeInt) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The type of Stride of " << instr_name << " " + << _.getIdName(inst->id()) << " must be OpTypeInt. Found Op" + << spvOpcodeString(stride_type->opcode()) << '.'; + } + + // Index and Offset type must be OpTypeInt with a width of 32 + const auto ValidateType = [&](const char* name, + int operandIndex) -> spv_result_t { + const auto value = _.FindDef(inst->GetOperandAs(operandIndex)); + const auto value_type = _.FindDef(value->type_id()); + if (value_type->opcode() != spv::Op::OpTypeInt) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The type of " << name << " of " << instr_name << " " + << _.getIdName(inst->id()) << " must be OpTypeInt. Found Op" + << spvOpcodeString(value_type->opcode()) << '.'; + } + const auto width = value_type->GetOperandAs(1); + if (width != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The integer width of " << name << " of " << instr_name + << " " << _.getIdName(inst->id()) << " must be 32. Found " + << width << '.'; + } + return SPV_SUCCESS; + }; + spv_result_t result; + result = ValidateType("Index", 4); + if (result != SPV_SUCCESS) { + return result; + } + result = ValidateType("Offset", 5); + if (result != SPV_SUCCESS) { + return result; + } + + uint32_t access_operands = 0; + if (inst->operands().size() >= 7) { + access_operands = inst->GetOperandAs(6); + } + if (access_operands & + uint32_t(spv::RawAccessChainOperandsMask::RobustnessPerElementNV)) { + uint64_t stride_value = 0; + if (_.EvalConstantValUint64(stride->id(), &stride_value) && + stride_value == 0) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Stride must not be zero when per-element robustness is used."; + } + } + if (access_operands & + uint32_t(spv::RawAccessChainOperandsMask::RobustnessPerComponentNV) || + access_operands & + uint32_t(spv::RawAccessChainOperandsMask::RobustnessPerElementNV)) { + if (storage_class == spv::StorageClass::PhysicalStorageBuffer) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Storage class cannot be PhysicalStorageBuffer when " + "raw access chain robustness is used."; + } + } + if (access_operands & + uint32_t(spv::RawAccessChainOperandsMask::RobustnessPerComponentNV) && + access_operands & + uint32_t(spv::RawAccessChainOperandsMask::RobustnessPerElementNV)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Per-component robustness and per-element robustness are " + "mutually exclusive."; + } + + return SPV_SUCCESS; +} + spv_result_t ValidatePtrAccessChain(ValidationState_t& _, const Instruction* inst) { if (_.addressing_model() == spv::AddressingModel::Logical) { @@ -1866,6 +1986,9 @@ spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) { case spv::Op::OpInBoundsPtrAccessChain: if (auto error = ValidateAccessChain(_, inst)) return error; break; + case spv::Op::OpRawAccessChainNV: + if (auto error = ValidateRawAccessChain(_, inst)) return error; + break; case spv::Op::OpArrayLength: if (auto error = ValidateArrayLength(_, inst)) return error; break; diff --git a/spirv-tools/source/val/validate_mode_setting.cpp b/spirv-tools/source/val/validate_mode_setting.cpp index 199d8ed..8502fda 100644 --- a/spirv-tools/source/val/validate_mode_setting.cpp +++ b/spirv-tools/source/val/validate_mode_setting.cpp @@ -724,6 +724,25 @@ spv_result_t ValidateMemoryModel(ValidationState_t& _, return SPV_SUCCESS; } +bool PerEntryExecutionMode(spv::ExecutionMode mode) { + switch (mode) { + // These execution modes can be specified multiple times per entry point. + case spv::ExecutionMode::DenormPreserve: + case spv::ExecutionMode::DenormFlushToZero: + case spv::ExecutionMode::SignedZeroInfNanPreserve: + case spv::ExecutionMode::RoundingModeRTE: + case spv::ExecutionMode::RoundingModeRTZ: + case spv::ExecutionMode::FPFastMathDefault: + case spv::ExecutionMode::RoundingModeRTPINTEL: + case spv::ExecutionMode::RoundingModeRTNINTEL: + case spv::ExecutionMode::FloatingPointModeALTINTEL: + case spv::ExecutionMode::FloatingPointModeIEEEINTEL: + return false; + default: + return true; + } +} + } // namespace spv_result_t ValidateFloatControls2(ValidationState_t& _) { @@ -808,5 +827,52 @@ spv_result_t ModeSettingPass(ValidationState_t& _, const Instruction* inst) { return SPV_SUCCESS; } +spv_result_t ValidateDuplicateExecutionModes(ValidationState_t& _) { + using PerEntryKey = std::tuple; + using PerOperandKey = std::tuple; + std::set seen_per_entry; + std::set seen_per_operand; + + const auto lookupMode = [&_](spv::ExecutionMode mode) -> std::string { + spv_operand_desc desc = nullptr; + if (_.grammar().lookupOperand(SPV_OPERAND_TYPE_EXECUTION_MODE, + static_cast(mode), + &desc) == SPV_SUCCESS) { + return std::string(desc->name); + } + return "Unknown"; + }; + + for (const auto& inst : _.ordered_instructions()) { + if (inst.opcode() != spv::Op::OpExecutionMode && + inst.opcode() != spv::Op::OpExecutionModeId) { + continue; + } + + const auto entry = inst.GetOperandAs(0); + const auto mode = inst.GetOperandAs(1); + if (PerEntryExecutionMode(mode)) { + if (!seen_per_entry.insert(std::make_tuple(mode, entry)).second) { + return _.diag(SPV_ERROR_INVALID_ID, &inst) + << lookupMode(mode) + << " execution mode must not be specified multiple times per " + "entry point"; + } + } else { + // Execution modes allowed multiple times all take a single operand. + const auto operand = inst.GetOperandAs(2); + if (!seen_per_operand.insert(std::make_tuple(mode, entry, operand)) + .second) { + return _.diag(SPV_ERROR_INVALID_ID, &inst) + << lookupMode(mode) + << " execution mode must not be specified multiple times for " + "the same entry point and operands"; + } + } + } + + return SPV_SUCCESS; +} + } // namespace val } // namespace spvtools diff --git a/spirv-tools/source/val/validation_state.cpp b/spirv-tools/source/val/validation_state.cpp index 8968499..87322d2 100644 --- a/spirv-tools/source/val/validation_state.cpp +++ b/spirv-tools/source/val/validation_state.cpp @@ -2351,6 +2351,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-08722); case 8973: return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973); + case 9638: + return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-09638); default: return ""; // unknown id } diff --git a/spirv-tools/spirv-tools/build-version.inc b/spirv-tools/spirv-tools/build-version.inc index a72ccef..c56d126 100644 --- a/spirv-tools/spirv-tools/build-version.inc +++ b/spirv-tools/spirv-tools/build-version.inc @@ -1 +1 @@ -"v2024.1", "SPIRV-Tools v2024.1 v2024.1-0-g04896c4" +"v2024.2", "SPIRV-Tools v2024.2 v2024.2.rc1-0-gdd4b663" diff --git a/spirv-tools/spirv-tools/generators.inc b/spirv-tools/spirv-tools/generators.inc index 34f120f..e67e575 100644 --- a/spirv-tools/spirv-tools/generators.inc +++ b/spirv-tools/spirv-tools/generators.inc @@ -39,4 +39,6 @@ {38, "Meta", "SparkSL", "Meta SparkSL"}, {39, "SirLynix", "Nazara ShaderLang Compiler", "SirLynix Nazara ShaderLang Compiler"}, {40, "NVIDIA", "Slang Compiler", "NVIDIA Slang Compiler"}, -{41, "Zig Software Foundation", "Zig Compiler", "Zig Software Foundation Zig Compiler"}, \ No newline at end of file +{41, "Zig Software Foundation", "Zig Compiler", "Zig Software Foundation Zig Compiler"}, +{42, "Rendong Liang", "spq", "Rendong Liang spq"}, +{43, "LLVM", "LLVM SPIR-V Backend", "LLVM LLVM SPIR-V Backend"}, \ No newline at end of file diff --git a/spirv-tools/spirv-tools/libspirv.h b/spirv-tools/spirv-tools/libspirv.h index a7b57b8..83b1a8e 100644 --- a/spirv-tools/spirv-tools/libspirv.h +++ b/spirv-tools/spirv-tools/libspirv.h @@ -33,15 +33,19 @@ extern "C" { #else #define SPIRV_TOOLS_EXPORT __declspec(dllimport) #endif +#define SPIRV_TOOLS_LOCAL #else #if defined(SPIRV_TOOLS_IMPLEMENTATION) #define SPIRV_TOOLS_EXPORT __attribute__((visibility("default"))) +#define SPIRV_TOOLS_LOCAL __attribute__((visibility("hidden"))) #else #define SPIRV_TOOLS_EXPORT +#define SPIRV_TOOLS_LOCAL #endif #endif #else #define SPIRV_TOOLS_EXPORT +#define SPIRV_TOOLS_LOCAL #endif // Helpers @@ -333,6 +337,7 @@ typedef enum spv_ext_inst_type_t { SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100, SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION, SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100, + SPV_EXT_INST_TYPE_NONSEMANTIC_VKSPREFLECTION, // Multiple distinct extended instruction set types could return this // value, if they are prefixed with NonSemantic. and are otherwise diff --git a/spirv-tools/spirv-tools/libspirv.hpp b/spirv-tools/spirv-tools/libspirv.hpp index ee6c846..59ff82b 100644 --- a/spirv-tools/spirv-tools/libspirv.hpp +++ b/spirv-tools/spirv-tools/libspirv.hpp @@ -37,7 +37,7 @@ using InstructionParser = std::function; // C++ RAII wrapper around the C context object spv_context. -class Context { +class SPIRV_TOOLS_EXPORT Context { public: // Constructs a context targeting the given environment |env|. // @@ -73,7 +73,7 @@ class Context { }; // A RAII wrapper around a validator options object. -class ValidatorOptions { +class SPIRV_TOOLS_EXPORT ValidatorOptions { public: ValidatorOptions() : options_(spvValidatorOptionsCreate()) {} ~ValidatorOptions() { spvValidatorOptionsDestroy(options_); } @@ -163,7 +163,7 @@ class ValidatorOptions { }; // A C++ wrapper around an optimization options object. -class OptimizerOptions { +class SPIRV_TOOLS_EXPORT OptimizerOptions { public: OptimizerOptions() : options_(spvOptimizerOptionsCreate()) {} ~OptimizerOptions() { spvOptimizerOptionsDestroy(options_); } @@ -205,7 +205,7 @@ class OptimizerOptions { }; // A C++ wrapper around a reducer options object. -class ReducerOptions { +class SPIRV_TOOLS_EXPORT ReducerOptions { public: ReducerOptions() : options_(spvReducerOptionsCreate()) {} ~ReducerOptions() { spvReducerOptionsDestroy(options_); } @@ -236,7 +236,7 @@ class ReducerOptions { }; // A C++ wrapper around a fuzzer options object. -class FuzzerOptions { +class SPIRV_TOOLS_EXPORT FuzzerOptions { public: FuzzerOptions() : options_(spvFuzzerOptionsCreate()) {} ~FuzzerOptions() { spvFuzzerOptionsDestroy(options_); } @@ -283,7 +283,7 @@ class FuzzerOptions { // provides methods for assembling, disassembling, and validating. // // Instances of this class provide basic thread-safety guarantee. -class SpirvTools { +class SPIRV_TOOLS_EXPORT SpirvTools { public: enum { // Default assembling option used by assemble(): @@ -388,7 +388,8 @@ class SpirvTools { bool IsValid() const; private: - struct Impl; // Opaque struct for holding the data fields used by this class. + struct SPIRV_TOOLS_LOCAL + Impl; // Opaque struct for holding the data fields used by this class. std::unique_ptr impl_; // Unique pointer to implementation data. }; diff --git a/spirv-tools/spirv-tools/linker.hpp b/spirv-tools/spirv-tools/linker.hpp index 5b60cb9..6ba6e96 100644 --- a/spirv-tools/spirv-tools/linker.hpp +++ b/spirv-tools/spirv-tools/linker.hpp @@ -24,7 +24,7 @@ namespace spvtools { -class LinkerOptions { +class SPIRV_TOOLS_EXPORT LinkerOptions { public: // Returns whether a library or an executable should be produced by the // linking phase. @@ -84,14 +84,15 @@ class LinkerOptions { // * Some entry points were defined multiple times; // * Some imported symbols did not have an exported counterpart; // * Possibly other reasons. -spv_result_t Link(const Context& context, - const std::vector>& binaries, - std::vector* linked_binary, - const LinkerOptions& options = LinkerOptions()); -spv_result_t Link(const Context& context, const uint32_t* const* binaries, - const size_t* binary_sizes, size_t num_binaries, - std::vector* linked_binary, - const LinkerOptions& options = LinkerOptions()); +SPIRV_TOOLS_EXPORT spv_result_t +Link(const Context& context, const std::vector>& binaries, + std::vector* linked_binary, + const LinkerOptions& options = LinkerOptions()); +SPIRV_TOOLS_EXPORT spv_result_t +Link(const Context& context, const uint32_t* const* binaries, + const size_t* binary_sizes, size_t num_binaries, + std::vector* linked_binary, + const LinkerOptions& options = LinkerOptions()); } // namespace spvtools diff --git a/spirv-tools/spirv-tools/linter.hpp b/spirv-tools/spirv-tools/linter.hpp index 52ed5a4..ccbcf0c 100644 --- a/spirv-tools/spirv-tools/linter.hpp +++ b/spirv-tools/spirv-tools/linter.hpp @@ -24,7 +24,7 @@ namespace spvtools { // provides a method for linting. // // Instances of this class provides basic thread-safety guarantee. -class Linter { +class SPIRV_TOOLS_EXPORT Linter { public: explicit Linter(spv_target_env env); @@ -40,7 +40,7 @@ class Linter { bool Run(const uint32_t* binary, size_t binary_size); private: - struct Impl; + struct SPIRV_TOOLS_LOCAL Impl; std::unique_ptr impl_; }; } // namespace spvtools diff --git a/spirv-tools/spirv-tools/nonsemantic.vkspreflection.insts.inc b/spirv-tools/spirv-tools/nonsemantic.vkspreflection.insts.inc new file mode 100644 index 0000000..8a78518 --- /dev/null +++ b/spirv-tools/spirv-tools/nonsemantic.vkspreflection.insts.inc @@ -0,0 +1,12 @@ + + +static const spv_ext_inst_desc_t nonsemantic_vkspreflection_entries[] = { + {"Configuration", 1, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"StartCounter", 2, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_NONE}}, + {"StopCounter", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}, + {"PushConstants", 4, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"SpecializationMapEntry", 5, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DescriptorSetBuffer", 6, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DescriptorSetImage", 7, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}}, + {"DescriptorSetSampler", 8, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_FLOAT, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_FLOAT, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_FLOAT, SPV_OPERAND_TYPE_LITERAL_FLOAT, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}} +}; \ No newline at end of file diff --git a/spirv-tools/spirv-tools/optimizer.hpp b/spirv-tools/spirv-tools/optimizer.hpp index 926e438..a3119d9 100644 --- a/spirv-tools/spirv-tools/optimizer.hpp +++ b/spirv-tools/spirv-tools/optimizer.hpp @@ -37,14 +37,14 @@ struct DescriptorSetAndBinding; // provides methods for registering optimization passes and optimizing. // // Instances of this class provides basic thread-safety guarantee. -class Optimizer { +class SPIRV_TOOLS_EXPORT Optimizer { public: // The token for an optimization pass. It is returned via one of the // Create*Pass() standalone functions at the end of this header file and // consumed by the RegisterPass() method. Tokens are one-time objects that // only support move; copying is not allowed. struct PassToken { - struct Impl; // Opaque struct for holding internal data. + struct SPIRV_TOOLS_LOCAL Impl; // Opaque struct for holding internal data. PassToken(std::unique_ptr); @@ -239,7 +239,7 @@ class Optimizer { Optimizer& SetValidateAfterAll(bool validate); private: - struct Impl; // Opaque struct for holding internal data. + struct SPIRV_TOOLS_LOCAL Impl; // Opaque struct for holding internal data. std::unique_ptr impl_; // Unique pointer to internal data. };