iris: completely rewrite binder
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 6 Jun 2018 18:59:17 +0000 (11:59 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Feb 2019 18:26:06 +0000 (10:26 -0800)
now we get a new one per batch, and flush if it fills up

src/gallium/drivers/iris/iris_batch.c
src/gallium/drivers/iris/iris_batch.h
src/gallium/drivers/iris/iris_binder.c
src/gallium/drivers/iris/iris_binder.h
src/gallium/drivers/iris/iris_blorp.c
src/gallium/drivers/iris/iris_context.c
src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_draw.c
src/gallium/drivers/iris/iris_state.c

index 6ee460308935bdd9a3a0c81cac010cbb694625bd..c3078d9c638d3c99c3237765ec3cccf707879cc7 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "iris_batch.h"
+#include "iris_binder.h"
 #include "iris_bufmgr.h"
 #include "iris_context.h"
 
@@ -128,6 +129,8 @@ iris_init_batch(struct iris_batch *batch,
    batch->validation_list =
       malloc(batch->exec_array_size * sizeof(batch->validation_list[0]));
 
+   batch->binder.bo = NULL;
+
    batch->cache.render = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                                  _mesa_key_pointer_equal);
    batch->cache.depth = _mesa_set_create(NULL, _mesa_hash_pointer,
@@ -221,6 +224,9 @@ iris_batch_reset(struct iris_batch *batch)
    create_batch(batch);
    assert(batch->bo->index == 0);
 
+   iris_destroy_binder(&batch->binder);
+   iris_init_binder(&batch->binder, batch->bo->bufmgr);
+
    if (batch->state_sizes)
       _mesa_hash_table_clear(batch->state_sizes, NULL);
 
index 13525a4d4dd4bd0164e46776426a9d83e6078423..88a58d083f5b0d313010369a35596ef2287130ae 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdbool.h>
 #include "i915_drm.h"
 #include "common/gen_decoder.h"
+#include "iris_binder.h"
 
 /* The kernel assumes batchbuffers are smaller than 256kB. */
 #define MAX_BATCH_SIZE (256 * 1024)
@@ -50,7 +51,6 @@ struct iris_batch {
    /** Size of the primary batch if we've moved on to a secondary. */
    unsigned primary_batch_size;
 
-
    /** Last BO submitted to the hardware.  Used for glFinish(). */
    struct iris_bo *last_bo;
 
@@ -68,6 +68,9 @@ struct iris_batch {
    /** The amount of aperture space (in bytes) used by all exec_bos */
    int aperture_space;
 
+   /** Binder (containing binding tables) */
+   struct iris_binder binder;
+
    struct {
       /**
        * Set of struct brw_bo * that have been rendered to within this
index 408e2007ae24d78874afa15c121f199a56871c76..1b1c78380bb2161c1045a719480c2951c6b75bc4 100644 (file)
 #include "util/u_math.h"
 #include "iris_binder.h"
 #include "iris_bufmgr.h"
+#include "iris_context.h"
 
 /* 64kb */
 #define BINDER_SIZE (64 * 1024)
 
-void *
-iris_binder_reserve(struct iris_binder *binder, unsigned size,
-                    uint32_t *out_offset)
+/**
+ * Reserve a block of space in the binder.
+ */
+uint32_t
+iris_binder_reserve(struct iris_batch *batch, unsigned size)
 {
-   /* XXX: if we ever make this allocate a new BO, then make binder_reserve
-    * return the BO, so at least verify use_pinned_bo gets the right one
-    */
-   /* XXX: Implement a real ringbuffer, for now just croak if run out */
-   assert(size > 0);
-   assert(binder->insert_point + size <= BINDER_SIZE);
+   struct iris_binder *binder = &batch->binder;
 
+   assert(size > 0);
    assert((binder->insert_point % 64) == 0);
-   *out_offset = binder->insert_point;
+
+   /* If we can't fit all stages in the binder, flush the batch which
+    * will cause us to gain a new empty binder.
+    */
+   if (binder->insert_point + size > BINDER_SIZE)
+      iris_batch_flush(batch);
+
+   uint32_t offset = binder->insert_point;
+
+   /* It had better fit now. */
+   assert(offset + size <= BINDER_SIZE);
 
    binder->insert_point = align(binder->insert_point + size, 64);
 
-   return binder->map + *out_offset;
+   iris_use_pinned_bo(batch, binder->bo, false);
+
+   return offset;
+}
+
+/**
+ * Reserve and record binder space for 3D pipeline shader stages.
+ */
+void
+iris_binder_reserve_3d(struct iris_batch *batch,
+                       struct iris_compiled_shader **shaders)
+{
+   struct iris_binder *binder = &batch->binder;
+   unsigned total_size = 0;
+   unsigned sizes[MESA_SHADER_STAGES] = {};
+
+   for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+      if (!shaders[stage])
+         continue;
+
+      const struct brw_stage_prog_data *prog_data =
+         (const void *) shaders[stage]->prog_data;
+
+      sizes[stage] = align(prog_data->binding_table.size_bytes, 64);
+      total_size += sizes[stage];
+   }
+
+   uint32_t offset = iris_binder_reserve(batch, total_size);
+
+   /* Assign space and record the current binding table. */
+   for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+      binder->bt_offset[stage] = sizes[stage] > 0 ? offset : 0;
+      offset += sizes[stage];
+   }
 }
 
 void
index 5830288b5c570708f745fbc701fa02d46ba1ca92..ea455dd5cfd674e3d189585c71ec989f3f00355f 100644 (file)
 
 #include <stdint.h>
 #include <stdbool.h>
+#include "compiler/shader_enums.h"
 
 struct iris_bo;
+struct iris_batch;
 struct iris_bufmgr;
+struct iris_compiled_shader;
 
 struct iris_binder
 {
    struct iris_bo *bo;
    void *map;
 
-   /* Insert new entries at this offset (in bytes) */
-   unsigned insert_point;
+   /** Insert new entries at this offset (in bytes) */
+   uint32_t insert_point;
+
+   /**
+    * Last assigned offset for each shader stage's binding table.
+    * Zero is considered invalid and means there's no binding table.
+    */
+   uint32_t bt_offset[MESA_SHADER_STAGES];
 };
 
 void iris_init_binder(struct iris_binder *binder, struct iris_bufmgr *bufmgr);
 void iris_destroy_binder(struct iris_binder *binder);
-void *iris_binder_reserve(struct iris_binder *binder, unsigned size,
-                          uint32_t *out_offset);
+uint32_t iris_binder_reserve(struct iris_batch *batch, unsigned size);
+void iris_binder_reserve_3d(struct iris_batch *batch,
+                            struct iris_compiled_shader **shaders);
 
 #endif
index 06ba830de75fd0036ede1c9daff751ee93795b20..8def4619e8ca3e851143b0fce7f473ea195a1b22 100644 (file)
@@ -134,10 +134,8 @@ blorp_alloc_binding_table(struct blorp_batch *blorp_batch,
    struct iris_context *ice = blorp_batch->blorp->driver_ctx;
    struct iris_batch *batch = blorp_batch->driver_batch;
 
-   uint32_t *bt_map = iris_binder_reserve(&ice->state.binder,
-                                          num_entries * sizeof(uint32_t),
-                                          bt_offset);
-   iris_use_pinned_bo(batch, ice->state.binder.bo, false);
+   *bt_offset = iris_binder_reserve(batch, num_entries * sizeof(uint32_t));
+   uint32_t *bt_map = batch->binder.map + *bt_offset;
 
    for (unsigned i = 0; i < num_entries; i++) {
       surface_maps[i] = stream_state(batch, ice->state.surface_uploader,
index 417a09f64eef17be6eec0df868a0a16540e36d02..09eb288bbbcc6ed47ba04f29410709a8e8904e60 100644 (file)
@@ -80,7 +80,6 @@ iris_destroy_context(struct pipe_context *ctx)
       u_upload_destroy(ctx->stream_uploader);
 
    iris_destroy_program_cache(ice);
-   iris_destroy_binder(&ice->state.binder);
    u_upload_destroy(ice->state.surface_uploader);
    u_upload_destroy(ice->state.dynamic_uploader);
 
@@ -137,8 +136,6 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
 
    iris_init_program_cache(ice);
 
-   iris_init_binder(&ice->state.binder, screen->bufmgr);
-
    ice->state.surface_uploader =
       u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,
                       IRIS_RESOURCE_FLAG_SURFACE_MEMZONE);
index f23ba7c73e8cfd3df4b203c56b47bd820e1a741f..90230e8705af0c71b9cf2a2ee84bb883b786007d 100644 (file)
@@ -30,7 +30,6 @@
 #include "intel/common/gen_debug.h"
 #include "intel/compiler/brw_compiler.h"
 #include "iris_batch.h"
-#include "iris_binder.h"
 #include "iris_screen.h"
 
 struct iris_bo;
@@ -256,7 +255,6 @@ struct iris_context {
       unsigned num_samplers[MESA_SHADER_STAGES];
       unsigned num_textures[MESA_SHADER_STAGES];
 
-      struct iris_binder binder;
       struct u_upload_mgr *surface_uploader;
       // XXX: may want a separate uploader for "hey I made a CSO!" vs
       // "I'm streaming this out at draw time and never want it again!"
index 2494ade77d1d1f17dfd1a37886ed803bfadd7bca..5295f2ac8476a220ca873f585dc88123244a0481 100644 (file)
@@ -52,8 +52,8 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
    iris_cache_sets_clear(batch);
    // XXX: ^^^
 
-
    iris_update_compiled_shaders(ice);
+   iris_binder_reserve_3d(batch, ice->shaders.prog);
    ice->vtbl.upload_render_state(ice, batch, info);
 
    // XXX: don't flush always
index f8772315d1c0d6f5142ea7240ea682b65aa8e8e4..e0000c1988796f463d357683e313488845a1f8b6 100644 (file)
@@ -2092,6 +2092,54 @@ use_sampler_view(struct iris_batch *batch, struct iris_sampler_view *isv)
    return isv->surface_state_offset;
 }
 
+static void
+iris_populate_binding_table(struct iris_context *ice,
+                            struct iris_batch *batch,
+                            gl_shader_stage stage)
+{
+   const struct iris_binder *binder = &batch->binder;
+   struct iris_compiled_shader *shader = ice->shaders.prog[stage];
+   if (!shader)
+      return;
+
+   // Surfaces:
+   // - pull constants
+   // - ubos/ssbos/abos
+   // - images
+   // - textures
+   // - render targets - write and read
+
+   struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
+   uint32_t *bt_map = binder->map + binder->bt_offset[stage];
+   int s = 0;
+
+   if (stage == MESA_SHADER_FRAGMENT) {
+      struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
+      for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
+         bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true);
+      }
+   }
+
+   assert(prog_data->binding_table.texture_start ==
+          (ice->state.num_textures[stage] ? s : 0xd0d0d0d0));
+
+   for (int i = 0; i < ice->state.num_textures[stage]; i++) {
+      struct iris_sampler_view *view = ice->state.textures[stage][i];
+      bt_map[s++] = use_sampler_view(batch, view);
+   }
+
+#if 0
+      // XXX: not implemented yet
+      assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0);
+      assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0);
+      assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0);
+      assert(prog_data->binding_table.image_start == 0xd0d0d0d0);
+      assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0);
+      //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0);
+      //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0);
+#endif
+}
+
 static void
 iris_upload_render_state(struct iris_context *ice,
                          struct iris_batch *batch,
@@ -2226,61 +2274,19 @@ iris_upload_render_state(struct iris_context *ice,
       }
    }
 
