Skip to content

Commit

Permalink
Make weights tuneable and implement compression of the data
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Evstyukhin committed Apr 3, 2022
1 parent e04eece commit a6777cf
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 186 deletions.
36 changes: 15 additions & 21 deletions src/Bc7Compress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg
bool flip = true;
bool mask = true;
int border = 1;
bool linearData = false;

const char* src_name = nullptr;
const char* dst_name = nullptr;
Expand Down Expand Up @@ -300,13 +301,6 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg
doSlow = false;
continue;
}
else if (strcmp(arg, "/normal") == 0)
{
doDraft = true;
doNormal = true;
doSlow = false;
continue;
}
else if (strcmp(arg, "/slow") == 0)
{
doDraft = true;
Expand All @@ -329,6 +323,12 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg
border = 2;
continue;
}
else if (strcmp(arg, "/data") == 0)
{
mask = false;
linearData = true;
continue;
}
else if (strcmp(arg, "/debug") == 0)
{
if (++i < n)
Expand Down Expand Up @@ -462,7 +462,7 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg
head[22] = flip ? 0x00753Du : 0x00643Du;
head[23] = static_cast<uint32_t>(Size); // imageSize

bc7Core.pInitTables(doDraft, doNormal, doSlow);
bc7Core.pInitTables(doDraft, doNormal, doSlow, linearData);

if ((dst_name != nullptr) && dst_name[0])
{
Expand Down Expand Up @@ -492,8 +492,8 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg
if (mse_alpha > 0)
{
PRINTF(" SubTexture A qMSE = %.1f, qPSNR = %f, SSIM_4x4 = %.8f",
(1.0 / kAlpha) * mse_alpha / pixels,
10.0 * log((255.0 * 255.0) * kAlpha * pixels / mse_alpha) / log(10.0),
(1.0 / gWeightAlpha) * mse_alpha / pixels,
10.0 * log((255.0 * 255.0) * gWeightAlpha * pixels / mse_alpha) / log(10.0),
ssim.Alpha * 16.0 / pixels);
}
else
Expand All @@ -503,17 +503,10 @@ int Bc7MainWithArgs(const IBc7Core& bc7Core, const std::vector<std::string>& arg

if (mse_color > 0)
{
#if defined(OPTION_LINEAR)
PRINTF(" SubTexture RGB qMSE = %.1f, qPSNR = %f, SSIM_4x4 = %.8f",
(1.0 / kColor) * mse_color / pixels,
10.0 * log((255.0 * 255.0) * kColor * pixels / mse_color) / log(10.0),
ssim.Color * 16.0 / pixels);
#else
PRINTF(" SubTexture RGB qMSE = %.1f, qPSNR = %f, wSSIM_4x4 = %.8f",
(1.0 / kColor) * mse_color / pixels,
10.0 * log((255.0 * 255.0) * kColor * pixels / mse_color) / log(10.0),
(1.0 / gWeightColor) * mse_color / pixels,
10.0 * log((255.0 * 255.0) * gWeightColor * pixels / mse_color) / log(10.0),
ssim.Color * 16.0 / pixels);
#endif
}
else
{
Expand Down Expand Up @@ -577,8 +570,9 @@ int __cdecl main(int argc, char* argv[])

if (argc < 2)
{
PRINTF("Usage: Bc7Compress [/draft | /normal | /slow] [/retina] [/nomask] [/noflip] src");
PRINTF(" [dst.ktx] [/debug result.png] [/map partitions.png] [/bad bad.png]");
PRINTF("Usage: Bc7Compress [/retina] [/nomask] [/noflip] [/data] src");
PRINTF(" [/draft | /slow] [dst.ktx]");
PRINTF(" [/debug result.png] [/map partitions.png] [/bad bad.png]");
return 1;
}

Expand Down
38 changes: 20 additions & 18 deletions src/Bc7Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static INLINED int ComputeOpaqueAlphaError(const Area& area) noexcept
error += da * da;
}

error *= kAlpha;
error *= gWeightAlpha;
}

return error;
Expand Down Expand Up @@ -207,7 +207,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
{
bool changes = false;

int64_t b = covBG * kGreen + covRB * kRed;
int64_t b = covBG * gWeightGreen + covRB * gWeightRed;
if (b < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(2, 3, 1, 0));
Expand All @@ -218,7 +218,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
changes = true;
}

int64_t r = covGR * kGreen + covRB * kBlue;
int64_t r = covGR * gWeightGreen + covRB * gWeightBlue;
if (r < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(3, 2, 0, 1));
Expand Down Expand Up @@ -354,7 +354,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
{
bool changes = false;

int64_t b = covBG * kGreen + covRB * kRed;
int64_t b = covBG * gWeightGreen + covRB * gWeightRed;
if (b < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(2, 3, 1, 0));
Expand All @@ -365,7 +365,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
changes = true;
}

int64_t r = covGR * kGreen + covRB * kBlue;
int64_t r = covGR * gWeightGreen + covRB * gWeightBlue;
if (r < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(3, 2, 0, 1));
Expand Down Expand Up @@ -447,7 +447,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
{
bool changes = false;

int64_t b = covAB * kAlpha + covBG * kGreen + covRB * kRed;
int64_t b = covAB * gWeightAlpha + covBG * gWeightGreen + covRB * gWeightRed;
if (b < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(2, 3, 1, 0));
Expand All @@ -459,7 +459,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
changes = true;
}

int64_t r = covAR * kAlpha + covGR * kGreen + covRB * kBlue;
int64_t r = covAR * gWeightAlpha + covGR * gWeightGreen + covRB * gWeightBlue;
if (r < 0)
{
mbounds = _mm_shufflehi_epi16(mbounds, _MM_SHUFFLE(3, 2, 0, 1));
Expand All @@ -471,7 +471,7 @@ NOTINLINED void MakeAreaFromCell(Area& area, const Cell& cell, const size_t coun
changes = true;
}

int64_t g = covAG * kAlpha + covGR * kRed + covBG * kBlue;
int64_t g = covAG * gWeightAlpha + covGR * gWeightRed + covBG * gWeightBlue;
if (g < 0)
{
mbounds = _mm_shufflelo_epi16(mbounds, _MM_SHUFFLE(2, 3, 1, 0));
Expand Down Expand Up @@ -689,7 +689,7 @@ NOTINLINED NodeShort* radix_sort(NodeShort* input, NodeShort* work, size_t N) no
template<int M>
INLINED int ComputeSubsetTable(const Area& area, const __m128i mweights, Modulations& state) noexcept
{
const int denoiseStep = (area.IsOpaque ? kDenoiseStep * kColor : kDenoiseStep * (kColor + kAlpha));
const int denoiseStep = kDenoiseStep * (area.IsOpaque ? gWeightColor : gWeightColorAlpha);

int good = 1;
{
Expand Down Expand Up @@ -887,7 +887,7 @@ INLINED int ComputeSubsetTable(const Area& area, const __m128i mweights, Modulat
__m128i mpacked = _mm_load_si128(&area.DataMask_I16[i]);
__m256i vpixel = _mm256_broadcastq_epi64(mpacked);

__m256i vbottom = _mm256_set1_epi32(kBlockMaximalAlphaError + kBlockMaximalColorError);
__m256i vbottom = _mm256_set1_epi32(kBlockMaximalColorAlphaError);

if constexpr (M == 16)
{
Expand Down Expand Up @@ -1107,7 +1107,7 @@ INLINED int ComputeSubsetTable(const Area& area, const __m128i mweights, Modulat
__m128i mpacked = _mm_load_si128(&area.DataMask_I16[i]);
__m128i mpixel = _mm_unpacklo_epi64(mpacked, mpacked);

uint64_t bottom = (kBlockMaximalAlphaError + kBlockMaximalColorError) * ((1uLL << 32) + 1uLL);
constexpr uint64_t bottom = kBlockMaximalColorAlphaError * ((1uLL << 32) + 1uLL);

for (int j = 0; j < M; j += 2)
{
Expand Down Expand Up @@ -1282,7 +1282,7 @@ INLINED int ComputeSubsetTable(const Area& area, const __m128i mweights, Modulat

//

double best = -(kAlpha + kColor + 0.1);
double best = -(gWeightColorAlpha + 0.1);

for (;;)
{
Expand Down Expand Up @@ -1482,7 +1482,7 @@ static void CompressBlock(uint8_t output[16], Cell& input) noexcept

if (gDoDraft)
{
const int denoiseStep = static_cast<int>(input.Area1.Active) * ((input.Area1.IsOpaque ? kDenoiseStep * kColor : kDenoiseStep * (kColor + kAlpha)) >> (kDenoise + kDenoise));
const int denoiseStep = static_cast<int>(input.Area1.Active) * ((kDenoiseStep * (input.Area1.IsOpaque ? gWeightColor : gWeightColorAlpha)) >> (kDenoise + kDenoise));
input.DenoiseStep = denoiseStep;

input.OpaqueAlphaError = ComputeOpaqueAlphaError(input.Area1);
Expand Down Expand Up @@ -1818,12 +1818,18 @@ static ALWAYS_INLINED __m128i ConvertBgraToAgrb(__m128i mc) noexcept
return _mm_shuffle_epi8(mc, mrot);
}

static void InitTables(bool doDraft, bool doNormal, bool doSlow)
static void InitTables(bool doDraft, bool doNormal, bool doSlow, bool linearData)
{
gDoDraft = doDraft;
gDoNormal = doNormal;
gDoSlow = doSlow;

InitWeights(linearData);

#if defined(OPTION_PCA)
InitPCA();
#endif

{
static bool gsInited = false;
if (gsInited)
Expand All @@ -1837,10 +1843,6 @@ static void InitTables(bool doDraft, bool doNormal, bool doSlow)
InitShrinked();
InitSelection();
InitLevels();

#if defined(OPTION_PCA)
InitPCA();
#endif
}

static void DecompressKernel(const WorkerItem* begin, const WorkerItem* end, int stride, int64_t& pErrorAlpha, int64_t& pErrorColor, BlockSSIM& pssim) noexcept
Expand Down
6 changes: 3 additions & 3 deletions src/Bc7Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include "pch.h"

constexpr int kBlockMaximalAlphaError = 16 * (255 >> kDenoise) * (255 >> kDenoise) * kAlpha + 1;
constexpr int kBlockMaximalColorError = 16 * (255 >> kDenoise) * (255 >> kDenoise) * kColor + 1;
constexpr int kBlockMaximalColorError = 16 * (255 >> kDenoise) * (255 >> kDenoise) * kWeightLimit + 1;
constexpr int kBlockMaximalColorAlphaError = kBlockMaximalColorError * 2;

struct BlockError
{
Expand Down Expand Up @@ -307,7 +307,7 @@ struct WorkerItem
}
};

using PInitTables = void(*)(bool doDraft, bool doNormal, bool doSlow);
using PInitTables = void(*)(bool doDraft, bool doNormal, bool doSlow, bool linearData);

using PBlockKernel = void(*)(const WorkerItem* begin, const WorkerItem* end, int stride, int64_t& pErrorAlpha, int64_t& pErrorColor, BlockSSIM& pssim) noexcept;

Expand Down
12 changes: 6 additions & 6 deletions src/Bc7CoreMode0.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,17 +249,17 @@ namespace Mode0 {
template<int pbits>
INLINED bool InitLevels(const Area& area, const int water, const Estimation& estimation) noexcept
{
ch1.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 1, kGreen, water - estimation.ch2 - estimation.ch3);
ch1.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 1, gWeightGreen, water - estimation.ch2 - estimation.ch3);
int min1 = ch1.MinErr;
if (min1 >= water)
return false;

ch2.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 2, kRed, water - min1 - estimation.ch3);
ch2.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 2, gWeightRed, water - min1 - estimation.ch3);
int min2 = ch2.MinErr;
if (min1 + min2 >= water)
return false;

ch3.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 3, kBlue, water - min1 - min2);
ch3.ComputeChannelLevelsReduced<4, pbits, false, gTableDeltas3_Value5>(area, 3, gWeightBlue, water - min1 - min2);
int min3 = ch3.MinErr;
if (min1 + min2 + min3 >= water)
return false;
Expand Down Expand Up @@ -505,19 +505,19 @@ namespace Mode0 {
int error = 0;
if (error < water)
{
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 1, kGreen, water - error);
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 1, gWeightGreen, water - error);
estimation.ch1 = level1;
error += level1;

if (error < water)
{
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 2, kRed, water - error);
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 2, gWeightRed, water - error);
estimation.ch2 = level2;
error += level2;

if (error < water)
{
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 3, kBlue, water - error);
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas3_Value5, gTableCuts3_Value5>(area, 3, gWeightBlue, water - error);
estimation.ch3 = level3;
error += level3;

Expand Down
12 changes: 6 additions & 6 deletions src/Bc7CoreMode1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,17 @@ namespace Mode1 {
template<int pbits>
INLINED bool InitLevels(const Area& area, const int water, const Estimation& estimation) noexcept
{
ch1.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 1, kGreen, water - estimation.ch2 - estimation.ch3);
ch1.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 1, gWeightGreen, water - estimation.ch2 - estimation.ch3);
int min1 = ch1.MinErr;
if (min1 >= water)
return false;

ch2.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 2, kRed, water - min1 - estimation.ch3);
ch2.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 2, gWeightRed, water - min1 - estimation.ch3);
int min2 = ch2.MinErr;
if (min1 + min2 >= water)
return false;

ch3.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 3, kBlue, water - min1 - min2);
ch3.ComputeChannelLevelsReduced<6, pbits, false, gTableDeltas3_Value7Shared>(area, 3, gWeightBlue, water - min1 - min2);
int min3 = ch3.MinErr;
if (min1 + min2 + min3 >= water)
return false;
Expand Down Expand Up @@ -445,19 +445,19 @@ namespace Mode1 {
int error = 0;
if (error < water)
{
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 1, kGreen, water - error);
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 1, gWeightGreen, water - error);
estimation.ch1 = level1;
error += level1;

if (error < water)
{
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 2, kRed, water - error);
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 2, gWeightRed, water - error);
estimation.ch2 = level2;
error += level2;

if (error < water)
{
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 3, kBlue, water - error);
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<7, false, gTableDeltas3_Value7Shared, gTableCuts3_Value7Shared>(area, 3, gWeightBlue, water - error);
estimation.ch3 = level3;
error += level3;

Expand Down
12 changes: 6 additions & 6 deletions src/Bc7CoreMode2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,17 @@ namespace Mode2 {

INLINED bool InitLevels(const Area& area, const int water, const Estimation& estimation) noexcept
{
ch1.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 1, kGreen, water - estimation.ch2 - estimation.ch3);
ch1.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 1, gWeightGreen, water - estimation.ch2 - estimation.ch3);
int min1 = ch1.MinErr;
if (min1 >= water)
return false;

ch2.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 2, kRed, water - min1 - estimation.ch3);
ch2.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 2, gWeightRed, water - min1 - estimation.ch3);
int min2 = ch2.MinErr;
if (min1 + min2 >= water)
return false;

ch3.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 3, kBlue, water - min1 - min2);
ch3.ComputeChannelLevelsReduced<5, -1, false, gTableDeltas2_Value5>(area, 3, gWeightBlue, water - min1 - min2);
int min3 = ch3.MinErr;
if (min1 + min2 + min3 >= water)
return false;
Expand Down Expand Up @@ -429,19 +429,19 @@ namespace Mode2 {
int error = 0;
if (error < water)
{
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 1, kGreen, water - error);
int level1 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 1, gWeightGreen, water - error);
estimation.ch1 = level1;
error += level1;

if (error < water)
{
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 2, kRed, water - error);
int level2 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 2, gWeightRed, water - error);
estimation.ch2 = level2;
error += level2;

if (error < water)
{
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 3, kBlue, water - error);
int level3 = LevelsMinimum::EstimateChannelLevelsReduced<5, false, gTableDeltas2_Value5, gTableCuts2_Value5>(area, 3, gWeightBlue, water - error);
estimation.ch3 = level3;
error += level3;

Expand Down
Loading

0 comments on commit a6777cf

Please sign in to comment.