[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