• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  * Copyright (c) 2020 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief VK_EXT_full_screen_exclusive extension Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktWsiFullScreenExclusiveTests.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 
30 #include "vkRefUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkWsiPlatform.hpp"
36 #include "vkWsiUtil.hpp"
37 
38 #include "tcuTestLog.hpp"
39 #include "tcuPlatform.hpp"
40 #include "tcuCommandLine.hpp"
41 
42 #include <limits>
43 
44 #if ( DE_OS == DE_OS_WIN32 )
45 	#define NOMINMAX
46 	#define WIN32_LEAN_AND_MEAN
47 	#include <windows.h>
48 #endif
49 
50 namespace vkt
51 {
52 namespace wsi
53 {
54 
55 namespace
56 {
57 
58 using namespace vk;
59 using namespace vk::wsi;
60 
61 typedef std::vector<VkExtensionProperties> Extensions;
62 
63 struct TestParams
64 {
65 	vk::wsi::Type				wsiType;
66 	VkFullScreenExclusiveEXT	fseType;
67 };
68 
checkAllSupported(const Extensions & supportedExtensions,const std::vector<std::string> & requiredExtensions)69 void checkAllSupported (const Extensions& supportedExtensions,
70 						const std::vector<std::string>& requiredExtensions)
71 {
72 	for (std::vector<std::string>::const_iterator requiredExtName = requiredExtensions.begin();
73 		 requiredExtName != requiredExtensions.end();
74 		 ++requiredExtName)
75 	{
76 		if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
77 			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
78 	}
79 }
80 
createInstanceWithWsi(Context & context,const Extensions & supportedExtensions,Type wsiType,const VkAllocationCallbacks * pAllocator=DE_NULL)81 CustomInstance createInstanceWithWsi (Context&						context,
82 									  const Extensions&				supportedExtensions,
83 									  Type							wsiType,
84 									  const VkAllocationCallbacks*	pAllocator	= DE_NULL)
85 {
86 	std::vector<std::string>	extensions;
87 
88 	extensions.push_back("VK_KHR_surface");
89 	extensions.push_back(getExtensionName(wsiType));
90 
91 	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_get_surface_capabilities2")))
92 		extensions.push_back("VK_KHR_get_surface_capabilities2");
93 
94 	checkAllSupported(supportedExtensions, extensions);
95 
96 	return createCustomInstanceWithExtensions(context, extensions, pAllocator);
97 }
98 
getDeviceFeaturesForWsi(void)99 VkPhysicalDeviceFeatures getDeviceFeaturesForWsi (void)
100 {
101 	VkPhysicalDeviceFeatures features;
102 	deMemset(&features, 0, sizeof(features));
103 	return features;
104 }
105 
createDeviceWithWsi(const vk::PlatformInterface & vkp,vk::VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const deUint32 queueFamilyIndex,const VkAllocationCallbacks * pAllocator,bool validationEnabled)106 Move<VkDevice> createDeviceWithWsi (const vk::PlatformInterface&	vkp,
107 									vk::VkInstance					instance,
108 									const InstanceInterface&		vki,
109 									VkPhysicalDevice				physicalDevice,
110 									const Extensions&				supportedExtensions,
111 									const deUint32					queueFamilyIndex,
112 									const VkAllocationCallbacks*	pAllocator,
113 									bool							validationEnabled)
114 {
115 	const float						queuePriorities[]	= { 1.0f };
116 	const VkDeviceQueueCreateInfo	queueInfos[]		=
117 	{
118 		{
119 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
120 			DE_NULL,
121 			(VkDeviceQueueCreateFlags)0,
122 			queueFamilyIndex,
123 			DE_LENGTH_OF_ARRAY(queuePriorities),
124 			&queuePriorities[0]
125 		}
126 	};
127 	const VkPhysicalDeviceFeatures	features		= getDeviceFeaturesForWsi();
128 	std::vector<const char*>		extensions;
129 
130 	if (!isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_swapchain")))
131 		TCU_THROW(NotSupportedError, "VK_KHR_swapchain is not supported");
132 	extensions.push_back("VK_KHR_swapchain");
133 
134 	if (isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
135 	{
136 		extensions.push_back("VK_EXT_full_screen_exclusive");
137 	}
138 
139 	VkDeviceCreateInfo		deviceParams	=
140 	{
141 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
142 		DE_NULL,
143 		(VkDeviceCreateFlags)0,
144 		DE_LENGTH_OF_ARRAY(queueInfos),
145 		&queueInfos[0],
146 		0u,									// enabledLayerCount
147 		DE_NULL,							// ppEnabledLayerNames
148 		(deUint32)extensions.size(),
149 		extensions.empty() ? DE_NULL : &extensions[0],
150 		&features
151 	};
152 
153 	return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
154 }
155 
156 struct InstanceHelper
157 {
158 	const std::vector<VkExtensionProperties>	supportedExtensions;
159 	const CustomInstance				instance;
160 	const InstanceDriver&				vki;
161 
InstanceHelpervkt::wsi::__anon9e6ba1860111::InstanceHelper162 	InstanceHelper (Context& context,
163 					Type wsiType,
164 					const VkAllocationCallbacks* pAllocator = DE_NULL)
165 		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
166 																	  DE_NULL))
167 		, instance				(createInstanceWithWsi(context,
168 													   supportedExtensions,
169 													   wsiType,
170 													   pAllocator))
171 		, vki					(instance.getDriver())
172 	{}
173 };
174 
175 struct DeviceHelper
176 {
177 	const VkPhysicalDevice	physicalDevice;
178 	const deUint32			queueFamilyIndex;
179 	const Unique<VkDevice>	device;
180 	const DeviceDriver		vkd;
181 	const VkQueue			queue;
182 
DeviceHelpervkt::wsi::__anon9e6ba1860111::DeviceHelper183 	DeviceHelper (Context&						context,
184 				  const InstanceInterface&		vki,
185 				  VkInstance					instance,
186 				  VkSurfaceKHR					surface,
187 				  const VkAllocationCallbacks*	pAllocator = DE_NULL)
188 		: physicalDevice	(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
189 		, queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, surface))
190 		, device			(createDeviceWithWsi(context.getPlatformInterface(),
191 												 instance,
192 												 vki,
193 												 physicalDevice,
194 												 enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
195 												 queueFamilyIndex,
196 												 pAllocator,
197 												 context.getTestContext().getCommandLine().isValidationEnabled()))
198 		, vkd				(context.getPlatformInterface(), instance, *device)
199 		, queue				(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
200 	{
201 	}
202 };
203 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,Type wsiType)204 de::MovePtr<Display> createDisplay (const vk::Platform&	platform,
205 									const Extensions&	supportedExtensions,
206 									Type				wsiType)
207 {
208 	try
209 	{
210 		return de::MovePtr<Display>(platform.createWsiDisplay(wsiType));
211 	}
212 	catch (const tcu::NotSupportedError& e)
213 	{
214 		if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))) &&
215 		    platform.hasDisplay(wsiType))
216 		{
217 			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
218 			// must support creating native display & window for that WSI type.
219 			throw tcu::TestError(e.getMessage());
220 		}
221 		else
222 			throw;
223 	}
224 }
225 
createWindow(const Display & display,const tcu::Maybe<tcu::UVec2> & initialSize)226 de::MovePtr<Window> createWindow (const Display& display,
227 								  const tcu::Maybe<tcu::UVec2>& initialSize)
228 {
229 	try
230 	{
231 		return de::MovePtr<Window>(display.createWindow(initialSize));
232 	}
233 	catch (const tcu::NotSupportedError& e)
234 	{
235 		// See createDisplay - assuming that wsi::Display was supported platform port
236 		// should also support creating a window.
237 		throw tcu::TestError(e.getMessage());
238 	}
239 }
240 
241 struct NativeObjectsFS
242 {
243 	const de::UniquePtr<Display>	display;
244 	tcu::UVec2						windowSize;
245 	const de::UniquePtr<Window>		window;
246 
NativeObjectsFSvkt::wsi::__anon9e6ba1860111::NativeObjectsFS247 	NativeObjectsFS	(Context&				context,
248 					 const Extensions&		supportedExtensions,
249 					 Type					wsiType)
250 		: display		(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
251 		, windowSize	(getFullScreenSize(wsiType, *display.get(), tcu::UVec2(256U, 256U)))
252 		, window		(createWindow(*display, windowSize))
253 	{}
254 };
255 
getBasicSwapchainParameters(Type wsiType,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceFormatKHR surfaceFormat,const tcu::UVec2 & desiredSize,deUint32 desiredImageCount)256 VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type						wsiType,
257 													  const InstanceInterface&	vki,
258 													  VkPhysicalDevice			physicalDevice,
259 													  VkSurfaceKHR				surface,
260 													  VkSurfaceFormatKHR		surfaceFormat,
261 													  const tcu::UVec2&			desiredSize,
262 													  deUint32					desiredImageCount)
263 {
264 	const VkSurfaceCapabilitiesKHR		capabilities		= getPhysicalDeviceSurfaceCapabilities(vki,
265 																								   physicalDevice,
266 																								   surface);
267 	const PlatformProperties&			platformProperties	= getPlatformProperties(wsiType);
268 	const VkSurfaceTransformFlagBitsKHR transform			= (capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : capabilities.currentTransform;
269 	const VkSwapchainCreateInfoKHR		parameters			=
270 	{
271 		VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
272 		DE_NULL,
273 		(VkSwapchainCreateFlagsKHR)0,
274 		surface,
275 		de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount > 0 ? capabilities.maxImageCount : capabilities.minImageCount + desiredImageCount),
276 		surfaceFormat.format,
277 		surfaceFormat.colorSpace,
278 		(platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE
279 			? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())),
280 		1u,									// imageArrayLayers
281 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
282 		VK_SHARING_MODE_EXCLUSIVE,
283 		0u,
284 		(const deUint32*)DE_NULL,
285 		transform,
286 		VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
287 		VK_PRESENT_MODE_FIFO_KHR,
288 		VK_FALSE,							// clipped
289 		(VkSwapchainKHR)0					// oldSwapchain
290 	};
291 
292 	return parameters;
293 }
294 
295 typedef de::SharedPtr<Unique<VkCommandBuffer> >	CommandBufferSp;
296 typedef de::SharedPtr<Unique<VkFence> >			FenceSp;
297 typedef de::SharedPtr<Unique<VkSemaphore> >		SemaphoreSp;
298 
createFences(const DeviceInterface & vkd,const VkDevice device,size_t numFences)299 std::vector<FenceSp> createFences (const DeviceInterface&	vkd,
300 								   const VkDevice			device,
301 								   size_t					numFences)
302 {
303 	std::vector<FenceSp> fences(numFences);
304 
305 	for (size_t ndx = 0; ndx < numFences; ++ndx)
306 		fences[ndx] = FenceSp(new Unique<VkFence>(createFence(vkd, device)));
307 
308 	return fences;
309 }
310 
createSemaphores(const DeviceInterface & vkd,const VkDevice device,size_t numSemaphores)311 std::vector<SemaphoreSp> createSemaphores (const DeviceInterface&	vkd,
312 										   const VkDevice			device,
313 										   size_t					numSemaphores)
314 {
315 	std::vector<SemaphoreSp> semaphores(numSemaphores);
316 
317 	for (size_t ndx = 0; ndx < numSemaphores; ++ndx)
318 		semaphores[ndx] = SemaphoreSp(new Unique<VkSemaphore>(createSemaphore(vkd, device)));
319 
320 	return semaphores;
321 }
322 
allocateCommandBuffers(const DeviceInterface & vkd,const VkDevice device,const VkCommandPool commandPool,const VkCommandBufferLevel level,const size_t numCommandBuffers)323 std::vector<CommandBufferSp> allocateCommandBuffers (const DeviceInterface&		vkd,
324 													 const VkDevice				device,
325 													 const VkCommandPool		commandPool,
326 													 const VkCommandBufferLevel	level,
327 													 const size_t				numCommandBuffers)
328 {
329 	std::vector<CommandBufferSp>				buffers		(numCommandBuffers);
330 
331 	for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx)
332 		buffers[ndx] = CommandBufferSp(new Unique<VkCommandBuffer>(allocateCommandBuffer(vkd, device, commandPool, level)));
333 
334 	return buffers;
335 }
336 
fullScreenExclusiveTest(Context & context,TestParams testParams)337 tcu::TestStatus fullScreenExclusiveTest(Context& context,
338 	TestParams testParams)
339 {
340 	if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_full_screen_exclusive"))
341 		TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
342 
343 	const InstanceHelper						instHelper(context, testParams.wsiType);
344 	const NativeObjectsFS						native(context, instHelper.supportedExtensions, testParams.wsiType);
345 	const Unique<VkSurfaceKHR>					surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType, *native.display, *native.window));
346 	const DeviceHelper							devHelper(context, instHelper.vki, instHelper.instance, *surface);
347 	const std::vector<VkExtensionProperties>	deviceExtensions(enumerateDeviceExtensionProperties(instHelper.vki, devHelper.physicalDevice, DE_NULL));
348 	if (!isExtensionSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
349 		TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
350 
351 	native.window->setVisible(true);
352 
353 	if (testParams.wsiType == TYPE_WIN32)
354 	{
355 		native.window->setForeground();
356 	}
357 
358 	// add information about full screen exclusive to VkSwapchainCreateInfoKHR
359 	VkSurfaceFullScreenExclusiveInfoEXT			fseInfo =
360 	{
361 		VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT,			// VkStructureType             sType;
362 		DE_NULL,															// void*                       pNext;
363 		testParams.fseType													// VkFullScreenExclusiveEXT    fullScreenExclusive;
364 	};
365 
366 	// for Win32 - create structure containing HMONITOR value
367 #if ( DE_OS == DE_OS_WIN32 )
368 	VkSurfaceFullScreenExclusiveWin32InfoEXT	fseWin32Info				= {
369 		VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT,		// VkStructureType    sType;
370 		DE_NULL,															// const void*        pNext;
371 		pt::Win32MonitorHandle(0)											// HMONITOR           hmonitor;
372 	};
373 	if (testParams.wsiType == TYPE_WIN32)
374 	{
375 		Win32WindowInterface*					windowInterface				= dynamic_cast<Win32WindowInterface*>(native.window.get());
376 		fseWin32Info.hmonitor												= (pt::Win32MonitorHandle)MonitorFromWindow((HWND)windowInterface->getNative().internal, MONITOR_DEFAULTTONEAREST);
377 	}
378 #endif
379 
380 	// check surface capabilities
381 	VkSurfaceCapabilitiesFullScreenExclusiveEXT	surfaceCapabilitiesFSE		= {
382 		VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT,	// VkStructureType    sType;
383 		DE_NULL,															// void*              pNext;
384 		DE_FALSE															// VkBool32           fullScreenExclusiveSupported;
385 	};
386 	VkSurfaceCapabilities2KHR					surfaceCapabilities2		= {
387 		VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,						// VkStructureType             sType;
388 		&surfaceCapabilitiesFSE,											// void*                       pNext;
389 		VkSurfaceCapabilitiesKHR {}											// VkSurfaceCapabilitiesKHR    surfaceCapabilities;
390 	};
391 	VkPhysicalDeviceSurfaceInfo2KHR				surfaceInfo					= {
392 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,				// VkStructureType    sType;
393 		DE_NULL,															// const void*        pNext;
394 		*surface															// VkSurfaceKHR       surface;
395 	};
396 
397 	surfaceInfo.pNext = &fseInfo;
398 
399 #if ( DE_OS == DE_OS_WIN32 )
400 	if (testParams.wsiType == TYPE_WIN32)
401 	{
402 		fseInfo.pNext = &fseWin32Info;
403 	}
404 #endif
405 
406 	instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &surfaceCapabilities2);
407 	if (surfaceCapabilitiesFSE.fullScreenExclusiveSupported == DE_FALSE)
408 		TCU_THROW(NotSupportedError, "VkSurfaceCapabilitiesFullScreenExclusiveEXT::fullScreenExclusiveSupported is set to false");
409 
410 	const DeviceInterface&						vkd							= devHelper.vkd;
411 	const VkDevice								device						= *devHelper.device;
412 	SimpleAllocator								allocator					(vkd, device, getPhysicalDeviceMemoryProperties(instHelper.vki, devHelper.physicalDevice));
413 
414 	std::vector<VkSurfaceFormatKHR>				surfaceFormats				= vk::wsi::getPhysicalDeviceSurfaceFormats(instHelper.vki, devHelper.physicalDevice, *surface);
415 	if(surfaceFormats.empty())
416 		return tcu::TestStatus::fail("No VkSurfaceFormatKHR defined");
417 
418 	VkSwapchainCreateInfoKHR					swapchainInfo				= getBasicSwapchainParameters(testParams.wsiType, instHelper.vki, devHelper.physicalDevice, *surface, surfaceFormats[0], native.windowSize, 2);
419 
420 	swapchainInfo.pNext = &fseInfo;
421 
422 #if ( DE_OS == DE_OS_WIN32 )
423 	if (testParams.wsiType == TYPE_WIN32)
424 	{
425 		fseInfo.pNext = &fseWin32Info;
426 	}
427 #endif
428 
429 	Move<VkSwapchainKHR>						swapchain;
430 	{
431 		VkSwapchainKHR object = 0;
432 		VkResult result = vkd.createSwapchainKHR(device, &swapchainInfo, DE_NULL, &object);
433 		if (result == VK_ERROR_INITIALIZATION_FAILED && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
434 		{
435 			// In some cases, swapchain creation may fail if exclusive full-screen mode is requested for application control,
436 			// but for some implementation-specific reason exclusive full-screen access is unavailable for the particular combination
437 			// of parameters provided. If this occurs, VK_ERROR_INITIALIZATION_FAILED will be returned.
438 			return  tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Failed to create swapchain with exclusive full-screen mode for application control.");
439 		}
440 		else
441 		{
442 			VK_CHECK(result);
443 		}
444 
445 		swapchain = Move<VkSwapchainKHR>(check<VkSwapchainKHR>(object), Deleter<VkSwapchainKHR>(vkd, device, DE_NULL));
446 	}
447 	const std::vector<VkImage>					swapchainImages				= getSwapchainImages(vkd, device, *swapchain);
448 
449 	const WsiTriangleRenderer					renderer					(vkd,
450 																			 device,
451 																			 allocator,
452 																			 context.getBinaryCollection(),
453 																			 true,
454 																			 swapchainImages,
455 																			 swapchainImages,
456 																			 swapchainInfo.imageFormat,
457 																			 tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height));
458 
459 	const Unique<VkCommandPool>					commandPool					(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex));
460 
461 	const size_t								maxQueuedFrames				= swapchainImages.size()*2;
462 
463 	// We need to keep hold of fences from vkAcquireNextImageKHR to actually
464 	// limit number of frames we allow to be queued.
465 	const std::vector<FenceSp>					imageReadyFences			(createFences(vkd, device, maxQueuedFrames));
466 
467 	// We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass
468 	// the semaphore in same time as the fence we use to meter rendering.
469 	const std::vector<SemaphoreSp>				imageReadySemaphores		(createSemaphores(vkd, device, maxQueuedFrames+1));
470 
471 	// For rest we simply need maxQueuedFrames as we will wait for image
472 	// from frameNdx-maxQueuedFrames to become available to us, guaranteeing that
473 	// previous uses must have completed.
474 	const std::vector<SemaphoreSp>				renderingCompleteSemaphores	(createSemaphores(vkd, device, maxQueuedFrames));
475 	const std::vector<CommandBufferSp>			commandBuffers				(allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames));
476 
477 	bool										fullScreenAcquired			= (testParams.fseType != VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT);
478 
479 	bool										fullScreenLost				= false;
480 
481 	try
482 	{
483 		const deUint32	numFramesToRender					= 60;
484 
485 		for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx)
486 		{
487 			const VkFence		imageReadyFence		= **imageReadyFences[frameNdx%imageReadyFences.size()];
488 			const VkSemaphore	imageReadySemaphore	= **imageReadySemaphores[frameNdx%imageReadySemaphores.size()];
489 			deUint32			imageNdx			= ~0u;
490 
491 			if (!fullScreenAcquired)
492 			{
493 				const VkResult acquireResult = vkd.acquireFullScreenExclusiveModeEXT(device, *swapchain);
494 
495 				switch (acquireResult)
496 				{
497 					case VK_SUCCESS:
498 					{
499 						fullScreenAcquired = true;
500 						break;
501 					}
502 					case VK_ERROR_INITIALIZATION_FAILED:
503 					{
504 						break;
505 					}
506 					case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
507 					{
508 						context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkAcquireFullScreenExclusiveModeEXT. Frame " << frameNdx << tcu::TestLog::EndMessage;
509 						break;
510 					}
511 					default:
512 					{
513 						VK_CHECK(acquireResult);
514 						break;
515 					}
516 				}
517 			}
518 
519 			if (frameNdx >= maxQueuedFrames)
520 				VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits<deUint64>::max()));
521 
522 			VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence));
523 
524 			VkResult	acquireResult;
525 
526 			{
527 				acquireResult	= vkd.acquireNextImageKHR(device,
528 														  *swapchain,
529 														  std::numeric_limits<deUint64>::max(),
530 														  imageReadySemaphore,
531 														  (vk::VkFence)0,
532 														  &imageNdx);
533 				if (acquireResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
534 				{
535 					context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkAcquireNextImageKHR" << tcu::TestLog::EndMessage;
536 
537 					fullScreenLost = true;
538 				}
539 				VK_CHECK_WSI(acquireResult);
540 			}
541 
542 			if (acquireResult != VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
543 			{
544 				TCU_CHECK((size_t)imageNdx < swapchainImages.size());
545 
546 				const VkSemaphore			renderingCompleteSemaphore	= **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()];
547 				const VkCommandBuffer		commandBuffer				= **commandBuffers[frameNdx%commandBuffers.size()];
548 				const VkPipelineStageFlags	waitDstStage				= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
549 				const VkSubmitInfo			submitInfo					=
550 				{
551 					VK_STRUCTURE_TYPE_SUBMIT_INFO,
552 					DE_NULL,
553 					1u,
554 					&imageReadySemaphore,
555 					&waitDstStage,
556 					1u,
557 					&commandBuffer,
558 					1u,
559 					&renderingCompleteSemaphore
560 				};
561 				const VkPresentInfoKHR		presentInfo					=
562 				{
563 					VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
564 					DE_NULL,
565 					1u,
566 					&renderingCompleteSemaphore,
567 					1u,
568 					&*swapchain,
569 					&imageNdx,
570 					(VkResult*)DE_NULL
571 				};
572 
573 				renderer.recordFrame(commandBuffer, imageNdx, frameNdx);
574 				VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, imageReadyFence));
575 				const VkResult presentResult = vkd.queuePresentKHR(devHelper.queue, &presentInfo);
576 				if (presentResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
577 				{
578 					context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkQueuePresentKHR" << tcu::TestLog::EndMessage;
579 
580 					fullScreenLost = true;
581 				}
582 				VK_CHECK_WSI(presentResult);
583 			}
584 			else
585 			{
586 				// image was not acquired, just roll the synchronization
587 				VK_CHECK(vkd.queueSubmit(devHelper.queue, 0u, DE_NULL, imageReadyFence));
588 			}
589 		}
590 
591 		VK_CHECK(vkd.deviceWaitIdle(device));
592 	}
593 	catch (...)
594 	{
595 		// Make sure device is idle before destroying resources
596 		vkd.deviceWaitIdle(device);
597 		throw;
598 	}
599 
600 	if (fullScreenAcquired && testParams.fseType == VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT)
601 	{
602 		const VkResult releaseResult = vkd.releaseFullScreenExclusiveModeEXT(device, *swapchain);
603 		if (releaseResult == VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
604 		{
605 			context.getTestContext().getLog() << tcu::TestLog::Message << "Got VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT at vkReleaseFullScreenExclusiveModeEXT" << tcu::TestLog::EndMessage;
606 
607 			fullScreenLost = true;
608 		}
609 		VK_CHECK_WSI(releaseResult);
610 	}
611 
612 	native.window->setVisible(false);
613 
614 	if (fullScreenAcquired && !fullScreenLost)
615 	{
616 		return tcu::TestStatus::pass("Rendering tests succeeded");
617 	}
618 	else
619 	{
620 		if (fullScreenLost)
621 		{
622 			return  tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Full screen exclusive was lost during test, but did not end with an error.");
623 		}
624 		else
625 		{
626 			return  tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Failed to acquire full screen exclusive, but did not end with an error.");
627 		}
628 	}
629 }
630 
getBasicRenderPrograms(SourceCollections & dst,TestParams)631 void getBasicRenderPrograms (SourceCollections& dst, TestParams)
632 {
633 	WsiTriangleRenderer::getPrograms(dst);
634 }
635 
636 } // anonymous
637 
createFullScreenExclusiveTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)638 void createFullScreenExclusiveTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
639 {
640 	struct
641 	{
642 		VkFullScreenExclusiveEXT				testType;
643 		const char*								name;
644 	} fullScreenTestTypes[] =
645 	{
646 		{ VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT,					"default" },
647 		{ VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT,					"allowed" },
648 		{ VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT,				"disallowed" },
649 		{ VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT,	"application_controlled" },
650 	};
651 
652 	for (size_t fseNdx = 0; fseNdx < DE_LENGTH_OF_ARRAY(fullScreenTestTypes); ++fseNdx)
653 	{
654 		TestParams testParams
655 		{
656 			wsiType,
657 			fullScreenTestTypes[fseNdx].testType
658 		};
659 		addFunctionCaseWithPrograms(testGroup, fullScreenTestTypes[fseNdx].name, "", getBasicRenderPrograms, fullScreenExclusiveTest, testParams);
660 	}
661 }
662 
663 } // wsi
664 
665 } // vkt
666