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"
59 static const deUint64 MILLISECOND = 1000ull * 1000ull;
60 static const deUint64 SECOND = 1000ull * MILLISECOND;
62 typedef vector<vk::VkExtensionProperties> Extensions;
64 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
66 for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
67 requiredExtName != requiredExtensions.end();
70 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName)))
71 TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
75 vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp,
76 const Extensions& supportedExtensions,
77 vk::wsi::Type wsiType)
79 vector<string> extensions;
81 extensions.push_back("VK_KHR_surface");
82 extensions.push_back(getExtensionName(wsiType));
84 checkAllSupported(supportedExtensions, extensions);
86 return vk::createDefaultInstance(vkp, vector<string>(), extensions);
89 vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void)
91 vk::VkPhysicalDeviceFeatures features;
92 deMemset(&features, 0, sizeof(features));
96 deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
98 deUint32 numFamilies = 0;
100 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
105 vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
107 const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice);
108 vector<deUint32> supportedFamilyIndices;
110 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
112 if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) == VK_TRUE)
113 supportedFamilyIndices.push_back(queueFamilyNdx);
116 return supportedFamilyIndices;
119 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
121 const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
123 if (supportedFamilyIndices.empty())
124 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
126 return supportedFamilyIndices[0];
129 vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::InstanceInterface& vki,
130 vk::VkPhysicalDevice physicalDevice,
131 const Extensions& supportedExtensions,
132 const deUint32 queueFamilyIndex,
133 bool requiresDisplayTiming,
134 const vk::VkAllocationCallbacks* pAllocator = DE_NULL)
136 const float queuePriorities[] = { 1.0f };
137 const vk::VkDeviceQueueCreateInfo queueInfos[] =
140 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
142 (vk::VkDeviceQueueCreateFlags)0,
144 DE_LENGTH_OF_ARRAY(queuePriorities),
148 const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures();
149 const char* const extensions[] =
152 "VK_GOOGLE_display_timing"
155 const vk::VkDeviceCreateInfo deviceParams =
157 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
159 (vk::VkDeviceCreateFlags)0,
160 DE_LENGTH_OF_ARRAY(queueInfos),
164 requiresDisplayTiming ? 2u : 1u,
165 DE_ARRAY_BEGIN(extensions),
169 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx)
171 if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx])))
172 TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str());
175 return createDevice(vki, physicalDevice, &deviceParams, pAllocator);
178 de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform,
179 const Extensions& supportedExtensions,
180 vk::wsi::Type wsiType)
184 return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType));
186 catch (const tcu::NotSupportedError& e)
188 if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))))
190 // If VK_KHR_{platform}_surface was supported, vk::Platform implementation
191 // must support creating native display & window for that WSI type.
192 throw tcu::TestError(e.getMessage());
199 de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize)
203 return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize));
205 catch (const tcu::NotSupportedError& e)
207 // See createDisplay - assuming that wsi::Display was supported platform port
208 // should also support creating a window.
209 throw tcu::TestError(e.getMessage());
213 void initSemaphores (const vk::DeviceInterface& vkd,
215 std::vector<vk::VkSemaphore>& semaphores)
217 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
218 semaphores[ndx] = createSemaphore(vkd, device).disown();
221 void deinitSemaphores (const vk::DeviceInterface& vkd,
223 std::vector<vk::VkSemaphore>& semaphores)
225 for (size_t ndx = 0; ndx < semaphores.size(); ndx++)
227 if (semaphores[ndx] != (vk::VkSemaphore)0)
228 vkd.destroySemaphore(device, semaphores[ndx], DE_NULL);
230 semaphores[ndx] = (vk::VkSemaphore)0;
236 void initFences (const vk::DeviceInterface& vkd,
238 std::vector<vk::VkFence>& fences)
240 for (size_t ndx = 0; ndx < fences.size(); ndx++)
241 fences[ndx] = createFence(vkd, device).disown();
244 void deinitFences (const vk::DeviceInterface& vkd,
246 std::vector<vk::VkFence>& fences)
248 for (size_t ndx = 0; ndx < fences.size(); ndx++)
250 if (fences[ndx] != (vk::VkFence)0)
251 vkd.destroyFence(device, fences[ndx], DE_NULL);
253 fences[ndx] = (vk::VkFence)0;
259 void cmdRenderFrame (const vk::DeviceInterface& vkd,
260 vk::VkCommandBuffer commandBuffer,
261 vk::VkPipelineLayout pipelineLayout,
262 vk::VkPipeline pipeline,
266 const deUint32 frameNdxValue = (deUint32)frameNdx;
268 vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &frameNdxValue);
269 vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
270 vkd.cmdDraw(commandBuffer, quadCount * 6u, 1u, 0u, 0u);
273 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
275 vk::VkCommandPool commandPool,
276 vk::VkPipelineLayout pipelineLayout,
277 vk::VkRenderPass renderPass,
278 vk::VkFramebuffer framebuffer,
279 vk::VkPipeline pipeline,
283 deUint32 imageHeight)
285 const vk::VkCommandBufferAllocateInfo allocateInfo =
287 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
291 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,
294 const vk::VkCommandBufferBeginInfo beginInfo =
296 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
302 vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo));
303 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo));
306 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.25f, 0.50f, 0.75f, 1.00f);
307 const vk::VkRenderPassBeginInfo renderPassBeginInfo =
309 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
316 { (deInt32)0, (deInt32)0 },
317 { imageWidth, imageHeight }
322 vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
325 cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, quadCount);
327 vkd.cmdEndRenderPass(*commandBuffer);
329 VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
330 return commandBuffer;
333 void deinitCommandBuffers (const vk::DeviceInterface& vkd,
335 vk::VkCommandPool commandPool,
336 std::vector<vk::VkCommandBuffer>& commandBuffers)
338 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
340 if (commandBuffers[ndx] != (vk::VkCommandBuffer)0)
341 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
343 commandBuffers[ndx] = (vk::VkCommandBuffer)0;
346 commandBuffers.clear();
349 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
351 deUint32 queueFamilyIndex)
353 const vk::VkCommandPoolCreateInfo createInfo =
355 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
361 return vk::createCommandPool(vkd, device, &createInfo);
364 vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd,
366 vk::VkRenderPass renderPass,
367 vk::VkImageView imageView,
371 const vk::VkFramebufferCreateInfo createInfo =
373 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
385 return vk::createFramebuffer(vkd, device, &createInfo);
388 void initFramebuffers (const vk::DeviceInterface& vkd,
390 vk::VkRenderPass renderPass,
391 std::vector<vk::VkImageView> imageViews,
394 std::vector<vk::VkFramebuffer>& framebuffers)
396 DE_ASSERT(framebuffers.size() == imageViews.size());
398 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
399 framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown();
402 void deinitFramebuffers (const vk::DeviceInterface& vkd,
404 std::vector<vk::VkFramebuffer>& framebuffers)
406 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
408 if (framebuffers[ndx] != (vk::VkFramebuffer)0)
409 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
411 framebuffers[ndx] = (vk::VkFramebuffer)0;
414 framebuffers.clear();
417 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd,
422 const vk::VkImageViewCreateInfo createInfo =
424 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
429 vk::VK_IMAGE_VIEW_TYPE_2D,
431 vk::makeComponentMappingRGBA(),
433 vk::VK_IMAGE_ASPECT_COLOR_BIT,
441 return vk::createImageView(vkd, device, &createInfo, DE_NULL);
444 void initImageViews (const vk::DeviceInterface& vkd,
446 const std::vector<vk::VkImage>& images,
448 std::vector<vk::VkImageView>& imageViews)
450 DE_ASSERT(images.size() == imageViews.size());
452 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
453 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
456 void deinitImageViews (const vk::DeviceInterface& vkd,
458 std::vector<vk::VkImageView>& imageViews)
460 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
462 if (imageViews[ndx] != (vk::VkImageView)0)
463 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
465 imageViews[ndx] = (vk::VkImageView)0;
471 vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd,
475 const vk::VkAttachmentDescription attachments[] =
480 vk::VK_SAMPLE_COUNT_1_BIT,
482 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
483 vk::VK_ATTACHMENT_STORE_OP_STORE,
485 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
486 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
488 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
489 vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
492 const vk::VkAttachmentReference colorAttachmentRefs[] =
496 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
499 const vk::VkSubpassDescription subpasses[] =
503 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
507 DE_LENGTH_OF_ARRAY(colorAttachmentRefs),
517 const vk::VkRenderPassCreateInfo createInfo =
519 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
523 DE_LENGTH_OF_ARRAY(attachments),
526 DE_LENGTH_OF_ARRAY(subpasses),
533 return vk::createRenderPass(vkd, device, &createInfo);
536 vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd,
538 vk::VkRenderPass renderPass,
539 vk::VkPipelineLayout layout,
540 vk::VkShaderModule vertexShaderModule,
541 vk::VkShaderModule fragmentShaderModule,
545 const vk::VkSpecializationInfo shaderSpecialization =
552 const vk::VkPipelineShaderStageCreateInfo stages[] =
555 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
558 vk::VK_SHADER_STAGE_VERTEX_BIT,
561 &shaderSpecialization
564 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
567 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
568 fragmentShaderModule,
570 &shaderSpecialization
573 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
575 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
583 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
585 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
588 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
591 const vk::VkViewport viewports[] =
595 (float)width, (float)height,
599 const vk::VkRect2D scissors[] =
606 const vk::VkPipelineViewportStateCreateInfo viewportState =
608 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
612 DE_LENGTH_OF_ARRAY(viewports),
614 DE_LENGTH_OF_ARRAY(scissors),
617 const vk::VkPipelineRasterizationStateCreateInfo rasterizationState =
619 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
624 vk::VK_POLYGON_MODE_FILL,
625 vk::VK_CULL_MODE_NONE,
626 vk::VK_FRONT_FACE_CLOCKWISE,
633 const vk::VkSampleMask sampleMask = ~0u;
634 const vk::VkPipelineMultisampleStateCreateInfo multisampleState =
636 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
639 vk::VK_SAMPLE_COUNT_1_BIT,
646 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilState =
648 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
653 vk::VK_COMPARE_OP_ALWAYS,
657 vk::VK_STENCIL_OP_KEEP,
658 vk::VK_STENCIL_OP_KEEP,
659 vk::VK_STENCIL_OP_KEEP,
660 vk::VK_COMPARE_OP_ALWAYS,
666 vk::VK_STENCIL_OP_KEEP,
667 vk::VK_STENCIL_OP_KEEP,
668 vk::VK_STENCIL_OP_KEEP,
669 vk::VK_COMPARE_OP_ALWAYS,
677 const vk::VkPipelineColorBlendAttachmentState attachmentBlendState =
680 vk::VK_BLEND_FACTOR_ONE,
681 vk::VK_BLEND_FACTOR_ZERO,
683 vk::VK_BLEND_FACTOR_ONE,
684 vk::VK_BLEND_FACTOR_ZERO,
686 (vk::VK_COLOR_COMPONENT_R_BIT|
687 vk::VK_COLOR_COMPONENT_G_BIT|
688 vk::VK_COLOR_COMPONENT_B_BIT|
689 vk::VK_COLOR_COMPONENT_A_BIT),
691 const vk::VkPipelineColorBlendStateCreateInfo blendState =
693 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
697 vk::VK_LOGIC_OP_COPY,
699 &attachmentBlendState,
700 { 0.0f, 0.0f, 0.0f, 0.0f }
702 const vk::VkPipelineDynamicStateCreateInfo dynamicState =
704 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
711 const vk::VkGraphicsPipelineCreateInfo createInfo =
713 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
717 DE_LENGTH_OF_ARRAY(stages),
735 return vk::createGraphicsPipeline(vkd, device, DE_NULL, &createInfo);
738 vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd,
741 const vk::VkPushConstantRange pushConstants[] =
744 vk::VK_SHADER_STAGE_FRAGMENT_BIT,
749 const vk::VkPipelineLayoutCreateInfo createInfo =
751 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
758 DE_LENGTH_OF_ARRAY(pushConstants),
762 return vk::createPipelineLayout(vkd, device, &createInfo);
767 vk::wsi::Type wsiType;
768 bool useDisplayTiming;
769 vk::VkPresentModeKHR presentMode;
772 class DisplayTimingTestInstance : public TestInstance
775 DisplayTimingTestInstance (Context& context, const TestConfig& testConfig);
776 ~DisplayTimingTestInstance (void);
778 tcu::TestStatus iterate (void);
781 const bool m_useDisplayTiming;
782 const deUint32 m_quadCount;
783 const vk::PlatformInterface& m_vkp;
784 const Extensions m_instanceExtensions;
785 const vk::Unique<vk::VkInstance> m_instance;
786 const vk::InstanceDriver m_vki;
787 const vk::VkPhysicalDevice m_physicalDevice;
788 const de::UniquePtr<vk::wsi::Display> m_nativeDisplay;
789 const de::UniquePtr<vk::wsi::Window> m_nativeWindow;
790 const vk::Unique<vk::VkSurfaceKHR> m_surface;
792 const deUint32 m_queueFamilyIndex;
793 const Extensions m_deviceExtensions;
794 const vk::Unique<vk::VkDevice> m_device;
795 const vk::DeviceDriver m_vkd;
796 const vk::VkQueue m_queue;
798 const vk::Unique<vk::VkCommandPool> m_commandPool;
799 const vk::Unique<vk::VkShaderModule> m_vertexShaderModule;
800 const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule;
801 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout;
803 const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties;
804 const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats;
805 const vector<vk::VkPresentModeKHR> m_presentModes;
807 tcu::ResultCollector m_resultCollector;
809 vk::Move<vk::VkSwapchainKHR> m_swapchain;
810 std::vector<vk::VkImage> m_swapchainImages;
812 vk::Move<vk::VkRenderPass> m_renderPass;
813 vk::Move<vk::VkPipeline> m_pipeline;
815 std::vector<vk::VkImageView> m_swapchainImageViews;
816 std::vector<vk::VkFramebuffer> m_framebuffers;
817 std::vector<vk::VkCommandBuffer> m_commandBuffers;
818 std::vector<vk::VkSemaphore> m_acquireSemaphores;
819 std::vector<vk::VkSemaphore> m_renderSemaphores;
820 std::vector<vk::VkFence> m_fences;
822 vk::VkSemaphore m_freeAcquireSemaphore;
823 vk::VkSemaphore m_freeRenderSemaphore;
825 vk::VkSwapchainCreateInfoKHR m_swapchainConfig;
827 const size_t m_frameCount;
830 const size_t m_maxOutOfDateCount;
831 size_t m_outOfDateCount;
833 std::map<deUint32, deUint64> m_queuePresentTimes;
835 vk::VkRefreshCycleDurationGOOGLE m_rcDuration;
836 deUint64 m_refreshDurationMultiplier;
837 deUint64 m_targetIPD;
838 deUint64 m_prevDesiredPresentTime;
839 deUint32 m_nextPresentID;
840 deUint32 m_ignoreThruPresentID;
841 bool m_ExpectImage80Late;
843 void initSwapchainResources (void);
844 void deinitSwapchainResources (void);
848 vk::VkSwapchainCreateInfoKHR createSwapchainConfig (vk::VkSurfaceKHR surface,
849 deUint32 queueFamilyIndex,
850 const vk::VkSurfaceCapabilitiesKHR& properties,
851 const vector<vk::VkSurfaceFormatKHR>& formats,
852 const vector<vk::VkPresentModeKHR>& presentModes,
853 vk::VkPresentModeKHR presentMode)
855 const deUint32 imageLayers = 1u;
856 const vk::VkImageUsageFlags imageUsage = properties.supportedUsageFlags;
857 const vk::VkBool32 clipped = VK_FALSE;
859 const deUint32 imageWidth = (properties.currentExtent.width != 0xFFFFFFFFu)
860 ? properties.currentExtent.width
861 : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
862 const deUint32 imageHeight = (properties.currentExtent.height != 0xFFFFFFFFu)
863 ? properties.currentExtent.height
864 : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
865 const vk::VkExtent2D imageSize = { imageWidth, imageHeight };
868 size_t presentModeNdx;
870 for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++)
872 if (presentModes[presentModeNdx] == presentMode)
876 if (presentModeNdx == presentModes.size())
877 TCU_THROW(NotSupportedError, "Present mode not supported");
880 // Pick the first supported transform, alpha, and format:
881 vk::VkSurfaceTransformFlagsKHR transform;
882 for (transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
884 if ((properties.supportedTransforms & transform) != 0)
888 vk::VkCompositeAlphaFlagsKHR alpha;
889 for (alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
891 if ((alpha & properties.supportedCompositeAlpha) != 0)
896 const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform;
897 const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha;
898 const vk::VkFormat imageFormat = formats[0].format;
899 const vk::VkColorSpaceKHR imageColorSpace = formats[0].colorSpace;
900 const vk::VkSwapchainCreateInfoKHR createInfo =
902 vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
906 properties.minImageCount,
912 vk::VK_SHARING_MODE_EXCLUSIVE,
919 (vk::VkSwapchainKHR)0
926 DisplayTimingTestInstance::DisplayTimingTestInstance (Context& context, const TestConfig& testConfig)
927 : TestInstance (context)
928 , m_useDisplayTiming (testConfig.useDisplayTiming)
930 , m_vkp (context.getPlatformInterface())
931 , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL))
932 , m_instance (createInstanceWithWsi(m_vkp, m_instanceExtensions, testConfig.wsiType))
933 , m_vki (m_vkp, *m_instance)
934 , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine()))
935 , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType))
936 , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>()))
937 , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow))
939 , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface))
940 , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL))
941 , m_device (createDeviceWithWsi(m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useDisplayTiming))
942 , m_vkd (m_vki, *m_device)
943 , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
945 , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
946 , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
947 , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
948 , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device))
950 , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface))
951 , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface))
952 , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface))
954 , m_freeAcquireSemaphore ((vk::VkSemaphore)0)
955 , m_freeRenderSemaphore ((vk::VkSemaphore)0)
957 , m_swapchainConfig (createSwapchainConfig(*m_surface, m_queueFamilyIndex, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode))
959 , m_frameCount (60u * 5u)
962 , m_maxOutOfDateCount (20u)
963 , m_outOfDateCount (0u)
964 , m_ExpectImage80Late (false)
967 const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities");
968 m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage;
972 DisplayTimingTestInstance::~DisplayTimingTestInstance (void)
974 deinitSwapchainResources();
977 void DisplayTimingTestInstance::initSwapchainResources (void)
979 const size_t fenceCount = 6;
980 const deUint32 imageWidth = m_swapchainConfig.imageExtent.width;
981 const deUint32 imageHeight = m_swapchainConfig.imageExtent.height;
982 const vk::VkFormat imageFormat = m_swapchainConfig.imageFormat;
984 m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfig);
985 m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
987 m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat);
988 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight);
990 m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0);
991 m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0);
992 m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
993 m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0);
995 m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0);
996 m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0);
998 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
999 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1001 m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown();
1002 m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown();
1004 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
1005 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
1006 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1007 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
1009 initFences(m_vkd, *m_device, m_fences);
1011 if (m_useDisplayTiming)
1013 // This portion should do interesting bits
1014 m_queuePresentTimes = std::map<deUint32, deUint64>();
1016 m_vkd.getRefreshCycleDurationGOOGLE(*m_device, *m_swapchain, &m_rcDuration);
1018 m_refreshDurationMultiplier = 1u;
1019 m_targetIPD = m_rcDuration.refreshDuration;
1020 m_prevDesiredPresentTime = 0u;
1021 m_nextPresentID = 0u;
1022 m_ignoreThruPresentID = 0u;
1026 void DisplayTimingTestInstance::deinitSwapchainResources (void)
1028 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
1030 if (m_freeAcquireSemaphore != (vk::VkSemaphore)0)
1032 m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL);
1033 m_freeAcquireSemaphore = (vk::VkSemaphore)0;
1036 if (m_freeRenderSemaphore != (vk::VkSemaphore)0)
1038 m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL);
1039 m_freeRenderSemaphore = (vk::VkSemaphore)0;
1042 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
1043 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
1044 deinitFences(m_vkd, *m_device, m_fences);
1045 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
1046 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
1047 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
1049 m_swapchainImages.clear();
1051 m_swapchain = vk::Move<vk::VkSwapchainKHR>();
1052 m_renderPass = vk::Move<vk::VkRenderPass>();
1053 m_pipeline = vk::Move<vk::VkPipeline>();
1057 vector<vk::VkPastPresentationTimingGOOGLE> getPastPresentationTiming (const vk::DeviceInterface& vkd,
1058 vk::VkDevice device,
1059 vk::VkSwapchainKHR swapchain)
1061 vector<vk::VkPastPresentationTimingGOOGLE> pastPresentationTimings;
1062 deUint32 numPastPresentationTimings = 0;
1064 vkd.getPastPresentationTimingGOOGLE(device, swapchain, &numPastPresentationTimings, DE_NULL);
1066 pastPresentationTimings.resize(numPastPresentationTimings);
1068 if (numPastPresentationTimings > 0)
1069 vkd.getPastPresentationTimingGOOGLE(device, swapchain, &numPastPresentationTimings, &pastPresentationTimings[0]);
1071 return pastPresentationTimings;
1074 void DisplayTimingTestInstance::render (void)
1076 const deUint64 foreverNs = ~0x0ull;
1077 const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()];
1078 const deUint32 width = m_swapchainConfig.imageExtent.width;
1079 const deUint32 height = m_swapchainConfig.imageExtent.height;
1080 tcu::TestLog& log = m_context.getTestContext().getLog();
1082 // Throttle execution
1083 if (m_frameNdx >= m_fences.size())
1085 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
1086 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
1088 m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]);
1089 m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0;
1092 vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore;
1093 vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore;
1094 deUint32 imageIndex;
1096 // Acquire next image
1097 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, fence, &imageIndex));
1099 // Create command buffer
1100 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();
1102 // Obtain timing data from previous frames
1103 if (m_useDisplayTiming)
1105 const vector<vk::VkPastPresentationTimingGOOGLE> pastPresentationTimings (getPastPresentationTiming(m_vkd, *m_device, *m_swapchain));
1106 bool isEarly = false;
1107 bool isLate = false;
1109 for (size_t pastPresentationInfoNdx = 0 ; pastPresentationInfoNdx < pastPresentationTimings.size(); pastPresentationInfoNdx++)
1111 if (m_queuePresentTimes[pastPresentationTimings[pastPresentationInfoNdx].presentID] > pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime)
1113 m_resultCollector.fail("Image with PresentID " + de::toString(pastPresentationTimings[pastPresentationInfoNdx].presentID) + "was displayed before vkQueuePresentKHR was called.");
1115 if (!m_ignoreThruPresentID)
1117 // This is the first time that we've received an
1118 // actualPresentTime for this swapchain. In order to not
1119 // perceive these early frames as "late", we need to sync-up
1120 // our future desiredPresentTime's with the
1121 // actualPresentTime(s) that we're receiving now.
1122 const deInt64 multiple = m_nextPresentID - pastPresentationTimings.back().presentID;
1124 m_prevDesiredPresentTime = pastPresentationTimings.back().actualPresentTime + (multiple * m_targetIPD);
1125 m_ignoreThruPresentID = pastPresentationTimings[pastPresentationInfoNdx].presentID + 1;
1127 else if (pastPresentationTimings[pastPresentationInfoNdx].presentID > m_ignoreThruPresentID)
1129 if (pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime > (pastPresentationTimings[pastPresentationInfoNdx].desiredPresentTime + m_rcDuration.refreshDuration + MILLISECOND))
1131 const deUint64 actual = pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime;
1132 const deUint64 desired = pastPresentationTimings[pastPresentationInfoNdx].desiredPresentTime;
1133 const deUint64 rdur = m_rcDuration.refreshDuration;
1134 const deUint64 diff1 = actual - (desired + rdur);
1135 const deUint64 diff2 = actual - desired;
1137 log << TestLog::Message << "Image PresentID " << pastPresentationTimings[pastPresentationInfoNdx].presentID << " was " << diff1 << " nsec late." << TestLog::EndMessage;
1138 if (m_ExpectImage80Late && (pastPresentationTimings[pastPresentationInfoNdx].presentID == 80))
1140 if (diff1 > (SECOND / 2))
1141 log << TestLog::Message << "\tNote: Image PresentID 80 was expected to be late by approximately 1 second." << TestLog::EndMessage;
1143 m_resultCollector.fail("Image PresentID 80 was not late by approximately 1 second, as expected.");
1145 log << TestLog::Message << "\t\t actualPresentTime = " << actual << " nsec" << TestLog::EndMessage;
1146 log << TestLog::Message << "\t\t - desiredPresentTime= " << desired << " nsec" << TestLog::EndMessage;
1147 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1148 log << TestLog::Message << "\t\t diff = " << diff2 << " nsec" << TestLog::EndMessage;
1149 log << TestLog::Message << "\t\t - refreshDuration = " << rdur << " nsec" << TestLog::EndMessage;
1150 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1151 log << TestLog::Message << "\t\t diff = " << diff1 << " nsec" << TestLog::EndMessage;
1155 else if ((pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime > pastPresentationTimings[pastPresentationInfoNdx].earliestPresentTime) &&
1156 (pastPresentationTimings[pastPresentationInfoNdx].presentMargin > (2 * MILLISECOND)))
1158 const deUint64 actual = pastPresentationTimings[pastPresentationInfoNdx].actualPresentTime;
1159 const deUint64 earliest = pastPresentationTimings[pastPresentationInfoNdx].earliestPresentTime;
1160 const deUint64 diff = actual - earliest;
1162 log << TestLog::Message << "Image PresentID " << pastPresentationTimings[pastPresentationInfoNdx].presentID << " can be presented " << diff << " nsec earlier." << TestLog::EndMessage;
1163 log << TestLog::Message << "\t\t actualPresentTime = " << actual << " nsec" << TestLog::EndMessage;
1164 log << TestLog::Message << "\t\t -earliestPresentTime= " << earliest << " nsec" << TestLog::EndMessage;
1165 log << TestLog::Message << "\t\t =========================================" << TestLog::EndMessage;
1166 log << TestLog::Message << "\t\t diff = " << diff << " nsec" << TestLog::EndMessage;
1172 // Preference is given to late presents over early presents:
1175 // Demonstrate how to slow down the frame rate if a frame is late,
1176 // but don't go too slow (for test time reasons):
1177 if (++m_refreshDurationMultiplier > 2)
1178 m_refreshDurationMultiplier = 2;
1180 log << TestLog::Message << "Increasing multiplier." << TestLog::EndMessage;
1184 // Demonstrate how to speed up the frame rate if a frame is early,
1185 // but don't let the multiplier hit zero:
1186 if (--m_refreshDurationMultiplier == 0)
1187 m_refreshDurationMultiplier = 1;
1189 log << TestLog::Message << "Decreasing multiplier." << TestLog::EndMessage;
1191 m_targetIPD = m_rcDuration.refreshDuration * m_refreshDurationMultiplier;
1194 // Submit command buffer
1196 const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1197 const vk::VkSubmitInfo submitInfo =
1199 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1202 ¤tAcquireSemaphore,
1205 &m_commandBuffers[m_frameNdx % m_commandBuffers.size()],
1207 ¤tRenderSemaphore
1210 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, (vk::VkFence)0));
1214 if (m_useDisplayTiming)
1216 // This portion should do interesting bits
1218 // Initially, mirror reference to move things along
1219 vk::VkResult result;
1220 vk::VkPresentTimeGOOGLE presentTime =
1223 m_prevDesiredPresentTime
1225 // Record the current time, to record as the time of the vkQueuePresentKHR() call:
1226 const deUint64 curtimeNano = deGetMicroseconds() * 1000;
1227 m_queuePresentTimes[m_nextPresentID] = curtimeNano;
1229 deUint64 desiredPresentTime = 0u;
1230 if (m_prevDesiredPresentTime == 0)
1232 // This must be the first present for this swapchain. Find out the
1233 // current time, as the basis for desiredPresentTime:
1234 if (curtimeNano != 0)
1236 presentTime.desiredPresentTime = curtimeNano;
1237 presentTime.desiredPresentTime += (m_targetIPD / 2);
1241 // Since we didn't find out the current time, don't give a
1242 // desiredPresentTime:
1243 presentTime.desiredPresentTime = 0;
1248 desiredPresentTime = m_prevDesiredPresentTime + m_targetIPD;
1249 if (presentTime.presentID == 80)
1251 // Test if desiredPresentTime is 1 second earlier (i.e. before the previous image could have been presented)
1252 presentTime.desiredPresentTime -= SECOND;
1253 m_ExpectImage80Late = true;
1256 m_prevDesiredPresentTime = desiredPresentTime;
1258 const vk::VkPresentTimesInfoGOOGLE presentTimesInfo =
1260 vk::VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE,
1265 const vk::VkPresentInfoKHR presentInfo =
1267 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1270 ¤tRenderSemaphore,
1277 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1282 vk::VkResult result;
1283 const vk::VkPresentInfoKHR presentInfo =
1285 vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
1288 ¤tRenderSemaphore,
1295 VK_CHECK(m_vkd.queuePresentKHR(m_queue, &presentInfo));
1300 m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex];
1301 m_acquireSemaphores[imageIndex] = currentAcquireSemaphore;
1303 m_freeRenderSemaphore = m_renderSemaphores[imageIndex];
1304 m_renderSemaphores[imageIndex] = currentRenderSemaphore;
1308 tcu::TestStatus DisplayTimingTestInstance::iterate (void)
1310 // Initialize swapchain specific resources
1314 if (m_frameNdx == 0)
1316 if (m_outOfDateCount == 0)
1317 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfig << tcu::TestLog::EndMessage;
1319 initSwapchainResources();
1324 catch (const vk::Error& error)
1326 if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR)
1328 if (m_outOfDateCount < m_maxOutOfDateCount)
1330 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage;
1331 deinitSwapchainResources();
1335 return tcu::TestStatus::incomplete();
1339 m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
1340 m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount));
1345 m_resultCollector.fail(error.what());
1348 deinitSwapchainResources();
1350 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1355 if (m_frameNdx >= m_frameCount)
1357 deinitSwapchainResources();
1359 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1362 return tcu::TestStatus::incomplete();
1367 static void init (vk::SourceCollections& dst, TestConfig)
1369 dst.glslSources.add("quad-vert") << glu::VertexSource(
1371 "out gl_PerVertex {\n"
1372 "\tvec4 gl_Position;\n"
1375 "void main (void) {\n"
1376 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1377 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1379 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1381 "layout(location = 0) out highp vec4 o_color;\n"
1382 "layout(push_constant) uniform PushConstant {\n"
1383 "\thighp uint frameNdx;\n"
1384 "} pushConstants;\n"
1385 "void main (void)\n"
1387 "\thighp uint frameNdx = pushConstants.frameNdx;\n"
1388 "\thighp uint x = frameNdx + uint(gl_FragCoord.x);\n"
1389 "\thighp uint y = frameNdx + uint(gl_FragCoord.y);\n"
1390 "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n"
1391 "\t + 64u * bitfieldExtract(y, 1, 1)\n"
1392 "\t + 32u * bitfieldExtract(x, 3, 1);\n"
1393 "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n"
1394 "\t + 64u * bitfieldExtract(x, 2, 1)\n"
1395 "\t + 32u * bitfieldExtract(y, 3, 1);\n"
1396 "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n"
1397 "\t + 64u * bitfieldExtract(y, 2, 1)\n"
1398 "\t + 32u * bitfieldExtract(x, 4, 1);\n"
1399 "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n"
1406 void createDisplayTimingTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1410 vk::VkPresentModeKHR mode;
1414 { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" },
1415 { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" },
1416 { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" },
1417 { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" },
1420 for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++)
1422 de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name));
1424 for (size_t ref = 0; ref < 2; ref++)
1426 const bool isReference = (ref == 0);
1427 const char* const name = isReference ? "reference" : "display_timing";
1430 config.wsiType = wsiType;
1431 config.useDisplayTiming = !isReference;
1432 config.presentMode = presentModes[presentModeNdx].mode;
1434 presentModeGroup->addChild(new vkt::InstanceFactory1<DisplayTimingTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config));
1437 testGroup->addChild(presentModeGroup.release());