diff options
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ir.h | 51 | ||||
-rw-r--r-- | src/glsl/ir_hierarchical_visitor.cpp | 18 | ||||
-rw-r--r-- | src/glsl/ir_hierarchical_visitor.h | 2 | ||||
-rw-r--r-- | src/glsl/ir_hv_accept.cpp | 13 | ||||
-rw-r--r-- | src/glsl/ir_print_visitor.cpp | 12 | ||||
-rw-r--r-- | src/glsl/ir_print_visitor.h | 2 | ||||
-rw-r--r-- | src/glsl/ir_reader.cpp | 30 | ||||
-rw-r--r-- | src/glsl/ir_visitor.h | 4 | ||||
-rw-r--r-- | src/glsl/lower_output_reads.cpp | 13 | ||||
-rw-r--r-- | src/glsl/opt_dead_code_local.cpp | 17 |
10 files changed, 161 insertions, 1 deletions
diff --git a/src/glsl/ir.h b/src/glsl/ir.h index f5b4468ec20..4cb1202e65b 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_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. @@ -1992,6 +1996,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 */ void diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp index f2441404678..2e606dda4be 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_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) { if (this->callback != NULL) diff --git a/src/glsl/ir_hierarchical_visitor.h b/src/glsl/ir_hierarchical_visitor.h index 1988ad0910b..647d2e002e5 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_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 diff --git a/src/glsl/ir_hv_accept.cpp b/src/glsl/ir_hv_accept.cpp index 559b71af38a..76a607d17cb 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_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); +} diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index ca973a5f38e..541231a33c1 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_emit_vertex *ir) +{ + printf("(emit-vertex)"); +} + +void +ir_print_visitor::visit(ir_end_primitive *ir) +{ + printf("(end-primitive)"); +} diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h index a84056d16b0..865376fe03a 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_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ private: diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index 51534ca7c56..f263fe81096 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_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; +} diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h index bd47ef7d5fa..40f96ffbca0 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_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 */ diff --git a/src/glsl/lower_output_reads.cpp b/src/glsl/lower_output_reads.cpp index b93e254ec9b..5ba9720d0dc 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_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) { @@ -141,6 +144,14 @@ output_read_remover::visit_leave(ir_return *ir) } 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) { 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 8c31802a6ac..42a30b3d878 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_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; }; |