diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp index 47d1a3c029..2f7c5cb1f9 100644 --- a/source/val/validate_memory.cpp +++ b/source/val/validate_memory.cpp @@ -1124,6 +1124,32 @@ spv_result_t ValidateVariableTileShadingQCOM(ValidationState_t& _, return SPV_SUCCESS; } +spv_result_t ValidateVariableTileImageEXT(ValidationState_t& _, + const Instruction* inst) { + bool is_valid_decl = true; + + auto result_type = _.FindDef(inst->type_id()); + if (result_type->opcode() == spv::Op::OpTypePointer) { + const auto pointee_type = _.FindDef(result_type->GetOperandAs(2)); + if (pointee_type && pointee_type->opcode() == spv::Op::OpTypeImage) { + spv::Dim dim = static_cast(pointee_type->word(3)); + if (dim != spv::Dim::TileImageDataEXT) { + is_valid_decl = false; + } + } else { + is_valid_decl = false; + } + } + + if (!is_valid_decl) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "The TileImageEXT Storage Class must only be used for declaring " + "tile image variables"; + } else { + return SPV_SUCCESS; + } +} + spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { const bool untyped_pointer = inst->opcode() == spv::Op::OpUntypedVariableKHR; @@ -1242,6 +1268,11 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (auto error = ValidateVariableTileShadingQCOM(_, inst)) return error; } + if (_.HasCapability(spv::Capability::TileImageColorReadAccessEXT) && + storage_class == spv::StorageClass::TileImageEXT) { + if (auto error = ValidateVariableTileImageEXT(_, inst)) return error; + } + return SPV_SUCCESS; } diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp index 15880c9de0..403487ea28 100644 --- a/test/val/val_image_test.cpp +++ b/test/val/val_image_test.cpp @@ -11477,12 +11477,12 @@ TEST_F(ValidateImage, TileImageNotFragment) { %void = OpTypeVoid %func = OpTypeFunction %void %float = OpTypeFloat 32 - %v4float = OpTypeVector %float 4 - %ptr = OpTypePointer TileImageEXT %v4float + %image = OpTypeImage %float TileImageDataEXT 0 0 0 2 Unknown + %ptr = OpTypePointer TileImageEXT %image %var = OpVariable %ptr TileImageEXT %main = OpFunction %void None %func %label = OpLabel - %val = OpLoad %v4float %var + %val = OpLoad %image %var OpReturn OpFunctionEnd )"; diff --git a/test/val/val_storage_test.cpp b/test/val/val_storage_test.cpp index b583fe30e3..8d84eee9f8 100644 --- a/test/val/val_storage_test.cpp +++ b/test/val/val_storage_test.cpp @@ -437,6 +437,38 @@ TEST_F(ValidateStorage, TileAttachmentQCOMBad6) { HasSubstr("requires one of these capabilities: TileShadingQCOM")); } +TEST_F(ValidateStorage, WrongDimTileImageEXT) { + const std::string spirv = R"( + OpCapability Shader + OpCapability Sampled1D + OpCapability TileImageColorReadAccessEXT + OpExtension "SPV_EXT_shader_tile_image" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + %void = OpTypeVoid + %int = OpTypeInt 32 1 + %img = OpTypeImage %int 1D 0 0 0 2 Rgba32i + %ptr_img = OpTypePointer TileImageEXT %img + %color1 = OpVariable %ptr_img TileImageEXT + %3 = OpTypeFunction %void + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd + )"; + + spv_target_env env = SPV_ENV_VULKAN_1_4; + CompileSuccessfully(spirv, env); + EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env)); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "The TileImageEXT Storage Class must only be used for declaring " + "tile image variables")); +} + std::string GenerateExecutionModelCode(const std::string& execution_model, const std::string& storage_class, bool store) {