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