[12/15] glsl: Add support for the framebuffer fetch layout(noncoherent) qualifier.

Submitted by Francisco Jerez on Feb. 14, 2018, 9:18 p.m.

Details

Message ID 20180214211837.29279-13-currojerez@riseup.net
State New
Headers show
Series "Implement latest version of EXT_shader_framebuffer_fetch." ( rev: 3 2 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Francisco Jerez Feb. 14, 2018, 9:18 p.m.
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.
---
 src/compiler/glsl/ast.h                 |  5 ++++
 src/compiler/glsl/ast_to_hir.cpp        | 45 +++++++++++++++++++++++++++++++++
 src/compiler/glsl/ast_type.cpp          |  6 +++--
 src/compiler/glsl/builtin_variables.cpp |  1 +
 src/compiler/glsl/glsl_parser.yy        |  6 +++++
 5 files changed, 61 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h
index b0db14e20b6..ba025266bd7 100644
--- a/src/compiler/glsl/ast.h
+++ b/src/compiler/glsl/ast.h
@@ -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;
diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
index 966450ca78b..5acbaa321a9 100644
--- a/src/compiler/glsl/ast_to_hir.cpp
+++ b/src/compiler/glsl/ast_to_hir.cpp
@@ -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) {
diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp
index e9d60de5baf..14ea936f244 100644
--- a/src/compiler/glsl/ast_type.cpp
+++ b/src/compiler/glsl/ast_type.cpp
@@ -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;
 }
 
diff --git a/src/compiler/glsl/builtin_variables.cpp b/src/compiler/glsl/builtin_variables.cpp
index a686cb6a457..2fafea532f3 100644
--- a/src/compiler/glsl/builtin_variables.cpp
+++ b/src/compiler/glsl/builtin_variables.cpp
@@ -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 = true;
    }
 
    if (state->es_shader && state->language_version == 100 && state->EXT_blend_func_extended_enable) {
diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy
index 4faf9602a08..f1986ed0a8a 100644
--- a/src/compiler/glsl/glsl_parser.yy
+++ b/src/compiler/glsl/glsl_parser.yy
@@ -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);