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 Tests for VK_GOOGLE_display_timing
22 *//*--------------------------------------------------------------------*/
24 #include "vktWsiDisplayTimingTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkWsiPlatform.hpp"
30 #include "vkWsiUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkPrograms.hpp"
37 #include "vkWsiUtil.hpp"
39 #include "tcuPlatform.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTestLog.hpp"
60 static const deUint64 MILLISECOND = 1000ull * 1000ull;
61 static const deUint64 SECOND = 1000ull * MILLISECOND;
63 typedef vector<vk::VkExtensionProperties> Extensions;
65 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
67 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
68 requiredExtName != requiredExtensions.end();
71 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
72 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
76 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp,
77 const Extensions& supportedExtensions,
78 vk::wsi::Type wsiType)
80 vector<string> extensions;
82 extensions.push_back("VK_KHR_surface");
83 extensions.push_back(getExtensionName(wsiType));
85 checkAllSupported(supportedExtensions, extensions);
87 return vk::createDefaultInstance(vkp, vector<string>(), extensions);
90 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
92 vk::VkPhysicalDeviceFeatures features;
93 deMemset(&features, 0, sizeof(features));
97 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
99 deUint32 numFamilies = 0;
101 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
106 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
108 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
109 vector<deUint32> supportedFamilyIndices;
111 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
113 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) == VK_TRUE)
114 supportedFamilyIndices.push_back(queueFamilyNdx);
117 return supportedFamilyIndices;
120 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
122 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
124 if (supportedFamilyIndices.empty())
125 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
127 return supportedFamilyIndices[0];
130 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::InstanceInterface& vki,
131 vk::VkPhysicalDevice physicalDevice,
132 const Extensions& supportedExtensions,
133 const deUint32 queueFamilyIndex,
134 bool requiresDisplayTiming,
135 const vk::VkAllocationCallbacks* pAllocator = DE_NULL)
137 const float queuePriorities[] = { 1.0f };
138 const vk::VkDeviceQueueCreateInfo queueInfos[] =
141 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
143 (vk::VkDeviceQueueCreateFlags)0,
145 DE_LENGTH_OF_ARRAY(queuePriorities),
149 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures();
150 const char* const extensions[] =
153 "VK_GOOGLE_display_timing"
156 const vk::VkDeviceCreateInfo deviceParams =
158 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
160 (vk::VkDeviceCreateFlags)0,
161 DE_LENGTH_OF_ARRAY(queueInfos),
165 requiresDisplayTiming ? 2u : 1u,
166 DE_ARRAY_BEGIN(extensions),
170 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
172 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
173 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
176 return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
179 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform,
180 const Extensions& supportedExtensions,
181 vk::wsi::Type wsiType)
185 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
187 catch (const tcu::NotSupportedError& e)
189 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
191 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
192 // must support creating native display & window for that WSI type.
193 throw tcu::TestError(e.getMessage());
200 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
204 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
206 catch (const tcu::NotSupportedError& e)
208 // See createDisplay - assuming that wsi::Display was supported platform port
209 // should also support creating a window.
210 throw tcu::TestError(e.getMessage());
214 void initSemaphores (const vk::DeviceInterface& vkd,
216 std::vector<vk::VkSemaphore>& semaphores)
218 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
219 semaphores[ndx] = createSemaphore(vkd, device).disown();
222 void deinitSemaphores (const vk::DeviceInterface& vkd,
224 std::vector<vk::VkSemaphore>& semaphores)
226 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
228 if (semaphores[ndx] != (vk::VkSemaphore)0)
229 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
231 semaphores[ndx] = (vk::VkSemaphore)0;
237 void initFences (const vk::DeviceInterface& vkd,
239 std::vector<vk::VkFence>& fences)
241 for (size_t ndx = 0; ndx < fences.size(); ndx++)
242 fences[ndx] = createFence(vkd, device).disown();
245 void deinitFences (const vk::DeviceInterface& vkd,
247 std::vector<vk::VkFence>& fences)
249 for (size_t ndx = 0; ndx < fences.size(); ndx++)
251 if (fences[ndx] != (vk::VkFence)0)
252 vkd.destroyFence(device, fences[ndx], DE_NULL);
254 fences[ndx] = (vk::VkFence)0;
260 void cmdRenderFrame (const vk::DeviceInterface& vkd,
261 vk::VkCommandBuffer commandBuffer,
262 vk::VkPipelineLayout pipelineLayout,
263 vk::VkPipeline pipeline,
267 const deUint32 frameNdxValue = (deUint32)frameNdx;
269 vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &frameNdxValue);
270 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
271 vkd.cmdDraw(commandBuffer, quadCount * 6u, 1u, 0u, 0u);
274 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
276 vk::VkCommandPool commandPool,
277 vk::VkPipelineLayout pipelineLayout,
278 vk::VkRenderPass renderPass,
279 vk::VkFramebuffer framebuffer,
280 vk::VkPipeline pipeline,
284 deUint32 imageHeight)
286 const vk::VkCommandBufferAllocateInfo allocateInfo =
288 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
292 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
295 const vk::VkCommandBufferBeginInfo beginInfo =
297 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
303 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
304 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
307 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f);
308 const vk::VkRenderPassBeginInfo renderPassBeginInfo =
310 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
317 { (deInt32)0, (deInt32)0 },
318 { imageWidth, imageHeight }
323 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
326 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, quadCount);
328 vkd.cmdEndRenderPass(*commandBuffer);
330 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
331 return commandBuffer;
334 void deinitCommandBuffers (const vk::DeviceInterface& vkd,
336 vk::VkCommandPool commandPool,
337 std::vector<vk::VkCommandBuffer>& commandBuffers)
339 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
341 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
342 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
344 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
347 commandBuffers.clear();
350 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
352 deUint32 queueFamilyIndex)
354 const vk::VkCommandPoolCreateInfo createInfo =
356 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
362 return vk::createCommandPool(vkd, device, &createInfo);
365 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd,
367 vk::VkRenderPass renderPass,
368 vk::VkImageView imageView,
372 const vk::VkFramebufferCreateInfo createInfo =
374 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
386 return vk::createFramebuffer(vkd, device, &createInfo);
389 void initFramebuffers (const vk::DeviceInterface& vkd,
391 vk::VkRenderPass renderPass,
392 std::vector<vk::VkImageView> imageViews,
395 std::vector<vk::VkFramebuffer>& framebuffers)
397 DE_ASSERT(framebuffers.size() == imageViews.size());
399 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
400 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
403 void deinitFramebuffers (const vk::DeviceInterface& vkd,
405 std::vector<vk::VkFramebuffer>& framebuffers)
407 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
409 if (framebuffers[ndx] != (vk::VkFramebuffer)0)
410 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
412 framebuffers[ndx] = (vk::VkFramebuffer)0;
415 framebuffers.clear();
418 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
423 const vk::VkImageViewCreateInfo createInfo =
425 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
430 vk::VK_IMAGE_VIEW_TYPE_2D,
432 vk::makeComponentMappingRGBA(),
434 vk::VK_IMAGE_ASPECT_COLOR_BIT,
442 return vk::createImageView(vkd, device, &createInfo, DE_NULL);
445 void initImageViews (const vk::DeviceInterface& vkd,
447 const std::vector<vk::VkImage>& images,
449 std::vector<vk::VkImageView>& imageViews)
451 DE_ASSERT(images.size() == imageViews.size());
453 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
454 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
457 void deinitImageViews (const vk::DeviceInterface& vkd,
459 std::vector<vk::VkImageView>& imageViews)
461 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
463 if (imageViews[ndx] != (vk::VkImageView)0)
464 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
466 imageViews[ndx] = (vk::VkImageView)0;
472 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
476 const vk::VkAttachmentDescription attachments[] =
481 vk::VK_SAMPLE_COUNT_1_BIT,
483 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
484 vk::VK_ATTACHMENT_STORE_OP_STORE,
486 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
487 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
489 vk::VK_IMAGE_LAYOUT_UNDEFINED,
490 vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
493 const vk::VkAttachmentReference colorAttachmentRefs[] =
497 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
500 const vk::VkSubpassDescription subpasses[] =
504 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
508 DE_LENGTH_OF_ARRAY(colorAttachmentRefs),
518 const vk::VkRenderPassCreateInfo createInfo =
520 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
524 DE_LENGTH_OF_ARRAY(attachments),
527 DE_LENGTH_OF_ARRAY(subpasses),
534 return vk::createRenderPass(vkd, device, &createInfo);
537 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd,
539 vk::VkRenderPass renderPass,
540 vk::VkPipelineLayout layout,
541 vk::VkShaderModule vertexShaderModule,
542 vk::VkShaderModule fragmentShaderModule,
546 const vk::VkSpecializationInfo shaderSpecialization =
553 const vk::VkPipelineShaderStageCreateInfo stages[] =
556 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
559 vk::VK_SHADER_STAGE_VERTEX_BIT,
562 &shaderSpecialization
565 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
568 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
569 fragmentShaderModule,
571 &shaderSpecialization
574 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
576 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
584 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
586 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
589 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
592 const vk::VkViewport viewports[] =
596 (float)width, (float)height,
600 const vk::VkRect2D scissors[] =
607 const vk::VkPipelineViewportStateCreateInfo viewportState =
609 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
613 DE_LENGTH_OF_ARRAY(viewports),
615 DE_LENGTH_OF_ARRAY(scissors),
618 const vk::VkPipelineRasterizationStateCreateInfo rasterizationState =
620 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
625 vk::VK_POLYGON_MODE_FILL,
626 vk::VK_CULL_MODE_NONE,
627 vk::VK_FRONT_FACE_CLOCKWISE,
634 const vk::VkSampleMask sampleMask = ~0u;
635 const vk::VkPipelineMultisampleStateCreateInfo multisampleState =
637 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
640 vk::VK_SAMPLE_COUNT_1_BIT,
647 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilState =
649 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
654 vk::VK_COMPARE_OP_ALWAYS,
658 vk::VK_STENCIL_OP_KEEP,
659 vk::VK_STENCIL_OP_KEEP,
660 vk::VK_STENCIL_OP_KEEP,
661 vk::VK_COMPARE_OP_ALWAYS,
667 vk::VK_STENCIL_OP_KEEP,
668 vk::VK_STENCIL_OP_KEEP,
669 vk::VK_STENCIL_OP_KEEP,
670 vk::VK_COMPARE_OP_ALWAYS,
678 const vk::VkPipelineColorBlendAttachmentState attachmentBlendState =
681 vk::VK_BLEND_FACTOR_ONE,
682 vk::VK_BLEND_FACTOR_ZERO,
684 vk::VK_BLEND_FACTOR_ONE,
685 vk::VK_BLEND_FACTOR_ZERO,
687 (vk::VK_COLOR_COMPONENT_R_BIT|
688 vk::VK_COLOR_COMPONENT_G_BIT|
689 vk::VK_COLOR_COMPONENT_B_BIT|
690 vk::VK_COLOR_COMPONENT_A_BIT),
692 const vk::VkPipelineColorBlendStateCreateInfo blendState =
694 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
698 vk::VK_LOGIC_OP_COPY,
700 &attachmentBlendState,
701 { 0.0f, 0.0f, 0.0f, 0.0f }
703 const vk::VkPipelineDynamicStateCreateInfo dynamicState =
705 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
712 const vk::VkGraphicsPipelineCreateInfo createInfo =
714 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
718 DE_LENGTH_OF_ARRAY(stages),
736 return vk::createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
739 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
742 const vk::VkPushConstantRange pushConstants[] =
745 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
750 const vk::VkPipelineLayoutCreateInfo createInfo =
752 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
759 DE_LENGTH_OF_ARRAY(pushConstants),
763 return vk::createPipelineLayout(vkd, device, &createInfo);
768 vk::wsi::Type wsiType;
769 bool useDisplayTiming;
770 vk::VkPresentModeKHR presentMode;
773 class DisplayTimingTestInstance : public TestInstance
776 DisplayTimingTestInstance (Context& context, const TestConfig& testConfig);
777 ~DisplayTimingTestInstance (void);
779 tcu::TestStatus iterate (void);
782 const bool m_useDisplayTiming;
783 const deUint32 m_quadCount;
784 const vk::PlatformInterface& m_vkp;
785 const Extensions m_instanceExtensions;
786 const vk::Unique<vk::VkInstance> m_instance;
787 const vk::InstanceDriver m_vki;
788 const vk::VkPhysicalDevice m_physicalDevice;
789 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
790 const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
791 const vk::Unique<vk::VkSurfaceKHR> m_surface;
793 const deUint32 m_queueFamilyIndex;
794 const Extensions m_deviceExtensions;
795 const vk::Unique<vk::VkDevice> m_device;
796 const vk::DeviceDriver m_vkd;
797 const vk::VkQueue m_queue;
799 const vk::Unique<vk::VkCommandPool> m_commandPool;
800 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
801 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
802 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
804 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
805 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
806 const vector<vk::VkPresentModeKHR> m_presentModes;
808 tcu::ResultCollector m_resultCollector;
810 vk::Move<vk::VkSwapchainKHR> m_swapchain;
811 std::vector<vk::VkImage> m_swapchainImages;
813 vk::Move<vk::VkRenderPass> m_renderPass;
814 vk::Move<vk::VkPipeline> m_pipeline;
816 std::vector<vk::VkImageView> m_swapchainImageViews;
817 std::vector<vk::VkFramebuffer> m_framebuffers;
818 std::vector<vk::VkCommandBuffer> m_commandBuffers;
819 std::vector<vk::VkSemaphore> m_acquireSemaphores;
820 std::vector<vk::VkSemaphore> m_renderSemaphores;
821 std::vector<vk::VkFence> m_fences;
823 vk::VkSemaphore m_freeAcquireSemaphore;
824 vk::VkSemaphore m_freeRenderSemaphore;
826 vk::VkSwapchainCreateInfoKHR m_swapchainConfig;
828 const size_t m_frameCount;
831 const size_t m_maxOutOfDateCount;
832 size_t m_outOfDateCount;
834 std::map<deUint32, deUint64> m_queuePresentTimes;
836 vk::VkRefreshCycleDurationGOOGLE m_rcDuration;
837 deUint64 m_refreshDurationMultiplier;
838 deUint64 m_targetIPD;
839 deUint64 m_prevDesiredPresentTime;
840 deUint32 m_nextPresentID;
841 deUint32 m_ignoreThruPresentID;
842 bool m_ExpectImage80Late;
844 void initSwapchainResources (void);
845 void deinitSwapchainResources (void);
849 vk::VkSwapchainCreateInfoKHR createSwapchainConfig (vk::VkSurfaceKHR surface,
850 deUint32 queueFamilyIndex,
851 const vk::VkSurfaceCapabilitiesKHR& properties,
852 const vector<vk::VkSurfaceFormatKHR>& formats,
853 const vector<vk::VkPresentModeKHR>& presentModes,
854 vk::VkPresentModeKHR presentMode)
856 const deUint32 imageLayers = 1u;
857 const vk::VkImageUsageFlags imageUsage = properties.supportedUsageFlags;
858 const vk::VkBool32 clipped = VK_FALSE;
860 const deUint32 imageWidth = (properties.currentExtent.width != 0xFFFFFFFFu)
861 ? properties.currentExtent.width
862 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
863 const deUint32 imageHeight = (properties.currentExtent.height != 0xFFFFFFFFu)
864 ? properties.currentExtent.height
865 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
866 const vk::VkExtent2D imageSize = { imageWidth, imageHeight };
869 size_t presentModeNdx;
871 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
873 if (presentModes[presentModeNdx] == presentMode)
877 if (presentModeNdx == presentModes.size())
878 TCU_THROW(NotSupportedError, "Present mode not supported");
881 // Pick the first supported transform, alpha, and format:
882 vk::VkSurfaceTransformFlagsKHR transform;
883 for (transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
885 if ((properties.supportedTransforms & transform) != 0)
889 vk::VkCompositeAlphaFlagsKHR alpha;
890 for (alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
892 if ((alpha & properties.supportedCompositeAlpha) != 0)
897 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
898 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
899 const vk::VkFormat imageFormat = formats[0].format;
900 const vk::VkColorSpaceKHR imageColorSpace = formats[0].colorSpace;
901 const vk::VkSwapchainCreateInfoKHR createInfo =
903 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
907 properties.minImageCount,
913 vk::VK_SHARING_MODE_EXCLUSIVE,
920 (vk::VkSwapchainKHR)0
927 DisplayTimingTestInstance::DisplayTimingTestInstance (Context& context, const TestConfig& testConfig)
928 : TestInstance (context)
929 , m_useDisplayTiming (testConfig.useDisplayTiming)
931 , m_vkp (context.getPlatformInterface())
932 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
933 , m_instance (createInstanceWithWsi(m_vkp, m_instanceExtensions, testConfig.wsiType))
934 , m_vki (m_vkp, *m_instance)
935 , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
936 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
937 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
938 , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
940 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
941 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
942 , m_device (createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useDisplayTiming))
943 , m_vkd (m_vki, *m_device)
944 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
946 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
947 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
948 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
949 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device))
951 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
952 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
953 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
955 , m_freeAcquireSemaphore ((vk::VkSemaphore)0)
956 , m_freeRenderSemaphore ((vk::VkSemaphore)0)
958 , m_swapchainConfig (createSwapchainConfig(*m_surface, m_queueFamilyIndex, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode))
960 , m_frameCount (60u * 5u)
963 , m_maxOutOfDateCount (20u)
964 , m_outOfDateCount (0u)
965 , m_ExpectImage80Late (false)
968 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
969 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
973 DisplayTimingTestInstance::~DisplayTimingTestInstance (void)
975 deinitSwapchainResources();
978 void DisplayTimingTestInstance::initSwapchainResources (void)
980 const size_t fenceCount = 6;
981 const deUint32 imageWidth = m_swapchainConfig.imageExtent.width;
982 const deUint32 imageHeight = m_swapchainConfig.imageExtent.height;
983 const vk::VkFormat imageFormat = m_swapchainConfig.imageFormat;
985 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfig);
986 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
988 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
989 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
991 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
992 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
993 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
994 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
996 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
997 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
999 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
1000 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1002 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
1003 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown();
1005 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
1006 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
1007 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1008 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
1010 initFences(m_vkd, *m_device, m_fences);
1012 if (m_useDisplayTiming)
1014 // This portion should do interesting bits
1015 m_queuePresentTimes = std::map<deUint32, deUint64>();
1017 m_vkd.getRefreshCycleDurationGOOGLE(*m_device, *m_swapchain, &m_rcDuration);
1019 m_refreshDurationMultiplier = 1u;
1020 m_targetIPD = m_rcDuration.refreshDuration;
1021 m_prevDesiredPresentTime = 0u;
1022 m_nextPresentID = 0u;
1023 m_ignoreThruPresentID = 0u;
1027 void DisplayTimingTestInstance::deinitSwapchainResources (void)
1029 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
1031 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
1033 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
1034 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
1037 if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
1039 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
1040 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1043 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1044 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
1045 deinitFences(m_vkd, *m_device, m_fences);
1046 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
1047 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
1048 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
1050 m_swapchainImages.clear();
1052 m_swapchain = vk::Move<vk::VkSwapchainKHR>();
1053 m_renderPass = vk::Move<vk::VkRenderPass>();
1054 m_pipeline = vk::Move<vk::VkPipeline>();
1058 vector<vk::VkPastPresentationTimingGOOGLE> getPastPresentationTiming (const vk::DeviceInterface& vkd,
1059 vk::VkDevice device,
1060 vk::VkSwapchainKHR swapchain)
1062 vector<vk::VkPastPresentationTimingGOOGLE> pastPresentationTimings;
1063 deUint32 numPastPresentationTimings = 0;
1065 vkd.getPastPresentationTimingGOOGLE(device, swapchain, &numPastPresentationTimings, DE_NULL);
1067 pastPresentationTimings.resize(numPastPresentationTimings);
1069 if (numPastPresentationTimings > 0)
1070 vkd.getPastPresentationTimingGOOGLE(device, swapchain, &numPastPresentationTimings, &pastPresentationTimings[0]);
1072 return pastPresentationTimings;
1075 void DisplayTimingTestInstance::render (void)
1077 const deUint64 foreverNs = ~0x0ull;
1078 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()];
1079 const deUint32 width = m_swapchainConfig.imageExtent.width;
1080 const deUint32 height = m_swapchainConfig.imageExtent.height;
1081 tcu::TestLog& log = m_context.getTestContext().getLog();
1083 // Throttle execution
1084 if (m_frameNdx >= m_fences.size())
1086 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
1087 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
1089 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
1090 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
1093 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
1094 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore;
1095 deUint32 imageIndex;
1097 // Acquire next image
1098 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex));
1100 // Create command buffer
1101 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, m_frameNdx, m_quadCount, width, height).disown();
1103 // Obtain timing data from previous frames
1104 if (m_useDisplayTiming)
1106 const vector<vk::VkPastPresentationTimingGOOGLE> pastPresentationTimings (getPastPresentationTiming(m_vkd, *m_device, *m_swapchain));
1107 bool isEarly = false;
1108 bool isLate = false;
1110 for (size_t pastPresentationInfoNdx = 0 ; pastPresentationInfoNdx < pastPresentationTimings.size(); pastPresentationInfoNdx++)
1112 if (m_queuePresentTimes[pastPresentationTimings[pastPresentationInfoNdx].presentID] > pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime)
1114 m_resultCollector.fail("Image with PresentID " + de::toString(pastPresentationTimings[pastPresentationInfoNdx].presentID) + "was displayed before vkQueuePresentKHR was called.");
1116 if (!m_ignoreThruPresentID)
1118 // This is the first time that we've received an
1119 // actualPresentTime for this swapchain. In order to not
1120 // perceive these early frames as "late", we need to sync-up
1121 // our future desiredPresentTime's with the
1122 // actualPresentTime(s) that we're receiving now.
1123 const deInt64 multiple = m_nextPresentID - pastPresentationTimings.back().presentID;
1125 m_prevDesiredPresentTime = pastPresentationTimings.back().actualPresentTime + (multiple * m_targetIPD);
1126 m_ignoreThruPresentID = pastPresentationTimings[pastPresentationInfoNdx].presentID + 1;
1128 else if (pastPresentationTimings[pastPresentationInfoNdx].presentID > m_ignoreThruPresentID)
1130 if (pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime > (pastPresentationTimings[pastPresentationInfoNdx].desiredPresentTime + m_rcDuration.refreshDuration + MILLISECOND))
1132 const deUint64 actual = pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime;
1133 const deUint64 desired = pastPresentationTimings[pastPresentationInfoNdx].desiredPresentTime;
1134 const deUint64 rdur = m_rcDuration.refreshDuration;
1135 const deUint64 diff1 = actual - (desired + rdur);
1136 const deUint64 diff2 = actual - desired;
1138 log << TestLog::Message << "Image PresentID " << pastPresentationTimings[pastPresentationInfoNdx].presentID << " was " << diff1 << " nsec late." << TestLog::EndMessage;
1139 if (m_ExpectImage80Late && (pastPresentationTimings[pastPresentationInfoNdx].presentID == 80))
1141 if (diff1 > (SECOND / 2))
1142 log << TestLog::Message << "\tNote: Image PresentID 80 was expected to be late by approximately 1 second." << TestLog::EndMessage;
1144 m_resultCollector.fail("Image PresentID 80 was not late by approximately 1 second, as expected.");
1146 log << TestLog::Message << "\t\t actualPresentTime = " << actual << " nsec" << TestLog::EndMessage;
1147 log << TestLog::Message << "\t\t - desiredPresentTime= " << desired << " nsec" << TestLog::EndMessage;
1148 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1149 log << TestLog::Message << "\t\t diff = " << diff2 << " nsec" << TestLog::EndMessage;
1150 log << TestLog::Message << "\t\t - refreshDuration = " << rdur << " nsec" << TestLog::EndMessage;
1151 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1152 log << TestLog::Message << "\t\t diff = " << diff1 << " nsec" << TestLog::EndMessage;
1156 else if ((pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime > pastPresentationTimings[pastPresentationInfoNdx].earliestPresentTime) &&
1157 (pastPresentationTimings[pastPresentationInfoNdx].presentMargin > (2 * MILLISECOND)))
1159 const deUint64 actual = pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime;
1160 const deUint64 earliest = pastPresentationTimings[pastPresentationInfoNdx].earliestPresentTime;
1161 const deUint64 diff = actual - earliest;
1163 log << TestLog::Message << "Image PresentID " << pastPresentationTimings[pastPresentationInfoNdx].presentID << " can be presented " << diff << " nsec earlier." << TestLog::EndMessage;
1164 log << TestLog::Message << "\t\t actualPresentTime = " << actual << " nsec" << TestLog::EndMessage;
1165 log << TestLog::Message << "\t\t -earliestPresentTime= " << earliest << " nsec" << TestLog::EndMessage;
1166 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1167 log << TestLog::Message << "\t\t diff = " << diff << " nsec" << TestLog::EndMessage;
1173 // Preference is given to late presents over early presents:
1176 // Demonstrate how to slow down the frame rate if a frame is late,
1177 // but don't go too slow (for test time reasons):
1178 if (++m_refreshDurationMultiplier > 2)
1179 m_refreshDurationMultiplier = 2;
1181 log << TestLog::Message << "Increasing multiplier." << TestLog::EndMessage;
1185 // Demonstrate how to speed up the frame rate if a frame is early,
1186 // but don't let the multiplier hit zero:
1187 if (--m_refreshDurationMultiplier == 0)
1188 m_refreshDurationMultiplier = 1;
1190 log << TestLog::Message << "Decreasing multiplier." << TestLog::EndMessage;
1192 m_targetIPD = m_rcDuration.refreshDuration * m_refreshDurationMultiplier;
1195 // Submit command buffer
1197 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1198 const vk::VkSubmitInfo submitInfo =
1200 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1203 ¤tAcquireSemaphore,
1206 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
1208 ¤tRenderSemaphore
1211 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
1215 if (m_useDisplayTiming)
1217 // This portion should do interesting bits
1219 // Initially, mirror reference to move things along
1220 vk::VkResult result;
1221 vk::VkPresentTimeGOOGLE presentTime =
1224 m_prevDesiredPresentTime
1226 // Record the current time, to record as the time of the vkQueuePresentKHR() call:
1227 const deUint64 curtimeNano = deGetMicroseconds() * 1000;
1228 m_queuePresentTimes[m_nextPresentID] = curtimeNano;
1230 deUint64 desiredPresentTime = 0u;
1231 if (m_prevDesiredPresentTime == 0)
1233 // This must be the first present for this swapchain. Find out the
1234 // current time, as the basis for desiredPresentTime:
1235 if (curtimeNano != 0)
1237 presentTime.desiredPresentTime = curtimeNano;
1238 presentTime.desiredPresentTime += (m_targetIPD / 2);
1242 // Since we didn't find out the current time, don't give a
1243 // desiredPresentTime:
1244 presentTime.desiredPresentTime = 0;
1249 desiredPresentTime = m_prevDesiredPresentTime + m_targetIPD;
1250 if ((presentTime.presentID == 80) && (m_swapchainConfig.presentMode != vk::VK_PRESENT_MODE_MAILBOX_KHR))
1252 // Test if desiredPresentTime is 1 second earlier (i.e. before the previous image could have been presented)
1253 presentTime.desiredPresentTime -= SECOND;
1254 m_ExpectImage80Late = true;
1257 m_prevDesiredPresentTime = desiredPresentTime;
1259 const vk::VkPresentTimesInfoGOOGLE presentTimesInfo =
1261 vk::VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE,
1266 const vk::VkPresentInfoKHR presentInfo =
1268 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1271 ¤tRenderSemaphore,
1278 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1283 vk::VkResult result;
1284 const vk::VkPresentInfoKHR presentInfo =
1286 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1289 ¤tRenderSemaphore,
1296 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1301 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1302 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1304 m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1305 m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1309 tcu::TestStatus DisplayTimingTestInstance::iterate (void)
1311 // Initialize swapchain specific resources
1315 if (m_frameNdx == 0)
1317 if (m_outOfDateCount == 0)
1318 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfig << tcu::TestLog::EndMessage;
1320 initSwapchainResources();
1325 catch (const vk::Error& error)
1327 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1329 if (m_outOfDateCount < m_maxOutOfDateCount)
1331 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1332 deinitSwapchainResources();
1336 return tcu::TestStatus::incomplete();
1340 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1341 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1346 m_resultCollector.fail(error.what());
1349 deinitSwapchainResources();
1351 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1356 if (m_frameNdx >= m_frameCount)
1358 deinitSwapchainResources();
1360 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1363 return tcu::TestStatus::incomplete();
1368 static void init (vk::SourceCollections& dst, TestConfig)
1370 dst.glslSources.add("quad-vert") << glu::VertexSource(
1372 "out gl_PerVertex {\n"
1373 "\tvec4 gl_Position;\n"
1376 "void main (void) {\n"
1377 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1378 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1380 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1382 "layout(location = 0) out highp vec4 o_color;\n"
1383 "layout(push_constant) uniform PushConstant {\n"
1384 "\thighp uint frameNdx;\n"
1385 "} pushConstants;\n"
1386 "void main (void)\n"
1388 "\thighp uint frameNdx = pushConstants.frameNdx;\n"
1389 "\thighp uint x = frameNdx + uint(gl_FragCoord.x);\n"
1390 "\thighp uint y = frameNdx + uint(gl_FragCoord.y);\n"
1391 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1392 "\t + 64u * bitfieldExtract(y, 1, 1)\n"
1393 "\t + 32u * bitfieldExtract(x, 3, 1);\n"
1394 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1395 "\t + 64u * bitfieldExtract(x, 2, 1)\n"
1396 "\t + 32u * bitfieldExtract(y, 3, 1);\n"
1397 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1398 "\t + 64u * bitfieldExtract(y, 2, 1)\n"
1399 "\t + 32u * bitfieldExtract(x, 4, 1);\n"
1400 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1407 void createDisplayTimingTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1411 vk::VkPresentModeKHR mode;
1415 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" },
1416 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" },
1417 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" },
1418 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" },
1421 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1423 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1425 for (size_t ref = 0; ref < 2; ref++)
1427 const bool isReference = (ref == 0);
1428 const char* const name = isReference ? "reference" : "display_timing";
1431 config.wsiType = wsiType;
1432 config.useDisplayTiming = !isReference;
1433 config.presentMode = presentModes[presentModeNdx].mode;
1435 presentModeGroup->addChild(new vkt::InstanceFactory1<DisplayTimingTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1438 testGroup->addChild(presentModeGroup.release());