-   // Surfaces:
-   // - pull constants
-   // - ubos/ssbos/abos
-   // - images
-   // - textures
-   // - render targets - write and read
-   // XXX: 3DSTATE_BINDING_TABLE_POINTERS_XS
-
-   for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
-      struct iris_compiled_shader *shader = ice->shaders.prog[stage];
-      if (!shader) // XXX: dirty bits...also, emit a disable maybe?
-         continue;
-
-      struct brw_stage_prog_data *prog_data = (void *) shader->prog_data;
-      uint32_t bt_offset = 0;
-      uint32_t *bt_map = NULL;
-      int s = 0;
-
-      if (prog_data->binding_table.size_bytes != 0) {
-         iris_use_pinned_bo(batch, ice->state.binder.bo, false);
-         bt_map = iris_binder_reserve(&ice->state.binder,
-                                      prog_data->binding_table.size_bytes,
-                                      &bt_offset);
-      }
+   if (1) { // XXX: DIRTY BINDINGS
+      const struct iris_binder *binder = &batch->binder;
 
-      iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) {
-         ptr._3DCommandSubOpcode = 38 + stage;
-         ptr.PointertoVSBindingTable = bt_offset;
-      }
-
-      if (stage == MESA_SHADER_FRAGMENT) {
-         struct pipe_framebuffer_state *cso_fb = &ice->state.framebuffer;
-         for (unsigned i = 0; i < cso_fb->nr_cbufs; i++) {
-            bt_map[s++] = use_surface(batch, cso_fb->cbufs[i], true);
+      for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+         iris_emit_cmd(batch, GENX(3DSTATE_BINDING_TABLE_POINTERS_VS), ptr) {
+            ptr._3DCommandSubOpcode = 38 + stage;
+            ptr.PointertoVSBindingTable = binder->bt_offset[stage];
          }
       }
 
-      assert(prog_data->binding_table.texture_start ==
-             (ice->state.num_textures[stage] ? s : 0xd0d0d0d0));
-
-      for (int i = 0; i < ice->state.num_textures[stage]; i++) {
-         struct iris_sampler_view *view = ice->state.textures[stage][i];
-         bt_map[s++] = use_sampler_view(batch, view);
+      for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {
+         iris_populate_binding_table(ice, batch, stage);
       }
-
-#if 0
-      // XXX: not implemented yet
-      assert(prog_data->binding_table.pull_constants_start == 0xd0d0d0d0);
-      assert(prog_data->binding_table.ubo_start == 0xd0d0d0d0);
-      assert(prog_data->binding_table.ssbo_start == 0xd0d0d0d0);
-      assert(prog_data->binding_table.image_start == 0xd0d0d0d0);
-      assert(prog_data->binding_table.shader_time_start == 0xd0d0d0d0);
-      //assert(prog_data->binding_table.plane_start[1] == 0xd0d0d0d0);
-      //assert(prog_data->binding_table.plane_start[2] == 0xd0d0d0d0);
-#endif
    }
 
    for (int stage = 0; stage <= MESA_SHADER_FRAGMENT; stage++) {