mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-06-09 11:28:21 +02:00
Implement objects associated with VkSurface
Defines an abstract wsi::surface object to be implemented by each WSI backend. This object is then associated with the corresponding VkSurface object in the instance specific data. To keep track of these objects the layer now intercepts vkDestroySurfaceKHR, while specific surface creation entrypoints are intercepted by individual WSI backends. In addition this change should allow for fixing incompatibility issues with layers that wrap VkSurface which breaks casting to the Loader's ICD VkSurface type. Make greater use of util::unique_ptr and allow for such pointers to be constructable when casting derived types. Change-Id: I163e9c47088ad9989583ebce1319b1fc05559d73 Signed-off-by: Rosen Zhelev <rosen.zhelev@arm.com>
This commit is contained in:
parent
feb2445f2a
commit
c7be05e3ff
19 changed files with 500 additions and 59 deletions
|
|
@ -96,6 +96,7 @@ endif()
|
|||
if(BUILD_WSI_WAYLAND)
|
||||
add_library(wayland_wsi STATIC
|
||||
wsi/wayland/surface_properties.cpp
|
||||
wsi/wayland/surface.cpp
|
||||
wsi/wayland/wl_helpers.cpp
|
||||
wsi/wayland/swapchain.cpp)
|
||||
|
||||
|
|
@ -153,6 +154,7 @@ add_library(${PROJECT_NAME} SHARED
|
|||
wsi/swapchain_base.cpp
|
||||
wsi/wsi_factory.cpp
|
||||
wsi/headless/surface_properties.cpp
|
||||
wsi/headless/surface.cpp
|
||||
wsi/headless/swapchain.cpp)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE ${WSI_DEFINES})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
|
|
|
|||
|
|
@ -461,6 +461,7 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wsi_layer_vkGetInstance
|
|||
GET_PROC_ADDR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
|
||||
GET_PROC_ADDR(vkGetPhysicalDeviceSurfaceFormatsKHR);
|
||||
GET_PROC_ADDR(vkGetPhysicalDeviceSurfacePresentModesKHR);
|
||||
GET_PROC_ADDR(vkDestroySurfaceKHR);
|
||||
GET_PROC_ADDR(vkEnumerateDeviceExtensionProperties);
|
||||
GET_PROC_ADDR(vkEnumerateInstanceLayerProperties);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "private_data.hpp"
|
||||
#include "wsi/wsi_factory.hpp"
|
||||
#include "wsi/surface.hpp"
|
||||
#include "util/unordered_map.hpp"
|
||||
#include "util/log.hpp"
|
||||
|
||||
|
|
@ -81,6 +82,7 @@ instance_private_data::instance_private_data(const instance_dispatch_table &tabl
|
|||
, SetInstanceLoaderData(set_loader_data)
|
||||
, enabled_layer_platforms(enabled_layer_platforms)
|
||||
, allocator(alloc)
|
||||
, surfaces(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -172,15 +174,60 @@ instance_private_data &instance_private_data::get(VkPhysicalDevice phys_dev)
|
|||
return get_instance_private_data(phys_dev);
|
||||
}
|
||||
|
||||
static VkIcdWsiPlatform get_platform_of_surface(VkSurfaceKHR surface)
|
||||
VkResult instance_private_data::add_surface(VkSurfaceKHR vk_surface, util::unique_ptr<wsi::surface> &wsi_surface)
|
||||
{
|
||||
VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
|
||||
return surface_base->platform;
|
||||
scoped_mutex lock(surfaces_lock);
|
||||
|
||||
auto it = surfaces.find(vk_surface);
|
||||
if (it != surfaces.end())
|
||||
{
|
||||
WSI_LOG_WARNING("Hash collision when adding new surface (%p). Old surface is replaced.",
|
||||
reinterpret_cast<void *>(vk_surface));
|
||||
surfaces.erase(it);
|
||||
}
|
||||
|
||||
auto result = surfaces.try_insert(std::make_pair(vk_surface, nullptr));
|
||||
if (result.has_value())
|
||||
{
|
||||
assert(result->second);
|
||||
result->first->second = wsi_surface.release();
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
wsi::surface *instance_private_data::get_surface(VkSurfaceKHR vk_surface)
|
||||
{
|
||||
scoped_mutex lock(surfaces_lock);
|
||||
auto it = surfaces.find(vk_surface);
|
||||
if (it != surfaces.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void instance_private_data::remove_surface(VkSurfaceKHR vk_surface, const util::allocator &alloc)
|
||||
{
|
||||
scoped_mutex lock(surfaces_lock);
|
||||
auto it = surfaces.find(vk_surface);
|
||||
if (it != surfaces.end())
|
||||
{
|
||||
alloc.destroy<wsi::surface>(1, it->second);
|
||||
surfaces.erase(it);
|
||||
}
|
||||
/* Failing to find a surface is not an error. It could have been created by a WSI extension, which is not handled
|
||||
* by this layer.
|
||||
*/
|
||||
}
|
||||
|
||||
bool instance_private_data::does_layer_support_surface(VkSurfaceKHR surface)
|
||||
{
|
||||
return enabled_layer_platforms.contains(get_platform_of_surface(surface));
|
||||
scoped_mutex lock(surfaces_lock);
|
||||
auto it = surfaces.find(surface);
|
||||
return it != surfaces.end();
|
||||
}
|
||||
|
||||
void instance_private_data::destroy(instance_private_data *instance_data)
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@
|
|||
#include "util/platform_set.hpp"
|
||||
#include "util/custom_allocator.hpp"
|
||||
#include "util/unordered_set.hpp"
|
||||
#include "util/unordered_map.hpp"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vk_layer.h>
|
||||
#include <vulkan/vk_icd.h>
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
|
@ -39,6 +41,12 @@
|
|||
|
||||
using scoped_mutex = std::lock_guard<std::mutex>;
|
||||
|
||||
/** Forward declare stored objects */
|
||||
namespace wsi
|
||||
{
|
||||
class surface;
|
||||
}
|
||||
|
||||
namespace layer
|
||||
{
|
||||
|
||||
|
|
@ -57,6 +65,9 @@ namespace layer
|
|||
OPTIONAL(GetPhysicalDeviceSurfaceFormatsKHR) \
|
||||
OPTIONAL(GetPhysicalDeviceSurfacePresentModesKHR) \
|
||||
OPTIONAL(GetPhysicalDeviceSurfaceSupportKHR) \
|
||||
OPTIONAL(CreateHeadlessSurfaceEXT) \
|
||||
OPTIONAL(CreateWaylandSurfaceKHR) \
|
||||
OPTIONAL(DestroySurfaceKHR) \
|
||||
OPTIONAL(GetPhysicalDeviceImageFormatProperties2KHR) \
|
||||
OPTIONAL(GetPhysicalDeviceFormatProperties2KHR) \
|
||||
OPTIONAL(GetPhysicalDevicePresentRectanglesKHR)
|
||||
|
|
@ -190,6 +201,39 @@ public:
|
|||
*/
|
||||
static instance_private_data &get(VkPhysicalDevice phys_dev);
|
||||
|
||||
/**
|
||||
* @brief Associate a VkSurface with a WSI surface object.
|
||||
*
|
||||
* @param vk_surface The VkSurface object created by the Vulkan implementation.
|
||||
* @param wsi_surface The WSI layer object representing the surface.
|
||||
*
|
||||
* @return VK_SUCCESS or VK_ERROR_OUT_OF_HOST_MEMORY
|
||||
*
|
||||
* @note On success this transfers ownership of the WSI surface. The WSI surface is then explicitly destroyed by the
|
||||
* user with @ref remove_surface
|
||||
*/
|
||||
VkResult add_surface(VkSurfaceKHR vk_surface, util::unique_ptr<wsi::surface> &wsi_surface);
|
||||
|
||||
/**
|
||||
* @brief Returns any associated WSI surface to the VkSurface.
|
||||
*
|
||||
* @param vk_surface The VkSurface object queried for association.
|
||||
*
|
||||
* @return nullptr or a raw pointer to the WSI surface.
|
||||
*
|
||||
* @note This returns a raw pointer that does not change any ownership. The user is responsible for ensuring that the
|
||||
* pointer is valid as it explicitly controls the lifetime of the object.
|
||||
*/
|
||||
wsi::surface *get_surface(VkSurfaceKHR vk_surface);
|
||||
|
||||
/**
|
||||
* @brief Destroys any VkSurface associated WSI surface.
|
||||
*
|
||||
* @param vk_surface The VkSurface to check for associations.
|
||||
* @param alloc The allocator to use if destroying a @ref wsi::surface object.
|
||||
*/
|
||||
void remove_surface(VkSurfaceKHR vk_surface, const util::allocator &alloc);
|
||||
|
||||
/**
|
||||
* @brief Get the set of enabled platforms that are also supported by the layer.
|
||||
*/
|
||||
|
|
@ -263,6 +307,19 @@ private:
|
|||
const PFN_vkSetInstanceLoaderData SetInstanceLoaderData;
|
||||
const util::wsi_platform_set enabled_layer_platforms;
|
||||
const util::allocator allocator;
|
||||
|
||||
/**
|
||||
* @brief Container for all VkSurface objects tracked and supported by the Layer's WSI implementation.
|
||||
*
|
||||
* Uses plain pointers to store surface data as the lifetime of the object is explicitly controlled by the Vulkan
|
||||
* application. The application may also use different but compatible host allocators on creation and destruction.
|
||||
*/
|
||||
util::unordered_map<VkSurfaceKHR, wsi::surface *> surfaces;
|
||||
|
||||
/**
|
||||
* @brief Lock for thread safe access to @ref surfaces
|
||||
*/
|
||||
std::mutex surfaces_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysic
|
|||
auto &instance = layer::instance_private_data::get(physicalDevice);
|
||||
if (instance.should_layer_handle_surface(physicalDevice, surface))
|
||||
{
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(surface);
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
return props->get_surface_capabilities(physicalDevice, surface, pSurfaceCapabilities);
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDev
|
|||
auto &instance = layer::instance_private_data::get(physicalDevice);
|
||||
if (instance.should_layer_handle_surface(physicalDevice, surface))
|
||||
{
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(surface);
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
return props->get_surface_formats(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysic
|
|||
auto &instance = layer::instance_private_data::get(physicalDevice);
|
||||
if (instance.should_layer_handle_surface(physicalDevice, surface))
|
||||
{
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(surface);
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props != nullptr);
|
||||
return props->get_surface_present_modes(physicalDevice, surface, pPresentModeCount, pPresentModes);
|
||||
}
|
||||
|
|
@ -107,4 +107,15 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDev
|
|||
return instance.disp.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
auto &instance_data = layer::instance_private_data::get(instance);
|
||||
|
||||
instance_data.disp.DestroySurfaceKHR(instance, surface, pAllocator);
|
||||
|
||||
instance_data.remove_surface(
|
||||
surface, util::allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator });
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -61,4 +61,10 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysic
|
|||
VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
|
||||
uint32_t queueFamilyIndex, VkSurfaceKHR surface,
|
||||
VkBool32 *pSupported);
|
||||
|
||||
/**
|
||||
* @brief Implements vkDestroySurfaceKHR Vulkan entrypoint.
|
||||
*/
|
||||
VKAPI_ATTR void wsi_layer_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
|
||||
const VkAllocationCallbacks *pAllocator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device,
|
|||
return device_data.disp.CreateSwapchainKHR(device_data.device, pSwapchainCreateInfo, pAllocator, pSwapchain);
|
||||
}
|
||||
|
||||
wsi::swapchain_base *sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
|
||||
auto sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
|
||||
if (sc == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
|
@ -65,20 +65,16 @@ VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device,
|
|||
VkResult result = sc->init(device, pSwapchainCreateInfo);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
/* Error occured during initialization, need to free allocated memory. */
|
||||
wsi::destroy_surface_swapchain(sc, device_data, pAllocator);
|
||||
return result;
|
||||
}
|
||||
|
||||
auto vulkan_swapchain = reinterpret_cast<VkSwapchainKHR>(sc);
|
||||
result = device_data.add_layer_swapchain(vulkan_swapchain);
|
||||
result = device_data.add_layer_swapchain(reinterpret_cast<VkSwapchainKHR>(sc.get()));
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
wsi::destroy_surface_swapchain(sc, device_data, pAllocator);
|
||||
return result;
|
||||
}
|
||||
|
||||
*pSwapchain = vulkan_swapchain;
|
||||
*pSwapchain = reinterpret_cast<VkSwapchainKHR>(sc.release());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +210,7 @@ VKAPI_ATTR VkResult wsi_layer_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysical
|
|||
}
|
||||
|
||||
VkResult result;
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(surface);
|
||||
wsi::surface_properties *props = wsi::get_surface_properties(instance, surface);
|
||||
assert(props);
|
||||
|
||||
if (nullptr == pRects)
|
||||
|
|
|
|||
|
|
@ -246,20 +246,21 @@ void allocator::destroy(size_t num_objects, T *objects) const noexcept
|
|||
* destroy method.
|
||||
*/
|
||||
template <typename T>
|
||||
class deleter
|
||||
class deleter : public allocator
|
||||
{
|
||||
public:
|
||||
deleter(allocator allocator)
|
||||
: m_allocator(std::move(allocator))
|
||||
deleter()
|
||||
: deleter(allocator::get_generic())
|
||||
{}
|
||||
|
||||
deleter(allocator alloc)
|
||||
: allocator(std::move(alloc))
|
||||
{}
|
||||
|
||||
void operator()(T *object)
|
||||
{
|
||||
m_allocator.destroy<T>(1, object);
|
||||
destroy<T>(1, object);
|
||||
}
|
||||
|
||||
private:
|
||||
allocator m_allocator;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
51
wsi/headless/surface.cpp
Normal file
51
wsi/headless/surface.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Implementation of a headless WSI Surface
|
||||
*/
|
||||
|
||||
#include "surface.hpp"
|
||||
#include "swapchain.hpp"
|
||||
#include "surface_properties.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace headless
|
||||
{
|
||||
|
||||
wsi::surface_properties &surface::get_properties()
|
||||
{
|
||||
return surface_properties::get_instance();
|
||||
}
|
||||
|
||||
util::unique_ptr<swapchain_base> surface::allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator)
|
||||
{
|
||||
util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator };
|
||||
return util::unique_ptr<swapchain_base>(alloc.make_unique<swapchain>(dev_data, allocator));
|
||||
}
|
||||
|
||||
} /* namespace headless */
|
||||
} /* namespace wsi */
|
||||
48
wsi/headless/surface.hpp
Normal file
48
wsi/headless/surface.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Definitions for a headless WSI Surface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wsi/surface.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace headless
|
||||
{
|
||||
|
||||
class surface : public wsi::surface
|
||||
{
|
||||
public:
|
||||
surface() = default;
|
||||
wsi::surface_properties &get_properties() override;
|
||||
util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator) override;
|
||||
};
|
||||
|
||||
} /* namespace headless */
|
||||
} /* namespace wsi */
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
#include <layer/private_data.hpp>
|
||||
|
||||
#include "surface_properties.hpp"
|
||||
#include "surface.hpp"
|
||||
|
||||
#define UNUSED(x) ((void)(x))
|
||||
|
||||
|
|
@ -168,5 +170,38 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
|
|||
return res;
|
||||
}
|
||||
|
||||
extern "C" VKAPI_ATTR VkResult VKAPI_CALL CreateHeadlessSurfaceEXT(VkInstance instance,
|
||||
const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator,
|
||||
VkSurfaceKHR *pSurface)
|
||||
{
|
||||
auto &instance_data = layer::instance_private_data::get(instance);
|
||||
util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator };
|
||||
auto wsi_surface = util::unique_ptr<wsi::surface>(allocator.make_unique<surface>());
|
||||
if (wsi_surface == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
VkResult res = instance_data.disp.CreateHeadlessSurfaceEXT(instance, pCreateInfo, pAllocator, pSurface);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
res = instance_data.add_surface(*pSurface, wsi_surface);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
|
||||
{
|
||||
if (strcmp(name, "vkCreateHeadlessSurfaceEXT") == 0)
|
||||
{
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(CreateHeadlessSurfaceEXT);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} /* namespace headless */
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ public:
|
|||
VkResult get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
|
||||
uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) override;
|
||||
|
||||
PFN_vkVoidFunction get_proc_addr(const char *name) override;
|
||||
|
||||
static surface_properties &get_instance();
|
||||
};
|
||||
|
||||
|
|
|
|||
66
wsi/surface.hpp
Normal file
66
wsi/surface.hpp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Vulkan WSI surface interfaces.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "surface_properties.hpp"
|
||||
#include "swapchain_base.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A generic WSI representation of a VkSurface.
|
||||
*
|
||||
* The association between these objects and VkSurfaces is kept in the VkInstance private data.
|
||||
*/
|
||||
class surface
|
||||
{
|
||||
public:
|
||||
virtual ~surface() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns a @ref surface_properties implementation that can be specific to the VkSurface represented.
|
||||
*/
|
||||
virtual surface_properties &get_properties() = 0;
|
||||
|
||||
/**
|
||||
* @brief Allocates a swapchain for the VkSurface type represented.
|
||||
*
|
||||
* @param dev_data The VkDevice associated private date.
|
||||
* @param allocator Allocation callbacks to use for host memory.
|
||||
*
|
||||
* @return nullptr on failure otherwise a constructed swapchain.
|
||||
*/
|
||||
virtual util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator) = 0;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
@ -71,11 +71,10 @@ public:
|
|||
|
||||
/**
|
||||
* @brief Implements vkGetProcAddr for entrypoints specific to the surface type.
|
||||
*
|
||||
* At least the specific VkSurface creation entrypoint must be intercepted.
|
||||
*/
|
||||
virtual PFN_vkVoidFunction get_proc_addr(const char *name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual PFN_vkVoidFunction get_proc_addr(const char *name) = 0;
|
||||
};
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
51
wsi/wayland/surface.cpp
Normal file
51
wsi/wayland/surface.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Implementation of a Wayland WSI Surface
|
||||
*/
|
||||
|
||||
#include "surface.hpp"
|
||||
#include "swapchain.hpp"
|
||||
#include "surface_properties.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
wsi::surface_properties &surface::get_properties()
|
||||
{
|
||||
return surface_properties::get_instance();
|
||||
}
|
||||
|
||||
util::unique_ptr<swapchain_base> surface::allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator)
|
||||
{
|
||||
util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, allocator };
|
||||
return util::unique_ptr<swapchain_base>(alloc.make_unique<swapchain>(dev_data, allocator));
|
||||
}
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
49
wsi/wayland/surface.hpp
Normal file
49
wsi/wayland/surface.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Definitions for a Wayland WSI Surface
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wsi/surface.hpp"
|
||||
|
||||
namespace wsi
|
||||
{
|
||||
namespace wayland
|
||||
{
|
||||
|
||||
class surface : public wsi::surface
|
||||
{
|
||||
public:
|
||||
surface() = default;
|
||||
|
||||
wsi::surface_properties &get_properties() override;
|
||||
util::unique_ptr<swapchain_base> allocate_swapchain(layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *allocator) override;
|
||||
};
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
#include <array>
|
||||
#include <cstring>
|
||||
#include "surface_properties.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "layer/private_data.hpp"
|
||||
#include "wl_helpers.hpp"
|
||||
#include "wl_object_owner.hpp"
|
||||
|
|
@ -281,13 +282,40 @@ VkBool32 GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physica
|
|||
return VK_TRUE;
|
||||
}
|
||||
|
||||
extern "C" VkResult CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface)
|
||||
{
|
||||
auto &instance_data = layer::instance_private_data::get(instance);
|
||||
util::allocator allocator{ instance_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator };
|
||||
auto wsi_surface = util::unique_ptr<wsi::surface>(allocator.make_unique<surface>());
|
||||
if (wsi_surface == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
VkResult res = instance_data.disp.CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
res = instance_data.add_surface(*pSurface, wsi_surface);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
instance_data.disp.DestroySurfaceKHR(instance, *pSurface, pAllocator);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
PFN_vkVoidFunction surface_properties::get_proc_addr(const char *name)
|
||||
{
|
||||
if (strcmp(name, "vkGetPhysicalDeviceWaylandPresentationSupportKHR") == 0)
|
||||
{
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR);
|
||||
}
|
||||
else if (strcmp(name, "vkCreateWaylandSurfaceKHR") == 0)
|
||||
{
|
||||
return reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace wayland
|
||||
} // namespace wsi
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
*/
|
||||
|
||||
#include "wsi_factory.hpp"
|
||||
#include "surface.hpp"
|
||||
#include "headless/surface_properties.hpp"
|
||||
#include "headless/swapchain.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
|
@ -41,7 +41,6 @@
|
|||
#if BUILD_WSI_WAYLAND
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
#include "wayland/surface_properties.hpp"
|
||||
#include "wayland/swapchain.hpp"
|
||||
#endif
|
||||
|
||||
namespace wsi
|
||||
|
|
@ -73,36 +72,27 @@ static surface_properties *get_surface_properties(VkIcdWsiPlatform platform)
|
|||
}
|
||||
}
|
||||
|
||||
surface_properties *get_surface_properties(VkSurfaceKHR surface)
|
||||
surface_properties *get_surface_properties(layer::instance_private_data &instance_data, VkSurfaceKHR surface)
|
||||
{
|
||||
VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
|
||||
auto *wsi_surface = instance_data.get_surface(surface);
|
||||
|
||||
return get_surface_properties(surface_base->platform);
|
||||
}
|
||||
|
||||
template <typename swapchain_type>
|
||||
static swapchain_base *allocate_swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, pAllocator };
|
||||
return alloc.create<swapchain_type>(1, dev_data, pAllocator);
|
||||
}
|
||||
|
||||
swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
VkIcdSurfaceBase *surface_base = reinterpret_cast<VkIcdSurfaceBase *>(surface);
|
||||
|
||||
switch (surface_base->platform)
|
||||
if (wsi_surface)
|
||||
{
|
||||
case VK_ICD_WSI_PLATFORM_HEADLESS:
|
||||
return allocate_swapchain<wsi::headless::swapchain>(dev_data, pAllocator);
|
||||
#if BUILD_WSI_WAYLAND
|
||||
case VK_ICD_WSI_PLATFORM_WAYLAND:
|
||||
return allocate_swapchain<wsi::wayland::swapchain>(dev_data, pAllocator);
|
||||
#endif
|
||||
default:
|
||||
return nullptr;
|
||||
return &wsi_surface->get_properties();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
util::unique_ptr<swapchain_base> allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
wsi::surface *wsi_surface = dev_data.instance_data.get_surface(surface);
|
||||
if (wsi_surface)
|
||||
{
|
||||
return wsi_surface->allocate_swapchain(dev_data, pAllocator);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
util::wsi_platform_set find_enabled_layer_platforms(const VkInstanceCreateInfo *pCreateInfo)
|
||||
|
|
@ -195,7 +185,7 @@ void destroy_surface_swapchain(swapchain_base *swapchain, layer::device_private_
|
|||
{
|
||||
assert(swapchain);
|
||||
|
||||
util::allocator alloc{ swapchain->get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE, pAllocator };
|
||||
util::allocator alloc{ dev_data.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT, pAllocator };
|
||||
alloc.destroy(1, swapchain);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,11 +41,12 @@ namespace wsi
|
|||
/**
|
||||
* @brief Obtains the surface properties for the specific surface type.
|
||||
*
|
||||
* @param surface The surface for which to get the properties.
|
||||
* @param instance_data The instance specific data.
|
||||
* @param surface The surface for which to get the properties.
|
||||
*
|
||||
* @return nullptr if surface type is unsupported.
|
||||
*/
|
||||
surface_properties *get_surface_properties(VkSurfaceKHR surface);
|
||||
surface_properties *get_surface_properties(layer::instance_private_data &instance_data, VkSurfaceKHR surface);
|
||||
|
||||
/**
|
||||
* @brief Allocates a surface specific swapchain.
|
||||
|
|
@ -56,8 +57,8 @@ surface_properties *get_surface_properties(VkSurfaceKHR surface);
|
|||
*
|
||||
* @return nullptr on failure.
|
||||
*/
|
||||
swapchain_base *allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *pAllocator);
|
||||
util::unique_ptr<swapchain_base> allocate_surface_swapchain(VkSurfaceKHR surface, layer::device_private_data &dev_data,
|
||||
const VkAllocationCallbacks *pAllocator);
|
||||
|
||||
/**
|
||||
* @brief Destroys a swapchain and frees memory. Used with @ref allocate_surface_swapchain.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue