mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 11:48:06 +02:00
linker: Assign locations for fragment shader output
Fixes an assertion failure in the piglib out-01.frag
ARB_explicit_attrib_location test. The locations set via the layout
qualifier in fragment shader were not being applied to the shader
outputs. As a result all of these variables still had a location of
-1 set.
This may need some more work for pre-3.0 contexts. The problem is
dealing with generic outputs that lack a layout qualifier. There is
no way for the application to specify a location
(glBindFragDataLocation is not supported) or query the location
assigned by the linker (glGetFragDataLocation is not supported).
NOTE: This is a candidate for the 7.10 and 7.11 branches.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38624
Reviewed-by: Eric Anholt <eric@anholt.net>
Cc: Kenneth Graunke <kenneth@whitecape.org>
Cc: Vinson Lee <vlee@vmware.com>
(cherry picked from commit d32d4f780f)
This commit is contained in:
parent
4e2a5d013d
commit
c286f7870f
1 changed files with 75 additions and 33 deletions
|
|
@ -1158,16 +1158,43 @@ find_available_slots(unsigned used_mask, unsigned needed_count)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assign locations for either VS inputs for FS outputs
|
||||
*
|
||||
* \param prog Shader program whose variables need locations assigned
|
||||
* \param target_index Selector for the program target to receive location
|
||||
* assignmnets. Must be either \c MESA_SHADER_VERTEX or
|
||||
* \c MESA_SHADER_FRAGMENT.
|
||||
* \param max_index Maximum number of generic locations. This corresponds
|
||||
* to either the maximum number of draw buffers or the
|
||||
* maximum number of generic attributes.
|
||||
*
|
||||
* \return
|
||||
* If locations are successfully assigned, true is returned. Otherwise an
|
||||
* error is emitted to the shader link log and false is returned.
|
||||
*
|
||||
* \bug
|
||||
* Locations set via \c glBindFragDataLocation are not currently supported.
|
||||
* Only locations assigned automatically by the linker, explicitly set by a
|
||||
* layout qualifier, or explicitly set by a built-in variable (e.g., \c
|
||||
* gl_FragColor) are supported for fragment shaders.
|
||||
*/
|
||||
bool
|
||||
assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index)
|
||||
assign_attribute_or_color_locations(gl_shader_program *prog,
|
||||
unsigned target_index,
|
||||
unsigned max_index)
|
||||
{
|
||||
/* Mark invalid attribute locations as being used.
|
||||
/* Mark invalid locations as being used.
|
||||
*/
|
||||
unsigned used_locations = (max_attribute_index >= 32)
|
||||
? ~0 : ~((1 << max_attribute_index) - 1);
|
||||
unsigned used_locations = (max_index >= 32)
|
||||
? ~0 : ~((1 << max_index) - 1);
|
||||
|
||||
gl_shader *const sh = prog->_LinkedShaders[0];
|
||||
assert(sh->Type == GL_VERTEX_SHADER);
|
||||
assert((target_index == MESA_SHADER_VERTEX)
|
||||
|| (target_index == MESA_SHADER_FRAGMENT));
|
||||
|
||||
gl_shader *const sh = prog->_LinkedShaders[target_index];
|
||||
if (sh == NULL)
|
||||
return true;
|
||||
|
||||
/* Operate in a total of four passes.
|
||||
*
|
||||
|
|
@ -1184,9 +1211,16 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
|
|||
* 4. Assign locations to any inputs without assigned locations.
|
||||
*/
|
||||
|
||||
invalidate_variable_locations(sh, ir_var_in, VERT_ATTRIB_GENERIC0);
|
||||
const int generic_base = (target_index == MESA_SHADER_VERTEX)
|
||||
? VERT_ATTRIB_GENERIC0 : FRAG_RESULT_DATA0;
|
||||
|
||||
if (prog->Attributes != NULL) {
|
||||
const enum ir_variable_mode direction =
|
||||
(target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out;
|
||||
|
||||
|
||||
invalidate_variable_locations(sh, direction, generic_base);
|
||||
|
||||
if ((target_index == MESA_SHADER_VERTEX) && (prog->Attributes != NULL)) {
|
||||
for (unsigned i = 0; i < prog->Attributes->NumParameters; i++) {
|
||||
ir_variable *const var =
|
||||
sh->symbols->get_variable(prog->Attributes->Parameters[i].Name);
|
||||
|
|
@ -1273,15 +1307,15 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
|
|||
foreach_list(node, sh->ir) {
|
||||
ir_variable *const var = ((ir_instruction *) node)->as_variable();
|
||||
|
||||
if ((var == NULL) || (var->mode != ir_var_in))
|
||||
if ((var == NULL) || (var->mode != direction))
|
||||
continue;
|
||||
|
||||
if (var->explicit_location) {
|
||||
const unsigned slots = count_attribute_slots(var->type);
|
||||
const unsigned use_mask = (1 << slots) - 1;
|
||||
const int attr = var->location - VERT_ATTRIB_GENERIC0;
|
||||
const int attr = var->location - generic_base;
|
||||
|
||||
if ((var->location >= (int)(max_attribute_index + VERT_ATTRIB_GENERIC0))
|
||||
if ((var->location >= (int)(max_index + generic_base))
|
||||
|| (var->location < 0)) {
|
||||
linker_error_printf(prog,
|
||||
"invalid explicit location %d specified for "
|
||||
|
|
@ -1289,7 +1323,7 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
|
|||
(var->location < 0) ? var->location : attr,
|
||||
var->name);
|
||||
return false;
|
||||
} else if (var->location >= VERT_ATTRIB_GENERIC0) {
|
||||
} else if (var->location >= generic_base) {
|
||||
used_locations |= (use_mask << attr);
|
||||
}
|
||||
}
|
||||
|
|
@ -1313,14 +1347,16 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
|
|||
|
||||
qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
|
||||
|
||||
/* VERT_ATTRIB_GENERIC0 is a psdueo-alias for VERT_ATTRIB_POS. It can only
|
||||
* be explicitly assigned by via glBindAttribLocation. Mark it as reserved
|
||||
* to prevent it from being automatically allocated below.
|
||||
*/
|
||||
find_deref_visitor find("gl_Vertex");
|
||||
find.run(sh->ir);
|
||||
if (find.variable_found())
|
||||
used_locations |= (1 << 0);
|
||||
if (target_index == MESA_SHADER_VERTEX) {
|
||||
/* VERT_ATTRIB_GENERIC0 is a pseudo-alias for VERT_ATTRIB_POS. It can
|
||||
* only be explicitly assigned by via glBindAttribLocation. Mark it as
|
||||
* reserved to prevent it from being automatically allocated below.
|
||||
*/
|
||||
find_deref_visitor find("gl_Vertex");
|
||||
find.run(sh->ir);
|
||||
if (find.variable_found())
|
||||
used_locations |= (1 << 0);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_attr; i++) {
|
||||
/* Mask representing the contiguous slots that will be used by this
|
||||
|
|
@ -1331,14 +1367,17 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
|
|||
int location = find_available_slots(used_locations, to_assign[i].slots);
|
||||
|
||||
if (location < 0) {
|
||||
const char *const string = (target_index == MESA_SHADER_VERTEX)
|
||||
? "vertex shader input" : "fragment shader output";
|
||||
|
||||
linker_error_printf(prog,
|
||||
"insufficient contiguous attribute locations "
|
||||
"available for vertex shader input `%s'",
|
||||
to_assign[i].var->name);
|
||||
"available for %s `%s'",
|
||||
string, to_assign[i].var->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
to_assign[i].var->location = VERT_ATTRIB_GENERIC0 + location;
|
||||
to_assign[i].var->location = generic_base + location;
|
||||
used_locations |= (use_mask << location);
|
||||
}
|
||||
|
||||
|
|
@ -1635,16 +1674,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||
|
||||
assign_uniform_locations(prog);
|
||||
|
||||
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
|
||||
/* FINISHME: The value of the max_attribute_index parameter is
|
||||
* FINISHME: implementation dependent based on the value of
|
||||
* FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be
|
||||
* FINISHME: at least 16, so hardcode 16 for now.
|
||||
*/
|
||||
if (!assign_attribute_locations(prog, 16)) {
|
||||
prog->LinkStatus = false;
|
||||
goto done;
|
||||
}
|
||||
/* FINISHME: The value of the max_attribute_index parameter is
|
||||
* FINISHME: implementation dependent based on the value of
|
||||
* FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be
|
||||
* FINISHME: at least 16, so hardcode 16 for now.
|
||||
*/
|
||||
if (!assign_attribute_or_color_locations(prog, MESA_SHADER_VERTEX, 16)) {
|
||||
prog->LinkStatus = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) {
|
||||
prog->LinkStatus = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
unsigned prev;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue