nv50,nvc0: fix depth/stencil resolve
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 29 Apr 2012 13:38:20 +0000 (15:38 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 29 Apr 2012 16:03:18 +0000 (18:03 +0200)
Cannot sample depth/stencil with a single view, and needed to use
different shader code for nve4.

src/gallium/drivers/nv50/nv50_formats.c
src/gallium/drivers/nv50/nv50_resource.h
src/gallium/drivers/nv50/nv50_surface.c
src/gallium/drivers/nv50/nv50_texture.xml.h
src/gallium/drivers/nvc0/nvc0_surface.c

index a009b27c861e3b55e72cc9db05402ac905f0445e..41757d2a00d34ade1fcb8c4a9894ea99888696eb 100644 (file)
@@ -60,6 +60,7 @@
 #endif
 
 #define NV50_SURFACE_FORMAT_NONE 0
+#define NV50_ZETA_FORMAT_NONE 0
 
 /* for vertex buffers: */
 #define NV50_TIC_0_FMT_8_8_8    NV50_TIC_0_FMT_8_8_8_8
@@ -167,10 +168,13 @@ const struct nv50_format nv50_format_table[PIPE_FORMAT_COUNT] =
    ZXB(Z16_UNORM, Z16_UNORM, C0, C0, C0, xx, UNORM, Z16, TZ),
    ZXB(Z32_FLOAT, Z32_FLOAT, C0, C0, C0, xx, FLOAT, Z32, TZ),
    ZXB(Z24X8_UNORM, Z24_X8_UNORM, C0, C0, C0, xx, UNORM, Z24_X8, TZ),
-   ZSB(Z24_UNORM_S8_UINT, Z24_S8_UNORM, C0, C1, C0, xx, UNORM, Z24_S8, TZ),
-   SZB(S8_UINT_Z24_UNORM, S8_Z24_UNORM, C1, C0, C1, xx, UNORM, S8_Z24, TZ),
-   ZSB(Z32_FLOAT_S8X24_UINT, Z32_S8_X24_FLOAT, C0, C1, C0, xx, FLOAT,
+   ZSB(Z24_UNORM_S8_UINT, Z24_S8_UNORM, C0, C0, C0, xx, UNORM, Z24_S8, TZ),
+   ZSB(X24S8_UINT, NONE, C1, C1, C1, xx, UNORM, Z24_S8, T),
+   SZB(S8_UINT_Z24_UNORM, S8_Z24_UNORM, C1, C1, C1, xx, UNORM, S8_Z24, TZ),
+   SZB(S8X24_UINT, NONE, C0, C0, C0, xx, UNORM, S8_Z24, T),
+   ZSB(Z32_FLOAT_S8X24_UINT, Z32_S8_X24_FLOAT, C0, C0, C0, xx, FLOAT,
        Z32_S8_X24, TZ),
+   ZSB(X32_S8X24_UINT, NONE, C1, C1, C1, xx, FLOAT, Z32_S8_X24, T),
 
    F3B(B5G6R5_UNORM, B5G6R5_UNORM, C2, C1, C0, xx, UNORM, 5_6_5, T),
    C4B(B5G5R5A1_UNORM, BGR5_A1_UNORM, C2, C1, C0, C3, UNORM, 5_5_5_1, TB),
index 5d5596ea6e3a8b2a269ca92fe1fff31ce398cc76..920fa0a4a2b665fabee4eee57d94c0ed784b19d1 100644 (file)
@@ -96,6 +96,18 @@ nv50_surface(struct pipe_surface *ps)
    return (struct nv50_surface *)ps;
 }
 
+static INLINE enum pipe_format
+nv50_zs_to_s_format(enum pipe_format format)
+{
+   switch (format) {
+   case PIPE_FORMAT_Z24_UNORM_S8_UINT: return PIPE_FORMAT_X24S8_UINT;
+   case PIPE_FORMAT_S8_UINT_Z24_UNORM: return PIPE_FORMAT_S8X24_UINT;
+   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: return PIPE_FORMAT_X32_S8X24_UINT;
+   default:
+      return format;
+   }
+}
+
 #ifndef __NVC0_RESOURCE_H__
 
 unsigned
index 0d29dcc8a2a40a92e39b4d5638767eff2822299a..b38e49ffcc103d341457782cb3f3d89da7bf9084 100644 (file)
@@ -207,7 +207,8 @@ nv50_resource_copy_region(struct pipe_context *pipe,
       return;
    }
 
-   assert(src->nr_samples == dst->nr_samples);
+   /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
+   assert((src->nr_samples | 1) == (dst->nr_samples | 1));
 
    m2mf = (src->format == dst->format) ||
       (util_format_get_blocksizebits(src->format) ==
@@ -433,8 +434,8 @@ struct nv50_blitctx
       struct nv50_program *fp;
       unsigned num_textures[3];
       unsigned num_samplers[3];
-      struct pipe_sampler_view *texture;
-      struct nv50_tsc_entry *sampler;
+      struct pipe_sampler_view *texture[2];
+      struct nv50_tsc_entry *sampler[2];
       unsigned dirty;
    } saved;
    struct nv50_program vp;
@@ -495,17 +496,21 @@ nv50_blitctx_make_fp(struct nv50_blitctx *blit)
       /* 3 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM) */
       0x80000000, /* interp $r0 v[0x00] */
       0x80010004, /* interp $r1 v[0x04] */
-      0x80020009, /* interp $r2 flat v[0x8] */
-      0x00040780,
-      0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
+      0x80020108, /* interp $r2 flat v[0x8] */
+      0x10008010, /* mov b32 $r4 $r0 */
+      0xf2820201, /* texauto live { $r0,#,#,# } $t1 $s1 { $r0,1,2 } */
+      0x00000784,
+      0xa000000d, /* cvt f32 $r3 s32 $r0 */
+      0x44014780,
+      0x10000801, /* mov b32 $r0 $r4 */
+      0x0403c780,
+      0xf2800001, /* texauto live { $r0,#,#,# } $t0 $s0 { $r0,1,2 } */
       0x00000784,
       0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
       0x04b7ffff,
-      0xa0000201, /* cvt f32 $r0 s32 $r1 */
-      0x44014780,
       0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
       0x8c004780,
-      0xc0010001, /* mul f32 $r0 $r0 1/0xff */
+      0xc0010601, /* mul f32 $r0 $r3 1/0xff */
       0x03b8080b,
       0xd03f0405, /* and b32 $r1 $r2 0x0000ff */
       0x0000000f,
@@ -531,14 +536,18 @@ nv50_blitctx_make_fp(struct nv50_blitctx *blit)
       /* 3 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
       0x80000000, /* interp $r0 v[0x00] */
       0x80010004, /* interp $r1 v[0x04] */
-      0x80020009, /* interp $r2 flat v[0x8] */
-      0x00040780,
-      0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
+      0x80020108, /* interp $r2 flat v[0x8] */
+      0x10008010, /* mov b32 $r4 $r0 */
+      0xf2820201, /* texauto live { $r0,#,#,# } $t1 $s1 { $r0,1,2 } */
+      0x00000784,
+      0xa000000d, /* cvt f32 $r3 s32 $r0 */
+      0x44014780,
+      0x10000801, /* mov b32 $r0 $r4 */
+      0x0403c780,
+      0xf2800001, /* texauto live { $r0,#,#,# } $t0 $s0 { $r0,1,2 } */
       0x00000784,
       0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
       0x04b7ffff,
-      0xa0000281, /* cvt f32 $r3 s32 $r1 */
-      0x44014780,
       0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
       0x8c004780,
       0xc001060d, /* mul f32 $r3 $r3 1/0xff */
@@ -569,7 +578,7 @@ nv50_blitctx_make_fp(struct nv50_blitctx *blit)
    blit->fp.translated = TRUE;
    blit->fp.code = (uint32_t *)code; /* const_cast */
    blit->fp.code_size = sizeof(code);
-   blit->fp.max_gpr = 4;
+   blit->fp.max_gpr = 5;
    blit->fp.max_out = 4;
    blit->fp.in_nr = 1;
    blit->fp.in[0].mask = 0x7; /* last component flat */
@@ -702,11 +711,19 @@ nv50_blit_set_src(struct nv50_context *nv50,
    templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
 
    nv50->textures[2][0] = nv50_create_sampler_view(pipe, res, &templ);
+   nv50->textures[2][0] = NULL;
 
    nv50_blit_fixup_tic_entry(nv50->textures[2][0]);
 
    nv50->num_textures[0] = nv50->num_textures[1] = 0;
    nv50->num_textures[2] = 1;
+
+   templ.format = nv50_zs_to_s_format(res->format);
+   if (templ.format != res->format) {
+      nv50->textures[2][1] = nv50_create_sampler_view(pipe, res, &templ);
+      nv50_blit_fixup_tic_entry(nv50->textures[2][1]);
+      nv50->num_textures[2] = 2;
+   }
 }
 
 static void
@@ -781,13 +798,16 @@ nv50_blitctx_pre_blit(struct nv50_blitctx *blit, struct nv50_context *nv50)
       blit->saved.num_textures[s] = nv50->num_textures[s];
       blit->saved.num_samplers[s] = nv50->num_samplers[s];
    }
-   blit->saved.texture = nv50->textures[2][0];
-   blit->saved.sampler = nv50->samplers[2][0];
+   blit->saved.texture[0] = nv50->textures[2][0];
+   blit->saved.texture[1] = nv50->textures[2][1];
+   blit->saved.sampler[0] = nv50->samplers[2][0];
+   blit->saved.sampler[1] = nv50->samplers[2][1];
 
    nv50->samplers[2][0] = &blit->sampler[blit->filter];
+   nv50->samplers[2][1] = &blit->sampler[blit->filter];
 
    nv50->num_samplers[0] = nv50->num_samplers[1] = 0;
-   nv50->num_samplers[2] = 1;
+   nv50->num_samplers[2] = 2;
 
    blit->saved.dirty = nv50->dirty;
 
@@ -815,13 +835,16 @@ nv50_blitctx_post_blit(struct nv50_context *nv50, struct nv50_blitctx *blit)
    nv50->fragprog = blit->saved.fp;
 
    pipe_sampler_view_reference(&nv50->textures[2][0], NULL);
+   pipe_sampler_view_reference(&nv50->textures[2][1], NULL);
 
    for (s = 0; s < 3; ++s) {
       nv50->num_textures[s] = blit->saved.num_textures[s];
       nv50->num_samplers[s] = blit->saved.num_samplers[s];
    }
-   nv50->textures[2][0] = blit->saved.texture;
-   nv50->samplers[2][0] = blit->saved.sampler;
+   nv50->textures[2][0] = blit->saved.texture[0];
+   nv50->textures[2][1] = blit->saved.texture[1];
+   nv50->samplers[2][0] = blit->saved.sampler[0];
+   nv50->samplers[2][1] = blit->saved.sampler[1];
 
    nv50->dirty = blit->saved.dirty |
       (NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR | NV50_NEW_SAMPLE_MASK |
index 2b140be8d800f69ac6dde2dcb1f6d38cd36ba294..34accd81741de71b292e374bbcd1030b4bd16f2d 100644 (file)
@@ -8,7 +8,7 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng
 git clone git://0x04.net/rules-ng-ng
 
 The rules-ng-ng source files this header was generated from are:
-- rnndb/nv50_texture.xml (   8111 bytes, from 2012-03-31 16:47:45)
+- rnndb/nv50_texture.xml (   8111 bytes, from 2012-04-29 11:17:45)
 - ./rnndb/copyright.xml  (   6452 bytes, from 2011-08-11 18:25:12)
 - ./rnndb/nvchipsets.xml (   3701 bytes, from 2012-03-22 20:40:59)
 - ./rnndb/nv50_defs.xml  (   5468 bytes, from 2011-08-11 18:25:12)
@@ -147,8 +147,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NV50_TIC_0_FMT_RGTC1                                   0x00000027
 #define NV50_TIC_0_FMT_RGTC2                                   0x00000028
 #define NV50_TIC_0_FMT_S8_Z24                                  0x00000029
-#define NV50_TIC_0_FMT_Z24_S8                                  0x0000002a
-#define NV50_TIC_0_FMT_Z24_X8                                  0x0000002b
+#define NV50_TIC_0_FMT_Z24_X8                                  0x0000002a
+#define NV50_TIC_0_FMT_Z24_S8                                  0x0000002b
 #define NV50_TIC_0_FMT_Z24_C8_MS4_CS4                          0x0000002c
 #define NV50_TIC_0_FMT_Z24_C8_MS8_CS8                          0x0000002d
 #define NV50_TIC_0_FMT_Z24_C8_MS4_CS12                         0x0000002e
index 2b47c04056e709cdb1841f899c5702ba333f1b71..607b02e0277dee6dc4aeeef679e850d545ad8d0a 100644 (file)
@@ -214,7 +214,8 @@ nvc0_resource_copy_region(struct pipe_context *pipe,
       return;
    }
 
-   assert(src->nr_samples == dst->nr_samples);
+   /* 0 and 1 are equal, only supporting 0/1, 2, 4 and 8 */
+   assert((src->nr_samples | 1) == (dst->nr_samples | 1));
 
    m2mf = (src->format == dst->format) ||
       (util_format_get_blocksizebits(src->format) ==
@@ -454,8 +455,8 @@ struct nvc0_blitctx
       struct nvc0_program *fp;
       unsigned num_textures[5];
       unsigned num_samplers[5];
-      struct pipe_sampler_view *texture;
-      struct nv50_tsc_entry *sampler;
+      struct pipe_sampler_view *texture[2];
+      struct nv50_tsc_entry *sampler[2];
       unsigned dirty;
    } saved;
    struct nvc0_program vp;
@@ -494,7 +495,7 @@ nvc0_blitctx_make_vp(struct nvc0_blitctx *blit)
 static void
 nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
 {
-   static const uint32_t code[] = /* use nvc0dis */
+   static const uint32_t code_nvc0[] = /* use nvc0dis */
    {
       /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
        * NOTE:
@@ -503,7 +504,7 @@ nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
        */
       0xfff01c00, 0xc07e0080,
       0xfff05c00, 0xc07e0084,
-      0x00001c86, 0x8013c000,
+      0x00001e86, 0x8013c000,
       0x00001de7, 0x80000000,
       /* size: 0x70 + padding  */
       0, 0, 0, 0,
@@ -517,9 +518,10 @@ nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
-      0xfff01c00, 0xc07e0080,
-      0xfff05c00, 0xc07e0084,
-      0x00001c86, 0x8010c000,
+      0xfff09c00, 0xc07e0080,
+      0xfff0dc00, 0xc07e0084,
+      0x00201e86, 0x80104000,
+      0x00205f06, 0x80104101,
       0xfc009c02, 0x312dffff,
       0x05001c88,
       0x09009e88,
@@ -534,19 +536,20 @@ nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
       0x0430dc02, 0x30ce0202,
       0x04209c02, 0x30de0202,
       0x00001de7, 0x80000000,
-      /* size: 0xc8 + padding */
-      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+      /* size: 0xd0 + padding */
+      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
       /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
       0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
       0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
       0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
-      0xfff01c00, 0xc07e0080,
-      0xfff05c00, 0xc07e0084,
-      0x00001c86, 0x8010c000,
+      0xfff09c00, 0xc07e0080,
+      0xfff0dc00, 0xc07e0084,
+      0x00201e86, 0x80104000,
+      0x00205f06, 0x80104101,
       0xfc009c02, 0x312dffff,
-      0x05081c88,
+      0x0500dc88,
       0x09009e88,
       0x0430dc02, 0x30ee0202,
       0xfc201c02, 0x38000003,
@@ -560,11 +563,92 @@ nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
       0x04209c02, 0x30ce0202,
       0x00001de7, 0x80000000,
    };
+   static const uint32_t code_nve4[] = /* use nvc0dis */
+   {
+      /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
+       * NOTE:
+       * NVC0 doesn't like tex 3d on non-3d textures, but there should
+       * only be 2d and 2d-array MS resources anyway.
+       */
+      0x2202e237, 0x200002ec,
+      0xfff01c00, 0xc07e0080,
+      0xfff05c00, 0xc07e0084,
+      0x00001e86, 0x8013c000,
+      0x00001de6, 0xf0000000,
+      0x00001de7, 0x80000000,
+      /* size: 0x80 */
+
+      /* 2 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM)
+       * Setup float outputs in a way that conversion to UNORM yields the
+       * desired byte value.
+       */
+      /* NOTE: need to repeat header */
+      0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+      0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
+      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+      0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
+      0x0202e237, 0x22804c22,
+      0xfff09c00, 0xc07e0080,
+      0xfff0dc00, 0xc07e0084,
+      0x00201e86, 0x80104008,
+      0x00205f06, 0x80104009,
+      0x00001de6, 0xf0000000,
+      0xfc009c02, 0x312dffff,
+      0x05201e04, 0x18000000,
+      0x00428047, 0x22020272,
+      0x09209c84, 0x14000000,
+      0x04001c02, 0x30ee0202,
+      0xfc205c02, 0x38000003,
+      0x0020dc02, 0x3803fc00,
+      0x00209c02, 0x380003fc,
+      0x05205e04, 0x18000000,
+      0x0d20de04, 0x18000000,
+      0x42004277, 0x200002e0,
+      0x09209e04, 0x18000000,
+      0x04105c02, 0x30ee0202,
+      0x0430dc02, 0x30ce0202,
+      0x04209c02, 0x30de0202,
+      0x00001de7, 0x80000000,
+      /* size: 0x100 */
+
+      /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
+      0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+      0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
+      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+      0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
+      0x0202e237, 0x22804c22,
+      0xfff09c00, 0xc07e0080,
+      0xfff0dc00, 0xc07e0084,
+      0x00201e86, 0x80104008,
+      0x00205f06, 0x80104009,
+      0x00001de6, 0xf0000000,
+      0xfc009c02, 0x312dffff,
+      0x0520de04, 0x18000000,
+      0x00428047, 0x22020272,
+      0x09209c84, 0x14000000,
+      0x0430dc02, 0x30ee0202,
+      0xfc201c02, 0x38000003,
+      0x00205c02, 0x380003fc,
+      0x00209c02, 0x3803fc00,
+      0x01201e04, 0x18000000,
+      0x05205e04, 0x18000000,
+      0x42004277, 0x200002e0,
+      0x09209e04, 0x18000000,
+      0x04001c02, 0x30ee0202,
+      0x04105c02, 0x30de0202,
+      0x04209c02, 0x30ce0202,
+      0x00001de7, 0x80000000,
+   };
 
    blit->fp.type = PIPE_SHADER_FRAGMENT;
    blit->fp.translated = TRUE;
-   blit->fp.code = (uint32_t *)code; /* const_cast */
-   blit->fp.code_size = sizeof(code);
+   if (blit->screen->base.class_3d >= NVE4_3D_CLASS) {
+      blit->fp.code = (uint32_t *)code_nve4; /* const_cast */
+      blit->fp.code_size = sizeof(code_nve4);
+   } else {
+      blit->fp.code = (uint32_t *)code_nvc0; /* const_cast */
+      blit->fp.code_size = sizeof(code_nvc0);
+   }
    blit->fp.max_gpr = 4;
 
    blit->fp.hdr[0]  = 0x00021462; /* fragprog magic */
@@ -666,7 +750,7 @@ nvc0_blit_set_dst(struct nvc0_context *nvc0,
 }
 
 static INLINE void
-nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view)
+nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view, const boolean filter)
 {
    struct nv50_tic_entry *ent = nv50_tic_entry(view);
 
@@ -674,12 +758,19 @@ nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view)
 
    /* magic: */
 
-   ent->tic[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
+   if (filter) {
+      /* affects quality of near vertical edges in MS8: */
+      ent->tic[3] = 0x20000000;
+   } else {
+      ent->tic[3] = 0;
+      ent->tic[6] = 0;
+   }
 }
 
 static void
 nvc0_blit_set_src(struct nvc0_context *nvc0,
-                  struct pipe_resource *res, unsigned level, unsigned layer)
+                  struct pipe_resource *res, unsigned level, unsigned layer,
+                  const boolean filter)
 {
    struct pipe_context *pipe = &nvc0->base.pipe;
    struct pipe_sampler_view templ;
@@ -694,12 +785,20 @@ nvc0_blit_set_src(struct nvc0_context *nvc0,
    templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
 
    nvc0->textures[4][0] = nvc0_create_sampler_view(pipe, res, &templ);
+   nvc0->textures[4][1] = NULL;
 
-   nvc0_blit_fixup_tic_entry(nvc0->textures[4][0]);
+   nvc0_blit_fixup_tic_entry(nvc0->textures[4][0], filter);
 
    for (s = 0; s <= 3; ++s)
       nvc0->num_textures[s] = 0;
    nvc0->num_textures[4] = 1;
+
+   templ.format = nv50_zs_to_s_format(res->format);
+   if (templ.format != res->format) {
+      nvc0->textures[4][1] = nvc0_create_sampler_view(pipe, res, &templ);
+      nvc0_blit_fixup_tic_entry(nvc0->textures[4][1], filter);
+      nvc0->num_textures[4] = 2;
+   }
 }
 
 static void
@@ -769,20 +868,26 @@ nvc0_blitctx_pre_blit(struct nvc0_blitctx *blit, struct nvc0_context *nvc0)
    for (s = 0; s <= 4; ++s) {
       blit->saved.num_textures[s] = nvc0->num_textures[s];
       blit->saved.num_samplers[s] = nvc0->num_samplers[s];
-      nvc0->textures_dirty[s] = ~0;
-      nvc0->samplers_dirty[s] = ~0;
+      nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
+      nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
    }
-   blit->saved.texture = nvc0->textures[4][0];
-   blit->saved.sampler = nvc0->samplers[4][0];
+   blit->saved.texture[0] = nvc0->textures[4][0];
+   blit->saved.texture[1] = nvc0->textures[4][1];
+   blit->saved.sampler[0] = nvc0->samplers[4][0];
+   blit->saved.sampler[1] = nvc0->samplers[4][1];
 
    nvc0->samplers[4][0] = &blit->sampler[blit->filter];
+   nvc0->samplers[4][1] = &blit->sampler[blit->filter];
 
    for (s = 0; s <= 3; ++s)
       nvc0->num_samplers[s] = 0;
-   nvc0->num_samplers[4] = 1;
+   nvc0->num_samplers[4] = 2;
 
    blit->saved.dirty = nvc0->dirty;
 
+   nvc0->textures_dirty[4] |= 3;
+   nvc0->samplers_dirty[4] |= 3;
+
    nvc0->dirty = NVC0_NEW_FRAMEBUFFER |
       NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
       NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
@@ -809,15 +914,21 @@ nvc0_blitctx_post_blit(struct nvc0_context *nvc0, struct nvc0_blitctx *blit)
    nvc0->fragprog = blit->saved.fp;
 
    pipe_sampler_view_reference(&nvc0->textures[4][0], NULL);
+   pipe_sampler_view_reference(&nvc0->textures[4][1], NULL);
 
    for (s = 0; s <= 4; ++s) {
       nvc0->num_textures[s] = blit->saved.num_textures[s];
       nvc0->num_samplers[s] = blit->saved.num_samplers[s];
-      nvc0->textures_dirty[s] = ~0;
-      nvc0->samplers_dirty[s] = ~0;
+      nvc0->textures_dirty[s] = (1 << nvc0->num_textures[s]) - 1;
+      nvc0->samplers_dirty[s] = (1 << nvc0->num_samplers[s]) - 1;
    }
-   nvc0->textures[4][0] = blit->saved.texture;
-   nvc0->samplers[4][0] = blit->saved.sampler;
+   nvc0->textures[4][0] = blit->saved.texture[0];
+   nvc0->textures[4][1] = blit->saved.texture[1];
+   nvc0->samplers[4][0] = blit->saved.sampler[0];
+   nvc0->samplers[4][1] = blit->saved.sampler[1];
+
+   nvc0->textures_dirty[4] |= 3;
+   nvc0->samplers_dirty[4] |= 3;
 
    nvc0->dirty = blit->saved.dirty |
       (NVC0_NEW_FRAMEBUFFER | NVC0_NEW_SCISSOR | NVC0_NEW_SAMPLE_MASK |
@@ -854,7 +965,7 @@ nvc0_resource_resolve(struct pipe_context *pipe,
    nvc0_blitctx_pre_blit(blit, nvc0);
 
    nvc0_blit_set_dst(nvc0, dst, info->dst.level, info->dst.layer);
-   nvc0_blit_set_src(nvc0, src, 0,               info->src.layer);
+   nvc0_blit_set_src(nvc0, src, 0,               info->src.layer, blit->filter);
 
    nvc0_blitctx_prepare_state(blit);