• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 			&currentAcquireSemaphore,
829 			&dstStageMask,
830 			1u,
831 			&commandBuffer,
832 			1u,
833 			&currentRenderSemaphore
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 		&currentRenderSemaphore,
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