winsys/amdgpu: Add support for const IB.
authorMarek Olšák <marek.olsak@amd.com>
Sat, 8 Aug 2015 12:02:02 +0000 (14:02 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tue, 19 Apr 2016 16:10:30 +0000 (18:10 +0200)
v2: Use the correct IB to update request (Bas Nieuwenhuizen)
v3: Add preamble IB. (Bas Nieuwenhuizen)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeon/radeon_winsys.h
src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
src/gallium/winsys/amdgpu/drm/amdgpu_cs.h

index aa94df693628ad18e5b94744f967d9763105fd35..451d8a4ec0c33926af5e8d53978c96eae36bea86 100644 (file)
@@ -602,6 +602,36 @@ struct radeon_winsys {
                                                        struct pipe_fence_handle **fence),
                                           void *flush_ctx);
 
+    /**
+     * Add a constant engine IB to a graphics CS. This makes the graphics CS
+     * from "cs_create" a group of two IBs that share a buffer list and are
+     * flushed together.
+     *
+     * The returned constant CS is only a stream for writing packets to the new
+     * IB. Calling other winsys functions with it is not allowed, not even
+     * "cs_destroy".
+     *
+     * In order to add buffers and check memory usage, use the graphics CS.
+     * In order to flush it, use the graphics CS, which will flush both IBs.
+     * Destroying the graphics CS will destroy both of them.
+     *
+     * \param cs  The graphics CS from "cs_create" that will hold the buffer
+     *            list and will be used for flushing.
+     */
+    struct radeon_winsys_cs *(*cs_add_const_ib)(struct radeon_winsys_cs *cs);
+
+     /**
+     * Add a constant engine preamble IB to a graphics CS. This add an extra IB
+     * in similar manner to cs_add_const_ib. This should always be called after
+     * cs_add_const_ib.
+     *
+     * The returned IB is a constant engine IB that only gets flushed if the
+     * context changed.
+     *
+     * \param cs  The graphics CS from "cs_create" that will hold the buffer
+     *            list and will be used for flushing.
+     */
+    struct radeon_winsys_cs *(*cs_add_const_preamble_ib)(struct radeon_winsys_cs *cs);
     /**
      * Destroy a command stream.
      *
index b0fe8b91b1ca450072f2d2bfbdc8f39aa1210ff9..018266039125c1250631ee11c9df75ea85e0a0ac 100644 (file)
@@ -350,19 +350,62 @@ amdgpu_cs_create(struct radeon_winsys_ctx *rwctx,
       return NULL;
    }
 
-   if (!amdgpu_get_new_ib(&ctx->ws->base, &cs->main, &cs->ib)) {
+   if (!amdgpu_get_new_ib(&ctx->ws->base, &cs->main, &cs->ib[IB_MAIN])) {
       amdgpu_destroy_cs_context(cs);
       FREE(cs);
       return NULL;
    }
 
    cs->request.number_of_ibs = 1;
-   cs->request.ibs = &cs->ib;
+   cs->request.ibs = &cs->ib[IB_MAIN];
 
    p_atomic_inc(&ctx->ws->num_cs);
    return &cs->main.base;
 }
 
+static struct radeon_winsys_cs *
+amdgpu_cs_add_const_ib(struct radeon_winsys_cs *rcs)
+{
+   struct amdgpu_cs *cs = (struct amdgpu_cs*)rcs;
+   struct amdgpu_winsys *ws = cs->ctx->ws;
+
+   /* only one const IB can be added */
+   if (cs->ring_type != RING_GFX || cs->const_ib.ib_mapped)
+      return NULL;
+
+   if (!amdgpu_get_new_ib(&ws->base, &cs->const_ib, &cs->ib[IB_CONST]))
+      return NULL;
+
+   cs->request.number_of_ibs = 2;
+   cs->request.ibs = &cs->ib[IB_CONST];
+   cs->ib[IB_CONST].flags = AMDGPU_IB_FLAG_CE;
+
+   return &cs->const_ib.base;
+}
+
+static struct radeon_winsys_cs *
+amdgpu_cs_add_const_preamble_ib(struct radeon_winsys_cs *rcs)
+{
+   struct amdgpu_cs *cs = (struct amdgpu_cs*)rcs;
+   struct amdgpu_winsys *ws = cs->ctx->ws;
+
+   /* only one const preamble IB can be added and only when the const IB has
+    * also been mapped */
+   if (cs->ring_type != RING_GFX || !cs->const_ib.ib_mapped ||
+       cs->const_preamble_ib.ib_mapped)
+      return NULL;
+
+   if (!amdgpu_get_new_ib(&ws->base, &cs->const_preamble_ib,
+                                 &cs->ib[IB_CONST_PREAMBLE], IB_CONST_PREAMBLE))
+      return NULL;
+
+   cs->request.number_of_ibs = 3;
+   cs->request.ibs = &cs->ib[IB_CONST_PREAMBLE];
+   cs->ib[IB_CONST_PREAMBLE].flags = AMDGPU_IB_FLAG_CE | AMDGPU_IB_FLAG_PREAMBLE;
+
+   return &cs->const_preamble_ib.base;
+}
+
 #define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
 
 int amdgpu_lookup_buffer(struct amdgpu_cs *cs, struct amdgpu_winsys_bo *bo)
@@ -621,6 +664,15 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
       /* pad GFX ring to 8 DWs to meet CP fetch alignment requirements */
       while (rcs->cdw & 7)
          OUT_CS(rcs, 0xffff1000); /* type3 nop packet */
