[Mesa-dev] [PATCH 7/8] i965/vs: Split final assembly code generation out of vec4_visitor.

Kenneth Graunke kenneth at whitecape.org
Tue Nov 27 00:42:32 PST 2012


Compiling shaders requires several main steps:

   1. Generating VS IR from either GLSL IR or Mesa IR
   2. Optimizing the IR
   3. Register allocation
   4. Generating assembly code

This patch splits out step 4 into a separate class named "vec4_generator."

There are several reasons for doing so:

   1. Future hardware has a different instruction encoding.  Splitting
      this out will allow us to replace vec4_generator (which relies
      heavily on the brw_eu_emit.c code and struct brw_instruction) with
      a new code generator that writes the new format.

   2. It reduces the size of the vec4_visitor monolith.  (Arguably, a lot
      more should be split out, but that's left for "future work.")

   3. Separate namespaces allow us to make helper functions for
      generating instructions in both classes: ADD() can exist in
      vec4_visitor and create IR, while ADD() in vec4_generator() can
      create brw_instructions.  (Patches for this upcoming.)
---
 src/mesa/drivers/dri/i965/brw_vec4.cpp         |  10 +--
 src/mesa/drivers/dri/i965/brw_vec4.h           |  44 ++++++++++-
 src/mesa/drivers/dri/i965/brw_vec4_emit.cpp    | 104 +++++++++++++++----------
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp |   1 -
 4 files changed, 106 insertions(+), 53 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index d5f1abe..d705235 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -1113,13 +1113,6 @@ vec4_visitor::run()
          break;
    }
 
-   if (failed)
-      return false;
-
-   brw_set_access_mode(p, BRW_ALIGN_16);
-
-   generate_code();
-
    return !failed;
 }
 
@@ -1185,7 +1178,8 @@ brw_vs_emit(struct brw_context *brw,
       return NULL;
    }
 
-   return brw_get_program(&c->func, final_assembly_size);
+   vec4_generator g(brw, c, prog, mem_ctx);
+   return g.generate_assembly(&v.instructions, final_assembly_size);
 }
 
 } /* extern "C" */
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 3d9d0dc..d060941 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -195,6 +195,12 @@ public:
    bool is_math();
 };
 
+/**
+ * The vertex shader front-end.
+ *
+ * Translates either GLSL IR or Mesa IR (for ARB_vertex_program and
+ * fixed-function) into VS IR.
+ */
 class vec4_visitor : public backend_visitor
 {
 public:
@@ -218,7 +224,6 @@ public:
    const struct gl_vertex_program *vp;
    struct brw_vs_compile *c;
    struct brw_vs_prog_data *prog_data;
-   struct brw_compile *p;
 
    char *fail_msg;
    bool failed;
@@ -448,7 +453,28 @@ public:
 
    bool process_move_condition(ir_rvalue *ir);
 
-   void generate_code();
+   void dump_instruction(vec4_instruction *inst);
+   void dump_instructions();
+};
+
+/**
+ * The vertex shader code generator.
+ *
+ * Translates VS IR to actual i965 assembly code.
+ */
+class vec4_generator
+{
+public:
+   vec4_generator(struct brw_context *brw,
+                  struct brw_vs_compile *c,
+                  struct gl_shader_program *prog,
+                  void *mem_ctx);
+   ~vec4_generator();
+
+   const unsigned *generate_assembly(exec_list *insts, unsigned *asm_size);
+
+private:
+   void generate_code(exec_list *instructions);
    void generate_vs_instruction(vec4_instruction *inst,
 				struct brw_reg dst,
 				struct brw_reg *src);
@@ -491,8 +517,18 @@ public:
 				    struct brw_reg index,
 				    struct brw_reg offset);
 
