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