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