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"
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkWsiPlatform.hpp"
41 #include "vkWsiUtil.hpp"
42 #include "vkAllocationCallbackUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuFormatUtil.hpp"
48 #include "tcuPlatform.hpp"
49 #include "tcuResultCollector.hpp"
51 #include "deUniquePtr.hpp"
52 #include "deStringUtil.hpp"
53 #include "deArrayUtil.hpp"
54 #include "deSharedPtr.hpp"
67 using namespace vk::wsi;
79 typedef vector<VkExtensionProperties> Extensions;
81 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
83 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
84 requiredExtName != requiredExtensions.end();
87 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
88 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
92 Move<VkInstance> createInstanceWithWsi (const PlatformInterface& vkp,
94 const Extensions& supportedExtensions,
96 const VkAllocationCallbacks* pAllocator = DE_NULL)
98 vector<string> extensions;
100 extensions.push_back("VK_KHR_surface");
101 extensions.push_back(getExtensionName(wsiType));
103 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
104 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
105 // but using them without enabling the extension is not allowed. Thus we have
108 // 1) Filter out non-core formats to stay within valid usage.
110 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
112 // We opt for (2) as it provides basic coverage for the extension as a bonus.
113 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
114 extensions.push_back("VK_EXT_swapchain_colorspace");
116 checkAllSupported(supportedExtensions, extensions);
118 return createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
121 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
123 VkPhysicalDeviceFeatures features;
124 deMemset(&features, 0, sizeof(features));
128 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp,
129 vk::VkInstance instance,
130 const InstanceInterface& vki,
131 VkPhysicalDevice physicalDevice,
132 const Extensions& supportedExtensions,
133 const deUint32 queueFamilyIndex,
134 const VkAllocationCallbacks* pAllocator = DE_NULL)
136 const float queuePriorities[] = { 1.0f };
137 const VkDeviceQueueCreateInfo queueInfos[] =
140 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
142 (VkDeviceQueueCreateFlags)0,
144 DE_LENGTH_OF_ARRAY(queuePriorities),
148 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
149 vector<const char*> extensions;
151 if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
152 TCU_THROW(NotSupportedError, (string(extensions[0]) + " is not supported").c_str());
153 extensions.push_back("VK_KHR_swapchain");
155 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
156 extensions.push_back("VK_EXT_hdr_metadata");
158 const VkDeviceCreateInfo deviceParams =
160 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
162 (VkDeviceCreateFlags)0,
163 DE_LENGTH_OF_ARRAY(queueInfos),
165 0u, // enabledLayerCount
166 DE_NULL, // ppEnabledLayerNames
167 (deUint32)extensions.size(),
168 extensions.empty() ? DE_NULL : &extensions[0],
172 return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
175 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
177 deUint32 numFamilies = 0;
179 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
184 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
186 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
187 vector<deUint32> supportedFamilyIndices;
189 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
191 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
192 supportedFamilyIndices.push_back(queueFamilyNdx);
195 return supportedFamilyIndices;
198 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
200 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
202 if (supportedFamilyIndices.empty())
203 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
205 return supportedFamilyIndices[0];
208 struct InstanceHelper
210 const vector<VkExtensionProperties> supportedExtensions;
211 const Unique<VkInstance> instance;
212 const InstanceDriver vki;
214 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
215 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
217 , instance (createInstanceWithWsi(context.getPlatformInterface(),
218 context.getUsedApiVersion(),
222 , vki (context.getPlatformInterface(), *instance)
228 const VkPhysicalDevice physicalDevice;
229 const deUint32 queueFamilyIndex;
230 const Unique<VkDevice> device;
231 const DeviceDriver vkd;
234 DeviceHelper (Context& context,
235 const InstanceInterface& vki,
237 VkSurfaceKHR surface,
238 const VkAllocationCallbacks* pAllocator = DE_NULL)
239 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
240 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
241 , device (createDeviceWithWsi(context.getPlatformInterface(),
245 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
248 , vkd (context.getPlatformInterface(), instance, *device)
249 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
254 MovePtr<Display> createDisplay (const vk::Platform& platform,
255 const Extensions& supportedExtensions,
260 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
262 catch (const tcu::NotSupportedError& e)
264 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
266 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
267 // must support creating native display & window for that WSI type.
268 throw tcu::TestError(e.getMessage());
275 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
279 return MovePtr<Window>(display.createWindow(initialSize));
281 catch (const tcu::NotSupportedError& e)
283 // See createDisplay - assuming that wsi::Display was supported platform port
284 // should also support creating a window.
285 throw tcu::TestError(e.getMessage());
291 const UniquePtr<Display> display;
292 const UniquePtr<Window> window;
294 NativeObjects (Context& context,
295 const Extensions& supportedExtensions,
297 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
298 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
299 , window (createWindow(*display, initialWindowSize))
305 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
306 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
307 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
308 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
309 TEST_DIMENSION_IMAGE_USAGE,
310 TEST_DIMENSION_IMAGE_SHARING_MODE,
311 TEST_DIMENSION_PRE_TRANSFORM,
312 TEST_DIMENSION_COMPOSITE_ALPHA,
313 TEST_DIMENSION_PRESENT_MODE,
314 TEST_DIMENSION_CLIPPED,
319 struct TestParameters
322 TestDimension dimension;
324 TestParameters (Type wsiType_, TestDimension dimension_)
326 , dimension (dimension_)
329 TestParameters (void)
330 : wsiType (TYPE_LAST)
331 , dimension (TEST_DIMENSION_LAST)
335 struct GroupParameters
337 typedef FunctionInstance1<TestParameters>::Function Function;
342 GroupParameters (Type wsiType_, Function function_)
344 , function (function_)
347 GroupParameters (void)
348 : wsiType (TYPE_LAST)
349 , function ((Function)DE_NULL)
353 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
354 const InstanceInterface& vki,
355 VkPhysicalDevice physicalDevice,
356 VkSurfaceKHR surface,
357 VkSurfaceFormatKHR surfaceFormat,
358 const tcu::UVec2& desiredSize,
359 deUint32 desiredImageCount)
361 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
364 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
365 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
366 const VkSwapchainCreateInfoKHR parameters =
368 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
370 (VkSwapchainCreateFlagsKHR)0,
372 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
373 surfaceFormat.format,
374 surfaceFormat.colorSpace,
375 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
376 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
377 1u, // imageArrayLayers
378 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
379 VK_SHARING_MODE_EXCLUSIVE,
381 (const deUint32*)DE_NULL,
383 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
384 VK_PRESENT_MODE_FIFO_KHR,
386 (VkSwapchainKHR)0 // oldSwapchain
392 typedef de::SharedPtr<Unique<VkImageView> > ImageViewSp;
393 typedef de::SharedPtr<Unique<VkFramebuffer> > FramebufferSp;
395 class TriangleRenderer
398 TriangleRenderer (const DeviceInterface& vkd,
399 const VkDevice device,
400 Allocator& allocator,
401 const BinaryCollection& binaryRegistry,
402 const vector<VkImage> swapchainImages,
403 const VkFormat framebufferFormat,
404 const UVec2& renderSize);
405 ~TriangleRenderer (void);
407 void recordFrame (VkCommandBuffer cmdBuffer,
409 deUint32 frameNdx) const;
411 static void getPrograms (SourceCollections& dst);
414 static Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd,
415 const VkDevice device,
416 const VkFormat colorAttachmentFormat);
417 static Move<VkPipelineLayout> createPipelineLayout(const DeviceInterface& vkd,
419 static Move<VkPipeline> createPipeline (const DeviceInterface& vkd,
420 const VkDevice device,
421 const VkRenderPass renderPass,
422 const VkPipelineLayout pipelineLayout,
423 const BinaryCollection& binaryCollection,
424 const UVec2& renderSize);
426 static Move<VkImageView> createAttachmentView(const DeviceInterface& vkd,
427 const VkDevice device,
429 const VkFormat format);
430 static Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd,
431 const VkDevice device,
432 const VkRenderPass renderPass,
433 const VkImageView colorAttachment,
434 const UVec2& renderSize);
436 static Move<VkBuffer> createBuffer (const DeviceInterface& vkd,
439 VkBufferUsageFlags usage);
441 const DeviceInterface& m_vkd;
443 const vector<VkImage> m_swapchainImages;
444 const tcu::UVec2 m_renderSize;
446 const Unique<VkRenderPass> m_renderPass;
447 const Unique<VkPipelineLayout> m_pipelineLayout;
448 const Unique<VkPipeline> m_pipeline;
450 const Unique<VkBuffer> m_vertexBuffer;
451 const UniquePtr<Allocation> m_vertexBufferMemory;
453 vector<ImageViewSp> m_attachmentViews;
454 vector<FramebufferSp> m_framebuffers;
457 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface& vkd,
458 const VkDevice device,
459 const VkFormat colorAttachmentFormat)
461 const VkAttachmentDescription colorAttDesc =
463 (VkAttachmentDescriptionFlags)0,
464 colorAttachmentFormat,
465 VK_SAMPLE_COUNT_1_BIT,
466 VK_ATTACHMENT_LOAD_OP_CLEAR,
467 VK_ATTACHMENT_STORE_OP_STORE,
468 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
469 VK_ATTACHMENT_STORE_OP_DONT_CARE,
470 VK_IMAGE_LAYOUT_UNDEFINED,
471 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
473 const VkAttachmentReference colorAttRef =
476 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
478 const VkSubpassDescription subpassDesc =
480 (VkSubpassDescriptionFlags)0u,
481 VK_PIPELINE_BIND_POINT_GRAPHICS,
482 0u, // inputAttachmentCount
483 DE_NULL, // pInputAttachments
484 1u, // colorAttachmentCount
485 &colorAttRef, // pColorAttachments
486 DE_NULL, // pResolveAttachments
487 DE_NULL, // depthStencilAttachment
488 0u, // preserveAttachmentCount
489 DE_NULL, // pPreserveAttachments
491 const VkSubpassDependency dependencies[] =
494 VK_SUBPASS_EXTERNAL, // srcSubpass
496 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
497 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
498 VK_ACCESS_MEMORY_READ_BIT,
499 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
500 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
501 VK_DEPENDENCY_BY_REGION_BIT
505 VK_SUBPASS_EXTERNAL, // dstSubpass
506 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
507 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
508 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
509 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
510 VK_ACCESS_MEMORY_READ_BIT,
511 VK_DEPENDENCY_BY_REGION_BIT
514 const VkRenderPassCreateInfo renderPassParams =
516 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
518 (VkRenderPassCreateFlags)0,
523 DE_LENGTH_OF_ARRAY(dependencies),
527 return vk::createRenderPass(vkd, device, &renderPassParams);
530 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface& vkd,
531 const VkDevice device)
533 const VkPushConstantRange pushConstantRange =
535 VK_SHADER_STAGE_VERTEX_BIT,
537 (deUint32)sizeof(deUint32), // size
539 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
541 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
543 (vk::VkPipelineLayoutCreateFlags)0,
544 0u, // setLayoutCount
545 DE_NULL, // pSetLayouts
550 return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
553 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface& vkd,
554 const VkDevice device,
555 const VkRenderPass renderPass,
556 const VkPipelineLayout pipelineLayout,
557 const BinaryCollection& binaryCollection,
558 const UVec2& renderSize)
560 // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
561 // and can be deleted immediately following that call.
562 const Unique<VkShaderModule> vertShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
563 const Unique<VkShaderModule> fragShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
564 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
565 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
567 return vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk
568 device, // const VkDevice device
569 pipelineLayout, // const VkPipelineLayout pipelineLayout
570 *vertShaderModule, // const VkShaderModule vertexShaderModule
571 DE_NULL, // const VkShaderModule tessellationControlShaderModule
572 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
573 DE_NULL, // const VkShaderModule geometryShaderModule
574 *fragShaderModule, // const VkShaderModule fragmentShaderModule
575 renderPass, // const VkRenderPass renderPass
576 viewports, // const std::vector<VkViewport>& viewports
577 scissors); // const std::vector<VkRect2D>& scissors
580 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface& vkd,
581 const VkDevice device,
583 const VkFormat format)
585 const VkImageViewCreateInfo viewParams =
587 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
589 (VkImageViewCreateFlags)0,
591 VK_IMAGE_VIEW_TYPE_2D,
593 vk::makeComponentMappingRGBA(),
595 VK_IMAGE_ASPECT_COLOR_BIT,
598 0u, // baseArrayLayer
603 return vk::createImageView(vkd, device, &viewParams);
606 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface& vkd,
607 const VkDevice device,
608 const VkRenderPass renderPass,
609 const VkImageView colorAttachment,
610 const UVec2& renderSize)
612 const VkFramebufferCreateInfo framebufferParams =
614 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
616 (VkFramebufferCreateFlags)0,
625 return vk::createFramebuffer(vkd, device, &framebufferParams);
628 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface& vkd,
631 VkBufferUsageFlags usage)
633 const VkBufferCreateInfo bufferParams =
635 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
637 (VkBufferCreateFlags)0,
640 VK_SHARING_MODE_EXCLUSIVE,
645 return vk::createBuffer(vkd, device, &bufferParams);
648 TriangleRenderer::TriangleRenderer (const DeviceInterface& vkd,
649 const VkDevice device,
650 Allocator& allocator,
651 const BinaryCollection& binaryRegistry,
652 const vector<VkImage> swapchainImages,
653 const VkFormat framebufferFormat,
654 const UVec2& renderSize)
656 , m_swapchainImages (swapchainImages)
657 , m_renderSize (renderSize)
658 , m_renderPass (createRenderPass(vkd, device, framebufferFormat))
659 , m_pipelineLayout (createPipelineLayout(vkd, device))
660 , m_pipeline (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
661 , m_vertexBuffer (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
662 , m_vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
663 MemoryRequirement::HostVisible))
665 m_attachmentViews.resize(swapchainImages.size());
666 m_framebuffers.resize(swapchainImages.size());
668 for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
670 m_attachmentViews[imageNdx] = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
671 m_framebuffers[imageNdx] = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
674 VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
677 const VkMappedMemoryRange memRange =
679 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
681 m_vertexBufferMemory->getMemory(),
682 m_vertexBufferMemory->getOffset(),
685 const tcu::Vec4 vertices[] =
687 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
688 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
689 tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
691 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
693 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
694 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
698 TriangleRenderer::~TriangleRenderer (void)
702 void TriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer,
704 deUint32 frameNdx) const
706 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx];
708 beginCommandBuffer(m_vkd, cmdBuffer, 0u);
710 beginRenderPass(m_vkd, cmdBuffer, *m_renderPass, curFramebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.125f, 0.25f, 0.75f, 1.0f));
712 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
715 const VkDeviceSize bindingOffset = 0;
716 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
719 m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
720 m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
721 endRenderPass(m_vkd, cmdBuffer);
723 endCommandBuffer(m_vkd, cmdBuffer);
726 void TriangleRenderer::getPrograms (SourceCollections& dst)
728 dst.glslSources.add("tri-vert") << glu::VertexSource(
730 "layout(location = 0) in highp vec4 a_position;\n"
731 "layout(push_constant) uniform FrameData\n"
733 " highp uint frameNdx;\n"
737 " highp float angle = float(frameData.frameNdx) / 100.0;\n"
738 " highp float c = cos(angle);\n"
739 " highp float s = sin(angle);\n"
740 " highp mat4 t = mat4( c, -s, 0, 0,\n"
744 " gl_Position = t * a_position;\n"
746 dst.glslSources.add("tri-frag") << glu::FragmentSource(
748 "layout(location = 0) out lowp vec4 o_color;\n"
749 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
752 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
753 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
754 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
756 vector<FenceSp> createFences (const DeviceInterface& vkd,
757 const VkDevice device,
760 vector<FenceSp> fences(numFences);
762 for (size_t ndx = 0; ndx < numFences; ++ndx)
763 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
768 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
769 const VkDevice device,
770 size_t numSemaphores)
772 vector<SemaphoreSp> semaphores(numSemaphores);
774 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
775 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
780 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
781 const VkDevice device,
782 const VkCommandPool commandPool,
783 const VkCommandBufferLevel level,
784 const size_t numCommandBuffers)
786 vector<CommandBufferSp> buffers (numCommandBuffers);
788 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
789 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
794 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
796 const tcu::UVec2 desiredSize (256, 256);
797 const InstanceHelper instHelper (context, wsiType);
798 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
799 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
800 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
802 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
803 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
805 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
806 devHelper.physicalDevice,
810 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
812 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
820 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
822 return tcu::TestStatus::pass("Extension tests succeeded");
825 tcu::TestStatus surfaceFormatRenderTest (Context& context,
827 VkSurfaceKHR surface,
828 VkSurfaceFormatKHR curFmt,
829 deBool checkHdr = false)
831 const tcu::UVec2 desiredSize (256, 256);
832 const InstanceHelper instHelper (context, wsiType);
833 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, surface);
834 const DeviceInterface& vkd = devHelper.vkd;
835 const VkDevice device = *devHelper.device;
836 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
838 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
839 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
840 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
841 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
843 if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
844 TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
846 const TriangleRenderer renderer (vkd,
849 context.getBinaryCollection(),
851 swapchainInfo.imageFormat,
852 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
854 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
856 const size_t maxQueuedFrames = swapchainImages.size()*2;
858 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
859 // limit number of frames we allow to be queued.
860 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
862 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
863 // the semaphore in same time as the fence we use to meter rendering.
864 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
866 // For rest we simply need maxQueuedFrames as we will wait for image
867 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
868 // previous uses must have completed.
869 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
870 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
874 const deUint32 numFramesToRender = 60;
876 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
878 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
879 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
880 deUint32 imageNdx = ~0u;
882 if (frameNdx >= maxQueuedFrames)
883 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
885 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
888 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
890 std::numeric_limits<deUint64>::max(),
895 if (acquireResult == VK_SUBOPTIMAL_KHR)
896 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
898 VK_CHECK(acquireResult);
901 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
904 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
905 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
906 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
907 const VkSubmitInfo submitInfo =
909 VK_STRUCTURE_TYPE_SUBMIT_INFO,
912 &imageReadySemaphore,
917 &renderingCompleteSemaphore
919 const VkPresentInfoKHR presentInfo =
921 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
924 &renderingCompleteSemaphore,
932 const VkHdrMetadataEXT hdrData = {
933 VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
935 makeXYColorEXT(0.680f, 0.320f),
936 makeXYColorEXT(0.265f, 0.690f),
937 makeXYColorEXT(0.150f, 0.060f),
938 makeXYColorEXT(0.3127f, 0.3290f),
944 vector<VkSwapchainKHR> swapchainArray;
946 swapchainArray.push_back(*swapchain);
947 vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
950 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
951 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
952 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
956 VK_CHECK(vkd.deviceWaitIdle(device));
960 // Make sure device is idle before destroying resources
961 vkd.deviceWaitIdle(device);
965 return tcu::TestStatus::pass("Rendering test succeeded");
968 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
970 const tcu::UVec2 desiredSize (256, 256);
971 const InstanceHelper instHelper (context, wsiType);
972 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
973 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
974 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
976 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
977 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
979 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
980 devHelper.physicalDevice,
982 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
984 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt);
986 return tcu::TestStatus::pass("Rendering tests succeeded");
989 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
991 const tcu::UVec2 desiredSize (256, 256);
992 const InstanceHelper instHelper (context, wsiType);
993 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
994 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
995 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
997 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
998 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
1000 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
1001 devHelper.physicalDevice,
1003 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1005 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt, true);
1007 return tcu::TestStatus::pass("Rendering tests succeeded");
1010 void getBasicRenderPrograms (SourceCollections& dst, Type)
1012 TriangleRenderer::getPrograms(dst);
1017 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1019 addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
1020 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
1021 addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);