v3dv: implement vkMapMemory

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga 2019-12-04 12:21:35 +01:00 committed by Marge Bot
parent d1d97ea746
commit cff9f08d31
1 changed files with 89 additions and 2 deletions

View File

@ -1053,6 +1053,79 @@ device_free(struct v3dv_device *device, struct v3dv_device_memory *mem)
fprintf(stderr, "close object %d: %s\n", mem->handle, strerror(errno));
}
static VkResult
device_map_unsynchronized(struct v3dv_device *device,
struct v3dv_device_memory *mem,
uint32_t size)
{
assert(mem != NULL && size < mem->size);
/* From the spec:
*
* "After a successful call to vkMapMemory the memory object memory is
* considered to be currently host mapped. It is an application error to
* call vkMapMemory on a memory object that is already host mapped."
*/
assert(mem->map = NULL);
struct drm_v3d_mmap_bo map;
memset(&map, 0, sizeof(map));
map.handle = mem->handle;
int ret = v3dv_ioctl(device->fd, DRM_IOCTL_V3D_MMAP_BO, &map);
if (ret != 0) {
fprintf(stderr, "map ioctl failure\n");
return VK_ERROR_MEMORY_MAP_FAILED;
}
mem->map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
device->fd, map.offset);
if (mem->map == MAP_FAILED) {
fprintf(stderr, "mmap of bo %d (offset 0x%016llx, size %d) failed\n",
mem->handle, (long long)map.offset, (uint32_t)mem->size);
return VK_ERROR_MEMORY_MAP_FAILED;
}
VG(VALGRIND_MALLOCLIKE_BLOCK(mem->map, mem->size, 0, false));
mem->map_size = size;
return VK_SUCCESS;
}
static bool
device_memory_wait(struct v3dv_device *device,
struct v3dv_device_memory *mem,
uint64_t timeout_ns)
{
struct drm_v3d_wait_bo wait = {
.handle = mem->handle,
.timeout_ns = timeout_ns,
};
int ret = v3dv_ioctl(device->fd, DRM_IOCTL_V3D_WAIT_BO, &wait);
if (ret == -1)
return -errno;
else
return 0;
}
static VkResult
device_map(struct v3dv_device *device,
struct v3dv_device_memory *mem,
uint32_t size)
{
VkResult result = device_map_unsynchronized(device, mem, size);
if (result != VK_SUCCESS)
return result;
const uint64_t infinite = 0xffffffffffffffffull;
bool ok = device_memory_wait(device, mem, infinite);
if (!ok) {
fprintf(stderr, "memory wait for map failed\n");
return VK_ERROR_MEMORY_MAP_FAILED;
}
return VK_SUCCESS;
}
VkResult
v3dv_AllocateMemory(VkDevice _device,
const VkMemoryAllocateInfo *pAllocateInfo,
@ -1117,9 +1190,23 @@ v3dv_MapMemory(VkDevice _device,
return VK_SUCCESS;
}
/* FIXME: stub */
assert(offset < mem->size);
return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
/* We always map from the beginning of the region, so if our offset
* is not 0 and we are not mapping the entire region, we need to
* add the offset to the map size.
*/
if (size == VK_WHOLE_SIZE)
size = mem->size;
else if (offset > 0)
size += offset;
VkResult result = device_map(device, mem, size);
if (result != VK_SUCCESS)
return vk_error(device->instance, result);
*ppData = ((uint8_t *) mem->map) + offset;
return VK_SUCCESS;
}
void