glsl/sso: Add parser and AST-to-HIR support for separate shader object layouts
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 25 Sep 2013 23:16:00 +0000 (16:16 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 21 Feb 2014 23:41:02 +0000 (15:41 -0800)
GL_ARB_separate_shader_objects adds the ability to specify location
layouts for interstage inputs and outputs.

In addition, this extension makes 'in' and 'out' generally available for
shader inputs and outputs.  This mimics the behavior of
GL_ARB_explicit_attrib_location.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/glsl/ast_to_hir.cpp
src/glsl/glcpp/glcpp-parse.y
src/glsl/glsl_lexer.ll
src/glsl/glsl_parser_extras.h

index f754652dc9c17597c775ef29d077aee89c89c15d..f06baeb9f31cf6654702a2c17433f706cc682838 100644 (file)
@@ -2123,11 +2123,16 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
 {
    bool fail = false;
 
-   /* In the vertex shader only shader inputs can be given explicit
-    * locations.
+   /* Between GL_ARB_explicit_attrib_location an
+    * GL_ARB_separate_shader_objects, the inputs and outputs of any shader
+    * stage can be assigned explicit locations.  The checking here associates
+    * the correct extension with the correct stage's input / output:
     *
-    * In the fragment shader only shader outputs can be given explicit
-    * locations.
+    *                     input            output
+    *                     -----            ------
+    * vertex              explicit_loc     sso
+    * geometry            sso              sso
+    * fragment            sso              explicit_loc
     */
    switch (state->stage) {
    case MESA_SHADER_VERTEX:
@@ -2138,16 +2143,35 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
          break;
       }
 
+      if (var->data.mode == ir_var_shader_out) {
+         if (!state->check_separate_shader_objects_allowed(loc, var))
+            return;
+
+         break;
+      }
+
       fail = true;
       break;
 
    case MESA_SHADER_GEOMETRY:
-      _mesa_glsl_error(loc, state,
-                       "geometry shader variables cannot be given "
-                       "explicit locations");
-      return;
+      if (var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out) {
+         if (!state->check_separate_shader_objects_allowed(loc, var))
+            return;
+
+         break;
+      }
+
+      fail = true;
+      break;
 
    case MESA_SHADER_FRAGMENT:
+      if (var->data.mode == ir_var_shader_in) {
+         if (!state->check_separate_shader_objects_allowed(loc, var))
+            return;
+
+         break;
+      }
+
       if (var->data.mode == ir_var_shader_out) {
          if (!state->check_explicit_attrib_location_allowed(loc, var))
             return;
@@ -2181,9 +2205,23 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
        * ensures that negative values stay negative.
        */
       if (qual->location >= 0) {
-         var->data.location = (state->stage == MESA_SHADER_VERTEX)
-            ? (qual->location + VERT_ATTRIB_GENERIC0)
-            : (qual->location + FRAG_RESULT_DATA0);
+         switch (state->stage) {
+         case MESA_SHADER_VERTEX:
+            var->data.location = (var->data.mode == ir_var_shader_in)
+               ? (qual->location + VERT_ATTRIB_GENERIC0)
+               : (qual->location + VARYING_SLOT_VAR0);
+            break;
+
+         case MESA_SHADER_GEOMETRY:
+            var->data.location = qual->location + VARYING_SLOT_VAR0;
+            break;
+
+         case MESA_SHADER_FRAGMENT:
+            var->data.location = (var->data.mode == ir_var_shader_out)
+               ? (qual->location + FRAG_RESULT_DATA0)
+               : (qual->location + VARYING_SLOT_VAR0);
+            break;
+         }
       } else {
          var->data.location = qual->location;
       }
@@ -2207,8 +2245,6 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
          }
       }
    }
-
-   return;
 }
 
 static void
@@ -3147,6 +3183,7 @@ ast_declarator_list::hir(exec_list *instructions,
        */
       if (!state->is_version(130, 300)
          && !state->has_explicit_attrib_location()
+         && !state->has_separate_shader_objects()
          && !state->ARB_fragment_coord_conventions_enable) {
         if (this->type->qualifier.flags.q.out) {
            _mesa_glsl_error(& loc, state,
index bdc598f31b8d7e6684472f3645964aa8e21371d4..f28d8531eb1de8b2ca5a022afecd12a64852e252 100644 (file)
@@ -2134,6 +2134,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
              if (extensions->ARB_texture_gather)
                 add_builtin_define(parser, "GL_ARB_texture_gather", 1);
 
+              if (extensions->ARB_separate_shader_objects)
+                 add_builtin_define(parser, "GL_ARB_separate_shader_objects", 1);
+
              if (extensions->ARB_shader_atomic_counters)
                 add_builtin_define(parser, "GL_ARB_shader_atomic_counters", 1);
 
index 9f31ceeed79e634bce1398d21afb0c5bd24f7a5c..9fd9b80d3e86da0804865075833e2442c354326e 100644 (file)
@@ -392,6 +392,7 @@ layout              {
                      || yyextra->AMD_conservative_depth_enable
                      || yyextra->ARB_conservative_depth_enable
                      || yyextra->ARB_explicit_attrib_location_enable
+                      || yyextra->has_separate_shader_objects()
                      || yyextra->ARB_uniform_buffer_object_enable
                      || yyextra->ARB_fragment_coord_conventions_enable
                       || yyextra->ARB_shading_language_420pack_enable
index 884e83e2f6279f9e8a3ec7832f5bc015e9827532..300d9005117f8957a4c4ed31e2274037bf69391b 100644 (file)
@@ -135,6 +135,23 @@ struct _mesa_glsl_parse_state {
       return true;
    }
 
+   bool check_separate_shader_objects_allowed(YYLTYPE *locp,
+                                              const ir_variable *var)
+   {
+      if (!this->has_separate_shader_objects()) {
+         const char *const requirement = this->es_shader
+            ? "GL_EXT_separate_shader_objects (not supported by this "
+              "implementation)"
+            : "GL_ARB_separate_shader_objects extension or GLSL 420";
+
+         _mesa_glsl_error(locp, this, "%s explicit location requires %s",
+                          mode_string(var), requirement);
+         return false;
+      }
+
+      return true;
+   }
+
    bool has_explicit_attrib_location() const
    {
       return ARB_explicit_attrib_location_enable || is_version(330, 300);