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