From ae6eba3e32a142665d2ae6e15c9122d3201c0b5d Mon Sep 17 00:00:00 2001 From: Bryan Cain Date: Fri, 15 Feb 2013 09:26:35 -0600 Subject: [PATCH] glsl: add ir_emit_vertex and ir_end_primitive instruction types These correspond to the EmitVertex and EndPrimitive functions in GLSL. v2 (Paul Berry ): Add stub implementations of new pure visitor functions to i965's vec4_visitor and fs_visitor classes. v3 (Paul Berry ): Rename classes to be more consistent with the names used in the GL spec. Reviewed-by: Ian Romanick Reviewed-by: Kenneth Graunke --- 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 + .../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 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. @@ -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 */ 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 @@ -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) { 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) { @@ -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) { 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; }; diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 0645fb75a78..370ab6c3386 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_emit_vertex *); + void visit(ir_end_primitive *); 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 15d1c6a6985..ee7728cb6ec 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_emit_vertex *) +{ + assert(!"not reached"); +} + +void +fs_visitor::visit(ir_end_primitive *) +{ + 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 407d8b60485..3313a635f38 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_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ 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 525485048cf..8d4a5d42dfc 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp @@ -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() { diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 14f43f64e24..ae78aca19d3 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_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; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 69f860a0e08..d9b4ed2a010 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_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; -- 2.30.2