Skip to content
Ethatron edited this page Jun 6, 2012 · 4 revisions

Taken out from DDSopt. texo/texd are D3DSURFACE_DESC, texs/texr are raw pointer to the mip-level, blocksize is the number of ULONGs for the requested coding. The code is so complex, it likely refuses to compile a coded switch for all the formats in your life-time, so just do a function per compression-method; and don't make the flags variable, it'll add unnessessary checks in the inner kernel, better permute the kernal over all options you want to offer, having a seperate kernal for each case.

int iwidth  = texo.Width;
int iheight = texo.Height;
int owidth  = texd.Width;
int oheight = texd.Height;
int cwidth  = owidth;
int cheight = oheight;

cheight = (cheight + 3) / 4;        /* 4x4 LONG ... */
cwidth  = (cwidth  + 3) / 4;        /* 4x4 LONG ... */
cwidth *= 2 * blocksize;            /* ... to 2x|4x LONG */

/* ensure tile ability (bit on overhead for non-4 resolutions) */
owidth  = (owidth  + (TX - 1)) & (~(TX - 1));
oheight = (oheight + (TY - 1)) & (~(TY - 1));

assert((owidth  & (TX - 1)) == 0);
assert((oheight & (TY - 1)) == 0);

/* constant buffer array */
Concurrency::array_view<const SingleColourLookup_CCR, 2> lArr(2, 256,
                       (const SingleColourLookup_CCR *)::lookup_34_56_ccr);
Concurrency::array_view<const   IndexBlockLookup_CCR, 2> yArr(4, 8,
                       (const   IndexBlockLookup_CCR *)::lookup_c34a57_ccr);

/* get a two-dimensional extend over the whole output (without re-cast to LONG),
 * then get a tile-extend over that one ()
 */
Concurrency::extent<2> ee(oheight, owidth);
Concurrency::tiled_extent<TY, TX> te(ee);

Concurrency::array_view<const unsigned int, 2> sArr(iheight, iwidth, (const unsigned int *)texs);
Concurrency::array_view<      unsigned int, 2> dArr(cheight, cwidth, (      unsigned int *)texr);

Concurrency::parallel_for_each(te, [=](tiled_index<TY, TX> elm) restrict(amp) {
  tile_static int iTex[TY*TX][DIM];

  /* generate this level's 4x4-block from the original surface */
  const int y = elm.tile[0] * TY;
  const int x = elm.tile[1] * TX;
  const int ly = elm.local[0];
  const int lx = elm.local[1];
  const int lxy = ly * TX + lx;

  const ULONG &t = sArr(posy, posx);
  
  iTex[lxy][0] = (t >> 24) & 0xFF;
  iTex[lxy][1] = (t >> 16) & 0xFF;
  iTex[lxy][2] = (t >>  8) & 0xFF;
  iTex[lxy][3] = (t >>  0) & 0xFF;

  tile_static_memory_fence(elm.barrier);

  /* put this level's 4x4-block into the destination surface */
  {
    /* round down */
    int posx = (x + lx) >> 2;
    int posy = (y + ly) >> 2;

    /* first and second block */
    unsigned int b[2][2];

    /* compress to DXT1/DXT3/DXT5/ATI1/ATI2 */

#define sflgs SQUISH_METRIC_PERCEPTUAL
true,
SQUISH_FIT_RANGE

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /* 1x LONG per block for DXT1, 2x for the others */

#if (coding == 1) { posx <<= 0; squish::CompressColorDxt1(elm.barrier, lxy, iTex, 0xFFFF, b[1], sflgs, yArr, lArr);

      if (elm.local == index<2>(0, 0)) {
        dArr(posy, posx + 0) = b[1][0];
        dArr(posy, posx + 1) = b[1][1];
      }
    }

#elif (coding == 2) { posx <<= 1; squish::CompressAlphaDxt3(elm.barrier, lxy, iTex, 0xFFFF, b[0] , yArr ); squish::CompressColorDxt3(elm.barrier, lxy, iTex, 0xFFFF, b[1], sflgs, yArr, lArr);

      if (elm.local == index<2>(0, 0)) {
        dArr(posy, posx + 0) = b[0][0];
        dArr(posy, posx + 1) = b[0][1];
        dArr(posy, posx + 2) = b[1][0];
        dArr(posy, posx + 3) = b[1][1];
      }
    }

#elif (coding == 3) { posx <<= 1; squish::CompressAlphaDxt5(elm.barrier, lxy, iTex, 0xFFFF, b[0] , yArr ); squish::CompressColorDxt5(elm.barrier, lxy, iTex, 0xFFFF, b[1], sflgs, yArr, lArr);

      if (elm.local == index<2>(0, 0)) {
        dArr(posy, posx + 0) = b[0][0];
        dArr(posy, posx + 1) = b[0][1];
        dArr(posy, posx + 2) = b[1][0];
        dArr(posy, posx + 3) = b[1][1];
      }
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - */
    /* 2x LONG for ATI2 */

#elif (coding == 4) { posx <<= 1; squish::CompressAlphaDxt5(elm.barrier, lxy, iTex, 0xFFFF, b[0] , yArr ); squish::CompressAlphaDxt5(elm.barrier, lxy, iTex, 0xFFFF, b[1] , yArr );

      if (elm.local == index<2>(0, 0)) {
        dArr(posy, posx + 0) = b[0][0];
        dArr(posy, posx + 1) = b[0][1];
        dArr(posy, posx + 2) = b[1][0];
        dArr(posy, posx + 3) = b[1][1];  
      }
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - */
    /* 1x LONG for ATI1 */

#elif (coding == 5) { posx <<= 0; squish::CompressAlphaDxt5(elm.barrier, lxy, iTex, 0xFFFF, b[0] , yArr );

      if (elm.local == index<2>(0, 0)) {
        dArr(posy, posx + 0) = b[0][0];
        dArr(posy, posx + 1) = b[0][1];
      }
    }

#endif

#undef sflgs }

});

dArr.synchronize();

Clone this wiki locally