-   void dump_instruction(vec4_instruction *inst);
-   void dump_instructions();
+   struct brw_context *brw;
+   struct intel_context *intel;
+   struct gl_context *ctx;
+
+   struct brw_compile *p;
+   struct brw_vs_compile *c;
+
+   struct gl_shader_program *prog;
+   struct gl_shader *shader;
+   const struct gl_vertex_program *vp;
+
+   void *mem_ctx;
 };
 
 } /* namespace brw */
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp b/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
index a2a5975..c033804 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
@@ -132,10 +132,25 @@ vec4_instruction::get_src(int i)
    return brw_reg;
 }
 
+vec4_generator::vec4_generator(struct brw_context *brw,
+                               struct brw_vs_compile *c,
+                               struct gl_shader_program *prog,
+                               void *mem_ctx)
+   : brw(brw), c(c), prog(prog), mem_ctx(mem_ctx)
+{
+   intel = &brw->intel;
+   vp = &c->vp->program;
+   p = &c->func;
+}
+
+vec4_generator::~vec4_generator()
+{
+}
+
 void
-vec4_visitor::generate_math1_gen4(vec4_instruction *inst,
-				  struct brw_reg dst,
-				  struct brw_reg src)
+vec4_generator::generate_math1_gen4(vec4_instruction *inst,
+                                    struct brw_reg dst,
+                                    struct brw_reg src)
 {
    brw_math(p,
 	    dst,
@@ -156,9 +171,9 @@ check_gen6_math_src_arg(struct brw_reg src)
 }
 
 void
-vec4_visitor::generate_math1_gen6(vec4_instruction *inst,
-				  struct brw_reg dst,
-				  struct brw_reg src)
+vec4_generator::generate_math1_gen6(vec4_instruction *inst,
+                                    struct brw_reg dst,
+                                    struct brw_reg src)
 {
    /* Can't do writemask because math can't be align16. */
    assert(dst.dw1.bits.writemask == WRITEMASK_XYZW);
@@ -176,10 +191,10 @@ vec4_visitor::generate_math1_gen6(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_math2_gen7(vec4_instruction *inst,
-				  struct brw_reg dst,
-				  struct brw_reg src0,
-				  struct brw_reg src1)
+vec4_generator::generate_math2_gen7(vec4_instruction *inst,
+                                    struct brw_reg dst,
+                                    struct brw_reg src0,
+                                    struct brw_reg src1)
 {
    brw_math2(p,
 	     dst,
@@ -188,10 +203,10 @@ vec4_visitor::generate_math2_gen7(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_math2_gen6(vec4_instruction *inst,
-				  struct brw_reg dst,
-				  struct brw_reg src0,
-				  struct brw_reg src1)
+vec4_generator::generate_math2_gen6(vec4_instruction *inst,
+                                    struct brw_reg dst,
+                                    struct brw_reg src0,
+                                    struct brw_reg src1)
 {
    /* Can't do writemask because math can't be align16. */
    assert(dst.dw1.bits.writemask == WRITEMASK_XYZW);
@@ -208,10 +223,10 @@ vec4_visitor::generate_math2_gen6(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_math2_gen4(vec4_instruction *inst,
-				  struct brw_reg dst,
-				  struct brw_reg src0,
-				  struct brw_reg src1)
+vec4_generator::generate_math2_gen4(vec4_instruction *inst,
+                                    struct brw_reg dst,
+                                    struct brw_reg src0,
+                                    struct brw_reg src1)
 {
    /* From the Ironlake PRM, Volume 4, Part 1, Section 6.1.13
     * "Message Payload":
@@ -242,9 +257,9 @@ vec4_visitor::generate_math2_gen4(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_tex(vec4_instruction *inst,
-			   struct brw_reg dst,
-			   struct brw_reg src)
+vec4_generator::generate_tex(vec4_instruction *inst,
+                             struct brw_reg dst,
+                             struct brw_reg src)
 {
    int msg_type = -1;
 
@@ -356,7 +371,7 @@ vec4_visitor::generate_tex(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_urb_write(vec4_instruction *inst)
+vec4_generator::generate_urb_write(vec4_instruction *inst)
 {
    brw_urb_WRITE(p,
 		 brw_null_reg(), /* dest */
@@ -373,8 +388,8 @@ vec4_visitor::generate_urb_write(vec4_instruction *inst)
 }
 
 void
-vec4_visitor::generate_oword_dual_block_offsets(struct brw_reg m1,
-						struct brw_reg index)
+vec4_generator::generate_oword_dual_block_offsets(struct brw_reg m1,
+                                                  struct brw_reg index)
 {
    int second_vertex_offset;
 
@@ -410,9 +425,9 @@ vec4_visitor::generate_oword_dual_block_offsets(struct brw_reg m1,
 }
 
 void
-vec4_visitor::generate_scratch_read(vec4_instruction *inst,
-				    struct brw_reg dst,
-				    struct brw_reg index)
+vec4_generator::generate_scratch_read(vec4_instruction *inst,
+                                      struct brw_reg dst,
+                                      struct brw_reg index)
 {
    struct brw_reg header = brw_vec8_grf(0, 0);
 
@@ -448,10 +463,10 @@ vec4_visitor::generate_scratch_read(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_scratch_write(vec4_instruction *inst,
-				     struct brw_reg dst,
-				     struct brw_reg src,
-				     struct brw_reg index)
+vec4_generator::generate_scratch_write(vec4_instruction *inst,
+                                       struct brw_reg dst,
+                                       struct brw_reg src,
+                                       struct brw_reg index)
 {
    struct brw_reg header = brw_vec8_grf(0, 0);
    bool write_commit;
@@ -521,10 +536,10 @@ vec4_visitor::generate_scratch_write(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_pull_constant_load(vec4_instruction *inst,
-					  struct brw_reg dst,
-					  struct brw_reg index,
-					  struct brw_reg offset)
+vec4_generator::generate_pull_constant_load(vec4_instruction *inst,
+                                            struct brw_reg dst,
+                                            struct brw_reg index,
+                                            struct brw_reg offset)
 {
    assert(index.file == BRW_IMMEDIATE_VALUE &&
 	  index.type == BRW_REGISTER_TYPE_UD);
@@ -581,9 +596,9 @@ vec4_visitor::generate_pull_constant_load(vec4_instruction *inst,
 }
 
 void
-vec4_visitor::generate_vs_instruction(vec4_instruction *instruction,
-				      struct brw_reg dst,
-				      struct brw_reg *src)
+vec4_generator::generate_vs_instruction(vec4_instruction *instruction,
+                                        struct brw_reg dst,
+                                        struct brw_reg *src)
 {
    vec4_instruction *inst = (vec4_instruction *)instruction;
 
@@ -651,7 +666,7 @@ vec4_visitor::generate_vs_instruction(vec4_instruction *instruction,
 }
 
 void
-vec4_visitor::generate_code()
+vec4_generator::generate_code(exec_list *instructions)
 {
    int last_native_insn_offset = 0;
    const char *last_annotation_string = NULL;
@@ -665,7 +680,7 @@ vec4_visitor::generate_code()
       }
    }
 
-   foreach_list(node, &this->instructions) {
+   foreach_list(node, instructions) {
       vec4_instruction *inst = (vec4_instruction *)node;
       struct brw_reg src[3], dst;
 
@@ -845,4 +860,13 @@ vec4_visitor::generate_code()
    }
 }
 
+const unsigned *
+vec4_generator::generate_assembly(exec_list *instructions,
+                                  unsigned *assembly_size)
+{
+   brw_set_access_mode(p, BRW_ALIGN_16);
+   generate_code(instructions);
+   return brw_get_program(p, assembly_size);
+}
+
 } /* namespace brw */
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 4579e0c..aaf932f 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2813,7 +2813,6 @@ vec4_visitor::vec4_visitor(struct brw_context *brw,
 			   void *mem_ctx)
 {
    this->c = c;
-   this->p = &c->func;
    this->brw = brw;
    this->intel = &brw->intel;
    this->ctx = &intel->ctx;
-- 
1.8.0



More information about the mesa-dev mailing list