xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/wsi/vktWsiIncrementalPresentTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 "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"
39 
40 #include "vkWsiUtil.hpp"
41 
42 #include "tcuPlatform.hpp"
43 #include "tcuResultCollector.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuCommandLine.hpp"
46 
47 #include <vector>
48 #include <string>
49 
50 using std::string;
51 using std::vector;
52 
53 using tcu::Maybe;
54 using tcu::TestLog;
55 using tcu::UVec2;
56 
57 namespace vkt
58 {
59 namespace wsi
60 {
61 namespace
62 {
63 enum Scaling
64 {
65     SCALING_NONE,
66     SCALING_UP,
67     SCALING_DOWN
68 };
69 
70 typedef vector<vk::VkExtensionProperties> Extensions;
71 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)72 void checkAllSupported(const Extensions &supportedExtensions, const vector<string> &requiredExtensions)
73 {
74     for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
75          requiredExtName != requiredExtensions.end(); ++requiredExtName)
76     {
77         if (!isExtensionStructSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
78             TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
79     }
80 }
81 
createInstanceWithWsi(Context & context,const Extensions & supportedExtensions,vk::wsi::Type wsiType)82 CustomInstance createInstanceWithWsi(Context &context, const Extensions &supportedExtensions, vk::wsi::Type wsiType)
83 {
84     vector<string> extensions;
85 
86     extensions.push_back("VK_KHR_surface");
87     extensions.push_back(getExtensionName(wsiType));
88     if (isDisplaySurface(wsiType))
89         extensions.push_back("VK_KHR_display");
90 
91     checkAllSupported(supportedExtensions, extensions);
92 
93     return vkt::createCustomInstanceWithExtensions(context, extensions);
94 }
95 
getDeviceNullFeatures(void)96 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures(void)
97 {
98     vk::VkPhysicalDeviceFeatures features;
99     deMemset(&features, 0, sizeof(features));
100     return features;
101 }
102 
createDeviceWithWsi(const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const uint32_t queueFamilyIndex,bool requiresIncrementalPresent,bool validationEnabled,const vk::VkAllocationCallbacks * pAllocator=DE_NULL)103 vk::Move<vk::VkDevice> createDeviceWithWsi(const vk::PlatformInterface &vkp, vk::VkInstance instance,
104                                            const vk::InstanceInterface &vki, vk::VkPhysicalDevice physicalDevice,
105                                            const Extensions &supportedExtensions, const uint32_t queueFamilyIndex,
106                                            bool requiresIncrementalPresent, bool validationEnabled,
107                                            const vk::VkAllocationCallbacks *pAllocator = DE_NULL)
108 {
109     const float queuePriorities[]                  = {1.0f};
110     const vk::VkDeviceQueueCreateInfo queueInfos[] = {{vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, DE_NULL,
111                                                        (vk::VkDeviceQueueCreateFlags)0, queueFamilyIndex,
112                                                        DE_LENGTH_OF_ARRAY(queuePriorities), &queuePriorities[0]}};
113     const vk::VkPhysicalDeviceFeatures features    = getDeviceNullFeatures();
114     const char *const extensions[]                 = {"VK_KHR_swapchain", "VK_KHR_incremental_present"};
115 
116     const vk::VkDeviceCreateInfo deviceParams = {vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
117                                                  DE_NULL,
118                                                  (vk::VkDeviceCreateFlags)0,
119                                                  DE_LENGTH_OF_ARRAY(queueInfos),
120                                                  &queueInfos[0],
121                                                  0u,
122                                                  DE_NULL,
123                                                  requiresIncrementalPresent ? 2u : 1u,
124                                                  DE_ARRAY_BEGIN(extensions),
125                                                  &features};
126 
127     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
128     {
129         if (!isExtensionStructSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
130             TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
131     }
132 
133     return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
134 }
135 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,vk::wsi::Type wsiType)136 de::MovePtr<vk::wsi::Display> createDisplay(const vk::Platform &platform, const Extensions &supportedExtensions,
137                                             vk::wsi::Type wsiType)
138 {
139     try
140     {
141         return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
142     }
143     catch (const tcu::NotSupportedError &e)
144     {
145         if (isExtensionStructSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) &&
146             platform.hasDisplay(wsiType))
147         {
148             // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
149             // must support creating native display & window for that WSI type.
150             throw tcu::TestError(e.getMessage());
151         }
152         else
153             throw;
154     }
155 }
156 
createWindow(const vk::wsi::Display & display,const Maybe<UVec2> & initialSize)157 de::MovePtr<vk::wsi::Window> createWindow(const vk::wsi::Display &display, const Maybe<UVec2> &initialSize)
158 {
159     try
160     {
161         return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
162     }
163     catch (const tcu::NotSupportedError &e)
164     {
165         // See createDisplay - assuming that wsi::Display was supported platform port
166         // should also support creating a window.
167         throw tcu::TestError(e.getMessage());
168     }
169 }
170 
initSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)171 void initSemaphores(const vk::DeviceInterface &vkd, vk::VkDevice device, std::vector<vk::VkSemaphore> &semaphores)
172 {
173     for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
174         semaphores[ndx] = createSemaphore(vkd, device).disown();
175 }
176 
deinitSemaphores(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkSemaphore> & semaphores)177 void deinitSemaphores(const vk::DeviceInterface &vkd, vk::VkDevice device, std::vector<vk::VkSemaphore> &semaphores)
178 {
179     for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
180     {
181         if (semaphores[ndx] != (vk::VkSemaphore)0)
182             vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
183 
184         semaphores[ndx] = (vk::VkSemaphore)0;
185     }
186 
187     semaphores.clear();
188 }
189 
initFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)190 void initFences(const vk::DeviceInterface &vkd, vk::VkDevice device, std::vector<vk::VkFence> &fences)
191 {
192     for (size_t ndx = 0; ndx < fences.size(); ndx++)
193         fences[ndx] = createFence(vkd, device).disown();
194 }
195 
deinitFences(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFence> & fences)196 void deinitFences(const vk::DeviceInterface &vkd, vk::VkDevice device, std::vector<vk::VkFence> &fences)
197 {
198     for (size_t ndx = 0; ndx < fences.size(); ndx++)
199     {
200         if (fences[ndx] != (vk::VkFence)0)
201             vkd.destroyFence(device, fences[ndx], DE_NULL);
202 
203         fences[ndx] = (vk::VkFence)0;
204     }
205 
206     fences.clear();
207 }
208 
getRenderFrameRect(size_t frameNdx,uint32_t imageWidth,uint32_t imageHeight)209 vk::VkRect2D getRenderFrameRect(size_t frameNdx, uint32_t imageWidth, uint32_t imageHeight)
210 {
211     const uint32_t x = frameNdx == 0 ? 0 : de::min(((uint32_t)frameNdx) % imageWidth, imageWidth - 1u);
212     const uint32_t y = frameNdx == 0 ? 0 : de::min(((uint32_t)frameNdx) % imageHeight, imageHeight - 1u);
213     const uint32_t width =
214         frameNdx == 0 ? imageWidth :
215                         1 + de::min((uint32_t)(frameNdx) % de::min<uint32_t>(100, imageWidth / 3), imageWidth - x - 1);
216     const uint32_t height   = frameNdx == 0 ? imageHeight :
217                                               1 + de::min((uint32_t)(frameNdx) % de::min<uint32_t>(100, imageHeight / 3),
218                                                           imageHeight - y - 1);
219     const vk::VkRect2D rect = {{(int32_t)x, (int32_t)y}, {width, height}};
220 
221     DE_ASSERT(width > 0);
222     DE_ASSERT(height > 0);
223 
224     return rect;
225 }
226 
getUpdatedRects(size_t firstFrameNdx,size_t lastFrameNdx,uint32_t width,uint32_t height)227 vector<vk::VkRectLayerKHR> getUpdatedRects(size_t firstFrameNdx, size_t lastFrameNdx, uint32_t width, uint32_t height)
228 {
229     vector<vk::VkRectLayerKHR> rects;
230 
231     for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++)
232     {
233         const vk::VkRect2D rect            = getRenderFrameRect(frameNdx, width, height);
234         const vk::VkRectLayerKHR rectLayer = {rect.offset, rect.extent, 0};
235 
236         rects.push_back(rectLayer);
237     }
238 
239     return rects;
240 }
241 
cmdRenderFrame(const vk::DeviceInterface & vkd,vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout,vk::VkPipeline pipeline,size_t frameNdx,uint32_t imageWidth,uint32_t imageHeight)242 void cmdRenderFrame(const vk::DeviceInterface &vkd, vk::VkCommandBuffer commandBuffer,
243                     vk::VkPipelineLayout pipelineLayout, vk::VkPipeline pipeline, size_t frameNdx, uint32_t imageWidth,
244                     uint32_t imageHeight)
245 {
246     const uint32_t mask = (uint32_t)frameNdx;
247 
248     if (frameNdx == 0)
249     {
250         const vk::VkRect2D scissor = vk::makeRect2D(imageWidth, imageHeight);
251         vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
252         const vk::VkClearAttachment attachment = {vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u,
253                                                   vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f)};
254         const vk::VkClearRect rect             = {scissor, 0u, 1u};
255 
256         vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect);
257     }
258 
259     {
260         const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight);
261         vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor);
262 
263         vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask);
264         vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
265         vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u);
266     }
267 }
268 
createCommandBuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,vk::VkPipelineLayout pipelineLayout,vk::VkRenderPass renderPass,vk::VkFramebuffer framebuffer,vk::VkPipeline pipeline,vk::VkImage image,bool isFirst,size_t imageNextFrame,size_t currentFrame,uint32_t imageWidth,uint32_t imageHeight)269 vk::Move<vk::VkCommandBuffer> createCommandBuffer(const vk::DeviceInterface &vkd, vk::VkDevice device,
270                                                   vk::VkCommandPool commandPool, vk::VkPipelineLayout pipelineLayout,
271                                                   vk::VkRenderPass renderPass, vk::VkFramebuffer framebuffer,
272                                                   vk::VkPipeline pipeline, vk::VkImage image, bool isFirst,
273                                                   size_t imageNextFrame, size_t currentFrame, uint32_t imageWidth,
274                                                   uint32_t imageHeight)
275 {
276     const vk::VkCommandBufferAllocateInfo allocateInfo = {vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, DE_NULL,
277 
278                                                           commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
279 
280     vk::Move<vk::VkCommandBuffer> commandBuffer(vk::allocateCommandBuffer(vkd, device, &allocateInfo));
281     beginCommandBuffer(vkd, *commandBuffer, 0u);
282 
283     {
284         const vk::VkImageSubresourceRange subRange = {vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
285         const vk::VkImageMemoryBarrier barrier     = {
286             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
287             DE_NULL,
288             0u,
289             0u,
290             (isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR),
291             vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
292             VK_QUEUE_FAMILY_IGNORED,
293             VK_QUEUE_FAMILY_IGNORED,
294             image,
295             subRange};
296         const vk::VkPipelineStageFlags srcStages =
297             (vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
298         const vk::VkPipelineStageFlags dstStages = vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
299         vkd.cmdPipelineBarrier(*commandBuffer, srcStages, dstStages, 0u, 0u, nullptr, 0u, nullptr, 1u, &barrier);
300     }
301 
302     beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, vk::makeRect2D(imageWidth, imageHeight),
303                     tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f));
304 
305     for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++)
306         cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight);
307 
308     endRenderPass(vkd, *commandBuffer);
309 
310     endCommandBuffer(vkd, *commandBuffer);
311     return commandBuffer;
312 }
313 
deinitCommandBuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkCommandPool commandPool,std::vector<vk::VkCommandBuffer> & commandBuffers)314 void deinitCommandBuffers(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkCommandPool commandPool,
315                           std::vector<vk::VkCommandBuffer> &commandBuffers)
316 {
317     for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
318     {
319         if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
320             vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
321 
322         commandBuffers[ndx] = (vk::VkCommandBuffer)0;
323     }
324 
325     commandBuffers.clear();
326 }
327 
createCommandPool(const vk::DeviceInterface & vkd,vk::VkDevice device,uint32_t queueFamilyIndex)328 vk::Move<vk::VkCommandPool> createCommandPool(const vk::DeviceInterface &vkd, vk::VkDevice device,
329                                               uint32_t queueFamilyIndex)
330 {
331     const vk::VkCommandPoolCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL, 0u,
332                                                     queueFamilyIndex};
333 
334     return vk::createCommandPool(vkd, device, &createInfo);
335 }
336 
createFramebuffer(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkImageView imageView,uint32_t width,uint32_t height)337 vk::Move<vk::VkFramebuffer> createFramebuffer(const vk::DeviceInterface &vkd, vk::VkDevice device,
338                                               vk::VkRenderPass renderPass, vk::VkImageView imageView, uint32_t width,
339                                               uint32_t height)
340 {
341     const vk::VkFramebufferCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
342                                                     DE_NULL,
343 
344                                                     0u,
345                                                     renderPass,
346                                                     1u,
347                                                     &imageView,
348                                                     width,
349                                                     height,
350                                                     1u};
351 
352     return vk::createFramebuffer(vkd, device, &createInfo);
353 }
354 
initFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,std::vector<vk::VkImageView> imageViews,uint32_t width,uint32_t height,std::vector<vk::VkFramebuffer> & framebuffers)355 void initFramebuffers(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkRenderPass renderPass,
356                       std::vector<vk::VkImageView> imageViews, uint32_t width, uint32_t height,
357                       std::vector<vk::VkFramebuffer> &framebuffers)
358 {
359     DE_ASSERT(framebuffers.size() == imageViews.size());
360 
361     for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
362         framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
363 }
364 
deinitFramebuffers(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkFramebuffer> & framebuffers)365 void deinitFramebuffers(const vk::DeviceInterface &vkd, vk::VkDevice device,
366                         std::vector<vk::VkFramebuffer> &framebuffers)
367 {
368     for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
369     {
370         if (framebuffers[ndx] != (vk::VkFramebuffer)0)
371             vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
372 
373         framebuffers[ndx] = (vk::VkFramebuffer)0;
374     }
375 
376     framebuffers.clear();
377 }
378 
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format)379 vk::Move<vk::VkImageView> createImageView(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkImage image,
380                                           vk::VkFormat format)
381 {
382     const vk::VkImageViewCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
383                                                   DE_NULL,
384 
385                                                   0u,
386                                                   image,
387                                                   vk::VK_IMAGE_VIEW_TYPE_2D,
388                                                   format,
389                                                   vk::makeComponentMappingRGBA(),
390                                                   {vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
391 
392     return vk::createImageView(vkd, device, &createInfo, DE_NULL);
393 }
394 
initImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<vk::VkImage> & images,vk::VkFormat format,std::vector<vk::VkImageView> & imageViews)395 void initImageViews(const vk::DeviceInterface &vkd, vk::VkDevice device, const std::vector<vk::VkImage> &images,
396                     vk::VkFormat format, std::vector<vk::VkImageView> &imageViews)
397 {
398     DE_ASSERT(images.size() == imageViews.size());
399 
400     for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
401         imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
402 }
403 
deinitImageViews(const vk::DeviceInterface & vkd,vk::VkDevice device,std::vector<vk::VkImageView> & imageViews)404 void deinitImageViews(const vk::DeviceInterface &vkd, vk::VkDevice device, std::vector<vk::VkImageView> &imageViews)
405 {
406     for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
407     {
408         if (imageViews[ndx] != (vk::VkImageView)0)
409             vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
410 
411         imageViews[ndx] = (vk::VkImageView)0;
412     }
413 
414     imageViews.clear();
415 }
416 
createRenderPass(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format)417 vk::Move<vk::VkRenderPass> createRenderPass(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkFormat format)
418 {
419     return vk::makeRenderPass(vkd, device, format, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
420                               vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
421 }
422 
createPipeline(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkRenderPass renderPass,vk::VkPipelineLayout layout,vk::VkShaderModule vertexShaderModule,vk::VkShaderModule fragmentShaderModule,uint32_t width,uint32_t height)423 vk::Move<vk::VkPipeline> createPipeline(const vk::DeviceInterface &vkd, vk::VkDevice device,
424                                         vk::VkRenderPass renderPass, vk::VkPipelineLayout layout,
425                                         vk::VkShaderModule vertexShaderModule, vk::VkShaderModule fragmentShaderModule,
426                                         uint32_t width, uint32_t height)
427 {
428     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
429         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, DE_NULL, 0u, 0u, DE_NULL, 0u, DE_NULL};
430     const std::vector<vk::VkViewport> viewports(1, vk::makeViewport(tcu::UVec2(width, height)));
431     const std::vector<vk::VkRect2D> scissors(1, vk::makeRect2D(tcu::UVec2(width, height)));
432 
433     return vk::makeGraphicsPipeline(
434         vkd,                  // const DeviceInterface&                        vk
435         device,               // const VkDevice                                device
436         layout,               // const VkPipelineLayout                        pipelineLayout
437         vertexShaderModule,   // const VkShaderModule                          vertexShaderModule
438         DE_NULL,              // const VkShaderModule                          tessellationControlShaderModule
439         DE_NULL,              // const VkShaderModule                          tessellationEvalShaderModule
440         DE_NULL,              // const VkShaderModule                          geometryShaderModule
441         fragmentShaderModule, // const VkShaderModule                          fragmentShaderModule
442         renderPass,           // const VkRenderPass                            renderPass
443         viewports,            // const std::vector<VkViewport>&                viewports
444         scissors,             // const std::vector<VkRect2D>&                  scissors
445         vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
446         0u,                                      // const uint32_t                                subpass
447         0u,                                      // const uint32_t                                patchControlPoints
448         &vertexInputState); // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
449 }
450 
createPipelineLayout(const vk::DeviceInterface & vkd,vk::VkDevice device)451 vk::Move<vk::VkPipelineLayout> createPipelineLayout(const vk::DeviceInterface &vkd, vk::VkDevice device)
452 {
453     const vk::VkPushConstantRange pushConstants[]   = {{vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u}};
454     const vk::VkPipelineLayoutCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
455                                                        DE_NULL,
456                                                        0u,
457 
458                                                        0u,
459                                                        DE_NULL,
460 
461                                                        DE_LENGTH_OF_ARRAY(pushConstants),
462                                                        pushConstants};
463 
464     return vk::createPipelineLayout(vkd, device, &createInfo);
465 }
466 
467 struct TestConfig
468 {
469     vk::wsi::Type wsiType;
470     Scaling scaling;
471     bool useIncrementalPresent;
472     vk::VkPresentModeKHR presentMode;
473     vk::VkSurfaceTransformFlagsKHR transform;
474     vk::VkCompositeAlphaFlagsKHR alpha;
475 };
476 
477 class IncrementalPresentTestInstance : public TestInstance
478 {
479 public:
480     IncrementalPresentTestInstance(Context &context, const TestConfig &testConfig);
481     ~IncrementalPresentTestInstance(void);
482 
483     tcu::TestStatus iterate(void);
484 
485 private:
486     const TestConfig m_testConfig;
487     const bool m_useIncrementalPresent;
488     const vk::PlatformInterface &m_vkp;
489     const Extensions m_instanceExtensions;
490     const CustomInstance m_instance;
491     const vk::InstanceDriver &m_vki;
492     const vk::VkPhysicalDevice m_physicalDevice;
493     const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
494     const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
495     const vk::Unique<vk::VkSurfaceKHR> m_surface;
496 
497     const uint32_t m_queueFamilyIndex;
498     const Extensions m_deviceExtensions;
499     const vk::Unique<vk::VkDevice> m_device;
500     const vk::DeviceDriver m_vkd;
501     const vk::VkQueue m_queue;
502 
503     const vk::Unique<vk::VkCommandPool> m_commandPool;
504     const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
505     const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
506     const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
507 
508     const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
509     const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
510     const vector<vk::VkPresentModeKHR> m_presentModes;
511 
512     tcu::ResultCollector m_resultCollector;
513 
514     vk::Move<vk::VkSwapchainKHR> m_swapchain;
515     std::vector<vk::VkImage> m_swapchainImages;
516     std::vector<size_t> m_imageNextFrames;
517     std::vector<bool> m_isFirst;
518 
519     vk::Move<vk::VkRenderPass> m_renderPass;
520     vk::Move<vk::VkPipeline> m_pipeline;
521 
522     std::vector<vk::VkImageView> m_swapchainImageViews;
523     std::vector<vk::VkFramebuffer> m_framebuffers;
524     std::vector<vk::VkCommandBuffer> m_commandBuffers;
525     std::vector<vk::VkSemaphore> m_acquireSemaphores;
526     std::vector<vk::VkSemaphore> m_renderSemaphores;
527     std::vector<vk::VkFence> m_fences;
528 
529     vk::VkSemaphore m_freeAcquireSemaphore;
530     vk::VkSemaphore m_freeRenderSemaphore;
531 
532     std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs;
533     size_t m_swapchainConfigNdx;
534 
535     const size_t m_frameCount;
536     size_t m_frameNdx;
537 
538     const size_t m_maxOutOfDateCount;
539     size_t m_outOfDateCount;
540 
541     void initSwapchainResources(void);
542     void deinitSwapchainResources(void);
543     void render(void);
544 };
545 
generateSwapchainConfigs(vk::VkSurfaceKHR surface,const uint32_t * queueFamilyIndex,Scaling scaling,const vk::VkSurfaceCapabilitiesKHR & properties,const vector<vk::VkSurfaceFormatKHR> & formats,const vector<vk::VkPresentModeKHR> & presentModes,vk::VkPresentModeKHR presentMode,const vk::VkSurfaceTransformFlagsKHR transform,const vk::VkCompositeAlphaFlagsKHR alpha)546 std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs(
547     vk::VkSurfaceKHR surface, const uint32_t *queueFamilyIndex, Scaling scaling,
548     const vk::VkSurfaceCapabilitiesKHR &properties, const vector<vk::VkSurfaceFormatKHR> &formats,
549     const vector<vk::VkPresentModeKHR> &presentModes, vk::VkPresentModeKHR presentMode,
550     const vk::VkSurfaceTransformFlagsKHR transform, const vk::VkCompositeAlphaFlagsKHR alpha)
551 {
552     const uint32_t imageLayers             = 1u;
553     const vk::VkImageUsageFlags imageUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
554     const vk::VkBool32 clipped             = VK_FALSE;
555     vector<vk::VkSwapchainCreateInfoKHR> createInfos;
556 
557     const uint32_t currentWidth =
558         properties.currentExtent.width != 0xFFFFFFFFu ?
559             properties.currentExtent.width :
560             de::min(1024u, properties.minImageExtent.width +
561                                ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
562     const uint32_t currentHeight =
563         properties.currentExtent.height != 0xFFFFFFFFu ?
564             properties.currentExtent.height :
565             de::min(1024u, properties.minImageExtent.height +
566                                ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
567 
568     const uint32_t imageWidth =
569         scaling == SCALING_NONE ?
570             currentWidth :
571             (scaling == SCALING_UP ?
572                  de::max(31u, properties.minImageExtent.width) :
573                  de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentWidth + 1), properties.maxImageExtent.width));
574     const uint32_t imageHeight =
575         scaling == SCALING_NONE ?
576             currentHeight :
577             (scaling == SCALING_UP ?
578                  de::max(31u, properties.minImageExtent.height) :
579                  de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentHeight + 1), properties.maxImageExtent.height));
580     const vk::VkExtent2D imageSize  = {imageWidth, imageHeight};
581     const vk::VkExtent2D unusedSize = {de::max(31u, properties.minImageExtent.width),
582                                        de::max(31u, properties.minImageExtent.height)};
583 
584     {
585         size_t presentModeNdx;
586 
587         for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
588         {
589             if (presentModes[presentModeNdx] == presentMode)
590                 break;
591         }
592 
593         if (presentModeNdx == presentModes.size())
594             TCU_THROW(NotSupportedError, "Present mode not supported");
595 
596         if ((properties.supportedTransforms & transform) == 0)
597             TCU_THROW(NotSupportedError, "Transform not supported");
598 
599         if ((properties.supportedCompositeAlpha & alpha) == 0)
600             TCU_THROW(NotSupportedError, "Composite alpha not supported");
601     }
602 
603     for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++)
604     {
605 
606         const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
607         const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
608         const vk::VkFormat imageFormat                       = formats[formatNdx].format;
609         const vk::VkColorSpaceKHR imageColorSpace            = formats[formatNdx].colorSpace;
610         const vk::VkSwapchainCreateInfoKHR createInfo        = {vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
611                                                                 DE_NULL,
612                                                                 0u,
613                                                                 surface,
614                                                                 properties.minImageCount,
615                                                                 imageFormat,
616                                                                 imageColorSpace,
617                                                                 imageSize,
618                                                                 imageLayers,
619                                                                 imageUsage,
620                                                                 vk::VK_SHARING_MODE_EXCLUSIVE,
621                                                                 1u,
622                                                                 queueFamilyIndex,
623                                                                 preTransform,
624                                                                 compositeAlpha,
625                                                                 presentMode,
626                                                                 clipped,
627                                                                 (vk::VkSwapchainKHR)0};
628 
629         createInfos.push_back(createInfo);
630 
631         // add an extra unused swapchain
632         const vk::VkSwapchainCreateInfoKHR unusedInfo = {vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
633                                                          DE_NULL,
634                                                          0u,
635                                                          surface,
636                                                          properties.minImageCount,
637                                                          imageFormat,
638                                                          imageColorSpace,
639                                                          unusedSize,
640                                                          imageLayers,
641                                                          imageUsage,
642                                                          vk::VK_SHARING_MODE_EXCLUSIVE,
643                                                          1u,
644                                                          queueFamilyIndex,
645                                                          preTransform,
646                                                          compositeAlpha,
647                                                          presentMode,
648                                                          clipped,
649                                                          (vk::VkSwapchainKHR)0};
650 
651         createInfos.push_back(unusedInfo);
652     }
653 
654     return createInfos;
655 }
656 
IncrementalPresentTestInstance(Context & context,const TestConfig & testConfig)657 IncrementalPresentTestInstance::IncrementalPresentTestInstance(Context &context, const TestConfig &testConfig)
658     : TestInstance(context)
659     , m_testConfig(testConfig)
660     , m_useIncrementalPresent(testConfig.useIncrementalPresent)
661     , m_vkp(context.getPlatformInterface())
662     , m_instanceExtensions(vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
663     , m_instance(createInstanceWithWsi(context, m_instanceExtensions, testConfig.wsiType))
664     , m_vki(m_instance.getDriver())
665     , m_physicalDevice(vk::chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
666     , m_nativeDisplay(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions,
667                                     testConfig.wsiType))
668     , m_nativeWindow(createWindow(*m_nativeDisplay, tcu::Nothing))
669     , m_surface(vk::wsi::createSurface(m_vki, m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow,
670                                        context.getTestContext().getCommandLine()))
671 
672     , m_queueFamilyIndex(vk::wsi::chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
673     , m_deviceExtensions(vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
674     , m_device(createDeviceWithWsi(m_vkp, m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex,
675                                    testConfig.useIncrementalPresent,
676                                    context.getTestContext().getCommandLine().isValidationEnabled()))
677     , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
678     , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
679 
680     , m_commandPool(createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
681     , m_vertexShaderModule(vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
682     , m_fragmentShaderModule(
683           vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
684     , m_pipelineLayout(createPipelineLayout(m_vkd, *m_device))
685 
686     , m_surfaceProperties(vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
687     , m_surfaceFormats(vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
688     , m_presentModes(vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
689 
690     , m_freeAcquireSemaphore((vk::VkSemaphore)0)
691     , m_freeRenderSemaphore((vk::VkSemaphore)0)
692 
693     , m_swapchainConfigs(generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, testConfig.scaling,
694                                                   m_surfaceProperties, m_surfaceFormats, m_presentModes,
695                                                   testConfig.presentMode, testConfig.transform, testConfig.alpha))
696     , m_swapchainConfigNdx(0u)
697 
698     , m_frameCount(60u * 5u)
699     , m_frameNdx(0u)
700 
701     , m_maxOutOfDateCount(20u)
702     , m_outOfDateCount(0u)
703 {
704     {
705         const tcu::ScopedLogSection surfaceInfo(m_context.getTestContext().getLog(), "SurfaceCapabilities",
706                                                 "SurfaceCapabilities");
707         m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
708     }
709 }
710 
~IncrementalPresentTestInstance(void)711 IncrementalPresentTestInstance::~IncrementalPresentTestInstance(void)
712 {
713     deinitSwapchainResources();
714 }
715 
initSwapchainResources(void)716 void IncrementalPresentTestInstance::initSwapchainResources(void)
717 {
718     const size_t fenceCount        = 6;
719     const uint32_t imageWidth      = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
720     const uint32_t imageHeight     = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
721     const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat;
722 
723     m_swapchain       = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]);
724     m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
725 
726     m_imageNextFrames.resize(m_swapchainImages.size(), 0);
727     m_isFirst.resize(m_swapchainImages.size(), true);
728 
729     m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
730     m_pipeline   = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule,
731                                   *m_fragmentShaderModule, imageWidth, imageHeight);
732 
733     m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
734     m_framebuffers        = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
735     m_acquireSemaphores   = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
736     m_renderSemaphores    = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
737 
738     m_fences         = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
739     m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
740 
741     m_freeAcquireSemaphore = (vk::VkSemaphore)0;
742     m_freeRenderSemaphore  = (vk::VkSemaphore)0;
743 
744     m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
745     m_freeRenderSemaphore  = createSemaphore(m_vkd, *m_device).disown();
746 
747     initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
748     initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
749     initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
750     initSemaphores(m_vkd, *m_device, m_renderSemaphores);
751 
752     initFences(m_vkd, *m_device, m_fences);
753 }
754 
deinitSwapchainResources(void)755 void IncrementalPresentTestInstance::deinitSwapchainResources(void)
756 {
757     VK_CHECK(m_vkd.queueWaitIdle(m_queue));
758 
759     if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
760     {
761         m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
762         m_freeAcquireSemaphore = (vk::VkSemaphore)0;
763     }
764 
765     if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
766     {
767         m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
768         m_freeRenderSemaphore = (vk::VkSemaphore)0;
769     }
770 
771     deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
772     deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
773     deinitFences(m_vkd, *m_device, m_fences);
774     deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
775     deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
776     deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
777 
778     m_swapchainImages.clear();
779     m_imageNextFrames.clear();
780     m_isFirst.clear();
781 
782     m_swapchain  = vk::Move<vk::VkSwapchainKHR>();
783     m_renderPass = vk::Move<vk::VkRenderPass>();
784     m_pipeline   = vk::Move<vk::VkPipeline>();
785 }
786 
render(void)787 void IncrementalPresentTestInstance::render(void)
788 {
789     const uint64_t foreverNs = 0xFFFFFFFFFFFFFFFFul;
790     const vk::VkFence fence  = m_fences[m_frameNdx % m_fences.size()];
791     const uint32_t width     = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width;
792     const uint32_t height    = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height;
793     size_t imageNextFrame;
794 
795     // Throttle execution
796     if (m_frameNdx >= m_fences.size())
797     {
798         VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
799         VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
800 
801         m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u,
802                                  &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
803         m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
804     }
805 
806     vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
807     vk::VkSemaphore currentRenderSemaphore  = m_freeRenderSemaphore;
808     uint32_t imageIndex;
809 
810     // Acquire next image
811     VK_CHECK_WSI(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0,
812                                            &imageIndex));
813 
814     // Create command buffer
815     {
816         imageNextFrame = m_imageNextFrames[imageIndex];
817         m_commandBuffers[m_frameNdx % m_commandBuffers.size()] =
818             createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass,
819                                 m_framebuffers[imageIndex], *m_pipeline, m_swapchainImages[imageIndex],
820                                 m_isFirst[imageIndex], imageNextFrame, m_frameNdx, width, height)
821                 .disown();
822         m_imageNextFrames[imageIndex] = m_frameNdx + 1;
823         m_isFirst[imageIndex]         = false;
824     }
825 
826     // Submit command buffer
827     {
828         const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
829         const vk::VkSubmitInfo submitInfo           = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
830                                                        DE_NULL,
831                                                        1u,
832                                                        &currentAcquireSemaphore,
833                                                        &dstStageMask,
834                                                        1u,
835                                                        &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
836                                                        1u,
837                                                        &currentRenderSemaphore};
838 
839         VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
840     }
841 
842     // Present frame
843     if (m_useIncrementalPresent)
844     {
845         vk::VkResult result;
846         const vector<vk::VkRectLayerKHR> rects   = getUpdatedRects(imageNextFrame, m_frameNdx, width, height);
847         const vk::VkPresentRegionKHR region      = {(uint32_t)rects.size(), rects.empty() ? DE_NULL : &rects[0]};
848         const vk::VkPresentRegionsKHR regionInfo = {vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR, DE_NULL, 1u, &region};
849         const vk::VkPresentInfoKHR presentInfo   = {vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
850                                                     &regionInfo,
851                                                     1u,
852                                                     &currentRenderSemaphore,
853                                                     1u,
854                                                     &*m_swapchain,
855                                                     &imageIndex,
856                                                     &result};
857 
858         VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
859         VK_CHECK_WSI(result);
860     }
861     else
862     {
863         vk::VkResult result;
864         const vk::VkPresentInfoKHR presentInfo = {vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
865                                                   DE_NULL,
866                                                   1u,
867                                                   &currentRenderSemaphore,
868                                                   1u,
869                                                   &*m_swapchain,
870                                                   &imageIndex,
871                                                   &result};
872 
873         VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
874         VK_CHECK_WSI(result);
875     }
876 
877     {
878         m_freeAcquireSemaphore          = m_acquireSemaphores[imageIndex];
879         m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
880 
881         m_freeRenderSemaphore          = m_renderSemaphores[imageIndex];
882         m_renderSemaphores[imageIndex] = currentRenderSemaphore;
883     }
884 }
885 
iterate(void)886 tcu::TestStatus IncrementalPresentTestInstance::iterate(void)
887 {
888     // Initialize swapchain specific resources
889     // Render test
890     try
891     {
892         if (m_frameNdx == 0)
893         {
894             if (m_outOfDateCount == 0)
895                 m_context.getTestContext().getLog()
896                     << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx]
897                     << tcu::TestLog::EndMessage;
898 
899             initSwapchainResources();
900         }
901 
902         render();
903     }
904     catch (const vk::Error &error)
905     {
906         if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR || error.getError() == vk::VK_SUBOPTIMAL_KHR)
907         {
908             m_swapchainConfigs = generateSwapchainConfigs(
909                 *m_surface, &m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats,
910                 m_presentModes, m_testConfig.presentMode, m_testConfig.transform, m_testConfig.alpha);
911 
912             if (m_outOfDateCount < m_maxOutOfDateCount)
913             {
914                 m_context.getTestContext().getLog()
915                     << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources."
916                     << TestLog::EndMessage;
917                 deinitSwapchainResources();
918                 m_frameNdx = 0;
919                 m_outOfDateCount++;
920 
921                 return tcu::TestStatus::incomplete();
922             }
923             else
924             {
925                 m_context.getTestContext().getLog()
926                     << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
927                 m_resultCollector.fail(
928                     "Received too many VK_ERROR_OUT_OF_DATE_KHR or VK_SUBOPTIMAL_KHR errors. Received " +
929                     de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
930             }
931         }
932         else
933         {
934             m_resultCollector.fail(error.what());
935         }
936 
937         deinitSwapchainResources();
938 
939         m_swapchainConfigNdx++;
940         m_frameNdx       = 0;
941         m_outOfDateCount = 0;
942 
943         if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
944             return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
945         else
946             return tcu::TestStatus::incomplete();
947     }
948 
949     m_frameNdx++;
950 
951     if (m_frameNdx >= m_frameCount)
952     {
953         m_frameNdx       = 0;
954         m_outOfDateCount = 0;
955         m_swapchainConfigNdx++;
956 
957         deinitSwapchainResources();
958 
959         if (m_swapchainConfigNdx >= m_swapchainConfigs.size())
960             return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
961         else
962             return tcu::TestStatus::incomplete();
963     }
964     else
965         return tcu::TestStatus::incomplete();
966 }
967 
968 struct Programs
969 {
initvkt::wsi::__anon4cd76d050111::Programs970     static void init(vk::SourceCollections &dst, TestConfig)
971     {
972         dst.glslSources.add("quad-vert") << glu::VertexSource(
973             "#version 450\n"
974             "out gl_PerVertex {\n"
975             "\tvec4 gl_Position;\n"
976             "};\n"
977             "highp float;\n"
978             "void main (void) {\n"
979             "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
980             "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
981             "}\n");
982         dst.glslSources.add("quad-frag") << glu::FragmentSource(
983             "#version 310 es\n"
984             "layout(location = 0) out highp vec4 o_color;\n"
985             "layout(push_constant) uniform PushConstant {\n"
986             "\thighp uint mask;\n"
987             "} pushConstants;\n"
988             "void main (void)\n"
989             "{\n"
990             "\thighp uint mask = pushConstants.mask;\n"
991             "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n"
992             "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n"
993             "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
994             "\t             +  64u * bitfieldExtract(y, 1, 1)\n"
995             "\t             +  32u * bitfieldExtract(x, 3, 1);\n"
996             "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
997             "\t             +  64u * bitfieldExtract(x, 2, 1)\n"
998             "\t             +  32u * bitfieldExtract(y, 3, 1);\n"
999             "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1000             "\t             +  64u * bitfieldExtract(y, 2, 1)\n"
1001             "\t             +  32u * bitfieldExtract(x, 4, 1);\n"
1002             "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1003             "}\n");
1004     }
1005 };
1006 
1007 } // namespace
1008 
createIncrementalPresentTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1009 void createIncrementalPresentTests(tcu::TestCaseGroup *testGroup, vk::wsi::Type wsiType)
1010 {
1011     const struct
1012     {
1013         Scaling scaling;
1014         const char *name;
1015     } scaling[] = {{SCALING_NONE, "scale_none"}, {SCALING_UP, "scale_up"}, {SCALING_DOWN, "scale_down"}};
1016     const struct
1017     {
1018         vk::VkPresentModeKHR mode;
1019         const char *name;
1020     } presentModes[] = {{vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate"},
1021                         {vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox"},
1022                         {vk::VK_PRESENT_MODE_FIFO_KHR, "fifo"},
1023                         {vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed"}};
1024     const struct
1025     {
1026         vk::VkSurfaceTransformFlagsKHR transform;
1027         const char *name;
1028     } transforms[] = {{vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, "identity"},
1029                       {vk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, "rotate_90"},
1030                       {vk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, "rotate_180"},
1031                       {vk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, "rotate_270"},
1032                       {vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, "horizontal_mirror"},
1033                       {vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, "horizontal_mirror_rotate_90"},
1034                       {vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, "horizontal_mirror_rotate_180"},
1035                       {vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, "horizontal_mirror_rotate_270"},
1036                       {vk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, "inherit"}};
1037     const struct
1038     {
1039         vk::VkCompositeAlphaFlagsKHR alpha;
1040         const char *name;
1041     } alphas[] = {{vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, "opaque"},
1042                   {vk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, "pre_multiplied"},
1043                   {vk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, "post_multiplied"},
1044                   {vk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, "inherit"}};
1045 
1046     for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++)
1047     {
1048         if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND)
1049             continue;
1050 
1051         if (scaling[scalingNdx].scaling != SCALING_NONE &&
1052             vk::wsi::getPlatformProperties(wsiType).swapchainExtent !=
1053                 vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
1054             continue;
1055 
1056         {
1057 
1058             de::MovePtr<tcu::TestCaseGroup> scaleGroup(
1059                 new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name));
1060 
1061             for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1062             {
1063                 de::MovePtr<tcu::TestCaseGroup> presentModeGroup(
1064                     new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name));
1065 
1066                 for (size_t transformNdx = 0; transformNdx < DE_LENGTH_OF_ARRAY(transforms); transformNdx++)
1067                 {
1068                     de::MovePtr<tcu::TestCaseGroup> transformGroup(
1069                         new tcu::TestCaseGroup(testGroup->getTestContext(), transforms[transformNdx].name));
1070 
1071                     for (size_t alphaNdx = 0; alphaNdx < DE_LENGTH_OF_ARRAY(alphas); alphaNdx++)
1072                     {
1073                         de::MovePtr<tcu::TestCaseGroup> alphaGroup(
1074                             new tcu::TestCaseGroup(testGroup->getTestContext(), alphas[alphaNdx].name));
1075 
1076                         for (size_t ref = 0; ref < 2; ref++)
1077                         {
1078                             const bool isReference = (ref == 0);
1079                             const char *const name = isReference ? "reference" : "incremental_present";
1080                             TestConfig config;
1081 
1082                             config.wsiType               = wsiType;
1083                             config.scaling               = scaling[scalingNdx].scaling;
1084                             config.useIncrementalPresent = !isReference;
1085                             config.presentMode           = presentModes[presentModeNdx].mode;
1086                             config.transform             = transforms[transformNdx].transform;
1087                             config.alpha                 = alphas[alphaNdx].alpha;
1088 
1089                             alphaGroup->addChild(
1090                                 new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(
1091                                     testGroup->getTestContext(), name, Programs(), config));
1092                         }
1093 
1094                         transformGroup->addChild(alphaGroup.release());
1095                     }
1096 
1097                     presentModeGroup->addChild(transformGroup.release());
1098                 }
1099 
1100                 scaleGroup->addChild(presentModeGroup.release());
1101             }
1102 
1103             testGroup->addChild(scaleGroup.release());
1104         }
1105     }
1106 }
1107 
1108 } // namespace wsi
1109 } // namespace vkt
1110