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