v3d: Add the V3D TFU submit interface to the simulator.
authorEric Anholt <eric@anholt.net>
Thu, 1 Nov 2018 23:10:01 +0000 (16:10 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 8 Dec 2018 00:48:23 +0000 (16:48 -0800)
The TFU lets us format raster and SAND images into formats that can be
read by the texture engine, and do mipmap generation.

The UAPI comes from drm-next e69aa5f9b97f ("Merge tag
'drm-misc-next-2018-12-06' of git://anongit.freedesktop.org/drm/drm-misc
into drm-next")

include/drm-uapi/v3d_drm.h
src/gallium/drivers/v3d/v3d_simulator.c
src/gallium/drivers/v3d/v3dx_context.h
src/gallium/drivers/v3d/v3dx_simulator.c

index 7b6627783608edb92cc6fbfe7c9932a5766e6e8b..35c7d813c66e297d3814710d7bfddbf05b2c346c 100644 (file)
@@ -36,6 +36,7 @@ extern "C" {
 #define DRM_V3D_MMAP_BO                           0x03
 #define DRM_V3D_GET_PARAM                         0x04
 #define DRM_V3D_GET_BO_OFFSET                     0x05
+#define DRM_V3D_SUBMIT_TFU                        0x06
 
 #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
 #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -43,6 +44,7 @@ extern "C" {
 #define DRM_IOCTL_V3D_MMAP_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_MMAP_BO, struct drm_v3d_mmap_bo)
 #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
 #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
+#define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
 
 /**
  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
@@ -58,10 +60,15 @@ struct drm_v3d_submit_cl {
         * coordinate shader to determine where primitives land on the screen,
         * then writes out the state updates and draw calls necessary per tile
         * to the tile allocation BO.
+        *
+        * This BCL will block on any previous BCL submitted on the
+        * same FD, but not on any RCL or BCLs submitted by other
+        * clients -- that is left up to the submitter to control
+        * using in_sync_bcl if necessary.
         */
        __u32 bcl_start;
 
-        /** End address of the BCL (first byte after the BCL) */
+       /** End address of the BCL (first byte after the BCL) */
        __u32 bcl_end;
 
        /* Offset of the render command list.
@@ -69,10 +76,15 @@ struct drm_v3d_submit_cl {
         * This is the second set of commands executed, which will either
         * execute the tiles that have been set up by the BCL, or a fixed set
         * of tiles (in the case of RCL-only blits).
+        *
+        * This RCL will block on this submit's BCL, and any previous
+        * RCL submitted on the same FD, but not on any RCL or BCLs
+        * submitted by other clients -- that is left up to the
+        * submitter to control using in_sync_rcl if necessary.
         */
        __u32 rcl_start;
 
-        /** End address of the RCL (first byte after the RCL) */
+       /** End address of the RCL (first byte after the RCL) */
        __u32 rcl_end;
 
        /** An optional sync object to wait on before starting the BCL. */
@@ -169,6 +181,7 @@ enum drm_v3d_param {
        DRM_V3D_PARAM_V3D_CORE0_IDENT0,
        DRM_V3D_PARAM_V3D_CORE0_IDENT1,
        DRM_V3D_PARAM_V3D_CORE0_IDENT2,
+       DRM_V3D_PARAM_SUPPORTS_TFU,
 };
 
 struct drm_v3d_get_param {
@@ -187,6 +200,28 @@ struct drm_v3d_get_bo_offset {
        __u32 offset;
 };
 
+struct drm_v3d_submit_tfu {
+       __u32 icfg;
+       __u32 iia;
+       __u32 iis;
+       __u32 ica;
+       __u32 iua;
+       __u32 ioa;
+       __u32 ios;
+       __u32 coef[4];
+       /* First handle is the output BO, following are other inputs.
+        * 0 for unused.
+        */
+       __u32 bo_handles[4];
+       /* sync object to block on before running the TFU job.  Each TFU
+        * job will execute in the order submitted to its FD.  Synchronization
+        * against rendering jobs requires using sync objects.
+        */
+       __u32 in_sync;
+       /* Sync object to signal when the TFU job is done. */
+       __u32 out_sync;
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 9e66065b5002904735c16071f4b223130bd84dfc..6610009ad800617327eb1bf70b31dc8073e5003f 100644 (file)
@@ -244,19 +244,42 @@ v3d_get_simulator_bo(struct v3d_simulator_file *file, int gem_handle)
         return entry ? entry->data : NULL;
 }
 
+static void
+v3d_simulator_copy_in_handle(struct v3d_simulator_file *file, int handle)
+{
+        struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle);
+
+        if (!sim_bo)
+                return;
+
+        memcpy(sim_bo->sim_vaddr, sim_bo->gem_vaddr, sim_bo->size);
+}
+
+static void
+v3d_simulator_copy_out_handle(struct v3d_simulator_file *file, int handle)
+{
+        struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle);
+
+        if (!sim_bo)
+                return;
+
+        memcpy(sim_bo->gem_vaddr, sim_bo->sim_vaddr, sim_bo->size);
+
+        if (*(uint32_t *)(sim_bo->sim_vaddr +
+                          sim_bo->size) != BO_SENTINEL) {
+                fprintf(stderr, "Buffer overflow in handle %d\n",
+                        handle);
+        }
+}
+
 static int
 v3d_simulator_pin_bos(struct v3d_simulator_file *file,
                       struct drm_v3d_submit_cl *submit)
 {
         uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles;
 
-        for (int i = 0; i < submit->bo_handle_count; i++) {
-                int handle = bo_handles[i];
-                struct v3d_simulator_bo *sim_bo =
-                        v3d_get_simulator_bo(file, handle);
-
-                memcpy(sim_bo->sim_vaddr, sim_bo->gem_vaddr, sim_bo->size);
-        }
+        for (int i = 0; i < submit->bo_handle_count; i++)
+                v3d_simulator_copy_in_handle(file, bo_handles[i]);
 
         return 0;
 }
@@ -267,19 +290,8 @@ v3d_simulator_unpin_bos(struct v3d_simulator_file *file,
 {
         uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles;
 
-        for (int i = 0; i < submit->bo_handle_count; i++) {
-                int handle = bo_handles[i];
-                struct v3d_simulator_bo *sim_bo =
-                        v3d_get_simulator_bo(file, handle);
-
-                memcpy(sim_bo->gem_vaddr, sim_bo->sim_vaddr, sim_bo->size);
-
-                if (*(uint32_t *)(sim_bo->sim_vaddr +
-                                  sim_bo->size) != BO_SENTINEL) {
-                        fprintf(stderr, "Buffer overflow in handle %d\n",
-                                handle);
-                }
-        }
+        for (int i = 0; i < submit->bo_handle_count; i++)
+                v3d_simulator_copy_out_handle(file, bo_handles[i]);
 
         return 0;
 }
@@ -400,6 +412,27 @@ v3d_simulator_get_param_ioctl(int fd, struct drm_v3d_get_param *args)
                 return v3d33_simulator_get_param_ioctl(sim_state.v3d, args);
 }
 
+static int
+v3d_simulator_submit_tfu_ioctl(int fd, struct drm_v3d_submit_tfu *args)
+{
+        struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd);
+        int ret;
+
+        v3d_simulator_copy_in_handle(file, args->bo_handles[0]);
+        v3d_simulator_copy_in_handle(file, args->bo_handles[1]);
+        v3d_simulator_copy_in_handle(file, args->bo_handles[2]);
+        v3d_simulator_copy_in_handle(file, args->bo_handles[3]);
+
+        if (sim_state.ver >= 41)
+                ret = v3d41_simulator_submit_tfu_ioctl(sim_state.v3d, args);
+        else
+                ret = v3d33_simulator_submit_tfu_ioctl(sim_state.v3d, args);
+
+        v3d_simulator_copy_out_handle(file, args->bo_handles[0]);
+
+        return ret;
+}
+
 int
 v3d_simulator_ioctl(int fd, unsigned long request, void *args)
 {
@@ -427,6 +460,9 @@ v3d_simulator_ioctl(int fd, unsigned long request, void *args)
         case DRM_IOCTL_GEM_CLOSE:
                 return v3d_simulator_gem_close_ioctl(fd, args);
 
+        case DRM_IOCTL_V3D_SUBMIT_TFU:
+                return v3d_simulator_submit_tfu_ioctl(fd, args);
+
         case DRM_IOCTL_GEM_OPEN:
         case DRM_IOCTL_GEM_FLINK:
                 return drmIoctl(fd, request, args);
index ab826af6c29e1415ccc6735540ad35bfc761b0d2..ca69294a99f89aa5dd56f3a568d4f80108070d62 100644 (file)
@@ -42,6 +42,8 @@ int v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d,
 void v3dX(simulator_submit_cl_ioctl)(struct v3d_hw *v3d,
                                      struct drm_v3d_submit_cl *args,
                                      uint32_t gmp_offset);
+int v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d,
+                                     struct drm_v3d_submit_tfu *args);
 const struct v3d_format *v3dX(get_format_desc)(enum pipe_format f);
 void v3dX(get_internal_type_bpp_for_output_format)(uint32_t format,
                                                    uint32_t *type,
index 27cc3732344965d5b53fcfed6054db40428fdbc8..a48c24e7f915a25bc64646c54f4f102f2c198079 100644 (file)
@@ -98,6 +98,32 @@ v3d_flush_caches(struct v3d_hw *v3d)
         v3d_flush_slices(v3d);
 }
 
+int
+v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d,
+                                 struct drm_v3d_submit_tfu *args)
+{
+        int last_vtct = V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET;
+
+        V3D_WRITE(V3D_TFU_IIA, args->iia);
+        V3D_WRITE(V3D_TFU_IIS, args->iis);
+        V3D_WRITE(V3D_TFU_ICA, args->ica);
+        V3D_WRITE(V3D_TFU_IUA, args->iua);
+        V3D_WRITE(V3D_TFU_IOA, args->ioa);
+        V3D_WRITE(V3D_TFU_IOS, args->ios);
+        V3D_WRITE(V3D_TFU_COEF0, args->coef[0]);
+        V3D_WRITE(V3D_TFU_COEF1, args->coef[1]);
+        V3D_WRITE(V3D_TFU_COEF2, args->coef[2]);
+        V3D_WRITE(V3D_TFU_COEF3, args->coef[3]);
+
+        V3D_WRITE(V3D_TFU_ICFG, args->icfg);
+
+        while ((V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET) != last_vtct) {
+                v3d_hw_tick(v3d);
+        }
+
+        return 0;
+}
+
 int
 v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d,
                                 struct drm_v3d_get_param *args)
@@ -112,6 +138,12 @@ v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d,
                 [DRM_V3D_PARAM_V3D_CORE0_IDENT2] = V3D_CTL_0_IDENT2,
         };
 
+        switch (args->param) {
+        case DRM_V3D_PARAM_SUPPORTS_TFU:
+                args->value = 1;
+                return 0;
+        }
+
         if (args->param < ARRAY_SIZE(reg_map) && reg_map[args->param]) {
                 args->value = V3D_READ(reg_map[args->param]);
                 return 0;