glsl: add ir_emit_vertex and ir_end_primitive instruction types
authorBryan Cain <bryancain3@gmail.com>
Fri, 15 Feb 2013 15:26:35 +0000 (09:26 -0600)
committerPaul Berry <stereotype441@gmail.com>
Fri, 2 Aug 2013 03:20:16 +0000 (20:20 -0700)
These correspond to the EmitVertex and EndPrimitive functions in GLSL.

v2 (Paul Berry <stereotype441@gmail.com>): Add stub implementations of
new pure visitor functions to i965's vec4_visitor and fs_visitor
classes.

v3 (Paul Berry <stereotype441@gmail.com>): Rename classes to be more
consistent with the names used in the GL spec.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
16 files changed:
src/glsl/ir.h
src/glsl/ir_hierarchical_visitor.cpp
src/glsl/ir_hierarchical_visitor.h
src/glsl/ir_hv_accept.cpp
src/glsl/ir_print_visitor.cpp
src/glsl/ir_print_visitor.h
src/glsl/ir_reader.cpp
src/glsl/ir_visitor.h
src/glsl/lower_output_reads.cpp
src/glsl/opt_dead_code_local.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
src/mesa/program/ir_to_mesa.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index f5b4468ec2054e8e7b42917fcf091da982ed8dee..4cb1202e65bf93c0cebff1862c266c115c2568cc 100644 (file)
@@ -81,6 +81,8 @@ enum ir_node_type {
    ir_type_return,
    ir_type_swizzle,
    ir_type_texture,
+   ir_type_emit_vertex,
+   ir_type_end_primitive,
    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.
@@ -1991,6 +1995,53 @@ private:
 
 /*@}*/
 
+/**
+ * IR instruction to emit a vertex in a geometry shader.
+ */
+class ir_emit_vertex : public ir_instruction {
+public:
+   ir_emit_vertex()
+   {
+      ir_type = ir_type_emit_vertex;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const
+   {
+      return new(mem_ctx) ir_emit_vertex();
+   }
+
+   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_end_primitive : public ir_instruction {
+public:
+   ir_end_primitive()
+   {
+      ir_type = ir_type_end_primitive;
+   }
+
+   virtual void accept(ir_visitor *v)
+   {
+      v->visit(this);
+   }
+
+   virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const
+   {
+      return new(mem_ctx) ir_end_primitive();
+   }
+
+   virtual ir_visitor_status accept(ir_hierarchical_visitor *);
+};
+
 /**
  * Apply a visitor to each IR node in a list
  */
index f2441404678981e73109a3f4ecd316948b306e64..2e606dda4bef26500c08cdf7f0b8a73fb2bb5108 100644 (file)
@@ -68,6 +68,24 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir)
    return visit_continue;
 }
 
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_emit_vertex *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_hierarchical_visitor::visit(ir_end_primitive *ir)
+{
+   if (this->callback != NULL)
+      this->callback(ir, this->data);
+
+   return visit_continue;
+}
+
 ir_visitor_status
 ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
 {
index 1988ad0910bf556d124c6d90a190600f04dfe78e..647d2e002e522f4eb9c02b468fcdd88c9080aa3b 100644 (file)
@@ -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_emit_vertex *);
+   virtual ir_visitor_status visit(class ir_end_primitive *);
 
    /**
     * ir_dereference_variable isn't technically a leaf, but it is treated as a
index 559b71af38ab8e591b18bd916aa710c3d3fcc3d7..76a607d17cb940a0a41d28aaf19e2d022e917f8a 100644 (file)
@@ -415,3 +415,16 @@ ir_if::accept(ir_hierarchical_visitor *v)
 
    return v->visit_leave(this);
 }
+
+ir_visitor_status
+ir_emit_vertex::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
+
+
+ir_visitor_status
+ir_end_primitive::accept(ir_hierarchical_visitor *v)
+{
+   return v->visit(this);
+}
index ca973a5f38ec468a0e7d7751f65a4eb6f87a8dd4..541231a33c1da9bd59b29a20507ec62053437a4d 100644 (file)
@@ -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_emit_vertex *ir)
+{
+   printf("(emit-vertex)");
+}
+
+void
+ir_print_visitor::visit(ir_end_primitive *ir)
+{
+   printf("(end-primitive)");
+}
index a84056d16b0a676a0896fffb182f9e945ca75946..865376fe03abebc9bb00f216cf8e188fb061a4da 100644 (file)
@@ -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_emit_vertex *);
+   virtual void visit(ir_end_primitive *);
    /*@}*/
 
 private:
index 51534ca7c563a185c9cceffeb51e81f69700f63e..f263fe8109697f52c742804381afbcd23e1fcd45 100644 (file)
@@ -59,6 +59,8 @@ private:
    ir_swizzle *read_swizzle(s_expression *);
    ir_constant *read_constant(s_expression *);
    ir_texture *read_texture(s_expression *);
+   ir_emit_vertex *read_emit_vertex(s_expression *);
+   ir_end_primitive *read_end_primitive(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(), "emit-vertex") == 0) {
+      inst = read_emit_vertex(list);
+   } else if (strcmp(tag->value(), "end-primitive") == 0) {
+      inst = read_end_primitive(list);
    } else {
       inst = read_rvalue(list);
       if (inst == NULL)
@@ -1065,3 +1071,27 @@ ir_reader::read_texture(s_expression *expr)
    };
    return tex;
 }
