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