• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Max Varying Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineMaxVaryingsTests.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vktPipelineMakeUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vktPipelineSpecConstantUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTextureUtil.hpp"
41 
42 #include <string.h>
43 
44 namespace vkt
45 {
46 namespace pipeline
47 {
48 namespace
49 {
50 using namespace vk;
51 using de::UniquePtr;
52 using de::MovePtr;
53 
54 struct MaxVaryingsParam
55 {
56 	VkShaderStageFlags	outputStage;
57 	VkShaderStageFlags	inputStage;
58 	VkShaderStageFlags  stageToStressIO;
MaxVaryingsParamvkt::pipeline::__anon287b805a0111::MaxVaryingsParam59 	MaxVaryingsParam(VkShaderStageFlags out, VkShaderStageFlags in, VkShaderStageFlags stageToTest)
60 		: outputStage(out), inputStage(in), stageToStressIO(stageToTest) {}
61 };
62 
63 struct SelectedShaders
64 {
65 	VkShaderStageFlagBits	stage;
66 	std::string				shaderName;
SelectedShadersvkt::pipeline::__anon287b805a0111::SelectedShaders67 	SelectedShaders(VkShaderStageFlagBits shaderStage, std::string name)
68 		: stage(shaderStage), shaderName(name) {}
69 };
70 
71 // Helper functions
getShaderStageName(VkShaderStageFlags stage)72 std::string getShaderStageName(VkShaderStageFlags stage)
73 {
74 	switch (stage)
75 	{
76 		default:
77 			DE_FATAL("Unhandled stage!");
78 			return "";
79 		case VK_SHADER_STAGE_COMPUTE_BIT:
80 			return "compute";
81 		case VK_SHADER_STAGE_FRAGMENT_BIT:
82 			return "fragment";
83 		case VK_SHADER_STAGE_VERTEX_BIT:
84 			return "vertex";
85 		case VK_SHADER_STAGE_GEOMETRY_BIT:
86 			return "geometry";
87 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
88 			return "tess_control";
89 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
90 			return "tess_eval";
91 	}
92 }
93 
generateTestName(struct MaxVaryingsParam param)94 const std::string generateTestName (struct MaxVaryingsParam param)
95 {
96 	std::ostringstream result;
97 
98 	result << "test_" << getShaderStageName(param.stageToStressIO) << "_io_between_";
99 	result << getShaderStageName(param.outputStage) << "_";
100 	result << getShaderStageName(param.inputStage);
101 	return result.str();
102 }
103 
generateTestDescription()104 const std::string generateTestDescription ()
105 {
106 	std::string result("Tests to check max varyings per stage");
107 	return result;
108 }
109 
initPrograms(SourceCollections & programCollection,MaxVaryingsParam param)110 void initPrograms (SourceCollections& programCollection, MaxVaryingsParam param)
111 {
112 	const vk::ShaderBuildOptions	buildOptions	(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u);
113 
114 	// Vertex shader. SPIR-V generated from:
115 	// #version 450
116 	// layout(location = 0) in highp vec4 pos;
117 	// layout(constant_id = 0) const int arraySize = 1;
118 	// layout(location = 0) out ivec4 outputData[arraySize];
119 	// out gl_PerVertex {
120 	//    vec4 gl_Position;
121 	// };
122 	//
123 	// void main()
124 	// {
125 	//     gl_Position = pos;
126 	//     int i;
127 	//     for (i = 0; i &lt; arraySize; i++)
128 	//     {
129 	//         outputData[i] = ivec4(i);
130 	//     }
131 	// }
132 	std::ostringstream	vertex_out;
133 	vertex_out << "OpCapability Shader\n"
134 			   << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
135 			   << "OpMemoryModel Logical GLSL450\n"
136 			   << "OpEntryPoint Vertex %4 \"main\" %10 %14 %32\n"
137 			   << "OpMemberDecorate %8 0 BuiltIn Position\n"
138 			   << "OpDecorate %8 Block\n"
139 			   << "OpDecorate %14 Location 0\n"
140 			   << "OpDecorate %26 SpecId 0\n"
141 			   << "OpDecorate %32 Location 0\n"
142 			   << "%2 = OpTypeVoid\n"
143 			   << "%3 = OpTypeFunction %2\n"
144 			   << "%6 = OpTypeFloat 32\n"
145 			   << "%7 = OpTypeVector %6 4\n"
146 			   << "%8 = OpTypeStruct %7\n"
147 			   << "%9 = OpTypePointer Output %8\n"
148 			   << "%10 = OpVariable %9 Output\n"
149 			   << "%11 = OpTypeInt 32 1\n"
150 			   << "%12 = OpConstant %11 0\n"
151 			   << "%13 = OpTypePointer Input %7\n"
152 			   << "%14 = OpVariable %13 Input\n"
153 			   << "%16 = OpTypePointer Output %7\n"
154 			   << "%18 = OpTypePointer Function %11\n"
155 			   << "%26 = OpSpecConstant %11 1\n"
156 			   << "%27 = OpTypeBool\n"
157 			   << "%29 = OpTypeVector %11 4\n"
158 			   << "%30 = OpTypeArray %29 %26\n"
159 			   << "%31 = OpTypePointer Output %30\n"
160 			   << "%32 = OpVariable %31 Output\n"
161 			   << "%36 = OpTypePointer Output %29\n"
162 			   << "%39 = OpConstant %11 1\n"
163 			   << "%4 = OpFunction %2 None %3\n"
164 			   << "%5 = OpLabel\n"
165 			   << "%19 = OpVariable %18 Function\n"
166 			   << "%15 = OpLoad %7 %14\n"
167 			   << "%17 = OpAccessChain %16 %10 %12\n"
168 			   << "OpStore %17 %15\n"
169 			   << "OpStore %19 %12\n"
170 			   << "OpBranch %20\n"
171 			   << "%20 = OpLabel\n"
172 			   << "OpLoopMerge %22 %23 None\n"
173 			   << "OpBranch %24\n"
174 			   << "%24 = OpLabel\n"
175 			   << "%25 = OpLoad %11 %19\n"
176 			   << "%28 = OpSLessThan %27 %25 %26\n"
177 			   << "OpBranchConditional %28 %21 %22\n"
178 			   << "%21 = OpLabel\n"
179 			   << "%33 = OpLoad %11 %19\n"
180 			   << "%34 = OpLoad %11 %19\n"
181 			   << "%35 = OpCompositeConstruct %29 %34 %34 %34 %34\n"
182 			   << "%37 = OpAccessChain %36 %32 %33\n"
183 			   << "OpStore %37 %35\n"
184 			   << "OpBranch %23\n"
185 			   << "%23 = OpLabel\n"
186 			   << "%38 = OpLoad %11 %19\n"
187 			   << "%40 = OpIAdd %11 %38 %39\n"
188 			   << "OpStore %19 %40\n"
189 			   << "OpBranch %20\n"
190 			   << "%22 = OpLabel\n"
191 			   << "OpReturn\n"
192 			   << "OpFunctionEnd\n";
193 
194 	// Vertex shader passthrough. SPIR-V generated from:
195 	// #version 450
196 	// layout(location = 0) in highp vec4 pos;
197 	// out gl_PerVertex {
198 	//    vec4 gl_Position;
199 	// };
200 	// void main()
201 	// {
202 	//     gl_Position = pos;
203 	// }
204 	std::ostringstream	vertex_passthrough;
205 	vertex_passthrough << "OpCapability Shader\n"
206 					   << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
207 					   << "OpMemoryModel Logical GLSL450\n"
208 					   << "OpEntryPoint Vertex %4 \"main\" %10 %14\n"
209 					   << "OpMemberDecorate %8 0 BuiltIn Position\n"
210 					   << "OpDecorate %8 Block\n"
211 					   << "OpDecorate %14 Location 0\n"
212 					   << "%2 = OpTypeVoid\n"
213 					   << "%3 = OpTypeFunction %2\n"
214 					   << "%6 = OpTypeFloat 32\n"
215 					   << "%7 = OpTypeVector %6 4\n"
216 					   << "%8 = OpTypeStruct %7\n"
217 					   << "%9 = OpTypePointer Output %8\n"
218 					   << "%10 = OpVariable %9 Output\n"
219 					   << "%11 = OpTypeInt 32 1\n"
220 					   << "%12 = OpConstant %11 0\n"
221 					   << "%13 = OpTypePointer Input %7\n"
222 					   << "%14 = OpVariable %13 Input\n"
223 					   << "%16 = OpTypePointer Output %7\n"
224 					   << "%4 = OpFunction %2 None %3\n"
225 					   << "%5 = OpLabel\n"
226 					   << "%15 = OpLoad %7 %14\n"
227 					   << "%17 = OpAccessChain %16 %10 %12\n"
228 					   << "OpStore %17 %15\n"
229 					   << "OpReturn\n"
230 					   << "OpFunctionEnd\n";
231 
232 	// Tesselation Control shader. SPIR-V generated from:
233 	// #version 450
234 	// layout(vertices = 3) out;
235 	// in gl_PerVertex
236 	// {
237 	//   vec4 gl_Position;
238 	// } gl_in[];
239 	// out gl_PerVertex
240 	// {
241 	//   vec4 gl_Position;
242 	// } gl_out[];
243 	// void main(void)
244 	// {
245 	//     if (gl_InvocationID == 0) {
246 	//         gl_TessLevelInner[0] = 1.0;
247 	//         gl_TessLevelInner[1] = 1.0;
248 	//         gl_TessLevelOuter[0] = 1.0;
249 	//         gl_TessLevelOuter[1] = 1.0;
250 	//         gl_TessLevelOuter[2] = 1.0;
251 	//         gl_TessLevelOuter[3] = 1.0;
252 	//     }
253 	//     gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
254 	// }
255 	std::ostringstream	tcs_passthrough;
256 	tcs_passthrough << "OpCapability Tessellation\n"
257 					<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
258 					<< "OpMemoryModel Logical GLSL450\n"
259 					<< "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %29 %41 %47\n"
260 					<< "OpExecutionMode %4 OutputVertices 3\n"
261 					<< "OpDecorate %8 BuiltIn InvocationId\n"
262 					<< "OpDecorate %20 Patch\n"
263 					<< "OpDecorate %20 BuiltIn TessLevelInner\n"
264 					<< "OpDecorate %29 Patch\n"
265 					<< "OpDecorate %29 BuiltIn TessLevelOuter\n"
266 					<< "OpMemberDecorate %37 0 BuiltIn Position\n"
267 					<< "OpDecorate %37 Block\n"
268 					<< "OpMemberDecorate %43 0 BuiltIn Position\n"
269 					<< "OpDecorate %43 Block\n"
270 					<< "%2 = OpTypeVoid\n"
271 					<< "%3 = OpTypeFunction %2\n"
272 					<< "%6 = OpTypeInt 32 1\n"
273 					<< "%7 = OpTypePointer Input %6\n"
274 					<< "%8 = OpVariable %7 Input\n"
275 					<< "%10 = OpConstant %6 0\n"
276 					<< "%11 = OpTypeBool\n"
277 					<< "%15 = OpTypeFloat 32\n"
278 					<< "%16 = OpTypeInt 32 0\n"
279 					<< "%17 = OpConstant %16 2\n"
280 					<< "%18 = OpTypeArray %15 %17\n"
281 					<< "%19 = OpTypePointer Output %18\n"
282 					<< "%20 = OpVariable %19 Output\n"
283 					<< "%21 = OpConstant %15 1\n"
284 					<< "%22 = OpTypePointer Output %15\n"
285 					<< "%24 = OpConstant %6 1\n"
286 					<< "%26 = OpConstant %16 4\n"
287 					<< "%27 = OpTypeArray %15 %26\n"
288 					<< "%28 = OpTypePointer Output %27\n"
289 					<< "%29 = OpVariable %28 Output\n"
290 					<< "%32 = OpConstant %6 2\n"
291 					<< "%34 = OpConstant %6 3\n"
292 					<< "%36 = OpTypeVector %15 4\n"
293 					<< "%37 = OpTypeStruct %36\n"
294 					<< "%38 = OpConstant %16 3\n"
295 					<< "%39 = OpTypeArray %37 %38\n"
296 					<< "%40 = OpTypePointer Output %39\n"
297 					<< "%41 = OpVariable %40 Output\n"
298 					<< "%43 = OpTypeStruct %36\n"
299 					<< "%44 = OpConstant %16 32\n"
300 					<< "%45 = OpTypeArray %43 %44\n"
301 					<< "%46 = OpTypePointer Input %45\n"
302 					<< "%47 = OpVariable %46 Input\n"
303 					<< "%49 = OpTypePointer Input %36\n"
304 					<< "%52 = OpTypePointer Output %36\n"
305 					<< "%4 = OpFunction %2 None %3\n"
306 					<< "%5 = OpLabel\n"
307 					<< "%9 = OpLoad %6 %8\n"
308 					<< "%12 = OpIEqual %11 %9 %10\n"
309 					<< "OpSelectionMerge %14 None\n"
310 					<< "OpBranchConditional %12 %13 %14\n"
311 					<< "%13 = OpLabel\n"
312 					<< "%23 = OpAccessChain %22 %20 %10\n"
313 					<< "OpStore %23 %21\n"
314 					<< "%25 = OpAccessChain %22 %20 %24\n"
315 					<< "OpStore %25 %21\n"
316 					<< "%30 = OpAccessChain %22 %29 %10\n"
317 					<< "OpStore %30 %21\n"
318 					<< "%31 = OpAccessChain %22 %29 %24\n"
319 					<< "OpStore %31 %21\n"
320 					<< "%33 = OpAccessChain %22 %29 %32\n"
321 					<< "OpStore %33 %21\n"
322 					<< "%35 = OpAccessChain %22 %29 %34\n"
323 					<< "OpStore %35 %21\n"
324 					<< "OpBranch %14\n"
325 					<< "%14 = OpLabel\n"
326 					<< "%42 = OpLoad %6 %8\n"
327 					<< "%48 = OpLoad %6 %8\n"
328 					<< "%50 = OpAccessChain %49 %47 %48 %10\n"
329 					<< "%51 = OpLoad %36 %50\n"
330 					<< "%53 = OpAccessChain %52 %41 %42 %10\n"
331 					<< "OpStore %53 %51\n"
332 					<< "OpReturn\n"
333 					<< "OpFunctionEnd\n";
334 
335 	// Tessellation Evaluation shader. SPIR-V generated from:
336 	// #version 450
337 	// layout(triangles, equal_spacing, cw) in;
338 	// layout(constant_id = 0) const int arraySize = 1;
339 	// layout(location = 0) out ivec4 outputData[arraySize];
340 	// in gl_PerVertex {
341 	//    vec4 gl_Position;
342 	// } gl_in[];
343 	// out gl_PerVertex {
344 	//    vec4 gl_Position;
345 	// };
346 	// void main(void)
347 	// {
348 	//     gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position +
349 	//                    gl_TessCoord.y * gl_in[1].gl_Position +
350 	//                    gl_TessCoord.z * gl_in[2].gl_Position);
351 	//     int j;
352 	//     for (j = 0; j &lt; arraySize; j++)
353 	//     {
354 	//         outputData[j] = ivec4(j);
355 	//     }
356 	// }
357 	std::ostringstream	tes_out;
358 	tes_out << "OpCapability Tessellation\n"
359 			<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
360 			<< "OpMemoryModel Logical GLSL450\n"
361 			<< "OpEntryPoint TessellationEvaluation %4 \"main\" %10 %15 %25 %62\n"
362 			<< "OpExecutionMode %4 Triangles\n"
363 			<< "OpExecutionMode %4 SpacingEqual\n"
364 			<< "OpExecutionMode %4 VertexOrderCw\n"
365 			<< "OpMemberDecorate %8 0 BuiltIn Position\n"
366 			<< "OpDecorate %8 Block\n"
367 			<< "OpDecorate %15 BuiltIn TessCoord\n"
368 			<< "OpMemberDecorate %21 0 BuiltIn Position\n"
369 			<< "OpDecorate %21 Block\n"
370 			<< "OpDecorate %56 SpecId 0\n"
371 			<< "OpDecorate %62 Location 0\n"
372 			<< "%2 = OpTypeVoid\n"
373 			<< "%3 = OpTypeFunction %2\n"
374 			<< "%6 = OpTypeFloat 32\n"
375 			<< "%7 = OpTypeVector %6 4\n"
376 			<< "%8 = OpTypeStruct %7\n"
377 			<< "%9 = OpTypePointer Output %8\n"
378 			<< "%10 = OpVariable %9 Output\n"
379 			<< "%11 = OpTypeInt 32 1\n"
380 			<< "%12 = OpConstant %11 0\n"
381 			<< "%13 = OpTypeVector %6 3\n"
382 			<< "%14 = OpTypePointer Input %13\n"
383 			<< "%15 = OpVariable %14 Input\n"
384 			<< "%16 = OpTypeInt 32 0\n"
385 			<< "%17 = OpConstant %16 0\n"
386 			<< "%18 = OpTypePointer Input %6\n"
387 			<< "%21 = OpTypeStruct %7\n"
388 			<< "%22 = OpConstant %16 32\n"
389 			<< "%23 = OpTypeArray %21 %22\n"
390 			<< "%24 = OpTypePointer Input %23\n"
391 			<< "%25 = OpVariable %24 Input\n"
392 			<< "%26 = OpTypePointer Input %7\n"
393 			<< "%30 = OpConstant %16 1\n"
394 			<< "%33 = OpConstant %11 1\n"
395 			<< "%38 = OpConstant %16 2\n"
396 			<< "%41 = OpConstant %11 2\n"
397 			<< "%46 = OpTypePointer Output %7\n"
398 			<< "%48 = OpTypePointer Function %11\n"
399 			<< "%56 = OpSpecConstant %11 1\n"
400 			<< "%57 = OpTypeBool\n"
401 			<< "%59 = OpTypeVector %11 4\n"
402 			<< "%60 = OpTypeArray %59 %56\n"
403 			<< "%61 = OpTypePointer Output %60\n"
404 			<< "%62 = OpVariable %61 Output\n"
405 			<< "%66 = OpTypePointer Output %59\n"
406 			<< "%4 = OpFunction %2 None %3\n"
407 			<< "%5 = OpLabel\n"
408 			<< "%49 = OpVariable %48 Function\n"
409 			<< "%19 = OpAccessChain %18 %15 %17\n"
410 			<< "%20 = OpLoad %6 %19\n"
411 			<< "%27 = OpAccessChain %26 %25 %12 %12\n"
412 			<< "%28 = OpLoad %7 %27\n"
413 			<< "%29 = OpVectorTimesScalar %7 %28 %20\n"
414 			<< "%31 = OpAccessChain %18 %15 %30\n"
415 			<< "%32 = OpLoad %6 %31\n"
416 			<< "%34 = OpAccessChain %26 %25 %33 %12\n"
417 			<< "%35 = OpLoad %7 %34\n"
418 			<< "%36 = OpVectorTimesScalar %7 %35 %32\n"
419 			<< "%37 = OpFAdd %7 %29 %36\n"
420 			<< "%39 = OpAccessChain %18 %15 %38\n"
421 			<< "%40 = OpLoad %6 %39\n"
422 			<< "%42 = OpAccessChain %26 %25 %41 %12\n"
423 			<< "%43 = OpLoad %7 %42\n"
424 			<< "%44 = OpVectorTimesScalar %7 %43 %40\n"
425 			<< "%45 = OpFAdd %7 %37 %44\n"
426 			<< "%47 = OpAccessChain %46 %10 %12\n"
427 			<< "OpStore %47 %45\n"
428 			<< "OpStore %49 %12\n"
429 			<< "OpBranch %50\n"
430 			<< "%50 = OpLabel\n"
431 			<< "OpLoopMerge %52 %53 None\n"
432 			<< "OpBranch %54\n"
433 			<< "%54 = OpLabel\n"
434 			<< "%55 = OpLoad %11 %49\n"
435 			<< "%58 = OpSLessThan %57 %55 %56\n"
436 			<< "OpBranchConditional %58 %51 %52\n"
437 			<< "%51 = OpLabel\n"
438 			<< "%63 = OpLoad %11 %49\n"
439 			<< "%64 = OpLoad %11 %49\n"
440 			<< "%65 = OpCompositeConstruct %59 %64 %64 %64 %64\n"
441 			<< "%67 = OpAccessChain %66 %62 %63\n"
442 			<< "OpStore %67 %65\n"
443 			<< "OpBranch %53\n"
444 			<< "%53 = OpLabel\n"
445 			<< "%68 = OpLoad %11 %49\n"
446 			<< "%69 = OpIAdd %11 %68 %33\n"
447 			<< "OpStore %49 %69\n"
448 			<< "OpBranch %50\n"
449 			<< "%52 = OpLabel\n"
450 			<< "OpReturn\n"
451 			<< "OpFunctionEnd\n";
452 
453 	// Geometry shader. SPIR-V generated from:
454 	// #version 450
455 	// layout (triangles) in;
456 	// layout (triangle_strip, max_vertices = 3) out;
457 	// layout(constant_id = 0) const int arraySize = 1;
458 	// layout(location = 0) out ivec4 outputData[arraySize];
459 	// in gl_PerVertex {
460 	//    vec4 gl_Position;
461 	// } gl_in[];
462 	// void main()
463 	// {
464 	//     int i;
465 	//     int j;
466 	//     for(i = 0; i &lt; gl_in.length(); i++)
467 	//     {
468 	//         gl_Position = gl_in[i].gl_Position;
469 	//         for (j = 0; j &lt; arraySize; j++)
470 	//         {
471 	//             outputData[j] = ivec4(j);
472 	//         }
473 	//         EmitVertex();
474 	//     }
475 	//     EndPrimitive();
476 	// }
477 	std::ostringstream	geom_out;
478 	geom_out << "OpCapability Geometry\n"
479 			 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
480 			 << "OpMemoryModel Logical GLSL450\n"
481 			 << "OpEntryPoint Geometry %4 \"main\" %26 %31 %50\n"
482 			 << "OpExecutionMode %4 Triangles\n"
483 			 << "OpExecutionMode %4 Invocations 1\n"
484 			 << "OpExecutionMode %4 OutputTriangleStrip\n"
485 			 << "OpExecutionMode %4 OutputVertices 3\n"
486 			 << "OpMemberDecorate %24 0 BuiltIn Position\n"
487 			 << "OpDecorate %24 Block\n"
488 			 << "OpMemberDecorate %27 0 BuiltIn Position\n"
489 			 << "OpDecorate %27 Block\n"
490 			 << "OpDecorate %45 SpecId 0\n"
491 			 << "OpDecorate %50 Location 0\n"
492 			 << "%2 = OpTypeVoid\n"
493 			 << "%3 = OpTypeFunction %2\n"
494 			 << "%6 = OpTypeInt 32 1\n"
495 			 << "%7 = OpTypePointer Function %6\n"
496 			 << "%9 = OpConstant %6 0\n"
497 			 << "%16 = OpConstant %6 3\n"
498 			 << "%17 = OpTypeBool\n"
499 			 << "%19 = OpTypeFloat 32\n"
500 			 << "%20 = OpTypeVector %19 4\n"
501 			 << "%21 = OpTypeInt 32 0\n"
502 			 << "%22 = OpConstant %21 1\n"
503 			 << "%23 = OpTypeArray %19 %22\n"
504 			 << "%24 = OpTypeStruct %20\n"
505 			 << "%25 = OpTypePointer Output %24\n"
506 			 << "%26 = OpVariable %25 Output\n"
507 			 << "%27 = OpTypeStruct %20\n"
508 			 << "%28 = OpConstant %21 3\n"
509 			 << "%29 = OpTypeArray %27 %28\n"
510 			 << "%30 = OpTypePointer Input %29\n"
511 			 << "%31 = OpVariable %30 Input\n"
512 			 << "%33 = OpTypePointer Input %20\n"
513 			 << "%36 = OpTypePointer Output %20\n"
514 			 << "%45 = OpSpecConstant %6 1\n"
515 			 << "%47 = OpTypeVector %6 4\n"
516 			 << "%48 = OpTypeArray %47 %45\n"
517 			 << "%49 = OpTypePointer Output %48\n"
518 			 << "%50 = OpVariable %49 Output\n"
519 			 << "%54 = OpTypePointer Output %47\n"
520 			 << "%57 = OpConstant %6 1\n"
521 			 << "%4 = OpFunction %2 None %3\n"
522 			 << "%5 = OpLabel\n"
523 			 << "%8 = OpVariable %7 Function\n"
524 			 << "%38 = OpVariable %7 Function\n"
525 			 << "OpStore %8 %9\n"
526 			 << "OpBranch %10\n"
527 			 << "%10 = OpLabel\n"
528 			 << "OpLoopMerge %12 %13 None\n"
529 			 << "OpBranch %14\n"
530 			 << "%14 = OpLabel\n"
531 			 << "%15 = OpLoad %6 %8\n"
532 			 << "%18 = OpSLessThan %17 %15 %16\n"
533 			 << "OpBranchConditional %18 %11 %12\n"
534 			 << "%11 = OpLabel\n"
535 			 << "%32 = OpLoad %6 %8\n"
536 			 << "%34 = OpAccessChain %33 %31 %32 %9\n"
537 			 << "%35 = OpLoad %20 %34\n"
538 			 << "%37 = OpAccessChain %36 %26 %9\n"
539 			 << "OpStore %37 %35\n"
540 			 << "OpStore %38 %9\n"
541 			 << "OpBranch %39\n"
542 			 << "%39 = OpLabel\n"
543 			 << "OpLoopMerge %41 %42 None\n"
544 			 << "OpBranch %43\n"
545 			 << "%43 = OpLabel\n"
546 			 << "%44 = OpLoad %6 %38\n"
547 			 << "%46 = OpSLessThan %17 %44 %45\n"
548 			 << "OpBranchConditional %46 %40 %41\n"
549 			 << "%40 = OpLabel\n"
550 			 << "%51 = OpLoad %6 %38\n"
551 			 << "%52 = OpLoad %6 %38\n"
552 			 << "%53 = OpCompositeConstruct %47 %52 %52 %52 %52\n"
553 			 << "%55 = OpAccessChain %54 %50 %51\n"
554 			 << "OpStore %55 %53\n"
555 			 << "OpBranch %42\n"
556 			 << "%42 = OpLabel\n"
557 			 << "%56 = OpLoad %6 %38\n"
558 			 << "%58 = OpIAdd %6 %56 %57\n"
559 			 << "OpStore %38 %58\n"
560 			 << "OpBranch %39\n"
561 			 << "%41 = OpLabel\n"
562 			 << "OpEmitVertex\n"
563 			 << "OpBranch %13\n"
564 			 << "%13 = OpLabel\n"
565 			 << "%59 = OpLoad %6 %8\n"
566 			 << "%60 = OpIAdd %6 %59 %57\n"
567 			 << "OpStore %8 %60\n"
568 			 << "OpBranch %10\n"
569 			 << "%12 = OpLabel\n"
570 			 << "OpEndPrimitive\n"
571 			 << "OpReturn\n"
572 			 << "OpFunctionEnd\n";
573 
574 	// Fragment shader. SPIR-V code generated from:
575 	//
576 	// #version 450
577 	// layout(constant_id = 0) const int arraySize = 1;
578 	// layout(location = 0) flat in ivec4 inputData[arraySize];
579 	// layout(location = 0) out vec4 color;
580 	// void main()
581 	// {
582 	//    color = vec4(1.0, 0.0, 0.0, 1.0);
583 	//    int i;
584 	//    bool result = true;
585 	//    for (i = 0; i &lt; arraySize; i++)
586 	//    {
587 	//        if (result &amp;&amp; inputData[i] != ivec4(i))
588 	//            result = false;
589 	//    }
590 	//    if (result)
591 	//      color = vec4(0.0, 1.0, 0.0, 1.0);
592 	// }
593 	std::ostringstream	fragment_in;
594 	fragment_in << "OpCapability Shader\n"
595 				<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
596 				<< "OpMemoryModel Logical GLSL450\n"
597 				<< "OpEntryPoint Fragment %4 \"main\" %9 %35\n"
598 				<< "OpExecutionMode %4 OriginUpperLeft\n"
599 				<< "OpDecorate %9 Location 0\n"
600 				<< "OpDecorate %27 SpecId 0\n"
601 				<< "OpDecorate %35 Flat\n"
602 				<< "OpDecorate %35 Location 0\n"
603 				<< "%2 = OpTypeVoid\n"
604 				<< "%3 = OpTypeFunction %2\n"
605 				<< "%6 = OpTypeFloat 32\n"
606 				<< "%7 = OpTypeVector %6 4\n"
607 				<< "%8 = OpTypePointer Output %7\n"
608 				<< "%9 = OpVariable %8 Output\n"
609 				<< "%10 = OpConstant %6 1\n"
610 				<< "%11 = OpConstant %6 0\n"
611 				<< "%12 = OpConstantComposite %7 %10 %11 %11 %10\n"
612 				<< "%13 = OpTypeBool\n"
613 				<< "%14 = OpTypePointer Function %13\n"
614 				<< "%16 = OpConstantTrue %13\n"
615 				<< "%17 = OpTypeInt 32 1\n"
616 				<< "%18 = OpTypePointer Function %17\n"
617 				<< "%20 = OpConstant %17 0\n"
618 				<< "%27 = OpSpecConstant %17 1\n"
619 				<< "%32 = OpTypeVector %17 4\n"
620 				<< "%33 = OpTypeArray %32 %27\n"
621 				<< "%34 = OpTypePointer Input %33\n"
622 				<< "%35 = OpVariable %34 Input\n"
623 				<< "%37 = OpTypePointer Input %32\n"
624 				<< "%42 = OpTypeVector %13 4\n"
625 				<< "%48 = OpConstantFalse %13\n"
626 				<< "%50 = OpConstant %17 1\n"
627 				<< "%55 = OpConstantComposite %7 %11 %10 %11 %10\n"
628 				<< "%4 = OpFunction %2 None %3\n"
629 				<< "%5 = OpLabel\n"
630 				<< "%15 = OpVariable %14 Function\n"
631 				<< "%19 = OpVariable %18 Function\n"
632 				<< "OpStore %9 %12\n"
633 				<< "OpStore %15 %16\n"
634 				<< "OpStore %19 %20\n"
635 				<< "OpBranch %21\n"
636 				<< "%21 = OpLabel\n"
637 				<< "OpLoopMerge %23 %24 None\n"
638 				<< "OpBranch %25\n"
639 				<< "%25 = OpLabel\n"
640 				<< "%26 = OpLoad %17 %19\n"
641 				<< "%28 = OpSLessThan %13 %26 %27\n"
642 				<< "OpBranchConditional %28 %22 %23\n"
643 				<< "%22 = OpLabel\n"
644 				<< "%29 = OpLoad %13 %15\n"
645 				<< "OpSelectionMerge %31 None\n"
646 				<< "OpBranchConditional %29 %30 %31\n"
647 				<< "%30 = OpLabel\n"
648 				<< "%36 = OpLoad %17 %19\n"
649 				<< "%38 = OpAccessChain %37 %35 %36\n"
650 				<< "%39 = OpLoad %32 %38\n"
651 				<< "%40 = OpLoad %17 %19\n"
652 				<< "%41 = OpCompositeConstruct %32 %40 %40 %40 %40\n"
653 				<< "%43 = OpINotEqual %42 %39 %41\n"
654 				<< "%44 = OpAny %13 %43\n"
655 				<< "OpBranch %31\n"
656 				<< "%31 = OpLabel\n"
657 				<< "%45 = OpPhi %13 %29 %22 %44 %30\n"
658 				<< "OpSelectionMerge %47 None\n"
659 				<< "OpBranchConditional %45 %46 %47\n"
660 				<< "%46 = OpLabel\n"
661 				<< "OpStore %15 %48\n"
662 				<< "OpBranch %47\n"
663 				<< "%47 = OpLabel\n"
664 				<< "OpBranch %24\n"
665 				<< "%24 = OpLabel\n"
666 				<< "%49 = OpLoad %17 %19\n"
667 				<< "%51 = OpIAdd %17 %49 %50\n"
668 				<< "OpStore %19 %51\n"
669 				<< "OpBranch %21\n"
670 				<< "%23 = OpLabel\n"
671 				<< "%52 = OpLoad %13 %15\n"
672 				<< "OpSelectionMerge %54 None\n"
673 				<< "OpBranchConditional %52 %53 %54\n"
674 				<< "%53 = OpLabel\n"
675 				<< "OpStore %9 %55\n"
676 				<< "OpBranch %54\n"
677 				<< "%54 = OpLabel\n"
678 				<< "OpReturn\n"
679 				<< "OpFunctionEnd\n";
680 
681 	if (param.outputStage == VK_SHADER_STAGE_VERTEX_BIT)
682 	{
683 		programCollection.spirvAsmSources.add("vert")
684 			<< vertex_out.str().c_str();
685 
686 		if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT)
687 		{
688 			programCollection.spirvAsmSources.add("frag")
689 				<< fragment_in.str().c_str();
690 			return;
691 		}
692 	}
693 
694 	programCollection.spirvAsmSources.add("vert")
695 		<< vertex_passthrough.str().c_str();
696 
697 	if (param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
698 	{
699 		programCollection.spirvAsmSources.add("tcs")
700 			<< tcs_passthrough.str().c_str();
701 		programCollection.spirvAsmSources.add("tes")
702 			<< tes_out.str().c_str();
703 
704 		if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT)
705 		{
706 			programCollection.spirvAsmSources.add("frag")
707 				<< fragment_in.str().c_str();
708 			return;
709 		}
710 	}
711 
712 	if (param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT)
713 	{
714 		programCollection.spirvAsmSources.add("geom")
715 				<< geom_out.str().c_str();
716 		programCollection.spirvAsmSources.add("frag")
717 			<< fragment_in.str().c_str();
718 		return;
719 	}
720 
721 	DE_FATAL("Unsupported combination");
722 }
723 
supportedCheck(Context & context,MaxVaryingsParam param)724 void supportedCheck (Context& context, MaxVaryingsParam param)
725 {
726 
727 	const vk::InstanceInterface&	vki = context.getInstanceInterface();
728 	VkPhysicalDeviceFeatures		features;
729 	vki.getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
730 
731 	// Check support for the tessellation and geometry shaders on the device
732 	if ((param.inputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
733 		 param.inputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
734 		 param.outputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
735 		 param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
736 		&& !features.tessellationShader)
737 	{
738 		TCU_THROW(NotSupportedError, "Device does not support tessellation shaders");
739 	}
740 
741 	if ((param.inputStage == VK_SHADER_STAGE_GEOMETRY_BIT || param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT) && !features.geometryShader)
742 	{
743 		TCU_THROW(NotSupportedError, "Device does not support geometry shaders");
744 	}
745 
746 	// Check data sizes, throw unsupported if the case cannot be tested.
747 	VkPhysicalDeviceProperties properties;
748 	vki.getPhysicalDeviceProperties(context.getPhysicalDevice(), &properties);
749 	std::ostringstream	error;
750 	if (param.stageToStressIO == VK_SHADER_STAGE_VERTEX_BIT)
751 	{
752 		DE_ASSERT(param.outputStage == VK_SHADER_STAGE_VERTEX_BIT);
753 		if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxVertexOutputComponents - 4))
754 		{
755 			error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than VS outputs (" << properties.limits.maxVertexOutputComponents << " - 4 built-ins)";
756 			TCU_THROW(NotSupportedError, error.str().c_str());
757 		}
758 	}
759 
760 	if (param.stageToStressIO == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
761 	{
762 		if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxTessellationEvaluationOutputComponents - 4))
763 		{
764 			error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than TES outputs (" << properties.limits.maxTessellationEvaluationOutputComponents << " - 4 builtins)";
765 			TCU_THROW(NotSupportedError, error.str().c_str());
766 		}
767 	}
768 
769 	if (param.stageToStressIO == VK_SHADER_STAGE_GEOMETRY_BIT)
770 	{
771 		if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxGeometryOutputComponents - 4))
772 		{
773 			error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than GS outputs (" << properties.limits.maxGeometryOutputComponents << " - 4 built-ins)";
774 			TCU_THROW(NotSupportedError, error.str().c_str());
775 		}
776 	}
777 
778 	if (param.stageToStressIO == VK_SHADER_STAGE_FRAGMENT_BIT)
779 	{
780 		DE_ASSERT(param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT);
781 
782 		if (param.outputStage == VK_SHADER_STAGE_VERTEX_BIT && (properties.limits.maxVertexOutputComponents - 4) < properties.limits.maxFragmentInputComponents)
783 		{
784 			error << "Device supports smaller number of VS outputs (" << properties.limits.maxVertexOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")";
785 			TCU_THROW(NotSupportedError, error.str().c_str());
786 		}
787 		if (param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT && (properties.limits.maxGeometryOutputComponents - 4) < properties.limits.maxFragmentInputComponents)
788 		{
789 			error << "Device supports smaller number of GS outputs (" << properties.limits.maxGeometryOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")";
790 			TCU_THROW(NotSupportedError, error.str().c_str());
791 		}
792 		if (param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT && (properties.limits.maxTessellationEvaluationOutputComponents - 4) < properties.limits.maxFragmentInputComponents)
793 		{
794 			error << "Device supports smaller number of TES outputs (" << properties.limits.maxTessellationEvaluationOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")";
795 			TCU_THROW(NotSupportedError, error.str().c_str());
796 		}
797 	}
798 }
799 
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)800 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
801 {
802 	const VkImageCreateInfo imageInfo =
803 	{
804 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
805 		DE_NULL,									// const void*				pNext;
806 		(VkImageCreateFlags)0,						// VkImageCreateFlags		flags;
807 		VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
808 		format,										// VkFormat					format;
809 		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D				extent;
810 		1u,											// uint32_t					mipLevels;
811 		1u,											// uint32_t					arrayLayers;
812 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
813 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
814 		usage,										// VkImageUsageFlags		usage;
815 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
816 		0u,											// uint32_t					queueFamilyIndexCount;
817 		DE_NULL,									// const uint32_t*			pQueueFamilyIndices;
818 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			initialLayout;
819 	};
820 	return imageInfo;
821 }
822 
makeBuffer(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)823 Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
824 {
825 	const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
826 	return createBuffer(vk, device, &bufferCreateInfo);
827 }
828 
recordImageBarrier(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageAspectFlags aspect,const VkPipelineStageFlags srcStageMask,const VkPipelineStageFlags dstStageMask,const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkSampleLocationsInfoEXT * pSampleLocationsInfo=DE_NULL)829 void recordImageBarrier (const DeviceInterface&				vk,
830 						 const VkCommandBuffer				cmdBuffer,
831 						 const VkImage						image,
832 						 const VkImageAspectFlags			aspect,
833 						 const VkPipelineStageFlags			srcStageMask,
834 						 const VkPipelineStageFlags			dstStageMask,
835 						 const VkAccessFlags				srcAccessMask,
836 						 const VkAccessFlags				dstAccessMask,
837 						 const VkImageLayout				oldLayout,
838 						 const VkImageLayout				newLayout,
839 						 const VkSampleLocationsInfoEXT*	pSampleLocationsInfo = DE_NULL)
840 {
841 	const VkImageMemoryBarrier barrier =
842 	{
843 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,						// VkStructureType			sType;
844 		pSampleLocationsInfo,										// const void*				pNext;
845 		srcAccessMask,												// VkAccessFlags			srcAccessMask;
846 		dstAccessMask,												// VkAccessFlags			dstAccessMask;
847 		oldLayout,													// VkImageLayout			oldLayout;
848 		newLayout,													// VkImageLayout			newLayout;
849 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t					srcQueueFamilyIndex;
850 		VK_QUEUE_FAMILY_IGNORED,									// uint32_t					dstQueueFamilyIndex;
851 		image,														// VkImage					image;
852 		makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u),			// VkImageSubresourceRange	subresourceRange;
853 	};
854 
855 	vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
856 }
857 
recordCopyImageToBuffer(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const tcu::IVec2 & imageSize,const VkImage srcImage,const VkBuffer dstBuffer)858 void recordCopyImageToBuffer (const DeviceInterface&	vk,
859 							  const VkCommandBuffer		cmdBuffer,
860 							  const tcu::IVec2&			imageSize,
861 							  const VkImage				srcImage,
862 							  const VkBuffer			dstBuffer)
863 {
864 	// Resolve image -> host buffer
865 	{
866 		const VkBufferImageCopy region =
867 		{
868 			0ull,																// VkDeviceSize				bufferOffset;
869 			0u,																	// uint32_t					bufferRowLength;
870 			0u,																	// uint32_t					bufferImageHeight;
871 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers	imageSubresource;
872 			makeOffset3D(0, 0, 0),												// VkOffset3D				imageOffset;
873 			makeExtent3D(imageSize.x(), imageSize.y(), 1u),						// VkExtent3D				imageExtent;
874 		};
875 
876 		vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, &region);
877 	}
878 	// Buffer write barrier
879 	{
880 		const VkBufferMemoryBarrier barrier =
881 		{
882 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// VkStructureType	sType;
883 			DE_NULL,										// const void*		pNext;
884 			VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags	srcAccessMask;
885 			VK_ACCESS_HOST_READ_BIT,						// VkAccessFlags	dstAccessMask;
886 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t			srcQueueFamilyIndex;
887 			VK_QUEUE_FAMILY_IGNORED,						// uint32_t			dstQueueFamilyIndex;
888 			dstBuffer,										// VkBuffer			buffer;
889 			0ull,											// VkDeviceSize		offset;
890 			VK_WHOLE_SIZE,									// VkDeviceSize		size;
891 		};
892 
893 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
894 							  0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
895 	}
896 }
897 
createBufferAndBindMemory(Context & context,VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)898 Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
899 {
900 	const DeviceInterface&	vk					= context.getDeviceInterface();
901 	const VkDevice			vkDevice			= context.getDevice();
902 	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
903 
904 	const VkBufferCreateInfo vertexBufferParams =
905 	{
906 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
907 		DE_NULL,									// const void*			pNext;
908 		0u,											// VkBufferCreateFlags	flags;
909 		size,										// VkDeviceSize			size;
910 		usage,										// VkBufferUsageFlags	usage;
911 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
912 		1u,											// deUint32				queueFamilyCount;
913 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
914 	};
915 
916 	Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
917 
918 	*pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
919 	VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
920 
921 	return vertexBuffer;
922 }
923 
getMaxIOComponents(deBool input,VkShaderStageFlags stage,VkPhysicalDeviceProperties properties)924 deInt32 getMaxIOComponents(deBool input, VkShaderStageFlags stage, VkPhysicalDeviceProperties properties)
925 {
926 	deInt32 data = 0u;
927 	switch (stage)
928 	{
929 	case VK_SHADER_STAGE_VERTEX_BIT:
930 		DE_ASSERT(!input);
931 		data = (properties.limits.maxVertexOutputComponents / 4) - 1; // outputData + gl_Position
932 		break;
933 
934 	case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
935 		if (input)
936 			data = properties.limits.maxTessellationEvaluationInputComponents / 4;
937 		else
938 			data = (properties.limits.maxTessellationEvaluationOutputComponents / 4) - 1; // outputData + gl_Position
939 		break;
940 
941 	case VK_SHADER_STAGE_GEOMETRY_BIT:
942 		if (input)
943 			data = properties.limits.maxGeometryInputComponents / 4;
944 		else
945 			data = (properties.limits.maxGeometryOutputComponents / 4) - 1; // outputData + gl_Position
946 		break;
947 
948 	case VK_SHADER_STAGE_FRAGMENT_BIT:
949 		DE_ASSERT(input);
950 		data = (properties.limits.maxFragmentInputComponents / 4); // inputData
951 		break;
952 	default:
953 		DE_FATAL("Unsupported shader");
954 	}
955 
956 	return data;
957 }
958 
test(Context & context,const MaxVaryingsParam param)959 tcu::TestStatus test(Context& context, const MaxVaryingsParam param)
960 {
961 	const InstanceInterface&	vki					= context.getInstanceInterface();
962 	const DeviceInterface&		vk					= context.getDeviceInterface();
963 	const VkDevice				device				= context.getDevice();
964 	const VkQueue				queue				= context.getUniversalQueue();
965 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
966 	Allocator&					allocator			= context.getDefaultAllocator();
967 	tcu::TestLog				&log				= context.getTestContext().getLog();
968 
969 
970 	// Color attachment
971 	const tcu::IVec2			renderSize		= tcu::IVec2(32, 32);
972 	const VkFormat				imageFormat	= VK_FORMAT_R8G8B8A8_UNORM;
973 	const Image				colorImage		(vk, device, allocator, makeImageCreateInfo(renderSize, imageFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::Any);
974 	const Unique<VkImageView> colorImageView	(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, imageFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)));
975 	const VkDeviceSize	colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(imageFormat));
976 	Move<VkBuffer>		colorBuffer			= vkt::pipeline::makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
977 	MovePtr<Allocation>	colorBufferAlloc	= bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible);
978 
979 
980 	// Create vertex buffer
981 	de::MovePtr<Allocation>				vertexBufferMemory;
982 	Move<VkBuffer>		vertexBuffer	= createBufferAndBindMemory(context, sizeof(tcu::Vec4) * 6u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertexBufferMemory);
983 	std::vector<tcu::Vec4>			vertices;
984 	{
985 		vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
986 		vertices.push_back(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
987 		vertices.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
988 		vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
989 		vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
990 		vertices.push_back(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
991 		// Load vertices into vertex buffer
992 		deMemcpy(vertexBufferMemory->getHostPtr(), vertices.data(), vertices.size() * sizeof(tcu::Vec4));
993 		flushAlloc(vk, device, *vertexBufferMemory);
994 	}
995 
996 	// Specialization
997 	VkPhysicalDeviceProperties properties;
998 	vki.getPhysicalDeviceProperties(context.getPhysicalDevice(), &properties);
999 	VkPhysicalDeviceFeatures features;
1000 	vki.getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
1001 
1002 	deInt32		data		= 0u;
1003 	size_t		dataSize	= sizeof(data);
1004 	deInt32		maxOutput	= getMaxIOComponents(false, param.outputStage, properties);
1005 	deInt32		maxInput	= getMaxIOComponents(true, param.inputStage, properties);
1006 
1007 	data = deMin32(maxOutput, maxInput);
1008 
1009 	DE_ASSERT(data != 0u);
1010 
1011 	log << tcu::TestLog::Message << "Testing " << data * 4 << " input components for stage " << getShaderStageName(param.stageToStressIO).c_str() << tcu::TestLog::EndMessage;
1012 
1013 	VkSpecializationMapEntry	mapEntries =
1014 	{
1015 		0u,							// deUint32	constantID;
1016 		0u,							// deUint32	offset;
1017 		dataSize					// size_t	size;
1018 	};
1019 
1020 	VkSpecializationInfo		pSpecInfo =
1021 	{
1022 		1u,							// deUint32							mapEntryCount;
1023 		&mapEntries,				// const VkSpecializationMapEntry*	pMapEntries;
1024 		dataSize,					// size_t							dataSize;
1025 		&data						// const void*						pData;
1026 	};
1027 
1028 	// Pipeline
1029 
1030 	const Unique<VkRenderPass>		renderPass		(makeRenderPass	(vk, device, imageFormat));
1031 	const Unique<VkFramebuffer>	framebuffer	(makeFramebuffer	(vk, device, *renderPass, 1u, &colorImageView.get(), static_cast<deUint32>(renderSize.x()), static_cast<deUint32>(renderSize.y())));
1032 	const Unique<VkPipelineLayout>	pipelineLayout	(makePipelineLayout(vk, device));
1033 	const Unique<VkCommandPool>	cmdPool		(createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1034 	const Unique<VkCommandBuffer>	cmdBuffer		(makeCommandBuffer (vk, device, *cmdPool));
1035 
1036 	GraphicsPipelineBuilder pipelineBuilder;
1037 	pipelineBuilder
1038 		.setRenderSize(renderSize);
1039 
1040 	// Get the shaders to run
1041 	std::vector<SelectedShaders>	shaders;
1042 	shaders.push_back(SelectedShaders(VK_SHADER_STAGE_VERTEX_BIT, "vert"));
1043 	shaders.push_back(SelectedShaders(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"));
1044 
1045 	if (param.inputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || param.outputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
1046 		param.inputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT || param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1047 	{
1048 		shaders.push_back(SelectedShaders(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tcs"));
1049 		shaders.push_back(SelectedShaders(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tes"));
1050 	}
1051 	if (param.inputStage == VK_SHADER_STAGE_GEOMETRY_BIT || param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT)
1052 	{
1053 		shaders.push_back(SelectedShaders(VK_SHADER_STAGE_GEOMETRY_BIT, "geom"));
1054 	}
1055 
1056 	for (deUint32 i = 0; i < (deUint32)shaders.size(); i++)
1057 	{
1058 		pipelineBuilder.setShader(vk, device, shaders[i].stage, context.getBinaryCollection().get(shaders[i].shaderName.c_str()), &pSpecInfo);
1059 	}
1060 
1061 	const Unique<VkPipeline> pipeline (pipelineBuilder.build(vk, device, *pipelineLayout, *renderPass));
1062 
1063 	// Draw commands
1064 
1065 	const VkRect2D		renderArea			= makeRect2D(renderSize);
1066 	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 1.0f);
1067 
1068 	beginCommandBuffer(vk, *cmdBuffer);
1069 
1070 	{
1071 		const VkImageSubresourceRange imageFullSubresourceRange				= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1072 		const VkImageMemoryBarrier    barrierColorAttachmentSetInitialLayout	= makeImageMemoryBarrier(
1073 			0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1074 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1075 			*colorImage, imageFullSubresourceRange);
1076 
1077 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1078 			0u, DE_NULL, 0u, DE_NULL, 1u, &barrierColorAttachmentSetInitialLayout);
1079 	}
1080 
1081 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
1082 
1083 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1084 	const VkDeviceSize vertexBufferOffset = 0ull;
1085 	vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1086 
1087 	// Draw one vertex
1088 	vk.cmdDraw(*cmdBuffer, (deUint32)vertices.size(), 1u, 0u, 0u);
1089 	endRenderPass(vk, *cmdBuffer);
1090 	// Resolve image -> host buffer
1091 	recordImageBarrier(vk, *cmdBuffer, *colorImage,
1092 						VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags	aspect,
1093 						VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,			// VkPipelineStageFlags srcStageMask,
1094 						VK_PIPELINE_STAGE_TRANSFER_BIT,							// VkPipelineStageFlags dstStageMask,
1095 						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags		srcAccessMask,
1096 						VK_ACCESS_TRANSFER_READ_BIT,							// VkAccessFlags		dstAccessMask,
1097 						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout		oldLayout,
1098 						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);					// VkImageLayout		newLayout)
1099 
1100 	recordCopyImageToBuffer(vk, *cmdBuffer, renderSize, *colorImage, *colorBuffer);
1101 	endCommandBuffer(vk, *cmdBuffer);
1102 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1103 
1104 	// Verify results
1105 	{
1106 		invalidateAlloc(vk, device, *colorBufferAlloc);
1107 
1108 		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(imageFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
1109 		tcu::TextureLevel	referenceImage (mapVkFormat(imageFormat), renderSize.x(), renderSize.y());
1110 		tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1111 
1112 		if (!tcu::floatThresholdCompare(log, "Compare", "Result comparison", referenceImage.getAccess(), resultImage, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1113 			TCU_FAIL("Rendered image is not correct");
1114 	}
1115 	return tcu::TestStatus::pass("OK");
1116 }
1117 } // anonymous
1118 
createMaxVaryingsTests(tcu::TestContext & testCtx)1119 tcu::TestCaseGroup* createMaxVaryingsTests (tcu::TestContext& testCtx)
1120 {
1121 	std::vector<MaxVaryingsParam> tests;
1122 
1123 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_VERTEX_BIT)); // Test max vertex outputs: VS-FS
1124 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test max FS inputs: VS-FS
1125 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)); // Test max tess evaluation outputs: VS-TCS-TES-FS
1126 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test fragment inputs: VS-TCS-TES-FS
1127 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_GEOMETRY_BIT)); // Test geometry outputs: VS-GS-FS
1128 	tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test fragment inputs: VS-GS-FS
1129 
1130 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "max_varyings", "Max Varyings tests"));
1131 
1132 	for (deUint32 testIndex = 0; testIndex < (deUint32)tests.size(); ++testIndex)
1133 	{
1134 		MaxVaryingsParam testParams = tests[testIndex];
1135 		addFunctionCaseWithPrograms(group.get(), generateTestName(testParams), generateTestDescription(),
1136 									supportedCheck, initPrograms, test, testParams);
1137 	}
1138 
1139 	return group.release();
1140 }
1141 
1142 } // pipeline
1143 } // vkt
1144