mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-06-08 00:23:52 +00:00
- Fixing minor block artifacts on pure 2 color B&W blocks when transcoding to BC1/BC7. This was caused by the ETC1S blocks using extreme ETC1S settings: codetable 7 (the one with the largest intensity deltas), using blocks with selectors that took up the full range (0-3), but the blocks only actually used the two outlier colors (0 and 3 only). The ETC1S->BC1/BC7 table based format conversion system doesn't realize that only the outlie colors were going to be used (i.e. not all 4 colors, just the outer 2), and so the quality of the transcoded block suffered because pure black could not be mapped. In BC7 mode, we now switch to pure BCT (block truncation coding) for any blocks with <= 2 unique colors, independent of their selectors.
- Adding -csv_file option, to generate .csv files for mass benchmarking/testing - Adding -no_ktx option, to avoid writing large .KTX files while unpacking - Fixing printf() format issue when one of the -multifile options wasn't correct Rebuilt compiled javascript transcoder
This commit is contained in:
@@ -1074,47 +1074,63 @@ namespace basisu
|
||||
|
||||
image_stats &s = m_stats[slice_index];
|
||||
|
||||
// TODO: We used to output SSIM (during heavy encoder development), but this slowed down compression too much. We'll be adding it back.
|
||||
|
||||
image_metrics em;
|
||||
|
||||
// best possible ETC1S stats
|
||||
// ---- Nearly best possible ETC1S stats
|
||||
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0);
|
||||
em.print("Unquantized ETC1S Luma: ");
|
||||
em.print("Unquantized ETC1S 709 Luma: ");
|
||||
|
||||
s.m_best_luma_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_best_luma_ssim = static_cast<float>(em.m_ssim);
|
||||
s.m_best_luma_709_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_best_luma_709_ssim = static_cast<float>(em.m_ssim);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0, true, true);
|
||||
em.print("Unquantized ETC1S 601 Luma: ");
|
||||
|
||||
s.m_best_luma_601_psnr = static_cast<float>(em.m_psnr);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 3);
|
||||
em.print("Unquantized ETC1S RGB Avg: ");
|
||||
em.print("Unquantized ETC1S RGB Avg: ");
|
||||
|
||||
s.m_best_rgb_avg_psnr = static_cast<float>(em.m_psnr);
|
||||
|
||||
// .basis ETC1S stats
|
||||
// ---- .basis ETC1S stats
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0);
|
||||
em.print(".basis ETC1S 709 Luma: ");
|
||||
em.print(".basis ETC1S 709 Luma: ");
|
||||
|
||||
s.m_basis_etc1s_luma_709_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_basis_etc1s_luma_709_ssim = static_cast<float>(em.m_ssim);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0, true, true);
|
||||
em.print(".basis ETC1S 601 Luma: ");
|
||||
em.print(".basis ETC1S 601 Luma: ");
|
||||
|
||||
s.m_basis_etc1_luma_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_basis_etc1_luma_ssim = static_cast<float>(em.m_ssim);
|
||||
s.m_basis_etc1s_luma_601_psnr = static_cast<float>(em.m_psnr);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 3);
|
||||
em.print(".basis ETC1S RGB Avg: ");
|
||||
em.print(".basis ETC1S RGB Avg: ");
|
||||
|
||||
//debug_printf(".basis ETC1 Luma SSIM per bit/texel*1000: %3.3f\n", 1000.0f * s.m_basis_etc1_luma_ssim / ((m_backend.get_output().get_output_size_estimate() * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
|
||||
s.m_basis_etc1s_rgb_avg_psnr = em.m_psnr;
|
||||
|
||||
// .basis BC1 stats
|
||||
if (m_slice_descs.size() == 1)
|
||||
{
|
||||
debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_etc1s_luma_709_psnr / ((m_backend.get_output().get_output_size_estimate() * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
|
||||
}
|
||||
|
||||
// ---- .basis BC1 stats
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 0);
|
||||
em.print(".basis BC1 709 Luma: ");
|
||||
em.print(".basis BC1 709 Luma: ");
|
||||
|
||||
s.m_basis_bc1_luma_709_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_basis_bc1_luma_709_ssim = static_cast<float>(em.m_ssim);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 0, true, true);
|
||||
em.print(".basis BC1 601 Luma: ");
|
||||
em.print(".basis BC1 601 Luma: ");
|
||||
|
||||
s.m_basis_bc1_luma_psnr = static_cast<float>(em.m_psnr);
|
||||
s.m_basis_bc1_luma_ssim = static_cast<float>(em.m_ssim);
|
||||
s.m_basis_bc1_luma_601_psnr = static_cast<float>(em.m_psnr);
|
||||
|
||||
em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc1[slice_index], 0, 3);
|
||||
em.print(".basis BC1 RGB Avg: ");
|
||||
em.print(".basis BC1 RGB Avg: ");
|
||||
|
||||
s.m_basis_bc1_rgb_avg_psnr = static_cast<float>(em.m_psnr);
|
||||
}
|
||||
|
||||
@@ -53,19 +53,20 @@ namespace basisu
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
|
||||
m_basis_etc1_rgb_avg_psnr = 0.0f;
|
||||
m_basis_etc1_luma_psnr = 0.0f;
|
||||
m_basis_etc1_luma_ssim = 0.0f;
|
||||
m_basis_bits_per_texel = 0.0f;
|
||||
m_basis_orig_size = 0;
|
||||
m_basis_compressed_size = 0;
|
||||
m_basis_etc1s_rgb_avg_psnr = 0.0f;
|
||||
m_basis_etc1s_luma_709_psnr = 0.0f;
|
||||
m_basis_etc1s_luma_601_psnr = 0.0f;
|
||||
m_basis_etc1s_luma_709_ssim = 0.0f;
|
||||
|
||||
m_basis_bc1_rgb_avg_psnr = 0.0f;
|
||||
m_basis_bc1_luma_709_psnr = 0.0f;
|
||||
m_basis_bc1_luma_601_psnr = 0.0f;
|
||||
m_basis_bc1_luma_709_ssim = 0.0f;
|
||||
|
||||
m_best_rgb_avg_psnr = 0.0f;
|
||||
m_best_luma_psnr = 0.0f;
|
||||
m_best_luma_ssim = 0.0f;
|
||||
m_best_bits_per_texel = 0.0f;
|
||||
m_best_orig_size = 0;
|
||||
m_best_compressed_size = 0;
|
||||
m_best_luma_709_psnr = 0.0f;
|
||||
m_best_luma_601_psnr = 0.0f;
|
||||
m_best_luma_709_ssim = 0.0f;
|
||||
}
|
||||
|
||||
std::string m_filename;
|
||||
@@ -73,24 +74,21 @@ namespace basisu
|
||||
uint32_t m_height;
|
||||
|
||||
// .basis compressed
|
||||
float m_basis_etc1_rgb_avg_psnr;
|
||||
float m_basis_etc1_luma_psnr;
|
||||
float m_basis_etc1_luma_ssim;
|
||||
float m_basis_bits_per_texel;
|
||||
uint64_t m_basis_orig_size;
|
||||
uint64_t m_basis_compressed_size;
|
||||
|
||||
float m_basis_etc1s_rgb_avg_psnr;
|
||||
float m_basis_etc1s_luma_709_psnr;
|
||||
float m_basis_etc1s_luma_601_psnr;
|
||||
float m_basis_etc1s_luma_709_ssim;
|
||||
|
||||
float m_basis_bc1_rgb_avg_psnr;
|
||||
float m_basis_bc1_luma_psnr;
|
||||
float m_basis_bc1_luma_ssim;
|
||||
float m_basis_bc1_luma_709_psnr;
|
||||
float m_basis_bc1_luma_601_psnr;
|
||||
float m_basis_bc1_luma_709_ssim;
|
||||
|
||||
// Normal (highest quality) compressed (ETC1S, not full ETC1)
|
||||
// Normal (highest quality) compressed ETC1S
|
||||
float m_best_rgb_avg_psnr;
|
||||
float m_best_luma_psnr;
|
||||
float m_best_luma_ssim;
|
||||
float m_best_bits_per_texel;
|
||||
uint64_t m_best_orig_size;
|
||||
uint64_t m_best_compressed_size;
|
||||
float m_best_luma_709_psnr;
|
||||
float m_best_luma_601_psnr;
|
||||
float m_best_luma_709_ssim;
|
||||
};
|
||||
|
||||
template<bool def>
|
||||
@@ -370,6 +368,8 @@ namespace basisu
|
||||
uint32_t get_basis_file_size() const { return m_basis_file_size; }
|
||||
double get_basis_bits_per_texel() const { return m_basis_bits_per_texel; }
|
||||
|
||||
bool get_any_source_image_has_alpha() const { return m_any_source_image_has_alpha; }
|
||||
|
||||
private:
|
||||
basis_compressor_params m_params;
|
||||
|
||||
|
||||
11
basisu_enc.h
11
basisu_enc.h
@@ -2295,6 +2295,17 @@ namespace basisu
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
inline FILE *fopen_safe(const char *pFilename, const char *pMode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILE *pFile = nullptr;
|
||||
fopen_s(&pFile, pFilename, pMode);
|
||||
return pFile;
|
||||
#else
|
||||
return fopen(pFilename, pMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ static void print_usage()
|
||||
" -force_alpha: Always output alpha basis files, even if no inputs has alpha\n"
|
||||
" -seperate_rg_to_color_alpha: Seperate input R and G channels to RGB and A (for tangent space XY normal maps)\n"
|
||||
" -no_multithreading: Disable OpenMP multithreading\n"
|
||||
" -no_ktx: Disable KTX writing when unpacking\n"
|
||||
"\n"
|
||||
"Mipmap generation options:\n"
|
||||
" -mipmap: Generate mipmaps for each source image\n"
|
||||
@@ -205,7 +206,8 @@ public:
|
||||
m_mode(cDefault),
|
||||
m_multifile_first(0),
|
||||
m_multifile_num(0),
|
||||
m_individual(false)
|
||||
m_individual(false),
|
||||
m_no_ktx(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -326,6 +328,8 @@ public:
|
||||
}
|
||||
else if (strcasecmp(pArg, "-mipmap") == 0)
|
||||
m_comp_params.m_mip_gen = true;
|
||||
else if (strcasecmp(pArg, "-no_ktx") == 0)
|
||||
m_no_ktx = true;
|
||||
else if (strcasecmp(pArg, "-mip_scale") == 0)
|
||||
{
|
||||
REMAINING_ARGS_CHECK(1);
|
||||
@@ -439,6 +443,14 @@ public:
|
||||
}
|
||||
else if (strcasecmp(pArg, "-individual") == 0)
|
||||
m_individual = true;
|
||||
else if (strcasecmp(pArg, "-csv_file") == 0)
|
||||
{
|
||||
REMAINING_ARGS_CHECK(1);
|
||||
m_csv_file = arg_v[arg_index + 1];
|
||||
m_comp_params.m_compute_stats = true;
|
||||
|
||||
arg_count++;
|
||||
}
|
||||
else if (pArg[0] == '-')
|
||||
{
|
||||
error_printf("Unrecognized command line option: %s\n", pArg);
|
||||
@@ -515,7 +527,10 @@ public:
|
||||
uint32_t m_multifile_first;
|
||||
uint32_t m_multifile_num;
|
||||
|
||||
std::string m_csv_file;
|
||||
|
||||
bool m_individual;
|
||||
bool m_no_ktx;
|
||||
};
|
||||
|
||||
static bool expand_multifile(command_line_params &opts)
|
||||
@@ -536,7 +551,7 @@ static bool expand_multifile(command_line_params &opts)
|
||||
|
||||
if (string_find_right(fmt, '%') == -1)
|
||||
{
|
||||
error_printf("Must include C-style printf() format character '%' in -multifile_printf string\n");
|
||||
error_printf("Must include C-style printf() format character '%%' in -multifile_printf string\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -559,22 +574,38 @@ static bool expand_multifile(command_line_params &opts)
|
||||
static bool compress_mode(command_line_params &opts)
|
||||
{
|
||||
basist::etc1_global_selector_codebook sel_codebook(basist::g_global_selector_cb_size, basist::g_global_selector_cb);
|
||||
|
||||
if (!expand_multifile(opts))
|
||||
return false;
|
||||
|
||||
if (!expand_multifile(opts))
|
||||
{
|
||||
error_printf("-multifile expansion failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!opts.m_input_filenames.size())
|
||||
{
|
||||
error_printf("No input files to process!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
basis_compressor_params ¶ms = opts.m_comp_params;
|
||||
|
||||
params.m_read_source_images = true;
|
||||
params.m_write_output_basis_files = true;
|
||||
params.m_pSel_codebook = &sel_codebook;
|
||||
|
||||
FILE *pCSV_file = nullptr;
|
||||
if (opts.m_csv_file.size())
|
||||
{
|
||||
pCSV_file = fopen_safe(opts.m_csv_file.c_str(), "w");
|
||||
if (!pCSV_file)
|
||||
{
|
||||
error_printf("Failed opening CVS file \"%s\"\n", opts.m_csv_file.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Processing %u total files\n", (uint32_t)opts.m_input_filenames.size());
|
||||
|
||||
for (size_t file_index = 0; file_index < (opts.m_individual ? opts.m_input_filenames.size() : 1U); file_index++)
|
||||
{
|
||||
if (opts.m_individual)
|
||||
@@ -623,6 +654,13 @@ static bool compress_mode(command_line_params &opts)
|
||||
if (!c.init(opts.m_comp_params))
|
||||
{
|
||||
error_printf("basis_compressor::init() failed!\n");
|
||||
|
||||
if (pCSV_file)
|
||||
{
|
||||
fclose(pCSV_file);
|
||||
pCSV_file = nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -668,13 +706,43 @@ static bool compress_mode(command_line_params &opts)
|
||||
}
|
||||
|
||||
if (exit_flag)
|
||||
{
|
||||
if (pCSV_file)
|
||||
{
|
||||
fclose(pCSV_file);
|
||||
pCSV_file = nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pCSV_file) && (c.get_stats().size()))
|
||||
{
|
||||
for (size_t slice_index = 0; slice_index < c.get_stats().size(); slice_index++)
|
||||
{
|
||||
fprintf(pCSV_file, "\"%s\", %u, %u, %u, %u, %u, %f, %f, %f, %f, %u\n",
|
||||
params.m_out_filename.c_str(),
|
||||
(uint32_t)slice_index, (uint32_t)c.get_stats().size(),
|
||||
c.get_stats()[slice_index].m_width, c.get_stats()[slice_index].m_height, (uint32_t)c.get_any_source_image_has_alpha(),
|
||||
c.get_basis_bits_per_texel(),
|
||||
c.get_stats()[slice_index].m_best_luma_709_psnr,
|
||||
c.get_stats()[slice_index].m_basis_etc1s_luma_709_psnr,
|
||||
c.get_stats()[slice_index].m_basis_bc1_luma_709_psnr,
|
||||
params.m_quality_level);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.m_individual)
|
||||
printf("\n");
|
||||
|
||||
} // file_index
|
||||
|
||||
if (pCSV_file)
|
||||
{
|
||||
fclose(pCSV_file);
|
||||
pCSV_file = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -836,7 +904,7 @@ static bool unpack_and_validate_mode(command_line_params &opts, bool validate_fl
|
||||
{
|
||||
const basist::transcoder_texture_format transcoder_tex_fmt = static_cast<basist::transcoder_texture_format>(format_iter);
|
||||
|
||||
if (fileinfo.m_tex_type == basist::cBASISTexTypeCubemapArray)
|
||||
if ((!opts.m_no_ktx) && (fileinfo.m_tex_type == basist::cBASISTexTypeCubemapArray))
|
||||
{
|
||||
// No KTX tool that we know of supports cubemap arrays, so write individual cubemap files.
|
||||
for (uint32_t image_index = 0; image_index < fileinfo.m_total_images; image_index += 6)
|
||||
@@ -870,7 +938,7 @@ static bool unpack_and_validate_mode(command_line_params &opts, bool validate_fl
|
||||
if (level < gi.size())
|
||||
continue;
|
||||
|
||||
if (fileinfo.m_tex_type != basist::cBASISTexTypeCubemapArray)
|
||||
if ((!opts.m_no_ktx) && (fileinfo.m_tex_type != basist::cBASISTexTypeCubemapArray))
|
||||
{
|
||||
std::string ktx_filename(base_filename + string_format("_transcoded_%s_%u.ktx", basist::basis_get_format_name(transcoder_tex_fmt), image_index));
|
||||
if (!write_compressed_texture_file(ktx_filename.c_str(), gi))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// basisu_transcoder.cpp
|
||||
// basisu_transcoder.cpp
|
||||
// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -910,8 +911,9 @@ namespace basist
|
||||
uint8_t m_lo;
|
||||
};
|
||||
static bc1_match_entry g_bc1_match5_equals_1[256], g_bc1_match6_equals_1[256]; // selector 1, allow equals hi/lo
|
||||
static bc1_match_entry g_bc1_match5_equals_0[256], g_bc1_match6_equals_0[256]; // selector 0, allow equals hi/lo
|
||||
|
||||
static void prepare_bc1_single_color_table(bc1_match_entry *pTable, const uint8_t *pExpand, int size, int sel, bool allow_equals)
|
||||
static void prepare_bc1_single_color_table(bc1_match_entry *pTable, const uint8_t *pExpand, int size, int sel)
|
||||
{
|
||||
int total_e = 0;
|
||||
|
||||
@@ -924,13 +926,7 @@ namespace basist
|
||||
{
|
||||
const int lo_e = pExpand[lo], hi_e = pExpand[hi];
|
||||
int e;
|
||||
|
||||
if (!allow_equals)
|
||||
{
|
||||
if (lo == hi)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (sel == 1)
|
||||
{
|
||||
// Selector 1
|
||||
@@ -941,7 +937,7 @@ namespace basist
|
||||
assert(sel == 0);
|
||||
|
||||
// Selector 0
|
||||
e = abs(hi_e - i) + ((abs(hi_e - lo_e) >> 5));
|
||||
e = abs(hi_e - i);
|
||||
}
|
||||
|
||||
if (e < lowest_e)
|
||||
@@ -955,11 +951,6 @@ namespace basist
|
||||
} // hi
|
||||
} // lo
|
||||
|
||||
if (!allow_equals)
|
||||
{
|
||||
assert(pTable[i].m_lo != pTable[i].m_hi);
|
||||
}
|
||||
|
||||
total_e += lowest_e;
|
||||
}
|
||||
}
|
||||
@@ -1649,12 +1640,14 @@ namespace basist
|
||||
uint8_t bc1_expand5[32];
|
||||
for (int i = 0; i < 32; i++)
|
||||
bc1_expand5[i] = static_cast<uint8_t>((i << 3) | (i >> 2));
|
||||
prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, 1, true);
|
||||
prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, 1);
|
||||
prepare_bc1_single_color_table(g_bc1_match5_equals_0, bc1_expand5, 32, 0);
|
||||
|
||||
uint8_t bc1_expand6[64];
|
||||
for (int i = 0; i < 64; i++)
|
||||
bc1_expand6[i] = static_cast<uint8_t>((i << 2) | (i >> 4));
|
||||
prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, 1, true);
|
||||
prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, 1);
|
||||
prepare_bc1_single_color_table(g_bc1_match6_equals_0, bc1_expand6, 64, 0);
|
||||
|
||||
for (uint32_t i = 0; i < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; i++)
|
||||
{
|
||||
@@ -1775,6 +1768,72 @@ namespace basist
|
||||
|
||||
return;
|
||||
}
|
||||
else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3))
|
||||
{
|
||||
color32 block_colors[4];
|
||||
|
||||
decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table);
|
||||
|
||||
const uint32_t r0 = block_colors[0].r;
|
||||
const uint32_t g0 = block_colors[0].g;
|
||||
const uint32_t b0 = block_colors[0].b;
|
||||
|
||||
const uint32_t r1 = block_colors[3].r;
|
||||
const uint32_t g1 = block_colors[3].g;
|
||||
const uint32_t b1 = block_colors[3].b;
|
||||
|
||||
uint32_t max16 = (g_bc1_match5_equals_0[r0].m_hi << 11) | (g_bc1_match6_equals_0[g0].m_hi << 5) | g_bc1_match5_equals_0[b0].m_hi;
|
||||
uint32_t min16 = (g_bc1_match5_equals_0[r1].m_hi << 11) | (g_bc1_match6_equals_0[g1].m_hi << 5) | g_bc1_match5_equals_0[b1].m_hi;
|
||||
|
||||
uint32_t l = 0, h = 1;
|
||||
|
||||
if (min16 == max16)
|
||||
{
|
||||
// Make l > h
|
||||
if (min16 > 0)
|
||||
{
|
||||
min16--;
|
||||
|
||||
l = 0;
|
||||
h = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// l = h = 0
|
||||
assert(min16 == max16 && max16 == 0);
|
||||
|
||||
max16 = 1;
|
||||
min16 = 0;
|
||||
|
||||
l = 1;
|
||||
h = 1;
|
||||
}
|
||||
|
||||
assert(max16 > min16);
|
||||
}
|
||||
|
||||
if (max16 < min16)
|
||||
{
|
||||
std::swap(max16, min16);
|
||||
l = 1;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
pDst_block->set_low_color((uint16_t)max16);
|
||||
pDst_block->set_high_color((uint16_t)min16);
|
||||
|
||||
// TODO: This can be further optimized (read of ETC1 selector bits)
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
{
|
||||
uint32_t s = pSrc_block->get_selector(x, y);
|
||||
pDst_block->set_selector(x, y, (s == 3) ? h : l);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t selector_range_table = g_etc1_to_dxt1_selector_range_index[low_selector][high_selector];
|
||||
|
||||
@@ -2975,13 +3034,94 @@ namespace basist
|
||||
#if !BASISD_WRITE_NEW_BC7_TABLES
|
||||
const uint32_t low_selector = pSelector->m_lo_selector;
|
||||
const uint32_t high_selector = pSelector->m_hi_selector;
|
||||
|
||||
|
||||
const uint32_t inten_table = pSrc_block->m_differential.m_cw1;
|
||||
const uint32_t base_color_r = pSrc_block->m_differential.m_red1;
|
||||
const uint32_t base_color_g = pSrc_block->m_differential.m_green1;
|
||||
const uint32_t base_color_b = pSrc_block->m_differential.m_blue1;
|
||||
|
||||
const uint32_t inten_table = pSrc_block->m_differential.m_cw1;
|
||||
if (pSelector->m_num_unique_selectors <= 2)
|
||||
{
|
||||
// Only two unique selectors so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks.
|
||||
pDst_block->m_lo.m_mode = 64;
|
||||
|
||||
pDst_block->m_lo.m_a0 = 127;
|
||||
pDst_block->m_lo.m_a1 = 127;
|
||||
|
||||
color32 block_colors[4];
|
||||
|
||||
decoder_etc_block::get_block_colors5(block_colors, color32(base_color_r, base_color_g, base_color_b, 255), inten_table);
|
||||
|
||||
const uint32_t r0 = block_colors[low_selector].r;
|
||||
const uint32_t g0 = block_colors[low_selector].g;
|
||||
const uint32_t b0 = block_colors[low_selector].b;
|
||||
const uint32_t low_bits0 = (r0 & 1) + (g0 & 1) + (b0 & 1);
|
||||
uint32_t p0 = low_bits0 >= 2;
|
||||
|
||||
const uint32_t r1 = block_colors[high_selector].r;
|
||||
const uint32_t g1 = block_colors[high_selector].g;
|
||||
const uint32_t b1 = block_colors[high_selector].b;
|
||||
const uint32_t low_bits1 = (r1 & 1) + (g1 & 1) + (b1 & 1);
|
||||
uint32_t p1 = low_bits1 >= 2;
|
||||
|
||||
pDst_block->m_lo.m_r0 = r0 >> 1;
|
||||
pDst_block->m_lo.m_g0 = g0 >> 1;
|
||||
pDst_block->m_lo.m_b0 = b0 >> 1;
|
||||
pDst_block->m_lo.m_p0 = p0;
|
||||
|
||||
pDst_block->m_lo.m_r1 = r1 >> 1;
|
||||
pDst_block->m_lo.m_g1 = g1 >> 1;
|
||||
pDst_block->m_lo.m_b1 = b1 >> 1;
|
||||
|
||||
uint32_t output_low_selector = 0;
|
||||
uint32_t output_bit_offset = 1;
|
||||
uint64_t output_hi_bits = p1;
|
||||
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
{
|
||||
uint32_t s = pSrc_block->get_selector(x, y);
|
||||
uint32_t os = (s == low_selector) ? output_low_selector : (15 ^ output_low_selector);
|
||||
|
||||
uint32_t num_bits = 4;
|
||||
|
||||
if ((x | y) == 0)
|
||||
{
|
||||
if (os & 8)
|
||||
{
|
||||
pDst_block->m_lo.m_r0 = r1 >> 1;
|
||||
pDst_block->m_lo.m_g0 = g1 >> 1;
|
||||
pDst_block->m_lo.m_b0 = b1 >> 1;
|
||||
pDst_block->m_lo.m_p0 = p1;
|
||||
|
||||
pDst_block->m_lo.m_r1 = r0 >> 1;
|
||||
pDst_block->m_lo.m_g1 = g0 >> 1;
|
||||
pDst_block->m_lo.m_b1 = b0 >> 1;
|
||||
|
||||
output_hi_bits &= ~1ULL;
|
||||
output_hi_bits |= p0;
|
||||
std::swap(p0, p1);
|
||||
|
||||
output_low_selector = 15;
|
||||
os = 0;
|
||||
}
|
||||
|
||||
num_bits = 3;
|
||||
}
|
||||
|
||||
output_hi_bits |= (static_cast<uint64_t>(os) << output_bit_offset);
|
||||
output_bit_offset += num_bits;
|
||||
}
|
||||
}
|
||||
|
||||
pDst_block->m_hi_bits = output_hi_bits;
|
||||
|
||||
assert(pDst_block->m_hi.m_p1 == p1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t selector_range_table = g_etc1_to_bc7_m6_selector_range_index[low_selector][high_selector];
|
||||
|
||||
const uint32_t* pTable_r = g_etc1_to_bc7_m6_table[base_color_r + inten_table * 32] + (selector_range_table * NUM_ETC1_TO_BC7_M6_SELECTOR_MAPPINGS);
|
||||
@@ -3750,7 +3890,7 @@ namespace basist
|
||||
{
|
||||
#if BASISD_SUPPORT_BC7
|
||||
block.set_raw_selector_bits(pSelector->m_bytes[0], pSelector->m_bytes[1], pSelector->m_bytes[2], pSelector->m_bytes[3]);
|
||||
|
||||
|
||||
void* pDst_block = static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * num_blocks_x) * output_stride;
|
||||
convert_etc1s_to_bc7_m6(static_cast<bc7_mode_6*>(pDst_block), &block, pSelector);
|
||||
#else
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Reference in New Issue
Block a user