summaryrefslogtreecommitdiff
path: root/freedreno
diff options
context:
space:
mode:
authorRob Clark <robclark@freedesktop.org>2018-10-10 12:51:33 -0400
committerRob Clark <robclark@freedesktop.org>2018-10-13 17:23:35 -0400
commit880871b3787d2664daefe228bc99ead298d5a76e (patch)
tree77a7768e34a37c7e06e1e4b34e03707eece8ceec /freedreno
parent5c4722e9078a845dce097168731f1be88cf61e75 (diff)
downloaddrm-880871b3787d2664daefe228bc99ead298d5a76e.tar.gz
freedreno/msm: use hashtable to track submit.cmds table
With streaming stateobjs to upload uniforms, the submit.cmds table gets much larger, and iterating over it for each ring to ring reloc starts getting expensive. TODO if we have flag to pass when constructing parent rb, we could avoid dynamically allocating this and bo_table in get_cmd() or bo2idx Signed-off-by: Rob Clark <robclark@freedesktop.org>
Diffstat (limited to 'freedreno')
-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 {