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

Anuj Phogat anuj.phogat at gmail.com
Tue Sep 11 12:08:36 PDT 2012


On Tue, Sep 11, 2012 at 12:56 AM, Ian Romanick <idr at freedesktop.org> wrote:
> On 09/05/2012 05:42 AM, 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;
>> +   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"
>
>
> Since each of these is only used once, why use the extra #defines?  I
> believe we can use $ to force the arguments to have the same order.
>
>
> static const char *fs_template =
>         "uniform %1$s texSampler;\n"
>
>         "varying vec3 texCoords;\n"
>         "void main()\n"
>         "{\n"
>         "   gl_FragColor = %2$s(texSampler, %3$s);\n"
>         "}\n";
>
> This works like the {0} formatting in Python.
>
> Brian, do you know if this is supported on Windows?
>
Never used this before. Good to know this technique.
I used #defines for better readability of shader code. We can anyway
pass the arguments in order we need them without the need of $.

>> +      "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);
>> +
>
>
> If we can use ralloc in this code, ralloc_asprintf would make this a lot
> better.
>
>
>         /* Generate a fragment shader program appropriate for the
>          * texture target
>          */
>         setup_texture_sampler(target, &sampler);
>         fs_source = ralloc_asprintf(mem_ctx, fs_template,
>                 sampler.type, sampler.func, sampler.texcoords);
>
>
Right. This looks better. I'll see if it can be used in meta.c

>>      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);
>> +
>
>
> Same here.
>
>
>>         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