Fixing frontend's selector codebook generator so it guarantees that all-flag selector clusters will be present in the output codebook.

Adding debug visualization flags to transoder
Hooking up debug visualization to WebGL demo
This commit is contained in:
richgel999
2019-05-20 10:48:20 -07:00
parent a33b5144d5
commit 481de7da7d
11 changed files with 221 additions and 39 deletions
+2 -2
View File
@@ -18,7 +18,7 @@
#define BASISU_USE_STB_IMAGE_RESIZE_FOR_MIPMAP_GEN 0
#define DEBUG_CROP_TEXTURE_TO_64x64 (0)
#define DEBUG_RESIZE_TEXTURE (0)
#define DEBUG_RESIZE_TEXTURE (1)
#define DEBUG_EXTRACT_SINGLE_BLOCK (0)
namespace basisu
@@ -319,7 +319,7 @@ namespace basisu
#endif
#if DEBUG_RESIZE_TEXTURE
image temp_img((file_image.get_width() + 3) / 4, (file_image.get_height() + 3) / 4);
image temp_img((file_image.get_width() + 1) / 2, (file_image.get_height() + 1) / 2);
image_resample(file_image, temp_img, m_params.m_perceptual, "kaiser");
temp_img.swap(file_image);
#endif
+86 -7
View File
@@ -156,6 +156,8 @@ namespace basisu
find_optimal_selector_clusters_for_each_block();
introduce_special_selector_clusters();
if (!m_params.m_faster)
{
if (!refine_block_endpoints_given_selectors())
@@ -181,6 +183,80 @@ namespace basisu
return true;
}
void basisu_frontend::introduce_special_selector_clusters()
{
debug_printf("optimize_selector_codebook\n");
if (m_params.m_pGlobal_sel_codebook)
return;
uint32_t total_blocks_relocated = 0;
// Make sure the selector codebook always has pure flat blocks for each possible selector, to avoid obvious artifacts.
// optimize_selector_codebook() will clean up any redundant clusters we create here.
for (uint32_t sel = 0; sel < 4; sel++)
{
etc_block blk;
clear_obj(blk);
for (uint32_t j = 0; j < 16; j++)
blk.set_selector(j & 3, j >> 2, sel);
int k;
for (k = 0; k < m_optimized_cluster_selectors.size(); k++)
if (m_optimized_cluster_selectors[k].get_raw_selector_bits() == blk.get_raw_selector_bits())
break;
if (k < m_optimized_cluster_selectors.size())
continue;
const uint32_t new_selector_cluster_index = (uint32_t)m_optimized_cluster_selectors.size();
m_optimized_cluster_selectors.push_back(blk);
vector_ensure_element_is_valid(m_selector_cluster_indices, new_selector_cluster_index);
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
if (m_orig_encoded_blocks[block_index].get_raw_selector_bits() != blk.get_raw_selector_bits())
continue;
// See if using flat selectors actually decreases the block's error.
const uint32_t old_selector_cluster_index = m_block_selector_cluster_index[block_index];
etc_block cur_blk;
const uint32_t endpoint_cluster_index = get_subblock_endpoint_cluster_index(block_index, 0);
cur_blk.set_block_color5_etc1s(get_endpoint_cluster_unscaled_color(endpoint_cluster_index, false));
cur_blk.set_inten_tables_etc1s(get_endpoint_cluster_inten_table(endpoint_cluster_index, false));
cur_blk.set_raw_selector_bits(get_selector_cluster_selector_bits(old_selector_cluster_index).get_raw_selector_bits());
const uint64_t cur_err = cur_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
cur_blk.set_raw_selector_bits(blk.get_raw_selector_bits());
const uint64_t new_err = cur_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
if (new_err >= cur_err)
continue;
// Change the block to use the new cluster
m_block_selector_cluster_index[block_index] = new_selector_cluster_index;
m_selector_cluster_indices[new_selector_cluster_index].push_back(block_index);
int j = vector_find(m_selector_cluster_indices[old_selector_cluster_index], block_index);
if (j >= 0)
m_selector_cluster_indices[old_selector_cluster_index].erase(m_selector_cluster_indices[old_selector_cluster_index].begin() + j);
total_blocks_relocated++;
m_encoded_blocks[block_index].set_raw_selector_bits(blk.get_raw_selector_bits());
} // block_index
} // sel
debug_printf("Total blocks relocated to new flat selector clusters: %u\n", total_blocks_relocated);
}
void basisu_frontend::optimize_selector_codebook()
{
debug_printf("optimize_selector_codebook\n");
@@ -233,21 +309,23 @@ namespace basisu
if (m_optimized_cluster_selector_global_cb_ids.size())
new_optimized_cluster_selector_global_cb_ids[i] = m_optimized_cluster_selector_global_cb_ids[new_to_old[i]];
if (m_selector_cluster_indices.size())
new_selector_cluster_indices[i] = m_selector_cluster_indices[new_to_old[i]];
if (m_selector_cluster_uses_global_cb.size())
new_selector_cluster_uses_global_cb[i] = m_selector_cluster_uses_global_cb[new_to_old[i]];
}
for (uint32_t i = 0; i < m_block_selector_cluster_index.size(); i++)
{
m_block_selector_cluster_index[i] = old_to_new[m_block_selector_cluster_index[i]];
if (m_selector_cluster_indices.size())
new_selector_cluster_indices[m_block_selector_cluster_index[i]].push_back(i);
}
m_optimized_cluster_selectors.swap(new_optimized_cluster_selectors);
m_optimized_cluster_selector_global_cb_ids.swap(new_optimized_cluster_selector_global_cb_ids);
m_selector_cluster_indices.swap(new_selector_cluster_indices);
m_selector_cluster_uses_global_cb.swap(new_selector_cluster_uses_global_cb);
for (uint32_t i = 0; i < m_block_selector_cluster_index.size(); i++)
m_block_selector_cluster_index[i] = old_to_new[m_block_selector_cluster_index[i]];
debug_printf("optimize_selector_codebook: Before: %u After: %u\n", orig_total_selector_clusters, total_new_entries);
}
@@ -1722,7 +1800,8 @@ namespace basisu
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
#define CHECK(x) do { if (!(x)) return false; } while(0)
//#define CHECK(x) do { if (!(x)) { DebugBreak(); return false; } } while(0)
#define CHECK(x) BASISU_FRONTEND_VERIFY(x);
CHECK(get_output_block(block_index).get_flip_bit() == true);
+1
View File
@@ -290,6 +290,7 @@ namespace basisu
uint32_t refine_block_endpoints_given_selectors();
void finalize();
bool validate_output() const;
void introduce_special_selector_clusters();
void optimize_selector_codebook();
bool check_etc1s_constraints() const;
};
+74 -19
View File
@@ -33,10 +33,12 @@
#define BASISD_WRITE_NEW_DXT1_TABLES 0
#define BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES 0
#define BASISD_ENABLE_DEBUG_FLAGS 1
namespace basisu
{
static bool g_debug_printf;
void enable_debug_printf(bool enabled)
{
g_debug_printf = enabled;
@@ -60,7 +62,28 @@ namespace basisu
namespace basist
{
#include "basisu_transcoder_tables_bc7_m6.inc"
#if BASISD_ENABLE_DEBUG_FLAGS
static uint32_t g_debug_flags = 0;
#endif
uint32_t get_debug_flags()
{
#if BASISD_ENABLE_DEBUG_FLAGS
return g_debug_flags;
#else
return 0;
#endif
}
void set_debug_flags(uint32_t f)
{
(void)f;
#if BASISD_ENABLE_DEBUG_FLAGS
g_debug_flags = f;
#endif
}
uint16_t crc16(const void *r, size_t size, uint16_t crc)
{
crc = ~crc;
@@ -1718,7 +1741,7 @@ namespace basist
const color32 base_color(pSrc_block->get_base5_color_unscaled());
const uint32_t inten_table = pSrc_block->get_inten_table(0);
if (low_selector == high_selector)
{
color32 block_colors[4];
@@ -1742,7 +1765,7 @@ namespace basist
// Make l > h
if (min16 > 0)
min16--;
else
else
{
// l = h = 0
assert(min16 == max16 && max16 == 0);
@@ -1751,7 +1774,7 @@ namespace basist
min16 = 0;
mask = 0x55;
}
assert(max16 > min16);
}
@@ -1760,7 +1783,7 @@ namespace basist
std::swap(max16, min16);
mask ^= 0x55;
}
pDst_block->set_low_color(static_cast<uint16_t>(max16));
pDst_block->set_high_color(static_cast<uint16_t>(min16));
pDst_block->m_selectors[0] = static_cast<uint8_t>(mask);
@@ -1796,28 +1819,28 @@ namespace basist
{
min16--;
l = 0;
l = 0;
h = 0;
}
else
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;
l = 1;
h = 0;
}
@@ -1966,6 +1989,28 @@ namespace basist
pDst_block->m_selectors[3] = (uint8_t)dxt1_sels3;
#endif
}
#if BASISD_ENABLE_DEBUG_FLAGS
static void convert_etc1s_to_dxt1_vis(dxt1_block* pDst_block, const decoder_etc_block* pSrc_block, const selector* pSelector, bool use_threecolor_blocks)
{
convert_etc1s_to_dxt1(pDst_block, pSrc_block, pSelector, use_threecolor_blocks);
if (g_debug_flags & cDebugFlagVisBC1Sels)
{
uint32_t l = dxt1_block::pack_unscaled_color(31, 63, 31);
uint32_t h = dxt1_block::pack_unscaled_color(0, 0, 0);
pDst_block->set_low_color(static_cast<uint16_t>(l));
pDst_block->set_high_color(static_cast<uint16_t>(h));
}
else if (g_debug_flags & cDebugFlagVisBC1Endpoints)
{
for (uint32_t y = 0; y < 4; y++)
for (uint32_t x = 0; x < 4; x++)
pDst_block->set_selector(x, y, (y < 2) ? 0 : 1);
}
}
#endif
#endif
static dxt_selector_range s_dxt5a_selector_ranges[] =
@@ -3927,15 +3972,18 @@ namespace basist
if (is_video)
(*pPrevFrameIndices)[block_x + block_y * num_blocks_x] = endpoint_index | (selector_index << 16);
#if 0
// Visualize CR's
if ((is_video) && (pred == 2))
#if BASISD_ENABLE_DEBUG_FLAGS
if ((g_debug_flags & cDebugFlagVisCRs) && ((fmt == cETC1) || (fmt == cBC1)))
{
decoder_etc_block* pDst_block = reinterpret_cast<decoder_etc_block*>(static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * num_blocks_x) * output_stride);
memset(pDst_block, 0xFF, 8);
continue;
// Visualize CR's
if ((is_video) && (pred == 2))
{
decoder_etc_block* pDst_block = reinterpret_cast<decoder_etc_block*>(static_cast<uint8_t*>(pDst_blocks) + (block_x + block_y * num_blocks_x) * output_stride);
memset(pDst_block, 0xFF, 8);
continue;
}
}
#endif
#endif
const endpoint *pEndpoint0 = &m_endpoints[endpoint_index];
@@ -3964,8 +4012,15 @@ namespace basist
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;
#if BASISD_SUPPORT_DXT1
convert_etc1s_to_dxt1(static_cast<dxt1_block*>(pDst_block), &block, pSelector, bc1_allow_threecolor_blocks);
#if BASISD_ENABLE_DEBUG_FLAGS
if (g_debug_flags & (cDebugFlagVisBC1Sels | cDebugFlagVisBC1Endpoints))
convert_etc1s_to_dxt1_vis(static_cast<dxt1_block*>(pDst_block), &block, pSelector, bc1_allow_threecolor_blocks);
else
#endif
convert_etc1s_to_dxt1(static_cast<dxt1_block*>(pDst_block), &block, pSelector, bc1_allow_threecolor_blocks);
#else
assert(0);
#endif
+9
View File
@@ -304,4 +304,13 @@ namespace basist
// basisu_transcoder_init() must be called before a .basis file can be transcoded.
void basisu_transcoder_init();
enum debug_flags_t
{
cDebugFlagVisCRs = 1,
cDebugFlagVisBC1Sels = 2,
cDebugFlagVisBC1Endpoints = 4
};
uint32_t get_debug_flags();
void set_debug_flags(uint32_t f);
} // namespace basisu
File diff suppressed because one or more lines are too long
Binary file not shown.
+3
View File
@@ -29,6 +29,9 @@ extern "C"
uint basis_transcode_image(void *h, void *dst, uint dst_size_in_bytes,
uint image_index, uint level_index, uint format,
uint pvrtc_wrap_addressing, uint get_alpha_for_opaque_formats);
void basis_set_debug_flags(uint f) { basist::set_debug_flags(f); }
uint basis_get_debug_flags() { return basist::get_debug_flags(); }
}
void basis_init()
+1 -1
View File
@@ -1,3 +1,3 @@
@REM -O0 -s ASSERTIONS=1 -s DEMANGLE_SUPPORT=1
@REM -O2 -s ASSERTIONS=0
emcc -s EXPORTED_FUNCTIONS="['allocate', '_malloc', '_free', '_basis_init','_basis_open','_basis_close','_basis_get_has_alpha','_basis_get_num_images','_basis_get_num_levels','_basis_get_image_width','_basis_get_image_height','_basis_get_image_transcoded_size_in_bytes','_basis_transcode_image','_basis_start_transcoding']" -o basis.js ../transcoder/basisu_transcoder.cpp basis_wrappers.cpp -s TOTAL_MEMORY=60000000 -O2 -s ASSERTIONS=0 -I ../transcoder
emcc -s EXPORTED_FUNCTIONS="['allocate', '_malloc', '_free', '_basis_init','_basis_open','_basis_close','_basis_get_has_alpha','_basis_get_num_images','_basis_get_num_levels','_basis_get_image_width','_basis_get_image_height','_basis_get_image_transcoded_size_in_bytes','_basis_transcode_image','_basis_start_transcoding','_basis_get_debug_flags','_basis_set_debug_flags']" -o basis.js ../transcoder/basisu_transcoder.cpp basis_wrappers.cpp -s TOTAL_MEMORY=80000000 -O2 -s ASSERTIONS=0 -I ../transcoder
+1 -1
View File
@@ -4,7 +4,7 @@
~/emscripten_tutorial/emscripten/emcc \
-s EXPORTED_FUNCTIONS="['allocate', '_malloc', '_free', '_basis_init','_basis_open','_basis_close','_basis_get_has_alpha','_basis_get_num_images','_basis_get_num_levels','_basis_get_image_width','_basis_get_image_height','_basis_get_image_transcoded_size_in_bytes','_basis_transcode_image','_basis_start_transcoding']" \
-s TOTAL_MEMORY=60000000 -O2 -s ASSERTIONS=0 -I ../transcoder \
-s TOTAL_MEMORY=80000000 -O2 -s ASSERTIONS=0 -I ../transcoder \
-o basis.js \
../transcoder/basisu_transcoder.cpp basis_wrappers.cpp && \
chmod -R a+rX .
+39 -4
View File
@@ -98,6 +98,12 @@ BASIS_FORMAT = {
cTFBC5: 7,
};
BASIS_DEBUG_FLAGS = {
DEBUG_FLAG_VIS_CR: 1,
DEBUG_FLAG_VIS_SELS: 2,
DEBUG_FLAG_VIS_ENDPOINTS: 4
};
BASIS_FORMAT_NAMES = {};
for (var name in BASIS_FORMAT) {
BASIS_FORMAT_NAMES[BASIS_FORMAT[name]] = name;
@@ -190,9 +196,9 @@ function frame(now)
redraw()
timeSinceLastFrame += deltaTime;
if (timeSinceLastFrame > 1.0/25.0)
if (timeSinceLastFrame > 1.0/24.0)
{
timeSinceLastFrame -= 1.0/25.0;
timeSinceLastFrame -= 1.0/24.0;
curImageIndex++;
if (curImageIndex == images)
@@ -265,6 +271,9 @@ function dataLoaded(data)
log('Decoding .basis data to BC1');
}
log('.basis file size: ' + srcSize);
if (levels == 1)
log('average bits/texel: ' + ((srcSize * 8.0) / (width * height * images)));
log('width: ' + width);
log('height: ' + height);
log('images: ' + images);
@@ -347,6 +356,27 @@ function alphaBlend() { drawMode = 0; redraw(); }
function viewRGB() { drawMode = 1; redraw(); }
function viewAlpha() { drawMode = 2; redraw(); }
function visCR()
{
var i = Module._basis_get_debug_flags();
i = i ^ BASIS_DEBUG_FLAGS.DEBUG_FLAG_VIS_CR;
Module._basis_set_debug_flags(i);
}
function visSels()
{
var i = Module._basis_get_debug_flags();
i = i ^ BASIS_DEBUG_FLAGS.DEBUG_FLAG_VIS_SELS;
Module._basis_set_debug_flags(i);
}
function visEndpoints()
{
var i = Module._basis_get_debug_flags();
i ^= BASIS_DEBUG_FLAGS.DEBUG_FLAG_VIS_ENDPOINTS;
Module._basis_set_debug_flags(i);
}
</script>
</head>
<body onload="initialize()">
@@ -360,14 +390,19 @@ function viewAlpha() { drawMode = 2; redraw(); }
<br>
<br>
.basis file:
<input id="file" type="text" size=30 value="pic0001.basis"></input>
<input id="file" type="text" size=30 value="2010_2.basis"></input>
<input type="button" value="Run!" onclick="run()"></input>
<br>
<br>
<input type="button" value="Alpha blend" onclick="alphaBlend()"></input>
<input type="button" value="View RGB" onclick="viewRGB()"></input>
<input type="button" value="View Alpha" onclick="viewAlpha()"></input>
<br>
<br>
<input type="button" value="Visualize CR's" onclick="visCR()"></input>
<input type="button" value="Visualize Selectors" onclick="visSels()"></input>
<input type="button" value="Visualize Endpoints" onclick="visEndpoints()"></input>
<div style="position:absolute; left: 525px; top:130px; font-size: 20pt; font-weight: bold; color: red">
<div id="nodxt" style="display: none; width: 768px; font-size: 20pt; font-weight: bold; color: red">
NOTE: Your browser does not support DXT, so using RGB565