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