gallium/u_blitter: make nearest filtering emulation using TXF conformant
authorMarek Olšák <marek.olsak@amd.com>
Sun, 17 Jul 2022 12:25:23 +0000 (08:25 -0400)
committerMarge Bot <emma+marge@anholt.net>
Tue, 9 Aug 2022 19:19:09 +0000 (19:19 +0000)
This is required by glBlitFramebuffer.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Acked-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17692>

src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_simple_shaders.c
src/gallium/auxiliary/util/u_simple_shaders.h
src/gallium/drivers/d3d12/ci/d3d12-quick_gl.txt

index c7f5a07..85522a1 100644 (file)
@@ -148,7 +148,7 @@ struct blitter_context_priv
    bool has_stencil_export;
    bool has_texture_multisample;
    bool has_tex_lz;
-   bool has_txf;
+   bool has_txf_txq;
    bool has_sample_shading;
    bool cube_as_2darray;
    bool has_texrect;
@@ -214,8 +214,8 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
 
    ctx->has_tex_lz = pipe->screen->get_param(pipe->screen,
                                              PIPE_CAP_TGSI_TEX_TXF_LZ);
-   ctx->has_txf = pipe->screen->get_param(pipe->screen,
-                                          PIPE_CAP_GLSL_FEATURE_LEVEL) >= 130;
+   ctx->has_txf_txq = pipe->screen->get_param(pipe->screen,
+                                              PIPE_CAP_GLSL_FEATURE_LEVEL) >= 130;
    ctx->has_sample_shading = pipe->screen->get_param(pipe->screen,
                                                      PIPE_CAP_SAMPLE_SHADING);
    ctx->cube_as_2darray = pipe->screen->get_param(pipe->screen,
@@ -1036,7 +1036,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
             }
             else {
                *shader = util_make_fs_msaa_resolve(pipe, tgsi_tex,
-                                                   src_nr_samples);
+                                                   src_nr_samples, ctx->has_txf_txq);
             }
          }
       }
@@ -1050,7 +1050,8 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
          if (!*shader) {
             assert(!ctx->cached_all_shaders);
             *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex, stype, dtype,
-                                                   ctx->has_sample_shading);
+                                                   ctx->has_sample_shading,
+                                                   ctx->has_txf_txq);
          }
       }
 
@@ -1134,7 +1135,8 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
          enum tgsi_texture_type tgsi_tex;
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
-         *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex, sample_shading);
+         *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex, sample_shading,
+                                                ctx->has_txf_txq);
       }
 
       return *shader;
@@ -1180,7 +1182,8 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
          *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex,
-                                                       sample_shading);
+                                                       sample_shading,
+                                                       ctx->has_txf_txq);
       }
 
       return *shader;
@@ -1226,7 +1229,8 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_samples);
          *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex,
-                                                  sample_shading);
+                                                  sample_shading,
+                                                  ctx->has_txf_txq);
       }
 
       return *shader;
