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 "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"
37 #include "vkWsiUtil.hpp"
39 #include "tcuPlatform.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTestLog.hpp"
66 typedef vector<vk::VkExtensionProperties> Extensions;
68 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
70 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
71 requiredExtName != requiredExtensions.end();
74 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
75 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
79 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp,
80 const Extensions& supportedExtensions,
81 vk::wsi::Type wsiType)
83 vector<string> extensions;
85 extensions.push_back("VK_KHR_surface");
86 extensions.push_back(getExtensionName(wsiType));
88 checkAllSupported(supportedExtensions, extensions);
90 return vk::createDefaultInstance(vkp, vector<string>(), extensions);
93 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
95 vk::VkPhysicalDeviceFeatures features;
96 deMemset(&features, 0, sizeof(features));
100 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
102 deUint32 numFamilies = 0;
104 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
109 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
111 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
112 vector<deUint32> supportedFamilyIndices;
114 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
116 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
117 supportedFamilyIndices.push_back(queueFamilyNdx);
120 return supportedFamilyIndices;
123 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
125 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
127 if (supportedFamilyIndices.empty())
128 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
130 return supportedFamilyIndices[0];
133 vk::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)
140 const float queuePriorities[] = { 1.0f };
141 const vk::VkDeviceQueueCreateInfo queueInfos[] =
144 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
146 (vk::VkDeviceQueueCreateFlags)0,
148 DE_LENGTH_OF_ARRAY(queuePriorities),
152 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures();
153 const char* const extensions[] =
156 "VK_KHR_incremental_present"
159 const vk::VkDeviceCreateInfo deviceParams =
161 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
163 (vk::VkDeviceCreateFlags)0,
164 DE_LENGTH_OF_ARRAY(queueInfos),
168 requiresIncrementalPresent ? 2u : 1u,
169 DE_ARRAY_BEGIN(extensions),
173 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
175 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
176 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
179 return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
182 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform,
183 const Extensions& supportedExtensions,
184 vk::wsi::Type wsiType)
188 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
190 catch (const tcu::NotSupportedError& e)
192 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
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());
203 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
207 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
209 catch (const tcu::NotSupportedError& e)
211 // See createDisplay - assuming that wsi::Display was supported platform port
212 // should also support creating a window.
213 throw tcu::TestError(e.getMessage());
217 void initSemaphores (const vk::DeviceInterface& vkd,
219 std::vector<vk::VkSemaphore>& semaphores)
221 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
222 semaphores[ndx] = createSemaphore(vkd, device).disown();
225 void deinitSemaphores (const vk::DeviceInterface& vkd,
227 std::vector<vk::VkSemaphore>& semaphores)
229 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
231 if (semaphores[ndx] != (vk::VkSemaphore)0)
232 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
234 semaphores[ndx] = (vk::VkSemaphore)0;
240 void initFences (const vk::DeviceInterface& vkd,
242 std::vector<vk::VkFence>& fences)
244 for (size_t ndx = 0; ndx < fences.size(); ndx++)
245 fences[ndx] = createFence(vkd, device).disown();
248 void deinitFences (const vk::DeviceInterface& vkd,
250 std::vector<vk::VkFence>& fences)
252 for (size_t ndx = 0; ndx < fences.size(); ndx++)
254 if (fences[ndx] != (vk::VkFence)0)
255 vkd.destroyFence(device, fences[ndx], DE_NULL);
257 fences[ndx] = (vk::VkFence)0;
263 vk::VkRect2D getRenderFrameRect (size_t frameNdx,
265 deUint32 imageHeight)
267 const deUint32 x = frameNdx == 0
269 : de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u);
270 const deUint32 y = frameNdx == 0
272 : de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u);
273 const deUint32 width = frameNdx == 0
275 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x);
276 const deUint32 height = frameNdx == 0
278 : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y);
279 const vk::VkRect2D rect =
281 { (deInt32)x, (deInt32)y },
285 DE_ASSERT(width > 0);
286 DE_ASSERT(height > 0);
291 vector<vk::VkRectLayerKHR> getUpdatedRects (size_t firstFrameNdx,
296 vector<vk::VkRectLayerKHR> rects;
298 for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++)
300 const vk::VkRect2D rect = getRenderFrameRect(frameNdx, width, height);
301 const vk::VkRectLayerKHR rectLayer =
308 rects.push_back(rectLayer);
314 void cmdRenderFrame (const vk::DeviceInterface& vkd,
315 vk::VkCommandBuffer commandBuffer,
316 vk::VkPipelineLayout pipelineLayout,
317 vk::VkPipeline pipeline,
320 deUint32 imageHeight)
322 const deUint32 mask = (deUint32)frameNdx;
326 const vk::VkRect2D scissor =
329 { imageWidth, imageHeight }
332 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
333 const vk::VkClearAttachment attachment =
335 vk::VK_IMAGE_ASPECT_COLOR_BIT,
337 vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f)
339 const vk::VkClearRect rect =
346 vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
350 const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight);
351 vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
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);
359 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
361 vk::VkCommandPool commandPool,
362 vk::VkPipelineLayout pipelineLayout,
363 vk::VkRenderPass renderPass,
364 vk::VkFramebuffer framebuffer,
365 vk::VkPipeline pipeline,
366 size_t imageNextFrame,
369 deUint32 imageHeight)
371 const vk::VkCommandBufferAllocateInfo allocateInfo =
373 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
377 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
380 const vk::VkCommandBufferBeginInfo beginInfo =
382 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
388 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
389 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
392 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f);
393 const vk::VkRenderPassBeginInfo renderPassBeginInfo =
395 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
402 { (deInt32)0, (deInt32)0 },
403 { imageWidth, imageHeight }
408 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
411 for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++)
412 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight);
414 vkd.cmdEndRenderPass(*commandBuffer);
416 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
417 return commandBuffer;
420 void deinitCommandBuffers (const vk::DeviceInterface& vkd,
422 vk::VkCommandPool commandPool,
423 std::vector<vk::VkCommandBuffer>& commandBuffers)
425 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
427 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
428 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
430 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
433 commandBuffers.clear();
436 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
438 deUint32 queueFamilyIndex)
440 const vk::VkCommandPoolCreateInfo createInfo =
442 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
448 return vk::createCommandPool(vkd, device, &createInfo);
451 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd,
453 vk::VkRenderPass renderPass,
454 vk::VkImageView imageView,
458 const vk::VkFramebufferCreateInfo createInfo =
460 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
472 return vk::createFramebuffer(vkd, device, &createInfo);
475 void initFramebuffers (const vk::DeviceInterface& vkd,
477 vk::VkRenderPass renderPass,
478 std::vector<vk::VkImageView> imageViews,
481 std::vector<vk::VkFramebuffer>& framebuffers)
483 DE_ASSERT(framebuffers.size() == imageViews.size());
485 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
486 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
489 void deinitFramebuffers (const vk::DeviceInterface& vkd,
491 std::vector<vk::VkFramebuffer>& framebuffers)
493 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
495 if (framebuffers[ndx] != (vk::VkFramebuffer)0)
496 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
498 framebuffers[ndx] = (vk::VkFramebuffer)0;
501 framebuffers.clear();
504 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
509 const vk::VkImageViewCreateInfo createInfo =
511 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
516 vk::VK_IMAGE_VIEW_TYPE_2D,
518 vk::makeComponentMappingRGBA(),
520 vk::VK_IMAGE_ASPECT_COLOR_BIT,
528 return vk::createImageView(vkd, device, &createInfo, DE_NULL);
531 void initImageViews (const vk::DeviceInterface& vkd,
533 const std::vector<vk::VkImage>& images,
535 std::vector<vk::VkImageView>& imageViews)
537 DE_ASSERT(images.size() == imageViews.size());
539 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
540 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
543 void deinitImageViews (const vk::DeviceInterface& vkd,
545 std::vector<vk::VkImageView>& imageViews)
547 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
549 if (imageViews[ndx] != (vk::VkImageView)0)
550 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
552 imageViews[ndx] = (vk::VkImageView)0;
558 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
562 const vk::VkAttachmentDescription attachments[] =
567 vk::VK_SAMPLE_COUNT_1_BIT,
569 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
570 vk::VK_ATTACHMENT_STORE_OP_STORE,
572 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
573 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
575 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
576 vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
579 const vk::VkAttachmentReference colorAttachmentRefs[] =
583 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
586 const vk::VkSubpassDescription subpasses[] =
590 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
594 DE_LENGTH_OF_ARRAY(colorAttachmentRefs),
604 const vk::VkRenderPassCreateInfo createInfo =
606 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
610 DE_LENGTH_OF_ARRAY(attachments),
613 DE_LENGTH_OF_ARRAY(subpasses),
620 return vk::createRenderPass(vkd, device, &createInfo);
623 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd,
625 vk::VkRenderPass renderPass,
626 vk::VkPipelineLayout layout,
627 vk::VkShaderModule vertexShaderModule,
628 vk::VkShaderModule fragmentShaderModule,
632 const vk::VkSpecializationInfo shaderSpecialization =
639 const vk::VkPipelineShaderStageCreateInfo stages[] =
642 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
645 vk::VK_SHADER_STAGE_VERTEX_BIT,
648 &shaderSpecialization
651 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
654 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
655 fragmentShaderModule,
657 &shaderSpecialization
660 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
662 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
670 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
672 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
675 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
678 const vk::VkViewport viewports[] =
682 (float)width, (float)height,
686 const vk::VkRect2D scissors[] =
693 const vk::VkPipelineViewportStateCreateInfo viewportState =
695 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
699 DE_LENGTH_OF_ARRAY(viewports),
701 DE_LENGTH_OF_ARRAY(scissors),
704 const vk::VkPipelineRasterizationStateCreateInfo rasterizationState =
706 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
711 vk::VK_POLYGON_MODE_FILL,
712 vk::VK_CULL_MODE_NONE,
713 vk::VK_FRONT_FACE_CLOCKWISE,
720 const vk::VkSampleMask sampleMask = ~0u;
721 const vk::VkPipelineMultisampleStateCreateInfo multisampleState =
723 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
726 vk::VK_SAMPLE_COUNT_1_BIT,
733 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilState =
735 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
740 vk::VK_COMPARE_OP_ALWAYS,
744 vk::VK_STENCIL_OP_KEEP,
745 vk::VK_STENCIL_OP_KEEP,
746 vk::VK_STENCIL_OP_KEEP,
747 vk::VK_COMPARE_OP_ALWAYS,
753 vk::VK_STENCIL_OP_KEEP,
754 vk::VK_STENCIL_OP_KEEP,
755 vk::VK_STENCIL_OP_KEEP,
756 vk::VK_COMPARE_OP_ALWAYS,
764 const vk::VkPipelineColorBlendAttachmentState attachmentBlendState =
767 vk::VK_BLEND_FACTOR_ONE,
768 vk::VK_BLEND_FACTOR_ZERO,
770 vk::VK_BLEND_FACTOR_ONE,
771 vk::VK_BLEND_FACTOR_ZERO,
773 (vk::VK_COLOR_COMPONENT_R_BIT|
774 vk::VK_COLOR_COMPONENT_G_BIT|
775 vk::VK_COLOR_COMPONENT_B_BIT|
776 vk::VK_COLOR_COMPONENT_A_BIT),
778 const vk::VkPipelineColorBlendStateCreateInfo blendState =
780 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
784 vk::VK_LOGIC_OP_COPY,
786 &attachmentBlendState,
787 { 0.0f, 0.0f, 0.0f, 0.0f }
789 const vk::VkDynamicState dynamicStates[] =
791 vk::VK_DYNAMIC_STATE_SCISSOR
793 const vk::VkPipelineDynamicStateCreateInfo dynamicState =
795 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
799 DE_LENGTH_OF_ARRAY(dynamicStates),
802 const vk::VkGraphicsPipelineCreateInfo createInfo =
804 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
808 DE_LENGTH_OF_ARRAY(stages),
826 return vk::createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
829 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
832 const vk::VkPushConstantRange pushConstants[] =
835 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
840 const vk::VkPipelineLayoutCreateInfo createInfo =
842 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
849 DE_LENGTH_OF_ARRAY(pushConstants),
853 return vk::createPipelineLayout(vkd, device, &createInfo);
858 vk::wsi::Type wsiType;
860 bool useIncrementalPresent;
861 vk::VkPresentModeKHR presentMode;
864 class IncrementalPresentTestInstance : public TestInstance
867 IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig);
868 ~IncrementalPresentTestInstance (void);
870 tcu::TestStatus iterate (void);
873 const TestConfig m_testConfig;
874 const bool m_useIncrementalPresent;
875 const vk::PlatformInterface& m_vkp;
876 const Extensions m_instanceExtensions;
877 const vk::Unique<vk::VkInstance> m_instance;
878 const vk::InstanceDriver m_vki;
879 const vk::VkPhysicalDevice m_physicalDevice;
880 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
881 const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
882 const vk::Unique<vk::VkSurfaceKHR> m_surface;
884 const deUint32 m_queueFamilyIndex;
885 const Extensions m_deviceExtensions;
886 const vk::Unique<vk::VkDevice> m_device;
887 const vk::DeviceDriver m_vkd;
888 const vk::VkQueue m_queue;
890 const vk::Unique<vk::VkCommandPool> m_commandPool;
891 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
892 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
893 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
895 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
896 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
897 const vector<vk::VkPresentModeKHR> m_presentModes;
899 tcu::ResultCollector m_resultCollector;
901 vk::Move<vk::VkSwapchainKHR> m_swapchain;
902 std::vector<vk::VkImage> m_swapchainImages;
903 std::vector<size_t> m_imageNextFrames;
905 vk::Move<vk::VkRenderPass> m_renderPass;
906 vk::Move<vk::VkPipeline> m_pipeline;
908 std::vector<vk::VkImageView> m_swapchainImageViews;
909 std::vector<vk::VkFramebuffer> m_framebuffers;
910 std::vector<vk::VkCommandBuffer> m_commandBuffers;
911 std::vector<vk::VkSemaphore> m_acquireSemaphores;
912 std::vector<vk::VkSemaphore> m_renderSemaphores;
913 std::vector<vk::VkFence> m_fences;
915 vk::VkSemaphore m_freeAcquireSemaphore;
916 vk::VkSemaphore m_freeRenderSemaphore;
918 std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs;
919 size_t m_swapchainConfigNdx;
921 const size_t m_frameCount;
924 const size_t m_maxOutOfDateCount;
925 size_t m_outOfDateCount;
927 void initSwapchainResources (void);
928 void deinitSwapchainResources (void);
932 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR surface,
933 deUint32 queueFamilyIndex,
935 const vk::VkSurfaceCapabilitiesKHR& properties,
936 const vector<vk::VkSurfaceFormatKHR>& formats,
937 const vector<vk::VkPresentModeKHR>& presentModes,
938 vk::VkPresentModeKHR presentMode)
940 const deUint32 imageLayers = 1u;
941 const vk::VkImageUsageFlags imageUsage = properties.supportedUsageFlags;
942 const vk::VkBool32 clipped = VK_FALSE;
943 vector<vk::VkSwapchainCreateInfoKHR> createInfos;
945 const deUint32 imageWidth = scaling == SCALING_NONE
946 ? (properties.currentExtent.width != 0xFFFFFFFFu
947 ? properties.currentExtent.width
948 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2)))
949 : (scaling == SCALING_UP
950 ? de::max(31u, properties.minImageExtent.width)
951 : properties.maxImageExtent.width);
952 const deUint32 imageHeight = scaling == SCALING_NONE
953 ? (properties.currentExtent.height != 0xFFFFFFFFu
954 ? properties.currentExtent.height
955 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2)))
956 : (scaling == SCALING_UP
957 ? de::max(31u, properties.minImageExtent.height)
958 : properties.maxImageExtent.height);
959 const vk::VkExtent2D imageSize = { imageWidth, imageHeight };
962 size_t presentModeNdx;
964 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
966 if (presentModes[presentModeNdx] == presentMode)
970 if (presentModeNdx == presentModes.size())
971 TCU_THROW(NotSupportedError, "Present mode not supported");
974 for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
976 for (vk::VkSurfaceTransformFlagsKHR transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
978 if ((properties.supportedTransforms & transform) == 0)
981 for (vk::VkCompositeAlphaFlagsKHR alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
983 if ((alpha & properties.supportedCompositeAlpha) == 0)
986 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
987 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
988 const vk::VkFormat imageFormat = formats[formatNdx].format;
989 const vk::VkColorSpaceKHR imageColorSpace = formats[formatNdx].colorSpace;
990 const vk::VkSwapchainCreateInfoKHR createInfo =
992 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
996 properties.minImageCount,
1002 vk::VK_SHARING_MODE_EXCLUSIVE,
1009 (vk::VkSwapchainKHR)0
1012 createInfos.push_back(createInfo);
1020 IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig)
1021 : TestInstance (context)
1022 , m_testConfig (testConfig)
1023 , m_useIncrementalPresent (testConfig.useIncrementalPresent)
1024 , m_vkp (context.getPlatformInterface())
1025 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
1026 , m_instance (createInstanceWithWsi(m_vkp, m_instanceExtensions, testConfig.wsiType))
1027 , m_vki (m_vkp, *m_instance)
1028 , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
1029 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
1030 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
1031 , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
1033 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
1034 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
1035 , m_device (createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent))
1036 , m_vkd (m_vki, *m_device)
1037 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
1039 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
1040 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
1041 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
1042 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device))
1044 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
1045 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
1046 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
1048 , m_freeAcquireSemaphore ((vk::VkSemaphore)0)
1049 , m_freeRenderSemaphore ((vk::VkSemaphore)0)
1051 , m_swapchainConfigs (generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode))
1052 , m_swapchainConfigNdx (0u)
1054 , m_frameCount (60u * 5u)
1057 , m_maxOutOfDateCount (20u)
1058 , m_outOfDateCount (0u)
1061 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
1062 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
1066 IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void)
1068 deinitSwapchainResources();
1071 void IncrementalPresentTestInstance::initSwapchainResources (void)
1073 const size_t fenceCount = 6;
1074 const deUint32 imageWidth = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
1075 const deUint32 imageHeight = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
1076 const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
1078 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
1079 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
1081 m_imageNextFrames.resize(m_swapchainImages.size(), 0);
1083 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
1084 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
1086 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
1087 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
1088 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
1089 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
1091 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
1092 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
1094 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
1095 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1097 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
1098 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown();
1100 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
1101 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
1102 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1103 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
1105 initFences(m_vkd, *m_device, m_fences);
1108 void IncrementalPresentTestInstance::deinitSwapchainResources (void)
1110 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
1112 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
1114 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
1115 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
1118 if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
1120 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
1121 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1124 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1125 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
1126 deinitFences(m_vkd, *m_device, m_fences);
1127 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
1128 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
1129 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
1131 m_swapchainImages.clear();
1132 m_imageNextFrames.clear();
1134 m_swapchain = vk::Move<vk::VkSwapchainKHR>();
1135 m_renderPass = vk::Move<vk::VkRenderPass>();
1136 m_pipeline = vk::Move<vk::VkPipeline>();
1140 void IncrementalPresentTestInstance::render (void)
1142 const deUint64 foreverNs = 0xFFFFFFFFFFFFFFFFul;
1143 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()];
1144 const deUint32 width = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
1145 const deUint32 height = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
1146 size_t imageNextFrame;
1148 // Throttle execution
1149 if (m_frameNdx >= m_fences.size())
1151 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
1152 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
1154 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
1155 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
1158 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
1159 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore;
1160 deUint32 imageIndex;
1162 // Acquire next image
1163 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, fence, &imageIndex));
1165 // Create command buffer
1167 imageNextFrame = m_imageNextFrames[imageIndex];
1168 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, imageNextFrame, m_frameNdx, width, height).disown();
1169 m_imageNextFrames[imageIndex] = m_frameNdx + 1;
1172 // Submit command buffer
1174 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1175 const vk::VkSubmitInfo submitInfo =
1177 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1180 ¤tAcquireSemaphore,
1183 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
1185 ¤tRenderSemaphore
1188 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, (vk::VkFence)0));
1192 if (m_useIncrementalPresent)
1194 vk::VkResult result;
1195 const vector<vk::VkRectLayerKHR> rects = getUpdatedRects(imageNextFrame, m_frameNdx, width, height);
1196 const vk::VkPresentRegionKHR region =
1198 (deUint32)rects.size(),
1199 rects.empty() ? DE_NULL : &rects[0]
1201 const vk::VkPresentRegionsKHR regionInfo =
1203 vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
1208 const vk::VkPresentInfoKHR presentInfo =
1210 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1213 ¤tRenderSemaphore,
1220 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1225 vk::VkResult result;
1226 const vk::VkPresentInfoKHR presentInfo =
1228 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1231 ¤tRenderSemaphore,
1238 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1243 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1244 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1246 m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1247 m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1251 tcu::TestStatus IncrementalPresentTestInstance::iterate (void)
1253 // Initialize swapchain specific resources
1257 if (m_frameNdx == 0)
1259 if (m_outOfDateCount == 0)
1260 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage;
1262 initSwapchainResources();
1267 catch (const vk::Error& error)
1269 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1271 m_swapchainConfigs = generateSwapchainConfigs(*m_surface, m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode);
1273 if (m_outOfDateCount < m_maxOutOfDateCount)
1275 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1276 deinitSwapchainResources();
1280 return tcu::TestStatus::incomplete();
1284 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1285 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1290 m_resultCollector.fail(error.what());
1293 deinitSwapchainResources();
1295 m_swapchainConfigNdx++;
1297 m_outOfDateCount = 0;
1299 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1300 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1302 return tcu::TestStatus::incomplete();
1307 if (m_frameNdx >= m_frameCount)
1310 m_outOfDateCount = 0;
1311 m_swapchainConfigNdx++;
1313 deinitSwapchainResources();
1315 if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
1316 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1318 return tcu::TestStatus::incomplete();
1321 return tcu::TestStatus::incomplete();
1326 static void init (vk::SourceCollections& dst, TestConfig)
1328 dst.glslSources.add("quad-vert") << glu::VertexSource(
1330 "out gl_PerVertex {\n"
1331 "\tvec4 gl_Position;\n"
1334 "void main (void) {\n"
1335 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1336 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1338 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1340 "layout(location = 0) out highp vec4 o_color;\n"
1341 "layout(push_constant) uniform PushConstant {\n"
1342 "\thighp uint mask;\n"
1343 "} pushConstants;\n"
1344 "void main (void)\n"
1346 "\thighp uint mask = pushConstants.mask;\n"
1347 "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n"
1348 "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n"
1349 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1350 "\t + 64u * bitfieldExtract(y, 1, 1)\n"
1351 "\t + 32u * bitfieldExtract(x, 3, 1);\n"
1352 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1353 "\t + 64u * bitfieldExtract(x, 2, 1)\n"
1354 "\t + 32u * bitfieldExtract(y, 3, 1);\n"
1355 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1356 "\t + 64u * bitfieldExtract(y, 2, 1)\n"
1357 "\t + 32u * bitfieldExtract(x, 4, 1);\n"
1358 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1365 void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1373 { SCALING_NONE, "scale_none" },
1374 { SCALING_UP, "scale_up" },
1375 { SCALING_DOWN, "scale_down" }
1379 vk::VkPresentModeKHR mode;
1383 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" },
1384 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" },
1385 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" },
1386 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" }
1389 for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1391 if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND)
1394 if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
1399 de::MovePtr<tcu::TestCaseGroup> scaleGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name));
1401 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1403 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1405 for (size_t ref = 0; ref < 2; ref++)
1407 const bool isReference = (ref == 0);
1408 const char* const name = isReference ? "reference" : "incremental_present";
1411 config.wsiType = wsiType;
1412 config.scaling = scaling[scalingNdx].scaling;
1413 config.useIncrementalPresent = !isReference;
1414 config.presentMode = presentModes[presentModeNdx].mode;
1416 presentModeGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1419 scaleGroup->addChild(presentModeGroup.release());
1422 testGroup->addChild(scaleGroup.release());