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