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 OpBranchConditional instruction.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSpvAsmConditionalBranchTests.hpp"
25 #include "vktSpvAsmComputeShaderCase.hpp"
26 #include "vktSpvAsmComputeShaderTestUtil.hpp"
27 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
28 
29 #include "tcuStringTemplate.hpp"
30 
31 namespace vkt
32 {
33 namespace SpirVAssembly
34 {
35 
36 using namespace vk;
37 using std::map;
38 using std::string;
39 using std::vector;
40 using tcu::IVec3;
41 using tcu::RGBA;
42 using tcu::StringTemplate;
43 
44 namespace
45 {
46 
47 static const string conditions[] = {"true", "false"};
48 
addComputeSameLabelsTest(tcu::TestCaseGroup * group)49 void addComputeSameLabelsTest(tcu::TestCaseGroup *group)
50 {
51     tcu::TestContext &testCtx = group->getTestContext();
52     const int numItems        = 128;
53     vector<uint32_t> outputData;
54 
55     outputData.reserve(numItems);
56     for (uint32_t numIdx = 0; numIdx < numItems; ++numIdx)
57         outputData.push_back(numIdx);
58 
59     for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
60     {
61         ComputeShaderSpec spec;
62         map<string, string> specs;
63         string testName = string("same_labels_") + conditions[conditionIdx];
64 
65         const StringTemplate shaderSource(
66             "                         OpCapability Shader\n"
67             "                    %1 = OpExtInstImport \"GLSL.std.450\"\n"
68             "                         OpMemoryModel Logical GLSL450\n"
69             "                         OpEntryPoint GLCompute %main \"main\" %gl_GlobalInvocationID\n"
70             "                         OpExecutionMode %main LocalSize 1 1 1\n"
71             "                         OpSource GLSL 430\n"
72             "                         OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId\n"
73             "                         OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
74             "                         OpMemberDecorate %Output 0 Offset 0\n"
75             "                         OpDecorate %Output BufferBlock\n"
76             "                         OpDecorate %dataOutput DescriptorSet 0\n"
77             "                         OpDecorate %dataOutput Binding 0\n"
78             "                 %void = OpTypeVoid\n"
79             "                    %3 = OpTypeFunction %void\n"
80             "                 %uint = OpTypeInt 32 0\n"
81             "   %_ptr_Function_uint = OpTypePointer Function %uint\n"
82             "               %v3uint = OpTypeVector %uint 3\n"
83             "    %_ptr_Input_v3uint = OpTypePointer Input %v3uint\n"
84             "%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input\n"
85             "               %uint_0 = OpConstant %uint 0\n"
86             "      %_ptr_Input_uint = OpTypePointer Input %uint\n"
87             "                 %bool = OpTypeBool\n"
88             "                 %true = OpConstantTrue %bool\n"
89             "                %false = OpConstantFalse %bool\n"
90             "             %uint_128 = OpConstant %uint 128\n"
91             "   %_arr_uint_uint_128 = OpTypeArray %uint %uint_128\n"
92             "               %Output = OpTypeStruct %_arr_uint_uint_128\n"
93             "  %_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
94             "           %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
95             "    %_ptr_Uniform_uint = OpTypePointer Uniform %uint\n"
96             "          %uint_unused = OpConstant %uint 2863311530\n"
97             "                 %main = OpFunction %void None %3\n"
98             "                    %5 = OpLabel\n"
99             "                    %i = OpVariable %_ptr_Function_uint Function\n"
100             "                   %14 = OpAccessChain %_ptr_Input_uint %gl_GlobalInvocationID %uint_0\n"
101             "                   %15 = OpLoad %uint %14\n"
102             "                         OpStore %i %15\n"
103             "               %uint_i = OpLoad %uint %i\n"
104             "                         OpSelectionMerge %merge None\n"
105             "                         OpBranchConditional %${condition} %live %live\n"
106             "                 %live = OpLabel\n"
107             "                   %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
108             "                         OpStore %31 %uint_i\n"
109             "                         OpBranch %merge\n"
110             "                 %dead = OpLabel\n"
111             "                   %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %uint_0 %uint_i\n"
112             "                         OpStore %35 %uint_unused\n"
113             "                         OpBranch %merge\n"
114             "                %merge = OpLabel\n"
115             "                         OpReturn\n"
116             "                         OpFunctionEnd\n");
117 
118         specs["condition"] = conditions[conditionIdx];
119         spec.assembly      = shaderSource.specialize(specs);
120         spec.numWorkGroups = IVec3(numItems, 1, 1);
121 
122         spec.outputs.push_back(Resource(BufferSp(new Buffer<uint32_t>(outputData))));
123 
124         group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), spec));
125     }
126 }
127 
addGraphicsSameLabelsTest(tcu::TestCaseGroup * group)128 void addGraphicsSameLabelsTest(tcu::TestCaseGroup *group)
129 {
130     const uint32_t numItems = 128;
131     RGBA defaultColors[4];
132     GraphicsResources resources;
133     vector<uint32_t> outputData;
134     VulkanFeatures features;
135 
136     outputData.reserve(numItems);
137     for (uint32_t numIdx = 0; numIdx < numItems; ++numIdx)
138         outputData.push_back(numIdx);
139 
140     resources.outputs.push_back(
141         Resource(BufferSp(new Buffer<uint32_t>(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
142 
143     features.coreFeatures.vertexPipelineStoresAndAtomics = true;
144     features.coreFeatures.fragmentStoresAndAtomics       = true;
145 
146     getDefaultColors(defaultColors);
147 
148     for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
149     {
150         map<string, string> fragments;
151         map<string, string> specs;
152         string testName = string("same_labels_") + conditions[conditionIdx];
153 
154         fragments["pre_main"] = "          %c_u32_128 = OpConstant %u32 128\n"
155                                 "               %true = OpConstantTrue %bool\n"
156                                 "              %false = OpConstantFalse %bool\n"
157                                 " %_arr_uint_uint_128 = OpTypeArray %u32 %c_u32_128\n"
158                                 "             %Output = OpTypeStruct %_arr_uint_uint_128\n"
159                                 "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
160                                 "         %dataOutput = OpVariable %_ptr_Uniform_Output Uniform\n"
161                                 "  %_ptr_Uniform_uint = OpTypePointer Uniform %u32\n"
162                                 "             %fp_u32 = OpTypePointer Function %u32\n"
163                                 "        %uint_unused = OpConstant %u32 2863311530\n";
164 
165         fragments["decoration"] = "                       OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
166                                   "                       OpMemberDecorate %Output 0 Offset 0\n"
167                                   "                       OpDecorate %Output BufferBlock\n"
168                                   "                       OpDecorate %dataOutput DescriptorSet 0\n"
169                                   "                       OpDecorate %dataOutput Binding 0\n";
170 
171         const StringTemplate testFun(
172             "          %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
173             "              %param = OpFunctionParameter %v4f32\n"
174 
175             "              %entry = OpLabel\n"
176             "                  %i = OpVariable %fp_u32 Function\n"
177             "                       OpStore %i %c_u32_0\n"
178             "                       OpBranch %loop\n"
179 
180             "               %loop = OpLabel\n"
181             "                 %15 = OpLoad %u32 %i\n"
182             "                 %lt = OpSLessThan %bool %15 %c_u32_128\n"
183             "                       OpLoopMerge %merge %inc None\n"
184             "                       OpBranchConditional %lt %write %merge\n"
185 
186             "              %write = OpLabel\n"
187             "             %uint_i = OpLoad %u32 %i\n"
188             "                       OpSelectionMerge %condmerge None\n"
189             "                       OpBranchConditional %${condition} %live %live\n"
190             "               %live = OpLabel\n"
191             "                 %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
192             "                       OpStore %31 %uint_i\n"
193             "                       OpBranch %condmerge\n"
194             "               %dead = OpLabel\n"
195             "                 %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
196             "                       OpStore %35 %uint_unused\n"
197             "                       OpBranch %condmerge\n"
198             "          %condmerge = OpLabel\n"
199             "                       OpBranch %inc\n"
200 
201             "                %inc = OpLabel\n"
202             "                 %37 = OpLoad %u32 %i\n"
203             "                 %39 = OpIAdd %u32 %37 %c_u32_1\n"
204             "                       OpStore %i %39\n"
205             "                       OpBranch %loop\n"
206 
207             "              %merge = OpLabel\n"
208             "                       OpReturnValue %param\n"
209 
210             "                       OpFunctionEnd\n");
211 
212         specs["condition"]   = conditions[conditionIdx];
213         fragments["testfun"] = testFun.specialize(specs);
214 
215         createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, resources, vector<string>(),
216                                 group, features);
217     }
218 }
219 
220 } // namespace
221 
createConditionalBranchComputeGroup(tcu::TestContext & testCtx)222 tcu::TestCaseGroup *createConditionalBranchComputeGroup(tcu::TestContext &testCtx)
223 {
224     // Compute tests for OpBranchConditional.
225     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "conditional_branch"));
226     addComputeSameLabelsTest(group.get());
227 
228     return group.release();
229 }
230 
createConditionalBranchGraphicsGroup(tcu::TestContext & testCtx)231 tcu::TestCaseGroup *createConditionalBranchGraphicsGroup(tcu::TestContext &testCtx)
232 {
233     // Graphics tests for OpBranchConditional.
234     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "conditional_branch"));
235     addGraphicsSameLabelsTest(group.get());
236 
237     return group.release();
238 }
239 
240 } // namespace SpirVAssembly
241 } // namespace vkt
242