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