-
Notifications
You must be signed in to change notification settings - Fork 6
Exemplary AMP code
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();