glsl: Handle the inout qualifier in fragment shader output declarations.
authorFrancisco Jerez <currojerez@riseup.net>
Wed, 20 Jul 2016 03:10:21 +0000 (20:10 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Wed, 24 Aug 2016 20:28:30 +0000 (13:28 -0700)
According to the EXT_shader_framebuffer_fetch extension the inout
qualifier can be used on ESSL 3.0+ shaders to declare a special kind
of fragment output that gets implicitly initialized with the previous
framebuffer contents at the current fragment coordinates.  In addition
we allow using the same language to define FB fetch outputs in GLSL
1.3+ shaders in preparation for the desktop MESA_shader_framebuffer_fetch
extensions.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/glsl_parser.yy

index c05fb17cabe8ef2aed6b9a1df375dd8ff827a9de..c91ed53962315a8ac44f762cffab3ad05d682eac 100644 (file)
@@ -3713,7 +3713,7 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
     */
    assert(var->data.mode != ir_var_temporary);
    if (qual->flags.q.in && qual->flags.q.out)
-      var->data.mode = ir_var_function_inout;
+      var->data.mode = is_parameter ? ir_var_function_inout : ir_var_shader_out;
    else if (qual->flags.q.in)
       var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
    else if (qual->flags.q.attribute
@@ -3730,6 +3730,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    else if (qual->flags.q.shared_storage)
       var->data.mode = ir_var_shader_shared;
 
+   var->data.fb_fetch_output = state->stage == MESA_SHADER_FRAGMENT &&
+                               qual->flags.q.in && qual->flags.q.out;
+
    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) {
index 5b6586141d868be21c35f8ebe34995cdcf50e7b2..f2853da08481b0096700a85a580e5f9c17e1b601 100644 (file)
@@ -1944,6 +1944,18 @@ storage_qualifier:
           $$.xfb_buffer = state->out_qualifier->xfb_buffer;
       }
    }
+   | INOUT_TOK
+   {
+      memset(& $$, 0, sizeof($$));
+      $$.flags.q.in = 1;
+      $$.flags.q.out = 1;
+
+      if (!state->has_framebuffer_fetch() ||
+          !state->is_version(130, 300) ||
+          state->stage != MESA_SHADER_FRAGMENT)
+         _mesa_glsl_error(&@1, state, "A single interface variable cannot be "
+                          "declared as both input and output");
+   }
    | UNIFORM
    {
       memset(& $$, 0, sizeof($$));