@@ -1275,7 +1279,7 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter)
    /* It only matters if i <= 1 or > 1. */
    for (samples = 1; samples <= max_samples; samples++) {
       for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {
-         for (use_txf = 0; use_txf <= ctx->has_txf; use_txf++) {
+         for (use_txf = 0; use_txf <= ctx->has_txf_txq; use_txf++) {
             if (!has_arraytex &&
                 (target == PIPE_TEXTURE_1D_ARRAY ||
                  target == PIPE_TEXTURE_2D_ARRAY)) {
@@ -2050,7 +2054,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
    bool use_txf = false;
 
    /* Don't support scaled blits. The TXF shader uses F2I for rounding. */
-   if (ctx->has_txf &&
+   if (ctx->has_txf_txq &&
        !is_scaled &&
        filter == PIPE_TEX_FILTER_NEAREST &&
        src->target != PIPE_TEXTURE_CUBE &&
@@ -2839,7 +2843,7 @@ get_stencil_blit_fallback_fs(struct blitter_context_priv *ctx, bool msaa_src)
 {
    if (!ctx->fs_stencil_blit_fallback[msaa_src]) {
       ctx->fs_stencil_blit_fallback[msaa_src] =
-         util_make_fs_stencil_blit(ctx->base.pipe, msaa_src);
+         util_make_fs_stencil_blit(ctx->base.pipe, msaa_src, ctx->has_txf_txq);
    }
 
    return ctx->fs_stencil_blit_fallback[msaa_src];
index 33952f7..923389a 100644 (file)
@@ -208,7 +208,19 @@ ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out,
    if (use_txf) {
       struct ureg_dst temp = ureg_DECL_temporary(ureg);
 
-      ureg_F2I(ureg, temp, coord);
+      /* Nearest filtering floors and then converts to integer, and then
+       * applies clamp to edge as clamp(coord, 0, dim - 1).
+       * u_blitter only uses this when the coordinates are in bounds,
+       * so no clamping is needed.
+       */
+      unsigned wrmask = tex_target == TGSI_TEXTURE_1D ||
+                        tex_target == TGSI_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_X :
+                        tex_target == TGSI_TEXTURE_3D ? TGSI_WRITEMASK_XYZ :
+                                                        TGSI_WRITEMASK_XY;
+
+      ureg_MOV(ureg, temp, coord);
+      ureg_FLR(ureg, ureg_writemask(temp, wrmask), ureg_src(temp));
+      ureg_F2I(ureg, temp, ureg_src(temp));
 
       if (load_level_zero)
          ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler);
@@ -527,41 +539,90 @@ util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
 static void *
 util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
                            enum tgsi_texture_type tgsi_tex,
-                           bool sample_shading,
+                           bool sample_shading, bool has_txq,
                            const char *samp_type,
                            const char *output_semantic,
                            const char *output_mask,
                            const char *conversion)
 {
-   static const char shader_templ[] =
-         "FRAG\n"
-         "DCL IN[0], GENERIC[0], LINEAR\n"
-         "DCL SAMP[0]\n"
-         "DCL SVIEW[0], %s, %s\n"
-         "DCL OUT[0], %s\n"
-         "DCL TEMP[0]\n"
-         "IMM[0] INT32 {0, -1, 2147483647, 0}\n"
-         "%s"
-
-         "F2U TEMP[0], IN[0]\n"
-         "%s"
-         "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
-         "%s"
-         "MOV OUT[0]%s, TEMP[0]\n"
-         "END\n";
-
-   const char *type = tgsi_texture_names[tgsi_tex];
-   char text[sizeof(shader_templ)+400];
+   char text[1000];
    struct tgsi_token tokens[1000];
    struct pipe_shader_state state = {0};
 
-   assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
-          tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
-
-   snprintf(text, sizeof(text), shader_templ, type, samp_type,
-            output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
-            sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
-            type, conversion, output_mask);
+   if (has_txq) {
+      static const char shader_templ[] =
+            "FRAG\n"
+            "DCL IN[0], GENERIC[0], LINEAR\n"
+            "DCL SAMP[0]\n"
+            "DCL SVIEW[0], %s, %s\n"
+            "DCL OUT[0], %s\n"
+            "DCL TEMP[0..1]\n"
+            "IMM[0] INT32 {0, -1, 2147483647, 0}\n"
+            "%s"
+
+            /* Nearest filtering floors and then converts to integer, and then
+             * applies clamp to edge as clamp(coord, 0, dim - 1).
+             */
+            "MOV TEMP[0], IN[0]\n"
+            "FLR TEMP[0].xy, TEMP[0]\n"
+            "F2I TEMP[0], TEMP[0]\n"
+            "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+            /* Clamp to edge for the upper bound. */
+            "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
+            "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
+            "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
+            /* Texel fetch. */
+            "%s"
+            "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
+            "%s"
+            "MOV OUT[0]%s, TEMP[0]\n"
+            "END\n";
+
+      const char *type = tgsi_texture_names[tgsi_tex];
+
+      assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
+             tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
+
+      snprintf(text, sizeof(text), shader_templ, type, samp_type,
+               output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
+               type, sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
+               type, conversion, output_mask);
+   } else {
+      static const char shader_templ[] =
+            "FRAG\n"
+            "DCL IN[0], GENERIC[0], LINEAR\n"
+            "DCL SAMP[0]\n"
+            "DCL SVIEW[0], %s, %s\n"
+            "DCL OUT[0], %s\n"
+            "DCL TEMP[0..1]\n"
+            "IMM[0] INT32 {0, -1, 2147483647, 0}\n"
+            "%s"
+
+            /* Nearest filtering floors and then converts to integer, and then
+             * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp
+             * to dim - 1 because TXQ is unsupported.
+             */
+            "MOV TEMP[0], IN[0]\n"
+            "FLR TEMP[0].xy, TEMP[0]\n"
+            "F2I TEMP[0], TEMP[0]\n"
+            "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+            /* Texel fetch. */
+            "%s"
+            "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
+            "%s"
+            "MOV OUT[0]%s, TEMP[0]\n"
+            "END\n";
+
+      const char *type = tgsi_texture_names[tgsi_tex];
+
+      assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
+             tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
+
+      snprintf(text, sizeof(text), shader_templ, type, samp_type,
+               output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
+               sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
+               type, conversion, output_mask);
+   }
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       puts(text);
@@ -587,7 +648,7 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe,
                              enum tgsi_texture_type tgsi_tex,
                              enum tgsi_return_type stype,
                              enum tgsi_return_type dtype,
-                             bool sample_shading)
+                             bool sample_shading, bool has_txq)
 {
    const char *samp_type;
    const char *conversion = "";
@@ -609,8 +670,8 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe,
       samp_type = "FLOAT";
    }
 
-   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, samp_type,
-                                     "COLOR[0]", "", conversion);
+   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
+                                     samp_type, "COLOR[0]", "", conversion);
 }
 
 
@@ -622,10 +683,10 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe,
 void *
 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
                              enum tgsi_texture_type tgsi_tex,
-                             bool sample_shading)
+                             bool sample_shading, bool has_txq)
 {
-   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "FLOAT",
-                                     "POSITION", ".z",
+   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
+                                     "FLOAT", "POSITION", ".z",
                                      "MOV TEMP[0].z, TEMP[0].xxxx\n");
 }
 
