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