summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--freedreno/msm/msm_ringbuffer.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c
index 24aa9fd4..5cd97709 100644
--- a/freedreno/msm/msm_ringbuffer.c
+++ b/freedreno/msm/msm_ringbuffer.c
@@ -46,6 +46,9 @@ struct msm_cmd {
DECLARE_ARRAY(struct drm_msm_gem_submit_reloc, relocs);
uint32_t size;
+
+ /* has cmd already been added to parent rb's submit.cmds table? */
+ int is_appended_to_submit;
};
struct msm_ringbuffer {
@@ -91,6 +94,18 @@ struct msm_ringbuffer {
/* maps fd_bo to idx: */
void *bo_table;
+
+ /* maps msm_cmd to drm_msm_gem_submit_cmd in parent rb. Each rb has a
+ * list of msm_cmd's which correspond to each chunk of cmdstream in
+ * a 'growable' rb. For each of those we need to create one
+ * drm_msm_gem_submit_cmd in the parent rb which collects the state
+ * for the submit ioctl. Because we can have multiple IB's to the same
+ * target rb (for example, or same stateobj emit multiple times), and
+ * because in theory we can have multiple different rb's that have a
+ * reference to a given target, we need a hashtable to track this per
+ * rb.
+ */
+ void *cmd_table;
};
static inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x)
@@ -234,13 +249,6 @@ static uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t fl
return idx;
}
-static int check_cmd_bo(struct fd_ringbuffer *ring,
- struct drm_msm_gem_submit_cmd *cmd, struct fd_bo *bo)
-{
- struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
- return msm_ring->submit.bos[cmd->submit_idx].handle == bo->handle;
-}
-
/* Ensure that submit has corresponding entry in cmds table for the
* target cmdstream buffer:
*
@@ -253,15 +261,31 @@ static int get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
struct drm_msm_gem_submit_cmd *cmd;
uint32_t i;
+ void *val;
- /* figure out if we already have a cmd buf: */
- for (i = 0; i < msm_ring->submit.nr_cmds; i++) {
+ if (!msm_ring->cmd_table)
+ msm_ring->cmd_table = drmHashCreate();
+
+ /* figure out if we already have a cmd buf.. short-circuit hash
+ * lookup if:
+ * - target cmd has never been added to submit.cmds
+ * - target cmd is not a streaming stateobj (which unlike longer
+ * lived CSO stateobj, is not expected to be reused with multiple
+ * submits)
+ */
+ if (target_cmd->is_appended_to_submit &&
+ !(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING) &&
+ !drmHashLookup(msm_ring->cmd_table, (unsigned long)target_cmd, &val)) {
+ i = VOID2U64(val);
cmd = &msm_ring->submit.cmds[i];
- if ((cmd->submit_offset == submit_offset) &&
- (cmd->size == size) &&
- (cmd->type == type) &&
- check_cmd_bo(ring, cmd, target_cmd->ring_bo))
- return FALSE;
+
+ assert(cmd->submit_offset == submit_offset);
+ assert(cmd->size == size);
+ assert(cmd->type == type);
+ assert(msm_ring->submit.bos[cmd->submit_idx].handle ==
+ target_cmd->ring_bo->handle);
+
+ return FALSE;
}
/* create cmd buf if not: */
@@ -275,6 +299,13 @@ static int get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
cmd->size = size;
cmd->pad = 0;
+ target_cmd->is_appended_to_submit = TRUE;
+
+ if (!(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING)) {
+ drmHashInsert(msm_ring->cmd_table, (unsigned long)target_cmd,
+ U642VOID(i));
+ }
+
target_cmd->size = size;
return TRUE;
@@ -334,6 +365,11 @@ static void flush_reset(struct fd_ringbuffer *ring)
msm_ring->bo_table = NULL;
}
+ if (msm_ring->cmd_table) {
+ drmHashDestroy(msm_ring->cmd_table);
+ msm_ring->cmd_table = NULL;
+ }
+
if (msm_ring->is_growable) {
delete_cmds(msm_ring);
} else {