xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/wsi/vktWsiSurfaceTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
operator !=(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)59 inline bool operator!=(const VkSurfaceFormatKHR &a, const VkSurfaceFormatKHR &b)
60 {
61     return (a.format != b.format) || (a.colorSpace != b.colorSpace);
62 }
63 
operator ==(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)64 inline bool operator==(const VkSurfaceFormatKHR &a, const VkSurfaceFormatKHR &b)
65 {
66     return !(a != b);
67 }
68 
operator !=(const VkExtent2D & a,const VkExtent2D & b)69 inline bool operator!=(const VkExtent2D &a, const VkExtent2D &b)
70 {
71     return (a.width != b.width) || (a.height != b.height);
72 }
73 
operator !=(const VkSurfaceCapabilitiesKHR & a,const VkSurfaceCapabilitiesKHR & b)74 inline bool operator!=(const VkSurfaceCapabilitiesKHR &a, const VkSurfaceCapabilitiesKHR &b)
75 {
76     return (a.minImageCount != b.minImageCount) || (a.maxImageCount != b.maxImageCount) ||
77            (a.currentExtent != b.currentExtent) || (a.minImageExtent != b.minImageExtent) ||
78            (a.maxImageExtent != b.maxImageExtent) || (a.maxImageArrayLayers != b.maxImageArrayLayers) ||
79            (a.supportedTransforms != b.supportedTransforms) || (a.currentTransform != b.currentTransform) ||
80            (a.supportedCompositeAlpha != b.supportedCompositeAlpha) || (a.supportedUsageFlags != b.supportedUsageFlags);
81 }
82 
83 } // namespace vk
84 
85 namespace vkt
86 {
87 namespace wsi
88 {
89 
90 namespace
91 {
92 
93 using namespace vk;
94 using namespace vk::wsi;
95 
96 using tcu::Maybe;
97 using tcu::TestLog;
98 using tcu::UVec2;
99 
100 using de::MovePtr;
101 using de::UniquePtr;
102 
103 using std::string;
104 using std::vector;
105 
106 enum
107 {
108     SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC = 0xffffffff
109 };
110 
111 enum
112 {
113     GUARD_SIZE  = 0x20, //!< Number of bytes to check
114     GUARD_VALUE = 0xcd, //!< Data pattern
115 };
116 
117 template <typename T>
118 class CheckIncompleteResult
119 {
120 public:
~CheckIncompleteResult(void)121     virtual ~CheckIncompleteResult(void)
122     {
123     }
124     virtual void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
125                            T *data) = 0;
126 
operator ()(tcu::ResultCollector & results,const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSurfaceKHR surface,const std::size_t expectedCompleteSize)127     void operator()(tcu::ResultCollector &results, const InstanceInterface &vki, const VkPhysicalDevice physDevice,
128                     const VkSurfaceKHR surface, const std::size_t expectedCompleteSize)
129     {
130         if (expectedCompleteSize == 0)
131             return;
132 
133         vector<T> outputData(expectedCompleteSize);
134         const uint32_t usedSize = static_cast<uint32_t>(expectedCompleteSize / 3);
135 
136         ValidateQueryBits::fillBits(outputData.begin(),
137                                     outputData.end()); // unused entries should have this pattern intact
138         m_count  = usedSize;
139         m_result = VK_SUCCESS;
140 
141         getResult(vki, physDevice, surface, &outputData[0]); // update m_count and m_result
142 
143         if (m_count != usedSize || m_result != VK_INCOMPLETE ||
144             !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
145             results.fail("Query didn't return VK_INCOMPLETE");
146     }
147 
148 protected:
149     uint32_t m_count;
150     VkResult m_result;
151 };
152 
153 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
154 {
getResultvkt::wsi::__anon2b710b1b0111::CheckPhysicalDeviceSurfaceFormatsIncompleteResult155     void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
156                    VkSurfaceFormatKHR *data)
157     {
158         m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
159     }
160 };
161 
162 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
163 {
getResultvkt::wsi::__anon2b710b1b0111::CheckPhysicalDeviceSurfacePresentModesIncompleteResult164     void getResult(const InstanceInterface &vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface,
165                    VkPresentModeKHR *data)
166     {
167         m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
168     }
169 };
170 
171 typedef vector<VkExtensionProperties> Extensions;
172 
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)173 CustomInstance createInstanceWithWsi(Context &context, Type wsiType, const vector<string> extraExtensions,
174                                      const VkAllocationCallbacks *pAllocator = DE_NULL)
175 {
176     const uint32_t version    = context.getUsedApiVersion();
177     vector<string> extensions = extraExtensions;
178 
179     extensions.push_back("VK_KHR_surface");
180     extensions.push_back(getExtensionName(wsiType));
181     if (isDisplaySurface(wsiType))
182         extensions.push_back("VK_KHR_display");
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 
InstanceHelpervkt::wsi::__anon2b710b1b0111::InstanceHelper203     InstanceHelper(Context &context, Type wsiType, const VkAllocationCallbacks *pAllocator = DE_NULL)
204         : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
205         , instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
206         , vki(instance.getDriver())
207     {
208     }
209 
InstanceHelpervkt::wsi::__anon2b710b1b0111::InstanceHelper210     InstanceHelper(Context &context, Type wsiType, const vector<string> &extensions,
211                    const VkAllocationCallbacks *pAllocator = DE_NULL)
212         : supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
213         , instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
214         , vki(instance.getDriver())
215     {
216     }
217 };
218 
createSurfaceTest(Context & context,Type wsiType)219 tcu::TestStatus createSurfaceTest(Context &context, Type wsiType)
220 {
221     const InstanceHelper instHelper(context, wsiType);
222     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
223     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
224                                                      native.getWindow(), context.getTestContext().getCommandLine()));
225 
226     return tcu::TestStatus::pass("Creating surface succeeded");
227 }
228 
querySurfaceCounterTest(Context & context,Type wsiType)229 tcu::TestStatus querySurfaceCounterTest(Context &context, Type wsiType)
230 {
231     const InstanceHelper instHelper(context, wsiType, {"VK_KHR_display", "VK_EXT_display_surface_counter"});
232     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
233     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
234                                                      native.getWindow(), context.getTestContext().getCommandLine()));
235     const vk::InstanceInterface &vki          = instHelper.vki;
236     const tcu::CommandLine &cmdLine           = context.getTestContext().getCommandLine();
237     const vk::VkPhysicalDevice physicalDevice = chooseDevice(vki, instHelper.instance, cmdLine);
238     const bool isDisplay                      = isDisplaySurface(wsiType);
239 
240     if (!isInstanceExtensionSupported(context.getUsedApiVersion(), context.getInstanceExtensions(),
241                                       "VK_EXT_display_surface_counter"))
242         TCU_THROW(NotSupportedError, "VK_EXT_display_surface_counter not supported");
243 
244     VkBool32 surfaceSupported;
245     vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, 0u, surface.get(), &surfaceSupported);
246     if (!surfaceSupported)
247         TCU_THROW(NotSupportedError, "Surface is not supported by physical device");
248 
249     const vk::VkSurfaceCapabilities2EXT capsExt =
250         getPhysicalDeviceSurfaceCapabilities2EXT(vki, physicalDevice, surface.get());
251     const vk::VkSurfaceCapabilitiesKHR capsKhr =
252         getPhysicalDeviceSurfaceCapabilities(vki, physicalDevice, surface.get());
253 
254     if (!sameSurfaceCapabilities(capsKhr, capsExt))
255     {
256         return tcu::TestStatus::fail("KHR and EXT surface capabilities do not match");
257     }
258 
259     if (!isDisplay && capsExt.supportedSurfaceCounters != 0)
260     {
261         return tcu::TestStatus::fail("supportedSurfaceCounters nonzero (" +
262                                      de::toString(capsExt.supportedSurfaceCounters) + ") for non-display surface");
263     }
264 
265     return tcu::TestStatus::pass("Pass");
266 }
267 
createSurfaceCustomAllocatorTest(Context & context,Type wsiType)268 tcu::TestStatus createSurfaceCustomAllocatorTest(Context &context, Type wsiType)
269 {
270     AllocationCallbackRecorder allocationRecorder(getSystemAllocator());
271     tcu::TestLog &log = context.getTestContext().getLog();
272 
273     {
274         const InstanceHelper instHelper(context, wsiType, allocationRecorder.getCallbacks());
275         const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
276         const Unique<VkSurfaceKHR> surface(
277             createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(),
278                           context.getTestContext().getCommandLine(), allocationRecorder.getCallbacks()));
279 
280         if (!validateAndLog(log, allocationRecorder,
281                             (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) | (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
282             return tcu::TestStatus::fail("Detected invalid system allocation callback");
283     }
284 
285     if (!validateAndLog(log, allocationRecorder, 0u))
286         return tcu::TestStatus::fail("Detected invalid system allocation callback");
287 
288     if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
289         return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
290     else
291         return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
292 }
293 
createSurfaceSimulateOOMTest(Context & context,Type wsiType)294 tcu::TestStatus createSurfaceSimulateOOMTest(Context &context, Type wsiType)
295 {
296     tcu::TestLog &log = context.getTestContext().getLog();
297 
298     for (uint32_t numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
299     {
300         AllocationCallbackRecorder allocationRecorder(getSystemAllocator());
301         DeterministicFailAllocator failingAllocator(allocationRecorder.getCallbacks(),
302                                                     DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0);
303         bool gotOOM = false;
304 
305         log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding"
306             << TestLog::EndMessage;
307 
308         try
309         {
310             const InstanceHelper instHelper(context, wsiType, failingAllocator.getCallbacks());
311 
312             // OOM is not simulated for VkInstance as we don't want to spend time
313             // testing OOM paths inside instance creation.
314             failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
315 
316             const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
317             const Unique<VkSurfaceKHR> surface(
318                 createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(),
319                               context.getTestContext().getCommandLine(), failingAllocator.getCallbacks()));
320 
321             if (!validateAndLog(log, allocationRecorder,
322                                 (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
323                                     (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
324                 return tcu::TestStatus::fail("Detected invalid system allocation callback");
325         }
326         catch (const OutOfMemoryError &e)
327         {
328             log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
329             gotOOM = true;
330         }
331 
332         if (!validateAndLog(log, allocationRecorder, 0u))
333             return tcu::TestStatus::fail("Detected invalid system allocation callback");
334 
335         if (!gotOOM)
336         {
337             log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
338 
339             if (numPassingAllocs == 0)
340                 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
341             else
342                 return tcu::TestStatus::pass("OOM simulation completed");
343         }
344     }
345 
346     return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
347 }
348 
getNumQueueFamilies(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)349 uint32_t getNumQueueFamilies(const InstanceInterface &vki, VkPhysicalDevice physicalDevice)
350 {
351     uint32_t numFamilies = 0;
352 
353     vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
354 
355     return numFamilies;
356 }
357 
querySurfaceSupportTest(Context & context,Type wsiType)358 tcu::TestStatus querySurfaceSupportTest(Context &context, Type wsiType)
359 {
360     tcu::TestLog &log = context.getTestContext().getLog();
361     tcu::ResultCollector results(log);
362 
363     const InstanceHelper instHelper(context, wsiType);
364     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
365     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
366                                                      native.getWindow(), context.getTestContext().getCommandLine()));
367     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
368 
369     // On Android surface must be supported by all devices and queue families
370     const bool expectSupportedOnAll = wsiType == TYPE_ANDROID;
371 
372     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
373     {
374         const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
375         const uint32_t numQueueFamilies       = getNumQueueFamilies(instHelper.vki, physicalDevice);
376 
377         for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
378         {
379             const VkBool32 isSupported =
380                 getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
381 
382             log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
383                 << (isSupported == VK_FALSE ? "NOT " : "") << "supported" << TestLog::EndMessage;
384 
385             if (expectSupportedOnAll && !isSupported)
386                 results.fail("Surface must be supported by all devices and queue families");
387         }
388     }
389 
390     return tcu::TestStatus(results.getResult(), results.getMessage());
391 }
392 
queryPresentationSupportTest(Context & context,Type wsiType)393 tcu::TestStatus queryPresentationSupportTest(Context &context, Type wsiType)
394 {
395     // There is no implementation of getPhysicalDevicePresentationSupport for DRM.
396     if (wsiType == TYPE_DIRECT_DRM)
397     {
398         TCU_THROW(NotSupportedError, "No presentation support query for Drm.");
399     }
400 
401     tcu::TestLog &log = context.getTestContext().getLog();
402     tcu::ResultCollector results(log);
403 
404     const InstanceHelper instHelper(context, wsiType);
405     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
406     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
407                                                      native.getWindow(), context.getTestContext().getCommandLine()));
408     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
409 
410     native.getDisplay();
411     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
412     {
413         const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
414         const uint32_t numQueueFamilies       = getNumQueueFamilies(instHelper.vki, physicalDevice);
415 
416         for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
417         {
418             VkBool32 isPresentationSupported = getPhysicalDevicePresentationSupport(
419                 instHelper.vki, physicalDevice, queueFamilyNdx, wsiType, native.getDisplay());
420             VkBool32 isSurfaceSupported =
421                 getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
422 
423             log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx
424                 << ": presentation " << (isPresentationSupported == VK_FALSE ? "NOT " : "") << "supported. Surface "
425                 << (isSurfaceSupported == VK_FALSE ? "NOT " : "") << "supported." << TestLog::EndMessage;
426 
427             if (isPresentationSupported != isSurfaceSupported)
428                 results.fail("Presentation support is different from surface support");
429         }
430     }
431 
432     return tcu::TestStatus(results.getResult(), results.getMessage());
433 }
434 
isSupportedByAnyQueue(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)435 bool isSupportedByAnyQueue(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
436 {
437     const uint32_t numQueueFamilies = getNumQueueFamilies(vki, physicalDevice);
438 
439     for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
440     {
441         if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
442             return true;
443     }
444 
445     return false;
446 }
447 
validateSurfaceCapabilities(tcu::ResultCollector & results,const VkSurfaceCapabilitiesKHR & capabilities)448 void validateSurfaceCapabilities(tcu::ResultCollector &results, const VkSurfaceCapabilitiesKHR &capabilities)
449 {
450     results.check(capabilities.minImageCount > 0, "minImageCount must be larger than 0");
451 
452     results.check(capabilities.minImageExtent.width > 0 && capabilities.minImageExtent.height > 0,
453                   "minImageExtent dimensions must be larger than 0");
454 
455     results.check(capabilities.maxImageExtent.width > 0 && capabilities.maxImageExtent.height > 0,
456                   "maxImageExtent dimensions must be larger than 0");
457 
458     results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
459                       capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
460                   "maxImageExtent must be larger or equal to minImageExtent");
461 
462     if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
463         capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
464     {
465         results.check(capabilities.currentExtent.width > 0 && capabilities.currentExtent.height > 0,
466                       "currentExtent dimensions must be larger than 0");
467 
468         results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width,
469                                   capabilities.maxImageExtent.width) &&
470                           de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height,
471                                       capabilities.maxImageExtent.height),
472                       "currentExtent is not in supported extent limits");
473     }
474 
475     results.check(capabilities.maxImageArrayLayers > 0, "maxImageArrayLayers must be larger than 0");
476 
477     results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
478                   "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
479 
480     results.check(capabilities.supportedTransforms != 0, "At least one transform must be supported");
481 
482     results.check(dePop32(capabilities.currentTransform) != 0, "Invalid currentTransform");
483 
484     results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
485                   "currentTransform is not supported by surface");
486 
487     results.check(capabilities.supportedCompositeAlpha != 0, "At least one alpha mode must be supported");
488 }
489 
querySurfaceCapabilitiesTest(Context & context,Type wsiType)490 tcu::TestStatus querySurfaceCapabilitiesTest(Context &context, Type wsiType)
491 {
492     tcu::TestLog &log = context.getTestContext().getLog();
493     tcu::ResultCollector results(log);
494 
495     const InstanceHelper instHelper(context, wsiType);
496     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
497     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
498                                                      native.getWindow(), context.getTestContext().getCommandLine()));
499     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
500 
501     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
502     {
503         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
504         {
505             const VkSurfaceCapabilitiesKHR capabilities =
506                 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
507 
508             log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
509 
510             validateSurfaceCapabilities(results, capabilities);
511         }
512         // else skip query as surface is not supported by the device
513     }
514 
515     return tcu::TestStatus(results.getResult(), results.getMessage());
516 }
517 
querySurfaceCapabilities2Test(Context & context,Type wsiType)518 tcu::TestStatus querySurfaceCapabilities2Test(Context &context, Type wsiType)
519 {
520     tcu::TestLog &log = context.getTestContext().getLog();
521     tcu::ResultCollector results(log);
522 
523     const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
524     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
525     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
526                                                      native.getWindow(), context.getTestContext().getCommandLine()));
527     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
528 
529     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
530     {
531         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
532         {
533             const VkSurfaceCapabilitiesKHR refCapabilities =
534                 getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
535             VkSurfaceCapabilities2KHR extCapabilities;
536 
537             deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
538             extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
539             extCapabilities.pNext = DE_NULL;
540 
541             {
542                 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
543                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, *surface};
544                 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
545 
546                 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
547 
548                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx],
549                                                                                  &surfaceInfo, &extCapabilities));
550 
551                 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == true,
552                               "Driver wrote into input struct");
553             }
554 
555             results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
556                               extCapabilities.pNext == DE_NULL,
557                           "sType/pNext modified");
558 
559             if (refCapabilities != extCapabilities.surfaceCapabilities)
560             {
561                 log << TestLog::Message << "Device " << deviceNdx << ": expected " << refCapabilities << ", got "
562                     << extCapabilities.surfaceCapabilities << TestLog::EndMessage;
563                 results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
564             }
565         }
566     }
567 
568     return tcu::TestStatus(results.getResult(), results.getMessage());
569 }
570 
querySurfaceProtectedCapabilitiesTest(Context & context,Type wsiType)571 tcu::TestStatus querySurfaceProtectedCapabilitiesTest(Context &context, Type wsiType)
572 {
573     tcu::TestLog &log = context.getTestContext().getLog();
574     tcu::ResultCollector results(log);
575 
576     vector<string> requiredExtensions;
577     requiredExtensions.push_back("VK_KHR_get_surface_capabilities2");
578     requiredExtensions.push_back("VK_KHR_surface_protected_capabilities");
579     const InstanceHelper instHelper(context, wsiType, requiredExtensions);
580     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
581     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
582                                                      native.getWindow(), context.getTestContext().getCommandLine()));
583     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
584 
585     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
586     {
587         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
588         {
589             VkSurfaceCapabilities2KHR extCapabilities;
590             VkSurfaceProtectedCapabilitiesKHR extProtectedCapabilities;
591 
592             deMemset(&extProtectedCapabilities, 0xcd, sizeof(VkSurfaceProtectedCapabilitiesKHR));
593             extProtectedCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR;
594             extProtectedCapabilities.pNext = DE_NULL;
595 
596             deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
597             extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
598             extCapabilities.pNext = &extProtectedCapabilities;
599 
600             {
601                 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
602                 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {
603                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, *surface};
604 
605                 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
606 
607                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx],
608                                                                                  &surfaceInfo, &extCapabilities));
609 
610                 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == true,
611                               "Driver wrote into input struct");
612             }
613 
614             results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
615                               extCapabilities.pNext == &extProtectedCapabilities,
616                           "sType/pNext modified");
617 
618             results.check(extProtectedCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
619                               extProtectedCapabilities.pNext == DE_NULL,
620                           "sType/pNext modified");
621 
622             results.check(extProtectedCapabilities.supportsProtected == 0 ||
623                               extProtectedCapabilities.supportsProtected == 1,
624                           "supportsProtected ");
625         }
626     }
627 
628     return tcu::TestStatus(results.getResult(), results.getMessage());
629 }
630 
validateSurfaceFormats(tcu::ResultCollector & results,Type wsiType,const vector<VkSurfaceFormatKHR> & formats)631 void validateSurfaceFormats(tcu::ResultCollector &results, Type wsiType, const vector<VkSurfaceFormatKHR> &formats)
632 {
633     const VkSurfaceFormatKHR *requiredFormats = DE_NULL;
634     size_t numRequiredFormats                 = 0;
635 
636     if (wsiType == TYPE_ANDROID)
637     {
638         static const VkSurfaceFormatKHR s_androidFormats[] = {
639             {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
640             {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
641             {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
642 
643         requiredFormats    = &s_androidFormats[0];
644         numRequiredFormats = DE_LENGTH_OF_ARRAY(s_androidFormats);
645     }
646 
647     for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
648     {
649         const VkSurfaceFormatKHR &requiredFormat = requiredFormats[ndx];
650 
651         if (!de::contains(formats.begin(), formats.end(), requiredFormat))
652             results.fail(de::toString(requiredFormat) + " not supported");
653     }
654 
655     // Check that there are no duplicates
656     for (size_t ndx = 1; ndx < formats.size(); ++ndx)
657     {
658         if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
659             results.fail("Found duplicate entry " + de::toString(formats[ndx]));
660     }
661 }
662 
querySurfaceFormatsTest(Context & context,Type wsiType)663 tcu::TestStatus querySurfaceFormatsTest(Context &context, Type wsiType)
664 {
665     tcu::TestLog &log = context.getTestContext().getLog();
666     tcu::ResultCollector results(log);
667 
668     const InstanceHelper instHelper(context, wsiType);
669     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
670     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
671                                                      native.getWindow(), context.getTestContext().getCommandLine()));
672     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
673 
674     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
675     {
676         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
677         {
678             uint32_t numFormats = 0;
679 
680             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
681                                                                        &numFormats, DE_NULL));
682 
683             std::vector<VkSurfaceFormatKHR> formats(numFormats + 1);
684 
685             if (numFormats > 0)
686             {
687                 const uint32_t numFormatsOrig = numFormats;
688 
689                 // check if below call properly overwrites formats count
690                 numFormats++;
691 
692                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
693                                                                            &numFormats, &formats[0]));
694 
695                 if (numFormats != numFormatsOrig)
696                     results.fail("Format count changed between calls");
697             }
698 
699             formats.pop_back();
700 
701             log << TestLog::Message << "Device " << deviceNdx << ": "
702                 << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
703 
704             validateSurfaceFormats(results, wsiType, formats);
705             CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx],
706                                                                 *surface, formats.size());
707         }
708         // else skip query as surface is not supported by the device
709     }
710 
711     return tcu::TestStatus(results.getResult(), results.getMessage());
712 }
713 
querySurfaceFormatsTestSurfaceless(Context & context,Type wsiType)714 tcu::TestStatus querySurfaceFormatsTestSurfaceless(Context &context, Type wsiType)
715 {
716     tcu::TestLog &log = context.getTestContext().getLog();
717     tcu::ResultCollector results(log);
718 
719     const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_GOOGLE_surfaceless_query")));
720     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
721     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
722                                                      native.getWindow(), context.getTestContext().getCommandLine()));
723     const VkSurfaceKHR nullSurface                 = 0;
724     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
725 
726     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
727     {
728         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
729         {
730             uint32_t numFormatsSurface = 0;
731             uint32_t numFormatsNull    = 0;
732 
733             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
734                                                                        &numFormatsSurface, DE_NULL));
735             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface,
736                                                                        &numFormatsNull, DE_NULL));
737 
738             if (numFormatsSurface != numFormatsNull)
739             {
740                 results.fail("Number of formats do not match");
741                 continue;
742             }
743 
744             std::vector<VkSurfaceFormatKHR> formatsSurface(numFormatsSurface + 1);
745             std::vector<VkSurfaceFormatKHR> formatsNull(numFormatsSurface + 1);
746 
747             if (numFormatsSurface > 0)
748             {
749                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface,
750                                                                            &numFormatsSurface, &formatsSurface[0]));
751                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface,
752                                                                            &numFormatsSurface, &formatsNull[0]));
753             }
754 
755             formatsSurface.pop_back();
756             formatsNull.pop_back();
757 
758             for (uint32_t i = 0; i < numFormatsSurface; i++)
759             {
760                 if (formatsSurface[i].colorSpace != formatsNull[i].colorSpace ||
761                     formatsSurface[i].format != formatsNull[i].format)
762                 {
763                     results.fail("Surface formats do not match");
764                 }
765             }
766         }
767     }
768 
769     return tcu::TestStatus(results.getResult(), results.getMessage());
770 }
771 
querySurfaceFormats2Test(Context & context,Type wsiType)772 tcu::TestStatus querySurfaceFormats2Test(Context &context, Type wsiType)
773 {
774     tcu::TestLog &log = context.getTestContext().getLog();
775     tcu::ResultCollector results(log);
776 
777     const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
778     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
779     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
780                                                      native.getWindow(), context.getTestContext().getCommandLine()));
781     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
782 
783     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
784     {
785         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
786         {
787             const vector<VkSurfaceFormatKHR> refFormats =
788                 getPhysicalDeviceSurfaceFormats(instHelper.vki, physicalDevices[deviceNdx], *surface);
789             const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
790                                                                  DE_NULL, *surface};
791             uint32_t numFormats                               = 0;
792 
793             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
794                                                                         &numFormats, DE_NULL));
795 
796             if ((size_t)numFormats != refFormats.size())
797                 results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
798 
799             if (numFormats > 0)
800             {
801                 vector<VkSurfaceFormat2KHR> formats(numFormats + 1);
802 
803                 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
804                 {
805                     formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
806                     formats[ndx].pNext = DE_NULL;
807                 }
808 
809                 const uint32_t numFormatsOrig = numFormats;
810 
811                 // check if below call properly overwrites formats count
812                 numFormats++;
813 
814                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
815                                                                             &numFormats, &formats[0]));
816 
817                 if ((size_t)numFormats != numFormatsOrig)
818                     results.fail("Format count changed between calls");
819 
820                 formats.pop_back();
821 
822                 {
823                     vector<VkSurfaceFormatKHR> extFormats(formats.size());
824 
825                     for (size_t ndx = 0; ndx < formats.size(); ++ndx)
826                     {
827                         results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
828                                           formats[ndx].pNext == DE_NULL,
829                                       "sType/pNext modified");
830                         extFormats[ndx] = formats[ndx].surfaceFormat;
831                     }
832 
833                     for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
834                     {
835                         if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
836                             results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
837                     }
838                 }
839 
840                 // Check VK_INCOMPLETE
841                 {
842                     vector<VkSurfaceFormat2KHR> formatsClone(formats);
843                     uint32_t numToSupply = numFormats / 2;
844                     VkResult queryResult;
845 
846                     ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
847 
848                     queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(
849                         physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
850 
851                     results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
852                     results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
853                                   "Driver wrote past last element");
854 
855                     for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
856                     {
857                         results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
858                                           formatsClone[ndx].pNext == DE_NULL &&
859                                           formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
860                                       "Returned element " + de::toString(ndx) + " is different");
861                     }
862                 }
863             }
864         }
865         // else skip query as surface is not supported by the device
866     }
867 
868     return tcu::TestStatus(results.getResult(), results.getMessage());
869 }
870 
validateSurfacePresentModes(tcu::ResultCollector & results,Type wsiType,const vector<VkPresentModeKHR> & modes)871 void validateSurfacePresentModes(tcu::ResultCollector &results, Type wsiType, const vector<VkPresentModeKHR> &modes)
872 {
873     results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
874                   "VK_PRESENT_MODE_FIFO_KHR is not supported");
875 
876     if (wsiType == TYPE_ANDROID)
877         results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
878                       "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
879 }
880 
querySurfacePresentModes2Test(Context & context,Type wsiType)881 tcu::TestStatus querySurfacePresentModes2Test(Context &context, Type wsiType)
882 {
883     tcu::TestLog &log = context.getTestContext().getLog();
884     tcu::ResultCollector results(log);
885 
886     const InstanceHelper instHelper(context, wsiType);
887     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
888     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
889                                                      native.getWindow(), context.getTestContext().getCommandLine()));
890     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
891     const std::vector<VkExtensionProperties> deviceExtensions(
892         enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
893     if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
894         TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
895 
896     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
897     {
898         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
899         {
900             const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
901                                                                  DE_NULL, *surface};
902 
903             uint32_t numModesRef = 0;
904             uint32_t numModes    = 0;
905 
906             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
907                                                                             &numModesRef, DE_NULL));
908             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo,
909                                                                              &numModes, DE_NULL));
910 
911             if (numModes != numModesRef)
912             {
913                 results.fail("Number of modes do not match");
914                 continue;
915             }
916 
917             vector<VkPresentModeKHR> modes(numModes + 1);
918 
919             if (numModes > 0)
920             {
921                 const uint32_t numModesOrig = numModes;
922 
923                 // check if below call properly overwrites mode count
924                 numModes++;
925 
926                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx],
927                                                                                  &surfaceInfo, &numModes, &modes[0]));
928 
929                 if ((size_t)numModes != numModesOrig)
930                     TCU_FAIL("Mode count changed between calls");
931             }
932 
933             modes.pop_back();
934 
935             log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end())
936                 << TestLog::EndMessage;
937 
938             validateSurfacePresentModes(results, wsiType, modes);
939             if (numModes > 1)
940             {
941                 numModes /= 2;
942                 vk::VkResult res = instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(
943                     physicalDevices[deviceNdx], &surfaceInfo, &numModes, &modes[0]);
944                 if (res != VK_INCOMPLETE)
945                     TCU_FAIL("Failed to fetch incomplete results");
946             }
947         }
948         // else skip query as surface is not supported by the device
949     }
950 
951     return tcu::TestStatus(results.getResult(), results.getMessage());
952 }
953 
querySurfacePresentModes2TestSurfaceless(Context & context,Type wsiType)954 tcu::TestStatus querySurfacePresentModes2TestSurfaceless(Context &context, Type wsiType)
955 {
956     tcu::TestLog &log = context.getTestContext().getLog();
957     tcu::ResultCollector results(log);
958 
959     const std::string extensionName = "VK_GOOGLE_surfaceless_query";
960     const InstanceHelper instHelper(context, wsiType, vector<string>(1, extensionName), DE_NULL);
961     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
962     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
963                                                      native.getWindow(), context.getTestContext().getCommandLine()));
964     const VkSurfaceKHR nullSurface                 = 0;
965     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
966     const std::vector<vk::VkExtensionProperties> deviceExtensions(
967         enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
968     const vector<VkPresentModeKHR> validPresentModes{VK_PRESENT_MODE_FIFO_KHR,
969                                                      VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
970                                                      VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR};
971 
972     if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
973         return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED, "Extension VK_EXT_full_screen_exclusive not supported");
974 
975     // Ensure "VK_GOOGLE_surfaceless_query" extension's spec version is at least 2
976     {
977         uint32_t propertyCount = 0u;
978         std::vector<vk::VkExtensionProperties> extensionsProperties;
979         vk::VkResult extensionResult;
980 
981         extensionResult =
982             context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
983         if (extensionResult != vk::VK_SUCCESS)
984             return tcu::TestStatus(QP_TEST_RESULT_FAIL,
985                                    "Failed to retrieve spec version for extension " + extensionName);
986 
987         extensionsProperties.resize(propertyCount);
988 
989         extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(
990             DE_NULL, &propertyCount, extensionsProperties.data());
991         if (extensionResult != vk::VK_SUCCESS)
992             return tcu::TestStatus(QP_TEST_RESULT_FAIL,
993                                    "Failed to retrieve spec version for extension " + extensionName);
994 
995         for (const auto &property : extensionsProperties)
996         {
997             if (property.extensionName == extensionName)
998             {
999                 if (property.specVersion < 2)
1000                     return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED,
1001                                            "VK_GOOGLE_surfaceless_query is version 1. Need version 2 or higher");
1002                 break;
1003             }
1004         }
1005     }
1006 
1007     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1008     {
1009         const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1010                                                                  DE_NULL, nullSurface};
1011         uint32_t numModesNull                                 = 0u;
1012 
1013         VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo,
1014                                                                          &numModesNull, DE_NULL));
1015 
1016         if (numModesNull == 0u)
1017             continue;
1018 
1019         vector<VkPresentModeKHR> modesNull(numModesNull);
1020 
1021         VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo,
1022                                                                          &numModesNull, &modesNull[0]));
1023 
1024         for (uint32_t i = 0; i < modesNull.size(); i++)
1025         {
1026             if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1027             {
1028                 std::string error_string =
1029                     std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1030                 results.fail(error_string);
1031                 break;
1032             }
1033         }
1034     }
1035 
1036     return tcu::TestStatus(results.getResult(), results.getMessage());
1037 }
1038 
querySurfaceFormats2TestSurfaceless(Context & context,Type wsiType)1039 tcu::TestStatus querySurfaceFormats2TestSurfaceless(Context &context, Type wsiType)
1040 {
1041     tcu::TestLog &log = context.getTestContext().getLog();
1042     tcu::ResultCollector results(log);
1043 
1044     const vector<std::string> extensions({"VK_KHR_get_surface_capabilities2", "VK_GOOGLE_surfaceless_query"});
1045     const InstanceHelper instHelper(context, wsiType, extensions);
1046     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1047     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1048                                                      native.getWindow(), context.getTestContext().getCommandLine()));
1049     const VkSurfaceKHR nullSurface                 = 0;
1050     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1051 
1052     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1053     {
1054         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1055         {
1056             const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1057                                                                  DE_NULL, *surface};
1058             const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo = {
1059                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, DE_NULL, nullSurface};
1060             uint32_t numFormatsSurface = 0;
1061             uint32_t numFormatsNull    = 0;
1062 
1063             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
1064                                                                         &numFormatsSurface, DE_NULL));
1065             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo,
1066                                                                         &numFormatsNull, DE_NULL));
1067 
1068             if (numFormatsSurface != numFormatsNull)
1069             {
1070                 results.fail("Number of formats do not match");
1071                 continue;
1072             }
1073 
1074             if (numFormatsSurface > 0)
1075             {
1076                 vector<VkSurfaceFormat2KHR> formatsSurface(numFormatsSurface + 1);
1077                 vector<VkSurfaceFormat2KHR> formatsNull(numFormatsSurface + 1);
1078 
1079                 for (size_t ndx = 0; ndx < formatsSurface.size(); ++ndx)
1080                 {
1081                     formatsSurface[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1082                     formatsSurface[ndx].pNext = DE_NULL;
1083                     formatsNull[ndx].sType    = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1084                     formatsNull[ndx].pNext    = DE_NULL;
1085                 }
1086 
1087                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo,
1088                                                                             &numFormatsSurface, &formatsSurface[0]));
1089                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(
1090                     physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsSurface, &formatsNull[0]));
1091 
1092                 formatsSurface.pop_back();
1093                 formatsNull.pop_back();
1094 
1095                 for (uint32_t i = 0; i < numFormatsSurface; i++)
1096                 {
1097                     if (formatsSurface[i].surfaceFormat != formatsNull[i].surfaceFormat)
1098                     {
1099                         results.fail("Surface formats do not match");
1100                     }
1101                 }
1102             }
1103         }
1104     }
1105 
1106     return tcu::TestStatus(results.getResult(), results.getMessage());
1107 }
1108 
querySurfacePresentModesTest(Context & context,Type wsiType)1109 tcu::TestStatus querySurfacePresentModesTest(Context &context, Type wsiType)
1110 {
1111     tcu::TestLog &log = context.getTestContext().getLog();
1112     tcu::ResultCollector results(log);
1113 
1114     const InstanceHelper instHelper(context, wsiType);
1115     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1116     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1117                                                      native.getWindow(), context.getTestContext().getCommandLine()));
1118     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1119 
1120     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1121     {
1122         if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1123         {
1124             uint32_t numModes = 0;
1125 
1126             VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
1127                                                                             &numModes, DE_NULL));
1128 
1129             vector<VkPresentModeKHR> modes(numModes + 1);
1130 
1131             if (numModes > 0)
1132             {
1133                 const uint32_t numModesOrig = numModes;
1134 
1135                 // check if below call properly overwrites mode count
1136                 numModes++;
1137 
1138                 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface,
1139                                                                                 &numModes, &modes[0]));
1140 
1141                 if ((size_t)numModes != numModesOrig)
1142                     TCU_FAIL("Mode count changed between calls");
1143             }
1144 
1145             modes.pop_back();
1146 
1147             log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end())
1148                 << TestLog::EndMessage;
1149 
1150             validateSurfacePresentModes(results, wsiType, modes);
1151             CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(
1152                 results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
1153         }
1154         // else skip query as surface is not supported by the device
1155     }
1156 
1157     return tcu::TestStatus(results.getResult(), results.getMessage());
1158 }
1159 
checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,tcu::ResultCollector & result)1160 void checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver &vk, VkPhysicalDevice physicalDevice,
1161                                                     VkSurfaceKHR surface, tcu::ResultCollector &result)
1162 {
1163     const VkSurfaceKHR nullSurface = DE_NULL;
1164 
1165     if (isSupportedByAnyQueue(vk, physicalDevice, surface))
1166     {
1167         uint32_t numModesSurface = 0;
1168         uint32_t numModesNull    = 0;
1169 
1170         VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, DE_NULL));
1171         VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1172 
1173         if (numModesNull == 0)
1174             return;
1175 
1176         // Actual surface needs to have at least the amount of modes that null surface has
1177         if (numModesSurface < numModesNull)
1178         {
1179             result.fail("Number of modes does not match");
1180             return;
1181         }
1182 
1183         vector<VkPresentModeKHR> modesSurface(numModesSurface);
1184         vector<VkPresentModeKHR> modesNull(numModesNull);
1185 
1186         VK_CHECK(
1187             vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, &modesSurface[0]));
1188         VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1189 
1190         // All modes present in null surface should also be present in actual surface
1191         for (uint32_t i = 0; i < modesNull.size(); i++)
1192         {
1193             if (std::find(modesSurface.begin(), modesSurface.end(), modesNull[i]) == modesSurface.end())
1194             {
1195                 std::string error_string =
1196                     std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1197                 result.fail(error_string);
1198                 break;
1199             }
1200         }
1201     }
1202 }
1203 
checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,tcu::ResultCollector & result)1204 void checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver &vk, VkPhysicalDevice physicalDevice,
1205                                           tcu::ResultCollector &result)
1206 {
1207     const VkSurfaceKHR nullSurface = DE_NULL;
1208     const vector<VkPresentModeKHR> validPresentModes{VK_PRESENT_MODE_FIFO_KHR,
1209                                                      VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
1210                                                      VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR};
1211 
1212     uint32_t numModesNull = 0;
1213     VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1214 
1215     if (numModesNull == 0u)
1216         return;
1217 
1218     vector<VkPresentModeKHR> modesNull(numModesNull);
1219 
1220     VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1221 
1222     for (uint32_t i = 0; i < modesNull.size(); i++)
1223     {
1224         if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1225         {
1226             std::string error_string =
1227                 std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1228             result.fail(error_string);
1229             break;
1230         }
1231     }
1232 }
1233 
querySurfacePresentModesTestSurfaceless(Context & context,Type wsiType)1234 tcu::TestStatus querySurfacePresentModesTestSurfaceless(Context &context, Type wsiType)
1235 {
1236     tcu::TestLog &log = context.getTestContext().getLog();
1237     tcu::ResultCollector results(log);
1238 
1239     const std::string extensionName = "VK_GOOGLE_surfaceless_query";
1240     const InstanceHelper instHelper(context, wsiType, vector<string>(1, extensionName), DE_NULL);
1241     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1242     const Unique<vk::VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType,
1243                                                          native.getDisplay(), native.getWindow(),
1244                                                          context.getTestContext().getCommandLine()));
1245 
1246     uint32_t extensionVersion = 1u;
1247 
1248     // Get "VK_GOOGLE_surfaceless_query" extension's spec version
1249     {
1250         uint32_t propertyCount = 0u;
1251         std::vector<vk::VkExtensionProperties> extensionsProperties;
1252         vk::VkResult extensionResult;
1253 
1254         extensionResult =
1255             context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
1256         if (extensionResult != vk::VK_SUCCESS)
1257             return tcu::TestStatus(QP_TEST_RESULT_FAIL,
1258                                    "Failed to retrieve spec version for extension " + extensionName);
1259 
1260         extensionsProperties.resize(propertyCount);
1261 
1262         extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(
1263             DE_NULL, &propertyCount, extensionsProperties.data());
1264         if (extensionResult != vk::VK_SUCCESS)
1265             return tcu::TestStatus(QP_TEST_RESULT_FAIL,
1266                                    "Failed to retrieve spec version for extension " + extensionName);
1267 
1268         for (const auto &property : extensionsProperties)
1269         {
1270             if (property.extensionName == extensionName)
1271             {
1272                 extensionVersion = property.specVersion;
1273                 break;
1274             }
1275         }
1276     }
1277 
1278     log << TestLog::Message << "Checking spec version " << extensionVersion << " for VK_GOOGLE_surfaceless_query"
1279         << TestLog::EndMessage;
1280 
1281     const bool checkDeprecatedVersion              = extensionVersion < 2;
1282     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1283     for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1284     {
1285         if (checkDeprecatedVersion)
1286             checkDeprecatedExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], *surface,
1287                                                            results);
1288         else
1289             checkExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], results);
1290     }
1291 
1292     return tcu::TestStatus(results.getResult(), results.getMessage());
1293 }
1294 
queryDevGroupSurfacePresentCapabilitiesTest(Context & context,Type wsiType)1295 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest(Context &context, Type wsiType)
1296 {
1297     tcu::TestLog &log = context.getTestContext().getLog();
1298     const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1299     const float queuePriority       = 1.0f;
1300     const tcu::CommandLine &cmdLine = context.getTestContext().getCommandLine();
1301     const uint32_t devGroupIdx      = cmdLine.getVKDeviceGroupId() - 1;
1302     const uint32_t deviceIdx        = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1303     const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1304     const VkDeviceGroupPresentModeFlagsKHR maxValidFlag =
1305         VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1306         VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1307     uint8_t buffer[sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
1308     uint32_t queueFamilyIndex = 0;
1309     VkDeviceGroupPresentCapabilitiesKHR *presentCapabilities;
1310     std::vector<const char *> deviceExtensions;
1311 
1312     if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1313         deviceExtensions.push_back("VK_KHR_device_group");
1314     deviceExtensions.push_back("VK_KHR_swapchain");
1315 
1316     for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1317     {
1318         if (!context.isDeviceFunctionalitySupported(deviceExtensions[ndx]))
1319             TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1320     }
1321 
1322     const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps =
1323         enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1324 
1325     const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(
1326         instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1327     for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1328     {
1329         if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1330             queueFamilyIndex = (uint32_t)queueNdx;
1331     }
1332     const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
1333         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1334         DE_NULL,                                    //pNext
1335         (VkDeviceQueueCreateFlags)0u,               //flags
1336         queueFamilyIndex,                           //queueFamilyIndex;
1337         1u,                                         //queueCount;
1338         &queuePriority,                             //pQueuePriorities;
1339     };
1340     const VkDeviceGroupDeviceCreateInfo deviceGroupInfo = {
1341         VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1342         DE_NULL,                                               //pNext
1343         deviceGroupProps[devGroupIdx].physicalDeviceCount,     //physicalDeviceCount
1344         deviceGroupProps[devGroupIdx].physicalDevices          //physicalDevices
1345     };
1346 
1347     const VkDeviceCreateInfo deviceCreateInfo = {
1348         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,                        //sType;
1349         &deviceGroupInfo,                                            //pNext;
1350         (VkDeviceCreateFlags)0u,                                     //flags
1351         1,                                                           //queueRecordCount;
1352         &deviceQueueCreateInfo,                                      //pRequestedQueues;
1353         0,                                                           //layerCount;
1354         DE_NULL,                                                     //ppEnabledLayerNames;
1355         uint32_t(deviceExtensions.size()),                           //enabledExtensionCount;
1356         (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1357         DE_NULL,                                                     //pEnabledFeatures;
1358     };
1359 
1360     Move<VkDevice> deviceGroup =
1361         createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
1362                            context.getPlatformInterface(), instHelper.instance, instHelper.vki,
1363                            deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1364     const DeviceDriver vk(context.getPlatformInterface(), instHelper.instance, *deviceGroup,
1365                           context.getUsedApiVersion(), context.getTestContext().getCommandLine());
1366 
1367     presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR *>(buffer);
1368     deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1369     presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
1370     presentCapabilities->pNext = DE_NULL;
1371     VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
1372 
1373     // Guard check
1374     for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1375     {
1376         if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
1377         {
1378             log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid"
1379                 << TestLog::EndMessage;
1380             return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
1381         }
1382     }
1383 
1384     // Check each physical device can present on itself
1385     for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE; physDevIdx++)
1386     {
1387         if (presentCapabilities->presentMask[physDevIdx])
1388             if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
1389                 return tcu::TestStatus::fail(
1390                     "deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
1391     }
1392 
1393     // Check if flags are valid
1394     if ((!(presentCapabilities->modes & requiredFlag)) || presentCapabilities->modes > maxValidFlag)
1395         return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
1396 
1397     return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
1398 }
1399 
queryDevGroupSurfacePresentModesTest(Context & context,Type wsiType)1400 tcu::TestStatus queryDevGroupSurfacePresentModesTest(Context &context, Type wsiType)
1401 {
1402     tcu::TestLog &log = context.getTestContext().getLog();
1403     tcu::ResultCollector results(log);
1404     const InstanceHelper instHelper(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1405     const NativeObjects native(context, instHelper.supportedExtensions, wsiType);
1406     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(),
1407                                                      native.getWindow(), context.getTestContext().getCommandLine()));
1408     const float queuePriority       = 1.0f;
1409     const tcu::CommandLine &cmdLine = context.getTestContext().getCommandLine();
1410     const uint32_t devGroupIdx      = cmdLine.getVKDeviceGroupId() - 1;
1411     const uint32_t deviceIdx        = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1412     const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1413     const VkDeviceGroupPresentModeFlagsKHR maxValidFlag =
1414         VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1415         VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR | VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1416     VkResult result = VK_SUCCESS;
1417     uint8_t buffer[sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
1418     uint32_t rectCount           = 0;
1419     uint32_t incompleteRectCount = 0;
1420     uint32_t queueFamilyIndex    = 0;
1421     VkRect2D *presentRectangles;
1422     VkDeviceGroupPresentModeFlagsKHR *presentModeFlags;
1423     vector<uint8_t> rectanglesBuffer;
1424     VkPhysicalDevice physicalDevice       = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1425     const Extensions &supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1426     std::vector<const char *> deviceExtensions;
1427 
1428     if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1429         deviceExtensions.push_back("VK_KHR_device_group");
1430     deviceExtensions.push_back("VK_KHR_swapchain");
1431 
1432     for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1433     {
1434         if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1435             TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1436     }
1437 
1438     const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps =
1439         enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1440     const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(
1441         instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1442     for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1443     {
1444         if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1445             queueFamilyIndex = (uint32_t)queueNdx;
1446     }
1447     const VkDeviceQueueCreateInfo deviceQueueCreateInfo = {
1448         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1449         DE_NULL,                                    //pNext
1450         (VkDeviceQueueCreateFlags)0u,               //flags
1451         queueFamilyIndex,                           //queueFamilyIndex;
1452         1u,                                         //queueCount;
1453         &queuePriority,                             //pQueuePriorities;
1454     };
1455     const VkDeviceGroupDeviceCreateInfo deviceGroupInfo = {
1456         VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1457         DE_NULL,                                               //pNext
1458         deviceGroupProps[devGroupIdx].physicalDeviceCount,     //physicalDeviceCount
1459         deviceGroupProps[devGroupIdx].physicalDevices          //physicalDevices
1460     };
1461 
1462     const VkDeviceCreateInfo deviceCreateInfo = {
1463         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,                        //sType;
1464         &deviceGroupInfo,                                            //pNext;
1465         (VkDeviceCreateFlags)0u,                                     //flags
1466         1,                                                           //queueRecordCount;
1467         &deviceQueueCreateInfo,                                      //pRequestedQueues;
1468         0,                                                           //layerCount;
1469         DE_NULL,                                                     //ppEnabledLayerNames;
1470         uint32_t(deviceExtensions.size()),                           //enabledExtensionCount;
1471         (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1472         DE_NULL,                                                     //pEnabledFeatures;
1473     };
1474 
1475     Move<VkDevice> deviceGroup =
1476         createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
1477                            context.getPlatformInterface(), instHelper.instance, instHelper.vki,
1478                            deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1479     const DeviceDriver vk(context.getPlatformInterface(), instHelper.instance, *deviceGroup,
1480                           context.getUsedApiVersion(), context.getTestContext().getCommandLine());
1481     presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR *>(buffer);
1482     deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1483 
1484     VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1485 
1486     // Guard check
1487     for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1488     {
1489         if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1490         {
1491             log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid"
1492                 << TestLog::EndMessage;
1493             return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1494         }
1495     }
1496 
1497     // Check if flags are valid
1498     if ((!(*presentModeFlags & requiredFlag)) || *presentModeFlags > maxValidFlag)
1499         return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1500 
1501     // getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1502     if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1503     {
1504         for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1505         {
1506             VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1507                 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1508             rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1509             presentRectangles = reinterpret_cast<VkRect2D *>(rectanglesBuffer.data());
1510             deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1511 
1512             VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1513                 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1514 
1515             // Guard check
1516             for (int32_t ndx = 0; ndx < GUARD_SIZE; ndx++)
1517             {
1518                 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1519                 {
1520                     log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx
1521                         << " not valid" << TestLog::EndMessage;
1522                     return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1523                 }
1524             }
1525 
1526             // Check rectangles do not overlap
1527             for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1528             {
1529                 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1530                 {
1531                     if (rectIdx1 != rectIdx2)
1532                     {
1533                         uint32_t rectATop  = presentRectangles[rectIdx1].offset.y;
1534                         uint32_t rectALeft = presentRectangles[rectIdx1].offset.x;
1535                         uint32_t rectABottom =
1536                             presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1537                         uint32_t rectARight =
1538                             presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1539 
1540                         uint32_t rectBTop  = presentRectangles[rectIdx2].offset.y;
1541                         uint32_t rectBLeft = presentRectangles[rectIdx2].offset.x;
1542                         uint32_t rectBBottom =
1543                             presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1544                         uint32_t rectBRight =
1545                             presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1546 
1547                         if (rectALeft < rectBRight && rectARight > rectBLeft && rectATop < rectBBottom &&
1548                             rectABottom > rectBTop)
1549                             return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1550                     }
1551                 }
1552             }
1553 
1554             // Check incomplete
1555             incompleteRectCount = rectCount / 2;
1556             result              = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(
1557                 deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount,
1558                 presentRectangles);
1559             results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1560         }
1561     }
1562 
1563     return tcu::TestStatus(results.getResult(), results.getMessage());
1564 }
1565 
createSurfaceInitialSizeTest(Context & context,Type wsiType)1566 tcu::TestStatus createSurfaceInitialSizeTest(Context &context, Type wsiType)
1567 {
1568     tcu::TestLog &log = context.getTestContext().getLog();
1569     tcu::ResultCollector results(log);
1570 
1571     const InstanceHelper instHelper(context, wsiType);
1572 
1573     const UniquePtr<Display> nativeDisplay(NativeObjects::createDisplay(
1574         context.getTestContext().getPlatform().getVulkanPlatform(), instHelper.supportedExtensions, wsiType));
1575 
1576     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1577     const UVec2 sizes[]                            = {UVec2(64, 64), UVec2(124, 119), UVec2(256, 512)};
1578 
1579     DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1580 
1581     for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1582     {
1583         const UVec2 &testSize = sizes[sizeNdx];
1584         const UniquePtr<Window> nativeWindow(NativeObjects::createWindow(*nativeDisplay, tcu::just(testSize)));
1585         const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay,
1586                                                          *nativeWindow, context.getTestContext().getCommandLine()));
1587 
1588         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1589         {
1590             if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1591             {
1592                 const VkSurfaceCapabilitiesKHR capabilities =
1593                     getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1594 
1595                 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1596                 results.check(capabilities.currentExtent.width == testSize.x() &&
1597                                   capabilities.currentExtent.height == testSize.y(),
1598                               "currentExtent " + de::toString(capabilities.currentExtent) +
1599                                   " doesn't match requested size " + de::toString(testSize));
1600             }
1601         }
1602     }
1603 
1604     return tcu::TestStatus(results.getResult(), results.getMessage());
1605 }
1606 
resizeSurfaceTest(Context & context,Type wsiType)1607 tcu::TestStatus resizeSurfaceTest(Context &context, Type wsiType)
1608 {
1609     tcu::TestLog &log = context.getTestContext().getLog();
1610     tcu::ResultCollector results(log);
1611 
1612     const InstanceHelper instHelper(context, wsiType);
1613 
1614     const UniquePtr<Display> nativeDisplay(NativeObjects::createDisplay(
1615         context.getTestContext().getPlatform().getVulkanPlatform(), instHelper.supportedExtensions, wsiType));
1616     UniquePtr<Window> nativeWindow(NativeObjects::createWindow(*nativeDisplay, tcu::Nothing));
1617 
1618     const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1619     const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay,
1620                                                      *nativeWindow, context.getTestContext().getCommandLine()));
1621 
1622     const UVec2 sizes[] = {UVec2(64, 64), UVec2(124, 119), UVec2(256, 512)};
1623 
1624     DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1625 
1626     for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1627     {
1628         const UVec2 testSize = sizes[sizeNdx];
1629 
1630         try
1631         {
1632             nativeWindow->resize(testSize);
1633         }
1634         catch (const tcu::Exception &e)
1635         {
1636             // Make sure all exception types result in a test failure
1637             results.fail(e.getMessage());
1638         }
1639 
1640         for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1641         {
1642             if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1643             {
1644                 const VkSurfaceCapabilitiesKHR capabilities =
1645                     getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1646 
1647                 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1648                 results.check(capabilities.currentExtent.width == testSize.x() &&
1649                                   capabilities.currentExtent.height == testSize.y(),
1650                               "currentExtent " + de::toString(capabilities.currentExtent) +
1651                                   " doesn't match requested size " + de::toString(testSize));
1652             }
1653         }
1654     }
1655 
1656     return tcu::TestStatus(results.getResult(), results.getMessage());
1657 }
1658 
destroyNullHandleSurfaceTest(Context & context,Type wsiType)1659 tcu::TestStatus destroyNullHandleSurfaceTest(Context &context, Type wsiType)
1660 {
1661     const InstanceHelper instHelper(context, wsiType);
1662     const VkSurfaceKHR nullHandle = DE_NULL;
1663 
1664     // Default allocator
1665     instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1666 
1667     // Custom allocator
1668     {
1669         AllocationCallbackRecorder recordingAllocator(getSystemAllocator(), 1u);
1670 
1671         instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1672 
1673         if (recordingAllocator.getNumRecords() != 0u)
1674             return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1675     }
1676 
1677     return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1678 }
1679 
1680 } // namespace
1681 
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1682 void createSurfaceTests(tcu::TestCaseGroup *testGroup, vk::wsi::Type wsiType)
1683 {
1684     const PlatformProperties &platformProperties = getPlatformProperties(wsiType);
1685 
1686     // Create surface
1687     addFunctionCase(testGroup, "create", createSurfaceTest, wsiType);
1688     // Create surface with custom allocator
1689     addFunctionCase(testGroup, "create_custom_allocator", createSurfaceCustomAllocatorTest, wsiType);
1690     // Create surface with simulating OOM
1691     addFunctionCase(testGroup, "create_simulate_oom", createSurfaceSimulateOOMTest, wsiType);
1692     // Query surface support
1693     addFunctionCase(testGroup, "query_support", querySurfaceSupportTest, wsiType);
1694     // Query native presentation support
1695     addFunctionCase(testGroup, "query_presentation_support", queryPresentationSupportTest, wsiType);
1696     // Query surface capabilities
1697     addFunctionCase(testGroup, "query_capabilities", querySurfaceCapabilitiesTest, wsiType);
1698     // Query extended surface capabilities
1699     addFunctionCase(testGroup, "query_capabilities2", querySurfaceCapabilities2Test, wsiType);
1700     // Query protected surface capabilities
1701     addFunctionCase(testGroup, "query_protected_capabilities", querySurfaceProtectedCapabilitiesTest, wsiType);
1702     // Query and check available surface counters
1703     addFunctionCase(testGroup, "query_surface_counters", querySurfaceCounterTest, wsiType);
1704     // Query surface formats
1705     addFunctionCase(testGroup, "query_formats", querySurfaceFormatsTest, wsiType);
1706     // Query extended surface formats
1707     addFunctionCase(testGroup, "query_formats2", querySurfaceFormats2Test, wsiType);
1708     // Query surface present modes
1709     addFunctionCase(testGroup, "query_present_modes", querySurfacePresentModesTest, wsiType);
1710     // Query extended surface present modes
1711     addFunctionCase(testGroup, "query_present_modes2", querySurfacePresentModes2Test, wsiType);
1712     // Query surface present modes capabilities in device groups
1713     addFunctionCase(testGroup, "query_devgroup_present_capabilities", queryDevGroupSurfacePresentCapabilitiesTest,
1714                     wsiType);
1715     // Query surface present modes for device groups
1716     addFunctionCase(testGroup, "query_devgroup_present_modes", queryDevGroupSurfacePresentModesTest, wsiType);
1717     // Destroy VK_NULL_HANDLE surface
1718     addFunctionCase(testGroup, "destroy_null_handle", destroyNullHandleSurfaceTest, wsiType);
1719 
1720     if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1721         // Create surface with initial window size set
1722         addFunctionCase(testGroup, "initial_size", createSurfaceInitialSizeTest, wsiType);
1723 
1724     if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1725         // Resize window and surface
1726         addFunctionCase(testGroup, "resize", resizeSurfaceTest, wsiType);
1727 
1728     // Query surface formats without surface
1729     addFunctionCase(testGroup, "query_formats_surfaceless", querySurfaceFormatsTestSurfaceless, wsiType);
1730     // Query surface present modes without surface
1731     addFunctionCase(testGroup, "query_present_modes_surfaceless", querySurfacePresentModesTestSurfaceless, wsiType);
1732     // Query extended surface present modes without surface
1733     addFunctionCase(testGroup, "query_present_modes2_surfaceless", querySurfacePresentModes2TestSurfaceless, wsiType);
1734     // Query extended surface formats without surface
1735     addFunctionCase(testGroup, "query_formats2_surfaceless", querySurfaceFormats2TestSurfaceless, wsiType);
1736 }
1737 
1738 } // namespace wsi
1739 } // namespace vkt
1740