mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-10-29 04:05:32 +00:00
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:
+2
-2
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
@@ -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,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
|
||||
|
||||
@@ -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 .
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user