vktSpvAsmInstructionTests.cpp revision e980616481c75957f9b48b0fb576712ab967829c
1/*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and/or associated documentation files (the 9 * "Materials"), to deal in the Materials without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Materials, and to 12 * permit persons to whom the Materials are furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice(s) and this permission notice shall be 16 * included in all copies or substantial portions of the Materials. 17 * 18 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 25 * 26 *//*! 27 * \file 28 * \brief SPIR-V Assembly Tests for Instructions (special opcode/operand) 29 *//*--------------------------------------------------------------------*/ 30 31#include "vktSpvAsmInstructionTests.hpp" 32 33#include "tcuCommandLine.hpp" 34#include "tcuFormatUtil.hpp" 35#include "tcuRGBA.hpp" 36#include "tcuStringTemplate.hpp" 37#include "tcuTestLog.hpp" 38#include "tcuVectorUtil.hpp" 39 40#include "vkDefs.hpp" 41#include "vkDeviceUtil.hpp" 42#include "vkMemUtil.hpp" 43#include "vkPlatform.hpp" 44#include "vkPrograms.hpp" 45#include "vkQueryUtil.hpp" 46#include "vkRef.hpp" 47#include "vkRefUtil.hpp" 48#include "vkStrUtil.hpp" 49#include "vkTypeUtil.hpp" 50 51#include "deRandom.hpp" 52#include "deStringUtil.hpp" 53#include "deUniquePtr.hpp" 54#include "tcuStringTemplate.hpp" 55 56#include <cmath> 57#include "vktSpvAsmComputeShaderCase.hpp" 58#include "vktSpvAsmComputeShaderTestUtil.hpp" 59#include "vktTestCaseUtil.hpp" 60 61#include <cmath> 62#include <limits> 63#include <map> 64#include <string> 65#include <sstream> 66 67namespace vkt 68{ 69namespace SpirVAssembly 70{ 71 72namespace 73{ 74 75using namespace vk; 76using std::map; 77using std::string; 78using std::vector; 79using tcu::IVec3; 80using tcu::IVec4; 81using tcu::RGBA; 82using tcu::TestLog; 83using tcu::TestStatus; 84using tcu::Vec4; 85using de::UniquePtr; 86using tcu::StringTemplate; 87using tcu::Vec4; 88 89typedef Unique<VkShaderModule> ModuleHandleUp; 90typedef de::SharedPtr<ModuleHandleUp> ModuleHandleSp; 91 92template<typename T> T randomScalar (de::Random& rnd, T minValue, T maxValue); 93template<> inline float randomScalar (de::Random& rnd, float minValue, float maxValue) { return rnd.getFloat(minValue, maxValue); } 94template<> inline deInt32 randomScalar (de::Random& rnd, deInt32 minValue, deInt32 maxValue) { return rnd.getInt(minValue, maxValue); } 95 96template<typename T> 97static void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0) 98{ 99 T* const typedPtr = (T*)dst; 100 for (int ndx = 0; ndx < numValues; ndx++) 101 typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue); 102} 103 104static void floorAll (vector<float>& values) 105{ 106 for (size_t i = 0; i < values.size(); i++) 107 values[i] = deFloatFloor(values[i]); 108} 109 110static void floorAll (vector<Vec4>& values) 111{ 112 for (size_t i = 0; i < values.size(); i++) 113 values[i] = floor(values[i]); 114} 115 116struct CaseParameter 117{ 118 const char* name; 119 string param; 120 121 CaseParameter (const char* case_, const string& param_) : name(case_), param(param_) {} 122}; 123 124// Assembly code used for testing OpNop, OpConstant{Null|Composite}, Op[No]Line, OpSource[Continued], OpSourceExtension, OpUndef is based on GLSL source code: 125// 126// #version 430 127// 128// layout(std140, set = 0, binding = 0) readonly buffer Input { 129// float elements[]; 130// } input_data; 131// layout(std140, set = 0, binding = 1) writeonly buffer Output { 132// float elements[]; 133// } output_data; 134// 135// layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 136// 137// void main() { 138// uint x = gl_GlobalInvocationID.x; 139// output_data.elements[x] = -input_data.elements[x]; 140// } 141 142static const char* const s_ShaderPreamble = 143 "OpCapability Shader\n" 144 "OpMemoryModel Logical GLSL450\n" 145 "OpEntryPoint GLCompute %main \"main\" %id\n" 146 "OpExecutionMode %main LocalSize 1 1 1\n"; 147 148static const char* const s_CommonTypes = 149 "%bool = OpTypeBool\n" 150 "%void = OpTypeVoid\n" 151 "%voidf = OpTypeFunction %void\n" 152 "%u32 = OpTypeInt 32 0\n" 153 "%i32 = OpTypeInt 32 1\n" 154 "%f32 = OpTypeFloat 32\n" 155 "%uvec3 = OpTypeVector %u32 3\n" 156 "%fvec3 = OpTypeVector %f32 3\n" 157 "%uvec3ptr = OpTypePointer Input %uvec3\n" 158 "%f32ptr = OpTypePointer Uniform %f32\n" 159 "%f32arr = OpTypeRuntimeArray %f32\n"; 160 161// Declares two uniform variables (indata, outdata) of type "struct { float[] }". Depends on type "f32arr" (for "float[]"). 162static const char* const s_InputOutputBuffer = 163 "%buf = OpTypeStruct %f32arr\n" 164 "%bufptr = OpTypePointer Uniform %buf\n" 165 "%indata = OpVariable %bufptr Uniform\n" 166 "%outdata = OpVariable %bufptr Uniform\n"; 167 168// Declares buffer type and layout for uniform variables indata and outdata. Both of them are SSBO bounded to descriptor set 0. 169// indata is at binding point 0, while outdata is at 1. 170static const char* const s_InputOutputBufferTraits = 171 "OpDecorate %buf BufferBlock\n" 172 "OpDecorate %indata DescriptorSet 0\n" 173 "OpDecorate %indata Binding 0\n" 174 "OpDecorate %outdata DescriptorSet 0\n" 175 "OpDecorate %outdata Binding 1\n" 176 "OpDecorate %f32arr ArrayStride 4\n" 177 "OpMemberDecorate %buf 0 Offset 0\n"; 178 179tcu::TestCaseGroup* createOpNopGroup (tcu::TestContext& testCtx) 180{ 181 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnop", "Test the OpNop instruction")); 182 ComputeShaderSpec spec; 183 de::Random rnd (deStringHash(group->getName())); 184 const int numElements = 100; 185 vector<float> positiveFloats (numElements, 0); 186 vector<float> negativeFloats (numElements, 0); 187 188 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 189 190 for (size_t ndx = 0; ndx < numElements; ++ndx) 191 negativeFloats[ndx] = -positiveFloats[ndx]; 192 193 spec.assembly = 194 string(s_ShaderPreamble) + 195 196 "OpSource GLSL 430\n" 197 "OpName %main \"main\"\n" 198 "OpName %id \"gl_GlobalInvocationID\"\n" 199 200 "OpDecorate %id BuiltIn GlobalInvocationId\n" 201 202 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) 203 204 + string(s_InputOutputBuffer) + 205 206 "%id = OpVariable %uvec3ptr Input\n" 207 "%zero = OpConstant %i32 0\n" 208 209 "%main = OpFunction %void None %voidf\n" 210 "%label = OpLabel\n" 211 "%idval = OpLoad %uvec3 %id\n" 212 "%x = OpCompositeExtract %u32 %idval 0\n" 213 214 " OpNop\n" // Inside a function body 215 216 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 217 "%inval = OpLoad %f32 %inloc\n" 218 "%neg = OpFNegate %f32 %inval\n" 219 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 220 " OpStore %outloc %neg\n" 221 " OpReturn\n" 222 " OpFunctionEnd\n"; 223 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 224 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 225 spec.numWorkGroups = IVec3(numElements, 1, 1); 226 227 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNop appearing at different places", spec)); 228 229 return group.release(); 230} 231 232tcu::TestCaseGroup* createOpLineGroup (tcu::TestContext& testCtx) 233{ 234 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opline", "Test the OpLine instruction")); 235 ComputeShaderSpec spec; 236 de::Random rnd (deStringHash(group->getName())); 237 const int numElements = 100; 238 vector<float> positiveFloats (numElements, 0); 239 vector<float> negativeFloats (numElements, 0); 240 241 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 242 243 for (size_t ndx = 0; ndx < numElements; ++ndx) 244 negativeFloats[ndx] = -positiveFloats[ndx]; 245 246 spec.assembly = 247 string(s_ShaderPreamble) + 248 249 "%fname1 = OpString \"negateInputs.comp\"\n" 250 "%fname2 = OpString \"negateInputs\"\n" 251 252 "OpSource GLSL 430\n" 253 "OpName %main \"main\"\n" 254 "OpName %id \"gl_GlobalInvocationID\"\n" 255 256 "OpDecorate %id BuiltIn GlobalInvocationId\n" 257 258 + string(s_InputOutputBufferTraits) + 259 260 "OpLine %fname1 0 0\n" // At the earliest possible position 261 262 + string(s_CommonTypes) + string(s_InputOutputBuffer) + 263 264 "OpLine %fname1 0 1\n" // Multiple OpLines in sequence 265 "OpLine %fname2 1 0\n" // Different filenames 266 "OpLine %fname1 1000 100000\n" 267 268 "%id = OpVariable %uvec3ptr Input\n" 269 "%zero = OpConstant %i32 0\n" 270 271 "OpLine %fname1 1 1\n" // Before a function 272 273 "%main = OpFunction %void None %voidf\n" 274 "%label = OpLabel\n" 275 276 "OpLine %fname1 1 1\n" // In a function 277 278 "%idval = OpLoad %uvec3 %id\n" 279 "%x = OpCompositeExtract %u32 %idval 0\n" 280 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 281 "%inval = OpLoad %f32 %inloc\n" 282 "%neg = OpFNegate %f32 %inval\n" 283 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 284 " OpStore %outloc %neg\n" 285 " OpReturn\n" 286 " OpFunctionEnd\n"; 287 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 288 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 289 spec.numWorkGroups = IVec3(numElements, 1, 1); 290 291 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpLine appearing at different places", spec)); 292 293 return group.release(); 294} 295 296tcu::TestCaseGroup* createOpNoLineGroup (tcu::TestContext& testCtx) 297{ 298 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opnoline", "Test the OpNoLine instruction")); 299 ComputeShaderSpec spec; 300 de::Random rnd (deStringHash(group->getName())); 301 const int numElements = 100; 302 vector<float> positiveFloats (numElements, 0); 303 vector<float> negativeFloats (numElements, 0); 304 305 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 306 307 for (size_t ndx = 0; ndx < numElements; ++ndx) 308 negativeFloats[ndx] = -positiveFloats[ndx]; 309 310 spec.assembly = 311 string(s_ShaderPreamble) + 312 313 "%fname = OpString \"negateInputs.comp\"\n" 314 315 "OpSource GLSL 430\n" 316 "OpName %main \"main\"\n" 317 "OpName %id \"gl_GlobalInvocationID\"\n" 318 319 "OpDecorate %id BuiltIn GlobalInvocationId\n" 320 321 + string(s_InputOutputBufferTraits) + 322 323 "OpNoLine\n" // At the earliest possible position, without preceding OpLine 324 325 + string(s_CommonTypes) + string(s_InputOutputBuffer) + 326 327 "OpLine %fname 0 1\n" 328 "OpNoLine\n" // Immediately following a preceding OpLine 329 330 "OpLine %fname 1000 1\n" 331 332 "%id = OpVariable %uvec3ptr Input\n" 333 "%zero = OpConstant %i32 0\n" 334 335 "OpNoLine\n" // Contents after the previous OpLine 336 337 "%main = OpFunction %void None %voidf\n" 338 "%label = OpLabel\n" 339 "%idval = OpLoad %uvec3 %id\n" 340 "%x = OpCompositeExtract %u32 %idval 0\n" 341 342 "OpNoLine\n" // Multiple OpNoLine 343 "OpNoLine\n" 344 "OpNoLine\n" 345 346 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 347 "%inval = OpLoad %f32 %inloc\n" 348 "%neg = OpFNegate %f32 %inval\n" 349 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 350 " OpStore %outloc %neg\n" 351 " OpReturn\n" 352 " OpFunctionEnd\n"; 353 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 354 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 355 spec.numWorkGroups = IVec3(numElements, 1, 1); 356 357 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpNoLine appearing at different places", spec)); 358 359 return group.release(); 360} 361 362// Compare instruction for the contraction compute case. 363// Returns true if the output is what is expected from the test case. 364bool compareNoContractCase(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs) 365{ 366 if (outputAllocs.size() != 1) 367 return false; 368 369 // We really just need this for size because we are not comparing the exact values. 370 const BufferSp& expectedOutput = expectedOutputs[0]; 371 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());; 372 373 for(size_t i = 0; i < expectedOutput->getNumBytes() / sizeof(float); ++i) { 374 if (outputAsFloat[i] != 0.f && 375 outputAsFloat[i] != -ldexp(1, -24)) { 376 return false; 377 } 378 } 379 380 return true; 381} 382 383tcu::TestCaseGroup* createNoContractionGroup (tcu::TestContext& testCtx) 384{ 385 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration")); 386 vector<CaseParameter> cases; 387 const int numElements = 100; 388 vector<float> inputFloats1 (numElements, 0); 389 vector<float> inputFloats2 (numElements, 0); 390 vector<float> outputFloats (numElements, 0); 391 const StringTemplate shaderTemplate ( 392 string(s_ShaderPreamble) + 393 394 "OpName %main \"main\"\n" 395 "OpName %id \"gl_GlobalInvocationID\"\n" 396 397 "OpDecorate %id BuiltIn GlobalInvocationId\n" 398 399 "${DECORATION}\n" 400 401 "OpDecorate %buf BufferBlock\n" 402 "OpDecorate %indata1 DescriptorSet 0\n" 403 "OpDecorate %indata1 Binding 0\n" 404 "OpDecorate %indata2 DescriptorSet 0\n" 405 "OpDecorate %indata2 Binding 1\n" 406 "OpDecorate %outdata DescriptorSet 0\n" 407 "OpDecorate %outdata Binding 2\n" 408 "OpDecorate %f32arr ArrayStride 4\n" 409 "OpMemberDecorate %buf 0 Offset 0\n" 410 411 + string(s_CommonTypes) + 412 413 "%buf = OpTypeStruct %f32arr\n" 414 "%bufptr = OpTypePointer Uniform %buf\n" 415 "%indata1 = OpVariable %bufptr Uniform\n" 416 "%indata2 = OpVariable %bufptr Uniform\n" 417 "%outdata = OpVariable %bufptr Uniform\n" 418 419 "%id = OpVariable %uvec3ptr Input\n" 420 "%zero = OpConstant %i32 0\n" 421 "%c_f_m1 = OpConstant %f32 -1.\n" 422 423 "%main = OpFunction %void None %voidf\n" 424 "%label = OpLabel\n" 425 "%idval = OpLoad %uvec3 %id\n" 426 "%x = OpCompositeExtract %u32 %idval 0\n" 427 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n" 428 "%inval1 = OpLoad %f32 %inloc1\n" 429 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n" 430 "%inval2 = OpLoad %f32 %inloc2\n" 431 "%mul = OpFMul %f32 %inval1 %inval2\n" 432 "%add = OpFAdd %f32 %mul %c_f_m1\n" 433 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 434 " OpStore %outloc %add\n" 435 " OpReturn\n" 436 " OpFunctionEnd\n"); 437 438 cases.push_back(CaseParameter("multiplication", "OpDecorate %mul NoContraction")); 439 cases.push_back(CaseParameter("addition", "OpDecorate %add NoContraction")); 440 cases.push_back(CaseParameter("both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction")); 441 442 for (size_t ndx = 0; ndx < numElements; ++ndx) 443 { 444 inputFloats1[ndx] = 1.f + std::ldexp(1.f, -23); // 1 + 2^-23. 445 inputFloats2[ndx] = 1.f - std::ldexp(1.f, -23); // 1 - 2^-23. 446 // Result for (1 + 2^-23) * (1 - 2^-23) - 1. With NoContraction, the multiplication will be 447 // conducted separately and the result is rounded to 1, or 0x1.fffffcp-1 448 // So the final result will be 0.f or 0x1p-24. 449 // If the operation is combined into a precise fused multiply-add, then the result would be 450 // 2^-46 (0xa8800000). 451 outputFloats[ndx] = 0.f; 452 } 453 454 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 455 { 456 map<string, string> specializations; 457 ComputeShaderSpec spec; 458 459 specializations["DECORATION"] = cases[caseNdx].param; 460 spec.assembly = shaderTemplate.specialize(specializations); 461 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1))); 462 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); 463 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 464 spec.numWorkGroups = IVec3(numElements, 1, 1); 465 // Check against the two possible answers based on rounding mode. 466 spec.verifyIO = &compareNoContractCase; 467 468 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 469 } 470 return group.release(); 471} 472 473bool compareFRem(const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs) 474{ 475 if (outputAllocs.size() != 1) 476 return false; 477 478 const BufferSp& expectedOutput = expectedOutputs[0]; 479 const float *expectedOutputAsFloat = static_cast<const float*>(expectedOutput->data()); 480 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());; 481 482 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx) 483 { 484 const float f0 = expectedOutputAsFloat[idx]; 485 const float f1 = outputAsFloat[idx]; 486 // \todo relative error needs to be fairly high because FRem may be implemented as 487 // (roughly) frac(a/b)*b, so LSB errors can be magnified. But this should be fine for now. 488 if (deFloatAbs((f1 - f0) / f0) > 0.02) 489 return false; 490 } 491 492 return true; 493} 494 495tcu::TestCaseGroup* createOpFRemGroup (tcu::TestContext& testCtx) 496{ 497 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opfrem", "Test the OpFRem instruction")); 498 ComputeShaderSpec spec; 499 de::Random rnd (deStringHash(group->getName())); 500 const int numElements = 200; 501 vector<float> inputFloats1 (numElements, 0); 502 vector<float> inputFloats2 (numElements, 0); 503 vector<float> outputFloats (numElements, 0); 504 505 fillRandomScalars(rnd, -10000.f, 10000.f, &inputFloats1[0], numElements); 506 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats2[0], numElements); 507 508 for (size_t ndx = 0; ndx < numElements; ++ndx) 509 { 510 // Guard against divisors near zero. 511 if (std::fabs(inputFloats2[ndx]) < 1e-3) 512 inputFloats2[ndx] = 8.f; 513 514 // The return value of std::fmod() has the same sign as its first operand, which is how OpFRem spec'd. 515 outputFloats[ndx] = std::fmod(inputFloats1[ndx], inputFloats2[ndx]); 516 } 517 518 spec.assembly = 519 string(s_ShaderPreamble) + 520 521 "OpName %main \"main\"\n" 522 "OpName %id \"gl_GlobalInvocationID\"\n" 523 524 "OpDecorate %id BuiltIn GlobalInvocationId\n" 525 526 "OpDecorate %buf BufferBlock\n" 527 "OpDecorate %indata1 DescriptorSet 0\n" 528 "OpDecorate %indata1 Binding 0\n" 529 "OpDecorate %indata2 DescriptorSet 0\n" 530 "OpDecorate %indata2 Binding 1\n" 531 "OpDecorate %outdata DescriptorSet 0\n" 532 "OpDecorate %outdata Binding 2\n" 533 "OpDecorate %f32arr ArrayStride 4\n" 534 "OpMemberDecorate %buf 0 Offset 0\n" 535 536 + string(s_CommonTypes) + 537 538 "%buf = OpTypeStruct %f32arr\n" 539 "%bufptr = OpTypePointer Uniform %buf\n" 540 "%indata1 = OpVariable %bufptr Uniform\n" 541 "%indata2 = OpVariable %bufptr Uniform\n" 542 "%outdata = OpVariable %bufptr Uniform\n" 543 544 "%id = OpVariable %uvec3ptr Input\n" 545 "%zero = OpConstant %i32 0\n" 546 547 "%main = OpFunction %void None %voidf\n" 548 "%label = OpLabel\n" 549 "%idval = OpLoad %uvec3 %id\n" 550 "%x = OpCompositeExtract %u32 %idval 0\n" 551 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n" 552 "%inval1 = OpLoad %f32 %inloc1\n" 553 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n" 554 "%inval2 = OpLoad %f32 %inloc2\n" 555 "%rem = OpFRem %f32 %inval1 %inval2\n" 556 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 557 " OpStore %outloc %rem\n" 558 " OpReturn\n" 559 " OpFunctionEnd\n"; 560 561 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1))); 562 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); 563 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 564 spec.numWorkGroups = IVec3(numElements, 1, 1); 565 spec.verifyIO = &compareFRem; 566 567 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "", spec)); 568 569 return group.release(); 570} 571 572// Copy contents in the input buffer to the output buffer. 573tcu::TestCaseGroup* createOpCopyMemoryGroup (tcu::TestContext& testCtx) 574{ 575 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopymemory", "Test the OpCopyMemory instruction")); 576 de::Random rnd (deStringHash(group->getName())); 577 const int numElements = 100; 578 579 // 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. 580 ComputeShaderSpec spec1; 581 vector<Vec4> inputFloats1 (numElements); 582 vector<Vec4> outputFloats1 (numElements); 583 584 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats1[0], numElements * 4); 585 586 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 587 floorAll(inputFloats1); 588 589 for (size_t ndx = 0; ndx < numElements; ++ndx) 590 outputFloats1[ndx] = inputFloats1[ndx] + Vec4(0.f, 0.5f, 1.5f, 2.5f); 591 592 spec1.assembly = 593 string(s_ShaderPreamble) + 594 595 "OpName %main \"main\"\n" 596 "OpName %id \"gl_GlobalInvocationID\"\n" 597 598 "OpDecorate %id BuiltIn GlobalInvocationId\n" 599 "OpDecorate %vec4arr ArrayStride 16\n" 600 601 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 602 603 "%vec4 = OpTypeVector %f32 4\n" 604 "%vec4ptr_u = OpTypePointer Uniform %vec4\n" 605 "%vec4ptr_f = OpTypePointer Function %vec4\n" 606 "%vec4arr = OpTypeRuntimeArray %vec4\n" 607 "%buf = OpTypeStruct %vec4arr\n" 608 "%bufptr = OpTypePointer Uniform %buf\n" 609 "%indata = OpVariable %bufptr Uniform\n" 610 "%outdata = OpVariable %bufptr Uniform\n" 611 612 "%id = OpVariable %uvec3ptr Input\n" 613 "%zero = OpConstant %i32 0\n" 614 "%c_f_0 = OpConstant %f32 0.\n" 615 "%c_f_0_5 = OpConstant %f32 0.5\n" 616 "%c_f_1_5 = OpConstant %f32 1.5\n" 617 "%c_f_2_5 = OpConstant %f32 2.5\n" 618 "%c_vec4 = OpConstantComposite %vec4 %c_f_0 %c_f_0_5 %c_f_1_5 %c_f_2_5\n" 619 620 "%main = OpFunction %void None %voidf\n" 621 "%label = OpLabel\n" 622 "%v_vec4 = OpVariable %vec4ptr_f Function\n" 623 "%idval = OpLoad %uvec3 %id\n" 624 "%x = OpCompositeExtract %u32 %idval 0\n" 625 "%inloc = OpAccessChain %vec4ptr_u %indata %zero %x\n" 626 "%outloc = OpAccessChain %vec4ptr_u %outdata %zero %x\n" 627 " OpCopyMemory %v_vec4 %inloc\n" 628 "%v_vec4_val = OpLoad %vec4 %v_vec4\n" 629 "%add = OpFAdd %vec4 %v_vec4_val %c_vec4\n" 630 " OpStore %outloc %add\n" 631 " OpReturn\n" 632 " OpFunctionEnd\n"; 633 634 spec1.inputs.push_back(BufferSp(new Vec4Buffer(inputFloats1))); 635 spec1.outputs.push_back(BufferSp(new Vec4Buffer(outputFloats1))); 636 spec1.numWorkGroups = IVec3(numElements, 1, 1); 637 638 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector", "OpCopyMemory elements of vector type", spec1)); 639 640 // The following case copies a float[100] variable from the input buffer to the output buffer. 641 ComputeShaderSpec spec2; 642 vector<float> inputFloats2 (numElements); 643 vector<float> outputFloats2 (numElements); 644 645 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats2[0], numElements); 646 647 for (size_t ndx = 0; ndx < numElements; ++ndx) 648 outputFloats2[ndx] = inputFloats2[ndx]; 649 650 spec2.assembly = 651 string(s_ShaderPreamble) + 652 653 "OpName %main \"main\"\n" 654 "OpName %id \"gl_GlobalInvocationID\"\n" 655 656 "OpDecorate %id BuiltIn GlobalInvocationId\n" 657 "OpDecorate %f32arr100 ArrayStride 4\n" 658 659 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 660 661 "%hundred = OpConstant %u32 100\n" 662 "%f32arr100 = OpTypeArray %f32 %hundred\n" 663 "%f32arr100ptr_f = OpTypePointer Function %f32arr100\n" 664 "%f32arr100ptr_u = OpTypePointer Uniform %f32arr100\n" 665 "%buf = OpTypeStruct %f32arr100\n" 666 "%bufptr = OpTypePointer Uniform %buf\n" 667 "%indata = OpVariable %bufptr Uniform\n" 668 "%outdata = OpVariable %bufptr Uniform\n" 669 670 "%id = OpVariable %uvec3ptr Input\n" 671 "%zero = OpConstant %i32 0\n" 672 673 "%main = OpFunction %void None %voidf\n" 674 "%label = OpLabel\n" 675 "%var = OpVariable %f32arr100ptr_f Function\n" 676 "%inarr = OpAccessChain %f32arr100ptr_u %indata %zero\n" 677 "%outarr = OpAccessChain %f32arr100ptr_u %outdata %zero\n" 678 " OpCopyMemory %var %inarr\n" 679 " OpCopyMemory %outarr %var\n" 680 " OpReturn\n" 681 " OpFunctionEnd\n"; 682 683 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); 684 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2))); 685 spec2.numWorkGroups = IVec3(1, 1, 1); 686 687 group->addChild(new SpvAsmComputeShaderCase(testCtx, "array", "OpCopyMemory elements of array type", spec2)); 688 689 // The following case copies a struct{vec4, vec4, vec4, vec4} variable from the input buffer to the output buffer. 690 ComputeShaderSpec spec3; 691 vector<float> inputFloats3 (16); 692 vector<float> outputFloats3 (16); 693 694 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats3[0], 16); 695 696 for (size_t ndx = 0; ndx < 16; ++ndx) 697 outputFloats3[ndx] = inputFloats3[ndx]; 698 699 spec3.assembly = 700 string(s_ShaderPreamble) + 701 702 "OpName %main \"main\"\n" 703 "OpName %id \"gl_GlobalInvocationID\"\n" 704 705 "OpDecorate %id BuiltIn GlobalInvocationId\n" 706 "OpMemberDecorate %buf 0 Offset 0\n" 707 "OpMemberDecorate %buf 1 Offset 16\n" 708 "OpMemberDecorate %buf 2 Offset 32\n" 709 "OpMemberDecorate %buf 3 Offset 48\n" 710 711 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 712 713 "%vec4 = OpTypeVector %f32 4\n" 714 "%buf = OpTypeStruct %vec4 %vec4 %vec4 %vec4\n" 715 "%bufptr = OpTypePointer Uniform %buf\n" 716 "%indata = OpVariable %bufptr Uniform\n" 717 "%outdata = OpVariable %bufptr Uniform\n" 718 "%vec4stptr = OpTypePointer Function %buf\n" 719 720 "%id = OpVariable %uvec3ptr Input\n" 721 "%zero = OpConstant %i32 0\n" 722 723 "%main = OpFunction %void None %voidf\n" 724 "%label = OpLabel\n" 725 "%var = OpVariable %vec4stptr Function\n" 726 " OpCopyMemory %var %indata\n" 727 " OpCopyMemory %outdata %var\n" 728 " OpReturn\n" 729 " OpFunctionEnd\n"; 730 731 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3))); 732 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3))); 733 spec3.numWorkGroups = IVec3(1, 1, 1); 734 735 group->addChild(new SpvAsmComputeShaderCase(testCtx, "struct", "OpCopyMemory elements of struct type", spec3)); 736 737 // The following case negates multiple float variables from the input buffer and stores the results to the output buffer. 738 ComputeShaderSpec spec4; 739 vector<float> inputFloats4 (numElements); 740 vector<float> outputFloats4 (numElements); 741 742 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats4[0], numElements); 743 744 for (size_t ndx = 0; ndx < numElements; ++ndx) 745 outputFloats4[ndx] = -inputFloats4[ndx]; 746 747 spec4.assembly = 748 string(s_ShaderPreamble) + 749 750 "OpName %main \"main\"\n" 751 "OpName %id \"gl_GlobalInvocationID\"\n" 752 753 "OpDecorate %id BuiltIn GlobalInvocationId\n" 754 755 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 756 757 "%f32ptr_f = OpTypePointer Function %f32\n" 758 "%id = OpVariable %uvec3ptr Input\n" 759 "%zero = OpConstant %i32 0\n" 760 761 "%main = OpFunction %void None %voidf\n" 762 "%label = OpLabel\n" 763 "%var = OpVariable %f32ptr_f Function\n" 764 "%idval = OpLoad %uvec3 %id\n" 765 "%x = OpCompositeExtract %u32 %idval 0\n" 766 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 767 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 768 " OpCopyMemory %var %inloc\n" 769 "%val = OpLoad %f32 %var\n" 770 "%neg = OpFNegate %f32 %val\n" 771 " OpStore %outloc %neg\n" 772 " OpReturn\n" 773 " OpFunctionEnd\n"; 774 775 spec4.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4))); 776 spec4.outputs.push_back(BufferSp(new Float32Buffer(outputFloats4))); 777 spec4.numWorkGroups = IVec3(numElements, 1, 1); 778 779 group->addChild(new SpvAsmComputeShaderCase(testCtx, "float", "OpCopyMemory elements of float type", spec4)); 780 781 return group.release(); 782} 783 784tcu::TestCaseGroup* createOpCopyObjectGroup (tcu::TestContext& testCtx) 785{ 786 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opcopyobject", "Test the OpCopyObject instruction")); 787 ComputeShaderSpec spec; 788 de::Random rnd (deStringHash(group->getName())); 789 const int numElements = 100; 790 vector<float> inputFloats (numElements, 0); 791 vector<float> outputFloats (numElements, 0); 792 793 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements); 794 795 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 796 floorAll(inputFloats); 797 798 for (size_t ndx = 0; ndx < numElements; ++ndx) 799 outputFloats[ndx] = inputFloats[ndx] + 7.5f; 800 801 spec.assembly = 802 string(s_ShaderPreamble) + 803 804 "OpName %main \"main\"\n" 805 "OpName %id \"gl_GlobalInvocationID\"\n" 806 807 "OpDecorate %id BuiltIn GlobalInvocationId\n" 808 809 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 810 811 "%fmat = OpTypeMatrix %fvec3 3\n" 812 "%three = OpConstant %u32 3\n" 813 "%farr = OpTypeArray %f32 %three\n" 814 "%fst = OpTypeStruct %f32 %f32\n" 815 816 + string(s_InputOutputBuffer) + 817 818 "%id = OpVariable %uvec3ptr Input\n" 819 "%zero = OpConstant %i32 0\n" 820 "%c_f = OpConstant %f32 1.5\n" 821 "%c_fvec3 = OpConstantComposite %fvec3 %c_f %c_f %c_f\n" 822 "%c_fmat = OpConstantComposite %fmat %c_fvec3 %c_fvec3 %c_fvec3\n" 823 "%c_farr = OpConstantComposite %farr %c_f %c_f %c_f\n" 824 "%c_fst = OpConstantComposite %fst %c_f %c_f\n" 825 826 "%main = OpFunction %void None %voidf\n" 827 "%label = OpLabel\n" 828 "%c_f_copy = OpCopyObject %f32 %c_f\n" 829 "%c_fvec3_copy = OpCopyObject %fvec3 %c_fvec3\n" 830 "%c_fmat_copy = OpCopyObject %fmat %c_fmat\n" 831 "%c_farr_copy = OpCopyObject %farr %c_farr\n" 832 "%c_fst_copy = OpCopyObject %fst %c_fst\n" 833 "%fvec3_elem = OpCompositeExtract %f32 %c_fvec3_copy 0\n" 834 "%fmat_elem = OpCompositeExtract %f32 %c_fmat_copy 1 2\n" 835 "%farr_elem = OpCompositeExtract %f32 %c_farr_copy 2\n" 836 "%fst_elem = OpCompositeExtract %f32 %c_fst_copy 1\n" 837 // Add up. 1.5 * 5 = 7.5. 838 "%add1 = OpFAdd %f32 %c_f_copy %fvec3_elem\n" 839 "%add2 = OpFAdd %f32 %add1 %fmat_elem\n" 840 "%add3 = OpFAdd %f32 %add2 %farr_elem\n" 841 "%add4 = OpFAdd %f32 %add3 %fst_elem\n" 842 843 "%idval = OpLoad %uvec3 %id\n" 844 "%x = OpCompositeExtract %u32 %idval 0\n" 845 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 846 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 847 "%inval = OpLoad %f32 %inloc\n" 848 "%add = OpFAdd %f32 %add4 %inval\n" 849 " OpStore %outloc %add\n" 850 " OpReturn\n" 851 " OpFunctionEnd\n"; 852 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 853 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 854 spec.numWorkGroups = IVec3(numElements, 1, 1); 855 856 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "OpCopyObject on different types", spec)); 857 858 return group.release(); 859} 860// Assembly code used for testing OpUnreachable is based on GLSL source code: 861// 862// #version 430 863// 864// layout(std140, set = 0, binding = 0) readonly buffer Input { 865// float elements[]; 866// } input_data; 867// layout(std140, set = 0, binding = 1) writeonly buffer Output { 868// float elements[]; 869// } output_data; 870// 871// void not_called_func() { 872// // place OpUnreachable here 873// } 874// 875// uint modulo4(uint val) { 876// switch (val % uint(4)) { 877// case 0: return 3; 878// case 1: return 2; 879// case 2: return 1; 880// case 3: return 0; 881// default: return 100; // place OpUnreachable here 882// } 883// } 884// 885// uint const5() { 886// return 5; 887// // place OpUnreachable here 888// } 889// 890// void main() { 891// uint x = gl_GlobalInvocationID.x; 892// if (const5() > modulo4(1000)) { 893// output_data.elements[x] = -input_data.elements[x]; 894// } else { 895// // place OpUnreachable here 896// output_data.elements[x] = input_data.elements[x]; 897// } 898// } 899 900tcu::TestCaseGroup* createOpUnreachableGroup (tcu::TestContext& testCtx) 901{ 902 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opunreachable", "Test the OpUnreachable instruction")); 903 ComputeShaderSpec spec; 904 de::Random rnd (deStringHash(group->getName())); 905 const int numElements = 100; 906 vector<float> positiveFloats (numElements, 0); 907 vector<float> negativeFloats (numElements, 0); 908 909 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 910 911 for (size_t ndx = 0; ndx < numElements; ++ndx) 912 negativeFloats[ndx] = -positiveFloats[ndx]; 913 914 spec.assembly = 915 string(s_ShaderPreamble) + 916 917 "OpSource GLSL 430\n" 918 "OpName %main \"main\"\n" 919 "OpName %func_not_called_func \"not_called_func(\"\n" 920 "OpName %func_modulo4 \"modulo4(u1;\"\n" 921 "OpName %func_const5 \"const5(\"\n" 922 "OpName %id \"gl_GlobalInvocationID\"\n" 923 924 "OpDecorate %id BuiltIn GlobalInvocationId\n" 925 926 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 927 928 "%u32ptr = OpTypePointer Function %u32\n" 929 "%uintfuint = OpTypeFunction %u32 %u32ptr\n" 930 "%unitf = OpTypeFunction %u32\n" 931 932 "%id = OpVariable %uvec3ptr Input\n" 933 "%zero = OpConstant %u32 0\n" 934 "%one = OpConstant %u32 1\n" 935 "%two = OpConstant %u32 2\n" 936 "%three = OpConstant %u32 3\n" 937 "%four = OpConstant %u32 4\n" 938 "%five = OpConstant %u32 5\n" 939 "%hundred = OpConstant %u32 100\n" 940 "%thousand = OpConstant %u32 1000\n" 941 942 + string(s_InputOutputBuffer) + 943 944 // Main() 945 "%main = OpFunction %void None %voidf\n" 946 "%main_entry = OpLabel\n" 947 "%v_thousand = OpVariable %u32ptr Function %thousand\n" 948 "%idval = OpLoad %uvec3 %id\n" 949 "%x = OpCompositeExtract %u32 %idval 0\n" 950 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 951 "%inval = OpLoad %f32 %inloc\n" 952 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 953 "%ret_const5 = OpFunctionCall %u32 %func_const5\n" 954 "%ret_modulo4 = OpFunctionCall %u32 %func_modulo4 %v_thousand\n" 955 "%cmp_gt = OpUGreaterThan %bool %ret_const5 %ret_modulo4\n" 956 " OpSelectionMerge %if_end None\n" 957 " OpBranchConditional %cmp_gt %if_true %if_false\n" 958 "%if_true = OpLabel\n" 959 "%negate = OpFNegate %f32 %inval\n" 960 " OpStore %outloc %negate\n" 961 " OpBranch %if_end\n" 962 "%if_false = OpLabel\n" 963 " OpUnreachable\n" // Unreachable else branch for if statement 964 "%if_end = OpLabel\n" 965 " OpReturn\n" 966 " OpFunctionEnd\n" 967 968 // not_called_function() 969 "%func_not_called_func = OpFunction %void None %voidf\n" 970 "%not_called_func_entry = OpLabel\n" 971 " OpUnreachable\n" // Unreachable entry block in not called static function 972 " OpFunctionEnd\n" 973 974 // modulo4() 975 "%func_modulo4 = OpFunction %u32 None %uintfuint\n" 976 "%valptr = OpFunctionParameter %u32ptr\n" 977 "%modulo4_entry = OpLabel\n" 978 "%val = OpLoad %u32 %valptr\n" 979 "%modulo = OpUMod %u32 %val %four\n" 980 " OpSelectionMerge %switch_merge None\n" 981 " OpSwitch %modulo %default 0 %case0 1 %case1 2 %case2 3 %case3\n" 982 "%case0 = OpLabel\n" 983 " OpReturnValue %three\n" 984 "%case1 = OpLabel\n" 985 " OpReturnValue %two\n" 986 "%case2 = OpLabel\n" 987 " OpReturnValue %one\n" 988 "%case3 = OpLabel\n" 989 " OpReturnValue %zero\n" 990 "%default = OpLabel\n" 991 " OpUnreachable\n" // Unreachable default case for switch statement 992 "%switch_merge = OpLabel\n" 993 " OpUnreachable\n" // Unreachable merge block for switch statement 994 " OpFunctionEnd\n" 995 996 // const5() 997 "%func_const5 = OpFunction %u32 None %unitf\n" 998 "%const5_entry = OpLabel\n" 999 " OpReturnValue %five\n" 1000 "%unreachable = OpLabel\n" 1001 " OpUnreachable\n" // Unreachable block in function 1002 " OpFunctionEnd\n"; 1003 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 1004 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 1005 spec.numWorkGroups = IVec3(numElements, 1, 1); 1006 1007 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "OpUnreachable appearing at different places", spec)); 1008 1009 return group.release(); 1010} 1011 1012// Assembly code used for testing decoration group is based on GLSL source code: 1013// 1014// #version 430 1015// 1016// layout(std140, set = 0, binding = 0) readonly buffer Input0 { 1017// float elements[]; 1018// } input_data0; 1019// layout(std140, set = 0, binding = 1) readonly buffer Input1 { 1020// float elements[]; 1021// } input_data1; 1022// layout(std140, set = 0, binding = 2) readonly buffer Input2 { 1023// float elements[]; 1024// } input_data2; 1025// layout(std140, set = 0, binding = 3) readonly buffer Input3 { 1026// float elements[]; 1027// } input_data3; 1028// layout(std140, set = 0, binding = 4) readonly buffer Input4 { 1029// float elements[]; 1030// } input_data4; 1031// layout(std140, set = 0, binding = 5) writeonly buffer Output { 1032// float elements[]; 1033// } output_data; 1034// 1035// void main() { 1036// uint x = gl_GlobalInvocationID.x; 1037// output_data.elements[x] = input_data0.elements[x] + input_data1.elements[x] + input_data2.elements[x] + input_data3.elements[x] + input_data4.elements[x]; 1038// } 1039tcu::TestCaseGroup* createDecorationGroupGroup (tcu::TestContext& testCtx) 1040{ 1041 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Test the OpDecorationGroup & OpGroupDecorate instruction")); 1042 ComputeShaderSpec spec; 1043 de::Random rnd (deStringHash(group->getName())); 1044 const int numElements = 100; 1045 vector<float> inputFloats0 (numElements, 0); 1046 vector<float> inputFloats1 (numElements, 0); 1047 vector<float> inputFloats2 (numElements, 0); 1048 vector<float> inputFloats3 (numElements, 0); 1049 vector<float> inputFloats4 (numElements, 0); 1050 vector<float> outputFloats (numElements, 0); 1051 1052 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats0[0], numElements); 1053 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats1[0], numElements); 1054 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats2[0], numElements); 1055 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats3[0], numElements); 1056 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats4[0], numElements); 1057 1058 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 1059 floorAll(inputFloats0); 1060 floorAll(inputFloats1); 1061 floorAll(inputFloats2); 1062 floorAll(inputFloats3); 1063 floorAll(inputFloats4); 1064 1065 for (size_t ndx = 0; ndx < numElements; ++ndx) 1066 outputFloats[ndx] = inputFloats0[ndx] + inputFloats1[ndx] + inputFloats2[ndx] + inputFloats3[ndx] + inputFloats4[ndx]; 1067 1068 spec.assembly = 1069 string(s_ShaderPreamble) + 1070 1071 "OpSource GLSL 430\n" 1072 "OpName %main \"main\"\n" 1073 "OpName %id \"gl_GlobalInvocationID\"\n" 1074 1075 // Not using group decoration on variable. 1076 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1077 // Not using group decoration on type. 1078 "OpDecorate %f32arr ArrayStride 4\n" 1079 1080 "OpDecorate %groups BufferBlock\n" 1081 "OpDecorate %groupm Offset 0\n" 1082 "%groups = OpDecorationGroup\n" 1083 "%groupm = OpDecorationGroup\n" 1084 1085 // Group decoration on multiple structs. 1086 "OpGroupDecorate %groups %outbuf %inbuf0 %inbuf1 %inbuf2 %inbuf3 %inbuf4\n" 1087 // Group decoration on multiple struct members. 1088 "OpGroupMemberDecorate %groupm %outbuf 0 %inbuf0 0 %inbuf1 0 %inbuf2 0 %inbuf3 0 %inbuf4 0\n" 1089 1090 "OpDecorate %group1 DescriptorSet 0\n" 1091 "OpDecorate %group3 DescriptorSet 0\n" 1092 "OpDecorate %group3 NonWritable\n" 1093 "OpDecorate %group3 Restrict\n" 1094 "%group0 = OpDecorationGroup\n" 1095 "%group1 = OpDecorationGroup\n" 1096 "%group3 = OpDecorationGroup\n" 1097 1098 // Applying the same decoration group multiple times. 1099 "OpGroupDecorate %group1 %outdata\n" 1100 "OpGroupDecorate %group1 %outdata\n" 1101 "OpGroupDecorate %group1 %outdata\n" 1102 "OpDecorate %outdata DescriptorSet 0\n" 1103 "OpDecorate %outdata Binding 5\n" 1104 // Applying decoration group containing nothing. 1105 "OpGroupDecorate %group0 %indata0\n" 1106 "OpDecorate %indata0 DescriptorSet 0\n" 1107 "OpDecorate %indata0 Binding 0\n" 1108 // Applying decoration group containing one decoration. 1109 "OpGroupDecorate %group1 %indata1\n" 1110 "OpDecorate %indata1 Binding 1\n" 1111 // Applying decoration group containing multiple decorations. 1112 "OpGroupDecorate %group3 %indata2 %indata3\n" 1113 "OpDecorate %indata2 Binding 2\n" 1114 "OpDecorate %indata3 Binding 3\n" 1115 // Applying multiple decoration groups (with overlapping). 1116 "OpGroupDecorate %group0 %indata4\n" 1117 "OpGroupDecorate %group1 %indata4\n" 1118 "OpGroupDecorate %group3 %indata4\n" 1119 "OpDecorate %indata4 Binding 4\n" 1120 1121 + string(s_CommonTypes) + 1122 1123 "%id = OpVariable %uvec3ptr Input\n" 1124 "%zero = OpConstant %i32 0\n" 1125 1126 "%outbuf = OpTypeStruct %f32arr\n" 1127 "%outbufptr = OpTypePointer Uniform %outbuf\n" 1128 "%outdata = OpVariable %outbufptr Uniform\n" 1129 "%inbuf0 = OpTypeStruct %f32arr\n" 1130 "%inbuf0ptr = OpTypePointer Uniform %inbuf0\n" 1131 "%indata0 = OpVariable %inbuf0ptr Uniform\n" 1132 "%inbuf1 = OpTypeStruct %f32arr\n" 1133 "%inbuf1ptr = OpTypePointer Uniform %inbuf1\n" 1134 "%indata1 = OpVariable %inbuf1ptr Uniform\n" 1135 "%inbuf2 = OpTypeStruct %f32arr\n" 1136 "%inbuf2ptr = OpTypePointer Uniform %inbuf2\n" 1137 "%indata2 = OpVariable %inbuf2ptr Uniform\n" 1138 "%inbuf3 = OpTypeStruct %f32arr\n" 1139 "%inbuf3ptr = OpTypePointer Uniform %inbuf3\n" 1140 "%indata3 = OpVariable %inbuf3ptr Uniform\n" 1141 "%inbuf4 = OpTypeStruct %f32arr\n" 1142 "%inbufptr = OpTypePointer Uniform %inbuf4\n" 1143 "%indata4 = OpVariable %inbufptr Uniform\n" 1144 1145 "%main = OpFunction %void None %voidf\n" 1146 "%label = OpLabel\n" 1147 "%idval = OpLoad %uvec3 %id\n" 1148 "%x = OpCompositeExtract %u32 %idval 0\n" 1149 "%inloc0 = OpAccessChain %f32ptr %indata0 %zero %x\n" 1150 "%inloc1 = OpAccessChain %f32ptr %indata1 %zero %x\n" 1151 "%inloc2 = OpAccessChain %f32ptr %indata2 %zero %x\n" 1152 "%inloc3 = OpAccessChain %f32ptr %indata3 %zero %x\n" 1153 "%inloc4 = OpAccessChain %f32ptr %indata4 %zero %x\n" 1154 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 1155 "%inval0 = OpLoad %f32 %inloc0\n" 1156 "%inval1 = OpLoad %f32 %inloc1\n" 1157 "%inval2 = OpLoad %f32 %inloc2\n" 1158 "%inval3 = OpLoad %f32 %inloc3\n" 1159 "%inval4 = OpLoad %f32 %inloc4\n" 1160 "%add0 = OpFAdd %f32 %inval0 %inval1\n" 1161 "%add1 = OpFAdd %f32 %add0 %inval2\n" 1162 "%add2 = OpFAdd %f32 %add1 %inval3\n" 1163 "%add = OpFAdd %f32 %add2 %inval4\n" 1164 " OpStore %outloc %add\n" 1165 " OpReturn\n" 1166 " OpFunctionEnd\n"; 1167 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats0))); 1168 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats1))); 1169 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats2))); 1170 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats3))); 1171 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats4))); 1172 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 1173 spec.numWorkGroups = IVec3(numElements, 1, 1); 1174 1175 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "decoration group cases", spec)); 1176 1177 return group.release(); 1178} 1179 1180struct SpecConstantTwoIntCase 1181{ 1182 const char* caseName; 1183 const char* scDefinition0; 1184 const char* scDefinition1; 1185 const char* scResultType; 1186 const char* scOperation; 1187 deInt32 scActualValue0; 1188 deInt32 scActualValue1; 1189 const char* resultOperation; 1190 vector<deInt32> expectedOutput; 1191 1192 SpecConstantTwoIntCase (const char* name, 1193 const char* definition0, 1194 const char* definition1, 1195 const char* resultType, 1196 const char* operation, 1197 deInt32 value0, 1198 deInt32 value1, 1199 const char* resultOp, 1200 const vector<deInt32>& output) 1201 : caseName (name) 1202 , scDefinition0 (definition0) 1203 , scDefinition1 (definition1) 1204 , scResultType (resultType) 1205 , scOperation (operation) 1206 , scActualValue0 (value0) 1207 , scActualValue1 (value1) 1208 , resultOperation (resultOp) 1209 , expectedOutput (output) {} 1210}; 1211 1212tcu::TestCaseGroup* createSpecConstantGroup (tcu::TestContext& testCtx) 1213{ 1214 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction")); 1215 vector<SpecConstantTwoIntCase> cases; 1216 de::Random rnd (deStringHash(group->getName())); 1217 const int numElements = 100; 1218 vector<deInt32> inputInts (numElements, 0); 1219 vector<deInt32> outputInts1 (numElements, 0); 1220 vector<deInt32> outputInts2 (numElements, 0); 1221 vector<deInt32> outputInts3 (numElements, 0); 1222 vector<deInt32> outputInts4 (numElements, 0); 1223 const StringTemplate shaderTemplate ( 1224 string(s_ShaderPreamble) + 1225 1226 "OpName %main \"main\"\n" 1227 "OpName %id \"gl_GlobalInvocationID\"\n" 1228 1229 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1230 "OpDecorate %sc_0 SpecId 0\n" 1231 "OpDecorate %sc_1 SpecId 1\n" 1232 "OpDecorate %i32arr ArrayStride 4\n" 1233 1234 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 1235 1236 "%i32ptr = OpTypePointer Uniform %i32\n" 1237 "%i32arr = OpTypeRuntimeArray %i32\n" 1238 "%boolptr = OpTypePointer Uniform %bool\n" 1239 "%boolarr = OpTypeRuntimeArray %bool\n" 1240 "%buf = OpTypeStruct %i32arr\n" 1241 "%bufptr = OpTypePointer Uniform %buf\n" 1242 "%indata = OpVariable %bufptr Uniform\n" 1243 "%outdata = OpVariable %bufptr Uniform\n" 1244 1245 "%id = OpVariable %uvec3ptr Input\n" 1246 "%zero = OpConstant %i32 0\n" 1247 1248 "%sc_0 = OpSpecConstant${SC_DEF0}\n" 1249 "%sc_1 = OpSpecConstant${SC_DEF1}\n" 1250 "%sc_final = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n" 1251 1252 "%main = OpFunction %void None %voidf\n" 1253 "%label = OpLabel\n" 1254 "%idval = OpLoad %uvec3 %id\n" 1255 "%x = OpCompositeExtract %u32 %idval 0\n" 1256 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n" 1257 "%inval = OpLoad %i32 %inloc\n" 1258 "%final = ${GEN_RESULT}\n" 1259 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n" 1260 " OpStore %outloc %final\n" 1261 " OpReturn\n" 1262 " OpFunctionEnd\n"); 1263 1264 fillRandomScalars(rnd, -65536, 65536, &inputInts[0], numElements); 1265 1266 for (size_t ndx = 0; ndx < numElements; ++ndx) 1267 { 1268 outputInts1[ndx] = inputInts[ndx] + 42; 1269 outputInts2[ndx] = inputInts[ndx]; 1270 outputInts3[ndx] = inputInts[ndx] - 11200; 1271 outputInts4[ndx] = inputInts[ndx] + 1; 1272 } 1273 1274 const char addScToInput[] = "OpIAdd %i32 %inval %sc_final"; 1275 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_final %inval %zero"; 1276 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_final %zero %inval"; 1277 1278 cases.push_back(SpecConstantTwoIntCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 62, -20, addScToInput, outputInts1)); 1279 cases.push_back(SpecConstantTwoIntCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 100, 58, addScToInput, outputInts1)); 1280 cases.push_back(SpecConstantTwoIntCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -2, -21, addScToInput, outputInts1)); 1281 cases.push_back(SpecConstantTwoIntCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, -3, addScToInput, outputInts1)); 1282 cases.push_back(SpecConstantTwoIntCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 3, addScToInput, outputInts1)); 1283 cases.push_back(SpecConstantTwoIntCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 7, 3, addScToInput, outputInts4)); 1284 cases.push_back(SpecConstantTwoIntCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 7, 3, addScToInput, outputInts4)); 1285 cases.push_back(SpecConstantTwoIntCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 342, 50, addScToInput, outputInts1)); 1286 cases.push_back(SpecConstantTwoIntCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 42, 63, addScToInput, outputInts1)); 1287 cases.push_back(SpecConstantTwoIntCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 34, 8, addScToInput, outputInts1)); 1288 cases.push_back(SpecConstantTwoIntCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseXor %sc_0 %sc_1", 18, 56, addScToInput, outputInts1)); 1289 cases.push_back(SpecConstantTwoIntCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 168, 2, addScToInput, outputInts1)); 1290 cases.push_back(SpecConstantTwoIntCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", 168, 2, addScToInput, outputInts1)); 1291 cases.push_back(SpecConstantTwoIntCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 21, 1, addScToInput, outputInts1)); 1292 cases.push_back(SpecConstantTwoIntCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputInts2)); 1293 cases.push_back(SpecConstantTwoIntCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputInts2)); 1294 cases.push_back(SpecConstantTwoIntCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2)); 1295 cases.push_back(SpecConstantTwoIntCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputInts2)); 1296 cases.push_back(SpecConstantTwoIntCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputInts2)); 1297 cases.push_back(SpecConstantTwoIntCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputInts2)); 1298 cases.push_back(SpecConstantTwoIntCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputInts2)); 1299 cases.push_back(SpecConstantTwoIntCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputInts2)); 1300 cases.push_back(SpecConstantTwoIntCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputInts2)); 1301 cases.push_back(SpecConstantTwoIntCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2)); 1302 cases.push_back(SpecConstantTwoIntCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2)); 1303 cases.push_back(SpecConstantTwoIntCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputInts2)); 1304 cases.push_back(SpecConstantTwoIntCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputInts2)); 1305 cases.push_back(SpecConstantTwoIntCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -42, 0, addScToInput, outputInts1)); 1306 cases.push_back(SpecConstantTwoIntCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -43, 0, addScToInput, outputInts1)); 1307 cases.push_back(SpecConstantTwoIntCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputInts2)); 1308 cases.push_back(SpecConstantTwoIntCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %zero", 1, 42, addScToInput, outputInts1)); 1309 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths. 1310 1311 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 1312 { 1313 map<string, string> specializations; 1314 ComputeShaderSpec spec; 1315 1316 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0; 1317 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1; 1318 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType; 1319 specializations["SC_OP"] = cases[caseNdx].scOperation; 1320 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation; 1321 1322 spec.assembly = shaderTemplate.specialize(specializations); 1323 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts))); 1324 spec.outputs.push_back(BufferSp(new Int32Buffer(cases[caseNdx].expectedOutput))); 1325 spec.numWorkGroups = IVec3(numElements, 1, 1); 1326 spec.specConstants.push_back(cases[caseNdx].scActualValue0); 1327 spec.specConstants.push_back(cases[caseNdx].scActualValue1); 1328 1329 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].caseName, cases[caseNdx].caseName, spec)); 1330 } 1331 1332 ComputeShaderSpec spec; 1333 1334 spec.assembly = 1335 string(s_ShaderPreamble) + 1336 1337 "OpName %main \"main\"\n" 1338 "OpName %id \"gl_GlobalInvocationID\"\n" 1339 1340 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1341 "OpDecorate %sc_0 SpecId 0\n" 1342 "OpDecorate %sc_1 SpecId 1\n" 1343 "OpDecorate %sc_2 SpecId 2\n" 1344 "OpDecorate %i32arr ArrayStride 4\n" 1345 1346 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 1347 1348 "%ivec3 = OpTypeVector %i32 3\n" 1349 "%i32ptr = OpTypePointer Uniform %i32\n" 1350 "%i32arr = OpTypeRuntimeArray %i32\n" 1351 "%boolptr = OpTypePointer Uniform %bool\n" 1352 "%boolarr = OpTypeRuntimeArray %bool\n" 1353 "%buf = OpTypeStruct %i32arr\n" 1354 "%bufptr = OpTypePointer Uniform %buf\n" 1355 "%indata = OpVariable %bufptr Uniform\n" 1356 "%outdata = OpVariable %bufptr Uniform\n" 1357 1358 "%id = OpVariable %uvec3ptr Input\n" 1359 "%zero = OpConstant %i32 0\n" 1360 "%ivec3_0 = OpConstantComposite %ivec3 %zero %zero %zero\n" 1361 1362 "%sc_0 = OpSpecConstant %i32 0\n" 1363 "%sc_1 = OpSpecConstant %i32 0\n" 1364 "%sc_2 = OpSpecConstant %i32 0\n" 1365 "%sc_vec3_0 = OpSpecConstantOp %ivec3 CompositeInsert %sc_0 %ivec3_0 0\n" // (sc_0, 0, 0) 1366 "%sc_vec3_1 = OpSpecConstantOp %ivec3 CompositeInsert %sc_1 %ivec3_0 1\n" // (0, sc_1, 0) 1367 "%sc_vec3_2 = OpSpecConstantOp %ivec3 CompositeInsert %sc_2 %ivec3_0 2\n" // (0, 0, sc_2) 1368 "%sc_vec3_01 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1) 1369 "%sc_vec3_012 = OpSpecConstantOp %ivec3 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1) 1370 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2 1371 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0 1372 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1 1373 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0) 1374 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n" // (sc_2 - sc_0) * sc_1 1375 1376 "%main = OpFunction %void None %voidf\n" 1377 "%label = OpLabel\n" 1378 "%idval = OpLoad %uvec3 %id\n" 1379 "%x = OpCompositeExtract %u32 %idval 0\n" 1380 "%inloc = OpAccessChain %i32ptr %indata %zero %x\n" 1381 "%inval = OpLoad %i32 %inloc\n" 1382 "%final = OpIAdd %i32 %inval %sc_final\n" 1383 "%outloc = OpAccessChain %i32ptr %outdata %zero %x\n" 1384 " OpStore %outloc %final\n" 1385 " OpReturn\n" 1386 " OpFunctionEnd\n"; 1387 spec.inputs.push_back(BufferSp(new Int32Buffer(inputInts))); 1388 spec.outputs.push_back(BufferSp(new Int32Buffer(outputInts3))); 1389 spec.numWorkGroups = IVec3(numElements, 1, 1); 1390 spec.specConstants.push_back(123); 1391 spec.specConstants.push_back(56); 1392 spec.specConstants.push_back(-77); 1393 1394 group->addChild(new SpvAsmComputeShaderCase(testCtx, "vector_related", "VectorShuffle, CompositeExtract, & CompositeInsert", spec)); 1395 1396 return group.release(); 1397} 1398 1399tcu::TestCaseGroup* createOpPhiGroup (tcu::TestContext& testCtx) 1400{ 1401 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction")); 1402 ComputeShaderSpec spec1; 1403 ComputeShaderSpec spec2; 1404 ComputeShaderSpec spec3; 1405 de::Random rnd (deStringHash(group->getName())); 1406 const int numElements = 100; 1407 vector<float> inputFloats (numElements, 0); 1408 vector<float> outputFloats1 (numElements, 0); 1409 vector<float> outputFloats2 (numElements, 0); 1410 vector<float> outputFloats3 (numElements, 0); 1411 1412 fillRandomScalars(rnd, -300.f, 300.f, &inputFloats[0], numElements); 1413 1414 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 1415 floorAll(inputFloats); 1416 1417 for (size_t ndx = 0; ndx < numElements; ++ndx) 1418 { 1419 switch (ndx % 3) 1420 { 1421 case 0: outputFloats1[ndx] = inputFloats[ndx] + 5.5f; break; 1422 case 1: outputFloats1[ndx] = inputFloats[ndx] + 20.5f; break; 1423 case 2: outputFloats1[ndx] = inputFloats[ndx] + 1.75f; break; 1424 default: break; 1425 } 1426 outputFloats2[ndx] = inputFloats[ndx] + 6.5f * 3; 1427 outputFloats3[ndx] = 8.5f - inputFloats[ndx]; 1428 } 1429 1430 spec1.assembly = 1431 string(s_ShaderPreamble) + 1432 1433 "OpSource GLSL 430\n" 1434 "OpName %main \"main\"\n" 1435 "OpName %id \"gl_GlobalInvocationID\"\n" 1436 1437 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1438 1439 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1440 1441 "%id = OpVariable %uvec3ptr Input\n" 1442 "%zero = OpConstant %i32 0\n" 1443 "%three = OpConstant %u32 3\n" 1444 "%constf5p5 = OpConstant %f32 5.5\n" 1445 "%constf20p5 = OpConstant %f32 20.5\n" 1446 "%constf1p75 = OpConstant %f32 1.75\n" 1447 "%constf8p5 = OpConstant %f32 8.5\n" 1448 "%constf6p5 = OpConstant %f32 6.5\n" 1449 1450 "%main = OpFunction %void None %voidf\n" 1451 "%entry = OpLabel\n" 1452 "%idval = OpLoad %uvec3 %id\n" 1453 "%x = OpCompositeExtract %u32 %idval 0\n" 1454 "%selector = OpUMod %u32 %x %three\n" 1455 " OpSelectionMerge %phi None\n" 1456 " OpSwitch %selector %default 0 %case0 1 %case1 2 %case2\n" 1457 1458 // Case 1 before OpPhi. 1459 "%case1 = OpLabel\n" 1460 " OpBranch %phi\n" 1461 1462 "%default = OpLabel\n" 1463 " OpUnreachable\n" 1464 1465 "%phi = OpLabel\n" 1466 "%operand = OpPhi %f32 %constf1p75 %case2 %constf20p5 %case1 %constf5p5 %case0\n" // not in the order of blocks 1467 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 1468 "%inval = OpLoad %f32 %inloc\n" 1469 "%add = OpFAdd %f32 %inval %operand\n" 1470 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 1471 " OpStore %outloc %add\n" 1472 " OpReturn\n" 1473 1474 // Case 0 after OpPhi. 1475 "%case0 = OpLabel\n" 1476 " OpBranch %phi\n" 1477 1478 1479 // Case 2 after OpPhi. 1480 "%case2 = OpLabel\n" 1481 " OpBranch %phi\n" 1482 1483 " OpFunctionEnd\n"; 1484 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1485 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1))); 1486 spec1.numWorkGroups = IVec3(numElements, 1, 1); 1487 1488 group->addChild(new SpvAsmComputeShaderCase(testCtx, "block", "out-of-order and unreachable blocks for OpPhi", spec1)); 1489 1490 spec2.assembly = 1491 string(s_ShaderPreamble) + 1492 1493 "OpName %main \"main\"\n" 1494 "OpName %id \"gl_GlobalInvocationID\"\n" 1495 1496 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1497 1498 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1499 1500 "%id = OpVariable %uvec3ptr Input\n" 1501 "%zero = OpConstant %i32 0\n" 1502 "%one = OpConstant %i32 1\n" 1503 "%three = OpConstant %i32 3\n" 1504 "%constf6p5 = OpConstant %f32 6.5\n" 1505 1506 "%main = OpFunction %void None %voidf\n" 1507 "%entry = OpLabel\n" 1508 "%idval = OpLoad %uvec3 %id\n" 1509 "%x = OpCompositeExtract %u32 %idval 0\n" 1510 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 1511 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 1512 "%inval = OpLoad %f32 %inloc\n" 1513 " OpBranch %phi\n" 1514 1515 "%phi = OpLabel\n" 1516 "%step = OpPhi %i32 %zero %entry %step_next %phi\n" 1517 "%accum = OpPhi %f32 %inval %entry %accum_next %phi\n" 1518 "%step_next = OpIAdd %i32 %step %one\n" 1519 "%accum_next = OpFAdd %f32 %accum %constf6p5\n" 1520 "%still_loop = OpSLessThan %bool %step %three\n" 1521 " OpLoopMerge %exit %phi None\n" 1522 " OpBranchConditional %still_loop %phi %exit\n" 1523 1524 "%exit = OpLabel\n" 1525 " OpStore %outloc %accum\n" 1526 " OpReturn\n" 1527 " OpFunctionEnd\n"; 1528 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1529 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2))); 1530 spec2.numWorkGroups = IVec3(numElements, 1, 1); 1531 1532 group->addChild(new SpvAsmComputeShaderCase(testCtx, "induction", "The usual way induction variables are handled in LLVM IR", spec2)); 1533 1534 spec3.assembly = 1535 string(s_ShaderPreamble) + 1536 1537 "OpName %main \"main\"\n" 1538 "OpName %id \"gl_GlobalInvocationID\"\n" 1539 1540 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1541 1542 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1543 1544 "%f32ptr_f = OpTypePointer Function %f32\n" 1545 "%id = OpVariable %uvec3ptr Input\n" 1546 "%true = OpConstantTrue %bool\n" 1547 "%false = OpConstantFalse %bool\n" 1548 "%zero = OpConstant %i32 0\n" 1549 "%constf8p5 = OpConstant %f32 8.5\n" 1550 1551 "%main = OpFunction %void None %voidf\n" 1552 "%entry = OpLabel\n" 1553 "%b = OpVariable %f32ptr_f Function %constf8p5\n" 1554 "%idval = OpLoad %uvec3 %id\n" 1555 "%x = OpCompositeExtract %u32 %idval 0\n" 1556 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 1557 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 1558 "%a_init = OpLoad %f32 %inloc\n" 1559 "%b_init = OpLoad %f32 %b\n" 1560 " OpBranch %phi\n" 1561 1562 "%phi = OpLabel\n" 1563 "%still_loop = OpPhi %bool %true %entry %false %phi\n" 1564 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n" 1565 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n" 1566 " OpLoopMerge %exit %phi None\n" 1567 " OpBranchConditional %still_loop %phi %exit\n" 1568 1569 "%exit = OpLabel\n" 1570 "%sub = OpFSub %f32 %a_next %b_next\n" 1571 " OpStore %outloc %sub\n" 1572 " OpReturn\n" 1573 " OpFunctionEnd\n"; 1574 spec3.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1575 spec3.outputs.push_back(BufferSp(new Float32Buffer(outputFloats3))); 1576 spec3.numWorkGroups = IVec3(numElements, 1, 1); 1577 1578 group->addChild(new SpvAsmComputeShaderCase(testCtx, "swap", "Swap the values of two variables using OpPhi", spec3)); 1579 1580 return group.release(); 1581} 1582 1583// Assembly code used for testing block order is based on GLSL source code: 1584// 1585// #version 430 1586// 1587// layout(std140, set = 0, binding = 0) readonly buffer Input { 1588// float elements[]; 1589// } input_data; 1590// layout(std140, set = 0, binding = 1) writeonly buffer Output { 1591// float elements[]; 1592// } output_data; 1593// 1594// void main() { 1595// uint x = gl_GlobalInvocationID.x; 1596// output_data.elements[x] = input_data.elements[x]; 1597// if (x > uint(50)) { 1598// switch (x % uint(3)) { 1599// case 0: output_data.elements[x] += 1.5f; break; 1600// case 1: output_data.elements[x] += 42.f; break; 1601// case 2: output_data.elements[x] -= 27.f; break; 1602// default: break; 1603// } 1604// } else { 1605// output_data.elements[x] = -input_data.elements[x]; 1606// } 1607// } 1608tcu::TestCaseGroup* createBlockOrderGroup (tcu::TestContext& testCtx) 1609{ 1610 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "block_order", "Test block orders")); 1611 ComputeShaderSpec spec; 1612 de::Random rnd (deStringHash(group->getName())); 1613 const int numElements = 100; 1614 vector<float> inputFloats (numElements, 0); 1615 vector<float> outputFloats (numElements, 0); 1616 1617 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); 1618 1619 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 1620 floorAll(inputFloats); 1621 1622 for (size_t ndx = 0; ndx <= 50; ++ndx) 1623 outputFloats[ndx] = -inputFloats[ndx]; 1624 1625 for (size_t ndx = 51; ndx < numElements; ++ndx) 1626 { 1627 switch (ndx % 3) 1628 { 1629 case 0: outputFloats[ndx] = inputFloats[ndx] + 1.5f; break; 1630 case 1: outputFloats[ndx] = inputFloats[ndx] + 42.f; break; 1631 case 2: outputFloats[ndx] = inputFloats[ndx] - 27.f; break; 1632 default: break; 1633 } 1634 } 1635 1636 spec.assembly = 1637 string(s_ShaderPreamble) + 1638 1639 "OpSource GLSL 430\n" 1640 "OpName %main \"main\"\n" 1641 "OpName %id \"gl_GlobalInvocationID\"\n" 1642 1643 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1644 1645 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 1646 1647 "%u32ptr = OpTypePointer Function %u32\n" 1648 "%u32ptr_input = OpTypePointer Input %u32\n" 1649 1650 + string(s_InputOutputBuffer) + 1651 1652 "%id = OpVariable %uvec3ptr Input\n" 1653 "%zero = OpConstant %i32 0\n" 1654 "%const3 = OpConstant %u32 3\n" 1655 "%const50 = OpConstant %u32 50\n" 1656 "%constf1p5 = OpConstant %f32 1.5\n" 1657 "%constf27 = OpConstant %f32 27.0\n" 1658 "%constf42 = OpConstant %f32 42.0\n" 1659 1660 "%main = OpFunction %void None %voidf\n" 1661 1662 // entry block. 1663 "%entry = OpLabel\n" 1664 1665 // Create a temporary variable to hold the value of gl_GlobalInvocationID.x. 1666 "%xvar = OpVariable %u32ptr Function\n" 1667 "%xptr = OpAccessChain %u32ptr_input %id %zero\n" 1668 "%x = OpLoad %u32 %xptr\n" 1669 " OpStore %xvar %x\n" 1670 1671 "%cmp = OpUGreaterThan %bool %x %const50\n" 1672 " OpSelectionMerge %if_merge None\n" 1673 " OpBranchConditional %cmp %if_true %if_false\n" 1674 1675 // Merge block for switch-statement: placed at the beginning. 1676 "%switch_merge = OpLabel\n" 1677 " OpBranch %if_merge\n" 1678 1679 // Case 1 for switch-statement. 1680 "%case1 = OpLabel\n" 1681 "%x_1 = OpLoad %u32 %xvar\n" 1682 "%inloc_1 = OpAccessChain %f32ptr %indata %zero %x_1\n" 1683 "%inval_1 = OpLoad %f32 %inloc_1\n" 1684 "%addf42 = OpFAdd %f32 %inval_1 %constf42\n" 1685 "%outloc_1 = OpAccessChain %f32ptr %outdata %zero %x_1\n" 1686 " OpStore %outloc_1 %addf42\n" 1687 " OpBranch %switch_merge\n" 1688 1689 // False branch for if-statement: placed in the middle of switch cases and before true branch. 1690 "%if_false = OpLabel\n" 1691 "%x_f = OpLoad %u32 %xvar\n" 1692 "%inloc_f = OpAccessChain %f32ptr %indata %zero %x_f\n" 1693 "%inval_f = OpLoad %f32 %inloc_f\n" 1694 "%negate = OpFNegate %f32 %inval_f\n" 1695 "%outloc_f = OpAccessChain %f32ptr %outdata %zero %x_f\n" 1696 " OpStore %outloc_f %negate\n" 1697 " OpBranch %if_merge\n" 1698 1699 // Merge block for if-statement: placed in the middle of true and false branch. 1700 "%if_merge = OpLabel\n" 1701 " OpReturn\n" 1702 1703 // True branch for if-statement: placed in the middle of swtich cases and after the false branch. 1704 "%if_true = OpLabel\n" 1705 "%xval_t = OpLoad %u32 %xvar\n" 1706 "%mod = OpUMod %u32 %xval_t %const3\n" 1707 " OpSelectionMerge %switch_merge None\n" 1708 " OpSwitch %mod %default 0 %case0 1 %case1 2 %case2\n" 1709 1710 // Case 2 for switch-statement. 1711 "%case2 = OpLabel\n" 1712 "%x_2 = OpLoad %u32 %xvar\n" 1713 "%inloc_2 = OpAccessChain %f32ptr %indata %zero %x_2\n" 1714 "%inval_2 = OpLoad %f32 %inloc_2\n" 1715 "%subf27 = OpFSub %f32 %inval_2 %constf27\n" 1716 "%outloc_2 = OpAccessChain %f32ptr %outdata %zero %x_2\n" 1717 " OpStore %outloc_2 %subf27\n" 1718 " OpBranch %switch_merge\n" 1719 1720 // Default case for switch-statement: placed in the middle of normal cases. 1721 "%default = OpLabel\n" 1722 " OpBranch %switch_merge\n" 1723 1724 // Case 0 for switch-statement: out of order. 1725 "%case0 = OpLabel\n" 1726 "%x_0 = OpLoad %u32 %xvar\n" 1727 "%inloc_0 = OpAccessChain %f32ptr %indata %zero %x_0\n" 1728 "%inval_0 = OpLoad %f32 %inloc_0\n" 1729 "%addf1p5 = OpFAdd %f32 %inval_0 %constf1p5\n" 1730 "%outloc_0 = OpAccessChain %f32ptr %outdata %zero %x_0\n" 1731 " OpStore %outloc_0 %addf1p5\n" 1732 " OpBranch %switch_merge\n" 1733 1734 " OpFunctionEnd\n"; 1735 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1736 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 1737 spec.numWorkGroups = IVec3(numElements, 1, 1); 1738 1739 group->addChild(new SpvAsmComputeShaderCase(testCtx, "all", "various out-of-order blocks", spec)); 1740 1741 return group.release(); 1742} 1743 1744tcu::TestCaseGroup* createMultipleShaderGroup (tcu::TestContext& testCtx) 1745{ 1746 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "multiple_shaders", "Test multiple shaders in the same module")); 1747 ComputeShaderSpec spec1; 1748 ComputeShaderSpec spec2; 1749 de::Random rnd (deStringHash(group->getName())); 1750 const int numElements = 100; 1751 vector<float> inputFloats (numElements, 0); 1752 vector<float> outputFloats1 (numElements, 0); 1753 vector<float> outputFloats2 (numElements, 0); 1754 fillRandomScalars(rnd, -500.f, 500.f, &inputFloats[0], numElements); 1755 1756 for (size_t ndx = 0; ndx < numElements; ++ndx) 1757 { 1758 outputFloats1[ndx] = inputFloats[ndx] + inputFloats[ndx]; 1759 outputFloats2[ndx] = -inputFloats[ndx]; 1760 } 1761 1762 const string assembly( 1763 "OpCapability Shader\n" 1764 "OpCapability ClipDistance\n" 1765 "OpMemoryModel Logical GLSL450\n" 1766 "OpEntryPoint GLCompute %comp_main1 \"entrypoint1\" %id\n" 1767 "OpEntryPoint GLCompute %comp_main2 \"entrypoint2\" %id\n" 1768 // A module cannot have two OpEntryPoint instructions with the same Execution Model and the same Name string. 1769 "OpEntryPoint Vertex %vert_main \"entrypoint2\" %vert_builtins %vertexIndex %instanceIndex\n" 1770 "OpExecutionMode %comp_main1 LocalSize 1 1 1\n" 1771 "OpExecutionMode %comp_main2 LocalSize 1 1 1\n" 1772 1773 "OpName %comp_main1 \"entrypoint1\"\n" 1774 "OpName %comp_main2 \"entrypoint2\"\n" 1775 "OpName %vert_main \"entrypoint2\"\n" 1776 "OpName %id \"gl_GlobalInvocationID\"\n" 1777 "OpName %vert_builtin_st \"gl_PerVertex\"\n" 1778 "OpName %vertexIndex \"gl_VertexIndex\"\n" 1779 "OpName %instanceIndex \"gl_InstanceIndex\"\n" 1780 "OpMemberName %vert_builtin_st 0 \"gl_Position\"\n" 1781 "OpMemberName %vert_builtin_st 1 \"gl_PointSize\"\n" 1782 "OpMemberName %vert_builtin_st 2 \"gl_ClipDistance\"\n" 1783 1784 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1785 "OpDecorate %vertexIndex BuiltIn VertexIndex\n" 1786 "OpDecorate %instanceIndex BuiltIn InstanceIndex\n" 1787 "OpDecorate %vert_builtin_st Block\n" 1788 "OpMemberDecorate %vert_builtin_st 0 BuiltIn Position\n" 1789 "OpMemberDecorate %vert_builtin_st 1 BuiltIn PointSize\n" 1790 "OpMemberDecorate %vert_builtin_st 2 BuiltIn ClipDistance\n" 1791 1792 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1793 1794 "%zero = OpConstant %i32 0\n" 1795 "%one = OpConstant %u32 1\n" 1796 "%c_f32_1 = OpConstant %f32 1\n" 1797 1798 "%i32ptr = OpTypePointer Input %i32\n" 1799 "%vec4 = OpTypeVector %f32 4\n" 1800 "%vec4ptr = OpTypePointer Output %vec4\n" 1801 "%f32arr1 = OpTypeArray %f32 %one\n" 1802 "%vert_builtin_st = OpTypeStruct %vec4 %f32 %f32arr1\n" 1803 "%vert_builtin_st_ptr = OpTypePointer Output %vert_builtin_st\n" 1804 "%vert_builtins = OpVariable %vert_builtin_st_ptr Output\n" 1805 1806 "%id = OpVariable %uvec3ptr Input\n" 1807 "%vertexIndex = OpVariable %i32ptr Input\n" 1808 "%instanceIndex = OpVariable %i32ptr Input\n" 1809 "%c_vec4_1 = OpConstantComposite %vec4 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" 1810 1811 // gl_Position = vec4(1.); 1812 "%vert_main = OpFunction %void None %voidf\n" 1813 "%vert_entry = OpLabel\n" 1814 "%position = OpAccessChain %vec4ptr %vert_builtins %zero\n" 1815 " OpStore %position %c_vec4_1\n" 1816 " OpReturn\n" 1817 " OpFunctionEnd\n" 1818 1819 // Double inputs. 1820 "%comp_main1 = OpFunction %void None %voidf\n" 1821 "%comp1_entry = OpLabel\n" 1822 "%idval1 = OpLoad %uvec3 %id\n" 1823 "%x1 = OpCompositeExtract %u32 %idval1 0\n" 1824 "%inloc1 = OpAccessChain %f32ptr %indata %zero %x1\n" 1825 "%inval1 = OpLoad %f32 %inloc1\n" 1826 "%add = OpFAdd %f32 %inval1 %inval1\n" 1827 "%outloc1 = OpAccessChain %f32ptr %outdata %zero %x1\n" 1828 " OpStore %outloc1 %add\n" 1829 " OpReturn\n" 1830 " OpFunctionEnd\n" 1831 1832 // Negate inputs. 1833 "%comp_main2 = OpFunction %void None %voidf\n" 1834 "%comp2_entry = OpLabel\n" 1835 "%idval2 = OpLoad %uvec3 %id\n" 1836 "%x2 = OpCompositeExtract %u32 %idval2 0\n" 1837 "%inloc2 = OpAccessChain %f32ptr %indata %zero %x2\n" 1838 "%inval2 = OpLoad %f32 %inloc2\n" 1839 "%neg = OpFNegate %f32 %inval2\n" 1840 "%outloc2 = OpAccessChain %f32ptr %outdata %zero %x2\n" 1841 " OpStore %outloc2 %neg\n" 1842 " OpReturn\n" 1843 " OpFunctionEnd\n"); 1844 1845 spec1.assembly = assembly; 1846 spec1.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1847 spec1.outputs.push_back(BufferSp(new Float32Buffer(outputFloats1))); 1848 spec1.numWorkGroups = IVec3(numElements, 1, 1); 1849 spec1.entryPoint = "entrypoint1"; 1850 1851 spec2.assembly = assembly; 1852 spec2.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 1853 spec2.outputs.push_back(BufferSp(new Float32Buffer(outputFloats2))); 1854 spec2.numWorkGroups = IVec3(numElements, 1, 1); 1855 spec2.entryPoint = "entrypoint2"; 1856 1857 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader1", "multiple shaders in the same module", spec1)); 1858 group->addChild(new SpvAsmComputeShaderCase(testCtx, "shader2", "multiple shaders in the same module", spec2)); 1859 1860 return group.release(); 1861} 1862 1863inline std::string makeLongUTF8String (size_t num4ByteChars) 1864{ 1865 // An example of a longest valid UTF-8 character. Be explicit about the 1866 // character type because Microsoft compilers can otherwise interpret the 1867 // character string as being over wide (16-bit) characters. Ideally, we 1868 // would just use a C++11 UTF-8 string literal, but we want to support older 1869 // Microsoft compilers. 1870 const std::basic_string<char> earthAfrica("\xF0\x9F\x8C\x8D"); 1871 std::string longString; 1872 longString.reserve(num4ByteChars * 4); 1873 for (size_t count = 0; count < num4ByteChars; count++) 1874 { 1875 longString += earthAfrica; 1876 } 1877 return longString; 1878} 1879 1880tcu::TestCaseGroup* createOpSourceGroup (tcu::TestContext& testCtx) 1881{ 1882 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsource", "Tests the OpSource & OpSourceContinued instruction")); 1883 vector<CaseParameter> cases; 1884 de::Random rnd (deStringHash(group->getName())); 1885 const int numElements = 100; 1886 vector<float> positiveFloats (numElements, 0); 1887 vector<float> negativeFloats (numElements, 0); 1888 const StringTemplate shaderTemplate ( 1889 "OpCapability Shader\n" 1890 "OpMemoryModel Logical GLSL450\n" 1891 1892 "OpEntryPoint GLCompute %main \"main\" %id\n" 1893 "OpExecutionMode %main LocalSize 1 1 1\n" 1894 1895 "${SOURCE}\n" 1896 1897 "OpName %main \"main\"\n" 1898 "OpName %id \"gl_GlobalInvocationID\"\n" 1899 1900 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1901 1902 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1903 1904 "%id = OpVariable %uvec3ptr Input\n" 1905 "%zero = OpConstant %i32 0\n" 1906 1907 "%main = OpFunction %void None %voidf\n" 1908 "%label = OpLabel\n" 1909 "%idval = OpLoad %uvec3 %id\n" 1910 "%x = OpCompositeExtract %u32 %idval 0\n" 1911 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 1912 "%inval = OpLoad %f32 %inloc\n" 1913 "%neg = OpFNegate %f32 %inval\n" 1914 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 1915 " OpStore %outloc %neg\n" 1916 " OpReturn\n" 1917 " OpFunctionEnd\n"); 1918 1919 cases.push_back(CaseParameter("unknown_source", "OpSource Unknown 0")); 1920 cases.push_back(CaseParameter("wrong_source", "OpSource OpenCL_C 210")); 1921 cases.push_back(CaseParameter("normal_filename", "%fname = OpString \"filename\"\n" 1922 "OpSource GLSL 430 %fname")); 1923 cases.push_back(CaseParameter("empty_filename", "%fname = OpString \"\"\n" 1924 "OpSource GLSL 430 %fname")); 1925 cases.push_back(CaseParameter("normal_source_code", "%fname = OpString \"filename\"\n" 1926 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"")); 1927 cases.push_back(CaseParameter("empty_source_code", "%fname = OpString \"filename\"\n" 1928 "OpSource GLSL 430 %fname \"\"")); 1929 cases.push_back(CaseParameter("long_source_code", "%fname = OpString \"filename\"\n" 1930 "OpSource GLSL 430 %fname \"" + makeLongUTF8String(65530) + "ccc\"")); // word count: 65535 1931 cases.push_back(CaseParameter("utf8_source_code", "%fname = OpString \"filename\"\n" 1932 "OpSource GLSL 430 %fname \"\xE2\x98\x82\xE2\x98\x85\"")); // umbrella & black star symbol 1933 cases.push_back(CaseParameter("normal_sourcecontinued", "%fname = OpString \"filename\"\n" 1934 "OpSource GLSL 430 %fname \"#version 430\nvo\"\n" 1935 "OpSourceContinued \"id main() {}\"")); 1936 cases.push_back(CaseParameter("empty_sourcecontinued", "%fname = OpString \"filename\"\n" 1937 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n" 1938 "OpSourceContinued \"\"")); 1939 cases.push_back(CaseParameter("long_sourcecontinued", "%fname = OpString \"filename\"\n" 1940 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n" 1941 "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\"")); // word count: 65535 1942 cases.push_back(CaseParameter("utf8_sourcecontinued", "%fname = OpString \"filename\"\n" 1943 "OpSource GLSL 430 %fname \"#version 430\nvoid main() {}\"\n" 1944 "OpSourceContinued \"\xE2\x98\x8E\xE2\x9A\x91\"")); // white telephone & black flag symbol 1945 cases.push_back(CaseParameter("multi_sourcecontinued", "%fname = OpString \"filename\"\n" 1946 "OpSource GLSL 430 %fname \"#version 430\n\"\n" 1947 "OpSourceContinued \"void\"\n" 1948 "OpSourceContinued \"main()\"\n" 1949 "OpSourceContinued \"{}\"")); 1950 cases.push_back(CaseParameter("empty_source_before_sourcecontinued", "%fname = OpString \"filename\"\n" 1951 "OpSource GLSL 430 %fname \"\"\n" 1952 "OpSourceContinued \"#version 430\nvoid main() {}\"")); 1953 1954 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 1955 1956 for (size_t ndx = 0; ndx < numElements; ++ndx) 1957 negativeFloats[ndx] = -positiveFloats[ndx]; 1958 1959 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 1960 { 1961 map<string, string> specializations; 1962 ComputeShaderSpec spec; 1963 1964 specializations["SOURCE"] = cases[caseNdx].param; 1965 spec.assembly = shaderTemplate.specialize(specializations); 1966 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 1967 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 1968 spec.numWorkGroups = IVec3(numElements, 1, 1); 1969 1970 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 1971 } 1972 1973 return group.release(); 1974} 1975 1976tcu::TestCaseGroup* createOpSourceExtensionGroup (tcu::TestContext& testCtx) 1977{ 1978 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opsourceextension", "Tests the OpSource instruction")); 1979 vector<CaseParameter> cases; 1980 de::Random rnd (deStringHash(group->getName())); 1981 const int numElements = 100; 1982 vector<float> inputFloats (numElements, 0); 1983 vector<float> outputFloats (numElements, 0); 1984 const StringTemplate shaderTemplate ( 1985 string(s_ShaderPreamble) + 1986 1987 "OpSourceExtension \"${EXTENSION}\"\n" 1988 1989 "OpName %main \"main\"\n" 1990 "OpName %id \"gl_GlobalInvocationID\"\n" 1991 1992 "OpDecorate %id BuiltIn GlobalInvocationId\n" 1993 1994 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 1995 1996 "%id = OpVariable %uvec3ptr Input\n" 1997 "%zero = OpConstant %i32 0\n" 1998 1999 "%main = OpFunction %void None %voidf\n" 2000 "%label = OpLabel\n" 2001 "%idval = OpLoad %uvec3 %id\n" 2002 "%x = OpCompositeExtract %u32 %idval 0\n" 2003 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2004 "%inval = OpLoad %f32 %inloc\n" 2005 "%neg = OpFNegate %f32 %inval\n" 2006 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2007 " OpStore %outloc %neg\n" 2008 " OpReturn\n" 2009 " OpFunctionEnd\n"); 2010 2011 cases.push_back(CaseParameter("empty_extension", "")); 2012 cases.push_back(CaseParameter("real_extension", "GL_ARB_texture_rectangle")); 2013 cases.push_back(CaseParameter("fake_extension", "GL_ARB_im_the_ultimate_extension")); 2014 cases.push_back(CaseParameter("utf8_extension", "GL_ARB_\xE2\x98\x82\xE2\x98\x85")); 2015 cases.push_back(CaseParameter("long_extension", makeLongUTF8String(65533) + "ccc")); // word count: 65535 2016 2017 fillRandomScalars(rnd, -200.f, 200.f, &inputFloats[0], numElements); 2018 2019 for (size_t ndx = 0; ndx < numElements; ++ndx) 2020 outputFloats[ndx] = -inputFloats[ndx]; 2021 2022 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 2023 { 2024 map<string, string> specializations; 2025 ComputeShaderSpec spec; 2026 2027 specializations["EXTENSION"] = cases[caseNdx].param; 2028 spec.assembly = shaderTemplate.specialize(specializations); 2029 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 2030 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 2031 spec.numWorkGroups = IVec3(numElements, 1, 1); 2032 2033 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 2034 } 2035 2036 return group.release(); 2037} 2038 2039// Checks that a compute shader can generate a constant null value of various types, without exercising a computation on it. 2040tcu::TestCaseGroup* createOpConstantNullGroup (tcu::TestContext& testCtx) 2041{ 2042 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnull", "Tests the OpConstantNull instruction")); 2043 vector<CaseParameter> cases; 2044 de::Random rnd (deStringHash(group->getName())); 2045 const int numElements = 100; 2046 vector<float> positiveFloats (numElements, 0); 2047 vector<float> negativeFloats (numElements, 0); 2048 const StringTemplate shaderTemplate ( 2049 string(s_ShaderPreamble) + 2050 2051 "OpSource GLSL 430\n" 2052 "OpName %main \"main\"\n" 2053 "OpName %id \"gl_GlobalInvocationID\"\n" 2054 2055 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2056 2057 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2058 2059 "${TYPE}\n" 2060 "%null = OpConstantNull %type\n" 2061 2062 "%id = OpVariable %uvec3ptr Input\n" 2063 "%zero = OpConstant %i32 0\n" 2064 2065 "%main = OpFunction %void None %voidf\n" 2066 "%label = OpLabel\n" 2067 "%idval = OpLoad %uvec3 %id\n" 2068 "%x = OpCompositeExtract %u32 %idval 0\n" 2069 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2070 "%inval = OpLoad %f32 %inloc\n" 2071 "%neg = OpFNegate %f32 %inval\n" 2072 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2073 " OpStore %outloc %neg\n" 2074 " OpReturn\n" 2075 " OpFunctionEnd\n"); 2076 2077 cases.push_back(CaseParameter("bool", "%type = OpTypeBool")); 2078 cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1")); 2079 cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0")); 2080 cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32")); 2081 cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4")); 2082 cases.push_back(CaseParameter("vec3bool", "%type = OpTypeVector %bool 3")); 2083 cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2")); 2084 cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %fvec3 3")); 2085 cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n" 2086 "%type = OpTypeArray %i32 %100")); 2087 cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32")); 2088 cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32")); 2089 2090 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 2091 2092 for (size_t ndx = 0; ndx < numElements; ++ndx) 2093 negativeFloats[ndx] = -positiveFloats[ndx]; 2094 2095 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 2096 { 2097 map<string, string> specializations; 2098 ComputeShaderSpec spec; 2099 2100 specializations["TYPE"] = cases[caseNdx].param; 2101 spec.assembly = shaderTemplate.specialize(specializations); 2102 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 2103 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 2104 spec.numWorkGroups = IVec3(numElements, 1, 1); 2105 2106 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 2107 } 2108 2109 return group.release(); 2110} 2111 2112// Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it. 2113tcu::TestCaseGroup* createOpConstantCompositeGroup (tcu::TestContext& testCtx) 2114{ 2115 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "Tests the OpConstantComposite instruction")); 2116 vector<CaseParameter> cases; 2117 de::Random rnd (deStringHash(group->getName())); 2118 const int numElements = 100; 2119 vector<float> positiveFloats (numElements, 0); 2120 vector<float> negativeFloats (numElements, 0); 2121 const StringTemplate shaderTemplate ( 2122 string(s_ShaderPreamble) + 2123 2124 "OpSource GLSL 430\n" 2125 "OpName %main \"main\"\n" 2126 "OpName %id \"gl_GlobalInvocationID\"\n" 2127 2128 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2129 2130 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2131 2132 "%id = OpVariable %uvec3ptr Input\n" 2133 "%zero = OpConstant %i32 0\n" 2134 2135 "${CONSTANT}\n" 2136 2137 "%main = OpFunction %void None %voidf\n" 2138 "%label = OpLabel\n" 2139 "%idval = OpLoad %uvec3 %id\n" 2140 "%x = OpCompositeExtract %u32 %idval 0\n" 2141 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2142 "%inval = OpLoad %f32 %inloc\n" 2143 "%neg = OpFNegate %f32 %inval\n" 2144 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2145 " OpStore %outloc %neg\n" 2146 " OpReturn\n" 2147 " OpFunctionEnd\n"); 2148 2149 cases.push_back(CaseParameter("vector", "%five = OpConstant %u32 5\n" 2150 "%const = OpConstantComposite %uvec3 %five %zero %five")); 2151 cases.push_back(CaseParameter("matrix", "%m3fvec3 = OpTypeMatrix %fvec3 3\n" 2152 "%ten = OpConstant %f32 10.\n" 2153 "%fzero = OpConstant %f32 0.\n" 2154 "%vec = OpConstantComposite %fvec3 %ten %fzero %ten\n" 2155 "%mat = OpConstantComposite %m3fvec3 %vec %vec %vec")); 2156 cases.push_back(CaseParameter("struct", "%m2vec3 = OpTypeMatrix %fvec3 2\n" 2157 "%struct = OpTypeStruct %i32 %f32 %fvec3 %m2vec3\n" 2158 "%fzero = OpConstant %f32 0.\n" 2159 "%one = OpConstant %f32 1.\n" 2160 "%point5 = OpConstant %f32 0.5\n" 2161 "%vec = OpConstantComposite %fvec3 %one %one %fzero\n" 2162 "%mat = OpConstantComposite %m2vec3 %vec %vec\n" 2163 "%const = OpConstantComposite %struct %zero %point5 %vec %mat")); 2164 cases.push_back(CaseParameter("nested_struct", "%st1 = OpTypeStruct %u32 %f32\n" 2165 "%st2 = OpTypeStruct %i32 %i32\n" 2166 "%struct = OpTypeStruct %st1 %st2\n" 2167 "%point5 = OpConstant %f32 0.5\n" 2168 "%one = OpConstant %u32 1\n" 2169 "%ten = OpConstant %i32 10\n" 2170 "%st1val = OpConstantComposite %st1 %one %point5\n" 2171 "%st2val = OpConstantComposite %st2 %ten %ten\n" 2172 "%const = OpConstantComposite %struct %st1val %st2val")); 2173 2174 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 2175 2176 for (size_t ndx = 0; ndx < numElements; ++ndx) 2177 negativeFloats[ndx] = -positiveFloats[ndx]; 2178 2179 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 2180 { 2181 map<string, string> specializations; 2182 ComputeShaderSpec spec; 2183 2184 specializations["CONSTANT"] = cases[caseNdx].param; 2185 spec.assembly = shaderTemplate.specialize(specializations); 2186 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 2187 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 2188 spec.numWorkGroups = IVec3(numElements, 1, 1); 2189 2190 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 2191 } 2192 2193 return group.release(); 2194} 2195 2196// Creates a floating point number with the given exponent, and significand 2197// bits set. It can only create normalized numbers. Only the least significant 2198// 24 bits of the significand will be examined. The final bit of the 2199// significand will also be ignored. This allows alignment to be written 2200// similarly to C99 hex-floats. 2201// For example if you wanted to write 0x1.7f34p-12 you would call 2202// constructNormalizedFloat(-12, 0x7f3400) 2203float constructNormalizedFloat (deInt32 exponent, deUint32 significand) 2204{ 2205 float f = 1.0f; 2206 2207 for (deInt32 idx = 0; idx < 23; ++idx) 2208 { 2209 f += ((significand & 0x800000) == 0) ? 0.f : std::ldexp(1.0f, -(idx + 1)); 2210 significand <<= 1; 2211 } 2212 2213 return std::ldexp(f, exponent); 2214} 2215 2216// Compare instruction for the OpQuantizeF16 compute exact case. 2217// Returns true if the output is what is expected from the test case. 2218bool compareOpQuantizeF16ComputeExactCase (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs) 2219{ 2220 if (outputAllocs.size() != 1) 2221 return false; 2222 2223 // We really just need this for size because we cannot compare Nans. 2224 const BufferSp& expectedOutput = expectedOutputs[0]; 2225 const float* outputAsFloat = static_cast<const float*>(outputAllocs[0]->getHostPtr());; 2226 2227 if (expectedOutput->getNumBytes() != 4*sizeof(float)) { 2228 return false; 2229 } 2230 2231 if (*outputAsFloat != constructNormalizedFloat(8, 0x304000) && 2232 *outputAsFloat != constructNormalizedFloat(8, 0x300000)) { 2233 return false; 2234 } 2235 outputAsFloat++; 2236 2237 if (*outputAsFloat != -constructNormalizedFloat(-7, 0x600000) && 2238 *outputAsFloat != -constructNormalizedFloat(-7, 0x604000)) { 2239 return false; 2240 } 2241 outputAsFloat++; 2242 2243 if (*outputAsFloat != constructNormalizedFloat(2, 0x01C000) && 2244 *outputAsFloat != constructNormalizedFloat(2, 0x020000)) { 2245 return false; 2246 } 2247 outputAsFloat++; 2248 2249 if (*outputAsFloat != constructNormalizedFloat(1, 0xFFC000) && 2250 *outputAsFloat != constructNormalizedFloat(2, 0x000000)) { 2251 return false; 2252 } 2253 2254 return true; 2255} 2256 2257// Checks that every output from a test-case is a float NaN. 2258bool compareNan (const std::vector<BufferSp>&, const vector<AllocationSp>& outputAllocs, const std::vector<BufferSp>& expectedOutputs) 2259{ 2260 if (outputAllocs.size() != 1) 2261 return false; 2262 2263 // We really just need this for size because we cannot compare Nans. 2264 const BufferSp& expectedOutput = expectedOutputs[0]; 2265 const float* output_as_float = static_cast<const float*>(outputAllocs[0]->getHostPtr());; 2266 2267 for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx) 2268 { 2269 if (!isnan(output_as_float[idx])) 2270 { 2271 return false; 2272 } 2273 } 2274 2275 return true; 2276} 2277 2278// Checks that a compute shader can generate a constant composite value of various types, without exercising a computation on it. 2279tcu::TestCaseGroup* createOpQuantizeToF16Group (tcu::TestContext& testCtx) 2280{ 2281 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opquantize", "Tests the OpQuantizeToF16 instruction")); 2282 2283 const std::string shader ( 2284 string(s_ShaderPreamble) + 2285 2286 "OpSource GLSL 430\n" 2287 "OpName %main \"main\"\n" 2288 "OpName %id \"gl_GlobalInvocationID\"\n" 2289 2290 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2291 2292 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2293 2294 "%id = OpVariable %uvec3ptr Input\n" 2295 "%zero = OpConstant %i32 0\n" 2296 2297 "%main = OpFunction %void None %voidf\n" 2298 "%label = OpLabel\n" 2299 "%idval = OpLoad %uvec3 %id\n" 2300 "%x = OpCompositeExtract %u32 %idval 0\n" 2301 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2302 "%inval = OpLoad %f32 %inloc\n" 2303 "%quant = OpQuantizeToF16 %f32 %inval\n" 2304 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2305 " OpStore %outloc %quant\n" 2306 " OpReturn\n" 2307 " OpFunctionEnd\n"); 2308 2309 { 2310 ComputeShaderSpec spec; 2311 const deUint32 numElements = 100; 2312 vector<float> infinities; 2313 vector<float> results; 2314 2315 infinities.reserve(numElements); 2316 results.reserve(numElements); 2317 2318 for (size_t idx = 0; idx < numElements; ++idx) 2319 { 2320 switch(idx % 4) 2321 { 2322 case 0: 2323 infinities.push_back(std::numeric_limits<float>::infinity()); 2324 results.push_back(std::numeric_limits<float>::infinity()); 2325 break; 2326 case 1: 2327 infinities.push_back(-std::numeric_limits<float>::infinity()); 2328 results.push_back(-std::numeric_limits<float>::infinity()); 2329 break; 2330 case 2: 2331 infinities.push_back(std::ldexp(1.0f, 16)); 2332 results.push_back(std::numeric_limits<float>::infinity()); 2333 break; 2334 case 3: 2335 infinities.push_back(std::ldexp(-1.0f, 32)); 2336 results.push_back(-std::numeric_limits<float>::infinity()); 2337 break; 2338 } 2339 } 2340 2341 spec.assembly = shader; 2342 spec.inputs.push_back(BufferSp(new Float32Buffer(infinities))); 2343 spec.outputs.push_back(BufferSp(new Float32Buffer(results))); 2344 spec.numWorkGroups = IVec3(numElements, 1, 1); 2345 2346 group->addChild(new SpvAsmComputeShaderCase( 2347 testCtx, "infinities", "Check that infinities propagated and created", spec)); 2348 } 2349 2350 { 2351 ComputeShaderSpec spec; 2352 vector<float> nans; 2353 const deUint32 numElements = 100; 2354 2355 nans.reserve(numElements); 2356 2357 for (size_t idx = 0; idx < numElements; ++idx) 2358 { 2359 if (idx % 2 == 0) 2360 { 2361 nans.push_back(std::numeric_limits<float>::quiet_NaN()); 2362 } 2363 else 2364 { 2365 nans.push_back(-std::numeric_limits<float>::quiet_NaN()); 2366 } 2367 } 2368 2369 spec.assembly = shader; 2370 spec.inputs.push_back(BufferSp(new Float32Buffer(nans))); 2371 spec.outputs.push_back(BufferSp(new Float32Buffer(nans))); 2372 spec.numWorkGroups = IVec3(numElements, 1, 1); 2373 spec.verifyIO = &compareNan; 2374 2375 group->addChild(new SpvAsmComputeShaderCase( 2376 testCtx, "propagated_nans", "Check that nans are propagated", spec)); 2377 } 2378 2379 { 2380 ComputeShaderSpec spec; 2381 vector<float> small; 2382 vector<float> zeros; 2383 const deUint32 numElements = 100; 2384 2385 small.reserve(numElements); 2386 zeros.reserve(numElements); 2387 2388 for (size_t idx = 0; idx < numElements; ++idx) 2389 { 2390 switch(idx % 6) 2391 { 2392 case 0: 2393 small.push_back(0.f); 2394 zeros.push_back(0.f); 2395 break; 2396 case 1: 2397 small.push_back(-0.f); 2398 zeros.push_back(-0.f); 2399 break; 2400 case 2: 2401 small.push_back(std::ldexp(1.0f, -16)); 2402 zeros.push_back(0.f); 2403 break; 2404 case 3: 2405 small.push_back(std::ldexp(-1.0f, -32)); 2406 zeros.push_back(-0.f); 2407 break; 2408 case 4: 2409 small.push_back(std::ldexp(1.0f, -127)); 2410 zeros.push_back(0.f); 2411 break; 2412 case 5: 2413 small.push_back(-std::ldexp(1.0f, -128)); 2414 zeros.push_back(-0.f); 2415 break; 2416 } 2417 } 2418 2419 spec.assembly = shader; 2420 spec.inputs.push_back(BufferSp(new Float32Buffer(small))); 2421 spec.outputs.push_back(BufferSp(new Float32Buffer(zeros))); 2422 spec.numWorkGroups = IVec3(numElements, 1, 1); 2423 2424 group->addChild(new SpvAsmComputeShaderCase( 2425 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec)); 2426 } 2427 2428 { 2429 ComputeShaderSpec spec; 2430 vector<float> exact; 2431 const deUint32 numElements = 200; 2432 2433 exact.reserve(numElements); 2434 2435 for (size_t idx = 0; idx < numElements; ++idx) 2436 exact.push_back(static_cast<float>(static_cast<int>(idx) - 100)); 2437 2438 spec.assembly = shader; 2439 spec.inputs.push_back(BufferSp(new Float32Buffer(exact))); 2440 spec.outputs.push_back(BufferSp(new Float32Buffer(exact))); 2441 spec.numWorkGroups = IVec3(numElements, 1, 1); 2442 2443 group->addChild(new SpvAsmComputeShaderCase( 2444 testCtx, "exact", "Check that values exactly preserved where appropriate", spec)); 2445 } 2446 2447 { 2448 ComputeShaderSpec spec; 2449 vector<float> inputs; 2450 const deUint32 numElements = 4; 2451 2452 inputs.push_back(constructNormalizedFloat(8, 0x300300)); 2453 inputs.push_back(-constructNormalizedFloat(-7, 0x600800)); 2454 inputs.push_back(constructNormalizedFloat(2, 0x01E000)); 2455 inputs.push_back(constructNormalizedFloat(1, 0xFFE000)); 2456 2457 spec.assembly = shader; 2458 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase; 2459 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2460 spec.outputs.push_back(BufferSp(new Float32Buffer(inputs))); 2461 spec.numWorkGroups = IVec3(numElements, 1, 1); 2462 2463 group->addChild(new SpvAsmComputeShaderCase( 2464 testCtx, "rounded", "Check that are rounded when needed", spec)); 2465 } 2466 2467 return group.release(); 2468} 2469 2470// Performs a bitwise copy of source to the destination type Dest. 2471template <typename Dest, typename Src> 2472Dest bitwiseCast(Src source) 2473{ 2474 Dest dest; 2475 DE_STATIC_ASSERT(sizeof(source) == sizeof(dest)); 2476 deMemcpy(&dest, &source, sizeof(dest)); 2477 return dest; 2478} 2479 2480tcu::TestCaseGroup* createSpecConstantOpQuantizeToF16Group (tcu::TestContext& testCtx) 2481{ 2482 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop_opquantize", "Tests the OpQuantizeToF16 opcode for the OpSpecConstantOp instruction")); 2483 2484 const std::string shader ( 2485 string(s_ShaderPreamble) + 2486 2487 "OpName %main \"main\"\n" 2488 "OpName %id \"gl_GlobalInvocationID\"\n" 2489 2490 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2491 2492 "OpDecorate %sc_0 SpecId 0\n" 2493 "OpDecorate %sc_1 SpecId 1\n" 2494 "OpDecorate %sc_2 SpecId 2\n" 2495 "OpDecorate %sc_3 SpecId 3\n" 2496 "OpDecorate %sc_4 SpecId 4\n" 2497 "OpDecorate %sc_5 SpecId 5\n" 2498 2499 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2500 2501 "%id = OpVariable %uvec3ptr Input\n" 2502 "%zero = OpConstant %i32 0\n" 2503 "%c_u32_6 = OpConstant %u32 6\n" 2504 2505 "%sc_0 = OpSpecConstant %f32 0.\n" 2506 "%sc_1 = OpSpecConstant %f32 0.\n" 2507 "%sc_2 = OpSpecConstant %f32 0.\n" 2508 "%sc_3 = OpSpecConstant %f32 0.\n" 2509 "%sc_4 = OpSpecConstant %f32 0.\n" 2510 "%sc_5 = OpSpecConstant %f32 0.\n" 2511 2512 "%sc_0_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_0\n" 2513 "%sc_1_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_1\n" 2514 "%sc_2_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_2\n" 2515 "%sc_3_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_3\n" 2516 "%sc_4_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_4\n" 2517 "%sc_5_quant = OpSpecConstantOp %f32 QuantizeToF16 %sc_5\n" 2518 2519 "%main = OpFunction %void None %voidf\n" 2520 "%label = OpLabel\n" 2521 "%idval = OpLoad %uvec3 %id\n" 2522 "%x = OpCompositeExtract %u32 %idval 0\n" 2523 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2524 "%selector = OpUMod %u32 %x %c_u32_6\n" 2525 " OpSelectionMerge %exit None\n" 2526 " OpSwitch %selector %exit 0 %case0 1 %case1 2 %case2 3 %case3 4 %case4 5 %case5\n" 2527 2528 "%case0 = OpLabel\n" 2529 " OpStore %outloc %sc_0_quant\n" 2530 " OpBranch %exit\n" 2531 2532 "%case1 = OpLabel\n" 2533 " OpStore %outloc %sc_1_quant\n" 2534 " OpBranch %exit\n" 2535 2536 "%case2 = OpLabel\n" 2537 " OpStore %outloc %sc_2_quant\n" 2538 " OpBranch %exit\n" 2539 2540 "%case3 = OpLabel\n" 2541 " OpStore %outloc %sc_3_quant\n" 2542 " OpBranch %exit\n" 2543 2544 "%case4 = OpLabel\n" 2545 " OpStore %outloc %sc_4_quant\n" 2546 " OpBranch %exit\n" 2547 2548 "%case5 = OpLabel\n" 2549 " OpStore %outloc %sc_5_quant\n" 2550 " OpBranch %exit\n" 2551 2552 "%exit = OpLabel\n" 2553 " OpReturn\n" 2554 2555 " OpFunctionEnd\n"); 2556 2557 { 2558 ComputeShaderSpec spec; 2559 const deUint8 numCases = 4; 2560 vector<float> inputs (numCases, 0.f); 2561 vector<float> outputs; 2562 2563 spec.assembly = shader; 2564 spec.numWorkGroups = IVec3(numCases, 1, 1); 2565 2566 spec.specConstants.push_back(bitwiseCast<deUint32>(std::numeric_limits<float>::infinity())); 2567 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::numeric_limits<float>::infinity())); 2568 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, 16))); 2569 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, 32))); 2570 2571 outputs.push_back(std::numeric_limits<float>::infinity()); 2572 outputs.push_back(-std::numeric_limits<float>::infinity()); 2573 outputs.push_back(std::numeric_limits<float>::infinity()); 2574 outputs.push_back(-std::numeric_limits<float>::infinity()); 2575 2576 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2577 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs))); 2578 2579 group->addChild(new SpvAsmComputeShaderCase( 2580 testCtx, "infinities", "Check that infinities propagated and created", spec)); 2581 } 2582 2583 { 2584 ComputeShaderSpec spec; 2585 const deUint8 numCases = 2; 2586 vector<float> inputs (numCases, 0.f); 2587 vector<float> outputs; 2588 2589 spec.assembly = shader; 2590 spec.numWorkGroups = IVec3(numCases, 1, 1); 2591 spec.verifyIO = &compareNan; 2592 2593 outputs.push_back(std::numeric_limits<float>::quiet_NaN()); 2594 outputs.push_back(-std::numeric_limits<float>::quiet_NaN()); 2595 2596 for (deUint8 idx = 0; idx < numCases; ++idx) 2597 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx])); 2598 2599 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2600 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs))); 2601 2602 group->addChild(new SpvAsmComputeShaderCase( 2603 testCtx, "propagated_nans", "Check that nans are propagated", spec)); 2604 } 2605 2606 { 2607 ComputeShaderSpec spec; 2608 const deUint8 numCases = 6; 2609 vector<float> inputs (numCases, 0.f); 2610 vector<float> outputs; 2611 2612 spec.assembly = shader; 2613 spec.numWorkGroups = IVec3(numCases, 1, 1); 2614 2615 spec.specConstants.push_back(bitwiseCast<deUint32>(0.f)); 2616 spec.specConstants.push_back(bitwiseCast<deUint32>(-0.f)); 2617 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -16))); 2618 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(-1.0f, -32))); 2619 spec.specConstants.push_back(bitwiseCast<deUint32>(std::ldexp(1.0f, -127))); 2620 spec.specConstants.push_back(bitwiseCast<deUint32>(-std::ldexp(1.0f, -128))); 2621 2622 outputs.push_back(0.f); 2623 outputs.push_back(-0.f); 2624 outputs.push_back(0.f); 2625 outputs.push_back(-0.f); 2626 outputs.push_back(0.f); 2627 outputs.push_back(-0.f); 2628 2629 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2630 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs))); 2631 2632 group->addChild(new SpvAsmComputeShaderCase( 2633 testCtx, "flush_to_zero", "Check that values are zeroed correctly", spec)); 2634 } 2635 2636 { 2637 ComputeShaderSpec spec; 2638 const deUint8 numCases = 6; 2639 vector<float> inputs (numCases, 0.f); 2640 vector<float> outputs; 2641 2642 spec.assembly = shader; 2643 spec.numWorkGroups = IVec3(numCases, 1, 1); 2644 2645 for (deUint8 idx = 0; idx < 6; ++idx) 2646 { 2647 const float f = static_cast<float>(idx * 10 - 30) / 4.f; 2648 spec.specConstants.push_back(bitwiseCast<deUint32>(f)); 2649 outputs.push_back(f); 2650 } 2651 2652 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2653 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs))); 2654 2655 group->addChild(new SpvAsmComputeShaderCase( 2656 testCtx, "exact", "Check that values exactly preserved where appropriate", spec)); 2657 } 2658 2659 { 2660 ComputeShaderSpec spec; 2661 const deUint8 numCases = 4; 2662 vector<float> inputs (numCases, 0.f); 2663 vector<float> outputs; 2664 2665 spec.assembly = shader; 2666 spec.numWorkGroups = IVec3(numCases, 1, 1); 2667 spec.verifyIO = &compareOpQuantizeF16ComputeExactCase; 2668 2669 outputs.push_back(constructNormalizedFloat(8, 0x300300)); 2670 outputs.push_back(-constructNormalizedFloat(-7, 0x600800)); 2671 outputs.push_back(constructNormalizedFloat(2, 0x01E000)); 2672 outputs.push_back(constructNormalizedFloat(1, 0xFFE000)); 2673 2674 for (deUint8 idx = 0; idx < numCases; ++idx) 2675 spec.specConstants.push_back(bitwiseCast<deUint32>(outputs[idx])); 2676 2677 spec.inputs.push_back(BufferSp(new Float32Buffer(inputs))); 2678 spec.outputs.push_back(BufferSp(new Float32Buffer(outputs))); 2679 2680 group->addChild(new SpvAsmComputeShaderCase( 2681 testCtx, "rounded", "Check that are rounded when needed", spec)); 2682 } 2683 2684 return group.release(); 2685} 2686 2687// Checks that constant null/composite values can be used in computation. 2688tcu::TestCaseGroup* createOpConstantUsageGroup (tcu::TestContext& testCtx) 2689{ 2690 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opconstantnullcomposite", "Spotcheck the OpConstantNull & OpConstantComposite instruction")); 2691 ComputeShaderSpec spec; 2692 de::Random rnd (deStringHash(group->getName())); 2693 const int numElements = 100; 2694 vector<float> positiveFloats (numElements, 0); 2695 vector<float> negativeFloats (numElements, 0); 2696 2697 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 2698 2699 for (size_t ndx = 0; ndx < numElements; ++ndx) 2700 negativeFloats[ndx] = -positiveFloats[ndx]; 2701 2702 spec.assembly = 2703 "OpCapability Shader\n" 2704 "%std450 = OpExtInstImport \"GLSL.std.450\"\n" 2705 "OpMemoryModel Logical GLSL450\n" 2706 "OpEntryPoint GLCompute %main \"main\" %id\n" 2707 "OpExecutionMode %main LocalSize 1 1 1\n" 2708 2709 "OpSource GLSL 430\n" 2710 "OpName %main \"main\"\n" 2711 "OpName %id \"gl_GlobalInvocationID\"\n" 2712 2713 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2714 2715 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + 2716 2717 "%fmat = OpTypeMatrix %fvec3 3\n" 2718 "%ten = OpConstant %u32 10\n" 2719 "%f32arr10 = OpTypeArray %f32 %ten\n" 2720 "%fst = OpTypeStruct %f32 %f32\n" 2721 2722 + string(s_InputOutputBuffer) + 2723 2724 "%id = OpVariable %uvec3ptr Input\n" 2725 "%zero = OpConstant %i32 0\n" 2726 2727 // Create a bunch of null values 2728 "%unull = OpConstantNull %u32\n" 2729 "%fnull = OpConstantNull %f32\n" 2730 "%vnull = OpConstantNull %fvec3\n" 2731 "%mnull = OpConstantNull %fmat\n" 2732 "%anull = OpConstantNull %f32arr10\n" 2733 "%snull = OpConstantComposite %fst %fnull %fnull\n" 2734 2735 "%main = OpFunction %void None %voidf\n" 2736 "%label = OpLabel\n" 2737 "%idval = OpLoad %uvec3 %id\n" 2738 "%x = OpCompositeExtract %u32 %idval 0\n" 2739 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2740 "%inval = OpLoad %f32 %inloc\n" 2741 "%neg = OpFNegate %f32 %inval\n" 2742 2743 // Get the abs() of (a certain element of) those null values 2744 "%unull_cov = OpConvertUToF %f32 %unull\n" 2745 "%unull_abs = OpExtInst %f32 %std450 FAbs %unull_cov\n" 2746 "%fnull_abs = OpExtInst %f32 %std450 FAbs %fnull\n" 2747 "%vnull_0 = OpCompositeExtract %f32 %vnull 0\n" 2748 "%vnull_abs = OpExtInst %f32 %std450 FAbs %vnull_0\n" 2749 "%mnull_12 = OpCompositeExtract %f32 %mnull 1 2\n" 2750 "%mnull_abs = OpExtInst %f32 %std450 FAbs %mnull_12\n" 2751 "%anull_3 = OpCompositeExtract %f32 %anull 3\n" 2752 "%anull_abs = OpExtInst %f32 %std450 FAbs %anull_3\n" 2753 "%snull_1 = OpCompositeExtract %f32 %snull 1\n" 2754 "%snull_abs = OpExtInst %f32 %std450 FAbs %snull_1\n" 2755 2756 // Add them all 2757 "%add1 = OpFAdd %f32 %neg %unull_abs\n" 2758 "%add2 = OpFAdd %f32 %add1 %fnull_abs\n" 2759 "%add3 = OpFAdd %f32 %add2 %vnull_abs\n" 2760 "%add4 = OpFAdd %f32 %add3 %mnull_abs\n" 2761 "%add5 = OpFAdd %f32 %add4 %anull_abs\n" 2762 "%final = OpFAdd %f32 %add5 %snull_abs\n" 2763 2764 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2765 " OpStore %outloc %final\n" // write to output 2766 " OpReturn\n" 2767 " OpFunctionEnd\n"; 2768 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 2769 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 2770 spec.numWorkGroups = IVec3(numElements, 1, 1); 2771 2772 group->addChild(new SpvAsmComputeShaderCase(testCtx, "spotcheck", "Check that values constructed via OpConstantNull & OpConstantComposite can be used", spec)); 2773 2774 return group.release(); 2775} 2776 2777// Assembly code used for testing loop control is based on GLSL source code: 2778// #version 430 2779// 2780// layout(std140, set = 0, binding = 0) readonly buffer Input { 2781// float elements[]; 2782// } input_data; 2783// layout(std140, set = 0, binding = 1) writeonly buffer Output { 2784// float elements[]; 2785// } output_data; 2786// 2787// void main() { 2788// uint x = gl_GlobalInvocationID.x; 2789// output_data.elements[x] = input_data.elements[x]; 2790// for (uint i = 0; i < 4; ++i) 2791// output_data.elements[x] += 1.f; 2792// } 2793tcu::TestCaseGroup* createLoopControlGroup (tcu::TestContext& testCtx) 2794{ 2795 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "loop_control", "Tests loop control cases")); 2796 vector<CaseParameter> cases; 2797 de::Random rnd (deStringHash(group->getName())); 2798 const int numElements = 100; 2799 vector<float> inputFloats (numElements, 0); 2800 vector<float> outputFloats (numElements, 0); 2801 const StringTemplate shaderTemplate ( 2802 string(s_ShaderPreamble) + 2803 2804 "OpSource GLSL 430\n" 2805 "OpName %main \"main\"\n" 2806 "OpName %id \"gl_GlobalInvocationID\"\n" 2807 2808 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2809 2810 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2811 2812 "%u32ptr = OpTypePointer Function %u32\n" 2813 2814 "%id = OpVariable %uvec3ptr Input\n" 2815 "%zero = OpConstant %i32 0\n" 2816 "%uzero = OpConstant %u32 0\n" 2817 "%one = OpConstant %i32 1\n" 2818 "%constf1 = OpConstant %f32 1.0\n" 2819 "%four = OpConstant %u32 4\n" 2820 2821 "%main = OpFunction %void None %voidf\n" 2822 "%entry = OpLabel\n" 2823 "%i = OpVariable %u32ptr Function\n" 2824 " OpStore %i %uzero\n" 2825 2826 "%idval = OpLoad %uvec3 %id\n" 2827 "%x = OpCompositeExtract %u32 %idval 0\n" 2828 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2829 "%inval = OpLoad %f32 %inloc\n" 2830 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2831 " OpStore %outloc %inval\n" 2832 " OpBranch %loop_entry\n" 2833 2834 "%loop_entry = OpLabel\n" 2835 "%i_val = OpLoad %u32 %i\n" 2836 "%cmp_lt = OpULessThan %bool %i_val %four\n" 2837 " OpLoopMerge %loop_merge %loop_entry ${CONTROL}\n" 2838 " OpBranchConditional %cmp_lt %loop_body %loop_merge\n" 2839 "%loop_body = OpLabel\n" 2840 "%outval = OpLoad %f32 %outloc\n" 2841 "%addf1 = OpFAdd %f32 %outval %constf1\n" 2842 " OpStore %outloc %addf1\n" 2843 "%new_i = OpIAdd %u32 %i_val %one\n" 2844 " OpStore %i %new_i\n" 2845 " OpBranch %loop_entry\n" 2846 "%loop_merge = OpLabel\n" 2847 " OpReturn\n" 2848 " OpFunctionEnd\n"); 2849 2850 cases.push_back(CaseParameter("none", "None")); 2851 cases.push_back(CaseParameter("unroll", "Unroll")); 2852 cases.push_back(CaseParameter("dont_unroll", "DontUnroll")); 2853 cases.push_back(CaseParameter("unroll_dont_unroll", "Unroll|DontUnroll")); 2854 2855 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); 2856 2857 for (size_t ndx = 0; ndx < numElements; ++ndx) 2858 outputFloats[ndx] = inputFloats[ndx] + 4.f; 2859 2860 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 2861 { 2862 map<string, string> specializations; 2863 ComputeShaderSpec spec; 2864 2865 specializations["CONTROL"] = cases[caseNdx].param; 2866 spec.assembly = shaderTemplate.specialize(specializations); 2867 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 2868 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 2869 spec.numWorkGroups = IVec3(numElements, 1, 1); 2870 2871 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 2872 } 2873 2874 return group.release(); 2875} 2876 2877// Assembly code used for testing selection control is based on GLSL source code: 2878// #version 430 2879// 2880// layout(std140, set = 0, binding = 0) readonly buffer Input { 2881// float elements[]; 2882// } input_data; 2883// layout(std140, set = 0, binding = 1) writeonly buffer Output { 2884// float elements[]; 2885// } output_data; 2886// 2887// void main() { 2888// uint x = gl_GlobalInvocationID.x; 2889// float val = input_data.elements[x]; 2890// if (val > 10.f) 2891// output_data.elements[x] = val + 1.f; 2892// else 2893// output_data.elements[x] = val - 1.f; 2894// } 2895tcu::TestCaseGroup* createSelectionControlGroup (tcu::TestContext& testCtx) 2896{ 2897 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_control", "Tests selection control cases")); 2898 vector<CaseParameter> cases; 2899 de::Random rnd (deStringHash(group->getName())); 2900 const int numElements = 100; 2901 vector<float> inputFloats (numElements, 0); 2902 vector<float> outputFloats (numElements, 0); 2903 const StringTemplate shaderTemplate ( 2904 string(s_ShaderPreamble) + 2905 2906 "OpSource GLSL 430\n" 2907 "OpName %main \"main\"\n" 2908 "OpName %id \"gl_GlobalInvocationID\"\n" 2909 2910 "OpDecorate %id BuiltIn GlobalInvocationId\n" 2911 2912 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 2913 2914 "%id = OpVariable %uvec3ptr Input\n" 2915 "%zero = OpConstant %i32 0\n" 2916 "%constf1 = OpConstant %f32 1.0\n" 2917 "%constf10 = OpConstant %f32 10.0\n" 2918 2919 "%main = OpFunction %void None %voidf\n" 2920 "%entry = OpLabel\n" 2921 "%idval = OpLoad %uvec3 %id\n" 2922 "%x = OpCompositeExtract %u32 %idval 0\n" 2923 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 2924 "%inval = OpLoad %f32 %inloc\n" 2925 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 2926 "%cmp_gt = OpFOrdGreaterThan %bool %inval %constf10\n" 2927 2928 " OpSelectionMerge %if_end ${CONTROL}\n" 2929 " OpBranchConditional %cmp_gt %if_true %if_false\n" 2930 "%if_true = OpLabel\n" 2931 "%addf1 = OpFAdd %f32 %inval %constf1\n" 2932 " OpStore %outloc %addf1\n" 2933 " OpBranch %if_end\n" 2934 "%if_false = OpLabel\n" 2935 "%subf1 = OpFSub %f32 %inval %constf1\n" 2936 " OpStore %outloc %subf1\n" 2937 " OpBranch %if_end\n" 2938 "%if_end = OpLabel\n" 2939 " OpReturn\n" 2940 " OpFunctionEnd\n"); 2941 2942 cases.push_back(CaseParameter("none", "None")); 2943 cases.push_back(CaseParameter("flatten", "Flatten")); 2944 cases.push_back(CaseParameter("dont_flatten", "DontFlatten")); 2945 cases.push_back(CaseParameter("flatten_dont_flatten", "DontFlatten|Flatten")); 2946 2947 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); 2948 2949 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 2950 floorAll(inputFloats); 2951 2952 for (size_t ndx = 0; ndx < numElements; ++ndx) 2953 outputFloats[ndx] = inputFloats[ndx] + (inputFloats[ndx] > 10.f ? 1.f : -1.f); 2954 2955 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 2956 { 2957 map<string, string> specializations; 2958 ComputeShaderSpec spec; 2959 2960 specializations["CONTROL"] = cases[caseNdx].param; 2961 spec.assembly = shaderTemplate.specialize(specializations); 2962 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 2963 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 2964 spec.numWorkGroups = IVec3(numElements, 1, 1); 2965 2966 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 2967 } 2968 2969 return group.release(); 2970} 2971 2972// Assembly code used for testing function control is based on GLSL source code: 2973// 2974// #version 430 2975// 2976// layout(std140, set = 0, binding = 0) readonly buffer Input { 2977// float elements[]; 2978// } input_data; 2979// layout(std140, set = 0, binding = 1) writeonly buffer Output { 2980// float elements[]; 2981// } output_data; 2982// 2983// float const10() { return 10.f; } 2984// 2985// void main() { 2986// uint x = gl_GlobalInvocationID.x; 2987// output_data.elements[x] = input_data.elements[x] + const10(); 2988// } 2989tcu::TestCaseGroup* createFunctionControlGroup (tcu::TestContext& testCtx) 2990{ 2991 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "function_control", "Tests function control cases")); 2992 vector<CaseParameter> cases; 2993 de::Random rnd (deStringHash(group->getName())); 2994 const int numElements = 100; 2995 vector<float> inputFloats (numElements, 0); 2996 vector<float> outputFloats (numElements, 0); 2997 const StringTemplate shaderTemplate ( 2998 string(s_ShaderPreamble) + 2999 3000 "OpSource GLSL 430\n" 3001 "OpName %main \"main\"\n" 3002 "OpName %func_const10 \"const10(\"\n" 3003 "OpName %id \"gl_GlobalInvocationID\"\n" 3004 3005 "OpDecorate %id BuiltIn GlobalInvocationId\n" 3006 3007 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 3008 3009 "%f32f = OpTypeFunction %f32\n" 3010 "%id = OpVariable %uvec3ptr Input\n" 3011 "%zero = OpConstant %i32 0\n" 3012 "%constf10 = OpConstant %f32 10.0\n" 3013 3014 "%main = OpFunction %void None %voidf\n" 3015 "%entry = OpLabel\n" 3016 "%idval = OpLoad %uvec3 %id\n" 3017 "%x = OpCompositeExtract %u32 %idval 0\n" 3018 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 3019 "%inval = OpLoad %f32 %inloc\n" 3020 "%ret_10 = OpFunctionCall %f32 %func_const10\n" 3021 "%fadd = OpFAdd %f32 %inval %ret_10\n" 3022 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 3023 " OpStore %outloc %fadd\n" 3024 " OpReturn\n" 3025 " OpFunctionEnd\n" 3026 3027 "%func_const10 = OpFunction %f32 ${CONTROL} %f32f\n" 3028 "%label = OpLabel\n" 3029 " OpReturnValue %constf10\n" 3030 " OpFunctionEnd\n"); 3031 3032 cases.push_back(CaseParameter("none", "None")); 3033 cases.push_back(CaseParameter("inline", "Inline")); 3034 cases.push_back(CaseParameter("dont_inline", "DontInline")); 3035 cases.push_back(CaseParameter("pure", "Pure")); 3036 cases.push_back(CaseParameter("const", "Const")); 3037 cases.push_back(CaseParameter("inline_pure", "Inline|Pure")); 3038 cases.push_back(CaseParameter("const_dont_inline", "Const|DontInline")); 3039 cases.push_back(CaseParameter("inline_dont_inline", "Inline|DontInline")); 3040 cases.push_back(CaseParameter("pure_inline_dont_inline", "Pure|Inline|DontInline")); 3041 3042 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); 3043 3044 // CPU might not use the same rounding mode as the GPU. Use whole numbers to avoid rounding differences. 3045 floorAll(inputFloats); 3046 3047 for (size_t ndx = 0; ndx < numElements; ++ndx) 3048 outputFloats[ndx] = inputFloats[ndx] + 10.f; 3049 3050 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 3051 { 3052 map<string, string> specializations; 3053 ComputeShaderSpec spec; 3054 3055 specializations["CONTROL"] = cases[caseNdx].param; 3056 spec.assembly = shaderTemplate.specialize(specializations); 3057 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 3058 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 3059 spec.numWorkGroups = IVec3(numElements, 1, 1); 3060 3061 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 3062 } 3063 3064 return group.release(); 3065} 3066 3067tcu::TestCaseGroup* createMemoryAccessGroup (tcu::TestContext& testCtx) 3068{ 3069 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory_access", "Tests memory access cases")); 3070 vector<CaseParameter> cases; 3071 de::Random rnd (deStringHash(group->getName())); 3072 const int numElements = 100; 3073 vector<float> inputFloats (numElements, 0); 3074 vector<float> outputFloats (numElements, 0); 3075 const StringTemplate shaderTemplate ( 3076 string(s_ShaderPreamble) + 3077 3078 "OpSource GLSL 430\n" 3079 "OpName %main \"main\"\n" 3080 "OpName %id \"gl_GlobalInvocationID\"\n" 3081 3082 "OpDecorate %id BuiltIn GlobalInvocationId\n" 3083 3084 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 3085 3086 "%f32ptr_f = OpTypePointer Function %f32\n" 3087 3088 "%id = OpVariable %uvec3ptr Input\n" 3089 "%zero = OpConstant %i32 0\n" 3090 "%four = OpConstant %i32 4\n" 3091 3092 "%main = OpFunction %void None %voidf\n" 3093 "%label = OpLabel\n" 3094 "%copy = OpVariable %f32ptr_f Function\n" 3095 "%idval = OpLoad %uvec3 %id ${ACCESS}\n" 3096 "%x = OpCompositeExtract %u32 %idval 0\n" 3097 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 3098 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 3099 " OpCopyMemory %copy %inloc ${ACCESS}\n" 3100 "%val1 = OpLoad %f32 %copy\n" 3101 "%val2 = OpLoad %f32 %inloc\n" 3102 "%add = OpFAdd %f32 %val1 %val2\n" 3103 " OpStore %outloc %add ${ACCESS}\n" 3104 " OpReturn\n" 3105 " OpFunctionEnd\n"); 3106 3107 cases.push_back(CaseParameter("null", "")); 3108 cases.push_back(CaseParameter("none", "None")); 3109 cases.push_back(CaseParameter("volatile", "Volatile")); 3110 cases.push_back(CaseParameter("aligned", "Aligned 4")); 3111 cases.push_back(CaseParameter("nontemporal", "Nontemporal")); 3112 cases.push_back(CaseParameter("aligned_nontemporal", "Aligned|Nontemporal 4")); 3113 cases.push_back(CaseParameter("aligned_volatile", "Volatile|Aligned 4")); 3114 3115 fillRandomScalars(rnd, -100.f, 100.f, &inputFloats[0], numElements); 3116 3117 for (size_t ndx = 0; ndx < numElements; ++ndx) 3118 outputFloats[ndx] = inputFloats[ndx] + inputFloats[ndx]; 3119 3120 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 3121 { 3122 map<string, string> specializations; 3123 ComputeShaderSpec spec; 3124 3125 specializations["ACCESS"] = cases[caseNdx].param; 3126 spec.assembly = shaderTemplate.specialize(specializations); 3127 spec.inputs.push_back(BufferSp(new Float32Buffer(inputFloats))); 3128 spec.outputs.push_back(BufferSp(new Float32Buffer(outputFloats))); 3129 spec.numWorkGroups = IVec3(numElements, 1, 1); 3130 3131 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 3132 } 3133 3134 return group.release(); 3135} 3136 3137// Checks that we can get undefined values for various types, without exercising a computation with it. 3138tcu::TestCaseGroup* createOpUndefGroup (tcu::TestContext& testCtx) 3139{ 3140 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opundef", "Tests the OpUndef instruction")); 3141 vector<CaseParameter> cases; 3142 de::Random rnd (deStringHash(group->getName())); 3143 const int numElements = 100; 3144 vector<float> positiveFloats (numElements, 0); 3145 vector<float> negativeFloats (numElements, 0); 3146 const StringTemplate shaderTemplate ( 3147 string(s_ShaderPreamble) + 3148 3149 "OpSource GLSL 430\n" 3150 "OpName %main \"main\"\n" 3151 "OpName %id \"gl_GlobalInvocationID\"\n" 3152 3153 "OpDecorate %id BuiltIn GlobalInvocationId\n" 3154 3155 + string(s_InputOutputBufferTraits) + string(s_CommonTypes) + string(s_InputOutputBuffer) + 3156 3157 "${TYPE}\n" 3158 3159 "%id = OpVariable %uvec3ptr Input\n" 3160 "%zero = OpConstant %i32 0\n" 3161 3162 "%main = OpFunction %void None %voidf\n" 3163 "%label = OpLabel\n" 3164 3165 "%undef = OpUndef %type\n" 3166 3167 "%idval = OpLoad %uvec3 %id\n" 3168 "%x = OpCompositeExtract %u32 %idval 0\n" 3169 3170 "%inloc = OpAccessChain %f32ptr %indata %zero %x\n" 3171 "%inval = OpLoad %f32 %inloc\n" 3172 "%neg = OpFNegate %f32 %inval\n" 3173 "%outloc = OpAccessChain %f32ptr %outdata %zero %x\n" 3174 " OpStore %outloc %neg\n" 3175 " OpReturn\n" 3176 " OpFunctionEnd\n"); 3177 3178 cases.push_back(CaseParameter("bool", "%type = OpTypeBool")); 3179 cases.push_back(CaseParameter("sint32", "%type = OpTypeInt 32 1")); 3180 cases.push_back(CaseParameter("uint32", "%type = OpTypeInt 32 0")); 3181 cases.push_back(CaseParameter("float32", "%type = OpTypeFloat 32")); 3182 cases.push_back(CaseParameter("vec4float32", "%type = OpTypeVector %f32 4")); 3183 cases.push_back(CaseParameter("vec2uint32", "%type = OpTypeVector %u32 2")); 3184 cases.push_back(CaseParameter("matrix", "%type = OpTypeMatrix %fvec3 3")); 3185 cases.push_back(CaseParameter("image", "%type = OpTypeImage %f32 2D 0 0 0 1 Unknown")); 3186 cases.push_back(CaseParameter("sampler", "%type = OpTypeSampler")); 3187 cases.push_back(CaseParameter("sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 1 Unknown\n" 3188 "%type = OpTypeSampledImage %img")); 3189 cases.push_back(CaseParameter("array", "%100 = OpConstant %u32 100\n" 3190 "%type = OpTypeArray %i32 %100")); 3191 cases.push_back(CaseParameter("runtimearray", "%type = OpTypeRuntimeArray %f32")); 3192 cases.push_back(CaseParameter("struct", "%type = OpTypeStruct %f32 %i32 %u32")); 3193 cases.push_back(CaseParameter("pointer", "%type = OpTypePointer Function %i32")); 3194 3195 fillRandomScalars(rnd, 1.f, 100.f, &positiveFloats[0], numElements); 3196 3197 for (size_t ndx = 0; ndx < numElements; ++ndx) 3198 negativeFloats[ndx] = -positiveFloats[ndx]; 3199 3200 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 3201 { 3202 map<string, string> specializations; 3203 ComputeShaderSpec spec; 3204 3205 specializations["TYPE"] = cases[caseNdx].param; 3206 spec.assembly = shaderTemplate.specialize(specializations); 3207 spec.inputs.push_back(BufferSp(new Float32Buffer(positiveFloats))); 3208 spec.outputs.push_back(BufferSp(new Float32Buffer(negativeFloats))); 3209 spec.numWorkGroups = IVec3(numElements, 1, 1); 3210 3211 group->addChild(new SpvAsmComputeShaderCase(testCtx, cases[caseNdx].name, cases[caseNdx].name, spec)); 3212 } 3213 3214 return group.release(); 3215} 3216typedef std::pair<std::string, VkShaderStageFlagBits> EntryToStage; 3217typedef map<string, vector<EntryToStage> > ModuleMap; 3218typedef map<VkShaderStageFlagBits, vector<deInt32> > StageToSpecConstantMap; 3219 3220// Context for a specific test instantiation. For example, an instantiation 3221// may test colors yellow/magenta/cyan/mauve in a tesselation shader 3222// with an entry point named 'main_to_the_main' 3223struct InstanceContext 3224{ 3225 // Map of modules to what entry_points we care to use from those modules. 3226 ModuleMap moduleMap; 3227 RGBA inputColors[4]; 3228 RGBA outputColors[4]; 3229 // Concrete SPIR-V code to test via boilerplate specialization. 3230 map<string, string> testCodeFragments; 3231 StageToSpecConstantMap specConstants; 3232 bool hasTessellation; 3233 VkShaderStageFlagBits requiredStages; 3234 3235 InstanceContext (const RGBA (&inputs)[4], const RGBA (&outputs)[4], const map<string, string>& testCodeFragments_, const StageToSpecConstantMap& specConstants_) 3236 : testCodeFragments (testCodeFragments_) 3237 , specConstants (specConstants_) 3238 , hasTessellation (false) 3239 , requiredStages (static_cast<VkShaderStageFlagBits>(0)) 3240 { 3241 inputColors[0] = inputs[0]; 3242 inputColors[1] = inputs[1]; 3243 inputColors[2] = inputs[2]; 3244 inputColors[3] = inputs[3]; 3245 3246 outputColors[0] = outputs[0]; 3247 outputColors[1] = outputs[1]; 3248 outputColors[2] = outputs[2]; 3249 outputColors[3] = outputs[3]; 3250 } 3251 3252 InstanceContext (const InstanceContext& other) 3253 : moduleMap (other.moduleMap) 3254 , testCodeFragments (other.testCodeFragments) 3255 , specConstants (other.specConstants) 3256 , hasTessellation (other.hasTessellation) 3257 , requiredStages (other.requiredStages) 3258 { 3259 inputColors[0] = other.inputColors[0]; 3260 inputColors[1] = other.inputColors[1]; 3261 inputColors[2] = other.inputColors[2]; 3262 inputColors[3] = other.inputColors[3]; 3263 3264 outputColors[0] = other.outputColors[0]; 3265 outputColors[1] = other.outputColors[1]; 3266 outputColors[2] = other.outputColors[2]; 3267 outputColors[3] = other.outputColors[3]; 3268 } 3269}; 3270 3271// A description of a shader to be used for a single stage of the graphics pipeline. 3272struct ShaderElement 3273{ 3274 // The module that contains this shader entrypoint. 3275 string moduleName; 3276 3277 // The name of the entrypoint. 3278 string entryName; 3279 3280 // Which shader stage this entry point represents. 3281 VkShaderStageFlagBits stage; 3282 3283 ShaderElement (const string& moduleName_, const string& entryPoint_, VkShaderStageFlagBits shaderStage_) 3284 : moduleName(moduleName_) 3285 , entryName(entryPoint_) 3286 , stage(shaderStage_) 3287 { 3288 } 3289}; 3290 3291void getDefaultColors (RGBA (&colors)[4]) 3292{ 3293 colors[0] = RGBA::white(); 3294 colors[1] = RGBA::red(); 3295 colors[2] = RGBA::green(); 3296 colors[3] = RGBA::blue(); 3297} 3298 3299void getHalfColorsFullAlpha (RGBA (&colors)[4]) 3300{ 3301 colors[0] = RGBA(127, 127, 127, 255); 3302 colors[1] = RGBA(127, 0, 0, 255); 3303 colors[2] = RGBA(0, 127, 0, 255); 3304 colors[3] = RGBA(0, 0, 127, 255); 3305} 3306 3307void getInvertedDefaultColors (RGBA (&colors)[4]) 3308{ 3309 colors[0] = RGBA(0, 0, 0, 255); 3310 colors[1] = RGBA(0, 255, 255, 255); 3311 colors[2] = RGBA(255, 0, 255, 255); 3312 colors[3] = RGBA(255, 255, 0, 255); 3313} 3314 3315// Turns a statically sized array of ShaderElements into an instance-context 3316// by setting up the mapping of modules to their contained shaders and stages. 3317// The inputs and expected outputs are given by inputColors and outputColors 3318template<size_t N> 3319InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, const StageToSpecConstantMap& specConstants) 3320{ 3321 InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants); 3322 for (size_t i = 0; i < N; ++i) 3323 { 3324 ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage)); 3325 ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | elements[i].stage); 3326 } 3327 return ctx; 3328} 3329 3330template<size_t N> 3331inline InstanceContext createInstanceContext (const ShaderElement (&elements)[N], RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments) 3332{ 3333 return createInstanceContext(elements, inputColors, outputColors, testCodeFragments, StageToSpecConstantMap()); 3334} 3335 3336// The same as createInstanceContext above, but with default colors. 3337template<size_t N> 3338InstanceContext createInstanceContext (const ShaderElement (&elements)[N], const map<string, string>& testCodeFragments) 3339{ 3340 RGBA defaultColors[4]; 3341 getDefaultColors(defaultColors); 3342 return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments); 3343} 3344 3345// For the current InstanceContext, constructs the required modules and shader stage create infos. 3346void createPipelineShaderStages (const DeviceInterface& vk, const VkDevice vkDevice, InstanceContext& instance, Context& context, vector<ModuleHandleSp>& modules, vector<VkPipelineShaderStageCreateInfo>& createInfos) 3347{ 3348 for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx) 3349 { 3350 const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0))); 3351 modules.push_back(ModuleHandleSp(mod)); 3352 for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx) 3353 { 3354 const EntryToStage& stage = *shaderNdx; 3355 const VkPipelineShaderStageCreateInfo shaderParam = 3356 { 3357 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 3358 DE_NULL, // const void* pNext; 3359 (VkPipelineShaderStageCreateFlags)0, 3360 stage.second, // VkShaderStageFlagBits stage; 3361 **modules.back(), // VkShaderModule module; 3362 stage.first.c_str(), // const char* pName; 3363 (const VkSpecializationInfo*)DE_NULL, 3364 }; 3365 createInfos.push_back(shaderParam); 3366 } 3367 } 3368} 3369 3370#define SPIRV_ASSEMBLY_TYPES \ 3371 "%void = OpTypeVoid\n" \ 3372 "%bool = OpTypeBool\n" \ 3373 \ 3374 "%i32 = OpTypeInt 32 1\n" \ 3375 "%u32 = OpTypeInt 32 0\n" \ 3376 \ 3377 "%f32 = OpTypeFloat 32\n" \ 3378 "%v3f32 = OpTypeVector %f32 3\n" \ 3379 "%v4f32 = OpTypeVector %f32 4\n" \ 3380 "%v4bool = OpTypeVector %bool 4\n" \ 3381 \ 3382 "%v4f32_function = OpTypeFunction %v4f32 %v4f32\n" \ 3383 "%fun = OpTypeFunction %void\n" \ 3384 \ 3385 "%ip_f32 = OpTypePointer Input %f32\n" \ 3386 "%ip_i32 = OpTypePointer Input %i32\n" \ 3387 "%ip_v3f32 = OpTypePointer Input %v3f32\n" \ 3388 "%ip_v4f32 = OpTypePointer Input %v4f32\n" \ 3389 \ 3390 "%op_f32 = OpTypePointer Output %f32\n" \ 3391 "%op_v4f32 = OpTypePointer Output %v4f32\n" \ 3392 \ 3393 "%fp_f32 = OpTypePointer Function %f32\n" \ 3394 "%fp_i32 = OpTypePointer Function %i32\n" \ 3395 "%fp_v4f32 = OpTypePointer Function %v4f32\n" 3396 3397#define SPIRV_ASSEMBLY_CONSTANTS \ 3398 "%c_f32_1 = OpConstant %f32 1.0\n" \ 3399 "%c_f32_0 = OpConstant %f32 0.0\n" \ 3400 "%c_f32_0_5 = OpConstant %f32 0.5\n" \ 3401 "%c_f32_n1 = OpConstant %f32 -1.\n" \ 3402 "%c_f32_7 = OpConstant %f32 7.0\n" \ 3403 "%c_f32_8 = OpConstant %f32 8.0\n" \ 3404 "%c_i32_0 = OpConstant %i32 0\n" \ 3405 "%c_i32_1 = OpConstant %i32 1\n" \ 3406 "%c_i32_2 = OpConstant %i32 2\n" \ 3407 "%c_i32_3 = OpConstant %i32 3\n" \ 3408 "%c_i32_4 = OpConstant %i32 4\n" \ 3409 "%c_u32_0 = OpConstant %u32 0\n" \ 3410 "%c_u32_1 = OpConstant %u32 1\n" \ 3411 "%c_u32_2 = OpConstant %u32 2\n" \ 3412 "%c_u32_3 = OpConstant %u32 3\n" \ 3413 "%c_u32_32 = OpConstant %u32 32\n" \ 3414 "%c_u32_4 = OpConstant %u32 4\n" \ 3415 "%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n" \ 3416 "%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" \ 3417 "%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n" \ 3418 "%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n" 3419 3420#define SPIRV_ASSEMBLY_ARRAYS \ 3421 "%a1f32 = OpTypeArray %f32 %c_u32_1\n" \ 3422 "%a2f32 = OpTypeArray %f32 %c_u32_2\n" \ 3423 "%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n" \ 3424 "%a4f32 = OpTypeArray %f32 %c_u32_4\n" \ 3425 "%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n" \ 3426 "%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n" \ 3427 "%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n" \ 3428 "%op_a2f32 = OpTypePointer Output %a2f32\n" \ 3429 "%op_a3v4f32 = OpTypePointer Output %a3v4f32\n" \ 3430 "%op_a4f32 = OpTypePointer Output %a4f32\n" 3431 3432// Creates vertex-shader assembly by specializing a boilerplate StringTemplate 3433// on fragments, which must (at least) map "testfun" to an OpFunction definition 3434// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed 3435// with "BP_" to avoid collisions with fragments. 3436// 3437// It corresponds roughly to this GLSL: 3438//; 3439// layout(location = 0) in vec4 position; 3440// layout(location = 1) in vec4 color; 3441// layout(location = 1) out highp vec4 vtxColor; 3442// void main (void) { gl_Position = position; vtxColor = test_func(color); } 3443string makeVertexShaderAssembly(const map<string, string>& fragments) 3444{ 3445// \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized 3446 static const char vertexShaderBoilerplate[] = 3447 "OpCapability Shader\n" 3448 "OpCapability ClipDistance\n" 3449 "OpCapability CullDistance\n" 3450 "OpMemoryModel Logical GLSL450\n" 3451 "OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex\n" 3452 "${debug:opt}\n" 3453 "OpName %main \"main\"\n" 3454 "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" 3455 "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" 3456 "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" 3457 "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" 3458 "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" 3459 "OpName %test_code \"testfun(vf4;\"\n" 3460 "OpName %BP_stream \"\"\n" 3461 "OpName %BP_position \"position\"\n" 3462 "OpName %BP_vtx_color \"vtxColor\"\n" 3463 "OpName %BP_color \"color\"\n" 3464 "OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n" 3465 "OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n" 3466 "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" 3467 "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" 3468 "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" 3469 "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" 3470 "OpDecorate %BP_gl_PerVertex Block\n" 3471 "OpDecorate %BP_position Location 0\n" 3472 "OpDecorate %BP_vtx_color Location 1\n" 3473 "OpDecorate %BP_color Location 1\n" 3474 "OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n" 3475 "OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n" 3476 "${decoration:opt}\n" 3477 SPIRV_ASSEMBLY_TYPES 3478 SPIRV_ASSEMBLY_CONSTANTS 3479 SPIRV_ASSEMBLY_ARRAYS 3480 "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3481 "%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n" 3482 "%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n" 3483 "%BP_position = OpVariable %ip_v4f32 Input\n" 3484 "%BP_vtx_color = OpVariable %op_v4f32 Output\n" 3485 "%BP_color = OpVariable %ip_v4f32 Input\n" 3486 "%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n" 3487 "%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n" 3488 "${pre_main:opt}\n" 3489 "%main = OpFunction %void None %fun\n" 3490 "%BP_label = OpLabel\n" 3491 "%BP_pos = OpLoad %v4f32 %BP_position\n" 3492 "%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" 3493 "OpStore %BP_gl_pos %BP_pos\n" 3494 "%BP_col = OpLoad %v4f32 %BP_color\n" 3495 "%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n" 3496 "OpStore %BP_vtx_color %BP_col_transformed\n" 3497 "OpReturn\n" 3498 "OpFunctionEnd\n" 3499 "${testfun}\n"; 3500 return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments); 3501} 3502 3503// Creates tess-control-shader assembly by specializing a boilerplate 3504// StringTemplate on fragments, which must (at least) map "testfun" to an 3505// OpFunction definition for %test_code that takes and returns a %v4f32. 3506// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. 3507// 3508// It roughly corresponds to the following GLSL. 3509// 3510// #version 450 3511// layout(vertices = 3) out; 3512// layout(location = 1) in vec4 in_color[]; 3513// layout(location = 1) out vec4 out_color[]; 3514// 3515// void main() { 3516// out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]); 3517// gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; 3518// if (gl_InvocationID == 0) { 3519// gl_TessLevelOuter[0] = 1.0; 3520// gl_TessLevelOuter[1] = 1.0; 3521// gl_TessLevelOuter[2] = 1.0; 3522// gl_TessLevelInner[0] = 1.0; 3523// } 3524// } 3525string makeTessControlShaderAssembly (const map<string, string>& fragments) 3526{ 3527 static const char tessControlShaderBoilerplate[] = 3528 "OpCapability Tessellation\n" 3529 "OpCapability ClipDistance\n" 3530 "OpCapability CullDistance\n" 3531 "OpMemoryModel Logical GLSL450\n" 3532 "OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner\n" 3533 "OpExecutionMode %BP_main OutputVertices 3\n" 3534 "${debug:opt}\n" 3535 "OpName %BP_main \"main\"\n" 3536 "OpName %test_code \"testfun(vf4;\"\n" 3537 "OpName %BP_out_color \"out_color\"\n" 3538 "OpName %BP_gl_InvocationID \"gl_InvocationID\"\n" 3539 "OpName %BP_in_color \"in_color\"\n" 3540 "OpName %BP_gl_PerVertex \"gl_PerVertex\"\n" 3541 "OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n" 3542 "OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n" 3543 "OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n" 3544 "OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n" 3545 "OpName %BP_gl_out \"gl_out\"\n" 3546 "OpName %BP_gl_PVOut \"gl_PerVertex\"\n" 3547 "OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n" 3548 "OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n" 3549 "OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n" 3550 "OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n" 3551 "OpName %BP_gl_in \"gl_in\"\n" 3552 "OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" 3553 "OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n" 3554 "OpDecorate %BP_out_color Location 1\n" 3555 "OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n" 3556 "OpDecorate %BP_in_color Location 1\n" 3557 "OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n" 3558 "OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n" 3559 "OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n" 3560 "OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n" 3561 "OpDecorate %BP_gl_PerVertex Block\n" 3562 "OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n" 3563 "OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n" 3564 "OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n" 3565 "OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n" 3566 "OpDecorate %BP_gl_PVOut Block\n" 3567 "OpDecorate %BP_gl_TessLevelOuter Patch\n" 3568 "OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n" 3569 "OpDecorate %BP_gl_TessLevelInner Patch\n" 3570 "OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n" 3571 "${decoration:opt}\n" 3572 SPIRV_ASSEMBLY_TYPES 3573 SPIRV_ASSEMBLY_CONSTANTS 3574 SPIRV_ASSEMBLY_ARRAYS 3575 "%BP_out_color = OpVariable %op_a3v4f32 Output\n" 3576 "%BP_gl_InvocationID = OpVariable %ip_i32 Input\n" 3577 "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" 3578 "%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3579 "%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n" 3580 "%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n" 3581 "%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n" 3582 "%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3583 "%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n" 3584 "%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n" 3585 "%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n" 3586 "%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" 3587 "%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" 3588 "${pre_main:opt}\n" 3589 3590 "%BP_main = OpFunction %void None %fun\n" 3591 "%BP_label = OpLabel\n" 3592 3593 "%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n" 3594 3595 "%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n" 3596 "%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n" 3597 "%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n" 3598 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n" 3599 "OpStore %BP_out_col_loc %BP_clr_transformed\n" 3600 3601 "%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n" 3602 "%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n" 3603 "%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n" 3604 "OpStore %BP_out_pos_loc %BP_in_pos_val\n" 3605 3606 "%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n" 3607 "OpSelectionMerge %BP_merge_label None\n" 3608 "OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n" 3609 "%BP_if_label = OpLabel\n" 3610 "%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n" 3611 "%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n" 3612 "%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n" 3613 "%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n" 3614 "OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n" 3615 "OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n" 3616 "OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n" 3617 "OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n" 3618 "OpBranch %BP_merge_label\n" 3619 "%BP_merge_label = OpLabel\n" 3620 "OpReturn\n" 3621 "OpFunctionEnd\n" 3622 "${testfun}\n"; 3623 return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments); 3624} 3625 3626// Creates tess-evaluation-shader assembly by specializing a boilerplate 3627// StringTemplate on fragments, which must (at least) map "testfun" to an 3628// OpFunction definition for %test_code that takes and returns a %v4f32. 3629// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments. 3630// 3631// It roughly corresponds to the following glsl. 3632// 3633// #version 450 3634// 3635// layout(triangles, equal_spacing, ccw) in; 3636// layout(location = 1) in vec4 in_color[]; 3637// layout(location = 1) out vec4 out_color; 3638// 3639// #define interpolate(val) 3640// vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] + 3641// vec4(gl_TessCoord.z) * val[2] 3642// 3643// void main() { 3644// gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position + 3645// vec4(gl_TessCoord.y) * gl_in[1].gl_Position + 3646// vec4(gl_TessCoord.z) * gl_in[2].gl_Position; 3647// out_color = testfun(interpolate(in_color)); 3648// } 3649string makeTessEvalShaderAssembly(const map<string, string>& fragments) 3650{ 3651 static const char tessEvalBoilerplate[] = 3652 "OpCapability Tessellation\n" 3653 "OpCapability ClipDistance\n" 3654 "OpCapability CullDistance\n" 3655 "OpMemoryModel Logical GLSL450\n" 3656 "OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_in %BP_out_color %BP_in_color\n" 3657 "OpExecutionMode %BP_main Triangles\n" 3658 "OpExecutionMode %BP_main SpacingEqual\n" 3659 "OpExecutionMode %BP_main VertexOrderCcw\n" 3660 "${debug:opt}\n" 3661 "OpName %BP_main \"main\"\n" 3662 "OpName %test_code \"testfun(vf4;\"\n" 3663 "OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n" 3664 "OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n" 3665 "OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n" 3666 "OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n" 3667 "OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n" 3668 "OpName %BP_stream \"\"\n" 3669 "OpName %BP_gl_TessCoord \"gl_TessCoord\"\n" 3670 "OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n" 3671 "OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n" 3672 "OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n" 3673 "OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n" 3674 "OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n" 3675 "OpName %BP_gl_in \"gl_in\"\n" 3676 "OpName %BP_out_color \"out_color\"\n" 3677 "OpName %BP_in_color \"in_color\"\n" 3678 "OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n" 3679 "OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n" 3680 "OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n" 3681 "OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n" 3682 "OpDecorate %BP_gl_PerVertexOut Block\n" 3683 "OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n" 3684 "OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n" 3685 "OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n" 3686 "OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n" 3687 "OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n" 3688 "OpDecorate %BP_gl_PerVertexIn Block\n" 3689 "OpDecorate %BP_out_color Location 1\n" 3690 "OpDecorate %BP_in_color Location 1\n" 3691 "${decoration:opt}\n" 3692 SPIRV_ASSEMBLY_TYPES 3693 SPIRV_ASSEMBLY_CONSTANTS 3694 SPIRV_ASSEMBLY_ARRAYS 3695 "%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3696 "%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n" 3697 "%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n" 3698 "%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n" 3699 "%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3700 "%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n" 3701 "%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n" 3702 "%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n" 3703 "%BP_out_color = OpVariable %op_v4f32 Output\n" 3704 "%BP_in_color = OpVariable %ip_a32v4f32 Input\n" 3705 "${pre_main:opt}\n" 3706 "%BP_main = OpFunction %void None %fun\n" 3707 "%BP_label = OpLabel\n" 3708 "%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n" 3709 "%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n" 3710 "%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n" 3711 "%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" 3712 "%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" 3713 "%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" 3714 3715 "%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n" 3716 "%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" 3717 "%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" 3718 "%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" 3719 3720 "%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n" 3721 "%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n" 3722 "%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n" 3723 "%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n" 3724 "%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n" 3725 "%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n" 3726 3727 "%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n" 3728 "%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n" 3729 "%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n" 3730 3731 "%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n" 3732 "%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n" 3733 "%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n" 3734 3735 "%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n" 3736 "%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n" 3737 3738 "OpStore %BP_gl_OPos %BP_pos_sum_1\n" 3739 3740 "%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n" 3741 "%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n" 3742 "%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n" 3743 3744 "%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n" 3745 "%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n" 3746 "%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n" 3747 3748 "%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n" 3749 "%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n" 3750 3751 "%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n" 3752 3753 "OpStore %BP_out_color %BP_clr_transformed\n" 3754 "OpReturn\n" 3755 "OpFunctionEnd\n" 3756 "${testfun}\n"; 3757 return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments); 3758} 3759 3760// Creates geometry-shader assembly by specializing a boilerplate StringTemplate 3761// on fragments, which must (at least) map "testfun" to an OpFunction definition 3762// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed 3763// with "BP_" to avoid collisions with fragments. 3764// 3765// Derived from this GLSL: 3766// 3767// #version 450 3768// layout(triangles) in; 3769// layout(triangle_strip, max_vertices = 3) out; 3770// 3771// layout(location = 1) in vec4 in_color[]; 3772// layout(location = 1) out vec4 out_color; 3773// 3774// void main() { 3775// gl_Position = gl_in[0].gl_Position; 3776// out_color = test_fun(in_color[0]); 3777// EmitVertex(); 3778// gl_Position = gl_in[1].gl_Position; 3779// out_color = test_fun(in_color[1]); 3780// EmitVertex(); 3781// gl_Position = gl_in[2].gl_Position; 3782// out_color = test_fun(in_color[2]); 3783// EmitVertex(); 3784// EndPrimitive(); 3785// } 3786string makeGeometryShaderAssembly(const map<string, string>& fragments) 3787{ 3788 static const char geometryShaderBoilerplate[] = 3789 "OpCapability Geometry\n" 3790 "OpCapability ClipDistance\n" 3791 "OpCapability CullDistance\n" 3792 "OpMemoryModel Logical GLSL450\n" 3793 "OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_in %BP_out_color %BP_in_color\n" 3794 "OpExecutionMode %BP_main Triangles\n" 3795 "OpExecutionMode %BP_main OutputTriangleStrip\n" 3796 "OpExecutionMode %BP_main OutputVertices 3\n" 3797 "${debug:opt}\n" 3798 "OpName %BP_main \"main\"\n" 3799 "OpName %BP_per_vertex_in \"gl_PerVertex\"\n" 3800 "OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n" 3801 "OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n" 3802 "OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n" 3803 "OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n" 3804 "OpName %BP_gl_in \"gl_in\"\n" 3805 "OpName %BP_out_color \"out_color\"\n" 3806 "OpName %BP_in_color \"in_color\"\n" 3807 "OpName %test_code \"testfun(vf4;\"\n" 3808 "OpDecorate %BP_out_gl_position BuiltIn Position\n" 3809 "OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n" 3810 "OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n" 3811 "OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n" 3812 "OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n" 3813 "OpDecorate %BP_per_vertex_in Block\n" 3814 "OpDecorate %BP_out_color Location 1\n" 3815 "OpDecorate %BP_in_color Location 1\n" 3816 "${decoration:opt}\n" 3817 SPIRV_ASSEMBLY_TYPES 3818 SPIRV_ASSEMBLY_CONSTANTS 3819 SPIRV_ASSEMBLY_ARRAYS 3820 "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 3821 "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n" 3822 "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n" 3823 3824 "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n" 3825 "%BP_out_color = OpVariable %op_v4f32 Output\n" 3826 "%BP_in_color = OpVariable %ip_a3v4f32 Input\n" 3827 "%BP_out_gl_position = OpVariable %op_v4f32 Output\n" 3828 "${pre_main:opt}\n" 3829 3830 "%BP_main = OpFunction %void None %fun\n" 3831 "%BP_label = OpLabel\n" 3832 "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n" 3833 "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n" 3834 "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n" 3835 3836 "%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n" 3837 "%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n" 3838 "%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n" 3839 3840 "%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n" 3841 "%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n" 3842 "%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n" 3843 3844 "%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n" 3845 "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n" 3846 "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n" 3847 3848 "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n" 3849 "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n" 3850 "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n" 3851 3852 3853 "OpStore %BP_out_gl_position %BP_in_position_0\n" 3854 "OpStore %BP_out_color %BP_transformed_in_color_0\n" 3855 "OpEmitVertex\n" 3856 3857 "OpStore %BP_out_gl_position %BP_in_position_1\n" 3858 "OpStore %BP_out_color %BP_transformed_in_color_1\n" 3859 "OpEmitVertex\n" 3860 3861 "OpStore %BP_out_gl_position %BP_in_position_2\n" 3862 "OpStore %BP_out_color %BP_transformed_in_color_2\n" 3863 "OpEmitVertex\n" 3864 3865 "OpEndPrimitive\n" 3866 "OpReturn\n" 3867 "OpFunctionEnd\n" 3868 "${testfun}\n"; 3869 return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments); 3870} 3871 3872// Creates fragment-shader assembly by specializing a boilerplate StringTemplate 3873// on fragments, which must (at least) map "testfun" to an OpFunction definition 3874// for %test_code that takes and returns a %v4f32. Boilerplate IDs are prefixed 3875// with "BP_" to avoid collisions with fragments. 3876// 3877// Derived from this GLSL: 3878// 3879// layout(location = 1) in highp vec4 vtxColor; 3880// layout(location = 0) out highp vec4 fragColor; 3881// highp vec4 testfun(highp vec4 x) { return x; } 3882// void main(void) { fragColor = testfun(vtxColor); } 3883// 3884// with modifications including passing vtxColor by value and ripping out 3885// testfun() definition. 3886string makeFragmentShaderAssembly(const map<string, string>& fragments) 3887{ 3888 static const char fragmentShaderBoilerplate[] = 3889 "OpCapability Shader\n" 3890 "OpMemoryModel Logical GLSL450\n" 3891 "OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor\n" 3892 "OpExecutionMode %BP_main OriginUpperLeft\n" 3893 "${debug:opt}\n" 3894 "OpName %BP_main \"main\"\n" 3895 "OpName %BP_fragColor \"fragColor\"\n" 3896 "OpName %BP_vtxColor \"vtxColor\"\n" 3897 "OpName %test_code \"testfun(vf4;\"\n" 3898 "OpDecorate %BP_fragColor Location 0\n" 3899 "OpDecorate %BP_vtxColor Location 1\n" 3900 "${decoration:opt}\n" 3901 SPIRV_ASSEMBLY_TYPES 3902 SPIRV_ASSEMBLY_CONSTANTS 3903 SPIRV_ASSEMBLY_ARRAYS 3904 "%BP_fragColor = OpVariable %op_v4f32 Output\n" 3905 "%BP_vtxColor = OpVariable %ip_v4f32 Input\n" 3906 "${pre_main:opt}\n" 3907 "%BP_main = OpFunction %void None %fun\n" 3908 "%BP_label_main = OpLabel\n" 3909 "%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n" 3910 "%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n" 3911 "OpStore %BP_fragColor %BP_tmp2\n" 3912 "OpReturn\n" 3913 "OpFunctionEnd\n" 3914 "${testfun}\n"; 3915 return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments); 3916} 3917 3918// Creates fragments that specialize into a simple pass-through shader (of any kind). 3919map<string, string> passthruFragments(void) 3920{ 3921 map<string, string> fragments; 3922 fragments["testfun"] = 3923 // A %test_code function that returns its argument unchanged. 3924 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 3925 "%param1 = OpFunctionParameter %v4f32\n" 3926 "%label_testfun = OpLabel\n" 3927 "OpReturnValue %param1\n" 3928 "OpFunctionEnd\n"; 3929 return fragments; 3930} 3931 3932// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. 3933// Vertex shader gets custom code from context, the rest are pass-through. 3934void addShaderCodeCustomVertex(vk::SourceCollections& dst, InstanceContext context) 3935{ 3936 map<string, string> passthru = passthruFragments(); 3937 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(context.testCodeFragments); 3938 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); 3939} 3940 3941// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. 3942// Tessellation control shader gets custom code from context, the rest are 3943// pass-through. 3944void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext context) 3945{ 3946 map<string, string> passthru = passthruFragments(); 3947 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); 3948 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(context.testCodeFragments); 3949 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(passthru); 3950 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); 3951} 3952 3953// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. 3954// Tessellation evaluation shader gets custom code from context, the rest are 3955// pass-through. 3956void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext context) 3957{ 3958 map<string, string> passthru = passthruFragments(); 3959 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); 3960 dst.spirvAsmSources.add("tessc") << makeTessControlShaderAssembly(passthru); 3961 dst.spirvAsmSources.add("tesse") << makeTessEvalShaderAssembly(context.testCodeFragments); 3962 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); 3963} 3964 3965// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. 3966// Geometry shader gets custom code from context, the rest are pass-through. 3967void addShaderCodeCustomGeometry(vk::SourceCollections& dst, InstanceContext context) 3968{ 3969 map<string, string> passthru = passthruFragments(); 3970 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); 3971 dst.spirvAsmSources.add("geom") << makeGeometryShaderAssembly(context.testCodeFragments); 3972 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(passthru); 3973} 3974 3975// Adds shader assembly text to dst.spirvAsmSources for all shader kinds. 3976// Fragment shader gets custom code from context, the rest are pass-through. 3977void addShaderCodeCustomFragment(vk::SourceCollections& dst, InstanceContext context) 3978{ 3979 map<string, string> passthru = passthruFragments(); 3980 dst.spirvAsmSources.add("vert") << makeVertexShaderAssembly(passthru); 3981 dst.spirvAsmSources.add("frag") << makeFragmentShaderAssembly(context.testCodeFragments); 3982} 3983 3984void createCombinedModule(vk::SourceCollections& dst, InstanceContext) 3985{ 3986 // \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional 3987 // \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point 3988 dst.spirvAsmSources.add("module") << 3989 "OpCapability Shader\n" 3990 "OpCapability ClipDistance\n" 3991 "OpCapability CullDistance\n" 3992 "OpCapability Geometry\n" 3993 "OpCapability Tessellation\n" 3994 "OpMemoryModel Logical GLSL450\n" 3995 3996 "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n" 3997 "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n" 3998 "OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n" 3999 "OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n" 4000 "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n" 4001 4002 "OpExecutionMode %geom_main Triangles\n" 4003 "OpExecutionMode %geom_main OutputTriangleStrip\n" 4004 "OpExecutionMode %geom_main OutputVertices 3\n" 4005 4006 "OpExecutionMode %tessc_main OutputVertices 3\n" 4007 4008 "OpExecutionMode %tesse_main Triangles\n" 4009 4010 "OpExecutionMode %frag_main OriginUpperLeft\n" 4011 4012 "OpName %vert_main \"main\"\n" 4013 "OpName %vert_vtxPosition \"vtxPosition\"\n" 4014 "OpName %vert_Position \"position\"\n" 4015 "OpName %vert_vtxColor \"vtxColor\"\n" 4016 "OpName %vert_color \"color\"\n" 4017 "OpName %vert_vertex_id \"gl_VertexIndex\"\n" 4018 "OpName %vert_instance_id \"gl_InstanceIndex\"\n" 4019 "OpName %geom_main \"main\"\n" 4020 "OpName %geom_per_vertex_in \"gl_PerVertex\"\n" 4021 "OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n" 4022 "OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n" 4023 "OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n" 4024 "OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n" 4025 "OpName %geom_gl_in \"gl_in\"\n" 4026 "OpName %geom_out_color \"out_color\"\n" 4027 "OpName %geom_in_color \"in_color\"\n" 4028 "OpName %tessc_main \"main\"\n" 4029 "OpName %tessc_out_color \"out_color\"\n" 4030 "OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n" 4031 "OpName %tessc_in_color \"in_color\"\n" 4032 "OpName %tessc_out_position \"out_position\"\n" 4033 "OpName %tessc_in_position \"in_position\"\n" 4034 "OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n" 4035 "OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n" 4036 "OpName %tesse_main \"main\"\n" 4037 "OpName %tesse_per_vertex_out \"gl_PerVertex\"\n" 4038 "OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n" 4039 "OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n" 4040 "OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n" 4041 "OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n" 4042 "OpName %tesse_stream \"\"\n" 4043 "OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n" 4044 "OpName %tesse_in_position \"in_position\"\n" 4045 "OpName %tesse_out_color \"out_color\"\n" 4046 "OpName %tesse_in_color \"in_color\"\n" 4047 "OpName %frag_main \"main\"\n" 4048 "OpName %frag_fragColor \"fragColor\"\n" 4049 "OpName %frag_vtxColor \"vtxColor\"\n" 4050 4051 "; Vertex decorations\n" 4052 "OpDecorate %vert_vtxPosition Location 2\n" 4053 "OpDecorate %vert_Position Location 0\n" 4054 "OpDecorate %vert_vtxColor Location 1\n" 4055 "OpDecorate %vert_color Location 1\n" 4056 "OpDecorate %vert_vertex_id BuiltIn VertexIndex\n" 4057 "OpDecorate %vert_instance_id BuiltIn InstanceIndex\n" 4058 4059 "; Geometry decorations\n" 4060 "OpDecorate %geom_out_gl_position BuiltIn Position\n" 4061 "OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n" 4062 "OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n" 4063 "OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n" 4064 "OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n" 4065 "OpDecorate %geom_per_vertex_in Block\n" 4066 "OpDecorate %geom_out_color Location 1\n" 4067 "OpDecorate %geom_in_color Location 1\n" 4068 4069 "; Tessellation Control decorations\n" 4070 "OpDecorate %tessc_out_color Location 1\n" 4071 "OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n" 4072 "OpDecorate %tessc_in_color Location 1\n" 4073 "OpDecorate %tessc_out_position Location 2\n" 4074 "OpDecorate %tessc_in_position Location 2\n" 4075 "OpDecorate %tessc_gl_TessLevelOuter Patch\n" 4076 "OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n" 4077 "OpDecorate %tessc_gl_TessLevelInner Patch\n" 4078 "OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n" 4079 4080 "; Tessellation Evaluation decorations\n" 4081 "OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n" 4082 "OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n" 4083 "OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n" 4084 "OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n" 4085 "OpDecorate %tesse_per_vertex_out Block\n" 4086 "OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n" 4087 "OpDecorate %tesse_in_position Location 2\n" 4088 "OpDecorate %tesse_out_color Location 1\n" 4089 "OpDecorate %tesse_in_color Location 1\n" 4090 4091 "; Fragment decorations\n" 4092 "OpDecorate %frag_fragColor Location 0\n" 4093 "OpDecorate %frag_vtxColor Location 1\n" 4094 4095 SPIRV_ASSEMBLY_TYPES 4096 SPIRV_ASSEMBLY_CONSTANTS 4097 SPIRV_ASSEMBLY_ARRAYS 4098 4099 "; Vertex Variables\n" 4100 "%vert_vtxPosition = OpVariable %op_v4f32 Output\n" 4101 "%vert_Position = OpVariable %ip_v4f32 Input\n" 4102 "%vert_vtxColor = OpVariable %op_v4f32 Output\n" 4103 "%vert_color = OpVariable %ip_v4f32 Input\n" 4104 "%vert_vertex_id = OpVariable %ip_i32 Input\n" 4105 "%vert_instance_id = OpVariable %ip_i32 Input\n" 4106 4107 "; Geometry Variables\n" 4108 "%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 4109 "%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n" 4110 "%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n" 4111 "%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n" 4112 "%geom_out_color = OpVariable %op_v4f32 Output\n" 4113 "%geom_in_color = OpVariable %ip_a3v4f32 Input\n" 4114 "%geom_out_gl_position = OpVariable %op_v4f32 Output\n" 4115 4116 "; Tessellation Control Variables\n" 4117 "%tessc_out_color = OpVariable %op_a3v4f32 Output\n" 4118 "%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n" 4119 "%tessc_in_color = OpVariable %ip_a32v4f32 Input\n" 4120 "%tessc_out_position = OpVariable %op_a3v4f32 Output\n" 4121 "%tessc_in_position = OpVariable %ip_a32v4f32 Input\n" 4122 "%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" 4123 "%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n" 4124 4125 "; Tessellation Evaluation Decorations\n" 4126 "%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 4127 "%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n" 4128 "%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n" 4129 "%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n" 4130 "%tesse_in_position = OpVariable %ip_a32v4f32 Input\n" 4131 "%tesse_out_color = OpVariable %op_v4f32 Output\n" 4132 "%tesse_in_color = OpVariable %ip_a32v4f32 Input\n" 4133 4134 "; Fragment Variables\n" 4135 "%frag_fragColor = OpVariable %op_v4f32 Output\n" 4136 "%frag_vtxColor = OpVariable %ip_v4f32 Input\n" 4137 4138 "; Vertex Entry\n" 4139 "%vert_main = OpFunction %void None %fun\n" 4140 "%vert_label = OpLabel\n" 4141 "%vert_tmp_position = OpLoad %v4f32 %vert_Position\n" 4142 "OpStore %vert_vtxPosition %vert_tmp_position\n" 4143 "%vert_tmp_color = OpLoad %v4f32 %vert_color\n" 4144 "OpStore %vert_vtxColor %vert_tmp_color\n" 4145 "OpReturn\n" 4146 "OpFunctionEnd\n" 4147 4148 "; Geometry Entry\n" 4149 "%geom_main = OpFunction %void None %fun\n" 4150 "%geom_label = OpLabel\n" 4151 "%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n" 4152 "%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n" 4153 "%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n" 4154 "%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n" 4155 "%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n" 4156 "%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n" 4157 "%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n" 4158 "%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n" 4159 "%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n" 4160 "%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n" 4161 "%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n" 4162 "%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n" 4163 "OpStore %geom_out_gl_position %geom_in_position_0\n" 4164 "OpStore %geom_out_color %geom_in_color_0\n" 4165 "OpEmitVertex\n" 4166 "OpStore %geom_out_gl_position %geom_in_position_1\n" 4167 "OpStore %geom_out_color %geom_in_color_1\n" 4168 "OpEmitVertex\n" 4169 "OpStore %geom_out_gl_position %geom_in_position_2\n" 4170 "OpStore %geom_out_color %geom_in_color_2\n" 4171 "OpEmitVertex\n" 4172 "OpEndPrimitive\n" 4173 "OpReturn\n" 4174 "OpFunctionEnd\n" 4175 4176 "; Tessellation Control Entry\n" 4177 "%tessc_main = OpFunction %void None %fun\n" 4178 "%tessc_label = OpLabel\n" 4179 "%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n" 4180 "%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n" 4181 "%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n" 4182 "%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n" 4183 "%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n" 4184 "%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n" 4185 "%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n" 4186 "OpStore %tessc_out_color_ptr %tessc_in_color_val\n" 4187 "OpStore %tessc_out_position_ptr %tessc_in_position_val\n" 4188 "%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n" 4189 "OpSelectionMerge %tessc_merge_label None\n" 4190 "OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n" 4191 "%tessc_first_invocation = OpLabel\n" 4192 "%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n" 4193 "%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n" 4194 "%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n" 4195 "%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n" 4196 "OpStore %tessc_tess_outer_0 %c_f32_1\n" 4197 "OpStore %tessc_tess_outer_1 %c_f32_1\n" 4198 "OpStore %tessc_tess_outer_2 %c_f32_1\n" 4199 "OpStore %tessc_tess_inner %c_f32_1\n" 4200 "OpBranch %tessc_merge_label\n" 4201 "%tessc_merge_label = OpLabel\n" 4202 "OpReturn\n" 4203 "OpFunctionEnd\n" 4204 4205 "; Tessellation Evaluation Entry\n" 4206 "%tesse_main = OpFunction %void None %fun\n" 4207 "%tesse_label = OpLabel\n" 4208 "%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n" 4209 "%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n" 4210 "%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n" 4211 "%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n" 4212 "%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n" 4213 "%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n" 4214 "%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n" 4215 "%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n" 4216 "%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n" 4217 "%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n" 4218 "%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n" 4219 "%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n" 4220 "%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_pos_0\n" 4221 "%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_pos_1\n" 4222 "%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_pos_2\n" 4223 "%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n" 4224 "%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n" 4225 "%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n" 4226 "OpStore %tesse_out_pos_ptr %tesse_computed_out\n" 4227 "%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n" 4228 "%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n" 4229 "%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n" 4230 "%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n" 4231 "%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n" 4232 "%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n" 4233 "%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_0 %tesse_in_clr_0\n" 4234 "%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_1 %tesse_in_clr_1\n" 4235 "%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_tc_2 %tesse_in_clr_2\n" 4236 "%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n" 4237 "%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n" 4238 "OpStore %tesse_out_color %tesse_computed_clr\n" 4239 "OpReturn\n" 4240 "OpFunctionEnd\n" 4241 4242 "; Fragment Entry\n" 4243 "%frag_main = OpFunction %void None %fun\n" 4244 "%frag_label_main = OpLabel\n" 4245 "%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n" 4246 "OpStore %frag_fragColor %frag_tmp1\n" 4247 "OpReturn\n" 4248 "OpFunctionEnd\n"; 4249} 4250 4251// This has two shaders of each stage. The first 4252// is a passthrough, the second inverts the color. 4253void createMultipleEntries(vk::SourceCollections& dst, InstanceContext) 4254{ 4255 dst.spirvAsmSources.add("vert") << 4256 // This module contains 2 vertex shaders. One that is a passthrough 4257 // and a second that inverts the color of the output (1.0 - color). 4258 "OpCapability Shader\n" 4259 "OpMemoryModel Logical GLSL450\n" 4260 "OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" 4261 "OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n" 4262 4263 "OpName %main \"vert1\"\n" 4264 "OpName %main2 \"vert2\"\n" 4265 "OpName %vtxPosition \"vtxPosition\"\n" 4266 "OpName %Position \"position\"\n" 4267 "OpName %vtxColor \"vtxColor\"\n" 4268 "OpName %color \"color\"\n" 4269 "OpName %vertex_id \"gl_VertexIndex\"\n" 4270 "OpName %instance_id \"gl_InstanceIndex\"\n" 4271 4272 "OpDecorate %vtxPosition Location 2\n" 4273 "OpDecorate %Position Location 0\n" 4274 "OpDecorate %vtxColor Location 1\n" 4275 "OpDecorate %color Location 1\n" 4276 "OpDecorate %vertex_id BuiltIn VertexIndex\n" 4277 "OpDecorate %instance_id BuiltIn InstanceIndex\n" 4278 SPIRV_ASSEMBLY_TYPES 4279 SPIRV_ASSEMBLY_CONSTANTS 4280 SPIRV_ASSEMBLY_ARRAYS 4281 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 4282 "%vtxPosition = OpVariable %op_v4f32 Output\n" 4283 "%Position = OpVariable %ip_v4f32 Input\n" 4284 "%vtxColor = OpVariable %op_v4f32 Output\n" 4285 "%color = OpVariable %ip_v4f32 Input\n" 4286 "%vertex_id = OpVariable %ip_i32 Input\n" 4287 "%instance_id = OpVariable %ip_i32 Input\n" 4288 4289 "%main = OpFunction %void None %fun\n" 4290 "%label = OpLabel\n" 4291 "%tmp_position = OpLoad %v4f32 %Position\n" 4292 "OpStore %vtxPosition %tmp_position\n" 4293 "%tmp_color = OpLoad %v4f32 %color\n" 4294 "OpStore %vtxColor %tmp_color\n" 4295 "OpReturn\n" 4296 "OpFunctionEnd\n" 4297 4298 "%main2 = OpFunction %void None %fun\n" 4299 "%label2 = OpLabel\n" 4300 "%tmp_position2 = OpLoad %v4f32 %Position\n" 4301 "OpStore %vtxPosition %tmp_position2\n" 4302 "%tmp_color2 = OpLoad %v4f32 %color\n" 4303 "%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n" 4304 "%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n" 4305 "OpStore %vtxColor %tmp_color4\n" 4306 "OpReturn\n" 4307 "OpFunctionEnd\n"; 4308 4309 dst.spirvAsmSources.add("frag") << 4310 // This is a single module that contains 2 fragment shaders. 4311 // One that passes color through and the other that inverts the output 4312 // color (1.0 - color). 4313 "OpCapability Shader\n" 4314 "OpMemoryModel Logical GLSL450\n" 4315 "OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n" 4316 "OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n" 4317 "OpExecutionMode %main OriginUpperLeft\n" 4318 "OpExecutionMode %main2 OriginUpperLeft\n" 4319 4320 "OpName %main \"frag1\"\n" 4321 "OpName %main2 \"frag2\"\n" 4322 "OpName %fragColor \"fragColor\"\n" 4323 "OpName %vtxColor \"vtxColor\"\n" 4324 "OpDecorate %fragColor Location 0\n" 4325 "OpDecorate %vtxColor Location 1\n" 4326 SPIRV_ASSEMBLY_TYPES 4327 SPIRV_ASSEMBLY_CONSTANTS 4328 SPIRV_ASSEMBLY_ARRAYS 4329 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 4330 "%fragColor = OpVariable %op_v4f32 Output\n" 4331 "%vtxColor = OpVariable %ip_v4f32 Input\n" 4332 4333 "%main = OpFunction %void None %fun\n" 4334 "%label_main = OpLabel\n" 4335 "%tmp1 = OpLoad %v4f32 %vtxColor\n" 4336 "OpStore %fragColor %tmp1\n" 4337 "OpReturn\n" 4338 "OpFunctionEnd\n" 4339 4340 "%main2 = OpFunction %void None %fun\n" 4341 "%label_main2 = OpLabel\n" 4342 "%tmp2 = OpLoad %v4f32 %vtxColor\n" 4343 "%tmp3 = OpFSub %v4f32 %cval %tmp2\n" 4344 "%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n" 4345 "OpStore %fragColor %tmp4\n" 4346 "OpReturn\n" 4347 "OpFunctionEnd\n"; 4348 4349 dst.spirvAsmSources.add("geom") << 4350 "OpCapability Geometry\n" 4351 "OpCapability ClipDistance\n" 4352 "OpCapability CullDistance\n" 4353 "OpMemoryModel Logical GLSL450\n" 4354 "OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n" 4355 "OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n" 4356 "OpExecutionMode %geom1_main Triangles\n" 4357 "OpExecutionMode %geom2_main Triangles\n" 4358 "OpExecutionMode %geom1_main OutputTriangleStrip\n" 4359 "OpExecutionMode %geom2_main OutputTriangleStrip\n" 4360 "OpExecutionMode %geom1_main OutputVertices 3\n" 4361 "OpExecutionMode %geom2_main OutputVertices 3\n" 4362 "OpName %geom1_main \"geom1\"\n" 4363 "OpName %geom2_main \"geom2\"\n" 4364 "OpName %per_vertex_in \"gl_PerVertex\"\n" 4365 "OpMemberName %per_vertex_in 0 \"gl_Position\"\n" 4366 "OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n" 4367 "OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n" 4368 "OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n" 4369 "OpName %gl_in \"gl_in\"\n" 4370 "OpName %out_color \"out_color\"\n" 4371 "OpName %in_color \"in_color\"\n" 4372 "OpDecorate %out_gl_position BuiltIn Position\n" 4373 "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n" 4374 "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n" 4375 "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n" 4376 "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n" 4377 "OpDecorate %per_vertex_in Block\n" 4378 "OpDecorate %out_color Location 1\n" 4379 "OpDecorate %in_color Location 1\n" 4380 SPIRV_ASSEMBLY_TYPES 4381 SPIRV_ASSEMBLY_CONSTANTS 4382 SPIRV_ASSEMBLY_ARRAYS 4383 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 4384 "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 4385 "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n" 4386 "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n" 4387 "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n" 4388 "%out_color = OpVariable %op_v4f32 Output\n" 4389 "%in_color = OpVariable %ip_a3v4f32 Input\n" 4390 "%out_gl_position = OpVariable %op_v4f32 Output\n" 4391 4392 "%geom1_main = OpFunction %void None %fun\n" 4393 "%geom1_label = OpLabel\n" 4394 "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" 4395 "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" 4396 "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" 4397 "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n" 4398 "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n" 4399 "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n" 4400 "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" 4401 "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" 4402 "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" 4403 "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n" 4404 "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n" 4405 "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n" 4406 "OpStore %out_gl_position %geom1_in_position_0\n" 4407 "OpStore %out_color %geom1_in_color_0\n" 4408 "OpEmitVertex\n" 4409 "OpStore %out_gl_position %geom1_in_position_1\n" 4410 "OpStore %out_color %geom1_in_color_1\n" 4411 "OpEmitVertex\n" 4412 "OpStore %out_gl_position %geom1_in_position_2\n" 4413 "OpStore %out_color %geom1_in_color_2\n" 4414 "OpEmitVertex\n" 4415 "OpEndPrimitive\n" 4416 "OpReturn\n" 4417 "OpFunctionEnd\n" 4418 4419 "%geom2_main = OpFunction %void None %fun\n" 4420 "%geom2_label = OpLabel\n" 4421 "%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n" 4422 "%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n" 4423 "%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n" 4424 "%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n" 4425 "%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n" 4426 "%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n" 4427 "%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" 4428 "%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" 4429 "%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" 4430 "%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n" 4431 "%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n" 4432 "%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n" 4433 "%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n" 4434 "%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n" 4435 "%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n" 4436 "%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n" 4437 "%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n" 4438 "%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n" 4439 "OpStore %out_gl_position %geom2_in_position_0\n" 4440 "OpStore %out_color %geom2_transformed_in_color_0_a\n" 4441 "OpEmitVertex\n" 4442 "OpStore %out_gl_position %geom2_in_position_1\n" 4443 "OpStore %out_color %geom2_transformed_in_color_1_a\n" 4444 "OpEmitVertex\n" 4445 "OpStore %out_gl_position %geom2_in_position_2\n" 4446 "OpStore %out_color %geom2_transformed_in_color_2_a\n" 4447 "OpEmitVertex\n" 4448 "OpEndPrimitive\n" 4449 "OpReturn\n" 4450 "OpFunctionEnd\n"; 4451 4452 dst.spirvAsmSources.add("tessc") << 4453 "OpCapability Tessellation\n" 4454 "OpMemoryModel Logical GLSL450\n" 4455 "OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" 4456 "OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n" 4457 "OpExecutionMode %tessc1_main OutputVertices 3\n" 4458 "OpExecutionMode %tessc2_main OutputVertices 3\n" 4459 "OpName %tessc1_main \"tessc1\"\n" 4460 "OpName %tessc2_main \"tessc2\"\n" 4461 "OpName %out_color \"out_color\"\n" 4462 "OpName %gl_InvocationID \"gl_InvocationID\"\n" 4463 "OpName %in_color \"in_color\"\n" 4464 "OpName %out_position \"out_position\"\n" 4465 "OpName %in_position \"in_position\"\n" 4466 "OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n" 4467 "OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n" 4468 "OpDecorate %out_color Location 1\n" 4469 "OpDecorate %gl_InvocationID BuiltIn InvocationId\n" 4470 "OpDecorate %in_color Location 1\n" 4471 "OpDecorate %out_position Location 2\n" 4472 "OpDecorate %in_position Location 2\n" 4473 "OpDecorate %gl_TessLevelOuter Patch\n" 4474 "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n" 4475 "OpDecorate %gl_TessLevelInner Patch\n" 4476 "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n" 4477 SPIRV_ASSEMBLY_TYPES 4478 SPIRV_ASSEMBLY_CONSTANTS 4479 SPIRV_ASSEMBLY_ARRAYS 4480 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 4481 "%out_color = OpVariable %op_a3v4f32 Output\n" 4482 "%gl_InvocationID = OpVariable %ip_i32 Input\n" 4483 "%in_color = OpVariable %ip_a32v4f32 Input\n" 4484 "%out_position = OpVariable %op_a3v4f32 Output\n" 4485 "%in_position = OpVariable %ip_a32v4f32 Input\n" 4486 "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n" 4487 "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n" 4488 4489 "%tessc1_main = OpFunction %void None %fun\n" 4490 "%tessc1_label = OpLabel\n" 4491 "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n" 4492 "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n" 4493 "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n" 4494 "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n" 4495 "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n" 4496 "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n" 4497 "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n" 4498 "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n" 4499 "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n" 4500 "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n" 4501 "OpSelectionMerge %tessc1_merge_label None\n" 4502 "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n" 4503 "%tessc1_first_invocation = OpLabel\n" 4504 "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" 4505 "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" 4506 "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" 4507 "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" 4508 "OpStore %tessc1_tess_outer_0 %c_f32_1\n" 4509 "OpStore %tessc1_tess_outer_1 %c_f32_1\n" 4510 "OpStore %tessc1_tess_outer_2 %c_f32_1\n" 4511 "OpStore %tessc1_tess_inner %c_f32_1\n" 4512 "OpBranch %tessc1_merge_label\n" 4513 "%tessc1_merge_label = OpLabel\n" 4514 "OpReturn\n" 4515 "OpFunctionEnd\n" 4516 4517 "%tessc2_main = OpFunction %void None %fun\n" 4518 "%tessc2_label = OpLabel\n" 4519 "%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n" 4520 "%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n" 4521 "%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n" 4522 "%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n" 4523 "%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n" 4524 "%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n" 4525 "%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n" 4526 "%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n" 4527 "%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n" 4528 "OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n" 4529 "OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n" 4530 "%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n" 4531 "OpSelectionMerge %tessc2_merge_label None\n" 4532 "OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n" 4533 "%tessc2_first_invocation = OpLabel\n" 4534 "%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n" 4535 "%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n" 4536 "%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n" 4537 "%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n" 4538 "OpStore %tessc2_tess_outer_0 %c_f32_1\n" 4539 "OpStore %tessc2_tess_outer_1 %c_f32_1\n" 4540 "OpStore %tessc2_tess_outer_2 %c_f32_1\n" 4541 "OpStore %tessc2_tess_inner %c_f32_1\n" 4542 "OpBranch %tessc2_merge_label\n" 4543 "%tessc2_merge_label = OpLabel\n" 4544 "OpReturn\n" 4545 "OpFunctionEnd\n"; 4546 4547 dst.spirvAsmSources.add("tesse") << 4548 "OpCapability Tessellation\n" 4549 "OpCapability ClipDistance\n" 4550 "OpCapability CullDistance\n" 4551 "OpMemoryModel Logical GLSL450\n" 4552 "OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n" 4553 "OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n" 4554 "OpExecutionMode %tesse1_main Triangles\n" 4555 "OpExecutionMode %tesse2_main Triangles\n" 4556 "OpName %tesse1_main \"tesse1\"\n" 4557 "OpName %tesse2_main \"tesse2\"\n" 4558 "OpName %per_vertex_out \"gl_PerVertex\"\n" 4559 "OpMemberName %per_vertex_out 0 \"gl_Position\"\n" 4560 "OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n" 4561 "OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n" 4562 "OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n" 4563 "OpName %stream \"\"\n" 4564 "OpName %gl_tessCoord \"gl_TessCoord\"\n" 4565 "OpName %in_position \"in_position\"\n" 4566 "OpName %out_color \"out_color\"\n" 4567 "OpName %in_color \"in_color\"\n" 4568 "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n" 4569 "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n" 4570 "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n" 4571 "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n" 4572 "OpDecorate %per_vertex_out Block\n" 4573 "OpDecorate %gl_tessCoord BuiltIn TessCoord\n" 4574 "OpDecorate %in_position Location 2\n" 4575 "OpDecorate %out_color Location 1\n" 4576 "OpDecorate %in_color Location 1\n" 4577 SPIRV_ASSEMBLY_TYPES 4578 SPIRV_ASSEMBLY_CONSTANTS 4579 SPIRV_ASSEMBLY_ARRAYS 4580 "%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 4581 "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n" 4582 "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n" 4583 "%stream = OpVariable %op_per_vertex_out Output\n" 4584 "%gl_tessCoord = OpVariable %ip_v3f32 Input\n" 4585 "%in_position = OpVariable %ip_a32v4f32 Input\n" 4586 "%out_color = OpVariable %op_v4f32 Output\n" 4587 "%in_color = OpVariable %ip_a32v4f32 Input\n" 4588 4589 "%tesse1_main = OpFunction %void None %fun\n" 4590 "%tesse1_label = OpLabel\n" 4591 "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" 4592 "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" 4593 "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" 4594 "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n" 4595 "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n" 4596 "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n" 4597 "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" 4598 "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" 4599 "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" 4600 "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n" 4601 "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n" 4602 "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n" 4603 "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_pos_0\n" 4604 "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_pos_1\n" 4605 "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_pos_2\n" 4606 "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" 4607 "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n" 4608 "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n" 4609 "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n" 4610 "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" 4611 "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" 4612 "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" 4613 "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n" 4614 "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n" 4615 "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n" 4616 "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_0 %tesse1_in_clr_0\n" 4617 "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_1 %tesse1_in_clr_1\n" 4618 "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_tc_2 %tesse1_in_clr_2\n" 4619 "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n" 4620 "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n" 4621 "OpStore %out_color %tesse1_computed_clr\n" 4622 "OpReturn\n" 4623 "OpFunctionEnd\n" 4624 4625 "%tesse2_main = OpFunction %void None %fun\n" 4626 "%tesse2_label = OpLabel\n" 4627 "%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n" 4628 "%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n" 4629 "%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n" 4630 "%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n" 4631 "%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n" 4632 "%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n" 4633 "%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n" 4634 "%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n" 4635 "%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n" 4636 "%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n" 4637 "%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n" 4638 "%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n" 4639 "%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_pos_0\n" 4640 "%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_pos_1\n" 4641 "%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_pos_2\n" 4642 "%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n" 4643 "%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n" 4644 "%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n" 4645 "OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n" 4646 "%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n" 4647 "%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n" 4648 "%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n" 4649 "%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n" 4650 "%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n" 4651 "%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n" 4652 "%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_0 %tesse2_in_clr_0\n" 4653 "%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_1 %tesse2_in_clr_1\n" 4654 "%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_tc_2 %tesse2_in_clr_2\n" 4655 "%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n" 4656 "%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n" 4657 "%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n" 4658 "%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n" 4659 "OpStore %out_color %tesse2_clr_transformed_a\n" 4660 "OpReturn\n" 4661 "OpFunctionEnd\n"; 4662} 4663 4664// Sets up and runs a Vulkan pipeline, then spot-checks the resulting image. 4665// Feeds the pipeline a set of colored triangles, which then must occur in the 4666// rendered image. The surface is cleared before executing the pipeline, so 4667// whatever the shaders draw can be directly spot-checked. 4668TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance) 4669{ 4670 const VkDevice vkDevice = context.getDevice(); 4671 const DeviceInterface& vk = context.getDeviceInterface(); 4672 const VkQueue queue = context.getUniversalQueue(); 4673 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 4674 const tcu::UVec2 renderSize (256, 256); 4675 vector<ModuleHandleSp> modules; 4676 map<VkShaderStageFlagBits, VkShaderModule> moduleByStage; 4677 const int testSpecificSeed = 31354125; 4678 const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed; 4679 bool supportsGeometry = false; 4680 bool supportsTessellation = false; 4681 bool hasTessellation = false; 4682 4683 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); 4684 supportsGeometry = features.geometryShader == VK_TRUE; 4685 supportsTessellation = features.tessellationShader == VK_TRUE; 4686 hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) || 4687 (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 4688 4689 if (hasTessellation && !supportsTessellation) 4690 { 4691 throw tcu::NotSupportedError(std::string("Tessellation not supported")); 4692 } 4693 4694 if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) && 4695 !supportsGeometry) 4696 { 4697 throw tcu::NotSupportedError(std::string("Geometry not supported")); 4698 } 4699 4700 de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4); 4701 de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4); 4702 const Vec4 vertexData[] = 4703 { 4704 // Upper left corner: 4705 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), 4706 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), 4707 Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), 4708 4709 // Upper right corner: 4710 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), 4711 Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), 4712 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), 4713 4714 // Lower left corner: 4715 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), 4716 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), 4717 Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), 4718 4719 // Lower right corner: 4720 Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), 4721 Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), 4722 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec() 4723 }; 4724 const size_t singleVertexDataSize = 2 * sizeof(Vec4); 4725 const size_t vertexCount = sizeof(vertexData) / singleVertexDataSize; 4726 4727 const VkBufferCreateInfo vertexBufferParams = 4728 { 4729 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 4730 DE_NULL, // const void* pNext; 4731 0u, // VkBufferCreateFlags flags; 4732 (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; 4733 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 4734 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 4735 1u, // deUint32 queueFamilyCount; 4736 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 4737 }; 4738 const Unique<VkBuffer> vertexBuffer (createBuffer(vk, vkDevice, &vertexBufferParams)); 4739 const UniquePtr<Allocation> vertexBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible)); 4740 4741 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset())); 4742 4743 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y()); 4744 const VkBufferCreateInfo readImageBufferParams = 4745 { 4746 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 4747 DE_NULL, // const void* pNext; 4748 0u, // VkBufferCreateFlags flags; 4749 imageSizeBytes, // VkDeviceSize size; 4750 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; 4751 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 4752 1u, // deUint32 queueFamilyCount; 4753 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 4754 }; 4755 const Unique<VkBuffer> readImageBuffer (createBuffer(vk, vkDevice, &readImageBufferParams)); 4756 const UniquePtr<Allocation> readImageBufferMemory (context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); 4757 4758 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); 4759 4760 const VkImageCreateInfo imageParams = 4761 { 4762 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 4763 DE_NULL, // const void* pNext; 4764 0u, // VkImageCreateFlags flags; 4765 VK_IMAGE_TYPE_2D, // VkImageType imageType; 4766 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 4767 { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent; 4768 1u, // deUint32 mipLevels; 4769 1u, // deUint32 arraySize; 4770 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; 4771 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 4772 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 4773 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 4774 1u, // deUint32 queueFamilyCount; 4775 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 4776 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 4777 }; 4778 4779 const Unique<VkImage> image (createImage(vk, vkDevice, &imageParams)); 4780 const UniquePtr<Allocation> imageMemory (context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any)); 4781 4782 VK_CHECK(vk.bindImageMemory(vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset())); 4783 4784 const VkAttachmentDescription colorAttDesc = 4785 { 4786 0u, // VkAttachmentDescriptionFlags flags; 4787 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 4788 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples; 4789 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 4790 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 4791 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 4792 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 4793 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 4794 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 4795 }; 4796 const VkAttachmentReference colorAttRef = 4797 { 4798 0u, // deUint32 attachment; 4799 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; 4800 }; 4801 const VkSubpassDescription subpassDesc = 4802 { 4803 0u, // VkSubpassDescriptionFlags flags; 4804 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 4805 0u, // deUint32 inputCount; 4806 DE_NULL, // const VkAttachmentReference* pInputAttachments; 4807 1u, // deUint32 colorCount; 4808 &colorAttRef, // const VkAttachmentReference* pColorAttachments; 4809 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 4810 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 4811 0u, // deUint32 preserveCount; 4812 DE_NULL, // const VkAttachmentReference* pPreserveAttachments; 4813 4814 }; 4815 const VkRenderPassCreateInfo renderPassParams = 4816 { 4817 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 4818 DE_NULL, // const void* pNext; 4819 (VkRenderPassCreateFlags)0, 4820 1u, // deUint32 attachmentCount; 4821 &colorAttDesc, // const VkAttachmentDescription* pAttachments; 4822 1u, // deUint32 subpassCount; 4823 &subpassDesc, // const VkSubpassDescription* pSubpasses; 4824 0u, // deUint32 dependencyCount; 4825 DE_NULL, // const VkSubpassDependency* pDependencies; 4826 }; 4827 const Unique<VkRenderPass> renderPass (createRenderPass(vk, vkDevice, &renderPassParams)); 4828 4829 const VkImageViewCreateInfo colorAttViewParams = 4830 { 4831 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 4832 DE_NULL, // const void* pNext; 4833 0u, // VkImageViewCreateFlags flags; 4834 *image, // VkImage image; 4835 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 4836 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format; 4837 { 4838 VK_COMPONENT_SWIZZLE_R, 4839 VK_COMPONENT_SWIZZLE_G, 4840 VK_COMPONENT_SWIZZLE_B, 4841 VK_COMPONENT_SWIZZLE_A 4842 }, // VkChannelMapping channels; 4843 { 4844 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 4845 0u, // deUint32 baseMipLevel; 4846 1u, // deUint32 mipLevels; 4847 0u, // deUint32 baseArrayLayer; 4848 1u, // deUint32 arraySize; 4849 }, // VkImageSubresourceRange subresourceRange; 4850 }; 4851 const Unique<VkImageView> colorAttView (createImageView(vk, vkDevice, &colorAttViewParams)); 4852 4853 4854 // Pipeline layout 4855 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 4856 { 4857 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 4858 DE_NULL, // const void* pNext; 4859 (VkPipelineLayoutCreateFlags)0, 4860 0u, // deUint32 descriptorSetCount; 4861 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 4862 0u, // deUint32 pushConstantRangeCount; 4863 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 4864 }; 4865 const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, vkDevice, &pipelineLayoutParams)); 4866 4867 // Pipeline 4868 vector<VkPipelineShaderStageCreateInfo> shaderStageParams; 4869 // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline(). 4870 vector<vector<VkSpecializationMapEntry> > specConstantEntries; 4871 vector<VkSpecializationInfo> specializationInfos; 4872 createPipelineShaderStages(vk, vkDevice, instance, context, modules, shaderStageParams); 4873 4874 // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents. 4875 specConstantEntries.reserve(shaderStageParams.size()); 4876 specializationInfos.reserve(shaderStageParams.size()); 4877 4878 // Patch the specialization info field in PipelineShaderStageCreateInfos. 4879 for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo) 4880 { 4881 const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage); 4882 4883 if (stageIt != instance.specConstants.end()) 4884 { 4885 const size_t numSpecConstants = stageIt->second.size(); 4886 vector<VkSpecializationMapEntry> entries; 4887 VkSpecializationInfo specInfo; 4888 4889 entries.resize(numSpecConstants); 4890 4891 // Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0. 4892 for (size_t ndx = 0; ndx < numSpecConstants; ++ndx) 4893 { 4894 entries[ndx].constantID = (deUint32)ndx; 4895 entries[ndx].offset = deUint32(ndx * sizeof(deInt32)); 4896 entries[ndx].size = sizeof(deInt32); 4897 } 4898 4899 specConstantEntries.push_back(entries); 4900 4901 specInfo.mapEntryCount = (deUint32)numSpecConstants; 4902 specInfo.pMapEntries = specConstantEntries.back().data(); 4903 specInfo.dataSize = numSpecConstants * sizeof(deInt32); 4904 specInfo.pData = stageIt->second.data(); 4905 specializationInfos.push_back(specInfo); 4906 4907 stageInfo->pSpecializationInfo = &specializationInfos.back(); 4908 } 4909 } 4910 const VkPipelineDepthStencilStateCreateInfo depthStencilParams = 4911 { 4912 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 4913 DE_NULL, // const void* pNext; 4914 (VkPipelineDepthStencilStateCreateFlags)0, 4915 DE_FALSE, // deUint32 depthTestEnable; 4916 DE_FALSE, // deUint32 depthWriteEnable; 4917 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; 4918 DE_FALSE, // deUint32 depthBoundsTestEnable; 4919 DE_FALSE, // deUint32 stencilTestEnable; 4920 { 4921 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; 4922 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; 4923 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; 4924 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; 4925 0u, // deUint32 stencilCompareMask; 4926 0u, // deUint32 stencilWriteMask; 4927 0u, // deUint32 stencilReference; 4928 }, // VkStencilOpState front; 4929 { 4930 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp; 4931 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp; 4932 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp; 4933 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp; 4934 0u, // deUint32 stencilCompareMask; 4935 0u, // deUint32 stencilWriteMask; 4936 0u, // deUint32 stencilReference; 4937 }, // VkStencilOpState back; 4938 -1.0f, // float minDepthBounds; 4939 +1.0f, // float maxDepthBounds; 4940 }; 4941 const VkViewport viewport0 = 4942 { 4943 0.0f, // float originX; 4944 0.0f, // float originY; 4945 (float)renderSize.x(), // float width; 4946 (float)renderSize.y(), // float height; 4947 0.0f, // float minDepth; 4948 1.0f, // float maxDepth; 4949 }; 4950 const VkRect2D scissor0 = 4951 { 4952 { 4953 0u, // deInt32 x; 4954 0u, // deInt32 y; 4955 }, // VkOffset2D offset; 4956 { 4957 renderSize.x(), // deInt32 width; 4958 renderSize.y(), // deInt32 height; 4959 }, // VkExtent2D extent; 4960 }; 4961 const VkPipelineViewportStateCreateInfo viewportParams = 4962 { 4963 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 4964 DE_NULL, // const void* pNext; 4965 (VkPipelineViewportStateCreateFlags)0, 4966 1u, // deUint32 viewportCount; 4967 &viewport0, 4968 1u, 4969 &scissor0 4970 }; 4971 const VkSampleMask sampleMask = ~0u; 4972 const VkPipelineMultisampleStateCreateInfo multisampleParams = 4973 { 4974 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 4975 DE_NULL, // const void* pNext; 4976 (VkPipelineMultisampleStateCreateFlags)0, 4977 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples; 4978 DE_FALSE, // deUint32 sampleShadingEnable; 4979 0.0f, // float minSampleShading; 4980 &sampleMask, // const VkSampleMask* pSampleMask; 4981 DE_FALSE, // VkBool32 alphaToCoverageEnable; 4982 DE_FALSE, // VkBool32 alphaToOneEnable; 4983 }; 4984 const VkPipelineRasterizationStateCreateInfo rasterParams = 4985 { 4986 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 4987 DE_NULL, // const void* pNext; 4988 (VkPipelineRasterizationStateCreateFlags)0, 4989 DE_TRUE, // deUint32 depthClipEnable; 4990 DE_FALSE, // deUint32 rasterizerDiscardEnable; 4991 VK_POLYGON_MODE_FILL, // VkFillMode fillMode; 4992 VK_CULL_MODE_NONE, // VkCullMode cullMode; 4993 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 4994 VK_FALSE, // VkBool32 depthBiasEnable; 4995 0.0f, // float depthBias; 4996 0.0f, // float depthBiasClamp; 4997 0.0f, // float slopeScaledDepthBias; 4998 1.0f, // float lineWidth; 4999 }; 5000 const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 5001 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = 5002 { 5003 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 5004 DE_NULL, // const void* pNext; 5005 (VkPipelineInputAssemblyStateCreateFlags)0, 5006 topology, // VkPrimitiveTopology topology; 5007 DE_FALSE, // deUint32 primitiveRestartEnable; 5008 }; 5009 const VkVertexInputBindingDescription vertexBinding0 = 5010 { 5011 0u, // deUint32 binding; 5012 deUint32(singleVertexDataSize), // deUint32 strideInBytes; 5013 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate; 5014 }; 5015 const VkVertexInputAttributeDescription vertexAttrib0[2] = 5016 { 5017 { 5018 0u, // deUint32 location; 5019 0u, // deUint32 binding; 5020 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 5021 0u // deUint32 offsetInBytes; 5022 }, 5023 { 5024 1u, // deUint32 location; 5025 0u, // deUint32 binding; 5026 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 5027 sizeof(Vec4), // deUint32 offsetInBytes; 5028 } 5029 }; 5030 5031 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 5032 { 5033 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 5034 DE_NULL, // const void* pNext; 5035 (VkPipelineVertexInputStateCreateFlags)0, 5036 1u, // deUint32 bindingCount; 5037 &vertexBinding0, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 5038 2u, // deUint32 attributeCount; 5039 vertexAttrib0, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 5040 }; 5041 const VkPipelineColorBlendAttachmentState attBlendParams = 5042 { 5043 DE_FALSE, // deUint32 blendEnable; 5044 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor; 5045 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor; 5046 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; 5047 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha; 5048 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha; 5049 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; 5050 (VK_COLOR_COMPONENT_R_BIT| 5051 VK_COLOR_COMPONENT_G_BIT| 5052 VK_COLOR_COMPONENT_B_BIT| 5053 VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask; 5054 }; 5055 const VkPipelineColorBlendStateCreateInfo blendParams = 5056 { 5057 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 5058 DE_NULL, // const void* pNext; 5059 (VkPipelineColorBlendStateCreateFlags)0, 5060 DE_FALSE, // VkBool32 logicOpEnable; 5061 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 5062 1u, // deUint32 attachmentCount; 5063 &attBlendParams, // const VkPipelineColorBlendAttachmentState* pAttachments; 5064 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; 5065 }; 5066 const VkPipelineDynamicStateCreateInfo dynamicStateInfo = 5067 { 5068 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 5069 DE_NULL, // const void* pNext; 5070 (VkPipelineDynamicStateCreateFlags)0, 5071 0u, // deUint32 dynamicStateCount; 5072 DE_NULL // const VkDynamicState* pDynamicStates; 5073 }; 5074 5075 const VkPipelineTessellationStateCreateInfo tessellationState = 5076 { 5077 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 5078 DE_NULL, 5079 (VkPipelineTessellationStateCreateFlags)0, 5080 3u 5081 }; 5082 5083 const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL; 5084 const VkGraphicsPipelineCreateInfo pipelineParams = 5085 { 5086 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 5087 DE_NULL, // const void* pNext; 5088 0u, // VkPipelineCreateFlags flags; 5089 (deUint32)shaderStageParams.size(), // deUint32 stageCount; 5090 &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; 5091 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 5092 &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 5093 tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 5094 &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 5095 &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState; 5096 &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 5097 &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 5098 &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 5099 &dynamicStateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 5100 *pipelineLayout, // VkPipelineLayout layout; 5101 *renderPass, // VkRenderPass renderPass; 5102 0u, // deUint32 subpass; 5103 DE_NULL, // VkPipeline basePipelineHandle; 5104 0u, // deInt32 basePipelineIndex; 5105 }; 5106 5107 const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, vkDevice, DE_NULL, &pipelineParams)); 5108 5109 // Framebuffer 5110 const VkFramebufferCreateInfo framebufferParams = 5111 { 5112 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 5113 DE_NULL, // const void* pNext; 5114 (VkFramebufferCreateFlags)0, 5115 *renderPass, // VkRenderPass renderPass; 5116 1u, // deUint32 attachmentCount; 5117 &*colorAttView, // const VkImageView* pAttachments; 5118 (deUint32)renderSize.x(), // deUint32 width; 5119 (deUint32)renderSize.y(), // deUint32 height; 5120 1u, // deUint32 layers; 5121 }; 5122 const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, vkDevice, &framebufferParams)); 5123 5124 const VkCommandPoolCreateInfo cmdPoolParams = 5125 { 5126 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 5127 DE_NULL, // const void* pNext; 5128 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCmdPoolCreateFlags flags; 5129 queueFamilyIndex, // deUint32 queueFamilyIndex; 5130 }; 5131 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams)); 5132 5133 // Command buffer 5134 const VkCommandBufferAllocateInfo cmdBufParams = 5135 { 5136 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 5137 DE_NULL, // const void* pNext; 5138 *cmdPool, // VkCmdPool pool; 5139 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level; 5140 1u, // deUint32 count; 5141 }; 5142 const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams)); 5143 5144 const VkCommandBufferBeginInfo cmdBufBeginParams = 5145 { 5146 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 5147 DE_NULL, // const void* pNext; 5148 (VkCommandBufferUsageFlags)0, 5149 (const VkCommandBufferInheritanceInfo*)DE_NULL, 5150 }; 5151 5152 // Record commands 5153 VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams)); 5154 5155 { 5156 const VkMemoryBarrier vertFlushBarrier = 5157 { 5158 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType; 5159 DE_NULL, // const void* pNext; 5160 VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask; 5161 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask; 5162 }; 5163 const VkImageMemoryBarrier colorAttBarrier = 5164 { 5165 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 5166 DE_NULL, // const void* pNext; 5167 0u, // VkMemoryOutputFlags outputMask; 5168 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask; 5169 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 5170 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 5171 queueFamilyIndex, // deUint32 srcQueueFamilyIndex; 5172 queueFamilyIndex, // deUint32 destQueueFamilyIndex; 5173 *image, // VkImage image; 5174 { 5175 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; 5176 0u, // deUint32 baseMipLevel; 5177 1u, // deUint32 mipLevels; 5178 0u, // deUint32 baseArraySlice; 5179 1u, // deUint32 arraySize; 5180 } // VkImageSubresourceRange subresourceRange; 5181 }; 5182 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier); 5183 } 5184 5185 { 5186 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); 5187 const VkRenderPassBeginInfo passBeginParams = 5188 { 5189 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 5190 DE_NULL, // const void* pNext; 5191 *renderPass, // VkRenderPass renderPass; 5192 *framebuffer, // VkFramebuffer framebuffer; 5193 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; 5194 1u, // deUint32 clearValueCount; 5195 &clearValue, // const VkClearValue* pClearValues; 5196 }; 5197 vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); 5198 } 5199 5200 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 5201 { 5202 const VkDeviceSize bindingOffset = 0; 5203 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset); 5204 } 5205 vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/); 5206 vk.cmdEndRenderPass(*cmdBuf); 5207 5208 { 5209 const VkImageMemoryBarrier renderFinishBarrier = 5210 { 5211 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 5212 DE_NULL, // const void* pNext; 5213 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask; 5214 VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask; 5215 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; 5216 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 5217 queueFamilyIndex, // deUint32 srcQueueFamilyIndex; 5218 queueFamilyIndex, // deUint32 destQueueFamilyIndex; 5219 *image, // VkImage image; 5220 { 5221 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 5222 0u, // deUint32 baseMipLevel; 5223 1u, // deUint32 mipLevels; 5224 0u, // deUint32 baseArraySlice; 5225 1u, // deUint32 arraySize; 5226 } // VkImageSubresourceRange subresourceRange; 5227 }; 5228 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier); 5229 } 5230 5231 { 5232 const VkBufferImageCopy copyParams = 5233 { 5234 (VkDeviceSize)0u, // VkDeviceSize bufferOffset; 5235 (deUint32)renderSize.x(), // deUint32 bufferRowLength; 5236 (deUint32)renderSize.y(), // deUint32 bufferImageHeight; 5237 { 5238 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; 5239 0u, // deUint32 mipLevel; 5240 0u, // deUint32 arrayLayer; 5241 1u, // deUint32 arraySize; 5242 }, // VkImageSubresourceCopy imageSubresource; 5243 { 0u, 0u, 0u }, // VkOffset3D imageOffset; 5244 { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; 5245 }; 5246 vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); 5247 } 5248 5249 { 5250 const VkBufferMemoryBarrier copyFinishBarrier = 5251 { 5252 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 5253 DE_NULL, // const void* pNext; 5254 VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask; 5255 VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask; 5256 queueFamilyIndex, // deUint32 srcQueueFamilyIndex; 5257 queueFamilyIndex, // deUint32 destQueueFamilyIndex; 5258 *readImageBuffer, // VkBuffer buffer; 5259 0u, // VkDeviceSize offset; 5260 imageSizeBytes // VkDeviceSize size; 5261 }; 5262 vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©FinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); 5263 } 5264 5265 VK_CHECK(vk.endCommandBuffer(*cmdBuf)); 5266 5267 // Upload vertex data 5268 { 5269 const VkMappedMemoryRange range = 5270 { 5271 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 5272 DE_NULL, // const void* pNext; 5273 vertexBufferMemory->getMemory(), // VkDeviceMemory mem; 5274 0, // VkDeviceSize offset; 5275 (VkDeviceSize)sizeof(vertexData), // VkDeviceSize size; 5276 }; 5277 void* vertexBufPtr = vertexBufferMemory->getHostPtr(); 5278 5279 deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData)); 5280 VK_CHECK(vk.flushMappedMemoryRanges(vkDevice, 1u, &range)); 5281 } 5282 5283 // Submit & wait for completion 5284 { 5285 const VkFenceCreateInfo fenceParams = 5286 { 5287 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 5288 DE_NULL, // const void* pNext; 5289 0u, // VkFenceCreateFlags flags; 5290 }; 5291 const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceParams)); 5292 const VkSubmitInfo submitInfo = 5293 { 5294 VK_STRUCTURE_TYPE_SUBMIT_INFO, 5295 DE_NULL, 5296 0u, 5297 (const VkSemaphore*)DE_NULL, 5298 (const VkPipelineStageFlags*)DE_NULL, 5299 1u, 5300 &cmdBuf.get(), 5301 0u, 5302 (const VkSemaphore*)DE_NULL, 5303 }; 5304 5305 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); 5306 VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull)); 5307 } 5308 5309 const void* imagePtr = readImageBufferMemory->getHostPtr(); 5310 const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 5311 renderSize.x(), renderSize.y(), 1, imagePtr); 5312 // Log image 5313 { 5314 const VkMappedMemoryRange range = 5315 { 5316 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 5317 DE_NULL, // const void* pNext; 5318 readImageBufferMemory->getMemory(), // VkDeviceMemory mem; 5319 0, // VkDeviceSize offset; 5320 imageSizeBytes, // VkDeviceSize size; 5321 }; 5322 5323 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range)); 5324 context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer); 5325 } 5326 5327 const RGBA threshold(1, 1, 1, 1); 5328 const RGBA upperLeft(pixelBuffer.getPixel(1, 1)); 5329 if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold)) 5330 return TestStatus::fail("Upper left corner mismatch"); 5331 5332 const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1)); 5333 if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold)) 5334 return TestStatus::fail("Upper right corner mismatch"); 5335 5336 const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1)); 5337 if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold)) 5338 return TestStatus::fail("Lower left corner mismatch"); 5339 5340 const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1)); 5341 if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold)) 5342 return TestStatus::fail("Lower right corner mismatch"); 5343 5344 return TestStatus::pass("Rendered output matches input"); 5345} 5346 5347void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, const vector<deInt32>& specConstants, tcu::TestCaseGroup* tests) 5348{ 5349 const ShaderElement vertFragPipelineStages[] = 5350 { 5351 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), 5352 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), 5353 }; 5354 5355 const ShaderElement tessPipelineStages[] = 5356 { 5357 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), 5358 ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), 5359 ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), 5360 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), 5361 }; 5362 5363 const ShaderElement geomPipelineStages[] = 5364 { 5365 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), 5366 ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT), 5367 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), 5368 }; 5369 5370 StageToSpecConstantMap specConstantMap; 5371 5372 specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants; 5373 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline, 5374 createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); 5375 5376 specConstantMap.clear(); 5377 specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants; 5378 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline, 5379 createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); 5380 5381 specConstantMap.clear(); 5382 specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants; 5383 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline, 5384 createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); 5385 5386 specConstantMap.clear(); 5387 specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants; 5388 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline, 5389 createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); 5390 5391 specConstantMap.clear(); 5392 specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants; 5393 addFunctionCaseWithPrograms<InstanceContext>(tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline, 5394 createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments, specConstantMap)); 5395} 5396 5397inline void createTestsForAllStages (const std::string& name, const RGBA (&inputColors)[4], const RGBA (&outputColors)[4], const map<string, string>& testCodeFragments, tcu::TestCaseGroup* tests) 5398{ 5399 vector<deInt32> noSpecConstants; 5400 createTestsForAllStages(name, inputColors, outputColors, testCodeFragments, noSpecConstants, tests); 5401} 5402 5403} // anonymous 5404 5405tcu::TestCaseGroup* createOpSourceTests (tcu::TestContext& testCtx) 5406{ 5407 struct NameCodePair { string name, code; }; 5408 RGBA defaultColors[4]; 5409 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsource", "OpSource instruction")); 5410 const std::string opsourceGLSLWithFile = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile "; 5411 map<string, string> fragments = passthruFragments(); 5412 const NameCodePair tests[] = 5413 { 5414 {"unknown", "OpSource Unknown 321"}, 5415 {"essl", "OpSource ESSL 310"}, 5416 {"glsl", "OpSource GLSL 450"}, 5417 {"opencl_cpp", "OpSource OpenCL_CPP 120"}, 5418 {"opencl_c", "OpSource OpenCL_C 120"}, 5419 {"multiple", "OpSource GLSL 450\nOpSource GLSL 450"}, 5420 {"file", opsourceGLSLWithFile}, 5421 {"source", opsourceGLSLWithFile + "\"void main(){}\""}, 5422 // Longest possible source string: SPIR-V limits instructions to 65535 5423 // words, of which the first 4 are opsourceGLSLWithFile; the rest will 5424 // contain 65530 UTF8 characters (one word each) plus one last word 5425 // containing 3 ASCII characters and \0. 5426 {"longsource", opsourceGLSLWithFile + '"' + makeLongUTF8String(65530) + "ccc" + '"'} 5427 }; 5428 5429 getDefaultColors(defaultColors); 5430 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx) 5431 { 5432 fragments["debug"] = tests[testNdx].code; 5433 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get()); 5434 } 5435 5436 return opSourceTests.release(); 5437} 5438 5439tcu::TestCaseGroup* createOpSourceContinuedTests (tcu::TestContext& testCtx) 5440{ 5441 struct NameCodePair { string name, code; }; 5442 RGBA defaultColors[4]; 5443 de::MovePtr<tcu::TestCaseGroup> opSourceTests (new tcu::TestCaseGroup(testCtx, "opsourcecontinued", "OpSourceContinued instruction")); 5444 map<string, string> fragments = passthruFragments(); 5445 const std::string opsource = "%opsrcfile = OpString \"foo.vert\"\nOpSource GLSL 450 %opsrcfile \"void main(){}\"\n"; 5446 const NameCodePair tests[] = 5447 { 5448 {"empty", opsource + "OpSourceContinued \"\""}, 5449 {"short", opsource + "OpSourceContinued \"abcde\""}, 5450 {"multiple", opsource + "OpSourceContinued \"abcde\"\nOpSourceContinued \"fghij\""}, 5451 // Longest possible source string: SPIR-V limits instructions to 65535 5452 // words, of which the first one is OpSourceContinued/length; the rest 5453 // will contain 65533 UTF8 characters (one word each) plus one last word 5454 // containing 3 ASCII characters and \0. 5455 {"long", opsource + "OpSourceContinued \"" + makeLongUTF8String(65533) + "ccc\""} 5456 }; 5457 5458 getDefaultColors(defaultColors); 5459 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx) 5460 { 5461 fragments["debug"] = tests[testNdx].code; 5462 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opSourceTests.get()); 5463 } 5464 5465 return opSourceTests.release(); 5466} 5467 5468tcu::TestCaseGroup* createOpNoLineTests(tcu::TestContext& testCtx) 5469{ 5470 RGBA defaultColors[4]; 5471 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opnoline", "OpNoLine instruction")); 5472 map<string, string> fragments; 5473 getDefaultColors(defaultColors); 5474 fragments["debug"] = 5475 "%name = OpString \"name\"\n"; 5476 5477 fragments["pre_main"] = 5478 "OpNoLine\n" 5479 "OpNoLine\n" 5480 "OpLine %name 1 1\n" 5481 "OpNoLine\n" 5482 "OpLine %name 1 1\n" 5483 "OpLine %name 1 1\n" 5484 "%second_function = OpFunction %v4f32 None %v4f32_function\n" 5485 "OpNoLine\n" 5486 "OpLine %name 1 1\n" 5487 "OpNoLine\n" 5488 "OpLine %name 1 1\n" 5489 "OpLine %name 1 1\n" 5490 "%second_param1 = OpFunctionParameter %v4f32\n" 5491 "OpNoLine\n" 5492 "OpNoLine\n" 5493 "%label_secondfunction = OpLabel\n" 5494 "OpNoLine\n" 5495 "OpReturnValue %second_param1\n" 5496 "OpFunctionEnd\n" 5497 "OpNoLine\n" 5498 "OpNoLine\n"; 5499 5500 fragments["testfun"] = 5501 // A %test_code function that returns its argument unchanged. 5502 "OpNoLine\n" 5503 "OpNoLine\n" 5504 "OpLine %name 1 1\n" 5505 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5506 "OpNoLine\n" 5507 "%param1 = OpFunctionParameter %v4f32\n" 5508 "OpNoLine\n" 5509 "OpNoLine\n" 5510 "%label_testfun = OpLabel\n" 5511 "OpNoLine\n" 5512 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n" 5513 "OpReturnValue %val1\n" 5514 "OpFunctionEnd\n" 5515 "OpLine %name 1 1\n" 5516 "OpNoLine\n"; 5517 5518 createTestsForAllStages("opnoline", defaultColors, defaultColors, fragments, opLineTests.get()); 5519 5520 return opLineTests.release(); 5521} 5522 5523 5524tcu::TestCaseGroup* createOpLineTests(tcu::TestContext& testCtx) 5525{ 5526 RGBA defaultColors[4]; 5527 de::MovePtr<tcu::TestCaseGroup> opLineTests (new tcu::TestCaseGroup(testCtx, "opline", "OpLine instruction")); 5528 map<string, string> fragments; 5529 std::vector<std::pair<std::string, std::string> > problemStrings; 5530 5531 problemStrings.push_back(std::make_pair<std::string, std::string>("empty_name", "")); 5532 problemStrings.push_back(std::make_pair<std::string, std::string>("short_name", "short_name")); 5533 problemStrings.push_back(std::make_pair<std::string, std::string>("long_name", makeLongUTF8String(65530) + "ccc")); 5534 getDefaultColors(defaultColors); 5535 5536 fragments["debug"] = 5537 "%other_name = OpString \"other_name\"\n"; 5538 5539 fragments["pre_main"] = 5540 "OpLine %file_name 32 0\n" 5541 "OpLine %file_name 32 32\n" 5542 "OpLine %file_name 32 40\n" 5543 "OpLine %other_name 32 40\n" 5544 "OpLine %other_name 0 100\n" 5545 "OpLine %other_name 0 4294967295\n" 5546 "OpLine %other_name 4294967295 0\n" 5547 "OpLine %other_name 32 40\n" 5548 "OpLine %file_name 0 0\n" 5549 "%second_function = OpFunction %v4f32 None %v4f32_function\n" 5550 "OpLine %file_name 1 0\n" 5551 "%second_param1 = OpFunctionParameter %v4f32\n" 5552 "OpLine %file_name 1 3\n" 5553 "OpLine %file_name 1 2\n" 5554 "%label_secondfunction = OpLabel\n" 5555 "OpLine %file_name 0 2\n" 5556 "OpReturnValue %second_param1\n" 5557 "OpFunctionEnd\n" 5558 "OpLine %file_name 0 2\n" 5559 "OpLine %file_name 0 2\n"; 5560 5561 fragments["testfun"] = 5562 // A %test_code function that returns its argument unchanged. 5563 "OpLine %file_name 1 0\n" 5564 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5565 "OpLine %file_name 16 330\n" 5566 "%param1 = OpFunctionParameter %v4f32\n" 5567 "OpLine %file_name 14 442\n" 5568 "%label_testfun = OpLabel\n" 5569 "OpLine %file_name 11 1024\n" 5570 "%val1 = OpFunctionCall %v4f32 %second_function %param1\n" 5571 "OpLine %file_name 2 97\n" 5572 "OpReturnValue %val1\n" 5573 "OpFunctionEnd\n" 5574 "OpLine %file_name 5 32\n"; 5575 5576 for (size_t i = 0; i < problemStrings.size(); ++i) 5577 { 5578 map<string, string> testFragments = fragments; 5579 testFragments["debug"] += "%file_name = OpString \"" + problemStrings[i].second + "\"\n"; 5580 createTestsForAllStages(string("opline") + "_" + problemStrings[i].first, defaultColors, defaultColors, testFragments, opLineTests.get()); 5581 } 5582 5583 return opLineTests.release(); 5584} 5585 5586tcu::TestCaseGroup* createOpConstantNullTests(tcu::TestContext& testCtx) 5587{ 5588 de::MovePtr<tcu::TestCaseGroup> opConstantNullTests (new tcu::TestCaseGroup(testCtx, "opconstantnull", "OpConstantNull instruction")); 5589 RGBA colors[4]; 5590 5591 5592 const char functionStart[] = 5593 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5594 "%param1 = OpFunctionParameter %v4f32\n" 5595 "%lbl = OpLabel\n"; 5596 5597 const char functionEnd[] = 5598 "OpReturnValue %transformed_param\n" 5599 "OpFunctionEnd\n"; 5600 5601 struct NameConstantsCode 5602 { 5603 string name; 5604 string constants; 5605 string code; 5606 }; 5607 5608 NameConstantsCode tests[] = 5609 { 5610 { 5611 "vec4", 5612 "%cnull = OpConstantNull %v4f32\n", 5613 "%transformed_param = OpFAdd %v4f32 %param1 %cnull\n" 5614 }, 5615 { 5616 "float", 5617 "%cnull = OpConstantNull %f32\n", 5618 "%vp = OpVariable %fp_v4f32 Function\n" 5619 "%v = OpLoad %v4f32 %vp\n" 5620 "%v0 = OpVectorInsertDynamic %v4f32 %v %cnull %c_i32_0\n" 5621 "%v1 = OpVectorInsertDynamic %v4f32 %v0 %cnull %c_i32_1\n" 5622 "%v2 = OpVectorInsertDynamic %v4f32 %v1 %cnull %c_i32_2\n" 5623 "%v3 = OpVectorInsertDynamic %v4f32 %v2 %cnull %c_i32_3\n" 5624 "%transformed_param = OpFAdd %v4f32 %param1 %v3\n" 5625 }, 5626 { 5627 "bool", 5628 "%cnull = OpConstantNull %bool\n", 5629 "%v = OpVariable %fp_v4f32 Function\n" 5630 " OpStore %v %param1\n" 5631 " OpSelectionMerge %false_label None\n" 5632 " OpBranchConditional %cnull %true_label %false_label\n" 5633 "%true_label = OpLabel\n" 5634 " OpStore %v %c_v4f32_0_5_0_5_0_5_0_5\n" 5635 " OpBranch %false_label\n" 5636 "%false_label = OpLabel\n" 5637 "%transformed_param = OpLoad %v4f32 %v\n" 5638 }, 5639 { 5640 "i32", 5641 "%cnull = OpConstantNull %i32\n", 5642 "%v = OpVariable %fp_v4f32 Function %c_v4f32_0_5_0_5_0_5_0_5\n" 5643 "%b = OpIEqual %bool %cnull %c_i32_0\n" 5644 " OpSelectionMerge %false_label None\n" 5645 " OpBranchConditional %b %true_label %false_label\n" 5646 "%true_label = OpLabel\n" 5647 " OpStore %v %param1\n" 5648 " OpBranch %false_label\n" 5649 "%false_label = OpLabel\n" 5650 "%transformed_param = OpLoad %v4f32 %v\n" 5651 }, 5652 { 5653 "struct", 5654 "%stype = OpTypeStruct %f32 %v4f32\n" 5655 "%fp_stype = OpTypePointer Function %stype\n" 5656 "%cnull = OpConstantNull %stype\n", 5657 "%v = OpVariable %fp_stype Function %cnull\n" 5658 "%f = OpAccessChain %fp_v4f32 %v %c_i32_1\n" 5659 "%f_val = OpLoad %v4f32 %f\n" 5660 "%transformed_param = OpFAdd %v4f32 %param1 %f_val\n" 5661 }, 5662 { 5663 "array", 5664 "%a4_v4f32 = OpTypeArray %v4f32 %c_u32_4\n" 5665 "%fp_a4_v4f32 = OpTypePointer Function %a4_v4f32\n" 5666 "%cnull = OpConstantNull %a4_v4f32\n", 5667 "%v = OpVariable %fp_a4_v4f32 Function %cnull\n" 5668 "%f = OpAccessChain %fp_v4f32 %v %c_u32_0\n" 5669 "%f1 = OpAccessChain %fp_v4f32 %v %c_u32_1\n" 5670 "%f2 = OpAccessChain %fp_v4f32 %v %c_u32_2\n" 5671 "%f3 = OpAccessChain %fp_v4f32 %v %c_u32_3\n" 5672 "%f_val = OpLoad %v4f32 %f\n" 5673 "%f1_val = OpLoad %v4f32 %f1\n" 5674 "%f2_val = OpLoad %v4f32 %f2\n" 5675 "%f3_val = OpLoad %v4f32 %f3\n" 5676 "%t0 = OpFAdd %v4f32 %param1 %f_val\n" 5677 "%t1 = OpFAdd %v4f32 %t0 %f1_val\n" 5678 "%t2 = OpFAdd %v4f32 %t1 %f2_val\n" 5679 "%transformed_param = OpFAdd %v4f32 %t2 %f3_val\n" 5680 }, 5681 { 5682 "matrix", 5683 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n" 5684 "%cnull = OpConstantNull %mat4x4_f32\n", 5685 // Our null matrix * any vector should result in a zero vector. 5686 "%v = OpVectorTimesMatrix %v4f32 %param1 %cnull\n" 5687 "%transformed_param = OpFAdd %v4f32 %param1 %v\n" 5688 } 5689 }; 5690 5691 getHalfColorsFullAlpha(colors); 5692 5693 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx) 5694 { 5695 map<string, string> fragments; 5696 fragments["pre_main"] = tests[testNdx].constants; 5697 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd; 5698 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, opConstantNullTests.get()); 5699 } 5700 return opConstantNullTests.release(); 5701} 5702tcu::TestCaseGroup* createOpConstantCompositeTests(tcu::TestContext& testCtx) 5703{ 5704 de::MovePtr<tcu::TestCaseGroup> opConstantCompositeTests (new tcu::TestCaseGroup(testCtx, "opconstantcomposite", "OpConstantComposite instruction")); 5705 RGBA inputColors[4]; 5706 RGBA outputColors[4]; 5707 5708 5709 const char functionStart[] = 5710 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5711 "%param1 = OpFunctionParameter %v4f32\n" 5712 "%lbl = OpLabel\n"; 5713 5714 const char functionEnd[] = 5715 "OpReturnValue %transformed_param\n" 5716 "OpFunctionEnd\n"; 5717 5718 struct NameConstantsCode 5719 { 5720 string name; 5721 string constants; 5722 string code; 5723 }; 5724 5725 NameConstantsCode tests[] = 5726 { 5727 { 5728 "vec4", 5729 5730 "%cval = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0\n", 5731 "%transformed_param = OpFAdd %v4f32 %param1 %cval\n" 5732 }, 5733 { 5734 "struct", 5735 5736 "%stype = OpTypeStruct %v4f32 %f32\n" 5737 "%fp_stype = OpTypePointer Function %stype\n" 5738 "%f32_n_1 = OpConstant %f32 -1.0\n" 5739 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5 5740 "%cvec = OpConstantComposite %v4f32 %f32_1_5 %f32_1_5 %f32_1_5 %c_f32_1\n" 5741 "%cval = OpConstantComposite %stype %cvec %f32_n_1\n", 5742 5743 "%v = OpVariable %fp_stype Function %cval\n" 5744 "%vec_ptr = OpAccessChain %fp_v4f32 %v %c_u32_0\n" 5745 "%f32_ptr = OpAccessChain %fp_f32 %v %c_u32_1\n" 5746 "%vec_val = OpLoad %v4f32 %vec_ptr\n" 5747 "%f32_val = OpLoad %f32 %f32_ptr\n" 5748 "%tmp1 = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_1 %f32_val\n" // vec4(-1) 5749 "%tmp2 = OpFAdd %v4f32 %tmp1 %param1\n" // param1 + vec4(-1) 5750 "%transformed_param = OpFAdd %v4f32 %tmp2 %vec_val\n" // param1 + vec4(-1) + vec4(1.5, 1.5, 1.5, 1.0) 5751 }, 5752 { 5753 // [1|0|0|0.5] [x] = x + 0.5 5754 // [0|1|0|0.5] [y] = y + 0.5 5755 // [0|0|1|0.5] [z] = z + 0.5 5756 // [0|0|0|1 ] [1] = 1 5757 "matrix", 5758 5759 "%mat4x4_f32 = OpTypeMatrix %v4f32 4\n" 5760 "%v4f32_1_0_0_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_0\n" 5761 "%v4f32_0_1_0_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_1 %c_f32_0 %c_f32_0\n" 5762 "%v4f32_0_0_1_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_1 %c_f32_0\n" 5763 "%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" 5764 "%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", 5765 5766 "%transformed_param = OpMatrixTimesVector %v4f32 %cval %param1\n" 5767 }, 5768 { 5769 "array", 5770 5771 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 5772 "%fp_a4f32 = OpTypePointer Function %a4f32\n" 5773 "%f32_n_1 = OpConstant %f32 -1.0\n" 5774 "%f32_1_5 = OpConstant %f32 !0x3fc00000\n" // +1.5 5775 "%carr = OpConstantComposite %a4f32 %c_f32_0 %f32_n_1 %f32_1_5 %c_f32_0\n", 5776 5777 "%v = OpVariable %fp_a4f32 Function %carr\n" 5778 "%f = OpAccessChain %fp_f32 %v %c_u32_0\n" 5779 "%f1 = OpAccessChain %fp_f32 %v %c_u32_1\n" 5780 "%f2 = OpAccessChain %fp_f32 %v %c_u32_2\n" 5781 "%f3 = OpAccessChain %fp_f32 %v %c_u32_3\n" 5782 "%f_val = OpLoad %f32 %f\n" 5783 "%f1_val = OpLoad %f32 %f1\n" 5784 "%f2_val = OpLoad %f32 %f2\n" 5785 "%f3_val = OpLoad %f32 %f3\n" 5786 "%ftot1 = OpFAdd %f32 %f_val %f1_val\n" 5787 "%ftot2 = OpFAdd %f32 %ftot1 %f2_val\n" 5788 "%ftot3 = OpFAdd %f32 %ftot2 %f3_val\n" // 0 - 1 + 1.5 + 0 5789 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %ftot3\n" 5790 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n" 5791 }, 5792 { 5793 // 5794 // [ 5795 // { 5796 // 0.0, 5797 // [ 1.0, 1.0, 1.0, 1.0] 5798 // }, 5799 // { 5800 // 1.0, 5801 // [ 0.0, 0.5, 0.0, 0.0] 5802 // }, // ^^^ 5803 // { 5804 // 0.0, 5805 // [ 1.0, 1.0, 1.0, 1.0] 5806 // } 5807 // ] 5808 "array_of_struct_of_array", 5809 5810 "%c_v4f32_1_1_1_0 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n" 5811 "%fp_a4f32 = OpTypePointer Function %a4f32\n" 5812 "%stype = OpTypeStruct %f32 %a4f32\n" 5813 "%a3stype = OpTypeArray %stype %c_u32_3\n" 5814 "%fp_a3stype = OpTypePointer Function %a3stype\n" 5815 "%ca4f32_0 = OpConstantComposite %a4f32 %c_f32_0 %c_f32_0_5 %c_f32_0 %c_f32_0\n" 5816 "%ca4f32_1 = OpConstantComposite %a4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" 5817 "%cstype1 = OpConstantComposite %stype %c_f32_0 %ca4f32_1\n" 5818 "%cstype2 = OpConstantComposite %stype %c_f32_1 %ca4f32_0\n" 5819 "%carr = OpConstantComposite %a3stype %cstype1 %cstype2 %cstype1", 5820 5821 "%v = OpVariable %fp_a3stype Function %carr\n" 5822 "%f = OpAccessChain %fp_f32 %v %c_u32_1 %c_u32_1 %c_u32_1\n" 5823 "%f_l = OpLoad %f32 %f\n" 5824 "%add_vec = OpVectorTimesScalar %v4f32 %c_v4f32_1_1_1_0 %f_l\n" 5825 "%transformed_param = OpFAdd %v4f32 %param1 %add_vec\n" 5826 } 5827 }; 5828 5829 getHalfColorsFullAlpha(inputColors); 5830 outputColors[0] = RGBA(255, 255, 255, 255); 5831 outputColors[1] = RGBA(255, 127, 127, 255); 5832 outputColors[2] = RGBA(127, 255, 127, 255); 5833 outputColors[3] = RGBA(127, 127, 255, 255); 5834 5835 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameConstantsCode); ++testNdx) 5836 { 5837 map<string, string> fragments; 5838 fragments["pre_main"] = tests[testNdx].constants; 5839 fragments["testfun"] = string(functionStart) + tests[testNdx].code + functionEnd; 5840 createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, opConstantCompositeTests.get()); 5841 } 5842 return opConstantCompositeTests.release(); 5843} 5844 5845tcu::TestCaseGroup* createSelectionBlockOrderTests(tcu::TestContext& testCtx) 5846{ 5847 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "selection_block_order", "Out-of-order blocks for selection")); 5848 RGBA inputColors[4]; 5849 RGBA outputColors[4]; 5850 map<string, string> fragments; 5851 5852 // vec4 test_code(vec4 param) { 5853 // vec4 result = param; 5854 // for (int i = 0; i < 4; ++i) { 5855 // if (i == 0) result[i] = 0.; 5856 // else result[i] = 1. - result[i]; 5857 // } 5858 // return result; 5859 // } 5860 const char function[] = 5861 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5862 "%param1 = OpFunctionParameter %v4f32\n" 5863 "%lbl = OpLabel\n" 5864 "%iptr = OpVariable %fp_i32 Function\n" 5865 "%result = OpVariable %fp_v4f32 Function\n" 5866 " OpStore %iptr %c_i32_0\n" 5867 " OpStore %result %param1\n" 5868 " OpBranch %loop\n" 5869 5870 // Loop entry block. 5871 "%loop = OpLabel\n" 5872 "%ival = OpLoad %i32 %iptr\n" 5873 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n" 5874 " OpLoopMerge %exit %loop None\n" 5875 " OpBranchConditional %lt_4 %if_entry %exit\n" 5876 5877 // Merge block for loop. 5878 "%exit = OpLabel\n" 5879 "%ret = OpLoad %v4f32 %result\n" 5880 " OpReturnValue %ret\n" 5881 5882 // If-statement entry block. 5883 "%if_entry = OpLabel\n" 5884 "%loc = OpAccessChain %fp_f32 %result %ival\n" 5885 "%eq_0 = OpIEqual %bool %ival %c_i32_0\n" 5886 " OpSelectionMerge %if_exit None\n" 5887 " OpBranchConditional %eq_0 %if_true %if_false\n" 5888 5889 // False branch for if-statement. 5890 "%if_false = OpLabel\n" 5891 "%val = OpLoad %f32 %loc\n" 5892 "%sub = OpFSub %f32 %c_f32_1 %val\n" 5893 " OpStore %loc %sub\n" 5894 " OpBranch %if_exit\n" 5895 5896 // Merge block for if-statement. 5897 "%if_exit = OpLabel\n" 5898 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n" 5899 " OpStore %iptr %ival_next\n" 5900 " OpBranch %loop\n" 5901 5902 // True branch for if-statement. 5903 "%if_true = OpLabel\n" 5904 " OpStore %loc %c_f32_0\n" 5905 " OpBranch %if_exit\n" 5906 5907 " OpFunctionEnd\n"; 5908 5909 fragments["testfun"] = function; 5910 5911 inputColors[0] = RGBA(127, 127, 127, 0); 5912 inputColors[1] = RGBA(127, 0, 0, 0); 5913 inputColors[2] = RGBA(0, 127, 0, 0); 5914 inputColors[3] = RGBA(0, 0, 127, 0); 5915 5916 outputColors[0] = RGBA(0, 128, 128, 255); 5917 outputColors[1] = RGBA(0, 255, 255, 255); 5918 outputColors[2] = RGBA(0, 128, 255, 255); 5919 outputColors[3] = RGBA(0, 255, 128, 255); 5920 5921 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get()); 5922 5923 return group.release(); 5924} 5925 5926tcu::TestCaseGroup* createSwitchBlockOrderTests(tcu::TestContext& testCtx) 5927{ 5928 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "switch_block_order", "Out-of-order blocks for switch")); 5929 RGBA inputColors[4]; 5930 RGBA outputColors[4]; 5931 map<string, string> fragments; 5932 5933 const char typesAndConstants[] = 5934 "%c_f32_p2 = OpConstant %f32 0.2\n" 5935 "%c_f32_p4 = OpConstant %f32 0.4\n" 5936 "%c_f32_p6 = OpConstant %f32 0.6\n" 5937 "%c_f32_p8 = OpConstant %f32 0.8\n"; 5938 5939 // vec4 test_code(vec4 param) { 5940 // vec4 result = param; 5941 // for (int i = 0; i < 4; ++i) { 5942 // switch (i) { 5943 // case 0: result[i] += .2; break; 5944 // case 1: result[i] += .6; break; 5945 // case 2: result[i] += .4; break; 5946 // case 3: result[i] += .8; break; 5947 // default: break; // unreachable 5948 // } 5949 // } 5950 // return result; 5951 // } 5952 const char function[] = 5953 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 5954 "%param1 = OpFunctionParameter %v4f32\n" 5955 "%lbl = OpLabel\n" 5956 "%iptr = OpVariable %fp_i32 Function\n" 5957 "%result = OpVariable %fp_v4f32 Function\n" 5958 " OpStore %iptr %c_i32_0\n" 5959 " OpStore %result %param1\n" 5960 " OpBranch %loop\n" 5961 5962 // Loop entry block. 5963 "%loop = OpLabel\n" 5964 "%ival = OpLoad %i32 %iptr\n" 5965 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n" 5966 " OpLoopMerge %exit %loop None\n" 5967 " OpBranchConditional %lt_4 %switch_entry %exit\n" 5968 5969 // Merge block for loop. 5970 "%exit = OpLabel\n" 5971 "%ret = OpLoad %v4f32 %result\n" 5972 " OpReturnValue %ret\n" 5973 5974 // Switch-statement entry block. 5975 "%switch_entry = OpLabel\n" 5976 "%loc = OpAccessChain %fp_f32 %result %ival\n" 5977 "%val = OpLoad %f32 %loc\n" 5978 " OpSelectionMerge %switch_exit None\n" 5979 " OpSwitch %ival %switch_default 0 %case0 1 %case1 2 %case2 3 %case3\n" 5980 5981 "%case2 = OpLabel\n" 5982 "%addp4 = OpFAdd %f32 %val %c_f32_p4\n" 5983 " OpStore %loc %addp4\n" 5984 " OpBranch %switch_exit\n" 5985 5986 "%switch_default = OpLabel\n" 5987 " OpUnreachable\n" 5988 5989 "%case3 = OpLabel\n" 5990 "%addp8 = OpFAdd %f32 %val %c_f32_p8\n" 5991 " OpStore %loc %addp8\n" 5992 " OpBranch %switch_exit\n" 5993 5994 "%case0 = OpLabel\n" 5995 "%addp2 = OpFAdd %f32 %val %c_f32_p2\n" 5996 " OpStore %loc %addp2\n" 5997 " OpBranch %switch_exit\n" 5998 5999 // Merge block for switch-statement. 6000 "%switch_exit = OpLabel\n" 6001 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n" 6002 " OpStore %iptr %ival_next\n" 6003 " OpBranch %loop\n" 6004 6005 "%case1 = OpLabel\n" 6006 "%addp6 = OpFAdd %f32 %val %c_f32_p6\n" 6007 " OpStore %loc %addp6\n" 6008 " OpBranch %switch_exit\n" 6009 6010 " OpFunctionEnd\n"; 6011 6012 fragments["pre_main"] = typesAndConstants; 6013 fragments["testfun"] = function; 6014 6015 inputColors[0] = RGBA(127, 27, 127, 51); 6016 inputColors[1] = RGBA(127, 0, 0, 51); 6017 inputColors[2] = RGBA(0, 27, 0, 51); 6018 inputColors[3] = RGBA(0, 0, 127, 51); 6019 6020 outputColors[0] = RGBA(178, 180, 229, 255); 6021 outputColors[1] = RGBA(178, 153, 102, 255); 6022 outputColors[2] = RGBA(51, 180, 102, 255); 6023 outputColors[3] = RGBA(51, 153, 229, 255); 6024 6025 createTestsForAllStages("out_of_order", inputColors, outputColors, fragments, group.get()); 6026 6027 return group.release(); 6028} 6029 6030tcu::TestCaseGroup* createDecorationGroupTests(tcu::TestContext& testCtx) 6031{ 6032 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "decoration_group", "Decoration group tests")); 6033 RGBA inputColors[4]; 6034 RGBA outputColors[4]; 6035 map<string, string> fragments; 6036 6037 const char decorations[] = 6038 "OpDecorate %array_group ArrayStride 4\n" 6039 "OpDecorate %struct_member_group Offset 0\n" 6040 "%array_group = OpDecorationGroup\n" 6041 "%struct_member_group = OpDecorationGroup\n" 6042 6043 "OpDecorate %group1 RelaxedPrecision\n" 6044 "OpDecorate %group3 RelaxedPrecision\n" 6045 "OpDecorate %group3 Invariant\n" 6046 "OpDecorate %group3 Restrict\n" 6047 "%group0 = OpDecorationGroup\n" 6048 "%group1 = OpDecorationGroup\n" 6049 "%group3 = OpDecorationGroup\n"; 6050 6051 const char typesAndConstants[] = 6052 "%a3f32 = OpTypeArray %f32 %c_u32_3\n" 6053 "%struct1 = OpTypeStruct %a3f32\n" 6054 "%struct2 = OpTypeStruct %a3f32\n" 6055 "%fp_struct1 = OpTypePointer Function %struct1\n" 6056 "%fp_struct2 = OpTypePointer Function %struct2\n" 6057 "%c_f32_2 = OpConstant %f32 2.\n" 6058 "%c_f32_n2 = OpConstant %f32 -2.\n" 6059 6060 "%c_a3f32_1 = OpConstantComposite %a3f32 %c_f32_1 %c_f32_2 %c_f32_1\n" 6061 "%c_a3f32_2 = OpConstantComposite %a3f32 %c_f32_n1 %c_f32_n2 %c_f32_n1\n" 6062 "%c_struct1 = OpConstantComposite %struct1 %c_a3f32_1\n" 6063 "%c_struct2 = OpConstantComposite %struct2 %c_a3f32_2\n"; 6064 6065 const char function[] = 6066 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6067 "%param = OpFunctionParameter %v4f32\n" 6068 "%entry = OpLabel\n" 6069 "%result = OpVariable %fp_v4f32 Function\n" 6070 "%v_struct1 = OpVariable %fp_struct1 Function\n" 6071 "%v_struct2 = OpVariable %fp_struct2 Function\n" 6072 " OpStore %result %param\n" 6073 " OpStore %v_struct1 %c_struct1\n" 6074 " OpStore %v_struct2 %c_struct2\n" 6075 "%ptr1 = OpAccessChain %fp_f32 %v_struct1 %c_i32_0 %c_i32_2\n" 6076 "%val1 = OpLoad %f32 %ptr1\n" 6077 "%ptr2 = OpAccessChain %fp_f32 %v_struct2 %c_i32_0 %c_i32_2\n" 6078 "%val2 = OpLoad %f32 %ptr2\n" 6079 "%addvalues = OpFAdd %f32 %val1 %val2\n" 6080 "%ptr = OpAccessChain %fp_f32 %result %c_i32_1\n" 6081 "%val = OpLoad %f32 %ptr\n" 6082 "%addresult = OpFAdd %f32 %addvalues %val\n" 6083 " OpStore %ptr %addresult\n" 6084 "%ret = OpLoad %v4f32 %result\n" 6085 " OpReturnValue %ret\n" 6086 " OpFunctionEnd\n"; 6087 6088 struct CaseNameDecoration 6089 { 6090 string name; 6091 string decoration; 6092 }; 6093 6094 CaseNameDecoration tests[] = 6095 { 6096 { 6097 "same_decoration_group_on_multiple_types", 6098 "OpGroupMemberDecorate %struct_member_group %struct1 0 %struct2 0\n" 6099 }, 6100 { 6101 "empty_decoration_group", 6102 "OpGroupDecorate %group0 %a3f32\n" 6103 "OpGroupDecorate %group0 %result\n" 6104 }, 6105 { 6106 "one_element_decoration_group", 6107 "OpGroupDecorate %array_group %a3f32\n" 6108 }, 6109 { 6110 "multiple_elements_decoration_group", 6111 "OpGroupDecorate %group3 %v_struct1\n" 6112 }, 6113 { 6114 "multiple_decoration_groups_on_same_variable", 6115 "OpGroupDecorate %group0 %v_struct2\n" 6116 "OpGroupDecorate %group1 %v_struct2\n" 6117 "OpGroupDecorate %group3 %v_struct2\n" 6118 }, 6119 { 6120 "same_decoration_group_multiple_times", 6121 "OpGroupDecorate %group1 %addvalues\n" 6122 "OpGroupDecorate %group1 %addvalues\n" 6123 "OpGroupDecorate %group1 %addvalues\n" 6124 }, 6125 6126 }; 6127 6128 getHalfColorsFullAlpha(inputColors); 6129 getHalfColorsFullAlpha(outputColors); 6130 6131 for (size_t idx = 0; idx < (sizeof(tests) / sizeof(tests[0])); ++idx) 6132 { 6133 fragments["decoration"] = decorations + tests[idx].decoration; 6134 fragments["pre_main"] = typesAndConstants; 6135 fragments["testfun"] = function; 6136 6137 createTestsForAllStages(tests[idx].name, inputColors, outputColors, fragments, group.get()); 6138 } 6139 6140 return group.release(); 6141} 6142 6143struct SpecConstantTwoIntGraphicsCase 6144{ 6145 const char* caseName; 6146 const char* scDefinition0; 6147 const char* scDefinition1; 6148 const char* scResultType; 6149 const char* scOperation; 6150 deInt32 scActualValue0; 6151 deInt32 scActualValue1; 6152 const char* resultOperation; 6153 RGBA expectedColors[4]; 6154 6155 SpecConstantTwoIntGraphicsCase (const char* name, 6156 const char* definition0, 6157 const char* definition1, 6158 const char* resultType, 6159 const char* operation, 6160 deInt32 value0, 6161 deInt32 value1, 6162 const char* resultOp, 6163 const RGBA (&output)[4]) 6164 : caseName (name) 6165 , scDefinition0 (definition0) 6166 , scDefinition1 (definition1) 6167 , scResultType (resultType) 6168 , scOperation (operation) 6169 , scActualValue0 (value0) 6170 , scActualValue1 (value1) 6171 , resultOperation (resultOp) 6172 { 6173 expectedColors[0] = output[0]; 6174 expectedColors[1] = output[1]; 6175 expectedColors[2] = output[2]; 6176 expectedColors[3] = output[3]; 6177 } 6178}; 6179 6180tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx) 6181{ 6182 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opspecconstantop", "Test the OpSpecConstantOp instruction")); 6183 vector<SpecConstantTwoIntGraphicsCase> cases; 6184 RGBA inputColors[4]; 6185 RGBA outputColors0[4]; 6186 RGBA outputColors1[4]; 6187 RGBA outputColors2[4]; 6188 6189 const char decorations1[] = 6190 "OpDecorate %sc_0 SpecId 0\n" 6191 "OpDecorate %sc_1 SpecId 1\n"; 6192 6193 const char typesAndConstants1[] = 6194 "%sc_0 = OpSpecConstant${SC_DEF0}\n" 6195 "%sc_1 = OpSpecConstant${SC_DEF1}\n" 6196 "%sc_op = OpSpecConstantOp ${SC_RESULT_TYPE} ${SC_OP}\n"; 6197 6198 const char function1[] = 6199 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6200 "%param = OpFunctionParameter %v4f32\n" 6201 "%label = OpLabel\n" 6202 "%result = OpVariable %fp_v4f32 Function\n" 6203 " OpStore %result %param\n" 6204 "%gen = ${GEN_RESULT}\n" 6205 "%index = OpIAdd %i32 %gen %c_i32_1\n" 6206 "%loc = OpAccessChain %fp_f32 %result %index\n" 6207 "%val = OpLoad %f32 %loc\n" 6208 "%add = OpFAdd %f32 %val %c_f32_0_5\n" 6209 " OpStore %loc %add\n" 6210 "%ret = OpLoad %v4f32 %result\n" 6211 " OpReturnValue %ret\n" 6212 " OpFunctionEnd\n"; 6213 6214 inputColors[0] = RGBA(127, 127, 127, 255); 6215 inputColors[1] = RGBA(127, 0, 0, 255); 6216 inputColors[2] = RGBA(0, 127, 0, 255); 6217 inputColors[3] = RGBA(0, 0, 127, 255); 6218 6219 // Derived from inputColors[x] by adding 128 to inputColors[x][0]. 6220 outputColors0[0] = RGBA(255, 127, 127, 255); 6221 outputColors0[1] = RGBA(255, 0, 0, 255); 6222 outputColors0[2] = RGBA(128, 127, 0, 255); 6223 outputColors0[3] = RGBA(128, 0, 127, 255); 6224 6225 // Derived from inputColors[x] by adding 128 to inputColors[x][1]. 6226 outputColors1[0] = RGBA(127, 255, 127, 255); 6227 outputColors1[1] = RGBA(127, 128, 0, 255); 6228 outputColors1[2] = RGBA(0, 255, 0, 255); 6229 outputColors1[3] = RGBA(0, 128, 127, 255); 6230 6231 // Derived from inputColors[x] by adding 128 to inputColors[x][2]. 6232 outputColors2[0] = RGBA(127, 127, 255, 255); 6233 outputColors2[1] = RGBA(127, 0, 128, 255); 6234 outputColors2[2] = RGBA(0, 127, 128, 255); 6235 outputColors2[3] = RGBA(0, 0, 255, 255); 6236 6237 const char addZeroToSc[] = "OpIAdd %i32 %c_i32_0 %sc_op"; 6238 const char selectTrueUsingSc[] = "OpSelect %i32 %sc_op %c_i32_1 %c_i32_0"; 6239 const char selectFalseUsingSc[] = "OpSelect %i32 %sc_op %c_i32_0 %c_i32_1"; 6240 6241 cases.push_back(SpecConstantTwoIntGraphicsCase("iadd", " %i32 0", " %i32 0", "%i32", "IAdd %sc_0 %sc_1", 19, -20, addZeroToSc, outputColors0)); 6242 cases.push_back(SpecConstantTwoIntGraphicsCase("isub", " %i32 0", " %i32 0", "%i32", "ISub %sc_0 %sc_1", 19, 20, addZeroToSc, outputColors0)); 6243 cases.push_back(SpecConstantTwoIntGraphicsCase("imul", " %i32 0", " %i32 0", "%i32", "IMul %sc_0 %sc_1", -1, -1, addZeroToSc, outputColors2)); 6244 cases.push_back(SpecConstantTwoIntGraphicsCase("sdiv", " %i32 0", " %i32 0", "%i32", "SDiv %sc_0 %sc_1", -126, 126, addZeroToSc, outputColors0)); 6245 cases.push_back(SpecConstantTwoIntGraphicsCase("udiv", " %i32 0", " %i32 0", "%i32", "UDiv %sc_0 %sc_1", 126, 126, addZeroToSc, outputColors2)); 6246 cases.push_back(SpecConstantTwoIntGraphicsCase("srem", " %i32 0", " %i32 0", "%i32", "SRem %sc_0 %sc_1", 3, 2, addZeroToSc, outputColors2)); 6247 cases.push_back(SpecConstantTwoIntGraphicsCase("smod", " %i32 0", " %i32 0", "%i32", "SMod %sc_0 %sc_1", 3, 2, addZeroToSc, outputColors2)); 6248 cases.push_back(SpecConstantTwoIntGraphicsCase("umod", " %i32 0", " %i32 0", "%i32", "UMod %sc_0 %sc_1", 1001, 500, addZeroToSc, outputColors2)); 6249 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseand", " %i32 0", " %i32 0", "%i32", "BitwiseAnd %sc_0 %sc_1", 0x33, 0x0d, addZeroToSc, outputColors2)); 6250 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwiseor", " %i32 0", " %i32 0", "%i32", "BitwiseOr %sc_0 %sc_1", 0, 1, addZeroToSc, outputColors2)); 6251 cases.push_back(SpecConstantTwoIntGraphicsCase("bitwisexor", " %i32 0", " %i32 0", "%i32", "BitwiseXor %sc_0 %sc_1", 0x2e, 0x2f, addZeroToSc, outputColors2)); 6252 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightlogical", " %i32 0", " %i32 0", "%i32", "ShiftRightLogical %sc_0 %sc_1", 2, 1, addZeroToSc, outputColors2)); 6253 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftrightarithmetic", " %i32 0", " %i32 0", "%i32", "ShiftRightArithmetic %sc_0 %sc_1", -4, 2, addZeroToSc, outputColors0)); 6254 cases.push_back(SpecConstantTwoIntGraphicsCase("shiftleftlogical", " %i32 0", " %i32 0", "%i32", "ShiftLeftLogical %sc_0 %sc_1", 1, 0, addZeroToSc, outputColors2)); 6255 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthan", " %i32 0", " %i32 0", "%bool", "SLessThan %sc_0 %sc_1", -20, -10, selectTrueUsingSc, outputColors2)); 6256 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthan", " %i32 0", " %i32 0", "%bool", "ULessThan %sc_0 %sc_1", 10, 20, selectTrueUsingSc, outputColors2)); 6257 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthan", " %i32 0", " %i32 0", "%bool", "SGreaterThan %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2)); 6258 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthan", " %i32 0", " %i32 0", "%bool", "UGreaterThan %sc_0 %sc_1", 10, 5, selectTrueUsingSc, outputColors2)); 6259 cases.push_back(SpecConstantTwoIntGraphicsCase("slessthanequal", " %i32 0", " %i32 0", "%bool", "SLessThanEqual %sc_0 %sc_1", -10, -10, selectTrueUsingSc, outputColors2)); 6260 cases.push_back(SpecConstantTwoIntGraphicsCase("ulessthanequal", " %i32 0", " %i32 0", "%bool", "ULessThanEqual %sc_0 %sc_1", 50, 100, selectTrueUsingSc, outputColors2)); 6261 cases.push_back(SpecConstantTwoIntGraphicsCase("sgreaterthanequal", " %i32 0", " %i32 0", "%bool", "SGreaterThanEqual %sc_0 %sc_1", -1000, 50, selectFalseUsingSc, outputColors2)); 6262 cases.push_back(SpecConstantTwoIntGraphicsCase("ugreaterthanequal", " %i32 0", " %i32 0", "%bool", "UGreaterThanEqual %sc_0 %sc_1", 10, 10, selectTrueUsingSc, outputColors2)); 6263 cases.push_back(SpecConstantTwoIntGraphicsCase("iequal", " %i32 0", " %i32 0", "%bool", "IEqual %sc_0 %sc_1", 42, 24, selectFalseUsingSc, outputColors2)); 6264 cases.push_back(SpecConstantTwoIntGraphicsCase("logicaland", "True %bool", "True %bool", "%bool", "LogicalAnd %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2)); 6265 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalor", "False %bool", "False %bool", "%bool", "LogicalOr %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2)); 6266 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalequal", "True %bool", "True %bool", "%bool", "LogicalEqual %sc_0 %sc_1", 0, 1, selectFalseUsingSc, outputColors2)); 6267 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnotequal", "False %bool", "False %bool", "%bool", "LogicalNotEqual %sc_0 %sc_1", 1, 0, selectTrueUsingSc, outputColors2)); 6268 cases.push_back(SpecConstantTwoIntGraphicsCase("snegate", " %i32 0", " %i32 0", "%i32", "SNegate %sc_0", -1, 0, addZeroToSc, outputColors2)); 6269 cases.push_back(SpecConstantTwoIntGraphicsCase("not", " %i32 0", " %i32 0", "%i32", "Not %sc_0", -2, 0, addZeroToSc, outputColors2)); 6270 cases.push_back(SpecConstantTwoIntGraphicsCase("logicalnot", "False %bool", "False %bool", "%bool", "LogicalNot %sc_0", 1, 0, selectFalseUsingSc, outputColors2)); 6271 cases.push_back(SpecConstantTwoIntGraphicsCase("select", "False %bool", " %i32 0", "%i32", "Select %sc_0 %sc_1 %c_i32_0", 1, 1, addZeroToSc, outputColors2)); 6272 // OpSConvert, OpFConvert: these two instructions involve ints/floats of different bitwidths. 6273 // \todo[2015-12-1 antiagainst] OpQuantizeToF16 6274 6275 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx) 6276 { 6277 map<string, string> specializations; 6278 map<string, string> fragments; 6279 vector<deInt32> specConstants; 6280 6281 specializations["SC_DEF0"] = cases[caseNdx].scDefinition0; 6282 specializations["SC_DEF1"] = cases[caseNdx].scDefinition1; 6283 specializations["SC_RESULT_TYPE"] = cases[caseNdx].scResultType; 6284 specializations["SC_OP"] = cases[caseNdx].scOperation; 6285 specializations["GEN_RESULT"] = cases[caseNdx].resultOperation; 6286 6287 fragments["decoration"] = tcu::StringTemplate(decorations1).specialize(specializations); 6288 fragments["pre_main"] = tcu::StringTemplate(typesAndConstants1).specialize(specializations); 6289 fragments["testfun"] = tcu::StringTemplate(function1).specialize(specializations); 6290 6291 specConstants.push_back(cases[caseNdx].scActualValue0); 6292 specConstants.push_back(cases[caseNdx].scActualValue1); 6293 6294 createTestsForAllStages(cases[caseNdx].caseName, inputColors, cases[caseNdx].expectedColors, fragments, specConstants, group.get()); 6295 } 6296 6297 const char decorations2[] = 6298 "OpDecorate %sc_0 SpecId 0\n" 6299 "OpDecorate %sc_1 SpecId 1\n" 6300 "OpDecorate %sc_2 SpecId 2\n"; 6301 6302 const char typesAndConstants2[] = 6303 "%v3i32 = OpTypeVector %i32 3\n" 6304 6305 "%sc_0 = OpSpecConstant %i32 0\n" 6306 "%sc_1 = OpSpecConstant %i32 0\n" 6307 "%sc_2 = OpSpecConstant %i32 0\n" 6308 6309 "%vec3_0 = OpConstantComposite %v3i32 %c_i32_0 %c_i32_0 %c_i32_0\n" 6310 "%sc_vec3_0 = OpSpecConstantOp %v3i32 CompositeInsert %sc_0 %vec3_0 0\n" // (sc_0, 0, 0) 6311 "%sc_vec3_1 = OpSpecConstantOp %v3i32 CompositeInsert %sc_1 %vec3_0 1\n" // (0, sc_1, 0) 6312 "%sc_vec3_2 = OpSpecConstantOp %v3i32 CompositeInsert %sc_2 %vec3_0 2\n" // (0, 0, sc_2) 6313 "%sc_vec3_01 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_0 %sc_vec3_1 1 0 4\n" // (0, sc_0, sc_1) 6314 "%sc_vec3_012 = OpSpecConstantOp %v3i32 VectorShuffle %sc_vec3_01 %sc_vec3_2 5 1 2\n" // (sc_2, sc_0, sc_1) 6315 "%sc_ext_0 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 0\n" // sc_2 6316 "%sc_ext_1 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 1\n" // sc_0 6317 "%sc_ext_2 = OpSpecConstantOp %i32 CompositeExtract %sc_vec3_012 2\n" // sc_1 6318 "%sc_sub = OpSpecConstantOp %i32 ISub %sc_ext_0 %sc_ext_1\n" // (sc_2 - sc_0) 6319 "%sc_final = OpSpecConstantOp %i32 IMul %sc_sub %sc_ext_2\n"; // (sc_2 - sc_0) * sc_1 6320 6321 const char function2[] = 6322 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6323 "%param = OpFunctionParameter %v4f32\n" 6324 "%label = OpLabel\n" 6325 "%result = OpVariable %fp_v4f32 Function\n" 6326 " OpStore %result %param\n" 6327 "%loc = OpAccessChain %fp_f32 %result %sc_final\n" 6328 "%val = OpLoad %f32 %loc\n" 6329 "%add = OpFAdd %f32 %val %c_f32_0_5\n" 6330 " OpStore %loc %add\n" 6331 "%ret = OpLoad %v4f32 %result\n" 6332 " OpReturnValue %ret\n" 6333 " OpFunctionEnd\n"; 6334 6335 map<string, string> fragments; 6336 vector<deInt32> specConstants; 6337 6338 fragments["decoration"] = decorations2; 6339 fragments["pre_main"] = typesAndConstants2; 6340 fragments["testfun"] = function2; 6341 6342 specConstants.push_back(56789); 6343 specConstants.push_back(-2); 6344 specConstants.push_back(56788); 6345 6346 createTestsForAllStages("vector_related", inputColors, outputColors2, fragments, specConstants, group.get()); 6347 6348 return group.release(); 6349} 6350 6351tcu::TestCaseGroup* createOpPhiTests(tcu::TestContext& testCtx) 6352{ 6353 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "opphi", "Test the OpPhi instruction")); 6354 RGBA inputColors[4]; 6355 RGBA outputColors1[4]; 6356 RGBA outputColors2[4]; 6357 RGBA outputColors3[4]; 6358 map<string, string> fragments1; 6359 map<string, string> fragments2; 6360 map<string, string> fragments3; 6361 6362 const char typesAndConstants1[] = 6363 "%c_f32_p2 = OpConstant %f32 0.2\n" 6364 "%c_f32_p4 = OpConstant %f32 0.4\n" 6365 "%c_f32_p5 = OpConstant %f32 0.5\n" 6366 "%c_f32_p8 = OpConstant %f32 0.8\n"; 6367 6368 // vec4 test_code(vec4 param) { 6369 // vec4 result = param; 6370 // for (int i = 0; i < 4; ++i) { 6371 // float operand; 6372 // switch (i) { 6373 // case 0: operand = .2; break; 6374 // case 1: operand = .5; break; 6375 // case 2: operand = .4; break; 6376 // case 3: operand = .0; break; 6377 // default: break; // unreachable 6378 // } 6379 // result[i] += operand; 6380 // } 6381 // return result; 6382 // } 6383 const char function1[] = 6384 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6385 "%param1 = OpFunctionParameter %v4f32\n" 6386 "%lbl = OpLabel\n" 6387 "%iptr = OpVariable %fp_i32 Function\n" 6388 "%result = OpVariable %fp_v4f32 Function\n" 6389 " OpStore %iptr %c_i32_0\n" 6390 " OpStore %result %param1\n" 6391 " OpBranch %loop\n" 6392 6393 "%loop = OpLabel\n" 6394 "%ival = OpLoad %i32 %iptr\n" 6395 "%lt_4 = OpSLessThan %bool %ival %c_i32_4\n" 6396 " OpLoopMerge %exit %loop None\n" 6397 " OpBranchConditional %lt_4 %entry %exit\n" 6398 6399 "%entry = OpLabel\n" 6400 "%loc = OpAccessChain %fp_f32 %result %ival\n" 6401 "%val = OpLoad %f32 %loc\n" 6402 " OpSelectionMerge %phi None\n" 6403 " OpSwitch %ival %default 0 %case0 1 %case1 2 %case2 3 %case3\n" 6404 6405 "%case0 = OpLabel\n" 6406 " OpBranch %phi\n" 6407 "%case1 = OpLabel\n" 6408 " OpBranch %phi\n" 6409 "%case2 = OpLabel\n" 6410 " OpBranch %phi\n" 6411 "%case3 = OpLabel\n" 6412 " OpBranch %phi\n" 6413 6414 "%default = OpLabel\n" 6415 " OpUnreachable\n" 6416 6417 "%phi = OpLabel\n" 6418 "%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 6419 "%add = OpFAdd %f32 %val %operand\n" 6420 " OpStore %loc %add\n" 6421 "%ival_next = OpIAdd %i32 %ival %c_i32_1\n" 6422 " OpStore %iptr %ival_next\n" 6423 " OpBranch %loop\n" 6424 6425 "%exit = OpLabel\n" 6426 "%ret = OpLoad %v4f32 %result\n" 6427 " OpReturnValue %ret\n" 6428 6429 " OpFunctionEnd\n"; 6430 6431 fragments1["pre_main"] = typesAndConstants1; 6432 fragments1["testfun"] = function1; 6433 6434 getHalfColorsFullAlpha(inputColors); 6435 6436 outputColors1[0] = RGBA(178, 255, 229, 255); 6437 outputColors1[1] = RGBA(178, 127, 102, 255); 6438 outputColors1[2] = RGBA(51, 255, 102, 255); 6439 outputColors1[3] = RGBA(51, 127, 229, 255); 6440 6441 createTestsForAllStages("out_of_order", inputColors, outputColors1, fragments1, group.get()); 6442 6443 const char typesAndConstants2[] = 6444 "%c_f32_p2 = OpConstant %f32 0.2\n"; 6445 6446 // Add .4 to the second element of the given parameter. 6447 const char function2[] = 6448 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6449 "%param = OpFunctionParameter %v4f32\n" 6450 "%entry = OpLabel\n" 6451 "%result = OpVariable %fp_v4f32 Function\n" 6452 " OpStore %result %param\n" 6453 "%loc = OpAccessChain %fp_f32 %result %c_i32_1\n" 6454 "%val = OpLoad %f32 %loc\n" 6455 " OpBranch %phi\n" 6456 6457 "%phi = OpLabel\n" 6458 "%step = OpPhi %i32 %c_i32_0 %entry %step_next %phi\n" 6459 "%accum = OpPhi %f32 %val %entry %accum_next %phi\n" 6460 "%step_next = OpIAdd %i32 %step %c_i32_1\n" 6461 "%accum_next = OpFAdd %f32 %accum %c_f32_p2\n" 6462 "%still_loop = OpSLessThan %bool %step %c_i32_2\n" 6463 " OpLoopMerge %exit %phi None\n" 6464 " OpBranchConditional %still_loop %phi %exit\n" 6465 6466 "%exit = OpLabel\n" 6467 " OpStore %loc %accum\n" 6468 "%ret = OpLoad %v4f32 %result\n" 6469 " OpReturnValue %ret\n" 6470 6471 " OpFunctionEnd\n"; 6472 6473 fragments2["pre_main"] = typesAndConstants2; 6474 fragments2["testfun"] = function2; 6475 6476 outputColors2[0] = RGBA(127, 229, 127, 255); 6477 outputColors2[1] = RGBA(127, 102, 0, 255); 6478 outputColors2[2] = RGBA(0, 229, 0, 255); 6479 outputColors2[3] = RGBA(0, 102, 127, 255); 6480 6481 createTestsForAllStages("induction", inputColors, outputColors2, fragments2, group.get()); 6482 6483 const char typesAndConstants3[] = 6484 "%true = OpConstantTrue %bool\n" 6485 "%false = OpConstantFalse %bool\n" 6486 "%c_f32_p2 = OpConstant %f32 0.2\n"; 6487 6488 // Swap the second and the third element of the given parameter. 6489 const char function3[] = 6490 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6491 "%param = OpFunctionParameter %v4f32\n" 6492 "%entry = OpLabel\n" 6493 "%result = OpVariable %fp_v4f32 Function\n" 6494 " OpStore %result %param\n" 6495 "%a_loc = OpAccessChain %fp_f32 %result %c_i32_1\n" 6496 "%a_init = OpLoad %f32 %a_loc\n" 6497 "%b_loc = OpAccessChain %fp_f32 %result %c_i32_2\n" 6498 "%b_init = OpLoad %f32 %b_loc\n" 6499 " OpBranch %phi\n" 6500 6501 "%phi = OpLabel\n" 6502 "%still_loop = OpPhi %bool %true %entry %false %phi\n" 6503 "%a_next = OpPhi %f32 %a_init %entry %b_next %phi\n" 6504 "%b_next = OpPhi %f32 %b_init %entry %a_next %phi\n" 6505 " OpLoopMerge %exit %phi None\n" 6506 " OpBranchConditional %still_loop %phi %exit\n" 6507 6508 "%exit = OpLabel\n" 6509 " OpStore %a_loc %a_next\n" 6510 " OpStore %b_loc %b_next\n" 6511 "%ret = OpLoad %v4f32 %result\n" 6512 " OpReturnValue %ret\n" 6513 6514 " OpFunctionEnd\n"; 6515 6516 fragments3["pre_main"] = typesAndConstants3; 6517 fragments3["testfun"] = function3; 6518 6519 outputColors3[0] = RGBA(127, 127, 127, 255); 6520 outputColors3[1] = RGBA(127, 0, 0, 255); 6521 outputColors3[2] = RGBA(0, 0, 127, 255); 6522 outputColors3[3] = RGBA(0, 127, 0, 255); 6523 6524 createTestsForAllStages("swap", inputColors, outputColors3, fragments3, group.get()); 6525 6526 return group.release(); 6527} 6528 6529tcu::TestCaseGroup* createNoContractionTests(tcu::TestContext& testCtx) 6530{ 6531 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "nocontraction", "Test the NoContraction decoration")); 6532 RGBA inputColors[4]; 6533 RGBA outputColors[4]; 6534 6535 // With NoContraction, (1 + 2^-23) * (1 - 2^-23) - 1 should be conducted as a multiplication and an addition separately. 6536 // For the multiplication, the result is 1 - 2^-46, which is out of the precision range for 32-bit float. (32-bit float 6537 // only have 23-bit fraction.) So it will be rounded to 1. Or 0x1.fffffc. Then the final result is 0 or -0x1p-24. 6538 // On the contrary, the result will be 2^-46, which is a normalized number perfectly representable as 32-bit float. 6539 const char constantsAndTypes[] = 6540 "%c_vec4_0 = OpConstantComposite %v4f32 %c_f32_0 %c_f32_0 %c_f32_0 %c_f32_1\n" 6541 "%c_vec4_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n" 6542 "%c_f32_1pl2_23 = OpConstant %f32 0x1.000002p+0\n" // 1 + 2^-23 6543 "%c_f32_1mi2_23 = OpConstant %f32 0x1.fffffcp-1\n" // 1 - 2^-23 6544 "%c_f32_n1pn24 = OpConstant %f32 -0x1p-24\n" 6545 ; 6546 6547 const char function[] = 6548 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6549 "%param = OpFunctionParameter %v4f32\n" 6550 "%label = OpLabel\n" 6551 "%var1 = OpVariable %fp_f32 Function %c_f32_1pl2_23\n" 6552 "%var2 = OpVariable %fp_f32 Function\n" 6553 "%red = OpCompositeExtract %f32 %param 0\n" 6554 "%plus_red = OpFAdd %f32 %c_f32_1mi2_23 %red\n" 6555 " OpStore %var2 %plus_red\n" 6556 "%val1 = OpLoad %f32 %var1\n" 6557 "%val2 = OpLoad %f32 %var2\n" 6558 "%mul = OpFMul %f32 %val1 %val2\n" 6559 "%add = OpFAdd %f32 %mul %c_f32_n1\n" 6560 "%is0 = OpFOrdEqual %bool %add %c_f32_0\n" 6561 "%isn1n24 = OpFOrdEqual %bool %add %c_f32_n1pn24\n" 6562 "%success = OpLogicalOr %bool %is0 %isn1n24\n" 6563 "%v4success = OpCompositeConstruct %v4bool %success %success %success %success\n" 6564 "%ret = OpSelect %v4f32 %v4success %c_vec4_0 %c_vec4_1\n" 6565 " OpReturnValue %ret\n" 6566 " OpFunctionEnd\n"; 6567 6568 struct CaseNameDecoration 6569 { 6570 string name; 6571 string decoration; 6572 }; 6573 6574 6575 CaseNameDecoration tests[] = { 6576 {"multiplication", "OpDecorate %mul NoContraction"}, 6577 {"addition", "OpDecorate %add NoContraction"}, 6578 {"both", "OpDecorate %mul NoContraction\nOpDecorate %add NoContraction"}, 6579 }; 6580 6581 getHalfColorsFullAlpha(inputColors); 6582 6583 for (deUint8 idx = 0; idx < 4; ++idx) 6584 { 6585 inputColors[idx].setRed(0); 6586 outputColors[idx] = RGBA(0, 0, 0, 255); 6587 } 6588 6589 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(CaseNameDecoration); ++testNdx) 6590 { 6591 map<string, string> fragments; 6592 6593 fragments["decoration"] = tests[testNdx].decoration; 6594 fragments["pre_main"] = constantsAndTypes; 6595 fragments["testfun"] = function; 6596 6597 createTestsForAllStages(tests[testNdx].name, inputColors, outputColors, fragments, group.get()); 6598 } 6599 6600 return group.release(); 6601} 6602 6603tcu::TestCaseGroup* createMemoryAccessTests(tcu::TestContext& testCtx) 6604{ 6605 de::MovePtr<tcu::TestCaseGroup> memoryAccessTests (new tcu::TestCaseGroup(testCtx, "opmemoryaccess", "Memory Semantics")); 6606 RGBA colors[4]; 6607 6608 const char constantsAndTypes[] = 6609 "%c_a2f32_1 = OpConstantComposite %a2f32 %c_f32_1 %c_f32_1\n" 6610 "%fp_a2f32 = OpTypePointer Function %a2f32\n" 6611 "%stype = OpTypeStruct %v4f32 %a2f32 %f32\n" 6612 "%fp_stype = OpTypePointer Function %stype\n"; 6613 6614 const char function[] = 6615 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6616 "%param1 = OpFunctionParameter %v4f32\n" 6617 "%lbl = OpLabel\n" 6618 "%v1 = OpVariable %fp_v4f32 Function\n" 6619 "%v2 = OpVariable %fp_a2f32 Function\n" 6620 "%v3 = OpVariable %fp_f32 Function\n" 6621 "%v = OpVariable %fp_stype Function\n" 6622 "%vv = OpVariable %fp_stype Function\n" 6623 "%vvv = OpVariable %fp_f32 Function\n" 6624 6625 " OpStore %v1 %c_v4f32_1_1_1_1\n" 6626 " OpStore %v2 %c_a2f32_1\n" 6627 " OpStore %v3 %c_f32_1\n" 6628 6629 "%p_v4f32 = OpAccessChain %fp_v4f32 %v %c_u32_0\n" 6630 "%p_a2f32 = OpAccessChain %fp_a2f32 %v %c_u32_1\n" 6631 "%p_f32 = OpAccessChain %fp_f32 %v %c_u32_2\n" 6632 "%v1_v = OpLoad %v4f32 %v1 ${access_type}\n" 6633 "%v2_v = OpLoad %a2f32 %v2 ${access_type}\n" 6634 "%v3_v = OpLoad %f32 %v3 ${access_type}\n" 6635 6636 " OpStore %p_v4f32 %v1_v ${access_type}\n" 6637 " OpStore %p_a2f32 %v2_v ${access_type}\n" 6638 " OpStore %p_f32 %v3_v ${access_type}\n" 6639 6640 " OpCopyMemory %vv %v ${access_type}\n" 6641 " OpCopyMemory %vvv %p_f32 ${access_type}\n" 6642 6643 "%p_f32_2 = OpAccessChain %fp_f32 %vv %c_u32_2\n" 6644 "%v_f32_2 = OpLoad %f32 %p_f32_2\n" 6645 "%v_f32_3 = OpLoad %f32 %vvv\n" 6646 6647 "%ret1 = OpVectorTimesScalar %v4f32 %param1 %v_f32_2\n" 6648 "%ret2 = OpVectorTimesScalar %v4f32 %ret1 %v_f32_3\n" 6649 " OpReturnValue %ret2\n" 6650 " OpFunctionEnd\n"; 6651 6652 struct NameMemoryAccess 6653 { 6654 string name; 6655 string accessType; 6656 }; 6657 6658 6659 NameMemoryAccess tests[] = 6660 { 6661 { "none", "" }, 6662 { "volatile", "Volatile" }, 6663 { "aligned", "Aligned 1" }, 6664 { "volatile_aligned", "Volatile|Aligned 1" }, 6665 { "nontemporal_aligned", "Nontemporal|Aligned 1" }, 6666 { "volatile_nontemporal", "Volatile|Nontemporal" }, 6667 { "volatile_nontermporal_aligned", "Volatile|Nontemporal|Aligned 1" }, 6668 }; 6669 6670 getHalfColorsFullAlpha(colors); 6671 6672 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameMemoryAccess); ++testNdx) 6673 { 6674 map<string, string> fragments; 6675 map<string, string> memoryAccess; 6676 memoryAccess["access_type"] = tests[testNdx].accessType; 6677 6678 fragments["pre_main"] = constantsAndTypes; 6679 fragments["testfun"] = tcu::StringTemplate(function).specialize(memoryAccess); 6680 createTestsForAllStages(tests[testNdx].name, colors, colors, fragments, memoryAccessTests.get()); 6681 } 6682 return memoryAccessTests.release(); 6683} 6684tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx) 6685{ 6686 de::MovePtr<tcu::TestCaseGroup> opUndefTests (new tcu::TestCaseGroup(testCtx, "opundef", "Test OpUndef")); 6687 RGBA defaultColors[4]; 6688 map<string, string> fragments; 6689 getDefaultColors(defaultColors); 6690 6691 // First, simple cases that don't do anything with the OpUndef result. 6692 fragments["testfun"] = 6693 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6694 "%param1 = OpFunctionParameter %v4f32\n" 6695 "%label_testfun = OpLabel\n" 6696 "%undef = OpUndef %type\n" 6697 "OpReturnValue %param1\n" 6698 "OpFunctionEnd\n" 6699 ; 6700 struct NameCodePair { string name, code; }; 6701 const NameCodePair tests[] = 6702 { 6703 {"bool", "%type = OpTypeBool"}, 6704 {"vec2uint32", "%type = OpTypeVector %u32 2"}, 6705 {"image", "%type = OpTypeImage %f32 2D 0 0 0 1 Unknown"}, 6706 {"sampler", "%type = OpTypeSampler"}, 6707 {"sampledimage", "%img = OpTypeImage %f32 2D 0 0 0 1 Unknown\n" "%type = OpTypeSampledImage %img"}, 6708 {"pointer", "%type = OpTypePointer Function %i32"}, 6709 {"runtimearray", "%type = OpTypeRuntimeArray %f32"}, 6710 {"array", "%c_u32_100 = OpConstant %u32 100\n" "%type = OpTypeArray %i32 %c_u32_100"}, 6711 {"struct", "%type = OpTypeStruct %f32 %i32 %u32"}}; 6712 for (size_t testNdx = 0; testNdx < sizeof(tests) / sizeof(NameCodePair); ++testNdx) 6713 { 6714 fragments["pre_main"] = tests[testNdx].code; 6715 createTestsForAllStages(tests[testNdx].name, defaultColors, defaultColors, fragments, opUndefTests.get()); 6716 } 6717 fragments.clear(); 6718 6719 fragments["testfun"] = 6720 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6721 "%param1 = OpFunctionParameter %v4f32\n" 6722 "%label_testfun = OpLabel\n" 6723 "%undef = OpUndef %f32\n" 6724 "%zero = OpFMul %f32 %undef %c_f32_0\n" 6725 "%is_nan = OpIsNan %bool %zero\n" //OpUndef may result in NaN which may turn %zero into Nan. 6726 "%actually_zero = OpSelect %f32 %is_nan %c_f32_0 %zero\n" 6727 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 6728 "%b = OpFAdd %f32 %a %actually_zero\n" 6729 "%ret = OpVectorInsertDynamic %v4f32 %param1 %b %c_i32_0\n" 6730 "OpReturnValue %ret\n" 6731 "OpFunctionEnd\n" 6732 ; 6733 createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get()); 6734 6735 fragments["testfun"] = 6736 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6737 "%param1 = OpFunctionParameter %v4f32\n" 6738 "%label_testfun = OpLabel\n" 6739 "%undef = OpUndef %i32\n" 6740 "%zero = OpIMul %i32 %undef %c_i32_0\n" 6741 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n" 6742 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n" 6743 "OpReturnValue %ret\n" 6744 "OpFunctionEnd\n" 6745 ; 6746 createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get()); 6747 6748 fragments["testfun"] = 6749 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6750 "%param1 = OpFunctionParameter %v4f32\n" 6751 "%label_testfun = OpLabel\n" 6752 "%undef = OpUndef %u32\n" 6753 "%zero = OpIMul %u32 %undef %c_i32_0\n" 6754 "%a = OpVectorExtractDynamic %f32 %param1 %zero\n" 6755 "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n" 6756 "OpReturnValue %ret\n" 6757 "OpFunctionEnd\n" 6758 ; 6759 createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get()); 6760 6761 fragments["testfun"] = 6762 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6763 "%param1 = OpFunctionParameter %v4f32\n" 6764 "%label_testfun = OpLabel\n" 6765 "%undef = OpUndef %v4f32\n" 6766 "%vzero = OpVectorTimesScalar %v4f32 %undef %c_f32_0\n" 6767 "%zero_0 = OpVectorExtractDynamic %f32 %vzero %c_i32_0\n" 6768 "%zero_1 = OpVectorExtractDynamic %f32 %vzero %c_i32_1\n" 6769 "%zero_2 = OpVectorExtractDynamic %f32 %vzero %c_i32_2\n" 6770 "%zero_3 = OpVectorExtractDynamic %f32 %vzero %c_i32_3\n" 6771 "%is_nan_0 = OpIsNan %bool %zero_0\n" 6772 "%is_nan_1 = OpIsNan %bool %zero_1\n" 6773 "%is_nan_2 = OpIsNan %bool %zero_2\n" 6774 "%is_nan_3 = OpIsNan %bool %zero_3\n" 6775 "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n" 6776 "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n" 6777 "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n" 6778 "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n" 6779 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 6780 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n" 6781 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n" 6782 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n" 6783 "%sum_0 = OpFAdd %f32 %param1_0 %actually_zero_0\n" 6784 "%sum_1 = OpFAdd %f32 %param1_1 %actually_zero_1\n" 6785 "%sum_2 = OpFAdd %f32 %param1_2 %actually_zero_2\n" 6786 "%sum_3 = OpFAdd %f32 %param1_3 %actually_zero_3\n" 6787 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n" 6788 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n" 6789 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n" 6790 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n" 6791 "OpReturnValue %ret\n" 6792 "OpFunctionEnd\n" 6793 ; 6794 createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get()); 6795 6796 fragments["pre_main"] = 6797 "%v2f32 = OpTypeVector %f32 2\n" 6798 "%m2x2f32 = OpTypeMatrix %v2f32 2\n"; 6799 fragments["testfun"] = 6800 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6801 "%param1 = OpFunctionParameter %v4f32\n" 6802 "%label_testfun = OpLabel\n" 6803 "%undef = OpUndef %m2x2f32\n" 6804 "%mzero = OpMatrixTimesScalar %m2x2f32 %undef %c_f32_0\n" 6805 "%zero_0 = OpCompositeExtract %f32 %mzero 0 0\n" 6806 "%zero_1 = OpCompositeExtract %f32 %mzero 0 1\n" 6807 "%zero_2 = OpCompositeExtract %f32 %mzero 1 0\n" 6808 "%zero_3 = OpCompositeExtract %f32 %mzero 1 1\n" 6809 "%is_nan_0 = OpIsNan %bool %zero_0\n" 6810 "%is_nan_1 = OpIsNan %bool %zero_1\n" 6811 "%is_nan_2 = OpIsNan %bool %zero_2\n" 6812 "%is_nan_3 = OpIsNan %bool %zero_3\n" 6813 "%actually_zero_0 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_0\n" 6814 "%actually_zero_1 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_1\n" 6815 "%actually_zero_2 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_2\n" 6816 "%actually_zero_3 = OpSelect %f32 %is_nan_0 %c_f32_0 %zero_3\n" 6817 "%param1_0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 6818 "%param1_1 = OpVectorExtractDynamic %f32 %param1 %c_i32_1\n" 6819 "%param1_2 = OpVectorExtractDynamic %f32 %param1 %c_i32_2\n" 6820 "%param1_3 = OpVectorExtractDynamic %f32 %param1 %c_i32_3\n" 6821 "%sum_0 = OpFAdd %f32 %param1_0 %actually_zero_0\n" 6822 "%sum_1 = OpFAdd %f32 %param1_1 %actually_zero_1\n" 6823 "%sum_2 = OpFAdd %f32 %param1_2 %actually_zero_2\n" 6824 "%sum_3 = OpFAdd %f32 %param1_3 %actually_zero_3\n" 6825 "%ret3 = OpVectorInsertDynamic %v4f32 %param1 %sum_3 %c_i32_3\n" 6826 "%ret2 = OpVectorInsertDynamic %v4f32 %ret3 %sum_2 %c_i32_2\n" 6827 "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n" 6828 "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n" 6829 "OpReturnValue %ret\n" 6830 "OpFunctionEnd\n" 6831 ; 6832 createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, opUndefTests.get()); 6833 6834 return opUndefTests.release(); 6835} 6836 6837void createOpQuantizeSingleOptionTests(tcu::TestCaseGroup* testCtx) 6838{ 6839 const RGBA inputColors[4] = 6840 { 6841 RGBA(0, 0, 0, 255), 6842 RGBA(0, 0, 255, 255), 6843 RGBA(0, 255, 0, 255), 6844 RGBA(0, 255, 255, 255) 6845 }; 6846 6847 const RGBA expectedColors[4] = 6848 { 6849 RGBA(255, 0, 0, 255), 6850 RGBA(255, 0, 0, 255), 6851 RGBA(255, 0, 0, 255), 6852 RGBA(255, 0, 0, 255) 6853 }; 6854 6855 const struct SingleFP16Possibility 6856 { 6857 const char* name; 6858 const char* constant; // Value to assign to %test_constant. 6859 float valueAsFloat; 6860 const char* condition; // Must assign to %cond an expression that evaluates to true after %c = OpQuantizeToF16(%test_constant + 0). 6861 } tests[] = 6862 { 6863 { 6864 "negative", 6865 "-0x1.3p1\n", 6866 -constructNormalizedFloat(1, 0x300000), 6867 "%cond = OpFOrdEqual %bool %c %test_constant\n" 6868 }, // -19 6869 { 6870 "positive", 6871 "0x1.0p7\n", 6872 constructNormalizedFloat(7, 0x000000), 6873 "%cond = OpFOrdEqual %bool %c %test_constant\n" 6874 }, // +128 6875 // SPIR-V requires that OpQuantizeToF16 flushes 6876 // any numbers that would end up denormalized in F16 to zero. 6877 { 6878 "denorm", 6879 "0x0.0006p-126\n", 6880 std::ldexp(1.5f, -140), 6881 "%cond = OpFOrdEqual %bool %c %c_f32_0\n" 6882 }, // denorm 6883 { 6884 "negative_denorm", 6885 "-0x0.0006p-126\n", 6886 -std::ldexp(1.5f, -140), 6887 "%cond = OpFOrdEqual %bool %c %c_f32_0\n" 6888 }, // -denorm 6889 { 6890 "too_small", 6891 "0x1.0p-16\n", 6892 std::ldexp(1.0f, -16), 6893 "%cond = OpFOrdEqual %bool %c %c_f32_0\n" 6894 }, // too small positive 6895 { 6896 "negative_too_small", 6897 "-0x1.0p-32\n", 6898 -std::ldexp(1.0f, -32), 6899 "%cond = OpFOrdEqual %bool %c %c_f32_0\n" 6900 }, // too small negative 6901 { 6902 "negative_inf", 6903 "-0x1.0p128\n", 6904 -std::ldexp(1.0f, 128), 6905 6906 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n" 6907 "%inf = OpIsInf %bool %c\n" 6908 "%cond = OpLogicalAnd %bool %gz %inf\n" 6909 }, // -inf to -inf 6910 { 6911 "inf", 6912 "0x1.0p128\n", 6913 std::ldexp(1.0f, 128), 6914 6915 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n" 6916 "%inf = OpIsInf %bool %c\n" 6917 "%cond = OpLogicalAnd %bool %gz %inf\n" 6918 }, // +inf to +inf 6919 { 6920 "round_to_negative_inf", 6921 "-0x1.0p32\n", 6922 -std::ldexp(1.0f, 32), 6923 6924 "%gz = OpFOrdLessThan %bool %c %c_f32_0\n" 6925 "%inf = OpIsInf %bool %c\n" 6926 "%cond = OpLogicalAnd %bool %gz %inf\n" 6927 }, // round to -inf 6928 { 6929 "round_to_inf", 6930 "0x1.0p16\n", 6931 std::ldexp(1.0f, 16), 6932 6933 "%gz = OpFOrdGreaterThan %bool %c %c_f32_0\n" 6934 "%inf = OpIsInf %bool %c\n" 6935 "%cond = OpLogicalAnd %bool %gz %inf\n" 6936 }, // round to +inf 6937 { 6938 "nan", 6939 "0x1.1p128\n", 6940 std::numeric_limits<float>::quiet_NaN(), 6941 6942 // Test for any NaN value, as NaNs are not preserved 6943 "%direct_quant = OpQuantizeToF16 %f32 %test_constant\n" 6944 "%cond = OpIsNan %bool %direct_quant\n" 6945 }, // nan 6946 { 6947 "negative_nan", 6948 "-0x1.0001p128\n", 6949 std::numeric_limits<float>::quiet_NaN(), 6950 6951 // Test for any NaN value, as NaNs are not preserved 6952 "%direct_quant = OpQuantizeToF16 %f32 %test_constant\n" 6953 "%cond = OpIsNan %bool %direct_quant\n" 6954 } // -nan 6955 }; 6956 const char* constants = 6957 "%test_constant = OpConstant %f32 "; // The value will be test.constant. 6958 6959 StringTemplate function ( 6960 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6961 "%param1 = OpFunctionParameter %v4f32\n" 6962 "%label_testfun = OpLabel\n" 6963 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 6964 "%b = OpFAdd %f32 %test_constant %a\n" 6965 "%c = OpQuantizeToF16 %f32 %b\n" 6966 "${condition}\n" 6967 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n" 6968 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1\n" 6969 " OpReturnValue %retval\n" 6970 "OpFunctionEnd\n" 6971 ); 6972 6973 const char* specDecorations = "OpDecorate %test_constant SpecId 0\n"; 6974 const char* specConstants = 6975 "%test_constant = OpSpecConstant %f32 0.\n" 6976 "%c = OpSpecConstantOp %f32 QuantizeToF16 %test_constant\n"; 6977 6978 StringTemplate specConstantFunction( 6979 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 6980 "%param1 = OpFunctionParameter %v4f32\n" 6981 "%label_testfun = OpLabel\n" 6982 "${condition}\n" 6983 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n" 6984 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1\n" 6985 " OpReturnValue %retval\n" 6986 "OpFunctionEnd\n" 6987 ); 6988 6989 for (size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) 6990 { 6991 map<string, string> codeSpecialization; 6992 map<string, string> fragments; 6993 codeSpecialization["condition"] = tests[idx].condition; 6994 fragments["testfun"] = function.specialize(codeSpecialization); 6995 fragments["pre_main"] = string(constants) + tests[idx].constant + "\n"; 6996 createTestsForAllStages(tests[idx].name, inputColors, expectedColors, fragments, testCtx); 6997 } 6998 6999 for (size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) 7000 { 7001 map<string, string> codeSpecialization; 7002 map<string, string> fragments; 7003 vector<deInt32> passConstants; 7004 deInt32 specConstant; 7005 7006 codeSpecialization["condition"] = tests[idx].condition; 7007 fragments["testfun"] = specConstantFunction.specialize(codeSpecialization); 7008 fragments["decoration"] = specDecorations; 7009 fragments["pre_main"] = specConstants; 7010 7011 memcpy(&specConstant, &tests[idx].valueAsFloat, sizeof(float)); 7012 passConstants.push_back(specConstant); 7013 7014 createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx); 7015 } 7016} 7017 7018void createOpQuantizeTwoPossibilityTests(tcu::TestCaseGroup* testCtx) 7019{ 7020 RGBA inputColors[4] = { 7021 RGBA(0, 0, 0, 255), 7022 RGBA(0, 0, 255, 255), 7023 RGBA(0, 255, 0, 255), 7024 RGBA(0, 255, 255, 255) 7025 }; 7026 7027 RGBA expectedColors[4] = 7028 { 7029 RGBA(255, 0, 0, 255), 7030 RGBA(255, 0, 0, 255), 7031 RGBA(255, 0, 0, 255), 7032 RGBA(255, 0, 0, 255) 7033 }; 7034 7035 struct DualFP16Possibility 7036 { 7037 const char* name; 7038 const char* input; 7039 float inputAsFloat; 7040 const char* possibleOutput1; 7041 const char* possibleOutput2; 7042 } tests[] = { 7043 { 7044 "positive_round_up_or_round_down", 7045 "0x1.3003p8", 7046 constructNormalizedFloat(8, 0x300300), 7047 "0x1.304p8", 7048 "0x1.3p8" 7049 }, 7050 { 7051 "negative_round_up_or_round_down", 7052 "-0x1.6008p-7", 7053 -constructNormalizedFloat(-7, 0x600800), 7054 "-0x1.6p-7", 7055 "-0x1.604p-7" 7056 }, 7057 { 7058 "carry_bit", 7059 "0x1.01ep2", 7060 constructNormalizedFloat(2, 0x01e000), 7061 "0x1.01cp2", 7062 "0x1.02p2" 7063 }, 7064 { 7065 "carry_to_exponent", 7066 "0x1.ffep1", 7067 constructNormalizedFloat(1, 0xffe000), 7068 "0x1.ffcp1", 7069 "0x1.0p2" 7070 }, 7071 }; 7072 StringTemplate constants ( 7073 "%input_const = OpConstant %f32 ${input}\n" 7074 "%possible_solution1 = OpConstant %f32 ${output1}\n" 7075 "%possible_solution2 = OpConstant %f32 ${output2}\n" 7076 ); 7077 7078 StringTemplate specConstants ( 7079 "%input_const = OpSpecConstant %f32 0.\n" 7080 "%possible_solution1 = OpConstant %f32 ${output1}\n" 7081 "%possible_solution2 = OpConstant %f32 ${output2}\n" 7082 ); 7083 7084 const char* specDecorations = "OpDecorate %input_const SpecId 0\n"; 7085 7086 const char* function = 7087 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7088 "%param1 = OpFunctionParameter %v4f32\n" 7089 "%label_testfun = OpLabel\n" 7090 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7091 // For the purposes of this test we assume that 0.f will always get 7092 // faithfully passed through the pipeline stages. 7093 "%b = OpFAdd %f32 %input_const %a\n" 7094 "%c = OpQuantizeToF16 %f32 %b\n" 7095 "%eq_1 = OpFOrdEqual %bool %c %possible_solution1\n" 7096 "%eq_2 = OpFOrdEqual %bool %c %possible_solution2\n" 7097 "%cond = OpLogicalOr %bool %eq_1 %eq_2\n" 7098 "%v4cond = OpCompositeConstruct %v4bool %cond %cond %cond %cond\n" 7099 "%retval = OpSelect %v4f32 %v4cond %c_v4f32_1_0_0_1 %param1" 7100 " OpReturnValue %retval\n" 7101 "OpFunctionEnd\n"; 7102 7103 for(size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) { 7104 map<string, string> fragments; 7105 map<string, string> constantSpecialization; 7106 7107 constantSpecialization["input"] = tests[idx].input; 7108 constantSpecialization["output1"] = tests[idx].possibleOutput1; 7109 constantSpecialization["output2"] = tests[idx].possibleOutput2; 7110 fragments["testfun"] = function; 7111 fragments["pre_main"] = constants.specialize(constantSpecialization); 7112 createTestsForAllStages(tests[idx].name, inputColors, expectedColors, fragments, testCtx); 7113 } 7114 7115 for(size_t idx = 0; idx < (sizeof(tests)/sizeof(tests[0])); ++idx) { 7116 map<string, string> fragments; 7117 map<string, string> constantSpecialization; 7118 vector<deInt32> passConstants; 7119 deInt32 specConstant; 7120 7121 constantSpecialization["output1"] = tests[idx].possibleOutput1; 7122 constantSpecialization["output2"] = tests[idx].possibleOutput2; 7123 fragments["testfun"] = function; 7124 fragments["decoration"] = specDecorations; 7125 fragments["pre_main"] = specConstants.specialize(constantSpecialization); 7126 7127 memcpy(&specConstant, &tests[idx].inputAsFloat, sizeof(float)); 7128 passConstants.push_back(specConstant); 7129 7130 createTestsForAllStages(string("spec_const_") + tests[idx].name, inputColors, expectedColors, fragments, passConstants, testCtx); 7131 } 7132} 7133 7134tcu::TestCaseGroup* createOpQuantizeTests(tcu::TestContext& testCtx) 7135{ 7136 de::MovePtr<tcu::TestCaseGroup> opQuantizeTests (new tcu::TestCaseGroup(testCtx, "opquantize", "Test OpQuantizeToF16")); 7137 createOpQuantizeSingleOptionTests(opQuantizeTests.get()); 7138 createOpQuantizeTwoPossibilityTests(opQuantizeTests.get()); 7139 return opQuantizeTests.release(); 7140} 7141 7142struct ShaderPermutation 7143{ 7144 deUint8 vertexPermutation; 7145 deUint8 geometryPermutation; 7146 deUint8 tesscPermutation; 7147 deUint8 tessePermutation; 7148 deUint8 fragmentPermutation; 7149}; 7150 7151ShaderPermutation getShaderPermutation(deUint8 inputValue) 7152{ 7153 ShaderPermutation permutation = 7154 { 7155 static_cast<deUint8>(inputValue & 0x10? 1u: 0u), 7156 static_cast<deUint8>(inputValue & 0x08? 1u: 0u), 7157 static_cast<deUint8>(inputValue & 0x04? 1u: 0u), 7158 static_cast<deUint8>(inputValue & 0x02? 1u: 0u), 7159 static_cast<deUint8>(inputValue & 0x01? 1u: 0u) 7160 }; 7161 return permutation; 7162} 7163 7164tcu::TestCaseGroup* createModuleTests(tcu::TestContext& testCtx) 7165{ 7166 RGBA defaultColors[4]; 7167 RGBA invertedColors[4]; 7168 de::MovePtr<tcu::TestCaseGroup> moduleTests (new tcu::TestCaseGroup(testCtx, "module", "Multiple entry points into shaders")); 7169 7170 const ShaderElement combinedPipeline[] = 7171 { 7172 ShaderElement("module", "main", VK_SHADER_STAGE_VERTEX_BIT), 7173 ShaderElement("module", "main", VK_SHADER_STAGE_GEOMETRY_BIT), 7174 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), 7175 ShaderElement("module", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), 7176 ShaderElement("module", "main", VK_SHADER_STAGE_FRAGMENT_BIT) 7177 }; 7178 7179 getDefaultColors(defaultColors); 7180 getInvertedDefaultColors(invertedColors); 7181 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), "same_module", "", createCombinedModule, runAndVerifyDefaultPipeline, createInstanceContext(combinedPipeline, map<string, string>())); 7182 7183 const char* numbers[] = 7184 { 7185 "1", "2" 7186 }; 7187 7188 for (deInt8 idx = 0; idx < 32; ++idx) 7189 { 7190 ShaderPermutation permutation = getShaderPermutation(idx); 7191 string name = string("vert") + numbers[permutation.vertexPermutation] + "_geom" + numbers[permutation.geometryPermutation] + "_tessc" + numbers[permutation.tesscPermutation] + "_tesse" + numbers[permutation.tessePermutation] + "_frag" + numbers[permutation.fragmentPermutation]; 7192 const ShaderElement pipeline[] = 7193 { 7194 ShaderElement("vert", string("vert") + numbers[permutation.vertexPermutation], VK_SHADER_STAGE_VERTEX_BIT), 7195 ShaderElement("geom", string("geom") + numbers[permutation.geometryPermutation], VK_SHADER_STAGE_GEOMETRY_BIT), 7196 ShaderElement("tessc", string("tessc") + numbers[permutation.tesscPermutation], VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), 7197 ShaderElement("tesse", string("tesse") + numbers[permutation.tessePermutation], VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), 7198 ShaderElement("frag", string("frag") + numbers[permutation.fragmentPermutation], VK_SHADER_STAGE_FRAGMENT_BIT) 7199 }; 7200 7201 // If there are an even number of swaps, then it should be no-op. 7202 // If there are an odd number, the color should be flipped. 7203 if ((permutation.vertexPermutation + permutation.geometryPermutation + permutation.tesscPermutation + permutation.tessePermutation + permutation.fragmentPermutation) % 2 == 0) 7204 { 7205 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, defaultColors, map<string, string>())); 7206 } 7207 else 7208 { 7209 addFunctionCaseWithPrograms<InstanceContext>(moduleTests.get(), name, "", createMultipleEntries, runAndVerifyDefaultPipeline, createInstanceContext(pipeline, defaultColors, invertedColors, map<string, string>())); 7210 } 7211 } 7212 return moduleTests.release(); 7213} 7214 7215tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx) 7216{ 7217 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "loop", "Looping control flow")); 7218 RGBA defaultColors[4]; 7219 getDefaultColors(defaultColors); 7220 map<string, string> fragments; 7221 fragments["pre_main"] = 7222 "%c_f32_5 = OpConstant %f32 5.\n"; 7223 7224 // A loop with a single block. The Continue Target is the loop block 7225 // itself. In SPIR-V terms, the "loop construct" contains no blocks at all 7226 // -- the "continue construct" forms the entire loop. 7227 fragments["testfun"] = 7228 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7229 "%param1 = OpFunctionParameter %v4f32\n" 7230 7231 "%entry = OpLabel\n" 7232 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7233 "OpBranch %loop\n" 7234 7235 ";adds and subtracts 1.0 to %val in alternate iterations\n" 7236 "%loop = OpLabel\n" 7237 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %loop\n" 7238 "%delta = OpPhi %f32 %c_f32_1 %entry %minus_delta %loop\n" 7239 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n" 7240 "%val = OpFAdd %f32 %val1 %delta\n" 7241 "%minus_delta = OpFSub %f32 %c_f32_0 %delta\n" 7242 "%count__ = OpISub %i32 %count %c_i32_1\n" 7243 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7244 "OpLoopMerge %exit %loop None\n" 7245 "OpBranchConditional %again %loop %exit\n" 7246 7247 "%exit = OpLabel\n" 7248 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n" 7249 "OpReturnValue %result\n" 7250 7251 "OpFunctionEnd\n" 7252 ; 7253 createTestsForAllStages("single_block", defaultColors, defaultColors, fragments, testGroup.get()); 7254 7255 // Body comprised of multiple basic blocks. 7256 const StringTemplate multiBlock( 7257 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7258 "%param1 = OpFunctionParameter %v4f32\n" 7259 7260 "%entry = OpLabel\n" 7261 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7262 "OpBranch %loop\n" 7263 7264 ";adds and subtracts 1.0 to %val in alternate iterations\n" 7265 "%loop = OpLabel\n" 7266 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %gather\n" 7267 "%delta = OpPhi %f32 %c_f32_1 %entry %delta_next %gather\n" 7268 "%val1 = OpPhi %f32 %val0 %entry %val %gather\n" 7269 // There are several possibilities for the Continue Target below. Each 7270 // will be specialized into a separate test case. 7271 "OpLoopMerge %exit ${continue_target} None\n" 7272 "OpBranch %if\n" 7273 7274 "%if = OpLabel\n" 7275 ";delta_next = (delta > 0) ? -1 : 1;\n" 7276 "%gt0 = OpFOrdGreaterThan %bool %delta %c_f32_0\n" 7277 "OpSelectionMerge %gather DontFlatten\n" 7278 "OpBranchConditional %gt0 %even %odd ;tells us if %count is even or odd\n" 7279 7280 "%odd = OpLabel\n" 7281 "OpBranch %gather\n" 7282 7283 "%even = OpLabel\n" 7284 "OpBranch %gather\n" 7285 7286 "%gather = OpLabel\n" 7287 "%delta_next = OpPhi %f32 %c_f32_n1 %even %c_f32_1 %odd\n" 7288 "%val = OpFAdd %f32 %val1 %delta\n" 7289 "%count__ = OpISub %i32 %count %c_i32_1\n" 7290 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7291 "OpBranchConditional %again %loop %exit\n" 7292 7293 "%exit = OpLabel\n" 7294 "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n" 7295 "OpReturnValue %result\n" 7296 7297 "OpFunctionEnd\n"); 7298 7299 map<string, string> continue_target; 7300 7301 // The Continue Target is the loop block itself. 7302 continue_target["continue_target"] = "%loop"; 7303 fragments["testfun"] = multiBlock.specialize(continue_target); 7304 createTestsForAllStages("multi_block_continue_construct", defaultColors, defaultColors, fragments, testGroup.get()); 7305 7306 // The Continue Target is at the end of the loop. 7307 continue_target["continue_target"] = "%gather"; 7308 fragments["testfun"] = multiBlock.specialize(continue_target); 7309 createTestsForAllStages("multi_block_loop_construct", defaultColors, defaultColors, fragments, testGroup.get()); 7310 7311 // A loop with continue statement. 7312 fragments["testfun"] = 7313 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7314 "%param1 = OpFunctionParameter %v4f32\n" 7315 7316 "%entry = OpLabel\n" 7317 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7318 "OpBranch %loop\n" 7319 7320 ";adds 4, 3, and 1 to %val0 (skips 2)\n" 7321 "%loop = OpLabel\n" 7322 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n" 7323 "%val1 = OpPhi %f32 %val0 %entry %val %continue\n" 7324 "OpLoopMerge %exit %continue None\n" 7325 "OpBranch %if\n" 7326 7327 "%if = OpLabel\n" 7328 ";skip if %count==2\n" 7329 "%eq2 = OpIEqual %bool %count %c_i32_2\n" 7330 "OpSelectionMerge %continue DontFlatten\n" 7331 "OpBranchConditional %eq2 %continue %body\n" 7332 7333 "%body = OpLabel\n" 7334 "%fcount = OpConvertSToF %f32 %count\n" 7335 "%val2 = OpFAdd %f32 %val1 %fcount\n" 7336 "OpBranch %continue\n" 7337 7338 "%continue = OpLabel\n" 7339 "%val = OpPhi %f32 %val2 %body %val1 %if\n" 7340 "%count__ = OpISub %i32 %count %c_i32_1\n" 7341 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7342 "OpBranchConditional %again %loop %exit\n" 7343 7344 "%exit = OpLabel\n" 7345 "%same = OpFSub %f32 %val %c_f32_8\n" 7346 "%result = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n" 7347 "OpReturnValue %result\n" 7348 "OpFunctionEnd\n"; 7349 createTestsForAllStages("continue", defaultColors, defaultColors, fragments, testGroup.get()); 7350 7351 // A loop with break. 7352 fragments["testfun"] = 7353 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7354 "%param1 = OpFunctionParameter %v4f32\n" 7355 7356 "%entry = OpLabel\n" 7357 ";param1 components are between 0 and 1, so dot product is 4 or less\n" 7358 "%dot = OpDot %f32 %param1 %param1\n" 7359 "%div = OpFDiv %f32 %dot %c_f32_5\n" 7360 "%zero = OpConvertFToU %u32 %div\n" 7361 "%two = OpIAdd %i32 %zero %c_i32_2\n" 7362 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7363 "OpBranch %loop\n" 7364 7365 ";adds 4 and 3 to %val0 (exits early)\n" 7366 "%loop = OpLabel\n" 7367 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n" 7368 "%val1 = OpPhi %f32 %val0 %entry %val2 %continue\n" 7369 "OpLoopMerge %exit %continue None\n" 7370 "OpBranch %if\n" 7371 7372 "%if = OpLabel\n" 7373 ";end loop if %count==%two\n" 7374 "%above2 = OpSGreaterThan %bool %count %two\n" 7375 "OpSelectionMerge %continue DontFlatten\n" 7376 "OpBranchConditional %above2 %body %exit\n" 7377 7378 "%body = OpLabel\n" 7379 "%fcount = OpConvertSToF %f32 %count\n" 7380 "%val2 = OpFAdd %f32 %val1 %fcount\n" 7381 "OpBranch %continue\n" 7382 7383 "%continue = OpLabel\n" 7384 "%count__ = OpISub %i32 %count %c_i32_1\n" 7385 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7386 "OpBranchConditional %again %loop %exit\n" 7387 7388 "%exit = OpLabel\n" 7389 "%val_post = OpPhi %f32 %val2 %continue %val1 %if\n" 7390 "%same = OpFSub %f32 %val_post %c_f32_7\n" 7391 "%result = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n" 7392 "OpReturnValue %result\n" 7393 "OpFunctionEnd\n"; 7394 createTestsForAllStages("break", defaultColors, defaultColors, fragments, testGroup.get()); 7395 7396 // A loop with return. 7397 fragments["testfun"] = 7398 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7399 "%param1 = OpFunctionParameter %v4f32\n" 7400 7401 "%entry = OpLabel\n" 7402 ";param1 components are between 0 and 1, so dot product is 4 or less\n" 7403 "%dot = OpDot %f32 %param1 %param1\n" 7404 "%div = OpFDiv %f32 %dot %c_f32_5\n" 7405 "%zero = OpConvertFToU %u32 %div\n" 7406 "%two = OpIAdd %i32 %zero %c_i32_2\n" 7407 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7408 "OpBranch %loop\n" 7409 7410 ";returns early without modifying %param1\n" 7411 "%loop = OpLabel\n" 7412 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %continue\n" 7413 "%val1 = OpPhi %f32 %val0 %entry %val2 %continue\n" 7414 "OpLoopMerge %exit %continue None\n" 7415 "OpBranch %if\n" 7416 7417 "%if = OpLabel\n" 7418 ";return if %count==%two\n" 7419 "%above2 = OpSGreaterThan %bool %count %two\n" 7420 "OpSelectionMerge %continue DontFlatten\n" 7421 "OpBranchConditional %above2 %body %early_exit\n" 7422 7423 "%early_exit = OpLabel\n" 7424 "OpReturnValue %param1\n" 7425 7426 "%body = OpLabel\n" 7427 "%fcount = OpConvertSToF %f32 %count\n" 7428 "%val2 = OpFAdd %f32 %val1 %fcount\n" 7429 "OpBranch %continue\n" 7430 7431 "%continue = OpLabel\n" 7432 "%count__ = OpISub %i32 %count %c_i32_1\n" 7433 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7434 "OpBranchConditional %again %loop %exit\n" 7435 7436 "%exit = OpLabel\n" 7437 ";should never get here, so return an incorrect result\n" 7438 "%result = OpVectorInsertDynamic %v4f32 %param1 %val2 %c_i32_0\n" 7439 "OpReturnValue %result\n" 7440 "OpFunctionEnd\n"; 7441 createTestsForAllStages("return", defaultColors, defaultColors, fragments, testGroup.get()); 7442 7443 return testGroup.release(); 7444} 7445 7446// Adds a new test to group using custom fragments for the tessellation-control 7447// stage and passthrough fragments for all other stages. Uses default colors 7448// for input and expected output. 7449void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments) 7450{ 7451 RGBA defaultColors[4]; 7452 getDefaultColors(defaultColors); 7453 const ShaderElement pipelineStages[] = 7454 { 7455 ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT), 7456 ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), 7457 ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), 7458 ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT), 7459 }; 7460 7461 addFunctionCaseWithPrograms<InstanceContext>(group, name, "", addShaderCodeCustomTessControl, 7462 runAndVerifyDefaultPipeline, createInstanceContext( 7463 pipelineStages, defaultColors, defaultColors, fragments, StageToSpecConstantMap())); 7464} 7465 7466// A collection of tests putting OpControlBarrier in places GLSL forbids but SPIR-V allows. 7467tcu::TestCaseGroup* createBarrierTests(tcu::TestContext& testCtx) 7468{ 7469 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "barrier", "OpControlBarrier")); 7470 map<string, string> fragments; 7471 7472 // A barrier inside a function body. 7473 fragments["pre_main"] = 7474 "%Workgroup = OpConstant %i32 2\n" 7475 "%SequentiallyConsistent = OpConstant %i32 0x10\n"; 7476 fragments["testfun"] = 7477 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7478 "%param1 = OpFunctionParameter %v4f32\n" 7479 "%label_testfun = OpLabel\n" 7480 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7481 "OpReturnValue %param1\n" 7482 "OpFunctionEnd\n"; 7483 addTessCtrlTest(testGroup.get(), "in_function", fragments); 7484 7485 // Common setup code for the following tests. 7486 fragments["pre_main"] = 7487 "%Workgroup = OpConstant %i32 2\n" 7488 "%SequentiallyConsistent = OpConstant %i32 0x10\n" 7489 "%c_f32_5 = OpConstant %f32 5.\n"; 7490 const string setupPercentZero = // Begins %test_code function with code that sets %zero to 0u but cannot be optimized away. 7491 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7492 "%param1 = OpFunctionParameter %v4f32\n" 7493 "%entry = OpLabel\n" 7494 ";param1 components are between 0 and 1, so dot product is 4 or less\n" 7495 "%dot = OpDot %f32 %param1 %param1\n" 7496 "%div = OpFDiv %f32 %dot %c_f32_5\n" 7497 "%zero = OpConvertFToU %u32 %div\n"; 7498 7499 // Barriers inside OpSwitch branches. 7500 fragments["testfun"] = 7501 setupPercentZero + 7502 "OpSelectionMerge %switch_exit None\n" 7503 "OpSwitch %zero %switch_default 0 %case0 1 %case1 ;should always go to %case0\n" 7504 7505 "%case1 = OpLabel\n" 7506 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n" 7507 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7508 "%wrong_branch_alert1 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n" 7509 "OpBranch %switch_exit\n" 7510 7511 "%switch_default = OpLabel\n" 7512 "%wrong_branch_alert2 = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n" 7513 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n" 7514 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7515 "OpBranch %switch_exit\n" 7516 7517 "%case0 = OpLabel\n" 7518 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7519 "OpBranch %switch_exit\n" 7520 7521 "%switch_exit = OpLabel\n" 7522 "%ret = OpPhi %v4f32 %param1 %case0 %wrong_branch_alert1 %case1 %wrong_branch_alert2 %switch_default\n" 7523 "OpReturnValue %ret\n" 7524 "OpFunctionEnd\n"; 7525 addTessCtrlTest(testGroup.get(), "in_switch", fragments); 7526 7527 // Barriers inside if-then-else. 7528 fragments["testfun"] = 7529 setupPercentZero + 7530 "%eq0 = OpIEqual %bool %zero %c_u32_0\n" 7531 "OpSelectionMerge %exit DontFlatten\n" 7532 "OpBranchConditional %eq0 %then %else\n" 7533 7534 "%else = OpLabel\n" 7535 ";This barrier should never be executed, but its presence makes test failure more likely when there's a bug.\n" 7536 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7537 "%wrong_branch_alert = OpVectorInsertDynamic %v4f32 %param1 %c_f32_0_5 %c_i32_0\n" 7538 "OpBranch %exit\n" 7539 7540 "%then = OpLabel\n" 7541 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7542 "OpBranch %exit\n" 7543 7544 "%exit = OpLabel\n" 7545 "%ret = OpPhi %v4f32 %param1 %then %wrong_branch_alert %else\n" 7546 "OpReturnValue %ret\n" 7547 "OpFunctionEnd\n"; 7548 addTessCtrlTest(testGroup.get(), "in_if", fragments); 7549 7550 // A barrier after control-flow reconvergence, tempting the compiler to attempt something like this: 7551 // http://lists.llvm.org/pipermail/llvm-dev/2009-October/026317.html. 7552 fragments["testfun"] = 7553 setupPercentZero + 7554 "%thread_id = OpLoad %i32 %BP_gl_InvocationID\n" 7555 "%thread0 = OpIEqual %bool %thread_id %c_i32_0\n" 7556 "OpSelectionMerge %exit DontFlatten\n" 7557 "OpBranchConditional %thread0 %then %else\n" 7558 7559 "%else = OpLabel\n" 7560 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7561 "OpBranch %exit\n" 7562 7563 "%then = OpLabel\n" 7564 "%val1 = OpVectorExtractDynamic %f32 %param1 %zero\n" 7565 "OpBranch %exit\n" 7566 7567 "%exit = OpLabel\n" 7568 "%val = OpPhi %f32 %val0 %else %val1 %then\n" 7569 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7570 "%ret = OpVectorInsertDynamic %v4f32 %param1 %val %zero\n" 7571 "OpReturnValue %ret\n" 7572 "OpFunctionEnd\n"; 7573 addTessCtrlTest(testGroup.get(), "after_divergent_if", fragments); 7574 7575 // A barrier inside a loop. 7576 fragments["pre_main"] = 7577 "%Workgroup = OpConstant %i32 2\n" 7578 "%SequentiallyConsistent = OpConstant %i32 0x10\n" 7579 "%c_f32_10 = OpConstant %f32 10.\n"; 7580 fragments["testfun"] = 7581 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7582 "%param1 = OpFunctionParameter %v4f32\n" 7583 "%entry = OpLabel\n" 7584 "%val0 = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7585 "OpBranch %loop\n" 7586 7587 ";adds 4, 3, 2, and 1 to %val0\n" 7588 "%loop = OpLabel\n" 7589 "%count = OpPhi %i32 %c_i32_4 %entry %count__ %loop\n" 7590 "%val1 = OpPhi %f32 %val0 %entry %val %loop\n" 7591 "OpControlBarrier %Workgroup %Workgroup %SequentiallyConsistent\n" 7592 "%fcount = OpConvertSToF %f32 %count\n" 7593 "%val = OpFAdd %f32 %val1 %fcount\n" 7594 "%count__ = OpISub %i32 %count %c_i32_1\n" 7595 "%again = OpSGreaterThan %bool %count__ %c_i32_0\n" 7596 "OpLoopMerge %exit %loop None\n" 7597 "OpBranchConditional %again %loop %exit\n" 7598 7599 "%exit = OpLabel\n" 7600 "%same = OpFSub %f32 %val %c_f32_10\n" 7601 "%ret = OpVectorInsertDynamic %v4f32 %param1 %same %c_i32_0\n" 7602 "OpReturnValue %ret\n" 7603 "OpFunctionEnd\n"; 7604 addTessCtrlTest(testGroup.get(), "in_loop", fragments); 7605 7606 return testGroup.release(); 7607} 7608 7609// Test for the OpFRem instruction. 7610tcu::TestCaseGroup* createFRemTests(tcu::TestContext& testCtx) 7611{ 7612 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "frem", "OpFRem")); 7613 map<string, string> fragments; 7614 RGBA inputColors[4]; 7615 RGBA outputColors[4]; 7616 7617 fragments["pre_main"] = 7618 "%c_f32_3 = OpConstant %f32 3.0\n" 7619 "%c_f32_n3 = OpConstant %f32 -3.0\n" 7620 "%c_f32_4 = OpConstant %f32 4.0\n" 7621 "%c_f32_p75 = OpConstant %f32 0.75\n" 7622 "%c_v4f32_p75_p75_p75_p75 = OpConstantComposite %v4f32 %c_f32_p75 %c_f32_p75 %c_f32_p75 %c_f32_p75 \n" 7623 "%c_v4f32_4_4_4_4 = OpConstantComposite %v4f32 %c_f32_4 %c_f32_4 %c_f32_4 %c_f32_4\n" 7624 "%c_v4f32_3_n3_3_n3 = OpConstantComposite %v4f32 %c_f32_3 %c_f32_n3 %c_f32_3 %c_f32_n3\n"; 7625 7626 // The test does the following. 7627 // vec4 result = (param1 * 8.0) - 4.0; 7628 // return (frem(result.x,3) + 0.75, frem(result.y, -3) + 0.75, 0, 1) 7629 fragments["testfun"] = 7630 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7631 "%param1 = OpFunctionParameter %v4f32\n" 7632 "%label_testfun = OpLabel\n" 7633 "%v_times_8 = OpVectorTimesScalar %v4f32 %param1 %c_f32_8\n" 7634 "%minus_4 = OpFSub %v4f32 %v_times_8 %c_v4f32_4_4_4_4\n" 7635 "%frem = OpFRem %v4f32 %minus_4 %c_v4f32_3_n3_3_n3\n" 7636 "%added = OpFAdd %v4f32 %frem %c_v4f32_p75_p75_p75_p75\n" 7637 "%xyz_1 = OpVectorInsertDynamic %v4f32 %added %c_f32_1 %c_i32_3\n" 7638 "%xy_0_1 = OpVectorInsertDynamic %v4f32 %xyz_1 %c_f32_0 %c_i32_2\n" 7639 "OpReturnValue %xy_0_1\n" 7640 "OpFunctionEnd\n"; 7641 7642 7643 inputColors[0] = RGBA(16, 16, 0, 255); 7644 inputColors[1] = RGBA(232, 232, 0, 255); 7645 inputColors[2] = RGBA(232, 16, 0, 255); 7646 inputColors[3] = RGBA(16, 232, 0, 255); 7647 7648 outputColors[0] = RGBA(64, 64, 0, 255); 7649 outputColors[1] = RGBA(255, 255, 0, 255); 7650 outputColors[2] = RGBA(255, 64, 0, 255); 7651 outputColors[3] = RGBA(64, 255, 0, 255); 7652 7653 createTestsForAllStages("frem", inputColors, outputColors, fragments, testGroup.get()); 7654 return testGroup.release(); 7655} 7656 7657tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx) 7658{ 7659 de::MovePtr<tcu::TestCaseGroup> instructionTests (new tcu::TestCaseGroup(testCtx, "instruction", "Instructions with special opcodes/operands")); 7660 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Compute Instructions with special opcodes/operands")); 7661 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Graphics Instructions with special opcodes/operands")); 7662 7663 computeTests->addChild(createOpNopGroup(testCtx)); 7664 computeTests->addChild(createOpLineGroup(testCtx)); 7665 computeTests->addChild(createOpNoLineGroup(testCtx)); 7666 computeTests->addChild(createOpConstantNullGroup(testCtx)); 7667 computeTests->addChild(createOpConstantCompositeGroup(testCtx)); 7668 computeTests->addChild(createOpConstantUsageGroup(testCtx)); 7669 computeTests->addChild(createSpecConstantGroup(testCtx)); 7670 computeTests->addChild(createOpSourceGroup(testCtx)); 7671 computeTests->addChild(createOpSourceExtensionGroup(testCtx)); 7672 computeTests->addChild(createDecorationGroupGroup(testCtx)); 7673 computeTests->addChild(createOpPhiGroup(testCtx)); 7674 computeTests->addChild(createLoopControlGroup(testCtx)); 7675 computeTests->addChild(createFunctionControlGroup(testCtx)); 7676 computeTests->addChild(createSelectionControlGroup(testCtx)); 7677 computeTests->addChild(createBlockOrderGroup(testCtx)); 7678 computeTests->addChild(createMultipleShaderGroup(testCtx)); 7679 computeTests->addChild(createMemoryAccessGroup(testCtx)); 7680 computeTests->addChild(createOpCopyMemoryGroup(testCtx)); 7681 computeTests->addChild(createOpCopyObjectGroup(testCtx)); 7682 computeTests->addChild(createNoContractionGroup(testCtx)); 7683 computeTests->addChild(createOpUndefGroup(testCtx)); 7684 computeTests->addChild(createOpUnreachableGroup(testCtx)); 7685 computeTests ->addChild(createOpQuantizeToF16Group(testCtx)); 7686 computeTests ->addChild(createOpFRemGroup(testCtx)); 7687 7688 RGBA defaultColors[4]; 7689 getDefaultColors(defaultColors); 7690 7691 de::MovePtr<tcu::TestCaseGroup> opnopTests (new tcu::TestCaseGroup(testCtx, "opnop", "Test OpNop")); 7692 map<string, string> opNopFragments; 7693 opNopFragments["testfun"] = 7694 "%test_code = OpFunction %v4f32 None %v4f32_function\n" 7695 "%param1 = OpFunctionParameter %v4f32\n" 7696 "%label_testfun = OpLabel\n" 7697 "OpNop\n" 7698 "OpNop\n" 7699 "OpNop\n" 7700 "OpNop\n" 7701 "OpNop\n" 7702 "OpNop\n" 7703 "OpNop\n" 7704 "OpNop\n" 7705 "%a = OpVectorExtractDynamic %f32 %param1 %c_i32_0\n" 7706 "%b = OpFAdd %f32 %a %a\n" 7707 "OpNop\n" 7708 "%c = OpFSub %f32 %b %a\n" 7709 "%ret = OpVectorInsertDynamic %v4f32 %param1 %c %c_i32_0\n" 7710 "OpNop\n" 7711 "OpNop\n" 7712 "OpReturnValue %ret\n" 7713 "OpFunctionEnd\n" 7714 ; 7715 createTestsForAllStages("opnop", defaultColors, defaultColors, opNopFragments, opnopTests.get()); 7716 7717 7718 graphicsTests->addChild(opnopTests.release()); 7719 graphicsTests->addChild(createOpSourceTests(testCtx)); 7720 graphicsTests->addChild(createOpSourceContinuedTests(testCtx)); 7721 graphicsTests->addChild(createOpLineTests(testCtx)); 7722 graphicsTests->addChild(createOpNoLineTests(testCtx)); 7723 graphicsTests->addChild(createOpConstantNullTests(testCtx)); 7724 graphicsTests->addChild(createOpConstantCompositeTests(testCtx)); 7725 graphicsTests->addChild(createMemoryAccessTests(testCtx)); 7726 graphicsTests->addChild(createOpUndefTests(testCtx)); 7727 graphicsTests->addChild(createSelectionBlockOrderTests(testCtx)); 7728 graphicsTests->addChild(createModuleTests(testCtx)); 7729 graphicsTests->addChild(createSwitchBlockOrderTests(testCtx)); 7730 graphicsTests->addChild(createOpPhiTests(testCtx)); 7731 graphicsTests->addChild(createNoContractionTests(testCtx)); 7732 graphicsTests->addChild(createOpQuantizeTests(testCtx)); 7733 graphicsTests->addChild(createLoopTests(testCtx)); 7734 graphicsTests->addChild(createSpecConstantTests(testCtx)); 7735 graphicsTests->addChild(createSpecConstantOpQuantizeToF16Group(testCtx)); 7736 graphicsTests->addChild(createBarrierTests(testCtx)); 7737 graphicsTests->addChild(createDecorationGroupTests(testCtx)); 7738 graphicsTests->addChild(createFRemTests(testCtx)); 7739 7740 instructionTests->addChild(computeTests.release()); 7741 instructionTests->addChild(graphicsTests.release()); 7742 7743 return instructionTests.release(); 7744} 7745 7746} // SpirVAssembly 7747} // vkt 7748