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