Merge pull request #276 from Ella-0/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / wsi / vktWsiPresentIdWaitTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for the present id and present wait extensions.
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktWsiPresentIdWaitTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 #include "vktNativeObjectsUtil.hpp"
29
30 #include "vkQueryUtil.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkWsiUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkRefUtil.hpp"
36
37 #include "tcuTestContext.hpp"
38 #include "tcuPlatform.hpp"
39 #include "tcuCommandLine.hpp"
40 #include "tcuTestLog.hpp"
41
42 #include "deDefs.hpp"
43
44 #include <vector>
45 #include <string>
46 #include <set>
47 #include <sstream>
48 #include <chrono>
49 #include <algorithm>
50 #include <utility>
51 #include <limits>
52
53 using std::vector;
54 using std::string;
55 using std::set;
56
57 namespace vkt
58 {
59 namespace wsi
60 {
61
62 namespace
63 {
64
65 // Handy time constants in nanoseconds.
66 constexpr deUint64 k10sec       = 10000000000ull;
67 constexpr deUint64 k1sec        =  1000000000ull;
68
69 // 100 milliseconds, way above 1/50 seconds for systems with 50Hz ticks.
70 // This should also take into account possible measure deviations due to the machine being loaded.
71 constexpr deUint64 kMargin      =   100000000ull;
72
73 using TimeoutRange = std::pair<deInt64, deInt64>;
74
75 // Calculate acceptable timeout range based on indicated timeout and taking into account kMargin.
76 TimeoutRange calcTimeoutRange (deUint64 timeout)
77 {
78         constexpr auto kUnsignedMax     = std::numeric_limits<deUint64>::max();
79         constexpr auto kSignedMax       = static_cast<deUint64>(std::numeric_limits<deInt64>::max());
80
81         // Watch for over- and under-flows.
82         deUint64 timeoutMin = ((timeout < kMargin) ? 0ull : (timeout - kMargin));
83         deUint64 timeoutMax = ((kUnsignedMax - timeout < kMargin) ? kUnsignedMax : timeout + kMargin);
84
85         // Make sure casting is safe.
86         timeoutMin = de::min(kSignedMax, timeoutMin);
87         timeoutMax = de::min(kSignedMax, timeoutMax);
88
89         return TimeoutRange(static_cast<deInt64>(timeoutMin), static_cast<deInt64>(timeoutMax));
90 }
91
92 class PresentIdWaitInstance : public TestInstance
93 {
94 public:
95                                                                 PresentIdWaitInstance   (Context& context, vk::wsi::Type wsiType) : TestInstance(context), m_wsiType(wsiType) {}
96         virtual                                         ~PresentIdWaitInstance  (void) {}
97
98         virtual tcu::TestStatus         iterate                                 (void);
99
100         virtual tcu::TestStatus         run                                             (const vk::DeviceInterface&                             vkd,
101                                                                                                                  vk::VkDevice                                                   device,
102                                                                                                                  vk::VkQueue                                                    queue,
103                                                                                                                  vk::VkCommandPool                                              commandPool,
104                                                                                                                  vk::VkSwapchainKHR                                             swapchain,
105                                                                                                                  size_t                                                                 swapchainSize,
106                                                                                                                  const vk::wsi::WsiTriangleRenderer&    renderer) = 0;
107
108         // Subclasses will need to implement a static method like this one indicating which extensions they need.
109         static vector<const char*>      requiredDeviceExts              (void) { return vector<const char*>(); }
110
111         // Subclasses will also need to implement this nonstatic method returning the same information as above.
112         virtual vector<const char*>     getRequiredDeviceExts   (void) = 0;
113
114 protected:
115         vk::wsi::Type                           m_wsiType;
116 };
117
118 vector<const char*> getRequiredInstanceExtensions (vk::wsi::Type wsiType)
119 {
120         vector<const char*> extensions;
121         extensions.push_back("VK_KHR_surface");
122         extensions.push_back(getExtensionName(wsiType));
123         return extensions;
124 }
125
126 CustomInstance createInstanceWithWsi (Context&                                                  context,
127                                                                           vk::wsi::Type                                         wsiType,
128                                                                           const vk::VkAllocationCallbacks*      pAllocator      = nullptr)
129 {
130         const auto version                              = context.getUsedApiVersion();
131         const auto requiredExtensions   = getRequiredInstanceExtensions(wsiType);
132
133         vector<string> requestedExtensions;
134         for (const auto& extensionName : requiredExtensions)
135         {
136                 if (!vk::isCoreInstanceExtension(version, extensionName))
137                         requestedExtensions.push_back(extensionName);
138         }
139
140         return vkt::createCustomInstanceWithExtensions(context, requestedExtensions, pAllocator);
141 }
142
143 struct InstanceHelper
144 {
145         const vector<vk::VkExtensionProperties> supportedExtensions;
146         CustomInstance                                                  instance;
147         const vk::InstanceDriver&                               vki;
148
149         InstanceHelper (Context& context, vk::wsi::Type wsiType, const vk::VkAllocationCallbacks* pAllocator = nullptr)
150                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(), nullptr))
151                 , instance                              (createInstanceWithWsi(context, wsiType, pAllocator))
152                 , vki                                   (instance.getDriver())
153         {}
154 };
155
156 vector<const char*> getMandatoryDeviceExtensions ()
157 {
158         vector<const char*> mandatoryExtensions;
159         mandatoryExtensions.push_back("VK_KHR_swapchain");
160         return mandatoryExtensions;
161 }
162
163 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface&                                vkp,
164                                                                                         vk::VkInstance                                                          instance,
165                                                                                         const vk::InstanceInterface&                            vki,
166                                                                                         vk::VkPhysicalDevice                                            physicalDevice,
167                                                                                         const vector<const char*>&                                      extraExtensions,
168                                                                                         const deUint32                                                          queueFamilyIndex,
169                                                                                         bool                                                                            validationEnabled,
170                                                                                         const vk::VkAllocationCallbacks*                        pAllocator = nullptr)
171 {
172         const float                                                     queuePriorities[]       = { 1.0f };
173         const vk::VkDeviceQueueCreateInfo       queueInfos[]            =
174         {
175                 {
176                         vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
177                         nullptr,
178                         (vk::VkDeviceQueueCreateFlags)0,
179                         queueFamilyIndex,
180                         DE_LENGTH_OF_ARRAY(queuePriorities),
181                         &queuePriorities[0]
182                 }
183         };
184         vk::VkPhysicalDeviceFeatures            features;
185         std::vector<const char*>                        extensions                      = extraExtensions;
186         const auto                                                      mandatoryExtensions     = getMandatoryDeviceExtensions();
187
188         for (const auto& ext : mandatoryExtensions)
189                 extensions.push_back(ext);
190
191         deMemset(&features, 0, sizeof(features));
192         const vk::VkDeviceCreateInfo            deviceParams    =
193         {
194                 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
195                 nullptr,
196                 (vk::VkDeviceCreateFlags)0,
197                 DE_LENGTH_OF_ARRAY(queueInfos),
198                 &queueInfos[0],
199                 0u,                                                                                     // enabledLayerCount
200                 nullptr,                                                                        // ppEnabledLayerNames
201                 static_cast<deUint32>(extensions.size()),       // enabledExtensionCount
202                 extensions.data(),                                                      // ppEnabledExtensionNames
203                 &features
204         };
205
206         return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
207 }
208
209 struct DeviceHelper
210 {
211         const vk::VkPhysicalDevice              physicalDevice;
212         const deUint32                                  queueFamilyIndex;
213         const vk::Unique<vk::VkDevice>  device;
214         const vk::DeviceDriver                  vkd;
215         const vk::VkQueue                               queue;
216
217         DeviceHelper (Context&                                          context,
218                                   const vk::InstanceInterface&          vki,
219                                   vk::VkInstance                                        instance,
220                                   const vector<vk::VkSurfaceKHR>&       surfaces,
221                                   const vector<const char*>&            extraExtensions,
222                                   const vk::VkAllocationCallbacks*      pAllocator = nullptr)
223                 : physicalDevice        (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
224                 , queueFamilyIndex      (vk::wsi::chooseQueueFamilyIndex(vki, physicalDevice, surfaces))
225                 , device                        (createDeviceWithWsi(context.getPlatformInterface(),
226                                                                                                  instance,
227                                                                                                  vki,
228                                                                                                  physicalDevice,
229                                                                                                  extraExtensions,
230                                                                                                  queueFamilyIndex,
231                                                                                                  context.getTestContext().getCommandLine().isValidationEnabled(),
232                                                                                                  pAllocator))
233                 , vkd                           (context.getPlatformInterface(), instance, *device)
234                 , queue                         (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
235         {
236         }
237 };
238
239 vk::VkSwapchainCreateInfoKHR getBasicSwapchainParameters (vk::wsi::Type                                 wsiType,
240                                                                                                                   const vk::InstanceInterface&  vki,
241                                                                                                                   vk::VkPhysicalDevice                  physicalDevice,
242                                                                                                                   vk::VkSurfaceKHR                              surface,
243                                                                                                                   const tcu::UVec2&                             desiredSize,
244                                                                                                                   deUint32                                              desiredImageCount)
245 {
246         const vk::VkSurfaceCapabilitiesKHR              capabilities            = vk::wsi::getPhysicalDeviceSurfaceCapabilities(vki,
247                                                                                                                                                                                                    physicalDevice,
248                                                                                                                                                                                                    surface);
249         const vector<vk::VkSurfaceFormatKHR>    formats                         = vk::wsi::getPhysicalDeviceSurfaceFormats(vki,
250                                                                                                                                                                                           physicalDevice,
251                                                                                                                                                                                           surface);
252         const vk::wsi::PlatformProperties&              platformProperties      = vk::wsi::getPlatformProperties(wsiType);
253         const vk::VkSurfaceTransformFlagBitsKHR transform                       = (capabilities.supportedTransforms & vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
254         const vk::VkSwapchainCreateInfoKHR              parameters                      =
255         {
256                 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
257                 nullptr,
258                 (vk::VkSwapchainCreateFlagsKHR)0,
259                 surface,
260                 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
261                 formats[0].format,
262                 formats[0].colorSpace,
263                 (platformProperties.swapchainExtent == vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
264                         ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
265                 1u,                                                                     // imageArrayLayers
266                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
267                 vk::VK_SHARING_MODE_EXCLUSIVE,
268                 0u,
269                 nullptr,
270                 transform,
271                 vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
272                 vk::VK_PRESENT_MODE_FIFO_KHR,
273                 VK_FALSE,                                                       // clipped
274                 (vk::VkSwapchainKHR)0                           // oldSwapchain
275         };
276
277         return parameters;
278 }
279
280 using CommandBufferSp   = de::SharedPtr<vk::Unique<vk::VkCommandBuffer>>;
281 using FenceSp                   = de::SharedPtr<vk::Unique<vk::VkFence>>;
282 using SemaphoreSp               = de::SharedPtr<vk::Unique<vk::VkSemaphore>>;
283
284 vector<FenceSp> createFences (const vk::DeviceInterface&        vkd,
285                                                           const vk::VkDevice                    device,
286                                                           size_t                                                numFences)
287 {
288         vector<FenceSp> fences(numFences);
289
290         for (size_t ndx = 0; ndx < numFences; ++ndx)
291                 fences[ndx] = FenceSp(new vk::Unique<vk::VkFence>(createFence(vkd, device, vk::VK_FENCE_CREATE_SIGNALED_BIT)));
292
293         return fences;
294 }
295
296 vector<SemaphoreSp> createSemaphores (const vk::DeviceInterface&        vkd,
297                                                                           const vk::VkDevice                    device,
298                                                                           size_t                                                numSemaphores)
299 {
300         vector<SemaphoreSp> semaphores(numSemaphores);
301
302         for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
303                 semaphores[ndx] = SemaphoreSp(new vk::Unique<vk::VkSemaphore>(createSemaphore(vkd, device)));
304
305         return semaphores;
306 }
307
308 vector<CommandBufferSp> allocateCommandBuffers (const vk::DeviceInterface&              vkd,
309                                                                                                 const vk::VkDevice                              device,
310                                                                                                 const vk::VkCommandPool                 commandPool,
311                                                                                                 const vk::VkCommandBufferLevel  level,
312                                                                                                 const size_t                                    numCommandBuffers)
313 {
314         vector<CommandBufferSp>                         buffers         (numCommandBuffers);
315
316         for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
317                 buffers[ndx] = CommandBufferSp(new vk::Unique<vk::VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
318
319         return buffers;
320 }
321
322 class FrameStreamObjects
323 {
324 public:
325         struct FrameObjects
326         {
327                 const vk::VkFence&                      renderCompleteFence;
328                 const vk::VkSemaphore&          renderCompleteSemaphore;
329                 const vk::VkSemaphore&          imageAvailableSemaphore;
330                 const vk::VkCommandBuffer&      commandBuffer;
331         };
332
333         FrameStreamObjects (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkCommandPool cmdPool, size_t maxQueuedFrames)
334                 : renderingCompleteFences               (createFences(vkd, device, maxQueuedFrames))
335                 , renderingCompleteSemaphores   (createSemaphores(vkd, device, maxQueuedFrames))
336                 , imageAvailableSemaphores              (createSemaphores(vkd, device, maxQueuedFrames))
337                 , commandBuffers                                (allocateCommandBuffers(vkd, device, cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames))
338                 , m_maxQueuedFrames                             (maxQueuedFrames)
339                 , m_nextFrame                                   (0u)
340         {}
341
342         size_t frameNumber (void) const { DE_ASSERT(m_nextFrame > 0u); return m_nextFrame - 1u; }
343
344         FrameObjects newFrame ()
345         {
346                 const size_t mod = m_nextFrame % m_maxQueuedFrames;
347                 FrameObjects ret =
348                 {
349                         **renderingCompleteFences[mod],
350                         **renderingCompleteSemaphores[mod],
351                         **imageAvailableSemaphores[mod],
352                         **commandBuffers[mod],
353                 };
354                 ++m_nextFrame;
355                 return ret;
356         }
357
358 private:
359         const vector<FenceSp>                   renderingCompleteFences;
360         const vector<SemaphoreSp>               renderingCompleteSemaphores;
361         const vector<SemaphoreSp>               imageAvailableSemaphores;
362         const vector<CommandBufferSp>   commandBuffers;
363
364         const size_t    m_maxQueuedFrames;
365         size_t                  m_nextFrame;
366 };
367
368 tcu::TestStatus PresentIdWaitInstance::iterate (void)
369 {
370         const tcu::UVec2                                                desiredSize                                     (256, 256);
371         const InstanceHelper                                    instHelper                                      (m_context, m_wsiType);
372         const NativeObjects                                             native                                          (m_context, instHelper.supportedExtensions, m_wsiType, 1u, tcu::just(desiredSize));
373         const vk::Unique<vk::VkSurfaceKHR>              surface                                         (createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow()));
374         const DeviceHelper                                              devHelper                                       (m_context, instHelper.vki, instHelper.instance, vector<vk::VkSurfaceKHR>(1u, surface.get()), getRequiredDeviceExts());
375         const vk::DeviceInterface&                              vkd                                                     = devHelper.vkd;
376         const vk::VkDevice                                              device                                          = *devHelper.device;
377         vk::SimpleAllocator                                             allocator                                       (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
378         const vk::VkSwapchainCreateInfoKHR              swapchainInfo                           = getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
379         const vk::Unique<vk::VkSwapchainKHR>    swapchain                                       (vk::createSwapchainKHR(vkd, device, &swapchainInfo));
380         const vector<vk::VkImage>                               swapchainImages                         = vk::wsi::getSwapchainImages(vkd, device, *swapchain);
381         const vk::Unique<vk::VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
382         const vk::wsi::WsiTriangleRenderer              renderer                                        (vkd,
383                                                                                                                                                  device,
384                                                                                                                                                  allocator,
385                                                                                                                                                  m_context.getBinaryCollection(),
386                                                                                                                                                  false,
387                                                                                                                                                  swapchainImages,
388                                                                                                                                                  swapchainImages,
389                                                                                                                                                  swapchainInfo.imageFormat,
390                                                                                                                                                  tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
391
392         try
393         {
394                 return run(vkd, device, devHelper.queue, commandPool.get(), swapchain.get(), swapchainImages.size(), renderer);
395         }
396         catch (...)
397         {
398                 // Make sure device is idle before destroying resources
399                 vkd.deviceWaitIdle(device);
400                 throw;
401         }
402
403         return tcu::TestStatus(QP_TEST_RESULT_INTERNAL_ERROR, "Reached unreachable code");
404 }
405
406 struct PresentParameters
407 {
408         tcu::Maybe<deUint64>            presentId;
409         tcu::Maybe<vk::VkResult>        expectedResult;
410 };
411
412 struct WaitParameters
413 {
414         deUint64        presentId;
415         deUint64        timeout; // Nanoseconds.
416         bool            timeoutExpected;
417 };
418
419 // This structure represents a set of present operations to be run followed by a set of wait operations to be run after them.
420 // When running the present operations, the present id can be provided, together with an optional expected result to be checked.
421 // When runing the wait operations, the present id must be provided together with a timeout and an indication of whether the operation is expected to time out or not.
422 struct PresentAndWaitOps
423 {
424         vector<PresentParameters>       presentOps;
425         vector<WaitParameters>          waitOps;
426 };
427
428 // Parent class for VK_KHR_present_id and VK_KHR_present_wait simple tests.
429 class PresentIdWaitSimpleInstance : public PresentIdWaitInstance
430 {
431 public:
432         PresentIdWaitSimpleInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
433                 : PresentIdWaitInstance(context, wsiType), m_sequence(sequence)
434         {}
435
436         virtual ~PresentIdWaitSimpleInstance() {}
437
438         virtual tcu::TestStatus         run                                             (const vk::DeviceInterface&                             vkd,
439                                                                                                                  vk::VkDevice                                                   device,
440                                                                                                                  vk::VkQueue                                                    queue,
441                                                                                                                  vk::VkCommandPool                                              commandPool,
442                                                                                                                  vk::VkSwapchainKHR                                             swapchain,
443                                                                                                                  size_t                                                                 swapchainSize,
444                                                                                                                  const vk::wsi::WsiTriangleRenderer&    renderer);
445 protected:
446         const vector<PresentAndWaitOps> m_sequence;
447 };
448
449 // Waits for the appropriate fences, acquires swapchain image, records frame and submits it to the given queue, signaling the appropriate frame semaphores.
450 // Returns the image index from the swapchain.
451 deUint32 recordAndSubmitFrame (FrameStreamObjects::FrameObjects& frameObjects, const vk::wsi::WsiTriangleRenderer& triangleRenderer, const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkSwapchainKHR swapchain, size_t swapchainSize, vk::VkQueue queue, size_t frameNumber, tcu::TestLog& testLog)
452 {
453         // Wait and reset the render complete fence to avoid having too many submitted frames.
454         VK_CHECK(vkd.waitForFences(device, 1u, &frameObjects.renderCompleteFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
455         VK_CHECK(vkd.resetFences(device, 1, &frameObjects.renderCompleteFence));
456
457         // Acquire swapchain image.
458         deUint32 imageNdx = std::numeric_limits<deUint32>::max();
459         const vk::VkResult acquireResult = vkd.acquireNextImageKHR(device,
460                                                                                                                                 swapchain,
461                                                                                                                                 std::numeric_limits<deUint64>::max(),
462                                                                                                                                 frameObjects.imageAvailableSemaphore,
463                                                                                                                                 (vk::VkFence)0,
464                                                                                                                                 &imageNdx);
465
466         if (acquireResult == vk::VK_SUBOPTIMAL_KHR)
467                 testLog << tcu::TestLog::Message << "Got " << acquireResult << " at frame " << frameNumber << tcu::TestLog::EndMessage;
468         else
469                 VK_CHECK(acquireResult);
470         TCU_CHECK(static_cast<size_t>(imageNdx) < swapchainSize);
471
472         // Submit frame to the queue.
473         const vk::VkPipelineStageFlags  waitDstStage    = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
474         const vk::VkSubmitInfo                  submitInfo              =
475         {
476                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
477                 nullptr,
478                 1u,
479                 &frameObjects.imageAvailableSemaphore,
480                 &waitDstStage,
481                 1u,
482                 &frameObjects.commandBuffer,
483                 1u,
484                 &frameObjects.renderCompleteSemaphore,
485         };
486
487         triangleRenderer.recordFrame(frameObjects.commandBuffer, imageNdx, static_cast<deUint32>(frameNumber));
488         VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, frameObjects.renderCompleteFence));
489
490         return imageNdx;
491 }
492
493 tcu::TestStatus PresentIdWaitSimpleInstance::run (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkQueue queue, vk::VkCommandPool commandPool, vk::VkSwapchainKHR swapchain, size_t swapchainSize, const vk::wsi::WsiTriangleRenderer& renderer)
494 {
495         const size_t            maxQueuedFrames         = swapchainSize*2;
496         FrameStreamObjects      frameStreamObjects      (vkd, device, commandPool, maxQueuedFrames);
497
498         for (const auto& step : m_sequence)
499         {
500                 for (const auto& presentOp : step.presentOps)
501                 {
502                         // Get objects for the next frame.
503                         FrameStreamObjects::FrameObjects frameObjects = frameStreamObjects.newFrame();
504
505                         // Record and submit new frame.
506                         deUint32 imageNdx = recordAndSubmitFrame(frameObjects, renderer, vkd, device, swapchain, swapchainSize, queue, frameStreamObjects.frameNumber(), m_context.getTestContext().getLog());
507
508                         // Present rendered frame.
509                         const vk::VkPresentIdKHR                presentId               =
510                         {
511                                 vk::VK_STRUCTURE_TYPE_PRESENT_ID_KHR,                                                   // VkStructureType              sType;
512                                 nullptr,                                                                                                                // const void*                  pNext;
513                                 (presentOp.presentId ? 1u : 0u),                                                                // deUint32                             swapchainCount;
514                                 (presentOp.presentId ? &presentOp.presentId.get() : nullptr ),  // const deUint64*              pPresentIds;
515                         };
516
517                         const vk::VkPresentInfoKHR              presentInfo             =
518                         {
519                                 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
520                                 (presentOp.presentId ? &presentId : nullptr),
521                                 1u,
522                                 &frameObjects.renderCompleteSemaphore,
523                                 1u,
524                                 &swapchain,
525                                 &imageNdx,
526                                 nullptr,
527                         };
528
529                         vk::VkResult result = vkd.queuePresentKHR(queue, &presentInfo);
530
531                         if (presentOp.expectedResult)
532                         {
533                                 const vk::VkResult expected = presentOp.expectedResult.get();
534                                 if ((expected == vk::VK_SUCCESS && result != vk::VK_SUCCESS && result != vk::VK_SUBOPTIMAL_KHR) ||
535                                         (expected != vk::VK_SUCCESS && result != expected))
536                                 {
537                                         std::ostringstream msg;
538                                         msg << "Got " << result << " while expecting " << expected << " after presenting with ";
539                                         if (presentOp.presentId)
540                                                 msg << "id " << presentOp.presentId.get();
541                                         else
542                                                 msg << "no id";
543                                         TCU_FAIL(msg.str());
544                                 }
545                         }
546                 }
547
548                 // Wait operations.
549                 for (const auto& waitOp : step.waitOps)
550                 {
551                         auto                    before          = std::chrono::high_resolution_clock::now();
552                         vk::VkResult    waitResult      = vkd.waitForPresentKHR(device, swapchain, waitOp.presentId, waitOp.timeout);
553                         auto                    after           = std::chrono::high_resolution_clock::now();
554                         auto                    diff            = std::chrono::nanoseconds(after - before).count();
555
556                         if (waitOp.timeoutExpected)
557                         {
558                                 if (waitResult != vk::VK_TIMEOUT)
559                                 {
560                                         std::ostringstream msg;
561                                         msg << "Got " << waitResult << " while expecting a timeout in vkWaitForPresentKHR call";
562                                         TCU_FAIL(msg.str());
563                                 }
564
565                                 const auto timeoutRange = calcTimeoutRange(waitOp.timeout);
566
567                                 if (diff < timeoutRange.first || diff > timeoutRange.second)
568                                 {
569                                         std::ostringstream msg;
570                                         msg << "vkWaitForPresentKHR waited for " << diff << " nanoseconds with a timeout of " << waitOp.timeout << " nanoseconds";
571                                         TCU_FAIL(msg.str());
572                                 }
573                         }
574                         else if (waitResult != vk::VK_SUCCESS)
575                         {
576                                 std::ostringstream msg;
577                                 msg << "Got " << waitResult << " while expecting success in vkWaitForPresentKHR call";
578                                 TCU_FAIL(msg.str());
579                         }
580                 }
581         }
582
583         // Wait until device is idle.
584         VK_CHECK(vkd.deviceWaitIdle(device));
585
586         return tcu::TestStatus::pass("Pass");
587 }
588
589 // Parent class for VK_KHR_present_id simple tests.
590 class PresentIdInstance : public PresentIdWaitSimpleInstance
591 {
592 public:
593         PresentIdInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
594                 : PresentIdWaitSimpleInstance(context, wsiType, sequence)
595         {}
596
597         virtual ~PresentIdInstance() {}
598
599         static vector<const char*>      requiredDeviceExts (void)
600         {
601                 vector<const char*> extensions;
602                 extensions.push_back("VK_KHR_present_id");
603                 return extensions;
604         }
605
606         virtual vector<const char*> getRequiredDeviceExts (void)
607         {
608                 return requiredDeviceExts();
609         }
610 };
611
612 // Parent class for VK_KHR_present_wait simple tests.
613 class PresentWaitInstance : public PresentIdWaitSimpleInstance
614 {
615 public:
616         PresentWaitInstance(Context& context, vk::wsi::Type wsiType, const vector<PresentAndWaitOps>& sequence)
617                 : PresentIdWaitSimpleInstance(context, wsiType, sequence)
618         {}
619
620         virtual ~PresentWaitInstance() {}
621
622         static vector<const char*>      requiredDeviceExts (void)
623         {
624                 vector<const char*> extensions;
625                 extensions.push_back("VK_KHR_present_id");
626                 extensions.push_back("VK_KHR_present_wait");
627                 return extensions;
628         }
629
630         virtual vector<const char*>     getRequiredDeviceExts (void)
631         {
632                 return requiredDeviceExts();
633         }
634 };
635
636 class PresentIdZeroInstance : public PresentIdInstance
637 {
638 public:
639         static const vector<PresentAndWaitOps> sequence;
640
641         PresentIdZeroInstance (Context& context, vk::wsi::Type wsiType)
642                 : PresentIdInstance(context, wsiType, sequence)
643         {}
644 };
645
646 const vector<PresentAndWaitOps> PresentIdZeroInstance::sequence =
647 {
648         { // PresentAndWaitOps
649                 {       // presentOps vector
650                         { tcu::just<deUint64>(0), tcu::just(vk::VK_SUCCESS) },
651                 },
652                 {       // waitOps vector
653                 },
654         },
655 };
656
657 class PresentIdIncreasingInstance : public PresentIdInstance
658 {
659 public:
660         static const vector<PresentAndWaitOps> sequence;
661
662         PresentIdIncreasingInstance (Context& context, vk::wsi::Type wsiType)
663                 : PresentIdInstance(context, wsiType, sequence)
664         {}
665 };
666
667 const vector<PresentAndWaitOps> PresentIdIncreasingInstance::sequence =
668 {
669         { // PresentAndWaitOps
670                 {       // presentOps vector
671                         { tcu::just<deUint64>(1),                                                       tcu::just(vk::VK_SUCCESS) },
672                         { tcu::just(std::numeric_limits<deUint64>::max()),      tcu::just(vk::VK_SUCCESS) },
673                 },
674                 {       // waitOps vector
675                 },
676         },
677 };
678
679 class PresentIdInterleavedInstance : public PresentIdInstance
680 {
681 public:
682         static const vector<PresentAndWaitOps> sequence;
683
684         PresentIdInterleavedInstance (Context& context, vk::wsi::Type wsiType)
685                 : PresentIdInstance(context, wsiType, sequence)
686         {}
687 };
688
689 const vector<PresentAndWaitOps> PresentIdInterleavedInstance::sequence =
690 {
691         { // PresentAndWaitOps
692                 {       // presentOps vector
693                         { tcu::just<deUint64>(0),                                                       tcu::just(vk::VK_SUCCESS) },
694                         { tcu::just<deUint64>(1),                                                       tcu::just(vk::VK_SUCCESS) },
695                         { tcu::nothing<deUint64>(),                                                     tcu::just(vk::VK_SUCCESS) },
696                         { tcu::just(std::numeric_limits<deUint64>::max()),      tcu::just(vk::VK_SUCCESS) },
697                 },
698                 {       // waitOps vector
699                 },
700         },
701 };
702
703 class PresentWaitSingleFrameInstance : public PresentWaitInstance
704 {
705 public:
706         static const vector<PresentAndWaitOps> sequence;
707
708         PresentWaitSingleFrameInstance (Context& context, vk::wsi::Type wsiType)
709                 : PresentWaitInstance(context, wsiType, sequence)
710         {}
711 };
712
713 const vector<PresentAndWaitOps> PresentWaitSingleFrameInstance::sequence =
714 {
715         { // PresentAndWaitOps
716                 {       // presentOps vector
717                         { tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
718                 },
719                 {       // waitOps vector
720                         { 1ull, k10sec, false },
721                 },
722         },
723 };
724
725 class PresentWaitPastFrameInstance : public PresentWaitInstance
726 {
727 public:
728         static const vector<PresentAndWaitOps> sequence;
729
730         PresentWaitPastFrameInstance (Context& context, vk::wsi::Type wsiType)
731                 : PresentWaitInstance(context, wsiType, sequence)
732         {}
733 };
734
735 const vector<PresentAndWaitOps> PresentWaitPastFrameInstance::sequence =
736 {
737         // Start with present id 1.
738         { // PresentAndWaitOps
739                 {       // presentOps vector
740                         { tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
741                 },
742                 {       // waitOps vector
743                         { 1ull, k10sec, false },
744                         { 1ull, 0ull,   false },
745                 },
746         },
747         // Then the maximum value. Both waiting for id 1 and the max id should work.
748         { // PresentAndWaitOps
749                 {       // presentOps vector
750                         { tcu::just(std::numeric_limits<deUint64>::max()), tcu::just(vk::VK_SUCCESS) },
751                 },
752                 {       // waitOps vector
753                         { 1ull,                                 0ull,   false },
754                         { 1ull,                                 k10sec, false },
755                         { std::numeric_limits<deUint64>::max(), k10sec, false },
756                         { std::numeric_limits<deUint64>::max(), 0ull,   false },
757                 },
758         },
759         // Submit some frames without id after having used the maximum value. This should also work.
760         { // PresentAndWaitOps
761                 {       // presentOps vector
762                         { tcu::nothing<deUint64>(),     tcu::just(vk::VK_SUCCESS) },
763                         { tcu::just<deUint64>(0),       tcu::just(vk::VK_SUCCESS) },
764                 },
765                 {       // waitOps vector
766                 },
767         },
768 };
769
770 class PresentWaitNoFramesInstance : public PresentWaitInstance
771 {
772 public:
773         static const vector<PresentAndWaitOps> sequence;
774
775         PresentWaitNoFramesInstance (Context& context, vk::wsi::Type wsiType)
776                 : PresentWaitInstance(context, wsiType, sequence)
777         {}
778 };
779
780 const vector<PresentAndWaitOps> PresentWaitNoFramesInstance::sequence =
781 {
782         { // PresentAndWaitOps
783                 {       // presentOps vector
784                 },
785                 {       // waitOps vector
786                         { 1ull, 0ull,  true },
787                         { 1ull, k1sec, true },
788                 },
789         },
790 };
791
792 class PresentWaitNoFrameIdInstance : public PresentWaitInstance
793 {
794 public:
795         static const vector<PresentAndWaitOps> sequence;
796
797         PresentWaitNoFrameIdInstance (Context& context, vk::wsi::Type wsiType)
798                 : PresentWaitInstance(context, wsiType, sequence)
799         {}
800 };
801
802 const vector<PresentAndWaitOps> PresentWaitNoFrameIdInstance::sequence =
803 {
804         { // PresentAndWaitOps
805                 {       // presentOps vector
806                         { tcu::just<deUint64>(0), tcu::just(vk::VK_SUCCESS) },
807                 },
808                 {       // waitOps vector
809                         { 1ull, 0ull,  true },
810                         { 1ull, k1sec, true },
811                 },
812         },
813         { // PresentAndWaitOps
814                 {       // presentOps vector
815                         { tcu::nothing<deUint64>(), tcu::just(vk::VK_SUCCESS) },
816                 },
817                 {       // waitOps vector
818                         { 1ull, 0ull,  true },
819                         { 1ull, k1sec, true },
820                 },
821         },
822 };
823
824 class PresentWaitFutureFrameInstance : public PresentWaitInstance
825 {
826 public:
827         static const vector<PresentAndWaitOps> sequence;
828
829         PresentWaitFutureFrameInstance (Context& context, vk::wsi::Type wsiType)
830                 : PresentWaitInstance(context, wsiType, sequence)
831         {}
832 };
833
834 const vector<PresentAndWaitOps> PresentWaitFutureFrameInstance::sequence =
835 {
836         { // PresentAndWaitOps
837                 {       // presentOps vector
838                         { tcu::just<deUint64>(1), tcu::just(vk::VK_SUCCESS) },
839                 },
840                 {       // waitOps vector
841                         { std::numeric_limits<deUint64>::max(), k1sec, true },
842                         { std::numeric_limits<deUint64>::max(), 0ull,  true },
843                         { 2ull,                                 0ull,  true },
844                         { 2ull,                                 k1sec, true },
845                 },
846         },
847 };
848
849 // Instance with two windows and surfaces to check present ids are not mixed up.
850 class PresentWaitDualInstance : public TestInstance
851 {
852 public:
853                                                                 PresentWaitDualInstance         (Context& context, vk::wsi::Type wsiType) : TestInstance(context), m_wsiType(wsiType) {}
854         virtual                                         ~PresentWaitDualInstance        (void) {}
855
856         virtual tcu::TestStatus         iterate                                         (void);
857
858         static vector<const char*>      requiredDeviceExts                      (void)
859         {
860                 vector<const char*> extensions;
861                 extensions.push_back("VK_KHR_present_id");
862                 extensions.push_back("VK_KHR_present_wait");
863                 return extensions;
864         }
865
866         virtual vector<const char*>     getRequiredDeviceExts           (void)
867         {
868                 return requiredDeviceExts();
869         }
870
871 protected:
872         vk::wsi::Type                           m_wsiType;
873 };
874
875 struct IdAndWait
876 {
877         deUint64        presentId;
878         bool            wait;
879 };
880
881 struct DualIdAndWait
882 {
883         IdAndWait idWait1;
884         IdAndWait idWait2;
885 };
886
887 tcu::TestStatus PresentWaitDualInstance::iterate (void)
888 {
889         const tcu::UVec2                                                desiredSize                                     (256, 256);
890         const InstanceHelper                                    instHelper                                      (m_context, m_wsiType);
891         const NativeObjects                                             native                                          (m_context, instHelper.supportedExtensions, m_wsiType, 2u, tcu::just(desiredSize));
892         const vk::Unique<vk::VkSurfaceKHR>              surface1                                        (createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow(0)));
893         const vk::Unique<vk::VkSurfaceKHR>              surface2                                        (createSurface(instHelper.vki, instHelper.instance, m_wsiType, native.getDisplay(), native.getWindow(1)));
894         const DeviceHelper                                              devHelper                                       (m_context, instHelper.vki, instHelper.instance, vector<vk::VkSurfaceKHR>{surface1.get(), surface2.get()}, getRequiredDeviceExts());
895         const vk::DeviceInterface&                              vkd                                                     = devHelper.vkd;
896         const vk::VkDevice                                              device                                          = *devHelper.device;
897         vk::SimpleAllocator                                             allocator                                       (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
898         const vk::VkSwapchainCreateInfoKHR              swapchainInfo1                          = getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, surface1.get(), desiredSize, 2);
899         const vk::VkSwapchainCreateInfoKHR              swapchainInfo2                          = getBasicSwapchainParameters(m_wsiType, instHelper.vki, devHelper.physicalDevice, surface2.get(), desiredSize, 2);
900         const vk::Unique<vk::VkSwapchainKHR>    swapchain1                                      (vk::createSwapchainKHR(vkd, device, &swapchainInfo1));
901         const vk::Unique<vk::VkSwapchainKHR>    swapchain2                                      (vk::createSwapchainKHR(vkd, device, &swapchainInfo2));
902         const vector<vk::VkImage>                               swapchainImages1                        = vk::wsi::getSwapchainImages(vkd, device, swapchain1.get());
903         const vector<vk::VkImage>                               swapchainImages2                        = vk::wsi::getSwapchainImages(vkd, device, swapchain2.get());
904         const vk::Unique<vk::VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
905         const vk::wsi::WsiTriangleRenderer              renderer1                                       (vkd,
906                                                                                                                                                  device,
907                                                                                                                                                  allocator,
908                                                                                                                                                  m_context.getBinaryCollection(),
909                                                                                                                                                  false,
910                                                                                                                                                  swapchainImages1,
911                                                                                                                                                  swapchainImages1,
912                                                                                                                                                  swapchainInfo1.imageFormat,
913                                                                                                                                                  tcu::UVec2(swapchainInfo1.imageExtent.width, swapchainInfo1.imageExtent.height));
914         const vk::wsi::WsiTriangleRenderer              renderer2                                       (vkd,
915                                                                                                                                                  device,
916                                                                                                                                                  allocator,
917                                                                                                                                                  m_context.getBinaryCollection(),
918                                                                                                                                                  false,
919                                                                                                                                                  swapchainImages2,
920                                                                                                                                                  swapchainImages2,
921                                                                                                                                                  swapchainInfo2.imageFormat,
922                                                                                                                                                  tcu::UVec2(swapchainInfo2.imageExtent.width, swapchainInfo2.imageExtent.height));
923         tcu::TestLog&                                                   testLog                                         = m_context.getTestContext().getLog();
924
925         try
926         {
927                 const size_t            maxQueuedFrames         = swapchainImages1.size()*2;
928                 FrameStreamObjects      frameStreamObjects1     (vkd, device, commandPool.get(), maxQueuedFrames);
929                 FrameStreamObjects      frameStreamObjects2     (vkd, device, commandPool.get(), maxQueuedFrames);
930
931                 // Increasing ids for both swapchains, waiting on some to make sure we do not time out unexpectedly.
932                 const vector<DualIdAndWait> sequence =
933                 {
934                         {
935                                 { 1ull, false },
936                                 { 2ull, true  },
937                         },
938                         {
939                                 { 4ull, true  },
940                                 { 3ull, false },
941                         },
942                         {
943                                 { 5ull, true  },
944                                 { 6ull, true  },
945                         },
946                 };
947
948                 for (const auto& step : sequence)
949                 {
950                         // Get objects for the next frames.
951                         FrameStreamObjects::FrameObjects frameObjects1 = frameStreamObjects1.newFrame();
952                         FrameStreamObjects::FrameObjects frameObjects2 = frameStreamObjects2.newFrame();
953
954                         // Record and submit frame.
955                         deUint32 imageNdx1 = recordAndSubmitFrame(frameObjects1, renderer1, vkd, device, swapchain1.get(), swapchainImages1.size(), devHelper.queue, frameStreamObjects1.frameNumber(), testLog);
956                         deUint32 imageNdx2 = recordAndSubmitFrame(frameObjects2, renderer2, vkd, device, swapchain2.get(), swapchainImages2.size(), devHelper.queue, frameStreamObjects2.frameNumber(), testLog);
957
958                         // Present both images at the same time with their corresponding ids.
959                         const deUint64                          presentIdsArr[] = { step.idWait1.presentId, step.idWait2.presentId };
960                         const vk::VkPresentIdKHR        presentId               =
961                         {
962                                 vk::VK_STRUCTURE_TYPE_PRESENT_ID_KHR,                                                   // VkStructureType              sType;
963                                 nullptr,                                                                                                                // const void*                  pNext;
964                                 static_cast<deUint32>(DE_LENGTH_OF_ARRAY(presentIdsArr)),               // deUint32                             swapchainCount;
965                                 presentIdsArr,                                                                                                  // const deUint64*              pPresentIds;
966                         };
967
968                         const vk::VkSemaphore           semaphoreArr[]  = { frameObjects1.renderCompleteSemaphore, frameObjects2.renderCompleteSemaphore };
969                         const vk::VkSwapchainKHR        swapchainArr[]  = { swapchain1.get(), swapchain2.get() };
970                         const deUint32                          imgIndexArr[]   = { imageNdx1, imageNdx2 };
971                         const vk::VkPresentInfoKHR      presentInfo             =
972                         {
973                                 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
974                                 &presentId,
975                                 static_cast<deUint32>(DE_LENGTH_OF_ARRAY(semaphoreArr)),
976                                 semaphoreArr,
977                                 static_cast<deUint32>(DE_LENGTH_OF_ARRAY(swapchainArr)),
978                                 swapchainArr,
979                                 imgIndexArr,
980                                 nullptr,
981                         };
982
983                         VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
984
985                         const IdAndWait* idWaitArr[] = { &step.idWait1, &step.idWait2 };
986                         for (int i = 0; i < DE_LENGTH_OF_ARRAY(idWaitArr); ++i)
987                         {
988                                 if (idWaitArr[i]->wait)
989                                         VK_CHECK(vkd.waitForPresentKHR(device, swapchainArr[i], idWaitArr[i]->presentId, k10sec));
990                         }
991                 }
992
993                 // Wait until device is idle.
994                 VK_CHECK(vkd.deviceWaitIdle(device));
995
996                 return tcu::TestStatus::pass("Pass");
997         }
998         catch (...)
999         {
1000                 // Make sure device is idle before destroying resources
1001                 vkd.deviceWaitIdle(device);
1002                 throw;
1003         }
1004
1005         return tcu::TestStatus(QP_TEST_RESULT_INTERNAL_ERROR, "Reached unreachable code");
1006 }
1007
1008 // Templated class for every instance type.
1009 template <class T>      // T is the test instance class.
1010 class PresentIdWaitCase : public TestCase
1011 {
1012 public:
1013                                                         PresentIdWaitCase       (vk::wsi::Type wsiType, tcu::TestContext& ctx, const std::string& name, const std::string& description);
1014         virtual                                 ~PresentIdWaitCase      (void) {}
1015         virtual void                    initPrograms            (vk::SourceCollections& programCollection) const;
1016         virtual TestInstance*   createInstance          (Context& context) const;
1017         virtual void                    checkSupport            (Context& context) const;
1018
1019 protected:
1020         vk::wsi::Type                   m_wsiType;
1021 };
1022
1023 template <class T>
1024 PresentIdWaitCase<T>::PresentIdWaitCase (vk::wsi::Type wsiType, tcu::TestContext& ctx, const std::string& name, const std::string& description)
1025         : TestCase(ctx, name, description), m_wsiType(wsiType)
1026 {
1027 }
1028
1029 template <class T>
1030 void PresentIdWaitCase<T>::initPrograms (vk::SourceCollections& programCollection) const
1031 {
1032         vk::wsi::WsiTriangleRenderer::getPrograms(programCollection);
1033 }
1034
1035 template <class T>
1036 TestInstance* PresentIdWaitCase<T>::createInstance (Context& context) const
1037 {
1038         return new T(context, m_wsiType);
1039 }
1040
1041 template <class T>
1042 void PresentIdWaitCase<T>::checkSupport (Context& context) const
1043 {
1044         // Check instance extension support.
1045         const auto instanceExtensions = getRequiredInstanceExtensions(m_wsiType);
1046         for (const auto& ext : instanceExtensions)
1047         {
1048                 if (!context.isInstanceFunctionalitySupported(ext))
1049                         TCU_THROW(NotSupportedError, ext + string(" is not supported"));
1050         }
1051
1052         // Check device extension support.
1053         const auto& vki                 = context.getInstanceInterface();
1054         const auto  physDev             = context.getPhysicalDevice();
1055         const auto  supportedDeviceExts = vk::enumerateDeviceExtensionProperties(vki, physDev, nullptr);
1056         const auto  mandatoryDeviceExts = getMandatoryDeviceExtensions();
1057
1058         auto checkedDeviceExts = T::requiredDeviceExts();
1059         for (const auto& ext : mandatoryDeviceExts)
1060                 checkedDeviceExts.push_back(ext);
1061
1062         for (const auto& ext : checkedDeviceExts)
1063         {
1064                 if (!vk::isExtensionSupported(supportedDeviceExts, vk::RequiredExtension(ext)))
1065                         TCU_THROW(NotSupportedError, ext + string(" is not supported"));
1066         }
1067 }
1068
1069 void createPresentIdTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1070 {
1071         testGroup->addChild(new PresentIdWaitCase<PresentIdZeroInstance>                (wsiType, testGroup->getTestContext(), "zero",                  "Use present id zero"));
1072         testGroup->addChild(new PresentIdWaitCase<PresentIdIncreasingInstance>  (wsiType, testGroup->getTestContext(), "increasing",    "Use increasing present ids"));
1073         testGroup->addChild(new PresentIdWaitCase<PresentIdInterleavedInstance> (wsiType, testGroup->getTestContext(), "interleaved",   "Use increasing present ids interleaved with no ids"));
1074 }
1075
1076 void createPresentWaitTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1077 {
1078         testGroup->addChild(new PresentIdWaitCase<PresentWaitSingleFrameInstance>       (wsiType, testGroup->getTestContext(), "single_no_timeout",     "Present single frame with no expected timeout"));
1079         testGroup->addChild(new PresentIdWaitCase<PresentWaitPastFrameInstance>         (wsiType, testGroup->getTestContext(), "past_no_timeout",       "Wait for past frame with no expected timeout"));
1080         testGroup->addChild(new PresentIdWaitCase<PresentWaitNoFramesInstance>          (wsiType, testGroup->getTestContext(), "no_frames",                     "Expect timeout before submitting any frame"));
1081         testGroup->addChild(new PresentIdWaitCase<PresentWaitNoFrameIdInstance>         (wsiType, testGroup->getTestContext(), "no_frame_id",           "Expect timeout after submitting frames with no id"));
1082         testGroup->addChild(new PresentIdWaitCase<PresentWaitFutureFrameInstance>       (wsiType, testGroup->getTestContext(), "future_frame",          "Expect timeout when waiting for a future frame"));
1083         testGroup->addChild(new PresentIdWaitCase<PresentWaitDualInstance>                      (wsiType, testGroup->getTestContext(), "two_swapchains",        "Smoke test using two windows, surfaces and swapchains"));
1084 }
1085
1086 } // anonymous
1087
1088 void createPresentIdWaitTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1089 {
1090         de::MovePtr<tcu::TestCaseGroup> idGroup         (new tcu::TestCaseGroup(testGroup->getTestContext(), "id",              "VK_KHR_present_id tests"));
1091         de::MovePtr<tcu::TestCaseGroup> waitGroup       (new tcu::TestCaseGroup(testGroup->getTestContext(), "wait",    "VK_KHR_present_wait tests"));
1092
1093         createPresentIdTests    (idGroup.get(),         wsiType);
1094         createPresentWaitTests  (waitGroup.get(),       wsiType);
1095
1096         testGroup->addChild(idGroup.release());
1097         testGroup->addChild(waitGroup.release());
1098 }
1099
1100 } // wsi
1101 } // vkt
1102