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