llvmpipe: Introduce llvmpipe_memory_allocation

Will be useful for adding sparse info to pipe_memory_allocation.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29408>
This commit is contained in:
Dave Airlie
2023-05-17 17:41:10 +10:00
committed by Marge Bot
parent eb64ce4386
commit 3d159c02f6
7 changed files with 96 additions and 84 deletions

View File

@@ -662,7 +662,7 @@ llvmpipe_resource_from_handle(struct pipe_screen *_screen,
if (whandle->type != WINSYS_HANDLE_TYPE_UNBACKED) {
void *data;
#ifdef HAVE_LINUX_UDMABUF_H
struct llvmpipe_memory_fd_alloc *alloc;
struct llvmpipe_memory_allocation *alloc;
uint64_t size;
/* Not all winsys implement displaytarget_create_mapped so we need to check
* that is available (not null).
@@ -671,7 +671,7 @@ llvmpipe_resource_from_handle(struct pipe_screen *_screen,
_screen->import_memory_fd(_screen, whandle->handle,
(struct pipe_memory_allocation**)&alloc,
&size, true)) {
data = alloc->data;
data = alloc->cpu_addr;
lpr->dt = winsys->displaytarget_create_mapped(winsys, template->bind,
template->format, template->width0, template->height0,
whandle->stride, data);
@@ -740,7 +740,7 @@ llvmpipe_resource_get_handle(struct pipe_screen *_screen,
whandle->modifier = DRM_FORMAT_MOD_LINEAR;
if (!lpr->dt && whandle->type == WINSYS_HANDLE_TYPE_FD) {
if (!lpr->dmabuf_alloc) {
lpr->dmabuf_alloc = (struct llvmpipe_memory_fd_alloc*)_screen->allocate_memory_fd(_screen, lpr->size_required, (int*)&whandle->handle, true);
lpr->dmabuf_alloc = (struct llvmpipe_memory_allocation*)_screen->allocate_memory_fd(_screen, lpr->size_required, (int*)&whandle->handle, true);
if (!lpr->dmabuf_alloc)
return false;
@@ -748,17 +748,17 @@ llvmpipe_resource_get_handle(struct pipe_screen *_screen,
bool is_tex = llvmpipe_resource_is_texture(pt);
if (is_tex) {
if (lpr->tex_data)
memcpy(lpr->dmabuf_alloc->data, lpr->tex_data, lpr->size_required);
memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->tex_data, lpr->size_required);
} else {
if (lpr->data)
memcpy(lpr->dmabuf_alloc->data, lpr->data, lpr->size_required);
memcpy(lpr->dmabuf_alloc->cpu_addr, lpr->data, lpr->size_required);
}
if (!lpr->imported_memory)
align_free(is_tex ? lpr->tex_data : lpr->data);
if (is_tex)
lpr->tex_data = lpr->dmabuf_alloc->data;
lpr->tex_data = lpr->dmabuf_alloc->cpu_addr;
else
lpr->data = lpr->dmabuf_alloc->data;
lpr->data = lpr->dmabuf_alloc->cpu_addr;
/* reuse lavapipe codepath to handle destruction */
lpr->backable = true;
}
@@ -1103,10 +1103,12 @@ llvmpipe_memory_barrier(struct pipe_context *pipe,
static struct pipe_memory_allocation *
llvmpipe_allocate_memory(struct pipe_screen *screen, uint64_t size)
{
struct llvmpipe_memory_allocation *mem = CALLOC_STRUCT(llvmpipe_memory_allocation);
uint64_t alignment;
if (!os_get_page_size(&alignment))
alignment = 256;
return os_malloc_aligned(size, alignment);
mem->cpu_addr = os_malloc_aligned(size, alignment);
return (struct pipe_memory_allocation *)mem;
}
@@ -1121,7 +1123,7 @@ llvmpipe_free_memory(struct pipe_screen *screen,
#ifdef HAVE_LINUX_UDMABUF_H
static void*
llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen *screen,
struct llvmpipe_memory_fd_alloc *alloc,
struct llvmpipe_memory_allocation *alloc,
size_t size)
{
int mem_fd = -1;
@@ -1188,7 +1190,7 @@ llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
int *fd,
bool dmabuf)
{
struct llvmpipe_memory_fd_alloc *alloc = CALLOC_STRUCT(llvmpipe_memory_fd_alloc);
struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
if (!alloc)
goto fail;
@@ -1198,9 +1200,9 @@ llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
if (dmabuf) {
struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
alloc->data = llvmpipe_resource_alloc_udmabuf(screen, alloc, size);
alloc->cpu_addr = llvmpipe_resource_alloc_udmabuf(screen, alloc, size);
if (alloc->data)
if (alloc->cpu_addr)
*fd = os_dupfd_cloexec(alloc->dmabuf_fd);
} else
#endif
@@ -1209,11 +1211,11 @@ llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen,
uint64_t alignment;
if (!os_get_page_size(&alignment))
alignment = 256;
alloc->data = os_malloc_aligned_fd(size, alignment, fd,
alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, fd,
"llvmpipe memory fd", driver_id);
}
if(alloc && !alloc->data) {
if(alloc && !alloc->cpu_addr) {
free(alloc);
alloc = NULL;
}
@@ -1230,22 +1232,22 @@ llvmpipe_import_memory_fd(struct pipe_screen *screen,
uint64_t *size,
bool dmabuf)
{
struct llvmpipe_memory_fd_alloc *alloc = CALLOC_STRUCT(llvmpipe_memory_fd_alloc);
struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation);
alloc->mem_fd = -1;
alloc->dmabuf_fd = -1;
#ifdef HAVE_LINUX_UDMABUF_H
if (dmabuf) {
off_t mmap_size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
void *data = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
void *cpu_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (cpu_addr == MAP_FAILED) {
free(alloc);
*ptr = NULL;
return false;
}
alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF;
alloc->data = data;
alloc->cpu_addr = cpu_addr;
alloc->size = mmap_size;
alloc->dmabuf_fd = os_dupfd_cloexec(fd);
*ptr = (struct pipe_memory_allocation*)alloc;
@@ -1255,7 +1257,7 @@ llvmpipe_import_memory_fd(struct pipe_screen *screen,
} else
#endif
{
bool ret = os_import_memory_fd(fd, (void**)&alloc->data, size, driver_id);
bool ret = os_import_memory_fd(fd, (void**)&alloc->cpu_addr, size, driver_id);
if (!ret) {
free(alloc);
@@ -1274,13 +1276,13 @@ static void
llvmpipe_free_memory_fd(struct pipe_screen *screen,
struct pipe_memory_allocation *pmem)
{
struct llvmpipe_memory_fd_alloc *alloc = (struct llvmpipe_memory_fd_alloc*)pmem;
struct llvmpipe_memory_allocation *alloc = (struct llvmpipe_memory_allocation*)pmem;
if (alloc->type == LLVMPIPE_MEMORY_FD_TYPE_OPAQUE) {
os_free_fd(alloc->data);
os_free_fd(alloc->cpu_addr);
}
#ifdef HAVE_LINUX_UDMABUF_H
else {
munmap(alloc->data, alloc->size);
munmap(alloc->cpu_addr, alloc->size);
if (alloc->dmabuf_fd >= 0)
close(alloc->dmabuf_fd);
if (alloc->mem_fd >= 0)
@@ -1293,6 +1295,20 @@ llvmpipe_free_memory_fd(struct pipe_screen *screen,
#endif
static void *
llvmpipe_map_memory(struct pipe_screen *screen,
struct pipe_memory_allocation *pmem)
{
struct llvmpipe_memory_allocation *mem = (struct llvmpipe_memory_allocation *)pmem;
return mem->cpu_addr;
}
static void
llvmpipe_unmap_memory(struct pipe_screen *screen,
struct pipe_memory_allocation *pmem)
{
}
static bool
llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
struct pipe_resource *pt,
@@ -1303,14 +1319,17 @@ llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
struct sw_winsys *winsys = screen->winsys;
void *addr;
if (!lpr->backable)
return false;
addr = llvmpipe_map_memory(pscreen, pmem);
if (llvmpipe_resource_is_texture(&lpr->base)) {
if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
return false;
lpr->tex_data = (char *)pmem + offset;
lpr->tex_data = (char *)addr + offset;
if (lpr->dmabuf) {
if (lpr->dt)
@@ -1331,27 +1350,13 @@ llvmpipe_resource_bind_backing(struct pipe_screen *pscreen,
}
}
} else
lpr->data = (char *)pmem + offset;
lpr->data = (char *)addr + offset;
lpr->backing_offset = offset;
return true;
}
static void *
llvmpipe_map_memory(struct pipe_screen *screen,
struct pipe_memory_allocation *pmem)
{
return pmem;
}
static void
llvmpipe_unmap_memory(struct pipe_screen *screen,
struct pipe_memory_allocation *pmem)
{
}
#if MESA_DEBUG
void

View File

@@ -58,14 +58,6 @@ struct llvmpipe_screen;
struct sw_displaytarget;
struct llvmpipe_memory_fd_alloc {
void *data;
enum llvmpipe_memory_fd_type type;
int mem_fd;
int dmabuf_fd;
size_t size;
};
/**
* llvmpipe subclass of pipe_resource. A texture, drawing surface,
* vertex buffer, const buffer, etc.
@@ -116,7 +108,7 @@ struct llvmpipe_resource
uint64_t size_required;
uint64_t backing_offset;
#ifdef HAVE_LIBDRM
struct llvmpipe_memory_fd_alloc *dmabuf_alloc;
struct llvmpipe_memory_allocation *dmabuf_alloc;
#endif
bool backable;
bool imported_memory;
@@ -132,6 +124,14 @@ struct llvmpipe_transfer
struct pipe_transfer base;
};
struct llvmpipe_memory_allocation
{
void *cpu_addr;
uint64_t size;
enum llvmpipe_memory_fd_type type;
int mem_fd;
int dmabuf_fd;
};
struct llvmpipe_memory_object
{

View File

@@ -28,6 +28,7 @@
#include "vk_util.h"
#include "util/u_math.h"
#include "util/u_inlines.h"
#include "lp_texture.h"
static bool
binding_has_immutable_samplers(const VkDescriptorSetLayoutBinding *binding)
@@ -250,7 +251,12 @@ get_buffer_resource(struct pipe_context *ctx, const VkDescriptorAddressInfoEXT *
uint64_t size;
struct pipe_resource *pres = pscreen->resource_create_unbacked(pscreen, &templ, &size);
assert(size == bda->range);
pscreen->resource_bind_backing(pscreen, pres, (void *)(uintptr_t)bda->address, 0);
struct llvmpipe_memory_allocation alloc = {
.cpu_addr = (void *)(uintptr_t)bda->address,
};
pscreen->resource_bind_backing(pscreen, pres, (void *)&alloc, 0);
return pres;
}

View File

@@ -1767,7 +1767,7 @@ set_mem_priority(struct lvp_device_memory *mem, int priority)
if (priority > 0)
advice |= MADV_WILLNEED;
if (advice)
madvise(mem->pmem, mem->size, advice);
madvise(mem->map, mem->size, advice);
}
#endif
}
@@ -1844,22 +1844,25 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory(
mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DEFAULT;
mem->backed_fd = -1;
mem->size = pAllocateInfo->allocationSize;
if (host_ptr_info) {
mem->pmem = host_ptr_info->pHostPointer;
mem->mem_alloc = (struct llvmpipe_memory_allocation) {
.cpu_addr = host_ptr_info->pHostPointer,
};
mem->pmem = (void *)&mem->mem_alloc;
mem->map = host_ptr_info->pHostPointer;
mem->memory_type = LVP_DEVICE_MEMORY_TYPE_USER_PTR;
}
#ifdef PIPE_MEMORY_FD
else if(import_info && import_info->handleType) {
bool dmabuf = import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
uint64_t size;
if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, (struct pipe_memory_allocation**)&mem->alloc, &size, dmabuf)) {
if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, &mem->pmem, &size, dmabuf)) {
close(import_info->fd);
error = VK_ERROR_INVALID_EXTERNAL_HANDLE;
goto fail;
}
if(size < pAllocateInfo->allocationSize) {
device->pscreen->free_memory_fd(device->pscreen, (struct pipe_memory_allocation*)mem->alloc);
device->pscreen->free_memory_fd(device->pscreen, mem->pmem);
close(import_info->fd);
goto fail;
}
@@ -1871,17 +1874,17 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory(
}
mem->size = size;
mem->pmem = mem->alloc->data;
mem->map = device->pscreen->map_memory(device->pscreen, mem->pmem);
mem->memory_type = dmabuf ? LVP_DEVICE_MEMORY_TYPE_DMA_BUF : LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD;
}
else if (export_info && export_info->handleTypes) {
bool dmabuf = export_info->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
mem->alloc = (struct llvmpipe_memory_fd_alloc*)device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd, dmabuf);
if (!mem->alloc || mem->backed_fd < 0) {
mem->pmem = device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd, dmabuf);
if (!mem->pmem || mem->backed_fd < 0) {
goto fail;
}
mem->pmem = mem->alloc->data;
mem->map = device->pscreen->map_memory(device->pscreen, mem->pmem);
mem->memory_type = dmabuf ? LVP_DEVICE_MEMORY_TYPE_DMA_BUF : LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD;
}
#endif
@@ -1890,9 +1893,11 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory(
if (!mem->pmem) {
goto fail;
}
if (device->poison_mem)
mem->map = device->pscreen->map_memory(device->pscreen, mem->pmem);
if (device->poison_mem) {
/* this is a value that will definitely break things */
memset(mem->pmem, UINT8_MAX / 2 + 1, pAllocateInfo->allocationSize);
memset(mem->map, UINT8_MAX / 2 + 1, pAllocateInfo->allocationSize);
}
set_mem_priority(mem, priority);
}
@@ -1918,6 +1923,9 @@ VKAPI_ATTR void VKAPI_CALL lvp_FreeMemory(
if (mem == NULL)
return;
if (mem->memory_type != LVP_DEVICE_MEMORY_TYPE_USER_PTR)
device->pscreen->unmap_memory(device->pscreen, mem->pmem);
switch(mem->memory_type) {
case LVP_DEVICE_MEMORY_TYPE_DEFAULT:
device->pscreen->free_memory(device->pscreen, mem->pmem);
@@ -1925,7 +1933,7 @@ VKAPI_ATTR void VKAPI_CALL lvp_FreeMemory(
#ifdef PIPE_MEMORY_FD
case LVP_DEVICE_MEMORY_TYPE_DMA_BUF:
case LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD:
device->pscreen->free_memory_fd(device->pscreen, (struct pipe_memory_allocation*)mem->alloc);
device->pscreen->free_memory_fd(device->pscreen, mem->pmem);
if(mem->backed_fd >= 0)
close(mem->backed_fd);
break;
@@ -1944,17 +1952,14 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_MapMemory2KHR(
const VkMemoryMapInfoKHR* pMemoryMapInfo,
void** ppData)
{
LVP_FROM_HANDLE(lvp_device, device, _device);
LVP_FROM_HANDLE(lvp_device_memory, mem, pMemoryMapInfo->memory);
void *map;
if (mem == NULL) {
*ppData = NULL;
return VK_SUCCESS;
}
map = device->pscreen->map_memory(device->pscreen, mem->pmem);
*ppData = (char *)map + pMemoryMapInfo->offset;
*ppData = (char *)mem->map + pMemoryMapInfo->offset;
return VK_SUCCESS;
}
@@ -1962,13 +1967,6 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_UnmapMemory2KHR(
VkDevice _device,
const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo)
{
LVP_FROM_HANDLE(lvp_device, device, _device);
LVP_FROM_HANDLE(lvp_device_memory, mem, pMemoryUnmapInfo->memory);
if (mem == NULL)
return VK_SUCCESS;
device->pscreen->unmap_memory(device->pscreen, mem->pmem);
return VK_SUCCESS;
}
@@ -2147,7 +2145,8 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_BindBufferMemory2(VkDevice _device,
LVP_FROM_HANDLE(lvp_buffer, buffer, pBindInfos[i].buffer);
VkBindMemoryStatusKHR *status = (void*)vk_find_struct_const(&pBindInfos[i], BIND_MEMORY_STATUS_KHR);
buffer->pmem = mem->pmem;
buffer->mem = mem;
buffer->map = (char*)mem->map + pBindInfos[i].memoryOffset;
buffer->offset = pBindInfos[i].memoryOffset;
device->pscreen->resource_bind_backing(device->pscreen,
buffer->bo,

View File

@@ -227,7 +227,12 @@ get_buffer_resource(struct pipe_context *ctx, void *mem)
uint64_t size;
struct pipe_resource *pres = pscreen->resource_create_unbacked(pscreen, &templ, &size);
pscreen->resource_bind_backing(pscreen, pres, mem, 0);
struct llvmpipe_memory_allocation alloc = {
.cpu_addr = mem,
};
pscreen->resource_bind_backing(pscreen, pres, (void *)&alloc, 0);
return pres;
}

View File

@@ -560,10 +560,9 @@ VKAPI_ATTR void VKAPI_CALL lvp_DestroyBuffer(
if (!_buffer)
return;
char *ptr = (char*)buffer->pmem + buffer->offset;
if (ptr) {
if (buffer->map) {
simple_mtx_lock(&device->bda_lock);
struct hash_entry *he = _mesa_hash_table_search(&device->bda, ptr);
struct hash_entry *he = _mesa_hash_table_search(&device->bda, buffer->map);
if (he)
_mesa_hash_table_remove(&device->bda, he);
simple_mtx_unlock(&device->bda_lock);
@@ -578,12 +577,11 @@ VKAPI_ATTR VkDeviceAddress VKAPI_CALL lvp_GetBufferDeviceAddress(
{
LVP_FROM_HANDLE(lvp_device, device, _device);
LVP_FROM_HANDLE(lvp_buffer, buffer, pInfo->buffer);
char *ptr = (char*)buffer->pmem + buffer->offset;
simple_mtx_lock(&device->bda_lock);
_mesa_hash_table_insert(&device->bda, ptr, buffer);
_mesa_hash_table_insert(&device->bda, buffer->map, buffer);
simple_mtx_unlock(&device->bda_lock);
return (VkDeviceAddress)(uintptr_t)ptr;
return (VkDeviceAddress)(uintptr_t)buffer->map;
}
VKAPI_ATTR uint64_t VKAPI_CALL lvp_GetBufferOpaqueCaptureAddress(

View File

@@ -230,15 +230,13 @@ enum lvp_device_memory_type {
struct lvp_device_memory {
struct vk_object_base base;
struct pipe_memory_allocation *pmem;
struct llvmpipe_memory_allocation mem_alloc;
uint32_t type_index;
VkDeviceSize map_size;
VkDeviceSize size;
void * map;
enum lvp_device_memory_type memory_type;
int backed_fd;
#ifdef PIPE_MEMORY_FD
struct llvmpipe_memory_fd_alloc *alloc;
#endif
};
struct lvp_pipe_sync {
@@ -579,10 +577,11 @@ struct lvp_event {
struct lvp_buffer {
struct vk_buffer vk;
struct pipe_memory_allocation *pmem;
struct lvp_device_memory *mem;
struct pipe_resource *bo;
uint64_t total_size;
uint64_t offset;
void *map;
};
struct lvp_buffer_view {