[Mesa-dev] [PATCH 09/34] glsl: add ir_emitvertex and ir_endprim instruction types

Paul Berry stereotype441 at gmail.com
Sun Jul 28 23:03:35 PDT 2013


From: Bryan Cain <bryancain3 at gmail.com>

These correspond to the EmitVertex and EndPrimitive functions in GLSL.

v2 (Paul Berry <stereotype441 at gmail.com>): Add stub implementations of
new pure visitor functions to i965's vec4_visitor and fs_visitor
classes.
---
 src/glsl/ir.h                                  | 51 ++++++++++++++++++++++++++
 src/glsl/ir_hierarchical_visitor.cpp           | 18 +++++++++
 src/glsl/ir_hierarchical_visitor.h             |  2 +
 src/glsl/ir_hv_accept.cpp                      | 13 +++++++
 src/glsl/ir_print_visitor.cpp                  | 12 ++++++
 src/glsl/ir_print_visitor.h                    |  2 +
 src/glsl/ir_reader.cpp                         | 30 +++++++++++++++
 src/glsl/ir_visitor.h                          |  4 ++
 src/glsl/lower_output_reads.cpp                | 13 ++++++-
 src/glsl/opt_dead_code_local.cpp               | 17 +++++++++
 src/mesa/drivers/dri/i965/brw_fs.h             |  2 +
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp   | 12 ++++++
 src/mesa/drivers/dri/i965/brw_vec4.h           |  2 +
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 12 ++++++
 src/mesa/program/ir_to_mesa.cpp                | 14 +++++++
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp     | 14 +++++++
 16 files changed, 217 insertions(+), 1 deletion(-)

diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 7ac291c..ae79a39 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -81,6 +81,8 @@ enum ir_node_type {
    ir_type_return,
    ir_type_swizzle,
    ir_type_texture,
+   ir_type_emitvertex,
+   ir_type_endprim,
    ir_type_max /**< maximum ir_type enum number, for validation */
 };
 
@@ -519,6 +521,8 @@ public:
     *
     *   - Vertex shader input: one of the values from \c gl_vert_attrib.
     *   - Vertex shader output: one of the values from \c gl_varying_slot.
+    *   - Geometry shader input: one of the values from \c gl_varying_slot.
+    *   - Geometry shader output: one of the values from \c gl_varying_slot.
     *   - Fragment shader input: one of the values from \c gl_varying_slot.
     *   - Fragment shader output: one of the values from \c gl_frag_result.
     *   - Uniforms: Per-stage uniform slot number for default uniform block.
