summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBryan Cain <[email protected]>2013-02-15 09:46:50 -0600
committerPaul Berry <[email protected]>2013-08-01 20:20:45 -0700
commit2548092ad80156a407281a124f833a6a93fbf2f3 (patch)
treee839a3d1c14eb45dbfe1362f5a8f4ce9afeb0c74 /src
parent844bd71736dd59808e1ea4319800db042a7c4267 (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')
-rw-r--r--src/glsl/ast_to_hir.cpp32
-rw-r--r--src/glsl/ir.cpp21
-rw-r--r--src/glsl/ir.h3
-rw-r--r--src/glsl/linker.cpp54
-rw-r--r--src/mesa/main/mtypes.h4
5 files changed, 103 insertions, 11 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 598da92f8fb..4b5645221a4 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2056,12 +2056,12 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->interpolation = INTERP_QUALIFIER_NONE;
if (var->interpolation != INTERP_QUALIFIER_NONE &&
- !(state->target == vertex_shader && var->mode == ir_var_shader_out) &&
- !(state->target == fragment_shader && var->mode == ir_var_shader_in)) {
+ ((state->target == vertex_shader && var->mode == ir_var_shader_in) ||
+ (state->target == fragment_shader && var->mode == ir_var_shader_out))) {
_mesa_glsl_error(loc, state,
- "interpolation qualifier `%s' can only be applied to "
- "vertex shader outputs and fragment shader inputs",
- var->interpolation_string());
+ "interpolation qualifier `%s' cannot be applied to "
+ "vertex shader inputs or fragment shader outputs",
+ var->interpolation_string());
}
var->pixel_center_integer = qual->flags.q.pixel_center_integer;
@@ -2662,6 +2662,26 @@ ast_declarator_list::hir(exec_list *instructions,
var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
+ /* The 'varying in' and 'varying out' qualifiers can only be used with
+ * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support
+ * yet.
+ */
+ if (this->type->qualifier.flags.q.varying) {
+ if (this->type->qualifier.flags.q.in) {
+ _mesa_glsl_error(& loc, state,
+ "`varying in' qualifier in declaration of "
+ "`%s' only valid for geometry shaders using "
+ "ARB_geometry_shader4 or EXT_geometry_shader4",
+ decl->identifier);
+ } else if (this->type->qualifier.flags.q.out) {
+ _mesa_glsl_error(& loc, state,
+ "`varying out' qualifier in declaration of "
+ "`%s' only valid for geometry shaders using "
+ "ARB_geometry_shader4 or EXT_geometry_shader4",
+ decl->identifier);
+ }
+ }
+
/* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
*
* "Global variables can only use the qualifiers const,
@@ -2906,7 +2926,7 @@ ast_declarator_list::hir(exec_list *instructions,
}
break;
default:
- assert(0);
+ break;
}
}
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index dad58deeb97..99dceacf85f 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1778,3 +1778,24 @@ ir_rvalue::as_rvalue_to_saturate()
return NULL;
}
+
+
+unsigned
+vertices_per_prim(GLenum prim)
+{
+ switch (prim) {
+ case GL_POINTS:
+ return 1;
+ case GL_LINES:
+ return 2;
+ case GL_TRIANGLES:
+ return 3;
+ case GL_LINES_ADJACENCY:
+ return 4;
+ case GL_TRIANGLES_ADJACENCY:
+ return 6;
+ default:
+ assert(!"Bad primitive");
+ return 3;
+ }
+}
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 4cb1202e65b..62e3b27ca92 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -2128,4 +2128,7 @@ extern void _mesa_print_ir(struct exec_list *instructions,
} /* extern "C" */
#endif
+unsigned
+vertices_per_prim(GLenum prim);
+
#endif /* IR_H */
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)
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 91c3abf683e..c78fe855f6c 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1852,7 +1852,7 @@ struct gl_program
GLuint Id;
GLubyte *String; /**< Null-terminated program text */
GLint RefCount;
- GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB */
+ GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */
GLenum Format; /**< String encoding format */
struct prog_instruction *Instructions;
@@ -1919,6 +1919,7 @@ struct gl_geometry_program
{
struct gl_program Base; /**< base class */
+ GLint VerticesIn;
GLint VerticesOut;
GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
@@ -2321,6 +2322,7 @@ struct gl_shader_program
/** Geometry shader state - copied into gl_geometry_program at link time */
struct {
+ GLint VerticesIn;
GLint VerticesOut;
GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */