• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "vktCustomInstancesDevices.hpp"
29 #include "vktNativeObjectsUtil.hpp"
30 
31 #include "vkDefs.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkStrUtil.hpp"
34 #include "vkRef.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkDeviceUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkWsiPlatform.hpp"
42 #include "vkWsiUtil.hpp"
43 #include "vkAllocationCallbackUtil.hpp"
44 #include "vkQueryUtil.hpp"
45 
46 #include "tcuTestLog.hpp"
47 #include "tcuFormatUtil.hpp"
48 #include "tcuPlatform.hpp"
49 #include "tcuResultCollector.hpp"
50 #include "tcuCommandLine.hpp"
51 
52 #include "deUniquePtr.hpp"
53 #include "deStringUtil.hpp"
54 #include "deMemory.h"
55 
56 namespace vk
57 {
58 
operator !=(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)59 inline bool operator!= (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
60 {
61 	return (a.format != b.format) || (a.colorSpace != b.colorSpace);
62 }
63 
operator ==(const VkSurfaceFormatKHR & a,const VkSurfaceFormatKHR & b)64 inline bool operator== (const VkSurfaceFormatKHR& a, const VkSurfaceFormatKHR& b)
65 {
66 	return !(a != b);
67 }
68 
operator !=(const VkExtent2D & a,const VkExtent2D & b)69 inline bool operator!= (const VkExtent2D& a, const VkExtent2D& b)
70 {
71 	return (a.width != b.width) || (a.height != b.height);
72 }
73 
operator !=(const VkSurfaceCapabilitiesKHR & a,const VkSurfaceCapabilitiesKHR & b)74 inline bool operator!= (const VkSurfaceCapabilitiesKHR& a, const VkSurfaceCapabilitiesKHR& b)
75 {
76 	return (a.minImageCount				!= b.minImageCount)				||
77 		   (a.maxImageCount				!= b.maxImageCount)				||
78 		   (a.currentExtent				!= b.currentExtent)				||
79 		   (a.minImageExtent			!= b.minImageExtent)			||
80 		   (a.maxImageExtent			!= b.maxImageExtent)			||
81 		   (a.maxImageArrayLayers		!= b.maxImageArrayLayers)		||
82 		   (a.supportedTransforms		!= b.supportedTransforms)		||
83 		   (a.currentTransform			!= b.currentTransform)			||
84 		   (a.supportedCompositeAlpha	!= b.supportedCompositeAlpha)	||
85 		   (a.supportedUsageFlags		!= b.supportedUsageFlags);
86 }
87 
88 } // vk
89 
90 namespace vkt
91 {
92 namespace wsi
93 {
94 
95 namespace
96 {
97 
98 using namespace vk;
99 using namespace vk::wsi;
100 
101 using tcu::TestLog;
102 using tcu::Maybe;
103 using tcu::UVec2;
104 
105 using de::MovePtr;
106 using de::UniquePtr;
107 
108 using std::string;
109 using std::vector;
110 
111 enum
112 {
113 	SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC	= 0xffffffff
114 };
115 
116 enum
117 {
118 	GUARD_SIZE										= 0x20,			//!< Number of bytes to check
119 	GUARD_VALUE										= 0xcd,			//!< Data pattern
120 };
121 
122 template<typename T>
123 class CheckIncompleteResult
124 {
125 public:
~CheckIncompleteResult(void)126 	virtual			~CheckIncompleteResult	(void) {}
127 	virtual void	getResult				(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, T* data) = 0;
128 
operator ()(tcu::ResultCollector & results,const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSurfaceKHR surface,const std::size_t expectedCompleteSize)129 	void operator() (tcu::ResultCollector&		results,
130 					 const InstanceInterface&	vki,
131 					 const VkPhysicalDevice		physDevice,
132 					 const VkSurfaceKHR			surface,
133 					 const std::size_t			expectedCompleteSize)
134 	{
135 		if (expectedCompleteSize == 0)
136 			return;
137 
138 		vector<T>		outputData	(expectedCompleteSize);
139 		const deUint32	usedSize	= static_cast<deUint32>(expectedCompleteSize / 3);
140 
141 		ValidateQueryBits::fillBits(outputData.begin(), outputData.end());	// unused entries should have this pattern intact
142 		m_count		= usedSize;
143 		m_result	= VK_SUCCESS;
144 
145 		getResult(vki, physDevice, surface, &outputData[0]);				// update m_count and m_result
146 
147 		if (m_count != usedSize || m_result != VK_INCOMPLETE || !ValidateQueryBits::checkBits(outputData.begin() + m_count, outputData.end()))
148 			results.fail("Query didn't return VK_INCOMPLETE");
149 	}
150 
151 protected:
152 	deUint32	m_count;
153 	VkResult	m_result;
154 };
155 
156 struct CheckPhysicalDeviceSurfaceFormatsIncompleteResult : public CheckIncompleteResult<VkSurfaceFormatKHR>
157 {
getResultvkt::wsi::__anon25bf98310111::CheckPhysicalDeviceSurfaceFormatsIncompleteResult158 	void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkSurfaceFormatKHR* data)
159 	{
160 		m_result = vki.getPhysicalDeviceSurfaceFormatsKHR(physDevice, surface, &m_count, data);
161 	}
162 };
163 
164 struct CheckPhysicalDeviceSurfacePresentModesIncompleteResult : public CheckIncompleteResult<VkPresentModeKHR>
165 {
getResultvkt::wsi::__anon25bf98310111::CheckPhysicalDeviceSurfacePresentModesIncompleteResult166 	void getResult (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSurfaceKHR surface, VkPresentModeKHR* data)
167 	{
168 		m_result = vki.getPhysicalDeviceSurfacePresentModesKHR(physDevice, surface, &m_count, data);
169 	}
170 };
171 
172 typedef vector<VkExtensionProperties> Extensions;
173 
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)174 CustomInstance createInstanceWithWsi (Context&						context,
175 									  Type							wsiType,
176 									  const vector<string>			extraExtensions,
177 									  const VkAllocationCallbacks*	pAllocator	= DE_NULL)
178 {
179 	const deUint32	version		= context.getUsedApiVersion();
180 	vector<string>	extensions	= extraExtensions;
181 
182 	extensions.push_back("VK_KHR_surface");
183 	extensions.push_back(getExtensionName(wsiType));
184 	if (isDisplaySurface(wsiType))
185 		extensions.push_back("VK_KHR_display");
186 
187 	vector<string>	instanceExtensions;
188 	for (const auto& ext : extensions)
189 	{
190 		if (!context.isInstanceFunctionalitySupported(ext))
191 			TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
192 
193 		if (!isCoreInstanceExtension(version, ext))
194 			instanceExtensions.push_back(ext);
195 	}
196 
197 	return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
198 }
199 
200 struct InstanceHelper
201 {
202 	const vector<VkExtensionProperties>	supportedExtensions;
203 	CustomInstance						instance;
204 	const InstanceDriver&				vki;
205 
InstanceHelpervkt::wsi::__anon25bf98310111::InstanceHelper206 	InstanceHelper (Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
207 		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
208 																	  DE_NULL))
209 		, instance				(createInstanceWithWsi(context,
210 													   wsiType,
211 													   vector<string>(),
212 													   pAllocator))
213 		, vki					(instance.getDriver())
214 	{}
215 
InstanceHelpervkt::wsi::__anon25bf98310111::InstanceHelper216 	InstanceHelper (Context& context, Type wsiType, const vector<string>& extensions, const VkAllocationCallbacks* pAllocator = DE_NULL)
217 		: supportedExtensions	(enumerateInstanceExtensionProperties(context.getPlatformInterface(),
218 																	  DE_NULL))
219 		, instance				(createInstanceWithWsi(context,
220 													   wsiType,
221 													   extensions,
222 													   pAllocator))
223 		, vki					(instance.getDriver())
224 	{}
225 };
226 
createSurfaceTest(Context & context,Type wsiType)227 tcu::TestStatus createSurfaceTest (Context& context, Type wsiType)
228 {
229 	const InstanceHelper		instHelper	(context, wsiType);
230 	const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
231 	const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
232 
233 	return tcu::TestStatus::pass("Creating surface succeeded");
234 }
235 
querySurfaceCounterTest(Context & context,Type wsiType)236 tcu::TestStatus querySurfaceCounterTest (Context& context, Type wsiType)
237 {
238 	const InstanceHelper			instHelper		(context, wsiType);
239 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
240 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
241 	const vk::InstanceInterface&	vki				= context.getInstanceInterface();
242 	const vk::VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
243 	const bool						isDisplay		= isDisplaySurface(wsiType);
244 
245 	if (!isInstanceExtensionSupported(context.getUsedApiVersion(), context.getInstanceExtensions(), "VK_EXT_display_surface_counter"))
246 		TCU_THROW(NotSupportedError, "VK_EXT_display_surface_counter not supported");
247 
248 	const vk::VkSurfaceCapabilities2EXT	capsExt = getPhysicalDeviceSurfaceCapabilities2EXT	(vki, physicalDevice, surface.get());
249 	const vk::VkSurfaceCapabilitiesKHR	capsKhr = getPhysicalDeviceSurfaceCapabilities		(vki, physicalDevice, surface.get());
250 
251 	if (!sameSurfaceCapabilities(capsKhr, capsExt))
252 	{
253 		return tcu::TestStatus::fail("KHR and EXT surface capabilities do not match");
254 	}
255 
256 	if (!isDisplay && capsExt.supportedSurfaceCounters != 0)
257 	{
258 		return tcu::TestStatus::fail("supportedSurfaceCounters nonzero (" + de::toString(capsExt.supportedSurfaceCounters) + ") for non-display surface");
259 	}
260 
261 	return tcu::TestStatus::pass("Pass");
262 }
263 
createSurfaceCustomAllocatorTest(Context & context,Type wsiType)264 tcu::TestStatus createSurfaceCustomAllocatorTest (Context& context, Type wsiType)
265 {
266 	AllocationCallbackRecorder	allocationRecorder	(getSystemAllocator());
267 	tcu::TestLog&				log					= context.getTestContext().getLog();
268 
269 	{
270 		const InstanceHelper		instHelper	(context, wsiType, allocationRecorder.getCallbacks());
271 		const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
272 		const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki,
273 															   instHelper.instance,
274 															   wsiType,
275 															   native.getDisplay(),
276 															   native.getWindow(),
277 															   context.getTestContext().getCommandLine(),
278 															   allocationRecorder.getCallbacks()));
279 
280 		if (!validateAndLog(log,
281 							allocationRecorder,
282 							(1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)		|
283 							(1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
284 			return tcu::TestStatus::fail("Detected invalid system allocation callback");
285 	}
286 
287 	if (!validateAndLog(log, allocationRecorder, 0u))
288 		return tcu::TestStatus::fail("Detected invalid system allocation callback");
289 
290 	if (allocationRecorder.getRecordsBegin() == allocationRecorder.getRecordsEnd())
291 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
292 	else
293 		return tcu::TestStatus::pass("Creating surface succeeded using custom allocator");
294 }
295 
createSurfaceSimulateOOMTest(Context & context,Type wsiType)296 tcu::TestStatus createSurfaceSimulateOOMTest (Context& context, Type wsiType)
297 {
298 	tcu::TestLog&	log	= context.getTestContext().getLog();
299 
300 	for (deUint32 numPassingAllocs = 0; numPassingAllocs <= 1024u; ++numPassingAllocs)
301 	{
302 		AllocationCallbackRecorder	allocationRecorder	(getSystemAllocator());
303 		DeterministicFailAllocator	failingAllocator	(allocationRecorder.getCallbacks(),
304 														 DeterministicFailAllocator::MODE_DO_NOT_COUNT,
305 														 0);
306 		bool						gotOOM				= false;
307 
308 		log << TestLog::Message << "Testing with " << numPassingAllocs << " first allocations succeeding" << TestLog::EndMessage;
309 
310 		try
311 		{
312 			const InstanceHelper		instHelper	(context, wsiType, failingAllocator.getCallbacks());
313 
314 			// OOM is not simulated for VkInstance as we don't want to spend time
315 			// testing OOM paths inside instance creation.
316 			failingAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
317 
318 			const NativeObjects			native		(context, instHelper.supportedExtensions, wsiType);
319 			const Unique<VkSurfaceKHR>	surface		(createSurface(instHelper.vki,
320 																   instHelper.instance,
321 																   wsiType,
322 																   native.getDisplay(),
323 																   native.getWindow(),
324 																   context.getTestContext().getCommandLine(),
325 																   failingAllocator.getCallbacks()));
326 
327 			if (!validateAndLog(log,
328 								allocationRecorder,
329 								(1u<<VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)		|
330 								(1u<<VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)))
331 				return tcu::TestStatus::fail("Detected invalid system allocation callback");
332 		}
333 		catch (const OutOfMemoryError& e)
334 		{
335 			log << TestLog::Message << "Got " << e.getError() << TestLog::EndMessage;
336 			gotOOM = true;
337 		}
338 
339 		if (!validateAndLog(log, allocationRecorder, 0u))
340 			return tcu::TestStatus::fail("Detected invalid system allocation callback");
341 
342 		if (!gotOOM)
343 		{
344 			log << TestLog::Message << "Creating surface succeeded!" << TestLog::EndMessage;
345 
346 			if (numPassingAllocs == 0)
347 				return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks were not used");
348 			else
349 				return tcu::TestStatus::pass("OOM simulation completed");
350 		}
351 	}
352 
353 	return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Creating surface did not succeed, callback limit exceeded");
354 }
355 
getNumQueueFamilies(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)356 deUint32 getNumQueueFamilies (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
357 {
358 	deUint32	numFamilies		= 0;
359 
360 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL);
361 
362 	return numFamilies;
363 }
364 
querySurfaceSupportTest(Context & context,Type wsiType)365 tcu::TestStatus querySurfaceSupportTest (Context& context, Type wsiType)
366 {
367 	tcu::TestLog&					log						= context.getTestContext().getLog();
368 	tcu::ResultCollector			results					(log);
369 
370 	const InstanceHelper			instHelper				(context, wsiType);
371 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
372 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
373 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
374 
375 	// On Android surface must be supported by all devices and queue families
376 	const bool						expectSupportedOnAll	= wsiType == TYPE_ANDROID;
377 
378 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
379 	{
380 		const VkPhysicalDevice		physicalDevice		= physicalDevices[deviceNdx];
381 		const deUint32				numQueueFamilies	= getNumQueueFamilies(instHelper.vki, physicalDevice);
382 
383 		for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
384 		{
385 			const VkBool32	isSupported		= getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
386 
387 			log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": "
388 									<< (isSupported == VK_FALSE ? "NOT " : "") << "supported"
389 				<< TestLog::EndMessage;
390 
391 			if (expectSupportedOnAll && !isSupported)
392 				results.fail("Surface must be supported by all devices and queue families");
393 		}
394 	}
395 
396 	return tcu::TestStatus(results.getResult(), results.getMessage());
397 }
398 
queryPresentationSupportTest(Context & context,Type wsiType)399 tcu::TestStatus queryPresentationSupportTest(Context& context, Type wsiType)
400 {
401 	// There is no implementation of getPhysicalDevicePresentationSupport for DRM.
402 	if (wsiType == TYPE_DIRECT_DRM) {
403 		TCU_THROW(NotSupportedError, "No presentation support query for Drm.");
404 	}
405 
406 	tcu::TestLog&					log						= context.getTestContext().getLog();
407 	tcu::ResultCollector			results					(log);
408 
409 	const InstanceHelper			instHelper				(context, wsiType);
410 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
411 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
412 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
413 
414 	native.getDisplay();
415 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
416 	{
417 		const VkPhysicalDevice		physicalDevice		= physicalDevices[deviceNdx];
418 		const deUint32				numQueueFamilies	= getNumQueueFamilies(instHelper.vki, physicalDevice);
419 
420 		for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
421 		{
422 			VkBool32	isPresentationSupported	= getPhysicalDevicePresentationSupport(instHelper.vki, physicalDevice, queueFamilyNdx, wsiType, native.getDisplay());
423 			VkBool32	isSurfaceSupported		= getPhysicalDeviceSurfaceSupport(instHelper.vki, physicalDevice, queueFamilyNdx, *surface);
424 
425 			log << TestLog::Message << "Device " << deviceNdx << ", queue family " << queueFamilyNdx << ": presentation "
426 									<< (isPresentationSupported == VK_FALSE ? "NOT " : "") << "supported. Surface "
427 									<< (isSurfaceSupported == VK_FALSE ? "NOT " : "") << "supported."
428 				<< TestLog::EndMessage;
429 
430 			if (isPresentationSupported != isSurfaceSupported)
431 				results.fail("Presentation support is different from surface support");
432 		}
433 	}
434 
435 	return tcu::TestStatus(results.getResult(), results.getMessage());
436 }
437 
isSupportedByAnyQueue(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)438 bool isSupportedByAnyQueue (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
439 {
440 	const deUint32	numQueueFamilies	= getNumQueueFamilies(vki, physicalDevice);
441 
442 	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numQueueFamilies; ++queueFamilyNdx)
443 	{
444 		if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
445 			return true;
446 	}
447 
448 	return false;
449 }
450 
validateSurfaceCapabilities(tcu::ResultCollector & results,const VkSurfaceCapabilitiesKHR & capabilities)451 void validateSurfaceCapabilities (tcu::ResultCollector& results, const VkSurfaceCapabilitiesKHR& capabilities)
452 {
453 	results.check(capabilities.minImageCount > 0,
454 				  "minImageCount must be larger than 0");
455 
456 	results.check(capabilities.minImageExtent.width > 0 &&
457 				  capabilities.minImageExtent.height > 0,
458 				  "minImageExtent dimensions must be larger than 0");
459 
460 	results.check(capabilities.maxImageExtent.width > 0 &&
461 				  capabilities.maxImageExtent.height > 0,
462 				  "maxImageExtent dimensions must be larger than 0");
463 
464 	results.check(capabilities.minImageExtent.width <= capabilities.maxImageExtent.width &&
465 				  capabilities.minImageExtent.height <= capabilities.maxImageExtent.height,
466 				  "maxImageExtent must be larger or equal to minImageExtent");
467 
468 	if (capabilities.currentExtent.width != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC ||
469 		capabilities.currentExtent.height != SURFACE_EXTENT_DETERMINED_BY_SWAPCHAIN_MAGIC)
470 	{
471 		results.check(capabilities.currentExtent.width > 0 &&
472 					  capabilities.currentExtent.height > 0,
473 					  "currentExtent dimensions must be larger than 0");
474 
475 		results.check(de::inRange(capabilities.currentExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width) &&
476 					  de::inRange(capabilities.currentExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height),
477 					  "currentExtent is not in supported extent limits");
478 	}
479 
480 	results.check(capabilities.maxImageArrayLayers > 0,
481 				  "maxImageArrayLayers must be larger than 0");
482 
483 	results.check((capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
484 				  "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT must be set in supportedUsageFlags");
485 
486 	results.check(capabilities.supportedTransforms != 0,
487 				  "At least one transform must be supported");
488 
489 	results.check(dePop32(capabilities.currentTransform) != 0,
490 				  "Invalid currentTransform");
491 
492 	results.check((capabilities.supportedTransforms & capabilities.currentTransform) != 0,
493 				  "currentTransform is not supported by surface");
494 
495 	results.check(capabilities.supportedCompositeAlpha != 0,
496 				  "At least one alpha mode must be supported");
497 }
498 
querySurfaceCapabilitiesTest(Context & context,Type wsiType)499 tcu::TestStatus querySurfaceCapabilitiesTest (Context& context, Type wsiType)
500 {
501 	tcu::TestLog&					log						= context.getTestContext().getLog();
502 	tcu::ResultCollector			results					(log);
503 
504 	const InstanceHelper			instHelper				(context, wsiType);
505 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
506 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
507 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
508 
509 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
510 	{
511 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
512 		{
513 			const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
514 																								   physicalDevices[deviceNdx],
515 																								   *surface);
516 
517 			log << TestLog::Message << "Device " << deviceNdx << ": " << capabilities << TestLog::EndMessage;
518 
519 			validateSurfaceCapabilities(results, capabilities);
520 		}
521 		// else skip query as surface is not supported by the device
522 	}
523 
524 	return tcu::TestStatus(results.getResult(), results.getMessage());
525 }
526 
querySurfaceCapabilities2Test(Context & context,Type wsiType)527 tcu::TestStatus querySurfaceCapabilities2Test (Context& context, Type wsiType)
528 {
529 	tcu::TestLog&					log						= context.getTestContext().getLog();
530 	tcu::ResultCollector			results					(log);
531 
532 	const InstanceHelper			instHelper				(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
533 	const NativeObjects				native					(context, instHelper.supportedExtensions, wsiType);
534 	const Unique<VkSurfaceKHR>		surface					(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
535 	const vector<VkPhysicalDevice>	physicalDevices			= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
536 
537 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
538 	{
539 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
540 		{
541 			const VkSurfaceCapabilitiesKHR	refCapabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki,
542 																								   physicalDevices[deviceNdx],
543 																								   *surface);
544 			VkSurfaceCapabilities2KHR		extCapabilities;
545 
546 			deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
547 			extCapabilities.sType	= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
548 			extCapabilities.pNext	= DE_NULL;
549 
550 			{
551 				const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo	=
552 				{
553 					VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
554 					DE_NULL,
555 					*surface
556 				};
557 				VkPhysicalDeviceSurfaceInfo2KHR			infoCopy;
558 
559 				deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
560 
561 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
562 
563 				results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
564 			}
565 
566 			results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
567 						  extCapabilities.pNext == DE_NULL,
568 						  "sType/pNext modified");
569 
570 			if (refCapabilities != extCapabilities.surfaceCapabilities)
571 			{
572 				log << TestLog::Message
573 					<< "Device " << deviceNdx
574 					<< ": expected " << refCapabilities
575 					<< ", got " << extCapabilities.surfaceCapabilities
576 					<< TestLog::EndMessage;
577 				results.fail("Mismatch between VK_KHR_surface and VK_KHR_surface2 query results");
578 			}
579 		}
580 	}
581 
582 	return tcu::TestStatus(results.getResult(), results.getMessage());
583 }
584 
querySurfaceProtectedCapabilitiesTest(Context & context,Type wsiType)585 tcu::TestStatus querySurfaceProtectedCapabilitiesTest (Context& context, Type wsiType)
586 {
587 	tcu::TestLog&			log			= context.getTestContext().getLog();
588 	tcu::ResultCollector		results			(log);
589 
590 	vector<string>			requiredExtensions;
591 	requiredExtensions.push_back("VK_KHR_get_surface_capabilities2");
592 	requiredExtensions.push_back("VK_KHR_surface_protected_capabilities");
593 	const InstanceHelper		instHelper		(context, wsiType, requiredExtensions);
594 	const NativeObjects		native			(context, instHelper.supportedExtensions, wsiType);
595 	const Unique<VkSurfaceKHR>	surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
596 	const vector<VkPhysicalDevice>	physicalDevices		= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
597 
598 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
599 	{
600 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
601 		{
602 			VkSurfaceCapabilities2KHR		extCapabilities;
603 			VkSurfaceProtectedCapabilitiesKHR	extProtectedCapabilities;
604 
605 			deMemset(&extProtectedCapabilities, 0xcd, sizeof(VkSurfaceProtectedCapabilitiesKHR));
606 			extProtectedCapabilities.sType		= VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR;
607 			extProtectedCapabilities.pNext		= DE_NULL;
608 
609 			deMemset(&extCapabilities, 0xcd, sizeof(VkSurfaceCapabilities2KHR));
610 			extCapabilities.sType	= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
611 			extCapabilities.pNext	= &extProtectedCapabilities;
612 
613 			{
614 				VkPhysicalDeviceSurfaceInfo2KHR		infoCopy;
615 				const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo =
616 				{
617 					VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
618 					DE_NULL,
619 					*surface
620 				};
621 
622 
623 				deMemcpy(&infoCopy, &surfaceInfo, sizeof(VkPhysicalDeviceSurfaceInfo2KHR));
624 
625 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(physicalDevices[deviceNdx], &surfaceInfo, &extCapabilities));
626 
627 				results.check(deMemoryEqual(&surfaceInfo, &infoCopy, sizeof(VkPhysicalDeviceSurfaceInfo2KHR)) == DE_TRUE, "Driver wrote into input struct");
628 			}
629 
630 			results.check(extCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR &&
631 					extCapabilities.pNext == &extProtectedCapabilities,
632 					"sType/pNext modified");
633 
634 			results.check(extProtectedCapabilities.sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
635 					extProtectedCapabilities.pNext == DE_NULL,
636 					"sType/pNext modified");
637 
638 			results.check(extProtectedCapabilities.supportsProtected == 0 ||
639 					extProtectedCapabilities.supportsProtected == 1,
640 					"supportsProtected ");
641 		}
642 	}
643 
644 	return tcu::TestStatus(results.getResult(), results.getMessage());
645 }
646 
validateSurfaceFormats(tcu::ResultCollector & results,Type wsiType,const vector<VkSurfaceFormatKHR> & formats)647 void validateSurfaceFormats (tcu::ResultCollector& results, Type wsiType, const vector<VkSurfaceFormatKHR>& formats)
648 {
649 	const VkSurfaceFormatKHR*	requiredFormats		= DE_NULL;
650 	size_t						numRequiredFormats	= 0;
651 
652 	if (wsiType == TYPE_ANDROID)
653 	{
654 		static const VkSurfaceFormatKHR s_androidFormats[] =
655 		{
656 			{ VK_FORMAT_R8G8B8A8_UNORM,			VK_COLOR_SPACE_SRGB_NONLINEAR_KHR	},
657 			{ VK_FORMAT_R8G8B8A8_SRGB,			VK_COLOR_SPACE_SRGB_NONLINEAR_KHR	},
658 			{ VK_FORMAT_R5G6B5_UNORM_PACK16,	VK_COLOR_SPACE_SRGB_NONLINEAR_KHR	}
659 		};
660 
661 		requiredFormats		= &s_androidFormats[0];
662 		numRequiredFormats	= DE_LENGTH_OF_ARRAY(s_androidFormats);
663 	}
664 
665 	for (size_t ndx = 0; ndx < numRequiredFormats; ++ndx)
666 	{
667 		const VkSurfaceFormatKHR&	requiredFormat	= requiredFormats[ndx];
668 
669 		if (!de::contains(formats.begin(), formats.end(), requiredFormat))
670 			results.fail(de::toString(requiredFormat) + " not supported");
671 	}
672 
673 	// Check that there are no duplicates
674 	for (size_t ndx = 1; ndx < formats.size(); ++ndx)
675 	{
676 		if (de::contains(formats.begin(), formats.begin() + ndx, formats[ndx]))
677 			results.fail("Found duplicate entry " + de::toString(formats[ndx]));
678 	}
679 }
680 
querySurfaceFormatsTest(Context & context,Type wsiType)681 tcu::TestStatus querySurfaceFormatsTest (Context& context, Type wsiType)
682 {
683 	tcu::TestLog&					log				= context.getTestContext().getLog();
684 	tcu::ResultCollector			results			(log);
685 
686 	const InstanceHelper			instHelper		(context, wsiType);
687 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
688 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
689 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
690 
691 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
692 	{
693 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
694 		{
695 			deUint32	numFormats = 0;
696 
697 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, DE_NULL));
698 
699 			std::vector<VkSurfaceFormatKHR>	formats	(numFormats + 1);
700 
701 			if (numFormats > 0)
702 			{
703 				const deUint32 numFormatsOrig = numFormats;
704 
705 				// check if below call properly overwrites formats count
706 				numFormats++;
707 
708 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormats, &formats[0]));
709 
710 				if (numFormats != numFormatsOrig)
711 					results.fail("Format count changed between calls");
712 			}
713 
714 			formats.pop_back();
715 
716 			log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(formats.begin(), formats.end()) << TestLog::EndMessage;
717 
718 			validateSurfaceFormats(results, wsiType, formats);
719 			CheckPhysicalDeviceSurfaceFormatsIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, formats.size());
720 		}
721 		// else skip query as surface is not supported by the device
722 	}
723 
724 	return tcu::TestStatus(results.getResult(), results.getMessage());
725 }
726 
querySurfaceFormatsTestSurfaceless(Context & context,Type wsiType)727 tcu::TestStatus querySurfaceFormatsTestSurfaceless (Context& context, Type wsiType)
728 {
729 	tcu::TestLog&					log				= context.getTestContext().getLog();
730 	tcu::ResultCollector			results			(log);
731 
732 	const InstanceHelper			instHelper		(context, wsiType, vector<string>(1, string("VK_GOOGLE_surfaceless_query")));
733 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
734 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
735 	const VkSurfaceKHR				nullSurface		= 0;
736 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
737 
738 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
739 	{
740 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
741 		{
742 			deUint32	numFormatsSurface = 0;
743 			deUint32	numFormatsNull = 0;
744 
745 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormatsSurface, DE_NULL));
746 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface, &numFormatsNull, DE_NULL));
747 
748 			if (numFormatsSurface != numFormatsNull)
749 			{
750 				results.fail("Number of formats do not match");
751 				continue;
752 			}
753 
754 			std::vector<VkSurfaceFormatKHR>	formatsSurface(numFormatsSurface + 1);
755 			std::vector<VkSurfaceFormatKHR>	formatsNull(numFormatsSurface + 1);
756 
757 			if (numFormatsSurface > 0)
758 			{
759 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], *surface, &numFormatsSurface, &formatsSurface[0]));
760 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevices[deviceNdx], nullSurface, &numFormatsSurface, &formatsNull[0]));
761 			}
762 
763 			formatsSurface.pop_back();
764 			formatsNull.pop_back();
765 
766 			for (deUint32 i = 0; i < numFormatsSurface; i++)
767 			{
768 				if (formatsSurface[i].colorSpace != formatsNull[i].colorSpace ||
769 					formatsSurface[i].format     != formatsNull[i].format)
770 				{
771 					results.fail("Surface formats do not match");
772 				}
773 			}
774 		}
775 	}
776 
777 	return tcu::TestStatus(results.getResult(), results.getMessage());
778 }
779 
querySurfaceFormats2Test(Context & context,Type wsiType)780 tcu::TestStatus querySurfaceFormats2Test (Context& context, Type wsiType)
781 {
782 	tcu::TestLog&					log				= context.getTestContext().getLog();
783 	tcu::ResultCollector			results			(log);
784 
785 	const InstanceHelper			instHelper		(context, wsiType, vector<string>(1, string("VK_KHR_get_surface_capabilities2")));
786 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
787 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
788 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
789 
790 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
791 	{
792 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
793 		{
794 			const vector<VkSurfaceFormatKHR>		refFormats	= getPhysicalDeviceSurfaceFormats(instHelper.vki,
795 																								  physicalDevices[deviceNdx],
796 																								  *surface);
797 			const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo	=
798 			{
799 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
800 				DE_NULL,
801 				*surface
802 			};
803 			deUint32								numFormats	= 0;
804 
805 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, DE_NULL));
806 
807 			if ((size_t)numFormats != refFormats.size())
808 				results.fail("vkGetPhysicalDeviceSurfaceFormats2KHR() returned different number of formats");
809 
810 			if (numFormats > 0)
811 			{
812 				vector<VkSurfaceFormat2KHR>	formats	(numFormats + 1);
813 
814 				for (size_t ndx = 0; ndx < formats.size(); ++ndx)
815 				{
816 					formats[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
817 					formats[ndx].pNext = DE_NULL;
818 				}
819 
820 				const deUint32 numFormatsOrig = numFormats;
821 
822 				// check if below call properly overwrites formats count
823 				numFormats++;
824 
825 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormats, &formats[0]));
826 
827 				if ((size_t)numFormats != numFormatsOrig)
828 					results.fail("Format count changed between calls");
829 
830 				formats.pop_back();
831 
832 				{
833 					vector<VkSurfaceFormatKHR>	extFormats	(formats.size());
834 
835 					for (size_t ndx = 0; ndx < formats.size(); ++ndx)
836 					{
837 						results.check(formats[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
838 									  formats[ndx].pNext == DE_NULL,
839 									  "sType/pNext modified");
840 						extFormats[ndx] = formats[ndx].surfaceFormat;
841 					}
842 
843 					for (size_t ndx = 0; ndx < refFormats.size(); ++ndx)
844 					{
845 						if (!de::contains(extFormats.begin(), extFormats.end(), refFormats[ndx]))
846 							results.fail(de::toString(refFormats[ndx]) + " missing from extended query");
847 					}
848 				}
849 
850 				// Check VK_INCOMPLETE
851 				{
852 					vector<VkSurfaceFormat2KHR>	formatsClone	(formats);
853 					deUint32					numToSupply		= numFormats/2;
854 					VkResult					queryResult;
855 
856 					ValidateQueryBits::fillBits(formatsClone.begin() + numToSupply, formatsClone.end());
857 
858 					queryResult = instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numToSupply, &formatsClone[0]);
859 
860 					results.check(queryResult == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
861 					results.check(ValidateQueryBits::checkBits(formatsClone.begin() + numToSupply, formatsClone.end()),
862 								  "Driver wrote past last element");
863 
864 					for (size_t ndx = 0; ndx < (size_t)numToSupply; ++ndx)
865 					{
866 						results.check(formatsClone[ndx].sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR &&
867 									  formatsClone[ndx].pNext == DE_NULL &&
868 									  formatsClone[ndx].surfaceFormat == formats[ndx].surfaceFormat,
869 									  "Returned element " + de::toString(ndx) + " is different");
870 					}
871 				}
872 			}
873 		}
874 		// else skip query as surface is not supported by the device
875 	}
876 
877 	return tcu::TestStatus(results.getResult(), results.getMessage());
878 }
879 
validateSurfacePresentModes(tcu::ResultCollector & results,Type wsiType,const vector<VkPresentModeKHR> & modes)880 void validateSurfacePresentModes (tcu::ResultCollector& results, Type wsiType, const vector<VkPresentModeKHR>& modes)
881 {
882 	results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_FIFO_KHR),
883 				  "VK_PRESENT_MODE_FIFO_KHR is not supported");
884 
885 	if (wsiType == TYPE_ANDROID)
886 		results.check(de::contains(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR),
887 					  "VK_PRESENT_MODE_MAILBOX_KHR is not supported");
888 }
889 
querySurfacePresentModes2Test(Context & context,Type wsiType)890 tcu::TestStatus querySurfacePresentModes2Test (Context& context, Type wsiType)
891 {
892 	tcu::TestLog&					log				= context.getTestContext().getLog();
893 	tcu::ResultCollector			results			(log);
894 
895 	const InstanceHelper			instHelper		(context, wsiType);
896 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
897 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
898 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
899 	const std::vector<VkExtensionProperties>	deviceExtensions(enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
900 	if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
901 		TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
902 
903 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
904 	{
905 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
906 		{
907 			const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo =
908 			{
909 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
910 				DE_NULL,
911 				*surface
912 			};
913 
914 			deUint32	numModesRef = 0;
915 			deUint32	numModes    = 0;
916 
917 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModesRef, DE_NULL));
918 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo, &numModes, DE_NULL));
919 
920 			if (numModes != numModesRef)
921 			{
922 				results.fail("Number of modes do not match");
923 				continue;
924 			}
925 
926 			vector<VkPresentModeKHR>	modes	(numModes + 1);
927 
928 			if (numModes > 0)
929 			{
930 				const deUint32 numModesOrig = numModes;
931 
932 				// check if below call properly overwrites mode count
933 				numModes++;
934 
935 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo, &numModes, &modes[0]));
936 
937 				if ((size_t)numModes != numModesOrig)
938 					TCU_FAIL("Mode count changed between calls");
939 			}
940 
941 			modes.pop_back();
942 
943 			log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
944 
945 			validateSurfacePresentModes(results, wsiType, modes);
946 			if (numModes > 1)
947 			{
948 				numModes /= 2;
949 				vk::VkResult res = instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo, &numModes, &modes[0]);
950 				if (res != VK_INCOMPLETE)
951 					TCU_FAIL("Failed to fetch incomplete results");
952 			}
953 		}
954 		// else skip query as surface is not supported by the device
955 	}
956 
957 	return tcu::TestStatus(results.getResult(), results.getMessage());
958 }
959 
querySurfacePresentModes2TestSurfaceless(Context & context,Type wsiType)960 tcu::TestStatus querySurfacePresentModes2TestSurfaceless (Context& context, Type wsiType)
961 {
962 	tcu::TestLog&					log				= context.getTestContext().getLog();
963 	tcu::ResultCollector			results			(log);
964 
965 	const InstanceHelper			instHelper		(context, wsiType, vector<string>(1, string("VK_GOOGLE_surfaceless_query")));
966 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
967 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
968 	const VkSurfaceKHR				nullSurface		= 0;
969 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
970 	const std::vector<VkExtensionProperties>	deviceExtensions(enumerateDeviceExtensionProperties(instHelper.vki, context.getPhysicalDevice(), DE_NULL));
971 	if (!isExtensionStructSupported(deviceExtensions, RequiredExtension("VK_EXT_full_screen_exclusive")))
972 		TCU_THROW(NotSupportedError, "Extension VK_EXT_full_screen_exclusive not supported");
973 
974 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
975 	{
976 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
977 		{
978 			const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo =
979 			{
980 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
981 				DE_NULL,
982 				*surface
983 			};
984 			const VkPhysicalDeviceSurfaceInfo2KHR	nullSurfaceInfo =
985 			{
986 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
987 				DE_NULL,
988 				nullSurface
989 			};
990 			deUint32	numModesSurface = 0;
991 			deUint32	numModesNull	= 0;
992 
993 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo, &numModesSurface, DE_NULL));
994 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo, &numModesNull, DE_NULL));
995 
996 			if (numModesSurface != numModesNull)
997 			{
998 				results.fail("Number of modes does not match");
999 				continue;
1000 			}
1001 
1002 			vector<VkPresentModeKHR>	modesSurface(numModesSurface + 1);
1003 			vector<VkPresentModeKHR>	modesNull(numModesSurface + 1);
1004 
1005 			if (numModesSurface > 0)
1006 			{
1007 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &surfaceInfo, &numModesSurface, &modesSurface[0]));
1008 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModes2EXT(physicalDevices[deviceNdx], &nullSurfaceInfo, &numModesSurface, &modesNull[0]));
1009 			}
1010 
1011 			modesSurface.pop_back();
1012 			modesNull.pop_back();
1013 
1014 			for (deUint32 i = 0; i < modesSurface.size(); i++)
1015 			{
1016 				if (modesSurface[i] != modesNull[i])
1017 				{
1018 					results.fail("Present modes mismatch");
1019 				}
1020 			}
1021 		}
1022 	}
1023 
1024 	return tcu::TestStatus(results.getResult(), results.getMessage());
1025 }
1026 
querySurfaceFormats2TestSurfaceless(Context & context,Type wsiType)1027 tcu::TestStatus querySurfaceFormats2TestSurfaceless (Context& context, Type wsiType)
1028 {
1029 	tcu::TestLog&					log				= context.getTestContext().getLog();
1030 	tcu::ResultCollector			results			(log);
1031 
1032 	const vector<std::string>		extensions		({"VK_KHR_get_surface_capabilities2", "VK_GOOGLE_surfaceless_query"});
1033 	const InstanceHelper			instHelper		(context, wsiType, extensions );
1034 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
1035 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1036 	const VkSurfaceKHR				nullSurface		= 0;
1037 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1038 
1039 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1040 	{
1041 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1042 		{
1043 			const VkPhysicalDeviceSurfaceInfo2KHR	surfaceInfo =
1044 			{
1045 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1046 				DE_NULL,
1047 				*surface
1048 			};
1049 			const VkPhysicalDeviceSurfaceInfo2KHR	nullSurfaceInfo =
1050 			{
1051 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
1052 				DE_NULL,
1053 				nullSurface
1054 			};
1055 			deUint32								numFormatsSurface = 0;
1056 			deUint32								numFormatsNull    = 0;
1057 
1058 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormatsSurface, DE_NULL));
1059 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsNull, DE_NULL));
1060 
1061 			if (numFormatsSurface != numFormatsNull)
1062 			{
1063 				results.fail("Number of formats do not match");
1064 				continue;
1065 			}
1066 
1067 			if (numFormatsSurface > 0)
1068 			{
1069 				vector<VkSurfaceFormat2KHR>	formatsSurface(numFormatsSurface + 1);
1070 				vector<VkSurfaceFormat2KHR>	formatsNull(numFormatsSurface + 1);
1071 
1072 				for (size_t ndx = 0; ndx < formatsSurface.size(); ++ndx)
1073 				{
1074 					formatsSurface[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1075 					formatsSurface[ndx].pNext = DE_NULL;
1076 					formatsNull[ndx].sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
1077 					formatsNull[ndx].pNext = DE_NULL;
1078 				}
1079 
1080 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &surfaceInfo, &numFormatsSurface, &formatsSurface[0]));
1081 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(physicalDevices[deviceNdx], &nullSurfaceInfo, &numFormatsSurface, &formatsNull[0]));
1082 
1083 				formatsSurface.pop_back();
1084 				formatsNull.pop_back();
1085 
1086 				for (deUint32 i = 0; i < numFormatsSurface; i++)
1087 				{
1088 					if (formatsSurface[i].surfaceFormat != formatsNull[i].surfaceFormat)
1089 					{
1090 						results.fail("Surface formats do not match");
1091 					}
1092 				}
1093 			}
1094 		}
1095 	}
1096 
1097 	return tcu::TestStatus(results.getResult(), results.getMessage());
1098 }
1099 
querySurfacePresentModesTest(Context & context,Type wsiType)1100 tcu::TestStatus querySurfacePresentModesTest (Context& context, Type wsiType)
1101 {
1102 	tcu::TestLog&					log				= context.getTestContext().getLog();
1103 	tcu::ResultCollector			results			(log);
1104 
1105 	const InstanceHelper			instHelper		(context, wsiType);
1106 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
1107 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1108 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1109 
1110 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1111 	{
1112 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1113 		{
1114 			deUint32	numModes = 0;
1115 
1116 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, DE_NULL));
1117 
1118 			vector<VkPresentModeKHR>	modes	(numModes + 1);
1119 
1120 			if (numModes > 0)
1121 			{
1122 				const deUint32 numModesOrig = numModes;
1123 
1124 				// check if below call properly overwrites mode count
1125 				numModes++;
1126 
1127 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModes, &modes[0]));
1128 
1129 				if ((size_t)numModes != numModesOrig)
1130 					TCU_FAIL("Mode count changed between calls");
1131 			}
1132 
1133 			modes.pop_back();
1134 
1135 			log << TestLog::Message << "Device " << deviceNdx << ": " << tcu::formatArray(modes.begin(), modes.end()) << TestLog::EndMessage;
1136 
1137 			validateSurfacePresentModes(results, wsiType, modes);
1138 			CheckPhysicalDeviceSurfacePresentModesIncompleteResult()(results, instHelper.vki, physicalDevices[deviceNdx], *surface, modes.size());
1139 		}
1140 		// else skip query as surface is not supported by the device
1141 	}
1142 
1143 	return tcu::TestStatus(results.getResult(), results.getMessage());
1144 }
1145 
querySurfacePresentModesTestSurfaceless(Context & context,Type wsiType)1146 tcu::TestStatus querySurfacePresentModesTestSurfaceless (Context& context, Type wsiType)
1147 {
1148 	tcu::TestLog&					log				= context.getTestContext().getLog();
1149 	tcu::ResultCollector			results			(log);
1150 
1151 	const InstanceHelper			instHelper(context, wsiType, vector<string>(1, string("VK_GOOGLE_surfaceless_query")));
1152 	const NativeObjects				native			(context, instHelper.supportedExtensions, wsiType);
1153 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1154 	const VkSurfaceKHR				nullSurface		= 0;
1155 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1156 
1157 	for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1158 	{
1159 		if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1160 		{
1161 			deUint32	numModesSurface = 0;
1162 			deUint32	numModesNull	= 0;
1163 
1164 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModesSurface, DE_NULL));
1165 			VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], nullSurface, &numModesNull, DE_NULL));
1166 
1167 			if (numModesSurface != numModesNull)
1168 			{
1169 				results.fail("Number of modes does not match");
1170 				continue;
1171 			}
1172 
1173 			vector<VkPresentModeKHR>	modesSurface(numModesSurface + 1);
1174 			vector<VkPresentModeKHR>	modesNull(numModesSurface + 1);
1175 
1176 			if (numModesSurface > 0)
1177 			{
1178 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], *surface, &numModesSurface, &modesSurface[0]));
1179 				VK_CHECK(instHelper.vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevices[deviceNdx], nullSurface, &numModesSurface, &modesNull[0]));
1180 			}
1181 
1182 			modesSurface.pop_back();
1183 			modesNull.pop_back();
1184 
1185 			for (deUint32 i = 0; i < modesSurface.size(); i++)
1186 			{
1187 				if (modesSurface[i] != modesNull[i])
1188 				{
1189 					results.fail("Present modes mismatch");
1190 				}
1191 			}
1192 		}
1193 	}
1194 
1195 	return tcu::TestStatus(results.getResult(), results.getMessage());
1196 }
1197 
queryDevGroupSurfacePresentCapabilitiesTest(Context & context,Type wsiType)1198 tcu::TestStatus queryDevGroupSurfacePresentCapabilitiesTest (Context& context, Type wsiType)
1199 {
1200 	tcu::TestLog&									log						= context.getTestContext().getLog();
1201 	const InstanceHelper							instHelper				(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1202 	const float										queuePriority			= 1.0f;
1203 	const tcu::CommandLine&							cmdLine					= context.getTestContext().getCommandLine();
1204 	const deUint32									devGroupIdx				= cmdLine.getVKDeviceGroupId() - 1;
1205 	const deUint32									deviceIdx				= context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1206 	const VkDeviceGroupPresentModeFlagsKHR			requiredFlag			= VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1207 	const VkDeviceGroupPresentModeFlagsKHR			maxValidFlag			= VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1208 																				VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1209 	deUint8											buffer					[sizeof(VkDeviceGroupPresentCapabilitiesKHR) + GUARD_SIZE];
1210 	deUint32										queueFamilyIndex		= 0;
1211 	VkDeviceGroupPresentCapabilitiesKHR*			presentCapabilities;
1212 	std::vector<const char*>						deviceExtensions;
1213 
1214 	if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1215 		deviceExtensions.push_back("VK_KHR_device_group");
1216 	deviceExtensions.push_back("VK_KHR_swapchain");
1217 
1218 	for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1219 	{
1220 		if (!context.isDeviceFunctionalitySupported(deviceExtensions[ndx]))
1221 			TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1222 	}
1223 
1224 	const vector<VkPhysicalDeviceGroupProperties>	deviceGroupProps		= enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1225 
1226 	const std::vector<VkQueueFamilyProperties>		queueProps				= getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1227 	for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1228 	{
1229 		if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1230 			queueFamilyIndex = (deUint32)queueNdx;
1231 	}
1232 	const VkDeviceQueueCreateInfo					deviceQueueCreateInfo	=
1233 	{
1234 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,				//type
1235 		DE_NULL,												//pNext
1236 		(VkDeviceQueueCreateFlags)0u,							//flags
1237 		queueFamilyIndex,										//queueFamilyIndex;
1238 		1u,														//queueCount;
1239 		&queuePriority,											//pQueuePriorities;
1240 	};
1241 	const VkDeviceGroupDeviceCreateInfo				deviceGroupInfo			=
1242 	{
1243 		VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,	//stype
1244 		DE_NULL,												//pNext
1245 		deviceGroupProps[devGroupIdx].physicalDeviceCount,		//physicalDeviceCount
1246 		deviceGroupProps[devGroupIdx].physicalDevices			//physicalDevices
1247 	};
1248 
1249 	const VkDeviceCreateInfo						deviceCreateInfo		=
1250 	{
1251 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,							//sType;
1252 		&deviceGroupInfo,												//pNext;
1253 		(VkDeviceCreateFlags)0u,										//flags
1254 		1,																//queueRecordCount;
1255 		&deviceQueueCreateInfo,											//pRequestedQueues;
1256 		0,																//layerCount;
1257 		DE_NULL,														//ppEnabledLayerNames;
1258 		deUint32(deviceExtensions.size()),								//enabledExtensionCount;
1259 		(deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]),	//ppEnabledExtensionNames;
1260 		DE_NULL,														//pEnabledFeatures;
1261 	};
1262 
1263 	Move<VkDevice>		deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1264 	const DeviceDriver	vk	(context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1265 
1266 
1267 	presentCapabilities = reinterpret_cast<VkDeviceGroupPresentCapabilitiesKHR*>(buffer);
1268 	deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1269 	presentCapabilities->sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR;
1270 	presentCapabilities->pNext = DE_NULL;
1271 	VK_CHECK(vk.getDeviceGroupPresentCapabilitiesKHR(deviceGroup.get(), presentCapabilities));
1272 
1273 	// Guard check
1274 	for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1275 	{
1276 		if (buffer[ndx + sizeof(VkDeviceGroupPresentCapabilitiesKHR)] != GUARD_VALUE)
1277 		{
1278 			log << TestLog::Message << "deviceGroupPresentCapabilities - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1279 			return tcu::TestStatus::fail("deviceGroupPresentCapabilities buffer overflow");
1280 		}
1281 	}
1282 
1283 	// Check each physical device can present on itself
1284 	for (size_t physDevIdx = 0; physDevIdx < VK_MAX_DEVICE_GROUP_SIZE; physDevIdx++)
1285 	{
1286 		if (presentCapabilities->presentMask[physDevIdx])
1287 			if (!((1 << physDevIdx) & (presentCapabilities->presentMask[physDevIdx])))
1288 				return tcu::TestStatus::fail("deviceGroupPresentCapabilities, device can not present on itself, invalid present mask");
1289 	}
1290 
1291 	// Check if flags are valid
1292 	if ((!(presentCapabilities->modes & requiredFlag)) ||
1293 		presentCapabilities->modes > maxValidFlag)
1294 		return tcu::TestStatus::fail("deviceGroupPresentCapabilities flag not valid");
1295 
1296 	return tcu::TestStatus::pass("Querying deviceGroup present capabilities succeeded");
1297 }
1298 
queryDevGroupSurfacePresentModesTest(Context & context,Type wsiType)1299 tcu::TestStatus queryDevGroupSurfacePresentModesTest (Context& context, Type wsiType)
1300 {
1301 	tcu::TestLog&							log					= context.getTestContext().getLog();
1302 	tcu::ResultCollector					results				(log);
1303 	const InstanceHelper					instHelper			(context, wsiType, vector<string>(1, string("VK_KHR_device_group_creation")));
1304 	const NativeObjects						native				(context, instHelper.supportedExtensions, wsiType);
1305 	const Unique<VkSurfaceKHR>				surface				(createSurface(instHelper.vki, instHelper.instance, wsiType, native.getDisplay(), native.getWindow(), context.getTestContext().getCommandLine()));
1306 	const float								queuePriority		= 1.0f;
1307 	const tcu::CommandLine&					cmdLine				= context.getTestContext().getCommandLine();
1308 	const deUint32							devGroupIdx			= cmdLine.getVKDeviceGroupId() - 1;
1309 	const deUint32							deviceIdx			= context.getTestContext().getCommandLine().getVKDeviceId() - 1u;
1310 	const VkDeviceGroupPresentModeFlagsKHR	requiredFlag		= VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1311 	const VkDeviceGroupPresentModeFlagsKHR	maxValidFlag		= VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR |
1312 																	VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR|VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR;
1313 	VkResult								result				= VK_SUCCESS;
1314 	deUint8									buffer				[sizeof(VkDeviceGroupPresentModeFlagsKHR) + GUARD_SIZE];
1315 	deUint32								rectCount			= 0;
1316 	deUint32								incompleteRectCount	= 0;
1317 	deUint32								queueFamilyIndex	= 0;
1318 	VkRect2D*								presentRectangles;
1319 	VkDeviceGroupPresentModeFlagsKHR*		presentModeFlags;
1320 	vector<deUint8>							rectanglesBuffer;
1321 	VkPhysicalDevice						physicalDevice		= chooseDevice(instHelper.vki, instHelper.instance, cmdLine);
1322 	const Extensions&						supportedExtensions	= enumerateDeviceExtensionProperties(instHelper.vki, physicalDevice, DE_NULL);
1323 	std::vector<const char*>				deviceExtensions;
1324 
1325 	if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_device_group"))
1326 		deviceExtensions.push_back("VK_KHR_device_group");
1327 	deviceExtensions.push_back("VK_KHR_swapchain");
1328 
1329 	for (int ndx = 0; ndx < int(deviceExtensions.size()); ++ndx)
1330 	{
1331 		if (!isExtensionStructSupported(supportedExtensions, RequiredExtension(deviceExtensions[ndx])))
1332 			TCU_THROW(NotSupportedError, (string(deviceExtensions[ndx]) + " is not supported").c_str());
1333 	}
1334 
1335 	const vector<VkPhysicalDeviceGroupProperties>	deviceGroupProps = enumeratePhysicalDeviceGroups(instHelper.vki, instHelper.instance);
1336 	const std::vector<VkQueueFamilyProperties>	queueProps		= getPhysicalDeviceQueueFamilyProperties(instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx]);
1337 	for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
1338 	{
1339 		if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
1340 			queueFamilyIndex = (deUint32)queueNdx;
1341 	}
1342 	const VkDeviceQueueCreateInfo			deviceQueueCreateInfo =
1343 	{
1344 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,					//type
1345 		DE_NULL,													//pNext
1346 		(VkDeviceQueueCreateFlags)0u,								//flags
1347 		queueFamilyIndex,											//queueFamilyIndex;
1348 		1u,															//queueCount;
1349 		&queuePriority,												//pQueuePriorities;
1350 	};
1351 	const VkDeviceGroupDeviceCreateInfo			deviceGroupInfo =
1352 	{
1353 		VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,	//stype
1354 		DE_NULL,												//pNext
1355 		deviceGroupProps[devGroupIdx].physicalDeviceCount,		//physicalDeviceCount
1356 		deviceGroupProps[devGroupIdx].physicalDevices			//physicalDevices
1357 	};
1358 
1359 	const VkDeviceCreateInfo					deviceCreateInfo =
1360 	{
1361 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,							//sType;
1362 		&deviceGroupInfo,												//pNext;
1363 		(VkDeviceCreateFlags)0u,										//flags
1364 		1,																//queueRecordCount;
1365 		&deviceQueueCreateInfo,											//pRequestedQueues;
1366 		0,																//layerCount;
1367 		DE_NULL,														//ppEnabledLayerNames;
1368 		deUint32(deviceExtensions.size()),								//enabledExtensionCount;
1369 		(deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0]),	//ppEnabledExtensionNames;
1370 		DE_NULL,														//pEnabledFeatures;
1371 	};
1372 
1373 	Move<VkDevice>		deviceGroup = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instHelper.instance, instHelper.vki, deviceGroupProps[devGroupIdx].physicalDevices[deviceIdx], &deviceCreateInfo);
1374 	const DeviceDriver	vk	(context.getPlatformInterface(), instHelper.instance, *deviceGroup);
1375 	presentModeFlags = reinterpret_cast<VkDeviceGroupPresentModeFlagsKHR*>(buffer);
1376 	deMemset(buffer, GUARD_VALUE, sizeof(buffer));
1377 
1378 	VK_CHECK(vk.getDeviceGroupSurfacePresentModesKHR(deviceGroup.get(), *surface, presentModeFlags));
1379 
1380 	// Guard check
1381 	for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1382 	{
1383 		if (buffer[ndx + sizeof(VkDeviceGroupPresentModeFlagsKHR)] != GUARD_VALUE)
1384 		{
1385 			log << TestLog::Message << "queryDevGroupSurfacePresentModesTest - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1386 			return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest buffer overflow");
1387 		}
1388 	}
1389 
1390 	// Check if flags are valid
1391 	if ((!(*presentModeFlags & requiredFlag)) ||
1392 		*presentModeFlags > maxValidFlag)
1393 		return tcu::TestStatus::fail("queryDevGroupSurfacePresentModesTest flag not valid");
1394 
1395 	// getPhysicalDevicePresentRectanglesKHR is supported only when VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR is set
1396 	if ((*presentModeFlags & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR))
1397 	{
1398 		for (size_t physDevIdx = 0; physDevIdx < deviceGroupProps[devGroupIdx].physicalDeviceCount; physDevIdx++)
1399 		{
1400 			VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, DE_NULL));
1401 			rectanglesBuffer.resize(sizeof(VkRect2D) * rectCount + GUARD_SIZE);
1402 			presentRectangles = reinterpret_cast<VkRect2D*>(rectanglesBuffer.data());
1403 			deMemset(rectanglesBuffer.data(), GUARD_VALUE, rectanglesBuffer.size());
1404 
1405 			VK_CHECK(instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &rectCount, presentRectangles));
1406 
1407 			// Guard check
1408 			for (deInt32 ndx = 0; ndx < GUARD_SIZE; ndx++)
1409 			{
1410 				if (rectanglesBuffer[ndx + sizeof(VkRect2D) * rectCount] != GUARD_VALUE)
1411 				{
1412 					log << TestLog::Message << "getPhysicalDevicePresentRectanglesKHR - Guard offset " << ndx << " not valid" << TestLog::EndMessage;
1413 					return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR buffer overflow");
1414 				}
1415 			}
1416 
1417 			// Check rectangles do not overlap
1418 			for (size_t rectIdx1 = 0; rectIdx1 < rectCount; rectIdx1++)
1419 			{
1420 				for (size_t rectIdx2 = 0; rectIdx2 < rectCount; rectIdx2++)
1421 				{
1422 					if (rectIdx1 != rectIdx2)
1423 					{
1424 						deUint32 rectATop		= presentRectangles[rectIdx1].offset.y;
1425 						deUint32 rectALeft		= presentRectangles[rectIdx1].offset.x;
1426 						deUint32 rectABottom	= presentRectangles[rectIdx1].offset.y + presentRectangles[rectIdx1].extent.height;
1427 						deUint32 rectARight		= presentRectangles[rectIdx1].offset.x + presentRectangles[rectIdx1].extent.width;
1428 
1429 						deUint32 rectBTop		= presentRectangles[rectIdx2].offset.y;
1430 						deUint32 rectBLeft		= presentRectangles[rectIdx2].offset.x;
1431 						deUint32 rectBBottom	= presentRectangles[rectIdx2].offset.y + presentRectangles[rectIdx2].extent.height;
1432 						deUint32 rectBRight		= presentRectangles[rectIdx2].offset.x + presentRectangles[rectIdx2].extent.width;
1433 
1434 						if (rectALeft < rectBRight && rectARight > rectBLeft &&
1435 							rectATop < rectBBottom && rectABottom > rectBTop)
1436 							return tcu::TestStatus::fail("getPhysicalDevicePresentRectanglesKHR rectangles overlap");
1437 					}
1438 				}
1439 			}
1440 
1441 			// Check incomplete
1442 			incompleteRectCount = rectCount / 2;
1443 			result = instHelper.vki.getPhysicalDevicePresentRectanglesKHR(deviceGroupProps[devGroupIdx].physicalDevices[physDevIdx], *surface, &incompleteRectCount, presentRectangles);
1444 			results.check(result == VK_INCOMPLETE, "Expected VK_INCOMPLETE");
1445 		}
1446 	}
1447 
1448 		return tcu::TestStatus(results.getResult(), results.getMessage());
1449 }
1450 
createSurfaceInitialSizeTest(Context & context,Type wsiType)1451 tcu::TestStatus createSurfaceInitialSizeTest (Context& context, Type wsiType)
1452 {
1453 	tcu::TestLog&					log				= context.getTestContext().getLog();
1454 	tcu::ResultCollector			results			(log);
1455 
1456 	const InstanceHelper			instHelper		(context, wsiType);
1457 
1458 	const UniquePtr<Display>		nativeDisplay	(NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1459 																				  instHelper.supportedExtensions,
1460 																				  wsiType));
1461 
1462 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1463 	const UVec2						sizes[]			=
1464 	{
1465 		UVec2(64, 64),
1466 		UVec2(124, 119),
1467 		UVec2(256, 512)
1468 	};
1469 
1470 	DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE);
1471 
1472 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1473 	{
1474 		const UVec2&				testSize		= sizes[sizeNdx];
1475 		const UniquePtr<Window>		nativeWindow	(NativeObjects::createWindow(*nativeDisplay, tcu::just(testSize)));
1476 		const Unique<VkSurfaceKHR>	surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow, context.getTestContext().getCommandLine()));
1477 
1478 		for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1479 		{
1480 			if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1481 			{
1482 				const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1483 
1484 				// \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1485 				results.check(capabilities.currentExtent.width == testSize.x() &&
1486 								capabilities.currentExtent.height == testSize.y(),
1487 								"currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1488 			}
1489 		}
1490 	}
1491 
1492 	return tcu::TestStatus(results.getResult(), results.getMessage());
1493 }
1494 
resizeSurfaceTest(Context & context,Type wsiType)1495 tcu::TestStatus resizeSurfaceTest (Context& context, Type wsiType)
1496 {
1497 	tcu::TestLog&					log				= context.getTestContext().getLog();
1498 	tcu::ResultCollector			results			(log);
1499 
1500 	const InstanceHelper			instHelper		(context, wsiType);
1501 
1502 	const UniquePtr<Display>		nativeDisplay	(NativeObjects::createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(),
1503 																				  instHelper.supportedExtensions,
1504 																				  wsiType));
1505 	UniquePtr<Window>				nativeWindow	(NativeObjects::createWindow(*nativeDisplay, tcu::Nothing));
1506 
1507 	const vector<VkPhysicalDevice>	physicalDevices	= enumeratePhysicalDevices(instHelper.vki, instHelper.instance);
1508 	const Unique<VkSurfaceKHR>		surface			(createSurface(instHelper.vki, instHelper.instance, wsiType, *nativeDisplay, *nativeWindow, context.getTestContext().getCommandLine()));
1509 
1510 	const UVec2						sizes[]			=
1511 	{
1512 		UVec2(64, 64),
1513 		UVec2(124, 119),
1514 		UVec2(256, 512)
1515 	};
1516 
1517 	DE_ASSERT(getPlatformProperties(wsiType).features & PlatformProperties::FEATURE_RESIZE_WINDOW);
1518 
1519 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1520 	{
1521 		const UVec2		testSize	= sizes[sizeNdx];
1522 
1523 		try
1524 		{
1525 			nativeWindow->resize(testSize);
1526 		}
1527 		catch (const tcu::Exception& e)
1528 		{
1529 			// Make sure all exception types result in a test failure
1530 			results.fail(e.getMessage());
1531 		}
1532 
1533 		for (size_t deviceNdx = 0; deviceNdx < physicalDevices.size(); ++deviceNdx)
1534 		{
1535 			if (isSupportedByAnyQueue(instHelper.vki, physicalDevices[deviceNdx], *surface))
1536 			{
1537 				const VkSurfaceCapabilitiesKHR	capabilities	= getPhysicalDeviceSurfaceCapabilities(instHelper.vki, physicalDevices[deviceNdx], *surface);
1538 
1539 				// \note Assumes that surface size is NOT set by swapchain if initial window size is honored by platform
1540 				results.check(capabilities.currentExtent.width == testSize.x() &&
1541 								capabilities.currentExtent.height == testSize.y(),
1542 								"currentExtent " + de::toString(capabilities.currentExtent) + " doesn't match requested size " + de::toString(testSize));
1543 			}
1544 		}
1545 	}
1546 
1547 	return tcu::TestStatus(results.getResult(), results.getMessage());
1548 }
1549 
destroyNullHandleSurfaceTest(Context & context,Type wsiType)1550 tcu::TestStatus destroyNullHandleSurfaceTest (Context& context, Type wsiType)
1551 {
1552 	const InstanceHelper	instHelper	(context, wsiType);
1553 	const VkSurfaceKHR		nullHandle	= DE_NULL;
1554 
1555 	// Default allocator
1556 	instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, DE_NULL);
1557 
1558 	// Custom allocator
1559 	{
1560 		AllocationCallbackRecorder	recordingAllocator	(getSystemAllocator(), 1u);
1561 
1562 		instHelper.vki.destroySurfaceKHR(instHelper.instance, nullHandle, recordingAllocator.getCallbacks());
1563 
1564 		if (recordingAllocator.getNumRecords() != 0u)
1565 			return tcu::TestStatus::fail("Implementation allocated/freed the memory");
1566 	}
1567 
1568 	return tcu::TestStatus::pass("Destroying a VK_NULL_HANDLE surface has no effect");
1569 }
1570 
1571 } // anonymous
1572 
createSurfaceTests(tcu::TestCaseGroup * testGroup,vk::wsi::Type wsiType)1573 void createSurfaceTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType)
1574 {
1575 	const PlatformProperties&	platformProperties	= getPlatformProperties(wsiType);
1576 
1577 	addFunctionCase(testGroup, "create",								"Create surface",											createSurfaceTest,							wsiType);
1578 	addFunctionCase(testGroup, "create_custom_allocator",				"Create surface with custom allocator",						createSurfaceCustomAllocatorTest,			wsiType);
1579 	addFunctionCase(testGroup, "create_simulate_oom",					"Create surface with simulating OOM",						createSurfaceSimulateOOMTest,				wsiType);
1580 	addFunctionCase(testGroup, "query_support",							"Query surface support",									querySurfaceSupportTest,					wsiType);
1581 	addFunctionCase(testGroup, "query_presentation_support",			"Query native presentation support",						queryPresentationSupportTest,				wsiType);
1582 	addFunctionCase(testGroup, "query_capabilities",					"Query surface capabilities",								querySurfaceCapabilitiesTest,				wsiType);
1583 	addFunctionCase(testGroup, "query_capabilities2",					"Query extended surface capabilities",						querySurfaceCapabilities2Test,				wsiType);
1584 	addFunctionCase(testGroup, "query_protected_capabilities",			"Query protected surface capabilities",						querySurfaceProtectedCapabilitiesTest,		wsiType);
1585 	addFunctionCase(testGroup, "query_surface_counters",				"Query and check available surface counters",				querySurfaceCounterTest,					wsiType);
1586 	addFunctionCase(testGroup, "query_formats",							"Query surface formats",									querySurfaceFormatsTest,					wsiType);
1587 	addFunctionCase(testGroup, "query_formats2",						"Query extended surface formats",							querySurfaceFormats2Test,					wsiType);
1588 	addFunctionCase(testGroup, "query_present_modes",					"Query surface present modes",								querySurfacePresentModesTest,				wsiType);
1589 	addFunctionCase(testGroup, "query_present_modes2",					"Query extended surface present modes",						querySurfacePresentModes2Test,				wsiType);
1590 	addFunctionCase(testGroup, "query_devgroup_present_capabilities",	"Query surface present modes capabilities in device groups",queryDevGroupSurfacePresentCapabilitiesTest,wsiType);
1591 	addFunctionCase(testGroup, "query_devgroup_present_modes",			"Query surface present modes for device groups",			queryDevGroupSurfacePresentModesTest,		wsiType);
1592 	addFunctionCase(testGroup, "destroy_null_handle",					"Destroy VK_NULL_HANDLE surface",							destroyNullHandleSurfaceTest,				wsiType);
1593 
1594 	if ((platformProperties.features & PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE) != 0)
1595 		addFunctionCase(testGroup, "initial_size",	"Create surface with initial window size set",	createSurfaceInitialSizeTest,	wsiType);
1596 
1597 	if ((platformProperties.features & PlatformProperties::FEATURE_RESIZE_WINDOW) != 0)
1598 		addFunctionCase(testGroup, "resize",		"Resize window and surface",					resizeSurfaceTest,				wsiType);
1599 
1600 	addFunctionCase(testGroup, "query_formats_surfaceless", "Query surface formats without surface", querySurfaceFormatsTestSurfaceless, wsiType);
1601 	addFunctionCase(testGroup, "query_present_modes_surfaceless", "Query surface present modes without surface", querySurfacePresentModesTestSurfaceless, wsiType);
1602 	addFunctionCase(testGroup, "query_present_modes2_surfaceless", "Query extended surface present modes without surface", querySurfacePresentModes2TestSurfaceless, wsiType);
1603 	addFunctionCase(testGroup, "query_formats2_surfaceless", "Query extended surface formats without surface", querySurfaceFormats2TestSurfaceless, wsiType);
1604 }
1605 
1606 } // wsi
1607 } // vkt
1608