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