From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 9BA1D4D785 for ; Mon, 24 Feb 2025 08:05:15 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 83C7F68CC8B; Mon, 24 Feb 2025 10:04:47 +0200 (EET) Received: from vidala.pars.ee (vidala.pars.ee [116.203.72.101]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2AFEB68CB32 for ; Mon, 24 Feb 2025 10:04:38 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; s=202405r; d=lynne.ee; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1740384278; bh=mJgZGQgTjsCX0JniwL4aLos 3Xzf63hGzO+bx3z1kMXU=; b=V+2JgSjhBBRFiE1Hm7ma1berxT9dWTp3vJyPuBXRNjj+oC+MyH NAyDVrEedXi+SpiPvJ7RD5G0ZXR8/ZQ4EX54kUh2BkK/5qPQsSyHAi+HhXUaMjInfBHJWOL4seI qG5YcPdTSwYCg3g1hx2oE9zyvaSZqSJtrHIOJNNhDnR8h6xWCiYHupewZwS3zbgOqNmwRoqVkGP TFpp+YwF9RpsZgiGSaYweBFFGu1ghpIiO+8tYtKVytH9Iter64iVZ1BFzYWGj3O7gd6uuaD+RUQ e6omVlIbsGEPQgi0H6n8+zWIIKLxB1T+9sVDTLTRycZrdp+G2sL6lD98FkCFHyzg5/g==; DKIM-Signature: v=1; a=ed25519-sha256; s=202405e; d=lynne.ee; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1740384278; bh=mJgZGQgTjsCX0JniwL4aLos 3Xzf63hGzO+bx3z1kMXU=; b=7tHYXnqZ7rwMvrFS9w6YJTko4KaBVILWYFeuoLxB9c8gREgqgU ANoHG6CcD8rLdHz2vIaW/4rEMgbTc+QFnEBQ==; From: Lynne To: ffmpeg-devel@ffmpeg.org Date: Mon, 24 Feb 2025 09:04:16 +0100 Message-ID: <20250224080434.5632-3-dev@lynne.ee> X-Mailer: git-send-email 2.47.2 In-Reply-To: <20250224080434.5632-1-dev@lynne.ee> References: <20250224080434.5632-1-dev@lynne.ee> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 03/12] vulkan: copy host-mapping buffer code from hwcontext X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Lynne Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: This is useful elsewhere. --- libavutil/vulkan.c | 153 ++++++++++++++++++++++++++++++++++++++++++++- libavutil/vulkan.h | 17 ++++- 2 files changed, 167 insertions(+), 3 deletions(-) diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index de6260b2f8..4d60ac1b3a 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -1115,6 +1115,8 @@ int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, .memory = buf[i]->mem, .size = VK_WHOLE_SIZE, }; + + av_assert0(!buf[i]->host_ref); if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) continue; flush_list[flush_count++] = flush_buf; @@ -1146,12 +1148,18 @@ void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) if (!buf || !s->hwctx) return; - if (buf->mapped_mem) + if (buf->mapped_mem && !buf->host_ref) ff_vk_unmap_buffer(s, buf, 0); if (buf->buf != VK_NULL_HANDLE) vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); if (buf->mem != VK_NULL_HANDLE) vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); + if (buf->host_ref) + av_buffer_unref(&buf->host_ref); + + buf->buf = VK_NULL_HANDLE; + buf->mem = VK_NULL_HANDLE; + buf->mapped_mem = NULL; } static void free_data_buf(void *opaque, uint8_t *data) @@ -1228,6 +1236,147 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, return 0; } +static int create_mapped_buffer(FFVulkanContext *s, + FFVkBuffer *vkb, VkBufferUsageFlags usage, + size_t size, + VkExternalMemoryBufferCreateInfo *create_desc, + VkImportMemoryHostPointerInfoEXT *import_desc, + VkMemoryHostPointerPropertiesEXT props) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkBufferCreateInfo buf_spawn = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = create_desc, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .size = size, + }; + VkMemoryRequirements req = { + .size = size, + .alignment = s->hprops.minImportedHostPointerAlignment, + .memoryTypeBits = props.memoryTypeBits, + }; + + err = ff_vk_alloc_mem(s, &req, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + import_desc, &vkb->flags, &vkb->mem); + if (err < 0) + return err; + + ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf); + if (ret != VK_SUCCESS) { + vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc); + return AVERROR_EXTERNAL; + } + + ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0); + if (ret != VK_SUCCESS) { + vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc); + vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc); + return AVERROR_EXTERNAL; + } + + return 0; +} + +int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst, + AVBufferRef *src, VkBufferUsageFlags usage) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkExternalMemoryBufferCreateInfo create_desc = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + }; + VkMemoryAllocateFlagsInfo alloc_flags = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, + .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, + }; + VkImportMemoryHostPointerInfoEXT import_desc = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, + .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL, + }; + VkMemoryHostPointerPropertiesEXT props; + + AVBufferRef *ref; + FFVkBuffer *vkb; + size_t offs; + size_t buffer_size; + + *dst = NULL; + + /* Get the previous point at which mapping was possible and use it */ + offs = (uintptr_t)src->data % s->hprops.minImportedHostPointerAlignment; + import_desc.pHostPointer = src->data - offs; + + props = (VkMemoryHostPointerPropertiesEXT) { + VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, + }; + ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev, + import_desc.handleType, + import_desc.pHostPointer, + &props); + if (!(ret == VK_SUCCESS && props.memoryTypeBits)) + return AVERROR(EINVAL); + + /* Ref the source buffer */ + ref = av_buffer_ref(src); + if (!ref) + return AVERROR(ENOMEM); + + /* Add the offset at the start, which gets ignored */ + buffer_size = offs + src->size; + buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment); + buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment); + + /* Create a buffer struct */ + vkb = av_mallocz(sizeof(*vkb)); + if (!vkb) { + av_buffer_unref(&ref); + return AVERROR(ENOMEM); + } + + err = create_mapped_buffer(s, vkb, usage, + buffer_size, &create_desc, &import_desc, + props); + if (err < 0) { + av_buffer_unref(&ref); + av_free(vkb); + return err; + } + + if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { + VkBufferDeviceAddressInfo address_info = { + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = vkb->buf, + }; + vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info); + } + + vkb->host_ref = ref; + vkb->virtual_offset = offs; + vkb->address += offs; + vkb->mapped_mem = src->data; + vkb->size = buffer_size - offs; + + /* Create a ref */ + *dst = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), + destroy_avvkbuf, s, 0); + if (!(*dst)) { + destroy_avvkbuf(s, (uint8_t *)vkb); + *dst = NULL; + return AVERROR(ENOMEM); + } + + return 0; +} + int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage) { @@ -2546,7 +2695,7 @@ int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e, } else { VkDescriptorBufferInfo desc_pool_write_info_buf = { .buffer = buf->buf, - .offset = offset, + .offset = buf->virtual_offset + offset, .range = len, }; VkWriteDescriptorSet desc_pool_write_info = { diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h index c3ddf0cd6b..327ce2b286 100644 --- a/libavutil/vulkan.h +++ b/libavutil/vulkan.h @@ -96,8 +96,17 @@ typedef struct FFVkBuffer { VkPipelineStageFlags2 stage; VkAccessFlags2 access; - /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE */ + /* Only valid when allocated via ff_vk_get_pooled_buffer with HOST_VISIBLE or + * via ff_vk_host_map_buffer */ uint8_t *mapped_mem; + + /* Set by ff_vk_host_map_buffer. This is the offset at which the buffer data + * actually begins at. + * The address and mapped_mem fields will be offset by this amount. */ + size_t virtual_offset; + + /* If host mapping, reference to the backing host memory buffer */ + AVBufferRef *host_ref; } FFVkBuffer; typedef struct FFVkExecContext { @@ -523,6 +532,12 @@ int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props); +/** Maps a system RAM buffer into a Vulkan buffer. + * References the source buffer. + */ +int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst, + AVBufferRef *src, VkBufferUsageFlags usage); + /** * Create a sampler. */ -- 2.47.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".