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"
29 #include "vktNativeObjectsUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkStrUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkDeviceUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkWsiPlatform.hpp"
43 #include "vkWsiUtil.hpp"
44 #include "vkAllocationCallbackUtil.hpp"
45 #include "vkCmdUtil.hpp"
46 #include "vkObjUtil.hpp"
47 #include "tcuSurface.hpp"
48 #include "vkImageUtil.hpp"
50 #include "tcuTestLog.hpp"
51 #include "tcuFormatUtil.hpp"
52 #include "tcuPlatform.hpp"
53 #include "tcuResultCollector.hpp"
54 #include "tcuCommandLine.hpp"
56 #include "deUniquePtr.hpp"
57 #include "deStringUtil.hpp"
58 #include "deArrayUtil.hpp"
59 #include "deSharedPtr.hpp"
72 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 VkAllocationCallbacks* pAllocator = DE_NULL)
102 vector<string> extensions;
104 extensions.push_back("VK_KHR_surface");
105 extensions.push_back(getExtensionName(wsiType));
107 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
108 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
109 // but using them without enabling the extension is not allowed. Thus we have
112 // 1) Filter out non-core formats to stay within valid usage.
114 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
116 // We opt for (2) as it provides basic coverage for the extension as a bonus.
117 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
118 extensions.push_back("VK_EXT_swapchain_colorspace");
120 checkAllSupported(supportedExtensions, extensions);
122 return createCustomInstanceWithExtensions(context, extensions, pAllocator);
125 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
127 VkPhysicalDeviceFeatures features;
128 deMemset(&features, 0, sizeof(features));
132 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
133 vk::VkInstance instance,
134 const InstanceInterface& vki,
135 VkPhysicalDevice physicalDevice,
136 const Extensions& supportedExtensions,
137 const deUint32 queueFamilyIndex,
138 const VkAllocationCallbacks* pAllocator,
139 bool validationEnabled)
141 const float queuePriorities[] = { 1.0f };
142 const VkDeviceQueueCreateInfo queueInfos[] =
145 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
147 (VkDeviceQueueCreateFlags)0,
149 DE_LENGTH_OF_ARRAY(queuePriorities),
153 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
154 vector<const char*> extensions;
156 if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
157 TCU_THROW(NotSupportedError, "VK_KHR_swapchain is not supported");
158 extensions.push_back("VK_KHR_swapchain");
160 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
161 extensions.push_back("VK_EXT_hdr_metadata");
163 VkDeviceCreateInfo deviceParams =
165 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
167 (VkDeviceCreateFlags)0,
168 DE_LENGTH_OF_ARRAY(queueInfos),
170 0u, // enabledLayerCount
171 DE_NULL, // ppEnabledLayerNames
172 (deUint32)extensions.size(),
173 extensions.empty() ? DE_NULL : &extensions[0],
177 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
180 struct InstanceHelper
182 const vector<VkExtensionProperties> supportedExtensions;
183 const CustomInstance instance;
184 const InstanceDriver& vki;
186 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
187 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
189 , instance (createInstanceWithWsi(context,
193 , vki (instance.getDriver())
199 const VkPhysicalDevice physicalDevice;
200 const deUint32 queueFamilyIndex;
201 const Unique<VkDevice> device;
202 const DeviceDriver vkd;
205 DeviceHelper (Context& context,
206 const InstanceInterface& vki,
208 VkSurfaceKHR surface,
209 const VkAllocationCallbacks* pAllocator = DE_NULL)
210 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
211 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
212 , device (createDeviceWithWsi(context.getPlatformInterface(),
216 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
219 context.getTestContext().getCommandLine().isValidationEnabled()))
220 , vkd (context.getPlatformInterface(), instance, *device)
221 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
228 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
229 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
230 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
231 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
232 TEST_DIMENSION_IMAGE_USAGE,
233 TEST_DIMENSION_IMAGE_SHARING_MODE,
234 TEST_DIMENSION_PRE_TRANSFORM,
235 TEST_DIMENSION_COMPOSITE_ALPHA,
236 TEST_DIMENSION_PRESENT_MODE,
237 TEST_DIMENSION_CLIPPED,
242 struct TestParameters
245 TestDimension dimension;
247 TestParameters (Type wsiType_, TestDimension dimension_)
249 , dimension (dimension_)
252 TestParameters (void)
253 : wsiType (TYPE_LAST)
254 , dimension (TEST_DIMENSION_LAST)
258 struct GroupParameters
260 typedef FunctionInstance1<TestParameters>::Function Function;
265 GroupParameters (Type wsiType_, Function function_)
267 , function (function_)
270 GroupParameters (void)
271 : wsiType (TYPE_LAST)
272 , function ((Function)DE_NULL)
276 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
277 const InstanceInterface& vki,
278 VkPhysicalDevice physicalDevice,
279 VkSurfaceKHR surface,
280 VkSurfaceFormatKHR surfaceFormat,
281 const tcu::UVec2& desiredSize,
282 deUint32 desiredImageCount,
283 VkColorSpaceKHR desiredColorspace = VK_COLOR_SPACE_MAX_ENUM_KHR)
285 bool setColorspaceManually = desiredColorspace != VK_COLOR_SPACE_MAX_ENUM_KHR;
287 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
290 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
291 const VkSurfaceCapabilitiesKHR surfaceCapabilities = getPhysicalDeviceSurfaceCapabilities(vki,physicalDevice, surface);
293 // Check that the device has at least one supported alpha compositing mode
294 // and pick the first supported mode to be used.
295 vk::VkCompositeAlphaFlagsKHR alpha = 0;
296 for (deUint32 i = 1u; i <= surfaceCapabilities.supportedCompositeAlpha; i <<= 1u)
298 if ((i & surfaceCapabilities.supportedCompositeAlpha) != 0)
305 TCU_THROW(NotSupportedError, "No supported composite alphas available.");
307 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
308 const VkSwapchainCreateInfoKHR parameters =
310 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
312 (VkSwapchainCreateFlagsKHR)0,
314 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
315 surfaceFormat.format,
316 (setColorspaceManually ? desiredColorspace : surfaceFormat.colorSpace),
317 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
318 1u, // imageArrayLayers
319 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
320 VK_SHARING_MODE_EXCLUSIVE,
322 (const deUint32*)DE_NULL,
324 static_cast<VkCompositeAlphaFlagBitsKHR>(alpha),
325 VK_PRESENT_MODE_FIFO_KHR,
327 (VkSwapchainKHR)0 // oldSwapchain
333 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
334 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
335 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
337 vector<FenceSp> createFences (const DeviceInterface& vkd,
338 const VkDevice device,
341 vector<FenceSp> fences(numFences);
343 for (size_t ndx = 0; ndx < numFences; ++ndx)
344 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
349 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
350 const VkDevice device,
351 size_t numSemaphores)
353 vector<SemaphoreSp> semaphores(numSemaphores);
355 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
356 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
361 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
362 const VkDevice device,
363 const VkCommandPool commandPool,
364 const VkCommandBufferLevel level,
365 const size_t numCommandBuffers)
367 vector<CommandBufferSp> buffers (numCommandBuffers);
369 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
370 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
375 tcu::Vec4 getPixel (const DeviceInterface& vkd,
376 const VkDevice device,
378 const VkCommandPool& commandPool,
379 Allocator& allocator,
380 const tcu::UVec2 size,
381 const tcu::TextureFormat textureFormat,
382 const VkImage* image)
384 Move<VkCommandBuffer> commandBuffer;
385 Move<VkBuffer> resultBuffer;
386 de::MovePtr<Allocation> resultBufferMemory;
388 commandBuffer = allocateCommandBuffer(vkd, device, commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
392 const VkDeviceSize bufferSize = textureFormat.getPixelSize() * size.x() * size.y();
393 const VkBufferCreateInfo createInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
395 resultBuffer = createBuffer(vkd, device, &createInfo);
396 resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vkd, device, *resultBuffer), MemoryRequirement::HostVisible);
398 VK_CHECK(vkd.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
401 beginCommandBuffer(vkd, *commandBuffer, 0u);
403 copyImageToBuffer(vkd, *commandBuffer, *image, *resultBuffer, tcu::IVec2(size.x(), size.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
405 endCommandBuffer(vkd, *commandBuffer);
406 submitCommandsAndWait(vkd, device, queue, commandBuffer.get());
408 tcu::ConstPixelBufferAccess resultAccess(textureFormat,
409 tcu::IVec3(size.x(), size.y(), 1),
410 resultBufferMemory->getHostPtr());
412 return (resultAccess.getPixel(128, 128));
415 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
417 const tcu::UVec2 desiredSize (256, 256);
418 const InstanceHelper instHelper (context, wsiType);
419 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
420 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
421 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
423 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
424 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
426 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
427 devHelper.physicalDevice,
431 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
433 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
441 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
443 return tcu::TestStatus::pass("Extension tests succeeded");
452 // Create swapchain with multiple images on different colorspaces and compare pixels on those images.
453 tcu::TestStatus colorspaceCompareTest (Context& context, TestParams params)
455 if (!context.isInstanceFunctionalitySupported("VK_EXT_swapchain_colorspace"))
456 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
458 const tcu::UVec2 desiredSize (256, 256);
459 const InstanceHelper instHelper (context, params.wsiType);
460 const NativeObjects native (context, instHelper.supportedExtensions, params.wsiType, tcu::just(desiredSize));
461 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, params.wsiType, native.getDisplay(), native.getWindow()));
462 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
464 const vector<VkSurfaceFormatKHR> queriedFormats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
465 devHelper.physicalDevice,
468 vector<vk::VkColorSpaceKHR> supportedColorSpaces;
469 for (const auto& queriedFormat : queriedFormats)
471 if (queriedFormat.format == params.format)
473 supportedColorSpaces.push_back(queriedFormat.colorSpace);
477 // Not supported if there's no color spaces for the format.
478 if(supportedColorSpaces.size() < 2)
479 TCU_THROW(NotSupportedError, "Format not supported");
481 // Surface format is used to create the swapchain.
482 VkSurfaceFormatKHR surfaceFormat =
484 params.format, // format
485 supportedColorSpaces.at(0) // colorSpace
488 tcu::Vec4 referenceColorspacePixel;
489 const tcu::TextureFormat textureFormat = vk::mapVkFormat(surfaceFormat.format);
490 const DeviceInterface& vkd = devHelper.vkd;
491 const VkDevice device = *devHelper.device;
492 SimpleAllocator allocator (vkd,
494 getPhysicalDeviceMemoryProperties(instHelper.vki,
495 context.getPhysicalDevice()));
497 for (size_t colorspaceNdx = 0; colorspaceNdx < supportedColorSpaces.size(); ++colorspaceNdx)
499 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(params.wsiType,
501 devHelper.physicalDevice,
506 supportedColorSpaces[colorspaceNdx]);
507 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
508 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
509 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
511 const WsiTriangleRenderer renderer(vkd,
514 context.getBinaryCollection(),
518 swapchainInfo.imageFormat,
519 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
521 const Move<VkCommandPool> commandPool (createCommandPool(vkd,
523 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
524 devHelper.queueFamilyIndex));
525 const Move<VkSemaphore> imageReadySemaphore = createSemaphore(vkd, device);
526 const Move<VkSemaphore> renderingCompleteSemaphore = createSemaphore(vkd, device);
527 const Move<VkCommandBuffer> commandBuffer = allocateCommandBuffer(vkd,
530 VK_COMMAND_BUFFER_LEVEL_PRIMARY);
534 deUint32 imageNdx = ~0u;
537 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
539 std::numeric_limits<deUint64>::max(),
540 imageReadySemaphore.get(),
544 if (acquireResult == VK_SUBOPTIMAL_KHR)
546 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult
547 << TestLog::EndMessage;
551 VK_CHECK(acquireResult);
555 TCU_CHECK((size_t) imageNdx < swapchainImages.size());
558 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
559 const VkSubmitInfo submitInfo =
561 VK_STRUCTURE_TYPE_SUBMIT_INFO,
564 &imageReadySemaphore.get(),
567 &commandBuffer.get(),
569 &renderingCompleteSemaphore.get()
571 const VkPresentInfoKHR presentInfo =
573 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
576 &renderingCompleteSemaphore.get(),
583 renderer.recordFrame(commandBuffer.get(), imageNdx, 0);
584 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, DE_NULL));
585 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
588 // Set reference pixelBufferAccess for comparison.
589 if (colorspaceNdx == 0)
591 referenceColorspacePixel = getPixel(vkd, device, devHelper.queue, commandPool.get(),
592 allocator, desiredSize, textureFormat,
593 &swapchainImages[imageNdx]);
597 // Compare pixels from images to make sure the colorspace makes no difference.
598 if (referenceColorspacePixel == getPixel(vkd, device, devHelper.queue, commandPool.get(),
599 allocator, desiredSize, textureFormat,
600 &swapchainImages[imageNdx]))
604 VK_CHECK(vkd.deviceWaitIdle(device));
605 return tcu::TestStatus::fail("Colorspace comparison test failed");
610 // Make sure device is idle before destroying resources
611 vkd.deviceWaitIdle(device);
616 VK_CHECK(vkd.deviceWaitIdle(device));
617 return tcu::TestStatus::pass("Colorspace comparison test succeeded");
620 tcu::TestStatus surfaceFormatRenderTest (Context& context,
622 const InstanceHelper& instHelper,
623 const DeviceHelper& devHelper,
624 VkSurfaceKHR surface,
625 VkSurfaceFormatKHR curFmt,
626 deBool checkHdr = false)
628 const tcu::UVec2 desiredSize (256, 256);
629 const DeviceInterface& vkd = devHelper.vkd;
630 const VkDevice device = *devHelper.device;
631 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
633 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
634 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
635 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
636 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
638 if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
639 TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
641 const WsiTriangleRenderer renderer (vkd,
644 context.getBinaryCollection(),
648 swapchainInfo.imageFormat,
649 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
651 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
653 const size_t maxQueuedFrames = swapchainImages.size()*2;
655 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
656 // limit number of frames we allow to be queued.
657 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
659 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
660 // the semaphore in same time as the fence we use to meter rendering.
661 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
663 // For rest we simply need maxQueuedFrames as we will wait for image
664 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
665 // previous uses must have completed.
666 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
667 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
671 const deUint32 numFramesToRender = 60;
673 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
675 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
676 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
677 deUint32 imageNdx = ~0u;
679 if (frameNdx >= maxQueuedFrames)
680 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
682 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
685 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
687 std::numeric_limits<deUint64>::max(),
692 if (acquireResult == VK_SUBOPTIMAL_KHR)
693 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
695 VK_CHECK(acquireResult);
698 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
701 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
702 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
703 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
704 const VkSubmitInfo submitInfo =
706 VK_STRUCTURE_TYPE_SUBMIT_INFO,
709 &imageReadySemaphore,
714 &renderingCompleteSemaphore
716 const VkPresentInfoKHR presentInfo =
718 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
721 &renderingCompleteSemaphore,
729 const VkHdrMetadataEXT hdrData = {
730 VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
732 makeXYColorEXT(0.680f, 0.320f),
733 makeXYColorEXT(0.265f, 0.690f),
734 makeXYColorEXT(0.150f, 0.060f),
735 makeXYColorEXT(0.3127f, 0.3290f),
741 vector<VkSwapchainKHR> swapchainArray;
743 swapchainArray.push_back(*swapchain);
744 vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
747 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
748 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
749 VK_CHECK_WSI(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
753 VK_CHECK(vkd.deviceWaitIdle(device));
757 // Make sure device is idle before destroying resources
758 vkd.deviceWaitIdle(device);
762 return tcu::TestStatus::pass("Rendering test succeeded");
765 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
767 const tcu::UVec2 desiredSize (256, 256);
768 const InstanceHelper instHelper (context, wsiType);
769 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
770 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
771 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
773 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
774 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
776 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
777 devHelper.physicalDevice,
779 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
781 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt);
783 return tcu::TestStatus::pass("Rendering tests succeeded");
786 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
788 const tcu::UVec2 desiredSize (256, 256);
789 const InstanceHelper instHelper (context, wsiType);
790 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, 1u, tcu::just(desiredSize));
791 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow()));
792 const DeviceHelper devHelper (context, instHelper.vki, instHelper.instance, *surface);
794 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
795 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
797 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
798 devHelper.physicalDevice,
800 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
802 surfaceFormatRenderTest(context, wsiType, instHelper, devHelper, *surface, *curFmt, true);
804 return tcu::TestStatus::pass("Rendering tests succeeded");
807 // We need different versions of this function in order to invoke
808 // different overloaded versions of addFunctionCaseWithPrograms.
809 void getBasicRenderPrograms2 (SourceCollections& dst, TestParams)
811 WsiTriangleRenderer::getPrograms(dst);
814 void getBasicRenderPrograms (SourceCollections& dst, Type)
816 WsiTriangleRenderer::getPrograms(dst);
820 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
822 addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
823 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
824 addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);
827 void createColorspaceCompareTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
829 const VkFormat formatList[] = {
830 VK_FORMAT_B8G8R8A8_UNORM,
831 VK_FORMAT_R8G8B8A8_UNORM,
832 VK_FORMAT_R8G8B8A8_SRGB,
833 VK_FORMAT_R5G6B5_UNORM_PACK16,
834 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
835 VK_FORMAT_R16G16B16A16_SFLOAT
838 // Create test for every format.
839 for (const VkFormat& format : formatList)
841 const char* const enumName = getFormatName(format);
842 const string caseName = de::toLower(string(enumName).substr(10));
843 const TestParams params =
848 addFunctionCaseWithPrograms(testGroup, caseName, "", getBasicRenderPrograms2, colorspaceCompareTest, params);