[Mesa-dev] [PATCH 2/2] mesa: add hard limits for the number of varyings and uniforms for the linker

Marek Olšák maraeo at gmail.com
Tue Nov 22 06:05:30 PST 2011


These are different from hardware limits, because some drivers can correctly
handle higher values than they report in most cases, either due
to driver-specific compiler optimizations, or due to just how the hardware
works internally.

The problem with the linker is that it artifically reduces driver capabilities
by failing to link shaders which would otherwise run correctly.

This is a regression fix.

Another solution would be to just disable the broken checks in the linker,
but some people obviously want to preserve the new broken behavior.

NOTE: Of course, the Gallium drivers will be modified such that
MAX_xxx == MAX_xxx_HARD_LIMIT.
---
 src/gallium/include/pipe/p_defines.h     |    4 +++-
 src/glsl/linker.cpp                      |   12 ++++++------
 src/glsl/standalone_scaffolding.cpp      |    3 +++
 src/mesa/drivers/dri/i915/i915_context.c |    2 +-
 src/mesa/main/context.c                  |    5 ++++-
 src/mesa/main/mtypes.h                   |    6 ++++++
 src/mesa/state_tracker/st_extensions.c   |    8 ++++++++
 7 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 6d6faab..108830c 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -502,7 +502,9 @@ enum pipe_shader_cap
    PIPE_SHADER_CAP_SUBROUTINES = 16, /* BGNSUB, ENDSUB, CAL, RET */
    PIPE_SHADER_CAP_INTEGERS = 17,
    PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18,
-   PIPE_SHADER_CAP_OUTPUT_READ = 19
+   PIPE_SHADER_CAP_OUTPUT_READ = 19,
+   PIPE_SHADER_CAP_MAX_INPUTS_HARD_LIMIT = 20,
+   PIPE_SHADER_CAP_MAX_CONSTS_HARD_LIMIT = 21
 };
 
 
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 3527088..77b50d8 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1814,18 +1814,18 @@ assign_varying_locations(struct gl_context *ctx,
    }
 
    if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
-      if (varying_vectors > ctx->Const.MaxVarying) {
+      if (varying_vectors > ctx->Const.MaxVaryingHardLimit) {
 	 linker_error(prog, "shader uses too many varying vectors "
 		      "(%u > %u)\n",
-		      varying_vectors, ctx->Const.MaxVarying);
+		      varying_vectors, ctx->Const.MaxVaryingHardLimit);
 	 return false;
       }
    } else {
       const unsigned float_components = varying_vectors * 4;
-      if (float_components > ctx->Const.MaxVarying * 4) {
+      if (float_components > ctx->Const.MaxVaryingHardLimit * 4) {
 	 linker_error(prog, "shader uses too many varying components "
 		      "(%u > %u)\n",
-		      float_components, ctx->Const.MaxVarying * 4);
+		      float_components, ctx->Const.MaxVaryingHardLimit * 4);
 	 return false;
       }
    }
@@ -1943,8 +1943,8 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
    };
 
    const unsigned max_uniform_components[MESA_SHADER_TYPES] = {
-      ctx->Const.VertexProgram.MaxUniformComponents,
-      ctx->Const.FragmentProgram.MaxUniformComponents,
+      ctx->Const.VertexProgram.MaxUniformComponentsHardLimit,
+      ctx->Const.FragmentProgram.MaxUniformComponentsHardLimit,
       0          /* FINISHME: Geometry shaders. */
    };
 
diff --git a/src/glsl/standalone_scaffolding.cpp b/src/glsl/standalone_scaffolding.cpp
index 24cc64a..7d51c55 100644
--- a/src/glsl/standalone_scaffolding.cpp
+++ b/src/glsl/standalone_scaffolding.cpp
@@ -83,11 +83,14 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
    ctx->Const.MaxTextureCoordUnits = 2;
    ctx->Const.VertexProgram.MaxAttribs = 16;
 
+   ctx->Const.VertexProgram.MaxUniformComponentsHardLimit =
    ctx->Const.VertexProgram.MaxUniformComponents = 512;
+   ctx->Const.MaxVaryingHardLimit =
    ctx->Const.MaxVarying = 8; /* == gl_MaxVaryingFloats / 4 */
    ctx->Const.MaxVertexTextureImageUnits = 0;
    ctx->Const.MaxCombinedTextureImageUnits = 2;
    ctx->Const.MaxTextureImageUnits = 2;