+
+ir_emit_vertex *
+ir_reader::read_emit_vertex(s_expression *expr)
+{
+   s_pattern pat[] = { "emit-vertex" };
+
+   if (MATCH(expr, pat)) {
+      return new(mem_ctx) ir_emit_vertex();
+   }
+   ir_read_error(NULL, "when reading emit-vertex");
+   return NULL;
+}
+
+ir_end_primitive *
+ir_reader::read_end_primitive(s_expression *expr)
+{
+   s_pattern pat[] = { "end-primitive" };
+
+   if (MATCH(expr, pat)) {
+      return new(mem_ctx) ir_end_primitive();
+   }
+   ir_read_error(NULL, "when reading end-primitive");
+   return NULL;
+}
index bd47ef7d5faa946743f241f9cd3a000ecec3ec54..40f96ffbca0384a7673396fdf7386be163f78a61 100644 (file)
@@ -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_emit_vertex *) = 0;
+   virtual void visit(class ir_end_primitive *) = 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_emit_vertex *) {}
+   virtual void visit(class ir_end_primitive *) {}
 };
 #endif /* __cplusplus */
 
index b93e254ec9b5d07580e9aa8038d2f7830b59a45d..5ba9720d0dc36239a15b24bf5ed20461a6cacdc5 100644 (file)
@@ -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_emit_vertex *);
    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)
 {
@@ -140,6 +143,14 @@ output_read_remover::visit_leave(ir_return *ir)
    return visit_continue;
 }
 
+ir_visitor_status
+output_read_remover::visit(ir_emit_vertex *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)
 {
index 8c31802a6ac1ac090e42e27c41a3d1794222dbfc..42a30b3d878b4a76d9811768e05faa4a521289dd 100644 (file)
@@ -114,6 +114,23 @@ public:
       return visit_continue_with_parent;
    }
 
+   virtual ir_visitor_status visit(ir_emit_vertex *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;
 };
index 0645fb75a78528de7b1f1aee51375db3a9c9d256..370ab6c33863563086f08deaa6f6cc043a1c82ac 100644 (file)
@@ -238,6 +238,8 @@ public:
    void visit(ir_call *ir);
    void visit(ir_function *ir);
    void visit(ir_function_signature *ir);
+   void visit(ir_emit_vertex *);
+   void visit(ir_end_primitive *);
 
    void swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler);
 
index 15d1c6a6985c199966286788e89a5d52becd24fe..ee7728cb6ec2948af92931a2f5c0267d93984e4f 100644 (file)
@@ -1991,6 +1991,18 @@ fs_visitor::visit(ir_function_signature *ir)
    (void)ir;
 }
 
+void
+fs_visitor::visit(ir_emit_vertex *)
+{
+   assert(!"not reached");
+}
+
+void
+fs_visitor::visit(ir_end_primitive *)
+{
+   assert(!"not reached");
+}
+
 fs_inst *
 fs_visitor::emit(fs_inst inst)
 {
index 407d8b604856881c9d164e973152fe5e7ddec513..3313a635f38dc76ace7bc7195bdc9eb457e88fa4 100644 (file)
@@ -283,6 +283,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emit_vertex *);
+   virtual void visit(ir_end_primitive *);
    /*@}*/
 
    src_reg result;
index 525485048cfc4ff16422523b3cab1b6ad58bb9be..8d4a5d42dfcea2af88aeb48d693b9a53cd5a2b5d 100644 (file)
@@ -2581,6 +2581,18 @@ vec4_visitor::visit(ir_if *ir)
    emit(BRW_OPCODE_ENDIF);
 }
 
+void
+vec4_visitor::visit(ir_emit_vertex *)
+{
+   assert(!"not reached");
+}
+
+void
+vec4_visitor::visit(ir_end_primitive *)
+{
+   assert(!"not reached");
+}
+
 void
 vec4_visitor::emit_ndc_computation()
 {
index 14f43f64e24e1264580bcdd2a93374aa17598357..ae78aca19d387ea788270a6ed3ee34b92a82abcf 100644 (file)
@@ -265,6 +265,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emit_vertex *);
+   virtual void visit(ir_end_primitive *);
    /*@}*/
 
    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_emit_vertex *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
+void
+ir_to_mesa_visitor::visit(ir_end_primitive *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
 ir_to_mesa_visitor::ir_to_mesa_visitor()
 {
    result.file = PROGRAM_UNDEFINED;
index 69f860a0e083b9f1e5e6a10a964a7f34d8ac577b..d9b4ed2a010b547f8697ea68ec9cb22cb144917c 100644 (file)
@@ -369,6 +369,8 @@ public:
    virtual void visit(ir_discard *);
    virtual void visit(ir_texture *);
    virtual void visit(ir_if *);
+   virtual void visit(ir_emit_vertex *);
+   virtual void visit(ir_end_primitive *);
    /*@}*/
 
    st_src_reg result;
@@ -3015,6 +3017,18 @@ glsl_to_tgsi_visitor::visit(ir_if *ir)
    if_inst = emit(ir->condition, TGSI_OPCODE_ENDIF);
 }
 
+void
+glsl_to_tgsi_visitor::visit(ir_emit_vertex *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
+void
+glsl_to_tgsi_visitor::visit(ir_end_primitive *ir)
+{
+   assert(!"Geometry shaders not supported.");
+}
+
 glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
 {
    result.file = PROGRAM_UNDEFINED;