This patch enables GLSL to parse geometry shader and generate corresponding ir tree (behaviour of glCompileShader). It adds ir_gs_function type to represent EmitVertex and EndPrimitive function. - This patch does not make linking of geometry shader possible. - This patch does not implement GS part of GLSL 1.5 but GS from http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
# Patch for review only # openGL API part is not covered yet --- src/glsl/ast_to_hir.cpp | 2 + src/glsl/builtin_variables.h | 14 ++++++ src/glsl/builtins/ir/EmitVertex | 5 ++ src/glsl/builtins/ir/EndPrimitive | 5 ++ .../builtins/profiles/EXT_geometry_shader.geom | 2 + src/glsl/builtins/tools/generate_builtins.py | 4 +- src/glsl/glsl_parser_extras.h | 1 + src/glsl/ir.h | 29 ++++++++++++ src/glsl/ir_basic_block.cpp | 7 +++ src/glsl/ir_clone.cpp | 6 +++ src/glsl/ir_hierarchical_visitor.cpp | 9 ++++ src/glsl/ir_hierarchical_visitor.h | 1 + src/glsl/ir_hv_accept.cpp | 6 +++ src/glsl/ir_print_visitor.cpp | 13 +++++ src/glsl/ir_print_visitor.h | 1 + src/glsl/ir_reader.cpp | 22 +++++++++ src/glsl/ir_variable.cpp | 47 ++++++++++++++++++++ src/glsl/ir_visitor.h | 1 + src/glsl/linker.cpp | 27 ++++++++++-- src/glsl/lower_jumps.cpp | 5 ++ src/mesa/main/shaderapi.c | 5 +- src/mesa/program/ir_to_mesa.cpp | 7 +++ src/mesa/program/programopt.c | 2 +- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 7 +++ 24 files changed, 220 insertions(+), 8 deletions(-) create mode 100644 src/glsl/builtins/ir/EmitVertex create mode 100644 src/glsl/builtins/ir/EndPrimitive create mode 100644 src/glsl/builtins/profiles/EXT_geometry_shader.geom diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 9e7496b..eb55fd1 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -59,6 +59,8 @@ void _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { + // TODO : this should be enabled with other EXT + state->EXT_geometry_shader_enable = true; _mesa_glsl_initialize_variables(instructions, state); _mesa_glsl_initialize_functions(state); diff --git a/src/glsl/builtin_variables.h b/src/glsl/builtin_variables.h index 9b4f5d9..8509a25 100644 --- a/src/glsl/builtin_variables.h +++ b/src/glsl/builtin_variables.h @@ -35,6 +35,20 @@ static const builtin_variable builtin_core_vs_variables[] = { { ir_var_out, VERT_RESULT_PSIZ, "float", "gl_PointSize" }, }; +static const builtin_variable builtin_core_gs_variables[] = { + { ir_var_in, GEOM_ATTRIB_PRIMITIVE_ID, "int", "gl_PrimitiveIDIn" }, + { ir_var_out, GEOM_RESULT_COL0, "vec4", "gl_FrontColor" }, + { ir_var_out, GEOM_RESULT_COL1, "vec4", "gl_BackColor" }, + { ir_var_out, GEOM_RESULT_SCOL0, "vec4", "gl_FrontSecondaryColor" }, + { ir_var_out, GEOM_RESULT_SCOL1, "vec4", "gl_BackSecondaryColor" }, + { ir_var_out, GEOM_RESULT_FOGC, "float", "gl_FogFragCoord" }, + { ir_var_out, GEOM_RESULT_POS, "vec4", "gl_Position" }, + { ir_var_out, GEOM_RESULT_CLPV, "vec4", "gl_ClipVertex" }, + { ir_var_out, GEOM_RESULT_PSIZ, "float", "gl_PointSize" }, + { ir_var_out, GEOM_RESULT_PRID, "int", "gl_PrimitiveId" }, + { ir_var_out, GEOM_RESULT_LAYR, "int", "gl_Layer" }, +}; + static const builtin_variable builtin_core_fs_variables[] = { { ir_var_in, FRAG_ATTRIB_WPOS, "vec4", "gl_FragCoord" }, { ir_var_in, FRAG_ATTRIB_FACE, "bool", "gl_FrontFacing" }, diff --git a/src/glsl/builtins/ir/EmitVertex b/src/glsl/builtins/ir/EmitVertex new file mode 100644 index 0000000..8fdb80c --- /dev/null +++ b/src/glsl/builtins/ir/EmitVertex @@ -0,0 +1,5 @@ +((function EmitVertex + (signature void + (parameters) + ((gs_function EMITVERTEX))) +)) diff --git a/src/glsl/builtins/ir/EndPrimitive b/src/glsl/builtins/ir/EndPrimitive new file mode 100644 index 0000000..2e7a1ed --- /dev/null +++ b/src/glsl/builtins/ir/EndPrimitive @@ -0,0 +1,5 @@ +((function EndPrimitive + (signature void + (parameters) + ((gs_function ENDPRIMITIVE))) +)) diff --git a/src/glsl/builtins/profiles/EXT_geometry_shader.geom b/src/glsl/builtins/profiles/EXT_geometry_shader.geom new file mode 100644 index 0000000..0338eb3 --- /dev/null +++ b/src/glsl/builtins/profiles/EXT_geometry_shader.geom @@ -0,0 +1,2 @@ +void EmitVertex(); +void EndPrimitive(); \ No newline at end of file diff --git a/src/glsl/builtins/tools/generate_builtins.py b/src/glsl/builtins/tools/generate_builtins.py index 17d528c..99c7846 100755 --- a/src/glsl/builtins/tools/generate_builtins.py +++ b/src/glsl/builtins/tools/generate_builtins.py @@ -242,8 +242,10 @@ _mesa_glsl_initialize_functions(struct _mesa_glsl_parse_state *state) check = 'state->target == vertex_shader && ' elif profile.endswith('_frag'): check = 'state->target == fragment_shader && ' + elif profile.endswith('_geom'): + check = 'state->target == geometry_shader && ' - version = re.sub(r'_(vert|frag)$', '', profile) + version = re.sub(r'_(vert|frag|geom)$', '', profile) if version.isdigit(): check += 'state->language_version == ' + version else: # an extension name diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index dc6911d..7e16bd6 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -186,6 +186,7 @@ struct _mesa_glsl_parse_state { bool AMD_shader_stencil_export_warn; bool OES_texture_3D_enable; bool OES_texture_3D_warn; + bool EXT_geometry_shader_enable; /*@}*/ /** Extensions supported by the OpenGL implementation. */ diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 2e899f3..d24e3ce 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -78,6 +78,7 @@ enum ir_node_type { ir_type_return, ir_type_swizzle, ir_type_texture, + ir_type_gs_function, ir_type_max /**< maximum ir_type enum number, for validation */ }; @@ -120,6 +121,7 @@ public: virtual class ir_swizzle * as_swizzle() { return NULL; } virtual class ir_constant * as_constant() { return NULL; } virtual class ir_discard * as_discard() { return NULL; } + virtual class ir_gs_function * as_gs_function() { return NULL; } /*@}*/ protected: @@ -1626,6 +1628,33 @@ private: /*@}*/ +enum gs_function_name { + EmitVertex, + EndPrimitive, +}; + +class ir_gs_function : public ir_instruction { +public: + gs_function_name type; + + ir_gs_function(gs_function_name t) { + type = t; + this->ir_type = ir_type_gs_function; + } + + virtual ir_gs_function *clone(void *mem_ctx, hash_table *ht) const; + + virtual void accept(ir_visitor *v) { + v->visit(this); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); + + virtual ir_gs_function *as_gs_function() { + return this; + } +}; + /** * Apply a visitor to each IR node in a list */ diff --git a/src/glsl/ir_basic_block.cpp b/src/glsl/ir_basic_block.cpp index a833825..bd58d96 100644 --- a/src/glsl/ir_basic_block.cpp +++ b/src/glsl/ir_basic_block.cpp @@ -46,6 +46,13 @@ public: return visit_stop; } + virtual ir_visitor_status visit_enter(ir_gs_function *ir) + { + (void) ir; + has_call = true; + return visit_stop; + } + bool has_call; }; diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index f075736..609e672 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -114,6 +114,12 @@ ir_loop_jump::clone(void *mem_ctx, struct hash_table *ht) const return new(mem_ctx) ir_loop_jump(this->mode); } +ir_gs_function * +ir_gs_function::clone(void *mem_ctx, hash_table *ht) const +{ + return new(mem_ctx) ir_gs_function(this->type); +} + ir_if * ir_if::clone(void *mem_ctx, struct hash_table *ht) const { diff --git a/src/glsl/ir_hierarchical_visitor.cpp b/src/glsl/ir_hierarchical_visitor.cpp index b5eacd6..42ca9f2 100644 --- a/src/glsl/ir_hierarchical_visitor.cpp +++ b/src/glsl/ir_hierarchical_visitor.cpp @@ -60,6 +60,15 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir) } ir_visitor_status +ir_hierarchical_visitor::visit(ir_gs_function *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 dc177f5..32cd10b 100644 --- a/src/glsl/ir_hierarchical_visitor.h +++ b/src/glsl/ir_hierarchical_visitor.h @@ -85,6 +85,7 @@ 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_gs_function *); /** * 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 d33fc85..93aec0a 100644 --- a/src/glsl/ir_hv_accept.cpp +++ b/src/glsl/ir_hv_accept.cpp @@ -359,6 +359,12 @@ ir_discard::accept(ir_hierarchical_visitor *v) return v->visit_leave(this); } +ir_visitor_status +ir_gs_function::accept(ir_hierarchical_visitor *v) +{ + return v->visit(this); +} + ir_visitor_status ir_if::accept(ir_hierarchical_visitor *v) diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp index ea78582..9b06538 100644 --- a/src/glsl/ir_print_visitor.cpp +++ b/src/glsl/ir_print_visitor.cpp @@ -447,6 +447,19 @@ ir_print_visitor::visit(ir_discard *ir) printf(")"); } +void +ir_print_visitor::visit(ir_gs_function *ir) +{ + switch(ir->type) + { + case EmitVertex: + printf("gs_function EMITVERTEX"); + break; + case EndPrimitive: + printf("gs_function ENDPRIMITIVE"); + } +} + void ir_print_visitor::visit(ir_if *ir) diff --git a/src/glsl/ir_print_visitor.h b/src/glsl/ir_print_visitor.h index c7136f1..eee9a49 100644 --- a/src/glsl/ir_print_visitor.h +++ b/src/glsl/ir_print_visitor.h @@ -71,6 +71,7 @@ public: virtual void visit(ir_if *); virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); + virtual void visit(ir_gs_function *); /*@}*/ private: diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp index 22009ee..b58f6a0 100644 --- a/src/glsl/ir_reader.cpp +++ b/src/glsl/ir_reader.cpp @@ -59,6 +59,7 @@ private: ir_swizzle *read_swizzle(s_expression *); ir_constant *read_constant(s_expression *); ir_texture *read_texture(s_expression *); + ir_gs_function *read_gs_function(s_expression*); ir_dereference *read_dereference(s_expression *); }; @@ -236,6 +237,8 @@ ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) state->symbols->push_scope(); exec_list_iterator it = paramlist->subexpressions.iterator(); + if(it.has_next()) + { for (it.next() /* skip "parameters" */; it.has_next(); it.next()) { ir_variable *var = read_declaration((s_expression *) it.get()); if (var == NULL) @@ -243,6 +246,7 @@ ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) hir_parameters.push_tail(var); } + } ir_function_signature *sig = f->exact_matching_signature(&hir_parameters); if (sig == NULL && skip_body) { @@ -351,6 +355,8 @@ 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(), "gs_function") == 0) { + inst = read_gs_function(list); } else { inst = read_rvalue(list); if (inst == NULL) @@ -421,6 +427,22 @@ ir_reader::read_declaration(s_expression *expr) return var; } +ir_gs_function * +ir_reader::read_gs_function(s_expression* expr) +{ + s_symbol* tag; + s_pattern pat[] = {"gs_function",tag}; + if(!MATCH(expr,pat)) + ir_read_error(expr, "wrong syntax for gs_function"); + ir_gs_function *retval = NULL; + if(strcmp(tag->value(),"EMITVERTEX")==0) + retval = new(mem_ctx) ir_gs_function(EmitVertex); + if(strcmp(tag->value(),"ENDPRIMITIVE")==0) + retval = new(mem_ctx) ir_gs_function(EndPrimitive); + if(!retval) + ir_read_error(expr, "unknown gs_function: %s", tag->value()); + return retval; +} ir_if * ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp index b848769..4fb64f7 100644 --- a/src/glsl/ir_variable.cpp +++ b/src/glsl/ir_variable.cpp @@ -631,6 +631,52 @@ initialize_vs_variables(exec_list *instructions, vertex_shader); } +static void +initialize_gs_variables(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + + for (unsigned i = 0; i < Elements(builtin_core_gs_variables); i++) { + add_builtin_variable(instructions, state->symbols, + & builtin_core_gs_variables[i]); + } + + const glsl_type *const float_array_type = + glsl_type::get_array_instance(glsl_type::float_type,0); + const glsl_type *const vec4_array_type = + glsl_type::get_array_instance(glsl_type::vec4_type,0); + const glsl_type *const vec4_array_array_type = + glsl_type::get_array_instance(vec4_array_type,0); + + + // Input array variable + add_variable(instructions,state->symbols, + "gl_FrontColorIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_COLOR0); + add_variable(instructions,state->symbols, + "gl_BackColorIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_COLOR1); + add_variable(instructions,state->symbols, + "gl_FrontSecondaryColorIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_SECONDARY_COLOR0); + add_variable(instructions,state->symbols, + "gl_BackSecondaryColorIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_SECONDARY_COLOR0); + add_variable(instructions,state->symbols, + "gl_TexCoordIn",vec4_array_array_type,ir_var_in,GEOM_ATTRIB_TEX_COORD); + add_variable(instructions,state->symbols, + "gl_ForFragCoordIn",float_array_type,ir_var_in,GEOM_ATTRIB_FOG_FRAG_COORD); + add_variable(instructions,state->symbols, + "gl_PositionIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_POSITION); + add_variable(instructions,state->symbols, + "gl_ClipVertexIn",vec4_array_type,ir_var_in,GEOM_ATTRIB_CLIP_VERTEX); + add_variable(instructions,state->symbols, + "gl_PointSizeIn",float_array_type,ir_var_in,GEOM_ATTRIB_POINT_SIZE); + + // Output array variables + add_variable(instructions, state->symbols, + "gl_TexCoord", vec4_array_type, ir_var_out, GEOM_RESULT_TEX0); + + generate_110_uniforms(instructions, state); + +} + /* This function should only be called for ES, not desktop GL. */ static void @@ -849,6 +895,7 @@ _mesa_glsl_initialize_variables(exec_list *instructions, initialize_vs_variables(instructions, state); break; case geometry_shader: + initialize_gs_variables(instructions,state); break; case fragment_shader: initialize_fs_variables(instructions, state); diff --git a/src/glsl/ir_visitor.h b/src/glsl/ir_visitor.h index 7dd35fe..0f24e0a 100644 --- a/src/glsl/ir_visitor.h +++ b/src/glsl/ir_visitor.h @@ -61,6 +61,7 @@ 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_gs_function *) = 0; /*@}*/ }; diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index ba81c59..4e685f7 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1601,10 +1601,13 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) unsigned num_vert_shaders = 0; struct gl_shader **frag_shader_list; unsigned num_frag_shaders = 0; + struct gl_shader **geom_shader_list; + unsigned num_geom_shaders = 0; vert_shader_list = (struct gl_shader **) - calloc(2 * prog->NumShaders, sizeof(struct gl_shader *)); - frag_shader_list = &vert_shader_list[prog->NumShaders]; + calloc(3 * prog->NumShaders, sizeof(struct gl_shader *)); + geom_shader_list = &vert_shader_list[prog->NumShaders]; + frag_shader_list = &vert_shader_list[ 2 * prog->NumShaders]; unsigned min_version = UINT_MAX; unsigned max_version = 0; @@ -1622,8 +1625,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) num_frag_shaders++; break; case GL_GEOMETRY_SHADER: - /* FINISHME: Support geometry shaders. */ - assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER); + geom_shader_list[num_geom_shaders] = prog->Shaders[i]; + num_geom_shaders++; break; } } @@ -1682,6 +1685,22 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) sh); } + if (num_geom_shaders > 0) { + gl_shader *const sh = + link_intrastage_shaders(mem_ctx, ctx, prog, geom_shader_list, + num_geom_shaders); + + if (sh == NULL) + goto done; + + // TODO : Validate this + //if (!validate_geometry_shader_executable(prog, sh)) + // goto done; + + _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY], + sh); + } + /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and * varyings. diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp index 6187499..df4df70 100644 --- a/src/glsl/lower_jumps.cpp +++ b/src/glsl/lower_jumps.cpp @@ -440,6 +440,11 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor { */ } + virtual void visit(class ir_gs_function *) + { + + } + enum jump_strength get_jump_strength(ir_instruction* ir) { if(!ir) diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 74997ea..f8c019c 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -228,9 +228,10 @@ validate_shader_target(const struct gl_context *ctx, GLenum type) case GL_VERTEX_SHADER: return ctx->Extensions.ARB_vertex_shader; #endif -#if FEATURE_ARB_geometry_shader4 +// TODO : Enable FEATURE_ARB_geometry_shader4 in configure/Makefile +#if FEATURE_ARB_geometry_shader4 || 1 case GL_GEOMETRY_SHADER_ARB: - return ctx->Extensions.ARB_geometry_shader4; + return ctx->Extensions.ARB_geometry_shader4 || true; #endif default: return false; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 6820e4c..72fa55f 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -268,6 +268,7 @@ public: virtual void visit(ir_discard *); virtual void visit(ir_texture *); virtual void visit(ir_if *); + virtual void visit(ir_gs_function *); /*@}*/ src_reg result; @@ -2306,6 +2307,12 @@ ir_to_mesa_visitor::visit(ir_discard *ir) } void +ir_to_mesa_visitor::visit(ir_gs_function *ir) +{ + // FINISHME +} + +void ir_to_mesa_visitor::visit(ir_if *ir) { ir_to_mesa_instruction *cond_inst, *if_inst; diff --git a/src/mesa/program/programopt.c b/src/mesa/program/programopt.c index c72dfb2..b34d847 100644 --- a/src/mesa/program/programopt.c +++ b/src/mesa/program/programopt.c @@ -518,7 +518,7 @@ _mesa_remove_output_reads(struct gl_program *prog, gl_register_file type) usedTemps, MAX_PROGRAM_TEMPS); assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT); - assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING); + assert(prog->Target == GL_VERTEX_PROGRAM_ARB || prog->Target == GL_GEOMETRY_PROGRAM_NV|| type != PROGRAM_VARYING); for (i = 0; i < VERT_RESULT_MAX; i++) outputMap[i] = -1; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 3fbb0cd..a988f36 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -334,6 +334,7 @@ public: virtual void visit(ir_call *); virtual void visit(ir_return *); virtual void visit(ir_discard *); + virtual void visit(ir_gs_function *); virtual void visit(ir_texture *); virtual void visit(ir_if *); /*@}*/ @@ -2636,6 +2637,12 @@ glsl_to_tgsi_visitor::visit(ir_discard *ir) } void +glsl_to_tgsi_visitor::visit(ir_gs_function *ir) +{ + +} + +void glsl_to_tgsi_visitor::visit(ir_if *ir) { glsl_to_tgsi_instruction *cond_inst, *if_inst; -- 1.7.6 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev