glsl: Reject shader versions not supported by the implementation
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 31 Jan 2011 23:02:24 +0000 (15:02 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 31 Jan 2011 23:32:56 +0000 (15:32 -0800)
Previously we'd happily compile GLSL 1.30 shaders on any driver.  We'd
also happily compile GLSL 1.10 and 1.20 shaders in an ES2 context.
This has been a long standing FINISHME in the compiler.

NOTE: This is a candidate for the 7.9 and 7.10 branches

src/glsl/glsl_parser.ypp
src/glsl/glsl_parser_extras.cpp
src/glsl/glsl_parser_extras.h

index 7336b18..d0bebc7 100644 (file)
@@ -220,25 +220,40 @@ version_statement:
        /* blank - no #version specified: defaults are already set */
        | VERSION INTCONSTANT EOL
        {
+          bool supported = false;
+
           switch ($2) {
           case 100:
              state->es_shader = true;
+             supported = state->Const.GLSL_100ES;
+             break;
           case 110:
+             supported = state->Const.GLSL_110;
+             break;
           case 120:
+             supported = state->Const.GLSL_120;
+             break;
           case 130:
-             /* FINISHME: Check against implementation support versions. */
-             state->language_version = $2;
-             state->version_string =
-                ralloc_asprintf(state, "GLSL%s %d.%02d",
-                                state->es_shader ? " ES" : "",
-                                state->language_version / 100,
-                                state->language_version % 100);
+             supported = state->Const.GLSL_130;
              break;
           default:
-             _mesa_glsl_error(& @2, state, "Shading language version"
-                              "%u is not supported\n", $2);
+             supported = false;
              break;
           }
+
+          state->language_version = $2;
+          state->version_string =
+             ralloc_asprintf(state, "GLSL%s %d.%02d",
+                             state->es_shader ? " ES" : "",
+                             state->language_version / 100,
+                             state->language_version % 100);
+
+          if (!supported) {
+             _mesa_glsl_error(& @2, state, "%s is not supported. "
+                              "Supported versions are: %s\n",
+                              state->version_string,
+                              state->supported_version_string);
+          }
        }
        ;
 
index 5a8a524..2ed8b84 100644 (file)
@@ -79,6 +79,38 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx,
    this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents;
 
    this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers;
+
+   /* Note: Once the OpenGL 3.0 'forward compatible' context or the OpenGL 3.2
+    * Core context is supported, this logic will need change.  Older versions of
+    * GLSL are no longer supported outside the compatibility contexts of 3.x.
+    */
+   this->Const.GLSL_100ES = (ctx->API == API_OPENGLES2)
+      || ctx->Extensions.ARB_ES2_compatibility;
+   this->Const.GLSL_110 = (ctx->API == API_OPENGL);
+   this->Const.GLSL_120 = (ctx->API == API_OPENGL)
+      && (ctx->Const.GLSLVersion >= 120);
+   this->Const.GLSL_130 = (ctx->API == API_OPENGL)
+      && (ctx->Const.GLSLVersion >= 130);
+
+   const unsigned lowest_version =
+      (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility
+      ? 100 : 110;
+   const unsigned highest_version =
+      (ctx->API == API_OPENGL) ? ctx->Const.GLSLVersion : 100;
+   char *supported = (char *) ralloc_context(this);
+
+   for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) {
+      const char *const prefix = (ver == lowest_version)
+        ? ""
+        : ((ver == highest_version) ? ", and " : ", ");
+
+      ralloc_asprintf_append(& supported, "%s%d.%02d%s",
+                            prefix,
+                            ver / 100, ver % 100,
+                            (ver == 100) ? " ES" : "");
+   }
+
+   this->supported_version_string = supported;
 }
 
 const char *
index 970275c..8d4fca7 100644 (file)
@@ -73,6 +73,16 @@ struct _mesa_glsl_parse_state {
    enum _mesa_glsl_parser_targets target;
 
    /**
+    * Printable list of GLSL versions supported by the current context
+    *
+    * \note
+    * This string should probably be generated per-context instead of per
+    * invokation of the compiler.  This should be changed when the method of
+    * tracking supported GLSL versions changes.
+    */
+   const char *supported_version_string;
+
+   /**
     * Implementation defined limits that affect built-in variables, etc.
     *
     * \sa struct gl_constants (in mtypes.h)
@@ -93,6 +103,22 @@ struct _mesa_glsl_parse_state {
 
       /* ARB_draw_buffers */
       unsigned MaxDrawBuffers;
+
+      /**
+       * Set of GLSL versions supported by the current context
+       *
+       * Knowing that version X is supported doesn't mean that versions before
+       * X are also supported.  Version 1.00 is only supported in an ES2
+       * context or when GL_ARB_ES2_compatibility is supported.  In an OpenGL
+       * 3.0 "forward compatible" context, GLSL 1.10 and 1.20 are \b not
+       * supported.
+       */
+      /*@{*/
+      unsigned GLSL_100ES:1;
+      unsigned GLSL_110:1;
+      unsigned GLSL_120:1;
+      unsigned GLSL_130:1;
+      /*@}*/
    } Const;
 
    /**