1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief VkSurface Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktWsiSurfaceTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkStrUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkDeviceUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkWsiPlatform.hpp"
41 #include "vkWsiUtil.hpp"
42 #include "vkAllocationCallbackUtil.hpp"
43 #include "vkQueryUtil.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuFormatUtil.hpp"
47 #include "tcuPlatform.hpp"
48 #include "tcuResultCollector.hpp"
49 #include "tcuCommandLine.hpp"
51 #include "deUniquePtr.hpp"
52 #include "deStringUtil.hpp"
58 inline bool operator!= (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
60 return (a.format != b.format) || (a.colorSpace != b.colorSpace);
63 inline bool operator== (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
68 inline bool operator!= (const VkExtent2D& a, const VkExtent2D& b)
70 return (a.width != b.width) || (a.height != b.height);
73 inline bool operator!= (const VkSurfaceCapabilitiesKHR& a, const VkSurfaceCapabilitiesKHR& b)
75 return (a.minImageCount != b.minImageCount) ||
76 (a.maxImageCount != b.maxImageCount) ||
77 (a.currentExtent != b.currentExtent) ||
78 (a.minImageExtent != b.minImageExtent) ||
79 (a.maxImageExtent != b.maxImageExtent) ||
80 (a.maxImageArrayLayers != b.maxImageArrayLayers) ||
81 (a.supportedTransforms != b.supportedTransforms) ||
82 (a.currentTransform != b.currentTransform) ||
83 (a.supportedCompositeAlpha != b.supportedCompositeAlpha) ||
84 (a.supportedUsageFlags != b.supportedUsageFlags);
98 using namespace vk::wsi;
112 SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC = 0xffffffff
117 GUARD_SIZE = 0x20, //!< Number of bytes to check
118 GUARD_VALUE = 0xcd, //!< Data pattern
122 class CheckIncompleteResult
125 virtual ~CheckIncompleteResult (void) {}
126 virtual void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, T* data) = 0;
128 void operator() (tcu::ResultCollector& results,
129 const InstanceInterface& vki,
130 const VkPhysicalDevice physDevice,
131 const VkSurfaceKHR surface,
132 const std::size_t expectedCompleteSize)
134 if (expectedCompleteSize == 0)
137 vector<T> outputData (expectedCompleteSize);
138 const deUint32 usedSize = static_cast<deUint32>(expectedCompleteSize / 3);
140 ValidateQueryBits::fillBits(outputData.begin(), outputData.end()); // unused entries should have this pattern intact
142 m_result = VK_SUCCESS;
144 getResult(vki, physDevice, surface, &outputData[0]); // update m_count and m_result
146 if (m_count != usedSize || m_result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
147 results.fail("Query didn't return VK_INCOMPLETE");
155 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
157 void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkSurfaceFormatKHR* data)
159 m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
163 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
165 void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkPresentModeKHR* data)
167 m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
171 typedef vector<VkExtensionProperties> Extensions;
173 CustomInstance createInstanceWithWsi (Context& context,
175 const vector<string> extraExtensions,
176 const VkAllocationCallbacks* pAllocator = DE_NULL)
178 const deUint32 version = context.getUsedApiVersion();
179 vector<string> extensions = extraExtensions;
181 extensions.push_back("VK_KHR_surface");
182 extensions.push_back(getExtensionName(wsiType));
184 vector<string> instanceExtensions;
185 for (const auto& ext : extensions)
187 if (!context.isInstanceFunctionalitySupported(ext))
188 TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
190 if (!isCoreInstanceExtension(version, ext))
191 instanceExtensions.push_back(ext);
194 return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
197 struct InstanceHelper
199 const vector<VkExtensionProperties> supportedExtensions;
200 CustomInstance instance;
201 const InstanceDriver& vki;
203 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
204 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
206 , instance (createInstanceWithWsi(context,
210 , vki (instance.getDriver())
213 InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
214 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
216 , instance (createInstanceWithWsi(context,
220 , vki (instance.getDriver())
224 MovePtr<Display> createDisplay (const vk::Platform& platform,
225 const Extensions& supportedExtensions,
230 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
232 catch (const tcu::NotSupportedError& e)
234 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
235 platform.hasDisplay(wsiType))
237 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
238 // must support creating native display & window for that WSI type.
239 throw tcu::TestError(e.getMessage());
246 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
250 return MovePtr<Window>(display.createWindow(initialSize));
252 catch (const tcu::NotSupportedError& e)
254 // See createDisplay - assuming that wsi::Display was supported platform port
255 // should also support creating a window.
256 throw tcu::TestError(e.getMessage());
262 const UniquePtr<Display> display;
263 const UniquePtr<Window> window;
265 NativeObjects (Context& context,
266 const Extensions& supportedExtensions,
268 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
269 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
270 , window (createWindow(*display, initialWindowSize))
274 tcu::TestStatus createSurfaceTest (Context& context, Type wsiType)
276 const InstanceHelper instHelper (context, wsiType);
277 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
278 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
280 return tcu::TestStatus::pass("Creating surface succeeded");
283 tcu::TestStatus querySurfaceCounterTest (Context& context, Type wsiType)
285 const InstanceHelper instHelper (context, wsiType);
286 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
287 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
288 const vk::InstanceInterface& vki = context.getInstanceInterface();
289 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
291 if (!isInstanceExtensionSupported(context.getUsedApiVersion(), context.getInstanceExtensions(), "VK_EXT_display_surface_counter"))
292 TCU_THROW(NotSupportedError, "VK_EXT_display_surface_counter not supported");
294 const vk::VkSurfaceCapabilities2EXT capsExt = getPhysicalDeviceSurfaceCapabilities2EXT (vki, physicalDevice, surface.get());
295 const vk::VkSurfaceCapabilitiesKHR capsKhr = getPhysicalDeviceSurfaceCapabilities (vki, physicalDevice, surface.get());
297 if (!sameSurfaceCapabilities(capsKhr, capsExt))
299 return tcu::TestStatus::fail("KHR and EXT surface capabilities do not match");
302 if (capsExt.supportedSurfaceCounters != 0)
304 return tcu::TestStatus::fail("supportedSurfaceCounters nonzero (" + de::toString(capsExt.supportedSurfaceCounters) + ") for non-display surface");
307 return tcu::TestStatus::pass("Pass");
310 tcu::TestStatus createSurfaceCustomAllocatorTest (Context& context, Type wsiType)
312 AllocationCallbackRecorder allocationRecorder (getSystemAllocator());
313 tcu::TestLog& log = context.getTestContext().getLog();
316 const InstanceHelper instHelper (context, wsiType, allocationRecorder.getCallbacks());
317 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
318 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
323 allocationRecorder.getCallbacks()));
325 if (!validateAndLog(log,
327 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
328 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
329 return tcu::TestStatus::fail("Detected invalid system allocation callback");
332 if (!validateAndLog(log, allocationRecorder, 0u))
333 return tcu::TestStatus::fail("Detected invalid system allocation callback");
335 if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
336 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
338 return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
341 tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
343 tcu::TestLog& log = context.getTestContext().getLog();
345 for (deUint32 numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
347 AllocationCallbackRecorder allocationRecorder (getSystemAllocator());
348 DeterministicFailAllocator failingAllocator (allocationRecorder.getCallbacks(),
349 DeterministicFailAllocator::MODE_DO_NOT_COUNT,
353 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
357 const InstanceHelper instHelper (context, wsiType, failingAllocator.getCallbacks());
359 // OOM is not simulated for VkInstance as we don't want to spend time
360 // testing OOM paths inside instance creation.
361 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
363 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
364 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
369 failingAllocator.getCallbacks()));
371 if (!validateAndLog(log,
373 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT) |
374 (1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
375 return tcu::TestStatus::fail("Detected invalid system allocation callback");
377 catch (const OutOfMemoryError& e)
379 log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
383 if (!validateAndLog(log, allocationRecorder, 0u))
384 return tcu::TestStatus::fail("Detected invalid system allocation callback");
388 log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
390 if (numPassingAllocs == 0)
391 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
393 return tcu::TestStatus::pass("OOM simulation completed");
397 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
400 deUint32 getNumQueueFamilies (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
402 deUint32 numFamilies = 0;
404 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
409 tcu::TestStatus querySurfaceSupportTest (Context& context, Type wsiType)
411 tcu::TestLog& log = context.getTestContext().getLog();
412 tcu::ResultCollector results (log);
414 const InstanceHelper instHelper (context, wsiType);
415 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
416 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
417 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
419 // On Android surface must be supported by all devices and queue families
420 const bool expectSupportedOnAll = wsiType == TYPE_ANDROID;
422 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
424 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
425 const deUint32 numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
427 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
429 const VkBool32 isSupported = getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
431 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
432 << (isSupported == VK_FALSE ? "NOT " : "") << "supported"
433 << TestLog::EndMessage;
435 if (expectSupportedOnAll && !isSupported)
436 results.fail("Surface must be supported by all devices and queue families");
440 return tcu::TestStatus(results.getResult(), results.getMessage());
443 tcu::TestStatus queryPresentationSupportTest(Context& context, Type wsiType)
445 tcu::TestLog& log = context.getTestContext().getLog();
446 tcu::ResultCollector results (log);
448 const InstanceHelper instHelper (context, wsiType);
449 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
450 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
451 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
453 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
455 const VkPhysicalDevice physicalDevice = physicalDevices[deviceNdx];
456 const deUint32 numQueueFamilies = getNumQueueFamilies(instHelper.vki, physicalDevice);
458 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
460 VkBool32 isPresentationSupported = getPhysicalDevicePresentationSupport(instHelper.vki, physicalDevice, queueFamilyNdx, wsiType, *native.display);
461 VkBool32 isSurfaceSupported = getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
463 log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": presentation "
464 << (isPresentationSupported == VK_FALSE ? "NOT " : "") << "supported. Surface "
465 << (isSurfaceSupported == VK_FALSE ? "NOT " : "") << "supported."
466 << TestLog::EndMessage;
468 if (isPresentationSupported != isSurfaceSupported)
469 results.fail("Presentation support is different from surface support");
473 return tcu::TestStatus(results.getResult(), results.getMessage());
476 bool isSupportedByAnyQueue (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
478 const deUint32 numQueueFamilies = getNumQueueFamilies(vki, physicalDevice);
480 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
482 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
489 void validateSurfaceCapabilities (tcu::ResultCollector& results, const VkSurfaceCapabilitiesKHR& capabilities)
491 results.check(capabilities.minImageCount > 0,
492 "minImageCount must be larger than 0");
494 results.check(capabilities.minImageExtent.width > 0 &&
495 capabilities.minImageExtent.height > 0,
496 "minImageExtent dimensions must be larger than 0");
498 results.check(capabilities.maxImageExtent.width > 0 &&
499 capabilities.maxImageExtent.height > 0,
500 "maxImageExtent dimensions must be larger than 0");
502 results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
503 capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
504 "maxImageExtent must be larger or equal to minImageExtent");
506 if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
507 capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
509 results.check(capabilities.currentExtent.width > 0 &&
510 capabilities.currentExtent.height > 0,
511 "currentExtent dimensions must be larger than 0");
513 results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width) &&
514 de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height),
515 "currentExtent is not in supported extent limits");
518 results.check(capabilities.maxImageArrayLayers > 0,
519 "maxImageArrayLayers must be larger than 0");
521 results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
522 "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
524 results.check(capabilities.supportedTransforms != 0,
525 "At least one transform must be supported");
527 results.check(dePop32(capabilities.currentTransform) != 0,
528 "Invalid currentTransform");
530 results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
531 "currentTransform is not supported by surface");
533 results.check(capabilities.supportedCompositeAlpha != 0,
534 "At least one alpha mode must be supported");
537 tcu::TestStatus querySurfaceCapabilitiesTest (Context& context, Type wsiType)
539 tcu::TestLog& log = context.getTestContext().getLog();
540 tcu::ResultCollector results (log);
542 const InstanceHelper instHelper (context, wsiType);
543 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
544 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
545 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
547 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
549 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
551 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
552 physicalDevices[deviceNdx],
555 log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
557 validateSurfaceCapabilities(results, capabilities);
559 // else skip query as surface is not supported by the device
562 return tcu::TestStatus(results.getResult(), results.getMessage());
565 tcu::TestStatus querySurfaceCapabilities2Test (Context& context, Type wsiType)
567 tcu::TestLog& log = context.getTestContext().getLog();
568 tcu::ResultCollector results (log);
570 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
571 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
572 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
573 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
575 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
577 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
579 const VkSurfaceCapabilitiesKHR refCapabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
580 physicalDevices[deviceNdx],
582 VkSurfaceCapabilities2KHR extCapabilities;
584 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
585 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
586 extCapabilities.pNext = DE_NULL;
589 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
591 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
595 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
597 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
599 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
601 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
604 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
605 extCapabilities.pNext == DE_NULL,
606 "sType/pNext modified");
608 if (refCapabilities != extCapabilities.surfaceCapabilities)
610 log << TestLog::Message
611 << "Device " << deviceNdx
612 << ": expected " << refCapabilities
613 << ", got " << extCapabilities.surfaceCapabilities
614 << TestLog::EndMessage;
615 results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
620 return tcu::TestStatus(results.getResult(), results.getMessage());
623 tcu::TestStatus querySurfaceProtectedCapabilitiesTest (Context& context, Type wsiType)
625 tcu::TestLog& log = context.getTestContext().getLog();
626 tcu::ResultCollector results (log);
628 vector<string> requiredExtensions;
629 requiredExtensions.push_back("VK_KHR_get_surface_capabilities2");
630 requiredExtensions.push_back("VK_KHR_surface_protected_capabilities");
631 const InstanceHelper instHelper (context, wsiType, requiredExtensions);
632 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
633 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
634 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
636 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
638 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
640 VkSurfaceCapabilities2KHR extCapabilities;
641 VkSurfaceProtectedCapabilitiesKHR extProtectedCapabilities;
643 deMemset(&extProtectedCapabilities, 0xcd, sizeof(VkSurfaceProtectedCapabilitiesKHR));
644 extProtectedCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR;
645 extProtectedCapabilities.pNext = DE_NULL;
647 deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
648 extCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
649 extCapabilities.pNext = &extProtectedCapabilities;
652 VkPhysicalDeviceSurfaceInfo2KHR infoCopy;
653 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
655 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
661 deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
663 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
665 results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
668 results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
669 extCapabilities.pNext == &extProtectedCapabilities,
670 "sType/pNext modified");
672 results.check(extProtectedCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
673 extProtectedCapabilities.pNext == DE_NULL,
674 "sType/pNext modified");
676 results.check(extProtectedCapabilities.supportsProtected == 0 ||
677 extProtectedCapabilities.supportsProtected == 1,
678 "supportsProtected ");
682 return tcu::TestStatus(results.getResult(), results.getMessage());
685 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
687 const VkSurfaceFormatKHR* requiredFormats = DE_NULL;
688 size_t numRequiredFormats = 0;
690 if (wsiType == TYPE_ANDROID)
692 static const VkSurfaceFormatKHR s_androidFormats[] =
694 { VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
695 { VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
696 { VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }
699 requiredFormats = &s_androidFormats[0];
700 numRequiredFormats = DE_LENGTH_OF_ARRAY(s_androidFormats);
703 for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
705 const VkSurfaceFormatKHR& requiredFormat = requiredFormats[ndx];
707 if (!de::contains(formats.begin(), formats.end(), requiredFormat))
708 results.fail(de::toString(requiredFormat) + " not supported");
711 // Check that there are no duplicates
712 for (size_t ndx = 1; ndx < formats.size(); ++ndx)
714 if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
715 results.fail("Found duplicate entry " + de::toString(formats[ndx]));
719 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
721 tcu::TestLog& log = context.getTestContext().getLog();
722 tcu::ResultCollector results (log);
724 const InstanceHelper instHelper (context, wsiType);
725 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
726 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
727 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
729 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
731 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
733 deUint32 numFormats = 0;
735 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, DE_NULL));
737 std::vector<VkSurfaceFormatKHR> formats (numFormats + 1);
741 const deUint32 numFormatsOrig = numFormats;
743 // check if below call properly overwrites formats count
746 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, &formats[0]));
748 if (numFormats != numFormatsOrig)
749 results.fail("Format count changed between calls");
754 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
756 validateSurfaceFormats(results, wsiType, formats);
757 CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, formats.size());
759 // else skip query as surface is not supported by the device
762 return tcu::TestStatus(results.getResult(), results.getMessage());
765 tcu::TestStatus querySurfaceFormats2Test (Context& context, Type wsiType)
767 tcu::TestLog& log = context.getTestContext().getLog();
768 tcu::ResultCollector results (log);
770 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
771 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
772 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
773 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
775 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
777 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
779 const vector<VkSurfaceFormatKHR> refFormats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
780 physicalDevices[deviceNdx],
782 const VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo =
784 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
788 deUint32 numFormats = 0;
790 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, DE_NULL));
792 if ((size_t)numFormats != refFormats.size())
793 results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
797 vector<VkSurfaceFormat2KHR> formats (numFormats + 1);
799 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
801 formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
802 formats[ndx].pNext = DE_NULL;
805 const deUint32 numFormatsOrig = numFormats;
807 // check if below call properly overwrites formats count
810 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, &formats[0]));
812 if ((size_t)numFormats != numFormatsOrig)
813 results.fail("Format count changed between calls");
818 vector<VkSurfaceFormatKHR> extFormats (formats.size());
820 for (size_t ndx = 0; ndx < formats.size(); ++ndx)
822 results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
823 formats[ndx].pNext == DE_NULL,
824 "sType/pNext modified");
825 extFormats[ndx] = formats[ndx].surfaceFormat;
828 for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
830 if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
831 results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
835 // Check VK_INCOMPLETE
837 vector<VkSurfaceFormat2KHR> formatsClone (formats);
838 deUint32 numToSupply = numFormats/2;
839 VkResult queryResult;
841 ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
843 queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
845 results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
846 results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
847 "Driver wrote past last element");
849 for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
851 results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
852 formatsClone[ndx].pNext == DE_NULL &&
853 formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
854 "Returned element " + de::toString(ndx) + " is different");
859 // else skip query as surface is not supported by the device
862 return tcu::TestStatus(results.getResult(), results.getMessage());
865 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
867 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
868 "VK_PRESENT_MODE_FIFO_KHR is not supported");
870 if (wsiType == TYPE_ANDROID)
871 results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
872 "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
875 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
877 tcu::TestLog& log = context.getTestContext().getLog();
878 tcu::ResultCollector results (log);
880 const InstanceHelper instHelper (context, wsiType);
881 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
882 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
883 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
885 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
887 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
889 deUint32 numModes = 0;
891 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, DE_NULL));
893 vector<VkPresentModeKHR> modes (numModes + 1);
897 const deUint32 numModesOrig = numModes;
899 // check if below call properly overwrites mode count
902 VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, &modes[0]));
904 if ((size_t)numModes != numModesOrig)
905 TCU_FAIL("Mode count changed between calls");
910 log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
912 validateSurfacePresentModes(results, wsiType, modes);
913 CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
915 // else skip query as surface is not supported by the device
918 return tcu::TestStatus(results.getResult(), results.getMessage());
921 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest (Context& context, Type wsiType)
923 tcu::TestLog& log = context.getTestContext().getLog();
924 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
925 const float queuePriority = 1.0f;
926 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
927 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
928 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
929 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
930 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
931 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
932 deUint8 buffer [sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
933 deUint32 queueFamilyIndex = 0;
934 VkDeviceGroupPresentCapabilitiesKHR* presentCapabilities;
935 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
936 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
937 std::vector<const char*> deviceExtensions;
939 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
940 deviceExtensions.push_back("VK_KHR_device_group");
941 deviceExtensions.push_back("VK_KHR_swapchain");
943 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
945 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
946 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
949 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
951 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
952 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
954 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
955 queueFamilyIndex = (deUint32)queueNdx;
957 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
959 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
961 (VkDeviceQueueCreateFlags)0u, //flags
962 queueFamilyIndex, //queueFamilyIndex;
964 &queuePriority, //pQueuePriorities;
966 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
968 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
970 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
971 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
974 const VkDeviceCreateInfo deviceCreateInfo =
976 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
977 &deviceGroupInfo, //pNext;
978 (VkDeviceCreateFlags)0u, //flags
979 1, //queueRecordCount;
980 &deviceQueueCreateInfo, //pRequestedQueues;
982 DE_NULL, //ppEnabledLayerNames;
983 deUint32(deviceExtensions.size()), //enabledExtensionCount;
984 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
985 DE_NULL, //pEnabledFeatures;
988 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
989 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
992 presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>(buffer);
993 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
994 presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
995 presentCapabilities->pNext = DE_NULL;
996 VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
999 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1001 if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
1003 log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1004 return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
1008 // Check each physical device can present on itself
1009 for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE_KHR; physDevIdx++)
1011 if (presentCapabilities->presentMask[physDevIdx])
1012 if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
1013 return tcu::TestStatus::fail("deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
1016 // Check if flags are valid
1017 if ((!(presentCapabilities->modes & requiredFlag)) ||
1018 presentCapabilities->modes > maxValidFlag)
1019 return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
1021 return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
1024 tcu::TestStatus queryDevGroupSurfacePresentModesTest (Context& context, Type wsiType)
1026 tcu::TestLog& log = context.getTestContext().getLog();
1027 tcu::ResultCollector results (log);
1028 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1029 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
1030 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
1031 const float queuePriority = 1.0f;
1032 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
1033 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1034 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1035 const VkDeviceGroupPresentModeFlagsKHR requiredFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1036 const VkDeviceGroupPresentModeFlagsKHR maxValidFlag = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1037 VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1038 VkResult result = VK_SUCCESS;
1039 deUint8 buffer [sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
1040 deUint32 rectCount = 0;
1041 deUint32 incompleteRectCount = 0;
1042 deUint32 queueFamilyIndex = 0;
1043 VkRect2D* presentRectangles;
1044 VkDeviceGroupPresentModeFlagsKHR* presentModeFlags;
1045 vector<deUint8> rectanglesBuffer;
1046 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1047 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1048 std::vector<const char*> deviceExtensions;
1050 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1051 deviceExtensions.push_back("VK_KHR_device_group");
1052 deviceExtensions.push_back("VK_KHR_swapchain");
1054 for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1056 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1057 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1060 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1061 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1062 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1064 if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1065 queueFamilyIndex = (deUint32)queueNdx;
1067 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1069 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
1071 (VkDeviceQueueCreateFlags)0u, //flags
1072 queueFamilyIndex, //queueFamilyIndex;
1074 &queuePriority, //pQueuePriorities;
1076 const VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
1078 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
1080 deviceGroupProps[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
1081 deviceGroupProps[devGroupIdx].physicalDevices //physicalDevices
1084 const VkDeviceCreateInfo deviceCreateInfo =
1086 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
1087 &deviceGroupInfo, //pNext;
1088 (VkDeviceCreateFlags)0u, //flags
1089 1, //queueRecordCount;
1090 &deviceQueueCreateInfo, //pRequestedQueues;
1092 DE_NULL, //ppEnabledLayerNames;
1093 deUint32(deviceExtensions.size()), //enabledExtensionCount;
1094 (deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]), //ppEnabledExtensionNames;
1095 DE_NULL, //pEnabledFeatures;
1098 Move<VkDevice> deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1099 const DeviceDriver vk (context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1100 presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>(buffer);
1101 deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1103 VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1106 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1108 if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1110 log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1111 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1115 // Check if flags are valid
1116 if ((!(*presentModeFlags & requiredFlag)) ||
1117 *presentModeFlags > maxValidFlag)
1118 return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1120 // getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1121 if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1123 for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1125 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1126 rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1127 presentRectangles = reinterpret_cast<VkRect2D*>(rectanglesBuffer.data());
1128 deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1130 VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1133 for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1135 if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1137 log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1138 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1142 // Check rectangles do not overlap
1143 for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1145 for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1147 if (rectIdx1 != rectIdx2)
1149 deUint32 rectATop = presentRectangles[rectIdx1].offset.y;
1150 deUint32 rectALeft = presentRectangles[rectIdx1].offset.x;
1151 deUint32 rectABottom = presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1152 deUint32 rectARight = presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1154 deUint32 rectBTop = presentRectangles[rectIdx2].offset.y;
1155 deUint32 rectBLeft = presentRectangles[rectIdx2].offset.x;
1156 deUint32 rectBBottom = presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1157 deUint32 rectBRight = presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1159 if (rectALeft < rectBRight && rectARight > rectBLeft &&
1160 rectATop < rectBBottom && rectABottom > rectBTop)
1161 return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1167 incompleteRectCount = rectCount / 2;
1168 result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount, presentRectangles);
1169 results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1173 return tcu::TestStatus(results.getResult(), results.getMessage());
1176 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
1178 tcu::TestLog& log = context.getTestContext().getLog();
1179 tcu::ResultCollector results (log);
1181 const InstanceHelper instHelper (context, wsiType);
1183 const UniquePtr<Display> nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1184 instHelper.supportedExtensions,
1187 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1188 const UVec2 sizes[] =
1195 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1197 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1199 const UVec2& testSize = sizes[sizeNdx];
1200 const UniquePtr<Window> nativeWindow (createWindow(*nativeDisplay, tcu::just(testSize)));
1201 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1203 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1205 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1207 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1209 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1210 results.check(capabilities.currentExtent.width == testSize.x() &&
1211 capabilities.currentExtent.height == testSize.y(),
1212 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1217 return tcu::TestStatus(results.getResult(), results.getMessage());
1220 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
1222 tcu::TestLog& log = context.getTestContext().getLog();
1223 tcu::ResultCollector results (log);
1225 const InstanceHelper instHelper (context, wsiType);
1227 const UniquePtr<Display> nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1228 instHelper.supportedExtensions,
1230 UniquePtr<Window> nativeWindow (createWindow(*nativeDisplay, tcu::nothing<UVec2>()));
1232 const vector<VkPhysicalDevice> physicalDevices = enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1233 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
1235 const UVec2 sizes[] =
1242 DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1244 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1246 const UVec2 testSize = sizes[sizeNdx];
1250 nativeWindow->resize(testSize);
1252 catch (const tcu::Exception& e)
1254 // Make sure all exception types result in a test failure
1255 results.fail(e.getMessage());
1258 for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1260 if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1262 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1264 // \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1265 results.check(capabilities.currentExtent.width == testSize.x() &&
1266 capabilities.currentExtent.height == testSize.y(),
1267 "currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1272 return tcu::TestStatus(results.getResult(), results.getMessage());
1275 tcu::TestStatus destroyNullHandleSurfaceTest (Context& context, Type wsiType)
1277 const InstanceHelper instHelper (context, wsiType);
1278 const VkSurfaceKHR nullHandle = DE_NULL;
1280 // Default allocator
1281 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1285 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u);
1287 instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1289 if (recordingAllocator.getNumRecords() != 0u)
1290 return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1293 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1298 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1300 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
1302 addFunctionCase(testGroup, "create", "Create surface", createSurfaceTest, wsiType);
1303 addFunctionCase(testGroup, "create_custom_allocator", "Create surface with custom allocator", createSurfaceCustomAllocatorTest, wsiType);
1304 addFunctionCase(testGroup, "create_simulate_oom", "Create surface with simulating OOM", createSurfaceSimulateOOMTest, wsiType);
1305 addFunctionCase(testGroup, "query_support", "Query surface support", querySurfaceSupportTest, wsiType);
1306 addFunctionCase(testGroup, "query_presentation_support", "Query native presentation support", queryPresentationSupportTest, wsiType);
1307 addFunctionCase(testGroup, "query_capabilities", "Query surface capabilities", querySurfaceCapabilitiesTest, wsiType);
1308 addFunctionCase(testGroup, "query_capabilities2", "Query extended surface capabilities", querySurfaceCapabilities2Test, wsiType);
1309 addFunctionCase(testGroup, "query_protected_capabilities", "Query protected surface capabilities", querySurfaceProtectedCapabilitiesTest, wsiType);
1310 addFunctionCase(testGroup, "query_surface_counters", "Query and check available surface counters", querySurfaceCounterTest, wsiType);
1311 addFunctionCase(testGroup, "query_formats", "Query surface formats", querySurfaceFormatsTest, wsiType);
1312 addFunctionCase(testGroup, "query_formats2", "Query extended surface formats", querySurfaceFormats2Test, wsiType);
1313 addFunctionCase(testGroup, "query_present_modes", "Query surface present modes", querySurfacePresentModesTest, wsiType);
1314 addFunctionCase(testGroup, "query_devgroup_present_capabilities", "Query surface present modes capabilities in device groups",queryDevGroupSurfacePresentCapabilitiesTest,wsiType);
1315 addFunctionCase(testGroup, "query_devgroup_present_modes", "Query surface present modes for device groups", queryDevGroupSurfacePresentModesTest, wsiType);
1316 addFunctionCase(testGroup, "destroy_null_handle", "Destroy VK_NULL_HANDLE surface", destroyNullHandleSurfaceTest, wsiType);
1318 if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1319 addFunctionCase(testGroup, "initial_size", "Create surface with initial window size set", createSurfaceInitialSizeTest, wsiType);
1321 if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1322 addFunctionCase(testGroup, "resize", "Resize window and surface", resizeSurfaceTest, wsiType);