From 145c188277260e8c95cc44f26d25329bb690ae31 Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" Date: Thu, 30 Apr 2026 23:12:41 +0200 Subject: [PATCH 1/2] Add validation support for SPV_INTEL_predicated_io Add spirv-val validation for OpPredicatedLoadINTEL and OpPredicatedStoreINTEL instructions introduced by the SPV_INTEL_predicated_io extension: - Result/Object type must be scalar or vector of numerical type - Predicate must be a Boolean scalar - Default Value type must match Result Type (for load) - Pointer type must match Result/Object type (for typed pointers) - Volatile memory operand is not allowed Co-Authored-By: Claude (commercial) --- source/val/validate_logical_pointers.cpp | 3 + source/val/validate_memory.cpp | 166 ++++++++- test/val/CMakeLists.txt | 1 + ...extension_spv_intel_predicated_io_test.cpp | 342 ++++++++++++++++++ 4 files changed, 508 insertions(+), 4 deletions(-) create mode 100644 test/val/val_extension_spv_intel_predicated_io_test.cpp diff --git a/source/val/validate_logical_pointers.cpp b/source/val/validate_logical_pointers.cpp index b4843120d9..6077a9e0e8 100644 --- a/source/val/validate_logical_pointers.cpp +++ b/source/val/validate_logical_pointers.cpp @@ -305,6 +305,9 @@ spv_result_t ValidateLogicalPointerOperands(ValidationState_t& _, case spv::Op::OpNodePayloadArrayLengthAMDX: case spv::Op::OpIsNodePayloadValidAMDX: case spv::Op::OpFinishWritingNodePayloadAMDX: + // SPV_INTEL_predicated_io + case spv::Op::OpPredicatedLoadINTEL: + case spv::Op::OpPredicatedStoreINTEL: // SPV_ARM_graph case spv::Op::OpGraphEntryPointARM: return SPV_SUCCESS; diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp index 47d1a3c029..e1f49d83fb 100644 --- a/source/val/validate_memory.cpp +++ b/source/val/validate_memory.cpp @@ -207,7 +207,8 @@ std::pair GetPointerTypes(ValidationState_t& _, case spv::Op::OpCooperativeMatrixLoadTensorNV: case spv::Op::OpCooperativeMatrixLoadKHR: case spv::Op::OpCooperativeVectorLoadNV: - case spv::Op::OpLoad: { + case spv::Op::OpLoad: + case spv::Op::OpPredicatedLoadINTEL: { auto load_pointer = _.FindDef(inst->GetOperandAs(2)); dst_pointer_type = _.FindDef(load_pointer->type_id()); break; @@ -216,7 +217,8 @@ std::pair GetPointerTypes(ValidationState_t& _, case spv::Op::OpCooperativeMatrixStoreTensorNV: case spv::Op::OpCooperativeMatrixStoreKHR: case spv::Op::OpCooperativeVectorStoreNV: - case spv::Op::OpStore: { + case spv::Op::OpStore: + case spv::Op::OpPredicatedStoreINTEL: { auto store_pointer = _.FindDef(inst->GetOperandAs(0)); dst_pointer_type = _.FindDef(store_pointer->type_id()); break; @@ -315,7 +317,8 @@ spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst, inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV || inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV || inst->opcode() == spv::Op::OpCooperativeMatrixLoadKHR || - inst->opcode() == spv::Op::OpCooperativeVectorLoadNV) { + inst->opcode() == spv::Op::OpCooperativeVectorLoadNV || + inst->opcode() == spv::Op::OpPredicatedLoadINTEL) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "MakePointerAvailableKHR cannot be used with OpLoad."; } @@ -337,7 +340,8 @@ spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst, inst->opcode() == spv::Op::OpCooperativeMatrixStoreNV || inst->opcode() == spv::Op::OpCooperativeMatrixStoreKHR || inst->opcode() == spv::Op::OpCooperativeMatrixStoreTensorNV || - inst->opcode() == spv::Op::OpCooperativeVectorStoreNV) { + inst->opcode() == spv::Op::OpCooperativeVectorStoreNV || + inst->opcode() == spv::Op::OpPredicatedStoreINTEL) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "MakePointerVisibleKHR cannot be used with OpStore."; } @@ -3475,6 +3479,156 @@ spv_result_t ValidatePtrComparison(ValidationState_t& _, return SPV_SUCCESS; } +spv_result_t ValidatePredicatedLoadINTEL(ValidationState_t& _, + const Instruction* inst) { + const auto result_type_id = inst->type_id(); + if (!_.IsIntScalarOrVectorType(result_type_id) && + !_.IsFloatScalarOrVectorType(result_type_id)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL Result Type " + << _.getIdName(result_type_id) + << " must be a scalar or vector of numerical type."; + } + + const auto pointer_id = inst->GetOperandAs(2); + const auto pointer = _.FindDef(pointer_id); + if (!pointer || + ((_.addressing_model() == spv::AddressingModel::Logical) && + ((!_.features().variable_pointers && + !spvOpcodeReturnsLogicalPointer(pointer->opcode())) || + (_.features().variable_pointers && + !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL Pointer " << _.getIdName(pointer_id) + << " is not a logical pointer."; + } + + const auto pointer_type = _.FindDef(pointer->type_id()); + if (!pointer_type || + (pointer_type->opcode() != spv::Op::OpTypePointer && + pointer_type->opcode() != spv::Op::OpTypeUntypedPointerKHR)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL type for pointer " + << _.getIdName(pointer_id) << " is not a pointer type."; + } + + if (pointer_type->opcode() == spv::Op::OpTypePointer) { + const auto pointee_type = + _.FindDef(pointer_type->GetOperandAs(2)); + if (!pointee_type || result_type_id != pointee_type->id()) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL Result Type " + << _.getIdName(result_type_id) + << " does not match Pointer " << _.getIdName(pointer->id()) + << "s type."; + } + } + + const auto predicate_id = inst->GetOperandAs(3); + const auto predicate = _.FindDef(predicate_id); + if (!predicate || !_.IsBoolScalarType(predicate->type_id())) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL Predicate " + << _.getIdName(predicate_id) << " must be a Boolean scalar."; + } + + const auto default_value_id = inst->GetOperandAs(4); + const auto default_value = _.FindDef(default_value_id); + if (!default_value || default_value->type_id() != result_type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL Default Value " + << _.getIdName(default_value_id) + << " type does not match Result Type."; + } + + if (inst->operands().size() > 5) { + const auto mask = inst->GetOperandAs(5); + if (mask & uint32_t(spv::MemoryAccessMask::Volatile)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedLoadINTEL does not allow the Volatile memory " + "operand."; + } + } + + if (auto error = CheckMemoryAccess(_, inst, 5)) return error; + + return SPV_SUCCESS; +} + +spv_result_t ValidatePredicatedStoreINTEL(ValidationState_t& _, + const Instruction* inst) { + const auto pointer_id = inst->GetOperandAs(0); + const auto pointer = _.FindDef(pointer_id); + if (!pointer || + (_.addressing_model() == spv::AddressingModel::Logical && + ((!_.features().variable_pointers && + !spvOpcodeReturnsLogicalPointer(pointer->opcode())) || + (_.features().variable_pointers && + !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL Pointer " + << _.getIdName(pointer_id) << " is not a logical pointer."; + } + + const auto pointer_type = _.FindDef(pointer->type_id()); + if (!pointer_type || + (pointer_type->opcode() != spv::Op::OpTypePointer && + pointer_type->opcode() != spv::Op::OpTypeUntypedPointerKHR)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL type for pointer " + << _.getIdName(pointer_id) << " is not a pointer type."; + } + + const auto object_id = inst->GetOperandAs(1); + const auto object = _.FindDef(object_id); + if (!object || !object->type_id()) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL Object " << _.getIdName(object_id) + << " is not an object."; + } + + const auto object_type_id = object->type_id(); + if (!_.IsIntScalarOrVectorType(object_type_id) && + !_.IsFloatScalarOrVectorType(object_type_id)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL Object " << _.getIdName(object_id) + << " type must be a scalar or vector of numerical type."; + } + + if (pointer_type->opcode() == spv::Op::OpTypePointer) { + const auto pointee_type = + _.FindDef(pointer_type->GetOperandAs(2)); + if (!pointee_type || pointee_type->id() != object_type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL Pointer " + << _.getIdName(pointer_id) + << "s type does not match Object " + << _.getIdName(object->id()) << "s type."; + } + } + + const auto predicate_id = inst->GetOperandAs(2); + const auto predicate = _.FindDef(predicate_id); + if (!predicate || !_.IsBoolScalarType(predicate->type_id())) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL Predicate " + << _.getIdName(predicate_id) << " must be a Boolean scalar."; + } + + if (inst->operands().size() > 3) { + const auto mask = inst->GetOperandAs(3); + if (mask & uint32_t(spv::MemoryAccessMask::Volatile)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpPredicatedStoreINTEL does not allow the Volatile memory " + "operand."; + } + } + + if (auto error = CheckMemoryAccess(_, inst, 3)) return error; + + return SPV_SUCCESS; +} + } // namespace spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) { @@ -3529,6 +3683,10 @@ spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) { case spv::Op::OpCooperativeVectorMatrixMulNV: case spv::Op::OpCooperativeVectorMatrixMulAddNV: return ValidateCooperativeVectorMatrixMulNV(_, inst); + case spv::Op::OpPredicatedLoadINTEL: + return ValidatePredicatedLoadINTEL(_, inst); + case spv::Op::OpPredicatedStoreINTEL: + return ValidatePredicatedStoreINTEL(_, inst); case spv::Op::OpPtrEqual: case spv::Op::OpPtrNotEqual: case spv::Op::OpPtrDiff: diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt index 550a5b2803..4f2d5fa140 100644 --- a/test/val/CMakeLists.txt +++ b/test/val/CMakeLists.txt @@ -53,6 +53,7 @@ add_spvtools_unittest(TARGET val_abcde val_extension_spv_intel_arbitrary_precision_integers_test.cpp val_extension_spv_intel_function_variants.cpp val_extension_spv_intel_inline_assembly.cpp + val_extension_spv_intel_predicated_io_test.cpp val_extension_spv_ext_descriptor_heap.cpp val_ext_inst_test.cpp val_ext_inst_debug_test.cpp diff --git a/test/val/val_extension_spv_intel_predicated_io_test.cpp b/test/val/val_extension_spv_intel_predicated_io_test.cpp new file mode 100644 index 0000000000..cf8a2cdc34 --- /dev/null +++ b/test/val/val_extension_spv_intel_predicated_io_test.cpp @@ -0,0 +1,342 @@ +// Copyright (c) 2026 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Tests for SPV_INTEL_predicated_io extension + +#include + +#include "gmock/gmock.h" +#include "test/val/val_fixtures.h" + +namespace spvtools { +namespace val { +namespace { + +using ::testing::HasSubstr; + +using ValidatePredicatedIOINTEL = spvtest::ValidateBase; + +std::string GenerateShaderCode( + const std::string& body, + const std::string& extra_types_and_vars = "") { + std::ostringstream ss; + ss << R"( +OpCapability Shader +OpCapability Linkage +OpCapability PredicatedIOINTEL +OpExtension "SPV_INTEL_predicated_io" +OpMemoryModel Logical GLSL450 +%void = OpTypeVoid +%void_fn = OpTypeFunction %void +%bool = OpTypeBool +%int = OpTypeInt 32 1 +%float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 +%int_ptr_func = OpTypePointer Function %int +%float_ptr_func = OpTypePointer Function %float +%v4float_ptr_func = OpTypePointer Function %v4float +%int_0 = OpConstant %int 0 +%int_1 = OpConstant %int 1 +%float_0 = OpConstant %float 0.0 +%float_1 = OpConstant %float 1.0 +%v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 +%true = OpConstantTrue %bool +%false = OpConstantFalse %bool +)"; + ss << extra_types_and_vars; + ss << R"( +%func = OpFunction %void None %void_fn +%entry = OpLabel +)"; + ss << body; + ss << R"( +OpReturn +OpFunctionEnd +)"; + return ss.str(); +} + +// ---- OpPredicatedLoadINTEL valid cases ---- + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadScalarFloatSuccess) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %float_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadScalarIntSuccess) { + const std::string body = R"( +%ptr = OpVariable %int_ptr_func Function +%val = OpPredicatedLoadINTEL %int %ptr %true %int_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadVectorFloatSuccess) { + const std::string body = R"( +%ptr = OpVariable %v4float_ptr_func Function +%val = OpPredicatedLoadINTEL %v4float %ptr %true %v4float_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadWithAlignedSuccess) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %float_0 Aligned 4 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadFalsePredicateSuccess) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %false %float_1 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +// ---- OpPredicatedLoadINTEL error cases ---- + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadBoolResultType) { + const std::string extra = R"( +%bool_ptr_func = OpTypePointer Function %bool +)"; + const std::string body = R"( +%ptr = OpVariable %bool_ptr_func Function +%val = OpPredicatedLoadINTEL %bool %ptr %true %true +)"; + CompileSuccessfully(GenerateShaderCode(body, extra)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("must be a scalar or vector of numerical type")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadStructResultType) { + const std::string extra = R"( +%struct_type = OpTypeStruct %int %float +%struct_ptr_func = OpTypePointer Function %struct_type +%struct_default = OpConstantComposite %struct_type %int_0 %float_0 +)"; + const std::string body = R"( +%ptr = OpVariable %struct_ptr_func Function +%val = OpPredicatedLoadINTEL %struct_type %ptr %true %struct_default +)"; + CompileSuccessfully(GenerateShaderCode(body, extra)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("must be a scalar or vector of numerical type")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadPredicateNotBool) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %int_0 %float_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Predicate")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("must be a Boolean scalar")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadDefaultValueTypeMismatch) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %int_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Default Value")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("type does not match Result Type")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadPointerTypeMismatch) { + const std::string body = R"( +%ptr = OpVariable %int_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %float_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("does not match Pointer")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadVolatileNotAllowed) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %float_0 Volatile +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("does not allow the Volatile memory operand")); +} + +// ---- OpPredicatedStoreINTEL valid cases ---- + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreScalarFloatSuccess) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %true +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreScalarIntSuccess) { + const std::string body = R"( +%ptr = OpVariable %int_ptr_func Function +OpPredicatedStoreINTEL %ptr %int_1 %true +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreVectorFloatSuccess) { + const std::string body = R"( +%ptr = OpVariable %v4float_ptr_func Function +OpPredicatedStoreINTEL %ptr %v4float_0 %true +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreWithAlignedSuccess) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %true Aligned 4 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); +} + +// ---- OpPredicatedStoreINTEL error cases ---- + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreBoolObject) { + const std::string extra = R"( +%bool_ptr_func = OpTypePointer Function %bool +)"; + const std::string body = R"( +%ptr = OpVariable %bool_ptr_func Function +OpPredicatedStoreINTEL %ptr %true %true +)"; + CompileSuccessfully(GenerateShaderCode(body, extra)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("type must be a scalar or vector of numerical type")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStorePredicateNotBool) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %int_0 +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Predicate")); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("must be a Boolean scalar")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStorePointerTypeMismatch) { + const std::string body = R"( +%ptr = OpVariable %int_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %true +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("type does not match Object")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreVolatileNotAllowed) { + const std::string body = R"( +%ptr = OpVariable %float_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %true Volatile +)"; + CompileSuccessfully(GenerateShaderCode(body)); + EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("does not allow the Volatile memory operand")); +} + +// ---- Capability/Extension requirement tests ---- + +TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadWithoutCapability) { + const std::string spirv = R"( +OpCapability Shader +OpCapability Linkage +OpExtension "SPV_INTEL_predicated_io" +OpMemoryModel Logical GLSL450 +%void = OpTypeVoid +%void_fn = OpTypeFunction %void +%bool = OpTypeBool +%float = OpTypeFloat 32 +%float_ptr_func = OpTypePointer Function %float +%float_0 = OpConstant %float 0.0 +%true = OpConstantTrue %bool +%func = OpFunction %void None %void_fn +%entry = OpLabel +%ptr = OpVariable %float_ptr_func Function +%val = OpPredicatedLoadINTEL %float %ptr %true %float_0 +OpReturn +OpFunctionEnd +)"; + CompileSuccessfully(spirv); + EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("PredicatedIOINTEL")); +} + +TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreWithoutCapability) { + const std::string spirv = R"( +OpCapability Shader +OpCapability Linkage +OpExtension "SPV_INTEL_predicated_io" +OpMemoryModel Logical GLSL450 +%void = OpTypeVoid +%void_fn = OpTypeFunction %void +%bool = OpTypeBool +%float = OpTypeFloat 32 +%float_ptr_func = OpTypePointer Function %float +%float_1 = OpConstant %float 1.0 +%true = OpConstantTrue %bool +%func = OpFunction %void None %void_fn +%entry = OpLabel +%ptr = OpVariable %float_ptr_func Function +OpPredicatedStoreINTEL %ptr %float_1 %true +OpReturn +OpFunctionEnd +)"; + CompileSuccessfully(spirv); + EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("PredicatedIOINTEL")); +} + +} // namespace +} // namespace val +} // namespace spvtools From f6487c7402b386536f5bf39825bea67eb7ed06d4 Mon Sep 17 00:00:00 2001 From: "Plyakhin, Yury" Date: Fri, 1 May 2026 02:05:43 +0200 Subject: [PATCH 2/2] clang-format --- source/val/validate_memory.cpp | 12 +++---- ...extension_spv_intel_predicated_io_test.cpp | 32 +++++++------------ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp index e1f49d83fb..7f3daa1431 100644 --- a/source/val/validate_memory.cpp +++ b/source/val/validate_memory.cpp @@ -3518,9 +3518,8 @@ spv_result_t ValidatePredicatedLoadINTEL(ValidationState_t& _, if (!pointee_type || result_type_id != pointee_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpPredicatedLoadINTEL Result Type " - << _.getIdName(result_type_id) - << " does not match Pointer " << _.getIdName(pointer->id()) - << "s type."; + << _.getIdName(result_type_id) << " does not match Pointer " + << _.getIdName(pointer->id()) << "s type."; } } @@ -3566,8 +3565,8 @@ spv_result_t ValidatePredicatedStoreINTEL(ValidationState_t& _, (_.features().variable_pointers && !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpPredicatedStoreINTEL Pointer " - << _.getIdName(pointer_id) << " is not a logical pointer."; + << "OpPredicatedStoreINTEL Pointer " << _.getIdName(pointer_id) + << " is not a logical pointer."; } const auto pointer_type = _.FindDef(pointer->type_id()); @@ -3601,8 +3600,7 @@ spv_result_t ValidatePredicatedStoreINTEL(ValidationState_t& _, if (!pointee_type || pointee_type->id() != object_type_id) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpPredicatedStoreINTEL Pointer " - << _.getIdName(pointer_id) - << "s type does not match Object " + << _.getIdName(pointer_id) << "s type does not match Object " << _.getIdName(object->id()) << "s type."; } } diff --git a/test/val/val_extension_spv_intel_predicated_io_test.cpp b/test/val/val_extension_spv_intel_predicated_io_test.cpp index cf8a2cdc34..aab91315fc 100644 --- a/test/val/val_extension_spv_intel_predicated_io_test.cpp +++ b/test/val/val_extension_spv_intel_predicated_io_test.cpp @@ -27,9 +27,8 @@ using ::testing::HasSubstr; using ValidatePredicatedIOINTEL = spvtest::ValidateBase; -std::string GenerateShaderCode( - const std::string& body, - const std::string& extra_types_and_vars = "") { +std::string GenerateShaderCode(const std::string& body, + const std::string& extra_types_and_vars = "") { std::ostringstream ss; ss << R"( OpCapability Shader @@ -153,10 +152,8 @@ TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadPredicateNotBool) { )"; CompileSuccessfully(GenerateShaderCode(body)); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Predicate")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be a Boolean scalar")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("Predicate")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a Boolean scalar")); } TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadDefaultValueTypeMismatch) { @@ -166,8 +163,7 @@ TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadDefaultValueTypeMismatch) { )"; CompileSuccessfully(GenerateShaderCode(body)); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Default Value")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("Default Value")); EXPECT_THAT(getDiagnosticString(), HasSubstr("type does not match Result Type")); } @@ -179,8 +175,7 @@ TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadPointerTypeMismatch) { )"; CompileSuccessfully(GenerateShaderCode(body)); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("does not match Pointer")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("does not match Pointer")); } TEST_F(ValidatePredicatedIOINTEL, PredicatedLoadVolatileNotAllowed) { @@ -255,10 +250,8 @@ OpPredicatedStoreINTEL %ptr %float_1 %int_0 )"; CompileSuccessfully(GenerateShaderCode(body)); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("Predicate")); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("must be a Boolean scalar")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("Predicate")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a Boolean scalar")); } TEST_F(ValidatePredicatedIOINTEL, PredicatedStorePointerTypeMismatch) { @@ -268,8 +261,7 @@ OpPredicatedStoreINTEL %ptr %float_1 %true )"; CompileSuccessfully(GenerateShaderCode(body)); EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("type does not match Object")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("type does not match Object")); } TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreVolatileNotAllowed) { @@ -307,8 +299,7 @@ OpFunctionEnd )"; CompileSuccessfully(spirv); EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("PredicatedIOINTEL")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("PredicatedIOINTEL")); } TEST_F(ValidatePredicatedIOINTEL, PredicatedStoreWithoutCapability) { @@ -333,8 +324,7 @@ OpFunctionEnd )"; CompileSuccessfully(spirv); EXPECT_NE(SPV_SUCCESS, ValidateInstructions()); - EXPECT_THAT(getDiagnosticString(), - HasSubstr("PredicatedIOINTEL")); + EXPECT_THAT(getDiagnosticString(), HasSubstr("PredicatedIOINTEL")); } } // namespace