mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2025-01-09 02:25:36 +00:00
Add new compression function that collects preliminary stats.
This commit is contained in:
parent
fcbca9ca8d
commit
1e6a2d4c7b
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
#include "BC7Config.h"
|
#include "BC7Config.h"
|
||||||
|
|
||||||
|
class BlockStatManager;
|
||||||
|
|
||||||
namespace BC7C
|
namespace BC7C
|
||||||
{
|
{
|
||||||
// This is the error metric that is applied to our error measurement algorithm
|
// 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
|
// Compress the image given as RGBA data to BC7 format. Width and Height are the dimensions of
|
||||||
// the image in pixels.
|
// 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
|
#ifdef HAS_SSE_41
|
||||||
// Compress the image given as RGBA data to BC7 format using an algorithm optimized for SIMD
|
// Compress the image given as RGBA data to BC7 format using an algorithm optimized for SIMD
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "RGBAEndpoints.h"
|
#include "RGBAEndpoints.h"
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
|
|
||||||
|
#include "BlockStats.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -35,6 +37,18 @@
|
||||||
#define ALIGN_SSE __attribute__((aligned(16)))
|
#define ALIGN_SSE __attribute__((aligned(16)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum EBlockStats {
|
||||||
|
eBlockStat_Path,
|
||||||
|
eBlockStat_Mode,
|
||||||
|
|
||||||
|
kNumBlockStats
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *kBlockStatString[kNumBlockStats] = {
|
||||||
|
"BlockStat_Path",
|
||||||
|
"BlockStat_Mode"
|
||||||
|
};
|
||||||
|
|
||||||
static const uint32 kNumShapes2 = 64;
|
static const uint32 kNumShapes2 = 64;
|
||||||
static const uint16 kShapeMask2[kNumShapes2] = {
|
static const uint16 kShapeMask2[kNumShapes2] = {
|
||||||
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
|
0xcccc, 0x8888, 0xeeee, 0xecc8, 0xc880, 0xfeec, 0xfec8, 0xec80,
|
||||||
|
@ -1343,7 +1357,7 @@ namespace BC7C
|
||||||
|
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
static void ExtractBlock(const uint8* inPtr, int width, uint32* colorBlock);
|
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;
|
static int gQualityLevel = 50;
|
||||||
void SetQualityLevel(int q) {
|
void SetQualityLevel(int q) {
|
||||||
|
@ -1427,7 +1441,48 @@ namespace BC7C
|
||||||
for(int i = 0; i < width; i += 4)
|
for(int i = 0; i < width; i += 4)
|
||||||
{
|
{
|
||||||
// ExtractBlock(inBuf + i * 4, width, block);
|
// 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]++;
|
BC7CompressionMode::NumUses[gBestMode]++;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -1595,13 +1650,27 @@ namespace BC7C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress a single block.
|
// 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?
|
// All a single color?
|
||||||
if(AllOneColor(block)) {
|
if(AllOneColor(block)) {
|
||||||
BitStream bStrm(outBuf, 128, 0);
|
BitStream bStrm(outBuf, 128, 0);
|
||||||
CompressOptimalColorBC7(*block, bStrm);
|
CompressOptimalColorBC7(*block, bStrm);
|
||||||
gBestMode = 5;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1624,6 +1693,15 @@ namespace BC7C
|
||||||
BitStream bStrm(outBuf, 128, 0);
|
BitStream bStrm(outBuf, 128, 0);
|
||||||
WriteTransparentBlock(bStrm);
|
WriteTransparentBlock(bStrm);
|
||||||
gBestMode = 6;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1647,6 +1725,14 @@ namespace BC7C
|
||||||
if(err < 1e-9) {
|
if(err < 1e-9) {
|
||||||
CompressTwoClusters(i, clusters, outBuf, opaque);
|
CompressTwoClusters(i, clusters, outBuf, opaque);
|
||||||
gBestMode = gModeChosen;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1675,6 +1761,15 @@ namespace BC7C
|
||||||
if(err < 1e-9) {
|
if(err < 1e-9) {
|
||||||
CompressThreeClusters(i, clusters, outBuf, opaque);
|
CompressThreeClusters(i, clusters, outBuf, opaque);
|
||||||
gBestMode = gModeChosen;
|
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;
|
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];
|
uint8 tempBuf1[16], tempBuf2[16];
|
||||||
|
|
||||||
BitStream tempStream1 (tempBuf1, 128, 0);
|
BitStream tempStream1 (tempBuf1, 128, 0);
|
||||||
|
@ -1695,6 +1795,12 @@ namespace BC7C
|
||||||
double best = compressor.Compress(tempStream1, 0, &blockCluster);
|
double best = compressor.Compress(tempStream1, 0, &blockCluster);
|
||||||
gBestMode = 6;
|
gBestMode = 6;
|
||||||
if(best == 0.0f) {
|
if(best == 0.0f) {
|
||||||
|
|
||||||
|
if(statManager) {
|
||||||
|
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
|
||||||
|
statManager->AddStat(blockIdx, s);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(outBuf, tempBuf1, 16);
|
memcpy(outBuf, tempBuf1, 16);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1731,6 +1837,12 @@ namespace BC7C
|
||||||
|
|
||||||
if(error == 0.0f) {
|
if(error == 0.0f) {
|
||||||
memcpy(outBuf, tempBuf2, 16);
|
memcpy(outBuf, tempBuf2, 16);
|
||||||
|
|
||||||
|
if(statManager) {
|
||||||
|
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
|
||||||
|
statManager->AddStat(blockIdx, s);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1744,17 +1856,27 @@ namespace BC7C
|
||||||
gBestMode = gModeChosen;
|
gBestMode = gModeChosen;
|
||||||
memcpy(outBuf, tempBuf2, 16);
|
memcpy(outBuf, tempBuf2, 16);
|
||||||
|
|
||||||
|
if(statManager) {
|
||||||
|
BlockStat s = BlockStat(kBlockStatString[eBlockStat_Mode], gBestMode);
|
||||||
|
statManager->AddStat(blockIdx, s);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(outBuf, tempBuf1, 16);
|
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]) {
|
static void DecompressBC7Block(const uint8 block[16], uint32 outBuf[16]) {
|
||||||
|
|
||||||
BitStreamReadOnly strm(block);
|
BitStreamReadOnly strm(block);
|
||||||
|
|
||||||
uint32 mode = 0;
|
uint32 mode = 0;
|
||||||
while(!strm.ReadBit()) {
|
while(!strm.ReadBit()) {
|
||||||
mode++;
|
mode++;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
struct BlockStat {
|
struct BlockStat {
|
||||||
friend class BlockStatManager;
|
friend class BlockStatManager;
|
||||||
public:
|
public:
|
||||||
BlockStat(const CHAR *statName, uint64 stat);
|
BlockStat(const CHAR *statName, int);
|
||||||
BlockStat(const CHAR *statName, double stat);
|
BlockStat(const CHAR *statName, double stat);
|
||||||
|
|
||||||
BlockStat(const BlockStat &);
|
BlockStat(const BlockStat &);
|
||||||
|
|
|
@ -16,8 +16,12 @@ static T max(const T &a, const T &b) {
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
BlockStat::BlockStat(const CHAR *statName, double stat) :
|
BlockStat::BlockStat(const CHAR *statName, int stat) : m_IntStat(stat)
|
||||||
m_FloatStat(stat)
|
{
|
||||||
|
strncpy(m_StatName, statName, kStatNameSz);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockStat::BlockStat(const CHAR *statName, double stat) : m_FloatStat(stat)
|
||||||
{
|
{
|
||||||
strncpy(m_StatName, statName, kStatNameSz);
|
strncpy(m_StatName, statName, kStatNameSz);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +105,10 @@ BlockStatManager::BlockStatList::~BlockStatList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockStatManager::BlockStatList::AddStat(const BlockStat &stat) {
|
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);
|
m_Tail->AddStat(stat);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in a new issue