Add support for VK_EXT_image_compression_control_swapchain

Implement support for VK_EXT_image_compression_control_swapchain
for both the Wayland and the headless windowing systems.
The extension can be conditionally enabled through the new build option
BUILD_WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN. Compiling with this
option enabled requires recent Vulkan headers (1.3.213)
Note also that support in the layer is enabled conditionally to
the ICD supporting VK_EXT_image_compression_control.

Update the WSIALLOC interface to version 2 and add support to
prefer selection of a format with the highest fixed rate compression
from the formats provided. This is used to pick a fixed rate
compression when VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT is
specified during swapchain creation.

Signed-off-by: Dennis Tsiang <dennis.tsiang@arm.com>
Signed-off-by: Rosen Zhelev <rosen.zhelev@arm.com>
Signed-off-by: Normunds Rieksts <normunds.rieksts@arm.com>
Signed-off-by: Matteo Franchin <matteo.franchin@arm.com>
Change-Id: Ie37e6901042a65f2a408e428a705b5a24227b262
This commit is contained in:
Dennis Tsiang 2022-03-18 12:05:46 +00:00 committed by Matteo Franchin
parent 2aa963ba92
commit 2bc2109194
23 changed files with 715 additions and 167 deletions

View file

@ -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

View file

@ -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",

View file

@ -27,6 +27,7 @@
#include <cstring>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan.h>
#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<VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT>(
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<VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT>(
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);

View file

@ -22,11 +22,14 @@
* SOFTWARE.
*/
#include <vulkan/vulkan.h>
#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<void *, instance_private_data *> g_instance_data{ util::allocator::get_generic() };
static util::unordered_map<void *, device_private_data *> g_device_data{ util::allocator::get_generic() };
static const std::array<const char *, 4> 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<const char *, 1> supported_device_extensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
template <typename object_type, typename get_proc_type>
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<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;
}
bool device_private_data::is_swapchain_compression_control_enabled() const
{
return compression_control_enabled;
}
#endif /* WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN */
} /* namespace layer */

View file

@ -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 */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021 Arm Limited.
* Copyright (c) 2019, 2021-2022 Arm Limited.
*
* SPDX-License-Identifier: MIT
*

54
util/format_modifiers.cpp Normal file
View file

@ -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<VkDrmFormatModifierPropertiesEXT> &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 */

47
util/format_modifiers.hpp Normal file
View file

@ -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 <vulkan/vulkan.h>
#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<VkDrmFormatModifierPropertiesEXT> &format_props_list);
} /* namespace util */

View file

@ -80,6 +80,17 @@ const T *find_extension(VkStructureType sType, const void *pNext)
return reinterpret_cast<const T *>(entry);
}
template <typename T>
T *find_extension(VkStructureType sType, void *pNext)
{
auto entry = reinterpret_cast<VkBaseOutStructure *>(pNext);
while (entry && entry->sType != sType)
{
entry = entry->pNext;
}
return reinterpret_cast<T *>(entry);
}
class noncopyable
{
protected:

View file

@ -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

View file

@ -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

View file

@ -90,22 +90,31 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
}
static uint32_t fill_supported_formats(VkPhysicalDevice physical_device,
std::array<VkFormat, max_core_1_0_formats> &formats)
std::array<surface_format_properties, max_core_1_0_formats> &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<VkFormat>(id) };
VkResult res =
layer::instance_private_data::get(physical_device)
.disp.GetPhysicalDeviceImageFormatProperties(physical_device, static_cast<VkFormat>(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<VkFormat>(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<VkFormat>(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<VkFormat, max_core_1_0_formats> formats{};
std::array<surface_format_properties, max_core_1_0_formats> 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,

View file

@ -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<std::recursive_mutex> 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;

View file

@ -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.
*/

View file

@ -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<VkImageCompressionPropertiesEXT>(
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 */

View file

@ -33,6 +33,10 @@
#include <vulkan/vulkan.h>
#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 <typename It>
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 <typename K>
static surface_format_properties& from_iterator(std::pair<const K, surface_format_properties> &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 <typename It>
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 */

View file

@ -41,6 +41,7 @@
#include <vulkan/vulkan.h>
#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<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)
{
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))
{

View file

@ -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 <semaphore.h>
#include <vulkan/vulkan.h>
#include <thread>
#include <array>
#include <layer/private_data.hpp>
#include <util/timed_semaphore.hpp>
@ -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<VkImageCompressionFixedRateFlagsEXT, MAX_PLANES> 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.
*/

View file

@ -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_format_pair> &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_pair> &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_pair> &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,

View file

@ -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<uint64_t>()(static_cast<uint64_t>(format));
}
};
using vk_format_set = util::unordered_set<VkFormat, vk_format_hasher>;
using surface_format_properties_map = util::unordered_map<VkFormat, surface_format_properties, surface_format_properties_hasher>;
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

View file

@ -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<VkDrmFormatModifierPropertiesEXT> &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<VkDrmFormatModifierPropertiesEXT> 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<unsigned>(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)

View file

@ -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<VkDrmFormatModifierPropertiesEXT> &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<wsialloc_format> &importable_formats,
util::vector<uint64_t> &exportable_modifers);
};
} // namespace wayland
} // namespace wsi

View file

@ -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. */