mesa: use check_resources() to check program against limits
authorBrian Paul <brianp@vmware.com>
Fri, 11 Mar 2011 16:25:22 +0000 (09:25 -0700)
committerBrian Paul <brianp@vmware.com>
Fri, 11 Mar 2011 16:25:22 +0000 (09:25 -0700)
Without these checks we could create shaders with more samplers,
constants than the driver could handle.  Fail linking rather than
dying later.

src/mesa/program/ir_to_mesa.cpp

index 33c262f8ca4cea2833bc838a80f9551020ed0a8d..9c77f387593b36c4004750521a8aeea2e44b803c 100644 (file)
@@ -2406,6 +2406,11 @@ print_program(struct prog_instruction *mesa_instructions,
    }
 }
 
+
+/**
+ * Count resources used by the given gpu program (number of texture
+ * samplers, etc).
+ */
 static void
 count_resources(struct gl_program *prog)
 {
@@ -2429,6 +2434,57 @@ count_resources(struct gl_program *prog)
    _mesa_update_shader_textures_used(prog);
 }
 
+
+/**
+ * Check if the given vertex/fragment/shader program is within the
+ * resource limits of the context (number of texture units, etc).
+ * If any of those checks fail, record a linker error.
+ *
+ * XXX more checks are needed...
+ */
+static void
+check_resources(const struct gl_context *ctx,
+                struct gl_shader_program *shader_program,
+                struct gl_program *prog)
+{
+   switch (prog->Target) {
+   case GL_VERTEX_PROGRAM_ARB:
+      if (_mesa_bitcount(prog->SamplersUsed) >
+          ctx->Const.MaxVertexTextureImageUnits) {
+         fail_link(shader_program, "Too many vertex shader texture samplers");
+      }
+      if (prog->Parameters->NumParameters >
+          ctx->Const.VertexProgram.MaxParameters) {
+         fail_link(shader_program, "Too many vertex shader constants");
+      }
+      break;
+   case MESA_GEOMETRY_PROGRAM:
+      if (_mesa_bitcount(prog->SamplersUsed) >
+          ctx->Const.GeometryProgram.MaxGeometryTextureImageUnits) {
+         fail_link(shader_program, "Too many geometry shader texture samplers");
+      }
+      if (prog->Parameters->NumParameters >
+          ctx->Const.GeometryProgram.MaxParameters) {
+         fail_link(shader_program, "Too many geometry shader constants");
+      }
+      break;
+   case GL_FRAGMENT_PROGRAM_ARB:
+      if (_mesa_bitcount(prog->SamplersUsed) >
+          ctx->Const.MaxTextureImageUnits) {
+         fail_link(shader_program, "Too many fragment shader texture samplers");
+      }
+      if (prog->Parameters->NumParameters >
+          ctx->Const.FragmentProgram.MaxParameters) {
+         fail_link(shader_program, "Too many fragment shader constants");
+      }
+      break;
+   default:
+      _mesa_problem(ctx, "unexpected program type in check_resources()");
+   }
+}
+
+
+
 struct uniform_sort {
    struct gl_uniform *u;
    int pos;
@@ -3026,6 +3082,8 @@ get_mesa_program(struct gl_context *ctx,
    do_set_program_inouts(shader->ir, prog);
    count_resources(prog);
 
+   check_resources(ctx, shader_program, prog);
+
    _mesa_reference_program(ctx, &shader->Program, prog);
 
    if ((ctx->Shader.Flags & GLSL_NO_OPT) == 0) {