diff options
author | Timo Rothenpieler <timo@rothenpieler.org> | 2021-11-13 20:00:50 +0100 |
---|---|---|
committer | Timo Rothenpieler <timo@rothenpieler.org> | 2021-11-14 12:50:32 +0100 |
commit | 2ece70090d61ccc1aea8000ba57d2fd759f204f7 (patch) | |
tree | 8f3eb734354a930e3cea919fefd4296ed1155515 /libavutil | |
parent | fedf4ff85c325fa164a5646785104aaa292c877b (diff) | |
download | ffmpeg-2ece70090d61ccc1aea8000ba57d2fd759f204f7.tar.gz |
avutil/hwcontext_vulkan: add support for exporting memory via Win32 Handles
Diffstat (limited to 'libavutil')
-rw-r--r-- | libavutil/hwcontext_vulkan.c | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index d40b1e5de0..b218b6c411 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -21,6 +21,7 @@ #ifdef _WIN32 #include <windows.h> /* Included to prevent conflicts with CreateSemaphore */ +#include <versionhelpers.h> #include "compat/w32dlfcn.h" #else #include <dlfcn.h> @@ -123,6 +124,10 @@ typedef struct AVVkFrameInternal { CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; CUarray cu_array[AV_NUM_DATA_POINTERS]; CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; +#ifdef _WIN32 + HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS]; + HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS]; +#endif #endif } AVVkFrameInternal; @@ -309,6 +314,10 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, +#ifdef _WIN32 + { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, +#endif /* Video encoding/decoding */ { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, @@ -1575,6 +1584,12 @@ static void vulkan_free_internal(AVVkFrame *f) CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); if (internal->ext_mem[i]) CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); +#ifdef _WIN32 + if (internal->ext_sem_handle[i]) + CloseHandle(internal->ext_sem_handle[i]); + if (internal->ext_mem_handle[i]) + CloseHandle(internal->ext_mem_handle[i]); +#endif } av_buffer_unref(&internal->cuda_fc_ref); @@ -1811,12 +1826,22 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkExportSemaphoreCreateInfo ext_sem_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, +#ifdef _WIN32 + .handleTypes = IsWindows8OrGreater() + ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, +#else .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, +#endif }; VkSemaphoreTypeCreateInfo sem_type_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, +#ifdef _WIN32 + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, +#else .pNext = p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, +#endif .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = 0, }; @@ -1947,6 +1972,12 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) .pNext = hwctx->create_pnext, }; +#ifdef _WIN32 + if (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) + try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); +#else if (p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); @@ -1954,6 +1985,7 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); +#endif for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) { eminfo[i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; @@ -2651,6 +2683,43 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, }, .numLevels = 1, }; + 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", + 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], @@ -2669,12 +2738,6 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */, }; - int p_w, p_h; - 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 = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info, &ext_desc.handle.fd); if (ret != VK_SUCCESS) { @@ -2683,14 +2746,21 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, 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], &tex_desc)); @@ -2706,19 +2776,29 @@ 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", 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; } @@ -3544,8 +3624,13 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, switch (src->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif default: @@ -3657,8 +3742,13 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif default: |