@@ -638,10 +699,10 @@ util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
 void *
 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
                                enum tgsi_texture_type tgsi_tex,
-                               bool sample_shading)
+                               bool sample_shading, bool has_txq)
 {
-   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "UINT",
-                                     "STENCIL", ".y",
+   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq,
+                                     "UINT", "STENCIL", ".y",
                                      "MOV TEMP[0].y, TEMP[0].xxxx\n");
 }
 
@@ -656,37 +717,82 @@ util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
 void *
 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
                                     enum tgsi_texture_type tgsi_tex,
-                                    bool sample_shading)
+                                    bool sample_shading, bool has_txq)
 {
-   static const char shader_templ[] =
-         "FRAG\n"
-         "DCL IN[0], GENERIC[0], LINEAR\n"
-         "DCL SAMP[0..1]\n"
-         "DCL SVIEW[0], %s, FLOAT\n"
-         "DCL SVIEW[1], %s, UINT\n"
-         "DCL OUT[0], POSITION\n"
-         "DCL OUT[1], STENCIL\n"
-         "DCL TEMP[0]\n"
-         "%s"
-
-         "F2U TEMP[0], IN[0]\n"
-         "%s"
-         "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
-         "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
-         "END\n";
-
    const char *type = tgsi_texture_names[tgsi_tex];
-   char text[sizeof(shader_templ)+400];
+   char text[1000];
    struct tgsi_token tokens[1000];
    struct pipe_shader_state state = {0};
 
    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
 
-   sprintf(text, shader_templ, type, type,
-           sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
-           sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
-           type, type);
+   if (has_txq) {
+      static const char shader_templ[] =
+            "FRAG\n"
+            "DCL IN[0], GENERIC[0], LINEAR\n"
+            "DCL SAMP[0..1]\n"
+            "DCL SVIEW[0], %s, FLOAT\n"
+            "DCL SVIEW[1], %s, UINT\n"
+            "DCL OUT[0], POSITION\n"
+            "DCL OUT[1], STENCIL\n"
+            "DCL TEMP[0..1]\n"
+            "IMM[0] INT32 {0, -1, 0, 0}\n"
+            "%s"
+
+            /* Nearest filtering floors and then converts to integer, and then
+             * applies clamp to edge as clamp(coord, 0, dim - 1).
+             */
+            "MOV TEMP[0], IN[0]\n"
+            "FLR TEMP[0].xy, TEMP[0]\n"
+            "F2I TEMP[0], TEMP[0]\n"
+            "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+            /* Clamp to edge for the upper bound. */
+            "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
+            "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
+            "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
+            /* Texel fetch. */
+            "%s"
+            "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
+            "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
+            "END\n";
+
+      sprintf(text, shader_templ, type, type,
+              sample_shading ? "DCL SV[0], SAMPLEID\n" : "", type,
+              sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
+              type, type);
+   } else {
+      static const char shader_templ[] =
+            "FRAG\n"
+            "DCL IN[0], GENERIC[0], LINEAR\n"
+            "DCL SAMP[0..1]\n"
+            "DCL SVIEW[0], %s, FLOAT\n"
+            "DCL SVIEW[1], %s, UINT\n"
+            "DCL OUT[0], POSITION\n"
+            "DCL OUT[1], STENCIL\n"
+            "DCL TEMP[0..1]\n"
+            "IMM[0] INT32 {0, -1, 0, 0}\n"
+            "%s"
+
+            /* Nearest filtering floors and then converts to integer, and then
+             * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp
+             * to dim - 1 because TXQ is unsupported.
+             */
+            "MOV TEMP[0], IN[0]\n"
+            "FLR TEMP[0].xy, TEMP[0]\n"
+            "F2I TEMP[0], TEMP[0]\n"
+            "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+            /* Texel fetch. */
+            "%s"
+            "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
+            "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
+            "END\n";
+
+      sprintf(text, shader_templ, type, type,
+              sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
+              sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
+              type, type);
+   }
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       assert(0);
@@ -703,7 +809,8 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
 
 void *
 util_make_fs_msaa_resolve(struct pipe_context *pipe,
-                          enum tgsi_texture_type tgsi_tex, unsigned nr_samples)
+                          enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
+                          bool has_txq)
 {
    struct ureg_program *ureg;
    struct ureg_src sampler, coord;
@@ -728,7 +835,25 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe,
 
    /* Instructions. */
    ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
-   ureg_F2U(ureg, tmp_coord, coord);
+
+   /* Nearest filtering floors and then converts to integer, and then
+    * applies clamp to edge as clamp(coord, 0, dim - 1).
+    */
+   ureg_MOV(ureg, tmp_coord, coord);
+   ureg_FLR(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY),
+            ureg_src(tmp_coord));
+   ureg_F2I(ureg, tmp_coord, ureg_src(tmp_coord));
+   ureg_IMAX(ureg, tmp_coord, ureg_src(tmp_coord), ureg_imm1i(ureg, 0));
+
+   /* Clamp to edge for the upper bound. */
+   if (has_txq) {
+      ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex,
+               ureg_imm1u(ureg, 0), sampler);
+      ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp),
+                ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */
+      ureg_IMIN(ureg,  ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY),
+                ureg_src(tmp_coord), ureg_src(tmp));
+   }
 
    for (i = 0; i < nr_samples; i++) {
       /* Read one sample. */
@@ -1153,32 +1278,73 @@ util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe,
 }
 
 void *
