| // Copyright (c) 2023 Google 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. |
| |
| #include "spirv-tools/optimizer.hpp" |
| #include "test/opt/pass_fixture.h" |
| #include "test/opt/pass_utils.h" |
| |
| namespace spvtools { |
| namespace opt { |
| namespace { |
| |
| using TrimCapabilitiesPassTest = PassTest<::testing::Test>; |
| |
| TEST_F(TrimCapabilitiesPassTest, CheckKnownAliasTransformations) { |
| // Those are expected changes caused by the test process: |
| // - SPV is assembled. -> capability goes from text to number. |
| // - SPV is optimized. |
| // - SPV is disassembled -> capability goes from number to text. |
| // - CHECK rule compares both text versions. |
| // Because some capabilities share the same number (aliases), the text |
| // compared with the CHECK rules depends on which alias is the first on the |
| // SPIRV-Headers enum. This could change, and we want to easily distinguish |
| // real failure from alias order change. This test is only here to list known |
| // alias transformations. If this test breaks, it's not a bug in the |
| // optimization pass, but just the SPIRV-Headers enum order that has changed. |
| // If that happens, tests needs to be updated to the correct alias is used in |
| // the CHECK rule. |
| const std::string kTest = R"( |
| OpCapability Linkage |
| OpCapability StorageUniform16 |
| OpCapability StorageUniformBufferBlock16 |
| OpCapability ShaderViewportIndexLayerNV |
| OpCapability FragmentBarycentricNV |
| OpCapability ShadingRateNV |
| OpCapability ShaderNonUniformEXT |
| OpCapability RuntimeDescriptorArrayEXT |
| OpCapability InputAttachmentArrayDynamicIndexingEXT |
| OpCapability UniformTexelBufferArrayDynamicIndexingEXT |
| OpCapability StorageTexelBufferArrayDynamicIndexingEXT |
| OpCapability UniformBufferArrayNonUniformIndexingEXT |
| OpCapability SampledImageArrayNonUniformIndexingEXT |
| OpCapability StorageBufferArrayNonUniformIndexingEXT |
| OpCapability StorageImageArrayNonUniformIndexingEXT |
| OpCapability InputAttachmentArrayNonUniformIndexingEXT |
| OpCapability UniformTexelBufferArrayNonUniformIndexingEXT |
| OpCapability StorageTexelBufferArrayNonUniformIndexingEXT |
| OpCapability VulkanMemoryModelKHR |
| OpCapability VulkanMemoryModelDeviceScopeKHR |
| OpCapability PhysicalStorageBufferAddressesEXT |
| OpCapability DemoteToHelperInvocationEXT |
| OpCapability DotProductInputAllKHR |
| OpCapability DotProductInput4x8BitKHR |
| OpCapability DotProductInput4x8BitPackedKHR |
| OpCapability DotProductKHR |
| OpCapability ComputeDerivativeGroupQuadsNV |
| OpCapability ComputeDerivativeGroupLinearNV |
| ; CHECK: OpCapability Linkage |
| ; CHECK-NOT: OpCapability StorageUniform16 |
| ; CHECK-NOT: OpCapability StorageUniformBufferBlock16 |
| ; CHECK-NOT: OpCapability ShaderViewportIndexLayerNV |
| ; CHECK-NOT: OpCapability FragmentBarycentricNV |
| ; CHECK-NOT: OpCapability ShadingRateNV |
| ; CHECK-NOT: OpCapability ShaderNonUniformEXT |
| ; CHECK-NOT: OpCapability RuntimeDescriptorArrayEXT |
| ; CHECK-NOT: OpCapability InputAttachmentArrayDynamicIndexingEXT |
| ; CHECK-NOT: OpCapability UniformTexelBufferArrayDynamicIndexingEXT |
| ; CHECK-NOT: OpCapability StorageTexelBufferArrayDynamicIndexingEXT |
| ; CHECK-NOT: OpCapability UniformBufferArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability SampledImageArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability StorageBufferArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability StorageImageArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability InputAttachmentArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability UniformTexelBufferArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability StorageTexelBufferArrayNonUniformIndexingEXT |
| ; CHECK-NOT: OpCapability VulkanMemoryModelKHR |
| ; CHECK-NOT: OpCapability VulkanMemoryModelDeviceScopeKHR |
| ; CHECK-NOT: OpCapability PhysicalStorageBufferAddressesEXT |
| ; CHECK-NOT: OpCapability DemoteToHelperInvocationEXT |
| ; CHECK-NOT: OpCapability DotProductInputAllKHR |
| ; CHECK-NOT: OpCapability DotProductInput4x8BitKHR |
| ; CHECK-NOT: OpCapability DotProductInput4x8BitPackedKHR |
| ; CHECK-NOT: OpCapability DotProductKHR |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupQuadsNV |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupLinearNV |
| ; CHECK: OpCapability UniformAndStorageBuffer16BitAccess |
| ; CHECK: OpCapability StorageBuffer16BitAccess |
| ; CHECK: OpCapability ShaderViewportIndexLayerEXT |
| ; CHECK: OpCapability FragmentBarycentricKHR |
| ; CHECK: OpCapability FragmentDensityEXT |
| ; CHECK: OpCapability ShaderNonUniform |
| ; CHECK: OpCapability RuntimeDescriptorArray |
| ; CHECK: OpCapability InputAttachmentArrayDynamicIndexing |
| ; CHECK: OpCapability UniformTexelBufferArrayDynamicIndexing |
| ; CHECK: OpCapability StorageTexelBufferArrayDynamicIndexing |
| ; CHECK: OpCapability UniformBufferArrayNonUniformIndexing |
| ; CHECK: OpCapability SampledImageArrayNonUniformIndexing |
| ; CHECK: OpCapability StorageBufferArrayNonUniformIndexing |
| ; CHECK: OpCapability StorageImageArrayNonUniformIndexing |
| ; CHECK: OpCapability InputAttachmentArrayNonUniformIndexing |
| ; CHECK: OpCapability UniformTexelBufferArrayNonUniformIndexing |
| ; CHECK: OpCapability StorageTexelBufferArrayNonUniformIndexing |
| ; CHECK: OpCapability VulkanMemoryModel |
| ; CHECK: OpCapability VulkanMemoryModelDeviceScope |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability DemoteToHelperInvocation |
| ; CHECK: OpCapability DotProductInputAll |
| ; CHECK: OpCapability DotProductInput4x8Bit |
| ; CHECK: OpCapability DotProductInput4x8BitPacked |
| ; CHECK: OpCapability DotProduct |
| OpMemoryModel Logical Vulkan |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_3); |
| const auto result = |
| SinglePassRunAndMatch<EmptyPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, LinkagePreventsChanges) { |
| const std::string kTest = R"( |
| OpCapability Linkage |
| OpCapability ClipDistance |
| OpCapability CullDistance |
| OpCapability DemoteToHelperInvocation |
| OpCapability DeviceGroup |
| OpCapability DrawParameters |
| OpCapability Float16 |
| OpCapability Float64 |
| OpCapability FragmentBarycentricKHR |
| OpCapability FragmentFullyCoveredEXT |
| OpCapability FragmentShadingRateKHR |
| OpCapability GroupNonUniform |
| OpCapability GroupNonUniformArithmetic |
| OpCapability GroupNonUniformBallot |
| OpCapability GroupNonUniformQuad |
| OpCapability GroupNonUniformShuffle |
| OpCapability Image1D |
| OpCapability ImageBuffer |
| OpCapability ImageGatherExtended |
| OpCapability ImageMSArray |
| OpCapability ImageQuery |
| OpCapability InputAttachment |
| OpCapability InputAttachmentArrayNonUniformIndexing |
| OpCapability Int16 |
| OpCapability Int64 |
| OpCapability Int64Atomics |
| OpCapability Int64ImageEXT |
| OpCapability MeshShadingNV |
| OpCapability MinLod |
| OpCapability MultiView |
| OpCapability MultiViewport |
| OpCapability PhysicalStorageBufferAddresses |
| OpCapability RayQueryKHR |
| OpCapability RayTracingKHR |
| OpCapability RayTracingNV |
| OpCapability RayTraversalPrimitiveCullingKHR |
| OpCapability RuntimeDescriptorArray |
| OpCapability SampleMaskPostDepthCoverage |
| OpCapability SampleRateShading |
| OpCapability Sampled1D |
| OpCapability SampledBuffer |
| OpCapability SampledImageArrayNonUniformIndexing |
| OpCapability Shader |
| OpCapability ShaderClockKHR |
| OpCapability ShaderLayer |
| OpCapability ShaderNonUniform |
| OpCapability ShaderViewportIndex |
| OpCapability ShaderViewportIndexLayerEXT |
| OpCapability SparseResidency |
| OpCapability StencilExportEXT |
| OpCapability StorageImageArrayNonUniformIndexingEXT |
| OpCapability StorageImageExtendedFormats |
| OpCapability StorageImageReadWithoutFormat |
| OpCapability StorageImageWriteWithoutFormat |
| OpCapability StorageInputOutput16 |
| OpCapability StoragePushConstant16 |
| OpCapability StorageTexelBufferArrayNonUniformIndexing |
| OpCapability StorageUniform16 |
| OpCapability StorageUniformBufferBlock16 |
| OpCapability Tessellation |
| OpCapability UniformTexelBufferArrayNonUniformIndexing |
| OpCapability VulkanMemoryModel |
| OpExtension "SPV_EXT_fragment_fully_covered" |
| OpExtension "SPV_EXT_shader_image_int64" |
| OpExtension "SPV_EXT_shader_stencil_export" |
| OpExtension "SPV_EXT_shader_viewport_index_layer" |
| OpExtension "SPV_KHR_fragment_shader_barycentric" |
| OpExtension "SPV_KHR_fragment_shading_rate" |
| OpExtension "SPV_KHR_post_depth_coverage" |
| OpExtension "SPV_KHR_ray_query" |
| OpExtension "SPV_KHR_ray_tracing" |
| OpExtension "SPV_KHR_shader_clock" |
| OpExtension "SPV_NV_mesh_shader" |
| OpExtension "SPV_NV_ray_tracing" |
| OpExtension "SPV_NV_viewport_array2" |
| ; CHECK: OpCapability Linkage |
| ; CHECK: OpCapability ClipDistance |
| ; CHECK: OpCapability CullDistance |
| ; CHECK: OpCapability DemoteToHelperInvocation |
| ; CHECK: OpCapability DeviceGroup |
| ; CHECK: OpCapability DrawParameters |
| ; CHECK: OpCapability Float16 |
| ; CHECK: OpCapability Float64 |
| ; CHECK: OpCapability FragmentBarycentricKHR |
| ; CHECK: OpCapability FragmentFullyCoveredEXT |
| ; CHECK: OpCapability FragmentShadingRateKHR |
| ; CHECK: OpCapability GroupNonUniform |
| ; CHECK: OpCapability GroupNonUniformArithmetic |
| ; CHECK: OpCapability GroupNonUniformBallot |
| ; CHECK: OpCapability GroupNonUniformQuad |
| ; CHECK: OpCapability GroupNonUniformShuffle |
| ; CHECK: OpCapability Image1D |
| ; CHECK: OpCapability ImageBuffer |
| ; CHECK: OpCapability ImageGatherExtended |
| ; CHECK: OpCapability ImageMSArray |
| ; CHECK: OpCapability ImageQuery |
| ; CHECK: OpCapability InputAttachment |
| ; CHECK: OpCapability InputAttachmentArrayNonUniformIndexing |
| ; CHECK: OpCapability Int16 |
| ; CHECK: OpCapability Int64 |
| ; CHECK: OpCapability Int64Atomics |
| ; CHECK: OpCapability Int64ImageEXT |
| ; CHECK: OpCapability MeshShadingNV |
| ; CHECK: OpCapability MinLod |
| ; CHECK: OpCapability MultiView |
| ; CHECK: OpCapability MultiViewport |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability RayQueryKHR |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpCapability RayTracingNV |
| ; CHECK: OpCapability RayTraversalPrimitiveCullingKHR |
| ; CHECK: OpCapability RuntimeDescriptorArray |
| ; CHECK: OpCapability SampleMaskPostDepthCoverage |
| ; CHECK: OpCapability SampleRateShading |
| ; CHECK: OpCapability Sampled1D |
| ; CHECK: OpCapability SampledBuffer |
| ; CHECK: OpCapability SampledImageArrayNonUniformIndexing |
| ; CHECK: OpCapability Shader |
| ; CHECK: OpCapability ShaderClockKHR |
| ; CHECK: OpCapability ShaderLayer |
| ; CHECK: OpCapability ShaderNonUniform |
| ; CHECK: OpCapability ShaderViewportIndex |
| ; CHECK: OpCapability ShaderViewportIndexLayerEXT |
| ; CHECK: OpCapability SparseResidency |
| ; CHECK: OpCapability StencilExportEXT |
| ; CHECK: OpCapability StorageImageArrayNonUniformIndexing |
| ; CHECK: OpCapability StorageImageExtendedFormats |
| ; CHECK: OpCapability StorageImageReadWithoutFormat |
| ; CHECK: OpCapability StorageImageWriteWithoutFormat |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpCapability StoragePushConstant16 |
| ; CHECK: OpCapability StorageTexelBufferArrayNonUniformIndexing |
| ; CHECK: OpCapability Tessellation |
| ; CHECK: OpCapability UniformTexelBufferArrayNonUniformIndex |
| ; CHECK: OpCapability VulkanMemoryModel |
| ; CHECK: OpExtension "SPV_EXT_fragment_fully_covered" |
| ; CHECK: OpExtension "SPV_EXT_shader_image_int64" |
| ; CHECK: OpExtension "SPV_EXT_shader_stencil_export" |
| ; CHECK: OpExtension "SPV_EXT_shader_viewport_index_layer" |
| ; CHECK: OpExtension "SPV_KHR_fragment_shader_barycentric" |
| ; CHECK: OpExtension "SPV_KHR_fragment_shading_rate" |
| ; CHECK: OpExtension "SPV_KHR_post_depth_coverage" |
| ; CHECK: OpExtension "SPV_KHR_ray_query" |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpExtension "SPV_KHR_shader_clock" |
| ; CHECK: OpExtension "SPV_NV_mesh_shader" |
| ; CHECK: OpExtension "SPV_NV_ray_tracing" |
| ; CHECK: OpExtension "SPV_NV_viewport_array2" |
| OpMemoryModel Logical Vulkan |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_3); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, KeepShader) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| ; CHECK: OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, KeepShaderClockWhenInUse) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Int64 |
| OpCapability ShaderClockKHR |
| OpExtension "SPV_KHR_shader_clock" |
| ; CHECK: OpCapability ShaderClockKHR |
| ; CHECK: OpExtension "SPV_KHR_shader_clock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %uint = OpTypeInt 32 0 |
| %ulong = OpTypeInt 64 0 |
| %scope = OpConstant %uint 1 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| %7 = OpReadClockKHR %ulong %scope |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, TrimShaderClockWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Int64 |
| OpCapability ShaderClockKHR |
| OpExtension "SPV_KHR_shader_clock" |
| ; CHECK-NOT: OpCapability ShaderClockKHR |
| ; CHECK-NOT: OpExtension "SPV_KHR_shader_clock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, AMDShaderBallotExtensionRemains) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Groups |
| OpExtension "SPV_AMD_shader_ballot" |
| ; CHECK: OpCapability Groups |
| ; CHECK: OpExtension "SPV_AMD_shader_ballot" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %uint = OpTypeInt 32 0 |
| %1 = OpTypeFunction %void |
| %uint_0 = OpConstant %uint 0 |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| %4 = OpGroupIAddNonUniformAMD %uint %uint_0 ExclusiveScan %uint_0 |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, AMDShaderBallotExtensionRemoved) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Groups |
| OpExtension "SPV_AMD_shader_ballot" |
| ; CHECK-NOT: OpCapability Groups |
| ; CHECK-NOT: OpExtension "SPV_AMD_shader_ballot" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, MinLod_RemovedIfNotUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability MinLod |
| ; CHECK-NOT: OpCapability MinLod |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %v4float = OpTypeVector %float 4 |
| %type_image = OpTypeImage %float Cube 2 0 0 1 Rgba32f |
| %ptr_type_image = OpTypePointer UniformConstant %type_image |
| %type_sampler = OpTypeSampler |
| %ptr_type_sampler = OpTypePointer UniformConstant %type_sampler |
| %float_0 = OpConstant %float 0 |
| %float_000 = OpConstantComposite %v3float %float_0 %float_0 %float_0 |
| %image = OpVariable %ptr_type_image UniformConstant |
| %sampler = OpVariable %ptr_type_sampler UniformConstant |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| %21 = OpLoad %type_image %image |
| %22 = OpLoad %type_sampler %sampler |
| %24 = OpSampledImage %type_sampled_image %21 %22 |
| %25 = OpImageSampleImplicitLod %v4float %24 %float_000 |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, MinLod_RemainsWithOpImageSampleImplicitLod) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Sampled1D |
| OpCapability MinLod |
| ; CHECK: OpCapability MinLod |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %float = OpTypeFloat 32 |
| %v3float = OpTypeVector %float 3 |
| %v4float = OpTypeVector %float 4 |
| %type_image = OpTypeImage %float Cube 2 0 0 1 Rgba32f |
| %ptr_type_image = OpTypePointer UniformConstant %type_image |
| %type_sampler = OpTypeSampler |
| %ptr_type_sampler = OpTypePointer UniformConstant %type_sampler |
| %float_0 = OpConstant %float 0 |
| %float_000 = OpConstantComposite %v3float %float_0 %float_0 %float_0 |
| %image = OpVariable %ptr_type_image UniformConstant |
| %sampler = OpVariable %ptr_type_sampler UniformConstant |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| %21 = OpLoad %type_image %image |
| %22 = OpLoad %type_sampler %sampler |
| %24 = OpSampledImage %type_sampled_image %21 %22 |
| %25 = OpImageSampleImplicitLod %v4float %24 %float_000 MinLod %float_0 |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| MinLod_RemainsWithOpImageSparseSampleImplicitLod) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability SparseResidency |
| OpCapability ImageGatherExtended |
| OpCapability MinLod |
| ; CHECK: OpCapability MinLod |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %2 "main" |
| OpExecutionMode %2 OriginUpperLeft |
| %void = OpTypeVoid |
| %uint = OpTypeInt 32 0 |
| %float = OpTypeFloat 32 |
| %v2float = OpTypeVector %float 2 |
| %v3float = OpTypeVector %float 3 |
| %v4float = OpTypeVector %float 4 |
| %type_image = OpTypeImage %float 2D 2 0 0 1 Unknown |
| %ptr_type_image = OpTypePointer UniformConstant %type_image |
| %type_sampler = OpTypeSampler |
| %ptr_type_sampler = OpTypePointer UniformConstant %type_sampler |
| %type_sampled_image = OpTypeSampledImage %type_image |
| %sparse_struct = OpTypeStruct %uint %v4float |
| %float_0 = OpConstant %float 0 |
| %float_00 = OpConstantComposite %v2float %float_0 %float_0 |
| %float_000 = OpConstantComposite %v3float %float_0 %float_0 %float_0 |
| %image = OpVariable %ptr_type_image UniformConstant |
| %sampler = OpVariable %ptr_type_sampler UniformConstant |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| %21 = OpLoad %type_image %image |
| %22 = OpLoad %type_sampler %sampler |
| %24 = OpSampledImage %type_sampled_image %21 %22 |
| %25 = OpImageSparseSampleImplicitLod %sparse_struct %24 %float_00 MinLod %float_0 |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, MinLod_DetectsMinLodWithBitmaskImageOperand) { |
| const std::string kTest = R"( |
| OpCapability MinLod |
| ; CHECK: OpCapability MinLod |
| OpCapability Shader |
| OpCapability SparseResidency |
| OpCapability ImageGatherExtended |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %1 "main" |
| OpExecutionMode %1 OriginUpperLeft |
| %type_sampler = OpTypeSampler |
| %int = OpTypeInt 32 1 |
| %float = OpTypeFloat 32 |
| %v2int = OpTypeVector %int 2 |
| %v2float = OpTypeVector %float 2 |
| %v4float = OpTypeVector %float 4 |
| %ptr_sampler = OpTypePointer UniformConstant %type_sampler |
| %type_image = OpTypeImage %float 2D 2 0 0 1 Unknown |
| %ptr_image = OpTypePointer UniformConstant %type_image |
| %void = OpTypeVoid |
| %uint = OpTypeInt 32 0 |
| %type_sampled_image = OpTypeSampledImage %type_image |
| %type_struct = OpTypeStruct %uint %v4float |
| |
| %int_1 = OpConstant %int 1 |
| %float_0 = OpConstant %float 0 |
| %float_1 = OpConstant %float 1 |
| %8 = OpConstantComposite %v2float %float_0 %float_0 |
| %12 = OpConstantComposite %v2int %int_1 %int_1 |
| |
| %2 = OpVariable %ptr_sampler UniformConstant |
| %3 = OpVariable %ptr_image UniformConstant |
| %27 = OpTypeFunction %void |
| %1 = OpFunction %void None %27 |
| %28 = OpLabel |
| %29 = OpLoad %type_image %3 |
| %30 = OpLoad %type_sampler %2 |
| %31 = OpSampledImage %type_sampled_image %29 %30 |
| %32 = OpImageSparseSampleImplicitLod %type_struct %31 %8 ConstOffset|MinLod %12 %float_0 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointer_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer Input %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointer_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer Input %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerArray_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %uint = OpTypeInt 32 0 |
| %uint_1 = OpConstant %uint 1 |
| %array = OpTypeArray %half %uint_1 |
| %ptr = OpTypePointer Input %array |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerArray_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %uint = OpTypeInt 32 0 |
| %uint_1 = OpConstant %uint 1 |
| %array = OpTypeArray %half %uint_1 |
| %ptr = OpTypePointer Input %array |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerStruct_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Input %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerStruct_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Input %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerStructOfStruct_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %float = OpTypeFloat 32 |
| %struct = OpTypeStruct %float %half |
| %parent = OpTypeStruct %float %struct |
| %ptr = OpTypePointer Input %parent |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerStructOfStruct_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %float = OpTypeFloat 32 |
| %struct = OpTypeStruct %float %half |
| %parent = OpTypeStruct %float %struct |
| %ptr = OpTypePointer Input %parent |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerArrayOfStruct_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %uint = OpTypeInt 32 0 |
| %uint_1 = OpConstant %uint 1 |
| %array = OpTypeArray %struct %uint_1 |
| %ptr = OpTypePointer Input %array |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerArrayOfStruct_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %uint = OpTypeInt 32 0 |
| %uint_1 = OpConstant %uint 1 |
| %array = OpTypeArray %struct %uint_1 |
| %ptr = OpTypePointer Input %array |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerVector_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %vector = OpTypeVector %half 4 |
| %ptr = OpTypePointer Input %vector |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerVector_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %vector = OpTypeVector %half 4 |
| %ptr = OpTypePointer Input %vector |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerMatrix_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %vector = OpTypeVector %half 4 |
| %matrix = OpTypeMatrix %vector 4 |
| %ptr = OpTypePointer Input %matrix |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithInputPointerMatrix_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %vector = OpTypeVector %half 4 |
| %matrix = OpTypeMatrix %vector 4 |
| %ptr = OpTypePointer Input %matrix |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_IsRemovedWithoutInputPointer) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK-NOT: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithOutputPointer_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer Output %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemainsWithOutputPointer_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer Output %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageInputOutput16_RemovedWithoutOutputPointer) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageInputOutput16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK-NOT: OpCapability StorageInputOutput16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StoragePushConstant16_RemainsSimplePointer_Vulkan1_0) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StoragePushConstant16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StoragePushConstant16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer PushConstant %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StoragePushConstant16_RemainsSimplePointer_Vulkan1_1) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StoragePushConstant16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK: OpCapability StoragePushConstant16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer PushConstant %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, StoragePushConstant16_RemovedSimplePointer) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StoragePushConstant16 |
| OpExtension "SPV_KHR_16bit_storage" |
| ; CHECK-NOT: OpCapability StoragePushConstant16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %ptr = OpTypePointer Function %half |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniformBufferBlock16_RemainsSimplePointer_Vulkan1_0) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| OpDecorate %struct BufferBlock |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniformBufferBlock16_RemainsSimplePointer_Vulkan1_1) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| OpDecorate %struct BufferBlock |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniformBufferBlock16_RemovedSimplePointer) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK-NOT: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Function %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniform16_RemovedWithBufferBlockPointer_Vulkan1_0) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| static_assert(spv::Capability::StorageUniform16 == |
| spv::Capability::UniformAndStorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpCapability UniformAndStorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK-NOT: OpCapability UniformAndStorageBuffer16BitAccess |
| ; `-> StorageUniform16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| OpDecorate %struct BufferBlock |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniform16_RemovedWithBufferBlockPointer_Vulkan1_1) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| static_assert(spv::Capability::StorageUniform16 == |
| spv::Capability::UniformAndStorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpCapability UniformAndStorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK-NOT: OpCapability UniformAndStorageBuffer16BitAccess |
| ; `-> StorageUniform16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| OpDecorate %struct BufferBlock |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniform16_RemovedWithNonBlockUniformPointer_Vulkan1_0) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| static_assert(spv::Capability::StorageUniform16 == |
| spv::Capability::UniformAndStorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpCapability UniformAndStorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK-NOT: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK: OpCapability UniformAndStorageBuffer16BitAccess |
| ; `-> StorageUniform16 |
| ; CHECK: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_0); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageUniform16_RemovedWithNonBlockUniformPointer_Vulkan1_1) { |
| // See https://github.com/KhronosGroup/SPIRV-Tools/issues/5354 |
| static_assert(spv::Capability::StorageUniformBufferBlock16 == |
| spv::Capability::StorageBuffer16BitAccess); |
| static_assert(spv::Capability::StorageUniform16 == |
| spv::Capability::UniformAndStorageBuffer16BitAccess); |
| |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability Float16 |
| OpCapability StorageBuffer16BitAccess |
| OpCapability UniformAndStorageBuffer16BitAccess |
| OpExtension "SPV_KHR_16bit_storage" |
| |
| ; CHECK-NOT: OpCapability StorageBuffer16BitAccess |
| ; `-> StorageUniformBufferBlock16 |
| ; CHECK: OpCapability UniformAndStorageBuffer16BitAccess |
| ; `-> StorageUniform16 |
| ; CHECK-NOT: OpExtension "SPV_KHR_16bit_storage" |
| |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %2 "main" |
| %void = OpTypeVoid |
| %half = OpTypeFloat 16 |
| %struct = OpTypeStruct %half |
| %ptr = OpTypePointer Uniform %struct |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| SetTargetEnv(SPV_ENV_VULKAN_1_1); |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, FragmentShaderInterlock_RemovedIfNotUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK-NOT: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK-NOT: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderPixelInterlock_RemainsWhenOrderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main PixelInterlockOrderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderPixelInterlock_RemainsWhenUnorderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main PixelInterlockUnorderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderSampleInterlock_RemainsWhenOrderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK-NOT: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main SampleInterlockOrderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderSampleInterlock_RemainsWhenUnorderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK-NOT: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main SampleInterlockUnorderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderShadingRateInterlock_RemainsWhenOrderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK-NOT: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main ShadingRateInterlockOrderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| FragmentShaderShadingRateInterlock_RemainsWhenUnorderedIsUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability FragmentShaderPixelInterlockEXT |
| OpCapability FragmentShaderSampleInterlockEXT |
| OpCapability FragmentShaderShadingRateInterlockEXT |
| OpExtension "SPV_EXT_fragment_shader_interlock" |
| ; CHECK-NOT: OpCapability FragmentShaderPixelInterlockEXT |
| ; CHECK-NOT: OpCapability FragmentShaderSampleInterlockEXT |
| ; CHECK: OpCapability FragmentShaderShadingRateInterlockEXT |
| ; CHECK: OpExtension "SPV_EXT_fragment_shader_interlock" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %main ShadingRateInterlockUnorderedEXT |
| %void = OpTypeVoid |
| %1 = OpTypeFunction %void |
| %2 = OpFunction %void None %1 |
| %3 = OpLabel |
| OpBeginInvocationInterlockEXT |
| OpEndInvocationInterlockEXT |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Int64_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Int64 |
| ; CHECK-NOT: OpCapability Int64 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Int64_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Int64 |
| ; CHECK: OpCapability Int64 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %int = OpTypeInt 64 0 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, RayQueryKHR_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability RayQueryKHR |
| OpExtension "SPV_KHR_ray_query" |
| ; CHECK-NOT: OpCapability RayQueryKHR |
| ; CHECK-NOT: OpExtension "SPV_KHR_ray_query" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Vertex %main "main" %out_var_TEXCOORD1 |
| OpSource HLSL 660 |
| OpName %out_var_TEXCOORD1 "out.var.TEXCOORD1" |
| OpName %main "main" |
| OpDecorate %out_var_TEXCOORD1 Flat |
| OpDecorate %out_var_TEXCOORD1 Location 0 |
| %uint = OpTypeInt 32 0 |
| %uint_1234 = OpConstant %uint 1234 |
| %_ptr_Output_uint = OpTypePointer Output %uint |
| %void = OpTypeVoid |
| %7 = OpTypeFunction %void |
| %out_var_TEXCOORD1 = OpVariable %_ptr_Output_uint Output |
| %main = OpFunction %void None %7 |
| %8 = OpLabel |
| OpStore %out_var_TEXCOORD1 %uint_1234 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| RayQueryKHR_RemainsWhenAccelerationStructureIsPresent) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability RayQueryKHR |
| OpExtension "SPV_KHR_ray_query" |
| ; CHECK: OpCapability RayQueryKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_query" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| OpDecorate %var_bvh DescriptorSet 0 |
| OpDecorate %var_bvh Binding 0 |
| %bvh = OpTypeAccelerationStructureKHR |
| %ptr_bvh = OpTypePointer UniformConstant %bvh |
| %void = OpTypeVoid |
| %20 = OpTypeFunction %void |
| %var_bvh = OpVariable %ptr_bvh UniformConstant |
| %main = OpFunction %void None %20 |
| %30 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, RayQueryKHR_RemainsWhenRayQueryTypeIsPresent) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability RayQueryKHR |
| OpExtension "SPV_KHR_ray_query" |
| ; CHECK: OpCapability RayQueryKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_query" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| %query = OpTypeRayQueryKHR |
| %void = OpTypeVoid |
| %20 = OpTypeFunction %void |
| %ptr_query = OpTypePointer Function %query |
| %main = OpFunction %void None %20 |
| %30 = OpLabel |
| %var_query = OpVariable %ptr_query Function |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, RayQueryKHR_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability RayQueryKHR |
| OpExtension "SPV_KHR_ray_query" |
| ; CHECK: OpCapability RayQueryKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_query" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| OpDecorate %bvh DescriptorSet 0 |
| OpDecorate %bvh Binding 0 |
| OpDecorate %output DescriptorSet 0 |
| OpDecorate %output Binding 1 |
| OpDecorate %_runtimearr_float ArrayStride 4 |
| OpMemberDecorate %type_RWStructuredBuffer_float 0 Offset 0 |
| OpDecorate %type_RWStructuredBuffer_float BufferBlock |
| %float = OpTypeFloat 32 |
| %float_0 = OpConstant %float 0 |
| %int = OpTypeInt 32 1 |
| %v3float = OpTypeVector %float 3 |
| %12 = OpConstantComposite %v3float %float_0 %float_0 %float_0 |
| %int_0 = OpConstant %int 0 |
| %uint = OpTypeInt 32 0 |
| %uint_0 = OpConstant %uint 0 |
| %uint_1 = OpConstant %uint 1 |
| %accelerationStructureKHR = OpTypeAccelerationStructureKHR |
| %_ptr_UniformConstant_accelerationStructureKHR = OpTypePointer UniformConstant %accelerationStructureKHR |
| %_runtimearr_float = OpTypeRuntimeArray %float |
| %type_RWStructuredBuffer_float = OpTypeStruct %_runtimearr_float |
| %_ptr_Uniform_type_RWStructuredBuffer_float = OpTypePointer Uniform %type_RWStructuredBuffer_float |
| %void = OpTypeVoid |
| %20 = OpTypeFunction %void |
| %rayQueryKHR = OpTypeRayQueryKHR |
| %_ptr_Function_rayQueryKHR = OpTypePointer Function %rayQueryKHR |
| %bool = OpTypeBool |
| %_ptr_Uniform_float = OpTypePointer Uniform %float |
| %bvh = OpVariable %_ptr_UniformConstant_accelerationStructureKHR UniformConstant |
| %output = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_float Uniform |
| %main = OpFunction %void None %20 |
| %24 = OpLabel |
| %25 = OpVariable %_ptr_Function_rayQueryKHR Function |
| %26 = OpLoad %accelerationStructureKHR %bvh |
| OpRayQueryInitializeKHR %25 %26 %uint_0 %uint_0 %12 %float_0 %12 %float_0 |
| %27 = OpRayQueryProceedKHR %bool %25 |
| %28 = OpRayQueryGetIntersectionTypeKHR %uint %25 %uint_1 |
| %29 = OpIEqual %bool %28 %uint_1 |
| OpSelectionMerge %30 None |
| OpBranchConditional %29 %31 %30 |
| %31 = OpLabel |
| %32 = OpAccessChain %_ptr_Uniform_float %output %int_0 %uint_0 |
| OpStore %32 %float_0 |
| OpBranch %30 |
| %30 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| RayTracingKHR_RemainsWithIntersectionExecutionMode) { |
| const std::string kTest = R"( |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint IntersectionKHR %main "main" |
| OpSource HLSL 660 |
| OpName %main "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %4 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| RayTracingKHR_RemainsWithClosestHitExecutionMode) { |
| const std::string kTest = R"( |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint ClosestHitKHR %main "main" %a |
| OpSource HLSL 630 |
| OpName %Payload "Payload" |
| OpMemberName %Payload 0 "color" |
| OpName %a "a" |
| OpName %main "main" |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %Payload = OpTypeStruct %v4float |
| %ptr_payload = OpTypePointer IncomingRayPayloadKHR %Payload |
| %void = OpTypeVoid |
| %8 = OpTypeFunction %void |
| %a = OpVariable %ptr_payload IncomingRayPayloadKHR |
| %main = OpFunction %void None %8 |
| %9 = OpLabel |
| %10 = OpLoad %Payload %a |
| OpStore %a %10 |
| OpReturn |
| OpFunctionEnd |
| |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, RayTracingKHR_RemainsWithAnyHitExecutionMode) { |
| const std::string kTest = R"( |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint AnyHitKHR %main "main" %a |
| OpSource HLSL 630 |
| OpName %Payload "Payload" |
| OpMemberName %Payload 0 "color" |
| OpName %a "a" |
| OpName %main "main" |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %Payload = OpTypeStruct %v4float |
| %ptr_payload = OpTypePointer IncomingRayPayloadKHR %Payload |
| %void = OpTypeVoid |
| %8 = OpTypeFunction %void |
| %a = OpVariable %ptr_payload IncomingRayPayloadKHR |
| %main = OpFunction %void None %8 |
| %9 = OpLabel |
| %10 = OpLoad %Payload %a |
| OpStore %a %10 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, RayTracingKHR_RemainsWithMissExecutionMode) { |
| const std::string kTest = R"( |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint MissKHR %main "main" %a |
| OpSource HLSL 630 |
| OpName %Payload "Payload" |
| OpMemberName %Payload 0 "color" |
| OpName %a "a" |
| OpName %main "main" |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %Payload = OpTypeStruct %v4float |
| %ptr_payload = OpTypePointer IncomingRayPayloadKHR %Payload |
| %void = OpTypeVoid |
| %8 = OpTypeFunction %void |
| %a = OpVariable %ptr_payload IncomingRayPayloadKHR |
| %main = OpFunction %void None %8 |
| %9 = OpLabel |
| %10 = OpLoad %Payload %a |
| OpStore %a %10 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| RayTracingKHR_RemainsWithRayGenerationExecutionMode) { |
| const std::string kTest = R"( |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint RayGenerationKHR %main "main" |
| OpSource HLSL 630 |
| OpName %main "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %4 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| RayTracingKHR_RemainsWithCallableExecutionMode) { |
| const std::string kTest = R"( |
| ; CHECK: OpCapability RayTracingKHR |
| ; CHECK: OpExtension "SPV_KHR_ray_tracing" |
| OpCapability RayTracingKHR |
| OpExtension "SPV_KHR_ray_tracing" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint CallableKHR %main "main" %a |
| OpSource HLSL 660 |
| OpName %Payload "Payload" |
| OpMemberName %Payload 0 "data" |
| OpName %a "a" |
| OpName %main "main" |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %Payload = OpTypeStruct %v4float |
| %ptr_payload = OpTypePointer IncomingCallableDataKHR %Payload |
| %void = OpTypeVoid |
| %8 = OpTypeFunction %void |
| %a = OpVariable %ptr_payload IncomingCallableDataKHR |
| %main = OpFunction %void None %8 |
| %9 = OpLabel |
| %10 = OpLoad %Payload %a |
| OpStore %a %10 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| ImageMSArray_RemainsIfSampledIs2AndArrayedIs1) { |
| const std::string kTest = R"( |
| OpCapability ImageMSArray |
| ; CHECK: OpCapability ImageMSArray |
| OpCapability Shader |
| OpCapability StorageImageMultisample |
| OpCapability StorageImageReadWithoutFormat |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" |
| OpExecutionMode %main OriginUpperLeft |
| OpDecorate %var_image DescriptorSet 0 |
| OpDecorate %var_image Binding 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %f32 = OpTypeFloat 32 |
| %u32 = OpTypeInt 32 0 |
| %uint_2 = OpConstant %u32 2 |
| %uint_1 = OpConstant %u32 1 |
| %v2uint = OpTypeVector %u32 2 |
| %v4float = OpTypeVector %f32 4 |
| %image = OpTypeImage %f32 2D 2 1 1 2 Unknown |
| %ptr_image = OpTypePointer UniformConstant %image |
| %10 = OpConstantComposite %v2uint %uint_1 %uint_2 |
| %var_image = OpVariable %ptr_image UniformConstant |
| %main = OpFunction %void None %func |
| %main_lab = OpLabel |
| %18 = OpLoad %image %var_image |
| %19 = OpImageRead %v4float %18 %10 Sample %uint_2 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, ImageMSArray_RemovedIfNotUsed) { |
| const std::string kTest = R"( |
| OpCapability Shader |
| OpCapability ImageMSArray |
| ; CHECK-NOT: OpCapability ImageMSArray |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" %out_var_SV_Target |
| OpExecutionMode %main OriginUpperLeft |
| OpSource HLSL 660 |
| OpName %out_var_SV_Target "out.var.SV_Target" |
| OpName %main "main" |
| OpDecorate %out_var_SV_Target Location 0 |
| %float = OpTypeFloat 32 |
| %v4float = OpTypeVector %float 4 |
| %_ptr_Output_v4float = OpTypePointer Output %v4float |
| %void = OpTypeVoid |
| %7 = OpTypeFunction %void |
| %out_var_SV_Target = OpVariable %_ptr_Output_v4float Output |
| %main = OpFunction %void None %7 |
| %8 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, ImageMSArray_RemovedIfArrayedIsNot1) { |
| const std::string kTest = R"( |
| OpCapability ImageMSArray |
| ; CHECK-NOT: OpCapability ImageMSArray |
| OpCapability Shader |
| OpCapability StorageImageMultisample |
| OpCapability StorageImageReadWithoutFormat |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" |
| OpExecutionMode %main OriginUpperLeft |
| OpDecorate %var_image DescriptorSet 0 |
| OpDecorate %var_image Binding 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %f32 = OpTypeFloat 32 |
| %u32 = OpTypeInt 32 0 |
| %uint_2 = OpConstant %u32 2 |
| %uint_1 = OpConstant %u32 1 |
| %v2uint = OpTypeVector %u32 2 |
| %v4float = OpTypeVector %f32 4 |
| %image = OpTypeImage %f32 2D 2 0 1 2 Unknown |
| %ptr_image = OpTypePointer UniformConstant %image |
| %10 = OpConstantComposite %v2uint %uint_1 %uint_2 |
| %var_image = OpVariable %ptr_image UniformConstant |
| %main = OpFunction %void None %func |
| %main_lab = OpLabel |
| %18 = OpLoad %image %var_image |
| %19 = OpImageRead %v4float %18 %10 Sample %uint_2 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, ImageMSArray_RemovedIfSampledNot2) { |
| const std::string kTest = R"( |
| OpCapability ImageMSArray |
| ; CHECK-NOT: OpCapability ImageMSArray |
| OpCapability Shader |
| OpCapability StorageImageReadWithoutFormat |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %main "main" |
| OpExecutionMode %main OriginUpperLeft |
| OpDecorate %var_image DescriptorSet 0 |
| OpDecorate %var_image Binding 1 |
| %void = OpTypeVoid |
| %func = OpTypeFunction %void |
| %f32 = OpTypeFloat 32 |
| %u32 = OpTypeInt 32 0 |
| %uint_3 = OpConstant %u32 3 |
| %uint_2 = OpConstant %u32 2 |
| %uint_1 = OpConstant %u32 1 |
| %v3uint = OpTypeVector %u32 3 |
| %v4float = OpTypeVector %f32 4 |
| %image = OpTypeImage %f32 2D 2 1 0 2 Unknown |
| %ptr_image = OpTypePointer UniformConstant %image |
| %10 = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3 |
| %var_image = OpVariable %ptr_image UniformConstant |
| %main = OpFunction %void None %func |
| %main_lab = OpLabel |
| %18 = OpLoad %image %var_image |
| %19 = OpImageRead %v4float %18 %10 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Float64_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Float64 |
| ; CHECK-NOT: OpCapability Float64 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Float64_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Float64 |
| ; CHECK: OpCapability Float64 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %float = OpTypeFloat 64 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| ComputeDerivativeGroupQuads_ReamainsWithExecMode) { |
| const std::string kTest = R"( |
| OpCapability ComputeDerivativeGroupQuadsNV |
| OpCapability ComputeDerivativeGroupLinearNV |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupLinearNV |
| ; CHECK: OpCapability ComputeDerivativeGroupQuadsNV |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupLinearNV |
| OpCapability Shader |
| ; CHECK: OpExtension "SPV_NV_compute_shader_derivatives" |
| OpExtension "SPV_NV_compute_shader_derivatives" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 DerivativeGroupQuadsNV |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| ComputeDerivativeGroupLinear_ReamainsWithExecMode) { |
| const std::string kTest = R"( |
| OpCapability ComputeDerivativeGroupLinearNV |
| OpCapability ComputeDerivativeGroupQuadsNV |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupQuadsNV |
| ; CHECK: OpCapability ComputeDerivativeGroupLinearNV |
| ; CHECK-NOT: OpCapability ComputeDerivativeGroupQuadsNV |
| OpCapability Shader |
| ; CHECK: OpExtension "SPV_NV_compute_shader_derivatives" |
| OpExtension "SPV_NV_compute_shader_derivatives" |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| OpExecutionMode %1 DerivativeGroupLinearNV |
| %void = OpTypeVoid |
| %float = OpTypeFloat 64 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageImageReadWithoutFormat_RemovedIfUnused) { |
| const std::string kTest = R"( |
| OpCapability StorageImageReadWithoutFormat |
| ; CHECK-NOT: OpCapability StorageImageReadWithoutFormat |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" %out_var |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpDecorate %out_var Location 0 |
| %float = OpTypeFloat 32 |
| %float4 = OpTypeVector %float 4 |
| %float_0 = OpConstant %float 0 |
| %float4_0000 = OpConstantComposite %float4 %float_0 %float_0 %float_0 %float_0 |
| %ptr_float4 = OpTypePointer Output %float4 |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %out_var = OpVariable %ptr_float4 Output |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| OpStore %out_var %float4_0000 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageImageReadWithoutFormat_RemovedIfUnusedOpImageFetch) { |
| const std::string kTest = R"( |
| OpCapability StorageImageReadWithoutFormat |
| ; CHECK-NOT: OpCapability StorageImageReadWithoutFormat |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" %out_var |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpDecorate %out_var Location 0 |
| OpDecorate %texture DescriptorSet 0 |
| OpDecorate %texture Binding 1 |
| %float = OpTypeFloat 32 |
| %float4 = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int2 = OpTypeVector %int 2 |
| %type_image = OpTypeImage %float 2D 2 0 0 1 Unknown |
| %ptr_image = OpTypePointer UniformConstant %type_image |
| %int_0 = OpConstant %int 0 |
| %int2_00 = OpConstantComposite %int2 %int_0 %int_0 |
| %ptr_float4 = OpTypePointer Output %float4 |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %texture = OpVariable %ptr_image UniformConstant |
| %out_var = OpVariable %ptr_float4 Output |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| %11 = OpLoad %type_image %texture |
| %12 = OpImageFetch %float4 %11 %int2_00 Lod %int_0 |
| OpStore %out_var %12 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageImageReadWithoutFormat_RemainsWhenRequiredWithRead) { |
| const std::string kTest = R"( |
| OpCapability StorageImageReadWithoutFormat |
| ; CHECK: OpCapability StorageImageReadWithoutFormat |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" %out_var |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpDecorate %out_var Location 0 |
| OpDecorate %texture DescriptorSet 0 |
| OpDecorate %texture Binding 1 |
| %float = OpTypeFloat 32 |
| %float4 = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int2 = OpTypeVector %int 2 |
| %type_image = OpTypeImage %float 2D 2 0 0 1 Unknown |
| %ptr_image = OpTypePointer UniformConstant %type_image |
| %int_0 = OpConstant %int 0 |
| %int2_00 = OpConstantComposite %int2 %int_0 %int_0 |
| %ptr_float4 = OpTypePointer Output %float4 |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %texture = OpVariable %ptr_image UniformConstant |
| %out_var = OpVariable %ptr_float4 Output |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| %11 = OpLoad %type_image %texture |
| %12 = OpImageRead %float4 %11 %int2_00 Lod %int_0 |
| OpStore %out_var %12 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageImageReadWithoutFormat_RemainsWhenRequiredWithSparseRead) { |
| const std::string kTest = R"( |
| OpCapability StorageImageReadWithoutFormat |
| ; CHECK: OpCapability StorageImageReadWithoutFormat |
| OpCapability SparseResidency |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpDecorate %texture DescriptorSet 0 |
| OpDecorate %texture Binding 1 |
| %float = OpTypeFloat 32 |
| %float4 = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int2 = OpTypeVector %int 2 |
| %type_image = OpTypeImage %float 2D 2 0 0 2 Unknown |
| %struct = OpTypeStruct %int %float4 |
| %ptr_image = OpTypePointer UniformConstant %type_image |
| %int_0 = OpConstant %int 0 |
| %int2_00 = OpConstantComposite %int2 %int_0 %int_0 |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %texture = OpVariable %ptr_image UniformConstant |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| %11 = OpLoad %type_image %texture |
| %12 = OpImageSparseRead %struct %11 %int2_00 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| StorageImageReadWithoutFormat_RemovedWithReadOnSubpassData) { |
| const std::string kTest = R"( |
| OpCapability StorageImageReadWithoutFormat |
| ; CHECK-NOT: OpCapability StorageImageReadWithoutFormat |
| OpCapability InputAttachment |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint Fragment %PSMain "PSMain" %out_var |
| OpExecutionMode %PSMain OriginUpperLeft |
| OpDecorate %out_var Location 0 |
| OpDecorate %texture DescriptorSet 0 |
| OpDecorate %texture Binding 1 |
| %float = OpTypeFloat 32 |
| %float4 = OpTypeVector %float 4 |
| %int = OpTypeInt 32 1 |
| %int2 = OpTypeVector %int 2 |
| %type_image = OpTypeImage %float SubpassData 2 0 0 2 Unknown |
| %ptr_image = OpTypePointer UniformConstant %type_image |
| %int_0 = OpConstant %int 0 |
| %int2_00 = OpConstantComposite %int2 %int_0 %int_0 |
| %ptr_float4 = OpTypePointer Output %float4 |
| %void = OpTypeVoid |
| %9 = OpTypeFunction %void |
| %texture = OpVariable %ptr_image UniformConstant |
| %out_var = OpVariable %ptr_float4 Output |
| %PSMain = OpFunction %void None %9 |
| %10 = OpLabel |
| %11 = OpLoad %type_image %texture |
| %12 = OpImageRead %float4 %11 %int2_00 |
| OpStore %out_var %12 |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, PhysicalStorageBuffer_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability PhysicalStorageBufferAddresses |
| ; CHECK-NOT: OpCapability PhysicalStorageBufferAddresses |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| PhysicalStorageBuffer_RemainsWithOpTypeForwardPointer) { |
| const std::string kTest = R"( |
| OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %struct = OpTypeStruct %int |
| OpTypeForwardPointer %ptr PhysicalStorageBuffer |
| %ptr = OpTypePointer PhysicalStorageBuffer %struct |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| PhysicalStorageBuffer_RemainsWithPhysicalStorageBufferStorage) { |
| const std::string kTest = R"( |
| OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %struct = OpTypeStruct %int |
| %ptr = OpTypePointer PhysicalStorageBuffer %struct |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| PhysicalStorageBuffer_RemainsWithRestrictDecoration) { |
| const std::string kTest = R"( |
| OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| OpDecorate %var RestrictPointer |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %struct = OpTypeStruct %int |
| %ptr = OpTypePointer Function %struct |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %6 = OpLabel |
| %var = OpVariable %ptr Function |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| PhysicalStorageBuffer_RemainsWithAliasedDecoration) { |
| const std::string kTest = R"( |
| OpCapability PhysicalStorageBufferAddresses |
| ; CHECK: OpCapability PhysicalStorageBufferAddresses |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %main "main" |
| OpExecutionMode %main LocalSize 1 2 4 |
| OpDecorate %var AliasedPointer |
| %void = OpTypeVoid |
| %int = OpTypeInt 32 0 |
| %struct = OpTypeStruct %int |
| %ptr = OpTypePointer Function %struct |
| %3 = OpTypeFunction %void |
| %main = OpFunction %void None %3 |
| %6 = OpLabel |
| %var = OpVariable %ptr Function |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Float16_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Float16 |
| ; CHECK-NOT: OpCapability Float16 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Float16_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Float16 |
| ; CHECK: OpCapability Float16 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %float = OpTypeFloat 16 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Int16_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability Int16 |
| ; CHECK-NOT: OpCapability Int16 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, Int16_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Int16 |
| ; CHECK: OpCapability Int16 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %int = OpTypeInt 16 1 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, UInt16_RemainsWhenUsed) { |
| const std::string kTest = R"( |
| OpCapability Int16 |
| ; CHECK: OpCapability Int16 |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
| %uint = OpTypeInt 16 0 |
| %3 = OpTypeFunction %void |
| %1 = OpFunction %void None %3 |
| %6 = OpLabel |
| OpReturn |
| OpFunctionEnd; |
| )"; |
| const auto result = |
| SinglePassRunAndMatch<TrimCapabilitiesPass>(kTest, /* skip_nop= */ false); |
| EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange); |
| } |
| |
| TEST_F(TrimCapabilitiesPassTest, |
| VulkanMemoryModelDeviceScope_RemovedWhenUnused) { |
| const std::string kTest = R"( |
| OpCapability VulkanMemoryModelDeviceScope |
| ; CHECK-NOT: OpCapability VulkanMemoryModelDeviceScope |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %1 "main" |
| %void = OpTypeVoid |
|