meta: Add support for integer blits.
authorEric Anholt <eric@anholt.net>
Tue, 11 Feb 2014 07:44:54 +0000 (23:44 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 21 Feb 2014 18:43:38 +0000 (10:43 -0800)
Compared to i965, the code generated doesn't use the AVG instruction.  But
I'm not sure that multisampled integer resolves are really that important
to worry about.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/common/meta.h
src/mesa/drivers/common/meta_blit.c

index c7a21fc065604637ccd734f5fef70d3cc52a8412..fcf45c40352bae9dbb38d11c54b4ef4f8a056d11 100644 (file)
@@ -221,9 +221,19 @@ struct blit_shader_table {
    struct blit_shader sampler_cubemap_array;
 };
 
+/**
+ * Indices in the blit_state->msaa_shaders[] array
+ *
+ * Note that setup_glsl_msaa_blit_shader() assumes that the _INT enums are one
+ * more than the non-_INT version and _UINT is one beyond that.
+ */
 enum blit_msaa_shader {
    BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE,
+   BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT,
+   BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT,
    BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY,
+   BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_INT,
+   BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_UINT,
    BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE,
    BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY,
    BLIT_MSAA_SHADER_COUNT,
index 7f5416dfbd6d3dde16e5a3250e0eb9bb27bb1025..34b58d99a03a61b72114916742d71fc277da53e8 100644 (file)
@@ -95,9 +95,24 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
    enum blit_msaa_shader shader_index;
    const char *samplers[] = {
       [BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE] = "sampler2DMS",
+      [BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT] = "isampler2DMS",
+      [BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT] = "usampler2DMS",
       [BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY] = "sampler2DMS",
+      [BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_INT] = "isampler2DMS",
+      [BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY_UINT] = "usampler2DMS",
    };
    bool dst_is_msaa = false;
+   GLenum src_datatype;
+   const char *vec4_prefix;
+
+   if (src_rb) {
+      src_datatype = _mesa_get_format_datatype(src_rb->Format);
+   } else {
+      /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and
+       * doesn't handle integer.
+       */
+      src_datatype = GL_UNSIGNED_NORMALIZED;
+   }
 
    if (ctx->DrawBuffer->Visual.samples > 1) {
       /* If you're calling meta_BlitFramebuffer with the destination
@@ -135,6 +150,21 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
       shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE;
    }
 
+   /* We rely on the enum being sorted this way. */
+   STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT ==
+                 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 1);
+   STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT ==
+                 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 2);
+   if (src_datatype == GL_INT) {
+      shader_index++;
+      vec4_prefix = "i";
+   } else if (src_datatype == GL_UNSIGNED_INT) {
+      shader_index += 2;
+      vec4_prefix = "u";
+   } else {
+      vec4_prefix = "";
+   }
+
    if (blit->msaa_shaders[shader_index]) {
       _mesa_UseProgram(blit->msaa_shaders[shader_index]);
       return;
@@ -199,11 +229,25 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
       int samples = MAX2(src_rb->NumSamples, 1);
       char *sample_resolve;
       const char *arb_sample_shading_extension_string;
+      const char *merge_function;
 
       if (dst_is_msaa) {
          arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable";
          sample_resolve = ralloc_asprintf(mem_ctx, "   out_color = texelFetch(texSampler, ivec2(texCoords), gl_SampleID);");
+         merge_function = "";
       } else {
+         if (src_datatype == GL_INT) {
+            merge_function =
+               "ivec4 merge(ivec4 a, ivec4 b) { return (a >> ivec4(1)) + (b >> ivec4(1)) + (a & b & ivec4(1)); }\n";
+         } else if (src_datatype == GL_UNSIGNED_INT) {
+            merge_function =
+               "uvec4 merge(uvec4 a, uvec4 b) { return (a >> uvec4(1)) + (b >> uvec4(1)) + (a & b & uvec4(1)); }\n";
+         } else {
+            /* The divide will happen at the end for floats. */
+            merge_function =
+               "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n";
+         }
+
          arb_sample_shading_extension_string = "";
 
          /* We're assuming power of two samples for this resolution procedure.
@@ -218,8 +262,8 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
          sample_resolve = rzalloc_size(mem_ctx, 1);
          for (int i = 0; i < samples; i++) {
             ralloc_asprintf_append(&sample_resolve,
-                                   "   vec4 sample_1_%d = texelFetch(texSampler, ivec2(texCoords), %d);\n",
-                                   i, i);
+                                   "   %svec4 sample_1_%d = texelFetch(texSampler, ivec2(texCoords), %d);\n",
+                                   vec4_prefix, i, i);
          }
          /* Now, merge each pair of samples, then merge each pair of those,
           * etc.
@@ -227,7 +271,8 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
          for (int step = 2; step <= samples; step *= 2) {
             for (int i = 0; i < samples; i += step) {
                ralloc_asprintf_append(&sample_resolve,
-                                      "vec4 sample_%d_%d = sample_%d_%d + sample_%d_%d;\n",
+                                      "   %svec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n",
+                                      vec4_prefix,
                                       step, i,
                                       step / 2, i,
                                       step / 2, i + step / 2);
@@ -235,9 +280,15 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
          }
 
          /* Scale the final result. */
-         ralloc_asprintf_append(&sample_resolve,
-                                "   out_color = sample_%d_0 / %f;\n",
-                                samples, (float)samples);
+         if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) {
+            ralloc_asprintf_append(&sample_resolve,
+                                   "   out_color = sample_%d_0;\n",
+                                   samples);
+         } else {
+            ralloc_asprintf_append(&sample_resolve,
+                                   "   out_color = sample_%d_0 / %f;\n",
+                                   samples, (float)samples);
+         }
       }
 
       vs_source = ralloc_asprintf(mem_ctx,
@@ -256,14 +307,17 @@ setup_glsl_msaa_blit_shader(struct gl_context *ctx,
                                   "%s\n"
                                   "uniform %s texSampler;\n"
                                   "in vec2 texCoords;\n"
-                                  "out vec4 out_color;\n"
+                                  "out %svec4 out_color;\n"
                                   "\n"
+                                  "%s" /* merge_function */
                                   "void main()\n"
                                   "{\n"
                                   "%s\n" /* sample_resolve */
                                   "}\n",
                                   arb_sample_shading_extension_string,
                                   samplers[shader_index],
+                                  vec4_prefix,
+                                  merge_function,
                                   sample_resolve);
    }