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