glsl: Cross-validate GS layout qualifiers while intrastage linking.
This gets piglit's geometry-basic test running. TODO: Still need to validate that the GS layout qualifiers don't get used in places they shouldn't (like an interface block, or a particular shader input or output) Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
@@ -77,6 +77,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include "main/shaderobj.h"
|
||||
#include "main/enums.h"
|
||||
}
|
||||
|
||||
void linker_error(gl_shader_program *, const char *, ...);
|
||||
@@ -916,6 +917,99 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the cross-validation of geometry shader max_vertices and
|
||||
* primitive type layout qualifiers for the attached geometry shaders,
|
||||
* and propagates them to the linked GS and linked shader program.
|
||||
*/
|
||||
static void
|
||||
link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
|
||||
struct gl_shader *linked_shader,
|
||||
struct gl_shader **shader_list,
|
||||
unsigned num_shaders)
|
||||
{
|
||||
linked_shader->Geom.VerticesOut = 0;
|
||||
linked_shader->Geom.InputType = PRIM_UNKNOWN;
|
||||
linked_shader->Geom.OutputType = PRIM_UNKNOWN;
|
||||
|
||||
/* No in/out qualifiers defined for anything but GLSL 1.50+
|
||||
* geometry shaders so far.
|
||||
*/
|
||||
if (linked_shader->Type != GL_GEOMETRY_SHADER || prog->Version < 150)
|
||||
return;
|
||||
|
||||
/* From the GLSL 1.50 spec, page 46:
|
||||
*
|
||||
* "All geometry shader output layout declarations in a program
|
||||
* must declare the same layout and same value for
|
||||
* max_vertices. There must be at least one geometry output
|
||||
* layout declaration somewhere in a program, but not all
|
||||
* geometry shaders (compilation units) are required to
|
||||
* declare it."
|
||||
*/
|
||||
|
||||
for (unsigned i = 0; i < num_shaders; i++) {
|
||||
struct gl_shader *shader = shader_list[i];
|
||||
|
||||
if (shader->Geom.InputType != PRIM_UNKNOWN) {
|
||||
if (linked_shader->Geom.InputType != PRIM_UNKNOWN &&
|
||||
linked_shader->Geom.InputType != shader->Geom.InputType) {
|
||||
linker_error(prog, "geometry shader defined with conflicting "
|
||||
"input types\n");
|
||||
return;
|
||||
}
|
||||
linked_shader->Geom.InputType = shader->Geom.InputType;
|
||||
}
|
||||
|
||||
if (shader->Geom.OutputType != PRIM_UNKNOWN) {
|
||||
if (linked_shader->Geom.OutputType != PRIM_UNKNOWN &&
|
||||
linked_shader->Geom.OutputType != shader->Geom.OutputType) {
|
||||
linker_error(prog, "geometry shader defined with conflicting "
|
||||
"output types\n");
|
||||
return;
|
||||
}
|
||||
linked_shader->Geom.OutputType = shader->Geom.OutputType;
|
||||
}
|
||||
|
||||
if (shader->Geom.VerticesOut != 0) {
|
||||
if (linked_shader->Geom.VerticesOut != 0 &&
|
||||
linked_shader->Geom.VerticesOut != shader->Geom.VerticesOut) {
|
||||
linker_error(prog, "geometry shader defined with conflicting "
|
||||
"output vertex count (%d and %d)\n",
|
||||
linked_shader->Geom.VerticesOut,
|
||||
shader->Geom.VerticesOut);
|
||||
return;
|
||||
}
|
||||
linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut;
|
||||
}
|
||||
}
|
||||
|
||||
/* Just do the intrastage -> interstage propagation right now,
|
||||
* since we already know we're in the right type of shader program
|
||||
* for doing it.
|
||||
*/
|
||||
if (linked_shader->Geom.InputType == PRIM_UNKNOWN) {
|
||||
linker_error(prog,
|
||||
"geometry shader didn't declare primitive input type\n");
|
||||
return;
|
||||
}
|
||||
prog->Geom.InputType = linked_shader->Geom.InputType;
|
||||
|
||||
if (linked_shader->Geom.OutputType == PRIM_UNKNOWN) {
|
||||
linker_error(prog,
|
||||
"geometry shader didn't declare primitive output type\n");
|
||||
return;
|
||||
}
|
||||
prog->Geom.OutputType = linked_shader->Geom.OutputType;
|
||||
|
||||
if (linked_shader->Geom.VerticesOut == 0) {
|
||||
linker_error(prog,
|
||||
"geometry shader didn't declare max_vertices\n");
|
||||
return;
|
||||
}
|
||||
prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine a group of shaders for a single stage to generate a linked shader
|
||||
*
|
||||
@@ -1020,6 +1114,8 @@ link_intrastage_shaders(void *mem_ctx,
|
||||
linked->NumUniformBlocks = num_uniform_blocks;
|
||||
ralloc_steal(linked, linked->UniformBlocks);
|
||||
|
||||
link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders);
|
||||
|
||||
populate_symbol_table(linked);
|
||||
|
||||
/* The a pointer to the main function in the final linked shader (i.e., the
|
||||
|
||||
Reference in New Issue
Block a user