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"
55 #include "deRandom.hpp"
56 #include "deStringUtil.hpp"
57 #include "deUniquePtr.hpp"
58 #include "tcuStringTemplate.hpp"
61 #include "vktSpvAsmComputeShaderCase.hpp"
62 #include "vktSpvAsmComputeShaderTestUtil.hpp"
63 #include "vktTestCaseUtil.hpp"
73 namespace SpirVAssembly
87 using tcu::TestStatus;
90 using tcu::StringTemplate;
93 typedef Unique<VkShaderModule> ModuleHandleUp;
94 typedef de::SharedPtr<ModuleHandleUp> ModuleHandleSp;
96 template<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue);
97 template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); }
98 template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); }
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);
113 CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {}
116 // Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code:
120 // layout(std140, set = 0, binding = 0) readonly buffer Input {
123 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
127 // layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
130 // uint x = gl_GlobalInvocationID.x;
131 // output_data.elements[x] = -input_data.elements[x];
134 static const char* const s_ShaderPreamble =
135 "OpCapability Shader\n"
136 "OpMemoryModel Logical GLSL450\n"
137 "OpEntryPoint GLCompute %main \"main\" %id\n"
138 "OpExecutionMode %main LocalSize 1 1 1\n";
140 static const char* const s_CommonTypes =
141 "%bool = OpTypeBool\n"
142 "%void = OpTypeVoid\n"
143 "%voidf = OpTypeFunction %void\n"
144 "%u32 = OpTypeInt 32 0\n"
145 "%i32 = OpTypeInt 32 1\n"
146 "%f32 = OpTypeFloat 32\n"
147 "%uvec3 = OpTypeVector %u32 3\n"
148 "%uvec3ptr = OpTypePointer Input %uvec3\n"
149 "%f32ptr = OpTypePointer Uniform %f32\n"
150 "%f32arr = OpTypeRuntimeArray %f32\n";
152 // Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]").
153 static const char* const s_InputOutputBuffer =
154 "%inbuf = OpTypeStruct %f32arr\n"
155 "%inbufptr = OpTypePointer Uniform %inbuf\n"
156 "%indata = OpVariable %inbufptr Uniform\n"
157 "%outbuf = OpTypeStruct %f32arr\n"
158 "%outbufptr = OpTypePointer Uniform %outbuf\n"
159 "%outdata = OpVariable %outbufptr Uniform\n";
161 // Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0.
162 // indata is at binding point 0, while outdata is at 1.
163 static const char* const s_InputOutputBufferTraits =
164 "OpDecorate %inbuf BufferBlock\n"
165 "OpDecorate %indata DescriptorSet 0\n"
166 "OpDecorate %indata Binding 0\n"
167 "OpDecorate %outbuf BufferBlock\n"
168 "OpDecorate %outdata DescriptorSet 0\n"
169 "OpDecorate %outdata Binding 1\n"
170 "OpDecorate %f32arr ArrayStride 4\n"
171 "OpMemberDecorate %inbuf 0 Offset 0\n"
172 "OpMemberDecorate %outbuf 0 Offset 0\n";
174 tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
176 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction"));
177 ComputeShaderSpec spec;
178 de::Random rnd (deStringHash(group->getName()));
179 const int numElements = 100;
180 vector<float> positiveFloats (numElements, 0);
181 vector<float> negativeFloats (numElements, 0);
183 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
185 for (size_t ndx = 0; ndx < numElements; ++ndx)
186 negativeFloats[ndx] = -positiveFloats[ndx];
189 string(s_ShaderPreamble) +
191 "OpSource GLSL 430\n"
192 "OpName %main \"main\"\n"
193 "OpName %id \"gl_GlobalInvocationID\"\n"
195 "OpDecorate %id BuiltIn GlobalInvocationId\n"
197 + string(s_InputOutputBufferTraits) + string(s_CommonTypes)
199 + string(s_InputOutputBuffer) +
201 "%id = OpVariable %uvec3ptr Input\n"
202 "%zero = OpConstant %i32 0\n"
204 "%main = OpFunction %void None %voidf\n"
206 "%idval = OpLoad %uvec3 %id\n"
207 "%x = OpCompositeExtract %u32 %idval 0\n"
209 " OpNop\n" // Inside a function body
211 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
212 "%inval = OpLoad %f32 %inloc\n"
213 "%neg = OpFNegate %f32 %inval\n"
214 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
215 " OpStore %outloc %neg\n"
218 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
219 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
220 spec.numWorkGroups = IVec3(numElements, 1, 1);
222 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec));
224 return group.release();
227 tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
229 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction"));
230 ComputeShaderSpec spec;
231 de::Random rnd (deStringHash(group->getName()));
232 const int numElements = 100;
233 vector<float> positiveFloats (numElements, 0);
234 vector<float> negativeFloats (numElements, 0);
236 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
238 for (size_t ndx = 0; ndx < numElements; ++ndx)
239 negativeFloats[ndx] = -positiveFloats[ndx];
242 string(s_ShaderPreamble) +
244 "%fname1 = OpString \"negateInputs.comp\"\n"
245 "%fname2 = OpString \"negateInputs\"\n"
247 "OpSource GLSL 430\n"
248 "OpName %main \"main\"\n"
249 "OpName %id \"gl_GlobalInvocationID\"\n"
251 "OpDecorate %id BuiltIn GlobalInvocationId\n"
253 + string(s_InputOutputBufferTraits) +
255 "OpLine %fname1 0 0\n" // At the earliest possible position
257 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
259 "OpLine %fname1 0 1\n" // Multiple OpLines in sequence
260 "OpLine %fname2 1 0\n" // Different filenames
261 "OpLine %fname1 1000 100000\n"
263 "%id = OpVariable %uvec3ptr Input\n"
264 "%zero = OpConstant %i32 0\n"
266 "OpLine %fname1 1 1\n" // Before a function
268 "%main = OpFunction %void None %voidf\n"
271 "OpLine %fname1 1 1\n" // In a function
273 "%idval = OpLoad %uvec3 %id\n"
274 "%x = OpCompositeExtract %u32 %idval 0\n"
275 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
276 "%inval = OpLoad %f32 %inloc\n"
277 "%neg = OpFNegate %f32 %inval\n"
278 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
279 " OpStore %outloc %neg\n"
282 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
283 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
284 spec.numWorkGroups = IVec3(numElements, 1, 1);
286 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec));
288 return group.release();
291 tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
293 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction"));
294 ComputeShaderSpec spec;
295 de::Random rnd (deStringHash(group->getName()));
296 const int numElements = 100;
297 vector<float> positiveFloats (numElements, 0);
298 vector<float> negativeFloats (numElements, 0);
300 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
302 for (size_t ndx = 0; ndx < numElements; ++ndx)
303 negativeFloats[ndx] = -positiveFloats[ndx];
306 string(s_ShaderPreamble) +
308 "%fname = OpString \"negateInputs.comp\"\n"
310 "OpSource GLSL 430\n"
311 "OpName %main \"main\"\n"
312 "OpName %id \"gl_GlobalInvocationID\"\n"
314 "OpDecorate %id BuiltIn GlobalInvocationId\n"
316 + string(s_InputOutputBufferTraits) +
318 "OpNoLine\n" // At the earliest possible position, without preceding OpLine
320 + string(s_CommonTypes) + string(s_InputOutputBuffer) +
322 "OpLine %fname 0 1\n"
323 "OpNoLine\n" // Immediately following a preceding OpLine
325 "OpLine %fname 1000 1\n"
327 "%id = OpVariable %uvec3ptr Input\n"
328 "%zero = OpConstant %i32 0\n"
330 "OpNoLine\n" // Contents after the previous OpLine
332 "%main = OpFunction %void None %voidf\n"
334 "%idval = OpLoad %uvec3 %id\n"
335 "%x = OpCompositeExtract %u32 %idval 0\n"
337 "OpNoLine\n" // Multiple OpNoLine
341 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
342 "%inval = OpLoad %f32 %inloc\n"
343 "%neg = OpFNegate %f32 %inval\n"
344 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
345 " OpStore %outloc %neg\n"
348 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
349 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
350 spec.numWorkGroups = IVec3(numElements, 1, 1);
352 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec));
354 return group.release();
357 tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx)
359 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration"));
360 vector<CaseParameter> cases;
361 const int numElements = 100;
362 vector<float> inputFloats1 (numElements, 0);
363 vector<float> inputFloats2 (numElements, 0);
364 vector<float> outputFloats (numElements, 0);
365 const StringTemplate shaderTemplate (
366 string(s_ShaderPreamble) +
368 "OpName %main \"main\"\n"
369 "OpName %id \"gl_GlobalInvocationID\"\n"
371 "OpDecorate %id BuiltIn GlobalInvocationId\n"
375 "OpDecorate %inbuf1 BufferBlock\n"
376 "OpDecorate %indata1 DescriptorSet 0\n"
377 "OpDecorate %indata1 Binding 0\n"
378 "OpDecorate %inbuf2 BufferBlock\n"
379 "OpDecorate %indata2 DescriptorSet 0\n"
380 "OpDecorate %indata2 Binding 1\n"
381 "OpDecorate %outbuf BufferBlock\n"
382 "OpDecorate %outdata DescriptorSet 0\n"
383 "OpDecorate %outdata Binding 2\n"
384 "OpDecorate %f32arr ArrayStride 4\n"
385 "OpMemberDecorate %inbuf1 0 Offset 0\n"
386 "OpMemberDecorate %inbuf2 0 Offset 0\n"
387 "OpMemberDecorate %outbuf 0 Offset 0\n"
389 + string(s_CommonTypes) +
391 "%inbuf1 = OpTypeStruct %f32arr\n"
392 "%inbufptr1 = OpTypePointer Uniform %inbuf1\n"
393 "%indata1 = OpVariable %inbufptr1 Uniform\n"
394 "%inbuf2 = OpTypeStruct %f32arr\n"
395 "%inbufptr2 = OpTypePointer Uniform %inbuf2\n"
396 "%indata2 = OpVariable %inbufptr2 Uniform\n"
397 "%outbuf = OpTypeStruct %f32arr\n"
398 "%outbufptr = OpTypePointer Uniform %outbuf\n"
399 "%outdata = OpVariable %outbufptr Uniform\n"
401 "%id = OpVariable %uvec3ptr Input\n"
402 "%zero = OpConstant %i32 0\n"
403 "%c_f_m1 = OpConstant %f32 -1.\n"
405 "%main = OpFunction %void None %voidf\n"
407 "%idval = OpLoad %uvec3 %id\n"
408 "%x = OpCompositeExtract %u32 %idval 0\n"
409 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
410 "%inval1 = OpLoad %f32 %inloc1\n"
411 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
412 "%inval2 = OpLoad %f32 %inloc2\n"
413 "%mul = OpFMul %f32 %inval1 %inval2\n"
414 "%add = OpFAdd %f32 %mul %c_f_m1\n"
415 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
416 " OpStore %outloc %add\n"
420 cases.push_back(CaseParameter("multiplication", "OpDecorate %mul NoContraction"));
421 cases.push_back(CaseParameter("addition", "OpDecorate %add NoContraction"));
422 cases.push_back(CaseParameter("both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction"));
424 for (size_t ndx = 0; ndx < numElements; ++ndx)
426 inputFloats1[ndx] = 1.f + std::ldexp(1.f, -23); // 1 + 2^-23.
427 inputFloats2[ndx] = 1.f - std::ldexp(1.f, -23); // 1 - 2^-23.
428 // Result for (1 + 2^-23) * (1 - 2^-23) - 1. With NoContraction, the multiplication will be
429 // conducted separately and the result is rounded to 1. So the final result will be 0.f.
430 // If the operation is combined into a precise fused multiply-add, then the result would be
431 // 2^-46 (0xa8800000).
432 outputFloats[ndx] = 0.f;
435 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
437 map<string, string> specializations;
438 ComputeShaderSpec spec;
440 specializations["DECORATION"] = cases[caseNdx].param;
441 spec.assembly = shaderTemplate.specialize(specializations);
442 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
443 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
444 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
445 spec.numWorkGroups = IVec3(numElements, 1, 1);
447 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
449 return group.release();
452 // Copy contents in the input buffer to the output buffer.
453 tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx)
455 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopymemory", "Test the OpCopyMemory instruction"));
456 de::Random rnd (deStringHash(group->getName()));
457 const int numElements = 100;
459 // The following case adds vec4(0., 0.5, 1.5, 2.5) to each of the elements in the input buffer and writes output to the output buffer.
460 ComputeShaderSpec spec1;
461 vector<Vec4> inputFloats1 (numElements);
462 vector<Vec4> outputFloats1 (numElements);
464 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats1[0], numElements * 4);
466 for (size_t ndx = 0; ndx < numElements; ++ndx)
467 outputFloats1[ndx] = inputFloats1[ndx] + Vec4(0.f, 0.5f, 1.5f, 2.5f);
470 string(s_ShaderPreamble) +
472 "OpName %main \"main\"\n"
473 "OpName %id \"gl_GlobalInvocationID\"\n"
475 "OpDecorate %id BuiltIn GlobalInvocationId\n"
477 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
479 "%vec4 = OpTypeVector %f32 4\n"
480 "%vec4ptr_u = OpTypePointer Uniform %vec4\n"
481 "%vec4ptr_f = OpTypePointer Function %vec4\n"
482 "%vec4arr = OpTypeRuntimeArray %vec4\n"
483 "%inbuf = OpTypeStruct %vec4arr\n"
484 "%inbufptr = OpTypePointer Uniform %inbuf\n"
485 "%indata = OpVariable %inbufptr Uniform\n"
486 "%outbuf = OpTypeStruct %vec4arr\n"
487 "%outbufptr = OpTypePointer Uniform %outbuf\n"
488 "%outdata = OpVariable %outbufptr Uniform\n"
490 "%id = OpVariable %uvec3ptr Input\n"
491 "%zero = OpConstant %i32 0\n"
492 "%c_f_0 = OpConstant %f32 0.\n"
493 "%c_f_0_5 = OpConstant %f32 0.5\n"
494 "%c_f_1_5 = OpConstant %f32 1.5\n"
495 "%c_f_2_5 = OpConstant %f32 2.5\n"
496 "%c_vec4 = OpConstantComposite %vec4 %c_f_0 %c_f_0_5 %c_f_1_5 %c_f_2_5\n"
498 "%main = OpFunction %void None %voidf\n"
500 "%v_vec4 = OpVariable %vec4ptr_f Function\n"
501 "%idval = OpLoad %uvec3 %id\n"
502 "%x = OpCompositeExtract %u32 %idval 0\n"
503 "%inloc = OpAccessChain %vec4ptr_u %indata %zero %x\n"
504 "%outloc = OpAccessChain %vec4ptr_u %outdata %zero %x\n"
505 " OpCopyMemory %v_vec4 %inloc\n"
506 "%v_vec4_val = OpLoad %vec4 %v_vec4\n"
507 "%add = OpFAdd %vec4 %v_vec4_val %c_vec4\n"
508 " OpStore %outloc %add\n"
512 spec1.inputs.push_back(BufferSp(new Vec4Buffer(inputFloats1)));
513 spec1.outputs.push_back(BufferSp(new Vec4Buffer(outputFloats1)));
514 spec1.numWorkGroups = IVec3(numElements, 1, 1);
516 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector", "OpCopyMemory elements of vector type", spec1));
518 // The following case copies a float[100] variable from the input buffer to the output buffer.
519 ComputeShaderSpec spec2;
520 vector<float> inputFloats2 (numElements);
521 vector<float> outputFloats2 (numElements);
523 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats2[0], numElements);
525 for (size_t ndx = 0; ndx < numElements; ++ndx)
526 outputFloats2[ndx] = inputFloats2[ndx];
529 string(s_ShaderPreamble) +
531 "OpName %main \"main\"\n"
532 "OpName %id \"gl_GlobalInvocationID\"\n"
534 "OpDecorate %id BuiltIn GlobalInvocationId\n"
536 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
538 "%hundred = OpConstant %u32 100\n"
539 "%f32arr100 = OpTypeArray %f32 %hundred\n"
540 "%f32arr100ptr_f = OpTypePointer Function %f32arr100\n"
541 "%f32arr100ptr_u = OpTypePointer Uniform %f32arr100\n"
542 "%inbuf = OpTypeStruct %f32arr100\n"
543 "%inbufptr = OpTypePointer Uniform %inbuf\n"
544 "%indata = OpVariable %inbufptr Uniform\n"
545 "%outbuf = OpTypeStruct %f32arr100\n"
546 "%outbufptr = OpTypePointer Uniform %outbuf\n"
547 "%outdata = OpVariable %outbufptr Uniform\n"
549 "%id = OpVariable %uvec3ptr Input\n"
550 "%zero = OpConstant %i32 0\n"
552 "%main = OpFunction %void None %voidf\n"
554 "%var = OpVariable %f32arr100ptr_f Function\n"
555 "%inarr = OpAccessChain %f32arr100ptr_u %indata %zero\n"
556 "%outarr = OpAccessChain %f32arr100ptr_u %outdata %zero\n"
557 " OpCopyMemory %var %inarr\n"
558 " OpCopyMemory %outarr %var\n"
562 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
563 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
564 spec2.numWorkGroups = IVec3(1, 1, 1);
566 group->addChild(new SpvAsmComputeShaderCase(testCtx, "array", "OpCopyMemory elements of array type", spec2));
568 // The following case copies a struct{vec4, vec4, vec4, vec4} variable from the input buffer to the output buffer.
569 ComputeShaderSpec spec3;
570 vector<float> inputFloats3 (16);
571 vector<float> outputFloats3 (16);
573 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats3[0], 16);
575 for (size_t ndx = 0; ndx < 16; ++ndx)
576 outputFloats3[ndx] = -inputFloats3[ndx];
579 string(s_ShaderPreamble) +
581 "OpName %main \"main\"\n"
582 "OpName %id \"gl_GlobalInvocationID\"\n"
584 "OpDecorate %id BuiltIn GlobalInvocationId\n"
586 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
588 "%vec4 = OpTypeVector %f32 4\n"
589 "%inbuf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n"
590 "%inbufptr = OpTypePointer Uniform %inbuf\n"
591 "%indata = OpVariable %inbufptr Uniform\n"
592 "%outbuf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n"
593 "%outbufptr = OpTypePointer Uniform %outbuf\n"
594 "%outdata = OpVariable %outbufptr Uniform\n"
595 "%vec4stptr = OpTypePointer Function %inbuf\n"
597 "%id = OpVariable %uvec3ptr Input\n"
598 "%zero = OpConstant %i32 0\n"
600 "%main = OpFunction %void None %voidf\n"
602 "%var = OpVariable %vec4stptr Function\n"
603 " OpCopyMemory %var %indata\n"
604 " OpCopyMemory %outdata %var\n"
608 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
609 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3)));
610 spec3.numWorkGroups = IVec3(1, 1, 1);
612 group->addChild(new SpvAsmComputeShaderCase(testCtx, "struct", "OpCopyMemory elements of struct type", spec3));
614 // The following case negates multiple float variables from the input buffer and stores the results to the output buffer.
615 ComputeShaderSpec spec4;
616 vector<float> inputFloats4 (numElements);
617 vector<float> outputFloats4 (numElements);
619 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats4[0], numElements);
621 for (size_t ndx = 0; ndx < numElements; ++ndx)
622 outputFloats4[ndx] = -inputFloats4[ndx];
625 string(s_ShaderPreamble) +
627 "OpName %main \"main\"\n"
628 "OpName %id \"gl_GlobalInvocationID\"\n"
630 "OpDecorate %id BuiltIn GlobalInvocationId\n"
632 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
634 "%f32ptr_f = OpTypePointer Function %f32\n"
635 "%id = OpVariable %uvec3ptr Input\n"
636 "%zero = OpConstant %i32 0\n"
638 "%main = OpFunction %void None %voidf\n"
640 "%var = OpVariable %f32ptr_f Function\n"
641 "%idval = OpLoad %uvec3 %id\n"
642 "%x = OpCompositeExtract %u32 %idval 0\n"
643 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
644 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
645 " OpCopyMemory %var %inloc\n"
646 "%val = OpLoad %f32 %var\n"
647 "%neg = OpFNegate %f32 %val\n"
648 " OpStore %outloc %neg\n"
652 spec4.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
653 spec4.outputs.push_back(BufferSp(new Float32Buffer(outputFloats4)));
654 spec4.numWorkGroups = IVec3(numElements, 1, 1);
656 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float", "OpCopyMemory elements of float type", spec4));
658 return group.release();
661 tcu::TestCaseGroup* createOpCopyObjectGroup (tcu::TestContext& testCtx)
663 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopyobject", "Test the OpCopyObject instruction"));
664 ComputeShaderSpec spec;
665 de::Random rnd (deStringHash(group->getName()));
666 const int numElements = 100;
667 vector<float> inputFloats (numElements, 0);
668 vector<float> outputFloats (numElements, 0);
670 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
672 for (size_t ndx = 0; ndx < numElements; ++ndx)
673 outputFloats[ndx] = inputFloats[ndx] + 7.5f;
676 string(s_ShaderPreamble) +
678 "OpName %main \"main\"\n"
679 "OpName %id \"gl_GlobalInvocationID\"\n"
681 "OpDecorate %id BuiltIn GlobalInvocationId\n"
683 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
685 "%fvec3 = OpTypeVector %f32 3\n"
686 "%fmat = OpTypeMatrix %fvec3 3\n"
687 "%three = OpConstant %u32 3\n"
688 "%farr = OpTypeArray %f32 %three\n"
689 "%fst = OpTypeStruct %f32 %f32\n"
691 + string(s_InputOutputBuffer) +
693 "%id = OpVariable %uvec3ptr Input\n"
694 "%zero = OpConstant %i32 0\n"
695 "%c_f = OpConstant %f32 1.5\n"
696 "%c_fvec3 = OpConstantComposite %fvec3 %c_f %c_f %c_f\n"
697 "%c_fmat = OpConstantComposite %fmat %c_fvec3 %c_fvec3 %c_fvec3\n"
698 "%c_farr = OpConstantComposite %farr %c_f %c_f %c_f\n"
699 "%c_fst = OpConstantComposite %fst %c_f %c_f\n"
701 "%main = OpFunction %void None %voidf\n"
703 "%c_f_copy = OpCopyObject %f32 %c_f\n"
704 "%c_fvec3_copy = OpCopyObject %fvec3 %c_fvec3\n"
705 "%c_fmat_copy = OpCopyObject %fmat %c_fmat\n"
706 "%c_farr_copy = OpCopyObject %farr %c_farr\n"
707 "%c_fst_copy = OpCopyObject %fst %c_fst\n"
708 "%fvec3_elem = OpCompositeExtract %f32 %c_fvec3_copy 0\n"
709 "%fmat_elem = OpCompositeExtract %f32 %c_fmat_copy 1 2\n"
710 "%farr_elem = OpCompositeExtract %f32 %c_fmat_copy 2\n"
711 "%fst_elem = OpCompositeExtract %f32 %c_fmat_copy 1\n"
712 // Add up. 1.5 * 5 = 7.5.
713 "%add1 = OpFAdd %f32 %c_f_copy %fvec3_elem\n"
714 "%add2 = OpFAdd %f32 %add1 %fmat_elem\n"
715 "%add3 = OpFAdd %f32 %add2 %farr_elem\n"
716 "%add4 = OpFAdd %f32 %add3 %fst_elem\n"
718 "%idval = OpLoad %uvec3 %id\n"
719 "%x = OpCompositeExtract %u32 %idval 0\n"
720 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
721 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
722 "%inval = OpLoad %f32 %inloc\n"
723 "%add = OpFAdd %f32 %add4 %inval\n"
724 " OpStore %outloc %add\n"
727 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
728 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
729 spec.numWorkGroups = IVec3(numElements, 1, 1);
731 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "OpCopyObject on different types", spec));
733 return group.release();
735 // Assembly code used for testing OpUnreachable is based on GLSL source code:
739 // layout(std140, set = 0, binding = 0) readonly buffer Input {
742 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
746 // void not_called_func() {
747 // // place OpUnreachable here
750 // uint modulo4(uint val) {
751 // switch (val % uint(4)) {
756 // default: return 100; // place OpUnreachable here
762 // // place OpUnreachable here
766 // uint x = gl_GlobalInvocationID.x;
767 // if (const5() > modulo4(1000)) {
768 // output_data.elements[x] = -input_data.elements[x];
770 // // place OpUnreachable here
771 // output_data.elements[x] = input_data.elements[x];
775 tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx)
777 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opunreachable", "Test the OpUnreachable instruction"));
778 ComputeShaderSpec spec;
779 de::Random rnd (deStringHash(group->getName()));
780 const int numElements = 100;
781 vector<float> positiveFloats (numElements, 0);
782 vector<float> negativeFloats (numElements, 0);
784 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
786 for (size_t ndx = 0; ndx < numElements; ++ndx)
787 negativeFloats[ndx] = -positiveFloats[ndx];
790 string(s_ShaderPreamble) +
792 "OpSource GLSL 430\n"
793 "OpName %func_main \"main\"\n"
794 "OpName %func_not_called_func \"not_called_func(\"\n"
795 "OpName %func_modulo4 \"modulo4(u1;\"\n"
796 "OpName %func_const5 \"const5(\"\n"
797 "OpName %id \"gl_GlobalInvocationID\"\n"
799 "OpDecorate %id BuiltIn GlobalInvocationId\n"
801 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
803 "%u32ptr = OpTypePointer Function %u32\n"
804 "%uintfuint = OpTypeFunction %u32 %u32ptr\n"
805 "%unitf = OpTypeFunction %u32\n"
807 "%id = OpVariable %uvec3ptr Input\n"
808 "%zero = OpConstant %u32 0\n"
809 "%one = OpConstant %u32 1\n"
810 "%two = OpConstant %u32 2\n"
811 "%three = OpConstant %u32 3\n"
812 "%four = OpConstant %u32 4\n"
813 "%five = OpConstant %u32 5\n"
814 "%hundred = OpConstant %u32 100\n"
815 "%thousand = OpConstant %u32 1000\n"
817 + string(s_InputOutputBuffer) +
820 "%func_main = OpFunction %void None %voidf\n"
821 "%main_entry = OpLabel\n"
822 "%idval = OpLoad %uvec3 %id\n"
823 "%x = OpCompositeExtract %u32 %idval 0\n"
824 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
825 "%inval = OpLoad %f32 %inloc\n"
826 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
827 "%ret_const5 = OpFunctionCall %u32 %func_const5\n"
828 "%ret_modulo4 = OpFunctionCall %u32 %func_modulo4 %thousand\n"
829 "%cmp_gt = OpUGreaterThan %bool %ret_const5 %ret_modulo4\n"
830 " OpSelectionMerge %if_end None\n"
831 " OpBranchConditional %cmp_gt %if_true %if_false\n"
832 "%if_true = OpLabel\n"
833 "%negate = OpFNegate %f32 %inval\n"
834 " OpStore %outloc %negate\n"
835 " OpBranch %if_end\n"
836 "%if_false = OpLabel\n"
837 " OpUnreachable\n" // Unreachable else branch for if statement
838 "%if_end = OpLabel\n"
842 // not_called_function()
843 "%func_not_called_func = OpFunction %void None %voidf\n"
844 "%not_called_func_entry = OpLabel\n"
845 " OpUnreachable\n" // Unreachable entry block in not called static function
849 "%func_modulo4 = OpFunction %u32 None %uintfuint\n"
850 "%valptr = OpFunctionParameter %u32ptr\n"
851 "%modulo4_entry = OpLabel\n"
852 "%val = OpLoad %u32 %valptr\n"
853 "%modulo = OpUMod %u32 %val %four\n"
854 " OpSelectionMerge %switch_merge None\n"
855 " OpSwitch %modulo %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
857 " OpReturnValue %three\n"
859 " OpReturnValue %two\n"
861 " OpReturnValue %one\n"
863 " OpReturnValue %zero\n"
864 "%default = OpLabel\n"
865 " OpUnreachable\n" // Unreachable default case for switch statement
866 "%switch_merge = OpLabel\n"
867 " OpUnreachable\n" // Unreachable merge block for switch statement
871 "%func_const5 = OpFunction %u32 None %unitf\n"
872 "%const5_entry = OpLabel\n"
873 " OpReturnValue %five\n"
874 "%unreachable = OpLabel\n"
875 " OpUnreachable\n" // Unreachable block in function
877 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
878 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
879 spec.numWorkGroups = IVec3(numElements, 1, 1);
881 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec));
883 return group.release();
886 // Assembly code used for testing decoration group is based on GLSL source code:
890 // layout(std140, set = 0, binding = 0) readonly buffer Input0 {
893 // layout(std140, set = 0, binding = 1) readonly buffer Input1 {
896 // layout(std140, set = 0, binding = 2) readonly buffer Input2 {
899 // layout(std140, set = 0, binding = 3) readonly buffer Input3 {
902 // layout(std140, set = 0, binding = 4) readonly buffer Input4 {
905 // layout(std140, set = 0, binding = 5) writeonly buffer Output {
910 // uint x = gl_GlobalInvocationID.x;
911 // output_data.elements[x] = input_data0.elements[x] + input_data1.elements[x] + input_data2.elements[x] + input_data3.elements[x] + input_data4.elements[x];
913 tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx)
915 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Test the OpDecorationGroup & OpGroupDecorate instruction"));
916 ComputeShaderSpec spec;
917 de::Random rnd (deStringHash(group->getName()));
918 const int numElements = 100;
919 vector<float> inputFloats0 (numElements, 0);
920 vector<float> inputFloats1 (numElements, 0);
921 vector<float> inputFloats2 (numElements, 0);
922 vector<float> inputFloats3 (numElements, 0);
923 vector<float> inputFloats4 (numElements, 0);
924 vector<float> outputFloats (numElements, 0);
926 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats0[0], numElements);
927 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats1[0], numElements);
928 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats2[0], numElements);
929 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats3[0], numElements);
930 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats4[0], numElements);
932 for (size_t ndx = 0; ndx < numElements; ++ndx)
933 outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx];
936 string(s_ShaderPreamble) +
938 "OpSource GLSL 430\n"
939 "OpName %main \"main\"\n"
940 "OpName %id \"gl_GlobalInvocationID\"\n"
942 // Not using group decoration on variable.
943 "OpDecorate %id BuiltIn GlobalInvocationId\n"
944 // Not using group decoration on type.
945 "OpDecorate %f32arr ArrayStride 4\n"
947 "OpDecorate %groups BufferBlock\n"
948 "OpDecorate %groupm Offset 0\n"
949 "%groups = OpDecorationGroup\n"
950 "%groupm = OpDecorationGroup\n"
952 // Group decoration on multiple structs.
953 "OpGroupDecorate %groups %outbuf %inbuf0 %inbuf1 %inbuf2 %inbuf3 %inbuf4\n"
954 // Group decoration on multiple struct members.
955 "OpGroupMemberDecorate %groupm %outbuf 0 %inbuf0 0 %inbuf1 0 %inbuf2 0 %inbuf3 0 %inbuf4 0\n"
957 "OpDecorate %group1 DescriptorSet 0\n"
958 "OpDecorate %group3 DescriptorSet 0\n"
959 "OpDecorate %group3 NonWritable\n"
960 "OpDecorate %group3 Restrict\n"
961 "%group0 = OpDecorationGroup\n"
962 "%group1 = OpDecorationGroup\n"
963 "%group3 = OpDecorationGroup\n"
965 // Applying the same decoration group multiple times.
966 "OpGroupDecorate %group1 %outdata\n"
967 "OpGroupDecorate %group1 %outdata\n"
968 "OpGroupDecorate %group1 %outdata\n"
969 "OpDecorate %outdata DescriptorSet 0\n"
970 "OpDecorate %outdata Binding 5\n"
971 // Applying decoration group containing nothing.
972 "OpGroupDecorate %group0 %indata0\n"
973 "OpDecorate %indata0 DescriptorSet 0\n"
974 "OpDecorate %indata0 Binding 0\n"
975 // Applying decoration group containing one decoration.
976 "OpGroupDecorate %group1 %indata1\n"
977 "OpDecorate %indata1 Binding 1\n"
978 // Applying decoration group containing multiple decorations.
979 "OpGroupDecorate %group3 %indata2 %indata3\n"
980 "OpDecorate %indata2 Binding 2\n"
981 "OpDecorate %indata3 Binding 3\n"
982 // Applying multiple decoration groups (with overlapping).
983 "OpGroupDecorate %group0 %indata4\n"
984 "OpGroupDecorate %group1 %indata4\n"
985 "OpGroupDecorate %group3 %indata4\n"
986 "OpDecorate %indata4 Binding 4\n"
988 + string(s_CommonTypes) +
990 "%id = OpVariable %uvec3ptr Input\n"
991 "%zero = OpConstant %i32 0\n"
993 "%outbuf = OpTypeStruct %f32arr\n"
994 "%outbufptr = OpTypePointer Uniform %outbuf\n"
995 "%outdata = OpVariable %outbufptr Uniform\n"
996 "%inbuf0 = OpTypeStruct %f32arr\n"
997 "%inbuf0ptr = OpTypePointer Uniform %inbuf0\n"
998 "%indata0 = OpVariable %inbuf0ptr Uniform\n"
999 "%inbuf1 = OpTypeStruct %f32arr\n"
1000 "%inbuf1ptr = OpTypePointer Uniform %inbuf1\n"
1001 "%indata1 = OpVariable %inbuf1ptr Uniform\n"
1002 "%inbuf2 = OpTypeStruct %f32arr\n"
1003 "%inbuf2ptr = OpTypePointer Uniform %inbuf2\n"
1004 "%indata2 = OpVariable %inbuf2ptr Uniform\n"
1005 "%inbuf3 = OpTypeStruct %f32arr\n"
1006 "%inbuf3ptr = OpTypePointer Uniform %inbuf3\n"
1007 "%indata3 = OpVariable %inbuf3ptr Uniform\n"
1008 "%inbuf4 = OpTypeStruct %f32arr\n"
1009 "%inbufptr = OpTypePointer Uniform %inbuf4\n"
1010 "%indata4 = OpVariable %inbufptr Uniform\n"
1012 "%main = OpFunction %void None %voidf\n"
1013 "%label = OpLabel\n"
1014 "%idval = OpLoad %uvec3 %id\n"
1015 "%x = OpCompositeExtract %u32 %idval 0\n"
1016 "%inloc0 = OpAccessChain %f32ptr %indata0 %zero %x\n"
1017 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
1018 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
1019 "%inloc3 = OpAccessChain %f32ptr %indata3 %zero %x\n"
1020 "%inloc4 = OpAccessChain %f32ptr %indata4 %zero %x\n"
1021 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1022 "%inval0 = OpLoad %f32 %inloc0\n"
1023 "%inval1 = OpLoad %f32 %inloc1\n"
1024 "%inval2 = OpLoad %f32 %inloc2\n"
1025 "%inval3 = OpLoad %f32 %inloc3\n"
1026 "%inval4 = OpLoad %f32 %inloc4\n"
1027 "%add0 = OpFAdd %f32 %inval0 %inval1\n"
1028 "%add1 = OpFAdd %f32 %add0 %inval2\n"
1029 "%add2 = OpFAdd %f32 %add1 %inval3\n"
1030 "%add = OpFAdd %f32 %add2 %inval4\n"
1031 " OpStore %outloc %add\n"
1034 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats0)));
1035 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
1036 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
1037 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
1038 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
1039 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1040 spec.numWorkGroups = IVec3(numElements, 1, 1);
1042 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec));
1044 return group.release();
1047 struct SpecConstantTwoIntCase
1049 const char* caseName;
1050 const char* scDefinition0;
1051 const char* scDefinition1;
1052 const char* scResultType;
1053 const char* scOperation;
1054 deInt32 scActualValue0;
1055 deInt32 scActualValue1;
1056 const char* resultOperation;
1057 vector<deInt32> expectedOutput;
1059 SpecConstantTwoIntCase (const char* name,
1060 const char* definition0,
1061 const char* definition1,
1062 const char* resultType,
1063 const char* operation,
1066 const char* resultOp,
1067 const vector<deInt32>& output)
1069 , scDefinition0 (definition0)
1070 , scDefinition1 (definition1)
1071 , scResultType (resultType)
1072 , scOperation (operation)
1073 , scActualValue0 (value0)
1074 , scActualValue1 (value1)
1075 , resultOperation (resultOp)
1076 , expectedOutput (output) {}
1079 tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
1081 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction"));
1082 vector<SpecConstantTwoIntCase> cases;
1083 de::Random rnd (deStringHash(group->getName()));
1084 const int numElements = 100;
1085 vector<deInt32> inputInts (numElements, 0);
1086 vector<deInt32> outputInts1 (numElements, 0);
1087 vector<deInt32> outputInts2 (numElements, 0);
1088 vector<deInt32> outputInts3 (numElements, 0);
1089 vector<deInt32> outputInts4 (numElements, 0);
1090 vector<deInt32> outputInts5 (numElements, 0);
1091 const StringTemplate shaderTemplate (
1092 string(s_ShaderPreamble) +
1094 "OpName %main \"main\"\n"
1095 "OpName %id \"gl_GlobalInvocationID\"\n"
1097 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1098 "OpDecorate %sc_0 SpecId 0\n"
1099 "OpDecorate %sc_1 SpecId 1\n"
1101 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
1103 "%i32ptr = OpTypePointer Uniform %i32\n"
1104 "%i32arr = OpTypeRuntimeArray %i32\n"
1105 "%boolptr = OpTypePointer Uniform %bool\n"
1106 "%boolarr = OpTypeRuntimeArray %bool\n"
1107 "%inbuf = OpTypeStruct %i32arr\n"
1108 "%inbufptr = OpTypePointer Uniform %inbuf\n"
1109 "%indata = OpVariable %inbufptr Uniform\n"
1110 "%outbuf = OpTypeStruct %i32arr\n"
1111 "%outbufptr = OpTypePointer Uniform %outbuf\n"
1112 "%outdata = OpVariable %outbufptr Uniform\n"
1114 "%id = OpVariable %uvec3ptr Input\n"
1115 "%zero = OpConstant %i32 0\n"
1117 "%sc_0 = OpSpecConstant${SC_DEF0}\n"
1118 "%sc_1 = OpSpecConstant${SC_DEF1}\n"
1119 "%sc_final = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n"
1121 "%main = OpFunction %void None %voidf\n"
1122 "%label = OpLabel\n"
1123 "%idval = OpLoad %uvec3 %id\n"
1124 "%x = OpCompositeExtract %u32 %idval 0\n"
1125 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
1126 "%inval = OpLoad %i32 %inloc\n"
1127 "%final = ${GEN_RESULT}\n"
1128 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n"
1129 " OpStore %outloc %final\n"
1131 " OpFunctionEnd\n");
1133 fillRandomScalars(rnd, -65536, 65536, &inputInts[0], numElements);
1135 for (size_t ndx = 0; ndx < numElements; ++ndx)
1137 outputInts1[ndx] = inputInts[ndx] + 42;
1138 outputInts2[ndx] = inputInts[ndx];
1139 outputInts3[ndx] = inputInts[ndx] - 11200;
1140 outputInts4[ndx] = inputInts[ndx] + 1;
1141 outputInts5[ndx] = inputInts[ndx] - 2;
1144 const char addScToInput[] = "OpIAdd %i32 %inval %sc_final";
1145 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_final %inval %zero";
1146 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_final %zero %inval";
1148 cases.push_back(SpecConstantTwoIntCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 62, -20, addScToInput, outputInts1));
1149 cases.push_back(SpecConstantTwoIntCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 100, 58, addScToInput, outputInts1));
1150 cases.push_back(SpecConstantTwoIntCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -2, -21, addScToInput, outputInts1));
1151 cases.push_back(SpecConstantTwoIntCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, -3, addScToInput, outputInts1));
1152 cases.push_back(SpecConstantTwoIntCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 3, addScToInput, outputInts1));
1153 cases.push_back(SpecConstantTwoIntCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 7, -3, addScToInput, outputInts4));
1154 cases.push_back(SpecConstantTwoIntCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 7, -3, addScToInput, outputInts5));
1155 cases.push_back(SpecConstantTwoIntCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 342, 50, addScToInput, outputInts1));
1156 cases.push_back(SpecConstantTwoIntCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 42, 63, addScToInput, outputInts1));
1157 cases.push_back(SpecConstantTwoIntCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 34, 8, addScToInput, outputInts1));
1158 cases.push_back(SpecConstantTwoIntCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 18, 56, addScToInput, outputInts1));
1159 cases.push_back(SpecConstantTwoIntCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 168, 2, addScToInput, outputInts1));
1160 cases.push_back(SpecConstantTwoIntCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", 168, 2, addScToInput, outputInts1));
1161 cases.push_back(SpecConstantTwoIntCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 21, 1, addScToInput, outputInts1));
1162 cases.push_back(SpecConstantTwoIntCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputInts2));
1163 cases.push_back(SpecConstantTwoIntCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputInts2));
1164 cases.push_back(SpecConstantTwoIntCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2));
1165 cases.push_back(SpecConstantTwoIntCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputInts2));
1166 cases.push_back(SpecConstantTwoIntCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputInts2));
1167 cases.push_back(SpecConstantTwoIntCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputInts2));
1168 cases.push_back(SpecConstantTwoIntCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2));
1169 cases.push_back(SpecConstantTwoIntCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputInts2));
1170 cases.push_back(SpecConstantTwoIntCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputInts2));
1171 cases.push_back(SpecConstantTwoIntCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2));
1172 cases.push_back(SpecConstantTwoIntCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2));
1173 cases.push_back(SpecConstantTwoIntCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2));
1174 cases.push_back(SpecConstantTwoIntCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2));
1175 cases.push_back(SpecConstantTwoIntCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -42, 0, addScToInput, outputInts1));
1176 cases.push_back(SpecConstantTwoIntCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -43, 0, addScToInput, outputInts1));
1177 cases.push_back(SpecConstantTwoIntCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputInts2));
1178 cases.push_back(SpecConstantTwoIntCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %zero", 1, 42, addScToInput, outputInts1));
1179 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths.
1181 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1183 map<string, string> specializations;
1184 ComputeShaderSpec spec;
1186 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0;
1187 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1;
1188 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType;
1189 specializations["SC_OP"] = cases[caseNdx].scOperation;
1190 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation;
1192 spec.assembly = shaderTemplate.specialize(specializations);
1193 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
1194 spec.outputs.push_back(BufferSp(new Int32Buffer(cases[caseNdx].expectedOutput)));
1195 spec.numWorkGroups = IVec3(numElements, 1, 1);
1196 spec.specConstants.push_back(cases[caseNdx].scActualValue0);
1197 spec.specConstants.push_back(cases[caseNdx].scActualValue1);
1199 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].caseName, cases[caseNdx].caseName, spec));
1202 ComputeShaderSpec spec;
1205 string(s_ShaderPreamble) +
1207 "OpName %main \"main\"\n"
1208 "OpName %id \"gl_GlobalInvocationID\"\n"
1210 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1211 "OpDecorate %sc_0 SpecId 0\n"
1212 "OpDecorate %sc_1 SpecId 1\n"
1213 "OpDecorate %sc_2 SpecId 2\n"
1215 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
1217 "%ivec3 = OpTypeVector %i32 3\n"
1218 "%i32ptr = OpTypePointer Uniform %i32\n"
1219 "%i32arr = OpTypeRuntimeArray %i32\n"
1220 "%boolptr = OpTypePointer Uniform %bool\n"
1221 "%boolarr = OpTypeRuntimeArray %bool\n"
1222 "%inbuf = OpTypeStruct %i32arr\n"
1223 "%inbufptr = OpTypePointer Uniform %inbuf\n"
1224 "%indata = OpVariable %inbufptr Uniform\n"
1225 "%outbuf = OpTypeStruct %i32arr\n"
1226 "%outbufptr = OpTypePointer Uniform %outbuf\n"
1227 "%outdata = OpVariable %outbufptr Uniform\n"
1229 "%id = OpVariable %uvec3ptr Input\n"
1230 "%zero = OpConstant %i32 0\n"
1231 "%ivec3_0 = OpConstantComposite %ivec3 %zero %zero %zero\n"
1233 "%sc_0 = OpSpecConstant %i32 0\n"
1234 "%sc_1 = OpSpecConstant %i32 0\n"
1235 "%sc_2 = OpSpecConstant %i32 0\n"
1236 "%sc_vec3_0 = OpSpecConstantOp %ivec3 CompositeInsert %sc_0 %ivec3_0 0\n" // (sc_0, 0, 0)
1237 "%sc_vec3_1 = OpSpecConstantOp %ivec3 CompositeInsert %sc_1 %ivec3_0 1\n" // (0, sc_1, 0)
1238 "%sc_vec3_2 = OpSpecConstantOp %ivec3 CompositeInsert %sc_2 %ivec3_0 2\n" // (0, 0, sc_2)
1239 "%sc_vec3_01 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1)
1240 "%sc_vec3_012 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1)
1241 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2
1242 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0
1243 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1
1244 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0)
1245 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n" // (sc_2 - sc_0) * sc_1
1247 "%main = OpFunction %void None %voidf\n"
1248 "%label = OpLabel\n"
1249 "%idval = OpLoad %uvec3 %id\n"
1250 "%x = OpCompositeExtract %u32 %idval 0\n"
1251 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
1252 "%inval = OpLoad %i32 %inloc\n"
1253 "%final = OpIAdd %i32 %inval %sc_final\n"
1254 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n"
1255 " OpStore %outloc %final\n"
1258 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
1259 spec.outputs.push_back(BufferSp(new Int32Buffer(outputInts3)));
1260 spec.numWorkGroups = IVec3(numElements, 1, 1);
1261 spec.specConstants.push_back(123);
1262 spec.specConstants.push_back(56);
1263 spec.specConstants.push_back(-77);
1265 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector_related", "VectorShuffle, CompositeExtract, & CompositeInsert", spec));
1267 return group.release();
1269 tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx)
1271 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
1272 ComputeShaderSpec spec1;
1273 ComputeShaderSpec spec2;
1274 ComputeShaderSpec spec3;
1275 de::Random rnd (deStringHash(group->getName()));
1276 const int numElements = 100;
1277 vector<float> inputFloats (numElements, 0);
1278 vector<float> outputFloats1 (numElements, 0);
1279 vector<float> outputFloats2 (numElements, 0);
1280 vector<float> outputFloats3 (numElements, 0);
1282 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements);
1284 for (size_t ndx = 0; ndx < numElements; ++ndx)
1288 case 0: outputFloats1[ndx] = inputFloats[ndx] + 5.5f; break;
1289 case 1: outputFloats1[ndx] = inputFloats[ndx] + 20.5f; break;
1290 case 2: outputFloats1[ndx] = inputFloats[ndx] + 1.75f; break;
1293 outputFloats2[ndx] = inputFloats[ndx] + 6.5f * 3;
1294 outputFloats3[ndx] = 8.5f - inputFloats[ndx];
1298 string(s_ShaderPreamble) +
1300 "OpSource GLSL 430\n"
1301 "OpName %main \"main\"\n"
1302 "OpName %id \"gl_GlobalInvocationID\"\n"
1304 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1306 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1308 "%id = OpVariable %uvec3ptr Input\n"
1309 "%zero = OpConstant %i32 0\n"
1310 "%three = OpConstant %u32 3\n"
1311 "%constf5p5 = OpConstant %f32 5.5\n"
1312 "%constf20p5 = OpConstant %f32 20.5\n"
1313 "%constf1p75 = OpConstant %f32 1.75\n"
1314 "%constf8p5 = OpConstant %f32 8.5\n"
1315 "%constf6p5 = OpConstant %f32 6.5\n"
1317 "%main = OpFunction %void None %voidf\n"
1318 "%entry = OpLabel\n"
1319 "%idval = OpLoad %uvec3 %id\n"
1320 "%x = OpCompositeExtract %u32 %idval 0\n"
1321 "%selector = OpUMod %u32 %x %three\n"
1322 " OpSelectionMerge %phi None\n"
1323 " OpSwitch %selector %default 0 %case0 1 %case1 2 %case2\n"
1325 // Case 1 before OpPhi.
1326 "%case1 = OpLabel\n"
1329 "%default = OpLabel\n"
1333 "%operand = OpPhi %f32 %constf1p75 %case2 %constf20p5 %case1 %constf5p5 %case0\n" // not in the order of blocks
1334 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1335 "%inval = OpLoad %f32 %inloc\n"
1336 "%add = OpFAdd %f32 %inval %operand\n"
1337 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1338 " OpStore %outloc %add\n"
1341 // Case 0 after OpPhi.
1342 "%case0 = OpLabel\n"
1346 // Case 2 after OpPhi.
1347 "%case2 = OpLabel\n"
1351 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1352 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1)));
1353 spec1.numWorkGroups = IVec3(numElements, 1, 1);
1355 group->addChild(new SpvAsmComputeShaderCase(testCtx, "block", "out-of-order and unreachable blocks for OpPhi", spec1));
1358 string(s_ShaderPreamble) +
1360 "OpName %main \"main\"\n"
1361 "OpName %id \"gl_GlobalInvocationID\"\n"
1363 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1365 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1367 "%id = OpVariable %uvec3ptr Input\n"
1368 "%zero = OpConstant %i32 0\n"
1369 "%one = OpConstant %i32 1\n"
1370 "%three = OpConstant %i32 3\n"
1371 "%constf6p5 = OpConstant %f32 6.5\n"
1373 "%main = OpFunction %void None %voidf\n"
1374 "%entry = OpLabel\n"
1375 "%idval = OpLoad %uvec3 %id\n"
1376 "%x = OpCompositeExtract %u32 %idval 0\n"
1377 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1378 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1379 "%inval = OpLoad %f32 %inloc\n"
1383 "%step = OpPhi %i32 %zero %entry %step_next %phi\n"
1384 "%accum = OpPhi %f32 %inval %entry %accum_next %phi\n"
1385 "%step_next = OpIAdd %i32 %step %one\n"
1386 "%accum_next = OpFAdd %f32 %accum %constf6p5\n"
1387 "%still_loop = OpSLessThan %bool %step %three\n"
1388 " OpLoopMerge %exit %phi None\n"
1389 " OpBranchConditional %still_loop %phi %exit\n"
1392 " OpStore %outloc %accum\n"
1395 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1396 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
1397 spec2.numWorkGroups = IVec3(numElements, 1, 1);
1399 group->addChild(new SpvAsmComputeShaderCase(testCtx, "induction", "The usual way induction variables are handled in LLVM IR", spec2));
1402 string(s_ShaderPreamble) +
1404 "OpName %main \"main\"\n"
1405 "OpName %id \"gl_GlobalInvocationID\"\n"
1407 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1409 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1411 "%f32ptr_f = OpTypePointer Function %f32\n"
1412 "%id = OpVariable %uvec3ptr Input\n"
1413 "%true = OpConstantTrue %bool\n"
1414 "%false = OpConstantFalse %bool\n"
1415 "%zero = OpConstant %i32 0\n"
1416 "%constf8p5 = OpConstant %f32 8.5\n"
1418 "%main = OpFunction %void None %voidf\n"
1419 "%entry = OpLabel\n"
1420 "%b = OpVariable %f32ptr_f Function %constf8p5\n"
1421 "%idval = OpLoad %uvec3 %id\n"
1422 "%x = OpCompositeExtract %u32 %idval 0\n"
1423 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1424 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1425 "%a_init = OpLoad %f32 %inloc\n"
1426 "%b_init = OpLoad %f32 %b\n"
1430 "%still_loop = OpPhi %bool %true %entry %false %phi\n"
1431 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n"
1432 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n"
1433 " OpLoopMerge %exit %phi None\n"
1434 " OpBranchConditional %still_loop %phi %exit\n"
1437 "%sub = OpFSub %f32 %a_next %b_next\n"
1438 " OpStore %outloc %sub\n"
1441 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1442 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3)));
1443 spec3.numWorkGroups = IVec3(numElements, 1, 1);
1445 group->addChild(new SpvAsmComputeShaderCase(testCtx, "swap", "Swap the values of two variables using OpPhi", spec3));
1447 return group.release();
1450 // Assembly code used for testing block order is based on GLSL source code:
1454 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1455 // float elements[];
1457 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1458 // float elements[];
1462 // uint x = gl_GlobalInvocationID.x;
1463 // output_data.elements[x] = input_data.elements[x];
1464 // if (x > uint(50)) {
1465 // switch (x % uint(3)) {
1466 // case 0: output_data.elements[x] += 1.5f; break;
1467 // case 1: output_data.elements[x] += 42.f; break;
1468 // case 2: output_data.elements[x] -= 27.f; break;
1472 // output_data.elements[x] = -input_data.elements[x];
1475 tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
1477 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "block_order", "Test block orders"));
1478 ComputeShaderSpec spec;
1479 de::Random rnd (deStringHash(group->getName()));
1480 const int numElements = 100;
1481 vector<float> inputFloats (numElements, 0);
1482 vector<float> outputFloats (numElements, 0);
1484 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1486 for (size_t ndx = 0; ndx <= 50; ++ndx)
1487 outputFloats[ndx] = -inputFloats[ndx];
1489 for (size_t ndx = 51; ndx < numElements; ++ndx)
1493 case 0: outputFloats[ndx] = inputFloats[ndx] + 1.5f; break;
1494 case 1: outputFloats[ndx] = inputFloats[ndx] + 42.f; break;
1495 case 2: outputFloats[ndx] = inputFloats[ndx] - 27.f; break;
1501 string(s_ShaderPreamble) +
1503 "OpSource GLSL 430\n"
1504 "OpName %main \"main\"\n"
1505 "OpName %id \"gl_GlobalInvocationID\"\n"
1507 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1509 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
1511 "%u32ptr = OpTypePointer Function %u32\n"
1512 "%u32ptr_input = OpTypePointer Input %u32\n"
1514 + string(s_InputOutputBuffer) +
1516 "%id = OpVariable %uvec3ptr Input\n"
1517 "%zero = OpConstant %i32 0\n"
1518 "%const3 = OpConstant %u32 3\n"
1519 "%const50 = OpConstant %u32 50\n"
1520 "%constf1p5 = OpConstant %f32 1.5\n"
1521 "%constf27 = OpConstant %f32 27.0\n"
1522 "%constf42 = OpConstant %f32 42.0\n"
1524 "%main = OpFunction %void None %voidf\n"
1527 "%entry = OpLabel\n"
1529 // Create a temporary variable to hold the value of gl_GlobalInvocationID.x.
1530 "%xvar = OpVariable %u32ptr Function\n"
1531 "%xptr = OpAccessChain %u32ptr_input %id %zero\n"
1532 "%x = OpLoad %u32 %xptr\n"
1533 " OpStore %xvar %x\n"
1535 "%cmp = OpUGreaterThan %bool %x %const50\n"
1536 " OpSelectionMerge %if_merge None\n"
1537 " OpBranchConditional %cmp %if_true %if_false\n"
1539 // Merge block for switch-statement: placed at the beginning.
1540 "%switch_merge = OpLabel\n"
1541 " OpBranch %if_merge\n"
1543 // Case 1 for switch-statement.
1544 "%case1 = OpLabel\n"
1545 "%x_1 = OpLoad %u32 %xvar\n"
1546 "%inloc_1 = OpAccessChain %f32ptr %indata %zero %x_1\n"
1547 "%inval_1 = OpLoad %f32 %inloc_1\n"
1548 "%addf42 = OpFAdd %f32 %inval_1 %constf42\n"
1549 "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
1550 " OpStore %outloc_1 %addf42\n"
1551 " OpBranch %switch_merge\n"
1553 // False branch for if-statement: placed in the middle of switch cases and before true branch.
1554 "%if_false = OpLabel\n"
1555 "%x_f = OpLoad %u32 %xvar\n"
1556 "%inloc_f = OpAccessChain %f32ptr %indata %zero %x_f\n"
1557 "%inval_f = OpLoad %f32 %inloc_f\n"
1558 "%negate = OpFNegate %f32 %inval_f\n"
1559 "%outloc_f = OpAccessChain %f32ptr %outdata %zero %x_f\n"
1560 " OpStore %outloc_f %negate\n"
1561 " OpBranch %if_merge\n"
1563 // Merge block for if-statement: placed in the middle of true and false branch.
1564 "%if_merge = OpLabel\n"
1567 // True branch for if-statement: placed in the middle of swtich cases and after the false branch.
1568 "%if_true = OpLabel\n"
1569 "%xval_t = OpLoad %u32 %xvar\n"
1570 "%mod = OpUMod %u32 %xval_t %const3\n"
1571 " OpSelectionMerge %switch_merge None\n"
1572 " OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n"
1574 // Case 2 for switch-statement.
1575 "%case2 = OpLabel\n"
1576 "%x_2 = OpLoad %u32 %xvar\n"
1577 "%inloc_2 = OpAccessChain %f32ptr %indata %zero %x_2\n"
1578 "%inval_2 = OpLoad %f32 %inloc_2\n"
1579 "%subf27 = OpFSub %f32 %inval_2 %constf27\n"
1580 "%outloc_2 = OpAccessChain %f32ptr %outdata %zero %x_2\n"
1581 " OpStore %outloc_2 %subf27\n"
1582 " OpBranch %switch_merge\n"
1584 // Default case for switch-statement: placed in the middle of normal cases.
1585 "%default = OpLabel\n"
1586 " OpBranch %switch_merge\n"
1588 // Case 0 for switch-statement: out of order.
1589 "%case0 = OpLabel\n"
1590 "%x_0 = OpLoad %u32 %xvar\n"
1591 "%inloc_0 = OpAccessChain %f32ptr %indata %zero %x_0\n"
1592 "%inval_0 = OpLoad %f32 %inloc_0\n"
1593 "%addf1p5 = OpFAdd %f32 %inval_0 %constf1p5\n"
1594 "%outloc_0 = OpAccessChain %f32ptr %outdata %zero %x_0\n"
1595 " OpStore %outloc_0 %addf1p5\n"
1596 " OpBranch %switch_merge\n"
1599 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1600 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1601 spec.numWorkGroups = IVec3(numElements, 1, 1);
1603 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec));
1605 return group.release();
1608 tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx)
1610 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "multiple_shaders", "Test multiple shaders in the same module"));
1611 ComputeShaderSpec spec1;
1612 ComputeShaderSpec spec2;
1613 de::Random rnd (deStringHash(group->getName()));
1614 const int numElements = 100;
1615 vector<float> inputFloats (numElements, 0);
1616 vector<float> outputFloats1 (numElements, 0);
1617 vector<float> outputFloats2 (numElements, 0);
1618 fillRandomScalars(rnd, -500.f, 500.f, &inputFloats[0], numElements);
1620 for (size_t ndx = 0; ndx < numElements; ++ndx)
1622 outputFloats1[ndx] = inputFloats[ndx] + inputFloats[ndx];
1623 outputFloats2[ndx] = -inputFloats[ndx];
1626 const string assembly =
1627 "OpCapability Shader\n"
1628 "OpMemoryModel Logical GLSL450\n"
1629 "OpEntryPoint GLCompute %comp_main1 \"entrypoint1\" %id\n"
1630 "OpEntryPoint GLCompute %comp_main2 \"entrypoint2\" %id\n"
1631 // A module cannot have two OpEntryPoint instructions with the same Execution Model and the same Name string.
1632 "OpEntryPoint Vertex %vert_main \"entrypoint2\" %vert_builtins %vertexID %instanceID\n"
1633 "OpExecutionMode %main LocalSize 1 1 1\n";
1635 "OpName %comp_main1 \"entrypoint1\"\n"
1636 "OpName %comp_main2 \"entrypoint2\"\n"
1637 "OpName %vert_main \"entrypoint2\"\n"
1638 "OpName %id \"gl_GlobalInvocationID\"\n"
1639 "OpName %vert_builtin_st \"gl_PerVertex\"\n"
1640 "OpName %vertexID \"gl_VertexID\"\n"
1641 "OpName %instanceID \"gl_InstanceID\"\n"
1642 "OpMemberName %vert_builtin_st 0 \"gl_Position\"\n"
1643 "OpMemberName %vert_builtin_st 1 \"gl_PointSize\"\n"
1644 "OpMemberName %vert_builtin_st 2 \"gl_ClipDistance\"\n"
1646 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1647 "OpDecorate %vertexID BuiltIn VertexId\n"
1648 "OpDecorate %instanceID BuiltIn InstanceId\n"
1649 "OpDecorate %vert_builtin_st Block\n"
1650 "OpMemberDecorate %vert_builtin_st 0 BuiltIn Position\n"
1651 "OpMemberDecorate %vert_builtin_st 1 BuiltIn PointSize\n"
1652 "OpMemberDecorate %vert_builtin_st 2 BuiltIn ClipDistance\n"
1654 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1656 "%i32ptr = OpTypePointer Input %i32\n"
1657 "%vec4 = OpTypeVector %f32 4\n"
1658 "%vec4ptr = OpTypePointer Output %vec4\n"
1659 "%f32arr1 = OpTypeArray %f32 %one\n"
1660 "%vert_builtin_st = OpTypeStruct %vec4 %f32 %f32arr1\n"
1661 "%vert_builtin_st_ptr = OpTypePointer Output %vert_builtin_st\n"
1662 "%vert_builtins = OpVariable %vert_builtin_st_ptr Output\n"
1664 "%id = OpVariable %uvec3ptr Input\n"
1665 "%vertexID = OpVariable %i32ptr Input\n"
1666 "%instanceID = OpVariable %i32ptr Input\n"
1667 "%zero = OpConstant %i32 0\n"
1668 "%one = OpConstant %u32 1\n"
1669 "%c_f32_1 = OpConstant %f32 1\n"
1670 "%c_vec4_1 = OpConstantComposite %vec4 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
1672 // gl_Position = vec4(1.);
1673 "%vert_main = OpFunction %void None %voidf\n"
1674 "%vert_entry = OpLabel\n"
1675 "%position = OpAccessChain %vec4ptr %vert_builtins %zero\n"
1676 " OpStore %position %c_vec4_1\n"
1681 "%comp_main1 = OpFunction %void None %voidf\n"
1682 "%comp1_entry = OpLabel\n"
1683 "%idval1 = OpLoad %uvec3 %id\n"
1684 "%x1 = OpCompositeExtract %u32 %idval1 0\n"
1685 "%inloc1 = OpAccessChain %f32ptr %indata %zero %x1\n"
1686 "%inval1 = OpLoad %f32 %inloc1\n"
1687 "%add = OpFAdd %f32 %inval1 %inval1\n"
1688 "%outloc1 = OpAccessChain %f32ptr %outdata %zero %x1\n"
1689 " OpStore %outloc1 %add\n"
1694 "%comp_main2 = OpFunction %void None %voidf\n"
1695 "%comp2_entry = OpLabel\n"
1696 "%idval2 = OpLoad %uvec3 %id\n"
1697 "%x2 = OpCompositeExtract %u32 %idval2 0\n"
1698 "%inloc2 = OpAccessChain %f32ptr %indata %zero %x2\n"
1699 "%inval2 = OpLoad %f32 %inloc2\n"
1700 "%neg = OpFNegate %f32 %inval2\n"
1701 "%outloc2 = OpAccessChain %f32ptr %outdata %zero %x2\n"
1702 " OpStore %outloc2 %neg\n"
1706 spec1.assembly = assembly;
1707 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1708 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1)));
1709 spec1.numWorkGroups = IVec3(numElements, 1, 1);
1710 spec1.entryPoint = "entrypoint1";
1712 spec2.assembly = assembly;
1713 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1714 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
1715 spec2.numWorkGroups = IVec3(numElements, 1, 1);
1716 spec2.entryPoint = "entrypoint2";
1718 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader1", "multiple shaders in the same module", spec1));
1719 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader2", "multiple shaders in the same module", spec2));
1721 return group.release();
1724 inline std::string makeLongUTF8String (size_t num4ByteChars)
1726 // An example of a longest valid UTF-8 character. Be explicit about the
1727 // character type because Microsoft compilers can otherwise interpret the
1728 // character string as being over wide (16-bit) characters. Ideally, we
1729 // would just use a C++11 UTF-8 string literal, but we want to support older
1730 // Microsoft compilers.
1731 const std::basic_string<char> earthAfrica("\xF0\x9F\x8C\x8D");
1732 std::string longString;
1733 longString.reserve(num4ByteChars * 4);
1734 for (size_t count = 0; count < num4ByteChars; count++)
1736 longString += earthAfrica;
1741 tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
1743 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction"));
1744 vector<CaseParameter> cases;
1745 de::Random rnd (deStringHash(group->getName()));
1746 const int numElements = 100;
1747 vector<float> positiveFloats (numElements, 0);
1748 vector<float> negativeFloats (numElements, 0);
1749 const StringTemplate shaderTemplate (
1750 "OpCapability Shader\n"
1751 "OpMemoryModel Logical GLSL450\n"
1753 "OpEntryPoint GLCompute %main \"main\" %id\n"
1754 "OpExecutionMode %main LocalSize 1 1 1\n"
1758 "OpName %main \"main\"\n"
1759 "OpName %id \"gl_GlobalInvocationID\"\n"
1761 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1763 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1765 "%id = OpVariable %uvec3ptr Input\n"
1766 "%zero = OpConstant %i32 0\n"
1768 "%main = OpFunction %void None %voidf\n"
1769 "%label = OpLabel\n"
1770 "%idval = OpLoad %uvec3 %id\n"
1771 "%x = OpCompositeExtract %u32 %idval 0\n"
1772 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1773 "%inval = OpLoad %f32 %inloc\n"
1774 "%neg = OpFNegate %f32 %inval\n"
1775 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1776 " OpStore %outloc %neg\n"
1778 " OpFunctionEnd\n");
1780 cases.push_back(CaseParameter("unknown_source", "OpSource Unknown 0"));
1781 cases.push_back(CaseParameter("wrong_source", "OpSource OpenCL_C 210"));
1782 cases.push_back(CaseParameter("normal_filename", "%fname = OpString \"filename\"\n"
1783 "OpSource GLSL 430 %fname"));
1784 cases.push_back(CaseParameter("empty_filename", "%fname = OpString \"\"\n"
1785 "OpSource GLSL 430 %fname"));
1786 cases.push_back(CaseParameter("normal_source_code", "%fname = OpString \"filename\"\n"
1787 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\""));
1788 cases.push_back(CaseParameter("empty_source_code", "%fname = OpString \"filename\"\n"
1789 "OpSource GLSL 430 %fname \"\""));
1790 cases.push_back(CaseParameter("long_source_code", "%fname = OpString \"filename\"\n"
1791 "OpSource GLSL 430 %fname \"" + makeLongUTF8String(65530) + "ccc\"")); // word count: 65535
1792 cases.push_back(CaseParameter("utf8_source_code", "%fname = OpString \"filename\"\n"
1793 "OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol
1794 cases.push_back(CaseParameter("normal_sourcecontinued", "%fname = OpString \"filename\"\n"
1795 "OpSource GLSL 430 %fname \"#version 430\nvo\"\n"
1796 "OpSourceContinued \"id main() {}\""));
1797 cases.push_back(CaseParameter("empty_sourcecontinued", "%fname = OpString \"filename\"\n"
1798 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
1799 "OpSourceContinued \"\""));
1800 cases.push_back(CaseParameter("long_sourcecontinued", "%fname = OpString \"filename\"\n"
1801 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
1802 "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\"")); // word count: 65535
1803 cases.push_back(CaseParameter("utf8_sourcecontinued", "%fname = OpString \"filename\"\n"
1804 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
1805 "OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol
1806 cases.push_back(CaseParameter("multi_sourcecontinued", "%fname = OpString \"filename\"\n"
1807 "OpSource GLSL 430 %fname \"#version 430\n\"\n"
1808 "OpSourceContinued \"void\"\n"
1809 "OpSourceContinued \"main()\"\n"
1810 "OpSourceContinued \"{}\""));
1811 cases.push_back(CaseParameter("empty_source_before_sourcecontinued", "%fname = OpString \"filename\"\n"
1812 "OpSource GLSL 430 %fname \"\"\n"
1813 "OpSourceContinued \"#version 430\nvoid main() {}\""));
1815 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1817 for (size_t ndx = 0; ndx < numElements; ++ndx)
1818 negativeFloats[ndx] = -positiveFloats[ndx];
1820 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1822 map<string, string> specializations;
1823 ComputeShaderSpec spec;
1825 specializations["SOURCE"] = cases[caseNdx].param;
1826 spec.assembly = shaderTemplate.specialize(specializations);
1827 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1828 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1829 spec.numWorkGroups = IVec3(numElements, 1, 1);
1831 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1834 return group.release();
1837 tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx)
1839 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsourceextension", "Tests the OpSource instruction"));
1840 vector<CaseParameter> cases;
1841 de::Random rnd (deStringHash(group->getName()));
1842 const int numElements = 100;
1843 vector<float> inputFloats (numElements, 0);
1844 vector<float> outputFloats (numElements, 0);
1845 const StringTemplate shaderTemplate (
1846 string(s_ShaderPreamble) +
1848 "OpSourceExtension \"${EXTENSION}\"\n"
1850 "OpName %main \"main\"\n"
1851 "OpName %id \"gl_GlobalInvocationID\"\n"
1853 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1855 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1857 "%id = OpVariable %uvec3ptr Input\n"
1858 "%zero = OpConstant %i32 0\n"
1860 "%main = OpFunction %void None %voidf\n"
1861 "%label = OpLabel\n"
1862 "%idval = OpLoad %uvec3 %id\n"
1863 "%x = OpCompositeExtract %u32 %idval 0\n"
1864 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1865 "%inval = OpLoad %f32 %inloc\n"
1866 "%neg = OpFNegate %f32 %inval\n"
1867 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1868 " OpStore %outloc %neg\n"
1870 " OpFunctionEnd\n");
1872 cases.push_back(CaseParameter("empty_extension", ""));
1873 cases.push_back(CaseParameter("real_extension", "GL_ARB_texture_rectangle"));
1874 cases.push_back(CaseParameter("fake_extension", "GL_ARB_im_the_ultimate_extension"));
1875 cases.push_back(CaseParameter("utf8_extension", "GL_ARB_\xE2\x98\x82\xE2\x98\x85"));
1876 cases.push_back(CaseParameter("long_extension", makeLongUTF8String(65533) + "ccc")); // word count: 65535
1878 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
1880 for (size_t ndx = 0; ndx < numElements; ++ndx)
1881 outputFloats[ndx] = -inputFloats[ndx];
1883 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1885 map<string, string> specializations;
1886 ComputeShaderSpec spec;
1888 specializations["EXTENSION"] = cases[caseNdx].param;
1889 spec.assembly = shaderTemplate.specialize(specializations);
1890 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1891 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1892 spec.numWorkGroups = IVec3(numElements, 1, 1);
1894 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1897 return group.release();
1900 // Checks that a compute shader can generate a constant null value of various types, without exercising a computation on it.
1901 tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx)
1903 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnull", "Tests the OpConstantNull instruction"));
1904 vector<CaseParameter> cases;
1905 de::Random rnd (deStringHash(group->getName()));
1906 const int numElements = 100;
1907 vector<float> positiveFloats (numElements, 0);
1908 vector<float> negativeFloats (numElements, 0);
1909 const StringTemplate shaderTemplate (
1910 string(s_ShaderPreamble) +
1912 "OpSource GLSL 430\n"
1913 "OpName %main \"main\"\n"
1914 "OpName %id \"gl_GlobalInvocationID\"\n"
1916 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1918 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1921 "%null = OpConstantNull %type\n"
1923 "%id = OpVariable %uvec3ptr Input\n"
1924 "%zero = OpConstant %i32 0\n"
1926 "%main = OpFunction %void None %voidf\n"
1927 "%label = OpLabel\n"
1928 "%idval = OpLoad %uvec3 %id\n"
1929 "%x = OpCompositeExtract %u32 %idval 0\n"
1930 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1931 "%inval = OpLoad %f32 %inloc\n"
1932 "%neg = OpFNegate %f32 %inval\n"
1933 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1934 " OpStore %outloc %neg\n"
1936 " OpFunctionEnd\n");
1938 cases.push_back(CaseParameter("bool", "%type = OpTypeBool"));
1939 cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1"));
1940 cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0"));
1941 cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32"));
1942 cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4"));
1943 cases.push_back(CaseParameter("vec3bool", "%type = OpTypeVector %bool 3"));
1944 cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2"));
1945 cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %uvec3 3"));
1946 cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n"
1947 "%type = OpTypeArray %i32 %100"));
1948 cases.push_back(CaseParameter("runtimearray", "%type = OpTypeRuntimeArray %f32"));
1949 cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32"));
1950 cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32"));
1952 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1954 for (size_t ndx = 0; ndx < numElements; ++ndx)
1955 negativeFloats[ndx] = -positiveFloats[ndx];
1957 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1959 map<string, string> specializations;
1960 ComputeShaderSpec spec;
1962 specializations["TYPE"] = cases[caseNdx].param;
1963 spec.assembly = shaderTemplate.specialize(specializations);
1964 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1965 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1966 spec.numWorkGroups = IVec3(numElements, 1, 1);
1968 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
1971 return group.release();
1974 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
1975 tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx)
1977 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "Tests the OpConstantComposite instruction"));
1978 vector<CaseParameter> cases;
1979 de::Random rnd (deStringHash(group->getName()));
1980 const int numElements = 100;
1981 vector<float> positiveFloats (numElements, 0);
1982 vector<float> negativeFloats (numElements, 0);
1983 const StringTemplate shaderTemplate (
1984 string(s_ShaderPreamble) +
1986 "OpSource GLSL 430\n"
1987 "OpName %main \"main\"\n"
1988 "OpName %id \"gl_GlobalInvocationID\"\n"
1990 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1992 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
1994 "%id = OpVariable %uvec3ptr Input\n"
1995 "%zero = OpConstant %i32 0\n"
1999 "%main = OpFunction %void None %voidf\n"
2000 "%label = OpLabel\n"
2001 "%idval = OpLoad %uvec3 %id\n"
2002 "%x = OpCompositeExtract %u32 %idval 0\n"
2003 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2004 "%inval = OpLoad %f32 %inloc\n"
2005 "%neg = OpFNegate %f32 %inval\n"
2006 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2007 " OpStore %outloc %neg\n"
2009 " OpFunctionEnd\n");
2011 cases.push_back(CaseParameter("vector", "%five = OpConstant %u32 5\n"
2012 "%const = OpConstantComposite %uvec3 %five %zero %five"));
2013 cases.push_back(CaseParameter("matrix", "%m3uvec3 = OpTypeMatrix %uvec3 3\n"
2014 "%ten = OpConstant %u32 10\n"
2015 "%vec = OpConstantComposite %uvec3 %ten %zero %ten\n"
2016 "%mat = OpConstantComposite %m3uvec3 %vec %vec %vec"));
2017 cases.push_back(CaseParameter("struct", "%m2vec3 = OpTypeMatrix %uvec3 2\n"
2018 "%struct = OpTypeStruct %u32 %f32 %uvec3 %m2vec3\n"
2019 "%one = OpConstant %u32 1\n"
2020 "%point5 = OpConstant %f32 0.5\n"
2021 "%vec = OpConstantComposite %uvec3 %one %one %zero\n"
2022 "%mat = OpConstantComposite %m2vec3 %vec %vec\n"
2023 "%const = OpConstantComposite %struct %one %point5 %vec %mat"));
2024 cases.push_back(CaseParameter("nested_struct", "%st1 = OpTypeStruct %u32 %f32\n"
2025 "%st2 = OpTypeStruct %i32 %i32\n"
2026 "%struct = OpTypeStruct %st1 %st2\n"
2027 "%point5 = OpConstant %f32 0.5\n"
2028 "%one = OpConstant %u32 1\n"
2029 "%ten = OpConstant %i32 10\n"
2030 "%st1val = OpConstantComposite %st1 %one %point5\n"
2031 "%st2val = OpConstantComposite %st2 %ten %ten\n"
2032 "%const = OpConstantComposite %struct %st1val %st2val"));
2034 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2036 for (size_t ndx = 0; ndx < numElements; ++ndx)
2037 negativeFloats[ndx] = -positiveFloats[ndx];
2039 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2041 map<string, string> specializations;
2042 ComputeShaderSpec spec;
2044 specializations["CONSTANT"] = cases[caseNdx].param;
2045 spec.assembly = shaderTemplate.specialize(specializations);
2046 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
2047 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
2048 spec.numWorkGroups = IVec3(numElements, 1, 1);
2050 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2053 return group.release();
2056 // Creates a floating point number with the given exponent, and significand
2057 // bits set. It can only create normalized numbers. Only the least significant
2058 // 24 bits of the significand will be examined. The final bit of the
2059 // significand will also be ignored. This allows alignment to be written
2060 // similarly to C99 hex-floats.
2061 // For example if you wanted to write 0x1.7f34p-12 you would call
2062 // constructNormalizedFloat(-12, 0x7f3400)
2063 float constructNormalizedFloat (deInt32 exponent, deUint32 significand)
2067 for (deInt32 idx = 0; idx < 23; ++idx)
2069 f += ((significand & 0x800000) == 0) ? 0.f : std::ldexp(1.0f, -idx);
2073 return std::ldexp(f, exponent);
2076 // Compare instruction for the OpQuantizeF16 compute exact case.
2077 // Returns true if the output is what is expected from the test case.
2078 bool compareOpQuantizeF16ComputeExactCase (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs)
2080 if (outputAllocs.size() != 1)
2083 // We really just need this for size because we cannot compare Nans.
2084 const BufferSp& expectedOutput = expectedOutputs[0];
2085 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
2087 if (expectedOutput->getNumBytes() != 4*sizeof(float)) {
2091 if (*outputAsFloat != constructNormalizedFloat(8, 0x304000) &&
2092 *outputAsFloat != constructNormalizedFloat(8, 0x300000)) {
2096 if (*outputAsFloat != -constructNormalizedFloat(-7, 0x600000) &&
2097 *outputAsFloat != -constructNormalizedFloat(-7, 0x604000)) {
2101 if (*outputAsFloat != constructNormalizedFloat(2, 0x01C000) &&
2102 *outputAsFloat != constructNormalizedFloat(2, 0x020000)) {
2106 if (*outputAsFloat != constructNormalizedFloat(1, 0xFFC000) &&
2107 *outputAsFloat != constructNormalizedFloat(2, 0x000000)) {
2114 // Checks that every output from a test-case is a float NaN.
2115 bool compareNan (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs)
2117 if (outputAllocs.size() != 1)
2120 // We really just need this for size because we cannot compare Nans.
2121 const BufferSp& expectedOutput = expectedOutputs[0];
2122 const float* output_as_float = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
2124 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx)
2126 if (!isnan(output_as_float[idx]))
2135 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
2136 tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx)
2138 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opquantize", "Tests the OpQuantizeToF16 instruction"));
2140 const std::string shader (
2141 string(s_ShaderPreamble) +
2143 "OpSource GLSL 430\n"
2144 "OpName %main \"main\"\n"
2145 "OpName %id \"gl_GlobalInvocationID\"\n"
2147 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2149 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2151 "%id = OpVariable %uvec3ptr Input\n"
2152 "%zero = OpConstant %i32 0\n"
2154 "%main = OpFunction %void None %voidf\n"
2155 "%label = OpLabel\n"
2156 "%idval = OpLoad %uvec3 %id\n"
2157 "%x = OpCompositeExtract %u32 %idval 0\n"
2158 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2159 "%inval = OpLoad %f32 %inloc\n"
2160 "%quant = OpQuantizeToF16 %f32 %inval\n"
2161 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2162 " OpStore %outloc %quant\n"
2164 " OpFunctionEnd\n");
2167 ComputeShaderSpec spec;
2168 const deUint32 numElements = 100;
2169 vector<float> infinities;
2170 vector<float> results;
2172 infinities.reserve(numElements);
2173 results.reserve(numElements);
2175 for (size_t idx = 0; idx < numElements; ++idx)
2180 infinities.push_back(std::numeric_limits<float>::infinity());
2181 results.push_back(std::numeric_limits<float>::infinity());
2184 infinities.push_back(-std::numeric_limits<float>::infinity());
2185 results.push_back(-std::numeric_limits<float>::infinity());
2188 infinities.push_back(std::ldexp(1.0f, 16));
2189 results.push_back(std::numeric_limits<float>::infinity());
2192 infinities.push_back(std::ldexp(-1.0f, 32));
2193 results.push_back(-std::numeric_limits<float>::infinity());
2198 spec.inputs.push_back(BufferSp(new Float32Buffer(infinities)));
2199 spec.outputs.push_back(BufferSp(new Float32Buffer(results)));
2200 spec.numWorkGroups = IVec3(numElements, 1, 1);
2202 group->addChild(new SpvAsmComputeShaderCase(
2203 testCtx, "infinities", "Check that infinities propagated and created", spec));
2207 ComputeShaderSpec spec;
2209 const deUint32 numElements = 100;
2211 nans.reserve(numElements);
2213 for (size_t idx = 0; idx < numElements; ++idx)
2217 nans.push_back(std::numeric_limits<float>::quiet_NaN());
2221 nans.push_back(-std::numeric_limits<float>::quiet_NaN());
2225 spec.inputs.push_back(BufferSp(new Float32Buffer(nans)));
2226 spec.outputs.push_back(BufferSp(new Float32Buffer(nans)));
2227 spec.numWorkGroups = IVec3(numElements, 1, 1);
2228 spec.verifyIO = &compareNan;
2230 group->addChild(new SpvAsmComputeShaderCase(
2231 testCtx, "propagated_nans", "Check that nans are propagated", spec));
2235 ComputeShaderSpec spec;
2236 vector<float> small;
2237 vector<float> zeros;
2238 const deUint32 numElements = 100;
2240 small.reserve(numElements);
2241 zeros.reserve(numElements);
2243 for (size_t idx = 0; idx < numElements; ++idx)
2248 small.push_back(0.f);
2249 zeros.push_back(0.f);
2252 small.push_back(-0.f);
2253 zeros.push_back(-0.f);
2256 small.push_back(std::ldexp(1.0f, -16));
2257 zeros.push_back(0.f);
2260 small.push_back(std::ldexp(-1.0f, -32));
2261 zeros.push_back(-0.f);
2264 small.push_back(std::ldexp(1.0f, -127));
2265 zeros.push_back(0.f);
2268 small.push_back(-std::ldexp(1.0f, -128));
2269 zeros.push_back(-0.f);
2274 spec.inputs.push_back(BufferSp(new Float32Buffer(small)));
2275 spec.outputs.push_back(BufferSp(new Float32Buffer(zeros)));
2276 spec.numWorkGroups = IVec3(numElements, 1, 1);
2278 group->addChild(new SpvAsmComputeShaderCase(
2279 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec));
2283 ComputeShaderSpec spec;
2284 vector<float> exact;
2285 const deUint32 numElements = 200;
2287 exact.reserve(numElements);
2289 for (size_t idx = 0; idx < numElements; ++idx)
2290 exact.push_back(static_cast<float>(idx - 100));
2292 spec.inputs.push_back(BufferSp(new Float32Buffer(exact)));
2293 spec.outputs.push_back(BufferSp(new Float32Buffer(exact)));
2294 spec.numWorkGroups = IVec3(numElements, 1, 1);
2296 group->addChild(new SpvAsmComputeShaderCase(
2297 testCtx, "exact", "Check that values exactly preserved where appropriate", spec));
2301 ComputeShaderSpec spec;
2302 vector<float> inputs;
2303 const deUint32 numElements = 4;
2305 inputs.push_back(constructNormalizedFloat(8, 0x300300));
2306 inputs.push_back(-constructNormalizedFloat(-7, 0x600800));
2307 inputs.push_back(constructNormalizedFloat(2, 0x01E000));
2308 inputs.push_back(constructNormalizedFloat(1, 0xFFE000));
2310 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase;
2311 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2312 spec.outputs.push_back(BufferSp(new Float32Buffer(inputs)));
2313 spec.numWorkGroups = IVec3(numElements, 1, 1);
2315 group->addChild(new SpvAsmComputeShaderCase(
2316 testCtx, "rounded", "Check that are rounded when needed", spec));
2319 return group.release();
2322 // Performs a bitwise copy of source to the destination type Dest.
2323 template <typename Dest, typename Src>
2324 Dest bitwiseCast(Src source)
2327 DE_STATIC_ASSERT(sizeof(source) == sizeof(dest));
2328 deMemcpy(&dest, &source, sizeof(dest));
2332 tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& testCtx)
2334 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop_opquantize", "Tests the OpQuantizeToF16 opcode for the OpSpecConstantOp instruction"));
2335 de::Random rnd (deStringHash(group->getName()));
2337 const std::string shader (
2338 string(s_ShaderPreamble) +
2340 "OpName %main \"main\"\n"
2341 "OpName %id \"gl_GlobalInvocationID\"\n"
2343 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2345 "OpDecorate %sc_0 SpecId 0\n"
2346 "OpDecorate %sc_1 SpecId 1\n"
2347 "OpDecorate %sc_2 SpecId 2\n"
2348 "OpDecorate %sc_3 SpecId 3\n"
2349 "OpDecorate %sc_4 SpecId 4\n"
2350 "OpDecorate %sc_5 SpecId 5\n"
2352 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2354 "%id = OpVariable %uvec3ptr Input\n"
2355 "%zero = OpConstant %i32 0\n"
2356 "%c_u32_6 = OpConstant %u32 6\n"
2358 "%sc_0 = OpSpecConstant %f32 0.\n"
2359 "%sc_1 = OpSpecConstant %f32 0.\n"
2360 "%sc_2 = OpSpecConstant %f32 0.\n"
2361 "%sc_3 = OpSpecConstant %f32 0.\n"
2362 "%sc_4 = OpSpecConstant %f32 0.\n"
2363 "%sc_5 = OpSpecConstant %f32 0.\n"
2365 "%sc_0_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_0\n"
2366 "%sc_1_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_1\n"
2367 "%sc_2_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_2\n"
2368 "%sc_3_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_3\n"
2369 "%sc_4_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_4\n"
2370 "%sc_5_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_5\n"
2372 "%main = OpFunction %void None %voidf\n"
2373 "%label = OpLabel\n"
2374 "%idval = OpLoad %uvec3 %id\n"
2375 "%x = OpCompositeExtract %u32 %idval 0\n"
2376 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2377 "%selector = OpUMod %u32 %x %c_u32_6\n"
2378 " OpSelectionMerge %exit None\n"
2379 " OpSwitch %selector %exit 0 %case0 1 %case1 2 %case2 3 %case3 4 %case4 5 %case5\n"
2381 "%case0 = OpLabel\n"
2382 " OpStore %outloc %sc_0_quant\n"
2385 "%case1 = OpLabel\n"
2386 " OpStore %outloc %sc_1_quant\n"
2389 "%case2 = OpLabel\n"
2390 " OpStore %outloc %sc_2_quant\n"
2393 "%case3 = OpLabel\n"
2394 " OpStore %outloc %sc_3_quant\n"
2397 "%case4 = OpLabel\n"
2398 " OpStore %outloc %sc_4_quant\n"
2401 "%case5 = OpLabel\n"
2402 " OpStore %outloc %sc_5_quant\n"
2408 " OpFunctionEnd\n");
2411 ComputeShaderSpec spec;
2412 const deUint8 numCases = 4;
2413 vector<float> inputs (numCases, 0.f);
2414 vector<float> outputs;
2416 spec.numWorkGroups = IVec3(numCases, 1, 1);
2418 spec.specConstants.push_back(bitwiseCast<deUint32>(std::numeric_limits<float>::infinity()));
2419 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::numeric_limits<float>::infinity()));
2420 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, 16)));
2421 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, 32)));
2423 outputs.push_back(std::numeric_limits<float>::infinity());
2424 outputs.push_back(-std::numeric_limits<float>::infinity());
2425 outputs.push_back(std::numeric_limits<float>::infinity());
2426 outputs.push_back(-std::numeric_limits<float>::infinity());
2428 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2429 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2431 group->addChild(new SpvAsmComputeShaderCase(
2432 testCtx, "infinities", "Check that infinities propagated and created", spec));
2436 ComputeShaderSpec spec;
2437 const deUint8 numCases = 2;
2438 vector<float> inputs (numCases, 0.f);
2439 vector<float> outputs;
2441 spec.numWorkGroups = IVec3(numCases, 1, 1);
2442 spec.verifyIO = &compareNan;
2444 outputs.push_back(std::numeric_limits<float>::quiet_NaN());
2445 outputs.push_back(-std::numeric_limits<float>::quiet_NaN());
2447 for (deUint8 idx = 0; idx < numCases; ++idx)
2448 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
2450 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2451 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2453 group->addChild(new SpvAsmComputeShaderCase(
2454 testCtx, "propagated_nans", "Check that nans are propagated", spec));
2458 ComputeShaderSpec spec;
2459 const deUint8 numCases = 6;
2460 vector<float> inputs (numCases, 0.f);
2461 vector<float> outputs;
2463 spec.numWorkGroups = IVec3(numCases, 1, 1);
2465 spec.specConstants.push_back(bitwiseCast<deUint32>(0.f));
2466 spec.specConstants.push_back(bitwiseCast<deUint32>(-0.f));
2467 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -16)));
2468 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, -32)));
2469 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -127)));
2470 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::ldexp(1.0f, -128)));
2472 outputs.push_back(0.f);
2473 outputs.push_back(-0.f);
2474 outputs.push_back(0.f);
2475 outputs.push_back(-0.f);
2476 outputs.push_back(0.f);
2477 outputs.push_back(-0.f);
2479 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2480 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2482 group->addChild(new SpvAsmComputeShaderCase(
2483 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec));
2487 ComputeShaderSpec spec;
2488 const deUint8 numCases = 6;
2489 vector<float> inputs (numCases, 0.f);
2490 vector<float> outputs;
2492 spec.numWorkGroups = IVec3(numCases, 1, 1);
2494 for (deUint8 idx = 0; idx < 6; ++idx)
2496 const float f = static_cast<float>(idx * 10 - 30) / 4.f;
2497 spec.specConstants.push_back(bitwiseCast<deUint32>(f));
2498 outputs.push_back(f);
2501 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2502 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2504 group->addChild(new SpvAsmComputeShaderCase(
2505 testCtx, "exact", "Check that values exactly preserved where appropriate", spec));
2509 ComputeShaderSpec spec;
2510 const deUint8 numCases = 4;
2511 vector<float> inputs (numCases, 0.f);
2512 vector<float> outputs;
2514 spec.numWorkGroups = IVec3(numCases, 1, 1);
2515 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase;
2517 outputs.push_back(constructNormalizedFloat(8, 0x300300));
2518 outputs.push_back(-constructNormalizedFloat(-7, 0x600800));
2519 outputs.push_back(constructNormalizedFloat(2, 0x01E000));
2520 outputs.push_back(constructNormalizedFloat(1, 0xFFE000));
2522 for (deUint8 idx = 0; idx < numCases; ++idx)
2523 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
2525 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2526 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2528 group->addChild(new SpvAsmComputeShaderCase(
2529 testCtx, "rounded", "Check that are rounded when needed", spec));
2532 return group.release();
2535 // Checks that constant null/composite values can be used in computation.
2536 tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
2538 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnullcomposite", "Spotcheck the OpConstantNull & OpConstantComposite instruction"));
2539 ComputeShaderSpec spec;
2540 de::Random rnd (deStringHash(group->getName()));
2541 const int numElements = 100;
2542 vector<float> positiveFloats (numElements, 0);
2543 vector<float> negativeFloats (numElements, 0);
2545 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2547 for (size_t ndx = 0; ndx < numElements; ++ndx)
2548 negativeFloats[ndx] = -positiveFloats[ndx];
2551 "OpCapability Shader\n"
2552 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2553 "OpMemoryModel Logical GLSL450\n"
2554 "OpEntryPoint GLCompute %main \"main\" %id\n"
2555 "OpExecutionMode %main LocalSize 1 1 1\n"
2557 "OpSource GLSL 430\n"
2558 "OpName %main \"main\"\n"
2559 "OpName %id \"gl_GlobalInvocationID\"\n"
2561 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2563 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) +
2565 "%fvec3 = OpTypeVector %f32 3\n"
2566 "%fmat = OpTypeMatrix %fvec3 3\n"
2567 "%ten = OpConstant %u32 10\n"
2568 "%f32arr10 = OpTypeArray %f32 %ten\n"
2569 "%fst = OpTypeStruct %f32 %f32\n"
2571 + string(s_InputOutputBuffer) +
2573 "%id = OpVariable %uvec3ptr Input\n"
2574 "%zero = OpConstant %i32 0\n"
2576 // Create a bunch of null values
2577 "%unull = OpConstantNull %u32\n"
2578 "%fnull = OpConstantNull %f32\n"
2579 "%vnull = OpConstantNull %fvec3\n"
2580 "%mnull = OpConstantNull %fmat\n"
2581 "%anull = OpConstantNull %f32arr10\n"
2582 "%snull = OpConstantComposite %fst %fnull %fnull\n"
2584 "%main = OpFunction %void None %voidf\n"
2585 "%label = OpLabel\n"
2586 "%idval = OpLoad %uvec3 %id\n"
2587 "%x = OpCompositeExtract %u32 %idval 0\n"
2588 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2589 "%inval = OpLoad %f32 %inloc\n"
2590 "%neg = OpFNegate %f32 %inval\n"
2592 // Get the abs() of (a certain element of) those null values
2593 "%unull_cov = OpConvertUToF %f32 %unull\n"
2594 "%unull_abs = OpExtInst %f32 %std450 FAbs %unull_cov\n"
2595 "%fnull_abs = OpExtInst %f32 %std450 FAbs %fnull\n"
2596 "%vnull_0 = OpCompositeExtract %f32 %vnull 0\n"
2597 "%vnull_abs = OpExtInst %f32 %std450 FAbs %vnull_0\n"
2598 "%mnull_12 = OpCompositeExtract %f32 %mnull 1 2\n"
2599 "%mnull_abs = OpExtInst %f32 %std450 FAbs %mnull_12\n"
2600 "%anull_3 = OpCompositeExtract %f32 %anull 3\n"
2601 "%anull_abs = OpExtInst %f32 %std450 FAbs %anull_3\n"
2602 "%snull_1 = OpCompositeExtract %f32 %snull 1\n"
2603 "%snull_abs = OpExtInst %f32 %std450 FAbs %snull_1\n"
2606 "%add1 = OpFAdd %f32 %neg %unull_abs\n"
2607 "%add2 = OpFAdd %f32 %add1 %fnull_abs\n"
2608 "%add3 = OpFAdd %f32 %add2 %vnull_abs\n"
2609 "%add4 = OpFAdd %f32 %add3 %mnull_abs\n"
2610 "%add5 = OpFAdd %f32 %add4 %anull_abs\n"
2611 "%final = OpFAdd %f32 %add5 %snull_abs\n"
2613 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2614 " OpStore %outloc %final\n" // write to output
2617 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
2618 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
2619 spec.numWorkGroups = IVec3(numElements, 1, 1);
2621 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec));
2623 return group.release();
2626 // Assembly code used for testing loop control is based on GLSL source code:
2629 // layout(std140, set = 0, binding = 0) readonly buffer Input {
2630 // float elements[];
2632 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
2633 // float elements[];
2637 // uint x = gl_GlobalInvocationID.x;
2638 // output_data.elements[x] = input_data.elements[x];
2639 // for (uint i = 0; i < 4; ++i)
2640 // output_data.elements[x] += 1.f;
2642 tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
2644 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "loop_control", "Tests loop control cases"));
2645 vector<CaseParameter> cases;
2646 de::Random rnd (deStringHash(group->getName()));
2647 const int numElements = 100;
2648 vector<float> inputFloats (numElements, 0);
2649 vector<float> outputFloats (numElements, 0);
2650 const StringTemplate shaderTemplate (
2651 string(s_ShaderPreamble) +
2653 "OpSource GLSL 430\n"
2654 "OpName %main \"main\"\n"
2655 "OpName %id \"gl_GlobalInvocationID\"\n"
2657 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2659 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2661 "%u32ptr = OpTypePointer Function %u32\n"
2663 "%id = OpVariable %uvec3ptr Input\n"
2664 "%zero = OpConstant %i32 0\n"
2665 "%one = OpConstant %i32 1\n"
2666 "%constf1 = OpConstant %f32 1.0\n"
2667 "%four = OpConstant %u32 4\n"
2669 "%main = OpFunction %void None %voidf\n"
2670 "%entry = OpLabel\n"
2671 "%i = OpVariable %u32ptr Function\n"
2672 " OpStore %i %zero\n"
2674 "%idval = OpLoad %uvec3 %id\n"
2675 "%x = OpCompositeExtract %u32 %idval 0\n"
2676 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2677 "%inval = OpLoad %f32 %inloc\n"
2678 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2679 " OpStore %outloc %inval\n"
2680 " OpBranch %loop_entry\n"
2682 "%loop_entry = OpLabel\n"
2683 "%i_val = OpLoad %u32 %i\n"
2684 "%cmp_lt = OpULessThan %bool %i_val %four\n"
2685 " OpLoopMerge %loop_merge %loop_entry ${CONTROL}\n"
2686 " OpBranchConditional %cmp_lt %loop_body %loop_merge\n"
2687 "%loop_body = OpLabel\n"
2688 "%outval = OpLoad %f32 %outloc\n"
2689 "%addf1 = OpFAdd %f32 %outval %constf1\n"
2690 " OpStore %outloc %addf1\n"
2691 "%new_i = OpIAdd %u32 %i_val %one\n"
2692 " OpStore %i %new_i\n"
2693 " OpBranch %loop_entry\n"
2694 "%loop_merge = OpLabel\n"
2696 " OpFunctionEnd\n");
2698 cases.push_back(CaseParameter("none", "None"));
2699 cases.push_back(CaseParameter("unroll", "Unroll"));
2700 cases.push_back(CaseParameter("dont_unroll", "DontUnroll"));
2701 cases.push_back(CaseParameter("unroll_dont_unroll", "Unroll|DontUnroll"));
2703 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
2705 for (size_t ndx = 0; ndx < numElements; ++ndx)
2706 outputFloats[ndx] = inputFloats[ndx] + 4.f;
2708 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2710 map<string, string> specializations;
2711 ComputeShaderSpec spec;
2713 specializations["CONTROL"] = cases[caseNdx].param;
2714 spec.assembly = shaderTemplate.specialize(specializations);
2715 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2716 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
2717 spec.numWorkGroups = IVec3(numElements, 1, 1);
2719 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2722 return group.release();
2725 // Assembly code used for testing selection control is based on GLSL source code:
2728 // layout(std140, set = 0, binding = 0) readonly buffer Input {
2729 // float elements[];
2731 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
2732 // float elements[];
2736 // uint x = gl_GlobalInvocationID.x;
2737 // float val = input_data.elements[x];
2739 // output_data.elements[x] = val + 1.f;
2741 // output_data.elements[x] = val - 1.f;
2743 tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
2745 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_control", "Tests selection control cases"));
2746 vector<CaseParameter> cases;
2747 de::Random rnd (deStringHash(group->getName()));
2748 const int numElements = 100;
2749 vector<float> inputFloats (numElements, 0);
2750 vector<float> outputFloats (numElements, 0);
2751 const StringTemplate shaderTemplate (
2752 string(s_ShaderPreamble) +
2754 "OpSource GLSL 430\n"
2755 "OpName %main \"main\"\n"
2756 "OpName %id \"gl_GlobalInvocationID\"\n"
2758 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2760 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2762 "%id = OpVariable %uvec3ptr Input\n"
2763 "%zero = OpConstant %i32 0\n"
2764 "%constf1 = OpConstant %f32 1.0\n"
2765 "%constf10 = OpConstant %f32 10.0\n"
2767 "%main = OpFunction %void None %voidf\n"
2768 "%entry = OpLabel\n"
2769 "%idval = OpLoad %uvec3 %id\n"
2770 "%x = OpCompositeExtract %u32 %idval 0\n"
2771 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2772 "%inval = OpLoad %f32 %inloc\n"
2773 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2774 "%cmp_gt = OpFOrdGreaterThan %bool %inval %constf10\n"
2776 " OpSelectionMerge %if_end ${CONTROL}\n"
2777 " OpBranchConditional %cmp_gt %if_true %if_false\n"
2778 "%if_true = OpLabel\n"
2779 "%addf1 = OpFAdd %f32 %inval %constf1\n"
2780 " OpStore %outloc %addf1\n"
2781 " OpBranch %if_end\n"
2782 "%if_false = OpLabel\n"
2783 "%subf1 = OpFSub %f32 %inval %constf1\n"
2784 " OpStore %outloc %subf1\n"
2785 " OpBranch %if_end\n"
2786 "%if_end = OpLabel\n"
2788 " OpFunctionEnd\n");
2790 cases.push_back(CaseParameter("none", "None"));
2791 cases.push_back(CaseParameter("flatten", "Flatten"));
2792 cases.push_back(CaseParameter("dont_flatten", "DontFlatten"));
2793 cases.push_back(CaseParameter("flatten_dont_flatten", "DontFlatten|Flatten"));
2795 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
2797 for (size_t ndx = 0; ndx < numElements; ++ndx)
2798 outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f);
2800 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2802 map<string, string> specializations;
2803 ComputeShaderSpec spec;
2805 specializations["CONTROL"] = cases[caseNdx].param;
2806 spec.assembly = shaderTemplate.specialize(specializations);
2807 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2808 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
2809 spec.numWorkGroups = IVec3(numElements, 1, 1);
2811 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2814 return group.release();
2817 // Assembly code used for testing function control is based on GLSL source code:
2821 // layout(std140, set = 0, binding = 0) readonly buffer Input {
2822 // float elements[];
2824 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
2825 // float elements[];
2828 // float const10() { return 10.f; }
2831 // uint x = gl_GlobalInvocationID.x;
2832 // output_data.elements[x] = input_data.elements[x] + const10();
2834 tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx)
2836 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "function_control", "Tests function control cases"));
2837 vector<CaseParameter> cases;
2838 de::Random rnd (deStringHash(group->getName()));
2839 const int numElements = 100;
2840 vector<float> inputFloats (numElements, 0);
2841 vector<float> outputFloats (numElements, 0);
2842 const StringTemplate shaderTemplate (
2843 string(s_ShaderPreamble) +
2845 "OpSource GLSL 430\n"
2846 "OpName %main \"main\"\n"
2847 "OpName %func_const10 \"const10(\"\n"
2848 "OpName %id \"gl_GlobalInvocationID\"\n"
2850 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2852 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2854 "%f32f = OpTypeFunction %f32\n"
2855 "%id = OpVariable %uvec3ptr Input\n"
2856 "%zero = OpConstant %i32 0\n"
2857 "%constf10 = OpConstant %f32 10.0\n"
2859 "%main = OpFunction %void None %voidf\n"
2860 "%entry = OpLabel\n"
2861 "%idval = OpLoad %uvec3 %id\n"
2862 "%x = OpCompositeExtract %u32 %idval 0\n"
2863 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2864 "%inval = OpLoad %f32 %inloc\n"
2865 "%ret_10 = OpFunctionCall %f32 %func_const10\n"
2866 "%fadd = OpFAdd %f32 %inval %ret_10\n"
2867 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2868 " OpStore %outloc %fadd\n"
2872 "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n"
2873 "%label = OpLabel\n"
2874 " OpReturnValue %constf10\n"
2875 " OpFunctionEnd\n");
2877 cases.push_back(CaseParameter("none", "None"));
2878 cases.push_back(CaseParameter("inline", "Inline"));
2879 cases.push_back(CaseParameter("dont_inline", "DontInline"));
2880 cases.push_back(CaseParameter("pure", "Pure"));
2881 cases.push_back(CaseParameter("const", "Const"));
2882 cases.push_back(CaseParameter("inline_pure", "Inline|Pure"));
2883 cases.push_back(CaseParameter("const_dont_inline", "Const|DontInline"));
2884 cases.push_back(CaseParameter("inline_dont_inline", "Inline|DontInline"));
2885 cases.push_back(CaseParameter("pure_inline_dont_inline", "Pure|Inline|DontInline"));
2887 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
2889 for (size_t ndx = 0; ndx < numElements; ++ndx)
2890 outputFloats[ndx] = inputFloats[ndx] + 10.f;
2892 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2894 map<string, string> specializations;
2895 ComputeShaderSpec spec;
2897 specializations["CONTROL"] = cases[caseNdx].param;
2898 spec.assembly = shaderTemplate.specialize(specializations);
2899 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2900 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
2901 spec.numWorkGroups = IVec3(numElements, 1, 1);
2903 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2906 return group.release();
2909 tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx)
2911 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory_access", "Tests memory access cases"));
2912 vector<CaseParameter> cases;
2913 de::Random rnd (deStringHash(group->getName()));
2914 const int numElements = 100;
2915 vector<float> inputFloats (numElements, 0);
2916 vector<float> outputFloats (numElements, 0);
2917 const StringTemplate shaderTemplate (
2918 string(s_ShaderPreamble) +
2920 "OpSource GLSL 430\n"
2921 "OpName %main \"main\"\n"
2922 "OpName %id \"gl_GlobalInvocationID\"\n"
2924 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2926 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
2928 "%f32ptr_f = OpTypePointer Function %f32\n"
2930 "%id = OpVariable %uvec3ptr Input\n"
2931 "%zero = OpConstant %i32 0\n"
2932 "%four = OpConstant %i32 4\n"
2934 "%main = OpFunction %void None %voidf\n"
2935 "%label = OpLabel\n"
2936 "%copy = OpVariable %f32ptr_f Function\n"
2937 "%idval = OpLoad %uvec3 %id ${ACCESS}\n"
2938 "%x = OpCompositeExtract %u32 %idval 0\n"
2939 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2940 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2941 " OpCopyMemory %copy %inloc ${ACCESS}\n"
2942 "%val1 = OpLoad %f32 %copy\n"
2943 "%val2 = OpLoad %f32 %inloc\n"
2944 "%add = OpFAdd %f32 %val1 %val2\n"
2945 " OpStore %outloc %add ${ACCESS}\n"
2947 " OpFunctionEnd\n");
2949 cases.push_back(CaseParameter("null", ""));
2950 cases.push_back(CaseParameter("none", "None"));
2951 cases.push_back(CaseParameter("volatile", "Volatile"));
2952 cases.push_back(CaseParameter("aligned", "Aligned 4"));
2953 cases.push_back(CaseParameter("nontemporal", "Nontemporal"));
2954 cases.push_back(CaseParameter("aligned_nontemporal", "Aligned|Nontemporal 4"));
2955 cases.push_back(CaseParameter("aligned_volatile", "Volatile|Aligned 4"));
2957 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
2959 for (size_t ndx = 0; ndx < numElements; ++ndx)
2960 outputFloats[ndx] = inputFloats[ndx] + inputFloats[ndx];
2962 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2964 map<string, string> specializations;
2965 ComputeShaderSpec spec;
2967 specializations["ACCESS"] = cases[caseNdx].param;
2968 spec.assembly = shaderTemplate.specialize(specializations);
2969 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2970 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
2971 spec.numWorkGroups = IVec3(numElements, 1, 1);
2973 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2976 return group.release();
2979 // Checks that we can get undefined values for various types, without exercising a computation with it.
2980 tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx)
2982 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opundef", "Tests the OpUndef instruction"));
2983 vector<CaseParameter> cases;
2984 de::Random rnd (deStringHash(group->getName()));
2985 const int numElements = 100;
2986 vector<float> positiveFloats (numElements, 0);
2987 vector<float> negativeFloats (numElements, 0);
2988 const StringTemplate shaderTemplate (
2989 string(s_ShaderPreamble) +
2991 "OpSource GLSL 430\n"
2992 "OpName %main \"main\"\n"
2993 "OpName %id \"gl_GlobalInvocationID\"\n"
2995 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2997 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) +
3001 "%id = OpVariable %uvec3ptr Input\n"
3002 "%zero = OpConstant %i32 0\n"
3004 "%main = OpFunction %void None %voidf\n"
3005 "%label = OpLabel\n"
3007 "%undef = OpUndef %type\n"
3009 "%idval = OpLoad %uvec3 %id\n"
3010 "%x = OpCompositeExtract %u32 %idval 0\n"
3012 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3013 "%inval = OpLoad %f32 %inloc\n"
3014 "%neg = OpFNegate %f32 %inval\n"
3015 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3016 " OpStore %outloc %neg\n"
3018 " OpFunctionEnd\n");
3020 cases.push_back(CaseParameter("bool", "%type = OpTypeBool"));
3021 cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1"));
3022 cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0"));
3023 cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32"));
3024 cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4"));
3025 cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2"));
3026 cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %uvec3 3"));
3027 cases.push_back(CaseParameter("image", "%type = OpTypeImage %f32 2D 0 0 0 0 Unknown"));
3028 cases.push_back(CaseParameter("sampler", "%type = OpTypeSampler"));
3029 cases.push_back(CaseParameter("sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 0 Unknown\n"
3030 "%type = OpTypeSampledImage %img"));
3031 cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n"
3032 "%type = OpTypeArray %i32 %100"));
3033 cases.push_back(CaseParameter("runtimearray", "%type = OpTypeRuntimeArray %f32"));
3034 cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32"));
3035 cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32"));
3036 cases.push_back(CaseParameter("function", "%type = OpTypeFunction %void %i32 %f32"));
3038 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
3040 for (size_t ndx = 0; ndx < numElements; ++ndx)
3041 negativeFloats[ndx] = -positiveFloats[ndx];
3043 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3045 map<string, string> specializations;
3046 ComputeShaderSpec spec;
3048 specializations["TYPE"] = cases[caseNdx].param;
3049 spec.assembly = shaderTemplate.specialize(specializations);
3050 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
3051 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
3052 spec.numWorkGroups = IVec3(numElements, 1, 1);
3054 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3057 return group.release();
3059 typedef std::pair<std::string, VkShaderStageFlagBits> EntryToStage;
3060 typedef map<string, vector<EntryToStage> > ModuleMap;
3061 typedef map<VkShaderStageFlagBits, vector<deInt32> > StageToSpecConstantMap;
3063 // Context for a specific test instantiation. For example, an instantiation
3064 // may test colors yellow/magenta/cyan/mauve in a tesselation shader
3065 // with an entry point named 'main_to_the_main'
3066 struct InstanceContext
3068 // Map of modules to what entry_points we care to use from those modules.
3069 ModuleMap moduleMap;
3070 RGBA inputColors[4];
3071 RGBA outputColors[4];
3072 // Concrete SPIR-V code to test via boilerplate specialization.
3073 map<string, string> testCodeFragments;
3074 StageToSpecConstantMap specConstants;
3076 bool hasTessellation;
3077 InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_, const StageToSpecConstantMap& specConstants_)
3078 : testCodeFragments (testCodeFragments_)
3079 , specConstants (specConstants_)
3080 , hasTessellation (false)
3082 inputColors[0] = inputs[0];
3083 inputColors[1] = inputs[1];
3084 inputColors[2] = inputs[2];
3085 inputColors[3] = inputs[3];
3087 outputColors[0] = outputs[0];
3088 outputColors[1] = outputs[1];
3089 outputColors[2] = outputs[2];
3090 outputColors[3] = outputs[3];
3093 InstanceContext (const InstanceContext& other)
3094 : moduleMap (other.moduleMap)
3095 , testCodeFragments (other.testCodeFragments)
3096 , specConstants (other.specConstants)
3097 , hasTessellation (other.hasTessellation)
3099 inputColors[0] = other.inputColors[0];
3100 inputColors[1] = other.inputColors[1];
3101 inputColors[2] = other.inputColors[2];
3102 inputColors[3] = other.inputColors[3];
3104 outputColors[0] = other.outputColors[0];
3105 outputColors[1] = other.outputColors[1];
3106 outputColors[2] = other.outputColors[2];
3107 outputColors[3] = other.outputColors[3];
3111 // A description of a shader to be used for a single stage of the graphics pipeline.
3112 struct ShaderElement
3114 // The module that contains this shader entrypoint.
3117 // The name of the entrypoint.
3120 // Which shader stage this entry point represents.
3121 VkShaderStageFlagBits stage;
3123 ShaderElement (const string& moduleName_, const string& entryPoint_, VkShaderStageFlagBits shaderStage_)
3124 : moduleName(moduleName_)
3125 , entryName(entryPoint_)
3126 , stage(shaderStage_)
3131 void getDefaultColors (RGBA (&colors)[4])
3133 colors[0] = RGBA::white();
3134 colors[1] = RGBA::red();
3135 colors[2] = RGBA::green();
3136 colors[3] = RGBA::blue();
3139 void getHalfColorsFullAlpha (RGBA (&colors)[4])
3141 colors[0] = RGBA(127, 127, 127, 255);
3142 colors[1] = RGBA(127, 0, 0, 255);
3143 colors[2] = RGBA(0, 127, 0, 255);
3144 colors[3] = RGBA(0, 0, 127, 255);
3147 void getInvertedDefaultColors (RGBA (&colors)[4])
3149 colors[0] = RGBA(0, 0, 0, 255);
3150 colors[1] = RGBA(0, 255, 255, 255);
3151 colors[2] = RGBA(255, 0, 255, 255);
3152 colors[3] = RGBA(255, 255, 0, 255);
3155 // Turns a statically sized array of ShaderElements into an instance-context
3156 // by setting up the mapping of modules to their contained shaders and stages.
3157 // The inputs and expected outputs are given by inputColors and outputColors
3159 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, const StageToSpecConstantMap& specConstants)
3161 InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants);
3162 for (size_t i = 0; i < N; ++i)
3164 ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
3165 if (elements[i].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
3166 elements[i].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3168 ctx.hasTessellation = true;
3175 inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments)
3177 return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, StageToSpecConstantMap());
3180 // The same as createInstanceContext above, but with default colors.
3182 InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map<string, string>& testCodeFragments)
3184 RGBA defaultColors[4];
3185 getDefaultColors(defaultColors);
3186 return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
3189 // For the current InstanceContext, constructs the required modules and shader stage create infos.
3190 void createPipelineShaderStages (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector<ModuleHandleSp>& modules, vector<VkPipelineShaderStageCreateInfo>& createInfos)
3192 for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
3194 const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
3195 modules.push_back(ModuleHandleSp(mod));
3196 for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
3198 const EntryToStage& stage = *shaderNdx;
3199 const VkPipelineShaderStageCreateInfo shaderParam =
3201 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
3202 DE_NULL, // const void* pNext;
3203 (VkPipelineShaderStageCreateFlags)0,
3204 stage.second, // VkShaderStageFlagBits stage;
3205 **modules.back(), // VkShaderModule module;
3206 stage.first.c_str(), // const char* pName;
3207 (const VkSpecializationInfo*)DE_NULL,
3209 createInfos.push_back(shaderParam);
3214 #define SPIRV_ASSEMBLY_TYPES \
3215 "%void = OpTypeVoid\n" \
3216 "%bool = OpTypeBool\n" \
3218 "%i32 = OpTypeInt 32 1\n" \
3219 "%u32 = OpTypeInt 32 0\n" \
3221 "%f32 = OpTypeFloat 32\n" \
3222 "%v3f32 = OpTypeVector %f32 3\n" \
3223 "%v4f32 = OpTypeVector %f32 4\n" \
3225 "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \
3226 "%fun = OpTypeFunction %void\n" \
3228 "%ip_f32 = OpTypePointer Input %f32\n" \
3229 "%ip_i32 = OpTypePointer Input %i32\n" \
3230 "%ip_v3f32 = OpTypePointer Input %v3f32\n" \
3231 "%ip_v4f32 = OpTypePointer Input %v4f32\n" \
3233 "%op_f32 = OpTypePointer Output %f32\n" \
3234 "%op_v4f32 = OpTypePointer Output %v4f32\n" \
3236 "%fp_f32 = OpTypePointer Function %f32\n" \
3237 "%fp_i32 = OpTypePointer Function %i32\n" \
3238 "%fp_v4f32 = OpTypePointer Function %v4f32\n"
3240 #define SPIRV_ASSEMBLY_CONSTANTS \
3241 "%c_f32_1 = OpConstant %f32 1.0\n" \
3242 "%c_f32_0 = OpConstant %f32 0.0\n" \
3243 "%c_f32_0_5 = OpConstant %f32 0.5\n" \
3244 "%c_i32_0 = OpConstant %i32 0\n" \
3245 "%c_i32_1 = OpConstant %i32 1\n" \
3246 "%c_i32_2 = OpConstant %i32 2\n" \
3247 "%c_i32_3 = OpConstant %i32 3\n" \
3248 "%c_i32_4 = OpConstant %i32 4\n" \
3249 "%c_u32_0 = OpConstant %u32 0\n" \
3250 "%c_u32_1 = OpConstant %u32 1\n" \
3251 "%c_u32_2 = OpConstant %u32 2\n" \
3252 "%c_u32_3 = OpConstant %u32 3\n" \
3253 "%c_u32_32 = OpConstant %u32 32\n" \
3254 "%c_u32_4 = OpConstant %u32 4\n" \
3255 "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \
3256 "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \
3257 "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \
3258 "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n"
3260 #define SPIRV_ASSEMBLY_ARRAYS \
3261 "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \
3262 "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \
3263 "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \
3264 "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \
3265 "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \
3266 "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \
3267 "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \
3268 "%op_a2f32 = OpTypePointer Output %a2f32\n" \
3269 "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \
3270 "%op_a4f32 = OpTypePointer Output %a4f32\n"
3272 // Creates vertex-shader assembly by specializing a boilerplate StringTemplate
3273 // on fragments, which must (at least) map "testfun" to an OpFunction definition
3274 // for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
3275 // with "BP_" to avoid collisions with fragments.
3277 // It corresponds roughly to this GLSL:
3279 // layout(location = 0) in vec4 position;
3280 // layout(location = 1) in vec4 color;
3281 // layout(location = 1) out highp vec4 vtxColor;
3282 // void main (void) { gl_Position = position; vtxColor = test_func(color); }
3283 string makeVertexShaderAssembly(const map<string, string>& fragments)
3285 // \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized
3286 static const char vertexShaderBoilerplate[] =
3287 "OpCapability Shader\n"
3288 "OpMemoryModel Logical GLSL450\n"
3289 "OpEntryPoint Vertex %main \"main\" %BP_Position %BP_vtxColor %BP_color "
3290 "%BP_vtxPosition %BP_vertex_id %BP_instance_id\n"
3292 "OpName %main \"main\"\n"
3293 "OpName %BP_vtxPosition \"vtxPosition\"\n"
3294 "OpName %BP_Position \"position\"\n"
3295 "OpName %BP_vtxColor \"vtxColor\"\n"
3296 "OpName %BP_color \"color\"\n"
3297 "OpName %BP_vertex_id \"gl_VertexID\"\n"
3298 "OpName %BP_instance_id \"gl_InstanceID\"\n"
3299 "OpName %test_code \"testfun(vf4;\"\n"
3300 "OpDecorate %BP_vtxPosition Location 2\n"
3301 "OpDecorate %BP_Position Location 0\n"
3302 "OpDecorate %BP_vtxColor Location 1\n"
3303 "OpDecorate %BP_color Location 1\n"
3304 "OpDecorate %BP_vertex_id BuiltIn VertexId\n"
3305 "OpDecorate %BP_instance_id BuiltIn InstanceId\n"
3306 "${decoration:opt}\n"
3307 SPIRV_ASSEMBLY_TYPES
3308 SPIRV_ASSEMBLY_CONSTANTS
3309 SPIRV_ASSEMBLY_ARRAYS
3310 "%BP_vtxPosition = OpVariable %op_v4f32 Output\n"
3311 "%BP_Position = OpVariable %ip_v4f32 Input\n"
3312 "%BP_vtxColor = OpVariable %op_v4f32 Output\n"
3313 "%BP_color = OpVariable %ip_v4f32 Input\n"
3314 "%BP_vertex_id = OpVariable %ip_i32 Input\n"
3315 "%BP_instance_id = OpVariable %ip_i32 Input\n"
3317 "%main = OpFunction %void None %fun\n"
3318 "%BP_label = OpLabel\n"
3319 "%BP_tmp_position = OpLoad %v4f32 %BP_Position\n"
3320 "OpStore %BP_vtxPosition %BP_tmp_position\n"
3321 "%BP_tmp_color = OpLoad %v4f32 %BP_color\n"
3322 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_tmp_color\n"
3323 "OpStore %BP_vtxColor %BP_clr_transformed\n"
3327 return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments);
3330 // Creates tess-control-shader assembly by specializing a boilerplate
3331 // StringTemplate on fragments, which must (at least) map "testfun" to an
3332 // OpFunction definition for %test_code that takes and returns a %v4f32.
3333 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
3335 // It roughly corresponds to the following GLSL.
3338 // layout(vertices = 3) out;
3339 // layout(location = 1) in vec4 in_color[];
3340 // layout(location = 2) in vec4 in_position[];
3341 // layout(location = 1) out vec4 out_color[];
3342 // layout(location = 2) out vec4 out_position[];
3345 // out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
3346 // out_position[gl_InvocationID] = in_position[gl_InvocationID];
3347 // if (gl_InvocationID == 0) {
3348 // gl_TessLevelOuter[0] = 1.0;
3349 // gl_TessLevelOuter[1] = 1.0;
3350 // gl_TessLevelOuter[2] = 1.0;
3351 // gl_TessLevelInner[0] = 1.0;
3354 string makeTessControlShaderAssembly (const map<string, string>& fragments)
3356 static const char tessControlShaderBoilerplate[] =
3357 "OpCapability Tessellation\n"
3358 "OpMemoryModel Logical GLSL450\n"
3359 "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"
3360 "OpExecutionMode %BP_main OutputVertices 3\n"
3362 "OpName %BP_main \"main\"\n"
3363 "OpName %BP_out_color \"out_color\"\n"
3364 "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n"
3365 "OpName %BP_in_color \"in_color\"\n"
3366 "OpName %BP_out_position \"out_position\"\n"
3367 "OpName %BP_in_position \"in_position\"\n"
3368 "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
3369 "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n"
3370 "OpName %test_code \"testfun(vf4;\"\n"
3371 "OpDecorate %BP_out_color Location 1\n"
3372 "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
3373 "OpDecorate %BP_in_color Location 1\n"
3374 "OpDecorate %BP_out_position Location 2\n"
3375 "OpDecorate %BP_in_position Location 2\n"
3376 "OpDecorate %BP_gl_TessLevelOuter Patch\n"
3377 "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
3378 "OpDecorate %BP_gl_TessLevelInner Patch\n"
3379 "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
3380 "${decoration:opt}\n"
3381 SPIRV_ASSEMBLY_TYPES
3382 SPIRV_ASSEMBLY_CONSTANTS
3383 SPIRV_ASSEMBLY_ARRAYS
3384 "%BP_out_color = OpVariable %op_a3v4f32 Output\n"
3385 "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
3386 "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
3387 "%BP_out_position = OpVariable %op_a3v4f32 Output\n"
3388 "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
3389 "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
3390 "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
3393 "%BP_main = OpFunction %void None %fun\n"
3394 "%BP_label = OpLabel\n"
3396 "%BP_invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
3398 "%BP_in_color_ptr = OpAccessChain %ip_v4f32 %BP_in_color %BP_invocation_id\n"
3399 "%BP_in_position_ptr = OpAccessChain %ip_v4f32 %BP_in_position %BP_invocation_id\n"
3401 "%BP_in_color_val = OpLoad %v4f32 %BP_in_color_ptr\n"
3402 "%BP_in_position_val = OpLoad %v4f32 %BP_in_position_ptr\n"
3404 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_color_val\n"
3406 "%BP_out_color_ptr = OpAccessChain %op_v4f32 %BP_out_color %BP_invocation_id\n"
3407 "%BP_out_position_ptr = OpAccessChain %op_v4f32 %BP_out_position %BP_invocation_id\n"
3409 "OpStore %BP_out_color_ptr %BP_clr_transformed\n"
3410 "OpStore %BP_out_position_ptr %BP_in_position_val\n"
3412 "%BP_is_first_invocation = OpIEqual %bool %BP_invocation_id %c_i32_0\n"
3413 "OpSelectionMerge %BP_merge_label None\n"
3414 "OpBranchConditional %BP_is_first_invocation %BP_first_invocation %BP_merge_label\n"
3416 "%BP_first_invocation = OpLabel\n"
3417 "%BP_tess_outer_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
3418 "%BP_tess_outer_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
3419 "%BP_tess_outer_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
3420 "%BP_tess_inner = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
3422 "OpStore %BP_tess_outer_0 %c_f32_1\n"
3423 "OpStore %BP_tess_outer_1 %c_f32_1\n"
3424 "OpStore %BP_tess_outer_2 %c_f32_1\n"
3425 "OpStore %BP_tess_inner %c_f32_1\n"
3427 "OpBranch %BP_merge_label\n"
3428 "%BP_merge_label = OpLabel\n"
3432 return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments);
3435 // Creates tess-evaluation-shader assembly by specializing a boilerplate
3436 // StringTemplate on fragments, which must (at least) map "testfun" to an
3437 // OpFunction definition for %test_code that takes and returns a %v4f32.
3438 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
3440 // It roughly corresponds to the following glsl.
3444 // layout(triangles, equal_spacing, ccw) in;
3445 // layout(location = 1) in vec4 in_color[];
3446 // layout(location = 2) in vec4 in_position[];
3447 // layout(location = 1) out vec4 out_color;
3449 // #define interpolate(val)
3450 // vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
3451 // vec4(gl_TessCoord.z) * val[2]
3454 // gl_Position = vec4(gl_TessCoord.x) * in_position[0] +
3455 // vec4(gl_TessCoord.y) * in_position[1] +
3456 // vec4(gl_TessCoord.z) * in_position[2];
3457 // out_color = testfun(interpolate(in_color));
3459 string makeTessEvalShaderAssembly(const map<string, string>& fragments)
3461 static const char tessEvalBoilerplate[] =
3462 "OpCapability Tessellation\n"
3463 "OpMemoryModel Logical GLSL450\n"
3464 "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_tessCoord %BP_in_position %BP_out_color %BP_in_color \n"
3465 "OpExecutionMode %BP_main Triangles\n"
3467 "OpName %BP_main \"main\"\n"
3468 "OpName %BP_per_vertex_out \"gl_PerVertex\"\n"
3469 "OpMemberName %BP_per_vertex_out 0 \"gl_Position\"\n"
3470 "OpMemberName %BP_per_vertex_out 1 \"gl_PointSize\"\n"
3471 "OpMemberName %BP_per_vertex_out 2 \"gl_ClipDistance\"\n"
3472 "OpMemberName %BP_per_vertex_out 3 \"gl_CullDistance\"\n"
3473 "OpName %BP_stream \"\"\n"
3474 "OpName %BP_gl_tessCoord \"gl_TessCoord\"\n"
3475 "OpName %BP_in_position \"in_position\"\n"
3476 "OpName %BP_out_color \"out_color\"\n"
3477 "OpName %BP_in_color \"in_color\"\n"
3478 "OpName %test_code \"testfun(vf4;\"\n"
3479 "OpMemberDecorate %BP_per_vertex_out 0 BuiltIn Position\n"
3480 "OpMemberDecorate %BP_per_vertex_out 1 BuiltIn PointSize\n"
3481 "OpMemberDecorate %BP_per_vertex_out 2 BuiltIn ClipDistance\n"
3482 "OpMemberDecorate %BP_per_vertex_out 3 BuiltIn CullDistance\n"
3483 "OpDecorate %BP_per_vertex_out Block\n"
3484 "OpDecorate %BP_gl_tessCoord BuiltIn TessCoord\n"
3485 "OpDecorate %BP_in_position Location 2\n"
3486 "OpDecorate %BP_out_color Location 1\n"
3487 "OpDecorate %BP_in_color Location 1\n"
3488 "${decoration:opt}\n"
3489 SPIRV_ASSEMBLY_TYPES
3490 SPIRV_ASSEMBLY_CONSTANTS
3491 SPIRV_ASSEMBLY_ARRAYS
3492 "%BP_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
3493 "%BP_op_per_vertex_out = OpTypePointer Output %BP_per_vertex_out\n"
3494 "%BP_stream = OpVariable %BP_op_per_vertex_out Output\n"
3495 "%BP_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
3496 "%BP_in_position = OpVariable %ip_a32v4f32 Input\n"
3497 "%BP_out_color = OpVariable %op_v4f32 Output\n"
3498 "%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
3501 "%BP_main = OpFunction %void None %fun\n"
3502 "%BP_label = OpLabel\n"
3503 "%BP_tc_0_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_0\n"
3504 "%BP_tc_1_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_1\n"
3505 "%BP_tc_2_ptr = OpAccessChain %ip_f32 %BP_gl_tessCoord %c_u32_2\n"
3507 "%BP_tc_0 = OpLoad %f32 %BP_tc_0_ptr\n"
3508 "%BP_tc_1 = OpLoad %f32 %BP_tc_1_ptr\n"
3509 "%BP_tc_2 = OpLoad %f32 %BP_tc_2_ptr\n"
3511 "%BP_in_pos_0_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_0\n"
3512 "%BP_in_pos_1_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_1\n"
3513 "%BP_in_pos_2_ptr = OpAccessChain %ip_v4f32 %BP_in_position %c_i32_2\n"
3515 "%BP_in_pos_0 = OpLoad %v4f32 %BP_in_pos_0_ptr\n"
3516 "%BP_in_pos_1 = OpLoad %v4f32 %BP_in_pos_1_ptr\n"
3517 "%BP_in_pos_2 = OpLoad %v4f32 %BP_in_pos_2_ptr\n"
3519 "%BP_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_pos_0\n"
3520 "%BP_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_pos_1\n"
3521 "%BP_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_pos_2\n"
3523 "%BP_out_pos_ptr = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
3525 "%BP_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %BP_in_pos_0_weighted %BP_in_pos_1_weighted\n"
3526 "%BP_computed_out = OpFAdd %v4f32 %BP_in_pos_0_plus_pos_1 %BP_in_pos_2_weighted\n"
3527 "OpStore %BP_out_pos_ptr %BP_computed_out\n"
3529 "%BP_in_clr_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
3530 "%BP_in_clr_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
3531 "%BP_in_clr_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
3533 "%BP_in_clr_0 = OpLoad %v4f32 %BP_in_clr_0_ptr\n"
3534 "%BP_in_clr_1 = OpLoad %v4f32 %BP_in_clr_1_ptr\n"
3535 "%BP_in_clr_2 = OpLoad %v4f32 %BP_in_clr_2_ptr\n"
3537 "%BP_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %BP_in_clr_0\n"
3538 "%BP_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %BP_in_clr_1\n"
3539 "%BP_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %BP_in_clr_2\n"
3541 "%BP_in_clr_0_plus_col_1 = OpFAdd %v4f32 %BP_in_clr_0_weighted %BP_in_clr_1_weighted\n"
3542 "%BP_computed_clr = OpFAdd %v4f32 %BP_in_clr_0_plus_col_1 %BP_in_clr_2_weighted\n"
3543 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_computed_clr\n"
3545 "OpStore %BP_out_color %BP_clr_transformed\n"
3549 return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments);
3552 // Creates geometry-shader assembly by specializing a boilerplate StringTemplate
3553 // on fragments, which must (at least) map "testfun" to an OpFunction definition
3554 // for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
3555 // with "BP_" to avoid collisions with fragments.
3557 // Derived from this GLSL:
3560 // layout(triangles) in;
3561 // layout(triangle_strip, max_vertices = 3) out;
3563 // layout(location = 1) in vec4 in_color[];
3564 // layout(location = 1) out vec4 out_color;
3567 // gl_Position = gl_in[0].gl_Position;
3568 // out_color = test_fun(in_color[0]);
3570 // gl_Position = gl_in[1].gl_Position;
3571 // out_color = test_fun(in_color[1]);
3573 // gl_Position = gl_in[2].gl_Position;
3574 // out_color = test_fun(in_color[2]);
3578 string makeGeometryShaderAssembly(const map<string, string>& fragments)
3580 static const char geometryShaderBoilerplate[] =
3581 "OpCapability Geometry\n"
3582 "OpMemoryModel Logical GLSL450\n"
3583 "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n"
3584 "OpExecutionMode %BP_main Triangles\n"
3585 "OpExecutionMode %BP_main Invocations 0\n"
3586 "OpExecutionMode %BP_main OutputTriangleStrip\n"
3587 "OpExecutionMode %BP_main OutputVertices 3\n"
3589 "OpName %BP_main \"main\"\n"
3590 "OpName %BP_per_vertex_in \"gl_PerVertex\"\n"
3591 "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n"
3592 "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n"
3593 "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n"
3594 "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n"
3595 "OpName %BP_gl_in \"gl_in\"\n"
3596 "OpName %BP_out_color \"out_color\"\n"
3597 "OpName %BP_in_color \"in_color\"\n"
3598 "OpName %test_code \"testfun(vf4;\"\n"
3599 "OpDecorate %BP_out_gl_position BuiltIn Position\n"
3600 "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
3601 "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
3602 "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
3603 "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
3604 "OpDecorate %BP_per_vertex_in Block\n"
3605 "OpDecorate %BP_out_color Location 1\n"
3606 "OpDecorate %BP_out_color Stream 0\n"
3607 "OpDecorate %BP_in_color Location 1\n"
3608 "${decoration:opt}\n"
3609 SPIRV_ASSEMBLY_TYPES
3610 SPIRV_ASSEMBLY_CONSTANTS
3611 SPIRV_ASSEMBLY_ARRAYS
3612 "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
3613 "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
3614 "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
3616 "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
3617 "%BP_out_color = OpVariable %op_v4f32 Output\n"
3618 "%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
3619 "%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
3622 "%BP_main = OpFunction %void None %fun\n"
3623 "%BP_label = OpLabel\n"
3624 "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
3625 "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
3626 "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
3628 "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
3629 "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
3630 "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
3632 "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
3633 "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
3634 "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
3636 "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
3637 "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
3638 "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
3640 "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
3641 "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
3642 "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
3645 "OpStore %BP_out_gl_position %BP_in_position_0\n"
3646 "OpStore %BP_out_color %BP_transformed_in_color_0\n"
3649 "OpStore %BP_out_gl_position %BP_in_position_1\n"
3650 "OpStore %BP_out_color %BP_transformed_in_color_1\n"
3653 "OpStore %BP_out_gl_position %BP_in_position_2\n"
3654 "OpStore %BP_out_color %BP_transformed_in_color_2\n"
3661 return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments);
3664 // Creates fragment-shader assembly by specializing a boilerplate StringTemplate
3665 // on fragments, which must (at least) map "testfun" to an OpFunction definition
3666 // for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed
3667 // with "BP_" to avoid collisions with fragments.
3669 // Derived from this GLSL:
3671 // layout(location = 1) in highp vec4 vtxColor;
3672 // layout(location = 0) out highp vec4 fragColor;
3673 // highp vec4 testfun(highp vec4 x) { return x; }
3674 // void main(void) { fragColor = testfun(vtxColor); }
3676 // with modifications including passing vtxColor by value and ripping out
3677 // testfun() definition.
3678 string makeFragmentShaderAssembly(const map<string, string>& fragments)
3680 static const char fragmentShaderBoilerplate[] =
3681 "OpCapability Shader\n"
3682 "OpMemoryModel Logical GLSL450\n"
3683 "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n"
3684 "OpExecutionMode %BP_main OriginUpperLeft\n"
3686 "OpName %BP_main \"main\"\n"
3687 "OpName %BP_fragColor \"fragColor\"\n"
3688 "OpName %BP_vtxColor \"vtxColor\"\n"
3689 "OpName %test_code \"testfun(vf4;\"\n"
3690 "OpDecorate %BP_fragColor Location 0\n"
3691 "OpDecorate %BP_vtxColor Location 1\n"
3692 "${decoration:opt}\n"
3693 SPIRV_ASSEMBLY_TYPES
3694 SPIRV_ASSEMBLY_CONSTANTS
3695 SPIRV_ASSEMBLY_ARRAYS
3696 "%BP_fragColor = OpVariable %op_v4f32 Output\n"
3697 "%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
3699 "%BP_main = OpFunction %void None %fun\n"
3700 "%BP_label_main = OpLabel\n"
3701 "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
3702 "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
3703 "OpStore %BP_fragColor %BP_tmp2\n"
3707 return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments);
3710 // Creates fragments that specialize into a simple pass-through shader (of any kind).
3711 map<string, string> passthruFragments(void)
3713 map<string, string> fragments;
3714 fragments["testfun"] =
3715 // A %test_code function that returns its argument unchanged.
3716 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3717 "%param1 = OpFunctionParameter %v4f32\n"
3718 "%label_testfun = OpLabel\n"
3719 "OpReturnValue %param1\n"
3724 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
3725 // Vertex shader gets custom code from context, the rest are pass-through.
3726 void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context)
3728 map<string, string> passthru = passthruFragments();
3729 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments);
3730 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
3731 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
3732 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
3733 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
3736 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
3737 // Tessellation control shader gets custom code from context, the rest are
3739 void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context)
3741 map<string, string> passthru = passthruFragments();
3742 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
3743 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments);
3744 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
3745 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
3746 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
3749 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
3750 // Tessellation evaluation shader gets custom code from context, the rest are
3752 void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context)
3754 map<string, string> passthru = passthruFragments();
3755 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
3756 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
3757 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments);
3758 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
3759 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
3762 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
3763 // Geometry shader gets custom code from context, the rest are pass-through.
3764 void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context)
3766 map<string, string> passthru = passthruFragments();
3767 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
3768 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
3769 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
3770 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments);
3771 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru);
3774 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
3775 // Fragment shader gets custom code from context, the rest are pass-through.
3776 void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context)
3778 map<string, string> passthru = passthruFragments();
3779 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru);
3780 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru);
3781 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru);
3782 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(passthru);
3783 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments);
3786 void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
3788 // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional
3789 // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemeberName at some point
3790 dst.spirvAsmSources.add("module") <<
3791 "OpCapability Shader\n"
3792 "OpCapability Geometry\n"
3793 "OpCapability Tessellation\n"
3794 "OpMemoryModel Logical GLSL450\n"
3796 "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n"
3797 "OpEntryPoint Geometry %geom_main \"main\" %out_gl_position %gl_in %out_color %in_color\n"
3798 "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n"
3799 "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n"
3800 "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n"
3802 "OpExecutionMode %geom_main Triangles\n"
3803 "OpExecutionMode %geom_main Invocations 0\n"
3804 "OpExecutionMode %geom_main OutputTriangleStrip\n"
3805 "OpExecutionMode %geom_main OutputVertices 3\n"
3807 "OpExecutionMode %tessc_main OutputVertices 3\n"
3809 "OpExecutionMode %tesse_main Triangles\n"
3811 "OpExecutionMode %frag_main OriginUpperLeft\n"
3813 "; Vertex decorations\n"
3814 "OpName %vert_main \"main\"\n"
3815 "OpName %vert_vtxPosition \"vtxPosition\"\n"
3816 "OpName %vert_Position \"position\"\n"
3817 "OpName %vert_vtxColor \"vtxColor\"\n"
3818 "OpName %vert_color \"color\"\n"
3819 "OpName %vert_vertex_id \"gl_VertexID\"\n"
3820 "OpName %vert_instance_id \"gl_InstanceID\"\n"
3821 "OpDecorate %vert_vtxPosition Location 2\n"
3822 "OpDecorate %vert_Position Location 0\n"
3823 "OpDecorate %vert_vtxColor Location 1\n"
3824 "OpDecorate %vert_color Location 1\n"
3825 "OpDecorate %vert_vertex_id BuiltIn VertexId\n"
3826 "OpDecorate %vert_instance_id BuiltIn InstanceId\n"
3828 "; Geometry decorations\n"
3829 "OpName %geom_main \"main\"\n"
3830 "OpName %per_vertex_in \"gl_PerVertex\"\n"
3831 "OpMemberName %per_vertex_in 0 \"gl_Position\"\n"
3832 "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n"
3833 "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n"
3834 "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n"
3835 "OpName %gl_in \"gl_in\"\n"
3836 "OpName %out_color \"out_color\"\n"
3837 "OpName %in_color \"in_color\"\n"
3838 "OpDecorate %out_gl_position BuiltIn Position\n"
3839 "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
3840 "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
3841 "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
3842 "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
3843 "OpDecorate %per_vertex_in Block\n"
3844 "OpDecorate %out_color Location 1\n"
3845 "OpDecorate %out_color Stream 0\n"
3846 "OpDecorate %in_color Location 1\n"
3848 "; Tessellation Control decorations\n"
3849 "OpName %tessc_main \"main\"\n"
3850 "OpName %tessc_out_color \"out_color\"\n"
3851 "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n"
3852 "OpName %tessc_in_color \"in_color\"\n"
3853 "OpName %tessc_out_position \"out_position\"\n"
3854 "OpName %tessc_in_position \"in_position\"\n"
3855 "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
3856 "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n"
3857 "OpDecorate %tessc_out_color Location 1\n"
3858 "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n"
3859 "OpDecorate %tessc_in_color Location 1\n"
3860 "OpDecorate %tessc_out_position Location 2\n"
3861 "OpDecorate %tessc_in_position Location 2\n"
3862 "OpDecorate %tessc_gl_TessLevelOuter Patch\n"
3863 "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
3864 "OpDecorate %tessc_gl_TessLevelInner Patch\n"
3865 "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n"
3867 "; Tessellation Evaluation decorations\n"
3868 "OpName %tesse_main \"main\"\n"
3869 "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n"
3870 "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n"
3871 "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n"
3872 "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n"
3873 "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n"
3874 "OpName %tesse_stream \"\"\n"
3875 "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n"
3876 "OpName %tesse_in_position \"in_position\"\n"
3877 "OpName %tesse_out_color \"out_color\"\n"
3878 "OpName %tesse_in_color \"in_color\"\n"
3879 "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n"
3880 "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n"
3881 "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n"
3882 "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n"
3883 "OpDecorate %tesse_per_vertex_out Block\n"
3884 "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n"
3885 "OpDecorate %tesse_in_position Location 2\n"
3886 "OpDecorate %tesse_out_color Location 1\n"
3887 "OpDecorate %tesse_in_color Location 1\n"
3889 "; Fragment decorations\n"
3890 "OpName %frag_main \"main\"\n"
3891 "OpName %frag_fragColor \"fragColor\"\n"
3892 "OpName %frag_vtxColor \"vtxColor\"\n"
3893 "OpDecorate %frag_fragColor Location 0\n"
3894 "OpDecorate %frag_vtxColor Location 1\n"
3896 SPIRV_ASSEMBLY_TYPES
3897 SPIRV_ASSEMBLY_CONSTANTS
3898 SPIRV_ASSEMBLY_ARRAYS
3900 "; Vertex Variables\n"
3901 "%vert_vtxPosition = OpVariable %op_v4f32 Output\n"
3902 "%vert_Position = OpVariable %ip_v4f32 Input\n"
3903 "%vert_vtxColor = OpVariable %op_v4f32 Output\n"
3904 "%vert_color = OpVariable %ip_v4f32 Input\n"
3905 "%vert_vertex_id = OpVariable %ip_i32 Input\n"
3906 "%vert_instance_id = OpVariable %ip_i32 Input\n"
3908 "; Geometry Variables\n"
3909 "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
3910 "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n"
3911 "%geom_ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
3912 "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n"
3913 "%geom_out_color = OpVariable %op_v4f32 Output\n"
3914 "%geom_in_color = OpVariable %ip_a3v4f32 Input\n"
3915 "%geom_out_gl_position = OpVariable %op_v4f32 Output\n"
3917 "; Tessellation Control Variables\n"
3918 "%tessc_out_color = OpVariable %op_a3v4f32 Output\n"
3919 "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n"
3920 "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n"
3921 "%tessc_out_position = OpVariable %op_a3v4f32 Output\n"
3922 "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n"
3923 "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
3924 "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
3926 "; Tessellation Evaluation Decorations\n"
3927 "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
3928 "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n"
3929 "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n"
3930 "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
3931 "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n"
3932 "%tesse_out_color = OpVariable %op_v4f32 Output\n"
3933 "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n"
3935 "; Fragment Variables\n"
3936 "%frag_fragColor = OpVariable %op_v4f32 Output\n"
3937 "%frag_vtxColor = OpVariable %ip_v4f32 Input\n"
3940 "%vert_main = OpFunction %void None %fun\n"
3941 "%vert_label = OpLabel\n"
3942 "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n"
3943 "OpStore %vert_vtxPosition %vert_tmp_position\n"
3944 "%vert_tmp_color = OpLoad %v4f32 %vert_color\n"
3945 "OpStore %vert_vtxColor %vert_tmp_color\n"
3949 "; Geometry Entry\n"
3950 "%geom_main = OpFunction %void None %fun\n"
3951 "%geom_label = OpLabel\n"
3952 "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n"
3953 "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n"
3954 "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n"
3955 "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n"
3956 "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n"
3957 "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n"
3958 "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n"
3959 "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n"
3960 "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n"
3961 "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n"
3962 "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n"
3963 "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n"
3964 "OpStore %geom_out_gl_position %geom_in_position_0\n"
3965 "OpStore %geom_out_color %geom_in_color_0\n"
3967 "OpStore %geom_out_gl_position %geom_in_position_1\n"
3968 "OpStore %geom_out_color %geom_in_color_1\n"
3970 "OpStore %geom_out_gl_position %geom_in_position_2\n"
3971 "OpStore %geom_out_color %geom_in_color_2\n"
3977 "; Tessellation Control Entry\n"
3978 "%tessc_main = OpFunction %void None %fun\n"
3979 "%tessc_label = OpLabel\n"
3980 "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n"
3981 "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n"
3982 "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n"
3983 "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n"
3984 "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n"
3985 "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n"
3986 "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n"
3987 "OpStore %tessc_out_color_ptr %tessc_in_color_val\n"
3988 "OpStore %tessc_out_position_ptr %tessc_in_position_val\n"
3989 "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n"
3990 "OpSelectionMerge %tessc_merge_label None\n"
3991 "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n"
3992 "%tessc_first_invocation = OpLabel\n"
3993 "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n"
3994 "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n"
3995 "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n"
3996 "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n"
3997 "OpStore %tessc_tess_outer_0 %c_f32_1\n"
3998 "OpStore %tessc_tess_outer_1 %c_f32_1\n"
3999 "OpStore %tessc_tess_outer_2 %c_f32_1\n"
4000 "OpStore %tessc_tess_inner %c_f32_1\n"
4001 "OpBranch %tessc_merge_label\n"
4002 "%tessc_merge_label = OpLabel\n"
4006 "; Tessellation Evaluation Entry\n"
4007 "%tesse_main = OpFunction %void None %fun\n"
4008 "%tesse_label = OpLabel\n"
4009 "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n"
4010 "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n"
4011 "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n"
4012 "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n"
4013 "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n"
4014 "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n"
4015 "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n"
4016 "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n"
4017 "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n"
4018 "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
4019 "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
4020 "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
4021 "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %BP_tc_0 %tesse_in_pos_0\n"
4022 "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %BP_tc_1 %tesse_in_pos_1\n"
4023 "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %BP_tc_2 %tesse_in_pos_2\n"
4024 "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
4025 "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
4026 "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
4027 "OpStore %tesse_out_pos_ptr %tesse_computed_out\n"
4028 "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n"
4029 "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n"
4030 "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n"
4031 "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
4032 "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
4033 "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
4034 "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_clr_0\n"
4035 "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_clr_1\n"
4036 "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_clr_2\n"
4037 "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
4038 "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
4039 "OpStore %tesse_out_color %tesse_computed_clr\n"
4043 "; Fragment Entry\n"
4044 "%frag_main = OpFunction %void None %fun\n"
4045 "%frag_label_main = OpLabel\n"
4046 "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n"
4047 "OpStore %frag_fragColor %frag_tmp1\n"
4052 // This has two shaders of each stage. The first
4053 // is a passthrough, the second inverts the color.
4054 void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
4056 dst.spirvAsmSources.add("vert") <<
4057 // This module contains 2 vertex shaders. One that is a passthrough
4058 // and a second that inverts the color of the output (1.0 - color).
4059 "OpCapability Shader\n"
4060 "OpMemoryModel Logical GLSL450\n"
4061 "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
4062 "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
4064 "OpName %main \"frag1\"\n"
4065 "OpName %main2 \"frag2\"\n"
4066 "OpName %vtxPosition \"vtxPosition\"\n"
4067 "OpName %Position \"position\"\n"
4068 "OpName %vtxColor \"vtxColor\"\n"
4069 "OpName %color \"color\"\n"
4070 "OpName %vertex_id \"gl_VertexID\"\n"
4071 "OpName %instance_id \"gl_InstanceID\"\n"
4072 "OpName %test_code \"testfun(vf4;\"\n"
4074 "OpDecorate %vtxPosition Location 2\n"
4075 "OpDecorate %Position Location 0\n"
4076 "OpDecorate %vtxColor Location 1\n"
4077 "OpDecorate %color Location 1\n"
4078 "OpDecorate %vertex_id BuiltIn VertexId\n"
4079 "OpDecorate %instance_id BuiltIn InstanceId\n"
4080 SPIRV_ASSEMBLY_TYPES
4081 SPIRV_ASSEMBLY_CONSTANTS
4082 SPIRV_ASSEMBLY_ARRAYS
4083 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
4084 "%vtxPosition = OpVariable %op_v4f32 Output\n"
4085 "%Position = OpVariable %ip_v4f32 Input\n"
4086 "%vtxColor = OpVariable %op_v4f32 Output\n"
4087 "%color = OpVariable %ip_v4f32 Input\n"
4088 "%vertex_id = OpVariable %ip_i32 Input\n"
4089 "%instance_id = OpVariable %ip_i32 Input\n"
4091 "%main = OpFunction %void None %fun\n"
4092 "%label = OpLabel\n"
4093 "%tmp_position = OpLoad %v4f32 %Position\n"
4094 "OpStore %vtxPosition %tmp_position\n"
4095 "%tmp_color = OpLoad %v4f32 %color\n"
4096 "OpStore %vtxColor %tmp_color\n"
4100 "%main2 = OpFunction %void None %fun\n"
4101 "%label2 = OpLabel\n"
4102 "%tmp_position2 = OpLoad %v4f32 %Position\n"
4103 "OpStore %vtxPosition %tmp_position2\n"
4104 "%tmp_color2 = OpLoad %v4f32 %color\n"
4105 "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
4106 "OpStore %vtxColor %tmp_color3\n"
4110 dst.spirvAsmSources.add("frag") <<
4111 // This is a single module that contains 2 fragment shaders.
4112 // One that passes color through and the other that inverts the output
4113 // color (1.0 - color).
4114 "OpCapability Shader\n"
4115 "OpMemoryModel Logical GLSL450\n"
4116 "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
4117 "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
4118 "OpExecutionMode %main OriginUpperLeft\n"
4119 "OpExecutionMode %main2 OriginUpperLeft\n"
4121 "OpName %main \"frag1\"\n"
4122 "OpName %main2 \"frag2\"\n"
4123 "OpName %fragColor \"fragColor\"\n"
4124 "OpName %vtxColor \"vtxColor\"\n"
4125 "OpDecorate %fragColor Location 0\n"
4126 "OpDecorate %vtxColor Location 1\n"
4127 SPIRV_ASSEMBLY_TYPES
4128 SPIRV_ASSEMBLY_CONSTANTS
4129 SPIRV_ASSEMBLY_ARRAYS
4130 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
4131 "%fragColor = OpVariable %op_v4f32 Output\n"
4132 "%vtxColor = OpVariable %ip_v4f32 Input\n"
4134 "%main = OpFunction %void None %fun\n"
4135 "%label_main = OpLabel\n"
4136 "%tmp1 = OpLoad %v4f32 %vtxColor\n"
4137 "OpStore %fragColor %tmp1\n"
4141 "%main2 = OpFunction %void None %fun\n"
4142 "%label_main2 = OpLabel\n"
4143 "%tmp2 = OpLoad %v4f32 %vtxColor\n"
4144 "%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
4145 "OpStore %fragColor %tmp3\n"
4149 dst.spirvAsmSources.add("geom") <<
4150 "OpCapability Geometry\n"
4151 "OpMemoryModel Logical GLSL450\n"
4152 "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
4153 "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
4154 "OpExecutionMode %geom1_main Triangles\n"
4155 "OpExecutionMode %geom2_main Triangles\n"
4156 "OpExecutionMode %geom1_main Invocations 0\n"
4157 "OpExecutionMode %geom2_main Invocations 0\n"
4158 "OpExecutionMode %geom1_main OutputTriangleStrip\n"
4159 "OpExecutionMode %geom2_main OutputTriangleStrip\n"
4160 "OpExecutionMode %geom1_main OutputVertices 3\n"
4161 "OpExecutionMode %geom2_main OutputVertices 3\n"
4162 "OpName %geom1_main \"geom1\"\n"
4163 "OpName %geom2_main \"geom2\"\n"
4164 "OpName %per_vertex_in \"gl_PerVertex\"\n"
4165 "OpMemberName %per_vertex_in 0 \"gl_Position\"\n"
4166 "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n"
4167 "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n"
4168 "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n"
4169 "OpName %gl_in \"gl_in\"\n"
4170 "OpName %out_color \"out_color\"\n"
4171 "OpName %in_color \"in_color\"\n"
4172 "OpDecorate %out_gl_position BuiltIn Position\n"
4173 "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
4174 "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
4175 "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
4176 "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
4177 "OpDecorate %per_vertex_in Block\n"
4178 "OpDecorate %out_color Location 1\n"
4179 "OpDecorate %out_color Stream 0\n"
4180 "OpDecorate %in_color Location 1\n"
4181 SPIRV_ASSEMBLY_TYPES
4182 SPIRV_ASSEMBLY_CONSTANTS
4183 SPIRV_ASSEMBLY_ARRAYS
4184 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
4185 "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
4186 "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
4187 "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
4188 "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
4189 "%out_color = OpVariable %op_v4f32 Output\n"
4190 "%in_color = OpVariable %ip_a3v4f32 Input\n"
4191 "%out_gl_position = OpVariable %op_v4f32 Output\n"
4193 "%geom1_main = OpFunction %void None %fun\n"
4194 "%geom1_label = OpLabel\n"
4195 "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
4196 "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
4197 "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
4198 "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
4199 "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
4200 "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
4201 "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
4202 "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
4203 "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
4204 "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
4205 "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
4206 "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
4207 "OpStore %out_gl_position %geom1_in_position_0\n"
4208 "OpStore %out_color %geom1_in_color_0\n"
4210 "OpStore %out_gl_position %geom1_in_position_1\n"
4211 "OpStore %out_color %geom1_in_color_1\n"
4213 "OpStore %out_gl_position %geom1_in_position_2\n"
4214 "OpStore %out_color %geom1_in_color_2\n"
4220 "%geom2_main = OpFunction %void None %fun\n"
4221 "%geom2_label = OpLabel\n"
4222 "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
4223 "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
4224 "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
4225 "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
4226 "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
4227 "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
4228 "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
4229 "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
4230 "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
4231 "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
4232 "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
4233 "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
4234 "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
4235 "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
4236 "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
4237 "OpStore %out_gl_position %geom2_in_position_0\n"
4238 "OpStore %out_color %geom2_transformed_in_color_0\n"
4240 "OpStore %out_gl_position %geom2_in_position_1\n"
4241 "OpStore %out_color %geom2_transformed_in_color_1\n"
4243 "OpStore %out_gl_position %geom2_in_position_2\n"
4244 "OpStore %out_color %geom2_transformed_in_color_2\n"
4250 dst.spirvAsmSources.add("tessc") <<
4251 "OpCapability Tessellation\n"
4252 "OpMemoryModel Logical GLSL450\n"
4253 "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
4254 "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
4255 "OpExecutionMode %tessc1_main OutputVertices 3\n"
4256 "OpExecutionMode %tessc2_main OutputVertices 3\n"
4257 "OpName %tessc1_main \"tessc1\"\n"
4258 "OpName %tessc2_main \"tessc2\"\n"
4259 "OpName %out_color \"out_color\"\n"
4260 "OpName %gl_InvocationID \"gl_InvocationID\"\n"
4261 "OpName %in_color \"in_color\"\n"
4262 "OpName %out_position \"out_position\"\n"
4263 "OpName %in_position \"in_position\"\n"
4264 "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
4265 "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n"
4266 "OpDecorate %out_color Location 1\n"
4267 "OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
4268 "OpDecorate %in_color Location 1\n"
4269 "OpDecorate %out_position Location 2\n"
4270 "OpDecorate %in_position Location 2\n"
4271 "OpDecorate %gl_TessLevelOuter Patch\n"
4272 "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
4273 "OpDecorate %gl_TessLevelInner Patch\n"
4274 "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
4275 SPIRV_ASSEMBLY_TYPES
4276 SPIRV_ASSEMBLY_CONSTANTS
4277 SPIRV_ASSEMBLY_ARRAYS
4278 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
4279 "%out_color = OpVariable %op_a3v4f32 Output\n"
4280 "%gl_InvocationID = OpVariable %ip_i32 Input\n"
4281 "%in_color = OpVariable %ip_a32v4f32 Input\n"
4282 "%out_position = OpVariable %op_a3v4f32 Output\n"
4283 "%in_position = OpVariable %ip_a32v4f32 Input\n"
4284 "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
4285 "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
4287 "%tessc1_main = OpFunction %void None %fun\n"
4288 "%tessc1_label = OpLabel\n"
4289 "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
4290 "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
4291 "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
4292 "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
4293 "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
4294 "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
4295 "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
4296 "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
4297 "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
4298 "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
4299 "OpSelectionMerge %tessc1_merge_label None\n"
4300 "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
4301 "%tessc1_first_invocation = OpLabel\n"
4302 "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
4303 "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
4304 "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
4305 "%tessc1_tess_inner = OpAccessChain %op_f32 %tessc1_gl_TessLevelInner %c_i32_0\n"
4306 "OpStore %tessc1_tess_outer_0 %c_f32_1\n"
4307 "OpStore %tessc1_tess_outer_1 %c_f32_1\n"
4308 "OpStore %tessc1_tess_outer_2 %c_f32_1\n"
4309 "OpStore %tessc1_tess_inner %c_f32_1\n"
4310 "OpBranch %tessc1_merge_label\n"
4311 "%tessc1_merge_label = OpLabel\n"
4315 "%tessc2_main = OpFunction %void None %fun\n"
4316 "%tessc2_label = OpLabel\n"
4317 "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
4318 "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
4319 "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
4320 "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
4321 "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
4322 "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
4323 "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
4324 "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
4325 "OpStore %tessc2_out_color_ptr %tessc2_transformed_color\n"
4326 "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
4327 "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
4328 "OpSelectionMerge %tessc2_merge_label None\n"
4329 "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
4330 "%tessc2_first_invocation = OpLabel\n"
4331 "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
4332 "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
4333 "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
4334 "%tessc2_tess_inner = OpAccessChain %op_f32 %tessc2_gl_TessLevelInner %c_i32_0\n"
4335 "OpStore %tessc2_tess_outer_0 %c_f32_1\n"
4336 "OpStore %tessc2_tess_outer_1 %c_f32_1\n"
4337 "OpStore %tessc2_tess_outer_2 %c_f32_1\n"
4338 "OpStore %tessc2_tess_inner %c_f32_1\n"
4339 "OpBranch %tessc2_merge_label\n"
4340 "%tessc2_merge_label = OpLabel\n"
4344 dst.spirvAsmSources.add("tesse") <<
4345 "OpCapability Tessellation\n"
4346 "OpMemoryModel Logical GLSL450\n"
4347 "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
4348 "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
4349 "OpExecutionMode %tesse1_main Triangles\n"
4350 "OpExecutionMode %tesse2_main Triangles\n"
4351 "OpName %tesse1_main \"tesse1\"\n"
4352 "OpName %tesse2_main \"tesse2\"\n"
4353 "OpName %per_vertex_out \"gl_PerVertex\"\n"
4354 "OpMemberName %per_vertex_out 0 \"gl_Position\"\n"
4355 "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n"
4356 "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n"
4357 "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n"
4358 "OpName %stream \"\"\n"
4359 "OpName %gl_tessCoord \"gl_TessCoord\"\n"
4360 "OpName %in_position \"in_position\"\n"
4361 "OpName %out_color \"out_color\"\n"
4362 "OpName %in_color \"in_color\"\n"
4363 "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
4364 "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
4365 "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
4366 "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
4367 "OpDecorate %per_vertex_out Block\n"
4368 "OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
4369 "OpDecorate %in_position Location 2\n"
4370 "OpDecorate %out_color Location 1\n"
4371 "OpDecorate %in_color Location 1\n"
4372 SPIRV_ASSEMBLY_TYPES
4373 SPIRV_ASSEMBLY_CONSTANTS
4374 SPIRV_ASSEMBLY_ARRAYS
4375 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
4376 "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
4377 "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
4378 "%stream = OpVariable %op_per_vertex_out Output\n"
4379 "%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
4380 "%in_position = OpVariable %ip_a32v4f32 Input\n"
4381 "%out_color = OpVariable %op_v4f32 Output\n"
4382 "%in_color = OpVariable %ip_a32v4f32 Input\n"
4384 "%tesse1_main = OpFunction %void None %fun\n"
4385 "%tesse1_label = OpLabel\n"
4386 "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
4387 "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
4388 "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
4389 "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
4390 "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
4391 "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
4392 "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
4393 "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
4394 "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
4395 "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
4396 "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
4397 "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
4398 "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_pos_0\n"
4399 "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_pos_1\n"
4400 "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_pos_2\n"
4401 "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
4402 "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
4403 "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
4404 "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
4405 "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
4406 "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
4407 "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
4408 "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
4409 "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
4410 "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
4411 "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %in_clr_0\n"
4412 "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %in_clr_1\n"
4413 "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %in_clr_2\n"
4414 "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
4415 "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
4416 "OpStore %out_color %tesse1_computed_clr\n"
4420 "%tesse2_main = OpFunction %void None %fun\n"
4421 "%tesse2_label = OpLabel\n"
4422 "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
4423 "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
4424 "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
4425 "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
4426 "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
4427 "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
4428 "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
4429 "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
4430 "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
4431 "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
4432 "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
4433 "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
4434 "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_pos_0\n"
4435 "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_pos_1\n"
4436 "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_pos_2\n"
4437 "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
4438 "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
4439 "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
4440 "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
4441 "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
4442 "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
4443 "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
4444 "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
4445 "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
4446 "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
4447 "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %in_clr_0\n"
4448 "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %in_clr_1\n"
4449 "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %in_clr_2\n"
4450 "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
4451 "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
4452 "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
4453 "OpStore %out_color %tesse2_clr_transformed\n"
4458 // Sets up and runs a Vulkan pipeline, then spot-checks the resulting image.
4459 // Feeds the pipeline a set of colored triangles, which then must occur in the
4460 // rendered image. The surface is cleared before executing the pipeline, so
4461 // whatever the shaders draw can be directly spot-checked.
4462 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
4464 const VkDevice vkDevice = context.getDevice();
4465 const DeviceInterface& vk = context.getDeviceInterface();
4466 const VkQueue queue = context.getUniversalQueue();
4467 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
4468 const tcu::IVec2 renderSize (256, 256);
4469 vector<ModuleHandleSp> modules;
4470 map<VkShaderStageFlagBits, VkShaderModule> moduleByStage;
4471 const int testSpecificSeed = 31354125;
4472 const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
4473 de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
4474 de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
4475 const Vec4 vertexData[] =
4477 // Upper left corner:
4478 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
4479 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
4480 Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
4482 // Upper right corner:
4483 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
4484 Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
4485 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
4487 // Lower left corner:
4488 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
4489 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
4490 Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
4492 // Lower right corner:
4493 Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
4494 Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
4495 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec()
4497 const size_t singleVertexDataSize = 2 * sizeof(Vec4);
4498 const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize;
4500 const VkBufferCreateInfo vertexBufferParams =
4502 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
4503 DE_NULL, // const void* pNext;
4504 0u, // VkBufferCreateFlags flags;
4505 (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size;
4506 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
4507 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
4508 1u, // deUint32 queueFamilyCount;
4509 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
4511 const Unique<VkBuffer> vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams));
4512 const UniquePtr<Allocation> vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
4514 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
4516 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
4517 const VkBufferCreateInfo readImageBufferParams =
4519 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
4520 DE_NULL, // const void* pNext;
4521 0u, // VkBufferCreateFlags flags;
4522 imageSizeBytes, // VkDeviceSize size;
4523 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
4524 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
4525 1u, // deUint32 queueFamilyCount;
4526 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
4528 const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams));
4529 const UniquePtr<Allocation> readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
4531 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
4533 const VkImageCreateInfo imageParams =
4535 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
4536 DE_NULL, // const void* pNext;
4537 0u, // VkImageCreateFlags flags;
4538 VK_IMAGE_TYPE_2D, // VkImageType imageType;
4539 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
4540 { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent;
4541 1u, // deUint32 mipLevels;
4542 1u, // deUint32 arraySize;
4543 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
4544 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
4545 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
4546 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
4547 1u, // deUint32 queueFamilyCount;
4548 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
4549 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
4552 const Unique<VkImage> image (createImage(vk, vkDevice, &imageParams));
4553 const UniquePtr<Allocation> imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any));
4555 VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
4557 const VkAttachmentDescription colorAttDesc =
4559 0u, // VkAttachmentDescriptionFlags flags;
4560 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
4561 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
4562 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
4563 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
4564 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
4565 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
4566 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
4567 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
4569 const VkAttachmentReference colorAttRef =
4571 0u, // deUint32 attachment;
4572 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
4574 const VkSubpassDescription subpassDesc =
4576 0u, // VkSubpassDescriptionFlags flags;
4577 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
4578 0u, // deUint32 inputCount;
4579 DE_NULL, // const VkAttachmentReference* pInputAttachments;
4580 1u, // deUint32 colorCount;
4581 &colorAttRef, // const VkAttachmentReference* pColorAttachments;
4582 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
4583 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
4584 0u, // deUint32 preserveCount;
4585 DE_NULL, // const VkAttachmentReference* pPreserveAttachments;
4588 const VkRenderPassCreateInfo renderPassParams =
4590 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
4591 DE_NULL, // const void* pNext;
4592 (VkRenderPassCreateFlags)0,
4593 1u, // deUint32 attachmentCount;
4594 &colorAttDesc, // const VkAttachmentDescription* pAttachments;
4595 1u, // deUint32 subpassCount;
4596 &subpassDesc, // const VkSubpassDescription* pSubpasses;
4597 0u, // deUint32 dependencyCount;
4598 DE_NULL, // const VkSubpassDependency* pDependencies;
4600 const Unique<VkRenderPass> renderPass (createRenderPass(vk, vkDevice, &renderPassParams));
4602 const VkImageViewCreateInfo colorAttViewParams =
4604 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
4605 DE_NULL, // const void* pNext;
4606 0u, // VkImageViewCreateFlags flags;
4607 *image, // VkImage image;
4608 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
4609 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
4611 VK_COMPONENT_SWIZZLE_R,
4612 VK_COMPONENT_SWIZZLE_G,
4613 VK_COMPONENT_SWIZZLE_B,
4614 VK_COMPONENT_SWIZZLE_A
4615 }, // VkChannelMapping channels;
4617 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
4618 0u, // deUint32 baseMipLevel;
4619 1u, // deUint32 mipLevels;
4620 0u, // deUint32 baseArrayLayer;
4621 1u, // deUint32 arraySize;
4622 }, // VkImageSubresourceRange subresourceRange;
4624 const Unique<VkImageView> colorAttView (createImageView(vk, vkDevice, &colorAttViewParams));
4628 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
4630 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
4631 DE_NULL, // const void* pNext;
4632 (VkPipelineLayoutCreateFlags)0,
4633 0u, // deUint32 descriptorSetCount;
4634 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
4635 0u, // deUint32 pushConstantRangeCount;
4636 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
4638 const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
4641 vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
4642 // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
4643 vector<vector<VkSpecializationMapEntry> > specConstantEntries;
4644 vector<VkSpecializationInfo> specializationInfos;
4645 createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams);
4647 // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
4648 specConstantEntries.reserve(shaderStageParams.size());
4649 specializationInfos.reserve(shaderStageParams.size());
4651 // Patch the specialization info field in PipelineShaderStageCreateInfos.
4652 for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
4654 const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
4656 if (stageIt != instance.specConstants.end())
4658 const size_t numSpecConstants = stageIt->second.size();
4659 vector<VkSpecializationMapEntry> entries;
4660 VkSpecializationInfo specInfo;
4662 entries.reserve(numSpecConstants);
4664 // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0.
4665 for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
4667 entries[ndx].constantID = (deUint32)ndx;
4668 entries[ndx].offset = deUint32(ndx * sizeof(deInt32));
4669 entries[ndx].size = sizeof(deInt32);
4672 specConstantEntries.push_back(entries);
4674 specInfo.mapEntryCount = (deUint32)numSpecConstants;
4675 specInfo.pMapEntries = specConstantEntries.back().data();
4676 specInfo.dataSize = numSpecConstants * sizeof(deInt32);
4677 specInfo.pData = stageIt->second.data();
4678 specializationInfos.push_back(specInfo);
4680 stageInfo->pSpecializationInfo = &specializationInfos.back();
4683 const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
4685 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
4686 DE_NULL, // const void* pNext;
4687 (VkPipelineDepthStencilStateCreateFlags)0,
4688 DE_FALSE, // deUint32 depthTestEnable;
4689 DE_FALSE, // deUint32 depthWriteEnable;
4690 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
4691 DE_FALSE, // deUint32 depthBoundsTestEnable;
4692 DE_FALSE, // deUint32 stencilTestEnable;
4694 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
4695 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
4696 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
4697 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
4698 0u, // deUint32 stencilCompareMask;
4699 0u, // deUint32 stencilWriteMask;
4700 0u, // deUint32 stencilReference;
4701 }, // VkStencilOpState front;
4703 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
4704 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
4705 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
4706 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
4707 0u, // deUint32 stencilCompareMask;
4708 0u, // deUint32 stencilWriteMask;
4709 0u, // deUint32 stencilReference;
4710 }, // VkStencilOpState back;
4711 -1.0f, // float minDepthBounds;
4712 +1.0f, // float maxDepthBounds;
4714 const VkViewport viewport0 =
4716 0.0f, // float originX;
4717 0.0f, // float originY;
4718 (float)renderSize.x(), // float width;
4719 (float)renderSize.y(), // float height;
4720 0.0f, // float minDepth;
4721 1.0f, // float maxDepth;
4723 const VkRect2D scissor0 =
4728 }, // VkOffset2D offset;
4730 renderSize.x(), // deInt32 width;
4731 renderSize.y(), // deInt32 height;
4732 }, // VkExtent2D extent;
4734 const VkPipelineViewportStateCreateInfo viewportParams =
4736 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
4737 DE_NULL, // const void* pNext;
4738 (VkPipelineViewportStateCreateFlags)0,
4739 1u, // deUint32 viewportCount;
4744 const VkSampleMask sampleMask = ~0u;
4745 const VkPipelineMultisampleStateCreateInfo multisampleParams =
4747 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
4748 DE_NULL, // const void* pNext;
4749 (VkPipelineMultisampleStateCreateFlags)0,
4750 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples;
4751 DE_FALSE, // deUint32 sampleShadingEnable;
4752 0.0f, // float minSampleShading;
4753 &sampleMask, // const VkSampleMask* pSampleMask;
4754 DE_FALSE, // VkBool32 alphaToCoverageEnable;
4755 DE_FALSE, // VkBool32 alphaToOneEnable;
4757 const VkPipelineRasterizationStateCreateInfo rasterParams =
4759 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
4760 DE_NULL, // const void* pNext;
4761 (VkPipelineRasterizationStateCreateFlags)0,
4762 DE_TRUE, // deUint32 depthClipEnable;
4763 DE_FALSE, // deUint32 rasterizerDiscardEnable;
4764 VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
4765 VK_CULL_MODE_NONE, // VkCullMode cullMode;
4766 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
4767 VK_FALSE, // VkBool32 depthBiasEnable;
4768 0.0f, // float depthBias;
4769 0.0f, // float depthBiasClamp;
4770 0.0f, // float slopeScaledDepthBias;
4771 1.0f, // float lineWidth;
4773 const VkPrimitiveTopology topology = instance.hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
4774 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
4776 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
4777 DE_NULL, // const void* pNext;
4778 (VkPipelineInputAssemblyStateCreateFlags)0,
4779 topology, // VkPrimitiveTopology topology;
4780 DE_FALSE, // deUint32 primitiveRestartEnable;
4782 const VkVertexInputBindingDescription vertexBinding0 =
4784 0u, // deUint32 binding;
4785 deUint32(singleVertexDataSize), // deUint32 strideInBytes;
4786 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
4788 const VkVertexInputAttributeDescription vertexAttrib0[2] =
4791 0u, // deUint32 location;
4792 0u, // deUint32 binding;
4793 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
4794 0u // deUint32 offsetInBytes;
4797 1u, // deUint32 location;
4798 0u, // deUint32 binding;
4799 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
4800 sizeof(Vec4), // deUint32 offsetInBytes;
4804 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
4806 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
4807 DE_NULL, // const void* pNext;
4808 (VkPipelineVertexInputStateCreateFlags)0,
4809 1u, // deUint32 bindingCount;
4810 &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
4811 2u, // deUint32 attributeCount;
4812 vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
4814 const VkPipelineColorBlendAttachmentState attBlendParams =
4816 DE_FALSE, // deUint32 blendEnable;
4817 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
4818 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
4819 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
4820 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
4821 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
4822 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
4823 (VK_COLOR_COMPONENT_R_BIT|
4824 VK_COLOR_COMPONENT_G_BIT|
4825 VK_COLOR_COMPONENT_B_BIT|
4826 VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask;
4828 const VkPipelineColorBlendStateCreateInfo blendParams =
4830 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
4831 DE_NULL, // const void* pNext;
4832 (VkPipelineColorBlendStateCreateFlags)0,
4833 DE_FALSE, // VkBool32 logicOpEnable;
4834 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
4835 1u, // deUint32 attachmentCount;
4836 &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments;
4837 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
4839 const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
4841 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
4842 DE_NULL, // const void* pNext;
4843 (VkPipelineDynamicStateCreateFlags)0,
4844 0u, // deUint32 dynamicStateCount;
4845 DE_NULL // const VkDynamicState* pDynamicStates;
4848 const VkPipelineTessellationStateCreateInfo tessellationState =
4850 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
4852 (VkPipelineTesselationStateCreateFlags)0,
4856 const VkPipelineTessellationStateCreateInfo* tessellationInfo = instance.hasTessellation? &tessellationState: DE_NULL;
4857 const VkGraphicsPipelineCreateInfo pipelineParams =
4859 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
4860 DE_NULL, // const void* pNext;
4861 0u, // VkPipelineCreateFlags flags;
4862 (deUint32)shaderStageParams.size(), // deUint32 stageCount;
4863 &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages;
4864 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
4865 &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
4866 tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
4867 &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
4868 &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
4869 &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
4870 &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
4871 &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
4872 &dynamicStateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
4873 *pipelineLayout, // VkPipelineLayout layout;
4874 *renderPass, // VkRenderPass renderPass;
4875 0u, // deUint32 subpass;
4876 DE_NULL, // VkPipeline basePipelineHandle;
4877 0u, // deInt32 basePipelineIndex;
4880 const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams));
4883 const VkFramebufferCreateInfo framebufferParams =
4885 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
4886 DE_NULL, // const void* pNext;
4887 (VkFramebufferCreateFlags)0,
4888 *renderPass, // VkRenderPass renderPass;
4889 1u, // deUint32 attachmentCount;
4890 &*colorAttView, // const VkImageView* pAttachments;
4891 (deUint32)renderSize.x(), // deUint32 width;
4892 (deUint32)renderSize.y(), // deUint32 height;
4893 1u, // deUint32 layers;
4895 const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams));
4897 const VkCommandPoolCreateInfo cmdPoolParams =
4899 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
4900 DE_NULL, // const void* pNext;
4901 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCmdPoolCreateFlags flags;
4902 queueFamilyIndex, // deUint32 queueFamilyIndex;
4904 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
4907 const VkCommandBufferAllocateInfo cmdBufParams =
4909 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
4910 DE_NULL, // const void* pNext;
4911 *cmdPool, // VkCmdPool pool;
4912 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
4913 1u, // deUint32 count;
4915 const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
4917 const VkCommandBufferBeginInfo cmdBufBeginParams =
4919 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
4920 DE_NULL, // const void* pNext;
4921 (VkCommandBufferUsageFlags)0,
4922 DE_NULL, // VkRenderPass renderPass;
4923 0u, // deUint32 subpass;
4924 DE_NULL, // VkFramebuffer framebuffer;
4925 VK_FALSE, // VkBool32 occlusionQueryEnable;
4926 (VkQueryControlFlags)0,
4927 (VkQueryPipelineStatisticFlags)0,
4931 VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
4934 const VkMemoryBarrier vertFlushBarrier =
4936 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
4937 DE_NULL, // const void* pNext;
4938 VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask;
4939 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask;
4941 const VkImageMemoryBarrier colorAttBarrier =
4943 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
4944 DE_NULL, // const void* pNext;
4945 0u, // VkMemoryOutputFlags outputMask;
4946 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask;
4947 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
4948 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
4949 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
4950 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
4951 *image, // VkImage image;
4953 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
4954 0u, // deUint32 baseMipLevel;
4955 1u, // deUint32 mipLevels;
4956 0u, // deUint32 baseArraySlice;
4957 1u, // deUint32 arraySize;
4958 } // VkImageSubresourceRange subresourceRange;
4960 const void* barriers[] = { &vertFlushBarrier, &colorAttBarrier };
4961 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
4965 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
4966 const VkRenderPassBeginInfo passBeginParams =
4968 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
4969 DE_NULL, // const void* pNext;
4970 *renderPass, // VkRenderPass renderPass;
4971 *framebuffer, // VkFramebuffer framebuffer;
4972 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea;
4973 1u, // deUint32 clearValueCount;
4974 &clearValue, // const VkClearValue* pClearValues;
4976 vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
4979 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
4981 const VkDeviceSize bindingOffset = 0;
4982 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
4984 vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
4985 vk.cmdEndRenderPass(*cmdBuf);
4988 const VkImageMemoryBarrier renderFinishBarrier =
4990 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
4991 DE_NULL, // const void* pNext;
4992 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask;
4993 VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask;
4994 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
4995 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
4996 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
4997 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
4998 *image, // VkImage image;
5000 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
5001 0u, // deUint32 baseMipLevel;
5002 1u, // deUint32 mipLevels;
5003 0u, // deUint32 baseArraySlice;
5004 1u, // deUint32 arraySize;
5005 } // VkImageSubresourceRange subresourceRange;
5007 const void* barriers[] = { &renderFinishBarrier };
5008 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
5012 const VkBufferImageCopy copyParams =
5014 (VkDeviceSize)0u, // VkDeviceSize bufferOffset;
5015 (deUint32)renderSize.x(), // deUint32 bufferRowLength;
5016 (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
5018 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
5019 0u, // deUint32 mipLevel;
5020 0u, // deUint32 arrayLayer;
5021 1u, // deUint32 arraySize;
5022 }, // VkImageSubresourceCopy imageSubresource;
5023 { 0u, 0u, 0u }, // VkOffset3D imageOffset;
5024 { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent;
5026 vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
5030 const VkBufferMemoryBarrier copyFinishBarrier =
5032 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
5033 DE_NULL, // const void* pNext;
5034 VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask;
5035 VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask;
5036 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
5037 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
5038 *readImageBuffer, // VkBuffer buffer;
5039 0u, // VkDeviceSize offset;
5040 imageSizeBytes // VkDeviceSize size;
5042 const void* barriers[] = { ©FinishBarrier };
5043 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, DE_FALSE, (deUint32)DE_LENGTH_OF_ARRAY(barriers), barriers);
5046 VK_CHECK(vk.endCommandBuffer(*cmdBuf));
5048 // Upload vertex data
5050 const VkMappedMemoryRange range =
5052 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
5053 DE_NULL, // const void* pNext;
5054 vertexBufferMemory->getMemory(), // VkDeviceMemory mem;
5055 0, // VkDeviceSize offset;
5056 (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size;
5058 void* vertexBufPtr = vertexBufferMemory->getHostPtr();
5060 deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData));
5061 VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range));
5064 // Submit & wait for completion
5066 const VkFenceCreateInfo fenceParams =
5068 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
5069 DE_NULL, // const void* pNext;
5070 0u, // VkFenceCreateFlags flags;
5072 const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams));
5073 const VkSubmitInfo submitInfo =
5075 VK_STRUCTURE_TYPE_SUBMIT_INFO,
5078 (const VkSemaphore*)DE_NULL,
5082 (const VkSemaphore*)DE_NULL,
5085 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
5086 VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
5089 const void* imagePtr = readImageBufferMemory->getHostPtr();
5090 const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
5091 renderSize.x(), renderSize.y(), 1, imagePtr);
5094 const VkMappedMemoryRange range =
5096 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
5097 DE_NULL, // const void* pNext;
5098 readImageBufferMemory->getMemory(), // VkDeviceMemory mem;
5099 0, // VkDeviceSize offset;
5100 imageSizeBytes, // VkDeviceSize size;
5103 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
5104 context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
5107 const RGBA threshold(1, 1, 1, 1);
5108 const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
5109 if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
5110 return TestStatus::fail("Upper left corner mismatch");
5112 const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
5113 if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
5114 return TestStatus::fail("Upper right corner mismatch");
5116 const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
5117 if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
5118 return TestStatus::fail("Lower left corner mismatch");
5120 const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
5121 if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
5122 return TestStatus::fail("Lower right corner mismatch");
5124 return TestStatus::pass("Rendered output matches input");
5127 void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, const vector<deInt32>& specConstants, tcu::TestCaseGroup* tests)
5129 const ShaderElement pipelineStages[] =
5131 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
5132 ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
5133 ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
5134 ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
5135 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
5138 StageToSpecConstantMap specConstantMap;
5140 specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants;
5141 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
5142 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap));
5144 specConstantMap.clear();
5145 specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants;
5146 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
5147 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap));
5149 specConstantMap.clear();
5150 specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants;
5151 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
5152 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap));
5154 specConstantMap.clear();
5155 specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants;
5156 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
5157 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap));
5159 specConstantMap.clear();
5160 specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants;
5161 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "-frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
5162 createInstanceContext(pipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap));
5165 inline void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, tcu::TestCaseGroup* tests)
5167 vector<deInt32> noSpecConstants;
5168 createTestsForAllStages(name, inputColors, outputColors, testCodeFragments, noSpecConstants, tests);
5173 tcu::TestCaseGroup* createOpSourceTests (tcu::TestContext& testCtx)
5175 struct NameCodePair { string name, code; };
5176 RGBA defaultColors[4];
5177 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsource", "OpSource instruction"));
5178 const std::string opsourceGLSLWithFile = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile ";
5179 map<string, string> fragments = passthruFragments();
5180 const NameCodePair tests[] =
5182 {"unknown", "OpSource Unknown 321"},
5183 {"essl", "OpSource ESSL 310"},
5184 {"glsl", "OpSource GLSL 450"},
5185 {"opencl_cpp", "OpSource OpenCL_CPP 120"},
5186 {"opencl_c", "OpSource OpenCL_C 120"},
5187 {"multiple", "OpSource GLSL 450\nOpSource GLSL 450"},
5188 {"file", opsourceGLSLWithFile},
5189 {"source", opsourceGLSLWithFile + "\"void main(){}\""},
5190 // Longest possible source string: SPIR-V limits instructions to 65535
5191 // words, of which the first 4 are opsourceGLSLWithFile; the rest will
5192 // contain 65530 UTF8 characters (one word each) plus one last word
5193 // containing 3 ASCII characters and \0.
5194 {"longsource", opsourceGLSLWithFile + '"' + makeLongUTF8String(65530) + "ccc" + '"'}
5197 getDefaultColors(defaultColors);
5198 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
5200 fragments["debug"] = tests[testNdx].code;
5201 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
5204 return opSourceTests.release();
5207 tcu::TestCaseGroup* createOpSourceContinuedTests (tcu::TestContext& testCtx)
5209 struct NameCodePair { string name, code; };
5210 RGBA defaultColors[4];
5211 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsourcecontinued", "OpSourceContinued instruction"));
5212 map<string, string> fragments = passthruFragments();
5213 const std::string opsource = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile \"void main(){}\"\n";
5214 const NameCodePair tests[] =
5216 {"empty", opsource + "OpSourceContinued \"\""},
5217 {"short", opsource + "OpSourceContinued \"abcde\""},
5218 {"multiple", opsource + "OpSourceContinued \"abcde\"\nOpSourceContinued \"fghij\""},
5219 // Longest possible source string: SPIR-V limits instructions to 65535
5220 // words, of which the first one is OpSourceContinued/length; the rest
5221 // will contain 65533 UTF8 characters (one word each) plus one last word
5222 // containing 3 ASCII characters and \0.
5223 {"long", opsource + "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\""}
5226 getDefaultColors(defaultColors);
5227 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
5229 fragments["debug"] = tests[testNdx].code;
5230 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
5233 return opSourceTests.release();
5236 tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
5238 RGBA defaultColors[4];
5239 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opNoLine", "OpNoLine instruction"));
5240 map<string, string> fragments;
5241 getDefaultColors(defaultColors);
5242 fragments["debug"] =
5243 "%name = OpString \"name\"\n";
5245 fragments["pre_main"] =
5248 "OpLine %name 1 1\n"
5250 "OpLine %name 1 1\n"
5251 "OpLine %name 1 1\n"
5252 "%second_function = OpFunction %v4f32 None %v4f32_function\n"
5254 "OpLine %name 1 1\n"
5256 "OpLine %name 1 1\n"
5257 "OpLine %name 1 1\n"
5258 "%second_param1 = OpFunctionParameter %v4f32\n"
5261 "%label_secondfunction = OpLabel\n"
5263 "OpReturnValue %second_param1\n"
5268 fragments["testfun"] =
5269 // A %test_code function that returns its argument unchanged.
5272 "OpLine %name 1 1\n"
5273 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5275 "%param1 = OpFunctionParameter %v4f32\n"
5278 "%label_testfun = OpLabel\n"
5280 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
5281 "OpReturnValue %val1\n"
5283 "OpLine %name 1 1\n"
5286 createTestsForAllStages("opNoLine", defaultColors, defaultColors, fragments, opLineTests.get());
5288 return opLineTests.release();
5292 tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
5294 RGBA defaultColors[4];
5295 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opLine", "OpLine instruction"));
5296 map<string, string> fragments;
5297 std::vector<std::pair<std::string, std::string> > problemStrings;
5299 problemStrings.push_back(std::make_pair<std::string, std::string>("empty_name", ""));
5300 problemStrings.push_back(std::make_pair<std::string, std::string>("short_name", "short_name"));
5301 problemStrings.push_back(std::make_pair<std::string, std::string>("long_name", makeLongUTF8String(65530) + "ccc"));
5302 getDefaultColors(defaultColors);
5304 fragments["debug"] =
5305 "%other_name = OpString \"other_name\"\n";
5307 fragments["pre_main"] =
5308 "OpLine %file_name 32 0\n"
5309 "OpLine %file_name 32 32\n"
5310 "OpLine %file_name 32 40\n"
5311 "OpLine %other_name 32 40\n"
5312 "OpLine %other_name 0 100\n"
5313 "OpLine %other_name 0 4294967295\n"
5314 "OpLine %other_name 4294967295 0\n"
5315 "OpLine %other_name 32 40\n"
5316 "OpLine %file_name 0 0\n"
5317 "%second_function = OpFunction %v4f32 None %v4f32_function\n"
5318 "OpLine %file_name 1 0\n"
5319 "%second_param1 = OpFunctionParameter %v4f32\n"
5320 "OpLine %file_name 1 3\n"
5321 "OpLine %file_name 1 2\n"
5322 "%label_secondfunction = OpLabel\n"
5323 "OpLine %file_name 0 2\n"
5324 "OpReturnValue %second_param1\n"
5326 "OpLine %file_name 0 2\n"
5327 "OpLine %file_name 0 2\n";
5329 fragments["testfun"] =
5330 // A %test_code function that returns its argument unchanged.
5331 "OpLine %file_name 1 0\n"
5332 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5333 "OpLine %file_name 16 330\n"
5334 "%param1 = OpFunctionParameter %v4f32\n"
5335 "OpLine %file_name 14 442\n"
5336 "%label_testfun = OpLabel\n"
5337 "OpLine %file_name 11 1024\n"
5338 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
5339 "OpLine %file_name 2 97\n"
5340 "OpReturnValue %val1\n"
5342 "OpLine %file_name 5 32\n";
5344 for (size_t i = 0; i < problemStrings.size(); ++i)
5346 map<string, string> testFragments = fragments;
5347 testFragments["debug"] += "%file_name = OpString \"" + problemStrings[i].second + "\"\n";
5348 createTestsForAllStages(string("opLine") + "-" + problemStrings[i].first, defaultColors, defaultColors, testFragments, opLineTests.get());
5351 return opLineTests.release();
5354 tcu::TestCaseGroup* createOpConstantNullTests(tcu::TestContext& testCtx)
5356 de::MovePtr<tcu::TestCaseGroup> opConstantNullTests (new tcu::TestCaseGroup(testCtx, "opConstantNull", "OpConstantNull instruction"));
5360 const char functionStart[] =
5361 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5362 "%param1 = OpFunctionParameter %v4f32\n"
5365 const char functionEnd[] =
5366 "OpReturnValue %transformed_param\n"
5369 struct NameConstantsCode
5376 NameConstantsCode tests[] =
5380 "%cnull = OpConstantNull %v4f32\n",
5381 "%transformed_param = OpFAdd %v4f32 %param1 %cnull\n"
5385 "%cnull = OpConstantNull %f32\n",
5386 "%vp = OpVariable %fp_v4f32 Function\n"
5387 "%v = OpLoad %v4f32 %vp\n"
5388 "%v0 = OpVectorInsertDynamic %v4f32 %v %cnull %c_i32_0\n"
5389 "%v1 = OpVectorInsertDynamic %v4f32 %v0 %cnull %c_i32_1\n"
5390 "%v2 = OpVectorInsertDynamic %v4f32 %v1 %cnull %c_i32_2\n"
5391 "%v3 = OpVectorInsertDynamic %v4f32 %v2 %cnull %c_i32_3\n"
5392 "%transformed_param = OpFAdd %v4f32 %param1 %v3\n"
5396 "%cnull = OpConstantNull %bool\n",
5397 "%v = OpVariable %fp_v4f32 Function\n"
5398 " OpStore %v %param1\n"
5399 " OpSelectionMerge %false_label None\n"
5400 " OpBranchConditional %cnull %true_label %false_label\n"
5401 "%true_label = OpLabel\n"
5402 " OpStore %v %c_v4f32_0_5_0_5_0_5_0_5\n"
5403 " OpBranch %false_label\n"
5404 "%false_label = OpLabel\n"
5405 "%transformed_param = OpLoad %v4f32 %v\n"
5409 "%cnull = OpConstantNull %i32\n",
5410 "%v = OpVariable %fp_v4f32 Function %c_v4f32_0_5_0_5_0_5_0_5\n"
5411 "%b = OpIEqual %bool %cnull %c_i32_0\n"
5412 " OpSelectionMerge %false_label None\n"
5413 " OpBranchConditional %b %true_label %false_label\n"
5414 "%true_label = OpLabel\n"
5415 " OpStore %v %param1\n"
5416 " OpBranch %false_label\n"
5417 "%false_label = OpLabel\n"
5418 "%transformed_param = OpLoad %v4f32 %v\n"
5422 "%stype = OpTypeStruct %f32 %v4f32\n"
5423 "%fp_stype = OpTypePointer Function %stype\n"
5424 "%cnull = OpConstantNull %stype\n",
5425 "%v = OpVariable %fp_stype Function %cnull\n"
5426 "%f = OpAccessChain %fp_v4f32 %v %c_i32_1\n"
5427 "%f_val = OpLoad %v4f32 %f\n"
5428 "%transformed_param = OpFAdd %v4f32 %param1 %f_val\n"
5432 "%a4_v4f32 = OpTypeArray %v4f32 %c_u32_4\n"
5433 "%fp_a4_v4f32 = OpTypePointer Function %a4_v4f32\n"
5434 "%cnull = OpConstantNull %a4_v4f32\n",
5435 "%v = OpVariable %fp_a4_v4f32 Function %cnull\n"
5436 "%f = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
5437 "%f1 = OpAccessChain %fp_v4f32 %v %c_u32_1\n"
5438 "%f2 = OpAccessChain %fp_v4f32 %v %c_u32_2\n"
5439 "%f3 = OpAccessChain %fp_v4f32 %v %c_u32_3\n"
5440 "%f_val = OpLoad %v4f32 %f\n"
5441 "%f1_val = OpLoad %v4f32 %f1\n"
5442 "%f2_val = OpLoad %v4f32 %f2\n"
5443 "%f3_val = OpLoad %v4f32 %f3\n"
5444 "%t0 = OpFAdd %v4f32 %param1 %f_val\n"
5445 "%t1 = OpFAdd %v4f32 %t0 %f1_val\n"
5446 "%t2 = OpFAdd %v4f32 %t1 %f2_val\n"
5447 "%transformed_param = OpFAdd %v4f32 %t2 %f3_val\n"
5451 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
5452 "%cnull = OpConstantNull %mat4x4_f32\n",
5453 // Our null matrix * any vector should result in a zero vector.
5454 "%v = OpVectorTimesMatrix %v4f32 %param1 %cnull\n"
5455 "%transformed_param = OpFAdd %v4f32 %param1 %v\n"
5459 getHalfColorsFullAlpha(colors);
5461 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
5463 map<string, string> fragments;
5464 fragments["pre_main"] = tests[testNdx].constants;
5465 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
5466 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, opConstantNullTests.get());
5468 return opConstantNullTests.release();
5470 tcu::TestCaseGroup* createOpConstantCompositeTests(tcu::TestContext& testCtx)
5472 de::MovePtr<tcu::TestCaseGroup> opConstantCompositeTests (new tcu::TestCaseGroup(testCtx, "opConstantComposite", "OpConstantComposite instruction"));
5473 RGBA inputColors[4];
5474 RGBA outputColors[4];
5477 const char functionStart[] =
5478 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5479 "%param1 = OpFunctionParameter %v4f32\n"
5482 const char functionEnd[] =
5483 "OpReturnValue %transformed_param\n"
5486 struct NameConstantsCode
5493 NameConstantsCode tests[] =
5498 "%cval = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0\n",
5499 "%transformed_param = OpFAdd %v4f32 %param1 %cval\n"
5504 "%stype = OpTypeStruct %v4f32 %f32\n"
5505 "%fp_stype = OpTypePointer Function %stype\n"
5506 "%f32_n_1 = OpConstant %f32 -1.0\n"
5507 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
5508 "%cvec = OpConstantComposite %v4f32 %f32_1_5 %f32_1_5 %f32_1_5 %c_f32_1\n"
5509 "%cval = OpConstantComposite %stype %cvec %f32_n_1\n",
5511 "%v = OpVariable %fp_stype Function %cval\n"
5512 "%vec_ptr = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
5513 "%f32_ptr = OpAccessChain %fp_v4f32 %v %c_u32_1\n"
5514 "%vec_val = OpLoad %v4f32 %vec_ptr\n"
5515 "%f32_val = OpLoad %v4f32 %f32_ptr\n"
5516 "%tmp1 = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_1 %f32_val\n" // vec4(-1)
5517 "%tmp2 = OpFAdd %v4f32 %tmp1 %param1\n" // param1 + vec4(-1)
5518 "%transformed_param = OpFAdd %v4f32 %tmp2 %vec_val\n" // param1 + vec4(-1) + vec4(1.5, 1.5, 1.5, 1.0)
5521 // [1|0|0|0.5] [x] = x + 0.5
5522 // [0|1|0|0.5] [y] = y + 0.5
5523 // [0|0|1|0.5] [z] = z + 0.5
5524 // [0|0|0|1 ] [1] = 1
5527 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
5528 "%v4f32_1_0_0_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_0\n"
5529 "%v4f32_0_1_0_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_1 %c_f32_0 %c_f32_0\n"
5530 "%v4f32_0_0_1_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_1 %c_f32_0\n"
5531 "%v4f32_0_5_0_5_0_5_1 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_1\n"
5532 "%cval = OpConstantComposite %mat4x4_f32 %v4f32_1_0_0_0 %v4f32_0_1_0_0 %v4f32_0_0_1_0 %v4f32_0_5_0_5_0_5_1\n",
5534 "%transformed_param = OpMatrixTimesVector %v4f32 %cval %param1\n"
5539 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
5540 "%fp_a4f32 = OpTypePointer Function %a4f32\n"
5541 "%f32_n_1 = OpConstant %f32 -1.0\n"
5542 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
5543 "%carr = OpConstantComposite %a4f32 %c_f32_0 %f32_n_1 %f32_1_5 %c_f32_0\n",
5545 "%v = OpVariable %fp_a4f32 Function %carr\n"
5546 "%f = OpAccessChain %fp_f32 %v %c_u32_0\n"
5547 "%f1 = OpAccessChain %fp_f32 %v %c_u32_1\n"
5548 "%f2 = OpAccessChain %fp_f32 %v %c_u32_2\n"
5549 "%f3 = OpAccessChain %fp_f32 %v %c_u32_3\n"
5550 "%f_val = OpLoad %f32 %f\n"
5551 "%f1_val = OpLoad %f32 %f1\n"
5552 "%f2_val = OpLoad %f32 %f2\n"
5553 "%f3_val = OpLoad %f32 %f3\n"
5554 "%ftot1 = OpFAdd %f32 %f_val %f1_val\n"
5555 "%ftot2 = OpFAdd %f32 %ftot1 %f2_val\n"
5556 "%ftot3 = OpFAdd %f32 %ftot2 %f3_val\n" // 0 - 1 + 1.5 + 0
5557 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %ftot3\n"
5558 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
5565 // [ 1.0, 1.0, 1.0, 1.0]
5569 // [ 0.0, 0.5, 0.0, 0.0]
5573 // [ 1.0, 1.0, 1.0, 1.0]
5576 "array_of_struct_of_array",
5578 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
5579 "%fp_a4f32 = OpTypePointer Function %a4f32\n"
5580 "%stype = OpTypeStruct %f32 %a4f32\n"
5581 "%a3stype = OpTypeArray %stype %c_u32_3\n"
5582 "%fp_a3stype = OpTypePointer Function %a3stype\n"
5583 "%ca4f32_0 = OpConstantComposite %a4f32 %c_f32_0 %c_f32_0_5 %c_f32_0 %c_f32_0\n"
5584 "%ca4f32_1 = OpConstantComposite %a4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
5585 "%cstype1 = OpConstantComposite %stype %c_f32_0 %ca4f32_1\n"
5586 "%cstype2 = OpConstantComposite %stype %c_f32_1 %ca4f32_0\n"
5587 "%carr = OpConstantComposite %a3stype %cstype1 %cstype2 %cstype1",
5589 "%v = OpVariable %fp_a3stype Function %carr\n"
5590 "%f = OpAccessChain %fp_f32 %v %c_u32_1 %c_u32_1 %c_u32_1\n"
5591 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %f\n"
5592 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
5596 getHalfColorsFullAlpha(inputColors);
5597 outputColors[0] = RGBA(255, 255, 255, 255);
5598 outputColors[1] = RGBA(255, 127, 127, 255);
5599 outputColors[2] = RGBA(127, 255, 127, 255);
5600 outputColors[3] = RGBA(127, 127, 255, 255);
5602 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
5604 map<string, string> fragments;
5605 fragments["pre_main"] = tests[testNdx].constants;
5606 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
5607 createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, opConstantCompositeTests.get());
5609 return opConstantCompositeTests.release();
5612 tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx)
5614 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_block_order", "Out-of-order blocks for selection"));
5615 RGBA inputColors[4];
5616 RGBA outputColors[4];
5617 map<string, string> fragments;
5619 // vec4 test_code(vec4 param) {
5620 // vec4 result = param;
5621 // for (int i = 0; i < 4; ++i) {
5622 // if (i == 0) result[i] = 0.;
5623 // else result[i] = 1. - result[i];
5627 const char function[] =
5628 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5629 "%param1 = OpFunctionParameter %v4f32\n"
5631 "%iptr = OpVariable %fp_i32 Function\n"
5632 " OpStore %iptr %c_i32_0\n"
5633 "%result = OpVariable %fp_v4f32 Function\n"
5634 " OpStore %result %param1\n"
5637 // Loop entry block.
5639 "%ival = OpLoad %i32 %iptr\n"
5640 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
5641 " OpLoopMerge %exit %loop None\n"
5642 " OpBranchConditional %lt_4 %if_entry %exit\n"
5644 // Merge block for loop.
5646 "%ret = OpLoad %v4f32 %result\n"
5647 " OpReturnValue %ret\n"
5649 // If-statement entry block.
5650 "%if_entry = OpLabel\n"
5651 "%loc = OpAccessChain %fp_f32 %result %ival\n"
5652 "%eq_0 = OpIEqual %bool %ival %c_i32_0\n"
5653 " OpSelectionMerge %if_exit None\n"
5654 " OpBranchConditional %eq_0 %if_true %if_false\n"
5656 // False branch for if-statement.
5657 "%if_false = OpLabel\n"
5658 "%val = OpLoad %f32 %loc\n"
5659 "%sub = OpFSub %f32 %c_f32_1 %val\n"
5660 " OpStore %loc %sub\n"
5661 " OpBranch %if_exit\n"
5663 // Merge block for if-statement.
5664 "%if_exit = OpLabel\n"
5665 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
5666 " OpStore %iptr %ival_next\n"
5669 // True branch for if-statement.
5670 "%if_true = OpLabel\n"
5671 " OpStore %loc %c_f32_0\n"
5672 " OpBranch %if_exit\n"
5676 fragments["testfun"] = function;
5678 inputColors[0] = RGBA(127, 127, 127, 0);
5679 inputColors[1] = RGBA(127, 0, 0, 0);
5680 inputColors[2] = RGBA(0, 127, 0, 0);
5681 inputColors[3] = RGBA(0, 0, 127, 0);
5683 outputColors[0] = RGBA(0, 128, 128, 255);
5684 outputColors[1] = RGBA(0, 255, 255, 255);
5685 outputColors[2] = RGBA(0, 128, 255, 255);
5686 outputColors[3] = RGBA(0, 255, 128, 255);
5688 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
5690 return group.release();
5693 tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx)
5695 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "switch_block_order", "Out-of-order blocks for switch"));
5696 RGBA inputColors[4];
5697 RGBA outputColors[4];
5698 map<string, string> fragments;
5700 const char typesAndConstants[] =
5701 "%c_f32_p2 = OpConstant %f32 0.2\n"
5702 "%c_f32_p4 = OpConstant %f32 0.4\n"
5703 "%c_f32_p6 = OpConstant %f32 0.6\n"
5704 "%c_f32_p8 = OpConstant %f32 0.8\n";
5706 // vec4 test_code(vec4 param) {
5707 // vec4 result = param;
5708 // for (int i = 0; i < 4; ++i) {
5710 // case 0: result[i] += .2; break;
5711 // case 1: result[i] += .6; break;
5712 // case 2: result[i] += .4; break;
5713 // case 3: result[i] += .8; break;
5714 // default: break; // unreachable
5719 const char function[] =
5720 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5721 "%param1 = OpFunctionParameter %v4f32\n"
5723 "%iptr = OpVariable %fp_i32 Function\n"
5724 " OpStore %iptr %c_i32_0\n"
5725 "%result = OpVariable %fp_v4f32 Function\n"
5726 " OpStore %result %param1\n"
5729 // Loop entry block.
5731 "%ival = OpLoad %i32 %iptr\n"
5732 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
5733 " OpLoopMerge %exit %loop None\n"
5734 " OpBranchConditional %lt_4 %switch_entry %exit\n"
5736 // Merge block for loop.
5738 "%ret = OpLoad %v4f32 %result\n"
5739 " OpReturnValue %ret\n"
5741 // Switch-statement entry block.
5742 "%switch_entry = OpLabel\n"
5743 "%loc = OpAccessChain %fp_f32 %result %ival\n"
5744 "%val = OpLoad %f32 %loc\n"
5745 " OpSelectionMerge %switch_exit None\n"
5746 " OpSwitch %ival %switch_default 0 %case0 1 %case1 2 %case2 3 %case3\n"
5748 "%case2 = OpLabel\n"
5749 "%addp4 = OpFAdd %f32 %val %c_f32_p4\n"
5750 " OpStore %loc %addp4\n"
5751 " OpBranch %switch_exit\n"
5753 "%switch_default = OpLabel\n"
5756 "%case3 = OpLabel\n"
5757 "%addp8 = OpFAdd %f32 %val %c_f32_p8\n"
5758 " OpStore %loc %addp8\n"
5759 " OpBranch %switch_exit\n"
5761 "%case0 = OpLabel\n"
5762 "%addp2 = OpFAdd %f32 %val %c_f32_p2\n"
5763 " OpStore %loc %addp2\n"
5764 " OpBranch %switch_exit\n"
5766 // Merge block for switch-statement.
5767 "%switch_exit = OpLabel\n"
5768 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
5769 " OpStore %iptr %ival_next\n"
5772 "%case1 = OpLabel\n"
5773 "%addp6 = OpFAdd %f32 %val %c_f32_p6\n"
5774 " OpStore %loc %addp6\n"
5775 " OpBranch %switch_exit\n"
5779 fragments["pre_main"] = typesAndConstants;
5780 fragments["testfun"] = function;
5782 inputColors[0] = RGBA(127, 27, 127, 51);
5783 inputColors[1] = RGBA(127, 0, 0, 51);
5784 inputColors[2] = RGBA(0, 27, 0, 51);
5785 inputColors[3] = RGBA(0, 0, 127, 51);
5787 outputColors[0] = RGBA(178, 180, 229, 255);
5788 outputColors[1] = RGBA(178, 153, 102, 255);
5789 outputColors[2] = RGBA(51, 180, 102, 255);
5790 outputColors[3] = RGBA(51, 153, 229, 255);
5792 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
5794 return group.release();
5797 struct SpecConstantTwoIntGraphicsCase
5799 const char* caseName;
5800 const char* scDefinition0;
5801 const char* scDefinition1;
5802 const char* scResultType;
5803 const char* scOperation;
5804 deInt32 scActualValue0;
5805 deInt32 scActualValue1;
5806 const char* resultOperation;
5807 RGBA expectedColors[4];
5809 SpecConstantTwoIntGraphicsCase (const char* name,
5810 const char* definition0,
5811 const char* definition1,
5812 const char* resultType,
5813 const char* operation,
5816 const char* resultOp,
5817 const RGBA (&output)[4])
5819 , scDefinition0 (definition0)
5820 , scDefinition1 (definition1)
5821 , scResultType (resultType)
5822 , scOperation (operation)
5823 , scActualValue0 (value0)
5824 , scActualValue1 (value1)
5825 , resultOperation (resultOp)
5827 expectedColors[0] = output[0];
5828 expectedColors[1] = output[1];
5829 expectedColors[2] = output[2];
5830 expectedColors[3] = output[3];
5834 tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
5836 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction"));
5837 vector<SpecConstantTwoIntGraphicsCase> cases;
5838 RGBA inputColors[4];
5839 RGBA outputColors0[4];
5840 RGBA outputColors1[4];
5841 RGBA outputColors2[4];
5843 const char decorations1[] =
5844 "OpDecorate %sc_0 SpecId 0\n"
5845 "OpDecorate %sc_1 SpecId 1\n";
5847 const char typesAndConstants1[] =
5848 "%sc_0 = OpSpecConstant${SC_DEF0}\n"
5849 "%sc_1 = OpSpecConstant${SC_DEF1}\n"
5850 "%sc_op = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n";
5852 const char function1[] =
5853 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5854 "%param = OpFunctionParameter %v4f32\n"
5855 "%label = OpLabel\n"
5856 "%result = OpVariable %fp_v4f32 Function\n"
5857 " OpStore %result %param\n"
5858 "%gen = ${GEN_RESULT}\n"
5859 "%index = OpIAdd %i32 %gen %c_i32_1\n"
5860 "%loc = OpAccessChain %fp_f32 %result %index\n"
5861 "%val = OpLoad %f32 %loc\n"
5862 "%add = OpFAdd %f32 %val %c_f32_0_5\n"
5863 " OpStore %loc %add\n"
5864 "%ret = OpLoad %v4f32 %result\n"
5865 " OpReturnValue %ret\n"
5868 inputColors[0] = RGBA(127, 127, 127, 255);
5869 inputColors[1] = RGBA(127, 0, 0, 255);
5870 inputColors[2] = RGBA(0, 127, 0, 255);
5871 inputColors[3] = RGBA(0, 0, 127, 255);
5873 // Derived from inputColors[x] by adding 128 to inputColors[x][0].
5874 outputColors0[0] = RGBA(255, 127, 127, 255);
5875 outputColors0[1] = RGBA(255, 0, 0, 255);
5876 outputColors0[2] = RGBA(128, 127, 0, 255);
5877 outputColors0[3] = RGBA(128, 0, 127, 255);
5879 // Derived from inputColors[x] by adding 128 to inputColors[x][1].
5880 outputColors1[0] = RGBA(127, 255, 127, 255);
5881 outputColors1[1] = RGBA(127, 128, 0, 255);
5882 outputColors1[2] = RGBA(0, 255, 0, 255);
5883 outputColors1[3] = RGBA(0, 128, 127, 255);
5885 // Derived from inputColors[x] by adding 128 to inputColors[x][2].
5886 outputColors2[0] = RGBA(127, 127, 255, 255);
5887 outputColors2[1] = RGBA(127, 0, 128, 255);
5888 outputColors2[2] = RGBA(0, 127, 128, 255);
5889 outputColors2[3] = RGBA(0, 0, 255, 255);
5891 const char addZeroToSc[] = "OpIAdd %i32 %c_i32_0 %sc_op";
5892 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_op %c_i32_1 %c_i32_0";
5893 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_op %c_i32_0 %c_i32_1";
5895 cases.push_back(SpecConstantTwoIntGraphicsCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 19, -20, addZeroToSc, outputColors0));
5896 cases.push_back(SpecConstantTwoIntGraphicsCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 19, 20, addZeroToSc, outputColors0));
5897 cases.push_back(SpecConstantTwoIntGraphicsCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -1, -1, addZeroToSc, outputColors2));
5898 cases.push_back(SpecConstantTwoIntGraphicsCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, 126, addZeroToSc, outputColors0));
5899 cases.push_back(SpecConstantTwoIntGraphicsCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 126, addZeroToSc, outputColors2));
5900 cases.push_back(SpecConstantTwoIntGraphicsCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", -3, 2, addZeroToSc, outputColors0));
5901 cases.push_back(SpecConstantTwoIntGraphicsCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", -3, 2, addZeroToSc, outputColors2));
5902 cases.push_back(SpecConstantTwoIntGraphicsCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 1001, 500, addZeroToSc, outputColors2));
5903 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 0x33, 0x0d, addZeroToSc, outputColors2));
5904 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 0, 1, addZeroToSc, outputColors2));
5905 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 0x2e, 0x2f, addZeroToSc, outputColors2));
5906 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 2, 1, addZeroToSc, outputColors2));
5907 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", -4, 2, addZeroToSc, outputColors0));
5908 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 1, 0, addZeroToSc, outputColors2));
5909 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputColors2));
5910 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputColors2));
5911 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2));
5912 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputColors2));
5913 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputColors2));
5914 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputColors2));
5915 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2));
5916 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputColors2));
5917 cases.push_back(SpecConstantTwoIntGraphicsCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputColors2));
5918 cases.push_back(SpecConstantTwoIntGraphicsCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2));
5919 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2));
5920 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2));
5921 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2));
5922 cases.push_back(SpecConstantTwoIntGraphicsCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -1, 0, addZeroToSc, outputColors2));
5923 cases.push_back(SpecConstantTwoIntGraphicsCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -2, 0, addZeroToSc, outputColors2));
5924 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputColors2));
5925 cases.push_back(SpecConstantTwoIntGraphicsCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %c_i32_0", 1, 1, addZeroToSc, outputColors2));
5926 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths.
5927 // \todo[2015-12-1 antiagainst] OpQuantizeToF16
5929 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
5931 map<string, string> specializations;
5932 map<string, string> fragments;
5933 vector<deInt32> specConstants;
5935 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0;
5936 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1;
5937 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType;
5938 specializations["SC_OP"] = cases[caseNdx].scOperation;
5939 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation;
5941 fragments["decoration"] = tcu::StringTemplate(decorations1).specialize(specializations);
5942 fragments["pre_main"] = tcu::StringTemplate(typesAndConstants1).specialize(specializations);
5943 fragments["testfun"] = tcu::StringTemplate(function1).specialize(specializations);
5945 specConstants.push_back(cases[caseNdx].scActualValue0);
5946 specConstants.push_back(cases[caseNdx].scActualValue1);
5948 createTestsForAllStages(cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants, group.get());
5951 const char decorations2[] =
5952 "OpDecorate %sc_0 SpecId 0\n"
5953 "OpDecorate %sc_1 SpecId 1\n"
5954 "OpDecorate %sc_2 SpecId 2\n";
5956 const char typesAndConstants2[] =
5957 "%v3i32 = OpTypeVector %i32 3\n"
5959 "%sc_0 = OpSpecConstant %i32 0\n"
5960 "%sc_1 = OpSpecConstant %i32 0\n"
5961 "%sc_2 = OpSpecConstant %i32 0\n"
5963 "%vec3_0 = OpConstantComposite %v3i32 %c_i32_0 %c_i32_0 %c_i32_0\n"
5964 "%sc_vec3_0 = OpSpecConstantOp %v3i32 CompositeInsert %sc_0 %vec3_0 0\n" // (sc_0, 0, 0)
5965 "%sc_vec3_1 = OpSpecConstantOp %v3i32 CompositeInsert %sc_1 %vec3_0 1\n" // (0, sc_1, 0)
5966 "%sc_vec3_2 = OpSpecConstantOp %v3i32 CompositeInsert %sc_2 %vec3_0 2\n" // (0, 0, sc_2)
5967 "%sc_vec3_01 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1)
5968 "%sc_vec3_012 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1)
5969 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2
5970 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0
5971 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1
5972 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0)
5973 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n"; // (sc_2 - sc_0) * sc_1
5975 const char function2[] =
5976 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5977 "%param = OpFunctionParameter %v4f32\n"
5978 "%label = OpLabel\n"
5979 "%result = OpVariable %fp_v4f32 Function\n"
5980 " OpStore %result %param\n"
5981 "%loc = OpAccessChain %fp_f32 %result %sc_final\n"
5982 "%val = OpLoad %f32 %loc\n"
5983 "%add = OpFAdd %f32 %val %c_f32_0_5\n"
5984 " OpStore %loc %add\n"
5985 "%ret = OpLoad %v4f32 %result\n"
5986 " OpReturnValue %ret\n"
5989 map<string, string> fragments;
5990 vector<deInt32> specConstants;
5992 fragments["decoration"] = decorations2;
5993 fragments["pre_main"] = typesAndConstants2;
5994 fragments["testfun"] = function2;
5996 specConstants.push_back(56789);
5997 specConstants.push_back(-2);
5998 specConstants.push_back(56788);
6000 createTestsForAllStages("vector_related", inputColors, outputColors2, fragments, specConstants, group.get());
6002 return group.release();
6005 tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
6007 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
6008 RGBA inputColors[4];
6009 RGBA outputColors1[4];
6010 RGBA outputColors2[4];
6011 RGBA outputColors3[4];
6012 map<string, string> fragments1;
6013 map<string, string> fragments2;
6014 map<string, string> fragments3;
6016 const char typesAndConstants1[] =
6017 "%c_f32_p2 = OpConstant %f32 0.2\n"
6018 "%c_f32_p4 = OpConstant %f32 0.4\n"
6019 "%c_f32_p6 = OpConstant %f32 0.6\n"
6020 "%c_f32_p8 = OpConstant %f32 0.8\n";
6022 // vec4 test_code(vec4 param) {
6023 // vec4 result = param;
6024 // for (int i = 0; i < 4; ++i) {
6027 // case 0: operand = .2; break;
6028 // case 1: operand = .6; break;
6029 // case 2: operand = .4; break;
6030 // case 3: operand = .0; break;
6031 // default: break; // unreachable
6033 // result[i] += operand;
6037 const char function1[] =
6038 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6039 "%param1 = OpFunctionParameter %v4f32\n"
6041 "%iptr = OpVariable %fp_i32 Function\n"
6042 " OpStore %iptr %c_i32_0\n"
6043 "%result = OpVariable %fp_v4f32 Function\n"
6044 " OpStore %result %param1\n"
6048 "%ival = OpLoad %i32 %iptr\n"
6049 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
6050 " OpLoopMerge %exit %loop None\n"
6051 " OpBranchConditional %lt_4 %entry %exit\n"
6053 "%entry = OpLabel\n"
6054 "%loc = OpAccessChain %fp_f32 %result %ival\n"
6055 "%val = OpLoad %f32 %loc\n"
6056 " OpSelectionMerge %phi None\n"
6057 " OpSwitch %ival %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
6059 "%case0 = OpLabel\n"
6061 "%case1 = OpLabel\n"
6063 "%case2 = OpLabel\n"
6065 "%case3 = OpLabel\n"
6068 "%default = OpLabel\n"
6072 "%operand = OpPhi %f32 %c_f32_p4 %case2 %c_f32_p6 %case1 %c_f32_p2 %case0 %c_f32_0 %case3\n" // not in the order of blocks
6073 "%add = OpFAdd %f32 %val %operand\n"
6074 " OpStore %loc %add\n"
6075 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
6076 " OpStore %iptr %ival_next\n"
6080 "%ret = OpLoad %v4f32 %result\n"
6081 " OpReturnValue %ret\n"
6085 fragments1["pre_main"] = typesAndConstants1;
6086 fragments1["testfun"] = function1;
6088 getHalfColorsFullAlpha(inputColors);
6090 outputColors1[0] = RGBA(178, 180, 229, 255);
6091 outputColors1[1] = RGBA(178, 153, 102, 255);
6092 outputColors1[2] = RGBA(51, 180, 102, 255);
6093 outputColors1[3] = RGBA(51, 153, 229, 255);
6095 createTestsForAllStages("out_of_order", inputColors, outputColors1, fragments1, group.get());
6097 const char typesAndConstants2[] =
6098 "%c_f32_p2 = OpConstant %f32 0.2\n";
6100 // Add .4 to the second element of the given parameter.
6101 const char function2[] =
6102 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6103 "%param = OpFunctionParameter %v4f32\n"
6104 "%entry = OpLabel\n"
6105 "%result = OpVariable %fp_v4f32 Function\n"
6106 " OpStore %result %param\n"
6107 "%loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
6108 "%val = OpLoad %f32 %loc\n"
6112 "%step = OpPhi %i32 %c_i32_0 %entry %step_next %phi\n"
6113 "%accum = OpPhi %f32 %val %entry %accum_next %phi\n"
6114 "%step_next = OpIAdd %i32 %step %c_i32_1\n"
6115 "%accum_next = OpFAdd %f32 %accum %c_f32_p2\n"
6116 "%still_loop = OpSLessThan %bool %step %c_i32_2\n"
6117 " OpLoopMerge %exit %phi None\n"
6118 " OpBranchConditional %still_loop %phi %exit\n"
6121 " OpStore %loc %accum\n"
6122 "%ret = OpLoad %v4f32 %result\n"
6123 " OpReturnValue %ret\n"
6127 fragments2["pre_main"] = typesAndConstants2;
6128 fragments2["testfun"] = function2;
6130 outputColors2[0] = RGBA(127, 229, 127, 255);
6131 outputColors2[1] = RGBA(127, 102, 0, 255);
6132 outputColors2[2] = RGBA(0, 229, 0, 255);
6133 outputColors2[3] = RGBA(0, 102, 127, 255);
6135 createTestsForAllStages("induction", inputColors, outputColors2, fragments2, group.get());
6137 const char typesAndConstants3[] =
6138 "%true = OpConstantTrue %bool\n"
6139 "%false = OpConstantFalse %bool\n"
6140 "%c_f32_p2 = OpConstant %f32 0.2\n";
6142 // Swap the second and the third element of the given parameter.
6143 const char function3[] =
6144 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6145 "%param = OpFunctionParameter %v4f32\n"
6146 "%entry = OpLabel\n"
6147 "%result = OpVariable %fp_v4f32 Function\n"
6148 " OpStore %result %param\n"
6149 "%a_loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
6150 "%a_init = OpLoad %f32 %a_loc\n"
6151 "%b_loc = OpAccessChain %fp_f32 %result %c_i32_2\n"
6152 "%b_init = OpLoad %f32 %b_loc\n"
6156 "%still_loop = OpPhi %bool %true %entry %false %phi\n"
6157 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n"
6158 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n"
6159 " OpLoopMerge %exit %phi None\n"
6160 " OpBranchConditional %still_loop %phi %exit\n"
6163 " OpStore %a_loc %a_next\n"
6164 " OpStore %b_loc %b_next\n"
6165 "%ret = OpLoad %v4f32 %result\n"
6166 " OpReturnValue %ret\n"
6170 fragments3["pre_main"] = typesAndConstants3;
6171 fragments3["testfun"] = function3;
6173 outputColors3[0] = RGBA(127, 127, 127, 255);
6174 outputColors3[1] = RGBA(127, 0, 0, 255);
6175 outputColors3[2] = RGBA(0, 0, 127, 255);
6176 outputColors3[3] = RGBA(0, 127, 0, 255);
6178 createTestsForAllStages("swap", inputColors, outputColors3, fragments3, group.get());
6180 return group.release();
6182 tcu::TestCaseGroup* createMemoryAccessTests(tcu::TestContext& testCtx)
6184 de::MovePtr<tcu::TestCaseGroup> memoryAccessTests (new tcu::TestCaseGroup(testCtx, "opMemoryAccess", "Memory Semantics"));
6187 const char constantsAndTypes[] =
6188 "%c_a2f32_1 = OpConstantComposite %a2f32 %c_f32_1 %c_f32_1\n"
6189 "%fp_a2f32 = OpTypePointer Function %a2f32\n"
6190 "%stype = OpTypeStruct %v4f32 %a2f32 %f32\n"
6191 "%fp_stype = OpTypePointer Function %stype\n";
6193 const char function[] =
6194 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6195 "%param1 = OpFunctionParameter %v4f32\n"
6197 "%v1 = OpVariable %fp_v4f32 Function\n"
6198 " OpStore %v1 %c_v4f32_1_1_1_1\n"
6199 "%v2 = OpVariable %fp_a2f32 Function\n"
6200 " OpStore %v2 %c_a2f32_1\n"
6201 "%v3 = OpVariable %fp_f32 Function\n"
6202 " OpStore %v3 %c_f32_1\n"
6204 "%v = OpVariable %fp_stype Function\n"
6206 "%vv = OpVariable %fp_stype Function\n"
6207 "%vvv = OpVariable %fp_f32 Function\n"
6209 "%p_v4f32 = OpAccessChain %fp_v4_f32 %v %c_u32_0\n"
6210 "%p_a2f32 = OpAccessChain %fp_a2f32 %v %c_u32_1\n"
6211 "%p_f32 = OpAccessChain %fp_f32 %v %c_u32_2\n"
6212 "%v1_v = OpLoad %v4f32 %v1 ${access_type}\n"
6213 "%v2_v = OpLoad %a2f32 %v2 ${access_type}\n"
6214 "%v3_v = OpLoad %f32 %v3 ${access_type}\n"
6216 " OpStore %p_v4f32 %v1_v ${access_type}\n"
6217 " OpStore %p_a2f32 %v2_v ${access_type}\n"
6218 " OpStore %p_f32 %v3_v ${access_type}\n"
6220 " OpCopyMemory %vv %v ${access_type}\n"
6221 " OpCopyMemory %vvv %p_f32 ${access_type}\n"
6223 "%p_f32_2 = OpAccessChain %fp_f32 %vv %c_u32_2\n"
6224 "%v_f32_2 = OpLoad %f32 %p_f32_2\n"
6225 "%v_f32_3 = OpLoad %f32 %vvv\n"
6227 "%ret1 = OpVectorTimesScalar %v4f32 %param1 %v_f32_2\n"
6228 "%ret2 = OpVectorTimesScalar %v4f32 %ret1 %v_f32_3\n"
6229 " OpReturnValue %ret2\n"
6232 struct NameMemoryAccess
6239 NameMemoryAccess tests[] =
6242 { "volatile", "Volatile" },
6243 { "aligned", "Aligned 1" },
6244 { "volatile-aligned", "Volatile|Aligned 1" },
6245 { "nontemporal-aligned", "Nontemporal|Aligned 1" },
6246 { "volatile-nontemporal", "Volatile|Nontemporal" },
6247 { "volatile-nontermporal-aligned", "Volatile|NonTermporal|Aligned" },
6250 getHalfColorsFullAlpha(colors);
6252 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameMemoryAccess); ++testNdx)
6254 map<string, string> fragments;
6255 map<string, string> memoryAccess;
6256 memoryAccess["access_type"] = tests[testNdx].accessType;
6258 fragments["pre_main"] = constantsAndTypes;
6259 fragments["testfun"] = tcu::StringTemplate(function).specialize(memoryAccess);
6260 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, memoryAccessTests.get());
6262 return memoryAccessTests.release();
6264 tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
6266 de::MovePtr<tcu::TestCaseGroup> opUndefTests (new tcu::TestCaseGroup(testCtx, "opundef", "Test OpUndef"));
6267 RGBA defaultColors[4];
6268 map<string, string> fragments;
6269 getDefaultColors(defaultColors);
6271 // First, simple cases that don't do anything with the OpUndef result.
6272 fragments["testfun"] =
6273 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6274 "%param1 = OpFunctionParameter %v4f32\n"
6275 "%label_testfun = OpLabel\n"
6276 "%undef = OpUndef %type\n"
6277 "OpReturnValue %param1\n"
6280 struct NameCodePair { string name, code; };
6281 const NameCodePair tests[] =
6283 {"bool", "%type = OpTypeBool"},
6284 {"vec2uint32", "%type = OpTypeVector %u32 2"},
6285 {"image", "%type = OpTypeImage %f32 2D 0 0 0 0 Unknown"},
6286 {"sampler", "%type = OpTypeSampler"},
6287 {"sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 0 Unknown\n" "%type = OpTypeSampledImage %img"},
6288 {"function", "%type = OpTypeFunction %void %i32 %f32"},
6289 {"pointer", "%type = OpTypePointer Function %i32"},
6290 {"runtimearray", "%type = OpTypeRuntimeArray %f32"},
6291 {"array", "%c_u32_100 = OpConstant %u32 100\n" "%type = OpTypeArray %i32 %c_u32_100"},
6292 {"struct", "%type = OpTypeStruct %f32 %i32 %u32"}};
6293 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
6295 fragments["pre_main"] = tests[testNdx].code;
6296 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opUndefTests.get());
6300 fragments["testfun"] =
6301 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6302 "%param1 = OpFunctionParameter %v4f32\n"
6303 "%label_testfun = OpLabel\n"
6304 "%undef = OpUndef %f32\n"
6305 "%zero = OpFMul %f32 %undef %c_f32_0\n"
6306 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6307 "%b = OpFAdd %f32 %a %zero\n"
6308 "%ret = OpVectorInsertDynamic %v4f32 %param1 %b %c_i32_0\n"
6309 "OpReturnValue %ret\n"
6312 createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get());
6314 fragments["testfun"] =
6315 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6316 "%param1 = OpFunctionParameter %v4f32\n"
6317 "%label_testfun = OpLabel\n"
6318 "%undef = OpUndef %i32\n"
6319 "%zero = OpIMul %i32 %undef %c_i32_0\n"
6320 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
6321 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
6322 "OpReturnValue %ret\n"
6325 createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get());
6327 fragments["testfun"] =
6328 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6329 "%param1 = OpFunctionParameter %v4f32\n"
6330 "%label_testfun = OpLabel\n"
6331 "%undef = OpUndef %u32\n"
6332 "%zero = OpIMul %u32 %undef %c_i32_0\n"
6333 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
6334 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
6335 "OpReturnValue %ret\n"
6338 createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get());
6340 fragments["testfun"] =
6341 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6342 "%param1 = OpFunctionParameter %v4f32\n"
6343 "%label_testfun = OpLabel\n"
6344 "%undef = OpUndef %v4f32\n"
6345 "%vzero = OpVectorTimesScalar %v4f32 %undef %c_f32_0\n"
6346 "%zero_0 = OpVectorExtractDynamic %f32 %vzero %c_i32_0\n"
6347 "%zero_1 = OpVectorExtractDynamic %f32 %vzero %c_i32_1\n"
6348 "%zero_2 = OpVectorExtractDynamic %f32 %vzero %c_i32_2\n"
6349 "%zero_3 = OpVectorExtractDynamic %f32 %vzero %c_i32_3\n"
6350 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6351 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
6352 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
6353 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
6354 "%sum_0 = OpFAdd %f32 %param1_0 %zero_0\n"
6355 "%sum_1 = OpFAdd %f32 %param1_1 %zero_1\n"
6356 "%sum_2 = OpFAdd %f32 %param1_2 %zero_2\n"
6357 "%sum_3 = OpFAdd %f32 %param1_3 %zero_3\n"
6358 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
6359 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
6360 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
6361 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
6362 "OpReturnValue %ret\n"
6365 createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get());
6367 fragments["pre_main"] =
6368 "%v2f32 = OpTypeVector %f32 2\n"
6369 "%m2x2f32 = OpTypeMatrix %v2f32 2\n";
6370 fragments["testfun"] =
6371 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6372 "%param1 = OpFunctionParameter %v4f32\n"
6373 "%label_testfun = OpLabel\n"
6374 "%undef = OpUndef %m2x2f32\n"
6375 "%mzero = OpMatrixTimesScalar %m2x2f32 %undef %c_f32_0\n"
6376 "%zero_0 = OpCompositeExtract %f32 %mzero 0 0\n"
6377 "%zero_1 = OpCompositeExtract %f32 %mzero 0 1\n"
6378 "%zero_2 = OpCompositeExtract %f32 %mzero 1 0\n"
6379 "%zero_3 = OpCompositeExtract %f32 %mzero 1 1\n"
6380 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6381 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
6382 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
6383 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
6384 "%sum_0 = OpFAdd %f32 %param1_0 %zero_0\n"
6385 "%sum_1 = OpFAdd %f32 %param1_1 %zero_1\n"
6386 "%sum_2 = OpFAdd %f32 %param1_2 %zero_2\n"
6387 "%sum_3 = OpFAdd %f32 %param1_3 %zero_3\n"
6388 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
6389 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
6390 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
6391 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
6392 "OpReturnValue %ret\n"
6395 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, opUndefTests.get());
6397 return opUndefTests.release();
6400 void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
6402 const RGBA inputColors[4] = {
6404 RGBA(0, 0, 255, 255),
6405 RGBA(0, 255, 0, 255),
6406 RGBA(0, 255, 255, 255)
6409 const RGBA expectedColors[4] =
6411 RGBA(255, 0, 0, 255),
6412 RGBA(255, 0, 0, 255),
6413 RGBA(255, 0, 0, 255),
6414 RGBA(255, 0, 0, 255)
6417 const struct SingleFP16Possibility
6420 const char* constant;
6421 const char* condition;
6422 // condition must evaluate to true after %test_constant = OpQuantizeToF16(%constant)
6427 "%cond = OpFOrdEqual %bool %c %test_constant\n"
6432 "%cond = OpFOrdEqual %bool %c %test_constant\n"
6434 // SPIR-V requires that OpQuantizeToF16 flushes
6435 // any numbers that would end up denormalized in F16 to zero.
6439 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
6444 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
6449 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
6450 }, // too small negative
6452 "negative_too_small",
6454 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
6455 }, // too small positive
6460 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n"
6461 "%inf = OpIsInf %bool %c\n"
6462 "%cond = OpLogicalAnd %bool %gz %inf\n"
6468 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n"
6469 "%inf = OpIsInf %bool %c\n"
6470 "%cond = OpLogicalAnd %bool %gz %inf\n"
6473 "round_to_negative_inf",
6476 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n"
6477 "%inf = OpIsInf %bool %c\n"
6478 "%comp = OpLogicalAnd %bool %gz %inf\n"
6484 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n"
6485 "%inf = OpIsInf %bool %c\n"
6486 "%cond = OpLogicalAnd %bool %gz %inf\n"
6492 "%nan = OpIsNan %bool %c\n"
6493 "%as_int = OpBitcast %i32 %c\n"
6494 "%positive = OpSGreaterThan %bool %as_int %c_i32_0\n"
6495 "%cond = OpLogicalAnd %bool %nan %positive\n"
6501 "%nan = OpIsNan %bool %c\n"
6502 "%as_int = OpBitcast %i32 %c\n"
6503 "%negative = OpSLessThan %bool %as_int %c_i32_0\n"
6504 "%cond = OpLogicalAnd %bool %nan %negative\n"
6507 StringTemplate constants(
6508 "%test_constant = OpConstant %f32 ${constant}\n");
6509 StringTemplate function(
6510 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6511 "%param1 = OpFunctionParameter %v4f32\n"
6512 "%label_testfun = OpLabel\n"
6513 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6514 "%b = OpFAdd %f32 %test_constant %a\n"
6515 "%c = OpQuantizeToF16 %f32 %b\n"
6517 "%retval = OpSelect %v4f32 %cond %c_v4f32_1_0_0_1 %param1"
6518 " OpReturnValue %retval\n"
6521 for(size_t i = 0; i < (sizeof(tests)/sizeof(tests[0])); ++i) {
6522 map<string, string> code_specialization;
6523 map<string, string> constant_specialization;
6524 map<string, string> fragments;
6525 code_specialization["condition"] = tests[i].condition;
6526 constant_specialization["constant"] = tests[i].constant;
6527 fragments["testfun"] = function.specialize(code_specialization);
6528 fragments["pre_main"] = constants.specialize(constant_specialization);
6529 createTestsForAllStages(tests[i].name, inputColors, expectedColors, fragments, testCtx);
6533 void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx)
6535 RGBA inputColors[4] = {
6537 RGBA(0, 0, 255, 255),
6538 RGBA(0, 255, 0, 255),
6539 RGBA(0, 255, 255, 255)
6542 RGBA expectedColors[4] =
6544 RGBA(255, 0, 0, 255),
6545 RGBA(255, 0, 0, 255),
6546 RGBA(255, 0, 0, 255),
6547 RGBA(255, 0, 0, 255)
6550 struct DualFP16Possibility
6554 const char* possible_output1;
6555 const char* possible_output2;
6558 "positive_round_up_or_round_down",
6564 "negative_round_up_or_round_down",
6576 "carry_to_exponent",
6582 StringTemplate constants (
6583 "%input_const = OpConstant %f32 ${input}\n"
6584 "%possible_solution1 = OpConstant %f32 ${output1}\n"
6585 "%possible_solution2 = OpConstant %f32 ${output2}\n"
6587 const char* function =
6588 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6589 "%param1 = OpFunctionParameter %v4f32\n"
6590 "%label_testfun = OpLabel\n"
6591 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6592 // For the purposes of this test we assume that 0.f will always get
6593 // faithfully passed through the pipeline stages.
6594 "%b = OpFAdd %f32 %test_constant %a\n"
6595 "%c = OpQuantizeToF16 %f32 %b\n"
6596 "%eq_1 = OpFOrdEqual %bool %c %possible_solution1\n"
6597 "%eq_2 = OpFOrdEqual %bool %c %possible_solution2\n"
6598 "%cond = OpLogicalOr %bool %eq_1 %eq_2\n"
6599 "%retval = OpSelect %v4f32 %cond %c_v4f32_1_0_0_1 %param1"
6600 " OpReturnValue %retval\n";
6602 for(size_t i = 0; i < (sizeof(tests)/sizeof(tests[0])); ++i) {
6603 map<string, string> fragments;
6604 map<string, string> constant_specialization;
6605 constant_specialization["input"] = tests[i].input;
6606 constant_specialization["output1"] = tests[i].possible_output1;
6607 constant_specialization["output2"] = tests[i].possible_output2;
6608 fragments["testfun"] = function;
6609 fragments["pre_main"] = constants.specialize(constant_specialization);
6610 createTestsForAllStages(tests[i].name, inputColors, expectedColors, fragments, testCtx);
6614 tcu::TestCaseGroup* createOpQuantizeTests(tcu::TestContext& testCtx)
6616 de::MovePtr<tcu::TestCaseGroup> opQuantizeTests (new tcu::TestCaseGroup(testCtx, "opquantize", "Test OpQuantizeToF16"));
6617 createOpQuantizeSingleOptionTests(opQuantizeTests.get());
6618 createOpQuantizeTwoPossibilityTests(opQuantizeTests.get());
6619 return opQuantizeTests.release();
6622 struct ShaderPermutation
6624 deUint8 vertexPermutation;
6625 deUint8 geometryPermutation;
6626 deUint8 tesscPermutation;
6627 deUint8 tessePermutation;
6628 deUint8 fragmentPermutation;
6631 ShaderPermutation getShaderPermutation(deUint8 inputValue)
6633 ShaderPermutation permutation =
6635 static_cast<deUint8>(inputValue & 0x10? 1u: 0u),
6636 static_cast<deUint8>(inputValue & 0x08? 1u: 0u),
6637 static_cast<deUint8>(inputValue & 0x04? 1u: 0u),
6638 static_cast<deUint8>(inputValue & 0x02? 1u: 0u),
6639 static_cast<deUint8>(inputValue & 0x01? 1u: 0u)
6644 tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx)
6646 RGBA defaultColors[4];
6647 RGBA invertedColors[4];
6648 de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders"));
6650 const ShaderElement combinedPipeline[] =
6652 ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
6653 ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
6654 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
6655 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
6656 ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
6659 getDefaultColors(defaultColors);
6660 getInvertedDefaultColors(invertedColors);
6661 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), "same-module", "", createCombinedModule, runAndVerifyDefaultPipeline, createInstanceContext(combinedPipeline, map<string, string>()));
6663 const char* numbers[] =
6668 for (deInt8 idx = 0; idx < 32; ++idx)
6670 ShaderPermutation permutation = getShaderPermutation(idx);
6671 string name = string("vert") + numbers[permutation.vertexPermutation] + "-geom" + numbers[permutation.geometryPermutation] + "-tessc" + numbers[permutation.tesscPermutation] + "-tesse" + numbers[permutation.tessePermutation] + "-frag" + numbers[permutation.fragmentPermutation];
6672 const ShaderElement pipeline[] =
6674 ShaderElement("vert", string("vert") + numbers[permutation.vertexPermutation], VK_SHADER_STAGE_VERTEX_BIT),
6675 ShaderElement("geom", string("geom") + numbers[permutation.geometryPermutation], VK_SHADER_STAGE_GEOMETRY_BIT),
6676 ShaderElement("tessc", string("tessc") + numbers[permutation.tesscPermutation], VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
6677 ShaderElement("tesse", string("tesse") + numbers[permutation.tessePermutation], VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
6678 ShaderElement("frag", string("frag") + numbers[permutation.fragmentPermutation], VK_SHADER_STAGE_FRAGMENT_BIT)
6681 // If there are an even number of swaps, then it should be no-op.
6682 // If there are an odd number, the color should be flipped.
6683 if ((permutation.vertexPermutation + permutation.geometryPermutation + permutation.tesscPermutation + permutation.tessePermutation + permutation.fragmentPermutation) % 2 == 0)
6685 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, defaultColors, map<string, string>()));
6689 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, invertedColors, map<string, string>()));
6692 return moduleTests.release();
6695 tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
6697 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "loop", "Looping control flow"));
6698 RGBA defaultColors[4];
6699 getDefaultColors(defaultColors);
6700 map<string, string> fragments;
6702 // A loop with a single block. The Continue Target is the loop block
6703 // itself. In SPIR-V terms, the "loop construct" contains no blocks at all
6704 // -- the "continue construct" forms the entire loop.
6705 fragments["testfun"] =
6706 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6707 "%param1 = OpFunctionParameter %v4f32\n"
6709 "%entry = OpLabel\n"
6710 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6713 ";adds and subtracts 1.0 to %val in alternate iterations\n"
6715 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %loop\n"
6716 "%delta = OpPhi %f32 %c_f32_1 %entry %minus_delta %loop\n"
6717 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n"
6718 "%val = OpFAdd %f32 %val1 %delta\n"
6719 "%minus_delta = OpFSub %f32 %c_f32_0 %delta\n"
6720 "%count__ = OpISub %i32 %count %c_i32_1\n"
6721 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
6722 "OpLoopMerge %exit %loop None\n"
6723 "OpBranchConditional %again %loop %exit\n"
6726 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n"
6727 "OpReturnValue %result\n"
6731 createTestsForAllStages("single-block", defaultColors, defaultColors, fragments, testGroup.get());
6733 fragments["pre_main"] = "%c_f32_neg1 = OpConstant %f32 -1.0\n";
6735 // Body comprised of multiple basic blocks.
6736 const StringTemplate multiBlock(
6737 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6738 "%param1 = OpFunctionParameter %v4f32\n"
6740 "%entry = OpLabel\n"
6741 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6744 ";adds and subtracts 1.0 to %val in alternate iterations\n"
6746 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %gather\n"
6747 "%delta = OpPhi %f32 %c_f32_1 %entry %delta_next %gather\n"
6748 "%val1 = OpPhi %f32 %val0 %entry %val %gather\n"
6749 // There are several possibilities for the Continue Target below. Each
6750 // will be specialized into a separate test case.
6751 "OpLoopMerge %exit ${continue_target} None\n"
6755 ";delta_next = (delta > 0) ? -1 : 1;\n"
6756 "%gt0 = OpFOrdGreaterThan %bool %delta %c_f32_0\n"
6757 "OpSelectionMerge %gather DontFlatten\n"
6758 "OpBranchConditional %gt0 %even %odd ;tells us if %count is even or odd\n"
6761 "OpBranch %gather\n"
6764 "OpBranch %gather\n"
6766 "%gather = OpLabel\n"
6767 "%delta_next = OpPhi %f32 %c_f32_neg1 %even %c_f32_1 %odd\n"
6768 "%val = OpFAdd %f32 %val1 %delta\n"
6769 "%count__ = OpISub %i32 %count %c_i32_1\n"
6770 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
6771 "OpBranchConditional %again %loop %exit\n"
6774 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n"
6775 "OpReturnValue %result\n"
6779 map<string, string> continue_target;
6781 // The Continue Target is the loop block itself.
6782 continue_target["continue_target"] = "%loop";
6783 fragments["testfun"] = multiBlock.specialize(continue_target);
6784 createTestsForAllStages("multi-block-continue-construct", defaultColors, defaultColors, fragments, testGroup.get());
6786 // The Continue Target is at the end of the loop.
6787 continue_target["continue_target"] = "%gather";
6788 fragments["testfun"] = multiBlock.specialize(continue_target);
6789 createTestsForAllStages("multi-block-loop-construct", defaultColors, defaultColors, fragments, testGroup.get());
6791 // \todo [2015-12-14 dekimir] More cases:
6795 return testGroup.release();
6798 // Adds a new test to group using custom fragments for the tessellation-control
6799 // stage and passthrough fragments for all other stages. Uses default colors
6800 // for input and expected output.
6801 void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
6803 RGBA defaultColors[4];
6804 getDefaultColors(defaultColors);
6805 const ShaderElement pipelineStages[] =
6807 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
6808 ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
6809 ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
6810 ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
6811 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
6814 addFunctionCaseWithPrograms<InstanceContext>(group, name, "", addShaderCodeCustomTessControl,
6815 runAndVerifyDefaultPipeline, createInstanceContext(
6816 pipelineStages, defaultColors, defaultColors, fragments, StageToSpecConstantMap()));
6819 // A collection of tests putting OpControlBarrier in places GLSL forbids but SPIR-V allows.
6820 tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
6822 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "barrier", "OpControlBarrier"));
6823 map<string, string> fragments;
6825 // A barrier inside a function body.
6826 fragments["pre_main"] =
6827 "%Workgroup = OpConstant %i32 2\n"
6828 "%SequentiallyConsistent = OpConstant %i32 0x10\n";
6829 fragments["testfun"] =
6830 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6831 "%param1 = OpFunctionParameter %v4f32\n"
6832 "%label_testfun = OpLabel\n"
6833 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6834 "OpReturnValue %param1\n"
6836 addTessCtrlTest(testGroup.get(), "in-function", fragments);
6838 // Common setup code for the following tests.
6839 fragments["pre_main"] =
6840 "%Workgroup = OpConstant %i32 2\n"
6841 "%SequentiallyConsistent = OpConstant %i32 0x10\n"
6842 "%c_f32_5 = OpConstant %f32 5.\n";
6843 const string setupPercentZero = // Begins %test_code function with code that sets %zero to 0u but cannot be optimized away.
6844 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6845 "%param1 = OpFunctionParameter %v4f32\n"
6846 "%entry = OpLabel\n"
6847 ";param1 components are between 0 and 1, so dot product is 4 or less\n"
6848 "%dot = OpDot %f32 %param1 %param1\n"
6849 "%div = OpFDiv %f32 %dot %c_f32_5\n"
6850 "%zero = OpConvertFToU %u32 %div\n";
6852 // Barriers inside OpSwitch branches.
6853 fragments["testfun"] =
6855 "OpSelectionMerge %switch_exit None\n"
6856 "OpSwitch %zero %switch_default 0 %case0 1 %case1 ;should always go to %case0\n"
6858 "%case1 = OpLabel\n"
6859 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
6860 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6861 "%wrong_branch_alert1 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
6862 "OpBranch %switch_exit\n"
6864 "%switch_default = OpLabel\n"
6865 "%wrong_branch_alert2 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
6866 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
6867 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6868 "OpBranch %switch_exit\n"
6870 "%case0 = OpLabel\n"
6871 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6872 "OpBranch %switch_exit\n"
6874 "%switch_exit = OpLabel\n"
6875 "%ret = OpPhi %v4f32 %param1 %case0 %wrong_branch_alert1 %case1 %wrong_branch_alert2 %switch_default\n"
6876 "OpReturnValue %ret\n"
6878 addTessCtrlTest(testGroup.get(), "in-switch", fragments);
6880 // Barriers inside if-then-else.
6881 fragments["testfun"] =
6883 "%eq0 = OpIEqual %bool %zero %c_u32_0\n"
6884 "OpSelectionMerge %exit DontFlatten\n"
6885 "OpBranchConditional %eq0 %then %else\n"
6888 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
6889 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6890 "%wrong_branch_alert = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
6894 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6898 "%ret = OpPhi %v4f32 %param1 %then %wrong_branch_alert %else\n"
6899 "OpReturnValue %ret\n"
6901 addTessCtrlTest(testGroup.get(), "in-if", fragments);
6903 // A barrier after control-flow reconvergence, tempting the compiler to attempt something like this:
6904 // http://lists.llvm.org/pipermail/llvm-dev/2009-October/026317.html.
6905 fragments["testfun"] =
6907 "%thread_id = OpLoad %i32 %gl_InvocationID\n"
6908 "%thread0 = OpIEqual %bool %thread_id %c_i32_0\n"
6909 "OpSelectionMerge %exit DontFlatten\n"
6910 "OpBranchConditional %thread0 %then %else\n"
6913 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6917 "%val1 = OpVectorExtractDynamic %f32 %param1 %zero\n"
6921 "%val = OpPhi %f32 %val0 %else %val1 %then\n"
6922 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6923 "%ret = OpVectorInsertDynamic %v4f32 %param1 %val %zero\n"
6924 "OpReturnValue %ret\n"
6926 addTessCtrlTest(testGroup.get(), "after-divergent-if", fragments);
6928 // A barrier inside a loop.
6929 fragments["pre_main"] =
6930 "%Workgroup = OpConstant %i32 2\n"
6931 "%SequentiallyConsistent = OpConstant %i32 0x10\n"
6932 "%c_f32_10 = OpConstant %f32 10.\n";
6933 fragments["testfun"] =
6934 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6935 "%param1 = OpFunctionParameter %v4f32\n"
6936 "%entry = OpLabel\n"
6937 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6940 ";adds 1, 2, 3, and 4 to %val0\n"
6942 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %latch\n"
6943 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n"
6944 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
6945 "%fcount = OpConvertSToF %f32 %count\n"
6946 "%val = OpFAdd %f32 %val1 %fcount\n"
6947 "%count__ = OpISub %i32 %count %c_i32_1\n"
6948 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
6949 "OpLoopMerge %exit %loop None\n"
6950 "OpBranchConditional %again %loop %exit\n"
6953 "%same = OpFSub %f32 %val %c_f32_10\n"
6954 "%ret = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n"
6955 "OpReturnValue %ret\n"
6957 addTessCtrlTest(testGroup.get(), "in-loop", fragments);
6959 return testGroup.release();
6962 tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
6964 de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
6965 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Compute Instructions with special opcodes/operands"));
6966 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Graphics Instructions with special opcodes/operands"));
6968 computeTests->addChild(createOpNopGroup(testCtx));
6969 computeTests->addChild(createOpLineGroup(testCtx));
6970 computeTests->addChild(createOpNoLineGroup(testCtx));
6971 computeTests->addChild(createOpConstantNullGroup(testCtx));
6972 computeTests->addChild(createOpConstantCompositeGroup(testCtx));
6973 computeTests->addChild(createOpConstantUsageGroup(testCtx));
6974 computeTests->addChild(createSpecConstantGroup(testCtx));
6975 computeTests->addChild(createOpSourceGroup(testCtx));
6976 computeTests->addChild(createOpSourceExtensionGroup(testCtx));
6977 computeTests->addChild(createDecorationGroupGroup(testCtx));
6978 computeTests->addChild(createOpPhiGroup(testCtx));
6979 computeTests->addChild(createLoopControlGroup(testCtx));
6980 computeTests->addChild(createFunctionControlGroup(testCtx));
6981 computeTests->addChild(createSelectionControlGroup(testCtx));
6982 computeTests->addChild(createBlockOrderGroup(testCtx));
6983 computeTests->addChild(createMultipleShaderGroup(testCtx));
6984 computeTests->addChild(createMemoryAccessGroup(testCtx));
6985 computeTests->addChild(createOpCopyMemoryGroup(testCtx));
6986 computeTests->addChild(createOpCopyObjectGroup(testCtx));
6987 computeTests->addChild(createNoContractionGroup(testCtx));
6988 computeTests->addChild(createOpUndefGroup(testCtx));
6989 computeTests->addChild(createOpUnreachableGroup(testCtx));
6990 computeTests ->addChild(createOpQuantizeToF16Group(testCtx));
6992 RGBA defaultColors[4];
6993 getDefaultColors(defaultColors);
6995 de::MovePtr<tcu::TestCaseGroup> opnopTests (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop"));
6996 map<string, string> opNopFragments;
6997 opNopFragments["testfun"] =
6998 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6999 "%param1 = OpFunctionParameter %v4f32\n"
7000 "%label_testfun = OpLabel\n"
7009 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
7010 "%b = OpFAdd %f32 %a %a\n"
7012 "%c = OpFSub %f32 %b %a\n"
7013 "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
7016 "OpReturnValue %ret\n"
7019 createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, opnopTests.get());
7022 graphicsTests->addChild(opnopTests.release());
7023 graphicsTests->addChild(createOpSourceTests(testCtx));
7024 graphicsTests->addChild(createOpSourceContinuedTests(testCtx));
7025 graphicsTests->addChild(createOpLineTests(testCtx));
7026 graphicsTests->addChild(createOpNoLineTests(testCtx));
7027 graphicsTests->addChild(createOpConstantNullTests(testCtx));
7028 graphicsTests->addChild(createOpConstantCompositeTests(testCtx));
7029 graphicsTests->addChild(createMemoryAccessTests(testCtx));
7030 graphicsTests->addChild(createOpUndefTests(testCtx));
7031 graphicsTests->addChild(createSelectionBlockOrderTests(testCtx));
7032 graphicsTests->addChild(createModuleTests(testCtx));
7033 graphicsTests->addChild(createSwitchBlockOrderTests(testCtx));
7034 graphicsTests->addChild(createOpPhiTests(testCtx));
7035 graphicsTests->addChild(createOpQuantizeTests(testCtx));
7036 graphicsTests->addChild(createLoopTests(testCtx));
7037 graphicsTests->addChild(createSpecConstantTests(testCtx));
7038 graphicsTests->addChild(createSpecConstantOpQuantizeToF16Group(testCtx));
7039 graphicsTests->addChild(createBarrierTests(testCtx));
7041 instructionTests->addChild(computeTests.release());
7042 instructionTests->addChild(graphicsTests.release());
7044 return instructionTests.release();