mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-05-05 00:38:02 +02:00
Introduce an extensions abstraction in the layer
In this change, an abstraction layer is added to the swapchain extensions. The extensions present_timing, present_id, image_compression_control, frame_boundary, and swapchain_maintenance1 are moved to the new extensions abstraction framework. Additionally, the compression control extension has been formalized in the layer as it is part of Vulkan spec so compression control guards have been removed. Change-Id: Ib28739ca35dfbf5df987241a9010619279f3e1bb Signed-off-by: Ginu Jacob <ginu.jacob@arm.com> Signed-off-by: Normunds Rieksts <normunds.rieksts@arm.com>
This commit is contained in:
parent
6fef4eea25
commit
02ae04d08f
34 changed files with 1641 additions and 616 deletions
|
|
@ -65,7 +65,6 @@ set(EXTERNAL_WSIALLOC_LIBRARY "" CACHE STRING "External implementation of the ws
|
|||
set(WSIALLOC_MEMORY_HEAP_NAME "linux,cma" CACHE STRING "Heap name used by the dma_buf_heaps allocator")
|
||||
|
||||
# Optional features
|
||||
option(BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN "Build with support for VK_EXT_image_compression_control_swapchain" OFF)
|
||||
option(BUILD_WSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS "Build with support for format modifiers in VK_KHR_display" ON)
|
||||
option(VULKAN_WSI_LAYER_EXPERIMENTAL "Enable the Vulkan WSI Experimental features" OFF)
|
||||
option(ENABLE_WAYLAND_FIFO_PRESENTATION_THREAD "Enable the non-conformant FIFO presentation thread implementation in the Wayland backend" OFF)
|
||||
|
|
@ -268,14 +267,18 @@ add_library(${PROJECT_NAME} SHARED
|
|||
util/log.cpp
|
||||
util/format_modifiers.cpp
|
||||
wsi/external_memory.cpp
|
||||
wsi/frame_boundary.cpp
|
||||
wsi/extensions/image_compression_control.cpp
|
||||
wsi/extensions/present_id.cpp
|
||||
wsi/extensions/frame_boundary.cpp
|
||||
wsi/extensions/wsi_extension.cpp
|
||||
wsi/extensions/swapchain_maintenance.cpp
|
||||
wsi/surface_properties.cpp
|
||||
wsi/swapchain_base.cpp
|
||||
wsi/synchronization.cpp
|
||||
wsi/wsi_factory.cpp)
|
||||
if (VULKAN_WSI_LAYER_EXPERIMENTAL)
|
||||
target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_timing.cpp)
|
||||
target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/time_domains.cpp)
|
||||
target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_timing_api.cpp)
|
||||
target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/extensions/present_timing.cpp)
|
||||
add_definitions("-DVULKAN_WSI_LAYER_EXPERIMENTAL=1")
|
||||
else()
|
||||
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_present_timing/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
|
||||
|
|
@ -287,13 +290,6 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE ${WSI_DEFINES})
|
|||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${VULKAN_CXX_INCLUDE})
|
||||
|
||||
if (BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN)
|
||||
add_definitions("-DWSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN=1")
|
||||
else()
|
||||
add_definitions("-DWSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN=0")
|
||||
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_image_compression_control_swapchain/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
|
||||
endif()
|
||||
|
||||
if (BUILD_WSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS)
|
||||
add_definitions("-DWSI_DISPLAY_SUPPORT_FORMAT_MODIFIERS=1")
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <vulkan/vk_layer.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "wsi_layer_experimental.hpp"
|
||||
#include "private_data.hpp"
|
||||
#include "surface_api.hpp"
|
||||
#include "swapchain_api.hpp"
|
||||
|
|
@ -42,10 +43,6 @@
|
|||
#include "util/helpers.hpp"
|
||||
#include "wsi/unsupported_surfaces.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
#include "wsi_layer_experimental.hpp"
|
||||
#endif
|
||||
|
||||
#define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
|
||||
|
||||
namespace layer
|
||||
|
|
@ -364,7 +361,6 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
|
|||
return result;
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
const auto *swapchain_compression_feature =
|
||||
util::find_extension<VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT, pCreateInfo->pNext);
|
||||
|
|
@ -373,7 +369,6 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic
|
|||
device_data.set_swapchain_compression_control_enabled(
|
||||
swapchain_compression_feature->imageCompressionControlSwapchain);
|
||||
}
|
||||
#endif
|
||||
|
||||
const auto present_id_features = util::find_extension<VkPhysicalDevicePresentIdFeaturesKHR>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR, pCreateInfo->pNext);
|
||||
|
|
@ -495,7 +490,6 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|||
#endif
|
||||
instance.disp.GetPhysicalDeviceFeatures2KHR(physicalDevice, pFeatures);
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
auto *image_compression_control_swapchain_features =
|
||||
util::find_extension<VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT, pFeatures->pNext);
|
||||
|
|
@ -504,7 +498,6 @@ wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
|
|||
image_compression_control_swapchain_features->imageCompressionControlSwapchain =
|
||||
instance.has_image_compression_support(physicalDevice);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto *present_id_features = util::find_extension<VkPhysicalDevicePresentIdFeaturesKHR>(
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR, pFeatures->pNext);
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@
|
|||
*/
|
||||
#include <cassert>
|
||||
#include "wsi_layer_experimental.hpp"
|
||||
#include "wsi/swapchain_base.hpp"
|
||||
|
||||
#include <wsi/extensions/present_timing.hpp>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
#include "util/macros.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
/**
|
||||
* @brief Implements vkSetSwapchainPresentTimingQueueSizeEXT Vulkan entrypoint.
|
||||
*/
|
||||
|
|
@ -43,7 +44,9 @@ wsi_layer_vkSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKH
|
|||
UNUSED(device);
|
||||
assert(swapchain != VK_NULL_HANDLE);
|
||||
auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapchain);
|
||||
return sc->presentation_timing_queue_set_size(size);
|
||||
|
||||
auto *ext = sc->get_swapchain_extension<wsi::wsi_ext_present_timing>(true);
|
||||
return ext->present_timing_queue_set_size(size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -77,8 +80,11 @@ wsi_layer_vkGetSwapchainTimeDomainPropertiesEXT(
|
|||
return device_data.disp.GetSwapchainTimeDomainPropertiesEXT(device, swapchain, pTimeDomainsCounter,
|
||||
pSwapchainTimeDomainProperties);
|
||||
}
|
||||
|
||||
auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapchain);
|
||||
return sc->set_swapchain_time_domain_properties(pSwapchainTimeDomainProperties, pTimeDomainsCounter);
|
||||
auto *ext = sc->get_swapchain_extension<wsi::wsi_ext_present_timing>(true);
|
||||
return ext->get_swapchain_time_domains().get_swapchain_time_domain_properties(pSwapchainTimeDomainProperties,
|
||||
pTimeDomainsCounter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -362,7 +362,6 @@ bool instance_private_data::should_layer_handle_surface(VkPhysicalDevice phys_de
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
bool instance_private_data::has_image_compression_support(VkPhysicalDevice phys_dev)
|
||||
{
|
||||
VkPhysicalDeviceImageCompressionControlFeaturesEXT compression = {
|
||||
|
|
@ -374,7 +373,6 @@ bool instance_private_data::has_image_compression_support(VkPhysicalDevice phys_
|
|||
|
||||
return compression.imageCompressionControl != VK_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool instance_private_data::has_frame_boundary_support(VkPhysicalDevice phys_dev)
|
||||
{
|
||||
|
|
@ -420,11 +418,12 @@ device_private_data::device_private_data(instance_private_data &inst_data, VkPhy
|
|||
, allocator{ alloc }
|
||||
, swapchains{ allocator } /* clang-format off */
|
||||
, enabled_extensions{ allocator }
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
, compression_control_enabled{ false }
|
||||
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
|
||||
, present_id_enabled { false }
|
||||
, swapchain_maintenance1_enabled{ false }
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
, present_timing_enabled { true }
|
||||
#endif
|
||||
/* clang-format on */
|
||||
{
|
||||
}
|
||||
|
|
@ -566,7 +565,6 @@ void device_private_data::destroy(device_private_data *device_data)
|
|||
alloc.destroy<device_private_data>(1, device_data);
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
void device_private_data::set_swapchain_compression_control_enabled(bool enable)
|
||||
{
|
||||
compression_control_enabled = enable;
|
||||
|
|
@ -576,7 +574,6 @@ bool device_private_data::is_swapchain_compression_control_enabled() const
|
|||
{
|
||||
return compression_control_enabled;
|
||||
}
|
||||
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
|
||||
|
||||
void device_private_data::set_layer_frame_boundary_handling_enabled(bool enable)
|
||||
{
|
||||
|
|
@ -593,6 +590,11 @@ void device_private_data::set_present_id_feature_enabled(bool enable)
|
|||
present_id_enabled = enable;
|
||||
}
|
||||
|
||||
bool device_private_data::is_present_id_enabled()
|
||||
{
|
||||
return present_id_enabled;
|
||||
}
|
||||
|
||||
void device_private_data::set_swapchain_maintenance1_enabled(bool enable)
|
||||
{
|
||||
swapchain_maintenance1_enabled = enable;
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "util/platform_set.hpp"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "util/unordered_set.hpp"
|
||||
#include "util/unordered_map.hpp"
|
||||
#include "util/extension_list.hpp"
|
||||
#include <layer/wsi_layer_experimental.hpp>
|
||||
|
||||
#include <util/platform_set.hpp>
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/unordered_set.hpp>
|
||||
#include <util/unordered_map.hpp>
|
||||
#include <util/extension_list.hpp>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vk_layer.h>
|
||||
|
|
@ -41,7 +43,6 @@
|
|||
#include <mutex>
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
#include "wsi_layer_experimental.hpp"
|
||||
using scoped_mutex = std::lock_guard<std::mutex>;
|
||||
|
||||
/** Forward declare stored objects */
|
||||
|
|
@ -593,7 +594,6 @@ public:
|
|||
*/
|
||||
bool does_layer_support_surface(VkSurfaceKHR surface);
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
/**
|
||||
* @brief Check if a physical device supports controlling image compression.
|
||||
*
|
||||
|
|
@ -601,7 +601,6 @@ public:
|
|||
* @return Whether image compression control is supported by the ICD.
|
||||
*/
|
||||
bool has_image_compression_support(VkPhysicalDevice phys_dev);
|
||||
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
|
||||
|
||||
bool has_frame_boundary_support(VkPhysicalDevice phys_dev);
|
||||
|
||||
|
|
@ -818,7 +817,6 @@ public:
|
|||
const VkPhysicalDevice physical_device;
|
||||
const VkDevice device;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
/**
|
||||
* @brief Set whether the device supports controlling the swapchain image compression.
|
||||
*
|
||||
|
|
@ -832,7 +830,6 @@ public:
|
|||
* @return true if enabled, false otherwise.
|
||||
*/
|
||||
bool is_swapchain_compression_control_enabled() const;
|
||||
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
|
||||
|
||||
/**
|
||||
* @brief Set whether we should handle frame boundary events.
|
||||
|
|
@ -855,6 +852,13 @@ public:
|
|||
*/
|
||||
void set_present_id_feature_enabled(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Check whether the device can support the present ID feature.
|
||||
*
|
||||
* @return true if supported, false otherwise.
|
||||
*/
|
||||
bool is_present_id_enabled();
|
||||
|
||||
/**
|
||||
* @brief Selectively enable/disable the swapchain maintenance1 features for this device.
|
||||
*
|
||||
|
|
@ -904,13 +908,11 @@ private:
|
|||
*/
|
||||
util::extension_list enabled_extensions;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
/**
|
||||
* @brief Stores whether the device supports controlling the swapchain image compression.
|
||||
*
|
||||
*/
|
||||
bool compression_control_enabled;
|
||||
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
|
||||
|
||||
/**
|
||||
* @brief Stores whether the layer should handle frame boundary events.
|
||||
|
|
@ -927,6 +929,13 @@ private:
|
|||
* @brief Stores whether the device has enabled support for the swapchain maintenance1 features.
|
||||
*/
|
||||
bool swapchain_maintenance1_enabled;
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Stores whether the device has enabled support for the present timing features.
|
||||
*/
|
||||
bool present_timing_enabled;
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace layer */
|
||||
|
|
|
|||
|
|
@ -32,12 +32,14 @@
|
|||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
#include <wsi/wsi_factory.hpp>
|
||||
|
||||
#include "private_data.hpp"
|
||||
#include "swapchain_api.hpp"
|
||||
|
||||
#include <util/helpers.hpp>
|
||||
#include "wsi/synchronization.hpp"
|
||||
|
||||
#include <wsi/synchronization.hpp>
|
||||
#include <wsi/wsi_factory.hpp>
|
||||
#include <wsi/extensions/frame_boundary.hpp>
|
||||
#include "util/macros.hpp"
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
|
|
@ -226,7 +228,8 @@ wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
|
|||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
if (present_timings_info)
|
||||
{
|
||||
present_params.present_timing_info = &(present_timings_info->pTimingInfos[i]);
|
||||
present_params.m_present_timing_info = present_timings_info->pTimingInfos[i];
|
||||
present_params.m_present_timing_info.pNext = nullptr;
|
||||
}
|
||||
#endif
|
||||
VkResult res = sc->queue_present(queue, present_info, present_params);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -28,11 +28,11 @@
|
|||
* @brief Contains the Vulkan entrypoints for the swapchain maintenance.
|
||||
*/
|
||||
|
||||
#include "swapchain_maintenance_api.hpp"
|
||||
#include <cassert>
|
||||
#include "private_data.hpp"
|
||||
#include "swapchain_maintenance_api.hpp"
|
||||
|
||||
#include <wsi/wsi_factory.hpp>
|
||||
#include <cassert>
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
wsi_layer_vkReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT *pReleaseInfo) VWL_API_POST
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -25,18 +25,18 @@
|
|||
/**
|
||||
* @file wsi_layer_experimental.hpp
|
||||
*
|
||||
* @brief Contains the Vulkan definitions for experimental features.
|
||||
* @brief Contains the declarations of the structures and entry point APIs of experimental extensions.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#pragma once
|
||||
#include "util/macros.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
#define VK_EXT_present_timing 1
|
||||
#define VK_EXT_PRESENT_TIMING_SPEC_VERSION 1
|
||||
#define VK_EXT_PRESENT_TIMING_EXTENSION_NAME "VK_KHR_present_timing"
|
||||
|
||||
#define VK_EXT_PRESENT_TIMING_EXTENSION_NAME "VK_EXT_present_timing"
|
||||
#define VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT ((VkResult)(-1000208000))
|
||||
#define VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT ((VkTimeDomainEXT)(1000208000))
|
||||
#define VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT ((VkTimeDomainEXT)(1000208001))
|
||||
|
|
@ -51,6 +51,9 @@
|
|||
#define VK_STRUCTURE_TYPE_PRESENT_TIMING_INFO_EXT ((VkStructureType)1000208010)
|
||||
#define VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT ((VkStructureType)1000208011)
|
||||
|
||||
/* Placeholder. Need to get the real value. */
|
||||
#define VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT ((VkSwapchainCreateFlagsKHR)0x00010000)
|
||||
|
||||
typedef VkFlags VkPresentStageFlagsEXT;
|
||||
|
||||
typedef struct VkPhysicalDevicePresentTimingFeaturesEXT
|
||||
|
|
@ -61,7 +64,6 @@ typedef struct VkPhysicalDevicePresentTimingFeaturesEXT
|
|||
VkBool32 presentAtAbsoluteTime;
|
||||
VkBool32 presentAtRelativeTime;
|
||||
} VkPhysicalDevicePresentTimingFeaturesEXT;
|
||||
|
||||
typedef struct VkPresentTimingSurfaceCapabilitiesEXT
|
||||
{
|
||||
VkStructureType sType;
|
||||
|
|
@ -189,4 +191,5 @@ VWL_VKAPI_CALL(VkResult)
|
|||
wsi_layer_vkGetPastPresentationTimingEXT(
|
||||
VkDevice device, const VkPastPresentationTimingInfoEXT *pPastPresentationTimingInfo,
|
||||
VkPastPresentationTimingPropertiesEXT *pPastPresentationTimingProperties) VWL_API_POST;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -137,12 +137,10 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
VkResult res = formats[format_count].check_device_support(physical_device, format_info);
|
||||
if (VK_SUCCESS == res)
|
||||
{
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (layer::instance_private_data::get(physical_device).has_image_compression_support(physical_device))
|
||||
{
|
||||
formats[format_count].add_device_compression_support(physical_device, format_info);
|
||||
}
|
||||
#endif
|
||||
format_count++;
|
||||
}
|
||||
}
|
||||
|
|
@ -165,12 +163,10 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
VkResult res = formats[format_count].check_device_support(physical_device, format_info);
|
||||
if (VK_SUCCESS == res)
|
||||
{
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (layer::instance_private_data::get(physical_device).has_image_compression_support(physical_device))
|
||||
{
|
||||
formats[format_count].add_device_compression_support(physical_device, format_info);
|
||||
}
|
||||
#endif
|
||||
format_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@
|
|||
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
#include "swapchain.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "util/macros.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <util/macros.hpp>
|
||||
#include <wsi/extensions/image_compression_control.hpp>
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
|
||||
#include "swapchain.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
|
|
@ -75,6 +78,36 @@ static void page_flip_event(int fd, unsigned int sequence, unsigned int tv_sec,
|
|||
*done = true;
|
||||
}
|
||||
|
||||
VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
auto compression_control = wsi_ext_image_compression_control::create(device, swapchain_create_info);
|
||||
if (compression_control)
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_image_compression_control>(*compression_control)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id>()))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.should_layer_handle_frame_boundary_events())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_frame_boundary>(m_device_data)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread)
|
||||
{
|
||||
|
|
@ -154,20 +187,22 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info
|
|||
image_info.usage = info.usage;
|
||||
image_info.flags = info.flags;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkImageCompressionControlEXT compression_control = {};
|
||||
compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
|
||||
compression_control.flags = m_image_compression_control_params.flags;
|
||||
compression_control.compressionControlPlaneCount =
|
||||
m_image_compression_control_params.compression_control_plane_count;
|
||||
compression_control.pFixedRateFlags = m_image_compression_control_params.fixed_rate_flags.data();
|
||||
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
compression_control.pNext = image_info.pNext;
|
||||
image_info.pNext = &compression_control;
|
||||
auto *ext = get_swapchain_extension<wsi_ext_image_compression_control>();
|
||||
/* For Image compression control, additional requirements to be satisfied such as
|
||||
existence of VkImageCompressionControlEXT in swaphain_create_info for
|
||||
the ext to be added to the list. so we check whether we got a valid pointer
|
||||
and proceed if yes. */
|
||||
if (ext)
|
||||
{
|
||||
compression_control = ext->get_compression_control_properties();
|
||||
compression_control.pNext = image_info.pNext;
|
||||
image_info.pNext = &compression_control;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
result = m_device_data.instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(
|
||||
m_device_data.physical_device, &image_info, &format_props);
|
||||
}
|
||||
|
|
@ -227,12 +262,21 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, disp
|
|||
allocation_flags |= WSIALLOC_ALLOCATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (m_image_compression_control_params.flags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
||||
auto *ext = get_swapchain_extension<wsi_ext_image_compression_control>();
|
||||
/* For Image compression control, additional requirements to be satisfied such as
|
||||
existence of VkImageCompressionControlEXT in swaphain_create_info for
|
||||
the ext to be added to the list. so we check whether we got a valid pointer
|
||||
and proceed if yes. */
|
||||
if (ext)
|
||||
{
|
||||
if (ext->get_bitmask_for_image_compression_flags() & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
||||
{
|
||||
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()),
|
||||
image_create_info.extent.width, image_create_info.extent.height,
|
||||
|
|
@ -561,7 +605,12 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
}
|
||||
/* The image is on screen, change the image status to PRESENTED. */
|
||||
m_swapchain_images[pending_present.image_index].status = swapchain_image::PRESENTED;
|
||||
set_present_id(pending_present.present_id);
|
||||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
}
|
||||
|
||||
/* And release the old one. */
|
||||
if (presented_index < m_swapchain_images.size())
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@
|
|||
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
#include "util/wsialloc/wsialloc.h"
|
||||
|
||||
#include "drm_display.hpp"
|
||||
#include "wsi/external_memory.hpp"
|
||||
#include "surface.hpp"
|
||||
#include <util/wsialloc/wsialloc.h>
|
||||
#include <wsi/external_memory.hpp>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
|
@ -124,11 +124,19 @@ private:
|
|||
|
||||
VkResult create_framebuffer(const VkImageCreateInfo &image_create_info, display_image_data *image_data);
|
||||
|
||||
/**
|
||||
* @brief Adds required extensions to the extension list of the swapchain
|
||||
*
|
||||
* @param device Vulkan device
|
||||
* @param swapchain_create_info Swapchain create info
|
||||
* @return VK_SUCCESS on success, other result codes on failure
|
||||
*/
|
||||
VkResult add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) override;
|
||||
|
||||
wsialloc_allocator *m_wsi_allocator;
|
||||
drm_display_mode *m_display_mode;
|
||||
image_creation_parameters m_image_creation_parameters;
|
||||
};
|
||||
|
||||
} /* namespace display */
|
||||
|
||||
} /* namespace wsi*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -25,19 +25,19 @@
|
|||
/**
|
||||
* @file frame_boundary.cpp
|
||||
*
|
||||
* @brief Contains the functionality for frame boundary handling.
|
||||
* @brief Contains the implementation for the VK_EXT_frame_boundary extension.
|
||||
*/
|
||||
|
||||
#include "frame_boundary.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
frame_boundary_handler::frame_boundary_handler(const layer::device_private_data &device_data)
|
||||
|
||||
wsi_ext_frame_boundary::wsi_ext_frame_boundary(const layer::device_private_data &device_data)
|
||||
: m_handle_frame_boundary_events(device_data.should_layer_handle_frame_boundary_events())
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<VkFrameBoundaryEXT> frame_boundary_handler::handle_frame_boundary_event(
|
||||
std::optional<VkFrameBoundaryEXT> wsi_ext_frame_boundary::handle_frame_boundary_event(
|
||||
const VkPresentInfoKHR *present_info, VkImage *current_image_to_be_presented)
|
||||
{
|
||||
/* If frame boundary feature is not enabled by the application, the layer will
|
||||
|
|
@ -74,12 +74,12 @@ std::optional<VkFrameBoundaryEXT> create_frame_boundary(const VkPresentInfoKHR &
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool frame_boundary_handler::should_layer_handle_frame_boundary_events() const
|
||||
bool wsi_ext_frame_boundary::should_layer_handle_frame_boundary_events() const
|
||||
{
|
||||
return m_handle_frame_boundary_events;
|
||||
}
|
||||
|
||||
VkFrameBoundaryEXT frame_boundary_handler::create_frame_boundary(VkImage *image)
|
||||
VkFrameBoundaryEXT wsi_ext_frame_boundary::create_frame_boundary(VkImage *image)
|
||||
{
|
||||
VkFrameBoundaryEXT frame_boundary{};
|
||||
frame_boundary.pNext = nullptr;
|
||||
|
|
@ -107,4 +107,16 @@ VkFrameBoundaryEXT frame_boundary_handler::create_frame_boundary(VkImage *image)
|
|||
return frame_boundary;
|
||||
}
|
||||
|
||||
}
|
||||
std::optional<VkFrameBoundaryEXT> handle_frame_boundary_event(const VkPresentInfoKHR *present_info,
|
||||
VkImage *current_image_to_be_presented,
|
||||
wsi::wsi_ext_frame_boundary *frame_boundary)
|
||||
{
|
||||
if (frame_boundary)
|
||||
{
|
||||
return frame_boundary->handle_frame_boundary_event(present_info, current_image_to_be_presented);
|
||||
}
|
||||
|
||||
return create_frame_boundary(*present_info);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
/**
|
||||
* @file frame_boundary.hpp
|
||||
*
|
||||
* @brief Contains the functionality for frame boundary handling.
|
||||
* @brief Contains the implementation for the VK_EXT_frame_boundary extension.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
@ -33,14 +33,31 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
#include <layer/private_data.hpp>
|
||||
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/macros.hpp>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
class frame_boundary_handler
|
||||
|
||||
/**
|
||||
* @brief Frame boundary extension class
|
||||
*
|
||||
* This class defines the frame boundary extension
|
||||
* features.
|
||||
*/
|
||||
class wsi_ext_frame_boundary : public wsi_ext
|
||||
{
|
||||
public:
|
||||
frame_boundary_handler(const layer::device_private_data &device_data);
|
||||
/**
|
||||
* @brief The name of the extension.
|
||||
*/
|
||||
WSI_DEFINE_EXTENSION(VK_EXT_FRAME_BOUNDARY_EXTENSION_NAME);
|
||||
|
||||
wsi_ext_frame_boundary(const layer::device_private_data &device_data);
|
||||
|
||||
/**
|
||||
* @brief Handle frame boundary event at present time
|
||||
|
|
@ -86,4 +103,15 @@ private:
|
|||
*/
|
||||
std::optional<VkFrameBoundaryEXT> create_frame_boundary(const VkPresentInfoKHR &present_info);
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Handle frame boundary event at present time
|
||||
*
|
||||
* @param present_info Information about the swapchain and image to be presented.
|
||||
* @param current_image_to_be_presented Address to the currently to be presented image
|
||||
* @param frame_boundary Frame boundary extension for current backend or nullptr if not enabled.
|
||||
*/
|
||||
std::optional<VkFrameBoundaryEXT> handle_frame_boundary_event(const VkPresentInfoKHR *present_info,
|
||||
VkImage *current_image_to_be_presented,
|
||||
wsi::wsi_ext_frame_boundary *frame_boundary);
|
||||
|
||||
} /* namespace wsi */
|
||||
79
wsi/extensions/image_compression_control.cpp
Normal file
79
wsi/extensions/image_compression_control.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file image_compression_control.cpp
|
||||
*
|
||||
* @brief Contains the implementation for VK_EXT_image_compression_control extension.
|
||||
*/
|
||||
#include <cassert>
|
||||
|
||||
#include <util/helpers.hpp>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
|
||||
#include "image_compression_control.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
wsi_ext_image_compression_control::wsi_ext_image_compression_control(const VkImageCompressionControlEXT &extension)
|
||||
: m_compression_control{ VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, nullptr, extension.flags,
|
||||
extension.compressionControlPlaneCount, m_array_fixed_rate_flags }
|
||||
{
|
||||
for (uint32_t i = 0; i < extension.compressionControlPlaneCount; i++)
|
||||
{
|
||||
m_compression_control.pFixedRateFlags[i] = extension.pFixedRateFlags[i];
|
||||
}
|
||||
}
|
||||
|
||||
wsi_ext_image_compression_control::wsi_ext_image_compression_control(const wsi_ext_image_compression_control &extension)
|
||||
: wsi_ext_image_compression_control(extension.m_compression_control)
|
||||
{
|
||||
}
|
||||
|
||||
VkImageCompressionControlEXT wsi_ext_image_compression_control::get_compression_control_properties()
|
||||
{
|
||||
return m_compression_control;
|
||||
}
|
||||
|
||||
VkImageCompressionFlagsEXT wsi_ext_image_compression_control::get_bitmask_for_image_compression_flags()
|
||||
{
|
||||
return m_compression_control.flags;
|
||||
}
|
||||
|
||||
std::optional<wsi_ext_image_compression_control> wsi_ext_image_compression_control::create(
|
||||
VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
const auto *image_compression_control = util::find_extension<VkImageCompressionControlEXT>(
|
||||
VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, swapchain_create_info->pNext);
|
||||
|
||||
layer::device_private_data &device_data = layer::device_private_data::get(device);
|
||||
if (device_data.is_swapchain_compression_control_enabled() && image_compression_control != nullptr)
|
||||
{
|
||||
return wsi_ext_image_compression_control{ *image_compression_control };
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
};
|
||||
124
wsi/extensions/image_compression_control.hpp
Normal file
124
wsi/extensions/image_compression_control.hpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file image_compression_control.hpp
|
||||
*
|
||||
* @brief Contains the implementation for VK_EXT_image_compression_control extension.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/macros.hpp>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
using util::MAX_PLANES;
|
||||
|
||||
/**
|
||||
* @brief Image compresssion control extension class
|
||||
*
|
||||
* This class implements the image compression control features.
|
||||
* Backends needing additional features will create its own local
|
||||
* copy and inherit this class.
|
||||
*/
|
||||
class wsi_ext_image_compression_control : public wsi_ext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the extension.
|
||||
*/
|
||||
WSI_DEFINE_EXTENSION(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME);
|
||||
|
||||
/**
|
||||
* @brief Constructor for the wsi_ext_image_compression_control class.
|
||||
*
|
||||
* @param extension Reference to VkImageCompressionControlEXT structure.
|
||||
*/
|
||||
wsi_ext_image_compression_control(const VkImageCompressionControlEXT &extension);
|
||||
|
||||
wsi_ext_image_compression_control(const wsi_ext_image_compression_control &extension);
|
||||
|
||||
wsi_ext_image_compression_control &operator=(const wsi_ext_image_compression_control &extension)
|
||||
{
|
||||
if (this == &extension)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto compression_control = wsi_ext_image_compression_control(extension);
|
||||
std::swap(m_compression_control, compression_control.m_compression_control);
|
||||
for (uint32_t i = 0; i < compression_control.m_compression_control.compressionControlPlaneCount; i++)
|
||||
{
|
||||
m_compression_control.pFixedRateFlags[i] = compression_control.m_compression_control.pFixedRateFlags[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create wsi_ext_image_compression_control class if deemed necessary.
|
||||
*
|
||||
* @param device The Vulkan device
|
||||
* @param swapchain_create_info Swapchain create info
|
||||
* @return Valid wsi_ext_image_compression_control if requested by application,
|
||||
* otherwise - an empty optional.
|
||||
*/
|
||||
static std::optional<wsi_ext_image_compression_control> create(
|
||||
VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info);
|
||||
|
||||
/**
|
||||
* @brief This API is used to get the compression control properties of an image.
|
||||
*
|
||||
* @return The image compression control properties.
|
||||
*/
|
||||
VkImageCompressionControlEXT get_compression_control_properties();
|
||||
|
||||
/**
|
||||
* @brief This API is used to get the bitmask for image compression flags.
|
||||
*
|
||||
* @return The bitmask for image compression flags.
|
||||
*/
|
||||
VkImageCompressionFlagsEXT get_bitmask_for_image_compression_flags();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Array to hold the pFixedRateFlags.
|
||||
*/
|
||||
VkImageCompressionFixedRateFlagsEXT m_array_fixed_rate_flags[MAX_PLANES];
|
||||
|
||||
/**
|
||||
* @brief Image compression control properties.
|
||||
*/
|
||||
VkImageCompressionControlEXT m_compression_control;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
44
wsi/extensions/present_id.cpp
Normal file
44
wsi/extensions/present_id.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file present_id.cpp
|
||||
*
|
||||
* @brief Contains the implementation for the VK_KHR_present_id extension.
|
||||
*/
|
||||
#include "present_id.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
void wsi_ext_present_id::set_present_id(uint64_t value)
|
||||
{
|
||||
if (value != 0)
|
||||
{
|
||||
assert(value > m_present_id);
|
||||
m_present_id = value;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
69
wsi/extensions/present_id.hpp
Normal file
69
wsi/extensions/present_id.hpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file present_id.hpp
|
||||
*
|
||||
* @brief Contains the base class declaration for the VK_KHR_present_id extension.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/macros.hpp>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Present ID extension class
|
||||
*
|
||||
* This class defines the present ID extension
|
||||
* features.
|
||||
*/
|
||||
class wsi_ext_present_id : public wsi_ext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the extension.
|
||||
*/
|
||||
WSI_DEFINE_EXTENSION(VK_KHR_PRESENT_ID_EXTENSION_NAME);
|
||||
|
||||
/**
|
||||
* @brief Set the present ID for the swapchain.
|
||||
*
|
||||
* @param value Value to set for the present_id.
|
||||
*/
|
||||
void set_present_id(uint64_t value);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Current present ID for this swapchain.
|
||||
*/
|
||||
uint64_t m_present_id{ 0 };
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -23,16 +23,84 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file time_domains.cpp
|
||||
* @file present_timing.cpp
|
||||
*
|
||||
* @brief Contains implemenations and details for the time domains per backend.
|
||||
* @brief Contains the implentation for the VK_EXT_present_timing extension.
|
||||
*/
|
||||
#include <cassert>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
|
||||
#include "time_domains.hpp"
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "present_timing.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
namespace wsi
|
||||
{
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
wsi_ext_present_timing::wsi_ext_present_timing(const util::allocator &allocator)
|
||||
: m_allocator(allocator)
|
||||
, m_queue(allocator)
|
||||
, m_time_domains(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
wsi_ext_present_timing::~wsi_ext_present_timing()
|
||||
{
|
||||
}
|
||||
|
||||
VkResult wsi_ext_present_timing::present_timing_queue_set_size(size_t queue_size)
|
||||
{
|
||||
if (present_timing_get_num_outstanding_results() > queue_size)
|
||||
{
|
||||
return VK_NOT_READY;
|
||||
}
|
||||
|
||||
util::vector<swapchain_presentation_entry> presentation_timing(
|
||||
util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE));
|
||||
if (!presentation_timing.try_reserve(queue_size))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
for (auto iter : m_queue.m_timings)
|
||||
{
|
||||
if (iter.is_outstanding)
|
||||
{
|
||||
if (!presentation_timing.try_push_back(iter))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_queue.m_timings.swap(presentation_timing);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
size_t wsi_ext_present_timing::present_timing_get_num_outstanding_results()
|
||||
{
|
||||
size_t num_outstanding = 0;
|
||||
|
||||
for (const auto &iter : m_queue.m_timings)
|
||||
{
|
||||
if (iter.is_outstanding)
|
||||
{
|
||||
num_outstanding++;
|
||||
}
|
||||
}
|
||||
return num_outstanding;
|
||||
}
|
||||
|
||||
VkResult wsi_ext_present_timing::add_presentation_entry(const wsi::swapchain_presentation_entry &presentation_entry)
|
||||
{
|
||||
if (!m_queue.m_timings.try_push_back(presentation_entry))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
swapchain_time_domains &wsi_ext_present_timing::get_swapchain_time_domains()
|
||||
{
|
||||
return m_time_domains;
|
||||
}
|
||||
|
||||
VkResult swapchain_time_domains::calibrate(VkPresentStageFlagBitsEXT present_stage,
|
||||
swapchain_calibrated_time *calibrated_time)
|
||||
|
|
@ -49,7 +117,7 @@ VkResult swapchain_time_domains::calibrate(VkPresentStageFlagBitsEXT present_sta
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
VkResult swapchain_time_domains::set_swapchain_time_domain_properties(
|
||||
VkResult swapchain_time_domains::get_swapchain_time_domain_properties(
|
||||
VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, uint64_t *pTimeDomainsCounter)
|
||||
{
|
||||
if (pTimeDomainsCounter != nullptr)
|
||||
|
|
@ -86,5 +154,16 @@ VkResult swapchain_time_domains::set_swapchain_time_domain_properties(
|
|||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool swapchain_time_domains::add_time_domain(util::unique_ptr<swapchain_time_domain> time_domain)
|
||||
{
|
||||
if (time_domain)
|
||||
{
|
||||
return m_time_domains.try_push_back(std::move(time_domain));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* namespace wsi */
|
||||
|
||||
#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */
|
||||
265
wsi/extensions/present_timing.hpp
Normal file
265
wsi/extensions/present_timing.hpp
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file present_timing.hpp
|
||||
*
|
||||
* @brief Contains the implentation for the VK_EXT_present_timing extension.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <layer/wsi_layer_experimental.hpp>
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/macros.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Swapchain presentation entry
|
||||
*
|
||||
* This structure is used to keep the parameters for the swapchain presentation entry.
|
||||
*
|
||||
*/
|
||||
struct swapchain_presentation_entry
|
||||
{
|
||||
/**
|
||||
* Whether this entry is an outstanding result or not.
|
||||
*/
|
||||
bool is_outstanding{ false };
|
||||
/**
|
||||
* The present id.
|
||||
*/
|
||||
uint64_t present_id{ 0 };
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Timings queue
|
||||
*
|
||||
* This structure is used to keep the parameters related to the presentation timing queue.
|
||||
*
|
||||
*/
|
||||
struct timings_queue
|
||||
{
|
||||
timings_queue(const util::allocator &allocator)
|
||||
: m_timings(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
util::vector<swapchain_presentation_entry> m_timings;
|
||||
};
|
||||
|
||||
// Predefined struct for calibrated time
|
||||
struct swapchain_calibrated_time
|
||||
{
|
||||
VkTimeDomainKHR time_domain;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
// Base struct for swapchain time domain
|
||||
class swapchain_time_domain
|
||||
{
|
||||
public:
|
||||
swapchain_time_domain(VkPresentStageFlagsEXT presentStages)
|
||||
: m_present_stages(presentStages)
|
||||
{
|
||||
}
|
||||
|
||||
virtual swapchain_calibrated_time calibrate() = 0;
|
||||
|
||||
VkPresentStageFlagsEXT get_present_stages()
|
||||
{
|
||||
return m_present_stages;
|
||||
}
|
||||
|
||||
private:
|
||||
VkPresentStageFlagsEXT m_present_stages;
|
||||
};
|
||||
|
||||
class vulkan_time_domain : public swapchain_time_domain
|
||||
{
|
||||
public:
|
||||
vulkan_time_domain(VkPresentStageFlagsEXT presentStages, VkTimeDomainKHR time_domain)
|
||||
: swapchain_time_domain(presentStages)
|
||||
, m_time_domain(time_domain)
|
||||
{
|
||||
}
|
||||
|
||||
/* The calibrate function should return a Vulkan time domain + an offset.*/
|
||||
swapchain_calibrated_time calibrate() override
|
||||
{
|
||||
return { m_time_domain, 0 };
|
||||
}
|
||||
|
||||
private:
|
||||
VkTimeDomainKHR m_time_domain;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class holding time domains for a swapchain
|
||||
*
|
||||
*/
|
||||
class swapchain_time_domains
|
||||
{
|
||||
public:
|
||||
swapchain_time_domains(const util::allocator &allocator)
|
||||
: m_time_domains(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add new time domain
|
||||
*
|
||||
* @param time_domain Time domain to add
|
||||
* @return true Time domain has been added.
|
||||
* @return false Time domain has not been added due to an issue.
|
||||
*/
|
||||
bool add_time_domain(util::unique_ptr<swapchain_time_domain> time_domain);
|
||||
|
||||
VkResult calibrate(VkPresentStageFlagBitsEXT presentStages, swapchain_calibrated_time *calibrated_time);
|
||||
|
||||
/**
|
||||
* @brief Get swapchain time domain properties.
|
||||
*
|
||||
* @param pSwapchainTimeDomainProperties time domain struct to be set
|
||||
* @param pTimeDomainsCounter size of the pSwapchainTimeDomainProperties
|
||||
*
|
||||
* @return Returns VK_SUCCESS on success, otherwise an appropriate error code.
|
||||
*/
|
||||
VkResult get_swapchain_time_domain_properties(VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties,
|
||||
uint64_t *pTimeDomainsCounter);
|
||||
|
||||
private:
|
||||
util::vector<util::unique_ptr<swapchain_time_domain>> m_time_domains;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Present timing extension class
|
||||
*
|
||||
* This class implements or act as a base class for the present timing extension
|
||||
* features.
|
||||
*/
|
||||
class wsi_ext_present_timing : public wsi_ext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the extension.
|
||||
*/
|
||||
WSI_DEFINE_EXTENSION(VK_EXT_PRESENT_TIMING_EXTENSION_NAME);
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
static util::unique_ptr<T> create(const util::allocator &allocator,
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, N> &domains)
|
||||
{
|
||||
auto present_timing = allocator.make_unique<T>(allocator);
|
||||
for (auto &domain : domains)
|
||||
{
|
||||
if (!present_timing->get_swapchain_time_domains().add_time_domain(std::move(domain)))
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to add a time domain.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return present_timing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor for the wsi_ext_present_timing class.
|
||||
*/
|
||||
wsi_ext_present_timing(const util::allocator &allocator);
|
||||
|
||||
/**
|
||||
* @brief Destructor for the wsi_ext_present_timing class.
|
||||
*/
|
||||
virtual ~wsi_ext_present_timing();
|
||||
|
||||
/**
|
||||
* @brief Set the queue size for the present timing queue.
|
||||
*
|
||||
* This API allows modifying the queue size of the present timing queue.
|
||||
*
|
||||
* @param queue_size The new queue size to set.
|
||||
*
|
||||
* @return VK_SUCCESS on if the queue size was updated correctly.
|
||||
* VK_NOT_READY when the number of present timing outstanding
|
||||
* items are larger than the queue size. VK_ERROR_OUT_OF_HOST_MEMORY
|
||||
* when there is no host memory available for the new size.
|
||||
*/
|
||||
VkResult present_timing_queue_set_size(size_t queue_size);
|
||||
|
||||
/**
|
||||
* @brief Get the number of outstanding presnt timing results.
|
||||
*
|
||||
* This API allows getting the number of the current outstanding results.
|
||||
*
|
||||
* @return The size of the currently outstanding present timing items.
|
||||
*/
|
||||
size_t present_timing_get_num_outstanding_results();
|
||||
|
||||
/**
|
||||
* @brief Add a presentation entry to the present timing queue.
|
||||
*
|
||||
* This API pushes a presentation entry to the present timing queue.
|
||||
*
|
||||
* @param sc_presentation_entry Reference to the presentation entry to be added.
|
||||
*
|
||||
* @return VK_SUCCESS when the entry was inserted successfully and VK_ERROR_OUT_OF_HOST_MEMORY
|
||||
* when there is no host memory.
|
||||
*/
|
||||
VkResult add_presentation_entry(const wsi::swapchain_presentation_entry &sc_presentation_entry);
|
||||
|
||||
/**
|
||||
* @brief Get the swapchain time domains
|
||||
*/
|
||||
swapchain_time_domains &get_swapchain_time_domains();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief User provided memory allocation callbacks.
|
||||
*/
|
||||
const util::allocator m_allocator;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief The presentation timing queue.
|
||||
*/
|
||||
timings_queue m_queue;
|
||||
|
||||
/**
|
||||
* @brief Handle the backend specific time domains for each present stage.
|
||||
*/
|
||||
swapchain_time_domains m_time_domains;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
#endif
|
||||
119
wsi/extensions/swapchain_maintenance.cpp
Normal file
119
wsi/extensions/swapchain_maintenance.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file swapchain_maintenance.cpp
|
||||
*
|
||||
* @brief Contains the implementation for VK_EXT_swapchain_maintenance1 extension.
|
||||
*/
|
||||
|
||||
#include <layer/private_data.hpp>
|
||||
#include <wsi/wsi_factory.hpp>
|
||||
#include <wsi/surface_properties.hpp>
|
||||
|
||||
#include "swapchain_maintenance.hpp"
|
||||
#include "present_id.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
wsi_ext_swapchain_maintenance1::wsi_ext_swapchain_maintenance1(const util::allocator &allocator)
|
||||
: m_present_modes(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
VkResult wsi_ext_swapchain_maintenance1::handle_switching_presentation_mode(VkPresentModeKHR swapchain_present_mode)
|
||||
{
|
||||
assert(m_present_modes.size() > 0);
|
||||
auto it = std::find_if(m_present_modes.begin(), m_present_modes.end(),
|
||||
[swapchain_present_mode](VkPresentModeKHR p) { return p == swapchain_present_mode; });
|
||||
if (it == m_present_modes.end())
|
||||
{
|
||||
WSI_LOG_ERROR("unable to switch presentation mode");
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
m_present_mode = swapchain_present_mode;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult wsi_ext_swapchain_maintenance1::handle_swapchain_present_modes_create_info(
|
||||
VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, VkSurfaceKHR surface)
|
||||
{
|
||||
const auto *swapchain_present_modes_create_info = util::find_extension<VkSwapchainPresentModesCreateInfoEXT>(
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT, swapchain_create_info->pNext);
|
||||
if (swapchain_present_modes_create_info != nullptr)
|
||||
{
|
||||
if (!m_present_modes.try_resize(swapchain_present_modes_create_info->presentModeCount))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
layer::device_private_data &device_data = layer::device_private_data::get(device);
|
||||
auto &instance = device_data.instance_data;
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
for (uint32_t i = 0; i < swapchain_present_modes_create_info->presentModeCount; i++)
|
||||
{
|
||||
auto res =
|
||||
props->is_compatible_present_modes(m_present_mode, swapchain_present_modes_create_info->pPresentModes[i]);
|
||||
if (!res)
|
||||
{
|
||||
WSI_LOG_ERROR("present modes incompatible");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
m_present_modes[i] = swapchain_present_modes_create_info->pPresentModes[i];
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult wsi_ext_swapchain_maintenance1::handle_scaling_create_info(
|
||||
VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, const VkSurfaceKHR surface)
|
||||
{
|
||||
|
||||
auto present_scaling_create_info = util::find_extension<VkSwapchainPresentScalingCreateInfoEXT>(
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT, swapchain_create_info);
|
||||
if (present_scaling_create_info != nullptr)
|
||||
{
|
||||
auto &device_data = layer::device_private_data::get(device);
|
||||
auto &instance = device_data.instance_data;
|
||||
|
||||
VkSurfacePresentScalingCapabilitiesEXT scaling_capabilities = {};
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
props->get_surface_present_scaling_and_gravity(&scaling_capabilities);
|
||||
|
||||
if (((present_scaling_create_info->scalingBehavior != 0) &&
|
||||
((scaling_capabilities.supportedPresentScaling & present_scaling_create_info->scalingBehavior) == 0)) ||
|
||||
((present_scaling_create_info->presentGravityX != 0) &&
|
||||
((scaling_capabilities.supportedPresentGravityX & present_scaling_create_info->presentGravityX) == 0)) ||
|
||||
((present_scaling_create_info->presentGravityY != 0) &&
|
||||
((scaling_capabilities.supportedPresentGravityY & present_scaling_create_info->presentGravityY) == 0)))
|
||||
{
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
};
|
||||
111
wsi/extensions/swapchain_maintenance.hpp
Normal file
111
wsi/extensions/swapchain_maintenance.hpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file swapchain_maintenance.cpp
|
||||
*
|
||||
* @brief Contains the base class declaration for the VK_EXT_swapchain_maintenance1 extension.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <layer/private_data.hpp>
|
||||
#include <util/custom_allocator.hpp>
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief VK_EXT_swapchain_maintenance1 extension class
|
||||
*
|
||||
* This class defines the VK_EXT_swapchain_maintenance1 extension
|
||||
* features.
|
||||
*/
|
||||
class wsi_ext_swapchain_maintenance1 : public wsi_ext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief The name of the extension.
|
||||
*/
|
||||
WSI_DEFINE_EXTENSION(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME);
|
||||
|
||||
/**
|
||||
* @brief Constructor for the wsi_ext_swapchain_maintenance1 class.
|
||||
*/
|
||||
wsi_ext_swapchain_maintenance1(const util::allocator &allocator);
|
||||
|
||||
/**
|
||||
* @brief Handle presentation mode switching.
|
||||
*
|
||||
* If VkSwapchainPresentModeInfoEXT is supplied as part of the pNext chain of VkPresentInfoKHR
|
||||
* then this function handles switching the swapchains(s)' presentation mode
|
||||
* to the one(s) requested in VkSwapchainPresentModeInfoEXT structure.
|
||||
*
|
||||
* @param swapchain_present_mode presentation mode to switch to.
|
||||
*
|
||||
* @return VK_SUCCESS on success or an error code otherwise.
|
||||
*/
|
||||
VkResult handle_switching_presentation_mode(VkPresentModeKHR swapchain_present_mode);
|
||||
|
||||
/**
|
||||
* @brief If VkSwapchainPresentModesCreateInfoEXT is supplied as part of the pNext chain of VkSwapchainCreateInfoKHR
|
||||
* then this function gets the surface properties and checks whether the present modes are compatible and updates the object's present modes.
|
||||
*
|
||||
* @param device The device handler.
|
||||
* @param swapchain_create_info Pointer to the swapchain create info, used to extract VkSwapchainPresentModesCreateInfoEXT.
|
||||
* @param surface The surface handler.
|
||||
*
|
||||
* @return VK_SUCCESS on success or an error code otherwise.
|
||||
*/
|
||||
VkResult handle_swapchain_present_modes_create_info(VkDevice device,
|
||||
const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
VkSurfaceKHR surface);
|
||||
|
||||
/**
|
||||
* @brief If VkSwapchainPresentScalingCreateInfoEXT is supplied as part of the pNext chain of VkSwapchainCreateInfoKHR
|
||||
* then this function gets the surface properties and checks whether scaling can be done.
|
||||
*
|
||||
* @param device The device handler.
|
||||
* @param swapchain_create_info Pointer to the swapchain create info, used to extract VkSwapchainPresentScalingCreateInfoEXT.
|
||||
* @param surface The surface handler.
|
||||
*
|
||||
* @return VK_SUCCESS on success or an error code otherwise.
|
||||
*/
|
||||
VkResult handle_scaling_create_info(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
const VkSurfaceKHR surface);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Possible presentation modes this swapchain is allowed to present with VkSwapchainPresentModesCreateInfoEXT
|
||||
*/
|
||||
util::vector<VkPresentModeKHR> m_present_modes;
|
||||
|
||||
/**
|
||||
* @brief Present mode currently being used for this swapchain
|
||||
*/
|
||||
VkPresentModeKHR m_present_mode;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
65
wsi/extensions/wsi_extension.cpp
Normal file
65
wsi/extensions/wsi_extension.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wsi_extension.hpp
|
||||
*
|
||||
* @brief Contains the base class definition for wsi extension.
|
||||
*/
|
||||
|
||||
#include "wsi_extension.hpp"
|
||||
|
||||
#include <util/log.hpp>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
wsi_ext_maintainer::wsi_ext_maintainer(const util::allocator &allocator)
|
||||
: m_enabled_extensions(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
bool wsi_ext_maintainer::add_extension(util::unique_ptr<wsi_ext> extension)
|
||||
{
|
||||
if (extension)
|
||||
{
|
||||
auto it = std::find_if(m_enabled_extensions.begin(), m_enabled_extensions.end(),
|
||||
[&extension](util::unique_ptr<wsi_ext> &ext) { return ext->is_same_type(*extension); });
|
||||
|
||||
if (it != m_enabled_extensions.end())
|
||||
{
|
||||
WSI_LOG_WARNING("Adding a duplicate extension (%s) to the extension list.", extension->get_name());
|
||||
assert(false && "Adding a duplicate extension to the extension list.");
|
||||
|
||||
/* Replace the extension. Preferably this should never happen at runtime. */
|
||||
*it = std::move(extension);
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_enabled_extensions.try_push_back(std::move(extension));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} /* namespace wsi */
|
||||
145
wsi/extensions/wsi_extension.hpp
Normal file
145
wsi/extensions/wsi_extension.hpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file wsi_extension.hpp
|
||||
*
|
||||
* @brief Contains the base class declarations for wsi extension.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/custom_allocator.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
#define WSI_DEFINE_EXTENSION(x) \
|
||||
static constexpr char ext_name[] = #x; \
|
||||
const char *get_name() const override \
|
||||
{ \
|
||||
return ext_name; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WSI extension class
|
||||
*
|
||||
* Base wsi_extension class, for each new extension we want to support
|
||||
* we will have to create a new class that will inherit this one.
|
||||
* Extensions that will need backend specific implementations/data
|
||||
* should have a specific pure virtual interface for backend implementation.
|
||||
*
|
||||
* @note All of the derived classes are required to use "WSI_DEFINE_EXTENSION"
|
||||
* macro within the body of the class as it will enable the derived classes to be
|
||||
* deduced through templates.
|
||||
*/
|
||||
class wsi_ext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Get the name of the extension.
|
||||
*
|
||||
* This API is used to get the name of the extension which was
|
||||
* set when the object is created through the constructor.
|
||||
*
|
||||
* @return Name of the extension.
|
||||
*/
|
||||
virtual const char *get_name() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Checks if the extension is of same type as this one.
|
||||
*
|
||||
* @param extension The extension to check.
|
||||
*/
|
||||
bool is_same_type(const wsi_ext &extension) const
|
||||
{
|
||||
/* The functionality of this relies that the address of the pointers returned by
|
||||
* get_name() function is the same. As long as the derived extension is using
|
||||
* "WSI_DEFINE_EXTENSION" macro, then this should work. */
|
||||
return extension.get_name() == get_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the extension is of same type as this one.
|
||||
*
|
||||
* @tparam T The extension to check.
|
||||
* @return true if both extensions are of same type, false otherwise.
|
||||
*/
|
||||
template <typename T>
|
||||
bool is_same_type() const
|
||||
{
|
||||
/* The functionality of this relies that the address of the pointers returned by
|
||||
* get_name() function & T::ext_name is the same. As long as the derived extension
|
||||
* is using "WSI_DEFINE_EXTENSION" macro, then this should work. */
|
||||
return T::ext_name == get_name();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Swapchain extensions class
|
||||
*
|
||||
* Implementations which are specific to extensions are placed in specific classes that
|
||||
* are inherited from the class wsi_ext. wsi_ext_maintainer class helps in handling the
|
||||
* vector which contains unique_ptrs to those extension specific classes.
|
||||
*/
|
||||
class wsi_ext_maintainer
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief Keeps the pointer to extensions that are enabled.
|
||||
*/
|
||||
util::vector<util::unique_ptr<wsi_ext>> m_enabled_extensions;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the wsi_ext_maintainer class.
|
||||
*/
|
||||
wsi_ext_maintainer(const util::allocator &allocator);
|
||||
|
||||
/**
|
||||
* @brief Template API to get the pointer to the extension mentioned by the typename.
|
||||
*
|
||||
* @return Pointer to the extension.
|
||||
*/
|
||||
template <typename T>
|
||||
T *get_extension()
|
||||
{
|
||||
auto it = std::find_if(m_enabled_extensions.begin(), m_enabled_extensions.end(),
|
||||
[](util::unique_ptr<wsi_ext> &ext) { return ext->is_same_type<T>(); });
|
||||
|
||||
return it != m_enabled_extensions.end() ? static_cast<T *>((*it).get()) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds an extension to the extensions list.
|
||||
*
|
||||
* @param extension The unique_ptr to the extension to be added.
|
||||
*
|
||||
* @return True when the extension is added successfully.
|
||||
*/
|
||||
bool add_extension(util::unique_ptr<wsi_ext> extension);
|
||||
};
|
||||
} /* namespace wsi */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
|
||||
* Copyright (c) 2017-2019, 2021-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -122,12 +122,10 @@ static uint32_t fill_supported_formats(VkPhysicalDevice physical_device,
|
|||
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (layer::instance_private_data::get(physical_device).has_image_compression_support(physical_device))
|
||||
{
|
||||
formats[format_count].add_device_compression_support(physical_device, format_info);
|
||||
}
|
||||
#endif
|
||||
format_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,15 @@
|
|||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "swapchain.hpp"
|
||||
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/timed_semaphore.hpp>
|
||||
|
||||
#include "swapchain.hpp"
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
#include <wsi/extensions/present_timing.hpp>
|
||||
#include <wsi/extensions/swapchain_maintenance.hpp>
|
||||
#include <wsi/extensions/image_compression_control.hpp>
|
||||
#include "util/macros.hpp"
|
||||
|
||||
namespace wsi
|
||||
|
|
@ -52,9 +56,6 @@ struct image_data
|
|||
|
||||
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
|
||||
: wsi::swapchain_base(dev_data, pAllocator)
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
, m_image_compression_control{}
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +65,55 @@ swapchain::~swapchain()
|
|||
teardown();
|
||||
}
|
||||
|
||||
VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
auto compression_control = wsi_ext_image_compression_control::create(device, swapchain_create_info);
|
||||
if (compression_control)
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_image_compression_control>(*compression_control)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id>()))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.is_swapchain_maintenance1_enabled())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_swapchain_maintenance1>(m_allocator)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.should_layer_handle_frame_boundary_events())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_frame_boundary>(m_device_data)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
bool swapchain_support_enabled = swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT;
|
||||
if (swapchain_support_enabled)
|
||||
{
|
||||
if (!add_swapchain_extension(wsi_ext_present_timing_headless::create(m_allocator)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread)
|
||||
{
|
||||
|
|
@ -76,27 +126,6 @@ VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKH
|
|||
{
|
||||
use_presentation_thread = true;
|
||||
}
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 4> time_domains_array = {
|
||||
m_allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
|
||||
VK_TIME_DOMAIN_DEVICE_KHR),
|
||||
m_allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
|
||||
m_allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
|
||||
m_allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR)
|
||||
};
|
||||
|
||||
for (auto &time_domain : time_domains_array)
|
||||
{
|
||||
if (!m_time_domains.m_time_domains.try_push_back(std::move(time_domain)))
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to add a time domain to m_time_domains.");
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
|
@ -169,27 +198,32 @@ VkResult swapchain::allocate_and_bind_swapchain_image(VkImageCreateInfo image_cr
|
|||
VkResult swapchain::create_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image)
|
||||
{
|
||||
m_image_create_info = image_create_info;
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkImageCompressionControlEXT image_compression_control = {};
|
||||
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
/* Initialize compression control */
|
||||
m_image_compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
|
||||
m_image_compression_control.compressionControlPlaneCount =
|
||||
m_image_compression_control_params.compression_control_plane_count;
|
||||
m_image_compression_control.flags = m_image_compression_control_params.flags;
|
||||
m_image_compression_control.pFixedRateFlags = m_image_compression_control_params.fixed_rate_flags.data();
|
||||
m_image_compression_control.pNext = m_image_create_info.pNext;
|
||||
|
||||
m_image_create_info.pNext = &m_image_compression_control;
|
||||
auto *ext = get_swapchain_extension<wsi_ext_image_compression_control>();
|
||||
/* For image compression control, additional requirements to be satisfied such as
|
||||
* existence of VkImageCompressionControlEXT in swaphain_create_info for
|
||||
* the ext to be added to the list. So we check whether we got a valid pointer
|
||||
* and proceed if yes. */
|
||||
if (ext)
|
||||
{
|
||||
image_compression_control = ext->get_compression_control_properties();
|
||||
image_compression_control.pNext = m_image_create_info.pNext;
|
||||
m_image_create_info.pNext = &image_compression_control;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), &image.image);
|
||||
}
|
||||
|
||||
void swapchain::present_image(const pending_present_request &pending_present)
|
||||
{
|
||||
set_present_id(pending_present.present_id);
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
}
|
||||
unpresent_image(pending_present.image_index);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2024 Arm Limited.
|
||||
* Copyright (c) 2017-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -32,13 +32,14 @@
|
|||
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <wsi/extensions/present_timing.hpp>
|
||||
#include <wsi/swapchain_base.hpp>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace headless
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Headless swapchain class.
|
||||
*
|
||||
|
|
@ -126,10 +127,50 @@ protected:
|
|||
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
|
||||
|
||||
private:
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkImageCompressionControlEXT m_image_compression_control;
|
||||
#endif
|
||||
/**
|
||||
* @brief Adds required extensions to the extension list of the swapchain
|
||||
*
|
||||
* @param device Vulkan device
|
||||
* @param swapchain_create_info Swapchain create info
|
||||
* @return VK_SUCCESS on success, other result codes on failure
|
||||
*/
|
||||
VkResult add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) override;
|
||||
};
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Present timing extension class
|
||||
*
|
||||
* This class implements present timing features declarations that are specific to the headless backend.
|
||||
*/
|
||||
class wsi_ext_present_timing_headless : public wsi_ext_present_timing
|
||||
{
|
||||
public:
|
||||
static util::unique_ptr<wsi_ext_present_timing_headless> create(const util::allocator &allocator)
|
||||
{
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 4> time_domains_array = {
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
|
||||
VK_TIME_DOMAIN_DEVICE_KHR),
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
|
||||
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT,
|
||||
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR)
|
||||
};
|
||||
|
||||
return wsi_ext_present_timing::create<wsi_ext_present_timing_headless>(allocator, time_domains_array);
|
||||
}
|
||||
|
||||
private:
|
||||
wsi_ext_present_timing_headless(const util::allocator &allocator)
|
||||
: wsi_ext_present_timing(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
/* Allow util::allocator to access the private constructor */
|
||||
friend util::allocator;
|
||||
};
|
||||
#endif
|
||||
} /* namespace headless */
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2025 Arm Limited.
|
||||
* Copyright (c) 2022, 2024-2025 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -39,7 +39,6 @@ VkResult surface_format_properties::check_device_support(VkPhysicalDevice phys_d
|
|||
&image_format_props);
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkResult surface_format_properties::add_device_compression_support(
|
||||
VkPhysicalDevice phys_dev, VkPhysicalDeviceImageFormatInfo2KHR image_format_info)
|
||||
{
|
||||
|
|
@ -70,12 +69,11 @@ VkResult surface_format_properties::add_device_compression_support(
|
|||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
void surface_format_properties::fill_format_properties(VkSurfaceFormat2KHR &surf_format) const
|
||||
{
|
||||
surf_format.surfaceFormat = m_surface_format;
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
|
||||
auto *compression_properties = util::find_extension<VkImageCompressionPropertiesEXT>(
|
||||
VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, surf_format.pNext);
|
||||
if (compression_properties != nullptr)
|
||||
|
|
@ -94,7 +92,6 @@ void surface_format_properties::fill_format_properties(VkSurfaceFormat2KHR &surf
|
|||
compression_properties->imageCompressionFixedRateFlags = m_compression.imageCompressionFixedRateFlags;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void get_surface_capabilities_common(VkPhysicalDevice physical_device, VkSurfaceCapabilitiesKHR *surface_capabilities)
|
||||
|
|
|
|||
|
|
@ -31,18 +31,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "util/extension_list.hpp"
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
#include "layer/private_data.hpp"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/format_modifiers.hpp"
|
||||
#include "util/drm/drm_utils.hpp"
|
||||
#include "util/extension_list.hpp"
|
||||
#include "util/format_modifiers.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/macros.hpp"
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
#endif
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
|
|
@ -135,10 +132,8 @@ class surface_format_properties
|
|||
public:
|
||||
surface_format_properties(VkFormat format)
|
||||
: m_surface_format{ format, VK_COLORSPACE_SRGB_NONLINEAR_KHR }
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
, m_compression{ VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, nullptr, VK_IMAGE_COMPRESSION_DEFAULT_EXT,
|
||||
VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT }
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -149,10 +144,8 @@ public:
|
|||
|
||||
VkResult check_device_support(VkPhysicalDevice phys_dev, VkPhysicalDeviceImageFormatInfo2 image_format_info);
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkResult add_device_compression_support(VkPhysicalDevice phys_dev,
|
||||
VkPhysicalDeviceImageFormatInfo2 image_format_info);
|
||||
#endif
|
||||
|
||||
void fill_format_properties(VkSurfaceFormat2KHR &surf_format) const;
|
||||
|
||||
|
|
@ -168,10 +161,8 @@ public:
|
|||
|
||||
VkSurfaceFormatKHR m_surface_format;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
private:
|
||||
VkImageCompressionPropertiesEXT m_compression;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@
|
|||
|
||||
#include "swapchain_base.hpp"
|
||||
#include "wsi_factory.hpp"
|
||||
|
||||
#include "extensions/present_timing.hpp"
|
||||
#include "extensions/swapchain_maintenance.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
|
|
@ -216,82 +220,14 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll
|
|||
, m_ancestor(VK_NULL_HANDLE)
|
||||
, m_device(VK_NULL_HANDLE)
|
||||
, m_queue(VK_NULL_HANDLE)
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
, m_image_compression_control_params({ VK_IMAGE_COMPRESSION_DEFAULT_EXT, 0, {} })
|
||||
#endif
|
||||
, m_image_create_info()
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
, m_time_domains(m_allocator)
|
||||
#endif
|
||||
, m_image_acquire_lock()
|
||||
, m_error_state(VK_NOT_READY)
|
||||
, m_started_presenting(false)
|
||||
, m_frame_boundary_handler(m_device_data)
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
, m_presentation_timing(m_allocator)
|
||||
#endif
|
||||
, m_extensions(m_allocator)
|
||||
{
|
||||
}
|
||||
|
||||
static VkResult handle_scaling_create_info(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
const VkSurfaceKHR &surface)
|
||||
{
|
||||
|
||||
auto present_scaling_create_info = util::find_extension<VkSwapchainPresentScalingCreateInfoEXT>(
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT, swapchain_create_info);
|
||||
if (present_scaling_create_info != nullptr)
|
||||
{
|
||||
auto &device_data = layer::device_private_data::get(device);
|
||||
auto &instance = device_data.instance_data;
|
||||
|
||||
VkSurfacePresentScalingCapabilitiesEXT scaling_capabilities = {};
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
props->get_surface_present_scaling_and_gravity(&scaling_capabilities);
|
||||
|
||||
if (((present_scaling_create_info->scalingBehavior != 0) &&
|
||||
((scaling_capabilities.supportedPresentScaling & present_scaling_create_info->scalingBehavior) == 0)) ||
|
||||
((present_scaling_create_info->presentGravityX != 0) &&
|
||||
((scaling_capabilities.supportedPresentGravityX & present_scaling_create_info->presentGravityX) == 0)) ||
|
||||
((present_scaling_create_info->presentGravityY != 0) &&
|
||||
((scaling_capabilities.supportedPresentGravityY & present_scaling_create_info->presentGravityY) == 0)))
|
||||
{
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain_base::handle_swapchain_present_modes_create_info(
|
||||
VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
const auto *swapchain_present_modes_create_info = util::find_extension<VkSwapchainPresentModesCreateInfoEXT>(
|
||||
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODES_CREATE_INFO_EXT, swapchain_create_info->pNext);
|
||||
if (swapchain_present_modes_create_info != nullptr)
|
||||
{
|
||||
if (!m_present_modes.try_resize(swapchain_present_modes_create_info->presentModeCount))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
layer::device_private_data &device_data = layer::device_private_data::get(device);
|
||||
auto &instance = device_data.instance_data;
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, m_surface);
|
||||
assert(props != nullptr);
|
||||
for (uint32_t i = 0; i < swapchain_present_modes_create_info->presentModeCount; i++)
|
||||
{
|
||||
auto res =
|
||||
props->is_compatible_present_modes(m_present_mode, swapchain_present_modes_create_info->pPresentModes[i]);
|
||||
if (!res)
|
||||
{
|
||||
WSI_LOG_ERROR("present modes incompatible");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
m_present_modes[i] = swapchain_present_modes_create_info->pPresentModes[i];
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
assert(device != VK_NULL_HANDLE);
|
||||
|
|
@ -300,25 +236,17 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
|
||||
m_device = device;
|
||||
m_surface = swapchain_create_info->surface;
|
||||
|
||||
m_present_mode = swapchain_create_info->presentMode;
|
||||
|
||||
TRY(handle_swapchain_present_modes_create_info(device, swapchain_create_info));
|
||||
/* Register required extensions by the swapchain */
|
||||
TRY_LOG_CALL(add_required_extensions(device, swapchain_create_info));
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
const auto *image_compression_control = util::find_extension<VkImageCompressionControlEXT>(
|
||||
VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, swapchain_create_info->pNext);
|
||||
if (m_device_data.is_swapchain_compression_control_enabled() && image_compression_control != nullptr)
|
||||
auto *ext = get_swapchain_extension<wsi::wsi_ext_swapchain_maintenance1>();
|
||||
if (ext)
|
||||
{
|
||||
m_image_compression_control_params.compression_control_plane_count =
|
||||
image_compression_control->compressionControlPlaneCount;
|
||||
m_image_compression_control_params.flags = image_compression_control->flags;
|
||||
for (uint32_t i = 0; i < image_compression_control->compressionControlPlaneCount; i++)
|
||||
{
|
||||
m_image_compression_control_params.fixed_rate_flags[i] = image_compression_control->pFixedRateFlags[i];
|
||||
}
|
||||
TRY_LOG_CALL(ext->handle_swapchain_present_modes_create_info(device, swapchain_create_info, m_surface));
|
||||
TRY_LOG_CALL(ext->handle_scaling_create_info(device, swapchain_create_info, m_surface));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Init image to invalid values. */
|
||||
if (!m_swapchain_images.try_resize(swapchain_create_info->minImageCount))
|
||||
|
|
@ -326,8 +254,6 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
TRY_LOG_CALL(handle_scaling_create_info(device, swapchain_create_info, m_surface));
|
||||
|
||||
/* We have allocated images, we can call the platform init function if something needs to be done. */
|
||||
bool use_presentation_thread = true;
|
||||
TRY_LOG_CALL(init_platform(device, swapchain_create_info, use_presentation_thread));
|
||||
|
|
@ -414,7 +340,6 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
}
|
||||
|
||||
set_error_state(VK_SUCCESS);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -683,25 +608,23 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
|
|||
const swapchain_presentation_parameters &submit_info)
|
||||
{
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
if (submit_info.present_timing_info)
|
||||
auto *ext = get_swapchain_extension<wsi::wsi_ext_present_timing>();
|
||||
if (ext)
|
||||
{
|
||||
wsi::swapchain_presentation_entry presentation_entry = {};
|
||||
presentation_entry.present_id = submit_info.pending_present.present_id;
|
||||
if ((m_presentation_timing.size()) >= m_presentation_timing.capacity())
|
||||
{
|
||||
return VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT;
|
||||
}
|
||||
|
||||
if (!m_presentation_timing.try_push_back(presentation_entry))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
TRY_LOG_CALL(ext->add_presentation_entry(presentation_entry));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (submit_info.switch_presentation_mode)
|
||||
{
|
||||
TRY(handle_switching_presentation_mode(submit_info.present_mode));
|
||||
/* Assert when a presentation mode switch is requested and the swapchain_maintenance1 extension which implements this is not available */
|
||||
auto *ext = get_swapchain_extension<wsi::wsi_ext_swapchain_maintenance1>(true);
|
||||
if (ext)
|
||||
{
|
||||
TRY_LOG_CALL(ext->handle_switching_presentation_mode(submit_info.present_mode));
|
||||
}
|
||||
}
|
||||
|
||||
const VkSemaphore *wait_semaphores = &m_swapchain_images[submit_info.pending_present.image_index].present_semaphore;
|
||||
|
|
@ -725,9 +648,11 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
|
|||
/* Do not handle the event if it was handled before reaching this point */
|
||||
if (submit_info.handle_present_frame_boundary_event)
|
||||
{
|
||||
frame_boundary = m_frame_boundary_handler.handle_frame_boundary_event(
|
||||
present_info, &m_swapchain_images[submit_info.pending_present.image_index].image);
|
||||
if (frame_boundary.has_value())
|
||||
auto *ext = get_swapchain_extension<wsi::wsi_ext_frame_boundary>();
|
||||
frame_boundary = handle_frame_boundary_event(
|
||||
present_info, &m_swapchain_images[submit_info.pending_present.image_index].image, ext);
|
||||
|
||||
if (frame_boundary)
|
||||
{
|
||||
submission_pnext = &frame_boundary.value();
|
||||
}
|
||||
|
|
@ -854,77 +779,9 @@ VkResult swapchain_base::is_bind_allowed(uint32_t image_index) const
|
|||
VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
VkResult swapchain_base::handle_switching_presentation_mode(VkPresentModeKHR swapchain_present_mode)
|
||||
bool swapchain_base::add_swapchain_extension(util::unique_ptr<wsi_ext> extension)
|
||||
{
|
||||
assert(m_present_modes.size() > 0);
|
||||
auto it = std::find_if(m_present_modes.begin(), m_present_modes.end(),
|
||||
[swapchain_present_mode](VkPresentModeKHR p) { return p == swapchain_present_mode; });
|
||||
if (it == m_present_modes.end())
|
||||
{
|
||||
WSI_LOG_ERROR("unable to switch presentation mode");
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
m_present_mode = swapchain_present_mode;
|
||||
return VK_SUCCESS;
|
||||
return m_extensions.add_extension(std::move(extension));
|
||||
}
|
||||
|
||||
void swapchain_base::set_present_id(uint64_t value)
|
||||
{
|
||||
if (value != 0)
|
||||
{
|
||||
assert(value > m_present_id);
|
||||
m_present_id = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
VkResult swapchain_base::presentation_timing_queue_set_size(size_t queue_size)
|
||||
{
|
||||
if (presentation_timing_get_num_outstanding_results() > queue_size)
|
||||
{
|
||||
return VK_NOT_READY;
|
||||
}
|
||||
|
||||
util::vector<swapchain_presentation_entry> presentation_timing(
|
||||
util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE));
|
||||
if (!presentation_timing.try_reserve(queue_size))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
for (auto iter : m_presentation_timing)
|
||||
{
|
||||
if (iter.is_outstanding)
|
||||
{
|
||||
if (!presentation_timing.try_push_back(iter))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_presentation_timing.swap(presentation_timing);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
size_t swapchain_base::presentation_timing_get_num_outstanding_results()
|
||||
{
|
||||
size_t num_outstanding = 0;
|
||||
|
||||
for (const auto &iter : m_presentation_timing)
|
||||
{
|
||||
if (iter.is_outstanding)
|
||||
{
|
||||
num_outstanding++;
|
||||
}
|
||||
}
|
||||
return num_outstanding;
|
||||
}
|
||||
|
||||
VkResult swapchain_base::set_swapchain_time_domain_properties(
|
||||
VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties, uint64_t *pTimeDomainsCounter)
|
||||
{
|
||||
return m_time_domains.set_swapchain_time_domain_properties(pSwapchainTimeDomainProperties, pTimeDomainsCounter);
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -36,16 +36,18 @@
|
|||
#include <thread>
|
||||
#include <array>
|
||||
|
||||
#include <layer/private_data.hpp>
|
||||
#include <util/timed_semaphore.hpp>
|
||||
#include <util/custom_allocator.hpp>
|
||||
#include <util/helpers.hpp>
|
||||
#include <util/ring_buffer.hpp>
|
||||
#include <util/timed_semaphore.hpp>
|
||||
#include <util/log.hpp>
|
||||
#include <layer/private_data.hpp>
|
||||
|
||||
#include "surface_properties.hpp"
|
||||
#include "wsi/synchronization.hpp"
|
||||
#include "wsi/frame_boundary.hpp"
|
||||
#include "util/helpers.hpp"
|
||||
#include "time_domains.hpp"
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
#include "synchronization.hpp"
|
||||
|
||||
#include "extensions/frame_boundary.hpp"
|
||||
#include "extensions/wsi_extension.hpp"
|
||||
#include "util/macros.hpp"
|
||||
|
||||
namespace wsi
|
||||
|
|
@ -115,35 +117,12 @@ struct swapchain_presentation_parameters
|
|||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* Pointer to the present timing info.
|
||||
* The present timing info.
|
||||
*/
|
||||
const VkPresentTimingInfoEXT *present_timing_info{ nullptr };
|
||||
VkPresentTimingInfoEXT m_present_timing_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
struct swapchain_presentation_entry
|
||||
{
|
||||
/**
|
||||
* Whether this entry is an outstanding result or not.
|
||||
*/
|
||||
bool is_outstanding{ false };
|
||||
/**
|
||||
* The present id.
|
||||
*/
|
||||
uint64_t present_id{ 0 };
|
||||
};
|
||||
#endif
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
struct image_compression_control_params
|
||||
{
|
||||
VkImageCompressionFlagsEXT flags;
|
||||
uint32_t compression_control_plane_count;
|
||||
std::array<VkImageCompressionFixedRateFlagsEXT, MAX_PLANES> fixed_rate_flags;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Base swapchain class
|
||||
*
|
||||
|
|
@ -297,28 +276,33 @@ public:
|
|||
*/
|
||||
VkResult is_bind_allowed(uint32_t image_index) const;
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Set the size for the presentation timing queue
|
||||
* @brief Get the swapchain extension's pointer.
|
||||
*
|
||||
* @param queue_size The new queue size to set.
|
||||
* @return Returns the pointer to the swapchain extensions of type T.
|
||||
*/
|
||||
template <typename T>
|
||||
T *get_swapchain_extension(bool required_to_be_present = false)
|
||||
{
|
||||
auto ext = m_extensions.get_extension<T>();
|
||||
if (!ext && required_to_be_present)
|
||||
{
|
||||
WSI_LOG_ERROR("Extension required (%s) but missing.", typeid(T).name());
|
||||
assert(false && "Extension required but missing");
|
||||
}
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a swapchain extension to the list of available swapchain extensions.
|
||||
*
|
||||
* @return VK_SUCCESS on success, VK_ERROR_OUT_OF_HOST_MEMORY when there is not enough memory, VK_NOT_READY otherwise.
|
||||
* .
|
||||
* @param extension unique_ptr to the extension to be added.
|
||||
*
|
||||
* @return Returns true on success and false otherwise.
|
||||
*/
|
||||
|
||||
VkResult presentation_timing_queue_set_size(size_t queue_size);
|
||||
/**
|
||||
* @brief Set swapchain time domain properties.
|
||||
*
|
||||
* @param pSwapchainTimeDomainProperties time domain struct to be set
|
||||
* @param pTimeDomainsCounter size of the pSwapchainTimeDomainProperties
|
||||
*
|
||||
* @return Returns VK_SUCCESS on success, otherwise an appropriate error code.
|
||||
*/
|
||||
VkResult set_swapchain_time_domain_properties(VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties,
|
||||
uint64_t *pTimeDomainsCounter);
|
||||
#endif
|
||||
bool add_swapchain_extension(util::unique_ptr<wsi_ext> extension);
|
||||
|
||||
protected:
|
||||
layer::device_private_data &m_device_data;
|
||||
|
|
@ -426,26 +410,11 @@ protected:
|
|||
*/
|
||||
VkQueue m_queue;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
/**
|
||||
* @brief Describes the image compression the swapchain will use
|
||||
*
|
||||
*/
|
||||
image_compression_control_params m_image_compression_control_params;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Image creation info used for all swapchain images.
|
||||
*/
|
||||
VkImageCreateInfo m_image_create_info;
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Handle the backend specific time domains for each present stage.
|
||||
*/
|
||||
swapchain_time_domains m_time_domains;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return the VkAllocationCallbacks passed in this object constructor.
|
||||
*/
|
||||
|
|
@ -494,6 +463,22 @@ protected:
|
|||
virtual VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread) = 0;
|
||||
|
||||
/**
|
||||
* @brief Adds required extensions to the extension list of the swapchain
|
||||
*
|
||||
* @param device Vulkan device
|
||||
* @param swapchain_create_info Swapchain create info
|
||||
* @return VK_SUCCESS on success, other result codes on failure
|
||||
*/
|
||||
virtual VkResult add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
UNUSED(device);
|
||||
UNUSED(swapchain_create_info);
|
||||
|
||||
/* No extensions required by base class implementation */
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Base swapchain teardown.
|
||||
*
|
||||
|
|
@ -628,13 +613,6 @@ protected:
|
|||
m_error_state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the present ID for the swapchain.
|
||||
*
|
||||
* This feature is provided by the VK_KHR_present_id extension.
|
||||
*/
|
||||
void set_present_id(uint64_t value);
|
||||
|
||||
private:
|
||||
std::mutex m_image_acquire_lock;
|
||||
/**
|
||||
|
|
@ -728,56 +706,9 @@ private:
|
|||
bool m_started_presenting;
|
||||
|
||||
/**
|
||||
* @brief Handle presentation mode switching.
|
||||
*
|
||||
* If VkSwapchainPresentModeInfoEXT is supplied as part of the pNext chain of VkPresentInfoKHR
|
||||
* then this function handles switching the swapchains(s)' presentation mode
|
||||
* to the one(s) requested in VkSwapchainPresentModeInfoEXT structure.
|
||||
*
|
||||
* @param swapchain_present_mode presentation mode to switch to.
|
||||
*
|
||||
* @return VK_SUCCESS on success or an error code otherwise.
|
||||
* @brief Holds the swapchain extensions and related functionalities.
|
||||
*/
|
||||
virtual VkResult handle_switching_presentation_mode(VkPresentModeKHR swapchain_present_mode);
|
||||
|
||||
/**
|
||||
* @brief Handle VkSwapchainPresentModesCreateInfoEXT .
|
||||
*
|
||||
* If VkSwapchainPresentModesCreateInfoEXT is supplied as part of the pNext chain of VkSwapchainCreateInfoKHR
|
||||
* then this function handles setting up the presentation modes for the swapchain.
|
||||
*
|
||||
* @param device VkDevice object.
|
||||
* @param swapchain_create_info Pointer to the swapchain create info struct.
|
||||
*
|
||||
* @return VK_SUCCESS on success or an error code otherwise.
|
||||
*/
|
||||
VkResult handle_swapchain_present_modes_create_info(VkDevice device,
|
||||
const VkSwapchainCreateInfoKHR *swapchain_create_info);
|
||||
|
||||
/**
|
||||
* @brief Current present ID for this swapchain.
|
||||
*/
|
||||
uint64_t m_present_id{ 0 };
|
||||
|
||||
/**
|
||||
* @brief Handler for frame boundary events
|
||||
*
|
||||
*/
|
||||
frame_boundary_handler m_frame_boundary_handler;
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Queue for presentation timings.
|
||||
*/
|
||||
util::vector<swapchain_presentation_entry> m_presentation_timing;
|
||||
|
||||
/**
|
||||
* @brief Get the size of the presentation timing queue
|
||||
*
|
||||
* @return queue size of the presentation timestamp queue.
|
||||
*/
|
||||
size_t presentation_timing_get_num_outstanding_results();
|
||||
#endif
|
||||
wsi_ext_maintainer m_extensions;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file time_domains.hpp
|
||||
*
|
||||
* @brief Contains functions and details for the time domains per backend.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <util/log.hpp>
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
namespace wsi
|
||||
{
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
|
||||
// Predefined struct for calibrated time
|
||||
struct swapchain_calibrated_time
|
||||
{
|
||||
VkTimeDomainKHR time_domain;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
// Base struct for swapchain time domain
|
||||
class swapchain_time_domain
|
||||
{
|
||||
public:
|
||||
swapchain_time_domain(VkPresentStageFlagsEXT presentStages)
|
||||
: m_present_stages(presentStages)
|
||||
{
|
||||
}
|
||||
|
||||
virtual swapchain_calibrated_time calibrate() = 0;
|
||||
|
||||
VkPresentStageFlagsEXT get_present_stages()
|
||||
{
|
||||
return m_present_stages;
|
||||
}
|
||||
|
||||
private:
|
||||
VkPresentStageFlagsEXT m_present_stages;
|
||||
};
|
||||
|
||||
class vulkan_time_domain : public swapchain_time_domain
|
||||
{
|
||||
public:
|
||||
vulkan_time_domain(VkPresentStageFlagsEXT presentStages, VkTimeDomainKHR time_domain)
|
||||
: swapchain_time_domain(presentStages)
|
||||
, m_time_domain(time_domain)
|
||||
{
|
||||
}
|
||||
|
||||
/* The calibrate function should return a Vulkan time domain + an offset.*/
|
||||
swapchain_calibrated_time calibrate() override
|
||||
{
|
||||
return { m_time_domain, 0 };
|
||||
}
|
||||
|
||||
private:
|
||||
VkTimeDomainKHR m_time_domain;
|
||||
};
|
||||
|
||||
/* Class holding multiple time domains for a swapchain*/
|
||||
class swapchain_time_domains
|
||||
{
|
||||
public:
|
||||
swapchain_time_domains(const util::allocator &allocator)
|
||||
: m_time_domains(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
util::vector<util::unique_ptr<swapchain_time_domain>> m_time_domains;
|
||||
|
||||
VkResult calibrate(VkPresentStageFlagBitsEXT presentStages, swapchain_calibrated_time *calibrated_time);
|
||||
|
||||
VkResult set_swapchain_time_domain_properties(VkSwapchainTimeDomainPropertiesEXT *pSwapchainTimeDomainProperties,
|
||||
uint64_t *pTimeDomainsCounter);
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
|
@ -118,12 +118,8 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
|
|||
|
||||
static VkResult surface_format_properties_add_modifier_support(VkPhysicalDevice phys_dev,
|
||||
surface_format_properties &format_props,
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
const drm_format_pair &drm_format,
|
||||
bool add_compression = false)
|
||||
#else
|
||||
const drm_format_pair &drm_format)
|
||||
#endif
|
||||
{
|
||||
VkPhysicalDeviceExternalImageFormatInfoKHR external_info = {};
|
||||
external_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
|
||||
|
|
@ -143,12 +139,10 @@ static VkResult surface_format_properties_add_modifier_support(VkPhysicalDevice
|
|||
image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||
image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (add_compression)
|
||||
{
|
||||
return format_props.add_device_compression_support(phys_dev, image_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
return format_props.check_device_support(phys_dev, image_info);
|
||||
}
|
||||
|
|
@ -195,7 +189,6 @@ static VkResult surface_format_properties_map_init(VkPhysicalDevice phys_dev, su
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
static VkResult surface_format_properties_map_add_compression(VkPhysicalDevice phys_dev,
|
||||
surface_format_properties_map &format_map,
|
||||
const util::vector<drm_format_pair> &drm_format_list)
|
||||
|
|
@ -223,7 +216,6 @@ static VkResult surface_format_properties_map_add_compression(VkPhysicalDevice p
|
|||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount,
|
||||
VkSurfaceFormatKHR *surfaceFormats,
|
||||
|
|
@ -234,13 +226,11 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
{
|
||||
TRY_LOG_CALL(
|
||||
surface_format_properties_map_init(physical_device, supported_formats, specific_surface->get_formats()));
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (layer::instance_private_data::get(physical_device).has_image_compression_support(physical_device))
|
||||
{
|
||||
TRY_LOG_CALL(surface_format_properties_map_add_compression(physical_device, supported_formats,
|
||||
specific_surface->get_formats()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return surface_properties_formats_helper(supported_formats.begin(), supported_formats.end(), surfaceFormatCount,
|
||||
|
|
|
|||
|
|
@ -24,11 +24,7 @@
|
|||
|
||||
#define VK_USE_PLATFORM_WAYLAND_KHR 1
|
||||
|
||||
#include "swapchain.hpp"
|
||||
#include "wl_helpers.hpp"
|
||||
#include "surface_properties.hpp"
|
||||
#include "layer/wsi_layer_experimental.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
|
@ -39,11 +35,17 @@
|
|||
#include <climits>
|
||||
#include <functional>
|
||||
|
||||
#include "swapchain.hpp"
|
||||
#include "util/drm/drm_utils.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/helpers.hpp"
|
||||
#include "util/macros.hpp"
|
||||
#include "util/format_modifiers.hpp"
|
||||
#include "util/helpers.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/macros.hpp"
|
||||
#include "wl_helpers.hpp"
|
||||
|
||||
#include <wsi/extensions/image_compression_control.hpp>
|
||||
#include <wsi/extensions/present_id.hpp>
|
||||
#include <wsi/extensions/swapchain_maintenance.hpp>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
|
@ -78,27 +80,61 @@ swapchain::~swapchain()
|
|||
}
|
||||
}
|
||||
|
||||
VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info)
|
||||
{
|
||||
auto compression_control = wsi_ext_image_compression_control::create(device, swapchain_create_info);
|
||||
if (compression_control)
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_image_compression_control>(*compression_control)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_present_id>()))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.is_swapchain_maintenance1_enabled())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_swapchain_maintenance1>(m_allocator)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_device_data.should_layer_handle_frame_boundary_events())
|
||||
{
|
||||
if (!add_swapchain_extension(m_allocator.make_unique<wsi_ext_frame_boundary>(m_device_data)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
bool swapchain_support_enabled = swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT;
|
||||
if (swapchain_support_enabled)
|
||||
{
|
||||
if (!add_swapchain_extension(wsi_ext_present_timing_wayland::create(m_allocator)))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||
bool &use_presentation_thread)
|
||||
{
|
||||
UNUSED(device);
|
||||
UNUSED(swapchain_create_info);
|
||||
UNUSED(use_presentation_thread);
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 1> time_domains_array = {
|
||||
m_allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
|
||||
VK_TIME_DOMAIN_DEVICE_KHR),
|
||||
};
|
||||
|
||||
for (auto &time_domain : time_domains_array)
|
||||
{
|
||||
if (!m_time_domains.m_time_domains.try_push_back(std::move(time_domain)))
|
||||
{
|
||||
WSI_LOG_ERROR("Failed to add a time domain to m_time_domains.");
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((m_display == nullptr) || (m_surface == nullptr) || (m_wsi_surface->get_dmabuf_interface() == nullptr))
|
||||
{
|
||||
|
|
@ -211,20 +247,19 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info
|
|||
image_info.usage = info.usage;
|
||||
image_info.flags = info.flags;
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
VkImageCompressionControlEXT compression_control = {};
|
||||
compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT;
|
||||
compression_control.flags = m_image_compression_control_params.flags;
|
||||
compression_control.compressionControlPlaneCount =
|
||||
m_image_compression_control_params.compression_control_plane_count;
|
||||
compression_control.pFixedRateFlags = m_image_compression_control_params.fixed_rate_flags.data();
|
||||
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
compression_control.pNext = image_info.pNext;
|
||||
image_info.pNext = &compression_control;
|
||||
auto *ext = get_swapchain_extension<wsi_ext_image_compression_control>();
|
||||
if (ext)
|
||||
{
|
||||
compression_control = ext->get_compression_control_properties();
|
||||
compression_control.pNext = image_info.pNext;
|
||||
image_info.pNext = &compression_control;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
result = m_device_data.instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(
|
||||
m_device_data.physical_device, &image_info, &format_props);
|
||||
}
|
||||
|
|
@ -284,12 +319,21 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayl
|
|||
allocation_flags |= WSIALLOC_ALLOCATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||
if (m_image_compression_control_params.flags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
||||
if (m_device_data.is_swapchain_compression_control_enabled())
|
||||
{
|
||||
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
||||
auto *ext = get_swapchain_extension<wsi_ext_image_compression_control>();
|
||||
/* For Image compression control, additional requirements to be satisfied such as
|
||||
existence of VkImageCompressionControlEXT in swaphain_create_info for
|
||||
the ext to be added to the list. so we check whether we got a valid pointer
|
||||
and proceed if yes. */
|
||||
if (ext)
|
||||
{
|
||||
if (ext->get_bitmask_for_image_compression_flags() & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
|
||||
{
|
||||
allocation_flags |= WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()),
|
||||
image_create_info.extent.width, image_create_info.extent.height,
|
||||
|
|
@ -531,7 +575,11 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
|||
set_error_state(VK_ERROR_SURFACE_LOST_KHR);
|
||||
}
|
||||
|
||||
set_present_id(pending_present.present_id);
|
||||
if (m_device_data.is_present_id_enabled())
|
||||
{
|
||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||
ext->set_present_id(pending_present.present_id);
|
||||
}
|
||||
}
|
||||
|
||||
void swapchain::destroy_image(swapchain_image &image)
|
||||
|
|
|
|||
|
|
@ -36,11 +36,13 @@ extern "C" {
|
|||
#endif
|
||||
#include <wayland-client.h>
|
||||
#include <linux-dmabuf-unstable-v1-client-protocol.h>
|
||||
#include "surface.hpp"
|
||||
#include "util/wsialloc/wsialloc.h"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "wl_object_owner.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "wsi/external_memory.hpp"
|
||||
|
||||
#include <wsi/external_memory.hpp>
|
||||
#include <wsi/extensions/present_timing.hpp>
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
|
@ -188,6 +190,15 @@ private:
|
|||
util::vector<wsialloc_format> &importable_formats, wsialloc_format *allocated_format,
|
||||
bool avoid_allocation);
|
||||
|
||||
/**
|
||||
* @brief Adds required extensions to the extension list of the swapchain
|
||||
*
|
||||
* @param device Vulkan device
|
||||
* @param swapchain_create_info Swapchain create info
|
||||
* @return VK_SUCCESS on success, other result codes on failure
|
||||
*/
|
||||
VkResult add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) override;
|
||||
|
||||
struct wl_display *m_display;
|
||||
struct wl_surface *m_surface;
|
||||
/** Raw pointer to the WSI Surface that this swapchain was created from. The Vulkan specification ensures that the
|
||||
|
|
@ -221,5 +232,35 @@ private:
|
|||
util::vector<uint64_t> &exportable_modifers,
|
||||
util::vector<VkDrmFormatModifierPropertiesEXT> &drm_format_props);
|
||||
};
|
||||
|
||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||
/**
|
||||
* @brief Present timing extension class
|
||||
*
|
||||
* This class implements present timing features declarations that are specific to the wayland backend.
|
||||
*/
|
||||
class wsi_ext_present_timing_wayland : public wsi_ext_present_timing
|
||||
{
|
||||
public:
|
||||
static util::unique_ptr<wsi_ext_present_timing_wayland> create(const util::allocator &allocator)
|
||||
{
|
||||
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 1> time_domains_array = {
|
||||
allocator.make_unique<vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
|
||||
VK_TIME_DOMAIN_DEVICE_KHR)
|
||||
};
|
||||
|
||||
return wsi_ext_present_timing::create<wsi_ext_present_timing_wayland>(allocator, time_domains_array);
|
||||
}
|
||||
|
||||
private:
|
||||
wsi_ext_present_timing_wayland(const util::allocator &allocator)
|
||||
: wsi_ext_present_timing(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
/* Allow util::allocator to access the private constructor */
|
||||
friend util::allocator;
|
||||
};
|
||||
#endif
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue