1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Tests for incremental present extension 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktWsiIncrementalPresentTests.hpp" 25 26 #include "vktTestCaseUtil.hpp" 27 #include "vktTestGroupUtil.hpp" 28 #include "vkRefUtil.hpp" 29 #include "vkWsiPlatform.hpp" 30 #include "vkWsiUtil.hpp" 31 #include "vkQueryUtil.hpp" 32 #include "vkDeviceUtil.hpp" 33 #include "vkPlatform.hpp" 34 #include "vkTypeUtil.hpp" 35 #include "vkPrograms.hpp" 36 37 #include "vkWsiUtil.hpp" 38 39 #include "tcuPlatform.hpp" 40 #include "tcuResultCollector.hpp" 41 #include "tcuTestLog.hpp" 42 43 #include <vector> 44 #include <string> 45 46 using std::vector; 47 using std::string; 48 49 using tcu::Maybe; 50 using tcu::UVec2; 51 using tcu::TestLog; 52 53 namespace vkt 54 { 55 namespace wsi 56 { 57 namespace 58 { 59 enum Scaling 60 { 61 SCALING_NONE, 62 SCALING_UP, 63 SCALING_DOWN 64 }; 65 66 typedef vector<vk::VkExtensionProperties> Extensions; 67 68 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions) 69 { 70 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin(); 71 requiredExtName != requiredExtensions.end(); 72 ++requiredExtName) 73 { 74 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName))) 75 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str()); 76 } 77 } 78 79 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp, 80 deUint32 version, 81 const Extensions& supportedExtensions, 82 vk::wsi::Type wsiType) 83 { 84 vector<string> extensions; 85 86 extensions.push_back("VK_KHR_surface"); 87 extensions.push_back(getExtensionName(wsiType)); 88 89 checkAllSupported(supportedExtensions, extensions); 90 91 return vk::createDefaultInstance(vkp, version, vector<string>(), extensions); 92 } 93 94 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void) 95 { 96 vk::VkPhysicalDeviceFeatures features; 97 deMemset(&features, 0, sizeof(features)); 98 return features; 99 } 100 101 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice) 102 { 103 deUint32 numFamilies = 0; 104 105 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL); 106 107 return numFamilies; 108 } 109 110 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface) 111 { 112 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice); 113 vector<deUint32> supportedFamilyIndices; 114 115 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx) 116 { 117 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE) 118 supportedFamilyIndices.push_back(queueFamilyNdx); 119 } 120 121 return supportedFamilyIndices; 122 } 123 124 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface) 125 { 126 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface); 127 128 if (supportedFamilyIndices.empty()) 129 TCU_THROW(NotSupportedError, "Device doesn't support presentation"); 130 131 return supportedFamilyIndices[0]; 132 } 133 134 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::InstanceInterface& vki, 135 vk::VkPhysicalDevice physicalDevice, 136 const Extensions& supportedExtensions, 137 const deUint32 queueFamilyIndex, 138 bool requiresIncrementalPresent, 139 const vk::VkAllocationCallbacks* pAllocator = DE_NULL) 140 { 141 const float queuePriorities[] = { 1.0f }; 142 const vk::VkDeviceQueueCreateInfo queueInfos[] = 143 { 144 { 145 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 146 DE_NULL, 147 (vk::VkDeviceQueueCreateFlags)0, 148 queueFamilyIndex, 149 DE_LENGTH_OF_ARRAY(queuePriorities), 150 &queuePriorities[0] 151 } 152 }; 153 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures(); 154 const char* const extensions[] = 155 { 156 "VK_KHR_swapchain", 157 "VK_KHR_incremental_present" 158 }; 159 160 const vk::VkDeviceCreateInfo deviceParams = 161 { 162 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 163 DE_NULL, 164 (vk::VkDeviceCreateFlags)0, 165 DE_LENGTH_OF_ARRAY(queueInfos), 166 &queueInfos[0], 167 0u, 168 DE_NULL, 169 requiresIncrementalPresent ? 2u : 1u, 170 DE_ARRAY_BEGIN(extensions), 171 &features 172 }; 173 174 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx) 175 { 176 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx]))) 177 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str()); 178 } 179 180 return createDevice(vki, physicalDevice, &deviceParams, pAllocator); 181 } 182 183 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform, 184 const Extensions& supportedExtensions, 185 vk::wsi::Type wsiType) 186 { 187 try 188 { 189 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType)); 190 } 191 catch (const tcu::NotSupportedError& e) 192 { 193 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType)))) 194 { 195 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation 196 // must support creating native display & window for that WSI type. 197 throw tcu::TestError(e.getMessage()); 198 } 199 else 200 throw; 201 } 202 } 203 204 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize) 205 { 206 try 207 { 208 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize)); 209 } 210 catch (const tcu::NotSupportedError& e) 211 { 212 // See createDisplay - assuming that wsi::Display was supported platform port 213 // should also support creating a window. 214 throw tcu::TestError(e.getMessage()); 215 } 216 } 217 218 void initSemaphores (const vk::DeviceInterface& vkd, 219 vk::VkDevice device, 220 std::vector<vk::VkSemaphore>& semaphores) 221 { 222 for (size_t ndx = 0; ndx < semaphores.size(); ndx++) 223 semaphores[ndx] = createSemaphore(vkd, device).disown(); 224 } 225 226 void deinitSemaphores (const vk::DeviceInterface& vkd, 227 vk::VkDevice device, 228 std::vector<vk::VkSemaphore>& semaphores) 229 { 230 for (size_t ndx = 0; ndx < semaphores.size(); ndx++) 231 { 232 if (semaphores[ndx] != (vk::VkSemaphore)0) 233 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL); 234 235 semaphores[ndx] = (vk::VkSemaphore)0; 236 } 237 238 semaphores.clear(); 239 } 240 241 void initFences (const vk::DeviceInterface& vkd, 242 vk::VkDevice device, 243 std::vector<vk::VkFence>& fences) 244 { 245 for (size_t ndx = 0; ndx < fences.size(); ndx++) 246 fences[ndx] = createFence(vkd, device).disown(); 247 } 248 249 void deinitFences (const vk::DeviceInterface& vkd, 250 vk::VkDevice device, 251 std::vector<vk::VkFence>& fences) 252 { 253 for (size_t ndx = 0; ndx < fences.size(); ndx++) 254 { 255 if (fences[ndx] != (vk::VkFence)0) 256 vkd.destroyFence(device, fences[ndx], DE_NULL); 257 258 fences[ndx] = (vk::VkFence)0; 259 } 260 261 fences.clear(); 262 } 263 264 vk::VkRect2D getRenderFrameRect (size_t frameNdx, 265 deUint32 imageWidth, 266 deUint32 imageHeight) 267 { 268 const deUint32 x = frameNdx == 0 269 ? 0 270 : de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u); 271 const deUint32 y = frameNdx == 0 272 ? 0 273 : de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u); 274 const deUint32 width = frameNdx == 0 275 ? imageWidth 276 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x); 277 const deUint32 height = frameNdx == 0 278 ? imageHeight 279 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y); 280 const vk::VkRect2D rect = 281 { 282 { (deInt32)x, (deInt32)y }, 283 { width, height } 284 }; 285 286 DE_ASSERT(width > 0); 287 DE_ASSERT(height > 0); 288 289 return rect; 290 } 291 292 vector<vk::VkRectLayerKHR> getUpdatedRects (size_t firstFrameNdx, 293 size_t lastFrameNdx, 294 deUint32 width, 295 deUint32 height) 296 { 297 vector<vk::VkRectLayerKHR> rects; 298 299 for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++) 300 { 301 const vk::VkRect2D rect = getRenderFrameRect(frameNdx, width, height); 302 const vk::VkRectLayerKHR rectLayer = 303 { 304 rect.offset, 305 rect.extent, 306 0 307 }; 308 309 rects.push_back(rectLayer); 310 } 311 312 return rects; 313 } 314 315 void cmdRenderFrame (const vk::DeviceInterface& vkd, 316 vk::VkCommandBuffer commandBuffer, 317 vk::VkPipelineLayout pipelineLayout, 318 vk::VkPipeline pipeline, 319 size_t frameNdx, 320 deUint32 imageWidth, 321 deUint32 imageHeight) 322 { 323 const deUint32 mask = (deUint32)frameNdx; 324 325 if (frameNdx == 0) 326 { 327 const vk::VkRect2D scissor = 328 { 329 { 0u, 0u }, 330 { imageWidth, imageHeight } 331 }; 332 333 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor); 334 const vk::VkClearAttachment attachment = 335 { 336 vk::VK_IMAGE_ASPECT_COLOR_BIT, 337 0u, 338 vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f) 339 }; 340 const vk::VkClearRect rect = 341 { 342 scissor, 343 0u, 344 1u 345 }; 346 347 vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect); 348 } 349 350 { 351 const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight); 352 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor); 353 354 vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask); 355 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); 356 vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u); 357 } 358 } 359 360 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd, 361 vk::VkDevice device, 362 vk::VkCommandPool commandPool, 363 vk::VkPipelineLayout pipelineLayout, 364 vk::VkRenderPass renderPass, 365 vk::VkFramebuffer framebuffer, 366 vk::VkPipeline pipeline, 367 vk::VkImage image, 368 bool isFirst, 369 size_t imageNextFrame, 370 size_t currentFrame, 371 deUint32 imageWidth, 372 deUint32 imageHeight) 373 { 374 const vk::VkCommandBufferAllocateInfo allocateInfo = 375 { 376 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 377 DE_NULL, 378 379 commandPool, 380 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, 381 1 382 }; 383 const vk::VkCommandBufferBeginInfo beginInfo = 384 { 385 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 386 DE_NULL, 387 0u, 388 DE_NULL 389 }; 390 391 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo)); 392 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo)); 393 394 { 395 const vk::VkImageSubresourceRange subRange = 396 { 397 vk::VK_IMAGE_ASPECT_COLOR_BIT, 398 0, 399 1, 400 0, 401 1 402 }; 403 const vk::VkImageMemoryBarrier barrier = 404 { 405 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 406 DE_NULL, 407 vk::VK_ACCESS_TRANSFER_WRITE_BIT, 408 vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT, 409 isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 410 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 411 VK_QUEUE_FAMILY_IGNORED, 412 VK_QUEUE_FAMILY_IGNORED, 413 image, 414 subRange 415 }; 416 vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &barrier); 417 } 418 419 { 420 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f); 421 const vk::VkRenderPassBeginInfo renderPassBeginInfo = 422 { 423 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 424 DE_NULL, 425 426 renderPass, 427 framebuffer, 428 429 { 430 { (deInt32)0, (deInt32)0 }, 431 { imageWidth, imageHeight } 432 }, 433 1u, 434 &clearValue 435 }; 436 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE); 437 } 438 439 for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++) 440 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight); 441 442 vkd.cmdEndRenderPass(*commandBuffer); 443 444 VK_CHECK(vkd.endCommandBuffer(*commandBuffer)); 445 return commandBuffer; 446 } 447 448 void deinitCommandBuffers (const vk::DeviceInterface& vkd, 449 vk::VkDevice device, 450 vk::VkCommandPool commandPool, 451 std::vector<vk::VkCommandBuffer>& commandBuffers) 452 { 453 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++) 454 { 455 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0) 456 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]); 457 458 commandBuffers[ndx] = (vk::VkCommandBuffer)0; 459 } 460 461 commandBuffers.clear(); 462 } 463 464 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd, 465 vk::VkDevice device, 466 deUint32 queueFamilyIndex) 467 { 468 const vk::VkCommandPoolCreateInfo createInfo = 469 { 470 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 471 DE_NULL, 472 0u, 473 queueFamilyIndex 474 }; 475 476 return vk::createCommandPool(vkd, device, &createInfo); 477 } 478 479 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd, 480 vk::VkDevice device, 481 vk::VkRenderPass renderPass, 482 vk::VkImageView imageView, 483 deUint32 width, 484 deUint32 height) 485 { 486 const vk::VkFramebufferCreateInfo createInfo = 487 { 488 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 489 DE_NULL, 490 491 0u, 492 renderPass, 493 1u, 494 &imageView, 495 width, 496 height, 497 1u 498 }; 499 500 return vk::createFramebuffer(vkd, device, &createInfo); 501 } 502 503 void initFramebuffers (const vk::DeviceInterface& vkd, 504 vk::VkDevice device, 505 vk::VkRenderPass renderPass, 506 std::vector<vk::VkImageView> imageViews, 507 deUint32 width, 508 deUint32 height, 509 std::vector<vk::VkFramebuffer>& framebuffers) 510 { 511 DE_ASSERT(framebuffers.size() == imageViews.size()); 512 513 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++) 514 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown(); 515 } 516 517 void deinitFramebuffers (const vk::DeviceInterface& vkd, 518 vk::VkDevice device, 519 std::vector<vk::VkFramebuffer>& framebuffers) 520 { 521 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++) 522 { 523 if (framebuffers[ndx] != (vk::VkFramebuffer)0) 524 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL); 525 526 framebuffers[ndx] = (vk::VkFramebuffer)0; 527 } 528 529 framebuffers.clear(); 530 } 531 532 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd, 533 vk::VkDevice device, 534 vk::VkImage image, 535 vk::VkFormat format) 536 { 537 const vk::VkImageViewCreateInfo createInfo = 538 { 539 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 540 DE_NULL, 541 542 0u, 543 image, 544 vk::VK_IMAGE_VIEW_TYPE_2D, 545 format, 546 vk::makeComponentMappingRGBA(), 547 { 548 vk::VK_IMAGE_ASPECT_COLOR_BIT, 549 0u, 550 1u, 551 0u, 552 1u 553 } 554 }; 555 556 return vk::createImageView(vkd, device, &createInfo, DE_NULL); 557 } 558 559 void initImageViews (const vk::DeviceInterface& vkd, 560 vk::VkDevice device, 561 const std::vector<vk::VkImage>& images, 562 vk::VkFormat format, 563 std::vector<vk::VkImageView>& imageViews) 564 { 565 DE_ASSERT(images.size() == imageViews.size()); 566 567 for (size_t ndx = 0; ndx < imageViews.size(); ndx++) 568 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown(); 569 } 570 571 void deinitImageViews (const vk::DeviceInterface& vkd, 572 vk::VkDevice device, 573 std::vector<vk::VkImageView>& imageViews) 574 { 575 for (size_t ndx = 0; ndx < imageViews.size(); ndx++) 576 { 577 if (imageViews[ndx] != (vk::VkImageView)0) 578 vkd.destroyImageView(device, imageViews[ndx], DE_NULL); 579 580 imageViews[ndx] = (vk::VkImageView)0; 581 } 582 583 imageViews.clear(); 584 } 585 586 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd, 587 vk::VkDevice device, 588 vk::VkFormat format) 589 { 590 const vk::VkAttachmentDescription attachments[] = 591 { 592 { 593 0u, 594 format, 595 vk::VK_SAMPLE_COUNT_1_BIT, 596 597 vk::VK_ATTACHMENT_LOAD_OP_LOAD, 598 vk::VK_ATTACHMENT_STORE_OP_STORE, 599 600 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, 601 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, 602 603 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 604 vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR 605 } 606 }; 607 const vk::VkAttachmentReference colorAttachmentRefs[] = 608 { 609 { 610 0u, 611 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 612 } 613 }; 614 const vk::VkSubpassDescription subpasses[] = 615 { 616 { 617 0u, 618 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 619 0u, 620 DE_NULL, 621 622 DE_LENGTH_OF_ARRAY(colorAttachmentRefs), 623 colorAttachmentRefs, 624 DE_NULL, 625 626 DE_NULL, 627 0u, 628 DE_NULL 629 } 630 }; 631 632 const vk::VkRenderPassCreateInfo createInfo = 633 { 634 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 635 DE_NULL, 636 0u, 637 638 DE_LENGTH_OF_ARRAY(attachments), 639 attachments, 640 641 DE_LENGTH_OF_ARRAY(subpasses), 642 subpasses, 643 644 0u, 645 DE_NULL 646 }; 647 648 return vk::createRenderPass(vkd, device, &createInfo); 649 } 650 651 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd, 652 vk::VkDevice device, 653 vk::VkRenderPass renderPass, 654 vk::VkPipelineLayout layout, 655 vk::VkShaderModule vertexShaderModule, 656 vk::VkShaderModule fragmentShaderModule, 657 deUint32 width, 658 deUint32 height) 659 { 660 const vk::VkSpecializationInfo shaderSpecialization = 661 { 662 0u, 663 DE_NULL, 664 0, 665 DE_NULL 666 }; 667 const vk::VkPipelineShaderStageCreateInfo stages[] = 668 { 669 { 670 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 671 DE_NULL, 672 0u, 673 vk::VK_SHADER_STAGE_VERTEX_BIT, 674 vertexShaderModule, 675 "main", 676 &shaderSpecialization 677 }, 678 { 679 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 680 DE_NULL, 681 0u, 682 vk::VK_SHADER_STAGE_FRAGMENT_BIT, 683 fragmentShaderModule, 684 "main", 685 &shaderSpecialization 686 } 687 }; 688 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = 689 { 690 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 691 DE_NULL, 692 0u, 693 0u, 694 DE_NULL, 695 0u, 696 DE_NULL 697 }; 698 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = 699 { 700 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 701 DE_NULL, 702 0u, 703 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 704 VK_FALSE 705 }; 706 const vk::VkViewport viewports[] = 707 { 708 { 709 0.0f, 0.0f, 710 (float)width, (float)height, 711 0.0f, 1.0f 712 } 713 }; 714 const vk::VkRect2D scissors[] = 715 { 716 { 717 { 0u, 0u }, 718 { width, height } 719 } 720 }; 721 const vk::VkPipelineViewportStateCreateInfo viewportState = 722 { 723 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 724 DE_NULL, 725 0u, 726 727 DE_LENGTH_OF_ARRAY(viewports), 728 viewports, 729 DE_LENGTH_OF_ARRAY(scissors), 730 scissors 731 }; 732 const vk::VkPipelineRasterizationStateCreateInfo rasterizationState = 733 { 734 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 735 DE_NULL, 736 0u, 737 VK_TRUE, 738 VK_FALSE, 739 vk::VK_POLYGON_MODE_FILL, 740 vk::VK_CULL_MODE_NONE, 741 vk::VK_FRONT_FACE_CLOCKWISE, 742 VK_FALSE, 743 0.0f, 744 0.0f, 745 0.0f, 746 1.0f 747 }; 748 const vk::VkSampleMask sampleMask = ~0u; 749 const vk::VkPipelineMultisampleStateCreateInfo multisampleState = 750 { 751 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 752 DE_NULL, 753 0u, 754 vk::VK_SAMPLE_COUNT_1_BIT, 755 VK_FALSE, 756 0.0f, 757 &sampleMask, 758 VK_FALSE, 759 VK_FALSE 760 }; 761 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilState = 762 { 763 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 764 DE_NULL, 765 0u, 766 DE_FALSE, 767 DE_FALSE, 768 vk::VK_COMPARE_OP_ALWAYS, 769 DE_FALSE, 770 DE_FALSE, 771 { 772 vk::VK_STENCIL_OP_KEEP, 773 vk::VK_STENCIL_OP_KEEP, 774 vk::VK_STENCIL_OP_KEEP, 775 vk::VK_COMPARE_OP_ALWAYS, 776 0u, 777 0u, 778 0u, 779 }, 780 { 781 vk::VK_STENCIL_OP_KEEP, 782 vk::VK_STENCIL_OP_KEEP, 783 vk::VK_STENCIL_OP_KEEP, 784 vk::VK_COMPARE_OP_ALWAYS, 785 0u, 786 0u, 787 0u, 788 }, 789 0.0f, 790 1.0f 791 }; 792 const vk::VkPipelineColorBlendAttachmentState attachmentBlendState = 793 { 794 VK_FALSE, 795 vk::VK_BLEND_FACTOR_ONE, 796 vk::VK_BLEND_FACTOR_ZERO, 797 vk::VK_BLEND_OP_ADD, 798 vk::VK_BLEND_FACTOR_ONE, 799 vk::VK_BLEND_FACTOR_ZERO, 800 vk::VK_BLEND_OP_ADD, 801 (vk::VK_COLOR_COMPONENT_R_BIT| 802 vk::VK_COLOR_COMPONENT_G_BIT| 803 vk::VK_COLOR_COMPONENT_B_BIT| 804 vk::VK_COLOR_COMPONENT_A_BIT), 805 }; 806 const vk::VkPipelineColorBlendStateCreateInfo blendState = 807 { 808 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 809 DE_NULL, 810 0u, 811 DE_FALSE, 812 vk::VK_LOGIC_OP_COPY, 813 1u, 814 &attachmentBlendState, 815 { 0.0f, 0.0f, 0.0f, 0.0f } 816 }; 817 const vk::VkDynamicState dynamicStates[] = 818 { 819 vk::VK_DYNAMIC_STATE_SCISSOR 820 }; 821 const vk::VkPipelineDynamicStateCreateInfo dynamicState = 822 { 823 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 824 DE_NULL, 825 0u, 826 827 DE_LENGTH_OF_ARRAY(dynamicStates), 828 dynamicStates 829 }; 830 const vk::VkGraphicsPipelineCreateInfo createInfo = 831 { 832 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 833 DE_NULL, 834 0u, 835 836 DE_LENGTH_OF_ARRAY(stages), 837 stages, 838 &vertexInputState, 839 &inputAssemblyState, 840 DE_NULL, 841 &viewportState, 842 &rasterizationState, 843 &multisampleState, 844 &depthStencilState, 845 &blendState, 846 &dynamicState, 847 layout, 848 renderPass, 849 0u, 850 DE_NULL, 851 0u 852 }; 853 854 return vk::createGraphicsPipeline(vkd, device, DE_NULL, &createInfo); 855 } 856 857 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd, 858 vk::VkDevice device) 859 { 860 const vk::VkPushConstantRange pushConstants[] = 861 { 862 { 863 vk::VK_SHADER_STAGE_FRAGMENT_BIT, 864 0u, 865 4u 866 } 867 }; 868 const vk::VkPipelineLayoutCreateInfo createInfo = 869 { 870 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 871 DE_NULL, 872 0u, 873 874 0u, 875 DE_NULL, 876 877 DE_LENGTH_OF_ARRAY(pushConstants), 878 pushConstants 879 }; 880 881 return vk::createPipelineLayout(vkd, device, &createInfo); 882 } 883 884 struct TestConfig 885 { 886 vk::wsi::Type wsiType; 887 Scaling scaling; 888 bool useIncrementalPresent; 889 vk::VkPresentModeKHR presentMode; 890 }; 891 892 class IncrementalPresentTestInstance : public TestInstance 893 { 894 public: 895 IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig); 896 ~IncrementalPresentTestInstance (void); 897 898 tcu::TestStatus iterate (void); 899 900 private: 901 const TestConfig m_testConfig; 902 const bool m_useIncrementalPresent; 903 const vk::PlatformInterface& m_vkp; 904 const Extensions m_instanceExtensions; 905 const vk::Unique<vk::VkInstance> m_instance; 906 const vk::InstanceDriver m_vki; 907 const vk::VkPhysicalDevice m_physicalDevice; 908 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay; 909 const de::UniquePtr<vk::wsi::Window> m_nativeWindow; 910 const vk::Unique<vk::VkSurfaceKHR> m_surface; 911 912 const deUint32 m_queueFamilyIndex; 913 const Extensions m_deviceExtensions; 914 const vk::Unique<vk::VkDevice> m_device; 915 const vk::DeviceDriver m_vkd; 916 const vk::VkQueue m_queue; 917 918 const vk::Unique<vk::VkCommandPool> m_commandPool; 919 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule; 920 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule; 921 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 922 923 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties; 924 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats; 925 const vector<vk::VkPresentModeKHR> m_presentModes; 926 927 tcu::ResultCollector m_resultCollector; 928 929 vk::Move<vk::VkSwapchainKHR> m_swapchain; 930 std::vector<vk::VkImage> m_swapchainImages; 931 std::vector<size_t> m_imageNextFrames; 932 std::vector<bool> m_isFirst; 933 934 vk::Move<vk::VkRenderPass> m_renderPass; 935 vk::Move<vk::VkPipeline> m_pipeline; 936 937 std::vector<vk::VkImageView> m_swapchainImageViews; 938 std::vector<vk::VkFramebuffer> m_framebuffers; 939 std::vector<vk::VkCommandBuffer> m_commandBuffers; 940 std::vector<vk::VkSemaphore> m_acquireSemaphores; 941 std::vector<vk::VkSemaphore> m_renderSemaphores; 942 std::vector<vk::VkFence> m_fences; 943 944 vk::VkSemaphore m_freeAcquireSemaphore; 945 vk::VkSemaphore m_freeRenderSemaphore; 946 947 std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs; 948 size_t m_swapchainConfigNdx; 949 950 const size_t m_frameCount; 951 size_t m_frameNdx; 952 953 const size_t m_maxOutOfDateCount; 954 size_t m_outOfDateCount; 955 956 void initSwapchainResources (void); 957 void deinitSwapchainResources (void); 958 void render (void); 959 }; 960 961 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR surface, 962 deUint32 queueFamilyIndex, 963 Scaling scaling, 964 const vk::VkSurfaceCapabilitiesKHR& properties, 965 const vector<vk::VkSurfaceFormatKHR>& formats, 966 const vector<vk::VkPresentModeKHR>& presentModes, 967 vk::VkPresentModeKHR presentMode) 968 { 969 const deUint32 imageLayers = 1u; 970 const vk::VkImageUsageFlags imageUsage = properties.supportedUsageFlags; 971 const vk::VkBool32 clipped = VK_FALSE; 972 vector<vk::VkSwapchainCreateInfoKHR> createInfos; 973 974 const deUint32 imageWidth = scaling == SCALING_NONE 975 ? (properties.currentExtent.width != 0xFFFFFFFFu 976 ? properties.currentExtent.width 977 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2))) 978 : (scaling == SCALING_UP 979 ? de::max(31u, properties.minImageExtent.width) 980 : properties.maxImageExtent.width); 981 const deUint32 imageHeight = scaling == SCALING_NONE 982 ? (properties.currentExtent.height != 0xFFFFFFFFu 983 ? properties.currentExtent.height 984 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2))) 985 : (scaling == SCALING_UP 986 ? de::max(31u, properties.minImageExtent.height) 987 : properties.maxImageExtent.height); 988 const vk::VkExtent2D imageSize = { imageWidth, imageHeight }; 989 990 { 991 size_t presentModeNdx; 992 993 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++) 994 { 995 if (presentModes[presentModeNdx] == presentMode) 996 break; 997 } 998 999 if (presentModeNdx == presentModes.size()) 1000 TCU_THROW(NotSupportedError, "Present mode not supported"); 1001 } 1002 1003 for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++) 1004 { 1005 for (vk::VkSurfaceTransformFlagsKHR transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u) 1006 { 1007 if ((properties.supportedTransforms & transform) == 0) 1008 continue; 1009 1010 for (vk::VkCompositeAlphaFlagsKHR alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u) 1011 { 1012 if ((alpha & properties.supportedCompositeAlpha) == 0) 1013 continue; 1014 1015 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform; 1016 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha; 1017 const vk::VkFormat imageFormat = formats[formatNdx].format; 1018 const vk::VkColorSpaceKHR imageColorSpace = formats[formatNdx].colorSpace; 1019 const vk::VkSwapchainCreateInfoKHR createInfo = 1020 { 1021 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 1022 DE_NULL, 1023 0u, 1024 surface, 1025 properties.minImageCount, 1026 imageFormat, 1027 imageColorSpace, 1028 imageSize, 1029 imageLayers, 1030 imageUsage, 1031 vk::VK_SHARING_MODE_EXCLUSIVE, 1032 1u, 1033 &queueFamilyIndex, 1034 preTransform, 1035 compositeAlpha, 1036 presentMode, 1037 clipped, 1038 (vk::VkSwapchainKHR)0 1039 }; 1040 1041 createInfos.push_back(createInfo); 1042 } 1043 } 1044 } 1045 1046 return createInfos; 1047 } 1048 1049 IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig) 1050 : TestInstance (context) 1051 , m_testConfig (testConfig) 1052 , m_useIncrementalPresent (testConfig.useIncrementalPresent) 1053 , m_vkp (context.getPlatformInterface()) 1054 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL)) 1055 , m_instance (createInstanceWithWsi(m_vkp, context.getUsedApiVersion(), m_instanceExtensions, testConfig.wsiType)) 1056 , m_vki (m_vkp, *m_instance) 1057 , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine())) 1058 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType)) 1059 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>())) 1060 , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow)) 1061 1062 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface)) 1063 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL)) 1064 , m_device (createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent)) 1065 , m_vkd (m_vki, *m_device) 1066 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u)) 1067 1068 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex)) 1069 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u)) 1070 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u)) 1071 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device)) 1072 1073 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface)) 1074 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface)) 1075 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface)) 1076 1077 , m_freeAcquireSemaphore ((vk::VkSemaphore)0) 1078 , m_freeRenderSemaphore ((vk::VkSemaphore)0) 1079 1080 , m_swapchainConfigs (generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode)) 1081 , m_swapchainConfigNdx (0u) 1082 1083 , m_frameCount (60u * 5u) 1084 , m_frameNdx (0u) 1085 1086 , m_maxOutOfDateCount (20u) 1087 , m_outOfDateCount (0u) 1088 { 1089 { 1090 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities"); 1091 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage; 1092 } 1093 } 1094 1095 IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void) 1096 { 1097 deinitSwapchainResources(); 1098 } 1099 1100 void IncrementalPresentTestInstance::initSwapchainResources (void) 1101 { 1102 const size_t fenceCount = 6; 1103 const deUint32 imageWidth = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width; 1104 const deUint32 imageHeight = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height; 1105 const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat; 1106 1107 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]); 1108 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain); 1109 1110 m_imageNextFrames.resize(m_swapchainImages.size(), 0); 1111 m_isFirst.resize(m_swapchainImages.size(), true); 1112 1113 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat); 1114 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight); 1115 1116 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0); 1117 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0); 1118 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0); 1119 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0); 1120 1121 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0); 1122 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0); 1123 1124 m_freeAcquireSemaphore = (vk::VkSemaphore)0; 1125 m_freeRenderSemaphore = (vk::VkSemaphore)0; 1126 1127 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown(); 1128 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown(); 1129 1130 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews); 1131 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers); 1132 initSemaphores(m_vkd, *m_device, m_acquireSemaphores); 1133 initSemaphores(m_vkd, *m_device, m_renderSemaphores); 1134 1135 initFences(m_vkd, *m_device, m_fences); 1136 } 1137 1138 void IncrementalPresentTestInstance::deinitSwapchainResources (void) 1139 { 1140 VK_CHECK(m_vkd.queueWaitIdle(m_queue)); 1141 1142 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0) 1143 { 1144 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL); 1145 m_freeAcquireSemaphore = (vk::VkSemaphore)0; 1146 } 1147 1148 if (m_freeRenderSemaphore != (vk::VkSemaphore)0) 1149 { 1150 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL); 1151 m_freeRenderSemaphore = (vk::VkSemaphore)0; 1152 } 1153 1154 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores); 1155 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores); 1156 deinitFences(m_vkd, *m_device, m_fences); 1157 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers); 1158 deinitFramebuffers(m_vkd, *m_device, m_framebuffers); 1159 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews); 1160 1161 m_swapchainImages.clear(); 1162 m_imageNextFrames.clear(); 1163 m_isFirst.clear(); 1164 1165 m_swapchain = vk::Move<vk::VkSwapchainKHR>(); 1166 m_renderPass = vk::Move<vk::VkRenderPass>(); 1167 m_pipeline = vk::Move<vk::VkPipeline>(); 1168 1169 } 1170 1171 void IncrementalPresentTestInstance::render (void) 1172 { 1173 const deUint64 foreverNs = 0xFFFFFFFFFFFFFFFFul; 1174 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()]; 1175 const deUint32 width = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width; 1176 const deUint32 height = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height; 1177 size_t imageNextFrame; 1178 1179 // Throttle execution 1180 if (m_frameNdx >= m_fences.size()) 1181 { 1182 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs)); 1183 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence)); 1184 1185 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]); 1186 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0; 1187 } 1188 1189 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore; 1190 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore; 1191 deUint32 imageIndex; 1192 1193 // Acquire next image 1194 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex)); 1195 1196 // Create command buffer 1197 { 1198 imageNextFrame = m_imageNextFrames[imageIndex]; 1199 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, m_swapchainImages[imageIndex], m_isFirst[imageIndex], imageNextFrame, m_frameNdx, width, height).disown(); 1200 m_imageNextFrames[imageIndex] = m_frameNdx + 1; 1201 m_isFirst[imageIndex] = false; 1202 } 1203 1204 // Submit command buffer 1205 { 1206 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 1207 const vk::VkSubmitInfo submitInfo = 1208 { 1209 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 1210 DE_NULL, 1211 1u, 1212 ¤tAcquireSemaphore, 1213 &dstStageMask, 1214 1u, 1215 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()], 1216 1u, 1217 ¤tRenderSemaphore 1218 }; 1219 1220 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence)); 1221 } 1222 1223 // Present frame 1224 if (m_useIncrementalPresent) 1225 { 1226 vk::VkResult result; 1227 const vector<vk::VkRectLayerKHR> rects = getUpdatedRects(imageNextFrame, m_frameNdx, width, height); 1228 const vk::VkPresentRegionKHR region = 1229 { 1230 (deUint32)rects.size(), 1231 rects.empty() ? DE_NULL : &rects[0] 1232 }; 1233 const vk::VkPresentRegionsKHR regionInfo = 1234 { 1235 vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR, 1236 DE_NULL, 1237 1u, 1238 ®ion 1239 }; 1240 const vk::VkPresentInfoKHR presentInfo = 1241 { 1242 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 1243 ®ionInfo, 1244 1u, 1245 ¤tRenderSemaphore, 1246 1u, 1247 &*m_swapchain, 1248 &imageIndex, 1249 &result 1250 }; 1251 1252 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo)); 1253 VK_CHECK(result); 1254 } 1255 else 1256 { 1257 vk::VkResult result; 1258 const vk::VkPresentInfoKHR presentInfo = 1259 { 1260 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 1261 DE_NULL, 1262 1u, 1263 ¤tRenderSemaphore, 1264 1u, 1265 &*m_swapchain, 1266 &imageIndex, 1267 &result 1268 }; 1269 1270 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo)); 1271 VK_CHECK(result); 1272 } 1273 1274 { 1275 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex]; 1276 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore; 1277 1278 m_freeRenderSemaphore = m_renderSemaphores[imageIndex]; 1279 m_renderSemaphores[imageIndex] = currentRenderSemaphore; 1280 } 1281 } 1282 1283 tcu::TestStatus IncrementalPresentTestInstance::iterate (void) 1284 { 1285 // Initialize swapchain specific resources 1286 // Render test 1287 try 1288 { 1289 if (m_frameNdx == 0) 1290 { 1291 if (m_outOfDateCount == 0) 1292 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage; 1293 1294 initSwapchainResources(); 1295 } 1296 1297 render(); 1298 } 1299 catch (const vk::Error& error) 1300 { 1301 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR) 1302 { 1303 m_swapchainConfigs = generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode); 1304 1305 if (m_outOfDateCount < m_maxOutOfDateCount) 1306 { 1307 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage; 1308 deinitSwapchainResources(); 1309 m_frameNdx = 0; 1310 m_outOfDateCount++; 1311 1312 return tcu::TestStatus::incomplete(); 1313 } 1314 else 1315 { 1316 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage; 1317 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount)); 1318 } 1319 } 1320 else 1321 { 1322 m_resultCollector.fail(error.what()); 1323 } 1324 1325 deinitSwapchainResources(); 1326 1327 m_swapchainConfigNdx++; 1328 m_frameNdx = 0; 1329 m_outOfDateCount = 0; 1330 1331 if (m_swapchainConfigNdx >= m_swapchainConfigs.size()) 1332 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); 1333 else 1334 return tcu::TestStatus::incomplete(); 1335 } 1336 1337 m_frameNdx++; 1338 1339 if (m_frameNdx >= m_frameCount) 1340 { 1341 m_frameNdx = 0; 1342 m_outOfDateCount = 0; 1343 m_swapchainConfigNdx++; 1344 1345 deinitSwapchainResources(); 1346 1347 if (m_swapchainConfigNdx >= m_swapchainConfigs.size()) 1348 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); 1349 else 1350 return tcu::TestStatus::incomplete(); 1351 } 1352 else 1353 return tcu::TestStatus::incomplete(); 1354 } 1355 1356 struct Programs 1357 { 1358 static void init (vk::SourceCollections& dst, TestConfig) 1359 { 1360 dst.glslSources.add("quad-vert") << glu::VertexSource( 1361 "#version 450\n" 1362 "out gl_PerVertex {\n" 1363 "\tvec4 gl_Position;\n" 1364 "};\n" 1365 "highp float;\n" 1366 "void main (void) {\n" 1367 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n" 1368 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n" 1369 "}\n"); 1370 dst.glslSources.add("quad-frag") << glu::FragmentSource( 1371 "#version 310 es\n" 1372 "layout(location = 0) out highp vec4 o_color;\n" 1373 "layout(push_constant) uniform PushConstant {\n" 1374 "\thighp uint mask;\n" 1375 "} pushConstants;\n" 1376 "void main (void)\n" 1377 "{\n" 1378 "\thighp uint mask = pushConstants.mask;\n" 1379 "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n" 1380 "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n" 1381 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n" 1382 "\t + 64u * bitfieldExtract(y, 1, 1)\n" 1383 "\t + 32u * bitfieldExtract(x, 3, 1);\n" 1384 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n" 1385 "\t + 64u * bitfieldExtract(x, 2, 1)\n" 1386 "\t + 32u * bitfieldExtract(y, 3, 1);\n" 1387 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n" 1388 "\t + 64u * bitfieldExtract(y, 2, 1)\n" 1389 "\t + 32u * bitfieldExtract(x, 4, 1);\n" 1390 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n" 1391 "}\n"); 1392 } 1393 }; 1394 1395 } // anonymous 1396 1397 void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType) 1398 { 1399 const struct 1400 { 1401 Scaling scaling; 1402 const char* name; 1403 } scaling [] = 1404 { 1405 { SCALING_NONE, "scale_none" }, 1406 { SCALING_UP, "scale_up" }, 1407 { SCALING_DOWN, "scale_down" } 1408 }; 1409 const struct 1410 { 1411 vk::VkPresentModeKHR mode; 1412 const char* name; 1413 } presentModes[] = 1414 { 1415 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" }, 1416 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" }, 1417 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" }, 1418 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" } 1419 }; 1420 1421 for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++) 1422 { 1423 if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND) 1424 continue; 1425 1426 if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE) 1427 continue; 1428 1429 { 1430 1431 de::MovePtr<tcu::TestCaseGroup> scaleGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name)); 1432 1433 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++) 1434 { 1435 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name)); 1436 1437 for (size_t ref = 0; ref < 2; ref++) 1438 { 1439 const bool isReference = (ref == 0); 1440 const char* const name = isReference ? "reference" : "incremental_present"; 1441 TestConfig config; 1442 1443 config.wsiType = wsiType; 1444 config.scaling = scaling[scalingNdx].scaling; 1445 config.useIncrementalPresent = !isReference; 1446 config.presentMode = presentModes[presentModeNdx].mode; 1447 1448 presentModeGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config)); 1449 } 1450 1451 scaleGroup->addChild(presentModeGroup.release()); 1452 } 1453 1454 testGroup->addChild(scaleGroup.release()); 1455 } 1456 } 1457 } 1458 1459 } // wsi 1460 } // vkt 1461