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