meta: Add on demand compilation of per target shader programs
authorAnuj Phogat <anuj.phogat@gmail.com>
Thu, 20 Sep 2012 20:17:19 +0000 (13:17 -0700)
committerAnuj Phogat <anuj.phogat@gmail.com>
Fri, 21 Sep 2012 20:31:58 +0000 (13:31 -0700)
A call to glGenerateMipmap() follows the generation of a relevant
shader program in setup_glsl_generate_mipmap().

To support all texture targets and to avoid compiling shaders
everytime, per target shader programs are compiled on demand
and saved for the next call.

Fixes float-texture(mipmap.manual):
See Comment 6: https://bugs.freedesktop.org/show_bug.cgi?id=54296

NOTE: This is a candidate for stable branches.

Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/drivers/common/meta.c

index 3b13ad7f1306d3acf169dfcd6bddc15c7fedf1c8..28a79b0a0d6509292976425da9d972ad2f54867b 100644 (file)
@@ -269,6 +269,16 @@ struct bitmap_state
    struct temp_texture Tex;  /**< separate texture from other meta ops */
 };
 
+/**
+ * State for GLSL texture sampler which is used to generate fragment
+ * shader in _mesa_meta_generate_mipmap().
+ */
+struct glsl_sampler {
+   const char *type;
+   const char *func;
+   const char *texcoords;
+   GLuint shader_prog;
+};
 
 /**
  * State for _mesa_meta_generate_mipmap()
@@ -281,16 +291,12 @@ struct gen_mipmap_state
    GLuint Sampler;
    GLuint ShaderProg;
    GLuint IntegerShaderProg;
-};
-
-/**
- * State for GLSL texture sampler which is used to generate fragment
- * shader in _mesa_meta_generate_mipmap().
- */
-struct glsl_sampler {
-   const char *type;
-   const char *func;
-   const char *texcoords;
+   struct glsl_sampler sampler_1d;
+   struct glsl_sampler sampler_2d;
+   struct glsl_sampler sampler_3d;
+   struct glsl_sampler sampler_cubemap;
+   struct glsl_sampler sampler_1d_array;
+   struct glsl_sampler sampler_2d_array;
 };
 
 /**
@@ -2977,46 +2983,47 @@ setup_ff_generate_mipmap(struct gl_context *ctx,
 }
 
 
-static void
-setup_texture_sampler(GLenum target, struct glsl_sampler *sampler)
+static struct glsl_sampler *
+setup_texture_sampler(GLenum target, struct gen_mipmap_state *mipmap)
 {
    switch(target) {
    case GL_TEXTURE_1D:
-      sampler->type = "sampler1D";
-      sampler->func = "texture1D";
-      sampler->texcoords = "texCoords.x";
-      break;
+      mipmap->sampler_1d.type = "sampler1D";
+      mipmap->sampler_1d.func = "texture1D";
+      mipmap->sampler_1d.texcoords = "texCoords.x";
+      return &mipmap->sampler_1d;
    case GL_TEXTURE_2D:
-      sampler->type = "sampler2D";
-      sampler->func = "texture2D";
-      sampler->texcoords = "texCoords.xy";
-      break;
+      mipmap->sampler_2d.type = "sampler2D";
+      mipmap->sampler_2d.func = "texture2D";
+      mipmap->sampler_2d.texcoords = "texCoords.xy";
+      return &mipmap->sampler_2d;
    case GL_TEXTURE_3D:
       /* Code for mipmap generation with 3D textures is not used yet.
        * It's a sw fallback.
        */
-      sampler->type = "sampler3D";
-      sampler->func = "texture3D";
-      sampler->texcoords = "texCoords";
-      break;
+      mipmap->sampler_3d.type = "sampler3D";
+      mipmap->sampler_3d.func = "texture3D";
+      mipmap->sampler_3d.texcoords = "texCoords";
+      return &mipmap->sampler_3d;
    case GL_TEXTURE_CUBE_MAP:
-      sampler->type = "samplerCube";
-      sampler->func = "textureCube";
-      sampler->texcoords = "texCoords";
-      break;
+      mipmap->sampler_cubemap.type = "samplerCube";
+      mipmap->sampler_cubemap.func = "textureCube";
+      mipmap->sampler_cubemap.texcoords = "texCoords";
+      return &mipmap->sampler_cubemap;
    case GL_TEXTURE_1D_ARRAY:
-      sampler->type = "sampler1DArray";
-      sampler->func = "texture1DArray";
-      sampler->texcoords = "texCoords.xy";
-      break;
+      mipmap->sampler_1d_array.type = "sampler1DArray";
+      mipmap->sampler_1d_array.func = "texture1DArray";
+      mipmap->sampler_1d_array.texcoords = "texCoords.xy";
+      return &mipmap->sampler_1d_array;
    case GL_TEXTURE_2D_ARRAY:
-      sampler->type = "sampler2DArray";
-      sampler->func = "texture2DArray";
-      sampler->texcoords = "texCoords";
-      break;
+      mipmap->sampler_2d_array.type = "sampler2DArray";
+      mipmap->sampler_2d_array.func = "texture2DArray";
+      mipmap->sampler_2d_array.texcoords = "texCoords";
+      return &mipmap->sampler_2d_array;
    default:
       _mesa_problem(NULL, "Unexpected texture target 0x%x in"
                     " setup_texture_sampler()\n", target);
+      return NULL;
    }
 }
 
@@ -3029,7 +3036,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
    struct vertex {
       GLfloat x, y, tex[3];
    };
-   struct glsl_sampler sampler;
+   struct glsl_sampler *sampler;
    const char *vs_source;
    const char *fs_template;
 
@@ -3099,24 +3106,31 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
     }
 
    /* Check if already initialized */
-   if (mipmap->ArrayObj != 0)
-      return;
-   /* create vertex array object */
-   _mesa_GenVertexArrays(1, &mipmap->ArrayObj);
-   _mesa_BindVertexArray(mipmap->ArrayObj);
+   if (mipmap->ArrayObj == 0) {
 
-   /* create vertex array buffer */
-   _mesa_GenBuffersARB(1, &mipmap->VBO);
-   _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+      /* create vertex array object */
+      _mesa_GenVertexArrays(1, &mipmap->ArrayObj);
+      _mesa_BindVertexArray(mipmap->ArrayObj);
 
-   /* setup vertex arrays */
-   _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE,
-                                sizeof(struct vertex), OFFSET(x));
-   _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE,
-                                sizeof(struct vertex), OFFSET(tex));
+      /* create vertex array buffer */
+      _mesa_GenBuffersARB(1, &mipmap->VBO);
+      _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO);
+
+      /* setup vertex arrays */
+      _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE,
+                                   sizeof(struct vertex), OFFSET(x));
+      _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE,
+                                   sizeof(struct vertex), OFFSET(tex));
+   }
 
    /* Generate a fragment shader program appropriate for the texture target */
-   setup_texture_sampler(target, &sampler);
+   sampler = setup_texture_sampler(target, mipmap);
+   assert(sampler != NULL);
+   if (sampler->shader_prog != 0) {
+      mipmap->ShaderProg = sampler->shader_prog;
+      return;
+   }
+
    mem_ctx = ralloc_context(NULL);
 
    if (ctx->Const.GLSLVersion < 130) {
@@ -3125,13 +3139,13 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
                        "require" : "disable";
 
       fs_source = ralloc_asprintf(mem_ctx, fs_template,
-                                  extension_mode, sampler.type,
-                                  sampler.func, sampler.texcoords);
+                                  extension_mode, sampler->type,
+                                  sampler->func, sampler->texcoords);
    }
    else {
       fs_source = ralloc_asprintf(mem_ctx, fs_template,
-                                  sampler.type, "vec4",
-                                  sampler.texcoords);
+                                  sampler->type, "vec4",
+                                  sampler->texcoords);
    }
 
    vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source);
@@ -3147,6 +3161,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
    _mesa_EnableVertexAttribArrayARB(0);
    _mesa_EnableVertexAttribArrayARB(1);
    link_program_with_debug(ctx, mipmap->ShaderProg);
+   sampler->shader_prog = mipmap->ShaderProg;
    ralloc_free(mem_ctx);
 
    if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) ||
@@ -3181,8 +3196,20 @@ meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx,
    mipmap->ArrayObj = 0;
    _mesa_DeleteBuffersARB(1, &mipmap->VBO);
    mipmap->VBO = 0;
-   _mesa_DeleteObjectARB(mipmap->ShaderProg);
-   mipmap->ShaderProg = 0;
+
+   _mesa_DeleteObjectARB(mipmap->sampler_1d.shader_prog);
+   _mesa_DeleteObjectARB(mipmap->sampler_2d.shader_prog);
+   _mesa_DeleteObjectARB(mipmap->sampler_3d.shader_prog);
+   _mesa_DeleteObjectARB(mipmap->sampler_cubemap.shader_prog);
+   _mesa_DeleteObjectARB(mipmap->sampler_1d_array.shader_prog);
+   _mesa_DeleteObjectARB(mipmap->sampler_2d_array.shader_prog);
+
+   mipmap->sampler_1d.shader_prog = 0;
+   mipmap->sampler_2d.shader_prog = 0;
+   mipmap->sampler_3d.shader_prog = 0;
+   mipmap->sampler_cubemap.shader_prog = 0;
+   mipmap->sampler_1d_array.shader_prog = 0;
+   mipmap->sampler_2d_array.shader_prog = 0;
 
    if (mipmap->IntegerShaderProg) {
       _mesa_DeleteObjectARB(mipmap->IntegerShaderProg);