1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Tests for incremental present extension
22 *//*--------------------------------------------------------------------*/
24 #include "vktWsiIncrementalPresentTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkWsiPlatform.hpp"
31 #include "vkWsiUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkDeviceUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkCmdUtil.hpp"
38 #include "vkObjUtil.hpp"
40 #include "vkWsiUtil.hpp"
42 #include "tcuPlatform.hpp"
43 #include "tcuResultCollector.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuCommandLine.hpp"
70 typedef vector<vk::VkExtensionProperties> Extensions;
72 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
74 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
75 requiredExtName != requiredExtensions.end();
78 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
79 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
83 CustomInstance createInstanceWithWsi (Context& context,
84 const Extensions& supportedExtensions,
85 vk::wsi::Type wsiType)
87 vector<string> extensions;
89 extensions.push_back("VK_KHR_surface");
90 extensions.push_back(getExtensionName(wsiType));
92 checkAllSupported(supportedExtensions, extensions);
94 return vkt::createCustomInstanceWithExtensions(context, extensions);
97 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
99 vk::VkPhysicalDeviceFeatures features;
100 deMemset(&features, 0, sizeof(features));
104 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
106 deUint32 numFamilies = 0;
108 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
113 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
115 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
116 vector<deUint32> supportedFamilyIndices;
118 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
120 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
121 supportedFamilyIndices.push_back(queueFamilyNdx);
124 return supportedFamilyIndices;
127 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
129 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
131 if (supportedFamilyIndices.empty())
132 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
134 return supportedFamilyIndices[0];
137 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
138 vk::VkInstance instance,
139 const vk::InstanceInterface& vki,
140 vk::VkPhysicalDevice physicalDevice,
141 const Extensions& supportedExtensions,
142 const deUint32 queueFamilyIndex,
143 bool requiresIncrementalPresent,
144 bool validationEnabled,
145 const vk::VkAllocationCallbacks* pAllocator = DE_NULL)
147 const float queuePriorities[] = { 1.0f };
148 const vk::VkDeviceQueueCreateInfo queueInfos[] =
151 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
153 (vk::VkDeviceQueueCreateFlags)0,
155 DE_LENGTH_OF_ARRAY(queuePriorities),
159 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures();
160 const char* const extensions[] =
163 "VK_KHR_incremental_present"
166 const vk::VkDeviceCreateInfo deviceParams =
168 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
170 (vk::VkDeviceCreateFlags)0,
171 DE_LENGTH_OF_ARRAY(queueInfos),
175 requiresIncrementalPresent ? 2u : 1u,
176 DE_ARRAY_BEGIN(extensions),
180 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
182 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
183 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
186 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
189 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform,
190 const Extensions& supportedExtensions,
191 vk::wsi::Type wsiType)
195 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
197 catch (const tcu::NotSupportedError& e)
199 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
200 platform.hasDisplay(wsiType))
202 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
203 // must support creating native display & window for that WSI type.
204 throw tcu::TestError(e.getMessage());
211 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
215 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
217 catch (const tcu::NotSupportedError& e)
219 // See createDisplay - assuming that wsi::Display was supported platform port
220 // should also support creating a window.
221 throw tcu::TestError(e.getMessage());
225 void initSemaphores (const vk::DeviceInterface& vkd,
227 std::vector<vk::VkSemaphore>& semaphores)
229 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
230 semaphores[ndx] = createSemaphore(vkd, device).disown();
233 void deinitSemaphores (const vk::DeviceInterface& vkd,
235 std::vector<vk::VkSemaphore>& semaphores)
237 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
239 if (semaphores[ndx] != (vk::VkSemaphore)0)
240 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
242 semaphores[ndx] = (vk::VkSemaphore)0;
248 void initFences (const vk::DeviceInterface& vkd,
250 std::vector<vk::VkFence>& fences)
252 for (size_t ndx = 0; ndx < fences.size(); ndx++)
253 fences[ndx] = createFence(vkd, device).disown();
256 void deinitFences (const vk::DeviceInterface& vkd,
258 std::vector<vk::VkFence>& fences)
260 for (size_t ndx = 0; ndx < fences.size(); ndx++)
262 if (fences[ndx] != (vk::VkFence)0)
263 vkd.destroyFence(device, fences[ndx], DE_NULL);
265 fences[ndx] = (vk::VkFence)0;
271 vk::VkRect2D getRenderFrameRect (size_t frameNdx,
273 deUint32 imageHeight)
275 const deUint32 x = frameNdx == 0
277 : de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u);
278 const deUint32 y = frameNdx == 0
280 : de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u);
281 const deUint32 width = frameNdx == 0
283 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x);
284 const deUint32 height = frameNdx == 0
286 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y);
287 const vk::VkRect2D rect =
289 { (deInt32)x, (deInt32)y },
293 DE_ASSERT(width > 0);
294 DE_ASSERT(height > 0);
299 vector<vk::VkRectLayerKHR> getUpdatedRects (size_t firstFrameNdx,
304 vector<vk::VkRectLayerKHR> rects;
306 for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++)
308 const vk::VkRect2D rect = getRenderFrameRect(frameNdx, width, height);
309 const vk::VkRectLayerKHR rectLayer =
316 rects.push_back(rectLayer);
322 void cmdRenderFrame (const vk::DeviceInterface& vkd,
323 vk::VkCommandBuffer commandBuffer,
324 vk::VkPipelineLayout pipelineLayout,
325 vk::VkPipeline pipeline,
328 deUint32 imageHeight)
330 const deUint32 mask = (deUint32)frameNdx;
334 const vk::VkRect2D scissor = vk::makeRect2D(imageWidth, imageHeight);
335 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
336 const vk::VkClearAttachment attachment =
338 vk::VK_IMAGE_ASPECT_COLOR_BIT,
340 vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f)
342 const vk::VkClearRect rect =
349 vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
353 const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight);
354 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
356 vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask);
357 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
358 vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
362 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
364 vk::VkCommandPool commandPool,
365 vk::VkPipelineLayout pipelineLayout,
366 vk::VkRenderPass renderPass,
367 vk::VkFramebuffer framebuffer,
368 vk::VkPipeline pipeline,
371 size_t imageNextFrame,
374 deUint32 imageHeight)
376 const vk::VkCommandBufferAllocateInfo allocateInfo =
378 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
382 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
386 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
387 beginCommandBuffer(vkd, *commandBuffer, 0u);
390 const vk::VkImageSubresourceRange subRange =
392 vk::VK_IMAGE_ASPECT_COLOR_BIT,
398 const vk::VkImageMemoryBarrier barrier =
400 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
402 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
403 vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT,
404 isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
405 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
406 VK_QUEUE_FAMILY_IGNORED,
407 VK_QUEUE_FAMILY_IGNORED,
411 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);
414 beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, vk::makeRect2D(imageWidth, imageHeight), tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f));
416 for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++)
417 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight);
419 endRenderPass(vkd, *commandBuffer);
421 endCommandBuffer(vkd, *commandBuffer);
422 return commandBuffer;
425 void deinitCommandBuffers (const vk::DeviceInterface& vkd,
427 vk::VkCommandPool commandPool,
428 std::vector<vk::VkCommandBuffer>& commandBuffers)
430 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
432 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
433 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
435 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
438 commandBuffers.clear();
441 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
443 deUint32 queueFamilyIndex)
445 const vk::VkCommandPoolCreateInfo createInfo =
447 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
453 return vk::createCommandPool(vkd, device, &createInfo);
456 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd,
458 vk::VkRenderPass renderPass,
459 vk::VkImageView imageView,
463 const vk::VkFramebufferCreateInfo createInfo =
465 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
477 return vk::createFramebuffer(vkd, device, &createInfo);
480 void initFramebuffers (const vk::DeviceInterface& vkd,
482 vk::VkRenderPass renderPass,
483 std::vector<vk::VkImageView> imageViews,
486 std::vector<vk::VkFramebuffer>& framebuffers)
488 DE_ASSERT(framebuffers.size() == imageViews.size());
490 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
491 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
494 void deinitFramebuffers (const vk::DeviceInterface& vkd,
496 std::vector<vk::VkFramebuffer>& framebuffers)
498 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
500 if (framebuffers[ndx] != (vk::VkFramebuffer)0)
501 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
503 framebuffers[ndx] = (vk::VkFramebuffer)0;
506 framebuffers.clear();
509 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
514 const vk::VkImageViewCreateInfo createInfo =
516 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
521 vk::VK_IMAGE_VIEW_TYPE_2D,
523 vk::makeComponentMappingRGBA(),
525 vk::VK_IMAGE_ASPECT_COLOR_BIT,
533 return vk::createImageView(vkd, device, &createInfo, DE_NULL);
536 void initImageViews (const vk::DeviceInterface& vkd,
538 const std::vector<vk::VkImage>& images,
540 std::vector<vk::VkImageView>& imageViews)
542 DE_ASSERT(images.size() == imageViews.size());
544 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
545 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
548 void deinitImageViews (const vk::DeviceInterface& vkd,
550 std::vector<vk::VkImageView>& imageViews)
552 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
554 if (imageViews[ndx] != (vk::VkImageView)0)
555 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
557 imageViews[ndx] = (vk::VkImageView)0;
563 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
567 return vk::makeRenderPass(vkd, device, format, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_LOAD, vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
570 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd,
572 vk::VkRenderPass renderPass,
573 vk::VkPipelineLayout layout,
574 vk::VkShaderModule vertexShaderModule,
575 vk::VkShaderModule fragmentShaderModule,
579 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
581 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
589 const std::vector<vk::VkViewport> viewports (1, vk::makeViewport(tcu::UVec2(width, height)));
590 const std::vector<vk::VkRect2D> scissors (1, vk::makeRect2D(tcu::UVec2(width, height)));
592 return vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk
593 device, // const VkDevice device
594 layout, // const VkPipelineLayout pipelineLayout
595 vertexShaderModule, // const VkShaderModule vertexShaderModule
596 DE_NULL, // const VkShaderModule tessellationControlShaderModule
597 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
598 DE_NULL, // const VkShaderModule geometryShaderModule
599 fragmentShaderModule, // const VkShaderModule fragmentShaderModule
600 renderPass, // const VkRenderPass renderPass
601 viewports, // const std::vector<VkViewport>& viewports
602 scissors, // const std::vector<VkRect2D>& scissors
603 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
604 0u, // const deUint32 subpass
605 0u, // const deUint32 patchControlPoints
606 &vertexInputState); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
609 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
612 const vk::VkPushConstantRange pushConstants[] =
615 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
620 const vk::VkPipelineLayoutCreateInfo createInfo =
622 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
629 DE_LENGTH_OF_ARRAY(pushConstants),
633 return vk::createPipelineLayout(vkd, device, &createInfo);
638 vk::wsi::Type wsiType;
640 bool useIncrementalPresent;
641 vk::VkPresentModeKHR presentMode;
642 vk::VkSurfaceTransformFlagsKHR transform;
643 vk::VkCompositeAlphaFlagsKHR alpha;
646 class IncrementalPresentTestInstance : public TestInstance
649 IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig);
650 ~IncrementalPresentTestInstance (void);
652 tcu::TestStatus iterate (void);
655 const TestConfig m_testConfig;
656 const bool m_useIncrementalPresent;
657 const vk::PlatformInterface& m_vkp;
658 const Extensions m_instanceExtensions;
659 const CustomInstance m_instance;
660 const vk::InstanceDriver& m_vki;
661 const vk::VkPhysicalDevice m_physicalDevice;
662 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
663 const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
664 const vk::Unique<vk::VkSurfaceKHR> m_surface;
666 const deUint32 m_queueFamilyIndex;
667 const Extensions m_deviceExtensions;
668 const vk::Unique<vk::VkDevice> m_device;
669 const vk::DeviceDriver m_vkd;
670 const vk::VkQueue m_queue;
672 const vk::Unique<vk::VkCommandPool> m_commandPool;
673 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
674 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
675 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
677 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
678 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
679 const vector<vk::VkPresentModeKHR> m_presentModes;
681 tcu::ResultCollector m_resultCollector;
683 vk::Move<vk::VkSwapchainKHR> m_swapchain;
684 std::vector<vk::VkImage> m_swapchainImages;
685 std::vector<size_t> m_imageNextFrames;
686 std::vector<bool> m_isFirst;
688 vk::Move<vk::VkRenderPass> m_renderPass;
689 vk::Move<vk::VkPipeline> m_pipeline;
691 std::vector<vk::VkImageView> m_swapchainImageViews;
692 std::vector<vk::VkFramebuffer> m_framebuffers;
693 std::vector<vk::VkCommandBuffer> m_commandBuffers;
694 std::vector<vk::VkSemaphore> m_acquireSemaphores;
695 std::vector<vk::VkSemaphore> m_renderSemaphores;
696 std::vector<vk::VkFence> m_fences;
698 vk::VkSemaphore m_freeAcquireSemaphore;
699 vk::VkSemaphore m_freeRenderSemaphore;
701 std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs;
702 size_t m_swapchainConfigNdx;
704 const size_t m_frameCount;
707 const size_t m_maxOutOfDateCount;
708 size_t m_outOfDateCount;
710 void initSwapchainResources (void);
711 void deinitSwapchainResources (void);
715 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR surface,
716 const deUint32 *queueFamilyIndex,
718 const vk::VkSurfaceCapabilitiesKHR& properties,
719 const vector<vk::VkSurfaceFormatKHR>& formats,
720 const vector<vk::VkPresentModeKHR>& presentModes,
721 vk::VkPresentModeKHR presentMode,
722 const vk::VkSurfaceTransformFlagsKHR transform,
723 const vk::VkCompositeAlphaFlagsKHR alpha)
725 const deUint32 imageLayers = 1u;
726 const vk::VkImageUsageFlags imageUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
727 const vk::VkBool32 clipped = VK_FALSE;
728 vector<vk::VkSwapchainCreateInfoKHR> createInfos;
730 const deUint32 currentWidth = properties.currentExtent.width != 0xFFFFFFFFu
731 ? properties.currentExtent.width
732 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
733 const deUint32 currentHeight = properties.currentExtent.height != 0xFFFFFFFFu
734 ? properties.currentExtent.height
735 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
737 const deUint32 imageWidth = scaling == SCALING_NONE
739 : (scaling == SCALING_UP
740 ? de::max(31u, properties.minImageExtent.width)
741 : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentWidth+1), properties.maxImageExtent.width));
742 const deUint32 imageHeight = scaling == SCALING_NONE
744 : (scaling == SCALING_UP
745 ? de::max(31u, properties.minImageExtent.height)
746 : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentHeight+1), properties.maxImageExtent.height));
747 const vk::VkExtent2D imageSize = { imageWidth, imageHeight };
748 const vk::VkExtent2D dummySize = { de::max(31u, properties.minImageExtent.width), de::max(31u, properties.minImageExtent.height) };
751 size_t presentModeNdx;
753 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
755 if (presentModes[presentModeNdx] == presentMode)
759 if (presentModeNdx == presentModes.size())
760 TCU_THROW(NotSupportedError, "Present mode not supported");
762 if ((properties.supportedTransforms & transform) == 0)
763 TCU_THROW(NotSupportedError, "Transform not supported");
765 if ((properties.supportedCompositeAlpha & alpha) == 0)
766 TCU_THROW(NotSupportedError, "Composite alpha not supported");
769 for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
772 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
773 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
774 const vk::VkFormat imageFormat = formats[formatNdx].format;
775 const vk::VkColorSpaceKHR imageColorSpace = formats[formatNdx].colorSpace;
776 const vk::VkSwapchainCreateInfoKHR createInfo =
778 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
782 properties.minImageCount,
788 vk::VK_SHARING_MODE_EXCLUSIVE,
795 (vk::VkSwapchainKHR)0
798 createInfos.push_back(createInfo);
800 // add an extra dummy swapchain
801 const vk::VkSwapchainCreateInfoKHR dummyInfo =
803 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
807 properties.minImageCount,
813 vk::VK_SHARING_MODE_EXCLUSIVE,
820 (vk::VkSwapchainKHR)0
823 createInfos.push_back(dummyInfo);
829 IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig)
830 : TestInstance (context)
831 , m_testConfig (testConfig)
832 , m_useIncrementalPresent (testConfig.useIncrementalPresent)
833 , m_vkp (context.getPlatformInterface())
834 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
835 , m_instance (createInstanceWithWsi(context, m_instanceExtensions, testConfig.wsiType))
836 , m_vki (m_instance.getDriver())
837 , m_physicalDevice (vk::chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
838 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
839 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
840 , m_surface (vk::wsi::createSurface(m_vki, m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
842 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
843 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
844 , m_device (createDeviceWithWsi(m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent, context.getTestContext().getCommandLine().isValidationEnabled()))
845 , m_vkd (m_vkp, m_instance, *m_device)
846 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
848 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
849 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
850 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
851 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device))
853 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
854 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
855 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
857 , m_freeAcquireSemaphore ((vk::VkSemaphore)0)
858 , m_freeRenderSemaphore ((vk::VkSemaphore)0)
860 , m_swapchainConfigs (generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, testConfig.transform, testConfig.alpha))
861 , m_swapchainConfigNdx (0u)
863 , m_frameCount (60u * 5u)
866 , m_maxOutOfDateCount (20u)
867 , m_outOfDateCount (0u)
870 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
871 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
875 IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void)
877 deinitSwapchainResources();
880 void IncrementalPresentTestInstance::initSwapchainResources (void)
882 const size_t fenceCount = 6;
883 const deUint32 imageWidth = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
884 const deUint32 imageHeight = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
885 const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
887 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
888 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
890 m_imageNextFrames.resize(m_swapchainImages.size(), 0);
891 m_isFirst.resize(m_swapchainImages.size(), true);
893 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
894 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
896 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
897 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
898 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
899 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
901 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
902 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
904 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
905 m_freeRenderSemaphore = (vk::VkSemaphore)0;
907 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
908 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown();
910 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
911 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
912 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
913 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
915 initFences(m_vkd, *m_device, m_fences);
918 void IncrementalPresentTestInstance::deinitSwapchainResources (void)
920 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
922 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
924 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
925 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
928 if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
930 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
931 m_freeRenderSemaphore = (vk::VkSemaphore)0;
934 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
935 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
936 deinitFences(m_vkd, *m_device, m_fences);
937 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
938 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
939 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
941 m_swapchainImages.clear();
942 m_imageNextFrames.clear();
945 m_swapchain = vk::Move<vk::VkSwapchainKHR>();
946 m_renderPass = vk::Move<vk::VkRenderPass>();
947 m_pipeline = vk::Move<vk::VkPipeline>();
951 void IncrementalPresentTestInstance::render (void)
953 const deUint64 foreverNs = 0xFFFFFFFFFFFFFFFFul;
954 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()];
955 const deUint32 width = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
956 const deUint32 height = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
957 size_t imageNextFrame;
959 // Throttle execution
960 if (m_frameNdx >= m_fences.size())
962 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
963 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
965 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
966 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
969 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
970 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore;
973 // Acquire next image
974 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex));
976 // Create command buffer
978 imageNextFrame = m_imageNextFrames[imageIndex];
979 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();
980 m_imageNextFrames[imageIndex] = m_frameNdx + 1;
981 m_isFirst[imageIndex] = false;
984 // Submit command buffer
986 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
987 const vk::VkSubmitInfo submitInfo =
989 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
992 ¤tAcquireSemaphore,
995 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
997 ¤tRenderSemaphore
1000 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
1004 if (m_useIncrementalPresent)
1006 vk::VkResult result;
1007 const vector<vk::VkRectLayerKHR> rects = getUpdatedRects(imageNextFrame, m_frameNdx, width, height);
1008 const vk::VkPresentRegionKHR region =
1010 (deUint32)rects.size(),
1011 rects.empty() ? DE_NULL : &rects[0]
1013 const vk::VkPresentRegionsKHR regionInfo =
1015 vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
1020 const vk::VkPresentInfoKHR presentInfo =
1022 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1025 ¤tRenderSemaphore,
1032 VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1033 VK_CHECK_WSI(result);
1037 vk::VkResult result;
1038 const vk::VkPresentInfoKHR presentInfo =
1040 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1043 ¤tRenderSemaphore,
1050 VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1051 VK_CHECK_WSI(result);
1055 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1056 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1058 m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1059 m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1063 tcu::TestStatus IncrementalPresentTestInstance::iterate (void)
1065 // Initialize swapchain specific resources
1069 if (m_frameNdx == 0)
1071 if (m_outOfDateCount == 0)
1072 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
1074 initSwapchainResources();
1079 catch (const vk::Error& error)
1081 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1083 m_swapchainConfigs = generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_testConfig.transform, m_testConfig.alpha);
1085 if (m_outOfDateCount < m_maxOutOfDateCount)
1087 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1088 deinitSwapchainResources();
1092 return tcu::TestStatus::incomplete();
1096 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1097 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1102 m_resultCollector.fail(error.what());
1105 deinitSwapchainResources();
1107 m_swapchainConfigNdx++;
1109 m_outOfDateCount = 0;
1111 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1112 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1114 return tcu::TestStatus::incomplete();
1119 if (m_frameNdx >= m_frameCount)
1122 m_outOfDateCount = 0;
1123 m_swapchainConfigNdx++;
1125 deinitSwapchainResources();
1127 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1128 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1130 return tcu::TestStatus::incomplete();
1133 return tcu::TestStatus::incomplete();
1138 static void init (vk::SourceCollections& dst, TestConfig)
1140 dst.glslSources.add("quad-vert") << glu::VertexSource(
1142 "out gl_PerVertex {\n"
1143 "\tvec4 gl_Position;\n"
1146 "void main (void) {\n"
1147 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1148 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1150 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1152 "layout(location = 0) out highp vec4 o_color;\n"
1153 "layout(push_constant) uniform PushConstant {\n"
1154 "\thighp uint mask;\n"
1155 "} pushConstants;\n"
1156 "void main (void)\n"
1158 "\thighp uint mask = pushConstants.mask;\n"
1159 "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n"
1160 "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n"
1161 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1162 "\t + 64u * bitfieldExtract(y, 1, 1)\n"
1163 "\t + 32u * bitfieldExtract(x, 3, 1);\n"
1164 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1165 "\t + 64u * bitfieldExtract(x, 2, 1)\n"
1166 "\t + 32u * bitfieldExtract(y, 3, 1);\n"
1167 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1168 "\t + 64u * bitfieldExtract(y, 2, 1)\n"
1169 "\t + 32u * bitfieldExtract(x, 4, 1);\n"
1170 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1177 void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1185 { SCALING_NONE, "scale_none" },
1186 { SCALING_UP, "scale_up" },
1187 { SCALING_DOWN, "scale_down" }
1191 vk::VkPresentModeKHR mode;
1195 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" },
1196 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" },
1197 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" },
1198 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" }
1202 vk::VkSurfaceTransformFlagsKHR transform;
1206 { vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, "identity" },
1207 { vk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, "rotate_90" },
1208 { vk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, "rotate_180" },
1209 { vk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, "rotate_270" },
1210 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, "horizontal_mirror" },
1211 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, "horizontal_mirror_rotate_90" },
1212 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, "horizontal_mirror_rotate_180" },
1213 { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, "horizontal_mirror_rotate_270" },
1214 { vk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, "inherit" }
1218 vk::VkCompositeAlphaFlagsKHR alpha;
1222 { vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, "opaque" },
1223 { vk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, "pre_multiplied" },
1224 { vk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, "post_multiplied" },
1225 { vk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, "inherit" }
1228 for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1230 if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND)
1233 if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
1238 de::MovePtr<tcu::TestCaseGroup> scaleGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
1240 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1242 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1244 for (size_t transformNdx = 0; transformNdx < DE_LENGTH_OF_ARRAY(transforms); transformNdx++)
1246 de::MovePtr<tcu::TestCaseGroup> transformGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), transforms[transformNdx].name, transforms[transformNdx].name));
1248 for (size_t alphaNdx = 0; alphaNdx < DE_LENGTH_OF_ARRAY(alphas); alphaNdx++)
1250 de::MovePtr<tcu::TestCaseGroup> alphaGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), alphas[alphaNdx].name, alphas[alphaNdx].name));
1252 for (size_t ref = 0; ref < 2; ref++)
1254 const bool isReference = (ref == 0);
1255 const char* const name = isReference ? "reference" : "incremental_present";
1258 config.wsiType = wsiType;
1259 config.scaling = scaling[scalingNdx].scaling;
1260 config.useIncrementalPresent = !isReference;
1261 config.presentMode = presentModes[presentModeNdx].mode;
1262 config.transform = transforms[transformNdx].transform;
1263 config.alpha = alphas[alphaNdx].alpha;
1265 alphaGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1268 transformGroup->addChild(alphaGroup.release());
1271 presentModeGroup->addChild(transformGroup.release());
1274 scaleGroup->addChild(presentModeGroup.release());
1277 testGroup->addChild(scaleGroup.release());