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")
This commit is contained in:
Eric Anholt 2018-11-01 16:10:01 -07:00
parent 42652ea51e
commit ee0549ff9a
4 changed files with 127 additions and 22 deletions

View 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

View 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);

View 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,

View 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;