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