1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Samsung Electronics Co., Ltd. 7 * Copyright (c) 2016 The Android Open Source Project 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Vulkan ShaderExecutor 24 *//*--------------------------------------------------------------------*/ 25 26 #include "vktShaderExecutor.hpp" 27 28 #include "vkMemUtil.hpp" 29 #include "vkRef.hpp" 30 #include "vkPrograms.hpp" 31 #include "vkRefUtil.hpp" 32 #include "vkTypeUtil.hpp" 33 #include "vkQueryUtil.hpp" 34 #include "vkBuilderUtil.hpp" 35 36 #include "gluShaderUtil.hpp" 37 38 #include "tcuVector.hpp" 39 #include "tcuTestLog.hpp" 40 #include "tcuTextureUtil.hpp" 41 42 #include "deUniquePtr.hpp" 43 #include "deStringUtil.hpp" 44 #include "deSharedPtr.hpp" 45 46 #include <map> 47 #include <sstream> 48 #include <iostream> 49 50 using std::vector; 51 using namespace vk; 52 53 namespace vkt 54 { 55 namespace shaderexecutor 56 { 57 namespace 58 { 59 60 enum 61 { 62 DEFAULT_RENDER_WIDTH = 100, 63 DEFAULT_RENDER_HEIGHT = 100, 64 }; 65 66 // Common typedefs 67 68 typedef de::SharedPtr<Unique<VkImage> > VkImageSp; 69 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp; 70 typedef de::SharedPtr<Unique<VkBuffer> > VkBufferSp; 71 typedef de::SharedPtr<Allocation> AllocationSp; 72 73 // Shader utilities 74 75 static VkClearValue getDefaultClearColor (void) 76 { 77 return makeClearValueColorF32(0.125f, 0.25f, 0.5f, 1.0f); 78 } 79 80 static std::string generateEmptyFragmentSource (void) 81 { 82 std::ostringstream src; 83 84 src << "#version 310 es\n" 85 "layout(location=0) out highp vec4 o_color;\n"; 86 87 src << "void main (void)\n{\n"; 88 src << " o_color = vec4(0.0);\n"; 89 src << "}\n"; 90 91 return src.str(); 92 } 93 94 static std::string generatePassthroughVertexShader (const std::vector<Symbol>& inputs, const char* inputPrefix, const char* outputPrefix) 95 { 96 97 std::ostringstream src; 98 int location = 0; 99 100 src << "#version 310 es\n" 101 "layout(location = " << location << ") in highp vec4 a_position;\n"; 102 103 for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input) 104 { 105 location++; 106 src << "layout(location = "<< location << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n" 107 << "layout(location = " << location - 1 << ") flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n"; 108 } 109 110 src << "\nvoid main (void)\n{\n" 111 << " gl_Position = a_position;\n" 112 << " gl_PointSize = 1.0;\n"; 113 114 for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input) 115 src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n"; 116 117 src << "}\n"; 118 119 return src.str(); 120 } 121 122 static std::string generateVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix) 123 { 124 DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty()); 125 126 std::ostringstream src; 127 128 src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n"; 129 130 if (!shaderSpec.globalDeclarations.empty()) 131 src << shaderSpec.globalDeclarations << "\n"; 132 133 src << "layout(location = 0) in highp vec4 a_position;\n"; 134 135 int locationNumber = 1; 136 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber) 137 src << "layout(location = " << locationNumber << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"; 138 139 locationNumber = 0; 140 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber) 141 { 142 DE_ASSERT(output->varType.isBasicType()); 143 144 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 145 { 146 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 147 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 148 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 149 150 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n"; 151 } 152 else 153 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n"; 154 } 155 156 src << "\n" 157 << "void main (void)\n" 158 << "{\n" 159 << " gl_Position = a_position;\n" 160 << " gl_PointSize = 1.0;\n"; 161 162 // Declare & fetch local input variables 163 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 164 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n"; 165 166 // Declare local output variables 167 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 168 src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 169 170 // Operation - indented to correct level. 171 { 172 std::istringstream opSrc (shaderSpec.source); 173 std::string line; 174 175 while (std::getline(opSrc, line)) 176 src << "\t" << line << "\n"; 177 } 178 179 // Assignments to outputs. 180 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 181 { 182 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 183 { 184 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 185 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 186 187 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 188 } 189 else 190 src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n"; 191 } 192 193 src << "}\n"; 194 195 return src.str(); 196 } 197 198 struct FragmentOutputLayout 199 { 200 std::vector<const Symbol*> locationSymbols; //! Symbols by location 201 std::map<std::string, int> locationMap; //! Map from symbol name to start location 202 }; 203 204 static void generateFragShaderOutputDecl (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& outputPrefix) 205 { 206 for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx) 207 { 208 const Symbol& output = shaderSpec.outputs[outNdx]; 209 const int location = de::lookup(outLocationMap, output.name); 210 const std::string outVarName = outputPrefix + output.name; 211 glu::VariableDeclaration decl (output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location)); 212 213 TCU_CHECK_INTERNAL(output.varType.isBasicType()); 214 215 if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType())) 216 { 217 const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 218 const glu::DataType uintBasicType = vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT; 219 const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 220 221 decl.varType = uintType; 222 src << decl << ";\n"; 223 } 224 else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType())) 225 { 226 const int vecSize = glu::getDataTypeScalarSize(output.varType.getBasicType()); 227 const glu::DataType intBasicType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 228 const glu::VarType intType (intBasicType, glu::PRECISION_HIGHP); 229 230 decl.varType = intType; 231 src << decl << ";\n"; 232 } 233 else if (glu::isDataTypeMatrix(output.varType.getBasicType())) 234 { 235 const int vecSize = glu::getDataTypeMatrixNumRows(output.varType.getBasicType()); 236 const int numVecs = glu::getDataTypeMatrixNumColumns(output.varType.getBasicType()); 237 const glu::DataType uintBasicType = glu::getDataTypeUintVec(vecSize); 238 const glu::VarType uintType (uintBasicType, glu::PRECISION_HIGHP); 239 240 decl.varType = uintType; 241 for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 242 { 243 decl.name = outVarName + "_" + de::toString(vecNdx); 244 decl.layout.location = location + vecNdx; 245 src << decl << ";\n"; 246 } 247 } 248 else 249 src << decl << ";\n"; 250 } 251 } 252 253 static void generateFragShaderOutAssign (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::string& valuePrefix, const std::string& outputPrefix) 254 { 255 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 256 { 257 if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType())) 258 src << " o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n"; 259 else if (glu::isDataTypeMatrix(output->varType.getBasicType())) 260 { 261 const int numVecs = glu::getDataTypeMatrixNumColumns(output->varType.getBasicType()); 262 263 for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx) 264 if (useIntOutputs) 265 src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix << output->name << "[" << vecNdx << "]);\n"; 266 else 267 src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name << "[" << vecNdx << "];\n"; 268 } 269 else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 270 { 271 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 272 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 273 274 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << valuePrefix << output->name << ");\n"; 275 } 276 else 277 src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n"; 278 } 279 } 280 281 static std::string generatePassthroughFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix) 282 { 283 std::ostringstream src; 284 285 src <<"#version 310 es\n"; 286 287 if (!shaderSpec.globalDeclarations.empty()) 288 src << shaderSpec.globalDeclarations << "\n"; 289 290 int locationNumber = 0; 291 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber) 292 { 293 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 294 { 295 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 296 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 297 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 298 299 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n"; 300 } 301 else 302 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n"; 303 } 304 305 generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix); 306 307 src << "\nvoid main (void)\n{\n"; 308 309 generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix); 310 311 src << "}\n"; 312 313 return src.str(); 314 } 315 316 static std::string generateGeometryShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix) 317 { 318 DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty()); 319 320 std::ostringstream src; 321 322 src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n"; 323 324 if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES) 325 src << "#extension GL_EXT_geometry_shader : require\n"; 326 327 if (!shaderSpec.globalDeclarations.empty()) 328 src << shaderSpec.globalDeclarations << "\n"; 329 330 src << "layout(points) in;\n" 331 << "layout(points, max_vertices = 1) out;\n"; 332 333 int locationNumber = 0; 334 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber) 335 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n"; 336 337 locationNumber = 0; 338 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber) 339 { 340 DE_ASSERT(output->varType.isBasicType()); 341 342 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 343 { 344 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 345 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 346 const glu::VarType intType (intBaseType, glu::PRECISION_HIGHP); 347 348 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n"; 349 } 350 else 351 src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n"; 352 } 353 354 src << "\n" 355 << "void main (void)\n" 356 << "{\n" 357 << " gl_Position = gl_in[0].gl_Position;\n\n"; 358 359 // Fetch input variables 360 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 361 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n"; 362 363 // Declare local output variables. 364 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 365 src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 366 367 src << "\n"; 368 369 // Operation - indented to correct level. 370 { 371 std::istringstream opSrc (shaderSpec.source); 372 std::string line; 373 374 while (std::getline(opSrc, line)) 375 src << "\t" << line << "\n"; 376 } 377 378 // Assignments to outputs. 379 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 380 { 381 if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType())) 382 { 383 const int vecSize = glu::getDataTypeScalarSize(output->varType.getBasicType()); 384 const glu::DataType intBaseType = vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT; 385 386 src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n"; 387 } 388 else 389 src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n"; 390 } 391 392 src << " EmitVertex();\n" 393 << " EndPrimitive();\n" 394 << "}\n"; 395 396 return src.str(); 397 } 398 399 static std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix) 400 { 401 std::ostringstream src; 402 src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n"; 403 if (!shaderSpec.globalDeclarations.empty()) 404 src << shaderSpec.globalDeclarations << "\n"; 405 406 int locationNumber = 0; 407 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber) 408 src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"; 409 410 generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix); 411 412 src << "\nvoid main (void)\n{\n"; 413 414 // Declare & fetch local input variables 415 for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input) 416 src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n"; 417 418 // Declare output variables 419 for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output) 420 src << "\t" << glu::declare(output->varType, output->name) << ";\n"; 421 422 // Operation - indented to correct level. 423 { 424 std::istringstream opSrc (shaderSpec.source); 425 std::string line; 426 427 while (std::getline(opSrc, line)) 428 src << "\t" << line << "\n"; 429 } 430 431 generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix); 432 433 src << "}\n"; 434 435 return src.str(); 436 } 437 438 // FragmentOutExecutor 439 440 class FragmentOutExecutor : public ShaderExecutor 441 { 442 public: 443 FragmentOutExecutor (Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 444 virtual ~FragmentOutExecutor (void); 445 446 virtual void execute (int numValues, 447 const void* const* inputs, 448 void* const* outputs, 449 VkDescriptorSet extraResources); 450 451 protected: 452 const glu::ShaderType m_shaderType; 453 const FragmentOutputLayout m_outputLayout; 454 455 private: 456 void bindAttributes (int numValues, 457 const void* const* inputs); 458 459 void addAttribute (deUint32 bindingLocation, 460 VkFormat format, 461 deUint32 sizePerElement, 462 deUint32 count, 463 const void* dataPtr); 464 // reinit render data members 465 virtual void clearRenderData (void); 466 467 const VkDescriptorSetLayout m_extraResourcesLayout; 468 469 std::vector<VkVertexInputBindingDescription> m_vertexBindingDescriptions; 470 std::vector<VkVertexInputAttributeDescription> m_vertexAttributeDescriptions; 471 std::vector<VkBufferSp> m_vertexBuffers; 472 std::vector<AllocationSp> m_vertexBufferAllocs; 473 }; 474 475 static FragmentOutputLayout computeFragmentOutputLayout (const std::vector<Symbol>& symbols) 476 { 477 FragmentOutputLayout ret; 478 int location = 0; 479 480 for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it) 481 { 482 const int numLocations = glu::getDataTypeNumLocations(it->varType.getBasicType()); 483 484 TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name)); 485 de::insert(ret.locationMap, it->name, location); 486 location += numLocations; 487 488 for (int ndx = 0; ndx < numLocations; ++ndx) 489 ret.locationSymbols.push_back(&*it); 490 } 491 492 return ret; 493 } 494 495 FragmentOutExecutor::FragmentOutExecutor (Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 496 : ShaderExecutor (context, shaderSpec) 497 , m_shaderType (shaderType) 498 , m_outputLayout (computeFragmentOutputLayout(m_shaderSpec.outputs)) 499 , m_extraResourcesLayout (extraResourcesLayout) 500 { 501 } 502 503 FragmentOutExecutor::~FragmentOutExecutor (void) 504 { 505 } 506 507 static std::vector<tcu::Vec2> computeVertexPositions (int numValues, const tcu::IVec2& renderSize) 508 { 509 std::vector<tcu::Vec2> positions(numValues); 510 for (int valNdx = 0; valNdx < numValues; valNdx++) 511 { 512 const int ix = valNdx % renderSize.x(); 513 const int iy = valNdx / renderSize.x(); 514 const float fx = -1.0f + 2.0f*((float(ix) + 0.5f) / float(renderSize.x())); 515 const float fy = -1.0f + 2.0f*((float(iy) + 0.5f) / float(renderSize.y())); 516 517 positions[valNdx] = tcu::Vec2(fx, fy); 518 } 519 520 return positions; 521 } 522 523 static tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs) 524 { 525 const tcu::TextureFormat::ChannelOrder channelOrderMap[] = 526 { 527 tcu::TextureFormat::R, 528 tcu::TextureFormat::RG, 529 tcu::TextureFormat::RGBA, // No RGB variants available. 530 tcu::TextureFormat::RGBA 531 }; 532 533 const glu::DataType basicType = outputType.getBasicType(); 534 const int numComps = glu::getDataTypeNumComponents(basicType); 535 tcu::TextureFormat::ChannelType channelType; 536 537 switch (glu::getDataTypeScalarType(basicType)) 538 { 539 case glu::TYPE_UINT: channelType = tcu::TextureFormat::UNSIGNED_INT32; break; 540 case glu::TYPE_INT: channelType = tcu::TextureFormat::SIGNED_INT32; break; 541 case glu::TYPE_BOOL: channelType = tcu::TextureFormat::SIGNED_INT32; break; 542 case glu::TYPE_FLOAT: channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT; break; 543 default: 544 throw tcu::InternalError("Invalid output type"); 545 } 546 547 DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap))); 548 549 return tcu::TextureFormat(channelOrderMap[numComps-1], channelType); 550 } 551 552 static VkFormat getAttributeFormat (const glu::DataType dataType) 553 { 554 switch (dataType) 555 { 556 case glu::TYPE_FLOAT: return VK_FORMAT_R32_SFLOAT; 557 case glu::TYPE_FLOAT_VEC2: return VK_FORMAT_R32G32_SFLOAT; 558 case glu::TYPE_FLOAT_VEC3: return VK_FORMAT_R32G32B32_SFLOAT; 559 case glu::TYPE_FLOAT_VEC4: return VK_FORMAT_R32G32B32A32_SFLOAT; 560 561 case glu::TYPE_INT: return VK_FORMAT_R32_SINT; 562 case glu::TYPE_INT_VEC2: return VK_FORMAT_R32G32_SINT; 563 case glu::TYPE_INT_VEC3: return VK_FORMAT_R32G32B32_SINT; 564 case glu::TYPE_INT_VEC4: return VK_FORMAT_R32G32B32A32_SINT; 565 566 case glu::TYPE_UINT: return VK_FORMAT_R32_UINT; 567 case glu::TYPE_UINT_VEC2: return VK_FORMAT_R32G32_UINT; 568 case glu::TYPE_UINT_VEC3: return VK_FORMAT_R32G32B32_UINT; 569 case glu::TYPE_UINT_VEC4: return VK_FORMAT_R32G32B32A32_UINT; 570 571 case glu::TYPE_FLOAT_MAT2: return VK_FORMAT_R32G32_SFLOAT; 572 case glu::TYPE_FLOAT_MAT2X3: return VK_FORMAT_R32G32B32_SFLOAT; 573 case glu::TYPE_FLOAT_MAT2X4: return VK_FORMAT_R32G32B32A32_SFLOAT; 574 case glu::TYPE_FLOAT_MAT3X2: return VK_FORMAT_R32G32_SFLOAT; 575 case glu::TYPE_FLOAT_MAT3: return VK_FORMAT_R32G32B32_SFLOAT; 576 case glu::TYPE_FLOAT_MAT3X4: return VK_FORMAT_R32G32B32A32_SFLOAT; 577 case glu::TYPE_FLOAT_MAT4X2: return VK_FORMAT_R32G32_SFLOAT; 578 case glu::TYPE_FLOAT_MAT4X3: return VK_FORMAT_R32G32B32_SFLOAT; 579 case glu::TYPE_FLOAT_MAT4: return VK_FORMAT_R32G32B32A32_SFLOAT; 580 default: 581 DE_ASSERT(false); 582 return VK_FORMAT_UNDEFINED; 583 } 584 } 585 586 void FragmentOutExecutor::addAttribute (deUint32 bindingLocation, VkFormat format, deUint32 sizePerElement, deUint32 count, const void* dataPtr) 587 { 588 // Add binding specification 589 const deUint32 binding = (deUint32)m_vertexBindingDescriptions.size(); 590 const VkVertexInputBindingDescription bindingDescription = 591 { 592 binding, 593 sizePerElement, 594 VK_VERTEX_INPUT_RATE_VERTEX 595 }; 596 597 m_vertexBindingDescriptions.push_back(bindingDescription); 598 599 // Add location and format specification 600 const VkVertexInputAttributeDescription attributeDescription = 601 { 602 bindingLocation, // deUint32 location; 603 binding, // deUint32 binding; 604 format, // VkFormat format; 605 0u, // deUint32 offsetInBytes; 606 }; 607 608 m_vertexAttributeDescriptions.push_back(attributeDescription); 609 610 // Upload data to buffer 611 const VkDevice vkDevice = m_context.getDevice(); 612 const DeviceInterface& vk = m_context.getDeviceInterface(); 613 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 614 615 const VkDeviceSize inputSize = sizePerElement * count; 616 const VkBufferCreateInfo vertexBufferParams = 617 { 618 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 619 DE_NULL, // const void* pNext; 620 0u, // VkBufferCreateFlags flags; 621 inputSize, // VkDeviceSize size; 622 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 623 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 624 1u, // deUint32 queueFamilyCount; 625 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 626 }; 627 628 Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &vertexBufferParams); 629 de::MovePtr<Allocation> alloc = m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible); 630 631 VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset())); 632 633 deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize); 634 flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize); 635 636 m_vertexBuffers.push_back(de::SharedPtr<Unique<VkBuffer> >(new Unique<VkBuffer>(buffer))); 637 m_vertexBufferAllocs.push_back(AllocationSp(alloc.release())); 638 } 639 640 void FragmentOutExecutor::bindAttributes (int numValues, const void* const* inputs) 641 { 642 // Input attributes 643 for (int inputNdx = 0; inputNdx < (int)m_shaderSpec.inputs.size(); inputNdx++) 644 { 645 const Symbol& symbol = m_shaderSpec.inputs[inputNdx]; 646 const void* ptr = inputs[inputNdx]; 647 const glu::DataType basicType = symbol.varType.getBasicType(); 648 const int vecSize = glu::getDataTypeScalarSize(basicType); 649 const VkFormat format = getAttributeFormat(basicType); 650 int elementSize = 0; 651 int numAttrsToAdd = 1; 652 653 if (glu::isDataTypeFloatOrVec(basicType)) 654 elementSize = sizeof(float); 655 else if (glu::isDataTypeIntOrIVec(basicType)) 656 elementSize = sizeof(int); 657 else if (glu::isDataTypeUintOrUVec(basicType)) 658 elementSize = sizeof(deUint32); 659 else if (glu::isDataTypeMatrix(basicType)) 660 { 661 int numRows = glu::getDataTypeMatrixNumRows(basicType); 662 int numCols = glu::getDataTypeMatrixNumColumns(basicType); 663 664 elementSize = numRows * numCols * (int)sizeof(float); 665 numAttrsToAdd = numCols; 666 } 667 else 668 DE_ASSERT(false); 669 670 // add attributes, in case of matrix every column is binded as an attribute 671 for (int attrNdx = 0; attrNdx < numAttrsToAdd; attrNdx++) 672 { 673 addAttribute((deUint32)m_vertexBindingDescriptions.size(), format, elementSize * vecSize, numValues, ptr); 674 } 675 } 676 } 677 678 void FragmentOutExecutor::clearRenderData (void) 679 { 680 m_vertexBindingDescriptions.clear(); 681 m_vertexAttributeDescriptions.clear(); 682 m_vertexBuffers.clear(); 683 m_vertexBufferAllocs.clear(); 684 } 685 686 static Move<VkDescriptorSetLayout> createEmptyDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device) 687 { 688 const VkDescriptorSetLayoutCreateInfo createInfo = 689 { 690 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 691 DE_NULL, 692 (VkDescriptorSetLayoutCreateFlags)0, 693 0u, 694 DE_NULL, 695 }; 696 return createDescriptorSetLayout(vkd, device, &createInfo); 697 } 698 699 static Move<VkDescriptorPool> createDummyDescriptorPool (const DeviceInterface& vkd, VkDevice device) 700 { 701 const VkDescriptorPoolSize dummySize = 702 { 703 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 704 1u, 705 }; 706 const VkDescriptorPoolCreateInfo createInfo = 707 { 708 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 709 DE_NULL, 710 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 711 1u, 712 1u, 713 &dummySize 714 }; 715 return createDescriptorPool(vkd, device, &createInfo); 716 } 717 718 static Move<VkDescriptorSet> allocateSingleDescriptorSet (const DeviceInterface& vkd, VkDevice device, VkDescriptorPool pool, VkDescriptorSetLayout layout) 719 { 720 const VkDescriptorSetAllocateInfo allocInfo = 721 { 722 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 723 DE_NULL, 724 pool, 725 1u, 726 &layout, 727 }; 728 return allocateDescriptorSet(vkd, device, &allocInfo); 729 } 730 731 void FragmentOutExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources) 732 { 733 const VkDevice vkDevice = m_context.getDevice(); 734 const DeviceInterface& vk = m_context.getDeviceInterface(); 735 const VkQueue queue = m_context.getUniversalQueue(); 736 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 737 Allocator& memAlloc = m_context.getDefaultAllocator(); 738 739 const deUint32 renderSizeX = de::min(static_cast<deUint32>(DEFAULT_RENDER_WIDTH), (deUint32)numValues); 740 const deUint32 renderSizeY = ((deUint32)numValues / renderSizeX) + (((deUint32)numValues % renderSizeX != 0) ? 1u : 0u); 741 const tcu::UVec2 renderSize (renderSizeX, renderSizeY); 742 std::vector<tcu::Vec2> positions; 743 744 const bool useGeometryShader = m_shaderType == glu::SHADERTYPE_GEOMETRY; 745 746 std::vector<VkImageSp> colorImages; 747 std::vector<VkImageMemoryBarrier> colorImagePreRenderBarriers; 748 std::vector<VkImageMemoryBarrier> colorImagePostRenderBarriers; 749 std::vector<AllocationSp> colorImageAllocs; 750 std::vector<VkAttachmentDescription> attachments; 751 std::vector<VkClearValue> attachmentClearValues; 752 std::vector<VkImageViewSp> colorImageViews; 753 754 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates; 755 std::vector<VkAttachmentReference> colorAttachmentReferences; 756 757 Move<VkRenderPass> renderPass; 758 Move<VkFramebuffer> framebuffer; 759 Move<VkPipelineLayout> pipelineLayout; 760 Move<VkPipeline> graphicsPipeline; 761 762 Move<VkShaderModule> vertexShaderModule; 763 Move<VkShaderModule> geometryShaderModule; 764 Move<VkShaderModule> fragmentShaderModule; 765 766 Move<VkCommandPool> cmdPool; 767 Move<VkCommandBuffer> cmdBuffer; 768 769 Move<VkFence> fence; 770 771 Unique<VkDescriptorSetLayout> emptyDescriptorSetLayout (createEmptyDescriptorSetLayout(vk, vkDevice)); 772 Unique<VkDescriptorPool> dummyDescriptorPool (createDummyDescriptorPool(vk, vkDevice)); 773 Unique<VkDescriptorSet> emptyDescriptorSet (allocateSingleDescriptorSet(vk, vkDevice, *dummyDescriptorPool, *emptyDescriptorSetLayout)); 774 775 clearRenderData(); 776 777 // Compute positions - 1px points are used to drive fragment shading. 778 positions = computeVertexPositions(numValues, renderSize.cast<int>()); 779 780 // Bind attributes 781 addAttribute(0u, VK_FORMAT_R32G32_SFLOAT, sizeof(tcu::Vec2), (deUint32)positions.size(), &positions[0]); 782 bindAttributes(numValues, inputs); 783 784 // Create color images 785 { 786 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 787 { 788 VK_FALSE, // VkBool32 blendEnable; 789 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 790 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 791 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; 792 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 793 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destAlphaBlendFactor; 794 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; 795 (VK_COLOR_COMPONENT_R_BIT | 796 VK_COLOR_COMPONENT_G_BIT | 797 VK_COLOR_COMPONENT_B_BIT | 798 VK_COLOR_COMPONENT_A_BIT) // VkColorComponentFlags colorWriteMask; 799 }; 800 801 for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx) 802 { 803 const bool isFloat = isDataTypeFloatOrVec(m_shaderSpec.outputs[outNdx].varType.getBasicType()); 804 const bool isSigned = isDataTypeIntOrIVec (m_shaderSpec.outputs[outNdx].varType.getBasicType()); 805 const bool isBool = isDataTypeBoolOrBVec(m_shaderSpec.outputs[outNdx].varType.getBasicType()); 806 const VkFormat colorFormat = isFloat ? VK_FORMAT_R32G32B32A32_SFLOAT : (isSigned || isBool ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32G32B32A32_UINT); 807 808 const VkImageCreateInfo colorImageParams = 809 { 810 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 811 DE_NULL, // const void* pNext; 812 0u, // VkImageCreateFlags flags; 813 VK_IMAGE_TYPE_2D, // VkImageType imageType; 814 colorFormat, // VkFormat format; 815 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent; 816 1u, // deUint32 mipLevels; 817 1u, // deUint32 arraySize; 818 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 819 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 820 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 821 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 822 1u, // deUint32 queueFamilyCount; 823 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 824 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 825 }; 826 827 const VkAttachmentDescription colorAttachmentDescription = 828 { 829 0u, // VkAttachmentDescriptorFlags flags; 830 colorFormat, // VkFormat format; 831 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 832 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 833 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 834 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 835 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 836 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 837 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 838 }; 839 840 Move<VkImage> colorImage = createImage(vk, vkDevice, &colorImageParams); 841 colorImages.push_back(de::SharedPtr<Unique<VkImage> >(new Unique<VkImage>(colorImage))); 842 attachmentClearValues.push_back(getDefaultClearColor()); 843 844 // Allocate and bind color image memory 845 { 846 de::MovePtr<Allocation> colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *((const VkImage*) colorImages.back().get())), MemoryRequirement::Any); 847 VK_CHECK(vk.bindImageMemory(vkDevice, colorImages.back().get()->get(), colorImageAlloc->getMemory(), colorImageAlloc->getOffset())); 848 colorImageAllocs.push_back(de::SharedPtr<Allocation>(colorImageAlloc.release())); 849 850 attachments.push_back(colorAttachmentDescription); 851 colorBlendAttachmentStates.push_back(colorBlendAttachmentState); 852 853 const VkAttachmentReference colorAttachmentReference = 854 { 855 (deUint32) (colorImages.size() - 1), // deUint32 attachment; 856 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 857 }; 858 859 colorAttachmentReferences.push_back(colorAttachmentReference); 860 } 861 862 // Create color attachment view 863 { 864 const VkImageViewCreateInfo colorImageViewParams = 865 { 866 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 867 DE_NULL, // const void* pNext; 868 0u, // VkImageViewCreateFlags flags; 869 colorImages.back().get()->get(), // VkImage image; 870 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 871 colorFormat, // VkFormat format; 872 { 873 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r; 874 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g; 875 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b; 876 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a; 877 }, // VkComponentMapping components; 878 { 879 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 880 0u, // deUint32 baseMipLevel; 881 1u, // deUint32 mipLevels; 882 0u, // deUint32 baseArraySlice; 883 1u // deUint32 arraySize; 884 } // VkImageSubresourceRange subresourceRange; 885 }; 886 887 Move<VkImageView> colorImageView = createImageView(vk, vkDevice, &colorImageViewParams); 888 colorImageViews.push_back(de::SharedPtr<Unique<VkImageView> >(new Unique<VkImageView>(colorImageView))); 889 890 const VkImageMemoryBarrier colorImagePreRenderBarrier = 891 { 892 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 893 DE_NULL, // pNext 894 0u, // srcAccessMask 895 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 896 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // dstAccessMask 897 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout 898 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout 899 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 900 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex 901 colorImages.back().get()->get(), // image 902 { 903 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 904 0u, // baseMipLevel 905 1u, // levelCount 906 0u, // baseArrayLayer 907 1u, // layerCount 908 } // subresourceRange 909 }; 910 colorImagePreRenderBarriers.push_back(colorImagePreRenderBarrier); 911 912 const VkImageMemoryBarrier colorImagePostRenderBarrier = 913 { 914 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType 915 DE_NULL, // pNext 916 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | 917 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // srcAccessMask 918 VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask 919 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout 920 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout 921 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 922 VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex 923 colorImages.back().get()->get(), // image 924 { 925 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 926 0u, // baseMipLevel 927 1u, // levelCount 928 0u, // baseArrayLayer 929 1u, // layerCount 930 } // subresourceRange 931 }; 932 colorImagePostRenderBarriers.push_back(colorImagePostRenderBarrier); 933 } 934 } 935 } 936 937 // Create render pass 938 { 939 const VkSubpassDescription subpassDescription = 940 { 941 0u, // VkSubpassDescriptionFlags flags; 942 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 943 0u, // deUint32 inputCount; 944 DE_NULL, // const VkAttachmentReference* pInputAttachments; 945 (deUint32)colorImages.size(), // deUint32 colorCount; 946 &colorAttachmentReferences[0], // const VkAttachmentReference* colorAttachments; 947 DE_NULL, // const VkAttachmentReference* resolveAttachments; 948 DE_NULL, // VkAttachmentReference depthStencilAttachment; 949 0u, // deUint32 preserveCount; 950 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 951 }; 952 953 const VkRenderPassCreateInfo renderPassParams = 954 { 955 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 956 DE_NULL, // const void* pNext; 957 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 958 (deUint32)attachments.size(), // deUint32 attachmentCount; 959 &attachments[0], // const VkAttachmentDescription* pAttachments; 960 1u, // deUint32 subpassCount; 961 &subpassDescription, // const VkSubpassDescription* pSubpasses; 962 0u, // deUint32 dependencyCount; 963 DE_NULL // const VkSubpassDependency* pDependencies; 964 }; 965 966 renderPass = createRenderPass(vk, vkDevice, &renderPassParams); 967 } 968 969 // Create framebuffer 970 { 971 std::vector<VkImageView> views(colorImageViews.size()); 972 for (size_t i = 0; i < colorImageViews.size(); i++) 973 { 974 views[i] = colorImageViews[i].get()->get(); 975 } 976 977 const VkFramebufferCreateInfo framebufferParams = 978 { 979 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 980 DE_NULL, // const void* pNext; 981 0u, // VkFramebufferCreateFlags flags; 982 *renderPass, // VkRenderPass renderPass; 983 (deUint32)views.size(), // deUint32 attachmentCount; 984 &views[0], // const VkImageView* pAttachments; 985 (deUint32)renderSize.x(), // deUint32 width; 986 (deUint32)renderSize.y(), // deUint32 height; 987 1u // deUint32 layers; 988 }; 989 990 framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 991 } 992 993 // Create pipeline layout 994 { 995 const VkDescriptorSetLayout setLayouts[] = 996 { 997 *emptyDescriptorSetLayout, 998 m_extraResourcesLayout 999 }; 1000 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 1001 { 1002 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 1003 DE_NULL, // const void* pNext; 1004 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 1005 (m_extraResourcesLayout != 0 ? 2u : 0u), // deUint32 descriptorSetCount; 1006 setLayouts, // const VkDescriptorSetLayout* pSetLayouts; 1007 0u, // deUint32 pushConstantRangeCount; 1008 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 1009 }; 1010 1011 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 1012 } 1013 1014 // Create shaders 1015 { 1016 vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0); 1017 fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0); 1018 1019 if (useGeometryShader) 1020 { 1021 geometryShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("geom"), 0); 1022 } 1023 } 1024 1025 // Create pipeline 1026 { 1027 std::vector<VkPipelineShaderStageCreateInfo> shaderStageParams; 1028 1029 const VkPipelineShaderStageCreateInfo vertexShaderStageParams = 1030 { 1031 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1032 DE_NULL, // const void* pNext; 1033 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 1034 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 1035 *vertexShaderModule, // VkShaderModule module; 1036 "main", // const char* pName; 1037 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 1038 }; 1039 1040 const VkPipelineShaderStageCreateInfo fragmentShaderStageParams = 1041 { 1042 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1043 DE_NULL, // const void* pNext; 1044 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 1045 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 1046 *fragmentShaderModule, // VkShaderModule module; 1047 "main", // const char* pName; 1048 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 1049 }; 1050 1051 shaderStageParams.push_back(vertexShaderStageParams); 1052 shaderStageParams.push_back(fragmentShaderStageParams); 1053 1054 if (useGeometryShader) 1055 { 1056 const VkPipelineShaderStageCreateInfo geometryShaderStageParams = 1057 { 1058 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1059 DE_NULL, // const void* pNext; 1060 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 1061 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage; 1062 *geometryShaderModule, // VkShaderModule module; 1063 "main", // VkShader shader; 1064 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 1065 }; 1066 1067 shaderStageParams.push_back(geometryShaderStageParams); 1068 } 1069 1070 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 1071 { 1072 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 1073 DE_NULL, // const void* pNext; 1074 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 1075 (deUint32)m_vertexBindingDescriptions.size(), // deUint32 bindingCount; 1076 &m_vertexBindingDescriptions[0], // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 1077 (deUint32)m_vertexAttributeDescriptions.size(), // deUint32 attributeCount; 1078 &m_vertexAttributeDescriptions[0], // const VkVertexInputAttributeDescription* pvertexAttributeDescriptions; 1079 }; 1080 1081 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 1082 { 1083 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 1084 DE_NULL, // const void* pNext; 1085 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 1086 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology; 1087 DE_FALSE // VkBool32 primitiveRestartEnable; 1088 }; 1089 1090 const VkViewport viewport = 1091 { 1092 0.0f, // float originX; 1093 0.0f, // float originY; 1094 (float)renderSize.x(), // float width; 1095 (float)renderSize.y(), // float height; 1096 0.0f, // float minDepth; 1097 1.0f // float maxDepth; 1098 }; 1099 1100 const VkRect2D scissor = 1101 { 1102 { 1103 0u, // deUint32 x; 1104 0u, // deUint32 y; 1105 }, // VkOffset2D offset; 1106 { 1107 renderSize.x(), // deUint32 width; 1108 renderSize.y(), // deUint32 height; 1109 }, // VkExtent2D extent; 1110 }; 1111 1112 const VkPipelineViewportStateCreateInfo viewportStateParams = 1113 { 1114 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 1115 DE_NULL, // const void* pNext; 1116 0u, // VkPipelineViewportStateCreateFlags flags; 1117 1u, // deUint32 viewportCount; 1118 &viewport, // const VkViewport* pViewports; 1119 1u, // deUint32 scissorsCount; 1120 &scissor // const VkRect2D* pScissors; 1121 }; 1122 1123 const VkPipelineRasterizationStateCreateInfo rasterStateParams = 1124 { 1125 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 1126 DE_NULL, // const void* pNext; 1127 (VkPipelineRasterizationStateCreateFlags)0u, //VkPipelineRasterizationStateCreateFlags flags; 1128 VK_FALSE, // VkBool32 depthClipEnable; 1129 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 1130 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 1131 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 1132 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 1133 VK_FALSE, // VkBool32 depthBiasEnable; 1134 0.0f, // float depthBias; 1135 0.0f, // float depthBiasClamp; 1136 0.0f, // float slopeScaledDepthBias; 1137 1.0f // float lineWidth; 1138 }; 1139 1140 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 1141 { 1142 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 1143 DE_NULL, // const void* pNext; 1144 0u, // VkPipelineMultisampleStateCreateFlags flags; 1145 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 1146 VK_FALSE, // VkBool32 sampleShadingEnable; 1147 0.0f, // float minSampleShading; 1148 DE_NULL, // const VkSampleMask* pSampleMask; 1149 VK_FALSE, // VkBool32 alphaToCoverageEnable; 1150 VK_FALSE // VkBool32 alphaToOneEnable; 1151 }; 1152 1153 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 1154 { 1155 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1156 DE_NULL, // const void* pNext; 1157 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 1158 VK_FALSE, // VkBool32 logicOpEnable; 1159 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 1160 (deUint32)colorBlendAttachmentStates.size(), // deUint32 attachmentCount; 1161 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments; 1162 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConst[4]; 1163 }; 1164 1165 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 1166 { 1167 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 1168 DE_NULL, // const void* pNext; 1169 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 1170 (deUint32)shaderStageParams.size(), // deUint32 stageCount; 1171 &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages; 1172 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 1173 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 1174 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 1175 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 1176 &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState; 1177 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 1178 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 1179 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 1180 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 1181 *pipelineLayout, // VkPipelineLayout layout; 1182 *renderPass, // VkRenderPass renderPass; 1183 0u, // deUint32 subpass; 1184 0u, // VkPipeline basePipelineHandle; 1185 0u // deInt32 basePipelineIndex; 1186 }; 1187 1188 graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 1189 } 1190 1191 // Create command pool 1192 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 1193 1194 // Create command buffer 1195 { 1196 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 1197 { 1198 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 1199 DE_NULL, // const void* pNext; 1200 0u, // VkCmdBufferOptimizeFlags flags; 1201 (const VkCommandBufferInheritanceInfo*)DE_NULL, 1202 }; 1203 1204 const VkRenderPassBeginInfo renderPassBeginInfo = 1205 { 1206 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 1207 DE_NULL, // const void* pNext; 1208 *renderPass, // VkRenderPass renderPass; 1209 *framebuffer, // VkFramebuffer framebuffer; 1210 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; 1211 (deUint32)attachmentClearValues.size(), // deUint32 attachmentCount; 1212 &attachmentClearValues[0] // const VkClearValue* pAttachmentClearValues; 1213 }; 1214 1215 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1216 1217 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 1218 1219 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 1220 0, (const VkMemoryBarrier*)DE_NULL, 1221 0, (const VkBufferMemoryBarrier*)DE_NULL, 1222 (deUint32)colorImagePreRenderBarriers.size(), colorImagePreRenderBarriers.empty() ? DE_NULL : &colorImagePreRenderBarriers[0]); 1223 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 1224 1225 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); 1226 1227 if (m_extraResourcesLayout != 0) 1228 { 1229 DE_ASSERT(extraResources != 0); 1230 const VkDescriptorSet descriptorSets[] = { *emptyDescriptorSet, extraResources }; 1231 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, DE_LENGTH_OF_ARRAY(descriptorSets), descriptorSets, 0u, DE_NULL); 1232 } 1233 else 1234 DE_ASSERT(extraResources == 0); 1235 1236 const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size(); 1237 1238 std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0); 1239 1240 std::vector<VkBuffer> buffers(numberOfVertexAttributes); 1241 for (size_t i = 0; i < numberOfVertexAttributes; i++) 1242 { 1243 buffers[i] = m_vertexBuffers[i].get()->get(); 1244 } 1245 1246 vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]); 1247 vk.cmdDraw(*cmdBuffer, (deUint32)positions.size(), 1u, 0u, 0u); 1248 1249 vk.cmdEndRenderPass(*cmdBuffer); 1250 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 1251 0, (const VkMemoryBarrier*)DE_NULL, 1252 0, (const VkBufferMemoryBarrier*)DE_NULL, 1253 (deUint32)colorImagePostRenderBarriers.size(), colorImagePostRenderBarriers.empty() ? DE_NULL : &colorImagePostRenderBarriers[0]); 1254 1255 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1256 } 1257 1258 // Create fence 1259 fence = createFence(vk, vkDevice); 1260 1261 // Execute Draw 1262 { 1263 1264 const VkSubmitInfo submitInfo = 1265 { 1266 VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType 1267 DE_NULL, // pNext 1268 0u, // waitSemaphoreCount 1269 DE_NULL, // pWaitSemaphores 1270 (const VkPipelineStageFlags*)DE_NULL, 1271 1u, // commandBufferCount 1272 &cmdBuffer.get(), // pCommandBuffers 1273 0u, // signalSemaphoreCount 1274 DE_NULL // pSignalSemaphores 1275 }; 1276 1277 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get())); 1278 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 1279 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), DE_TRUE, ~(0ull) /* infinity*/)); 1280 } 1281 1282 // Read back result and output 1283 { 1284 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(4 * sizeof(deUint32) * renderSize.x() * renderSize.y()); 1285 const VkBufferCreateInfo readImageBufferParams = 1286 { 1287 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1288 DE_NULL, // const void* pNext; 1289 0u, // VkBufferCreateFlags flags; 1290 imageSizeBytes, // VkDeviceSize size; 1291 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage; 1292 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1293 1u, // deUint32 queueFamilyCount; 1294 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 1295 }; 1296 1297 // constants for image copy 1298 Move<VkCommandPool> copyCmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 1299 1300 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 1301 { 1302 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 1303 DE_NULL, // const void* pNext; 1304 0u, // VkCmdBufferOptimizeFlags flags; 1305 (const VkCommandBufferInheritanceInfo*)DE_NULL, 1306 }; 1307 1308 const VkBufferImageCopy copyParams = 1309 { 1310 0u, // VkDeviceSize bufferOffset; 1311 (deUint32)renderSize.x(), // deUint32 bufferRowLength; 1312 (deUint32)renderSize.y(), // deUint32 bufferImageHeight; 1313 { 1314 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect; 1315 0u, // deUint32 mipLevel; 1316 0u, // deUint32 arraySlice; 1317 1u, // deUint32 arraySize; 1318 }, // VkImageSubresource imageSubresource; 1319 { 0u, 0u, 0u }, // VkOffset3D imageOffset; 1320 { renderSize.x(), renderSize.y(), 1u } // VkExtent3D imageExtent; 1321 }; 1322 1323 // Read back pixels. 1324 for (int outNdx = 0; outNdx < (int)m_shaderSpec.outputs.size(); ++outNdx) 1325 { 1326 const Symbol& output = m_shaderSpec.outputs[outNdx]; 1327 const int outSize = output.varType.getScalarSize(); 1328 const int outVecSize = glu::getDataTypeNumComponents(output.varType.getBasicType()); 1329 const int outNumLocs = glu::getDataTypeNumLocations(output.varType.getBasicType()); 1330 deUint32* dstPtrBase = static_cast<deUint32*>(outputs[outNdx]); 1331 const int outLocation = de::lookup(m_outputLayout.locationMap, output.name); 1332 1333 for (int locNdx = 0; locNdx < outNumLocs; ++locNdx) 1334 { 1335 tcu::TextureLevel tmpBuf; 1336 const tcu::TextureFormat format = getRenderbufferFormatForOutput(output.varType, false); 1337 const tcu::TextureFormat readFormat (tcu::TextureFormat::RGBA, format.type); 1338 const Unique<VkBuffer> readImageBuffer(createBuffer(vk, vkDevice, &readImageBufferParams)); 1339 const de::UniquePtr<Allocation> readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible)); 1340 1341 VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset())); 1342 1343 // Copy image to buffer 1344 { 1345 1346 Move<VkCommandBuffer> copyCmdBuffer = allocateCommandBuffer(vk, vkDevice, *copyCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1347 1348 const VkSubmitInfo submitInfo = 1349 { 1350 VK_STRUCTURE_TYPE_SUBMIT_INFO, 1351 DE_NULL, 1352 0u, 1353 (const VkSemaphore*)DE_NULL, 1354 (const VkPipelineStageFlags*)DE_NULL, 1355 1u, 1356 ©CmdBuffer.get(), 1357 0u, 1358 (const VkSemaphore*)DE_NULL, 1359 }; 1360 1361 VK_CHECK(vk.beginCommandBuffer(*copyCmdBuffer, &cmdBufferBeginInfo)); 1362 vk.cmdCopyImageToBuffer(*copyCmdBuffer, colorImages[outLocation + locNdx].get()->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params); 1363 VK_CHECK(vk.endCommandBuffer(*copyCmdBuffer)); 1364 1365 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get())); 1366 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 1367 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */)); 1368 } 1369 1370 const VkMappedMemoryRange range = 1371 { 1372 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 1373 DE_NULL, // const void* pNext; 1374 readImageBufferMemory->getMemory(), // VkDeviceMemory mem; 1375 0, // VkDeviceSize offset; 1376 imageSizeBytes, // VkDeviceSize size; 1377 }; 1378 1379 VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range)); 1380 1381 tmpBuf.setStorage(readFormat, renderSize.x(), renderSize.y()); 1382 1383 const tcu::TextureFormat resultFormat(tcu::TextureFormat::RGBA, format.type); 1384 const tcu::ConstPixelBufferAccess resultAccess(resultFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr()); 1385 1386 tcu::copy(tmpBuf.getAccess(), resultAccess); 1387 1388 if (outSize == 4 && outNumLocs == 1) 1389 deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues * outVecSize * sizeof(deUint32)); 1390 else 1391 { 1392 for (int valNdx = 0; valNdx < numValues; valNdx++) 1393 { 1394 const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx * 4; 1395 deUint32* dstPtr = &dstPtrBase[outSize * valNdx + outVecSize * locNdx]; 1396 deMemcpy(dstPtr, srcPtr, outVecSize * sizeof(deUint32)); 1397 } 1398 } 1399 } 1400 } 1401 } 1402 } 1403 1404 // VertexShaderExecutor 1405 1406 class VertexShaderExecutor : public FragmentOutExecutor 1407 { 1408 public: 1409 VertexShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 1410 virtual ~VertexShaderExecutor (void); 1411 1412 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& dst); 1413 }; 1414 1415 VertexShaderExecutor::VertexShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 1416 : FragmentOutExecutor(context, glu::SHADERTYPE_VERTEX, shaderSpec, extraResourcesLayout) 1417 { 1418 } 1419 1420 VertexShaderExecutor::~VertexShaderExecutor (void) 1421 { 1422 } 1423 1424 void VertexShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 1425 { 1426 const FragmentOutputLayout outputLayout (computeFragmentOutputLayout(shaderSpec.outputs)); 1427 1428 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShader(shaderSpec, "a_", "vtx_out_")) << shaderSpec.buildOptions; 1429 /* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */ 1430 programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, false, outputLayout.locationMap, "vtx_out_", "o_")) << shaderSpec.buildOptions; 1431 } 1432 1433 // GeometryShaderExecutor 1434 1435 class GeometryShaderExecutor : public FragmentOutExecutor 1436 { 1437 public: 1438 GeometryShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 1439 virtual ~GeometryShaderExecutor (void); 1440 1441 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection); 1442 1443 }; 1444 1445 GeometryShaderExecutor::GeometryShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 1446 : FragmentOutExecutor(context, glu::SHADERTYPE_GEOMETRY, shaderSpec, extraResourcesLayout) 1447 { 1448 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); 1449 1450 if (!features.geometryShader) 1451 TCU_THROW(NotSupportedError, "Geometry shader type not supported by device"); 1452 } 1453 1454 GeometryShaderExecutor::~GeometryShaderExecutor (void) 1455 { 1456 } 1457 1458 void GeometryShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 1459 { 1460 const FragmentOutputLayout outputLayout (computeFragmentOutputLayout(shaderSpec.outputs)); 1461 1462 programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(shaderSpec.inputs, "a_", "vtx_out_")) << shaderSpec.buildOptions; 1463 1464 programCollection.glslSources.add("geom") << glu::GeometrySource(generateGeometryShader(shaderSpec, "vtx_out_", "geom_out_")) << shaderSpec.buildOptions; 1465 1466 /* \todo [2015-09-18 rsipka] set useIntOutputs parameter if needed. */ 1467 programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, false, outputLayout.locationMap, "geom_out_", "o_")) << shaderSpec.buildOptions; 1468 1469 } 1470 1471 // FragmentShaderExecutor 1472 1473 class FragmentShaderExecutor : public FragmentOutExecutor 1474 { 1475 public: 1476 FragmentShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 1477 virtual ~FragmentShaderExecutor (void); 1478 1479 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection); 1480 1481 }; 1482 1483 FragmentShaderExecutor::FragmentShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 1484 : FragmentOutExecutor(context, glu::SHADERTYPE_FRAGMENT, shaderSpec, extraResourcesLayout) 1485 { 1486 } 1487 1488 FragmentShaderExecutor::~FragmentShaderExecutor (void) 1489 { 1490 } 1491 1492 void FragmentShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 1493 { 1494 const FragmentOutputLayout outputLayout (computeFragmentOutputLayout(shaderSpec.outputs)); 1495 1496 programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(shaderSpec.inputs, "a_", "vtx_out_")) << shaderSpec.buildOptions; 1497 /* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */ 1498 programCollection.glslSources.add("frag") << glu::FragmentSource(generateFragmentShader(shaderSpec, false, outputLayout.locationMap, "vtx_out_", "o_")) << shaderSpec.buildOptions; 1499 } 1500 1501 // Shared utilities for compute and tess executors 1502 1503 static deUint32 getVecStd430ByteAlignment (glu::DataType type) 1504 { 1505 switch (glu::getDataTypeScalarSize(type)) 1506 { 1507 case 1: return 4u; 1508 case 2: return 8u; 1509 case 3: return 16u; 1510 case 4: return 16u; 1511 default: 1512 DE_ASSERT(false); 1513 return 0u; 1514 } 1515 } 1516 1517 class BufferIoExecutor : public ShaderExecutor 1518 { 1519 public: 1520 BufferIoExecutor (Context& context, const ShaderSpec& shaderSpec); 1521 virtual ~BufferIoExecutor (void); 1522 1523 protected: 1524 enum 1525 { 1526 INPUT_BUFFER_BINDING = 0, 1527 OUTPUT_BUFFER_BINDING = 1, 1528 }; 1529 1530 void initBuffers (int numValues); 1531 VkBuffer getInputBuffer (void) const { return *m_inputBuffer; } 1532 VkBuffer getOutputBuffer (void) const { return *m_outputBuffer; } 1533 deUint32 getInputStride (void) const { return getLayoutStride(m_inputLayout); } 1534 deUint32 getOutputStride (void) const { return getLayoutStride(m_outputLayout); } 1535 1536 void uploadInputBuffer (const void* const* inputPtrs, int numValues); 1537 void readOutputBuffer (void* const* outputPtrs, int numValues); 1538 1539 static void declareBufferBlocks (std::ostream& src, const ShaderSpec& spec); 1540 static void generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName); 1541 1542 protected: 1543 Move<VkBuffer> m_inputBuffer; 1544 Move<VkBuffer> m_outputBuffer; 1545 1546 private: 1547 struct VarLayout 1548 { 1549 deUint32 offset; 1550 deUint32 stride; 1551 deUint32 matrixStride; 1552 1553 VarLayout (void) : offset(0), stride(0), matrixStride(0) {} 1554 }; 1555 1556 static void computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout); 1557 static deUint32 getLayoutStride (const vector<VarLayout>& layout); 1558 1559 static void copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 1560 static void copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr); 1561 1562 de::MovePtr<Allocation> m_inputAlloc; 1563 de::MovePtr<Allocation> m_outputAlloc; 1564 1565 vector<VarLayout> m_inputLayout; 1566 vector<VarLayout> m_outputLayout; 1567 }; 1568 1569 BufferIoExecutor::BufferIoExecutor (Context& context, const ShaderSpec& shaderSpec) 1570 : ShaderExecutor(context, shaderSpec) 1571 { 1572 computeVarLayout(m_shaderSpec.inputs, &m_inputLayout); 1573 computeVarLayout(m_shaderSpec.outputs, &m_outputLayout); 1574 } 1575 1576 BufferIoExecutor::~BufferIoExecutor (void) 1577 { 1578 } 1579 1580 inline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout) 1581 { 1582 return layout.empty() ? 0 : layout[0].stride; 1583 } 1584 1585 void BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout) 1586 { 1587 deUint32 maxAlignment = 0; 1588 deUint32 curOffset = 0; 1589 1590 DE_ASSERT(layout != DE_NULL); 1591 DE_ASSERT(layout->empty()); 1592 layout->resize(symbols.size()); 1593 1594 for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++) 1595 { 1596 const Symbol& symbol = symbols[varNdx]; 1597 const glu::DataType basicType = symbol.varType.getBasicType(); 1598 VarLayout& layoutEntry = (*layout)[varNdx]; 1599 1600 if (glu::isDataTypeScalarOrVector(basicType)) 1601 { 1602 const deUint32 alignment = getVecStd430ByteAlignment(basicType); 1603 const deUint32 size = (deUint32)glu::getDataTypeScalarSize(basicType) * (int)sizeof(deUint32); 1604 1605 curOffset = (deUint32)deAlign32((int)curOffset, (int)alignment); 1606 maxAlignment = de::max(maxAlignment, alignment); 1607 1608 layoutEntry.offset = curOffset; 1609 layoutEntry.matrixStride = 0; 1610 1611 curOffset += size; 1612 } 1613 else if (glu::isDataTypeMatrix(basicType)) 1614 { 1615 const int numVecs = glu::getDataTypeMatrixNumColumns(basicType); 1616 const glu::DataType vecType = glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType)); 1617 const deUint32 vecAlignment = getVecStd430ByteAlignment(vecType); 1618 1619 curOffset = (deUint32)deAlign32((int)curOffset, (int)vecAlignment); 1620 maxAlignment = de::max(maxAlignment, vecAlignment); 1621 1622 layoutEntry.offset = curOffset; 1623 layoutEntry.matrixStride = vecAlignment; 1624 1625 curOffset += vecAlignment*numVecs; 1626 } 1627 else 1628 DE_ASSERT(false); 1629 } 1630 1631 { 1632 const deUint32 totalSize = (deUint32)deAlign32(curOffset, maxAlignment); 1633 1634 for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter) 1635 varIter->stride = totalSize; 1636 } 1637 } 1638 1639 void BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec) 1640 { 1641 // Input struct 1642 if (!spec.inputs.empty()) 1643 { 1644 glu::StructType inputStruct("Inputs"); 1645 for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 1646 inputStruct.addMember(symIter->name.c_str(), symIter->varType); 1647 src << glu::declare(&inputStruct) << ";\n"; 1648 } 1649 1650 // Output struct 1651 { 1652 glu::StructType outputStruct("Outputs"); 1653 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1654 outputStruct.addMember(symIter->name.c_str(), symIter->varType); 1655 src << glu::declare(&outputStruct) << ";\n"; 1656 } 1657 1658 src << "\n"; 1659 1660 if (!spec.inputs.empty()) 1661 { 1662 src << "layout(set = 0, binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n" 1663 << "{\n" 1664 << " Inputs inputs[];\n" 1665 << "};\n"; 1666 } 1667 1668 src << "layout(set = 0, binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n" 1669 << "{\n" 1670 << " Outputs outputs[];\n" 1671 << "};\n" 1672 << "\n"; 1673 } 1674 1675 void BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName) 1676 { 1677 for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter) 1678 src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n"; 1679 1680 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1681 src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n"; 1682 1683 src << "\n"; 1684 1685 { 1686 std::istringstream opSrc (spec.source); 1687 std::string line; 1688 1689 while (std::getline(opSrc, line)) 1690 src << "\t" << line << "\n"; 1691 } 1692 1693 src << "\n"; 1694 for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter) 1695 src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n"; 1696 } 1697 1698 void BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 1699 { 1700 if (varType.isBasicType()) 1701 { 1702 const glu::DataType basicType = varType.getBasicType(); 1703 const bool isMatrix = glu::isDataTypeMatrix(basicType); 1704 const int scalarSize = glu::getDataTypeScalarSize(basicType); 1705 const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 1706 const int numComps = scalarSize / numVecs; 1707 1708 for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 1709 { 1710 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 1711 { 1712 const int srcOffset = (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps); 1713 const int dstOffset = layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0); 1714 const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 1715 deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 1716 1717 deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps); 1718 } 1719 } 1720 } 1721 else 1722 throw tcu::InternalError("Unsupported type"); 1723 } 1724 1725 void BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr) 1726 { 1727 if (varType.isBasicType()) 1728 { 1729 const glu::DataType basicType = varType.getBasicType(); 1730 const bool isMatrix = glu::isDataTypeMatrix(basicType); 1731 const int scalarSize = glu::getDataTypeScalarSize(basicType); 1732 const int numVecs = isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1; 1733 const int numComps = scalarSize / numVecs; 1734 1735 for (int elemNdx = 0; elemNdx < numValues; elemNdx++) 1736 { 1737 for (int vecNdx = 0; vecNdx < numVecs; vecNdx++) 1738 { 1739 const int srcOffset = layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0); 1740 const int dstOffset = (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps); 1741 const deUint8* srcPtr = (const deUint8*)srcBasePtr + srcOffset; 1742 deUint8* dstPtr = (deUint8*)dstBasePtr + dstOffset; 1743 1744 deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps); 1745 } 1746 } 1747 } 1748 else 1749 throw tcu::InternalError("Unsupported type"); 1750 } 1751 1752 void BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues) 1753 { 1754 const VkDevice vkDevice = m_context.getDevice(); 1755 const DeviceInterface& vk = m_context.getDeviceInterface(); 1756 1757 const deUint32 inputStride = getLayoutStride(m_inputLayout); 1758 const int inputBufferSize = inputStride * numValues; 1759 1760 if (inputBufferSize == 0) 1761 return; // No inputs 1762 1763 DE_ASSERT(m_shaderSpec.inputs.size() == m_inputLayout.size()); 1764 for (size_t inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx) 1765 { 1766 const glu::VarType& varType = m_shaderSpec.inputs[inputNdx].varType; 1767 const VarLayout& layout = m_inputLayout[inputNdx]; 1768 1769 copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], m_inputAlloc->getHostPtr()); 1770 } 1771 1772 flushMappedMemoryRange(vk, vkDevice, m_inputAlloc->getMemory(), m_inputAlloc->getOffset(), inputBufferSize); 1773 } 1774 1775 void BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues) 1776 { 1777 const VkDevice vkDevice = m_context.getDevice(); 1778 const DeviceInterface& vk = m_context.getDeviceInterface(); 1779 1780 const deUint32 outputStride = getLayoutStride(m_outputLayout); 1781 const int outputBufferSize = numValues * outputStride; 1782 1783 DE_ASSERT(outputBufferSize > 0); // At least some outputs are required. 1784 1785 invalidateMappedMemoryRange(vk, vkDevice, m_outputAlloc->getMemory(), m_outputAlloc->getOffset(), outputBufferSize); 1786 1787 DE_ASSERT(m_shaderSpec.outputs.size() == m_outputLayout.size()); 1788 for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx) 1789 { 1790 const glu::VarType& varType = m_shaderSpec.outputs[outputNdx].varType; 1791 const VarLayout& layout = m_outputLayout[outputNdx]; 1792 1793 copyFromBuffer(varType, layout, numValues, m_outputAlloc->getHostPtr(), outputPtrs[outputNdx]); 1794 } 1795 } 1796 1797 void BufferIoExecutor::initBuffers (int numValues) 1798 { 1799 const deUint32 inputStride = getLayoutStride(m_inputLayout); 1800 const deUint32 outputStride = getLayoutStride(m_outputLayout); 1801 // Avoid creating zero-sized buffer/memory 1802 const size_t inputBufferSize = de::max(numValues * inputStride, 1u); 1803 const size_t outputBufferSize = numValues * outputStride; 1804 1805 // Upload data to buffer 1806 const VkDevice vkDevice = m_context.getDevice(); 1807 const DeviceInterface& vk = m_context.getDeviceInterface(); 1808 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1809 Allocator& memAlloc = m_context.getDefaultAllocator(); 1810 1811 const VkBufferCreateInfo inputBufferParams = 1812 { 1813 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1814 DE_NULL, // const void* pNext; 1815 0u, // VkBufferCreateFlags flags; 1816 inputBufferSize, // VkDeviceSize size; 1817 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage; 1818 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1819 1u, // deUint32 queueFamilyCount; 1820 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 1821 }; 1822 1823 m_inputBuffer = createBuffer(vk, vkDevice, &inputBufferParams); 1824 m_inputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_inputBuffer), MemoryRequirement::HostVisible); 1825 1826 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_inputBuffer, m_inputAlloc->getMemory(), m_inputAlloc->getOffset())); 1827 1828 const VkBufferCreateInfo outputBufferParams = 1829 { 1830 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1831 DE_NULL, // const void* pNext; 1832 0u, // VkBufferCreateFlags flags; 1833 outputBufferSize, // VkDeviceSize size; 1834 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage; 1835 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1836 1u, // deUint32 queueFamilyCount; 1837 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 1838 }; 1839 1840 m_outputBuffer = createBuffer(vk, vkDevice, &outputBufferParams); 1841 m_outputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outputBuffer), MemoryRequirement::HostVisible); 1842 1843 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outputBuffer, m_outputAlloc->getMemory(), m_outputAlloc->getOffset())); 1844 } 1845 1846 // ComputeShaderExecutor 1847 1848 class ComputeShaderExecutor : public BufferIoExecutor 1849 { 1850 public: 1851 ComputeShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 1852 virtual ~ComputeShaderExecutor (void); 1853 1854 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection); 1855 1856 virtual void execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources); 1857 1858 protected: 1859 static std::string generateComputeShader (const ShaderSpec& spec); 1860 1861 private: 1862 const VkDescriptorSetLayout m_extraResourcesLayout; 1863 }; 1864 1865 ComputeShaderExecutor::ComputeShaderExecutor(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 1866 : BufferIoExecutor (context, shaderSpec) 1867 , m_extraResourcesLayout (extraResourcesLayout) 1868 { 1869 } 1870 1871 ComputeShaderExecutor::~ComputeShaderExecutor (void) 1872 { 1873 } 1874 1875 std::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec) 1876 { 1877 std::ostringstream src; 1878 src << glu::getGLSLVersionDeclaration(spec.glslVersion) << "\n"; 1879 1880 if (!spec.globalDeclarations.empty()) 1881 src << spec.globalDeclarations << "\n"; 1882 1883 src << "layout(local_size_x = 1) in;\n" 1884 << "\n"; 1885 1886 declareBufferBlocks(src, spec); 1887 1888 src << "void main (void)\n" 1889 << "{\n" 1890 << " uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n" 1891 << " + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"; 1892 1893 generateExecBufferIo(src, spec, "invocationNdx"); 1894 1895 src << "}\n"; 1896 1897 return src.str(); 1898 } 1899 1900 void ComputeShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 1901 { 1902 programCollection.glslSources.add("compute") << glu::ComputeSource(generateComputeShader(shaderSpec)) << shaderSpec.buildOptions; 1903 } 1904 1905 void ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources) 1906 { 1907 const VkDevice vkDevice = m_context.getDevice(); 1908 const DeviceInterface& vk = m_context.getDeviceInterface(); 1909 const VkQueue queue = m_context.getUniversalQueue(); 1910 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1911 1912 DescriptorPoolBuilder descriptorPoolBuilder; 1913 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder; 1914 1915 Move<VkShaderModule> computeShaderModule; 1916 Move<VkPipeline> computePipeline; 1917 Move<VkPipelineLayout> pipelineLayout; 1918 Move<VkCommandPool> cmdPool; 1919 Move<VkDescriptorPool> descriptorPool; 1920 Move<VkDescriptorSetLayout> descriptorSetLayout; 1921 Move<VkDescriptorSet> descriptorSet; 1922 const deUint32 numDescriptorSets = (m_extraResourcesLayout != 0) ? 2u : 1u; 1923 Move<VkFence> fence; 1924 1925 DE_ASSERT((m_extraResourcesLayout != 0) == (extraResources != 0)); 1926 1927 initBuffers(numValues); 1928 1929 // Setup input buffer & copy data 1930 uploadInputBuffer(inputs, numValues); 1931 1932 // Create command pool 1933 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 1934 1935 // Create command buffer 1936 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 1937 { 1938 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 1939 DE_NULL, // const void* pNext; 1940 0u, // VkCmdBufferOptimizeFlags flags; 1941 (const VkCommandBufferInheritanceInfo*)DE_NULL, 1942 }; 1943 1944 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); 1945 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1946 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT); 1947 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 1948 1949 descriptorSetLayout = descriptorSetLayoutBuilder.build(vk, vkDevice); 1950 descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1951 1952 const VkDescriptorSetAllocateInfo allocInfo = 1953 { 1954 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1955 DE_NULL, 1956 *descriptorPool, 1957 1u, 1958 &*descriptorSetLayout 1959 }; 1960 1961 descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo); 1962 1963 // Create pipeline layout 1964 { 1965 const VkDescriptorSetLayout descriptorSetLayouts[] = 1966 { 1967 *descriptorSetLayout, 1968 m_extraResourcesLayout 1969 }; 1970 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 1971 { 1972 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 1973 DE_NULL, // const void* pNext; 1974 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 1975 numDescriptorSets, // deUint32 CdescriptorSetCount; 1976 descriptorSetLayouts, // const VkDescriptorSetLayout* pSetLayouts; 1977 0u, // deUint32 pushConstantRangeCount; 1978 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 1979 }; 1980 1981 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 1982 } 1983 1984 // Create shaders 1985 { 1986 computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0); 1987 } 1988 1989 // create pipeline 1990 { 1991 const VkPipelineShaderStageCreateInfo shaderStageParams[1] = 1992 { 1993 { 1994 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1995 DE_NULL, // const void* pNext; 1996 (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags; 1997 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagsBit stage; 1998 *computeShaderModule, // VkShaderModule shader; 1999 "main", // const char* pName; 2000 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 2001 } 2002 }; 2003 2004 const VkComputePipelineCreateInfo computePipelineParams = 2005 { 2006 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; 2007 DE_NULL, // const void* pNext; 2008 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 2009 *shaderStageParams, // VkPipelineShaderStageCreateInfo cs; 2010 *pipelineLayout, // VkPipelineLayout layout; 2011 0u, // VkPipeline basePipelineHandle; 2012 0u, // int32_t basePipelineIndex; 2013 }; 2014 2015 computePipeline = createComputePipeline(vk, vkDevice, DE_NULL, &computePipelineParams); 2016 } 2017 2018 // Create fence 2019 fence = createFence(vk, vkDevice); 2020 2021 const int maxValuesPerInvocation = m_context.getDeviceProperties().limits.maxComputeWorkGroupSize[0]; 2022 int curOffset = 0; 2023 const deUint32 inputStride = getInputStride(); 2024 const deUint32 outputStride = getOutputStride(); 2025 2026 while (curOffset < numValues) 2027 { 2028 Move<VkCommandBuffer> cmdBuffer; 2029 const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset); 2030 2031 // Update descriptors 2032 { 2033 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder; 2034 2035 const VkDescriptorBufferInfo outputDescriptorBufferInfo = 2036 { 2037 *m_outputBuffer, // VkBuffer buffer; 2038 curOffset * outputStride, // VkDeviceSize offset; 2039 numToExec * outputStride // VkDeviceSize range; 2040 }; 2041 2042 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo); 2043 2044 if (inputStride) 2045 { 2046 const VkDescriptorBufferInfo inputDescriptorBufferInfo = 2047 { 2048 *m_inputBuffer, // VkBuffer buffer; 2049 curOffset * inputStride, // VkDeviceSize offset; 2050 numToExec * inputStride // VkDeviceSize range; 2051 }; 2052 2053 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo); 2054 } 2055 2056 descriptorSetUpdateBuilder.update(vk, vkDevice); 2057 } 2058 2059 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 2060 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 2061 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline); 2062 2063 { 2064 const VkDescriptorSet descriptorSets[] = { *descriptorSet, extraResources }; 2065 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, numDescriptorSets, descriptorSets, 0u, DE_NULL); 2066 } 2067 2068 vk.cmdDispatch(*cmdBuffer, numToExec, 1, 1); 2069 2070 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 2071 2072 curOffset += numToExec; 2073 2074 // Execute 2075 { 2076 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get())); 2077 2078 const VkSubmitInfo submitInfo = 2079 { 2080 VK_STRUCTURE_TYPE_SUBMIT_INFO, 2081 DE_NULL, 2082 0u, 2083 (const VkSemaphore*)DE_NULL, 2084 (const VkPipelineStageFlags*)DE_NULL, 2085 1u, 2086 &cmdBuffer.get(), 2087 0u, 2088 (const VkSemaphore*)DE_NULL, 2089 }; 2090 2091 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 2092 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/)); 2093 } 2094 } 2095 2096 // Read back data 2097 readOutputBuffer(outputs, numValues); 2098 } 2099 2100 // Tessellation utils 2101 2102 static std::string generateVertexShaderForTess (void) 2103 { 2104 std::ostringstream src; 2105 src << "#version 310 es\n" 2106 << "void main (void)\n{\n" 2107 << " gl_Position = vec4(gl_VertexIndex/2, gl_VertexIndex%2, 0.0, 1.0);\n" 2108 << "}\n"; 2109 2110 return src.str(); 2111 } 2112 2113 class TessellationExecutor : public BufferIoExecutor 2114 { 2115 public: 2116 TessellationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 2117 virtual ~TessellationExecutor (void); 2118 2119 void renderTess (deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints, VkDescriptorSet extraResources); 2120 2121 private: 2122 const VkDescriptorSetLayout m_extraResourcesLayout; 2123 }; 2124 2125 TessellationExecutor::TessellationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 2126 : BufferIoExecutor (context, shaderSpec) 2127 , m_extraResourcesLayout (extraResourcesLayout) 2128 { 2129 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures(); 2130 2131 if (!features.tessellationShader) 2132 TCU_THROW(NotSupportedError, "Tessellation shader is not supported by device"); 2133 } 2134 2135 TessellationExecutor::~TessellationExecutor (void) 2136 { 2137 } 2138 2139 void TessellationExecutor::renderTess (deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints, VkDescriptorSet extraResources) 2140 { 2141 const size_t inputBufferSize = numValues * getInputStride(); 2142 const VkDevice vkDevice = m_context.getDevice(); 2143 const DeviceInterface& vk = m_context.getDeviceInterface(); 2144 const VkQueue queue = m_context.getUniversalQueue(); 2145 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 2146 Allocator& memAlloc = m_context.getDefaultAllocator(); 2147 2148 const tcu::UVec2 renderSize (DEFAULT_RENDER_WIDTH, DEFAULT_RENDER_HEIGHT); 2149 2150 Move<VkImage> colorImage; 2151 de::MovePtr<Allocation> colorImageAlloc; 2152 VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 2153 Move<VkImageView> colorImageView; 2154 2155 Move<VkRenderPass> renderPass; 2156 Move<VkFramebuffer> framebuffer; 2157 Move<VkPipelineLayout> pipelineLayout; 2158 Move<VkPipeline> graphicsPipeline; 2159 2160 Move<VkShaderModule> vertexShaderModule; 2161 Move<VkShaderModule> tessControlShaderModule; 2162 Move<VkShaderModule> tessEvalShaderModule; 2163 Move<VkShaderModule> fragmentShaderModule; 2164 2165 Move<VkCommandPool> cmdPool; 2166 Move<VkCommandBuffer> cmdBuffer; 2167 2168 Move<VkFence> fence; 2169 2170 Move<VkDescriptorPool> descriptorPool; 2171 Move<VkDescriptorSetLayout> descriptorSetLayout; 2172 Move<VkDescriptorSet> descriptorSet; 2173 const deUint32 numDescriptorSets = (m_extraResourcesLayout != 0) ? 2u : 1u; 2174 2175 DE_ASSERT((m_extraResourcesLayout != 0) == (extraResources != 0)); 2176 2177 // Create color image 2178 { 2179 const VkImageCreateInfo colorImageParams = 2180 { 2181 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 2182 DE_NULL, // const void* pNext; 2183 0u, // VkImageCreateFlags flags; 2184 VK_IMAGE_TYPE_2D, // VkImageType imageType; 2185 colorFormat, // VkFormat format; 2186 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent; 2187 1u, // deUint32 mipLevels; 2188 1u, // deUint32 arraySize; 2189 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 2190 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 2191 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 2192 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 2193 1u, // deUint32 queueFamilyCount; 2194 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 2195 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 2196 }; 2197 2198 colorImage = createImage(vk, vkDevice, &colorImageParams); 2199 2200 // Allocate and bind color image memory 2201 colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any); 2202 VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset())); 2203 } 2204 2205 // Create color attachment view 2206 { 2207 const VkImageViewCreateInfo colorImageViewParams = 2208 { 2209 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 2210 DE_NULL, // const void* pNext; 2211 0u, // VkImageViewCreateFlags flags; 2212 *colorImage, // VkImage image; 2213 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 2214 colorFormat, // VkFormat format; 2215 { 2216 VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle r; 2217 VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle g; 2218 VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle b; 2219 VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle a; 2220 }, // VkComponentsMapping components; 2221 { 2222 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 2223 0u, // deUint32 baseMipLevel; 2224 1u, // deUint32 mipLevels; 2225 0u, // deUint32 baseArraylayer; 2226 1u // deUint32 layerCount; 2227 } // VkImageSubresourceRange subresourceRange; 2228 }; 2229 2230 colorImageView = createImageView(vk, vkDevice, &colorImageViewParams); 2231 } 2232 2233 // Create render pass 2234 { 2235 const VkAttachmentDescription colorAttachmentDescription = 2236 { 2237 0u, // VkAttachmentDescriptorFlags flags; 2238 colorFormat, // VkFormat format; 2239 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 2240 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 2241 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 2242 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 2243 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 2244 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 2245 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout 2246 }; 2247 2248 const VkAttachmentDescription attachments[1] = 2249 { 2250 colorAttachmentDescription 2251 }; 2252 2253 const VkAttachmentReference colorAttachmentReference = 2254 { 2255 0u, // deUint32 attachment; 2256 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 2257 }; 2258 2259 const VkSubpassDescription subpassDescription = 2260 { 2261 0u, // VkSubpassDescriptionFlags flags; 2262 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 2263 0u, // deUint32 inputCount; 2264 DE_NULL, // const VkAttachmentReference* pInputAttachments; 2265 1u, // deUint32 colorCount; 2266 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 2267 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 2268 DE_NULL, // VkAttachmentReference depthStencilAttachment; 2269 0u, // deUint32 preserveCount; 2270 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 2271 }; 2272 2273 const VkRenderPassCreateInfo renderPassParams = 2274 { 2275 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 2276 DE_NULL, // const void* pNext; 2277 0u, // VkRenderPassCreateFlags flags; 2278 1u, // deUint32 attachmentCount; 2279 attachments, // const VkAttachmentDescription* pAttachments; 2280 1u, // deUint32 subpassCount; 2281 &subpassDescription, // const VkSubpassDescription* pSubpasses; 2282 0u, // deUint32 dependencyCount; 2283 DE_NULL // const VkSubpassDependency* pDependencies; 2284 }; 2285 2286 renderPass = createRenderPass(vk, vkDevice, &renderPassParams); 2287 } 2288 2289 // Create framebuffer 2290 { 2291 const VkFramebufferCreateInfo framebufferParams = 2292 { 2293 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 2294 DE_NULL, // const void* pNext; 2295 0u, // VkFramebufferCreateFlags flags; 2296 *renderPass, // VkRenderPass renderPass; 2297 1u, // deUint32 attachmentCount; 2298 &*colorImageView, // const VkAttachmentBindInfo* pAttachments; 2299 (deUint32)renderSize.x(), // deUint32 width; 2300 (deUint32)renderSize.y(), // deUint32 height; 2301 1u // deUint32 layers; 2302 }; 2303 2304 framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 2305 } 2306 2307 // Create descriptors 2308 { 2309 DescriptorPoolBuilder descriptorPoolBuilder; 2310 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder; 2311 2312 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL); 2313 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 2314 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL); 2315 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 2316 2317 descriptorSetLayout = descriptorSetLayoutBuilder.build(vk, vkDevice); 2318 descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 2319 2320 const VkDescriptorSetAllocateInfo allocInfo = 2321 { 2322 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 2323 DE_NULL, 2324 *descriptorPool, 2325 1u, 2326 &*descriptorSetLayout 2327 }; 2328 2329 descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo); 2330 // Update descriptors 2331 { 2332 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder; 2333 const VkDescriptorBufferInfo outputDescriptorBufferInfo = 2334 { 2335 *m_outputBuffer, // VkBuffer buffer; 2336 0u, // VkDeviceSize offset; 2337 VK_WHOLE_SIZE // VkDeviceSize range; 2338 }; 2339 2340 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo); 2341 2342 VkDescriptorBufferInfo inputDescriptorBufferInfo = 2343 { 2344 0, // VkBuffer buffer; 2345 0u, // VkDeviceSize offset; 2346 VK_WHOLE_SIZE // VkDeviceSize range; 2347 }; 2348 2349 if (inputBufferSize > 0) 2350 { 2351 inputDescriptorBufferInfo.buffer = *m_inputBuffer; 2352 2353 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo); 2354 } 2355 2356 descriptorSetUpdateBuilder.update(vk, vkDevice); 2357 } 2358 } 2359 2360 // Create pipeline layout 2361 { 2362 const VkDescriptorSetLayout descriptorSetLayouts[] = 2363 { 2364 *descriptorSetLayout, 2365 m_extraResourcesLayout 2366 }; 2367 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 2368 { 2369 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 2370 DE_NULL, // const void* pNext; 2371 (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; 2372 numDescriptorSets, // deUint32 descriptorSetCount; 2373 descriptorSetLayouts, // const VkDescriptorSetLayout* pSetLayouts; 2374 0u, // deUint32 pushConstantRangeCount; 2375 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 2376 }; 2377 2378 pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 2379 } 2380 2381 // Create shader modules 2382 { 2383 vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0); 2384 tessControlShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tess_control"), 0); 2385 tessEvalShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tess_eval"), 0); 2386 fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0); 2387 } 2388 2389 // Create pipeline 2390 { 2391 const VkPipelineShaderStageCreateInfo shaderStageParams[4] = 2392 { 2393 { 2394 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 2395 DE_NULL, // const void* pNext; 2396 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 2397 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBit stage; 2398 *vertexShaderModule, // VkShaderModule shader; 2399 "main", // const char* pName; 2400 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 2401 }, 2402 { 2403 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 2404 DE_NULL, // const void* pNext; 2405 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 2406 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBit stage; 2407 *tessControlShaderModule, // VkShaderModule shader; 2408 "main", // const char* pName; 2409 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 2410 }, 2411 { 2412 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 2413 DE_NULL, // const void* pNext; 2414 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 2415 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, // VkShaderStageFlagBit stage; 2416 *tessEvalShaderModule, // VkShaderModule shader; 2417 "main", // const char* pName; 2418 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 2419 }, 2420 { 2421 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 2422 DE_NULL, // const void* pNext; 2423 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 2424 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBit stage; 2425 *fragmentShaderModule, // VkShaderModule shader; 2426 "main", // const char* pName; 2427 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 2428 } 2429 }; 2430 2431 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 2432 { 2433 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 2434 DE_NULL, // const void* pNext; 2435 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 2436 0u, // deUint32 bindingCount; 2437 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 2438 0u, // deUint32 attributeCount; 2439 DE_NULL, // const VkVertexInputAttributeDescription* pvertexAttributeDescriptions; 2440 }; 2441 2442 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 2443 { 2444 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 2445 DE_NULL, // const void* pNext; 2446 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 2447 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, // VkPrimitiveTopology topology; 2448 DE_FALSE // VkBool32 primitiveRestartEnable; 2449 }; 2450 2451 struct VkPipelineTessellationStateCreateInfo tessellationStateParams = 2452 { 2453 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType; 2454 DE_NULL, // const void* pNext; 2455 (VkPipelineTessellationStateCreateFlags)0, // VkPipelineTessellationStateCreateFlags flags; 2456 patchControlPoints // uint32_t patchControlPoints; 2457 }; 2458 2459 const VkViewport viewport = 2460 { 2461 0.0f, // float originX; 2462 0.0f, // float originY; 2463 (float)renderSize.x(), // float width; 2464 (float)renderSize.y(), // float height; 2465 0.0f, // float minDepth; 2466 1.0f // float maxDepth; 2467 }; 2468 2469 const VkRect2D scissor = 2470 { 2471 { 2472 0u, // deUint32 x; 2473 0u, // deUint32 y; 2474 }, // VkOffset2D offset; 2475 { 2476 renderSize.x(), // deUint32 width; 2477 renderSize.y(), // deUint32 height; 2478 }, // VkExtent2D extent; 2479 }; 2480 2481 const VkPipelineViewportStateCreateInfo viewportStateParams = 2482 { 2483 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 2484 DE_NULL, // const void* pNext; 2485 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewPortStateCreateFlags flags; 2486 1u, // deUint32 viewportCount; 2487 &viewport, // const VkViewport* pViewports; 2488 1u, // deUint32 scissorsCount; 2489 &scissor // const VkRect2D* pScissors; 2490 }; 2491 2492 const VkPipelineRasterizationStateCreateInfo rasterStateParams = 2493 { 2494 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 2495 DE_NULL, // const void* pNext; 2496 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStageCreateFlags flags; 2497 VK_FALSE, // VkBool32 depthClipEnable; 2498 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 2499 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 2500 VK_CULL_MODE_NONE, // VkCullMode cullMode; 2501 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 2502 VK_FALSE, // VkBool32 depthBiasEnable; 2503 0.0f, // float depthBias; 2504 0.0f, // float depthBiasClamp; 2505 0.0f, // float slopeScaledDepthBias; 2506 1.0f // float lineWidth; 2507 }; 2508 2509 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 2510 { 2511 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 2512 DE_NULL, // const void* pNext; 2513 0u, // VkPipelineMultisampleStateCreateFlags flags; 2514 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 2515 VK_FALSE, // VkBool32 sampleShadingEnable; 2516 0.0f, // float minSampleShading; 2517 DE_NULL, // const VkSampleMask* pSampleMask; 2518 VK_FALSE, // VkBool32 alphaToCoverageEnable; 2519 VK_FALSE // VkBool32 alphaToOneEnable; 2520 }; 2521 2522 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 2523 { 2524 VK_FALSE, // VkBool32 blendEnable; 2525 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcBlendColor; 2526 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destBlendColor; 2527 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor; 2528 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcBlendAlpha; 2529 VK_BLEND_FACTOR_ZERO, // VkBlendFactor destBlendAlpha; 2530 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha; 2531 (VK_COLOR_COMPONENT_R_BIT | 2532 VK_COLOR_COMPONENT_G_BIT | 2533 VK_COLOR_COMPONENT_B_BIT | 2534 VK_COLOR_COMPONENT_A_BIT) // VkColorComponentFlags colorWriteMask; 2535 }; 2536 2537 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 2538 { 2539 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 2540 DE_NULL, // const void* pNext; 2541 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags 2542 VK_FALSE, // VkBool32 logicOpEnable; 2543 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 2544 1u, // deUint32 attachmentCount; 2545 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 2546 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConst[4]; 2547 }; 2548 2549 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 2550 { 2551 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 2552 DE_NULL, // const void* pNext; 2553 0u, // VkPipelineCreateFlags flags; 2554 4u, // deUint32 stageCount; 2555 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages; 2556 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 2557 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 2558 &tessellationStateParams, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 2559 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 2560 &rasterStateParams, // const VkPipelineRasterStateCreateInfo* pRasterState; 2561 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 2562 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 2563 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 2564 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 2565 *pipelineLayout, // VkPipelineLayout layout; 2566 *renderPass, // VkRenderPass renderPass; 2567 0u, // deUint32 subpass; 2568 0u, // VkPipeline basePipelineHandle; 2569 0u // deInt32 basePipelineIndex; 2570 }; 2571 2572 graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 2573 } 2574 2575 // Create command pool 2576 cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 2577 2578 // Create command buffer 2579 { 2580 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 2581 { 2582 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 2583 DE_NULL, // const void* pNext; 2584 0u, // VkCmdBufferOptimizeFlags flags; 2585 (const VkCommandBufferInheritanceInfo*)DE_NULL, 2586 }; 2587 2588 const VkClearValue clearValues[1] = 2589 { 2590 getDefaultClearColor() 2591 }; 2592 2593 const VkRenderPassBeginInfo renderPassBeginInfo = 2594 { 2595 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 2596 DE_NULL, // const void* pNext; 2597 *renderPass, // VkRenderPass renderPass; 2598 *framebuffer, // VkFramebuffer framebuffer; 2599 { { 0, 0 }, { renderSize.x(), renderSize.y() } }, // VkRect2D renderArea; 2600 1, // deUint32 attachmentCount; 2601 clearValues // const VkClearValue* pClearValues; 2602 }; 2603 2604 cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 2605 2606 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); 2607 2608 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 2609 2610 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline); 2611 2612 { 2613 const VkDescriptorSet descriptorSets[] = { *descriptorSet, extraResources }; 2614 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, numDescriptorSets, descriptorSets, 0u, DE_NULL); 2615 } 2616 2617 vk.cmdDraw(*cmdBuffer, vertexCount, 1, 0, 0); 2618 2619 vk.cmdEndRenderPass(*cmdBuffer); 2620 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 2621 } 2622 2623 // Create fence 2624 fence = createFence(vk, vkDevice); 2625 2626 // Execute Draw 2627 { 2628 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get())); 2629 const VkSubmitInfo submitInfo = 2630 { 2631 VK_STRUCTURE_TYPE_SUBMIT_INFO, 2632 DE_NULL, 2633 0u, 2634 (const VkSemaphore*)0, 2635 (const VkPipelineStageFlags*)DE_NULL, 2636 1u, 2637 &cmdBuffer.get(), 2638 0u, 2639 (const VkSemaphore*)0, 2640 }; 2641 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence)); 2642 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/)); 2643 } 2644 } 2645 2646 // TessControlExecutor 2647 2648 class TessControlExecutor : public TessellationExecutor 2649 { 2650 public: 2651 TessControlExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 2652 virtual ~TessControlExecutor (void); 2653 2654 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection); 2655 2656 virtual void execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources); 2657 2658 protected: 2659 static std::string generateTessControlShader (const ShaderSpec& shaderSpec); 2660 }; 2661 2662 TessControlExecutor::TessControlExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 2663 : TessellationExecutor(context, shaderSpec, extraResourcesLayout) 2664 { 2665 } 2666 2667 TessControlExecutor::~TessControlExecutor (void) 2668 { 2669 } 2670 2671 std::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec) 2672 { 2673 std::ostringstream src; 2674 src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n"; 2675 2676 if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES) 2677 src << "#extension GL_EXT_tessellation_shader : require\n\n"; 2678 2679 if (!shaderSpec.globalDeclarations.empty()) 2680 src << shaderSpec.globalDeclarations << "\n"; 2681 2682 src << "\nlayout(vertices = 1) out;\n\n"; 2683 2684 declareBufferBlocks(src, shaderSpec); 2685 2686 src << "void main (void)\n{\n"; 2687 2688 for (int ndx = 0; ndx < 2; ndx++) 2689 src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 2690 2691 for (int ndx = 0; ndx < 4; ndx++) 2692 src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 2693 2694 src << "\n" 2695 << "\thighp uint invocationId = uint(gl_PrimitiveID);\n"; 2696 2697 generateExecBufferIo(src, shaderSpec, "invocationId"); 2698 2699 src << "}\n"; 2700 2701 return src.str(); 2702 } 2703 2704 static std::string generateEmptyTessEvalShader () 2705 { 2706 std::ostringstream src; 2707 2708 src << "#version 310 es\n" 2709 "#extension GL_EXT_tessellation_shader : require\n\n"; 2710 2711 src << "layout(triangles, ccw) in;\n"; 2712 2713 src << "\nvoid main (void)\n{\n" 2714 << "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n" 2715 << "}\n"; 2716 2717 return src.str(); 2718 } 2719 2720 void TessControlExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 2721 { 2722 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess()) << shaderSpec.buildOptions; 2723 programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generateTessControlShader(shaderSpec)) << shaderSpec.buildOptions; 2724 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateEmptyTessEvalShader()) << shaderSpec.buildOptions; 2725 programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource()) << shaderSpec.buildOptions; 2726 } 2727 2728 void TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources) 2729 { 2730 const deUint32 patchSize = 3; 2731 2732 initBuffers(numValues); 2733 2734 // Setup input buffer & copy data 2735 uploadInputBuffer(inputs, numValues); 2736 2737 renderTess(numValues, patchSize * numValues, patchSize, extraResources); 2738 2739 // Read back data 2740 readOutputBuffer(outputs, numValues); 2741 } 2742 2743 // TessEvaluationExecutor 2744 2745 class TessEvaluationExecutor : public TessellationExecutor 2746 { 2747 public: 2748 TessEvaluationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout); 2749 virtual ~TessEvaluationExecutor (void); 2750 2751 static void generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection); 2752 2753 virtual void execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources); 2754 2755 protected: 2756 static std::string generateTessEvalShader (const ShaderSpec& shaderSpec); 2757 }; 2758 2759 TessEvaluationExecutor::TessEvaluationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 2760 : TessellationExecutor (context, shaderSpec, extraResourcesLayout) 2761 { 2762 } 2763 2764 TessEvaluationExecutor::~TessEvaluationExecutor (void) 2765 { 2766 } 2767 2768 static std::string generatePassthroughTessControlShader (void) 2769 { 2770 std::ostringstream src; 2771 2772 src << "#version 310 es\n" 2773 "#extension GL_EXT_tessellation_shader : require\n\n"; 2774 2775 src << "layout(vertices = 1) out;\n\n"; 2776 2777 src << "void main (void)\n{\n"; 2778 2779 for (int ndx = 0; ndx < 2; ndx++) 2780 src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n"; 2781 2782 for (int ndx = 0; ndx < 4; ndx++) 2783 src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n"; 2784 2785 src << "}\n"; 2786 2787 return src.str(); 2788 } 2789 2790 std::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec) 2791 { 2792 std::ostringstream src; 2793 2794 src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n"; 2795 2796 if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES) 2797 src << "#extension GL_EXT_tessellation_shader : require\n\n"; 2798 2799 if (!shaderSpec.globalDeclarations.empty()) 2800 src << shaderSpec.globalDeclarations << "\n"; 2801 2802 src << "\n"; 2803 2804 src << "layout(isolines, equal_spacing) in;\n\n"; 2805 2806 declareBufferBlocks(src, shaderSpec); 2807 2808 src << "void main (void)\n{\n" 2809 << "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n" 2810 << "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n"; 2811 2812 generateExecBufferIo(src, shaderSpec, "invocationId"); 2813 2814 src << "}\n"; 2815 2816 return src.str(); 2817 } 2818 2819 void TessEvaluationExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection) 2820 { 2821 programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess()) << shaderSpec.buildOptions; 2822 programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generatePassthroughTessControlShader()) << shaderSpec.buildOptions; 2823 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec)) << shaderSpec.buildOptions; 2824 programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource()) << shaderSpec.buildOptions; 2825 } 2826 2827 void TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources) 2828 { 2829 const int patchSize = 2; 2830 const int alignedValues = deAlign32(numValues, patchSize); 2831 2832 // Initialize buffers with aligned value count to make room for padding 2833 initBuffers(alignedValues); 2834 2835 // Setup input buffer & copy data 2836 uploadInputBuffer(inputs, numValues); 2837 2838 renderTess((deUint32)alignedValues, (deUint32)alignedValues, (deUint32)patchSize, extraResources); 2839 2840 // Read back data 2841 readOutputBuffer(outputs, numValues); 2842 } 2843 2844 } // anonymous 2845 2846 // ShaderExecutor 2847 2848 ShaderExecutor::~ShaderExecutor (void) 2849 { 2850 } 2851 2852 // Utilities 2853 2854 void generateSources (glu::ShaderType shaderType, const ShaderSpec& shaderSpec, vk::SourceCollections& dst) 2855 { 2856 switch (shaderType) 2857 { 2858 case glu::SHADERTYPE_VERTEX: VertexShaderExecutor::generateSources (shaderSpec, dst); break; 2859 case glu::SHADERTYPE_TESSELLATION_CONTROL: TessControlExecutor::generateSources (shaderSpec, dst); break; 2860 case glu::SHADERTYPE_TESSELLATION_EVALUATION: TessEvaluationExecutor::generateSources (shaderSpec, dst); break; 2861 case glu::SHADERTYPE_GEOMETRY: GeometryShaderExecutor::generateSources (shaderSpec, dst); break; 2862 case glu::SHADERTYPE_FRAGMENT: FragmentShaderExecutor::generateSources (shaderSpec, dst); break; 2863 case glu::SHADERTYPE_COMPUTE: ComputeShaderExecutor::generateSources (shaderSpec, dst); break; 2864 default: 2865 TCU_THROW(InternalError, "Unsupported shader type"); 2866 } 2867 } 2868 2869 ShaderExecutor* createExecutor (Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout) 2870 { 2871 switch (shaderType) 2872 { 2873 case glu::SHADERTYPE_VERTEX: return new VertexShaderExecutor (context, shaderSpec, extraResourcesLayout); 2874 case glu::SHADERTYPE_TESSELLATION_CONTROL: return new TessControlExecutor (context, shaderSpec, extraResourcesLayout); 2875 case glu::SHADERTYPE_TESSELLATION_EVALUATION: return new TessEvaluationExecutor (context, shaderSpec, extraResourcesLayout); 2876 case glu::SHADERTYPE_GEOMETRY: return new GeometryShaderExecutor (context, shaderSpec, extraResourcesLayout); 2877 case glu::SHADERTYPE_FRAGMENT: return new FragmentShaderExecutor (context, shaderSpec, extraResourcesLayout); 2878 case glu::SHADERTYPE_COMPUTE: return new ComputeShaderExecutor (context, shaderSpec, extraResourcesLayout); 2879 default: 2880 TCU_THROW(InternalError, "Unsupported shader type"); 2881 } 2882 } 2883 2884 } // shaderexecutor 2885 } // vkt 2886