glsl: Add support for the framebuffer fetch layout(noncoherent) qualifier.

This allows the application to request framebuffer fetch coherency
with per-fragment output granularity.  Coherent framebuffer fetch
outputs (which is the default if no qualifier is present for
compatibility with older versions of the EXT_shader_framebuffer_fetch
extension) will have ir_variable_data::memory_coherent set to true.

Reviewed-by: Plamena Manolova <plamena.manolova@intel.com>
This commit is contained in:
Francisco Jerez
2018-02-12 15:54:33 -08:00
parent 0aeec504b4
commit ef9e3f63ca
5 changed files with 61 additions and 2 deletions

View File

@@ -635,6 +635,11 @@ struct ast_type_qualifier {
unsigned bound_sampler:1;
unsigned bound_image:1;
/** \} */
/** \name Layout qualifiers for GL_EXT_shader_framebuffer_fetch_non_coherent */
/** \{ */
unsigned non_coherent:1;
/** \} */
}
/** \brief Set of flags, accessed by name. */
q;

View File

@@ -2008,6 +2008,20 @@ ast_expression::do_hir(exec_list *instructions,
_mesa_glsl_warning(&loc, state, "`%s' used uninitialized",
this->primary_expression.identifier);
}
/* From the EXT_shader_framebuffer_fetch spec:
*
* "Unless the GL_EXT_shader_framebuffer_fetch extension has been
* enabled in addition, it's an error to use gl_LastFragData if it
* hasn't been explicitly redeclared with layout(noncoherent)."
*/
if (var->data.fb_fetch_output && var->data.memory_coherent &&
!state->EXT_shader_framebuffer_fetch_enable) {
_mesa_glsl_error(&loc, state,
"invalid use of framebuffer fetch output not "
"qualified with layout(noncoherent)");
}
} else {
_mesa_glsl_error(& loc, state, "`%s' undeclared",
this->primary_expression.identifier);
@@ -4002,6 +4016,33 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->data.fb_fetch_output = (strcmp(var->name, "gl_LastFragData") == 0);
}
if (var->data.fb_fetch_output) {
var->data.memory_coherent = !qual->flags.q.non_coherent;
/* From the EXT_shader_framebuffer_fetch spec:
*
* "It is an error to declare an inout fragment output not qualified
* with layout(noncoherent) if the GL_EXT_shader_framebuffer_fetch
* extension hasn't been enabled."
*/
if (var->data.memory_coherent &&
!state->EXT_shader_framebuffer_fetch_enable)
_mesa_glsl_error(loc, state,
"invalid declaration of framebuffer fetch output not "
"qualified with layout(noncoherent)");
} else {
/* From the EXT_shader_framebuffer_fetch spec:
*
* "Fragment outputs declared inout may specify the following layout
* qualifier: [...] noncoherent"
*/
if (qual->flags.q.non_coherent)
_mesa_glsl_error(loc, state,
"invalid layout(noncoherent) qualifier not part of "
"framebuffer fetch output declaration");
}
if (!is_parameter && is_varying_var(var, state->stage)) {
/* User-defined ins/outs are not permitted in compute shaders. */
if (state->stage == MESA_SHADER_COMPUTE) {
@@ -4268,8 +4309,12 @@ get_variable_being_redeclared(ir_variable **var_ptr, YYLTYPE loc,
* "By default, gl_LastFragData is declared with the mediump precision
* qualifier. This can be changed by redeclaring the corresponding
* variables with the desired precision qualifier."
*
* "Fragment shaders may specify the following layout qualifier only for
* redeclaring the built-in gl_LastFragData array [...]: noncoherent"
*/
earlier->data.precision = var->data.precision;
earlier->data.memory_coherent = var->data.memory_coherent;
} else if (earlier->data.how_declared == ir_var_declared_implicitly &&
state->allow_builtin_variable_redeclaration) {

View File

@@ -270,6 +270,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
input_layout_mask.flags.q.precise = 1;
input_layout_mask.flags.q.sample = 1;
input_layout_mask.flags.q.smooth = 1;
input_layout_mask.flags.q.non_coherent = 1;
if (state->has_bindless()) {
/* Allow to use image qualifiers with shader inputs/outputs. */
@@ -775,7 +776,7 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
"%s '%s':"
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
message, name,
bad.flags.q.invariant ? " invariant" : "",
bad.flags.q.precise ? " precise" : "",
@@ -838,7 +839,8 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
bad.flags.q.bindless_image ? " bindless_image" : "",
bad.flags.q.bound_sampler ? " bound_sampler" : "",
bad.flags.q.bound_image ? " bound_image" : "",
bad.flags.q.post_depth_coverage ? " post_depth_coverage" : "");
bad.flags.q.post_depth_coverage ? " post_depth_coverage" : "",
bad.flags.q.non_coherent ? " noncoherent" : "");
return false;
}

View File

@@ -1194,6 +1194,7 @@ builtin_variable_generator::generate_fs_special_vars()
var->data.precision = GLSL_PRECISION_MEDIUM;
var->data.read_only = 1;
var->data.fb_fetch_output = 1;
var->data.memory_coherent = 1;
}
if (state->es_shader && state->language_version == 100 && state->EXT_blend_func_extended_enable) {

View File

@@ -1587,6 +1587,12 @@ layout_qualifier_id:
}
}
if (!$$.flags.i &&
state->EXT_shader_framebuffer_fetch_non_coherent_enable) {
if (match_layout_qualifier($1, "noncoherent", state) == 0)
$$.flags.q.non_coherent = 1;
}
if (!$$.flags.i) {
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'", $1);