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