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