+
+      /* Also pad the const IB. */
+      if (cs->const_ib.ib_mapped)
+         while (!cs->const_ib.base.cdw || (cs->const_ib.base.cdw & 7))
+            OUT_CS(&cs->const_ib.base, 0xffff1000); /* type3 nop packet */
+
+      if (cs->const_preamble_ib.ib_mapped)
+         while (!cs->const_preamble_ib.base.cdw || (cs->const_preamble_ib.base.cdw & 7))
+            OUT_CS(&cs->const_preamble_ib.base, 0xffff1000);
       break;
    case RING_UVD:
       while (rcs->cdw & 15)
@@ -637,6 +689,14 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
    amdgpu_cs_add_buffer(rcs, cs->main.big_ib_buffer,
                         RADEON_USAGE_READ, 0, RADEON_PRIO_IB1);
 
+   if (cs->const_ib.ib_mapped)
+      amdgpu_cs_add_buffer(rcs, cs->const_ib.big_ib_buffer,
+                           RADEON_USAGE_READ, 0, RADEON_PRIO_IB1);
+
+   if (cs->const_preamble_ib.ib_mapped)
+      amdgpu_cs_add_buffer(rcs, cs->const_preamble_ib.big_ib_buffer,
+                           RADEON_USAGE_READ, 0, RADEON_PRIO_IB1);
+
    /* If the CS is not empty or overflowed.... */
    if (cs->main.base.cdw && cs->main.base.cdw <= cs->main.base.max_dw && !debug_get_option_noop()) {
       int r;
@@ -677,9 +737,19 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
         goto cleanup;
       }
 
-      cs->ib.size = cs->main.base.cdw;
+      cs->ib[IB_MAIN].size = cs->main.base.cdw;
       cs->main.used_ib_space += cs->main.base.cdw * 4;
 
+      if (cs->const_ib.ib_mapped) {
+         cs->ib[IB_CONST].size = cs->const_ib.base.cdw;
+         cs->const_ib.used_ib_space += cs->const_ib.base.cdw * 4;
+      }
+
+      if (cs->const_preamble_ib.ib_mapped) {
+         cs->ib[IB_CONST_PREAMBLE].size = cs->const_preamble_ib.base.cdw;
+         cs->const_preamble_ib.used_ib_space += cs->const_preamble_ib.base.cdw * 4;
+      }
+
       amdgpu_cs_do_submission(cs, fence);
 
       /* Cleanup. */
@@ -689,7 +759,13 @@ static void amdgpu_cs_flush(struct radeon_winsys_cs *rcs,
 
 cleanup:
    amdgpu_cs_context_cleanup(cs);
-   amdgpu_get_new_ib(&ws->base, &cs->main, &cs->ib);
+
+   amdgpu_get_new_ib(&ws->base, &cs->main, &cs->ib[IB_MAIN]);
+   if (cs->const_ib.ib_mapped)
+      amdgpu_get_new_ib(&ws->base, &cs->const_ib, &cs->ib[IB_CONST]);
+   if (cs->const_preamble_ib.ib_mapped)
+      amdgpu_get_new_ib(&ws->base, &cs->const_preamble_ib,
+                                 &cs->ib[IB_CONST_PREAMBLE]);
 
    ws->num_cs_flushes++;
 }
@@ -701,6 +777,8 @@ static void amdgpu_cs_destroy(struct radeon_winsys_cs *rcs)
    amdgpu_destroy_cs_context(cs);
    p_atomic_dec(&cs->ctx->ws->num_cs);
    pb_reference(&cs->main.big_ib_buffer, NULL);
+   pb_reference(&cs->const_ib.big_ib_buffer, NULL);
+   pb_reference(&cs->const_preamble_ib.big_ib_buffer, NULL);
    FREE(cs);
 }
 
@@ -720,6 +798,8 @@ void amdgpu_cs_init_functions(struct amdgpu_winsys *ws)
    ws->base.ctx_destroy = amdgpu_ctx_destroy;
    ws->base.ctx_query_reset_status = amdgpu_ctx_query_reset_status;
    ws->base.cs_create = amdgpu_cs_create;
+   ws->base.cs_add_const_ib = amdgpu_cs_add_const_ib;
+   ws->base.cs_add_const_preamble_ib = amdgpu_cs_add_const_preamble_ib;
    ws->base.cs_destroy = amdgpu_cs_destroy;
    ws->base.cs_add_buffer = amdgpu_cs_add_buffer;
    ws->base.cs_lookup_buffer = amdgpu_cs_lookup_buffer;
index 888b85b77b1fea783ced985adde6dcc0830b4024..4ed830b34b7606eec867977a5175f4529d8977d2 100644 (file)
@@ -59,8 +59,17 @@ struct amdgpu_ib {
    unsigned                used_ib_space;
 };
 
+enum {
+   IB_CONST_PREAMBLE = 0,
+   IB_CONST = 1, /* the const IB must be first */
+   IB_MAIN = 2,
+   IB_NUM
+};
+
 struct amdgpu_cs {
    struct amdgpu_ib main; /* must be first because this is inherited */
+   struct amdgpu_ib const_ib; /* optional constant engine IB */
+   struct amdgpu_ib const_preamble_ib;
    struct amdgpu_ctx *ctx;
 
    /* Flush CS. */
@@ -70,7 +79,7 @@ struct amdgpu_cs {
    /* amdgpu_cs_submit parameters */
    enum ring_type              ring_type;
    struct amdgpu_cs_request    request;
-   struct amdgpu_cs_ib_info    ib;
+   struct amdgpu_cs_ib_info    ib[IB_NUM];
 
    /* Buffers. */
    unsigned                    max_num_buffers;