vkmemory: don't map memory more than once

vkMapMemory may not be called on a memory object that is already
host-mapped. If the gstreamer memory object is mapped more than once then
reuse the existing Vulkan mapping.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5917>
This commit is contained in:
Chris Spencer 2024-01-12 14:42:29 +00:00 committed by Víctor Manuel Jáquez Leal
parent 2c61fd92e2
commit 2388932767
3 changed files with 47 additions and 13 deletions

View file

@ -4353,6 +4353,10 @@ It can be called from any thread.</doc>
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkmemory.h">number of times this memory is mapped</doc>
<type name="guint" c:type="guint"/>
</field>
<field name="mapping" version="1.24" writable="1">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkmemory.h">internal pointer to already mapped memory</doc>
<type name="gpointer" c:type="gpointer"/>
</field>
<field name="notify" readable="0" private="1">
<type name="GLib.DestroyNotify" c:type="GDestroyNotify"/>
</field>

View file

@ -77,6 +77,8 @@ _vk_mem_init (GstVulkanMemory * mem, GstAllocator * allocator,
mem->notify = notify;
mem->user_data = user_data;
mem->vk_offset = 0;
mem->map_count = 0;
mem->mapping = NULL;
g_mutex_init (&mem->lock);
@ -122,19 +124,29 @@ _vk_mem_map_full (GstVulkanMemory * mem, GstMapInfo * info, gsize size)
VkResult err;
GError *error = NULL;
if ((mem->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Cannot map host-invisible memory");
return NULL;
g_mutex_lock (&mem->lock);
if (mem->map_count == 0) {
if ((mem->properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Cannot map host-invisible memory");
g_mutex_unlock (&mem->lock);
return NULL;
}
err = vkMapMemory (mem->device->device, mem->mem_ptr, mem->vk_offset,
size, 0, &mem->mapping);
if (gst_vulkan_error_to_g_error (err, &error, "vkMapMemory") < 0) {
GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Failed to map device memory %s",
error->message);
g_clear_error (&error);
g_mutex_unlock (&mem->lock);
return NULL;
}
}
err = vkMapMemory (mem->device->device, mem->mem_ptr, mem->vk_offset,
size, 0, &data);
if (gst_vulkan_error_to_g_error (err, &error, "vkMapMemory") < 0) {
GST_CAT_ERROR (GST_CAT_VULKAN_MEMORY, "Failed to map device memory %s",
error->message);
g_clear_error (&error);
return NULL;
}
mem->map_count++;
data = mem->mapping;
g_mutex_unlock (&mem->lock);
return data;
}
@ -163,7 +175,16 @@ _vk_mem_unmap_full (GstVulkanMemory * mem, GstMapInfo * info)
}
}
vkUnmapMemory (mem->device->device, mem->mem_ptr);
g_mutex_lock (&mem->lock);
g_assert (mem->map_count != 0);
mem->map_count--;
if (mem->map_count == 0) {
vkUnmapMemory (mem->device->device, mem->mem_ptr);
mem->mapping = NULL;
}
g_mutex_unlock (&mem->lock);
}
static GstMemory *

View file

@ -53,12 +53,13 @@ GType gst_vulkan_memory_allocator_get_type(void);
#define GST_VULKAN_MEMORY_ALLOCATOR_NAME "Vulkan"
/**
* GstVulkanMemory
* GstVulkanMemory:
* @mem: the parent #GstMemory
* @device: the #GstVulkanDevice this memory is allocated from
* @mem_ptr: the vulkan memory handle
* @lock: lock for accessing/changing memory informat
* @map_count: number of times this memory is mapped
* @mapping: internal pointer to already mapped memory
*
* Since: 1.18
*/
@ -73,6 +74,14 @@ struct _GstVulkanMemory
/* <protected> */
GMutex lock;
guint map_count;
/**
* GstVulkanMemory.mapping:
*
* internal pointer to already mapped memory
*
* Since: 1.24
*/
gpointer mapping;
/* <private> */
GDestroyNotify notify;