CodecError CCodec_GT::Compress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, DWORD_PTR pUser1, DWORD_PTR pUser2) { assert(bufferIn.GetWidth() == bufferOut.GetWidth()); assert(bufferIn.GetHeight() == bufferOut.GetHeight()); if(bufferIn.GetWidth() != bufferOut.GetWidth() || bufferIn.GetHeight() != bufferOut.GetHeight()) return CE_Unknown; CodecError err = InitializeGTLibrary(); if (err != CE_OK) return err; #ifdef GT_COMPDEBUGGER CompViewerClient g_CompClient; if (g_CompClient.connect()) { #ifdef USE_DBGTRACE DbgTrace(("-------> Remote Server Connected")); #endif } #endif const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + 3) >> 2); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight() + 3) >> 2); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; #ifdef USE_DBGTRACE DbgTrace(("IN : BufferType %d ChannelCount %d ChannelDepth %d",bufferIn.GetBufferType(),bufferIn.GetChannelCount(),bufferIn.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d",bufferIn.GetHeight(),bufferIn.GetWidth(),bufferIn.GetWidth(),bufferIn.IsFloat())); DbgTrace(("OUT: BufferType %d ChannelCount %d ChannelDepth %d",bufferOut.GetBufferType(),bufferOut.GetChannelCount(),bufferOut.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d",bufferOut.GetHeight(),bufferOut.GetWidth(),bufferOut.GetWidth(),bufferOut.IsFloat())); #endif; char row,col,srcIndex; CMP_BYTE *pOutBuffer; pOutBuffer = bufferOut.GetData(); CMP_BYTE* pInBuffer; pInBuffer = bufferIn.GetData(); DWORD block = 0; for(CMP_DWORD j = 0; j < dwBlocksY; j++) { for(CMP_DWORD i = 0; i < dwBlocksX; i++) { BYTE blockToEncode[BLOCK_SIZE_4X4][CHANNEL_SIZE_ARGB]; CMP_BYTE srcBlock[BLOCK_SIZE_4X4X4]; memset(srcBlock,0,sizeof(srcBlock)); bufferIn.ReadBlockRGBA(i*4, j*4, 4, 4, srcBlock); #ifdef GT_COMPDEBUGGER g_CompClient.SendData(1,sizeof(srcBlock),srcBlock); #endif // Create the block for encoding srcIndex = 0; for(row=0; row < BLOCK_SIZE_4; row++) { for(col=0; col < BLOCK_SIZE_4; col++) { blockToEncode[row*BLOCK_SIZE_4+col][BC_COMP_RED] = srcBlock[srcIndex]; blockToEncode[row*BLOCK_SIZE_4+col][BC_COMP_GREEN] = srcBlock[srcIndex+1]; blockToEncode[row*BLOCK_SIZE_4+col][BC_COMP_BLUE] = srcBlock[srcIndex+2]; blockToEncode[row*BLOCK_SIZE_4+col][BC_COMP_ALPHA] = srcBlock[srcIndex+3]; srcIndex+=4; } } EncodeGTBlock(blockToEncode,pOutBuffer+block); block += 16; #ifdef GT_COMPDEBUGGER // Checks decompression it should match or be close to source union BBLOCKS { CMP_DWORD compressedBlock[4]; BYTE out[16]; BYTE in[16]; } data; memset(data.in,0,sizeof(data)); union DBLOCKS { double blockToSave[16][4]; double block[64]; } savedata; CMP_BYTE destBlock[BLOCK_SIZE_4X4X4]; memset(savedata.block,0,sizeof(savedata)); m_decoder->DecompressBlock(savedata.blockToSave,data.in); for (row=0; row<64; row++) { destBlock[row] = (BYTE)savedata.block[row]; } g_CompClient.SendData(3,sizeof(destBlock),destBlock); #endif } if(pFeedbackProc) { float fProgress = 100.f * (j * dwBlocksX) / dwBlocksXY; if(pFeedbackProc(fProgress, pUser1, pUser2)) { #ifdef GT_COMPDEBUGGER g_CompClient.disconnect(); #endif FinishGTEncoding(); return CE_Aborted; } } } #ifdef GT_COMPDEBUGGER g_CompClient.disconnect(); #endif return FinishGTEncoding(); }
CodecError CCodec_ASTC::Compress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2) { m_AbortRequested = false; int xsize = bufferIn.GetWidth(); int ysize = bufferIn.GetHeight(); int zsize = 1; //todo: add depth to support 3d textures m_xdim = bufferOut.GetBlockWidth(); m_ydim = bufferOut.GetBlockHeight(); m_zdim = 1; CodecError err = InitializeASTCLibrary(); if (err != CE_OK) return err; #ifdef ASTC_COMPDEBUGGER CompViewerClient g_CompClient; if (g_CompClient.connect()) { #ifdef USE_DBGTRACE DbgTrace(("-------> Remote Server Connected")); #endif } #endif #ifdef USE_DBGTRACE DbgTrace(("IN : BufferType %d ChannelCount %d ChannelDepth %d", bufferIn.GetBufferType(), bufferIn.GetChannelCount(), bufferIn.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d", bufferIn.GetHeight(), bufferIn.GetWidth(), bufferIn.GetWidth(), bufferIn.IsFloat())); DbgTrace(("OUT: BufferType %d ChannelCount %d ChannelDepth %d", bufferOut.GetBufferType(), bufferOut.GetChannelCount(), bufferOut.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d", bufferOut.GetHeight(), bufferOut.GetWidth(), bufferOut.GetWidth(), bufferOut.IsFloat())); #endif; int bitness = 0; //todo: replace astc_codec_image with bufferIn and rewrite fetch_imageblock() switch (bufferIn.GetBufferType()) { case CBT_RGBA8888: case CBT_BGRA8888: case CBT_ARGB8888: case CBT_RGB888: case CBT_RG8: case CBT_R8: bitness = 8; break; case CBT_RGBA2101010: break; case CBT_RGBA16: case CBT_RG16: case CBT_R16: break; case CBT_RGBA32: case CBT_RG32: case CBT_R32: break; case CBT_RGBA16F: case CBT_RG16F: case CBT_R16F: break; case CBT_RGBA32F: case CBT_RG32F: case CBT_R32F: break; default: break; } if (bitness != 8) assert("Unsupported type of input buffer"); astc_codec_image_cpu *input_image = allocate_image_cpu(bitness, xsize, ysize, zsize, 0); if (!input_image) assert("Unable to allocate image buffer"); // Loop through the original input image and setup compression threads for each // block to encode we will load the buffer to pass to ASTC code as 8 bit 4x4 blocks // the fill in source image. ASTC code will then use the adaptive sizes for process on the input BYTE *pData = bufferIn.GetData(); int ii = 0; for (int y = 0; y < ysize; y++) { for (int x = 0; x < xsize; x++) { input_image->imagedata8[0][y][4*x ] = pData[ii]; // Red ii++; input_image->imagedata8[0][y][4 * x + 1] = pData[ii]; // Green ii++; input_image->imagedata8[0][y][4 * x + 2] = pData[ii]; // Blue ii++; input_image->imagedata8[0][y][4 * x + 3] = pData[ii]; // Alpha ii++; } } m_NumEncodingThreads = min(m_NumThreads, (decltype(m_NumThreads))MAX_ASTC_THREADS); if (m_NumEncodingThreads == 0) m_NumEncodingThreads = 1; // Common ARM and AMD Code CodecError result = CE_OK; int xdim = m_xdim; int ydim = m_ydim; int zdim = m_zdim; uint8_t *bufferOutput = bufferOut.GetData(); // Common ARM and Compressonator Code int x, y, z, i; int xblocks = (xsize + xdim - 1) / xdim; int yblocks = (ysize + ydim - 1) / ydim; int zblocks = (zsize + zdim - 1) / zdim; float TotalBlocks = (float) (yblocks * xblocks); int processingBlock = 0; for (z = 0; z < zblocks; z++) { for (y = 0; y < yblocks; y++) { for (x = 0; x < xblocks; x++) { int offset = ((z * yblocks + y) * xblocks + x) * 16; uint8_t *bp = bufferOutput + offset; EncodeASTCBlock((astc_codec_image *)input_image, bp, xdim, ydim, zdim, x * xdim, y * ydim, z * zdim); processingBlock++; } if (pFeedbackProc) { float fProgress = 100.f * ((float)(processingBlock) / TotalBlocks); if (pFeedbackProc(fProgress, pUser1, pUser2)) { result = CE_Aborted; break; } } } } CodecError EncodeResult = FinishASTCEncoding(); if (result != CE_Aborted) result = EncodeResult; destroy_image_cpu(input_image); #ifdef ASTC_COMPDEBUGGER g_CompClient.disconnect(); #endif return result; }
// notes: // Slow CPU based decompression : Should look into also using HW based decompression with this interface // CodecError CCodec_ASTC::Decompress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, CMP_DWORD_PTR pUser1, CMP_DWORD_PTR pUser2) { m_xdim = bufferIn.GetBlockWidth(); m_ydim = bufferIn.GetBlockHeight(); m_zdim = 1; CodecError err = InitializeASTCLibrary(); if (err != CE_OK) return err; // Our Compressed data Blocks are always 128 bit long (4x4 blocks) const CMP_DWORD imageWidth = bufferIn.GetWidth(); const CMP_DWORD imageHeight = bufferIn.GetHeight(); const CMP_DWORD imageDepth = 1; const BYTE bitness = 8; const CMP_DWORD CompBlockX = bufferIn.GetBlockWidth(); const CMP_DWORD CompBlockY = bufferIn.GetBlockHeight(); CMP_BYTE Block_Width = bufferIn.GetBlockWidth(); CMP_BYTE Block_Height = bufferIn.GetBlockHeight(); const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + (CompBlockX - 1)) / CompBlockX); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight()+ (CompBlockY - 1)) / CompBlockY); const CMP_DWORD dwBlocksZ = 1; const CMP_DWORD dwBufferInDepth = 1; // Override the current input buffer Pitch size (Since it will be set according to the Compressed Block Sizes // and not to the Compressed Codec data which is for ASTC 16 Bytes per block x Number of blocks per row bufferIn.SetPitch(16 * dwBlocksX); // Output data size Pitch CMP_DWORD dwPitch = bufferOut.GetPitch(); // Output Buffer BYTE *pDataOut = bufferOut.GetData(); const CMP_DWORD dwBlocksXY = dwBlocksX*dwBlocksY; for(CMP_DWORD cmpRowY = 0; cmpRowY < dwBlocksY; cmpRowY++) // Compressed images row = height { for(CMP_DWORD cmpColX = 0; cmpColX < dwBlocksX; cmpColX++) // Compressed images Col = width { union FBLOCKS { float decodedBlock[144][4]; // max 12x12 block size float destBlock[576]; // max 12x12x4 } DecData; union BBLOCKS { CMP_DWORD compressedBlock[4]; BYTE out[16]; BYTE in[16]; } CompData; bufferIn.ReadBlock(cmpColX*4, cmpRowY*4, CompData.compressedBlock, 4); // Encode to the appropriate location in the compressed image m_decoder->DecompressBlock(Block_Width, Block_Height, bitness, DecData.decodedBlock,CompData.in); // Now that we have a decoded block lets copy that data over to the target image buffer CMP_DWORD outCol = cmpColX*Block_Width; CMP_DWORD outRow = cmpRowY*Block_Height; CMP_DWORD outImgRow = outRow; CMP_DWORD outImgCol = outCol; for (int row = 0; row < Block_Height; row++) { CMP_DWORD nextRowCol = (outRow+row)*dwPitch + (outCol * 4); CMP_BYTE* pData = (CMP_BYTE*)(pDataOut + nextRowCol); if ((outImgRow + row) < imageHeight) { outImgCol = outCol; for (int col = 0; col < Block_Width; col++) { CMP_DWORD w = outImgCol + col; if (w < imageWidth) { int index = row*Block_Width + col; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_RED]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_GREEN]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_BLUE]; *pData++ = (CMP_BYTE)DecData.decodedBlock[index][BC_COMP_ALPHA]; } else break; } } } } if (pFeedbackProc) { float fProgress = 100.f * (cmpRowY * dwBlocksX) / dwBlocksXY; if (pFeedbackProc(fProgress, pUser1, pUser2)) { return CE_Aborted; } } } return CE_OK; }
CodecError CCodec_BC6H::Compress(CCodecBuffer& bufferIn, CCodecBuffer& bufferOut, Codec_Feedback_Proc pFeedbackProc, DWORD_PTR pUser1, DWORD_PTR pUser2) { assert(bufferIn.GetWidth() == bufferOut.GetWidth()); assert(bufferIn.GetHeight() == bufferOut.GetHeight()); if(bufferIn.GetWidth() != bufferOut.GetWidth() || bufferIn.GetHeight() != bufferOut.GetHeight()) return CE_Unknown; CodecError err = CInitializeBC6HLibrary(); if (err != CE_OK) return err; #ifdef BC6H_COMPDEBUGGER CompViewerClient g_CompClient; if (g_CompClient.connect()) { #ifdef USE_DBGTRACE DbgTrace(("-------> Remote Server Connected")); #endif } #endif #ifdef BC6H_DEBUG_TO_RESULTS_TXT g_fp = fopen("AMD_Results.txt","w"); g_block = 0; #endif const CMP_DWORD dwBlocksX = ((bufferIn.GetWidth() + 3) >> 2); const CMP_DWORD dwBlocksY = ((bufferIn.GetHeight() + 3) >> 2); #ifdef _REMOTE_DEBUG DbgTrace(("IN : BufferType %d ChannelCount %d ChannelDepth %d",bufferIn.GetBufferType(),bufferIn.GetChannelCount(),bufferIn.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d",bufferIn.GetHeight(),bufferIn.GetWidth(),bufferIn.GetWidth(),bufferIn.IsFloat())); DbgTrace(("OUT: BufferType %d ChannelCount %d ChannelDepth %d",bufferOut.GetBufferType(),bufferOut.GetChannelCount(),bufferOut.GetChannelDepth())); DbgTrace((" : Height %d Width %d Pitch %d isFloat %d",bufferOut.GetHeight(),bufferOut.GetWidth(),bufferOut.GetWidth(),bufferOut.IsFloat())); #endif; char row,col,srcIndex; CMP_BYTE *pOutBuffer; pOutBuffer = bufferOut.GetData(); CMP_BYTE* pInBuffer; pInBuffer = bufferIn.GetData(); DWORD block = 0; #ifdef _SAVE_AS_BC6 FILE *bc6file = fopen("Test.bc6", "wb"); #endif for(CMP_DWORD j = 0; j < dwBlocksY; j++) { for(CMP_DWORD i = 0; i < dwBlocksX; i++) { float blockToEncode[BLOCK_SIZE_4X4][CHANNEL_SIZE_ARGB]; CMP_FLOAT srcBlock[BLOCK_SIZE_4X4X4]; memset(srcBlock,0,sizeof(srcBlock)); bufferIn.ReadBlockRGBA(i*4, j*4, 4, 4, srcBlock); #ifdef _BC6H_COMPDEBUGGER g_CompClient.SendData(1,sizeof(srcBlock),srcBlock); #endif // Create the block for encoding srcIndex = 0; for(row=0; row < BLOCK_SIZE_4; row++) { for(col=0; col < BLOCK_SIZE_4; col++) { blockToEncode[row*BLOCK_SIZE_4+col][BC6H_COMP_RED] = (float)srcBlock[srcIndex]; blockToEncode[row*BLOCK_SIZE_4+col][BC6H_COMP_GREEN] = (float)srcBlock[srcIndex+1]; blockToEncode[row*BLOCK_SIZE_4+col][BC6H_COMP_BLUE] = (float)srcBlock[srcIndex+2]; blockToEncode[row*BLOCK_SIZE_4+col][BC6H_COMP_ALPHA] = (float)srcBlock[srcIndex+3]; srcIndex+=4; } } union BBLOCKS { CMP_DWORD compressedBlock[4]; BYTE out[16]; BYTE in[16]; } data; memset(data.in,0,sizeof(data)); CEncodeBC6HBlock(blockToEncode,pOutBuffer+block); #ifdef _SAVE_AS_BC6 if (fwrite(pOutBuffer+block, sizeof(char), 16, bc6file) != 16) throw "File error on write"; #endif block += 16; #ifdef _BC6H_COMPDEBUGGER // Checks decompression it should match or be close to source union DBLOCKS { float blockToSave[16][4]; float block[64]; } savedata; CMP_BYTE destBlock[BLOCK_SIZE_4X4X4]; memset(savedata.block,0,sizeof(savedata)); m_decoder->DecompressBlock(savedata.blockToSave,data.in); for (row=0; row<64; row++) { destBlock[row] = (BYTE)savedata.block[row]; } g_CompClient.SendData(3,sizeof(destBlock),destBlock); #endif if(pFeedbackProc) { float fProgress = 100.f * (j * dwBlocksX) / (dwBlocksX * dwBlocksY); if(pFeedbackProc(fProgress, pUser1, pUser2)) { #ifdef _BC6H_COMPDEBUGGER g_CompClient.disconnect(); #endif CFinishBC6HEncoding(); return CE_Aborted; } } } } #ifdef _SAVE_AS_BC6 if (fclose(bc6file)) throw "Close failed on .bc6 file"; #endif #ifdef BC6H_COMPDEBUGGER g_CompClient.disconnect(); #endif #ifdef BC6H_DEBUG_TO_RESULTS_TXT if (g_fp) fclose(g_fp); #endif if(pFeedbackProc) { float fProgress = 100.f; pFeedbackProc(fProgress, pUser1, pUser2); } return CFinishBC6HEncoding(); }