• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan CTS Framework
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 Windowing System Integration (WSI) Utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vkDeviceUtil.hpp"
25 #include "vkRefUtil.hpp"
26 #include "vkTypeUtil.hpp"
27 #include "vkObjUtil.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkWsiUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 
33 #include "deArrayUtil.hpp"
34 #include "deMemory.h"
35 
36 #include <limits>
37 #include <vector>
38 
39 using std::vector;
40 
41 #if defined (DEQP_SUPPORT_X11)
42 #	include <X11/Xlib.h>
43 #	if defined (DEQP_SUPPORT_XCB)
44 #		include <xcb/xcb.h>
45 #	endif // DEQP_SUPPORT_XCB
46 #endif // DEQP_SUPPORT_X11
47 
48 #if defined (DEQP_SUPPORT_WAYLAND)
49 #	include "tcuLnxWayland.hpp"
50 #	define WAYLAND_DISPLAY DE_NULL
51 #endif // DEQP_SUPPORT_WAYLAND
52 
53 #if ( DE_OS == DE_OS_WIN32 )
54 	#define NOMINMAX
55 	#define WIN32_LEAN_AND_MEAN
56 	#include <windows.h>
57 #endif
58 
59 namespace vk
60 {
61 namespace wsi
62 {
63 
64 //! Get canonical WSI name that should be used for example in test case and group names.
getName(Type wsiType)65 const char* getName (Type wsiType)
66 {
67 	static const char* const s_names[] =
68 	{
69 		"xlib",
70 		"xcb",
71 		"wayland",
72 		"android",
73 		"win32",
74 		"macos",
75 		"headless",
76 		"direct_drm",
77 	};
78 	return de::getSizedArrayElement<TYPE_LAST>(s_names, wsiType);
79 }
80 
getExtensionName(Type wsiType)81 const char* getExtensionName (Type wsiType)
82 {
83 	static const char* const s_extNames[] =
84 	{
85 		"VK_KHR_xlib_surface",
86 		"VK_KHR_xcb_surface",
87 		"VK_KHR_wayland_surface",
88 		"VK_KHR_android_surface",
89 		"VK_KHR_win32_surface",
90 		"VK_MVK_macos_surface",
91 		"VK_EXT_headless_surface",
92 		"VK_EXT_acquire_drm_display",
93 	};
94 	return de::getSizedArrayElement<TYPE_LAST>(s_extNames, wsiType);
95 }
96 
getPlatformProperties(Type wsiType)97 const PlatformProperties& getPlatformProperties (Type wsiType)
98 {
99 	// \note These are declared here (rather than queried through vk::Platform for example)
100 	//		 on purpose. The behavior of a platform is partly defined by the platform spec,
101 	//		 and partly by WSI extensions, and platform ports should not need to override
102 	//		 that definition.
103 
104 	const deUint32	noDisplayLimit	= std::numeric_limits<deUint32>::max();
105 	const deUint32	noWindowLimit	= std::numeric_limits<deUint32>::max();
106 
107 	static const PlatformProperties s_properties[] =
108 	{
109 		// VK_KHR_xlib_surface
110 		{
111 			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
112 			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
113 			noDisplayLimit,
114 			noWindowLimit,
115 		},
116 		// VK_KHR_xcb_surface
117 		{
118 			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
119 			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
120 			noDisplayLimit,
121 			noWindowLimit,
122 		},
123 		// VK_KHR_wayland_surface
124 		{
125 			0u,
126 			PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE,
127 			noDisplayLimit,
128 			noWindowLimit,
129 		},
130 		// VK_KHR_android_surface
131 		{
132 			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE,
133 			PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE,
134 			1u,
135 			1u, // Only one window available
136 		},
137 		// VK_KHR_win32_surface
138 		{
139 			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
140 			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
141 			noDisplayLimit,
142 			noWindowLimit,
143 		},
144 		// VK_MVK_macos_surface
145 		{
146 			PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
147 			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
148 			noDisplayLimit,
149 			noWindowLimit,
150 		},
151 		// VK_EXT_headless_surface
152 		{
153 			0u,
154 			PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE,
155 			noDisplayLimit,
156 			noWindowLimit,
157 		},
158 		// VK_EXT_acquire_drm_display
159 		{
160 			0u,
161 			PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
162 			1u,
163 			1u,
164 		},
165 	};
166 
167 	return de::getSizedArrayElement<TYPE_LAST>(s_properties, wsiType);
168 }
169 
170 #ifndef CTS_USES_VULKANSC
createDisplaySurface(const InstanceInterface & vki,VkInstance instance,VkDisplayKHR display,const tcu::CommandLine & cmdLine,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)171 static VkResult createDisplaySurface (const InstanceInterface&		vki,
172 									  VkInstance					instance,
173 									  VkDisplayKHR					display,
174 									  const tcu::CommandLine&		cmdLine,
175 									  const VkAllocationCallbacks*	pAllocator,
176 									  VkSurfaceKHR*					pSurface)
177 {
178 	VkPhysicalDevice physDevice = chooseDevice(vki, instance, cmdLine);
179 
180 	vector<VkDisplayPlanePropertiesKHR>	planeProperties;
181 	deUint32							planeCount = 0u;
182 	deUint32							planeIndex = 0u;
183 	bool								planeFound = false;
184 	VK_CHECK_SUPPORTED(vki.getPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, DE_NULL));
185 
186 	planeProperties.resize(planeCount);
187 	VK_CHECK_SUPPORTED(vki.getPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, &planeProperties[0]));
188 
189 	for (deUint32 i = 0; i < planeCount; ++i)
190 	{
191 		vector<VkDisplayKHR>	supportedDisplays;
192 		deUint32				supportedDisplayCount	=	0u;
193 		VK_CHECK_SUPPORTED(vki.getDisplayPlaneSupportedDisplaysKHR(physDevice, i, &supportedDisplayCount, DE_NULL));
194 
195 		supportedDisplays.resize(supportedDisplayCount);
196 		VK_CHECK_SUPPORTED(vki.getDisplayPlaneSupportedDisplaysKHR(physDevice, i, &supportedDisplayCount, &supportedDisplays[0]));
197 
198 		for (deUint32 j = 0; j < supportedDisplayCount; ++j)
199 		{
200 			if (display == supportedDisplays[i])
201 			{
202 				planeIndex = i;
203 				planeFound = true;
204 				break;
205 			}
206 		}
207 
208 		if (planeFound)
209 			break;
210 	}
211 	if (!planeFound)
212 		TCU_THROW(NotSupportedError, "No supported displays for planes.");
213 
214 	vector<VkDisplayModePropertiesKHR>			displayModeProperties;
215 	deUint32									displayModeCount = 0u;
216 	VK_CHECK_SUPPORTED(vki.getDisplayModePropertiesKHR(physDevice, display, &displayModeCount, DE_NULL));
217 	if (displayModeCount < 1)
218 		TCU_THROW(NotSupportedError, "No display modes defined.");
219 
220 	displayModeProperties.resize(displayModeCount);
221 	VK_CHECK_SUPPORTED(vki.getDisplayModePropertiesKHR(physDevice, display, &displayModeCount, &displayModeProperties[0]));
222 
223     const VkDisplaySurfaceCreateInfoKHR createInfo = {
224         VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR,	// VkStructureType					sType
225 		DE_NULL,											// const void*						pNext
226         0,													// VkDisplaySurfaceCreateFlagsKHR	flags
227 		displayModeProperties[0].displayMode,				// VkDisplayModeKHR					displayMode
228 		planeIndex,											// uint32_t							planeIndex
229 		planeProperties[planeIndex].currentStackIndex,		// uint32_t							planeStackIndex
230 		VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,				// VkSurfaceTransformFlagBitsKHR	transform
231 		1.0f,												// float							globalAlpha
232 		VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR,				// VkDisplayPlaneAlphaFlagBitsKHR	alphaMode
233 		displayModeProperties[0].parameters.visibleRegion,	// VkExtent2D						imageExtent
234 	};
235 
236     return vki.createDisplayPlaneSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
237 }
238 #endif // CTS_USES_VULKANSC
239 
createSurface(const InstanceInterface & vki,VkInstance instance,Type wsiType,const Display & nativeDisplay,const Window & nativeWindow,const tcu::CommandLine & cmdLine,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)240 VkResult createSurface (const InstanceInterface&		vki,
241 						VkInstance						instance,
242 						Type							wsiType,
243 						const Display&					nativeDisplay,
244 						const Window&					nativeWindow,
245 						const tcu::CommandLine&			cmdLine,
246 						const VkAllocationCallbacks*	pAllocator,
247 						VkSurfaceKHR*					pSurface)
248 {
249 	// Update this function if you add more WSI implementations
250 	DE_STATIC_ASSERT(TYPE_LAST == 8);
251 
252 #ifdef CTS_USES_VULKANSC
253 	DE_UNREF(vki);
254 	DE_UNREF(instance);
255 	DE_UNREF(wsiType);
256 	DE_UNREF(nativeDisplay);
257 	DE_UNREF(nativeWindow);
258 	DE_UNREF(cmdLine);
259 	DE_UNREF(pAllocator);
260 	DE_UNREF(pSurface);
261 
262 	TCU_THROW(NotSupportedError, "Vulkan SC does not support createSurface");
263 #else // CTS_USES_VULKANSC
264 	switch (wsiType)
265 	{
266 		case TYPE_XLIB:
267 		{
268 			const XlibDisplayInterface&			xlibDisplay		= dynamic_cast<const XlibDisplayInterface&>(nativeDisplay);
269 			const XlibWindowInterface&			xlibWindow		= dynamic_cast<const XlibWindowInterface&>(nativeWindow);
270 			const VkXlibSurfaceCreateInfoKHR	createInfo		=
271 			{
272 				VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
273 				DE_NULL,
274 				(VkXlibSurfaceCreateFlagsKHR)0,
275 				xlibDisplay.getNative(),
276 				xlibWindow.getNative()
277 			};
278 
279 			return vki.createXlibSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
280 		}
281 
282 		case TYPE_XCB:
283 		{
284 			const XcbDisplayInterface&			xcbDisplay		= dynamic_cast<const XcbDisplayInterface&>(nativeDisplay);
285 			const XcbWindowInterface&			xcbWindow		= dynamic_cast<const XcbWindowInterface&>(nativeWindow);
286 			const VkXcbSurfaceCreateInfoKHR		createInfo		=
287 			{
288 				VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
289 				DE_NULL,
290 				(VkXcbSurfaceCreateFlagsKHR)0,
291 				xcbDisplay.getNative(),
292 				xcbWindow.getNative()
293 			};
294 
295 			return vki.createXcbSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
296 		}
297 
298 		case TYPE_WAYLAND:
299 		{
300 			const WaylandDisplayInterface&		waylandDisplay	= dynamic_cast<const WaylandDisplayInterface&>(nativeDisplay);
301 			const WaylandWindowInterface&		waylandWindow	= dynamic_cast<const WaylandWindowInterface&>(nativeWindow);
302 			const VkWaylandSurfaceCreateInfoKHR	createInfo		=
303 			{
304 				VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
305 				DE_NULL,
306 				(VkWaylandSurfaceCreateFlagsKHR)0,
307 				waylandDisplay.getNative(),
308 				waylandWindow.getNative()
309 			};
310 
311 			return vki.createWaylandSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
312 		}
313 
314 		case TYPE_ANDROID:
315 		{
316 			const AndroidWindowInterface&		androidWindow	= dynamic_cast<const AndroidWindowInterface&>(nativeWindow);
317 			const VkAndroidSurfaceCreateInfoKHR	createInfo		=
318 			{
319 				VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
320 				DE_NULL,
321 				(VkAndroidSurfaceCreateFlagsKHR)0,
322 				androidWindow.getNative()
323 			};
324 
325 			return vki.createAndroidSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
326 		}
327 
328 		case TYPE_WIN32:
329 		{
330 			const Win32DisplayInterface&		win32Display	= dynamic_cast<const Win32DisplayInterface&>(nativeDisplay);
331 			const Win32WindowInterface&			win32Window		= dynamic_cast<const Win32WindowInterface&>(nativeWindow);
332 			const VkWin32SurfaceCreateInfoKHR	createInfo		=
333 			{
334 				VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
335 				DE_NULL,
336 				(VkWin32SurfaceCreateFlagsKHR)0,
337 				win32Display.getNative(),
338 				win32Window.getNative()
339 			};
340 
341 			return vki.createWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
342 		}
343 
344 		case TYPE_MACOS:
345 		{
346 			const MacOSWindowInterface&			macOSWindow		= dynamic_cast<const MacOSWindowInterface&>(nativeWindow);
347 			const VkMacOSSurfaceCreateInfoMVK	createInfo		=
348 			{
349 				VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
350 				DE_NULL,
351 				(VkMacOSSurfaceCreateFlagsMVK)0,
352 				macOSWindow.getNative()
353 			};
354 
355 			return vki.createMacOSSurfaceMVK(instance, &createInfo, pAllocator, pSurface);
356 		}
357 
358 		case TYPE_HEADLESS:
359 		{
360 			const VkHeadlessSurfaceCreateInfoEXT	createInfo		=
361 			{
362 				VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT,
363 				DE_NULL,
364 				(VkHeadlessSurfaceCreateFlagsEXT)0
365 			};
366 
367 			return vki.createHeadlessSurfaceEXT(instance, &createInfo, pAllocator, pSurface);
368 		}
369 
370 		case TYPE_DIRECT_DRM:
371 		{
372 			DirectDrmDisplayInterface &drmDisplay = dynamic_cast<DirectDrmDisplayInterface &>(const_cast<Display&>(nativeDisplay));
373 			drmDisplay.initializeDisplay(vki, instance, cmdLine);
374 			return createDisplaySurface(vki, instance, drmDisplay.getNative(), cmdLine, pAllocator, pSurface);
375 		}
376 
377 		default:
378 			DE_FATAL("Unknown WSI type");
379 			return VK_ERROR_SURFACE_LOST_KHR;
380 	}
381 #endif // CTS_USES_VULKANSC
382 	return VK_ERROR_SURFACE_LOST_KHR;
383 }
384 
createSurface(const InstanceInterface & vki,VkInstance instance,Type wsiType,const Display & nativeDisplay,const Window & nativeWindow,const tcu::CommandLine & cmdLine,const VkAllocationCallbacks * pAllocator)385 Move<VkSurfaceKHR> createSurface (const InstanceInterface&		vki,
386 								  VkInstance					instance,
387 								  Type							wsiType,
388 								  const Display&				nativeDisplay,
389 								  const Window&					nativeWindow,
390 								  const tcu::CommandLine&		cmdLine,
391 								  const VkAllocationCallbacks*	pAllocator)
392 {
393 	VkSurfaceKHR object = 0;
394 	VK_CHECK(createSurface(vki, instance, wsiType, nativeDisplay, nativeWindow, cmdLine, pAllocator, &object));
395 	return Move<VkSurfaceKHR>(check<VkSurfaceKHR>(object), Deleter<VkSurfaceKHR>(vki, instance, pAllocator));
396 }
397 
getPhysicalDeviceSurfaceSupport(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 queueFamilyIndex,VkSurfaceKHR surface)398 VkBool32 getPhysicalDeviceSurfaceSupport (const InstanceInterface&	vki,
399 										  VkPhysicalDevice			physicalDevice,
400 										  deUint32					queueFamilyIndex,
401 										  VkSurfaceKHR				surface)
402 {
403 	VkBool32 result = 0;
404 
405 	VK_CHECK(vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &result));
406 
407 	return result;
408 }
409 
getPhysicalDevicePresentationSupport(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 queueFamilyIndex,Type wsiType,const Display & nativeDisplay)410 VkBool32 getPhysicalDevicePresentationSupport (const InstanceInterface&	vki,
411 											   VkPhysicalDevice			physicalDevice,
412 											   deUint32					queueFamilyIndex,
413 											   Type						wsiType,
414 											   const Display&			nativeDisplay)
415 {
416 #ifdef CTS_USES_VULKANSC
417 	DE_UNREF(vki);
418 	DE_UNREF(physicalDevice);
419 	DE_UNREF(queueFamilyIndex);
420 	DE_UNREF(wsiType);
421 	DE_UNREF(nativeDisplay);
422 	TCU_THROW(NotSupportedError, "Vulkan SC does not support getPhysicalDevicePresentationSupport");
423 #else // CTS_USES_VULKANSC
424 	switch (wsiType)
425 	{
426 		case TYPE_XLIB:
427 		{
428 			const XlibDisplayInterface&		xlibDisplay	= dynamic_cast<const XlibDisplayInterface&>(nativeDisplay);
429 			pt::XlibVisualID				visualID	(0U);
430 #if defined (DEQP_SUPPORT_X11)
431 			::Display*						displayPtr	= (::Display*)(xlibDisplay.getNative().internal);
432 			visualID.internal							= (deUint32)(::XDefaultVisual(displayPtr,0)->visualid);
433 #endif
434 			return vki.getPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, xlibDisplay.getNative(), visualID);
435 		}
436 		case TYPE_XCB:
437 		{
438 			const XcbDisplayInterface&		xcbDisplay	= dynamic_cast<const XcbDisplayInterface&>(nativeDisplay);
439 			pt::XcbVisualid					visualID	(0U);
440 #if defined (DEQP_SUPPORT_XCB)
441 			xcb_connection_t*				connPtr		= (xcb_connection_t*)(xcbDisplay.getNative().internal);
442 			xcb_screen_t*					screen		= xcb_setup_roots_iterator(xcb_get_setup(connPtr)).data;
443 			visualID.internal							= (deUint32)(screen->root_visual);
444 #endif
445 			return vki.getPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex, xcbDisplay.getNative(), visualID);
446 		}
447 		case TYPE_WAYLAND:
448 		{
449 			const WaylandDisplayInterface&	waylandDisplay	= dynamic_cast<const WaylandDisplayInterface&>(nativeDisplay);
450 			return vki.getPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, waylandDisplay.getNative());
451 		}
452 		case TYPE_WIN32:
453 		{
454 			return vki.getPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
455 		}
456 		case TYPE_HEADLESS:
457 		case TYPE_ANDROID:
458 		case TYPE_MACOS:
459 		case TYPE_DIRECT_DRM:
460 		{
461 			return 1;
462 		}
463 		default:
464 			DE_FATAL("Unknown WSI type");
465 			return 0;
466 	}
467 #endif // CTS_USES_VULKANSC
468 	return 1;
469 }
470 
getPhysicalDeviceSurfaceCapabilities(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)471 VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const InstanceInterface&		vki,
472 															   VkPhysicalDevice				physicalDevice,
473 															   VkSurfaceKHR					surface)
474 {
475 	VkSurfaceCapabilitiesKHR capabilities;
476 
477 	deMemset(&capabilities, 0, sizeof(capabilities));
478 
479 	VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities));
480 
481 	return capabilities;
482 }
483 
getPhysicalDeviceSurfaceCapabilities2EXT(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)484 VkSurfaceCapabilities2EXT getPhysicalDeviceSurfaceCapabilities2EXT (const InstanceInterface&		vki,
485 																	VkPhysicalDevice				physicalDevice,
486 																	VkSurfaceKHR					surface)
487 {
488 	VkSurfaceCapabilities2EXT capabilities;
489 
490 	deMemset(&capabilities, 0, sizeof(capabilities));
491 	capabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT;
492 
493 	VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, &capabilities));
494 
495 	return capabilities;
496 }
497 
sameSurfaceCapabilities(const VkSurfaceCapabilitiesKHR & khr,const VkSurfaceCapabilities2EXT & ext)498 bool sameSurfaceCapabilities (const VkSurfaceCapabilitiesKHR&	khr,
499 							  const VkSurfaceCapabilities2EXT&	ext)
500 {
501 	return (	khr.minImageCount			== ext.minImageCount &&
502 				khr.maxImageCount			== ext.maxImageCount &&
503 				khr.currentExtent.width		== ext.currentExtent.width &&
504 				khr.currentExtent.height	== ext.currentExtent.height &&
505 				khr.minImageExtent.width	== ext.minImageExtent.width &&
506 				khr.minImageExtent.height	== ext.minImageExtent.height &&
507 				khr.maxImageExtent.width	== ext.maxImageExtent.width &&
508 				khr.maxImageExtent.height	== ext.maxImageExtent.height &&
509 				khr.maxImageArrayLayers		== ext.maxImageArrayLayers &&
510 				khr.supportedTransforms		== ext.supportedTransforms &&
511 				khr.currentTransform		== ext.currentTransform &&
512 				khr.supportedCompositeAlpha	== ext.supportedCompositeAlpha &&
513 				khr.supportedUsageFlags		== ext.supportedUsageFlags	);
514 }
515 
getPhysicalDeviceSurfaceFormats(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)516 std::vector<VkSurfaceFormatKHR> getPhysicalDeviceSurfaceFormats (const InstanceInterface&		vki,
517 																 VkPhysicalDevice				physicalDevice,
518 																 VkSurfaceKHR					surface)
519 {
520 	deUint32	numFormats	= 0;
521 
522 	VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, DE_NULL));
523 
524 	if (numFormats > 0)
525 	{
526 		std::vector<VkSurfaceFormatKHR>	formats	(numFormats);
527 
528 		VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, &formats[0]));
529 
530 		return formats;
531 	}
532 	else
533 		return std::vector<VkSurfaceFormatKHR>();
534 }
535 
getPhysicalDeviceSurfacePresentModes(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)536 std::vector<VkPresentModeKHR> getPhysicalDeviceSurfacePresentModes (const InstanceInterface&		vki,
537 																	VkPhysicalDevice				physicalDevice,
538 																	VkSurfaceKHR					surface)
539 {
540 	deUint32	numModes	= 0;
541 
542 	VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, DE_NULL));
543 
544 	if (numModes > 0)
545 	{
546 		std::vector<VkPresentModeKHR>	modes	(numModes);
547 
548 		VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, &modes[0]));
549 
550 		return modes;
551 	}
552 	else
553 		return std::vector<VkPresentModeKHR>();
554 }
555 
getSwapchainImages(const DeviceInterface & vkd,VkDevice device,VkSwapchainKHR swapchain)556 std::vector<VkImage> getSwapchainImages (const DeviceInterface&			vkd,
557 										 VkDevice						device,
558 										 VkSwapchainKHR					swapchain)
559 {
560 	deUint32	numImages	= 0;
561 
562 	VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL));
563 
564 	if (numImages > 0)
565 	{
566 		std::vector<VkImage>	images	(numImages);
567 
568 		VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0]));
569 
570 		return images;
571 	}
572 	else
573 		return std::vector<VkImage>();
574 }
575 
576 namespace
577 {
578 
getSupportedQueueFamilyIndices(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkSurfaceKHR surface)579 std::vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
580 {
581 	deUint32 numTotalFamilyIndices;
582 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numTotalFamilyIndices, DE_NULL);
583 
584 	std::vector<VkQueueFamilyProperties> queueFamilyProperties(numTotalFamilyIndices);
585 	vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numTotalFamilyIndices, &queueFamilyProperties[0]);
586 
587 	std::vector<deUint32> supportedFamilyIndices;
588 	for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
589 	{
590 		if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
591 			supportedFamilyIndices.push_back(queueFamilyNdx);
592 	}
593 
594 	return supportedFamilyIndices;
595 }
596 
getSortedSupportedQueueFamilyIndices(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)597 std::vector<deUint32> getSortedSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
598 {
599 	std::vector<deUint32> indices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
600 	std::sort(begin(indices), end(indices));
601 	return indices;
602 }
603 
604 } // anonymous
605 
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const std::vector<vk::VkSurfaceKHR> & surfaces)606 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const std::vector<vk::VkSurfaceKHR>& surfaces)
607 {
608 	auto indices = getCompatibleQueueFamilyIndices(vki, physicalDevice, surfaces);
609 
610 	if (indices.empty())
611 		TCU_THROW(NotSupportedError, "Device does not support presentation to the given surfaces");
612 
613 	return indices[0];
614 }
615 
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,vk::VkSurfaceKHR surface)616 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
617 {
618 	return chooseQueueFamilyIndex(vki, physicalDevice, std::vector<vk::VkSurfaceKHR>(1u, surface));
619 }
620 
getCompatibleQueueFamilyIndices(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const std::vector<VkSurfaceKHR> & surfaces)621 std::vector<deUint32> getCompatibleQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const std::vector<VkSurfaceKHR>& surfaces)
622 {
623 	DE_ASSERT(!surfaces.empty());
624 
625 	auto indices = getSortedSupportedQueueFamilyIndices(vki, physicalDevice, surfaces[0]);
626 
627 	for (size_t i = 1; i < surfaces.size(); ++i)
628 	{
629 		auto newIndices = getSortedSupportedQueueFamilyIndices(vki, physicalDevice, surfaces[i]);
630 
631 		// Set intersection and overwrite.
632 		decltype(indices) intersection;
633 		std::set_intersection(begin(indices), end(indices), begin(newIndices), end(newIndices), std::back_inserter(intersection));
634 		indices = std::move(intersection);
635 	}
636 
637 	return indices;
638 }
639 
getFullScreenSize(const vk::wsi::Type wsiType,const vk::wsi::Display & display,const tcu::UVec2 & fallbackSize)640 tcu::UVec2 getFullScreenSize (const vk::wsi::Type wsiType, const vk::wsi::Display& display, const tcu::UVec2& fallbackSize)
641 {
642 	tcu::UVec2 result = fallbackSize;
643 
644 	switch (wsiType)
645 	{
646 		case TYPE_XLIB:
647 		{
648 #if defined (DEQP_SUPPORT_X11)
649 			const XlibDisplayInterface&			xlibDisplay		= dynamic_cast<const XlibDisplayInterface&>(display);
650 			::Display*							displayPtr		= (::Display*)(xlibDisplay.getNative().internal);
651 			const Screen*						screen			= ScreenOfDisplay(displayPtr, 0);
652 			result.x()											= deUint32(screen->width);
653 			result.y()											= deUint32(screen->height);
654 #endif
655 			break;
656 		}
657 		case TYPE_XCB:
658 		{
659 #if defined (DEQP_SUPPORT_XCB)
660 //			const XcbDisplayInterface&			xcbDisplay		= dynamic_cast<const XcbDisplayInterface&>(display);
661 //			xcb_connection_t*					connPtr			= (xcb_connection_t*)(xcbDisplay.getNative().internal);
662 //			xcb_screen_t*						screen			= xcb_setup_roots_iterator(xcb_get_setup(connPtr)).data;
663 //			result.x()											= deUint32(screen->width_in_pixels);
664 //			result.y()											= deUint32(screen->height_in_pixels);
665 #endif
666 			break;
667 		}
668 		case TYPE_WAYLAND:
669 		{
670 #if defined (DEQP_SUPPORT_WAYLAND)
671 #endif
672 			break;
673 		}
674 		case TYPE_ANDROID:
675 		{
676 #if ( DE_OS == DE_OS_ANDROID )
677 #endif
678 			break;
679 		}
680 		case TYPE_WIN32:
681 		{
682 #if ( DE_OS == DE_OS_WIN32 )
683 			de::MovePtr<Window>					nullWindow		(display.createWindow(tcu::Nothing));
684 			const Win32WindowInterface&			win32Window		= dynamic_cast<const Win32WindowInterface&>(*nullWindow);
685 			HMONITOR							hMonitor		= (HMONITOR)MonitorFromWindow((HWND)win32Window.getNative().internal, MONITOR_DEFAULTTONEAREST);
686 			MONITORINFO							monitorInfo;
687 			monitorInfo.cbSize									= sizeof(MONITORINFO);
688 			GetMonitorInfo(hMonitor, &monitorInfo);
689 			result.x()											= deUint32(abs(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left));
690 			result.y()											= deUint32(abs(monitorInfo.rcMonitor.top - monitorInfo.rcMonitor.bottom));
691 #endif
692 			break;
693 		}
694 
695 		case TYPE_MACOS:
696 		{
697 #if ( DE_OS == DE_OS_OSX )
698 #endif
699 			break;
700 		}
701 
702 		default:
703 			DE_FATAL("Unknown WSI type");
704 			break;
705 	}
706 
707 	DE_UNREF(display);
708 	return result;
709 }
710 
isDisplaySurface(Type wsiType)711 VkBool32 isDisplaySurface (Type wsiType)
712 {
713 	switch (wsiType)
714 	{
715 		case TYPE_XLIB:
716 		case TYPE_XCB:
717 		case TYPE_WAYLAND:
718 		case TYPE_ANDROID:
719 		case TYPE_WIN32:
720 		case TYPE_MACOS:
721 		case TYPE_HEADLESS:
722 			return 0;
723 		case TYPE_DIRECT_DRM:
724 			return 1;
725 		default:
726 			DE_FATAL("Unknown WSI type");
727 			return 0;
728 	}
729 }
730 
createRenderPass(const DeviceInterface & vkd,const VkDevice device,const VkFormat colorAttachmentFormat,const bool explicitLayoutTransitions)731 Move<VkRenderPass> WsiTriangleRenderer::createRenderPass (const DeviceInterface&	vkd,
732 														  const VkDevice			device,
733 														  const VkFormat			colorAttachmentFormat,
734 														  const bool				explicitLayoutTransitions)
735 {
736 	const VkAttachmentDescription	colorAttDesc		=
737 	{
738 		(VkAttachmentDescriptionFlags)0,
739 		colorAttachmentFormat,
740 		VK_SAMPLE_COUNT_1_BIT,
741 		VK_ATTACHMENT_LOAD_OP_CLEAR,
742 		VK_ATTACHMENT_STORE_OP_STORE,
743 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,
744 		VK_ATTACHMENT_STORE_OP_DONT_CARE,
745 		(explicitLayoutTransitions) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED,
746 		(explicitLayoutTransitions) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
747 	};
748 	const VkAttachmentReference		colorAttRef			=
749 	{
750 		0u,
751 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
752 	};
753 	const VkSubpassDescription		subpassDesc			=
754 	{
755 		(VkSubpassDescriptionFlags)0u,
756 		VK_PIPELINE_BIND_POINT_GRAPHICS,
757 		0u,							// inputAttachmentCount
758 		DE_NULL,					// pInputAttachments
759 		1u,							// colorAttachmentCount
760 		&colorAttRef,				// pColorAttachments
761 		DE_NULL,					// pResolveAttachments
762 		DE_NULL,					// depthStencilAttachment
763 		0u,							// preserveAttachmentCount
764 		DE_NULL,					// pPreserveAttachments
765 	};
766 	const VkSubpassDependency		dependencies[]		=
767 	{
768 		{
769 			VK_SUBPASS_EXTERNAL,	// srcSubpass
770 			0u,						// dstSubpass
771 			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
772 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
773 			VK_ACCESS_MEMORY_READ_BIT,
774 			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
775 			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
776 			VK_DEPENDENCY_BY_REGION_BIT
777 		},
778 		{
779 			0u,						// srcSubpass
780 			VK_SUBPASS_EXTERNAL,	// dstSubpass
781 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
782 			VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
783 			(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT|
784 			 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
785 			VK_ACCESS_MEMORY_READ_BIT,
786 			VK_DEPENDENCY_BY_REGION_BIT
787 		},
788 	};
789 	const VkRenderPassCreateInfo	renderPassParams	=
790 	{
791 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
792 		DE_NULL,
793 		(VkRenderPassCreateFlags)0,
794 		1u,
795 		&colorAttDesc,
796 		1u,
797 		&subpassDesc,
798 		DE_LENGTH_OF_ARRAY(dependencies),
799 		dependencies,
800 	};
801 
802 	return vk::createRenderPass(vkd, device, &renderPassParams);
803 }
804 
createPipelineLayout(const DeviceInterface & vkd,const VkDevice device)805 Move<VkPipelineLayout> WsiTriangleRenderer::createPipelineLayout (const DeviceInterface&	vkd,
806 																  const VkDevice			device)
807 {
808 	const VkPushConstantRange						pushConstantRange		=
809 	{
810 		VK_SHADER_STAGE_VERTEX_BIT,
811 		0u,											// offset
812 		(deUint32)sizeof(deUint32),					// size
813 	};
814 	const VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
815 	{
816 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
817 		DE_NULL,
818 		(vk::VkPipelineLayoutCreateFlags)0,
819 		0u,											// setLayoutCount
820 		DE_NULL,									// pSetLayouts
821 		1u,
822 		&pushConstantRange,
823 	};
824 
825 	return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
826 }
827 
createPipeline(const DeviceInterface & vkd,const VkDevice device,const VkRenderPass renderPass,const VkPipelineLayout pipelineLayout,const BinaryCollection & binaryCollection,const tcu::UVec2 & renderSize)828 Move<VkPipeline> WsiTriangleRenderer::createPipeline (const DeviceInterface&	vkd,
829 													  const VkDevice			device,
830 													  const VkRenderPass		renderPass,
831 													  const VkPipelineLayout	pipelineLayout,
832 													  const BinaryCollection&	binaryCollection,
833 													  const tcu::UVec2&			renderSize)
834 {
835 	// \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines()
836 	//		 and can be deleted immediately following that call.
837 	const Unique<VkShaderModule>					vertShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0));
838 	const Unique<VkShaderModule>					fragShaderModule		(createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0));
839 	const std::vector<VkViewport>					viewports				(1, makeViewport(renderSize));
840 	const std::vector<VkRect2D>						scissors				(1, makeRect2D(renderSize));
841 
842 	return vk::makeGraphicsPipeline(vkd,				// const DeviceInterface&            vk
843 									device,				// const VkDevice                    device
844 									pipelineLayout,		// const VkPipelineLayout            pipelineLayout
845 									*vertShaderModule,	// const VkShaderModule              vertexShaderModule
846 									DE_NULL,			// const VkShaderModule              tessellationControlShaderModule
847 									DE_NULL,			// const VkShaderModule              tessellationEvalShaderModule
848 									DE_NULL,			// const VkShaderModule              geometryShaderModule
849 									*fragShaderModule,	// const VkShaderModule              fragmentShaderModule
850 									renderPass,			// const VkRenderPass                renderPass
851 									viewports,			// const std::vector<VkViewport>&    viewports
852 									scissors);			// const std::vector<VkRect2D>&      scissors
853 }
854 
createAttachmentView(const DeviceInterface & vkd,const VkDevice device,const VkImage image,const VkFormat format)855 Move<VkImageView> WsiTriangleRenderer::createAttachmentView (const DeviceInterface&	vkd,
856 															 const VkDevice			device,
857 															 const VkImage			image,
858 															 const VkFormat			format)
859 {
860 	const VkImageViewCreateInfo		viewParams	=
861 	{
862 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
863 		DE_NULL,
864 		(VkImageViewCreateFlags)0,
865 		image,
866 		VK_IMAGE_VIEW_TYPE_2D,
867 		format,
868 		vk::makeComponentMappingRGBA(),
869 		{
870 			VK_IMAGE_ASPECT_COLOR_BIT,
871 			0u,						// baseMipLevel
872 			1u,						// levelCount
873 			0u,						// baseArrayLayer
874 			1u,						// layerCount
875 		},
876 	};
877 
878 	return vk::createImageView(vkd, device, &viewParams);
879 }
880 
createFramebuffer(const DeviceInterface & vkd,const VkDevice device,const VkRenderPass renderPass,const VkImageView colorAttachment,const tcu::UVec2 & renderSize)881 Move<VkFramebuffer> WsiTriangleRenderer::createFramebuffer	(const DeviceInterface&		vkd,
882 															 const VkDevice				device,
883 															 const VkRenderPass			renderPass,
884 															 const VkImageView			colorAttachment,
885 															 const tcu::UVec2&			renderSize)
886 {
887 	const VkFramebufferCreateInfo	framebufferParams	=
888 	{
889 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
890 		DE_NULL,
891 		(VkFramebufferCreateFlags)0,
892 		renderPass,
893 		1u,
894 		&colorAttachment,
895 		renderSize.x(),
896 		renderSize.y(),
897 		1u,							// layers
898 	};
899 
900 	return vk::createFramebuffer(vkd, device, &framebufferParams);
901 }
902 
createBuffer(const DeviceInterface & vkd,VkDevice device,VkDeviceSize size,VkBufferUsageFlags usage)903 Move<VkBuffer> WsiTriangleRenderer::createBuffer (const DeviceInterface&	vkd,
904 												  VkDevice					device,
905 												  VkDeviceSize				size,
906 												  VkBufferUsageFlags		usage)
907 {
908 	const VkBufferCreateInfo	bufferParams	=
909 	{
910 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
911 		DE_NULL,
912 		(VkBufferCreateFlags)0,
913 		size,
914 		usage,
915 		VK_SHARING_MODE_EXCLUSIVE,
916 		0,
917 		DE_NULL
918 	};
919 
920 	return vk::createBuffer(vkd, device, &bufferParams);
921 }
922 
WsiTriangleRenderer(const DeviceInterface & vkd,const VkDevice device,Allocator & allocator,const BinaryCollection & binaryRegistry,bool explicitLayoutTransitions,const vector<VkImage> swapchainImages,const vector<VkImage> aliasImages,const VkFormat framebufferFormat,const tcu::UVec2 & renderSize)923 WsiTriangleRenderer::WsiTriangleRenderer (const DeviceInterface&	vkd,
924 										  const VkDevice			device,
925 										  Allocator&				allocator,
926 										  const BinaryCollection&	binaryRegistry,
927 										  bool						explicitLayoutTransitions,
928 										  const vector<VkImage>		swapchainImages,
929 										  const vector<VkImage>		aliasImages,
930 										  const VkFormat			framebufferFormat,
931 										  const tcu::UVec2&			renderSize)
932 	: m_vkd							(vkd)
933 	, m_explicitLayoutTransitions	(explicitLayoutTransitions)
934 	, m_swapchainImages				(swapchainImages)
935 	, m_aliasImages					(aliasImages)
936 	, m_renderSize					(renderSize)
937 	, m_renderPass					(createRenderPass(vkd, device, framebufferFormat, m_explicitLayoutTransitions))
938 	, m_pipelineLayout				(createPipelineLayout(vkd, device))
939 	, m_pipeline					(createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize))
940 	, m_vertexBuffer				(createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
941 	, m_vertexBufferMemory			(allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer),
942 									 MemoryRequirement::HostVisible))
943 {
944 	m_attachmentViews.resize(swapchainImages.size());
945 	m_attachmentLayouts.resize(swapchainImages.size());
946 	m_framebuffers.resize(swapchainImages.size());
947 
948 	for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
949 	{
950 		m_attachmentViews[imageNdx]		= ImageViewSp(new Unique<VkImageView>(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat)));
951 		m_attachmentLayouts[imageNdx]	= VK_IMAGE_LAYOUT_UNDEFINED;
952 		m_framebuffers[imageNdx]		= FramebufferSp(new Unique<VkFramebuffer>(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize)));
953 	}
954 
955 	VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
956 
957 	{
958 		const VkMappedMemoryRange	memRange	=
959 		{
960 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
961 			DE_NULL,
962 			m_vertexBufferMemory->getMemory(),
963 			m_vertexBufferMemory->getOffset(),
964 			VK_WHOLE_SIZE
965 		};
966 		const tcu::Vec4				vertices[]	=
967 		{
968 			tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
969 			tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
970 			tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
971 		};
972 		DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
973 
974 		deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
975 		VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
976 	}
977 }
978 
WsiTriangleRenderer(WsiTriangleRenderer && other)979 WsiTriangleRenderer::WsiTriangleRenderer (WsiTriangleRenderer&& other)
980 	: m_vkd					(other.m_vkd)
981 	, m_explicitLayoutTransitions	(other.m_explicitLayoutTransitions)
982 	, m_swapchainImages		(other.m_swapchainImages)
983 	, m_aliasImages			(other.m_aliasImages)
984 	, m_renderSize			(other.m_renderSize)
985 	, m_renderPass			(other.m_renderPass)
986 	, m_pipelineLayout		(other.m_pipelineLayout)
987 	, m_pipeline			(other.m_pipeline)
988 	, m_vertexBuffer		(other.m_vertexBuffer)
989 	, m_vertexBufferMemory	(other.m_vertexBufferMemory)
990 	, m_attachmentViews		(other.m_attachmentViews)
991 	, m_attachmentLayouts	(other.m_attachmentLayouts)
992 	, m_framebuffers		(other.m_framebuffers)
993 {
994 }
995 
~WsiTriangleRenderer(void)996 WsiTriangleRenderer::~WsiTriangleRenderer (void)
997 {
998 }
999 
recordFrame(VkCommandBuffer cmdBuffer,deUint32 imageNdx,deUint32 frameNdx) const1000 void WsiTriangleRenderer::recordFrame (VkCommandBuffer	cmdBuffer,
1001 									   deUint32			imageNdx,
1002 									   deUint32			frameNdx) const
1003 {
1004 	const VkFramebuffer	curFramebuffer	= **m_framebuffers[imageNdx];
1005 
1006 	beginCommandBuffer(m_vkd, cmdBuffer, 0u);
1007 
1008 	if (m_explicitLayoutTransitions || m_attachmentLayouts[imageNdx] == VK_IMAGE_LAYOUT_UNDEFINED)
1009 	{
1010 		const auto range		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1011 		const auto newLayout	= (m_explicitLayoutTransitions ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
1012 		const auto srcStage		= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1013 		const auto srcMask		= 0u;
1014 		const auto dstStage		= (m_explicitLayoutTransitions ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
1015 		const auto dstMask		= (m_explicitLayoutTransitions ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT : 0);
1016 
1017 		const auto barrier = makeImageMemoryBarrier(srcMask, dstMask, m_attachmentLayouts[imageNdx], newLayout, m_aliasImages[imageNdx], range);
1018 		m_vkd.cmdPipelineBarrier(cmdBuffer, srcStage, dstStage, 0u, 0u, nullptr, 0u, nullptr, 1u, &barrier);
1019 
1020 		m_attachmentLayouts[imageNdx] = newLayout;
1021 	}
1022 
1023 	beginRenderPass(m_vkd, cmdBuffer, *m_renderPass, curFramebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), tcu::Vec4(0.125f, 0.25f, 0.75f, 1.0f));
1024 
1025 	m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1026 
1027 	{
1028 		const VkDeviceSize bindingOffset = 0;
1029 		m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
1030 	}
1031 
1032 	m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
1033 	m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1034 	endRenderPass(m_vkd, cmdBuffer);
1035 
1036 	if (m_explicitLayoutTransitions)
1037 	{
1038 		VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
1039 		const VkImageMemoryBarrier	barrier	= makeImageMemoryBarrier	(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0,
1040 																		 m_attachmentLayouts[imageNdx], VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
1041 																		 m_aliasImages[imageNdx], range);
1042 		m_vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1043 		m_attachmentLayouts[imageNdx] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
1044 	}
1045 
1046 	endCommandBuffer(m_vkd, cmdBuffer);
1047 }
1048 
recordDeviceGroupFrame(VkCommandBuffer cmdBuffer,deUint32 firstDeviceID,deUint32 secondDeviceID,deUint32 devicesCount,deUint32 imageNdx,deUint32 frameNdx) const1049 void WsiTriangleRenderer::recordDeviceGroupFrame (VkCommandBuffer	cmdBuffer,
1050 												  deUint32			firstDeviceID,
1051 												  deUint32			secondDeviceID,
1052 												  deUint32			devicesCount,
1053 												  deUint32			imageNdx,
1054 												  deUint32			frameNdx) const
1055 {
1056 	const VkFramebuffer	curFramebuffer	= **m_framebuffers[imageNdx];
1057 
1058 	beginCommandBuffer(m_vkd, cmdBuffer, 0u);
1059 
1060 	if (m_explicitLayoutTransitions || m_attachmentLayouts[imageNdx] == VK_IMAGE_LAYOUT_UNDEFINED)
1061 	{
1062 		const auto range		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1063 		const auto newLayout	= (m_explicitLayoutTransitions ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
1064 		const auto srcStage		= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
1065 		const auto srcMask		= 0u;
1066 		const auto dstStage		= (m_explicitLayoutTransitions ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
1067 		const auto dstMask		= (m_explicitLayoutTransitions ? VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT : 0);
1068 
1069 		const auto barrier = makeImageMemoryBarrier(srcMask, dstMask, m_attachmentLayouts[imageNdx], newLayout, m_aliasImages[imageNdx], range);
1070 		m_vkd.cmdPipelineBarrier(cmdBuffer, srcStage, dstStage, 0u, 0u, nullptr, 0u, nullptr, 1u, &barrier);
1071 
1072 		m_attachmentLayouts[imageNdx] = newLayout;
1073 	}
1074 
1075 	// begin renderpass
1076 	{
1077 		const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1078 
1079 		VkRect2D zeroRect = { { 0, 0, },{ 0, 0, } };
1080 		vector<VkRect2D> renderAreas;
1081 		for (deUint32 i = 0; i < devicesCount; i++)
1082 			renderAreas.push_back(zeroRect);
1083 
1084 		// Render completely if there is only 1 device
1085 		if (devicesCount == 1u)
1086 		{
1087 			renderAreas[0].extent.width = (deInt32)m_renderSize.x();
1088 			renderAreas[0].extent.height = (deInt32)m_renderSize.y();
1089 		}
1090 		else
1091 		{
1092 			// Split into 2 vertical halves
1093 			renderAreas[firstDeviceID].extent.width		= (deInt32)m_renderSize.x() / 2;
1094 			renderAreas[firstDeviceID].extent.height	= (deInt32)m_renderSize.y();
1095 			renderAreas[secondDeviceID]					= renderAreas[firstDeviceID];
1096 			renderAreas[secondDeviceID].offset.x		= (deInt32)m_renderSize.x() / 2;
1097 		}
1098 
1099 		const VkDeviceGroupRenderPassBeginInfo deviceGroupRPBeginInfo =
1100 		{
1101 			VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
1102 			DE_NULL,
1103 			(deUint32)((1 << devicesCount) - 1),
1104 			devicesCount,
1105 			&renderAreas[0]
1106 		};
1107 
1108 		const VkRenderPassBeginInfo passBeginParams =
1109 		{
1110 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,						// sType
1111 			&deviceGroupRPBeginInfo,										// pNext
1112 			*m_renderPass,													// renderPass
1113 			curFramebuffer,													// framebuffer
1114 			{
1115 				{ 0, 0 },
1116 				{ m_renderSize.x(), m_renderSize.y() }
1117 			},																// renderArea
1118 			1u,																// clearValueCount
1119 			&clearValue,													// pClearValues
1120 		};
1121 		m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
1122 	}
1123 
1124 	m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1125 
1126 	{
1127 		const VkDeviceSize bindingOffset = 0;
1128 		m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
1129 	}
1130 
1131 	m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx);
1132 	m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1133 	endRenderPass(m_vkd, cmdBuffer);
1134 
1135 	if (m_explicitLayoutTransitions)
1136 	{
1137 		VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
1138 		const VkImageMemoryBarrier	barrier	= makeImageMemoryBarrier	(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0,
1139 																		 m_attachmentLayouts[imageNdx], VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
1140 																		 m_aliasImages[imageNdx], range);
1141 		m_vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
1142 		m_attachmentLayouts[imageNdx] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
1143 	}
1144 
1145 	endCommandBuffer(m_vkd, cmdBuffer);
1146 }
1147 
getPrograms(SourceCollections & dst)1148 void WsiTriangleRenderer::getPrograms (SourceCollections& dst)
1149 {
1150 	dst.glslSources.add("tri-vert") << glu::VertexSource(
1151 		"#version 310 es\n"
1152 		"layout(location = 0) in highp vec4 a_position;\n"
1153 		"layout(push_constant) uniform FrameData\n"
1154 		"{\n"
1155 		"    highp uint frameNdx;\n"
1156 		"} frameData;\n"
1157 		"void main (void)\n"
1158 		"{\n"
1159 		"    highp float angle = float(frameData.frameNdx) / 100.0;\n"
1160 		"    highp float c     = cos(angle);\n"
1161 		"    highp float s     = sin(angle);\n"
1162 		"    highp mat4  t     = mat4( c, -s,  0,  0,\n"
1163 		"                              s,  c,  0,  0,\n"
1164 		"                              0,  0,  1,  0,\n"
1165 		"                              0,  0,  0,  1);\n"
1166 		"    gl_Position = t * a_position;\n"
1167 		"}\n");
1168 	dst.glslSources.add("tri-frag") << glu::FragmentSource(
1169 		"#version 310 es\n"
1170 		"layout(location = 0) out lowp vec4 o_color;\n"
1171 		"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
1172 }
1173 
1174 } // wsi
1175 } // vk
1176