[Mesa-dev] [PATCH 1/2] _mesa_meta_GenerateMipmap: Support all texture targets by generating shaders at runtime

Brian Paul brianp at vmware.com
Wed Sep 5 07:58:58 PDT 2012


On 09/04/2012 08:42 PM, Anuj Phogat wrote:
> glsl path of _mesa_meta_GenerateMipmap() function would require different fragment
> shaders depending on the texture target. This patch adds the code to generate
> appropriate fragment shader programs at run time.
> Fixes https://bugs.freedesktop.org/show_bug.cgi?id=54296
>
> NOTE: This is a candidate for stable branches.
>
> Signed-off-by: Anuj Phogat<anuj.phogat at gmail.com>
> ---
>   src/mesa/drivers/common/meta.c |  100 +++++++++++++++++++++++++++++++++++----
>   1 files changed, 89 insertions(+), 11 deletions(-)
>
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index 36672a7..7d701f4 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -286,6 +286,15 @@ struct gen_mipmap_state
>      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;
> +};
>
>   /**
>    * State for texture decompression
> @@ -2974,7 +2983,7 @@ setup_texture_coords(GLenum faceTarget,
>
>   static void
>   setup_ff_generate_mipmap(struct gl_context *ctx,
> -                           struct gen_mipmap_state *mipmap)
> +                         struct gen_mipmap_state *mipmap)
>   {
>      struct vertex {
>         GLfloat x, y, tex[3];
> @@ -3004,12 +3013,53 @@ setup_ff_generate_mipmap(struct gl_context *ctx,
>
>
>   static void
> +setup_texture_sampler(GLenum target, struct glsl_sampler *sampler)
> +{
> +   switch(target) {
> +   case GL_TEXTURE_1D:
> +      sampler->type = "sampler1D";
> +      sampler->func = "texture1D";
> +      sampler->texcoords = "texCoords.x";
> +      break;
> +   case GL_TEXTURE_2D:
> +      sampler->type = "sampler2D";
> +      sampler->func = "texture2D";
> +      sampler->texcoords = "texCoords.xy";
> +      break;
> +   case GL_TEXTURE_3D:
> +      sampler->type = "sampler3D";
> +      sampler->func = "texture3D";
> +      sampler->texcoords = "texCoords";
> +      break;
> +   case GL_TEXTURE_CUBE_MAP:
> +      sampler->type = "samplerCube";
> +      sampler->func = "textureCube";
> +      sampler->texcoords = "texCoords";
> +      break;
> +   case GL_TEXTURE_1D_ARRAY:
> +      sampler->type = "sampler1DARRAY";
> +      sampler->texcoords = "texCoords.xy";
> +      break;
> +   case GL_TEXTURE_2D_ARRAY:
> +      sampler->type = "sampler2DARRAY";
> +      sampler->texcoords = "texCoords";
> +      break;

Don't you need to set sampler->func for the ARARY cases?

Also note that we don't support mipmap generation for 3D textures yet 
(it's a sw fallback) and I don't recall ever testing 1D/2D ARRAY 
mipmap generation.


> +   default:
> +      /* unexpected texture target */
> +      return;
> +   }
> +}
> +
> +
> +static void
>   setup_glsl_generate_mipmap(struct gl_context *ctx,
> -                           struct gen_mipmap_state *mipmap)
> +                           struct gen_mipmap_state *mipmap,
> +                           GLenum target)
>   {
>      struct vertex {
>         GLfloat x, y, tex[3];
>      };
> +   struct glsl_sampler sampler;
>
>      static const char *vs_source =
>         "attribute vec2 position;\n"
> @@ -3020,14 +3070,17 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>         "   texCoords = textureCoords;\n"
>         "   gl_Position = vec4(position, 0.0, 1.0);\n"
>         "}\n";
> -   static const char *fs_source =
> -      "uniform sampler2D tex2d;\n"
> +   static const char *fs_template =
> +      "#define SAMPLER_TYPE %s\n"
> +      "#define SAMPLER_FUNCTION %s\n"
> +      "#define TEX_COORDS %s\n"
> +      "uniform SAMPLER_TYPE texSampler;\n"
>         "varying vec3 texCoords;\n"
>         "void main()\n"
>         "{\n"
> -      "   gl_FragColor = texture2D(tex2d, texCoords.xy);\n"
> +      "   gl_FragColor = SAMPLER_FUNCTION(texSampler, TEX_COORDS);\n"
>         "}\n";
> -
> +
>      static const char *vs_int_source =
>         "#version 130\n"
>         "in vec2 position;\n"
> @@ -3036,18 +3089,22 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>         "void main()\n"
>         "{\n"
>         "   texCoords = textureCoords;\n"
> -      "   gl_Position = gl_Vertex;\n"
> +      "   gl_Position = vec4(position, 0.0, 1.0);\n"
>         "}\n";
> -   static const char *fs_int_source =
> +   static const char *fs_int_template =
>         "#version 130\n"
> -      "uniform isampler2D tex2d;\n"
> +      "#define SAMPLER_TYPE i%s\n"
> +      "#define TEX_COORDS %s\n"
> +      "uniform SAMPLER_TYPE texSampler;\n"
>         "in vec3 texCoords;\n"
>         "out ivec4 out_color;\n"
>         "\n"
>         "void main()\n"
>         "{\n"
> -      "   out_color = texture(tex2d, texCoords.xy);\n"
> +      "   out_color = texture(texSampler, TEX_COORDS);\n"
>         "}\n";
> +   char *fs_source, *fs_int_source;
> +   unsigned fs_alloc_len;
>      GLuint vs, fs;
>
>      /* Check if already initialized */
> @@ -3067,6 +3124,15 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>      _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);
> +   fs_alloc_len = strlen(fs_template) + strlen(sampler.type) +
> +                  strlen(sampler.func) + strlen(sampler.texcoords) + 1;
> +   fs_source = (char *) malloc(fs_alloc_len);
> +
> +   sprintf(fs_source, fs_template,
> +           sampler.type, sampler.func, sampler.texcoords);
> +
>      vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source);
>      fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source);
>
> @@ -3080,9 +3146,20 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>      _mesa_EnableVertexAttribArrayARB(0);
>      _mesa_EnableVertexAttribArrayARB(1);
>      link_program_with_debug(ctx, mipmap->ShaderProg);
> +   free(fs_source);
>
>      if ((_mesa_is_desktop_gl(ctx)&&  ctx->Const.GLSLVersion>= 130) ||
>          _mesa_is_gles3(ctx)){
> +      /* Generate a fragment shader program appropriate for the texture
> +       * target
> +       */
> +      fs_alloc_len = strlen(fs_int_template) + strlen(sampler.type) +
> +                     strlen(sampler.texcoords) + 1;
> +      fs_int_source = (char *) malloc(fs_alloc_len);
> +
> +      sprintf(fs_int_source, fs_int_template,
> +              sampler.type, sampler.texcoords);
> +

I think the ARB is leaning toward disallowing automatic mipmap 
generation for integer-valued textures.  So you might put that part on 
hold.


>         vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source);
>         fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source);
>
> @@ -3099,6 +3176,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>          * BindFragDataLocation to 0.
>          */
>         link_program_with_debug(ctx, mipmap->IntegerShaderProg);
> +      free(fs_int_source);
>      }
>   }
>
> @@ -3172,7 +3250,7 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
>       * GenerateMipmap function.
>       */
>      if (use_glsl_version) {
> -      setup_glsl_generate_mipmap(ctx, mipmap);
> +      setup_glsl_generate_mipmap(ctx, mipmap, target);
>
>         if (texObj->_IsIntegerFormat)
>            _mesa_UseProgramObjectARB(mipmap->IntegerShaderProg);



More information about the mesa-dev mailing list