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