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