diff --git a/CMakeLists.txt b/CMakeLists.txt index ebf9ebf..55b5baa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021 Arm Limited. +# Copyright (c) 2019-2022 Arm Limited. # # SPDX-License-Identifier: MIT # @@ -55,17 +55,17 @@ endif() # Build Configuration options option(BUILD_WSI_HEADLESS "Build with support for VK_EXT_headless_surface" ON) option(BUILD_WSI_WAYLAND "Build with support for VK_KHR_wayland_surface" OFF) +option(BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN "Build with support for VK_EXT_image_compression_control_swapchain" OFF) set(SELECT_EXTERNAL_ALLOCATOR "none" CACHE STRING "Select an external system allocator (none, ion)") set(EXTERNAL_WSIALLOC_LIBRARY "" CACHE STRING "External implementation of the wsialloc interface to use") if(BUILD_WSI_WAYLAND) + set(BUILD_DRM_UTILS true) if(SELECT_EXTERNAL_ALLOCATOR STREQUAL "none") message(FATAL_ERROR "Wayland only supported with an external allocator.") endif() - set(BUILD_DRM_UTILS True) endif() -# DRM Utilities if(BUILD_DRM_UTILS) add_library(drm_utils STATIC util/drm/drm_utils.cpp) @@ -192,6 +192,8 @@ add_library(${PROJECT_NAME} SHARED util/custom_allocator.cpp util/extension_list.cpp util/log.cpp + util/format_modifiers.cpp + wsi/surface_properties.cpp wsi/swapchain_base.cpp wsi/synchronization.cpp wsi/wsi_factory.cpp) @@ -200,6 +202,13 @@ 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() + target_link_libraries(${PROJECT_NAME} ${LINK_WSI_LIBS}) add_custom_target(manifest_json ALL COMMAND diff --git a/layer/VkLayer_window_system_integration.json b/layer/VkLayer_window_system_integration.json index 07f3b0d..fa65baa 100644 --- a/layer/VkLayer_window_system_integration.json +++ b/layer/VkLayer_window_system_integration.json @@ -1,6 +1,6 @@ { - "file_format_version" : "1.1.2", - "layer" : { + "file_format_version": "1.1.2", + "layer": { "name": "VK_LAYER_window_system_integration", "type": "GLOBAL", "library_path": "./libVkLayer_window_system_integration.so", @@ -17,9 +17,10 @@ {"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"} ], "device_extensions": [ + {"name": "VK_EXT_image_compression_control_swapchain", "spec_version": "1"}, { - "name" : "VK_KHR_swapchain", - "spec_version" : "70", + "name": "VK_KHR_swapchain", + "spec_version": "70", "entrypoints": [ "vkAcquireNextImageKHR", "vkCreateSwapchainKHR", diff --git a/layer/layer.cpp b/layer/layer.cpp index 6b54fef..b2e00ba 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "private_data.hpp" #include "surface_api.hpp" @@ -36,6 +37,7 @@ #include "wsi/wsi_factory.hpp" #include "util/log.hpp" #include "util/macros.hpp" +#include "util/helpers.hpp" #define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) @@ -176,6 +178,7 @@ VKAPI_ATTR VkResult create_instance(const VkInstanceCreateInfo *pCreateInfo, con .set_instance_enabled_extensions(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount); if (result != VK_SUCCESS) { + instance_private_data::disassociate(*pInstance); if (table.DestroyInstance != nullptr) { table.DestroyInstance(*pInstance, pAllocator); @@ -282,6 +285,7 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic modified_info.ppEnabledExtensionNames, modified_info.enabledExtensionCount); if (result != VK_SUCCESS) { + layer::device_private_data::disassociate(*pDevice); if (table.DestroyDevice != nullptr) { table.DestroyDevice(*pDevice, pAllocator); @@ -289,6 +293,17 @@ 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( + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT, pCreateInfo->pNext); + if (swapchain_compression_feature != nullptr) + { + layer::device_private_data::get(*pDevice).set_swapchain_compression_control_enabled( + swapchain_compression_feature->imageCompressionControlSwapchain); + } +#endif + return VK_SUCCESS; } @@ -373,6 +388,26 @@ VK_LAYER_EXPORT wsi_layer_vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLaye return VK_SUCCESS; } +VWL_VKAPI_CALL(void) +wsi_layer_vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceFeatures2 *pFeatures) VWL_API_POST +{ + auto &instance = layer::instance_private_data::get(physicalDevice); + + instance.disp.GetPhysicalDeviceFeatures2KHR(physicalDevice, pFeatures); + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + auto *image_compression_control_swapchain_features = + util::find_extension( + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT, pFeatures->pNext); + if (image_compression_control_swapchain_features != nullptr) + { + image_compression_control_swapchain_features->imageCompressionControlSwapchain = + instance.has_image_compression_support(physicalDevice); + } +#endif +} + #define GET_PROC_ADDR(func) \ if (!strcmp(funcName, #func)) \ return (PFN_vkVoidFunction)&wsi_layer_##func; @@ -409,7 +444,18 @@ wsi_layer_vkGetInstanceProcAddr(VkInstance instance, const char *funcName) VWL_A GET_PROC_ADDR(vkCreateDevice); GET_PROC_ADDR(vkGetPhysicalDevicePresentRectanglesKHR); + if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures2")) + { + return (PFN_vkVoidFunction)wsi_layer_vkGetPhysicalDeviceFeatures2KHR; + } + auto &instance_data = layer::instance_private_data::get(instance); + + if (instance_data.is_instance_extension_enabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + { + GET_PROC_ADDR(vkGetPhysicalDeviceFeatures2KHR); + } + if (instance_data.is_instance_extension_enabled(VK_KHR_SURFACE_EXTENSION_NAME)) { PFN_vkVoidFunction wsi_func = wsi::get_proc_addr(funcName, instance_data); diff --git a/layer/private_data.cpp b/layer/private_data.cpp index de82ca8..e2befab 100644 --- a/layer/private_data.cpp +++ b/layer/private_data.cpp @@ -22,11 +22,14 @@ * SOFTWARE. */ +#include + #include "private_data.hpp" #include "wsi/wsi_factory.hpp" #include "wsi/surface.hpp" #include "util/unordered_map.hpp" #include "util/log.hpp" +#include "util/helpers.hpp" namespace layer { @@ -40,17 +43,6 @@ static std::mutex g_data_lock; static util::unordered_map g_instance_data{ util::allocator::get_generic() }; static util::unordered_map g_device_data{ util::allocator::get_generic() }; -static const std::array supported_instance_extensions = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, - VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, - VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, -}; - -static const std::array supported_device_extensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -}; - template static PFN_vkVoidFunction get_proc_helper(object_type obj, get_proc_type get_proc, const char* proc_name, bool required, bool &ok) @@ -273,11 +265,24 @@ 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 = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT, nullptr, VK_FALSE + }; + VkPhysicalDeviceFeatures2KHR features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, &compression }; + + disp.GetPhysicalDeviceFeatures2KHR(phys_dev, &features); + + return compression.imageCompressionControl != VK_FALSE; +} +#endif + VkResult instance_private_data::set_instance_enabled_extensions(const char *const *extension_names, size_t extension_count) { - return enabled_extensions.add(extension_names, extension_count, supported_instance_extensions.data(), - supported_instance_extensions.size()); + return enabled_extensions.add(extension_names, extension_count); } bool instance_private_data::is_instance_extension_enabled(const char *extension_name) const @@ -296,6 +301,9 @@ device_private_data::device_private_data(instance_private_data &inst_data, VkPhy , allocator{ alloc } , swapchains{ allocator } , enabled_extensions{ allocator } +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + , compression_control_enabled{ false } +#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */ { } @@ -409,8 +417,7 @@ bool device_private_data::can_icds_create_swapchain(VkSurfaceKHR vk_surface) VkResult device_private_data::set_device_enabled_extensions(const char *const *extension_names, size_t extension_count) { - return enabled_extensions.add(extension_names, extension_count, supported_device_extensions.data(), - supported_device_extensions.size()); + return enabled_extensions.add(extension_names, extension_count); } bool device_private_data::is_device_extension_enabled(const char *extension_name) const @@ -426,4 +433,15 @@ void device_private_data::destroy(device_private_data *device_data) alloc.destroy(1, device_data); } +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN +void device_private_data::set_swapchain_compression_control_enabled(bool enable) +{ + compression_control_enabled = enable; +} + +bool device_private_data::is_swapchain_compression_control_enabled() const +{ + return compression_control_enabled; +} +#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */ } /* namespace layer */ diff --git a/layer/private_data.hpp b/layer/private_data.hpp index f71d9b2..60c548d 100644 --- a/layer/private_data.hpp +++ b/layer/private_data.hpp @@ -74,7 +74,8 @@ namespace layer OPTIONAL(GetPhysicalDeviceImageFormatProperties2KHR) \ OPTIONAL(GetPhysicalDeviceFormatProperties2KHR) \ OPTIONAL(GetPhysicalDevicePresentRectanglesKHR) \ - OPTIONAL(GetPhysicalDeviceExternalFencePropertiesKHR) + OPTIONAL(GetPhysicalDeviceExternalFencePropertiesKHR)\ + OPTIONAL(GetPhysicalDeviceFeatures2KHR) struct instance_dispatch_table { @@ -273,6 +274,16 @@ public: */ bool does_layer_support_surface(VkSurfaceKHR surface); +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + /** + * @brief Check if a physical device supports controlling image compression. + * + * @param phys_dev The physical device to query. + * @return Whether image compression control is supported by the ICD. + */ + bool has_image_compression_support(VkPhysicalDevice phys_dev); +#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */ + /** * @brief Get the instance allocator * @@ -353,6 +364,7 @@ private: * @brief List with the names of the enabled instance extensions. */ util::extension_list enabled_extensions; + }; /** @@ -454,6 +466,22 @@ 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. + * + * @param enable Value to set compression_control_enabled member variable. + */ + void set_swapchain_compression_control_enabled(bool enable); + + /** + * @brief Check whether the device supports controlling the swapchain image compression. + * + * @return true if enabled, false otherwise. + */ + bool is_swapchain_compression_control_enabled() const; +#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */ + private: /* Allow util::allocator to access the private constructor */ friend util::allocator; @@ -488,6 +516,14 @@ private: * @brief List with the names of the enabled device extensions. */ 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 */ }; } /* namespace layer */ diff --git a/util/drm/drm_utils.hpp b/util/drm/drm_utils.hpp index c559a90..e523c00 100644 --- a/util/drm/drm_utils.hpp +++ b/util/drm/drm_utils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021 Arm Limited. + * Copyright (c) 2019, 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * diff --git a/util/format_modifiers.cpp b/util/format_modifiers.cpp new file mode 100644 index 0000000..722a141 --- /dev/null +++ b/util/format_modifiers.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 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. + */ + +#include "format_modifiers.hpp" +#include "layer/private_data.hpp" + +namespace util +{ + +VkResult get_drm_format_properties(VkPhysicalDevice physical_device, VkFormat format, + util::vector &format_props_list) +{ + auto &instance_data = layer::instance_private_data::get(physical_device); + + VkDrmFormatModifierPropertiesListEXT format_modifier_props = {}; + format_modifier_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT; + + VkFormatProperties2KHR format_props = {}; + format_props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR; + format_props.pNext = &format_modifier_props; + + instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(physical_device, format, &format_props); + + if (!format_props_list.try_resize(format_modifier_props.drmFormatModifierCount)) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + format_modifier_props.pDrmFormatModifierProperties = format_props_list.data(); + instance_data.disp.GetPhysicalDeviceFormatProperties2KHR(physical_device, format, &format_props); + return VK_SUCCESS; +} +} /* namespace util */ diff --git a/util/format_modifiers.hpp b/util/format_modifiers.hpp new file mode 100644 index 0000000..bab5467 --- /dev/null +++ b/util/format_modifiers.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 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. + */ + +#pragma once + +#include +#include "custom_allocator.hpp" + +namespace util +{ + +/** + * @brief Get the properties a format has when combined with a DRM modifier. + * + * @param physical_device The physical device + * @param format The target format. + * @param[out] format_props_list A vector which will store the supported properties + * for every modifier. + * + * @return VK_SUCCESS on success. VK_ERROR_OUT_OF_HOST_MEMORY is returned when + * the host gets out of memory. + */ +VkResult get_drm_format_properties(VkPhysicalDevice physical_device, VkFormat format, + util::vector &format_props_list); + +} /* namespace util */ diff --git a/util/helpers.hpp b/util/helpers.hpp index cbdc4e3..c477619 100644 --- a/util/helpers.hpp +++ b/util/helpers.hpp @@ -80,6 +80,17 @@ const T *find_extension(VkStructureType sType, const void *pNext) return reinterpret_cast(entry); } +template +T *find_extension(VkStructureType sType, void *pNext) +{ + auto entry = reinterpret_cast(pNext); + while (entry && entry->sType != sType) + { + entry = entry->pNext; + } + return reinterpret_cast(entry); +} + class noncopyable { protected: diff --git a/util/wsialloc/wsialloc.h b/util/wsialloc/wsialloc.h index e6a463a..2358130 100644 --- a/util/wsialloc/wsialloc.h +++ b/util/wsialloc/wsialloc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 2021 Arm Limited. + * Copyright (c) 2017, 2019, 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -56,9 +56,10 @@ extern "C" { * * Version History: * 1 - Initial wsialloc interface + * 2 - Added WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION */ -#define WSIALLOC_INTERFACE_VERSION 1 +#define WSIALLOC_INTERFACE_VERSION 2 #define WSIALLOC_CONCAT(x, y) x##y #define WSIALLOC_SYMBOL_VERSION(symbol, version) WSIALLOC_CONCAT(symbol, version) @@ -145,6 +146,8 @@ enum wsialloc_allocate_flag WSIALLOC_ALLOCATE_PROTECTED = 0x1, /** Performs allocation calculations and format selection without allocating any memory. */ WSIALLOC_ALLOCATE_NO_MEMORY = 0x2, + /** Sets a preference for selecting the format with the highest fixed compression rate. */ + WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION = 0x4, }; typedef struct wsialloc_format diff --git a/util/wsialloc/wsialloc_ion.c b/util/wsialloc/wsialloc_ion.c index 70fd66c..7a450ab 100644 --- a/util/wsialloc/wsialloc_ion.c +++ b/util/wsialloc/wsialloc_ion.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, 2021 Arm Limited. + * Copyright (c) 2017, 2019, 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -44,7 +44,7 @@ * * This should only be increased when this implementation is updated to match newer versions of wsialloc.h. */ -#define WSIALLOC_IMPLEMENTATION_VERSION 1 +#define WSIALLOC_IMPLEMENTATION_VERSION 2 /* Ensure we are implementing the wsialloc version matching the wsialloc.h header we are using. */ #if WSIALLOC_IMPLEMENTATION_VERSION != WSIALLOC_INTERFACE_VERSION diff --git a/wsi/headless/surface_properties.cpp b/wsi/headless/surface_properties.cpp index 7e482de..d13500e 100644 --- a/wsi/headless/surface_properties.cpp +++ b/wsi/headless/surface_properties.cpp @@ -90,22 +90,31 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_ } static uint32_t fill_supported_formats(VkPhysicalDevice physical_device, - std::array &formats) + std::array &formats) { uint32_t format_count = 0; for (int id = 0; id < max_core_1_0_formats; id++) { - VkImageFormatProperties image_format_props; + formats[format_count] = surface_format_properties{ static_cast(id) }; - VkResult res = - layer::instance_private_data::get(physical_device) - .disp.GetPhysicalDeviceImageFormatProperties(physical_device, static_cast(id), VK_IMAGE_TYPE_2D, - VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, &image_format_props); + VkPhysicalDeviceImageFormatInfo2KHR format_info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR, + nullptr, + static_cast(id), + VK_IMAGE_TYPE_2D, + VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + 0 }; - if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) + VkResult res = formats[format_count].check_device_support(physical_device, format_info); + + if (res == VK_SUCCESS) { - formats[format_count] = static_cast(id); +#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++; } } @@ -118,11 +127,11 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic VkSurfaceFormat2KHR *extended_surface_formats) { /* Construct a list of all formats supported by the driver - for color attachment */ - std::array formats{}; + std::array formats{}; auto format_count = fill_supported_formats(physical_device, formats); - return set_surface_formats(formats.begin(), formats.begin() + format_count, surface_format_count, surface_formats, - extended_surface_formats); + return surface_properties_formats_helper(formats.begin(), formats.begin() + format_count, surface_format_count, + surface_formats, extended_surface_formats); } VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index cb32e30..8fdf4d3 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 Arm Limited. + * Copyright (c) 2017-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -59,9 +59,40 @@ swapchain::~swapchain() teardown(); } +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN +VkImageCompressionControlEXT swapchain::construct_image_compression_control() +{ + VkImageCompressionControlEXT compression_control = {}; + compression_control.sType = VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT; + compression_control.compressionControlPlaneCount = m_image_compression_control.compression_control_plane_count; + compression_control.flags = m_image_compression_control.flags; + compression_control.pFixedRateFlags = m_image_compression_control.fixed_rate_flags.data(); + return compression_control; +} +#endif + VkResult swapchain::create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) { - return m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image); +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + VkImageCompressionControlEXT compression_control; + if (m_device_data.is_swapchain_compression_control_enabled()) + { + compression_control = construct_image_compression_control(); + compression_control.pNext = m_image_create_info.pNext; + m_image_create_info.pNext = &compression_control; + } +#endif + + VkResult res = m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image); + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + if (m_device_data.is_swapchain_compression_control_enabled()) + { + /* Restore pNext pointer of m_image_create_info as compression_control will be garbage after this function exits */ + m_image_create_info.pNext = compression_control.pNext; + } +#endif + return res; } VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create, wsi::swapchain_image &image) @@ -70,7 +101,23 @@ VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_crea const std::lock_guard lock(m_image_status_mutex); m_image_create_info = image_create; - res = m_device_data.disp.CreateImage(m_device, &image_create, get_allocation_callbacks(), &image.image); +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + VkImageCompressionControlEXT compression_control; + if (m_device_data.is_swapchain_compression_control_enabled()) + { + compression_control = construct_image_compression_control(); + compression_control.pNext = m_image_create_info.pNext; + m_image_create_info.pNext = &compression_control; + } +#endif + res = m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), &image.image); +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + if (m_device_data.is_swapchain_compression_control_enabled()) + { + /* Restore pNext pointer of m_image_create_info as compression_control will be garbage after this function exits */ + m_image_create_info.pNext = compression_control.pNext; + } +#endif if (res != VK_SUCCESS) { return res; diff --git a/wsi/headless/swapchain.hpp b/wsi/headless/swapchain.hpp index fb663b9..f851174 100644 --- a/wsi/headless/swapchain.hpp +++ b/wsi/headless/swapchain.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, 2021 Arm Limited. + * Copyright (c) 2017-2019, 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -121,6 +121,11 @@ protected: const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override; private: + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + VkImageCompressionControlEXT construct_image_compression_control(); +#endif + /** * @brief Image creation info used for all swapchain images. */ diff --git a/wsi/surface_properties.cpp b/wsi/surface_properties.cpp new file mode 100644 index 0000000..4b9c929 --- /dev/null +++ b/wsi/surface_properties.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2022 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. + */ + +#include "surface_properties.hpp" +#include "layer/private_data.hpp" + +namespace wsi +{ + +VkResult surface_format_properties::check_device_support(VkPhysicalDevice phys_dev, + VkPhysicalDeviceImageFormatInfo2KHR image_format_info) +{ + VkImageFormatProperties2KHR image_format_props{ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, nullptr }; + + auto &instance_data = layer::instance_private_data::get(phys_dev); + + return instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(phys_dev, &image_format_info, + &image_format_props); +} + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN +VkResult surface_format_properties::add_device_compression_support( + VkPhysicalDevice phys_dev, VkPhysicalDeviceImageFormatInfo2KHR image_format_info) +{ + auto &instance_data = layer::instance_private_data::get(phys_dev); + + VkImageCompressionPropertiesEXT compression_props = { VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, nullptr, 0, + 0 }; + VkImageFormatProperties2KHR image_format_props{ VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, + &compression_props }; + + VkImageCompressionControlEXT compression_control{ VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, + image_format_info.pNext, + VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT }; + image_format_info.pNext = &compression_control; + + VkResult res = + instance_data.disp.GetPhysicalDeviceImageFormatProperties2KHR(phys_dev, &image_format_info, &image_format_props); + if (res == VK_SUCCESS) + { + m_compression.imageCompressionFlags |= compression_props.imageCompressionFlags; + m_compression.imageCompressionFixedRateFlags |= compression_props.imageCompressionFixedRateFlags; + } + else if (res != VK_ERROR_FORMAT_NOT_SUPPORTED) + { + return res; + } + + 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( + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT, surf_format.pNext); + if (compression_properties != nullptr) + { + /** While a format can support multiple compression control flags the returned value is only allowed to be: + * VK_IMAGE_COMPRESSION_DEFAULT_EXT, VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT or + * VK_IMAGE_COMPRESSION_DISABLED_EXT. + * + * Since currently formats that are supported with both default and disabled compression are not distinguished + * from formats that would always be with disabled compression, disabled is not returned. + */ + compression_properties->imageCompressionFlags = VK_IMAGE_COMPRESSION_DEFAULT_EXT; + if (m_compression.imageCompressionFlags & VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT) + { + compression_properties->imageCompressionFlags = VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT; + compression_properties->imageCompressionFixedRateFlags = m_compression.imageCompressionFixedRateFlags; + } + } +#endif +} + +} /* namespace wsi */ \ No newline at end of file diff --git a/wsi/surface_properties.hpp b/wsi/surface_properties.hpp index a028ea7..646c79d 100644 --- a/wsi/surface_properties.hpp +++ b/wsi/surface_properties.hpp @@ -33,6 +33,10 @@ #include #include "util/extension_list.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" namespace wsi { @@ -86,64 +90,115 @@ public: /* There is no maximum theoretically speaking however we choose 3 for practicality */ static constexpr uint32_t MAX_SWAPCHAIN_IMAGE_COUNT = 3; -protected: - /** - * @brief Helper function for the vkGetPhysicalDeviceSurfaceFormatsKHR entrypoint. - * - * Implements the common logic, which is used by all the WSI backends for - * setting the supported formats by the surface. - * - * @param begin Beginning of an iterator with the supported VkFormats. - * @param end End of the iterator. - * @param surface_formats_count Pointer for setting the length of the supported - * formats. - * @param surface_formats The supported formats by the surface. - * @param extended_surface_formats Extended surface formats supported by the surface, it - * is being used when the vkGetPhysicalDeviceSurfaceFormats2KHR - * entrypoint is used. - * - * return VK_SUCCESS on success, an appropriate error code otherwise. - * - */ - template - VkResult set_surface_formats(It begin, It end, uint32_t *surface_formats_count, VkSurfaceFormatKHR *surface_formats, - VkSurfaceFormat2KHR *extended_surface_formats) - { - assert(surface_formats_count != nullptr); - - const uint32_t supported_formats_count = std::distance(begin, end); - if (surface_formats == nullptr && extended_surface_formats == nullptr) - { - *surface_formats_count = supported_formats_count; - return VK_SUCCESS; - } - - VkResult res = VK_SUCCESS; - if (supported_formats_count > *surface_formats_count) - { - res = VK_INCOMPLETE; - } - - *surface_formats_count = std::min(*surface_formats_count, supported_formats_count); - uint32_t format_count = 0; - std::for_each(begin, end, [&](const VkFormat &format) { - if (format_count < *surface_formats_count) - { - if (extended_surface_formats == nullptr) - { - surface_formats[format_count].format = format; - surface_formats[format_count++].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - } - else - { - extended_surface_formats[format_count].surfaceFormat.format = format; - extended_surface_formats[format_count++].surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - } - } - }); - - return res; - } }; +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 + { + } + + surface_format_properties() + : surface_format_properties{ VK_FORMAT_UNDEFINED } + { + } + + 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; + + template + static surface_format_properties& from_iterator(std::pair &iter) + { + return iter.second; + } + static surface_format_properties& from_iterator(surface_format_properties &iter) + { + return iter; + } + + VkSurfaceFormatKHR m_surface_format; + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN +private: + VkImageCompressionPropertiesEXT m_compression; +#endif +}; + +/** + * @brief Helper function for the vkGetPhysicalDeviceSurfaceFormatsKHR entrypoint. + * + * Implements the common logic, which is used by all the WSI backends for + * setting the supported formats by the surface. + * + * @param begin Beginning of an iterator with the supported @ref surface_format_properties + * @param end End of the iterator. + * @param surface_formats_count Pointer for setting the length of the supported + * formats. + * @param surface_formats The supported formats by the surface. + * @param extended_surface_formats Extended surface formats supported by the surface, it + * is being used when the vkGetPhysicalDeviceSurfaceFormats2KHR + * entrypoint is used. + * + * @return VK_SUCCESS on success, an appropriate error code otherwise. + * + */ +template +VkResult surface_properties_formats_helper(It begin, It end, uint32_t *surface_formats_count, + VkSurfaceFormatKHR *surface_formats, + VkSurfaceFormat2KHR *extended_surface_formats) +{ + assert(surface_formats_count != nullptr); + + const uint32_t supported_formats_count = std::distance(begin, end); + if (surface_formats == nullptr && extended_surface_formats == nullptr) + { + *surface_formats_count = supported_formats_count; + return VK_SUCCESS; + } + + VkResult res = VK_SUCCESS; + if (supported_formats_count > *surface_formats_count) + { + res = VK_INCOMPLETE; + } + + *surface_formats_count = std::min(*surface_formats_count, supported_formats_count); + uint32_t format_count = 0; + for (auto it = begin; it != end; ++it) + { + const auto &props = surface_format_properties::from_iterator(*it); + + if (format_count >= *surface_formats_count) + { + break; + } + + if (extended_surface_formats == nullptr) + { + surface_formats[format_count] = props.m_surface_format; + } + else + { + props.fill_format_properties(extended_surface_formats[format_count]); + } + + format_count++; + } + + return res; +} + + } /* namespace wsi */ diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index 7fbbe68..6292d3d 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -41,6 +41,7 @@ #include #include "util/log.hpp" +#include "util/helpers.hpp" #include "swapchain_base.hpp" namespace wsi @@ -184,6 +185,9 @@ 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({VK_IMAGE_COMPRESSION_DEFAULT_EXT, 0}) +#endif , m_image_acquire_lock() , m_error_state(VK_NOT_READY) , m_started_presenting(false) @@ -201,6 +205,20 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s m_present_mode = swapchain_create_info->presentMode; +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + const auto *image_compression_control = util::find_extension( + VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT, swapchain_create_info->pNext); + if (m_device_data.is_swapchain_compression_control_enabled() && image_compression_control != nullptr) + { + m_image_compression_control.compression_control_plane_count = image_compression_control->compressionControlPlaneCount; + m_image_compression_control.flags = image_compression_control->flags; + for (uint32_t i = 0; i < image_compression_control->compressionControlPlaneCount; i++) + { + m_image_compression_control.fixed_rate_flags[i] = image_compression_control->pFixedRateFlags[i]; + } + } +#endif + /* Init image to invalid values. */ if (!m_swapchain_images.try_resize(swapchain_create_info->minImageCount)) { diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index c8d5573..ffed117 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021 Arm Limited. + * Copyright (c) 2017-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,17 @@ struct swapchain_image VkSemaphore present_semaphore{ VK_NULL_HANDLE }; }; +constexpr uint32_t MAX_PLANES = 4; + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN +struct image_compression_control +{ + VkImageCompressionFlagsEXT flags; + uint32_t compression_control_plane_count; + std::array fixed_rate_flags; +}; +#endif + /** * @brief Base swapchain class * @@ -287,6 +299,14 @@ protected: */ VkQueue m_queue; +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + /** + * @brief Describes the image compression the swapchain will use + * + */ + image_compression_control m_image_compression_control; +#endif + /** * @brief Return the VkAllocationCallbacks passed in this object constructor. */ diff --git a/wsi/wayland/surface_properties.cpp b/wsi/wayland/surface_properties.cpp index ef947b1..cd54ddd 100644 --- a/wsi/wayland/surface_properties.cpp +++ b/wsi/wayland/surface_properties.cpp @@ -40,6 +40,7 @@ #include "util/drm/drm_utils.hpp" #include "util/log.hpp" #include "util/macros.hpp" +#include "util/helpers.hpp" #define NELEMS(x) (sizeof(x) / sizeof(x[0])) @@ -100,32 +101,114 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_ return VK_SUCCESS; } -static VkResult get_vk_supported_formats(const util::vector &drm_supported_formats, - vk_format_set &vk_supported_formats) +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 { - for (const auto &drm_format : drm_supported_formats) + VkPhysicalDeviceExternalImageFormatInfoKHR external_info = {}; + external_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR; + external_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + + VkPhysicalDeviceImageDrmFormatModifierInfoEXT drm_mod_info = {}; + drm_mod_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT; + drm_mod_info.pNext = &external_info; + drm_mod_info.drmFormatModifier = drm_format.modifier; + drm_mod_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkPhysicalDeviceImageFormatInfo2KHR image_info = {}; + image_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR; + image_info.pNext = &drm_mod_info; + image_info.format = format_props.m_surface_format.format; + image_info.type = VK_IMAGE_TYPE_2D; + 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); +} + +static VkResult surface_format_properties_map_add(VkPhysicalDevice phys_dev, surface_format_properties_map &format_map, + VkFormat format, const drm_format_pair &drm_format) +{ + surface_format_properties format_props{ format }; + VkResult res = surface_format_properties_add_modifier_support(phys_dev, format_props, drm_format); + if (res == VK_SUCCESS) + { + auto it = format_map.try_insert(std::make_pair(format, format_props)); + if (!it.has_value()) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } + + if (res == VK_ERROR_FORMAT_NOT_SUPPORTED) + { + return VK_SUCCESS; + } + + return res; +} + +static VkResult surface_format_properties_map_init(VkPhysicalDevice phys_dev, surface_format_properties_map &format_map, + const util::vector &drm_format_list) +{ + for (const auto &drm_format : drm_format_list) + { + const VkFormat vk_format = util::drm::drm_to_vk_format(drm_format.fourcc); + if (vk_format != VK_FORMAT_UNDEFINED && format_map.find(vk_format) == format_map.end()) + { + TRY(surface_format_properties_map_add(phys_dev, format_map, vk_format, drm_format)); + } + const VkFormat srgb_vk_format = util::drm::drm_to_vk_srgb_format(drm_format.fourcc); + if (srgb_vk_format != VK_FORMAT_UNDEFINED && format_map.find(srgb_vk_format) == format_map.end()) + { + TRY(surface_format_properties_map_add(phys_dev, format_map, srgb_vk_format, drm_format)); + } + } + + 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_list) +{ + for (const auto &drm_format : drm_format_list) { const VkFormat vk_format = util::drm::drm_to_vk_format(drm_format.fourcc); if (vk_format != VK_FORMAT_UNDEFINED) { - auto it = vk_supported_formats.try_insert(vk_format); - if (!it.has_value()) + auto entry = format_map.find(vk_format); + if (entry != format_map.end()) { - return VK_ERROR_OUT_OF_HOST_MEMORY; + TRY(surface_format_properties_add_modifier_support(phys_dev, entry->second, drm_format, true)); } } const VkFormat srgb_vk_format = util::drm::drm_to_vk_srgb_format(drm_format.fourcc); if (srgb_vk_format != VK_FORMAT_UNDEFINED) { - auto it = vk_supported_formats.try_insert(srgb_vk_format); - if (!it.has_value()) + auto entry = format_map.find(srgb_vk_format); + if (entry != format_map.end()) { - return VK_ERROR_OUT_OF_HOST_MEMORY; + TRY(surface_format_properties_add_modifier_support(phys_dev, entry->second, drm_format, true)); } } } return VK_SUCCESS; } +#endif VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount, VkSurfaceFormatKHR *surfaceFormats, @@ -134,15 +217,18 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic assert(specific_surface); if (!supported_formats.size()) { - VkResult res = get_vk_supported_formats(specific_surface->get_formats(), supported_formats); - if (res != VK_SUCCESS) + TRY(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)) { - return res; + TRY(surface_format_properties_map_add_compression(physical_device, supported_formats, + specific_surface->get_formats())); } +#endif } - return set_surface_formats(supported_formats.begin(), supported_formats.end(), surfaceFormatCount, surfaceFormats, - extended_surface_formats); + return surface_properties_formats_helper(supported_formats.begin(), supported_formats.end(), surfaceFormatCount, + surfaceFormats, extended_surface_formats); } VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, diff --git a/wsi/wayland/surface_properties.hpp b/wsi/wayland/surface_properties.hpp index a43ef94..594e430 100644 --- a/wsi/wayland/surface_properties.hpp +++ b/wsi/wayland/surface_properties.hpp @@ -32,15 +32,15 @@ namespace wsi namespace wayland { -struct vk_format_hasher +struct surface_format_properties_hasher { - size_t operator()(const VkFormat format) const + size_t operator()(const VkFormat &format) const { return std::hash()(static_cast(format)); } }; -using vk_format_set = util::unordered_set; +using surface_format_properties_map = util::unordered_map; class surface; @@ -73,7 +73,7 @@ private: */ surface *specific_surface; /** Set of supported Vulkan formats by the @ref specific_surface. */ - vk_format_set supported_formats; + surface_format_properties_map supported_formats; }; } // namespace wayland diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 8cb5c9c..4046df5 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -42,8 +42,7 @@ #include "util/log.hpp" #include "util/helpers.hpp" #include "util/macros.hpp" - -#define MAX_PLANES 4 +#include "util/format_modifiers.hpp" namespace wsi { @@ -222,31 +221,6 @@ VkResult swapchain::get_fd_mem_type_index(int fd, uint32_t &mem_idx) return VK_SUCCESS; } -VkResult swapchain::get_drm_format_properties( - VkFormat format, util::vector &format_props_list) -{ - VkDrmFormatModifierPropertiesListEXT format_modifier_props = {}; - format_modifier_props.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT; - - VkFormatProperties2KHR format_props = {}; - format_props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR; - format_props.pNext = &format_modifier_props; - - m_device_data.instance_data.disp.GetPhysicalDeviceFormatProperties2KHR( - m_device_data.physical_device, format, &format_props); - - if (!format_props_list.try_resize(format_modifier_props.drmFormatModifierCount)) - { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - - format_modifier_props.pDrmFormatModifierProperties = format_props_list.data(); - m_device_data.instance_data.disp.GetPhysicalDeviceFormatProperties2KHR( - m_device_data.physical_device, format, &format_props); - - return VK_SUCCESS; -} - static uint32_t get_same_fd_index(int fd, int const *fds) { uint32_t index = 0; @@ -265,7 +239,7 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info /* Query supported modifers. */ util::vector drm_format_props( util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - VkResult result = get_drm_format_properties(info.format, drm_format_props); + VkResult result = util::get_drm_format_properties(m_device_data.physical_device, info.format, drm_format_props); if (result != VK_SUCCESS) { WSI_LOG_ERROR("Failed to get format properties."); @@ -275,6 +249,7 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info { bool is_supported = false; drm_format_pair drm_format{ util::drm::vk_to_drm_format(info.format), prop.drmFormatModifier }; + for (const auto &format : m_wsi_surface->get_formats()) { if (format.fourcc == drm_format.fourcc && format.modifier == drm_format.modifier) @@ -316,6 +291,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.flags; + compression_control.compressionControlPlaneCount = m_image_compression_control.compression_control_plane_count; + compression_control.pFixedRateFlags = m_image_compression_control.fixed_rate_flags.data(); + + if (m_device_data.is_swapchain_compression_control_enabled()) + { + 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); } @@ -375,10 +363,19 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayl wsialloc_format *allocated_format) { bool is_protected_memory = (image_create_info.flags & VK_IMAGE_CREATE_PROTECTED_BIT) != 0; - const uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0; + uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0; + +#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN + if (m_image_compression_control.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(importable_formats.size()), - image_create_info.extent.width, image_create_info.extent.height, - allocation_flags }; + image_create_info.extent.width, image_create_info.extent.height, + allocation_flags }; + const auto res = wsialloc_alloc(m_wsi_allocator, &alloc_info, allocated_format, image_data.stride, image_data.buffer_fd, image_data.offset); if (res != WSIALLOC_ERROR_NONE) diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index e33ceec..381e9c4 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, 2021 Arm Limited. + * Copyright (c) 2017-2019, 2021-2022 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -215,19 +215,6 @@ private: */ VkResult get_fd_mem_type_index(int fd, uint32_t &mem_idx); - /* - * @brief Get the properties a format has when combined with a DRM modifier. - * - * @param format The target format. - * @param[out] format_props_list A vector which will store the supported properties - * for every modifier. - * - * @return VK_SUCCESS on success. VK_ERROR_OUT_OF_HOST_MEMORY is returned when - * the host gets out of memory. - */ - VkResult get_drm_format_properties( - VkFormat format, util::vector &format_props_list); - /** * @brief Finds what formats are compatible with the requested swapchain image Vulkan Device and Wayland surface. * @@ -240,6 +227,7 @@ private: VkResult get_surface_compatible_formats(const VkImageCreateInfo &info, util::vector &importable_formats, util::vector &exportable_modifers); + }; } // namespace wayland } // namespace wsi diff --git a/wsi/wsi_factory.cpp b/wsi/wsi_factory.cpp index d62b1ca..0cb2fe5 100644 --- a/wsi/wsi_factory.cpp +++ b/wsi/wsi_factory.cpp @@ -170,7 +170,6 @@ VkResult add_extensions_required_by_layer(VkPhysicalDevice phys_dev, const util: } } - layer::instance_private_data &inst_data = layer::instance_private_data::get(phys_dev); for (const auto &wsi_ext : supported_wsi_extensions) { /* Skip iterating over platforms not enabled in the instance. */