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