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