Mesa (master): vc4: Restructure the simulator mode.

Eric Anholt anholt at kemper.freedesktop.org
Fri Oct 21 21:12:56 UTC 2016


Module: Mesa
Branch: master
Commit: 78087676c98aa8884ba92e75a0a5306a8f78ad43
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=78087676c98aa8884ba92e75a0a5306a8f78ad43

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Oct 11 16:47:58 2016 -0700

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.

---

 src/gallium/drivers/vc4/vc4_bufmgr.c    |  98 +++++++---------------
 src/gallium/drivers/vc4/vc4_context.h   |  11 +++
 src/gallium/drivers/vc4/vc4_program.c   |   3 -
 src/gallium/drivers/vc4/vc4_screen.c    |  15 +---
 src/gallium/drivers/vc4/vc4_simulator.c | 139 ++++++++++++++++++++++++++++++++
 5 files changed, 182 insertions(+), 84 deletions(-)

diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c
index cf6a511..350761e 100644
--- a/src/gallium/drivers/vc4/vc4_bufmgr.c
+++ b/src/gallium/drivers/vc4/vc4_bufmgr.c
@@ -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));
-
-                create.size = size;
-
-                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);
-        }
+        struct drm_vc4_create_bo create = {
+                .size = size
+        };
+
+        ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_CREATE_BO, &create);
+        bo->handle = create.handle;
+
         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,
-                };
-
-                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));
-
-                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);
-        }
+        struct drm_vc4_create_shader_bo create = {
+                .size = size,
+                .data = (uintptr_t)data,
+        };
+
+        ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_CREATE_SHADER_BO,
+                        &create);
+        bo->handle = create.handle;
+
         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();
diff --git a/src/gallium/drivers/vc4/vc4_context.h b/src/gallium/drivers/vc4/vc4_context.h
index 313630a..249caeb 100644
--- a/src/gallium/drivers/vc4/vc4_context.h
+++ b/src/gallium/drivers/vc4/vc4_context.h
@@ -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,
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 81ac070..c0d956c 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -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);
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c
index 72fd09a..37bca30 100644
--- a/src/gallium/drivers/vc4/vc4_screen.c
+++ b/src/gallium/drivers/vc4/vc4_screen.c
@@ -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));
diff --git a/src/gallium/drivers/vc4/vc4_simulator.c b/src/gallium/drivers/vc4/vc4_simulator.c
index 0291a4e..76896c0 100644
--- a/src/gallium/drivers/vc4/vc4_simulator.c
+++ b/src/gallium/drivers/vc4/vc4_simulator.c
@@ -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;




More information about the mesa-commit mailing list