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))) &&
265 platform.hasDisplay(wsiType))
267 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
268 // must support creating native display & window for that WSI type.
269 throw tcu::TestError(e.getMessage());
276 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
280 return MovePtr<Window>(display.createWindow(initialSize));
282 catch (const tcu::NotSupportedError& e)
284 // See createDisplay - assuming that wsi::Display was supported platform port
285 // should also support creating a window.
286 throw tcu::TestError(e.getMessage());
292 const UniquePtr<Display> display;
293 const UniquePtr<Window> window;
295 NativeObjects (Context& context,
296 const Extensions& supportedExtensions,
298 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
299 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
300 , window (createWindow(*display, initialWindowSize))
306 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
307 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
308 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
309 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
310 TEST_DIMENSION_IMAGE_USAGE,
311 TEST_DIMENSION_IMAGE_SHARING_MODE,
312 TEST_DIMENSION_PRE_TRANSFORM,
313 TEST_DIMENSION_COMPOSITE_ALPHA,
314 TEST_DIMENSION_PRESENT_MODE,
315 TEST_DIMENSION_CLIPPED,
320 struct TestParameters
323 TestDimension dimension;
325 TestParameters (Type wsiType_, TestDimension dimension_)
327 , dimension (dimension_)
330 TestParameters (void)
331 : wsiType (TYPE_LAST)
332 , dimension (TEST_DIMENSION_LAST)
336 struct GroupParameters
338 typedef FunctionInstance1<TestParameters>::Function Function;
343 GroupParameters (Type wsiType_, Function function_)
345 , function (function_)
348 GroupParameters (void)
349 : wsiType (TYPE_LAST)
350 , function ((Function)DE_NULL)
354 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
355 const InstanceInterface& vki,
356 VkPhysicalDevice physicalDevice,
357 VkSurfaceKHR surface,
358 VkSurfaceFormatKHR surfaceFormat,
359 const tcu::UVec2& desiredSize,
360 deUint32 desiredImageCount)
362 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
365 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
366 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
367 const VkSwapchainCreateInfoKHR parameters =
369 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
371 (VkSwapchainCreateFlagsKHR)0,
373 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
374 surfaceFormat.format,
375 surfaceFormat.colorSpace,
376 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
377 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
378 1u, // imageArrayLayers
379 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
380 VK_SHARING_MODE_EXCLUSIVE,
382 (const deUint32*)DE_NULL,
384 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
385 VK_PRESENT_MODE_FIFO_KHR,
387 (VkSwapchainKHR)0 // oldSwapchain
393 typedef de::SharedPtr<Unique<VkImageView> > ImageViewSp;
394 typedef de::SharedPtr<Unique<VkFramebuffer> > FramebufferSp;
396 class TriangleRenderer
399 TriangleRenderer (const DeviceInterface& vkd,
400 const VkDevice device,
401 Allocator& allocator,
402 const BinaryCollection& binaryRegistry,
403 const vector<VkImage> swapchainImages,
404 const VkFormat framebufferFormat,
405 const UVec2& renderSize);
406 ~TriangleRenderer (void);
408 void recordFrame (VkCommandBuffer cmdBuffer,
410 deUint32 frameNdx) const;
412 static void getPrograms (SourceCollections& dst);
415 static Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd,
416 const VkDevice device,
417 const VkFormat colorAttachmentFormat);
418 static Move<VkPipelineLayout> createPipelineLayout(const DeviceInterface& vkd,
420 static Move<VkPipeline> createPipeline (const DeviceInterface& vkd,
421 const VkDevice device,
422 const VkRenderPass renderPass,
423 const VkPipelineLayout pipelineLayout,
424 const BinaryCollection& binaryCollection,
425 const UVec2& renderSize);
427 static Move<VkImageView> createAttachmentView(const DeviceInterface& vkd,
428 const VkDevice device,
430 const VkFormat format);
431 static Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd,
432 const VkDevice device,
433 const VkRenderPass renderPass,
434 const VkImageView colorAttachment,
435 const UVec2& renderSize);
437 static Move<VkBuffer> createBuffer (const DeviceInterface& vkd,
440 VkBufferUsageFlags usage);
442 const DeviceInterface& m_vkd;
444 const vector<VkImage> m_swapchainImages;
445 const tcu::UVec2 m_renderSize;
447 const Unique<VkRenderPass> m_renderPass;
448 const Unique<VkPipelineLayout> m_pipelineLayout;
449 const Unique<VkPipeline> m_pipeline;
451 const Unique<VkBuffer> m_vertexBuffer;
452 const UniquePtr<Allocation> m_vertexBufferMemory;
454 vector<ImageViewSp> m_attachmentViews;
455 vector<FramebufferSp> m_framebuffers;
458 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface& vkd,
459 const VkDevice device,
460 const VkFormat colorAttachmentFormat)
462 const VkAttachmentDescription colorAttDesc =
464 (VkAttachmentDescriptionFlags)0,
465 colorAttachmentFormat,
466 VK_SAMPLE_COUNT_1_BIT,
467 VK_ATTACHMENT_LOAD_OP_CLEAR,
468 VK_ATTACHMENT_STORE_OP_STORE,
469 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
470 VK_ATTACHMENT_STORE_OP_DONT_CARE,
471 VK_IMAGE_LAYOUT_UNDEFINED,
472 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
474 const VkAttachmentReference colorAttRef =
477 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
479 const VkSubpassDescription subpassDesc =
481 (VkSubpassDescriptionFlags)0u,
482 VK_PIPELINE_BIND_POINT_GRAPHICS,
483 0u, // inputAttachmentCount
484 DE_NULL, // pInputAttachments
485 1u, // colorAttachmentCount
486 &colorAttRef, // pColorAttachments
487 DE_NULL, // pResolveAttachments
488 DE_NULL, // depthStencilAttachment
489 0u, // preserveAttachmentCount
490 DE_NULL, // pPreserveAttachments
492 const VkSubpassDependency dependencies[] =
495 VK_SUBPASS_EXTERNAL, // srcSubpass
497 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
498 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
499 VK_ACCESS_MEMORY_READ_BIT,
500 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
501 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
502 VK_DEPENDENCY_BY_REGION_BIT
506 VK_SUBPASS_EXTERNAL, // dstSubpass
507 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
508 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
509 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
510 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
511 VK_ACCESS_MEMORY_READ_BIT,
512 VK_DEPENDENCY_BY_REGION_BIT
515 const VkRenderPassCreateInfo renderPassParams =
517 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
519 (VkRenderPassCreateFlags)0,
524 DE_LENGTH_OF_ARRAY(dependencies),
528 return vk::createRenderPass(vkd, device, &renderPassParams);
531 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface& vkd,
532 const VkDevice device)
534 const VkPushConstantRange pushConstantRange =
536 VK_SHADER_STAGE_VERTEX_BIT,
538 (deUint32)sizeof(deUint32), // size
540 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
542 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
544 (vk::VkPipelineLayoutCreateFlags)0,
545 0u, // setLayoutCount
546 DE_NULL, // pSetLayouts
551 return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
554 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface& vkd,
555 const VkDevice device,
556 const VkRenderPass renderPass,
557 const VkPipelineLayout pipelineLayout,
558 const BinaryCollection& binaryCollection,
559 const UVec2& renderSize)
561 // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
562 // and can be deleted immediately following that call.
563 const Unique<VkShaderModule> vertShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
564 const Unique<VkShaderModule> fragShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
565 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
566 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
568 return vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk
569 device, // const VkDevice device
570 pipelineLayout, // const VkPipelineLayout pipelineLayout
571 *vertShaderModule, // const VkShaderModule vertexShaderModule
572 DE_NULL, // const VkShaderModule tessellationControlShaderModule
573 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
574 DE_NULL, // const VkShaderModule geometryShaderModule
575 *fragShaderModule, // const VkShaderModule fragmentShaderModule
576 renderPass, // const VkRenderPass renderPass
577 viewports, // const std::vector<VkViewport>& viewports
578 scissors); // const std::vector<VkRect2D>& scissors
581 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface& vkd,
582 const VkDevice device,
584 const VkFormat format)
586 const VkImageViewCreateInfo viewParams =
588 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
590 (VkImageViewCreateFlags)0,
592 VK_IMAGE_VIEW_TYPE_2D,
594 vk::makeComponentMappingRGBA(),
596 VK_IMAGE_ASPECT_COLOR_BIT,
599 0u, // baseArrayLayer
604 return vk::createImageView(vkd, device, &viewParams);
607 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface& vkd,
608 const VkDevice device,
609 const VkRenderPass renderPass,
610 const VkImageView colorAttachment,
611 const UVec2& renderSize)
613 const VkFramebufferCreateInfo framebufferParams =
615 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
617 (VkFramebufferCreateFlags)0,
626 return vk::createFramebuffer(vkd, device, &framebufferParams);
629 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface& vkd,
632 VkBufferUsageFlags usage)
634 const VkBufferCreateInfo bufferParams =
636 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
638 (VkBufferCreateFlags)0,
641 VK_SHARING_MODE_EXCLUSIVE,
646 return vk::createBuffer(vkd, device, &bufferParams);
649 TriangleRenderer::TriangleRenderer (const DeviceInterface& vkd,
650 const VkDevice device,
651 Allocator& allocator,
652 const BinaryCollection& binaryRegistry,
653 const vector<VkImage> swapchainImages,
654 const VkFormat framebufferFormat,
655 const UVec2& renderSize)
657 , m_swapchainImages (swapchainImages)
658 , m_renderSize (renderSize)
659 , m_renderPass (createRenderPass(vkd, device, framebufferFormat))
660 , m_pipelineLayout (createPipelineLayout(vkd, device))
661 , m_pipeline (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
662 , m_vertexBuffer (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
663 , m_vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
664 MemoryRequirement::HostVisible))
666 m_attachmentViews.resize(swapchainImages.size());
667 m_framebuffers.resize(swapchainImages.size());
669 for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
671 m_attachmentViews[imageNdx] = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
672 m_framebuffers[imageNdx] = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
675 VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
678 const VkMappedMemoryRange memRange =
680 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
682 m_vertexBufferMemory->getMemory(),
683 m_vertexBufferMemory->getOffset(),
686 const tcu::Vec4 vertices[] =
688 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
689 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
690 tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
692 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
694 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
695 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
699 TriangleRenderer::~TriangleRenderer (void)
703 void TriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer,
705 deUint32 frameNdx) const
707 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx];
709 beginCommandBuffer(m_vkd, cmdBuffer, 0u);
711 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));
713 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
716 const VkDeviceSize bindingOffset = 0;
717 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
720 m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
721 m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
722 endRenderPass(m_vkd, cmdBuffer);
724 endCommandBuffer(m_vkd, cmdBuffer);
727 void TriangleRenderer::getPrograms (SourceCollections& dst)
729 dst.glslSources.add("tri-vert") << glu::VertexSource(
731 "layout(location = 0) in highp vec4 a_position;\n"
732 "layout(push_constant) uniform FrameData\n"
734 " highp uint frameNdx;\n"
738 " highp float angle = float(frameData.frameNdx) / 100.0;\n"
739 " highp float c = cos(angle);\n"
740 " highp float s = sin(angle);\n"
741 " highp mat4 t = mat4( c, -s, 0, 0,\n"
745 " gl_Position = t * a_position;\n"
747 dst.glslSources.add("tri-frag") << glu::FragmentSource(
749 "layout(location = 0) out lowp vec4 o_color;\n"
750 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
753 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
754 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
755 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
757 vector<FenceSp> createFences (const DeviceInterface& vkd,
758 const VkDevice device,
761 vector<FenceSp> fences(numFences);
763 for (size_t ndx = 0; ndx < numFences; ++ndx)
764 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
769 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
770 const VkDevice device,
771 size_t numSemaphores)
773 vector<SemaphoreSp> semaphores(numSemaphores);
775 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
776 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
781 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
782 const VkDevice device,
783 const VkCommandPool commandPool,
784 const VkCommandBufferLevel level,
785 const size_t numCommandBuffers)
787 vector<CommandBufferSp> buffers (numCommandBuffers);
789 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
790 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
795 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
797 const tcu::UVec2 desiredSize (256, 256);
798 const InstanceHelper instHelper (context, wsiType);
799 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
800 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
801 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
803 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
804 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
806 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
807 devHelper.physicalDevice,
811 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
813 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
821 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
823 return tcu::TestStatus::pass("Extension tests succeeded");
826 tcu::TestStatus surfaceFormatRenderTest (Context& context,
828 VkSurfaceKHR surface,
829 VkSurfaceFormatKHR curFmt,
830 deBool checkHdr = false)
832 const tcu::UVec2 desiredSize (256, 256);
833 const InstanceHelper instHelper (context, wsiType);
834 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, surface);
835 const DeviceInterface& vkd = devHelper.vkd;
836 const VkDevice device = *devHelper.device;
837 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
839 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
840 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
841 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
842 const vector<VkExtensionProperties> deviceExtensions (enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
844 if (checkHdr && !isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_hdr_metadata")))
845 TCU_THROW(NotSupportedError, "Extension VK_EXT_hdr_metadata not supported");
847 const TriangleRenderer renderer (vkd,
850 context.getBinaryCollection(),
852 swapchainInfo.imageFormat,
853 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
855 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
857 const size_t maxQueuedFrames = swapchainImages.size()*2;
859 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
860 // limit number of frames we allow to be queued.
861 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
863 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
864 // the semaphore in same time as the fence we use to meter rendering.
865 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
867 // For rest we simply need maxQueuedFrames as we will wait for image
868 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
869 // previous uses must have completed.
870 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
871 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
875 const deUint32 numFramesToRender = 60;
877 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
879 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
880 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
881 deUint32 imageNdx = ~0u;
883 if (frameNdx >= maxQueuedFrames)
884 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
886 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
889 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
891 std::numeric_limits<deUint64>::max(),
896 if (acquireResult == VK_SUBOPTIMAL_KHR)
897 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
899 VK_CHECK(acquireResult);
902 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
905 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
906 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
907 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
908 const VkSubmitInfo submitInfo =
910 VK_STRUCTURE_TYPE_SUBMIT_INFO,
913 &imageReadySemaphore,
918 &renderingCompleteSemaphore
920 const VkPresentInfoKHR presentInfo =
922 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
925 &renderingCompleteSemaphore,
933 const VkHdrMetadataEXT hdrData = {
934 VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
936 makeXYColorEXT(0.680f, 0.320f),
937 makeXYColorEXT(0.265f, 0.690f),
938 makeXYColorEXT(0.150f, 0.060f),
939 makeXYColorEXT(0.3127f, 0.3290f),
945 vector<VkSwapchainKHR> swapchainArray;
947 swapchainArray.push_back(*swapchain);
948 vkd.setHdrMetadataEXT(device, (deUint32)swapchainArray.size(), swapchainArray.data(), &hdrData);
951 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
952 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
953 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
957 VK_CHECK(vkd.deviceWaitIdle(device));
961 // Make sure device is idle before destroying resources
962 vkd.deviceWaitIdle(device);
966 return tcu::TestStatus::pass("Rendering test succeeded");
969 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
971 const tcu::UVec2 desiredSize (256, 256);
972 const InstanceHelper instHelper (context, wsiType);
973 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
974 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
975 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
977 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
978 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
980 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
981 devHelper.physicalDevice,
983 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
985 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt);
987 return tcu::TestStatus::pass("Rendering tests succeeded");
990 tcu::TestStatus surfaceFormatRenderWithHdrTests (Context& context, Type wsiType)
992 const tcu::UVec2 desiredSize (256, 256);
993 const InstanceHelper instHelper (context, wsiType);
994 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
995 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
996 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
998 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
999 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
1001 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
1002 devHelper.physicalDevice,
1004 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1006 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt, true);
1008 return tcu::TestStatus::pass("Rendering tests succeeded");
1011 void getBasicRenderPrograms (SourceCollections& dst, Type)
1013 TriangleRenderer::getPrograms(dst);
1018 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1020 addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
1021 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);
1022 addFunctionCaseWithPrograms(testGroup, "hdr", "Basic Rendering Tests with HDR", getBasicRenderPrograms, surfaceFormatRenderWithHdrTests, wsiType);