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;