iris: Enable GL_AMD_depth_clamp_separate
[mesa.git] / src / gallium / drivers / iris / iris_binder.c
index 2cac1b71256ad15aaf7a1dbd2d7342fdd6ac5969..6d23de229bf200071f8f6fc0e833e6fd35b597d4 100644 (file)
@@ -26,9 +26,8 @@
  * Shader programs refer to most resources via integer handles.  These are
  * indexes (BTIs) into a "Binding Table", which is simply a list of pointers
  * to SURFACE_STATE entries.  Each shader stage has its own binding table,
- * set by the 3DSTATE_BINDING_TABLE_POINTERS_* commands.  Both the binding
- * table itself and the SURFACE_STATEs are relative to Surface State Base
- * Address, so they all live in IRIS_MEMZONE_SURFACE.
+ * set by the 3DSTATE_BINDING_TABLE_POINTERS_* commands.  We stream out
+ * binding tables dynamically, storing them in special BOs we call "binders."
  *
  * Unfortunately, the hardware designers made 3DSTATE_BINDING_TABLE_POINTERS
  * only accept a 16-bit pointer.  This means that all binding tables have to
  * actual SURFACE_STATE entries can live anywhere in the 4GB zone, as the
  * binding table entries are full 32-bit pointers.)
  *
- * We stream out binding tables dynamically, storing them in a single 64kB
- * "binder" buffer, located at IRIS_BINDER_ADDRESS.  Before emitting a draw
- * call, we reserve space for any new binding tables needed by bound shaders.
- * If there is no space, we flush the batch and swap out the binder for a
- * new empty BO.
+ * To handle this, we split a 4GB region of VMA into two memory zones.
+ * IRIS_MEMZONE_BINDER is a small region at the bottom able to hold a few
+ * binder BOs.  IRIS_MEMZONE_SURFACE contains the rest of the 4GB, and is
+ * always at a higher address than the binders.  This allows us to program
+ * Surface State Base Address to the binder BO's address, and offset the
+ * values in the binding table to account for the base not starting at the
+ * beginning of the 4GB region.
  *
- * XXX: This should be fancier.  We currently replace the binder with a
- * fresh BO on every batch, which causes the kernel to stall, trying to
- * pin the new buffer at the same memory address as the old one.  We ought
- * to avoid this by using a ringbuffer, tracking the busy section of the BO,
- * and cycling back around where possible to avoid replacing it at all costs.
- *
- * XXX: if we do have to flush, we should emit a performance warning.
- *
- * XXX: these comments are out of date
+ * This does mean that we have to emit STATE_BASE_ADDRESS and stall when
+ * we run out of space in the binder, which hopefully won't happen too often.
  */
 
 #include <stdlib.h>
@@ -77,10 +71,23 @@ binder_realloc(struct iris_context *ice)
    struct iris_bufmgr *bufmgr = screen->bufmgr;
    struct iris_binder *binder = &ice->state.binder;
 
-   iris_bo_unreference(binder->bo);
+   uint64_t next_address = IRIS_MEMZONE_BINDER_START;
+
+   if (binder->bo) {
+      /* Place the new binder just after the old binder, unless we've hit the
+       * end of the memory zone...then wrap around to the start again.
+       */
+      next_address = binder->bo->gtt_offset + IRIS_BINDER_SIZE;
+      if (next_address >= IRIS_MEMZONE_SURFACE_START)
+         next_address = IRIS_MEMZONE_BINDER_START;
+
+      iris_bo_unreference(binder->bo);
+   }
+
 
    binder->bo =
       iris_bo_alloc(bufmgr, "binder", IRIS_BINDER_SIZE, IRIS_MEMZONE_BINDER);
+   binder->bo->gtt_offset = next_address;
    binder->map = iris_bo_map(NULL, binder->bo, MAP_WRITE);
    binder->insert_point = INIT_INSERT_POINT;
 
@@ -184,6 +191,24 @@ iris_binder_reserve_3d(struct iris_context *ice)
    }
 }
 
+void
+iris_binder_reserve_compute(struct iris_context *ice)
+{
+   if (!(ice->state.dirty & IRIS_DIRTY_BINDINGS_CS))
+      return;
+
+   struct iris_binder *binder = &ice->state.binder;
+   struct brw_stage_prog_data *prog_data =
+      ice->shaders.prog[MESA_SHADER_COMPUTE]->prog_data;
+
+   unsigned size = prog_data->binding_table.size_bytes;
+
+   if (size == 0)
+      return;
+
+   binder->bt_offset[MESA_SHADER_COMPUTE] = iris_binder_reserve(ice, size);
+}
+
 void
 iris_init_binder(struct iris_context *ice)
 {