nvc0: implement multisample textures
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 6 Apr 2013 12:52:05 +0000 (14:52 +0200)
committerChristoph Bumiller <christoph.bumiller@speed.at>
Fri, 12 Apr 2013 11:02:18 +0000 (13:02 +0200)
src/gallium/drivers/nv50/codegen/nv50_ir.h
src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nv50/nv50_resource.h
src/gallium/drivers/nv50/nv50_surface.c
src/gallium/drivers/nvc0/codegen/nv50_ir_lowering_nvc0.cpp
src/gallium/drivers/nvc0/nvc0_context.c
src/gallium/drivers/nvc0/nvc0_miptree.c
src/gallium/drivers/nvc0/nvc0_screen.c
src/gallium/drivers/nvc0/nvc0_surface.c
src/gallium/drivers/nvc0/nvc0_tex.c

index 236673c24891beb43044eb20ac67c093a0adcec6..ae365af78558616eb074e32f0133ce72ee0385db 100644 (file)
@@ -824,6 +824,8 @@ public:
       int isArray() const { return descTable[target].array ? 1 : 0; }
       int isCube() const { return descTable[target].cube ? 1 : 0; }
       int isShadow() const { return descTable[target].shadow ? 1 : 0; }
+      int isMS() const {
+        return target == TEX_TARGET_2D_MS || target == TEX_TARGET_2D_MS_ARRAY; }
 
       Target& operator=(TexTarget targ)
       {
index b546429922d61dbb18fff12a239a118de247b1ef..68976914240f97466ed4f4978b7828e79c6dd994 100644 (file)
@@ -358,11 +358,13 @@ static nv50_ir::TexTarget translateTexture(uint tex)
    switch (tex) {
    NV50_IR_TEX_TARG_CASE(1D, 1D);
    NV50_IR_TEX_TARG_CASE(2D, 2D);
+   NV50_IR_TEX_TARG_CASE(2D_MSAA, 2D_MS);
    NV50_IR_TEX_TARG_CASE(3D, 3D);
    NV50_IR_TEX_TARG_CASE(CUBE, CUBE);
    NV50_IR_TEX_TARG_CASE(RECT, RECT);
    NV50_IR_TEX_TARG_CASE(1D_ARRAY, 1D_ARRAY);
    NV50_IR_TEX_TARG_CASE(2D_ARRAY, 2D_ARRAY);
+   NV50_IR_TEX_TARG_CASE(2D_ARRAY_MSAA, 2D_MS_ARRAY);
    NV50_IR_TEX_TARG_CASE(CUBE_ARRAY, CUBE_ARRAY);
    NV50_IR_TEX_TARG_CASE(SHADOW1D, 1D_SHADOW);
    NV50_IR_TEX_TARG_CASE(SHADOW2D, 2D_SHADOW);
@@ -581,6 +583,8 @@ static nv50_ir::operation translateOpcode(uint opcode)
    NV50_IR_OPCODE_CASE(SAMPLE_C_LZ, TEX);
    NV50_IR_OPCODE_CASE(SAMPLE_D, TXD);
    NV50_IR_OPCODE_CASE(SAMPLE_L, TXL);
+   NV50_IR_OPCODE_CASE(SAMPLE_I, TXF);
+   NV50_IR_OPCODE_CASE(SAMPLE_I_MS, TXF);
    NV50_IR_OPCODE_CASE(GATHER4, TXG);
    NV50_IR_OPCODE_CASE(SVIEWINFO, TXQ);
 
@@ -1134,7 +1138,7 @@ private:
    // R,S,L,C,Dx,Dy encode TGSI sources for respective values (0xSf for auto)
    void setTexRS(TexInstruction *, unsigned int& s, int R, int S);
    void handleTEX(Value *dst0[4], int R, int S, int L, int C, int Dx, int Dy);
-   void handleTXF(Value *dst0[4], int R);
+   void handleTXF(Value *dst0[4], int R, int L_M);
    void handleTXQ(Value *dst0[4], enum TexQuery);
    void handleLIT(Value *dst0[4]);
    void handleUserClipPlanes();
@@ -1689,25 +1693,29 @@ Converter::handleTEX(Value *dst[4], int R, int S, int L, int C, int Dx, int Dy)
    bb->insertTail(texi);
 }
 
-// 1st source: xyz = coordinates, w = lod
+// 1st source: xyz = coordinates, w = lod/sample
 // 2nd source: offset
 void
-Converter::handleTXF(Value *dst[4], int R)
+Converter::handleTXF(Value *dst[4], int R, int L_M)
 {
    TexInstruction *texi = new_TexInstruction(func, tgsi.getOP());
+   int ms;
    unsigned int c, d, s;
 
    texi->tex.target = tgsi.getTexture(code, R);
 
+   ms = texi->tex.target.isMS() ? 1 : 0;
+   texi->tex.levelZero = ms; /* MS textures don't have mip-maps */
+
    for (c = 0, d = 0; c < 4; ++c) {
       if (dst[c]) {
          texi->setDef(d++, dst[c]);
          texi->tex.mask |= 1 << c;
       }
    }
-   for (c = 0; c < texi->tex.target.getArgCount(); ++c)
+   for (c = 0; c < (texi->tex.target.getArgCount() - ms); ++c)
       texi->setSrc(c, fetchSrc(0, c));
-   texi->setSrc(c++, fetchSrc(0, 3)); // lod
+   texi->setSrc(c++, fetchSrc(L_M >> 4, L_M & 3)); // lod or ms
 
    setTexRS(texi, c, R, -1);
 
@@ -2392,7 +2400,13 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
       handleTEX(dst0, 1, 2, 0x30, 0x30, 0x30, 0x40);
       break;
    case TGSI_OPCODE_TXF:
-      handleTXF(dst0, 1);
+      handleTXF(dst0, 1, 0x03);
+      break;
+   case TGSI_OPCODE_SAMPLE_I:
+      handleTXF(dst0, 1, 0x03);
+      break;
+   case TGSI_OPCODE_SAMPLE_I_MS:
+      handleTXF(dst0, 1, 0x20);
       break;
    case TGSI_OPCODE_TXQ:
    case TGSI_OPCODE_SVIEWINFO:
index 469d812098fe07a65eb75276961755de230479e8..6b924634f7c250688d2cd4b14d091f18f6bdca49 100644 (file)
@@ -62,6 +62,7 @@ nv50_miptree(struct pipe_resource *pt)
 
 #define NV50_TEXVIEW_SCALED_COORDS     (1 << 0)
 #define NV50_TEXVIEW_FILTER_MSAA8      (1 << 1)
+#define NV50_TEXVIEW_ACCESS_RESOLVE    (1 << 2)
 
 
 /* Internal functions:
index 5d0b31321a009f936c3d33c6f699f390ba11e81c..530832f1f78a06249edd9a5ac6d5fe6200891a48 100644 (file)
@@ -750,6 +750,7 @@ nv50_blit_set_src(struct nv50_blitctx *blit,
    }
 
    flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS;
+   flags |= NV50_TEXVIEW_ACCESS_RESOLVE;
    if (filter && res->nr_samples == 8)
       flags |= NV50_TEXVIEW_FILTER_MSAA8;
 
index c459d60759b33398d84aec7efbb5ffa00ec460bc..4d1d37281bc5be54ea8796ad346a943012c9c3db 100644 (file)
@@ -662,6 +662,7 @@ NVC0LoweringPass::handleTEX(TexInstruction *i)
 {
    const int dim = i->tex.target.getDim() + i->tex.target.isCube();
    const int arg = i->tex.target.getArgCount();
+   const int lyr = arg - (i->tex.target.isMS() ? 2 : 1);
 
    if (prog->getTarget()->getChipset() >= NVISA_GK104_CHIPSET) {
       if (i->tex.rIndirectSrc >= 0 || i->tex.sIndirectSrc >= 0) {
@@ -683,7 +684,7 @@ NVC0LoweringPass::handleTEX(TexInstruction *i)
       }
       if (i->tex.target.isArray()) {
          LValue *layer = new_LValue(func, FILE_GPR);
-         Value *src = i->getSrc(arg - 1);
+         Value *src = i->getSrc(lyr);
          const int sat = (i->op == OP_TXF) ? 1 : 0;
          DataType sTy = (i->op == OP_TXF) ? TYPE_U32 : TYPE_F32;
          bld.mkCvt(OP_CVT, TYPE_U16, layer, sTy, src)->saturate = sat;
@@ -696,7 +697,7 @@ NVC0LoweringPass::handleTEX(TexInstruction *i)
    if (dim != arg || i->tex.rIndirectSrc >= 0 || i->tex.sIndirectSrc >= 0) {
       LValue *src = new_LValue(func, FILE_GPR); // 0xttxsaaaa
 
-      Value *arrayIndex = i->tex.target.isArray() ? i->getSrc(arg - 1) : NULL;
+      Value *arrayIndex = i->tex.target.isArray() ? i->getSrc(lyr) : NULL;
       for (int s = dim; s >= 1; --s)
          i->setSrc(s, i->getSrc(s - 1));
       i->setSrc(0, arrayIndex);
index 12b890d9c0d7e810f6b5b50a399a96670faf0b8c..10baab5b335df8f238f12a733892d867331694db 100644 (file)
@@ -214,6 +214,10 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
    return ref;
 }
 
+static void
+nvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
+                                 float *);
+
 struct pipe_context *
 nvc0_create(struct pipe_screen *pscreen, void *priv)
 {
@@ -259,6 +263,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
 
    pipe->flush = nvc0_flush;
    pipe->texture_barrier = nvc0_texture_barrier;
+   pipe->get_sample_position = nvc0_context_get_sample_position;
 
    if (!screen->cur_ctx) {
       screen->cur_ctx = nvc0;
@@ -353,3 +358,44 @@ nvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx,
    }
    NOUVEAU_DRV_STAT(&nvc0->screen->base, resource_validate_count, count);
 }
+
+static void
+nvc0_context_get_sample_position(struct pipe_context *pipe,
+                                 unsigned sample_count, unsigned sample_index,
+                                 float *xy)
+{
+   static const uint8_t ms1[1][2] = { { 0x8, 0x8 } };
+   static const uint8_t ms2[2][2] = {
+      { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */
+   static const uint8_t ms4[4][2] = {
+      { 0x6, 0x2 }, { 0xe, 0x6 },   /* (0,0), (1,0) */
+      { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */
+   static const uint8_t ms8[8][2] = {
+      { 0x1, 0x7 }, { 0x5, 0x3 },   /* (0,0), (1,0) */
+      { 0x3, 0xd }, { 0x7, 0xb },   /* (0,1), (1,1) */
+      { 0x9, 0x5 }, { 0xf, 0x1 },   /* (2,0), (3,0) */
+      { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */
+#if 0
+   /* NOTE: there are alternative modes for MS2 and MS8, currently not used */
+   static const uint8_t ms8_alt[8][2] = {
+      { 0x9, 0x5 }, { 0x7, 0xb },   /* (2,0), (1,1) */
+      { 0xd, 0x9 }, { 0x5, 0x3 },   /* (3,1), (1,0) */
+      { 0x3, 0xd }, { 0x1, 0x7 },   /* (0,1), (0,0) */
+      { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */
+#endif
+
+   const uint8_t (*ptr)[2];
+
+   switch (sample_count) {
+   case 0:
+   case 1: ptr = ms1; break;
+   case 2: ptr = ms2; break;
+   case 4: ptr = ms4; break;
+   case 8: ptr = ms8; break;
+   default:
+      assert(0);
+      break;
+   }
+   xy[0] = ptr[sample_index][0] * 0.0625f;
+   xy[1] = ptr[sample_index][1] * 0.0625f;
+}
index 3d50735c058a999d3c446fdb18ed4314c5df0a0d..ec2ab5f38f97db611cafb2a703cbbb4c868912dc 100644 (file)
@@ -197,6 +197,8 @@ nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
     */
    d = mt->layout_3d ? pt->depth0 : 1;
 
+   assert(!mt->ms_mode || !pt->last_level);
+
    for (l = 0; l <= pt->last_level; ++l) {
       struct nv50_miptree_level *lvl = &mt->level[l];
       unsigned tsx, tsy, tsz;
index f2dd65ba0ca60b902622638feec70b16e425e568..ccdf2cde84bbca0d37d414b8fd266480f0435bab 100644 (file)
@@ -102,6 +102,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_SEAMLESS_CUBE_MAP:
    case PIPE_CAP_CUBE_MAP_ARRAY:
    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
+   case PIPE_CAP_TEXTURE_MULTISAMPLE:
       return 1;
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
@@ -170,7 +171,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
-   case PIPE_CAP_TEXTURE_MULTISAMPLE:
       return 0;
    case PIPE_CAP_COMPUTE:
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
index 4e8bb36e18ffc80bdd0fb70b2a60d89914da990a..394f196241c0292e68c519a7da813bc306be0260 100644 (file)
@@ -636,6 +636,7 @@ nvc0_blit_set_src(struct nvc0_blitctx *ctx,
    }
 
    flags = res->last_level ? 0 : NV50_TEXVIEW_SCALED_COORDS;
+   flags |= NV50_TEXVIEW_ACCESS_RESOLVE;
    if (filter && res->nr_samples == 8)
       flags |= NV50_TEXVIEW_FILTER_MSAA8;
 
index ffd285473a9ed5b8166553e07a23defab6ae532f..c11d3f791feb8c98aacb119702606d7b505bea18 100644 (file)
@@ -78,6 +78,7 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    uint64_t address;
    uint32_t *tic;
    uint32_t swz[4];
+   uint32_t width, height;
    uint32_t depth;
    struct nv50_tic_entry *view;
    struct nv50_miptree *mt;
@@ -168,7 +169,6 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    case PIPE_TEXTURE_1D:
       tic[2] |= NV50_TIC_2_TARGET_1D;
       break;
-/* case PIPE_TEXTURE_2D_MS: */
    case PIPE_TEXTURE_2D:
       tic[2] |= NV50_TIC_2_TARGET_2D;
       break;
@@ -185,7 +185,6 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    case PIPE_TEXTURE_1D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
       break;
-/* case PIPE_TEXTURE_2D_ARRAY_MS: */
    case PIPE_TEXTURE_2D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
       break;
@@ -194,30 +193,35 @@ nvc0_create_texture_view(struct pipe_context *pipe,
       tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
       break;
    default:
-      NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
+      NOUVEAU_ERR("unexpected/invalid texture target: %d\n",
+                  mt->base.base.target);
       return FALSE;
    }
 
-   if (mt->base.base.target == PIPE_BUFFER)
-      tic[3] = mt->base.base.width0;
-   else
-      tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
+   tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
+
+   if (flags & NV50_TEXVIEW_ACCESS_RESOLVE) {
+      width = mt->base.base.width0 << mt->ms_x;
+      height = mt->base.base.height0 << mt->ms_y;
+   } else {
+      width = mt->base.base.width0;
+      height = mt->base.base.height0;
+   }
 
-   tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
+   tic[4] = (1 << 31) | width;
 
-   tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
+   tic[5] = height & 0xffff;
    tic[5] |= depth << 16;
    tic[5] |= mt->base.base.last_level << 28;
 
-   tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
+   /* sampling points: (?) */
+   if (flags & NV50_TEXVIEW_ACCESS_RESOLVE)
+      tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000;
+   else
+      tic[6] = 0x03000000;
 
    tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
-
-   /*
-   if (mt->base.base.target == PIPE_TEXTURE_2D_MS ||
-       mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS)
-      tic[7] |= mt->ms_mode << 12;
-   */
+   tic[7] |= mt->ms_mode << 12;
 
    return &view->pipe;
 }