diff --git a/DEPS b/DEPS index 4fbf1a2b3..42c4fdfb7 100644 --- a/DEPS +++ b/DEPS @@ -11,7 +11,7 @@ vars = { 'protobuf_revision': 'v21.12', 're2_revision': '11073deb73b3d01018308863c0bcdfd0d51d3e70', - 'spirv_headers_revision': '29ba2493125effc581532518add689613cebfec7', + 'spirv_headers_revision': 'cfbe4feef20c3c0628712c2792624f0221e378ac', } deps = { diff --git a/source/val/validate_annotation.cpp b/source/val/validate_annotation.cpp index bef753d9c..73d0285a1 100644 --- a/source/val/validate_annotation.cpp +++ b/source/val/validate_annotation.cpp @@ -193,7 +193,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec, switch (dec) { case spv::Decoration::Location: case spv::Decoration::Component: - // Location is used for input, output and ray tracing stages. + // Location is used for input, output, tile image, and ray tracing + // stages. if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output && sc != spv::StorageClass::RayPayloadKHR && sc != spv::StorageClass::IncomingRayPayloadKHR && @@ -201,7 +202,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec, sc != spv::StorageClass::CallableDataKHR && sc != spv::StorageClass::IncomingCallableDataKHR && sc != spv::StorageClass::ShaderRecordBufferKHR && - sc != spv::StorageClass::HitObjectAttributeNV) { + sc != spv::StorageClass::HitObjectAttributeNV && + sc != spv::StorageClass::TileImageEXT) { return _.diag(SPV_ERROR_INVALID_ID, target) << _.VkErrorID(6672) << _.SpvDecorationString(dec) << " decoration must not be applied to this storage class"; diff --git a/source/val/validate_function.cpp b/source/val/validate_function.cpp index db402aa32..639817fef 100644 --- a/source/val/validate_function.cpp +++ b/source/val/validate_function.cpp @@ -14,6 +14,7 @@ #include +#include "source/enum_string_mapping.h" #include "source/opcode.h" #include "source/val/instruction.h" #include "source/val/validate.h" diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp index 0e5142248..ded88b118 100644 --- a/source/val/validate_image.cpp +++ b/source/val/validate_image.cpp @@ -210,6 +210,7 @@ uint32_t GetPlaneCoordSize(const ImageTypeInfo& info) { case spv::Dim::Dim2D: case spv::Dim::Rect: case spv::Dim::SubpassData: + case spv::Dim::TileImageDataEXT: plane_size = 2; break; case spv::Dim::Dim3D: @@ -854,6 +855,28 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Dim SubpassData requires format Unknown"; } + } else if (info.dim == spv::Dim::TileImageDataEXT) { + if (_.IsVoidType(info.sampled_type)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Dim TileImageDataEXT requires Sampled Type to be not " + "OpTypeVoid"; + } + if (info.sampled != 2) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Dim TileImageDataEXT requires Sampled to be 2"; + } + if (info.format != spv::ImageFormat::Unknown) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Dim TileImageDataEXT requires format Unknown"; + } + if (info.depth != 0) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Dim TileImageDataEXT requires Depth to be 0"; + } + if (info.arrayed != 0) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Dim TileImageDataEXT requires Arrayed to be 0"; + } } else { if (info.multisampled && (info.sampled == 2) && !_.HasCapability(spv::Capability::StorageImageMultisample)) { @@ -919,6 +942,8 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _, } // OpenCL requires Sampled=0, checked elsewhere. // Vulkan uses the Sampled=1 case. + // If Dim is TileImageDataEXT, Sampled must be 2 and this is validated + // elsewhere. if ((info.sampled != 0) && (info.sampled != 1)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << _.VkErrorID(4657) @@ -1118,6 +1143,12 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _, << "Image Dim SubpassData cannot be used with OpImageTexelPointer"; } + if (info.dim == spv::Dim::TileImageDataEXT) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Dim TileImageDataEXT cannot be used with " + "OpImageTexelPointer"; + } + const uint32_t coord_type = _.GetOperandTypeId(inst, 3); if (!coord_type || !_.IsIntScalarOrVectorType(coord_type)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) @@ -1624,6 +1655,19 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) { spvOpcodeString(opcode)); } + if (info.dim == spv::Dim::TileImageDataEXT) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Dim TileImageDataEXT cannot be used with " + << spvOpcodeString(opcode); + + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + spv::ExecutionModel::Fragment, + std::string( + "Dim TileImageDataEXT requires Fragment execution model: ") + + spvOpcodeString(opcode)); + } + if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) { const uint32_t result_component_type = _.GetComponentType(actual_result_type); @@ -1686,6 +1730,11 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) { << "Image 'Dim' cannot be SubpassData"; } + if (info.dim == spv::Dim::TileImageDataEXT) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image 'Dim' cannot be TileImageDataEXT"; + } + if (spv_result_t result = ValidateImageReadWrite(_, inst, info)) return result; @@ -1900,10 +1949,22 @@ spv_result_t ValidateImageQueryFormatOrOrder(ValidationState_t& _, << "Expected Result Type to be int scalar type"; } - if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != spv::Op::OpTypeImage) { + const uint32_t image_type = _.GetOperandTypeId(inst, 2); + if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Expected operand to be of type OpTypeImage"; } + + ImageTypeInfo info; + if (!GetImageTypeInfo(_, image_type, &info)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Corrupt image type definition"; + } + + if (info.dim == spv::Dim::TileImageDataEXT) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image 'Dim' cannot be TileImageDataEXT"; + } return SPV_SUCCESS; } diff --git a/source/val/validate_mode_setting.cpp b/source/val/validate_mode_setting.cpp index dfa46466f..d757d4f82 100644 --- a/source/val/validate_mode_setting.cpp +++ b/source/val/validate_mode_setting.cpp @@ -502,6 +502,9 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, case spv::ExecutionMode::DepthGreater: case spv::ExecutionMode::DepthLess: case spv::ExecutionMode::DepthUnchanged: + case spv::ExecutionMode::NonCoherentColorAttachmentReadEXT: + case spv::ExecutionMode::NonCoherentDepthAttachmentReadEXT: + case spv::ExecutionMode::NonCoherentStencilAttachmentReadEXT: case spv::ExecutionMode::PixelInterlockOrderedEXT: case spv::ExecutionMode::PixelInterlockUnorderedEXT: case spv::ExecutionMode::SampleInterlockOrderedEXT: diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index e43517850..dbf0ba6d9 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -1572,6 +1572,7 @@ bool ValidationState_t::IsValidStorageClass( case spv::StorageClass::ShaderRecordBufferKHR: case spv::StorageClass::TaskPayloadWorkgroupEXT: case spv::StorageClass::HitObjectAttributeNV: + case spv::StorageClass::TileImageEXT: return true; default: return false; diff --git a/test/text_to_binary.extension_test.cpp b/test/text_to_binary.extension_test.cpp index 6780c7e83..55f846660 100644 --- a/test/text_to_binary.extension_test.cpp +++ b/test/text_to_binary.extension_test.cpp @@ -1198,5 +1198,54 @@ INSTANTIATE_TEST_SUITE_P( {1, 2, 3, 4, 5, 6})}, }))); +// SPV_EXT_shader_tile_image + +INSTANTIATE_TEST_SUITE_P( + SPV_EXT_shader_tile_image, ExtensionRoundTripTest, + Combine( + Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_5, SPV_ENV_VULKAN_1_0, + SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3), + ValuesIn(std::vector{ + {"OpExtension \"SPV_EXT_shader_tile_image\"\n", + MakeInstruction(spv::Op::OpExtension, + MakeVector("SPV_EXT_shader_tile_image"))}, + {"OpCapability TileImageColorReadAccessEXT\n", + MakeInstruction( + spv::Op::OpCapability, + {(uint32_t)spv::Capability::TileImageColorReadAccessEXT})}, + {"OpCapability TileImageDepthReadAccessEXT\n", + MakeInstruction( + spv::Op::OpCapability, + {(uint32_t)spv::Capability::TileImageDepthReadAccessEXT})}, + {"OpCapability TileImageStencilReadAccessEXT\n", + MakeInstruction( + spv::Op::OpCapability, + {(uint32_t)spv::Capability::TileImageStencilReadAccessEXT})}, + {"OpExecutionMode %1 NonCoherentColorAttachmentReadEXT\n", + MakeInstruction(spv::Op::OpExecutionMode, + {1, (uint32_t)spv::ExecutionMode:: + NonCoherentColorAttachmentReadEXT})}, + {"OpExecutionMode %1 NonCoherentDepthAttachmentReadEXT\n", + MakeInstruction(spv::Op::OpExecutionMode, + {1, (uint32_t)spv::ExecutionMode:: + NonCoherentDepthAttachmentReadEXT})}, + {"OpExecutionMode %1 NonCoherentStencilAttachmentReadEXT\n", + MakeInstruction(spv::Op::OpExecutionMode, + {1, (uint32_t)spv::ExecutionMode:: + NonCoherentStencilAttachmentReadEXT})}, + {"%2 = OpColorAttachmentReadEXT %1 %3\n", + MakeInstruction(spv::Op::OpColorAttachmentReadEXT, {1, 2, 3})}, + {"%2 = OpColorAttachmentReadEXT %1 %3 %4\n", + MakeInstruction(spv::Op::OpColorAttachmentReadEXT, {1, 2, 3, 4})}, + {"%2 = OpDepthAttachmentReadEXT %1\n", + MakeInstruction(spv::Op::OpDepthAttachmentReadEXT, {1, 2})}, + {"%2 = OpDepthAttachmentReadEXT %1 %3\n", + MakeInstruction(spv::Op::OpDepthAttachmentReadEXT, {1, 2, 3})}, + {"%2 = OpStencilAttachmentReadEXT %1\n", + MakeInstruction(spv::Op::OpStencilAttachmentReadEXT, {1, 2})}, + {"%2 = OpStencilAttachmentReadEXT %1 %3\n", + MakeInstruction(spv::Op::OpStencilAttachmentReadEXT, {1, 2, 3})}, + }))); + } // namespace } // namespace spvtools diff --git a/test/text_to_binary.type_declaration_test.cpp b/test/text_to_binary.type_declaration_test.cpp index 241600eeb..770f298bc 100644 --- a/test/text_to_binary.type_declaration_test.cpp +++ b/test/text_to_binary.type_declaration_test.cpp @@ -59,6 +59,7 @@ INSTANTIATE_TEST_SUITE_P( CASE(Rect), CASE(Buffer), CASE(SubpassData), + CASE(TileImageDataEXT), })); #undef CASE // clang-format on @@ -221,6 +222,7 @@ TEST_F(OpTypeForwardPointerTest, ValidStorageClass) { CASE(AtomicCounter); CASE(Image); CASE(StorageBuffer); + CASE(TileImageEXT); } #undef CASE diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp index a97ef7cb3..aa335c869 100644 --- a/test/val/val_image_test.cpp +++ b/test/val/val_image_test.cpp @@ -356,7 +356,8 @@ OpFunctionEnd)"; std::string GenerateKernelCode( const std::string& body, - const std::string& capabilities_and_extensions = "") { + const std::string& capabilities_and_extensions = "", + const std::string& declarations = "") { std::ostringstream ss; ss << R"( OpCapability Addresses @@ -436,7 +437,11 @@ OpMemoryModel Physical32 OpenCL %type_sampler = OpTypeSampler %ptr_sampler = OpTypePointer UniformConstant %type_sampler %uniform_sampler = OpVariable %ptr_sampler UniformConstant +)"; + ss << declarations; + + ss << R"( %main = OpFunction %void None %func %main_entry = OpLabel )"; @@ -480,10 +485,10 @@ OpCapability Int64 OpCapability Float64 )"; - ss << capabilities_and_extensions; if (!include_entry_point) { - ss << "OpCapability Linkage"; + ss << "OpCapability Linkage\n"; } + ss << capabilities_and_extensions; ss << R"( OpMemoryModel Logical GLSL450 @@ -781,6 +786,279 @@ TEST_F(ValidateImage, TypeImageWrongArrayForSubpassDataVulkan) { HasSubstr("Dim SubpassData requires Arrayed to be 0")); } +TEST_F(ValidateImage, TypeImageWrongSampledTypeForTileImageDataEXT) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %void TileImageDataEXT 0 0 0 2 Unknown +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "Dim TileImageDataEXT requires Sampled Type to be not OpTypeVoid")); +} + +TEST_F(ValidateImage, TypeImageWrongSampledForTileImageDataEXT) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 1 Unknown +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Dim TileImageDataEXT requires Sampled to be 2")); +} + +TEST_F(ValidateImage, TypeImageWrongFormatForTileImageDataEXT) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Rgba32f +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Dim TileImageDataEXT requires format Unknown")); +} + +TEST_F(ValidateImage, TypeImageWrongDepthForTileImageDataEXT) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %f32 TileImageDataEXT 1 0 0 2 Unknown +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Dim TileImageDataEXT requires Depth to be 0")); +} + +TEST_F(ValidateImage, TypeImageWrongArrayedForTileImageDataEXT) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %f32 TileImageDataEXT 0 1 0 2 Unknown +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Dim TileImageDataEXT requires Arrayed to be 0")); +} + +TEST_F(ValidateImage, TypeSampledImage_TileImageDataEXT_Error) { + const std::string code = GetShaderHeader( + "OpCapability TileImageColorReadAccessEXT\n" + "OpExtension \"SPV_EXT_shader_tile_image\"\n", + false) + + R"( +%img_type = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%simg_type = OpTypeSampledImage %img_type +)"; + + CompileSuccessfully(code.c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Sampled image type requires an image type with " + "\"Sampled\" operand set to 0 or 1")); +} + +TEST_F(ValidateImage, ImageTexelPointerImageDimTileImageDataEXTBad) { + const std::string body = R"( +%texel_ptr = OpImageTexelPointer %ptr_Image_u32 %tile_image_u32_tid_0002 %u32_0 %u32_0 +%sum = OpAtomicIAdd %u32 %texel_ptr %u32_1 %u32_0 %u32_1 +)"; + const std::string decl = R"( +%type_image_u32_tid_0002 = OpTypeImage %u32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_u32_tid_0002 = OpTypePointer TileImageEXT %type_image_u32_tid_0002 +%tile_image_u32_tid_0002 = OpVariable %ptr_image_u32_tid_0002 TileImageEXT +)"; + + const std::string extra = R"( +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", + SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl) + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image Dim TileImageDataEXT cannot be used with " + "OpImageTexelPointer")); +} + +TEST_F(ValidateImage, ReadTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +%res1 = OpImageRead %f32vec4 %img %u32vec2_01 +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", + SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl) + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("Image Dim TileImageDataEXT cannot be used with ImageRead")); +} + +TEST_F(ValidateImage, WriteTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +OpImageWrite %img %u32vec2_01 %f32vec4_0000 +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", + SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl) + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image 'Dim' cannot be TileImageDataEXT")); +} + +TEST_F(ValidateImage, QueryFormatTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +%res1 = OpImageQueryFormat %u32 %img +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str()); + + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image 'Dim' cannot be TileImageDataEXT")); +} + +TEST_F(ValidateImage, QueryOrderTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +%res1 = OpImageQueryOrder %u32 %img +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateKernelCode(body, extra, decl).c_str()); + + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image 'Dim' cannot be TileImageDataEXT")); +} + +TEST_F(ValidateImage, SparseFetchTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +%res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", + SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl) + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Expected Image 'Sampled' parameter to be 1")); +} + +TEST_F(ValidateImage, SparseReadTileImageDataEXT) { + const std::string body = R"( +%img = OpLoad %type_image_f32_tid_0002 %uniform_image_f32_tid_0002 +%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 +)"; + + const std::string decl = R"( +%type_image_f32_tid_0002 = OpTypeImage %f32 TileImageDataEXT 0 0 0 2 Unknown +%ptr_image_f32_tid_0002 = OpTypePointer UniformConstant %type_image_f32_tid_0002 +%uniform_image_f32_tid_0002 = OpVariable %ptr_image_f32_tid_0002 UniformConstant +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability TileImageColorReadAccessEXT +OpExtension "SPV_EXT_shader_tile_image" +)"; + + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "", + SPV_ENV_UNIVERSAL_1_5, "GLSL450", decl) + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr( + "Image Dim TileImageDataEXT cannot be used with ImageSparseRead")); +} + TEST_F(ValidateImage, TypeImage_OpenCL_Sampled0_OK) { const std::string code = GetKernelHeader() + R"( %img_type = OpTypeImage %void 2D 0 0 0 0 Unknown ReadOnly diff --git a/test/val/val_modes_test.cpp b/test/val/val_modes_test.cpp index a50ac5164..8dc0fbc5a 100644 --- a/test/val/val_modes_test.cpp +++ b/test/val/val_modes_test.cpp @@ -578,6 +578,11 @@ TEST_P(ValidateModeExecution, ExecutionMode) { sstr << "OpCapability Kernel\n"; if (env == SPV_ENV_UNIVERSAL_1_3) { sstr << "OpCapability SubgroupDispatch\n"; + } else if (env == SPV_ENV_UNIVERSAL_1_5) { + sstr << "OpCapability TileImageColorReadAccessEXT\n"; + sstr << "OpCapability TileImageDepthReadAccessEXT\n"; + sstr << "OpCapability TileImageStencilReadAccessEXT\n"; + sstr << "OpExtension \"SPV_EXT_shader_tile_image\"\n"; } } sstr << "OpMemoryModel Logical GLSL450\n"; @@ -701,6 +706,27 @@ INSTANTIATE_TEST_SUITE_P( "DepthLess", "DepthUnchanged"), Values(SPV_ENV_UNIVERSAL_1_0))); +INSTANTIATE_TEST_SUITE_P(ValidateModeFragmentOnlyGoodSpv15, + ValidateModeExecution, + Combine(Values(SPV_SUCCESS), Values(""), + Values("Fragment"), + Values("NonCoherentColorAttachmentReadEXT", + "NonCoherentDepthAttachmentReadEXT", + "NonCoherentStencilAttachmentReadEXT"), + Values(SPV_ENV_UNIVERSAL_1_5))); + +INSTANTIATE_TEST_SUITE_P( + ValidateModeFragmentOnlyBadSpv15, ValidateModeExecution, + Combine(Values(SPV_ERROR_INVALID_DATA), + Values("Execution mode can only be used with the Fragment " + "execution model."), + Values("Geometry", "TessellationControl", "TessellationEvaluation", + "GLCompute", "Vertex", "Kernel"), + Values("NonCoherentColorAttachmentReadEXT", + "NonCoherentDepthAttachmentReadEXT", + "NonCoherentStencilAttachmentReadEXT"), + Values(SPV_ENV_UNIVERSAL_1_5))); + INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution, Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel"),