mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-09-18 00:14:28 +00:00
Merge branch 'branch'
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user