[Mesa-dev] [PATCH 14/17] i965/vs: Generalize vertex emission code in preparation for GS.
Paul Berry
stereotype441 at gmail.com
Sun Apr 7 15:54:07 PDT 2013
This patch introduces a new function, vec4_visitor::emit_vertex(),
which contains the code for emitting vertices that will need to be
common between the vertex and geometry shaders.
Geometry shaders will need to use a different message header, and a
different opcode, for their URB writes, so we introduce virtual
functions emit_urb_write_header() and emit_urb_write_opcode() to take
care of the GS-specific behaviours.
Also, since vertex emission happens at the end of the VS, but in the
middle of the GS, we need to be sure to only call
emit_shader_time_end() during VS vertex emission. We accomplish this
by moving the call to emit_shader_time_end() into the VS
implementation of emit_urb_write_opcode().
---
src/mesa/drivers/dri/i965/brw_vec4.h | 5 ++
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 71 +++++++++++++++-------
.../dri/i965/test_vec4_register_coalesce.cpp | 10 +++
3 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index f463739..e6470f1 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -479,11 +479,14 @@ public:
void dump_instructions();
protected:
+ void emit_vertex();
virtual dst_reg *make_reg_for_system_value(ir_variable *ir) = 0;
virtual int setup_attributes(int payload_reg) = 0;
virtual void emit_prolog() = 0;
virtual void emit_program_code() = 0;
virtual void emit_thread_end() = 0;
+ virtual void emit_urb_write_header(int mrf) = 0;
+ virtual vec4_instruction *emit_urb_write_opcode(bool complete) = 0;
};
class vec4_vs_visitor : public vec4_visitor
@@ -502,6 +505,8 @@ protected:
virtual void emit_prolog();
virtual void emit_program_code();
virtual void emit_thread_end();
+ virtual void emit_urb_write_header(int mrf);
+ virtual vec4_instruction *emit_urb_write_opcode(bool complete);
private:
void setup_vp_regs();
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 18f17c8..c61ec36 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2604,14 +2604,38 @@ align_interleaved_urb_mlen(struct brw_context *brw, int mlen)
return mlen;
}
+void
+vec4_vs_visitor::emit_urb_write_header(int mrf)
+{
+ /* No need to do anything for VS; an implied write to this MRF will be
+ * performed by VS_OPCODE_URB_WRITE.
+ */
+ (void) mrf;
+}
+
+vec4_instruction *
+vec4_vs_visitor::emit_urb_write_opcode(bool complete)
+{
+ /* For VS, the URB writes end the thread. */
+ if (complete) {
+ if (INTEL_DEBUG & DEBUG_SHADER_TIME)
+ emit_shader_time_end();
+ }
+
+ vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE);
+ inst->eot = complete;
+
+ return inst;
+}
+
/**
- * Generates the VUE payload plus the 1 or 2 URB write instructions to
- * complete the VS thread.
+ * Generates the VUE payload plus the necessary URB write instructions to
+ * output it.
*
* The VUE layout is documented in Volume 2a.
*/
void
-vec4_vs_visitor::emit_thread_end()
+vec4_visitor::emit_vertex()
{
/* MRF 0 is reserved for the debugger, so start with message header
* in MRF 1.
@@ -2630,10 +2654,10 @@ vec4_vs_visitor::emit_thread_end()
*/
assert ((max_usable_mrf - base_mrf) % 2 == 0);
- /* First mrf is the g0-based message header containing URB handles and such,
- * which is implied in VS_OPCODE_URB_WRITE.
+ /* First mrf is the g0-based message header containing URB handles and
+ * such.
*/
- mrf++;
+ emit_urb_write_header(mrf++);
if (intel->gen < 6) {
emit_ndc_computation();
@@ -2641,8 +2665,8 @@ vec4_vs_visitor::emit_thread_end()
/* Set up the VUE data for the first URB write */
int slot;
- for (slot = 0; slot < prog_data->base.vue_map.num_slots; ++slot) {
- emit_urb_slot(mrf++, prog_data->base.vue_map.slot_to_varying[slot]);
+ for (slot = 0; slot < vec4_prog_data->vue_map.num_slots; ++slot) {
+ emit_urb_slot(mrf++, vec4_prog_data->vue_map.slot_to_varying[slot]);
/* If this was max_usable_mrf, we can't fit anything more into this URB
* WRITE.
@@ -2653,35 +2677,26 @@ vec4_vs_visitor::emit_thread_end()
}
}
- bool eot = slot >= prog_data->base.vue_map.num_slots;
- if (eot) {
- if (INTEL_DEBUG & DEBUG_SHADER_TIME)
- emit_shader_time_end();
- }
+ bool complete = slot >= vec4_prog_data->vue_map.num_slots;
current_annotation = "URB write";
- vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE);
+ vec4_instruction *inst = emit_urb_write_opcode(complete);
inst->base_mrf = base_mrf;
inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf);
- inst->eot = eot;
/* Optional second URB write */
- if (!inst->eot) {
+ if (!complete) {
mrf = base_mrf + 1;
- for (; slot < prog_data->base.vue_map.num_slots; ++slot) {
+ for (; slot < vec4_prog_data->vue_map.num_slots; ++slot) {
assert(mrf < max_usable_mrf);
- emit_urb_slot(mrf++, prog_data->base.vue_map.slot_to_varying[slot]);
+ emit_urb_slot(mrf++, vec4_prog_data->vue_map.slot_to_varying[slot]);
}
- if (INTEL_DEBUG & DEBUG_SHADER_TIME)
- emit_shader_time_end();
-
current_annotation = "URB write";
- inst = emit(VS_OPCODE_URB_WRITE);
+ inst = emit_urb_write_opcode(true /* complete */);
inst->base_mrf = base_mrf;
inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf);
- inst->eot = true;
/* URB destination offset. In the previous write, we got MRFs
* 2-13 minus the one header MRF, so 12 regs. URB offset is in
* URB row increments, and each of our MRFs is half of one of
@@ -2691,6 +2706,16 @@ vec4_vs_visitor::emit_thread_end()
}
}
+void
+vec4_vs_visitor::emit_thread_end()
+{
+ /* For VS, we always end the thread by emitting a single vertex.
+ * emit_urb_write_opcode() will take care of setting the eot flag on the
+ * SEND instruction.
+ */
+ emit_vertex();
+}
+
src_reg
vec4_visitor::get_scratch_offset(vec4_instruction *inst,
src_reg *reladdr, int reg_offset)
diff --git a/src/mesa/drivers/dri/i965/test_vec4_register_coalesce.cpp b/src/mesa/drivers/dri/i965/test_vec4_register_coalesce.cpp
index 6d2bbf8..595f519 100644
--- a/src/mesa/drivers/dri/i965/test_vec4_register_coalesce.cpp
+++ b/src/mesa/drivers/dri/i965/test_vec4_register_coalesce.cpp
@@ -79,6 +79,16 @@ protected:
{
assert(!"Not reached");
}
+
+ virtual void emit_urb_write_header(int mrf)
+ {
+ assert(!"Not reached");
+ }
+
+ virtual vec4_instruction *emit_urb_write_opcode(bool complete)
+ {
+ assert(!"Not reached");
+ }
};
--
1.8.2
More information about the mesa-dev
mailing list