@@ -1992,6 +1996,53 @@ private:
 /*@}*/
 
 /**
+ * IR instruction to emit a vertex in a geometry shader.
+ */
+class ir_emitvertex : public ir_instruction {
+public:
+   ir_emitvertex()
+   {
+      ir_type = ir_type_emitvertex;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_emitvertex *clone(void *mem_ctx, struct hash_table *) const
+   {
+      return new(mem_ctx) ir_emitvertex();
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+};
+
+/**
+ * IR instruction to complete the current primitive and start a new one in a
+ * geometry shader.
+ */
+class ir_endprim : public ir_instruction {
+public:
+   ir_endprim()
+   {
+      ir_type = ir_type_endprim;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_endprim *clone(void *mem_ctx, struct hash_table *) const
+   {
+      return new(mem_ctx) ir_endprim();
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+};
+
+/**
  * Apply a visitor to each IR node in a list
  */
 void
diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp
index f244140..9600211 100644
--- a/src/glsl/ir_hierarchical_visitor.cpp
+++ b/src/glsl/ir_hierarchical_visitor.cpp
@@ -69,6 +69,24 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir)
 }
 
 ir_visitor_status
+ir_hierarchical_visitor::visit(ir_emitvertex *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_endprim *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
 ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
 {
    if (this->callback != NULL)
diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h
index 1988ad0..6245f80 100644
--- a/src/glsl/ir_hierarchical_visitor.h
+++ b/src/glsl/ir_hierarchical_visitor.h
@@ -87,6 +87,8 @@ public:
    virtual ir_visitor_status visit(class ir_variable *);
    virtual ir_visitor_status visit(class ir_constant *);
    virtual ir_visitor_status visit(class ir_loop_jump *);
+   virtual ir_visitor_status visit(class ir_emitvertex *);
+   virtual ir_visitor_status visit(class ir_endprim *);
 
    /**
     * ir_dereference_variable isn't technically a leaf, but it is treated as a
diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp
index 559b71a..ec9a8b6 100644
--- a/src/glsl/ir_hv_accept.cpp
+++ b/src/glsl/ir_hv_accept.cpp
@@ -415,3 +415,16 @@ ir_if::accept(ir_hierarchical_visitor *v)
 
    return v->visit_leave(this);
 }
+
+ir_visitor_status
+ir_emitvertex::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_endprim::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
index ca973a5..44c4933 100644
--- a/src/glsl/ir_print_visitor.cpp
+++ b/src/glsl/ir_print_visitor.cpp
@@ -539,3 +539,15 @@ ir_print_visitor::visit(ir_loop_jump *ir)
 {
    printf("%s", ir->is_break() ? "break" : "continue");
 }
+
+void
+ir_print_visitor::visit(ir_emitvertex *ir)
+{
+   printf("(emitvertex)");
+}
+
+void
+ir_print_visitor::visit(ir_endprim *ir)
+{
+   printf("(endprim)");
+}
diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h
index a84056d..38db6a1 100644
--- a/src/glsl/ir_print_visitor.h
+++ b/src/glsl/ir_print_visitor.h
@@ -69,6 +69,8 @@ public:
    virtual void visit(ir_if *);
    virtual void visit(ir_loop *);
    virtual void visit(ir_loop_jump *);
+   virtual void visit(ir_emitvertex *);
+   virtual void visit(ir_endprim *);
    /*@}*/
 
 private:
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index 51534ca..f8fb52d 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -59,6 +59,8 @@ private:
    ir_swizzle *read_swizzle(s_expression *);
    ir_constant *read_constant(s_expression *);
    ir_texture *read_texture(s_expression *);
+   ir_emitvertex *read_emitvertex(s_expression *);
+   ir_endprim *read_endprim(s_expression *);
 
    ir_dereference *read_dereference(s_expression *);
    ir_dereference_variable *read_var_ref(s_expression *);
@@ -355,6 +357,10 @@ ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx)
       inst = read_return(list);
    } else if (strcmp(tag->value(), "function") == 0) {
       inst = read_function(list, false);
+   } else if (strcmp(tag->value(), "emitvertex") == 0) {
+      inst = read_emitvertex(list);
+   } else if (strcmp(tag->value(), "endprim") == 0) {
+      inst = read_endprim(list);
    } else {
       inst = read_rvalue(list);
       if (inst == NULL)
@@ -1065,3 +1071,27 @@ ir_reader::read_texture(s_expression *expr)
    };
    return tex;
 }
+
+ir_emitvertex *
+ir_reader::read_emitvertex(s_expression *expr)
+{
+   s_pattern pat[] = { "emitvertex" };
+
+   if (MATCH(expr, pat)) {
+      return new(mem_ctx) ir_emitvertex();
+   }
+   ir_read_error(NULL, "when reading emitvertex");
+   return NULL;
+}
+
+ir_endprim *
+ir_reader::read_endprim(s_expression *expr)
+{
+   s_pattern pat[] = { "endprim" };
+
+   if (MATCH(expr, pat)) {
+      return new(mem_ctx) ir_endprim();
+   }
+   ir_read_error(NULL, "when reading emitvertex");
+   return NULL;
+}
diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h
index bd47ef7..af0f986 100644
--- a/src/glsl/ir_visitor.h
+++ b/src/glsl/ir_visitor.h
@@ -63,6 +63,8 @@ public:
    virtual void visit(class ir_if *) = 0;
    virtual void visit(class ir_loop *) = 0;
    virtual void visit(class ir_loop_jump *) = 0;
+   virtual void visit(class ir_emitvertex *) = 0;
+   virtual void visit(class ir_endprim *) = 0;
    /*@}*/
 };
 
@@ -81,6 +83,8 @@ public:
    virtual void visit(class ir_assignment *) {}
    virtual void visit(class ir_constant *) {}
    virtual void visit(class ir_call *) {}
+   virtual void visit(class ir_emitvertex *) {}
+   virtual void visit(class ir_endprim *) {}
 };
 #endif /* __cplusplus */
 
diff --git a/src/glsl/lower_output_reads.cpp b/src/glsl/lower_output_reads.cpp
index b93e254..bc633ba 100644
--- a/src/glsl/lower_output_reads.cpp
+++ b/src/glsl/lower_output_reads.cpp
@@ -50,6 +50,7 @@ public:
    output_read_remover();
    ~output_read_remover();
    virtual ir_visitor_status visit(class ir_dereference_variable *);
+   virtual ir_visitor_status visit(class ir_emitvertex *);
    virtual ir_visitor_status visit_leave(class ir_return *);
    virtual ir_visitor_status visit_leave(class ir_function_signature *);
 };
