[Mesa-dev] [PATCH 12/14] i965/meta: Introduce custom pipeline

Topi Pohjolainen topi.pohjolainen at intel.com
Thu Feb 25 09:46:17 UTC 2016


Meta gives core state upload a set of emit overrides programming
vertex fetcher without core vbo support.

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_context.h   |   3 +
 src/mesa/drivers/dri/i965/brw_meta_util.c | 216 ++++++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_meta_util.h |   5 +
 3 files changed, 224 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index ad69288..78f583a 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -913,6 +913,9 @@ struct brw_context
    /* Whether a meta-operation is in progress. */
    bool meta_in_progress;
 
+   /* Custom pipeline for meta operations. */
+   void (* const meta_emitters[76])(struct brw_context *, void *meta_ctx);
+
    struct brw_meta_save_state meta;
 
    /* Whether the last depth/stencil packets were both NULL. */
diff --git a/src/mesa/drivers/dri/i965/brw_meta_util.c b/src/mesa/drivers/dri/i965/brw_meta_util.c
index 90cb1ce..c9feb89 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_util.c
+++ b/src/mesa/drivers/dri/i965/brw_meta_util.c
@@ -28,6 +28,8 @@
 #include "brw_draw.h"
 #include "brw_context.h"
 #include "intel_batchbuffer.h"
