Add new compression function that collects preliminary stats.

This commit is contained in:
Pavel Krajcevski 2012-10-06 22:25:49 -04:00
parent fcbca9ca8d
commit 1e6a2d4c7b
4 changed files with 153 additions and 9 deletions

View File

@ -17,6 +17,8 @@
#include "BC7Config.h"
class BlockStatManager;
namespace BC7C
{
// This is the error metric that is applied to our error measurement algorithm
@ -52,7 +54,20 @@ namespace BC7C
// Compress the image given as RGBA data to BC7 format. Width and Height are the dimensions of
// the image in pixels.
void CompressImageBC7(const unsigned char *inBuf, unsigned char *outBuf, unsigned int width, unsigned int height);
void CompressImageBC7(
const unsigned char *inBuf,
unsigned char *outBuf,
unsigned int width,
unsigned int height
);
void CompressImageBC7Stats(
const unsigned char *inBuf,
unsigned char *outBuf,
unsigned int width,
unsigned int height,
BlockStatManager &statManager
);
#ifdef HAS_SSE_41
// Compress the image given as RGBA data to BC7 format using an algorithm optimized for SIMD

View File

@ -22,6 +22,8 @@
#include "RGBAEndpoints.h"
#include "BitStream.h"
#include "BlockStats.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
@ -35,6 +37,18 @@
#define ALIGN_SSE __attribute__((aligned(16)))
#endif
enum EBlockStats {
eBlockStat_Path,
eBlockStat_Mode,
kNumBlockStats
};
static const char *kBlockStatString[kNumBlockStats] = {
"BlockStat_Path",
"BlockStat_Mode"
};
static const uint32 kNumShapes2 = 64;
static const uint16 kShapeMask2[kNumShapes2] = {
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
@ -1343,7 +1357,7 @@ namespace BC7C
// Function prototypes
static void ExtractBlock(const uint8* inPtr, int width, uint32* colorBlock);
static void CompressBC7Block(const uint32 *block, uint8 *outBuf);
static void CompressBC7Block(const uint32 *block, uint8 *outBuf, BlockStatManager *statManager);
static int gQualityLevel = 50;
void SetQualityLevel(int q) {
@ -1427,7 +1441,48 @@ namespace BC7C
for(int i = 0; i < width; i += 4)
{
// ExtractBlock(inBuf + i * 4, width, block);
CompressBC7Block((const uint32 *)inBuf, outBuf);
CompressBC7Block((const uint32 *)inBuf, outBuf, NULL);
BC7CompressionMode::NumUses[gBestMode]++;
#ifndef NDEBUG
uint8 *block = (uint8 *)outBuf;
uint32 unComp[16];
DecompressBC7Block(block, unComp);
uint8* unCompData = (uint8 *)unComp;
int diffSum = 0;
for(int i = 0; i < 64; i++) {
diffSum += sad(unCompData[i], inBuf[i]);
}
double blockError = double(diffSum) / 64.0;
if(blockError > 50.0) {
fprintf(stderr, "WARNING: Block error very high (%.2f)\n", blockError);
}
#endif
outBuf += 16;
inBuf += 64;
}
}
}
void CompressImageBC7(
const unsigned char *inBuf,
unsigned char *outBuf,
unsigned int width,
unsigned int height,
BlockStatManager &statManager
) {
uint32 block[16];
BC7CompressionMode::ResetNumUses();
BC7CompressionMode::MaxAnnealingIterations = min(BC7CompressionMode::kMaxAnnealingIterations, GetQualityLevel());
for(int j = 0; j < height; j += 4)
{
for(int i = 0; i < width; i += 4)
{
// ExtractBlock(inBuf + i * 4, width, block);
CompressBC7Block((const uint32 *)inBuf, outBuf, &statManager);
BC7CompressionMode::NumUses[gBestMode]++;
#ifndef NDEBUG
@ -1595,13 +1650,27 @@ namespace BC7C
}
// Compress a single block.
static void CompressBC7Block(const uint32 *block, uint8 *outBuf) {
static void CompressBC7Block(const uint32 *block, uint8 *outBuf, BlockStatManager *statManager) {
uint32 blockIdx = 0;
if(statManager) {
blockIdx = statManager->BeginBlock();
}
// All a single color?
if(AllOneColor(block)) {
BitStream bStrm(outBuf, 128, 0);
CompressOptimalColorBC7(*block, bStrm);
gBestMode = 5;
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 0);
statManager->AddStat(blockIdx, s);
s = BlockStat(kBlockStatString[eBlockStat_Mode], 5);
statManager->AddStat(blockIdx, s);
}
return;
}
@ -1624,6 +1693,15 @@ namespace BC7C
BitStream bStrm(outBuf, 128, 0);
WriteTransparentBlock(bStrm);
gBestMode = 6;
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 1);
statManager->AddStat(blockIdx, s);
s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
return;
}
@ -1647,6 +1725,14 @@ namespace BC7C
if(err < 1e-9) {
CompressTwoClusters(i, clusters, outBuf, opaque);
gBestMode = gModeChosen;
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 2);
statManager->AddStat(blockIdx, s);
s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
return;
}
@ -1675,6 +1761,15 @@ namespace BC7C
if(err < 1e-9) {
CompressThreeClusters(i, clusters, outBuf, opaque);
gBestMode = gModeChosen;
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 2);
statManager->AddStat(blockIdx, s);
s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
return;
}
@ -1688,6 +1783,11 @@ namespace BC7C
}
}
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Path], 3);
statManager->AddStat(blockIdx, s);
}
uint8 tempBuf1[16], tempBuf2[16];
BitStream tempStream1 (tempBuf1, 128, 0);
@ -1695,6 +1795,12 @@ namespace BC7C
double best = compressor.Compress(tempStream1, 0, &blockCluster);
gBestMode = 6;
if(best == 0.0f) {
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
memcpy(outBuf, tempBuf1, 16);
return;
}
@ -1731,6 +1837,12 @@ namespace BC7C
if(error == 0.0f) {
memcpy(outBuf, tempBuf2, 16);
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
return;
}
else {
@ -1744,17 +1856,27 @@ namespace BC7C
gBestMode = gModeChosen;
memcpy(outBuf, tempBuf2, 16);
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
return;
}
}
memcpy(outBuf, tempBuf1, 16);
if(statManager) {
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
statManager->AddStat(blockIdx, s);
}
}
static void DecompressBC7Block(const uint8 block[16], uint32 outBuf[16]) {
BitStreamReadOnly strm(block);
uint32 mode = 0;
while(!strm.ReadBit()) {
mode++;

View File

@ -8,7 +8,7 @@
struct BlockStat {
friend class BlockStatManager;
public:
BlockStat(const CHAR *statName, uint64 stat);
BlockStat(const CHAR *statName, int);
BlockStat(const CHAR *statName, double stat);
BlockStat(const BlockStat &);

View File

@ -16,8 +16,12 @@ static T max(const T &a, const T &b) {
//
////////////////////////////////////////////////////////////////////////////////
BlockStat::BlockStat(const CHAR *statName, double stat) :
m_FloatStat(stat)
BlockStat::BlockStat(const CHAR *statName, int stat) : m_IntStat(stat)
{
strncpy(m_StatName, statName, kStatNameSz);
}
BlockStat::BlockStat(const CHAR *statName, double stat) : m_FloatStat(stat)
{
strncpy(m_StatName, statName, kStatNameSz);
}
@ -101,7 +105,10 @@ BlockStatManager::BlockStatList::~BlockStatList() {
}
void BlockStatManager::BlockStatList::AddStat(const BlockStat &stat) {
if(!m_Tail) {
if(strncmp(stat.m_StatName, m_Stat.m_StatName, BlockStat::kStatNameSz) == 0) {
m_Stat = stat;
}
else if(!m_Tail) {
m_Tail->AddStat(stat);
}
else {