-util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src)
+util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq)
 {
-   static const char shader_templ[] =
-      "FRAG\n"
-      "DCL IN[0], GENERIC[0], LINEAR\n"
-      "DCL SAMP[0]\n"
-      "DCL SVIEW[0], %s, UINT\n"
-      "DCL CONST[0][0]\n"
-      "DCL TEMP[0]\n"
-
-      "F2U TEMP[0], IN[0]\n"
-      "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
-      "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
-      "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
-      "U2F TEMP[0].x, TEMP[0]\n"
-      "KILL_IF -TEMP[0].xxxx\n"
-      "END\n";
-
-   char text[sizeof(shader_templ)+100];
+   char text[1000];
    struct tgsi_token tokens[1000];
    struct pipe_shader_state state = { 0 };
-
    enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA :
                                                 TGSI_TEXTURE_2D;
 
-   sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]);
+   if (has_txq) {
+      static const char shader_templ[] =
+         "FRAG\n"
+         "DCL IN[0], GENERIC[0], LINEAR\n"
+         "DCL SAMP[0]\n"
+         "DCL SVIEW[0], %s, UINT\n"
+         "DCL CONST[0][0]\n"
+         "DCL TEMP[0..1]\n"
+         "IMM[0] INT32 {0, -1, 0, 0}\n"
+
+         /* Nearest filtering floors and then converts to integer, and then
+          * applies clamp to edge as clamp(coord, 0, dim - 1).
+          */
+         "MOV TEMP[0], IN[0]\n"
+         "FLR TEMP[0].xy, TEMP[0]\n"
+         "F2I TEMP[0], TEMP[0]\n"
+         "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+         /* Clamp to edge for the upper bound. */
+         "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n"
+         "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */
+         "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n"
+         /* Texel fetch. */
+         "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
+         "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
+         "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
+         "U2F TEMP[0].x, TEMP[0]\n"
+         "KILL_IF -TEMP[0].xxxx\n"
+         "END\n";
+
+      sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex],
+              tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]);
+   } else {
+      static const char shader_templ[] =
+         "FRAG\n"
+         "DCL IN[0], GENERIC[0], LINEAR\n"
+         "DCL SAMP[0]\n"
+         "DCL SVIEW[0], %s, UINT\n"
+         "DCL CONST[0][0]\n"
+         "DCL TEMP[0..1]\n"
+         "IMM[0] INT32 {0, -1, 0, 0}\n"
+
+         /* Nearest filtering floors and then converts to integer, and then
+          * applies clamp to edge as clamp(coord, 0, dim - 1).
+          */
+         "MOV TEMP[0], IN[0]\n"
+         "FLR TEMP[0].xy, TEMP[0]\n"
+         "F2I TEMP[0], TEMP[0]\n"
+         "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n"
+         /* Texel fetch. */
+         "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
+         "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
+         "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
+         "U2F TEMP[0].x, TEMP[0]\n"
+         "KILL_IF -TEMP[0].xxxx\n"
+         "END\n";
+
+      sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex],
+              tgsi_texture_names[tgsi_tex]);
+   }
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       assert(0);
index 20d88b0..e278d41 100644 (file)
@@ -118,30 +118,31 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe,
                              enum tgsi_texture_type tgsi_tex,
                              enum tgsi_return_type stype,
                              enum tgsi_return_type dtype,
