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::__anon60bb292a0111::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::__anon60bb292a0111::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::__anon60bb292a0111::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::__anon60bb292a0111::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 std::string extensionName = "VK_GOOGLE_surfaceless_query";
966 const InstanceHelper instHelper (context, wsiType, vector<string>(1, extensionName), DE_NULL);
967 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
968 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
969 const VkSurfaceKHR nullSurface = 0;
970 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
971 const std::vector<vk::VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
972 const vector<VkPresentModeKHR> validPresentModes { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR };
973
974 if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
975 return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED, "Extension VK_EXT_full_screen_exclusive not supported");
976
977 // Ensure "VK_GOOGLE_surfaceless_query" extension's spec version is at least 2
978 {
979 deUint32 propertyCount = 0u;
980 std::vector<vk::VkExtensionProperties> extensionsProperties;
981 vk::VkResult extensionResult;
982
983 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
984 if (extensionResult != vk::VK_SUCCESS)
985 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Failed to retrieve spec version for extension " + extensionName);
986
987 extensionsProperties.resize(propertyCount);
988
989 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, extensionsProperties.data());
990 if (extensionResult != vk::VK_SUCCESS)
991 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Failed to retrieve spec version for extension " + extensionName);
992
993 for (const auto& property : extensionsProperties)
994 {
995 if (property.extensionName == extensionName)
996 {
997 if (property.specVersion < 2)
998 return tcu::TestStatus(QP_TEST_RESULT_NOT_SUPPORTED, "VK_GOOGLE_surfaceless_query is version 1. Need version 2 or higher");
999 break;
1000 }
1001 }
1002 }
1003
1004 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1005 {
1006 const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo =
1007 {
1008 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1009 DE_NULL,
1010 nullSurface
1011 };
1012 deUint32 numModesNull = 0u;
1013
1014 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo, &numModesNull, DE_NULL));
1015
1016 if (numModesNull == 0u)
1017 continue;
1018
1019 vector<VkPresentModeKHR> modesNull(numModesNull);
1020
1021 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo, &numModesNull, &modesNull[0]));
1022
1023 for (deUint32 i = 0; i < modesNull.size(); i++)
1024 {
1025 if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1026 {
1027 std::string error_string = std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1028 results.fail(error_string);
1029 break;
1030 }
1031 }
1032 }
1033
1034 return tcu::TestStatus(results.getResult(), results.getMessage());
1035 }
1036
querySurfaceFormats2TestSurfaceless(Context & context,Type wsiType)1037 tcu::TestStatus querySurfaceFormats2TestSurfaceless (Context& context, Type wsiType)
1038 {
1039 tcu::TestLog& log = context.getTestContext().getLog();
1040 tcu::ResultCollector results (log);
1041
1042 const vector<std::string> extensions ({"VK_KHR_get_surface_capabilities2", "VK_GOOGLE_surfaceless_query"});
1043 const InstanceHelper instHelper (context, wsiType, extensions );
1044 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
1045 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1046 const VkSurfaceKHR nullSurface = 0;
1047 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1048
1049 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1050 {
1051 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1052 {
1053 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
1054 {
1055 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1056 DE_NULL,
1057 *surface
1058 };
1059 const VkPhysicalDeviceSurfaceInfo2KHR nullSurfaceInfo =
1060 {
1061 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1062 DE_NULL,
1063 nullSurface
1064 };
1065 deUint32 numFormatsSurface = 0;
1066 deUint32 numFormatsNull = 0;
1067
1068 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormatsSurface, DE_NULL));
1069 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsNull, DE_NULL));
1070
1071 if (numFormatsSurface != numFormatsNull)
1072 {
1073 results.fail("Number of formats do not match");
1074 continue;
1075 }
1076
1077 if (numFormatsSurface > 0)
1078 {
1079 vector<VkSurfaceFormat2KHR> formatsSurface(numFormatsSurface + 1);
1080 vector<VkSurfaceFormat2KHR> formatsNull(numFormatsSurface + 1);
1081
1082 for (size_t ndx = 0; ndx < formatsSurface.size(); ++ndx)
1083 {
1084 formatsSurface[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1085 formatsSurface[ndx].pNext = DE_NULL;
1086 formatsNull[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1087 formatsNull[ndx].pNext = DE_NULL;
1088 }
1089
1090 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormatsSurface, &formatsSurface[0]));
1091 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsSurface, &formatsNull[0]));
1092
1093 formatsSurface.pop_back();
1094 formatsNull.pop_back();
1095
1096 for (deUint32 i = 0; i < numFormatsSurface; i++)
1097 {
1098 if (formatsSurface[i].surfaceFormat != formatsNull[i].surfaceFormat)
1099 {
1100 results.fail("Surface formats do not match");
1101 }
1102 }
1103 }
1104 }
1105 }
1106
1107 return tcu::TestStatus(results.getResult(), results.getMessage());
1108 }
1109
querySurfacePresentModesTest(Context & context,Type wsiType)1110 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
1111 {
1112 tcu::TestLog& log = context.getTestContext().getLog();
1113 tcu::ResultCollector results (log);
1114
1115 const InstanceHelper instHelper (context, wsiType);
1116 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
1117 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1118 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1119
1120 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1121 {
1122 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1123 {
1124 deUint32 numModes = 0;
1125
1126 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, DE_NULL));
1127
1128 vector<VkPresentModeKHR> modes (numModes + 1);
1129
1130 if (numModes > 0)
1131 {
1132 const deUint32 numModesOrig = numModes;
1133
1134 // check if below call properly overwrites mode count
1135 numModes++;
1136
1137 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, &modes[0]));
1138
1139 if ((size_t)numModes != numModesOrig)
1140 TCU_FAIL("Mode count changed between calls");
1141 }
1142
1143 modes.pop_back();
1144
1145 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
1146
1147 validateSurfacePresentModes(results, wsiType, modes);
1148 CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
1149 }
1150 // else skip query as surface is not supported by the device
1151 }
1152
1153 return tcu::TestStatus(results.getResult(), results.getMessage());
1154 }
1155
checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,tcu::ResultCollector & result)1156 void checkDeprecatedExtensionGoogleSurfacelessQuery(const vk::InstanceDriver& vk, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, tcu::ResultCollector& result)
1157 {
1158 const VkSurfaceKHR nullSurface = DE_NULL;
1159
1160 if (isSupportedByAnyQueue(vk, physicalDevice, surface))
1161 {
1162 deUint32 numModesSurface = 0;
1163 deUint32 numModesNull = 0;
1164
1165 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, DE_NULL));
1166 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1167
1168 if (numModesNull == 0)
1169 return;
1170
1171 // Actual surface needs to have at least the amount of modes that null surface has
1172 if (numModesSurface < numModesNull)
1173 {
1174 result.fail("Number of modes does not match");
1175 return;
1176 }
1177
1178 vector<VkPresentModeKHR> modesSurface(numModesSurface);
1179 vector<VkPresentModeKHR> modesNull(numModesNull);
1180
1181 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModesSurface, &modesSurface[0]));
1182 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1183
1184 // All modes present in null surface should also be present in actual surface
1185 for (deUint32 i = 0; i < modesNull.size(); i++)
1186 {
1187 if (std::find(modesSurface.begin(), modesSurface.end(), modesNull[i]) == modesSurface.end())
1188 {
1189 std::string error_string = std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1190 result.fail(error_string);
1191 break;
1192 }
1193 }
1194 }
1195 }
1196
checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver & vk,VkPhysicalDevice physicalDevice,tcu::ResultCollector & result)1197 void checkExtensionGoogleSurfacelessQuery(const vk::InstanceDriver& vk, VkPhysicalDevice physicalDevice, tcu::ResultCollector& result)
1198 {
1199 const VkSurfaceKHR nullSurface = DE_NULL;
1200 const vector<VkPresentModeKHR> validPresentModes { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR };
1201
1202 deUint32 numModesNull = 0;
1203 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, DE_NULL));
1204
1205 if (numModesNull == 0u)
1206 return;
1207
1208 vector<VkPresentModeKHR> modesNull(numModesNull);
1209
1210 VK_CHECK(vk.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, nullSurface, &numModesNull, &modesNull[0]));
1211
1212 for (deUint32 i = 0; i < modesNull.size(); i++)
1213 {
1214 if (std::find(validPresentModes.begin(), validPresentModes.end(), modesNull[i]) == validPresentModes.end())
1215 {
1216 std::string error_string = std::string("Present mode mismatch with mode: ") + getPresentModeKHRName(modesNull[i]);
1217 result.fail(error_string);
1218 break;
1219 }
1220 }
1221 }
1222
querySurfacePresentModesTestSurfaceless(Context & context,Type wsiType)1223 tcu::TestStatus querySurfacePresentModesTestSurfaceless (Context& context, Type wsiType)
1224 {
1225 tcu::TestLog& log = context.getTestContext().getLog();
1226 tcu::ResultCollector results (log);
1227
1228 const std::string extensionName = "VK_GOOGLE_surfaceless_query";
1229 const InstanceHelper instHelper (context, wsiType, vector<string>(1, extensionName), DE_NULL);
1230 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
1231 const Unique<vk::VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1232
1233 deUint32 extensionVersion = 1u;
1234
1235 // Get "VK_GOOGLE_surfaceless_query" extension's spec version
1236 {
1237 deUint32 propertyCount = 0u;
1238 std::vector<vk::VkExtensionProperties> extensionsProperties;
1239 vk::VkResult extensionResult;
1240
1241 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, DE_NULL);
1242 if (extensionResult != vk::VK_SUCCESS)
1243 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Failed to retrieve spec version for extension " + extensionName);
1244
1245 extensionsProperties.resize(propertyCount);
1246
1247 extensionResult = context.getPlatformInterface().enumerateInstanceExtensionProperties(DE_NULL, &propertyCount, extensionsProperties.data());
1248 if (extensionResult != vk::VK_SUCCESS)
1249 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Failed to retrieve spec version for extension " + extensionName);
1250
1251 for (const auto& property : extensionsProperties)
1252 {
1253 if (property.extensionName == extensionName)
1254 {
1255 extensionVersion = property.specVersion;
1256 break;
1257 }
1258 }
1259 }
1260
1261 log << TestLog::Message << "Checking spec version " << extensionVersion << " for VK_GOOGLE_surfaceless_query" << TestLog::EndMessage;
1262
1263 const bool checkDeprecatedVersion = extensionVersion < 2;
1264 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1265 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1266 {
1267 if (checkDeprecatedVersion)
1268 checkDeprecatedExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], *surface, results);
1269 else
1270 checkExtensionGoogleSurfacelessQuery(instHelper.vki, physicalDevices[deviceNdx], results);
1271 }
1272
1273 return tcu::TestStatus(results.getResult(), results.getMessage());
1274 }
1275
queryDevGroupSurfacePresentCapabilitiesTest(Context & context,Type wsiType)1276 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest (Context& context, Type wsiType)
1277 {
1278 tcu::TestLog& log = context.getTestContext().getLog();
1279 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1280 const float queuePriority = 1.0f;
1281 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
1282 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1283 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1284 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1285 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1286 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1287 deUint8 buffer [sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
1288 deUint32 queueFamilyIndex = 0;
1289 VkDeviceGroupPresentCapabilitiesKHR* presentCapabilities;
1290 std::vector<const char*> deviceExtensions;
1291
1292 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1293 deviceExtensions.push_back("VK_KHR_device_group");
1294 deviceExtensions.push_back("VK_KHR_swapchain");
1295
1296 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1297 {
1298 if (!context.isDeviceFunctionalitySupported(deviceExtensions[ndx]))
1299 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1300 }
1301
1302 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1303
1304 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1305 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1306 {
1307 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1308 queueFamilyIndex = (deUint32)queueNdx;
1309 }
1310 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1311 {
1312 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1313 DE_NULL, //pNext
1314 (VkDeviceQueueCreateFlags)0u, //flags
1315 queueFamilyIndex, //queueFamilyIndex;
1316 1u, //queueCount;
1317 &queuePriority, //pQueuePriorities;
1318 };
1319 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
1320 {
1321 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1322 DE_NULL, //pNext
1323 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1324 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1325 };
1326
1327 const VkDeviceCreateInfo deviceCreateInfo =
1328 {
1329 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1330 &deviceGroupInfo, //pNext;
1331 (VkDeviceCreateFlags)0u, //flags
1332 1, //queueRecordCount;
1333 &deviceQueueCreateInfo, //pRequestedQueues;
1334 0, //layerCount;
1335 DE_NULL, //ppEnabledLayerNames;
1336 deUint32(deviceExtensions.size()), //enabledExtensionCount;
1337 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1338 DE_NULL, //pEnabledFeatures;
1339 };
1340
1341 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1342 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1343
1344
1345 presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>(buffer);
1346 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1347 presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
1348 presentCapabilities->pNext = DE_NULL;
1349 VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
1350
1351 // Guard check
1352 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1353 {
1354 if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
1355 {
1356 log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1357 return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
1358 }
1359 }
1360
1361 // Check each physical device can present on itself
1362 for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE; physDevIdx++)
1363 {
1364 if (presentCapabilities->presentMask[physDevIdx])
1365 if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
1366 return tcu::TestStatus::fail("deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
1367 }
1368
1369 // Check if flags are valid
1370 if ((!(presentCapabilities->modes & requiredFlag)) ||
1371 presentCapabilities->modes > maxValidFlag)
1372 return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
1373
1374 return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
1375 }
1376
queryDevGroupSurfacePresentModesTest(Context & context,Type wsiType)1377 tcu::TestStatus queryDevGroupSurfacePresentModesTest (Context& context, Type wsiType)
1378 {
1379 tcu::TestLog& log = context.getTestContext().getLog();
1380 tcu::ResultCollector results (log);
1381 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1382 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
1383 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1384 const float queuePriority = 1.0f;
1385 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
1386 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1387 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1388 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1389 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1390 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1391 VkResult result = VK_SUCCESS;
1392 deUint8 buffer [sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
1393 deUint32 rectCount = 0;
1394 deUint32 incompleteRectCount = 0;
1395 deUint32 queueFamilyIndex = 0;
1396 VkRect2D* presentRectangles;
1397 VkDeviceGroupPresentModeFlagsKHR* presentModeFlags;
1398 vector<deUint8> rectanglesBuffer;
1399 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1400 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1401 std::vector<const char*> deviceExtensions;
1402
1403 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1404 deviceExtensions.push_back("VK_KHR_device_group");
1405 deviceExtensions.push_back("VK_KHR_swapchain");
1406
1407 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1408 {
1409 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1410 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1411 }
1412
1413 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1414 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1415 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1416 {
1417 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1418 queueFamilyIndex = (deUint32)queueNdx;
1419 }
1420 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1421 {
1422 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1423 DE_NULL, //pNext
1424 (VkDeviceQueueCreateFlags)0u, //flags
1425 queueFamilyIndex, //queueFamilyIndex;
1426 1u, //queueCount;
1427 &queuePriority, //pQueuePriorities;
1428 };
1429 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
1430 {
1431 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1432 DE_NULL, //pNext
1433 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1434 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1435 };
1436
1437 const VkDeviceCreateInfo deviceCreateInfo =
1438 {
1439 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1440 &deviceGroupInfo, //pNext;
1441 (VkDeviceCreateFlags)0u, //flags
1442 1, //queueRecordCount;
1443 &deviceQueueCreateInfo, //pRequestedQueues;
1444 0, //layerCount;
1445 DE_NULL, //ppEnabledLayerNames;
1446 deUint32(deviceExtensions.size()), //enabledExtensionCount;
1447 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1448 DE_NULL, //pEnabledFeatures;
1449 };
1450
1451 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1452 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1453 presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>(buffer);
1454 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1455
1456 VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1457
1458 // Guard check
1459 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1460 {
1461 if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1462 {
1463 log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1464 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1465 }
1466 }
1467
1468 // Check if flags are valid
1469 if ((!(*presentModeFlags & requiredFlag)) ||
1470 *presentModeFlags > maxValidFlag)
1471 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1472
1473 // getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1474 if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1475 {
1476 for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1477 {
1478 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1479 rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1480 presentRectangles = reinterpret_cast<VkRect2D*>(rectanglesBuffer.data());
1481 deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1482
1483 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1484
1485 // Guard check
1486 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1487 {
1488 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1489 {
1490 log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1491 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1492 }
1493 }
1494
1495 // Check rectangles do not overlap
1496 for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1497 {
1498 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1499 {
1500 if (rectIdx1 != rectIdx2)
1501 {
1502 deUint32 rectATop = presentRectangles[rectIdx1].offset.y;
1503 deUint32 rectALeft = presentRectangles[rectIdx1].offset.x;
1504 deUint32 rectABottom = presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1505 deUint32 rectARight = presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1506
1507 deUint32 rectBTop = presentRectangles[rectIdx2].offset.y;
1508 deUint32 rectBLeft = presentRectangles[rectIdx2].offset.x;
1509 deUint32 rectBBottom = presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1510 deUint32 rectBRight = presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1511
1512 if (rectALeft < rectBRight && rectARight > rectBLeft &&
1513 rectATop < rectBBottom && rectABottom > rectBTop)
1514 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1515 }
1516 }
1517 }
1518
1519 // Check incomplete
1520 incompleteRectCount = rectCount / 2;
1521 result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount, presentRectangles);
1522 results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1523 }
1524 }
1525
1526 return tcu::TestStatus(results.getResult(), results.getMessage());
1527 }
1528
createSurfaceInitialSizeTest(Context & context,Type wsiType)1529 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
1530 {
1531 tcu::TestLog& log = context.getTestContext().getLog();
1532 tcu::ResultCollector results (log);
1533
1534 const InstanceHelper instHelper (context, wsiType);
1535
1536 const UniquePtr<Display> nativeDisplay (NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1537 instHelper.supportedExtensions,
1538 wsiType));
1539
1540 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1541 const UVec2 sizes[] =
1542 {
1543 UVec2(64, 64),
1544 UVec2(124, 119),
1545 UVec2(256, 512)
1546 };
1547
1548 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1549
1550 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1551 {
1552 const UVec2& testSize = sizes[sizeNdx];
1553 const UniquePtr<Window> nativeWindow (NativeObjects::createWindow(*nativeDisplay, tcu::just(testSize)));
1554 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow, context.getTestContext().getCommandLine()));
1555
1556 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1557 {
1558 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1559 {
1560 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1561
1562 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1563 results.check(capabilities.currentExtent.width == testSize.x() &&
1564 capabilities.currentExtent.height == testSize.y(),
1565 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1566 }
1567 }
1568 }
1569
1570 return tcu::TestStatus(results.getResult(), results.getMessage());
1571 }
1572
resizeSurfaceTest(Context & context,Type wsiType)1573 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
1574 {
1575 tcu::TestLog& log = context.getTestContext().getLog();
1576 tcu::ResultCollector results (log);
1577
1578 const InstanceHelper instHelper (context, wsiType);
1579
1580 const UniquePtr<Display> nativeDisplay (NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1581 instHelper.supportedExtensions,
1582 wsiType));
1583 UniquePtr<Window> nativeWindow (NativeObjects::createWindow(*nativeDisplay, tcu::Nothing));
1584
1585 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1586 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow, context.getTestContext().getCommandLine()));
1587
1588 const UVec2 sizes[] =
1589 {
1590 UVec2(64, 64),
1591 UVec2(124, 119),
1592 UVec2(256, 512)
1593 };
1594
1595 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1596
1597 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1598 {
1599 const UVec2 testSize = sizes[sizeNdx];
1600
1601 try
1602 {
1603 nativeWindow->resize(testSize);
1604 }
1605 catch (const tcu::Exception& e)
1606 {
1607 // Make sure all exception types result in a test failure
1608 results.fail(e.getMessage());
1609 }
1610
1611 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1612 {
1613 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1614 {
1615 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1616
1617 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1618 results.check(capabilities.currentExtent.width == testSize.x() &&
1619 capabilities.currentExtent.height == testSize.y(),
1620 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1621 }
1622 }
1623 }
1624
1625 return tcu::TestStatus(results.getResult(), results.getMessage());
1626 }
1627
destroyNullHandleSurfaceTest(Context & context,Type wsiType)1628 tcu::TestStatus destroyNullHandleSurfaceTest (Context& context, Type wsiType)
1629 {
1630 const InstanceHelper instHelper (context, wsiType);
1631 const VkSurfaceKHR nullHandle = DE_NULL;
1632
1633 // Default allocator
1634 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1635
1636 // Custom allocator
1637 {
1638 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u);
1639
1640 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1641
1642 if (recordingAllocator.getNumRecords() != 0u)
1643 return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1644 }
1645
1646 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1647 }
1648
1649 } // anonymous
1650
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1651 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1652 {
1653 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
1654
1655 addFunctionCase(testGroup, "create", "Create surface", createSurfaceTest, wsiType);
1656 addFunctionCase(testGroup, "create_custom_allocator", "Create surface with custom allocator", createSurfaceCustomAllocatorTest, wsiType);
1657 addFunctionCase(testGroup, "create_simulate_oom", "Create surface with simulating OOM", createSurfaceSimulateOOMTest, wsiType);
1658 addFunctionCase(testGroup, "query_support", "Query surface support", querySurfaceSupportTest, wsiType);
1659 addFunctionCase(testGroup, "query_presentation_support", "Query native presentation support", queryPresentationSupportTest, wsiType);
1660 addFunctionCase(testGroup, "query_capabilities", "Query surface capabilities", querySurfaceCapabilitiesTest, wsiType);
1661 addFunctionCase(testGroup, "query_capabilities2", "Query extended surface capabilities", querySurfaceCapabilities2Test, wsiType);
1662 addFunctionCase(testGroup, "query_protected_capabilities", "Query protected surface capabilities", querySurfaceProtectedCapabilitiesTest, wsiType);
1663 addFunctionCase(testGroup, "query_surface_counters", "Query and check available surface counters", querySurfaceCounterTest, wsiType);
1664 addFunctionCase(testGroup, "query_formats", "Query surface formats", querySurfaceFormatsTest, wsiType);
1665 addFunctionCase(testGroup, "query_formats2", "Query extended surface formats", querySurfaceFormats2Test, wsiType);
1666 addFunctionCase(testGroup, "query_present_modes", "Query surface present modes", querySurfacePresentModesTest, wsiType);
1667 addFunctionCase(testGroup, "query_present_modes2", "Query extended surface present modes", querySurfacePresentModes2Test, wsiType);
1668 addFunctionCase(testGroup, "query_devgroup_present_capabilities", "Query surface present modes capabilities in device groups",queryDevGroupSurfacePresentCapabilitiesTest,wsiType);
1669 addFunctionCase(testGroup, "query_devgroup_present_modes", "Query surface present modes for device groups", queryDevGroupSurfacePresentModesTest, wsiType);
1670 addFunctionCase(testGroup, "destroy_null_handle", "Destroy VK_NULL_HANDLE surface", destroyNullHandleSurfaceTest, wsiType);
1671
1672 if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1673 addFunctionCase(testGroup, "initial_size", "Create surface with initial window size set", createSurfaceInitialSizeTest, wsiType);
1674
1675 if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1676 addFunctionCase(testGroup, "resize", "Resize window and surface", resizeSurfaceTest, wsiType);
1677
1678 addFunctionCase(testGroup, "query_formats_surfaceless", "Query surface formats without surface", querySurfaceFormatsTestSurfaceless, wsiType);
1679 addFunctionCase(testGroup, "query_present_modes_surfaceless", "Query surface present modes without surface", querySurfacePresentModesTestSurfaceless, wsiType);
1680 addFunctionCase(testGroup, "query_present_modes2_surfaceless", "Query extended surface present modes without surface", querySurfacePresentModes2TestSurfaceless, wsiType);
1681 addFunctionCase(testGroup, "query_formats2_surfaceless", "Query extended surface formats without surface", querySurfaceFormats2TestSurfaceless, wsiType);
1682 }
1683
1684 } // wsi
1685 } // vkt
1686