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