2501d3901e9160a08f8cadcf110a2622bea19c9c
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / wsi / vktWsiSurfaceTests.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 VkSurface Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktWsiSurfaceTests.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 "vkQueryUtil.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuFormatUtil.hpp"
46 #include "tcuPlatform.hpp"
47 #include "tcuResultCollector.hpp"
48 #include "tcuCommandLine.hpp"
49
50 #include "deUniquePtr.hpp"
51 #include "deStringUtil.hpp"
52 #include "deMemory.h"
53
54 namespace vk
55 {
56
57 inline bool operator!= (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
58 {
59         return (a.format != b.format) || (a.colorSpace != b.colorSpace);
60 }
61
62 inline bool operator== (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
63 {
64         return !(a != b);
65 }
66
67 inline bool operator!= (const VkExtent2D& a, const VkExtent2D& b)
68 {
69         return (a.width != b.width) || (a.height != b.height);
70 }
71
72 inline bool operator!= (const VkSurfaceCapabilitiesKHR& a, const VkSurfaceCapabilitiesKHR& b)
73 {
74         return (a.minImageCount                         != b.minImageCount)                             ||
75                    (a.maxImageCount                             != b.maxImageCount)                             ||
76                    (a.currentExtent                             != b.currentExtent)                             ||
77                    (a.minImageExtent                    != b.minImageExtent)                    ||
78                    (a.maxImageExtent                    != b.maxImageExtent)                    ||
79                    (a.maxImageArrayLayers               != b.maxImageArrayLayers)               ||
80                    (a.supportedTransforms               != b.supportedTransforms)               ||
81                    (a.currentTransform                  != b.currentTransform)                  ||
82                    (a.supportedCompositeAlpha   != b.supportedCompositeAlpha)   ||
83                    (a.supportedUsageFlags               != b.supportedUsageFlags);
84 }
85
86 } // vk
87
88 namespace vkt
89 {
90 namespace wsi
91 {
92
93 namespace
94 {
95
96 using namespace vk;
97 using namespace vk::wsi;
98
99 using tcu::TestLog;
100 using tcu::Maybe;
101 using tcu::UVec2;
102
103 using de::MovePtr;
104 using de::UniquePtr;
105
106 using std::string;
107 using std::vector;
108
109 enum
110 {
111         SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC    = 0xffffffff
112 };
113
114 enum
115 {
116         GUARD_SIZE                                                                              = 0x20,                 //!< Number of bytes to check
117         GUARD_VALUE                                                                             = 0xcd,                 //!< Data pattern
118 };
119
120 template<typename T>
121 class CheckIncompleteResult
122 {
123 public:
124         virtual                 ~CheckIncompleteResult  (void) {}
125         virtual void    getResult                               (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, T* data) = 0;
126
127         void operator() (tcu::ResultCollector&          results,
128                                          const InstanceInterface&       vki,
129                                          const VkPhysicalDevice         physDevice,
130                                          const VkSurfaceKHR                     surface,
131                                          const std::size_t                      expectedCompleteSize)
132         {
133                 if (expectedCompleteSize == 0)
134                         return;
135
136                 vector<T>               outputData      (expectedCompleteSize);
137                 const deUint32  usedSize        = static_cast<deUint32>(expectedCompleteSize / 3);
138
139                 ValidateQueryBits::fillBits(outputData.begin(), outputData.end());      // unused entries should have this pattern intact
140                 m_count         = usedSize;
141                 m_result        = VK_SUCCESS;
142
143                 getResult(vki, physDevice, surface, &outputData[0]);                            // update m_count and m_result
144
145                 if (m_count != usedSize || m_result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
146                         results.fail("Query didn't return VK_INCOMPLETE");
147         }
148
149 protected:
150         deUint32        m_count;
151         VkResult        m_result;
152 };
153
154 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
155 {
156         void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkSurfaceFormatKHR* data)
157         {
158                 m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
159         }
160 };
161
162 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
163 {
164         void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkPresentModeKHR* data)
165         {
166                 m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
167         }
168 };
169
170 typedef vector<VkExtensionProperties> Extensions;
171
172 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&                vkp,
173                                                                                 deUint32                                                version,
174                                                                                 const Extensions&                               supportedExtensions,
175                                                                                 Type                                                    wsiType,
176                                                                                 const vector<string>                    extraExtensions,
177                                                                                 const VkAllocationCallbacks*    pAllocator      = DE_NULL)
178 {
179         vector<string>  extensions = extraExtensions;
180
181         extensions.push_back("VK_KHR_surface");
182         extensions.push_back(getExtensionName(wsiType));
183
184         vector<string>  instanceExtensions;
185
186         for (vector<string>::const_iterator extensionName = extensions.begin();
187                  extensionName != extensions.end();
188                  ++extensionName)
189         {
190                 if (!isInstanceExtensionSupported(version, supportedExtensions, RequiredExtension(*extensionName)))
191                         TCU_THROW(NotSupportedError, (*extensionName + " is not supported").c_str());
192
193                 if (!isCoreInstanceExtension(version, *extensionName))
194                         instanceExtensions.push_back(*extensionName);
195         }
196
197         return vk::createDefaultInstance(vkp, version, vector<string>(), instanceExtensions, pAllocator);
198 }
199
200 struct InstanceHelper
201 {
202         const vector<VkExtensionProperties>     supportedExtensions;
203         Unique<VkInstance>                                      instance;
204         const InstanceDriver                            vki;
205
206         InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
207                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
208                                                                                                                                           DE_NULL))
209                 , instance                              (createInstanceWithWsi(context.getPlatformInterface(),
210                                                                                                            context.getUsedApiVersion(),
211                                                                                                            supportedExtensions,
212                                                                                                            wsiType,
213                                                                                                            vector<string>(),
214                                                                                                            pAllocator))
215                 , vki                                   (context.getPlatformInterface(), *instance)
216         {}
217
218         InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
219                 : supportedExtensions   (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
220                                                                                                                                           DE_NULL))
221                 , instance                              (createInstanceWithWsi(context.getPlatformInterface(),
222                                                                                                            context.getUsedApiVersion(),
223                                                                                                            supportedExtensions,
224                                                                                                            wsiType,
225                                                                                                            extensions,
226                                                                                                            pAllocator))
227                 , vki                                   (context.getPlatformInterface(), *instance)
228         {}
229 };
230
231 MovePtr<Display> createDisplay (const vk::Platform&     platform,
232                                                                 const Extensions&       supportedExtensions,
233                                                                 Type                            wsiType)
234 {
235         try
236         {
237                 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
238         }
239         catch (const tcu::NotSupportedError& e)
240         {
241                 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
242                     platform.hasDisplay(wsiType))
243                 {
244                         // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
245                         // must support creating native display & window for that WSI type.
246                         throw tcu::TestError(e.getMessage());
247                 }
248                 else
249                         throw;
250         }
251 }
252
253 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
254 {
255         try
256         {
257                 return MovePtr<Window>(display.createWindow(initialSize));
258         }
259         catch (const tcu::NotSupportedError& e)
260         {
261                 // See createDisplay - assuming that wsi::Display was supported platform port
262                 // should also support creating a window.
263                 throw tcu::TestError(e.getMessage());
264         }
265 }
266
267 struct NativeObjects
268 {
269         const UniquePtr<Display>        display;
270         const UniquePtr<Window>         window;
271
272         NativeObjects (Context&                         context,
273                                    const Extensions&    supportedExtensions,
274                                    Type                                 wsiType,
275                                    const Maybe<UVec2>&  initialWindowSize = tcu::nothing<UVec2>())
276                 : display       (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
277                 , window        (createWindow(*display, initialWindowSize))
278         {}
279 };
280
281 tcu::TestStatus createSurfaceTest (Context& context, Type wsiType)
282 {
283         const InstanceHelper            instHelper      (context, wsiType);
284         const NativeObjects                     native          (context, instHelper.supportedExtensions, wsiType);
285         const Unique<VkSurfaceKHR>      surface         (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
286
287         return tcu::TestStatus::pass("Creating surface succeeded");
288 }
289
290 tcu::TestStatus createSurfaceCustomAllocatorTest (Context& context, Type wsiType)
291 {
292         AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
293         tcu::TestLog&                           log                                     = context.getTestContext().getLog();
294
295         {
296                 const InstanceHelper            instHelper      (context, wsiType, allocationRecorder.getCallbacks());
297                 const NativeObjects                     native          (context, instHelper.supportedExtensions, wsiType);
298                 const Unique<VkSurfaceKHR>      surface         (createSurface(instHelper.vki,
299                                                                                                                            *instHelper.instance,
300                                                                                                                            wsiType,
301                                                                                                                            *native.display,
302                                                                                                                            *native.window,
303                                                                                                                            allocationRecorder.getCallbacks()));
304
305                 if (!validateAndLog(log,
306                                                         allocationRecorder,
307                                                         (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)         |
308                                                         (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
309                         return tcu::TestStatus::fail("Detected invalid system allocation callback");
310         }
311
312         if (!validateAndLog(log, allocationRecorder, 0u))
313                 return tcu::TestStatus::fail("Detected invalid system allocation callback");
314
315         if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
316                 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
317         else
318                 return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
319 }
320
321 tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
322 {
323         tcu::TestLog&   log     = context.getTestContext().getLog();
324
325         for (deUint32 numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
326         {
327                 AllocationCallbackRecorder      allocationRecorder      (getSystemAllocator());
328                 DeterministicFailAllocator      failingAllocator        (allocationRecorder.getCallbacks(),
329                                                                                                                  DeterministicFailAllocator::MODE_DO_NOT_COUNT,
330                                                                                                                  0);
331                 bool                                            gotOOM                          = false;
332
333                 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
334
335                 try
336                 {
337                         const InstanceHelper            instHelper      (context, wsiType, failingAllocator.getCallbacks());
338
339                         // OOM is not simulated for VkInstance as we don't want to spend time
340                         // testing OOM paths inside instance creation.
341                         failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
342
343                         const NativeObjects                     native          (context, instHelper.supportedExtensions, wsiType);
344                         const Unique<VkSurfaceKHR>      surface         (createSurface(instHelper.vki,
345                                                                                                                                    *instHelper.instance,
346                                                                                                                                    wsiType,
347                                                                                                                                    *native.display,
348                                                                                                                                    *native.window,
349                                                                                                                                    failingAllocator.getCallbacks()));
350
351                         if (!validateAndLog(log,
352                                                                 allocationRecorder,
353                                                                 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)         |
354                                                                 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
355                                 return tcu::TestStatus::fail("Detected invalid system allocation callback");
356                 }
357                 catch (const OutOfMemoryError& e)
358                 {
359                         log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
360                         gotOOM = true;
361                 }
362
363                 if (!validateAndLog(log, allocationRecorder, 0u))
364                         return tcu::TestStatus::fail("Detected invalid system allocation callback");
365
366                 if (!gotOOM)
367                 {
368                         log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
369
370                         if (numPassingAllocs == 0)
371                                 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
372                         else
373                                 return tcu::TestStatus::pass("OOM simulation completed");
374                 }
375         }
376
377         return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
378 }
379
380 deUint32 getNumQueueFamilies (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
381 {
382         deUint32        numFamilies             = 0;
383
384         vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
385
386         return numFamilies;
387 }
388
389 tcu::TestStatus querySurfaceSupportTest (Context& context, Type wsiType)
390 {
391         tcu::TestLog&                                   log                                             = context.getTestContext().getLog();
392         tcu::ResultCollector                    results                                 (log);
393
394         const InstanceHelper                    instHelper                              (context, wsiType);
395         const NativeObjects                             native                                  (context, instHelper.supportedExtensions, wsiType);
396         const Unique<VkSurfaceKHR>              surface                                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
397         const vector<VkPhysicalDevice>  physicalDevices                 = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
398
399         // On Android surface must be supported by all devices and queue families
400         const bool                                              expectSupportedOnAll    = wsiType == TYPE_ANDROID;
401
402         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
403         {
404                 const VkPhysicalDevice          physicalDevice          = physicalDevices[deviceNdx];
405                 const deUint32                          numQueueFamilies        = getNumQueueFamilies(instHelper.vki, physicalDevice);
406
407                 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
408                 {
409                         const VkBool32  isSupported             = getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
410
411                         log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
412                                                                         << (isSupported == VK_FALSE ? "NOT " : "") << "supported"
413                                 << TestLog::EndMessage;
414
415                         if (expectSupportedOnAll && !isSupported)
416                                 results.fail("Surface must be supported by all devices and queue families");
417                 }
418         }
419
420         return tcu::TestStatus(results.getResult(), results.getMessage());
421 }
422
423 bool isSupportedByAnyQueue (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
424 {
425         const deUint32  numQueueFamilies        = getNumQueueFamilies(vki, physicalDevice);
426
427         for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
428         {
429                 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
430                         return true;
431         }
432
433         return false;
434 }
435
436 void validateSurfaceCapabilities (tcu::ResultCollector& results, const VkSurfaceCapabilitiesKHR& capabilities)
437 {
438         results.check(capabilities.minImageCount > 0,
439                                   "minImageCount must be larger than 0");
440
441         results.check(capabilities.minImageExtent.width > 0 &&
442                                   capabilities.minImageExtent.height > 0,
443                                   "minImageExtent dimensions must be larger than 0");
444
445         results.check(capabilities.maxImageExtent.width > 0 &&
446                                   capabilities.maxImageExtent.height > 0,
447                                   "maxImageExtent dimensions must be larger than 0");
448
449         results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
450                                   capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
451                                   "maxImageExtent must be larger or equal to minImageExtent");
452
453         if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
454                 capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
455         {
456                 results.check(capabilities.currentExtent.width > 0 &&
457                                           capabilities.currentExtent.height > 0,
458                                           "currentExtent dimensions must be larger than 0");
459
460                 results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width) &&
461                                           de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height),
462                                           "currentExtent is not in supported extent limits");
463         }
464
465         results.check(capabilities.maxImageArrayLayers > 0,
466                                   "maxImageArrayLayers must be larger than 0");
467
468         results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
469                                   "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
470
471         results.check(capabilities.supportedTransforms != 0,
472                                   "At least one transform must be supported");
473
474         results.check(dePop32(capabilities.currentTransform) != 0,
475                                   "Invalid currentTransform");
476
477         results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
478                                   "currentTransform is not supported by surface");
479
480         results.check(capabilities.supportedCompositeAlpha != 0,
481                                   "At least one alpha mode must be supported");
482 }
483
484 tcu::TestStatus querySurfaceCapabilitiesTest (Context& context, Type wsiType)
485 {
486         tcu::TestLog&                                   log                                             = context.getTestContext().getLog();
487         tcu::ResultCollector                    results                                 (log);
488
489         const InstanceHelper                    instHelper                              (context, wsiType);
490         const NativeObjects                             native                                  (context, instHelper.supportedExtensions, wsiType);
491         const Unique<VkSurfaceKHR>              surface                                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
492         const vector<VkPhysicalDevice>  physicalDevices                 = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
493
494         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
495         {
496                 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
497                 {
498                         const VkSurfaceCapabilitiesKHR  capabilities    = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
499                                                                                                                                                                                                    physicalDevices[deviceNdx],
500                                                                                                                                                                                                    *surface);
501
502                         log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
503
504                         validateSurfaceCapabilities(results, capabilities);
505                 }
506                 // else skip query as surface is not supported by the device
507         }
508
509         return tcu::TestStatus(results.getResult(), results.getMessage());
510 }
511
512 tcu::TestStatus querySurfaceCapabilities2Test (Context& context, Type wsiType)
513 {
514         tcu::TestLog&                                   log                                             = context.getTestContext().getLog();
515         tcu::ResultCollector                    results                                 (log);
516
517         const InstanceHelper                    instHelper                              (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
518         const NativeObjects                             native                                  (context, instHelper.supportedExtensions, wsiType);
519         const Unique<VkSurfaceKHR>              surface                                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
520         const vector<VkPhysicalDevice>  physicalDevices                 = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
521
522         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
523         {
524                 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
525                 {
526                         const VkSurfaceCapabilitiesKHR  refCapabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
527                                                                                                                                                                                                    physicalDevices[deviceNdx],
528                                                                                                                                                                                                    *surface);
529                         VkSurfaceCapabilities2KHR               extCapabilities;
530
531                         deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
532                         extCapabilities.sType   = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
533                         extCapabilities.pNext   = DE_NULL;
534
535                         {
536                                 const VkPhysicalDeviceSurfaceInfo2KHR   surfaceInfo     =
537                                 {
538                                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
539                                         DE_NULL,
540                                         *surface
541                                 };
542                                 VkPhysicalDeviceSurfaceInfo2KHR                 infoCopy;
543
544                                 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
545
546                                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
547
548                                 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
549                         }
550
551                         results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
552                                                   extCapabilities.pNext == DE_NULL,
553                                                   "sType/pNext modified");
554
555                         if (refCapabilities != extCapabilities.surfaceCapabilities)
556                         {
557                                 log << TestLog::Message
558                                         << "Device " << deviceNdx
559                                         << ": expected " << refCapabilities
560                                         << ", got " << extCapabilities.surfaceCapabilities
561                                         << TestLog::EndMessage;
562                                 results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
563                         }
564                 }
565         }
566
567         return tcu::TestStatus(results.getResult(), results.getMessage());
568 }
569
570 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
571 {
572         const VkSurfaceFormatKHR*       requiredFormats         = DE_NULL;
573         size_t                                          numRequiredFormats      = 0;
574
575         if (wsiType == TYPE_ANDROID)
576         {
577                 static const VkSurfaceFormatKHR s_androidFormats[] =
578                 {
579                         { VK_FORMAT_R8G8B8A8_UNORM,                     VK_COLOR_SPACE_SRGB_NONLINEAR_KHR       },
580                         { VK_FORMAT_R8G8B8A8_SRGB,                      VK_COLOR_SPACE_SRGB_NONLINEAR_KHR       },
581                         { VK_FORMAT_R5G6B5_UNORM_PACK16,        VK_COLOR_SPACE_SRGB_NONLINEAR_KHR       }
582                 };
583
584                 requiredFormats         = &s_androidFormats[0];
585                 numRequiredFormats      = DE_LENGTH_OF_ARRAY(s_androidFormats);
586         }
587
588         for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
589         {
590                 const VkSurfaceFormatKHR&       requiredFormat  = requiredFormats[ndx];
591
592                 if (!de::contains(formats.begin(), formats.end(), requiredFormat))
593                         results.fail(de::toString(requiredFormat) + " not supported");
594         }
595
596         // Check that there are no duplicates
597         for (size_t ndx = 1; ndx < formats.size(); ++ndx)
598         {
599                 if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
600                         results.fail("Found duplicate entry " + de::toString(formats[ndx]));
601         }
602 }
603
604 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
605 {
606         tcu::TestLog&                                   log                             = context.getTestContext().getLog();
607         tcu::ResultCollector                    results                 (log);
608
609         const InstanceHelper                    instHelper              (context, wsiType);
610         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType);
611         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
612         const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
613
614         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
615         {
616                 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
617                 {
618                         deUint32        numFormats = 0;
619
620                         VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, DE_NULL));
621
622                         std::vector<VkSurfaceFormatKHR> formats (numFormats + 1);
623
624                         if (numFormats > 0)
625                         {
626                                 const deUint32 numFormatsOrig = numFormats;
627
628                                 // check if below call properly overwrites formats count
629                                 numFormats++;
630
631                                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, &formats[0]));
632
633                                 if (numFormats != numFormatsOrig)
634                                         results.fail("Format count changed between calls");
635                         }
636
637                         formats.pop_back();
638
639                         log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
640
641                         validateSurfaceFormats(results, wsiType, formats);
642                         CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, formats.size());
643                 }
644                 // else skip query as surface is not supported by the device
645         }
646
647         return tcu::TestStatus(results.getResult(), results.getMessage());
648 }
649
650 tcu::TestStatus querySurfaceFormats2Test (Context& context, Type wsiType)
651 {
652         tcu::TestLog&                                   log                             = context.getTestContext().getLog();
653         tcu::ResultCollector                    results                 (log);
654
655         const InstanceHelper                    instHelper              (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
656         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType);
657         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
658         const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
659
660         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
661         {
662                 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
663                 {
664                         const vector<VkSurfaceFormatKHR>                refFormats      = getPhysicalDeviceSurfaceFormats(instHelper.vki,
665                                                                                                                                                                                                   physicalDevices[deviceNdx],
666                                                                                                                                                                                                   *surface);
667                         const VkPhysicalDeviceSurfaceInfo2KHR   surfaceInfo     =
668                         {
669                                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
670                                 DE_NULL,
671                                 *surface
672                         };
673                         deUint32                                                                numFormats      = 0;
674
675                         VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, DE_NULL));
676
677                         if ((size_t)numFormats != refFormats.size())
678                                 results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
679
680                         if (numFormats > 0)
681                         {
682                                 vector<VkSurfaceFormat2KHR>     formats (numFormats + 1);
683
684                                 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
685                                 {
686                                         formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
687                                         formats[ndx].pNext = DE_NULL;
688                                 }
689
690                                 const deUint32 numFormatsOrig = numFormats;
691
692                                 // check if below call properly overwrites formats count
693                                 numFormats++;
694
695                                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, &formats[0]));
696
697                                 if ((size_t)numFormats != numFormatsOrig)
698                                         results.fail("Format count changed between calls");
699
700                                 formats.pop_back();
701
702                                 {
703                                         vector<VkSurfaceFormatKHR>      extFormats      (formats.size());
704
705                                         for (size_t ndx = 0; ndx < formats.size(); ++ndx)
706                                         {
707                                                 results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
708                                                                           formats[ndx].pNext == DE_NULL,
709                                                                           "sType/pNext modified");
710                                                 extFormats[ndx] = formats[ndx].surfaceFormat;
711                                         }
712
713                                         for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
714                                         {
715                                                 if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
716                                                         results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
717                                         }
718                                 }
719
720                                 // Check VK_INCOMPLETE
721                                 {
722                                         vector<VkSurfaceFormat2KHR>     formatsClone    (formats);
723                                         deUint32                                        numToSupply             = numFormats/2;
724                                         VkResult                                        queryResult;
725
726                                         ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
727
728                                         queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
729
730                                         results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
731                                         results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
732                                                                   "Driver wrote past last element");
733
734                                         for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
735                                         {
736                                                 results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
737                                                                           formatsClone[ndx].pNext == DE_NULL &&
738                                                                           formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
739                                                                           "Returned element " + de::toString(ndx) + " is different");
740                                         }
741                                 }
742                         }
743                 }
744                 // else skip query as surface is not supported by the device
745         }
746
747         return tcu::TestStatus(results.getResult(), results.getMessage());
748 }
749
750 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
751 {
752         results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
753                                   "VK_PRESENT_MODE_FIFO_KHR is not supported");
754
755         if (wsiType == TYPE_ANDROID)
756                 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
757                                           "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
758 }
759
760 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
761 {
762         tcu::TestLog&                                   log                             = context.getTestContext().getLog();
763         tcu::ResultCollector                    results                 (log);
764
765         const InstanceHelper                    instHelper              (context, wsiType);
766         const NativeObjects                             native                  (context, instHelper.supportedExtensions, wsiType);
767         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
768         const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
769
770         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
771         {
772                 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
773                 {
774                         deUint32        numModes = 0;
775
776                         VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, DE_NULL));
777
778                         vector<VkPresentModeKHR>        modes   (numModes + 1);
779
780                         if (numModes > 0)
781                         {
782                                 const deUint32 numModesOrig = numModes;
783
784                                 // check if below call properly overwrites mode count
785                                 numModes++;
786
787                                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, &modes[0]));
788
789                                 if ((size_t)numModes != numModesOrig)
790                                         TCU_FAIL("Mode count changed between calls");
791                         }
792
793                         modes.pop_back();
794
795                         log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
796
797                         validateSurfacePresentModes(results, wsiType, modes);
798                         CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
799                 }
800                 // else skip query as surface is not supported by the device
801         }
802
803         return tcu::TestStatus(results.getResult(), results.getMessage());
804 }
805
806 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest (Context& context, Type wsiType)
807 {
808         tcu::TestLog&                                                                   log                                             = context.getTestContext().getLog();
809         const InstanceHelper                                                    instHelper                              (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
810         const float                                                                             queuePriority                   = 1.0f;
811         const tcu::CommandLine&                                                 cmdLine                                 = context.getTestContext().getCommandLine();
812         const deUint32                                                                  devGroupIdx                             = cmdLine.getVKDeviceGroupId() - 1;
813         const deUint32                                                                  deviceIdx                               = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
814         const VkDeviceGroupPresentModeFlagsKHR                  requiredFlag                    = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
815         const VkDeviceGroupPresentModeFlagsKHR                  maxValidFlag                    = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
816                                                                                                                                                                 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
817         deUint8                                                                                 buffer                                  [sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
818         deUint32                                                                                queueFamilyIndex                = 0;
819         VkDeviceGroupPresentCapabilitiesKHR*                    presentCapabilities;
820         VkPhysicalDevice                                                                physicalDevice                  = chooseDevice(instHelper.vki, *instHelper.instance, cmdLine);
821         const Extensions&                                                               supportedExtensions             = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
822         std::vector<const char*>                                                deviceExtensions;
823
824         if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
825                 deviceExtensions.push_back("VK_KHR_device_group");
826         deviceExtensions.push_back("VK_KHR_swapchain");
827
828         for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
829         {
830                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
831                         TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
832         }
833
834         const vector<VkPhysicalDeviceGroupProperties>   deviceGroupProps                = enumeratePhysicalDeviceGroups(instHelper.vki, *instHelper.instance);
835
836         const std::vector<VkQueueFamilyProperties>              queueProps                              = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
837         for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
838         {
839                 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
840                         queueFamilyIndex = (deUint32)queueNdx;
841         }
842         const VkDeviceQueueCreateInfo                                   deviceQueueCreateInfo   =
843         {
844                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,                             //type
845                 DE_NULL,                                                                                                //pNext
846                 (VkDeviceQueueCreateFlags)0u,                                                   //flags
847                 queueFamilyIndex,                                                                               //queueFamilyIndex;
848                 1u,                                                                                                             //queueCount;
849                 &queuePriority,                                                                                 //pQueuePriorities;
850         };
851         const VkDeviceGroupDeviceCreateInfo                             deviceGroupInfo                 =
852         {
853                 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,  //stype
854                 DE_NULL,                                                                                                //pNext
855                 deviceGroupProps[devGroupIdx].physicalDeviceCount,              //physicalDeviceCount
856                 deviceGroupProps[devGroupIdx].physicalDevices                   //physicalDevices
857         };
858         const VkDeviceCreateInfo                                                deviceCreateInfo                =
859         {
860                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,                                                   //sType;
861                 &deviceGroupInfo,                                                                                               //pNext;
862                 (VkDeviceCreateFlags)0u,                                                                                //flags
863                 1,                                                                                                                              //queueRecordCount;
864                 &deviceQueueCreateInfo,                                                                                 //pRequestedQueues;
865                 0,                                                                                                                              //layerCount;
866                 DE_NULL,                                                                                                                //ppEnabledLayerNames;
867                 deUint32(deviceExtensions.size()),                                                              //enabledExtensionCount;
868                 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]),    //ppEnabledExtensionNames;
869                 DE_NULL,                                                                                                                //pEnabledFeatures;
870         };
871         Move<VkDevice>          deviceGroup = createDevice(context.getPlatformInterface(), *instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
872         const DeviceDriver      vk      (context.getPlatformInterface(), *instHelper.instance, *deviceGroup);
873
874
875         presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>(buffer);
876         deMemset(buffer, GUARD_VALUE, sizeof(buffer));
877         presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
878         presentCapabilities->pNext = DE_NULL;
879         VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
880
881         // Guard check
882         for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
883         {
884                 if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
885                 {
886                         log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
887                         return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
888                 }
889         }
890
891         // Check each physical device can present on itself
892         for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE_KHR; physDevIdx++)
893         {
894                 if (presentCapabilities->presentMask[physDevIdx])
895                         if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
896                                 return tcu::TestStatus::fail("deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
897         }
898
899         // Check if flags are valid
900         if ((!(presentCapabilities->modes & requiredFlag)) ||
901                 presentCapabilities->modes > maxValidFlag)
902                 return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
903
904         return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
905 }
906
907 tcu::TestStatus queryDevGroupSurfacePresentModesTest (Context& context, Type wsiType)
908 {
909         tcu::TestLog&                                                   log                                     = context.getTestContext().getLog();
910         tcu::ResultCollector                                    results                         (log);
911         const InstanceHelper                                    instHelper                      (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
912         const NativeObjects                                             native                          (context, instHelper.supportedExtensions, wsiType);
913         const Unique<VkSurfaceKHR>                              surface                         (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
914         const float                                                             queuePriority           = 1.0f;
915         const tcu::CommandLine&                                 cmdLine                         = context.getTestContext().getCommandLine();
916         const deUint32                                                  devGroupIdx                     = cmdLine.getVKDeviceGroupId() - 1;
917         const deUint32                                                  deviceIdx                       = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
918         const VkDeviceGroupPresentModeFlagsKHR  requiredFlag            = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
919         const VkDeviceGroupPresentModeFlagsKHR  maxValidFlag            = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
920                                                                                                                                         VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
921         VkResult                                                                result                          = VK_SUCCESS;
922         deUint8                                                                 buffer                          [sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
923         deUint32                                                                rectCount                       = 0;
924         deUint32                                                                incompleteRectCount     = 0;
925         deUint32                                                                queueFamilyIndex        = 0;
926         VkRect2D*                                                               presentRectangles;
927         VkDeviceGroupPresentModeFlagsKHR*               presentModeFlags;
928         vector<deUint8>                                                 rectanglesBuffer;
929         VkPhysicalDevice                                                physicalDevice          = chooseDevice(instHelper.vki, *instHelper.instance, cmdLine);
930         const Extensions&                                               supportedExtensions     = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
931         std::vector<const char*>                                deviceExtensions;
932
933         if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
934                 deviceExtensions.push_back("VK_KHR_device_group");
935         deviceExtensions.push_back("VK_KHR_swapchain");
936
937         for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
938         {
939                 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
940                         TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
941         }
942
943         const vector<VkPhysicalDeviceGroupProperties>   deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, *instHelper.instance);
944         const std::vector<VkQueueFamilyProperties>      queueProps              = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
945         for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
946         {
947                 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
948                         queueFamilyIndex = (deUint32)queueNdx;
949         }
950         const VkDeviceQueueCreateInfo                   deviceQueueCreateInfo =
951         {
952                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,                                     //type
953                 DE_NULL,                                                                                                        //pNext
954                 (VkDeviceQueueCreateFlags)0u,                                                           //flags
955                 queueFamilyIndex,                                                                                       //queueFamilyIndex;
956                 1u,                                                                                                                     //queueCount;
957                 &queuePriority,                                                                                         //pQueuePriorities;
958         };
959         const VkDeviceGroupDeviceCreateInfo                     deviceGroupInfo =
960         {
961                 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,  //stype
962                 DE_NULL,                                                                                                //pNext
963                 deviceGroupProps[devGroupIdx].physicalDeviceCount,              //physicalDeviceCount
964                 deviceGroupProps[devGroupIdx].physicalDevices                   //physicalDevices
965         };
966         const VkDeviceCreateInfo                                                deviceCreateInfo =
967         {
968                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,                                                   //sType;
969                 &deviceGroupInfo,                                                                                               //pNext;
970                 (VkDeviceCreateFlags)0u,                                                                                //flags
971                 1,                                                                                                                              //queueRecordCount;
972                 &deviceQueueCreateInfo,                                                                                 //pRequestedQueues;
973                 0,                                                                                                                              //layerCount;
974                 DE_NULL,                                                                                                                //ppEnabledLayerNames;
975                 deUint32(deviceExtensions.size()),                                                              //enabledExtensionCount;
976                 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]),    //ppEnabledExtensionNames;
977                 DE_NULL,                                                                                                                //pEnabledFeatures;
978         };
979
980         Move<VkDevice>          deviceGroup = createDevice(context.getPlatformInterface(), *instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
981         const DeviceDriver      vk      (context.getPlatformInterface(), *instHelper.instance, *deviceGroup);
982         presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>(buffer);
983         deMemset(buffer, GUARD_VALUE, sizeof(buffer));
984
985         VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
986
987         // Guard check
988         for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
989         {
990                 if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
991                 {
992                         log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
993                         return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
994                 }
995         }
996
997         // Check if flags are valid
998         if ((!(*presentModeFlags & requiredFlag)) ||
999                 *presentModeFlags > maxValidFlag)
1000                 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1001
1002         // Check presentation rectangles
1003         if (*presentModeFlags == VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR)
1004         {
1005                 for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1006                 {
1007                         VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1008                         rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1009                         presentRectangles = reinterpret_cast<VkRect2D*>(rectanglesBuffer.data());
1010                         deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1011
1012                         VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1013
1014                         // Guard check
1015                         for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1016                         {
1017                                 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1018                                 {
1019                                         log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1020                                         return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1021                                 }
1022                         }
1023
1024                         // Check rectangles do not overlap
1025                         for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1026                         {
1027                                 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1028                                 {
1029                                         if (rectIdx1 != rectIdx2)
1030                                         {
1031                                                 deUint32 rectATop               = presentRectangles[rectIdx1].offset.y;
1032                                                 deUint32 rectALeft              = presentRectangles[rectIdx1].offset.x;
1033                                                 deUint32 rectABottom    = presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1034                                                 deUint32 rectARight             = presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1035
1036                                                 deUint32 rectBTop               = presentRectangles[rectIdx2].offset.y;
1037                                                 deUint32 rectBLeft              = presentRectangles[rectIdx2].offset.x;
1038                                                 deUint32 rectBBottom    = presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1039                                                 deUint32 rectBRight             = presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1040
1041                                                 if (rectALeft < rectBRight && rectARight > rectBLeft &&
1042                                                         rectATop < rectBBottom && rectABottom > rectBTop)
1043                                                         return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1044                                         }
1045                                 }
1046                         }
1047
1048                         // Check incomplete
1049                         incompleteRectCount = rectCount / 2;
1050                         result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount, presentRectangles);
1051                         results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1052                 }
1053         }
1054         return tcu::TestStatus(results.getResult(), results.getMessage());
1055 }
1056
1057 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
1058 {
1059         tcu::TestLog&                                   log                             = context.getTestContext().getLog();
1060         tcu::ResultCollector                    results                 (log);
1061
1062         const InstanceHelper                    instHelper              (context, wsiType);
1063
1064         const UniquePtr<Display>                nativeDisplay   (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1065                                                                                                                                    instHelper.supportedExtensions,
1066                                                                                                                                    wsiType));
1067
1068         const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
1069         const UVec2                                             sizes[]                 =
1070         {
1071                 UVec2(64, 64),
1072                 UVec2(124, 119),
1073                 UVec2(256, 512)
1074         };
1075
1076         DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1077
1078         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1079         {
1080                 const UVec2&                            testSize                = sizes[sizeNdx];
1081                 const UniquePtr<Window>         nativeWindow    (createWindow(*nativeDisplay, tcu::just(testSize)));
1082                 const Unique<VkSurfaceKHR>      surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1083
1084                 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1085                 {
1086                         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1087                         {
1088                                 const VkSurfaceCapabilitiesKHR  capabilities    = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1089
1090                                 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1091                                 results.check(capabilities.currentExtent.width == testSize.x() &&
1092                                                                 capabilities.currentExtent.height == testSize.y(),
1093                                                                 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1094                         }
1095                 }
1096         }
1097
1098         return tcu::TestStatus(results.getResult(), results.getMessage());
1099 }
1100
1101 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
1102 {
1103         tcu::TestLog&                                   log                             = context.getTestContext().getLog();
1104         tcu::ResultCollector                    results                 (log);
1105
1106         const InstanceHelper                    instHelper              (context, wsiType);
1107
1108         const UniquePtr<Display>                nativeDisplay   (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1109                                                                                                                                    instHelper.supportedExtensions,
1110                                                                                                                                    wsiType));
1111         UniquePtr<Window>                               nativeWindow    (createWindow(*nativeDisplay, tcu::nothing<UVec2>()));
1112
1113         const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
1114         const Unique<VkSurfaceKHR>              surface                 (createSurface(instHelper.vki, *instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1115
1116         const UVec2                                             sizes[]                 =
1117         {
1118                 UVec2(64, 64),
1119                 UVec2(124, 119),
1120                 UVec2(256, 512)
1121         };
1122
1123         DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1124
1125         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1126         {
1127                 const UVec2             testSize        = sizes[sizeNdx];
1128
1129                 try
1130                 {
1131                         nativeWindow->resize(testSize);
1132                 }
1133                 catch (const tcu::Exception& e)
1134                 {
1135                         // Make sure all exception types result in a test failure
1136                         results.fail(e.getMessage());
1137                 }
1138
1139                 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1140                 {
1141                         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1142                         {
1143                                 const VkSurfaceCapabilitiesKHR  capabilities    = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1144
1145                                 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1146                                 results.check(capabilities.currentExtent.width == testSize.x() &&
1147                                                                 capabilities.currentExtent.height == testSize.y(),
1148                                                                 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1149                         }
1150                 }
1151         }
1152
1153         return tcu::TestStatus(results.getResult(), results.getMessage());
1154 }
1155
1156 tcu::TestStatus destroyNullHandleSurfaceTest (Context& context, Type wsiType)
1157 {
1158         const InstanceHelper    instHelper      (context, wsiType);
1159         const VkSurfaceKHR              nullHandle      = DE_NULL;
1160
1161         // Default allocator
1162         instHelper.vki.destroySurfaceKHR(*instHelper.instance, nullHandle, DE_NULL);
1163
1164         // Custom allocator
1165         {
1166                 AllocationCallbackRecorder      recordingAllocator      (getSystemAllocator(), 1u);
1167
1168                 instHelper.vki.destroySurfaceKHR(*instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1169
1170                 if (recordingAllocator.getNumRecords() != 0u)
1171                         return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1172         }
1173
1174         return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1175 }
1176
1177 } // anonymous
1178
1179 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1180 {
1181         const PlatformProperties&       platformProperties      = getPlatformProperties(wsiType);
1182
1183         addFunctionCase(testGroup, "create",                                                            "Create surface",                                                                                       createSurfaceTest,                                                      wsiType);
1184         addFunctionCase(testGroup, "create_custom_allocator",                           "Create surface with custom allocator",                                         createSurfaceCustomAllocatorTest,                       wsiType);
1185         addFunctionCase(testGroup, "create_simulate_oom",                                       "Create surface with simulating OOM",                                           createSurfaceSimulateOOMTest,                           wsiType);
1186         addFunctionCase(testGroup, "query_support",                                                     "Query surface support",                                                                        querySurfaceSupportTest,                                        wsiType);
1187         addFunctionCase(testGroup, "query_capabilities",                                        "Query surface capabilities",                                                           querySurfaceCapabilitiesTest,                           wsiType);
1188         addFunctionCase(testGroup, "query_capabilities2",                                       "Query extended surface capabilities",                                          querySurfaceCapabilities2Test,                          wsiType);
1189         addFunctionCase(testGroup, "query_formats",                                                     "Query surface formats",                                                                        querySurfaceFormatsTest,                                        wsiType);
1190         addFunctionCase(testGroup, "query_formats2",                                            "Query extended surface formats",                                                       querySurfaceFormats2Test,                                       wsiType);
1191         addFunctionCase(testGroup, "query_present_modes",                                       "Query surface present modes",                                                          querySurfacePresentModesTest,                           wsiType);
1192         addFunctionCase(testGroup, "query_devgroup_present_capabilities",       "Query surface present modes capabilities in device groups",queryDevGroupSurfacePresentCapabilitiesTest,wsiType);
1193         addFunctionCase(testGroup, "query_devgroup_present_modes",                      "Query surface present modes for device groups",                        queryDevGroupSurfacePresentModesTest,           wsiType);
1194         addFunctionCase(testGroup, "destroy_null_handle",                                       "Destroy VK_NULL_HANDLE surface",                                                       destroyNullHandleSurfaceTest,                           wsiType);
1195
1196         if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1197                 addFunctionCase(testGroup, "initial_size",      "Create surface with initial window size set",  createSurfaceInitialSizeTest,   wsiType);
1198
1199         if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1200                 addFunctionCase(testGroup, "resize",            "Resize window and surface",                                    resizeSurfaceTest,                              wsiType);
1201 }
1202
1203 } // wsi
1204 } // vkt