+   ctx->Const.FragmentProgram.MaxUniformComponentsHardLimit =
    ctx->Const.FragmentProgram.MaxUniformComponents = 64;
 
    ctx->Const.MaxDrawBuffers = 1;
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index ca03ad0..0fab9d2 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -131,7 +131,7 @@ i915CreateContext(int api,
    ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
-   ctx->Const.MaxVarying = I915_TEX_UNITS;
+   ctx->Const.MaxVaryingHardLimit = ctx->Const.MaxVarying = I915_TEX_UNITS;
    ctx->Const.MaxCombinedTextureImageUnits =
       ctx->Const.MaxVertexTextureImageUnits +
       ctx->Const.MaxTextureImageUnits;
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index e0af6ee..75b3441 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -494,18 +494,21 @@ init_program_limits(GLenum type, struct gl_program_constants *prog)
       prog->MaxParameters = MAX_VERTEX_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+      prog->MaxUniformComponentsHardLimit =
       prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
       break;
    case GL_FRAGMENT_PROGRAM_ARB:
       prog->MaxParameters = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_FRAGMENT_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_FRAGMENT_PROGRAM_ADDRESS_REGS;
+      prog->MaxUniformComponentsHardLimit =
       prog->MaxUniformComponents = 4 * MAX_UNIFORMS;
       break;
    case MESA_GEOMETRY_PROGRAM:
       prog->MaxParameters = MAX_NV_VERTEX_PROGRAM_PARAMS;
       prog->MaxAttribs = MAX_NV_VERTEX_PROGRAM_INPUTS;
       prog->MaxAddressRegs = MAX_VERTEX_PROGRAM_ADDRESS_REGS;
+      prog->MaxUniformComponentsHardLimit =
       prog->MaxUniformComponents = MAX_GEOMETRY_UNIFORM_COMPONENTS;
       break;
    default:
@@ -614,7 +617,7 @@ _mesa_init_constants(struct gl_context *ctx)
 #if FEATURE_ARB_vertex_shader
    ctx->Const.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
    ctx->Const.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
-   ctx->Const.MaxVarying = MAX_VARYING;
+   ctx->Const.MaxVaryingHardLimit = ctx->Const.MaxVarying = MAX_VARYING;
 #endif
 #if FEATURE_ARB_geometry_shader4
    ctx->Const.MaxGeometryTextureImageUnits = MAX_GEOMETRY_TEXTURE_IMAGE_UNITS;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index b3427da..7365598 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2699,6 +2699,9 @@ struct gl_program_constants
    GLuint MaxNativeParameters;
    /* For shaders */
    GLuint MaxUniformComponents;  /**< Usually == MaxParameters * 4 */
+   /* How many uniform components a driver can deal with on its own and not
+    * fail, can be greater than MaxUniformComponents. */
+   GLuint MaxUniformComponentsHardLimit;
    /* ES 2.0 and GL_ARB_ES2_compatibility */
    struct gl_precision LowFloat, MediumFloat, HighFloat;
    struct gl_precision LowInt, MediumInt, HighInt;
@@ -2764,6 +2767,9 @@ struct gl_constants
 
    /** Number of varying vectors between vertex and fragment shaders */
    GLuint MaxVarying;
+   /* How many varyings a driver can deal with on its own and not fail,
+    * can be greater than MaxVarying. */
+   GLuint MaxVaryingHardLimit;
    GLuint MaxVertexVaryingComponents;   /**< Between vert and geom shader */
    GLuint MaxGeometryVaryingComponents; /**< Between geom and frag shader */
 
diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 240497a..af2ed50 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -173,6 +173,10 @@ void st_init_limits(struct st_context *st)
       pc->MaxNativeAddressRegs     = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ADDRS);
       pc->MaxNativeParameters      = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONSTS);
       pc->MaxUniformComponents     = 4 * MIN2(pc->MaxNativeParameters, MAX_UNIFORMS);
+      pc->MaxUniformComponentsHardLimit = screen->get_shader_param(screen, sh,
+                                       PIPE_SHADER_CAP_MAX_CONSTS_HARD_LIMIT);
+      pc->MaxUniformComponentsHardLimit =
+            4 * MIN2(pc->MaxUniformComponentsHardLimit, MAX_UNIFORMS);
       /* raise MaxParameters if native support is higher */
       pc->MaxParameters            = MAX2(pc->MaxParameters, pc->MaxNativeParameters);
 
@@ -210,6 +214,10 @@ void st_init_limits(struct st_context *st)
    c->MaxVarying = screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
                                             PIPE_SHADER_CAP_MAX_INPUTS);
    c->MaxVarying = MIN2(c->MaxVarying, MAX_VARYING);
+   c->MaxVaryingHardLimit =
+      screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
+                               PIPE_SHADER_CAP_MAX_INPUTS_HARD_LIMIT);
+   c->MaxVaryingHardLimit = MIN2(c->MaxVaryingHardLimit, MAX_VARYING);
 
    /* XXX we'll need a better query here someday */
    if (screen->get_param(screen, PIPE_CAP_GLSL)) {
-- 
1.7.5.4



More information about the mesa-dev mailing list