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/malloc.c | |
parent | 6fbd933108a74bbd3a375be1456692320a97380e (diff) |
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/malloc.c')
-rw-r--r-- | video/out/vulkan/malloc.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/video/out/vulkan/malloc.c b/video/out/vulkan/malloc.c index 32c2c6b4d0..a68a9342e5 100644 --- a/video/out/vulkan/malloc.c +++ b/video/out/vulkan/malloc.c @@ -2,6 +2,10 @@ #include "utils.h" #include "osdep/timer.h" +#if HAVE_WIN32_DESKTOP +#include <versionhelpers.h> +#endif + // Controls the multiplication factor for new slab allocations. The new slab // will always be allocated such that the size of the slab is this factor times // the previous slab. Higher values make it grow faster. @@ -57,6 +61,7 @@ struct vk_heap { VkBufferUsageFlags usage; // the buffer usage type (or 0) VkMemoryPropertyFlags flags; // the memory type flags (or 0) uint32_t typeBits; // the memory type index requirements (or 0) + bool exportable; // whether memory is exportable to other APIs struct vk_slab **slabs; // array of slabs sorted by size int num_slabs; }; @@ -126,8 +131,20 @@ static struct vk_slab *slab_alloc(struct mpvk_ctx *vk, struct vk_heap *heap, .end = slab->size, }); + VkExportMemoryAllocateInfoKHR eminfo = { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, +#if HAVE_WIN32_DESKTOP + .handleTypes = IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, +#else + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, +#endif + }; + VkMemoryAllocateInfo minfo = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = heap->exportable ? &eminfo : NULL, .allocationSize = slab->size, }; @@ -141,8 +158,14 @@ static struct vk_slab *slab_alloc(struct mpvk_ctx *vk, struct vk_heap *heap, for (int i = 0; i < vk->num_pools; i++) qfs[i] = vk->pools[i]->qf; + VkExternalMemoryBufferCreateInfo ebinfo = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, + .handleTypes = eminfo.handleTypes, + }; + VkBufferCreateInfo binfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = heap->exportable ? &ebinfo : NULL, .size = slab->size, .usage = heap->usage, .sharingMode = vk->num_pools > 1 ? VK_SHARING_MODE_CONCURRENT @@ -292,7 +315,8 @@ void vk_free_memslice(struct mpvk_ctx *vk, struct vk_memslice slice) // reqs: can be NULL static struct vk_heap *find_heap(struct mpvk_ctx *vk, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags, - VkMemoryRequirements *reqs) + VkMemoryRequirements *reqs, + bool exportable) { struct vk_malloc *ma = vk->alloc; int typeBits = reqs ? reqs->memoryTypeBits : 0; @@ -304,6 +328,8 @@ static struct vk_heap *find_heap(struct mpvk_ctx *vk, VkBufferUsageFlags usage, continue; if (ma->heaps[i].typeBits != typeBits) continue; + if (ma->heaps[i].exportable != exportable) + continue; return &ma->heaps[i]; } @@ -314,6 +340,7 @@ static struct vk_heap *find_heap(struct mpvk_ctx *vk, VkBufferUsageFlags usage, .usage = usage, .flags = flags, .typeBits = typeBits, + .exportable = exportable, }; return heap; } @@ -396,6 +423,7 @@ static bool slice_heap(struct mpvk_ctx *vk, struct vk_heap *heap, size_t size, .vkmem = slab->mem, .offset = MP_ALIGN_UP(reg.start, alignment), .size = size, + .slab_size = slab->size, .priv = slab, }; @@ -413,15 +441,24 @@ static bool slice_heap(struct mpvk_ctx *vk, struct vk_heap *heap, size_t size, bool vk_malloc_generic(struct mpvk_ctx *vk, VkMemoryRequirements reqs, VkMemoryPropertyFlags flags, struct vk_memslice *out) { - struct vk_heap *heap = find_heap(vk, 0, flags, &reqs); + struct vk_heap *heap = find_heap(vk, 0, flags, &reqs, false); return slice_heap(vk, heap, reqs.size, reqs.alignment, out); } bool vk_malloc_buffer(struct mpvk_ctx *vk, VkBufferUsageFlags bufFlags, VkMemoryPropertyFlags memFlags, VkDeviceSize size, - VkDeviceSize alignment, struct vk_bufslice *out) + VkDeviceSize alignment, bool exportable, + struct vk_bufslice *out) { - struct vk_heap *heap = find_heap(vk, bufFlags, memFlags, NULL); + if (exportable) { + if (!vk->has_ext_external_memory_export) { + MP_ERR(vk, "Exportable memory requires the %s extension\n", + MP_VK_EXTERNAL_MEMORY_EXPORT_EXTENSION_NAME); + return false; + } + } + + struct vk_heap *heap = find_heap(vk, bufFlags, memFlags, NULL, exportable); if (!slice_heap(vk, heap, size, alignment, &out->mem)) return false; |