cb5fe91d9742526239f8c4fa0b3a259fe47c722c
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / wsi / vktWsiSwapchainTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief VkSwapchain Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiSwapchainTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkWsiPlatform.hpp"
40 #include "vkWsiUtil.hpp"
41 #include "vkAllocationCallbackUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44
45 #include "tcuTestLog.hpp"
46 #include "tcuFormatUtil.hpp"
47 #include "tcuPlatform.hpp"
48 #include "tcuResultCollector.hpp"
49
50 #include "deUniquePtr.hpp"
51 #include "deStringUtil.hpp"
52 #include "deArrayUtil.hpp"
53 #include "deSharedPtr.hpp"
54
55 #include <limits>
56
57 namespace vkt
58 {
59 namespace wsi
60 {
61
62 namespace
63 {
64
65 using namespace vk;
66 using namespace vk::wsi;
67
68 using tcu::TestLog;
69 using tcu::Maybe;
70 using tcu::UVec2;
71
72 using de::MovePtr;
73 using de::UniquePtr;
74
75 using std::string;
76 using std::vector;
77
78 typedef vector<VkExtensionProperties> Extensions;
79
80 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
81 {
82         for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
83                  requiredExtName != requiredExtensions.end();
84                  ++requiredExtName)
85         {
86                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
87                         TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
88         }
89 }
90
91 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&                vkp,
92                                                                                 deUint32                                                version,
93                                                                                 const Extensions&                               supportedExtensions,
94                                                                                 Type                                                    wsiType,
95                                                                                 const VkAllocationCallbacks*    pAllocator      = DE_NULL)
96 {
97         vector<string>  extensions;
98
99         extensions.push_back("VK_KHR_surface");
100         extensions.push_back(getExtensionName(wsiType));
101
102         // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
103         // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
104         // but using them without enabling the extension is not allowed. Thus we have
105         // two options:
106         //
107         // 1) Filter out non-core formats to stay within valid usage.
108         //
109         // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
110         //
111         // We opt for (2) as it provides basic coverage for the extension as a bonus.
112         if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
113                 extensions.push_back("VK_EXT_swapchain_colorspace");
114
115         checkAllSupported(supportedExtensions, extensions);
116
117         return vk::createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
118 }
119
120 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
121 {
122         VkPhysicalDeviceFeatures features;
123         deMemset(&features, 0, sizeof(features));
124         return features;
125 }
126
127 Move<VkDevice> createDeviceWithWsi (const PlatformInterface&            vkp,
128                                                                         VkInstance                                              instance,
129                                                                         const InstanceInterface&                vki,
130                                                                         VkPhysicalDevice                                physicalDevice,
131                                                                         const Extensions&                               supportedExtensions,
132                                                                         const deUint32                                  queueFamilyIndex,
133                                                                         const VkAllocationCallbacks*    pAllocator = DE_NULL)
134 {
135         const float                                             queuePriorities[]       = { 1.0f };
136         const VkDeviceQueueCreateInfo   queueInfos[]            =
137         {
138                 {
139                         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
140                         DE_NULL,
141                         (VkDeviceQueueCreateFlags)0,
142                         queueFamilyIndex,
143                         DE_LENGTH_OF_ARRAY(queuePriorities),
144                         &queuePriorities[0]
145                 }
146         };
147         const VkPhysicalDeviceFeatures  features                = getDeviceFeaturesForWsi();
148         const char* const                               extensions[]    = { "VK_KHR_swapchain" };
149         const VkDeviceCreateInfo                deviceParams    =
150         {
151                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
152                 DE_NULL,
153                 (VkDeviceCreateFlags)0,
154                 DE_LENGTH_OF_ARRAY(queueInfos),
155                 &queueInfos[0],
156                 0u,                                                                     // enabledLayerCount
157                 DE_NULL,                                                        // ppEnabledLayerNames
158                 DE_LENGTH_OF_ARRAY(extensions),         // enabledExtensionCount
159                 DE_ARRAY_BEGIN(extensions),                     // ppEnabledExtensionNames
160                 &features
161         };
162
163         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
164         {
165                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[ndx])))
166                         TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
167         }
168
169         return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
170 }
171
172 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
173 {
174         deUint32        numFamilies             = 0;
175
176         vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
177
178         return numFamilies;
179 }
180
181 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
182 {
183         const deUint32          numTotalFamilyIndices   = getNumQueueFamilyIndices(vki, physicalDevice);
184         vector<deUint32>        supportedFamilyIndices;
185
186         for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
187         {
188                 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
189                         supportedFamilyIndices.push_back(queueFamilyNdx);
190         }
191
192         return supportedFamilyIndices;
193 }
194
195 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
196 {
197         const vector<deUint32>  supportedFamilyIndices  = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
198
199         if (supportedFamilyIndices.empty())
200                 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
201
202         return supportedFamilyIndices[0];
203 }
204
205 struct InstanceHelper
206 {
207         const vector<VkExtensionProperties>     supportedExtensions;
208         const Unique<VkInstance>                        instance;
209         const InstanceDriver                            vki;
210
211         InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
212                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
213                                                                                                                                           DE_NULL))
214                 , instance                              (createInstanceWithWsi(context.getPlatformInterface(),
215                                                                                                            context.getUsedApiVersion(),
216                                                                                                            supportedExtensions,
217                                                                                                            wsiType,
218                                                                                                            pAllocator))
219                 , vki                                   (context.getPlatformInterface(), *instance)
220         {}
221 };
222
223 struct DeviceHelper
224 {
225         const VkPhysicalDevice  physicalDevice;
226         const deUint32                  queueFamilyIndex;
227         const Unique<VkDevice>  device;
228         const DeviceDriver              vkd;
229         const VkQueue                   queue;
230
231         DeviceHelper (Context&                                          context,
232                                   const InstanceInterface&              vki,
233                                   VkInstance                                    instance,
234                                   VkSurfaceKHR                                  surface,
235                                   const VkAllocationCallbacks*  pAllocator = DE_NULL)
236                 : physicalDevice        (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
237                 , queueFamilyIndex      (chooseQueueFamilyIndex(vki, physicalDevice, surface))
238                 , device                        (createDeviceWithWsi(context.getPlatformInterface(),
239                                                                                                  context.getInstance(),
240                                                                                                  vki,
241                                                                                                  physicalDevice,
242                                                                                                  enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
243                                                                                                  queueFamilyIndex,
244                                                                                                  pAllocator))
245                 , vkd                           (context.getPlatformInterface(), context.getInstance(), *device)
246                 , queue                         (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
247         {
248         }
249 };
250
251 MovePtr<Display> createDisplay (const vk::Platform&     platform,
252                                                                 const Extensions&       supportedExtensions,
253                                                                 Type                            wsiType)
254 {
255         try
256         {
257                 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
258         }
259         catch (const tcu::NotSupportedError& e)
260         {
261                 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
262                     platform.hasDisplay(wsiType))
263                 {
264                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
265                         // must support creating native display & window for that WSI type.
266                         throw tcu::TestError(e.getMessage());
267                 }
268                 else
269                         throw;
270         }
271 }
272
273 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
274 {
275         try
276         {
277                 return MovePtr<Window>(display.createWindow(initialSize));
278         }
279         catch (const tcu::NotSupportedError& e)
280         {
281                 // See createDisplay - assuming that wsi::Display was supported platform port
282                 // should also support creating a window.
283                 throw tcu::TestError(e.getMessage());
284         }
285 }
286
287 struct NativeObjects
288 {
289         const UniquePtr<Display>        display;
290         const UniquePtr<Window>         window;
291
292         NativeObjects (Context&                         context,
293                                    const Extensions&    supportedExtensions,
294                                    Type                                 wsiType,
295                                    const Maybe<UVec2>&  initialWindowSize = tcu::nothing<UVec2>())
296                 : display       (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
297                 , window        (createWindow(*display, initialWindowSize))
298         {}
299 };
300
301 enum TestDimension
302 {
303         TEST_DIMENSION_MIN_IMAGE_COUNT = 0,     //!< Test all supported image counts
304         TEST_DIMENSION_IMAGE_FORMAT,            //!< Test all supported formats
305         TEST_DIMENSION_IMAGE_EXTENT,            //!< Test various (supported) extents
306         TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
307         TEST_DIMENSION_IMAGE_USAGE,
308         TEST_DIMENSION_IMAGE_SHARING_MODE,
309         TEST_DIMENSION_PRE_TRANSFORM,
310         TEST_DIMENSION_COMPOSITE_ALPHA,
311         TEST_DIMENSION_PRESENT_MODE,
312         TEST_DIMENSION_CLIPPED,
313
314         TEST_DIMENSION_LAST
315 };
316
317 const char* getTestDimensionName (TestDimension dimension)
318 {
319         static const char* const s_names[] =
320         {
321                 "min_image_count",
322                 "image_format",
323                 "image_extent",
324                 "image_array_layers",
325                 "image_usage",
326                 "image_sharing_mode",
327                 "pre_transform",
328                 "composite_alpha",
329                 "present_mode",
330                 "clipped"
331         };
332         return de::getSizedArrayElement<TEST_DIMENSION_LAST>(s_names, dimension);
333 }
334
335 struct TestParameters
336 {
337         Type                    wsiType;
338         TestDimension   dimension;
339
340         TestParameters (Type wsiType_, TestDimension dimension_)
341                 : wsiType       (wsiType_)
342                 , dimension     (dimension_)
343         {}
344
345         TestParameters (void)
346                 : wsiType       (TYPE_LAST)
347                 , dimension     (TEST_DIMENSION_LAST)
348         {}
349 };
350
351 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type                                                          wsiType,
352                                                                                                                                   TestDimension                                         dimension,
353                                                                                                                                   const VkSurfaceCapabilitiesKHR&       capabilities,
354                                                                                                                                   const vector<VkSurfaceFormatKHR>&     formats,
355                                                                                                                                   const vector<VkPresentModeKHR>&       presentModes)
356 {
357         const PlatformProperties&                       platformProperties      = getPlatformProperties(wsiType);
358         vector<VkSwapchainCreateInfoKHR>        cases;
359         const VkSurfaceTransformFlagBitsKHR defaultTransform    = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
360         const VkSwapchainCreateInfoKHR          baseParameters          =
361         {
362                 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
363                 DE_NULL,
364                 (VkSwapchainCreateFlagsKHR)0,
365                 (VkSurfaceKHR)0,
366                 capabilities.minImageCount,
367                 formats[0].format,
368                 formats[0].colorSpace,
369                 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE
370                         ? capabilities.minImageExtent : capabilities.currentExtent),
371                 1u,                                                                     // imageArrayLayers
372                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
373                 VK_SHARING_MODE_EXCLUSIVE,
374                 0u,
375                 (const deUint32*)DE_NULL,
376                 defaultTransform,
377                 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
378                 VK_PRESENT_MODE_FIFO_KHR,
379                 VK_FALSE,                                                       // clipped
380                 (VkSwapchainKHR)0                                       // oldSwapchain
381         };
382
383         switch (dimension)
384         {
385                 case TEST_DIMENSION_MIN_IMAGE_COUNT:
386                 {
387                         const deUint32  maxImageCountToTest     = de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u);
388
389                         for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount)
390                         {
391                                 cases.push_back(baseParameters);
392                                 cases.back().minImageCount = imageCount;
393                         }
394
395                         break;
396                 }
397
398                 case TEST_DIMENSION_IMAGE_FORMAT:
399                 {
400                         for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
401                         {
402                                 cases.push_back(baseParameters);
403                                 cases.back().imageFormat                = curFmt->format;
404                                 cases.back().imageColorSpace    = curFmt->colorSpace;
405                         }
406
407                         break;
408                 }
409
410                 case TEST_DIMENSION_IMAGE_EXTENT:
411                 {
412                         static const VkExtent2D s_testSizes[]   =
413                         {
414                                 { 1, 1 },
415                                 { 16, 32 },
416                                 { 32, 16 },
417                                 { 632, 231 },
418                                 { 117, 998 },
419                         };
420
421                         if (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE ||
422                                 platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
423                         {
424                                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_testSizes); ++ndx)
425                                 {
426                                         cases.push_back(baseParameters);
427                                         cases.back().imageExtent.width  = de::clamp(s_testSizes[ndx].width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
428                                         cases.back().imageExtent.height = de::clamp(s_testSizes[ndx].height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
429                                 }
430                         }
431
432                         if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE)
433                         {
434                                 cases.push_back(baseParameters);
435                                 cases.back().imageExtent = capabilities.currentExtent;
436                         }
437
438                         if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
439                         {
440                                 cases.push_back(baseParameters);
441                                 cases.back().imageExtent = capabilities.minImageExtent;
442
443                                 cases.push_back(baseParameters);
444                                 cases.back().imageExtent = capabilities.maxImageExtent;
445                         }
446
447                         break;
448                 }
449
450                 case TEST_DIMENSION_IMAGE_ARRAY_LAYERS:
451                 {
452                         const deUint32  maxLayers       = de::min(capabilities.maxImageArrayLayers, 16u);
453
454                         for (deUint32 numLayers = 1; numLayers <= maxLayers; ++numLayers)
455                         {
456                                 cases.push_back(baseParameters);
457                                 cases.back().imageArrayLayers = numLayers;
458                         }
459
460                         break;
461                 }
462
463                 case TEST_DIMENSION_IMAGE_USAGE:
464                 {
465                         for (deUint32 flags = 1u; flags <= capabilities.supportedUsageFlags; ++flags)
466                         {
467                                 if ((flags & ~capabilities.supportedUsageFlags) == 0)
468                                 {
469                                         cases.push_back(baseParameters);
470                                         cases.back().imageUsage = flags;
471                                 }
472                         }
473
474                         break;
475                 }
476
477                 case TEST_DIMENSION_IMAGE_SHARING_MODE:
478                 {
479                         cases.push_back(baseParameters);
480                         cases.back().imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
481
482                         cases.push_back(baseParameters);
483                         cases.back().imageSharingMode = VK_SHARING_MODE_CONCURRENT;
484
485                         break;
486                 }
487
488                 case TEST_DIMENSION_PRE_TRANSFORM:
489                 {
490                         for (deUint32 transform = 1u;
491                                  transform <= capabilities.supportedTransforms;
492                                  transform = transform<<1u)
493                         {
494                                 if ((transform & capabilities.supportedTransforms) != 0)
495                                 {
496                                         cases.push_back(baseParameters);
497                                         cases.back().preTransform = (VkSurfaceTransformFlagBitsKHR)transform;
498                                 }
499                         }
500
501                         break;
502                 }
503
504                 case TEST_DIMENSION_COMPOSITE_ALPHA:
505                 {
506                         for (deUint32 alphaMode = 1u;
507                                  alphaMode <= capabilities.supportedCompositeAlpha;
508                                  alphaMode = alphaMode<<1u)
509                         {
510                                 if ((alphaMode & capabilities.supportedCompositeAlpha) != 0)
511                                 {
512                                         cases.push_back(baseParameters);
513                                         cases.back().compositeAlpha = (VkCompositeAlphaFlagBitsKHR)alphaMode;
514                                 }
515                         }
516
517                         break;
518                 }
519
520                 case TEST_DIMENSION_PRESENT_MODE:
521                 {
522                         for (vector<VkPresentModeKHR>::const_iterator curMode = presentModes.begin(); curMode != presentModes.end(); ++curMode)
523                         {
524                                 cases.push_back(baseParameters);
525                                 cases.back().presentMode = *curMode;
526                         }
527
528                         break;
529                 }
530
531                 case TEST_DIMENSION_CLIPPED:
532                 {
533                         cases.push_back(baseParameters);
534                         cases.back().clipped = VK_FALSE;
535
536                         cases.push_back(baseParameters);
537                         cases.back().clipped = VK_TRUE;
538
539                         break;
540                 }
541
542                 default:
543                         DE_FATAL("Impossible");
544         }
545
546         DE_ASSERT(!cases.empty());
547         return cases;
548 }
549
550 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type                                                          wsiType,
551                                                                                                                                   TestDimension                                         dimension,
552                                                                                                                                   const InstanceInterface&                      vki,
553                                                                                                                                   VkPhysicalDevice                                      physicalDevice,
554                                                                                                                                   VkSurfaceKHR                                          surface)
555 {
556         const VkSurfaceCapabilitiesKHR          capabilities    = getPhysicalDeviceSurfaceCapabilities(vki,
557                                                                                                                                                                                            physicalDevice,
558                                                                                                                                                                                            surface);
559         const vector<VkSurfaceFormatKHR>        formats                 = getPhysicalDeviceSurfaceFormats(vki,
560                                                                                                                                                                                   physicalDevice,
561                                                                                                                                                                                   surface);
562         const vector<VkPresentModeKHR>          presentModes    = getPhysicalDeviceSurfacePresentModes(vki,
563                                                                                                                                                                                            physicalDevice,
564                                                                                                                                                                                            surface);
565
566         return generateSwapchainParameterCases(wsiType, dimension, capabilities, formats, presentModes);
567 }
568
569 tcu::TestStatus createSwapchainTest (Context& context, TestParameters params)
570 {
571         tcu::TestLog&                                                   log                     = context.getTestContext().getLog();
572         const InstanceHelper                                    instHelper      (context, params.wsiType);
573         const NativeObjects                                             native          (context, instHelper.supportedExtensions, params.wsiType);
574         const Unique<VkSurfaceKHR>                              surface         (createSurface(instHelper.vki, *instHelper.instance, params.wsiType, *native.display, *native.window));
575         const DeviceHelper                                              devHelper       (context, instHelper.vki, *instHelper.instance, *surface);
576         const vector<VkSwapchainCreateInfoKHR>  cases           (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
577
578         for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
579         {
580                 std::ostringstream subcase;
581                 subcase << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": ";
582
583                 VkSwapchainCreateInfoKHR        curParams       = cases[caseNdx];
584
585                 curParams.surface                               = *surface;
586                 curParams.queueFamilyIndexCount = 1u;
587                 curParams.pQueueFamilyIndices   = &devHelper.queueFamilyIndex;
588
589                 log << TestLog::Message << subcase.str() << curParams << TestLog::EndMessage;
590
591                 // The Vulkan 1.1.87 spec contains the following VU for VkSwapchainCreateInfoKHR:
592                 //
593                 //     * imageFormat, imageUsage, imageExtent, and imageArrayLayers must be supported for VK_IMAGE_TYPE_2D
594                 //     VK_IMAGE_TILING_OPTIMAL images as reported by vkGetPhysicalDeviceImageFormatProperties.
595                 VkImageFormatProperties properties;
596                 const VkResult propertiesResult = instHelper.vki.getPhysicalDeviceImageFormatProperties(devHelper.physicalDevice,
597                                                                                                                                                                                                 curParams.imageFormat,
598                                                                                                                                                                                                 VK_IMAGE_TYPE_2D,
599                                                                                                                                                                                                 VK_IMAGE_TILING_OPTIMAL,
600                                                                                                                                                                                                 curParams.imageUsage,
601                                                                                                                                                                                                 0, // flags
602                                                                                                                                                                                                 &properties);
603
604                 log << TestLog::Message << subcase.str()
605                         << "vkGetPhysicalDeviceImageFormatProperties => "
606                         << getResultStr(propertiesResult) << TestLog::EndMessage;
607
608                 switch (propertiesResult) {
609                 case VK_SUCCESS:
610                         {
611                                 const Unique<VkSwapchainKHR>    swapchain       (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams));
612                         }
613                         log << TestLog::Message << subcase.str()
614                                 << "Creating swapchain succeeeded" << TestLog::EndMessage;
615                         break;
616                 case VK_ERROR_FORMAT_NOT_SUPPORTED:
617                         log << TestLog::Message << subcase.str()
618                                 << "Skip because vkGetPhysicalDeviceImageFormatProperties returned VK_ERROR_FORMAT_NOT_SUPPORTED" << TestLog::EndMessage;
619                         break;
620                 default:
621                         log << TestLog::Message << subcase.str()
622                                 << "Fail because vkGetPhysicalDeviceImageFormatProperties returned "
623                                 << getResultStr(propertiesResult) << TestLog::EndMessage;
624                         return tcu::TestStatus::fail("Unexpected result from vkGetPhysicalDeviceImageFormatProperties");
625                 }
626         }
627
628         return tcu::TestStatus::pass("No sub-case failed");
629 }
630
631 tcu::TestStatus createSwapchainSimulateOOMTest (Context& context, TestParameters params)
632 {
633         const size_t                            maxCases                        = 300u;
634         const deUint32                          maxAllocs                       = 1024u;
635
636         tcu::TestLog&                           log                                     = context.getTestContext().getLog();
637         tcu::ResultCollector            results                         (log);
638
639         AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
640         DeterministicFailAllocator      failingAllocator        (allocationRecorder.getCallbacks(),
641                                                                                                          DeterministicFailAllocator::MODE_DO_NOT_COUNT,
642                                                                                                          0);
643         {
644                 const InstanceHelper                                    instHelper      (context, params.wsiType, failingAllocator.getCallbacks());
645                 const NativeObjects                                             native          (context, instHelper.supportedExtensions, params.wsiType);
646                 const Unique<VkSurfaceKHR>                              surface         (createSurface(instHelper.vki,
647                                                                                                                                                         *instHelper.instance,
648                                                                                                                                                         params.wsiType,
649                                                                                                                                                         *native.display,
650                                                                                                                                                         *native.window,
651                                                                                                                                                         failingAllocator.getCallbacks()));
652                 const DeviceHelper                                              devHelper       (context, instHelper.vki, *instHelper.instance, *surface, failingAllocator.getCallbacks());
653                 const vector<VkSwapchainCreateInfoKHR>  allCases        (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
654
655                 if (maxCases < allCases.size())
656                         log << TestLog::Message << "Note: Will only test first " << maxCases << " cases out of total of " << allCases.size() << " parameter combinations" << TestLog::EndMessage;
657
658                 for (size_t caseNdx = 0; caseNdx < de::min(maxCases, allCases.size()); ++caseNdx)
659                 {
660                         log << TestLog::Message << "Testing parameter case " << caseNdx << ": " << allCases[caseNdx] << TestLog::EndMessage;
661
662                         for (deUint32 numPassingAllocs = 0; numPassingAllocs <= maxAllocs; ++numPassingAllocs)
663                         {
664                                 bool    gotOOM  = false;
665
666                                 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
667
668                                 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
669
670                                 try
671                                 {
672                                         VkSwapchainCreateInfoKHR        curParams       = allCases[caseNdx];
673
674                                         curParams.surface                               = *surface;
675                                         curParams.queueFamilyIndexCount = 1u;
676                                         curParams.pQueueFamilyIndices   = &devHelper.queueFamilyIndex;
677
678                                         {
679                                                 const Unique<VkSwapchainKHR>    swapchain       (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks()));
680                                         }
681                                 }
682                                 catch (const OutOfMemoryError& e)
683                                 {
684                                         log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
685                                         gotOOM = true;
686                                 }
687
688                                 if (!gotOOM)
689                                 {
690                                         log << TestLog::Message << "Creating swapchain succeeded!" << TestLog::EndMessage;
691
692                                         if (numPassingAllocs == 0)
693                                                 results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
694
695                                         break;
696                                 }
697                                 else if (numPassingAllocs == maxAllocs)
698                                         results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded");
699                         }
700
701                         context.getTestContext().touchWatchdog();
702                 }
703         }
704
705         if (!validateAndLog(log, allocationRecorder, 0u))
706                 results.fail("Detected invalid system allocation callback");
707
708         return tcu::TestStatus(results.getResult(), results.getMessage());
709 }
710
711 struct GroupParameters
712 {
713         typedef FunctionInstance1<TestParameters>::Function     Function;
714
715         Type            wsiType;
716         Function        function;
717
718         GroupParameters (Type wsiType_, Function function_)
719                 : wsiType       (wsiType_)
720                 , function      (function_)
721         {}
722
723         GroupParameters (void)
724                 : wsiType       (TYPE_LAST)
725                 , function      ((Function)DE_NULL)
726         {}
727 };
728
729 void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters params)
730 {
731         for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
732         {
733                 const TestDimension             testDimension   = (TestDimension)dimensionNdx;
734
735                 addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension));
736         }
737 }
738
739 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type                                              wsiType,
740                                                                                                           const InstanceInterface&      vki,
741                                                                                                           VkPhysicalDevice                      physicalDevice,
742                                                                                                           VkSurfaceKHR                          surface,
743                                                                                                           const tcu::UVec2&                     desiredSize,
744                                                                                                           deUint32                                      desiredImageCount)
745 {
746         const VkSurfaceCapabilitiesKHR          capabilities            = getPhysicalDeviceSurfaceCapabilities(vki,
747                                                                                                                                                                                                    physicalDevice,
748                                                                                                                                                                                                    surface);
749         const vector<VkSurfaceFormatKHR>        formats                         = getPhysicalDeviceSurfaceFormats(vki,
750                                                                                                                                                                                           physicalDevice,
751                                                                                                                                                                                           surface);
752         const PlatformProperties&                       platformProperties      = getPlatformProperties(wsiType);
753         const VkSurfaceTransformFlagBitsKHR transform                   = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
754         const VkSwapchainCreateInfoKHR          parameters                      =
755         {
756                 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
757                 DE_NULL,
758                 (VkSwapchainCreateFlagsKHR)0,
759                 surface,
760                 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
761                 formats[0].format,
762                 formats[0].colorSpace,
763                 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
764                         ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
765                 1u,                                                                     // imageArrayLayers
766                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
767                 VK_SHARING_MODE_EXCLUSIVE,
768                 0u,
769                 (const deUint32*)DE_NULL,
770                 transform,
771                 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
772                 VK_PRESENT_MODE_FIFO_KHR,
773                 VK_FALSE,                                                       // clipped
774                 (VkSwapchainKHR)0                                       // oldSwapchain
775         };
776
777         return parameters;
778 }
779
780 typedef de::SharedPtr<Unique<VkImageView> >             ImageViewSp;
781 typedef de::SharedPtr<Unique<VkFramebuffer> >   FramebufferSp;
782
783 class TriangleRenderer
784 {
785 public:
786                                                                         TriangleRenderer        (const DeviceInterface&         vkd,
787                                                                                                                  const VkDevice                         device,
788                                                                                                                  Allocator&                                     allocator,
789                                                                                                                  const BinaryCollection&        binaryRegistry,
790                                                                                                                  const vector<VkImage>          swapchainImages,
791                                                                                                                  const VkFormat                         framebufferFormat,
792                                                                                                                  const UVec2&                           renderSize);
793                                                                         ~TriangleRenderer       (void);
794
795         void                                                    recordFrame                     (VkCommandBuffer                        cmdBuffer,
796                                                                                                                  deUint32                                       imageNdx,
797                                                                                                                  deUint32                                       frameNdx) const;
798
799         static void                                             getPrograms                     (SourceCollections& dst);
800
801 private:
802         static Move<VkRenderPass>               createRenderPass        (const DeviceInterface&         vkd,
803                                                                                                                  const VkDevice                         device,
804                                                                                                                  const VkFormat                         colorAttachmentFormat);
805         static Move<VkPipelineLayout>   createPipelineLayout(const DeviceInterface&             vkd,
806                                                                                                                  VkDevice                                       device);
807         static Move<VkPipeline>                 createPipeline          (const DeviceInterface&         vkd,
808                                                                                                                  const VkDevice                         device,
809                                                                                                                  const VkRenderPass                     renderPass,
810                                                                                                                  const VkPipelineLayout         pipelineLayout,
811                                                                                                                  const BinaryCollection&        binaryCollection,
812                                                                                                                  const UVec2&                           renderSize);
813
814         static Move<VkImageView>                createAttachmentView(const DeviceInterface&             vkd,
815                                                                                                                  const VkDevice                         device,
816                                                                                                                  const VkImage                          image,
817                                                                                                                  const VkFormat                         format);
818         static Move<VkFramebuffer>              createFramebuffer       (const DeviceInterface&         vkd,
819                                                                                                                  const VkDevice                         device,
820                                                                                                                  const VkRenderPass                     renderPass,
821                                                                                                                  const VkImageView                      colorAttachment,
822                                                                                                                  const UVec2&                           renderSize);
823
824         static Move<VkBuffer>                   createBuffer            (const DeviceInterface&         vkd,
825                                                                                                                  VkDevice                                       device,
826                                                                                                                  VkDeviceSize                           size,
827                                                                                                                  VkBufferUsageFlags                     usage);
828
829         const DeviceInterface&                  m_vkd;
830
831         const vector<VkImage>                   m_swapchainImages;
832         const tcu::UVec2                                m_renderSize;
833
834         const Unique<VkRenderPass>              m_renderPass;
835         const Unique<VkPipelineLayout>  m_pipelineLayout;
836         const Unique<VkPipeline>                m_pipeline;
837
838         const Unique<VkBuffer>                  m_vertexBuffer;
839         const UniquePtr<Allocation>             m_vertexBufferMemory;
840
841         vector<ImageViewSp>                             m_attachmentViews;
842         vector<FramebufferSp>                   m_framebuffers;
843 };
844
845 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface&   vkd,
846                                                                                                            const VkDevice                       device,
847                                                                                                            const VkFormat                       colorAttachmentFormat)
848 {
849         const VkAttachmentDescription   colorAttDesc            =
850         {
851                 (VkAttachmentDescriptionFlags)0,
852                 colorAttachmentFormat,
853                 VK_SAMPLE_COUNT_1_BIT,
854                 VK_ATTACHMENT_LOAD_OP_CLEAR,
855                 VK_ATTACHMENT_STORE_OP_STORE,
856                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
857                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
858                 VK_IMAGE_LAYOUT_UNDEFINED,
859                 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
860         };
861         const VkAttachmentReference             colorAttRef                     =
862         {
863                 0u,
864                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
865         };
866         const VkSubpassDescription              subpassDesc                     =
867         {
868                 (VkSubpassDescriptionFlags)0u,
869                 VK_PIPELINE_BIND_POINT_GRAPHICS,
870                 0u,                                                     // inputAttachmentCount
871                 DE_NULL,                                        // pInputAttachments
872                 1u,                                                     // colorAttachmentCount
873                 &colorAttRef,                           // pColorAttachments
874                 DE_NULL,                                        // pResolveAttachments
875                 DE_NULL,                                        // depthStencilAttachment
876                 0u,                                                     // preserveAttachmentCount
877                 DE_NULL,                                        // pPreserveAttachments
878         };
879         const VkSubpassDependency               dependencies[]          =
880         {
881                 {
882                         VK_SUBPASS_EXTERNAL,    // srcSubpass
883                         0u,                                             // dstSubpass
884                         VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
885                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
886                         VK_ACCESS_MEMORY_READ_BIT,
887                         (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
888                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
889                         VK_DEPENDENCY_BY_REGION_BIT
890                 },
891                 {
892                         0u,                                             // srcSubpass
893                         VK_SUBPASS_EXTERNAL,    // dstSubpass
894                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
895                         VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
896                         (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
897                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
898                         VK_ACCESS_MEMORY_READ_BIT,
899                         VK_DEPENDENCY_BY_REGION_BIT
900                 },
901         };
902         const VkRenderPassCreateInfo    renderPassParams        =
903         {
904                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
905                 DE_NULL,
906                 (VkRenderPassCreateFlags)0,
907                 1u,
908                 &colorAttDesc,
909                 1u,
910                 &subpassDesc,
911                 DE_LENGTH_OF_ARRAY(dependencies),
912                 dependencies,
913         };
914
915         return vk::createRenderPass(vkd, device, &renderPassParams);
916 }
917
918 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface&   vkd,
919                                                                                                                            const VkDevice                       device)
920 {
921         const VkPushConstantRange                                               pushConstantRange               =
922         {
923                 VK_SHADER_STAGE_VERTEX_BIT,
924                 0u,                                                                                     // offset
925                 (deUint32)sizeof(deUint32),                                     // size
926         };
927         const VkPipelineLayoutCreateInfo                                pipelineLayoutParams    =
928         {
929                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
930                 DE_NULL,
931                 (vk::VkPipelineLayoutCreateFlags)0,
932                 0u,                                                                                     // setLayoutCount
933                 DE_NULL,                                                                        // pSetLayouts
934                 1u,
935                 &pushConstantRange,
936         };
937
938         return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
939 }
940
941 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface&       vkd,
942                                                                                                    const VkDevice                       device,
943                                                                                                    const VkRenderPass           renderPass,
944                                                                                                    const VkPipelineLayout       pipelineLayout,
945                                                                                                    const BinaryCollection&      binaryCollection,
946                                                                                                    const UVec2&                         renderSize)
947 {
948         // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
949         //               and can be deleted immediately following that call.
950         const Unique<VkShaderModule>                                    vertShaderModule                (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
951         const Unique<VkShaderModule>                                    fragShaderModule                (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
952         const std::vector<VkViewport>                                   viewports                               (1, makeViewport(renderSize));
953         const std::vector<VkRect2D>                                             scissors                                (1, makeRect2D(renderSize));
954
955         return vk::makeGraphicsPipeline(vkd,                            // const DeviceInterface&            vk
956                                                                         device,                         // const VkDevice                    device
957                                                                         pipelineLayout,         // const VkPipelineLayout            pipelineLayout
958                                                                         *vertShaderModule,      // const VkShaderModule              vertexShaderModule
959                                                                         DE_NULL,                        // const VkShaderModule              tessellationControlShaderModule
960                                                                         DE_NULL,                        // const VkShaderModule              tessellationEvalShaderModule
961                                                                         DE_NULL,                        // const VkShaderModule              geometryShaderModule
962                                                                         *fragShaderModule,      // const VkShaderModule              fragmentShaderModule
963                                                                         renderPass,                     // const VkRenderPass                renderPass
964                                                                         viewports,                      // const std::vector<VkViewport>&    viewports
965                                                                         scissors);                      // const std::vector<VkRect2D>&      scissors
966 }
967
968 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface&        vkd,
969                                                                                                                   const VkDevice                        device,
970                                                                                                                   const VkImage                         image,
971                                                                                                                   const VkFormat                        format)
972 {
973         const VkImageViewCreateInfo             viewParams      =
974         {
975                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
976                 DE_NULL,
977                 (VkImageViewCreateFlags)0,
978                 image,
979                 VK_IMAGE_VIEW_TYPE_2D,
980                 format,
981                 vk::makeComponentMappingRGBA(),
982                 {
983                         VK_IMAGE_ASPECT_COLOR_BIT,
984                         0u,                                             // baseMipLevel
985                         1u,                                             // levelCount
986                         0u,                                             // baseArrayLayer
987                         1u,                                             // layerCount
988                 },
989         };
990
991         return vk::createImageView(vkd, device, &viewParams);
992 }
993
994 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface&         vkd,
995                                                                                                                  const VkDevice                         device,
996                                                                                                                  const VkRenderPass                     renderPass,
997                                                                                                                  const VkImageView                      colorAttachment,
998                                                                                                                  const UVec2&                           renderSize)
999 {
1000         const VkFramebufferCreateInfo   framebufferParams       =
1001         {
1002                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1003                 DE_NULL,
1004                 (VkFramebufferCreateFlags)0,
1005                 renderPass,
1006                 1u,
1007                 &colorAttachment,
1008                 renderSize.x(),
1009                 renderSize.y(),
1010                 1u,                                                     // layers
1011         };
1012
1013         return vk::createFramebuffer(vkd, device, &framebufferParams);
1014 }
1015
1016 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface&   vkd,
1017                                                                                            VkDevice                                     device,
1018                                                                                            VkDeviceSize                         size,
1019                                                                                            VkBufferUsageFlags           usage)
1020 {
1021         const VkBufferCreateInfo        bufferParams    =
1022         {
1023                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1024                 DE_NULL,
1025                 (VkBufferCreateFlags)0,
1026                 size,
1027                 usage,
1028                 VK_SHARING_MODE_EXCLUSIVE,
1029                 0,
1030                 DE_NULL
1031         };
1032
1033         return vk::createBuffer(vkd, device, &bufferParams);
1034 }
1035
1036 TriangleRenderer::TriangleRenderer (const DeviceInterface&      vkd,
1037                                                                         const VkDevice                  device,
1038                                                                         Allocator&                              allocator,
1039                                                                         const BinaryCollection& binaryRegistry,
1040                                                                         const vector<VkImage>   swapchainImages,
1041                                                                         const VkFormat                  framebufferFormat,
1042                                                                         const UVec2&                    renderSize)
1043         : m_vkd                                 (vkd)
1044         , m_swapchainImages             (swapchainImages)
1045         , m_renderSize                  (renderSize)
1046         , m_renderPass                  (createRenderPass(vkd, device, framebufferFormat))
1047         , m_pipelineLayout              (createPipelineLayout(vkd, device))
1048         , m_pipeline                    (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
1049         , m_vertexBuffer                (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1050         , m_vertexBufferMemory  (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
1051                                                          MemoryRequirement::HostVisible))
1052 {
1053         m_attachmentViews.resize(swapchainImages.size());
1054         m_framebuffers.resize(swapchainImages.size());
1055
1056         for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
1057         {
1058                 m_attachmentViews[imageNdx]     = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
1059                 m_framebuffers[imageNdx]        = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
1060         }
1061
1062         VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
1063
1064         {
1065                 const VkMappedMemoryRange       memRange        =
1066                 {
1067                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1068                         DE_NULL,
1069                         m_vertexBufferMemory->getMemory(),
1070                         m_vertexBufferMemory->getOffset(),
1071                         VK_WHOLE_SIZE
1072                 };
1073                 const tcu::Vec4                         vertices[]      =
1074                 {
1075                         tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
1076                         tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
1077                         tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
1078                 };
1079                 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
1080
1081                 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
1082                 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
1083         }
1084 }
1085
1086 TriangleRenderer::~TriangleRenderer (void)
1087 {
1088 }
1089
1090 void TriangleRenderer::recordFrame (VkCommandBuffer     cmdBuffer,
1091                                                                         deUint32                imageNdx,
1092                                                                         deUint32                frameNdx) const
1093 {
1094         const VkFramebuffer     curFramebuffer  = **m_framebuffers[imageNdx];
1095
1096         beginCommandBuffer(m_vkd, cmdBuffer, 0u);
1097
1098         beginRenderPass(m_vkd, cmdBuffer, *m_renderPass, curFramebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.125f, 0.25f, 0.75f, 1.0f));
1099
1100         m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1101
1102         {
1103                 const VkDeviceSize bindingOffset = 0;
1104                 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
1105         }
1106
1107         m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
1108         m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1109         endRenderPass(m_vkd, cmdBuffer);
1110
1111         endCommandBuffer(m_vkd, cmdBuffer);
1112 }
1113
1114 void TriangleRenderer::getPrograms (SourceCollections& dst)
1115 {
1116         dst.glslSources.add("tri-vert") << glu::VertexSource(
1117                 "#version 310 es\n"
1118                 "layout(location = 0) in highp vec4 a_position;\n"
1119                 "layout(push_constant) uniform FrameData\n"
1120                 "{\n"
1121                 "    highp uint frameNdx;\n"
1122                 "} frameData;\n"
1123                 "void main (void)\n"
1124                 "{\n"
1125                 "    highp float angle = float(frameData.frameNdx) / 100.0;\n"
1126                 "    highp float c     = cos(angle);\n"
1127                 "    highp float s     = sin(angle);\n"
1128                 "    highp mat4  t     = mat4( c, -s,  0,  0,\n"
1129                 "                              s,  c,  0,  0,\n"
1130                 "                              0,  0,  1,  0,\n"
1131                 "                              0,  0,  0,  1);\n"
1132                 "    gl_Position = t * a_position;\n"
1133                 "}\n");
1134         dst.glslSources.add("tri-frag") << glu::FragmentSource(
1135                 "#version 310 es\n"
1136                 "layout(location = 0) out lowp vec4 o_color;\n"
1137                 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
1138 }
1139
1140 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
1141 typedef de::SharedPtr<Unique<VkFence> >                 FenceSp;
1142 typedef de::SharedPtr<Unique<VkSemaphore> >             SemaphoreSp;
1143
1144 vector<FenceSp> createFences (const DeviceInterface&    vkd,
1145                                                           const VkDevice                        device,
1146                                                           size_t                                        numFences)
1147 {
1148         vector<FenceSp> fences(numFences);
1149
1150         for (size_t ndx = 0; ndx < numFences; ++ndx)
1151                 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
1152
1153         return fences;
1154 }
1155
1156 vector<SemaphoreSp> createSemaphores (const DeviceInterface&    vkd,
1157                                                                           const VkDevice                        device,
1158                                                                           size_t                                        numSemaphores)
1159 {
1160         vector<SemaphoreSp> semaphores(numSemaphores);
1161
1162         for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
1163                 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
1164
1165         return semaphores;
1166 }
1167
1168 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&          vkd,
1169                                                                                                 const VkDevice                          device,
1170                                                                                                 const VkCommandPool                     commandPool,
1171                                                                                                 const VkCommandBufferLevel      level,
1172                                                                                                 const size_t                            numCommandBuffers)
1173 {
1174         vector<CommandBufferSp>                         buffers         (numCommandBuffers);
1175
1176         for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
1177                 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
1178
1179         return buffers;
1180 }
1181
1182 tcu::TestStatus basicRenderTest (Context& context, Type wsiType)
1183 {
1184         const tcu::UVec2                                desiredSize                                     (256, 256);
1185         const InstanceHelper                    instHelper                                      (context, wsiType);
1186         const NativeObjects                             native                                          (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
1187         const Unique<VkSurfaceKHR>              surface                                         (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1188         const DeviceHelper                              devHelper                                       (context, instHelper.vki, *instHelper.instance, *surface);
1189         const DeviceInterface&                  vkd                                                     = devHelper.vkd;
1190         const VkDevice                                  device                                          = *devHelper.device;
1191         SimpleAllocator                                 allocator                                       (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1192         const VkSwapchainCreateInfoKHR  swapchainInfo                           = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
1193         const Unique<VkSwapchainKHR>    swapchain                                       (createSwapchainKHR(vkd, device, &swapchainInfo));
1194         const vector<VkImage>                   swapchainImages                         = getSwapchainImages(vkd, device, *swapchain);
1195
1196         const TriangleRenderer                  renderer                                        (vkd,
1197                                                                                                                                  device,
1198                                                                                                                                  allocator,
1199                                                                                                                                  context.getBinaryCollection(),
1200                                                                                                                                  swapchainImages,
1201                                                                                                                                  swapchainInfo.imageFormat,
1202                                                                                                                                  tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1203
1204         const Unique<VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1205
1206         const size_t                                    maxQueuedFrames                         = swapchainImages.size()*2;
1207
1208         // We need to keep hold of fences from vkAcquireNextImageKHR to actually
1209         // limit number of frames we allow to be queued.
1210         const vector<FenceSp>                   imageReadyFences                        (createFences(vkd, device, maxQueuedFrames));
1211
1212         // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
1213         // the semaphore in same time as the fence we use to meter rendering.
1214         const vector<SemaphoreSp>               imageReadySemaphores            (createSemaphores(vkd, device, maxQueuedFrames+1));
1215
1216         // For rest we simply need maxQueuedFrames as we will wait for image
1217         // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
1218         // previous uses must have completed.
1219         const vector<SemaphoreSp>               renderingCompleteSemaphores     (createSemaphores(vkd, device, maxQueuedFrames));
1220         const vector<CommandBufferSp>   commandBuffers                          (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1221
1222         try
1223         {
1224                 const deUint32  numFramesToRender       = 60*10;
1225
1226                 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1227                 {
1228                         const VkFence           imageReadyFence         = **imageReadyFences[frameNdx%imageReadyFences.size()];
1229                         const VkSemaphore       imageReadySemaphore     = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1230                         deUint32                        imageNdx                        = ~0u;
1231
1232                         if (frameNdx >= maxQueuedFrames)
1233                                 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1234
1235                         VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
1236
1237                         {
1238                                 const VkResult  acquireResult   = vkd.acquireNextImageKHR(device,
1239                                                                                                                                                   *swapchain,
1240                                                                                                                                                   std::numeric_limits<deUint64>::max(),
1241                                                                                                                                                   imageReadySemaphore,
1242                                                                                                                                                   (VkFence)0,
1243                                                                                                                                                   &imageNdx);
1244
1245                                 if (acquireResult == VK_SUBOPTIMAL_KHR)
1246                                         context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1247                                 else
1248                                         VK_CHECK(acquireResult);
1249                         }
1250
1251                         TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1252
1253                         {
1254                                 const VkSemaphore                       renderingCompleteSemaphore      = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1255                                 const VkCommandBuffer           commandBuffer                           = **commandBuffers[frameNdx%commandBuffers.size()];
1256                                 const VkPipelineStageFlags      waitDstStage                            = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1257                                 const VkSubmitInfo                      submitInfo                                      =
1258                                 {
1259                                         VK_STRUCTURE_TYPE_SUBMIT_INFO,
1260                                         DE_NULL,
1261                                         1u,
1262                                         &imageReadySemaphore,
1263                                         &waitDstStage,
1264                                         1u,
1265                                         &commandBuffer,
1266                                         1u,
1267                                         &renderingCompleteSemaphore
1268                                 };
1269                                 const VkPresentInfoKHR          presentInfo                                     =
1270                                 {
1271                                         VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1272                                         DE_NULL,
1273                                         1u,
1274                                         &renderingCompleteSemaphore,
1275                                         1u,
1276                                         &*swapchain,
1277                                         &imageNdx,
1278                                         (VkResult*)DE_NULL
1279                                 };
1280
1281                                 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
1282                                 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
1283                                 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1284                         }
1285                 }
1286
1287                 VK_CHECK(vkd.deviceWaitIdle(device));
1288         }
1289         catch (...)
1290         {
1291                 // Make sure device is idle before destroying resources
1292                 vkd.deviceWaitIdle(device);
1293                 throw;
1294         }
1295
1296         return tcu::TestStatus::pass("Rendering tests succeeded");
1297 }
1298
1299 vector<tcu::UVec2> getSwapchainSizeSequence (const VkSurfaceCapabilitiesKHR& capabilities, const tcu::UVec2& defaultSize)
1300 {
1301         vector<tcu::UVec2> sizes(3);
1302         sizes[0] = defaultSize / 2u;
1303         sizes[1] = defaultSize;
1304         sizes[2] = defaultSize * 2u;
1305
1306         for (deUint32 i = 0; i < sizes.size(); ++i)
1307         {
1308                 sizes[i].x() = de::clamp(sizes[i].x(), capabilities.minImageExtent.width,  capabilities.maxImageExtent.width);
1309                 sizes[i].y() = de::clamp(sizes[i].y(), capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
1310         }
1311
1312         return sizes;
1313 }
1314
1315 tcu::TestStatus resizeSwapchainTest (Context& context, Type wsiType)
1316 {
1317         const tcu::UVec2                                desiredSize                     (256, 256);
1318         const InstanceHelper                    instHelper                      (context, wsiType);
1319         const NativeObjects                             native                          (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
1320         const Unique<VkSurfaceKHR>              surface                         (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1321         const DeviceHelper                              devHelper                       (context, instHelper.vki, *instHelper.instance, *surface);
1322         const PlatformProperties&               platformProperties      = getPlatformProperties(wsiType);
1323         const VkSurfaceCapabilitiesKHR  capabilities            = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface);
1324         const DeviceInterface&                  vkd                                     = devHelper.vkd;
1325         const VkDevice                                  device                          = *devHelper.device;
1326         SimpleAllocator                                 allocator                       (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1327         vector<tcu::UVec2>                              sizes                           = getSwapchainSizeSequence(capabilities, desiredSize);
1328         Move<VkSwapchainKHR>                    prevSwapchain;
1329
1330         DE_ASSERT(platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE);
1331         DE_UNREF(platformProperties);
1332
1333         for (deUint32 sizeNdx = 0; sizeNdx < sizes.size(); ++sizeNdx)
1334         {
1335                 // \todo [2016-05-30 jesse] This test currently waits for idle and
1336                 // recreates way more than necessary when recreating the swapchain. Make
1337                 // it match expected real app behavior better by smoothly switching from
1338                 // old to new swapchain. Once that is done, it will also be possible to
1339                 // test creating a new swapchain while images from the previous one are
1340                 // still acquired.
1341
1342                 VkSwapchainCreateInfoKHR                swapchainInfo                           = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, sizes[sizeNdx], 2);
1343                 swapchainInfo.oldSwapchain = *prevSwapchain;
1344
1345                 Move<VkSwapchainKHR>                    swapchain                                       (createSwapchainKHR(vkd, device, &swapchainInfo));
1346                 const vector<VkImage>                   swapchainImages                         = getSwapchainImages(vkd, device, *swapchain);
1347                 const TriangleRenderer                  renderer                                        (vkd,
1348                                                                                                                                         device,
1349                                                                                                                                         allocator,
1350                                                                                                                                         context.getBinaryCollection(),
1351                                                                                                                                         swapchainImages,
1352                                                                                                                                         swapchainInfo.imageFormat,
1353                                                                                                                                         tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1354                 const Unique<VkCommandPool>             commandPool                                     (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1355                 const size_t                                    maxQueuedFrames                         = swapchainImages.size()*2;
1356
1357                 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
1358                 // limit number of frames we allow to be queued.
1359                 const vector<FenceSp>                   imageReadyFences                        (createFences(vkd, device, maxQueuedFrames));
1360
1361                 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
1362                 // the semaphore in same time as the fence we use to meter rendering.
1363                 const vector<SemaphoreSp>               imageReadySemaphores            (createSemaphores(vkd, device, maxQueuedFrames+1));
1364
1365                 // For rest we simply need maxQueuedFrames as we will wait for image
1366                 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
1367                 // previous uses must have completed.
1368                 const vector<SemaphoreSp>               renderingCompleteSemaphores     (createSemaphores(vkd, device, maxQueuedFrames));
1369                 const vector<CommandBufferSp>   commandBuffers                          (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1370
1371                 try
1372                 {
1373                         const deUint32  numFramesToRender       = 60;
1374
1375                         for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1376                         {
1377                                 const VkFence           imageReadyFence         = **imageReadyFences[frameNdx%imageReadyFences.size()];
1378                                 const VkSemaphore       imageReadySemaphore     = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1379                                 deUint32                        imageNdx                        = ~0u;
1380
1381                                 if (frameNdx >= maxQueuedFrames)
1382                                         VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1383
1384                                 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
1385
1386                                 {
1387                                         const VkResult  acquireResult   = vkd.acquireNextImageKHR(device,
1388                                                                                                                                                           *swapchain,
1389                                                                                                                                                           std::numeric_limits<deUint64>::max(),
1390                                                                                                                                                           imageReadySemaphore,
1391                                                                                                                                                           imageReadyFence,
1392                                                                                                                                                           &imageNdx);
1393
1394                                         if (acquireResult == VK_SUBOPTIMAL_KHR)
1395                                                 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1396                                         else
1397                                                 VK_CHECK(acquireResult);
1398                                 }
1399
1400                                 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1401
1402                                 {
1403                                         const VkSemaphore                       renderingCompleteSemaphore      = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1404                                         const VkCommandBuffer           commandBuffer                           = **commandBuffers[frameNdx%commandBuffers.size()];
1405                                         const VkPipelineStageFlags      waitDstStage                            = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1406                                         const VkSubmitInfo                      submitInfo                                      =
1407                                         {
1408                                                 VK_STRUCTURE_TYPE_SUBMIT_INFO,
1409                                                 DE_NULL,
1410                                                 1u,
1411                                                 &imageReadySemaphore,
1412                                                 &waitDstStage,
1413                                                 1u,
1414                                                 &commandBuffer,
1415                                                 1u,
1416                                                 &renderingCompleteSemaphore
1417                                         };
1418                                         const VkPresentInfoKHR          presentInfo                                     =
1419                                         {
1420                                                 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1421                                                 DE_NULL,
1422                                                 1u,
1423                                                 &renderingCompleteSemaphore,
1424                                                 1u,
1425                                                 &*swapchain,
1426                                                 &imageNdx,
1427                                                 (VkResult*)DE_NULL
1428                                         };
1429
1430                                         renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
1431                                         VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, (VkFence)0));
1432                                         VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1433                                 }
1434                         }
1435
1436                         VK_CHECK(vkd.deviceWaitIdle(device));
1437
1438                         prevSwapchain = swapchain;
1439                 }
1440                 catch (...)
1441                 {
1442                         // Make sure device is idle before destroying resources
1443                         vkd.deviceWaitIdle(device);
1444                         throw;
1445                 }
1446         }
1447
1448         return tcu::TestStatus::pass("Resizing tests succeeded");
1449 }
1450
1451 tcu::TestStatus getImagesIncompleteResultTest (Context& context, Type wsiType)
1452 {
1453         const tcu::UVec2                                desiredSize             (256, 256);
1454         const InstanceHelper                    instHelper              (context, wsiType);
1455         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
1456         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1457         const DeviceHelper                              devHelper               (context, instHelper.vki, *instHelper.instance, *surface);
1458         const VkSwapchainCreateInfoKHR  swapchainInfo   = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
1459         const Unique<VkSwapchainKHR>    swapchain               (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
1460
1461         vector<VkImage>         swapchainImages = getSwapchainImages(devHelper.vkd, *devHelper.device, *swapchain);
1462
1463         ValidateQueryBits::fillBits(swapchainImages.begin(), swapchainImages.end());
1464
1465         const deUint32          usedCount               = static_cast<deUint32>(swapchainImages.size() / 2);
1466         deUint32                        count                   = usedCount;
1467         const VkResult          result                  = devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &count, &swapchainImages[0]);
1468
1469         if (count != usedCount || result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(swapchainImages.begin() + count, swapchainImages.end()))
1470                 return tcu::TestStatus::fail("Get swapchain images didn't return VK_INCOMPLETE");
1471         else
1472                 return tcu::TestStatus::pass("Get swapchain images tests succeeded");
1473 }
1474
1475 tcu::TestStatus destroyNullHandleSwapchainTest (Context& context, Type wsiType)
1476 {
1477         const InstanceHelper            instHelper      (context, wsiType);
1478         const NativeObjects                     native          (context, instHelper.supportedExtensions, wsiType);
1479         const Unique<VkSurfaceKHR>      surface         (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1480         const DeviceHelper                      devHelper       (context, instHelper.vki, *instHelper.instance, *surface);
1481         const VkSwapchainKHR            nullHandle      = DE_NULL;
1482
1483         // Default allocator
1484         devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, DE_NULL);
1485
1486         // Custom allocator
1487         {
1488                 AllocationCallbackRecorder      recordingAllocator      (getSystemAllocator(), 1u);
1489
1490                 devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, recordingAllocator.getCallbacks());
1491
1492                 if (recordingAllocator.getNumRecords() != 0u)
1493                         return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1494         }
1495
1496         return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1497 }
1498
1499 void getBasicRenderPrograms (SourceCollections& dst, Type)
1500 {
1501         TriangleRenderer::getPrograms(dst);
1502 }
1503
1504 void populateRenderGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
1505 {
1506         addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest, wsiType);
1507 }
1508
1509 void populateGetImagesGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
1510 {
1511         addFunctionCase(testGroup, "incomplete", "Test VK_INCOMPLETE return code", getImagesIncompleteResultTest, wsiType);
1512 }
1513
1514 void populateModifyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
1515 {
1516         const PlatformProperties&       platformProperties      = getPlatformProperties(wsiType);
1517
1518         if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
1519         {
1520                 addFunctionCaseWithPrograms(testGroup, "resize", "Resize Swapchain Test", getBasicRenderPrograms, resizeSwapchainTest, wsiType);
1521         }
1522
1523         // \todo [2016-05-30 jesse] Add tests for modifying preTransform, compositeAlpha, presentMode
1524 }
1525
1526 void populateDestroyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
1527 {
1528         addFunctionCase(testGroup, "null_handle", "Destroying a VK_NULL_HANDLE swapchain", destroyNullHandleSwapchainTest, wsiType);
1529 }
1530
1531 } // anonymous
1532
1533 void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1534 {
1535         addTestGroup(testGroup, "create",                       "Create VkSwapchain with various parameters",                                   populateSwapchainGroup,         GroupParameters(wsiType, createSwapchainTest));
1536         addTestGroup(testGroup, "simulate_oom",         "Simulate OOM using callbacks during swapchain construction",   populateSwapchainGroup,         GroupParameters(wsiType, createSwapchainSimulateOOMTest));
1537         addTestGroup(testGroup, "render",                       "Rendering Tests",                                                                                              populateRenderGroup,            wsiType);
1538         addTestGroup(testGroup, "modify",                       "Modify VkSwapchain",                                                                                   populateModifyGroup,            wsiType);
1539         addTestGroup(testGroup, "destroy",                      "Destroy VkSwapchain",                                                                                  populateDestroyGroup,           wsiType);
1540         addTestGroup(testGroup, "get_images",           "Get swapchain images",                                                                                 populateGetImagesGroup,         wsiType);
1541 }
1542
1543 } // wsi
1544 } // vkt