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