* [FFmpeg-devel] [PATCH] hwcontext_vulkan: add support for mapping multiplane images into CUDA
@ 2025-03-07 0:03 Lynne
0 siblings, 0 replies; only message in thread
From: Lynne @ 2025-03-07 0:03 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
This patch refactors the CUDA import code to allow for Vulkan images
with multiple planes to be mapped.
---
libavutil/hwcontext_vulkan.c | 262 +++++++++++++++++++++--------------
1 file changed, 160 insertions(+), 102 deletions(-)
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 10521ce685..fcff34b5e2 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -3409,6 +3409,130 @@ fail:
#endif
#if CONFIG_CUDA
+static int export_mem_to_cuda(AVHWDeviceContext *ctx,
+ AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
+ AVVkFrameInternal *dst_int, int idx,
+ VkDeviceMemory mem, size_t size)
+{
+ VkResult ret;
+ VulkanDevicePriv *p = ctx->hwctx;
+ AVVulkanDeviceContext *hwctx = &p->p;
+ FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+#ifdef _WIN32
+ CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
+ .type = IsWindows8OrGreater()
+ ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
+ : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
+ .size = size,
+ };
+ VkMemoryGetWin32HandleInfoKHR export_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
+ .memory = mem,
+ .handleType = IsWindows8OrGreater()
+ ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
+ : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ };
+
+ ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info,
+ &ext_desc.handle.win32.handle);
+ if (ret != VK_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+ dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
+#else
+ CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
+ .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
+ .size = size,
+ };
+ VkMemoryGetFdInfoKHR export_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+ .memory = mem,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
+ };
+
+ ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
+ &ext_desc.handle.fd);
+ if (ret != VK_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+#endif
+
+ ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
+ if (ret < 0) {
+#ifndef _WIN32
+ close(ext_desc.handle.fd);
+#endif
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+}
+
+static int export_sem_to_cuda(AVHWDeviceContext *ctx,
+ AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
+ AVVkFrameInternal *dst_int, int idx,
+ VkSemaphore sem)
+{
+ VkResult ret;
+ VulkanDevicePriv *p = ctx->hwctx;
+ AVVulkanDeviceContext *hwctx = &p->p;
+ FFVulkanFunctions *vk = &p->vkctx.vkfn;
+
+#ifdef _WIN32
+ VkSemaphoreGetWin32HandleInfoKHR sem_export = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
+ .semaphore = sem,
+ .handleType = IsWindows8OrGreater()
+ ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
+ : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
+ };
+ CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
+ .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */,
+ };
+#else
+ VkSemaphoreGetFdInfoKHR sem_export = {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
+ .semaphore = sem,
+ .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
+ };
+ CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
+ .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */,
+ };
+#endif
+
+#ifdef _WIN32
+ ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export,
+ &ext_sem_desc.handle.win32.handle);
+#else
+ ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export,
+ &ext_sem_desc.handle.fd);
+#endif
+ if (ret != VK_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n",
+ ff_vk_ret2str(ret));
+ return AVERROR_EXTERNAL;
+ }
+#ifdef _WIN32
+ dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
+#endif
+
+ ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
+ &ext_sem_desc));
+ if (ret < 0) {
+#ifndef _WIN32
+ close(ext_sem_desc.handle.fd);
+#endif
+ return AVERROR_EXTERNAL;
+ }
+
+ return 0;
+}
+
static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
AVBufferRef *cuda_hwfc,
const AVFrame *frame)
@@ -3423,6 +3547,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
VulkanDevicePriv *p = ctx->hwctx;
AVVulkanDeviceContext *hwctx = &p->p;
FFVulkanFunctions *vk = &p->vkctx.vkfn;
+ int nb_images;
AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data;
AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
@@ -3436,13 +3561,42 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
dst_int = dst_f->internal;
if (!dst_int->cuda_fc_ref) {
+ size_t offsets[3] = { 0 };
+
dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc);
if (!dst_int->cuda_fc_ref)
return AVERROR(ENOMEM);
+ nb_images = ff_vk_count_images(dst_f);
+ for (int i = 0; i < nb_images; i++) {
+ err = export_mem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
+ dst_f->mem[i], dst_f->size[i]);
+ if (err < 0)
+ goto fail;
+
+ err = export_sem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
+ dst_f->sem[i]);
+ if (err < 0)
+ goto fail;
+ }
+
+ if (nb_images != planes) {
+ for (int i = 0; i < planes; i++) {
+ VkImageSubresource subres = {
+ .aspectMask = i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
+ i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
+ VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
+ };
+ VkSubresourceLayout layout = { 0 };
+ vk->GetImageSubresourceLayout(hwctx->act_dev, dst_f->img[FFMIN(i, nb_images - 1)],
+ &subres, &layout);
+ offsets[i] = layout.offset;
+ }
+ }
+
for (int i = 0; i < planes; i++) {
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
- .offset = 0,
+ .offset = offsets[i],
.arrayDesc = {
.Depth = 0,
.Format = cufmt,
@@ -3453,84 +3607,12 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
};
int p_w, p_h;
-#ifdef _WIN32
- CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
- .type = IsWindows8OrGreater()
- ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
- : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
- .size = dst_f->size[i],
- };
- VkMemoryGetWin32HandleInfoKHR export_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
- .memory = dst_f->mem[i],
- .handleType = IsWindows8OrGreater()
- ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
- : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
- };
- VkSemaphoreGetWin32HandleInfoKHR sem_export = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
- .semaphore = dst_f->sem[i],
- .handleType = IsWindows8OrGreater()
- ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
- : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
- };
- CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
- .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */,
- };
-
- ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info,
- &ext_desc.handle.win32.handle);
- if (ret != VK_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n",
- ff_vk_ret2str(ret));
- err = AVERROR_EXTERNAL;
- goto fail;
- }
- dst_int->ext_mem_handle[i] = ext_desc.handle.win32.handle;
-#else
- CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
- .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
- .size = dst_f->size[i],
- };
- VkMemoryGetFdInfoKHR export_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
- .memory = dst_f->mem[i],
- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
- };
- VkSemaphoreGetFdInfoKHR sem_export = {
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
- .semaphore = dst_f->sem[i],
- .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
- };
- CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
- .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */,
- };
-
- ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
- &ext_desc.handle.fd);
- if (ret != VK_SUCCESS) {
- av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n",
- ff_vk_ret2str(ret));
- err = AVERROR_EXTERNAL;
- goto fail;
- }
-#endif
-
- ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[i], &ext_desc));
- if (ret < 0) {
-#ifndef _WIN32
- close(ext_desc.handle.fd);
-#endif
- err = AVERROR_EXTERNAL;
- goto fail;
- }
-
get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
tex_desc.arrayDesc.Width = p_w;
tex_desc.arrayDesc.Height = p_h;
ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i],
- dst_int->ext_mem[i],
+ dst_int->ext_mem[FFMIN(i, nb_images - 1)],
&tex_desc));
if (ret < 0) {
err = AVERROR_EXTERNAL;
@@ -3544,32 +3626,6 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
goto fail;
}
-#ifdef _WIN32
- ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export,
- &ext_sem_desc.handle.win32.handle);
-#else
- ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export,
- &ext_sem_desc.handle.fd);
-#endif
- if (ret != VK_SUCCESS) {
- av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n",
- ff_vk_ret2str(ret));
- err = AVERROR_EXTERNAL;
- goto fail;
- }
-#ifdef _WIN32
- dst_int->ext_sem_handle[i] = ext_sem_desc.handle.win32.handle;
-#endif
-
- ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i],
- &ext_sem_desc));
- if (ret < 0) {
-#ifndef _WIN32
- close(ext_sem_desc.handle.fd);
-#endif
- err = AVERROR_EXTERNAL;
- goto fail;
- }
}
}
@@ -4313,6 +4369,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
VulkanFramesPriv *fp = hwfc->hwctx;
const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format);
+ int nb_images;
AVHWFramesContext *cuda_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data;
AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
@@ -4323,6 +4380,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
dst_f = (AVVkFrame *)src->data[0];
+ nb_images = ff_vk_count_images(dst_f);
err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
if (err < 0)
@@ -4346,7 +4404,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
}
err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
- planes, cuda_dev->stream));
+ nb_images, cuda_dev->stream));
if (err < 0)
goto fail;
@@ -4373,7 +4431,7 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
}
err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
- planes, cuda_dev->stream));
+ nb_images, cuda_dev->stream));
if (err < 0)
goto fail;
--
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".
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-03-07 0:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-07 0:03 [FFmpeg-devel] [PATCH] hwcontext_vulkan: add support for mapping multiplane images into CUDA Lynne
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git