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