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