1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
6 * Copyright (c) 2016 The Khronos Group Inc.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand)
23 *//*--------------------------------------------------------------------*/
25 #include "vktSpvAsmInstructionTests.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "tcuFormatUtil.hpp"
29 #include "tcuFloat.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuVectorUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkPlatform.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkQueryUtil.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vkStrUtil.hpp"
44 #include "vkTypeUtil.hpp"
46 #include "deRandom.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
49 #include "tcuStringTemplate.hpp"
51 #include "vktSpvAsm16bitStorageTests.hpp"
52 #include "vktSpvAsmComputeShaderCase.hpp"
53 #include "vktSpvAsmComputeShaderTestUtil.hpp"
54 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
55 #include "vktTestCaseUtil.hpp"
66 namespace SpirVAssembly
80 using tcu::TestStatus;
83 using tcu::StringTemplate;
87 static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
89 T* const typedPtr = (T*)dst;
90 for (int ndx = 0; ndx < numValues; ndx++)
91 typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
94 // Filter is a function that returns true if a value should pass, false otherwise.
95 template<typename T, typename FilterT>
96 static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, FilterT filter, int offset = 0)
98 T* const typedPtr = (T*)dst;
100 for (int ndx = 0; ndx < numValues; ndx++)
103 value = randomScalar<T>(rnd, minValue, maxValue);
104 while (!filter(value));
106 typedPtr[offset + ndx] = value;
110 static void floorAll (vector<float>& values)
112 for (size_t i = 0; i < values.size(); i++)
113 values[i] = deFloatFloor(values[i]);
116 static void floorAll (vector<Vec4>& values)
118 for (size_t i = 0; i < values.size(); i++)
119 values[i] = floor(values[i]);
127 CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {}
130 // Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code:
134 // layout(std140, set = 0, binding = 0) readonly buffer Input {
137 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
141 // layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
144 // uint x = gl_GlobalInvocationID.x;
145 // output_data.elements[x] = -input_data.elements[x];
148 tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx)
150 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction"));
151 ComputeShaderSpec spec;
152 de::Random rnd (deStringHash(group->getName()));
153 const int numElements = 100;
154 vector<float> positiveFloats (numElements, 0);
155 vector<float> negativeFloats (numElements, 0);
157 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
159 for (size_t ndx = 0; ndx < numElements; ++ndx)
160 negativeFloats[ndx] = -positiveFloats[ndx];
163 string(getComputeAsmShaderPreamble()) +
165 "OpSource GLSL 430\n"
166 "OpName %main \"main\"\n"
167 "OpName %id \"gl_GlobalInvocationID\"\n"
169 "OpDecorate %id BuiltIn GlobalInvocationId\n"
171 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes())
173 + string(getComputeAsmInputOutputBuffer()) +
175 "%id = OpVariable %uvec3ptr Input\n"
176 "%zero = OpConstant %i32 0\n"
178 "%main = OpFunction %void None %voidf\n"
180 "%idval = OpLoad %uvec3 %id\n"
181 "%x = OpCompositeExtract %u32 %idval 0\n"
183 " OpNop\n" // Inside a function body
185 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
186 "%inval = OpLoad %f32 %inloc\n"
187 "%neg = OpFNegate %f32 %inval\n"
188 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
189 " OpStore %outloc %neg\n"
192 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
193 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
194 spec.numWorkGroups = IVec3(numElements, 1, 1);
196 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec));
198 return group.release();
201 bool compareFUnord (const std::vector<BufferSp>& inputs, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog& log)
203 if (outputAllocs.size() != 1)
206 const BufferSp& expectedOutput = expectedOutputs[0];
207 const deInt32* expectedOutputAsInt = static_cast<const deInt32*>(expectedOutputs[0]->data());
208 const deInt32* outputAsInt = static_cast<const deInt32*>(outputAllocs[0]->getHostPtr());
209 const float* input1AsFloat = static_cast<const float*>(inputs[0]->data());
210 const float* input2AsFloat = static_cast<const float*>(inputs[1]->data());
211 bool returnValue = true;
213 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(deInt32); ++idx)
215 if (outputAsInt[idx] != expectedOutputAsInt[idx])
217 log << TestLog::Message << "ERROR: Sub-case failed. inputs: " << input1AsFloat[idx] << "," << input2AsFloat[idx] << " output: " << outputAsInt[idx]<< " expected output: " << expectedOutputAsInt[idx] << TestLog::EndMessage;
224 typedef VkBool32 (*compareFuncType) (float, float);
230 compareFuncType compareFunc;
232 OpFUnordCase (const char* _name, const char* _opCode, compareFuncType _compareFunc)
235 , compareFunc (_compareFunc) {}
238 #define ADD_OPFUNORD_CASE(NAME, OPCODE, OPERATOR) \
240 struct compare_##NAME { static VkBool32 compare(float x, float y) { return (x OPERATOR y) ? VK_TRUE : VK_FALSE; } }; \
241 cases.push_back(OpFUnordCase(#NAME, OPCODE, compare_##NAME::compare)); \
242 } while (deGetFalse())
244 tcu::TestCaseGroup* createOpFUnordGroup (tcu::TestContext& testCtx)
246 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opfunord", "Test the OpFUnord* opcodes"));
247 de::Random rnd (deStringHash(group->getName()));
248 const int numElements = 100;
249 vector<OpFUnordCase> cases;
251 const StringTemplate shaderTemplate (
253 string(getComputeAsmShaderPreamble()) +
255 "OpSource GLSL 430\n"
256 "OpName %main \"main\"\n"
257 "OpName %id \"gl_GlobalInvocationID\"\n"
259 "OpDecorate %id BuiltIn GlobalInvocationId\n"
261 "OpDecorate %buf BufferBlock\n"
262 "OpDecorate %buf2 BufferBlock\n"
263 "OpDecorate %indata1 DescriptorSet 0\n"
264 "OpDecorate %indata1 Binding 0\n"
265 "OpDecorate %indata2 DescriptorSet 0\n"
266 "OpDecorate %indata2 Binding 1\n"
267 "OpDecorate %outdata DescriptorSet 0\n"
268 "OpDecorate %outdata Binding 2\n"
269 "OpDecorate %f32arr ArrayStride 4\n"
270 "OpDecorate %i32arr ArrayStride 4\n"
271 "OpMemberDecorate %buf 0 Offset 0\n"
272 "OpMemberDecorate %buf2 0 Offset 0\n"
274 + string(getComputeAsmCommonTypes()) +
276 "%buf = OpTypeStruct %f32arr\n"
277 "%bufptr = OpTypePointer Uniform %buf\n"
278 "%indata1 = OpVariable %bufptr Uniform\n"
279 "%indata2 = OpVariable %bufptr Uniform\n"
281 "%buf2 = OpTypeStruct %i32arr\n"
282 "%buf2ptr = OpTypePointer Uniform %buf2\n"
283 "%outdata = OpVariable %buf2ptr Uniform\n"
285 "%id = OpVariable %uvec3ptr Input\n"
286 "%zero = OpConstant %i32 0\n"
287 "%consti1 = OpConstant %i32 1\n"
288 "%constf1 = OpConstant %f32 1.0\n"
290 "%main = OpFunction %void None %voidf\n"
292 "%idval = OpLoad %uvec3 %id\n"
293 "%x = OpCompositeExtract %u32 %idval 0\n"
295 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
296 "%inval1 = OpLoad %f32 %inloc1\n"
297 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
298 "%inval2 = OpLoad %f32 %inloc2\n"
299 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n"
301 "%result = ${OPCODE} %bool %inval1 %inval2\n"
302 "%int_res = OpSelect %i32 %result %consti1 %zero\n"
303 " OpStore %outloc %int_res\n"
308 ADD_OPFUNORD_CASE(equal, "OpFUnordEqual", ==);
309 ADD_OPFUNORD_CASE(less, "OpFUnordLessThan", <);
310 ADD_OPFUNORD_CASE(lessequal, "OpFUnordLessThanEqual", <=);
311 ADD_OPFUNORD_CASE(greater, "OpFUnordGreaterThan", >);
312 ADD_OPFUNORD_CASE(greaterequal, "OpFUnordGreaterThanEqual", >=);
313 ADD_OPFUNORD_CASE(notequal, "OpFUnordNotEqual", !=);
315 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
317 map<string, string> specializations;
318 ComputeShaderSpec spec;
319 const float NaN = std::numeric_limits<float>::quiet_NaN();
320 vector<float> inputFloats1 (numElements, 0);
321 vector<float> inputFloats2 (numElements, 0);
322 vector<deInt32> expectedInts (numElements, 0);
324 specializations["OPCODE"] = cases[caseNdx].opCode;
325 spec.assembly = shaderTemplate.specialize(specializations);
327 fillRandomScalars(rnd, 1.f, 100.f, &inputFloats1[0], numElements);
328 for (size_t ndx = 0; ndx < numElements; ++ndx)
332 case 0: inputFloats2[ndx] = inputFloats1[ndx] + 1.0f; break;
333 case 1: inputFloats2[ndx] = inputFloats1[ndx] - 1.0f; break;
334 case 2: inputFloats2[ndx] = inputFloats1[ndx]; break;
335 case 3: inputFloats2[ndx] = NaN; break;
336 case 4: inputFloats2[ndx] = inputFloats1[ndx]; inputFloats1[ndx] = NaN; break;
337 case 5: inputFloats2[ndx] = NaN; inputFloats1[ndx] = NaN; break;
339 expectedInts[ndx] = tcu::Float32(inputFloats1[ndx]).isNaN() || tcu::Float32(inputFloats2[ndx]).isNaN() || cases[caseNdx].compareFunc(inputFloats1[ndx], inputFloats2[ndx]);
342 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
343 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
344 spec.outputs.push_back(BufferSp(new Int32Buffer(expectedInts)));
345 spec.numWorkGroups = IVec3(numElements, 1, 1);
346 spec.verifyIO = &compareFUnord;
347 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
350 return group.release();
356 const char* assembly;
357 void (*calculateExpected)(deInt32&, deInt32);
358 deInt32 numOutputElements;
360 OpAtomicCase (const char* _name, const char* _assembly, void (*_calculateExpected)(deInt32&, deInt32), deInt32 _numOutputElements)
362 , assembly (_assembly)
363 , calculateExpected (_calculateExpected)
364 , numOutputElements (_numOutputElements) {}
367 tcu::TestCaseGroup* createOpAtomicGroup (tcu::TestContext& testCtx, bool useStorageBuffer)
369 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx,
370 useStorageBuffer ? "opatomic_storage_buffer" : "opatomic",
371 "Test the OpAtomic* opcodes"));
372 de::Random rnd (deStringHash(group->getName()));
373 const int numElements = 1000000;
374 vector<OpAtomicCase> cases;
376 const StringTemplate shaderTemplate (
378 string("OpCapability Shader\n") +
379 (useStorageBuffer ? "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n" : "") +
380 "OpMemoryModel Logical GLSL450\n"
381 "OpEntryPoint GLCompute %main \"main\" %id\n"
382 "OpExecutionMode %main LocalSize 1 1 1\n" +
384 "OpSource GLSL 430\n"
385 "OpName %main \"main\"\n"
386 "OpName %id \"gl_GlobalInvocationID\"\n"
388 "OpDecorate %id BuiltIn GlobalInvocationId\n"
390 "OpDecorate %buf ${BLOCK_DECORATION}\n"
391 "OpDecorate %indata DescriptorSet 0\n"
392 "OpDecorate %indata Binding 0\n"
393 "OpDecorate %i32arr ArrayStride 4\n"
394 "OpMemberDecorate %buf 0 Offset 0\n"
396 "OpDecorate %sumbuf ${BLOCK_DECORATION}\n"
397 "OpDecorate %sum DescriptorSet 0\n"
398 "OpDecorate %sum Binding 1\n"
399 "OpMemberDecorate %sumbuf 0 Coherent\n"
400 "OpMemberDecorate %sumbuf 0 Offset 0\n"
402 "%void = OpTypeVoid\n"
403 "%voidf = OpTypeFunction %void\n"
404 "%u32 = OpTypeInt 32 0\n"
405 "%i32 = OpTypeInt 32 1\n"
406 "%uvec3 = OpTypeVector %u32 3\n"
407 "%uvec3ptr = OpTypePointer Input %uvec3\n"
408 "%i32ptr = OpTypePointer ${BLOCK_POINTER_TYPE} %i32\n"
409 "%i32arr = OpTypeRuntimeArray %i32\n"
411 "%buf = OpTypeStruct %i32arr\n"
412 "%bufptr = OpTypePointer ${BLOCK_POINTER_TYPE} %buf\n"
413 "%indata = OpVariable %bufptr ${BLOCK_POINTER_TYPE}\n"
415 "%sumbuf = OpTypeStruct %i32arr\n"
416 "%sumbufptr = OpTypePointer ${BLOCK_POINTER_TYPE} %sumbuf\n"
417 "%sum = OpVariable %sumbufptr ${BLOCK_POINTER_TYPE}\n"
419 "%id = OpVariable %uvec3ptr Input\n"
420 "%minusone = OpConstant %i32 -1\n"
421 "%zero = OpConstant %i32 0\n"
422 "%one = OpConstant %u32 1\n"
423 "%two = OpConstant %i32 2\n"
425 "%main = OpFunction %void None %voidf\n"
427 "%idval = OpLoad %uvec3 %id\n"
428 "%x = OpCompositeExtract %u32 %idval 0\n"
430 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
431 "%inval = OpLoad %i32 %inloc\n"
433 "%outloc = OpAccessChain %i32ptr %sum %zero ${INDEX}\n"
439 #define ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, NUM_OUTPUT_ELEMENTS) \
441 DE_STATIC_ASSERT((NUM_OUTPUT_ELEMENTS) == 1 || (NUM_OUTPUT_ELEMENTS) == numElements); \
442 struct calculateExpected_##NAME { static void calculateExpected(deInt32& expected, deInt32 input) CALCULATE_EXPECTED }; /* NOLINT(CALCULATE_EXPECTED) */ \
443 cases.push_back(OpAtomicCase(#NAME, ASSEMBLY, calculateExpected_##NAME::calculateExpected, NUM_OUTPUT_ELEMENTS)); \
444 } while (deGetFalse())
445 #define ADD_OPATOMIC_CASE_1(NAME, ASSEMBLY, CALCULATE_EXPECTED) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, 1)
446 #define ADD_OPATOMIC_CASE_N(NAME, ASSEMBLY, CALCULATE_EXPECTED) ADD_OPATOMIC_CASE(NAME, ASSEMBLY, CALCULATE_EXPECTED, numElements)
448 ADD_OPATOMIC_CASE_1(iadd, "%unused = OpAtomicIAdd %i32 %outloc %one %zero %inval\n", { expected += input; } );
449 ADD_OPATOMIC_CASE_1(isub, "%unused = OpAtomicISub %i32 %outloc %one %zero %inval\n", { expected -= input; } );
450 ADD_OPATOMIC_CASE_1(iinc, "%unused = OpAtomicIIncrement %i32 %outloc %one %zero\n", { ++expected; (void)input;} );
451 ADD_OPATOMIC_CASE_1(idec, "%unused = OpAtomicIDecrement %i32 %outloc %one %zero\n", { --expected; (void)input;} );
452 ADD_OPATOMIC_CASE_N(load, "%inval2 = OpAtomicLoad %i32 %inloc %zero %zero\n"
453 " OpStore %outloc %inval2\n", { expected = input;} );
454 ADD_OPATOMIC_CASE_N(store, " OpAtomicStore %outloc %zero %zero %inval\n", { expected = input;} );
455 ADD_OPATOMIC_CASE_N(compex, "%even = OpSMod %i32 %inval %two\n"
456 " OpStore %outloc %even\n"
457 "%unused = OpAtomicCompareExchange %i32 %outloc %one %zero %zero %minusone %zero\n", { expected = (input % 2) == 0 ? -1 : 1;} );
459 #undef ADD_OPATOMIC_CASE
460 #undef ADD_OPATOMIC_CASE_1
461 #undef ADD_OPATOMIC_CASE_N
463 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
465 map<string, string> specializations;
466 ComputeShaderSpec spec;
467 vector<deInt32> inputInts (numElements, 0);
468 vector<deInt32> expected (cases[caseNdx].numOutputElements, -1);
470 specializations["INDEX"] = (cases[caseNdx].numOutputElements == 1) ? "%zero" : "%x";
471 specializations["INSTRUCTION"] = cases[caseNdx].assembly;
472 specializations["BLOCK_DECORATION"] = useStorageBuffer ? "Block" : "BufferBlock";
473 specializations["BLOCK_POINTER_TYPE"] = useStorageBuffer ? "StorageBuffer" : "Uniform";
474 spec.assembly = shaderTemplate.specialize(specializations);
476 if (useStorageBuffer)
477 spec.extensions.push_back("VK_KHR_storage_buffer_storage_class");
479 fillRandomScalars(rnd, 1, 100, &inputInts[0], numElements);
480 for (size_t ndx = 0; ndx < numElements; ++ndx)
482 cases[caseNdx].calculateExpected((cases[caseNdx].numOutputElements == 1) ? expected[0] : expected[ndx], inputInts[ndx]);
485 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
486 spec.outputs.push_back(BufferSp(new Int32Buffer(expected)));
487 spec.numWorkGroups = IVec3(numElements, 1, 1);
488 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
491 return group.release();
494 tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx)
496 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction"));
497 ComputeShaderSpec spec;
498 de::Random rnd (deStringHash(group->getName()));
499 const int numElements = 100;
500 vector<float> positiveFloats (numElements, 0);
501 vector<float> negativeFloats (numElements, 0);
503 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
505 for (size_t ndx = 0; ndx < numElements; ++ndx)
506 negativeFloats[ndx] = -positiveFloats[ndx];
509 string(getComputeAsmShaderPreamble()) +
511 "%fname1 = OpString \"negateInputs.comp\"\n"
512 "%fname2 = OpString \"negateInputs\"\n"
514 "OpSource GLSL 430\n"
515 "OpName %main \"main\"\n"
516 "OpName %id \"gl_GlobalInvocationID\"\n"
518 "OpDecorate %id BuiltIn GlobalInvocationId\n"
520 + string(getComputeAsmInputOutputBufferTraits()) +
522 "OpLine %fname1 0 0\n" // At the earliest possible position
524 + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
526 "OpLine %fname1 0 1\n" // Multiple OpLines in sequence
527 "OpLine %fname2 1 0\n" // Different filenames
528 "OpLine %fname1 1000 100000\n"
530 "%id = OpVariable %uvec3ptr Input\n"
531 "%zero = OpConstant %i32 0\n"
533 "OpLine %fname1 1 1\n" // Before a function
535 "%main = OpFunction %void None %voidf\n"
538 "OpLine %fname1 1 1\n" // In a function
540 "%idval = OpLoad %uvec3 %id\n"
541 "%x = OpCompositeExtract %u32 %idval 0\n"
542 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
543 "%inval = OpLoad %f32 %inloc\n"
544 "%neg = OpFNegate %f32 %inval\n"
545 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
546 " OpStore %outloc %neg\n"
549 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
550 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
551 spec.numWorkGroups = IVec3(numElements, 1, 1);
553 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec));
555 return group.release();
558 tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx)
560 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction"));
561 ComputeShaderSpec spec;
562 de::Random rnd (deStringHash(group->getName()));
563 const int numElements = 100;
564 vector<float> positiveFloats (numElements, 0);
565 vector<float> negativeFloats (numElements, 0);
567 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
569 for (size_t ndx = 0; ndx < numElements; ++ndx)
570 negativeFloats[ndx] = -positiveFloats[ndx];
573 string(getComputeAsmShaderPreamble()) +
575 "%fname = OpString \"negateInputs.comp\"\n"
577 "OpSource GLSL 430\n"
578 "OpName %main \"main\"\n"
579 "OpName %id \"gl_GlobalInvocationID\"\n"
581 "OpDecorate %id BuiltIn GlobalInvocationId\n"
583 + string(getComputeAsmInputOutputBufferTraits()) +
585 "OpNoLine\n" // At the earliest possible position, without preceding OpLine
587 + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
589 "OpLine %fname 0 1\n"
590 "OpNoLine\n" // Immediately following a preceding OpLine
592 "OpLine %fname 1000 1\n"
594 "%id = OpVariable %uvec3ptr Input\n"
595 "%zero = OpConstant %i32 0\n"
597 "OpNoLine\n" // Contents after the previous OpLine
599 "%main = OpFunction %void None %voidf\n"
601 "%idval = OpLoad %uvec3 %id\n"
602 "%x = OpCompositeExtract %u32 %idval 0\n"
604 "OpNoLine\n" // Multiple OpNoLine
608 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
609 "%inval = OpLoad %f32 %inloc\n"
610 "%neg = OpFNegate %f32 %inval\n"
611 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
612 " OpStore %outloc %neg\n"
615 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
616 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
617 spec.numWorkGroups = IVec3(numElements, 1, 1);
619 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec));
621 return group.release();
624 // Compare instruction for the contraction compute case.
625 // Returns true if the output is what is expected from the test case.
626 bool compareNoContractCase(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
628 if (outputAllocs.size() != 1)
631 // We really just need this for size because we are not comparing the exact values.
632 const BufferSp& expectedOutput = expectedOutputs[0];
633 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
635 for(size_t i = 0; i < expectedOutput->getNumBytes() / sizeof(float); ++i) {
636 if (outputAsFloat[i] != 0.f &&
637 outputAsFloat[i] != -ldexp(1, -24)) {
645 tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx)
647 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration"));
648 vector<CaseParameter> cases;
649 const int numElements = 100;
650 vector<float> inputFloats1 (numElements, 0);
651 vector<float> inputFloats2 (numElements, 0);
652 vector<float> outputFloats (numElements, 0);
653 const StringTemplate shaderTemplate (
654 string(getComputeAsmShaderPreamble()) +
656 "OpName %main \"main\"\n"
657 "OpName %id \"gl_GlobalInvocationID\"\n"
659 "OpDecorate %id BuiltIn GlobalInvocationId\n"
663 "OpDecorate %buf BufferBlock\n"
664 "OpDecorate %indata1 DescriptorSet 0\n"
665 "OpDecorate %indata1 Binding 0\n"
666 "OpDecorate %indata2 DescriptorSet 0\n"
667 "OpDecorate %indata2 Binding 1\n"
668 "OpDecorate %outdata DescriptorSet 0\n"
669 "OpDecorate %outdata Binding 2\n"
670 "OpDecorate %f32arr ArrayStride 4\n"
671 "OpMemberDecorate %buf 0 Offset 0\n"
673 + string(getComputeAsmCommonTypes()) +
675 "%buf = OpTypeStruct %f32arr\n"
676 "%bufptr = OpTypePointer Uniform %buf\n"
677 "%indata1 = OpVariable %bufptr Uniform\n"
678 "%indata2 = OpVariable %bufptr Uniform\n"
679 "%outdata = OpVariable %bufptr Uniform\n"
681 "%id = OpVariable %uvec3ptr Input\n"
682 "%zero = OpConstant %i32 0\n"
683 "%c_f_m1 = OpConstant %f32 -1.\n"
685 "%main = OpFunction %void None %voidf\n"
687 "%idval = OpLoad %uvec3 %id\n"
688 "%x = OpCompositeExtract %u32 %idval 0\n"
689 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
690 "%inval1 = OpLoad %f32 %inloc1\n"
691 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
692 "%inval2 = OpLoad %f32 %inloc2\n"
693 "%mul = OpFMul %f32 %inval1 %inval2\n"
694 "%add = OpFAdd %f32 %mul %c_f_m1\n"
695 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
696 " OpStore %outloc %add\n"
700 cases.push_back(CaseParameter("multiplication", "OpDecorate %mul NoContraction"));
701 cases.push_back(CaseParameter("addition", "OpDecorate %add NoContraction"));
702 cases.push_back(CaseParameter("both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction"));
704 for (size_t ndx = 0; ndx < numElements; ++ndx)
706 inputFloats1[ndx] = 1.f + std::ldexp(1.f, -23); // 1 + 2^-23.
707 inputFloats2[ndx] = 1.f - std::ldexp(1.f, -23); // 1 - 2^-23.
708 // Result for (1 + 2^-23) * (1 - 2^-23) - 1. With NoContraction, the multiplication will be
709 // conducted separately and the result is rounded to 1, or 0x1.fffffcp-1
710 // So the final result will be 0.f or 0x1p-24.
711 // If the operation is combined into a precise fused multiply-add, then the result would be
712 // 2^-46 (0xa8800000).
713 outputFloats[ndx] = 0.f;
716 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
718 map<string, string> specializations;
719 ComputeShaderSpec spec;
721 specializations["DECORATION"] = cases[caseNdx].param;
722 spec.assembly = shaderTemplate.specialize(specializations);
723 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
724 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
725 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
726 spec.numWorkGroups = IVec3(numElements, 1, 1);
727 // Check against the two possible answers based on rounding mode.
728 spec.verifyIO = &compareNoContractCase;
730 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
732 return group.release();
735 bool compareFRem(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
737 if (outputAllocs.size() != 1)
740 const BufferSp& expectedOutput = expectedOutputs[0];
741 const float *expectedOutputAsFloat = static_cast<const float*>(expectedOutput->data());
742 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
744 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx)
746 const float f0 = expectedOutputAsFloat[idx];
747 const float f1 = outputAsFloat[idx];
748 // \todo relative error needs to be fairly high because FRem may be implemented as
749 // (roughly) frac(a/b)*b, so LSB errors can be magnified. But this should be fine for now.
750 if (deFloatAbs((f1 - f0) / f0) > 0.02)
757 tcu::TestCaseGroup* createOpFRemGroup (tcu::TestContext& testCtx)
759 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opfrem", "Test the OpFRem instruction"));
760 ComputeShaderSpec spec;
761 de::Random rnd (deStringHash(group->getName()));
762 const int numElements = 200;
763 vector<float> inputFloats1 (numElements, 0);
764 vector<float> inputFloats2 (numElements, 0);
765 vector<float> outputFloats (numElements, 0);
767 fillRandomScalars(rnd, -10000.f, 10000.f, &inputFloats1[0], numElements);
768 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats2[0], numElements);
770 for (size_t ndx = 0; ndx < numElements; ++ndx)
772 // Guard against divisors near zero.
773 if (std::fabs(inputFloats2[ndx]) < 1e-3)
774 inputFloats2[ndx] = 8.f;
776 // The return value of std::fmod() has the same sign as its first operand, which is how OpFRem spec'd.
777 outputFloats[ndx] = std::fmod(inputFloats1[ndx], inputFloats2[ndx]);
781 string(getComputeAsmShaderPreamble()) +
783 "OpName %main \"main\"\n"
784 "OpName %id \"gl_GlobalInvocationID\"\n"
786 "OpDecorate %id BuiltIn GlobalInvocationId\n"
788 "OpDecorate %buf BufferBlock\n"
789 "OpDecorate %indata1 DescriptorSet 0\n"
790 "OpDecorate %indata1 Binding 0\n"
791 "OpDecorate %indata2 DescriptorSet 0\n"
792 "OpDecorate %indata2 Binding 1\n"
793 "OpDecorate %outdata DescriptorSet 0\n"
794 "OpDecorate %outdata Binding 2\n"
795 "OpDecorate %f32arr ArrayStride 4\n"
796 "OpMemberDecorate %buf 0 Offset 0\n"
798 + string(getComputeAsmCommonTypes()) +
800 "%buf = OpTypeStruct %f32arr\n"
801 "%bufptr = OpTypePointer Uniform %buf\n"
802 "%indata1 = OpVariable %bufptr Uniform\n"
803 "%indata2 = OpVariable %bufptr Uniform\n"
804 "%outdata = OpVariable %bufptr Uniform\n"
806 "%id = OpVariable %uvec3ptr Input\n"
807 "%zero = OpConstant %i32 0\n"
809 "%main = OpFunction %void None %voidf\n"
811 "%idval = OpLoad %uvec3 %id\n"
812 "%x = OpCompositeExtract %u32 %idval 0\n"
813 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
814 "%inval1 = OpLoad %f32 %inloc1\n"
815 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
816 "%inval2 = OpLoad %f32 %inloc2\n"
817 "%rem = OpFRem %f32 %inval1 %inval2\n"
818 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
819 " OpStore %outloc %rem\n"
823 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
824 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
825 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
826 spec.numWorkGroups = IVec3(numElements, 1, 1);
827 spec.verifyIO = &compareFRem;
829 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "", spec));
831 return group.release();
834 // Copy contents in the input buffer to the output buffer.
835 tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx)
837 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopymemory", "Test the OpCopyMemory instruction"));
838 de::Random rnd (deStringHash(group->getName()));
839 const int numElements = 100;
841 // 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.
842 ComputeShaderSpec spec1;
843 vector<Vec4> inputFloats1 (numElements);
844 vector<Vec4> outputFloats1 (numElements);
846 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats1[0], numElements * 4);
848 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
849 floorAll(inputFloats1);
851 for (size_t ndx = 0; ndx < numElements; ++ndx)
852 outputFloats1[ndx] = inputFloats1[ndx] + Vec4(0.f, 0.5f, 1.5f, 2.5f);
855 string(getComputeAsmShaderPreamble()) +
857 "OpName %main \"main\"\n"
858 "OpName %id \"gl_GlobalInvocationID\"\n"
860 "OpDecorate %id BuiltIn GlobalInvocationId\n"
861 "OpDecorate %vec4arr ArrayStride 16\n"
863 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
865 "%vec4 = OpTypeVector %f32 4\n"
866 "%vec4ptr_u = OpTypePointer Uniform %vec4\n"
867 "%vec4ptr_f = OpTypePointer Function %vec4\n"
868 "%vec4arr = OpTypeRuntimeArray %vec4\n"
869 "%buf = OpTypeStruct %vec4arr\n"
870 "%bufptr = OpTypePointer Uniform %buf\n"
871 "%indata = OpVariable %bufptr Uniform\n"
872 "%outdata = OpVariable %bufptr Uniform\n"
874 "%id = OpVariable %uvec3ptr Input\n"
875 "%zero = OpConstant %i32 0\n"
876 "%c_f_0 = OpConstant %f32 0.\n"
877 "%c_f_0_5 = OpConstant %f32 0.5\n"
878 "%c_f_1_5 = OpConstant %f32 1.5\n"
879 "%c_f_2_5 = OpConstant %f32 2.5\n"
880 "%c_vec4 = OpConstantComposite %vec4 %c_f_0 %c_f_0_5 %c_f_1_5 %c_f_2_5\n"
882 "%main = OpFunction %void None %voidf\n"
884 "%v_vec4 = OpVariable %vec4ptr_f Function\n"
885 "%idval = OpLoad %uvec3 %id\n"
886 "%x = OpCompositeExtract %u32 %idval 0\n"
887 "%inloc = OpAccessChain %vec4ptr_u %indata %zero %x\n"
888 "%outloc = OpAccessChain %vec4ptr_u %outdata %zero %x\n"
889 " OpCopyMemory %v_vec4 %inloc\n"
890 "%v_vec4_val = OpLoad %vec4 %v_vec4\n"
891 "%add = OpFAdd %vec4 %v_vec4_val %c_vec4\n"
892 " OpStore %outloc %add\n"
896 spec1.inputs.push_back(BufferSp(new Vec4Buffer(inputFloats1)));
897 spec1.outputs.push_back(BufferSp(new Vec4Buffer(outputFloats1)));
898 spec1.numWorkGroups = IVec3(numElements, 1, 1);
900 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector", "OpCopyMemory elements of vector type", spec1));
902 // The following case copies a float[100] variable from the input buffer to the output buffer.
903 ComputeShaderSpec spec2;
904 vector<float> inputFloats2 (numElements);
905 vector<float> outputFloats2 (numElements);
907 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats2[0], numElements);
909 for (size_t ndx = 0; ndx < numElements; ++ndx)
910 outputFloats2[ndx] = inputFloats2[ndx];
913 string(getComputeAsmShaderPreamble()) +
915 "OpName %main \"main\"\n"
916 "OpName %id \"gl_GlobalInvocationID\"\n"
918 "OpDecorate %id BuiltIn GlobalInvocationId\n"
919 "OpDecorate %f32arr100 ArrayStride 4\n"
921 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
923 "%hundred = OpConstant %u32 100\n"
924 "%f32arr100 = OpTypeArray %f32 %hundred\n"
925 "%f32arr100ptr_f = OpTypePointer Function %f32arr100\n"
926 "%f32arr100ptr_u = OpTypePointer Uniform %f32arr100\n"
927 "%buf = OpTypeStruct %f32arr100\n"
928 "%bufptr = OpTypePointer Uniform %buf\n"
929 "%indata = OpVariable %bufptr Uniform\n"
930 "%outdata = OpVariable %bufptr Uniform\n"
932 "%id = OpVariable %uvec3ptr Input\n"
933 "%zero = OpConstant %i32 0\n"
935 "%main = OpFunction %void None %voidf\n"
937 "%var = OpVariable %f32arr100ptr_f Function\n"
938 "%inarr = OpAccessChain %f32arr100ptr_u %indata %zero\n"
939 "%outarr = OpAccessChain %f32arr100ptr_u %outdata %zero\n"
940 " OpCopyMemory %var %inarr\n"
941 " OpCopyMemory %outarr %var\n"
945 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
946 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
947 spec2.numWorkGroups = IVec3(1, 1, 1);
949 group->addChild(new SpvAsmComputeShaderCase(testCtx, "array", "OpCopyMemory elements of array type", spec2));
951 // The following case copies a struct{vec4, vec4, vec4, vec4} variable from the input buffer to the output buffer.
952 ComputeShaderSpec spec3;
953 vector<float> inputFloats3 (16);
954 vector<float> outputFloats3 (16);
956 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats3[0], 16);
958 for (size_t ndx = 0; ndx < 16; ++ndx)
959 outputFloats3[ndx] = inputFloats3[ndx];
962 string(getComputeAsmShaderPreamble()) +
964 "OpName %main \"main\"\n"
965 "OpName %id \"gl_GlobalInvocationID\"\n"
967 "OpDecorate %id BuiltIn GlobalInvocationId\n"
968 "OpMemberDecorate %buf 0 Offset 0\n"
969 "OpMemberDecorate %buf 1 Offset 16\n"
970 "OpMemberDecorate %buf 2 Offset 32\n"
971 "OpMemberDecorate %buf 3 Offset 48\n"
973 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
975 "%vec4 = OpTypeVector %f32 4\n"
976 "%buf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n"
977 "%bufptr = OpTypePointer Uniform %buf\n"
978 "%indata = OpVariable %bufptr Uniform\n"
979 "%outdata = OpVariable %bufptr Uniform\n"
980 "%vec4stptr = OpTypePointer Function %buf\n"
982 "%id = OpVariable %uvec3ptr Input\n"
983 "%zero = OpConstant %i32 0\n"
985 "%main = OpFunction %void None %voidf\n"
987 "%var = OpVariable %vec4stptr Function\n"
988 " OpCopyMemory %var %indata\n"
989 " OpCopyMemory %outdata %var\n"
993 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
994 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3)));
995 spec3.numWorkGroups = IVec3(1, 1, 1);
997 group->addChild(new SpvAsmComputeShaderCase(testCtx, "struct", "OpCopyMemory elements of struct type", spec3));
999 // The following case negates multiple float variables from the input buffer and stores the results to the output buffer.
1000 ComputeShaderSpec spec4;
1001 vector<float> inputFloats4 (numElements);
1002 vector<float> outputFloats4 (numElements);
1004 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats4[0], numElements);
1006 for (size_t ndx = 0; ndx < numElements; ++ndx)
1007 outputFloats4[ndx] = -inputFloats4[ndx];
1010 string(getComputeAsmShaderPreamble()) +
1012 "OpName %main \"main\"\n"
1013 "OpName %id \"gl_GlobalInvocationID\"\n"
1015 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1017 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
1019 "%f32ptr_f = OpTypePointer Function %f32\n"
1020 "%id = OpVariable %uvec3ptr Input\n"
1021 "%zero = OpConstant %i32 0\n"
1023 "%main = OpFunction %void None %voidf\n"
1024 "%label = OpLabel\n"
1025 "%var = OpVariable %f32ptr_f Function\n"
1026 "%idval = OpLoad %uvec3 %id\n"
1027 "%x = OpCompositeExtract %u32 %idval 0\n"
1028 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1029 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1030 " OpCopyMemory %var %inloc\n"
1031 "%val = OpLoad %f32 %var\n"
1032 "%neg = OpFNegate %f32 %val\n"
1033 " OpStore %outloc %neg\n"
1037 spec4.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
1038 spec4.outputs.push_back(BufferSp(new Float32Buffer(outputFloats4)));
1039 spec4.numWorkGroups = IVec3(numElements, 1, 1);
1041 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float", "OpCopyMemory elements of float type", spec4));
1043 return group.release();
1046 tcu::TestCaseGroup* createOpCopyObjectGroup (tcu::TestContext& testCtx)
1048 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopyobject", "Test the OpCopyObject instruction"));
1049 ComputeShaderSpec spec;
1050 de::Random rnd (deStringHash(group->getName()));
1051 const int numElements = 100;
1052 vector<float> inputFloats (numElements, 0);
1053 vector<float> outputFloats (numElements, 0);
1055 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
1057 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
1058 floorAll(inputFloats);
1060 for (size_t ndx = 0; ndx < numElements; ++ndx)
1061 outputFloats[ndx] = inputFloats[ndx] + 7.5f;
1064 string(getComputeAsmShaderPreamble()) +
1066 "OpName %main \"main\"\n"
1067 "OpName %id \"gl_GlobalInvocationID\"\n"
1069 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1071 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
1073 "%fmat = OpTypeMatrix %fvec3 3\n"
1074 "%three = OpConstant %u32 3\n"
1075 "%farr = OpTypeArray %f32 %three\n"
1076 "%fst = OpTypeStruct %f32 %f32\n"
1078 + string(getComputeAsmInputOutputBuffer()) +
1080 "%id = OpVariable %uvec3ptr Input\n"
1081 "%zero = OpConstant %i32 0\n"
1082 "%c_f = OpConstant %f32 1.5\n"
1083 "%c_fvec3 = OpConstantComposite %fvec3 %c_f %c_f %c_f\n"
1084 "%c_fmat = OpConstantComposite %fmat %c_fvec3 %c_fvec3 %c_fvec3\n"
1085 "%c_farr = OpConstantComposite %farr %c_f %c_f %c_f\n"
1086 "%c_fst = OpConstantComposite %fst %c_f %c_f\n"
1088 "%main = OpFunction %void None %voidf\n"
1089 "%label = OpLabel\n"
1090 "%c_f_copy = OpCopyObject %f32 %c_f\n"
1091 "%c_fvec3_copy = OpCopyObject %fvec3 %c_fvec3\n"
1092 "%c_fmat_copy = OpCopyObject %fmat %c_fmat\n"
1093 "%c_farr_copy = OpCopyObject %farr %c_farr\n"
1094 "%c_fst_copy = OpCopyObject %fst %c_fst\n"
1095 "%fvec3_elem = OpCompositeExtract %f32 %c_fvec3_copy 0\n"
1096 "%fmat_elem = OpCompositeExtract %f32 %c_fmat_copy 1 2\n"
1097 "%farr_elem = OpCompositeExtract %f32 %c_farr_copy 2\n"
1098 "%fst_elem = OpCompositeExtract %f32 %c_fst_copy 1\n"
1099 // Add up. 1.5 * 5 = 7.5.
1100 "%add1 = OpFAdd %f32 %c_f_copy %fvec3_elem\n"
1101 "%add2 = OpFAdd %f32 %add1 %fmat_elem\n"
1102 "%add3 = OpFAdd %f32 %add2 %farr_elem\n"
1103 "%add4 = OpFAdd %f32 %add3 %fst_elem\n"
1105 "%idval = OpLoad %uvec3 %id\n"
1106 "%x = OpCompositeExtract %u32 %idval 0\n"
1107 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1108 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1109 "%inval = OpLoad %f32 %inloc\n"
1110 "%add = OpFAdd %f32 %add4 %inval\n"
1111 " OpStore %outloc %add\n"
1114 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1115 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1116 spec.numWorkGroups = IVec3(numElements, 1, 1);
1118 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "OpCopyObject on different types", spec));
1120 return group.release();
1122 // Assembly code used for testing OpUnreachable is based on GLSL source code:
1126 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1127 // float elements[];
1129 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1130 // float elements[];
1133 // void not_called_func() {
1134 // // place OpUnreachable here
1137 // uint modulo4(uint val) {
1138 // switch (val % uint(4)) {
1139 // case 0: return 3;
1140 // case 1: return 2;
1141 // case 2: return 1;
1142 // case 3: return 0;
1143 // default: return 100; // place OpUnreachable here
1149 // // place OpUnreachable here
1153 // uint x = gl_GlobalInvocationID.x;
1154 // if (const5() > modulo4(1000)) {
1155 // output_data.elements[x] = -input_data.elements[x];
1157 // // place OpUnreachable here
1158 // output_data.elements[x] = input_data.elements[x];
1162 tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx)
1164 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opunreachable", "Test the OpUnreachable instruction"));
1165 ComputeShaderSpec spec;
1166 de::Random rnd (deStringHash(group->getName()));
1167 const int numElements = 100;
1168 vector<float> positiveFloats (numElements, 0);
1169 vector<float> negativeFloats (numElements, 0);
1171 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
1173 for (size_t ndx = 0; ndx < numElements; ++ndx)
1174 negativeFloats[ndx] = -positiveFloats[ndx];
1177 string(getComputeAsmShaderPreamble()) +
1179 "OpSource GLSL 430\n"
1180 "OpName %main \"main\"\n"
1181 "OpName %func_not_called_func \"not_called_func(\"\n"
1182 "OpName %func_modulo4 \"modulo4(u1;\"\n"
1183 "OpName %func_const5 \"const5(\"\n"
1184 "OpName %id \"gl_GlobalInvocationID\"\n"
1186 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1188 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
1190 "%u32ptr = OpTypePointer Function %u32\n"
1191 "%uintfuint = OpTypeFunction %u32 %u32ptr\n"
1192 "%unitf = OpTypeFunction %u32\n"
1194 "%id = OpVariable %uvec3ptr Input\n"
1195 "%zero = OpConstant %u32 0\n"
1196 "%one = OpConstant %u32 1\n"
1197 "%two = OpConstant %u32 2\n"
1198 "%three = OpConstant %u32 3\n"
1199 "%four = OpConstant %u32 4\n"
1200 "%five = OpConstant %u32 5\n"
1201 "%hundred = OpConstant %u32 100\n"
1202 "%thousand = OpConstant %u32 1000\n"
1204 + string(getComputeAsmInputOutputBuffer()) +
1207 "%main = OpFunction %void None %voidf\n"
1208 "%main_entry = OpLabel\n"
1209 "%v_thousand = OpVariable %u32ptr Function %thousand\n"
1210 "%idval = OpLoad %uvec3 %id\n"
1211 "%x = OpCompositeExtract %u32 %idval 0\n"
1212 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1213 "%inval = OpLoad %f32 %inloc\n"
1214 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1215 "%ret_const5 = OpFunctionCall %u32 %func_const5\n"
1216 "%ret_modulo4 = OpFunctionCall %u32 %func_modulo4 %v_thousand\n"
1217 "%cmp_gt = OpUGreaterThan %bool %ret_const5 %ret_modulo4\n"
1218 " OpSelectionMerge %if_end None\n"
1219 " OpBranchConditional %cmp_gt %if_true %if_false\n"
1220 "%if_true = OpLabel\n"
1221 "%negate = OpFNegate %f32 %inval\n"
1222 " OpStore %outloc %negate\n"
1223 " OpBranch %if_end\n"
1224 "%if_false = OpLabel\n"
1225 " OpUnreachable\n" // Unreachable else branch for if statement
1226 "%if_end = OpLabel\n"
1230 // not_called_function()
1231 "%func_not_called_func = OpFunction %void None %voidf\n"
1232 "%not_called_func_entry = OpLabel\n"
1233 " OpUnreachable\n" // Unreachable entry block in not called static function
1237 "%func_modulo4 = OpFunction %u32 None %uintfuint\n"
1238 "%valptr = OpFunctionParameter %u32ptr\n"
1239 "%modulo4_entry = OpLabel\n"
1240 "%val = OpLoad %u32 %valptr\n"
1241 "%modulo = OpUMod %u32 %val %four\n"
1242 " OpSelectionMerge %switch_merge None\n"
1243 " OpSwitch %modulo %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
1244 "%case0 = OpLabel\n"
1245 " OpReturnValue %three\n"
1246 "%case1 = OpLabel\n"
1247 " OpReturnValue %two\n"
1248 "%case2 = OpLabel\n"
1249 " OpReturnValue %one\n"
1250 "%case3 = OpLabel\n"
1251 " OpReturnValue %zero\n"
1252 "%default = OpLabel\n"
1253 " OpUnreachable\n" // Unreachable default case for switch statement
1254 "%switch_merge = OpLabel\n"
1255 " OpUnreachable\n" // Unreachable merge block for switch statement
1259 "%func_const5 = OpFunction %u32 None %unitf\n"
1260 "%const5_entry = OpLabel\n"
1261 " OpReturnValue %five\n"
1262 "%unreachable = OpLabel\n"
1263 " OpUnreachable\n" // Unreachable block in function
1265 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
1266 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
1267 spec.numWorkGroups = IVec3(numElements, 1, 1);
1269 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec));
1271 return group.release();
1274 // Assembly code used for testing decoration group is based on GLSL source code:
1278 // layout(std140, set = 0, binding = 0) readonly buffer Input0 {
1279 // float elements[];
1281 // layout(std140, set = 0, binding = 1) readonly buffer Input1 {
1282 // float elements[];
1284 // layout(std140, set = 0, binding = 2) readonly buffer Input2 {
1285 // float elements[];
1287 // layout(std140, set = 0, binding = 3) readonly buffer Input3 {
1288 // float elements[];
1290 // layout(std140, set = 0, binding = 4) readonly buffer Input4 {
1291 // float elements[];
1293 // layout(std140, set = 0, binding = 5) writeonly buffer Output {
1294 // float elements[];
1298 // uint x = gl_GlobalInvocationID.x;
1299 // output_data.elements[x] = input_data0.elements[x] + input_data1.elements[x] + input_data2.elements[x] + input_data3.elements[x] + input_data4.elements[x];
1301 tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx)
1303 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Test the OpDecorationGroup & OpGroupDecorate instruction"));
1304 ComputeShaderSpec spec;
1305 de::Random rnd (deStringHash(group->getName()));
1306 const int numElements = 100;
1307 vector<float> inputFloats0 (numElements, 0);
1308 vector<float> inputFloats1 (numElements, 0);
1309 vector<float> inputFloats2 (numElements, 0);
1310 vector<float> inputFloats3 (numElements, 0);
1311 vector<float> inputFloats4 (numElements, 0);
1312 vector<float> outputFloats (numElements, 0);
1314 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats0[0], numElements);
1315 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats1[0], numElements);
1316 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats2[0], numElements);
1317 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats3[0], numElements);
1318 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats4[0], numElements);
1320 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
1321 floorAll(inputFloats0);
1322 floorAll(inputFloats1);
1323 floorAll(inputFloats2);
1324 floorAll(inputFloats3);
1325 floorAll(inputFloats4);
1327 for (size_t ndx = 0; ndx < numElements; ++ndx)
1328 outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx];
1331 string(getComputeAsmShaderPreamble()) +
1333 "OpSource GLSL 430\n"
1334 "OpName %main \"main\"\n"
1335 "OpName %id \"gl_GlobalInvocationID\"\n"
1337 // Not using group decoration on variable.
1338 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1339 // Not using group decoration on type.
1340 "OpDecorate %f32arr ArrayStride 4\n"
1342 "OpDecorate %groups BufferBlock\n"
1343 "OpDecorate %groupm Offset 0\n"
1344 "%groups = OpDecorationGroup\n"
1345 "%groupm = OpDecorationGroup\n"
1347 // Group decoration on multiple structs.
1348 "OpGroupDecorate %groups %outbuf %inbuf0 %inbuf1 %inbuf2 %inbuf3 %inbuf4\n"
1349 // Group decoration on multiple struct members.
1350 "OpGroupMemberDecorate %groupm %outbuf 0 %inbuf0 0 %inbuf1 0 %inbuf2 0 %inbuf3 0 %inbuf4 0\n"
1352 "OpDecorate %group1 DescriptorSet 0\n"
1353 "OpDecorate %group3 DescriptorSet 0\n"
1354 "OpDecorate %group3 NonWritable\n"
1355 "OpDecorate %group3 Restrict\n"
1356 "%group0 = OpDecorationGroup\n"
1357 "%group1 = OpDecorationGroup\n"
1358 "%group3 = OpDecorationGroup\n"
1360 // Applying the same decoration group multiple times.
1361 "OpGroupDecorate %group1 %outdata\n"
1362 "OpGroupDecorate %group1 %outdata\n"
1363 "OpGroupDecorate %group1 %outdata\n"
1364 "OpDecorate %outdata DescriptorSet 0\n"
1365 "OpDecorate %outdata Binding 5\n"
1366 // Applying decoration group containing nothing.
1367 "OpGroupDecorate %group0 %indata0\n"
1368 "OpDecorate %indata0 DescriptorSet 0\n"
1369 "OpDecorate %indata0 Binding 0\n"
1370 // Applying decoration group containing one decoration.
1371 "OpGroupDecorate %group1 %indata1\n"
1372 "OpDecorate %indata1 Binding 1\n"
1373 // Applying decoration group containing multiple decorations.
1374 "OpGroupDecorate %group3 %indata2 %indata3\n"
1375 "OpDecorate %indata2 Binding 2\n"
1376 "OpDecorate %indata3 Binding 3\n"
1377 // Applying multiple decoration groups (with overlapping).
1378 "OpGroupDecorate %group0 %indata4\n"
1379 "OpGroupDecorate %group1 %indata4\n"
1380 "OpGroupDecorate %group3 %indata4\n"
1381 "OpDecorate %indata4 Binding 4\n"
1383 + string(getComputeAsmCommonTypes()) +
1385 "%id = OpVariable %uvec3ptr Input\n"
1386 "%zero = OpConstant %i32 0\n"
1388 "%outbuf = OpTypeStruct %f32arr\n"
1389 "%outbufptr = OpTypePointer Uniform %outbuf\n"
1390 "%outdata = OpVariable %outbufptr Uniform\n"
1391 "%inbuf0 = OpTypeStruct %f32arr\n"
1392 "%inbuf0ptr = OpTypePointer Uniform %inbuf0\n"
1393 "%indata0 = OpVariable %inbuf0ptr Uniform\n"
1394 "%inbuf1 = OpTypeStruct %f32arr\n"
1395 "%inbuf1ptr = OpTypePointer Uniform %inbuf1\n"
1396 "%indata1 = OpVariable %inbuf1ptr Uniform\n"
1397 "%inbuf2 = OpTypeStruct %f32arr\n"
1398 "%inbuf2ptr = OpTypePointer Uniform %inbuf2\n"
1399 "%indata2 = OpVariable %inbuf2ptr Uniform\n"
1400 "%inbuf3 = OpTypeStruct %f32arr\n"
1401 "%inbuf3ptr = OpTypePointer Uniform %inbuf3\n"
1402 "%indata3 = OpVariable %inbuf3ptr Uniform\n"
1403 "%inbuf4 = OpTypeStruct %f32arr\n"
1404 "%inbufptr = OpTypePointer Uniform %inbuf4\n"
1405 "%indata4 = OpVariable %inbufptr Uniform\n"
1407 "%main = OpFunction %void None %voidf\n"
1408 "%label = OpLabel\n"
1409 "%idval = OpLoad %uvec3 %id\n"
1410 "%x = OpCompositeExtract %u32 %idval 0\n"
1411 "%inloc0 = OpAccessChain %f32ptr %indata0 %zero %x\n"
1412 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n"
1413 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n"
1414 "%inloc3 = OpAccessChain %f32ptr %indata3 %zero %x\n"
1415 "%inloc4 = OpAccessChain %f32ptr %indata4 %zero %x\n"
1416 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1417 "%inval0 = OpLoad %f32 %inloc0\n"
1418 "%inval1 = OpLoad %f32 %inloc1\n"
1419 "%inval2 = OpLoad %f32 %inloc2\n"
1420 "%inval3 = OpLoad %f32 %inloc3\n"
1421 "%inval4 = OpLoad %f32 %inloc4\n"
1422 "%add0 = OpFAdd %f32 %inval0 %inval1\n"
1423 "%add1 = OpFAdd %f32 %add0 %inval2\n"
1424 "%add2 = OpFAdd %f32 %add1 %inval3\n"
1425 "%add = OpFAdd %f32 %add2 %inval4\n"
1426 " OpStore %outloc %add\n"
1429 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats0)));
1430 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1)));
1431 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2)));
1432 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3)));
1433 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4)));
1434 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1435 spec.numWorkGroups = IVec3(numElements, 1, 1);
1437 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec));
1439 return group.release();
1442 struct SpecConstantTwoIntCase
1444 const char* caseName;
1445 const char* scDefinition0;
1446 const char* scDefinition1;
1447 const char* scResultType;
1448 const char* scOperation;
1449 deInt32 scActualValue0;
1450 deInt32 scActualValue1;
1451 const char* resultOperation;
1452 vector<deInt32> expectedOutput;
1454 SpecConstantTwoIntCase (const char* name,
1455 const char* definition0,
1456 const char* definition1,
1457 const char* resultType,
1458 const char* operation,
1461 const char* resultOp,
1462 const vector<deInt32>& output)
1464 , scDefinition0 (definition0)
1465 , scDefinition1 (definition1)
1466 , scResultType (resultType)
1467 , scOperation (operation)
1468 , scActualValue0 (value0)
1469 , scActualValue1 (value1)
1470 , resultOperation (resultOp)
1471 , expectedOutput (output) {}
1474 tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx)
1476 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction"));
1477 vector<SpecConstantTwoIntCase> cases;
1478 de::Random rnd (deStringHash(group->getName()));
1479 const int numElements = 100;
1480 vector<deInt32> inputInts (numElements, 0);
1481 vector<deInt32> outputInts1 (numElements, 0);
1482 vector<deInt32> outputInts2 (numElements, 0);
1483 vector<deInt32> outputInts3 (numElements, 0);
1484 vector<deInt32> outputInts4 (numElements, 0);
1485 const StringTemplate shaderTemplate (
1486 string(getComputeAsmShaderPreamble()) +
1488 "OpName %main \"main\"\n"
1489 "OpName %id \"gl_GlobalInvocationID\"\n"
1491 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1492 "OpDecorate %sc_0 SpecId 0\n"
1493 "OpDecorate %sc_1 SpecId 1\n"
1494 "OpDecorate %i32arr ArrayStride 4\n"
1496 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
1498 "%buf = OpTypeStruct %i32arr\n"
1499 "%bufptr = OpTypePointer Uniform %buf\n"
1500 "%indata = OpVariable %bufptr Uniform\n"
1501 "%outdata = OpVariable %bufptr Uniform\n"
1503 "%id = OpVariable %uvec3ptr Input\n"
1504 "%zero = OpConstant %i32 0\n"
1506 "%sc_0 = OpSpecConstant${SC_DEF0}\n"
1507 "%sc_1 = OpSpecConstant${SC_DEF1}\n"
1508 "%sc_final = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n"
1510 "%main = OpFunction %void None %voidf\n"
1511 "%label = OpLabel\n"
1512 "%idval = OpLoad %uvec3 %id\n"
1513 "%x = OpCompositeExtract %u32 %idval 0\n"
1514 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
1515 "%inval = OpLoad %i32 %inloc\n"
1516 "%final = ${GEN_RESULT}\n"
1517 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n"
1518 " OpStore %outloc %final\n"
1520 " OpFunctionEnd\n");
1522 fillRandomScalars(rnd, -65536, 65536, &inputInts[0], numElements);
1524 for (size_t ndx = 0; ndx < numElements; ++ndx)
1526 outputInts1[ndx] = inputInts[ndx] + 42;
1527 outputInts2[ndx] = inputInts[ndx];
1528 outputInts3[ndx] = inputInts[ndx] - 11200;
1529 outputInts4[ndx] = inputInts[ndx] + 1;
1532 const char addScToInput[] = "OpIAdd %i32 %inval %sc_final";
1533 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_final %inval %zero";
1534 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_final %zero %inval";
1536 cases.push_back(SpecConstantTwoIntCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 62, -20, addScToInput, outputInts1));
1537 cases.push_back(SpecConstantTwoIntCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 100, 58, addScToInput, outputInts1));
1538 cases.push_back(SpecConstantTwoIntCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -2, -21, addScToInput, outputInts1));
1539 cases.push_back(SpecConstantTwoIntCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, -3, addScToInput, outputInts1));
1540 cases.push_back(SpecConstantTwoIntCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 3, addScToInput, outputInts1));
1541 cases.push_back(SpecConstantTwoIntCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 7, 3, addScToInput, outputInts4));
1542 cases.push_back(SpecConstantTwoIntCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 7, 3, addScToInput, outputInts4));
1543 cases.push_back(SpecConstantTwoIntCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 342, 50, addScToInput, outputInts1));
1544 cases.push_back(SpecConstantTwoIntCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 42, 63, addScToInput, outputInts1));
1545 cases.push_back(SpecConstantTwoIntCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 34, 8, addScToInput, outputInts1));
1546 cases.push_back(SpecConstantTwoIntCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseXor %sc_0 %sc_1", 18, 56, addScToInput, outputInts1));
1547 cases.push_back(SpecConstantTwoIntCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 168, 2, addScToInput, outputInts1));
1548 cases.push_back(SpecConstantTwoIntCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", 168, 2, addScToInput, outputInts1));
1549 cases.push_back(SpecConstantTwoIntCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 21, 1, addScToInput, outputInts1));
1550 cases.push_back(SpecConstantTwoIntCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputInts2));
1551 cases.push_back(SpecConstantTwoIntCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputInts2));
1552 cases.push_back(SpecConstantTwoIntCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2));
1553 cases.push_back(SpecConstantTwoIntCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputInts2));
1554 cases.push_back(SpecConstantTwoIntCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputInts2));
1555 cases.push_back(SpecConstantTwoIntCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputInts2));
1556 cases.push_back(SpecConstantTwoIntCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2));
1557 cases.push_back(SpecConstantTwoIntCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputInts2));
1558 cases.push_back(SpecConstantTwoIntCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputInts2));
1559 cases.push_back(SpecConstantTwoIntCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2));
1560 cases.push_back(SpecConstantTwoIntCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2));
1561 cases.push_back(SpecConstantTwoIntCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2));
1562 cases.push_back(SpecConstantTwoIntCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2));
1563 cases.push_back(SpecConstantTwoIntCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -42, 0, addScToInput, outputInts1));
1564 cases.push_back(SpecConstantTwoIntCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -43, 0, addScToInput, outputInts1));
1565 cases.push_back(SpecConstantTwoIntCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputInts2));
1566 cases.push_back(SpecConstantTwoIntCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %zero", 1, 42, addScToInput, outputInts1));
1567 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths.
1569 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
1571 map<string, string> specializations;
1572 ComputeShaderSpec spec;
1574 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0;
1575 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1;
1576 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType;
1577 specializations["SC_OP"] = cases[caseNdx].scOperation;
1578 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation;
1580 spec.assembly = shaderTemplate.specialize(specializations);
1581 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
1582 spec.outputs.push_back(BufferSp(new Int32Buffer(cases[caseNdx].expectedOutput)));
1583 spec.numWorkGroups = IVec3(numElements, 1, 1);
1584 spec.specConstants.push_back(cases[caseNdx].scActualValue0);
1585 spec.specConstants.push_back(cases[caseNdx].scActualValue1);
1587 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].caseName, cases[caseNdx].caseName, spec));
1590 ComputeShaderSpec spec;
1593 string(getComputeAsmShaderPreamble()) +
1595 "OpName %main \"main\"\n"
1596 "OpName %id \"gl_GlobalInvocationID\"\n"
1598 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1599 "OpDecorate %sc_0 SpecId 0\n"
1600 "OpDecorate %sc_1 SpecId 1\n"
1601 "OpDecorate %sc_2 SpecId 2\n"
1602 "OpDecorate %i32arr ArrayStride 4\n"
1604 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
1606 "%ivec3 = OpTypeVector %i32 3\n"
1607 "%buf = OpTypeStruct %i32arr\n"
1608 "%bufptr = OpTypePointer Uniform %buf\n"
1609 "%indata = OpVariable %bufptr Uniform\n"
1610 "%outdata = OpVariable %bufptr Uniform\n"
1612 "%id = OpVariable %uvec3ptr Input\n"
1613 "%zero = OpConstant %i32 0\n"
1614 "%ivec3_0 = OpConstantComposite %ivec3 %zero %zero %zero\n"
1616 "%sc_0 = OpSpecConstant %i32 0\n"
1617 "%sc_1 = OpSpecConstant %i32 0\n"
1618 "%sc_2 = OpSpecConstant %i32 0\n"
1619 "%sc_vec3_0 = OpSpecConstantOp %ivec3 CompositeInsert %sc_0 %ivec3_0 0\n" // (sc_0, 0, 0)
1620 "%sc_vec3_1 = OpSpecConstantOp %ivec3 CompositeInsert %sc_1 %ivec3_0 1\n" // (0, sc_1, 0)
1621 "%sc_vec3_2 = OpSpecConstantOp %ivec3 CompositeInsert %sc_2 %ivec3_0 2\n" // (0, 0, sc_2)
1622 "%sc_vec3_01 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1)
1623 "%sc_vec3_012 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1)
1624 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2
1625 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0
1626 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1
1627 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0)
1628 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n" // (sc_2 - sc_0) * sc_1
1630 "%main = OpFunction %void None %voidf\n"
1631 "%label = OpLabel\n"
1632 "%idval = OpLoad %uvec3 %id\n"
1633 "%x = OpCompositeExtract %u32 %idval 0\n"
1634 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n"
1635 "%inval = OpLoad %i32 %inloc\n"
1636 "%final = OpIAdd %i32 %inval %sc_final\n"
1637 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n"
1638 " OpStore %outloc %final\n"
1641 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts)));
1642 spec.outputs.push_back(BufferSp(new Int32Buffer(outputInts3)));
1643 spec.numWorkGroups = IVec3(numElements, 1, 1);
1644 spec.specConstants.push_back(123);
1645 spec.specConstants.push_back(56);
1646 spec.specConstants.push_back(-77);
1648 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector_related", "VectorShuffle, CompositeExtract, & CompositeInsert", spec));
1650 return group.release();
1653 tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx)
1655 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
1656 ComputeShaderSpec spec1;
1657 ComputeShaderSpec spec2;
1658 ComputeShaderSpec spec3;
1659 de::Random rnd (deStringHash(group->getName()));
1660 const int numElements = 100;
1661 vector<float> inputFloats (numElements, 0);
1662 vector<float> outputFloats1 (numElements, 0);
1663 vector<float> outputFloats2 (numElements, 0);
1664 vector<float> outputFloats3 (numElements, 0);
1666 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements);
1668 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
1669 floorAll(inputFloats);
1671 for (size_t ndx = 0; ndx < numElements; ++ndx)
1675 case 0: outputFloats1[ndx] = inputFloats[ndx] + 5.5f; break;
1676 case 1: outputFloats1[ndx] = inputFloats[ndx] + 20.5f; break;
1677 case 2: outputFloats1[ndx] = inputFloats[ndx] + 1.75f; break;
1680 outputFloats2[ndx] = inputFloats[ndx] + 6.5f * 3;
1681 outputFloats3[ndx] = 8.5f - inputFloats[ndx];
1685 string(getComputeAsmShaderPreamble()) +
1687 "OpSource GLSL 430\n"
1688 "OpName %main \"main\"\n"
1689 "OpName %id \"gl_GlobalInvocationID\"\n"
1691 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1693 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
1695 "%id = OpVariable %uvec3ptr Input\n"
1696 "%zero = OpConstant %i32 0\n"
1697 "%three = OpConstant %u32 3\n"
1698 "%constf5p5 = OpConstant %f32 5.5\n"
1699 "%constf20p5 = OpConstant %f32 20.5\n"
1700 "%constf1p75 = OpConstant %f32 1.75\n"
1701 "%constf8p5 = OpConstant %f32 8.5\n"
1702 "%constf6p5 = OpConstant %f32 6.5\n"
1704 "%main = OpFunction %void None %voidf\n"
1705 "%entry = OpLabel\n"
1706 "%idval = OpLoad %uvec3 %id\n"
1707 "%x = OpCompositeExtract %u32 %idval 0\n"
1708 "%selector = OpUMod %u32 %x %three\n"
1709 " OpSelectionMerge %phi None\n"
1710 " OpSwitch %selector %default 0 %case0 1 %case1 2 %case2\n"
1712 // Case 1 before OpPhi.
1713 "%case1 = OpLabel\n"
1716 "%default = OpLabel\n"
1720 "%operand = OpPhi %f32 %constf1p75 %case2 %constf20p5 %case1 %constf5p5 %case0\n" // not in the order of blocks
1721 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1722 "%inval = OpLoad %f32 %inloc\n"
1723 "%add = OpFAdd %f32 %inval %operand\n"
1724 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1725 " OpStore %outloc %add\n"
1728 // Case 0 after OpPhi.
1729 "%case0 = OpLabel\n"
1733 // Case 2 after OpPhi.
1734 "%case2 = OpLabel\n"
1738 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1739 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1)));
1740 spec1.numWorkGroups = IVec3(numElements, 1, 1);
1742 group->addChild(new SpvAsmComputeShaderCase(testCtx, "block", "out-of-order and unreachable blocks for OpPhi", spec1));
1745 string(getComputeAsmShaderPreamble()) +
1747 "OpName %main \"main\"\n"
1748 "OpName %id \"gl_GlobalInvocationID\"\n"
1750 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1752 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
1754 "%id = OpVariable %uvec3ptr Input\n"
1755 "%zero = OpConstant %i32 0\n"
1756 "%one = OpConstant %i32 1\n"
1757 "%three = OpConstant %i32 3\n"
1758 "%constf6p5 = OpConstant %f32 6.5\n"
1760 "%main = OpFunction %void None %voidf\n"
1761 "%entry = OpLabel\n"
1762 "%idval = OpLoad %uvec3 %id\n"
1763 "%x = OpCompositeExtract %u32 %idval 0\n"
1764 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1765 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1766 "%inval = OpLoad %f32 %inloc\n"
1770 "%step = OpPhi %i32 %zero %entry %step_next %phi\n"
1771 "%accum = OpPhi %f32 %inval %entry %accum_next %phi\n"
1772 "%step_next = OpIAdd %i32 %step %one\n"
1773 "%accum_next = OpFAdd %f32 %accum %constf6p5\n"
1774 "%still_loop = OpSLessThan %bool %step %three\n"
1775 " OpLoopMerge %exit %phi None\n"
1776 " OpBranchConditional %still_loop %phi %exit\n"
1779 " OpStore %outloc %accum\n"
1782 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1783 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
1784 spec2.numWorkGroups = IVec3(numElements, 1, 1);
1786 group->addChild(new SpvAsmComputeShaderCase(testCtx, "induction", "The usual way induction variables are handled in LLVM IR", spec2));
1789 string(getComputeAsmShaderPreamble()) +
1791 "OpName %main \"main\"\n"
1792 "OpName %id \"gl_GlobalInvocationID\"\n"
1794 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1796 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
1798 "%f32ptr_f = OpTypePointer Function %f32\n"
1799 "%id = OpVariable %uvec3ptr Input\n"
1800 "%true = OpConstantTrue %bool\n"
1801 "%false = OpConstantFalse %bool\n"
1802 "%zero = OpConstant %i32 0\n"
1803 "%constf8p5 = OpConstant %f32 8.5\n"
1805 "%main = OpFunction %void None %voidf\n"
1806 "%entry = OpLabel\n"
1807 "%b = OpVariable %f32ptr_f Function %constf8p5\n"
1808 "%idval = OpLoad %uvec3 %id\n"
1809 "%x = OpCompositeExtract %u32 %idval 0\n"
1810 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
1811 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
1812 "%a_init = OpLoad %f32 %inloc\n"
1813 "%b_init = OpLoad %f32 %b\n"
1817 "%still_loop = OpPhi %bool %true %entry %false %phi\n"
1818 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n"
1819 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n"
1820 " OpLoopMerge %exit %phi None\n"
1821 " OpBranchConditional %still_loop %phi %exit\n"
1824 "%sub = OpFSub %f32 %a_next %b_next\n"
1825 " OpStore %outloc %sub\n"
1828 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1829 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3)));
1830 spec3.numWorkGroups = IVec3(numElements, 1, 1);
1832 group->addChild(new SpvAsmComputeShaderCase(testCtx, "swap", "Swap the values of two variables using OpPhi", spec3));
1834 return group.release();
1837 // Assembly code used for testing block order is based on GLSL source code:
1841 // layout(std140, set = 0, binding = 0) readonly buffer Input {
1842 // float elements[];
1844 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
1845 // float elements[];
1849 // uint x = gl_GlobalInvocationID.x;
1850 // output_data.elements[x] = input_data.elements[x];
1851 // if (x > uint(50)) {
1852 // switch (x % uint(3)) {
1853 // case 0: output_data.elements[x] += 1.5f; break;
1854 // case 1: output_data.elements[x] += 42.f; break;
1855 // case 2: output_data.elements[x] -= 27.f; break;
1859 // output_data.elements[x] = -input_data.elements[x];
1862 tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx)
1864 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "block_order", "Test block orders"));
1865 ComputeShaderSpec spec;
1866 de::Random rnd (deStringHash(group->getName()));
1867 const int numElements = 100;
1868 vector<float> inputFloats (numElements, 0);
1869 vector<float> outputFloats (numElements, 0);
1871 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
1873 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
1874 floorAll(inputFloats);
1876 for (size_t ndx = 0; ndx <= 50; ++ndx)
1877 outputFloats[ndx] = -inputFloats[ndx];
1879 for (size_t ndx = 51; ndx < numElements; ++ndx)
1883 case 0: outputFloats[ndx] = inputFloats[ndx] + 1.5f; break;
1884 case 1: outputFloats[ndx] = inputFloats[ndx] + 42.f; break;
1885 case 2: outputFloats[ndx] = inputFloats[ndx] - 27.f; break;
1891 string(getComputeAsmShaderPreamble()) +
1893 "OpSource GLSL 430\n"
1894 "OpName %main \"main\"\n"
1895 "OpName %id \"gl_GlobalInvocationID\"\n"
1897 "OpDecorate %id BuiltIn GlobalInvocationId\n"
1899 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
1901 "%u32ptr = OpTypePointer Function %u32\n"
1902 "%u32ptr_input = OpTypePointer Input %u32\n"
1904 + string(getComputeAsmInputOutputBuffer()) +
1906 "%id = OpVariable %uvec3ptr Input\n"
1907 "%zero = OpConstant %i32 0\n"
1908 "%const3 = OpConstant %u32 3\n"
1909 "%const50 = OpConstant %u32 50\n"
1910 "%constf1p5 = OpConstant %f32 1.5\n"
1911 "%constf27 = OpConstant %f32 27.0\n"
1912 "%constf42 = OpConstant %f32 42.0\n"
1914 "%main = OpFunction %void None %voidf\n"
1917 "%entry = OpLabel\n"
1919 // Create a temporary variable to hold the value of gl_GlobalInvocationID.x.
1920 "%xvar = OpVariable %u32ptr Function\n"
1921 "%xptr = OpAccessChain %u32ptr_input %id %zero\n"
1922 "%x = OpLoad %u32 %xptr\n"
1923 " OpStore %xvar %x\n"
1925 "%cmp = OpUGreaterThan %bool %x %const50\n"
1926 " OpSelectionMerge %if_merge None\n"
1927 " OpBranchConditional %cmp %if_true %if_false\n"
1929 // False branch for if-statement: placed in the middle of switch cases and before true branch.
1930 "%if_false = OpLabel\n"
1931 "%x_f = OpLoad %u32 %xvar\n"
1932 "%inloc_f = OpAccessChain %f32ptr %indata %zero %x_f\n"
1933 "%inval_f = OpLoad %f32 %inloc_f\n"
1934 "%negate = OpFNegate %f32 %inval_f\n"
1935 "%outloc_f = OpAccessChain %f32ptr %outdata %zero %x_f\n"
1936 " OpStore %outloc_f %negate\n"
1937 " OpBranch %if_merge\n"
1939 // Merge block for if-statement: placed in the middle of true and false branch.
1940 "%if_merge = OpLabel\n"
1943 // True branch for if-statement: placed in the middle of swtich cases and after the false branch.
1944 "%if_true = OpLabel\n"
1945 "%xval_t = OpLoad %u32 %xvar\n"
1946 "%mod = OpUMod %u32 %xval_t %const3\n"
1947 " OpSelectionMerge %switch_merge None\n"
1948 " OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n"
1950 // Merge block for switch-statement: placed before the case
1951 // bodies. But it must follow OpSwitch which dominates it.
1952 "%switch_merge = OpLabel\n"
1953 " OpBranch %if_merge\n"
1955 // Case 1 for switch-statement: placed before case 0.
1956 // It must follow the OpSwitch that dominates it.
1957 "%case1 = OpLabel\n"
1958 "%x_1 = OpLoad %u32 %xvar\n"
1959 "%inloc_1 = OpAccessChain %f32ptr %indata %zero %x_1\n"
1960 "%inval_1 = OpLoad %f32 %inloc_1\n"
1961 "%addf42 = OpFAdd %f32 %inval_1 %constf42\n"
1962 "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n"
1963 " OpStore %outloc_1 %addf42\n"
1964 " OpBranch %switch_merge\n"
1966 // Case 2 for switch-statement.
1967 "%case2 = OpLabel\n"
1968 "%x_2 = OpLoad %u32 %xvar\n"
1969 "%inloc_2 = OpAccessChain %f32ptr %indata %zero %x_2\n"
1970 "%inval_2 = OpLoad %f32 %inloc_2\n"
1971 "%subf27 = OpFSub %f32 %inval_2 %constf27\n"
1972 "%outloc_2 = OpAccessChain %f32ptr %outdata %zero %x_2\n"
1973 " OpStore %outloc_2 %subf27\n"
1974 " OpBranch %switch_merge\n"
1976 // Default case for switch-statement: placed in the middle of normal cases.
1977 "%default = OpLabel\n"
1978 " OpBranch %switch_merge\n"
1980 // Case 0 for switch-statement: out of order.
1981 "%case0 = OpLabel\n"
1982 "%x_0 = OpLoad %u32 %xvar\n"
1983 "%inloc_0 = OpAccessChain %f32ptr %indata %zero %x_0\n"
1984 "%inval_0 = OpLoad %f32 %inloc_0\n"
1985 "%addf1p5 = OpFAdd %f32 %inval_0 %constf1p5\n"
1986 "%outloc_0 = OpAccessChain %f32ptr %outdata %zero %x_0\n"
1987 " OpStore %outloc_0 %addf1p5\n"
1988 " OpBranch %switch_merge\n"
1991 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
1992 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
1993 spec.numWorkGroups = IVec3(numElements, 1, 1);
1995 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec));
1997 return group.release();
2000 tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx)
2002 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "multiple_shaders", "Test multiple shaders in the same module"));
2003 ComputeShaderSpec spec1;
2004 ComputeShaderSpec spec2;
2005 de::Random rnd (deStringHash(group->getName()));
2006 const int numElements = 100;
2007 vector<float> inputFloats (numElements, 0);
2008 vector<float> outputFloats1 (numElements, 0);
2009 vector<float> outputFloats2 (numElements, 0);
2010 fillRandomScalars(rnd, -500.f, 500.f, &inputFloats[0], numElements);
2012 for (size_t ndx = 0; ndx < numElements; ++ndx)
2014 outputFloats1[ndx] = inputFloats[ndx] + inputFloats[ndx];
2015 outputFloats2[ndx] = -inputFloats[ndx];
2018 const string assembly(
2019 "OpCapability Shader\n"
2020 "OpCapability ClipDistance\n"
2021 "OpMemoryModel Logical GLSL450\n"
2022 "OpEntryPoint GLCompute %comp_main1 \"entrypoint1\" %id\n"
2023 "OpEntryPoint GLCompute %comp_main2 \"entrypoint2\" %id\n"
2024 // A module cannot have two OpEntryPoint instructions with the same Execution Model and the same Name string.
2025 "OpEntryPoint Vertex %vert_main \"entrypoint2\" %vert_builtins %vertexIndex %instanceIndex\n"
2026 "OpExecutionMode %comp_main1 LocalSize 1 1 1\n"
2027 "OpExecutionMode %comp_main2 LocalSize 1 1 1\n"
2029 "OpName %comp_main1 \"entrypoint1\"\n"
2030 "OpName %comp_main2 \"entrypoint2\"\n"
2031 "OpName %vert_main \"entrypoint2\"\n"
2032 "OpName %id \"gl_GlobalInvocationID\"\n"
2033 "OpName %vert_builtin_st \"gl_PerVertex\"\n"
2034 "OpName %vertexIndex \"gl_VertexIndex\"\n"
2035 "OpName %instanceIndex \"gl_InstanceIndex\"\n"
2036 "OpMemberName %vert_builtin_st 0 \"gl_Position\"\n"
2037 "OpMemberName %vert_builtin_st 1 \"gl_PointSize\"\n"
2038 "OpMemberName %vert_builtin_st 2 \"gl_ClipDistance\"\n"
2040 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2041 "OpDecorate %vertexIndex BuiltIn VertexIndex\n"
2042 "OpDecorate %instanceIndex BuiltIn InstanceIndex\n"
2043 "OpDecorate %vert_builtin_st Block\n"
2044 "OpMemberDecorate %vert_builtin_st 0 BuiltIn Position\n"
2045 "OpMemberDecorate %vert_builtin_st 1 BuiltIn PointSize\n"
2046 "OpMemberDecorate %vert_builtin_st 2 BuiltIn ClipDistance\n"
2048 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2050 "%zero = OpConstant %i32 0\n"
2051 "%one = OpConstant %u32 1\n"
2052 "%c_f32_1 = OpConstant %f32 1\n"
2054 "%i32inputptr = OpTypePointer Input %i32\n"
2055 "%vec4 = OpTypeVector %f32 4\n"
2056 "%vec4ptr = OpTypePointer Output %vec4\n"
2057 "%f32arr1 = OpTypeArray %f32 %one\n"
2058 "%vert_builtin_st = OpTypeStruct %vec4 %f32 %f32arr1\n"
2059 "%vert_builtin_st_ptr = OpTypePointer Output %vert_builtin_st\n"
2060 "%vert_builtins = OpVariable %vert_builtin_st_ptr Output\n"
2062 "%id = OpVariable %uvec3ptr Input\n"
2063 "%vertexIndex = OpVariable %i32inputptr Input\n"
2064 "%instanceIndex = OpVariable %i32inputptr Input\n"
2065 "%c_vec4_1 = OpConstantComposite %vec4 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
2067 // gl_Position = vec4(1.);
2068 "%vert_main = OpFunction %void None %voidf\n"
2069 "%vert_entry = OpLabel\n"
2070 "%position = OpAccessChain %vec4ptr %vert_builtins %zero\n"
2071 " OpStore %position %c_vec4_1\n"
2076 "%comp_main1 = OpFunction %void None %voidf\n"
2077 "%comp1_entry = OpLabel\n"
2078 "%idval1 = OpLoad %uvec3 %id\n"
2079 "%x1 = OpCompositeExtract %u32 %idval1 0\n"
2080 "%inloc1 = OpAccessChain %f32ptr %indata %zero %x1\n"
2081 "%inval1 = OpLoad %f32 %inloc1\n"
2082 "%add = OpFAdd %f32 %inval1 %inval1\n"
2083 "%outloc1 = OpAccessChain %f32ptr %outdata %zero %x1\n"
2084 " OpStore %outloc1 %add\n"
2089 "%comp_main2 = OpFunction %void None %voidf\n"
2090 "%comp2_entry = OpLabel\n"
2091 "%idval2 = OpLoad %uvec3 %id\n"
2092 "%x2 = OpCompositeExtract %u32 %idval2 0\n"
2093 "%inloc2 = OpAccessChain %f32ptr %indata %zero %x2\n"
2094 "%inval2 = OpLoad %f32 %inloc2\n"
2095 "%neg = OpFNegate %f32 %inval2\n"
2096 "%outloc2 = OpAccessChain %f32ptr %outdata %zero %x2\n"
2097 " OpStore %outloc2 %neg\n"
2099 " OpFunctionEnd\n");
2101 spec1.assembly = assembly;
2102 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2103 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1)));
2104 spec1.numWorkGroups = IVec3(numElements, 1, 1);
2105 spec1.entryPoint = "entrypoint1";
2107 spec2.assembly = assembly;
2108 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2109 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2)));
2110 spec2.numWorkGroups = IVec3(numElements, 1, 1);
2111 spec2.entryPoint = "entrypoint2";
2113 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader1", "multiple shaders in the same module", spec1));
2114 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader2", "multiple shaders in the same module", spec2));
2116 return group.release();
2119 inline std::string makeLongUTF8String (size_t num4ByteChars)
2121 // An example of a longest valid UTF-8 character. Be explicit about the
2122 // character type because Microsoft compilers can otherwise interpret the
2123 // character string as being over wide (16-bit) characters. Ideally, we
2124 // would just use a C++11 UTF-8 string literal, but we want to support older
2125 // Microsoft compilers.
2126 const std::basic_string<char> earthAfrica("\xF0\x9F\x8C\x8D");
2127 std::string longString;
2128 longString.reserve(num4ByteChars * 4);
2129 for (size_t count = 0; count < num4ByteChars; count++)
2131 longString += earthAfrica;
2136 tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx)
2138 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction"));
2139 vector<CaseParameter> cases;
2140 de::Random rnd (deStringHash(group->getName()));
2141 const int numElements = 100;
2142 vector<float> positiveFloats (numElements, 0);
2143 vector<float> negativeFloats (numElements, 0);
2144 const StringTemplate shaderTemplate (
2145 "OpCapability Shader\n"
2146 "OpMemoryModel Logical GLSL450\n"
2148 "OpEntryPoint GLCompute %main \"main\" %id\n"
2149 "OpExecutionMode %main LocalSize 1 1 1\n"
2153 "OpName %main \"main\"\n"
2154 "OpName %id \"gl_GlobalInvocationID\"\n"
2156 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2158 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2160 "%id = OpVariable %uvec3ptr Input\n"
2161 "%zero = OpConstant %i32 0\n"
2163 "%main = OpFunction %void None %voidf\n"
2164 "%label = OpLabel\n"
2165 "%idval = OpLoad %uvec3 %id\n"
2166 "%x = OpCompositeExtract %u32 %idval 0\n"
2167 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2168 "%inval = OpLoad %f32 %inloc\n"
2169 "%neg = OpFNegate %f32 %inval\n"
2170 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2171 " OpStore %outloc %neg\n"
2173 " OpFunctionEnd\n");
2175 cases.push_back(CaseParameter("unknown_source", "OpSource Unknown 0"));
2176 cases.push_back(CaseParameter("wrong_source", "OpSource OpenCL_C 210"));
2177 cases.push_back(CaseParameter("normal_filename", "%fname = OpString \"filename\"\n"
2178 "OpSource GLSL 430 %fname"));
2179 cases.push_back(CaseParameter("empty_filename", "%fname = OpString \"\"\n"
2180 "OpSource GLSL 430 %fname"));
2181 cases.push_back(CaseParameter("normal_source_code", "%fname = OpString \"filename\"\n"
2182 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\""));
2183 cases.push_back(CaseParameter("empty_source_code", "%fname = OpString \"filename\"\n"
2184 "OpSource GLSL 430 %fname \"\""));
2185 cases.push_back(CaseParameter("long_source_code", "%fname = OpString \"filename\"\n"
2186 "OpSource GLSL 430 %fname \"" + makeLongUTF8String(65530) + "ccc\"")); // word count: 65535
2187 cases.push_back(CaseParameter("utf8_source_code", "%fname = OpString \"filename\"\n"
2188 "OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol
2189 cases.push_back(CaseParameter("normal_sourcecontinued", "%fname = OpString \"filename\"\n"
2190 "OpSource GLSL 430 %fname \"#version 430\nvo\"\n"
2191 "OpSourceContinued \"id main() {}\""));
2192 cases.push_back(CaseParameter("empty_sourcecontinued", "%fname = OpString \"filename\"\n"
2193 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
2194 "OpSourceContinued \"\""));
2195 cases.push_back(CaseParameter("long_sourcecontinued", "%fname = OpString \"filename\"\n"
2196 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
2197 "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\"")); // word count: 65535
2198 cases.push_back(CaseParameter("utf8_sourcecontinued", "%fname = OpString \"filename\"\n"
2199 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n"
2200 "OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol
2201 cases.push_back(CaseParameter("multi_sourcecontinued", "%fname = OpString \"filename\"\n"
2202 "OpSource GLSL 430 %fname \"#version 430\n\"\n"
2203 "OpSourceContinued \"void\"\n"
2204 "OpSourceContinued \"main()\"\n"
2205 "OpSourceContinued \"{}\""));
2206 cases.push_back(CaseParameter("empty_source_before_sourcecontinued", "%fname = OpString \"filename\"\n"
2207 "OpSource GLSL 430 %fname \"\"\n"
2208 "OpSourceContinued \"#version 430\nvoid main() {}\""));
2210 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2212 for (size_t ndx = 0; ndx < numElements; ++ndx)
2213 negativeFloats[ndx] = -positiveFloats[ndx];
2215 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2217 map<string, string> specializations;
2218 ComputeShaderSpec spec;
2220 specializations["SOURCE"] = cases[caseNdx].param;
2221 spec.assembly = shaderTemplate.specialize(specializations);
2222 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
2223 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
2224 spec.numWorkGroups = IVec3(numElements, 1, 1);
2226 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2229 return group.release();
2232 tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx)
2234 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsourceextension", "Tests the OpSource instruction"));
2235 vector<CaseParameter> cases;
2236 de::Random rnd (deStringHash(group->getName()));
2237 const int numElements = 100;
2238 vector<float> inputFloats (numElements, 0);
2239 vector<float> outputFloats (numElements, 0);
2240 const StringTemplate shaderTemplate (
2241 string(getComputeAsmShaderPreamble()) +
2243 "OpSourceExtension \"${EXTENSION}\"\n"
2245 "OpName %main \"main\"\n"
2246 "OpName %id \"gl_GlobalInvocationID\"\n"
2248 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2250 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2252 "%id = OpVariable %uvec3ptr Input\n"
2253 "%zero = OpConstant %i32 0\n"
2255 "%main = OpFunction %void None %voidf\n"
2256 "%label = OpLabel\n"
2257 "%idval = OpLoad %uvec3 %id\n"
2258 "%x = OpCompositeExtract %u32 %idval 0\n"
2259 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2260 "%inval = OpLoad %f32 %inloc\n"
2261 "%neg = OpFNegate %f32 %inval\n"
2262 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2263 " OpStore %outloc %neg\n"
2265 " OpFunctionEnd\n");
2267 cases.push_back(CaseParameter("empty_extension", ""));
2268 cases.push_back(CaseParameter("real_extension", "GL_ARB_texture_rectangle"));
2269 cases.push_back(CaseParameter("fake_extension", "GL_ARB_im_the_ultimate_extension"));
2270 cases.push_back(CaseParameter("utf8_extension", "GL_ARB_\xE2\x98\x82\xE2\x98\x85"));
2271 cases.push_back(CaseParameter("long_extension", makeLongUTF8String(65533) + "ccc")); // word count: 65535
2273 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements);
2275 for (size_t ndx = 0; ndx < numElements; ++ndx)
2276 outputFloats[ndx] = -inputFloats[ndx];
2278 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2280 map<string, string> specializations;
2281 ComputeShaderSpec spec;
2283 specializations["EXTENSION"] = cases[caseNdx].param;
2284 spec.assembly = shaderTemplate.specialize(specializations);
2285 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
2286 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
2287 spec.numWorkGroups = IVec3(numElements, 1, 1);
2289 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2292 return group.release();
2295 // Checks that a compute shader can generate a constant null value of various types, without exercising a computation on it.
2296 tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx)
2298 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnull", "Tests the OpConstantNull instruction"));
2299 vector<CaseParameter> cases;
2300 de::Random rnd (deStringHash(group->getName()));
2301 const int numElements = 100;
2302 vector<float> positiveFloats (numElements, 0);
2303 vector<float> negativeFloats (numElements, 0);
2304 const StringTemplate shaderTemplate (
2305 string(getComputeAsmShaderPreamble()) +
2307 "OpSource GLSL 430\n"
2308 "OpName %main \"main\"\n"
2309 "OpName %id \"gl_GlobalInvocationID\"\n"
2311 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2313 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2316 "%null = OpConstantNull ${TYPE}\n"
2318 "%id = OpVariable %uvec3ptr Input\n"
2319 "%zero = OpConstant %i32 0\n"
2321 "%main = OpFunction %void None %voidf\n"
2322 "%label = OpLabel\n"
2323 "%idval = OpLoad %uvec3 %id\n"
2324 "%x = OpCompositeExtract %u32 %idval 0\n"
2325 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2326 "%inval = OpLoad %f32 %inloc\n"
2327 "%neg = OpFNegate %f32 %inval\n"
2328 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2329 " OpStore %outloc %neg\n"
2331 " OpFunctionEnd\n");
2333 cases.push_back(CaseParameter("bool", "%bool"));
2334 cases.push_back(CaseParameter("sint32", "%i32"));
2335 cases.push_back(CaseParameter("uint32", "%u32"));
2336 cases.push_back(CaseParameter("float32", "%f32"));
2337 cases.push_back(CaseParameter("vec4float32", "%fvec4"));
2338 cases.push_back(CaseParameter("vec3bool", "%bvec3"));
2339 cases.push_back(CaseParameter("vec2uint32", "%uvec2"));
2340 cases.push_back(CaseParameter("matrix", "%fmat33"));
2341 cases.push_back(CaseParameter("array", "%uarr100"));
2342 cases.push_back(CaseParameter("struct", "%struct"));
2343 cases.push_back(CaseParameter("pointer", "%pointer"));
2345 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2347 for (size_t ndx = 0; ndx < numElements; ++ndx)
2348 negativeFloats[ndx] = -positiveFloats[ndx];
2350 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2352 map<string, string> specializations;
2353 ComputeShaderSpec spec;
2355 specializations["TYPE"] = cases[caseNdx].param;
2356 spec.assembly = shaderTemplate.specialize(specializations);
2357 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
2358 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
2359 spec.numWorkGroups = IVec3(numElements, 1, 1);
2361 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2364 return group.release();
2367 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
2368 tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx)
2370 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "Tests the OpConstantComposite instruction"));
2371 vector<CaseParameter> cases;
2372 de::Random rnd (deStringHash(group->getName()));
2373 const int numElements = 100;
2374 vector<float> positiveFloats (numElements, 0);
2375 vector<float> negativeFloats (numElements, 0);
2376 const StringTemplate shaderTemplate (
2377 string(getComputeAsmShaderPreamble()) +
2379 "OpSource GLSL 430\n"
2380 "OpName %main \"main\"\n"
2381 "OpName %id \"gl_GlobalInvocationID\"\n"
2383 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2385 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2387 "%id = OpVariable %uvec3ptr Input\n"
2388 "%zero = OpConstant %i32 0\n"
2392 "%main = OpFunction %void None %voidf\n"
2393 "%label = OpLabel\n"
2394 "%idval = OpLoad %uvec3 %id\n"
2395 "%x = OpCompositeExtract %u32 %idval 0\n"
2396 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2397 "%inval = OpLoad %f32 %inloc\n"
2398 "%neg = OpFNegate %f32 %inval\n"
2399 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2400 " OpStore %outloc %neg\n"
2402 " OpFunctionEnd\n");
2404 cases.push_back(CaseParameter("vector", "%five = OpConstant %u32 5\n"
2405 "%const = OpConstantComposite %uvec3 %five %zero %five"));
2406 cases.push_back(CaseParameter("matrix", "%m3fvec3 = OpTypeMatrix %fvec3 3\n"
2407 "%ten = OpConstant %f32 10.\n"
2408 "%fzero = OpConstant %f32 0.\n"
2409 "%vec = OpConstantComposite %fvec3 %ten %fzero %ten\n"
2410 "%mat = OpConstantComposite %m3fvec3 %vec %vec %vec"));
2411 cases.push_back(CaseParameter("struct", "%m2vec3 = OpTypeMatrix %fvec3 2\n"
2412 "%struct = OpTypeStruct %i32 %f32 %fvec3 %m2vec3\n"
2413 "%fzero = OpConstant %f32 0.\n"
2414 "%one = OpConstant %f32 1.\n"
2415 "%point5 = OpConstant %f32 0.5\n"
2416 "%vec = OpConstantComposite %fvec3 %one %one %fzero\n"
2417 "%mat = OpConstantComposite %m2vec3 %vec %vec\n"
2418 "%const = OpConstantComposite %struct %zero %point5 %vec %mat"));
2419 cases.push_back(CaseParameter("nested_struct", "%st1 = OpTypeStruct %u32 %f32\n"
2420 "%st2 = OpTypeStruct %i32 %i32\n"
2421 "%struct = OpTypeStruct %st1 %st2\n"
2422 "%point5 = OpConstant %f32 0.5\n"
2423 "%one = OpConstant %u32 1\n"
2424 "%ten = OpConstant %i32 10\n"
2425 "%st1val = OpConstantComposite %st1 %one %point5\n"
2426 "%st2val = OpConstantComposite %st2 %ten %ten\n"
2427 "%const = OpConstantComposite %struct %st1val %st2val"));
2429 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2431 for (size_t ndx = 0; ndx < numElements; ++ndx)
2432 negativeFloats[ndx] = -positiveFloats[ndx];
2434 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
2436 map<string, string> specializations;
2437 ComputeShaderSpec spec;
2439 specializations["CONSTANT"] = cases[caseNdx].param;
2440 spec.assembly = shaderTemplate.specialize(specializations);
2441 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
2442 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
2443 spec.numWorkGroups = IVec3(numElements, 1, 1);
2445 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
2448 return group.release();
2451 // Creates a floating point number with the given exponent, and significand
2452 // bits set. It can only create normalized numbers. Only the least significant
2453 // 24 bits of the significand will be examined. The final bit of the
2454 // significand will also be ignored. This allows alignment to be written
2455 // similarly to C99 hex-floats.
2456 // For example if you wanted to write 0x1.7f34p-12 you would call
2457 // constructNormalizedFloat(-12, 0x7f3400)
2458 float constructNormalizedFloat (deInt32 exponent, deUint32 significand)
2462 for (deInt32 idx = 0; idx < 23; ++idx)
2464 f += ((significand & 0x800000) == 0) ? 0.f : std::ldexp(1.0f, -(idx + 1));
2468 return std::ldexp(f, exponent);
2471 // Compare instruction for the OpQuantizeF16 compute exact case.
2472 // Returns true if the output is what is expected from the test case.
2473 bool compareOpQuantizeF16ComputeExactCase (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
2475 if (outputAllocs.size() != 1)
2478 // We really just need this for size because we cannot compare Nans.
2479 const BufferSp& expectedOutput = expectedOutputs[0];
2480 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
2482 if (expectedOutput->getNumBytes() != 4*sizeof(float)) {
2486 if (*outputAsFloat != constructNormalizedFloat(8, 0x304000) &&
2487 *outputAsFloat != constructNormalizedFloat(8, 0x300000)) {
2492 if (*outputAsFloat != -constructNormalizedFloat(-7, 0x600000) &&
2493 *outputAsFloat != -constructNormalizedFloat(-7, 0x604000)) {
2498 if (*outputAsFloat != constructNormalizedFloat(2, 0x01C000) &&
2499 *outputAsFloat != constructNormalizedFloat(2, 0x020000)) {
2504 if (*outputAsFloat != constructNormalizedFloat(1, 0xFFC000) &&
2505 *outputAsFloat != constructNormalizedFloat(2, 0x000000)) {
2512 // Checks that every output from a test-case is a float NaN.
2513 bool compareNan (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
2515 if (outputAllocs.size() != 1)
2518 // We really just need this for size because we cannot compare Nans.
2519 const BufferSp& expectedOutput = expectedOutputs[0];
2520 const float* output_as_float = static_cast<const float*>(outputAllocs[0]->getHostPtr());;
2522 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx)
2524 if (!deFloatIsNaN(output_as_float[idx]))
2533 // Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it.
2534 tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx)
2536 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opquantize", "Tests the OpQuantizeToF16 instruction"));
2538 const std::string shader (
2539 string(getComputeAsmShaderPreamble()) +
2541 "OpSource GLSL 430\n"
2542 "OpName %main \"main\"\n"
2543 "OpName %id \"gl_GlobalInvocationID\"\n"
2545 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2547 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2549 "%id = OpVariable %uvec3ptr Input\n"
2550 "%zero = OpConstant %i32 0\n"
2552 "%main = OpFunction %void None %voidf\n"
2553 "%label = OpLabel\n"
2554 "%idval = OpLoad %uvec3 %id\n"
2555 "%x = OpCompositeExtract %u32 %idval 0\n"
2556 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2557 "%inval = OpLoad %f32 %inloc\n"
2558 "%quant = OpQuantizeToF16 %f32 %inval\n"
2559 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2560 " OpStore %outloc %quant\n"
2562 " OpFunctionEnd\n");
2565 ComputeShaderSpec spec;
2566 const deUint32 numElements = 100;
2567 vector<float> infinities;
2568 vector<float> results;
2570 infinities.reserve(numElements);
2571 results.reserve(numElements);
2573 for (size_t idx = 0; idx < numElements; ++idx)
2578 infinities.push_back(std::numeric_limits<float>::infinity());
2579 results.push_back(std::numeric_limits<float>::infinity());
2582 infinities.push_back(-std::numeric_limits<float>::infinity());
2583 results.push_back(-std::numeric_limits<float>::infinity());
2586 infinities.push_back(std::ldexp(1.0f, 16));
2587 results.push_back(std::numeric_limits<float>::infinity());
2590 infinities.push_back(std::ldexp(-1.0f, 32));
2591 results.push_back(-std::numeric_limits<float>::infinity());
2596 spec.assembly = shader;
2597 spec.inputs.push_back(BufferSp(new Float32Buffer(infinities)));
2598 spec.outputs.push_back(BufferSp(new Float32Buffer(results)));
2599 spec.numWorkGroups = IVec3(numElements, 1, 1);
2601 group->addChild(new SpvAsmComputeShaderCase(
2602 testCtx, "infinities", "Check that infinities propagated and created", spec));
2606 ComputeShaderSpec spec;
2608 const deUint32 numElements = 100;
2610 nans.reserve(numElements);
2612 for (size_t idx = 0; idx < numElements; ++idx)
2616 nans.push_back(std::numeric_limits<float>::quiet_NaN());
2620 nans.push_back(-std::numeric_limits<float>::quiet_NaN());
2624 spec.assembly = shader;
2625 spec.inputs.push_back(BufferSp(new Float32Buffer(nans)));
2626 spec.outputs.push_back(BufferSp(new Float32Buffer(nans)));
2627 spec.numWorkGroups = IVec3(numElements, 1, 1);
2628 spec.verifyIO = &compareNan;
2630 group->addChild(new SpvAsmComputeShaderCase(
2631 testCtx, "propagated_nans", "Check that nans are propagated", spec));
2635 ComputeShaderSpec spec;
2636 vector<float> small;
2637 vector<float> zeros;
2638 const deUint32 numElements = 100;
2640 small.reserve(numElements);
2641 zeros.reserve(numElements);
2643 for (size_t idx = 0; idx < numElements; ++idx)
2648 small.push_back(0.f);
2649 zeros.push_back(0.f);
2652 small.push_back(-0.f);
2653 zeros.push_back(-0.f);
2656 small.push_back(std::ldexp(1.0f, -16));
2657 zeros.push_back(0.f);
2660 small.push_back(std::ldexp(-1.0f, -32));
2661 zeros.push_back(-0.f);
2664 small.push_back(std::ldexp(1.0f, -127));
2665 zeros.push_back(0.f);
2668 small.push_back(-std::ldexp(1.0f, -128));
2669 zeros.push_back(-0.f);
2674 spec.assembly = shader;
2675 spec.inputs.push_back(BufferSp(new Float32Buffer(small)));
2676 spec.outputs.push_back(BufferSp(new Float32Buffer(zeros)));
2677 spec.numWorkGroups = IVec3(numElements, 1, 1);
2679 group->addChild(new SpvAsmComputeShaderCase(
2680 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec));
2684 ComputeShaderSpec spec;
2685 vector<float> exact;
2686 const deUint32 numElements = 200;
2688 exact.reserve(numElements);
2690 for (size_t idx = 0; idx < numElements; ++idx)
2691 exact.push_back(static_cast<float>(static_cast<int>(idx) - 100));
2693 spec.assembly = shader;
2694 spec.inputs.push_back(BufferSp(new Float32Buffer(exact)));
2695 spec.outputs.push_back(BufferSp(new Float32Buffer(exact)));
2696 spec.numWorkGroups = IVec3(numElements, 1, 1);
2698 group->addChild(new SpvAsmComputeShaderCase(
2699 testCtx, "exact", "Check that values exactly preserved where appropriate", spec));
2703 ComputeShaderSpec spec;
2704 vector<float> inputs;
2705 const deUint32 numElements = 4;
2707 inputs.push_back(constructNormalizedFloat(8, 0x300300));
2708 inputs.push_back(-constructNormalizedFloat(-7, 0x600800));
2709 inputs.push_back(constructNormalizedFloat(2, 0x01E000));
2710 inputs.push_back(constructNormalizedFloat(1, 0xFFE000));
2712 spec.assembly = shader;
2713 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase;
2714 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2715 spec.outputs.push_back(BufferSp(new Float32Buffer(inputs)));
2716 spec.numWorkGroups = IVec3(numElements, 1, 1);
2718 group->addChild(new SpvAsmComputeShaderCase(
2719 testCtx, "rounded", "Check that are rounded when needed", spec));
2722 return group.release();
2725 tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& testCtx)
2727 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop_opquantize", "Tests the OpQuantizeToF16 opcode for the OpSpecConstantOp instruction"));
2729 const std::string shader (
2730 string(getComputeAsmShaderPreamble()) +
2732 "OpName %main \"main\"\n"
2733 "OpName %id \"gl_GlobalInvocationID\"\n"
2735 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2737 "OpDecorate %sc_0 SpecId 0\n"
2738 "OpDecorate %sc_1 SpecId 1\n"
2739 "OpDecorate %sc_2 SpecId 2\n"
2740 "OpDecorate %sc_3 SpecId 3\n"
2741 "OpDecorate %sc_4 SpecId 4\n"
2742 "OpDecorate %sc_5 SpecId 5\n"
2744 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
2746 "%id = OpVariable %uvec3ptr Input\n"
2747 "%zero = OpConstant %i32 0\n"
2748 "%c_u32_6 = OpConstant %u32 6\n"
2750 "%sc_0 = OpSpecConstant %f32 0.\n"
2751 "%sc_1 = OpSpecConstant %f32 0.\n"
2752 "%sc_2 = OpSpecConstant %f32 0.\n"
2753 "%sc_3 = OpSpecConstant %f32 0.\n"
2754 "%sc_4 = OpSpecConstant %f32 0.\n"
2755 "%sc_5 = OpSpecConstant %f32 0.\n"
2757 "%sc_0_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_0\n"
2758 "%sc_1_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_1\n"
2759 "%sc_2_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_2\n"
2760 "%sc_3_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_3\n"
2761 "%sc_4_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_4\n"
2762 "%sc_5_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_5\n"
2764 "%main = OpFunction %void None %voidf\n"
2765 "%label = OpLabel\n"
2766 "%idval = OpLoad %uvec3 %id\n"
2767 "%x = OpCompositeExtract %u32 %idval 0\n"
2768 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
2769 "%selector = OpUMod %u32 %x %c_u32_6\n"
2770 " OpSelectionMerge %exit None\n"
2771 " OpSwitch %selector %exit 0 %case0 1 %case1 2 %case2 3 %case3 4 %case4 5 %case5\n"
2773 "%case0 = OpLabel\n"
2774 " OpStore %outloc %sc_0_quant\n"
2777 "%case1 = OpLabel\n"
2778 " OpStore %outloc %sc_1_quant\n"
2781 "%case2 = OpLabel\n"
2782 " OpStore %outloc %sc_2_quant\n"
2785 "%case3 = OpLabel\n"
2786 " OpStore %outloc %sc_3_quant\n"
2789 "%case4 = OpLabel\n"
2790 " OpStore %outloc %sc_4_quant\n"
2793 "%case5 = OpLabel\n"
2794 " OpStore %outloc %sc_5_quant\n"
2800 " OpFunctionEnd\n");
2803 ComputeShaderSpec spec;
2804 const deUint8 numCases = 4;
2805 vector<float> inputs (numCases, 0.f);
2806 vector<float> outputs;
2808 spec.assembly = shader;
2809 spec.numWorkGroups = IVec3(numCases, 1, 1);
2811 spec.specConstants.push_back(bitwiseCast<deUint32>(std::numeric_limits<float>::infinity()));
2812 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::numeric_limits<float>::infinity()));
2813 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, 16)));
2814 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, 32)));
2816 outputs.push_back(std::numeric_limits<float>::infinity());
2817 outputs.push_back(-std::numeric_limits<float>::infinity());
2818 outputs.push_back(std::numeric_limits<float>::infinity());
2819 outputs.push_back(-std::numeric_limits<float>::infinity());
2821 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2822 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2824 group->addChild(new SpvAsmComputeShaderCase(
2825 testCtx, "infinities", "Check that infinities propagated and created", spec));
2829 ComputeShaderSpec spec;
2830 const deUint8 numCases = 2;
2831 vector<float> inputs (numCases, 0.f);
2832 vector<float> outputs;
2834 spec.assembly = shader;
2835 spec.numWorkGroups = IVec3(numCases, 1, 1);
2836 spec.verifyIO = &compareNan;
2838 outputs.push_back(std::numeric_limits<float>::quiet_NaN());
2839 outputs.push_back(-std::numeric_limits<float>::quiet_NaN());
2841 for (deUint8 idx = 0; idx < numCases; ++idx)
2842 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
2844 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2845 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2847 group->addChild(new SpvAsmComputeShaderCase(
2848 testCtx, "propagated_nans", "Check that nans are propagated", spec));
2852 ComputeShaderSpec spec;
2853 const deUint8 numCases = 6;
2854 vector<float> inputs (numCases, 0.f);
2855 vector<float> outputs;
2857 spec.assembly = shader;
2858 spec.numWorkGroups = IVec3(numCases, 1, 1);
2860 spec.specConstants.push_back(bitwiseCast<deUint32>(0.f));
2861 spec.specConstants.push_back(bitwiseCast<deUint32>(-0.f));
2862 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -16)));
2863 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, -32)));
2864 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -127)));
2865 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::ldexp(1.0f, -128)));
2867 outputs.push_back(0.f);
2868 outputs.push_back(-0.f);
2869 outputs.push_back(0.f);
2870 outputs.push_back(-0.f);
2871 outputs.push_back(0.f);
2872 outputs.push_back(-0.f);
2874 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2875 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2877 group->addChild(new SpvAsmComputeShaderCase(
2878 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec));
2882 ComputeShaderSpec spec;
2883 const deUint8 numCases = 6;
2884 vector<float> inputs (numCases, 0.f);
2885 vector<float> outputs;
2887 spec.assembly = shader;
2888 spec.numWorkGroups = IVec3(numCases, 1, 1);
2890 for (deUint8 idx = 0; idx < 6; ++idx)
2892 const float f = static_cast<float>(idx * 10 - 30) / 4.f;
2893 spec.specConstants.push_back(bitwiseCast<deUint32>(f));
2894 outputs.push_back(f);
2897 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2898 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2900 group->addChild(new SpvAsmComputeShaderCase(
2901 testCtx, "exact", "Check that values exactly preserved where appropriate", spec));
2905 ComputeShaderSpec spec;
2906 const deUint8 numCases = 4;
2907 vector<float> inputs (numCases, 0.f);
2908 vector<float> outputs;
2910 spec.assembly = shader;
2911 spec.numWorkGroups = IVec3(numCases, 1, 1);
2912 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase;
2914 outputs.push_back(constructNormalizedFloat(8, 0x300300));
2915 outputs.push_back(-constructNormalizedFloat(-7, 0x600800));
2916 outputs.push_back(constructNormalizedFloat(2, 0x01E000));
2917 outputs.push_back(constructNormalizedFloat(1, 0xFFE000));
2919 for (deUint8 idx = 0; idx < numCases; ++idx)
2920 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx]));
2922 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs)));
2923 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs)));
2925 group->addChild(new SpvAsmComputeShaderCase(
2926 testCtx, "rounded", "Check that are rounded when needed", spec));
2929 return group.release();
2932 // Checks that constant null/composite values can be used in computation.
2933 tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx)
2935 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnullcomposite", "Spotcheck the OpConstantNull & OpConstantComposite instruction"));
2936 ComputeShaderSpec spec;
2937 de::Random rnd (deStringHash(group->getName()));
2938 const int numElements = 100;
2939 vector<float> positiveFloats (numElements, 0);
2940 vector<float> negativeFloats (numElements, 0);
2942 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
2944 for (size_t ndx = 0; ndx < numElements; ++ndx)
2945 negativeFloats[ndx] = -positiveFloats[ndx];
2948 "OpCapability Shader\n"
2949 "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
2950 "OpMemoryModel Logical GLSL450\n"
2951 "OpEntryPoint GLCompute %main \"main\" %id\n"
2952 "OpExecutionMode %main LocalSize 1 1 1\n"
2954 "OpSource GLSL 430\n"
2955 "OpName %main \"main\"\n"
2956 "OpName %id \"gl_GlobalInvocationID\"\n"
2958 "OpDecorate %id BuiltIn GlobalInvocationId\n"
2960 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) +
2962 "%fmat = OpTypeMatrix %fvec3 3\n"
2963 "%ten = OpConstant %u32 10\n"
2964 "%f32arr10 = OpTypeArray %f32 %ten\n"
2965 "%fst = OpTypeStruct %f32 %f32\n"
2967 + string(getComputeAsmInputOutputBuffer()) +
2969 "%id = OpVariable %uvec3ptr Input\n"
2970 "%zero = OpConstant %i32 0\n"
2972 // Create a bunch of null values
2973 "%unull = OpConstantNull %u32\n"
2974 "%fnull = OpConstantNull %f32\n"
2975 "%vnull = OpConstantNull %fvec3\n"
2976 "%mnull = OpConstantNull %fmat\n"
2977 "%anull = OpConstantNull %f32arr10\n"
2978 "%snull = OpConstantComposite %fst %fnull %fnull\n"
2980 "%main = OpFunction %void None %voidf\n"
2981 "%label = OpLabel\n"
2982 "%idval = OpLoad %uvec3 %id\n"
2983 "%x = OpCompositeExtract %u32 %idval 0\n"
2984 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
2985 "%inval = OpLoad %f32 %inloc\n"
2986 "%neg = OpFNegate %f32 %inval\n"
2988 // Get the abs() of (a certain element of) those null values
2989 "%unull_cov = OpConvertUToF %f32 %unull\n"
2990 "%unull_abs = OpExtInst %f32 %std450 FAbs %unull_cov\n"
2991 "%fnull_abs = OpExtInst %f32 %std450 FAbs %fnull\n"
2992 "%vnull_0 = OpCompositeExtract %f32 %vnull 0\n"
2993 "%vnull_abs = OpExtInst %f32 %std450 FAbs %vnull_0\n"
2994 "%mnull_12 = OpCompositeExtract %f32 %mnull 1 2\n"
2995 "%mnull_abs = OpExtInst %f32 %std450 FAbs %mnull_12\n"
2996 "%anull_3 = OpCompositeExtract %f32 %anull 3\n"
2997 "%anull_abs = OpExtInst %f32 %std450 FAbs %anull_3\n"
2998 "%snull_1 = OpCompositeExtract %f32 %snull 1\n"
2999 "%snull_abs = OpExtInst %f32 %std450 FAbs %snull_1\n"
3002 "%add1 = OpFAdd %f32 %neg %unull_abs\n"
3003 "%add2 = OpFAdd %f32 %add1 %fnull_abs\n"
3004 "%add3 = OpFAdd %f32 %add2 %vnull_abs\n"
3005 "%add4 = OpFAdd %f32 %add3 %mnull_abs\n"
3006 "%add5 = OpFAdd %f32 %add4 %anull_abs\n"
3007 "%final = OpFAdd %f32 %add5 %snull_abs\n"
3009 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3010 " OpStore %outloc %final\n" // write to output
3013 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
3014 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
3015 spec.numWorkGroups = IVec3(numElements, 1, 1);
3017 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec));
3019 return group.release();
3022 // Assembly code used for testing loop control is based on GLSL source code:
3025 // layout(std140, set = 0, binding = 0) readonly buffer Input {
3026 // float elements[];
3028 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
3029 // float elements[];
3033 // uint x = gl_GlobalInvocationID.x;
3034 // output_data.elements[x] = input_data.elements[x];
3035 // for (uint i = 0; i < 4; ++i)
3036 // output_data.elements[x] += 1.f;
3038 tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx)
3040 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "loop_control", "Tests loop control cases"));
3041 vector<CaseParameter> cases;
3042 de::Random rnd (deStringHash(group->getName()));
3043 const int numElements = 100;
3044 vector<float> inputFloats (numElements, 0);
3045 vector<float> outputFloats (numElements, 0);
3046 const StringTemplate shaderTemplate (
3047 string(getComputeAsmShaderPreamble()) +
3049 "OpSource GLSL 430\n"
3050 "OpName %main \"main\"\n"
3051 "OpName %id \"gl_GlobalInvocationID\"\n"
3053 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3055 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
3057 "%u32ptr = OpTypePointer Function %u32\n"
3059 "%id = OpVariable %uvec3ptr Input\n"
3060 "%zero = OpConstant %i32 0\n"
3061 "%uzero = OpConstant %u32 0\n"
3062 "%one = OpConstant %i32 1\n"
3063 "%constf1 = OpConstant %f32 1.0\n"
3064 "%four = OpConstant %u32 4\n"
3066 "%main = OpFunction %void None %voidf\n"
3067 "%entry = OpLabel\n"
3068 "%i = OpVariable %u32ptr Function\n"
3069 " OpStore %i %uzero\n"
3071 "%idval = OpLoad %uvec3 %id\n"
3072 "%x = OpCompositeExtract %u32 %idval 0\n"
3073 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3074 "%inval = OpLoad %f32 %inloc\n"
3075 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3076 " OpStore %outloc %inval\n"
3077 " OpBranch %loop_entry\n"
3079 "%loop_entry = OpLabel\n"
3080 "%i_val = OpLoad %u32 %i\n"
3081 "%cmp_lt = OpULessThan %bool %i_val %four\n"
3082 " OpLoopMerge %loop_merge %loop_body ${CONTROL}\n"
3083 " OpBranchConditional %cmp_lt %loop_body %loop_merge\n"
3084 "%loop_body = OpLabel\n"
3085 "%outval = OpLoad %f32 %outloc\n"
3086 "%addf1 = OpFAdd %f32 %outval %constf1\n"
3087 " OpStore %outloc %addf1\n"
3088 "%new_i = OpIAdd %u32 %i_val %one\n"
3089 " OpStore %i %new_i\n"
3090 " OpBranch %loop_entry\n"
3091 "%loop_merge = OpLabel\n"
3093 " OpFunctionEnd\n");
3095 cases.push_back(CaseParameter("none", "None"));
3096 cases.push_back(CaseParameter("unroll", "Unroll"));
3097 cases.push_back(CaseParameter("dont_unroll", "DontUnroll"));
3098 cases.push_back(CaseParameter("unroll_dont_unroll", "Unroll|DontUnroll"));
3100 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
3102 for (size_t ndx = 0; ndx < numElements; ++ndx)
3103 outputFloats[ndx] = inputFloats[ndx] + 4.f;
3105 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3107 map<string, string> specializations;
3108 ComputeShaderSpec spec;
3110 specializations["CONTROL"] = cases[caseNdx].param;
3111 spec.assembly = shaderTemplate.specialize(specializations);
3112 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
3113 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
3114 spec.numWorkGroups = IVec3(numElements, 1, 1);
3116 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3119 return group.release();
3122 // Assembly code used for testing selection control is based on GLSL source code:
3125 // layout(std140, set = 0, binding = 0) readonly buffer Input {
3126 // float elements[];
3128 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
3129 // float elements[];
3133 // uint x = gl_GlobalInvocationID.x;
3134 // float val = input_data.elements[x];
3136 // output_data.elements[x] = val + 1.f;
3138 // output_data.elements[x] = val - 1.f;
3140 tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx)
3142 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_control", "Tests selection control cases"));
3143 vector<CaseParameter> cases;
3144 de::Random rnd (deStringHash(group->getName()));
3145 const int numElements = 100;
3146 vector<float> inputFloats (numElements, 0);
3147 vector<float> outputFloats (numElements, 0);
3148 const StringTemplate shaderTemplate (
3149 string(getComputeAsmShaderPreamble()) +
3151 "OpSource GLSL 430\n"
3152 "OpName %main \"main\"\n"
3153 "OpName %id \"gl_GlobalInvocationID\"\n"
3155 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3157 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
3159 "%id = OpVariable %uvec3ptr Input\n"
3160 "%zero = OpConstant %i32 0\n"
3161 "%constf1 = OpConstant %f32 1.0\n"
3162 "%constf10 = OpConstant %f32 10.0\n"
3164 "%main = OpFunction %void None %voidf\n"
3165 "%entry = OpLabel\n"
3166 "%idval = OpLoad %uvec3 %id\n"
3167 "%x = OpCompositeExtract %u32 %idval 0\n"
3168 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3169 "%inval = OpLoad %f32 %inloc\n"
3170 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3171 "%cmp_gt = OpFOrdGreaterThan %bool %inval %constf10\n"
3173 " OpSelectionMerge %if_end ${CONTROL}\n"
3174 " OpBranchConditional %cmp_gt %if_true %if_false\n"
3175 "%if_true = OpLabel\n"
3176 "%addf1 = OpFAdd %f32 %inval %constf1\n"
3177 " OpStore %outloc %addf1\n"
3178 " OpBranch %if_end\n"
3179 "%if_false = OpLabel\n"
3180 "%subf1 = OpFSub %f32 %inval %constf1\n"
3181 " OpStore %outloc %subf1\n"
3182 " OpBranch %if_end\n"
3183 "%if_end = OpLabel\n"
3185 " OpFunctionEnd\n");
3187 cases.push_back(CaseParameter("none", "None"));
3188 cases.push_back(CaseParameter("flatten", "Flatten"));
3189 cases.push_back(CaseParameter("dont_flatten", "DontFlatten"));
3190 cases.push_back(CaseParameter("flatten_dont_flatten", "DontFlatten|Flatten"));
3192 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
3194 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
3195 floorAll(inputFloats);
3197 for (size_t ndx = 0; ndx < numElements; ++ndx)
3198 outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f);
3200 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3202 map<string, string> specializations;
3203 ComputeShaderSpec spec;
3205 specializations["CONTROL"] = cases[caseNdx].param;
3206 spec.assembly = shaderTemplate.specialize(specializations);
3207 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
3208 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
3209 spec.numWorkGroups = IVec3(numElements, 1, 1);
3211 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3214 return group.release();
3217 // Assembly code used for testing function control is based on GLSL source code:
3221 // layout(std140, set = 0, binding = 0) readonly buffer Input {
3222 // float elements[];
3224 // layout(std140, set = 0, binding = 1) writeonly buffer Output {
3225 // float elements[];
3228 // float const10() { return 10.f; }
3231 // uint x = gl_GlobalInvocationID.x;
3232 // output_data.elements[x] = input_data.elements[x] + const10();
3234 tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx)
3236 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "function_control", "Tests function control cases"));
3237 vector<CaseParameter> cases;
3238 de::Random rnd (deStringHash(group->getName()));
3239 const int numElements = 100;
3240 vector<float> inputFloats (numElements, 0);
3241 vector<float> outputFloats (numElements, 0);
3242 const StringTemplate shaderTemplate (
3243 string(getComputeAsmShaderPreamble()) +
3245 "OpSource GLSL 430\n"
3246 "OpName %main \"main\"\n"
3247 "OpName %func_const10 \"const10(\"\n"
3248 "OpName %id \"gl_GlobalInvocationID\"\n"
3250 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3252 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
3254 "%f32f = OpTypeFunction %f32\n"
3255 "%id = OpVariable %uvec3ptr Input\n"
3256 "%zero = OpConstant %i32 0\n"
3257 "%constf10 = OpConstant %f32 10.0\n"
3259 "%main = OpFunction %void None %voidf\n"
3260 "%entry = OpLabel\n"
3261 "%idval = OpLoad %uvec3 %id\n"
3262 "%x = OpCompositeExtract %u32 %idval 0\n"
3263 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3264 "%inval = OpLoad %f32 %inloc\n"
3265 "%ret_10 = OpFunctionCall %f32 %func_const10\n"
3266 "%fadd = OpFAdd %f32 %inval %ret_10\n"
3267 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3268 " OpStore %outloc %fadd\n"
3272 "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n"
3273 "%label = OpLabel\n"
3274 " OpReturnValue %constf10\n"
3275 " OpFunctionEnd\n");
3277 cases.push_back(CaseParameter("none", "None"));
3278 cases.push_back(CaseParameter("inline", "Inline"));
3279 cases.push_back(CaseParameter("dont_inline", "DontInline"));
3280 cases.push_back(CaseParameter("pure", "Pure"));
3281 cases.push_back(CaseParameter("const", "Const"));
3282 cases.push_back(CaseParameter("inline_pure", "Inline|Pure"));
3283 cases.push_back(CaseParameter("const_dont_inline", "Const|DontInline"));
3284 cases.push_back(CaseParameter("inline_dont_inline", "Inline|DontInline"));
3285 cases.push_back(CaseParameter("pure_inline_dont_inline", "Pure|Inline|DontInline"));
3287 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
3289 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences.
3290 floorAll(inputFloats);
3292 for (size_t ndx = 0; ndx < numElements; ++ndx)
3293 outputFloats[ndx] = inputFloats[ndx] + 10.f;
3295 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3297 map<string, string> specializations;
3298 ComputeShaderSpec spec;
3300 specializations["CONTROL"] = cases[caseNdx].param;
3301 spec.assembly = shaderTemplate.specialize(specializations);
3302 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
3303 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
3304 spec.numWorkGroups = IVec3(numElements, 1, 1);
3306 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3309 return group.release();
3312 tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx)
3314 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory_access", "Tests memory access cases"));
3315 vector<CaseParameter> cases;
3316 de::Random rnd (deStringHash(group->getName()));
3317 const int numElements = 100;
3318 vector<float> inputFloats (numElements, 0);
3319 vector<float> outputFloats (numElements, 0);
3320 const StringTemplate shaderTemplate (
3321 string(getComputeAsmShaderPreamble()) +
3323 "OpSource GLSL 430\n"
3324 "OpName %main \"main\"\n"
3325 "OpName %id \"gl_GlobalInvocationID\"\n"
3327 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3329 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
3331 "%f32ptr_f = OpTypePointer Function %f32\n"
3333 "%id = OpVariable %uvec3ptr Input\n"
3334 "%zero = OpConstant %i32 0\n"
3335 "%four = OpConstant %i32 4\n"
3337 "%main = OpFunction %void None %voidf\n"
3338 "%label = OpLabel\n"
3339 "%copy = OpVariable %f32ptr_f Function\n"
3340 "%idval = OpLoad %uvec3 %id ${ACCESS}\n"
3341 "%x = OpCompositeExtract %u32 %idval 0\n"
3342 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3343 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3344 " OpCopyMemory %copy %inloc ${ACCESS}\n"
3345 "%val1 = OpLoad %f32 %copy\n"
3346 "%val2 = OpLoad %f32 %inloc\n"
3347 "%add = OpFAdd %f32 %val1 %val2\n"
3348 " OpStore %outloc %add ${ACCESS}\n"
3350 " OpFunctionEnd\n");
3352 cases.push_back(CaseParameter("null", ""));
3353 cases.push_back(CaseParameter("none", "None"));
3354 cases.push_back(CaseParameter("volatile", "Volatile"));
3355 cases.push_back(CaseParameter("aligned", "Aligned 4"));
3356 cases.push_back(CaseParameter("nontemporal", "Nontemporal"));
3357 cases.push_back(CaseParameter("aligned_nontemporal", "Aligned|Nontemporal 4"));
3358 cases.push_back(CaseParameter("aligned_volatile", "Volatile|Aligned 4"));
3360 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements);
3362 for (size_t ndx = 0; ndx < numElements; ++ndx)
3363 outputFloats[ndx] = inputFloats[ndx] + inputFloats[ndx];
3365 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3367 map<string, string> specializations;
3368 ComputeShaderSpec spec;
3370 specializations["ACCESS"] = cases[caseNdx].param;
3371 spec.assembly = shaderTemplate.specialize(specializations);
3372 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats)));
3373 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats)));
3374 spec.numWorkGroups = IVec3(numElements, 1, 1);
3376 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3379 return group.release();
3382 // Checks that we can get undefined values for various types, without exercising a computation with it.
3383 tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx)
3385 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opundef", "Tests the OpUndef instruction"));
3386 vector<CaseParameter> cases;
3387 de::Random rnd (deStringHash(group->getName()));
3388 const int numElements = 100;
3389 vector<float> positiveFloats (numElements, 0);
3390 vector<float> negativeFloats (numElements, 0);
3391 const StringTemplate shaderTemplate (
3392 string(getComputeAsmShaderPreamble()) +
3394 "OpSource GLSL 430\n"
3395 "OpName %main \"main\"\n"
3396 "OpName %id \"gl_GlobalInvocationID\"\n"
3398 "OpDecorate %id BuiltIn GlobalInvocationId\n"
3400 + string(getComputeAsmInputOutputBufferTraits()) + string(getComputeAsmCommonTypes()) + string(getComputeAsmInputOutputBuffer()) +
3404 "%id = OpVariable %uvec3ptr Input\n"
3405 "%zero = OpConstant %i32 0\n"
3407 "%main = OpFunction %void None %voidf\n"
3408 "%label = OpLabel\n"
3410 "%undef = OpUndef ${TYPE}\n"
3412 "%idval = OpLoad %uvec3 %id\n"
3413 "%x = OpCompositeExtract %u32 %idval 0\n"
3415 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n"
3416 "%inval = OpLoad %f32 %inloc\n"
3417 "%neg = OpFNegate %f32 %inval\n"
3418 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n"
3419 " OpStore %outloc %neg\n"
3421 " OpFunctionEnd\n");
3423 cases.push_back(CaseParameter("bool", "%bool"));
3424 cases.push_back(CaseParameter("sint32", "%i32"));
3425 cases.push_back(CaseParameter("uint32", "%u32"));
3426 cases.push_back(CaseParameter("float32", "%f32"));
3427 cases.push_back(CaseParameter("vec4float32", "%fvec4"));
3428 cases.push_back(CaseParameter("vec2uint32", "%uvec2"));
3429 cases.push_back(CaseParameter("matrix", "%fmat33"));
3430 cases.push_back(CaseParameter("image", "%image"));
3431 cases.push_back(CaseParameter("sampler", "%sampler"));
3432 cases.push_back(CaseParameter("sampledimage", "%simage"));
3433 cases.push_back(CaseParameter("array", "%uarr100"));
3434 cases.push_back(CaseParameter("runtimearray", "%f32arr"));
3435 cases.push_back(CaseParameter("struct", "%struct"));
3436 cases.push_back(CaseParameter("pointer", "%pointer"));
3438 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements);
3440 for (size_t ndx = 0; ndx < numElements; ++ndx)
3441 negativeFloats[ndx] = -positiveFloats[ndx];
3443 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
3445 map<string, string> specializations;
3446 ComputeShaderSpec spec;
3448 specializations["TYPE"] = cases[caseNdx].param;
3449 spec.assembly = shaderTemplate.specialize(specializations);
3450 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats)));
3451 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats)));
3452 spec.numWorkGroups = IVec3(numElements, 1, 1);
3454 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec));
3457 return group.release();
3461 tcu::TestCaseGroup* createOpSourceTests (tcu::TestContext& testCtx)
3463 struct NameCodePair { string name, code; };
3464 RGBA defaultColors[4];
3465 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsource", "OpSource instruction"));
3466 const std::string opsourceGLSLWithFile = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile ";
3467 map<string, string> fragments = passthruFragments();
3468 const NameCodePair tests[] =
3470 {"unknown", "OpSource Unknown 321"},
3471 {"essl", "OpSource ESSL 310"},
3472 {"glsl", "OpSource GLSL 450"},
3473 {"opencl_cpp", "OpSource OpenCL_CPP 120"},
3474 {"opencl_c", "OpSource OpenCL_C 120"},
3475 {"multiple", "OpSource GLSL 450\nOpSource GLSL 450"},
3476 {"file", opsourceGLSLWithFile},
3477 {"source", opsourceGLSLWithFile + "\"void main(){}\""},
3478 // Longest possible source string: SPIR-V limits instructions to 65535
3479 // words, of which the first 4 are opsourceGLSLWithFile; the rest will
3480 // contain 65530 UTF8 characters (one word each) plus one last word
3481 // containing 3 ASCII characters and \0.
3482 {"longsource", opsourceGLSLWithFile + '"' + makeLongUTF8String(65530) + "ccc" + '"'}
3485 getDefaultColors(defaultColors);
3486 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
3488 fragments["debug"] = tests[testNdx].code;
3489 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
3492 return opSourceTests.release();
3495 tcu::TestCaseGroup* createOpSourceContinuedTests (tcu::TestContext& testCtx)
3497 struct NameCodePair { string name, code; };
3498 RGBA defaultColors[4];
3499 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsourcecontinued", "OpSourceContinued instruction"));
3500 map<string, string> fragments = passthruFragments();
3501 const std::string opsource = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile \"void main(){}\"\n";
3502 const NameCodePair tests[] =
3504 {"empty", opsource + "OpSourceContinued \"\""},
3505 {"short", opsource + "OpSourceContinued \"abcde\""},
3506 {"multiple", opsource + "OpSourceContinued \"abcde\"\nOpSourceContinued \"fghij\""},
3507 // Longest possible source string: SPIR-V limits instructions to 65535
3508 // words, of which the first one is OpSourceContinued/length; the rest
3509 // will contain 65533 UTF8 characters (one word each) plus one last word
3510 // containing 3 ASCII characters and \0.
3511 {"long", opsource + "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\""}
3514 getDefaultColors(defaultColors);
3515 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
3517 fragments["debug"] = tests[testNdx].code;
3518 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get());
3521 return opSourceTests.release();
3524 tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx)
3526 RGBA defaultColors[4];
3527 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opnoline", "OpNoLine instruction"));
3528 map<string, string> fragments;
3529 getDefaultColors(defaultColors);
3530 fragments["debug"] =
3531 "%name = OpString \"name\"\n";
3533 fragments["pre_main"] =
3536 "OpLine %name 1 1\n"
3538 "OpLine %name 1 1\n"
3539 "OpLine %name 1 1\n"
3540 "%second_function = OpFunction %v4f32 None %v4f32_function\n"
3542 "OpLine %name 1 1\n"
3544 "OpLine %name 1 1\n"
3545 "OpLine %name 1 1\n"
3546 "%second_param1 = OpFunctionParameter %v4f32\n"
3549 "%label_secondfunction = OpLabel\n"
3551 "OpReturnValue %second_param1\n"
3556 fragments["testfun"] =
3557 // A %test_code function that returns its argument unchanged.
3560 "OpLine %name 1 1\n"
3561 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3563 "%param1 = OpFunctionParameter %v4f32\n"
3566 "%label_testfun = OpLabel\n"
3568 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
3569 "OpReturnValue %val1\n"
3571 "OpLine %name 1 1\n"
3574 createTestsForAllStages("opnoline", defaultColors, defaultColors, fragments, opLineTests.get());
3576 return opLineTests.release();
3580 tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx)
3582 RGBA defaultColors[4];
3583 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opline", "OpLine instruction"));
3584 map<string, string> fragments;
3585 std::vector<std::pair<std::string, std::string> > problemStrings;
3587 problemStrings.push_back(std::make_pair<std::string, std::string>("empty_name", ""));
3588 problemStrings.push_back(std::make_pair<std::string, std::string>("short_name", "short_name"));
3589 problemStrings.push_back(std::make_pair<std::string, std::string>("long_name", makeLongUTF8String(65530) + "ccc"));
3590 getDefaultColors(defaultColors);
3592 fragments["debug"] =
3593 "%other_name = OpString \"other_name\"\n";
3595 fragments["pre_main"] =
3596 "OpLine %file_name 32 0\n"
3597 "OpLine %file_name 32 32\n"
3598 "OpLine %file_name 32 40\n"
3599 "OpLine %other_name 32 40\n"
3600 "OpLine %other_name 0 100\n"
3601 "OpLine %other_name 0 4294967295\n"
3602 "OpLine %other_name 4294967295 0\n"
3603 "OpLine %other_name 32 40\n"
3604 "OpLine %file_name 0 0\n"
3605 "%second_function = OpFunction %v4f32 None %v4f32_function\n"
3606 "OpLine %file_name 1 0\n"
3607 "%second_param1 = OpFunctionParameter %v4f32\n"
3608 "OpLine %file_name 1 3\n"
3609 "OpLine %file_name 1 2\n"
3610 "%label_secondfunction = OpLabel\n"
3611 "OpLine %file_name 0 2\n"
3612 "OpReturnValue %second_param1\n"
3614 "OpLine %file_name 0 2\n"
3615 "OpLine %file_name 0 2\n";
3617 fragments["testfun"] =
3618 // A %test_code function that returns its argument unchanged.
3619 "OpLine %file_name 1 0\n"
3620 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3621 "OpLine %file_name 16 330\n"
3622 "%param1 = OpFunctionParameter %v4f32\n"
3623 "OpLine %file_name 14 442\n"
3624 "%label_testfun = OpLabel\n"
3625 "OpLine %file_name 11 1024\n"
3626 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n"
3627 "OpLine %file_name 2 97\n"
3628 "OpReturnValue %val1\n"
3630 "OpLine %file_name 5 32\n";
3632 for (size_t i = 0; i < problemStrings.size(); ++i)
3634 map<string, string> testFragments = fragments;
3635 testFragments["debug"] += "%file_name = OpString \"" + problemStrings[i].second + "\"\n";
3636 createTestsForAllStages(string("opline") + "_" + problemStrings[i].first, defaultColors, defaultColors, testFragments, opLineTests.get());
3639 return opLineTests.release();
3642 tcu::TestCaseGroup* createOpConstantNullTests(tcu::TestContext& testCtx)
3644 de::MovePtr<tcu::TestCaseGroup> opConstantNullTests (new tcu::TestCaseGroup(testCtx, "opconstantnull", "OpConstantNull instruction"));
3648 const char functionStart[] =
3649 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3650 "%param1 = OpFunctionParameter %v4f32\n"
3653 const char functionEnd[] =
3654 "OpReturnValue %transformed_param\n"
3657 struct NameConstantsCode
3664 NameConstantsCode tests[] =
3668 "%cnull = OpConstantNull %v4f32\n",
3669 "%transformed_param = OpFAdd %v4f32 %param1 %cnull\n"
3673 "%cnull = OpConstantNull %f32\n",
3674 "%vp = OpVariable %fp_v4f32 Function\n"
3675 "%v = OpLoad %v4f32 %vp\n"
3676 "%v0 = OpVectorInsertDynamic %v4f32 %v %cnull %c_i32_0\n"
3677 "%v1 = OpVectorInsertDynamic %v4f32 %v0 %cnull %c_i32_1\n"
3678 "%v2 = OpVectorInsertDynamic %v4f32 %v1 %cnull %c_i32_2\n"
3679 "%v3 = OpVectorInsertDynamic %v4f32 %v2 %cnull %c_i32_3\n"
3680 "%transformed_param = OpFAdd %v4f32 %param1 %v3\n"
3684 "%cnull = OpConstantNull %bool\n",
3685 "%v = OpVariable %fp_v4f32 Function\n"
3686 " OpStore %v %param1\n"
3687 " OpSelectionMerge %false_label None\n"
3688 " OpBranchConditional %cnull %true_label %false_label\n"
3689 "%true_label = OpLabel\n"
3690 " OpStore %v %c_v4f32_0_5_0_5_0_5_0_5\n"
3691 " OpBranch %false_label\n"
3692 "%false_label = OpLabel\n"
3693 "%transformed_param = OpLoad %v4f32 %v\n"
3697 "%cnull = OpConstantNull %i32\n",
3698 "%v = OpVariable %fp_v4f32 Function %c_v4f32_0_5_0_5_0_5_0_5\n"
3699 "%b = OpIEqual %bool %cnull %c_i32_0\n"
3700 " OpSelectionMerge %false_label None\n"
3701 " OpBranchConditional %b %true_label %false_label\n"
3702 "%true_label = OpLabel\n"
3703 " OpStore %v %param1\n"
3704 " OpBranch %false_label\n"
3705 "%false_label = OpLabel\n"
3706 "%transformed_param = OpLoad %v4f32 %v\n"
3710 "%stype = OpTypeStruct %f32 %v4f32\n"
3711 "%fp_stype = OpTypePointer Function %stype\n"
3712 "%cnull = OpConstantNull %stype\n",
3713 "%v = OpVariable %fp_stype Function %cnull\n"
3714 "%f = OpAccessChain %fp_v4f32 %v %c_i32_1\n"
3715 "%f_val = OpLoad %v4f32 %f\n"
3716 "%transformed_param = OpFAdd %v4f32 %param1 %f_val\n"
3720 "%a4_v4f32 = OpTypeArray %v4f32 %c_u32_4\n"
3721 "%fp_a4_v4f32 = OpTypePointer Function %a4_v4f32\n"
3722 "%cnull = OpConstantNull %a4_v4f32\n",
3723 "%v = OpVariable %fp_a4_v4f32 Function %cnull\n"
3724 "%f = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
3725 "%f1 = OpAccessChain %fp_v4f32 %v %c_u32_1\n"
3726 "%f2 = OpAccessChain %fp_v4f32 %v %c_u32_2\n"
3727 "%f3 = OpAccessChain %fp_v4f32 %v %c_u32_3\n"
3728 "%f_val = OpLoad %v4f32 %f\n"
3729 "%f1_val = OpLoad %v4f32 %f1\n"
3730 "%f2_val = OpLoad %v4f32 %f2\n"
3731 "%f3_val = OpLoad %v4f32 %f3\n"
3732 "%t0 = OpFAdd %v4f32 %param1 %f_val\n"
3733 "%t1 = OpFAdd %v4f32 %t0 %f1_val\n"
3734 "%t2 = OpFAdd %v4f32 %t1 %f2_val\n"
3735 "%transformed_param = OpFAdd %v4f32 %t2 %f3_val\n"
3739 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
3740 "%cnull = OpConstantNull %mat4x4_f32\n",
3741 // Our null matrix * any vector should result in a zero vector.
3742 "%v = OpVectorTimesMatrix %v4f32 %param1 %cnull\n"
3743 "%transformed_param = OpFAdd %v4f32 %param1 %v\n"
3747 getHalfColorsFullAlpha(colors);
3749 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
3751 map<string, string> fragments;
3752 fragments["pre_main"] = tests[testNdx].constants;
3753 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
3754 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, opConstantNullTests.get());
3756 return opConstantNullTests.release();
3758 tcu::TestCaseGroup* createOpConstantCompositeTests(tcu::TestContext& testCtx)
3760 de::MovePtr<tcu::TestCaseGroup> opConstantCompositeTests (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "OpConstantComposite instruction"));
3761 RGBA inputColors[4];
3762 RGBA outputColors[4];
3765 const char functionStart[] =
3766 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3767 "%param1 = OpFunctionParameter %v4f32\n"
3770 const char functionEnd[] =
3771 "OpReturnValue %transformed_param\n"
3774 struct NameConstantsCode
3781 NameConstantsCode tests[] =
3786 "%cval = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0\n",
3787 "%transformed_param = OpFAdd %v4f32 %param1 %cval\n"
3792 "%stype = OpTypeStruct %v4f32 %f32\n"
3793 "%fp_stype = OpTypePointer Function %stype\n"
3794 "%f32_n_1 = OpConstant %f32 -1.0\n"
3795 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
3796 "%cvec = OpConstantComposite %v4f32 %f32_1_5 %f32_1_5 %f32_1_5 %c_f32_1\n"
3797 "%cval = OpConstantComposite %stype %cvec %f32_n_1\n",
3799 "%v = OpVariable %fp_stype Function %cval\n"
3800 "%vec_ptr = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
3801 "%f32_ptr = OpAccessChain %fp_f32 %v %c_u32_1\n"
3802 "%vec_val = OpLoad %v4f32 %vec_ptr\n"
3803 "%f32_val = OpLoad %f32 %f32_ptr\n"
3804 "%tmp1 = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_1 %f32_val\n" // vec4(-1)
3805 "%tmp2 = OpFAdd %v4f32 %tmp1 %param1\n" // param1 + vec4(-1)
3806 "%transformed_param = OpFAdd %v4f32 %tmp2 %vec_val\n" // param1 + vec4(-1) + vec4(1.5, 1.5, 1.5, 1.0)
3809 // [1|0|0|0.5] [x] = x + 0.5
3810 // [0|1|0|0.5] [y] = y + 0.5
3811 // [0|0|1|0.5] [z] = z + 0.5
3812 // [0|0|0|1 ] [1] = 1
3815 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n"
3816 "%v4f32_1_0_0_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_0\n"
3817 "%v4f32_0_1_0_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_1 %c_f32_0 %c_f32_0\n"
3818 "%v4f32_0_0_1_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_1 %c_f32_0\n"
3819 "%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"
3820 "%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",
3822 "%transformed_param = OpMatrixTimesVector %v4f32 %cval %param1\n"
3827 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
3828 "%fp_a4f32 = OpTypePointer Function %a4f32\n"
3829 "%f32_n_1 = OpConstant %f32 -1.0\n"
3830 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5
3831 "%carr = OpConstantComposite %a4f32 %c_f32_0 %f32_n_1 %f32_1_5 %c_f32_0\n",
3833 "%v = OpVariable %fp_a4f32 Function %carr\n"
3834 "%f = OpAccessChain %fp_f32 %v %c_u32_0\n"
3835 "%f1 = OpAccessChain %fp_f32 %v %c_u32_1\n"
3836 "%f2 = OpAccessChain %fp_f32 %v %c_u32_2\n"
3837 "%f3 = OpAccessChain %fp_f32 %v %c_u32_3\n"
3838 "%f_val = OpLoad %f32 %f\n"
3839 "%f1_val = OpLoad %f32 %f1\n"
3840 "%f2_val = OpLoad %f32 %f2\n"
3841 "%f3_val = OpLoad %f32 %f3\n"
3842 "%ftot1 = OpFAdd %f32 %f_val %f1_val\n"
3843 "%ftot2 = OpFAdd %f32 %ftot1 %f2_val\n"
3844 "%ftot3 = OpFAdd %f32 %ftot2 %f3_val\n" // 0 - 1 + 1.5 + 0
3845 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %ftot3\n"
3846 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
3853 // [ 1.0, 1.0, 1.0, 1.0]
3857 // [ 0.0, 0.5, 0.0, 0.0]
3861 // [ 1.0, 1.0, 1.0, 1.0]
3864 "array_of_struct_of_array",
3866 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
3867 "%fp_a4f32 = OpTypePointer Function %a4f32\n"
3868 "%stype = OpTypeStruct %f32 %a4f32\n"
3869 "%a3stype = OpTypeArray %stype %c_u32_3\n"
3870 "%fp_a3stype = OpTypePointer Function %a3stype\n"
3871 "%ca4f32_0 = OpConstantComposite %a4f32 %c_f32_0 %c_f32_0_5 %c_f32_0 %c_f32_0\n"
3872 "%ca4f32_1 = OpConstantComposite %a4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
3873 "%cstype1 = OpConstantComposite %stype %c_f32_0 %ca4f32_1\n"
3874 "%cstype2 = OpConstantComposite %stype %c_f32_1 %ca4f32_0\n"
3875 "%carr = OpConstantComposite %a3stype %cstype1 %cstype2 %cstype1",
3877 "%v = OpVariable %fp_a3stype Function %carr\n"
3878 "%f = OpAccessChain %fp_f32 %v %c_u32_1 %c_u32_1 %c_u32_1\n"
3879 "%f_l = OpLoad %f32 %f\n"
3880 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %f_l\n"
3881 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n"
3885 getHalfColorsFullAlpha(inputColors);
3886 outputColors[0] = RGBA(255, 255, 255, 255);
3887 outputColors[1] = RGBA(255, 127, 127, 255);
3888 outputColors[2] = RGBA(127, 255, 127, 255);
3889 outputColors[3] = RGBA(127, 127, 255, 255);
3891 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx)
3893 map<string, string> fragments;
3894 fragments["pre_main"] = tests[testNdx].constants;
3895 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd;
3896 createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, opConstantCompositeTests.get());
3898 return opConstantCompositeTests.release();
3901 tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx)
3903 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_block_order", "Out-of-order blocks for selection"));
3904 RGBA inputColors[4];
3905 RGBA outputColors[4];
3906 map<string, string> fragments;
3908 // vec4 test_code(vec4 param) {
3909 // vec4 result = param;
3910 // for (int i = 0; i < 4; ++i) {
3911 // if (i == 0) result[i] = 0.;
3912 // else result[i] = 1. - result[i];
3916 const char function[] =
3917 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
3918 "%param1 = OpFunctionParameter %v4f32\n"
3920 "%iptr = OpVariable %fp_i32 Function\n"
3921 "%result = OpVariable %fp_v4f32 Function\n"
3922 " OpStore %iptr %c_i32_0\n"
3923 " OpStore %result %param1\n"
3926 // Loop entry block.
3928 "%ival = OpLoad %i32 %iptr\n"
3929 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
3930 " OpLoopMerge %exit %if_entry None\n"
3931 " OpBranchConditional %lt_4 %if_entry %exit\n"
3933 // Merge block for loop.
3935 "%ret = OpLoad %v4f32 %result\n"
3936 " OpReturnValue %ret\n"
3938 // If-statement entry block.
3939 "%if_entry = OpLabel\n"
3940 "%loc = OpAccessChain %fp_f32 %result %ival\n"
3941 "%eq_0 = OpIEqual %bool %ival %c_i32_0\n"
3942 " OpSelectionMerge %if_exit None\n"
3943 " OpBranchConditional %eq_0 %if_true %if_false\n"
3945 // False branch for if-statement.
3946 "%if_false = OpLabel\n"
3947 "%val = OpLoad %f32 %loc\n"
3948 "%sub = OpFSub %f32 %c_f32_1 %val\n"
3949 " OpStore %loc %sub\n"
3950 " OpBranch %if_exit\n"
3952 // Merge block for if-statement.
3953 "%if_exit = OpLabel\n"
3954 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
3955 " OpStore %iptr %ival_next\n"
3958 // True branch for if-statement.
3959 "%if_true = OpLabel\n"
3960 " OpStore %loc %c_f32_0\n"
3961 " OpBranch %if_exit\n"
3965 fragments["testfun"] = function;
3967 inputColors[0] = RGBA(127, 127, 127, 0);
3968 inputColors[1] = RGBA(127, 0, 0, 0);
3969 inputColors[2] = RGBA(0, 127, 0, 0);
3970 inputColors[3] = RGBA(0, 0, 127, 0);
3972 outputColors[0] = RGBA(0, 128, 128, 255);
3973 outputColors[1] = RGBA(0, 255, 255, 255);
3974 outputColors[2] = RGBA(0, 128, 255, 255);
3975 outputColors[3] = RGBA(0, 255, 128, 255);
3977 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
3979 return group.release();
3982 tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx)
3984 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "switch_block_order", "Out-of-order blocks for switch"));
3985 RGBA inputColors[4];
3986 RGBA outputColors[4];
3987 map<string, string> fragments;
3989 const char typesAndConstants[] =
3990 "%c_f32_p2 = OpConstant %f32 0.2\n"
3991 "%c_f32_p4 = OpConstant %f32 0.4\n"
3992 "%c_f32_p6 = OpConstant %f32 0.6\n"
3993 "%c_f32_p8 = OpConstant %f32 0.8\n";
3995 // vec4 test_code(vec4 param) {
3996 // vec4 result = param;
3997 // for (int i = 0; i < 4; ++i) {
3999 // case 0: result[i] += .2; break;
4000 // case 1: result[i] += .6; break;
4001 // case 2: result[i] += .4; break;
4002 // case 3: result[i] += .8; break;
4003 // default: break; // unreachable
4008 const char function[] =
4009 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4010 "%param1 = OpFunctionParameter %v4f32\n"
4012 "%iptr = OpVariable %fp_i32 Function\n"
4013 "%result = OpVariable %fp_v4f32 Function\n"
4014 " OpStore %iptr %c_i32_0\n"
4015 " OpStore %result %param1\n"
4018 // Loop entry block.
4020 "%ival = OpLoad %i32 %iptr\n"
4021 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
4022 " OpLoopMerge %exit %switch_exit None\n"
4023 " OpBranchConditional %lt_4 %switch_entry %exit\n"
4025 // Merge block for loop.
4027 "%ret = OpLoad %v4f32 %result\n"
4028 " OpReturnValue %ret\n"
4030 // Switch-statement entry block.
4031 "%switch_entry = OpLabel\n"
4032 "%loc = OpAccessChain %fp_f32 %result %ival\n"
4033 "%val = OpLoad %f32 %loc\n"
4034 " OpSelectionMerge %switch_exit None\n"
4035 " OpSwitch %ival %switch_default 0 %case0 1 %case1 2 %case2 3 %case3\n"
4037 "%case2 = OpLabel\n"
4038 "%addp4 = OpFAdd %f32 %val %c_f32_p4\n"
4039 " OpStore %loc %addp4\n"
4040 " OpBranch %switch_exit\n"
4042 "%switch_default = OpLabel\n"
4045 "%case3 = OpLabel\n"
4046 "%addp8 = OpFAdd %f32 %val %c_f32_p8\n"
4047 " OpStore %loc %addp8\n"
4048 " OpBranch %switch_exit\n"
4050 "%case0 = OpLabel\n"
4051 "%addp2 = OpFAdd %f32 %val %c_f32_p2\n"
4052 " OpStore %loc %addp2\n"
4053 " OpBranch %switch_exit\n"
4055 // Merge block for switch-statement.
4056 "%switch_exit = OpLabel\n"
4057 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
4058 " OpStore %iptr %ival_next\n"
4061 "%case1 = OpLabel\n"
4062 "%addp6 = OpFAdd %f32 %val %c_f32_p6\n"
4063 " OpStore %loc %addp6\n"
4064 " OpBranch %switch_exit\n"
4068 fragments["pre_main"] = typesAndConstants;
4069 fragments["testfun"] = function;
4071 inputColors[0] = RGBA(127, 27, 127, 51);
4072 inputColors[1] = RGBA(127, 0, 0, 51);
4073 inputColors[2] = RGBA(0, 27, 0, 51);
4074 inputColors[3] = RGBA(0, 0, 127, 51);
4076 outputColors[0] = RGBA(178, 180, 229, 255);
4077 outputColors[1] = RGBA(178, 153, 102, 255);
4078 outputColors[2] = RGBA(51, 180, 102, 255);
4079 outputColors[3] = RGBA(51, 153, 229, 255);
4081 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get());
4083 return group.release();
4086 tcu::TestCaseGroup* createDecorationGroupTests(tcu::TestContext& testCtx)
4088 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Decoration group tests"));
4089 RGBA inputColors[4];
4090 RGBA outputColors[4];
4091 map<string, string> fragments;
4093 const char decorations[] =
4094 "OpDecorate %array_group ArrayStride 4\n"
4095 "OpDecorate %struct_member_group Offset 0\n"
4096 "%array_group = OpDecorationGroup\n"
4097 "%struct_member_group = OpDecorationGroup\n"
4099 "OpDecorate %group1 RelaxedPrecision\n"
4100 "OpDecorate %group3 RelaxedPrecision\n"
4101 "OpDecorate %group3 Invariant\n"
4102 "OpDecorate %group3 Restrict\n"
4103 "%group0 = OpDecorationGroup\n"
4104 "%group1 = OpDecorationGroup\n"
4105 "%group3 = OpDecorationGroup\n";
4107 const char typesAndConstants[] =
4108 "%a3f32 = OpTypeArray %f32 %c_u32_3\n"
4109 "%struct1 = OpTypeStruct %a3f32\n"
4110 "%struct2 = OpTypeStruct %a3f32\n"
4111 "%fp_struct1 = OpTypePointer Function %struct1\n"
4112 "%fp_struct2 = OpTypePointer Function %struct2\n"
4113 "%c_f32_2 = OpConstant %f32 2.\n"
4114 "%c_f32_n2 = OpConstant %f32 -2.\n"
4116 "%c_a3f32_1 = OpConstantComposite %a3f32 %c_f32_1 %c_f32_2 %c_f32_1\n"
4117 "%c_a3f32_2 = OpConstantComposite %a3f32 %c_f32_n1 %c_f32_n2 %c_f32_n1\n"
4118 "%c_struct1 = OpConstantComposite %struct1 %c_a3f32_1\n"
4119 "%c_struct2 = OpConstantComposite %struct2 %c_a3f32_2\n";
4121 const char function[] =
4122 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4123 "%param = OpFunctionParameter %v4f32\n"
4124 "%entry = OpLabel\n"
4125 "%result = OpVariable %fp_v4f32 Function\n"
4126 "%v_struct1 = OpVariable %fp_struct1 Function\n"
4127 "%v_struct2 = OpVariable %fp_struct2 Function\n"
4128 " OpStore %result %param\n"
4129 " OpStore %v_struct1 %c_struct1\n"
4130 " OpStore %v_struct2 %c_struct2\n"
4131 "%ptr1 = OpAccessChain %fp_f32 %v_struct1 %c_i32_0 %c_i32_2\n"
4132 "%val1 = OpLoad %f32 %ptr1\n"
4133 "%ptr2 = OpAccessChain %fp_f32 %v_struct2 %c_i32_0 %c_i32_2\n"
4134 "%val2 = OpLoad %f32 %ptr2\n"
4135 "%addvalues = OpFAdd %f32 %val1 %val2\n"
4136 "%ptr = OpAccessChain %fp_f32 %result %c_i32_1\n"
4137 "%val = OpLoad %f32 %ptr\n"
4138 "%addresult = OpFAdd %f32 %addvalues %val\n"
4139 " OpStore %ptr %addresult\n"
4140 "%ret = OpLoad %v4f32 %result\n"
4141 " OpReturnValue %ret\n"
4144 struct CaseNameDecoration
4150 CaseNameDecoration tests[] =
4153 "same_decoration_group_on_multiple_types",
4154 "OpGroupMemberDecorate %struct_member_group %struct1 0 %struct2 0\n"
4157 "empty_decoration_group",
4158 "OpGroupDecorate %group0 %a3f32\n"
4159 "OpGroupDecorate %group0 %result\n"
4162 "one_element_decoration_group",
4163 "OpGroupDecorate %array_group %a3f32\n"
4166 "multiple_elements_decoration_group",
4167 "OpGroupDecorate %group3 %v_struct1\n"
4170 "multiple_decoration_groups_on_same_variable",
4171 "OpGroupDecorate %group0 %v_struct2\n"
4172 "OpGroupDecorate %group1 %v_struct2\n"
4173 "OpGroupDecorate %group3 %v_struct2\n"
4176 "same_decoration_group_multiple_times",
4177 "OpGroupDecorate %group1 %addvalues\n"
4178 "OpGroupDecorate %group1 %addvalues\n"
4179 "OpGroupDecorate %group1 %addvalues\n"
4184 getHalfColorsFullAlpha(inputColors);
4185 getHalfColorsFullAlpha(outputColors);
4187 for (size_t idx = 0; idx < (sizeof(tests) / sizeof(tests[0])); ++idx)
4189 fragments["decoration"] = decorations + tests[idx].decoration;
4190 fragments["pre_main"] = typesAndConstants;
4191 fragments["testfun"] = function;
4193 createTestsForAllStages(tests[idx].name, inputColors, outputColors, fragments, group.get());
4196 return group.release();
4199 struct SpecConstantTwoIntGraphicsCase
4201 const char* caseName;
4202 const char* scDefinition0;
4203 const char* scDefinition1;
4204 const char* scResultType;
4205 const char* scOperation;
4206 deInt32 scActualValue0;
4207 deInt32 scActualValue1;
4208 const char* resultOperation;
4209 RGBA expectedColors[4];
4211 SpecConstantTwoIntGraphicsCase (const char* name,
4212 const char* definition0,
4213 const char* definition1,
4214 const char* resultType,
4215 const char* operation,
4218 const char* resultOp,
4219 const RGBA (&output)[4])
4221 , scDefinition0 (definition0)
4222 , scDefinition1 (definition1)
4223 , scResultType (resultType)
4224 , scOperation (operation)
4225 , scActualValue0 (value0)
4226 , scActualValue1 (value1)
4227 , resultOperation (resultOp)
4229 expectedColors[0] = output[0];
4230 expectedColors[1] = output[1];
4231 expectedColors[2] = output[2];
4232 expectedColors[3] = output[3];
4236 tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx)
4238 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction"));
4239 vector<SpecConstantTwoIntGraphicsCase> cases;
4240 RGBA inputColors[4];
4241 RGBA outputColors0[4];
4242 RGBA outputColors1[4];
4243 RGBA outputColors2[4];
4245 const char decorations1[] =
4246 "OpDecorate %sc_0 SpecId 0\n"
4247 "OpDecorate %sc_1 SpecId 1\n";
4249 const char typesAndConstants1[] =
4250 "%sc_0 = OpSpecConstant${SC_DEF0}\n"
4251 "%sc_1 = OpSpecConstant${SC_DEF1}\n"
4252 "%sc_op = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n";
4254 const char function1[] =
4255 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4256 "%param = OpFunctionParameter %v4f32\n"
4257 "%label = OpLabel\n"
4258 "%result = OpVariable %fp_v4f32 Function\n"
4259 " OpStore %result %param\n"
4260 "%gen = ${GEN_RESULT}\n"
4261 "%index = OpIAdd %i32 %gen %c_i32_1\n"
4262 "%loc = OpAccessChain %fp_f32 %result %index\n"
4263 "%val = OpLoad %f32 %loc\n"
4264 "%add = OpFAdd %f32 %val %c_f32_0_5\n"
4265 " OpStore %loc %add\n"
4266 "%ret = OpLoad %v4f32 %result\n"
4267 " OpReturnValue %ret\n"
4270 inputColors[0] = RGBA(127, 127, 127, 255);
4271 inputColors[1] = RGBA(127, 0, 0, 255);
4272 inputColors[2] = RGBA(0, 127, 0, 255);
4273 inputColors[3] = RGBA(0, 0, 127, 255);
4275 // Derived from inputColors[x] by adding 128 to inputColors[x][0].
4276 outputColors0[0] = RGBA(255, 127, 127, 255);
4277 outputColors0[1] = RGBA(255, 0, 0, 255);
4278 outputColors0[2] = RGBA(128, 127, 0, 255);
4279 outputColors0[3] = RGBA(128, 0, 127, 255);
4281 // Derived from inputColors[x] by adding 128 to inputColors[x][1].
4282 outputColors1[0] = RGBA(127, 255, 127, 255);
4283 outputColors1[1] = RGBA(127, 128, 0, 255);
4284 outputColors1[2] = RGBA(0, 255, 0, 255);
4285 outputColors1[3] = RGBA(0, 128, 127, 255);
4287 // Derived from inputColors[x] by adding 128 to inputColors[x][2].
4288 outputColors2[0] = RGBA(127, 127, 255, 255);
4289 outputColors2[1] = RGBA(127, 0, 128, 255);
4290 outputColors2[2] = RGBA(0, 127, 128, 255);
4291 outputColors2[3] = RGBA(0, 0, 255, 255);
4293 const char addZeroToSc[] = "OpIAdd %i32 %c_i32_0 %sc_op";
4294 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_op %c_i32_1 %c_i32_0";
4295 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_op %c_i32_0 %c_i32_1";
4297 cases.push_back(SpecConstantTwoIntGraphicsCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 19, -20, addZeroToSc, outputColors0));
4298 cases.push_back(SpecConstantTwoIntGraphicsCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 19, 20, addZeroToSc, outputColors0));
4299 cases.push_back(SpecConstantTwoIntGraphicsCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -1, -1, addZeroToSc, outputColors2));
4300 cases.push_back(SpecConstantTwoIntGraphicsCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, 126, addZeroToSc, outputColors0));
4301 cases.push_back(SpecConstantTwoIntGraphicsCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 126, addZeroToSc, outputColors2));
4302 cases.push_back(SpecConstantTwoIntGraphicsCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 3, 2, addZeroToSc, outputColors2));
4303 cases.push_back(SpecConstantTwoIntGraphicsCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 3, 2, addZeroToSc, outputColors2));
4304 cases.push_back(SpecConstantTwoIntGraphicsCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 1001, 500, addZeroToSc, outputColors2));
4305 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 0x33, 0x0d, addZeroToSc, outputColors2));
4306 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 0, 1, addZeroToSc, outputColors2));
4307 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseXor %sc_0 %sc_1", 0x2e, 0x2f, addZeroToSc, outputColors2));
4308 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 2, 1, addZeroToSc, outputColors2));
4309 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", -4, 2, addZeroToSc, outputColors0));
4310 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 1, 0, addZeroToSc, outputColors2));
4311 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputColors2));
4312 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputColors2));
4313 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2));
4314 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputColors2));
4315 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputColors2));
4316 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputColors2));
4317 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2));
4318 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputColors2));
4319 cases.push_back(SpecConstantTwoIntGraphicsCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputColors2));
4320 cases.push_back(SpecConstantTwoIntGraphicsCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2));
4321 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2));
4322 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2));
4323 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2));
4324 cases.push_back(SpecConstantTwoIntGraphicsCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -1, 0, addZeroToSc, outputColors2));
4325 cases.push_back(SpecConstantTwoIntGraphicsCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -2, 0, addZeroToSc, outputColors2));
4326 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputColors2));
4327 cases.push_back(SpecConstantTwoIntGraphicsCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %c_i32_0", 1, 1, addZeroToSc, outputColors2));
4328 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths.
4329 // \todo[2015-12-1 antiagainst] OpQuantizeToF16
4331 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
4333 map<string, string> specializations;
4334 map<string, string> fragments;
4335 vector<deInt32> specConstants;
4337 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0;
4338 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1;
4339 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType;
4340 specializations["SC_OP"] = cases[caseNdx].scOperation;
4341 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation;
4343 fragments["decoration"] = tcu::StringTemplate(decorations1).specialize(specializations);
4344 fragments["pre_main"] = tcu::StringTemplate(typesAndConstants1).specialize(specializations);
4345 fragments["testfun"] = tcu::StringTemplate(function1).specialize(specializations);
4347 specConstants.push_back(cases[caseNdx].scActualValue0);
4348 specConstants.push_back(cases[caseNdx].scActualValue1);
4350 createTestsForAllStages(cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants, group.get());
4353 const char decorations2[] =
4354 "OpDecorate %sc_0 SpecId 0\n"
4355 "OpDecorate %sc_1 SpecId 1\n"
4356 "OpDecorate %sc_2 SpecId 2\n";
4358 const char typesAndConstants2[] =
4359 "%v3i32 = OpTypeVector %i32 3\n"
4361 "%sc_0 = OpSpecConstant %i32 0\n"
4362 "%sc_1 = OpSpecConstant %i32 0\n"
4363 "%sc_2 = OpSpecConstant %i32 0\n"
4365 "%vec3_0 = OpConstantComposite %v3i32 %c_i32_0 %c_i32_0 %c_i32_0\n"
4366 "%sc_vec3_0 = OpSpecConstantOp %v3i32 CompositeInsert %sc_0 %vec3_0 0\n" // (sc_0, 0, 0)
4367 "%sc_vec3_1 = OpSpecConstantOp %v3i32 CompositeInsert %sc_1 %vec3_0 1\n" // (0, sc_1, 0)
4368 "%sc_vec3_2 = OpSpecConstantOp %v3i32 CompositeInsert %sc_2 %vec3_0 2\n" // (0, 0, sc_2)
4369 "%sc_vec3_01 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1)
4370 "%sc_vec3_012 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1)
4371 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2
4372 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0
4373 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1
4374 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0)
4375 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n"; // (sc_2 - sc_0) * sc_1
4377 const char function2[] =
4378 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4379 "%param = OpFunctionParameter %v4f32\n"
4380 "%label = OpLabel\n"
4381 "%result = OpVariable %fp_v4f32 Function\n"
4382 " OpStore %result %param\n"
4383 "%loc = OpAccessChain %fp_f32 %result %sc_final\n"
4384 "%val = OpLoad %f32 %loc\n"
4385 "%add = OpFAdd %f32 %val %c_f32_0_5\n"
4386 " OpStore %loc %add\n"
4387 "%ret = OpLoad %v4f32 %result\n"
4388 " OpReturnValue %ret\n"
4391 map<string, string> fragments;
4392 vector<deInt32> specConstants;
4394 fragments["decoration"] = decorations2;
4395 fragments["pre_main"] = typesAndConstants2;
4396 fragments["testfun"] = function2;
4398 specConstants.push_back(56789);
4399 specConstants.push_back(-2);
4400 specConstants.push_back(56788);
4402 createTestsForAllStages("vector_related", inputColors, outputColors2, fragments, specConstants, group.get());
4404 return group.release();
4407 tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx)
4409 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction"));
4410 RGBA inputColors[4];
4411 RGBA outputColors1[4];
4412 RGBA outputColors2[4];
4413 RGBA outputColors3[4];
4414 map<string, string> fragments1;
4415 map<string, string> fragments2;
4416 map<string, string> fragments3;
4418 const char typesAndConstants1[] =
4419 "%c_f32_p2 = OpConstant %f32 0.2\n"
4420 "%c_f32_p4 = OpConstant %f32 0.4\n"
4421 "%c_f32_p5 = OpConstant %f32 0.5\n"
4422 "%c_f32_p8 = OpConstant %f32 0.8\n";
4424 // vec4 test_code(vec4 param) {
4425 // vec4 result = param;
4426 // for (int i = 0; i < 4; ++i) {
4429 // case 0: operand = .2; break;
4430 // case 1: operand = .5; break;
4431 // case 2: operand = .4; break;
4432 // case 3: operand = .0; break;
4433 // default: break; // unreachable
4435 // result[i] += operand;
4439 const char function1[] =
4440 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4441 "%param1 = OpFunctionParameter %v4f32\n"
4443 "%iptr = OpVariable %fp_i32 Function\n"
4444 "%result = OpVariable %fp_v4f32 Function\n"
4445 " OpStore %iptr %c_i32_0\n"
4446 " OpStore %result %param1\n"
4450 "%ival = OpLoad %i32 %iptr\n"
4451 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n"
4452 " OpLoopMerge %exit %phi None\n"
4453 " OpBranchConditional %lt_4 %entry %exit\n"
4455 "%entry = OpLabel\n"
4456 "%loc = OpAccessChain %fp_f32 %result %ival\n"
4457 "%val = OpLoad %f32 %loc\n"
4458 " OpSelectionMerge %phi None\n"
4459 " OpSwitch %ival %default 0 %case0 1 %case1 2 %case2 3 %case3\n"
4461 "%case0 = OpLabel\n"
4463 "%case1 = OpLabel\n"
4465 "%case2 = OpLabel\n"
4467 "%case3 = OpLabel\n"
4470 "%default = OpLabel\n"
4474 "%operand = OpPhi %f32 %c_f32_p4 %case2 %c_f32_p5 %case1 %c_f32_p2 %case0 %c_f32_0 %case3\n" // not in the order of blocks
4475 "%add = OpFAdd %f32 %val %operand\n"
4476 " OpStore %loc %add\n"
4477 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n"
4478 " OpStore %iptr %ival_next\n"
4482 "%ret = OpLoad %v4f32 %result\n"
4483 " OpReturnValue %ret\n"
4487 fragments1["pre_main"] = typesAndConstants1;
4488 fragments1["testfun"] = function1;
4490 getHalfColorsFullAlpha(inputColors);
4492 outputColors1[0] = RGBA(178, 255, 229, 255);
4493 outputColors1[1] = RGBA(178, 127, 102, 255);
4494 outputColors1[2] = RGBA(51, 255, 102, 255);
4495 outputColors1[3] = RGBA(51, 127, 229, 255);
4497 createTestsForAllStages("out_of_order", inputColors, outputColors1, fragments1, group.get());
4499 const char typesAndConstants2[] =
4500 "%c_f32_p2 = OpConstant %f32 0.2\n";
4502 // Add .4 to the second element of the given parameter.
4503 const char function2[] =
4504 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4505 "%param = OpFunctionParameter %v4f32\n"
4506 "%entry = OpLabel\n"
4507 "%result = OpVariable %fp_v4f32 Function\n"
4508 " OpStore %result %param\n"
4509 "%loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
4510 "%val = OpLoad %f32 %loc\n"
4514 "%step = OpPhi %i32 %c_i32_0 %entry %step_next %phi\n"
4515 "%accum = OpPhi %f32 %val %entry %accum_next %phi\n"
4516 "%step_next = OpIAdd %i32 %step %c_i32_1\n"
4517 "%accum_next = OpFAdd %f32 %accum %c_f32_p2\n"
4518 "%still_loop = OpSLessThan %bool %step %c_i32_2\n"
4519 " OpLoopMerge %exit %phi None\n"
4520 " OpBranchConditional %still_loop %phi %exit\n"
4523 " OpStore %loc %accum\n"
4524 "%ret = OpLoad %v4f32 %result\n"
4525 " OpReturnValue %ret\n"
4529 fragments2["pre_main"] = typesAndConstants2;
4530 fragments2["testfun"] = function2;
4532 outputColors2[0] = RGBA(127, 229, 127, 255);
4533 outputColors2[1] = RGBA(127, 102, 0, 255);
4534 outputColors2[2] = RGBA(0, 229, 0, 255);
4535 outputColors2[3] = RGBA(0, 102, 127, 255);
4537 createTestsForAllStages("induction", inputColors, outputColors2, fragments2, group.get());
4539 const char typesAndConstants3[] =
4540 "%true = OpConstantTrue %bool\n"
4541 "%false = OpConstantFalse %bool\n"
4542 "%c_f32_p2 = OpConstant %f32 0.2\n";
4544 // Swap the second and the third element of the given parameter.
4545 const char function3[] =
4546 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4547 "%param = OpFunctionParameter %v4f32\n"
4548 "%entry = OpLabel\n"
4549 "%result = OpVariable %fp_v4f32 Function\n"
4550 " OpStore %result %param\n"
4551 "%a_loc = OpAccessChain %fp_f32 %result %c_i32_1\n"
4552 "%a_init = OpLoad %f32 %a_loc\n"
4553 "%b_loc = OpAccessChain %fp_f32 %result %c_i32_2\n"
4554 "%b_init = OpLoad %f32 %b_loc\n"
4558 "%still_loop = OpPhi %bool %true %entry %false %phi\n"
4559 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n"
4560 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n"
4561 " OpLoopMerge %exit %phi None\n"
4562 " OpBranchConditional %still_loop %phi %exit\n"
4565 " OpStore %a_loc %a_next\n"
4566 " OpStore %b_loc %b_next\n"
4567 "%ret = OpLoad %v4f32 %result\n"
4568 " OpReturnValue %ret\n"
4572 fragments3["pre_main"] = typesAndConstants3;
4573 fragments3["testfun"] = function3;
4575 outputColors3[0] = RGBA(127, 127, 127, 255);
4576 outputColors3[1] = RGBA(127, 0, 0, 255);
4577 outputColors3[2] = RGBA(0, 0, 127, 255);
4578 outputColors3[3] = RGBA(0, 127, 0, 255);
4580 createTestsForAllStages("swap", inputColors, outputColors3, fragments3, group.get());
4582 return group.release();
4585 tcu::TestCaseGroup* createNoContractionTests(tcu::TestContext& testCtx)
4587 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration"));
4588 RGBA inputColors[4];
4589 RGBA outputColors[4];
4591 // With NoContraction, (1 + 2^-23) * (1 - 2^-23) - 1 should be conducted as a multiplication and an addition separately.
4592 // For the multiplication, the result is 1 - 2^-46, which is out of the precision range for 32-bit float. (32-bit float
4593 // only have 23-bit fraction.) So it will be rounded to 1. Or 0x1.fffffc. Then the final result is 0 or -0x1p-24.
4594 // On the contrary, the result will be 2^-46, which is a normalized number perfectly representable as 32-bit float.
4595 const char constantsAndTypes[] =
4596 "%c_vec4_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_0 %c_f32_1\n"
4597 "%c_vec4_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
4598 "%c_f32_1pl2_23 = OpConstant %f32 0x1.000002p+0\n" // 1 + 2^-23
4599 "%c_f32_1mi2_23 = OpConstant %f32 0x1.fffffcp-1\n" // 1 - 2^-23
4600 "%c_f32_n1pn24 = OpConstant %f32 -0x1p-24\n"
4603 const char function[] =
4604 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4605 "%param = OpFunctionParameter %v4f32\n"
4606 "%label = OpLabel\n"
4607 "%var1 = OpVariable %fp_f32 Function %c_f32_1pl2_23\n"
4608 "%var2 = OpVariable %fp_f32 Function\n"
4609 "%red = OpCompositeExtract %f32 %param 0\n"
4610 "%plus_red = OpFAdd %f32 %c_f32_1mi2_23 %red\n"
4611 " OpStore %var2 %plus_red\n"
4612 "%val1 = OpLoad %f32 %var1\n"
4613 "%val2 = OpLoad %f32 %var2\n"
4614 "%mul = OpFMul %f32 %val1 %val2\n"
4615 "%add = OpFAdd %f32 %mul %c_f32_n1\n"
4616 "%is0 = OpFOrdEqual %bool %add %c_f32_0\n"
4617 "%isn1n24 = OpFOrdEqual %bool %add %c_f32_n1pn24\n"
4618 "%success = OpLogicalOr %bool %is0 %isn1n24\n"
4619 "%v4success = OpCompositeConstruct %v4bool %success %success %success %success\n"
4620 "%ret = OpSelect %v4f32 %v4success %c_vec4_0 %c_vec4_1\n"
4621 " OpReturnValue %ret\n"
4624 struct CaseNameDecoration
4631 CaseNameDecoration tests[] = {
4632 {"multiplication", "OpDecorate %mul NoContraction"},
4633 {"addition", "OpDecorate %add NoContraction"},
4634 {"both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction"},
4637 getHalfColorsFullAlpha(inputColors);
4639 for (deUint8 idx = 0; idx < 4; ++idx)
4641 inputColors[idx].setRed(0);
4642 outputColors[idx] = RGBA(0, 0, 0, 255);
4645 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(CaseNameDecoration); ++testNdx)
4647 map<string, string> fragments;
4649 fragments["decoration"] = tests[testNdx].decoration;
4650 fragments["pre_main"] = constantsAndTypes;
4651 fragments["testfun"] = function;
4653 createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, group.get());
4656 return group.release();
4659 tcu::TestCaseGroup* createMemoryAccessTests(tcu::TestContext& testCtx)
4661 de::MovePtr<tcu::TestCaseGroup> memoryAccessTests (new tcu::TestCaseGroup(testCtx, "opmemoryaccess", "Memory Semantics"));
4664 const char constantsAndTypes[] =
4665 "%c_a2f32_1 = OpConstantComposite %a2f32 %c_f32_1 %c_f32_1\n"
4666 "%fp_a2f32 = OpTypePointer Function %a2f32\n"
4667 "%stype = OpTypeStruct %v4f32 %a2f32 %f32\n"
4668 "%fp_stype = OpTypePointer Function %stype\n";
4670 const char function[] =
4671 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4672 "%param1 = OpFunctionParameter %v4f32\n"
4674 "%v1 = OpVariable %fp_v4f32 Function\n"
4675 "%v2 = OpVariable %fp_a2f32 Function\n"
4676 "%v3 = OpVariable %fp_f32 Function\n"
4677 "%v = OpVariable %fp_stype Function\n"
4678 "%vv = OpVariable %fp_stype Function\n"
4679 "%vvv = OpVariable %fp_f32 Function\n"
4681 " OpStore %v1 %c_v4f32_1_1_1_1\n"
4682 " OpStore %v2 %c_a2f32_1\n"
4683 " OpStore %v3 %c_f32_1\n"
4685 "%p_v4f32 = OpAccessChain %fp_v4f32 %v %c_u32_0\n"
4686 "%p_a2f32 = OpAccessChain %fp_a2f32 %v %c_u32_1\n"
4687 "%p_f32 = OpAccessChain %fp_f32 %v %c_u32_2\n"
4688 "%v1_v = OpLoad %v4f32 %v1 ${access_type}\n"
4689 "%v2_v = OpLoad %a2f32 %v2 ${access_type}\n"
4690 "%v3_v = OpLoad %f32 %v3 ${access_type}\n"
4692 " OpStore %p_v4f32 %v1_v ${access_type}\n"
4693 " OpStore %p_a2f32 %v2_v ${access_type}\n"
4694 " OpStore %p_f32 %v3_v ${access_type}\n"
4696 " OpCopyMemory %vv %v ${access_type}\n"
4697 " OpCopyMemory %vvv %p_f32 ${access_type}\n"
4699 "%p_f32_2 = OpAccessChain %fp_f32 %vv %c_u32_2\n"
4700 "%v_f32_2 = OpLoad %f32 %p_f32_2\n"
4701 "%v_f32_3 = OpLoad %f32 %vvv\n"
4703 "%ret1 = OpVectorTimesScalar %v4f32 %param1 %v_f32_2\n"
4704 "%ret2 = OpVectorTimesScalar %v4f32 %ret1 %v_f32_3\n"
4705 " OpReturnValue %ret2\n"
4708 struct NameMemoryAccess
4715 NameMemoryAccess tests[] =
4718 { "volatile", "Volatile" },
4719 { "aligned", "Aligned 1" },
4720 { "volatile_aligned", "Volatile|Aligned 1" },
4721 { "nontemporal_aligned", "Nontemporal|Aligned 1" },
4722 { "volatile_nontemporal", "Volatile|Nontemporal" },
4723 { "volatile_nontermporal_aligned", "Volatile|Nontemporal|Aligned 1" },
4726 getHalfColorsFullAlpha(colors);
4728 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameMemoryAccess); ++testNdx)
4730 map<string, string> fragments;
4731 map<string, string> memoryAccess;
4732 memoryAccess["access_type"] = tests[testNdx].accessType;
4734 fragments["pre_main"] = constantsAndTypes;
4735 fragments["testfun"] = tcu::StringTemplate(function).specialize(memoryAccess);
4736 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, memoryAccessTests.get());
4738 return memoryAccessTests.release();
4740 tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
4742 de::MovePtr<tcu::TestCaseGroup> opUndefTests (new tcu::TestCaseGroup(testCtx, "opundef", "Test OpUndef"));
4743 RGBA defaultColors[4];
4744 map<string, string> fragments;
4745 getDefaultColors(defaultColors);
4747 // First, simple cases that don't do anything with the OpUndef result.
4748 struct NameCodePair { string name, decl, type; };
4749 const NameCodePair tests[] =
4751 {"bool", "", "%bool"},
4752 {"vec2uint32", "%type = OpTypeVector %u32 2", "%type"},
4753 {"image", "%type = OpTypeImage %f32 2D 0 0 0 1 Unknown", "%type"},
4754 {"sampler", "%type = OpTypeSampler", "%type"},
4755 {"sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 1 Unknown\n" "%type = OpTypeSampledImage %img", "%type"},
4756 {"pointer", "", "%fp_i32"},
4757 {"runtimearray", "%type = OpTypeRuntimeArray %f32", "%type"},
4758 {"array", "%c_u32_100 = OpConstant %u32 100\n" "%type = OpTypeArray %i32 %c_u32_100", "%type"},
4759 {"struct", "%type = OpTypeStruct %f32 %i32 %u32", "%type"}};
4760 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx)
4762 fragments["undef_type"] = tests[testNdx].type;
4763 fragments["testfun"] = StringTemplate(
4764 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4765 "%param1 = OpFunctionParameter %v4f32\n"
4766 "%label_testfun = OpLabel\n"
4767 "%undef = OpUndef ${undef_type}\n"
4768 "OpReturnValue %param1\n"
4769 "OpFunctionEnd\n").specialize(fragments);
4770 fragments["pre_main"] = tests[testNdx].decl;
4771 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opUndefTests.get());
4775 fragments["testfun"] =
4776 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4777 "%param1 = OpFunctionParameter %v4f32\n"
4778 "%label_testfun = OpLabel\n"
4779 "%undef = OpUndef %f32\n"
4780 "%zero = OpFMul %f32 %undef %c_f32_0\n"
4781 "%is_nan = OpIsNan %bool %zero\n" //OpUndef may result in NaN which may turn %zero into Nan.
4782 "%actually_zero = OpSelect %f32 %is_nan %c_f32_0 %zero\n"
4783 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
4784 "%b = OpFAdd %f32 %a %actually_zero\n"
4785 "%ret = OpVectorInsertDynamic %v4f32 %param1 %b %c_i32_0\n"
4786 "OpReturnValue %ret\n"
4789 createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get());
4791 fragments["testfun"] =
4792 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4793 "%param1 = OpFunctionParameter %v4f32\n"
4794 "%label_testfun = OpLabel\n"
4795 "%undef = OpUndef %i32\n"
4796 "%zero = OpIMul %i32 %undef %c_i32_0\n"
4797 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
4798 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
4799 "OpReturnValue %ret\n"
4802 createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get());
4804 fragments["testfun"] =
4805 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4806 "%param1 = OpFunctionParameter %v4f32\n"
4807 "%label_testfun = OpLabel\n"
4808 "%undef = OpUndef %u32\n"
4809 "%zero = OpIMul %u32 %undef %c_i32_0\n"
4810 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
4811 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
4812 "OpReturnValue %ret\n"
4815 createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get());
4817 fragments["testfun"] =
4818 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4819 "%param1 = OpFunctionParameter %v4f32\n"
4820 "%label_testfun = OpLabel\n"
4821 "%undef = OpUndef %v4f32\n"
4822 "%vzero = OpVectorTimesScalar %v4f32 %undef %c_f32_0\n"
4823 "%zero_0 = OpVectorExtractDynamic %f32 %vzero %c_i32_0\n"
4824 "%zero_1 = OpVectorExtractDynamic %f32 %vzero %c_i32_1\n"
4825 "%zero_2 = OpVectorExtractDynamic %f32 %vzero %c_i32_2\n"
4826 "%zero_3 = OpVectorExtractDynamic %f32 %vzero %c_i32_3\n"
4827 "%is_nan_0 = OpIsNan %bool %zero_0\n"
4828 "%is_nan_1 = OpIsNan %bool %zero_1\n"
4829 "%is_nan_2 = OpIsNan %bool %zero_2\n"
4830 "%is_nan_3 = OpIsNan %bool %zero_3\n"
4831 "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n"
4832 "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n"
4833 "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n"
4834 "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n"
4835 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
4836 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
4837 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
4838 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
4839 "%sum_0 = OpFAdd %f32 %param1_0 %actually_zero_0\n"
4840 "%sum_1 = OpFAdd %f32 %param1_1 %actually_zero_1\n"
4841 "%sum_2 = OpFAdd %f32 %param1_2 %actually_zero_2\n"
4842 "%sum_3 = OpFAdd %f32 %param1_3 %actually_zero_3\n"
4843 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
4844 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
4845 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
4846 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
4847 "OpReturnValue %ret\n"
4850 createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get());
4852 fragments["pre_main"] =
4853 "%m2x2f32 = OpTypeMatrix %v2f32 2\n";
4854 fragments["testfun"] =
4855 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
4856 "%param1 = OpFunctionParameter %v4f32\n"
4857 "%label_testfun = OpLabel\n"
4858 "%undef = OpUndef %m2x2f32\n"
4859 "%mzero = OpMatrixTimesScalar %m2x2f32 %undef %c_f32_0\n"
4860 "%zero_0 = OpCompositeExtract %f32 %mzero 0 0\n"
4861 "%zero_1 = OpCompositeExtract %f32 %mzero 0 1\n"
4862 "%zero_2 = OpCompositeExtract %f32 %mzero 1 0\n"
4863 "%zero_3 = OpCompositeExtract %f32 %mzero 1 1\n"
4864 "%is_nan_0 = OpIsNan %bool %zero_0\n"
4865 "%is_nan_1 = OpIsNan %bool %zero_1\n"
4866 "%is_nan_2 = OpIsNan %bool %zero_2\n"
4867 "%is_nan_3 = OpIsNan %bool %zero_3\n"
4868 "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n"
4869 "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n"
4870 "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n"
4871 "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n"
4872 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
4873 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n"
4874 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n"
4875 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n"
4876 "%sum_0 = OpFAdd %f32 %param1_0 %actually_zero_0\n"
4877 "%sum_1 = OpFAdd %f32 %param1_1 %actually_zero_1\n"
4878 "%sum_2 = OpFAdd %f32 %param1_2 %actually_zero_2\n"
4879 "%sum_3 = OpFAdd %f32 %param1_3 %actually_zero_3\n"
4880 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n"
4881 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n"
4882 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
4883 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
4884 "OpReturnValue %ret\n"
4887 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, opUndefTests.get());
4889 return opUndefTests.release();
4892 void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx)
4894 const RGBA inputColors[4] =
4897 RGBA(0, 0, 255, 255),
4898 RGBA(0, 255, 0, 255),
4899 RGBA(0, 255, 255, 255)
4902 const RGBA expectedColors[4] =
4904 RGBA(255, 0, 0, 255),
4905 RGBA(255, 0, 0, 255),
4906 RGBA(255, 0, 0, 255),
4907 RGBA(255, 0, 0, 255)
4910 const struct SingleFP16Possibility
4913 const char* constant; // Value to assign to %test_constant.
4915 const char* condition; // Must assign to %cond an expression that evaluates to true after %c = OpQuantizeToF16(%test_constant + 0).
4921 -constructNormalizedFloat(1, 0x300000),
4922 "%cond = OpFOrdEqual %bool %c %test_constant\n"
4927 constructNormalizedFloat(7, 0x000000),
4928 "%cond = OpFOrdEqual %bool %c %test_constant\n"
4930 // SPIR-V requires that OpQuantizeToF16 flushes
4931 // any numbers that would end up denormalized in F16 to zero.
4935 std::ldexp(1.5f, -140),
4936 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
4941 -std::ldexp(1.5f, -140),
4942 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
4947 std::ldexp(1.0f, -16),
4948 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
4949 }, // too small positive
4951 "negative_too_small",
4953 -std::ldexp(1.0f, -32),
4954 "%cond = OpFOrdEqual %bool %c %c_f32_0\n"
4955 }, // too small negative
4959 -std::ldexp(1.0f, 128),
4961 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n"
4962 "%inf = OpIsInf %bool %c\n"
4963 "%cond = OpLogicalAnd %bool %gz %inf\n"
4968 std::ldexp(1.0f, 128),
4970 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n"
4971 "%inf = OpIsInf %bool %c\n"
4972 "%cond = OpLogicalAnd %bool %gz %inf\n"
4975 "round_to_negative_inf",
4977 -std::ldexp(1.0f, 32),
4979 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n"
4980 "%inf = OpIsInf %bool %c\n"
4981 "%cond = OpLogicalAnd %bool %gz %inf\n"
4986 std::ldexp(1.0f, 16),
4988 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n"
4989 "%inf = OpIsInf %bool %c\n"
4990 "%cond = OpLogicalAnd %bool %gz %inf\n"
4995 std::numeric_limits<float>::quiet_NaN(),
4997 // Test for any NaN value, as NaNs are not preserved
4998 "%direct_quant = OpQuantizeToF16 %f32 %test_constant\n"
4999 "%cond = OpIsNan %bool %direct_quant\n"
5004 std::numeric_limits<float>::quiet_NaN(),
5006 // Test for any NaN value, as NaNs are not preserved
5007 "%direct_quant = OpQuantizeToF16 %f32 %test_constant\n"
5008 "%cond = OpIsNan %bool %direct_quant\n"
5011 const char* constants =
5012 "%test_constant = OpConstant %f32 "; // The value will be test.constant.
5014 StringTemplate function (
5015 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5016 "%param1 = OpFunctionParameter %v4f32\n"
5017 "%label_testfun = OpLabel\n"
5018 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5019 "%b = OpFAdd %f32 %test_constant %a\n"
5020 "%c = OpQuantizeToF16 %f32 %b\n"
5022 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n"
5023 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1\n"
5024 " OpReturnValue %retval\n"
5028 const char* specDecorations = "OpDecorate %test_constant SpecId 0\n";
5029 const char* specConstants =
5030 "%test_constant = OpSpecConstant %f32 0.\n"
5031 "%c = OpSpecConstantOp %f32 QuantizeToF16 %test_constant\n";
5033 StringTemplate specConstantFunction(
5034 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5035 "%param1 = OpFunctionParameter %v4f32\n"
5036 "%label_testfun = OpLabel\n"
5038 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n"
5039 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1\n"
5040 " OpReturnValue %retval\n"
5044 for (size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx)
5046 map<string, string> codeSpecialization;
5047 map<string, string> fragments;
5048 codeSpecialization["condition"] = tests[idx].condition;
5049 fragments["testfun"] = function.specialize(codeSpecialization);
5050 fragments["pre_main"] = string(constants) + tests[idx].constant + "\n";
5051 createTestsForAllStages(tests[idx].name, inputColors, expectedColors, fragments, testCtx);
5054 for (size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx)
5056 map<string, string> codeSpecialization;
5057 map<string, string> fragments;
5058 vector<deInt32> passConstants;
5059 deInt32 specConstant;
5061 codeSpecialization["condition"] = tests[idx].condition;
5062 fragments["testfun"] = specConstantFunction.specialize(codeSpecialization);
5063 fragments["decoration"] = specDecorations;
5064 fragments["pre_main"] = specConstants;
5066 memcpy(&specConstant, &tests[idx].valueAsFloat, sizeof(float));
5067 passConstants.push_back(specConstant);
5069 createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx);
5073 void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx)
5075 RGBA inputColors[4] = {
5077 RGBA(0, 0, 255, 255),
5078 RGBA(0, 255, 0, 255),
5079 RGBA(0, 255, 255, 255)
5082 RGBA expectedColors[4] =
5084 RGBA(255, 0, 0, 255),
5085 RGBA(255, 0, 0, 255),
5086 RGBA(255, 0, 0, 255),
5087 RGBA(255, 0, 0, 255)
5090 struct DualFP16Possibility
5095 const char* possibleOutput1;
5096 const char* possibleOutput2;
5099 "positive_round_up_or_round_down",
5101 constructNormalizedFloat(8, 0x300300),
5106 "negative_round_up_or_round_down",
5108 -constructNormalizedFloat(-7, 0x600800),
5115 constructNormalizedFloat(2, 0x01e000),
5120 "carry_to_exponent",
5122 constructNormalizedFloat(1, 0xffe000),
5127 StringTemplate constants (
5128 "%input_const = OpConstant %f32 ${input}\n"
5129 "%possible_solution1 = OpConstant %f32 ${output1}\n"
5130 "%possible_solution2 = OpConstant %f32 ${output2}\n"
5133 StringTemplate specConstants (
5134 "%input_const = OpSpecConstant %f32 0.\n"
5135 "%possible_solution1 = OpConstant %f32 ${output1}\n"
5136 "%possible_solution2 = OpConstant %f32 ${output2}\n"
5139 const char* specDecorations = "OpDecorate %input_const SpecId 0\n";
5141 const char* function =
5142 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5143 "%param1 = OpFunctionParameter %v4f32\n"
5144 "%label_testfun = OpLabel\n"
5145 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5146 // For the purposes of this test we assume that 0.f will always get
5147 // faithfully passed through the pipeline stages.
5148 "%b = OpFAdd %f32 %input_const %a\n"
5149 "%c = OpQuantizeToF16 %f32 %b\n"
5150 "%eq_1 = OpFOrdEqual %bool %c %possible_solution1\n"
5151 "%eq_2 = OpFOrdEqual %bool %c %possible_solution2\n"
5152 "%cond = OpLogicalOr %bool %eq_1 %eq_2\n"
5153 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n"
5154 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1"
5155 " OpReturnValue %retval\n"
5158 for(size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) {
5159 map<string, string> fragments;
5160 map<string, string> constantSpecialization;
5162 constantSpecialization["input"] = tests[idx].input;
5163 constantSpecialization["output1"] = tests[idx].possibleOutput1;
5164 constantSpecialization["output2"] = tests[idx].possibleOutput2;
5165 fragments["testfun"] = function;
5166 fragments["pre_main"] = constants.specialize(constantSpecialization);
5167 createTestsForAllStages(tests[idx].name, inputColors, expectedColors, fragments, testCtx);
5170 for(size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) {
5171 map<string, string> fragments;
5172 map<string, string> constantSpecialization;
5173 vector<deInt32> passConstants;
5174 deInt32 specConstant;
5176 constantSpecialization["output1"] = tests[idx].possibleOutput1;
5177 constantSpecialization["output2"] = tests[idx].possibleOutput2;
5178 fragments["testfun"] = function;
5179 fragments["decoration"] = specDecorations;
5180 fragments["pre_main"] = specConstants.specialize(constantSpecialization);
5182 memcpy(&specConstant, &tests[idx].inputAsFloat, sizeof(float));
5183 passConstants.push_back(specConstant);
5185 createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx);
5189 tcu::TestCaseGroup* createOpQuantizeTests(tcu::TestContext& testCtx)
5191 de::MovePtr<tcu::TestCaseGroup> opQuantizeTests (new tcu::TestCaseGroup(testCtx, "opquantize", "Test OpQuantizeToF16"));
5192 createOpQuantizeSingleOptionTests(opQuantizeTests.get());
5193 createOpQuantizeTwoPossibilityTests(opQuantizeTests.get());
5194 return opQuantizeTests.release();
5197 struct ShaderPermutation
5199 deUint8 vertexPermutation;
5200 deUint8 geometryPermutation;
5201 deUint8 tesscPermutation;
5202 deUint8 tessePermutation;
5203 deUint8 fragmentPermutation;
5206 ShaderPermutation getShaderPermutation(deUint8 inputValue)
5208 ShaderPermutation permutation =
5210 static_cast<deUint8>(inputValue & 0x10? 1u: 0u),
5211 static_cast<deUint8>(inputValue & 0x08? 1u: 0u),
5212 static_cast<deUint8>(inputValue & 0x04? 1u: 0u),
5213 static_cast<deUint8>(inputValue & 0x02? 1u: 0u),
5214 static_cast<deUint8>(inputValue & 0x01? 1u: 0u)
5219 tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx)
5221 RGBA defaultColors[4];
5222 RGBA invertedColors[4];
5223 de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders"));
5225 const ShaderElement combinedPipeline[] =
5227 ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT),
5228 ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
5229 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
5230 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
5231 ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT)
5234 getDefaultColors(defaultColors);
5235 getInvertedDefaultColors(invertedColors);
5236 addFunctionCaseWithPrograms<InstanceContext>(
5237 moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline,
5238 createInstanceContext(combinedPipeline, map<string, string>()));
5240 const char* numbers[] =
5245 for (deInt8 idx = 0; idx < 32; ++idx)
5247 ShaderPermutation permutation = getShaderPermutation(idx);
5248 string name = string("vert") + numbers[permutation.vertexPermutation] + "_geom" + numbers[permutation.geometryPermutation] + "_tessc" + numbers[permutation.tesscPermutation] + "_tesse" + numbers[permutation.tessePermutation] + "_frag" + numbers[permutation.fragmentPermutation];
5249 const ShaderElement pipeline[] =
5251 ShaderElement("vert", string("vert") + numbers[permutation.vertexPermutation], VK_SHADER_STAGE_VERTEX_BIT),
5252 ShaderElement("geom", string("geom") + numbers[permutation.geometryPermutation], VK_SHADER_STAGE_GEOMETRY_BIT),
5253 ShaderElement("tessc", string("tessc") + numbers[permutation.tesscPermutation], VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
5254 ShaderElement("tesse", string("tesse") + numbers[permutation.tessePermutation], VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
5255 ShaderElement("frag", string("frag") + numbers[permutation.fragmentPermutation], VK_SHADER_STAGE_FRAGMENT_BIT)
5258 // If there are an even number of swaps, then it should be no-op.
5259 // If there are an odd number, the color should be flipped.
5260 if ((permutation.vertexPermutation + permutation.geometryPermutation + permutation.tesscPermutation + permutation.tessePermutation + permutation.fragmentPermutation) % 2 == 0)
5262 addFunctionCaseWithPrograms<InstanceContext>(
5263 moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline,
5264 createInstanceContext(pipeline, defaultColors, defaultColors, map<string, string>()));
5268 addFunctionCaseWithPrograms<InstanceContext>(
5269 moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline,
5270 createInstanceContext(pipeline, defaultColors, invertedColors, map<string, string>()));
5273 return moduleTests.release();
5276 tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
5278 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "loop", "Looping control flow"));
5279 RGBA defaultColors[4];
5280 getDefaultColors(defaultColors);
5281 map<string, string> fragments;
5282 fragments["pre_main"] =
5283 "%c_f32_5 = OpConstant %f32 5.\n";
5285 // A loop with a single block. The Continue Target is the loop block
5286 // itself. In SPIR-V terms, the "loop construct" contains no blocks at all
5287 // -- the "continue construct" forms the entire loop.
5288 fragments["testfun"] =
5289 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5290 "%param1 = OpFunctionParameter %v4f32\n"
5292 "%entry = OpLabel\n"
5293 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5296 ";adds and subtracts 1.0 to %val in alternate iterations\n"
5298 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %loop\n"
5299 "%delta = OpPhi %f32 %c_f32_1 %entry %minus_delta %loop\n"
5300 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n"
5301 "%val = OpFAdd %f32 %val1 %delta\n"
5302 "%minus_delta = OpFSub %f32 %c_f32_0 %delta\n"
5303 "%count__ = OpISub %i32 %count %c_i32_1\n"
5304 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5305 "OpLoopMerge %exit %loop None\n"
5306 "OpBranchConditional %again %loop %exit\n"
5309 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n"
5310 "OpReturnValue %result\n"
5314 createTestsForAllStages("single_block", defaultColors, defaultColors, fragments, testGroup.get());
5316 // Body comprised of multiple basic blocks.
5317 const StringTemplate multiBlock(
5318 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5319 "%param1 = OpFunctionParameter %v4f32\n"
5321 "%entry = OpLabel\n"
5322 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5325 ";adds and subtracts 1.0 to %val in alternate iterations\n"
5327 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %gather\n"
5328 "%delta = OpPhi %f32 %c_f32_1 %entry %delta_next %gather\n"
5329 "%val1 = OpPhi %f32 %val0 %entry %val %gather\n"
5330 // There are several possibilities for the Continue Target below. Each
5331 // will be specialized into a separate test case.
5332 "OpLoopMerge %exit ${continue_target} None\n"
5336 ";delta_next = (delta > 0) ? -1 : 1;\n"
5337 "%gt0 = OpFOrdGreaterThan %bool %delta %c_f32_0\n"
5338 "OpSelectionMerge %gather DontFlatten\n"
5339 "OpBranchConditional %gt0 %even %odd ;tells us if %count is even or odd\n"
5342 "OpBranch %gather\n"
5345 "OpBranch %gather\n"
5347 "%gather = OpLabel\n"
5348 "%delta_next = OpPhi %f32 %c_f32_n1 %even %c_f32_1 %odd\n"
5349 "%val = OpFAdd %f32 %val1 %delta\n"
5350 "%count__ = OpISub %i32 %count %c_i32_1\n"
5351 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5352 "OpBranchConditional %again %loop %exit\n"
5355 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n"
5356 "OpReturnValue %result\n"
5360 map<string, string> continue_target;
5362 // The Continue Target is the loop block itself.
5363 continue_target["continue_target"] = "%loop";
5364 fragments["testfun"] = multiBlock.specialize(continue_target);
5365 createTestsForAllStages("multi_block_continue_construct", defaultColors, defaultColors, fragments, testGroup.get());
5367 // The Continue Target is at the end of the loop.
5368 continue_target["continue_target"] = "%gather";
5369 fragments["testfun"] = multiBlock.specialize(continue_target);
5370 createTestsForAllStages("multi_block_loop_construct", defaultColors, defaultColors, fragments, testGroup.get());
5372 // A loop with continue statement.
5373 fragments["testfun"] =
5374 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5375 "%param1 = OpFunctionParameter %v4f32\n"
5377 "%entry = OpLabel\n"
5378 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5381 ";adds 4, 3, and 1 to %val0 (skips 2)\n"
5383 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n"
5384 "%val1 = OpPhi %f32 %val0 %entry %val %continue\n"
5385 "OpLoopMerge %exit %continue None\n"
5389 ";skip if %count==2\n"
5390 "%eq2 = OpIEqual %bool %count %c_i32_2\n"
5391 "OpSelectionMerge %continue DontFlatten\n"
5392 "OpBranchConditional %eq2 %continue %body\n"
5395 "%fcount = OpConvertSToF %f32 %count\n"
5396 "%val2 = OpFAdd %f32 %val1 %fcount\n"
5397 "OpBranch %continue\n"
5399 "%continue = OpLabel\n"
5400 "%val = OpPhi %f32 %val2 %body %val1 %if\n"
5401 "%count__ = OpISub %i32 %count %c_i32_1\n"
5402 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5403 "OpBranchConditional %again %loop %exit\n"
5406 "%same = OpFSub %f32 %val %c_f32_8\n"
5407 "%result = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n"
5408 "OpReturnValue %result\n"
5410 createTestsForAllStages("continue", defaultColors, defaultColors, fragments, testGroup.get());
5412 // A loop with break.
5413 fragments["testfun"] =
5414 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5415 "%param1 = OpFunctionParameter %v4f32\n"
5417 "%entry = OpLabel\n"
5418 ";param1 components are between 0 and 1, so dot product is 4 or less\n"
5419 "%dot = OpDot %f32 %param1 %param1\n"
5420 "%div = OpFDiv %f32 %dot %c_f32_5\n"
5421 "%zero = OpConvertFToU %u32 %div\n"
5422 "%two = OpIAdd %i32 %zero %c_i32_2\n"
5423 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5426 ";adds 4 and 3 to %val0 (exits early)\n"
5428 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n"
5429 "%val1 = OpPhi %f32 %val0 %entry %val2 %continue\n"
5430 "OpLoopMerge %exit %continue None\n"
5434 ";end loop if %count==%two\n"
5435 "%above2 = OpSGreaterThan %bool %count %two\n"
5436 "OpSelectionMerge %continue DontFlatten\n"
5437 "OpBranchConditional %above2 %body %exit\n"
5440 "%fcount = OpConvertSToF %f32 %count\n"
5441 "%val2 = OpFAdd %f32 %val1 %fcount\n"
5442 "OpBranch %continue\n"
5444 "%continue = OpLabel\n"
5445 "%count__ = OpISub %i32 %count %c_i32_1\n"
5446 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5447 "OpBranchConditional %again %loop %exit\n"
5450 "%val_post = OpPhi %f32 %val2 %continue %val1 %if\n"
5451 "%same = OpFSub %f32 %val_post %c_f32_7\n"
5452 "%result = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n"
5453 "OpReturnValue %result\n"
5455 createTestsForAllStages("break", defaultColors, defaultColors, fragments, testGroup.get());
5457 // A loop with return.
5458 fragments["testfun"] =
5459 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5460 "%param1 = OpFunctionParameter %v4f32\n"
5462 "%entry = OpLabel\n"
5463 ";param1 components are between 0 and 1, so dot product is 4 or less\n"
5464 "%dot = OpDot %f32 %param1 %param1\n"
5465 "%div = OpFDiv %f32 %dot %c_f32_5\n"
5466 "%zero = OpConvertFToU %u32 %div\n"
5467 "%two = OpIAdd %i32 %zero %c_i32_2\n"
5468 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5471 ";returns early without modifying %param1\n"
5473 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n"
5474 "%val1 = OpPhi %f32 %val0 %entry %val2 %continue\n"
5475 "OpLoopMerge %exit %continue None\n"
5479 ";return if %count==%two\n"
5480 "%above2 = OpSGreaterThan %bool %count %two\n"
5481 "OpSelectionMerge %continue DontFlatten\n"
5482 "OpBranchConditional %above2 %body %early_exit\n"
5484 "%early_exit = OpLabel\n"
5485 "OpReturnValue %param1\n"
5488 "%fcount = OpConvertSToF %f32 %count\n"
5489 "%val2 = OpFAdd %f32 %val1 %fcount\n"
5490 "OpBranch %continue\n"
5492 "%continue = OpLabel\n"
5493 "%count__ = OpISub %i32 %count %c_i32_1\n"
5494 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5495 "OpBranchConditional %again %loop %exit\n"
5498 ";should never get here, so return an incorrect result\n"
5499 "%result = OpVectorInsertDynamic %v4f32 %param1 %val2 %c_i32_0\n"
5500 "OpReturnValue %result\n"
5502 createTestsForAllStages("return", defaultColors, defaultColors, fragments, testGroup.get());
5504 return testGroup.release();
5507 // A collection of tests putting OpControlBarrier in places GLSL forbids but SPIR-V allows.
5508 tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx)
5510 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "barrier", "OpControlBarrier"));
5511 map<string, string> fragments;
5513 // A barrier inside a function body.
5514 fragments["pre_main"] =
5515 "%Workgroup = OpConstant %i32 2\n"
5516 "%SequentiallyConsistent = OpConstant %i32 0x10\n";
5517 fragments["testfun"] =
5518 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5519 "%param1 = OpFunctionParameter %v4f32\n"
5520 "%label_testfun = OpLabel\n"
5521 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5522 "OpReturnValue %param1\n"
5524 addTessCtrlTest(testGroup.get(), "in_function", fragments);
5526 // Common setup code for the following tests.
5527 fragments["pre_main"] =
5528 "%Workgroup = OpConstant %i32 2\n"
5529 "%SequentiallyConsistent = OpConstant %i32 0x10\n"
5530 "%c_f32_5 = OpConstant %f32 5.\n";
5531 const string setupPercentZero = // Begins %test_code function with code that sets %zero to 0u but cannot be optimized away.
5532 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5533 "%param1 = OpFunctionParameter %v4f32\n"
5534 "%entry = OpLabel\n"
5535 ";param1 components are between 0 and 1, so dot product is 4 or less\n"
5536 "%dot = OpDot %f32 %param1 %param1\n"
5537 "%div = OpFDiv %f32 %dot %c_f32_5\n"
5538 "%zero = OpConvertFToU %u32 %div\n";
5540 // Barriers inside OpSwitch branches.
5541 fragments["testfun"] =
5543 "OpSelectionMerge %switch_exit None\n"
5544 "OpSwitch %zero %switch_default 0 %case0 1 %case1 ;should always go to %case0\n"
5546 "%case1 = OpLabel\n"
5547 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
5548 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5549 "%wrong_branch_alert1 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
5550 "OpBranch %switch_exit\n"
5552 "%switch_default = OpLabel\n"
5553 "%wrong_branch_alert2 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
5554 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
5555 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5556 "OpBranch %switch_exit\n"
5558 "%case0 = OpLabel\n"
5559 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5560 "OpBranch %switch_exit\n"
5562 "%switch_exit = OpLabel\n"
5563 "%ret = OpPhi %v4f32 %param1 %case0 %wrong_branch_alert1 %case1 %wrong_branch_alert2 %switch_default\n"
5564 "OpReturnValue %ret\n"
5566 addTessCtrlTest(testGroup.get(), "in_switch", fragments);
5568 // Barriers inside if-then-else.
5569 fragments["testfun"] =
5571 "%eq0 = OpIEqual %bool %zero %c_u32_0\n"
5572 "OpSelectionMerge %exit DontFlatten\n"
5573 "OpBranchConditional %eq0 %then %else\n"
5576 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n"
5577 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5578 "%wrong_branch_alert = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n"
5582 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5586 "%ret = OpPhi %v4f32 %param1 %then %wrong_branch_alert %else\n"
5587 "OpReturnValue %ret\n"
5589 addTessCtrlTest(testGroup.get(), "in_if", fragments);
5591 // A barrier after control-flow reconvergence, tempting the compiler to attempt something like this:
5592 // http://lists.llvm.org/pipermail/llvm-dev/2009-October/026317.html.
5593 fragments["testfun"] =
5595 "%thread_id = OpLoad %i32 %BP_gl_InvocationID\n"
5596 "%thread0 = OpIEqual %bool %thread_id %c_i32_0\n"
5597 "OpSelectionMerge %exit DontFlatten\n"
5598 "OpBranchConditional %thread0 %then %else\n"
5601 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5605 "%val1 = OpVectorExtractDynamic %f32 %param1 %zero\n"
5609 "%val = OpPhi %f32 %val0 %else %val1 %then\n"
5610 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5611 "%ret = OpVectorInsertDynamic %v4f32 %param1 %val %zero\n"
5612 "OpReturnValue %ret\n"
5614 addTessCtrlTest(testGroup.get(), "after_divergent_if", fragments);
5616 // A barrier inside a loop.
5617 fragments["pre_main"] =
5618 "%Workgroup = OpConstant %i32 2\n"
5619 "%SequentiallyConsistent = OpConstant %i32 0x10\n"
5620 "%c_f32_10 = OpConstant %f32 10.\n";
5621 fragments["testfun"] =
5622 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5623 "%param1 = OpFunctionParameter %v4f32\n"
5624 "%entry = OpLabel\n"
5625 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
5628 ";adds 4, 3, 2, and 1 to %val0\n"
5630 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %loop\n"
5631 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n"
5632 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n"
5633 "%fcount = OpConvertSToF %f32 %count\n"
5634 "%val = OpFAdd %f32 %val1 %fcount\n"
5635 "%count__ = OpISub %i32 %count %c_i32_1\n"
5636 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n"
5637 "OpLoopMerge %exit %loop None\n"
5638 "OpBranchConditional %again %loop %exit\n"
5641 "%same = OpFSub %f32 %val %c_f32_10\n"
5642 "%ret = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n"
5643 "OpReturnValue %ret\n"
5645 addTessCtrlTest(testGroup.get(), "in_loop", fragments);
5647 return testGroup.release();
5650 // Test for the OpFRem instruction.
5651 tcu::TestCaseGroup* createFRemTests(tcu::TestContext& testCtx)
5653 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "frem", "OpFRem"));
5654 map<string, string> fragments;
5655 RGBA inputColors[4];
5656 RGBA outputColors[4];
5658 fragments["pre_main"] =
5659 "%c_f32_3 = OpConstant %f32 3.0\n"
5660 "%c_f32_n3 = OpConstant %f32 -3.0\n"
5661 "%c_f32_4 = OpConstant %f32 4.0\n"
5662 "%c_f32_p75 = OpConstant %f32 0.75\n"
5663 "%c_v4f32_p75_p75_p75_p75 = OpConstantComposite %v4f32 %c_f32_p75 %c_f32_p75 %c_f32_p75 %c_f32_p75 \n"
5664 "%c_v4f32_4_4_4_4 = OpConstantComposite %v4f32 %c_f32_4 %c_f32_4 %c_f32_4 %c_f32_4\n"
5665 "%c_v4f32_3_n3_3_n3 = OpConstantComposite %v4f32 %c_f32_3 %c_f32_n3 %c_f32_3 %c_f32_n3\n";
5667 // The test does the following.
5668 // vec4 result = (param1 * 8.0) - 4.0;
5669 // return (frem(result.x,3) + 0.75, frem(result.y, -3) + 0.75, 0, 1)
5670 fragments["testfun"] =
5671 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
5672 "%param1 = OpFunctionParameter %v4f32\n"
5673 "%label_testfun = OpLabel\n"
5674 "%v_times_8 = OpVectorTimesScalar %v4f32 %param1 %c_f32_8\n"
5675 "%minus_4 = OpFSub %v4f32 %v_times_8 %c_v4f32_4_4_4_4\n"
5676 "%frem = OpFRem %v4f32 %minus_4 %c_v4f32_3_n3_3_n3\n"
5677 "%added = OpFAdd %v4f32 %frem %c_v4f32_p75_p75_p75_p75\n"
5678 "%xyz_1 = OpVectorInsertDynamic %v4f32 %added %c_f32_1 %c_i32_3\n"
5679 "%xy_0_1 = OpVectorInsertDynamic %v4f32 %xyz_1 %c_f32_0 %c_i32_2\n"
5680 "OpReturnValue %xy_0_1\n"
5684 inputColors[0] = RGBA(16, 16, 0, 255);
5685 inputColors[1] = RGBA(232, 232, 0, 255);
5686 inputColors[2] = RGBA(232, 16, 0, 255);
5687 inputColors[3] = RGBA(16, 232, 0, 255);
5689 outputColors[0] = RGBA(64, 64, 0, 255);
5690 outputColors[1] = RGBA(255, 255, 0, 255);
5691 outputColors[2] = RGBA(255, 64, 0, 255);
5692 outputColors[3] = RGBA(64, 255, 0, 255);
5694 createTestsForAllStages("frem", inputColors, outputColors, fragments, testGroup.get());
5695 return testGroup.release();
5700 INTEGER_TYPE_SIGNED_16,
5701 INTEGER_TYPE_SIGNED_32,
5702 INTEGER_TYPE_SIGNED_64,
5704 INTEGER_TYPE_UNSIGNED_16,
5705 INTEGER_TYPE_UNSIGNED_32,
5706 INTEGER_TYPE_UNSIGNED_64,
5709 const string getBitWidthStr (IntegerType type)
5713 case INTEGER_TYPE_SIGNED_16:
5714 case INTEGER_TYPE_UNSIGNED_16: return "16";
5716 case INTEGER_TYPE_SIGNED_32:
5717 case INTEGER_TYPE_UNSIGNED_32: return "32";
5719 case INTEGER_TYPE_SIGNED_64:
5720 case INTEGER_TYPE_UNSIGNED_64: return "64";
5722 default: DE_ASSERT(false);
5727 const string getByteWidthStr (IntegerType type)
5731 case INTEGER_TYPE_SIGNED_16:
5732 case INTEGER_TYPE_UNSIGNED_16: return "2";
5734 case INTEGER_TYPE_SIGNED_32:
5735 case INTEGER_TYPE_UNSIGNED_32: return "4";
5737 case INTEGER_TYPE_SIGNED_64:
5738 case INTEGER_TYPE_UNSIGNED_64: return "8";
5740 default: DE_ASSERT(false);
5745 bool isSigned (IntegerType type)
5747 return (type <= INTEGER_TYPE_SIGNED_64);
5750 const string getTypeName (IntegerType type)
5752 string prefix = isSigned(type) ? "" : "u";
5753 return prefix + "int" + getBitWidthStr(type);
5756 const string getTestName (IntegerType from, IntegerType to)
5758 return getTypeName(from) + "_to_" + getTypeName(to);
5761 const string getAsmTypeDeclaration (IntegerType type)
5763 string sign = isSigned(type) ? " 1" : " 0";
5764 return "OpTypeInt " + getBitWidthStr(type) + sign;
5767 template<typename T>
5768 BufferSp getSpecializedBuffer (deInt64 number)
5770 return BufferSp(new Buffer<T>(vector<T>(1, (T)number)));
5773 BufferSp getBuffer (IntegerType type, deInt64 number)
5777 case INTEGER_TYPE_SIGNED_16: return getSpecializedBuffer<deInt16>(number);
5778 case INTEGER_TYPE_SIGNED_32: return getSpecializedBuffer<deInt32>(number);
5779 case INTEGER_TYPE_SIGNED_64: return getSpecializedBuffer<deInt64>(number);
5781 case INTEGER_TYPE_UNSIGNED_16: return getSpecializedBuffer<deUint16>(number);
5782 case INTEGER_TYPE_UNSIGNED_32: return getSpecializedBuffer<deUint32>(number);
5783 case INTEGER_TYPE_UNSIGNED_64: return getSpecializedBuffer<deUint64>(number);
5785 default: DE_ASSERT(false);
5786 return BufferSp(new Buffer<deInt32>(vector<deInt32>(1, 0)));
5790 bool usesInt16 (IntegerType from, IntegerType to)
5792 return (from == INTEGER_TYPE_SIGNED_16 || from == INTEGER_TYPE_UNSIGNED_16
5793 || to == INTEGER_TYPE_SIGNED_16 || to == INTEGER_TYPE_UNSIGNED_16);
5796 bool usesInt64 (IntegerType from, IntegerType to)
5798 return (from == INTEGER_TYPE_SIGNED_64 || from == INTEGER_TYPE_UNSIGNED_64
5799 || to == INTEGER_TYPE_SIGNED_64 || to == INTEGER_TYPE_UNSIGNED_64);
5802 ComputeTestFeatures getConversionUsedFeatures (IntegerType from, IntegerType to)
5804 if (usesInt16(from, to))
5806 if (usesInt64(from, to))
5808 return COMPUTE_TEST_USES_INT16_INT64;
5812 return COMPUTE_TEST_USES_INT16;
5817 return COMPUTE_TEST_USES_INT64;
5823 ConvertCase (IntegerType from, IntegerType to, deInt64 number)
5826 , m_features (getConversionUsedFeatures(from, to))
5827 , m_name (getTestName(from, to))
5828 , m_inputBuffer (getBuffer(from, number))
5829 , m_outputBuffer (getBuffer(to, number))
5831 m_asmTypes["inputType"] = getAsmTypeDeclaration(from);
5832 m_asmTypes["outputType"] = getAsmTypeDeclaration(to);
5834 if (m_features == COMPUTE_TEST_USES_INT16)
5836 m_asmTypes["int_capabilities"] = "OpCapability Int16\n";
5838 else if (m_features == COMPUTE_TEST_USES_INT64)
5840 m_asmTypes["int_capabilities"] = "OpCapability Int64\n";
5842 else if (m_features == COMPUTE_TEST_USES_INT16_INT64)
5844 m_asmTypes["int_capabilities"] = string("OpCapability Int16\n") +
5845 "OpCapability Int64\n";
5853 IntegerType m_fromType;
5854 IntegerType m_toType;
5855 ComputeTestFeatures m_features;
5857 map<string, string> m_asmTypes;
5858 BufferSp m_inputBuffer;
5859 BufferSp m_outputBuffer;
5862 const string getConvertCaseShaderStr (const string& instruction, const ConvertCase& convertCase)
5864 map<string, string> params = convertCase.m_asmTypes;
5866 params["instruction"] = instruction;
5868 params["inDecorator"] = getByteWidthStr(convertCase.m_fromType);
5869 params["outDecorator"] = getByteWidthStr(convertCase.m_toType);
5871 const StringTemplate shader (
5872 "OpCapability Shader\n"
5873 "${int_capabilities}"
5874 "OpMemoryModel Logical GLSL450\n"
5875 "OpEntryPoint GLCompute %main \"main\" %id\n"
5876 "OpExecutionMode %main LocalSize 1 1 1\n"
5877 "OpSource GLSL 430\n"
5878 "OpName %main \"main\"\n"
5879 "OpName %id \"gl_GlobalInvocationID\"\n"
5881 "OpDecorate %id BuiltIn GlobalInvocationId\n"
5882 "OpDecorate %indata DescriptorSet 0\n"
5883 "OpDecorate %indata Binding 0\n"
5884 "OpDecorate %outdata DescriptorSet 0\n"
5885 "OpDecorate %outdata Binding 1\n"
5886 "OpDecorate %in_arr ArrayStride ${inDecorator}\n"
5887 "OpDecorate %out_arr ArrayStride ${outDecorator}\n"
5888 "OpDecorate %in_buf BufferBlock\n"
5889 "OpDecorate %out_buf BufferBlock\n"
5890 "OpMemberDecorate %in_buf 0 Offset 0\n"
5891 "OpMemberDecorate %out_buf 0 Offset 0\n"
5893 "%void = OpTypeVoid\n"
5894 "%voidf = OpTypeFunction %void\n"
5895 "%u32 = OpTypeInt 32 0\n"
5896 "%i32 = OpTypeInt 32 1\n"
5897 "%uvec3 = OpTypeVector %u32 3\n"
5898 "%uvec3ptr = OpTypePointer Input %uvec3\n"
5900 "%in_type = ${inputType}\n"
5901 "%out_type = ${outputType}\n"
5903 "%in_ptr = OpTypePointer Uniform %in_type\n"
5904 "%out_ptr = OpTypePointer Uniform %out_type\n"
5905 "%in_arr = OpTypeRuntimeArray %in_type\n"
5906 "%out_arr = OpTypeRuntimeArray %out_type\n"
5907 "%in_buf = OpTypeStruct %in_arr\n"
5908 "%out_buf = OpTypeStruct %out_arr\n"
5909 "%in_bufptr = OpTypePointer Uniform %in_buf\n"
5910 "%out_bufptr = OpTypePointer Uniform %out_buf\n"
5911 "%indata = OpVariable %in_bufptr Uniform\n"
5912 "%outdata = OpVariable %out_bufptr Uniform\n"
5913 "%inputptr = OpTypePointer Input %in_type\n"
5914 "%id = OpVariable %uvec3ptr Input\n"
5916 "%zero = OpConstant %i32 0\n"
5918 "%main = OpFunction %void None %voidf\n"
5919 "%label = OpLabel\n"
5920 "%idval = OpLoad %uvec3 %id\n"
5921 "%x = OpCompositeExtract %u32 %idval 0\n"
5922 "%inloc = OpAccessChain %in_ptr %indata %zero %x\n"
5923 "%outloc = OpAccessChain %out_ptr %outdata %zero %x\n"
5924 "%inval = OpLoad %in_type %inloc\n"
5925 "%conv = ${instruction} %out_type %inval\n"
5926 " OpStore %outloc %conv\n"
5931 return shader.specialize(params);
5934 void createSConvertCases (vector<ConvertCase>& testCases)
5936 // Convert int to int
5937 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_16, INTEGER_TYPE_SIGNED_32, 14669));
5938 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_16, INTEGER_TYPE_SIGNED_64, 3341));
5940 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_32, INTEGER_TYPE_SIGNED_64, 973610259));
5942 // Convert int to unsigned int
5943 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_16, INTEGER_TYPE_UNSIGNED_32, 9288));
5944 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_16, INTEGER_TYPE_UNSIGNED_64, 15460));
5946 testCases.push_back(ConvertCase(INTEGER_TYPE_SIGNED_32, INTEGER_TYPE_UNSIGNED_64, 346213461));
5949 // Test for the OpSConvert instruction.
5950 tcu::TestCaseGroup* createSConvertTests (tcu::TestContext& testCtx)
5952 const string instruction ("OpSConvert");
5953 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "sconvert", "OpSConvert"));
5954 vector<ConvertCase> testCases;
5955 createSConvertCases(testCases);
5957 for (vector<ConvertCase>::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
5959 ComputeShaderSpec spec;
5961 spec.assembly = getConvertCaseShaderStr(instruction, *test);
5962 spec.inputs.push_back(test->m_inputBuffer);
5963 spec.outputs.push_back(test->m_outputBuffer);
5964 spec.numWorkGroups = IVec3(1, 1, 1);
5966 group->addChild(new SpvAsmComputeShaderCase(testCtx, test->m_name.c_str(), "Convert integers with OpSConvert.", spec, test->m_features));
5969 return group.release();
5972 void createUConvertCases (vector<ConvertCase>& testCases)
5974 // Convert unsigned int to unsigned int
5975 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_16, INTEGER_TYPE_UNSIGNED_32, 60653));
5976 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_16, INTEGER_TYPE_UNSIGNED_64, 17991));
5978 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_32, INTEGER_TYPE_UNSIGNED_64, 904256275));
5980 // Convert unsigned int to int
5981 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_16, INTEGER_TYPE_SIGNED_32, 38002));
5982 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_16, INTEGER_TYPE_SIGNED_64, 64921));
5984 testCases.push_back(ConvertCase(INTEGER_TYPE_UNSIGNED_32, INTEGER_TYPE_SIGNED_64, 4294956295ll));
5987 // Test for the OpUConvert instruction.
5988 tcu::TestCaseGroup* createUConvertTests (tcu::TestContext& testCtx)
5990 const string instruction ("OpUConvert");
5991 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "uconvert", "OpUConvert"));
5992 vector<ConvertCase> testCases;
5993 createUConvertCases(testCases);
5995 for (vector<ConvertCase>::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
5997 ComputeShaderSpec spec;
5999 spec.assembly = getConvertCaseShaderStr(instruction, *test);
6000 spec.inputs.push_back(test->m_inputBuffer);
6001 spec.outputs.push_back(test->m_outputBuffer);
6002 spec.numWorkGroups = IVec3(1, 1, 1);
6004 group->addChild(new SpvAsmComputeShaderCase(testCtx, test->m_name.c_str(), "Convert integers with OpUConvert.", spec, test->m_features));
6006 return group.release();
6009 const string getNumberTypeName (const NumberType type)
6011 if (type == NUMBERTYPE_INT32)
6015 else if (type == NUMBERTYPE_UINT32)
6019 else if (type == NUMBERTYPE_FLOAT32)
6030 deInt32 getInt(de::Random& rnd)
6032 return rnd.getInt(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
6035 const string repeatString (const string& str, int times)
6038 for (int i = 0; i < times; ++i)
6045 const string getRandomConstantString (const NumberType type, de::Random& rnd)
6047 if (type == NUMBERTYPE_INT32)
6049 return numberToString<deInt32>(getInt(rnd));
6051 else if (type == NUMBERTYPE_UINT32)
6053 return numberToString<deUint32>(rnd.getUint32());
6055 else if (type == NUMBERTYPE_FLOAT32)
6057 return numberToString<float>(rnd.getFloat());
6066 void createVectorCompositeCases (vector<map<string, string> >& testCases, de::Random& rnd, const NumberType type)
6068 map<string, string> params;
6071 for (int width = 2; width <= 4; ++width)
6073 string randomConst = numberToString(getInt(rnd));
6074 string widthStr = numberToString(width);
6075 int index = rnd.getInt(0, width-1);
6077 params["type"] = "vec";
6078 params["name"] = params["type"] + "_" + widthStr;
6079 params["compositeType"] = "%composite = OpTypeVector %custom " + widthStr +"\n";
6080 params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n";
6081 params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %filler", width) + "\n";
6082 params["indexes"] = numberToString(index);
6083 testCases.push_back(params);
6087 void createArrayCompositeCases (vector<map<string, string> >& testCases, de::Random& rnd, const NumberType type)
6089 const int limit = 10;
6090 map<string, string> params;
6092 for (int width = 2; width <= limit; ++width)
6094 string randomConst = numberToString(getInt(rnd));
6095 string widthStr = numberToString(width);
6096 int index = rnd.getInt(0, width-1);
6098 params["type"] = "array";
6099 params["name"] = params["type"] + "_" + widthStr;
6100 params["compositeType"] = string("%arraywidth = OpConstant %u32 " + widthStr + "\n")
6101 + "%composite = OpTypeArray %custom %arraywidth\n";
6103 params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n";
6104 params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %filler", width) + "\n";
6105 params["indexes"] = numberToString(index);
6106 testCases.push_back(params);
6110 void createStructCompositeCases (vector<map<string, string> >& testCases, de::Random& rnd, const NumberType type)
6112 const int limit = 10;
6113 map<string, string> params;
6115 for (int width = 2; width <= limit; ++width)
6117 string randomConst = numberToString(getInt(rnd));
6118 int index = rnd.getInt(0, width-1);
6120 params["type"] = "struct";
6121 params["name"] = params["type"] + "_" + numberToString(width);
6122 params["compositeType"] = "%composite = OpTypeStruct" + repeatString(" %custom", width) + "\n";
6123 params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n";
6124 params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %filler", width) + "\n";
6125 params["indexes"] = numberToString(index);
6126 testCases.push_back(params);
6130 void createMatrixCompositeCases (vector<map<string, string> >& testCases, de::Random& rnd, const NumberType type)
6132 map<string, string> params;
6135 for (int width = 2; width <= 4; ++width)
6137 string widthStr = numberToString(width);
6139 for (int column = 2 ; column <= 4; ++column)
6141 int index_0 = rnd.getInt(0, column-1);
6142 int index_1 = rnd.getInt(0, width-1);
6143 string columnStr = numberToString(column);
6145 params["type"] = "matrix";
6146 params["name"] = params["type"] + "_" + widthStr + "x" + columnStr;
6147 params["compositeType"] = string("%vectype = OpTypeVector %custom " + widthStr + "\n")
6148 + "%composite = OpTypeMatrix %vectype " + columnStr + "\n";
6150 params["filler"] = string("%filler = OpConstant %custom ") + getRandomConstantString(type, rnd) + "\n"
6151 + "%fillerVec = OpConstantComposite %vectype" + repeatString(" %filler", width) + "\n";
6153 params["compositeConstruct"] = "%instance = OpCompositeConstruct %composite" + repeatString(" %fillerVec", column) + "\n";
6154 params["indexes"] = numberToString(index_0) + " " + numberToString(index_1);
6155 testCases.push_back(params);
6160 void createCompositeCases (vector<map<string, string> >& testCases, de::Random& rnd, const NumberType type)
6162 createVectorCompositeCases(testCases, rnd, type);
6163 createArrayCompositeCases(testCases, rnd, type);
6164 createStructCompositeCases(testCases, rnd, type);
6165 // Matrix only supports float types
6166 if (type == NUMBERTYPE_FLOAT32)
6168 createMatrixCompositeCases(testCases, rnd, type);
6172 const string getAssemblyTypeDeclaration (const NumberType type)
6176 case NUMBERTYPE_INT32: return "OpTypeInt 32 1";
6177 case NUMBERTYPE_UINT32: return "OpTypeInt 32 0";
6178 case NUMBERTYPE_FLOAT32: return "OpTypeFloat 32";
6179 default: DE_ASSERT(false); return "";
6183 const string specializeCompositeInsertShaderTemplate (const NumberType type, const map<string, string>& params)
6185 map<string, string> parameters(params);
6187 parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
6189 parameters["compositeDecorator"] = (parameters["type"] == "array") ? "OpDecorate %composite ArrayStride 4\n" : "";
6191 return StringTemplate (
6192 "OpCapability Shader\n"
6193 "OpCapability Matrix\n"
6194 "OpMemoryModel Logical GLSL450\n"
6195 "OpEntryPoint GLCompute %main \"main\" %id\n"
6196 "OpExecutionMode %main LocalSize 1 1 1\n"
6198 "OpSource GLSL 430\n"
6199 "OpName %main \"main\"\n"
6200 "OpName %id \"gl_GlobalInvocationID\"\n"
6203 "OpDecorate %id BuiltIn GlobalInvocationId\n"
6204 "OpDecorate %buf BufferBlock\n"
6205 "OpDecorate %indata DescriptorSet 0\n"
6206 "OpDecorate %indata Binding 0\n"
6207 "OpDecorate %outdata DescriptorSet 0\n"
6208 "OpDecorate %outdata Binding 1\n"
6209 "OpDecorate %customarr ArrayStride 4\n"
6210 "${compositeDecorator}"
6211 "OpMemberDecorate %buf 0 Offset 0\n"
6214 "%void = OpTypeVoid\n"
6215 "%voidf = OpTypeFunction %void\n"
6216 "%u32 = OpTypeInt 32 0\n"
6217 "%i32 = OpTypeInt 32 1\n"
6218 "%uvec3 = OpTypeVector %u32 3\n"
6219 "%uvec3ptr = OpTypePointer Input %uvec3\n"
6222 "%custom = ${typeDeclaration}\n"
6228 // Inherited from custom
6229 "%customptr = OpTypePointer Uniform %custom\n"
6230 "%customarr = OpTypeRuntimeArray %custom\n"
6231 "%buf = OpTypeStruct %customarr\n"
6232 "%bufptr = OpTypePointer Uniform %buf\n"
6234 "%indata = OpVariable %bufptr Uniform\n"
6235 "%outdata = OpVariable %bufptr Uniform\n"
6237 "%id = OpVariable %uvec3ptr Input\n"
6238 "%zero = OpConstant %i32 0\n"
6240 "%main = OpFunction %void None %voidf\n"
6241 "%label = OpLabel\n"
6242 "%idval = OpLoad %uvec3 %id\n"
6243 "%x = OpCompositeExtract %u32 %idval 0\n"
6245 "%inloc = OpAccessChain %customptr %indata %zero %x\n"
6246 "%outloc = OpAccessChain %customptr %outdata %zero %x\n"
6247 // Read the input value
6248 "%inval = OpLoad %custom %inloc\n"
6249 // Create the composite and fill it
6250 "${compositeConstruct}"
6251 // Insert the input value to a place
6252 "%instance2 = OpCompositeInsert %composite %inval %instance ${indexes}\n"
6253 // Read back the value from the position
6254 "%out_val = OpCompositeExtract %custom %instance2 ${indexes}\n"
6255 // Store it in the output position
6256 " OpStore %outloc %out_val\n"
6259 ).specialize(parameters);
6262 template<typename T>
6263 BufferSp createCompositeBuffer(T number)
6265 return BufferSp(new Buffer<T>(vector<T>(1, number)));
6268 tcu::TestCaseGroup* createOpCompositeInsertGroup (tcu::TestContext& testCtx)
6270 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcompositeinsert", "Test the OpCompositeInsert instruction"));
6271 de::Random rnd (deStringHash(group->getName()));
6273 for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type)
6275 NumberType numberType = NumberType(type);
6276 const string typeName = getNumberTypeName(numberType);
6277 const string description = "Test the OpCompositeInsert instruction with " + typeName + "s";
6278 de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, typeName.c_str(), description.c_str()));
6279 vector<map<string, string> > testCases;
6281 createCompositeCases(testCases, rnd, numberType);
6283 for (vector<map<string, string> >::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
6285 ComputeShaderSpec spec;
6287 spec.assembly = specializeCompositeInsertShaderTemplate(numberType, *test);
6291 case NUMBERTYPE_INT32:
6293 deInt32 number = getInt(rnd);
6294 spec.inputs.push_back(createCompositeBuffer<deInt32>(number));
6295 spec.outputs.push_back(createCompositeBuffer<deInt32>(number));
6298 case NUMBERTYPE_UINT32:
6300 deUint32 number = rnd.getUint32();
6301 spec.inputs.push_back(createCompositeBuffer<deUint32>(number));
6302 spec.outputs.push_back(createCompositeBuffer<deUint32>(number));
6305 case NUMBERTYPE_FLOAT32:
6307 float number = rnd.getFloat();
6308 spec.inputs.push_back(createCompositeBuffer<float>(number));
6309 spec.outputs.push_back(createCompositeBuffer<float>(number));
6316 spec.numWorkGroups = IVec3(1, 1, 1);
6317 subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, test->at("name").c_str(), "OpCompositeInsert test", spec));
6319 group->addChild(subGroup.release());
6321 return group.release();
6324 struct AssemblyStructInfo
6326 AssemblyStructInfo (const deUint32 comp, const deUint32 idx)
6331 deUint32 components;
6335 const string specializeInBoundsShaderTemplate (const NumberType type, const AssemblyStructInfo& structInfo, const map<string, string>& params)
6337 // Create the full index string
6338 string fullIndex = numberToString(structInfo.index) + " " + params.at("indexes");
6339 // Convert it to list of indexes
6340 vector<string> indexes = de::splitString(fullIndex, ' ');
6342 map<string, string> parameters (params);
6343 parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
6344 parameters["structType"] = repeatString(" %composite", structInfo.components);
6345 parameters["structConstruct"] = repeatString(" %instance", structInfo.components);
6346 parameters["insertIndexes"] = fullIndex;
6348 // In matrix cases the last two index is the CompositeExtract indexes
6349 const deUint32 extractIndexes = (parameters["type"] == "matrix") ? 2 : 1;
6351 // Construct the extractIndex
6352 for (vector<string>::const_iterator index = indexes.end() - extractIndexes; index != indexes.end(); ++index)
6354 parameters["extractIndexes"] += " " + *index;
6357 // Remove the last 1 or 2 element depends on matrix case or not
6358 indexes.erase(indexes.end() - extractIndexes, indexes.end());
6361 // Generate AccessChain index expressions (except for the last one, because we use ptr to the composite)
6362 for (vector<string>::const_iterator index = indexes.begin(); index != indexes.end(); ++index)
6364 string indexId = "%index_" + numberToString(id++);
6365 parameters["accessChainConstDeclaration"] += indexId + " = OpConstant %u32 " + *index + "\n";
6366 parameters["accessChainIndexes"] += " " + indexId;
6369 parameters["compositeDecorator"] = (parameters["type"] == "array") ? "OpDecorate %composite ArrayStride 4\n" : "";
6371 return StringTemplate (
6372 "OpCapability Shader\n"
6373 "OpCapability Matrix\n"
6374 "OpMemoryModel Logical GLSL450\n"
6375 "OpEntryPoint GLCompute %main \"main\" %id\n"
6376 "OpExecutionMode %main LocalSize 1 1 1\n"
6378 "OpSource GLSL 430\n"
6379 "OpName %main \"main\"\n"
6380 "OpName %id \"gl_GlobalInvocationID\"\n"
6382 "OpDecorate %id BuiltIn GlobalInvocationId\n"
6383 "OpDecorate %buf BufferBlock\n"
6384 "OpDecorate %indata DescriptorSet 0\n"
6385 "OpDecorate %indata Binding 0\n"
6386 "OpDecorate %outdata DescriptorSet 0\n"
6387 "OpDecorate %outdata Binding 1\n"
6388 "OpDecorate %customarr ArrayStride 4\n"
6389 "${compositeDecorator}"
6390 "OpMemberDecorate %buf 0 Offset 0\n"
6392 "%void = OpTypeVoid\n"
6393 "%voidf = OpTypeFunction %void\n"
6394 "%u32 = OpTypeInt 32 0\n"
6395 "%uvec3 = OpTypeVector %u32 3\n"
6396 "%uvec3ptr = OpTypePointer Input %uvec3\n"
6398 "%custom = ${typeDeclaration}\n"
6401 // Inherited from composite
6402 "%composite_p = OpTypePointer Function %composite\n"
6403 "%struct_t = OpTypeStruct${structType}\n"
6404 "%struct_p = OpTypePointer Function %struct_t\n"
6407 "${accessChainConstDeclaration}"
6408 // Inherited from custom
6409 "%customptr = OpTypePointer Uniform %custom\n"
6410 "%customarr = OpTypeRuntimeArray %custom\n"
6411 "%buf = OpTypeStruct %customarr\n"
6412 "%bufptr = OpTypePointer Uniform %buf\n"
6413 "%indata = OpVariable %bufptr Uniform\n"
6414 "%outdata = OpVariable %bufptr Uniform\n"
6416 "%id = OpVariable %uvec3ptr Input\n"
6417 "%zero = OpConstant %u32 0\n"
6418 "%main = OpFunction %void None %voidf\n"
6419 "%label = OpLabel\n"
6420 "%struct_v = OpVariable %struct_p Function\n"
6421 "%idval = OpLoad %uvec3 %id\n"
6422 "%x = OpCompositeExtract %u32 %idval 0\n"
6423 // Create the input/output type
6424 "%inloc = OpInBoundsAccessChain %customptr %indata %zero %x\n"
6425 "%outloc = OpInBoundsAccessChain %customptr %outdata %zero %x\n"
6426 // Read the input value
6427 "%inval = OpLoad %custom %inloc\n"
6428 // Create the composite and fill it
6429 "${compositeConstruct}"
6430 // Create the struct and fill it with the composite
6431 "%struct = OpCompositeConstruct %struct_t${structConstruct}\n"
6433 "%comp_obj = OpCompositeInsert %struct_t %inval %struct ${insertIndexes}\n"
6435 " OpStore %struct_v %comp_obj\n"
6436 // Get deepest possible composite pointer
6437 "%inner_ptr = OpInBoundsAccessChain %composite_p %struct_v${accessChainIndexes}\n"
6438 "%read_obj = OpLoad %composite %inner_ptr\n"
6439 // Read back the stored value
6440 "%read_val = OpCompositeExtract %custom %read_obj${extractIndexes}\n"
6441 " OpStore %outloc %read_val\n"
6443 " OpFunctionEnd\n").specialize(parameters);
6446 tcu::TestCaseGroup* createOpInBoundsAccessChainGroup (tcu::TestContext& testCtx)
6448 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opinboundsaccesschain", "Test the OpInBoundsAccessChain instruction"));
6449 de::Random rnd (deStringHash(group->getName()));
6451 for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type)
6453 NumberType numberType = NumberType(type);
6454 const string typeName = getNumberTypeName(numberType);
6455 const string description = "Test the OpInBoundsAccessChain instruction with " + typeName + "s";
6456 de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, typeName.c_str(), description.c_str()));
6458 vector<map<string, string> > testCases;
6459 createCompositeCases(testCases, rnd, numberType);
6461 for (vector<map<string, string> >::const_iterator test = testCases.begin(); test != testCases.end(); ++test)
6463 ComputeShaderSpec spec;
6465 // Number of components inside of a struct
6466 deUint32 structComponents = rnd.getInt(2, 8);
6467 // Component index value
6468 deUint32 structIndex = rnd.getInt(0, structComponents - 1);
6469 AssemblyStructInfo structInfo(structComponents, structIndex);
6471 spec.assembly = specializeInBoundsShaderTemplate(numberType, structInfo, *test);
6475 case NUMBERTYPE_INT32:
6477 deInt32 number = getInt(rnd);
6478 spec.inputs.push_back(createCompositeBuffer<deInt32>(number));
6479 spec.outputs.push_back(createCompositeBuffer<deInt32>(number));
6482 case NUMBERTYPE_UINT32:
6484 deUint32 number = rnd.getUint32();
6485 spec.inputs.push_back(createCompositeBuffer<deUint32>(number));
6486 spec.outputs.push_back(createCompositeBuffer<deUint32>(number));
6489 case NUMBERTYPE_FLOAT32:
6491 float number = rnd.getFloat();
6492 spec.inputs.push_back(createCompositeBuffer<float>(number));
6493 spec.outputs.push_back(createCompositeBuffer<float>(number));
6499 spec.numWorkGroups = IVec3(1, 1, 1);
6500 subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, test->at("name").c_str(), "OpInBoundsAccessChain test", spec));
6502 group->addChild(subGroup.release());
6504 return group.release();
6507 // If the params missing, uninitialized case
6508 const string specializeDefaultOutputShaderTemplate (const NumberType type, const map<string, string>& params = map<string, string>())
6510 map<string, string> parameters(params);
6512 parameters["typeDeclaration"] = getAssemblyTypeDeclaration(type);
6514 // Declare the const value, and use it in the initializer
6515 if (params.find("constValue") != params.end())
6517 parameters["constDeclaration"] = "%const = OpConstant %in_type " + params.at("constValue") + "\n";
6518 parameters["variableInitializer"] = "%const";
6520 // Uninitialized case
6523 parameters["constDeclaration"] = "";
6524 parameters["variableInitializer"] = "";
6527 return StringTemplate(
6528 "OpCapability Shader\n"
6529 "OpMemoryModel Logical GLSL450\n"
6530 "OpEntryPoint GLCompute %main \"main\" %id\n"
6531 "OpExecutionMode %main LocalSize 1 1 1\n"
6532 "OpSource GLSL 430\n"
6533 "OpName %main \"main\"\n"
6534 "OpName %id \"gl_GlobalInvocationID\"\n"
6536 "OpDecorate %id BuiltIn GlobalInvocationId\n"
6537 "OpDecorate %indata DescriptorSet 0\n"
6538 "OpDecorate %indata Binding 0\n"
6539 "OpDecorate %outdata DescriptorSet 0\n"
6540 "OpDecorate %outdata Binding 1\n"
6541 "OpDecorate %in_arr ArrayStride 4\n"
6542 "OpDecorate %in_buf BufferBlock\n"
6543 "OpMemberDecorate %in_buf 0 Offset 0\n"
6545 "%void = OpTypeVoid\n"
6546 "%voidf = OpTypeFunction %void\n"
6547 "%u32 = OpTypeInt 32 0\n"
6548 "%i32 = OpTypeInt 32 1\n"
6549 "%uvec3 = OpTypeVector %u32 3\n"
6550 "%uvec3ptr = OpTypePointer Input %uvec3\n"
6552 "%in_type = ${typeDeclaration}\n"
6553 // "%const = OpConstant %in_type ${constValue}\n"
6554 "${constDeclaration}\n"
6556 "%in_ptr = OpTypePointer Uniform %in_type\n"
6557 "%in_arr = OpTypeRuntimeArray %in_type\n"
6558 "%in_buf = OpTypeStruct %in_arr\n"
6559 "%in_bufptr = OpTypePointer Uniform %in_buf\n"
6560 "%indata = OpVariable %in_bufptr Uniform\n"
6561 "%outdata = OpVariable %in_bufptr Uniform\n"
6562 "%id = OpVariable %uvec3ptr Input\n"
6563 "%var_ptr = OpTypePointer Function %in_type\n"
6565 "%zero = OpConstant %i32 0\n"
6567 "%main = OpFunction %void None %voidf\n"
6568 "%label = OpLabel\n"
6569 "%out_var = OpVariable %var_ptr Function ${variableInitializer}\n"
6570 "%idval = OpLoad %uvec3 %id\n"
6571 "%x = OpCompositeExtract %u32 %idval 0\n"
6572 "%inloc = OpAccessChain %in_ptr %indata %zero %x\n"
6573 "%outloc = OpAccessChain %in_ptr %outdata %zero %x\n"
6575 "%outval = OpLoad %in_type %out_var\n"
6576 " OpStore %outloc %outval\n"
6579 ).specialize(parameters);
6582 bool compareFloats (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog& log)
6584 DE_ASSERT(outputAllocs.size() != 0);
6585 DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
6587 // Use custom epsilon because of the float->string conversion
6588 const float epsilon = 0.00001f;
6590 for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
6593 memcpy(&expected, expectedOutputs[outputNdx]->data(), expectedOutputs[outputNdx]->getNumBytes());
6596 memcpy(&actual, outputAllocs[outputNdx]->getHostPtr(), expectedOutputs[outputNdx]->getNumBytes());
6598 // Test with epsilon
6599 if (fabs(expected - actual) > epsilon)
6601 log << TestLog::Message << "Error: The actual and expected values not matching."
6602 << " Expected: " << expected << " Actual: " << actual << " Epsilon: " << epsilon << TestLog::EndMessage;
6609 // Checks if the driver crash with uninitialized cases
6610 bool passthruVerify (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs, TestLog&)
6612 DE_ASSERT(outputAllocs.size() != 0);
6613 DE_ASSERT(outputAllocs.size() == expectedOutputs.size());
6615 // Copy and discard the result.
6616 for (size_t outputNdx = 0; outputNdx < outputAllocs.size(); ++outputNdx)
6618 size_t width = expectedOutputs[outputNdx]->getNumBytes();
6620 vector<char> data(width);
6621 memcpy(&data[0], outputAllocs[outputNdx]->getHostPtr(), width);
6626 tcu::TestCaseGroup* createShaderDefaultOutputGroup (tcu::TestContext& testCtx)
6628 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_default_output", "Test shader default output."));
6629 de::Random rnd (deStringHash(group->getName()));
6631 for (int type = NUMBERTYPE_INT32; type != NUMBERTYPE_END32; ++type)
6633 NumberType numberType = NumberType(type);
6634 const string typeName = getNumberTypeName(numberType);
6635 const string description = "Test the OpVariable initializer with " + typeName + ".";
6636 de::MovePtr<tcu::TestCaseGroup> subGroup (new tcu::TestCaseGroup(testCtx, typeName.c_str(), description.c_str()));
6638 // 2 similar subcases (initialized and uninitialized)
6639 for (int subCase = 0; subCase < 2; ++subCase)
6641 ComputeShaderSpec spec;
6642 spec.numWorkGroups = IVec3(1, 1, 1);
6644 map<string, string> params;
6648 case NUMBERTYPE_INT32:
6650 deInt32 number = getInt(rnd);
6651 spec.inputs.push_back(createCompositeBuffer<deInt32>(number));
6652 spec.outputs.push_back(createCompositeBuffer<deInt32>(number));
6653 params["constValue"] = numberToString(number);
6656 case NUMBERTYPE_UINT32:
6658 deUint32 number = rnd.getUint32();
6659 spec.inputs.push_back(createCompositeBuffer<deUint32>(number));
6660 spec.outputs.push_back(createCompositeBuffer<deUint32>(number));
6661 params["constValue"] = numberToString(number);
6664 case NUMBERTYPE_FLOAT32:
6666 float number = rnd.getFloat();
6667 spec.inputs.push_back(createCompositeBuffer<float>(number));
6668 spec.outputs.push_back(createCompositeBuffer<float>(number));
6669 spec.verifyIO = &compareFloats;
6670 params["constValue"] = numberToString(number);
6677 // Initialized subcase
6680 spec.assembly = specializeDefaultOutputShaderTemplate(numberType, params);
6681 subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "initialized", "OpVariable initializer tests.", spec));
6683 // Uninitialized subcase
6686 spec.assembly = specializeDefaultOutputShaderTemplate(numberType);
6687 spec.verifyIO = &passthruVerify;
6688 subGroup->addChild(new SpvAsmComputeShaderCase(testCtx, "uninitialized", "OpVariable initializer tests.", spec));
6691 group->addChild(subGroup.release());
6693 return group.release();
6696 tcu::TestCaseGroup* createOpNopTests (tcu::TestContext& testCtx)
6698 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop"));
6699 RGBA defaultColors[4];
6700 map<string, string> opNopFragments;
6702 getDefaultColors(defaultColors);
6704 opNopFragments["testfun"] =
6705 "%test_code = OpFunction %v4f32 None %v4f32_function\n"
6706 "%param1 = OpFunctionParameter %v4f32\n"
6707 "%label_testfun = OpLabel\n"
6716 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n"
6717 "%b = OpFAdd %f32 %a %a\n"
6719 "%c = OpFSub %f32 %b %a\n"
6720 "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n"
6723 "OpReturnValue %ret\n"
6726 createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, testGroup.get());
6728 return testGroup.release();
6731 tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
6733 de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands"));
6734 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Compute Instructions with special opcodes/operands"));
6735 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Graphics Instructions with special opcodes/operands"));
6737 computeTests->addChild(createOpNopGroup(testCtx));
6738 computeTests->addChild(createOpFUnordGroup(testCtx));
6739 computeTests->addChild(createOpAtomicGroup(testCtx, false));
6740 computeTests->addChild(createOpAtomicGroup(testCtx, true)); // Using new StorageBuffer decoration
6741 computeTests->addChild(createOpLineGroup(testCtx));
6742 computeTests->addChild(createOpNoLineGroup(testCtx));
6743 computeTests->addChild(createOpConstantNullGroup(testCtx));
6744 computeTests->addChild(createOpConstantCompositeGroup(testCtx));
6745 computeTests->addChild(createOpConstantUsageGroup(testCtx));
6746 computeTests->addChild(createSpecConstantGroup(testCtx));
6747 computeTests->addChild(createOpSourceGroup(testCtx));
6748 computeTests->addChild(createOpSourceExtensionGroup(testCtx));
6749 computeTests->addChild(createDecorationGroupGroup(testCtx));
6750 computeTests->addChild(createOpPhiGroup(testCtx));
6751 computeTests->addChild(createLoopControlGroup(testCtx));
6752 computeTests->addChild(createFunctionControlGroup(testCtx));
6753 computeTests->addChild(createSelectionControlGroup(testCtx));
6754 computeTests->addChild(createBlockOrderGroup(testCtx));
6755 computeTests->addChild(createMultipleShaderGroup(testCtx));
6756 computeTests->addChild(createMemoryAccessGroup(testCtx));
6757 computeTests->addChild(createOpCopyMemoryGroup(testCtx));
6758 computeTests->addChild(createOpCopyObjectGroup(testCtx));
6759 computeTests->addChild(createNoContractionGroup(testCtx));
6760 computeTests->addChild(createOpUndefGroup(testCtx));
6761 computeTests->addChild(createOpUnreachableGroup(testCtx));
6762 computeTests ->addChild(createOpQuantizeToF16Group(testCtx));
6763 computeTests ->addChild(createOpFRemGroup(testCtx));
6764 computeTests->addChild(createSConvertTests(testCtx));
6765 computeTests->addChild(createUConvertTests(testCtx));
6766 computeTests->addChild(createOpCompositeInsertGroup(testCtx));
6767 computeTests->addChild(createOpInBoundsAccessChainGroup(testCtx));
6768 computeTests->addChild(createShaderDefaultOutputGroup(testCtx));
6769 computeTests->addChild(create16BitStorageComputeGroup(testCtx));
6771 graphicsTests->addChild(createOpNopTests(testCtx));
6772 graphicsTests->addChild(createOpSourceTests(testCtx));
6773 graphicsTests->addChild(createOpSourceContinuedTests(testCtx));
6774 graphicsTests->addChild(createOpLineTests(testCtx));
6775 graphicsTests->addChild(createOpNoLineTests(testCtx));
6776 graphicsTests->addChild(createOpConstantNullTests(testCtx));
6777 graphicsTests->addChild(createOpConstantCompositeTests(testCtx));
6778 graphicsTests->addChild(createMemoryAccessTests(testCtx));
6779 graphicsTests->addChild(createOpUndefTests(testCtx));
6780 graphicsTests->addChild(createSelectionBlockOrderTests(testCtx));
6781 graphicsTests->addChild(createModuleTests(testCtx));
6782 graphicsTests->addChild(createSwitchBlockOrderTests(testCtx));
6783 graphicsTests->addChild(createOpPhiTests(testCtx));
6784 graphicsTests->addChild(createNoContractionTests(testCtx));
6785 graphicsTests->addChild(createOpQuantizeTests(testCtx));
6786 graphicsTests->addChild(createLoopTests(testCtx));
6787 graphicsTests->addChild(createSpecConstantTests(testCtx));
6788 graphicsTests->addChild(createSpecConstantOpQuantizeToF16Group(testCtx));
6789 graphicsTests->addChild(createBarrierTests(testCtx));
6790 graphicsTests->addChild(createDecorationGroupTests(testCtx));
6791 graphicsTests->addChild(createFRemTests(testCtx));
6793 graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
6795 instructionTests->addChild(computeTests.release());
6796 instructionTests->addChild(graphicsTests.release());
6798 return instructionTests.release();