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