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