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 "vkWsiPlatform.hpp"
40 #include "vkWsiUtil.hpp"
41 #include "vkAllocationCallbackUtil.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuFormatUtil.hpp"
45 #include "tcuPlatform.hpp"
46 #include "tcuResultCollector.hpp"
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deArrayUtil.hpp"
51 #include "deSharedPtr.hpp"
64 using namespace vk::wsi;
76 typedef vector<VkExtensionProperties> Extensions;
78 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
80 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
81 requiredExtName != requiredExtensions.end();
84 if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
85 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
89 Move<VkInstance> createInstanceWithWsi (const PlatformInterface& vkp,
91 const Extensions& supportedExtensions,
93 const VkAllocationCallbacks* pAllocator = DE_NULL)
95 vector<string> extensions;
97 extensions.push_back("VK_KHR_surface");
98 extensions.push_back(getExtensionName(wsiType));
100 // VK_EXT_swapchain_colorspace adds new surface formats. Driver can enumerate
101 // the formats regardless of whether VK_EXT_swapchain_colorspace was enabled,
102 // but using them without enabling the extension is not allowed. Thus we have
105 // 1) Filter out non-core formats to stay within valid usage.
107 // 2) Enable VK_EXT_swapchain colorspace if advertised by the driver.
109 // We opt for (2) as it provides basic coverage for the extension as a bonus.
110 if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_swapchain_colorspace")))
111 extensions.push_back("VK_EXT_swapchain_colorspace");
113 checkAllSupported(supportedExtensions, extensions);
115 return createDefaultInstance(vkp, version, vector<string>(), extensions, pAllocator);
118 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
120 VkPhysicalDeviceFeatures features;
121 deMemset(&features, 0, sizeof(features));
125 Move<VkDevice> createDeviceWithWsi (const InstanceInterface& vki,
126 VkPhysicalDevice physicalDevice,
127 const Extensions& supportedExtensions,
128 const deUint32 queueFamilyIndex,
129 const VkAllocationCallbacks* pAllocator = DE_NULL)
131 const float queuePriorities[] = { 1.0f };
132 const VkDeviceQueueCreateInfo queueInfos[] =
135 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
137 (VkDeviceQueueCreateFlags)0,
139 DE_LENGTH_OF_ARRAY(queuePriorities),
143 const VkPhysicalDeviceFeatures features = getDeviceFeaturesForWsi();
144 const char* const extensions[] = { "VK_KHR_swapchain" };
145 const VkDeviceCreateInfo deviceParams =
147 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
149 (VkDeviceCreateFlags)0,
150 DE_LENGTH_OF_ARRAY(queueInfos),
152 0u, // enabledLayerCount
153 DE_NULL, // ppEnabledLayerNames
154 DE_LENGTH_OF_ARRAY(extensions), // enabledExtensionCount
155 DE_ARRAY_BEGIN(extensions), // ppEnabledExtensionNames
159 if (!isExtensionSupported(supportedExtensions, RequiredExtension(extensions[0])))
160 TCU_THROW(NotSupportedError, (string(extensions[0]) + " is not supported").c_str());
162 return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
165 deUint32 getNumQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
167 deUint32 numFamilies = 0;
169 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
174 vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
176 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
177 vector<deUint32> supportedFamilyIndices;
179 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
181 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
182 supportedFamilyIndices.push_back(queueFamilyNdx);
185 return supportedFamilyIndices;
188 deUint32 chooseQueueFamilyIndex (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
190 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
192 if (supportedFamilyIndices.empty())
193 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
195 return supportedFamilyIndices[0];
198 struct InstanceHelper
200 const vector<VkExtensionProperties> supportedExtensions;
201 const Unique<VkInstance> instance;
202 const InstanceDriver vki;
204 InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
205 : supportedExtensions (enumerateInstanceExtensionProperties(context.getPlatformInterface(),
207 , instance (createInstanceWithWsi(context.getPlatformInterface(),
208 context.getUsedApiVersion(),
212 , vki (context.getPlatformInterface(), *instance)
218 const VkPhysicalDevice physicalDevice;
219 const deUint32 queueFamilyIndex;
220 const Unique<VkDevice> device;
221 const DeviceDriver vkd;
224 DeviceHelper (Context& context,
225 const InstanceInterface& vki,
227 VkSurfaceKHR surface,
228 const VkAllocationCallbacks* pAllocator = DE_NULL)
229 : physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
230 , queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, surface))
231 , device (createDeviceWithWsi(vki,
233 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
237 , queue (getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
242 MovePtr<Display> createDisplay (const vk::Platform& platform,
243 const Extensions& supportedExtensions,
248 return MovePtr<Display>(platform.createWsiDisplay(wsiType));
250 catch (const tcu::NotSupportedError& e)
252 if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
254 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
255 // must support creating native display & window for that WSI type.
256 throw tcu::TestError(e.getMessage());
263 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
267 return MovePtr<Window>(display.createWindow(initialSize));
269 catch (const tcu::NotSupportedError& e)
271 // See createDisplay - assuming that wsi::Display was supported platform port
272 // should also support creating a window.
273 throw tcu::TestError(e.getMessage());
279 const UniquePtr<Display> display;
280 const UniquePtr<Window> window;
282 NativeObjects (Context& context,
283 const Extensions& supportedExtensions,
285 const Maybe<UVec2>& initialWindowSize = tcu::nothing<UVec2>())
286 : display (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
287 , window (createWindow(*display, initialWindowSize))
293 TEST_DIMENSION_MIN_IMAGE_COUNT = 0, //!< Test all supported image counts
294 TEST_DIMENSION_IMAGE_FORMAT, //!< Test all supported formats
295 TEST_DIMENSION_IMAGE_EXTENT, //!< Test various (supported) extents
296 TEST_DIMENSION_IMAGE_ARRAY_LAYERS,
297 TEST_DIMENSION_IMAGE_USAGE,
298 TEST_DIMENSION_IMAGE_SHARING_MODE,
299 TEST_DIMENSION_PRE_TRANSFORM,
300 TEST_DIMENSION_COMPOSITE_ALPHA,
301 TEST_DIMENSION_PRESENT_MODE,
302 TEST_DIMENSION_CLIPPED,
307 struct TestParameters
310 TestDimension dimension;
312 TestParameters (Type wsiType_, TestDimension dimension_)
314 , dimension (dimension_)
317 TestParameters (void)
318 : wsiType (TYPE_LAST)
319 , dimension (TEST_DIMENSION_LAST)
323 struct GroupParameters
325 typedef FunctionInstance1<TestParameters>::Function Function;
330 GroupParameters (Type wsiType_, Function function_)
332 , function (function_)
335 GroupParameters (void)
336 : wsiType (TYPE_LAST)
337 , function ((Function)DE_NULL)
341 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType,
342 const InstanceInterface& vki,
343 VkPhysicalDevice physicalDevice,
344 VkSurfaceKHR surface,
345 VkSurfaceFormatKHR surfaceFormat,
346 const tcu::UVec2& desiredSize,
347 deUint32 desiredImageCount)
349 const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki,
352 const PlatformProperties& platformProperties = getPlatformProperties(wsiType);
353 const VkSurfaceTransformFlagBitsKHR transform = (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
354 const VkSwapchainCreateInfoKHR parameters =
356 VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
358 (VkSwapchainCreateFlagsKHR)0,
360 de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
361 surfaceFormat.format,
362 surfaceFormat.colorSpace,
363 (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
364 ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
365 1u, // imageArrayLayers
366 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
367 VK_SHARING_MODE_EXCLUSIVE,
369 (const deUint32*)DE_NULL,
371 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
372 VK_PRESENT_MODE_FIFO_KHR,
374 (VkSwapchainKHR)0 // oldSwapchain
380 typedef de::SharedPtr<Unique<VkImageView> > ImageViewSp;
381 typedef de::SharedPtr<Unique<VkFramebuffer> > FramebufferSp;
383 class TriangleRenderer
386 TriangleRenderer (const DeviceInterface& vkd,
387 const VkDevice device,
388 Allocator& allocator,
389 const BinaryCollection& binaryRegistry,
390 const vector<VkImage> swapchainImages,
391 const VkFormat framebufferFormat,
392 const UVec2& renderSize);
393 ~TriangleRenderer (void);
395 void recordFrame (VkCommandBuffer cmdBuffer,
397 deUint32 frameNdx) const;
399 static void getPrograms (SourceCollections& dst);
402 static Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd,
403 const VkDevice device,
404 const VkFormat colorAttachmentFormat);
405 static Move<VkPipelineLayout> createPipelineLayout(const DeviceInterface& vkd,
407 static Move<VkPipeline> createPipeline (const DeviceInterface& vkd,
408 const VkDevice device,
409 const VkRenderPass renderPass,
410 const VkPipelineLayout pipelineLayout,
411 const BinaryCollection& binaryCollection,
412 const UVec2& renderSize);
414 static Move<VkImageView> createAttachmentView(const DeviceInterface& vkd,
415 const VkDevice device,
417 const VkFormat format);
418 static Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd,
419 const VkDevice device,
420 const VkRenderPass renderPass,
421 const VkImageView colorAttachment,
422 const UVec2& renderSize);
424 static Move<VkBuffer> createBuffer (const DeviceInterface& vkd,
427 VkBufferUsageFlags usage);
429 const DeviceInterface& m_vkd;
431 const vector<VkImage> m_swapchainImages;
432 const tcu::UVec2 m_renderSize;
434 const Unique<VkRenderPass> m_renderPass;
435 const Unique<VkPipelineLayout> m_pipelineLayout;
436 const Unique<VkPipeline> m_pipeline;
438 const Unique<VkBuffer> m_vertexBuffer;
439 const UniquePtr<Allocation> m_vertexBufferMemory;
441 vector<ImageViewSp> m_attachmentViews;
442 vector<FramebufferSp> m_framebuffers;
445 Move<VkRenderPass> TriangleRenderer::createRenderPass (const DeviceInterface& vkd,
446 const VkDevice device,
447 const VkFormat colorAttachmentFormat)
449 const VkAttachmentDescription colorAttDesc =
451 (VkAttachmentDescriptionFlags)0,
452 colorAttachmentFormat,
453 VK_SAMPLE_COUNT_1_BIT,
454 VK_ATTACHMENT_LOAD_OP_CLEAR,
455 VK_ATTACHMENT_STORE_OP_STORE,
456 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
457 VK_ATTACHMENT_STORE_OP_DONT_CARE,
458 VK_IMAGE_LAYOUT_UNDEFINED,
459 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
461 const VkAttachmentReference colorAttRef =
464 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
466 const VkSubpassDescription subpassDesc =
468 (VkSubpassDescriptionFlags)0u,
469 VK_PIPELINE_BIND_POINT_GRAPHICS,
470 0u, // inputAttachmentCount
471 DE_NULL, // pInputAttachments
472 1u, // colorAttachmentCount
473 &colorAttRef, // pColorAttachments
474 DE_NULL, // pResolveAttachments
475 DE_NULL, // depthStencilAttachment
476 0u, // preserveAttachmentCount
477 DE_NULL, // pPreserveAttachments
479 const VkSubpassDependency dependencies[] =
482 VK_SUBPASS_EXTERNAL, // srcSubpass
484 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
485 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
486 VK_ACCESS_MEMORY_READ_BIT,
487 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
488 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
489 VK_DEPENDENCY_BY_REGION_BIT
493 VK_SUBPASS_EXTERNAL, // dstSubpass
494 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
495 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
496 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
497 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
498 VK_ACCESS_MEMORY_READ_BIT,
499 VK_DEPENDENCY_BY_REGION_BIT
502 const VkRenderPassCreateInfo renderPassParams =
504 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
506 (VkRenderPassCreateFlags)0,
511 DE_LENGTH_OF_ARRAY(dependencies),
515 return vk::createRenderPass(vkd, device, &renderPassParams);
518 Move<VkPipelineLayout> TriangleRenderer::createPipelineLayout (const DeviceInterface& vkd,
519 const VkDevice device)
521 const VkPushConstantRange pushConstantRange =
523 VK_SHADER_STAGE_VERTEX_BIT,
525 (deUint32)sizeof(deUint32), // size
527 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
529 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
531 (vk::VkPipelineLayoutCreateFlags)0,
532 0u, // setLayoutCount
533 DE_NULL, // pSetLayouts
538 return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
541 Move<VkPipeline> TriangleRenderer::createPipeline (const DeviceInterface& vkd,
542 const VkDevice device,
543 const VkRenderPass renderPass,
544 const VkPipelineLayout pipelineLayout,
545 const BinaryCollection& binaryCollection,
546 const UVec2& renderSize)
548 // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
549 // and can be deleted immediately following that call.
550 const Unique<VkShaderModule> vertShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
551 const Unique<VkShaderModule> fragShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
553 const VkSpecializationInfo emptyShaderSpecParams =
560 const VkPipelineShaderStageCreateInfo shaderStageParams[] =
563 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
565 (VkPipelineShaderStageCreateFlags)0,
566 VK_SHADER_STAGE_VERTEX_BIT,
569 &emptyShaderSpecParams,
572 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
574 (VkPipelineShaderStageCreateFlags)0,
575 VK_SHADER_STAGE_FRAGMENT_BIT,
578 &emptyShaderSpecParams,
581 const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
583 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
585 (VkPipelineDepthStencilStateCreateFlags)0,
586 DE_FALSE, // depthTestEnable
587 DE_FALSE, // depthWriteEnable
588 VK_COMPARE_OP_ALWAYS, // depthCompareOp
589 DE_FALSE, // depthBoundsTestEnable
590 DE_FALSE, // stencilTestEnable
592 VK_STENCIL_OP_KEEP, // failOp
593 VK_STENCIL_OP_KEEP, // passOp
594 VK_STENCIL_OP_KEEP, // depthFailOp
595 VK_COMPARE_OP_ALWAYS, // compareOp
601 VK_STENCIL_OP_KEEP, // failOp
602 VK_STENCIL_OP_KEEP, // passOp
603 VK_STENCIL_OP_KEEP, // depthFailOp
604 VK_COMPARE_OP_ALWAYS, // compareOp
609 -1.0f, // minDepthBounds
610 +1.0f, // maxDepthBounds
612 const VkViewport viewport0 =
616 (float)renderSize.x(), // width
617 (float)renderSize.y(), // height
621 const VkRect2D scissor0 =
623 { 0u, 0u, }, // offset
624 { renderSize.x(), renderSize.y() }, // extent
626 const VkPipelineViewportStateCreateInfo viewportParams =
628 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
630 (VkPipelineViewportStateCreateFlags)0,
636 const VkPipelineMultisampleStateCreateInfo multisampleParams =
638 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
640 (VkPipelineMultisampleStateCreateFlags)0,
641 VK_SAMPLE_COUNT_1_BIT, // rasterizationSamples
642 VK_FALSE, // sampleShadingEnable
643 0.0f, // minSampleShading
644 (const VkSampleMask*)DE_NULL, // sampleMask
645 VK_FALSE, // alphaToCoverageEnable
646 VK_FALSE, // alphaToOneEnable
648 const VkPipelineRasterizationStateCreateInfo rasterParams =
650 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
652 (VkPipelineRasterizationStateCreateFlags)0,
653 VK_FALSE, // depthClampEnable
654 VK_FALSE, // rasterizerDiscardEnable
655 VK_POLYGON_MODE_FILL, // polygonMode
656 VK_CULL_MODE_NONE, // cullMode
657 VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
658 VK_FALSE, // depthBiasEnable
659 0.0f, // depthBiasConstantFactor
660 0.0f, // depthBiasClamp
661 0.0f, // depthBiasSlopeFactor
664 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
666 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
668 (VkPipelineInputAssemblyStateCreateFlags)0,
669 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
670 DE_FALSE, // primitiveRestartEnable
672 const VkVertexInputBindingDescription vertexBinding0 =
675 (deUint32)sizeof(tcu::Vec4), // stride
676 VK_VERTEX_INPUT_RATE_VERTEX, // inputRate
678 const VkVertexInputAttributeDescription vertexAttrib0 =
682 VK_FORMAT_R32G32B32A32_SFLOAT, // format
685 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
687 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
689 (VkPipelineVertexInputStateCreateFlags)0,
695 const VkPipelineColorBlendAttachmentState attBlendParams0 =
697 VK_FALSE, // blendEnable
698 VK_BLEND_FACTOR_ONE, // srcColorBlendFactor
699 VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor
700 VK_BLEND_OP_ADD, // colorBlendOp
701 VK_BLEND_FACTOR_ONE, // srcAlphaBlendFactor
702 VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor
703 VK_BLEND_OP_ADD, // alphaBlendOp
704 (VK_COLOR_COMPONENT_R_BIT|
705 VK_COLOR_COMPONENT_G_BIT|
706 VK_COLOR_COMPONENT_B_BIT|
707 VK_COLOR_COMPONENT_A_BIT), // colorWriteMask
709 const VkPipelineColorBlendStateCreateInfo blendParams =
711 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
713 (VkPipelineColorBlendStateCreateFlags)0,
714 VK_FALSE, // logicOpEnable
718 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants[4]
720 const VkGraphicsPipelineCreateInfo pipelineParams =
722 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
724 (VkPipelineCreateFlags)0,
725 (deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams),
727 &vertexInputStateParams,
728 &inputAssemblyParams,
729 (const VkPipelineTessellationStateCreateInfo*)DE_NULL,
735 (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
739 DE_NULL, // basePipelineHandle
740 0u, // basePipelineIndex
743 return vk::createGraphicsPipeline(vkd, device, (VkPipelineCache)0, &pipelineParams);
746 Move<VkImageView> TriangleRenderer::createAttachmentView (const DeviceInterface& vkd,
747 const VkDevice device,
749 const VkFormat format)
751 const VkImageViewCreateInfo viewParams =
753 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
755 (VkImageViewCreateFlags)0,
757 VK_IMAGE_VIEW_TYPE_2D,
759 vk::makeComponentMappingRGBA(),
761 VK_IMAGE_ASPECT_COLOR_BIT,
764 0u, // baseArrayLayer
769 return vk::createImageView(vkd, device, &viewParams);
772 Move<VkFramebuffer> TriangleRenderer::createFramebuffer (const DeviceInterface& vkd,
773 const VkDevice device,
774 const VkRenderPass renderPass,
775 const VkImageView colorAttachment,
776 const UVec2& renderSize)
778 const VkFramebufferCreateInfo framebufferParams =
780 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
782 (VkFramebufferCreateFlags)0,
791 return vk::createFramebuffer(vkd, device, &framebufferParams);
794 Move<VkBuffer> TriangleRenderer::createBuffer (const DeviceInterface& vkd,
797 VkBufferUsageFlags usage)
799 const VkBufferCreateInfo bufferParams =
801 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
803 (VkBufferCreateFlags)0,
806 VK_SHARING_MODE_EXCLUSIVE,
811 return vk::createBuffer(vkd, device, &bufferParams);
814 TriangleRenderer::TriangleRenderer (const DeviceInterface& vkd,
815 const VkDevice device,
816 Allocator& allocator,
817 const BinaryCollection& binaryRegistry,
818 const vector<VkImage> swapchainImages,
819 const VkFormat framebufferFormat,
820 const UVec2& renderSize)
822 , m_swapchainImages (swapchainImages)
823 , m_renderSize (renderSize)
824 , m_renderPass (createRenderPass(vkd, device, framebufferFormat))
825 , m_pipelineLayout (createPipelineLayout(vkd, device))
826 , m_pipeline (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
827 , m_vertexBuffer (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
828 , m_vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
829 MemoryRequirement::HostVisible))
831 m_attachmentViews.resize(swapchainImages.size());
832 m_framebuffers.resize(swapchainImages.size());
834 for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
836 m_attachmentViews[imageNdx] = ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
837 m_framebuffers[imageNdx] = FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
840 VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
843 const VkMappedMemoryRange memRange =
845 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
847 m_vertexBufferMemory->getMemory(),
848 m_vertexBufferMemory->getOffset(),
851 const tcu::Vec4 vertices[] =
853 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
854 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
855 tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
857 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
859 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
860 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
864 TriangleRenderer::~TriangleRenderer (void)
868 void TriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer,
870 deUint32 frameNdx) const
872 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx];
875 const VkCommandBufferBeginInfo cmdBufBeginParams =
877 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
879 (VkCommandBufferUsageFlags)0,
880 (const VkCommandBufferInheritanceInfo*)DE_NULL,
882 VK_CHECK(m_vkd.beginCommandBuffer(cmdBuffer, &cmdBufBeginParams));
886 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
887 const VkRenderPassBeginInfo passBeginParams =
889 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
895 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() }
897 1u, // clearValueCount
898 &clearValue, // pClearValues
900 m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
903 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
906 const VkDeviceSize bindingOffset = 0;
907 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
910 m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
911 m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
912 m_vkd.cmdEndRenderPass(cmdBuffer);
914 VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer));
917 void TriangleRenderer::getPrograms (SourceCollections& dst)
919 dst.glslSources.add("tri-vert") << glu::VertexSource(
921 "layout(location = 0) in highp vec4 a_position;\n"
922 "layout(push_constant) uniform FrameData\n"
924 " highp uint frameNdx;\n"
928 " highp float angle = float(frameData.frameNdx) / 100.0;\n"
929 " highp float c = cos(angle);\n"
930 " highp float s = sin(angle);\n"
931 " highp mat4 t = mat4( c, -s, 0, 0,\n"
935 " gl_Position = t * a_position;\n"
937 dst.glslSources.add("tri-frag") << glu::FragmentSource(
939 "layout(location = 0) out lowp vec4 o_color;\n"
940 "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
943 typedef de::SharedPtr<Unique<VkCommandBuffer> > CommandBufferSp;
944 typedef de::SharedPtr<Unique<VkFence> > FenceSp;
945 typedef de::SharedPtr<Unique<VkSemaphore> > SemaphoreSp;
947 vector<FenceSp> createFences (const DeviceInterface& vkd,
948 const VkDevice device,
951 vector<FenceSp> fences(numFences);
953 for (size_t ndx = 0; ndx < numFences; ++ndx)
954 fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
959 vector<SemaphoreSp> createSemaphores (const DeviceInterface& vkd,
960 const VkDevice device,
961 size_t numSemaphores)
963 vector<SemaphoreSp> semaphores(numSemaphores);
965 for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
966 semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
971 vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface& vkd,
972 const VkDevice device,
973 const VkCommandPool commandPool,
974 const VkCommandBufferLevel level,
975 const size_t numCommandBuffers)
977 vector<CommandBufferSp> buffers (numCommandBuffers);
979 for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
980 buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
985 tcu::TestStatus basicExtensionTest (Context& context, Type wsiType)
987 const tcu::UVec2 desiredSize (256, 256);
988 const InstanceHelper instHelper (context, wsiType);
989 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
990 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
991 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
993 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
994 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
996 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
997 devHelper.physicalDevice,
1001 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1003 if (curFmt->colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
1011 TCU_THROW(NotSupportedError, "VK_EXT_swapchain_colorspace supported, but no non-SRGB_NONLINEAR_KHR surface formats found.");
1013 return tcu::TestStatus::pass("Extension tests succeeded");
1016 tcu::TestStatus surfaceFormatRenderTest (Context& context, Type wsiType, VkSurfaceKHR surface, VkSurfaceFormatKHR curFmt)
1018 const tcu::UVec2 desiredSize (256, 256);
1019 const InstanceHelper instHelper (context, wsiType);
1020 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, surface);
1021 const DeviceInterface& vkd = devHelper.vkd;
1022 const VkDevice device = *devHelper.device;
1023 SimpleAllocator allocator (vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
1025 tcu::print("Test Surface format: %s, %s\n", de::toString(curFmt.format).c_str(), de::toString(curFmt.colorSpace).c_str());
1026 const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, surface, curFmt, desiredSize, 2);
1027 const Unique<VkSwapchainKHR> swapchain (createSwapchainKHR(vkd, device, &swapchainInfo));
1028 const vector<VkImage> swapchainImages = getSwapchainImages(vkd, device, *swapchain);
1030 const TriangleRenderer renderer (vkd,
1033 context.getBinaryCollection(),
1035 swapchainInfo.imageFormat,
1036 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
1038 const Unique<VkCommandPool> commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
1040 const size_t maxQueuedFrames = swapchainImages.size()*2;
1042 // We need to keep hold of fences from vkAcquireNextImageKHR to actually
1043 // limit number of frames we allow to be queued.
1044 const vector<FenceSp> imageReadyFences (createFences(vkd, device, maxQueuedFrames));
1046 // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
1047 // the semaphore in same time as the fence we use to meter rendering.
1048 const vector<SemaphoreSp> imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1));
1050 // For rest we simply need maxQueuedFrames as we will wait for image
1051 // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
1052 // previous uses must have completed.
1053 const vector<SemaphoreSp> renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames));
1054 const vector<CommandBufferSp> commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
1058 const deUint32 numFramesToRender = 60;
1060 for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
1062 const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()];
1063 const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
1064 deUint32 imageNdx = ~0u;
1066 if (frameNdx >= maxQueuedFrames)
1067 VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
1069 VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
1072 const VkResult acquireResult = vkd.acquireNextImageKHR(device,
1074 std::numeric_limits<deUint64>::max(),
1075 imageReadySemaphore,
1079 if (acquireResult == VK_SUBOPTIMAL_KHR)
1080 context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage;
1082 VK_CHECK(acquireResult);
1085 TCU_CHECK((size_t)imageNdx < swapchainImages.size());
1088 const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
1089 const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()];
1090 const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1091 const VkSubmitInfo submitInfo =
1093 VK_STRUCTURE_TYPE_SUBMIT_INFO,
1096 &imageReadySemaphore,
1101 &renderingCompleteSemaphore
1103 const VkPresentInfoKHR presentInfo =
1105 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1108 &renderingCompleteSemaphore,
1115 renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
1116 VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
1117 VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo));
1121 VK_CHECK(vkd.deviceWaitIdle(device));
1125 // Make sure device is idle before destroying resources
1126 vkd.deviceWaitIdle(device);
1129 tcu::print("Done\n");
1131 return tcu::TestStatus::pass("Rendering test succeeded");
1134 tcu::TestStatus surfaceFormatRenderTests (Context& context, Type wsiType)
1136 const tcu::UVec2 desiredSize (256, 256);
1137 const InstanceHelper instHelper (context, wsiType);
1138 const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize));
1139 const Unique<VkSurfaceKHR> surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
1140 const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface);
1142 if (!de::contains(context.getInstanceExtensions().begin(), context.getInstanceExtensions().end(), "VK_EXT_swapchain_colorspace"))
1143 TCU_THROW(NotSupportedError, "Extension VK_EXT_swapchain_colorspace not supported");
1145 const vector<VkSurfaceFormatKHR> formats = getPhysicalDeviceSurfaceFormats(instHelper.vki,
1146 devHelper.physicalDevice,
1148 for (vector<VkSurfaceFormatKHR>::const_iterator curFmt = formats.begin(); curFmt != formats.end(); ++curFmt)
1150 surfaceFormatRenderTest(context, wsiType, *surface, *curFmt);
1152 return tcu::TestStatus::pass("Rendering tests succeeded");
1155 void getBasicRenderPrograms (SourceCollections& dst, Type)
1157 TriangleRenderer::getPrograms(dst);
1162 void createColorSpaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1164 addFunctionCase(testGroup, "extensions", "Verify Colorspace Extensions", basicExtensionTest, wsiType);
1165 addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Tests", getBasicRenderPrograms, surfaceFormatRenderTests, wsiType);