vc4: Restructure the simulator mode.

Rather than having simulator mode changes scattered around vc4_bufmgr.c
and vc4_screen.c, make vc4_bufmgr.c just call a vc4_simulator_ioctl, which
then dispatches to a corresponding implementation.

This will give the simulator support a centralized place to do tricks like
storing most BOs directly in simulator memory rather than copying in and
out.

This leaves special casing of mmaping BOs and execution, because of the
winsys mapping.
This commit is contained in:
Eric Anholt 2016-10-11 16:47:58 -07:00
parent 1d7874fa7b
commit 78087676c9
5 changed files with 178 additions and 80 deletions

View file

@ -148,28 +148,17 @@ vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name)
bo->name = name;
bo->private = true;
retry:
;
bool cleared_and_retried = false;
retry:
if (!using_vc4_simulator) {
struct drm_vc4_create_bo create;
memset(&create, 0, sizeof(create));
struct drm_vc4_create_bo create = {
.size = size
};
create.size = size;
ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_CREATE_BO, &create);
bo->handle = create.handle;
ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_CREATE_BO, &create);
bo->handle = create.handle;
} else {
struct drm_mode_create_dumb create;
memset(&create, 0, sizeof(create));
create.width = 128;
create.bpp = 8;
create.height = (size + 127) / 128;
ret = drmIoctl(screen->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
bo->handle = create.handle;
assert(create.size >= size);
}
if (ret != 0) {
if (!list_empty(&screen->bo_cache.time_list) &&
!cleared_and_retried) {
@ -223,7 +212,7 @@ vc4_bo_free(struct vc4_bo *bo)
struct drm_gem_close c;
memset(&c, 0, sizeof(c));
c.handle = bo->handle;
int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c);
int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c);
if (ret != 0)
fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno));
@ -380,7 +369,7 @@ vc4_bo_open_name(struct vc4_screen *screen, uint32_t name,
struct drm_gem_open o = {
.name = name
};
int ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o);
int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_OPEN, &o);
if (ret) {
fprintf(stderr, "Failed to open bo %d: %s\n",
name, strerror(errno));
@ -447,30 +436,15 @@ vc4_bo_alloc_shader(struct vc4_screen *screen, const void *data, uint32_t size)
bo->name = "code";
bo->private = false; /* Make sure it doesn't go back to the cache. */
if (!using_vc4_simulator) {
struct drm_vc4_create_shader_bo create = {
.size = size,
.data = (uintptr_t)data,
};
struct drm_vc4_create_shader_bo create = {
.size = size,
.data = (uintptr_t)data,
};
ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_CREATE_SHADER_BO,
&create);
bo->handle = create.handle;
} else {
struct drm_mode_create_dumb create;
memset(&create, 0, sizeof(create));
ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_CREATE_SHADER_BO,
&create);
bo->handle = create.handle;
create.width = 128;
create.bpp = 8;
create.height = (size + 127) / 128;
ret = drmIoctl(screen->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
bo->handle = create.handle;
assert(create.size >= size);
vc4_bo_map(bo);
memcpy(bo->map, data, size);
}
if (ret != 0) {
fprintf(stderr, "create shader ioctl failure\n");
abort();
@ -492,7 +466,7 @@ vc4_bo_flink(struct vc4_bo *bo, uint32_t *name)
struct drm_gem_flink flink = {
.handle = bo->handle,
};
int ret = drmIoctl(bo->screen->fd, DRM_IOCTL_GEM_FLINK, &flink);
int ret = vc4_ioctl(bo->screen->fd, DRM_IOCTL_GEM_FLINK, &flink);
if (ret) {
fprintf(stderr, "Failed to flink bo %d: %s\n",
bo->handle, strerror(errno));
@ -508,14 +482,11 @@ vc4_bo_flink(struct vc4_bo *bo, uint32_t *name)
static int vc4_wait_seqno_ioctl(int fd, uint64_t seqno, uint64_t timeout_ns)
{
if (using_vc4_simulator)
return 0;
struct drm_vc4_wait_seqno wait = {
.seqno = seqno,
.timeout_ns = timeout_ns,
};
int ret = drmIoctl(fd, DRM_IOCTL_VC4_WAIT_SEQNO, &wait);
int ret = vc4_ioctl(fd, DRM_IOCTL_VC4_WAIT_SEQNO, &wait);
if (ret == -1)
return -errno;
else
@ -553,14 +524,11 @@ vc4_wait_seqno(struct vc4_screen *screen, uint64_t seqno, uint64_t timeout_ns,
static int vc4_wait_bo_ioctl(int fd, uint32_t handle, uint64_t timeout_ns)
{
if (using_vc4_simulator)
return 0;
struct drm_vc4_wait_bo wait = {
.handle = handle,
.timeout_ns = timeout_ns,
};
int ret = drmIoctl(fd, DRM_IOCTL_VC4_WAIT_BO, &wait);
int ret = vc4_ioctl(fd, DRM_IOCTL_VC4_WAIT_BO, &wait);
if (ret == -1)
return -errno;
else
@ -602,19 +570,11 @@ vc4_bo_map_unsynchronized(struct vc4_bo *bo)
if (bo->map)
return bo->map;
if (!using_vc4_simulator) {
struct drm_vc4_mmap_bo map;
memset(&map, 0, sizeof(map));
map.handle = bo->handle;
ret = drmIoctl(bo->screen->fd, DRM_IOCTL_VC4_MMAP_BO, &map);
offset = map.offset;
} else {
struct drm_mode_map_dumb map;
memset(&map, 0, sizeof(map));
map.handle = bo->handle;
ret = drmIoctl(bo->screen->fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
offset = map.offset;
}
struct drm_vc4_mmap_bo map;
memset(&map, 0, sizeof(map));
map.handle = bo->handle;
ret = vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_MMAP_BO, &map);
offset = map.offset;
if (ret != 0) {
fprintf(stderr, "map ioctl failure\n");
abort();

View file

@ -30,6 +30,7 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/slab.h"
#include "xf86drm.h"
#define __user
#include "vc4_drm.h"
@ -427,6 +428,16 @@ void vc4_simulator_destroy(struct vc4_screen *screen);
int vc4_simulator_flush(struct vc4_context *vc4,
struct drm_vc4_submit_cl *args,
struct vc4_job *job);
int vc4_simulator_ioctl(int fd, unsigned long request, void *arg);
static inline int
vc4_ioctl(int fd, unsigned long request, void *arg)
{
if (using_vc4_simulator)
return vc4_simulator_ioctl(fd, request, arg);
else
return drmIoctl(fd, request, arg);
}
void vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader);
void vc4_write_uniforms(struct vc4_context *vc4,

View file

@ -38,9 +38,6 @@
#include "vc4_qpu.h"
#include "vc4_qir.h"
#include "mesa/state_tracker/st_glsl_types.h"
#ifdef USE_VC4_SIMULATOR
#include "simpenrose/simpenrose.h"
#endif
static struct qreg
ntq_get_src(struct vc4_compile *c, nir_src src, int i);

View file

@ -528,14 +528,10 @@ static int handle_compare(void *key1, void *key2)
static bool
vc4_supports_branches(struct vc4_screen *screen)
{
#if USE_VC4_SIMULATOR
return true;
#endif
struct drm_vc4_get_param p = {
.param = DRM_VC4_PARAM_SUPPORTS_BRANCHES,
};
int ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
if (ret != 0)
return false;
@ -546,11 +542,6 @@ vc4_supports_branches(struct vc4_screen *screen)
static bool
vc4_get_chip_info(struct vc4_screen *screen)
{
#if USE_VC4_SIMULATOR
screen->v3d_ver = 21;
return true;
#endif
struct drm_vc4_get_param ident0 = {
.param = DRM_VC4_PARAM_V3D_IDENT0,
};
@ -559,7 +550,7 @@ vc4_get_chip_info(struct vc4_screen *screen)
};
int ret;
ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident0);
ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident0);
if (ret != 0) {
if (errno == EINVAL) {
/* Backwards compatibility with 2835 kernels which
@ -573,7 +564,7 @@ vc4_get_chip_info(struct vc4_screen *screen)
return false;
}
}
ret = drmIoctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident1);
ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &ident1);
if (ret != 0) {
fprintf(stderr, "Couldn't get V3D IDENT1: %s\n",
strerror(errno));

View file

@ -23,6 +23,8 @@
#ifdef USE_VC4_SIMULATOR
#include <sys/mman.h>
#include "xf86drm.h"
#include "util/u_memory.h"
#include "util/ralloc.h"
@ -320,6 +322,143 @@ vc4_simulator_flush(struct vc4_context *vc4,
return 0;
}
/**
* Simulated ioctl(fd, DRM_VC4_CREATE_BO) implementation.
*
* Making a VC4 BO is just a matter of making a corresponding BO on the host.
*/
static int
vc4_simulator_create_bo_ioctl(int fd, struct drm_vc4_create_bo *args)
{
int ret;
struct drm_mode_create_dumb create = {
.width = 128,
.bpp = 8,
.height = (args->size + 127) / 128,
};
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
assert(create.size >= args->size);
args->handle = create.handle;
return ret;
}
/**
* Simulated ioctl(fd, DRM_VC4_CREATE_SHADER_BO) implementation.
*
* In simulation we defer shader validation until exec time. Just make a host
* BO and memcpy the contents in.
*/
static int
vc4_simulator_create_shader_bo_ioctl(int fd,
struct drm_vc4_create_shader_bo *args)
{
int ret;
struct drm_mode_create_dumb create = {
.width = 128,
.bpp = 8,
.height = (args->size + 127) / 128,
};
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
if (ret)
return ret;
assert(create.size >= args->size);
args->handle = create.handle;
struct drm_mode_map_dumb map = {
.handle = create.handle
};
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
if (ret)
return ret;
void *shader = mmap(NULL, args->size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, map.offset);
memcpy(shader, (void *)(uintptr_t)args->data, args->size);
munmap(shader, args->size);
return 0;
}
/**
* Simulated ioctl(fd, DRM_VC4_MMAP_BO) implementation.
*
* We just pass this straight through to dumb mmap.
*/
static int
vc4_simulator_mmap_bo_ioctl(int fd, struct drm_vc4_mmap_bo *args)
{
int ret;
struct drm_mode_map_dumb map = {
.handle = args->handle,
};
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
args->offset = map.offset;
return ret;
}
static int
vc4_simulator_get_param_ioctl(int fd, struct drm_vc4_get_param *args)
{
switch (args->param) {
case DRM_VC4_PARAM_SUPPORTS_BRANCHES:
args->value = true;
return 0;
case DRM_VC4_PARAM_V3D_IDENT0:
args->value = 0x02000000;
return 0;
case DRM_VC4_PARAM_V3D_IDENT1:
args->value = 0x00000001;
return 0;
default:
fprintf(stderr, "Unknown DRM_IOCTL_VC4_GET_PARAM(%lld)\n",
(long long)args->value);
abort();
};
}
int
vc4_simulator_ioctl(int fd, unsigned long request, void *args)
{
switch (request) {
case DRM_IOCTL_VC4_CREATE_BO:
return vc4_simulator_create_bo_ioctl(fd, args);
case DRM_IOCTL_VC4_CREATE_SHADER_BO:
return vc4_simulator_create_shader_bo_ioctl(fd, args);
case DRM_IOCTL_VC4_MMAP_BO:
return vc4_simulator_mmap_bo_ioctl(fd, args);
case DRM_IOCTL_VC4_WAIT_BO:
case DRM_IOCTL_VC4_WAIT_SEQNO:
/* We do all of the vc4 rendering synchronously, so we just
* return immediately on the wait ioctls. This ignores any
* native rendering to the host BO, so it does mean we race on
* front buffer rendering.
*/
return 0;
case DRM_IOCTL_VC4_GET_PARAM:
return vc4_simulator_get_param_ioctl(fd, args);
case DRM_IOCTL_GEM_OPEN:
case DRM_IOCTL_GEM_CLOSE:
case DRM_IOCTL_GEM_FLINK:
return drmIoctl(fd, request, args);
default:
fprintf(stderr, "Unknown ioctl 0x%08x\n", (int)request);
abort();
}
}
static void *sim_mem_base = NULL;
static int sim_mem_refcount = 0;
static ssize_t sim_mem_size = 256 * 1024 * 1024;