1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2016 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 Robust Vertex Buffer Access Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktRobustnessVertexAccessTests.hpp" 26 #include "vktRobustnessUtil.hpp" 27 #include "vktTestCaseUtil.hpp" 28 #include "vkBuilderUtil.hpp" 29 #include "vkImageUtil.hpp" 30 #include "vkMemUtil.hpp" 31 #include "vkPrograms.hpp" 32 #include "vkQueryUtil.hpp" 33 #include "vkRef.hpp" 34 #include "vkRefUtil.hpp" 35 #include "vkTypeUtil.hpp" 36 #include "tcuTestLog.hpp" 37 #include "deMath.h" 38 #include "deUniquePtr.hpp" 39 #include <vector> 40 41 namespace vkt 42 { 43 namespace robustness 44 { 45 46 using namespace vk; 47 48 typedef std::vector<VkVertexInputBindingDescription> BindingList; 49 typedef std::vector<VkVertexInputAttributeDescription> AttributeList; 50 51 class VertexAccessTest : public vkt::TestCase 52 { 53 public: 54 VertexAccessTest (tcu::TestContext& testContext, 55 const std::string& name, 56 const std::string& description, 57 VkFormat inputFormat, 58 deUint32 numVertexValues, 59 deUint32 numInstanceValues, 60 deUint32 numVertices, 61 deUint32 numInstances); 62 63 virtual ~VertexAccessTest (void) {} 64 65 void initPrograms (SourceCollections& programCollection) const; 66 TestInstance* createInstance (Context& context) const = 0; 67 68 protected: 69 const VkFormat m_inputFormat; 70 const deUint32 m_numVertexValues; 71 const deUint32 m_numInstanceValues; 72 const deUint32 m_numVertices; 73 const deUint32 m_numInstances; 74 75 }; 76 77 class DrawAccessTest : public VertexAccessTest 78 { 79 public: 80 DrawAccessTest (tcu::TestContext& testContext, 81 const std::string& name, 82 const std::string& description, 83 VkFormat inputFormat, 84 deUint32 numVertexValues, 85 deUint32 numInstanceValues, 86 deUint32 numVertices, 87 deUint32 numInstances); 88 89 virtual ~DrawAccessTest (void) {} 90 TestInstance* createInstance (Context& context) const; 91 92 protected: 93 }; 94 95 class DrawIndexedAccessTest : public VertexAccessTest 96 { 97 public: 98 enum IndexConfig 99 { 100 INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS, 101 INDEX_CONFIG_INDICES_OUT_OF_BOUNDS, 102 INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS, 103 104 INDEX_CONFIG_COUNT 105 }; 106 107 const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT]; 108 109 DrawIndexedAccessTest (tcu::TestContext& testContext, 110 const std::string& name, 111 const std::string& description, 112 VkFormat inputFormat, 113 IndexConfig indexConfig); 114 115 virtual ~DrawIndexedAccessTest (void) {} 116 TestInstance* createInstance (Context& context) const; 117 118 protected: 119 const IndexConfig m_indexConfig; 120 }; 121 122 class VertexAccessInstance : public vkt::TestInstance 123 { 124 public: 125 VertexAccessInstance (Context& context, 126 Move<VkDevice> device, 127 VkFormat inputFormat, 128 deUint32 numVertexValues, 129 deUint32 numInstanceValues, 130 deUint32 numVertices, 131 deUint32 numInstances, 132 const std::vector<deUint32>& indices); 133 134 virtual ~VertexAccessInstance (void) {} 135 virtual tcu::TestStatus iterate (void); 136 virtual bool verifyResult (void); 137 138 private: 139 bool isValueWithinVertexBufferOrZero (void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa); 140 141 protected: 142 static bool isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value); 143 static VkDeviceSize getBufferSizeInBytes (deUint32 numScalars, VkFormat format); 144 145 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount) = 0; 146 virtual deUint32 getIndex (deUint32 vertexNum) const = 0; 147 148 Move<VkDevice> m_device; 149 150 const VkFormat m_inputFormat; 151 const deUint32 m_numVertexValues; 152 const deUint32 m_numInstanceValues; 153 const deUint32 m_numVertices; 154 const deUint32 m_numInstances; 155 AttributeList m_vertexInputAttributes; 156 BindingList m_vertexInputBindings; 157 158 Move<VkBuffer> m_vertexRateBuffer; 159 VkDeviceSize m_vertexRateBufferSize; 160 de::MovePtr<Allocation> m_vertexRateBufferAlloc; 161 VkDeviceSize m_vertexRateBufferAllocSize; 162 163 Move<VkBuffer> m_instanceRateBuffer; 164 VkDeviceSize m_instanceRateBufferSize; 165 de::MovePtr<Allocation> m_instanceRateBufferAlloc; 166 VkDeviceSize m_instanceRateBufferAllocSize; 167 168 Move<VkBuffer> m_vertexNumBuffer; 169 VkDeviceSize m_vertexNumBufferSize; 170 de::MovePtr<Allocation> m_vertexNumBufferAlloc; 171 172 Move<VkBuffer> m_indexBuffer; 173 VkDeviceSize m_indexBufferSize; 174 de::MovePtr<Allocation> m_indexBufferAlloc; 175 176 Move<VkBuffer> m_outBuffer; // SSBO 177 VkDeviceSize m_outBufferSize; 178 de::MovePtr<Allocation> m_outBufferAlloc; 179 180 Move<VkDescriptorPool> m_descriptorPool; 181 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 182 Move<VkDescriptorSet> m_descriptorSet; 183 184 Move<VkFence> m_fence; 185 VkQueue m_queue; 186 187 de::MovePtr<GraphicsEnvironment> m_graphicsTestEnvironment; 188 }; 189 190 class DrawAccessInstance : public VertexAccessInstance 191 { 192 public: 193 DrawAccessInstance (Context& context, 194 Move<VkDevice> device, 195 VkFormat inputFormat, 196 deUint32 numVertexValues, 197 deUint32 numInstanceValues, 198 deUint32 numVertices, 199 deUint32 numInstances); 200 201 virtual ~DrawAccessInstance (void) {} 202 203 protected: 204 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount); 205 virtual deUint32 getIndex (deUint32 vertexNum) const; 206 }; 207 208 class DrawIndexedAccessInstance : public VertexAccessInstance 209 { 210 public: 211 DrawIndexedAccessInstance (Context& context, 212 Move<VkDevice> device, 213 VkFormat inputFormat, 214 deUint32 numVertexValues, 215 deUint32 numInstanceValues, 216 deUint32 numVertices, 217 deUint32 numInstances, 218 const std::vector<deUint32>& indices); 219 220 virtual ~DrawIndexedAccessInstance (void) {} 221 222 protected: 223 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount); 224 virtual deUint32 getIndex (deUint32 vertexNum) const; 225 226 const std::vector<deUint32> m_indices; 227 }; 228 229 // VertexAccessTest 230 231 VertexAccessTest::VertexAccessTest (tcu::TestContext& testContext, 232 const std::string& name, 233 const std::string& description, 234 VkFormat inputFormat, 235 deUint32 numVertexValues, 236 deUint32 numInstanceValues, 237 deUint32 numVertices, 238 deUint32 numInstances) 239 240 : vkt::TestCase (testContext, name, description) 241 , m_inputFormat (inputFormat) 242 , m_numVertexValues (numVertexValues) 243 , m_numInstanceValues (numInstanceValues) 244 , m_numVertices (numVertices) 245 , m_numInstances (numInstances) 246 { 247 } 248 249 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const 250 { 251 std::ostringstream attributeDeclaration; 252 std::ostringstream attributeUse; 253 254 std::ostringstream vertexShaderSource; 255 std::ostringstream fragmentShaderSource; 256 257 std::ostringstream attributeTypeStr; 258 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order); 259 const deUint32 numScalarsPerVertex = numChannels * 3; // Use 3 identical attributes 260 deUint32 numValues = 0; 261 262 if (numChannels == 1) 263 { 264 if (isUintFormat(m_inputFormat)) 265 attributeTypeStr << "uint"; 266 else if (isIntFormat(m_inputFormat)) 267 attributeTypeStr << "int"; 268 else 269 attributeTypeStr << "float"; 270 } 271 else 272 { 273 if (isUintFormat(m_inputFormat)) 274 attributeTypeStr << "uvec"; 275 else if (isIntFormat(m_inputFormat)) 276 attributeTypeStr << "ivec"; 277 else 278 attributeTypeStr << "vec"; 279 280 attributeTypeStr << numChannels; 281 } 282 283 for (int attrNdx = 0; attrNdx < 3; attrNdx++) 284 { 285 attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n"; 286 287 for (int chanNdx = 0; chanNdx < numChannels; chanNdx++) 288 { 289 attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices 290 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx; 291 292 if (numChannels == 1) 293 attributeUse << ";\n"; 294 else 295 attributeUse << "[" << chanNdx << "];\n"; 296 } 297 } 298 299 attributeDeclaration << "layout(location = 3) in int vertexNum;\n"; 300 301 attributeUse << "\n"; 302 303 const char *outType = ""; 304 if (isUintFormat(m_inputFormat)) 305 outType = "uint"; 306 else if (isIntFormat(m_inputFormat)) 307 outType = "int"; 308 else 309 outType = "float"; 310 311 vertexShaderSource << 312 "#version 310 es\n" 313 "precision highp float;\n" 314 << attributeDeclaration.str() << 315 "layout(set = 0, binding = 0, std430) buffer outBuffer\n" 316 "{\n" 317 "\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n" 318 "};\n\n" 319 "void main (void)\n" 320 "{\n" 321 << attributeUse.str() << 322 "\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 323 "}\n"; 324 325 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str()); 326 327 fragmentShaderSource << 328 "#version 310 es\n" 329 "precision highp float;\n" 330 "layout(location = 0) out vec4 fragColor;\n" 331 "void main (void)\n" 332 "{\n" 333 "\tfragColor = vec4(1.0);\n" 334 "}\n"; 335 336 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str()); 337 } 338 339 // DrawAccessTest 340 341 DrawAccessTest::DrawAccessTest (tcu::TestContext& testContext, 342 const std::string& name, 343 const std::string& description, 344 VkFormat inputFormat, 345 deUint32 numVertexValues, 346 deUint32 numInstanceValues, 347 deUint32 numVertices, 348 deUint32 numInstances) 349 350 : VertexAccessTest (testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances) 351 { 352 } 353 354 TestInstance* DrawAccessTest::createInstance (Context& context) const 355 { 356 Move<VkDevice> device = createRobustBufferAccessDevice(context); 357 358 return new DrawAccessInstance(context, 359 device, 360 m_inputFormat, 361 m_numVertexValues, 362 m_numInstanceValues, 363 m_numVertices, 364 m_numInstances); 365 } 366 367 // DrawIndexedAccessTest 368 369 const deUint32 lastIndexOutOfBounds[] = 370 { 371 0, 1, 2, 3, 4, 100, // Indices of 100 and above are out of bounds 372 }; 373 const deUint32 indicesOutOfBounds[] = 374 { 375 0, 100, 2, 101, 3, 102, // Indices of 100 and above are out of bounds 376 }; 377 const deUint32 triangleOutOfBounds[] = 378 { 379 100, 101, 102, 3, 4, 5, // Indices of 100 and above are out of bounds 380 }; 381 382 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] = 383 { 384 std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)), 385 std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)), 386 std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)), 387 }; 388 389 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext& testContext, 390 const std::string& name, 391 const std::string& description, 392 VkFormat inputFormat, 393 IndexConfig indexConfig) 394 395 : VertexAccessTest (testContext, 396 name, 397 description, 398 inputFormat, 399 getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2, // numVertexValues 400 getNumUsedChannels(mapVkFormat(inputFormat).order), // numInstanceValues 401 (deUint32)s_indexConfigs[indexConfig].size(), // numVertices 402 1) // numInstances 403 , m_indexConfig (indexConfig) 404 { 405 } 406 407 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const 408 { 409 Move<VkDevice> device = createRobustBufferAccessDevice(context); 410 411 return new DrawIndexedAccessInstance(context, 412 device, 413 m_inputFormat, 414 m_numVertexValues, 415 m_numInstanceValues, 416 m_numVertices, 417 m_numInstances, 418 s_indexConfigs[m_indexConfig]); 419 } 420 421 // VertexAccessInstance 422 423 VertexAccessInstance::VertexAccessInstance (Context& context, 424 Move<VkDevice> device, 425 VkFormat inputFormat, 426 deUint32 numVertexValues, 427 deUint32 numInstanceValues, 428 deUint32 numVertices, 429 deUint32 numInstances, 430 const std::vector<deUint32>& indices) 431 432 : vkt::TestInstance (context) 433 , m_device (device) 434 , m_inputFormat (inputFormat) 435 , m_numVertexValues (numVertexValues) 436 , m_numInstanceValues (numInstanceValues) 437 , m_numVertices (numVertices) 438 , m_numInstances (numInstances) 439 { 440 const DeviceInterface& vk = context.getDeviceInterface(); 441 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 442 SimpleAllocator memAlloc (vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 443 const deUint32 formatSizeInBytes = tcu::getPixelSize(mapVkFormat(m_inputFormat)); 444 445 // Check storage support 446 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics) 447 { 448 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage"); 449 } 450 451 const VkVertexInputAttributeDescription attributes[] = 452 { 453 // input rate: vertex 454 { 455 0u, // deUint32 location; 456 0u, // deUint32 binding; 457 m_inputFormat, // VkFormat format; 458 0u, // deUint32 offset; 459 }, 460 { 461 1u, // deUint32 location; 462 0u, // deUint32 binding; 463 m_inputFormat, // VkFormat format; 464 formatSizeInBytes, // deUint32 offset; 465 }, 466 467 // input rate: instance 468 { 469 2u, // deUint32 location; 470 1u, // deUint32 binding; 471 m_inputFormat, // VkFormat format; 472 0u, // deUint32 offset; 473 }, 474 475 // Attribute for vertex number 476 { 477 3u, // deUint32 location; 478 2u, // deUint32 binding; 479 VK_FORMAT_R32_SINT, // VkFormat format; 480 0, // deUint32 offset; 481 }, 482 }; 483 484 const VkVertexInputBindingDescription bindings[] = 485 { 486 { 487 0u, // deUint32 binding; 488 formatSizeInBytes * 2, // deUint32 stride; 489 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; 490 }, 491 { 492 1u, // deUint32 binding; 493 formatSizeInBytes, // deUint32 stride; 494 VK_VERTEX_INPUT_RATE_INSTANCE // VkVertexInputRate inputRate; 495 }, 496 { 497 2u, // deUint32 binding; 498 sizeof(deInt32), // deUint32 stride; 499 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; 500 }, 501 }; 502 503 m_vertexInputBindings = std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)); 504 m_vertexInputAttributes = std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)); 505 506 // Create vertex buffer for vertex input rate 507 { 508 VkMemoryRequirements bufferMemoryReqs; 509 510 m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based. 511 512 const VkBufferCreateInfo vertexRateBufferParams = 513 { 514 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 515 DE_NULL, // const void* pNext; 516 0u, // VkBufferCreateFlags flags; 517 m_vertexRateBufferSize, // VkDeviceSize size; 518 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 519 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 520 1u, // deUint32 queueFamilyIndexCount; 521 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 522 }; 523 524 m_vertexRateBuffer = createBuffer(vk, *m_device, &vertexRateBufferParams); 525 bufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer); 526 m_vertexRateBufferAllocSize = bufferMemoryReqs.size; 527 m_vertexRateBufferAlloc = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible); 528 529 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset())); 530 populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat); 531 flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE); 532 } 533 534 // Create vertex buffer for instance input rate 535 { 536 VkMemoryRequirements bufferMemoryReqs; 537 538 m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based. 539 540 const VkBufferCreateInfo instanceRateBufferParams = 541 { 542 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 543 DE_NULL, // const void* pNext; 544 0u, // VkBufferCreateFlags flags; 545 m_instanceRateBufferSize, // VkDeviceSize size; 546 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 547 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 548 1u, // deUint32 queueFamilyIndexCount; 549 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 550 }; 551 552 m_instanceRateBuffer = createBuffer(vk, *m_device, &instanceRateBufferParams); 553 bufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer); 554 m_instanceRateBufferAllocSize = bufferMemoryReqs.size; 555 m_instanceRateBufferAlloc = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible); 556 557 VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset())); 558 populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat); 559 flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE); 560 } 561 562 // Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1) 563 { 564 m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127). 565 566 const VkBufferCreateInfo vertexNumBufferParams = 567 { 568 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 569 DE_NULL, // const void* pNext; 570 0u, // VkBufferCreateFlags flags; 571 m_vertexNumBufferSize, // VkDeviceSize size; 572 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 573 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 574 1u, // deUint32 queueFamilyIndexCount; 575 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 576 }; 577 578 m_vertexNumBuffer = createBuffer(vk, *m_device, &vertexNumBufferParams); 579 m_vertexNumBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible); 580 581 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset())); 582 } 583 584 // Create index buffer if required 585 if (!indices.empty()) 586 { 587 m_indexBufferSize = sizeof(deUint32) * indices.size(); 588 589 const VkBufferCreateInfo indexBufferParams = 590 { 591 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 592 DE_NULL, // const void* pNext; 593 0u, // VkBufferCreateFlags flags; 594 m_indexBufferSize, // VkDeviceSize size; 595 VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage; 596 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 597 1u, // deUint32 queueFamilyIndexCount; 598 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 599 }; 600 601 m_indexBuffer = createBuffer(vk, *m_device, &indexBufferParams); 602 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible); 603 604 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset())); 605 deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize); 606 flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE); 607 } 608 609 // Create result ssbo 610 { 611 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order); 612 613 m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT); 614 615 const VkBufferCreateInfo outBufferParams = 616 { 617 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 618 DE_NULL, // const void* pNext; 619 0u, // VkBufferCreateFlags flags; 620 m_outBufferSize, // VkDeviceSize size; 621 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage; 622 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 623 1u, // deUint32 queueFamilyIndexCount; 624 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 625 }; 626 627 m_outBuffer = createBuffer(vk, *m_device, &outBufferParams); 628 m_outBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_outBuffer), MemoryRequirement::HostVisible); 629 630 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset())); 631 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize); 632 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE); 633 } 634 635 // Create descriptor set data 636 { 637 DescriptorPoolBuilder descriptorPoolBuilder; 638 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u); 639 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 640 641 DescriptorSetLayoutBuilder setLayoutBuilder; 642 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); 643 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device); 644 645 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = 646 { 647 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; 648 DE_NULL, // const void* pNext; 649 *m_descriptorPool, // VkDescriptorPool desciptorPool; 650 1u, // deUint32 setLayoutCount; 651 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts; 652 }; 653 654 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo); 655 656 const VkDescriptorBufferInfo outBufferDescriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE); 657 658 DescriptorSetUpdateBuilder setUpdateBuilder; 659 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo); 660 setUpdateBuilder.update(vk, *m_device); 661 } 662 663 // Create fence 664 { 665 const VkFenceCreateInfo fenceParams = 666 { 667 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 668 DE_NULL, // const void* pNext; 669 0u // VkFenceCreateFlags flags; 670 }; 671 672 m_fence = createFence(vk, *m_device, &fenceParams); 673 } 674 675 // Get queue 676 vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue); 677 678 // Setup graphics test environment 679 { 680 GraphicsEnvironment::DrawConfig drawConfig; 681 682 drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer); 683 drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer); 684 drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer); 685 686 drawConfig.vertexCount = m_numVertices; 687 drawConfig.instanceCount = m_numInstances; 688 drawConfig.indexBuffer = *m_indexBuffer; 689 drawConfig.indexCount = (deUint32)(m_indexBufferSize / sizeof(deUint32)); 690 691 m_graphicsTestEnvironment = de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context, 692 *m_device, 693 *m_descriptorSetLayout, 694 *m_descriptorSet, 695 GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)), 696 GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)), 697 drawConfig)); 698 } 699 } 700 701 tcu::TestStatus VertexAccessInstance::iterate (void) 702 { 703 const DeviceInterface& vk = m_context.getDeviceInterface(); 704 const vk::VkCommandBuffer cmdBuffer = m_graphicsTestEnvironment->getCommandBuffer(); 705 706 // Initialize vertex ids 707 { 708 deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr()); 709 deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize); 710 711 initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32))); 712 713 flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE); 714 } 715 716 // Submit command buffer 717 { 718 const VkSubmitInfo submitInfo = 719 { 720 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 721 DE_NULL, // const void* pNext; 722 0u, // deUint32 waitSemaphoreCount; 723 DE_NULL, // const VkSemaphore* pWaitSemaphores; 724 DE_NULL, // const VkPIpelineStageFlags* pWaitDstStageMask; 725 1u, // deUint32 commandBufferCount; 726 &cmdBuffer, // const VkCommandBuffer* pCommandBuffers; 727 0u, // deUint32 signalSemaphoreCount; 728 DE_NULL // const VkSemaphore* pSignalSemaphores; 729 }; 730 731 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get())); 732 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence)); 733 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */)); 734 } 735 736 // Prepare result buffer for read 737 { 738 const VkMappedMemoryRange outBufferRange = 739 { 740 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 741 DE_NULL, // const void* pNext; 742 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem; 743 0ull, // VkDeviceSize offset; 744 m_outBufferSize, // VkDeviceSize size; 745 }; 746 747 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange)); 748 } 749 750 if (verifyResult()) 751 return tcu::TestStatus::pass("All values OK"); 752 else 753 return tcu::TestStatus::fail("Invalid value(s) found"); 754 } 755 756 bool VertexAccessInstance::verifyResult (void) 757 { 758 std::ostringstream logMsg; 759 const DeviceInterface& vk = m_context.getDeviceInterface(); 760 tcu::TestLog& log = m_context.getTestContext().getLog(); 761 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order); 762 const deUint32 numScalarsPerVertex = numChannels * 3; // Use 3 identical attributes 763 void* outDataPtr = m_outBufferAlloc->getHostPtr(); 764 const deUint32 outValueSize = sizeof(deUint32); 765 bool allOk = true; 766 767 const VkMappedMemoryRange outBufferRange = 768 { 769 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType; 770 DE_NULL, // const void* pNext; 771 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem; 772 m_outBufferAlloc->getOffset(), // VkDeviceSize offset; 773 m_outBufferSize, // VkDeviceSize size; 774 }; 775 776 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange)); 777 778 for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++) 779 { 780 deUint32 numInBufferValues; 781 void* inBufferPtr; 782 VkDeviceSize inBufferAllocSize; 783 deUint32 inBufferValueIndex; 784 bool isOutOfBoundsAccess = false; 785 const deUint32 attributeIndex = (valueNdx / numChannels) % 3; 786 const deUint32* outValuePtr = (deUint32*)outDataPtr + valueNdx; 787 788 if (attributeIndex == 2) 789 { 790 // Instance rate 791 const deUint32 elementIndex = valueNdx / (numScalarsPerVertex * m_numVertices); // instance id 792 793 numInBufferValues = m_numInstanceValues; 794 inBufferPtr = m_instanceRateBufferAlloc->getHostPtr(); 795 inBufferAllocSize = m_instanceRateBufferAllocSize; 796 inBufferValueIndex = (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels); 797 } 798 else 799 { 800 // Vertex rate 801 const deUint32 vertexNdx = valueNdx / numScalarsPerVertex; 802 const deUint32 instanceNdx = vertexNdx / m_numVertices; 803 const deUint32 elementIndex = valueNdx / numScalarsPerVertex; // vertex id 804 805 numInBufferValues = m_numVertexValues; 806 inBufferPtr = m_vertexRateBufferAlloc->getHostPtr(); 807 inBufferAllocSize = m_vertexRateBufferAllocSize; 808 inBufferValueIndex = (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2); 809 810 // Binding 0 contains two attributes, so bounds checking for attribute 0 must also consider attribute 1 to determine if the binding is out of bounds. 811 if ((attributeIndex == 0) && (numInBufferValues >= numChannels)) 812 numInBufferValues -= numChannels; 813 } 814 815 isOutOfBoundsAccess = (inBufferValueIndex >= numInBufferValues); 816 817 const deInt32 distanceToOutOfBounds = (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex); 818 819 if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16)) 820 isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues); 821 822 // Log value information 823 { 824 // Vertex separator 825 if (valueNdx && valueNdx % numScalarsPerVertex == 0) 826 logMsg << "\n"; 827 828 logMsg << "\n" << valueNdx << ": Value "; 829 830 // Result index and value 831 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 832 logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4); 833 else 834 logValue(logMsg, outValuePtr, m_inputFormat, 4); 835 836 // Attribute name 837 logMsg << "\tfrom attr" << attributeIndex; 838 if (numChannels > 1) 839 logMsg << "[" << valueNdx % numChannels << "]"; 840 841 // Input rate 842 if (attributeIndex == 2) 843 logMsg << "\tinstance rate"; 844 else 845 logMsg << "\tvertex rate"; 846 } 847 848 if (isOutOfBoundsAccess) 849 { 850 const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex); 851 852 logMsg << "\t(out of bounds)"; 853 854 if (!isValidValue) 855 { 856 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1, 857 // or the maximum representable positive integer value (if the format is integer-based). 858 859 const bool canMatchVec4Pattern = ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32); 860 bool matchesVec4Pattern = false; 861 862 if (canMatchVec4Pattern) 863 { 864 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 865 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr, m_inputFormat); 866 else 867 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr - 3, m_inputFormat); 868 } 869 870 if (!canMatchVec4Pattern || !matchesVec4Pattern) 871 { 872 logMsg << ", Failed: expected a value within the buffer range or 0"; 873 874 if (canMatchVec4Pattern) 875 logMsg << ", or the [0, 0, 0, x] pattern"; 876 877 allOk = false; 878 } 879 } 880 } 881 else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr)) 882 { 883 logMsg << ", Failed: unexpected value"; 884 allOk = false; 885 } 886 } 887 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage; 888 889 return allOk; 890 } 891 892 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex) 893 { 894 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 895 { 896 const float normValue = *reinterpret_cast<const float*>(value); 897 const deUint32 scalarIndex = valueIndex % 4; 898 const bool isAlpha = (scalarIndex == 3); 899 deUint32 encodedValue; 900 901 if (isAlpha) 902 encodedValue = deMin32(deUint32(normValue * 0x3u), 0x3u); 903 else 904 encodedValue = deMin32(deUint32(normValue * 0x3FFu), 0x3FFu); 905 906 if (encodedValue == 0) 907 return true; 908 909 for (deUint32 i = 0; i < vertexBufferSize / 4; i++) 910 { 911 const deUint32 packedValue = reinterpret_cast<deUint32*>(vertexBuffer)[i]; 912 deUint32 unpackedValue; 913 914 if (scalarIndex < 3) 915 unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu; 916 else 917 unpackedValue = (packedValue >> 30) & 0x3u; 918 919 if (unpackedValue == encodedValue) 920 return true; 921 } 922 923 return false; 924 } 925 else 926 { 927 return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32)); 928 } 929 } 930 931 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value) 932 { 933 if (isUintFormat(vertexFormat)) 934 { 935 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer); 936 937 return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value); 938 } 939 else if (isIntFormat(vertexFormat)) 940 { 941 const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer); 942 943 return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value); 944 } 945 else if (isFloatFormat(vertexFormat)) 946 { 947 const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer); 948 949 return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value)); 950 } 951 else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 952 { 953 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer); 954 const deUint32 packedValue = bufferPtr[vertexIndex / 4]; 955 const deUint32 scalarIndex = vertexIndex % 4; 956 float normValue; 957 958 if (scalarIndex < 3) 959 normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu; 960 else 961 normValue = float(packedValue >> 30) / 0x3u; 962 963 return areEqual(normValue, *reinterpret_cast<const float *>(value)); 964 } 965 966 DE_ASSERT(false); 967 return false; 968 } 969 970 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format) 971 { 972 if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format)) 973 { 974 return numScalars * 4; 975 } 976 else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) 977 { 978 DE_ASSERT(numScalars % 4 == 0); 979 return numScalars; 980 } 981 982 DE_ASSERT(false); 983 return 0; 984 } 985 986 // DrawAccessInstance 987 988 DrawAccessInstance::DrawAccessInstance (Context& context, 989 Move<VkDevice> device, 990 VkFormat inputFormat, 991 deUint32 numVertexValues, 992 deUint32 numInstanceValues, 993 deUint32 numVertices, 994 deUint32 numInstances) 995 : VertexAccessInstance (context, 996 device, 997 inputFormat, 998 numVertexValues, 999 numInstanceValues, 1000 numVertices, 1001 numInstances, 1002 std::vector<deUint32>()) // No index buffer 1003 { 1004 } 1005 1006 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount) 1007 { 1008 for (deUint32 i = 0; i < indexCount; i++) 1009 indicesPtr[i] = i; 1010 } 1011 1012 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const 1013 { 1014 return vertexNum; 1015 } 1016 1017 // DrawIndexedAccessInstance 1018 1019 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context& context, 1020 Move<VkDevice> device, 1021 VkFormat inputFormat, 1022 deUint32 numVertexValues, 1023 deUint32 numInstanceValues, 1024 deUint32 numVertices, 1025 deUint32 numInstances, 1026 const std::vector<deUint32>& indices) 1027 : VertexAccessInstance (context, 1028 device, 1029 inputFormat, 1030 numVertexValues, 1031 numInstanceValues, 1032 numVertices, 1033 numInstances, 1034 indices) 1035 , m_indices (indices) 1036 { 1037 } 1038 1039 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount) 1040 { 1041 DE_UNREF(indexCount); 1042 1043 for (deUint32 i = 0; i < m_indices.size(); i++) 1044 { 1045 DE_ASSERT(m_indices[i] < indexCount); 1046 1047 indicesPtr[m_indices[i]] = i; 1048 } 1049 } 1050 1051 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const 1052 { 1053 DE_ASSERT(vertexNum < (deUint32)m_indices.size()); 1054 1055 return m_indices[vertexNum]; 1056 } 1057 1058 // Test node creation functions 1059 1060 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format) 1061 { 1062 struct TestConfig 1063 { 1064 std::string name; 1065 std::string description; 1066 VkFormat inputFormat; 1067 deUint32 numVertexValues; 1068 deUint32 numInstanceValues; 1069 deUint32 numVertices; 1070 deUint32 numInstances; 1071 }; 1072 1073 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order); 1074 1075 const TestConfig testConfigs[] = 1076 { 1077 // name description format numVertexValues numInstanceValues numVertices numInstances 1078 { "vertex_out_of_bounds", "Create data for 6 vertices, draw 9 vertices", format, numChannels * 2 * 6, numChannels, 9, 1 }, 1079 { "vertex_incomplete", "Create data for half a vertex, draw 3 vertices", format, numChannels, numChannels, 3, 1 }, 1080 { "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances", format, numChannels * 2 * 9, numChannels, 3, 3 }, 1081 }; 1082 1083 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw", "")); 1084 1085 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++) 1086 { 1087 const TestConfig &config = testConfigs[i]; 1088 1089 drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat, 1090 config.numVertexValues, config.numInstanceValues, 1091 config.numVertices, config.numInstances)); 1092 } 1093 1094 return drawTests.release(); 1095 } 1096 1097 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format) 1098 { 1099 struct TestConfig 1100 { 1101 std::string name; 1102 std::string description; 1103 VkFormat inputFormat; 1104 DrawIndexedAccessTest::IndexConfig indexConfig; 1105 }; 1106 1107 const TestConfig testConfigs[] = 1108 { 1109 // name description format indexConfig 1110 { "last_index_out_of_bounds", "Only last index is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS }, 1111 { "indices_out_of_bounds", "Random indices out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS }, 1112 { "triangle_out_of_bounds", "First triangle is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS }, 1113 }; 1114 1115 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", "")); 1116 1117 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++) 1118 { 1119 const TestConfig &config = testConfigs[i]; 1120 1121 drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig)); 1122 } 1123 1124 return drawTests.release(); 1125 } 1126 1127 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup) 1128 { 1129 const VkFormat vertexFormats[] = 1130 { 1131 VK_FORMAT_R32_UINT, 1132 VK_FORMAT_R32_SINT, 1133 VK_FORMAT_R32_SFLOAT, 1134 VK_FORMAT_R32G32_UINT, 1135 VK_FORMAT_R32G32_SINT, 1136 VK_FORMAT_R32G32_SFLOAT, 1137 VK_FORMAT_R32G32B32_UINT, 1138 VK_FORMAT_R32G32B32_SINT, 1139 VK_FORMAT_R32G32B32_SFLOAT, 1140 VK_FORMAT_R32G32B32A32_UINT, 1141 VK_FORMAT_R32G32B32A32_SINT, 1142 VK_FORMAT_R32G32B32A32_SFLOAT, 1143 1144 VK_FORMAT_A2B10G10R10_UNORM_PACK32 1145 }; 1146 1147 for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++) 1148 { 1149 const std::string formatName = getFormatName(vertexFormats[i]); 1150 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), "")); 1151 1152 formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i])); 1153 formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i])); 1154 1155 parentGroup->addChild(formatGroup.release()); 1156 } 1157 } 1158 1159 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx) 1160 { 1161 de::MovePtr<tcu::TestCaseGroup> vertexAccessTests (new tcu::TestCaseGroup(testCtx, "vertex_access", "")); 1162 1163 addVertexFormatTests(testCtx, vertexAccessTests.get()); 1164 1165 return vertexAccessTests.release(); 1166 } 1167 1168 } // robustness 1169 } // vkt 1170