1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Vertex Input Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktPipelineVertexInputTests.hpp" 26 #include "vktTestGroupUtil.hpp" 27 #include "vktPipelineClearUtil.hpp" 28 #include "vktPipelineImageUtil.hpp" 29 #include "vktPipelineVertexUtil.hpp" 30 #include "vktPipelineReferenceRenderer.hpp" 31 #include "vktTestCase.hpp" 32 #include "vktTestCaseUtil.hpp" 33 #include "vkImageUtil.hpp" 34 #include "vkMemUtil.hpp" 35 #include "vkPrograms.hpp" 36 #include "vkQueryUtil.hpp" 37 #include "vkRef.hpp" 38 #include "vkRefUtil.hpp" 39 #include "tcuFloat.hpp" 40 #include "tcuImageCompare.hpp" 41 #include "deFloat16.h" 42 #include "deMemory.h" 43 #include "deRandom.hpp" 44 #include "deStringUtil.hpp" 45 #include "deUniquePtr.hpp" 46 47 #include <sstream> 48 #include <vector> 49 50 namespace vkt 51 { 52 namespace pipeline 53 { 54 55 using namespace vk; 56 57 namespace 58 { 59 60 bool isSupportedVertexFormat (Context& context, VkFormat format) 61 { 62 if (isVertexFormatDouble(format) && !context.getDeviceFeatures().shaderFloat64) 63 return false; 64 65 VkFormatProperties formatProps; 66 deMemset(&formatProps, 0, sizeof(VkFormatProperties)); 67 context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), format, &formatProps); 68 69 return (formatProps.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0u; 70 } 71 72 float getRepresentableDifferenceUnorm (VkFormat format) 73 { 74 DE_ASSERT(isVertexFormatUnorm(format) || isVertexFormatSRGB(format)); 75 76 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8)) - 1); 77 } 78 79 float getRepresentableDifferenceSnorm (VkFormat format) 80 { 81 DE_ASSERT(isVertexFormatSnorm(format)); 82 83 return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8 - 1)) - 1); 84 } 85 86 deUint32 getNextMultipleOffset (deUint32 divisor, deUint32 value) 87 { 88 if (value % divisor == 0) 89 return 0; 90 else 91 return divisor - (value % divisor); 92 } 93 94 class VertexInputTest : public vkt::TestCase 95 { 96 public: 97 enum GlslType 98 { 99 GLSL_TYPE_INT, 100 GLSL_TYPE_IVEC2, 101 GLSL_TYPE_IVEC3, 102 GLSL_TYPE_IVEC4, 103 104 GLSL_TYPE_UINT, 105 GLSL_TYPE_UVEC2, 106 GLSL_TYPE_UVEC3, 107 GLSL_TYPE_UVEC4, 108 109 GLSL_TYPE_FLOAT, 110 GLSL_TYPE_VEC2, 111 GLSL_TYPE_VEC3, 112 GLSL_TYPE_VEC4, 113 GLSL_TYPE_MAT2, 114 GLSL_TYPE_MAT3, 115 GLSL_TYPE_MAT4, 116 117 GLSL_TYPE_DOUBLE, 118 GLSL_TYPE_DVEC2, 119 GLSL_TYPE_DVEC3, 120 GLSL_TYPE_DVEC4, 121 GLSL_TYPE_DMAT2, 122 GLSL_TYPE_DMAT3, 123 GLSL_TYPE_DMAT4, 124 125 GLSL_TYPE_COUNT 126 }; 127 128 enum GlslBasicType 129 { 130 GLSL_BASIC_TYPE_INT, 131 GLSL_BASIC_TYPE_UINT, 132 GLSL_BASIC_TYPE_FLOAT, 133 GLSL_BASIC_TYPE_DOUBLE 134 }; 135 136 enum BindingMapping 137 { 138 BINDING_MAPPING_ONE_TO_ONE, //!< Vertex input bindings will not contain data for more than one attribute. 139 BINDING_MAPPING_ONE_TO_MANY //!< Vertex input bindings can contain data for more than one attribute. 140 }; 141 142 enum AttributeLayout 143 { 144 ATTRIBUTE_LAYOUT_INTERLEAVED, //!< Attribute data is bundled together as if in a structure: [pos 0][color 0][pos 1][color 1]... 145 ATTRIBUTE_LAYOUT_SEQUENTIAL //!< Data for each attribute is laid out separately: [pos 0][pos 1]...[color 0][color 1]... 146 // Sequential only makes a difference if ONE_TO_MANY mapping is used (more than one attribute in a binding). 147 }; 148 149 struct AttributeInfo 150 { 151 GlslType glslType; 152 VkFormat vkType; 153 VkVertexInputRate inputRate; 154 }; 155 156 struct GlslTypeDescription 157 { 158 const char* name; 159 int vertexInputComponentCount; 160 int vertexInputCount; 161 GlslBasicType basicType; 162 }; 163 164 static const GlslTypeDescription s_glslTypeDescriptions[GLSL_TYPE_COUNT]; 165 166 VertexInputTest (tcu::TestContext& testContext, 167 const std::string& name, 168 const std::string& description, 169 const std::vector<AttributeInfo>& attributeInfos, 170 BindingMapping bindingMapping, 171 AttributeLayout attributeLayout); 172 173 virtual ~VertexInputTest (void) {} 174 virtual void initPrograms (SourceCollections& programCollection) const; 175 virtual TestInstance* createInstance (Context& context) const; 176 static bool isCompatibleType (VkFormat format, GlslType glslType); 177 178 private: 179 AttributeInfo getAttributeInfo (size_t attributeNdx) const; 180 size_t getNumAttributes (void) const; 181 std::string getGlslInputDeclarations (void) const; 182 std::string getGlslVertexCheck (void) const; 183 std::string getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const; 184 static tcu::Vec4 getFormatThreshold (VkFormat format); 185 186 const std::vector<AttributeInfo> m_attributeInfos; 187 const BindingMapping m_bindingMapping; 188 const AttributeLayout m_attributeLayout; 189 const bool m_queryMaxAttributes; 190 bool m_usesDoubleType; 191 mutable size_t m_maxAttributes; 192 }; 193 194 class VertexInputInstance : public vkt::TestInstance 195 { 196 public: 197 struct VertexInputAttributeDescription 198 { 199 VertexInputTest::GlslType glslType; 200 int vertexInputIndex; 201 VkVertexInputAttributeDescription vkDescription; 202 }; 203 204 typedef std::vector<VertexInputAttributeDescription> AttributeDescriptionList; 205 206 VertexInputInstance (Context& context, 207 const AttributeDescriptionList& attributeDescriptions, 208 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions, 209 const std::vector<VkDeviceSize>& bindingOffsets); 210 211 virtual ~VertexInputInstance (void); 212 virtual tcu::TestStatus iterate (void); 213 214 215 static void writeVertexInputData (deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes); 216 static void writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attributes, int indexId); 217 218 private: 219 tcu::TestStatus verifyImage (void); 220 221 private: 222 std::vector<VkBuffer> m_vertexBuffers; 223 std::vector<Allocation*> m_vertexBufferAllocs; 224 225 const tcu::UVec2 m_renderSize; 226 const VkFormat m_colorFormat; 227 228 Move<VkImage> m_colorImage; 229 de::MovePtr<Allocation> m_colorImageAlloc; 230 Move<VkImage> m_depthImage; 231 Move<VkImageView> m_colorAttachmentView; 232 Move<VkRenderPass> m_renderPass; 233 Move<VkFramebuffer> m_framebuffer; 234 235 Move<VkShaderModule> m_vertexShaderModule; 236 Move<VkShaderModule> m_fragmentShaderModule; 237 238 Move<VkPipelineLayout> m_pipelineLayout; 239 Move<VkPipeline> m_graphicsPipeline; 240 241 Move<VkCommandPool> m_cmdPool; 242 Move<VkCommandBuffer> m_cmdBuffer; 243 244 Move<VkFence> m_fence; 245 }; 246 247 const VertexInputTest::GlslTypeDescription VertexInputTest::s_glslTypeDescriptions[GLSL_TYPE_COUNT] = 248 { 249 { "int", 1, 1, GLSL_BASIC_TYPE_INT }, 250 { "ivec2", 2, 1, GLSL_BASIC_TYPE_INT }, 251 { "ivec3", 3, 1, GLSL_BASIC_TYPE_INT }, 252 { "ivec4", 4, 1, GLSL_BASIC_TYPE_INT }, 253 254 { "uint", 1, 1, GLSL_BASIC_TYPE_UINT }, 255 { "uvec2", 2, 1, GLSL_BASIC_TYPE_UINT }, 256 { "uvec3", 3, 1, GLSL_BASIC_TYPE_UINT }, 257 { "uvec4", 4, 1, GLSL_BASIC_TYPE_UINT }, 258 259 { "float", 1, 1, GLSL_BASIC_TYPE_FLOAT }, 260 { "vec2", 2, 1, GLSL_BASIC_TYPE_FLOAT }, 261 { "vec3", 3, 1, GLSL_BASIC_TYPE_FLOAT }, 262 { "vec4", 4, 1, GLSL_BASIC_TYPE_FLOAT }, 263 { "mat2", 2, 2, GLSL_BASIC_TYPE_FLOAT }, 264 { "mat3", 3, 3, GLSL_BASIC_TYPE_FLOAT }, 265 { "mat4", 4, 4, GLSL_BASIC_TYPE_FLOAT }, 266 267 { "double", 1, 1, GLSL_BASIC_TYPE_DOUBLE }, 268 { "dvec2", 2, 1, GLSL_BASIC_TYPE_DOUBLE }, 269 { "dvec3", 3, 1, GLSL_BASIC_TYPE_DOUBLE }, 270 { "dvec4", 4, 1, GLSL_BASIC_TYPE_DOUBLE }, 271 { "dmat2", 2, 2, GLSL_BASIC_TYPE_DOUBLE }, 272 { "dmat3", 3, 3, GLSL_BASIC_TYPE_DOUBLE }, 273 { "dmat4", 4, 4, GLSL_BASIC_TYPE_DOUBLE } 274 }; 275 276 277 VertexInputTest::VertexInputTest (tcu::TestContext& testContext, 278 const std::string& name, 279 const std::string& description, 280 const std::vector<AttributeInfo>& attributeInfos, 281 BindingMapping bindingMapping, 282 AttributeLayout attributeLayout) 283 284 : vkt::TestCase (testContext, name, description) 285 , m_attributeInfos (attributeInfos) 286 , m_bindingMapping (bindingMapping) 287 , m_attributeLayout (attributeLayout) 288 , m_queryMaxAttributes (attributeInfos.size() == 0) 289 , m_maxAttributes (16) 290 { 291 DE_ASSERT(m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED || m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY); 292 293 m_usesDoubleType = false; 294 295 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) 296 { 297 if (s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].basicType == GLSL_BASIC_TYPE_DOUBLE) 298 { 299 m_usesDoubleType = true; 300 break; 301 } 302 } 303 } 304 305 deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate firstInputRate, const VkVertexInputRate inputRate, const deUint32 attributeNdx) 306 { 307 if (bindingMapping == VertexInputTest::BINDING_MAPPING_ONE_TO_ONE) 308 { 309 // Each attribute uses a unique binding 310 return attributeNdx; 311 } 312 else // bindingMapping == BINDING_MAPPING_ONE_TO_MANY 313 { 314 // Alternate between two bindings 315 return deUint32(firstInputRate + inputRate) % 2u; 316 } 317 } 318 319 //! Number of locations used up by an attribute. 320 deUint32 getConsumedLocations (const VertexInputTest::AttributeInfo& attributeInfo) 321 { 322 // double formats with more than 2 components will take 2 locations 323 const VertexInputTest::GlslType type = attributeInfo.glslType; 324 if ((type == VertexInputTest::GLSL_TYPE_DMAT2 || type == VertexInputTest::GLSL_TYPE_DMAT3 || type == VertexInputTest::GLSL_TYPE_DMAT4) && 325 (attributeInfo.vkType == VK_FORMAT_R64G64B64_SFLOAT || attributeInfo.vkType == VK_FORMAT_R64G64B64A64_SFLOAT)) 326 { 327 return 2u; 328 } 329 else 330 return 1u; 331 } 332 333 VertexInputTest::AttributeInfo VertexInputTest::getAttributeInfo (size_t attributeNdx) const 334 { 335 if (m_queryMaxAttributes) 336 { 337 AttributeInfo attributeInfo = 338 { 339 GLSL_TYPE_VEC4, 340 VK_FORMAT_R8G8B8A8_SNORM, 341 (attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE 342 }; 343 344 return attributeInfo; 345 } 346 else 347 { 348 return m_attributeInfos.at(attributeNdx); 349 } 350 } 351 352 size_t VertexInputTest::getNumAttributes (void) const 353 { 354 if (m_queryMaxAttributes) 355 return m_maxAttributes; 356 else 357 return m_attributeInfos.size(); 358 } 359 360 TestInstance* VertexInputTest::createInstance (Context& context) const 361 { 362 typedef VertexInputInstance::VertexInputAttributeDescription VertexInputAttributeDescription; 363 364 // Check upfront for maximum number of vertex input attributes 365 { 366 const InstanceInterface& vki = context.getInstanceInterface(); 367 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 368 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; 369 370 const deUint32 maxAttributes = limits.maxVertexInputAttributes; 371 372 if (m_attributeInfos.size() > maxAttributes) 373 { 374 const std::string notSupportedStr = "Unsupported number of vertex input attributes, maxVertexInputAttributes: " + de::toString(maxAttributes); 375 TCU_THROW(NotSupportedError, notSupportedStr.c_str()); 376 } 377 378 // Use VkPhysicalDeviceLimits::maxVertexInputAttributes 379 if (m_queryMaxAttributes) 380 m_maxAttributes = maxAttributes; 381 } 382 383 // Create enough binding descriptions with random offsets 384 std::vector<VkVertexInputBindingDescription> bindingDescriptions; 385 std::vector<VkDeviceSize> bindingOffsets; 386 const size_t numAttributes = getNumAttributes(); 387 const size_t numBindings = (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE) ? numAttributes : ((numAttributes > 1) ? 2 : 1); 388 const VkVertexInputRate firstInputrate = getAttributeInfo(0).inputRate; 389 390 for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx) 391 { 392 // Bindings alternate between STEP_RATE_VERTEX and STEP_RATE_INSTANCE 393 const VkVertexInputRate inputRate = ((firstInputrate + bindingNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; 394 395 // Stride will be updated when creating the attribute descriptions 396 const VkVertexInputBindingDescription bindingDescription = 397 { 398 static_cast<deUint32>(bindingNdx), // deUint32 binding; 399 0u, // deUint32 stride; 400 inputRate // VkVertexInputRate inputRate; 401 }; 402 403 bindingDescriptions.push_back(bindingDescription); 404 bindingOffsets.push_back(4 * bindingNdx); 405 } 406 407 std::vector<VertexInputAttributeDescription> attributeDescriptions; 408 deUint32 attributeLocation = 0; 409 std::vector<deUint32> attributeOffsets (bindingDescriptions.size(), 0); 410 std::vector<deUint32> attributeMaxSizes (bindingDescriptions.size(), 0); // max component or vector size, depending on which layout we are using 411 412 // To place the attributes sequentially we need to know the largest attribute and use its size in stride and offset calculations. 413 if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL) 414 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx) 415 { 416 const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx); 417 const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx)); 418 const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType); 419 420 attributeMaxSizes[attributeBinding] = de::max(attributeMaxSizes[attributeBinding], inputSize); 421 } 422 423 // Create attribute descriptions, assign them to bindings and update stride. 424 for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx) 425 { 426 const AttributeInfo& attributeInfo = getAttributeInfo(attributeNdx); 427 const GlslTypeDescription& glslTypeDescription = s_glslTypeDescriptions[attributeInfo.glslType]; 428 const deUint32 inputSize = getVertexFormatSize(attributeInfo.vkType); 429 const deUint32 attributeBinding = getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx)); 430 const deUint32 vertexCount = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2; 431 432 VertexInputAttributeDescription attributeDescription = 433 { 434 attributeInfo.glslType, // GlslType glslType; 435 0, // int vertexInputIndex; 436 { 437 0u, // uint32_t location; 438 attributeBinding, // uint32_t binding; 439 attributeInfo.vkType, // VkFormat format; 440 0u, // uint32_t offset; 441 }, 442 }; 443 444 // Matrix types add each column as a separate attribute. 445 for (int descNdx = 0; descNdx < glslTypeDescription.vertexInputCount; ++descNdx) 446 { 447 attributeDescription.vertexInputIndex = descNdx; 448 attributeDescription.vkDescription.location = attributeLocation; 449 450 if (m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED) 451 { 452 const deUint32 offsetToComponentAlignment = getNextMultipleOffset(getVertexFormatComponentSize(attributeInfo.vkType), 453 (deUint32)bindingOffsets[attributeBinding] + attributeOffsets[attributeBinding]); 454 attributeOffsets[attributeBinding] += offsetToComponentAlignment; 455 456 attributeDescription.vkDescription.offset = attributeOffsets[attributeBinding]; 457 attributeDescriptions.push_back(attributeDescription); 458 459 bindingDescriptions[attributeBinding].stride += offsetToComponentAlignment + inputSize; 460 attributeOffsets[attributeBinding] += inputSize; 461 attributeMaxSizes[attributeBinding] = de::max(attributeMaxSizes[attributeBinding], getVertexFormatComponentSize(attributeInfo.vkType)); 462 } 463 else // m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL 464 { 465 attributeDescription.vkDescription.offset = attributeOffsets[attributeBinding]; 466 attributeDescriptions.push_back(attributeDescription); 467 468 attributeOffsets[attributeBinding] += vertexCount * attributeMaxSizes[attributeBinding]; 469 } 470 471 attributeLocation += getConsumedLocations(attributeInfo); 472 } 473 474 if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL) 475 bindingDescriptions[attributeBinding].stride = attributeMaxSizes[attributeBinding]; 476 } 477 478 // Make sure the stride results in aligned access 479 for (size_t bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx) 480 { 481 if (attributeMaxSizes[bindingNdx] > 0) 482 bindingDescriptions[bindingNdx].stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], bindingDescriptions[bindingNdx].stride); 483 } 484 485 // Check upfront for maximum number of vertex input bindings 486 { 487 const InstanceInterface& vki = context.getInstanceInterface(); 488 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 489 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits; 490 491 const deUint32 maxBindings = limits.maxVertexInputBindings; 492 493 if (bindingDescriptions.size() > maxBindings) 494 { 495 const std::string notSupportedStr = "Unsupported number of vertex input bindings, maxVertexInputBindings: " + de::toString(maxBindings); 496 TCU_THROW(NotSupportedError, notSupportedStr.c_str()); 497 } 498 } 499 500 return new VertexInputInstance(context, attributeDescriptions, bindingDescriptions, bindingOffsets); 501 } 502 503 void VertexInputTest::initPrograms (SourceCollections& programCollection) const 504 { 505 std::ostringstream vertexSrc; 506 507 vertexSrc << "#version 440\n" 508 << "layout(constant_id = 0) const int numAttributes = " << m_maxAttributes << ";\n" 509 << getGlslInputDeclarations() 510 << "layout(location = 0) out highp vec4 vtxColor;\n" 511 << "out gl_PerVertex {\n" 512 << " vec4 gl_Position;\n" 513 << "};\n"; 514 515 // NOTE: double abs(double x) undefined in glslang ?? 516 if (m_usesDoubleType) 517 vertexSrc << "double abs (double x) { if (x < 0.0LF) return -x; else return x; }\n"; 518 519 vertexSrc << "void main (void)\n" 520 << "{\n" 521 << getGlslVertexCheck() 522 << "}\n"; 523 524 programCollection.glslSources.add("attribute_test_vert") << glu::VertexSource(vertexSrc.str()); 525 526 programCollection.glslSources.add("attribute_test_frag") << glu::FragmentSource( 527 "#version 440\n" 528 "layout(location = 0) in highp vec4 vtxColor;\n" 529 "layout(location = 0) out highp vec4 fragColor;\n" 530 "void main (void)\n" 531 "{\n" 532 " fragColor = vtxColor;\n" 533 "}\n"); 534 } 535 536 std::string VertexInputTest::getGlslInputDeclarations (void) const 537 { 538 std::ostringstream glslInputs; 539 deUint32 location = 0; 540 541 if (m_queryMaxAttributes) 542 { 543 const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[GLSL_TYPE_VEC4]; 544 glslInputs << "layout(location = 0) in " << glslTypeDesc.name << " attr[numAttributes];\n"; 545 } 546 else 547 { 548 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) 549 { 550 const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType]; 551 552 glslInputs << "layout(location = " << location << ") in " << glslTypeDesc.name << " attr" << attributeNdx << ";\n"; 553 location += glslTypeDesc.vertexInputCount; 554 } 555 } 556 557 return glslInputs.str(); 558 } 559 560 std::string VertexInputTest::getGlslVertexCheck (void) const 561 { 562 std::ostringstream glslCode; 563 int totalInputComponentCount = 0; 564 565 glslCode << " int okCount = 0;\n"; 566 567 if (m_queryMaxAttributes) 568 { 569 const AttributeInfo attributeInfo = getAttributeInfo(0); 570 571 glslCode << " for (int checkNdx = 0; checkNdx < numAttributes; checkNdx++)\n" 572 << " {\n" 573 << " uint index = (checkNdx % 2 == 0) ? gl_VertexIndex : gl_InstanceIndex;\n"; 574 575 glslCode << getGlslAttributeConditions(attributeInfo, "checkNdx") 576 << " }\n"; 577 578 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount; 579 totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount; 580 581 glslCode << 582 " if (okCount == " << totalInputComponentCount << " * numAttributes)\n" 583 " {\n" 584 " if (gl_InstanceIndex == 0)\n" 585 " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 586 " else\n" 587 " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n" 588 " }\n" 589 " else\n" 590 " {\n" 591 " vtxColor = vec4(okCount / float(" << totalInputComponentCount << " * numAttributes), 0.0f, 0.0f, 1.0);\n" << 592 " }\n\n" 593 " if (gl_InstanceIndex == 0)\n" 594 " {\n" 595 " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 596 " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 597 " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 598 " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" 599 " else gl_Position = vec4(0.0);\n" 600 " }\n" 601 " else\n" 602 " {\n" 603 " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 604 " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" 605 " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" 606 " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" 607 " else gl_Position = vec4(0.0);\n" 608 " }\n"; 609 } 610 else 611 { 612 for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++) 613 { 614 glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], de::toString(attributeNdx)); 615 616 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount; 617 totalInputComponentCount += vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount; 618 } 619 620 glslCode << 621 " if (okCount == " << totalInputComponentCount << ")\n" 622 " {\n" 623 " if (gl_InstanceIndex == 0)\n" 624 " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 625 " else\n" 626 " vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n" 627 " }\n" 628 " else\n" 629 " {\n" 630 " vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" << 631 " }\n\n" 632 " if (gl_InstanceIndex == 0)\n" 633 " {\n" 634 " if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 635 " else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 636 " else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 637 " else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" 638 " else gl_Position = vec4(0.0);\n" 639 " }\n" 640 " else\n" 641 " {\n" 642 " if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n" 643 " else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n" 644 " else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n" 645 " else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n" 646 " else gl_Position = vec4(0.0);\n" 647 " }\n"; 648 } 649 return glslCode.str(); 650 } 651 652 std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const 653 { 654 std::ostringstream glslCode; 655 std::ostringstream attributeVar; 656 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount; 657 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount; 658 const deUint32 totalComponentCount = componentCount * vertexInputCount; 659 const tcu::Vec4 threshold = getFormatThreshold(attributeInfo.vkType); 660 deUint32 componentIndex = 0; 661 const std::string indexStr = m_queryMaxAttributes ? "[" + attributeIndex + "]" : attributeIndex; 662 const std::string indentStr = m_queryMaxAttributes ? "\t\t" : "\t"; 663 std::string indexId; 664 665 if (m_queryMaxAttributes) 666 indexId = "index"; 667 else 668 indexId = (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex"; 669 670 attributeVar << "attr" << indexStr; 671 672 glslCode << std::fixed; 673 674 for (int columnNdx = 0; columnNdx< vertexInputCount; columnNdx++) 675 { 676 for (int rowNdx = 0; rowNdx < componentCount; rowNdx++) 677 { 678 std::string accessStr; 679 { 680 // Build string representing the access to the attribute component 681 std::ostringstream accessStream; 682 accessStream << attributeVar.str(); 683 684 if (vertexInputCount == 1) 685 { 686 if (componentCount > 1) 687 accessStream << "[" << rowNdx << "]"; 688 } 689 else 690 { 691 accessStream << "[" << columnNdx << "][" << rowNdx << "]"; 692 } 693 694 accessStr = accessStream.str(); 695 } 696 697 if (isVertexFormatSint(attributeInfo.vkType)) 698 { 699 glslCode << indentStr << "if (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; 700 } 701 else if (isVertexFormatUint(attributeInfo.vkType)) 702 { 703 glslCode << indentStr << "if (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n"; 704 } 705 else if (isVertexFormatSfloat(attributeInfo.vkType)) 706 { 707 if (VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE) 708 { 709 glslCode << indentStr << "if (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n"; 710 } 711 else 712 { 713 glslCode << indentStr << "if (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; 714 } 715 } 716 else if (isVertexFormatSscaled(attributeInfo.vkType)) 717 { 718 glslCode << indentStr << "if (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; 719 } 720 else if (isVertexFormatUscaled(attributeInfo.vkType)) 721 { 722 glslCode << indentStr << "if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n"; 723 } 724 else if (isVertexFormatSnorm(attributeInfo.vkType)) 725 { 726 const float representableDiff = getRepresentableDifferenceSnorm(attributeInfo.vkType); 727 728 glslCode << indentStr << "if (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; 729 } 730 else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType)) 731 { 732 const float representableDiff = getRepresentableDifferenceUnorm(attributeInfo.vkType); 733 734 glslCode << indentStr << "if (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n"; 735 } 736 else 737 { 738 DE_ASSERT(false); 739 } 740 741 glslCode << indentStr << "\tokCount++;\n\n"; 742 743 componentIndex++; 744 } 745 } 746 return glslCode.str(); 747 } 748 749 tcu::Vec4 VertexInputTest::getFormatThreshold (VkFormat format) 750 { 751 using tcu::Vec4; 752 753 switch (format) 754 { 755 case VK_FORMAT_R32_SFLOAT: 756 case VK_FORMAT_R32G32_SFLOAT: 757 case VK_FORMAT_R32G32B32_SFLOAT: 758 case VK_FORMAT_R32G32B32A32_SFLOAT: 759 case VK_FORMAT_R64_SFLOAT: 760 case VK_FORMAT_R64G64_SFLOAT: 761 case VK_FORMAT_R64G64B64_SFLOAT: 762 case VK_FORMAT_R64G64B64A64_SFLOAT: 763 return Vec4(0.00001f); 764 765 default: 766 break; 767 } 768 769 if (isVertexFormatSnorm(format)) 770 { 771 return Vec4(1.5f * getRepresentableDifferenceSnorm(format)); 772 } 773 else if (isVertexFormatUnorm(format)) 774 { 775 return Vec4(1.5f * getRepresentableDifferenceUnorm(format)); 776 } 777 778 return Vec4(0.001f); 779 } 780 781 VertexInputInstance::VertexInputInstance (Context& context, 782 const AttributeDescriptionList& attributeDescriptions, 783 const std::vector<VkVertexInputBindingDescription>& bindingDescriptions, 784 const std::vector<VkDeviceSize>& bindingOffsets) 785 : vkt::TestInstance (context) 786 , m_renderSize (16, 16) 787 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 788 { 789 DE_ASSERT(bindingDescriptions.size() == bindingOffsets.size()); 790 791 const DeviceInterface& vk = context.getDeviceInterface(); 792 const VkDevice vkDevice = context.getDevice(); 793 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 794 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())); 795 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 796 797 // Check upfront for unsupported features 798 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++) 799 { 800 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription; 801 if (!isSupportedVertexFormat(context, attributeDescription.format)) 802 { 803 throw tcu::NotSupportedError(std::string("Unsupported format for vertex input: ") + getFormatName(attributeDescription.format)); 804 } 805 } 806 807 // Create color image 808 { 809 const VkImageCreateInfo colorImageParams = 810 { 811 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 812 DE_NULL, // const void* pNext; 813 0u, // VkImageCreateFlags flags; 814 VK_IMAGE_TYPE_2D, // VkImageType imageType; 815 m_colorFormat, // VkFormat format; 816 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 817 1u, // deUint32 mipLevels; 818 1u, // deUint32 arrayLayers; 819 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 820 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 821 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 822 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 823 1u, // deUint32 queueFamilyIndexCount; 824 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 825 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 826 }; 827 828 m_colorImage = createImage(vk, vkDevice, &colorImageParams); 829 830 // Allocate and bind color image memory 831 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); 832 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 833 } 834 835 // Create color attachment view 836 { 837 const VkImageViewCreateInfo colorAttachmentViewParams = 838 { 839 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 840 DE_NULL, // const void* pNext; 841 0u, // VkImageViewCreateFlags flags; 842 *m_colorImage, // VkImage image; 843 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 844 m_colorFormat, // VkFormat format; 845 componentMappingRGBA, // VkComponentMapping components; 846 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; 847 }; 848 849 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); 850 } 851 852 // Create render pass 853 { 854 const VkAttachmentDescription colorAttachmentDescription = 855 { 856 0u, // VkAttachmentDescriptionFlags flags; 857 m_colorFormat, // VkFormat format; 858 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 859 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 860 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 861 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 862 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 863 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 864 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; 865 }; 866 867 const VkAttachmentReference colorAttachmentReference = 868 { 869 0u, // deUint32 attachment; 870 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 871 }; 872 873 const VkSubpassDescription subpassDescription = 874 { 875 0u, // VkSubpassDescriptionFlags flags; 876 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 877 0u, // deUint32 inputAttachmentCount; 878 DE_NULL, // const VkAttachmentReference* pInputAttachments; 879 1u, // deUint32 colorAttachmentCount; 880 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 881 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 882 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 883 0u, // deUint32 preserveAttachmentCount; 884 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 885 }; 886 887 const VkRenderPassCreateInfo renderPassParams = 888 { 889 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 890 DE_NULL, // const void* pNext; 891 0u, // VkRenderPassCreateFlags flags; 892 1u, // deUint32 attachmentCount; 893 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 894 1u, // deUint32 subpassCount; 895 &subpassDescription, // const VkSubpassDescription* pSubpasses; 896 0u, // deUint32 dependencyCount; 897 DE_NULL // const VkSubpassDependency* pDependencies; 898 }; 899 900 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams); 901 } 902 903 // Create framebuffer 904 { 905 const VkFramebufferCreateInfo framebufferParams = 906 { 907 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 908 DE_NULL, // const void* pNext; 909 0u, // VkFramebufferCreateFlags flags; 910 *m_renderPass, // VkRenderPass renderPass; 911 1u, // deUint32 attachmentCount; 912 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 913 (deUint32)m_renderSize.x(), // deUint32 width; 914 (deUint32)m_renderSize.y(), // deUint32 height; 915 1u // deUint32 layers; 916 }; 917 918 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 919 } 920 921 // Create pipeline layout 922 { 923 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 924 { 925 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 926 DE_NULL, // const void* pNext; 927 0u, // VkPipelineLayoutCreateFlags flags; 928 0u, // deUint32 setLayoutCount; 929 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 930 0u, // deUint32 pushConstantRangeCount; 931 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 932 }; 933 934 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 935 } 936 937 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0); 938 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0); 939 940 // Create specialization constant 941 deUint32 specializationData = static_cast<deUint32>(attributeDescriptions.size()); 942 943 const VkSpecializationMapEntry specializationMapEntry = 944 { 945 0, // uint32_t constantID 946 0, // uint32_t offset 947 sizeof(specializationData), // uint32_t size 948 }; 949 950 const VkSpecializationInfo specializationInfo = 951 { 952 1, // uint32_t mapEntryCount 953 &specializationMapEntry, // const void* pMapEntries 954 sizeof(specializationData), // size_t dataSize 955 &specializationData // const void* pData 956 }; 957 958 // Create pipeline 959 { 960 const VkPipelineShaderStageCreateInfo shaderStageParams[2] = 961 { 962 { 963 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 964 DE_NULL, // const void* pNext; 965 0u, // VkPipelineShaderStageCreateFlags flags; 966 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 967 *m_vertexShaderModule, // VkShaderModule module; 968 "main", // const char* pName; 969 &specializationInfo // const VkSpecializationInfo* pSpecializationInfo; 970 }, 971 { 972 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 973 DE_NULL, // const void* pNext; 974 0u, // VkPipelineShaderStageCreateFlags flags; 975 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 976 *m_fragmentShaderModule, // VkShaderModule module; 977 "main", // const char* pName; 978 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 979 } 980 }; 981 982 // Create vertex attribute array and check if their VK formats are supported 983 std::vector<VkVertexInputAttributeDescription> vkAttributeDescriptions; 984 for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++) 985 { 986 const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription; 987 vkAttributeDescriptions.push_back(attributeDescription); 988 } 989 990 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 991 { 992 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 993 DE_NULL, // const void* pNext; 994 0u, // VkPipelineVertexInputStateCreateFlags flags; 995 (deUint32)bindingDescriptions.size(), // deUint32 vertexBindingDescriptionCount; 996 bindingDescriptions.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 997 (deUint32)vkAttributeDescriptions.size(), // deUint32 vertexAttributeDescriptionCount; 998 vkAttributeDescriptions.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 999 }; 1000 1001 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 1002 { 1003 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 1004 DE_NULL, // const void* pNext; 1005 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 1006 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology; 1007 false // VkBool32 primitiveRestartEnable; 1008 }; 1009 1010 const VkViewport viewport = 1011 { 1012 0.0f, // float x; 1013 0.0f, // float y; 1014 (float)m_renderSize.x(), // float width; 1015 (float)m_renderSize.y(), // float height; 1016 0.0f, // float minDepth; 1017 1.0f // float maxDepth; 1018 }; 1019 1020 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }; 1021 1022 const VkPipelineViewportStateCreateInfo viewportStateParams = 1023 { 1024 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 1025 DE_NULL, // const void* pNext; 1026 0u, // VkPipelineViewportStateCreateFlags flags; 1027 1u, // deUint32 viewportCount; 1028 &viewport, // const VkViewport* pViewports; 1029 1u, // deUint32 scissorCount; 1030 &scissor // const VkRect2D* pScissors; 1031 }; 1032 1033 const VkPipelineRasterizationStateCreateInfo rasterStateParams = 1034 { 1035 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 1036 DE_NULL, // const void* pNext; 1037 0u, // VkPipelineRasterizationStateCreateFlags flags; 1038 false, // VkBool32 depthClampEnable; 1039 false, // VkBool32 rasterizerDiscardEnable; 1040 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 1041 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 1042 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 1043 VK_FALSE, // VkBool32 depthBiasEnable; 1044 0.0f, // float depthBiasConstantFactor; 1045 0.0f, // float depthBiasClamp; 1046 0.0f, // float depthBiasSlopeFactor; 1047 1.0f, // float lineWidth; 1048 }; 1049 1050 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 1051 { 1052 false, // VkBool32 blendEnable; 1053 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 1054 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 1055 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 1056 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 1057 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 1058 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 1059 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; 1060 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT 1061 }; 1062 1063 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 1064 { 1065 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1066 DE_NULL, // const void* pNext; 1067 0u, // VkPipelineColorBlendStateCreateFlags flags; 1068 false, // VkBool32 logicOpEnable; 1069 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 1070 1u, // deUint32 attachmentCount; 1071 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1072 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 1073 }; 1074 1075 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 1076 { 1077 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 1078 DE_NULL, // const void* pNext; 1079 0u, // VkPipelineMultisampleStateCreateFlags flags; 1080 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 1081 false, // VkBool32 sampleShadingEnable; 1082 0.0f, // float minSampleShading; 1083 DE_NULL, // const VkSampleMask* pSampleMask; 1084 false, // VkBool32 alphaToCoverageEnable; 1085 false // VkBool32 alphaToOneEnable; 1086 }; 1087 1088 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = 1089 { 1090 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 1091 DE_NULL, // const void* pNext; 1092 0u, // VkPipelineDepthStencilStateCreateFlags flags; 1093 false, // VkBool32 depthTestEnable; 1094 false, // VkBool32 depthWriteEnable; 1095 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 1096 false, // VkBool32 depthBoundsTestEnable; 1097 false, // VkBool32 stencilTestEnable; 1098 // VkStencilOpState front; 1099 { 1100 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 1101 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 1102 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 1103 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 1104 0u, // deUint32 compareMask; 1105 0u, // deUint32 writeMask; 1106 0u, // deUint32 reference; 1107 }, 1108 // VkStencilOpState back; 1109 { 1110 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 1111 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 1112 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 1113 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 1114 0u, // deUint32 compareMask; 1115 0u, // deUint32 writeMask; 1116 0u, // deUint32 reference; 1117 }, 1118 0.0f, // float minDepthBounds; 1119 1.0f, // float maxDepthBounds; 1120 }; 1121 1122 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 1123 { 1124 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 1125 DE_NULL, // const void* pNext; 1126 0u, // VkPipelineCreateFlags flags; 1127 2u, // deUint32 stageCount; 1128 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages; 1129 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 1130 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 1131 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 1132 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 1133 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 1134 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 1135 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 1136 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 1137 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 1138 *m_pipelineLayout, // VkPipelineLayout layout; 1139 *m_renderPass, // VkRenderPass renderPass; 1140 0u, // deUint32 subpass; 1141 0u, // VkPipeline basePipelineHandle; 1142 0u // deInt32 basePipelineIndex; 1143 }; 1144 1145 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 1146 } 1147 1148 // Create vertex buffer 1149 { 1150 const VkBufferCreateInfo vertexBufferParams = 1151 { 1152 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1153 DE_NULL, // const void* pNext; 1154 0u, // VkBufferCreateFlags flags; 1155 4096u, // VkDeviceSize size; 1156 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 1157 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1158 1u, // deUint32 queueFamilyIndexCount; 1159 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 1160 }; 1161 1162 // Upload data for each vertex input binding 1163 for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); bindingNdx++) 1164 { 1165 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 1166 de::MovePtr<Allocation> vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible); 1167 1168 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset())); 1169 1170 writeVertexInputData((deUint8*)vertexBufferAlloc->getHostPtr(), bindingDescriptions[bindingNdx], bindingOffsets[bindingNdx], attributeDescriptions); 1171 flushMappedMemoryRange(vk, vkDevice, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferParams.size); 1172 1173 m_vertexBuffers.push_back(vertexBuffer.disown()); 1174 m_vertexBufferAllocs.push_back(vertexBufferAlloc.release()); 1175 } 1176 } 1177 1178 // Create command pool 1179 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 1180 1181 // Create command buffer 1182 { 1183 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 1184 { 1185 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 1186 DE_NULL, // const void* pNext; 1187 0u, // VkCommandBufferUsageFlags flags; 1188 (const VkCommandBufferInheritanceInfo*)DE_NULL, 1189 }; 1190 1191 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); 1192 1193 const VkRenderPassBeginInfo renderPassBeginInfo = 1194 { 1195 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 1196 DE_NULL, // const void* pNext; 1197 *m_renderPass, // VkRenderPass renderPass; 1198 *m_framebuffer, // VkFramebuffer framebuffer; 1199 { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } }, // VkRect2D renderArea; 1200 1u, // deUint32 clearValueCount; 1201 &attachmentClearValue // const VkClearValue* pClearValues; 1202 }; 1203 1204 const VkImageMemoryBarrier attachmentLayoutBarrier = 1205 { 1206 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1207 DE_NULL, // const void* pNext; 1208 0u, // VkAccessFlags srcAccessMask; 1209 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 1210 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1211 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 1212 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1213 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 1214 *m_colorImage, // VkImage image; 1215 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; 1216 }; 1217 1218 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1219 1220 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); 1221 1222 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 1223 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier); 1224 1225 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 1226 1227 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline); 1228 1229 std::vector<VkBuffer> vertexBuffers; 1230 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++) 1231 vertexBuffers.push_back(m_vertexBuffers[bufferNdx]); 1232 1233 if (vertexBuffers.size() <= 1) 1234 { 1235 // One vertex buffer 1236 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, (deUint32)vertexBuffers.size(), vertexBuffers.data(), bindingOffsets.data()); 1237 } 1238 else 1239 { 1240 // Smoke-test vkCmdBindVertexBuffers(..., startBinding, ... ) 1241 1242 const deUint32 firstHalfLength = (deUint32)vertexBuffers.size() / 2; 1243 const deUint32 secondHalfLength = firstHalfLength + (deUint32)(vertexBuffers.size() % 2); 1244 1245 // Bind first half of vertex buffers 1246 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, firstHalfLength, vertexBuffers.data(), bindingOffsets.data()); 1247 1248 // Bind second half of vertex buffers 1249 vk.cmdBindVertexBuffers(*m_cmdBuffer, firstHalfLength, secondHalfLength, 1250 vertexBuffers.data() + firstHalfLength, 1251 bindingOffsets.data() + firstHalfLength); 1252 } 1253 1254 vk.cmdDraw(*m_cmdBuffer, 4, 2, 0, 0); 1255 1256 vk.cmdEndRenderPass(*m_cmdBuffer); 1257 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 1258 } 1259 1260 // Create fence 1261 m_fence = createFence(vk, vkDevice); 1262 } 1263 1264 VertexInputInstance::~VertexInputInstance (void) 1265 { 1266 const DeviceInterface& vk = m_context.getDeviceInterface(); 1267 const VkDevice vkDevice = m_context.getDevice(); 1268 1269 for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++) 1270 vk.destroyBuffer(vkDevice, m_vertexBuffers[bufferNdx], DE_NULL); 1271 1272 for (size_t allocNdx = 0; allocNdx < m_vertexBufferAllocs.size(); allocNdx++) 1273 delete m_vertexBufferAllocs[allocNdx]; 1274 } 1275 1276 void VertexInputInstance::writeVertexInputData(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes) 1277 { 1278 const deUint32 vertexCount = (bindingDescription.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2; 1279 1280 deUint8* destOffsetPtr = ((deUint8 *)destPtr) + bindingOffset; 1281 for (deUint32 vertexNdx = 0; vertexNdx < vertexCount; vertexNdx++) 1282 { 1283 for (size_t attributeNdx = 0; attributeNdx < attributes.size(); attributeNdx++) 1284 { 1285 const VertexInputAttributeDescription& attribDesc = attributes[attributeNdx]; 1286 1287 // Only write vertex input data to bindings referenced by attribute descriptions 1288 if (attribDesc.vkDescription.binding == bindingDescription.binding) 1289 { 1290 writeVertexInputValue(destOffsetPtr + attribDesc.vkDescription.offset, attribDesc, vertexNdx); 1291 } 1292 } 1293 destOffsetPtr += bindingDescription.stride; 1294 } 1295 } 1296 1297 void writeVertexInputValueSint (deUint8* destPtr, VkFormat format, int componentNdx, deInt32 value) 1298 { 1299 const deUint32 componentSize = getVertexFormatComponentSize(format); 1300 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx; 1301 1302 switch (componentSize) 1303 { 1304 case 1: 1305 *((deInt8*)destFormatPtr) = (deInt8)value; 1306 break; 1307 1308 case 2: 1309 *((deInt16*)destFormatPtr) = (deInt16)value; 1310 break; 1311 1312 case 4: 1313 *((deInt32*)destFormatPtr) = (deInt32)value; 1314 break; 1315 1316 default: 1317 DE_ASSERT(false); 1318 } 1319 } 1320 1321 void writeVertexInputValueUint (deUint8* destPtr, VkFormat format, int componentNdx, deUint32 value) 1322 { 1323 const deUint32 componentSize = getVertexFormatComponentSize(format); 1324 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx; 1325 1326 switch (componentSize) 1327 { 1328 case 1: 1329 *((deUint8 *)destFormatPtr) = (deUint8)value; 1330 break; 1331 1332 case 2: 1333 *((deUint16 *)destFormatPtr) = (deUint16)value; 1334 break; 1335 1336 case 4: 1337 *((deUint32 *)destFormatPtr) = (deUint32)value; 1338 break; 1339 1340 default: 1341 DE_ASSERT(false); 1342 } 1343 } 1344 1345 void writeVertexInputValueSfloat (deUint8* destPtr, VkFormat format, int componentNdx, float value) 1346 { 1347 const deUint32 componentSize = getVertexFormatComponentSize(format); 1348 deUint8* destFormatPtr = ((deUint8*)destPtr) + componentSize * componentNdx; 1349 1350 switch (componentSize) 1351 { 1352 case 2: 1353 { 1354 deFloat16 f16 = deFloat32To16(value); 1355 deMemcpy(destFormatPtr, &f16, sizeof(f16)); 1356 break; 1357 } 1358 1359 case 4: 1360 deMemcpy(destFormatPtr, &value, sizeof(value)); 1361 break; 1362 1363 default: 1364 DE_ASSERT(false); 1365 } 1366 } 1367 1368 void VertexInputInstance::writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attribute, int indexId) 1369 { 1370 const int vertexInputCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputCount; 1371 const int componentCount = VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputComponentCount; 1372 const deUint32 totalComponentCount = componentCount * vertexInputCount; 1373 const deUint32 vertexInputIndex = indexId * totalComponentCount + attribute.vertexInputIndex * componentCount; 1374 const bool hasBGROrder = isVertexFormatComponentOrderBGR(attribute.vkDescription.format); 1375 int swizzledNdx; 1376 1377 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++) 1378 { 1379 if (hasBGROrder) 1380 { 1381 if (componentNdx == 0) 1382 swizzledNdx = 2; 1383 else if (componentNdx == 2) 1384 swizzledNdx = 0; 1385 else 1386 swizzledNdx = componentNdx; 1387 } 1388 else 1389 swizzledNdx = componentNdx; 1390 1391 switch (attribute.glslType) 1392 { 1393 case VertexInputTest::GLSL_TYPE_INT: 1394 case VertexInputTest::GLSL_TYPE_IVEC2: 1395 case VertexInputTest::GLSL_TYPE_IVEC3: 1396 case VertexInputTest::GLSL_TYPE_IVEC4: 1397 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx)); 1398 break; 1399 1400 case VertexInputTest::GLSL_TYPE_UINT: 1401 case VertexInputTest::GLSL_TYPE_UVEC2: 1402 case VertexInputTest::GLSL_TYPE_UVEC3: 1403 case VertexInputTest::GLSL_TYPE_UVEC4: 1404 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx); 1405 break; 1406 1407 case VertexInputTest::GLSL_TYPE_FLOAT: 1408 case VertexInputTest::GLSL_TYPE_VEC2: 1409 case VertexInputTest::GLSL_TYPE_VEC3: 1410 case VertexInputTest::GLSL_TYPE_VEC4: 1411 case VertexInputTest::GLSL_TYPE_MAT2: 1412 case VertexInputTest::GLSL_TYPE_MAT3: 1413 case VertexInputTest::GLSL_TYPE_MAT4: 1414 if (isVertexFormatSfloat(attribute.vkDescription.format)) 1415 { 1416 writeVertexInputValueSfloat(destPtr, attribute.vkDescription.format, componentNdx, -(0.01f * (float)(vertexInputIndex + swizzledNdx))); 1417 } 1418 else if (isVertexFormatSscaled(attribute.vkDescription.format)) 1419 { 1420 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx)); 1421 } 1422 else if (isVertexFormatUscaled(attribute.vkDescription.format) || isVertexFormatUnorm(attribute.vkDescription.format) || isVertexFormatSRGB(attribute.vkDescription.format)) 1423 { 1424 writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx); 1425 } 1426 else if (isVertexFormatSnorm(attribute.vkDescription.format)) 1427 { 1428 const deInt32 minIntValue = -((1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 - 1))) + 1; 1429 writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, minIntValue + (vertexInputIndex + swizzledNdx)); 1430 } 1431 else 1432 DE_ASSERT(false); 1433 break; 1434 1435 case VertexInputTest::GLSL_TYPE_DOUBLE: 1436 case VertexInputTest::GLSL_TYPE_DVEC2: 1437 case VertexInputTest::GLSL_TYPE_DVEC3: 1438 case VertexInputTest::GLSL_TYPE_DVEC4: 1439 case VertexInputTest::GLSL_TYPE_DMAT2: 1440 case VertexInputTest::GLSL_TYPE_DMAT3: 1441 case VertexInputTest::GLSL_TYPE_DMAT4: 1442 *(reinterpret_cast<double *>(destPtr) + componentNdx) = -0.01 * (vertexInputIndex + swizzledNdx); 1443 1444 break; 1445 1446 default: 1447 DE_ASSERT(false); 1448 } 1449 } 1450 } 1451 1452 tcu::TestStatus VertexInputInstance::iterate (void) 1453 { 1454 const DeviceInterface& vk = m_context.getDeviceInterface(); 1455 const VkDevice vkDevice = m_context.getDevice(); 1456 const VkQueue queue = m_context.getUniversalQueue(); 1457 const VkSubmitInfo submitInfo = 1458 { 1459 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 1460 DE_NULL, // const void* pNext; 1461 0u, // deUint32 waitSemaphoreCount; 1462 DE_NULL, // const VkSemaphore* pWaitSemaphores; 1463 (const VkPipelineStageFlags*)DE_NULL, 1464 1u, // deUint32 commandBufferCount; 1465 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; 1466 0u, // deUint32 signalSemaphoreCount; 1467 DE_NULL // const VkSemaphore* pSignalSemaphores; 1468 }; 1469 1470 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get())); 1471 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence)); 1472 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/)); 1473 1474 return verifyImage(); 1475 } 1476 1477 bool VertexInputTest::isCompatibleType (VkFormat format, GlslType glslType) 1478 { 1479 const GlslTypeDescription glslTypeDesc = s_glslTypeDescriptions[glslType]; 1480 1481 if ((deUint32)s_glslTypeDescriptions[glslType].vertexInputComponentCount == getVertexFormatComponentCount(format)) 1482 { 1483 switch (glslTypeDesc.basicType) 1484 { 1485 case GLSL_BASIC_TYPE_INT: 1486 return isVertexFormatSint(format); 1487 1488 case GLSL_BASIC_TYPE_UINT: 1489 return isVertexFormatUint(format); 1490 1491 case GLSL_BASIC_TYPE_FLOAT: 1492 return getVertexFormatComponentSize(format) <= 4 && (isVertexFormatSfloat(format) || isVertexFormatSnorm(format) || isVertexFormatUnorm(format) || isVertexFormatSscaled(format) || isVertexFormatUscaled(format) || isVertexFormatSRGB(format)); 1493 1494 case GLSL_BASIC_TYPE_DOUBLE: 1495 return isVertexFormatSfloat(format) && getVertexFormatComponentSize(format) == 8; 1496 1497 default: 1498 DE_ASSERT(false); 1499 return false; 1500 } 1501 } 1502 else 1503 return false; 1504 } 1505 1506 tcu::TestStatus VertexInputInstance::verifyImage (void) 1507 { 1508 bool compareOk = false; 1509 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat); 1510 tcu::TextureLevel reference (tcuColorFormat, m_renderSize.x(), m_renderSize.y()); 1511 const tcu::PixelBufferAccess refRedSubregion (tcu::getSubregion(reference.getAccess(), 1512 deRoundFloatToInt32((float)m_renderSize.x() * 0.0f), 1513 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f), 1514 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f), 1515 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f))); 1516 const tcu::PixelBufferAccess refBlueSubregion (tcu::getSubregion(reference.getAccess(), 1517 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f), 1518 deRoundFloatToInt32((float)m_renderSize.y() * 0.0f), 1519 deRoundFloatToInt32((float)m_renderSize.x() * 0.5f), 1520 deRoundFloatToInt32((float)m_renderSize.y() * 1.0f))); 1521 1522 // Create reference image 1523 tcu::clear(reference.getAccess(), defaultClearColor(tcuColorFormat)); 1524 tcu::clear(refRedSubregion, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); 1525 tcu::clear(refBlueSubregion, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); 1526 1527 // Compare result with reference image 1528 { 1529 const DeviceInterface& vk = m_context.getDeviceInterface(); 1530 const VkDevice vkDevice = m_context.getDevice(); 1531 const VkQueue queue = m_context.getUniversalQueue(); 1532 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1533 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 1534 de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize); 1535 1536 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), 1537 "IntImageCompare", 1538 "Image comparison", 1539 reference.getAccess(), 1540 result->getAccess(), 1541 tcu::UVec4(2, 2, 2, 2), 1542 tcu::IVec3(1, 1, 0), 1543 true, 1544 tcu::COMPARE_LOG_RESULT); 1545 } 1546 1547 if (compareOk) 1548 return tcu::TestStatus::pass("Result image matches reference"); 1549 else 1550 return tcu::TestStatus::fail("Image mismatch"); 1551 } 1552 1553 std::string getAttributeInfoCaseName (const VertexInputTest::AttributeInfo& attributeInfo) 1554 { 1555 std::ostringstream caseName; 1556 const std::string formatName = getFormatName(attributeInfo.vkType); 1557 1558 caseName << "as_" << de::toLower(formatName.substr(10)) << "_rate_"; 1559 1560 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) 1561 caseName << "vertex"; 1562 else 1563 caseName << "instance"; 1564 1565 return caseName.str(); 1566 } 1567 1568 std::string getAttributeInfoDescription (const VertexInputTest::AttributeInfo& attributeInfo) 1569 { 1570 std::ostringstream caseDesc; 1571 1572 caseDesc << std::string(VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].name) << " from type " << getFormatName(attributeInfo.vkType) << " with "; 1573 1574 if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) 1575 caseDesc << "vertex input rate "; 1576 else 1577 caseDesc << "instance input rate "; 1578 1579 return caseDesc.str(); 1580 } 1581 1582 std::string getAttributeInfosDescription (const std::vector<VertexInputTest::AttributeInfo>& attributeInfos) 1583 { 1584 std::ostringstream caseDesc; 1585 1586 caseDesc << "Uses vertex attributes:\n"; 1587 1588 for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++) 1589 caseDesc << "\t- " << getAttributeInfoDescription (attributeInfos[attributeNdx]) << "\n"; 1590 1591 return caseDesc.str(); 1592 } 1593 1594 struct CompatibleFormats 1595 { 1596 VertexInputTest::GlslType glslType; 1597 std::vector<VkFormat> compatibleVkFormats; 1598 }; 1599 1600 void createSingleAttributeCases (tcu::TestCaseGroup* singleAttributeTests, VertexInputTest::GlslType glslType) 1601 { 1602 const VkFormat vertexFormats[] = 1603 { 1604 // Required, unpacked 1605 VK_FORMAT_R8_UNORM, 1606 VK_FORMAT_R8_SNORM, 1607 VK_FORMAT_R8_UINT, 1608 VK_FORMAT_R8_SINT, 1609 VK_FORMAT_R8G8_UNORM, 1610 VK_FORMAT_R8G8_SNORM, 1611 VK_FORMAT_R8G8_UINT, 1612 VK_FORMAT_R8G8_SINT, 1613 VK_FORMAT_R8G8B8A8_UNORM, 1614 VK_FORMAT_R8G8B8A8_SNORM, 1615 VK_FORMAT_R8G8B8A8_UINT, 1616 VK_FORMAT_R8G8B8A8_SINT, 1617 VK_FORMAT_B8G8R8A8_UNORM, 1618 VK_FORMAT_R16_UNORM, 1619 VK_FORMAT_R16_SNORM, 1620 VK_FORMAT_R16_UINT, 1621 VK_FORMAT_R16_SINT, 1622 VK_FORMAT_R16_SFLOAT, 1623 VK_FORMAT_R16G16_UNORM, 1624 VK_FORMAT_R16G16_SNORM, 1625 VK_FORMAT_R16G16_UINT, 1626 VK_FORMAT_R16G16_SINT, 1627 VK_FORMAT_R16G16_SFLOAT, 1628 VK_FORMAT_R16G16B16A16_UNORM, 1629 VK_FORMAT_R16G16B16A16_SNORM, 1630 VK_FORMAT_R16G16B16A16_UINT, 1631 VK_FORMAT_R16G16B16A16_SINT, 1632 VK_FORMAT_R16G16B16A16_SFLOAT, 1633 VK_FORMAT_R32_UINT, 1634 VK_FORMAT_R32_SINT, 1635 VK_FORMAT_R32_SFLOAT, 1636 VK_FORMAT_R32G32_UINT, 1637 VK_FORMAT_R32G32_SINT, 1638 VK_FORMAT_R32G32_SFLOAT, 1639 VK_FORMAT_R32G32B32_UINT, 1640 VK_FORMAT_R32G32B32_SINT, 1641 VK_FORMAT_R32G32B32_SFLOAT, 1642 VK_FORMAT_R32G32B32A32_UINT, 1643 VK_FORMAT_R32G32B32A32_SINT, 1644 VK_FORMAT_R32G32B32A32_SFLOAT, 1645 1646 // Scaled formats 1647 VK_FORMAT_R8G8_USCALED, 1648 VK_FORMAT_R8G8_SSCALED, 1649 VK_FORMAT_R16_USCALED, 1650 VK_FORMAT_R16_SSCALED, 1651 VK_FORMAT_R8G8B8_USCALED, 1652 VK_FORMAT_R8G8B8_SSCALED, 1653 VK_FORMAT_B8G8R8_USCALED, 1654 VK_FORMAT_B8G8R8_SSCALED, 1655 VK_FORMAT_R8G8B8A8_USCALED, 1656 VK_FORMAT_R8G8B8A8_SSCALED, 1657 VK_FORMAT_B8G8R8A8_USCALED, 1658 VK_FORMAT_B8G8R8A8_SSCALED, 1659 VK_FORMAT_R16G16_USCALED, 1660 VK_FORMAT_R16G16_SSCALED, 1661 VK_FORMAT_R16G16B16_USCALED, 1662 VK_FORMAT_R16G16B16_SSCALED, 1663 VK_FORMAT_R16G16B16A16_USCALED, 1664 VK_FORMAT_R16G16B16A16_SSCALED, 1665 1666 // SRGB formats 1667 VK_FORMAT_R8_SRGB, 1668 VK_FORMAT_R8G8_SRGB, 1669 VK_FORMAT_R8G8B8_SRGB, 1670 VK_FORMAT_B8G8R8_SRGB, 1671 VK_FORMAT_R8G8B8A8_SRGB, 1672 VK_FORMAT_B8G8R8A8_SRGB, 1673 1674 // Double formats 1675 VK_FORMAT_R64_SFLOAT, 1676 VK_FORMAT_R64G64_SFLOAT, 1677 VK_FORMAT_R64G64B64_SFLOAT, 1678 VK_FORMAT_R64G64B64A64_SFLOAT, 1679 }; 1680 1681 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++) 1682 { 1683 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], glslType)) 1684 { 1685 // Create test case for RATE_VERTEX 1686 VertexInputTest::AttributeInfo attributeInfo; 1687 attributeInfo.vkType = vertexFormats[formatNdx]; 1688 attributeInfo.glslType = glslType; 1689 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; 1690 1691 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(), 1692 getAttributeInfoCaseName(attributeInfo), 1693 getAttributeInfoDescription(attributeInfo), 1694 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo), 1695 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, 1696 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); 1697 1698 // Create test case for RATE_INSTANCE 1699 attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; 1700 1701 singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(), 1702 getAttributeInfoCaseName(attributeInfo), 1703 getAttributeInfoDescription(attributeInfo), 1704 std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo), 1705 VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, 1706 VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); 1707 } 1708 } 1709 } 1710 1711 void createSingleAttributeTests (tcu::TestCaseGroup* singleAttributeTests) 1712 { 1713 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++) 1714 { 1715 VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)glslTypeNdx; 1716 addTestGroup(singleAttributeTests, VertexInputTest::s_glslTypeDescriptions[glslType].name, "", createSingleAttributeCases, glslType); 1717 } 1718 } 1719 1720 // Create all unique GlslType combinations recursively 1721 void createMultipleAttributeCases (deUint32 depth, deUint32 firstNdx, CompatibleFormats* compatibleFormats, de::Random& randomFunc, tcu::TestCaseGroup& testGroup, VertexInputTest::BindingMapping bindingMapping, VertexInputTest::AttributeLayout attributeLayout, const std::vector<VertexInputTest::AttributeInfo>& attributeInfos = std::vector<VertexInputTest::AttributeInfo>(0)) 1722 { 1723 tcu::TestContext& testCtx = testGroup.getTestContext(); 1724 1725 // Exclude double values, which are not included in vertexFormats 1726 for (deUint32 currentNdx = firstNdx; currentNdx < VertexInputTest::GLSL_TYPE_DOUBLE - depth; currentNdx++) 1727 { 1728 std::vector <VertexInputTest::AttributeInfo> newAttributeInfos = attributeInfos; 1729 1730 { 1731 VertexInputTest::AttributeInfo attributeInfo; 1732 attributeInfo.glslType = (VertexInputTest::GlslType)currentNdx; 1733 attributeInfo.inputRate = (depth % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; 1734 attributeInfo.vkType = VK_FORMAT_UNDEFINED; 1735 1736 newAttributeInfos.push_back(attributeInfo); 1737 } 1738 1739 // Add test case 1740 if (depth == 0) 1741 { 1742 // Select a random compatible format for each attribute 1743 for (size_t i = 0; i < newAttributeInfos.size(); i++) 1744 { 1745 const std::vector<VkFormat>& formats = compatibleFormats[newAttributeInfos[i].glslType].compatibleVkFormats; 1746 newAttributeInfos[i].vkType = formats[randomFunc.getUint32() % formats.size()]; 1747 } 1748 1749 const std::string caseName = VertexInputTest::s_glslTypeDescriptions[currentNdx].name; 1750 const std::string caseDesc = getAttributeInfosDescription(newAttributeInfos); 1751 1752 testGroup.addChild(new VertexInputTest(testCtx, caseName, caseDesc, newAttributeInfos, bindingMapping, attributeLayout)); 1753 } 1754 // Add test group 1755 else 1756 { 1757 const std::string name = VertexInputTest::s_glslTypeDescriptions[currentNdx].name; 1758 de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, name.c_str(), "")); 1759 1760 createMultipleAttributeCases(depth - 1u, currentNdx + 1u, compatibleFormats, randomFunc, *newTestGroup, bindingMapping, attributeLayout, newAttributeInfos); 1761 testGroup.addChild(newTestGroup.release()); 1762 } 1763 } 1764 } 1765 1766 void createMultipleAttributeTests (tcu::TestCaseGroup* multipleAttributeTests) 1767 { 1768 // Required vertex formats, unpacked 1769 const VkFormat vertexFormats[] = 1770 { 1771 VK_FORMAT_R8_UNORM, 1772 VK_FORMAT_R8_SNORM, 1773 VK_FORMAT_R8_UINT, 1774 VK_FORMAT_R8_SINT, 1775 VK_FORMAT_R8G8_UNORM, 1776 VK_FORMAT_R8G8_SNORM, 1777 VK_FORMAT_R8G8_UINT, 1778 VK_FORMAT_R8G8_SINT, 1779 VK_FORMAT_R8G8B8A8_UNORM, 1780 VK_FORMAT_R8G8B8A8_SNORM, 1781 VK_FORMAT_R8G8B8A8_UINT, 1782 VK_FORMAT_R8G8B8A8_SINT, 1783 VK_FORMAT_B8G8R8A8_UNORM, 1784 VK_FORMAT_R16_UNORM, 1785 VK_FORMAT_R16_SNORM, 1786 VK_FORMAT_R16_UINT, 1787 VK_FORMAT_R16_SINT, 1788 VK_FORMAT_R16_SFLOAT, 1789 VK_FORMAT_R16G16_UNORM, 1790 VK_FORMAT_R16G16_SNORM, 1791 VK_FORMAT_R16G16_UINT, 1792 VK_FORMAT_R16G16_SINT, 1793 VK_FORMAT_R16G16_SFLOAT, 1794 VK_FORMAT_R16G16B16A16_UNORM, 1795 VK_FORMAT_R16G16B16A16_SNORM, 1796 VK_FORMAT_R16G16B16A16_UINT, 1797 VK_FORMAT_R16G16B16A16_SINT, 1798 VK_FORMAT_R16G16B16A16_SFLOAT, 1799 VK_FORMAT_R32_UINT, 1800 VK_FORMAT_R32_SINT, 1801 VK_FORMAT_R32_SFLOAT, 1802 VK_FORMAT_R32G32_UINT, 1803 VK_FORMAT_R32G32_SINT, 1804 VK_FORMAT_R32G32_SFLOAT, 1805 VK_FORMAT_R32G32B32_UINT, 1806 VK_FORMAT_R32G32B32_SINT, 1807 VK_FORMAT_R32G32B32_SFLOAT, 1808 VK_FORMAT_R32G32B32A32_UINT, 1809 VK_FORMAT_R32G32B32A32_SINT, 1810 VK_FORMAT_R32G32B32A32_SFLOAT 1811 }; 1812 1813 // Find compatible VK formats for each GLSL vertex type 1814 CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT]; 1815 { 1816 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++) 1817 { 1818 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++) 1819 { 1820 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx)) 1821 compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]); 1822 } 1823 } 1824 } 1825 1826 de::Random randomFunc(102030); 1827 tcu::TestContext& testCtx = multipleAttributeTests->getTestContext(); 1828 de::MovePtr<tcu::TestCaseGroup> oneToOneAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", "")); 1829 de::MovePtr<tcu::TestCaseGroup> oneToManyAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", "")); 1830 de::MovePtr<tcu::TestCaseGroup> oneToManySequentialAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes_sequential", "")); 1831 1832 createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToOneAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED); 1833 createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManyAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED); 1834 createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManySequentialAttributeTests, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL); 1835 1836 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding")); 1837 bindingOneToOneTests->addChild(oneToOneAttributeTests.release()); 1838 multipleAttributeTests->addChild(bindingOneToOneTests.release()); 1839 1840 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding")); 1841 bindingOneToManyTests->addChild(oneToManyAttributeTests.release()); 1842 bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release()); 1843 multipleAttributeTests->addChild(bindingOneToManyTests.release()); 1844 } 1845 1846 void createMaxAttributeTests (tcu::TestCaseGroup* maxAttributeTests) 1847 { 1848 // Required vertex formats, unpacked 1849 const VkFormat vertexFormats[] = 1850 { 1851 VK_FORMAT_R8_UNORM, 1852 VK_FORMAT_R8_SNORM, 1853 VK_FORMAT_R8_UINT, 1854 VK_FORMAT_R8_SINT, 1855 VK_FORMAT_R8G8_UNORM, 1856 VK_FORMAT_R8G8_SNORM, 1857 VK_FORMAT_R8G8_UINT, 1858 VK_FORMAT_R8G8_SINT, 1859 VK_FORMAT_R8G8B8A8_UNORM, 1860 VK_FORMAT_R8G8B8A8_SNORM, 1861 VK_FORMAT_R8G8B8A8_UINT, 1862 VK_FORMAT_R8G8B8A8_SINT, 1863 VK_FORMAT_B8G8R8A8_UNORM, 1864 VK_FORMAT_R16_UNORM, 1865 VK_FORMAT_R16_SNORM, 1866 VK_FORMAT_R16_UINT, 1867 VK_FORMAT_R16_SINT, 1868 VK_FORMAT_R16_SFLOAT, 1869 VK_FORMAT_R16G16_UNORM, 1870 VK_FORMAT_R16G16_SNORM, 1871 VK_FORMAT_R16G16_UINT, 1872 VK_FORMAT_R16G16_SINT, 1873 VK_FORMAT_R16G16_SFLOAT, 1874 VK_FORMAT_R16G16B16A16_UNORM, 1875 VK_FORMAT_R16G16B16A16_SNORM, 1876 VK_FORMAT_R16G16B16A16_UINT, 1877 VK_FORMAT_R16G16B16A16_SINT, 1878 VK_FORMAT_R16G16B16A16_SFLOAT, 1879 VK_FORMAT_R32_UINT, 1880 VK_FORMAT_R32_SINT, 1881 VK_FORMAT_R32_SFLOAT, 1882 VK_FORMAT_R32G32_UINT, 1883 VK_FORMAT_R32G32_SINT, 1884 VK_FORMAT_R32G32_SFLOAT, 1885 VK_FORMAT_R32G32B32_UINT, 1886 VK_FORMAT_R32G32B32_SINT, 1887 VK_FORMAT_R32G32B32_SFLOAT, 1888 VK_FORMAT_R32G32B32A32_UINT, 1889 VK_FORMAT_R32G32B32A32_SINT, 1890 VK_FORMAT_R32G32B32A32_SFLOAT 1891 }; 1892 1893 // VkPhysicalDeviceLimits::maxVertexInputAttributes is used when attributeCount is 0 1894 const deUint32 attributeCount[] = { 16, 32, 64, 128, 0 }; 1895 tcu::TestContext& testCtx (maxAttributeTests->getTestContext()); 1896 de::Random randomFunc (132030); 1897 1898 // Find compatible VK formats for each GLSL vertex type 1899 CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT]; 1900 { 1901 for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++) 1902 { 1903 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++) 1904 { 1905 if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx)) 1906 compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]); 1907 } 1908 } 1909 } 1910 1911 for (deUint32 attributeCountNdx = 0; attributeCountNdx < DE_LENGTH_OF_ARRAY(attributeCount); attributeCountNdx++) 1912 { 1913 const std::string groupName = (attributeCount[attributeCountNdx] == 0 ? "query_max" : de::toString(attributeCount[attributeCountNdx])) + "_attributes"; 1914 const std::string groupDesc = de::toString(attributeCount[attributeCountNdx]) + " vertex input attributes"; 1915 1916 de::MovePtr<tcu::TestCaseGroup> numAttributeTests(new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str())); 1917 de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding")); 1918 de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding")); 1919 1920 std::vector<VertexInputTest::AttributeInfo> attributeInfos(attributeCount[attributeCountNdx]); 1921 1922 for (deUint32 attributeNdx = 0; attributeNdx < attributeCount[attributeCountNdx]; attributeNdx++) 1923 { 1924 // Use random glslTypes, each consuming one attribute location 1925 const VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)(randomFunc.getUint32() % VertexInputTest::GLSL_TYPE_MAT2); 1926 const std::vector<VkFormat>& formats = compatibleFormats[glslType].compatibleVkFormats; 1927 const VkFormat format = formats[randomFunc.getUint32() % formats.size()]; 1928 1929 attributeInfos[attributeNdx].glslType = glslType; 1930 attributeInfos[attributeNdx].inputRate = ((attributeCountNdx + attributeNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE; 1931 attributeInfos[attributeNdx].vkType = format; 1932 } 1933 1934 bindingOneToOneTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); 1935 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED)); 1936 bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "sequential", "Sequential attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL)); 1937 1938 numAttributeTests->addChild(bindingOneToOneTests.release()); 1939 numAttributeTests->addChild(bindingOneToManyTests.release()); 1940 maxAttributeTests->addChild(numAttributeTests.release()); 1941 } 1942 } 1943 1944 } // anonymous 1945 1946 void createVertexInputTests (tcu::TestCaseGroup* vertexInputTests) 1947 { 1948 addTestGroup(vertexInputTests, "single_attribute", "Uses one attribute", createSingleAttributeTests); 1949 addTestGroup(vertexInputTests, "multiple_attributes", "Uses more than one attribute", createMultipleAttributeTests); 1950 addTestGroup(vertexInputTests, "max_attributes", "Implementations can use as many vertex input attributes as they advertise", createMaxAttributeTests); 1951 } 1952 1953 } // pipeline 1954 } // vkt 1955