diff options
author | Bryan Cain <[email protected]> | 2013-02-15 09:46:50 -0600 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-08-01 20:20:45 -0700 |
commit | 2548092ad80156a407281a124f833a6a93fbf2f3 (patch) | |
tree | e839a3d1c14eb45dbfe1362f5a8f4ce9afeb0c74 /src/glsl/linker.cpp | |
parent | 844bd71736dd59808e1ea4319800db042a7c4267 (diff) |
glsl: support compilation of geometry shaders
This commit adds all of the parsing and semantics for GLSL 150 style
geometry shaders.
v2 (Paul Berry <[email protected]>): Add a few missing calls to
get_pipeline_stage(). Fix some signed/unsigned comparison warnings.
Fix handling of NULL consumer in assign_varying_locations().
v3 (Bryan Cain <[email protected]>): fix indexing order of 2D
arrays. Also, allow interpolation qualifiers in geometry shaders.
v4 (Paul Berry <[email protected]>): Eliminate
get_pipeline_stage()--it is no longer needed thanks to 030ca23 (mesa:
renumber shader indices according to their placement in pipeline).
Remove 2D stuff. Move vertices_per_prim() to ir.h, so that it will be
accessible from outside the linker. Remove
inject_num_vertices_visitor. Rework for GLSL 1.50.
Reviewed-by: Ian Romanick <[email protected]>
v5 (Paul Berry <[email protected]>): Split out
do_set_program_inouts() argument refactoring to a separate patch.
Move geom_array_resizing_visitor to later in the series.
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r-- | src/glsl/linker.cpp | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index d7ea740dbf0..f25dca2109d 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -73,11 +73,14 @@ #include "linker.h" #include "link_varyings.h" #include "ir_optimization.h" +#include "ir_rvalue_visitor.h" extern "C" { #include "main/shaderobj.h" } +void linker_error(gl_shader_program *, const char *, ...); + /** * Visitor that determines whether or not a variable is ever written. */ @@ -402,6 +405,24 @@ validate_fragment_shader_executable(struct gl_shader_program *prog, } } +/** + * Verify that a geometry shader executable meets all semantic requirements + * + * Also sets prog->Geom.VerticesIn as a side effect. + * + * \param shader Geometry shader executable to be verified + */ +void +validate_geometry_shader_executable(struct gl_shader_program *prog, + struct gl_shader *shader) +{ + if (shader == NULL) + return; + + unsigned num_vertices = vertices_per_prim(prog->Geom.InputType); + prog->Geom.VerticesIn = num_vertices; +} + /** * Generate a string describing the mode of a variable @@ -1613,11 +1634,15 @@ 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(prog->NumShaders, sizeof(struct gl_shader *)); frag_shader_list = (struct gl_shader **) calloc(prog->NumShaders, sizeof(struct gl_shader *)); + geom_shader_list = (struct gl_shader **) + calloc(prog->NumShaders, sizeof(struct gl_shader *)); unsigned min_version = UINT_MAX; unsigned max_version = 0; @@ -1643,8 +1668,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; } } @@ -1706,6 +1731,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 (!prog->LinkStatus) + goto done; + + validate_geometry_shader_executable(prog, sh); + if (!prog->LinkStatus) + 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. @@ -1792,7 +1833,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->_LinkedShaders[MESA_SHADER_VERTEX], VERT_ATTRIB_GENERIC0, VARYING_SLOT_VAR0); } - /* FINISHME: Geometry shaders not implemented yet */ + if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { + link_invalidate_variable_locations( + prog->_LinkedShaders[MESA_SHADER_GEOMETRY], + VARYING_SLOT_VAR0, VARYING_SLOT_VAR0); + } if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { link_invalidate_variable_locations( prog->_LinkedShaders[MESA_SHADER_FRAGMENT], @@ -1826,7 +1871,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * non-zero, but the program object has no vertex or geometry * shader; */ - if (first >= MESA_SHADER_FRAGMENT) { + if (first == MESA_SHADER_FRAGMENT) { linker_error(prog, "Transform feedback varyings specified, but " "no vertex or geometry shader is present."); goto done; @@ -1950,6 +1995,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) done: free(vert_shader_list); free(frag_shader_list); + free(geom_shader_list); for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { if (prog->_LinkedShaders[i] == NULL) |