1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <string> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 18fd4e5da5Sopenharmony_ci#include "spirv-tools/optimizer.hpp" 19fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 20fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace opt { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_ciusing StripNonSemanticInfoTest = PassTest<::testing::Test>; 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_ci// This test acts as an end-to-end code example on how to strip 29fd4e5da5Sopenharmony_ci// reflection info from a SPIR-V module. Use this code pattern 30fd4e5da5Sopenharmony_ci// when you have compiled HLSL code with Glslang or DXC using 31fd4e5da5Sopenharmony_ci// option -fhlsl_functionality1 to insert reflection information, 32fd4e5da5Sopenharmony_ci// but then want to filter out the extra instructions before sending 33fd4e5da5Sopenharmony_ci// it to a driver that does not implement VK_GOOGLE_hlsl_functionality1. 34fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripReflectEnd2EndExample) { 35fd4e5da5Sopenharmony_ci // This is a non-sensical example, but exercises the instructions. 36fd4e5da5Sopenharmony_ci std::string before = R"(OpCapability Shader 37fd4e5da5Sopenharmony_ciOpCapability Linkage 38fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_decorate_string" 39fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_hlsl_functionality1" 40fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 41fd4e5da5Sopenharmony_ciOpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar" 42fd4e5da5Sopenharmony_ciOpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness" 43fd4e5da5Sopenharmony_ci%void = OpTypeVoid 44fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 45fd4e5da5Sopenharmony_ci)"; 46fd4e5da5Sopenharmony_ci SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); 47fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary_in; 48fd4e5da5Sopenharmony_ci tools.Assemble(before, &binary_in); 49fd4e5da5Sopenharmony_ci 50fd4e5da5Sopenharmony_ci // Instantiate the optimizer, and run the strip-nonsemantic-info 51fd4e5da5Sopenharmony_ci // pass over the |binary_in| module, and place the modified module 52fd4e5da5Sopenharmony_ci // into |binary_out|. 53fd4e5da5Sopenharmony_ci spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_1); 54fd4e5da5Sopenharmony_ci optimizer.RegisterPass(spvtools::CreateStripNonSemanticInfoPass()); 55fd4e5da5Sopenharmony_ci std::vector<uint32_t> binary_out; 56fd4e5da5Sopenharmony_ci optimizer.Run(binary_in.data(), binary_in.size(), &binary_out); 57fd4e5da5Sopenharmony_ci 58fd4e5da5Sopenharmony_ci // Check results 59fd4e5da5Sopenharmony_ci std::string disassembly; 60fd4e5da5Sopenharmony_ci tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly); 61fd4e5da5Sopenharmony_ci std::string after = R"(OpCapability Shader 62fd4e5da5Sopenharmony_ciOpCapability Linkage 63fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 64fd4e5da5Sopenharmony_ci%void = OpTypeVoid 65fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 66fd4e5da5Sopenharmony_ci)"; 67fd4e5da5Sopenharmony_ci EXPECT_THAT(disassembly, testing::Eq(after)); 68fd4e5da5Sopenharmony_ci} 69fd4e5da5Sopenharmony_ci 70fd4e5da5Sopenharmony_ci// This test is functionally the same as the end-to-end test above, 71fd4e5da5Sopenharmony_ci// but uses the test SinglePassRunAndCheck test fixture instead. 72fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripHlslSemantic) { 73fd4e5da5Sopenharmony_ci // This is a non-sensical example, but exercises the instructions. 74fd4e5da5Sopenharmony_ci std::string before = R"(OpCapability Shader 75fd4e5da5Sopenharmony_ciOpCapability Linkage 76fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_decorate_string" 77fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_hlsl_functionality1" 78fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 79fd4e5da5Sopenharmony_ciOpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar" 80fd4e5da5Sopenharmony_ciOpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness" 81fd4e5da5Sopenharmony_ci%void = OpTypeVoid 82fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 83fd4e5da5Sopenharmony_ci)"; 84fd4e5da5Sopenharmony_ci std::string after = R"(OpCapability Shader 85fd4e5da5Sopenharmony_ciOpCapability Linkage 86fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 87fd4e5da5Sopenharmony_ci%void = OpTypeVoid 88fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 89fd4e5da5Sopenharmony_ci)"; 90fd4e5da5Sopenharmony_ci 91fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false); 92fd4e5da5Sopenharmony_ci} 93fd4e5da5Sopenharmony_ci 94fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripHlslCounterBuffer) { 95fd4e5da5Sopenharmony_ci std::string before = R"(OpCapability Shader 96fd4e5da5Sopenharmony_ciOpCapability Linkage 97fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_hlsl_functionality1" 98fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 99fd4e5da5Sopenharmony_ciOpDecorateId %void HlslCounterBufferGOOGLE %float 100fd4e5da5Sopenharmony_ci%void = OpTypeVoid 101fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 102fd4e5da5Sopenharmony_ci)"; 103fd4e5da5Sopenharmony_ci std::string after = R"(OpCapability Shader 104fd4e5da5Sopenharmony_ciOpCapability Linkage 105fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 106fd4e5da5Sopenharmony_ci%void = OpTypeVoid 107fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 108fd4e5da5Sopenharmony_ci)"; 109fd4e5da5Sopenharmony_ci 110fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false); 111fd4e5da5Sopenharmony_ci} 112fd4e5da5Sopenharmony_ci 113fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripHlslSemanticOnMember) { 114fd4e5da5Sopenharmony_ci // This is a non-sensical example, but exercises the instructions. 115fd4e5da5Sopenharmony_ci std::string before = R"(OpCapability Shader 116fd4e5da5Sopenharmony_ciOpCapability Linkage 117fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_decorate_string" 118fd4e5da5Sopenharmony_ciOpExtension "SPV_GOOGLE_hlsl_functionality1" 119fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 120fd4e5da5Sopenharmony_ciOpMemberDecorateStringGOOGLE %struct 0 HlslSemanticGOOGLE "foobar" 121fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 122fd4e5da5Sopenharmony_ci%_struct_3 = OpTypeStruct %float 123fd4e5da5Sopenharmony_ci)"; 124fd4e5da5Sopenharmony_ci std::string after = R"(OpCapability Shader 125fd4e5da5Sopenharmony_ciOpCapability Linkage 126fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 127fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 128fd4e5da5Sopenharmony_ci%_struct_3 = OpTypeStruct %float 129fd4e5da5Sopenharmony_ci)"; 130fd4e5da5Sopenharmony_ci 131fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false); 132fd4e5da5Sopenharmony_ci} 133fd4e5da5Sopenharmony_ci 134fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripNonSemanticImport) { 135fd4e5da5Sopenharmony_ci std::string text = R"( 136fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtension "SPV_KHR_non_semantic_info" 137fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInstImport 138fd4e5da5Sopenharmony_ciOpCapability Shader 139fd4e5da5Sopenharmony_ciOpCapability Linkage 140fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info" 141fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test" 142fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 143fd4e5da5Sopenharmony_ci)"; 144fd4e5da5Sopenharmony_ci 145fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 146fd4e5da5Sopenharmony_ci} 147fd4e5da5Sopenharmony_ci 148fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripNonSemanticGlobal) { 149fd4e5da5Sopenharmony_ci std::string text = R"( 150fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst 151fd4e5da5Sopenharmony_ciOpCapability Shader 152fd4e5da5Sopenharmony_ciOpCapability Linkage 153fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info" 154fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test" 155fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 156fd4e5da5Sopenharmony_ci%void = OpTypeVoid 157fd4e5da5Sopenharmony_ci%1 = OpExtInst %void %ext 1 158fd4e5da5Sopenharmony_ci)"; 159fd4e5da5Sopenharmony_ci 160fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 161fd4e5da5Sopenharmony_ci} 162fd4e5da5Sopenharmony_ci 163fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripNonSemanticInFunction) { 164fd4e5da5Sopenharmony_ci std::string text = R"( 165fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst 166fd4e5da5Sopenharmony_ciOpCapability Shader 167fd4e5da5Sopenharmony_ciOpCapability Linkage 168fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info" 169fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test" 170fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 171fd4e5da5Sopenharmony_ci%void = OpTypeVoid 172fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void 173fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn 174fd4e5da5Sopenharmony_ci%entry = OpLabel 175fd4e5da5Sopenharmony_ci%1 = OpExtInst %void %ext 1 %foo 176fd4e5da5Sopenharmony_ciOpReturn 177fd4e5da5Sopenharmony_ciOpFunctionEnd 178fd4e5da5Sopenharmony_ci)"; 179fd4e5da5Sopenharmony_ci 180fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 181fd4e5da5Sopenharmony_ci} 182fd4e5da5Sopenharmony_ci 183fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripNonSemanticAfterFunction) { 184fd4e5da5Sopenharmony_ci std::string text = R"( 185fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst 186fd4e5da5Sopenharmony_ciOpCapability Shader 187fd4e5da5Sopenharmony_ciOpCapability Linkage 188fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info" 189fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test" 190fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 191fd4e5da5Sopenharmony_ci%void = OpTypeVoid 192fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void 193fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn 194fd4e5da5Sopenharmony_ci%entry = OpLabel 195fd4e5da5Sopenharmony_ciOpReturn 196fd4e5da5Sopenharmony_ciOpFunctionEnd 197fd4e5da5Sopenharmony_ci%1 = OpExtInst %void %ext 1 %foo 198fd4e5da5Sopenharmony_ci)"; 199fd4e5da5Sopenharmony_ci 200fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 201fd4e5da5Sopenharmony_ci} 202fd4e5da5Sopenharmony_ci 203fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, StripNonSemanticBetweenFunctions) { 204fd4e5da5Sopenharmony_ci std::string text = R"( 205fd4e5da5Sopenharmony_ci; CHECK-NOT: OpExtInst 206fd4e5da5Sopenharmony_ciOpCapability Shader 207fd4e5da5Sopenharmony_ciOpCapability Linkage 208fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info" 209fd4e5da5Sopenharmony_ci%ext = OpExtInstImport "NonSemantic.Test" 210fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 211fd4e5da5Sopenharmony_ci%void = OpTypeVoid 212fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void 213fd4e5da5Sopenharmony_ci%foo = OpFunction %void None %void_fn 214fd4e5da5Sopenharmony_ci%entry = OpLabel 215fd4e5da5Sopenharmony_ciOpReturn 216fd4e5da5Sopenharmony_ciOpFunctionEnd 217fd4e5da5Sopenharmony_ci%1 = OpExtInst %void %ext 1 %foo 218fd4e5da5Sopenharmony_ci%bar = OpFunction %void None %void_fn 219fd4e5da5Sopenharmony_ci%bar_entry = OpLabel 220fd4e5da5Sopenharmony_ciOpReturn 221fd4e5da5Sopenharmony_ciOpFunctionEnd 222fd4e5da5Sopenharmony_ci)"; 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 225fd4e5da5Sopenharmony_ci} 226fd4e5da5Sopenharmony_ci 227fd4e5da5Sopenharmony_ci// Make sure that strip reflect does not remove the debug info (OpString and 228fd4e5da5Sopenharmony_ci// OpLine). 229fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, DontStripDebug) { 230fd4e5da5Sopenharmony_ci std::string text = R"(OpCapability Shader 231fd4e5da5Sopenharmony_ciOpMemoryModel Logical Simple 232fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main" 233fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft 234fd4e5da5Sopenharmony_ci%2 = OpString "file" 235fd4e5da5Sopenharmony_ci%void = OpTypeVoid 236fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void 237fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %4 238fd4e5da5Sopenharmony_ci%5 = OpLabel 239fd4e5da5Sopenharmony_ciOpLine %2 1 1 240fd4e5da5Sopenharmony_ciOpReturn 241fd4e5da5Sopenharmony_ciOpFunctionEnd 242fd4e5da5Sopenharmony_ci)"; 243fd4e5da5Sopenharmony_ci 244fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<StripNonSemanticInfoPass>(text, text, false); 245fd4e5da5Sopenharmony_ci} 246fd4e5da5Sopenharmony_ci 247fd4e5da5Sopenharmony_ciTEST_F(StripNonSemanticInfoTest, RemovedNonSemanticDebugInfo) { 248fd4e5da5Sopenharmony_ci const std::string text = R"( 249fd4e5da5Sopenharmony_ci;CHECK-NOT: OpExtension "SPV_KHR_non_semantic_info 250fd4e5da5Sopenharmony_ci;CHECK-NOT: OpExtInstImport "NonSemantic.Shader.DebugInfo.100 251fd4e5da5Sopenharmony_ci;CHECK-NOT: OpExtInst %void {{%\w+}} DebugSource 252fd4e5da5Sopenharmony_ci;CHECK-NOT: OpExtInst %void {{%\w+}} DebugLine 253fd4e5da5Sopenharmony_ci OpCapability Shader 254fd4e5da5Sopenharmony_ci OpExtension "SPV_KHR_non_semantic_info" 255fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 256fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 257fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %PSMain "PSMain" %in_var_COLOR %out_var_SV_TARGET 258fd4e5da5Sopenharmony_ci OpExecutionMode %PSMain OriginUpperLeft 259fd4e5da5Sopenharmony_ci %5 = OpString "t.hlsl" 260fd4e5da5Sopenharmony_ci %6 = OpString "float" 261fd4e5da5Sopenharmony_ci %7 = OpString "color" 262fd4e5da5Sopenharmony_ci %8 = OpString "PSInput" 263fd4e5da5Sopenharmony_ci %9 = OpString "PSMain" 264fd4e5da5Sopenharmony_ci %10 = OpString "" 265fd4e5da5Sopenharmony_ci %11 = OpString "input" 266fd4e5da5Sopenharmony_ci OpName %in_var_COLOR "in.var.COLOR" 267fd4e5da5Sopenharmony_ci OpName %out_var_SV_TARGET "out.var.SV_TARGET" 268fd4e5da5Sopenharmony_ci OpName %PSMain "PSMain" 269fd4e5da5Sopenharmony_ci OpDecorate %in_var_COLOR Location 0 270fd4e5da5Sopenharmony_ci OpDecorate %out_var_SV_TARGET Location 0 271fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 272fd4e5da5Sopenharmony_ci %float = OpTypeFloat 32 273fd4e5da5Sopenharmony_ci %v4float = OpTypeVector %float 4 274fd4e5da5Sopenharmony_ci%_ptr_Input_v4float = OpTypePointer Input %v4float 275fd4e5da5Sopenharmony_ci%_ptr_Output_v4float = OpTypePointer Output %v4float 276fd4e5da5Sopenharmony_ci %void = OpTypeVoid 277fd4e5da5Sopenharmony_ci %uint_1 = OpConstant %uint 1 278fd4e5da5Sopenharmony_ci %uint_9 = OpConstant %uint 9 279fd4e5da5Sopenharmony_ci %21 = OpTypeFunction %void 280fd4e5da5Sopenharmony_ci%in_var_COLOR = OpVariable %_ptr_Input_v4float Input 281fd4e5da5Sopenharmony_ci%out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output 282fd4e5da5Sopenharmony_ci %13 = OpExtInst %void %1 DebugSource %5 283fd4e5da5Sopenharmony_ci %PSMain = OpFunction %void None %21 284fd4e5da5Sopenharmony_ci %22 = OpLabel 285fd4e5da5Sopenharmony_ci %23 = OpLoad %v4float %in_var_COLOR 286fd4e5da5Sopenharmony_ci OpStore %out_var_SV_TARGET %23 287fd4e5da5Sopenharmony_ci %24 = OpExtInst %void %1 DebugLine %13 %uint_9 %uint_9 %uint_1 %uint_1 288fd4e5da5Sopenharmony_ci OpReturn 289fd4e5da5Sopenharmony_ci OpFunctionEnd 290fd4e5da5Sopenharmony_ci)"; 291fd4e5da5Sopenharmony_ci SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true); 292fd4e5da5Sopenharmony_ci} 293fd4e5da5Sopenharmony_ci 294fd4e5da5Sopenharmony_ci} // namespace 295fd4e5da5Sopenharmony_ci} // namespace opt 296fd4e5da5Sopenharmony_ci} // namespace spvtools 297