• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020-2022 Valve Corporation
2 // Copyright (c) 2020-2022 LunarG Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 // Debug Printf Instrumentation Tests.
17 
18 #include <string>
19 #include <vector>
20 
21 #include "test/opt/assembly_builder.h"
22 #include "test/opt/pass_fixture.h"
23 #include "test/opt/pass_utils.h"
24 
25 namespace spvtools {
26 namespace opt {
27 namespace {
28 
29 static const std::string kOutputDecorations = R"(
30 ; CHECK: OpDecorate [[output_buffer_type:%inst_printf_OutputBuffer]] Block
31 ; CHECK: OpMemberDecorate [[output_buffer_type]] 0 Offset 0
32 ; CHECK: OpMemberDecorate [[output_buffer_type]] 1 Offset 4
33 ; CHECK: OpMemberDecorate [[output_buffer_type]] 2 Offset 8
34 ; CHECK: OpDecorate [[output_buffer_var:%\w+]] DescriptorSet 7
35 ; CHECK: OpDecorate [[output_buffer_var]] Binding 3
36 )";
37 
38 static const std::string kOutputGlobals = R"(
39 ; CHECK: [[output_buffer_type]] = OpTypeStruct %uint %uint %_runtimearr_uint
40 ; CHECK: [[output_ptr_type:%\w+]] = OpTypePointer StorageBuffer [[output_buffer_type]]
41 ; CHECK: [[output_buffer_var]] = OpVariable [[output_ptr_type]] StorageBuffer
42 )";
43 
44 using InstDebugPrintfTest = PassTest<::testing::Test>;
45 
TEST_F(InstDebugPrintfTest,V4Float32)46 TEST_F(InstDebugPrintfTest, V4Float32) {
47   // SamplerState g_sDefault;
48   // Texture2D g_tColor;
49   //
50   // struct PS_INPUT
51   // {
52   //   float2 vBaseTexCoord : TEXCOORD0;
53   // };
54   //
55   // struct PS_OUTPUT
56   // {
57   //   float4 vDiffuse : SV_Target0;
58   // };
59   //
60   // PS_OUTPUT MainPs(PS_INPUT i)
61   // {
62   //   PS_OUTPUT o;
63   //
64   //   o.vDiffuse.rgba = g_tColor.Sample(g_sDefault, (i.vBaseTexCoord.xy).xy);
65   //   debugPrintfEXT("diffuse: %v4f", o.vDiffuse.rgba);
66   //   return o;
67   // }
68 
69   const std::string defs =
70       R"(OpCapability Shader
71 OpExtension "SPV_KHR_non_semantic_info"
72 %1 = OpExtInstImport "NonSemantic.DebugPrintf"
73 ; CHECK-NOT: OpExtension "SPV_KHR_non_semantic_info"
74 ; CHECK-NOT: %1 = OpExtInstImport "NonSemantic.DebugPrintf"
75 ; CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
76 OpMemoryModel Logical GLSL450
77 OpEntryPoint Fragment %2 "MainPs" %3 %4
78 ; CHECK: OpEntryPoint Fragment %2 "MainPs" %3 %4 %gl_FragCoord
79 OpExecutionMode %2 OriginUpperLeft
80 %5 = OpString "Color is %vn"
81 )";
82 
83   // clang-format off
84   const std::string decorates =
85       R"(OpDecorate %6 DescriptorSet 0
86 OpDecorate %6 Binding 1
87 OpDecorate %7 DescriptorSet 0
88 OpDecorate %7 Binding 0
89 OpDecorate %3 Location 0
90 OpDecorate %4 Location 0
91 ; CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
92 )" + kOutputDecorations + R"(
93 ; CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
94 )";
95 
96   const std::string globals =
97       R"(%void = OpTypeVoid
98 %9 = OpTypeFunction %void
99 %float = OpTypeFloat 32
100 %v2float = OpTypeVector %float 2
101 %v4float = OpTypeVector %float 4
102 %13 = OpTypeImage %float 2D 0 0 0 1 Unknown
103 %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
104 %6 = OpVariable %_ptr_UniformConstant_13 UniformConstant
105 %15 = OpTypeSampler
106 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
107 %7 = OpVariable %_ptr_UniformConstant_15 UniformConstant
108 %17 = OpTypeSampledImage %13
109 %_ptr_Input_v2float = OpTypePointer Input %v2float
110 %3 = OpVariable %_ptr_Input_v2float Input
111 %_ptr_Output_v4float = OpTypePointer Output %v4float
112 %4 = OpVariable %_ptr_Output_v4float Output
113 ; CHECK: %uint = OpTypeInt 32 0
114 ; CHECK: [[func_type:%\w+]] = OpTypeFunction %void %uint %uint %uint %uint %uint %uint
115 ; CHECK: %_runtimearr_uint = OpTypeRuntimeArray %uint
116 )" + kOutputGlobals + R"(
117 ; CHECK: %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
118 ; CHECK: %bool = OpTypeBool
119 ; CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float
120 ; CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
121 ; CHECK: %v4uint = OpTypeVector %uint 4
122 )";
123   // clang-format on
124 
125   const std::string main =
126       R"(%2 = OpFunction %void None %9
127 %20 = OpLabel
128 %21 = OpLoad %v2float %3
129 %22 = OpLoad %13 %6
130 %23 = OpLoad %15 %7
131 %24 = OpSampledImage %17 %22 %23
132 %25 = OpImageSampleImplicitLod %v4float %24 %21
133 %26 = OpExtInst %void %1 1 %5 %25
134 ; CHECK-NOT: %26 = OpExtInst %void %1 1 %5 %25
135 ; CHECK: %29 = OpCompositeExtract %float %25 0
136 ; CHECK: %30 = OpBitcast %uint %29
137 ; CHECK: %31 = OpCompositeExtract %float %25 1
138 ; CHECK: %32 = OpBitcast %uint %31
139 ; CHECK: %33 = OpCompositeExtract %float %25 2
140 ; CHECK: %34 = OpBitcast %uint %33
141 ; CHECK: %35 = OpCompositeExtract %float %25 3
142 ; CHECK: %36 = OpBitcast %uint %35
143 ; CHECK: %101 = OpFunctionCall %void %inst_printf_stream_write_6 %uint_36 %uint_5 %30 %32 %34 %36
144 ; CHECK: OpBranch %102
145 ; CHECK: %102 = OpLabel
146 OpStore %4 %25
147 OpReturn
148 OpFunctionEnd
149 )";
150 
151   const std::string output_func = R"(
152 ; CHECK: %inst_printf_stream_write_6 = OpFunction %void None [[func_type]]
153 ; CHECK: [[param_1:%\w+]] = OpFunctionParameter %uint
154 ; CHECK: [[param_2:%\w+]] = OpFunctionParameter %uint
155 ; CHECK: [[param_3:%\w+]] = OpFunctionParameter %uint
156 ; CHECK: [[param_4:%\w+]] = OpFunctionParameter %uint
157 ; CHECK: [[param_5:%\w+]] = OpFunctionParameter %uint
158 ; CHECK: [[param_6:%\w+]] = OpFunctionParameter %uint
159 ; CHECK: {{%\w+}} = OpLabel
160 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_1
161 ; CHECK: {{%\w+}} = OpAtomicIAdd %uint {{%\w+}} %uint_4 %uint_0 %uint_12
162 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_12
163 ; CHECK: {{%\w+}} = OpArrayLength %uint %inst_printf_output_buffer 2
164 ; CHECK: {{%\w+}} = OpULessThanEqual %bool {{%\w+}} {{%\w+}}
165 ; CHECK: OpSelectionMerge {{%\w+}} None
166 ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
167 ; CHECK: {{%\w+}} = OpLabel
168 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_0
169 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
170 ; CHECK: OpStore {{%\w+}} %uint_12
171 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_1
172 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
173 ; CHECK: OpStore {{%\w+}} %uint_23
174 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_2
175 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
176 ; CHECK: OpStore {{%\w+}} [[param_1]]
177 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3
178 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
179 ; CHECK: OpStore {{%\w+}} %uint_4
180 ; CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord
181 ; CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}}
182 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
183 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_4
184 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
185 ; CHECK: OpStore {{%\w+}} {{%\w+}}
186 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1
187 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_5
188 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
189 ; CHECK: OpStore {{%\w+}} {{%\w+}}
190 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7
191 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
192 ; CHECK: OpStore {{%\w+}} [[param_2]]
193 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_8
194 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
195 ; CHECK: OpStore {{%\w+}} [[param_3]]
196 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_9
197 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
198 ; CHECK: OpStore {{%\w+}} [[param_4]]
199 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_10
200 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
201 ; CHECK: OpStore {{%\w+}} [[param_5]]
202 ; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_11
203 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer_uint %inst_printf_output_buffer %uint_2 {{%\w+}}
204 ; CHECK: OpStore {{%\w+}} [[param_6]]
205 ; CHECK: OpBranch {{%\w+}}
206 ; CHECK: {{%\w+}} = OpLabel
207 ; CHECK: OpReturn
208 ; CHECK: OpFunctionEnd
209 )";
210 
211   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
212   SinglePassRunAndMatch<InstDebugPrintfPass>(
213       defs + decorates + globals + main + output_func, true);
214 }
215 
216 // TODO(greg-lunarg): Add tests to verify handling of these cases:
217 //
218 //   Compute shader
219 //   Geometry shader
220 //   Tessellation control shader
221 //   Tessellation eval shader
222 //   Vertex shader
223 
224 }  // namespace
225 }  // namespace opt
226 }  // namespace spvtools
227