diff --git a/src/xrt/compositor/CMakeLists.txt b/src/xrt/compositor/CMakeLists.txt index 9cbc08c24..7e035a242 100644 --- a/src/xrt/compositor/CMakeLists.txt +++ b/src/xrt/compositor/CMakeLists.txt @@ -23,10 +23,9 @@ set(MAIN_SOURCE_FILES main/comp_shaders.c main/comp_swapchain.c main/comp_target.h - main/comp_vk_swapchain.c - main/comp_vk_swapchain.h + main/comp_target_swapchain.c + main/comp_target_swapchain.h main/comp_window.h - main/comp_window_target.c main/comp_layer.h main/comp_layer.c main/comp_layer_renderer.h diff --git a/src/xrt/compositor/main/comp_target_swapchain.c b/src/xrt/compositor/main/comp_target_swapchain.c new file mode 100644 index 000000000..c7b612534 --- /dev/null +++ b/src/xrt/compositor/main/comp_target_swapchain.c @@ -0,0 +1,508 @@ +// Copyright 2019-2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Target Vulkan swapchain code. + * @author Lubosz Sarnecki + * @author Jakob Bornecrantz + * @ingroup comp_main + */ + + +#include +#include +#include +#include + +#include "util/u_misc.h" + +#include "comp_target_swapchain.h" + + +/* + * + * Types, defines and data. + * + */ + +/*! + * These formats will be 'preferred' - in future we may wish to give preference + * to higher bit depths if they are available, but most display devices we are + * interested in should support one these. + */ +static VkFormat preferred_color_formats[] = { + VK_FORMAT_R8G8B8A8_SRGB, + VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_B8G8R8A8_UNORM, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, +}; + + +/* + * + * Pre declare functions. + * + */ + +static void +comp_target_swapchain_create_image_views(struct comp_target_swapchain *cts); + +static void +comp_target_swapchain_destroy_image_views(struct comp_target_swapchain *cts); + +static void +comp_target_swapchain_destroy_old(struct comp_target_swapchain *cts, + VkSwapchainKHR old); + +static VkExtent2D +comp_target_swapchain_select_extent(struct comp_target_swapchain *cts, + VkSurfaceCapabilitiesKHR caps, + uint32_t width, + uint32_t height); + +static bool +_find_surface_format(struct comp_target_swapchain *cts, + VkSurfaceKHR surface, + VkSurfaceFormatKHR *format); + +static bool +_check_surface_present_mode(struct vk_bundle *vk, + VkSurfaceKHR surface, + VkPresentModeKHR present_mode); + + +/* + * + * Functions! + * + */ + +void +comp_target_swapchain_create_images(struct comp_target *ct, + uint32_t width, + uint32_t height, + VkFormat color_format, + VkColorSpaceKHR color_space, + VkPresentModeKHR present_mode) +{ + struct comp_target_swapchain *cts = (struct comp_target_swapchain *)ct; + VkBool32 supported; + VkResult ret; + + // Free old image views. + comp_target_swapchain_destroy_image_views(cts); + + VkSwapchainKHR old_swapchain_handle = cts->swapchain.handle; + + cts->base.num_images = 0; + cts->swapchain.handle = VK_NULL_HANDLE; + cts->present_mode = present_mode; + cts->preferred.color_format = color_format; + cts->preferred.color_space = color_space; + + + // Sanity check. + cts->vk->vkGetPhysicalDeviceSurfaceSupportKHR( + cts->vk->physical_device, 0, cts->surface.handle, &supported); + if (!supported) { + VK_ERROR(cts->vk, + "vkGetPhysicalDeviceSurfaceSupportKHR: " + "surface not supported!"); + } + + // More sanity checks. + if (!_check_surface_present_mode(cts->vk, cts->surface.handle, + cts->present_mode)) { + // Free old. + comp_target_swapchain_destroy_old(cts, old_swapchain_handle); + return; + } + + // Find the correct format. + if (!_find_surface_format(cts, cts->surface.handle, + &cts->surface.format)) { + // Free old. + comp_target_swapchain_destroy_old(cts, old_swapchain_handle); + return; + } + + // Get the caps first. + VkSurfaceCapabilitiesKHR surface_caps; + ret = cts->vk->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + cts->vk->physical_device, cts->surface.handle, &surface_caps); + if (ret != VK_SUCCESS) { + VK_ERROR(cts->vk, + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR: %s", + vk_result_string(ret)); + + // Free old. + comp_target_swapchain_destroy_old(cts, old_swapchain_handle); + return; + } + + // Get the extents of the swapchain. + VkExtent2D extent = comp_target_swapchain_select_extent( + cts, surface_caps, width, height); + + // Create the swapchain now. + VkSwapchainCreateInfoKHR swapchain_info = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .surface = cts->surface.handle, + .minImageCount = surface_caps.minImageCount, + .imageFormat = cts->surface.format.format, + .imageColorSpace = cts->surface.format.colorSpace, + .imageExtent = + { + .width = extent.width, + .height = extent.height, + }, + .imageArrayLayers = 1, + .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = cts->present_mode, + .clipped = VK_TRUE, + .oldSwapchain = old_swapchain_handle, + }; + + ret = cts->vk->vkCreateSwapchainKHR(cts->vk->device, &swapchain_info, + NULL, &cts->swapchain.handle); + + // Always destroy the old. + comp_target_swapchain_destroy_old(cts, old_swapchain_handle); + + if (ret != VK_SUCCESS) { + VK_ERROR(cts->vk, "vkCreateSwapchainKHR: %s", + vk_result_string(ret)); + return; + } + + + /* + * Set target info. + */ + + cts->base.width = extent.width; + cts->base.height = extent.height; + cts->base.format = cts->surface.format.format; + + comp_target_swapchain_create_image_views(cts); +} + +static VkExtent2D +comp_target_swapchain_select_extent(struct comp_target_swapchain *cts, + VkSurfaceCapabilitiesKHR caps, + uint32_t width, + uint32_t height) +{ + // If width (and height) equals the special value 0xFFFFFFFF, + // the size of the surface will be set by the swapchain + if (caps.currentExtent.width == (uint32_t)-1) { + VkExtent2D extent = { + .width = width, + .height = height, + }; + return extent; + } + + if (caps.currentExtent.width != width || + caps.currentExtent.height != height) { + VK_DEBUG(cts->vk, + "Using swap chain extent dimensions %dx%d instead of " + "requested %dx%d.", + caps.currentExtent.width, caps.currentExtent.height, + width, height); + } + + return caps.currentExtent; +} + +static void +comp_target_swapchain_destroy_old(struct comp_target_swapchain *cts, + VkSwapchainKHR old) +{ + if (old != VK_NULL_HANDLE) { + cts->vk->vkDestroySwapchainKHR(cts->vk->device, old, NULL); + } +} + +VkResult +comp_target_swapchain_acquire_next_image(struct comp_target *ct, + VkSemaphore semaphore, + uint32_t *out_index) +{ + struct comp_target_swapchain *cts = (struct comp_target_swapchain *)ct; + + return cts->vk->vkAcquireNextImageKHR( // + cts->vk->device, // device + cts->swapchain.handle, // timeout + UINT64_MAX, // timeout + semaphore, // semaphore + VK_NULL_HANDLE, // fence + out_index); // pImageIndex +} + +VkResult +comp_target_swapchain_present(struct comp_target *ct, + VkQueue queue, + uint32_t index, + VkSemaphore semaphore) +{ + struct comp_target_swapchain *cts = (struct comp_target_swapchain *)ct; + + VkPresentInfoKHR presentInfo = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &semaphore, + .swapchainCount = 1, + .pSwapchains = &cts->swapchain.handle, + .pImageIndices = &index, + }; + + return cts->vk->vkQueuePresentKHR(queue, &presentInfo); +} + +static bool +_find_surface_format(struct comp_target_swapchain *cts, + VkSurfaceKHR surface, + VkSurfaceFormatKHR *format) +{ + uint32_t num_formats; + VkSurfaceFormatKHR *formats = NULL; + cts->vk->vkGetPhysicalDeviceSurfaceFormatsKHR( + cts->vk->physical_device, surface, &num_formats, NULL); + + if (num_formats != 0) { + formats = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, num_formats); + cts->vk->vkGetPhysicalDeviceSurfaceFormatsKHR( + cts->vk->physical_device, surface, &num_formats, formats); + } else { + VK_ERROR(cts->vk, "Could not enumerate surface formats."); + return false; + } + + VkSurfaceFormatKHR *formats_for_colorspace = NULL; + formats_for_colorspace = + U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, num_formats); + + uint32_t num_formats_cs = 0; + uint32_t num_pref_formats = ARRAY_SIZE(preferred_color_formats); + + // Gather formats that match our color space, we will select + // from these in preference to others. + + for (uint32_t i = 0; i < num_formats; i++) { + if (formats[i].colorSpace == cts->preferred.color_space) { + formats_for_colorspace[num_formats_cs] = formats[i]; + num_formats_cs++; + } + } + + if (num_formats_cs > 0) { + // we have at least one format with our preferred colorspace + // if we have one that is on our preferred formats list, use it + + for (uint32_t i = 0; i < num_formats_cs; i++) { + if (formats_for_colorspace[i].format == + cts->preferred.color_format) { + // perfect match. + *format = formats_for_colorspace[i]; + goto cleanup; + } + } + + // we don't have our swapchain default format and colorspace, + // but we may have at least one preferred format with the + // correct colorspace. + for (uint32_t i = 0; i < num_formats_cs; i++) { + for (uint32_t j = 0; j < num_pref_formats; j++) { + if (formats_for_colorspace[i].format == + preferred_color_formats[j]) { + *format = formats_for_colorspace[i]; + goto cleanup; + } + } + } + + // are we still here? this means we have a format with our + // preferred colorspace but we have no preferred color format - + // maybe we only have 10/12 bpc or 15/16bpp format. return the + // first one we have, at least its in the right color space. + *format = formats_for_colorspace[0]; + VK_ERROR(cts->vk, "Returning unknown color format"); + goto cleanup; + + } else { + + // we have nothing with the preferred colorspace? we can try to + // return a preferred format at least + for (uint32_t i = 0; i < num_formats; i++) { + for (uint32_t j = 0; j < num_pref_formats; j++) { + if (formats[i].format == + preferred_color_formats[j]) { + *format = formats_for_colorspace[i]; + VK_ERROR( + cts->vk, + "Returning known-wrong color " + "space! Color shift may occur."); + goto cleanup; + } + } + } + // if we are still here, we should just return the first format + // we have. we know its the wrong colorspace, and its not on our + // list of preferred formats, but its something. + *format = formats[0]; + VK_ERROR(cts->vk, + "Returning fallback format! cue up some Kenny " + "Loggins, cos we're in the DANGER ZONE!"); + goto cleanup; + } + + VK_ERROR(cts->vk, "We should not be here"); + goto error; + +cleanup: + free(formats_for_colorspace); + free(formats); + return true; + +error: + free(formats_for_colorspace); + free(formats); + return false; +} + +static bool +_check_surface_present_mode(struct vk_bundle *vk, + VkSurfaceKHR surface, + VkPresentModeKHR present_mode) +{ + uint32_t num_present_modes; + VkPresentModeKHR *present_modes; + vk->vkGetPhysicalDeviceSurfacePresentModesKHR( + vk->physical_device, surface, &num_present_modes, NULL); + + if (num_present_modes != 0) { + present_modes = + U_TYPED_ARRAY_CALLOC(VkPresentModeKHR, num_present_modes); + vk->vkGetPhysicalDeviceSurfacePresentModesKHR( + vk->physical_device, surface, &num_present_modes, + present_modes); + } else { + VK_ERROR(vk, "Could not enumerate present modes."); + return false; + } + + for (uint32_t i = 0; i < num_present_modes; i++) { + if (present_modes[i] == present_mode) { + free(present_modes); + return true; + } + } + + free(present_modes); + VK_ERROR(vk, "Requested present mode not supported.\n"); + return false; +} + +static void +comp_target_swapchain_destroy_image_views(struct comp_target_swapchain *cts) +{ + if (cts->base.images == NULL) { + return; + } + + for (uint32_t i = 0; i < cts->base.num_images; i++) { + if (cts->base.images[i].view == VK_NULL_HANDLE) { + continue; + } + + cts->vk->vkDestroyImageView(cts->vk->device, + cts->base.images[i].view, NULL); + cts->base.images[i].view = VK_NULL_HANDLE; + } + + free(cts->base.images); + cts->base.images = NULL; +} + +static void +comp_target_swapchain_create_image_views(struct comp_target_swapchain *cts) +{ + cts->vk->vkGetSwapchainImagesKHR( // + cts->vk->device, // device + cts->swapchain.handle, // swapchain + &cts->base.num_images, // pSwapchainImageCount + NULL); // pSwapchainImages + assert(cts->base.num_images > 0); + VK_DEBUG(cts->vk, "Creating %d image views.", cts->base.num_images); + + VkImage *images = U_TYPED_ARRAY_CALLOC(VkImage, cts->base.num_images); + cts->vk->vkGetSwapchainImagesKHR( // + cts->vk->device, // device + cts->swapchain.handle, // swapchain + &cts->base.num_images, // pSwapchainImageCount + images); // pSwapchainImages + + comp_target_swapchain_destroy_image_views(cts); + + cts->base.images = U_TYPED_ARRAY_CALLOC(struct comp_target_image, + cts->base.num_images); + + VkImageSubresourceRange subresource_range = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + for (uint32_t i = 0; i < cts->base.num_images; i++) { + cts->base.images[i].handle = images[i]; + vk_create_view(cts->vk, cts->base.images[i].handle, + cts->surface.format.format, subresource_range, + &cts->base.images[i].view); + } + + free(images); +} + +void +comp_target_swapchain_cleanup(struct comp_target_swapchain *cts) +{ + comp_target_swapchain_destroy_image_views(cts); + + if (cts->swapchain.handle != VK_NULL_HANDLE) { + cts->vk->vkDestroySwapchainKHR( // + cts->vk->device, // device + cts->swapchain.handle, // swapchain + NULL); // + cts->swapchain.handle = VK_NULL_HANDLE; + } + + if (cts->surface.handle != VK_NULL_HANDLE) { + cts->vk->vkDestroySurfaceKHR( // + cts->vk->instance, // instance + cts->surface.handle, // surface + NULL); // + cts->swapchain.handle = VK_NULL_HANDLE; + } +} + +void +comp_target_swapchain_init_set_fnptrs(struct comp_target_swapchain *cts) +{ + cts->base.create_images = comp_target_swapchain_create_images; + cts->base.acquire = comp_target_swapchain_acquire_next_image; + cts->base.present = comp_target_swapchain_present; +} + +void +comp_target_swapchain_init_post_vulkan(struct comp_target_swapchain *cts, + struct vk_bundle *vk) +{ + cts->vk = vk; +} diff --git a/src/xrt/compositor/main/comp_target_swapchain.h b/src/xrt/compositor/main/comp_target_swapchain.h new file mode 100644 index 000000000..a1f34c8a9 --- /dev/null +++ b/src/xrt/compositor/main/comp_target_swapchain.h @@ -0,0 +1,109 @@ +// Copyright 2019-2020, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Target Vulkan swapchain code header. + * @author Lubosz Sarnecki + * @author Jakob Bornecrantz + * @ingroup comp_main + */ + +#pragma once + +#include "vk/vk_helpers.h" + +#include "main/comp_target.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * + * Structs. + * + */ + +/*! + * Wraps and manage VkSwapchainKHR and VkSurfaceKHR, used by @ref comp code. + * + * @ingroup comp_main + */ +struct comp_target_swapchain +{ + //! Base target. + struct comp_target base; + + struct vk_bundle *vk; + + struct + { + VkSwapchainKHR handle; + } swapchain; + + struct + { + VkSurfaceKHR handle; + VkSurfaceFormatKHR format; + } surface; + + struct + { + VkFormat color_format; + VkColorSpaceKHR color_space; + } preferred; + + //! Present mode that the system must support. + VkPresentModeKHR present_mode; +}; + + +/* + * + * Functions. + * + */ + +/*! + * Pre Vulkan initialisation, sets function pointers. + */ +void +comp_target_swapchain_init_set_fnptrs(struct comp_target_swapchain *cts); + +/*! + * Initialize the given @ref comp_target_swapchain, does not allocate. + * + * @ingroup comp_main + */ +void +comp_target_swapchain_init_post_vulkan(struct comp_target_swapchain *cts, + struct vk_bundle *vk); + +/*! + * See comp_target::create_images. + * + * @ingroup comp_main + */ +void +comp_target_swapchain_create_images(struct comp_target *ct, + uint32_t width, + uint32_t height, + VkFormat color_format, + VkColorSpaceKHR color_space, + VkPresentModeKHR present_mode); + +/*! + * Free all managed resources on the given @ref comp_target_swapchain, + * does not free the struct itself. + * + * @ingroup comp_main + */ +void +comp_target_swapchain_cleanup(struct comp_target_swapchain *cts); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/compositor/main/comp_vk_swapchain.c b/src/xrt/compositor/main/comp_vk_swapchain.c deleted file mode 100644 index addcd55ce..000000000 --- a/src/xrt/compositor/main/comp_vk_swapchain.c +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright 2019, Collabora, Ltd. -// SPDX-License-Identifier: BSL-1.0 -/*! - * @file - * @brief Vulkan swapchain code. - * @author Lubosz Sarnecki - * @author Jakob Bornecrantz - * @ingroup comp_main - */ - - -#include -#include -#include -#include - -#include "util/u_misc.h" - -#include "comp_vk_swapchain.h" - - -/* - * - * Types, defines and data. - * - */ - -/*! - * These formats will be 'preferred' - in future we may wish to give preference - * to higher bit depths if they are available, but most display devices we are - * interested in should support one these. - */ -static VkFormat preferred_color_formats[] = { - VK_FORMAT_R8G8B8A8_SRGB, - VK_FORMAT_R8G8B8A8_UNORM, - VK_FORMAT_B8G8R8A8_UNORM, - VK_FORMAT_A8B8G8R8_UNORM_PACK32, -}; - - -/* - * - * Pre declare functions. - * - */ - -static void -vk_swapchain_create_image_views(struct vk_swapchain *sc); - -static void -vk_swapchain_destroy_image_views(struct vk_swapchain *sc); - -static void -vk_swapchain_destroy_old(struct vk_swapchain *sc, VkSwapchainKHR old); - -static VkExtent2D -vk_swapchain_select_extent(struct vk_swapchain *sc, - VkSurfaceCapabilitiesKHR caps, - uint32_t width, - uint32_t height); - -static bool -_find_surface_format(struct vk_swapchain *sc, - VkSurfaceKHR surface, - VkSurfaceFormatKHR *format); - -static bool -_check_surface_present_mode(struct vk_bundle *vk, - VkSurfaceKHR surface, - VkPresentModeKHR present_mode); - - -/* - * - * Functions! - * - */ - -void -vk_swapchain_init(struct vk_swapchain *sc, struct vk_bundle *vk) -{ - sc->vk = vk; -} - -void -vk_swapchain_create(struct vk_swapchain *sc, - uint32_t width, - uint32_t height, - VkFormat color_format, - VkColorSpaceKHR color_space, - VkPresentModeKHR present_mode) -{ - VkBool32 supported; - VkResult ret; - - // Free old image views. - vk_swapchain_destroy_image_views(sc); - - VkSwapchainKHR old_swapchain_handle = sc->swapchain.handle; - - sc->base.num_images = 0; - sc->swapchain.handle = VK_NULL_HANDLE; - sc->present_mode = present_mode; - sc->preferred.color_format = color_format; - sc->preferred.color_space = color_space; - - - // Sanity check. - sc->vk->vkGetPhysicalDeviceSurfaceSupportKHR( - sc->vk->physical_device, 0, sc->surface.handle, &supported); - if (!supported) { - VK_ERROR(sc->vk, - "vkGetPhysicalDeviceSurfaceSupportKHR: " - "surface not supported!"); - } - - // More sanity checks. - if (!_check_surface_present_mode(sc->vk, sc->surface.handle, - sc->present_mode)) { - // Free old. - vk_swapchain_destroy_old(sc, old_swapchain_handle); - return; - } - - // Find the correct format. - if (!_find_surface_format(sc, sc->surface.handle, - &sc->surface.format)) { - // Free old. - vk_swapchain_destroy_old(sc, old_swapchain_handle); - return; - } - - // Get the caps first. - VkSurfaceCapabilitiesKHR surface_caps; - ret = sc->vk->vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - sc->vk->physical_device, sc->surface.handle, &surface_caps); - if (ret != VK_SUCCESS) { - VK_ERROR(sc->vk, - "vkGetPhysicalDeviceSurfaceCapabilitiesKHR: %s", - vk_result_string(ret)); - - // Free old. - vk_swapchain_destroy_old(sc, old_swapchain_handle); - return; - } - - // Get the extents of the swapchain. - VkExtent2D extent = - vk_swapchain_select_extent(sc, surface_caps, width, height); - - // Create the swapchain now. - VkSwapchainCreateInfoKHR swapchain_info = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = sc->surface.handle, - .minImageCount = surface_caps.minImageCount, - .imageFormat = sc->surface.format.format, - .imageColorSpace = sc->surface.format.colorSpace, - .imageExtent = - { - .width = extent.width, - .height = extent.height, - }, - .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = sc->present_mode, - .clipped = VK_TRUE, - .oldSwapchain = old_swapchain_handle, - }; - - ret = sc->vk->vkCreateSwapchainKHR(sc->vk->device, &swapchain_info, - NULL, &sc->swapchain.handle); - - // Always destroy the old. - vk_swapchain_destroy_old(sc, old_swapchain_handle); - - if (ret != VK_SUCCESS) { - VK_ERROR(sc->vk, "vkCreateSwapchainKHR: %s", - vk_result_string(ret)); - return; - } - - - /* - * Set target info. - */ - - sc->base.width = extent.width; - sc->base.height = extent.height; - sc->base.format = sc->surface.format.format; - - vk_swapchain_create_image_views(sc); -} - -static VkExtent2D -vk_swapchain_select_extent(struct vk_swapchain *sc, - VkSurfaceCapabilitiesKHR caps, - uint32_t width, - uint32_t height) -{ - // If width (and height) equals the special value 0xFFFFFFFF, - // the size of the surface will be set by the swapchain - if (caps.currentExtent.width == (uint32_t)-1) { - VkExtent2D extent = { - .width = width, - .height = height, - }; - return extent; - } - - if (caps.currentExtent.width != width || - caps.currentExtent.height != height) { - VK_DEBUG(sc->vk, - "Using swap chain extent dimensions %dx%d instead of " - "requested %dx%d.", - caps.currentExtent.width, caps.currentExtent.height, - width, height); - } - - return caps.currentExtent; -} - -static void -vk_swapchain_destroy_old(struct vk_swapchain *sc, VkSwapchainKHR old) -{ - if (old != VK_NULL_HANDLE) { - sc->vk->vkDestroySwapchainKHR(sc->vk->device, old, NULL); - } -} - -VkResult -vk_swapchain_acquire_next_image(struct vk_swapchain *sc, - VkSemaphore semaphore, - uint32_t *out_index) -{ - return sc->vk->vkAcquireNextImageKHR( // - sc->vk->device, // device - sc->swapchain.handle, // timeout - UINT64_MAX, // timeout - semaphore, // semaphore - VK_NULL_HANDLE, // fence - out_index); // pImageIndex -} - -VkResult -vk_swapchain_present(struct vk_swapchain *sc, - VkQueue queue, - uint32_t index, - VkSemaphore semaphore) -{ - VkPresentInfoKHR presentInfo = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &semaphore, - .swapchainCount = 1, - .pSwapchains = &sc->swapchain.handle, - .pImageIndices = &index, - }; - - return sc->vk->vkQueuePresentKHR(queue, &presentInfo); -} - -static bool -_find_surface_format(struct vk_swapchain *sc, - VkSurfaceKHR surface, - VkSurfaceFormatKHR *format) -{ - uint32_t num_formats; - VkSurfaceFormatKHR *formats = NULL; - sc->vk->vkGetPhysicalDeviceSurfaceFormatsKHR( - sc->vk->physical_device, surface, &num_formats, NULL); - - if (num_formats != 0) { - formats = U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, num_formats); - sc->vk->vkGetPhysicalDeviceSurfaceFormatsKHR( - sc->vk->physical_device, surface, &num_formats, formats); - } else { - VK_ERROR(sc->vk, "Could not enumerate surface formats."); - return false; - } - - VkSurfaceFormatKHR *formats_for_colorspace = NULL; - formats_for_colorspace = - U_TYPED_ARRAY_CALLOC(VkSurfaceFormatKHR, num_formats); - - uint32_t num_formats_cs = 0; - uint32_t num_pref_formats = ARRAY_SIZE(preferred_color_formats); - - // Gather formats that match our color space, we will select - // from these in preference to others. - - for (uint32_t i = 0; i < num_formats; i++) { - if (formats[i].colorSpace == sc->preferred.color_space) { - formats_for_colorspace[num_formats_cs] = formats[i]; - num_formats_cs++; - } - } - - if (num_formats_cs > 0) { - // we have at least one format with our preferred colorspace - // if we have one that is on our preferred formats list, use it - - for (uint32_t i = 0; i < num_formats_cs; i++) { - if (formats_for_colorspace[i].format == - sc->preferred.color_format) { - // perfect match. - *format = formats_for_colorspace[i]; - goto cleanup; - } - } - - // we don't have our swapchain default format and colorspace, - // but we may have at least one preferred format with the - // correct colorspace. - for (uint32_t i = 0; i < num_formats_cs; i++) { - for (uint32_t j = 0; j < num_pref_formats; j++) { - if (formats_for_colorspace[i].format == - preferred_color_formats[j]) { - *format = formats_for_colorspace[i]; - goto cleanup; - } - } - } - - // are we still here? this means we have a format with our - // preferred colorspace but we have no preferred color format - - // maybe we only have 10/12 bpc or 15/16bpp format. return the - // first one we have, at least its in the right color space. - *format = formats_for_colorspace[0]; - VK_ERROR(sc->vk, "Returning unknown color format"); - goto cleanup; - - } else { - - // we have nothing with the preferred colorspace? we can try to - // return a preferred format at least - for (uint32_t i = 0; i < num_formats; i++) { - for (uint32_t j = 0; j < num_pref_formats; j++) { - if (formats[i].format == - preferred_color_formats[j]) { - *format = formats_for_colorspace[i]; - VK_ERROR( - sc->vk, - "Returning known-wrong color " - "space! Color shift may occur."); - goto cleanup; - } - } - } - // if we are still here, we should just return the first format - // we have. we know its the wrong colorspace, and its not on our - // list of preferred formats, but its something. - *format = formats[0]; - VK_ERROR(sc->vk, - "Returning fallback format! cue up some Kenny " - "Loggins, cos we're in the DANGER ZONE!"); - goto cleanup; - } - - VK_ERROR(sc->vk, "We should not be here"); - goto error; - -cleanup: - free(formats_for_colorspace); - free(formats); - return true; - -error: - free(formats_for_colorspace); - free(formats); - return false; -} - -static bool -_check_surface_present_mode(struct vk_bundle *vk, - VkSurfaceKHR surface, - VkPresentModeKHR present_mode) -{ - uint32_t num_present_modes; - VkPresentModeKHR *present_modes; - vk->vkGetPhysicalDeviceSurfacePresentModesKHR( - vk->physical_device, surface, &num_present_modes, NULL); - - if (num_present_modes != 0) { - present_modes = - U_TYPED_ARRAY_CALLOC(VkPresentModeKHR, num_present_modes); - vk->vkGetPhysicalDeviceSurfacePresentModesKHR( - vk->physical_device, surface, &num_present_modes, - present_modes); - } else { - VK_ERROR(vk, "Could not enumerate present modes."); - return false; - } - - for (uint32_t i = 0; i < num_present_modes; i++) { - if (present_modes[i] == present_mode) { - free(present_modes); - return true; - } - } - - free(present_modes); - VK_ERROR(vk, "Requested present mode not supported.\n"); - return false; -} - -static void -vk_swapchain_destroy_image_views(struct vk_swapchain *sc) -{ - if (sc->base.images == NULL) { - return; - } - - for (uint32_t i = 0; i < sc->base.num_images; i++) { - if (sc->base.images[i].view == VK_NULL_HANDLE) { - continue; - } - - sc->vk->vkDestroyImageView(sc->vk->device, - sc->base.images[i].view, NULL); - sc->base.images[i].view = VK_NULL_HANDLE; - } - - free(sc->base.images); - sc->base.images = NULL; -} - -static void -vk_swapchain_create_image_views(struct vk_swapchain *sc) -{ - sc->vk->vkGetSwapchainImagesKHR( // - sc->vk->device, // device - sc->swapchain.handle, // swapchain - &sc->base.num_images, // pSwapchainImageCount - NULL); // pSwapchainImages - assert(sc->base.num_images > 0); - VK_DEBUG(sc->vk, "Creating %d image views.", sc->base.num_images); - - VkImage *images = U_TYPED_ARRAY_CALLOC(VkImage, sc->base.num_images); - sc->vk->vkGetSwapchainImagesKHR( // - sc->vk->device, // device - sc->swapchain.handle, // swapchain - &sc->base.num_images, // pSwapchainImageCount - images); // pSwapchainImages - - vk_swapchain_destroy_image_views(sc); - - sc->base.images = - U_TYPED_ARRAY_CALLOC(struct comp_target_image, sc->base.num_images); - - VkImageSubresourceRange subresource_range = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - for (uint32_t i = 0; i < sc->base.num_images; i++) { - sc->base.images[i].handle = images[i]; - vk_create_view(sc->vk, sc->base.images[i].handle, - sc->surface.format.format, subresource_range, - &sc->base.images[i].view); - } - - free(images); -} - -void -vk_swapchain_cleanup(struct vk_swapchain *sc) -{ - vk_swapchain_destroy_image_views(sc); - - if (sc->swapchain.handle != VK_NULL_HANDLE) { - sc->vk->vkDestroySwapchainKHR( // - sc->vk->device, // device - sc->swapchain.handle, // swapchain - NULL); // - sc->swapchain.handle = VK_NULL_HANDLE; - } - - if (sc->surface.handle != VK_NULL_HANDLE) { - sc->vk->vkDestroySurfaceKHR( // - sc->vk->instance, // instance - sc->surface.handle, // surface - NULL); // - sc->swapchain.handle = VK_NULL_HANDLE; - } -} diff --git a/src/xrt/compositor/main/comp_vk_swapchain.h b/src/xrt/compositor/main/comp_vk_swapchain.h deleted file mode 100644 index 9cb4d4878..000000000 --- a/src/xrt/compositor/main/comp_vk_swapchain.h +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2019, Collabora, Ltd. -// SPDX-License-Identifier: BSL-1.0 -/*! - * @file - * @brief Vulkan swapchain code header. - * @author Lubosz Sarnecki - * @author Jakob Bornecrantz - * @ingroup comp_main - */ - -#pragma once - -#include "vk/vk_helpers.h" - -#include "main/comp_target.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * - * Structs. - * - */ - -/*! - * Wraps and manage VkSwapchainKHR and VkSurfaceKHR, used by @ref comp code. - * - * @ingroup comp_main - */ -struct vk_swapchain -{ - //! Base target. - struct comp_target base; - - struct vk_bundle *vk; - - struct - { - VkSwapchainKHR handle; - } swapchain; - - struct - { - VkSurfaceKHR handle; - VkSurfaceFormatKHR format; - } surface; - - struct - { - VkFormat color_format; - VkColorSpaceKHR color_space; - } preferred; - - //! Present mode that the system must support. - VkPresentModeKHR present_mode; -}; - - -/* - * - * Functions. - * - */ - -/*! - * Wraps and manage VkSwapchainKHR and VkSurfaceKHR, used by @ref comp code. - * - * @ingroup comp_main - */ -void -vk_swapchain_init(struct vk_swapchain *sc, struct vk_bundle *vk); - -/*! - * Initialize the given @ref vk_swapchain, does not allocate. - * - * @ingroup comp_main - */ -void -vk_swapchain_create(struct vk_swapchain *sc, - uint32_t width, - uint32_t height, - VkFormat color_format, - VkColorSpaceKHR color_space, - VkPresentModeKHR present_mode); - -/*! - * Acquire a image index from the given @ref vk_swapchain for rendering. - * - * @ingroup comp_main - */ -VkResult -vk_swapchain_acquire_next_image(struct vk_swapchain *sc, - VkSemaphore semaphore, - uint32_t *index); - -/*! - * Make the given @ref vk_swapchain present the next acquired image. - * - * @ingroup comp_main - */ -VkResult -vk_swapchain_present(struct vk_swapchain *sc, - VkQueue queue, - uint32_t index, - VkSemaphore semaphore); - -/*! - * Free all managed resources on the given @ref vk_swapchain, - * does not free the struct itself. - * - * @ingroup comp_main - */ -void -vk_swapchain_cleanup(struct vk_swapchain *sc); - - -#ifdef __cplusplus -} -#endif diff --git a/src/xrt/compositor/main/comp_window.h b/src/xrt/compositor/main/comp_window.h index 744279e05..4630df3de 100644 --- a/src/xrt/compositor/main/comp_window.h +++ b/src/xrt/compositor/main/comp_window.h @@ -10,9 +10,8 @@ #pragma once -#include "main/comp_vk_swapchain.h" +#include "main/comp_target_swapchain.h" #include "main/comp_compositor.h" -#include "render/comp_render.h" #include "xrt/xrt_config_os.h" @@ -36,7 +35,7 @@ extern "C" { struct comp_window { //! This has to be first. - struct vk_swapchain swapchain; + struct comp_target_swapchain swapchain; //! Owning compositor. struct comp_compositor *c; @@ -49,9 +48,6 @@ struct comp_window * */ -void -comp_window_init_target(struct comp_window *wt); - #ifdef VK_USE_PLATFORM_XCB_KHR /*! * Create a xcb window. diff --git a/src/xrt/compositor/main/comp_window_android.c b/src/xrt/compositor/main/comp_window_android.c index 68921fd4c..86415db68 100644 --- a/src/xrt/compositor/main/comp_window_android.c +++ b/src/xrt/compositor/main/comp_window_android.c @@ -59,7 +59,7 @@ comp_window_android_destroy(struct comp_target *ct) { struct comp_window_android *cwa = (struct comp_window_android *)ct; - vk_swapchain_cleanup(&cwa->base.swapchain); + comp_target_swapchain_cleanup(&cwa->base.swapchain); android_custom_surface_destroy(&cwa->custom_surface); @@ -146,6 +146,8 @@ comp_window_android_create(struct comp_compositor *c) struct comp_window_android *w = U_TYPED_CALLOC(struct comp_window_android); + comp_target_swapchain_init_set_fnptrs(&w->base.swapchain); + w->base.swapchain.base.name = "Android"; w->base.swapchain.base.destroy = comp_window_android_destroy; w->base.swapchain.base.flush = comp_window_android_flush; diff --git a/src/xrt/compositor/main/comp_window_direct.c b/src/xrt/compositor/main/comp_window_direct.c index 92fcb0def..21e37892c 100644 --- a/src/xrt/compositor/main/comp_window_direct.c +++ b/src/xrt/compositor/main/comp_window_direct.c @@ -277,7 +277,7 @@ comp_window_direct_init_swapchain(struct comp_window *w, uint32_t width, uint32_t height) { - vk_swapchain_init(&w->swapchain, &w->c->vk); + comp_target_swapchain_init_post_vulkan(&w->swapchain, &w->c->vk); VkResult ret; ret = comp_window_direct_acquire_xlib_display(w, dpy, display); diff --git a/src/xrt/compositor/main/comp_window_direct_nvidia.c b/src/xrt/compositor/main/comp_window_direct_nvidia.c index baed819fb..b639e4c7e 100644 --- a/src/xrt/compositor/main/comp_window_direct_nvidia.c +++ b/src/xrt/compositor/main/comp_window_direct_nvidia.c @@ -89,7 +89,7 @@ comp_window_direct_nvidia_create(struct comp_compositor *c) struct comp_window_direct_nvidia *w = U_TYPED_CALLOC(struct comp_window_direct_nvidia); - comp_window_init_target(&w->base); + comp_target_swapchain_init_set_fnptrs(&w->base.swapchain); w->base.swapchain.base.name = "direct"; w->base.swapchain.base.destroy = comp_window_direct_nvidia_destroy; @@ -109,7 +109,7 @@ comp_window_direct_nvidia_destroy(struct comp_target *ct) struct comp_window_direct_nvidia *w_direct = (struct comp_window_direct_nvidia *)ct; - vk_swapchain_cleanup(&w_direct->base.swapchain); + comp_target_swapchain_cleanup(&w_direct->base.swapchain); for (uint32_t i = 0; i < w_direct->num_displays; i++) { struct comp_window_direct_nvidia_display *d = @@ -255,7 +255,7 @@ comp_window_direct_nvidia_init_swapchain(struct comp_target *ct, (struct comp_window_direct_nvidia *)ct; struct comp_window *w = &w_direct->base; - vk_swapchain_init(&w->swapchain, &w->c->vk); + comp_target_swapchain_init_post_vulkan(&w->swapchain, &w->c->vk); struct comp_window_direct_nvidia_display *d = comp_window_direct_nvidia_current_display(w_direct); diff --git a/src/xrt/compositor/main/comp_window_direct_randr.c b/src/xrt/compositor/main/comp_window_direct_randr.c index ad35574b5..b9956986b 100644 --- a/src/xrt/compositor/main/comp_window_direct_randr.c +++ b/src/xrt/compositor/main/comp_window_direct_randr.c @@ -111,7 +111,7 @@ comp_window_direct_randr_create(struct comp_compositor *c) struct comp_window_direct_randr *w = U_TYPED_CALLOC(struct comp_window_direct_randr); - comp_window_init_target(&w->base); + comp_target_swapchain_init_set_fnptrs(&w->base.swapchain); w->base.swapchain.base.name = "direct"; w->base.swapchain.base.destroy = comp_window_direct_randr_destroy; @@ -131,7 +131,7 @@ comp_window_direct_randr_destroy(struct comp_target *ct) struct comp_window_direct_randr *w_direct = (struct comp_window_direct_randr *)ct; - vk_swapchain_cleanup(&w_direct->base.swapchain); + comp_target_swapchain_cleanup(&w_direct->base.swapchain); struct vk_bundle *vk = &w_direct->base.c->vk; @@ -254,7 +254,7 @@ comp_window_direct_randr_init_swapchain(struct comp_target *ct, (struct comp_window_direct_randr *)ct; struct comp_window *w = &w_direct->base; - vk_swapchain_init(&w->swapchain, &w->c->vk); + comp_target_swapchain_init_post_vulkan(&w->swapchain, &w->c->vk); struct comp_window_direct_randr_display *d = comp_window_direct_randr_current_display(w_direct); diff --git a/src/xrt/compositor/main/comp_window_target.c b/src/xrt/compositor/main/comp_window_target.c deleted file mode 100644 index f49cc3420..000000000 --- a/src/xrt/compositor/main/comp_window_target.c +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2020, Collabora, Ltd. -// SPDX-License-Identifier: BSL-1.0 -/*! - * @file - * @brief Compositor window header. - * @author Jakob Bornecrantz - * @ingroup comp_main - */ - -#include "main/comp_window.h" - - -static inline struct comp_window * -comp_window(struct comp_target *ct) -{ - return (struct comp_window *)ct; -} - -void -wt_create_images(struct comp_target *ct, - uint32_t preferred_width, - uint32_t preferred_height, - VkFormat preferred_color_format, - VkColorSpaceKHR preferred_color_space, - VkPresentModeKHR present_mode) -{ - struct comp_window *cw = comp_window(ct); - - vk_swapchain_create( // - &cw->swapchain, // - preferred_width, // - preferred_height, // - preferred_color_format, // - preferred_color_space, // - present_mode); // -} - -VkResult -wt_acquire(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index) -{ - struct comp_window *cw = comp_window(ct); - - return vk_swapchain_acquire_next_image( // - &cw->swapchain, // - semaphore, // - out_index); // -} - -VkResult -wt_present(struct comp_target *ct, - VkQueue queue, - uint32_t index, - VkSemaphore semaphore) -{ - struct comp_window *cw = comp_window(ct); - - return vk_swapchain_present( // - &cw->swapchain, // - queue, // - index, // - semaphore); // -} - -void -comp_window_init_target(struct comp_window *wt) -{ - wt->swapchain.base.create_images = wt_create_images; - wt->swapchain.base.acquire = wt_acquire; - wt->swapchain.base.present = wt_present; -} diff --git a/src/xrt/compositor/main/comp_window_wayland.c b/src/xrt/compositor/main/comp_window_wayland.c index 10d2a93bf..2f7491a73 100644 --- a/src/xrt/compositor/main/comp_window_wayland.c +++ b/src/xrt/compositor/main/comp_window_wayland.c @@ -121,7 +121,7 @@ comp_window_wayland_destroy(struct comp_target *ct) { struct comp_window_wayland *cww = (struct comp_window_wayland *)ct; - vk_swapchain_cleanup(&cww->base.swapchain); + comp_target_swapchain_cleanup(&cww->base.swapchain); if (cww->surface) { wl_surface_destroy(cww->surface); @@ -207,7 +207,7 @@ comp_window_wayland_init_swapchain(struct comp_target *ct, struct comp_window *w = &w_wayland->base; VkResult ret; - vk_swapchain_init(&w->swapchain, &w->c->vk); + comp_target_swapchain_init_post_vulkan(&w->swapchain, &w->c->vk); ret = comp_window_wayland_create_surface(w_wayland, &w->swapchain.surface.handle); diff --git a/src/xrt/compositor/main/comp_window_xcb.c b/src/xrt/compositor/main/comp_window_xcb.c index 2644e09c9..25e48e668 100644 --- a/src/xrt/compositor/main/comp_window_xcb.c +++ b/src/xrt/compositor/main/comp_window_xcb.c @@ -127,7 +127,7 @@ comp_window_xcb_create(struct comp_compositor *c) { struct comp_window_xcb *w = U_TYPED_CALLOC(struct comp_window_xcb); - comp_window_init_target(&w->base); + comp_target_swapchain_init_set_fnptrs(&w->base.swapchain); w->base.swapchain.base.name = "xcb"; w->base.swapchain.base.destroy = comp_window_xcb_destroy; @@ -146,7 +146,7 @@ comp_window_xcb_destroy(struct comp_target *ct) { struct comp_window_xcb *w_xcb = (struct comp_window_xcb *)ct; - vk_swapchain_cleanup(&w_xcb->base.swapchain); + comp_target_swapchain_cleanup(&w_xcb->base.swapchain); xcb_destroy_window(w_xcb->connection, w_xcb->window); xcb_disconnect(w_xcb->connection); @@ -249,7 +249,7 @@ comp_window_xcb_init_swapchain(struct comp_target *ct, struct comp_window *w = &w_xcb->base; VkResult ret; - vk_swapchain_init(&w->swapchain, &w->c->vk); + comp_target_swapchain_init_post_vulkan(&w->swapchain, &w->c->vk); ret = comp_window_xcb_create_surface(w_xcb, &w->swapchain.surface.handle); diff --git a/src/xrt/compositor/meson.build b/src/xrt/compositor/meson.build index 7f1b13497..3379bb293 100644 --- a/src/xrt/compositor/meson.build +++ b/src/xrt/compositor/meson.build @@ -23,10 +23,9 @@ compositor_srcs = [ 'main/comp_shaders.c', 'main/comp_swapchain.c', 'main/comp_target.h', - 'main/comp_vk_swapchain.c', - 'main/comp_vk_swapchain.h', + 'main/comp_target_swapchain.c', + 'main/comp_target_swapchain.h', 'main/comp_window.h', - 'main/comp_window_target.c', 'main/comp_layer_renderer.c', 'main/comp_layer.c', 'render/comp_buffer.c',