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