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:
Rich Geldreich
2021-03-09 11:00:25 -05:00
parent 4299495f77
commit 2d4fe933b2
38 changed files with 1457 additions and 528 deletions

View File

@@ -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++)
{