Merge branch 'branch'

This commit is contained in:
Rich Geldreich
2021-03-30 14:53:22 -04:00
14 changed files with 719 additions and 147 deletions

View File

@@ -183,8 +183,16 @@ namespace basisu
basisu_frontend& r = *m_pFront_end;
//const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
//if ((total_block_endpoints_remapped) && (m_params.m_compression_level > 0))
if ((total_block_endpoints_remapped) && (m_params.m_compression_level > 1))
if (m_params.m_used_global_codebooks)
{
m_endpoint_remap_table_old_to_new.resize(r.get_total_endpoint_clusters());
for (uint32_t i = 0; i < r.get_total_endpoint_clusters(); i++)
m_endpoint_remap_table_old_to_new[i] = i;
}
else
{
//if ((total_block_endpoints_remapped) && (m_params.m_compression_level > 0))
if ((total_block_endpoints_remapped) && (m_params.m_compression_level > 1))
{
// We've changed the block endpoint indices, so we need to go and adjust the endpoint codebook (remove unused entries, optimize existing entries that have changed)
uint_vec new_block_endpoints(get_total_blocks());
@@ -236,6 +244,7 @@ namespace basisu
palette_index_reorderer reorderer;
reorderer.init((uint32_t)all_endpoint_indices.size(), &all_endpoint_indices[0], r.get_total_endpoint_clusters(), nullptr, nullptr, 0);
m_endpoint_remap_table_old_to_new = reorderer.get_remap_table();
}
m_endpoint_remap_table_new_to_old.resize(r.get_total_endpoint_clusters());
for (uint32_t i = 0; i < m_endpoint_remap_table_old_to_new.size(); i++)
@@ -248,7 +257,7 @@ namespace basisu
m_selector_remap_table_new_to_old.resize(r.get_total_selector_clusters());
if (m_params.m_compression_level == 0)
if ((m_params.m_compression_level == 0) || (m_params.m_used_global_codebooks))
{
for (uint32_t i = 0; i < r.get_total_selector_clusters(); i++)
m_selector_remap_table_new_to_old[i] = i;
@@ -1115,7 +1124,7 @@ namespace basisu
total_used_selector_history_buf, total_used_selector_history_buf * 100.0f / get_total_blocks());
//if ((total_endpoint_indices_remapped) && (m_params.m_compression_level > 0))
if ((total_endpoint_indices_remapped) && (m_params.m_compression_level > 1))
if ((total_endpoint_indices_remapped) && (m_params.m_compression_level > 1) && (!m_params.m_used_global_codebooks))
{
int_vec unused;
r.reoptimize_remapped_endpoints(block_endpoint_indices, unused, false, &block_selector_indices);
@@ -1676,6 +1685,7 @@ namespace basisu
//const bool is_video = m_pFront_end->get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
m_output.m_slice_desc = m_slices;
m_output.m_etc1s = m_params.m_etc1s;
m_output.m_uses_global_codebooks = m_params.m_used_global_codebooks;
create_endpoint_palette();
create_selector_palette();

View File

@@ -84,6 +84,7 @@ namespace basisu
uint32_t m_global_sel_codebook_mod_bits;
bool m_use_hybrid_sel_codebooks;
bool m_used_global_codebooks;
basisu_backend_params()
{
clear();
@@ -102,6 +103,7 @@ namespace basisu
m_global_sel_codebook_pal_bits = ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS;
m_global_sel_codebook_mod_bits = basist::etc1_global_palette_entry_modifier::cTotalBits;
m_use_hybrid_sel_codebooks = false;
m_used_global_codebooks = false;
}
};
@@ -142,6 +144,7 @@ namespace basisu
basist::basis_tex_format m_tex_format;
bool m_etc1s;
bool m_uses_global_codebooks;
uint32_t m_num_endpoints;
uint32_t m_num_selectors;
@@ -164,6 +167,7 @@ namespace basisu
{
m_tex_format = basist::basis_tex_format::cETC1S;
m_etc1s = false;
m_uses_global_codebooks = false;
m_num_endpoints = 0;
m_num_selectors = 0;
@@ -201,6 +205,7 @@ namespace basisu
uint32_t encode();
const basisu_backend_output &get_output() const { return m_output; }
const basisu_backend_params& get_params() const { return m_params; }
private:
basisu_frontend *m_pFront_end;

View File

@@ -47,6 +47,8 @@ namespace basisu
if (y_flipped)
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagYFlipped;
if (encoder_output.m_uses_global_codebooks)
m_header.m_flags = m_header.m_flags | basist::cBASISHeaderFlagUsesGlobalCodebook;
for (uint32_t i = 0; i < encoder_output.m_slice_desc.size(); i++)
{
@@ -64,12 +66,26 @@ namespace basisu
m_header.m_userdata1 = userdata1;
m_header.m_total_endpoints = encoder_output.m_num_endpoints;
if (!encoder_output.m_uses_global_codebooks)
{
m_header.m_endpoint_cb_file_ofs = m_endpoint_cb_file_ofs;
m_header.m_endpoint_cb_file_size = (uint32_t)encoder_output.m_endpoint_palette.size();
}
else
{
assert(!m_endpoint_cb_file_ofs);
}
m_header.m_total_selectors = encoder_output.m_num_selectors;
if (!encoder_output.m_uses_global_codebooks)
{
m_header.m_selector_cb_file_ofs = m_selector_cb_file_ofs;
m_header.m_selector_cb_file_size = (uint32_t)encoder_output.m_selector_palette.size();
}
else
{
assert(!m_selector_cb_file_ofs);
}
m_header.m_tables_file_ofs = m_tables_file_ofs;
m_header.m_tables_file_size = (uint32_t)encoder_output.m_slice_image_tables.size();
@@ -134,6 +150,8 @@ namespace basisu
assert(m_comp_data.size() == m_slice_descs_file_ofs);
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&m_images_descs[0]), m_images_descs.size() * sizeof(m_images_descs[0]));
if (!encoder_output.m_uses_global_codebooks)
{
if (encoder_output.m_endpoint_palette.size())
{
assert(m_comp_data.size() == m_endpoint_cb_file_ofs);
@@ -144,6 +162,7 @@ namespace basisu
{
assert(m_comp_data.size() == m_selector_cb_file_ofs);
append_vector(m_comp_data, reinterpret_cast<const uint8_t*>(&encoder_output.m_selector_palette[0]), encoder_output.m_selector_palette.size());
}
}
if (encoder_output.m_slice_image_tables.size())
@@ -179,8 +198,17 @@ namespace basisu
const basisu_backend_slice_desc_vec &slice_descs = encoder_output.m_slice_desc;
// The Basis file uses 32-bit fields for lots of stuff, so make sure it's not too large.
uint64_t check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
uint64_t check_size = 0;
if (!encoder_output.m_uses_global_codebooks)
{
check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
(uint64_t)encoder_output.m_endpoint_palette.size() + (uint64_t)encoder_output.m_selector_palette.size() + (uint64_t)encoder_output.m_slice_image_tables.size();
}
else
{
check_size = (uint64_t)sizeof(basist::basis_file_header) + (uint64_t)sizeof(basist::basis_slice_desc) * slice_descs.size() +
(uint64_t)encoder_output.m_slice_image_tables.size();
}
if (check_size >= 0xFFFF0000ULL)
{
error_printf("basisu_file::init: File is too large!\n");
@@ -191,9 +219,18 @@ namespace basisu
m_slice_descs_file_ofs = sizeof(basist::basis_file_header);
if (encoder_output.m_tex_format == basist::basis_tex_format::cETC1S)
{
if (encoder_output.m_uses_global_codebooks)
{
m_endpoint_cb_file_ofs = 0;
m_selector_cb_file_ofs = 0;
m_tables_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
}
else
{
m_endpoint_cb_file_ofs = m_slice_descs_file_ofs + sizeof(basist::basis_slice_desc) * (uint32_t)slice_descs.size();
m_selector_cb_file_ofs = m_endpoint_cb_file_ofs + (uint32_t)encoder_output.m_endpoint_palette.size();
m_tables_file_ofs = m_selector_cb_file_ofs + (uint32_t)encoder_output.m_selector_palette.size();
}
m_first_image_file_ofs = m_tables_file_ofs + (uint32_t)encoder_output.m_slice_image_tables.size();
}
else

View File

@@ -61,6 +61,7 @@ namespace basisu
PRINT_BOOL_VALUE(m_uastc);
PRINT_BOOL_VALUE(m_y_flip);
PRINT_BOOL_VALUE(m_debug);
PRINT_BOOL_VALUE(m_validate);
PRINT_BOOL_VALUE(m_debug_images);
PRINT_BOOL_VALUE(m_global_sel_pal);
PRINT_BOOL_VALUE(m_auto_global_sel_pal);
@@ -121,6 +122,11 @@ namespace basisu
PRINT_BOOL_VALUE(m_rdo_uastc_multithreading);
PRINT_FLOAT_VALUE(m_resample_factor);
printf("Has global codebooks: %u\n", m_params.m_pGlobal_codebooks ? 1 : 0);
if (m_params.m_pGlobal_codebooks)
{
printf("Global codebook endpoints: %u selectors: %u\n", m_params.m_pGlobal_codebooks->get_endpoints().size(), m_params.m_pGlobal_codebooks->get_selectors().size());
}
#undef PRINT_BOOL_VALUE
#undef PRINT_INT_VALUE
@@ -1006,7 +1012,9 @@ namespace basisu
p.m_tex_type = m_params.m_tex_type;
p.m_multithreaded = m_params.m_multithreading;
p.m_disable_hierarchical_endpoint_codebooks = m_params.m_disable_hierarchical_endpoint_codebooks;
p.m_validate = m_params.m_validate;
p.m_pJob_pool = m_params.m_pJob_pool;
p.m_pGlobal_codebooks = m_params.m_pGlobal_codebooks;
if ((m_params.m_global_sel_pal) || (m_auto_global_sel_pal))
{
@@ -1113,6 +1121,7 @@ namespace basisu
backend_params.m_global_sel_codebook_pal_bits = m_frontend.get_params().m_num_global_sel_codebook_pal_bits;
backend_params.m_global_sel_codebook_mod_bits = m_frontend.get_params().m_num_global_sel_codebook_mod_bits;
backend_params.m_use_hybrid_sel_codebooks = m_frontend.get_params().m_use_hybrid_selector_codebooks;
backend_params.m_used_global_codebooks = m_frontend.get_params().m_pGlobal_codebooks != nullptr;
m_backend.init(&m_frontend, backend_params, m_slice_descs, m_params.m_pSel_codebook);
uint32_t total_packed_bytes = m_backend.encode();
@@ -1166,6 +1175,10 @@ namespace basisu
m_decoded_output_textures_unpacked_bc7.resize(m_slice_descs.size());
tm.start();
if (m_params.m_pGlobal_codebooks)
{
decoder.set_global_codebooks(m_params.m_pGlobal_codebooks);
}
if (!decoder.start_transcoding(&comp_data[0], (uint32_t)comp_data.size()))
{

View File

@@ -230,6 +230,7 @@ namespace basisu
m_y_flip.clear();
m_debug.clear();
m_validate.clear();
m_debug_images.clear();
m_global_sel_pal.clear();
m_auto_global_sel_pal.clear();
@@ -289,6 +290,7 @@ namespace basisu
m_resample_factor.clear();
m_pGlobal_codebooks = nullptr;
m_pJob_pool = nullptr;
}
@@ -319,6 +321,7 @@ namespace basisu
// Output debug information during compression
bool_param<false> m_debug;
bool_param<false> m_validate;
// m_debug_images is pretty slow
bool_param<false> m_debug_images;
@@ -407,6 +410,7 @@ namespace basisu
bool_param<true> m_rdo_uastc_multithreading;
param<float> m_resample_factor;
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
job_pool *m_pJob_pool;
};

View File

@@ -196,107 +196,114 @@ namespace basisu
init_etc1_images();
init_endpoint_training_vectors();
generate_endpoint_clusters();
for (uint32_t refine_endpoint_step = 0; refine_endpoint_step < m_num_endpoint_codebook_iterations; refine_endpoint_step++)
if (m_params.m_pGlobal_codebooks)
{
BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
init_global_codebooks();
}
else
{
init_endpoint_training_vectors();
if (refine_endpoint_step)
generate_endpoint_clusters();
for (uint32_t refine_endpoint_step = 0; refine_endpoint_step < m_num_endpoint_codebook_iterations; refine_endpoint_step++)
{
introduce_new_endpoint_clusters();
}
BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
generate_endpoint_codebook(refine_endpoint_step);
if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
{
char buf[256];
snprintf(buf, sizeof(buf), "endpoint_cluster_vis_pre_%u.png", refine_endpoint_step);
dump_endpoint_clusterization_visualization(buf, false);
}
bool early_out = false;
if (m_endpoint_refinement)
{
//dump_endpoint_clusterization_visualization("endpoint_clusters_before_refinement.png");
if (!refine_endpoint_clusterization())
early_out = true;
if ((m_params.m_tex_type == basist::cBASISTexTypeVideoFrames) && (!refine_endpoint_step) && (m_num_endpoint_codebook_iterations == 1))
if (refine_endpoint_step)
{
eliminate_redundant_or_empty_endpoint_clusters();
generate_endpoint_codebook(refine_endpoint_step);
introduce_new_endpoint_clusters();
}
generate_endpoint_codebook(refine_endpoint_step);
if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
{
char buf[256];
snprintf(buf, sizeof(buf), "endpoint_cluster_vis_post_%u.png", refine_endpoint_step);
snprintf(buf, sizeof(buf), "endpoint_cluster_vis_pre_%u.png", refine_endpoint_step);
dump_endpoint_clusterization_visualization(buf, false);
snprintf(buf, sizeof(buf), "endpoint_cluster_colors_vis_post_%u.png", refine_endpoint_step);
dump_endpoint_clusterization_visualization(buf, true);
}
}
bool early_out = false;
if (m_endpoint_refinement)
{
//dump_endpoint_clusterization_visualization("endpoint_clusters_before_refinement.png");
if (!refine_endpoint_clusterization())
early_out = true;
if ((m_params.m_tex_type == basist::cBASISTexTypeVideoFrames) && (!refine_endpoint_step) && (m_num_endpoint_codebook_iterations == 1))
{
eliminate_redundant_or_empty_endpoint_clusters();
generate_endpoint_codebook(refine_endpoint_step);
}
if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
{
char buf[256];
snprintf(buf, sizeof(buf), "endpoint_cluster_vis_post_%u.png", refine_endpoint_step);
dump_endpoint_clusterization_visualization(buf, false);
snprintf(buf, sizeof(buf), "endpoint_cluster_colors_vis_post_%u.png", refine_endpoint_step);
dump_endpoint_clusterization_visualization(buf, true);
}
}
eliminate_redundant_or_empty_endpoint_clusters();
eliminate_redundant_or_empty_endpoint_clusters();
if (m_params.m_debug_stats)
debug_printf("Total endpoint clusters: %u\n", (uint32_t)m_endpoint_clusters.size());
if (m_params.m_debug_stats)
debug_printf("Total endpoint clusters: %u\n", (uint32_t)m_endpoint_clusters.size());
if (early_out)
break;
}
if (early_out)
break;
}
BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
generate_block_endpoint_clusters();
generate_block_endpoint_clusters();
create_initial_packed_texture();
create_initial_packed_texture();
generate_selector_clusters();
generate_selector_clusters();
if (m_use_hierarchical_selector_codebooks)
compute_selector_clusters_within_each_parent_cluster();
if (m_use_hierarchical_selector_codebooks)
compute_selector_clusters_within_each_parent_cluster();
if (m_params.m_compression_level == 0)
{
create_optimized_selector_codebook(0);
find_optimal_selector_clusters_for_each_block();
introduce_special_selector_clusters();
}
else
{
const uint32_t num_refine_selector_steps = m_params.m_pGlobal_sel_codebook ? 1 : m_num_selector_codebook_iterations;
for (uint32_t refine_selector_steps = 0; refine_selector_steps < num_refine_selector_steps; refine_selector_steps++)
if (m_params.m_compression_level == 0)
{
create_optimized_selector_codebook(refine_selector_steps);
create_optimized_selector_codebook(0);
find_optimal_selector_clusters_for_each_block();
introduce_special_selector_clusters();
if ((m_params.m_compression_level >= 4) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
}
else
{
const uint32_t num_refine_selector_steps = m_params.m_pGlobal_sel_codebook ? 1 : m_num_selector_codebook_iterations;
for (uint32_t refine_selector_steps = 0; refine_selector_steps < num_refine_selector_steps; refine_selector_steps++)
{
if (!refine_block_endpoints_given_selectors())
break;
create_optimized_selector_codebook(refine_selector_steps);
find_optimal_selector_clusters_for_each_block();
introduce_special_selector_clusters();
if ((m_params.m_compression_level >= 4) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
{
if (!refine_block_endpoints_given_selectors())
break;
}
}
}
optimize_selector_codebook();
if (m_params.m_debug_stats)
debug_printf("Total selector clusters: %u\n", (uint32_t)m_selector_cluster_block_indices.size());
}
optimize_selector_codebook();
if (m_params.m_debug_stats)
debug_printf("Total selector clusters: %u\n", (uint32_t)m_selector_cluster_block_indices.size());
finalize();
if (m_params.m_validate)
@@ -310,6 +317,258 @@ namespace basisu
return true;
}
bool basisu_frontend::init_global_codebooks()
{
const basist::basisu_lowlevel_etc1s_transcoder* pTranscoder = m_params.m_pGlobal_codebooks;
const basist::basisu_lowlevel_etc1s_transcoder::endpoint_vec& endpoints = pTranscoder->get_endpoints();
const basist::basisu_lowlevel_etc1s_transcoder::selector_vec& selectors = pTranscoder->get_selectors();
m_endpoint_cluster_etc_params.resize(endpoints.size());
for (uint32_t i = 0; i < endpoints.size(); i++)
{
m_endpoint_cluster_etc_params[i].m_inten_table[0] = endpoints[i].m_inten5;
m_endpoint_cluster_etc_params[i].m_inten_table[1] = endpoints[i].m_inten5;
m_endpoint_cluster_etc_params[i].m_color_unscaled[0].set(endpoints[i].m_color5.r, endpoints[i].m_color5.g, endpoints[i].m_color5.b, 255);
m_endpoint_cluster_etc_params[i].m_color_used[0] = true;
m_endpoint_cluster_etc_params[i].m_valid = true;
}
m_optimized_cluster_selectors.resize(selectors.size());
for (uint32_t i = 0; i < m_optimized_cluster_selectors.size(); i++)
{
for (uint32_t y = 0; y < 4; y++)
for (uint32_t x = 0; x < 4; x++)
m_optimized_cluster_selectors[i].set_selector(x, y, selectors[i].get_selector(x, y));
}
m_block_endpoint_clusters_indices.resize(m_total_blocks);
m_orig_encoded_blocks.resize(m_total_blocks);
m_block_selector_cluster_index.resize(m_total_blocks);
#if 0
for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
{
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job([this, first_index, last_index] {
#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
const etc_block& blk = m_etc1_blocks_etc1s[block_index];
const uint32_t block_endpoint_index = m_block_endpoint_clusters_indices[block_index][0];
etc_block trial_blk;
trial_blk.set_block_color5_etc1s(blk.m_color_unscaled[0]);
trial_blk.set_flip_bit(true);
uint64_t best_err = UINT64_MAX;
uint32_t best_index = 0;
for (uint32_t i = 0; i < m_optimized_cluster_selectors.size(); i++)
{
trial_blk.set_raw_selector_bits(m_optimized_cluster_selectors[i].get_raw_selector_bits());
const uint64_t cur_err = trial_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
if (cur_err < best_err)
{
best_err = cur_err;
best_index = i;
if (!cur_err)
break;
}
} // block_index
m_block_selector_cluster_index[block_index] = best_index;
}
#ifndef __EMSCRIPTEN__
});
#endif
}
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
#endif
m_encoded_blocks.resize(m_total_blocks);
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
const uint32_t endpoint_index = m_block_endpoint_clusters_indices[block_index][0];
const uint32_t selector_index = m_block_selector_cluster_index[block_index];
etc_block& blk = m_encoded_blocks[block_index];
blk.set_block_color5_etc1s(m_endpoint_cluster_etc_params[endpoint_index].m_color_unscaled[0]);
blk.set_inten_tables_etc1s(m_endpoint_cluster_etc_params[endpoint_index].m_inten_table[0]);
blk.set_flip_bit(true);
blk.set_raw_selector_bits(m_optimized_cluster_selectors[selector_index].get_raw_selector_bits());
}
#endif
const uint32_t NUM_PASSES = 3;
for (uint32_t pass = 0; pass < NUM_PASSES; pass++)
{
debug_printf("init_global_codebooks: pass %u\n", pass);
const uint32_t N = 128;
for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
{
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job([this, first_index, last_index, pass] {
#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
const etc_block& blk = pass ? m_encoded_blocks[block_index] : m_etc1_blocks_etc1s[block_index];
const uint32_t blk_raw_selector_bits = blk.get_raw_selector_bits();
etc_block trial_blk(blk);
trial_blk.set_raw_selector_bits(blk_raw_selector_bits);
trial_blk.set_flip_bit(true);
uint64_t best_err = UINT64_MAX;
uint32_t best_index = 0;
etc_block best_block(trial_blk);
for (uint32_t i = 0; i < m_endpoint_cluster_etc_params.size(); i++)
{
if (m_endpoint_cluster_etc_params[i].m_inten_table[0] > blk.get_inten_table(0))
continue;
trial_blk.set_block_color5_etc1s(m_endpoint_cluster_etc_params[i].m_color_unscaled[0]);
trial_blk.set_inten_tables_etc1s(m_endpoint_cluster_etc_params[i].m_inten_table[0]);
const color_rgba* pSource_pixels = get_source_pixel_block(block_index).get_ptr();
uint64_t cur_err;
if (!pass)
cur_err = trial_blk.determine_selectors(pSource_pixels, m_params.m_perceptual);
else
cur_err = trial_blk.evaluate_etc1_error(pSource_pixels, m_params.m_perceptual);
if (cur_err < best_err)
{
best_err = cur_err;
best_index = i;
best_block = trial_blk;
if (!cur_err)
break;
}
}
m_block_endpoint_clusters_indices[block_index][0] = best_index;
m_block_endpoint_clusters_indices[block_index][1] = best_index;
m_orig_encoded_blocks[block_index] = best_block;
} // block_index
#ifndef __EMSCRIPTEN__
});
#endif
}
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
#endif
m_endpoint_clusters.resize(0);
m_endpoint_clusters.resize(endpoints.size());
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
const uint32_t endpoint_cluster_index = m_block_endpoint_clusters_indices[block_index][0];
m_endpoint_clusters[endpoint_cluster_index].push_back(block_index * 2);
m_endpoint_clusters[endpoint_cluster_index].push_back(block_index * 2 + 1);
}
m_block_selector_cluster_index.resize(m_total_blocks);
for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
{
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->add_job([this, first_index, last_index, pass] {
#endif
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
const uint32_t block_endpoint_index = m_block_endpoint_clusters_indices[block_index][0];
etc_block trial_blk;
trial_blk.set_block_color5_etc1s(m_endpoint_cluster_etc_params[block_endpoint_index].m_color_unscaled[0]);
trial_blk.set_inten_tables_etc1s(m_endpoint_cluster_etc_params[block_endpoint_index].m_inten_table[0]);
trial_blk.set_flip_bit(true);
uint64_t best_err = UINT64_MAX;
uint32_t best_index = 0;
for (uint32_t i = 0; i < m_optimized_cluster_selectors.size(); i++)
{
trial_blk.set_raw_selector_bits(m_optimized_cluster_selectors[i].get_raw_selector_bits());
const uint64_t cur_err = trial_blk.evaluate_etc1_error(get_source_pixel_block(block_index).get_ptr(), m_params.m_perceptual);
if (cur_err < best_err)
{
best_err = cur_err;
best_index = i;
if (!cur_err)
break;
}
} // block_index
m_block_selector_cluster_index[block_index] = best_index;
}
#ifndef __EMSCRIPTEN__
});
#endif
}
#ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
#endif
m_encoded_blocks.resize(m_total_blocks);
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
const uint32_t endpoint_index = m_block_endpoint_clusters_indices[block_index][0];
const uint32_t selector_index = m_block_selector_cluster_index[block_index];
etc_block& blk = m_encoded_blocks[block_index];
blk.set_block_color5_etc1s(m_endpoint_cluster_etc_params[endpoint_index].m_color_unscaled[0]);
blk.set_inten_tables_etc1s(m_endpoint_cluster_etc_params[endpoint_index].m_inten_table[0]);
blk.set_flip_bit(true);
blk.set_raw_selector_bits(m_optimized_cluster_selectors[selector_index].get_raw_selector_bits());
}
} // pass
m_selector_cluster_block_indices.resize(selectors.size());
for (uint32_t block_index = 0; block_index < m_etc1_blocks_etc1s.size(); block_index++)
m_selector_cluster_block_indices[m_block_selector_cluster_index[block_index]].push_back(block_index);
return true;
}
void basisu_frontend::introduce_special_selector_clusters()
{
debug_printf("introduce_special_selector_clusters\n");

View File

@@ -18,6 +18,7 @@
#include "basisu_gpu_texture.h"
#include "basisu_global_selector_palette_helpers.h"
#include "../transcoder/basisu_file_headers.h"
#include "../transcoder/basisu_transcoder.h"
namespace basisu
{
@@ -83,6 +84,7 @@ namespace basisu
m_use_hybrid_selector_codebooks(false),
m_hybrid_codebook_quality_thresh(0.0f),
m_tex_type(basist::cBASISTexType2D),
m_pGlobal_codebooks(nullptr),
m_pJob_pool(nullptr)
{
@@ -110,6 +112,7 @@ namespace basisu
bool m_use_hybrid_selector_codebooks;
float m_hybrid_codebook_quality_thresh;
basist::basis_texture_type m_tex_type;
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
job_pool *m_pJob_pool;
};
@@ -330,6 +333,7 @@ namespace basisu
//-----------------------------------------------------------------------------
void init_etc1_images();
bool init_global_codebooks();
void init_endpoint_training_vectors();
void dump_endpoint_clusterization_visualization(const char *pFilename, bool vis_endpoint_colors);
void generate_endpoint_clusters();