+#include "brw_state.h"
+#include "brw_atoms.h"
 
 /**
  * Helper function for handling mirror image blits.
@@ -293,3 +295,217 @@ brw_meta_emit_clip_disable(struct brw_context *brw)
    OUT_BATCH(0);
    ADVANCE_BATCH();
 }
+
+static void
+emit_vertex_elements(struct brw_context *brw)
+{
+   /* 3DSTATE_VERTEX_ELEMENTS
+    *
+    * These are instructions for VF (vertex fetcher) how the URB is to be
+    * filled with vertex data.
+    *
+    * There is an element containing vertex coordinates (x,y,w,z). We tell
+    * the VF to load X and Y from the vertex buffer and to use constant
+    * values of zero and one for the Z and W coordinates respectively.
+    * Additionally on Gen < 8 any system generated input values are
+    * programmed with an extra element. Newer generations have separate
+    * state packet for this.
+    */
+   const bool use_system_generated_values =
+      brw->gen < 8 &&
+      (brw->vs.prog_data->uses_vertexid ||
+       brw->vs.prog_data->uses_instanceid ||
+       brw->vs.prog_data->uses_basevertex ||
+       brw->vs.prog_data->uses_baseinstance);
+   const int num_elements = 1 + use_system_generated_values;
+   const int batch_length = 1 + 2 * num_elements;
+
+   BEGIN_BATCH(batch_length);
+   OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (batch_length - 2));
+   /* Element 0 */
+   OUT_BATCH(GEN6_VE0_VALID |
+             BRW_SURFACEFORMAT_R32G32_FLOAT << BRW_VE0_FORMAT_SHIFT |
+             0 << BRW_VE0_SRC_OFFSET_SHIFT);
+   OUT_BATCH(BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT |
+             BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_1_SHIFT |
+             BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT |
+             BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT);
+
+   if (use_system_generated_values) {
+      const uint32_t comp0 = brw->vs.prog_data->uses_basevertex ?
+         BRW_VE1_COMPONENT_STORE_SRC : BRW_VE1_COMPONENT_STORE_0;
+      const uint32_t comp1 = brw->vs.prog_data->uses_baseinstance ?
+         BRW_VE1_COMPONENT_STORE_SRC : BRW_VE1_COMPONENT_STORE_0;
+      const uint32_t comp2 = brw->vs.prog_data->uses_vertexid ?
+         BRW_VE1_COMPONENT_STORE_VID : BRW_VE1_COMPONENT_STORE_0;
+      const uint32_t comp3 = brw->vs.prog_data->uses_instanceid ?
+         BRW_VE1_COMPONENT_STORE_IID : BRW_VE1_COMPONENT_STORE_0;
+
+      OUT_BATCH(GEN6_VE0_VALID |
+                1 << GEN6_VE0_INDEX_SHIFT |
+                BRW_SURFACEFORMAT_R32G32_FLOAT << BRW_VE0_FORMAT_SHIFT);
+      OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) |
+                (comp1 << BRW_VE1_COMPONENT_1_SHIFT) |
+                (comp2 << BRW_VE1_COMPONENT_2_SHIFT) |
+                (comp3 << BRW_VE1_COMPONENT_3_SHIFT));
+   }
+
+   ADVANCE_BATCH();
+
+   if (brw->gen < 8)
+      return;
+
+   for (unsigned i = 0; i < num_elements; ++i) {
+       BEGIN_BATCH(3);
+       OUT_BATCH(_3DSTATE_VF_INSTANCING << 16 | (3 - 2));
+       OUT_BATCH(i);
+       OUT_BATCH(0);
+       ADVANCE_BATCH();
+   }
+}
+
+static void
+meta_setup_vertex_buffer(struct brw_context *brw,
+                         uint32_t x0, uint32_t y0,
+                         uint32_t x1, uint32_t y1)
+{
+   uint32_t vertex_offset;
+
+   /* See gen6_blorp_emit_vertices() */
+   const float vertices[] = {
+      /* v0 */ (float)x1, (float)y1,
+      /* v1 */ (float)x0, (float)y1,
+      /* v2 */ (float)x0, (float)y0
+   };
+
+   float *vertex_data = (float *)brw_state_batch(
+                                    brw, AUB_TRACE_VERTEX_BUFFER,
+                                    sizeof(vertices), 32,
+                                    &vertex_offset);
+   memcpy(vertex_data, vertices, sizeof(vertices));
+
+   const unsigned num_verts = 3;
+   const unsigned num_elems = sizeof(vertices) / (num_verts  * sizeof(float));
+
+   brw_meta_emit_vertex_buffer_state(brw, num_elems, sizeof(vertices),
+                                     vertex_offset);
+}
+
+static void
+meta_emit_noop(struct brw_context *brw, void *custom_ctx)
+{
+   (void)custom_ctx;
+   (void)brw;
+}
+
+static void
+meta_emit_clip_state(struct brw_context *brw, void *custom_ctx)
+{
+   (void)custom_ctx;
+   brw_meta_emit_clip_disable(brw);
+}
+
+struct meta_custom_context {
+   /* Dimensions for rectangle primitive. */
+   float x0, y0, x1, y1;
+};
+
+static void
+meta_emit_vertices(struct brw_context *brw, void *custom_ctx)
+{
+   const struct meta_custom_context *meta_ctx =
+      (const struct meta_custom_context *)custom_ctx;
+
+   if (brw->gen >= 8) {
+      gen8_emit_system_gen_values(brw,
+                                  brw->vs.prog_data->uses_vertexid,
+                                  brw->vs.prog_data->uses_instanceid,
+                                  1 /* nr_vb_enabled */,
+                                  false /* uses_edge_flag */);
+   }
+
+   meta_setup_vertex_buffer(brw,
+                            meta_ctx->x0, meta_ctx->y0,
+                            meta_ctx->x1, meta_ctx->y1);
+
+   emit_vertex_elements(brw);
+}
+
+static void
+meta_emit_no_cut_index(struct brw_context *brw, void *custom_ctx)
+{
+   (void)custom_ctx;
+
+   /* Don't trigger on Ivybridge */
+   if (brw->gen < 8 && !brw->is_haswell)
+      return;
+
+   BEGIN_BATCH(2);
+   OUT_BATCH(_3DSTATE_VF << 16 | (2 - 2));
+   OUT_BATCH(0);
+   ADVANCE_BATCH();
+}
+
+void
+brw_meta_pipeline_upload(struct brw_context *brw,
+                         float x0, float y0, float x1, float y1)
+{
+   assert(brw->gen >= 6);
+
+   struct meta_custom_context custom_ctx = {
+      .x0 = x0, .y0 = y0, .x1 = x1, .y1 = y1 };
+
+   brw->wm.base.sampler_count = 0;
+   brw->gs.base.sampler_count = 0;
+   brw->tes.base.sampler_count = 0;
+   brw->tcs.base.sampler_count = 0;
+   brw->vs.base.sampler_count = 0;
+
+   if (brw->primitive != _3DPRIM_RECTLIST) {
+      brw->primitive = _3DPRIM_RECTLIST;
+      brw->ctx.NewDriverState |= BRW_NEW_PRIMITIVE;
+   }
+
+   brw->ctx.NewDriverState |= BRW_NEW_VERTICES;
+   brw_upload_pipeline_state(brw, BRW_RENDER_PIPELINE,
+                             brw->meta_emitters, &custom_ctx);
+}
+
+void
+brw_meta_init(struct brw_context *brw)
+{
+   STATIC_ASSERT(ARRAY_SIZE(brw->meta_emitters) <=
+                 ARRAY_SIZE(brw->render_atoms));
+
+   /* This is to work around brw_context::meta_emitters being declared const.
+    * We want it to be const, but it needs to be initialized somehow!
+    */
+   void (** emitters)(struct brw_context *, void *) =
+      (void (**)(struct brw_context *, void *))brw->meta_emitters;
+
+   (void)memset(emitters, 0, sizeof(brw->meta_emitters));
+
+   switch (brw->gen) {
+   case 6:
+      emitters[GEN6_ATOM_CLIP_STATE] = meta_emit_clip_state;
+      emitters[GEN6_ATOM_INDICES] = meta_emit_noop;
+      emitters[GEN6_ATOM_INDEX_BUFFER] = meta_emit_noop;
+      emitters[GEN6_ATOM_VERTICES] = meta_emit_vertices;
+   break;
+   case 7:
+      emitters[GEN7_ATOM_CLIP_STATE] = meta_emit_clip_state;
+      emitters[GEN7_ATOM_INDICES] = meta_emit_noop;
+      emitters[GEN7_ATOM_INDEX_BUFFER] = meta_emit_noop;
+      emitters[GEN7_ATOM_VERTICES] = meta_emit_vertices;
+      emitters[GEN7_ATOM_HASWELL_CUT_INDEX] = meta_emit_no_cut_index;
+   break;
+   case 8:
+   case 9:
+      emitters[GEN8_ATOM_CLIP_STATE] = meta_emit_clip_state;
+      emitters[GEN8_ATOM_INDICES] = meta_emit_noop;
+      emitters[GEN8_ATOM_INDEX_BUFFER] = meta_emit_noop;
+      emitters[GEN8_ATOM_VERTICES] = meta_emit_vertices;
+      emitters[GEN8_ATOM_HASWELL_CUT_INDEX] = meta_emit_no_cut_index;
+   break;
+   }
+}
diff --git a/src/mesa/drivers/dri/i965/brw_meta_util.h b/src/mesa/drivers/dri/i965/brw_meta_util.h
index 99c9186..91b6b41 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_util.h
+++ b/src/mesa/drivers/dri/i965/brw_meta_util.h
@@ -58,6 +58,11 @@ void brw_meta_emit_vertex_buffer_state(struct brw_context *brw,
 
 void brw_meta_emit_clip_disable(struct brw_context *brw);
 
+void brw_meta_pipeline_upload(struct brw_context *brw,
+                              float x0, float y0, float x1, float y1);
+
+void brw_meta_init(struct brw_context *brw);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.5.0



More information about the mesa-dev mailing list