summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan Cain <[email protected]>2013-02-15 09:26:35 -0600
committerPaul Berry <[email protected]>2013-08-01 20:20:16 -0700
commitae6eba3e32a142665d2ae6e15c9122d3201c0b5d (patch)
tree924e3137d87fb4f2cd8878dd5d87399ae8b9e026
parentc6be77ee6fe27233f42e98e50002c4b0bdc02913 (diff)
glsl: add ir_emit_vertex and ir_end_primitive instruction types
These correspond to the EmitVertex and EndPrimitive functions in GLSL. v2 (Paul Berry <[email protected]>): Add stub implementations of new pure visitor functions to i965's vec4_visitor and fs_visitor classes. v3 (Paul Berry <[email protected]>): Rename classes to be more consistent with the names used in the GL spec. Reviewed-by: Ian Romanick <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/glsl/ir.h51
-rw-r--r--src/glsl/ir_hierarchical_visitor.cpp18
-rw-r--r--src/glsl/ir_hierarchical_visitor.h2
-rw-r--r--src/glsl/ir_hv_accept.cpp13
-rw-r--r--src/glsl/ir_print_visitor.cpp12
-rw-r--r--src/glsl/ir_print_visitor.h2
-rw-r--r--src/glsl/ir_reader.cpp30
-rw-r--r--src/glsl/ir_visitor.h4
-rw-r--r--src/glsl/lower_output_reads.cpp13
-rw-r--r--src/glsl/opt_dead_code_local.cpp17
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h2
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp12
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.h2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp12
-rw-r--r--src/mesa/program/ir_to_mesa.cpp14
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp14
16 files changed, 217 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;
};
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
@@ -2582,6 +2582,18 @@ vec4_visitor::visit(ir_if *ir)
}
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()
{
/* Get the position */
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;