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