1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief ShaderLibrary Vulkan implementation 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktShaderLibrary.hpp" 25 #include "vktTestCase.hpp" 26 27 #include "vkPrograms.hpp" 28 #include "vkRef.hpp" 29 #include "vkRefUtil.hpp" 30 #include "vkMemUtil.hpp" 31 #include "vkQueryUtil.hpp" 32 #include "vkBuilderUtil.hpp" 33 #include "vkTypeUtil.hpp" 34 35 #include "gluShaderLibrary.hpp" 36 #include "gluShaderUtil.hpp" 37 38 #include "tcuStringTemplate.hpp" 39 #include "tcuTexture.hpp" 40 #include "tcuTestLog.hpp" 41 #include "tcuVector.hpp" 42 #include "tcuVectorUtil.hpp" 43 44 #include "deStringUtil.hpp" 45 #include "deArrayUtil.hpp" 46 #include "deMemory.h" 47 48 #include <sstream> 49 #include <map> 50 51 namespace vkt 52 { 53 54 using std::string; 55 using std::vector; 56 using std::map; 57 using std::pair; 58 using std::ostringstream; 59 60 using de::MovePtr; 61 using de::UniquePtr; 62 63 using glu::ShaderType; 64 using glu::ProgramSources; 65 using glu::DataType; 66 67 using glu::sl::ShaderCaseSpecification; 68 using glu::sl::ProgramSpecializationParams; 69 using glu::sl::RequiredExtension; 70 using glu::sl::Value; 71 using glu::sl::ValueBlock; 72 73 using tcu::TestStatus; 74 using tcu::StringTemplate; 75 using tcu::Vec2; 76 using tcu::ConstPixelBufferAccess; 77 using tcu::TextureFormat; 78 using tcu::TestLog; 79 80 using vk::SourceCollections; 81 using vk::Move; 82 using vk::Unique; 83 84 namespace 85 { 86 87 enum 88 { 89 REFERENCE_UNIFORM_BINDING = 0, 90 USER_UNIFORM_BINDING = 1 91 }; 92 93 string getShaderName (ShaderType shaderType, size_t progNdx) 94 { 95 ostringstream str; 96 str << glu::getShaderTypeName(shaderType); 97 if (progNdx > 0) 98 str << "_" << progNdx; 99 return str.str(); 100 } 101 102 void genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms) 103 { 104 out << "layout("; 105 106 if (setNdx != 0) 107 out << "set = " << setNdx << ", "; 108 109 out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n" 110 << "{\n"; 111 112 for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val) 113 out << "\t" << glu::declare(val->type, val->name, 1) << ";\n"; 114 115 out << "}"; 116 117 if (!instanceName.empty()) 118 out << " " << instanceName; 119 120 out << ";\n"; 121 } 122 123 void declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock) 124 { 125 if (!valueBlock.outputs.empty()) 126 genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs); 127 } 128 129 void declareUniforms (ostringstream& out, const ValueBlock& valueBlock) 130 { 131 if (!valueBlock.uniforms.empty()) 132 genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms); 133 } 134 135 DataType getTransportType (DataType valueType) 136 { 137 if (isDataTypeBoolOrBVec(valueType)) 138 return glu::getDataTypeUintVec(getDataTypeScalarSize(valueType)); 139 else 140 return valueType; 141 } 142 143 int getNumTransportLocations (DataType valueType) 144 { 145 return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1; 146 } 147 148 // This functions builds a matching vertex shader for a 'both' case, when 149 // the fragment shader is being tested. 150 // We need to build attributes and varyings for each 'input'. 151 string genVertexShader (const ShaderCaseSpecification& spec) 152 { 153 ostringstream res; 154 int curInputLoc = 0; 155 int curOutputLoc = 0; 156 157 res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n"; 158 159 // Declarations (position + attribute/varying for each input). 160 res << "precision highp float;\n"; 161 res << "precision highp int;\n"; 162 res << "\n"; 163 res << "layout(location = 0) in highp vec4 dEQP_Position;\n"; 164 curInputLoc += 1; 165 166 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 167 { 168 const Value& val = spec.values.inputs[ndx]; 169 const DataType valueType = val.type.getBasicType(); 170 const DataType transportType = getTransportType(valueType); 171 const char* const transportTypeStr = getDataTypeName(transportType); 172 const int numLocs = getNumTransportLocations(valueType); 173 174 res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n"; 175 res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n"; 176 177 curInputLoc += numLocs; 178 curOutputLoc += numLocs; 179 } 180 res << "\n"; 181 182 // Main function. 183 // - gl_Position = dEQP_Position; 184 // - for each input: write attribute directly to varying 185 res << "void main()\n"; 186 res << "{\n"; 187 res << " gl_Position = dEQP_Position;\n"; 188 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 189 { 190 const Value& val = spec.values.inputs[ndx]; 191 const string& name = val.name; 192 193 res << " " << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "") 194 << name << " = a_" << name << ";\n"; 195 } 196 197 res << "}\n"; 198 return res.str(); 199 } 200 201 void genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName) 202 { 203 bool isFirstOutput = true; 204 205 for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++) 206 { 207 const Value& val = valueBlock.outputs[ndx]; 208 209 // Check if we're only interested in one variable (then skip if not the right one). 210 if (checkVarName && val.name != checkVarName) 211 continue; 212 213 // Prefix. 214 if (isFirstOutput) 215 { 216 output << "bool RES = "; 217 isFirstOutput = false; 218 } 219 else 220 output << "RES = RES && "; 221 222 // Generate actual comparison. 223 if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT) 224 output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n"; 225 else 226 output << "isOk(" << val.name << ", ref." << val.name << ");\n"; 227 } 228 229 if (isFirstOutput) 230 output << dstVec4Var << " = vec4(1.0);\n"; 231 else 232 output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n"; 233 } 234 235 string genFragmentShader (const ShaderCaseSpecification& spec) 236 { 237 ostringstream shader; 238 ostringstream setup; 239 int curInLoc = 0; 240 241 shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n"; 242 243 shader << "precision highp float;\n"; 244 shader << "precision highp int;\n"; 245 shader << "\n"; 246 247 shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 248 shader << "\n"; 249 250 genCompareFunctions(shader, spec.values, false); 251 shader << "\n"; 252 253 // Declarations (varying, reference for each output). 254 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 255 { 256 const Value& val = spec.values.outputs[ndx]; 257 const DataType valueType = val.type.getBasicType(); 258 const char* const valueTypeStr = getDataTypeName(valueType); 259 const DataType transportType = getTransportType(valueType); 260 const char* const transportTypeStr = getDataTypeName(transportType); 261 const int numLocs = getNumTransportLocations(valueType); 262 263 shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n"; 264 265 if (valueType != transportType) 266 setup << " " << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n"; 267 268 curInLoc += numLocs; 269 } 270 271 declareReferenceBlock(shader, spec.values); 272 273 shader << "\n"; 274 shader << "void main()\n"; 275 shader << "{\n"; 276 277 shader << setup.str(); 278 279 shader << " "; 280 genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL); 281 282 shader << "}\n"; 283 return shader.str(); 284 } 285 286 // Specialize a shader for the vertex shader test case. 287 string specializeVertexShader (const ShaderCaseSpecification& spec, const string& src) 288 { 289 ostringstream decl; 290 ostringstream setup; 291 ostringstream output; 292 int curInputLoc = 0; 293 int curOutputLoc = 0; 294 295 // generated from "both" case 296 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY); 297 298 // Output (write out position). 299 output << "gl_Position = dEQP_Position;\n"; 300 301 // Declarations (position + attribute for each input, varying for each output). 302 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n"; 303 curInputLoc += 1; 304 305 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 306 { 307 const Value& val = spec.values.inputs[ndx]; 308 const DataType valueType = val.type.getBasicType(); 309 const char* const valueTypeStr = getDataTypeName(valueType); 310 const DataType transportType = getTransportType(valueType); 311 const char* const transportTypeStr = getDataTypeName(transportType); 312 const int numLocs = getNumTransportLocations(valueType); 313 314 decl << "layout(location = " << curInputLoc << ") in "; 315 316 curInputLoc += numLocs; 317 318 if (valueType == transportType) 319 decl << transportTypeStr << " " << val.name << ";\n"; 320 else 321 { 322 decl << transportTypeStr << " a_" << val.name << ";\n"; 323 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n"; 324 } 325 } 326 327 declareUniforms(decl, spec.values); 328 329 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 330 { 331 const Value& val = spec.values.outputs[ndx]; 332 const DataType valueType = val.type.getBasicType(); 333 const char* const valueTypeStr = getDataTypeName(valueType); 334 const DataType transportType = getTransportType(valueType); 335 const char* const transportTypeStr = getDataTypeName(transportType); 336 const int numLocs = getNumTransportLocations(valueType); 337 338 decl << "layout(location = " << curOutputLoc << ") flat out "; 339 340 curOutputLoc += numLocs; 341 342 if (valueType == transportType) 343 decl << transportTypeStr << " " << val.name << ";\n"; 344 else 345 { 346 decl << transportTypeStr << " v_" << val.name << ";\n"; 347 decl << valueTypeStr << " " << val.name << ";\n"; 348 349 output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n"; 350 } 351 } 352 353 // Shader specialization. 354 map<string, string> params; 355 params.insert(pair<string, string>("DECLARATIONS", decl.str())); 356 params.insert(pair<string, string>("SETUP", setup.str())); 357 params.insert(pair<string, string>("OUTPUT", output.str())); 358 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position")); 359 360 StringTemplate tmpl (src); 361 const string baseSrc = tmpl.specialize(params); 362 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX); 363 364 return withExt; 365 } 366 367 // Specialize a shader for the fragment shader test case. 368 string specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src) 369 { 370 ostringstream decl; 371 ostringstream setup; 372 ostringstream output; 373 int curInputLoc = 0; 374 375 // generated from "both" case 376 DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY); 377 378 genCompareFunctions(decl, spec.values, false); 379 genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL); 380 381 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 382 383 for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++) 384 { 385 const Value& val = spec.values.inputs[ndx]; 386 const DataType valueType = val.type.getBasicType(); 387 const char* const valueTypeStr = getDataTypeName(valueType); 388 const DataType transportType = getTransportType(valueType); 389 const char* const transportTypeStr = getDataTypeName(transportType); 390 const int numLocs = getNumTransportLocations(valueType); 391 392 decl << "layout(location = " << curInputLoc << ") flat in "; 393 394 curInputLoc += numLocs; 395 396 if (valueType == transportType) 397 decl << transportTypeStr << " " << val.name << ";\n"; 398 else 399 { 400 decl << transportTypeStr << " v_" << val.name << ";\n"; 401 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n"; 402 } 403 } 404 405 declareUniforms(decl, spec.values); 406 declareReferenceBlock(decl, spec.values); 407 408 for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++) 409 { 410 const Value& val = spec.values.outputs[ndx]; 411 const DataType basicType = val.type.getBasicType(); 412 const char* const refTypeStr = getDataTypeName(basicType); 413 414 decl << refTypeStr << " " << val.name << ";\n"; 415 } 416 417 // Shader specialization. 418 map<string, string> params; 419 params.insert(pair<string, string>("DECLARATIONS", decl.str())); 420 params.insert(pair<string, string>("SETUP", setup.str())); 421 params.insert(pair<string, string>("OUTPUT", output.str())); 422 params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor")); 423 424 StringTemplate tmpl (src); 425 const string baseSrc = tmpl.specialize(params); 426 const string withExt = injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT); 427 428 return withExt; 429 } 430 431 map<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams) 432 { 433 ostringstream decl; 434 ostringstream setup; 435 map<string, string> params; 436 int curInputLoc = 0; 437 438 decl << "layout(location = 0) in highp vec4 dEQP_Position;\n"; 439 curInputLoc += 1; 440 441 for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++) 442 { 443 const Value& val = specParams.caseSpec.values.inputs[ndx]; 444 const DataType valueType = val.type.getBasicType(); 445 const char* const valueTypeStr = getDataTypeName(valueType); 446 const DataType transportType = getTransportType(valueType); 447 const char* const transportTypeStr = getDataTypeName(transportType); 448 const int numLocs = getNumTransportLocations(valueType); 449 450 decl << "layout(location = " << curInputLoc << ") in "; 451 452 curInputLoc += numLocs; 453 454 if (valueType == transportType) 455 decl << transportTypeStr << " " << val.name << ";\n"; 456 else 457 { 458 decl << transportTypeStr << " a_" << val.name << ";\n"; 459 setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n"; 460 } 461 } 462 463 declareUniforms(decl, specParams.caseSpec.values); 464 465 params.insert(pair<string, string>("VERTEX_DECLARATIONS", decl.str())); 466 params.insert(pair<string, string>("VERTEX_SETUP", setup.str())); 467 params.insert(pair<string, string>("VERTEX_OUTPUT", string("gl_Position = dEQP_Position;\n"))); 468 469 return params; 470 } 471 472 map<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams) 473 { 474 ostringstream decl; 475 ostringstream output; 476 map<string, string> params; 477 478 genCompareFunctions(decl, specParams.caseSpec.values, false); 479 genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL); 480 481 decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"; 482 483 for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++) 484 { 485 const Value& val = specParams.caseSpec.values.outputs[ndx]; 486 const char* const refTypeStr = getDataTypeName(val.type.getBasicType()); 487 488 decl << refTypeStr << " " << val.name << ";\n"; 489 } 490 491 declareReferenceBlock(decl, specParams.caseSpec.values); 492 declareUniforms(decl, specParams.caseSpec.values); 493 494 params.insert(pair<string, string>("FRAGMENT_DECLARATIONS", decl.str())); 495 params.insert(pair<string, string>("FRAGMENT_OUTPUT", output.str())); 496 params.insert(pair<string, string>("FRAG_COLOR", "dEQP_FragColor")); 497 498 return params; 499 } 500 501 map<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams) 502 { 503 ostringstream decl; 504 map<string, string> params; 505 506 decl << "layout (triangles) in;\n"; 507 decl << "layout (triangle_strip, max_vertices=3) out;\n"; 508 decl << "\n"; 509 510 declareUniforms(decl, specParams.caseSpec.values); 511 512 params.insert(pair<string, string>("GEOMETRY_DECLARATIONS", decl.str())); 513 514 return params; 515 } 516 517 map<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams) 518 { 519 ostringstream decl; 520 ostringstream output; 521 map<string, string> params; 522 523 decl << "layout (vertices=3) out;\n"; 524 decl << "\n"; 525 526 declareUniforms(decl, specParams.caseSpec.values); 527 528 output << "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 529 "gl_TessLevelInner[0] = 2.0;\n" 530 "gl_TessLevelInner[1] = 2.0;\n" 531 "gl_TessLevelOuter[0] = 2.0;\n" 532 "gl_TessLevelOuter[1] = 2.0;\n" 533 "gl_TessLevelOuter[2] = 2.0;\n" 534 "gl_TessLevelOuter[3] = 2.0;"; 535 536 params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS", decl.str())); 537 params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT", output.str())); 538 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices))); 539 540 return params; 541 } 542 543 map<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams) 544 { 545 ostringstream decl; 546 ostringstream output; 547 map<string, string> params; 548 549 decl << "layout (triangles) in;\n"; 550 decl << "\n"; 551 552 declareUniforms(decl, specParams.caseSpec.values); 553 554 output << "gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"; 555 556 params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS", decl.str())); 557 params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT", output.str())); 558 params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES", de::toString(specParams.maxPatchVertices))); 559 560 return params; 561 } 562 563 void specializeShaderSources (ProgramSources& dst, 564 const ProgramSources& src, 565 const ProgramSpecializationParams& specParams, 566 glu::ShaderType shaderType, 567 map<string, string> (*specializationGenerator) (const ProgramSpecializationParams& specParams)) 568 { 569 if (!src.sources[shaderType].empty()) 570 { 571 const map<string, string> tmplParams = specializationGenerator(specParams); 572 573 for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx) 574 { 575 const StringTemplate tmpl (src.sources[shaderType][ndx]); 576 const string baseGLSLCode = tmpl.specialize(tmplParams); 577 const string sourceWithExts = injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType); 578 579 dst << glu::ShaderSource(shaderType, sourceWithExts); 580 } 581 } 582 } 583 584 void specializeProgramSources (glu::ProgramSources& dst, 585 const glu::ProgramSources& src, 586 const ProgramSpecializationParams& specParams) 587 { 588 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX, generateVertexSpecialization); 589 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT, generateFragmentSpecialization); 590 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY, generateGeometrySpecialization); 591 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL, generateTessControlSpecialization); 592 specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION, generateTessEvalSpecialization); 593 594 dst << glu::ProgramSeparable(src.separable); 595 } 596 597 struct ValueBufferLayout 598 { 599 struct Entry 600 { 601 int offset; 602 int vecStride; //! Applies to matrices only 603 604 Entry (void) : offset(0), vecStride(0) {} 605 Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {} 606 }; 607 608 vector<Entry> entries; 609 int size; 610 611 ValueBufferLayout (void) : size(0) {} 612 }; 613 614 ValueBufferLayout computeStd140Layout (const vector<Value>& values) 615 { 616 ValueBufferLayout layout; 617 618 layout.entries.resize(values.size()); 619 620 for (size_t ndx = 0; ndx < values.size(); ++ndx) 621 { 622 const DataType basicType = values[ndx].type.getBasicType(); 623 const bool isMatrix = isDataTypeMatrix(basicType); 624 const int numVecs = isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1; 625 const DataType vecType = isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType; 626 const int vecSize = getDataTypeScalarSize(vecType); 627 const int alignment = ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32)); 628 629 layout.size = deAlign32(layout.size, alignment); 630 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment); 631 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32)); 632 } 633 634 return layout; 635 } 636 637 ValueBufferLayout computeStd430Layout (const vector<Value>& values) 638 { 639 ValueBufferLayout layout; 640 641 layout.entries.resize(values.size()); 642 643 for (size_t ndx = 0; ndx < values.size(); ++ndx) 644 { 645 const DataType basicType = values[ndx].type.getBasicType(); 646 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1; 647 const DataType vecType = isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType; 648 const int vecSize = getDataTypeScalarSize(vecType); 649 const int alignment = (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32)); 650 651 layout.size = deAlign32(layout.size, alignment); 652 layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment); 653 layout.size += alignment*(numVecs-1) + vecSize*int(sizeof(deUint32)); 654 } 655 656 return layout; 657 } 658 659 void copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx) 660 { 661 const DataType basicType = value.type.getBasicType(); 662 const int scalarSize = getDataTypeScalarSize(basicType); 663 const int numVecs = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1; 664 const int numComps = isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize; 665 666 DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size()); 667 668 if (isDataTypeBoolOrBVec(basicType)) 669 { 670 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 671 { 672 for (int compNdx = 0; compNdx < numComps; compNdx++) 673 { 674 const deUint32 data = value.elements[arrayNdx*scalarSize + vecNdx*numComps + compNdx].bool32 ? ~0u : 0u; 675 676 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride + compNdx * sizeof(deUint32), 677 &data, 678 sizeof(deUint32)); 679 } 680 } 681 } 682 else 683 { 684 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 685 deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride, 686 &value.elements[arrayNdx*scalarSize + vecNdx*numComps], 687 numComps*sizeof(deUint32)); 688 } 689 } 690 691 void copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx) 692 { 693 DE_ASSERT(layout.entries.size() == values.size()); 694 695 for (size_t ndx = 0; ndx < values.size(); ndx++) 696 copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx); 697 } 698 699 deUint32 getShaderStages (const ShaderCaseSpecification& spec) 700 { 701 if (spec.caseType == glu::sl::CASETYPE_COMPLETE) 702 { 703 deUint32 stages = 0u; 704 705 for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++) 706 { 707 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 708 { 709 if (!spec.programs[progNdx].sources.sources[shaderType].empty()) 710 stages |= (1u << shaderType); 711 } 712 } 713 714 return stages; 715 } 716 else 717 return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT); 718 } 719 720 class PipelineProgram 721 { 722 public: 723 PipelineProgram (Context& context, const ShaderCaseSpecification& spec); 724 725 deUint32 getStages (void) const { return m_stages; } 726 727 bool hasShader (glu::ShaderType type) const { return (m_stages & (1u << type)) != 0; } 728 vk::VkShaderModule getShader (glu::ShaderType type) const { return *m_shaderModules[type]; } 729 730 private: 731 const deUint32 m_stages; 732 Move<vk::VkShaderModule> m_shaderModules[glu::SHADERTYPE_LAST]; 733 }; 734 735 PipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec) 736 : m_stages(getShaderStages(spec)) 737 { 738 // \note Currently only a single source program is supported as framework lacks SPIR-V linking capability 739 TCU_CHECK_INTERNAL(spec.programs.size() == 1); 740 741 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 742 { 743 if ((m_stages & (1u << shaderType)) != 0) 744 { 745 m_shaderModules[shaderType] = vk::createShaderModule(context.getDeviceInterface(), context.getDevice(), 746 context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u); 747 } 748 } 749 } 750 751 vector<vk::VkPipelineShaderStageCreateInfo> getPipelineShaderStageCreateInfo (const PipelineProgram& program) 752 { 753 vector<vk::VkPipelineShaderStageCreateInfo> infos; 754 755 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 756 { 757 if (program.hasShader((glu::ShaderType)shaderType)) 758 { 759 const vk::VkPipelineShaderStageCreateInfo info = 760 { 761 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // sType 762 DE_NULL, // pNext 763 (vk::VkPipelineShaderStageCreateFlags)0, 764 vk::getVkShaderStage((glu::ShaderType)shaderType), // stage 765 program.getShader((glu::ShaderType)shaderType), // module 766 "main", 767 DE_NULL, // pSpecializationInfo 768 }; 769 770 infos.push_back(info); 771 } 772 } 773 774 return infos; 775 } 776 777 Move<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags) 778 { 779 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 780 const vk::VkBufferCreateInfo params = 781 { 782 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType 783 DE_NULL, // pNext 784 0u, // flags 785 size, // size 786 usageFlags, // usage 787 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 788 1u, // queueFamilyCount 789 &queueFamilyIndex, // pQueueFamilyIndices 790 }; 791 792 return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms); 793 } 794 795 Move<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags) 796 { 797 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 798 const vk::VkImageCreateInfo params = 799 { 800 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType 801 DE_NULL, // pNext 802 0u, // flags 803 vk::VK_IMAGE_TYPE_2D, // imageType 804 format, // format 805 { width, height, 1u }, // extent 806 1u, // mipLevels 807 1u, // arraySize 808 vk::VK_SAMPLE_COUNT_1_BIT, // samples 809 tiling, // tiling 810 usageFlags, // usage 811 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 812 1u, // queueFamilyCount 813 &queueFamilyIndex, // pQueueFamilyIndices 814 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout 815 }; 816 817 return vk::createImage(context.getDeviceInterface(), context.getDevice(), ¶ms); 818 } 819 820 Move<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format) 821 { 822 const vk::VkImageViewCreateInfo params = 823 { 824 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType 825 DE_NULL, // pNext 826 0u, // flags 827 image, // image 828 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType 829 format, // format 830 vk::makeComponentMappingRGBA(), // channels 831 { 832 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 833 0u, // baseMipLevel 834 1u, // mipLevels 835 0u, // baseArrayLayer 836 1u, // arraySize 837 }, // subresourceRange 838 }; 839 840 return vk::createImageView(context.getDeviceInterface(), context.getDevice(), ¶ms); 841 } 842 843 Move<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat) 844 { 845 const vk::VkAttachmentDescription colorAttDesc = 846 { 847 0u, // flags 848 colorAttFormat, // format 849 vk::VK_SAMPLE_COUNT_1_BIT, // samples 850 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp 851 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp 852 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp 853 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp 854 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout 855 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout 856 }; 857 const vk::VkAttachmentReference colorAttRef = 858 { 859 0u, // attachment 860 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout 861 }; 862 const vk::VkAttachmentReference dsAttRef = 863 { 864 vk::VK_NO_ATTACHMENT, // attachment 865 vk::VK_IMAGE_LAYOUT_GENERAL, // layout 866 }; 867 const vk::VkSubpassDescription subpassDesc = 868 { 869 (vk::VkSubpassDescriptionFlags)0, 870 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint 871 0u, // inputCount 872 DE_NULL, // pInputAttachments 873 1u, // colorCount 874 &colorAttRef, // pColorAttachments 875 DE_NULL, // pResolveAttachments 876 &dsAttRef, // depthStencilAttachment 877 0u, // preserveCount 878 DE_NULL, // pPreserveAttachments 879 880 }; 881 const vk::VkRenderPassCreateInfo renderPassParams = 882 { 883 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType 884 DE_NULL, // pNext 885 (vk::VkRenderPassCreateFlags)0, 886 1u, // attachmentCount 887 &colorAttDesc, // pAttachments 888 1u, // subpassCount 889 &subpassDesc, // pSubpasses 890 0u, // dependencyCount 891 DE_NULL, // pDependencies 892 }; 893 894 return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams); 895 } 896 897 vk::VkShaderStageFlags getVkStageFlags (deUint32 stages) 898 { 899 vk::VkShaderStageFlags vkStages = 0u; 900 901 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 902 { 903 if ((stages & (1u << shaderType)) != 0) 904 vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType); 905 } 906 907 return vkStages; 908 } 909 910 Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages) 911 { 912 DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING == 0); 913 DE_STATIC_ASSERT(USER_UNIFORM_BINDING == 1); 914 915 return vk::DescriptorSetLayoutBuilder() 916 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT) 917 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages)) 918 .build(context.getDeviceInterface(), context.getDevice()); 919 } 920 921 Move<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout) 922 { 923 const vk::VkPipelineLayoutCreateInfo params = 924 { 925 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType 926 DE_NULL, // pNext 927 (vk::VkPipelineLayoutCreateFlags)0, 928 1u, // descriptorSetCount 929 &descriptorSetLayout, // pSetLayouts 930 0u, // pushConstantRangeCount 931 DE_NULL, // pPushConstantRanges 932 }; 933 934 return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), ¶ms); 935 } 936 937 vk::VkFormat getVecFormat (DataType scalarType, int scalarSize) 938 { 939 switch (scalarType) 940 { 941 case glu::TYPE_FLOAT: 942 { 943 const vk::VkFormat vecFmts[] = 944 { 945 vk::VK_FORMAT_R32_SFLOAT, 946 vk::VK_FORMAT_R32G32_SFLOAT, 947 vk::VK_FORMAT_R32G32B32_SFLOAT, 948 vk::VK_FORMAT_R32G32B32A32_SFLOAT, 949 }; 950 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1); 951 } 952 953 case glu::TYPE_INT: 954 { 955 const vk::VkFormat vecFmts[] = 956 { 957 vk::VK_FORMAT_R32_SINT, 958 vk::VK_FORMAT_R32G32_SINT, 959 vk::VK_FORMAT_R32G32B32_SINT, 960 vk::VK_FORMAT_R32G32B32A32_SINT, 961 }; 962 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1); 963 } 964 965 case glu::TYPE_UINT: 966 { 967 const vk::VkFormat vecFmts[] = 968 { 969 vk::VK_FORMAT_R32_UINT, 970 vk::VK_FORMAT_R32G32_UINT, 971 vk::VK_FORMAT_R32G32B32_UINT, 972 vk::VK_FORMAT_R32G32B32A32_UINT, 973 }; 974 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1); 975 } 976 977 case glu::TYPE_BOOL: 978 { 979 const vk::VkFormat vecFmts[] = 980 { 981 vk::VK_FORMAT_R32_UINT, 982 vk::VK_FORMAT_R32G32_UINT, 983 vk::VK_FORMAT_R32G32B32_UINT, 984 vk::VK_FORMAT_R32G32B32A32_UINT, 985 }; 986 return de::getSizedArrayElement<4>(vecFmts, scalarSize-1); 987 } 988 989 default: 990 DE_FATAL("Unknown scalar type"); 991 return vk::VK_FORMAT_R8G8B8A8_UINT; 992 } 993 } 994 995 vector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout) 996 { 997 vector<vk::VkVertexInputAttributeDescription> attribs; 998 999 // Position 1000 { 1001 const vk::VkVertexInputAttributeDescription posDesc = 1002 { 1003 0u, // location 1004 0u, // binding 1005 vk::VK_FORMAT_R32G32_SFLOAT, // format 1006 0u, // offset 1007 }; 1008 1009 attribs.push_back(posDesc); 1010 } 1011 1012 // Input values 1013 for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++) 1014 { 1015 const Value& input = inputValues[inputNdx]; 1016 const ValueBufferLayout::Entry& layoutEntry = layout.entries[inputNdx]; 1017 const DataType basicType = input.type.getBasicType(); 1018 const int numVecs = isDataTypeMatrix(basicType) 1019 ? getDataTypeMatrixNumColumns(basicType) 1020 : 1; 1021 const int vecSize = isDataTypeMatrix(basicType) 1022 ? getDataTypeMatrixNumRows(basicType) 1023 : getDataTypeScalarSize(basicType); 1024 const DataType scalarType = getDataTypeScalarType(basicType); 1025 const vk::VkFormat vecFmt = getVecFormat(scalarType, vecSize); 1026 1027 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 1028 { 1029 const deUint32 curLoc = (deUint32)attribs.size(); 1030 const deUint32 offset = (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx); 1031 const vk::VkVertexInputAttributeDescription desc = 1032 { 1033 curLoc, // location 1034 1u, // binding 1035 vecFmt, // format 1036 offset, // offset 1037 }; 1038 1039 attribs.push_back(desc); 1040 } 1041 } 1042 1043 return attribs; 1044 } 1045 1046 Move<vk::VkPipeline> createPipeline (Context& context, 1047 const vector<Value>& inputValues, 1048 const ValueBufferLayout& inputLayout, 1049 const PipelineProgram& program, 1050 vk::VkRenderPass renderPass, 1051 vk::VkPipelineLayout pipelineLayout, 1052 tcu::UVec2 renderSize) 1053 { 1054 const vector<vk::VkPipelineShaderStageCreateInfo> shaderStageParams (getPipelineShaderStageCreateInfo(program)); 1055 const vector<vk::VkVertexInputAttributeDescription> vertexAttribParams (getVertexAttributeDescriptions(inputValues, inputLayout)); 1056 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilParams = 1057 { 1058 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // sType 1059 DE_NULL, // pNext 1060 (vk::VkPipelineDepthStencilStateCreateFlags)0, 1061 vk::VK_FALSE, // depthTestEnable 1062 vk::VK_FALSE, // depthWriteEnable 1063 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp 1064 vk::VK_FALSE, // depthBoundsTestEnable 1065 vk::VK_FALSE, // stencilTestEnable 1066 { 1067 vk::VK_STENCIL_OP_KEEP, // stencilFailOp; 1068 vk::VK_STENCIL_OP_KEEP, // stencilPassOp; 1069 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp; 1070 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp; 1071 0u, // stencilCompareMask 1072 0u, // stencilWriteMask 1073 0u, // stencilReference 1074 }, // front; 1075 { 1076 vk::VK_STENCIL_OP_KEEP, // stencilFailOp; 1077 vk::VK_STENCIL_OP_KEEP, // stencilPassOp; 1078 vk::VK_STENCIL_OP_KEEP, // stencilDepthFailOp; 1079 vk::VK_COMPARE_OP_ALWAYS, // stencilCompareOp; 1080 0u, // stencilCompareMask 1081 0u, // stencilWriteMask 1082 0u, // stencilReference 1083 }, // back; 1084 -1.0f, // minDepthBounds 1085 +1.0f, // maxDepthBounds 1086 }; 1087 const vk::VkViewport viewport0 = 1088 { 1089 0.0f, // originX 1090 0.0f, // originY 1091 (float)renderSize.x(), // width 1092 (float)renderSize.y(), // height 1093 0.0f, // minDepth 1094 1.0f, // maxDepth 1095 }; 1096 const vk::VkRect2D scissor0 = 1097 { 1098 { 0u, 0u }, // offset 1099 { renderSize.x(), renderSize.y() } // extent 1100 }; 1101 const vk::VkPipelineViewportStateCreateInfo viewportParams = 1102 { 1103 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // sType 1104 DE_NULL, // pNext 1105 (vk::VkPipelineViewportStateCreateFlags)0, 1106 1u, // viewportCount 1107 &viewport0, // pViewports 1108 1u, // scissorCount 1109 &scissor0, // pScissors 1110 }; 1111 const vk::VkPipelineMultisampleStateCreateInfo multisampleParams = 1112 { 1113 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // sType 1114 DE_NULL, // pNext 1115 (vk::VkPipelineMultisampleStateCreateFlags)0, 1116 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples 1117 DE_FALSE, // sampleShadingEnable 1118 0.0f, // minSampleShading 1119 DE_NULL, // pSampleMask 1120 vk::VK_FALSE, // alphaToCoverageEnable 1121 vk::VK_FALSE, // alphaToOneEnable 1122 }; 1123 const vk::VkPipelineRasterizationStateCreateInfo rasterParams = 1124 { 1125 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType 1126 DE_NULL, // pNext 1127 (vk::VkPipelineRasterizationStateCreateFlags)0, 1128 DE_TRUE, // depthClipEnable 1129 DE_FALSE, // rasterizerDiscardEnable 1130 vk::VK_POLYGON_MODE_FILL, // fillMode 1131 vk::VK_CULL_MODE_NONE, // cullMode; 1132 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace; 1133 vk::VK_FALSE, // depthBiasEnable 1134 0.0f, // depthBiasConstantFactor 1135 0.0f, // depthBiasClamp 1136 0.0f, // depthBiasSlopeFactor 1137 1.0f, // lineWidth 1138 }; 1139 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = 1140 { 1141 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // sType 1142 DE_NULL, // pNext 1143 (vk::VkPipelineInputAssemblyStateCreateFlags)0, 1144 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology 1145 DE_FALSE, // primitiveRestartEnable 1146 }; 1147 const vk::VkVertexInputBindingDescription vertexBindings[] = 1148 { 1149 { 1150 0u, // binding 1151 (deUint32)sizeof(tcu::Vec2), // stride 1152 vk::VK_VERTEX_INPUT_RATE_VERTEX, // stepRate 1153 }, 1154 { 1155 1u, // binding 1156 0u, // stride 1157 vk::VK_VERTEX_INPUT_RATE_INSTANCE, // stepRate 1158 }, 1159 }; 1160 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 1161 { 1162 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // sType 1163 DE_NULL, // pNext 1164 (vk::VkPipelineVertexInputStateCreateFlags)0, 1165 (inputValues.empty() ? 1u : 2u), // bindingCount 1166 vertexBindings, // pVertexBindingDescriptions 1167 (deUint32)vertexAttribParams.size(), // attributeCount 1168 &vertexAttribParams[0], // pVertexAttributeDescriptions 1169 }; 1170 const vk::VkColorComponentFlags allCompMask = vk::VK_COLOR_COMPONENT_R_BIT 1171 | vk::VK_COLOR_COMPONENT_G_BIT 1172 | vk::VK_COLOR_COMPONENT_B_BIT 1173 | vk::VK_COLOR_COMPONENT_A_BIT; 1174 const vk::VkPipelineColorBlendAttachmentState attBlendParams = 1175 { 1176 vk::VK_FALSE, // blendEnable 1177 vk::VK_BLEND_FACTOR_ONE, // srcBlendColor 1178 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor 1179 vk::VK_BLEND_OP_ADD, // blendOpColor 1180 vk::VK_BLEND_FACTOR_ONE, // srcBlendAlpha 1181 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha 1182 vk::VK_BLEND_OP_ADD, // blendOpAlpha 1183 allCompMask, // componentWriteMask 1184 }; 1185 const vk::VkPipelineColorBlendStateCreateInfo blendParams = 1186 { 1187 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // sType 1188 DE_NULL, // pNext 1189 (vk::VkPipelineColorBlendStateCreateFlags)0, 1190 vk::VK_FALSE, // logicOpEnable 1191 vk::VK_LOGIC_OP_COPY, // logicOp 1192 1u, // attachmentCount 1193 &attBlendParams, // pAttachments 1194 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants 1195 }; 1196 const vk::VkGraphicsPipelineCreateInfo pipelineParams = 1197 { 1198 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // sType 1199 DE_NULL, // pNext 1200 0u, // flags 1201 (deUint32)shaderStageParams.size(), // stageCount 1202 &shaderStageParams[0], // pStages 1203 &vertexInputStateParams, // pVertexInputState 1204 &inputAssemblyParams, // pInputAssemblyState 1205 DE_NULL, // pTessellationState 1206 &viewportParams, // pViewportState 1207 &rasterParams, // pRasterState 1208 &multisampleParams, // pMultisampleState 1209 &depthStencilParams, // pDepthStencilState 1210 &blendParams, // pColorBlendState 1211 (const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState 1212 pipelineLayout, // layout 1213 renderPass, // renderPass 1214 0u, // subpass 1215 DE_NULL, // basePipelineHandle 1216 0u, // basePipelineIndex 1217 }; 1218 1219 return vk::createGraphicsPipeline(context.getDeviceInterface(), context.getDevice(), DE_NULL, &pipelineParams); 1220 } 1221 1222 Move<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, vk::VkImageView colorAttView, int width, int height) 1223 { 1224 const vk::VkFramebufferCreateInfo framebufferParams = 1225 { 1226 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType 1227 DE_NULL, // pNext 1228 (vk::VkFramebufferCreateFlags)0, 1229 renderPass, // renderPass 1230 1u, // attachmentCount 1231 &colorAttView, // pAttachments 1232 (deUint32)width, // width 1233 (deUint32)height, // height 1234 1u, // layers 1235 }; 1236 1237 return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams); 1238 } 1239 1240 Move<vk::VkCommandPool> createCommandPool (Context& context) 1241 { 1242 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1243 const vk::VkCommandPoolCreateInfo params = 1244 { 1245 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType 1246 DE_NULL, // pNext 1247 (vk::VkCommandPoolCreateFlags)0, 1248 queueFamilyIndex, // queueFamilyIndex 1249 }; 1250 1251 return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), ¶ms); 1252 } 1253 1254 Move<vk::VkDescriptorPool> createDescriptorPool (Context& context) 1255 { 1256 return vk::DescriptorPoolBuilder() 1257 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u) 1258 .build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1259 } 1260 1261 Move<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout) 1262 { 1263 const vk::VkDescriptorSetAllocateInfo params = 1264 { 1265 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1266 DE_NULL, 1267 descriptorPool, 1268 1u, 1269 &setLayout 1270 }; 1271 1272 return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), ¶ms); 1273 } 1274 1275 Move<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool) 1276 { 1277 const vk::VkCommandBufferAllocateInfo params = 1278 { 1279 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType 1280 DE_NULL, // pNext 1281 cmdPool, // commandPool 1282 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 1283 1u, // bufferCount 1284 }; 1285 1286 return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), ¶ms); 1287 } 1288 1289 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkBuffer buffer, vk::MemoryRequirement memReqs) 1290 { 1291 const vk::DeviceInterface& vkd = context.getDeviceInterface(); 1292 const vk::VkMemoryRequirements bufReqs = vk::getBufferMemoryRequirements(vkd, context.getDevice(), buffer); 1293 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(bufReqs, memReqs); 1294 1295 vkd.bindBufferMemory(context.getDevice(), buffer, memory->getMemory(), memory->getOffset()); 1296 1297 return memory; 1298 } 1299 1300 MovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs) 1301 { 1302 const vk::DeviceInterface& vkd = context.getDeviceInterface(); 1303 const vk::VkMemoryRequirements imgReqs = vk::getImageMemoryRequirements(vkd, context.getDevice(), image); 1304 MovePtr<vk::Allocation> memory = context.getDefaultAllocator().allocate(imgReqs, memReqs); 1305 1306 vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset()); 1307 1308 return memory; 1309 } 1310 1311 void writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx) 1312 { 1313 copyToLayout(dst.getHostPtr(), layout, values, arrayNdx); 1314 1315 // \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches 1316 flushMappedMemoryRange(context.getDeviceInterface(), context.getDevice(), dst.getMemory(), dst.getOffset(), (vk::VkDeviceSize)layout.size); 1317 } 1318 1319 class ShaderCaseInstance : public TestInstance 1320 { 1321 public: 1322 ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec); 1323 ~ShaderCaseInstance (void); 1324 1325 TestStatus iterate (void); 1326 1327 private: 1328 enum 1329 { 1330 RENDER_WIDTH = 64, 1331 RENDER_HEIGHT = 64, 1332 1333 POSITIONS_OFFSET = 0, 1334 POSITIONS_SIZE = (int)sizeof(Vec2)*4, 1335 1336 INDICES_OFFSET = POSITIONS_SIZE, 1337 INDICES_SIZE = (int)sizeof(deUint16)*6, 1338 1339 TOTAL_POS_NDX_SIZE = POSITIONS_SIZE+INDICES_SIZE 1340 }; 1341 1342 const ShaderCaseSpecification& m_spec; 1343 1344 const Unique<vk::VkBuffer> m_posNdxBuffer; 1345 const UniquePtr<vk::Allocation> m_posNdxMem; 1346 1347 const ValueBufferLayout m_inputLayout; 1348 const Unique<vk::VkBuffer> m_inputBuffer; // Input values (attributes). Can be NULL if no inputs present 1349 const UniquePtr<vk::Allocation> m_inputMem; // Input memory, can be NULL if no input buffer exists 1350 1351 const ValueBufferLayout m_referenceLayout; 1352 const Unique<vk::VkBuffer> m_referenceBuffer; // Output (reference) values. Can be NULL if no outputs present 1353 const UniquePtr<vk::Allocation> m_referenceMem; // Output (reference) memory, can be NULL if no reference buffer exists 1354 1355 const ValueBufferLayout m_uniformLayout; 1356 const Unique<vk::VkBuffer> m_uniformBuffer; // Uniform values. Can be NULL if no uniforms present 1357 const UniquePtr<vk::Allocation> m_uniformMem; // Uniform memory, can be NULL if no uniform buffer exists 1358 1359 const Unique<vk::VkBuffer> m_readImageBuffer; 1360 const UniquePtr<vk::Allocation> m_readImageMem; 1361 1362 const Unique<vk::VkImage> m_rtImage; 1363 const UniquePtr<vk::Allocation> m_rtMem; 1364 const Unique<vk::VkImageView> m_rtView; 1365 1366 const Unique<vk::VkRenderPass> m_renderPass; 1367 const Unique<vk::VkFramebuffer> m_framebuffer; 1368 const PipelineProgram m_program; 1369 const Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout; 1370 const Unique<vk::VkPipelineLayout> m_pipelineLayout; 1371 const Unique<vk::VkPipeline> m_pipeline; 1372 1373 const Unique<vk::VkDescriptorPool> m_descriptorPool; 1374 const Unique<vk::VkDescriptorSet> m_descriptorSet; 1375 1376 const Unique<vk::VkCommandPool> m_cmdPool; 1377 const Unique<vk::VkCommandBuffer> m_cmdBuffer; 1378 1379 int m_subCaseNdx; 1380 }; 1381 1382 ShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec) 1383 : TestInstance (context) 1384 , m_spec (spec) 1385 1386 , m_posNdxBuffer (createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)) 1387 , m_posNdxMem (allocateAndBindMemory(context, *m_posNdxBuffer, vk::MemoryRequirement::HostVisible)) 1388 1389 , m_inputLayout (computeStd430Layout(spec.values.inputs)) 1390 , m_inputBuffer (m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>()) 1391 , m_inputMem (m_inputLayout.size > 0 ? allocateAndBindMemory(context, *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>()) 1392 1393 , m_referenceLayout (computeStd140Layout(spec.values.outputs)) 1394 , m_referenceBuffer (m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>()) 1395 , m_referenceMem (m_referenceLayout.size > 0 ? allocateAndBindMemory(context, *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>()) 1396 1397 , m_uniformLayout (computeStd140Layout(spec.values.uniforms)) 1398 , m_uniformBuffer (m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>()) 1399 , m_uniformMem (m_uniformLayout.size > 0 ? allocateAndBindMemory(context, *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>()) 1400 1401 , m_readImageBuffer (createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT)) 1402 , m_readImageMem (allocateAndBindMemory(context, *m_readImageBuffer, vk::MemoryRequirement::HostVisible)) 1403 1404 , m_rtImage (createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) 1405 , m_rtMem (allocateAndBindMemory(context, *m_rtImage, vk::MemoryRequirement::Any)) 1406 , m_rtView (createAttachmentView(context, *m_rtImage, vk::VK_FORMAT_R8G8B8A8_UNORM)) 1407 1408 , m_renderPass (createRenderPass(context, vk::VK_FORMAT_R8G8B8A8_UNORM)) 1409 , m_framebuffer (createFramebuffer(context, *m_renderPass, *m_rtView, RENDER_WIDTH, RENDER_HEIGHT)) 1410 , m_program (context, spec) 1411 , m_descriptorSetLayout (createDescriptorSetLayout(context, m_program.getStages())) 1412 , m_pipelineLayout (createPipelineLayout(context, *m_descriptorSetLayout)) 1413 , m_pipeline (createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT))) 1414 1415 , m_descriptorPool (createDescriptorPool(context)) 1416 , m_descriptorSet (allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout)) 1417 1418 , m_cmdPool (createCommandPool(context)) 1419 , m_cmdBuffer (allocateCommandBuffer(context, *m_cmdPool)) 1420 1421 , m_subCaseNdx (0) 1422 { 1423 const vk::DeviceInterface& vkd = context.getDeviceInterface(); 1424 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1425 1426 { 1427 const Vec2 s_positions[] = 1428 { 1429 Vec2(-1.0f, -1.0f), 1430 Vec2(-1.0f, +1.0f), 1431 Vec2(+1.0f, -1.0f), 1432 Vec2(+1.0f, +1.0f) 1433 }; 1434 const deUint16 s_indices[] = 1435 { 1436 0, 1, 2, 1437 1, 3, 2 1438 }; 1439 1440 DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE); 1441 DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE); 1442 1443 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET, &s_positions[0], sizeof(s_positions)); 1444 deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET, &s_indices[0], sizeof(s_indices)); 1445 1446 flushMappedMemoryRange(m_context.getDeviceInterface(), context.getDevice(), m_posNdxMem->getMemory(), m_posNdxMem->getOffset(), sizeof(s_positions)+sizeof(s_indices)); 1447 } 1448 1449 if (!m_spec.values.uniforms.empty()) 1450 { 1451 const vk::VkDescriptorBufferInfo bufInfo = 1452 { 1453 *m_uniformBuffer, 1454 (vk::VkDeviceSize)0, // offset 1455 (vk::VkDeviceSize)m_uniformLayout.size 1456 }; 1457 1458 vk::DescriptorSetUpdateBuilder() 1459 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING), 1460 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo) 1461 .update(vkd, m_context.getDevice()); 1462 } 1463 1464 if (!m_spec.values.outputs.empty()) 1465 { 1466 const vk::VkDescriptorBufferInfo bufInfo = 1467 { 1468 *m_referenceBuffer, 1469 (vk::VkDeviceSize)0, // offset 1470 (vk::VkDeviceSize)m_referenceLayout.size 1471 }; 1472 1473 vk::DescriptorSetUpdateBuilder() 1474 .writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING), 1475 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo) 1476 .update(vkd, m_context.getDevice()); 1477 } 1478 1479 // Record command buffer 1480 1481 { 1482 const vk::VkCommandBufferBeginInfo beginInfo = 1483 { 1484 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType 1485 DE_NULL, // pNext 1486 0u, // flags 1487 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 1488 }; 1489 1490 VK_CHECK(vkd.beginCommandBuffer(*m_cmdBuffer, &beginInfo)); 1491 } 1492 1493 { 1494 const vk::VkMemoryBarrier vertFlushBarrier = 1495 { 1496 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType 1497 DE_NULL, // pNext 1498 vk::VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask 1499 vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT, // dstAccessMask 1500 }; 1501 const vk::VkImageMemoryBarrier colorAttBarrier = 1502 { 1503 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 1504 DE_NULL, // pNext 1505 0u, // srcAccessMask 1506 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask 1507 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout 1508 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout 1509 queueFamilyIndex, // srcQueueFamilyIndex 1510 queueFamilyIndex, // destQueueFamilyIndex 1511 *m_rtImage, // image 1512 { 1513 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 1514 0u, // baseMipLevel 1515 1u, // mipLevels 1516 0u, // baseArraySlice 1517 1u, // arraySize 1518 } // subresourceRange 1519 }; 1520 1521 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0, 1522 1, &vertFlushBarrier, 1523 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1524 1, &colorAttBarrier); 1525 } 1526 1527 { 1528 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); 1529 const vk::VkRenderPassBeginInfo passBeginInfo = 1530 { 1531 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType 1532 DE_NULL, // pNext 1533 *m_renderPass, // renderPass 1534 *m_framebuffer, // framebuffer 1535 { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } }, // renderArea 1536 1u, // clearValueCount 1537 &clearValue, // pClearValues 1538 }; 1539 1540 vkd.cmdBeginRenderPass(*m_cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE); 1541 } 1542 1543 vkd.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); 1544 1545 if (!m_spec.values.uniforms.empty() || !m_spec.values.outputs.empty()) 1546 vkd.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL); 1547 1548 { 1549 const vk::VkBuffer buffers[] = { *m_posNdxBuffer, *m_inputBuffer }; 1550 const vk::VkDeviceSize offsets[] = { POSITIONS_OFFSET, 0u }; 1551 const deUint32 numBuffers = buffers[1] != 0 ? 2u : 1u; 1552 vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets); 1553 } 1554 1555 vkd.cmdBindIndexBuffer (*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16); 1556 vkd.cmdDrawIndexed (*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u); 1557 vkd.cmdEndRenderPass (*m_cmdBuffer); 1558 1559 { 1560 const vk::VkImageMemoryBarrier renderFinishBarrier = 1561 { 1562 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 1563 DE_NULL, // pNext 1564 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask 1565 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask 1566 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout 1567 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout 1568 queueFamilyIndex, // srcQueueFamilyIndex 1569 queueFamilyIndex, // destQueueFamilyIndex 1570 *m_rtImage, // image 1571 { 1572 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 1573 0u, // baseMipLevel 1574 1u, // mipLevels 1575 0u, // baseArraySlice 1576 1u, // arraySize 1577 } // subresourceRange 1578 }; 1579 1580 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 1581 0, (const vk::VkMemoryBarrier*)DE_NULL, 1582 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1583 1, &renderFinishBarrier); 1584 } 1585 1586 { 1587 const vk::VkBufferImageCopy copyParams = 1588 { 1589 (vk::VkDeviceSize)0u, // bufferOffset 1590 (deUint32)RENDER_WIDTH, // bufferRowLength 1591 (deUint32)RENDER_HEIGHT, // bufferImageHeight 1592 { 1593 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect 1594 0u, // mipLevel 1595 0u, // arrayLayer 1596 1u, // arraySize 1597 }, // imageSubresource 1598 { 0u, 0u, 0u }, // imageOffset 1599 { RENDER_WIDTH, RENDER_HEIGHT, 1u } // imageExtent 1600 }; 1601 1602 vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer, 1u, ©Params); 1603 } 1604 1605 { 1606 const vk::VkBufferMemoryBarrier copyFinishBarrier = 1607 { 1608 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType 1609 DE_NULL, // pNext 1610 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask 1611 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask 1612 queueFamilyIndex, // srcQueueFamilyIndex 1613 queueFamilyIndex, // destQueueFamilyIndex 1614 *m_readImageBuffer, // buffer 1615 0u, // offset 1616 (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4) // size 1617 }; 1618 1619 vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0, 1620 0, (const vk::VkMemoryBarrier*)DE_NULL, 1621 1, ©FinishBarrier, 1622 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 1623 } 1624 1625 VK_CHECK(vkd.endCommandBuffer(*m_cmdBuffer)); 1626 } 1627 1628 ShaderCaseInstance::~ShaderCaseInstance (void) 1629 { 1630 } 1631 1632 int getNumSubCases (const ValueBlock& values) 1633 { 1634 if (!values.outputs.empty()) 1635 return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize()); 1636 else 1637 return 1; // Always run at least one iteration even if no output values are specified 1638 } 1639 1640 bool checkResultImage (const ConstPixelBufferAccess& result) 1641 { 1642 const tcu::IVec4 refPix (255, 255, 255, 255); 1643 1644 for (int y = 0; y < result.getHeight(); y++) 1645 { 1646 for (int x = 0; x < result.getWidth(); x++) 1647 { 1648 const tcu::IVec4 resPix = result.getPixelInt(x, y); 1649 1650 if (boolAny(notEqual(resPix, refPix))) 1651 return false; 1652 } 1653 } 1654 1655 return true; 1656 } 1657 1658 TestStatus ShaderCaseInstance::iterate (void) 1659 { 1660 const vk::DeviceInterface& vkd = m_context.getDeviceInterface(); 1661 const vk::VkDevice device = m_context.getDevice(); 1662 const vk::VkQueue queue = m_context.getUniversalQueue(); 1663 1664 if (!m_spec.values.inputs.empty()) 1665 writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx); 1666 1667 if (!m_spec.values.outputs.empty()) 1668 writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx); 1669 1670 if (!m_spec.values.uniforms.empty()) 1671 writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx); 1672 1673 { 1674 const vk::VkSubmitInfo submitInfo = 1675 { 1676 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 1677 DE_NULL, 1678 0u, // waitSemaphoreCount 1679 (const vk::VkSemaphore*)0, // pWaitSemaphores 1680 (const vk::VkPipelineStageFlags*)DE_NULL, 1681 1u, 1682 &m_cmdBuffer.get(), 1683 0u, // signalSemaphoreCount 1684 (const vk::VkSemaphore*)0, // pSignalSemaphores 1685 }; 1686 const vk::VkFenceCreateInfo fenceParams = 1687 { 1688 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // sType 1689 DE_NULL, // pNext 1690 0u, // flags 1691 }; 1692 const Unique<vk::VkFence> fence (vk::createFence(vkd, device, &fenceParams)); 1693 1694 VK_CHECK(vkd.queueSubmit (queue, 1u, &submitInfo, *fence)); 1695 VK_CHECK(vkd.waitForFences (device, 1u, &fence.get(), DE_TRUE, ~0ull)); 1696 } 1697 1698 { 1699 const ConstPixelBufferAccess imgAccess (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem->getHostPtr()); 1700 1701 invalidateMappedMemoryRange(vkd, device, m_readImageMem->getMemory(), m_readImageMem->getOffset(), (vk::VkDeviceSize)(RENDER_WIDTH*RENDER_HEIGHT*4)); 1702 1703 if (!checkResultImage(imgAccess)) 1704 { 1705 TestLog& log = m_context.getTestContext().getLog(); 1706 1707 log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage 1708 << TestLog::Image("Result", "Result", imgAccess); 1709 1710 dumpValues(log, m_spec.values, m_subCaseNdx); 1711 1712 return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx)); 1713 } 1714 } 1715 1716 if (++m_subCaseNdx < getNumSubCases(m_spec.values)) 1717 return TestStatus::incomplete(); 1718 else 1719 return TestStatus::pass("All sub-cases passed"); 1720 } 1721 1722 class ShaderCase : public TestCase 1723 { 1724 public: 1725 ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec); 1726 1727 1728 void initPrograms (SourceCollections& programCollection) const; 1729 TestInstance* createInstance (Context& context) const; 1730 1731 private: 1732 const ShaderCaseSpecification m_spec; 1733 }; 1734 1735 ShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec) 1736 : TestCase (testCtx, name, description) 1737 , m_spec (spec) 1738 { 1739 } 1740 1741 void ShaderCase::initPrograms (SourceCollections& sourceCollection) const 1742 { 1743 vector<ProgramSources> specializedSources (m_spec.programs.size()); 1744 1745 DE_ASSERT(isValid(m_spec)); 1746 1747 if (m_spec.expectResult != glu::sl::EXPECT_PASS) 1748 TCU_THROW(InternalError, "Only EXPECT_PASS is supported"); 1749 1750 if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY) 1751 { 1752 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1); 1753 specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0])) 1754 << glu::FragmentSource(genFragmentShader(m_spec)); 1755 } 1756 else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY) 1757 { 1758 DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1); 1759 specializedSources[0] << glu::VertexSource(genVertexShader(m_spec)) 1760 << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0])); 1761 } 1762 else 1763 { 1764 DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE); 1765 1766 const int maxPatchVertices = 4; // \todo [2015-08-05 pyry] Query 1767 1768 for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++) 1769 { 1770 const ProgramSpecializationParams progSpecParams (m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices); 1771 1772 specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams); 1773 } 1774 } 1775 1776 for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++) 1777 { 1778 for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++) 1779 { 1780 if (!specializedSources[progNdx].sources[shaderType].empty()) 1781 { 1782 glu::ProgramSources& curSrc = sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx)); 1783 curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType]; 1784 } 1785 } 1786 } 1787 } 1788 1789 TestInstance* ShaderCase::createInstance (Context& context) const 1790 { 1791 return new ShaderCaseInstance(context, m_spec); 1792 } 1793 1794 class ShaderCaseFactory : public glu::sl::ShaderCaseFactory 1795 { 1796 public: 1797 ShaderCaseFactory (tcu::TestContext& testCtx) 1798 : m_testCtx(testCtx) 1799 { 1800 } 1801 1802 tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children) 1803 { 1804 return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children); 1805 } 1806 1807 tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec) 1808 { 1809 return new ShaderCase(m_testCtx, name, description, spec); 1810 } 1811 1812 private: 1813 tcu::TestContext& m_testCtx; 1814 }; 1815 1816 class ShaderLibraryGroup : public tcu::TestCaseGroup 1817 { 1818 public: 1819 ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename) 1820 : tcu::TestCaseGroup (testCtx, name.c_str(), description.c_str()) 1821 , m_filename (filename) 1822 { 1823 } 1824 1825 void init (void) 1826 { 1827 ShaderCaseFactory caseFactory (m_testCtx); 1828 const vector<tcu::TestNode*> children = glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory); 1829 1830 for (size_t ndx = 0; ndx < children.size(); ndx++) 1831 { 1832 try 1833 { 1834 addChild(children[ndx]); 1835 } 1836 catch (...) 1837 { 1838 for (; ndx < children.size(); ndx++) 1839 delete children[ndx]; 1840 throw; 1841 } 1842 } 1843 } 1844 1845 private: 1846 const string m_filename; 1847 }; 1848 1849 } // anonymous 1850 1851 MovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename) 1852 { 1853 return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename)); 1854 } 1855 1856 } // vkt 1857