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