glsl: add support for ARB_blend_func_extended (v3)

This adds index support to the GLSL compiler.

I'm not 100% sure of my approach here, esp without how output ordering
happens wrt location, index pairs, in the "mark" function.

Since current hw doesn't ever have a location > 0 with an index > 0,
we don't have to work out if the output ordering the hw requires is
location, index, location, index or location, location, index, index.
But we have no hw to know, so punt on it for now.

v2: index requires layout - catch and error
    setup explicit index properly.

v3: drop idx_offset stuff, assume index follow location

Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2012-03-24 13:33:41 +00:00
parent f8cf79936b
commit 1256a5dcc8
8 changed files with 57 additions and 7 deletions

View file

@ -363,6 +363,11 @@ struct ast_type_qualifier {
* qualifier is used. * qualifier is used.
*/ */
unsigned explicit_location:1; unsigned explicit_location:1;
/**
* Flag set if GL_ARB_explicit_attrib_location "index" layout
* qualifier is used.
*/
unsigned explicit_index:1;
/** \name Layout qualifiers for GL_AMD_conservative_depth */ /** \name Layout qualifiers for GL_AMD_conservative_depth */
/** \{ */ /** \{ */
@ -386,6 +391,13 @@ struct ast_type_qualifier {
* This field is only valid if \c explicit_location is set. * This field is only valid if \c explicit_location is set.
*/ */
int location; int location;
/**
* Index specified via GL_ARB_explicit_attrib_location layout
*
* \note
* This field is only valid if \c explicit_index is set.
*/
int index;
/** /**
* Return true if and only if an interpolation qualifier is present. * Return true if and only if an interpolation qualifier is present.

View file

@ -2092,14 +2092,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
} else { } else {
var->location = qual->location; var->location = qual->location;
} }
if (qual->flags.q.explicit_index) {
var->explicit_index = true;
var->index = qual->index;
}
} }
} else if (qual->flags.q.explicit_index) {
_mesa_glsl_error(loc, state,
"explicit index requires explicit location\n");
} }
/* Does the declaration use the 'layout' keyword? /* Does the declaration use the 'layout' keyword?
*/ */
const bool uses_layout = qual->flags.q.pixel_center_integer const bool uses_layout = qual->flags.q.pixel_center_integer
|| qual->flags.q.origin_upper_left || qual->flags.q.origin_upper_left
|| qual->flags.q.explicit_location; || qual->flags.q.explicit_location; /* no need for index since it relies on location */
/* Does the declaration use the deprecated 'attribute' or 'varying' /* Does the declaration use the deprecated 'attribute' or 'varying'
* keywords? * keywords?

View file

@ -408,6 +408,7 @@ add_variable(exec_list *instructions, glsl_symbol_table *symtab,
var->location = slot; var->location = slot;
var->explicit_location = (slot >= 0); var->explicit_location = (slot >= 0);
var->explicit_index = 0;
/* Once the variable is created an initialized, add it to the symbol table /* Once the variable is created an initialized, add it to the symbol table
* and add the declaration to the IR stream. * and add the declaration to the IR stream.

View file

@ -1103,8 +1103,14 @@ layout_qualifier_id_list:
if ($1.flags.q.explicit_location) if ($1.flags.q.explicit_location)
$$.location = $1.location; $$.location = $1.location;
if ($1.flags.q.explicit_index)
$$.index = $1.index;
if ($3.flags.q.explicit_location) if ($3.flags.q.explicit_location)
$$.location = $3.location; $$.location = $3.location;
if ($3.flags.q.explicit_index)
$$.index = $3.index;
} }
; ;
@ -1191,6 +1197,20 @@ layout_qualifier_id:
YYERROR; YYERROR;
} }
} }
if (strcmp("index", $1) == 0) {
got_one = true;
$$.flags.q.explicit_index = 1;
if ($3 >= 0) {
$$.index = $3;
} else {
_mesa_glsl_error(& @3, state,
"invalid index %d specified\n", $3);
YYERROR;
}
}
} }
/* If the identifier didn't match any known layout identifiers, /* If the identifier didn't match any known layout identifiers,

View file

@ -386,6 +386,7 @@ public:
* no effect). * no effect).
*/ */
unsigned explicit_location:1; unsigned explicit_location:1;
unsigned explicit_index:1;
/** /**
* Does this variable have an initializer? * Does this variable have an initializer?

View file

@ -57,6 +57,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->origin_upper_left = this->origin_upper_left; var->origin_upper_left = this->origin_upper_left;
var->pixel_center_integer = this->pixel_center_integer; var->pixel_center_integer = this->pixel_center_integer;
var->explicit_location = this->explicit_location; var->explicit_location = this->explicit_location;
var->explicit_index = this->explicit_index;
var->has_initializer = this->has_initializer; var->has_initializer = this->has_initializer;
var->depth_layout = this->depth_layout; var->depth_layout = this->depth_layout;
@ -74,6 +75,9 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
if (this->explicit_location) if (this->explicit_location)
var->location = this->location; var->location = this->location;
if (this->explicit_index)
var->index = this->index;
if (this->constant_value) if (this->constant_value)
var->constant_value = this->constant_value->clone(mem_ctx, ht); var->constant_value = this->constant_value->clone(mem_ctx, ht);

View file

@ -81,12 +81,12 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
*/ */
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i); GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i);
if (var->mode == ir_var_in) { if (var->mode == ir_var_in) {
prog->InputsRead |= bitfield; prog->InputsRead |= bitfield;
if (is_fragment_shader) { if (is_fragment_shader) {
gl_fragment_program *fprog = (gl_fragment_program *) prog; gl_fragment_program *fprog = (gl_fragment_program *) prog;
fprog->InterpQualifier[var->location + offset + i] = fprog->InterpQualifier[var->location + var->index + offset + i] =
(glsl_interp_qualifier) var->interpolation; (glsl_interp_qualifier) var->interpolation;
} }
} else if (var->mode == ir_var_system_value) { } else if (var->mode == ir_var_system_value) {

View file

@ -1274,10 +1274,15 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
} }
} else if (target_index == MESA_SHADER_FRAGMENT) { } else if (target_index == MESA_SHADER_FRAGMENT) {
unsigned binding; unsigned binding;
unsigned index;
if (prog->FragDataBindings->get(binding, var->name)) { if (prog->FragDataBindings->get(binding, var->name)) {
assert(binding >= FRAG_RESULT_DATA0); assert(binding >= FRAG_RESULT_DATA0);
var->location = binding; var->location = binding;
if (prog->FragDataIndexBindings->get(index, var->name)) {
var->index = index;
}
} }
} }
@ -1288,7 +1293,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
*/ */
const unsigned slots = count_attribute_slots(var->type); const unsigned slots = count_attribute_slots(var->type);
if (var->location != -1) { if (var->location != -1) {
if (var->location >= generic_base) { if (var->location >= generic_base && var->index < 1) {
/* From page 61 of the OpenGL 4.0 spec: /* From page 61 of the OpenGL 4.0 spec:
* *
* "LinkProgram will fail if the attribute bindings assigned * "LinkProgram will fail if the attribute bindings assigned
@ -1333,8 +1338,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
? "vertex shader input" : "fragment shader output"; ? "vertex shader input" : "fragment shader output";
linker_error(prog, linker_error(prog,
"insufficient contiguous locations " "insufficient contiguous locations "
"available for %s `%s'", string, "available for %s `%s' %d %d %d", string,
var->name); var->name, used_locations, use_mask, attr);
return false; return false;
} }
@ -2321,7 +2326,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
goto done; goto done;
} }
if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) { if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) {
goto done; goto done;
} }