mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-10-22 08:50:53 +00:00
Basis Universal v1.13:
- Optimized ETC1S encoder (3-4.5x faster) - Added optional SSE 4.1 support to encoder - Switched from std::vector to a custom vector in the encoder and transcoder - Added CppSPMD (SSE only for now) - UASTC RDO is now more effective, but the command line parameter controlling qualiy has changed (to "lambda")
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// basisu_frontend.cpp
|
||||
// Copyright (C) 2019-2020 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,11 @@
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
#if BASISU_SUPPORT_SSE
|
||||
#define CPPSPMD_NAME(a) a##_sse41
|
||||
#include "basisu_kernels_declares.h"
|
||||
#endif
|
||||
|
||||
#define BASISU_FRONTEND_VERIFY(c) do { if (!(c)) handle_verify_failure(__LINE__); } while(0)
|
||||
|
||||
namespace basisu
|
||||
@@ -32,7 +37,8 @@ namespace basisu
|
||||
//const uint32_t BASISU_MAX_SELECTOR_REFINEMENT_STEPS = 3;
|
||||
|
||||
const uint32_t BASISU_ENDPOINT_PARENT_CODEBOOK_SIZE = 16;
|
||||
const uint32_t BASISU_SELECTOR_PARENT_CODEBOOK_SIZE = 16;
|
||||
const uint32_t BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_01 = 32;
|
||||
const uint32_t BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_DEFAULT = 16;
|
||||
|
||||
// TODO - How to handle internal verifies in the basisu lib
|
||||
static inline void handle_verify_failure(int line)
|
||||
@@ -57,14 +63,14 @@ namespace basisu
|
||||
|
||||
uint32_t tv = size / sizeof(vec6F_quantizer::training_vec_with_weight);
|
||||
|
||||
std::vector<vec6F_quantizer::training_vec_with_weight> v(tv);
|
||||
basisu::vector<vec6F_quantizer::training_vec_with_weight> v(tv);
|
||||
fread(&v[0], 1, sizeof(v[0]) * tv, pFile);
|
||||
|
||||
for (uint32_t i = 0; i < tv; i++)
|
||||
m_endpoint_clusterizer.add_training_vec(v[i].first, v[i].second);
|
||||
|
||||
m_endpoint_clusterizer.generate(16128);
|
||||
std::vector<uint_vec> codebook;
|
||||
basisu::vector<uint_vec> codebook;
|
||||
m_endpoint_clusterizer.retrieve(codebook);
|
||||
|
||||
printf("Generated %u entries\n", (uint32_t)codebook.size());
|
||||
@@ -127,13 +133,21 @@ namespace basisu
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
m_endpoint_refinement = true;
|
||||
m_use_hierarchical_endpoint_codebooks = true;
|
||||
m_use_hierarchical_selector_codebooks = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
m_endpoint_refinement = true;
|
||||
m_use_hierarchical_endpoint_codebooks = false;
|
||||
m_use_hierarchical_selector_codebooks = false;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
case 4:
|
||||
{
|
||||
m_endpoint_refinement = true;
|
||||
m_use_hierarchical_endpoint_codebooks = true;
|
||||
@@ -142,7 +156,7 @@ namespace basisu
|
||||
m_num_selector_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
{
|
||||
m_endpoint_refinement = true;
|
||||
m_use_hierarchical_endpoint_codebooks = false;
|
||||
@@ -151,7 +165,8 @@ namespace basisu
|
||||
m_num_selector_codebook_iterations = BASISU_MAX_ENDPOINT_REFINEMENT_STEPS;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
case 6:
|
||||
default:
|
||||
{
|
||||
m_endpoint_refinement = true;
|
||||
m_use_hierarchical_endpoint_codebooks = false;
|
||||
@@ -269,7 +284,7 @@ namespace basisu
|
||||
|
||||
introduce_special_selector_clusters();
|
||||
|
||||
if ((m_params.m_compression_level >= 3) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
|
||||
if ((m_params.m_compression_level >= 4) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
|
||||
{
|
||||
if (!refine_block_endpoints_given_selectors())
|
||||
break;
|
||||
@@ -443,9 +458,9 @@ namespace basisu
|
||||
m_block_selector_cluster_index[i] = old_to_new[m_block_selector_cluster_index[i]];
|
||||
}
|
||||
|
||||
std::vector<etc_block> new_optimized_cluster_selectors(m_optimized_cluster_selectors.size() ? total_new_entries : 0);
|
||||
basisu::vector<etc_block> new_optimized_cluster_selectors(m_optimized_cluster_selectors.size() ? total_new_entries : 0);
|
||||
basist::etc1_global_selector_codebook_entry_id_vec new_optimized_cluster_selector_global_cb_ids(m_optimized_cluster_selector_global_cb_ids.size() ? total_new_entries : 0);
|
||||
std::vector<uint_vec> new_selector_cluster_indices(m_selector_cluster_indices.size() ? total_new_entries : 0);
|
||||
basisu::vector<uint_vec> new_selector_cluster_indices(m_selector_cluster_indices.size() ? total_new_entries : 0);
|
||||
bool_vec new_selector_cluster_uses_global_cb(m_selector_cluster_uses_global_cb.size() ? total_new_entries : 0);
|
||||
|
||||
for (uint32_t i = 0; i < total_new_entries; i++)
|
||||
@@ -474,6 +489,9 @@ namespace basisu
|
||||
void basisu_frontend::init_etc1_images()
|
||||
{
|
||||
debug_printf("basisu_frontend::init_etc1_images\n");
|
||||
|
||||
interval_timer tm;
|
||||
tm.start();
|
||||
|
||||
m_etc1_blocks_etc1s.resize(m_total_blocks);
|
||||
|
||||
@@ -497,6 +515,8 @@ namespace basisu
|
||||
|
||||
if (m_params.m_compression_level == 0)
|
||||
optimizer_params.m_quality = cETCQualityFast;
|
||||
else if (m_params.m_compression_level == 1)
|
||||
optimizer_params.m_quality = cETCQualityMedium;
|
||||
else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
|
||||
optimizer_params.m_quality = cETCQualityUber;
|
||||
|
||||
@@ -509,7 +529,8 @@ namespace basisu
|
||||
optimizer_results.m_n = 16;
|
||||
|
||||
optimizer.init(optimizer_params, optimizer_results);
|
||||
optimizer.compute();
|
||||
if (!optimizer.compute())
|
||||
BASISU_FRONTEND_VERIFY(false);
|
||||
|
||||
etc_block &blk = m_etc1_blocks_etc1s[block_index];
|
||||
|
||||
@@ -532,6 +553,8 @@ namespace basisu
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
|
||||
}
|
||||
|
||||
void basisu_frontend::init_endpoint_training_vectors()
|
||||
@@ -663,7 +686,7 @@ namespace basisu
|
||||
|
||||
for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
@@ -727,13 +750,13 @@ namespace basisu
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
|
||||
assert(cluster_indices.size());
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
std::vector<color_rgba> cluster_pixels(8);
|
||||
basisu::vector<color_rgba> cluster_pixels(8);
|
||||
|
||||
const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
|
||||
const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
|
||||
@@ -921,13 +944,13 @@ namespace basisu
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
|
||||
BASISU_FRONTEND_VERIFY(cluster_indices.size());
|
||||
|
||||
const uint32_t total_pixels = (uint32_t)cluster_indices.size() * 8;
|
||||
|
||||
std::vector<color_rgba> cluster_pixels(total_pixels);
|
||||
basisu::vector<color_rgba> cluster_pixels(total_pixels);
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
@@ -958,20 +981,21 @@ namespace basisu
|
||||
cluster_optimizer_params.m_use_color4 = false;
|
||||
cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
|
||||
|
||||
if (m_params.m_compression_level == 0)
|
||||
if (m_params.m_compression_level <= 1)
|
||||
cluster_optimizer_params.m_quality = cETCQualityMedium;
|
||||
else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
|
||||
cluster_optimizer_params.m_quality = cETCQualityUber;
|
||||
|
||||
etc1_optimizer::results cluster_optimizer_results;
|
||||
|
||||
std::vector<uint8_t> cluster_selectors(total_pixels);
|
||||
basisu::vector<uint8_t> cluster_selectors(total_pixels);
|
||||
cluster_optimizer_results.m_n = total_pixels;
|
||||
cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
|
||||
|
||||
optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
|
||||
|
||||
optimizer.compute();
|
||||
if (!optimizer.compute())
|
||||
BASISU_FRONTEND_VERIFY(false);
|
||||
|
||||
new_subblock_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
|
||||
new_subblock_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
|
||||
@@ -1048,11 +1072,11 @@ namespace basisu
|
||||
|
||||
bool basisu_frontend::check_etc1s_constraints() const
|
||||
{
|
||||
std::vector<vec2U> block_clusters(m_total_blocks);
|
||||
basisu::vector<vec2U> block_clusters(m_total_blocks);
|
||||
|
||||
for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
@@ -1080,11 +1104,11 @@ namespace basisu
|
||||
if (m_use_hierarchical_endpoint_codebooks)
|
||||
compute_endpoint_clusters_within_each_parent_cluster();
|
||||
|
||||
std::vector<vec2U> block_clusters(m_total_blocks);
|
||||
basisu::vector<vec2U> block_clusters(m_total_blocks);
|
||||
|
||||
for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
@@ -1114,15 +1138,13 @@ namespace basisu
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
{
|
||||
//const bool is_flipped = true;
|
||||
|
||||
const uint32_t cluster_index = block_clusters[block_index][0];
|
||||
BASISU_FRONTEND_VERIFY(cluster_index == block_clusters[block_index][1]);
|
||||
|
||||
const color_rgba *subblock_pixels = get_source_pixel_block(block_index).get_ptr();
|
||||
const color_rgba *pSubblock_pixels = get_source_pixel_block(block_index).get_ptr();
|
||||
const uint32_t num_subblock_pixels = 16;
|
||||
|
||||
uint64_t best_cluster_err = UINT64_MAX;
|
||||
uint64_t best_cluster_err = INT64_MAX;
|
||||
uint32_t best_cluster_index = 0;
|
||||
|
||||
const uint32_t block_parent_endpoint_cluster_index = m_block_parent_endpoint_cluster.size() ? m_block_parent_endpoint_cluster[block_index] : 0;
|
||||
@@ -1145,19 +1167,20 @@ namespace basisu
|
||||
// Can't assign it here - may result in too much error when selector quant occurs
|
||||
if (cluster_etc_inten > m_endpoint_cluster_etc_params[cluster_index].m_inten_table[0])
|
||||
{
|
||||
total_err = UINT64_MAX;
|
||||
total_err = INT64_MAX;
|
||||
goto skip_cluster;
|
||||
}
|
||||
|
||||
etc_block::get_block_colors5(subblock_colors, cluster_etc_base_color, cluster_etc_inten);
|
||||
|
||||
|
||||
#if 0
|
||||
for (uint32_t p = 0; p < num_subblock_pixels; p++)
|
||||
{
|
||||
uint64_t best_err = UINT64_MAX;
|
||||
|
||||
for (uint32_t r = low_selector; r <= high_selector; r++)
|
||||
{
|
||||
uint64_t err = color_distance(m_params.m_perceptual, subblock_pixels[p], subblock_colors[r], false);
|
||||
uint64_t err = color_distance(m_params.m_perceptual, pSubblock_pixels[p], subblock_colors[r], false);
|
||||
best_err = minimum(best_err, err);
|
||||
if (!best_err)
|
||||
break;
|
||||
@@ -1167,6 +1190,64 @@ namespace basisu
|
||||
if (total_err > best_cluster_err)
|
||||
break;
|
||||
} // p
|
||||
#else
|
||||
if (m_params.m_perceptual)
|
||||
{
|
||||
if (!g_cpu_supports_sse41)
|
||||
{
|
||||
for (uint32_t p = 0; p < num_subblock_pixels; p++)
|
||||
{
|
||||
uint64_t best_err = UINT64_MAX;
|
||||
|
||||
for (uint32_t r = low_selector; r <= high_selector; r++)
|
||||
{
|
||||
uint64_t err = color_distance(true, pSubblock_pixels[p], subblock_colors[r], false);
|
||||
best_err = minimum(best_err, err);
|
||||
if (!best_err)
|
||||
break;
|
||||
}
|
||||
|
||||
total_err += best_err;
|
||||
if (total_err > best_cluster_err)
|
||||
break;
|
||||
} // p
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BASISU_SUPPORT_SSE
|
||||
find_lowest_error_perceptual_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_cpu_supports_sse41)
|
||||
{
|
||||
for (uint32_t p = 0; p < num_subblock_pixels; p++)
|
||||
{
|
||||
uint64_t best_err = UINT64_MAX;
|
||||
|
||||
for (uint32_t r = low_selector; r <= high_selector; r++)
|
||||
{
|
||||
uint64_t err = color_distance(false, pSubblock_pixels[p], subblock_colors[r], false);
|
||||
best_err = minimum(best_err, err);
|
||||
if (!best_err)
|
||||
break;
|
||||
}
|
||||
|
||||
total_err += best_err;
|
||||
if (total_err > best_cluster_err)
|
||||
break;
|
||||
} // p
|
||||
}
|
||||
else
|
||||
{
|
||||
#if BASISU_SUPPORT_SSE
|
||||
find_lowest_error_linear_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
skip_cluster:
|
||||
if ((total_err < best_cluster_err) ||
|
||||
@@ -1194,7 +1275,7 @@ namespace basisu
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
std::vector<typename std::vector<uint32_t> > optimized_endpoint_clusters(m_endpoint_clusters.size());
|
||||
basisu::vector<typename basisu::vector<uint32_t> > optimized_endpoint_clusters(m_endpoint_clusters.size());
|
||||
uint32_t total_subblocks_reassigned = 0;
|
||||
|
||||
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
|
||||
@@ -1232,8 +1313,8 @@ namespace basisu
|
||||
|
||||
indirect_sort((uint32_t)m_endpoint_clusters.size(), &sorted_endpoint_cluster_indices[0], &m_endpoint_cluster_etc_params[0]);
|
||||
|
||||
std::vector<std::vector<uint32_t> > new_endpoint_clusters(m_endpoint_clusters.size());
|
||||
std::vector<endpoint_cluster_etc_params> new_subblock_etc_params(m_endpoint_clusters.size());
|
||||
basisu::vector<basisu::vector<uint32_t> > new_endpoint_clusters(m_endpoint_clusters.size());
|
||||
basisu::vector<endpoint_cluster_etc_params> new_subblock_etc_params(m_endpoint_clusters.size());
|
||||
|
||||
for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
|
||||
{
|
||||
@@ -1343,7 +1424,7 @@ namespace basisu
|
||||
|
||||
for (int cluster_index = 0; cluster_index < static_cast<int>(m_selector_cluster_indices.size()); cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_indices = m_selector_cluster_indices[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_indices = m_selector_cluster_indices[cluster_index];
|
||||
|
||||
for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
|
||||
{
|
||||
@@ -1437,7 +1518,9 @@ namespace basisu
|
||||
for (uint32_t i = 0; i < m_total_blocks; i++)
|
||||
selector_clusterizer.add_training_vec(training_vecs[i].first, training_vecs[i].second);
|
||||
|
||||
const uint32_t parent_codebook_size = (m_params.m_max_selector_clusters >= 256) ? BASISU_SELECTOR_PARENT_CODEBOOK_SIZE : 0;
|
||||
const int selector_parent_codebook_size = (m_params.m_compression_level <= 1) ? BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_01 : BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_DEFAULT;
|
||||
const uint32_t parent_codebook_size = (m_params.m_max_selector_clusters >= 256) ? selector_parent_codebook_size : 0;
|
||||
debug_printf("Using selector parent codebook size %u\n", parent_codebook_size);
|
||||
|
||||
uint32_t max_threads = 0;
|
||||
max_threads = m_params.m_multithreaded ? minimum<int>(std::thread::hardware_concurrency(), cMaxCodebookCreationThreads) : 0;
|
||||
@@ -1459,7 +1542,8 @@ namespace basisu
|
||||
m_selector_parent_cluster_indices[0].push_back(i);
|
||||
}
|
||||
|
||||
BASISU_ASSUME(BASISU_SELECTOR_PARENT_CODEBOOK_SIZE <= UINT8_MAX);
|
||||
BASISU_ASSUME(BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_01 <= UINT8_MAX);
|
||||
BASISU_ASSUME(BASISU_SELECTOR_PARENT_CODEBOOK_SIZE_COMP_LEVEL_DEFAULT <= UINT8_MAX);
|
||||
|
||||
m_block_parent_selector_cluster.resize(0);
|
||||
m_block_parent_selector_cluster.resize(m_total_blocks);
|
||||
@@ -1526,7 +1610,7 @@ namespace basisu
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
|
||||
const basisu::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
|
||||
|
||||
if (!cluster_block_indices.size())
|
||||
continue;
|
||||
@@ -1610,7 +1694,7 @@ namespace basisu
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
|
||||
const basisu::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[cluster_index];
|
||||
|
||||
if (!cluster_block_indices.size())
|
||||
continue;
|
||||
@@ -1746,7 +1830,7 @@ namespace basisu
|
||||
|
||||
for (uint32_t selector_cluster_index = 0; selector_cluster_index < m_selector_cluster_indices.size(); selector_cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[selector_cluster_index];
|
||||
const basisu::vector<uint32_t> &cluster_block_indices = m_selector_cluster_indices[selector_cluster_index];
|
||||
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
@@ -1788,10 +1872,22 @@ namespace basisu
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector< std::vector<uint32_t> > new_cluster_indices;
|
||||
basisu::vector< basisu::vector<uint32_t> > new_cluster_indices;
|
||||
|
||||
// For each block: Determine which quantized selectors best encode that block, given its quantized endpoints.
|
||||
|
||||
basisu::vector<uint8_t> unpacked_optimized_cluster_selectors(16 * m_optimized_cluster_selectors.size());
|
||||
for (uint32_t cluster_index = 0; cluster_index < m_optimized_cluster_selectors.size(); cluster_index++)
|
||||
{
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
{
|
||||
unpacked_optimized_cluster_selectors[cluster_index * 16 + y * 4 + x] = (uint8_t)m_optimized_cluster_selectors[cluster_index].get_selector(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t N = 1024;
|
||||
for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
|
||||
{
|
||||
@@ -1799,7 +1895,7 @@ namespace basisu
|
||||
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, &new_cluster_indices] {
|
||||
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &new_cluster_indices, &unpacked_optimized_cluster_selectors] {
|
||||
#endif
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
@@ -1811,7 +1907,7 @@ namespace basisu
|
||||
color_rgba trial_block_colors[4];
|
||||
blk.get_block_colors(trial_block_colors, 0);
|
||||
|
||||
uint64_t best_cluster_err = UINT64_MAX;
|
||||
uint64_t best_cluster_err = INT64_MAX;
|
||||
uint32_t best_cluster_index = 0;
|
||||
|
||||
const uint32_t parent_selector_cluster = m_block_parent_selector_cluster.size() ? m_block_parent_selector_cluster[block_index] : 0;
|
||||
@@ -1819,12 +1915,13 @@ namespace basisu
|
||||
|
||||
const uint32_t total_clusters = m_use_hierarchical_selector_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_selector_cluster_indices.size();
|
||||
|
||||
#if 0
|
||||
for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
|
||||
{
|
||||
const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
|
||||
|
||||
const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
|
||||
|
||||
|
||||
uint64_t trial_err = 0;
|
||||
for (int y = 0; y < 4; y++)
|
||||
{
|
||||
@@ -1837,18 +1934,82 @@ namespace basisu
|
||||
goto early_out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (trial_err < best_cluster_err)
|
||||
{
|
||||
best_cluster_err = trial_err;
|
||||
best_cluster_index = cluster_index;
|
||||
if (!best_cluster_err)
|
||||
if (!best_cluster_err)
|
||||
break;
|
||||
}
|
||||
|
||||
early_out:
|
||||
;
|
||||
}
|
||||
#else
|
||||
if (m_params.m_perceptual)
|
||||
{
|
||||
for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
|
||||
{
|
||||
const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
|
||||
//const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
|
||||
|
||||
uint64_t trial_err = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
const uint32_t sel = unpacked_optimized_cluster_selectors[cluster_index * 16 + i];
|
||||
|
||||
trial_err += color_distance(true, trial_block_colors[sel], pBlock_pixels[i], false);
|
||||
if (trial_err > best_cluster_err)
|
||||
goto early_out;
|
||||
}
|
||||
|
||||
if (trial_err < best_cluster_err)
|
||||
{
|
||||
best_cluster_err = trial_err;
|
||||
best_cluster_index = cluster_index;
|
||||
if (!best_cluster_err)
|
||||
break;
|
||||
}
|
||||
|
||||
early_out:
|
||||
;
|
||||
|
||||
} // cluster_iter
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
|
||||
{
|
||||
const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
|
||||
//const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
|
||||
|
||||
uint64_t trial_err = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
const uint32_t sel = unpacked_optimized_cluster_selectors[cluster_index * 16 + i];
|
||||
|
||||
trial_err += color_distance(false, trial_block_colors[sel], pBlock_pixels[i], false);
|
||||
if (trial_err > best_cluster_err)
|
||||
goto early_out2;
|
||||
}
|
||||
|
||||
if (trial_err < best_cluster_err)
|
||||
{
|
||||
best_cluster_err = trial_err;
|
||||
best_cluster_index = cluster_index;
|
||||
if (!best_cluster_err)
|
||||
break;
|
||||
}
|
||||
|
||||
early_out2:
|
||||
;
|
||||
|
||||
} // cluster_iter
|
||||
}
|
||||
#endif
|
||||
|
||||
blk.set_raw_selector_bits(m_optimized_cluster_selectors[best_cluster_index].get_raw_selector_bits());
|
||||
|
||||
@@ -1905,7 +2066,7 @@ namespace basisu
|
||||
const uint_vec &subblocks = subblock_params.m_subblocks;
|
||||
//uint32_t total_pixels = subblock.m_subblocks.size() * 8;
|
||||
|
||||
std::vector<color_rgba> subblock_colors[2]; // [use_individual_mode]
|
||||
basisu::vector<color_rgba> subblock_colors[2]; // [use_individual_mode]
|
||||
uint8_vec subblock_selectors[2];
|
||||
|
||||
uint64_t cur_subblock_err[2] = { 0, 0 };
|
||||
@@ -1945,7 +2106,7 @@ namespace basisu
|
||||
|
||||
clear_obj(cluster_optimizer_results);
|
||||
|
||||
std::vector<uint8_t> cluster_selectors[2];
|
||||
basisu::vector<uint8_t> cluster_selectors[2];
|
||||
|
||||
for (uint32_t use_individual_mode = 0; use_individual_mode < 2; use_individual_mode++)
|
||||
{
|
||||
@@ -2075,8 +2236,8 @@ namespace basisu
|
||||
|
||||
uint32_t max_endpoint_cluster_size = 0;
|
||||
|
||||
std::vector<uint32_t> cluster_sizes(m_endpoint_clusters.size());
|
||||
std::vector<uint32_t> sorted_cluster_indices(m_endpoint_clusters.size());
|
||||
basisu::vector<uint32_t> cluster_sizes(m_endpoint_clusters.size());
|
||||
basisu::vector<uint32_t> sorted_cluster_indices(m_endpoint_clusters.size());
|
||||
for (uint32_t i = 0; i < m_endpoint_clusters.size(); i++)
|
||||
{
|
||||
max_endpoint_cluster_size = maximum<uint32_t>(max_endpoint_cluster_size, (uint32_t)m_endpoint_clusters[i].size());
|
||||
@@ -2163,12 +2324,12 @@ namespace basisu
|
||||
{
|
||||
debug_printf("reoptimize_remapped_endpoints\n");
|
||||
|
||||
std::vector<uint_vec> new_endpoint_cluster_block_indices(m_endpoint_clusters.size());
|
||||
basisu::vector<uint_vec> new_endpoint_cluster_block_indices(m_endpoint_clusters.size());
|
||||
for (uint32_t i = 0; i < new_block_endpoints.size(); i++)
|
||||
new_endpoint_cluster_block_indices[new_block_endpoints[i]].push_back(i);
|
||||
|
||||
std::vector<uint8_t> cluster_valid(new_endpoint_cluster_block_indices.size());
|
||||
std::vector<uint8_t> cluster_improved(new_endpoint_cluster_block_indices.size());
|
||||
basisu::vector<uint8_t> cluster_valid(new_endpoint_cluster_block_indices.size());
|
||||
basisu::vector<uint8_t> cluster_improved(new_endpoint_cluster_block_indices.size());
|
||||
|
||||
const uint32_t N = 256;
|
||||
for (uint32_t cluster_index_iter = 0; cluster_index_iter < new_endpoint_cluster_block_indices.size(); cluster_index_iter += N)
|
||||
@@ -2182,14 +2343,14 @@ namespace basisu
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
const std::vector<uint32_t>& cluster_block_indices = new_endpoint_cluster_block_indices[cluster_index];
|
||||
const basisu::vector<uint32_t>& cluster_block_indices = new_endpoint_cluster_block_indices[cluster_index];
|
||||
|
||||
if (!cluster_block_indices.size())
|
||||
continue;
|
||||
|
||||
const uint32_t total_pixels = (uint32_t)cluster_block_indices.size() * 16;
|
||||
|
||||
std::vector<color_rgba> cluster_pixels(total_pixels);
|
||||
basisu::vector<color_rgba> cluster_pixels(total_pixels);
|
||||
uint8_vec force_selectors(total_pixels);
|
||||
|
||||
etc_block blk;
|
||||
@@ -2236,16 +2397,19 @@ namespace basisu
|
||||
|
||||
if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
|
||||
cluster_optimizer_params.m_quality = cETCQualityUber;
|
||||
else
|
||||
cluster_optimizer_params.m_quality = cETCQualitySlow;
|
||||
|
||||
etc1_optimizer::results cluster_optimizer_results;
|
||||
|
||||
std::vector<uint8_t> cluster_selectors(total_pixels);
|
||||
basisu::vector<uint8_t> cluster_selectors(total_pixels);
|
||||
cluster_optimizer_results.m_n = total_pixels;
|
||||
cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
|
||||
|
||||
optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
|
||||
|
||||
optimizer.compute();
|
||||
if (!optimizer.compute())
|
||||
BASISU_FRONTEND_VERIFY(false);
|
||||
|
||||
new_endpoint_cluster_etc_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
|
||||
new_endpoint_cluster_etc_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
|
||||
@@ -2310,7 +2474,7 @@ namespace basisu
|
||||
|
||||
debug_printf("basisu_frontend::reoptimize_remapped_endpoints: stage 1\n");
|
||||
|
||||
std::vector<uint_vec> new_endpoint_clusters(total_new_endpoint_clusters);
|
||||
basisu::vector<uint_vec> new_endpoint_clusters(total_new_endpoint_clusters);
|
||||
|
||||
for (uint32_t block_index = 0; block_index < new_block_endpoints.size(); block_index++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user