1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \brief VK_EXT_display_control tests
21 *//*--------------------------------------------------------------------*/
22
23 #include "vkRefUtil.hpp"
24 #include "vkWsiPlatform.hpp"
25 #include "vkWsiUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkDeviceUtil.hpp"
28 #include "vkPlatform.hpp"
29 #include "vkTypeUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkWsiUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35
36 #include "vktWsiDisplayControlTests.hpp"
37 #include "vktTestCaseUtil.hpp"
38 #include "vktTestGroupUtil.hpp"
39 #include "vktCustomInstancesDevices.hpp"
40
41 #include "tcuPlatform.hpp"
42 #include "tcuResultCollector.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuCommandLine.hpp"
45
46 #include "deClock.h"
47
48 #include <vector>
49 #include <string>
50
51 using std::string;
52 using std::vector;
53
54 using tcu::Maybe;
55 using tcu::TestLog;
56 using tcu::UVec2;
57
58 namespace vkt
59 {
60 namespace wsi
61 {
62 namespace
63 {
64
65 using namespace vk;
66 using namespace vk::wsi;
67
68 typedef vector<VkExtensionProperties> Extensions;
69
createInstance(Context & context)70 CustomInstance createInstance(Context &context)
71 {
72 vector<string> extensions = {
73 "VK_KHR_surface",
74 "VK_KHR_display",
75 "VK_EXT_display_surface_counter",
76 };
77
78 return vkt::createCustomInstanceWithExtensions(context, extensions);
79 }
80
chooseQueueFamilyIndex(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)81 uint32_t chooseQueueFamilyIndex(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
82 {
83 uint32_t numTotalFamilyIndices;
84 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numTotalFamilyIndices, DE_NULL);
85
86 for (uint32_t queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
87 {
88 if (wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) == VK_TRUE)
89 return queueFamilyNdx;
90 }
91
92 TCU_THROW(NotSupportedError, "Device doesn't support presentation");
93 return 0;
94 }
95
createTestDevice(const Context & context,const PlatformInterface & vkp,const VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const uint32_t queueFamilyIndex,const VkAllocationCallbacks * pAllocator=DE_NULL)96 Move<VkDevice> createTestDevice(const Context &context, const PlatformInterface &vkp, const VkInstance instance,
97 const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
98 const uint32_t queueFamilyIndex, const VkAllocationCallbacks *pAllocator = DE_NULL)
99 {
100 const float queuePriorities[] = {1.0f};
101 bool displayAvailable = true;
102 bool validationEnabled = context.getTestContext().getCommandLine().isValidationEnabled();
103 const vk::Platform &platform = context.getTestContext().getPlatform().getVulkanPlatform();
104
105 const VkDeviceQueueCreateInfo queueInfos[] = {{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, DE_NULL,
106 (VkDeviceQueueCreateFlags)0, queueFamilyIndex,
107 DE_LENGTH_OF_ARRAY(queuePriorities), &queuePriorities[0]}};
108
109 VkPhysicalDeviceFeatures features;
110 deMemset(&features, 0, sizeof(features));
111
112 const char *extensions[] = {"VK_KHR_swapchain", "VK_EXT_display_control"};
113
114 const VkDeviceCreateInfo deviceParams = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
115 DE_NULL,
116 (VkDeviceCreateFlags)0,
117 DE_LENGTH_OF_ARRAY(queueInfos),
118 &queueInfos[0],
119 0u,
120 DE_NULL,
121 DE_LENGTH_OF_ARRAY(extensions),
122 &extensions[0],
123 &features};
124
125 for (auto ext : extensions)
126 {
127 if (!context.isDeviceFunctionalitySupported(ext))
128 TCU_THROW(NotSupportedError, (string(ext) + " is not supported").c_str());
129 }
130
131 for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
132 {
133 vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
134 if (platform.hasDisplay(wsiType))
135 {
136 displayAvailable = false;
137 break;
138 }
139 }
140
141 if (!displayAvailable)
142 TCU_THROW(NotSupportedError, "Display is unavailable as windowing system has access");
143
144 return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
145 }
146
getDisplayAndDisplayPlane(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,uint32_t * pPlaneIndex)147 VkDisplayKHR getDisplayAndDisplayPlane(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
148 uint32_t *pPlaneIndex)
149 {
150 uint32_t countDisplays = 0;
151 VkResult result = vki.getPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &countDisplays, DE_NULL);
152 if (result != VK_SUCCESS)
153 TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceDisplayPropertiesKHR failed");
154
155 if (countDisplays == 0)
156 TCU_THROW(NotSupportedError, "No displays available");
157
158 uint32_t countDisplayPlanes = 0;
159 result = vki.getPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &countDisplayPlanes, DE_NULL);
160 if (result != VK_SUCCESS || !countDisplayPlanes)
161 TCU_FAIL("GetPhysicalDeviceDisplayPlanePropertiesKHR failed");
162
163 for (uint32_t p = 0; p < countDisplayPlanes; p++)
164 {
165 uint32_t count = 0u;
166 result = vki.getDisplayPlaneSupportedDisplaysKHR(physicalDevice, p, &count, DE_NULL);
167 if (result != VK_SUCCESS)
168 TCU_FAIL("GetDisplayPlaneSupportedDisplaysKHR failed");
169
170 // No displays that can make use of this plane are available.
171 if (!count)
172 continue;
173
174 std::vector<VkDisplayKHR> displays(count);
175 result = vki.getDisplayPlaneSupportedDisplaysKHR(physicalDevice, p, &count, &displays[0]);
176 if (result != VK_SUCCESS)
177 TCU_FAIL("GetDisplayPlaneSupportedDisplaysKHR failed");
178
179 // return first plane with an available display
180 *pPlaneIndex = p;
181 return displays[0];
182 }
183
184 TCU_FAIL("No intersection between displays and display planes");
185
186 // Unreachable.
187 return DE_NULL;
188 }
189
createSurface(const InstanceInterface & vki,VkInstance instance,VkPhysicalDevice physicalDevice,VkDisplayKHR display,uint32_t planeIndex)190 VkSurfaceKHR createSurface(const InstanceInterface &vki, VkInstance instance, VkPhysicalDevice physicalDevice,
191 VkDisplayKHR display, uint32_t planeIndex)
192 {
193 // get number of display modes for this display
194 uint32_t displayModesCount = 0;
195 VkResult result = vki.getDisplayModePropertiesKHR(physicalDevice, display, &displayModesCount, DE_NULL);
196 if (result != VK_SUCCESS)
197 TCU_FAIL("GetDisplayModePropertiesKHR failed");
198
199 // get first display mode of this display
200 std::vector<vk::VkDisplayModePropertiesKHR> modeProperties(displayModesCount);
201 result = vki.getDisplayModePropertiesKHR(physicalDevice, display, &displayModesCount, &modeProperties[0]);
202 if (result != VK_SUCCESS)
203 TCU_FAIL("GetDisplayModePropertiesKHR failed");
204 VkDisplayModeKHR displayMode = modeProperties[0].displayMode;
205
206 // get capabielieties for first plane of this display
207 VkDisplayPlaneCapabilitiesKHR planeCapabilities;
208 result = vki.getDisplayPlaneCapabilitiesKHR(physicalDevice, displayMode, planeIndex, &planeCapabilities);
209 if (result != VK_SUCCESS)
210 TCU_FAIL("GetDisplayPlaneCapabilitiesKHR failed");
211
212 // get plane properties count
213 uint32_t planePropertiesCount = 0;
214 result = vki.getPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &planePropertiesCount, DE_NULL);
215 if (result != VK_SUCCESS || !planePropertiesCount)
216 TCU_FAIL("GetPhysicalDeviceDisplayPlanePropertiesKHR failed");
217
218 // get plane properties
219 std::vector<VkDisplayPlanePropertiesKHR> planeProperties(planePropertiesCount);
220 result = vki.getPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &planePropertiesCount, &planeProperties[0]);
221 if (result != VK_SUCCESS)
222 TCU_FAIL("GetPhysicalDeviceDisplayPlanePropertiesKHR failed");
223
224 // define surface create info
225 const VkDisplaySurfaceCreateInfoKHR createInfo = {
226 VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, // VkStructureType sType
227 DE_NULL, // const void* pNext
228 0, // VkDisplaySurfaceCreateFlagsKHR flags
229 displayMode, // VkDisplayModeKHR displayMode
230 planeIndex, // uint32_t planeIndex
231 planeProperties[planeIndex].currentStackIndex, // uint32_t planeStackIndex
232 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, // VkSurfaceTransformFlagBitsKHR transform
233 1.0f, // float globalAlpha
234 VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, // VkDisplayPlaneAlphaFlagBitsKHR alphaMode
235 { // VkExtent2D imageExtent
236 planeCapabilities.minDstExtent.width, planeCapabilities.minDstExtent.height}};
237
238 VkSurfaceKHR surface = DE_NULL;
239 result = vki.createDisplayPlaneSurfaceKHR(instance, &createInfo, DE_NULL, &surface);
240 if (result != VK_SUCCESS)
241 TCU_FAIL("CreateDisplayPlaneSurfaceKHR failed");
242
243 if (surface == DE_NULL)
244 TCU_FAIL("Invalid surface handle returned");
245
246 return surface;
247 }
248
initSemaphores(const DeviceInterface & vkd,VkDevice device,std::vector<VkSemaphore> & semaphores)249 void initSemaphores(const DeviceInterface &vkd, VkDevice device, std::vector<VkSemaphore> &semaphores)
250 {
251 for (VkSemaphore &semaphore : semaphores)
252 semaphore = createSemaphore(vkd, device).disown();
253 }
254
deinitSemaphores(const DeviceInterface & vkd,VkDevice device,std::vector<VkSemaphore> & semaphores)255 void deinitSemaphores(const DeviceInterface &vkd, VkDevice device, std::vector<VkSemaphore> &semaphores)
256 {
257 for (VkSemaphore &semaphore : semaphores)
258 {
259 if (semaphore == (VkSemaphore)0)
260 continue;
261
262 vkd.destroySemaphore(device, semaphore, DE_NULL);
263 semaphore = (VkSemaphore)0;
264 }
265
266 semaphores.clear();
267 }
268
initFences(const DeviceInterface & vkd,VkDevice device,std::vector<VkFence> & fences)269 void initFences(const DeviceInterface &vkd, VkDevice device, std::vector<VkFence> &fences)
270 {
271 for (VkFence &fence : fences)
272 fence = createFence(vkd, device).disown();
273 }
274
deinitFences(const DeviceInterface & vkd,VkDevice device,std::vector<VkFence> & fences)275 void deinitFences(const DeviceInterface &vkd, VkDevice device, std::vector<VkFence> &fences)
276 {
277 for (VkFence &fence : fences)
278 {
279 if (fence == (VkFence)0)
280 continue;
281
282 vkd.destroyFence(device, fence, DE_NULL);
283 fence = (VkFence)0;
284 }
285
286 fences.clear();
287 }
288
createCommandBuffer(const DeviceInterface & vkd,VkDevice device,VkCommandPool commandPool,VkRenderPass renderPass,VkImage image,VkFramebuffer framebuffer,VkPipeline pipeline,uint32_t imageWidth,uint32_t imageHeight)289 Move<VkCommandBuffer> createCommandBuffer(const DeviceInterface &vkd, VkDevice device, VkCommandPool commandPool,
290 VkRenderPass renderPass, VkImage image, VkFramebuffer framebuffer,
291 VkPipeline pipeline, uint32_t imageWidth, uint32_t imageHeight)
292 {
293 const VkCommandBufferAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, DE_NULL,
294
295 commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1};
296
297 VkImageMemoryBarrier imageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
298 DE_NULL, // const void* pNext;
299 0u, // VkAccessFlags srcAccessMask;
300 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
301 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
302 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
303 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
304 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
305 image, // VkImage image;
306 {
307 // VkImageSubresourceRange subresourceRange;
308 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
309 0u, // uint32_t baseMipLevel;
310 1u, // uint32_t mipLevels;
311 0u, // uint32_t baseArraySlice;
312 1u // uint32_t arraySize;
313 }};
314
315 Move<VkCommandBuffer> commandBuffer(allocateCommandBuffer(vkd, device, &allocateInfo));
316 beginCommandBuffer(vkd, *commandBuffer, 0u);
317
318 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
319 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0,
320 (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1,
321 &imageBarrier);
322
323 beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, makeRect2D(0, 0, imageWidth, imageHeight),
324 tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f));
325
326 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
327 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
328
329 endRenderPass(vkd, *commandBuffer);
330
331 endCommandBuffer(vkd, *commandBuffer);
332 return commandBuffer;
333 }
334
deinitCommandBuffers(const DeviceInterface & vkd,VkDevice device,VkCommandPool commandPool,std::vector<VkCommandBuffer> & commandBuffers)335 void deinitCommandBuffers(const DeviceInterface &vkd, VkDevice device, VkCommandPool commandPool,
336 std::vector<VkCommandBuffer> &commandBuffers)
337 {
338 for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++)
339 {
340 if (commandBuffers[ndx] != (VkCommandBuffer)0)
341 vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]);
342
343 commandBuffers[ndx] = (VkCommandBuffer)0;
344 }
345
346 commandBuffers.clear();
347 }
348
createCommandPool(const DeviceInterface & vkd,VkDevice device,uint32_t queueFamilyIndex)349 Move<VkCommandPool> createCommandPool(const DeviceInterface &vkd, VkDevice device, uint32_t queueFamilyIndex)
350 {
351 const VkCommandPoolCreateInfo createInfo = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, DE_NULL, 0u,
352 queueFamilyIndex};
353
354 return createCommandPool(vkd, device, &createInfo);
355 }
356
initFramebuffers(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,std::vector<VkImageView> imageViews,uint32_t width,uint32_t height,std::vector<VkFramebuffer> & framebuffers)357 void initFramebuffers(const DeviceInterface &vkd, VkDevice device, VkRenderPass renderPass,
358 std::vector<VkImageView> imageViews, uint32_t width, uint32_t height,
359 std::vector<VkFramebuffer> &framebuffers)
360 {
361 DE_ASSERT(framebuffers.size() == imageViews.size());
362
363 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
364 {
365 const VkFramebufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
366 DE_NULL,
367
368 0u,
369 renderPass,
370 1u,
371 &imageViews[ndx],
372 width,
373 height,
374 1u};
375
376 framebuffers[ndx] = createFramebuffer(vkd, device, &createInfo).disown();
377 }
378 }
379
deinitFramebuffers(const DeviceInterface & vkd,VkDevice device,std::vector<VkFramebuffer> & framebuffers)380 void deinitFramebuffers(const DeviceInterface &vkd, VkDevice device, std::vector<VkFramebuffer> &framebuffers)
381 {
382 for (size_t ndx = 0; ndx < framebuffers.size(); ndx++)
383 {
384 if (framebuffers[ndx] != (VkFramebuffer)0)
385 vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL);
386
387 framebuffers[ndx] = (VkFramebuffer)0;
388 }
389
390 framebuffers.clear();
391 }
392
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format)393 Move<VkImageView> createImageView(const DeviceInterface &vkd, VkDevice device, VkImage image, VkFormat format)
394 {
395 const VkImageViewCreateInfo createInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
396 DE_NULL,
397
398 0u,
399 image,
400 VK_IMAGE_VIEW_TYPE_2D,
401 format,
402 makeComponentMappingRGBA(),
403 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}};
404
405 return createImageView(vkd, device, &createInfo, DE_NULL);
406 }
407
initImageViews(const DeviceInterface & vkd,VkDevice device,const std::vector<VkImage> & images,VkFormat format,std::vector<VkImageView> & imageViews)408 void initImageViews(const DeviceInterface &vkd, VkDevice device, const std::vector<VkImage> &images, VkFormat format,
409 std::vector<VkImageView> &imageViews)
410 {
411 DE_ASSERT(images.size() == imageViews.size());
412
413 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
414 imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown();
415 }
416
deinitImageViews(const DeviceInterface & vkd,VkDevice device,std::vector<VkImageView> & imageViews)417 void deinitImageViews(const DeviceInterface &vkd, VkDevice device, std::vector<VkImageView> &imageViews)
418 {
419 for (size_t ndx = 0; ndx < imageViews.size(); ndx++)
420 {
421 if (imageViews[ndx] != (VkImageView)0)
422 vkd.destroyImageView(device, imageViews[ndx], DE_NULL);
423
424 imageViews[ndx] = (VkImageView)0;
425 }
426
427 imageViews.clear();
428 }
429
createPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkPipelineLayout layout,VkShaderModule vertexShaderModule,VkShaderModule fragmentShaderModule,uint32_t width,uint32_t height)430 Move<VkPipeline> createPipeline(const DeviceInterface &vkd, VkDevice device, VkRenderPass renderPass,
431 VkPipelineLayout layout, VkShaderModule vertexShaderModule,
432 VkShaderModule fragmentShaderModule, uint32_t width, uint32_t height)
433 {
434 const VkPipelineVertexInputStateCreateInfo vertexInputState = {
435 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, DE_NULL, 0u, 0u, DE_NULL, 0u, DE_NULL};
436 const std::vector<VkViewport> viewports(1, makeViewport(tcu::UVec2(width, height)));
437 const std::vector<VkRect2D> scissors(1, makeRect2D(tcu::UVec2(width, height)));
438
439 return makeGraphicsPipeline(
440 vkd, // const DeviceInterface& vk
441 device, // const VkDevice device
442 layout, // const VkPipelineLayout pipelineLayout
443 vertexShaderModule, // const VkShaderModule vertexShaderModule
444 DE_NULL, // const VkShaderModule tessellationControlShaderModule
445 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
446 DE_NULL, // const VkShaderModule geometryShaderModule
447 fragmentShaderModule, // const VkShaderModule fragmentShaderModule
448 renderPass, // const VkRenderPass renderPass
449 viewports, // const std::vector<VkViewport>& viewports
450 scissors, // const std::vector<VkRect2D>& scissors
451 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
452 0u, // const uint32_t subpass
453 0u, // const uint32_t patchControlPoints
454 &vertexInputState); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
455 }
456
createPipelineLayout(const DeviceInterface & vkd,VkDevice device)457 Move<VkPipelineLayout> createPipelineLayout(const DeviceInterface &vkd, VkDevice device)
458 {
459 const VkPipelineLayoutCreateInfo createInfo = {
460 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, DE_NULL, 0u, 0u, DE_NULL, 0u, DE_NULL,
461 };
462
463 return createPipelineLayout(vkd, device, &createInfo);
464 }
465
createSwapchainCounterConfig()466 VkSwapchainCounterCreateInfoEXT createSwapchainCounterConfig()
467 {
468 const VkSwapchainCounterCreateInfoEXT swapchainCounterConfig = {VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT,
469 DE_NULL, VK_SURFACE_COUNTER_VBLANK_EXT};
470 return swapchainCounterConfig;
471 }
472
createSwapchainConfig(VkSurfaceKHR surface,uint32_t queueFamilyIndex,const VkSurfaceCapabilities2EXT & properties,const vector<VkSurfaceFormatKHR> & formats,const vector<VkPresentModeKHR> & presentModes,VkPresentModeKHR presentMode,VkSwapchainCounterCreateInfoEXT * swapchainCounterInfo)473 VkSwapchainCreateInfoKHR createSwapchainConfig(VkSurfaceKHR surface, uint32_t queueFamilyIndex,
474 const VkSurfaceCapabilities2EXT &properties,
475 const vector<VkSurfaceFormatKHR> &formats,
476 const vector<VkPresentModeKHR> &presentModes,
477 VkPresentModeKHR presentMode,
478 VkSwapchainCounterCreateInfoEXT *swapchainCounterInfo)
479 {
480 if ((properties.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) == 0)
481 TCU_THROW(NotSupportedError, "vblank counter not supported");
482
483 const uint32_t imageLayers = 1u;
484 const VkImageUsageFlags imageUsage = properties.supportedUsageFlags;
485 const VkBool32 clipped = VK_FALSE;
486
487 const uint32_t imageWidth =
488 (properties.currentExtent.width != 0xFFFFFFFFu) ?
489 properties.currentExtent.width :
490 de::min(1024u, properties.minImageExtent.width +
491 ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2));
492 const uint32_t imageHeight =
493 (properties.currentExtent.height != 0xFFFFFFFFu) ?
494 properties.currentExtent.height :
495 de::min(1024u, properties.minImageExtent.height +
496 ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2));
497 const VkExtent2D imageSize = {imageWidth, imageHeight};
498
499 if (std::find(presentModes.begin(), presentModes.end(), presentMode) == presentModes.end())
500 TCU_THROW(NotSupportedError, "Present mode not supported");
501
502 // Pick the first supported transform, alpha, and format:
503 VkSurfaceTransformFlagsKHR transform;
504 for (transform = 1u; transform <= properties.supportedTransforms; transform = transform << 1u)
505 {
506 if ((properties.supportedTransforms & transform) != 0)
507 break;
508 }
509
510 VkCompositeAlphaFlagsKHR alpha;
511 for (alpha = 1u; alpha <= properties.supportedCompositeAlpha; alpha = alpha << 1u)
512 {
513 if ((alpha & properties.supportedCompositeAlpha) != 0)
514 break;
515 }
516
517 {
518 const VkSurfaceTransformFlagBitsKHR preTransform = (VkSurfaceTransformFlagBitsKHR)transform;
519 const VkCompositeAlphaFlagBitsKHR compositeAlpha = (VkCompositeAlphaFlagBitsKHR)alpha;
520 const VkFormat imageFormat = formats[0].format;
521 const VkColorSpaceKHR imageColorSpace = formats[0].colorSpace;
522 const VkSwapchainCreateInfoKHR createInfo = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
523 swapchainCounterInfo,
524 0u,
525 surface,
526 properties.minImageCount,
527 imageFormat,
528 imageColorSpace,
529 imageSize,
530 imageLayers,
531 imageUsage,
532 VK_SHARING_MODE_EXCLUSIVE,
533 1u,
534 &queueFamilyIndex,
535 preTransform,
536 compositeAlpha,
537 presentMode,
538 clipped,
539 (VkSwapchainKHR)0};
540
541 return createInfo;
542 }
543 }
544
545 class SwapchainCounterTestInstance : public TestInstance
546 {
547 public:
548 SwapchainCounterTestInstance(Context &context);
549 ~SwapchainCounterTestInstance(void);
550
551 tcu::TestStatus iterate(void);
552
553 private:
554 void initSwapchainResources(void);
555 void deinitSwapchainResources(void);
556 void render(void);
557
558 private:
559 const PlatformInterface &m_vkp;
560 const CustomInstance m_instance;
561 const InstanceDriver &m_vki;
562 const VkPhysicalDevice m_physicalDevice;
563 uint32_t m_planeIndex;
564 const VkDisplayKHR m_display;
565 const VkSurfaceKHR m_surface;
566
567 const uint32_t m_queueFamilyIndex;
568 const Unique<VkDevice> m_device;
569 const DeviceDriver m_vkd;
570 const VkQueue m_queue;
571
572 const Unique<VkCommandPool> m_commandPool;
573 const Unique<VkShaderModule> m_vertexShaderModule;
574 const Unique<VkShaderModule> m_fragmentShaderModule;
575 const Unique<VkPipelineLayout> m_pipelineLayout;
576
577 const VkSurfaceCapabilities2EXT m_surfaceProperties;
578 const vector<VkSurfaceFormatKHR> m_surfaceFormats;
579 const vector<VkPresentModeKHR> m_presentModes;
580
581 tcu::ResultCollector m_resultCollector;
582
583 Move<VkSwapchainKHR> m_swapchain;
584 std::vector<VkImage> m_swapchainImages;
585
586 Move<VkRenderPass> m_renderPass;
587 Move<VkPipeline> m_pipeline;
588
589 std::vector<VkImageView> m_swapchainImageViews;
590 std::vector<VkFramebuffer> m_framebuffers;
591 std::vector<VkCommandBuffer> m_commandBuffers;
592 std::vector<VkSemaphore> m_acquireSemaphores;
593 std::vector<VkSemaphore> m_renderSemaphores;
594 std::vector<VkFence> m_fences;
595
596 VkSwapchainCounterCreateInfoEXT m_swapchainCounterConfig;
597 VkSwapchainCreateInfoKHR m_swapchainConfig;
598
599 const size_t m_frameCount;
600 size_t m_frameNdx;
601
602 const size_t m_maxOutOfDateCount;
603 size_t m_outOfDateCount;
604 };
605
SwapchainCounterTestInstance(Context & context)606 SwapchainCounterTestInstance::SwapchainCounterTestInstance(Context &context)
607 : TestInstance(context)
608 , m_vkp(context.getPlatformInterface())
609 , m_instance(createInstance(context))
610 , m_vki(m_instance.getDriver())
611 , m_physicalDevice(chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
612 , m_planeIndex(0)
613 , m_display(getDisplayAndDisplayPlane(m_vki, m_physicalDevice, &m_planeIndex))
614 , m_surface(createSurface(m_vki, m_instance, m_physicalDevice, m_display, m_planeIndex))
615
616 , m_queueFamilyIndex(chooseQueueFamilyIndex(m_vki, m_physicalDevice, m_surface))
617 , m_device(createTestDevice(context, m_vkp, m_instance, m_vki, m_physicalDevice, m_queueFamilyIndex))
618 , m_vkd(m_vkp, m_instance, *m_device, context.getUsedApiVersion(), context.getTestContext().getCommandLine())
619 , m_queue(getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u))
620
621 , m_commandPool(createCommandPool(m_vkd, *m_device, m_queueFamilyIndex))
622 , m_vertexShaderModule(createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u))
623 , m_fragmentShaderModule(createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u))
624 , m_pipelineLayout(createPipelineLayout(m_vkd, *m_device))
625
626 , m_surfaceProperties(wsi::getPhysicalDeviceSurfaceCapabilities2EXT(m_vki, m_physicalDevice, m_surface))
627 , m_surfaceFormats(wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, m_surface))
628 , m_presentModes(wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, m_surface))
629
630 , m_swapchainCounterConfig(createSwapchainCounterConfig())
631 , m_swapchainConfig(createSwapchainConfig(m_surface, m_queueFamilyIndex, m_surfaceProperties, m_surfaceFormats,
632 m_presentModes, VK_PRESENT_MODE_FIFO_KHR, &m_swapchainCounterConfig))
633
634 , m_frameCount(20u)
635 , m_frameNdx(0u)
636
637 , m_maxOutOfDateCount(10u)
638 , m_outOfDateCount(0u)
639 {
640 }
641
~SwapchainCounterTestInstance(void)642 SwapchainCounterTestInstance::~SwapchainCounterTestInstance(void)
643 {
644 deinitSwapchainResources();
645
646 m_vki.destroySurfaceKHR(m_instance, m_surface, DE_NULL);
647 }
648
initSwapchainResources(void)649 void SwapchainCounterTestInstance::initSwapchainResources(void)
650 {
651 const uint32_t imageWidth = m_swapchainConfig.imageExtent.width;
652 const uint32_t imageHeight = m_swapchainConfig.imageExtent.height;
653 const VkFormat imageFormat = m_swapchainConfig.imageFormat;
654
655 m_swapchain = createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfig);
656 m_swapchainImages = wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain);
657
658 m_renderPass = makeRenderPass(m_vkd, *m_device, imageFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD,
659 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
660 m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule,
661 *m_fragmentShaderModule, imageWidth, imageHeight);
662
663 const size_t swapchainImagesCount = m_swapchainImages.size();
664 const size_t fenceCount = swapchainImagesCount * 2;
665
666 m_swapchainImageViews = std::vector<VkImageView>(swapchainImagesCount, (VkImageView)0);
667 m_framebuffers = std::vector<VkFramebuffer>(swapchainImagesCount, (VkFramebuffer)0);
668 m_acquireSemaphores = std::vector<VkSemaphore>(swapchainImagesCount + 1, (VkSemaphore)0);
669 m_renderSemaphores = std::vector<VkSemaphore>(swapchainImagesCount + 1, (VkSemaphore)0);
670
671 m_fences = std::vector<VkFence>(fenceCount, (VkFence)0);
672 m_commandBuffers = std::vector<VkCommandBuffer>(fenceCount, (VkCommandBuffer)0);
673
674 initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews);
675 initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers);
676 initSemaphores(m_vkd, *m_device, m_acquireSemaphores);
677 initSemaphores(m_vkd, *m_device, m_renderSemaphores);
678
679 initFences(m_vkd, *m_device, m_fences);
680 }
681
deinitSwapchainResources(void)682 void SwapchainCounterTestInstance::deinitSwapchainResources(void)
683 {
684 VK_CHECK(m_vkd.queueWaitIdle(m_queue));
685
686 deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores);
687 deinitSemaphores(m_vkd, *m_device, m_renderSemaphores);
688 deinitFences(m_vkd, *m_device, m_fences);
689 deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers);
690 deinitFramebuffers(m_vkd, *m_device, m_framebuffers);
691 deinitImageViews(m_vkd, *m_device, m_swapchainImageViews);
692
693 m_swapchainImages.clear();
694
695 m_swapchain = Move<VkSwapchainKHR>();
696 m_renderPass = Move<VkRenderPass>();
697 m_pipeline = Move<VkPipeline>();
698 }
699
render(void)700 void SwapchainCounterTestInstance::render(void)
701 {
702 const uint64_t foreverNs = ~0x0ull;
703 VkCommandBuffer &commandBuffer = m_commandBuffers[m_frameNdx % m_commandBuffers.size()];
704 const VkFence fence = m_fences[m_frameNdx % m_fences.size()];
705 const uint32_t width = m_swapchainConfig.imageExtent.width;
706 const uint32_t height = m_swapchainConfig.imageExtent.height;
707
708 if (m_frameNdx >= m_fences.size())
709 VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs));
710 VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence));
711
712 VkSemaphore currentAcquireSemaphore = m_acquireSemaphores[m_frameNdx % m_acquireSemaphores.size()];
713 VkSemaphore currentRenderSemaphore = m_renderSemaphores[m_frameNdx % m_renderSemaphores.size()];
714
715 // Acquire next image
716 uint32_t imageIndex;
717 VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (VkFence)0,
718 &imageIndex));
719
720 // Create command buffer
721 commandBuffer = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_renderPass, m_swapchainImages[imageIndex],
722 m_framebuffers[imageIndex], *m_pipeline, width, height)
723 .disown();
724
725 // Submit command buffer
726 {
727 const VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
728 const VkSubmitInfo submitInfo = {
729 VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 1u, ¤tAcquireSemaphore, &dstStageMask, 1u, &commandBuffer, 1u,
730 ¤tRenderSemaphore};
731
732 VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence));
733 }
734
735 VkResult result;
736 const VkPresentInfoKHR presentInfo = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
737 DE_NULL,
738 1u,
739 ¤tRenderSemaphore,
740 1u,
741 &*m_swapchain,
742 &imageIndex,
743 &result};
744
745 VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo));
746 VK_CHECK_WSI(result);
747
748 // verify counter on last frame - we know that we must have presented as meny frames
749 // as we rendered minus the number of images in swapchain - that may not have been presented yet
750 if (m_frameNdx >= m_frameCount)
751 {
752 uint64_t counter = 0;
753 m_vkd.getSwapchainCounterEXT(*m_device, *m_swapchain, VK_SURFACE_COUNTER_VBLANK_EXT, &counter);
754 if ((counter < (m_frameCount - m_swapchainImages.size())) || (counter > m_frameCount))
755 {
756 deinitSwapchainResources();
757 m_resultCollector.fail("Invalid surface counter value");
758 }
759 }
760 }
761
iterate(void)762 tcu::TestStatus SwapchainCounterTestInstance::iterate(void)
763 {
764 try
765 {
766 // Initialize swapchain specific resources
767 if (m_frameNdx == 0)
768 initSwapchainResources();
769
770 // Render frame
771 render();
772 }
773 catch (const Error &error)
774 {
775 if (error.getError() == VK_ERROR_OUT_OF_DATE_KHR)
776 {
777 if (m_outOfDateCount < m_maxOutOfDateCount)
778 {
779 m_context.getTestContext().getLog()
780 << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources."
781 << TestLog::EndMessage;
782 deinitSwapchainResources();
783 m_outOfDateCount++;
784 m_frameNdx = 0;
785
786 return tcu::TestStatus::incomplete();
787 }
788
789 m_context.getTestContext().getLog()
790 << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage;
791 return tcu::TestStatus::fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors.");
792 }
793
794 deinitSwapchainResources();
795 return tcu::TestStatus::fail(error.what());
796 }
797
798 m_frameNdx++;
799 if (m_frameNdx < m_frameCount)
800 return tcu::TestStatus::incomplete();
801
802 deinitSwapchainResources();
803 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
804 }
805
806 class SwapchainCounterTestCase : public TestCase
807 {
808 public:
809 SwapchainCounterTestCase(tcu::TestContext &context, const char *name);
810 ~SwapchainCounterTestCase() = default;
811
812 void initPrograms(SourceCollections &programCollection) const;
813 virtual TestInstance *createInstance(Context &context) const;
814 virtual void checkSupport(Context &context) const;
815 };
816
SwapchainCounterTestCase(tcu::TestContext & context,const char * name)817 SwapchainCounterTestCase::SwapchainCounterTestCase(tcu::TestContext &context, const char *name)
818 : vkt::TestCase(context, name)
819 {
820 }
821
initPrograms(SourceCollections & dst) const822 void SwapchainCounterTestCase::initPrograms(SourceCollections &dst) const
823 {
824 dst.glslSources.add("quad-vert") << glu::VertexSource(
825 "#version 450\n"
826 "out gl_PerVertex {\n"
827 " vec4 gl_Position;\n"
828 "};\n"
829 "highp float;\n"
830 "void main (void) {\n"
831 " gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
832 " ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
833 "}\n");
834 dst.glslSources.add("quad-frag") << glu::FragmentSource("#version 450\n"
835 "layout(location = 0) out highp vec4 o_color;\n"
836 "void main (void)\n"
837 "{\n"
838 " o_color = vec4(1.0, 0.5, 0.0, 1.0);\n"
839 "}\n");
840 }
841
createInstance(Context & context) const842 TestInstance *SwapchainCounterTestCase::createInstance(Context &context) const
843 {
844 return new SwapchainCounterTestInstance(context);
845 }
846
checkSupport(Context & context) const847 void SwapchainCounterTestCase::checkSupport(Context &context) const
848 {
849 context.requireInstanceFunctionality("VK_KHR_display");
850 context.requireDeviceFunctionality("VK_EXT_display_control");
851 }
852
getDisplays(Context & context,std::vector<VkDisplayKHR> & availableDisplays)853 void getDisplays(Context &context, std::vector<VkDisplayKHR> &availableDisplays)
854 {
855 // get number of displays
856 uint32_t countReported = 0u;
857 VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
858 const InstanceInterface &vki = context.getInstanceInterface();
859 const vk::Platform &platform = context.getTestContext().getPlatform().getVulkanPlatform();
860
861 VkResult result = vki.getPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &countReported, DE_NULL);
862 if (result != VK_SUCCESS)
863 TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceDisplayPropertiesKHR failed");
864
865 if (countReported == 0)
866 TCU_THROW(NotSupportedError, "No displays available");
867
868 for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
869 {
870 vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
871 if (platform.hasDisplay(wsiType))
872 {
873 TCU_THROW(NotSupportedError, "Display is unavailable as windowing system has access");
874 }
875 }
876
877 // get display properties
878 std::vector<VkDisplayPropertiesKHR> displaysProperties(countReported);
879 result = vki.getPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &countReported, &displaysProperties[0]);
880
881 if (result != VK_SUCCESS)
882 TCU_THROW(NotSupportedError, "vkGetPhysicalDeviceDisplayPropertiesKHR failed");
883
884 availableDisplays.clear();
885 for (const auto &dp : displaysProperties)
886 availableDisplays.push_back(dp.display);
887 }
888
testDisplayPowerControl(Context & context)889 tcu::TestStatus testDisplayPowerControl(Context &context)
890 {
891 // make sure VK_EXT_display_control is available
892 context.requireDeviceFunctionality("VK_EXT_display_control");
893
894 // get all connected displays
895 std::vector<VkDisplayKHR> availableDisplays;
896 getDisplays(context, availableDisplays);
897
898 struct PowerStateData
899 {
900 VkDisplayPowerStateEXT state;
901 uint32_t waitMs;
902 };
903 vector<PowerStateData> powerStateDataVect = {
904 {VK_DISPLAY_POWER_STATE_ON_EXT, 1000},
905 {VK_DISPLAY_POWER_STATE_SUSPEND_EXT, 1000},
906 {VK_DISPLAY_POWER_STATE_OFF_EXT, 1000},
907 {VK_DISPLAY_POWER_STATE_ON_EXT, 1000},
908 };
909
910 // iterate over all displays
911 VkDevice device = context.getDevice();
912 const vk::DeviceInterface &vkd = context.getDeviceInterface();
913 for (const auto &display : availableDisplays)
914 {
915 // iterate over tested sequence of power states
916 for (const auto &psd : powerStateDataVect)
917 {
918 VkDisplayPowerInfoEXT displayPowerInfo = {VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT, DE_NULL, psd.state};
919
920 VkResult result = vkd.displayPowerControlEXT(device, display, &displayPowerInfo);
921 if (result != VK_SUCCESS)
922 return tcu::TestStatus::fail(std::string("vkDisplayPowerControlEXT returned invalid result for ") +
923 de::toString(psd.state));
924
925 deSleep(psd.waitMs);
926 }
927 }
928
929 return tcu::TestStatus::pass("pass");
930 }
931
testDisplayEvent(Context & context)932 tcu::TestStatus testDisplayEvent(Context &context)
933 {
934 // make sure VK_EXT_display_control is available
935 context.requireDeviceFunctionality("VK_EXT_display_control");
936
937 // get all connected displays
938 std::vector<vk::VkDisplayKHR> availableDisplays;
939 getDisplays(context, availableDisplays);
940
941 VkDevice device = context.getDevice();
942 const DeviceInterface &vkd = context.getDeviceInterface();
943 std::vector<VkFence> fences = std::vector<VkFence>(availableDisplays.size(), (VkFence)0);
944
945 // iterate over all displays
946 for (size_t i = 0; i < availableDisplays.size(); ++i)
947 {
948 VkDisplayEventInfoEXT displayEventInfo = {VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT, DE_NULL,
949 VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT};
950
951 VkFence &fence = fences[i];
952 VkDisplayKHR &display = availableDisplays[i];
953 VkResult result = vkd.registerDisplayEventEXT(device, display, &displayEventInfo, DE_NULL, &fence);
954 if (result != VK_SUCCESS)
955 return tcu::TestStatus::fail(std::string("vkRegisterDisplayEventEXT returned invalid result"));
956 }
957
958 // deinit fence
959 deinitFences(vkd, device, fences);
960
961 return tcu::TestStatus::pass("pass");
962 }
963
testDeviceEvent(Context & context)964 tcu::TestStatus testDeviceEvent(Context &context)
965 {
966 // make sure VK_EXT_display_control is available
967 context.requireDeviceFunctionality("VK_EXT_display_control");
968
969 VkDevice device = context.getDevice();
970 const DeviceInterface &vkd = context.getDeviceInterface();
971 std::vector<VkFence> fences = std::vector<VkFence>(1, (VkFence)0);
972
973 vk::VkDeviceEventInfoEXT deviceEventInfo = {VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT, DE_NULL,
974 VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT};
975
976 VkResult result = vkd.registerDeviceEventEXT(device, &deviceEventInfo, DE_NULL, &fences[0]);
977 if (result != VK_SUCCESS)
978 return tcu::TestStatus::fail(std::string("vkRegisterDeviceEventEXT returned invalid result"));
979
980 // deinit fence
981 deinitFences(vkd, device, fences);
982
983 return tcu::TestStatus::pass("pass");
984 }
985
986 } // namespace
987
createDisplayControlTests(tcu::TestCaseGroup * testGroup)988 void createDisplayControlTests(tcu::TestCaseGroup *testGroup)
989 {
990 testGroup->addChild(new SwapchainCounterTestCase(testGroup->getTestContext(), "swapchain_counter"));
991 addFunctionCase(testGroup, "display_power_control", testDisplayPowerControl);
992 addFunctionCase(testGroup, "register_display_event", testDisplayEvent);
993 addFunctionCase(testGroup, "register_device_event", testDeviceEvent);
994 }
995
996 } // namespace wsi
997 } // namespace vkt
998