diff options
author | Philip Langdale <philipl@overt.org> | 2018-09-29 17:56:07 -0700 |
---|---|---|
committer | sfan5 <sfan5@live.de> | 2018-10-22 21:35:48 +0200 |
commit | 93f800a00f3f8ef416082e0a3f9d34d979a1e9a6 (patch) | |
tree | b5108b3c2f4f4357adf0f9921c6b59a6c8e162e6 /video/out/vulkan/ra_vk.c | |
parent | 6fbd933108a74bbd3a375be1456692320a97380e (diff) | |
download | mpv-93f800a00f3f8ef416082e0a3f9d34d979a1e9a6.tar.bz2 mpv-93f800a00f3f8ef416082e0a3f9d34d979a1e9a6.tar.xz |
vo_gpu: vulkan: Add support for exporting buffer memory
The CUDA/Vulkan interop works on the basis of memory being exported
from Vulkan and then imported by CUDA. To enable this, we add a way
to declare a buffer as being intended for export, and then add a
function to do the export.
For now, we support the fd and Handle based exports on Linux and
Windows respectively. There are others, which we can support when
a need arises.
Also note that this is just for exporting buffers, rather than
textures (VkImages). Image import on the CUDA side is supposed to
work, but it is currently buggy and waiting for a new driver release.
Finally, at least with my nvidia hardware and drivers, everything
seems to work even if we don't initialise the buffer with the right
exportability options. Nevertheless I'm enforcing it so that we're
following the spec.
Diffstat (limited to 'video/out/vulkan/ra_vk.c')
-rw-r--r-- | video/out/vulkan/ra_vk.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/video/out/vulkan/ra_vk.c b/video/out/vulkan/ra_vk.c index 236287d7d3..1548b8c785 100644 --- a/video/out/vulkan/ra_vk.c +++ b/video/out/vulkan/ra_vk.c @@ -4,6 +4,10 @@ #include "ra_vk.h" #include "malloc.h" +#if HAVE_WIN32_DESKTOP +#include <versionhelpers.h> +#endif + static struct ra_fns ra_fns_vk; enum queue_type { @@ -787,6 +791,7 @@ static struct ra_buf *vk_buf_create(struct ra *ra, VkBufferUsageFlags bufFlags = 0; VkMemoryPropertyFlags memFlags = 0; VkDeviceSize align = 4; // alignment 4 is needed for buf_update + bool exportable = false; switch (params->type) { case RA_BUF_TYPE_TEX_UPLOAD: @@ -811,6 +816,11 @@ static struct ra_buf *vk_buf_create(struct ra *ra, bufFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; memFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; break; + case RA_BUF_TYPE_SHARED_MEMORY: + bufFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + memFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + exportable = true; + break; default: abort(); } @@ -826,7 +836,7 @@ static struct ra_buf *vk_buf_create(struct ra *ra, } if (!vk_malloc_buffer(vk, bufFlags, memFlags, params->size, align, - &buf_vk->slice)) + exportable, &buf_vk->slice)) { goto error; } @@ -916,6 +926,64 @@ error: return false; } +static bool ra_vk_mem_get_external_info(struct ra *ra, struct vk_memslice *mem, struct vk_external_mem *ret) +{ + struct mpvk_ctx *vk = ra_vk_get(ra); + +#if HAVE_WIN32_DESKTOP + HANDLE mem_handle; + + VkMemoryGetWin32HandleInfoKHR info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, + .pNext = NULL, + .memory = mem->vkmem, + .handleType = IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + }; + + VK_LOAD_PFN(vkGetMemoryWin32HandleKHR); + VK(pfn_vkGetMemoryWin32HandleKHR(vk->dev, &info, &mem_handle)); + + ret->mem_handle = mem_handle; +#else + int mem_fd; + + VkMemoryGetFdInfoKHR info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, + .pNext = NULL, + .memory = mem->vkmem, + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, + }; + + VK_LOAD_PFN(vkGetMemoryFdKHR); + VK(pfn_vkGetMemoryFdKHR(vk->dev, &info, &mem_fd)); + + ret->mem_fd = mem_fd; +#endif + ret->size = mem->size; + ret->offset = mem->offset; + ret->mem_size = mem->slab_size; + + return true; + +error: + return false; +} + +bool ra_vk_buf_get_external_info(struct ra *ra, struct ra_buf *buf, struct vk_external_mem *ret) +{ + if (buf->params.type != RA_BUF_TYPE_SHARED_MEMORY) { + MP_ERR(ra, "Buffer must be of TYPE_SHARED_MEMORY to be able to export it..."); + return false; + } + + struct ra_buf_vk *buf_vk = buf->priv; + struct vk_memslice *mem = &buf_vk->slice.mem; + + return ra_vk_mem_get_external_info(ra, mem, ret); +} + #define MPVK_NUM_DS MPVK_MAX_STREAMING_DEPTH // For ra_renderpass.priv |