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