1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 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 "vkCmdUtil.hpp"
41 #include "vkWsiPlatform.hpp"
42 #include "vkWsiUtil.hpp"
43 #include "vkAllocationCallbackUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkObjUtil.hpp"
46 #include "tcuSurface.hpp"
47 #include "vkImageUtil.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuFormatUtil.hpp"
51 #include "tcuPlatform.hpp"
52 #include "tcuResultCollector.hpp"
53 #include "tcuCommandLine.hpp"
55 #include "deUniquePtr.hpp"
56 #include "deStringUtil.hpp"
57 #include "deArrayUtil.hpp"
58 #include "deSharedPtr.hpp"
71 using namespace vk::wsi;
83 typedef vector<VkExtensionProperties> Extensions;
85 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
87 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
88 requiredExtName != requiredExtensions.end();
91 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
92 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
96 CustomInstance createInstanceWithWsi (Context& context,
97 const Extensions& supportedExtensions,
99 const VkAllocationCallbacks* pAllocator = DE_NULL)
101 vector<string> extensions;
103 extensions.push_back("VK_KHR_surface");
104 extensions.push_back(getExtensionName(wsiType));
106 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
107 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
108 // but using them without enabling the extension is not allowed. Thus we have
111 // 1) Filter out non-core formats to stay within valid usage.
113 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
115 // We opt for (2) as it provides basic coverage for the extension as a bonus.
116 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
117 extensions.push_back("VK_EXT_swapchain_colorspace");
119 checkAllSupported(supportedExtensions, extensions);
121 return createCustomInstanceWithExtensions(context, extensions, pAllocator);
124 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
126 VkPhysicalDeviceFeatures features;
127 deMemset(&features, 0, sizeof(features));
131 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
132 vk::VkInstance instance,
133 const InstanceInterface& vki,
134 VkPhysicalDevice physicalDevice,
135 const Extensions& supportedExtensions,
136 const deUint32 queueFamilyIndex,
137 const VkAllocationCallbacks* pAllocator,
138 bool validationEnabled)
140 const float queuePriorities[] = { 1.0f };
141 const VkDeviceQueueCreateInfo queueInfos[] =
144 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
146 (VkDeviceQueueCreateFlags)0,
148 DE_LENGTH_OF_ARRAY(queuePriorities),
152 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
153 vector<const char*> extensions;
155 if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
156 TCU_THROW(NotSupportedError, "VK_KHR_swapchain is not supported");
157 extensions.push_back("VK_KHR_swapchain");
159 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
160 extensions.push_back("VK_EXT_hdr_metadata");
162 VkDeviceCreateInfo deviceParams =
164 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
166 (VkDeviceCreateFlags)0,
167 DE_LENGTH_OF_ARRAY(queueInfos),
169 0u, // enabledLayerCount
170 DE_NULL, // ppEnabledLayerNames
171 (deUint32)extensions.size(),
172 extensions.empty() ? DE_NULL : &extensions[0],
176 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
179 struct InstanceHelper
181 const vector<VkExtensionProperties> supportedExtensions;
182 const CustomInstance instance;
183 const InstanceDriver& vki;
185 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
186 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
188 , instance (createInstanceWithWsi(context,
192 , vki (instance.getDriver())
198 const VkPhysicalDevice physicalDevice;
199 const deUint32 queueFamilyIndex;
200 const Unique<VkDevice> device;
201 const DeviceDriver vkd;
204 DeviceHelper (Context& context,
205 const InstanceInterface& vki,
207 VkSurfaceKHR surface,
208 const VkAllocationCallbacks* pAllocator = DE_NULL)
209 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
210 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
211 , device (createDeviceWithWsi(context.getPlatformInterface(),
215 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
218 context.getTestContext().getCommandLine().isValidationEnabled()))
219 , vkd (context.getPlatformInterface(), instance, *device)
220 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
225 MovePtr<Display> createDisplay (const vk::Platform& platform,
226 const Extensions& supportedExtensions,
231 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
233 catch (const tcu::NotSupportedError& e)
235 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
236 platform.hasDisplay(wsiType))
238 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
239 // must support creating native display & window for that WSI type.
240 throw tcu::TestError(e.getMessage());
247 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
251 return MovePtr<Window>(display.createWindow(initialSize));
253 catch (const tcu::NotSupportedError& e)
255 // See createDisplay - assuming that wsi::Display was supported platform port
256 // should also support creating a window.
257 throw tcu::TestError(e.getMessage());
263 const UniquePtr<Display> display;
264 const UniquePtr<Window> window;
266 NativeObjects (Context& context,
267 const Extensions& supportedExtensions,
269 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
270 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
271 , window (createWindow(*display, initialWindowSize))
277 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
278 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
279 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
280 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
281 TEST_DIMENSION_IMAGE_USAGE,
282 TEST_DIMENSION_IMAGE_SHARING_MODE,
283 TEST_DIMENSION_PRE_TRANSFORM,
284 TEST_DIMENSION_COMPOSITE_ALPHA,
285 TEST_DIMENSION_PRESENT_MODE,
286 TEST_DIMENSION_CLIPPED,
291 struct TestParameters
294 TestDimension dimension;
296 TestParameters (Type wsiType_, TestDimension dimension_)
298 , dimension (dimension_)
301 TestParameters (void)
302 : wsiType (TYPE_LAST)
303 , dimension (TEST_DIMENSION_LAST)
307 struct GroupParameters
309 typedef FunctionInstance1<TestParameters>::Function Function;
314 GroupParameters (Type wsiType_, Function function_)
316 , function (function_)
319 GroupParameters (void)
320 : wsiType (TYPE_LAST)
321 , function ((Function)DE_NULL)
325 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
326 const InstanceInterface& vki,
327 VkPhysicalDevice physicalDevice,
328 VkSurfaceKHR surface,
329 VkSurfaceFormatKHR surfaceFormat,
330 const tcu::UVec2& desiredSize,
331 deUint32 desiredImageCount,
332 VkColorSpaceKHR desiredColorspace = VK_COLOR_SPACE_MAX_ENUM_KHR)
334 bool setColorspaceManually = desiredColorspace != VK_COLOR_SPACE_MAX_ENUM_KHR;
336 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
339 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
340 const VkSurfaceCapabilitiesKHR surfaceCapabilities = getPhysicalDeviceSurfaceCapabilities(vki,physicalDevice, surface);
342 // Check that the device has at least one supported alpha compositing mode
343 // and pick the first supported mode to be used.
344 vk::VkCompositeAlphaFlagsKHR alpha = 0;
345 for (deUint32 i = 1u; i <= surfaceCapabilities.supportedCompositeAlpha; i <<= 1u)
347 if ((i & surfaceCapabilities.supportedCompositeAlpha) != 0)
354 TCU_THROW(NotSupportedError, "No supported composite alphas available.");
356 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
357 const VkSwapchainCreateInfoKHR parameters =
359 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
361 (VkSwapchainCreateFlagsKHR)0,
363 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
364 surfaceFormat.format,
365 (setColorspaceManually ? desiredColorspace : surfaceFormat.colorSpace),
366 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
367 1u, // imageArrayLayers
368 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
369 VK_SHARING_MODE_EXCLUSIVE,
371 (const deUint32*)DE_NULL,
373 static_cast<VkCompositeAlphaFlagBitsKHR>(alpha),
374 VK_PRESENT_MODE_FIFO_KHR,
376 (VkSwapchainKHR)0 // oldSwapchain
382 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
383 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
384 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
386 vector<FenceSp> createFences (const DeviceInterface& vkd,
387 const VkDevice device,
390 vector<FenceSp> fences(numFences);
392 for (size_t ndx = 0; ndx < numFences; ++ndx)
393 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
398 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
399 const VkDevice device,
400 size_t numSemaphores)
402 vector<SemaphoreSp> semaphores(numSemaphores);
404 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
405 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
410 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
411 const VkDevice device,
412 const VkCommandPool commandPool,
413 const VkCommandBufferLevel level,
414 const size_t numCommandBuffers)
416 vector<CommandBufferSp> buffers (numCommandBuffers);
418 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
419 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
424 tcu::Vec4 getPixel (const DeviceInterface& vkd,
425 const VkDevice device,
427 const VkCommandPool& commandPool,
428 Allocator& allocator,
429 const tcu::UVec2 size,
430 const tcu::TextureFormat textureFormat,
431 const VkImage* image)
433 Move<VkCommandBuffer> commandBuffer;
434 Move<VkBuffer> resultBuffer;
435 de::MovePtr<Allocation> resultBufferMemory;
437 commandBuffer = allocateCommandBuffer(vkd, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
441 const VkDeviceSize bufferSize = textureFormat.getPixelSize() * size.x() * size.y();
442 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
444 resultBuffer = createBuffer(vkd, device, &createInfo);
445 resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, device, *resultBuffer), MemoryRequirement::HostVisible);
447 VK_CHECK(vkd.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
450 beginCommandBuffer(vkd, *commandBuffer, 0u);
452 copyImageToBuffer(vkd, *commandBuffer, *image, *resultBuffer, tcu::IVec2(size.x(), size.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
454 endCommandBuffer(vkd, *commandBuffer);
455 submitCommandsAndWait(vkd, device, queue, commandBuffer.get());
457 tcu::ConstPixelBufferAccess resultAccess(textureFormat,
458 tcu::IVec3(size.x(), size.y(), 1),
459 resultBufferMemory->getHostPtr());
461 return (resultAccess.getPixel(128, 128));
464 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
466 const tcu::UVec2 desiredSize (256, 256);
467 const InstanceHelper instHelper (context, wsiType);
468 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
469 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
470 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
472 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
473 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
475 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
476 devHelper.physicalDevice,
480 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
482 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
490 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
492 return tcu::TestStatus::pass("Extension tests succeeded");
501 // Create swapchain with multiple images on different colorspaces and compare pixels on those images.
502 tcu::TestStatus colorspaceCompareTest (Context& context, TestParams params)
504 if (!context.isInstanceFunctionalitySupported("VK_EXT_swapchain_colorspace"))
505 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
507 const tcu::UVec2 desiredSize (256, 256);
508 const InstanceHelper instHelper (context, params.wsiType);
509 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType, tcu::just(desiredSize));
510 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, params.wsiType, *native.display, *native.window));
511 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
513 const vector<VkSurfaceFormatKHR> queriedFormats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
514 devHelper.physicalDevice,
517 vector<vk::VkColorSpaceKHR> supportedColorSpaces;
518 for (const auto& queriedFormat : queriedFormats)
520 if (queriedFormat.format == params.format)
522 supportedColorSpaces.push_back(queriedFormat.colorSpace);
526 // Not supported if there's no color spaces for the format.
527 if(supportedColorSpaces.size() < 2)
528 TCU_THROW(NotSupportedError, "Format not supported");
530 // Surface format is used to create the swapchain.
531 VkSurfaceFormatKHR surfaceFormat =
533 params.format, // format
534 supportedColorSpaces.at(0) // colorSpace
537 tcu::Vec4 referenceColorspacePixel;
538 const tcu::TextureFormat textureFormat = vk::mapVkFormat(surfaceFormat.format);
539 const DeviceInterface& vkd = devHelper.vkd;
540 const VkDevice device = *devHelper.device;
541 SimpleAllocator allocator (vkd,
543 getPhysicalDeviceMemoryProperties(instHelper.vki,
544 context.getPhysicalDevice()));
546 for (size_t colorspaceNdx = 0; colorspaceNdx < supportedColorSpaces.size(); ++colorspaceNdx)
548 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(params.wsiType,
550 devHelper.physicalDevice,
555 supportedColorSpaces[colorspaceNdx]);
556 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
557 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
558 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
560 const WsiTriangleRenderer renderer(vkd,
563 context.getBinaryCollection(),
567 swapchainInfo.imageFormat,
568 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
570 const Move<VkCommandPool> commandPool (createCommandPool(vkd,
572 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
573 devHelper.queueFamilyIndex));
574 const Move<VkSemaphore> imageReadySemaphore = createSemaphore(vkd, device);
575 const Move<VkSemaphore> renderingCompleteSemaphore = createSemaphore(vkd, device);
576 const Move<VkCommandBuffer> commandBuffer = allocateCommandBuffer(vkd,
579 VK_COMMAND_BUFFER_LEVEL_PRIMARY);
583 deUint32 imageNdx = ~0u;
586 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
588 std::numeric_limits<deUint64>::max(),
589 imageReadySemaphore.get(),
593 if (acquireResult == VK_SUBOPTIMAL_KHR)
595 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult
596 << TestLog::EndMessage;
600 VK_CHECK(acquireResult);
604 TCU_CHECK((size_t) imageNdx < swapchainImages.size());
607 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
608 const VkSubmitInfo submitInfo =
610 VK_STRUCTURE_TYPE_SUBMIT_INFO,
613 &imageReadySemaphore.get(),
616 &commandBuffer.get(),
618 &renderingCompleteSemaphore.get()
620 const VkPresentInfoKHR presentInfo =
622 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
625 &renderingCompleteSemaphore.get(),
632 renderer.recordFrame(commandBuffer.get(), imageNdx, 0);
633 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, DE_NULL));
634 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
637 // Set reference pixelBufferAccess for comparison.
638 if (colorspaceNdx == 0)
640 referenceColorspacePixel = getPixel(vkd, device, devHelper.queue, commandPool.get(),
641 allocator, desiredSize, textureFormat,
642 &swapchainImages[imageNdx]);
646 // Compare pixels from images to make sure the colorspace makes no difference.
647 if (referenceColorspacePixel == getPixel(vkd, device, devHelper.queue, commandPool.get(),
648 allocator, desiredSize, textureFormat,
649 &swapchainImages[imageNdx]))
653 VK_CHECK(vkd.deviceWaitIdle(device));
654 return tcu::TestStatus::fail("Colorspace comparison test failed");
659 // Make sure device is idle before destroying resources
660 vkd.deviceWaitIdle(device);
665 VK_CHECK(vkd.deviceWaitIdle(device));
666 return tcu::TestStatus::pass("Colorspace comparison test succeeded");
669 tcu::TestStatus surfaceFormatRenderTest (Context& context,
671 const InstanceHelper& instHelper,
672 const DeviceHelper& devHelper,
673 VkSurfaceKHR surface,
674 VkSurfaceFormatKHR curFmt,
675 deBool checkHdr = false)
677 const tcu::UVec2 desiredSize (256, 256);
678 const DeviceInterface& vkd = devHelper.vkd;
679 const VkDevice device = *devHelper.device;
680 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
682 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
683 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
684 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
685 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
687 if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
688 TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
690 const WsiTriangleRenderer renderer (vkd,
693 context.getBinaryCollection(),
697 swapchainInfo.imageFormat,
698 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
700 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
702 const size_t maxQueuedFrames = swapchainImages.size()*2;
704 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
705 // limit number of frames we allow to be queued.
706 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
708 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
709 // the semaphore in same time as the fence we use to meter rendering.
710 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
712 // For rest we simply need maxQueuedFrames as we will wait for image
713 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
714 // previous uses must have completed.
715 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
716 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
720 const deUint32 numFramesToRender = 60;
722 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
724 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
725 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
726 deUint32 imageNdx = ~0u;
728 if (frameNdx >= maxQueuedFrames)
729 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
731 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
734 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
736 std::numeric_limits<deUint64>::max(),
741 if (acquireResult == VK_SUBOPTIMAL_KHR)
742 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
744 VK_CHECK(acquireResult);
747 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
750 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
751 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
752 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
753 const VkSubmitInfo submitInfo =
755 VK_STRUCTURE_TYPE_SUBMIT_INFO,
758 &imageReadySemaphore,
763 &renderingCompleteSemaphore
765 const VkPresentInfoKHR presentInfo =
767 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
770 &renderingCompleteSemaphore,
778 const VkHdrMetadataEXT hdrData = {
779 VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
781 makeXYColorEXT(0.680f, 0.320f),
782 makeXYColorEXT(0.265f, 0.690f),
783 makeXYColorEXT(0.150f, 0.060f),
784 makeXYColorEXT(0.3127f, 0.3290f),
790 vector<VkSwapchainKHR> swapchainArray;
792 swapchainArray.push_back(*swapchain);
793 vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
796 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
797 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
798 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
802 VK_CHECK(vkd.deviceWaitIdle(device));
806 // Make sure device is idle before destroying resources
807 vkd.deviceWaitIdle(device);
811 return tcu::TestStatus::pass("Rendering test succeeded");
814 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
816 const tcu::UVec2 desiredSize (256, 256);
817 const InstanceHelper instHelper (context, wsiType);
818 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
819 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
820 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
822 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
823 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
825 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
826 devHelper.physicalDevice,
828 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
830 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt);
832 return tcu::TestStatus::pass("Rendering tests succeeded");
835 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
837 const tcu::UVec2 desiredSize (256, 256);
838 const InstanceHelper instHelper (context, wsiType);
839 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
840 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, *native.display, *native.window));
841 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
843 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
844 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
846 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
847 devHelper.physicalDevice,
849 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
851 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt, true);
853 return tcu::TestStatus::pass("Rendering tests succeeded");
856 // We need different versions of this function in order to invoke
857 // different overloaded versions of addFunctionCaseWithPrograms.
858 void getBasicRenderPrograms2 (SourceCollections& dst, TestParams)
860 WsiTriangleRenderer::getPrograms(dst);
863 void getBasicRenderPrograms (SourceCollections& dst, Type)
865 WsiTriangleRenderer::getPrograms(dst);
869 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
871 addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
872 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
873 addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);
876 void createColorspaceCompareTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
878 const VkFormat formatList[] = {
879 VK_FORMAT_B8G8R8A8_UNORM,
880 VK_FORMAT_R8G8B8A8_UNORM,
881 VK_FORMAT_R8G8B8A8_SRGB,
882 VK_FORMAT_R5G6B5_UNORM_PACK16,
883 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
884 VK_FORMAT_R16G16B16A16_SFLOAT
887 // Create test for every format.
888 for (const VkFormat& format : formatList)
890 const char* const enumName = getFormatName(format);
891 const string caseName = de::toLower(string(enumName).substr(10));
892 const TestParams params =
897 addFunctionCaseWithPrograms(testGroup, caseName, "", getBasicRenderPrograms2, colorspaceCompareTest, params);