1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
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:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
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.
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.
32 * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand)
33 *//*--------------------------------------------------------------------*/
35 #include "vktSpvAsmInstructionTests.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "tcuFormatUtil.hpp"
39 #include "tcuRGBA.hpp"
40 #include "tcuStringTemplate.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuVectorUtil.hpp"
45 #include "vkDeviceUtil.hpp"
46 #include "vkMemUtil.hpp"
47 #include "vkPlatform.hpp"
48 #include "vkPrograms.hpp"
49 #include "vkQueryUtil.hpp"
51 #include "vkRefUtil.hpp"
52 #include "vkStrUtil.hpp"
53 #include "vkTypeUtil.hpp"
56 #include "deRandom.hpp"
57 #include "deStringUtil.hpp"
58 #include "deUniquePtr.hpp"
59 #include "tcuStringTemplate.hpp"
61 #include "vktSpvAsmComputeShaderCase.hpp"
62 #include "vktSpvAsmComputeShaderTestUtil.hpp"
63 #include "vktTestCaseUtil.hpp"
71 namespace SpirVAssembly
85 using tcu::TestStatus;
88 using tcu::StringTemplate;
90 typedef Unique<VkShaderModule> ModuleHandleUp;
91 typedef de::SharedPtr<ModuleHandleUp> ModuleHandleSp;
92 typedef Unique<VkShader> VkShaderUp;
93 typedef de::SharedPtr<VkShaderUp> VkShaderSp;
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); }
101 static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
103 T* const typedPtr = (T*)dst;
104 for (int ndx = 0; ndx < numValues; ndx++)
105 typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
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).
111 // Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code:
115 // layout(std140, set = 0, binding = 0) readonly buffer Input {
118 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
122 // layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
125 // uint x = gl_GlobalInvocationID.x;
126 // output_data.elements[x] = -input_data.elements[x];
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";
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";
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";
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";
169 tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
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);
178 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
180 for (size_t ndx = 0; ndx < numElements; ++ndx)
181 negativeFloats[ndx] = -positiveFloats[ndx];
184 "OpNop\n" // As the first instruction
186 + string(s_ShaderPreamble) +
188 "OpNop\n" // After OpEntryPoint but before any type definitions
190 "OpSource GLSL 430\n"
191 "OpName %main \"main\"\n"
192 "OpName %id \"gl_GlobalInvocationID\"\n"
194 "OpDecorate %id BuiltIn GlobalInvocationId\n"
196 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
198 "OpNop\n" // In the middle of type definitions
200 + string(s_InputOutputBuffer) +
202 "%id = OpVariable %uvec3ptr Input\n"
203 "%zero = OpConstant %i32 0\n"
205 "%main = OpFunction %void None %voidf\n"
207 "%idval = OpLoad %uvec3 %id\n"
208 "%x = OpCompositeExtract %u32 %idval 0\n"
210 " OpNop\n" // Inside a function body
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"
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);
223 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec));
225 return group.release();
228 tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
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);
237 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
239 for (size_t ndx = 0; ndx < numElements; ++ndx)
240 negativeFloats[ndx] = -positiveFloats[ndx];
243 string(s_ShaderPreamble) +
245 "%fname1 = OpString \"negateInputs.comp\"\n"
246 "%fname2 = OpString \"negateInputs\"\n"
248 "OpSource GLSL 430\n"
249 "OpName %main \"main\"\n"
250 "OpName %id \"gl_GlobalInvocationID\"\n"
252 "OpDecorate %id BuiltIn GlobalInvocationId\n"
254 + string(s_InputOutputBufferTraits) +
256 "OpLine %fname1 0 0\n" // At the earliest possible position
258 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
260 "OpLine %fname1 0 1\n" // Multiple OpLines in sequence
261 "OpLine %fname2 1 0\n" // Different filenames
262 "OpLine %fname1 1000 100000\n"
264 "%id = OpVariable %uvec3ptr Input\n"
265 "%zero = OpConstant %i32 0\n"
267 "OpLine %fname1 1 1\n" // Before a function
269 "%main = OpFunction %void None %voidf\n"
272 "OpLine %fname1 1 1\n" // In a function
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"
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);
287 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec));
289 return group.release();
292 tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
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);
301 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
303 for (size_t ndx = 0; ndx < numElements; ++ndx)
304 negativeFloats[ndx] = -positiveFloats[ndx];
307 string(s_ShaderPreamble) +
309 "%fname = OpString \"negateInputs.comp\"\n"
311 "OpSource GLSL 430\n"
312 "OpName %main \"main\"\n"
313 "OpName %id \"gl_GlobalInvocationID\"\n"
315 "OpDecorate %id BuiltIn GlobalInvocationId\n"
317 + string(s_InputOutputBufferTraits) +
319 "OpNoLine\n" // At the earliest possible position, without preceding OpLine
321 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
323 "OpLine %fname 0 1\n"
324 "OpNoLine\n" // Immediately following a preceding OpLine
326 "OpLine %fname 1000 1\n"
328 "%id = OpVariable %uvec3ptr Input\n"
329 "%zero = OpConstant %i32 0\n"
331 "OpNoLine\n" // Contents after the previous OpLine
333 "%main = OpFunction %void None %voidf\n"
335 "%idval = OpLoad %uvec3 %id\n"
336 "%x = OpCompositeExtract %u32 %idval 0\n"
338 "OpNoLine\n" // Multiple OpNoLine
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"
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);
353 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec));
355 return group.release();
358 // Assembly code used for testing OpUnreachable is based on GLSL source code:
362 // layout(std140, set = 0, binding = 0) readonly buffer Input {
365 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
369 // void not_called_func() {
370 // // place OpUnreachable here
373 // uint modulo4(uint val) {
374 // switch (val % uint(4)) {
379 // default: return 100; // place OpUnreachable here
385 // // place OpUnreachable here
389 // uint x = gl_GlobalInvocationID.x;
390 // if (const5() > modulo4(1000)) {
391 // output_data.elements[x] = -input_data.elements[x];
393 // // place OpUnreachable here
394 // output_data.elements[x] = input_data.elements[x];
398 tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx)
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);
407 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
409 for (size_t ndx = 0; ndx < numElements; ++ndx)
410 negativeFloats[ndx] = -positiveFloats[ndx];
413 string(s_ShaderPreamble) +
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"
422 "OpDecorate %id BuiltIn GlobalInvocationId\n"
424 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
426 "%u32ptr = OpTypePointer Function %u32\n"
427 "%uintfuint = OpTypeFunction %u32 %u32ptr\n"
428 "%unitf = OpTypeFunction %u32\n"
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"
440 + string(s_InputOutputBuffer) +
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"
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
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"
480 " OpReturnValue %three\n"
482 " OpReturnValue %two\n"
484 " OpReturnValue %one\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
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
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);
504 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec));
506 return group.release();
509 // Assembly code used for testing decoration group is based on GLSL source code:
513 // layout(std140, set = 0, binding = 0) readonly buffer Input0 {
516 // layout(std140, set = 0, binding = 1) readonly buffer Input1 {
519 // layout(std140, set = 0, binding = 2) readonly buffer Input2 {
522 // layout(std140, set = 0, binding = 3) readonly buffer Input3 {
525 // layout(std140, set = 0, binding = 4) readonly buffer Input4 {
528 // layout(std140, set = 0, binding = 5) writeonly buffer Output {
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];
536 tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx)
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);
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);
555 for (size_t ndx = 0; ndx < numElements; ++ndx)
556 outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx];
559 string(s_ShaderPreamble) +
561 "OpSource GLSL 430\n"
562 "OpName %main \"main\"\n"
563 "OpName %id \"gl_GlobalInvocationID\"\n"
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"
570 "OpDecorate %groups BufferBlock\n"
571 "OpDecorate %groupm Offset 0\n"
572 "%groups = OpDecorationGroup\n"
573 "%groupm = OpDecorationGroup\n"
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"
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"
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"
611 + string(s_CommonTypes) +
613 "%id = OpVariable %uvec3ptr Input\n"
614 "%zero = OpConstant %i32 0\n"
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"
635 "%main = OpFunction %void None %voidf\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"
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);
665 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec));
667 return group.release();
670 tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx)
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);
679 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements);
681 for (size_t ndx = 0; ndx < numElements; ++ndx)
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;
693 string(s_ShaderPreamble) +
695 "OpSource GLSL 430\n"
696 "OpName %main \"main\"\n"
697 "OpName %id \"gl_GlobalInvocationID\"\n"
699 "OpDecorate %id BuiltIn GlobalInvocationId\n"
701 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
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"
712 "%main = OpFunction %void None %voidf\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"
720 // Case 1 before OpPhi.
724 "%default = 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"
737 // Case 0 after OpPhi.
742 // Case 2 after OpPhi.
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);
751 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpPhi corner cases", spec));
753 return group.release();
756 // Assembly code used for testing block order is based on GLSL source code:
760 // layout(std140, set = 0, binding = 0) readonly buffer Input {
763 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
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;
778 // output_data.elements[x] = -input_data.elements[x];
781 tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
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);
790 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
792 for (size_t ndx = 0; ndx <= 50; ++ndx)
793 outputFloats[ndx] = -inputFloats[ndx];
795 for (size_t ndx = 51; ndx < numElements; ++ndx)
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;
807 string(s_ShaderPreamble) +
809 "OpSource GLSL 430\n"
810 "OpName %main \"main\"\n"
811 "OpName %id \"gl_GlobalInvocationID\"\n"
813 "OpDecorate %id BuiltIn GlobalInvocationId\n"
815 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
817 "%u32ptr = OpTypePointer Function %u32\n"
818 "%u32ptr_input = OpTypePointer Input %u32\n"
820 + string(s_InputOutputBuffer) +
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"
830 "%main = OpFunction %void None %voidf\n"
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"
841 "%cmp = OpUGreaterThan %bool %x %const50\n"
842 " OpSelectionMerge %if_merge None\n"
843 " OpBranchConditional %cmp %if_true %if_false\n"
845 // Merge block for switch-statement: placed at the beginning.
846 "%switch_merge = OpLabel\n"
847 " OpBranch %if_merge\n"
849 // Case 1 for switch-statement.
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"
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"
869 // Merge block for if-statement: placed in the middle of true and false branch.
870 "%if_merge = OpLabel\n"
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"
880 // Case 2 for switch-statement.
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"
890 // Default case for switch-statement: placed in the middle of normal cases.
891 "%default = OpLabel\n"
892 " OpBranch %switch_merge\n"
894 // Case 0 for switch-statement: out of order.
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"
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);
909 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec));
911 return group.release();
919 CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {}
922 tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
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"
934 "OpEntryPoint GLCompute %main \"main\" %id\n"
935 "OpExecutionMode %main LocalSize 1 1 1\n"
939 "OpName %main \"main\"\n"
940 "OpName %id \"gl_GlobalInvocationID\"\n"
942 "OpDecorate %id BuiltIn GlobalInvocationId\n"
944 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
946 "%id = OpVariable %uvec3ptr Input\n"
947 "%zero = OpConstant %i32 0\n"
949 "%main = OpFunction %void None %voidf\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"
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() {}\""));
996 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
998 for (size_t ndx = 0; ndx < numElements; ++ndx)
999 negativeFloats[ndx] = -positiveFloats[ndx];
1001 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1003 map<string, string> specializations;
1004 ComputeShaderSpec spec;
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);
1012 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1015 return group.release();
1018 tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx)
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) +
1029 "OpSourceExtension \"${EXTENSION}\"\n"
1031 "OpName %main \"main\"\n"
1032 "OpName %id \"gl_GlobalInvocationID\"\n"
1034 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1036 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1038 "%id = OpVariable %uvec3ptr Input\n"
1039 "%zero = OpConstant %i32 0\n"
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"
1051 " OpFunctionEnd\n");
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
1059 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
1061 for (size_t ndx = 0; ndx < numElements; ++ndx)
1062 outputFloats[ndx] = -inputFloats[ndx];
1064 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1066 map<string, string> specializations;
1067 ComputeShaderSpec spec;
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);
1075 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1078 return group.release();
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)
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) +
1093 "OpSource GLSL 430\n"
1094 "OpName %main \"main\"\n"
1095 "OpName %id \"gl_GlobalInvocationID\"\n"
1097 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1099 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1102 "%null = OpConstantNull %type\n"
1104 "%id = OpVariable %uvec3ptr Input\n"
1105 "%zero = OpConstant %i32 0\n"
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"
1117 " OpFunctionEnd\n");
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"));
1133 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1135 for (size_t ndx = 0; ndx < numElements; ++ndx)
1136 negativeFloats[ndx] = -positiveFloats[ndx];
1138 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1140 map<string, string> specializations;
1141 ComputeShaderSpec spec;
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);
1149 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1152 return group.release();
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)
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) +
1167 "OpSource GLSL 430\n"
1168 "OpName %main \"main\"\n"
1169 "OpName %id \"gl_GlobalInvocationID\"\n"
1171 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1173 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1175 "%id = OpVariable %uvec3ptr Input\n"
1176 "%zero = OpConstant %i32 0\n"
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"
1190 " OpFunctionEnd\n");
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"));
1215 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1217 for (size_t ndx = 0; ndx < numElements; ++ndx)
1218 negativeFloats[ndx] = -positiveFloats[ndx];
1220 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1222 map<string, string> specializations;
1223 ComputeShaderSpec spec;
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);
1231 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1234 return group.release();
1237 // Checks that constant null/composite values can be used in computation.
1238 tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
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);
1247 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1249 for (size_t ndx = 0; ndx < numElements; ++ndx)
1250 negativeFloats[ndx] = -positiveFloats[ndx];
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"
1259 "OpSource GLSL 430\n"
1260 "OpName %main \"main\"\n"
1261 "OpName %id \"gl_GlobalInvocationID\"\n"
1263 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1265 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
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"
1273 + string(s_InputOutputBuffer) +
1275 "%id = OpVariable %uvec3ptr Input\n"
1276 "%zero = OpConstant %i32 0\n"
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"
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"
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"
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"
1315 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1316 " OpStore %outloc %final\n" // write to output
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);
1323 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec));
1325 return group.release();
1328 // Assembly code used for testing loop control is based on GLSL source code:
1331 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1332 // float elements[];
1334 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1335 // float elements[];
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;
1344 tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
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) +
1355 "OpSource GLSL 430\n"
1356 "OpName %main \"main\"\n"
1357 "OpName %id \"gl_GlobalInvocationID\"\n"
1359 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1361 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1363 "%u32ptr = OpTypePointer Function %u32\n"
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"
1371 "%main = OpFunction %void None %voidf\n"
1372 "%entry = OpLabel\n"
1373 "%i = OpVariable %u32ptr Function\n"
1374 " OpStore %i %zero\n"
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"
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"
1398 " OpFunctionEnd\n");
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"));
1405 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1407 for (size_t ndx = 0; ndx < numElements; ++ndx)
1408 outputFloats[ndx] = inputFloats[ndx] + 4.f;
1410 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1412 map<string, string> specializations;
1413 ComputeShaderSpec spec;
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);
1421 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1424 return group.release();
1427 // Assembly code used for testing selection control is based on GLSL source code:
1430 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1431 // float elements[];
1433 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1434 // float elements[];
1438 // uint x = gl_GlobalInvocationID.x;
1439 // float val = input_data.elements[x];
1441 // output_data.elements[x] = val + 1.f;
1443 // output_data.elements[x] = val - 1.f;
1445 tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
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) +
1456 "OpSource GLSL 430\n"
1457 "OpName %main \"main\"\n"
1458 "OpName %id \"gl_GlobalInvocationID\"\n"
1460 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1462 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
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"
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"
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"
1490 " OpFunctionEnd\n");
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"));
1497 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1499 for (size_t ndx = 0; ndx < numElements; ++ndx)
1500 outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f);
1502 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1504 map<string, string> specializations;
1505 ComputeShaderSpec spec;
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);
1513 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1516 return group.release();
1519 // Assembly code used for testing function control is based on GLSL source code:
1523 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1524 // float elements[];
1526 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1527 // float elements[];
1530 // float const10() { return 10.f; }
1533 // uint x = gl_GlobalInvocationID.x;
1534 // output_data.elements[x] = input_data.elements[x] + const10();
1536 tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx)
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) +
1547 "OpSource GLSL 430\n"
1548 "OpName %main \"main\"\n"
1549 "OpName %func_const10 \"const10(\"\n"
1550 "OpName %id \"gl_GlobalInvocationID\"\n"
1552 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1554 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1556 "%f32f = OpTypeFunction %f32\n"
1557 "%id = OpVariable %uvec3ptr Input\n"
1558 "%zero = OpConstant %i32 0\n"
1559 "%constf10 = OpConstant %f32 10.0\n"
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"
1574 "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n"
1575 "%label = OpLabel\n"
1576 " OpReturnValue %constf10\n"
1577 " OpFunctionEnd\n");
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"));
1589 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1591 for (size_t ndx = 0; ndx < numElements; ++ndx)
1592 outputFloats[ndx] = inputFloats[ndx] + 10.f;
1594 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1596 map<string, string> specializations;
1597 ComputeShaderSpec spec;
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);
1605 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1608 return group.release();
1611 // Checks that we can get undefined values for various types, without exercising a computation with it.
1612 tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx)
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) +
1623 "OpSource GLSL 430\n"
1624 "OpName %main \"main\"\n"
1625 "OpName %id \"gl_GlobalInvocationID\"\n"
1627 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1629 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1633 "%id = OpVariable %uvec3ptr Input\n"
1634 "%zero = OpConstant %i32 0\n"
1636 "%main = OpFunction %void None %voidf\n"
1637 "%label = OpLabel\n"
1639 "%undef = OpUndef %type\n"
1641 "%idval = OpLoad %uvec3 %id\n"
1642 "%x = OpCompositeExtract %u32 %idval 0\n"
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"
1650 " OpFunctionEnd\n");
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"));
1670 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1672 for (size_t ndx = 0; ndx < numElements; ++ndx)
1673 negativeFloats[ndx] = -positiveFloats[ndx];
1675 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1677 map<string, string> specializations;
1678 ComputeShaderSpec spec;
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);
1686 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1689 return group.release();
1693 typedef std::pair<std::string, VkShaderStage> EntryToStage;
1694 typedef map<string, vector<EntryToStage> > ModuleMap;
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
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;
1708 InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_)
1709 : testCodeFragments(testCodeFragments_)
1711 memcpy(inputColors, inputs, sizeof(inputs));
1712 memcpy(outputColors, outputs, sizeof(outputs));
1715 InstanceContext (const InstanceContext& other)
1716 : moduleMap(other.moduleMap)
1717 , testCodeFragments(other.testCodeFragments)
1719 memcpy(inputColors, other.inputColors, sizeof(inputColors));
1720 memcpy(outputColors, other.outputColors, sizeof(outputColors));
1724 // A description of a shader to be used for a single stage of the graphics pipeline.
1725 struct ShaderElement
1727 // The module that contains this shader entrypoint.
1728 const char* moduleName;
1730 // The name of the entrypoint.
1731 const char* entryName;
1733 // Which shader stage this entry point represents.
1734 VkShaderStage stage;
1736 ShaderElement (const char* moduleName_, const char* entryPoint_, VkShaderStage shaderStage_)
1737 : moduleName(moduleName_)
1738 , entryName(entryPoint_)
1739 , stage(shaderStage_)
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();
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
1754 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments)
1756 InstanceContext ctx(inputColors, outputColors, testCodeFragments);
1757 for (size_t i = 0; i < N; ++i)
1759 ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
1764 // The same as createInstanceContext above, but with default colors.
1766 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map<string, string>& testCodeFragments)
1768 RGBA defaultColors[4];
1769 getDefaultColors(defaultColors);
1770 return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
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)
1778 for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
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)
1784 const EntryToStage& stage = *shaderNdx;
1785 const VkShaderCreateInfo shaderParam =
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;
1794 stage_shaders[stage.second] = VkShaderSp(new Unique<VkShader>(createShader(vk, vkDevice, &shaderParam)));
1800 "%void = OpTypeVoid\n" \
1801 "%bool = OpTypeBool\n" \
1803 "%i32 = OpTypeInt 32 1\n" \
1804 "%u32 = OpTypeInt 32 0\n" \
1806 "%f32 = OpTypeFloat 32\n" \
1807 "%v3f32 = OpTypeVector %f32 3\n" \
1808 "%v4f32 = OpTypeVector %f32 4\n" \
1810 "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \
1811 "%fun = OpTypeFunction %void\n" \
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" \
1818 "%op_f32 = OpTypePointer Output %f32\n" \
1819 "%op_v4f32 = OpTypePointer Output %v4f32\n"
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"
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"
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
1851 // It corresponds roughly to this GLSL:
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"
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"
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"
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
1903 // It roughly corresponds to the following glsl.
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[];
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;
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_TessLevelOuter %BP_gl_TessLevelInner\n"
1926 "OpExecutionMode %BP_main OutputVertices 3\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_TessLevelOuter \"gl_TessLevelOuter\"\n"
1935 "OpName %BP_gl_TessLevelInner \"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_TessLevelOuter Patch\n"
1943 "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1944 "OpDecorate %BP_gl_TessLevelInner Patch\n"
1945 "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
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_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1955 "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
1957 "%BP_main = OpFunction %void None %fun\n"
1958 "%BP_label = OpLabel\n"
1960 "%BP_invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
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"
1965 "%BP_in_color_val = OpLoad %v4f32 %BP_in_color_ptr\n"
1966 "%BP_in_position_val = OpLoad %v4f32 %BP_in_position_ptr\n"
1968 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_color_val\n"
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"
1973 "OpStore %BP_out_color_ptr %BP_clr_transformed\n"
1974 "OpStore %BP_out_position_ptr %BP_in_position_val\n"
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"
1980 "%BP_first_invocation = OpLabel\n"
1981 "%BP_tess_outer_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
1982 "%BP_tess_outer_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
1983 "%BP_tess_outer_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
1984 "%BP_tess_inner = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
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"
1991 "OpBranch %BP_merge_label\n"
1992 "%BP_merge_label = OpLabel\n"
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
2002 // It roughly corresponds to the following glsl.
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;
2011 // #define interpolate(val)
2012 // vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
2013 // vec4(gl_TessCoord.z) * val[2]
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));
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"
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"
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"
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"
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"
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"
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"
2082 "%BP_out_pos_ptr = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
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"
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"
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"
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"
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"
2104 "OpStore %BP_out_color %BP_clr_transformed\n"
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
2114 // Derived from this GLSL:
2117 // layout(triangles) in;
2118 // layout(triangle_strip, max_vertices = 3) out;
2120 // layout(location = 1) in vec4 in_color[];
2121 // layout(location = 1) out vec4 out_color;
2124 // gl_Position = gl_in[0].gl_Position;
2125 // out_color = test_fun(in_color[0]);
2127 // gl_Position = gl_in[1].gl_Position;
2128 // out_color = test_fun(in_color[1]);
2130 // gl_Position = gl_in[2].gl_Position;
2131 // out_color = test_fun(in_color[2]);
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"
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"
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"
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"
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"
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"
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"
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"
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"
2211 "%BP_out_gl_position = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
2213 "OpStore %BP_out_gl_position %BP_in_position_0\n"
2214 "OpStore %BP_out_color %BP_transformed_in_color_0\n"
2217 "OpStore %BP_out_gl_position %BP_in_position_1\n"
2218 "OpStore %BP_out_color %BP_transformed_in_color_1\n"
2221 "OpStore %BP_out_gl_position %BP_in_position_2\n"
2222 "OpStore %BP_out_color %BP_transformed_in_color_2\n"
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
2235 // Derived from this GLSL:
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); }
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"
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"
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"
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"
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);
2295 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2296 // Tessellation control shader gets custom code from context, the rest are
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);
2307 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
2308 // Tessellation evaluation shader gets custom code from context, the rest are
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);
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);
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);
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)
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[] =
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(),
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(),
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(),
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()
2380 const size_t singleVertexDataSize = 2 * sizeof(Vec4);
2381 const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize;
2383 const VkBufferCreateInfo vertexBufferParams =
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;
2394 const Unique<VkBuffer> vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams));
2395 const UniquePtr<Allocation> vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
2397 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2399 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
2400 const VkBufferCreateInfo readImageBufferParams =
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;
2411 const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams));
2412 const UniquePtr<Allocation> readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
2414 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
2416 const VkImageCreateInfo imageParams =
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;
2435 const Unique<VkImage> image (createImage(vk, vkDevice, &imageParams));
2436 const UniquePtr<Allocation> imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
2438 VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
2440 const VkAttachmentDescription colorAttDesc =
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;
2454 const VkAttachmentReference colorAttRef =
2456 0u, // deUint32 attachment;
2457 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
2459 const VkSubpassDescription subpassDesc =
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;
2475 const VkRenderPassCreateInfo renderPassParams =
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;
2486 const Unique<VkRenderPass> renderPass (createRenderPass(vk, vkDevice, &renderPassParams));
2488 const VkImageViewCreateInfo colorAttViewParams =
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;
2496 VK_CHANNEL_SWIZZLE_R,
2497 VK_CHANNEL_SWIZZLE_G,
2498 VK_CHANNEL_SWIZZLE_B,
2499 VK_CHANNEL_SWIZZLE_A
2500 }, // VkChannelMapping channels;
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;
2510 const Unique<VkImageView> colorAttView (createImageView(vk, vkDevice, &colorAttViewParams));
2512 createShaders(vk, vkDevice, instance, context, modules, shaders);
2515 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
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;
2524 const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
2527 const VkSpecializationInfo emptyShaderSpecParams =
2529 0u, // deUint32 mapEntryCount;
2530 DE_NULL, // const VkSpecializationMapEntry* pMap;
2531 0, // const deUintptr dataSize;
2532 DE_NULL, // const void* pData;
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;
2543 shaderStageParams.push_back(info);
2545 const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
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;
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;
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;
2575 const VkViewport viewport0 =
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;
2584 const VkRect2D scissor0 =
2589 }, // VkOffset2D offset;
2591 renderSize.x(), // deInt32 width;
2592 renderSize.y(), // deInt32 height;
2593 }, // VkExtent2D extent;
2595 const VkPipelineViewportStateCreateInfo viewportParams =
2597 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2598 DE_NULL, // const void* pNext;
2599 1u, // deUint32 viewportCount;
2604 const VkSampleMask sampleMask = ~0u;
2605 const VkPipelineMultisampleStateCreateInfo multisampleParams =
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;
2614 const VkPipelineRasterStateCreateInfo rasterParams =
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;
2629 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
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;
2636 const VkVertexInputBindingDescription vertexBinding0 =
2638 0u, // deUint32 binding;
2639 deUint32(singleVertexDataSize), // deUint32 strideInBytes;
2640 VK_VERTEX_INPUT_STEP_RATE_VERTEX // VkVertexInputStepRate stepRate;
2642 const VkVertexInputAttributeDescription vertexAttrib0[2] =
2645 0u, // deUint32 location;
2646 0u, // deUint32 binding;
2647 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2648 0u // deUint32 offsetInBytes;
2651 1u, // deUint32 location;
2652 0u, // deUint32 binding;
2653 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2654 sizeof(Vec4), // deUint32 offsetInBytes;
2658 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
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;
2667 const VkPipelineColorBlendAttachmentState attBlendParams =
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;
2678 const VkPipelineColorBlendStateCreateInfo blendParams =
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];
2690 const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
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;
2698 const VkPipelineTessellationStateCreateInfo tessellationState =
2700 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
2705 const VkGraphicsPipelineCreateInfo pipelineParams =
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;
2728 const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams));
2731 const VkFramebufferCreateInfo framebufferParams =
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;
2742 const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams));
2744 const VkCmdPoolCreateInfo cmdPoolParams =
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;
2751 const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
2754 const VkCmdBufferCreateInfo cmdBufParams =
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;
2762 const Unique<VkCmdBuffer> cmdBuf (createCommandBuffer(vk, vkDevice, &cmdBufParams));
2764 const VkCmdBufferBeginInfo cmdBufBeginParams =
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;
2775 VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
2778 const VkMemoryBarrier vertFlushBarrier =
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;
2785 const VkImageMemoryBarrier colorAttBarrier =
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;
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;
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);
2809 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
2810 const VkRenderPassBeginInfo passBeginParams =
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;
2820 vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_RENDER_PASS_CONTENTS_INLINE);
2823 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2825 const VkDeviceSize bindingOffset = 0;
2826 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
2828 vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
2829 vk.cmdEndRenderPass(*cmdBuf);
2832 const VkImageMemoryBarrier renderFinishBarrier =
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;
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;
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);
2856 const VkBufferImageCopy copyParams =
2858 (VkDeviceSize)0u, // VkDeviceSize bufferOffset;
2859 (deUint32)renderSize.x(), // deUint32 bufferRowLength;
2860 (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
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;
2870 vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SOURCE_OPTIMAL, *readImageBuffer, 1u, ©Params);
2874 const VkBufferMemoryBarrier copyFinishBarrier =
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;
2886 const void* barriers[] = { ©FinishBarrier };
2887 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
2890 VK_CHECK(vk.endCommandBuffer(*cmdBuf));
2892 // Upload vertex data
2894 const VkMappedMemoryRange range =
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;
2902 void* vertexBufPtr = vertexBufferMemory->getHostPtr();
2904 deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData));
2905 VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
2908 // Submit & wait for completion
2910 const VkFenceCreateInfo fenceParams =
2912 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
2913 DE_NULL, // const void* pNext;
2914 0u, // VkFenceCreateFlags flags;
2916 const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams));
2918 VK_CHECK(vk.queueSubmit(queue, 1u, &cmdBuf.get(), *fence));
2919 VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
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);
2927 const VkMappedMemoryRange range =
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;
2936 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
2937 context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
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");
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");
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");
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");
2961 return TestStatus::pass("Rendered output matches input");
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)
2970 const ShaderElement pipelineStages[] =
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),
2979 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
2980 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2982 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
2983 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2985 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
2986 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2988 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
2989 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2991 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
2992 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments));
2996 tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
2998 de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
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));
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();