From ee0549ff9ab31b52301f693735f6987f72312fc7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 1 Nov 2018 16:10:01 -0700 Subject: [PATCH] v3d: Add the V3D TFU submit interface to the simulator. 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 | 39 +++++++++++- src/gallium/drivers/v3d/v3d_simulator.c | 76 +++++++++++++++++------- src/gallium/drivers/v3d/v3dx_context.h | 2 + src/gallium/drivers/v3d/v3dx_simulator.c | 32 ++++++++++ 4 files changed, 127 insertions(+), 22 deletions(-) diff --git a/include/drm-uapi/v3d_drm.h b/include/drm-uapi/v3d_drm.h index 7b662778360..35c7d813c66 100644 --- a/include/drm-uapi/v3d_drm.h +++ b/include/drm-uapi/v3d_drm.h @@ -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 diff --git a/src/gallium/drivers/v3d/v3d_simulator.c b/src/gallium/drivers/v3d/v3d_simulator.c index 9e66065b500..6610009ad80 100644 --- a/src/gallium/drivers/v3d/v3d_simulator.c +++ b/src/gallium/drivers/v3d/v3d_simulator.c @@ -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); diff --git a/src/gallium/drivers/v3d/v3dx_context.h b/src/gallium/drivers/v3d/v3dx_context.h index ab826af6c29..ca69294a99f 100644 --- a/src/gallium/drivers/v3d/v3dx_context.h +++ b/src/gallium/drivers/v3d/v3dx_context.h @@ -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, diff --git a/src/gallium/drivers/v3d/v3dx_simulator.c b/src/gallium/drivers/v3d/v3dx_simulator.c index 27cc3732344..a48c24e7f91 100644 --- a/src/gallium/drivers/v3d/v3dx_simulator.c +++ b/src/gallium/drivers/v3d/v3dx_simulator.c @@ -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; -- 2.30.2