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 < 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 < 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 < gl_in.length(); i++)
455 // {
456 // gl_Position = gl_in[i].gl_Position;
457 // for (j = 0; j < 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 < arraySize; i++)
574 // {
575 // if (result && 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, ®ion);
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