Test behaviour of color write enable with colorWriteMask
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / framework / vulkan / vkWsiUtil.cpp
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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<tcu::UVec2>()));
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
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_PRESENT_SRC_KHR,
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
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
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
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
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
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
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
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
863 WsiTriangleRenderer::~WsiTriangleRenderer (void)
864 {
865 }
866
867 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
916 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
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