Refactor: Compatible compute and graphics VerifyIO
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmUboMatrixPaddingTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief SPIR-V Assembly Tests for UBO matrix padding.
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSpvAsmUboMatrixPaddingTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28
29 namespace vkt
30 {
31 namespace SpirVAssembly
32 {
33
34 using namespace vk;
35 using std::map;
36 using std::string;
37 using std::vector;
38 using tcu::IVec3;
39 using tcu::RGBA;
40 using tcu::Vec4;
41
42 namespace
43 {
44
45 void addComputeUboMatrixPaddingTest (tcu::TestCaseGroup* group)
46 {
47         tcu::TestContext&       testCtx                 = group->getTestContext();
48         de::Random                      rnd                             (deStringHash(group->getName()));
49         const int                       numElements             = 128;
50
51         // Read input UBO containing and array of mat2x2 using no padding inside matrix. Output
52         // into output buffer containing floats. The input and output buffer data should match.
53         const string            shaderSource    =
54                 "                       OpCapability Shader\n"
55                 "                  %1 = OpExtInstImport \"GLSL.std.450\"\n"
56                 "                       OpMemoryModel Logical GLSL450\n"
57                 "                       OpEntryPoint GLCompute %main \"main\" %id\n"
58                 "                       OpExecutionMode %main LocalSize 1 1 1\n"
59                 "                       OpSource GLSL 430\n"
60                 "                       OpDecorate %id BuiltIn GlobalInvocationId\n"
61                 "                       OpDecorate %_arr_v4 ArrayStride 16\n"
62                 "                       OpMemberDecorate %Output 0 Offset 0\n"
63                 "                       OpDecorate %Output BufferBlock\n"
64                 "                       OpDecorate %dataOutput DescriptorSet 0\n"
65                 "                       OpDecorate %dataOutput Binding 1\n"
66                 "                       OpDecorate %_arr_mat2v2 ArrayStride 16\n"
67                 "                       OpMemberDecorate %Input 0 ColMajor\n"
68                 "                       OpMemberDecorate %Input 0 Offset 0\n"
69                 "                       OpMemberDecorate %Input 0 MatrixStride 8\n"
70                 "                       OpDecorate %Input Block\n"
71                 "                       OpDecorate %dataInput DescriptorSet 0\n"
72                 "                       OpDecorate %dataInput Binding 0\n"
73                 "               %void = OpTypeVoid\n"
74                 "                  %3 = OpTypeFunction %void\n"
75                 "                %u32 = OpTypeInt 32 0\n"
76                 " %_ptr_Function_uint = OpTypePointer Function %u32\n"
77                 "             %v3uint = OpTypeVector %u32 3\n"
78                 "  %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
79                 "                 %id = OpVariable %_ptr_Input_v3uint Input\n"
80                 "                %i32 = OpTypeInt 32 1\n"
81                 "              %int_0 = OpConstant %i32 0\n"
82                 "              %int_1 = OpConstant %i32 1\n"
83                 "             %uint_0 = OpConstant %u32 0\n"
84                 "             %uint_1 = OpConstant %u32 1\n"
85                 "             %uint_2 = OpConstant %u32 2\n"
86                 "             %uint_3 = OpConstant %u32 3\n"
87                 "    %_ptr_Input_uint = OpTypePointer Input %u32\n"
88                 "                %f32 = OpTypeFloat 32\n"
89                 "            %v4float = OpTypeVector %f32 4\n"
90                 "           %uint_128 = OpConstant %u32 128\n"
91                 "            %_arr_v4 = OpTypeArray %v4float %uint_128\n"
92                 "             %Output = OpTypeStruct %_arr_v4\n"
93                 "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
94                 "         %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
95                 "            %v2float = OpTypeVector %f32 2\n"
96                 "        %mat2v2float = OpTypeMatrix %v2float 2\n"
97                 "        %_arr_mat2v2 = OpTypeArray %mat2v2float %uint_128\n"
98                 "              %Input = OpTypeStruct %_arr_mat2v2\n"
99                 " %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
100                 "          %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
101                 " %_ptr_Uniform_float = OpTypePointer Uniform %f32\n"
102                 "               %main = OpFunction %void None %3\n"
103                 "                  %5 = OpLabel\n"
104                 "                  %i = OpVariable %_ptr_Function_uint Function\n"
105                 "                 %14 = OpAccessChain %_ptr_Input_uint %id %uint_0\n"
106                 "                 %15 = OpLoad %u32 %14\n"
107                 "                       OpStore %i %15\n"
108                 "                %idx = OpLoad %u32 %i\n"
109                 "                 %34 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_0 %uint_0\n"
110                 "                 %35 = OpLoad %f32 %34\n"
111                 "                 %36 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_0\n"
112                 "                       OpStore %36 %35\n"
113                 "                 %40 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_0 %uint_1\n"
114                 "                 %41 = OpLoad %f32 %40\n"
115                 "                 %42 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_1\n"
116                 "                       OpStore %42 %41\n"
117                 "                 %46 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_1 %uint_0\n"
118                 "                 %47 = OpLoad %f32 %46\n"
119                 "                 %49 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_2\n"
120                 "                       OpStore %49 %47\n"
121                 "                 %52 = OpAccessChain %_ptr_Uniform_float %dataInput %int_0 %idx %int_1 %uint_1\n"
122                 "                 %53 = OpLoad %f32 %52\n"
123                 "                 %55 = OpAccessChain %_ptr_Uniform_float %dataOutput %int_0 %idx %uint_3\n"
124                 "                       OpStore %55 %53\n"
125                 "                       OpReturn\n"
126                 "                       OpFunctionEnd\n";
127
128                 vector<tcu::Vec4>               inputData;
129                 ComputeShaderSpec               spec;
130
131                 inputData.reserve(numElements);
132                 for (deUint32 numIdx = 0; numIdx < numElements; ++numIdx)
133                         inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()));
134
135                 spec.assembly                   = shaderSource;
136                 spec.numWorkGroups              = IVec3(numElements, 1, 1);
137
138                 spec.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER));
139                 // Shader is expected to pass the input data by treating the input vec4 as mat2x2
140                 spec.outputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData))));
141
142                 group->addChild(new SpvAsmComputeShaderCase(testCtx, "mat2x2", "Tests mat2x2 member in UBO struct without padding (treated as vec4).", spec));
143         }
144 }
145
146 void addGraphicsUboMatrixPaddingTest (tcu::TestCaseGroup* group)
147 {
148         de::Random                                      rnd                                     (deStringHash(group->getName()));
149         map<string, string>                     fragments;
150         const deUint32                          numDataPoints           = 128;
151         RGBA                                            defaultColors[4];
152         GraphicsResources                       resources;
153
154         SpecConstants                           noSpecConstants;
155         PushConstants                           noPushConstants;
156         GraphicsInterfaces                      noInterfaces;
157         std::vector<std::string>        noFeatures;
158         std::vector<std::string>        noExtensions;
159         VulkanFeatures                          vulkanFeatures = VulkanFeatures();
160
161         vector<tcu::Vec4> inputData(numDataPoints);
162         for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
163                 inputData[numIdx] = tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat());
164
165         resources.inputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER));
166         // Shader is expected to pass the input data by treating the input vec4 as mat2x2
167         resources.outputs.push_back(Resource(BufferSp(new Vec4Buffer(inputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
168
169         getDefaultColors(defaultColors);
170
171         fragments["pre_main"]   =
172                 "             %uint_128 = OpConstant %u32 128\n"
173                 "    %_arr_v4f_uint_128 = OpTypeArray %v4f32 %uint_128\n"
174                 "               %Output = OpTypeStruct %_arr_v4f_uint_128\n"
175                 "  %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
176                 "           %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
177                 "              %mat2v2f = OpTypeMatrix %v2f32 2\n"
178                 "%_arr_mat2v2f_uint_128 = OpTypeArray %mat2v2f %uint_128\n"
179                 "                %Input = OpTypeStruct %_arr_mat2v2f_uint_128\n"
180                 "   %_ptr_Uniform_Input = OpTypePointer Uniform %Input\n"
181                 "            %dataInput = OpVariable %_ptr_Uniform_Input Uniform\n"
182                 "       %_ptr_Uniform_f = OpTypePointer Uniform %f32\n"
183                 "            %c_i32_128 = OpConstant %i32 128\n";
184
185         fragments["decoration"] =
186                 "                         OpDecorate %_arr_v4f_uint_128 ArrayStride 16\n"
187                 "                         OpMemberDecorate %Output 0 Offset 0\n"
188                 "                         OpDecorate %Output BufferBlock\n"
189                 "                         OpDecorate %dataOutput DescriptorSet 0\n"
190                 "                         OpDecorate %dataOutput Binding 1\n"
191                 "                         OpDecorate %_arr_mat2v2f_uint_128 ArrayStride 16\n"
192                 "                         OpMemberDecorate %Input 0 ColMajor\n"
193                 "                         OpMemberDecorate %Input 0 Offset 0\n"
194                 "                         OpMemberDecorate %Input 0 MatrixStride 8\n"
195                 "                         OpDecorate %Input Block\n"
196                 "                         OpDecorate %dataInput DescriptorSet 0\n"
197                 "                         OpDecorate %dataInput Binding 0\n";
198
199         // Read input UBO containing and array of mat2x2 using no padding inside matrix. Output
200         // into output buffer containing floats. The input and output buffer data should match.
201         // The whole array is handled inside a for loop.
202         fragments["testfun"]    =
203                 "            %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
204                 "                %param = OpFunctionParameter %v4f32\n"
205
206                 "                %entry = OpLabel\n"
207                 "                    %i = OpVariable %fp_i32 Function\n"
208                 "                         OpStore %i %c_i32_0\n"
209                 "                         OpBranch %loop\n"
210
211                 "                 %loop = OpLabel\n"
212                 "                   %15 = OpLoad %i32 %i\n"
213                 "                   %lt = OpSLessThan %bool %15 %c_i32_128\n"
214                 "                         OpLoopMerge %merge %inc None\n"
215                 "                         OpBranchConditional %lt %write %merge\n"
216
217                 "                %write = OpLabel\n"
218                 "                   %30 = OpLoad %i32 %i\n"
219                 "                   %34 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_0 %c_u32_0\n"
220                 "                   %35 = OpLoad %f32 %34\n"
221                 "                   %36 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_0\n"
222                 "                         OpStore %36 %35\n"
223                 "                   %40 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_0 %c_u32_1\n"
224                 "                   %41 = OpLoad %f32 %40\n"
225                 "                   %42 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_1\n"
226                 "                         OpStore %42 %41\n"
227                 "                   %46 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_1 %c_u32_0\n"
228                 "                   %47 = OpLoad %f32 %46\n"
229                 "                   %49 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_2\n"
230                 "                         OpStore %49 %47\n"
231                 "                   %52 = OpAccessChain %_ptr_Uniform_f %dataInput %c_i32_0 %30 %c_i32_1 %c_u32_1\n"
232                 "                   %53 = OpLoad %f32 %52\n"
233                 "                   %55 = OpAccessChain %_ptr_Uniform_f %dataOutput %c_i32_0 %30 %c_u32_3\n"
234                 "                         OpStore %55 %53\n"
235                 "                         OpBranch %inc\n"
236
237                 "                  %inc = OpLabel\n"
238                 "                   %37 = OpLoad %i32 %i\n"
239                 "                   %39 = OpIAdd %i32 %37 %c_i32_1\n"
240                 "                         OpStore %i %39\n"
241                 "                         OpBranch %loop\n"
242
243                 "                %merge = OpLabel\n"
244                 "                         OpReturnValue %param\n"
245
246                 "                         OpFunctionEnd\n";
247
248         resources.inputs.back().setDescriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
249
250         vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
251         vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
252         createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, "mat2x2_vert", defaultColors, defaultColors, fragments, noSpecConstants,
253                                            noPushConstants, resources, noInterfaces, noExtensions, noFeatures, vulkanFeatures, group);
254
255         createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "mat2x2_tessc", defaultColors, defaultColors, fragments, noSpecConstants,
256                                            noPushConstants, resources, noInterfaces, noExtensions, noFeatures, vulkanFeatures, group);
257
258         createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "mat2x2_tesse", defaultColors, defaultColors, fragments, noSpecConstants,
259                                            noPushConstants, resources, noInterfaces, noExtensions, noFeatures, vulkanFeatures, group);
260
261         createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, "mat2x2_geom", defaultColors, defaultColors, fragments, noSpecConstants,
262                                            noPushConstants, resources, noInterfaces, noExtensions, noFeatures, vulkanFeatures, group);
263
264         vulkanFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
265         vulkanFeatures.coreFeatures.fragmentStoresAndAtomics = DE_TRUE;
266         createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, "mat2x2_frag", defaultColors, defaultColors, fragments, noSpecConstants,
267                                            noPushConstants, resources, noInterfaces, noExtensions, noFeatures, vulkanFeatures, group);
268 }
269
270 tcu::TestCaseGroup* createUboMatrixPaddingComputeGroup (tcu::TestContext& testCtx)
271 {
272         de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "ubo_padding", "Compute tests for UBO struct member packing."));
273         addComputeUboMatrixPaddingTest(group.get());
274
275         return group.release();
276 }
277
278 tcu::TestCaseGroup* createUboMatrixPaddingGraphicsGroup (tcu::TestContext& testCtx)
279 {
280         de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "ubo_padding", "Graphics tests for UBO struct member packing."));
281         addGraphicsUboMatrixPaddingTest(group.get());
282
283         return group.release();
284 }
285
286 } // SpirVAssembly
287 } // vkt