Merge pull request #103968 from Chubercik/basis_universal-1.60
basis_universal: Update to 1.60
This commit is contained in:
@@ -20,22 +20,24 @@ basisu_encoder = env.editor_build
|
||||
if basisu_encoder:
|
||||
encoder_sources = [
|
||||
"3rdparty/android_astc_decomp.cpp",
|
||||
"basisu_astc_hdr_enc.cpp",
|
||||
"basisu_astc_hdr_6x6_enc.cpp",
|
||||
"basisu_astc_hdr_common.cpp",
|
||||
"basisu_backend.cpp",
|
||||
"basisu_basis_file.cpp",
|
||||
"basisu_bc7enc.cpp",
|
||||
"basisu_opencl.cpp",
|
||||
"basisu_comp.cpp",
|
||||
"basisu_enc.cpp",
|
||||
"basisu_etc.cpp",
|
||||
"basisu_frontend.cpp",
|
||||
"basisu_gpu_texture.cpp",
|
||||
"basisu_kernels_sse.cpp",
|
||||
"basisu_opencl.cpp",
|
||||
"basisu_pvrtc1_4.cpp",
|
||||
"basisu_resampler.cpp",
|
||||
"basisu_resample_filters.cpp",
|
||||
"basisu_resampler.cpp",
|
||||
"basisu_ssim.cpp",
|
||||
"basisu_uastc_enc.cpp",
|
||||
"basisu_uastc_hdr_4x4_enc.cpp",
|
||||
"pvpngreader.cpp",
|
||||
]
|
||||
encoder_sources = [thirdparty_dir + "encoder/" + file for file in encoder_sources]
|
||||
|
||||
@@ -101,13 +101,13 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha
|
||||
basisu::basis_compressor_params params;
|
||||
|
||||
params.m_uastc = true;
|
||||
params.m_quality_level = basisu::BASISU_QUALITY_MIN;
|
||||
params.m_pack_uastc_flags &= ~basisu::cPackUASTCLevelMask;
|
||||
params.m_pack_uastc_flags |= basisu::cPackUASTCLevelFastest;
|
||||
params.m_etc1s_quality_level = basisu::BASISU_QUALITY_MIN;
|
||||
params.m_pack_uastc_ldr_4x4_flags &= ~basisu::cPackUASTCLevelMask;
|
||||
params.m_pack_uastc_ldr_4x4_flags |= basisu::cPackUASTCLevelFastest;
|
||||
|
||||
params.m_rdo_uastc = 0.0f;
|
||||
params.m_rdo_uastc_quality_scalar = 0.0f;
|
||||
params.m_rdo_uastc_dict_size = 1024;
|
||||
params.m_rdo_uastc_ldr_4x4 = 0.0f;
|
||||
params.m_rdo_uastc_ldr_4x4_quality_scalar = 0.0f;
|
||||
params.m_rdo_uastc_ldr_4x4_dict_size = 1024;
|
||||
|
||||
params.m_mip_fast = true;
|
||||
params.m_multithreading = true;
|
||||
@@ -127,7 +127,7 @@ Vector<uint8_t> basis_universal_packer(const Ref<Image> &p_image, Image::UsedCha
|
||||
if (is_hdr) {
|
||||
decompress_format = BASIS_DECOMPRESS_HDR_RGB;
|
||||
params.m_hdr = true;
|
||||
params.m_uastc_hdr_options.set_quality_level(0);
|
||||
params.m_uastc_hdr_4x4_options.set_quality_level(0);
|
||||
|
||||
} else {
|
||||
switch (p_channels) {
|
||||
|
||||
Vendored
+4
-1
@@ -74,7 +74,7 @@ Files extracted from upstream source:
|
||||
## basis_universal
|
||||
|
||||
- Upstream: https://github.com/BinomialLLC/basis_universal
|
||||
- Version: 1.50.0 (051ad6d8a64bb95a79e8601c317055fd1782ad3e, 2024)
|
||||
- Version: 1.60 (323239a6a5ffa57d6570cfc403be99156e33a8b0, 2025)
|
||||
- License: Apache 2.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
@@ -89,6 +89,8 @@ Patches:
|
||||
- `0002-external-jpgd.patch` (GH-88508)
|
||||
- `0003-external-tinyexr.patch` (GH-97582)
|
||||
- `0004-remove-tinydds-qoi.patch` (GH-97582)
|
||||
- `0005-windows-illegal-character.patch` (GH-103968)
|
||||
- `0006-ambiguous-calls.patch` (GH-103968)
|
||||
|
||||
|
||||
## brotli
|
||||
@@ -523,6 +525,7 @@ Patches:
|
||||
|
||||
- `0001-external-basisu.patch` (GH-76572)
|
||||
- `0002-disable-astc-block-ext.patch` (GH-76572)
|
||||
- `0003-basisu-1.60.patch` (GH-103968)
|
||||
|
||||
|
||||
## libogg
|
||||
|
||||
@@ -836,10 +836,12 @@ void decodeISETritBlock (ISEDecodedResult* dst, int numValues, BitAccessStream&
|
||||
m[4] = data.getNext(numBits);
|
||||
deUint32 T7 = data.getNext(1);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough="
|
||||
#endif
|
||||
#endif
|
||||
switch (numValues)
|
||||
{
|
||||
// \note Fall-throughs.
|
||||
@@ -851,9 +853,11 @@ void decodeISETritBlock (ISEDecodedResult* dst, int numValues, BitAccessStream&
|
||||
default:
|
||||
DE_ASSERT(false);
|
||||
}
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const deUint32 T = (T7 << 7) | (T56 << 5) | (T4 << 4) | (T23 << 2) | (T01 << 0);
|
||||
|
||||
@@ -898,10 +902,12 @@ void decodeISEQuintBlock (ISEDecodedResult* dst, int numValues, BitAccessStream&
|
||||
m[2] = data.getNext(numBits);
|
||||
deUint32 Q56 = data.getNext(2);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough="
|
||||
#endif
|
||||
#endif
|
||||
switch (numValues)
|
||||
{
|
||||
// \note Fall-throughs.
|
||||
@@ -911,9 +917,11 @@ void decodeISEQuintBlock (ISEDecodedResult* dst, int numValues, BitAccessStream&
|
||||
default:
|
||||
DE_ASSERT(false);
|
||||
}
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const deUint32 Q = (Q56 << 5) | (Q34 << 3) | (Q012 << 0);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,129 @@
|
||||
// File: basisu_astc_hdr_6x6_enc.h
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
namespace astc_6x6_hdr
|
||||
{
|
||||
const uint32_t ASTC_HDR_6X6_MAX_USER_COMP_LEVEL = 12;
|
||||
|
||||
const uint32_t ASTC_HDR_6X6_MAX_COMP_LEVEL = 4;
|
||||
|
||||
const float LDR_BLACK_BIAS = 0.0f;// .49f;
|
||||
|
||||
// Note: This struct is copied several times, so do not place any heavyweight objects in here.
|
||||
struct astc_hdr_6x6_global_config
|
||||
{
|
||||
// Important: The Delta ITP colorspace error metric we use internally makes several assumptions about the nature of the HDR RGB inputs supplied to the encoder.
|
||||
// This encoder computes colorspace error in the ICtCp (or more accurately the delta ITP, where CT is scaled by .5 vs. ICtCp to become T) colorspace, so getting this correct is important.
|
||||
// By default the encoder assumes the input is in absolute luminance (in nits or candela per square meter, cd/m^2), specified as positive-only linear light RGB, using the REC 709 colorspace gamut (but NOT the sRGB transfer function, i.e. linear light).
|
||||
// If the m_rec2020_bt2100_color_gamut flag is true, the input colorspace is treated as REC 2020/BT.2100 (which is wider than 709).
|
||||
// For SDR/LDR->HDR upconversion, the REC 709 sRGB input should be converted to linear light (sRGB->linear) and the resulting normalized linear RGB values scaled by either 80 or 100 nits (the luminance of a typical SDR monitor).
|
||||
// SDR upconversion to normalized [0,1] (i.e. non-absolute) luminances may work but is not supported because ITP errors will not be predicted correctly.
|
||||
bool m_rec2020_bt2100_color_gamut = false;
|
||||
|
||||
// levels 0-3 normal levels, 4=exhaustive
|
||||
uint32_t m_master_comp_level = 0;
|
||||
uint32_t m_highest_comp_level = 1;
|
||||
|
||||
float m_lambda = 0.0f;
|
||||
|
||||
bool m_extra_patterns_flag = false; // def to false, works in comp levels [1,4]
|
||||
bool m_brute_force_partition_matching = false; // def to false
|
||||
|
||||
bool m_jnd_optimization = false; // defaults to false for HDR inputs, on SDR upconverted images this can default to enabled
|
||||
float m_jnd_delta_itp_thresh = .75f;
|
||||
|
||||
bool m_force_one_strip = false;
|
||||
|
||||
bool m_gaussian1_fallback = true; // def to true, if this is disabled m_gaussian2_fallback should be disabled too
|
||||
float m_gaussian1_strength = 1.45f;
|
||||
|
||||
bool m_gaussian2_fallback = true; // def to true, hopefully rarely kicks in
|
||||
float m_gaussian2_strength = 1.83f;
|
||||
|
||||
// m_disable_delta_endpoint_usage may give a slight increase in RDO ASTC encoding efficiency. It's also faster.
|
||||
bool m_disable_delta_endpoint_usage = false;
|
||||
|
||||
// Scale up Delta ITP errors for very dark pixels, assuming they will be brightly exposed > 1.0x.
|
||||
// We don't know if the output will be exposed, or not. If heavily exposed, our JND calculations will not be conservative enough.
|
||||
bool m_delta_itp_dark_adjustment = true;
|
||||
|
||||
bool m_debug_images = false;
|
||||
std::string m_debug_image_prefix = "dbg_astc_hdr_6x6_devel_";
|
||||
|
||||
bool m_output_images = false;
|
||||
std::string m_output_image_prefix = "dbg_astc_hdr_6x6_output_";
|
||||
|
||||
bool m_debug_output = false;
|
||||
bool m_image_stats = false;
|
||||
bool m_status_output = false;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// Very low level/devel parameters - intended for development. Best not to change them.
|
||||
//-------------------------------------------------------------------------------------
|
||||
bool m_deblocking_flag = true;
|
||||
float m_deblock_penalty_weight = .03f;
|
||||
bool m_disable_twothree_subsets = false; // def to false
|
||||
bool m_use_solid_blocks = true; // def to true
|
||||
bool m_use_runs = true; // def to true
|
||||
bool m_block_stat_optimizations_flag = true; // def to true
|
||||
|
||||
bool m_rdo_candidate_diversity_boost = true; // def to true
|
||||
float m_rdo_candidate_diversity_boost_bit_window_weight = 1.2f;
|
||||
|
||||
bool m_favor_higher_compression = true; // utilize all modes
|
||||
uint32_t m_num_reuse_xy_deltas = basist::astc_6x6_hdr::NUM_REUSE_XY_DELTAS;
|
||||
|
||||
void print() const
|
||||
{
|
||||
basisu::fmt_debug_printf("m_master_comp_level: {}, m_highest_comp_level: {}\n", m_master_comp_level, m_highest_comp_level);
|
||||
basisu::fmt_debug_printf("m_lambda: {}\n", m_lambda);
|
||||
basisu::fmt_debug_printf("m_rec2020_bt2100_color_gamut: {}\n", m_rec2020_bt2100_color_gamut);
|
||||
basisu::fmt_debug_printf("m_extra_patterns_flag: {}, m_brute_force_partition_matching: {}\n", m_extra_patterns_flag, m_brute_force_partition_matching);
|
||||
basisu::fmt_debug_printf("m_jnd_optimization: {}, m_jnd_delta_itp_thresh: {}\n", m_jnd_optimization, m_jnd_delta_itp_thresh);
|
||||
basisu::fmt_debug_printf("m_force_one_strip: {}\n", m_force_one_strip);
|
||||
basisu::fmt_debug_printf("m_gaussian1_fallback: {}, m_gaussian1_strength: {}\n", m_gaussian1_fallback, m_gaussian1_strength);
|
||||
basisu::fmt_debug_printf("m_gaussian2_fallback: {}, m_gaussian2_strength: {}\n", m_gaussian2_fallback, m_gaussian2_strength);
|
||||
basisu::fmt_debug_printf("m_disable_delta_endpoint_usage: {}\n", m_disable_delta_endpoint_usage);
|
||||
basisu::fmt_debug_printf("m_delta_itp_dark_adjustment: {}\n", m_delta_itp_dark_adjustment);
|
||||
basisu::fmt_debug_printf("m_debug_images: {}, m_debug_image_prefix: {}\n", m_debug_images, m_debug_image_prefix);
|
||||
basisu::fmt_debug_printf("m_output_images: {}, m_output_image_prefix: {}\n", m_output_images, m_output_image_prefix);
|
||||
basisu::fmt_debug_printf("m_image_stats: {}, m_status_output: {}\n", m_image_stats, m_status_output);
|
||||
basisu::fmt_debug_printf("m_deblocking_flag: {}, m_deblock_penalty_weight: {}\n", m_deblocking_flag, m_deblock_penalty_weight);
|
||||
basisu::fmt_debug_printf("m_disable_twothree_subsets: {}, m_use_solid_blocks: {}\n", m_disable_twothree_subsets, m_use_solid_blocks);
|
||||
basisu::fmt_debug_printf("m_use_runs: {}, m_block_stat_optimizations_flag: {}\n", m_use_runs, m_block_stat_optimizations_flag);
|
||||
basisu::fmt_debug_printf("m_rdo_candidate_diversity_boost: {}, m_rdo_candidate_diversity_boost_bit_window_weight: {}\n", m_rdo_candidate_diversity_boost, m_rdo_candidate_diversity_boost_bit_window_weight);
|
||||
basisu::fmt_debug_printf("m_favor_higher_compression: {}, m_num_reuse_xy_deltas: {}\n", m_favor_higher_compression, m_num_reuse_xy_deltas);
|
||||
}
|
||||
|
||||
astc_hdr_6x6_global_config()
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
astc_hdr_6x6_global_config def;
|
||||
std::swap(*this, def);
|
||||
}
|
||||
|
||||
// Max level is ASTC_HDR_6X6_MAX_USER_COMP_LEVEL
|
||||
void set_user_level(int level);
|
||||
};
|
||||
|
||||
void global_init();
|
||||
|
||||
struct result_metrics
|
||||
{
|
||||
basisu::image_metrics m_im_astc_log2;
|
||||
basisu::image_metrics m_im_astc_half;
|
||||
|
||||
basisu::image_metrics m_im_bc6h_log2;
|
||||
basisu::image_metrics m_im_bc6h_half;
|
||||
};
|
||||
|
||||
// The input image should be unpadded to 6x6 boundaries, i.e. the original unexpanded image.
|
||||
bool compress_photo(const basisu::imagef& orig_src_img, const astc_hdr_6x6_global_config& global_cfg, basisu::job_pool* pJob_pool,
|
||||
basisu::uint8_vec& intermediate_tex_data, basisu::uint8_vec& astc_tex_data, result_metrics& metrics);
|
||||
|
||||
} // namespace uastc_6x6_hdr
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,423 @@
|
||||
// File: basisu_astc_hdr_common.h
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include "../transcoder/basisu_astc_helpers.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
const uint32_t MAX_ASTC_HDR_BLOCK_W = 6, MAX_ASTC_HDR_BLOCK_H = 6;
|
||||
const uint32_t MAX_ASTC_HDR_ENC_BLOCK_PIXELS = 6 * 6;
|
||||
|
||||
const uint32_t MODE11_TOTAL_SUBMODES = 8; // plus an extra hidden submode, directly encoded, for direct, so really 9 (see tables 99/100 of the ASTC spec)
|
||||
const uint32_t MODE7_TOTAL_SUBMODES = 6;
|
||||
|
||||
// [ise_range][0] = # levels
|
||||
// [ise_range][1...] = lerp value [0,64]
|
||||
// in ASTC order
|
||||
// Supported ISE weight ranges: 0 to 11, 12 total
|
||||
const uint32_t MIN_SUPPORTED_ISE_WEIGHT_INDEX = astc_helpers::BISE_2_LEVELS; // ISE 0=2 levels
|
||||
const uint32_t MAX_SUPPORTED_ISE_WEIGHT_INDEX = astc_helpers::BISE_32_LEVELS; // ISE 11=16 levels
|
||||
const uint32_t MIN_SUPPORTED_WEIGHT_LEVELS = 2;
|
||||
const uint32_t MAX_SUPPORTED_WEIGHT_LEVELS = 32;
|
||||
|
||||
extern const uint8_t g_ise_weight_lerps[MAX_SUPPORTED_ISE_WEIGHT_INDEX + 1][33];
|
||||
|
||||
const float Q_LOG_BIAS_4x4 = .125f; // the original UASTC HDR 4x4 log bias
|
||||
const float Q_LOG_BIAS_6x6 = 1.0f; // the log bias both encoders use now
|
||||
|
||||
const float LDR_TO_HDR_NITS = 100.0f;
|
||||
|
||||
struct astc_hdr_codec_base_options
|
||||
{
|
||||
float m_r_err_scale, m_g_err_scale;
|
||||
float m_q_log_bias;
|
||||
|
||||
bool m_ultra_quant;
|
||||
|
||||
// If true, the ASTC HDR compressor is allowed to more aggressively vary weight indices for slightly higher compression in non-fastest mode. This will hurt BC6H quality, however.
|
||||
bool m_allow_uber_mode;
|
||||
|
||||
bool m_mode7_full_s_optimization;
|
||||
|
||||
bool m_take_first_non_clamping_mode11_submode;
|
||||
bool m_take_first_non_clamping_mode7_submode;
|
||||
|
||||
bool m_disable_weight_plane_optimization;
|
||||
|
||||
astc_hdr_codec_base_options() { init(); }
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
inline int get_bit(
|
||||
int src_val, int src_bit)
|
||||
{
|
||||
assert(src_bit >= 0 && src_bit <= 31);
|
||||
int bit = (src_val >> src_bit) & 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
inline void pack_bit(
|
||||
int& dst, int dst_bit,
|
||||
int src_val, int src_bit = 0)
|
||||
{
|
||||
assert(dst_bit >= 0 && dst_bit <= 31);
|
||||
int bit = get_bit(src_val, src_bit);
|
||||
dst |= (bit << dst_bit);
|
||||
}
|
||||
|
||||
inline uint32_t get_max_qlog(uint32_t bits)
|
||||
{
|
||||
switch (bits)
|
||||
{
|
||||
case 7: return basist::MAX_QLOG7;
|
||||
case 8: return basist::MAX_QLOG8;
|
||||
case 9: return basist::MAX_QLOG9;
|
||||
case 10: return basist::MAX_QLOG10;
|
||||
case 11: return basist::MAX_QLOG11;
|
||||
case 12: return basist::MAX_QLOG12;
|
||||
case 16: return basist::MAX_QLOG16;
|
||||
default: assert(0); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline float get_max_qlog_val(uint32_t bits)
|
||||
{
|
||||
switch (bits)
|
||||
{
|
||||
case 7: return MAX_QLOG7_VAL;
|
||||
case 8: return MAX_QLOG8_VAL;
|
||||
case 9: return MAX_QLOG9_VAL;
|
||||
case 10: return MAX_QLOG10_VAL;
|
||||
case 11: return MAX_QLOG11_VAL;
|
||||
case 12: return MAX_QLOG12_VAL;
|
||||
case 16: return MAX_QLOG16_VAL;
|
||||
default: assert(0); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Input is the low 11 bits of the qlog
|
||||
// Returns the 10-bit mantissa of the half float value
|
||||
int qlog11_to_half_float_mantissa(int M)
|
||||
{
|
||||
assert(M <= 0x7FF);
|
||||
int Mt;
|
||||
if (M < 512)
|
||||
Mt = 3 * M;
|
||||
else if (M >= 1536)
|
||||
Mt = 5 * M - 2048;
|
||||
else
|
||||
Mt = 4 * M - 512;
|
||||
return (Mt >> 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Input is the 10-bit mantissa of the half float value
|
||||
// Output is the 11-bit qlog value
|
||||
// Inverse of qlog11_to_half_float_mantissa()
|
||||
inline int half_float_mantissa_to_qlog11(int hf)
|
||||
{
|
||||
int q0 = (hf * 8 + 2) / 3;
|
||||
int q1 = (hf * 8 + 2048 + 4) / 5;
|
||||
|
||||
if (q0 < 512)
|
||||
return q0;
|
||||
else if (q1 >= 1536)
|
||||
return q1;
|
||||
|
||||
int q2 = (hf * 8 + 512 + 2) / 4;
|
||||
return q2;
|
||||
}
|
||||
|
||||
inline int half_to_qlog16(int hf)
|
||||
{
|
||||
assert(!basist::half_is_signed((basist::half_float)hf) && !basist::is_half_inf_or_nan((basist::half_float)hf));
|
||||
|
||||
// extract 5 bits exponent, which is carried through to qlog16 unchanged
|
||||
const int exp = (hf >> 10) & 0x1F;
|
||||
|
||||
// extract and invert the 10 bit mantissa to nearest qlog11 (should be lossless)
|
||||
const int mantissa = half_float_mantissa_to_qlog11(hf & 0x3FF);
|
||||
assert(mantissa <= 0x7FF);
|
||||
|
||||
// Now combine to qlog16, which is what ASTC HDR interpolates using the [0-64] weights.
|
||||
uint32_t qlog16 = (exp << 11) | mantissa;
|
||||
|
||||
// should be a lossless operation
|
||||
assert(astc_helpers::qlog16_to_half(qlog16) == hf);
|
||||
|
||||
return qlog16;
|
||||
}
|
||||
|
||||
void interpolate_qlog12_colors(
|
||||
const int e[2][3],
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range);
|
||||
|
||||
bool get_astc_hdr_mode_11_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
bool get_astc_hdr_mode_7_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
// Fast high precision piecewise linear approximation of log2(bias+x).
|
||||
// Half may be zero, positive or denormal. No NaN/Inf/negative.
|
||||
BASISU_FORCE_INLINE double q(basist::half_float x, float log_bias)
|
||||
{
|
||||
union { float f; int32_t i; uint32_t u; } fi;
|
||||
|
||||
fi.f = fast_half_to_float_pos_not_inf_or_nan(x);
|
||||
|
||||
assert(fi.f >= 0.0f);
|
||||
|
||||
fi.f += log_bias;
|
||||
|
||||
return (double)fi.u; // approx log2f(fi.f), need to return double for the precision
|
||||
}
|
||||
|
||||
BASISU_FORCE_INLINE uint32_t q2(basist::half_float x, float log_bias)
|
||||
{
|
||||
union { float f; int32_t i; uint32_t u; } fi;
|
||||
|
||||
fi.f = fast_half_to_float_pos_not_inf_or_nan(x);
|
||||
|
||||
assert(fi.f >= 0.0f);
|
||||
|
||||
fi.f += log_bias;
|
||||
|
||||
return fi.u;
|
||||
}
|
||||
|
||||
double eval_selectors(
|
||||
uint32_t num_pixels,
|
||||
uint8_t* pWeights,
|
||||
uint32_t ise_weight_range,
|
||||
const basist::half_float* pBlock_pixels_half,
|
||||
uint32_t num_weight_levels,
|
||||
const basist::half_float* pDecoded_half,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
uint32_t usable_selector_bitmask = UINT32_MAX);
|
||||
|
||||
double eval_selectors_dual_plane(
|
||||
uint32_t channel_index,
|
||||
uint32_t num_pixels,
|
||||
uint8_t* pWeights0, uint8_t* pWeights1,
|
||||
const basist::half_float* pBlock_pixels_half,
|
||||
uint32_t num_weight_levels,
|
||||
const basist::half_float* pDecoded_half,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
uint32_t usable_selector_bitmask = UINT32_MAX);
|
||||
|
||||
double compute_block_error(uint32_t num_pixels, const basist::half_float* pOrig_block, const basist::half_float* pPacked_block, const astc_hdr_codec_base_options& coptions);
|
||||
|
||||
const uint32_t FIRST_MODE7_SUBMODE_INDEX = 0;
|
||||
const uint32_t MAX_MODE7_SUBMODE_INDEX = 5;
|
||||
|
||||
bool pack_mode7(
|
||||
const vec3F& high_color_q16, const float s_q16,
|
||||
uint32_t ise_endpoint_range, uint8_t* pEndpoints,
|
||||
uint32_t ise_weight_range, // only used for determining biasing during CEM 7 packing
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
int32_t first_submode, int32_t last_submode, bool ignore_clamping, uint32_t& submode_used);
|
||||
|
||||
bool try_mode7(
|
||||
uint32_t num_pixels,
|
||||
uint8_t* pEndpoints, uint8_t* pWeights, double& cur_block_error, uint32_t& submode_used,
|
||||
const vec3F& high_color_q16, const float s_q16,
|
||||
const basist::half_float block_pixels_half[][3],
|
||||
uint32_t num_weight_levels, uint32_t ise_weight_range, const astc_hdr_codec_base_options& coptions,
|
||||
uint32_t ise_endpoint_range,
|
||||
int32_t first_submode = 0, int32_t last_submode = MAX_MODE7_SUBMODE_INDEX);
|
||||
|
||||
bool pack_mode11(
|
||||
const vec3F& low_color_q16, const vec3F& high_color_q16,
|
||||
uint32_t ise_endpoint_range, uint8_t* pEndpoints,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
bool direct_only, int32_t first_submode, int32_t last_submode, bool ignore_clamping, uint32_t& submode_used);
|
||||
|
||||
bool try_mode11(uint32_t num_pixels,
|
||||
uint8_t* pEndpoints, uint8_t* pWeights, double& cur_block_error, uint32_t& submode_used,
|
||||
const vec3F& low_color_q16, const vec3F& high_color_q16,
|
||||
const basist::half_float block_pixels_half[][3],
|
||||
uint32_t num_weight_levels, uint32_t ise_weight_range, const astc_hdr_codec_base_options& coptions, bool direct_only, uint32_t ise_endpoint_range,
|
||||
bool constrain_ise_weight_selectors,
|
||||
int32_t first_submode, int32_t last_submode, bool ignore_clamping);
|
||||
|
||||
bool try_mode11_dual_plane(uint32_t channel_index, uint32_t num_pixels,
|
||||
uint8_t* pEndpoints, uint8_t* pWeights0, uint8_t* pWeights1, double& cur_block_error, uint32_t& submode_used,
|
||||
const vec3F& low_color_q16, const vec3F& high_color_q16,
|
||||
const basist::half_float block_pixels_half[][3],
|
||||
uint32_t num_weight_levels, uint32_t ise_weight_range, const astc_hdr_codec_base_options& coptions, bool direct_only, uint32_t ise_endpoint_range,
|
||||
bool constrain_ise_weight_selectors,
|
||||
int32_t first_submode, int32_t last_submode, bool ignore_clamping);
|
||||
|
||||
const int FIRST_MODE11_SUBMODE_INDEX = -1;
|
||||
const int MAX_MODE11_SUBMODE_INDEX = 7;
|
||||
|
||||
enum opt_mode_t
|
||||
{
|
||||
cNoOpt,
|
||||
cOrdinaryLeastSquares,
|
||||
cWeightedLeastSquares,
|
||||
cWeightedLeastSquaresHeavy,
|
||||
cWeightedAverage
|
||||
};
|
||||
|
||||
struct encode_astc_block_stats
|
||||
{
|
||||
uint32_t m_num_pixels;
|
||||
vec3F m_mean_q16;
|
||||
vec3F m_axis_q16;
|
||||
|
||||
void init(uint32_t num_pixels, const vec4F pBlock_pixels_q16[]);
|
||||
};
|
||||
|
||||
double encode_astc_hdr_block_mode_11(
|
||||
uint32_t num_pixels,
|
||||
const basist::half_float pBlock_pixels_half[][3], const vec4F pBlock_pixels_q16[],
|
||||
uint32_t ise_weight_range,
|
||||
uint32_t& best_submode,
|
||||
double cur_block_error,
|
||||
uint8_t* blk_endpoints, uint8_t* blk_weights,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
bool direct_only,
|
||||
uint32_t ise_endpoint_range,
|
||||
bool uber_mode,
|
||||
bool constrain_ise_weight_selectors,
|
||||
int32_t first_submode, int32_t last_submode, bool ignore_clamping,
|
||||
opt_mode_t opt_mode,
|
||||
const encode_astc_block_stats *pBlock_stats = nullptr);
|
||||
|
||||
double encode_astc_hdr_block_downsampled_mode_11(
|
||||
uint32_t block_x, uint32_t block_y, uint32_t grid_x, uint32_t grid_y,
|
||||
uint32_t ise_weight_range, uint32_t ise_endpoint_range,
|
||||
uint32_t num_pixels, const basist::half_float pBlock_pixels_half[][3], const vec4F pBlock_pixels_q16[],
|
||||
double cur_block_error,
|
||||
int32_t first_submode, int32_t last_submode, bool ignore_clamping, opt_mode_t opt_mode,
|
||||
uint8_t* pBlk_endpoints, uint8_t* pBlk_weights, uint32_t& best_submode,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
const encode_astc_block_stats* pBlock_stats = nullptr);
|
||||
|
||||
double encode_astc_hdr_block_mode_11_dual_plane(
|
||||
uint32_t num_pixels,
|
||||
const basist::half_float pBlock_pixels_half[][3], const vec4F pBlock_pixels_q16[],
|
||||
uint32_t channel_index, // 0-2
|
||||
uint32_t ise_weight_range,
|
||||
uint32_t& best_submode,
|
||||
double cur_block_error,
|
||||
uint8_t* blk_endpoints, uint8_t* blk_weights0, uint8_t* blk_weights1,
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
bool direct_only,
|
||||
uint32_t ise_endpoint_range,
|
||||
bool uber_mode,
|
||||
bool constrain_ise_weight_selectors,
|
||||
int32_t first_submode, int32_t last_submode,
|
||||
bool ignore_clamping);
|
||||
|
||||
double encode_astc_hdr_block_mode_7(
|
||||
uint32_t num_pixels,
|
||||
const basist::half_float pBlock_pixels_half[][3], const vec4F pBlock_pixels_q16[],
|
||||
uint32_t ise_weight_range,
|
||||
uint32_t& best_submode,
|
||||
double cur_block_error,
|
||||
uint8_t* blk_endpoints, //[4]
|
||||
uint8_t* blk_weights, // [num_pixels]
|
||||
const astc_hdr_codec_base_options& coptions,
|
||||
uint32_t ise_endpoint_range,
|
||||
int first_submode = 0, int last_submode = MAX_MODE7_SUBMODE_INDEX,
|
||||
const encode_astc_block_stats *pBlock_stats = nullptr);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct mode11_log_desc
|
||||
{
|
||||
int32_t m_submode;
|
||||
int32_t m_maj_comp;
|
||||
|
||||
// Or R0, G0, B0 if maj_comp==3 (direct)
|
||||
int32_t m_a; // positive
|
||||
int32_t m_c; // positive
|
||||
int32_t m_b0; // positive
|
||||
|
||||
// Or R1, G1, B1 if maj_comp==3 (direct)
|
||||
int32_t m_b1; // positive
|
||||
int32_t m_d0; // if not direct, is signed
|
||||
int32_t m_d1; // if not direct, is signed
|
||||
|
||||
// limits if not direct
|
||||
int32_t m_a_bits, m_c_bits, m_b_bits, m_d_bits;
|
||||
int32_t m_max_a_val, m_max_c_val, m_max_b_val, m_min_d_val, m_max_d_val;
|
||||
|
||||
void clear() { clear_obj(*this); }
|
||||
|
||||
bool is_direct() const { return m_maj_comp == 3; }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
bool pack_astc_mode7_submode(uint32_t submode, uint8_t* pEndpoints, const vec3F& rgb_q16, float s_q16, int& max_clamp_mag, uint32_t ise_weight_range, bool early_out_if_clamped, int max_clamp_mag_accept_thresh);
|
||||
|
||||
bool pack_astc_mode11_submode(uint32_t submode, uint8_t* pEndpoints, int val_q[2][3], int& max_clamp_mag, bool early_out_if_clamped = false, int max_clamp_mag_accept_thresh = 0);
|
||||
bool pack_astc_mode11_submode(uint32_t submode, uint8_t* pEndpoints, const vec3F& low_q16, const vec3F& high_q16, int& max_clamp_mag, bool early_out_if_clamped = false, int max_clamp_mag_accept_thresh = 0);
|
||||
void pack_astc_mode11_direct(uint8_t* pEndpoints, vec3F l_q16, vec3F h_q16);
|
||||
|
||||
bool pack_mode11(mode11_log_desc& desc, uint8_t* pEndpoints);
|
||||
void unpack_mode11(const uint8_t* pEndpoints, mode11_log_desc& desc);
|
||||
|
||||
void decode_cem_11_config(const uint8_t* pEndpoints, int& submode_index, int& maj_index);
|
||||
void decode_cem_7_config(const uint8_t* pEndpoints, int& submode_index, int& maj_index);
|
||||
|
||||
void dequantize_astc_weights(uint32_t n, const uint8_t* pSrc_ise_vals, uint32_t from_ise_range, uint8_t* pDst_raw_weights);
|
||||
|
||||
const float* get_6x6_downsample_matrix(uint32_t grid_width, uint32_t grid_height);
|
||||
|
||||
void downsample_weight_grid(
|
||||
const float* pMatrix_weights,
|
||||
uint32_t bx, uint32_t by, // source/from dimension (block size)
|
||||
uint32_t wx, uint32_t wy, // dest/to dimension (grid size)
|
||||
const uint8_t* pSrc_weights, // these are dequantized weights, NOT ISE symbols, [by][bx]
|
||||
uint8_t* pDst_weights); // [wy][wx]
|
||||
|
||||
void downsample_ise_weights(
|
||||
uint32_t weight_ise_range, uint32_t quant_weight_ise_range,
|
||||
uint32_t block_w, uint32_t block_h,
|
||||
uint32_t grid_w, uint32_t grid_h,
|
||||
const uint8_t* pSrc_weights, uint8_t* pDst_weights);
|
||||
|
||||
void downsample_ise_weights_dual_plane(
|
||||
uint32_t dequant_weight_ise_range, uint32_t quant_weight_ise_range,
|
||||
uint32_t block_w, uint32_t block_h,
|
||||
uint32_t grid_w, uint32_t grid_h,
|
||||
const uint8_t* pSrc_weights0, const uint8_t* pSrc_weights1,
|
||||
uint8_t* pDst_weights);
|
||||
|
||||
bool refine_endpoints(
|
||||
uint32_t cem,
|
||||
uint32_t endpoint_ise_range,
|
||||
uint8_t* pEndpoint_vals, // the endpoints to optimize
|
||||
uint32_t block_w, uint32_t block_h, // block dimensions
|
||||
uint32_t grid_w, uint32_t grid_h, const uint8_t* pWeights, uint32_t weight_ise_range, // weight grid
|
||||
uint32_t num_pixels, const basist::half_float pBlock_pixels_half[][3], const vec4F pBlock_pixels_q16[],
|
||||
const uint8_t* pPixel_block_ofs, // maps this subset's pixels to block offsets
|
||||
astc_hdr_codec_base_options& coptions, opt_mode_t opt_mode);
|
||||
|
||||
extern bool g_astc_hdr_enc_initialized;
|
||||
|
||||
// This MUST be called before encoding any blocks.
|
||||
void astc_hdr_enc_init();
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+733
-268
File diff suppressed because it is too large
Load Diff
+209
-64
@@ -18,10 +18,11 @@
|
||||
#include "basisu_basis_file.h"
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
#include "basisu_uastc_enc.h"
|
||||
#include "basisu_astc_hdr_enc.h"
|
||||
#include "basisu_uastc_hdr_4x4_enc.h"
|
||||
#include "basisu_astc_hdr_6x6_enc.h"
|
||||
|
||||
#define BASISU_LIB_VERSION 150
|
||||
#define BASISU_LIB_VERSION_STRING "1.50"
|
||||
#define BASISU_LIB_VERSION 160
|
||||
#define BASISU_LIB_VERSION_STRING "1.60"
|
||||
|
||||
#ifndef BASISD_SUPPORT_KTX2
|
||||
#error BASISD_SUPPORT_KTX2 is undefined
|
||||
@@ -76,6 +77,8 @@ namespace basisu
|
||||
m_height = 0;
|
||||
|
||||
m_basis_rgb_avg_psnr = 0.0f;
|
||||
m_basis_rgb_avg_log2_psnr = 0.0f;
|
||||
|
||||
m_basis_rgba_avg_psnr = 0.0f;
|
||||
m_basis_a_avg_psnr = 0.0f;
|
||||
m_basis_luma_709_psnr = 0.0f;
|
||||
@@ -83,6 +86,7 @@ namespace basisu
|
||||
m_basis_luma_709_ssim = 0.0f;
|
||||
|
||||
m_basis_rgb_avg_bc6h_psnr = 0.0f;
|
||||
m_basis_rgb_avg_bc6h_log2_psnr = 0.0f;
|
||||
|
||||
m_bc7_rgb_avg_psnr = 0.0f;
|
||||
m_bc7_rgba_avg_psnr = 0.0f;
|
||||
@@ -105,6 +109,8 @@ namespace basisu
|
||||
|
||||
// .basis/.ktx2 compressed (LDR: ETC1S or UASTC statistics, HDR: transcoded BC6H statistics)
|
||||
float m_basis_rgb_avg_psnr;
|
||||
float m_basis_rgb_avg_log2_psnr;
|
||||
|
||||
float m_basis_rgba_avg_psnr;
|
||||
float m_basis_a_avg_psnr;
|
||||
float m_basis_luma_709_psnr;
|
||||
@@ -113,6 +119,7 @@ namespace basisu
|
||||
|
||||
// UASTC HDR only.
|
||||
float m_basis_rgb_avg_bc6h_psnr;
|
||||
float m_basis_rgb_avg_bc6h_log2_psnr;
|
||||
|
||||
// LDR: BC7 statistics
|
||||
float m_bc7_rgb_avg_psnr;
|
||||
@@ -131,6 +138,17 @@ namespace basisu
|
||||
bool m_opencl_failed;
|
||||
};
|
||||
|
||||
enum class hdr_modes
|
||||
{
|
||||
// standard but constrained ASTC HDR 4x4 tex data that can be rapidly transcoded to BC6H
|
||||
cUASTC_HDR_4X4,
|
||||
// standard RDO optimized or non-RDO (highest quality) ASTC HDR 6x6 tex data that can be rapidly re-encoded to BC6H
|
||||
cASTC_HDR_6X6,
|
||||
// a custom intermediate format based off ASTC HDR that can be rapidly decoded straight to ASTC HDR or re-encoded to BC6H
|
||||
cASTC_HDR_6X6_INTERMEDIATE,
|
||||
cTotal
|
||||
};
|
||||
|
||||
template<bool def>
|
||||
struct bool_param
|
||||
{
|
||||
@@ -220,21 +238,23 @@ namespace basisu
|
||||
m_endpoint_rdo_thresh(BASISU_DEFAULT_ENDPOINT_RDO_THRESH, 0.0f, 1e+10f),
|
||||
m_mip_scale(1.0f, .000125f, 4.0f),
|
||||
m_mip_smallest_dimension(1, 1, 16384),
|
||||
m_max_endpoint_clusters(512),
|
||||
m_max_selector_clusters(512),
|
||||
m_quality_level(-1),
|
||||
m_pack_uastc_flags(cPackUASTCLevelDefault),
|
||||
m_rdo_uastc_quality_scalar(1.0f, 0.001f, 50.0f),
|
||||
m_rdo_uastc_dict_size(BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX),
|
||||
m_rdo_uastc_max_smooth_block_error_scale(UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE, 1.0f, 300.0f),
|
||||
m_rdo_uastc_smooth_block_max_std_dev(UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV, .01f, 65536.0f),
|
||||
m_rdo_uastc_max_allowed_rms_increase_ratio(UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, .01f, 100.0f),
|
||||
m_rdo_uastc_skip_block_rms_thresh(UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, .01f, 100.0f),
|
||||
m_etc1s_max_endpoint_clusters(512),
|
||||
m_etc1s_max_selector_clusters(512),
|
||||
m_etc1s_quality_level(-1),
|
||||
m_pack_uastc_ldr_4x4_flags(cPackUASTCLevelDefault),
|
||||
m_rdo_uastc_ldr_4x4_quality_scalar(1.0f, 0.001f, 50.0f),
|
||||
m_rdo_uastc_ldr_4x4_dict_size(BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, BASISU_RDO_UASTC_DICT_SIZE_MIN, BASISU_RDO_UASTC_DICT_SIZE_MAX),
|
||||
m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale(UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE, 1.0f, 300.0f),
|
||||
m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev(UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV, .01f, 65536.0f),
|
||||
m_rdo_uastc_ldr_4x4_max_allowed_rms_increase_ratio(UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO, .01f, 100.0f),
|
||||
m_rdo_uastc_ldr_4x4_skip_block_rms_thresh(UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH, .01f, 100.0f),
|
||||
m_resample_width(0, 1, 16384),
|
||||
m_resample_height(0, 1, 16384),
|
||||
m_resample_factor(0.0f, .00125f, 100.0f),
|
||||
m_ktx2_uastc_supercompression(basist::KTX2_SS_NONE),
|
||||
m_ktx2_zstd_supercompression_level(6, INT_MIN, INT_MAX),
|
||||
m_ldr_hdr_upconversion_nit_multiplier(0.0f, 0.0f, basist::MAX_HALF_FLOAT),
|
||||
m_ldr_hdr_upconversion_black_bias(0.0f, 0.0f, 1.0f),
|
||||
m_pJob_pool(nullptr)
|
||||
{
|
||||
clear();
|
||||
@@ -243,6 +263,9 @@ namespace basisu
|
||||
void clear()
|
||||
{
|
||||
m_uastc.clear();
|
||||
m_hdr.clear();
|
||||
m_hdr_mode = hdr_modes::cUASTC_HDR_4X4;
|
||||
|
||||
m_use_opencl.clear();
|
||||
m_status_output.clear();
|
||||
|
||||
@@ -290,24 +313,24 @@ namespace basisu
|
||||
m_mip_fast.clear();
|
||||
m_mip_smallest_dimension.clear();
|
||||
|
||||
m_max_endpoint_clusters = 0;
|
||||
m_max_selector_clusters = 0;
|
||||
m_quality_level = -1;
|
||||
m_etc1s_max_endpoint_clusters = 0;
|
||||
m_etc1s_max_selector_clusters = 0;
|
||||
m_etc1s_quality_level = -1;
|
||||
|
||||
m_tex_type = basist::cBASISTexType2D;
|
||||
m_userdata0 = 0;
|
||||
m_userdata1 = 0;
|
||||
m_us_per_frame = 0;
|
||||
|
||||
m_pack_uastc_flags = cPackUASTCLevelDefault;
|
||||
m_rdo_uastc.clear();
|
||||
m_rdo_uastc_quality_scalar.clear();
|
||||
m_rdo_uastc_max_smooth_block_error_scale.clear();
|
||||
m_rdo_uastc_smooth_block_max_std_dev.clear();
|
||||
m_rdo_uastc_max_allowed_rms_increase_ratio.clear();
|
||||
m_rdo_uastc_skip_block_rms_thresh.clear();
|
||||
m_rdo_uastc_favor_simpler_modes_in_rdo_mode.clear();
|
||||
m_rdo_uastc_multithreading.clear();
|
||||
m_pack_uastc_ldr_4x4_flags = cPackUASTCLevelDefault;
|
||||
m_rdo_uastc_ldr_4x4.clear();
|
||||
m_rdo_uastc_ldr_4x4_quality_scalar.clear();
|
||||
m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale.clear();
|
||||
m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev.clear();
|
||||
m_rdo_uastc_ldr_4x4_max_allowed_rms_increase_ratio.clear();
|
||||
m_rdo_uastc_ldr_4x4_skip_block_rms_thresh.clear();
|
||||
m_rdo_uastc_ldr_4x4_favor_simpler_modes_in_rdo_mode.clear();
|
||||
m_rdo_uastc_ldr_4x4_multithreading.clear();
|
||||
|
||||
m_resample_width.clear();
|
||||
m_resample_height.clear();
|
||||
@@ -323,19 +346,80 @@ namespace basisu
|
||||
|
||||
m_validate_output_data.clear();
|
||||
|
||||
m_hdr_ldr_srgb_to_linear_conversion.clear();
|
||||
m_ldr_hdr_upconversion_srgb_to_linear.clear();
|
||||
|
||||
m_hdr_favor_astc.clear();
|
||||
|
||||
m_uastc_hdr_4x4_options.init();
|
||||
m_astc_hdr_6x6_options.clear();
|
||||
|
||||
m_ldr_hdr_upconversion_nit_multiplier.clear();
|
||||
m_ldr_hdr_upconversion_black_bias.clear();
|
||||
|
||||
m_pJob_pool = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Configures the compressor's mode by setting the proper parameters (which were preserved for backwards compatibility with old code).
|
||||
void set_format_mode(basist::basis_tex_format m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case basist::basis_tex_format::cETC1S:
|
||||
{
|
||||
m_hdr = false;
|
||||
m_uastc = false;
|
||||
m_hdr_mode = hdr_modes::cUASTC_HDR_4X4; // doesn't matter
|
||||
break;
|
||||
}
|
||||
case basist::basis_tex_format::cUASTC4x4:
|
||||
{
|
||||
m_hdr = false;
|
||||
m_uastc = true;
|
||||
m_hdr_mode = hdr_modes::cUASTC_HDR_4X4; // doesn't matter
|
||||
break;
|
||||
}
|
||||
case basist::basis_tex_format::cUASTC_HDR_4x4:
|
||||
{
|
||||
m_hdr = true;
|
||||
m_uastc = true;
|
||||
m_hdr_mode = hdr_modes::cUASTC_HDR_4X4;
|
||||
break;
|
||||
}
|
||||
case basist::basis_tex_format::cASTC_HDR_6x6:
|
||||
{
|
||||
m_hdr = true;
|
||||
m_uastc = true;
|
||||
m_hdr_mode = hdr_modes::cASTC_HDR_6X6;
|
||||
break;
|
||||
}
|
||||
case basist::basis_tex_format::cASTC_HDR_6x6_INTERMEDIATE:
|
||||
{
|
||||
m_hdr = true;
|
||||
m_uastc = true;
|
||||
m_hdr_mode = hdr_modes::cASTC_HDR_6X6_INTERMEDIATE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// By default we generate LDR ETC1S data.
|
||||
// if m_uastc is true but m_hdr is not true, we generate UASTC 4x4 LDR data (8bpp with or without RDO).
|
||||
// if m_uastc is true and m_hdr is true, we generate 4x4 or 6x6 HDR data (either standard ASTC, constrained ASTC, RDO ASTC, or intermediate), controlled by m_hdr_mode.
|
||||
|
||||
// True to generate UASTC .basis/.KTX2 file data, otherwise ETC1S.
|
||||
// Should be true for any non-ETC1S format (UASTC 4x4 LDR, UASTC 4x4 HDR, RDO ASTC 6x6 HDR, and ASTC 6x6 HDR intermediate).
|
||||
bool_param<false> m_uastc;
|
||||
|
||||
// Set m_hdr to true to switch to UASTC HDR mode.
|
||||
// Set m_hdr to true to switch to UASTC HDR mode. m_hdr_mode then controls which format is output.
|
||||
// m_hdr_mode then controls which format is output (4x4, 6x6, or 6x6 intermediate).
|
||||
bool_param<false> m_hdr;
|
||||
|
||||
// If m_hdr is true, this specifies which mode we operate in (currently UASTC 4x4 HDR or ASTC 6x6 HDR). Defaults to UASTC 4x4 HDR for backwards compatibility.
|
||||
hdr_modes m_hdr_mode;
|
||||
|
||||
bool_param<false> m_use_opencl;
|
||||
|
||||
// If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG etc. images to read.
|
||||
@@ -426,30 +510,31 @@ namespace basisu
|
||||
bool_param<true> m_mip_fast;
|
||||
param<int> m_mip_smallest_dimension;
|
||||
|
||||
// Codebook size (quality) control.
|
||||
// If m_quality_level != -1, it controls the quality level. It ranges from [1,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
|
||||
// ETC1S codebook size (quality) control.
|
||||
// If m_etc1s_quality_level != -1, it controls the quality level. It ranges from [1,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
|
||||
// Otherwise m_max_endpoint_clusters/m_max_selector_clusters controls the codebook sizes directly.
|
||||
uint32_t m_max_endpoint_clusters;
|
||||
uint32_t m_max_selector_clusters;
|
||||
int m_quality_level;
|
||||
uint32_t m_etc1s_max_endpoint_clusters;
|
||||
uint32_t m_etc1s_max_selector_clusters;
|
||||
int m_etc1s_quality_level;
|
||||
|
||||
// m_tex_type, m_userdata0, m_userdata1, m_framerate - These fields go directly into the Basis file header.
|
||||
// m_tex_type, m_userdata0, m_userdata1, m_framerate - These fields go directly into the .basis file header.
|
||||
basist::basis_texture_type m_tex_type;
|
||||
uint32_t m_userdata0;
|
||||
uint32_t m_userdata1;
|
||||
uint32_t m_us_per_frame;
|
||||
|
||||
// UASTC LDR 4x4 parameters
|
||||
// cPackUASTCLevelDefault, etc.
|
||||
uint32_t m_pack_uastc_flags;
|
||||
bool_param<false> m_rdo_uastc;
|
||||
param<float> m_rdo_uastc_quality_scalar;
|
||||
param<int> m_rdo_uastc_dict_size;
|
||||
param<float> m_rdo_uastc_max_smooth_block_error_scale;
|
||||
param<float> m_rdo_uastc_smooth_block_max_std_dev;
|
||||
param<float> m_rdo_uastc_max_allowed_rms_increase_ratio;
|
||||
param<float> m_rdo_uastc_skip_block_rms_thresh;
|
||||
bool_param<true> m_rdo_uastc_favor_simpler_modes_in_rdo_mode;
|
||||
bool_param<true> m_rdo_uastc_multithreading;
|
||||
uint32_t m_pack_uastc_ldr_4x4_flags;
|
||||
bool_param<false> m_rdo_uastc_ldr_4x4;
|
||||
param<float> m_rdo_uastc_ldr_4x4_quality_scalar;
|
||||
param<int> m_rdo_uastc_ldr_4x4_dict_size;
|
||||
param<float> m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale;
|
||||
param<float> m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev;
|
||||
param<float> m_rdo_uastc_ldr_4x4_max_allowed_rms_increase_ratio;
|
||||
param<float> m_rdo_uastc_ldr_4x4_skip_block_rms_thresh;
|
||||
bool_param<true> m_rdo_uastc_ldr_4x4_favor_simpler_modes_in_rdo_mode;
|
||||
bool_param<true> m_rdo_uastc_ldr_4x4_multithreading;
|
||||
|
||||
param<int> m_resample_width;
|
||||
param<int> m_resample_height;
|
||||
@@ -465,13 +550,26 @@ namespace basisu
|
||||
param<int> m_ktx2_zstd_supercompression_level;
|
||||
bool_param<false> m_ktx2_srgb_transfer_func;
|
||||
|
||||
astc_hdr_codec_options m_uastc_hdr_options;
|
||||
uastc_hdr_4x4_codec_options m_uastc_hdr_4x4_options;
|
||||
astc_6x6_hdr::astc_hdr_6x6_global_config m_astc_hdr_6x6_options;
|
||||
|
||||
bool_param<false> m_validate_output_data;
|
||||
|
||||
// If true, LDR images (such as PNG) will be converted to normalized [0,1] linear light (via a sRGB->Linear conversion) and then processed as HDR.
|
||||
// Otherwise, LDR images will be processed as HDR as-is.
|
||||
bool_param<true> m_hdr_ldr_srgb_to_linear_conversion;
|
||||
// LDR->HDR upconversion parameters.
|
||||
//
|
||||
// If true, LDR images (such as PNG) will be converted to normalized [0,1] linear light (via a sRGB->Linear conversion), or absolute luminance (nits or candelas per meter squared), and then processed as HDR.
|
||||
// Otherwise, LDR images are assumed to already be in linear light (i.e. they don't use the sRGB transfer function).
|
||||
bool_param<true> m_ldr_hdr_upconversion_srgb_to_linear;
|
||||
|
||||
// m_ldr_hdr_upconversion_nit_multiplier is only used when loading SDR/LDR images and compressing to an HDR output format.
|
||||
// By default m_ldr_hdr_upconversion_nit_multiplier is 0. It's an override for the default.
|
||||
// When loading LDR images, a default multiplier of 1.0 will be used in UASTC 4x4 HDR mode. Partially for backwards compatibility with previous library releases, and also because it doesn't really matter with this encoder what the multiplier is.
|
||||
// With the 6x6 HDR encoder it does matter because it expects inputs in absolute nits, so the LDR upconversion luminance multiplier default will be 100 nits. (Most SDR monitors were/are 80-100 nits or so.)
|
||||
param<float> m_ldr_hdr_upconversion_nit_multiplier;
|
||||
|
||||
// The optional sRGB space bias to use during LDR->HDR upconversion. Should be between [0,.49] or so. Only applied on black (0.0) color components.
|
||||
// Defaults to no bias (0.0f).
|
||||
param<float> m_ldr_hdr_upconversion_black_bias;
|
||||
|
||||
// If true, ASTC HDR quality is favored more than BC6H quality. Otherwise it's a rough balance.
|
||||
bool_param<false> m_hdr_favor_astc;
|
||||
@@ -526,8 +624,10 @@ namespace basisu
|
||||
|
||||
private:
|
||||
basis_compressor_params m_params;
|
||||
|
||||
|
||||
opencl_context_ptr m_pOpenCL_context;
|
||||
|
||||
basist::basis_tex_format m_fmt_mode;
|
||||
|
||||
basisu::vector<image> m_slice_images;
|
||||
basisu::vector<imagef> m_slice_images_hdr;
|
||||
@@ -543,6 +643,7 @@ namespace basisu
|
||||
|
||||
basisu_frontend m_frontend;
|
||||
|
||||
// These are 4x4 blocks.
|
||||
pixel_block_vec m_source_blocks;
|
||||
pixel_block_hdr_vec m_source_blocks_hdr;
|
||||
|
||||
@@ -572,6 +673,15 @@ namespace basisu
|
||||
basisu::vector<gpu_image> m_uastc_slice_textures;
|
||||
basisu_backend_output m_uastc_backend_output;
|
||||
|
||||
// The amount the HDR input has to be scaled up in case it had to be rescaled to fit into half floats.
|
||||
float m_hdr_image_scale;
|
||||
|
||||
// The upconversion multiplier used to load LDR images in HDR mode.
|
||||
float m_ldr_to_hdr_upconversion_nit_multiplier;
|
||||
|
||||
// True if any loaded source images were LDR and upconverted to HDR.
|
||||
bool m_upconverted_any_ldr_images;
|
||||
|
||||
bool m_any_source_image_has_alpha;
|
||||
|
||||
bool m_opencl_failed;
|
||||
@@ -588,14 +698,48 @@ namespace basisu
|
||||
bool create_basis_file_and_transcode();
|
||||
bool write_hdr_debug_images(const char* pBasename, const imagef& img, uint32_t width, uint32_t height);
|
||||
bool write_output_files_and_compute_stats();
|
||||
error_code encode_slices_to_uastc_hdr();
|
||||
error_code encode_slices_to_uastc();
|
||||
error_code encode_slices_to_astc_6x6_hdr();
|
||||
error_code encode_slices_to_uastc_4x4_hdr();
|
||||
error_code encode_slices_to_uastc_4x4_ldr();
|
||||
bool generate_mipmaps(const imagef& img, basisu::vector<imagef>& mips, bool has_alpha);
|
||||
bool generate_mipmaps(const image &img, basisu::vector<image> &mips, bool has_alpha);
|
||||
bool validate_texture_type_constraints();
|
||||
bool validate_ktx2_constraints();
|
||||
void get_dfd(uint8_vec& dfd, const basist::ktx2_header& hdr);
|
||||
bool get_dfd(uint8_vec& dfd, const basist::ktx2_header& hdr);
|
||||
bool create_ktx2_file();
|
||||
void pick_format_mode();
|
||||
|
||||
uint32_t get_block_width() const
|
||||
{
|
||||
if (m_params.m_hdr)
|
||||
{
|
||||
switch (m_params.m_hdr_mode)
|
||||
{
|
||||
case hdr_modes::cASTC_HDR_6X6:
|
||||
case hdr_modes::cASTC_HDR_6X6_INTERMEDIATE:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint32_t get_block_height() const
|
||||
{
|
||||
if (m_params.m_hdr)
|
||||
{
|
||||
switch (m_params.m_hdr_mode)
|
||||
{
|
||||
case hdr_modes::cASTC_HDR_6X6:
|
||||
case hdr_modes::cASTC_HDR_6X6_INTERMEDIATE:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
|
||||
// Alternative simple C-style wrapper API around the basis_compressor class.
|
||||
@@ -628,21 +772,19 @@ namespace basisu
|
||||
cFlagKTX2UASTCSuperCompression = 1 << 12, // use KTX2 Zstd supercompression on UASTC files
|
||||
|
||||
cFlagSRGB = 1 << 13, // input texture is sRGB, use perceptual colorspace metrics, also use sRGB filtering during mipmap gen, and also sets KTX2 output transfer func to sRGB
|
||||
cFlagGenMipsClamp = 1 << 14, // generate mipmaps with clamp addressing
|
||||
cFlagGenMipsWrap = 1 << 15, // generate mipmaps with wrap addressing
|
||||
cFlagGenMipsClamp = 1 << 14, // generate mipmaps with clamp addressing
|
||||
cFlagGenMipsWrap = 1 << 15, // generate mipmaps with wrap addressing
|
||||
|
||||
cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
|
||||
cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
|
||||
|
||||
cFlagUASTC = 1 << 17, // use UASTC compression vs. ETC1S
|
||||
cFlagUASTCRDO = 1 << 18, // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
|
||||
cFlagUASTCRDO = 1 << 17, // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
|
||||
|
||||
cFlagPrintStats = 1 << 19, // print image stats to stdout
|
||||
cFlagPrintStatus = 1 << 20, // print status to stdout
|
||||
cFlagPrintStats = 1 << 18, // print image stats to stdout
|
||||
cFlagPrintStatus = 1 << 19, // print status to stdout
|
||||
|
||||
cFlagHDR = 1 << 21, // Force encoder into HDR mode, even if source image is LDR.
|
||||
cFlagHDRLDRImageSRGBToLinearConversion = 1 << 22, // In HDR mode, convert LDR source images to linear before encoding.
|
||||
|
||||
cFlagDebugImages = 1 << 23 // enable status output
|
||||
cFlagDebugImages = 1 << 20, // enable status output
|
||||
|
||||
cFlagREC2020 = 1 << 21 // ASTC 6x6 modes: treat input as REC 2020 vs. the default 709
|
||||
};
|
||||
|
||||
// This function accepts an array of source images.
|
||||
@@ -652,6 +794,7 @@ namespace basisu
|
||||
// basisu_encoder_init() MUST be called first!
|
||||
// LDR version. To compress the LDR source image as HDR: Use the cFlagHDR flag.
|
||||
void* basis_compress(
|
||||
basist::basis_tex_format mode,
|
||||
const basisu::vector<image> &source_images,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
size_t* pSize,
|
||||
@@ -660,14 +803,16 @@ namespace basisu
|
||||
// HDR-only version.
|
||||
// Important: The returned block MUST be manually freed using basis_free_data().
|
||||
void* basis_compress(
|
||||
basist::basis_tex_format mode,
|
||||
const basisu::vector<imagef>& source_images_hdr,
|
||||
uint32_t flags_and_quality,
|
||||
uint32_t flags_and_quality, float lambda,
|
||||
size_t* pSize,
|
||||
image_stats* pStats = nullptr);
|
||||
|
||||
// This function only accepts a single LDR source image. It's just a wrapper for basis_compress() above.
|
||||
// Important: The returned block MUST be manually freed using basis_free_data().
|
||||
void* basis_compress(
|
||||
basist::basis_tex_format mode,
|
||||
const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
size_t* pSize,
|
||||
|
||||
+328
-46
File diff suppressed because it is too large
Load Diff
+432
-151
File diff suppressed because it is too large
Load Diff
+16
-94
@@ -353,9 +353,7 @@ namespace basisu
|
||||
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++)
|
||||
{
|
||||
@@ -388,15 +386,11 @@ namespace basisu
|
||||
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++)
|
||||
@@ -425,9 +419,7 @@ namespace basisu
|
||||
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++)
|
||||
{
|
||||
@@ -475,15 +467,11 @@ namespace basisu
|
||||
|
||||
} // 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());
|
||||
@@ -501,9 +489,7 @@ namespace basisu
|
||||
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++)
|
||||
{
|
||||
@@ -535,15 +521,11 @@ namespace basisu
|
||||
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++)
|
||||
@@ -573,7 +555,7 @@ namespace basisu
|
||||
debug_printf("introduce_special_selector_clusters\n");
|
||||
|
||||
uint32_t total_blocks_relocated = 0;
|
||||
const uint32_t initial_selector_clusters = (uint32_t)m_selector_cluster_block_indices.size();
|
||||
const uint32_t initial_selector_clusters = m_selector_cluster_block_indices.size_u32();
|
||||
|
||||
bool_vec block_relocated_flags(m_total_blocks);
|
||||
|
||||
@@ -595,7 +577,7 @@ namespace basisu
|
||||
|
||||
debug_printf("Introducing sel %u\n", sel);
|
||||
|
||||
const uint32_t new_selector_cluster_index = (uint32_t)m_optimized_cluster_selectors.size();
|
||||
const uint32_t new_selector_cluster_index = m_optimized_cluster_selectors.size_u32();
|
||||
|
||||
m_optimized_cluster_selectors.push_back(blk);
|
||||
|
||||
@@ -675,7 +657,7 @@ namespace basisu
|
||||
{
|
||||
debug_printf("optimize_selector_codebook\n");
|
||||
|
||||
const uint32_t orig_total_selector_clusters = (uint32_t)m_optimized_cluster_selectors.size();
|
||||
const uint32_t orig_total_selector_clusters = m_optimized_cluster_selectors.size_u32();
|
||||
|
||||
bool_vec selector_cluster_was_used(m_optimized_cluster_selectors.size());
|
||||
for (uint32_t i = 0; i < m_total_blocks; i++)
|
||||
@@ -787,9 +769,7 @@ namespace basisu
|
||||
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++)
|
||||
{
|
||||
@@ -830,15 +810,11 @@ namespace basisu
|
||||
blk.set_selector(x, y, selectors[x + y * 4]);
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
} // use_cpu
|
||||
|
||||
@@ -859,9 +835,7 @@ namespace basisu
|
||||
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, &training_vecs] {
|
||||
#endif
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
{
|
||||
@@ -883,15 +857,11 @@ namespace basisu
|
||||
|
||||
} // block_index;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
} );
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
void basisu_frontend::generate_endpoint_clusters()
|
||||
@@ -970,7 +940,7 @@ namespace basisu
|
||||
}
|
||||
|
||||
if (m_params.m_debug_stats)
|
||||
debug_printf("Total endpoint clusters: %u, parent clusters: %u\n", (uint32_t)m_endpoint_clusters.size(), (uint32_t)m_endpoint_parent_clusters.size());
|
||||
debug_printf("Total endpoint clusters: %u, parent clusters: %u\n", m_endpoint_clusters.size_u32(), m_endpoint_parent_clusters.size_u32());
|
||||
}
|
||||
|
||||
// Iterate through each array of endpoint cluster block indices and set the m_block_endpoint_clusters_indices[][] array to indicaste which cluster index each block uses.
|
||||
@@ -1040,11 +1010,9 @@ namespace basisu
|
||||
for (uint32_t cluster_index_iter = 0; cluster_index_iter < m_endpoint_clusters.size(); cluster_index_iter += N)
|
||||
{
|
||||
const uint32_t first_index = cluster_index_iter;
|
||||
const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
|
||||
const uint32_t last_index = minimum<uint32_t>(m_endpoint_clusters.size_u32(), cluster_index_iter + N);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
|
||||
#endif
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
@@ -1112,15 +1080,11 @@ namespace basisu
|
||||
}
|
||||
} // cluster_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
} );
|
||||
#endif
|
||||
|
||||
} // cluster_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
vector_sort(m_subblock_endpoint_quant_err_vec);
|
||||
}
|
||||
@@ -1131,19 +1095,19 @@ namespace basisu
|
||||
|
||||
generate_block_endpoint_clusters();
|
||||
|
||||
int num_new_endpoint_clusters = m_params.m_max_endpoint_clusters - (uint32_t)m_endpoint_clusters.size();
|
||||
int num_new_endpoint_clusters = m_params.m_max_endpoint_clusters - m_endpoint_clusters.size_u32();
|
||||
if (num_new_endpoint_clusters <= 0)
|
||||
return;
|
||||
|
||||
compute_endpoint_subblock_error_vec();
|
||||
|
||||
const uint32_t num_orig_endpoint_clusters = (uint32_t)m_endpoint_clusters.size();
|
||||
const uint32_t num_orig_endpoint_clusters = m_endpoint_clusters.size_u32();
|
||||
|
||||
std::unordered_set<uint32_t> training_vector_was_relocated;
|
||||
|
||||
uint_vec cluster_sizes(num_orig_endpoint_clusters);
|
||||
for (uint32_t i = 0; i < num_orig_endpoint_clusters; i++)
|
||||
cluster_sizes[i] = (uint32_t)m_endpoint_clusters[i].size();
|
||||
cluster_sizes[i] = m_endpoint_clusters[i].size_u32();
|
||||
|
||||
std::unordered_set<uint32_t> ignore_cluster;
|
||||
|
||||
@@ -1259,7 +1223,7 @@ namespace basisu
|
||||
// TODO: Get this working when step>0
|
||||
if (m_params.m_pOpenCL_context && !step)
|
||||
{
|
||||
const uint32_t total_clusters = m_endpoint_clusters.size();
|
||||
const uint32_t total_clusters = (uint32_t)m_endpoint_clusters.size();
|
||||
|
||||
basisu::vector<cl_pixel_cluster> pixel_clusters(total_clusters);
|
||||
|
||||
@@ -1342,7 +1306,7 @@ namespace basisu
|
||||
|
||||
} // cluster_indices_iter
|
||||
|
||||
uint32_t* pSorted = radix_sort(colors.size(), colors.data(), colors2.data(), 0, 3);
|
||||
uint32_t* pSorted = radix_sort((uint32_t)colors.size(), colors.data(), colors2.data(), 0, 3);
|
||||
|
||||
const uint64_t first_pixel_index = input_pixels.size();
|
||||
|
||||
@@ -1522,9 +1486,7 @@ namespace basisu
|
||||
const uint32_t first_index = cluster_index_iter;
|
||||
const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->add_job([this, first_index, last_index, step] {
|
||||
#endif
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
@@ -1643,15 +1605,11 @@ namespace basisu
|
||||
|
||||
} // cluster_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
});
|
||||
#endif
|
||||
|
||||
} // cluster_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
}
|
||||
|
||||
debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
|
||||
@@ -1726,14 +1684,14 @@ namespace basisu
|
||||
{
|
||||
// For the OpenCL kernel, we order the parent endpoint clusters by smallest to largest for efficiency.
|
||||
// We also prepare an array of block info structs that point into this new parent endpoint cluster array.
|
||||
const uint32_t total_parent_clusters = m_endpoint_clusters_within_each_parent_cluster.size();
|
||||
const uint32_t total_parent_clusters = (uint32_t)m_endpoint_clusters_within_each_parent_cluster.size();
|
||||
|
||||
basisu::vector<cl_block_info_struct> cl_block_info_structs(m_total_blocks);
|
||||
|
||||
// the size of each parent cluster, in total clusters
|
||||
uint_vec parent_cluster_sizes(total_parent_clusters);
|
||||
for (uint32_t i = 0; i < total_parent_clusters; i++)
|
||||
parent_cluster_sizes[i] = m_endpoint_clusters_within_each_parent_cluster[i].size();
|
||||
parent_cluster_sizes[i] = (uint32_t)m_endpoint_clusters_within_each_parent_cluster[i].size();
|
||||
|
||||
uint_vec first_parent_cluster_ofs(total_parent_clusters);
|
||||
uint32_t cur_ofs = 0;
|
||||
@@ -1818,9 +1776,7 @@ namespace basisu
|
||||
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, &best_cluster_indices, &block_clusters] {
|
||||
#endif
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
{
|
||||
@@ -1951,15 +1907,11 @@ namespace basisu
|
||||
|
||||
} // block_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
});
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
} // use_cpu
|
||||
|
||||
@@ -2104,9 +2056,7 @@ namespace basisu
|
||||
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++)
|
||||
{
|
||||
@@ -2131,15 +2081,11 @@ namespace basisu
|
||||
|
||||
} // block_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
});
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
} // use_cpu
|
||||
|
||||
@@ -2204,9 +2150,7 @@ namespace basisu
|
||||
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, &training_vecs] {
|
||||
#endif
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
{
|
||||
@@ -2233,15 +2177,11 @@ namespace basisu
|
||||
|
||||
} // block_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
} );
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
vec16F_clusterizer selector_clusterizer;
|
||||
for (uint32_t i = 0; i < m_total_blocks; i++)
|
||||
@@ -2335,9 +2275,7 @@ namespace basisu
|
||||
const uint32_t first_index = cluster_index_iter;
|
||||
const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->add_job([this, first_index, last_index] {
|
||||
#endif
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
@@ -2406,15 +2344,11 @@ namespace basisu
|
||||
|
||||
} // cluster_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
});
|
||||
#endif
|
||||
|
||||
} // cluster_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
|
||||
|
||||
@@ -2506,7 +2440,7 @@ namespace basisu
|
||||
|
||||
if ((m_params.m_pOpenCL_context) && m_use_hierarchical_selector_codebooks)
|
||||
{
|
||||
const uint32_t num_parent_clusters = m_selector_clusters_within_each_parent_cluster.size();
|
||||
const uint32_t num_parent_clusters = m_selector_clusters_within_each_parent_cluster.size_u32();
|
||||
|
||||
basisu::vector<fosc_selector_struct> selector_structs;
|
||||
selector_structs.reserve(m_optimized_cluster_selectors.size());
|
||||
@@ -2534,7 +2468,7 @@ namespace basisu
|
||||
selector_cluster_indices.push_back(selector_cluster_index);
|
||||
}
|
||||
|
||||
cur_ofs += m_selector_clusters_within_each_parent_cluster[parent_index].size();
|
||||
cur_ofs += m_selector_clusters_within_each_parent_cluster[parent_index].size_u32();
|
||||
}
|
||||
|
||||
const uint32_t total_input_selectors = cur_ofs;
|
||||
@@ -2549,7 +2483,7 @@ namespace basisu
|
||||
|
||||
block_structs[i].m_etc_color5_inten.a = (uint8_t)blk.get_inten_table(0);
|
||||
block_structs[i].m_first_selector = parent_selector_cluster_offsets[parent_selector_cluster];
|
||||
block_structs[i].m_num_selectors = m_selector_clusters_within_each_parent_cluster[parent_selector_cluster].size();
|
||||
block_structs[i].m_num_selectors = m_selector_clusters_within_each_parent_cluster[parent_selector_cluster].size_u32();
|
||||
}
|
||||
|
||||
uint_vec output_selector_cluster_indices(m_total_blocks);
|
||||
@@ -2615,10 +2549,8 @@ namespace basisu
|
||||
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, &unpacked_optimized_cluster_selectors] {
|
||||
#endif
|
||||
|
||||
|
||||
int prev_best_cluster_index = 0;
|
||||
|
||||
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
|
||||
@@ -2756,15 +2688,11 @@ namespace basisu
|
||||
|
||||
} // block_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
} );
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < m_selector_cluster_block_indices.size(); i++)
|
||||
{
|
||||
@@ -3081,9 +3009,7 @@ namespace basisu
|
||||
const uint32_t first_index = cluster_index_iter;
|
||||
const uint32_t last_index = minimum<uint32_t>((uint32_t)new_endpoint_cluster_block_indices.size(), cluster_index_iter + N);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->add_job( [this, first_index, last_index, &cluster_improved, &cluster_valid, &new_endpoint_cluster_block_indices, &pBlock_selector_indices ] {
|
||||
#endif
|
||||
|
||||
for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
|
||||
{
|
||||
@@ -3173,15 +3099,11 @@ namespace basisu
|
||||
|
||||
} // cluster_index
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
} );
|
||||
#endif
|
||||
|
||||
} // cluster_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_params.m_pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
uint32_t total_unused_clusters = 0;
|
||||
uint32_t total_improved_clusters = 0;
|
||||
|
||||
+74
-5
@@ -19,6 +19,8 @@
|
||||
#include "basisu_bc7enc.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
#define BASISU_USE_GOOGLE_ASTC_DECODER (1)
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -1421,6 +1423,7 @@ namespace basisu
|
||||
case texture_format::cBC6HUnsigned:
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4:
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
{
|
||||
// Can't unpack HDR blocks in unpack_block() because it returns 32bpp pixel data.
|
||||
assert(0);
|
||||
@@ -1487,15 +1490,44 @@ namespace basisu
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
{
|
||||
#if BASISU_USE_GOOGLE_ASTC_DECODER
|
||||
bool status = basisu_astc::astc::decompress_hdr(&pPixels[0][0], (uint8_t*)pBlock, 6, 6);
|
||||
assert(status);
|
||||
if (!status)
|
||||
return false;
|
||||
#else
|
||||
// Use our decoder
|
||||
basist::half_float half_block[6 * 6][4];
|
||||
|
||||
astc_helpers::log_astc_block log_blk;
|
||||
if (!astc_helpers::unpack_block(pBlock, log_blk, 6, 6))
|
||||
return false;
|
||||
if (!astc_helpers::decode_block(log_blk, half_block, 6, 6, astc_helpers::cDecodeModeHDR16))
|
||||
return false;
|
||||
|
||||
for (uint32_t p = 0; p < (6 * 6); p++)
|
||||
{
|
||||
pPixels[p][0] = basist::half_to_float(half_block[p][0]);
|
||||
pPixels[p][1] = basist::half_to_float(half_block[p][1]);
|
||||
pPixels[p][2] = basist::half_to_float(half_block[p][2]);
|
||||
pPixels[p][3] = basist::half_to_float(half_block[p][3]);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4:
|
||||
{
|
||||
#if 1
|
||||
#if BASISU_USE_GOOGLE_ASTC_DECODER
|
||||
// Use Google's decoder
|
||||
bool status = basisu_astc::astc::decompress_hdr(&pPixels[0][0], (uint8_t*)pBlock, 4, 4);
|
||||
assert(status);
|
||||
if (!status)
|
||||
return false;
|
||||
#else
|
||||
// Use our decoder
|
||||
basist::half_float half_block[16][4];
|
||||
|
||||
astc_helpers::log_astc_block log_blk;
|
||||
@@ -1592,10 +1624,8 @@ namespace basisu
|
||||
|
||||
bool gpu_image::unpack_hdr(imagef& img) const
|
||||
{
|
||||
if ((m_fmt != texture_format::cASTC_HDR_4x4) &&
|
||||
(m_fmt != texture_format::cUASTC_HDR_4x4) &&
|
||||
(m_fmt != texture_format::cBC6HUnsigned) &&
|
||||
(m_fmt != texture_format::cBC6HSigned))
|
||||
if ((m_fmt != texture_format::cASTC_HDR_4x4) && (m_fmt != texture_format::cUASTC_HDR_4x4) && (m_fmt != texture_format::cASTC_HDR_6x6) &&
|
||||
(m_fmt != texture_format::cBC6HUnsigned) && (m_fmt != texture_format::cBC6HSigned))
|
||||
{
|
||||
// Can't call on LDR images, at least currently. (Could unpack the LDR data and convert to float.)
|
||||
assert(0);
|
||||
@@ -1643,6 +1673,7 @@ namespace basisu
|
||||
KTX_RG = 0x8227,
|
||||
KTX_RGB = 0x1907,
|
||||
KTX_RGBA = 0x1908,
|
||||
|
||||
KTX_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0,
|
||||
KTX_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3,
|
||||
KTX_COMPRESSED_RED_RGTC1_EXT = 0x8DBB,
|
||||
@@ -1655,11 +1686,42 @@ namespace basisu
|
||||
KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
|
||||
KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
|
||||
KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
|
||||
|
||||
KTX_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
|
||||
KTX_COMPRESSED_RGBA_ASTC_5x4_KHR = 0x93B1,
|
||||
KTX_COMPRESSED_RGBA_ASTC_5x5_KHR = 0x93B2,
|
||||
KTX_COMPRESSED_RGBA_ASTC_6x5_KHR = 0x93B3,
|
||||
KTX_COMPRESSED_RGBA_ASTC_6x6_KHR = 0x93B4,
|
||||
KTX_COMPRESSED_RGBA_ASTC_8x5_KHR = 0x93B5,
|
||||
KTX_COMPRESSED_RGBA_ASTC_8x6_KHR = 0x93B6,
|
||||
KTX_COMPRESSED_RGBA_ASTC_8x8_KHR = 0x93B7,
|
||||
KTX_COMPRESSED_RGBA_ASTC_10x5_KHR = 0x93B8,
|
||||
KTX_COMPRESSED_RGBA_ASTC_10x6_KHR = 0x93B9,
|
||||
KTX_COMPRESSED_RGBA_ASTC_10x8_KHR = 0x93BA,
|
||||
KTX_COMPRESSED_RGBA_ASTC_10x10_KHR = 0x93BB,
|
||||
KTX_COMPRESSED_RGBA_ASTC_12x10_KHR = 0x93BC,
|
||||
KTX_COMPRESSED_RGBA_ASTC_12x12_KHR = 0x93BD,
|
||||
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 0x93D0,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 0x93D1,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 0x93D2,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 0x93D3,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 0x93D4,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 0x93D5,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 0x93D6,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 0x93D7,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 0x93D8,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 0x93D9,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 0x93DA,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 0x93DB,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 0x93DC,
|
||||
KTX_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD,
|
||||
|
||||
KTX_COMPRESSED_RGBA_UASTC_4x4_KHR = 0x94CC, // TODO - Use proper value!
|
||||
|
||||
KTX_ATC_RGB_AMD = 0x8C92,
|
||||
KTX_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE,
|
||||
|
||||
KTX_COMPRESSED_RGB_FXT1_3DFX = 0x86B0,
|
||||
KTX_COMPRESSED_RGBA_FXT1_3DFX = 0x86B1,
|
||||
KTX_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG = 0x9138,
|
||||
@@ -1836,6 +1898,13 @@ namespace basisu
|
||||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
{
|
||||
internal_fmt = KTX_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
// TODO: should we write RGB? We don't support generating HDR 6x6 with alpha.
|
||||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
// We use different enums for HDR vs. LDR ASTC, but internally they are both just ASTC.
|
||||
case texture_format::cASTC_LDR_4x4:
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
|
||||
+3146
File diff suppressed because it is too large
Load Diff
+15
-7
@@ -789,7 +789,7 @@ namespace basisu
|
||||
|
||||
struct opencl_context
|
||||
{
|
||||
uint32_t m_ocl_total_pixel_blocks;
|
||||
size_t m_ocl_total_pixel_blocks;
|
||||
cl_mem m_ocl_pixel_blocks;
|
||||
|
||||
cl_command_queue m_command_queue;
|
||||
@@ -907,7 +907,7 @@ namespace basisu
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks)
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, size_t total_blocks, const cl_pixel_block* pPixel_blocks)
|
||||
{
|
||||
if (!opencl_is_available())
|
||||
return false;
|
||||
@@ -938,9 +938,11 @@ namespace basisu
|
||||
assert(pContext->m_ocl_pixel_blocks);
|
||||
if (!pContext->m_ocl_pixel_blocks)
|
||||
return false;
|
||||
|
||||
assert(pContext->m_ocl_total_pixel_blocks <= INT_MAX);
|
||||
|
||||
cl_encode_etc1s_param_struct ps;
|
||||
ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_total_blocks = (int)pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_perceptual = perceptual;
|
||||
ps.m_total_perms = total_perms;
|
||||
|
||||
@@ -1062,9 +1064,11 @@ exit:
|
||||
assert(pContext->m_ocl_pixel_blocks);
|
||||
if (!pContext->m_ocl_pixel_blocks)
|
||||
return false;
|
||||
|
||||
assert(pContext->m_ocl_total_pixel_blocks <= INT_MAX);
|
||||
|
||||
cl_rec_param_struct ps;
|
||||
ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_total_blocks = (int)pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_perceptual = perceptual;
|
||||
|
||||
bool status = false;
|
||||
@@ -1118,8 +1122,10 @@ exit:
|
||||
if (!pContext->m_ocl_pixel_blocks)
|
||||
return false;
|
||||
|
||||
assert(pContext->m_ocl_total_pixel_blocks <= INT_MAX);
|
||||
|
||||
fosc_param_struct ps;
|
||||
ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_total_blocks = (int)pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_perceptual = perceptual;
|
||||
|
||||
bool status = false;
|
||||
@@ -1170,8 +1176,10 @@ exit:
|
||||
if (!pContext->m_ocl_pixel_blocks)
|
||||
return false;
|
||||
|
||||
assert(pContext->m_ocl_total_pixel_blocks <= INT_MAX);
|
||||
|
||||
ds_param_struct ps;
|
||||
ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_total_blocks = (int)pContext->m_ocl_total_pixel_blocks;
|
||||
ps.m_perceptual = perceptual;
|
||||
|
||||
bool status = false;
|
||||
@@ -1232,7 +1240,7 @@ namespace basisu
|
||||
BASISU_NOTE_UNUSED(context);
|
||||
}
|
||||
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks)
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, size_t total_blocks, const cl_pixel_block* pPixel_blocks)
|
||||
{
|
||||
BASISU_NOTE_UNUSED(pContext);
|
||||
BASISU_NOTE_UNUSED(total_blocks);
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ namespace basisu
|
||||
// Must match BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE
|
||||
const uint32_t OPENCL_ENCODE_ETC1S_MAX_PERMS = 165;
|
||||
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks);
|
||||
bool opencl_set_pixel_blocks(opencl_context_ptr pContext, size_t total_blocks, const cl_pixel_block* pPixel_blocks);
|
||||
|
||||
bool opencl_encode_etc1s_blocks(opencl_context_ptr pContext, etc_block* pOutput_blocks, bool perceptual, uint32_t total_perms);
|
||||
|
||||
|
||||
+11
-15
@@ -20,8 +20,7 @@
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
#define BOX_FILTER_SUPPORT (0.5f)
|
||||
static float box_filter(float t) /* pulse/Fourier window */
|
||||
float box_filter(float t) /* pulse/Fourier window */
|
||||
{
|
||||
// make_clist() calls the filter function with t inverted (pos = left, neg = right)
|
||||
if ((t >= -0.5f) && (t < 0.5f))
|
||||
@@ -29,9 +28,8 @@ namespace basisu
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#define TENT_FILTER_SUPPORT (1.0f)
|
||||
static float tent_filter(float t) /* box (*) box, bilinear/triangle */
|
||||
|
||||
float tent_filter(float t) /* box (*) box, bilinear/triangle */
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
@@ -42,8 +40,7 @@ namespace basisu
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
#define BELL_SUPPORT (1.5f)
|
||||
static float bell_filter(float t) /* box (*) box (*) box */
|
||||
float bell_filter(float t) /* box (*) box (*) box */
|
||||
{
|
||||
if (t < 0.0f)
|
||||
t = -t;
|
||||
@@ -201,13 +198,12 @@ namespace basisu
|
||||
return (0.0f);
|
||||
}
|
||||
|
||||
#define GAUSSIAN_SUPPORT (1.25f)
|
||||
static float gaussian_filter(float t) // with blackman window
|
||||
float gaussian_filter(float t) // with blackman window
|
||||
{
|
||||
if (t < 0)
|
||||
t = -t;
|
||||
if (t < GAUSSIAN_SUPPORT)
|
||||
return clean(exp(-2.0f * t * t) * sqrt(2.0f / M_PI) * blackman_exact_window(t / GAUSSIAN_SUPPORT));
|
||||
if (t < BASISU_GAUSSIAN_FILTER_SUPPORT)
|
||||
return clean(exp(-2.0f * t * t) * sqrt(2.0f / M_PI) * blackman_exact_window(t / BASISU_GAUSSIAN_FILTER_SUPPORT));
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -310,9 +306,9 @@ namespace basisu
|
||||
|
||||
const resample_filter g_resample_filters[] =
|
||||
{
|
||||
{ "box", box_filter, BOX_FILTER_SUPPORT },
|
||||
{ "tent", tent_filter, TENT_FILTER_SUPPORT },
|
||||
{ "bell", bell_filter, BELL_SUPPORT },
|
||||
{ "box", box_filter, BASISU_BOX_FILTER_SUPPORT },
|
||||
{ "tent", tent_filter, BASISU_TENT_FILTER_SUPPORT },
|
||||
{ "bell", bell_filter, BASISU_BELL_FILTER_SUPPORT },
|
||||
{ "b-spline", B_spline_filter, B_SPLINE_SUPPORT },
|
||||
{ "mitchell", mitchell_filter, MITCHELL_SUPPORT },
|
||||
{ "blackman", blackman_filter, BLACKMAN_SUPPORT },
|
||||
@@ -321,7 +317,7 @@ namespace basisu
|
||||
{ "lanczos6", lanczos6_filter, LANCZOS6_SUPPORT },
|
||||
{ "lanczos12", lanczos12_filter, LANCZOS12_SUPPORT },
|
||||
{ "kaiser", kaiser_filter, KAISER_SUPPORT },
|
||||
{ "gaussian", gaussian_filter, GAUSSIAN_SUPPORT },
|
||||
{ "gaussian", gaussian_filter, BASISU_GAUSSIAN_FILTER_SUPPORT },
|
||||
{ "catmullrom", catmull_rom_filter, CATMULL_ROM_SUPPORT },
|
||||
{ "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT },
|
||||
{ "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT },
|
||||
|
||||
+1
-1
@@ -573,7 +573,7 @@ namespace basisu
|
||||
|
||||
/* Don't deallocate a contibutor list
|
||||
* if the user passed us one of their own.
|
||||
*/
|
||||
*/
|
||||
|
||||
if ((m_Pclist_x) && (!m_clist_x_forced))
|
||||
{
|
||||
|
||||
@@ -113,6 +113,8 @@ namespace basisu
|
||||
Resample_Real filter_scale,
|
||||
Resample_Real src_ofs);
|
||||
|
||||
static void free_clist(Contrib_List* p) { if (p) { free(p->p); free(p); } }
|
||||
|
||||
private:
|
||||
Resampler();
|
||||
Resampler(const Resampler &o);
|
||||
|
||||
@@ -29,6 +29,18 @@ namespace basisu
|
||||
|
||||
extern const resample_filter g_resample_filters[];
|
||||
extern const int g_num_resample_filters;
|
||||
|
||||
const float BASISU_BOX_FILTER_SUPPORT = 0.5f;
|
||||
float box_filter(float t); /* pulse/Fourier window */
|
||||
|
||||
const float BASISU_TENT_FILTER_SUPPORT = 1.0f;
|
||||
float tent_filter(float t); /* box (*) box, bilinear/triangle */
|
||||
|
||||
const float BASISU_GAUSSIAN_FILTER_SUPPORT = 1.25f;
|
||||
float gaussian_filter(float t); // with blackman window
|
||||
|
||||
const float BASISU_BELL_FILTER_SUPPORT = 1.5f;
|
||||
float bell_filter(float t); /* box (*) box (*) box */
|
||||
|
||||
int find_resample_filter(const char *pName);
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ namespace basisu
|
||||
|
||||
void gaussian_filter(imagef &dst, const imagef &orig_img, uint32_t odd_filter_width, float sigma_sqr, bool wrapping, uint32_t width_divisor, uint32_t height_divisor)
|
||||
{
|
||||
assert(&dst != &orig_img);
|
||||
|
||||
assert(odd_filter_width && (odd_filter_width & 1));
|
||||
odd_filter_width |= 1;
|
||||
|
||||
|
||||
+1
-32
@@ -3813,32 +3813,7 @@ namespace basisu
|
||||
return hash_hsieh((const uint8_t*)&s, sizeof(s));
|
||||
}
|
||||
};
|
||||
|
||||
class tracked_stat
|
||||
{
|
||||
public:
|
||||
tracked_stat() { clear(); }
|
||||
|
||||
void clear() { m_num = 0; m_total = 0; m_total2 = 0; }
|
||||
|
||||
void update(uint32_t val) { m_num++; m_total += val; m_total2 += val * val; }
|
||||
|
||||
tracked_stat& operator += (uint32_t val) { update(val); return *this; }
|
||||
|
||||
uint32_t get_number_of_values() { return m_num; }
|
||||
uint64_t get_total() const { return m_total; }
|
||||
uint64_t get_total2() const { return m_total2; }
|
||||
|
||||
float get_average() const { return m_num ? (float)m_total / m_num : 0.0f; };
|
||||
float get_std_dev() const { return m_num ? sqrtf((float)(m_num * m_total2 - m_total * m_total)) / m_num : 0.0f; }
|
||||
float get_variance() const { float s = get_std_dev(); return s * s; }
|
||||
|
||||
private:
|
||||
uint32_t m_num;
|
||||
uint64_t m_total;
|
||||
uint64_t m_total2;
|
||||
};
|
||||
|
||||
|
||||
static bool uastc_rdo_blocks(uint32_t first_index, uint32_t last_index, basist::uastc_block* pBlocks, const color_rgba* pBlock_pixels, const uastc_rdo_params& params, uint32_t flags,
|
||||
uint32_t &total_skipped, uint32_t &total_refined, uint32_t &total_modified, uint32_t &total_smooth)
|
||||
{
|
||||
@@ -4150,9 +4125,7 @@ namespace basisu
|
||||
const uint32_t first_index = block_index_iter;
|
||||
const uint32_t last_index = minimum<uint32_t>(num_blocks, block_index_iter + blocks_per_job);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
pJob_pool->add_job([first_index, last_index, pBlocks, pBlock_pixels, ¶ms, flags, &total_skipped, &total_modified, &total_refined, &total_smooth, &all_succeeded, &stat_mutex] {
|
||||
#endif
|
||||
|
||||
uint32_t job_skipped = 0, job_modified = 0, job_refined = 0, job_smooth = 0;
|
||||
|
||||
@@ -4168,16 +4141,12 @@ namespace basisu
|
||||
total_smooth += job_smooth;
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
} // block_index_iter
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
pJob_pool->wait_for_all();
|
||||
#endif
|
||||
|
||||
status = all_succeeded;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+16
-59
@@ -1,29 +1,20 @@
|
||||
// basisu_astc_hdr_enc.h
|
||||
// basisu_uastc_hdr_4x4_enc.h
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include "../transcoder/basisu_astc_helpers.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
#include "basisu_astc_hdr_common.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
// This MUST be called before encoding any blocks.
|
||||
void astc_hdr_enc_init();
|
||||
|
||||
const uint32_t MODE11_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
|
||||
const uint32_t MODE7_PART1_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART1_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
|
||||
const uint32_t MODE7_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART2_LAST_ISE_RANGE = astc_helpers::BISE_8_LEVELS;
|
||||
const uint32_t MODE11_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_PART2_LAST_ISE_RANGE = astc_helpers::BISE_4_LEVELS;
|
||||
const uint32_t MODE11_TOTAL_SUBMODES = 8; // plus an extra hidden submode, directly encoded, for direct, so really 9 (see tables 99/100 of the ASTC spec)
|
||||
const uint32_t MODE7_TOTAL_SUBMODES = 6;
|
||||
|
||||
struct astc_hdr_codec_options
|
||||
struct uastc_hdr_4x4_codec_options : astc_hdr_codec_base_options
|
||||
{
|
||||
float m_bc6h_err_weight;
|
||||
|
||||
bool m_use_solid;
|
||||
|
||||
bool m_use_mode11;
|
||||
bool m_use_mode11_part1;
|
||||
bool m_mode11_uber_mode;
|
||||
uint32_t m_first_mode11_weight_ise_range;
|
||||
uint32_t m_last_mode11_weight_ise_range;
|
||||
@@ -45,8 +36,6 @@ namespace basisu
|
||||
uint32_t m_first_mode11_part2_weight_ise_range;
|
||||
uint32_t m_last_mode11_part2_weight_ise_range;
|
||||
|
||||
float m_r_err_scale, m_g_err_scale;
|
||||
|
||||
bool m_refine_weights;
|
||||
|
||||
uint32_t m_level;
|
||||
@@ -54,13 +43,10 @@ namespace basisu
|
||||
bool m_use_estimated_partitions;
|
||||
uint32_t m_max_estimated_partitions;
|
||||
|
||||
// If true, the ASTC HDR compressor is allowed to more aggressively vary weight indices for slightly higher compression in non-fastest mode. This will hurt BC6H quality, however.
|
||||
bool m_allow_uber_mode;
|
||||
|
||||
astc_hdr_codec_options();
|
||||
uastc_hdr_4x4_codec_options();
|
||||
|
||||
void init();
|
||||
|
||||
|
||||
// TODO: set_quality_level() is preferred to configure the codec for transcoding purposes.
|
||||
static const int cMinLevel = 0;
|
||||
static const int cMaxLevel = 4;
|
||||
@@ -73,7 +59,7 @@ namespace basisu
|
||||
void set_quality_fastest();
|
||||
};
|
||||
|
||||
struct astc_hdr_pack_results
|
||||
struct astc_hdr_4x4_pack_results
|
||||
{
|
||||
double m_best_block_error;
|
||||
double m_bc6h_block_error; // note this is not used/set by the encoder, here for convienance
|
||||
@@ -119,35 +105,6 @@ namespace basisu
|
||||
}
|
||||
};
|
||||
|
||||
void interpolate_qlog12_colors(
|
||||
const int e[2][3],
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range);
|
||||
|
||||
bool get_astc_hdr_mode_11_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
bool get_astc_hdr_mode_7_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
double eval_selectors(
|
||||
uint32_t num_pixels,
|
||||
uint8_t* pWeights,
|
||||
const basist::half_float* pBlock_pixels_half,
|
||||
uint32_t num_weight_levels,
|
||||
const basist::half_float* pDecoded_half,
|
||||
const astc_hdr_codec_options& coptions,
|
||||
uint32_t usable_selector_bitmask = UINT32_MAX);
|
||||
|
||||
double compute_block_error(const basist::half_float* pOrig_block, const basist::half_float* pPacked_block, const astc_hdr_codec_options& coptions);
|
||||
|
||||
// Encodes a 4x4 ASTC HDR block given a 4x4 array of source block pixels/texels.
|
||||
// Supports solid color blocks, mode 11 (all submodes), mode 7/1 partition (all submodes),
|
||||
// and mode 7/2 partitions (all submodes) - 30 patterns, only the ones also in common with the BC6H format.
|
||||
@@ -164,16 +121,16 @@ namespace basisu
|
||||
// astc_hdr_enc_init() MUST have been called first to initialized the codec.
|
||||
// Input pixels are checked and cannot be NaN's, Inf's, signed, or too large (greater than MAX_HALF_FLOAT, or 65504).
|
||||
// Normal values and denormals are okay.
|
||||
bool astc_hdr_enc_block(
|
||||
const float* pRGBPixels,
|
||||
const astc_hdr_codec_options& coptions,
|
||||
basisu::vector<astc_hdr_pack_results> &all_results);
|
||||
bool astc_hdr_4x4_enc_block(
|
||||
const float* pRGBPixels, const basist::half_float *pRGBPixelsHalf,
|
||||
const uastc_hdr_4x4_codec_options& coptions,
|
||||
basisu::vector<astc_hdr_4x4_pack_results> &all_results);
|
||||
|
||||
bool astc_hdr_pack_results_to_block(basist::astc_blk& dst_blk, const astc_hdr_pack_results& results);
|
||||
bool astc_hdr_4x4_pack_results_to_block(basist::astc_blk& dst_blk, const astc_hdr_4x4_pack_results& results);
|
||||
|
||||
bool astc_hdr_refine_weights(const basist::half_float* pSource_block, astc_hdr_pack_results& cur_results, const astc_hdr_codec_options& coptions, float bc6h_weight, bool* pImproved_flag);
|
||||
bool astc_hdr_4x4_refine_weights(const basist::half_float* pSource_block, astc_hdr_4x4_pack_results& cur_results, const uastc_hdr_4x4_codec_options& coptions, float bc6h_weight, bool* pImproved_flag);
|
||||
|
||||
struct astc_hdr_block_stats
|
||||
struct astc_hdr_4x4_block_stats
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
|
||||
@@ -195,7 +152,7 @@ namespace basisu
|
||||
|
||||
uint32_t m_total_refined;
|
||||
|
||||
astc_hdr_block_stats() { clear(); }
|
||||
astc_hdr_4x4_block_stats() { clear(); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
@@ -215,7 +172,7 @@ namespace basisu
|
||||
clear_obj(m_part_hist);
|
||||
}
|
||||
|
||||
void update(const astc_hdr_pack_results& log_blk);
|
||||
void update(const astc_hdr_4x4_pack_results& log_blk);
|
||||
|
||||
void print();
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
index f16e75bd46..81813257cd 100644
|
||||
index 59a2a50900..e9aa20f313 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
@@ -33,7 +33,7 @@
|
||||
@@ -12,10 +12,10 @@ index f16e75bd46..81813257cd 100644
|
||||
|
||||
// Set to 1 to disable the mipPadding alignment workaround (which only seems to be needed when no key-values are written at all)
|
||||
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
index ea994b0c4f..32018cd282 100644
|
||||
index 0f7ca1565f..d7bce42013 100644
|
||||
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
@@ -164,7 +164,7 @@
|
||||
@@ -169,7 +169,7 @@
|
||||
// If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded.
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
// We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError()
|
||||
|
||||
+11
-2
@@ -1,8 +1,8 @@
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 47e8981bc3..6c0ac0ad37 100644
|
||||
index b9804090b1..5987685ae7 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -458,7 +458,7 @@ namespace basisu
|
||||
@@ -492,7 +492,7 @@ namespace basisu
|
||||
bool load_jpg(const char *pFilename, image& img)
|
||||
{
|
||||
int width = 0, height = 0, actual_comps = 0;
|
||||
@@ -11,3 +11,12 @@ index 47e8981bc3..6c0ac0ad37 100644
|
||||
if (!pImage_data)
|
||||
return false;
|
||||
|
||||
@@ -512,7 +512,7 @@ namespace basisu
|
||||
}
|
||||
|
||||
int width = 0, height = 0, actual_comps = 0;
|
||||
- uint8_t* pImage_data = jpgd::decompress_jpeg_image_from_memory(pBuf, (int)buf_size, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagLinearChromaFiltering);
|
||||
+ uint8_t* pImage_data = jpgd::decompress_jpeg_image_from_memory(pBuf, (int)buf_size, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagBoxChromaFiltering);
|
||||
if (!pImage_data)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 6c0ac0ad37..2bf486a028 100644
|
||||
index 7904aab91c..4d885cba16 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -27,7 +27,7 @@
|
||||
@@ -29,7 +29,7 @@
|
||||
#ifndef TINYEXR_USE_ZFP
|
||||
#define TINYEXR_USE_ZFP (1)
|
||||
#endif
|
||||
@@ -11,7 +11,7 @@ index 6c0ac0ad37..2bf486a028 100644
|
||||
|
||||
#ifndef MINIZ_HEADER_FILE_ONLY
|
||||
#define MINIZ_HEADER_FILE_ONLY
|
||||
@@ -3257,7 +3257,8 @@ namespace basisu
|
||||
@@ -3420,7 +3420,8 @@ namespace basisu
|
||||
float* out_rgba = nullptr;
|
||||
const char* err = nullptr;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 2bf486a028..fff98e8301 100644
|
||||
index 4d885cba16..6c2cf0260e 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -37,9 +37,6 @@
|
||||
@@ -39,9 +39,6 @@
|
||||
#endif
|
||||
#include "basisu_miniz.h"
|
||||
|
||||
@@ -12,7 +12,7 @@ index 2bf486a028..fff98e8301 100644
|
||||
#if defined(_WIN32)
|
||||
// For QueryPerformanceCounter/QueryPerformanceFrequency
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@@ -408,16 +405,7 @@ namespace basisu
|
||||
@@ -453,16 +450,7 @@ namespace basisu
|
||||
|
||||
bool load_qoi(const char* pFilename, image& img)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ index 2bf486a028..fff98e8301 100644
|
||||
|
||||
bool load_png(const uint8_t *pBuf, size_t buf_size, image &img, const char *pFilename)
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
index 000869a533..648cfb47ae 100644
|
||||
index 339218fcf2..028ac3f314 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
@@ -19,9 +19,6 @@
|
||||
@@ -41,10 +41,10 @@ index 000869a533..648cfb47ae 100644
|
||||
-#define TINYDDS_IMPLEMENTATION
|
||||
-#include "3rdparty/tinydds.h"
|
||||
-
|
||||
#define BASISU_USE_GOOGLE_ASTC_DECODER (1)
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -1980,207 +1977,7 @@ namespace basisu
|
||||
@@ -2049,207 +2046,7 @@ namespace basisu
|
||||
// and cubemap, cubemap mipmapped, and cubemap array mipmapped.
|
||||
bool write_dds_file(uint8_vec &dds_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
{
|
||||
@@ -63,11 +63,11 @@ index 000869a533..648cfb47ae 100644
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
- slices = gpu_images.size() / 6;
|
||||
- slices = gpu_images.size_u32() / 6;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- slices = gpu_images.size();
|
||||
- slices = gpu_images.size_u32();
|
||||
- }
|
||||
-
|
||||
- uint32_t width = 0, height = 0, total_levels = 0;
|
||||
@@ -185,7 +185,7 @@ index 000869a533..648cfb47ae 100644
|
||||
- assert(total_levels < 32);
|
||||
- for (uint32_t i = 0; i < total_levels; i++)
|
||||
- {
|
||||
- mipmap_sizes[i] = mipmaps[i].size_in_bytes();
|
||||
- mipmap_sizes[i] = mipmaps[i].size_in_bytes_u32();
|
||||
- mipmap_ptrs[i] = mipmaps[i].get_ptr();
|
||||
- }
|
||||
-
|
||||
@@ -253,7 +253,7 @@ index 000869a533..648cfb47ae 100644
|
||||
}
|
||||
|
||||
bool write_dds_file(const char* pFilename, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
@@ -2201,188 +1998,6 @@ namespace basisu
|
||||
@@ -2270,188 +2067,6 @@ namespace basisu
|
||||
|
||||
bool read_uncompressed_dds_file(const char* pFilename, basisu::vector<image> &ldr_mips, basisu::vector<imagef>& hdr_mips)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_astc_hdr_6x6_enc.h b/thirdparty/basis_universal/encoder/basisu_astc_hdr_6x6_enc.h
|
||||
index 0d6d2ae936..8b82ad8c29 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_astc_hdr_6x6_enc.h
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_astc_hdr_6x6_enc.h
|
||||
@@ -16,7 +16,7 @@ namespace astc_6x6_hdr
|
||||
{
|
||||
// Important: The Delta ITP colorspace error metric we use internally makes several assumptions about the nature of the HDR RGB inputs supplied to the encoder.
|
||||
// This encoder computes colorspace error in the ICtCp (or more accurately the delta ITP, where CT is scaled by .5 vs. ICtCp to become T) colorspace, so getting this correct is important.
|
||||
- // By default the encoder assumes the input is in absolute luminance (in nits or candela per square meter, cd/m▓), specified as positive-only linear light RGB, using the REC 709 colorspace gamut (but NOT the sRGB transfer function, i.e. linear light).
|
||||
+ // By default the encoder assumes the input is in absolute luminance (in nits or candela per square meter, cd/m^2), specified as positive-only linear light RGB, using the REC 709 colorspace gamut (but NOT the sRGB transfer function, i.e. linear light).
|
||||
// If the m_rec2020_bt2100_color_gamut flag is true, the input colorspace is treated as REC 2020/BT.2100 (which is wider than 709).
|
||||
// For SDR/LDR->HDR upconversion, the REC 709 sRGB input should be converted to linear light (sRGB->linear) and the resulting normalized linear RGB values scaled by either 80 or 100 nits (the luminance of a typical SDR monitor).
|
||||
// SDR upconversion to normalized [0,1] (i.e. non-absolute) luminances may work but is not supported because ITP errors will not be predicted correctly.
|
||||
@@ -0,0 +1,22 @@
|
||||
diff --git a/thirdparty/basis_universal/transcoder/basisu_containers.h b/thirdparty/basis_universal/transcoder/basisu_containers.h
|
||||
index 03fae33974..7fff4c243e 100644
|
||||
--- a/thirdparty/basis_universal/transcoder/basisu_containers.h
|
||||
+++ b/thirdparty/basis_universal/transcoder/basisu_containers.h
|
||||
@@ -3349,7 +3349,7 @@ namespace basisu
|
||||
|
||||
inline size_t hash_key(const Key& k) const
|
||||
{
|
||||
- assert((safe_shift_left(1ULL, (SIZE_T_BITS - m_hash_shift))) == m_values.size());
|
||||
+ assert((safe_shift_left(static_cast<uint64_t>(1), (SIZE_T_BITS - m_hash_shift))) == m_values.size());
|
||||
|
||||
// Fibonacci hashing
|
||||
if (SIZE_T_BITS == 32)
|
||||
@@ -3433,7 +3433,7 @@ namespace basisu
|
||||
return false;
|
||||
|
||||
new_map.m_hash_shift = SIZE_T_BITS - helpers::floor_log2i((uint64_t)new_hash_size);
|
||||
- assert(new_hash_size == safe_shift_left(1ULL, SIZE_T_BITS - new_map.m_hash_shift));
|
||||
+ assert(new_hash_size == safe_shift_left(static_cast<uint64_t>(1), SIZE_T_BITS - new_map.m_hash_shift));
|
||||
|
||||
new_map.m_grow_threshold = std::numeric_limits<size_t>::max();
|
||||
|
||||
+163
-54
@@ -20,34 +20,7 @@
|
||||
#pragma warning (disable : 4201)
|
||||
#pragma warning (disable : 4127) // warning C4127: conditional expression is constant
|
||||
#pragma warning (disable : 4530) // C++ exception handler used, but unwind semantics are not enabled.
|
||||
|
||||
// Slamming this off always for v1.16 because we've gotten rid of most std containers.
|
||||
#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
|
||||
#define BASISU_NO_ITERATOR_DEBUG_LEVEL (1)
|
||||
#endif
|
||||
|
||||
#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
|
||||
//#define _HAS_ITERATOR_DEBUGGING 0
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUG)
|
||||
// This is madness, but we need to disable iterator debugging in debug builds or the encoder is unsable because MSVC's iterator debugging implementation is totally broken.
|
||||
#ifndef _ITERATOR_DEBUG_LEVEL
|
||||
#define _ITERATOR_DEBUG_LEVEL 1
|
||||
#endif
|
||||
#ifndef _SECURE_SCL
|
||||
#define _SECURE_SCL 1
|
||||
#endif
|
||||
#else // defined(_DEBUG) || defined(DEBUG)
|
||||
#ifndef _SECURE_SCL
|
||||
#define _SECURE_SCL 0
|
||||
#endif
|
||||
#ifndef _ITERATOR_DEBUG_LEVEL
|
||||
#define _ITERATOR_DEBUG_LEVEL 0
|
||||
#endif
|
||||
#endif // defined(_DEBUG) || defined(DEBUG)
|
||||
|
||||
#endif // BASISU_NO_ITERATOR_DEBUG_LEVEL
|
||||
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -66,6 +39,7 @@
|
||||
#include <type_traits>
|
||||
#include <assert.h>
|
||||
#include <random>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "basisu_containers.h"
|
||||
|
||||
@@ -114,6 +88,7 @@ namespace basisu
|
||||
typedef basisu::vector<int16_t> int16_vec;
|
||||
typedef basisu::vector<uint16_t> uint16_vec;
|
||||
typedef basisu::vector<uint32_t> uint_vec;
|
||||
typedef basisu::vector<size_t> size_t_vec;
|
||||
typedef basisu::vector<uint64_t> uint64_vec;
|
||||
typedef basisu::vector<int> int_vec;
|
||||
typedef basisu::vector<bool> bool_vec;
|
||||
@@ -121,6 +96,16 @@ namespace basisu
|
||||
|
||||
void enable_debug_printf(bool enabled);
|
||||
void debug_printf(const char *pFmt, ...);
|
||||
void debug_puts(const char* p);
|
||||
|
||||
template <typename... Args>
|
||||
inline void fmt_debug_printf(const char* pFmt, Args&&... args)
|
||||
{
|
||||
std::string res;
|
||||
if (!fmt_variants(res, pFmt, fmt_variant_vec{ fmt_variant(std::forward<Args>(args))... }))
|
||||
return;
|
||||
debug_puts(res.c_str());
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
@@ -137,16 +122,13 @@ namespace basisu
|
||||
#endif
|
||||
#endif
|
||||
|
||||
constexpr double cPiD = 3.14159265358979323846264338327950288;
|
||||
constexpr float REALLY_SMALL_FLOAT_VAL = .000000125f;
|
||||
constexpr float SMALL_FLOAT_VAL = .0000125f;
|
||||
constexpr float BIG_FLOAT_VAL = 1e+30f;
|
||||
|
||||
template <typename T0, typename T1> inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; }
|
||||
|
||||
template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
|
||||
template <typename S> inline S maximum(S a, S b, S c) { return maximum(maximum(a, b), c); }
|
||||
template <typename S> inline S maximum(S a, S b, S c, S d) { return maximum(maximum(maximum(a, b), c), d); }
|
||||
|
||||
template <typename S> inline S minimum(S a, S b) { return (a < b) ? a : b; }
|
||||
template <typename S> inline S minimum(S a, S b, S c) { return minimum(minimum(a, b), c); }
|
||||
template <typename S> inline S minimum(S a, S b, S c, S d) { return minimum(minimum(minimum(a, b), c), d); }
|
||||
|
||||
|
||||
inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; }
|
||||
inline float saturate(float value) { return clampf(value, 0, 1.0f); }
|
||||
inline uint8_t minimumub(uint8_t a, uint8_t b) { return (a < b) ? a : b; }
|
||||
@@ -159,10 +141,31 @@ namespace basisu
|
||||
inline float maximumf(float a, float b) { return (a > b) ? a : b; }
|
||||
inline int squarei(int i) { return i * i; }
|
||||
inline float squaref(float i) { return i * i; }
|
||||
inline double squared(double i) { return i * i; }
|
||||
template<typename T> inline T square(T a) { return a * a; }
|
||||
template<typename T> inline T sign(T a) { return (a < 0) ? (T)-1 : ((a == 0) ? (T)0 : (T)1); }
|
||||
|
||||
inline bool equal_tol(float a, float b, float t) { return fabsf(a - b) <= ((maximum(fabsf(a), fabsf(b)) + 1.0f) * t); }
|
||||
inline bool equal_tol(double a, double b, double t) { return fabs(a - b) <= ((maximum(fabs(a), fabs(b)) + 1.0f) * t); }
|
||||
|
||||
template <typename S> inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); }
|
||||
template <class T>
|
||||
inline T prev_wrap(T i, T n)
|
||||
{
|
||||
T temp = i - 1;
|
||||
if (temp < 0)
|
||||
temp = n - 1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T next_wrap(T i, T n)
|
||||
{
|
||||
T temp = i + 1;
|
||||
if (temp >= n)
|
||||
temp = 0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline uint32_t iabs(int32_t i) { return (i < 0) ? static_cast<uint32_t>(-i) : static_cast<uint32_t>(i); }
|
||||
inline uint64_t iabs64(int64_t i) { return (i < 0) ? static_cast<uint64_t>(-i) : static_cast<uint64_t>(i); }
|
||||
|
||||
@@ -356,6 +359,7 @@ namespace basisu
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
@@ -414,6 +418,57 @@ namespace basisu
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#else
|
||||
inline operator uint32_t() const
|
||||
{
|
||||
if constexpr (NumBytes == 1)
|
||||
{
|
||||
return m_bytes[0];
|
||||
}
|
||||
else if constexpr (NumBytes == 2)
|
||||
{
|
||||
return (m_bytes[1] << 8U) | m_bytes[0];
|
||||
}
|
||||
else if constexpr (NumBytes == 3)
|
||||
{
|
||||
return (m_bytes[2] << 16U) | (m_bytes[1] << 8U) | m_bytes[0];
|
||||
}
|
||||
else if constexpr (NumBytes == 4)
|
||||
{
|
||||
return read_le_dword(m_bytes);
|
||||
}
|
||||
else if constexpr (NumBytes == 5)
|
||||
{
|
||||
uint32_t l = read_le_dword(m_bytes);
|
||||
uint32_t h = m_bytes[4];
|
||||
return static_cast<uint64_t>(l) | (static_cast<uint64_t>(h) << 32U);
|
||||
}
|
||||
else if constexpr (NumBytes == 6)
|
||||
{
|
||||
uint32_t l = read_le_dword(m_bytes);
|
||||
uint32_t h = (m_bytes[5] << 8U) | m_bytes[4];
|
||||
return static_cast<uint64_t>(l) | (static_cast<uint64_t>(h) << 32U);
|
||||
}
|
||||
else if constexpr (NumBytes == 7)
|
||||
{
|
||||
uint32_t l = read_le_dword(m_bytes);
|
||||
uint32_t h = (m_bytes[6] << 16U) | (m_bytes[5] << 8U) | m_bytes[4];
|
||||
return static_cast<uint64_t>(l) | (static_cast<uint64_t>(h) << 32U);
|
||||
}
|
||||
else if constexpr (NumBytes == 8)
|
||||
{
|
||||
uint32_t l = read_le_dword(m_bytes);
|
||||
uint32_t h = read_le_dword(m_bytes + 4);
|
||||
return static_cast<uint64_t>(l) | (static_cast<uint64_t>(h) << 32U);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(NumBytes <= 8, "Invalid NumBytes");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
enum eZero { cZero };
|
||||
@@ -446,18 +501,18 @@ namespace basisu
|
||||
static const uint8_t g_huffman_sorted_codelength_codes[] = { cHuffmanSmallZeroRunCode, cHuffmanBigZeroRunCode, cHuffmanSmallRepeatCode, cHuffmanBigRepeatCode, 0, 8, 7, 9, 6, 0xA, 5, 0xB, 4, 0xC, 3, 0xD, 2, 0xE, 1, 0xF, 0x10 };
|
||||
const uint32_t cHuffmanTotalSortedCodelengthCodes = sizeof(g_huffman_sorted_codelength_codes) / sizeof(g_huffman_sorted_codelength_codes[0]);
|
||||
|
||||
// GPU texture formats
|
||||
// GPU texture formats and various uncompressed texture formats.
|
||||
|
||||
enum class texture_format
|
||||
{
|
||||
cInvalidTextureFormat = -1,
|
||||
|
||||
// Block-based formats
|
||||
cETC1, // ETC1
|
||||
cETC1S, // ETC1 (subset: diff colors only, no subblocks)
|
||||
cETC2_RGB, // ETC2 color block (basisu doesn't support ETC2 planar/T/H modes - just basic ETC1)
|
||||
cETC2_RGBA, // ETC2 EAC alpha block followed by ETC2 color block
|
||||
cETC2_ALPHA, // ETC2 EAC alpha block
|
||||
cETC1, // ETC1
|
||||
cETC1S, // ETC1 (subset: diff colors only, no subblocks)
|
||||
cETC2_RGB, // ETC2 color block (basisu doesn't support ETC2 planar/T/H modes - just basic ETC1)
|
||||
cETC2_RGBA, // ETC2 EAC alpha block followed by ETC2 color block
|
||||
cETC2_ALPHA, // ETC2 EAC alpha block
|
||||
cBC1, // DXT1
|
||||
cBC3, // DXT5 (BC4/DXT5A block followed by a BC1/DXT1 block)
|
||||
cBC4, // DXT5A
|
||||
@@ -466,7 +521,8 @@ namespace basisu
|
||||
cBC6HUnsigned, // HDR
|
||||
cBC7,
|
||||
cASTC_LDR_4x4, // ASTC 4x4 LDR only
|
||||
cASTC_HDR_4x4, // ASTC 4x4 HDR only (but may use LDR ASTC blocks internally)
|
||||
cASTC_HDR_4x4, // ASTC 4x4 HDR only (but may use LDR ASTC blocks internally, although our encoders don't do this)
|
||||
cASTC_HDR_6x6, // ASTC 6x6 HDR only (but may use LDR ASTC blocks internally, although our encoders don't do this)
|
||||
cPVRTC1_4_RGB,
|
||||
cPVRTC1_4_RGBA,
|
||||
cATC_RGB,
|
||||
@@ -491,8 +547,33 @@ namespace basisu
|
||||
cRGB_9E5
|
||||
};
|
||||
|
||||
inline bool is_uncompressed_texture_format(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cRGBA32:
|
||||
case texture_format::cRGB565:
|
||||
case texture_format::cBGR565:
|
||||
case texture_format::cRGBA4444:
|
||||
case texture_format::cABGR4444:
|
||||
case texture_format::cRGBA_HALF:
|
||||
case texture_format::cRGB_HALF:
|
||||
case texture_format::cRGB_9E5:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_block_based_texture_format(texture_format fmt)
|
||||
{
|
||||
return !is_uncompressed_texture_format(fmt);
|
||||
}
|
||||
|
||||
// This is bytes per block for GPU formats, or bytes per texel for uncompressed formats.
|
||||
inline uint32_t get_bytes_per_block(texture_format fmt)
|
||||
inline uint32_t get_bytes_per_block_or_pixel(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
@@ -534,16 +615,22 @@ namespace basisu
|
||||
// This is qwords per block for GPU formats, or not valid for uncompressed formats.
|
||||
inline uint32_t get_qwords_per_block(texture_format fmt)
|
||||
{
|
||||
return get_bytes_per_block(fmt) >> 3;
|
||||
assert(is_block_based_texture_format(fmt));
|
||||
|
||||
const uint32_t bytes_per_block = get_bytes_per_block_or_pixel(fmt);
|
||||
return bytes_per_block >> 3;
|
||||
}
|
||||
|
||||
inline uint32_t get_block_width(texture_format fmt)
|
||||
{
|
||||
BASISU_NOTE_UNUSED(fmt);
|
||||
assert(is_block_based_texture_format(fmt));
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cFXT1_RGB:
|
||||
return 8;
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -552,20 +639,42 @@ namespace basisu
|
||||
|
||||
inline uint32_t get_block_height(texture_format fmt)
|
||||
{
|
||||
BASISU_NOTE_UNUSED(fmt);
|
||||
assert(is_block_based_texture_format(fmt));
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline bool is_hdr_texture_format(texture_format fmt)
|
||||
{
|
||||
if (fmt == texture_format::cASTC_HDR_4x4)
|
||||
return true;
|
||||
if (fmt == texture_format::cUASTC_HDR_4x4)
|
||||
return true;
|
||||
if ((fmt == texture_format::cBC6HSigned) || (fmt == texture_format::cBC6HUnsigned))
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4:
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
case texture_format::cBC6HSigned:
|
||||
case texture_format::cBC6HUnsigned:
|
||||
case texture_format::cRGBA_HALF:
|
||||
case texture_format::cRGB_HALF:
|
||||
case texture_format::cRGB_9E5:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_ldr_texture_format(texture_format fmt)
|
||||
{
|
||||
return !is_hdr_texture_format(fmt);
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
+130
-26
@@ -35,40 +35,17 @@ namespace basist
|
||||
const uint32_t MAX_QLOG16 = 63487;
|
||||
const float MAX_QLOG16_VAL = 65504.0f;
|
||||
|
||||
// TODO: Should be called something like "NUM_MODE11_ENDPOINT_VALUES"
|
||||
const uint32_t NUM_MODE11_ENDPOINTS = 6, NUM_MODE7_ENDPOINTS = 4;
|
||||
|
||||
// Notes:
|
||||
// qlog16_to_half(half_to_qlog16(half_val_as_int)) == half_val_as_int (is lossless)
|
||||
// However, this is not lossless in the general sense.
|
||||
inline half_float qlog16_to_half_slow(uint32_t qlog16)
|
||||
{
|
||||
assert(qlog16 <= 0xFFFF);
|
||||
|
||||
int C = qlog16;
|
||||
|
||||
int E = (C & 0xF800) >> 11;
|
||||
int M = C & 0x7FF;
|
||||
|
||||
int Mt;
|
||||
if (M < 512)
|
||||
Mt = 3 * M;
|
||||
else if (M >= 1536)
|
||||
Mt = 5 * M - 2048;
|
||||
else
|
||||
Mt = 4 * M - 512;
|
||||
|
||||
int Cf = (E << 10) + (Mt >> 3);
|
||||
return (half_float)Cf;
|
||||
}
|
||||
|
||||
// This is not lossless
|
||||
inline half_float qlog_to_half_slow(uint32_t qlog, uint32_t bits)
|
||||
inline half_float qlog_to_half(uint32_t qlog, uint32_t bits)
|
||||
{
|
||||
assert((bits >= 7U) && (bits <= 16U));
|
||||
assert(qlog < (1U << bits));
|
||||
|
||||
int C = qlog << (16 - bits);
|
||||
return qlog16_to_half_slow(C);
|
||||
return astc_helpers::qlog16_to_half(C);
|
||||
}
|
||||
|
||||
void astc_hdr_core_init();
|
||||
@@ -99,4 +76,131 @@ namespace basist
|
||||
bool astc_hdr_transcode_to_bc6h(const astc_blk& src_blk, bc6h_block& dst_blk);
|
||||
bool astc_hdr_transcode_to_bc6h(const astc_helpers::log_astc_block& log_blk, bc6h_block& dst_blk);
|
||||
|
||||
namespace astc_6x6_hdr
|
||||
{
|
||||
const uint32_t MAX_ASTC_HDR_6X6_DIM = 32768;
|
||||
const int32_t REUSE_MAX_BUFFER_ROWS = 5; // 1+-(-4), so we need to buffer 5 rows total
|
||||
|
||||
struct block_mode_desc
|
||||
{
|
||||
bool m_dp;
|
||||
uint32_t m_cem;
|
||||
uint32_t m_num_partitions;
|
||||
uint32_t m_grid_x;
|
||||
uint32_t m_grid_y;
|
||||
|
||||
// the coding ISE ranges (which may not be valid ASTC ranges for this configuration)
|
||||
uint32_t m_endpoint_ise_range;
|
||||
uint32_t m_weight_ise_range;
|
||||
|
||||
// the physical/output ASTC decompression ISE ranges (i.e. what the decompressor must output)
|
||||
uint32_t m_transcode_endpoint_ise_range;
|
||||
uint32_t m_transcode_weight_ise_range;
|
||||
|
||||
uint32_t m_flags;
|
||||
int m_dp_channel;
|
||||
};
|
||||
|
||||
// Lack of level flag indicates level 3+
|
||||
const uint32_t BASIST_HDR_6X6_LEVEL0 = 1;
|
||||
const uint32_t BASIST_HDR_6X6_LEVEL1 = 2;
|
||||
const uint32_t BASIST_HDR_6X6_LEVEL2 = 4;
|
||||
|
||||
const uint32_t TOTAL_BLOCK_MODE_DECS = 75;
|
||||
extern const block_mode_desc g_block_mode_descs[TOTAL_BLOCK_MODE_DECS];
|
||||
|
||||
void copy_weight_grid(bool dual_plane, uint32_t grid_x, uint32_t grid_y, const uint8_t* transcode_weights, astc_helpers::log_astc_block& decomp_blk);
|
||||
|
||||
enum class encoding_type
|
||||
{
|
||||
cInvalid = -1,
|
||||
cRun = 0,
|
||||
cSolid = 1,
|
||||
cReuse = 2,
|
||||
cBlock = 3,
|
||||
cTotal
|
||||
};
|
||||
|
||||
const uint32_t REUSE_XY_DELTA_BITS = 5;
|
||||
const uint32_t NUM_REUSE_XY_DELTAS = 1 << REUSE_XY_DELTA_BITS;
|
||||
|
||||
struct reuse_xy_delta
|
||||
{
|
||||
int8_t m_x, m_y;
|
||||
};
|
||||
|
||||
extern const reuse_xy_delta g_reuse_xy_deltas[NUM_REUSE_XY_DELTAS];
|
||||
|
||||
const uint32_t RUN_CODE = 0b000, RUN_CODE_LEN = 3;
|
||||
const uint32_t SOLID_CODE = 0b100, SOLID_CODE_LEN = 3;
|
||||
const uint32_t REUSE_CODE = 0b10, REUSE_CODE_LEN = 2;
|
||||
const uint32_t BLOCK_CODE = 0b1, BLOCK_CODE_LEN = 1;
|
||||
|
||||
enum class endpoint_mode
|
||||
{
|
||||
cInvalid = -1,
|
||||
|
||||
cRaw = 0,
|
||||
cUseLeft,
|
||||
cUseUpper,
|
||||
cUseLeftDelta,
|
||||
cUseUpperDelta,
|
||||
|
||||
cTotal
|
||||
};
|
||||
|
||||
enum class block_mode
|
||||
{
|
||||
cInvalid = -1,
|
||||
|
||||
cBMTotalModes = TOTAL_BLOCK_MODE_DECS
|
||||
};
|
||||
|
||||
const uint32_t NUM_ENDPOINT_DELTA_BITS = 5;
|
||||
|
||||
const uint32_t NUM_UNIQUE_PARTITIONS2 = 521;
|
||||
extern const uint32_t g_part2_unique_index_to_seed[NUM_UNIQUE_PARTITIONS2];
|
||||
|
||||
const uint32_t NUM_UNIQUE_PARTITIONS3 = 333;
|
||||
extern const uint32_t g_part3_unique_index_to_seed[NUM_UNIQUE_PARTITIONS3];
|
||||
|
||||
bool decode_values(basist::bitwise_decoder& decoder, uint32_t total_values, uint32_t ise_range, uint8_t* pValues);
|
||||
|
||||
void requantize_astc_weights(uint32_t n, const uint8_t* pSrc_ise_vals, uint32_t from_ise_range, uint8_t* pDst_ise_vals, uint32_t to_ise_range);
|
||||
|
||||
void requantize_ise_endpoints(uint32_t cem, uint32_t src_ise_endpoint_range, const uint8_t* pSrc_endpoints, uint32_t dst_ise_endpoint_range, uint8_t* pDst_endpoints);
|
||||
|
||||
const uint32_t BC6H_NUM_DIFF_ENDPOINT_MODES_TO_TRY_2 = 2;
|
||||
const uint32_t BC6H_NUM_DIFF_ENDPOINT_MODES_TO_TRY_4 = 4;
|
||||
const uint32_t BC6H_NUM_DIFF_ENDPOINT_MODES_TO_TRY_9 = 9;
|
||||
|
||||
struct fast_bc6h_params
|
||||
{
|
||||
uint32_t m_num_diff_endpoint_modes_to_try;
|
||||
uint32_t m_max_2subset_pats_to_try;
|
||||
|
||||
bool m_hq_ls;
|
||||
bool m_brute_force_weight4_assignment;
|
||||
|
||||
fast_bc6h_params()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_hq_ls = true;
|
||||
m_num_diff_endpoint_modes_to_try = BC6H_NUM_DIFF_ENDPOINT_MODES_TO_TRY_2;
|
||||
m_max_2subset_pats_to_try = 1;
|
||||
m_brute_force_weight4_assignment = false;
|
||||
}
|
||||
};
|
||||
|
||||
void fast_encode_bc6h(const basist::half_float* pPixels, basist::bc6h_block* pBlock, const fast_bc6h_params ¶ms);
|
||||
|
||||
bool decode_6x6_hdr(const uint8_t* pComp_data, uint32_t comp_data_size, basisu::vector2D<astc_helpers::astc_block>& decoded_blocks, uint32_t& width, uint32_t& height);
|
||||
|
||||
} // namespace astc_6x6_hdr
|
||||
|
||||
} // namespace basist
|
||||
|
||||
|
||||
+208
-80
File diff suppressed because it is too large
Load Diff
+3944
-1777
File diff suppressed because it is too large
Load Diff
+730
-232
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,7 @@ namespace basist
|
||||
basisu::packed_uint<2> m_orig_width; // The original image width (may not be a multiple of 4 pixels)
|
||||
basisu::packed_uint<2> m_orig_height; // The original image height (may not be a multiple of 4 pixels)
|
||||
|
||||
basisu::packed_uint<2> m_num_blocks_x; // The slice's block X dimensions. Each block is 4x4 pixels. The slice's pixel resolution may or may not be a power of 2.
|
||||
basisu::packed_uint<2> m_num_blocks_x; // The slice's block X dimensions. Each block is 4x4 or 6x6 pixels. The slice's pixel resolution may or may not be a power of 2.
|
||||
basisu::packed_uint<2> m_num_blocks_y; // The slice's block Y dimensions.
|
||||
|
||||
basisu::packed_uint<4> m_file_ofs; // Offset from the start of the file to the start of the slice's data
|
||||
@@ -72,9 +72,9 @@ namespace basist
|
||||
// We do make sure the various constraints are followed (2DArray/cubemap/videoframes/volume implies that each image has the same resolution and # of mipmap levels, etc., cubemap implies that the # of image slices is a multiple of 6)
|
||||
enum basis_texture_type
|
||||
{
|
||||
cBASISTexType2D = 0, // An arbitrary array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image may have a different resolution and # of mipmap levels
|
||||
cBASISTexType2D = 0, // An arbitrary array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image may have a different resolution and # of mipmap levels
|
||||
cBASISTexType2DArray = 1, // An array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image has the same resolution and mipmap levels
|
||||
cBASISTexTypeCubemapArray = 2, // an array of cubemap levels, total # of images must be divisable by 6, in X+, X-, Y+, Y-, Z+, Z- order, with optional mipmaps
|
||||
cBASISTexTypeCubemapArray = 2, // an array of cubemap levels, total # of images must be divisable by 6, in X+, X-, Y+, Y-, Z+, Z- order, with optional mipmaps
|
||||
cBASISTexTypeVideoFrames = 3, // An array of 2D video frames, with optional mipmaps, # frames = # images, each image has the same resolution and # of mipmap levels
|
||||
cBASISTexTypeVolume = 4, // A 3D texture with optional mipmaps, Z dimension = # images, each image has the same resolution and # of mipmap levels
|
||||
|
||||
@@ -90,7 +90,10 @@ namespace basist
|
||||
{
|
||||
cETC1S = 0,
|
||||
cUASTC4x4 = 1,
|
||||
cUASTC_HDR_4x4 = 2
|
||||
cUASTC_HDR_4x4 = 2,
|
||||
cASTC_HDR_6x6 = 3,
|
||||
cASTC_HDR_6x6_INTERMEDIATE = 4,
|
||||
cTotalFormats
|
||||
};
|
||||
|
||||
struct basis_file_header
|
||||
|
||||
+4762
-259
File diff suppressed because it is too large
Load Diff
+253
-53
File diff suppressed because it is too large
Load Diff
@@ -20,9 +20,10 @@
|
||||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
// v1.50: Added UASTC HDR support
|
||||
#define BASISD_LIB_VERSION 150
|
||||
#define BASISD_VERSION_STRING "01.50"
|
||||
// v1.50: Added UASTC HDR 4x4 support
|
||||
// v1.60: Added RDO ASTC HDR 6x6 and intermediate support
|
||||
#define BASISD_LIB_VERSION 160
|
||||
#define BASISD_VERSION_STRING "01.60"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define BASISD_BUILD_DEBUG
|
||||
@@ -91,10 +92,37 @@ namespace basist
|
||||
cUASTC_HDR_4x4, // HDR, transcodes only to 4x4 HDR ASTC, BC6H, or uncompressed
|
||||
cBC6H,
|
||||
cASTC_HDR_4x4,
|
||||
cASTC_HDR_6x6,
|
||||
|
||||
cTotalBlockFormats
|
||||
};
|
||||
|
||||
inline uint32_t get_block_width(block_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case block_format::cFXT1_RGB:
|
||||
return 8;
|
||||
case block_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline uint32_t get_block_height(block_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case block_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
const int COLOR5_PAL0_PREV_HI = 9, COLOR5_PAL0_DELTA_LO = -9, COLOR5_PAL0_DELTA_HI = 31;
|
||||
const int COLOR5_PAL1_PREV_HI = 21, COLOR5_PAL1_DELTA_LO = -21, COLOR5_PAL1_DELTA_HI = 21;
|
||||
const int COLOR5_PAL2_PREV_HI = 31, COLOR5_PAL2_DELTA_LO = -31, COLOR5_PAL2_DELTA_HI = 9;
|
||||
@@ -559,6 +587,12 @@ namespace basist
|
||||
return ct.init(total_used_syms, &code_sizes[0]);
|
||||
}
|
||||
|
||||
size_t get_bits_remaining() const
|
||||
{
|
||||
size_t total_bytes_remaining = m_pBuf_end - m_pBuf;
|
||||
return total_bytes_remaining * 8 + m_bit_buf_size;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_buf_size;
|
||||
const uint8_t *m_pBuf;
|
||||
@@ -804,6 +838,7 @@ namespace basist
|
||||
const double MIN_DENORM_HALF_FLOAT = 0.000000059604645; // smallest positive subnormal number
|
||||
const double MIN_HALF_FLOAT = 0.00006103515625; // smallest positive normal number
|
||||
const double MAX_HALF_FLOAT = 65504.0; // largest normal number
|
||||
const uint32_t MAX_HALF_FLOAT_AS_INT_BITS = 0x7BFF; // the half float rep for 65504.0
|
||||
|
||||
inline uint32_t get_bits(uint32_t val, int low, int high)
|
||||
{
|
||||
@@ -975,6 +1010,13 @@ namespace basist
|
||||
return (h * 64 + 30) / 31;
|
||||
}
|
||||
|
||||
// Suboptimal, but very close.
|
||||
inline uint32_t bc6h_half_to_blog(half_float h, uint32_t num_bits)
|
||||
{
|
||||
assert(h <= MAX_BC6H_HALF_FLOAT_AS_UINT);
|
||||
return (h * 64 + 30) / (31 * (1 << (16 - num_bits)));
|
||||
}
|
||||
|
||||
struct bc6h_block
|
||||
{
|
||||
uint8_t m_bytes[16];
|
||||
@@ -987,6 +1029,26 @@ namespace basist
|
||||
void bc6h_enc_block_2subset_mode9_3bit_weights(bc6h_block* pPacked_block, uint32_t common_part_index, const half_float pEndpoints[2][3][2], const uint8_t* pWeights); // pEndpoints[subset][comp][lh_index]
|
||||
void bc6h_enc_block_2subset_3bit_weights(bc6h_block* pPacked_block, uint32_t common_part_index, const half_float pEndpoints[2][3][2], const uint8_t* pWeights); // pEndpoints[subset][comp][lh_index]
|
||||
bool bc6h_enc_block_solid_color(bc6h_block* pPacked_block, const half_float pColor[3]);
|
||||
|
||||
struct bc6h_logical_block
|
||||
{
|
||||
uint32_t m_mode;
|
||||
uint32_t m_partition_pattern; // must be 0 if 1 subset
|
||||
uint32_t m_endpoints[3][4]; // [comp][subset*2+lh_index] - must be already properly packed
|
||||
uint8_t m_weights[16]; // weights must be of the proper size, taking into account skipped MSB's which must be 0
|
||||
|
||||
void clear()
|
||||
{
|
||||
basisu::clear_obj(*this);
|
||||
}
|
||||
};
|
||||
|
||||
void pack_bc6h_block(bc6h_block& dst_blk, bc6h_logical_block& log_blk);
|
||||
|
||||
namespace bc7_mode_5_encoder
|
||||
{
|
||||
void encode_bc7_mode_5_block(void* pDst_block, color32* pPixels, bool hq_mode);
|
||||
}
|
||||
|
||||
} // namespace basist
|
||||
|
||||
|
||||
+1
-1
@@ -658,7 +658,7 @@ ktxTexture2_transcodeUastc(ktxTexture2* This,
|
||||
ktxLevelIndexEntry* protoLevelIndex = protoPriv._levelIndex;
|
||||
ktx_size_t levelOffsetWrite = 0;
|
||||
|
||||
basisu_lowlevel_uastc_transcoder uit;
|
||||
basisu_lowlevel_uastc_ldr_4x4_transcoder uit;
|
||||
// See comment on same declaration in transcodeEtc1s.
|
||||
std::vector<basisu_transcoder_state> xcoderStates;
|
||||
xcoderStates.resize(This->isVideo ? This->numFaces : 1);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/thirdparty/libktx/lib/basis_transcode.cpp b/thirdparty/libktx/lib/basis_transcode.cpp
|
||||
index d7ecb7a0fd..43ad059150 100644
|
||||
--- a/thirdparty/libktx/lib/basis_transcode.cpp
|
||||
+++ b/thirdparty/libktx/lib/basis_transcode.cpp
|
||||
@@ -658,7 +658,7 @@ ktxTexture2_transcodeUastc(ktxTexture2* This,
|
||||
ktxLevelIndexEntry* protoLevelIndex = protoPriv._levelIndex;
|
||||
ktx_size_t levelOffsetWrite = 0;
|
||||
|
||||
- basisu_lowlevel_uastc_transcoder uit;
|
||||
+ basisu_lowlevel_uastc_ldr_4x4_transcoder uit;
|
||||
// See comment on same declaration in transcodeEtc1s.
|
||||
std::vector<basisu_transcoder_state> xcoderStates;
|
||||
xcoderStates.resize(This->isVideo ? This->numFaces : 1);
|
||||
Reference in New Issue
Block a user