mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-05-05 01:48:04 +02:00
Use util::allocator in swapchain object
Change util::allocator's create and destroy methods so that they can allocate multiple objects, in line with the allocate and deallocate methods of std::allocator. Also add documentation for util::allocator and its methods. Finally, use util::allocator in swapchain.cpp, rather than allocating memory directly via VkAllocationCallbacks. Change-Id: I0bc25abe3cbc3af9608218411da8d70e04dd9749 Signed-off-by: Matteo Franchin <matteo.franchin@arm.com>
This commit is contained in:
parent
5b2b2511f7
commit
f0b541a4e3
5 changed files with 84 additions and 64 deletions
|
|
@ -62,4 +62,9 @@ allocator::allocator(const VkAllocationCallbacks *callbacks, VkSystemAllocationS
|
|||
}
|
||||
}
|
||||
|
||||
const VkAllocationCallbacks *allocator::get_original_callbacks() const
|
||||
{
|
||||
return m_callbacks.pfnAllocation == default_allocation ? nullptr : &m_callbacks;
|
||||
}
|
||||
|
||||
} /* namespace util */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <new>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
|
@ -39,13 +40,37 @@ namespace util
|
|||
class allocator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new wrapper for the given VK callbacks and scope.
|
||||
* @param callbacks Pointer to allocation callbacks. If this is @c nullptr, then default
|
||||
* allocation callbacks are used. These can be accessed through #m_callbacks.
|
||||
* @param scope The scope to use for this allocator.
|
||||
*/
|
||||
allocator(const VkAllocationCallbacks *callbacks, VkSystemAllocationScope scope);
|
||||
|
||||
template <typename T, typename... arg_types>
|
||||
T *create(arg_types &&... args) const;
|
||||
/**
|
||||
* @brief Get a pointer to the allocation callbacks provided while constructing this object.
|
||||
* @return a copy of the #VkAllocationCallback argument provided in the allocator constructor
|
||||
* or @c nullptr if this argument was provided as @c nullptr.
|
||||
* @note The #m_callbacks member is always populated with callable pointers for pfnAllocation,
|
||||
* pfnReallocation and pfnFree.
|
||||
*/
|
||||
const VkAllocationCallbacks *get_original_callbacks() const;
|
||||
|
||||
/**
|
||||
* @brief Helper method to allocate and construct objects with a custom allocator.
|
||||
* @param num_objects Number of objects to create.
|
||||
* @return Pointer to the newly created objects or @c nullptr if allocation failed.
|
||||
*/
|
||||
template <typename T, typename... arg_types>
|
||||
T *create(size_t num_objects, arg_types &&... args) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Helper method to destroy and deallocate objects constructed with allocator::create().
|
||||
* @param num_objects Number of objects to destroy.
|
||||
*/
|
||||
template <typename T>
|
||||
void destroy(T *obj) const;
|
||||
void destroy(size_t num_objects, T *obj) const noexcept;
|
||||
|
||||
VkAllocationCallbacks m_callbacks;
|
||||
VkSystemAllocationScope m_scope;
|
||||
|
|
@ -118,48 +143,66 @@ bool operator!=(const custom_allocator<T> &, const custom_allocator<U> &)
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper method to allocate and construct objects with a custom allocator.
|
||||
* @return The new object or @c nullptr if allocation failed.
|
||||
*/
|
||||
template <typename T, typename... arg_types>
|
||||
T *allocator::create(arg_types &&... args) const
|
||||
T *allocator::create(size_t num_objects, arg_types &&... args) const noexcept
|
||||
{
|
||||
if (num_objects < 1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
custom_allocator<T> allocator(*this);
|
||||
T *ptr;
|
||||
try
|
||||
{
|
||||
ptr = allocator.allocate(1);
|
||||
ptr = allocator.allocate(num_objects);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t objects_constructed = 0;
|
||||
try
|
||||
{
|
||||
new (ptr) T(std::forward<arg_types>(args)...);
|
||||
while (objects_constructed < num_objects)
|
||||
{
|
||||
T *next_object = &ptr[objects_constructed];
|
||||
new (next_object) T(std::forward<arg_types>(args)...);
|
||||
objects_constructed++;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
/* We catch all exceptions thrown while constructing the object, not just
|
||||
* std::bad_alloc.
|
||||
*/
|
||||
allocator.deallocate(ptr, 1);
|
||||
while (objects_constructed > 0)
|
||||
{
|
||||
objects_constructed--;
|
||||
ptr[objects_constructed].~T();
|
||||
}
|
||||
allocator.deallocate(ptr, num_objects);
|
||||
return nullptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper method to destroy and deallocate objects constructed with create_custom().
|
||||
*/
|
||||
template <typename T>
|
||||
void allocator::destroy(T *obj) const
|
||||
void allocator::destroy(size_t num_objects, T *objects) const noexcept
|
||||
{
|
||||
obj->~T();
|
||||
assert((objects == nullptr) == (num_objects == 0));
|
||||
if (num_objects == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
custom_allocator<T> allocator(*this);
|
||||
allocator.deallocate(obj, 1);
|
||||
for (size_t i = 0; i < num_objects; i++)
|
||||
{
|
||||
objects[i].~T();
|
||||
}
|
||||
allocator.deallocate(objects, num_objects);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -88,19 +88,10 @@ VkResult swapchain::create_image(const VkImageCreateInfo &image_create, wsi::swa
|
|||
image_data *data = nullptr;
|
||||
|
||||
/* Create image_data */
|
||||
if (m_alloc_callbacks != nullptr)
|
||||
{
|
||||
data = static_cast<image_data *>(m_alloc_callbacks->pfnAllocation(
|
||||
m_alloc_callbacks->pUserData, sizeof(image_data), 0, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
|
||||
}
|
||||
else
|
||||
{
|
||||
data = static_cast<image_data *>(malloc(sizeof(image_data)));
|
||||
}
|
||||
|
||||
data = m_allocator.create<image_data>(1);
|
||||
if (data == nullptr)
|
||||
{
|
||||
m_device_data.disp.DestroyImage(m_device, image.image, m_alloc_callbacks);
|
||||
m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
image.data = reinterpret_cast<void *>(data);
|
||||
|
|
@ -150,7 +141,7 @@ void swapchain::destroy_image(wsi::swapchain_image &image)
|
|||
|
||||
if (image.image != VK_NULL_HANDLE)
|
||||
{
|
||||
m_device_data.disp.DestroyImage(m_device, image.image, m_alloc_callbacks);
|
||||
m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
|
||||
image.image = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
|
@ -163,14 +154,7 @@ void swapchain::destroy_image(wsi::swapchain_image &image)
|
|||
m_device_data.disp.FreeMemory(m_device, data->memory, nullptr);
|
||||
data->memory = VK_NULL_HANDLE;
|
||||
}
|
||||
if (m_alloc_callbacks != nullptr)
|
||||
{
|
||||
m_alloc_callbacks->pfnFree(m_alloc_callbacks->pUserData, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
m_allocator.destroy(1, data);
|
||||
image.data = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,14 +134,14 @@ void swapchain_base::unpresent_image(uint32_t presented_index)
|
|||
m_free_image_semaphore.post();
|
||||
}
|
||||
|
||||
swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator)
|
||||
swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
|
||||
: m_device_data(dev_data)
|
||||
, m_page_flip_thread_run(true)
|
||||
, m_thread_sem_defined(false)
|
||||
, m_first_present(true)
|
||||
, m_pending_buffer_pool{ nullptr, 0, 0, 0 }
|
||||
, m_alloc_callbacks(allocator)
|
||||
, m_swapchain_images(util::allocator(m_alloc_callbacks, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
||||
, m_allocator(callbacks, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)
|
||||
, m_swapchain_images(m_allocator)
|
||||
, m_surface(VK_NULL_HANDLE)
|
||||
, m_present_mode(VK_PRESENT_MODE_IMMEDIATE_KHR)
|
||||
, m_descendant(VK_NULL_HANDLE)
|
||||
|
|
@ -184,17 +184,7 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
||||
/* Initialize ring buffer. */
|
||||
if (m_alloc_callbacks != nullptr)
|
||||
{
|
||||
m_pending_buffer_pool.ring = static_cast<uint32_t *>(
|
||||
m_alloc_callbacks->pfnAllocation(m_alloc_callbacks->pUserData, sizeof(uint32_t) * m_swapchain_images.size(),
|
||||
alignof(uint32_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pending_buffer_pool.ring = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * m_swapchain_images.size()));
|
||||
}
|
||||
|
||||
m_pending_buffer_pool.ring = m_allocator.create<uint32_t>(m_swapchain_images.size(), 0);
|
||||
if (m_pending_buffer_pool.ring == nullptr)
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
|
@ -377,17 +367,7 @@ void swapchain_base::teardown()
|
|||
destroy_image(img);
|
||||
}
|
||||
|
||||
if (m_pending_buffer_pool.ring != nullptr)
|
||||
{
|
||||
if (m_alloc_callbacks != nullptr)
|
||||
{
|
||||
m_alloc_callbacks->pfnFree(m_alloc_callbacks->pUserData, m_pending_buffer_pool.ring);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(m_pending_buffer_pool.ring);
|
||||
}
|
||||
}
|
||||
m_allocator.destroy(m_swapchain_images.size(), m_pending_buffer_pool.ring);
|
||||
}
|
||||
|
||||
VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ protected:
|
|||
/**
|
||||
* @brief User provided memory allocation callbacks.
|
||||
*/
|
||||
const VkAllocationCallbacks *m_alloc_callbacks;
|
||||
const util::allocator m_allocator;
|
||||
|
||||
/**
|
||||
* @brief Vector of images in the swapchain.
|
||||
|
|
@ -243,7 +243,15 @@ protected:
|
|||
*/
|
||||
VkQueue m_queue;
|
||||
|
||||
/*
|
||||
/**
|
||||
* @brief Return the VkAllocationCallbacks passed in this object constructor.
|
||||
*/
|
||||
const VkAllocationCallbacks *get_allocation_callbacks()
|
||||
{
|
||||
return m_allocator.get_original_callbacks();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Method to wait on all pending buffers to be displayed.
|
||||
*/
|
||||
void wait_for_pending_buffers();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue