Mesa (master): nv50,nvc0: add support for cube map arrays

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Fri Dec 7 21:52:19 UTC 2012


Module: Mesa
Branch: master
Commit: f7599b2c32185535b4c215de0ba0454129fa523f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f7599b2c32185535b4c215de0ba0454129fa523f

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Fri Dec  7 22:47:40 2012 +0100

nv50,nvc0: add support for cube map arrays

NOTE: nv50 support not enabled, someone with nva3/8 please fix.

---

 src/gallium/drivers/nv50/codegen/nv50_ir.h         |    3 +-
 .../drivers/nv50/codegen/nv50_ir_build_util.cpp    |    1 +
 .../drivers/nv50/codegen/nv50_ir_emit_nv50.cpp     |   17 +++++++++
 .../drivers/nv50/codegen/nv50_ir_from_tgsi.cpp     |   27 +++++++++++++-
 src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h |    4 +-
 .../drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp |   39 ++++++++++----------
 src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp |    2 +-
 .../drivers/nv50/codegen/nv50_ir_target.cpp        |    4 +-
 src/gallium/drivers/nv50/nv50_blit.h               |    1 +
 src/gallium/drivers/nv50/nv50_screen.c             |    5 +++
 src/gallium/drivers/nv50/nv50_surface.c            |    1 +
 src/gallium/drivers/nv50/nv50_tex.c                |    9 +++--
 .../drivers/nvc0/codegen/nv50_ir_emit_gk110.cpp    |    1 -
 .../drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp     |    1 -
 src/gallium/drivers/nvc0/nvc0_screen.c             |    1 +
 src/gallium/drivers/nvc0/nvc0_tex.c                |    9 +++--
 16 files changed, 88 insertions(+), 37 deletions(-)

diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir.h b/src/gallium/drivers/nv50/codegen/nv50_ir.h
index 0b47c32..b951b9d 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir.h
@@ -124,7 +124,7 @@ enum operation
    OP_DFDY,
    OP_RDSV, // read system value
    OP_WRSV, // write system value
-   OP_PIXLD,
+   OP_TEXPREP, // turn cube map array into 2d array coordinates, TODO: move
    OP_QUADOP,
    OP_QUADON,
    OP_QUADPOP,
@@ -750,6 +750,7 @@ public:
       Target& operator=(TexTarget targ)
       {
          assert(targ < TEX_TARGET_COUNT);
+         target = targ;
          return *this;
       }
 
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
index f713e63..322d6b9 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_build_util.cpp
@@ -254,6 +254,7 @@ BuildUtil::mkTex(operation op, TexTarget targ, uint8_t tic, uint8_t tsc,
 
    tex->setTexture(targ, tic, tsc);
 
+   insert(tex);
    return tex;
 }
 
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_emit_nv50.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_emit_nv50.cpp
index 90ec9d0..2ba87f3 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_emit_nv50.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_emit_nv50.cpp
@@ -116,6 +116,7 @@ private:
 
    void emitTEX(const TexInstruction *);
    void emitTXQ(const TexInstruction *);
+   void emitTEXPREP(const TexInstruction *);
 
    void emitQUADOP(const Instruction *, uint8_t lane, uint8_t quOp);
 
@@ -1430,6 +1431,19 @@ CodeEmitterNV50::emitTXQ(const TexInstruction *i)
 }
 
 void
+CodeEmitterNV50::emitTEXPREP(const TexInstruction *i)
+{
+   code[0] = 0xf8000001 | (3 << 22) | (i->tex.s << 17) | (i->tex.r << 9);
+   code[1] = 0x60010000;
+
+   code[0] |= (i->tex.mask & 0x3) << 25;
+   code[1] |= (i->tex.mask & 0xc) << 12;
+   defId(i->def(0), 2);
+
+   emitFlagsRd(i);
+}
+
+void
 CodeEmitterNV50::emitPRERETEmu(const FlowInstruction *i)
 {
    uint32_t pos = i->target.bb->binPos + 8; // +8 to skip an op */
@@ -1652,6 +1666,9 @@ CodeEmitterNV50::emitInstruction(Instruction *insn)
    case OP_TXQ:
       emitTXQ(insn->asTex());
       break;
+   case OP_TEXPREP:
+      emitTEXPREP(insn->asTex());
+      break;
    case OP_EMIT:
    case OP_RESTART:
       emitOUT(insn);
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
index e73c804..cf483d0 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_from_tgsi.cpp
@@ -237,6 +237,10 @@ unsigned int Instruction::srcMask(unsigned int s) const
       return 0x1;
    case TGSI_OPCODE_LIT:
       return 0xb;
+   case TGSI_OPCODE_TEX2:
+   case TGSI_OPCODE_TXB2:
+   case TGSI_OPCODE_TXL2:
+      return (s == 0) ? 0xf : 0x3;
    case TGSI_OPCODE_TEX:
    case TGSI_OPCODE_TXB:
    case TGSI_OPCODE_TXD:
@@ -264,6 +268,12 @@ unsigned int Instruction::srcMask(unsigned int s) const
       case TGSI_TEXTURE_RECT:
          mask &= 0xb;
          break;
+      case TGSI_TEXTURE_CUBE_ARRAY:
+      case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      case TGSI_TEXTURE_SHADOWCUBE:
+      case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+         mask |= 0x8;
+         break;
       default:
          break;
       }
@@ -343,12 +353,14 @@ static nv50_ir::TexTarget translateTexture(uint tex)
    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(CUBE_ARRAY, CUBE_ARRAY);
    NV50_IR_TEX_TARG_CASE(SHADOW1D, 1D_SHADOW);
    NV50_IR_TEX_TARG_CASE(SHADOW2D, 2D_SHADOW);
-   NV50_IR_TEX_TARG_CASE(SHADOW1D_ARRAY, 1D_ARRAY_SHADOW);
-   NV50_IR_TEX_TARG_CASE(SHADOW2D_ARRAY, 2D_ARRAY_SHADOW);
    NV50_IR_TEX_TARG_CASE(SHADOWCUBE, CUBE_SHADOW);
    NV50_IR_TEX_TARG_CASE(SHADOWRECT, RECT_SHADOW);
+   NV50_IR_TEX_TARG_CASE(SHADOW1D_ARRAY, 1D_ARRAY_SHADOW);
+   NV50_IR_TEX_TARG_CASE(SHADOW2D_ARRAY, 2D_ARRAY_SHADOW);
+   NV50_IR_TEX_TARG_CASE(SHADOWCUBE_ARRAY, CUBE_ARRAY_SHADOW);
    NV50_IR_TEX_TARG_CASE(BUFFER, BUFFER);
 
    case TGSI_TEXTURE_UNKNOWN:
@@ -553,6 +565,10 @@ static nv50_ir::operation translateOpcode(uint opcode)
    NV50_IR_OPCODE_CASE(GATHER4, TXG);
    NV50_IR_OPCODE_CASE(SVIEWINFO, TXQ);
 
+   NV50_IR_OPCODE_CASE(TEX2, TEX);
+   NV50_IR_OPCODE_CASE(TXB2, TXB);
+   NV50_IR_OPCODE_CASE(TXL2, TXL);
+
    NV50_IR_OPCODE_CASE(END, EXIT);
 
    default:
@@ -2034,6 +2050,13 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
    case TGSI_OPCODE_TXD:
       handleTEX(dst0, 3, 3, 0x03, 0x0f, 0x10, 0x20);
       break;
+   case TGSI_OPCODE_TEX2:
+      handleTEX(dst0, 2, 2, 0x03, 0x10, 0x00, 0x00);
+      break;
+   case TGSI_OPCODE_TXB2:
+   case TGSI_OPCODE_TXL2:
+      handleTEX(dst0, 2, 2, 0x10, 0x11, 0x00, 0x00);
+      break;
    case TGSI_OPCODE_SAMPLE:
    case TGSI_OPCODE_SAMPLE_B:
    case TGSI_OPCODE_SAMPLE_D:
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h b/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h
index 55a3332..40241b1 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_inlines.h
@@ -43,7 +43,7 @@ static inline bool isMemoryFile(DataFile f)
 // contrary to asTex(), this will never include SULD/SUST
 static inline bool isTextureOp(operation op)
 {
-   return (op >= OP_TEX && op <= OP_TEXCSAA);
+   return (op >= OP_TEX && op <= OP_TEXCSAA) || (op == OP_TEXPREP);
 }
 
 static inline unsigned int typeSizeof(DataType ty)
@@ -304,7 +304,7 @@ const FlowInstruction *Instruction::asFlow() const
 
 TexInstruction *Instruction::asTex()
 {
-   if (op >= OP_TEX && op <= OP_TEXCSAA)
+   if ((op >= OP_TEX && op <= OP_TEXCSAA) || (op == OP_TEXPREP))
       return static_cast<TexInstruction *>(this);
    return NULL;
 }
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp
index 3e0dc75..db13061 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_lowering_nv50.cpp
@@ -573,7 +573,6 @@ NV50LoweringPreSSA::visit(Function *f)
    return true;
 }
 
-// move array source to first slot, convert to u16, add indirections
 bool
 NV50LoweringPreSSA::handleTEX(TexInstruction *i)
 {
@@ -595,24 +594,26 @@ NV50LoweringPreSSA::handleTEX(TexInstruction *i)
       i->setSrc(arg - 1, src);
 
       if (i->tex.target.isCube()) {
-         // Value *face = layer;
-         Value *x, *y;
-         x = new_LValue(func, FILE_GPR);
-         y = new_LValue(func, FILE_GPR);
-         layer = new_LValue(func, FILE_GPR);
-
-         i->tex.target = TEX_TARGET_2D_ARRAY;
-
-         // TODO: use TEXPREP to convert x,y,z,face -> x,y,layer
-         bld.mkMov(x, i->getSrc(0));
-         bld.mkMov(y, i->getSrc(1));
-         bld.mkMov(layer, i->getSrc(3));
-
-         i->setSrc(0, x);
-         i->setSrc(1, y);
-         i->setSrc(2, layer);
-         i->setSrc(3, i->getSrc(4));
-         i->setSrc(4, NULL);
+         Value *acube[4], *a2d[4];
+         int c;
+
+         for (c = 0; c < 4; ++c)
+            acube[c] = i->getSrc(c);
+         for (c = 0; c < 3; ++c)
+            a2d[c] = new_LValue(func, FILE_GPR);
+         a2d[3] = NULL;
+
+         bld.mkTex(OP_TEXPREP, TEX_TARGET_CUBE_ARRAY, i->tex.r, i->tex.s,
+                   a2d, acube)->asTex()->tex.mask = 0x7;
+
+         for (c = 0; c < 3; ++c)
+            i->setSrc(c, a2d[c]);
+         i->setSrc(c, NULL);
+         for (; i->srcExists(c + 1); ++c)
+            i->setSrc(c, i->getSrc(c + 1));
+
+         i->tex.target = i->tex.target.isShadow() ?
+            TEX_TARGET_2D_ARRAY_SHADOW : TEX_TARGET_2D_ARRAY;
       }
    }
 
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp
index ded4f61..d27a10c 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_print.cpp
@@ -174,7 +174,7 @@ const char *operationStr[OP_LAST + 1] =
    "dfdy",
    "rdsv",
    "wrsv",
-   "pixld",
+   "texprep",
    "quadop",
    "quadon",
    "quadpop",
diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp
index 707c9e8..be6a276 100644
--- a/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp
+++ b/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp
@@ -47,7 +47,7 @@ const uint8_t Target::operationSrcNr[OP_LAST + 1] =
    1, 1, 1, 1, 1,          // TXF, TXQ, TXD, TXG, TEXCSAA
    1, 2,                   // SULD, SUST
    1, 1,                   // DFDX, DFDY
-   1, 2, 2, 2, 0, 0,       // RDSV, WRSV, PIXLD, QUADOP, QUADON, QUADPOP
+   1, 2, 2, 2, 0, 0,       // RDSV, WRSV, TEXPREP, QUADOP, QUADON, QUADPOP
    2, 3, 2, 0,             // POPCNT, INSBF, EXTBF, TEXBAR
    0
 };
@@ -101,7 +101,7 @@ const OpClass Target::operationClass[OP_LAST + 1] =
    OPCLASS_TEXTURE, OPCLASS_TEXTURE, OPCLASS_TEXTURE, OPCLASS_TEXTURE,
    // SULD, SUST
    OPCLASS_SURFACE, OPCLASS_SURFACE,
-   // DFDX, DFDY, RDSV, WRSV; PIXLD, QUADOP, QUADON, QUADPOP
+   // DFDX, DFDY, RDSV, WRSV; TEXPREP, QUADOP, QUADON, QUADPOP
    OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER,
    OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER, OPCLASS_OTHER,
    // POPCNT, INSBF, EXTBF
diff --git a/src/gallium/drivers/nv50/nv50_blit.h b/src/gallium/drivers/nv50/nv50_blit.h
index 0a1c2ae..d409f21 100644
--- a/src/gallium/drivers/nv50/nv50_blit.h
+++ b/src/gallium/drivers/nv50/nv50_blit.h
@@ -72,6 +72,7 @@ nv50_blit_reinterpret_pipe_texture_target(enum pipe_texture_target target)
 {
    switch (target) {
    case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_CUBE_ARRAY:
       return PIPE_TEXTURE_2D_ARRAY;
    case PIPE_TEXTURE_RECT:
       return PIPE_TEXTURE_2D;
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index d0a0295..2d6d4d6 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -111,6 +111,11 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS;
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
       return 0;
+   case PIPE_CAP_CUBE_MAP_ARRAY:
+      return 0;
+      /*
+      return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS;
+      */
    case PIPE_CAP_TWO_SIDED_STENCIL:
    case PIPE_CAP_DEPTH_CLIP_DISABLE:
    case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 511ee8f..d9722a8 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -959,6 +959,7 @@ nv50_blit_3d(struct nv50_context *nv50, const struct pipe_blit_info *info)
       y1 /= fv;
    }
 
+   /* XXX: multiply by 6 for cube arrays ? */
    dz = (float)info->src.box.depth / (float)info->dst.box.depth;
    z = (float)info->src.box.z;
    if (nv50_miptree(src)->layout_3d)
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
index 992ac4b..dfc97a2 100644
--- a/src/gallium/drivers/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -176,10 +176,7 @@ nv50_create_texture_view(struct pipe_context *pipe,
       break;
    case PIPE_TEXTURE_CUBE:
       depth /= 6;
-      if (depth > 1)
-         tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
-      else
-         tic[2] |= NV50_TIC_2_TARGET_CUBE;
+      tic[2] |= NV50_TIC_2_TARGET_CUBE;
       break;
    case PIPE_TEXTURE_1D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
@@ -187,6 +184,10 @@ nv50_create_texture_view(struct pipe_context *pipe,
    case PIPE_TEXTURE_2D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
       break;
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      depth /= 6;
+      tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
+      break;
    case PIPE_BUFFER:
       assert(0); /* should be linear and handled above ! */
       tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR;
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_gk110.cpp
index 6c229fd..c771459 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_gk110.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_gk110.cpp
@@ -110,7 +110,6 @@ private:
    void emitTEX(const TexInstruction *);
    void emitTEXCSAA(const TexInstruction *);
    void emitTXQ(const TexInstruction *);
-   void emitPIXLD(const TexInstruction *);
 
    void emitQUADOP(const Instruction *, uint8_t qOp, uint8_t laneMask);
 
diff --git a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
index cd04f4c..92496a3 100644
--- a/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
+++ b/src/gallium/drivers/nvc0/codegen/nv50_ir_emit_nvc0.cpp
@@ -110,7 +110,6 @@ private:
    void emitTEX(const TexInstruction *);
    void emitTEXCSAA(const TexInstruction *);
    void emitTXQ(const TexInstruction *);
-   void emitPIXLD(const TexInstruction *);
 
    void emitQUADOP(const Instruction *, uint8_t qOp, uint8_t laneMask);
 
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 3bf2191..08fc3b4 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -88,6 +88,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_NPOT_TEXTURES:
    case PIPE_CAP_ANISOTROPIC_FILTER:
    case PIPE_CAP_SEAMLESS_CUBE_MAP:
+   case PIPE_CAP_CUBE_MAP_ARRAY:
       return 1;
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c
index b52918e..2bce97b 100644
--- a/src/gallium/drivers/nvc0/nvc0_tex.c
+++ b/src/gallium/drivers/nvc0/nvc0_tex.c
@@ -180,10 +180,7 @@ nvc0_create_texture_view(struct pipe_context *pipe,
       break;
    case PIPE_TEXTURE_CUBE:
       depth /= 6;
-      if (depth > 1)
-         tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
-      else
-         tic[2] |= NV50_TIC_2_TARGET_CUBE;
+      tic[2] |= NV50_TIC_2_TARGET_CUBE;
       break;
    case PIPE_TEXTURE_1D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY;
@@ -192,6 +189,10 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    case PIPE_TEXTURE_2D_ARRAY:
       tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY;
       break;
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      depth /= 6;
+      tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY;
+      break;
    default:
       NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target);
       return FALSE;




More information about the mesa-commit mailing list