1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Windowing System Integration (WSI) Utilities.
22 *//*--------------------------------------------------------------------*/
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"
32 #include "deArrayUtil.hpp"
40 #if defined (DEQP_SUPPORT_X11)
41 # include <X11/Xlib.h>
42 # if defined (DEQP_SUPPORT_XCB)
44 # endif // DEQP_SUPPORT_XCB
45 #endif // DEQP_SUPPORT_X11
47 #if defined (DEQP_SUPPORT_WAYLAND)
48 # include "tcuLnxWayland.hpp"
49 # define WAYLAND_DISPLAY DE_NULL
50 #endif // DEQP_SUPPORT_WAYLAND
52 #if ( DE_OS == DE_OS_WIN32 )
54 #define WIN32_LEAN_AND_MEAN
63 //! Get canonical WSI name that should be used for example in test case and group names.
64 const char* getName (Type wsiType)
66 static const char* const s_names[] =
76 return de::getSizedArrayElement<TYPE_LAST>(s_names, wsiType);
79 const char* getExtensionName (Type wsiType)
81 static const char* const s_extNames[] =
83 "VK_KHR_xlib_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"
91 return de::getSizedArrayElement<TYPE_LAST>(s_extNames, wsiType);
94 const PlatformProperties& getPlatformProperties (Type wsiType)
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
101 const deUint32 noDisplayLimit = std::numeric_limits<deUint32>::max();
102 const deUint32 noWindowLimit = std::numeric_limits<deUint32>::max();
104 static const PlatformProperties s_properties[] =
106 // VK_KHR_xlib_surface
108 PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
109 PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
113 // VK_KHR_xcb_surface
115 PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
116 PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
120 // VK_KHR_wayland_surface
123 PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE,
127 // VK_KHR_android_surface
129 PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE,
130 PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE,
132 1u, // Only one window available
134 // VK_KHR_win32_surface
136 PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
137 PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
141 // VK_MVK_macos_surface
143 PlatformProperties::FEATURE_INITIAL_WINDOW_SIZE|PlatformProperties::FEATURE_RESIZE_WINDOW,
144 PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE,
148 // VK_EXT_headless_surface
151 PlatformProperties::SWAPCHAIN_EXTENT_SETS_WINDOW_SIZE,
157 return de::getSizedArrayElement<TYPE_LAST>(s_properties, wsiType);
160 VkResult createSurface (const InstanceInterface& vki,
163 const Display& nativeDisplay,
164 const Window& nativeWindow,
165 const VkAllocationCallbacks* pAllocator,
166 VkSurfaceKHR* pSurface)
168 // Update this function if you add more WSI implementations
169 DE_STATIC_ASSERT(TYPE_LAST == 7);
175 const XlibDisplayInterface& xlibDisplay = dynamic_cast<const XlibDisplayInterface&>(nativeDisplay);
176 const XlibWindowInterface& xlibWindow = dynamic_cast<const XlibWindowInterface&>(nativeWindow);
177 const VkXlibSurfaceCreateInfoKHR createInfo =
179 VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
181 (VkXlibSurfaceCreateFlagsKHR)0,
182 xlibDisplay.getNative(),
183 xlibWindow.getNative()
186 return vki.createXlibSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
191 const XcbDisplayInterface& xcbDisplay = dynamic_cast<const XcbDisplayInterface&>(nativeDisplay);
192 const XcbWindowInterface& xcbWindow = dynamic_cast<const XcbWindowInterface&>(nativeWindow);
193 const VkXcbSurfaceCreateInfoKHR createInfo =
195 VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
197 (VkXcbSurfaceCreateFlagsKHR)0,
198 xcbDisplay.getNative(),
199 xcbWindow.getNative()
202 return vki.createXcbSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
207 const WaylandDisplayInterface& waylandDisplay = dynamic_cast<const WaylandDisplayInterface&>(nativeDisplay);
208 const WaylandWindowInterface& waylandWindow = dynamic_cast<const WaylandWindowInterface&>(nativeWindow);
209 const VkWaylandSurfaceCreateInfoKHR createInfo =
211 VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
213 (VkWaylandSurfaceCreateFlagsKHR)0,
214 waylandDisplay.getNative(),
215 waylandWindow.getNative()
218 return vki.createWaylandSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
223 const AndroidWindowInterface& androidWindow = dynamic_cast<const AndroidWindowInterface&>(nativeWindow);
224 const VkAndroidSurfaceCreateInfoKHR createInfo =
226 VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
228 (VkAndroidSurfaceCreateFlagsKHR)0,
229 androidWindow.getNative()
232 return vki.createAndroidSurfaceKHR(instance, &createInfo, pAllocator, pSurface);
237 const Win32DisplayInterface& win32Display = dynamic_cast<const Win32DisplayInterface&>(nativeDisplay);
238 const Win32WindowInterface& win32Window = dynamic_cast<const Win32WindowInterface&>(nativeWindow);
239 const VkWin32SurfaceCreateInfoKHR createInfo =
241 VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
243 (VkWin32SurfaceCreateFlagsKHR)0,
244 win32Display.getNative(),
245 win32Window.getNative()
248 return vki.createWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
253 const MacOSWindowInterface& macOSWindow = dynamic_cast<const MacOSWindowInterface&>(nativeWindow);
254 const VkMacOSSurfaceCreateInfoMVK createInfo =
256 VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
258 (VkMacOSSurfaceCreateFlagsMVK)0,
259 macOSWindow.getNative()
262 return vki.createMacOSSurfaceMVK(instance, &createInfo, pAllocator, pSurface);
267 const VkHeadlessSurfaceCreateInfoEXT createInfo =
269 VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT,
271 (VkHeadlessSurfaceCreateFlagsEXT)0
274 return vki.createHeadlessSurfaceEXT(instance, &createInfo, pAllocator, pSurface);
278 DE_FATAL("Unknown WSI type");
279 return VK_ERROR_SURFACE_LOST_KHR;
283 Move<VkSurfaceKHR> createSurface (const InstanceInterface& vki,
286 const Display& nativeDisplay,
287 const Window& nativeWindow,
288 const VkAllocationCallbacks* pAllocator)
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));
295 VkBool32 getPhysicalDeviceSurfaceSupport (const InstanceInterface& vki,
296 VkPhysicalDevice physicalDevice,
297 deUint32 queueFamilyIndex,
298 VkSurfaceKHR surface)
302 VK_CHECK(vki.getPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, &result));
307 VkBool32 getPhysicalDevicePresentationSupport (const InstanceInterface& vki,
308 VkPhysicalDevice physicalDevice,
309 deUint32 queueFamilyIndex,
311 const Display& nativeDisplay)
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);
323 return vki.getPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, xlibDisplay.getNative(), visualID);
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);
334 return vki.getPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex, xcbDisplay.getNative(), visualID);
338 const WaylandDisplayInterface& waylandDisplay = dynamic_cast<const WaylandDisplayInterface&>(nativeDisplay);
339 return vki.getPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, waylandDisplay.getNative());
343 return vki.getPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
352 DE_FATAL("Unknown WSI type");
358 VkSurfaceCapabilitiesKHR getPhysicalDeviceSurfaceCapabilities (const InstanceInterface& vki,
359 VkPhysicalDevice physicalDevice,
360 VkSurfaceKHR surface)
362 VkSurfaceCapabilitiesKHR capabilities;
364 deMemset(&capabilities, 0, sizeof(capabilities));
366 VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities));
371 VkSurfaceCapabilities2EXT getPhysicalDeviceSurfaceCapabilities2EXT (const InstanceInterface& vki,
372 VkPhysicalDevice physicalDevice,
373 VkSurfaceKHR surface)
375 VkSurfaceCapabilities2EXT capabilities;
377 deMemset(&capabilities, 0, sizeof(capabilities));
378 capabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT;
380 VK_CHECK(vki.getPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, &capabilities));
385 bool sameSurfaceCapabilities (const VkSurfaceCapabilitiesKHR& khr,
386 const VkSurfaceCapabilities2EXT& ext)
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 );
403 std::vector<VkSurfaceFormatKHR> getPhysicalDeviceSurfaceFormats (const InstanceInterface& vki,
404 VkPhysicalDevice physicalDevice,
405 VkSurfaceKHR surface)
407 deUint32 numFormats = 0;
409 VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, DE_NULL));
413 std::vector<VkSurfaceFormatKHR> formats (numFormats);
415 VK_CHECK(vki.getPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &numFormats, &formats[0]));
420 return std::vector<VkSurfaceFormatKHR>();
423 std::vector<VkPresentModeKHR> getPhysicalDeviceSurfacePresentModes (const InstanceInterface& vki,
424 VkPhysicalDevice physicalDevice,
425 VkSurfaceKHR surface)
427 deUint32 numModes = 0;
429 VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, DE_NULL));
433 std::vector<VkPresentModeKHR> modes (numModes);
435 VK_CHECK(vki.getPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &numModes, &modes[0]));
440 return std::vector<VkPresentModeKHR>();
443 std::vector<VkImage> getSwapchainImages (const DeviceInterface& vkd,
445 VkSwapchainKHR swapchain)
447 deUint32 numImages = 0;
449 VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL));
453 std::vector<VkImage> images (numImages);
455 VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0]));
460 return std::vector<VkImage>();
466 std::vector<deUint32> getSupportedQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface)
468 deUint32 numTotalFamilyIndices;
469 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numTotalFamilyIndices, DE_NULL);
471 std::vector<VkQueueFamilyProperties> queueFamilyProperties(numTotalFamilyIndices);
472 vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numTotalFamilyIndices, &queueFamilyProperties[0]);
474 std::vector<deUint32> supportedFamilyIndices;
475 for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx)
477 if (getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE)
478 supportedFamilyIndices.push_back(queueFamilyNdx);
481 return supportedFamilyIndices;
484 std::vector<deUint32> getSortedSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
486 std::vector<deUint32> indices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface);
487 std::sort(begin(indices), end(indices));
493 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const std::vector<vk::VkSurfaceKHR>& surfaces)
495 auto indices = getCompatibleQueueFamilyIndices(vki, physicalDevice, surfaces);
498 TCU_THROW(NotSupportedError, "Device does not support presentation to the given surfaces");
503 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface)
505 return chooseQueueFamilyIndex(vki, physicalDevice, std::vector<vk::VkSurfaceKHR>(1u, surface));
508 std::vector<deUint32> getCompatibleQueueFamilyIndices (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, const std::vector<VkSurfaceKHR>& surfaces)
510 DE_ASSERT(!surfaces.empty());
512 auto indices = getSortedSupportedQueueFamilyIndices(vki, physicalDevice, surfaces[0]);
514 for (size_t i = 1; i < surfaces.size(); ++i)
516 auto newIndices = getSortedSupportedQueueFamilyIndices(vki, physicalDevice, surfaces[i]);
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);
527 tcu::UVec2 getFullScreenSize (const vk::wsi::Type wsiType, const vk::wsi::Display& display, const tcu::UVec2& fallbackSize)
529 tcu::UVec2 result = fallbackSize;
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);
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);
557 #if defined (DEQP_SUPPORT_WAYLAND)
563 #if ( DE_OS == DE_OS_ANDROID )
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));
584 #if ( DE_OS == DE_OS_OSX )
590 DE_FATAL("Unknown WSI type");
598 Move<VkRenderPass> WsiTriangleRenderer::createRenderPass (const DeviceInterface& vkd,
599 const VkDevice device,
600 const VkFormat colorAttachmentFormat,
601 const bool explicitLayoutTransitions)
603 const VkAttachmentDescription colorAttDesc =
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,
615 const VkAttachmentReference colorAttRef =
618 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
620 const VkSubpassDescription subpassDesc =
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
633 const VkSubpassDependency dependencies[] =
636 VK_SUBPASS_EXTERNAL, // srcSubpass
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
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
656 const VkRenderPassCreateInfo renderPassParams =
658 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
660 (VkRenderPassCreateFlags)0,
665 DE_LENGTH_OF_ARRAY(dependencies),
669 return vk::createRenderPass(vkd, device, &renderPassParams);
672 Move<VkPipelineLayout> WsiTriangleRenderer::createPipelineLayout (const DeviceInterface& vkd,
673 const VkDevice device)
675 const VkPushConstantRange pushConstantRange =
677 VK_SHADER_STAGE_VERTEX_BIT,
679 (deUint32)sizeof(deUint32), // size
681 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
683 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
685 (vk::VkPipelineLayoutCreateFlags)0,
686 0u, // setLayoutCount
687 DE_NULL, // pSetLayouts
692 return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams);
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)
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));
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
722 Move<VkImageView> WsiTriangleRenderer::createAttachmentView (const DeviceInterface& vkd,
723 const VkDevice device,
725 const VkFormat format)
727 const VkImageViewCreateInfo viewParams =
729 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
731 (VkImageViewCreateFlags)0,
733 VK_IMAGE_VIEW_TYPE_2D,
735 vk::makeComponentMappingRGBA(),
737 VK_IMAGE_ASPECT_COLOR_BIT,
740 0u, // baseArrayLayer
745 return vk::createImageView(vkd, device, &viewParams);
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)
754 const VkFramebufferCreateInfo framebufferParams =
756 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
758 (VkFramebufferCreateFlags)0,
767 return vk::createFramebuffer(vkd, device, &framebufferParams);
770 Move<VkBuffer> WsiTriangleRenderer::createBuffer (const DeviceInterface& vkd,
773 VkBufferUsageFlags usage)
775 const VkBufferCreateInfo bufferParams =
777 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
779 (VkBufferCreateFlags)0,
782 VK_SHARING_MODE_EXCLUSIVE,
787 return vk::createBuffer(vkd, device, &bufferParams);
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)
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))
811 m_attachmentViews.resize(swapchainImages.size());
812 m_attachmentLayouts.resize(swapchainImages.size());
813 m_framebuffers.resize(swapchainImages.size());
815 for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx)
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)));
822 VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset()));
825 const VkMappedMemoryRange memRange =
827 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
829 m_vertexBufferMemory->getMemory(),
830 m_vertexBufferMemory->getOffset(),
833 const tcu::Vec4 vertices[] =
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)
839 DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3);
841 deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices));
842 VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange));
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)
863 WsiTriangleRenderer::~WsiTriangleRenderer (void)
867 void WsiTriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer,
869 deUint32 frameNdx) const
871 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx];
873 beginCommandBuffer(m_vkd, cmdBuffer, 0u);
875 if (m_explicitLayoutTransitions || m_attachmentLayouts[imageNdx] == VK_IMAGE_LAYOUT_UNDEFINED)
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);
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);
887 m_attachmentLayouts[imageNdx] = newLayout;
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));
892 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
895 const VkDeviceSize bindingOffset = 0;
896 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
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);
903 if (m_explicitLayoutTransitions)
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;
913 endCommandBuffer(m_vkd, cmdBuffer);
916 void WsiTriangleRenderer::recordDeviceGroupFrame (VkCommandBuffer cmdBuffer,
917 deUint32 firstDeviceID,
918 deUint32 secondDeviceID,
919 deUint32 devicesCount,
921 deUint32 frameNdx) const
923 const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx];
925 beginCommandBuffer(m_vkd, cmdBuffer, 0u);
927 if (m_explicitLayoutTransitions || m_attachmentLayouts[imageNdx] == VK_IMAGE_LAYOUT_UNDEFINED)
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);
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);
939 m_attachmentLayouts[imageNdx] = newLayout;
944 const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
946 VkRect2D zeroRect = { { 0, 0, },{ 0, 0, } };
947 vector<VkRect2D> renderAreas;
948 for (deUint32 i = 0; i < devicesCount; i++)
949 renderAreas.push_back(zeroRect);
951 // Render completely if there is only 1 device
952 if (devicesCount == 1u)
954 renderAreas[0].extent.width = (deInt32)m_renderSize.x();
955 renderAreas[0].extent.height = (deInt32)m_renderSize.y();
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;
966 const VkDeviceGroupRenderPassBeginInfo deviceGroupRPBeginInfo =
968 VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
970 (deUint32)((1 << devicesCount) - 1),
975 const VkRenderPassBeginInfo passBeginParams =
977 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
978 &deviceGroupRPBeginInfo, // pNext
979 *m_renderPass, // renderPass
980 curFramebuffer, // framebuffer
983 { m_renderSize.x(), m_renderSize.y() }
985 1u, // clearValueCount
986 &clearValue, // pClearValues
988 m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
991 m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
994 const VkDeviceSize bindingOffset = 0;
995 m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset);
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);
1002 if (m_explicitLayoutTransitions)
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;
1012 endCommandBuffer(m_vkd, cmdBuffer);
1015 void WsiTriangleRenderer::getPrograms (SourceCollections& dst)
1017 dst.glslSources.add("tri-vert") << glu::VertexSource(
1019 "layout(location = 0) in highp vec4 a_position;\n"
1020 "layout(push_constant) uniform FrameData\n"
1022 " highp uint frameNdx;\n"
1024 "void main (void)\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"
1033 " gl_Position = t * a_position;\n"
1035 dst.glslSources.add("tri-frag") << glu::FragmentSource(
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");