1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Input Assembly Tests 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineInputAssemblyTests.hpp" 28#include "vktPipelineClearUtil.hpp" 29#include "vktPipelineImageUtil.hpp" 30#include "vktPipelineVertexUtil.hpp" 31#include "vktPipelineReferenceRenderer.hpp" 32#include "vktAmberTestCase.hpp" 33#include "vktTestCase.hpp" 34#include "vkImageUtil.hpp" 35#include "vkMemUtil.hpp" 36#include "vkPrograms.hpp" 37#include "vkQueryUtil.hpp" 38#include "vkRef.hpp" 39#include "vkRefUtil.hpp" 40#include "vkTypeUtil.hpp" 41#include "vkCmdUtil.hpp" 42#include "vkObjUtil.hpp" 43#include "tcuImageCompare.hpp" 44#include "deMath.h" 45#include "deMemory.h" 46#include "deRandom.hpp" 47#include "deStringUtil.hpp" 48#include "deUniquePtr.hpp" 49 50#include <algorithm> 51#include <sstream> 52#include <vector> 53 54namespace vkt 55{ 56namespace pipeline 57{ 58 59using namespace vk; 60 61enum class RestartType 62{ 63 NORMAL, 64 NONE, 65 ALL, 66}; 67 68namespace 69{ 70 71class InputAssemblyTest : public vkt::TestCase 72{ 73public: 74 const static VkPrimitiveTopology s_primitiveTopologies[]; 75 const static deUint32 s_restartIndex32; 76 const static deUint16 s_restartIndex16; 77 const static deUint8 s_restartIndex8; 78 79 InputAssemblyTest (tcu::TestContext& testContext, 80 const std::string& name, 81 const PipelineConstructionType pipelineConstructionType, 82 VkPrimitiveTopology primitiveTopology, 83 int primitiveCount, 84 bool testPrimitiveRestart, 85 VkIndexType indexType); 86 virtual ~InputAssemblyTest (void) {} 87 virtual void initPrograms (SourceCollections& sourceCollections) const; 88 virtual void checkSupport (Context& context) const; 89 virtual TestInstance* createInstance (Context& context) const; 90 static bool isRestartIndex (VkIndexType indexType, deUint32 indexValue); 91#ifndef CTS_USES_VULKANSC 92 static deUint32 getRestartIndex (VkIndexType indexType); 93#endif // CTS_USES_VULKANSC 94 95protected: 96 virtual void createBufferData (VkPrimitiveTopology topology, 97 int primitiveCount, 98 VkIndexType indexType, 99 std::vector<deUint32>& indexData, 100 std::vector<Vertex4RGBA>& vertexData) const = 0; 101 VkPrimitiveTopology m_primitiveTopology; 102 const int m_primitiveCount; 103 104private: 105 const PipelineConstructionType m_pipelineConstructionType; 106 bool m_testPrimitiveRestart; 107 VkIndexType m_indexType; 108}; 109 110class PrimitiveTopologyTest : public InputAssemblyTest 111{ 112public: 113 PrimitiveTopologyTest (tcu::TestContext& testContext, 114 const std::string& name, 115 PipelineConstructionType pipelineConstructionType, 116 VkPrimitiveTopology primitiveTopology, 117 VkIndexType indexType); 118 virtual ~PrimitiveTopologyTest (void) {} 119 120protected: 121 virtual void createBufferData (VkPrimitiveTopology topology, 122 int primitiveCount, 123 VkIndexType indexType, 124 std::vector<deUint32>& indexData, 125 std::vector<Vertex4RGBA>& vertexData) const; 126 127private: 128}; 129 130#ifndef CTS_USES_VULKANSC 131class PrimitiveRestartTest : public InputAssemblyTest 132{ 133public: 134 PrimitiveRestartTest (tcu::TestContext& testContext, 135 const std::string& name, 136 const PipelineConstructionType pipelineConstructionType, 137 VkPrimitiveTopology primitiveTopology, 138 VkIndexType indexType, 139 RestartType restartType); 140 virtual ~PrimitiveRestartTest (void) {} 141 virtual void checkSupport (Context& context) const; 142 143protected: 144 virtual void createBufferData (VkPrimitiveTopology topology, 145 int primitiveCount, 146 VkIndexType indexType, 147 std::vector<deUint32>& indexData, 148 std::vector<Vertex4RGBA>& vertexData) const; 149 150private: 151 bool isRestartPrimitive (int primitiveIndex) const; 152 void createListPrimitives (int primitiveCount, 153 float originX, 154 float originY, 155 float primitiveSizeX, 156 float primitiveSizeY, 157 int verticesPerPrimitive, 158 VkIndexType indexType, 159 std::vector<deUint32>& indexData, 160 std::vector<Vertex4RGBA>& vertexData, 161 std::vector<deUint32> adjacencies) const; 162 163 std::vector<deUint32> m_restartPrimitives; 164 RestartType m_restartType; 165}; 166#endif // CTS_USES_VULKANSC 167 168 169class InputAssemblyInstance : public vkt::TestInstance 170{ 171public: 172 InputAssemblyInstance (Context& context, 173 const PipelineConstructionType pipelineConstructionType, 174 const VkPrimitiveTopology primitiveTopology, 175 bool testPrimitiveRestart, 176 VkIndexType indexType, 177 const std::vector<deUint32>& indexBufferData, 178 const std::vector<Vertex4RGBA>& vertexBufferData); 179 virtual ~InputAssemblyInstance (void); 180 virtual tcu::TestStatus iterate (void); 181 182private: 183 tcu::TestStatus verifyImage (void); 184 void uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData); 185 void uploadIndexBufferData8 (deUint8* destPtr, const std::vector<deUint32>& indexBufferData); 186 187 VkPrimitiveTopology m_primitiveTopology; 188 bool m_primitiveRestartEnable; 189 VkIndexType m_indexType; 190 191 Move<VkBuffer> m_vertexBuffer; 192 std::vector<Vertex4RGBA> m_vertices; 193 de::MovePtr<Allocation> m_vertexBufferAlloc; 194 195 Move<VkBuffer> m_indexBuffer; 196 std::vector<deUint32> m_indices; 197 de::MovePtr<Allocation> m_indexBufferAlloc; 198 199 const tcu::UVec2 m_renderSize; 200 201 const VkFormat m_colorFormat; 202 VkImageCreateInfo m_colorImageCreateInfo; 203 Move<VkImage> m_colorImage; 204 de::MovePtr<Allocation> m_colorImageAlloc; 205 Move<VkImageView> m_colorAttachmentView; 206 RenderPassWrapper m_renderPass; 207 Move<VkFramebuffer> m_framebuffer; 208 209 ShaderWrapper m_vertexShaderModule; 210 ShaderWrapper m_fragmentShaderModule; 211 ShaderWrapper m_tcsShaderModule; 212 ShaderWrapper m_tesShaderModule; 213 214 PipelineLayoutWrapper m_pipelineLayout; 215 GraphicsPipelineWrapper m_graphicsPipeline; 216 217 Move<VkCommandPool> m_cmdPool; 218 Move<VkCommandBuffer> m_cmdBuffer; 219}; 220 221 222// InputAssemblyTest 223 224const VkPrimitiveTopology InputAssemblyTest::s_primitiveTopologies[] = 225{ 226 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 227 VK_PRIMITIVE_TOPOLOGY_LINE_LIST, 228 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 229 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 230 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 231 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, 232 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, 233 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, 234 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, 235 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY 236}; 237 238const deUint32 InputAssemblyTest::s_restartIndex32 = ~((deUint32)0u); 239const deUint16 InputAssemblyTest::s_restartIndex16 = ~((deUint16)0u); 240const deUint8 InputAssemblyTest::s_restartIndex8 = ~((deUint8)0u); 241 242InputAssemblyTest::InputAssemblyTest (tcu::TestContext& testContext, 243 const std::string& name, 244 const PipelineConstructionType pipelineConstructionType, 245 VkPrimitiveTopology primitiveTopology, 246 int primitiveCount, 247 bool testPrimitiveRestart, 248 VkIndexType indexType) 249 : vkt::TestCase (testContext, name) 250 , m_primitiveTopology (primitiveTopology) 251 , m_primitiveCount(primitiveCount) 252 , m_pipelineConstructionType(pipelineConstructionType) 253 , m_testPrimitiveRestart (testPrimitiveRestart) 254 , m_indexType (indexType) 255{ 256} 257 258void InputAssemblyTest::checkSupport (Context& context) const 259{ 260 if (m_indexType == VK_INDEX_TYPE_UINT8_EXT) 261 context.requireDeviceFunctionality("VK_EXT_index_type_uint8"); 262 263 switch (m_primitiveTopology) 264 { 265 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 266 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 267 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 268 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 269 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER); 270 break; 271 272 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 273 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER); 274 break; 275 276 default: 277 break; 278 } 279 280 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType); 281 282#ifndef CTS_USES_VULKANSC 283 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && 284 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && 285 !context.getPortabilitySubsetFeatures().triangleFans) 286 { 287 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation"); 288 } 289#endif // CTS_USES_VULKANSC 290} 291 292TestInstance* InputAssemblyTest::createInstance (Context& context) const 293{ 294 std::vector<deUint32> indexBufferData; 295 std::vector<Vertex4RGBA> vertexBufferData; 296 297 createBufferData(m_primitiveTopology, m_primitiveCount, m_indexType, indexBufferData, vertexBufferData); 298 299 return new InputAssemblyInstance(context, m_pipelineConstructionType, m_primitiveTopology, m_testPrimitiveRestart, m_indexType, indexBufferData, vertexBufferData); 300} 301 302void InputAssemblyTest::initPrograms (SourceCollections& sourceCollections) const 303{ 304 std::ostringstream vertexSource; 305 306 vertexSource << 307 "#version 310 es\n" 308 "layout(location = 0) in vec4 position;\n" 309 "layout(location = 1) in vec4 color;\n" 310 "layout(location = 0) out highp vec4 vtxColor;\n" 311 "void main (void)\n" 312 "{\n" 313 " gl_Position = position;\n" 314 << (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? " gl_PointSize = 3.0;\n" 315 : "" ) 316 << " vtxColor = color;\n" 317 "}\n"; 318 319 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str()); 320 321 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource( 322 "#version 310 es\n" 323 "layout(location = 0) in highp vec4 vtxColor;\n" 324 "layout(location = 0) out highp vec4 fragColor;\n" 325 "void main (void)\n" 326 "{\n" 327 " fragColor = vtxColor;\n" 328 "}\n"); 329 330 sourceCollections.glslSources.add("color_tcs") << glu::TessellationControlSource( 331 "#version 310 es\n" 332 "#extension GL_EXT_tessellation_shader : require\n" 333 "layout(vertices = 3) out;\n" 334 "layout(location = 0) in highp vec4 vtxColorIn[];\n" 335 "layout(location = 0) out highp vec4 vtxColorOut[];\n" 336 "#define ID gl_InvocationID\n" 337 "void main (void)\n" 338 "{\n" 339 " vtxColorOut[ID] = vtxColorIn[ID];\n" 340 " gl_out[ID].gl_Position = gl_in[ID].gl_Position;\n" 341 " if (ID == 0)\n" 342 " {\n" 343 " gl_TessLevelInner[0] = 5.0;\n" 344 " gl_TessLevelOuter[0] = 4.0;\n" 345 " gl_TessLevelOuter[1] = 5.0;\n" 346 " gl_TessLevelOuter[2] = 6.0;\n" 347 " }\n" 348 "}\n"); 349 350 sourceCollections.glslSources.add("color_tes") << glu::TessellationEvaluationSource( 351 "#version 310 es\n" 352 "#extension GL_EXT_tessellation_shader : require\n" 353 "layout(triangles) in;\n" 354 "layout(location = 0) in vec4 vtxColorIn[];\n" 355 "layout(location = 0) out vec4 vtxColorOut;\n" 356 "void main (void)\n" 357 "{\n" 358 " vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n" 359 " vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n" 360 " vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n" 361 " gl_Position = p0 + p1 + p2;\n" 362 " vec4 q0 = gl_TessCoord.x * vtxColorIn[0];\n" 363 " vec4 q1 = gl_TessCoord.y * vtxColorIn[1];\n" 364 " vec4 q2 = gl_TessCoord.z * vtxColorIn[2];\n" 365 " vtxColorOut = q0 + q1 + q2;\n" 366 "}\n"); 367} 368 369bool InputAssemblyTest::isRestartIndex (VkIndexType indexType, deUint32 indexValue) 370{ 371 if (indexType == VK_INDEX_TYPE_UINT16) 372 return indexValue == s_restartIndex16; 373 else if (indexType == VK_INDEX_TYPE_UINT8_EXT) 374 return indexValue == s_restartIndex8; 375 else 376 return indexValue == s_restartIndex32; 377} 378 379#ifndef CTS_USES_VULKANSC 380deUint32 InputAssemblyTest::getRestartIndex (VkIndexType indexType) 381{ 382 if (indexType == VK_INDEX_TYPE_UINT16) 383 return InputAssemblyTest::s_restartIndex16; 384 else if (indexType == VK_INDEX_TYPE_UINT8_EXT) 385 return InputAssemblyTest::s_restartIndex8; 386 else 387 return InputAssemblyTest::s_restartIndex32; 388} 389#endif // CTS_USES_VULKANSC 390 391// PrimitiveTopologyTest 392 393PrimitiveTopologyTest::PrimitiveTopologyTest (tcu::TestContext& testContext, 394 const std::string& name, 395 PipelineConstructionType pipelineConstructionType, 396 VkPrimitiveTopology primitiveTopology, 397 VkIndexType indexType) 398 : InputAssemblyTest (testContext, name, pipelineConstructionType, primitiveTopology, 10, false, indexType) 399{ 400} 401 402void PrimitiveTopologyTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const 403{ 404 DE_ASSERT(primitiveCount > 0); 405 DE_UNREF(indexType); 406 407 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 408 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 409 const float border = 0.2f; 410 const float originX = -1.0f + border; 411 const float originY = -1.0f + border; 412 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green }; 413 float primitiveSizeY = (2.0f - 2.0f * border); 414 float primitiveSizeX; 415 std::vector<deUint32> indices; 416 std::vector<Vertex4RGBA> vertices; 417 418 419 // Calculate primitive size 420 switch (topology) 421 { 422 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 423 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1); 424 break; 425 426 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 427 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 428 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount - 1); 429 break; 430 431 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 432 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 433 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2); 434 break; 435 436 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 437 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 438 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount + primitiveCount / 2 + primitiveCount % 2 - 1); 439 break; 440 441 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 442 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 443 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2); 444 break; 445 446 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 447 primitiveSizeX = 1.0f - border; 448 primitiveSizeY = 1.0f - border; 449 break; 450 451 default: 452 primitiveSizeX = 0.0f; // Garbage 453 DE_ASSERT(false); 454 } 455 456 switch (topology) 457 { 458 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 459 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 460 { 461 const Vertex4RGBA vertex = 462 { 463 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 464 red 465 }; 466 467 vertices.push_back(vertex); 468 indices.push_back(primitiveNdx); 469 } 470 break; 471 472 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 473 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 474 { 475 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) 476 { 477 const Vertex4RGBA vertex = 478 { 479 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 480 red 481 }; 482 483 vertices.push_back(vertex); 484 indices.push_back((primitiveNdx * 2 + vertexNdx)); 485 } 486 } 487 break; 488 489 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 490 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 491 { 492 if (primitiveNdx == 0) 493 { 494 Vertex4RGBA vertex = 495 { 496 tcu::Vec4(originX, originY, 0.0f, 1.0f), 497 red 498 }; 499 500 vertices.push_back(vertex); 501 indices.push_back(0); 502 503 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f); 504 vertices.push_back(vertex); 505 indices.push_back(1); 506 } 507 else 508 { 509 const Vertex4RGBA vertex = 510 { 511 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), 512 red 513 }; 514 515 vertices.push_back(vertex); 516 indices.push_back(primitiveNdx + 1); 517 } 518 } 519 break; 520 521 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 522 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 523 { 524 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) 525 { 526 const Vertex4RGBA vertex = 527 { 528 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f), 529 red 530 }; 531 532 vertices.push_back(vertex); 533 indices.push_back(primitiveNdx * 3 + vertexNdx); 534 } 535 } 536 break; 537 538 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 539 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 540 { 541 if (primitiveNdx == 0) 542 { 543 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) 544 { 545 const Vertex4RGBA vertex = 546 { 547 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 548 red 549 }; 550 551 vertices.push_back(vertex); 552 indices.push_back(vertexNdx); 553 } 554 } 555 else 556 { 557 const Vertex4RGBA vertex = 558 { 559 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), 560 red 561 }; 562 563 vertices.push_back(vertex); 564 indices.push_back(primitiveNdx + 2); 565 } 566 } 567 break; 568 569 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 570 { 571 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount)); 572 573 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 574 { 575 if (primitiveNdx == 0) 576 { 577 Vertex4RGBA vertex = 578 { 579 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 580 red 581 }; 582 583 vertices.push_back(vertex); 584 indices.push_back(0); 585 586 vertex.position = tcu::Vec4(primitiveSizeX, 0.0f, 0.0f, 1.0f); 587 vertices.push_back(vertex); 588 indices.push_back(1); 589 590 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle), primitiveSizeY * deFloatSin(stepAngle), 0.0f, 1.0f); 591 vertices.push_back(vertex); 592 indices.push_back(2); 593 } 594 else 595 { 596 const Vertex4RGBA vertex = 597 { 598 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f), 599 red 600 }; 601 602 vertices.push_back(vertex); 603 indices.push_back(primitiveNdx + 2); 604 } 605 } 606 break; 607 } 608 609 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 610 vertices.push_back(defaultVertex); 611 612 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 613 { 614 indices.push_back(0); 615 616 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) 617 { 618 const Vertex4RGBA vertex = 619 { 620 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 621 red 622 }; 623 624 vertices.push_back(vertex); 625 indices.push_back(primitiveNdx * 2 + vertexNdx + 1); 626 } 627 628 indices.push_back(0); 629 } 630 break; 631 632 633 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 634 vertices.push_back(defaultVertex); 635 indices.push_back(0); 636 637 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 638 { 639 if (primitiveNdx == 0) 640 { 641 Vertex4RGBA vertex = 642 { 643 tcu::Vec4(originX, originY, 0.0f, 1.0f), 644 red 645 }; 646 647 vertices.push_back(vertex); 648 indices.push_back(1); 649 650 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f); 651 vertices.push_back(vertex); 652 indices.push_back(2); 653 } 654 else 655 { 656 const Vertex4RGBA vertex = 657 { 658 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), 659 red 660 }; 661 662 vertices.push_back(vertex); 663 indices.push_back(primitiveNdx + 2); 664 } 665 } 666 667 indices.push_back(0); 668 break; 669 670 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 671 vertices.push_back(defaultVertex); 672 673 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 674 { 675 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) 676 { 677 const Vertex4RGBA vertex = 678 { 679 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f), 680 red 681 }; 682 683 vertices.push_back(vertex); 684 indices.push_back(primitiveNdx * 3 + vertexNdx + 1); 685 indices.push_back(0); 686 } 687 } 688 break; 689 690 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 691 vertices.push_back(defaultVertex); 692 693 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 694 { 695 if (primitiveNdx == 0) 696 { 697 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++) 698 { 699 const Vertex4RGBA vertex = 700 { 701 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 702 red 703 }; 704 705 vertices.push_back(vertex); 706 indices.push_back(vertexNdx + 1); 707 indices.push_back(0); 708 } 709 } 710 else 711 { 712 const Vertex4RGBA vertex = 713 { 714 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), 715 red 716 }; 717 718 vertices.push_back(vertex); 719 indices.push_back(primitiveNdx + 2 + 1); 720 indices.push_back(0); 721 } 722 } 723 break; 724 725 default: 726 DE_ASSERT(false); 727 break; 728 } 729 730 vertexData = vertices; 731 indexData = indices; 732} 733 734#ifndef CTS_USES_VULKANSC 735// PrimitiveRestartTest 736 737PrimitiveRestartTest::PrimitiveRestartTest (tcu::TestContext& testContext, 738 const std::string& name, 739 PipelineConstructionType pipelineConstructionType, 740 VkPrimitiveTopology primitiveTopology, 741 VkIndexType indexType, 742 RestartType restartType) 743 744 : InputAssemblyTest (testContext, name, pipelineConstructionType, primitiveTopology, 10, true, indexType) 745 , m_restartType(restartType) 746{ 747 deUint32 restartPrimitives[] = { 1, 5 }; 748 749 if (restartType == RestartType::NORMAL) 750 { 751 m_restartPrimitives = std::vector<deUint32>(restartPrimitives, restartPrimitives + sizeof(restartPrimitives) / sizeof(deUint32)); 752 } 753 else if (restartType == RestartType::NONE) 754 { 755 m_restartPrimitives = std::vector<deUint32>{}; 756 } 757 else 758 { 759 deUint32 count = 1; 760 switch (primitiveTopology) 761 { 762 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 763 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 764 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 765 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 766 count = 2; 767 break; 768 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 769 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 770 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 771 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 772 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 773 count = 3; 774 break; 775 default: 776 break; 777 } 778 for (deUint32 i = 0; i < (deUint32)m_primitiveCount; ++i) 779 { 780 if (i % count == count - 1) 781 { 782 m_restartPrimitives.push_back(i); 783 } 784 } 785 } 786} 787 788void PrimitiveRestartTest::checkSupport (Context& context) const 789{ 790 switch (m_primitiveTopology) 791 { 792 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 793 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 794 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 795 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 796 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 797 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 798 { 799 context.requireDeviceFunctionality("VK_EXT_primitive_topology_list_restart"); 800 801 const auto& features = context.getPrimitiveTopologyListRestartFeaturesEXT(); 802 if (!features.primitiveTopologyListRestart) 803 TCU_THROW(NotSupportedError, "Primitive topology list restart feature not supported"); 804 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && !features.primitiveTopologyPatchListRestart) 805 TCU_THROW(NotSupportedError, "Primitive topology patch list restart feature not supported"); 806 } 807 break; 808 809 default: 810 break; 811 } 812 813 InputAssemblyTest::checkSupport(context); 814} 815 816void PrimitiveRestartTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const 817{ 818 DE_ASSERT(primitiveCount > 0); 819 DE_UNREF(indexType); 820 821 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 822 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 823 const float border = 0.2f; 824 const float originX = -1.0f + border; 825 const float originY = -1.0f + border; 826 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green }; 827 float primitiveSizeY = (2.0f - 2.0f * border); 828 float primitiveSizeX; 829 bool primitiveStart = true; 830 std::vector<deUint32> indices; 831 std::vector<Vertex4RGBA> vertices; 832 833 // Calculate primitive size 834 switch (topology) 835 { 836 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 837 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1); 838 break; 839 840 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 841 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 842 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 843 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 844 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2); 845 break; 846 847 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 848 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 849 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 850 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 851 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 852 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2); 853 break; 854 855 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 856 primitiveSizeX = 1.0f - border; 857 primitiveSizeY = 1.0f - border; 858 break; 859 860 default: 861 primitiveSizeX = 0.0f; // Garbage 862 DE_ASSERT(false); 863 } 864 865 switch (topology) 866 { 867 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 868 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 869 { 870 if (isRestartPrimitive(primitiveNdx)) 871 { 872 indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); 873 primitiveStart = true; 874 } 875 else 876 { 877 if (primitiveStart && m_restartType != RestartType::ALL) 878 { 879 const Vertex4RGBA vertex = 880 { 881 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 882 red 883 }; 884 885 vertices.push_back(vertex); 886 indices.push_back((deUint32)vertices.size() - 1); 887 888 primitiveStart = false; 889 } 890 891 const Vertex4RGBA vertex = 892 { 893 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), 894 red 895 }; 896 897 vertices.push_back(vertex); 898 indices.push_back((deUint32)vertices.size() - 1); 899 } 900 } 901 break; 902 903 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 904 { 905 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 906 { 907 if (isRestartPrimitive(primitiveNdx)) 908 { 909 indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); 910 primitiveStart = true; 911 } 912 else 913 { 914 if (primitiveStart && m_restartType != RestartType::ALL) 915 { 916 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) 917 { 918 const Vertex4RGBA vertex = 919 { 920 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f), 921 red 922 }; 923 924 vertices.push_back(vertex); 925 indices.push_back((deUint32)vertices.size() - 1); 926 } 927 928 primitiveStart = false; 929 } 930 const Vertex4RGBA vertex = 931 { 932 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), 933 red 934 }; 935 936 vertices.push_back(vertex); 937 indices.push_back((deUint32)vertices.size() - 1); 938 } 939 } 940 break; 941 } 942 943 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 944 { 945 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount)); 946 947 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 948 { 949 if (isRestartPrimitive(primitiveNdx)) 950 { 951 indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); 952 primitiveStart = true; 953 } 954 else 955 { 956 if (primitiveStart && m_restartType != RestartType::ALL) 957 { 958 Vertex4RGBA vertex = 959 { 960 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 961 red 962 }; 963 964 vertices.push_back(vertex); 965 indices.push_back((deUint32)vertices.size() - 1); 966 967 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx)), 0.0f, 1.0f); 968 vertices.push_back(vertex); 969 indices.push_back((deUint32)vertices.size() - 1); 970 971 primitiveStart = false; 972 } 973 974 const Vertex4RGBA vertex = 975 { 976 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f), 977 red 978 }; 979 980 vertices.push_back(vertex); 981 indices.push_back((deUint32)vertices.size() - 1); 982 } 983 } 984 break; 985 } 986 987 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 988 vertices.push_back(defaultVertex); 989 990 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 991 { 992 if (isRestartPrimitive(primitiveNdx)) 993 { 994 indices.push_back(0); 995 indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); 996 primitiveStart = true; 997 } 998 else 999 { 1000 if (primitiveStart && m_restartType != RestartType::ALL) 1001 { 1002 indices.push_back(0); 1003 1004 const Vertex4RGBA vertex = 1005 { 1006 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f), 1007 red 1008 }; 1009 1010 vertices.push_back(vertex); 1011 indices.push_back((deUint32)vertices.size() - 1); 1012 1013 primitiveStart = false; 1014 } 1015 1016 const Vertex4RGBA vertex = 1017 { 1018 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f), 1019 red 1020 }; 1021 1022 vertices.push_back(vertex); 1023 indices.push_back((deUint32)vertices.size() - 1); 1024 } 1025 } 1026 1027 indices.push_back(0); 1028 break; 1029 1030 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 1031 vertices.push_back(defaultVertex); 1032 1033 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 1034 { 1035 if (isRestartPrimitive(primitiveNdx)) 1036 { 1037 indices.push_back(InputAssemblyTest::getRestartIndex(indexType)); 1038 primitiveStart = true; 1039 } 1040 else 1041 { 1042 if (primitiveStart && m_restartType != RestartType::ALL) 1043 { 1044 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++) 1045 { 1046 const Vertex4RGBA vertex = 1047 { 1048 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f), 1049 red 1050 }; 1051 1052 vertices.push_back(vertex); 1053 indices.push_back((deUint32)vertices.size() - 1); 1054 indices.push_back(0); 1055 } 1056 1057 primitiveStart = false; 1058 } 1059 1060 const Vertex4RGBA vertex = 1061 { 1062 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f), 1063 red 1064 }; 1065 1066 vertices.push_back(vertex); 1067 indices.push_back((deUint32)vertices.size() - 1); 1068 indices.push_back(0); 1069 } 1070 } 1071 break; 1072 1073 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 1074 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY, 1075 1, indexType, indices, vertices, std::vector<deUint32>()); 1076 break; 1077 1078 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 1079 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY, 1080 2, indexType, indices, vertices, std::vector<deUint32>()); 1081 break; 1082 1083 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 1084 { 1085 std::vector<deUint32> adjacencies = { 0, 3 }; 1086 1087 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY, 1088 4, indexType, indices, vertices, adjacencies); 1089 } 1090 break; 1091 1092 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 1093 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 1094 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY, 1095 3, indexType, indices, vertices, std::vector<deUint32>()); 1096 break; 1097 1098 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 1099 { 1100 std::vector<deUint32> adjacencies = { 1, 3, 5 }; 1101 1102 createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY, 1103 6, indexType, indices, vertices, adjacencies); 1104 } 1105 break; 1106 1107 default: 1108 DE_ASSERT(false); 1109 break; 1110 } 1111 1112 vertexData = vertices; 1113 indexData = indices; 1114} 1115 1116void PrimitiveRestartTest::createListPrimitives (int primitiveCount, 1117 float originX, 1118 float originY, 1119 float primitiveSizeX, 1120 float primitiveSizeY, 1121 int verticesPerPrimitive, 1122 VkIndexType indexType, 1123 std::vector<deUint32>& indexData, 1124 std::vector<Vertex4RGBA>& vertexData, 1125 std::vector<deUint32> adjacencies) const 1126{ 1127 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 1128 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 1129 // Tells which vertex of a primitive is used as a restart index. 1130 // This is decreased each time a restart primitive is used. 1131 int restartVertexIndex = verticesPerPrimitive - 1; 1132 1133 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++) 1134 { 1135 deUint32 nonAdjacentVertexNdx = 0; 1136 1137 for (int vertexNdx = 0; vertexNdx < verticesPerPrimitive; vertexNdx++) 1138 { 1139 if (isRestartPrimitive(primitiveNdx) && vertexNdx == restartVertexIndex) 1140 { 1141 indexData.push_back(InputAssemblyTest::getRestartIndex(indexType)); 1142 1143 restartVertexIndex--; 1144 if (restartVertexIndex < 0) restartVertexIndex = verticesPerPrimitive - 1; 1145 1146 break; 1147 } 1148 1149 if (std::find(adjacencies.begin(), adjacencies.end(), vertexNdx) != adjacencies.end()) 1150 { 1151 // This is an adjacency vertex index. Add a green vertex that should never end up to the framebuffer. 1152 const Vertex4RGBA vertex = 1153 { 1154 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 1155 green 1156 }; 1157 vertexData.push_back(vertex); 1158 indexData.push_back((deUint32) vertexData.size() - 1); 1159 continue; 1160 } 1161 1162 const Vertex4RGBA vertex = 1163 { 1164 tcu::Vec4(originX + float((primitiveNdx + nonAdjacentVertexNdx) / 2) * primitiveSizeX, 1165 originY + float((primitiveNdx + nonAdjacentVertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f), 1166 red 1167 }; 1168 1169 vertexData.push_back(vertex); 1170 indexData.push_back((deUint32) vertexData.size() - 1); 1171 nonAdjacentVertexNdx++; 1172 } 1173 } 1174} 1175 1176bool PrimitiveRestartTest::isRestartPrimitive (int primitiveIndex) const 1177{ 1178 return std::find(m_restartPrimitives.begin(), m_restartPrimitives.end(), primitiveIndex) != m_restartPrimitives.end(); 1179} 1180#endif // CTS_USES_VULKANSC 1181 1182// InputAssemblyInstance 1183 1184InputAssemblyInstance::InputAssemblyInstance (Context& context, 1185 PipelineConstructionType pipelineConstructionType, 1186 VkPrimitiveTopology primitiveTopology, 1187 bool testPrimitiveRestart, 1188 VkIndexType indexType, 1189 const std::vector<deUint32>& indexBufferData, 1190 const std::vector<Vertex4RGBA>& vertexBufferData) 1191 1192 : vkt::TestInstance (context) 1193 , m_primitiveTopology (primitiveTopology) 1194 , m_primitiveRestartEnable (testPrimitiveRestart) 1195 , m_indexType (indexType) 1196 , m_vertices (vertexBufferData) 1197 , m_indices (indexBufferData) 1198 , m_renderSize ((primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ? tcu::UVec2(32, 32) : tcu::UVec2(64, 16)) 1199 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 1200 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType) 1201{ 1202 const DeviceInterface& vk = context.getDeviceInterface(); 1203 const VkDevice vkDevice = context.getDevice(); 1204 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 1205 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())); 1206 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 1207 const bool patchList = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; 1208 1209 // Create color image 1210 { 1211 const VkImageCreateInfo colorImageParams = 1212 { 1213 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1214 DE_NULL, // const void* pNext; 1215 0u, // VkImageCreateFlags flags; 1216 VK_IMAGE_TYPE_2D, // VkImageType imageType; 1217 m_colorFormat, // VkFormat format; 1218 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; 1219 1u, // deUint32 mipLevels; 1220 1u, // deUint32 arrayLayers; 1221 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 1222 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1223 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 1224 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1225 1u, // deUint32 queueFamilyIndexCount; 1226 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 1227 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 1228 }; 1229 1230 m_colorImageCreateInfo = colorImageParams; 1231 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo); 1232 1233 // Allocate and bind color image memory 1234 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); 1235 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 1236 } 1237 1238 // Create color attachment view 1239 { 1240 const VkImageViewCreateInfo colorAttachmentViewParams = 1241 { 1242 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 1243 DE_NULL, // const void* pNext; 1244 0u, // VkImageViewCreateFlags flags; 1245 *m_colorImage, // VkImage image; 1246 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 1247 m_colorFormat, // VkFormat format; 1248 componentMappingRGBA, // VkComponentMapping components; 1249 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; 1250 }; 1251 1252 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); 1253 } 1254 1255 // Create render pass 1256 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat); 1257 1258 // Create framebuffer 1259 { 1260 const VkFramebufferCreateInfo framebufferParams = 1261 { 1262 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 1263 DE_NULL, // const void* pNext; 1264 0u, // VkFramebufferCreateFlags flags; 1265 *m_renderPass, // VkRenderPass renderPass; 1266 1u, // deUint32 attachmentCount; 1267 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 1268 (deUint32)m_renderSize.x(), // deUint32 width; 1269 (deUint32)m_renderSize.y(), // deUint32 height; 1270 1u // deUint32 layers; 1271 }; 1272 1273 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage); 1274 } 1275 1276 // Create pipeline layout 1277 { 1278 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 1279 { 1280 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 1281 DE_NULL, // const void* pNext; 1282 0u, // VkPipelineLayoutCreateFlags flags; 1283 0u, // deUint32 setLayoutCount; 1284 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 1285 0u, // deUint32 pushConstantRangeCount; 1286 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 1287 }; 1288 1289 m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams); 1290 } 1291 1292 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0); 1293 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0); 1294 1295 if (patchList) 1296 { 1297 m_tcsShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tcs"), 0); 1298 m_tesShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tes"), 0); 1299 } 1300 1301 // Create pipeline 1302 { 1303 const VkVertexInputBindingDescription vertexInputBindingDescription = 1304 { 1305 0u, // deUint32 binding; 1306 sizeof(Vertex4RGBA), // deUint32 stride; 1307 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate; 1308 }; 1309 1310 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 1311 { 1312 { 1313 0u, // deUint32 location; 1314 0u, // deUint32 binding; 1315 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 1316 0u // deUint32 offset; 1317 }, 1318 { 1319 1u, // deUint32 location; 1320 0u, // deUint32 binding; 1321 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 1322 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset; 1323 } 1324 }; 1325 1326 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 1327 { 1328 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 1329 DE_NULL, // const void* pNext; 1330 0u, // VkPipelineVertexInputStateCreateFlags flags; 1331 1u, // deUint32 vertexBindingDescriptionCount; 1332 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 1333 2u, // deUint32 vertexAttributeDescriptionCount; 1334 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 1335 }; 1336 1337 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 1338 { 1339 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 1340 DE_NULL, // const void* pNext; 1341 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 1342 m_primitiveTopology, // VkPrimitiveTopology topology; 1343 m_primitiveRestartEnable // VkBool32 primitiveRestartEnable; 1344 }; 1345 1346 const std::vector<VkViewport> viewport { makeViewport(m_renderSize) }; 1347 const std::vector<VkRect2D> scissor { makeRect2D(m_renderSize) }; 1348 1349 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 1350 { 1351 false, // VkBool32 blendEnable; 1352 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 1353 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 1354 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 1355 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 1356 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 1357 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 1358 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; 1359 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT 1360 }; 1361 1362 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 1363 { 1364 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1365 DE_NULL, // const void* pNext; 1366 0u, // VkPipelineColorBlendStateCreateFlags flags; 1367 false, // VkBool32 logicOpEnable; 1368 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 1369 1u, // deUint32 attachmentCount; 1370 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1371 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; 1372 }; 1373 1374 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = 1375 { 1376 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 1377 DE_NULL, // const void* pNext; 1378 0u, // VkPipelineDepthStencilStateCreateFlags flags; 1379 false, // VkBool32 depthTestEnable; 1380 false, // VkBool32 depthWriteEnable; 1381 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 1382 false, // VkBool32 depthBoundsTestEnable; 1383 false, // VkBool32 stencilTestEnable; 1384 // VkStencilOpState front; 1385 { 1386 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 1387 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 1388 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 1389 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 1390 0u, // deUint32 compareMask; 1391 0u, // deUint32 writeMask; 1392 0u, // deUint32 reference; 1393 }, 1394 // VkStencilOpState back; 1395 { 1396 VK_STENCIL_OP_KEEP, // VkStencilOp failOp; 1397 VK_STENCIL_OP_KEEP, // VkStencilOp passOp; 1398 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; 1399 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 1400 0u, // deUint32 compareMask; 1401 0u, // deUint32 writeMask; 1402 0u, // deUint32 reference; 1403 }, 1404 0.0f, // float minDepthBounds; 1405 1.0f // float maxDepthBounds; 1406 }; 1407 1408 m_graphicsPipeline.setDefaultRasterizationState() 1409 .setDefaultMultisampleState() 1410 .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams) 1411 .setupPreRasterizationShaderState(viewport, 1412 scissor, 1413 m_pipelineLayout, 1414 *m_renderPass, 1415 0u, 1416 m_vertexShaderModule, 1417 DE_NULL, 1418 m_tcsShaderModule, 1419 m_tesShaderModule) 1420 .setupFragmentShaderState(m_pipelineLayout, 1421 *m_renderPass, 1422 0u, 1423 m_fragmentShaderModule, 1424 &depthStencilStateParams) 1425 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams) 1426 .setMonolithicPipelineLayout(m_pipelineLayout) 1427 .buildPipeline(); 1428 } 1429 1430 // Create vertex and index buffer 1431 { 1432 const VkBufferCreateInfo indexBufferParams = 1433 { 1434 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1435 DE_NULL, // const void* pNext; 1436 0u, // VkBufferCreateFlags flags; 1437 m_indices.size() * sizeof(deUint32), // VkDeviceSize size; 1438 VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage; 1439 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1440 1u, // deUint32 queueFamilyIndexCount; 1441 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 1442 }; 1443 1444 const VkBufferCreateInfo vertexBufferParams = 1445 { 1446 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 1447 DE_NULL, // const void* pNext; 1448 0u, // VkBufferCreateFlags flags; 1449 m_vertices.size() * sizeof(Vertex4RGBA), // VkDeviceSize size; 1450 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 1451 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1452 1u, // deUint32 queueFamilyIndexCount; 1453 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 1454 }; 1455 1456 m_indexBuffer = createBuffer(vk, vkDevice, &indexBufferParams); 1457 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indexBuffer), MemoryRequirement::HostVisible); 1458 1459 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset())); 1460 1461 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 1462 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); 1463 1464 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 1465 1466 // Load vertices into index buffer 1467 if (m_indexType == VK_INDEX_TYPE_UINT32) 1468 { 1469 deMemcpy(m_indexBufferAlloc->getHostPtr(), m_indices.data(), m_indices.size() * sizeof(deUint32)); 1470 } 1471 else if (m_indexType == VK_INDEX_TYPE_UINT8_EXT) 1472 { 1473 uploadIndexBufferData8((deUint8*)m_indexBufferAlloc->getHostPtr(), m_indices); 1474 } 1475 else // m_indexType == VK_INDEX_TYPE_UINT16 1476 { 1477 uploadIndexBufferData16((deUint16*)m_indexBufferAlloc->getHostPtr(), m_indices); 1478 } 1479 1480 // Load vertices into vertex buffer 1481 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); 1482 1483 flushAlloc(vk, vkDevice, *m_indexBufferAlloc); 1484 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc); 1485 } 1486 1487 // Create command pool 1488 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 1489 1490 // Create command buffer 1491 { 1492 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); 1493 1494 const VkImageMemoryBarrier attachmentLayoutBarrier = 1495 { 1496 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1497 DE_NULL, // const void* pNext; 1498 0u, // VkAccessFlags srcAccessMask; 1499 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 1500 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 1501 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 1502 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 1503 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 1504 *m_colorImage, // VkImage image; 1505 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; 1506 }; 1507 1508 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1509 1510 beginCommandBuffer(vk, *m_cmdBuffer, 0u); 1511 1512 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 1513 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier); 1514 1515 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue); 1516 1517 const VkDeviceSize vertexBufferOffset = 0; 1518 1519 m_graphicsPipeline.bind(*m_cmdBuffer); 1520 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 1521 vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType); 1522 vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0); 1523 1524 m_renderPass.end(vk, *m_cmdBuffer); 1525 endCommandBuffer(vk, *m_cmdBuffer); 1526 } 1527} 1528 1529InputAssemblyInstance::~InputAssemblyInstance (void) 1530{ 1531} 1532 1533tcu::TestStatus InputAssemblyInstance::iterate (void) 1534{ 1535 const DeviceInterface& vk = m_context.getDeviceInterface(); 1536 const VkDevice vkDevice = m_context.getDevice(); 1537 const VkQueue queue = m_context.getUniversalQueue(); 1538 1539 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); 1540 1541 return verifyImage(); 1542} 1543 1544tcu::TestStatus InputAssemblyInstance::verifyImage (void) 1545{ 1546 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat); 1547 const tcu::TextureFormat tcuStencilFormat = tcu::TextureFormat(); 1548 const ColorVertexShader vertexShader; 1549 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat); 1550 const rr::Program program (&vertexShader, &fragmentShader); 1551 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program); 1552 bool compareOk = false; 1553 1554 // Render reference image 1555 { 1556 // The reference for tessellated patches are drawn using ordinary triangles. 1557 const rr::PrimitiveType topology = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST ? rr::PrimitiveType::PRIMITIVETYPE_TRIANGLES : mapVkPrimitiveTopology(m_primitiveTopology); 1558 rr::RenderState renderState (refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits); 1559 1560 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) 1561 renderState.point.pointSize = 3.0f; 1562 1563 if (m_primitiveRestartEnable) 1564 { 1565 std::vector<deUint32> indicesRange; 1566 1567 for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++) 1568 { 1569 const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]); 1570 1571 if (!isRestart) 1572 indicesRange.push_back(m_indices[indexNdx]); 1573 1574 if (isRestart || indexNdx == (m_indices.size() - 1)) 1575 { 1576 // Draw the range of indices found so far 1577 1578 std::vector<Vertex4RGBA> nonIndexedVertices; 1579 for (size_t i = 0; i < indicesRange.size(); i++) 1580 nonIndexedVertices.push_back(m_vertices[indicesRange[i]]); 1581 1582 refRenderer.draw(renderState, topology, nonIndexedVertices); 1583 indicesRange.clear(); 1584 } 1585 } 1586 } 1587 else 1588 { 1589 std::vector<Vertex4RGBA> nonIndexedVertices; 1590 for (size_t i = 0; i < m_indices.size(); i++) 1591 nonIndexedVertices.push_back(m_vertices[m_indices[i]]); 1592 1593 refRenderer.draw(renderState, topology, nonIndexedVertices); 1594 } 1595 } 1596 1597 // Compare result with reference image 1598 { 1599 const DeviceInterface& vk = m_context.getDeviceInterface(); 1600 const VkDevice vkDevice = m_context.getDevice(); 1601 const VkQueue queue = m_context.getUniversalQueue(); 1602 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1603 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 1604 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release()); 1605 1606 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), 1607 "IntImageCompare", 1608 "Image comparison", 1609 refRenderer.getAccess(), 1610 result->getAccess(), 1611 tcu::UVec4(2, 2, 2, 2), 1612 tcu::IVec3(1, 1, 0), 1613 true, 1614 tcu::COMPARE_LOG_RESULT); 1615 } 1616 1617 if (compareOk) 1618 return tcu::TestStatus::pass("Result image matches reference"); 1619 else 1620 return tcu::TestStatus::fail("Image mismatch"); 1621} 1622 1623void InputAssemblyInstance::uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData) 1624{ 1625 for (size_t i = 0; i < indexBufferData.size(); i++) 1626 { 1627 DE_ASSERT(indexBufferData[i] <= 0xFFFF); 1628 destPtr[i] = (deUint16)indexBufferData[i]; 1629 } 1630} 1631 1632void InputAssemblyInstance::uploadIndexBufferData8 (deUint8* destPtr, const std::vector<deUint32>& indexBufferData) 1633{ 1634 for (size_t i = 0; i < indexBufferData.size(); i++) 1635 { 1636 DE_ASSERT(indexBufferData[i] <= 0xFF); 1637 destPtr[i] = (deUint8)indexBufferData[i]; 1638 } 1639} 1640 1641 1642// Utilities for test names 1643 1644std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology) 1645{ 1646 const std::string fullName = getPrimitiveTopologyName(topology); 1647 1648 DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_")); 1649 1650 return de::toLower(fullName.substr(22)); 1651} 1652 1653de::MovePtr<tcu::TestCaseGroup> createPrimitiveTopologyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1654{ 1655 de::MovePtr<tcu::TestCaseGroup> primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology")); 1656 1657 de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16")); 1658 de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32")); 1659 de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8")); 1660 1661 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++) 1662 { 1663 const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx]; 1664 1665 indexUint16Tests->addChild(new PrimitiveTopologyTest(testCtx, 1666 getPrimitiveTopologyCaseName(topology), 1667 pipelineConstructionType, 1668 topology, 1669 VK_INDEX_TYPE_UINT16)); 1670 1671 indexUint32Tests->addChild(new PrimitiveTopologyTest(testCtx, 1672 getPrimitiveTopologyCaseName(topology), 1673 pipelineConstructionType, 1674 topology, 1675 VK_INDEX_TYPE_UINT32)); 1676 1677 indexUint8Tests->addChild(new PrimitiveTopologyTest(testCtx, 1678 getPrimitiveTopologyCaseName(topology), 1679 pipelineConstructionType, 1680 topology, 1681 VK_INDEX_TYPE_UINT8_EXT)); 1682 } 1683 1684 primitiveTopologyTests->addChild(indexUint16Tests.release()); 1685 primitiveTopologyTests->addChild(indexUint32Tests.release()); 1686 primitiveTopologyTests->addChild(indexUint8Tests.release()); 1687 1688 return primitiveTopologyTests; 1689} 1690 1691#ifndef CTS_USES_VULKANSC 1692de::MovePtr<tcu::TestCaseGroup> createPrimitiveRestartTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1693{ 1694 const VkPrimitiveTopology primitiveRestartTopologies[] = 1695 { 1696 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 1697 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1698 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, 1699 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, 1700 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, 1701 1702 // Supported with VK_EXT_primitive_topology_list_restart 1703 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 1704 VK_PRIMITIVE_TOPOLOGY_LINE_LIST, 1705 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, 1706 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1707 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, 1708 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST 1709 }; 1710 1711 de::MovePtr<tcu::TestCaseGroup> primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart")); 1712 1713 de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16")); 1714 de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32")); 1715 de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8")); 1716 1717 constexpr struct RestartTest 1718 { 1719 RestartType type; 1720 const char* name; 1721 } restartTypes[] = 1722 { 1723 { RestartType::NORMAL, "", }, 1724 { RestartType::NONE, "no_restart_", }, 1725 { RestartType::ALL, "restart_all_" }, 1726 }; 1727 1728 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++) 1729 { 1730 const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx]; 1731 1732 for (int useRestartNdx = 0; useRestartNdx < DE_LENGTH_OF_ARRAY(restartTypes); useRestartNdx++) 1733 { 1734 if (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && restartTypes[useRestartNdx].type == RestartType::ALL) { 1735 continue; 1736 } 1737 indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx, 1738 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology), 1739 pipelineConstructionType, 1740 topology, 1741 VK_INDEX_TYPE_UINT16, 1742 restartTypes[useRestartNdx].type)); 1743 1744 indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx, 1745 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology), 1746 pipelineConstructionType, 1747 topology, 1748 VK_INDEX_TYPE_UINT32, 1749 restartTypes[useRestartNdx].type)); 1750 1751 indexUint8Tests->addChild(new PrimitiveRestartTest(testCtx, 1752 restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology), 1753 pipelineConstructionType, 1754 topology, 1755 VK_INDEX_TYPE_UINT8_EXT, 1756 restartTypes[useRestartNdx].type)); 1757 } 1758 } 1759 1760 // Tests that have primitive restart disabled, but have indices with restart index value. 1761 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 1762 { 1763 struct 1764 { 1765 std::string name; 1766 std::vector<std::string> requirements; 1767 } tests[] = 1768 { 1769 { "line_list", { "VK_EXT_primitive_topology_list_restart" } }, 1770 { "line_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } }, 1771 { "line_strip", {} }, 1772 { "line_strip_with_adjacency", {"Features.geometryShader"} }, 1773 { "patch_list", { "VK_EXT_primitive_topology_list_restart", "Features.tessellationShader" } }, 1774 { "point_list", { "VK_EXT_primitive_topology_list_restart" } }, 1775 { "triangle_fan", {} }, 1776 { "triangle_list", { "VK_EXT_primitive_topology_list_restart" } }, 1777 { "triangle_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } }, 1778 { "triangle_strip", {} }, 1779 { "triangle_strip_with_adjacency", {"Features.geometryShader"} } 1780 }; 1781 1782 const std::string dataDir = "pipeline/input_assembly/primitive_restart"; 1783 1784 for (auto& test : tests) 1785 { 1786 std::string testName = "restart_disabled_" + test.name; 1787 indexUint16Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(), dataDir.c_str(), testName + "_uint16.amber", test.requirements)); 1788 test.requirements.push_back("VK_EXT_index_type_uint8"); 1789 indexUint8Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(), dataDir.c_str(), testName + "_uint8.amber", test.requirements)); 1790 } 1791 } 1792 1793 primitiveRestartTests->addChild(indexUint16Tests.release()); 1794 primitiveRestartTests->addChild(indexUint32Tests.release()); 1795 primitiveRestartTests->addChild(indexUint8Tests.release()); 1796 1797 return primitiveRestartTests; 1798} 1799#endif // CTS_USES_VULKANSC 1800 1801} // anonymous 1802 1803tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1804{ 1805 de::MovePtr<tcu::TestCaseGroup> inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly")); 1806 1807 inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx, pipelineConstructionType).release()); 1808#ifndef CTS_USES_VULKANSC 1809 inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx, pipelineConstructionType).release()); 1810#endif // CTS_USES_VULKANSC 1811 1812 return inputAssemblyTests.release(); 1813} 1814 1815} // pipeline 1816} // vkt 1817