aboutsummaryrefslogtreecommitdiffhomepage
path: root/video/out/vulkan/malloc.c
diff options
context:
space:
mode:
authorGravatar Philip Langdale <philipl@overt.org>2018-09-29 17:56:07 -0700
committerGravatar sfan5 <sfan5@live.de>2018-10-22 21:35:48 +0200
commit93f800a00f3f8ef416082e0a3f9d34d979a1e9a6 (patch)
treeb5108b3c2f4f4357adf0f9921c6b59a6c8e162e6 /video/out/vulkan/malloc.c
parent6fbd933108a74bbd3a375be1456692320a97380e (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.c45
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;