1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google 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  * \file
21  * \brief VkSurface Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktWsiSurfaceTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkWsiPlatform.hpp"
40 #include "vkWsiUtil.hpp"
41 #include "vkAllocationCallbackUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuFormatUtil.hpp"
45 #include "tcuPlatform.hpp"
46 #include "tcuResultCollector.hpp"
47 
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 
51 namespace vk
52 {
53 
operator !=(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)54 inline bool operator!= (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
55 {
56 	return (a.format != b.format) || (a.colorSpace != b.colorSpace);
57 }
58 
operator ==(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)59 inline bool operator== (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
60 {
61 	return !(a != b);
62 }
63 
64 } // vk
65 
66 namespace vkt
67 {
68 namespace wsi
69 {
70 
71 namespace
72 {
73 
74 using namespace vk;
75 using namespace vk::wsi;
76 
77 using tcu::TestLog;
78 using tcu::Maybe;
79 using tcu::UVec2;
80 
81 using de::MovePtr;
82 using de::UniquePtr;
83 
84 using std::string;
85 using std::vector;
86 
87 enum
88 {
89 	SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC	= 0xffffffff
90 };
91 
92 typedef vector<VkExtensionProperties> Extensions;
93 
checkAllSupported(const Extensions & supportedExtensions,const vector<string> & requiredExtensions)94 void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions)
95 {
96 	for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin();
97 		 requiredExtName != requiredExtensions.end();
98 		 ++requiredExtName)
99 	{
100 		if (!isExtensionSupported(supportedExtensions, RequiredExtension(*requiredExtName)))
101 			TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str());
102 	}
103 }
104 
createInstanceWithWsi(const PlatformInterface & vkp,const Extensions & supportedExtensions,Type wsiType,const VkAllocationCallbacks * pAllocator=DE_NULL)105 Move<VkInstance> createInstanceWithWsi (const PlatformInterface&		vkp,
106 										const Extensions&				supportedExtensions,
107 										Type							wsiType,
108 										const VkAllocationCallbacks*	pAllocator	= DE_NULL)
109 {
110 	vector<string>	extensions;
111 
112 	extensions.push_back("VK_KHR_surface");
113 	extensions.push_back(getExtensionName(wsiType));
114 
115 	checkAllSupported(supportedExtensions, extensions);
116 
117 	return createDefaultInstance(vkp, vector<string>(), extensions, pAllocator);
118 }
119 
120 struct InstanceHelper
121 {
122 	const vector<VkExtensionProperties>	supportedExtensions;
123 	Unique<VkInstance>					instance;
124 	const InstanceDriver				vki;
125 
InstanceHelpervkt::wsi::__anon1d6584650111::InstanceHelper126 	InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
127 		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
128 																	  DE_NULL))
129 		, instance				(createInstanceWithWsi(context.getPlatformInterface(),
130 													   supportedExtensions,
131 													   wsiType,
132 													   pAllocator))
133 		, vki					(context.getPlatformInterface(), *instance)
134 	{}
135 };
136 
createDisplay(const vk::Platform & platform,const Extensions & supportedExtensions,Type wsiType)137 MovePtr<Display> createDisplay (const vk::Platform&	platform,
138 								const Extensions&	supportedExtensions,
139 								Type				wsiType)
140 {
141 	try
142 	{
143 		return MovePtr<Display>(platform.createWsiDisplay(wsiType));
144 	}
145 	catch (const tcu::NotSupportedError& e)
146 	{
147 		if (isExtensionSupported(supportedExtensions, RequiredExtension(getExtensionName(wsiType))))
148 		{
149 			// If VK_KHR_{platform}_surface was supported, vk::Platform implementation
150 			// must support creating native display & window for that WSI type.
151 			throw tcu::TestError(e.getMessage());
152 		}
153 		else
154 			throw;
155 	}
156 }
157 
createWindow(const Display & display,const Maybe<UVec2> & initialSize)158 MovePtr<Window> createWindow (const Display& display, const Maybe<UVec2>& initialSize)
159 {
160 	try
161 	{
162 		return MovePtr<Window>(display.createWindow(initialSize));
163 	}
164 	catch (const tcu::NotSupportedError& e)
165 	{
166 		// See createDisplay - assuming that wsi::Display was supported platform port
167 		// should also support creating a window.
168 		throw tcu::TestError(e.getMessage());
169 	}
170 }
171 
172 struct NativeObjects
173 {
174 	const UniquePtr<Display>	display;
175 	const UniquePtr<Window>		window;
176 
NativeObjectsvkt::wsi::__anon1d6584650111::NativeObjects177 	NativeObjects (Context&				context,
178 				   const Extensions&	supportedExtensions,
179 				   Type					wsiType,
180 				   const Maybe<UVec2>&	initialWindowSize = tcu::nothing<UVec2>())
181 		: display	(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), supportedExtensions, wsiType))
182 		, window	(createWindow(*display, initialWindowSize))
183 	{}
184 };
185 
createSurfaceTest(Context & context,Type wsiType)186 tcu::TestStatus createSurfaceTest (Context& context, Type wsiType)
187 {
188 	const InstanceHelper		instHelper	(context, wsiType);
189 	const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
190 	const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
191 
192 	return tcu::TestStatus::pass("Creating surface succeeded");
193 }
194 
createSurfaceCustomAllocatorTest(Context & context,Type wsiType)195 tcu::TestStatus createSurfaceCustomAllocatorTest (Context& context, Type wsiType)
196 {
197 	AllocationCallbackRecorder	allocationRecorder	(getSystemAllocator());
198 	tcu::TestLog&				log					= context.getTestContext().getLog();
199 
200 	{
201 		const InstanceHelper		instHelper	(context, wsiType, allocationRecorder.getCallbacks());
202 		const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
203 		const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki,
204 															   *instHelper.instance,
205 															   wsiType,
206 															   *native.display,
207 															   *native.window,
208 															   allocationRecorder.getCallbacks()));
209 
210 		if (!validateAndLog(log,
211 							allocationRecorder,
212 							(1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)		|
213 							(1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
214 			return tcu::TestStatus::fail("Detected invalid system allocation callback");
215 	}
216 
217 	if (!validateAndLog(log, allocationRecorder, 0u))
218 		return tcu::TestStatus::fail("Detected invalid system allocation callback");
219 
220 	if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
221 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
222 	else
223 		return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
224 }
225 
createSurfaceSimulateOOMTest(Context & context,Type wsiType)226 tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
227 {
228 	tcu::TestLog&	log	= context.getTestContext().getLog();
229 
230 	for (deUint32 numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
231 	{
232 		AllocationCallbackRecorder	allocationRecorder	(getSystemAllocator());
233 		DeterministicFailAllocator	failingAllocator	(allocationRecorder.getCallbacks(), numPassingAllocs);
234 		bool						gotOOM				= false;
235 
236 		log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
237 
238 		try
239 		{
240 			const InstanceHelper		instHelper	(context, wsiType, failingAllocator.getCallbacks());
241 			const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
242 			const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki,
243 																   *instHelper.instance,
244 																   wsiType,
245 																   *native.display,
246 																   *native.window,
247 																   failingAllocator.getCallbacks()));
248 
249 			if (!validateAndLog(log,
250 								allocationRecorder,
251 								(1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)		|
252 								(1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
253 				return tcu::TestStatus::fail("Detected invalid system allocation callback");
254 		}
255 		catch (const OutOfMemoryError& e)
256 		{
257 			log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
258 			gotOOM = true;
259 		}
260 
261 		if (!validateAndLog(log, allocationRecorder, 0u))
262 			return tcu::TestStatus::fail("Detected invalid system allocation callback");
263 
264 		if (!gotOOM)
265 		{
266 			log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
267 
268 			if (numPassingAllocs == 0)
269 				return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
270 			else
271 				return tcu::TestStatus::pass("OOM simulation completed");
272 		}
273 	}
274 
275 	return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
276 }
277 
getNumQueueFamilies(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)278 deUint32 getNumQueueFamilies (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
279 {
280 	deUint32	numFamilies		= 0;
281 
282 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
283 
284 	return numFamilies;
285 }
286 
querySurfaceSupportTest(Context & context,Type wsiType)287 tcu::TestStatus querySurfaceSupportTest (Context& context, Type wsiType)
288 {
289 	tcu::TestLog&					log						= context.getTestContext().getLog();
290 	tcu::ResultCollector			results					(log);
291 
292 	const InstanceHelper			instHelper				(context, wsiType);
293 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
294 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
295 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
296 
297 	// On Android surface must be supported by all devices and queue families
298 	const bool						expectSupportedOnAll	= wsiType == TYPE_ANDROID;
299 
300 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
301 	{
302 		const VkPhysicalDevice		physicalDevice		= physicalDevices[deviceNdx];
303 		const deUint32				numQueueFamilies	= getNumQueueFamilies(instHelper.vki, physicalDevice);
304 
305 		for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
306 		{
307 			const VkBool32	isSupported		= getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
308 
309 			log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
310 									<< (isSupported == VK_FALSE ? "NOT " : "") << "supported"
311 				<< TestLog::EndMessage;
312 
313 			if (expectSupportedOnAll && !isSupported)
314 				results.fail("Surface must be supported by all devices and queue families");
315 		}
316 	}
317 
318 	return tcu::TestStatus(results.getResult(), results.getMessage());
319 }
320 
isSupportedByAnyQueue(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)321 bool isSupportedByAnyQueue (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
322 {
323 	const deUint32	numQueueFamilies	= getNumQueueFamilies(vki, physicalDevice);
324 
325 	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
326 	{
327 		if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
328 			return true;
329 	}
330 
331 	return false;
332 }
333 
validateSurfaceCapabilities(tcu::ResultCollector & results,const VkSurfaceCapabilitiesKHR & capabilities)334 void validateSurfaceCapabilities (tcu::ResultCollector& results, const VkSurfaceCapabilitiesKHR& capabilities)
335 {
336 	results.check(capabilities.minImageCount > 0,
337 				  "minImageCount must be larger than 0");
338 
339 	results.check(capabilities.minImageExtent.width > 0 &&
340 				  capabilities.minImageExtent.height > 0,
341 				  "minImageExtent dimensions must be larger than 0");
342 
343 	results.check(capabilities.maxImageExtent.width > 0 &&
344 				  capabilities.maxImageExtent.height > 0,
345 				  "maxImageExtent dimensions must be larger than 0");
346 
347 	results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
348 				  capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
349 				  "maxImageExtent must be larger or equal to minImageExtent");
350 
351 	if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
352 		capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
353 	{
354 		results.check(capabilities.currentExtent.width > 0 &&
355 					  capabilities.currentExtent.height > 0,
356 					  "currentExtent dimensions must be larger than 0");
357 
358 		results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width) &&
359 					  de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height),
360 					  "currentExtent is not in supported extent limits");
361 	}
362 
363 	results.check(capabilities.maxImageArrayLayers > 0,
364 				  "maxImageArrayLayers must be larger than 0");
365 
366 	results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
367 				  "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
368 
369 	results.check(capabilities.supportedTransforms != 0,
370 				  "At least one transform must be supported");
371 
372 	results.check(dePop32(capabilities.currentTransform) != 0,
373 				  "Invalid currentTransform");
374 
375 	results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
376 				  "currentTransform is not supported by surface");
377 
378 	results.check(capabilities.supportedCompositeAlpha != 0,
379 				  "At least one alpha mode must be supported");
380 }
381 
querySurfaceCapabilitiesTest(Context & context,Type wsiType)382 tcu::TestStatus querySurfaceCapabilitiesTest (Context& context, Type wsiType)
383 {
384 	tcu::TestLog&					log						= context.getTestContext().getLog();
385 	tcu::ResultCollector			results					(log);
386 
387 	const InstanceHelper			instHelper				(context, wsiType);
388 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
389 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
390 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
391 
392 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
393 	{
394 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
395 		{
396 			const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
397 																								   physicalDevices[deviceNdx],
398 																								   *surface);
399 
400 			log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
401 
402 			validateSurfaceCapabilities(results, capabilities);
403 		}
404 		// else skip query as surface is not supported by the device
405 	}
406 
407 	return tcu::TestStatus(results.getResult(), results.getMessage());
408 }
409 
validateSurfaceFormats(tcu::ResultCollector & results,Type wsiType,const vector<VkSurfaceFormatKHR> & formats)410 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
411 {
412 	const VkSurfaceFormatKHR*	requiredFormats		= DE_NULL;
413 	size_t						numRequiredFormats	= 0;
414 
415 	if (wsiType == TYPE_ANDROID)
416 	{
417 		static const VkSurfaceFormatKHR s_androidFormats[] =
418 		{
419 			{ VK_FORMAT_R8G8B8A8_UNORM,			VK_COLORSPACE_SRGB_NONLINEAR_KHR	},
420 			{ VK_FORMAT_R8G8B8A8_SRGB,			VK_COLORSPACE_SRGB_NONLINEAR_KHR	},
421 			{ VK_FORMAT_R5G6B5_UNORM_PACK16,	VK_COLORSPACE_SRGB_NONLINEAR_KHR	}
422 		};
423 
424 		requiredFormats		= &s_androidFormats[0];
425 		numRequiredFormats	= DE_LENGTH_OF_ARRAY(s_androidFormats);
426 	}
427 
428 	for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
429 	{
430 		const VkSurfaceFormatKHR&	requiredFormat	= requiredFormats[ndx];
431 
432 		if (!de::contains(formats.begin(), formats.end(), requiredFormat))
433 			results.fail(de::toString(requiredFormat) + " not supported");
434 	}
435 }
436 
querySurfaceFormatsTest(Context & context,Type wsiType)437 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
438 {
439 	tcu::TestLog&					log				= context.getTestContext().getLog();
440 	tcu::ResultCollector			results			(log);
441 
442 	const InstanceHelper			instHelper		(context, wsiType);
443 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
444 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
445 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
446 
447 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
448 	{
449 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
450 		{
451 			const vector<VkSurfaceFormatKHR>	formats	= getPhysicalDeviceSurfaceFormats(instHelper.vki,
452 																						  physicalDevices[deviceNdx],
453 																						  *surface);
454 
455 			log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
456 
457 			validateSurfaceFormats(results, wsiType, formats);
458 		}
459 		// else skip query as surface is not supported by the device
460 	}
461 
462 	return tcu::TestStatus(results.getResult(), results.getMessage());
463 }
464 
validateSurfacePresentModes(tcu::ResultCollector & results,Type wsiType,const vector<VkPresentModeKHR> & modes)465 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
466 {
467 	results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
468 				  "VK_PRESENT_MODE_FIFO_KHR is not supported");
469 
470 	if (wsiType == TYPE_ANDROID)
471 		results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
472 					  "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
473 }
474 
querySurfacePresentModesTest(Context & context,Type wsiType)475 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
476 {
477 	tcu::TestLog&					log				= context.getTestContext().getLog();
478 	tcu::ResultCollector			results			(log);
479 
480 	const InstanceHelper			instHelper		(context, wsiType);
481 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
482 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window));
483 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
484 
485 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
486 	{
487 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
488 		{
489 			const vector<VkPresentModeKHR>	modes	= getPhysicalDeviceSurfacePresentModes(instHelper.vki, physicalDevices[deviceNdx], *surface);
490 
491 			log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
492 
493 			validateSurfacePresentModes(results, wsiType, modes);
494 		}
495 		// else skip query as surface is not supported by the device
496 	}
497 
498 	return tcu::TestStatus(results.getResult(), results.getMessage());
499 }
500 
createSurfaceInitialSizeTest(Context & context,Type wsiType)501 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
502 {
503 	tcu::TestLog&					log				= context.getTestContext().getLog();
504 	tcu::ResultCollector			results			(log);
505 
506 	const InstanceHelper			instHelper		(context, wsiType);
507 
508 	const UniquePtr<Display>		nativeDisplay	(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
509 																   instHelper.supportedExtensions,
510 																   wsiType));
511 
512 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
513 	const UVec2						sizes[]			=
514 	{
515 		UVec2(64, 64),
516 		UVec2(124, 119),
517 		UVec2(256, 512)
518 	};
519 
520 	DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
521 
522 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
523 	{
524 		const UVec2&				testSize		= sizes[sizeNdx];
525 		const UniquePtr<Window>		nativeWindow	(createWindow(*nativeDisplay, tcu::just(testSize)));
526 		const Unique<VkSurfaceKHR>	surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
527 
528 		for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
529 		{
530 			if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
531 			{
532 				const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
533 
534 				// \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
535 				results.check(capabilities.currentExtent.width == testSize.x() &&
536 								capabilities.currentExtent.height == testSize.y(),
537 								"currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
538 			}
539 		}
540 	}
541 
542 	return tcu::TestStatus(results.getResult(), results.getMessage());
543 }
544 
resizeSurfaceTest(Context & context,Type wsiType)545 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
546 {
547 	tcu::TestLog&					log				= context.getTestContext().getLog();
548 	tcu::ResultCollector			results			(log);
549 
550 	const InstanceHelper			instHelper		(context, wsiType);
551 
552 	const UniquePtr<Display>		nativeDisplay	(createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
553 																   instHelper.supportedExtensions,
554 																   wsiType));
555 	UniquePtr<Window>				nativeWindow	(createWindow(*nativeDisplay, tcu::nothing<UVec2>()));
556 
557 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, *instHelper.instance);
558 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, *instHelper.instance, wsiType, *nativeDisplay, *nativeWindow));
559 
560 	const UVec2						sizes[]			=
561 	{
562 		UVec2(64, 64),
563 		UVec2(124, 119),
564 		UVec2(256, 512)
565 	};
566 
567 	DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
568 
569 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
570 	{
571 		const UVec2		testSize	= sizes[sizeNdx];
572 
573 		try
574 		{
575 			nativeWindow->resize(testSize);
576 		}
577 		catch (const tcu::Exception& e)
578 		{
579 			// Make sure all exception types result in a test failure
580 			results.fail(e.getMessage());
581 		}
582 
583 		for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
584 		{
585 			if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
586 			{
587 				const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
588 
589 				// \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
590 				results.check(capabilities.currentExtent.width == testSize.x() &&
591 								capabilities.currentExtent.height == testSize.y(),
592 								"currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
593 			}
594 		}
595 	}
596 
597 	return tcu::TestStatus(results.getResult(), results.getMessage());
598 }
599 
600 } // anonymous
601 
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)602 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
603 {
604 	const PlatformProperties&	platformProperties	= getPlatformProperties(wsiType);
605 
606 	addFunctionCase(testGroup, "create",					"Create surface",						createSurfaceTest,					wsiType);
607 	addFunctionCase(testGroup, "create_custom_allocator",	"Create surface with custom allocator",	createSurfaceCustomAllocatorTest,	wsiType);
608 	addFunctionCase(testGroup, "create_simulate_oom",		"Create surface with simulating OOM",	createSurfaceSimulateOOMTest,		wsiType);
609 	addFunctionCase(testGroup, "query_support",				"Query surface support",				querySurfaceSupportTest,			wsiType);
610 	addFunctionCase(testGroup, "query_capabilities",		"Query surface capabilities",			querySurfaceCapabilitiesTest,		wsiType);
611 	addFunctionCase(testGroup, "query_formats",				"Query surface formats",				querySurfaceFormatsTest,			wsiType);
612 	addFunctionCase(testGroup, "query_present_modes",		"Query surface present modes",			querySurfacePresentModesTest,		wsiType);
613 
614 	if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
615 		addFunctionCase(testGroup, "initial_size",	"Create surface with initial window size set",	createSurfaceInitialSizeTest,	wsiType);
616 
617 	if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
618 		addFunctionCase(testGroup, "resize",		"Resize window and surface",					resizeSurfaceTest,				wsiType);
619 }
620 
621 } // wsi
622 } // vkt
623