d4e6c6715820a35e2b5193e50db0d50f19fe24eb
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / spirv_assembly / vktSpvAsmInstructionTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
18  * The Materials are Confidential Information as defined by the
19  * Khronos Membership Agreement until designated non-confidential by
20  * Khronos, at which point this condition clause shall be removed.
21  *
22  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29  *
30  *//*!
31  * \file
32  * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand)
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktSpvAsmInstructionTests.hpp"
36
37 #include "tcuCommandLine.hpp"
38 #include "tcuFormatUtil.hpp"
39 #include "tcuRGBA.hpp"
40 #include "tcuStringTemplate.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuVectorUtil.hpp"
43
44 #include "vkDefs.hpp"
45 #include "vkDeviceUtil.hpp"
46 #include "vkMemUtil.hpp"
47 #include "vkPlatform.hpp"
48 #include "vkPrograms.hpp"
49 #include "vkQueryUtil.hpp"
50 #include "vkRef.hpp"
51 #include "vkRefUtil.hpp"
52 #include "vkStrUtil.hpp"
53 #include "vkTypeUtil.hpp"
54
55 #include "deClock.h"
56 #include "deRandom.hpp"
57 #include "deStringUtil.hpp"
58 #include "deUniquePtr.hpp"
59 #include "tcuStringTemplate.hpp"
60
61 #include "vktSpvAsmComputeShaderCase.hpp"
62 #include "vktSpvAsmComputeShaderTestUtil.hpp"
63 #include "vktTestCaseUtil.hpp"
64
65 #include <map>
66 #include <string>
67 #include <sstream>
68
69 namespace vkt
70 {
71 namespace SpirVAssembly
72 {
73
74 namespace
75 {
76
77 using namespace vk;
78 using std::map;
79 using std::string;
80 using std::vector;
81 using tcu::IVec3;
82 using tcu::IVec4;
83 using tcu::RGBA;
84 using tcu::TestLog;
85 using tcu::TestStatus;
86 using tcu::Vec4;
87 using de::UniquePtr;
88 using tcu::StringTemplate;
89
90 typedef Unique<VkShaderModule>                  ModuleHandleUp;
91 typedef de::SharedPtr<ModuleHandleUp>   ModuleHandleSp;
92 typedef Unique<VkShader>                                VkShaderUp;
93 typedef de::SharedPtr<VkShaderUp>               VkShaderSp;
94
95 template<typename T>    T                       randomScalar    (de::Random& rnd, T minValue, T maxValue);
96 template<> inline               float           randomScalar    (de::Random& rnd, float minValue, float maxValue)               { return rnd.getFloat(minValue, maxValue);      }
97 template<> inline               deInt32         randomScalar    (de::Random& rnd, deInt32 minValue, deInt32 maxValue)   { return rnd.getInt(minValue, maxValue);        }
98 template<> inline               deUint32        randomScalar    (de::Random& rnd, deUint32 minValue, deUint32 maxValue) { return minValue + rnd.getUint32() % (maxValue - minValue + 1); }
99
100 template<typename T>
101 static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
102 {
103         T* const typedPtr = (T*)dst;
104         for (int ndx = 0; ndx < numValues; ndx++)
105                 typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
106 }
107
108 // \todo [2015-11-19 antiagainst] New rules for Vulkan pipeline interface requires that
109 // all BuiltIn variables have to all be members in a block (struct with Block decoration).
110
111 // Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code:
112 //
113 // #version 430
114 //
115 // layout(std140, set = 0, binding = 0) readonly buffer Input {
116 //   float elements[];
117 // } input_data;
118 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
119 //   float elements[];
120 // } output_data;
121 //
122 // layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
123 //
124 // void main() {
125 //   uint x = gl_GlobalInvocationID.x;
126 //   output_data.elements[x] = -input_data.elements[x];
127 // }
128
129 static const char* const s_ShaderPreamble =
130                 "OpCapability Shader\n"
131                 "OpMemoryModel Logical GLSL450\n"
132                 "OpEntryPoint GLCompute %main \"main\" %id\n"
133         "OpExecutionMode %main LocalSize 1 1 1\n";
134
135 static const char* const s_CommonTypes =
136         "%bool      = OpTypeBool\n"
137         "%void      = OpTypeVoid\n"
138         "%voidf     = OpTypeFunction %void\n"
139         "%u32       = OpTypeInt 32 0\n"
140         "%i32       = OpTypeInt 32 1\n"
141         "%f32       = OpTypeFloat 32\n"
142         "%uvec3     = OpTypeVector %u32 3\n"
143         "%uvec3ptr  = OpTypePointer Input %uvec3\n"
144         "%f32ptr    = OpTypePointer Uniform %f32\n"
145         "%f32arr    = OpTypeRuntimeArray %f32\n";
146
147 // Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]").
148 static const char* const s_InputOutputBuffer =
149         "%inbuf     = OpTypeStruct %f32arr\n"
150         "%inbufptr  = OpTypePointer Uniform %inbuf\n"
151         "%indata    = OpVariable %inbufptr Uniform\n"
152         "%outbuf    = OpTypeStruct %f32arr\n"
153         "%outbufptr = OpTypePointer Uniform %outbuf\n"
154         "%outdata   = OpVariable %outbufptr Uniform\n";
155
156 // Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0.
157 // indata is at binding point 0, while outdata is at 1.
158 static const char* const s_InputOutputBufferTraits =
159                 "OpDecorate %inbuf BufferBlock\n"
160                 "OpDecorate %indata DescriptorSet 0\n"
161                 "OpDecorate %indata Binding 0\n"
162                 "OpDecorate %outbuf BufferBlock\n"
163                 "OpDecorate %outdata DescriptorSet 0\n"
164                 "OpDecorate %outdata Binding 1\n"
165                 "OpDecorate %f32arr ArrayStride 4\n"
166                 "OpMemberDecorate %inbuf 0 Offset 0\n"
167         "OpMemberDecorate %outbuf 0 Offset 0\n";
168
169 tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
170 {
171         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction"));
172         ComputeShaderSpec                               spec;
173         de::Random                                              rnd                             (deStringHash(group->getName()));
174         const int                                               numElements             = 100;
175         vector<float>                                   positiveFloats  (numElements, 0);
176         vector<float>                                   negativeFloats  (numElements, 0);
177
178         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
179
180         for (size_t ndx = 0; ndx < numElements; ++ndx)
181                 negativeFloats[ndx] = -positiveFloats[ndx];
182
183         spec.assembly =
184                 "OpNop\n" // As the first instruction
185
186                 + string(s_ShaderPreamble) +
187
188                 "OpNop\n" // After OpEntryPoint but before any type definitions
189
190                 "OpSource GLSL 430\n"
191                 "OpName %main           \"main\"\n"
192                 "OpName %id             \"gl_GlobalInvocationID\"\n"
193
194                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
195
196                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
197
198                 "OpNop\n" // In the middle of type definitions
199
200                 + string(s_InputOutputBuffer) +
201
202                 "%id        = OpVariable %uvec3ptr Input\n"
203                 "%zero      = OpConstant %i32 0\n"
204
205                 "%main      = OpFunction %void None %voidf\n"
206                 "%label     = OpLabel\n"
207                 "%idval     = OpLoad %uvec3 %id\n"
208                 "%x         = OpCompositeExtract %u32 %idval 0\n"
209
210                 "             OpNop\n" // Inside a function body
211
212                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
213                 "%inval     = OpLoad %f32 %inloc\n"
214                 "%neg       = OpFNegate %f32 %inval\n"
215                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
216                 "             OpStore %outloc %neg\n"
217                 "             OpReturn\n"
218                 "             OpFunctionEnd\n";
219         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
220         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
221         spec.numWorkGroups = IVec3(numElements, 1, 1);
222
223         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec));
224
225         return group.release();
226 }
227
228 tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
229 {
230         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction"));
231         ComputeShaderSpec                               spec;
232         de::Random                                              rnd                             (deStringHash(group->getName()));
233         const int                                               numElements             = 100;
234         vector<float>                                   positiveFloats  (numElements, 0);
235         vector<float>                                   negativeFloats  (numElements, 0);
236
237         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
238
239         for (size_t ndx = 0; ndx < numElements; ++ndx)
240                 negativeFloats[ndx] = -positiveFloats[ndx];
241
242         spec.assembly =
243                 string(s_ShaderPreamble) +
244
245                 "%fname1 = OpString \"negateInputs.comp\"\n"
246                 "%fname2 = OpString \"negateInputs\"\n"
247
248                 "OpSource GLSL 430\n"
249                 "OpName %main           \"main\"\n"
250                 "OpName %id             \"gl_GlobalInvocationID\"\n"
251
252                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
253
254                 + string(s_InputOutputBufferTraits) +
255
256                 "OpLine %fname1 0 0\n" // At the earliest possible position
257
258                 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
259
260                 "OpLine %fname1 0 1\n" // Multiple OpLines in sequence
261                 "OpLine %fname2 1 0\n" // Different filenames
262                 "OpLine %fname1 1000 100000\n"
263
264                 "%id        = OpVariable %uvec3ptr Input\n"
265                 "%zero      = OpConstant %i32 0\n"
266
267                 "OpLine %fname1 1 1\n" // Before a function
268
269                 "%main      = OpFunction %void None %voidf\n"
270                 "%label     = OpLabel\n"
271
272                 "OpLine %fname1 1 1\n" // In a function
273
274                 "%idval     = OpLoad %uvec3 %id\n"
275                 "%x         = OpCompositeExtract %u32 %idval 0\n"
276                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
277                 "%inval     = OpLoad %f32 %inloc\n"
278                 "%neg       = OpFNegate %f32 %inval\n"
279                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
280                 "             OpStore %outloc %neg\n"
281                 "             OpReturn\n"
282                 "             OpFunctionEnd\n";
283         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
284         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
285         spec.numWorkGroups = IVec3(numElements, 1, 1);
286
287         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec));
288
289         return group.release();
290 }
291
292 tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
293 {
294         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction"));
295         ComputeShaderSpec                               spec;
296         de::Random                                              rnd                             (deStringHash(group->getName()));
297         const int                                               numElements             = 100;
298         vector<float>                                   positiveFloats  (numElements, 0);
299         vector<float>                                   negativeFloats  (numElements, 0);
300
301         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
302
303         for (size_t ndx = 0; ndx < numElements; ++ndx)
304                 negativeFloats[ndx] = -positiveFloats[ndx];
305
306         spec.assembly =
307                 string(s_ShaderPreamble) +
308
309                 "%fname = OpString \"negateInputs.comp\"\n"
310
311                 "OpSource GLSL 430\n"
312                 "OpName %main           \"main\"\n"
313                 "OpName %id             \"gl_GlobalInvocationID\"\n"
314
315                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
316
317                 + string(s_InputOutputBufferTraits) +
318
319                 "OpNoLine\n" // At the earliest possible position, without preceding OpLine
320
321                 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
322
323                 "OpLine %fname 0 1\n"
324                 "OpNoLine\n" // Immediately following a preceding OpLine
325
326                 "OpLine %fname 1000 1\n"
327
328                 "%id        = OpVariable %uvec3ptr Input\n"
329                 "%zero      = OpConstant %i32 0\n"
330
331                 "OpNoLine\n" // Contents after the previous OpLine
332
333                 "%main      = OpFunction %void None %voidf\n"
334                 "%label     = OpLabel\n"
335                 "%idval     = OpLoad %uvec3 %id\n"
336                 "%x         = OpCompositeExtract %u32 %idval 0\n"
337
338                 "OpNoLine\n" // Multiple OpNoLine
339                 "OpNoLine\n"
340                 "OpNoLine\n"
341
342                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
343                 "%inval     = OpLoad %f32 %inloc\n"
344                 "%neg       = OpFNegate %f32 %inval\n"
345                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
346                 "             OpStore %outloc %neg\n"
347                 "             OpReturn\n"
348                 "             OpFunctionEnd\n";
349         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
350         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
351         spec.numWorkGroups = IVec3(numElements, 1, 1);
352
353         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec));
354
355         return group.release();
356 }
357
358 // Assembly code used for testing OpUnreachable is based on GLSL source code:
359 //
360 // #version 430
361 //
362 // layout(std140, set = 0, binding = 0) readonly buffer Input {
363 //   float elements[];
364 // } input_data;
365 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
366 //   float elements[];
367 // } output_data;
368 //
369 // void not_called_func() {
370 //   // place OpUnreachable here
371 // }
372 //
373 // uint modulo4(uint val) {
374 //   switch (val % uint(4)) {
375 //     case 0:  return 3;
376 //     case 1:  return 2;
377 //     case 2:  return 1;
378 //     case 3:  return 0;
379 //     default: return 100; // place OpUnreachable here
380 //   }
381 // }
382 //
383 // uint const5() {
384 //   return 5;
385 //   // place OpUnreachable here
386 // }
387 //
388 // void main() {
389 //   uint x = gl_GlobalInvocationID.x;
390 //   if (const5() > modulo4(1000)) {
391 //     output_data.elements[x] = -input_data.elements[x];
392 //   } else {
393 //     // place OpUnreachable here
394 //     output_data.elements[x] = input_data.elements[x];
395 //   }
396 // }
397
398 tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx)
399 {
400         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opunreachable", "Test the OpUnreachable instruction"));
401         ComputeShaderSpec                               spec;
402         de::Random                                              rnd                             (deStringHash(group->getName()));
403         const int                                               numElements             = 100;
404         vector<float>                                   positiveFloats  (numElements, 0);
405         vector<float>                                   negativeFloats  (numElements, 0);
406
407         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
408
409         for (size_t ndx = 0; ndx < numElements; ++ndx)
410                 negativeFloats[ndx] = -positiveFloats[ndx];
411
412         spec.assembly =
413                 string(s_ShaderPreamble) +
414
415                 "OpSource GLSL 430\n"
416                 "OpName %func_main            \"main\"\n"
417                 "OpName %func_not_called_func \"not_called_func(\"\n"
418                 "OpName %func_modulo4         \"modulo4(u1;\"\n"
419                 "OpName %func_const5          \"const5(\"\n"
420                 "OpName %id                   \"gl_GlobalInvocationID\"\n"
421
422                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
423
424                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
425
426                 "%u32ptr    = OpTypePointer Function %u32\n"
427                 "%uintfuint = OpTypeFunction %u32 %u32ptr\n"
428                 "%unitf     = OpTypeFunction %u32\n"
429
430                 "%id        = OpVariable %uvec3ptr Input\n"
431                 "%zero      = OpConstant %u32 0\n"
432                 "%one       = OpConstant %u32 1\n"
433                 "%two       = OpConstant %u32 2\n"
434                 "%three     = OpConstant %u32 3\n"
435                 "%four      = OpConstant %u32 4\n"
436                 "%five      = OpConstant %u32 5\n"
437                 "%hundred   = OpConstant %u32 100\n"
438                 "%thousand  = OpConstant %u32 1000\n"
439
440                 + string(s_InputOutputBuffer) +
441
442                 // Main()
443                 "%func_main   = OpFunction %void None %voidf\n"
444                 "%main_entry  = OpLabel\n"
445                 "%idval       = OpLoad %uvec3 %id\n"
446                 "%x           = OpCompositeExtract %u32 %idval 0\n"
447                 "%inloc       = OpAccessChain %f32ptr %indata %zero %x\n"
448                 "%inval       = OpLoad %f32 %inloc\n"
449                 "%outloc      = OpAccessChain %f32ptr %outdata %zero %x\n"
450                 "%ret_const5  = OpFunctionCall %u32 %func_const5\n"
451                 "%ret_modulo4 = OpFunctionCall %u32 %func_modulo4 %thousand\n"
452                 "%cmp_gt      = OpUGreaterThan %bool %ret_const5 %ret_modulo4\n"
453                 "               OpSelectionMerge %if_end None\n"
454                 "               OpBranchConditional %cmp_gt %if_true %if_false\n"
455                 "%if_true     = OpLabel\n"
456                 "%negate      = OpFNegate %f32 %inval\n"
457                 "               OpStore %outloc %negate\n"
458                 "               OpBranch %if_end\n"
459                 "%if_false    = OpLabel\n"
460                 "               OpUnreachable\n" // Unreachable else branch for if statement
461                 "%if_end      = OpLabel\n"
462                 "               OpReturn\n"
463                 "               OpFunctionEnd\n"
464
465                 // not_called_function()
466                 "%func_not_called_func  = OpFunction %void None %voidf\n"
467                 "%not_called_func_entry = OpLabel\n"
468                 "                         OpUnreachable\n" // Unreachable entry block in not called static function
469                 "                         OpFunctionEnd\n"
470
471                 // modulo4()
472                 "%func_modulo4  = OpFunction %u32 None %uintfuint\n"
473                 "%valptr        = OpFunctionParameter %u32ptr\n"
474                 "%modulo4_entry = OpLabel\n"
475                 "%val           = OpLoad %u32 %valptr\n"
476                 "%modulo        = OpUMod %u32 %val %four\n"
477                 "                 OpSelectionMerge %switch_merge None\n"
478                 "                 OpSwitch %modulo %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
479                 "%case0         = OpLabel\n"
480                 "                 OpReturnValue %three\n"
481                 "%case1         = OpLabel\n"
482                 "                 OpReturnValue %two\n"
483                 "%case2         = OpLabel\n"
484                 "                 OpReturnValue %one\n"
485                 "%case3         = OpLabel\n"
486                 "                 OpReturnValue %zero\n"
487                 "%default       = OpLabel\n"
488                 "                 OpUnreachable\n" // Unreachable default case for switch statement
489                 "%switch_merge  = OpLabel\n"
490                 "                 OpUnreachable\n" // Unreachable merge block for switch statement
491                 "                 OpFunctionEnd\n"
492
493                 // const5()
494                 "%func_const5  = OpFunction %u32 None %unitf\n"
495                 "%const5_entry = OpLabel\n"
496                 "                OpReturnValue %five\n"
497                 "%unreachable  = OpLabel\n"
498                 "                OpUnreachable\n" // Unreachable block in function
499                 "                OpFunctionEnd\n";
500         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
501         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
502         spec.numWorkGroups = IVec3(numElements, 1, 1);
503
504         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec));
505
506         return group.release();
507 }
508
509 // Assembly code used for testing decoration group is based on GLSL source code:
510 //
511 // #version 430
512 //
513 // layout(std140, set = 0, binding = 0) readonly buffer Input0 {
514 //   float elements[];
515 // } input_data0;
516 // layout(std140, set = 0, binding = 1) readonly buffer Input1 {
517 //   float elements[];
518 // } input_data1;
519 // layout(std140, set = 0, binding = 2) readonly buffer Input2 {
520 //   float elements[];
521 // } input_data2;
522 // layout(std140, set = 0, binding = 3) readonly buffer Input3 {
523 //   float elements[];
524 // } input_data3;
525 // layout(std140, set = 0, binding = 4) readonly buffer Input4 {
526 //   float elements[];
527 // } input_data4;
528 // layout(std140, set = 0, binding = 5) writeonly buffer Output {
529 //   float elements[];
530 // } output_data;
531 //
532 // void main() {
533 //   uint x = gl_GlobalInvocationID.x;
534 //   output_data.elements[x] = input_data0.elements[x] + input_data1.elements[x] + input_data2.elements[x] + input_data3.elements[x] + input_data4.elements[x];
535 // }
536 tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx)
537 {
538         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "decoration_group", "Test the OpDecorationGroup & OpGroupDecorate instruction"));
539         ComputeShaderSpec                               spec;
540         de::Random                                              rnd                             (deStringHash(group->getName()));
541         const int                                               numElements             = 100;
542         vector<float>                                   inputFloats0    (numElements, 0);
543         vector<float>                                   inputFloats1    (numElements, 0);
544         vector<float>                                   inputFloats2    (numElements, 0);
545         vector<float>                                   inputFloats3    (numElements, 0);
546         vector<float>                                   inputFloats4    (numElements, 0);
547         vector<float>                                   outputFloats    (numElements, 0);
548
549         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats0[0], numElements);
550         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats1[0], numElements);
551         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats2[0], numElements);
552         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats3[0], numElements);
553         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats4[0], numElements);
554
555         for (size_t ndx = 0; ndx < numElements; ++ndx)
556                 outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx];
557
558         spec.assembly =
559                 string(s_ShaderPreamble) +
560
561                 "OpSource GLSL 430\n"
562                 "OpName %main \"main\"\n"
563                 "OpName %id \"gl_GlobalInvocationID\"\n"
564
565                 // Not using group decoration on variable.
566                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
567                 // Not using group decoration on type.
568                 "OpDecorate %f32arr ArrayStride 4\n"
569
570                 "OpDecorate %groups BufferBlock\n"
571                 "OpDecorate %groupm Offset 0\n"
572                 "%groups = OpDecorationGroup\n"
573                 "%groupm = OpDecorationGroup\n"
574
575                 // Group decoration on multiple structs.
576                 "OpGroupDecorate %groups %outbuf %inbuf0 %inbuf1 %inbuf2 %inbuf3 %inbuf4\n"
577                 // Group decoration on multiple struct members.
578                 "OpGroupMemberDecorate %groupm %outbuf 0 %inbuf0 0 %inbuf1 0 %inbuf2 0 %inbuf3 0 %inbuf4 0\n"
579
580                 "OpDecorate %group1 DescriptorSet 0\n"
581                 "OpDecorate %group3 DescriptorSet 0\n"
582                 "OpDecorate %group3 NonWritable\n"
583                 "OpDecorate %group3 Restrict\n"
584                 "%group0 = OpDecorationGroup\n"
585                 "%group1 = OpDecorationGroup\n"
586                 "%group3 = OpDecorationGroup\n"
587
588                 // Applying the same decoration group multiple times.
589                 "OpGroupDecorate %group1 %outdata\n"
590                 "OpGroupDecorate %group1 %outdata\n"
591                 "OpGroupDecorate %group1 %outdata\n"
592                 "OpDecorate %outdata DescriptorSet 0\n"
593                 "OpDecorate %outdata Binding 5\n"
594                 // Applying decoration group containing nothing.
595                 "OpGroupDecorate %group0 %indata0\n"
596                 "OpDecorate %indata0 DescriptorSet 0\n"
597                 "OpDecorate %indata0 Binding 0\n"
598                 // Applying decoration group containing one decoration.
599                 "OpGroupDecorate %group1 %indata1\n"
600                 "OpDecorate %indata1 Binding 1\n"
601                 // Applying decoration group containing multiple decorations.
602                 "OpGroupDecorate %group3 %indata2 %indata3\n"
603                 "OpDecorate %indata2 Binding 2\n"
604                 "OpDecorate %indata3 Binding 3\n"
605                 // Applying multiple decoration groups (with overlapping).
606                 "OpGroupDecorate %group0 %indata4\n"
607                 "OpGroupDecorate %group1 %indata4\n"
608                 "OpGroupDecorate %group3 %indata4\n"
609                 "OpDecorate %indata4 Binding 4\n"
610
611                 + string(s_CommonTypes) +
612
613                 "%id   = OpVariable %uvec3ptr Input\n"
614                 "%zero = OpConstant %i32 0\n"
615
616                 "%outbuf    = OpTypeStruct %f32arr\n"
617                 "%outbufptr = OpTypePointer Uniform %outbuf\n"
618                 "%outdata   = OpVariable %outbufptr Uniform\n"
619                 "%inbuf0    = OpTypeStruct %f32arr\n"
620                 "%inbuf0ptr = OpTypePointer Uniform %inbuf0\n"
621                 "%indata0   = OpVariable %inbuf0ptr Uniform\n"
622                 "%inbuf1    = OpTypeStruct %f32arr\n"
623                 "%inbuf1ptr = OpTypePointer Uniform %inbuf1\n"
624                 "%indata1   = OpVariable %inbuf1ptr Uniform\n"
625                 "%inbuf2    = OpTypeStruct %f32arr\n"
626                 "%inbuf2ptr = OpTypePointer Uniform %inbuf2\n"
627                 "%indata2   = OpVariable %inbuf2ptr Uniform\n"
628                 "%inbuf3    = OpTypeStruct %f32arr\n"
629                 "%inbuf3ptr = OpTypePointer Uniform %inbuf3\n"
630                 "%indata3   = OpVariable %inbuf3ptr Uniform\n"
631                 "%inbuf4    = OpTypeStruct %f32arr\n"
632                 "%inbufptr  = OpTypePointer Uniform %inbuf4\n"
633                 "%indata4   = OpVariable %inbufptr Uniform\n"
634
635                 "%main   = OpFunction %void None %voidf\n"
636                 "%label  = OpLabel\n"
637                 "%idval  = OpLoad %uvec3 %id\n"
638                 "%x      = OpCompositeExtract %u32 %idval 0\n"
639                 "%inloc0 = OpAccessChain %f32ptr %indata0 %zero %x\n"
640                 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
641                 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
642                 "%inloc3 = OpAccessChain %f32ptr %indata3 %zero %x\n"
643                 "%inloc4 = OpAccessChain %f32ptr %indata4 %zero %x\n"
644                 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
645                 "%inval0 = OpLoad %f32 %inloc0\n"
646                 "%inval1 = OpLoad %f32 %inloc1\n"
647                 "%inval2 = OpLoad %f32 %inloc2\n"
648                 "%inval3 = OpLoad %f32 %inloc3\n"
649                 "%inval4 = OpLoad %f32 %inloc4\n"
650                 "%add0   = OpFAdd %f32 %inval0 %inval1\n"
651                 "%add1   = OpFAdd %f32 %add0 %inval2\n"
652                 "%add2   = OpFAdd %f32 %add1 %inval3\n"
653                 "%add    = OpFAdd %f32 %add2 %inval4\n"
654                 "          OpStore %outloc %add\n"
655                 "          OpReturn\n"
656                 "          OpFunctionEnd\n";
657         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats0)));
658         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
659         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
660         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
661         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
662         spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
663         spec.numWorkGroups = IVec3(numElements, 1, 1);
664
665         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec));
666
667         return group.release();
668 }
669
670 tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx)
671 {
672         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
673         ComputeShaderSpec                               spec;
674         de::Random                                              rnd                             (deStringHash(group->getName()));
675         const int                                               numElements             = 100;
676         vector<float>                                   inputFloats             (numElements, 0);
677         vector<float>                                   outputFloats    (numElements, 0);
678
679         fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements);
680
681         for (size_t ndx = 0; ndx < numElements; ++ndx)
682         {
683                 switch (ndx % 3)
684                 {
685                         case 0:         outputFloats[ndx] = inputFloats[ndx] + 5.5f;    break;
686                         case 1:         outputFloats[ndx] = inputFloats[ndx] + 20.5f;   break;
687                         case 2:         outputFloats[ndx] = inputFloats[ndx] + 1.75f;   break;
688                         default:        break;
689                 }
690         }
691
692         spec.assembly =
693                 string(s_ShaderPreamble) +
694
695                 "OpSource GLSL 430\n"
696                 "OpName %main \"main\"\n"
697                 "OpName %id \"gl_GlobalInvocationID\"\n"
698
699                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
700
701                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
702
703                 "%id = OpVariable %uvec3ptr Input\n"
704                 "%zero       = OpConstant %i32 0\n"
705                 "%three      = OpConstant %u32 3\n"
706                 "%constf5p5  = OpConstant %f32 5.5\n"
707                 "%constf20p5 = OpConstant %f32 20.5\n"
708                 "%constf1p75 = OpConstant %f32 1.75\n"
709                 "%constf8p5  = OpConstant %f32 8.5\n"
710                 "%constf6p5  = OpConstant %f32 6.5\n"
711
712                 "%main     = OpFunction %void None %voidf\n"
713                 "%entry    = OpLabel\n"
714                 "%idval    = OpLoad %uvec3 %id\n"
715                 "%x        = OpCompositeExtract %u32 %idval 0\n"
716                 "%selector = OpUMod %u32 %x %three\n"
717                 "            OpSelectionMerge %default None\n"
718                 "            OpSwitch %selector %default 0 %case0 1 %case1 2 %case2\n"
719
720                 // Case 1 before OpPhi.
721                 "%case1    = OpLabel\n"
722                 "            OpBranch %phi\n"
723
724                 "%default  = OpLabel\n"
725                 "            OpUnreachable\n"
726
727                 "%phi      = OpLabel\n"
728                 "%operand  = OpPhi %f32 %constf1p75 %case2   %constf20p5 %case1   %constf5p5 %case0" // not in the order of blocks
729         "                       %constf8p5  %phi     %constf6p5  %default\n" // from the same block & from an unreachable block
730                 "%inloc    = OpAccessChain %f32ptr %indata %zero %x\n"
731                 "%inval    = OpLoad %f32 %inloc\n"
732                 "%add      = OpFAdd %f32 %inval %operand\n"
733                 "%outloc   = OpAccessChain %f32ptr %outdata %zero %x\n"
734                 "            OpStore %outloc %add\n"
735                 "            OpReturn\n"
736
737                 // Case 0 after OpPhi.
738                 "%case0    = OpLabel\n"
739                 "            OpBranch %phi\n"
740
741
742                 // Case 2 after OpPhi.
743                 "%case2    = OpLabel\n"
744                 "            OpBranch %phi\n"
745
746                 "            OpFunctionEnd\n";
747         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
748         spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
749         spec.numWorkGroups = IVec3(numElements, 1, 1);
750
751         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpPhi corner cases", spec));
752
753         return group.release();
754 }
755
756 // Assembly code used for testing block order is based on GLSL source code:
757 //
758 // #version 430
759 //
760 // layout(std140, set = 0, binding = 0) readonly buffer Input {
761 //   float elements[];
762 // } input_data;
763 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
764 //   float elements[];
765 // } output_data;
766 //
767 // void main() {
768 //   uint x = gl_GlobalInvocationID.x;
769 //   output_data.elements[x] = input_data.elements[x];
770 //   if (x > uint(50)) {
771 //     switch (x % uint(3)) {
772 //       case 0: output_data.elements[x] += 1.5f; break;
773 //       case 1: output_data.elements[x] += 42.f; break;
774 //       case 2: output_data.elements[x] -= 27.f; break;
775 //       default: break;
776 //     }
777 //   } else {
778 //     output_data.elements[x] = -input_data.elements[x];
779 //   }
780 // }
781 tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
782 {
783         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "block_order", "Test block orders"));
784         ComputeShaderSpec                               spec;
785         de::Random                                              rnd                             (deStringHash(group->getName()));
786         const int                                               numElements             = 100;
787         vector<float>                                   inputFloats             (numElements, 0);
788         vector<float>                                   outputFloats    (numElements, 0);
789
790         fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
791
792         for (size_t ndx = 0; ndx <= 50; ++ndx)
793                 outputFloats[ndx] = -inputFloats[ndx];
794
795         for (size_t ndx = 51; ndx < numElements; ++ndx)
796         {
797                 switch (ndx % 3)
798                 {
799                         case 0:         outputFloats[ndx] = inputFloats[ndx] + 1.5f; break;
800                         case 1:         outputFloats[ndx] = inputFloats[ndx] + 42.f; break;
801                         case 2:         outputFloats[ndx] = inputFloats[ndx] - 27.f; break;
802                         default:        break;
803                 }
804         }
805
806         spec.assembly =
807                 string(s_ShaderPreamble) +
808
809                 "OpSource GLSL 430\n"
810                 "OpName %main \"main\"\n"
811                 "OpName %id \"gl_GlobalInvocationID\"\n"
812
813                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
814
815                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
816
817                 "%u32ptr       = OpTypePointer Function %u32\n"
818                 "%u32ptr_input = OpTypePointer Input %u32\n"
819
820                 + string(s_InputOutputBuffer) +
821
822                 "%id        = OpVariable %uvec3ptr Input\n"
823                 "%zero      = OpConstant %i32 0\n"
824                 "%const3    = OpConstant %u32 3\n"
825                 "%const50   = OpConstant %u32 50\n"
826                 "%constf1p5 = OpConstant %f32 1.5\n"
827                 "%constf27  = OpConstant %f32 27.0\n"
828                 "%constf42  = OpConstant %f32 42.0\n"
829
830                 "%main = OpFunction %void None %voidf\n"
831
832                 // entry block.
833                 "%entry    = OpLabel\n"
834
835                 // Create a temporary variable to hold the value of gl_GlobalInvocationID.x.
836                 "%xvar     = OpVariable %u32ptr Function\n"
837                 "%xptr     = OpAccessChain %u32ptr_input %id %zero\n"
838                 "%x        = OpLoad %u32 %xptr\n"
839                 "            OpStore %xvar %x\n"
840
841                 "%cmp      = OpUGreaterThan %bool %x %const50\n"
842                 "            OpSelectionMerge %if_merge None\n"
843                 "            OpBranchConditional %cmp %if_true %if_false\n"
844
845                 // Merge block for switch-statement: placed at the beginning.
846                 "%switch_merge = OpLabel\n"
847                 "                OpBranch %if_merge\n"
848
849                 // Case 1 for switch-statement.
850                 "%case1    = OpLabel\n"
851                 "%x_1      = OpLoad %u32 %xvar\n"
852                 "%inloc_1  = OpAccessChain %f32ptr %indata %zero %x_1\n"
853                 "%inval_1  = OpLoad %f32 %inloc_1\n"
854                 "%addf42   = OpFAdd %f32 %inval_1 %constf42\n"
855                 "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
856                 "            OpStore %outloc_1 %addf42\n"
857                 "            OpBranch %switch_merge\n"
858
859                 // False branch for if-statement: placed in the middle of switch cases and before true branch.
860                 "%if_false = OpLabel\n"
861                 "%x_f      = OpLoad %u32 %xvar\n"
862                 "%inloc_f  = OpAccessChain %f32ptr %indata %zero %x_f\n"
863                 "%inval_f  = OpLoad %f32 %inloc_f\n"
864                 "%negate   = OpFNegate %f32 %inval_f\n"
865                 "%outloc_f = OpAccessChain %f32ptr %outdata %zero %x_f\n"
866                 "            OpStore %outloc_f %negate\n"
867                 "            OpBranch %if_merge\n"
868
869                 // Merge block for if-statement: placed in the middle of true and false branch.
870                 "%if_merge = OpLabel\n"
871                 "            OpReturn\n"
872
873                 // True branch for if-statement: placed in the middle of swtich cases and after the false branch.
874                 "%if_true  = OpLabel\n"
875                 "%xval_t   = OpLoad %u32 %xvar\n"
876                 "%mod      = OpUMod %u32 %xval_t %const3\n"
877                 "            OpSelectionMerge %switch_merge None\n"
878                 "            OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n"
879
880                 // Case 2 for switch-statement.
881                 "%case2    = OpLabel\n"
882                 "%x_2      = OpLoad %u32 %xvar\n"
883                 "%inloc_2  = OpAccessChain %f32ptr %indata %zero %x_2\n"
884                 "%inval_2  = OpLoad %f32 %inloc_2\n"
885                 "%subf27   = OpFSub %f32 %inval_2 %constf27\n"
886                 "%outloc_2 = OpAccessChain %f32ptr %outdata %zero %x_2\n"
887                 "            OpStore %outloc_2 %subf27\n"
888                 "            OpBranch %switch_merge\n"
889
890                 // Default case for switch-statement: placed in the middle of normal cases.
891                 "%default = OpLabel\n"
892                 "           OpBranch %switch_merge\n"
893
894                 // Case 0 for switch-statement: out of order.
895                 "%case0    = OpLabel\n"
896                 "%x_0      = OpLoad %u32 %xvar\n"
897                 "%inloc_0  = OpAccessChain %f32ptr %indata %zero %x_0\n"
898                 "%inval_0  = OpLoad %f32 %inloc_0\n"
899                 "%addf1p5  = OpFAdd %f32 %inval_0 %constf1p5\n"
900                 "%outloc_0 = OpAccessChain %f32ptr %outdata %zero %x_0\n"
901                 "            OpStore %outloc_0 %addf1p5\n"
902                 "            OpBranch %switch_merge\n"
903
904                 "            OpFunctionEnd\n";
905         spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
906         spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
907         spec.numWorkGroups = IVec3(numElements, 1, 1);
908
909         group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec));
910
911         return group.release();
912 }
913
914 struct CaseParameter
915 {
916         const char*             name;
917         string                  param;
918
919         CaseParameter   (const char* case_, const string& param_) : name(case_), param(param_) {}
920 };
921
922 tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
923 {
924         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction"));
925         vector<CaseParameter>                   cases;
926         de::Random                                              rnd                             (deStringHash(group->getName()));
927         const int                                               numElements             = 100;
928         vector<float>                                   positiveFloats  (numElements, 0);
929         vector<float>                                   negativeFloats  (numElements, 0);
930         const StringTemplate                    shaderTemplate  (
931                 "OpCapability Shader\n"
932                 "OpMemoryModel Logical GLSL450\n"
933
934                 "OpEntryPoint GLCompute %main \"main\" %id\n"
935                 "OpExecutionMode %main LocalSize 1 1 1\n"
936
937                 "${SOURCE}\n"
938
939                 "OpName %main           \"main\"\n"
940                 "OpName %id             \"gl_GlobalInvocationID\"\n"
941
942                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
943
944                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
945
946                 "%id        = OpVariable %uvec3ptr Input\n"
947                 "%zero      = OpConstant %i32 0\n"
948
949                 "%main      = OpFunction %void None %voidf\n"
950                 "%label     = OpLabel\n"
951                 "%idval     = OpLoad %uvec3 %id\n"
952                 "%x         = OpCompositeExtract %u32 %idval 0\n"
953                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
954                 "%inval     = OpLoad %f32 %inloc\n"
955                 "%neg       = OpFNegate %f32 %inval\n"
956                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
957                 "             OpStore %outloc %neg\n"
958                 "             OpReturn\n"
959                 "             OpFunctionEnd\n");
960
961         cases.push_back(CaseParameter("unknown_source",                                                 "OpSource Unknown 0"));
962         cases.push_back(CaseParameter("wrong_source",                                                   "OpSource OpenCL 210"));
963         cases.push_back(CaseParameter("normal_filename",                                                "%fname = OpString \"filename\"\n"
964                                                                                                                                                         "OpSource GLSL 430 %fname"));
965         cases.push_back(CaseParameter("empty_filename",                                                 "%fname = OpString \"\"\n"
966                                                                                                                                                         "OpSource GLSL 430 %fname"));
967         cases.push_back(CaseParameter("normal_source_code",                                             "%fname = OpString \"filename\"\n"
968                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\""));
969         cases.push_back(CaseParameter("empty_source_code",                                              "%fname = OpString \"filename\"\n"
970                                                                                                                                                         "OpSource GLSL 430 %fname \"\""));
971         cases.push_back(CaseParameter("long_source_code",                                               "%fname = OpString \"filename\"\n"
972                                                                                                                                                         "OpSource GLSL 430 %fname \"" + string(65530, 'x') + "\"")); // word count: 65535
973         cases.push_back(CaseParameter("utf8_source_code",                                               "%fname = OpString \"filename\"\n"
974                                                                                                                                                         "OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol
975         cases.push_back(CaseParameter("normal_sourcecontinued",                                 "%fname = OpString \"filename\"\n"
976                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\nvo\"\n"
977                                                                                                                                                         "OpSourceContinued \"id main() {}\""));
978         cases.push_back(CaseParameter("empty_sourcecontinued",                                  "%fname = OpString \"filename\"\n"
979                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
980                                                                                                                                                         "OpSourceContinued \"\""));
981         cases.push_back(CaseParameter("long_sourcecontinued",                                   "%fname = OpString \"filename\"\n"
982                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
983                                                                                                                                                         "OpSourceContinued \"" + string(65533, 'x') + "\"")); // word count: 65535
984         cases.push_back(CaseParameter("utf8_sourcecontinued",                                   "%fname = OpString \"filename\"\n"
985                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
986                                                                                                                                                         "OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol
987         cases.push_back(CaseParameter("multi_sourcecontinued",                                  "%fname = OpString \"filename\"\n"
988                                                                                                                                                         "OpSource GLSL 430 %fname \"#version 430\n\"\n"
989                                                                                                                                                         "OpSourceContinued \"void\"\n"
990                                                                                                                                                         "OpSourceContinued \"main()\"\n"
991                                                                                                                                                         "OpSourceContinued \"{}\""));
992         cases.push_back(CaseParameter("empty_source_before_sourcecontinued",    "%fname = OpString \"filename\"\n"
993                                                                                                                                                         "OpSource GLSL 430 %fname \"\"\n"
994                                                                                                                                                         "OpSourceContinued \"#version 430\nvoid main() {}\""));
995
996         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
997
998         for (size_t ndx = 0; ndx < numElements; ++ndx)
999                 negativeFloats[ndx] = -positiveFloats[ndx];
1000
1001         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1002         {
1003                 map<string, string>             specializations;
1004                 ComputeShaderSpec               spec;
1005
1006                 specializations["SOURCE"] = cases[caseNdx].param;
1007                 spec.assembly = shaderTemplate.specialize(specializations);
1008                 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1009                 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1010                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1011
1012                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1013         }
1014
1015         return group.release();
1016 }
1017
1018 tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx)
1019 {
1020         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opsourceextension", "Tests the OpSource instruction"));
1021         vector<CaseParameter>                   cases;
1022         de::Random                                              rnd                             (deStringHash(group->getName()));
1023         const int                                               numElements             = 100;
1024         vector<float>                                   inputFloats             (numElements, 0);
1025         vector<float>                                   outputFloats    (numElements, 0);
1026         const StringTemplate                    shaderTemplate  (
1027                 string(s_ShaderPreamble) +
1028
1029                 "OpSourceExtension \"${EXTENSION}\"\n"
1030
1031                 "OpName %main           \"main\"\n"
1032                 "OpName %id             \"gl_GlobalInvocationID\"\n"
1033
1034                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1035
1036                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1037
1038                 "%id        = OpVariable %uvec3ptr Input\n"
1039                 "%zero      = OpConstant %i32 0\n"
1040
1041                 "%main      = OpFunction %void None %voidf\n"
1042                 "%label     = OpLabel\n"
1043                 "%idval     = OpLoad %uvec3 %id\n"
1044                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1045                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
1046                 "%inval     = OpLoad %f32 %inloc\n"
1047                 "%neg       = OpFNegate %f32 %inval\n"
1048                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
1049                 "             OpStore %outloc %neg\n"
1050                 "             OpReturn\n"
1051                 "             OpFunctionEnd\n");
1052
1053         cases.push_back(CaseParameter("empty_extension",        ""));
1054         cases.push_back(CaseParameter("real_extension",         "GL_ARB_texture_rectangle"));
1055         cases.push_back(CaseParameter("fake_extension",         "GL_ARB_im_the_ultimate_extension"));
1056         cases.push_back(CaseParameter("utf8_extension",         "GL_ARB_\xE2\x98\x82\xE2\x98\x85"));
1057         cases.push_back(CaseParameter("long_extension",         string(65533, 'e'))); // word count: 65535
1058
1059         fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
1060
1061         for (size_t ndx = 0; ndx < numElements; ++ndx)
1062                 outputFloats[ndx] = -inputFloats[ndx];
1063
1064         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1065         {
1066                 map<string, string>             specializations;
1067                 ComputeShaderSpec               spec;
1068
1069                 specializations["EXTENSION"] = cases[caseNdx].param;
1070                 spec.assembly = shaderTemplate.specialize(specializations);
1071                 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1072                 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1073                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1074
1075                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1076         }
1077
1078         return group.release();
1079 }
1080
1081 // Checks that a compute shader can generate a constant null value of various types, without exercising a computation on it.
1082 tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx)
1083 {
1084         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opconstantnull", "Tests the OpConstantNull instruction"));
1085         vector<CaseParameter>                   cases;
1086         de::Random                                              rnd                             (deStringHash(group->getName()));
1087         const int                                               numElements             = 100;
1088         vector<float>                                   positiveFloats  (numElements, 0);
1089         vector<float>                                   negativeFloats  (numElements, 0);
1090         const StringTemplate                    shaderTemplate  (
1091                 string(s_ShaderPreamble) +
1092
1093                 "OpSource GLSL 430\n"
1094                 "OpName %main           \"main\"\n"
1095                 "OpName %id             \"gl_GlobalInvocationID\"\n"
1096
1097                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1098
1099                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1100
1101                 "${TYPE}\n"
1102                 "%null      = OpConstantNull %type\n"
1103
1104                 "%id        = OpVariable %uvec3ptr Input\n"
1105                 "%zero      = OpConstant %i32 0\n"
1106
1107                 "%main      = OpFunction %void None %voidf\n"
1108                 "%label     = OpLabel\n"
1109                 "%idval     = OpLoad %uvec3 %id\n"
1110                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1111                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
1112                 "%inval     = OpLoad %f32 %inloc\n"
1113                 "%neg       = OpFNegate %f32 %inval\n"
1114                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
1115                 "             OpStore %outloc %neg\n"
1116                 "             OpReturn\n"
1117                 "             OpFunctionEnd\n");
1118
1119         cases.push_back(CaseParameter("bool",                   "%type = OpTypeBool"));
1120         cases.push_back(CaseParameter("sint32",                 "%type = OpTypeInt 32 1"));
1121         cases.push_back(CaseParameter("uint32",                 "%type = OpTypeInt 32 0"));
1122         cases.push_back(CaseParameter("float32",                "%type = OpTypeFloat 32"));
1123         cases.push_back(CaseParameter("vec4float32",    "%type = OpTypeVector %f32 4"));
1124         cases.push_back(CaseParameter("vec3bool",               "%type = OpTypeVector %bool 3"));
1125         cases.push_back(CaseParameter("vec2uint32",             "%type = OpTypeVector %u32 2"));
1126         cases.push_back(CaseParameter("matrix",                 "%type = OpTypeMatrix %uvec3 3"));
1127         cases.push_back(CaseParameter("array",                  "%100 = OpConstant %u32 100\n"
1128                                                                                                         "%type = OpTypeArray %i32 %100"));
1129         cases.push_back(CaseParameter("runtimearray",   "%type = OpTypeRuntimeArray %f32"));
1130         cases.push_back(CaseParameter("struct",                 "%type = OpTypeStruct %f32 %i32 %u32"));
1131         cases.push_back(CaseParameter("pointer",                "%type = OpTypePointer Function %i32"));
1132
1133         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1134
1135         for (size_t ndx = 0; ndx < numElements; ++ndx)
1136                 negativeFloats[ndx] = -positiveFloats[ndx];
1137
1138         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1139         {
1140                 map<string, string>             specializations;
1141                 ComputeShaderSpec               spec;
1142
1143                 specializations["TYPE"] = cases[caseNdx].param;
1144                 spec.assembly = shaderTemplate.specialize(specializations);
1145                 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1146                 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1147                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1148
1149                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1150         }
1151
1152         return group.release();
1153 }
1154
1155 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
1156 tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx)
1157 {
1158         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "Tests the OpConstantComposite instruction"));
1159         vector<CaseParameter>                   cases;
1160         de::Random                                              rnd                             (deStringHash(group->getName()));
1161         const int                                               numElements             = 100;
1162         vector<float>                                   positiveFloats  (numElements, 0);
1163         vector<float>                                   negativeFloats  (numElements, 0);
1164         const StringTemplate                    shaderTemplate  (
1165                 string(s_ShaderPreamble) +
1166
1167                 "OpSource GLSL 430\n"
1168                 "OpName %main           \"main\"\n"
1169                 "OpName %id             \"gl_GlobalInvocationID\"\n"
1170
1171                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1172
1173                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1174
1175                 "%id        = OpVariable %uvec3ptr Input\n"
1176                 "%zero      = OpConstant %i32 0\n"
1177
1178                 "${CONSTANT}\n"
1179
1180                 "%main      = OpFunction %void None %voidf\n"
1181                 "%label     = OpLabel\n"
1182                 "%idval     = OpLoad %uvec3 %id\n"
1183                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1184                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
1185                 "%inval     = OpLoad %f32 %inloc\n"
1186                 "%neg       = OpFNegate %f32 %inval\n"
1187                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
1188                 "             OpStore %outloc %neg\n"
1189                 "             OpReturn\n"
1190                 "             OpFunctionEnd\n");
1191
1192         cases.push_back(CaseParameter("vector",                 "%five = OpConstant %u32 5\n"
1193                                                                                                         "%const = OpConstantComposite %uvec3 %five %zero %five"));
1194         cases.push_back(CaseParameter("matrix",                 "%m3uvec3 = OpTypeMatrix %uvec3 3\n"
1195                                                                                                         "%ten = OpConstant %u32 10\n"
1196                                                                                                         "%vec = OpConstantComposite %uvec3 %ten %zero %ten\n"
1197                                                                                                         "%mat = OpConstantComposite %m3uvec3 %vec %vec %vec"));
1198         cases.push_back(CaseParameter("struct",                 "%m2vec3 = OpTypeMatrix %uvec3 2\n"
1199                                                                                                         "%struct = OpTypeStruct %u32 %f32 %uvec3 %m2vec3\n"
1200                                                                                                         "%one = OpConstant %u32 1\n"
1201                                                                                                         "%point5 = OpConstant %f32 0.5\n"
1202                                                                                                         "%vec = OpConstantComposite %uvec3 %one %one %zero\n"
1203                                                                                                         "%mat = OpConstantComposite %m2vec3 %vec %vec\n"
1204                                                                                                         "%const = OpConstantComposite %one %point5 %vec %mat"));
1205         cases.push_back(CaseParameter("nested_struct",  "%st1 = OpTypeStruct %u32 %f32\n"
1206                                                                                                         "%st2 = OpTypeStruct %i32 %i32\n"
1207                                                                                                         "%struct = OpTypeStruct %st1 %st2\n"
1208                                                                                                         "%point5 = OpConstant %f32 0.5\n"
1209                                                                                                         "%one = OpConstant %u32 1\n"
1210                                                                                                         "%ten = OpConstant %i32 10\n"
1211                                                                                                         "%st1val = OpConstantComposite %one %point5\n"
1212                                                                                                         "%st2val = OpConstantComposite %ten %ten\n"
1213                                                                                                         "%const = OpConstantComposite %st1val %st2val"));
1214
1215         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1216
1217         for (size_t ndx = 0; ndx < numElements; ++ndx)
1218                 negativeFloats[ndx] = -positiveFloats[ndx];
1219
1220         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1221         {
1222                 map<string, string>             specializations;
1223                 ComputeShaderSpec               spec;
1224
1225                 specializations["CONSTANT"] = cases[caseNdx].param;
1226                 spec.assembly = shaderTemplate.specialize(specializations);
1227                 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1228                 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1229                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1230
1231                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1232         }
1233
1234         return group.release();
1235 }
1236
1237 // Checks that constant null/composite values can be used in computation.
1238 tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
1239 {
1240         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opconstantnullcomposite", "Spotcheck the OpConstantNull & OpConstantComposite instruction"));
1241         ComputeShaderSpec                               spec;
1242         de::Random                                              rnd                             (deStringHash(group->getName()));
1243         const int                                               numElements             = 100;
1244         vector<float>                                   positiveFloats  (numElements, 0);
1245         vector<float>                                   negativeFloats  (numElements, 0);
1246
1247         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1248
1249         for (size_t ndx = 0; ndx < numElements; ++ndx)
1250                 negativeFloats[ndx] = -positiveFloats[ndx];
1251
1252         spec.assembly =
1253                 "OpCapability Shader\n"
1254                 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
1255                 "OpMemoryModel Logical GLSL450\n"
1256                 "OpEntryPoint GLCompute %main \"main\" %id\n"
1257                 "OpExecutionMode %main LocalSize 1 1 1\n"
1258
1259                 "OpSource GLSL 430\n"
1260                 "OpName %main           \"main\"\n"
1261                 "OpName %id             \"gl_GlobalInvocationID\"\n"
1262
1263                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1264
1265                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
1266
1267                 "%fvec3     = OpTypeVector %f32 3\n"
1268                 "%fmat      = OpTypeMatrix %fvec3 3\n"
1269                 "%ten       = OpConstant %u32 10\n"
1270                 "%f32arr10  = OpTypeArray %f32 %ten\n"
1271                 "%fst       = OpTypeStruct %f32 %f32\n"
1272
1273                 + string(s_InputOutputBuffer) +
1274
1275                 "%id        = OpVariable %uvec3ptr Input\n"
1276                 "%zero      = OpConstant %i32 0\n"
1277
1278                 // Create a bunch of null values
1279                 "%unull     = OpConstantNull %u32\n"
1280                 "%fnull     = OpConstantNull %f32\n"
1281                 "%vnull     = OpConstantNull %fvec3\n"
1282                 "%mnull     = OpConstantNull %fmat\n"
1283                 "%anull     = OpConstantNull %f32arr10\n"
1284                 "%snull     = OpConstantComposite %fst %fnull %fnull\n"
1285
1286                 "%main      = OpFunction %void None %voidf\n"
1287                 "%label     = OpLabel\n"
1288                 "%idval     = OpLoad %uvec3 %id\n"
1289                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1290                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
1291                 "%inval     = OpLoad %f32 %inloc\n"
1292                 "%neg       = OpFNegate %f32 %inval\n"
1293
1294                 // Get the abs() of (a certain element of) those null values
1295                 "%unull_cov = OpConvertUToF %f32 %unull\n"
1296                 "%unull_abs = OpExtInst %f32 %std450 FAbs %unull_cov\n"
1297                 "%fnull_abs = OpExtInst %f32 %std450 FAbs %fnull\n"
1298                 "%vnull_0   = OpCompositeExtract %f32 %vnull 0\n"
1299                 "%vnull_abs = OpExtInst %f32 %std450 FAbs %vnull_0\n"
1300                 "%mnull_12  = OpCompositeExtract %f32 %mnull 1 2\n"
1301                 "%mnull_abs = OpExtInst %f32 %std450 FAbs %mnull_12\n"
1302                 "%anull_3   = OpCompositeExtract %f32 %anull 3\n"
1303                 "%anull_abs = OpExtInst %f32 %std450 FAbs %anull_3\n"
1304                 "%snull_1   = OpCompositeExtract %f32 %snull 1\n"
1305                 "%snull_abs = OpExtInst %f32 %std450 FAbs %snull_1\n"
1306
1307                 // Add them all
1308                 "%add1      = OpFAdd %f32 %neg  %unull_abs\n"
1309                 "%add2      = OpFAdd %f32 %add1 %fnull_abs\n"
1310                 "%add3      = OpFAdd %f32 %add2 %vnull_abs\n"
1311                 "%add4      = OpFAdd %f32 %add3 %mnull_abs\n"
1312                 "%add5      = OpFAdd %f32 %add4 %anull_abs\n"
1313                 "%final     = OpFAdd %f32 %add5 %snull_abs\n"
1314
1315                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
1316                 "             OpStore %outloc %final\n" // write to output
1317                 "             OpReturn\n"
1318                 "             OpFunctionEnd\n";
1319         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1320         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1321         spec.numWorkGroups = IVec3(numElements, 1, 1);
1322
1323         group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec));
1324
1325         return group.release();
1326 }
1327
1328 // Assembly code used for testing loop control is based on GLSL source code:
1329 // #version 430
1330 //
1331 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1332 //   float elements[];
1333 // } input_data;
1334 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1335 //   float elements[];
1336 // } output_data;
1337 //
1338 // void main() {
1339 //   uint x = gl_GlobalInvocationID.x;
1340 //   output_data.elements[x] = input_data.elements[x];
1341 //   for (uint i = 0; i < 4; ++i)
1342 //     output_data.elements[x] += 1.f;
1343 // }
1344 tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
1345 {
1346         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "loop_control", "Tests loop control cases"));
1347         vector<CaseParameter>                   cases;
1348         de::Random                                              rnd                             (deStringHash(group->getName()));
1349         const int                                               numElements             = 100;
1350         vector<float>                                   inputFloats             (numElements, 0);
1351         vector<float>                                   outputFloats    (numElements, 0);
1352         const StringTemplate                    shaderTemplate  (
1353                 string(s_ShaderPreamble) +
1354
1355                 "OpSource GLSL 430\n"
1356                 "OpName %main \"main\"\n"
1357                 "OpName %id \"gl_GlobalInvocationID\"\n"
1358
1359                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1360
1361                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1362
1363                 "%u32ptr      = OpTypePointer Function %u32\n"
1364
1365                 "%id          = OpVariable %uvec3ptr Input\n"
1366                 "%zero        = OpConstant %i32 0\n"
1367                 "%one         = OpConstant %i32 1\n"
1368                 "%constf1     = OpConstant %f32 1.0\n"
1369                 "%four        = OpConstant %u32 4\n"
1370
1371                 "%main        = OpFunction %void None %voidf\n"
1372                 "%entry       = OpLabel\n"
1373                 "%i           = OpVariable %u32ptr Function\n"
1374                 "               OpStore %i %zero\n"
1375
1376                 "%idval       = OpLoad %uvec3 %id\n"
1377                 "%x           = OpCompositeExtract %u32 %idval 0\n"
1378                 "%inloc       = OpAccessChain %f32ptr %indata %zero %x\n"
1379                 "%inval       = OpLoad %f32 %inloc\n"
1380                 "%outloc      = OpAccessChain %f32ptr %outdata %zero %x\n"
1381                 "               OpStore %outloc %inval\n"
1382                 "               OpBranch %loop_entry\n"
1383
1384                 "%loop_entry  = OpLabel\n"
1385                 "%i_val       = OpLoad %u32 %i\n"
1386                 "%cmp_lt      = OpULessThan %bool %i_val %four\n"
1387                 "               OpLoopMerge %loop_merge %loop_entry ${CONTROL}\n"
1388                 "               OpBranchConditional %cmp_lt %loop_body %loop_merge\n"
1389                 "%loop_body   = OpLabel\n"
1390                 "%outval      = OpLoad %f32 %outloc\n"
1391                 "%addf1       = OpFAdd %f32 %outval %constf1\n"
1392                 "               OpStore %outloc %addf1\n"
1393                 "%new_i       = OpIAdd %u32 %i_val %one\n"
1394                 "               OpStore %i %new_i\n"
1395                 "               OpBranch %loop_entry\n"
1396                 "%loop_merge  = OpLabel\n"
1397                 "               OpReturn\n"
1398                 "               OpFunctionEnd\n");
1399
1400         cases.push_back(CaseParameter("none",                           "None"));
1401         cases.push_back(CaseParameter("unroll",                         "Unroll"));
1402         cases.push_back(CaseParameter("dont_unroll",            "DontUnroll"));
1403         cases.push_back(CaseParameter("unroll_dont_unroll",     "Unroll|DontUnroll"));
1404
1405         fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1406
1407         for (size_t ndx = 0; ndx < numElements; ++ndx)
1408                 outputFloats[ndx] = inputFloats[ndx] + 4.f;
1409
1410         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1411         {
1412                 map<string, string>             specializations;
1413                 ComputeShaderSpec               spec;
1414
1415                 specializations["CONTROL"] = cases[caseNdx].param;
1416                 spec.assembly = shaderTemplate.specialize(specializations);
1417                 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1418                 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1419                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1420
1421                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1422         }
1423
1424         return group.release();
1425 }
1426
1427 // Assembly code used for testing selection control is based on GLSL source code:
1428 // #version 430
1429 //
1430 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1431 //   float elements[];
1432 // } input_data;
1433 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1434 //   float elements[];
1435 // } output_data;
1436 //
1437 // void main() {
1438 //   uint x = gl_GlobalInvocationID.x;
1439 //   float val = input_data.elements[x];
1440 //   if (val > 10.f)
1441 //     output_data.elements[x] = val + 1.f;
1442 //   else
1443 //     output_data.elements[x] = val - 1.f;
1444 // }
1445 tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
1446 {
1447         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "selection_control", "Tests selection control cases"));
1448         vector<CaseParameter>                   cases;
1449         de::Random                                              rnd                             (deStringHash(group->getName()));
1450         const int                                               numElements             = 100;
1451         vector<float>                                   inputFloats             (numElements, 0);
1452         vector<float>                                   outputFloats    (numElements, 0);
1453         const StringTemplate                    shaderTemplate  (
1454                 string(s_ShaderPreamble) +
1455
1456                 "OpSource GLSL 430\n"
1457                 "OpName %main \"main\"\n"
1458                 "OpName %id \"gl_GlobalInvocationID\"\n"
1459
1460                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1461
1462                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1463
1464                 "%id       = OpVariable %uvec3ptr Input\n"
1465                 "%zero     = OpConstant %i32 0\n"
1466                 "%constf1  = OpConstant %f32 1.0\n"
1467                 "%constf10 = OpConstant %f32 10.0\n"
1468
1469                 "%main     = OpFunction %void None %voidf\n"
1470                 "%entry    = OpLabel\n"
1471                 "%idval    = OpLoad %uvec3 %id\n"
1472                 "%x        = OpCompositeExtract %u32 %idval 0\n"
1473                 "%inloc    = OpAccessChain %f32ptr %indata %zero %x\n"
1474                 "%inval    = OpLoad %f32 %inloc\n"
1475                 "%outloc   = OpAccessChain %f32ptr %outdata %zero %x\n"
1476                 "%cmp_gt   = OpFOrdGreaterThan %bool %inval %constf10\n"
1477
1478                 "            OpSelectionMerge %if_end ${CONTROL}\n"
1479                 "            OpBranchConditional %cmp_gt %if_true %if_false\n"
1480                 "%if_true  = OpLabel\n"
1481                 "%addf1    = OpFAdd %f32 %inval %constf1\n"
1482                 "            OpStore %outloc %addf1\n"
1483                 "            OpBranch %if_end\n"
1484                 "%if_false = OpLabel\n"
1485                 "%subf1    = OpFSub %f32 %inval %constf1\n"
1486                 "            OpStore %outloc %subf1\n"
1487                 "            OpBranch %if_end\n"
1488                 "%if_end   = OpLabel\n"
1489                 "            OpReturn\n"
1490                 "            OpFunctionEnd\n");
1491
1492         cases.push_back(CaseParameter("none",                                   "None"));
1493         cases.push_back(CaseParameter("flatten",                                "Flatten"));
1494         cases.push_back(CaseParameter("dont_flatten",                   "DontFlatten"));
1495         cases.push_back(CaseParameter("flatten_dont_flatten",   "DontFlatten|Flatten"));
1496
1497         fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1498
1499         for (size_t ndx = 0; ndx < numElements; ++ndx)
1500                 outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f);
1501
1502         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1503         {
1504                 map<string, string>             specializations;
1505                 ComputeShaderSpec               spec;
1506
1507                 specializations["CONTROL"] = cases[caseNdx].param;
1508                 spec.assembly = shaderTemplate.specialize(specializations);
1509                 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1510                 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1511                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1512
1513                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1514         }
1515
1516         return group.release();
1517 }
1518
1519 // Assembly code used for testing function control is based on GLSL source code:
1520 //
1521 // #version 430
1522 //
1523 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1524 //   float elements[];
1525 // } input_data;
1526 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1527 //   float elements[];
1528 // } output_data;
1529 //
1530 // float const10() { return 10.f; }
1531 //
1532 // void main() {
1533 //   uint x = gl_GlobalInvocationID.x;
1534 //   output_data.elements[x] = input_data.elements[x] + const10();
1535 // }
1536 tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx)
1537 {
1538         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "function_control", "Tests function control cases"));
1539         vector<CaseParameter>                   cases;
1540         de::Random                                              rnd                             (deStringHash(group->getName()));
1541         const int                                               numElements             = 100;
1542         vector<float>                                   inputFloats             (numElements, 0);
1543         vector<float>                                   outputFloats    (numElements, 0);
1544         const StringTemplate                    shaderTemplate  (
1545                 string(s_ShaderPreamble) +
1546
1547                 "OpSource GLSL 430\n"
1548                 "OpName %main \"main\"\n"
1549                 "OpName %func_const10 \"const10(\"\n"
1550                 "OpName %id \"gl_GlobalInvocationID\"\n"
1551
1552                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1553
1554                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1555
1556                 "%f32f = OpTypeFunction %f32\n"
1557                 "%id = OpVariable %uvec3ptr Input\n"
1558                 "%zero = OpConstant %i32 0\n"
1559                 "%constf10 = OpConstant %f32 10.0\n"
1560
1561                 "%main         = OpFunction %void None %voidf\n"
1562                 "%entry        = OpLabel\n"
1563                 "%idval        = OpLoad %uvec3 %id\n"
1564                 "%x            = OpCompositeExtract %u32 %idval 0\n"
1565                 "%inloc        = OpAccessChain %f32ptr %indata %zero %x\n"
1566                 "%inval        = OpLoad %f32 %inloc\n"
1567                 "%ret_10       = OpFunctionCall %f32 %func_const10\n"
1568                 "%fadd         = OpFAdd %f32 %inval %ret_10\n"
1569                 "%outloc       = OpAccessChain %f32ptr %outdata %zero %x\n"
1570                 "                OpStore %outloc %fadd\n"
1571                 "                OpReturn\n"
1572                 "                OpFunctionEnd\n"
1573
1574                 "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n"
1575                 "%label        = OpLabel\n"
1576                 "                OpReturnValue %constf10\n"
1577                 "                OpFunctionEnd\n");
1578
1579         cases.push_back(CaseParameter("none",                                           "None"));
1580         cases.push_back(CaseParameter("inline",                                         "Inline"));
1581         cases.push_back(CaseParameter("dont_inline",                            "DontInline"));
1582         cases.push_back(CaseParameter("pure",                                           "Pure"));
1583         cases.push_back(CaseParameter("const",                                          "Const"));
1584         cases.push_back(CaseParameter("inline_pure",                            "Inline|Pure"));
1585         cases.push_back(CaseParameter("const_dont_inline",                      "Const|DontInline"));
1586         cases.push_back(CaseParameter("inline_dont_inline",                     "Inline|DontInline"));
1587         cases.push_back(CaseParameter("pure_inline_dont_inline",        "Pure|Inline|DontInline"));
1588
1589         fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1590
1591         for (size_t ndx = 0; ndx < numElements; ++ndx)
1592                 outputFloats[ndx] = inputFloats[ndx] + 10.f;
1593
1594         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1595         {
1596                 map<string, string>             specializations;
1597                 ComputeShaderSpec               spec;
1598
1599                 specializations["CONTROL"] = cases[caseNdx].param;
1600                 spec.assembly = shaderTemplate.specialize(specializations);
1601                 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1602                 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1603                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1604
1605                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1606         }
1607
1608         return group.release();
1609 }
1610
1611 // Checks that we can get undefined values for various types, without exercising a computation with it.
1612 tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx)
1613 {
1614         de::MovePtr<tcu::TestCaseGroup> group                   (new tcu::TestCaseGroup(testCtx, "opundef", "Tests the OpUndef instruction"));
1615         vector<CaseParameter>                   cases;
1616         de::Random                                              rnd                             (deStringHash(group->getName()));
1617         const int                                               numElements             = 100;
1618         vector<float>                                   positiveFloats  (numElements, 0);
1619         vector<float>                                   negativeFloats  (numElements, 0);
1620         const StringTemplate                    shaderTemplate  (
1621                 string(s_ShaderPreamble) +
1622
1623                 "OpSource GLSL 430\n"
1624                 "OpName %main           \"main\"\n"
1625                 "OpName %id             \"gl_GlobalInvocationID\"\n"
1626
1627                 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1628
1629                 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1630
1631                 "${TYPE}\n"
1632
1633                 "%id        = OpVariable %uvec3ptr Input\n"
1634                 "%zero      = OpConstant %i32 0\n"
1635
1636                 "%main      = OpFunction %void None %voidf\n"
1637                 "%label     = OpLabel\n"
1638
1639                 "%undef     = OpUndef %type\n"
1640
1641                 "%idval     = OpLoad %uvec3 %id\n"
1642                 "%x         = OpCompositeExtract %u32 %idval 0\n"
1643
1644                 "%inloc     = OpAccessChain %f32ptr %indata %zero %x\n"
1645                 "%inval     = OpLoad %f32 %inloc\n"
1646                 "%neg       = OpFNegate %f32 %inval\n"
1647                 "%outloc    = OpAccessChain %f32ptr %outdata %zero %x\n"
1648                 "             OpStore %outloc %neg\n"
1649                 "             OpReturn\n"
1650                 "             OpFunctionEnd\n");
1651
1652         cases.push_back(CaseParameter("bool",                   "%type = OpTypeBool"));
1653         cases.push_back(CaseParameter("sint32",                 "%type = OpTypeInt 32 1"));
1654         cases.push_back(CaseParameter("uint32",                 "%type = OpTypeInt 32 0"));
1655         cases.push_back(CaseParameter("float32",                "%type = OpTypeFloat 32"));
1656         cases.push_back(CaseParameter("vec4float32",    "%type = OpTypeVector %f32 4"));
1657         cases.push_back(CaseParameter("vec2uint32",             "%type = OpTypeVector %u32 2"));
1658         cases.push_back(CaseParameter("matrix",                 "%type = OpTypeMatrix %uvec3 3"));
1659         cases.push_back(CaseParameter("image",                  "%type = OpTypeImage %f32 2D 0 0 0 0 Unknown"));
1660         cases.push_back(CaseParameter("sampler",                "%type = OpTypeSampler"));
1661         cases.push_back(CaseParameter("sampledimage",   "%img = OpTypeImage %f32 2D 0 0 0 0 Unknown\n"
1662                                                                                                         "%type = OpTypeSampledImage %img"));
1663         cases.push_back(CaseParameter("array",                  "%100 = OpConstant %u32 100\n"
1664                                                                                                         "%type = OpTypeArray %i32 %100"));
1665         cases.push_back(CaseParameter("runtimearray",   "%type = OpTypeRuntimeArray %f32"));
1666         cases.push_back(CaseParameter("struct",                 "%type = OpTypeStruct %f32 %i32 %u32"));
1667         cases.push_back(CaseParameter("pointer",                "%type = OpTypePointer Function %i32"));
1668         cases.push_back(CaseParameter("function",               "%type = OpTypeFunction %void %i32 %f32"));
1669
1670         fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1671
1672         for (size_t ndx = 0; ndx < numElements; ++ndx)
1673                 negativeFloats[ndx] = -positiveFloats[ndx];
1674
1675         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1676         {
1677                 map<string, string>             specializations;
1678                 ComputeShaderSpec               spec;
1679
1680                 specializations["TYPE"] = cases[caseNdx].param;
1681                 spec.assembly = shaderTemplate.specialize(specializations);
1682         spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1683         spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1684                 spec.numWorkGroups = IVec3(numElements, 1, 1);
1685
1686                 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1687         }
1688
1689                 return group.release();
1690 }
1691
1692
1693 typedef std::pair<std::string, VkShaderStage>   EntryToStage;
1694 typedef map<string, vector<EntryToStage> >              ModuleMap;
1695
1696 // Context for a specific test instantiation. For example, an instantiation
1697 // may test colors yellow/magenta/cyan/mauve in a tesselation shader
1698 // with an entry point named 'main_to_the_main'
1699 struct InstanceContext
1700 {
1701         // Map of modules to what entry_points we care to use from those modules.
1702         ModuleMap       moduleMap;
1703         RGBA            inputColors[4];
1704         RGBA            outputColors[4];
1705         // Concrete SPIR-V code to test via boilerplate specialization.
1706         map<string, string> testCodeFragments;
1707
1708         InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_)
1709                 : testCodeFragments(testCodeFragments_)
1710         {
1711                 memcpy(inputColors, inputs, sizeof(inputs));
1712                 memcpy(outputColors, outputs, sizeof(outputs));
1713         }
1714
1715         InstanceContext (const InstanceContext& other)
1716                         : moduleMap(other.moduleMap)
1717                         , testCodeFragments(other.testCodeFragments)
1718         {
1719                 memcpy(inputColors, other.inputColors, sizeof(inputColors));
1720                 memcpy(outputColors, other.outputColors, sizeof(outputColors));
1721         }
1722 };
1723
1724 // A description of a shader to be used for a single stage of the graphics pipeline.
1725 struct ShaderElement
1726 {
1727         // The module that contains this shader entrypoint.
1728         const char*             moduleName;
1729
1730         // The name of the entrypoint.
1731         const char*             entryName;
1732
1733         // Which shader stage this entry point represents.
1734         VkShaderStage   stage;
1735
1736         ShaderElement (const char* moduleName_, const char* entryPoint_, VkShaderStage shaderStage_)
1737                 : moduleName(moduleName_)
1738                 , entryName(entryPoint_)
1739                 , stage(shaderStage_)
1740         {
1741         }
1742 };
1743
1744 void getDefaultColors(RGBA colors[4]) {
1745         colors[0] = RGBA::white();
1746         colors[1] = RGBA::red();
1747         colors[2] = RGBA::blue();
1748         colors[3] = RGBA::green();
1749 }
1750 // Turns a statically sized array of ShaderElements into an instance-context
1751 // by setting up the mapping of modules to their contained shaders and stages.
1752 // The inputs and expected outputs are given by inputColors and outputColors
1753 template<size_t N>
1754 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments)
1755 {
1756         InstanceContext ctx(inputColors, outputColors, testCodeFragments);
1757         for (size_t i = 0; i < N; ++i)
1758         {
1759                 ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
1760         }
1761         return ctx;
1762 }
1763
1764 // The same as createInstanceContext above, but with default colors.
1765 template<size_t N>
1766 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map<string, string>& testCodeFragments)
1767 {
1768         RGBA defaultColors[4];
1769         getDefaultColors(defaultColors);
1770         return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
1771 }
1772
1773 // For the current InstanceContext, constructs the required modules and shaders.
1774 // Fills in the modules vector with all of the used modules, and stage_shaders with
1775 // all stages and shaders that are to be used.
1776 void createShaders (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector<ModuleHandleSp>& modules, map<VkShaderStage, VkShaderSp>& stage_shaders)
1777 {
1778         for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
1779         {
1780                 const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
1781                 modules.push_back(ModuleHandleSp(mod));
1782                 for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
1783                 {
1784                         const EntryToStage&                     stage                   = *shaderNdx;
1785                         const VkShaderCreateInfo        shaderParam             =
1786                         {
1787                                 VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,                   //      VkStructureType         sType;
1788                                 DE_NULL,                                                                                //      const void*                     pNext;
1789                                 **modules.back(),                                                               //      VkShaderModule          module;
1790                                 stage.first.c_str(),                                                    //      const char*                     pName;
1791                                 0u,                                                                                             //      VkShaderCreateFlags     flags;
1792                                 stage.second,                                                                   //      VkShaderStage           stage;
1793                         };
1794                         stage_shaders[stage.second] = VkShaderSp(new Unique<VkShader>(createShader(vk, vkDevice, &shaderParam)));
1795                 }
1796         }
1797 }
1798
1799 #define TYPES                                                                                                                           \
1800         "%void = OpTypeVoid\n"                                                                                                  \
1801         "%bool = OpTypeBool\n"                                                                                                  \
1802                                                                                                                                                         \
1803         "%i32 = OpTypeInt 32 1\n"                                                                                               \
1804         "%u32 = OpTypeInt 32 0\n"                                                                                               \
1805                                                                                                                                                         \
1806         "%f32 = OpTypeFloat 32\n"                                                                                               \
1807         "%v3f32 = OpTypeVector %f32 3\n"                                                                                \
1808         "%v4f32 = OpTypeVector %f32 4\n"                                                                                \
1809                                                                                                                                                         \
1810         "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n"                                              \
1811         "%fun = OpTypeFunction %void\n"                                                                                 \
1812                                                                                                                                                         \
1813         "%ip_f32 = OpTypePointer Input %f32\n"                                                                  \
1814         "%ip_i32 = OpTypePointer Input %i32\n"                                                                  \
1815         "%ip_v3f32 = OpTypePointer Input %v3f32\n"                                                              \
1816         "%ip_v4f32 = OpTypePointer Input %v4f32\n"                                                              \
1817                                                                                                                                                         \
1818         "%op_f32 = OpTypePointer Output %f32\n"                                                                 \
1819         "%op_v4f32 = OpTypePointer Output %v4f32\n"
1820
1821 #define CONSTANTS                                                                                                                       \
1822         "%c_f32_1 = OpConstant %f32 1\n"                                                                                \
1823         "%c_i32_0 = OpConstant %i32 0\n"                                                                                \
1824         "%c_i32_1 = OpConstant %i32 1\n"                                                                                \
1825         "%c_i32_2 = OpConstant %i32 2\n"                                                                                \
1826         "%c_u32_0 = OpConstant %u32 0\n"                                                                                \
1827         "%c_u32_1 = OpConstant %u32 1\n"                                                                                \
1828         "%c_u32_2 = OpConstant %u32 2\n"                                                                                \
1829         "%c_u32_3 = OpConstant %u32 3\n"                                                                                \
1830         "%c_u32_32 = OpConstant %u32 32\n"                                                                              \
1831         "%c_u32_4 = OpConstant %u32 4\n"
1832
1833 #define ARRAYS                                                                                                                          \
1834         "%a1f32 = OpTypeArray %f32 %c_u32_1\n"                                                                  \
1835         "%a2f32 = OpTypeArray %f32 %c_u32_2\n"                                                                  \
1836         "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n"                                                              \
1837         "%a4f32 = OpTypeArray %f32 %c_u32_4\n"                                                                  \
1838         "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n"                                                    \
1839         "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n"                                                  \
1840         "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n"                                                \
1841         "%op_a2f32 = OpTypePointer Output %a2f32\n"                                                             \
1842         "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n"                                                 \
1843         "%op_a4f32 = OpTypePointer Output %a4f32\n"                                                             \
1844         "%op_f32 = OpTypePointer Output %f32\n"
1845
1846 // Boilerplate vertex-shader assembly.  Specialize with "testfun" mapping to an
1847 // OpFunction definition for %test_code that takes and returns a %v4f32.
1848 // Prefixes local IDs with "BP_" to avoid collisions with the rest of assembly
1849 // code.
1850 //
1851 // It corresponds roughly to this GLSL:
1852 //
1853 // layout(location = 0) in vec4 position;
1854 // layout(location = 1) in vec4 color;
1855 // layout(location = 1) out highp vec4 vtxColor;
1856 // void main (void) { gl_Position = position; vtxColor = test_func(color); }
1857 tcu::StringTemplate vertexShaderBoilerplate(
1858         "OpCapability Shader\n"
1859         "OpMemoryModel Logical GLSL450\n"
1860         "OpEntryPoint Vertex %4 \"main\" %BP_Position %BP_vtxColor %BP_color %BP_vtxPosition %BP_vertex_id %BP_instance_id\n"
1861         "${debug:opt}\n"
1862         "OpName %main \"main\"\n"
1863         "OpName %BP_vtxPosition \"vtxPosition\"\n"
1864         "OpName %BP_Position \"position\"\n"
1865         "OpName %BP_vtxColor \"vtxColor\"\n"
1866         "OpName %BP_color \"color\"\n"
1867         "OpName %vertex_id \"gl_VertexID\"\n"
1868         "OpName %instance_id \"gl_InstanceID\"\n"
1869         "OpName %test_code \"testfun(vf4;\"\n"
1870         "OpDecorate %BP_vtxPosition Smooth\n"
1871         "OpDecorate %BP_vtxPosition Location 2\n"
1872         "OpDecorate %BP_Position Location 0\n"
1873         "OpDecorate %BP_vtxColor Smooth\n"
1874         "OpDecorate %BP_vtxColor Location 1\n"
1875         "OpDecorate %BP_color Location 1\n"
1876         "OpDecorate %BP_vertex_id BuiltIn VertexId\n"
1877         "OpDecorate %BP_instance_id BuiltIn InstanceId\n"
1878         TYPES
1879         CONSTANTS
1880         ARRAYS
1881         "%BP_vtxPosition = OpVariable %op_v4f32 Output\n"
1882         "%BP_Position = OpVariable %ip_v4f32 Input\n"
1883         "%BP_vtxColor = OpVariable %op_v4f32 Output\n"
1884         "%BP_color = OpVariable %ip_v4f32 Input\n"
1885         "%BP_vertex_id = OpVariable %ip_i32 Input\n"
1886         "%BP_instance_id = OpVariable %ip_i32 Input\n"
1887         "%main = OpFunction %void None %fun\n"
1888         "%BP_label = OpLabel\n"
1889         "%BP_tmp_position = OpLoad %v4f32 %BP_Position\n"
1890         "OpStore %BP_vtxPosition %BP_tmp_position\n"
1891         "%BP_tmp_color = OpLoad %v4f32 %BP_color\n"
1892         "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_tmp_color\n"
1893         "OpStore %BP_vtxColor %BP_clr_transformed\n"
1894         "OpReturn\n"
1895         "OpFunctionEnd\n"
1896         "${testfun}\n");
1897
1898 // Boilerplate tess-control shader assembly.  Specialize by mapping "testfun" to
1899 // an OpFunction definition for %test_code that takes and returns a %v4f32.
1900 // Prefixes local IDs with "BP_" to avoid collisions with the rest of assembly
1901 // code.
1902 //
1903 // It roughly corresponds to the following glsl.
1904 //
1905 // #version 450
1906 // layout(vertices = 3) out;
1907 // layout(location = 1) in vec4 in_color[];
1908 // layout(location = 2) in vec4 in_position[];
1909 // layout(location = 1) out vec4 out_color[];
1910 // layout(location = 2) out vec4 out_position[];
1911 //
1912 // void main() {
1913 //   out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
1914 //   out_position[gl_InvocationID] = in_position[gl_InvocationID];
1915 //   if (gl_InvocationID == 0) {
1916 //     gl_TessLevelOuter[0] = 1.0;
1917 //     gl_TessLevelOuter[1] = 1.0;
1918 //     gl_TessLevelOuter[2] = 1.0;
1919 //     gl_TessLevelInner[0] = 1.0;
1920 //   }
1921 // }
1922 tcu::StringTemplate tessControlShaderBoilerplate(
1923         "OpCapability Tessellation\n"
1924         "OpMemoryModel Logical GLSL450\n"
1925         "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_out_position %BP_in_position %BP_gl_TessCoordOuter %BP_gl_TessCoordInner\n"
1926         "OpExecutionMode %BP_main OutputVertices 3\n"
1927         "${debug:opt}\n"
1928         "OpName %BP_main \"main\"\n"
1929         "OpName %BP_out_color \"out_color\"\n"
1930         "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n"
1931         "OpName %BP_in_color \"in_color\"\n"
1932         "OpName %BP_out_position \"out_position\"\n"
1933         "OpName %BP_in_position \"in_position\"\n"
1934         "OpName %BP_gl_TessCoordOuter \"gl_TessLevelOuter\"\n"
1935         "OpName %BP_gl_TessCoordInner \"gl_TessLevelInner\"\n"
1936         "OpName %test_code \"testfun(vf4;\"\n"
1937         "OpDecorate %BP_out_color Location 1\n"
1938         "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
1939         "OpDecorate %BP_in_color Location 1\n"
1940         "OpDecorate %BP_out_position Location 2\n"
1941         "OpDecorate %BP_in_position Location 2\n"
1942         "OpDecorate %BP_gl_TessCoordOuter Patch\n"
1943         "OpDecorate %BP_gl_TessCoordOuter BuiltIn TessLevelOuter\n"
1944         "OpDecorate %BP_gl_TessCoordInner Patch\n"
1945         "OpDecorate %BP_gl_TessCoordInner BuiltIn TessLevelInner\n"
1946 TYPES
1947 CONSTANTS
1948 ARRAYS
1949         "%BP_out_color = OpVariable %op_a3v4f32 Output\n"
1950         "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
1951         "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
1952         "%BP_out_position = OpVariable %op_a3v4f32 Output\n"
1953         "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
1954         "%BP_gl_TessCoordOuter = OpVariable %op_a4f32 Output\n"
1955         "%BP_gl_TessCoordInner = OpVariable %op_a2f32 Output\n"
1956
1957         "%BP_main = OpFunction %void None %fun\n"
1958         "%BP_label = OpLabel\n"
1959
1960         "%BP_invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
1961
1962         "%BP_in_color_ptr = OpAccessChain %ip_v4f32 %BP_in_color %BP_invocation_id\n"
1963         "%BP_in_position_ptr = OpAccessChain %ip_v4f32 %BP_in_position %BP_invocation_id\n"
1964
1965         "%BP_in_color_val = OpLoad %v4f32 %BP_in_color_ptr\n"
1966         "%BP_in_position_val = OpLoad %v4f32 %BP_in_position_ptr\n"
1967
1968         "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_color_val\n"
1969
1970         "%BP_out_color_ptr = OpAccessChain %op_v4f32 %BP_out_color %BP_invocation_id\n"
1971         "%BP_out_position_ptr = OpAccessChain %op_v4f32 %BP_out_position %BP_invocation_id\n"
1972
1973         "OpStore %BP_out_color_ptr %BP_clr_transformed\n"
1974         "OpStore %BP_out_position_ptr %BP_in_position_val\n"
1975
1976         "%BP_is_first_invocation = OpIEqual %bool %BP_invocation_id %c_i32_0\n"
1977         "OpSelectionMerge %BP_merge_label None\n"
1978         "OpBranchConditional %BP_is_first_invocation %BP_first_invocation %BP_merge_label\n"
1979
1980         "%BP_first_invocation = OpLabel\n"
1981         "%BP_tess_outer_0 = OpAccessChain %op_f32 %BP_gl_TessCoordOuter %c_i32_0\n"
1982         "%BP_tess_outer_1 = OpAccessChain %op_f32 %BP_gl_TessCoordOuter %c_i32_1\n"
1983         "%BP_tess_outer_2 = OpAccessChain %op_f32 %BP_gl_TessCoordOuter %c_i32_2\n"
1984         "%BP_tess_inner = OpAccessChain %op_f32 %BP_gl_TessCoordInner %c_i32_0\n"
1985
1986         "OpStore %BP_tess_outer_0 %c_f32_1\n"
1987         "OpStore %BP_tess_outer_1 %c_f32_1\n"
1988         "OpStore %BP_tess_outer_2 %c_f32_1\n"
1989         "OpStore %BP_tess_inner %c_f32_1\n"
1990
1991         "OpBranch %BP_merge_label\n"
1992         "%BP_merge_label = OpLabel\n"
1993         "OpReturn\n"
1994         "OpFunctionEnd\n"
1995         "${testfun}\n");
1996
1997 // Boilerplate tess-eval shader assembly.  Specialize by mapping "testfun" to an
1998 // OpFunction definition for %test_code that takes and returns a %v4f32.
1999 // Prefixes local IDs with "BP_" to avoid collisions with the rest of assembly
2000 // code.
2001 //
2002 // It roughly corresponds to the following glsl.
2003 //
2004 // #version 450
2005 //
2006 // layout(triangles, equal_spacing, ccw) in;
2007 // layout(location = 1) in vec4 in_color[];
2008 // layout(location = 2) in vec4 in_position[];
2009 // layout(location = 1) out vec4 out_color;
2010 //
2011 // #define interpolate(val)
2012 //   vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
2013 //          vec4(gl_TessCoord.z) * val[2]
2014 //
2015 //
2016 // void main() {
2017 //   gl_Position = vec4(gl_TessCoord.x) * in_position[0] +
2018 //                  vec4(gl_TessCoord.y) * in_position[1] +
2019 //                  vec4(gl_TessCoord.z) * in_position[2];
2020 //   out_color = testfun(interpolate(in_color));
2021 // }
2022
2023 tcu::StringTemplate tessEvalBoilerplate(
2024         "OpCapability Tessellation\n"
2025         "OpMemoryModel Logical GLSL450\n"
2026         "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_tessCoord %BP_in_position %BP_out_color %BP_in_color \n"
2027         "OpExecutionMode %BP_main InputTriangles\n"
2028         "${debug:opt}\n"
2029         "OpName %BP_main \"main\"\n"
2030         "OpName %BP_per_vertex_out \"gl_PerVertex\"\n"
2031         "OpMemberName %BP_per_vertex_out 0 \"gl_Position\"\n"
2032         "OpMemberName %BP_per_vertex_out 1 \"gl_PointSize\"\n"
2033         "OpMemberName %BP_per_vertex_out 2 \"gl_ClipDistance\"\n"
2034         "OpMemberName %BP_per_vertex_out 3 \"gl_CullDistance\"\n"
2035         "OpName %BP_stream \"\"\n"
2036         "OpName %BP_gl_tessCoord \"gl_TessCoord\"\n"
2037         "OpName %BP_in_position \"in_position\"\n"
2038         "OpName %BP_out_color \"out_color\"\n"
2039         "OpName %BP_in_color \"in_color\"\n"
2040         "OpName %test_code \"testfun(vf4;\"\n"
2041         "OpMemberDecorate %BP_per_vertex_out 0 BuiltIn Position\n"
2042         "OpMemberDecorate %BP_per_vertex_out 1 BuiltIn PointSize\n"
2043         "OpMemberDecorate %BP_per_vertex_out 2 BuiltIn ClipDistance\n"
2044         "OpMemberDecorate %BP_per_vertex_out 3 BuiltIn CullDistance\n"
2045         "OpDecorate %BP_per_vertex_out Block\n"
2046         "OpDecorate %BP_gl_tessCoord BuiltIn TessCoord\n"
2047         "OpDecorate %BP_in_position Location 2\n"
2048         "OpDecorate %BP_out_color Location 1\n"
2049         "OpDecorate %BP_in_color Location 1\n"
2050         TYPES
2051         CONSTANTS
2052         ARRAYS
2053         "%BP_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2054         "%BP_op_per_vertex_out = OpTypePointer Output %BP_per_vertex_out\n"
2055         "%BP_stream = OpVariable %BP_op_per_vertex_out Output\n"
2056         "%BP_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2057         "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
2058         "%BP_out_color = OpVariable %op_v4f32 Output\n"
2059         "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
2060         "%BP_main = OpFunction %void None %fun\n"
2061         "%BP_label = OpLabel\n"
2062         "%BP_tc_0_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_0\n"
2063         "%BP_tc_1_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_1\n"
2064         "%BP_tc_2_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_2\n"
2065
2066         "%BP_tc_0 = OpLoad %f32 %BP_tc_0_ptr\n"
2067         "%BP_tc_1 = OpLoad %f32 %BP_tc_1_ptr\n"
2068         "%BP_tc_2 = OpLoad %f32 %BP_tc_2_ptr\n"
2069
2070         "%BP_in_pos_0_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_0\n"
2071         "%BP_in_pos_1_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_1\n"
2072         "%BP_in_pos_2_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_2\n"
2073
2074         "%BP_in_pos_0 = OpLoad %v4f32 %BP_in_pos_0_ptr\n"
2075         "%BP_in_pos_1 = OpLoad %v4f32 %BP_in_pos_1_ptr\n"
2076         "%BP_in_pos_2 = OpLoad %v4f32 %BP_in_pos_2_ptr\n"
2077
2078         "%BP_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_pos_0\n"
2079         "%BP_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_pos_1\n"
2080         "%BP_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_pos_2\n"
2081
2082         "%BP_out_pos_ptr = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
2083
2084         "%BP_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %BP_in_pos_0_weighted %BP_in_pos_1_weighted\n"
2085         "%BP_computed_out = OpFAdd %v4f32 %BP_in_pos_0_plus_pos_1 %BP_in_pos_2_weighted\n"
2086         "OpStore %BP_out_pos_ptr %BP_computed_out\n"
2087
2088         "%BP_in_clr_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
2089         "%BP_in_clr_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
2090         "%BP_in_clr_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
2091
2092         "%BP_in_clr_0 = OpLoad %v4f32 %BP_in_clr_0_ptr\n"
2093         "%BP_in_clr_1 = OpLoad %v4f32 %BP_in_clr_1_ptr\n"
2094         "%BP_in_clr_2 = OpLoad %v4f32 %BP_in_clr_2_ptr\n"
2095
2096         "%BP_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_clr_0\n"
2097         "%BP_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_clr_1\n"
2098         "%BP_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_clr_2\n"
2099
2100         "%BP_in_clr_0_plus_col_1 = OpFAdd %v4f32 %BP_in_clr_0_weighted %BP_in_clr_1_weighted\n"
2101         "%BP_computed_clr = OpFAdd %v4f32 %BP_in_clr_0_plus_col_1 %BP_in_clr_2_weighted\n"
2102         "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_computed_clr\n"
2103
2104         "OpStore %BP_out_color %BP_clr_transformed\n"
2105         "OpReturn\n"
2106         "OpFunctionEnd\n"
2107         "${testfun}\n");
2108
2109 // Boilerplate geometry-shader assembly.  Specialize by mapping "testfun" to an
2110 // OpFunction definition for %test_code that takes and returns a %v4f32.
2111 // Prefixes local IDs with "BP_" to avoid collisions with the rest of assembly
2112 // code.
2113 //
2114 // Derived from this GLSL:
2115 //
2116 // #version 450
2117 // layout(triangles) in;
2118 // layout(triangle_strip, max_vertices = 3) out;
2119 //
2120 // layout(location = 1) in vec4 in_color[];
2121 // layout(location = 1) out vec4 out_color;
2122 //
2123 // void main() {
2124 //       gl_Position = gl_in[0].gl_Position;
2125 //       out_color = test_fun(in_color[0]);
2126 //       EmitVertex();
2127 //       gl_Position = gl_in[1].gl_Position;
2128 //       out_color = test_fun(in_color[1]);
2129 //       EmitVertex();
2130 //       gl_Position = gl_in[2].gl_Position;
2131 //       out_color = test_fun(in_color[2]);
2132 //       EmitVertex();
2133 //       EndPrimitive();
2134 // }
2135 tcu::StringTemplate geometryShaderBoilerplate(
2136         "OpCapability Geometry\n"
2137         "OpMemoryModel Logical GLSL450\n"
2138         "OpEntryPoint Geometry %BP_main \"main\" %BP_stream %BP_gl_in %BP_out_color %BP_in_color\n"
2139         "OpExecutionMode %BP_main InputTriangles\n"
2140         "OpExecutionMode %BP_main Invocations 0\n"
2141         "OpExecutionMode %BP_main OutputTriangleStrip\n"
2142         "OpExecutionMode %BP_main OutputVertices 3\n"
2143         "${debug:opt}\n"
2144         "OpName %BP_main \"main\"\n"
2145         "OpName %BP_per_vertex_out \"gl_PerVertex\"\n"
2146         "OpMemberName %BP_per_vertex_out 0 \"gl_Position\"\n"
2147         "OpMemberName %BP_per_vertex_out 1 \"gl_PointSize\"\n"
2148         "OpMemberName %BP_per_vertex_out 2 \"gl_ClipDistance\"\n"
2149         "OpMemberName %BP_per_vertex_out 3 \"gl_CullDistance\"\n"
2150         "OpName %BP_stream \"\"\n"
2151         "OpName %BP_per_vertex_in \"gl_PerVertex\"\n"
2152         "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n"
2153         "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n"
2154         "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n"
2155         "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n"
2156         "OpName %BP_gl_in \"gl_in\"\n"
2157         "OpName %BP_out_color \"out_color\"\n"
2158         "OpName %BP_in_color \"in_color\"\n"
2159         "OpName %test_code \"testfun(vf4;\"\n"
2160         "OpMemberDecorate %BP_per_vertex_out 0 BuiltIn Position\n"
2161         "OpMemberDecorate %BP_per_vertex_out 1 BuiltIn PointSize\n"
2162         "OpMemberDecorate %BP_per_vertex_out 2 BuiltIn ClipDistance\n"
2163         "OpMemberDecorate %BP_per_vertex_out 3 BuiltIn CullDistance\n"
2164         "OpDecorate %BP_per_vertex_out Block\n"
2165         "OpDecorate %BP_per_vertex_out Stream 0\n"
2166         "OpDecorate %BP_stream Stream 0\n"
2167         "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
2168         "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
2169         "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
2170         "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
2171         "OpDecorate %BP_per_vertex_in Block\n"
2172         "OpDecorate %BP_out_color Location 1\n"
2173         "OpDecorate %BP_out_color Stream 0\n"
2174         "OpDecorate %BP_in_color Location 1\n"
2175 TYPES
2176 CONSTANTS
2177 ARRAYS
2178         "%BP_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2179         "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2180         "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
2181         "%BP_op_per_vertex_out = OpTypePointer Output %BP_per_vertex_out\n"
2182         "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
2183
2184         "%BP_stream = OpVariable %BP_op_per_vertex_out Output\n"
2185         "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
2186         "%BP_out_color = OpVariable %op_v4f32 Output\n"
2187         "%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
2188
2189         "%BP_main = OpFunction %void None %fun\n"
2190         "%BP_label = OpLabel\n"
2191         "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
2192         "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
2193         "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
2194
2195         "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
2196         "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
2197         "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
2198
2199         "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
2200         "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
2201         "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
2202
2203         "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
2204         "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
2205         "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
2206
2207         "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
2208         "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
2209         "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
2210
2211         "%BP_out_gl_position = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
2212
2213         "OpStore %BP_out_gl_position %BP_in_position_0\n"
2214         "OpStore %BP_out_color %BP_transformed_in_color_0\n"
2215         "OpEmitVertex\n"
2216
2217         "OpStore %BP_out_gl_position %BP_in_position_1\n"
2218         "OpStore %BP_out_color %BP_transformed_in_color_1\n"
2219         "OpEmitVertex\n"
2220
2221         "OpStore %BP_out_gl_position %BP_in_position_2\n"
2222         "OpStore %BP_out_color %BP_transformed_in_color_2\n"
2223         "OpEmitVertex\n"
2224
2225         "OpEndPrimitive\n"
2226         "OpReturn\n"
2227         "OpFunctionEnd\n"
2228         "${testfun}\n");
2229
2230 // Boilerplate fragment-shader assembly.  Specialize by mapping "testfun" to an
2231 // OpFunction definition for %test_code that takes and returns a %v4f32.
2232 // Prefixes local IDs with "BP_" to avoid collisions with the rest of assembly
2233 // code.
2234 //
2235 // Derived from this GLSL:
2236 //
2237 // layout(location = 0) in highp vec4 vtxColor;
2238 // layout(location = 1) out highp vec4 fragColor;
2239 // highp vec4 testfun(highp vec4 x) { return x; }
2240 // void main(void) { fragColor = testfun(vtxColor); }
2241 //
2242 // with modifications including passing vtxColor by value and ripping out
2243 // testfun() definition.
2244 tcu::StringTemplate fragmentShaderBoilerplate(
2245         "OpCapability Shader\n"
2246         "OpMemoryModel Logical GLSL450\n"
2247         "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n"
2248         "OpExecutionMode %BP_main OriginUpperLeft\n"
2249         "${debug:opt}\n"
2250         "OpName %BP_main \"main\"\n"
2251         "OpName %BP_fragColor \"fragColor\"\n"
2252         "OpName %BP_vtxColor \"vtxColor\"\n"
2253         "OpName %test_code \"testfun(vf4;\"\n"
2254         "OpDecorate %BP_fragColor Location 0\n"
2255         "OpDecorate %BP_vtxColor Smooth\n"
2256         "OpDecorate %BP_vtxColor Location 1\n"
2257         TYPES
2258         CONSTANTS
2259         ARRAYS
2260         "%BP_fragColor = OpVariable %op_v4f32 Output\n"
2261         "%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
2262         "%BP_main = OpFunction %void None %fun\n"
2263         "%BP_label_main = OpLabel\n"
2264         "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
2265         "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
2266         "OpStore %BP_fragColor %BP_tmp2\n"
2267         "OpReturn\n"
2268         "OpFunctionEnd\n"
2269         "${testfun}\n");
2270
2271 // Creates fragments that specialize into a simple pass-through shader (of any kind).
2272 map<string, string> passthruFragments() {
2273         map<string, string> fragments;
2274         fragments["testfun"] =
2275                 // A %test_code function that returns its argument unchanged.
2276                 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
2277                 "%param1 = OpFunctionParameter %v4f32\n"
2278                 "%label_testfun = OpLabel\n"
2279                 "OpReturnValue %param1\n"
2280                 "OpFunctionEnd\n";
2281         return fragments;
2282 }
2283
2284 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2285 // Vertex shader gets custom code from context, the rest are pass-through.
2286 void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) {
2287         map<string, string> passthru = passthruFragments();
2288         dst.spirvAsmSources.add("vert") << vertexShaderBoilerplate.specialize(context.testCodeFragments);
2289         dst.spirvAsmSources.add("tessc") << tessControlShaderBoilerplate.specialize(passthru);
2290         dst.spirvAsmSources.add("tesse") << tessEvalBoilerplate.specialize(passthru);
2291         dst.spirvAsmSources.add("geom") << geometryShaderBoilerplate.specialize(passthru);
2292         dst.spirvAsmSources.add("frag") << fragmentShaderBoilerplate.specialize(passthru);
2293 }
2294
2295 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2296 // Tessellation control shader gets custom code from context, the rest are
2297 // pass-through.
2298 void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) {
2299         map<string, string> passthru = passthruFragments();
2300         dst.spirvAsmSources.add("vert") << vertexShaderBoilerplate.specialize(passthru);
2301         dst.spirvAsmSources.add("tessc") << tessControlShaderBoilerplate.specialize(context.testCodeFragments);
2302         dst.spirvAsmSources.add("tesse") << tessEvalBoilerplate.specialize(passthru);
2303         dst.spirvAsmSources.add("geom") << geometryShaderBoilerplate.specialize(passthru);
2304         dst.spirvAsmSources.add("frag") << fragmentShaderBoilerplate.specialize(passthru);
2305 }
2306
2307 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2308 // Tessellation evaluation shader gets custom code from context, the rest are
2309 // pass-through.
2310 void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) {
2311         map<string, string> passthru = passthruFragments();
2312         dst.spirvAsmSources.add("vert") << vertexShaderBoilerplate.specialize(passthru);
2313         dst.spirvAsmSources.add("tessc") << tessControlShaderBoilerplate.specialize(passthru);
2314         dst.spirvAsmSources.add("tesse") << tessEvalBoilerplate.specialize(context.testCodeFragments);
2315         dst.spirvAsmSources.add("geom") << geometryShaderBoilerplate.specialize(passthru);
2316         dst.spirvAsmSources.add("frag") << fragmentShaderBoilerplate.specialize(passthru);
2317 }
2318
2319 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2320 // Geometry shader gets custom code from context, the rest are pass-through.
2321 void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) {
2322         map<string, string> passthru = passthruFragments();
2323         dst.spirvAsmSources.add("vert") << vertexShaderBoilerplate.specialize(passthru);
2324         dst.spirvAsmSources.add("tessc") << tessControlShaderBoilerplate.specialize(passthru);
2325         dst.spirvAsmSources.add("tesse") << tessEvalBoilerplate.specialize(passthru);
2326         dst.spirvAsmSources.add("geom") << geometryShaderBoilerplate.specialize(context.testCodeFragments);
2327         dst.spirvAsmSources.add("frag") << fragmentShaderBoilerplate.specialize(passthru);
2328 }
2329
2330 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2331 // Fragment shader gets custom code from context, the rest are pass-through.
2332 void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) {
2333         map<string, string> passthru = passthruFragments();
2334         dst.spirvAsmSources.add("vert") << vertexShaderBoilerplate.specialize(passthru);
2335         dst.spirvAsmSources.add("tessc") << tessControlShaderBoilerplate.specialize(passthru);
2336         dst.spirvAsmSources.add("tesse") << tessEvalBoilerplate.specialize(passthru);
2337         dst.spirvAsmSources.add("geom") << geometryShaderBoilerplate.specialize(passthru);
2338         dst.spirvAsmSources.add("frag") << fragmentShaderBoilerplate.specialize(context.testCodeFragments);
2339 }
2340
2341 // Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
2342 // Feeds the pipeline a set of colored triangles, which then must occur in the
2343 // rendered image.  The surface is cleared before executing the pipeline, so
2344 // whatever the shaders draw can be directly spot-checked.
2345 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
2346 {
2347         const VkDevice                                                  vkDevice                                = context.getDevice();
2348         const DeviceInterface&                                  vk                                              = context.getDeviceInterface();
2349         const VkQueue                                                   queue                                   = context.getUniversalQueue();
2350         const deUint32                                                  queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
2351         const tcu::IVec2                                                renderSize                              (256, 256);
2352         vector<ModuleHandleSp>                                  modules;
2353         map<VkShaderStage, VkShaderSp>                  shaders;
2354         const int                                                               testSpecificSeed                = 31354125;
2355         const int                                                               seed                                    = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
2356         de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
2357         de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
2358         const Vec4                                                              vertexData[]                    =
2359         {
2360                 // Upper left corner:
2361                 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
2362                 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
2363                 Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
2364
2365                 // Upper right corner:
2366                 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
2367                 Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
2368                 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
2369
2370                 // Lower left corner:
2371                 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
2372                 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
2373                 Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
2374
2375                 // Lower right corner:
2376                 Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
2377                 Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
2378                 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec()
2379         };
2380         const size_t                                                    singleVertexDataSize    = 2 * sizeof(Vec4);
2381         const size_t                                                    vertexCount                             = sizeof(vertexData) / singleVertexDataSize;
2382
2383         const VkBufferCreateInfo                                vertexBufferParams              =
2384         {
2385                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   //      VkStructureType         sType;
2386                 DE_NULL,                                                                //      const void*                     pNext;
2387                 (VkDeviceSize)sizeof(vertexData),               //      VkDeviceSize            size;
2388                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              //      VkBufferUsageFlags      usage;
2389                 0u,                                                                             //      VkBufferCreateFlags     flags;
2390                 VK_SHARING_MODE_EXCLUSIVE,                              //      VkSharingMode           sharingMode;
2391                 1u,                                                                             //      deUint32                        queueFamilyCount;
2392                 &queueFamilyIndex,                                              //      const deUint32*         pQueueFamilyIndices;
2393         };
2394         const Unique<VkBuffer>                                  vertexBuffer                    (createBuffer(vk, vkDevice, &vertexBufferParams));
2395         const UniquePtr<Allocation>                             vertexBufferMemory              (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
2396
2397         VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2398
2399         const VkDeviceSize                                              imageSizeBytes                  = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
2400         const VkBufferCreateInfo                                readImageBufferParams   =
2401         {
2402                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           //      VkStructureType         sType;
2403                 DE_NULL,                                                                        //      const void*                     pNext;
2404                 imageSizeBytes,                                                         //      VkDeviceSize            size;
2405                 VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT,       //      VkBufferUsageFlags      usage;
2406                 0u,                                                                                     //      VkBufferCreateFlags     flags;
2407                 VK_SHARING_MODE_EXCLUSIVE,                                      //      VkSharingMode           sharingMode;
2408                 1u,                                                                                     //      deUint32                        queueFamilyCount;
2409                 &queueFamilyIndex,                                                      //      const deUint32*         pQueueFamilyIndices;
2410         };
2411         const Unique<VkBuffer>                                  readImageBuffer                 (createBuffer(vk, vkDevice, &readImageBufferParams));
2412         const UniquePtr<Allocation>                             readImageBufferMemory   (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
2413
2414         VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
2415
2416         const VkImageCreateInfo                                 imageParams                             =
2417         {
2418                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                    //      VkStructureType         sType;
2419                 DE_NULL,                                                                                                                                //      const void*                     pNext;
2420                 VK_IMAGE_TYPE_2D,                                                                                                               //      VkImageType                     imageType;
2421                 VK_FORMAT_R8G8B8A8_UNORM,                                                                                               //      VkFormat                        format;
2422                 { renderSize.x(), renderSize.y(), 1 },                                                                  //      VkExtent3D                      extent;
2423                 1u,                                                                                                                                             //      deUint32                        mipLevels;
2424                 1u,                                                                                                                                             //      deUint32                        arraySize;
2425                 1u,                                                                                                                                             //      deUint32                        samples;
2426                 VK_IMAGE_TILING_OPTIMAL,                                                                                                //      VkImageTiling           tiling;
2427                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT, //      VkImageUsageFlags       usage;
2428                 0u,                                                                                                                                             //      VkImageCreateFlags      flags;
2429                 VK_SHARING_MODE_EXCLUSIVE,                                                                                              //      VkSharingMode           sharingMode;
2430                 1u,                                                                                                                                             //      deUint32                        queueFamilyCount;
2431                 &queueFamilyIndex,                                                                                                              //      const deUint32*         pQueueFamilyIndices;
2432                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                              //      VkImageLayout           initialLayout;
2433         };
2434
2435         const Unique<VkImage>                                   image                                   (createImage(vk, vkDevice, &imageParams));
2436         const UniquePtr<Allocation>                             imageMemory                             (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
2437
2438         VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
2439
2440         const VkAttachmentDescription                   colorAttDesc                    =
2441         {
2442                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION,               //      VkStructureType                                 sType;
2443                 DE_NULL,                                                                                //      const void*                                             pNext;
2444                 VK_FORMAT_R8G8B8A8_UNORM,                                               //      VkFormat                                                format;
2445                 1u,                                                                                             //      deUint32                                                samples;
2446                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                    //      VkAttachmentLoadOp                              loadOp;
2447                 VK_ATTACHMENT_STORE_OP_STORE,                                   //      VkAttachmentStoreOp                             storeOp;
2448                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                //      VkAttachmentLoadOp                              stencilLoadOp;
2449                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                               //      VkAttachmentStoreOp                             stencilStoreOp;
2450                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               //      VkImageLayout                                   initialLayout;
2451                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               //      VkImageLayout                                   finalLayout;
2452                 0u,                                                                                             //      VkAttachmentDescriptionFlags    flags;
2453         };
2454         const VkAttachmentReference                             colorAttRef                             =
2455         {
2456                 0u,                                                                                             //      deUint32                attachment;
2457                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               //      VkImageLayout   layout;
2458         };
2459         const VkSubpassDescription                              subpassDesc                             =
2460         {
2461                 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION,                  //      VkStructureType                                 sType;
2462                 DE_NULL,                                                                                //      const void*                                             pNext;
2463                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                //      VkPipelineBindPoint                             pipelineBindPoint;
2464                 0u,                                                                                             //      VkSubpassDescriptionFlags               flags;
2465                 0u,                                                                                             //      deUint32                                                inputCount;
2466                 DE_NULL,                                                                                //      const VkAttachmentReference*    pInputAttachments;
2467                 1u,                                                                                             //      deUint32                                                colorCount;
2468                 &colorAttRef,                                                                   //      const VkAttachmentReference*    pColorAttachments;
2469                 DE_NULL,                                                                                //      const VkAttachmentReference*    pResolveAttachments;
2470                 { VK_NO_ATTACHMENT, VK_IMAGE_LAYOUT_GENERAL },  //      VkAttachmentReference                   depthStencilAttachment;
2471                 0u,                                                                                             //      deUint32                                                preserveCount;
2472                 DE_NULL,                                                                                //      const VkAttachmentReference*    pPreserveAttachments;
2473
2474         };
2475         const VkRenderPassCreateInfo                    renderPassParams                =
2476         {
2477                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,              //      VkStructureType                                 sType;
2478                 DE_NULL,                                                                                //      const void*                                             pNext;
2479                 1u,                                                                                             //      deUint32                                                attachmentCount;
2480                 &colorAttDesc,                                                                  //      const VkAttachmentDescription*  pAttachments;
2481                 1u,                                                                                             //      deUint32                                                subpassCount;
2482                 &subpassDesc,                                                                   //      const VkSubpassDescription*             pSubpasses;
2483                 0u,                                                                                             //      deUint32                                                dependencyCount;
2484                 DE_NULL,                                                                                //      const VkSubpassDependency*              pDependencies;
2485         };
2486         const Unique<VkRenderPass>                              renderPass                              (createRenderPass(vk, vkDevice, &renderPassParams));
2487
2488         const VkImageViewCreateInfo                             colorAttViewParams              =
2489         {
2490                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               //      VkStructureType                         sType;
2491                 DE_NULL,                                                                                //      const void*                                     pNext;
2492                 *image,                                                                                 //      VkImage                                         image;
2493                 VK_IMAGE_VIEW_TYPE_2D,                                                  //      VkImageViewType                         viewType;
2494                 VK_FORMAT_R8G8B8A8_UNORM,                                               //      VkFormat                                        format;
2495                 {
2496                         VK_CHANNEL_SWIZZLE_R,
2497                         VK_CHANNEL_SWIZZLE_G,
2498                         VK_CHANNEL_SWIZZLE_B,
2499                         VK_CHANNEL_SWIZZLE_A
2500                 },                                                                                              //      VkChannelMapping                        channels;
2501                 {
2502                         VK_IMAGE_ASPECT_COLOR_BIT,                                              //      VkImageAspectFlags      aspectMask;
2503                         0u,                                                                                             //      deUint32                        baseMipLevel;
2504                         1u,                                                                                             //      deUint32                        mipLevels;
2505                         0u,                                                                                             //      deUint32                        baseArrayLayer;
2506                         1u,                                                                                             //      deUint32                        arraySize;
2507                 },                                                                                              //      VkImageSubresourceRange         subresourceRange;
2508                 0u,                                                                                             //      VkImageViewCreateFlags          flags;
2509         };
2510         const Unique<VkImageView>                               colorAttView                    (createImageView(vk, vkDevice, &colorAttViewParams));
2511
2512         createShaders(vk, vkDevice, instance, context, modules, shaders);
2513
2514         // Pipeline layout
2515         const VkPipelineLayoutCreateInfo                pipelineLayoutParams    =
2516         {
2517                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,                  //      VkStructureType                                 sType;
2518                 DE_NULL,                                                                                                //      const void*                                             pNext;
2519                 0u,                                                                                                             //      deUint32                                                descriptorSetCount;
2520                 DE_NULL,                                                                                                //      const VkDescriptorSetLayout*    pSetLayouts;
2521                 0u,                                                                                                             //      deUint32                                                pushConstantRangeCount;
2522                 DE_NULL,                                                                                                //      const VkPushConstantRange*              pPushConstantRanges;
2523         };
2524         const Unique<VkPipelineLayout>                  pipelineLayout                  (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
2525
2526         // Pipeline
2527         const VkSpecializationInfo                              emptyShaderSpecParams   =
2528         {
2529                 0u,                                                                                                             //      deUint32                                                mapEntryCount;
2530                 DE_NULL,                                                                                                //      const VkSpecializationMapEntry* pMap;
2531                 0,                                                                                                              //      const deUintptr                                 dataSize;
2532                 DE_NULL,                                                                                                //      const void*                                             pData;
2533         };
2534         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
2535         for(map<VkShaderStage, VkShaderSp>::const_iterator stage = shaders.begin(); stage != shaders.end(); ++stage) {
2536                 VkPipelineShaderStageCreateInfo info = {
2537                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    //      VkStructureType                         sType;
2538                         DE_NULL,                                                                                                //      const void*                                     pNext;
2539                         stage->first,                                                                                   //      VkShaderStage                           stage;
2540                         **stage->second,                                                                                //      VkShader                                        shader;
2541                         &emptyShaderSpecParams,                                                                 //      const VkSpecializationInfo*     pSpecializationInfo;
2542                 };
2543                 shaderStageParams.push_back(info);
2544         }
2545         const VkPipelineDepthStencilStateCreateInfo     depthStencilParams              =
2546         {
2547                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     //      VkStructureType         sType;
2548                 DE_NULL,                                                                                                        //      const void*                     pNext;
2549                 DE_FALSE,                                                                                                       //      deUint32                        depthTestEnable;
2550                 DE_FALSE,                                                                                                       //      deUint32                        depthWriteEnable;
2551                 VK_COMPARE_OP_ALWAYS,                                                                           //      VkCompareOp                     depthCompareOp;
2552                 DE_FALSE,                                                                                                       //      deUint32                        depthBoundsTestEnable;
2553                 DE_FALSE,                                                                                                       //      deUint32                        stencilTestEnable;
2554                 {
2555                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilFailOp;
2556                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilPassOp;
2557                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilDepthFailOp;
2558                         VK_COMPARE_OP_ALWAYS,                                                                           //      VkCompareOp     stencilCompareOp;
2559                         0u,                                                                                                                     //      deUint32        stencilCompareMask;
2560                         0u,                                                                                                                     //      deUint32        stencilWriteMask;
2561                         0u,                                                                                                                     //      deUint32        stencilReference;
2562                 },                                                                                                                      //      VkStencilOpState        front;
2563                 {
2564                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilFailOp;
2565                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilPassOp;
2566                         VK_STENCIL_OP_KEEP,                                                                                     //      VkStencilOp     stencilDepthFailOp;
2567                         VK_COMPARE_OP_ALWAYS,                                                                           //      VkCompareOp     stencilCompareOp;
2568                         0u,                                                                                                                     //      deUint32        stencilCompareMask;
2569                         0u,                                                                                                                     //      deUint32        stencilWriteMask;
2570                         0u,                                                                                                                     //      deUint32        stencilReference;
2571                 },                                                                                                                      //      VkStencilOpState        back;
2572                 -1.0f,                                                                                                          //      float                           minDepthBounds;
2573                 +1.0f,                                                                                                          //      float                           maxDepthBounds;
2574         };
2575         const VkViewport                                                viewport0                               =
2576         {
2577                 0.0f,                                                                                                           //      float   originX;
2578                 0.0f,                                                                                                           //      float   originY;
2579                 (float)renderSize.x(),                                                                          //      float   width;
2580                 (float)renderSize.y(),                                                                          //      float   height;
2581                 0.0f,                                                                                                           //      float   minDepth;
2582                 1.0f,                                                                                                           //      float   maxDepth;
2583         };
2584         const VkRect2D                                                  scissor0                                =
2585         {
2586                 {
2587                         0u,                                                                                                                     //      deInt32 x;
2588                         0u,                                                                                                                     //      deInt32 y;
2589                 },                                                                                                                      //      VkOffset2D      offset;
2590                 {
2591                         renderSize.x(),                                                                                         //      deInt32 width;
2592                         renderSize.y(),                                                                                         //      deInt32 height;
2593                 },                                                                                                                      //      VkExtent2D      extent;
2594         };
2595         const VkPipelineViewportStateCreateInfo         viewportParams                  =
2596         {
2597                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          //      VkStructureType         sType;
2598                 DE_NULL,                                                                                                        //      const void*                     pNext;
2599                 1u,                                                                                                                     //      deUint32                        viewportCount;
2600                 &viewport0,
2601                 1u,
2602                 &scissor0
2603         };
2604         const VkSampleMask                                                      sampleMask                              = ~0u;
2605         const VkPipelineMultisampleStateCreateInfo      multisampleParams               =
2606         {
2607                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       //      VkStructureType sType;
2608                 DE_NULL,                                                                                                        //      const void*             pNext;
2609                 1u,                                                                                                                     //      deUint32                rasterSamples;
2610                 DE_FALSE,                                                                                                       //      deUint32                sampleShadingEnable;
2611                 0.0f,                                                                                                           //      float                   minSampleShading;
2612                 &sampleMask,                                                                                            //      VkSampleMask    sampleMask;
2613         };
2614         const VkPipelineRasterStateCreateInfo           rasterParams                    =
2615         {
2616                 VK_STRUCTURE_TYPE_PIPELINE_RASTER_STATE_CREATE_INFO,    //      VkStructureType sType;
2617                 DE_NULL,                                                                                                //      const void*             pNext;
2618                 DE_TRUE,                                                                                                //      deUint32                depthClipEnable;
2619                 DE_FALSE,                                                                                               //      deUint32                rasterizerDiscardEnable;
2620                 VK_FILL_MODE_SOLID,                                                                             //      VkFillMode              fillMode;
2621                 VK_CULL_MODE_NONE,                                                                              //      VkCullMode              cullMode;
2622                 VK_FRONT_FACE_CCW,                                                                              //      VkFrontFace             frontFace;
2623                 VK_FALSE,                                                                                               //      VkBool32                depthBiasEnable;
2624                 0.0f,                                                                                                   //      float                   depthBias;
2625                 0.0f,                                                                                                   //      float                   depthBiasClamp;
2626                 0.0f,                                                                                                   //      float                   slopeScaledDepthBias;
2627                 1.0f,                                                                                                   //      float                   lineWidth;
2628         };
2629         const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyParams     =
2630         {
2631                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    //      VkStructureType         sType;
2632                 DE_NULL,                                                                                                                //      const void*                     pNext;
2633                 VK_PRIMITIVE_TOPOLOGY_PATCH,                                                                    //      VkPrimitiveTopology     topology;
2634                 DE_FALSE,                                                                                                               //      deUint32                        primitiveRestartEnable;
2635         };
2636         const VkVertexInputBindingDescription           vertexBinding0 =
2637         {
2638                 0u,                                                                     // deUint32                                     binding;
2639                 deUint32(singleVertexDataSize),         // deUint32                                     strideInBytes;
2640                 VK_VERTEX_INPUT_STEP_RATE_VERTEX        // VkVertexInputStepRate        stepRate;
2641         };
2642         const VkVertexInputAttributeDescription         vertexAttrib0[2] =
2643         {
2644                 {
2645                         0u,                                                                     // deUint32     location;
2646                         0u,                                                                     // deUint32     binding;
2647                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
2648                         0u                                                                      // deUint32     offsetInBytes;
2649                 },
2650                 {
2651                         1u,                                                                     // deUint32     location;
2652                         0u,                                                                     // deUint32     binding;
2653                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
2654                         sizeof(Vec4),                                           // deUint32     offsetInBytes;
2655                 }
2656         };
2657
2658         const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams  =
2659         {
2660                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      //      VkStructureType                                                         sType;
2661                 DE_NULL,                                                                                                        //      const void*                                                                     pNext;
2662                 1u,                                                                                                                     //      deUint32                                                                        bindingCount;
2663                 &vertexBinding0,                                                                                        //      const VkVertexInputBindingDescription*          pVertexBindingDescriptions;
2664                 2u,                                                                                                                     //      deUint32                                                                        attributeCount;
2665                 vertexAttrib0,                                                                                          //      const VkVertexInputAttributeDescription*        pVertexAttributeDescriptions;
2666         };
2667         const VkPipelineColorBlendAttachmentState       attBlendParams                  =
2668         {
2669                 DE_FALSE,                                                                                                                               //      deUint32                blendEnable;
2670                 VK_BLEND_ONE,                                                                                                                   //      VkBlend                 srcBlendColor;
2671                 VK_BLEND_ZERO,                                                                                                                  //      VkBlend                 destBlendColor;
2672                 VK_BLEND_OP_ADD,                                                                                                                //      VkBlendOp               blendOpColor;
2673                 VK_BLEND_ONE,                                                                                                                   //      VkBlend                 srcBlendAlpha;
2674                 VK_BLEND_ZERO,                                                                                                                  //      VkBlend                 destBlendAlpha;
2675                 VK_BLEND_OP_ADD,                                                                                                                //      VkBlendOp               blendOpAlpha;
2676                 VK_CHANNEL_R_BIT|VK_CHANNEL_G_BIT|VK_CHANNEL_B_BIT|VK_CHANNEL_A_BIT,    //      VkChannelFlags  channelWriteMask;
2677         };
2678         const VkPipelineColorBlendStateCreateInfo       blendParams                             =
2679         {
2680                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       //      VkStructureType                                                         sType;
2681                 DE_NULL,                                                                                                        //      const void*                                                                     pNext;
2682                 DE_FALSE,                                                                                                       //      VkBool32                                                                        alphaToCoverageEnable;
2683                 DE_FALSE,                                                                                                       //      VkBool32                                                                        alphaToOneEnable;
2684                 DE_FALSE,                                                                                                       //      VkBool32                                                                        logicOpEnable;
2685                 VK_LOGIC_OP_COPY,                                                                                       //      VkLogicOp                                                                       logicOp;
2686                 1u,                                                                                                                     //      deUint32                                                                        attachmentCount;
2687                 &attBlendParams,                                                                                        //      const VkPipelineColorBlendAttachmentState*      pAttachments;
2688                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     //      float                                                                           blendConst[4];
2689         };
2690         const VkPipelineDynamicStateCreateInfo  dynamicStateInfo                =
2691         {
2692                 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,   //      VkStructureType                 sType;
2693                 DE_NULL,                                                                                                //      const void*                             pNext;
2694                 0u,                                                                                                             //      deUint32                                dynamicStateCount;
2695                 DE_NULL                                                                                                 //      const VkDynamicState*   pDynamicStates;
2696         };
2697
2698         const VkPipelineTessellationStateCreateInfo     tessellationState       =
2699         {
2700                 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
2701                 DE_NULL,
2702                 3u
2703         };
2704
2705         const VkGraphicsPipelineCreateInfo              pipelineParams                  =
2706         {
2707                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                //      VkStructureType                                                                 sType;
2708                 DE_NULL,                                                                                                //      const void*                                                                             pNext;
2709                 (deUint32)shaderStageParams.size(),                                             //      deUint32                                                                                stageCount;
2710                 &shaderStageParams[0],                                                                  //      const VkPipelineShaderStageCreateInfo*                  pStages;
2711                 &vertexInputStateParams,                                                                //      const VkPipelineVertexInputStateCreateInfo*             pVertexInputState;
2712                 &inputAssemblyParams,                                                                   //      const VkPipelineInputAssemblyStateCreateInfo*   pInputAssemblyState;
2713                 &tessellationState,                                                                             //      const VkPipelineTessellationStateCreateInfo*    pTessellationState;
2714                 &viewportParams,                                                                                //      const VkPipelineViewportStateCreateInfo*                pViewportState;
2715                 &rasterParams,                                                                                  //      const VkPipelineRasterStateCreateInfo*                  pRasterState;
2716                 &multisampleParams,                                                                             //      const VkPipelineMultisampleStateCreateInfo*             pMultisampleState;
2717                 &depthStencilParams,                                                                    //      const VkPipelineDepthStencilStateCreateInfo*    pDepthStencilState;
2718                 &blendParams,                                                                                   //      const VkPipelineColorBlendStateCreateInfo*              pColorBlendState;
2719                 &dynamicStateInfo,                                                                              //      const VkPipelineDynamicStateCreateInfo*                 pDynamicState;
2720                 0u,                                                                                                             //      VkPipelineCreateFlags                                                   flags;
2721                 *pipelineLayout,                                                                                //      VkPipelineLayout                                                                layout;
2722                 *renderPass,                                                                                    //      VkRenderPass                                                                    renderPass;
2723                 0u,                                                                                                             //      deUint32                                                                                subpass;
2724                 DE_NULL,                                                                                                //      VkPipeline                                                                              basePipelineHandle;
2725                 0u,                                                                                                             //      deInt32                                                                                 basePipelineIndex;
2726         };
2727
2728         const Unique<VkPipeline>                                pipeline                                (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams));
2729
2730         // Framebuffer
2731         const VkFramebufferCreateInfo                   framebufferParams               =
2732         {
2733                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                              //      VkStructureType         sType;
2734                 DE_NULL,                                                                                                //      const void*                     pNext;
2735                 *renderPass,                                                                                    //      VkRenderPass            renderPass;
2736                 1u,                                                                                                             //      deUint32                        attachmentCount;
2737                 &*colorAttView,                                                                                 //      const VkImageView*      pAttachments;
2738                 (deUint32)renderSize.x(),                                                               //      deUint32                        width;
2739                 (deUint32)renderSize.y(),                                                               //      deUint32                        height;
2740                 1u,                                                                                                             //      deUint32                        layers;
2741         };
2742         const Unique<VkFramebuffer>                             framebuffer                             (createFramebuffer(vk, vkDevice, &framebufferParams));
2743
2744         const VkCmdPoolCreateInfo                               cmdPoolParams                   =
2745         {
2746                 VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,                                         //      VkStructureType                 sType;
2747                 DE_NULL,                                                                                                        //      const void*                             pNext;
2748                 queueFamilyIndex,                                                                                       //      deUint32                                queueFamilyIndex;
2749                 VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT                                     //      VkCmdPoolCreateFlags    flags;
2750         };
2751         const Unique<VkCmdPool>                                 cmdPool                                 (createCommandPool(vk, vkDevice, &cmdPoolParams));
2752
2753         // Command buffer
2754         const VkCmdBufferCreateInfo                             cmdBufParams                    =
2755         {
2756                 VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,                               //      VkStructureType                 sType;
2757                 DE_NULL,                                                                                                //      const void*                             pNext;
2758                 *cmdPool,                                                                                               //      VkCmdPool                               pool;
2759                 VK_CMD_BUFFER_LEVEL_PRIMARY,                                                    //      VkCmdBufferLevel                level;
2760                 0u,                                                                                                             //      VkCmdBufferCreateFlags  flags;
2761         };
2762         const Unique<VkCmdBuffer>                               cmdBuf                                  (createCommandBuffer(vk, vkDevice, &cmdBufParams));
2763
2764         const VkCmdBufferBeginInfo                              cmdBufBeginParams               =
2765         {
2766                 VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,                                //      VkStructureType                         sType;
2767                 DE_NULL,                                                                                                //      const void*                                     pNext;
2768                 0u,                                                                                                             //      VkCmdBufferOptimizeFlags        flags;
2769                 DE_NULL,                                                                                                //      VkRenderPass                            renderPass;
2770                 0u,                                                                                                             //      deUint32                                        subpass;
2771                 DE_NULL,                                                                                                //      VkFramebuffer                           framebuffer;
2772         };
2773
2774         // Record commands
2775         VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
2776
2777         {
2778                 const VkMemoryBarrier           vertFlushBarrier        =
2779                 {
2780                         VK_STRUCTURE_TYPE_MEMORY_BARRIER,                       //      VkStructureType         sType;
2781                         DE_NULL,                                                                        //      const void*                     pNext;
2782                         VK_MEMORY_OUTPUT_HOST_WRITE_BIT,                        //      VkMemoryOutputFlags     outputMask;
2783                         VK_MEMORY_INPUT_VERTEX_ATTRIBUTE_FETCH_BIT,     //      VkMemoryInputFlags      inputMask;
2784                 };
2785                 const VkImageMemoryBarrier      colorAttBarrier         =
2786                 {
2787                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         //      VkStructureType                 sType;
2788                         DE_NULL,                                                                        //      const void*                             pNext;
2789                         0u,                                                                                     //      VkMemoryOutputFlags             outputMask;
2790                         VK_MEMORY_INPUT_COLOR_ATTACHMENT_BIT,           //      VkMemoryInputFlags              inputMask;
2791                         VK_IMAGE_LAYOUT_UNDEFINED,                                      //      VkImageLayout                   oldLayout;
2792                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       //      VkImageLayout                   newLayout;
2793                         queueFamilyIndex,                                                       //      deUint32                                srcQueueFamilyIndex;
2794                         queueFamilyIndex,                                                       //      deUint32                                destQueueFamilyIndex;
2795                         *image,                                                                         //      VkImage                                 image;
2796                         {
2797                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      //      VkImageAspect   aspect;
2798                                 0u,                                                                                     //      deUint32                baseMipLevel;
2799                                 1u,                                                                                     //      deUint32                mipLevels;
2800                                 0u,                                                                                     //      deUint32                baseArraySlice;
2801                                 1u,                                                                                     //      deUint32                arraySize;
2802                         }                                                                                       //      VkImageSubresourceRange subresourceRange;
2803                 };
2804                 const void*                             barriers[]                              = { &vertFlushBarrier, &colorAttBarrier };
2805                 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GPU_COMMANDS, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
2806         }
2807
2808         {
2809                 const VkClearValue                      clearValue              = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
2810                 const VkRenderPassBeginInfo     passBeginParams =
2811                 {
2812                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                       //      VkStructureType         sType;
2813                         DE_NULL,                                                                                        //      const void*                     pNext;
2814                         *renderPass,                                                                            //      VkRenderPass            renderPass;
2815                         *framebuffer,                                                                           //      VkFramebuffer           framebuffer;
2816                         { { 0, 0 }, { renderSize.x(), renderSize.y() } },       //      VkRect2D                        renderArea;
2817                         1u,                                                                                                     //      deUint32                        clearValueCount;
2818                         &clearValue,                                                                            //      const VkClearValue*     pClearValues;
2819                 };
2820                 vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_RENDER_PASS_CONTENTS_INLINE);
2821         }
2822
2823         vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2824         {
2825                 const VkDeviceSize bindingOffset = 0;
2826                 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
2827         }
2828         vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
2829         vk.cmdEndRenderPass(*cmdBuf);
2830
2831         {
2832                 const VkImageMemoryBarrier      renderFinishBarrier     =
2833                 {
2834                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         //      VkStructureType                 sType;
2835                         DE_NULL,                                                                        //      const void*                             pNext;
2836                         VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT,          //      VkMemoryOutputFlags             outputMask;
2837                         VK_MEMORY_INPUT_TRANSFER_BIT,                           //      VkMemoryInputFlags              inputMask;
2838                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       //      VkImageLayout                   oldLayout;
2839                         VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL,        //      VkImageLayout                   newLayout;
2840                         queueFamilyIndex,                                                       //      deUint32                                srcQueueFamilyIndex;
2841                         queueFamilyIndex,                                                       //      deUint32                                destQueueFamilyIndex;
2842                         *image,                                                                         //      VkImage                                 image;
2843                         {
2844                                 VK_IMAGE_ASPECT_COLOR_BIT,                                      //      VkImageAspectFlags      aspectMask;
2845                                 0u,                                                                                     //      deUint32                        baseMipLevel;
2846                                 1u,                                                                                     //      deUint32                        mipLevels;
2847                                 0u,                                                                                     //      deUint32                        baseArraySlice;
2848                                 1u,                                                                                     //      deUint32                        arraySize;
2849                         }                                                                                       //      VkImageSubresourceRange subresourceRange;
2850                 };
2851                 const void*                             barriers[]                              = { &renderFinishBarrier };
2852                 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
2853         }
2854
2855         {
2856                 const VkBufferImageCopy copyParams      =
2857                 {
2858                         (VkDeviceSize)0u,                                               //      VkDeviceSize                    bufferOffset;
2859                         (deUint32)renderSize.x(),                               //      deUint32                                bufferRowLength;
2860                         (deUint32)renderSize.y(),                               //      deUint32                                bufferImageHeight;
2861                         {
2862                                 VK_IMAGE_ASPECT_COLOR,                                  //      VkImageAspect           aspect;
2863                                 0u,                                                                             //      deUint32                        mipLevel;
2864                                 0u,                                                                             //      deUint32                        arrayLayer;
2865                                 1u,                                                                             //      deUint32                        arraySize;
2866                         },                                                                              //      VkImageSubresourceCopy  imageSubresource;
2867                         { 0u, 0u, 0u },                                                 //      VkOffset3D                              imageOffset;
2868                         { renderSize.x(), renderSize.y(), 1u }  //      VkExtent3D                              imageExtent;
2869                 };
2870                 vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, *readImageBuffer, 1u, &copyParams);
2871         }
2872
2873         {
2874                 const VkBufferMemoryBarrier     copyFinishBarrier       =
2875                 {
2876                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        //      VkStructureType         sType;
2877                         DE_NULL,                                                                        //      const void*                     pNext;
2878                         VK_MEMORY_OUTPUT_TRANSFER_BIT,                          //      VkMemoryOutputFlags     outputMask;
2879                         VK_MEMORY_INPUT_HOST_READ_BIT,                          //      VkMemoryInputFlags      inputMask;
2880                         queueFamilyIndex,                                                       //      deUint32                        srcQueueFamilyIndex;
2881                         queueFamilyIndex,                                                       //      deUint32                        destQueueFamilyIndex;
2882                         *readImageBuffer,                                                       //      VkBuffer                        buffer;
2883                         0u,                                                                                     //      VkDeviceSize            offset;
2884                         imageSizeBytes                                                          //      VkDeviceSize            size;
2885                 };
2886                 const void*                             barriers[]                              = { &copyFinishBarrier };
2887                 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
2888         }
2889
2890         VK_CHECK(vk.endCommandBuffer(*cmdBuf));
2891
2892         // Upload vertex data
2893         {
2894                 const VkMappedMemoryRange       range                   =
2895                 {
2896                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  //      VkStructureType sType;
2897                         DE_NULL,                                                                //      const void*             pNext;
2898                         vertexBufferMemory->getMemory(),                //      VkDeviceMemory  mem;
2899                         0,                                                                              //      VkDeviceSize    offset;
2900                         (VkDeviceSize)sizeof(vertexData),               //      VkDeviceSize    size;
2901                 };
2902                 void*                                           vertexBufPtr    = vertexBufferMemory->getHostPtr();
2903
2904                 deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData));
2905                 VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
2906         }
2907
2908         // Submit & wait for completion
2909         {
2910                 const VkFenceCreateInfo fenceParams     =
2911                 {
2912                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    //      VkStructureType         sType;
2913                         DE_NULL,                                                                //      const void*                     pNext;
2914                         0u,                                                                             //      VkFenceCreateFlags      flags;
2915                 };
2916                 const Unique<VkFence>   fence           (createFence(vk, vkDevice, &fenceParams));
2917
2918                 VK_CHECK(vk.queueSubmit(queue, 1u, &cmdBuf.get(), *fence));
2919                 VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
2920         }
2921
2922         void* imagePtr  = readImageBufferMemory->getHostPtr();
2923         tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
2924                                                                                         renderSize.x(), renderSize.y(), 1, imagePtr);
2925         // Log image
2926         {
2927                 const VkMappedMemoryRange       range           =
2928                 {
2929                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  //      VkStructureType sType;
2930                         DE_NULL,                                                                //      const void*             pNext;
2931                         readImageBufferMemory->getMemory(),             //      VkDeviceMemory  mem;
2932                         0,                                                                              //      VkDeviceSize    offset;
2933                         imageSizeBytes,                                                 //      VkDeviceSize    size;
2934                 };
2935
2936                 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
2937                 context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
2938         }
2939
2940         const RGBA threshold(1, 1, 1, 1);
2941         const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
2942         if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) {
2943                 return TestStatus::fail("Upper left corner mismatch");
2944         }
2945
2946         const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
2947         if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) {
2948                 return TestStatus::fail("Upper right corner mismatch");
2949         }
2950
2951         const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
2952         if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) {
2953                 return TestStatus::fail("Lower left corner mismatch");
2954         }
2955
2956         const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
2957         if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) {
2958                 return TestStatus::fail("Lower right corner mismatch");
2959         }
2960
2961         return TestStatus::pass("Rendered output matches input");
2962 }
2963
2964 void createTestsForAllStages(const std::string& name,
2965                                                          const RGBA (&inputColors)[4],
2966                                                          const RGBA (&outputColors)[4],
2967                                                          const map<string, string>& testCodeFragments,
2968                                                          tcu::TestCaseGroup* tests)
2969 {
2970         const ShaderElement             pipelineStages[]                                =
2971         {
2972                 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX),
2973                 ShaderElement("tessc", "main", VK_SHADER_STAGE_TESS_CONTROL),
2974                 ShaderElement("tesse", "main", VK_SHADER_STAGE_TESS_EVALUATION),
2975                 ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY),
2976                 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT),
2977         };
2978
2979         addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
2980                                                                                                  createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2981
2982         addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
2983                                                                                                  createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2984
2985         addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
2986                                                                                                  createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2987
2988         addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
2989                                                                                                  createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2990
2991         addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
2992                                                                                                  createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2993 }
2994 } // anonymous
2995
2996 tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
2997 {
2998         de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
2999
3000         instructionTests->addChild(createOpNopGroup(testCtx));
3001         instructionTests->addChild(createOpLineGroup(testCtx));
3002         instructionTests->addChild(createOpNoLineGroup(testCtx));
3003         instructionTests->addChild(createOpConstantNullGroup(testCtx));
3004         instructionTests->addChild(createOpConstantCompositeGroup(testCtx));
3005         instructionTests->addChild(createOpConstantUsageGroup(testCtx));
3006         instructionTests->addChild(createOpSourceGroup(testCtx));
3007         instructionTests->addChild(createOpSourceExtensionGroup(testCtx));
3008         instructionTests->addChild(createDecorationGroupGroup(testCtx));
3009         instructionTests->addChild(createOpPhiGroup(testCtx));
3010         instructionTests->addChild(createLoopControlGroup(testCtx));
3011         instructionTests->addChild(createFunctionControlGroup(testCtx));
3012         instructionTests->addChild(createSelectionControlGroup(testCtx));
3013         instructionTests->addChild(createBlockOrderGroup(testCtx));
3014         instructionTests->addChild(createOpUndefGroup(testCtx));
3015         instructionTests->addChild(createOpUnreachableGroup(testCtx));
3016     
3017     RGBA defaultColors[4];
3018         getDefaultColors(defaultColors);
3019         de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "graphics-assembly", "Test the graphics pipeline"));
3020         createTestsForAllStages("passthru", defaultColors, defaultColors, passthruFragments(), group.get());
3021         instructionTests->addChild(group.release());
3022         return instructionTests.release();
3023 }
3024
3025 } // SpirVAssembly
3026 } // vkt