@@ -117,7 +118,9 @@ copy(void *ctx, ir_variable *output, ir_variable *temp)
    return new(ctx) ir_assignment(lhs, rhs);
 }
 
-/** Insert a copy-back assignment before a "return" statement */
+/** Insert a copy-back assignment before a "return" statement or a call to
+ * EmitVertex().
+ */
 static void
 emit_return_copy(const void *key, void *data, void *closure)
 {
@@ -141,6 +144,14 @@ output_read_remover::visit_leave(ir_return *ir)
 }
 
 ir_visitor_status
+output_read_remover::visit(ir_emitvertex *ir)
+{
+   hash_table_call_foreach(replacements, emit_return_copy, ir);
+   hash_table_clear(replacements);
+   return visit_continue;
+}
+
+ir_visitor_status
 output_read_remover::visit_leave(ir_function_signature *sig)
 {
    if (strcmp(sig->function_name(), "main") != 0)
diff --git a/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp
index 8c31802..72a4b38 100644
--- a/src/glsl/opt_dead_code_local.cpp
+++ b/src/glsl/opt_dead_code_local.cpp
@@ -114,6 +114,23 @@ public:
       return visit_continue_with_parent;
    }
 
+   virtual ir_visitor_status visit(ir_emitvertex *ir)
+   {
+      /* For the purpose of dead code elimination, emitting a vertex counts as
+       * "reading" all of the currently assigned output variables.
+       */
+      foreach_iter(exec_list_iterator, iter, *this->assignments) {
+         assignment_entry *entry = (assignment_entry *)iter.get();
+         if (entry->lhs->mode == ir_var_shader_out) {
+            if (debug)
+               printf("kill %s\n", entry->lhs->name);
+            entry->remove();
+         }
+      }
+
+      return visit_continue;
+   }
+
 private:
    exec_list *assignments;
 };
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 0645fb7..8170e7c 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -238,6 +238,8 @@ public:
    void visit(ir_call *ir);
    void visit(ir_function *ir);
    void visit(ir_function_signature *ir);
+   void visit(ir_emitvertex *);
+   void visit(ir_endprim *);
 
    void swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler);
 
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 15d1c6a..ac9ff0f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -1991,6 +1991,18 @@ fs_visitor::visit(ir_function_signature *ir)
    (void)ir;
 }
 
+void
+fs_visitor::visit(ir_emitvertex *)
+{
+   assert(!"not reached");
+}
+
+void
+fs_visitor::visit(ir_endprim *)
+{
+   assert(!"not reached");
+}
+
 fs_inst *
 fs_visitor::emit(fs_inst inst)
 {
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index 407d8b6..46210be 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -283,6 +283,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emitvertex *);
+   virtual void visit(ir_endprim *);
    /*@}*/
 
    src_reg result;
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 1d86b33..1c162ef 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -2582,6 +2582,18 @@ vec4_visitor::visit(ir_if *ir)
 }
 
 void
+vec4_visitor::visit(ir_emitvertex *)
+{
+   assert(!"not reached");
+}
+
+void
+vec4_visitor::visit(ir_endprim *)
+{
+   assert(!"not reached");
+}
+
+void
 vec4_visitor::emit_ndc_computation()
 {
    /* Get the position */
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index f0fc1b9..e526582 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -265,6 +265,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emitvertex *);
+   virtual void visit(ir_endprim *);
    /*@}*/
 
    src_reg result;
@@ -2252,6 +2254,18 @@ ir_to_mesa_visitor::visit(ir_if *ir)
    if_inst = emit(ir->condition, OPCODE_ENDIF);
 }
 
+void
+ir_to_mesa_visitor::visit(ir_emitvertex *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
+void
+ir_to_mesa_visitor::visit(ir_endprim *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
 ir_to_mesa_visitor::ir_to_mesa_visitor()
 {
    result.file = PROGRAM_UNDEFINED;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 69c1b41..77623f9 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -369,6 +369,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emitvertex *);
+   virtual void visit(ir_endprim *);
    /*@}*/
 
    st_src_reg result;
@@ -3008,6 +3010,18 @@ glsl_to_tgsi_visitor::visit(ir_if *ir)
    if_inst = emit(ir->condition, TGSI_OPCODE_ENDIF);
 }
 
+void
+glsl_to_tgsi_visitor::visit(ir_emitvertex *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
+void
+glsl_to_tgsi_visitor::visit(ir_endprim *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
 glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
 {
    result.file = PROGRAM_UNDEFINED;
-- 
1.8.3.4



More information about the mesa-dev mailing list