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 VkSwapchain Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktWsiSwapchainTests.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 "vkCmdUtil.hpp"
44 #include "vkObjTypeImpl.inl"
45 #include "vkObjUtil.hpp"
47 #include "tcuCommandLine.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuFormatUtil.hpp"
50 #include "tcuPlatform.hpp"
51 #include "tcuResultCollector.hpp"
53 #include "deUniquePtr.hpp"
54 #include "deStringUtil.hpp"
55 #include "deArrayUtil.hpp"
56 #include "deSharedPtr.hpp"
71 using namespace vk::wsi;
84 typedef vector<VkExtensionProperties> Extensions;
86 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
88 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
89 requiredExtName != requiredExtensions.end();
92 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
93 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
97 CustomInstance createInstanceWithWsi (Context& context,
98 const Extensions& supportedExtensions,
100 const vector<string> extraExtensions,
101 const VkAllocationCallbacks* pAllocator = DE_NULL)
103 vector<string> extensions = extraExtensions;
105 extensions.push_back("VK_KHR_surface");
106 extensions.push_back(getExtensionName(wsiType));
108 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
109 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
110 // but using them without enabling the extension is not allowed. Thus we have
113 // 1) Filter out non-core formats to stay within valid usage.
115 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
117 // We opt for (2) as it provides basic coverage for the extension as a bonus.
118 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
119 extensions.push_back("VK_EXT_swapchain_colorspace");
121 checkAllSupported(supportedExtensions, extensions);
123 return vkt::createCustomInstanceWithExtensions(context, extensions, pAllocator);
126 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
128 VkPhysicalDeviceFeatures features;
129 deMemset(&features, 0, sizeof(features));
133 Move<VkDevice> createDeviceWithWsi (const PlatformInterface& vkp,
136 const InstanceInterface& vki,
137 VkPhysicalDevice physicalDevice,
138 const Extensions& supportedExtensions,
139 const vector<string>& additionalExtensions,
140 const vector<deUint32>& queueFamilyIndices,
141 bool validationEnabled,
142 const VkAllocationCallbacks* pAllocator = DE_NULL)
144 const float queuePriorities[] = { 1.0f };
145 vector<VkDeviceQueueCreateInfo> queueInfos;
147 for (const auto familyIndex : queueFamilyIndices)
149 const VkDeviceQueueCreateInfo info =
151 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
153 (VkDeviceQueueCreateFlags)0,
155 DE_LENGTH_OF_ARRAY(queuePriorities),
159 queueInfos.push_back(info);
162 vector<string> extensions;
163 extensions.push_back("VK_KHR_swapchain");
164 extensions.insert(end(extensions), begin(additionalExtensions), end(additionalExtensions));
166 for (const auto& extName : extensions)
168 if (!isCoreDeviceExtension(apiVersion, extName) && !isExtensionSupported(supportedExtensions, RequiredExtension(extName)))
169 TCU_THROW(NotSupportedError, extName + " is not supported");
172 const void * pNext = nullptr;
173 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
175 VkDevicePrivateDataCreateInfoEXT pdci = initVulkanStructure();
176 pdci.privateDataSlotRequestCount = 4u;
178 VkPhysicalDevicePrivateDataFeaturesEXT privateDataFeatures = initVulkanStructure(&pdci);
179 privateDataFeatures.privateData = VK_TRUE;
181 if (de::contains(begin(extensions), end(extensions), "VK_EXT_private_data"))
183 pNext = &privateDataFeatures;
186 // Convert from std::vector<std::string> to std::vector<const char*>.
187 std::vector<const char*> extensionsChar;
188 extensionsChar.reserve(extensions.size());
189 std::transform(begin(extensions), end(extensions), std::back_inserter(extensionsChar), [](const std::string& s) { return s.c_str(); });
191 const VkDeviceCreateInfo deviceParams =
193 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
195 (VkDeviceCreateFlags)0,
196 static_cast<deUint32>(queueInfos.size()),
198 0u, // enabledLayerCount
199 nullptr, // ppEnabledLayerNames
200 static_cast<deUint32>(extensionsChar.size()), // enabledExtensionCount
201 extensionsChar.data(), // ppEnabledExtensionNames
205 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
208 Move<VkDevice> createDeviceWithWsi (const PlatformInterface& vkp,
211 const InstanceInterface& vki,
212 VkPhysicalDevice physicalDevice,
213 const Extensions& supportedExtensions,
214 const vector<string>& additionalExtensions,
215 const deUint32 queueFamilyIndex,
216 bool validationEnabled,
217 const VkAllocationCallbacks* pAllocator = DE_NULL)
219 return createDeviceWithWsi(vkp, apiVersion, instance, vki, physicalDevice, supportedExtensions, additionalExtensions, vector<deUint32>(1u, queueFamilyIndex), validationEnabled, pAllocator);
222 struct InstanceHelper
224 const vector<VkExtensionProperties> supportedExtensions;
225 const CustomInstance instance;
226 const InstanceDriver& vki;
228 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
229 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
231 , instance (createInstanceWithWsi(context,
236 , vki (instance.getDriver())
239 InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
240 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
242 , instance (createInstanceWithWsi(context,
247 , vki (instance.getDriver())
253 const VkPhysicalDevice physicalDevice;
254 const deUint32 queueFamilyIndex;
255 const Unique<VkDevice> device;
256 const DeviceDriver vkd;
259 DeviceHelper (Context& context,
260 const InstanceInterface& vki,
262 const vector<VkSurfaceKHR>& surface,
263 const vector<string>& additionalExtensions = vector<string>(),
264 const VkAllocationCallbacks* pAllocator = DE_NULL)
265 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
266 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
267 , device (createDeviceWithWsi(context.getPlatformInterface(),
268 context.getUsedApiVersion(),
272 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
273 additionalExtensions,
275 context.getTestContext().getCommandLine().isValidationEnabled(),
277 , vkd (context.getPlatformInterface(), instance, *device)
278 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
282 // Single-surface shortcut.
283 DeviceHelper (Context& context,
284 const InstanceInterface& vki,
286 VkSurfaceKHR surface,
287 const vector<string>& additionalExtensions = vector<string>(),
288 const VkAllocationCallbacks* pAllocator = DE_NULL)
289 : DeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
294 // Similar to the one above with no queues and multiple queue families.
295 struct MultiQueueDeviceHelper
297 const VkPhysicalDevice physicalDevice;
298 const vector<deUint32> queueFamilyIndices;
299 const Unique<VkDevice> device;
300 const DeviceDriver vkd;
302 MultiQueueDeviceHelper (Context& context,
303 const InstanceInterface& vki,
305 const vector<VkSurfaceKHR>& surface,
306 const vector<string>& additionalExtensions = vector<string>(),
307 const VkAllocationCallbacks* pAllocator = DE_NULL)
308 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
309 , queueFamilyIndices(getCompatibleQueueFamilyIndices(vki, physicalDevice, surface))
310 , device (createDeviceWithWsi(context.getPlatformInterface(),
311 context.getUsedApiVersion(),
315 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
316 additionalExtensions,
318 context.getTestContext().getCommandLine().isValidationEnabled(),
320 , vkd (context.getPlatformInterface(), instance, *device)
324 // Single-surface shortcut.
325 MultiQueueDeviceHelper (Context& context,
326 const InstanceInterface& vki,
328 VkSurfaceKHR surface,
329 const vector<string> additionalExtensions = vector<string>(),
330 const VkAllocationCallbacks* pAllocator = DE_NULL)
331 : MultiQueueDeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
336 MovePtr<Display> createDisplay (const vk::Platform& platform,
337 const Extensions& supportedExtensions,
342 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
344 catch (const tcu::NotSupportedError& e)
346 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
347 platform.hasDisplay(wsiType))
349 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
350 // must support creating native display & window for that WSI type.
351 throw tcu::TestError(e.getMessage());
358 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
362 return MovePtr<Window>(display.createWindow(initialSize));
364 catch (const tcu::NotSupportedError& e)
366 // See createDisplay - assuming that wsi::Display was supported platform port
367 // should also support creating a window.
368 throw tcu::TestError(e.getMessage());
375 UniquePtr<Display> display;
376 vector<MovePtr<Window>> windows;
379 NativeObjects (Context& context,
380 const Extensions& supportedExtensions,
382 size_t windowCount = 1u,
383 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
384 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
386 DE_ASSERT(windowCount > 0u);
387 for (size_t i = 0; i < windowCount; ++i)
388 windows.emplace_back(createWindow(*display, initialWindowSize));
391 NativeObjects (NativeObjects&& other)
392 : display (other.display.move())
395 windows.swap(other.windows);
398 Display& getDisplay () const
403 Window& getWindow (size_t index = 0u) const
405 DE_ASSERT(index < windows.size());
406 return *windows[index];
412 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
413 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
414 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
415 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
416 TEST_DIMENSION_IMAGE_USAGE,
417 TEST_DIMENSION_IMAGE_SHARING_MODE,
418 TEST_DIMENSION_PRE_TRANSFORM,
419 TEST_DIMENSION_COMPOSITE_ALPHA,
420 TEST_DIMENSION_PRESENT_MODE,
421 TEST_DIMENSION_CLIPPED,
426 const char* getTestDimensionName (TestDimension dimension)
428 static const char* const s_names[] =
433 "image_array_layers",
435 "image_sharing_mode",
441 return de::getSizedArrayElement<TEST_DIMENSION_LAST>(s_names, dimension);
444 struct TestParameters
447 TestDimension dimension;
449 TestParameters (Type wsiType_, TestDimension dimension_)
451 , dimension (dimension_)
454 TestParameters (void)
455 : wsiType (TYPE_LAST)
456 , dimension (TEST_DIMENSION_LAST)
460 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (const InstanceInterface& vki,
461 VkPhysicalDevice physicalDevice,
463 TestDimension dimension,
464 const VkSurfaceCapabilitiesKHR& capabilities,
465 const vector<VkSurfaceFormatKHR>& formats,
466 const vector<VkPresentModeKHR>& presentModes)
468 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
469 vector<VkSwapchainCreateInfoKHR> cases;
470 const VkSurfaceTransformFlagBitsKHR defaultTransform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
471 const VkSwapchainCreateInfoKHR baseParameters =
473 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
475 (VkSwapchainCreateFlagsKHR)0,
477 capabilities.minImageCount,
479 formats[0].colorSpace,
480 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE
481 ? capabilities.minImageExtent : capabilities.currentExtent),
482 1u, // imageArrayLayers
483 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
484 VK_SHARING_MODE_EXCLUSIVE,
486 (const deUint32*)DE_NULL,
488 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
489 VK_PRESENT_MODE_FIFO_KHR,
491 (VkSwapchainKHR)0 // oldSwapchain
496 case TEST_DIMENSION_MIN_IMAGE_COUNT:
498 const deUint32 maxImageCountToTest = de::clamp(16u, capabilities.minImageCount, (capabilities.maxImageCount > 0) ? capabilities.maxImageCount : capabilities.minImageCount + 16u);
500 for (deUint32 imageCount = capabilities.minImageCount; imageCount <= maxImageCountToTest; ++imageCount)
502 cases.push_back(baseParameters);
503 cases.back().minImageCount = imageCount;
509 case TEST_DIMENSION_IMAGE_FORMAT:
511 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
513 cases.push_back(baseParameters);
514 cases.back().imageFormat = curFmt->format;
515 cases.back().imageColorSpace = curFmt->colorSpace;
521 case TEST_DIMENSION_IMAGE_EXTENT:
523 static const VkExtent2D s_testSizes[] =
532 if (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE ||
533 platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE)
535 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_testSizes); ++ndx)
537 cases.push_back(baseParameters);
538 cases.back().imageExtent.width = de::clamp(s_testSizes[ndx].width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
539 cases.back().imageExtent.height = de::clamp(s_testSizes[ndx].height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
543 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE)
545 cases.push_back(baseParameters);
546 cases.back().imageExtent = capabilities.currentExtent;
549 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
551 cases.push_back(baseParameters);
552 cases.back().imageExtent = capabilities.minImageExtent;
554 cases.push_back(baseParameters);
555 cases.back().imageExtent = capabilities.maxImageExtent;
561 case TEST_DIMENSION_IMAGE_ARRAY_LAYERS:
563 const deUint32 maxLayers = de::min(capabilities.maxImageArrayLayers, 16u);
565 for (deUint32 numLayers = 1; numLayers <= maxLayers; ++numLayers)
567 cases.push_back(baseParameters);
568 cases.back().imageArrayLayers = numLayers;
574 case TEST_DIMENSION_IMAGE_USAGE:
576 for (deUint32 flags = 1u; flags <= capabilities.supportedUsageFlags; ++flags)
578 VkImageFormatProperties imageProps;
580 if (vki.getPhysicalDeviceImageFormatProperties(physicalDevice,
581 baseParameters.imageFormat,
583 VK_IMAGE_TILING_OPTIMAL,
585 (VkImageCreateFlags)0u,
586 &imageProps) != VK_SUCCESS)
589 if ((flags & ~capabilities.supportedUsageFlags) == 0)
591 cases.push_back(baseParameters);
592 cases.back().imageUsage = flags;
599 case TEST_DIMENSION_IMAGE_SHARING_MODE:
602 // Skipping since this matches the base parameters.
603 cases.push_back(baseParameters);
604 cases.back().imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
607 cases.push_back(baseParameters);
608 cases.back().imageSharingMode = VK_SHARING_MODE_CONCURRENT;
613 case TEST_DIMENSION_PRE_TRANSFORM:
615 for (deUint32 transform = 1u;
616 transform <= capabilities.supportedTransforms;
617 transform = transform<<1u)
619 if ((transform & capabilities.supportedTransforms) != 0)
621 cases.push_back(baseParameters);
622 cases.back().preTransform = (VkSurfaceTransformFlagBitsKHR)transform;
629 case TEST_DIMENSION_COMPOSITE_ALPHA:
631 for (deUint32 alphaMode = 1u;
632 alphaMode <= capabilities.supportedCompositeAlpha;
633 alphaMode = alphaMode<<1u)
635 if ((alphaMode & capabilities.supportedCompositeAlpha) != 0)
637 cases.push_back(baseParameters);
638 cases.back().compositeAlpha = (VkCompositeAlphaFlagBitsKHR)alphaMode;
645 case TEST_DIMENSION_PRESENT_MODE:
647 for (vector<VkPresentModeKHR>::const_iterator curMode = presentModes.begin(); curMode != presentModes.end(); ++curMode)
649 cases.push_back(baseParameters);
650 cases.back().presentMode = *curMode;
656 case TEST_DIMENSION_CLIPPED:
658 cases.push_back(baseParameters);
659 cases.back().clipped = VK_FALSE;
661 cases.push_back(baseParameters);
662 cases.back().clipped = VK_TRUE;
668 DE_FATAL("Impossible");
671 DE_ASSERT(!cases.empty());
675 vector<VkSwapchainCreateInfoKHR> generateSwapchainParameterCases (Type wsiType,
676 TestDimension dimension,
677 const InstanceInterface& vki,
678 VkPhysicalDevice physicalDevice,
679 VkSurfaceKHR surface)
681 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
684 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(vki,
687 const vector<VkPresentModeKHR> presentModes = getPhysicalDeviceSurfacePresentModes(vki,
691 return generateSwapchainParameterCases(vki, physicalDevice, wsiType, dimension, capabilities, formats, presentModes);
694 tcu::TestStatus createSwapchainTest (Context& context, TestParameters params)
696 tcu::TestLog& log = context.getTestContext().getLog();
697 const InstanceHelper instHelper (context, params.wsiType);
698 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType);
699 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, params.wsiType, native.getDisplay(), native.getWindow()));
700 const MultiQueueDeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
701 const vector<VkSwapchainCreateInfoKHR> cases (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
702 const VkSurfaceCapabilitiesKHR capabilities(getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface));
704 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
706 std::ostringstream subcase;
707 subcase << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": ";
709 VkSwapchainCreateInfoKHR curParams = cases[caseNdx];
711 if (curParams.imageSharingMode == VK_SHARING_MODE_CONCURRENT)
713 const deUint32 numFamilies = static_cast<deUint32>(devHelper.queueFamilyIndices.size());
714 if (numFamilies < 2u)
715 TCU_THROW(NotSupportedError, "Only " + de::toString(numFamilies) + " queue families available for VK_SHARING_MODE_CONCURRENT");
716 curParams.queueFamilyIndexCount = numFamilies;
720 // Take only the first queue.
721 if (devHelper.queueFamilyIndices.empty())
722 TCU_THROW(NotSupportedError, "No queue families compatible with the given surface");
723 curParams.queueFamilyIndexCount = 1u;
725 curParams.pQueueFamilyIndices = devHelper.queueFamilyIndices.data();
726 curParams.surface = *surface;
728 log << TestLog::Message << subcase.str() << curParams << TestLog::EndMessage;
730 // The Vulkan 1.1.87 spec contains the following VU for VkSwapchainCreateInfoKHR:
732 // * imageFormat, imageUsage, imageExtent, and imageArrayLayers must be supported for VK_IMAGE_TYPE_2D
733 // VK_IMAGE_TILING_OPTIMAL images as reported by vkGetPhysicalDeviceImageFormatProperties.
734 VkImageFormatProperties properties;
735 const VkResult propertiesResult = instHelper.vki.getPhysicalDeviceImageFormatProperties(devHelper.physicalDevice,
736 curParams.imageFormat,
738 VK_IMAGE_TILING_OPTIMAL,
739 curParams.imageUsage,
743 log << TestLog::Message << subcase.str()
744 << "vkGetPhysicalDeviceImageFormatProperties => "
745 << getResultStr(propertiesResult) << TestLog::EndMessage;
747 switch (propertiesResult) {
750 // The maxExtents case might not be able to create the requested surface due to insufficient
751 // memory, so in this case *only* we handle the OOM exception.
752 if (params.dimension == TEST_DIMENSION_IMAGE_EXTENT &&
753 capabilities.maxImageExtent.width == curParams.imageExtent.width &&
754 capabilities.maxImageExtent.height == curParams.imageExtent.height)
758 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams));
760 log << TestLog::Message << subcase.str()
761 << "Creating swapchain succeeded" << TestLog::EndMessage;
763 catch (const OutOfMemoryError& e)
765 log << TestLog::Message << subcase.str() << "vkCreateSwapchainKHR with maxImageExtent encountered " << e.getError() << TestLog::EndMessage;
770 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams));
772 log << TestLog::Message << subcase.str()
773 << "Creating swapchain succeeded" << TestLog::EndMessage;
777 case VK_ERROR_FORMAT_NOT_SUPPORTED:
778 log << TestLog::Message << subcase.str()
779 << "Skip because vkGetPhysicalDeviceImageFormatProperties returned VK_ERROR_FORMAT_NOT_SUPPORTED" << TestLog::EndMessage;
782 log << TestLog::Message << subcase.str()
783 << "Fail because vkGetPhysicalDeviceImageFormatProperties returned "
784 << getResultStr(propertiesResult) << TestLog::EndMessage;
785 return tcu::TestStatus::fail("Unexpected result from vkGetPhysicalDeviceImageFormatProperties");
789 return tcu::TestStatus::pass("No sub-case failed");
792 template<typename T> static deUint64 HandleToInt(T t) { return t.getInternal(); }
794 tcu::TestStatus createSwapchainPrivateDataTest (Context& context, TestParameters params)
796 if (!context.getPrivateDataFeaturesEXT().privateData)
797 TCU_THROW(NotSupportedError, "privateData not supported");
799 tcu::TestLog& log = context.getTestContext().getLog();
800 const InstanceHelper instHelper (context, params.wsiType);
801 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType);
802 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, params.wsiType, native.getDisplay(), native.getWindow()));
803 const vector<string> extraExts (1u, "VK_EXT_private_data");
804 const MultiQueueDeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface, extraExts);
805 const vector<VkSwapchainCreateInfoKHR> cases (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
807 for (size_t caseNdx = 0; caseNdx < cases.size(); ++caseNdx)
809 std::ostringstream subcase;
810 subcase << "Sub-case " << (caseNdx+1) << " / " << cases.size() << ": ";
812 VkSwapchainCreateInfoKHR curParams = cases[caseNdx];
814 if (curParams.imageSharingMode == VK_SHARING_MODE_CONCURRENT)
816 const deUint32 numFamilies = static_cast<deUint32>(devHelper.queueFamilyIndices.size());
817 if (numFamilies < 2u)
818 TCU_THROW(NotSupportedError, "Only " + de::toString(numFamilies) + " queue families available for VK_SHARING_MODE_CONCURRENT");
819 curParams.queueFamilyIndexCount = numFamilies;
823 // Take only the first queue.
824 if (devHelper.queueFamilyIndices.empty())
825 TCU_THROW(NotSupportedError, "No queue families compatible with the given surface");
826 curParams.queueFamilyIndexCount = 1u;
828 curParams.pQueueFamilyIndices = devHelper.queueFamilyIndices.data();
829 curParams.surface = *surface;
831 log << TestLog::Message << subcase.str() << curParams << TestLog::EndMessage;
833 // The Vulkan 1.1.87 spec contains the following VU for VkSwapchainCreateInfoKHR:
835 // * imageFormat, imageUsage, imageExtent, and imageArrayLayers must be supported for VK_IMAGE_TYPE_2D
836 // VK_IMAGE_TILING_OPTIMAL images as reported by vkGetPhysicalDeviceImageFormatProperties.
837 VkImageFormatProperties properties;
838 const VkResult propertiesResult = instHelper.vki.getPhysicalDeviceImageFormatProperties(devHelper.physicalDevice,
839 curParams.imageFormat,
841 VK_IMAGE_TILING_OPTIMAL,
842 curParams.imageUsage,
846 log << TestLog::Message << subcase.str()
847 << "vkGetPhysicalDeviceImageFormatProperties => "
848 << getResultStr(propertiesResult) << TestLog::EndMessage;
850 switch (propertiesResult) {
853 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams));
855 const int numSlots = 100;
856 typedef Unique<VkPrivateDataSlotEXT> PrivateDataSlotUp;
857 typedef SharedPtr<PrivateDataSlotUp> PrivateDataSlotSp;
858 vector<PrivateDataSlotSp> slots;
860 const VkPrivateDataSlotCreateInfoEXT createInfo =
862 VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT, // VkStructureType sType;
863 DE_NULL, // const void* pNext;
864 0u, // VkPrivateDataSlotCreateFlagsEXT flags;
867 for (int i = 0; i < numSlots; ++i)
869 Move<VkPrivateDataSlotEXT> s = createPrivateDataSlotEXT(devHelper.vkd, *devHelper.device, &createInfo, DE_NULL);
870 slots.push_back(PrivateDataSlotSp(new PrivateDataSlotUp(s)));
873 // Based on code in vktApiObjectManagementTests.cpp
874 for (int r = 0; r < 3; ++r)
878 for (int i = 0; i < numSlots; ++i)
881 devHelper.vkd.getPrivateDataEXT(*devHelper.device, getObjectType<VkSwapchainKHR>(), HandleToInt(swapchain.get()), **slots[i], &data);
882 // Don't test default value of zero on Android, due to spec erratum
883 if (params.wsiType != TYPE_ANDROID)
886 return tcu::TestStatus::fail("Expected initial value of zero");
890 for (int i = 0; i < numSlots; ++i)
891 VK_CHECK(devHelper.vkd.setPrivateDataEXT(*devHelper.device, getObjectType<VkSwapchainKHR>(), HandleToInt(swapchain.get()), **slots[i], i*i*i + 1));
893 for (int i = 0; i < numSlots; ++i)
896 devHelper.vkd.getPrivateDataEXT(*devHelper.device, getObjectType<VkSwapchainKHR>(), HandleToInt(swapchain.get()), **slots[i], &data);
897 if (data != (deUint64)(i*i*i + 1))
898 return tcu::TestStatus::fail("Didn't read back set value");
901 // Destroy and realloc slots for the next iteration
903 for (int i = 0; i < numSlots; ++i)
905 Move<VkPrivateDataSlotEXT> s = createPrivateDataSlotEXT(devHelper.vkd, *devHelper.device, &createInfo, DE_NULL);
906 slots.push_back(PrivateDataSlotSp(new PrivateDataSlotUp(s)));
913 case VK_ERROR_FORMAT_NOT_SUPPORTED:
914 log << TestLog::Message << subcase.str()
915 << "Skip because vkGetPhysicalDeviceImageFormatProperties returned VK_ERROR_FORMAT_NOT_SUPPORTED" << TestLog::EndMessage;
918 log << TestLog::Message << subcase.str()
919 << "Fail because vkGetPhysicalDeviceImageFormatProperties returned "
920 << getResultStr(propertiesResult) << TestLog::EndMessage;
921 return tcu::TestStatus::fail("Unexpected result from vkGetPhysicalDeviceImageFormatProperties");
925 return tcu::TestStatus::pass("No sub-case failed");
928 tcu::TestStatus createSwapchainSimulateOOMTest (Context& context, TestParameters params)
930 const size_t maxCases = 300u;
931 const deUint32 maxAllocs = 1024u;
933 tcu::TestLog& log = context.getTestContext().getLog();
934 tcu::ResultCollector results (log);
936 AllocationCallbackRecorder allocationRecorder (getSystemAllocator());
937 DeterministicFailAllocator failingAllocator (allocationRecorder.getCallbacks(),
938 DeterministicFailAllocator::MODE_DO_NOT_COUNT,
941 const InstanceHelper instHelper (context, params.wsiType, failingAllocator.getCallbacks());
942 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType);
943 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
948 failingAllocator.getCallbacks()));
949 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface, vector<string>(), failingAllocator.getCallbacks());
950 const vector<VkSwapchainCreateInfoKHR> allCases (generateSwapchainParameterCases(params.wsiType, params.dimension, instHelper.vki, devHelper.physicalDevice, *surface));
951 const VkSurfaceCapabilitiesKHR capabilities(getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface));
953 if (maxCases < allCases.size())
954 log << TestLog::Message << "Note: Will only test first " << maxCases << " cases out of total of " << allCases.size() << " parameter combinations" << TestLog::EndMessage;
956 for (size_t caseNdx = 0; caseNdx < de::min(maxCases, allCases.size()); ++caseNdx)
958 log << TestLog::Message << "Testing parameter case " << caseNdx << ": " << allCases[caseNdx] << TestLog::EndMessage;
960 for (deUint32 numPassingAllocs = 0; numPassingAllocs <= maxAllocs; ++numPassingAllocs)
963 VkSwapchainCreateInfoKHR curParams = allCases[caseNdx];
964 curParams.surface = *surface;
965 curParams.queueFamilyIndexCount = 1u;
966 curParams.pQueueFamilyIndices = &devHelper.queueFamilyIndex;
968 failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
970 log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
974 // With concurrent sharing mode, at least two queues are needed.
975 if (curParams.imageSharingMode == VK_SHARING_MODE_CONCURRENT)
978 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &curParams, failingAllocator.getCallbacks()));
980 catch (const OutOfMemoryError& e)
982 log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
988 log << TestLog::Message << "Creating swapchain succeeded!" << TestLog::EndMessage;
990 if (numPassingAllocs == 0)
991 results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
995 else if (numPassingAllocs == maxAllocs)
997 // The maxExtents case might not be able to create the requested surface due to insufficient
998 // memory, so in this case *only* we allow the OOM exception upto maxAllocs.
999 if (params.dimension == TEST_DIMENSION_IMAGE_EXTENT &&
1000 capabilities.maxImageExtent.width == curParams.imageExtent.width &&
1001 capabilities.maxImageExtent.height == curParams.imageExtent.height)
1004 results.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Creating swapchain did not succeed, callback limit exceeded");
1008 context.getTestContext().touchWatchdog();
1012 if (!validateAndLog(log, allocationRecorder, 0u))
1013 results.fail("Detected invalid system allocation callback");
1015 return tcu::TestStatus(results.getResult(), results.getMessage());
1018 tcu::TestStatus testImageSwapchainCreateInfo (Context& context, Type wsiType)
1020 const tcu::UVec2 desiredSize (256, 256);
1021 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1022 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
1023 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki,
1024 instHelper.instance,
1026 native.getDisplay(),
1027 native.getWindow()));
1028 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface, vector<string>(1u, "VK_KHR_bind_memory2"));
1029 const Extensions& deviceExtensions = enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL);
1031 // structures this tests checks were added in revision 69
1032 if (!isExtensionSupported(deviceExtensions, RequiredExtension("VK_KHR_swapchain", 69)))
1033 TCU_THROW(NotSupportedError, "Required extension revision is not supported");
1035 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
1036 devHelper.physicalDevice,
1038 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
1039 devHelper.physicalDevice,
1041 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
1042 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
1043 const deUint32 desiredImageCount = 2;
1044 const VkSwapchainCreateInfoKHR swapchainInfo =
1046 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
1048 (VkSwapchainCreateFlagsKHR)0,
1050 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
1052 formats[0].colorSpace,
1053 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
1054 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
1056 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1057 VK_SHARING_MODE_EXCLUSIVE,
1059 (const deUint32*)DE_NULL,
1061 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
1062 VK_PRESENT_MODE_FIFO_KHR,
1063 VK_FALSE, // clipped
1064 (VkSwapchainKHR)0 // oldSwapchain
1067 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
1068 deUint32 numImages = 0;
1069 VK_CHECK(devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &numImages, DE_NULL));
1071 return tcu::TestStatus::pass("Pass");
1073 VkImageSwapchainCreateInfoKHR imageSwapchainCreateInfo =
1075 VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR,
1080 VkImageCreateInfo imageCreateInfo =
1082 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1083 &imageSwapchainCreateInfo,
1084 (VkImageCreateFlags)0u, // flags
1085 VK_IMAGE_TYPE_2D, // imageType
1086 formats[0].format, // format
1088 desiredSize.x(), // width
1089 desiredSize.y(), // height
1094 VK_SAMPLE_COUNT_1_BIT, // samples
1095 VK_IMAGE_TILING_OPTIMAL, // tiling
1096 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // usage
1097 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1098 0u, // queueFamilyIndexCount
1099 DE_NULL, // pQueueFamilyIndices
1100 VK_IMAGE_LAYOUT_UNDEFINED // initialLayout
1103 typedef vk::Unique<VkImage> UniqueImage;
1104 typedef de::SharedPtr<UniqueImage> ImageSp;
1106 std::vector<ImageSp> images (numImages);
1107 std::vector<VkBindImageMemorySwapchainInfoKHR> bindImageMemorySwapchainInfo(numImages);
1108 std::vector<VkBindImageMemoryInfo> bindImageMemoryInfos (numImages);
1110 for (deUint32 idx = 0; idx < numImages; ++idx)
1113 images[idx] = ImageSp(new UniqueImage(createImage(devHelper.vkd, *devHelper.device, &imageCreateInfo)));
1115 VkBindImageMemorySwapchainInfoKHR bimsInfo =
1117 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR,
1122 bindImageMemorySwapchainInfo[idx] = bimsInfo;
1124 VkBindImageMemoryInfo bimInfo =
1126 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
1127 &bindImageMemorySwapchainInfo[idx],
1129 DE_NULL, // If the pNext chain includes an instance of VkBindImageMemorySwapchainInfoKHR, memory must be VK_NULL_HANDLE
1130 0u // If swapchain <in VkBindImageMemorySwapchainInfoKHR> is not NULL, the swapchain and imageIndex are used to determine the memory that the image is bound to, instead of memory and memoryOffset.
1133 bindImageMemoryInfos[idx] = bimInfo;
1136 VK_CHECK(devHelper.vkd.bindImageMemory2(*devHelper.device, numImages, &bindImageMemoryInfos[0]));
1138 return tcu::TestStatus::pass("Pass");
1141 struct GroupParameters
1143 typedef FunctionInstance1<TestParameters>::Function Function;
1148 GroupParameters (Type wsiType_, Function function_)
1149 : wsiType (wsiType_)
1150 , function (function_)
1153 GroupParameters (void)
1154 : wsiType (TYPE_LAST)
1155 , function ((Function)DE_NULL)
1159 void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters params)
1161 for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
1163 const TestDimension testDimension = (TestDimension)dimensionNdx;
1165 addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension));
1168 addFunctionCase(testGroup, "image_swapchain_create_info", "Test VkImageSwapchainCreateInfoKHR", testImageSwapchainCreateInfo, params.wsiType);
1171 void populateSwapchainPrivateDataGroup (tcu::TestCaseGroup* testGroup, GroupParameters params)
1173 for (int dimensionNdx = 0; dimensionNdx < TEST_DIMENSION_LAST; ++dimensionNdx)
1175 const TestDimension testDimension = (TestDimension)dimensionNdx;
1176 if (testDimension == TEST_DIMENSION_IMAGE_EXTENT)
1179 addFunctionCase(testGroup, getTestDimensionName(testDimension), "", params.function, TestParameters(params.wsiType, testDimension));
1183 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
1184 const InstanceInterface& vki,
1185 VkPhysicalDevice physicalDevice,
1186 VkSurfaceKHR surface,
1187 const tcu::UVec2& desiredSize,
1188 deUint32 desiredImageCount)
1190 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
1193 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(vki,
1196 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
1197 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
1198 const VkSwapchainCreateInfoKHR parameters =
1200 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
1202 (VkSwapchainCreateFlagsKHR)0,
1204 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
1206 formats[0].colorSpace,
1207 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
1208 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
1209 1u, // imageArrayLayers
1210 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1211 VK_SHARING_MODE_EXCLUSIVE,
1213 (const deUint32*)DE_NULL,
1215 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
1216 VK_PRESENT_MODE_FIFO_KHR,
1217 VK_FALSE, // clipped
1218 (VkSwapchainKHR)0 // oldSwapchain
1224 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
1225 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
1226 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
1228 vector<FenceSp> createFences (const DeviceInterface& vkd,
1229 const VkDevice device,
1231 bool isSignaled = true)
1233 vector<FenceSp> fences(numFences);
1235 for (size_t ndx = 0; ndx < numFences; ++ndx)
1236 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device, (isSignaled) ? vk::VK_FENCE_CREATE_SIGNALED_BIT : 0)));
1241 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
1242 const VkDevice device,
1243 size_t numSemaphores)
1245 vector<SemaphoreSp> semaphores(numSemaphores);
1247 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
1248 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
1253 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
1254 const VkDevice device,
1255 const VkCommandPool commandPool,
1256 const VkCommandBufferLevel level,
1257 const size_t numCommandBuffers)
1259 vector<CommandBufferSp> buffers (numCommandBuffers);
1261 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
1262 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
1267 class AcquireNextImageWrapper
1271 AcquireNextImageWrapper(const DeviceInterface& vkd,
1273 deUint32 deviceMask,
1274 VkSwapchainKHR swapchain,
1278 , m_swapchain (swapchain)
1279 , m_timeout (timeout)
1281 DE_UNREF(deviceMask); // needed for compatibility with acquireNextImage2KHR
1284 bool featureAvailable(Context&)
1286 return true; // needed for compatibility with acquireNextImage2KHR
1289 VkResult call(VkSemaphore semaphore, VkFence fence, deUint32* imageIndex)
1291 return m_vkd.acquireNextImageKHR(m_device,
1301 const DeviceInterface& m_vkd;
1303 VkSwapchainKHR m_swapchain;
1307 class AcquireNextImage2Wrapper
1311 AcquireNextImage2Wrapper(const DeviceInterface& vkd,
1313 deUint32 deviceMask,
1314 VkSwapchainKHR swapchain,
1319 m_info.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR;
1320 m_info.pNext = DE_NULL;
1321 m_info.swapchain = swapchain;
1322 m_info.timeout = timeout;
1323 m_info.semaphore = DE_NULL;
1324 m_info.fence = DE_NULL;
1325 m_info.deviceMask = deviceMask;
1328 bool featureAvailable(Context& context)
1330 return context.isDeviceFunctionalitySupported("VK_KHR_device_group");
1333 VkResult call(VkSemaphore semaphore, VkFence fence, deUint32* imageIndex)
1335 m_info.semaphore = semaphore;
1336 m_info.fence = fence;
1337 return m_vkd.acquireNextImage2KHR(m_device,
1344 const DeviceInterface& m_vkd;
1346 VkAcquireNextImageInfoKHR m_info;
1350 template <typename AcquireWrapperType>
1351 tcu::TestStatus basicRenderTest (Context& context, Type wsiType)
1353 const tcu::UVec2 desiredSize (256, 256);
1354 const InstanceHelper instHelper (context, wsiType);
1355 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
1356 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
1357 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
1358 const DeviceInterface& vkd = devHelper.vkd;
1359 const VkDevice device = *devHelper.device;
1360 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1361 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
1362 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
1363 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
1365 AcquireWrapperType acquireImageWrapper(vkd, device, 1u, *swapchain, std::numeric_limits<deUint64>::max());
1366 if (!acquireImageWrapper.featureAvailable(context))
1367 TCU_THROW(NotSupportedError, "Required extension is not supported");
1369 const WsiTriangleRenderer renderer (vkd,
1372 context.getBinaryCollection(),
1376 swapchainInfo.imageFormat,
1377 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1379 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1381 const size_t maxQueuedFrames = swapchainImages.size()*2;
1383 // We need to keep hold of fences from vkAcquireNextImage(2)KHR to actually
1384 // limit number of frames we allow to be queued.
1385 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
1387 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
1388 // the semaphore in same time as the fence we use to meter rendering.
1389 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
1391 // For rest we simply need maxQueuedFrames as we will wait for image
1392 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
1393 // previous uses must have completed.
1394 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
1395 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1399 const deUint32 numFramesToRender = 60*10;
1401 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1403 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
1404 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1405 deUint32 imageNdx = ~0u;
1407 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1408 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
1411 const VkResult acquireResult = acquireImageWrapper.call(imageReadySemaphore, (VkFence)0, &imageNdx);
1413 if (acquireResult == VK_SUBOPTIMAL_KHR)
1414 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1416 VK_CHECK(acquireResult);
1419 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1422 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1423 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
1424 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1425 const VkSubmitInfo submitInfo =
1427 VK_STRUCTURE_TYPE_SUBMIT_INFO,
1430 &imageReadySemaphore,
1435 &renderingCompleteSemaphore
1437 const VkPresentInfoKHR presentInfo =
1439 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1442 &renderingCompleteSemaphore,
1449 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
1450 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
1451 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1455 VK_CHECK(vkd.deviceWaitIdle(device));
1459 // Make sure device is idle before destroying resources
1460 vkd.deviceWaitIdle(device);
1464 return tcu::TestStatus::pass("Rendering tests succeeded");
1467 class FrameStreamObjects
1472 const vk::VkFence& renderCompleteFence;
1473 const vk::VkSemaphore& renderCompleteSemaphore;
1474 const vk::VkSemaphore& imageAvailableSemaphore;
1475 const vk::VkCommandBuffer& commandBuffer;
1478 FrameStreamObjects (const vk::DeviceInterface& vkd, vk::VkDevice device, vk::VkCommandPool cmdPool, size_t maxQueuedFrames)
1479 : renderingCompleteFences(createFences(vkd, device, maxQueuedFrames))
1480 , renderingCompleteSemaphores(createSemaphores(vkd, device, maxQueuedFrames))
1481 , imageAvailableSemaphores(createSemaphores(vkd, device, maxQueuedFrames))
1482 , commandBuffers(allocateCommandBuffers(vkd, device, cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames))
1483 , m_maxQueuedFrames(maxQueuedFrames)
1487 size_t frameNumber (void) const { DE_ASSERT(m_nextFrame > 0u); return m_nextFrame - 1u; }
1489 FrameObjects newFrame ()
1491 const size_t mod = m_nextFrame % m_maxQueuedFrames;
1494 **renderingCompleteFences[mod],
1495 **renderingCompleteSemaphores[mod],
1496 **imageAvailableSemaphores[mod],
1497 **commandBuffers[mod],
1504 const vector<FenceSp> renderingCompleteFences;
1505 const vector<SemaphoreSp> renderingCompleteSemaphores;
1506 const vector<SemaphoreSp> imageAvailableSemaphores;
1507 const vector<CommandBufferSp> commandBuffers;
1509 const size_t m_maxQueuedFrames;
1513 struct MultiSwapchainParams
1516 size_t swapchainCount;
1519 struct AccumulatedPresentInfo
1521 vector<VkSemaphore> semaphores;
1522 vector<VkSwapchainKHR> swapchains;
1523 vector<deUint32> imageIndices;
1525 AccumulatedPresentInfo ()
1526 : semaphores(), swapchains(), imageIndices()
1530 void push_back (VkSemaphore sem, VkSwapchainKHR sc, deUint32 index)
1532 semaphores.push_back(sem);
1533 swapchains.push_back(sc);
1534 imageIndices.push_back(index);
1539 semaphores.resize(0);
1540 swapchains.resize(0);
1541 imageIndices.resize(0);
1544 size_t size () const
1546 // Any of the vectors would do.
1547 return semaphores.size();
1551 template <typename AcquireWrapperType>
1552 tcu::TestStatus multiSwapchainRenderTest (Context& context, MultiSwapchainParams params)
1554 DE_ASSERT(params.swapchainCount > 0);
1556 const tcu::UVec2 desiredSize (256, 256);
1557 const InstanceHelper instHelper (context, params.wsiType);
1559 // Create native window system objects, surfaces and helper surface vector.
1560 std::unique_ptr<NativeObjects> native;
1563 native.reset(new NativeObjects(context, instHelper.supportedExtensions, params.wsiType, params.swapchainCount, tcu::just(desiredSize)));
1565 catch(tcu::ResourceError&)
1567 std::ostringstream msg;
1568 msg << "Unable to create " << params.swapchainCount << " windows";
1569 TCU_THROW(NotSupportedError, msg.str());
1572 vector<Move<VkSurfaceKHR>> surface;
1573 vector<VkSurfaceKHR> surfaceKHR; // The plain Vulkan objects from the vector above.
1575 for (size_t i = 0; i < params.swapchainCount; ++i)
1577 surface.emplace_back(createSurface(instHelper.vki, instHelper.instance, params.wsiType, native->getDisplay(), native->getWindow(i)));
1578 surfaceKHR.push_back(surface.back().get());
1581 // Create a device compatible with all surfaces.
1582 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, surfaceKHR);
1583 const DeviceInterface& vkd = devHelper.vkd;
1584 const VkDevice device = *devHelper.device;
1585 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1587 // Create several swapchains and images.
1588 vector<VkSwapchainCreateInfoKHR> swapchainInfo;
1589 vector<Move<VkSwapchainKHR>> swapchain;
1590 vector<vector<VkImage>> swapchainImages;
1591 vector<AcquireWrapperType> acquireImageWrapper;
1592 for (size_t i = 0; i < params.swapchainCount; ++i)
1594 swapchainInfo.emplace_back(getBasicSwapchainParameters(params.wsiType, instHelper.vki, devHelper.physicalDevice, *surface[i], desiredSize, 2));
1595 swapchain.emplace_back(createSwapchainKHR(vkd, device, &swapchainInfo.back()));
1596 swapchainImages.emplace_back(getSwapchainImages(vkd, device, swapchain.back().get()));
1597 acquireImageWrapper.emplace_back(vkd, device, 1u, swapchain.back().get(), std::numeric_limits<deUint64>::max());
1600 // Every acquire wrapper requires the same features, so we only check the first one.
1601 if (!acquireImageWrapper.front().featureAvailable(context))
1602 TCU_THROW(NotSupportedError, "Required extension is not supported");
1604 // Renderer per swapchain.
1605 vector<WsiTriangleRenderer> renderer;
1606 for (size_t i = 0; i < params.swapchainCount; ++i)
1608 renderer.emplace_back(vkd,
1611 context.getBinaryCollection(),
1615 swapchainInfo[i].imageFormat,
1616 tcu::UVec2(swapchainInfo[i].imageExtent.width, swapchainInfo[i].imageExtent.height));
1619 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1620 const size_t maxQueuedFrames = swapchainImages.front().size()*2; // Limit in-flight frames.
1622 vector<FrameStreamObjects> frameStreamObjects;
1623 for (size_t i = 0; i < params.swapchainCount; ++i)
1624 frameStreamObjects.emplace_back(vkd, device, commandPool.get(), maxQueuedFrames);
1628 // 3 seconds for 60 Hz screens.
1629 const deUint32 kNumFramesToRender = 60*3*static_cast<deUint32>(params.swapchainCount);
1630 AccumulatedPresentInfo accumulatedPresentInfo;
1632 for (size_t frameNdx = 0; frameNdx < kNumFramesToRender; ++frameNdx)
1634 size_t swapchainIndex = frameNdx % params.swapchainCount;
1635 auto& fsObjects = frameStreamObjects[swapchainIndex];
1636 auto frameObjects = fsObjects.newFrame();
1637 deUint32 imageNdx = std::numeric_limits<deUint32>::max();
1639 VK_CHECK(vkd.waitForFences(device, 1u, &frameObjects.renderCompleteFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1640 VK_CHECK(vkd.resetFences(device, 1u, &frameObjects.renderCompleteFence));
1643 const VkResult acquireResult = acquireImageWrapper[swapchainIndex].call(frameObjects.imageAvailableSemaphore, (VkFence)DE_NULL, &imageNdx);
1644 if (acquireResult == VK_SUBOPTIMAL_KHR)
1645 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1647 VK_CHECK(acquireResult);
1650 TCU_CHECK(static_cast<size_t>(imageNdx) < swapchainImages[swapchainIndex].size());
1653 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1654 const VkSubmitInfo submitInfo =
1656 VK_STRUCTURE_TYPE_SUBMIT_INFO,
1659 &frameObjects.imageAvailableSemaphore,
1662 &frameObjects.commandBuffer,
1664 &frameObjects.renderCompleteSemaphore,
1667 renderer[swapchainIndex].recordFrame(frameObjects.commandBuffer, imageNdx, static_cast<deUint32>(frameNdx));
1668 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, frameObjects.renderCompleteFence));
1670 // Save present information for the current frame.
1671 accumulatedPresentInfo.push_back(frameObjects.renderCompleteSemaphore, swapchain[swapchainIndex].get(), imageNdx);
1673 // Present frames when we have accumulated one frame per swapchain.
1674 if (accumulatedPresentInfo.size() == params.swapchainCount)
1676 DE_ASSERT( accumulatedPresentInfo.semaphores.size() == accumulatedPresentInfo.swapchains.size() &&
1677 accumulatedPresentInfo.semaphores.size() == accumulatedPresentInfo.imageIndices.size() );
1679 vector<VkResult> results(params.swapchainCount, VK_ERROR_DEVICE_LOST);
1681 const VkPresentInfoKHR presentInfo =
1683 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1685 static_cast<deUint32>(accumulatedPresentInfo.semaphores.size()),
1686 accumulatedPresentInfo.semaphores.data(),
1687 static_cast<deUint32>(accumulatedPresentInfo.swapchains.size()),
1688 accumulatedPresentInfo.swapchains.data(),
1689 accumulatedPresentInfo.imageIndices.data(),
1693 // Check both the global result and the individual results.
1694 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1695 for (const auto& result : results)
1696 VK_CHECK_WSI(result);
1698 accumulatedPresentInfo.reset();
1703 VK_CHECK(vkd.deviceWaitIdle(device));
1707 // Make sure device is idle before destroying resources
1708 vkd.deviceWaitIdle(device);
1712 return tcu::TestStatus::pass("Rendering tests succeeded");
1715 tcu::TestStatus deviceGroupRenderTest (Context& context, Type wsiType)
1717 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1718 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
1719 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1720 const Extensions& supportedExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1722 std::vector<const char*> deviceExtensions;
1723 deviceExtensions.push_back("VK_KHR_swapchain");
1724 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1725 deviceExtensions.push_back("VK_KHR_device_group");
1727 for (std::size_t ndx = 0; ndx < deviceExtensions.size(); ++ndx)
1729 if (!isExtensionSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1730 TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1733 const tcu::UVec2 desiredSize (256, 256);
1734 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
1735 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
1737 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1738 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1739 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1740 deUint32 physicalDevicesInGroupCount = deviceGroupProps[devGroupIdx].physicalDeviceCount;
1741 const VkPhysicalDevice* physicalDevicesInGroup = deviceGroupProps[devGroupIdx].physicalDevices;
1742 deUint32 queueFamilyIndex = chooseQueueFamilyIndex(instHelper.vki, physicalDevicesInGroup[deviceIdx], *surface);
1743 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, physicalDevicesInGroup[deviceIdx]);
1744 const float queuePriority = 1.0f;
1745 const deUint32 firstDeviceID = 0;
1746 const deUint32 secondDeviceID = 1;
1748 // create a device group
1749 const VkDeviceGroupDeviceCreateInfo groupDeviceInfo =
1751 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, // stype
1753 physicalDevicesInGroupCount, // physicalDeviceCount
1754 physicalDevicesInGroup // physicalDevices
1756 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1758 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // type
1760 (VkDeviceQueueCreateFlags)0u, // flags
1761 queueFamilyIndex, // queueFamilyIndex
1763 &queuePriority, // pQueuePriorities
1766 const VkDeviceCreateInfo deviceCreateInfo =
1768 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
1769 &groupDeviceInfo, // pNext
1770 (VkDeviceCreateFlags)0u, // flags
1771 1, // queueRecordCount
1772 &deviceQueueCreateInfo, // pRequestedQueues
1774 DE_NULL, // ppEnabledLayerNames
1775 deUint32(deviceExtensions.size()), // enabledExtensionCount
1776 &deviceExtensions[0], // ppEnabledExtensionNames
1777 DE_NULL, // pEnabledFeatures
1780 Move<VkDevice> groupDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, physicalDevicesInGroup[deviceIdx], &deviceCreateInfo);
1781 const DeviceDriver vkd (context.getPlatformInterface(), instHelper.instance, *groupDevice);
1782 VkQueue queue (getDeviceQueue(vkd, *groupDevice, queueFamilyIndex, 0));
1783 SimpleAllocator allocator (vkd, *groupDevice, getPhysicalDeviceMemoryProperties(instHelper.vki, physicalDevicesInGroup[deviceIdx]));
1785 // create swapchain for device group
1786 VkDeviceGroupSwapchainCreateInfoKHR deviceGroupSwapchainInfo = initVulkanStructure();
1787 deviceGroupSwapchainInfo.modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1789 VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType,
1791 physicalDevicesInGroup[deviceIdx],
1795 swapchainInfo.pNext = &deviceGroupSwapchainInfo;
1797 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, *groupDevice, &swapchainInfo));
1798 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, *groupDevice, *swapchain);
1800 const WsiTriangleRenderer renderer (vkd,
1803 context.getBinaryCollection(),
1807 swapchainInfo.imageFormat,
1808 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1810 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, *groupDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1812 const size_t maxQueuedFrames = swapchainImages.size()*2;
1814 // We need to keep hold of fences from vkAcquireNextImage2KHR
1815 // to actually limit number of frames we allow to be queued.
1816 const vector<FenceSp> imageReadyFences (createFences(vkd, *groupDevice, maxQueuedFrames));
1818 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to
1819 // pass the semaphore in same time as the fence we use to meter rendering.
1820 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, *groupDevice, maxQueuedFrames+1));
1822 // For rest we simply need maxQueuedFrames as we will wait for image from frameNdx-maxQueuedFrames
1823 // to become available to us, guaranteeing that previous uses must have completed.
1824 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, *groupDevice, maxQueuedFrames));
1825 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, *groupDevice, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1829 const deUint32 numFramesToRender = 60*10;
1831 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1833 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
1834 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1835 deUint32 imageNdx = ~0u;
1837 VK_CHECK(vkd.waitForFences(*groupDevice, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1838 VK_CHECK(vkd.resetFences(*groupDevice, 1, &imageReadyFence));
1841 VkAcquireNextImageInfoKHR acquireNextImageInfo =
1843 VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
1846 std::numeric_limits<deUint64>::max(),
1847 imageReadySemaphore,
1849 (1 << firstDeviceID)
1852 const VkResult acquireResult = vkd.acquireNextImage2KHR(*groupDevice, &acquireNextImageInfo, &imageNdx);
1854 if (acquireResult == VK_SUBOPTIMAL_KHR)
1855 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1857 VK_CHECK(acquireResult);
1860 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1863 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1864 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
1865 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1867 // render triangle using one or two subdevices when available
1868 renderer.recordDeviceGroupFrame(commandBuffer, firstDeviceID, secondDeviceID, physicalDevicesInGroupCount, imageNdx, frameNdx);
1871 deUint32 deviceMask = (1 << firstDeviceID);
1872 std::vector<deUint32> deviceIndices(1, firstDeviceID);
1873 if (physicalDevicesInGroupCount > 1)
1875 deviceMask |= (1 << secondDeviceID);
1876 deviceIndices.push_back(secondDeviceID);
1878 const VkDeviceGroupSubmitInfo deviceGroupSubmitInfo =
1880 VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR, // sType
1882 deUint32(deviceIndices.size()), // waitSemaphoreCount
1883 &deviceIndices[0], // pWaitSemaphoreDeviceIndices
1884 1u, // commandBufferCount
1885 &deviceMask, // pCommandBufferDeviceMasks
1886 deUint32(deviceIndices.size()), // signalSemaphoreCount
1887 &deviceIndices[0], // pSignalSemaphoreDeviceIndices
1889 const VkSubmitInfo submitInfo =
1891 VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
1892 &deviceGroupSubmitInfo, // pNext
1893 1u, // waitSemaphoreCount
1894 &imageReadySemaphore, // pWaitSemaphores
1895 &waitDstStage, // pWaitDstStageMask
1896 1u, // commandBufferCount
1897 &commandBuffer, // pCommandBuffers
1898 1u, // signalSemaphoreCount
1899 &renderingCompleteSemaphore, // pSignalSemaphores
1901 VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, imageReadyFence));
1903 // present swapchain image
1904 deviceMask = (1 << firstDeviceID);
1905 const VkDeviceGroupPresentInfoKHR deviceGroupPresentInfo =
1907 VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR,
1911 VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR,
1913 const VkPresentInfoKHR presentInfo =
1915 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1916 &deviceGroupPresentInfo,
1918 &renderingCompleteSemaphore,
1924 VK_CHECK_WSI(vkd.queuePresentKHR(queue, &presentInfo));
1928 VK_CHECK(vkd.deviceWaitIdle(*groupDevice));
1932 // Make sure device is idle before destroying resources
1933 vkd.deviceWaitIdle(*groupDevice);
1937 return tcu::TestStatus::pass("Rendering tests succeeded");
1940 tcu::TestStatus deviceGroupRenderTest2 (Context& context, Type wsiType)
1942 const InstanceHelper instHelper (context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1943 const tcu::CommandLine& cmdLine = context.getTestContext().getCommandLine();
1944 VkPhysicalDevice physicalDevice = chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1945 const Extensions& deviceExtensions = enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1947 // structures this tests checks were added in revision 69
1948 if (!isExtensionSupported(deviceExtensions, RequiredExtension("VK_KHR_swapchain", 69)))
1949 TCU_THROW(NotSupportedError, "Required extension revision is not supported");
1951 std::vector<const char*> requiredExtensions;
1952 requiredExtensions.push_back("VK_KHR_swapchain");
1953 if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1955 requiredExtensions.push_back("VK_KHR_device_group");
1956 if (!isExtensionSupported(deviceExtensions, RequiredExtension("VK_KHR_device_group")))
1957 TCU_THROW(NotSupportedError, "VK_KHR_device_group is not supported");
1960 const tcu::UVec2 desiredSize (256, 256);
1961 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
1962 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
1964 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
1965 const deUint32 deviceIdx = context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1966 const vector<VkPhysicalDeviceGroupProperties> deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1967 deUint32 physicalDevicesInGroupCount = deviceGroupProps[devGroupIdx].physicalDeviceCount;
1968 const VkPhysicalDevice* physicalDevicesInGroup = deviceGroupProps[devGroupIdx].physicalDevices;
1969 deUint32 queueFamilyIndex = chooseQueueFamilyIndex(instHelper.vki, physicalDevicesInGroup[deviceIdx], *surface);
1970 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instHelper.vki, physicalDevicesInGroup[deviceIdx]);
1971 const float queuePriority = 1.0f;
1972 const deUint32 firstDeviceID = 0;
1973 const deUint32 secondDeviceID = 1;
1974 const deUint32 deviceIndices[] = { firstDeviceID, secondDeviceID };
1976 if (physicalDevicesInGroupCount < 2)
1977 TCU_THROW(NotSupportedError, "Test requires more than 1 device in device group");
1979 // create a device group
1980 const VkDeviceGroupDeviceCreateInfo groupDeviceInfo =
1982 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, // stype
1984 physicalDevicesInGroupCount, // physicalDeviceCount
1985 physicalDevicesInGroup // physicalDevices
1987 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
1989 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // type
1991 (VkDeviceQueueCreateFlags)0u, // flags
1992 queueFamilyIndex, // queueFamilyIndex
1994 &queuePriority, // pQueuePriorities
1997 const VkDeviceCreateInfo deviceCreateInfo =
1999 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
2000 &groupDeviceInfo, // pNext
2001 (VkDeviceCreateFlags)0u, // flags
2002 1, // queueRecordCount
2003 &deviceQueueCreateInfo, // pRequestedQueues
2005 DE_NULL, // ppEnabledLayerNames
2006 deUint32(requiredExtensions.size()), // enabledExtensionCount
2007 &requiredExtensions[0], // ppEnabledExtensionNames
2008 DE_NULL, // pEnabledFeatures
2011 Move<VkDevice> groupDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, physicalDevicesInGroup[deviceIdx], &deviceCreateInfo);
2012 const DeviceDriver vkd (context.getPlatformInterface(), instHelper.instance, *groupDevice);
2013 VkQueue queue (getDeviceQueue(vkd, *groupDevice, queueFamilyIndex, 0));
2014 SimpleAllocator allocator (vkd, *groupDevice, getPhysicalDeviceMemoryProperties(instHelper.vki, physicalDevicesInGroup[deviceIdx]));
2016 // create swapchain for device group
2017 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevice, *surface);
2018 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki, physicalDevice, *surface);
2019 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
2020 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
2021 const deUint32 desiredImageCount = 2;
2023 struct VkDeviceGroupSwapchainCreateInfoKHR deviceGroupSwapchainInfo =
2025 VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR,
2027 VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR
2029 const VkSwapchainCreateInfoKHR swapchainInfo =
2031 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
2032 &deviceGroupSwapchainInfo,
2033 VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR,
2035 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
2037 formats[0].colorSpace,
2038 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
2039 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
2041 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
2042 VK_SHARING_MODE_EXCLUSIVE,
2044 (const deUint32*)DE_NULL,
2046 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
2047 VK_PRESENT_MODE_FIFO_KHR,
2052 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, *groupDevice, &swapchainInfo));
2053 deUint32 numImages = 0;
2054 VK_CHECK(vkd.getSwapchainImagesKHR(*groupDevice, *swapchain, &numImages, DE_NULL));
2056 return tcu::TestStatus::pass("Pass");
2058 VkImageSwapchainCreateInfoKHR imageSwapchainCreateInfo =
2060 VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR,
2065 VkImageCreateInfo imageCreateInfo =
2067 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2068 &imageSwapchainCreateInfo,
2069 VK_IMAGE_CREATE_ALIAS_BIT |
2070 VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR, // flags
2071 VK_IMAGE_TYPE_2D, // imageType
2072 formats[0].format, // format
2074 desiredSize.x(), // width
2075 desiredSize.y(), // height
2080 VK_SAMPLE_COUNT_1_BIT, // samples
2081 VK_IMAGE_TILING_OPTIMAL, // tiling
2082 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // usage
2083 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
2084 0u, // queueFamilyIndexCount
2085 DE_NULL, // pQueueFamilyIndices
2086 VK_IMAGE_LAYOUT_UNDEFINED // initialLayout
2089 typedef vk::Unique<VkImage> UniqueImage;
2090 typedef de::SharedPtr<UniqueImage> ImageSp;
2092 vector<ImageSp> images (numImages);
2093 vector<VkImage> rawImages (numImages);
2094 vector<ImageSp> imagesSfr (numImages);
2095 vector<VkImage> rawImagesSfr (numImages);
2096 vector<VkBindImageMemorySwapchainInfoKHR> bindImageMemorySwapchainInfo (numImages);
2098 // Create non-SFR image aliases for image layout transition
2100 vector<VkBindImageMemoryInfo> bindImageMemoryInfos (numImages);
2102 for (deUint32 idx = 0; idx < numImages; ++idx)
2105 images[idx] = ImageSp(new UniqueImage(createImage(vkd, *groupDevice, &imageCreateInfo)));
2107 VkBindImageMemorySwapchainInfoKHR bimsInfo =
2109 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR,
2114 bindImageMemorySwapchainInfo[idx] = bimsInfo;
2116 VkBindImageMemoryInfo bimInfo =
2118 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
2119 &bindImageMemorySwapchainInfo[idx],
2121 DE_NULL, // If the pNext chain includes an instance of VkBindImageMemorySwapchainInfoKHR, memory must be VK_NULL_HANDLE
2122 0u // If swapchain <in VkBindImageMemorySwapchainInfoKHR> is not NULL, the swapchain and imageIndex are used to determine the memory that the image is bound to, instead of memory and memoryOffset.
2124 bindImageMemoryInfos[idx] = bimInfo;
2125 rawImages[idx] = **images[idx];
2128 VK_CHECK(vkd.bindImageMemory2(*groupDevice, numImages, &bindImageMemoryInfos[0]));
2131 // Create the SFR images
2133 vector<VkBindImageMemoryDeviceGroupInfo > bindImageMemoryDeviceGroupInfo (numImages);
2134 vector<VkBindImageMemoryInfo> bindImageMemoryInfos (numImages);
2135 for (deUint32 idx = 0; idx < numImages; ++idx)
2138 imagesSfr[idx] = ImageSp(new UniqueImage(createImage(vkd, *groupDevice, &imageCreateInfo)));
2140 // Split into 2 vertical halves
2141 // NOTE: the same split has to be done also in WsiTriangleRenderer::recordDeviceGroupFrame
2142 const deUint32 halfWidth = desiredSize.x() / 2;
2143 const deUint32 height = desiredSize.y();
2144 const VkRect2D sfrRects[] =
2146 { { 0, 0 }, { halfWidth, height } }, // offset, extent
2147 { { (deInt32)halfWidth, 0 }, { halfWidth, height } }, // offset, extent
2148 { { 0, 0 }, { halfWidth, height } }, // offset, extent
2149 { { (deInt32)halfWidth, 0 }, { halfWidth, height } } // offset, extent
2152 VkBindImageMemoryDeviceGroupInfo bimdgInfo =
2154 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,
2155 &bindImageMemorySwapchainInfo[idx],
2156 DE_LENGTH_OF_ARRAY(deviceIndices),
2158 DE_LENGTH_OF_ARRAY(sfrRects),
2161 bindImageMemoryDeviceGroupInfo[idx] = bimdgInfo;
2163 VkBindImageMemoryInfo bimInfo =
2165 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
2166 &bindImageMemoryDeviceGroupInfo[idx],
2168 DE_NULL, // If the pNext chain includes an instance of VkBindImageMemorySwapchainInfoKHR, memory must be VK_NULL_HANDLE
2169 0u // If swapchain <in VkBindImageMemorySwapchainInfoKHR> is not NULL, the swapchain and imageIndex are used to determine the memory that the image is bound to, instead of memory and memoryOffset.
2171 bindImageMemoryInfos[idx] = bimInfo;
2172 rawImagesSfr[idx] = **imagesSfr[idx];
2175 VK_CHECK(vkd.bindImageMemory2(*groupDevice, numImages, &bindImageMemoryInfos[0]));
2178 VkPeerMemoryFeatureFlags peerMemoryFeatures = 0u;
2179 vkd.getDeviceGroupPeerMemoryFeatures(*groupDevice, 0, firstDeviceID, secondDeviceID, &peerMemoryFeatures);
2180 bool explicitLayoutTransitions = !(peerMemoryFeatures & VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT) ||
2181 !(peerMemoryFeatures & VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT);
2183 const WsiTriangleRenderer renderer (vkd,
2186 context.getBinaryCollection(),
2187 explicitLayoutTransitions,
2190 swapchainInfo.imageFormat,
2191 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
2193 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, *groupDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2195 const size_t maxQueuedFrames = rawImagesSfr.size()*2;
2197 // We need to keep hold of fences from vkAcquireNextImage2KHR
2198 // to actually limit number of frames we allow to be queued.
2199 const vector<FenceSp> imageReadyFences (createFences(vkd, *groupDevice, maxQueuedFrames));
2201 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to
2202 // pass the semaphore in same time as the fence we use to meter rendering.
2203 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, *groupDevice, maxQueuedFrames+1));
2205 // For rest we simply need maxQueuedFrames as we will wait for image from frameNdx-maxQueuedFrames
2206 // to become available to us, guaranteeing that previous uses must have completed.
2207 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, *groupDevice, maxQueuedFrames));
2208 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, *groupDevice, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
2212 const deUint32 numFramesToRender = 60*10;
2214 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
2216 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
2217 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
2218 deUint32 imageNdx = ~0u;
2220 VK_CHECK(vkd.waitForFences(*groupDevice, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
2221 VK_CHECK(vkd.resetFences(*groupDevice, 1, &imageReadyFence));
2224 VkAcquireNextImageInfoKHR acquireNextImageInfo =
2226 VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
2229 std::numeric_limits<deUint64>::max(),
2230 imageReadySemaphore,
2232 (1 << firstDeviceID)
2235 const VkResult acquireResult = vkd.acquireNextImage2KHR(*groupDevice, &acquireNextImageInfo, &imageNdx);
2237 if (acquireResult == VK_SUBOPTIMAL_KHR)
2238 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
2240 VK_CHECK(acquireResult);
2243 TCU_CHECK((size_t)imageNdx < rawImagesSfr.size());
2246 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
2247 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
2248 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2250 // render triangle using one or two subdevices when available
2251 renderer.recordDeviceGroupFrame(commandBuffer, firstDeviceID, secondDeviceID, physicalDevicesInGroupCount, imageNdx, frameNdx);
2254 deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
2255 const VkDeviceGroupSubmitInfo deviceGroupSubmitInfo =
2257 VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR, // sType
2259 DE_LENGTH_OF_ARRAY(deviceIndices), // waitSemaphoreCount
2260 deviceIndices, // pWaitSemaphoreDeviceIndices
2261 1u, // commandBufferCount
2262 &deviceMask, // pCommandBufferDeviceMasks
2263 DE_LENGTH_OF_ARRAY(deviceIndices), // signalSemaphoreCount
2264 deviceIndices, // pSignalSemaphoreDeviceIndices
2266 const VkSubmitInfo submitInfo =
2268 VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
2269 &deviceGroupSubmitInfo, // pNext
2270 1u, // waitSemaphoreCount
2271 &imageReadySemaphore, // pWaitSemaphores
2272 &waitDstStage, // pWaitDstStageMask
2273 1u, // commandBufferCount
2274 &commandBuffer, // pCommandBuffers
2275 1u, // signalSemaphoreCount
2276 &renderingCompleteSemaphore, // pSignalSemaphores
2278 VK_CHECK(vkd.queueSubmit(queue, 1u, &submitInfo, imageReadyFence));
2280 // present swapchain image - asume that first device has a presentation engine
2281 deviceMask = (1 << firstDeviceID);
2282 const VkDeviceGroupPresentInfoKHR deviceGroupPresentInfo =
2284 VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR,
2288 VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR,
2290 const VkPresentInfoKHR presentInfo =
2292 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
2293 &deviceGroupPresentInfo,
2295 &renderingCompleteSemaphore,
2301 VK_CHECK(vkd.queuePresentKHR(queue, &presentInfo));
2305 VK_CHECK(vkd.deviceWaitIdle(*groupDevice));
2309 // Make sure device is idle before destroying resources
2310 vkd.deviceWaitIdle(*groupDevice);
2314 return tcu::TestStatus::pass("Rendering tests succeeded");
2317 vector<tcu::UVec2> getSwapchainSizeSequence (const VkSurfaceCapabilitiesKHR& capabilities, const tcu::UVec2& defaultSize)
2319 vector<tcu::UVec2> sizes(3);
2320 sizes[0] = defaultSize / 2u;
2321 sizes[1] = defaultSize;
2322 sizes[2] = defaultSize * 2u;
2324 for (deUint32 i = 0; i < sizes.size(); ++i)
2326 sizes[i].x() = de::clamp(sizes[i].x(), capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
2327 sizes[i].y() = de::clamp(sizes[i].y(), capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
2333 tcu::TestStatus resizeSwapchainTest (Context& context, Type wsiType)
2335 const tcu::UVec2 desiredSize (256, 256);
2336 const InstanceHelper instHelper (context, wsiType);
2337 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
2338 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2339 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
2340 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
2341 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface);
2342 const DeviceInterface& vkd = devHelper.vkd;
2343 const VkDevice device = *devHelper.device;
2344 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
2345 vector<tcu::UVec2> sizes = getSwapchainSizeSequence(capabilities, desiredSize);
2346 Move<VkSwapchainKHR> prevSwapchain;
2348 DE_ASSERT(platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE);
2349 DE_UNREF(platformProperties);
2351 for (deUint32 sizeNdx = 0; sizeNdx < sizes.size(); ++sizeNdx)
2353 // \todo [2016-05-30 jesse] This test currently waits for idle and
2354 // recreates way more than necessary when recreating the swapchain. Make
2355 // it match expected real app behavior better by smoothly switching from
2356 // old to new swapchain. Once that is done, it will also be possible to
2357 // test creating a new swapchain while images from the previous one are
2360 VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, sizes[sizeNdx], 2);
2361 swapchainInfo.oldSwapchain = *prevSwapchain;
2363 Move<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
2364 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
2365 const WsiTriangleRenderer renderer (vkd,
2368 context.getBinaryCollection(),
2372 swapchainInfo.imageFormat,
2373 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
2374 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
2375 const size_t maxQueuedFrames = swapchainImages.size()*2;
2377 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
2378 // limit number of frames we allow to be queued.
2379 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
2381 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
2382 // the semaphore in same time as the fence we use to meter rendering.
2383 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
2385 // For rest we simply need maxQueuedFrames as we will wait for image
2386 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
2387 // previous uses must have completed.
2388 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
2389 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
2393 const deUint32 numFramesToRender = 60;
2395 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
2397 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
2398 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
2399 deUint32 imageNdx = ~0u;
2401 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
2402 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
2405 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
2407 std::numeric_limits<deUint64>::max(),
2408 imageReadySemaphore,
2412 if (acquireResult == VK_SUBOPTIMAL_KHR)
2413 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
2415 VK_CHECK(acquireResult);
2418 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
2421 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
2422 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
2423 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2424 const VkSubmitInfo submitInfo =
2426 VK_STRUCTURE_TYPE_SUBMIT_INFO,
2429 &imageReadySemaphore,
2434 &renderingCompleteSemaphore
2436 const VkPresentInfoKHR presentInfo =
2438 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
2441 &renderingCompleteSemaphore,
2448 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
2449 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
2450 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
2454 VK_CHECK(vkd.deviceWaitIdle(device));
2456 prevSwapchain = swapchain;
2460 // Make sure device is idle before destroying resources
2461 vkd.deviceWaitIdle(device);
2466 return tcu::TestStatus::pass("Resizing tests succeeded");
2469 tcu::TestStatus getImagesIncompleteResultTest (Context& context, Type wsiType)
2471 const tcu::UVec2 desiredSize (256, 256);
2472 const InstanceHelper instHelper (context, wsiType);
2473 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
2474 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2475 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
2476 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
2477 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
2479 vector<VkImage> swapchainImages = getSwapchainImages(devHelper.vkd, *devHelper.device, *swapchain);
2481 ValidateQueryBits::fillBits(swapchainImages.begin(), swapchainImages.end());
2483 const deUint32 usedCount = static_cast<deUint32>(swapchainImages.size() / 2);
2484 deUint32 count = usedCount;
2485 const VkResult result = devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &count, &swapchainImages[0]);
2487 if (count != usedCount || result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(swapchainImages.begin() + count, swapchainImages.end()))
2488 return tcu::TestStatus::fail("Get swapchain images didn't return VK_INCOMPLETE");
2490 return tcu::TestStatus::pass("Get swapchain images tests succeeded");
2493 tcu::TestStatus getImagesResultsCountTest (Context& context, Type wsiType)
2495 const tcu::UVec2 desiredSize(256, 256);
2496 const InstanceHelper instHelper(context, wsiType);
2497 const NativeObjects native(context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
2498 const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2499 const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface);
2500 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
2501 const Unique<VkSwapchainKHR> swapchain(createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
2503 deUint32 numImages = 0;
2505 VK_CHECK(devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &numImages, DE_NULL));
2509 std::vector<VkImage> images (numImages + 1);
2510 const deUint32 numImagesOrig = numImages;
2512 // check if below call properly overwrites formats count
2515 VK_CHECK(devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &numImages, &images[0]));
2517 if ((size_t)numImages != numImagesOrig)
2518 TCU_FAIL("Image count changed between calls");
2520 return tcu::TestStatus::pass("Get swapchain images tests succeeded");
2523 tcu::TestStatus destroyNullHandleSwapchainTest (Context& context, Type wsiType)
2525 const InstanceHelper instHelper (context, wsiType);
2526 const NativeObjects native (context, instHelper.supportedExtensions, wsiType);
2527 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2528 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
2529 const VkSwapchainKHR nullHandle = DE_NULL;
2531 // Default allocator
2532 devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, DE_NULL);
2536 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u);
2538 devHelper.vkd.destroySwapchainKHR(*devHelper.device, nullHandle, recordingAllocator.getCallbacks());
2540 if (recordingAllocator.getNumRecords() != 0u)
2541 return tcu::TestStatus::fail("Implementation allocated/freed the memory");
2544 return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
2547 tcu::TestStatus acquireTooManyTest (Context& context, Type wsiType)
2549 const tcu::UVec2 desiredSize (256, 256);
2550 const InstanceHelper instHelper (context, wsiType);
2551 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
2552 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2553 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
2554 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
2555 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
2558 VK_CHECK(devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &numImages, DE_NULL));
2559 const deUint32 minImageCount = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface).minImageCount;
2560 if (numImages < minImageCount) return tcu::TestStatus::fail("Get swapchain images returned less than minImageCount images");
2561 const deUint32 numAcquirableImages = numImages - minImageCount + 1;
2563 const auto fences = createFences(devHelper.vkd, *devHelper.device, numAcquirableImages + 1, false);
2565 for (deUint32 i = 0; i < numAcquirableImages; ++i) {
2566 VK_CHECK_WSI(devHelper.vkd.acquireNextImageKHR(*devHelper.device, *swapchain, std::numeric_limits<deUint64>::max(), (VkSemaphore)0, **fences[i], &dummy));
2569 const auto result = devHelper.vkd.acquireNextImageKHR(*devHelper.device, *swapchain, 0, (VkSemaphore)0, **fences[numAcquirableImages], &dummy);
2571 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR && result != VK_NOT_READY ){
2572 return tcu::TestStatus::fail("Implementation failed to respond well acquiring too many images with 0 timeout");
2576 const deUint32 numFences = (result == VK_NOT_READY) ? static_cast<deUint32>(fences.size() - 1) : static_cast<deUint32>(fences.size());
2577 vector<vk::VkFence> fencesRaw(numFences);
2578 std::transform(fences.begin(), fences.begin() + numFences, fencesRaw.begin(), [](const FenceSp& f) -> vk::VkFence{ return **f; });
2579 VK_CHECK(devHelper.vkd.waitForFences(*devHelper.device, numFences, fencesRaw.data(), VK_TRUE, std::numeric_limits<deUint64>::max()));
2581 return tcu::TestStatus::pass("Acquire too many swapchain images test succeeded");
2584 tcu::TestStatus acquireTooManyTimeoutTest (Context& context, Type wsiType)
2586 const tcu::UVec2 desiredSize (256, 256);
2587 const InstanceHelper instHelper (context, wsiType);
2588 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
2589 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
2590 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
2591 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2);
2592 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(devHelper.vkd, *devHelper.device, &swapchainInfo));
2595 VK_CHECK(devHelper.vkd.getSwapchainImagesKHR(*devHelper.device, *swapchain, &numImages, DE_NULL));
2596 const deUint32 minImageCount = getPhysicalDeviceSurfaceCapabilities(instHelper.vki, devHelper.physicalDevice, *surface).minImageCount;
2597 if (numImages < minImageCount) return tcu::TestStatus::fail("Get swapchain images returned less than minImageCount images");
2598 const deUint32 numAcquirableImages = numImages - minImageCount + 1;
2600 const auto fences = createFences(devHelper.vkd, *devHelper.device, numAcquirableImages + 1, false);
2602 for (deUint32 i = 0; i < numAcquirableImages; ++i) {
2603 VK_CHECK_WSI(devHelper.vkd.acquireNextImageKHR(*devHelper.device, *swapchain, std::numeric_limits<deUint64>::max(), (VkSemaphore)0, **fences[i], &dummy));
2606 const deUint64 millisecond = 1000000;
2607 const deUint64 timeout = 50 * millisecond; // arbitrary realistic non-0 non-infinite timeout
2608 const auto result = devHelper.vkd.acquireNextImageKHR(*devHelper.device, *swapchain, timeout, (VkSemaphore)0, **fences[numAcquirableImages], &dummy);
2610 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR && result != VK_TIMEOUT ){
2611 return tcu::TestStatus::fail("Implementation failed to respond well acquiring too many images with timeout");
2615 const deUint32 numFences = (result == VK_TIMEOUT) ? static_cast<deUint32>(fences.size() - 1) : static_cast<deUint32>(fences.size());
2616 vector<vk::VkFence> fencesRaw(numFences);
2617 std::transform(fences.begin(), fences.begin() + numFences, fencesRaw.begin(), [](const FenceSp& f) -> vk::VkFence{ return **f; });
2618 VK_CHECK(devHelper.vkd.waitForFences(*devHelper.device, numFences, fencesRaw.data(), VK_TRUE, std::numeric_limits<deUint64>::max()));
2620 return tcu::TestStatus::pass("Acquire too many swapchain images test succeeded");
2623 void getBasicRenderPrograms (SourceCollections& dst, Type)
2625 WsiTriangleRenderer::getPrograms(dst);
2628 void getBasicRenderPrograms (SourceCollections& dst, MultiSwapchainParams)
2630 WsiTriangleRenderer::getPrograms(dst);
2633 void populateRenderGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
2635 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest<AcquireNextImageWrapper>, wsiType);
2636 addFunctionCaseWithPrograms(testGroup, "basic2", "Basic Rendering Test using AcquireNextImage2", getBasicRenderPrograms, basicRenderTest<AcquireNextImage2Wrapper>, wsiType);
2637 addFunctionCaseWithPrograms(testGroup, "device_group", "Basic Rendering Test using device_group", getBasicRenderPrograms, deviceGroupRenderTest, wsiType);
2638 addFunctionCaseWithPrograms(testGroup, "device_group2", "Rendering Test using device_group and VkImageSwapchainCreateInfo", getBasicRenderPrograms, deviceGroupRenderTest2, wsiType);
2640 const MultiSwapchainParams kTwoSwapchains { wsiType, 2u };
2641 const MultiSwapchainParams kTenSwapchains { wsiType, 10u };
2643 addFunctionCaseWithPrograms(testGroup, "2swapchains", "2 Swapchains Rendering Test", getBasicRenderPrograms, multiSwapchainRenderTest<AcquireNextImageWrapper>, kTwoSwapchains);
2644 addFunctionCaseWithPrograms(testGroup, "2swapchains2", "2 Swapchains Rendering Test using AcquireNextImage2", getBasicRenderPrograms, multiSwapchainRenderTest<AcquireNextImage2Wrapper>, kTwoSwapchains);
2645 addFunctionCaseWithPrograms(testGroup, "10swapchains", "10 Swapchains Rendering Test", getBasicRenderPrograms, multiSwapchainRenderTest<AcquireNextImageWrapper>, kTenSwapchains);
2646 addFunctionCaseWithPrograms(testGroup, "10swapchains2", "10 Swapchains Rendering Test using AcquireNextImage2", getBasicRenderPrograms, multiSwapchainRenderTest<AcquireNextImage2Wrapper>, kTenSwapchains);
2649 void populateGetImagesGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
2651 addFunctionCase(testGroup, "incomplete", "Test VK_INCOMPLETE return code", getImagesIncompleteResultTest, wsiType);
2652 addFunctionCase(testGroup, "count", "Test proper count of images", getImagesResultsCountTest, wsiType);
2655 void populateModifyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
2657 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
2659 if (platformProperties.swapchainExtent != PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE)
2661 addFunctionCaseWithPrograms(testGroup, "resize", "Resize Swapchain Test", getBasicRenderPrograms, resizeSwapchainTest, wsiType);
2664 // \todo [2016-05-30 jesse] Add tests for modifying preTransform, compositeAlpha, presentMode
2667 void populateDestroyGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
2669 addFunctionCase(testGroup, "null_handle", "Destroying a VK_NULL_HANDLE swapchain", destroyNullHandleSwapchainTest, wsiType);
2672 void populateAcquireGroup (tcu::TestCaseGroup* testGroup, Type wsiType)
2674 addFunctionCase(testGroup, "too_many", "Test acquiring too many images with 0 timeout", acquireTooManyTest, wsiType);
2675 addFunctionCase(testGroup, "too_many_timeout", "Test acquiring too many images with timeout", acquireTooManyTimeoutTest, wsiType);
2680 void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
2682 addTestGroup(testGroup, "create", "Create VkSwapchain with various parameters", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainTest));
2683 addTestGroup(testGroup, "simulate_oom", "Simulate OOM using callbacks during swapchain construction", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainSimulateOOMTest));
2684 addTestGroup(testGroup, "render", "Rendering Tests", populateRenderGroup, wsiType);
2685 addTestGroup(testGroup, "modify", "Modify VkSwapchain", populateModifyGroup, wsiType);
2686 addTestGroup(testGroup, "destroy", "Destroy VkSwapchain", populateDestroyGroup, wsiType);
2687 addTestGroup(testGroup, "get_images", "Get swapchain images", populateGetImagesGroup, wsiType);
2688 addTestGroup(testGroup, "acquire", "Ancquire next swapchain image", populateAcquireGroup, wsiType);
2689 addTestGroup(testGroup, "private_data", "Create VkSwapchain and use VK_EXT_private_data", populateSwapchainPrivateDataGroup, GroupParameters(wsiType, createSwapchainPrivateDataTest));