-                             bool sample_shading);
+                             bool sample_shading, bool has_txq);
 
 
 extern void *
 util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
                              enum tgsi_texture_type tgsi_tex,
-                             bool sample_shading);
+                             bool sample_shading, bool has_txq);
 
 
 extern void *
 util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
                                     enum tgsi_texture_type tgsi_tex,
-                                    bool sample_shading);
+                                    bool sample_shading, bool has_txq);
 
 
 void *
 util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
                                enum tgsi_texture_type tgsi_tex,
-                               bool sample_shading);
+                               bool sample_shading, bool has_txq);
 
 
 void *
 util_make_fs_msaa_resolve(struct pipe_context *pipe,
-                          enum tgsi_texture_type tgsi_tex, unsigned nr_samples);
+                          enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
+                          bool has_txq);
 
 
 void *
@@ -172,7 +173,7 @@ util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe,
                                        const unsigned vertices_per_patch);
 
 void *
-util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src);
+util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq);
 
 void *
 util_make_fs_clear_all_cbufs(struct pipe_context *pipe);
index 38fbd26..80b8a14 100644 (file)
@@ -2794,10 +2794,20 @@ spec/ext_framebuffer_multisample/blit-multiple-render-targets 32: skip
 spec/ext_framebuffer_multisample/clear 32 color: skip
 spec/ext_framebuffer_multisample/clear 32 depth: skip
 spec/ext_framebuffer_multisample/clear 32 stencil: skip
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 16 downsample: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 16 msaa: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 2 downsample: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 2 msaa: fail
 spec/ext_framebuffer_multisample/clip-and-scissor-blit 32 downsample: skip
 spec/ext_framebuffer_multisample/clip-and-scissor-blit 32 msaa: skip
 spec/ext_framebuffer_multisample/clip-and-scissor-blit 32 normal: skip
 spec/ext_framebuffer_multisample/clip-and-scissor-blit 32 upsample: skip
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 4 downsample: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 4 msaa: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 6 downsample: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 6 msaa: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 8 downsample: fail
+spec/ext_framebuffer_multisample/clip-and-scissor-blit 8 msaa: fail
 spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage 16: fail
 spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage 2: fail
 spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage 32: skip
@@ -3511,8 +3521,8 @@ wgl/wgl-sanity: skip
 summary:
        name:  results
        ----  --------
-       pass:    17873
-       fail:     2035
+       pass:    17863
+       fail:     2045
       crash:       11
        skip:     1445
     timeout:        0