termux-packages/packages/mesa-vulkan-icd-freedreno-dri3/tu_kgsl_export_dmabuf.patch

193 lines
5.4 KiB
Diff

diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index f892fcedcb3..0a5c4dd7a49 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -2624,6 +2624,14 @@ tu_AllocateMemory(VkDevice _device,
uint64_t client_address = 0;
BITMASK_ENUM(tu_bo_alloc_flags) alloc_flags = TU_BO_ALLOC_NO_FLAGS;
+ const VkExportMemoryAllocateInfo *export_info = vk_find_struct_const(
+ pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+ if (export_info && (export_info->handleTypes &
+ (VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT))) {
+ alloc_flags |= TU_BO_ALLOC_SHAREABLE;
+ }
+
const VkMemoryOpaqueCaptureAddressAllocateInfo *replay_info =
vk_find_struct_const(pAllocateInfo->pNext,
MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO);
diff --git a/src/freedreno/vulkan/tu_knl.h b/src/freedreno/vulkan/tu_knl.h
index 78cb442dc93..264000c5ea8 100644
--- a/src/freedreno/vulkan/tu_knl.h
+++ b/src/freedreno/vulkan/tu_knl.h
@@ -21,6 +21,7 @@ enum tu_bo_alloc_flags
TU_BO_ALLOC_ALLOW_DUMP = 1 << 0,
TU_BO_ALLOC_GPU_READ_ONLY = 1 << 1,
TU_BO_ALLOC_REPLAYABLE = 1 << 2,
+ TU_BO_ALLOC_SHAREABLE = 1 << 3,
};
/* Define tu_timeline_sync type based on drm syncobj for a point type
@@ -53,6 +54,7 @@ struct tu_bo {
uint32_t bo_list_idx;
bool implicit_sync : 1;
+ int dmabuf_fd;
};
struct tu_knl {
diff --git a/src/freedreno/vulkan/tu_knl_kgsl.cc b/src/freedreno/vulkan/tu_knl_kgsl.cc
index 0c2f16c496c..6a484d83a47 100644
--- a/src/freedreno/vulkan/tu_knl_kgsl.cc
+++ b/src/freedreno/vulkan/tu_knl_kgsl.cc
@@ -11,6 +11,7 @@
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <linux/dma-heap.h>
#include "msm_kgsl.h"
#include "vk_util.h"
@@ -18,6 +19,7 @@
#include "util/u_debug.h"
#include "util/u_vector.h"
#include "util/libsync.h"
+#include "util/os_file.h"
#include "util/timespec.h"
#include "tu_cmd_buffer.h"
@@ -67,6 +69,57 @@ kgsl_submitqueue_close(struct tu_device *dev, uint32_t queue_id)
safe_ioctl(dev->physical_device->local_fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req);
}
+static int
+dmabuf_alloc(uint64_t size)
+{
+ int ret;
+ int dma_heap = open("/dev/dma_heap/system", O_RDONLY);
+
+ if (dma_heap < 0) {
+ int ion_heap = open("/dev/ion", O_RDONLY);
+
+ if (ion_heap < 0)
+ return -1;
+
+ struct ion_allocation_data {
+ __u64 len;
+ __u32 heap_id_mask;
+ __u32 flags;
+ __u32 fd;
+ __u32 unused;
+ } alloc_data = {
+ .len = size,
+ /* ION_HEAP_SYSTEM | ION_SYSTEM_HEAP_ID */
+ .heap_id_mask = (1U << 0) | (1U << 25),
+ .flags = 0, /* uncached */
+ };
+
+ ret = safe_ioctl(ion_heap, _IOWR('I', 0, struct ion_allocation_data),
+ &alloc_data);
+
+ close(ion_heap);
+
+ if (ret)
+ return -1;
+
+ return alloc_data.fd;
+ } else {
+ struct dma_heap_allocation_data alloc_data = {
+ .len = size,
+ .fd_flags = O_RDWR | O_CLOEXEC,
+ };
+
+ ret = safe_ioctl(dma_heap, DMA_HEAP_IOCTL_ALLOC, &alloc_data);
+
+ close(dma_heap);
+
+ if (ret)
+ return -1;
+
+ return alloc_data.fd;
+ }
+}
+
static VkResult
kgsl_bo_init(struct tu_device *dev,
struct tu_bo **out_bo,
@@ -78,6 +131,21 @@ kgsl_bo_init(struct tu_device *dev,
{
assert(client_iova == 0);
+ if (flags & TU_BO_ALLOC_SHAREABLE) {
+ int fd = dmabuf_alloc(size);
+
+ if (fd < 0) {
+ return vk_errorf(dev, VK_ERROR_OUT_OF_DEVICE_MEMORY,
+ "DMABUF_ALLOC failed (%s)", strerror(errno));
+ }
+
+ VkResult res = tu_bo_init_dmabuf(dev, out_bo, size, fd);
+
+ close(fd);
+
+ return res;
+ }
+
struct kgsl_gpumem_alloc_id req = {
.size = size,
};
@@ -113,6 +181,7 @@ kgsl_bo_init(struct tu_device *dev,
.iova = req.gpuaddr,
.name = tu_debug_bos_add(dev, req.mmapsize, name),
.refcnt = 1,
+ .dmabuf_fd = -1,
};
*out_bo = bo;
@@ -162,6 +231,7 @@ kgsl_bo_init_dmabuf(struct tu_device *dev,
.iova = info_req.gpuaddr,
.name = tu_debug_bos_add(dev, info_req.size, "dmabuf"),
.refcnt = 1,
+ .dmabuf_fd = os_dupfd_cloexec(fd),
};
*out_bo = bo;
@@ -172,9 +242,7 @@ kgsl_bo_init_dmabuf(struct tu_device *dev,
static int
kgsl_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
{
- tu_stub();
-
- return -1;
+ return os_dupfd_cloexec(bo->dmabuf_fd);
}
static VkResult
@@ -183,6 +251,15 @@ kgsl_bo_map(struct tu_device *dev, struct tu_bo *bo)
if (bo->map)
return VK_SUCCESS;
+ if (bo->dmabuf_fd != -1) {
+ void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->dmabuf_fd, 0);
+
+ if (map != MAP_FAILED) {
+ bo->map = map;
+ return VK_SUCCESS;
+ }
+ }
+
uint64_t offset = bo->gem_handle << 12;
void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
dev->physical_device->local_fd, offset);
@@ -210,6 +287,9 @@ kgsl_bo_finish(struct tu_device *dev, struct tu_bo *bo)
if (bo->map)
munmap(bo->map, bo->size);
+ if (bo->dmabuf_fd != -1)
+ close(bo->dmabuf_fd);
+
struct kgsl_gpumem_free_id req = {
.id = bo->gem_handle
};