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::RGBA;
41 using tcu::IVec3;
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<deUint32>		outputData;
54 
55 	outputData.reserve(numItems);
56 	for (deUint32 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_dummy = 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_dummy\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<deUint32>(outputData))));
123 
124 		group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), "Tests both labels pointing to a same branch.", spec));
125 	}
126 }
127 
addGraphicsSameLabelsTest(tcu::TestCaseGroup * group)128 void addGraphicsSameLabelsTest (tcu::TestCaseGroup* group)
129 {
130 	const deUint32			numItems			= 128;
131 	RGBA					defaultColors[4];
132 	GraphicsResources		resources;
133 	vector<deUint32>		outputData;
134 	VulkanFeatures			features;
135 
136 	outputData.reserve(numItems);
137 	for (deUint32 numIdx = 0; numIdx < numItems; ++numIdx)
138 		outputData.push_back(numIdx);
139 
140 	resources.outputs.push_back(Resource(BufferSp(new Buffer<deUint32>(outputData)), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
141 
142 	features.coreFeatures.vertexPipelineStoresAndAtomics	= true;
143 	features.coreFeatures.fragmentStoresAndAtomics			= true;
144 
145 	getDefaultColors(defaultColors);
146 
147 	for (int conditionIdx = 0; conditionIdx < DE_LENGTH_OF_ARRAY(conditions); ++conditionIdx)
148 	{
149 		map<string, string>		fragments;
150 		map<string, string>		specs;
151 		string					testName	= string("same_labels_") + conditions[conditionIdx];
152 
153 		fragments["pre_main"]				=
154 			"          %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_dummy = OpConstant %u32 2863311530\n";
164 
165 		fragments["decoration"]				=
166 			"                       OpDecorate %_arr_uint_uint_128 ArrayStride 4\n"
167 			"                       OpMemberDecorate %Output 0 Offset 0\n"
168 			"                       OpDecorate %Output BufferBlock\n"
169 			"                       OpDecorate %dataOutput DescriptorSet 0\n"
170 			"                       OpDecorate %dataOutput Binding 0\n";
171 
172 		const StringTemplate	testFun		(
173 			"          %test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
174 			"              %param = OpFunctionParameter %v4f32\n"
175 
176 			"              %entry = OpLabel\n"
177 			"                  %i = OpVariable %fp_u32 Function\n"
178 			"                       OpStore %i %c_u32_0\n"
179 			"                       OpBranch %loop\n"
180 
181 			"               %loop = OpLabel\n"
182 			"                 %15 = OpLoad %u32 %i\n"
183 			"                 %lt = OpSLessThan %bool %15 %c_u32_128\n"
184 			"                       OpLoopMerge %merge %inc None\n"
185 			"                       OpBranchConditional %lt %write %merge\n"
186 
187 			"              %write = OpLabel\n"
188 			"             %uint_i = OpLoad %u32 %i\n"
189 			"                       OpSelectionMerge %condmerge None\n"
190 			"                       OpBranchConditional %${condition} %live %live\n"
191 			"               %live = OpLabel\n"
192 			"                 %31 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
193 			"                       OpStore %31 %uint_i\n"
194 			"                       OpBranch %condmerge\n"
195 			"               %dead = OpLabel\n"
196 			"                 %35 = OpAccessChain %_ptr_Uniform_uint %dataOutput %c_u32_0 %uint_i\n"
197 			"                       OpStore %35 %uint_dummy\n"
198 			"                       OpBranch %condmerge\n"
199 			"          %condmerge = OpLabel\n"
200 			"                       OpBranch %inc\n"
201 
202 			"                %inc = OpLabel\n"
203 			"                 %37 = OpLoad %u32 %i\n"
204 			"                 %39 = OpIAdd %u32 %37 %c_u32_1\n"
205 			"                       OpStore %i %39\n"
206 			"                       OpBranch %loop\n"
207 
208 			"              %merge = OpLabel\n"
209 			"                       OpReturnValue %param\n"
210 
211 			"                       OpFunctionEnd\n");
212 
213 		specs["condition"]		= conditions[conditionIdx];
214 		fragments["testfun"]	= testFun.specialize(specs);
215 
216 		createTestsForAllStages(testName.c_str(), defaultColors, defaultColors, fragments, resources, vector<string>(), group, features);
217 	}
218 }
219 
220 } // anonymous
221 
createConditionalBranchComputeGroup(tcu::TestContext & testCtx)222 tcu::TestCaseGroup* createConditionalBranchComputeGroup (tcu::TestContext& testCtx)
223 {
224 	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "conditional_branch", "Compute tests for OpBranchConditional."));
225 	addComputeSameLabelsTest(group.get());
226 
227 	return group.release();
228 }
229 
createConditionalBranchGraphicsGroup(tcu::TestContext & testCtx)230 tcu::TestCaseGroup* createConditionalBranchGraphicsGroup (tcu::TestContext& testCtx)
231 {
232 	de::MovePtr<tcu::TestCaseGroup> group		(new tcu::TestCaseGroup(testCtx, "conditional_branch", "Graphics tests for OpBranchConditional."));
233 	addGraphicsSameLabelsTest(group.get());
234 
235 	return group.release();
236 }
237 
238 } // SpirVAssembly
239 } // vkt
240