From 0c7aedbec3359bc3f3883d7b03e20dfa0c7217d0 Mon Sep 17 00:00:00 2001 From: ql <826038571@qq.com> Date: Wed, 15 May 2024 17:46:24 +0800 Subject: [PATCH] ASTC-encoder update to 4.7.0 Signed-off-by: zhaonan287 --- BUILD.gn | 2 - CMakeLists.txt | 224 +-- Docs/Building.md | 151 +- Docs/ChangeLog-2x.md | 328 ---- Docs/ChangeLog-3x.md | 4 - Docs/ChangeLog-4x.md | 398 ++++ Docs/ChangeLogImg/absolute-1.7-to-2.0.png | Bin 114044 -> 0 bytes Docs/ChangeLogImg/absolute-2.0-to-2.1.png | Bin 151755 -> 0 bytes Docs/ChangeLogImg/absolute-2.1-to-2.2.png | Bin 144084 -> 0 bytes Docs/ChangeLogImg/absolute-2.2-to-2.3.png | Bin 152303 -> 0 bytes Docs/ChangeLogImg/absolute-2.5-to-3.0.png | Bin 136735 -> 0 bytes Docs/ChangeLogImg/relative-1.7-to-2.0.png | Bin 114507 -> 0 bytes Docs/ChangeLogImg/relative-2.0-to-2.1.png | Bin 122453 -> 0 bytes Docs/ChangeLogImg/relative-2.1-to-2.2.png | Bin 122512 -> 0 bytes Docs/ChangeLogImg/relative-2.2-to-2.3.png | Bin 125721 -> 0 bytes Docs/ChangeLogImg/relative-3.7-to-4.0.png | Bin 0 -> 123644 bytes Docs/ChangeLogImg/relative-4.0-to-4.2.png | Bin 0 -> 129092 bytes Docs/ChangeLogImg/relative-4.2-to-4.3.png | Bin 0 -> 118479 bytes Docs/ChangeLogImg/relative-4.3-to-4.4.png | Bin 0 -> 110253 bytes Docs/Encoding.md | 130 +- Docs/Testing.md | 4 +- README.OpenSource | 2 +- README.md | 71 +- README_zh.md | 2 +- Source/CMakeLists.txt | 91 +- .../fuzz_astc_physical_to_symbolic.cpp | 4 +- Source/UnitTest/CMakeLists.txt | 44 +- Source/UnitTest/cmake_core.cmake | 172 +- Source/UnitTest/test_decode.cpp | 79 + Source/UnitTest/test_simd.cpp | 488 +++-- Source/astcenc.h | 187 +- Source/astcenc_averages_and_directions.cpp | 113 +- Source/astcenc_block_sizes.cpp | 156 +- Source/astcenc_color_quantize.cpp | 969 +++++----- Source/astcenc_color_unquantize.cpp | 426 ++--- Source/astcenc_compress_symbolic.cpp | 443 +++-- Source/astcenc_compute_variance.cpp | 65 +- Source/astcenc_decompress_symbolic.cpp | 203 +- Source/astcenc_diagnostic_trace.cpp | 43 +- Source/astcenc_diagnostic_trace.h | 4 +- Source/astcenc_entry.cpp | 430 +++-- Source/astcenc_find_best_partitioning.cpp | 253 +-- .../astcenc_ideal_endpoints_and_weights.cpp | 362 ++-- Source/astcenc_image.cpp | 141 +- Source/astcenc_integer_sequence.cpp | 127 +- Source/astcenc_internal.h | 1014 ++++------ Source/astcenc_internal_entry.h | 330 ++++ Source/astcenc_mathlib.h | 18 +- Source/astcenc_mathlib_softfloat.cpp | 20 +- Source/astcenc_partition_tables.cpp | 79 +- Source/astcenc_percentile_tables.cpp | 1653 +++++++++-------- Source/astcenc_pick_best_endpoint_format.cpp | 154 +- Source/astcenc_quantization.cpp | 1160 ++++++++---- Source/astcenc_symbolic_physical.cpp | 241 ++- Source/astcenc_vecmathlib.h | 23 +- Source/astcenc_vecmathlib_avx2_8.h | 224 ++- Source/astcenc_vecmathlib_common_4.h | 34 +- Source/astcenc_vecmathlib_neon_4.h | 178 +- Source/astcenc_vecmathlib_none_4.h | 234 ++- Source/astcenc_vecmathlib_sse_4.h | 249 ++- Source/astcenc_weight_align.cpp | 367 ++-- Source/astcenc_weight_quant_xfer_tables.cpp | 174 +- ...isa_detection.cpp => astcenccli_entry.cpp} | 140 +- Source/astcenccli_error_metrics.cpp | 162 +- Source/astcenccli_image.cpp | 23 +- Source/astcenccli_image_external.cpp | 8 +- Source/astcenccli_image_load_store.cpp | 201 +- Source/astcenccli_internal.h | 60 +- Source/astcenccli_platform_dependents.cpp | 118 +- Source/astcenccli_toplevel.cpp | 892 +++++++-- Source/astcenccli_toplevel_help.cpp | 249 +-- Source/cmake_core.cmake | 455 +++-- Source/stb_image.h | 155 +- Source/stb_image_write.h | 16 +- Source/wuffs-v0.3.c | 26 +- .../astc_reference-3.6-avx2_fast_results.csv | 26 - ...stc_reference-3.6-avx2_fastest_results.csv | 26 - ...astc_reference-3.6-avx2_medium_results.csv | 26 - ...tc_reference-3.6-avx2_thorough_results.csv | 26 - .../astc_reference-3.6-sse2_fast_results.csv | 26 - ...stc_reference-3.6-sse2_fastest_results.csv | 26 - ...astc_reference-3.6-sse2_medium_results.csv | 26 - ...tc_reference-3.6-sse2_thorough_results.csv | 26 - ...astc_reference-3.6-sse4.1_fast_results.csv | 26 - ...c_reference-3.6-sse4.1_fastest_results.csv | 26 - ...tc_reference-3.6-sse4.1_medium_results.csv | 26 - ..._reference-3.6-sse4.1_thorough_results.csv | 26 - .../astc_reference-4.3-avx2_fast_results.csv | 26 + ...stc_reference-4.3-avx2_fastest_results.csv | 26 + ...astc_reference-4.3-avx2_medium_results.csv | 26 + ...tc_reference-4.3-avx2_thorough_results.csv | 26 + .../astc_reference-4.3-sse2_fast_results.csv | 26 + ...stc_reference-4.3-sse2_fastest_results.csv | 26 + ...astc_reference-4.3-sse2_medium_results.csv | 26 + ...tc_reference-4.3-sse2_thorough_results.csv | 26 + ...astc_reference-4.3-sse4.1_fast_results.csv | 26 + ...c_reference-4.3-sse4.1_fastest_results.csv | 26 + ...tc_reference-4.3-sse4.1_medium_results.csv | 26 + ..._reference-4.3-sse4.1_thorough_results.csv | 26 + .../astc_reference-4.4-avx2_fast_results.csv | 26 + ...stc_reference-4.4-avx2_fastest_results.csv | 26 + ...astc_reference-4.4-avx2_medium_results.csv | 26 + ...tc_reference-4.4-avx2_thorough_results.csv | 26 + .../astc_reference-4.4-sse2_fast_results.csv | 26 + ...stc_reference-4.4-sse2_fastest_results.csv | 26 + ...astc_reference-4.4-sse2_medium_results.csv | 26 + ...tc_reference-4.4-sse2_thorough_results.csv | 26 + ...astc_reference-4.4-sse4.1_fast_results.csv | 26 + ...c_reference-4.4-sse4.1_fastest_results.csv | 26 + ...tc_reference-4.4-sse4.1_medium_results.csv | 26 + ..._reference-4.4-sse4.1_thorough_results.csv | 26 + .../astc_reference-4.5-avx2_fast_results.csv | 26 + ...stc_reference-4.5-avx2_fastest_results.csv | 26 + ...astc_reference-4.5-avx2_medium_results.csv | 26 + ...tc_reference-4.5-avx2_thorough_results.csv | 26 + .../astc_reference-3.6-avx2_fast_results.csv | 51 - ...stc_reference-3.6-avx2_fastest_results.csv | 51 - ...astc_reference-3.6-avx2_medium_results.csv | 51 - ...tc_reference-3.6-avx2_thorough_results.csv | 51 - .../astc_reference-3.6-sse2_fast_results.csv | 51 - ...stc_reference-3.6-sse2_fastest_results.csv | 51 - ...astc_reference-3.6-sse2_medium_results.csv | 51 - ...tc_reference-3.6-sse2_thorough_results.csv | 51 - ...astc_reference-3.6-sse4.1_fast_results.csv | 51 - ...c_reference-3.6-sse4.1_fastest_results.csv | 51 - ...tc_reference-3.6-sse4.1_medium_results.csv | 51 - ..._reference-3.6-sse4.1_thorough_results.csv | 51 - .../astc_reference-4.3-avx2_fast_results.csv | 51 + ...stc_reference-4.3-avx2_fastest_results.csv | 51 + ...astc_reference-4.3-avx2_medium_results.csv | 51 + ...tc_reference-4.3-avx2_thorough_results.csv | 51 + .../astc_reference-4.3-sse2_fast_results.csv | 51 + ...stc_reference-4.3-sse2_fastest_results.csv | 51 + ...astc_reference-4.3-sse2_medium_results.csv | 51 + ...tc_reference-4.3-sse2_thorough_results.csv | 51 + ...astc_reference-4.3-sse4.1_fast_results.csv | 51 + ...c_reference-4.3-sse4.1_fastest_results.csv | 51 + ...tc_reference-4.3-sse4.1_medium_results.csv | 51 + ..._reference-4.3-sse4.1_thorough_results.csv | 51 + .../astc_reference-4.4-avx2_fast_results.csv | 51 + ...stc_reference-4.4-avx2_fastest_results.csv | 51 + ...astc_reference-4.4-avx2_medium_results.csv | 51 + ...tc_reference-4.4-avx2_thorough_results.csv | 51 + .../astc_reference-4.4-sse2_fast_results.csv | 51 + ...stc_reference-4.4-sse2_fastest_results.csv | 51 + ...astc_reference-4.4-sse2_medium_results.csv | 51 + ...tc_reference-4.4-sse2_thorough_results.csv | 51 + ...astc_reference-4.4-sse4.1_fast_results.csv | 51 + ...c_reference-4.4-sse4.1_fastest_results.csv | 51 + ...tc_reference-4.4-sse4.1_medium_results.csv | 51 + ..._reference-4.4-sse4.1_thorough_results.csv | 51 + .../astc_reference-4.5-avx2_fast_results.csv | 51 + ...stc_reference-4.5-avx2_fastest_results.csv | 51 + ...astc_reference-4.5-avx2_medium_results.csv | 51 + ...tc_reference-4.5-avx2_thorough_results.csv | 51 + .../astc_reference-3.6-avx2_fast_results.csv | 121 -- ...stc_reference-3.6-avx2_fastest_results.csv | 121 -- ...astc_reference-3.6-avx2_medium_results.csv | 121 -- ...tc_reference-3.6-avx2_thorough_results.csv | 121 -- .../astc_reference-3.6-sse2_fast_results.csv | 121 -- ...stc_reference-3.6-sse2_fastest_results.csv | 121 -- ...astc_reference-3.6-sse2_medium_results.csv | 121 -- ...tc_reference-3.6-sse2_thorough_results.csv | 121 -- ...astc_reference-3.6-sse4.1_fast_results.csv | 121 -- ...c_reference-3.6-sse4.1_fastest_results.csv | 121 -- ...tc_reference-3.6-sse4.1_medium_results.csv | 121 -- ..._reference-3.6-sse4.1_thorough_results.csv | 121 -- .../astc_reference-4.3-avx2_fast_results.csv | 121 ++ ...stc_reference-4.3-avx2_fastest_results.csv | 121 ++ ...astc_reference-4.3-avx2_medium_results.csv | 121 ++ ...tc_reference-4.3-avx2_thorough_results.csv | 121 ++ .../astc_reference-4.3-sse2_fast_results.csv | 121 ++ ...stc_reference-4.3-sse2_fastest_results.csv | 121 ++ ...astc_reference-4.3-sse2_medium_results.csv | 121 ++ ...tc_reference-4.3-sse2_thorough_results.csv | 121 ++ ...astc_reference-4.3-sse4.1_fast_results.csv | 121 ++ ...c_reference-4.3-sse4.1_fastest_results.csv | 121 ++ ...tc_reference-4.3-sse4.1_medium_results.csv | 121 ++ ..._reference-4.3-sse4.1_thorough_results.csv | 121 ++ .../astc_reference-4.4-avx2_fast_results.csv | 121 ++ ...stc_reference-4.4-avx2_fastest_results.csv | 121 ++ ...astc_reference-4.4-avx2_medium_results.csv | 121 ++ ...tc_reference-4.4-avx2_thorough_results.csv | 121 ++ .../astc_reference-4.4-sse2_fast_results.csv | 121 ++ ...stc_reference-4.4-sse2_fastest_results.csv | 121 ++ ...astc_reference-4.4-sse2_medium_results.csv | 121 ++ ...tc_reference-4.4-sse2_thorough_results.csv | 121 ++ ...astc_reference-4.4-sse4.1_fast_results.csv | 121 ++ ...c_reference-4.4-sse4.1_fastest_results.csv | 121 ++ ...tc_reference-4.4-sse4.1_medium_results.csv | 121 ++ ..._reference-4.4-sse4.1_thorough_results.csv | 121 ++ .../astc_reference-4.5-avx2_fast_results.csv | 121 ++ ...stc_reference-4.5-avx2_fastest_results.csv | 121 ++ ...astc_reference-4.5-avx2_medium_results.csv | 121 ++ ...tc_reference-4.5-avx2_thorough_results.csv | 121 ++ .../astc_reference-3.6-avx2_fast_results.csv | 6 - ...stc_reference-3.6-avx2_fastest_results.csv | 6 - ...astc_reference-3.6-avx2_medium_results.csv | 6 - ...tc_reference-3.6-avx2_thorough_results.csv | 6 - .../astc_reference-3.6-sse2_fast_results.csv | 6 - ...stc_reference-3.6-sse2_fastest_results.csv | 6 - ...astc_reference-3.6-sse2_medium_results.csv | 6 - ...tc_reference-3.6-sse2_thorough_results.csv | 6 - ...astc_reference-3.6-sse4.1_fast_results.csv | 6 - ...c_reference-3.6-sse4.1_fastest_results.csv | 6 - ...tc_reference-3.6-sse4.1_medium_results.csv | 6 - ..._reference-3.6-sse4.1_thorough_results.csv | 6 - .../astc_reference-4.3-avx2_fast_results.csv | 6 + ...stc_reference-4.3-avx2_fastest_results.csv | 6 + ...astc_reference-4.3-avx2_medium_results.csv | 6 + ...tc_reference-4.3-avx2_thorough_results.csv | 6 + .../astc_reference-4.3-sse2_fast_results.csv | 6 + ...stc_reference-4.3-sse2_fastest_results.csv | 6 + ...astc_reference-4.3-sse2_medium_results.csv | 6 + ...tc_reference-4.3-sse2_thorough_results.csv | 6 + ...astc_reference-4.3-sse4.1_fast_results.csv | 6 + ...c_reference-4.3-sse4.1_fastest_results.csv | 6 + ...tc_reference-4.3-sse4.1_medium_results.csv | 6 + ..._reference-4.3-sse4.1_thorough_results.csv | 6 + .../astc_reference-4.4-avx2_fast_results.csv | 6 + ...stc_reference-4.4-avx2_fastest_results.csv | 6 + ...astc_reference-4.4-avx2_medium_results.csv | 6 + ...tc_reference-4.4-avx2_thorough_results.csv | 6 + .../astc_reference-4.4-sse2_fast_results.csv | 6 + ...stc_reference-4.4-sse2_fastest_results.csv | 6 + ...astc_reference-4.4-sse2_medium_results.csv | 6 + ...tc_reference-4.4-sse2_thorough_results.csv | 6 + ...astc_reference-4.4-sse4.1_fast_results.csv | 6 + ...c_reference-4.4-sse4.1_fastest_results.csv | 6 + ...tc_reference-4.4-sse4.1_medium_results.csv | 6 + ..._reference-4.4-sse4.1_thorough_results.csv | 6 + .../astc_reference-4.5-avx2_fast_results.csv | 6 + ...stc_reference-4.5-avx2_fastest_results.csv | 6 + ...astc_reference-4.5-avx2_medium_results.csv | 6 + ...tc_reference-4.5-avx2_thorough_results.csv | 6 + .../astc_reference-3.6-avx2_fast_results.csv | 21 - ...stc_reference-3.6-avx2_fastest_results.csv | 21 - ...astc_reference-3.6-avx2_medium_results.csv | 21 - ...tc_reference-3.6-avx2_thorough_results.csv | 21 - .../astc_reference-3.6-sse2_fast_results.csv | 21 - ...stc_reference-3.6-sse2_fastest_results.csv | 21 - ...astc_reference-3.6-sse2_medium_results.csv | 21 - ...tc_reference-3.6-sse2_thorough_results.csv | 21 - ...astc_reference-3.6-sse4.1_fast_results.csv | 21 - ...c_reference-3.6-sse4.1_fastest_results.csv | 21 - ...tc_reference-3.6-sse4.1_medium_results.csv | 21 - ..._reference-3.6-sse4.1_thorough_results.csv | 21 - .../astc_reference-4.3-avx2_fast_results.csv | 21 + ...stc_reference-4.3-avx2_fastest_results.csv | 21 + ...astc_reference-4.3-avx2_medium_results.csv | 21 + ...tc_reference-4.3-avx2_thorough_results.csv | 21 + .../astc_reference-4.3-sse2_fast_results.csv | 21 + ...stc_reference-4.3-sse2_fastest_results.csv | 21 + ...astc_reference-4.3-sse2_medium_results.csv | 21 + ...tc_reference-4.3-sse2_thorough_results.csv | 21 + ...astc_reference-4.3-sse4.1_fast_results.csv | 21 + ...c_reference-4.3-sse4.1_fastest_results.csv | 21 + ...tc_reference-4.3-sse4.1_medium_results.csv | 21 + ..._reference-4.3-sse4.1_thorough_results.csv | 21 + .../astc_reference-4.4-avx2_fast_results.csv | 21 + ...stc_reference-4.4-avx2_fastest_results.csv | 21 + ...astc_reference-4.4-avx2_medium_results.csv | 21 + ...tc_reference-4.4-avx2_thorough_results.csv | 21 + .../astc_reference-4.4-sse2_fast_results.csv | 21 + ...stc_reference-4.4-sse2_fastest_results.csv | 21 + ...astc_reference-4.4-sse2_medium_results.csv | 21 + ...tc_reference-4.4-sse2_thorough_results.csv | 21 + ...astc_reference-4.4-sse4.1_fast_results.csv | 21 + ...c_reference-4.4-sse4.1_fastest_results.csv | 21 + ...tc_reference-4.4-sse4.1_medium_results.csv | 21 + ..._reference-4.4-sse4.1_thorough_results.csv | 21 + .../astc_reference-4.5-avx2_fast_results.csv | 21 + ...stc_reference-4.5-avx2_fastest_results.csv | 21 + ...astc_reference-4.5-avx2_medium_results.csv | 21 + ...tc_reference-4.5-avx2_thorough_results.csv | 21 + Test/Images/Small/HDR-RGB/hdr-rgb-r16.ktx | Bin 0 -> 612 bytes Test/Images/Small/HDR-RGB/hdr-rgb-r32.ktx | Bin 0 -> 1124 bytes Test/Images/Small/HDR-RGB/hdr-rgb-rg16.ktx | Bin 0 -> 1124 bytes Test/Images/Small/HDR-RGB/hdr-rgb-rg32.ktx | Bin 0 -> 2148 bytes Test/Images/Small/HDR-RGB/hdr-rgb-rgb16.ktx | Bin 0 -> 1636 bytes Test/Images/Small/HDR-RGB/hdr-rgb-rgb32.ktx | Bin 0 -> 3172 bytes .../Images/Small/HDR-RGBA/hdr-rgba-rgba16.ktx | Bin 0 -> 2148 bytes .../Images/Small/HDR-RGBA/hdr-rgba-rgba32.ktx | Bin 0 -> 4196 bytes .../astc_reference-3.6-avx2_fast_results.csv | 110 -- ...stc_reference-3.6-avx2_fastest_results.csv | 110 -- ...astc_reference-3.6-avx2_medium_results.csv | 110 -- ...tc_reference-3.6-avx2_thorough_results.csv | 110 -- .../astc_reference-3.6-sse2_fast_results.csv | 110 -- ...stc_reference-3.6-sse2_fastest_results.csv | 110 -- ...astc_reference-3.6-sse2_medium_results.csv | 110 -- ...tc_reference-3.6-sse2_thorough_results.csv | 110 -- ...astc_reference-3.6-sse4.1_fast_results.csv | 110 -- ...c_reference-3.6-sse4.1_fastest_results.csv | 110 -- ...tc_reference-3.6-sse4.1_medium_results.csv | 110 -- ..._reference-3.6-sse4.1_thorough_results.csv | 110 -- .../astc_reference-4.3-avx2_fast_results.csv | 150 ++ ...stc_reference-4.3-avx2_fastest_results.csv | 150 ++ ...astc_reference-4.3-avx2_medium_results.csv | 150 ++ ...tc_reference-4.3-avx2_thorough_results.csv | 150 ++ .../astc_reference-4.3-sse2_fast_results.csv | 150 ++ ...stc_reference-4.3-sse2_fastest_results.csv | 150 ++ ...astc_reference-4.3-sse2_medium_results.csv | 150 ++ ...tc_reference-4.3-sse2_thorough_results.csv | 150 ++ ...astc_reference-4.3-sse4.1_fast_results.csv | 150 ++ ...c_reference-4.3-sse4.1_fastest_results.csv | 150 ++ ...tc_reference-4.3-sse4.1_medium_results.csv | 150 ++ ..._reference-4.3-sse4.1_thorough_results.csv | 150 ++ .../astc_reference-4.4-avx2_fast_results.csv | 150 ++ ...stc_reference-4.4-avx2_fastest_results.csv | 150 ++ ...astc_reference-4.4-avx2_medium_results.csv | 150 ++ ...tc_reference-4.4-avx2_thorough_results.csv | 150 ++ .../astc_reference-4.4-sse2_fast_results.csv | 150 ++ ...stc_reference-4.4-sse2_fastest_results.csv | 150 ++ ...astc_reference-4.4-sse2_medium_results.csv | 150 ++ ...tc_reference-4.4-sse2_thorough_results.csv | 150 ++ ...astc_reference-4.4-sse4.1_fast_results.csv | 150 ++ ...c_reference-4.4-sse4.1_fastest_results.csv | 150 ++ ...tc_reference-4.4-sse4.1_medium_results.csv | 150 ++ ..._reference-4.4-sse4.1_thorough_results.csv | 150 ++ .../astc_reference-4.5-avx2_fast_results.csv | 150 ++ ...stc_reference-4.5-avx2_fastest_results.csv | 150 ++ ...astc_reference-4.5-avx2_medium_results.csv | 150 ++ ...tc_reference-4.5-avx2_thorough_results.csv | 150 ++ Test/astc_dump_binary.py | 4 +- Test/astc_image_sweep.py | 4 +- Test/astc_minify_test.sh | 16 +- Test/astc_profile_valgrind.py | 25 +- Test/astc_quality_test.py | 4 +- Test/astc_test_competitive.py | 2 +- Test/astc_test_functional.py | 294 ++- Test/astc_test_image.py | 57 +- Test/astc_test_result_plot.py | 99 +- Test/astc_update_ref.sh | 8 +- Test/testlib/encoder.py | 28 +- Test/testlib/image.py | 50 +- Test/testlib/resultset.py | 4 +- Utils/Example/CMakeLists.txt | 12 +- Utils/astc_blend_test.cpp | 298 +++ Utils/astc_quant_generator.cpp | 406 ++++ Utils/astcenc_u8_test_bench.cpp | 117 ++ bundle.json | 2 +- jenkins/build-image.sh | 9 +- jenkins/build.Dockerfile | 11 +- jenkins/nightly.Jenkinsfile | 75 +- jenkins/release.Jenkinsfile | 156 +- 345 files changed, 20682 insertions(+), 10292 deletions(-) delete mode 100644 Docs/ChangeLog-2x.md create mode 100644 Docs/ChangeLog-4x.md delete mode 100644 Docs/ChangeLogImg/absolute-1.7-to-2.0.png delete mode 100644 Docs/ChangeLogImg/absolute-2.0-to-2.1.png delete mode 100644 Docs/ChangeLogImg/absolute-2.1-to-2.2.png delete mode 100644 Docs/ChangeLogImg/absolute-2.2-to-2.3.png delete mode 100644 Docs/ChangeLogImg/absolute-2.5-to-3.0.png delete mode 100644 Docs/ChangeLogImg/relative-1.7-to-2.0.png delete mode 100644 Docs/ChangeLogImg/relative-2.0-to-2.1.png delete mode 100644 Docs/ChangeLogImg/relative-2.1-to-2.2.png delete mode 100644 Docs/ChangeLogImg/relative-2.2-to-2.3.png create mode 100644 Docs/ChangeLogImg/relative-3.7-to-4.0.png create mode 100644 Docs/ChangeLogImg/relative-4.0-to-4.2.png create mode 100644 Docs/ChangeLogImg/relative-4.2-to-4.3.png create mode 100644 Docs/ChangeLogImg/relative-4.3-to-4.4.png create mode 100644 Source/UnitTest/test_decode.cpp create mode 100644 Source/astcenc_internal_entry.h rename Source/{astcenc_platform_isa_detection.cpp => astcenccli_entry.cpp} (57%) delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/HDRIHaven/astc_reference-4.5-avx2_thorough_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/Khronos/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/Khronos/astc_reference-4.5-avx2_thorough_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/Kodak/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/Kodak/astc_reference-4.5-avx2_thorough_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/KodakMnt/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/KodakMnt/astc_reference-4.5-avx2_thorough_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/KodakSim/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/KodakSim/astc_reference-4.5-avx2_thorough_results.csv create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-r16.ktx create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-r32.ktx create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-rg16.ktx create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-rg32.ktx create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-rgb16.ktx create mode 100644 Test/Images/Small/HDR-RGB/hdr-rgb-rgb32.ktx create mode 100644 Test/Images/Small/HDR-RGBA/hdr-rgba-rgba16.ktx create mode 100644 Test/Images/Small/HDR-RGBA/hdr-rgba-rgba32.ktx delete mode 100644 Test/Images/Small/astc_reference-3.6-avx2_fast_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-avx2_fastest_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-avx2_medium_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-avx2_thorough_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse2_fast_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse2_fastest_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse2_medium_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse2_thorough_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse4.1_fast_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse4.1_fastest_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse4.1_medium_results.csv delete mode 100644 Test/Images/Small/astc_reference-3.6-sse4.1_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-avx2_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-avx2_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-avx2_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-avx2_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse2_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse2_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse2_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse2_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse4.1_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse4.1_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse4.1_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.3-sse4.1_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-avx2_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-avx2_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-avx2_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-avx2_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse2_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse2_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse2_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse2_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse4.1_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse4.1_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse4.1_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.4-sse4.1_thorough_results.csv create mode 100644 Test/Images/Small/astc_reference-4.5-avx2_fast_results.csv create mode 100644 Test/Images/Small/astc_reference-4.5-avx2_fastest_results.csv create mode 100644 Test/Images/Small/astc_reference-4.5-avx2_medium_results.csv create mode 100644 Test/Images/Small/astc_reference-4.5-avx2_thorough_results.csv create mode 100644 Utils/astc_blend_test.cpp create mode 100644 Utils/astc_quant_generator.cpp create mode 100644 Utils/astcenc_u8_test_bench.cpp diff --git a/BUILD.gn b/BUILD.gn index e55cf09..e509193 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -38,7 +38,6 @@ ohos_source_set("astc_encoder_static") { "//third_party/astc-encoder/Source/astcenc_partition_tables.cpp", "//third_party/astc-encoder/Source/astcenc_percentile_tables.cpp", "//third_party/astc-encoder/Source/astcenc_pick_best_endpoint_format.cpp", - "//third_party/astc-encoder/Source/astcenc_platform_isa_detection.cpp", "//third_party/astc-encoder/Source/astcenc_quantization.cpp", "//third_party/astc-encoder/Source/astcenc_symbolic_physical.cpp", "//third_party/astc-encoder/Source/astcenc_weight_align.cpp", @@ -51,7 +50,6 @@ ohos_source_set("astc_encoder_static") { ohos_shared_library("astc_encoder_shared") { public_configs = [ ":astc_encoder_config" ] deps = [ ":astc_encoder_static" ] - output_extension = "so" install_enable = true part_name = "astc-encoder" innerapi_tags = [ "platformsdk" ] diff --git a/CMakeLists.txt b/CMakeLists.txt index a17cb93..3044715 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ---------------------------------------------------------------------------- -# Copyright 2020-2022 Arm Limited +# Copyright 2020-2024 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -24,163 +24,83 @@ if(MSVC) add_compile_options("/wd4324") # Disable structure was padded due to alignment specifier endif() -project(astcencoder VERSION 3.7.0) +project(astcencoder VERSION 4.7.0) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS 1) -set(PACKAGE_ROOT astcenc) +set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS "x86_64 x86_64h arm64") include(CTest) -option(ISA_AVX2 "Enable builds for AVX2 SIMD") -option(ISA_SSE41 "Enable builds for SSE4.1 SIMD") -option(ISA_SSE2 "Enable builds for SSE2 SIMD") -option(ISA_NEON "Enable builds for NEON SIMD") -option(ISA_NONE "Enable builds for no SIMD") -option(ISA_NATIVE "Enable builds for native SIMD") -option(DECOMPRESSOR "Enable builds for decompression only") -option(DIAGNOSTICS "Enable builds for diagnostic trace") -option(ASAN "Enable builds width address sanitizer") -option(UNITTEST "Enable builds for unit tests") -option(NO_INVARIANCE "Enable builds without invariance") -option(CLI "Enable build of CLI" ON) - -set(UNIVERSAL_BUILD OFF) -set(MACOS_BUILD OFF) -set(MACOS_ARCH_LEN 0) +option(ASTCENC_ISA_AVX2 "Enable astcenc builds for AVX2 SIMD") +option(ASTCENC_ISA_SSE41 "Enable astcenc builds for SSE4.1 SIMD") +option(ASTCENC_ISA_SSE2 "Enable astcenc builds for SSE2 SIMD") +option(ASTCENC_ISA_NEON "Enable astcenc builds for NEON SIMD") +option(ASTCENC_ISA_NONE "Enable astcenc builds for no SIMD") +option(ASTCENC_ISA_NATIVE "Enable astcenc builds for native SIMD") +option(ASTCENC_DECOMPRESSOR "Enable astcenc builds for decompression only") +option(ASTCENC_SHAREDLIB "Enable astcenc builds with core library shared objects") +option(ASTCENC_DIAGNOSTICS "Enable astcenc builds with diagnostic trace") +option(ASTCENC_ASAN "Enable astcenc builds with address sanitizer") +option(ASTCENC_UNITTEST "Enable astcenc builds with unit tests") +option(ASTCENC_INVARIANCE "Enable astcenc floating point invariance" ON) +option(ASTCENC_CLI "Enable build of astcenc command line tools" ON) # Preflight for some macOS-specific build options if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") - set(MACOS_BUILD ON) - list(LENGTH CMAKE_OSX_ARCHITECTURES MACOS_ARCH_LEN) -endif() - -# Count options which MUST be x64 -set(X64_ISA_COUNT 0) -set(CONFIGS ${ISA_AVX2} ${ISA_SSE41} ${ISA_SSE2}) -foreach(CONFIG ${CONFIGS}) - if(${CONFIG}) - math(EXPR X64_ISA_COUNT "${X64_ISA_COUNT} + 1") - endif() -endforeach() - -# Count options which MUST be arm64 -set(ARM64_ISA_COUNT 0) -set(CONFIGS ${ISA_NEON}) -foreach(CONFIG ${CONFIGS}) - if(${CONFIG}) - math(EXPR ARM64_ISA_COUNT "${ARM64_ISA_COUNT} + 1") - endif() -endforeach() - -# macOS builds -if("${MACOS_BUILD}") - list(FIND CMAKE_OSX_ARCHITECTURES "x86_64" IS_X64) - list(FIND CMAKE_OSX_ARCHITECTURES "arm64" IS_ARM64) - list(FIND CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD)" IS_AUTO) - - # Turn list index into boolean - if(${IS_X64} EQUAL -1) - set(IS_X64 OFF) - else() - set(IS_X64 ON) - endif() - - if(${IS_ARM64} EQUAL -1) - set(IS_ARM64 OFF) - else() - set(IS_ARM64 ON) - endif() - - if(${IS_AUTO} EQUAL -1) - set(IS_AUTO OFF) - else() - set(IS_AUTO ON) - endif() - - # Set up defaults if no more specific ISA set - use XCode's own defaults - if((IS_ARM64 OR IS_AUTO) AND ("${ARM64_ISA_COUNT}" EQUAL 0) AND (NOT "${ISA_NONE}")) - set(ARM64_ISA_COUNT 1) - set(ISA_NEON ON) - endif() + option(ASTCENC_UNIVERSAL_BUILD "Enable universal multi-arch build" ON) - if((IS_X64 OR IS_AUTO) AND ("${X64_ISA_COUNT}" EQUAL 0) AND (NOT "${ISA_NONE}")) - set(X64_ISA_COUNT 1) - set(ISA_SSE41 ON) - endif() + if(${ASTCENC_UNIVERSAL_BUILD}) + set(ASTCENC_ISA_SSE41 ON) + set(ASTCENC_ISA_AVX2 ON) + set(ASTCENC_ISA_NEON ON) - # User might be doing multi-architecture - XCode sets this at runtime - if("${IS_AUTO}") - if(("${ARM64_ISA_COUNT}" GREATER 1) OR ("${X64_ISA_COUNT}" GREATER 1)) - message(FATAL_ERROR "For macOS universal binaries only one backend per architecture is allowed.") + if(${ASTCENC_ISA_SSE2}) + message(FATAL_ERROR "ISA_SSE2 cannot be used in a universal build") endif() - set(UNIVERSAL_BUILD ON) - - # User requested explicit multi-architecture universal build - elseif("${MACOS_ARCH_LEN}" GREATER 2) - message(FATAL_ERROR "For macOS universal binaries only x86_64 and arm64 builds are allowed.") - - elseif("${MACOS_ARCH_LEN}" EQUAL 2) - if(NOT (${IS_X64} AND ${IS_ARM64})) - message(FATAL_ERROR "For macOS universal binaries only x86_64 and arm64 builds are allowed.") + if(${ASTCENC_ISA_NONE}) + message(FATAL_ERROR "ISA_NONE cannot be used in a universal build") endif() - if(("${ARM64_ISA_COUNT}" GREATER 1) OR ("${X64_ISA_COUNT}" GREATER 1)) - message(FATAL_ERROR "For macOS universal binaries only one backend per architecture is allowed.") + if(${ASTCENC_ISA_NATIVE}) + message(FATAL_ERROR "ISA_NATIVE cannot be used in a universal build") endif() + endif() +else() + set(ASTCENC_UNIVERSAL_BUILD OFF) +endif() - set(UNIVERSAL_BUILD ON) - - # User requested explicit single architecture build - elseif("${MACOS_ARCH_LEN}" EQUAL 1) - if("${IS_X64}" AND "${ARM64_ISA_COUNT}") - message(FATAL_ERROR "For macOS x86_64 builds an arm64 backend cannot be specified.") - endif() - - if("${IS_ARM64}" AND "${X64_ISA_COUNT}") - message(FATAL_ERROR "For macOS arm64 builds an x86_64 backend cannot be specified.") - endif() - - # Else is this a implicit multi-architecture universal build? - elseif(("${ARM64_ISA_COUNT}" EQUAL 1) AND ("${X64_ISA_COUNT}" GREATER 1)) - string(CONCAT MSG "For macOS setting multiple architecture backends builds a universal binary. " - "For universal binaries only one backend per architecture is allowed.") - message(FATAL_ERROR "${MSG}") - - elseif(("${X64_ISA_COUNT}" EQUAL 1) AND ("${ARM64_ISA_COUNT}" GREATER 1)) - string(CONCAT MSG "For macOS setting multiple architecture backends builds a universal binary. " - "For universal binaries only one backend per architecture is allowed.") - message(FATAL_ERROR "${MSG}") - - elseif(("${ARM64_ISA_COUNT}" EQUAL 1) AND ("${X64_ISA_COUNT}" EQUAL 1)) - set(UNIVERSAL_BUILD ON) - set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64") - - # Else is this an implicit single architecture build? - elseif("${ARM64_ISA_COUNT}" EQUAL 1) - set(CMAKE_OSX_ARCHITECTURES "arm64") - - elseif("${X64_ISA_COUNT}" EQUAL 1) - set(CMAKE_OSX_ARCHITECTURES "x86_64") - - else() - # Do nothing here - assume it defaults to host? +# Count options which MUST be x64 +set(ASTCENC_X64_ISA_COUNT 0) +set(ASTCENC_CONFIGS ${ASTCENC_ISA_AVX2} ${ASTCENC_ISA_SSE41} ${ASTCENC_ISA_SSE2}) +foreach(ASTCENC_CONFIG ${ASTCENC_CONFIGS}) + if(${ASTCENC_CONFIG}) + math(EXPR ASTCENC_X64_ISA_COUNT "${ASTCENC_X64_ISA_COUNT} + 1") + endif() +endforeach() +# Count options which MUST be arm64 +set(ASTCENC_ARM64_ISA_COUNT 0) +set(ASTCENC_CONFIGS ${ASTCENC_ISA_NEON}) +foreach(ASTCENC_CONFIG ${ASTCENC_CONFIGS}) + if(${ASTCENC_CONFIG}) + math(EXPR ASTCENC_ARM64_ISA_COUNT "${ASTCENC_ARM64_ISA_COUNT} + 1") endif() +endforeach() # Non-macOS builds -else() - if(("${ARM64_ISA_COUNT}" GREATER 0) AND ("${X64_ISA_COUNT}" GREATER 0)) +if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + if(("${ASTCENC_ARM64_ISA_COUNT}" GREATER 0) AND ("${ASTCENC_X64_ISA_COUNT}" GREATER 0)) message(FATAL_ERROR "Builds can only support a single architecture per configure.") endif() endif() # If nothing more specific is set then fall back on the compiler's defaults -if(("${ARM64_ISA_COUNT}" EQUAL 0) AND ("${X64_ISA_COUNT}" EQUAL 0) AND (NOT "${ISA_NONE}")) - set(ISA_NATIVE ON) +if(("${ASTCENC_ARM64_ISA_COUNT}" EQUAL 0) AND ("${ASTCENC_X64_ISA_COUNT}" EQUAL 0) AND (NOT "${ASTCENC_ISA_NONE}")) + set(ASTCENC_ISA_NATIVE ON) endif() function(printopt optName optVal) @@ -191,38 +111,38 @@ function(printopt optName optVal) endif() endfunction() -if("${BLOCK_MAX_TEXELS}") - message(STATUS " Max block texels - ${BLOCK_MAX_TEXELS}") +if("${ASTCENC_BLOCK_MAX_TEXELS}") + message(STATUS " Max block texels - ${ASTCENC_BLOCK_MAX_TEXELS}") endif() -printopt("AVX2 backend " ${ISA_AVX2}) -printopt("SSE4.1 backend " ${ISA_SSE41}) -printopt("SSE2 backend " ${ISA_SSE2}) -printopt("NEON backend " ${ISA_NEON}) -printopt("NONE backend " ${ISA_NONE}) -printopt("NATIVE backend " ${ISA_NATIVE}) -if("${MACOS_BUILD}") - printopt("Universal bin " ${UNIVERSAL_BUILD}) + +printopt("AVX2 backend " ${ASTCENC_ISA_AVX2}) +printopt("SSE4.1 backend " ${ASTCENC_ISA_SSE41}) +printopt("SSE2 backend " ${ASTCENC_ISA_SSE2}) +printopt("NEON backend " ${ASTCENC_ISA_NEON}) +printopt("NONE backend " ${ASTCENC_ISA_NONE}) +printopt("NATIVE backend " ${ASTCENC_ISA_NATIVE}) +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + printopt("Universal bin " ${ASTCENC_UNIVERSAL_BUILD}) endif() -printopt("Decompressor " ${DECOMPRESSOR}) -printopt("No invariance " ${NO_INVARIANCE}) -printopt("Diagnostics " ${DIAGNOSTICS}) -printopt("ASAN " ${ASAN}) -printopt("Unit tests " ${UNITTEST}) +printopt("Invariance " ${ASTCENC_INVARIANCE}) +printopt("Shared libs " ${ASTCENC_SHAREDLIB}) +printopt("Decompressor " ${ASTCENC_DECOMPRESSOR}) +printopt("Diagnostics " ${ASTCENC_DIAGNOSTICS}) +printopt("ASAN " ${ASTCENC_ASAN}) +printopt("Unit tests " ${ASTCENC_UNITTEST}) # Subcomponents add_subdirectory(Source) # Configure package archive -if(PACKAGE) - if("${MACOS_BUILD}") - string(TOLOWER "macOS" PKG_OS) +if(ASTCENC_PACKAGE) + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") + string(TOLOWER "macOS" ASTCENC_PKG_OS) else() - string(TOLOWER ${CMAKE_SYSTEM_NAME} PKG_OS) + string(TOLOWER ${CMAKE_SYSTEM_NAME} ASTCENC_PKG_OS) endif() - set(PKG_VER ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}) - - set(CPACK_PACKAGE_FILE_NAME "astcenc-${PKG_VER}-${PKG_OS}-${PACKAGE}") + set(CPACK_PACKAGE_FILE_NAME "astcenc-${CMAKE_PROJECT_VERSION}-${ASTCENC_PKG_OS}-${ASTCENC_PACKAGE}") set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY FALSE) set(CPACK_PACKAGE_CHECKSUM SHA256) set(CPACK_GENERATOR ZIP) diff --git a/Docs/Building.md b/Docs/Building.md index d695dde..dda9df1 100644 --- a/Docs/Building.md +++ b/Docs/Building.md @@ -10,7 +10,7 @@ backends. ## Windows -Builds for Windows are tested with CMake 3.17 and Visual Studio 2019. +Builds for Windows are tested with CMake 3.17, and Visual Studio 2019 or newer. ### Configuring the build @@ -25,13 +25,13 @@ cd build # Configure your build of choice, for example: +# x86-64 using a Visual Studio solution +cmake -G "Visual Studio 16 2019" -T ClangCL -DCMAKE_INSTALL_PREFIX=..\ ^ + -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON .. + # x86-64 using NMake cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=..\ ^ - -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON .. - -# x86-64 using Visual Studio solution -cmake -G "Visual Studio 16 2019" -T ClangCL -DCMAKE_INSTALL_PREFIX=..\ ^ - -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON .. + -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON .. ``` A single CMake configure can build multiple binaries for a single target CPU @@ -49,14 +49,15 @@ Once you have configured the build you can use NMake to compile the project from your build dir, and install to your target install directory. ```shell -# Run a build and install build outputs in `${CMAKE_INSTALL_PREFIX}/astcenc/` +# Run a build and install build outputs in `${CMAKE_INSTALL_PREFIX}/bin/` cd build nmake install ``` -## macOS and Linux +## macOS and Linux using Make -Builds for macOS and Linux are tested with CMake 3.17 and clang++ 9.0. +Builds for macOS and Linux are tested with CMake 3.17, and clang++ 9.0 or +newer. > Compiling using g++ is supported, but clang++ builds are faster by ~15%. @@ -78,15 +79,14 @@ cd build # Arm arch64 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ \ - -DISA_NEON=ON .. + -DASTCENC_ISA_NEON=ON .. # x86-64 cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ \ - -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON .. + -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON .. # macOS universal binary build -cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ \ - -DISA_AVX2=ON -DISA_NEON=ON .. +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ .. ``` A single CMake configure can build multiple binaries for a single target CPU @@ -94,14 +94,13 @@ architecture, for example building x64 for both SSE2 and AVX2. Each binary name will include the build variant as a postfix. It is possible to build any set of the supported SIMD variants by enabling only the ones you require. -For macOS, we additionally support the ability to build a universal binary, -combining one x86 and one arm64 variant into a single output binary. The OS -will select the correct variant to run for the machine being used to run the -built binary. To build a universal binary select a single x86 variant and a -single arm64 variant, and both will be included in a single output binary. It -is not required, but if `CMAKE_OSX_ARCHITECTURES` is set on the command line -(e.g. by XCode-generated build commands) it will be validated against the other -configuration variant settings. +For macOS, we additionally support the ability to build a universal binary. +This build includes SSE4.1 (`x86_64`), AVX2 (`x86_64h`), and NEON (`arm64`) +build slices in a single output binary. The OS will select the correct variant +to run for the machine being used. This is the default build target for a macOS +build, but single-target binaries can still be built by setting +`-DASTCENC_UNIVERSAL_BINARY=OFF` and then manually selecting the specific ISA +variants that are required. ### Building @@ -109,11 +108,44 @@ Once you have configured the build you can use Make to compile the project from your build dir, and install to your target install directory. ```shell -# Run a build and install build outputs in `${CMAKE_INSTALL_PREFIX}/astcenc/` +# Run a build and install build outputs in `${CMAKE_INSTALL_PREFIX}/bin/` +# for executable binaries and `${CMAKE_INSTALL_PREFIX}/lib/` for libraries cd build make install -j16 ``` +## macOS using XCode + +Builds for macOS and Linux are tested with CMake 3.17, and XCode 14.0 or +newer. + +### Configuring the build + +To use CMake you must first configure the build. Create a build directory +in the root of the astcenc checkout, and then run `cmake` inside that directory +to generate the build system. + +```shell +# Create a build directory +mkdir build +cd build + +# Configure a universal build +cmake -G Xcode -DCMAKE_INSTALL_PREFIX=../ .. +``` + +### Building + +Once you have configured the build you can use CMake to compile the project +from your build dir, and install to your target install directory. + +```shell +cmake --build . --config Release + +# Optionally install the binaries to the installation directory +cmake --install . --config Release +``` + ## Advanced build options For codec developers and power users there are a number of useful features in @@ -132,22 +164,33 @@ We support and test the following `CMAKE_BUILD_TYPE` options. Note that optimized release builds are compiled with link-time optimization, which can make profiling more challenging ... +### Shared Libraries + +We support building the core library as a shared object by setting the CMake +option `-DASTCENC_SHAREDLIB=ON` at configure time. For macOS build targets the +shared library supports the same universal build configuration as the command +line utility. + +Note that the command line tool is always statically linked; the shared objects +are an extra build output that are not currently used by the command line tool. + ### Constrained block size builds All normal builds will support all ASTC block sizes, including the worst case 6x6x6 3D block size (216 texels per block). Compressor memory footprint and performance can be improved by limiting the block sizes supported in the build -by adding `-DBLOCK_MAX_TEXELS=` to to CMake command line when -configuring. Legal block sizes that are unavailable in a restricted build will -return the error `ASTCENC_ERR_NOT_IMPLEMENTED` during context creation. +by adding `-DASTCENC_BLOCK_MAX_TEXELS=` to to CMake command line +when configuring. Legal block sizes that are unavailable in a restricted build +will return the error `ASTCENC_ERR_NOT_IMPLEMENTED` during context creation. ### Non-invariant builds All normal builds are designed to be invariant, so any build from the same git revision will produce bit-identical results for all compilers and CPU architectures. To achieve this we sacrifice some performance, so if this is -not required you can specify `-DNO_INVARIANCE=ON` to enable additional -optimizations. +not required you can specify `-DASTCENC_INVARIANCE=OFF` to enable additional +optimizations. This has most benefit for AVX2 builds where we are able to +enable use of the FMA instruction set extensions. ### No intrinsics builds @@ -156,8 +199,8 @@ supported target architectures (x86 and arm64) guarantee SIMD availability. For development purposes it is possible to build an intrinsic-free build which uses no explicit SIMD acceleration (the compiler may still auto-vectorize). -To enable this binary variant add `-DISA_NONE=ON` to the CMake command line -when configuring. It is NOT recommended to use this for production; it is +To enable this binary variant add `-DASTCENC_ISA_NONE=ON` to the CMake command +line when configuring. It is NOT recommended to use this for production; it is significantly slower than the vectorized SIMD builds. ### Test builds @@ -171,7 +214,7 @@ git submodule init git submodule update ``` -To build unit tests add `-DUNITTEST=ON` to the CMake command line when +To build unit tests add `-DASTCENC_UNITTEST=ON` to the CMake command line when configuring. To run unit tests use the CMake `ctest` utility from your build directory after @@ -185,14 +228,56 @@ ctest --verbose ### Address sanitizer builds We support building with ASAN on Linux and macOS when using a compiler that -supports it. To build binaries with ASAN checking enabled add `-DASAN=ON` to -the CMake command line when configuring. +supports it. To build binaries with ASAN checking enabled add `-DASTCENC_ASAN=ON` +to the CMake command line when configuring. + +### Android builds + +Builds of the command line utility for Android are not officially supported, but can be a useful +development build for testing on e.g. different Arm CPU microarchitectures. + +The build script below shows one possible route to building the command line tool for Android. Once +built the application can be pushed to e.g. `/data/local/tmp` and executed from an Android shell +terminal over `adb`. + +```shell +ANDROID_ABI=arm64-v8a +ANDROID_NDK=/work/tools/android/ndk/22.1.7171670 + +BUILD_TYPE=RelWithDebInfo + +BUILD_DIR=build + +mkdir -p ${BUILD_DIR} +cd ${BUILD_DIR} + +cmake \ + -DCMAKE_INSTALL_PREFIX=./ \ + -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=${ANDROID_ABI} \ + -DANDROID_ARM_NEON=ON \ + -DANDROID_PLATFORM=android-21 \ + -DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \ + -DANDROID_TOOLCHAIN=clang \ + -DANDROID_STL=c++_static \ + -DARCH=aarch64 \ + -DASTCENC_ISA_NEON=ON \ + .. + +make -j16 +``` ## Packaging a release bundle We support building a release bundle of all enabled binary configurations in the current CMake configuration using the `package` build target +Configure CMake with: + +* `-DASTCENC_PACAKGE=` to set the package architecture/variant name used +to name the package archive (not set by default). + ```shell # Run a build and package build outputs in `./astcenc---.` cd build @@ -212,4 +297,4 @@ details. - - - -_Copyright © 2019-2022, Arm Limited and contributors. All rights reserved._ +_Copyright © 2019-2023, Arm Limited and contributors. All rights reserved._ diff --git a/Docs/ChangeLog-2x.md b/Docs/ChangeLog-2x.md deleted file mode 100644 index 0c1ccdc..0000000 --- a/Docs/ChangeLog-2x.md +++ /dev/null @@ -1,328 +0,0 @@ -# 2.x series change log - -This page summarizes the major functional and performance changes in each -release of the 2.x series. - -All performance data on this page is measured on an Intel Core i5-9600K -clocked at 4.2 GHz, running astcenc using 6 threads. - - -## 2.5 - -**Status:** Released, March 2021 - -The 2.5 release is the last major release in the 2.x series. After this release -a `2.x` branch will provide stable long-term support, and the `main` branch -will switch to focusing on more radical changes for the 3.x series. - -Reminder for users of the library interface - the API is not designed to be -stable across versions, and this release is not compatible with earlier 2.x -releases. Please update and rebuild your client-side code using the updated -`astcenc.h` header. - -**General:** - * **Feature:** The `ISA_INVARIANCE` build option is no longer supported, as - there is no longer any performance benefit from the variant paths. All - builds are now using the equivalent of the `ISA_INVARIANCE=ON` setting, and - all builds (except Armv7) are now believed to be invariant across operating - systems, compilers, CPU architectures, and SIMD instruction sets. - * **Feature:** Armv8 32-bit builds with NEON are now supported, with - out-of-the-box support for Arm Linux soft-float and hard-float ABIs. There - are no pre-built binaries for these targets; support is included for - library users targeting older 32-bit Android and iOS devices. - * **Feature:** A compressor mode for encoding HDR textures that have been - encoded into LDR RGBM wrapper format is now supported. Note that this - encoding has some strong recommendations for how the RGBM encoding is - implemented to avoid block artifacts in the compressed image. -* **Core API:** - * **API Change:** The core API has been changed to be a pure C API, making it - easier to wrap the codec in a stable shared library ABI. Some entry points - that used to accept references now expect pointers. - * **API Change:** The decompression functionality in the core API has been - changed to allow use of multiple threads. The design pattern matches the - compression functionality, requiring the caller to create the threads, - synchronize them between images, and to call the new - `astcenc_decompress_reset()` function between images. -* **API Feature:** Defines to support exporting public API entry point - symbols from a shared object are provided, but not exposed off-the-shelf by - the CMake provided by the project. - * **API Feature:** New `astcenc_get_block_info()` function added to the core - API to allow users to perform high level analysis of compressed data. This - API is not implemented in decompressor-only builds. - * **API Feature:** Codec configuration structure has been extended to expose - the new RGBM compression mode. See the API header for details. - - -## 2.4 - -**Status:** Released, February 2021 - -The 2.4 release is the fifth release in the 2.x series. It is primarily a bug -fix release for HDR image handling, which impacts all earlier 2.x series -releases. - -**General:** - * **Feature:** When using the `-a` option, or the equivalent config option - for the API, any 2D blocks that are entirely zero alpha after the alpha - filter radius is taken into account are replaced by transparent black - constant color blocks. This is an RDO-like technique to improve compression - ratios of any additional application packaging compression that is applied. -**Command Line:** - * **Bug fix:** The command line wrapper now correctly loads HDR images that - have a non-square aspect ratio. - - -## 2.3 - -**Status:** Released, January 2021 - -The 2.3 release is the fourth release in the 2.x series. It includes a number -of performance improvements and new features. - -Reminder for users of the library interface - the API is not designed to be -stable across versions, and this release is not compatible with 2.2. Please -recompile your client-side code using the updated `astcenc.h` header. - -* **General:** - * **Feature:** Decompressor-only builds of the codec are supported again. - While this is primarily a feature for library users who want to shrink - binary size, a variant command line tool `astcdec` can be built by - specifying `DECOMPRESSOR=ON` on the CMake configure command line. - * **Feature:** Diagnostic builds of the codec can now be built. These builds - generate a JSON file containing a trace of the compressor execution. - Diagnostic builds are only suitable for codec development; they are slower - and JSON generation cannot be disabled. Build by setting `DIAGNOSTICS=ON` - on the CMake configure command line. - * **Feature:** Code compatibility improved with older versions of GCC, - earliest compiler now tested is GCC 7.5 (was GCC 9.3). - * **Feature:** Code compatibility improved with newer versions of LLVM, - latest compiler now tested is Clang 12.0 (was Clang 9.0). - * **Feature:** Code compatibility improved with the Visual Studio 2019 LLVM - toolset (`clang-cl`). Using the LLVM toolset gives 25% performance - improvements and is recommended. -* **Command Line:** - * **Feature:** Quality level now accepts either a preset (`-fast`, etc) or a - float value between 0 and 100, allowing more control over the compression - quality vs performance trade-off. The presets are not evenly spaced in the - float range; they have been spaced to give the best distribution of points - between the fast and thorough presets. - * `-fastest`: 0.0 - * `-fast`: 10.0 - * `-medium`: 60.0 - * `-thorough`: 98.0 - * `-exhaustive`: 100.0 -* **Core API:** - * **API Change:** Quality level preset enum replaced with a float value - between 0 (`-fastest`) and 100 (`-exhaustive`). See above for more info. - -### Performance - -This release includes a number of optimizations to improve performance. - -* New compressor algorithm for handling encoding candidates and refinement. -* Vectorized implementation of `compute_error_of_weight_set()`. -* Unrolled implementation of `encode_ise()`. -* Many other small improvements! - -The most significant change is the change to the compressor path, which now -uses an adaptive approach to candidate trials and block refinement. - -In earlier releases the quality level will determine the number of encoding -candidates and the number of iterative refinement passes that are used for each -major encoding trial. This is a fixed behavior; it will always try the full N -candidates and M refinement iterations specified by the quality level for each -encoding trial. - -The new approach implements two optimizations for this: - -* Compression will complete when a block candidate hits the specified target - quality, after its M refinement iterations have been applied. Later block - candidates are simply abandoned. -* Block candidates will predict how much refinement can improve them, and - abandon refinement if they are unlikely to improve upon the best known - encoding already in-hand. - -This pair of optimizations provides significant performance improvement to the -high quality modes which use the most block candidates and refinement -iterations. A minor loss of image quality is expected, as the blocks we no -longer test or refine may have been better coding choices. - -**Absolute performance vs 2.2 release:** - -![Absolute scores 2.3 vs 2.2](./ChangeLogImg/absolute-2.2-to-2.3.png) - -**Relative performance vs 2.2 release:** - -![Relative scores 2.3 vs 2.2](./ChangeLogImg/relative-2.2-to-2.3.png) - - -## 2.2 - -**Status:** Released, January 2021 - -The 2.2 release is the third release in the 2.x series. It includes a number -of performance improvements and new features. - -Reminder for users of the library interface - the API is not designed to be -stable across versions, and this release is not compatible with 2.1. Please -recompile your client-side code using the updated `astcenc.h` header. - -* **General:** - * **Feature:** New Arm aarch64 NEON accelerated vector library support. - * **Improvement:** New CMake build system for all platforms. - * **Improvement:** SSE4.2 feature profile changed to SSE4.1, which more - accurately reflects the feature set used. -* **Binary releases:** - * **Improvement:** Linux binaries changed to use Clang 9.0, which gives - up to 15% performance improvement. - * **Improvement:** Windows binaries are now code signed. - * **Improvement:** macOS binaries for Apple silicon platforms now provided. - * **Improvement:** macOS binaries are now code signed and notarized. -* **Command Line:** - * **Feature:** New image preprocess `-pp-normalize` option added. This forces - normal vectors to be unit length, which is useful when compressing source - textures that use normal length to encode an NDF, which is incompatible - with ASTC's two channel encoding. - * **Feature:** New image preprocess `-pp-premultiply` option added. This - scales RGB values by the alpha value. This can be useful to minimize - cross-channel color bleed caused by GPU post-multiply filtering/blending. - * **Improvements:** Command line tool cleanly traps and reports errors for - corrupt input images rather than relying on standard library `assert()` - calls in release builds. -* **Core API:** - * **API Change:** Images using region-based metrics no longer need to include - padding; all input images should be tightly packed and `dim_pad` is removed - from the `astcenc_image` structure. This makes it easier to directly use - images loaded from other libraries. - * **API Change:** Image `data` is no longer a 3D array accessed using - `data[z][y][x]` indexing, it's an array of 2D slices. This makes it easier - to directly use images loaded from other libraries. - * **API Change:** New `ASTCENC_FLG_SELF_DECOMPRESS_ONLY` flag added to the - codec config. Using this flag enables additional optimizations that - aggressively exploit implementation- and configuration-specific, behavior - to gain performance. When using this flag the codec can only reliably - decompress images that were compressed in the same context session. Images - produced via other means may fail to decompress correctly, even if they are - otherwise valid ASTC files. - -### Performance - -There is one major set of optimizations in this release, related to the new -`ASTCENC_FLG_SELF_DECOMPRESS_ONLY` mode. These allow the compressor to only -create data tables it knows that it is going to use, based on its current set -of heuristics, rather than needing the full set the format allows. - -The first benefit of these changes is a reduced context creation time, which -can be reduced by up to 250ms on our test machine. This is a significant -percentage of the command line utility runtime for a small image when using a -quick search preset. Compressing the whole Kodak test suite using the command -line utility and the `-fastest` preset is ~30% faster with this release, which -is mostly due to faster startup. - -The reduction in the data table size in this mode also improve the core codec -speed. Our test sets show an average of 12% improvement in the codec for -`-fastest` mode, and an average of 3% for `-medium` mode. - -Key for performance charts: - -* Color = block size (see legend). -* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). - -**Absolute performance vs 2.1 release:** - -![Absolute scores 2.2 vs 2.1](./ChangeLogImg/absolute-2.1-to-2.2.png) - -**Relative performance vs 2.1 release:** - -![Relative scores 2.2 vs 2.1](./ChangeLogImg/relative-2.1-to-2.2.png) - - - -## 2.1 - -**Status:** Released, November 2020 - -The 2.1 release is the second release in the 2.x series. It includes a number -of performance optimizations and new features. - -Reminder for users of the library interface - the API is not designed to be -stable across versions, and this release is not compatible with 2.0. Please -recompile your client-side code using the updated `astcenc.h` header. - -### Features: - -* **Command line:** - * **Bug fix:** The meaning of the `-tH\cH\dH` and `-th\ch\dh` compression - modes was inverted. They now match the documentation; use `-*H` for HDR - RGBA, and `-*h` for HDR RGB with LDR alpha. - * **Feature:** A new `-fastest` quality preset is now available. This is - designed for fast "roughing out" of new content, and sacrifices significant - image quality compared to `-fast`. We do not recommend its use for - production builds. - * **Feature:** A new `-candidatelimit` compression tuning option is now - available. This is a power-user control to determine how many candidates - are returned for each block mode encoding trial. This feature is used - automatically by the search presets; see `-help` for details. - * **Improvement:** The compression test modes (`-tl\ts\th\tH`) now emit a - MTex/s performance metric, in addition to coding time. -* **Core API:** - * **Feature:** A new quality preset `ASTCENC_PRE_FASTEST` is available. See - `-fastest` above for details. - * **Feature:** A new tuning option `tune_candidate_limit` is available in - the config structure. See `-candidatelimit` above for details. - * **Feature:** Image input/output can now use `ASTCENC_TYPE_F32` data types. -* **Stability:** - * **Feature:** The SSE2, SSE4.2, and AVX2 variants now produce identical - compressed output when run on the same CPU when compiled with the - preprocessor define `ASTCENC_ISA_INVARIANCE=1`. For Make builds this can - be set on the command line by setting `ISA_INV=1`. ISA invariance is off - by default; it reduces performance by 1-3%. - -### Performance - -Key for performance charts: - -* Color = block size (see legend). -* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). - -**Absolute performance vs 2.0 release:** - -![Absolute scores 2.1 vs 2.0](./ChangeLogImg/absolute-2.0-to-2.1.png) - -**Relative performance vs 2.0 release:** - -![Relative scores 2.1 vs 2.0](./ChangeLogImg/relative-2.0-to-2.1.png) - - - -## 2.0 - -**Status:** Released, August 2020 - -The 2.0 release is first release in the 2.x series. It includes a number of -major changes over the earlier 1.7 series, and is not command-line compatible. - -### Features: - -* The core codec can be built as a library, exposed via a new codec API. -* The core codec supports accelerated SIMD paths for SSE2, SSE4.2, and AVX2. -* The command line syntax has a clearer mapping to Khronos feature profiles. - -### Performance: - -Key for performance charts - -* Color = block size (see legend). -* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). - -**Absolute performance vs 1.7 release:** - -![Absolute scores 2.0 vs 1.7](./ChangeLogImg/absolute-1.7-to-2.0.png) - -**Relative performance vs 1.7 release:** - -![Relative scores 2.0 vs 1.7](./ChangeLogImg/relative-1.7-to-2.0.png) - -- - - - -_Copyright © 2020-2022, Arm Limited and contributors. All rights reserved._ diff --git a/Docs/ChangeLog-3x.md b/Docs/ChangeLog-3x.md index 9d2239a..2bb022f 100644 --- a/Docs/ChangeLog-3x.md +++ b/Docs/ChangeLog-3x.md @@ -299,10 +299,6 @@ Key for charts: * Color = block size (see legend). * Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). -**Absolute performance vs 2.5 release:** - -![Absolute scores 3.0 vs 2.5](./ChangeLogImg/absolute-2.5-to-3.0.png) - **Relative performance vs 2.5 release:** ![Relative scores 3.0 vs 2.5](./ChangeLogImg/relative-2.5-to-3.0.png) diff --git a/Docs/ChangeLog-4x.md b/Docs/ChangeLog-4x.md new file mode 100644 index 0000000..4450a49 --- /dev/null +++ b/Docs/ChangeLog-4x.md @@ -0,0 +1,398 @@ +# 4.x series change log + +This page summarizes the major functional and performance changes in each +release of the 4.x series. + +All performance data on this page is measured on an Intel Core i5-9600K +clocked at 4.2 GHz, running `astcenc` using AVX2 and 6 threads. + + +## 4.7.0 + +**Status:** January 2024 + +The 4.7.0 release is a major maintenance release, fixing rounding behavior in +the decompressor to match the Khronos specification. This fix includes the +addition of explicit support for optimizing for `decode_unorm8` rounding. + +Reminder - the codec library API is not designed to be binary compatible across +versions. We always recommend rebuilding your client-side code using the updated +`astcenc.h` header. + +* **General:** + * **Bug fix:** sRGB LDR decompression now uses the correct endpoint expansion + method to create the 16-bit RGB endpoint colors, and removes the previous + correction code from the interpolation function. This bug could result in + LSB bit flips relative to the standard specification. + * **Bug fix:** Decompressing to an 8-bit per component output image now matches + the `decode_unorm8` extension rounding rules. This bug could result in + LSB bit flips relative to the standard specification. + * **Bug fix:** Code now avoids using `alignas()` in the reference C + implementation, as the default `alignas(16)` is narrower than the + native minimum alignment requirement on some CPUs. + * **Feature:** Library configuration supports a new flag, + `ASTCENC_FLG_USE_DECODE_UNORM8`. This flag indicates that the image will be + used with the `decode_unorm8` decode mode. When set during compression + this allows the compressor to use the correct rounding when determining the + best encoding. + * **Feature:** Command line tool supports a new option, `-decode_unorm8`. + This option indicates that the image will be used with the `decode_unorm8` + decode mode. This option will automatically be set for decompression + (`-d*`) and trial (`-t*`) tool operation if the decompressed output image + is stored to an 8-bit per component file format. This option must be set + manually for compression (`-c*`) tool operation, as the desired decode mode + cannot be reliably determined. + * **Feature:** Library configuration supports a new optional progress + reporting callback to be specified. This is called during compression to + to allow interactive tooling use cases to display incremental progress. The + command line tool uses this feature to show compression progress unless + `-silent` is used. + + +## 4.6.1 + +**Status:** November 2023 + +The 4.6.1 release is a minor maintenance release to fix a scaling bug on +large core count Windows systems. + +* **General:** + * **Optimization:** Windows builds of the `astcenc` command line tool can now + use more than 64 cores on large core count systems. This change doubled + command line performance for `-exhaustive` compression when testing on an + 96 core/192 thread system. + * **Feature:** Windows Arm64 native builds of the `astcenc` command line tool + are now included in the prebuilt release binaries. + + +## 4.6.0 + +**Status:** November 2023 + +The 4.6.0 release retunes the compressor heuristics to give improvements to +performance for trivial losses to image quality. It also includes some minor +bug fixes and code quality improvements. + +Reminder - the codec library API is not designed to be binary compatible across +versions. We always recommend rebuilding your client-side code using the updated +`astcenc.h` header. + +* **General:** + * **Bug-fix:** Fixed context allocation for contexts allocated with the + `ASTCENC_FLG_DECOMPRESS_ONLY` flag. + * **Bug-fix:** Reduced use of `reinterpret_cast` in the core codec to + avoid strict aliasing violations. + * **Optimization:** `-medium` search quality no longer tests 4 partition + encodings for block sizes between 25 and 83 texels (inclusive). This + improves performance for a tiny drop in image quality. + * **Optimization:** `-thorough` and higher search qualities no longer test the + mode0 first search for block sizes between 25 and 83 texels (inclusive). + This improves performance for a tiny drop in image quality. + * **Optimization:** `TUNE_MAX_PARTITIONING_CANDIDATES` reduced from 32 to 8 + to reduce the size of stack allocated data structures. This causes a tiny + drop in image quality for the `-verythorough` and `-exhaustive` presets. + + +## 4.5.0 + +**Status:** June 2023 + +The 4.5.0 release is a maintenance release with small image quality +improvements, and a number of build system quality of life improvements. + +* **General:** + * **Bug-fix:** Improved handling compiler arguments in CMake, including + consistent use of MSVC-style command line arguments for ClangCL. + * **Bug-fix:** Invariant Clang builds now use `-ffp-model=precise` with + `-ffp-contract=off` which is needed to restore invariance due to recent + changes in compiler defaults. + * **Change:** macOS binary releases are now distributed as a single universal + binary for all platforms. + * **Change:** Windows binary releases are now compiled with VS2022. + * **Change:** Invariant MSVC builds for VS2022 now use `/fp:precise` instead + of `/fp:strict`, which is is now possible because precise no longer implies + contraction. This should improve performance for MSVC builds. + * **Change:** Non-invariant Clang builds now use `-ffp-model=precise` with + `-ffp-contract=on`. This should improve performance on older Clang + versions which defaulted to no contraction. + * **Change:** Non-invariant MSVC builds for VS2022 now use `/fp:precise` + with `/fp:contract`. This should improve performance for MSVC builds. + * **Change:** CMake config variables now use an `ASTCENC_` prefix to add a + namespace and group options when the library is used in a larger project. + * **Change:** CMake config `ASTCENC_UNIVERSAL_BUILD` for building macOS + universal binaries has been improved to include the `x86_64h` slice for + AVX2 builds. Universal builds are now on by default for macOS, and always + include NEON (arm64), SSE4.1 (x86_64), and AVX2 (x86_64h) variants. + * **Change:** CMake config `ASTCENC_NO_INVARIANCE` has been inverted to + remove the negated option, and is now `ASTCENC_INVARIANCE` with a default + of `ON`. Disabling this option can substantially improve performance, but + images can different across platforms and compilers. + * **Optimization:** Color quantization and packing for LDR RGB and RGBA has + been vectorized to improve performance. + * **Change:** Color quantization for LDR RGB and RGBA endpoints will now try + multiple quantization packing methods, and pick the one with the lowest + endpoint encoding error. This gives a minor image quality improvement, for + no significant performance impact when combined with the vectorization + optimizations. + + +## 4.4.0 + +**Status:** March 2023 + +The 4.4.0 release is a minor release with image quality improvements, a small +performance boost, and a few new quality-of-life features. + +* **General:** + * **Change:** Core library no longer checks availability of required + instruction set extensions, such as SSE4.1 or AVX2. Checking compatibility + is now the responsibility of the caller. See `astcenccli_entry.cpp` for + an example of code performing this check. + * **Change:** Core library can be built as a shared object by setting the + `-DSHAREDLIB=ON` CMake option, resulting in e.g. `libastcenc-avx2-shared.so`. + Note that the command line tool is always statically linked. + * **Change:** Decompressed 3D images will now write one output file per + slice, if the target format is a 2D image format. + * **Change:** Command line errors print to stderr instead of stdout. + * **Change:** Color encoding uses new quantization tables, that now factor + in floating-point rounding if a distance tie is found when using the + integer quant256 value. This improves image quality for 4x4 and 5x5 block + sizes. + * **Optimization:** Partition selection uses a simplified line calculation + with a faster approximation. This improves performance for all block sizes. + * **Bug-fix:** Fixed missing symbol error in decompressor-only builds. + * **Bug-fix:** Fixed infinity handling in debug trace JSON files. + +### Performance: + +Key for charts: + +* Color = block size (see legend). +* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). + +**Relative performance vs 4.3 release:** + +![Relative scores 4.4 vs 4.3](./ChangeLogImg/relative-4.3-to-4.4.png) + + +## 4.3.1 + +**Status:** January 2023 + +The 4.3.1 release is a minor maintenance release. No performance or image +quality changes are expected. + +* **General:** + * **Bug-fix:** Fixed typo in `-2/3/4partitioncandidatelimit` CLI options. + * **Bug-fix:** Fixed handling for `-3/4partitionindexlimit` CLI options. + * **Bug-fix:** Updated to `stb_image.h` v2.28, which includes multiple fixes + and improvements for image loading. + + +## 4.3.0 + +**Status:** January 2023 + +The 4.3.0 release is an optimization release. There are minor performance +and image quality improvements in this release. + +Reminder - the codec library API is not designed to be binary compatible across +versions. We always recommend rebuilding your client-side code using the updated +`astcenc.h` header. + +* **General:** + * **Bug-fix:** Use lower case `windows.h` include for MinGW compatibility. + * **Change:** The `-mask` command line option, `ASTCENC_FLG_MAP_MASK` in the + library API, has been removed. + * **Optimization:** Always skip blue-contraction for `QUANT_256` encodings. + This gives a small image quality improvement for the 4x4 block size. + * **Optimization:** Always skip RGBO vector calculation for LDR encodings. + * **Optimization:** Defer color packing and scrambling to physical layer. + * **Optimization:** Remove folded `decimation_info` lookup tables. This + significantly reduces compressor memory footprint and improves context + creation time. Impact increases with the active block size. + * **Optimization:** Increased trial and refinement pruning by using stricter + target errors when determining whether to skip iterations. + +### Performance: + +Key for charts: + +* Color = block size (see legend). +* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). + +**Relative performance vs 4.2 release:** + +![Relative scores 4.3 vs 4.2](./ChangeLogImg/relative-4.2-to-4.3.png) + + + +## 4.2.0 + +**Status:** November 2022 + +The 4.2.0 release is an optimization release. There are significant performance +improvements, minor image quality improvements, and library interface changes in +this release. + +Reminder - the codec library API is not designed to be binary compatible across +versions. We always recommend rebuilding your client-side code using the updated +`astcenc.h` header. + +* **General:** + * **Bug-fix:** Compression for RGB and RGBA base+offset encodings no + longer generate endpoints with the incorrect blue-contract behavior. + * **Bug-fix:** Lowest channel correlation calculation now correctly ignores + constant color channels for the purposes of filtering 2 plane encodings. + On average this improves both performance and image quality. + * **Bug-fix:** ISA compatibility now checked in `config_init()` as well as + in `context_alloc()`. + * **Change:** Removed the low-weight count optimization, as more recent + changes had significantly reduced its performance benefit. Option removed + from both command line and configuration structure. + * **Feature:** The `-exhaustive` mode now runs full trials on more + partitioning candidates and block candidates. This improves image quality + by 0.1 to 0.25 dB, but slows down compression by 3x. The `-verythorough` + and `-thorough` modes also test more candidates. + * **Feature:** A new preset, `-verythorough`, has been introduced to provide + a standard performance point between `-thorough` and the re-tuned + `-exhaustive` mode. This new mode is faster and higher quality than the + `-exhaustive` preset in the 4.1 release. + * **Feature:** The compressor can now independently vary the number of + partitionings considered for error estimation for 2/3/4 partitions. This + allows heuristics to put more effort into 2 partitions, and less in to + 3/4 partitions. + * **Feature:** The compressor can now run trials on a variable number of + candidate partitionings, allowing high quality modes to explore more of the + search space at the expense of slower compression. The number of trials is + independently configurable for 2/3/4 partition cases. + * **Optimization:** Introduce early-out threshold for 2/3/4 partition + searches based on the results after 1 of 2 trials. This significantly + improves performance for `-medium` and `-thorough` searches, for a minor + loss in image quality. + * **Optimization:** Reduce early-out threshold for 3/4 partition searches + based on 2/3 partition results. This significantly improves performance, + especially for `-thorough` searches, for a minor loss in image quality. + * **Optimization:** Use direct vector compare to create a SIMD mask instead + of a scalar compare that is broadcast to a vector mask. + * **Optimization:** Remove obsolete partition validity masks from the + partition selection algorithm. + * **Optimization:** Removed obsolete channel scaling from partition + `avgs_and_dirs()` calculation. + +### Performance: + +Key for charts: + +* Color = block size (see legend). +* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). + +**Relative performance vs 4.0 and 4.1 release:** + +![Relative scores 4.2 vs 4.0](./ChangeLogImg/relative-4.0-to-4.2.png) + + + +## 4.1.0 + +**Status:** August 2022 + +The 4.1.0 release is a maintenance release. There is no performance or image +quality change in this release. + +* **General:** + * **Change:** Command line decompressor no longer uses the legacy + `GL_LUMINANCE` or `GL_LUMINANCE_ALPHA` format enums when writing KTX + output files. Luminance textures now use the `GL_RED` format and + luminance_alpha textures now use the `GL_RG` format. + * **Change:** Command line tool gains a new `-dimage` option to generate + diagnostic images showing aspects of the compression encoding. The output + file name with its extension stripped is used as the stem of the diagnostic + image file names. + * **Bug-fix:** Library decompressor builds for SSE no longer use masked store + `maskmovdqu` instructions, as they can generate faults on masked lanes. + * **Bug-fix:** Command line decompressor now correctly uses sized type enums + for the internal format when writing output KTX files. + * **Bug-fix:** Command line compressor now correctly loads 16 and 32-bit per + component input KTX files. + * **Bug-fix:** Fixed GCC9 compiler warnings on Arm aarch64. + + +## 4.0.0 + +**Status:** July 2022 + +The 4.0.0 release introduces some major performance enhancement, and a number +of larger changes to the heuristics used in the codec to find a more effective +cost:quality trade off. + +* **General:** + * **Change:** The `-array` option for specifying the number of image planes + for ASTC 3D volumetric block compression been renamed to `-zdim`. + * **Change:** The build root package directory is now `bin` instead of + `astcenc`, allowing the CMake install step to write binaries into + `/usr/local/bin` if the user wishes to do so. + * **Feature:** A new `-ssw` option for specifying the shader sampling swizzle + has been added as convenience alternative to the `-cw` option. This is + needed to correct error weighting during compression if not all components + are read in the shader. For example, to extract and compress two components + from an RGBA input image, weighting the two components equally when + sampling through .ra in the shader, use `-esw ggga -ssw ra`. In this + example `-ssw ra` is equivalent to the alternative `-cw 1 0 0 1` encoding. + * **Feature:** The `-a` alpha weighting option has been re-enabled in the + backend, and now again applies alpha scaling to the RGB error metrics when + encoding. This is based on the maximum alpha in each block, not the + individual texel alpha values used in the earlier implementation. + * **Feature:** The command line tool now has `-repeats ` for testing, + which will iterate around compression and decompression `count` times. + Reported performance metrics also now separate compression and + decompression scores. + * **Feature:** The core codec is now warning clean up to /W4 for both MSVC + `cl.exe` and `clangcl.exe` compilers. + * **Feature:** The core codec now supports arm64 for both MSVC `cl.exe` and + `clangcl.exe` compilers. + * **Feature:** `NO_INVARIANCE` builds will enable the `-ffp-contract=fast` + option for all targets when using Clang or GCC. In addition AVX2 targets + will also set the `-mfma` option. This reduces image quality by up to 0.2dB + (normally much less), but improves performance by up to 5-20%. + * **Optimization:** Angular endpoint min/max weight selection is restricted + to weight `QUANT_11` or lower. Higher quantization levels assume default + 0-1 range, which is less accurate but much faster. + * **Optimization:** Maximum weight quantization for later trials is selected + based on the weight quantization of the best encoding from the 1 plane 1 + partition trial. This significantly reduces the search space for the later + trials with more planes or partitions. + * **Optimization:** Small data tables now use in-register SIMD permutes + rather than gathers (AVX2) or unrolled scalar lookups (SSE/NEON). This can + be a significant optimization for paths that are load unit limited. + * **Optimization:** Decompressed image block writes in the decompressor now + use a vectorized approach to writing each row of texels in the block, + including to ability to exploit masked stores if the target supports them. + * **Optimization:** Weight scrambling has been moved into the physical layer; + the rest of the codec now uses linear order weights. + * **Optimization:** Weight packing has been moved into the physical layer; + the rest of the codec now uses unpacked weights in the 0-64 range. + * **Optimization:** Consistently vectorize the creation of unquantized weight + grids when they are needed. + * **Optimization:** Remove redundant per-decimation mode copies of endpoint + and weight structures, which were really read-only duplicates. + * **Optimization:** Early-out the same endpoint mode color calculation if it + cannot be applied. + * **Optimization:** Numerous type size reductions applied to arrays to reduce + both context working buffer size usage and stack usage. + +### Performance: + +Key for charts: + +* Color = block size (see legend). +* Letter = image format (N = normal map, G = grayscale, L = LDR, H = HDR). + +**Relative performance vs 3.7 release:** + +![Relative scores 4.0 vs 3.7](./ChangeLogImg/relative-3.7-to-4.0.png) + + +- - - + +_Copyright © 2022-2024, Arm Limited and contributors. All rights reserved._ diff --git a/Docs/ChangeLogImg/absolute-1.7-to-2.0.png b/Docs/ChangeLogImg/absolute-1.7-to-2.0.png deleted file mode 100644 index 9458f715b09347de711d737aebbe5a082501e4b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114044 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 diff --git a/Docs/ChangeLogImg/absolute-2.0-to-2.1.png b/Docs/ChangeLogImg/absolute-2.0-to-2.1.png deleted file mode 100644 index 6e943e4e4b29bcbd6567ef1e9639830ade59525a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151755 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 diff --git a/Docs/ChangeLogImg/absolute-2.1-to-2.2.png b/Docs/ChangeLogImg/absolute-2.1-to-2.2.png deleted file mode 100644 index c5067b45b4508352c3855c4de9d2711dcf22ba95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144084 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%0A}Hh=uX&dG-3CYtjKIvVgYU+JBUA3{@x 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 EFCHw<{Qv*} diff --git a/Docs/ChangeLogImg/absolute-2.2-to-2.3.png b/Docs/ChangeLogImg/absolute-2.2-to-2.3.png deleted file mode 100644 index c507896cb27cde330e4bc5448798744f9e5a9f9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 152303 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

eG0tfs2Qb*KEc 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 diff --git a/Docs/ChangeLogImg/relative-2.1-to-2.2.png b/Docs/ChangeLogImg/relative-2.1-to-2.2.png deleted file mode 100644 index 428db0e34c44b6e7e9ce0477231c891182e81602..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122512 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 diff --git a/Docs/ChangeLogImg/relative-3.7-to-4.0.png b/Docs/ChangeLogImg/relative-3.7-to-4.0.png new file mode 100644 index 0000000000000000000000000000000000000000..2c373b00ab049f7b24394becc1265c9c6e097fb0 GIT binary patch literal 123644 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 z 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

Y&O=7-uH&A!(K6b{+@f-@DMUO2Rc0Mw~x1iI5- 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 NCB=h#@5`I|{C`A_U{e49 literal 0 HcmV?d00001 diff --git a/Docs/ChangeLogImg/relative-4.0-to-4.2.png b/Docs/ChangeLogImg/relative-4.0-to-4.2.png new file mode 100644 index 0000000000000000000000000000000000000000..b65dbf4bb7afbef691047a27ebdf4f3faccf4330 GIT binary patch literal 129092 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ℑYDc|zS4^!m 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 z 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 Q%pzUkRrp;@W~V_C%>tH3_hL+;s5@4LT{;q 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 literal 0 HcmV?d00001 diff --git a/Docs/ChangeLogImg/relative-4.2-to-4.3.png b/Docs/ChangeLogImg/relative-4.2-to-4.3.png new file mode 100644 index 0000000000000000000000000000000000000000..ee6db037171fc2a68b48c19f9ac40adc3072816e GIT binary patch literal 118479 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 Z{Qd?}>5#Gwr4;xaQ&dq%K4^IT{{Yf7FLnR` literal 0 HcmV?d00001 diff --git a/Docs/ChangeLogImg/relative-4.3-to-4.4.png b/Docs/ChangeLogImg/relative-4.3-to-4.4.png new file mode 100644 index 0000000000000000000000000000000000000000..7dde3ddf380001e5a976f74fdf0f8cab2db0d96c GIT binary patch literal 110253 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 p?1 | | 2 | L + A | `rrrg` | `.ga` 1 | @@ -88,13 +88,13 @@ swizzling is specified by the application. **1:** Sampling from `g` is preferred to sampling from `r` because it allows a single shader to be compatible with ASTC, BC1, or ETC formats. BC1 and ETC1 -store color endpoints as RGB565 data, so the `g` channel will have higher +store color endpoints as RGB565 data, so the `g` component will have higher precision. For ASTC it doesn't actually make any difference; the same single -channel luminance will be returned for all three of the `.rgb` channels. +component luminance will be returned for all three of the `.rgb` components. ## Equivalence with other formats -Based on these channel encoding requirements we can now derive the the ASTC +Based on these component encoding requirements we can now derive the the ASTC coding equivalents for most of the other texture compression formats in common use today. @@ -105,7 +105,7 @@ use today. | BC3nm | `gggr` | `.ag` | | | BC4 | `rrr1` | `.r` | | | BC5 | `rrrg` | `.ra` 2 | | -| BC6 | `rgb1` | `.rgb` | HDR profile only | +| BC6H | `rgb1` | `.rgb` 3 | HDR profile only | | BC7 | `rgba` | `.rgba` | | | EAC_R11 | `rrr1` | `.r` | | | EAC_RG11 | `rrrg` | `.ra` 2 | | @@ -115,38 +115,66 @@ use today. | ETC2+EAC | `rgba` | `.rgba` | | **1:** ASTC has no equivalent of the 1-bit punch-through alpha encoding -supported by BC1 or ETC2; if alpha is present it will be a full alpha channel. +supported by BC1 or ETC2; if alpha is present it will be a full alpha +component. **2:** ASTC relies on using the L+A color endpoint type for coding efficiency -for two channel data. It therefore has no direct equivalent of a two-plane -format sampled though the `.rg` channels such as BC5 or EAC_RG11. This can -be emulated by setting texture channel swizzles in the runtime API - e.g. via +for two component data. It therefore has no direct equivalent of a two-plane +format sampled though the `.rg` components such as BC5 or EAC_RG11. This can +be emulated by setting texture component swizzles in the runtime API - e.g. via `glTexParameteri()` for OpenGL ES - although it has been noted that API controlled swizzles are not available in WebGL. +**3:** ASTC can only store unsigned values, and has no equivalent of the BC6 +signed endpoint mode. + # Other Considerations This section outlines some of the other things to consider when encoding textures using ASTC. -## Encoding non-correlated channels +## Decode mode extensions + +ASTC is specified to decompress into a 16-bit per component RGBA output by +default, with the exception of the sRGB format which uses an 8-bit value for the +RGB components. + +Decompressing in to a 16-bit per component output format is often higher than +many use cases require, especially for LDR textures which originally came from +an 8-bit per component source image. Most implementations of ASTC support the +decode mode extensions, which allow an application to opt-in to a lower +precision decompressed format (RGBA8 for LDR, RGB9E5 for HDR). Using these +extensions can improve GPU texture cache efficiency, and even improve texturing +filtering throughput, for use cases that do not need the higher precision. + +The ASTC format uses different data rounding rules when the decode mode +extensions are used. To ensure that the compressor chooses the best encodings +for the RGBA8 rounding rules, you can specify `-decode_unorm8` when compressing +textures that will be decompressed into the RGBA8 intermediate. This gives a +small image quality boost. -Most other texture compression formats have a static channel assignment in +**Note:** This mode is automatically enabled if you use the `astcenc` +decompressor to write an 8-bit per component output image. + +## Encoding non-correlated components + +Most other texture compression formats have a static component assignment in terms of the expected data correlation. For example, ETC2+EAC assumes that RGB are always correlated and that alpha is non-correlated. ASTC can automatically -encode data as either fully correlated across all 4 channels, or with any one -channel assigned to a separate non-correlated partition to the other three. +encode data as either fully correlated across all 4 components, or with any one +component assigned to a separate non-correlated partition to the other three. -The non-correlated channel can be changed on a block-by-block basis, so the +The non-correlated component can be changed on a block-by-block basis, so the compressor can dynamically adjust the coding based on the data present in the image. This means that there is no need for non-correlated data to be stored -in a specific channel in the input image. +in a specific component in the input image. -It is however worth noting that the alpha channel is treated differently to -the RGB color channels in some circumstances: +It is however worth noting that the alpha component is treated differently to +the RGB color components in some circumstances: -* When coding for sRGB the alpha channel will always be stored in linear space. -* When coding for HDR the alpha channel can optionally be kept as LDR data. +* When coding for sRGB the alpha component will always be stored in linear + space. +* When coding for HDR the alpha component can optionally be kept as LDR data. ## Encoding normal maps @@ -155,21 +183,21 @@ BC5; store the X and Y components of a unit-length normal. The Z component of the normal can be reconstructed in shader code based on the knowledge that the vector is unit length. -To encode this we therefore want to store two input channels and should -therefore use the `rrrg` coding swizzle, and the `.ga` sampling swizzle. The -OpenGL ES shader code for reconstruction of the Z value is: +To encode this we need to store only two input components in the compressed +data, and therefore use the `rrrg` coding swizzle to align the data with the +ASTC luminance+alpha endpoint. We can sample this in shader code using the +`.ga` sampling swizzle, and reconstruct the Z value with: vec3 nml; nml.xy = texture(...).ga; // Load normals (range 0 to 1) nml.xy = nml.xy * 2.0 - 1.0; // Unpack normals (range -1 to +1) nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z, given unit length -In addition to this it is useful to optimize for angular error in the resulting -vector rather than for absolute color error in the data, which improves the -perceptual quality of the image. - -Both the encoding swizzle and the angular error function are enabled by using -the `-normal` command line option. +The encoding swizzle and appropriate component weighting is enabled by using +the `-normal` command line option. If you wish to use a different pair of +components you can specify a custom swizzle after setting the `-normal` +parameter. For example, to match BC5n component ordering use +`-normal -esw gggr` for compression and `-normal -dsw arz1` for decompression. ## Encoding sRGB data @@ -182,8 +210,8 @@ For color data it is nearly always a perceptual quality win to use sRGB input source textures that are then compressed using the ASTC sRGB compression mode (compress using the `-cs` command line option rather than the `-cl` command line option). Note that sRGB gamma correction is only applied to the RGB -channels during decode; the alpha channel is always treated as linear encoded -data. +components during decode; the alpha component is always treated as linear +encoded data. *Important:* The uncompressed input texture provided on the command line must be stored in the sRGB color space for `-cs` to function correctly. @@ -191,17 +219,17 @@ be stored in the sRGB color space for `-cs` to function correctly. ## Encoding HDR data HDR data can be encoded just like LDR data, but with some caveats around -handling the alpha channel. +handling the alpha component. -For many use cases the alpha channel is an actual alpha opacity channel and is -therefore used for storing an LDR value between 0 and 1. For these cases use -the `-ch` compressor option which will treat the RGB channels as HDR, but the -A channel as LDR. +For many use cases the alpha component is an actual alpha opacity component and +is therefore used for storing an LDR value between 0 and 1. For these cases use +the `-ch` compressor option which will treat the RGB components as HDR, but the +A component as LDR. -For other use cases the alpha channel is simply a fourth data channel which is -also storing an HDR value. For these cases use the `-cH` compressor option -which will treat all channels as HDR data. +For other use cases the alpha component is simply a fourth data component which +is also storing an HDR value. For these cases use the `-cH` compressor option +which will treat all components as HDR data. - - - -_Copyright © 2019-2022, Arm Limited and contributors. All rights reserved._ +_Copyright © 2019-2024, Arm Limited and contributors. All rights reserved._ diff --git a/Docs/Testing.md b/Docs/Testing.md index 2cef276..da197fc 100644 --- a/Docs/Testing.md +++ b/Docs/Testing.md @@ -20,8 +20,8 @@ We support a small (but growing) number of C++ unit tests, which are written using the `googletest` framework and integrated in the CMake "CTest" test framework. -To build unit tests pull the `googletest` git submodule and add `-DUNITTEST=ON` -to the CMake command line when configuring. +To build unit tests pull the `googletest` git submodule and add +`-DASTCENC_UNITTEST=ON` to the CMake command line when configuring. To run unit tests use the CMake `ctest` utility from your build directory after you have built the tests. diff --git a/README.OpenSource b/README.OpenSource index f16f25e..66f0d64 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name":"astc-encoder", "License":"Apache 2.0 License", "License File":"LICENSE", - "Version Number":"3.7", + "Version Number":"4.7", "Owner":"wangyonglang@huawei.com", "Upstream URL":"https://github.com/ARM-software/astc-encoder.git", "Description":"The Arm Adaptive Scalable Texture Compression (ASTC) Encoder,astcenc,is a command-line tool for compressing and decompressing images using the ASTC texture compression standard." diff --git a/README.md b/README.md index 1566473..ce23b02 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # About -This is the official repository for the Arm® Adaptive Scalable Texture -Compression (ASTC) Encoder, `astcenc`, a command-line tool for compressing -and decompressing images using the ASTC texture compression standard. +The Arm® Adaptive Scalable Texture Compression (ASTC) Encoder, `astcenc`, is +a command-line tool for compressing and decompressing images using the ASTC +texture compression standard. ## The ASTC format The ASTC compressed data format, developed by Arm® and AMD, has been adopted as -an official extension to the Open GL®, OpenGL ES, and Vulkan® graphics APIs. It +an official extension to the OpenGL®, OpenGL ES, and Vulkan® graphics APIs. It provides a major step forward in terms of both the image quality at a given bitrate, and the format and bitrate flexibility available to content creators. This allows more assets to use compression, often at a reduced bitrate compared @@ -20,7 +20,7 @@ read the full [Khronos Data Format Specification][2] for all the details. This project is licensed under the Apache 2.0 license. By downloading any component from this repository you acknowledge that you accept terms specified -in the [LICENSE](LICENSE) file. +in the [LICENSE.txt](LICENSE.txt) file. # Encoder feature support @@ -33,8 +33,8 @@ dynamic range (BMP, PNG, TGA), high dynamic range (EXR, HDR), or DDS and KTX wrapped output images. The encoder allows control over the compression time/quality tradeoff with -`exhaustive`, `thorough`, `medium`, `fast`, and `fastest` encoding quality -presets. +`exhaustive`, `verythorough`, `thorough`, `medium`, `fast`, and `fastest` +encoding quality presets. The encoder allows compression time and quality analysis by reporting the compression time, and the Peak Signal-to-Noise Ratio (PSNR) between the input @@ -58,15 +58,15 @@ from 0.89 bits/pixel up to 8 bits/pixel. Release build binaries for the `astcenc` stable releases are provided in the [GitHub Releases page][3]. -**Latest 3.x stable release:** 3.7 +* Change log: [4.x series](./Docs/ChangeLog-4x.md) * Change log: [3.x series](./Docs/ChangeLog-3x.md) -**Latest 2.x stable release:** 2.5 -* Change log: [2.x series](./Docs/ChangeLog-2x.md) +Binaries are provided for 64-bit builds on Windows, macOS, and Linux. -Binaries are provided for 64-bit builds on Windows, macOS, and Linux. The -builds of the astcenc are provided as multiple binaries, each tuned for a -specific SIMD instruction set. +## Windows and Linux + +For Windows and Linux the builds of the astcenc are provided as multiple +binaries, each tuned for a specific SIMD instruction set. For x86-64 we provide, in order of increasing performance: @@ -78,23 +78,33 @@ The x86-64 SSE2 builds will work on all x86-64 machines, but it is the slowest of the three. The other two require extended CPU instruction set support which is not universally available, but each step gains ~15% more performance. -For Apple silicon macOS devices we provide: +For Arm, if binaries are available, we provide: * `astcenc-neon` - uses NEON +## macOS + +For macOS devices we provide a single universal binary `astcenc`, which allows +the OS to automatically use the correct binary variant for the current host +machine. Support is provided for three architecture slices: + +* `x86_64` - uses the `astcenc-sse4.1` build defined above. +* `x86_64h` - uses the `astcenc-avx2` build defined above. +* `arm64` - uses the `astcenc-neon` build defined above. ## Repository branches The `main` branch is an active development branch for the compressor. It aims -to be a stable branch, but as it is used for ongoing development expect it to -have some volatility. +to be a stable branch for the latest major release series, but as it is used +for ongoing development expect it to have some volatility. We recommend using +the latest stable release tag for production development. -The `2.x` branch is a stable branch for the 2.x release series. It is no longer -under active development, but is a supported branch that will continue to get +The `3.x` branch is a stable branch for the 3.x release series. It is no longer +under active development, but is a supported branch that continues to get backported bug fixes. -The `1.x` branch is a stable branch for the 1.x release series. It is no longer -under active development or getting bug fixes. +The `1.x` and `2.x` branches are stable branches for older releases. They are +no longer under active development or getting bug fixes. Any other branches you might find are development branches for new features or optimizations, so might be interesting to play with but should be considered @@ -135,6 +145,11 @@ The modes available are: * `-ch` : use the HDR color profile, tuned for HDR RGB and LDR A. * `-cH` : use the HDR color profile, tuned for HDR RGBA. +If you intend to use the resulting image with the decode mode extensions to +limit the decompressed precision to UNORM8, it is recommended that you also +specify the `-decode_unorm8` flag. This will ensure that the compressor uses +the correct rounding rules when choosing encodings. + ## Decompressing an image Decompress an image using the `-dl` \ `-ds` \ `-dh` \ `-dH` modes. For example: @@ -180,11 +195,6 @@ The compression speed can be controlled from `-fastest`, through `-fast`, encoder has to spend looking for good encodings the better the results, but it does result in increasingly small improvements for the amount of time required. -:warning: The `-fastest` quality preset is designed for quickly roughing-out -new content. It is tuned to give the fastest possible compression, often at the -expense of significant image quality loss compared to `-fast`. We do not -recommend using it for production builds. - There are many other command line options for tuning the encoder parameters which can be used to fine tune the compression algorithm. See the command line help message for more details. @@ -203,6 +213,9 @@ It covers: * How to efficiently encode normal maps, sRGB data, and HDR data. * Coding equivalents to other compression formats. +The [ASTC Developer Guide][5] document (external link) provides a more detailed +guide for developers using the `astcenc` compressor. + The [.astc File Format](./Docs/FileFormat.md) page provides a light-weight specification for the `.astc` file format and how to read or write it. @@ -217,10 +230,16 @@ how to test any modifications to the source code in this repository. If you have issues with the `astcenc` encoder, or questions about the ASTC texture format itself, please raise them in the GitHub issue tracker. +If you have any questions about Arm GPUs, application development for Arm GPUs, +or general mobile graphics development or technology please submit them on the +[Arm Community graphics forums][4]. + - - - -_Copyright © 2013-2022, Arm Limited and contributors. All rights reserved._ +_Copyright © 2013-2024, Arm Limited and contributors. All rights reserved._ [1]: ./Docs/FormatOverview.md [2]: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#ASTC [3]: https://github.com/ARM-software/astc-encoder/releases +[4]: https://community.arm.com/support-forums/f/graphics-gaming-and-vr-forum/ +[5]: https://developer.arm.com/documentation/102162/latest/?lang=en diff --git a/README_zh.md b/README_zh.md index 3767345..f5d1a5b 100644 --- a/README_zh.md +++ b/README_zh.md @@ -41,7 +41,7 @@ astc-encoder引入openharmony的thirdparty目录下, ``` ./build.sh --product-name rk3568 --ccache ``` -编译生成物对应路径:`out/rk3568/thirdparty/astc-encoder/libastc_encoder_shared.so`。 +编译生成物对应路径:`out/rk3568/thirdparty/astc-encoder/libastc_encoder_shared.z.so`。 ## 许可证 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a90fa27..4acbc95 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ---------------------------------------------------------------------------- -# Copyright 2020-2021 Arm Limited +# Copyright 2020-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -17,45 +17,80 @@ # Overwrite the LTO flags to force fat LTO; worth 3-4% performance # See https://gitlab.kitware.com/cmake/cmake/-/issues/16808 -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND ${CLI}) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND ${ASTCENC_CLI}) set(CMAKE_CXX_COMPILE_OPTIONS_IPO "-flto") endif() -if(${DECOMPRESSOR}) - set(CODEC dec) +if(${ASTCENC_DECOMPRESSOR}) + set(ASTCENC_CODEC dec) else() - set(CODEC enc) + set(ASTCENC_CODEC enc) endif() -if(${UNIVERSAL_BUILD}) - if(${ISA_AVX2}) - set(ISA_SIMD "avx2") - elseif(${ISA_SSE41}) - set(ISA_SIMD "sse4.1") - elseif(${ISA_SSE2}) - set(ISA_SIMD "sse2") - endif() - include(cmake_core.cmake) -else() - set(ARTEFACTS native none neon avx2 sse4.1 sse2) - set(CONFIGS ${ISA_NATIVE} ${ISA_NONE} ${ISA_NEON} ${ISA_AVX2} ${ISA_SSE41} ${ISA_SSE2}) - list(LENGTH ARTEFACTS ARTEFACTS_LEN) - math(EXPR ARTEFACTS_LEN "${ARTEFACTS_LEN} - 1") - - foreach(INDEX RANGE ${ARTEFACTS_LEN}) - list(GET ARTEFACTS ${INDEX} ARTEFACT) - list(GET CONFIGS ${INDEX} CONFIG) - if(${CONFIG}) - set(ISA_SIMD ${ARTEFACT}) - include(cmake_core.cmake) +set(ASTCENC_ARTIFACTS native none neon avx2 sse4.1 sse2) +set(ASTCENC_CONFIGS ${ASTCENC_ISA_NATIVE} ${ASTCENC_ISA_NONE} ${ASTCENC_ISA_NEON} ${ASTCENC_ISA_AVX2} ${ASTCENC_ISA_SSE41} ${ASTCENC_ISA_SSE2}) +list(LENGTH ASTCENC_ARTIFACTS ASTCENC_ARTIFACTS_LEN) +math(EXPR ASTCENC_ARTIFACTS_LEN "${ASTCENC_ARTIFACTS_LEN} - 1") + +foreach(INDEX RANGE ${ASTCENC_ARTIFACTS_LEN}) + list(GET ASTCENC_ARTIFACTS ${INDEX} ASTCENC_ARTIFACT) + list(GET ASTCENC_CONFIGS ${INDEX} ASTCENC_CONFIG) + if(${ASTCENC_CONFIG}) + set(ASTCENC_ISA_SIMD ${ASTCENC_ARTIFACT}) + + if(${ASTCENC_ISA_SIMD} MATCHES "neon") + set(CMAKE_OSX_ARCHITECTURES arm64) + elseif(${ASTCENC_ISA_SIMD} MATCHES "avx2") + set(CMAKE_OSX_ARCHITECTURES x86_64h) + elseif(NOT ${ASTCENC_ISA_SIMD} MATCHES "none") + set(CMAKE_OSX_ARCHITECTURES x86_64) endif() - endforeach() + + include(cmake_core.cmake) + endif() +endforeach() + +if(${ASTCENC_CLI} AND ${ASTCENC_UNIVERSAL_BUILD}) + add_custom_target( + astc${ASTCENC_CODEC} + ALL + COMMAND + lipo -create -output $/astc${ASTCENC_CODEC} -arch x86_64 $ -arch x86_64h $ -arch arm64 $ + VERBATIM) + + add_dependencies( + astc${ASTCENC_CODEC} + astc${ASTCENC_CODEC}-sse4.1 + astc${ASTCENC_CODEC}-avx2 + astc${ASTCENC_CODEC}-neon) + + install(PROGRAMS $/astc${ASTCENC_CODEC} + DESTINATION bin) +endif() + +if(${ASTCENC_SHAREDLIB} AND ${ASTCENC_UNIVERSAL_BUILD}) + add_custom_target( + astc${ASTCENC_CODEC}-shared + ALL + COMMAND + lipo -create -output $/libastc${ASTCENC_CODEC}-shared.dylib -arch x86_64 $ -arch x86_64h $ -arch arm64 $ + VERBATIM) + + add_dependencies( + astc${ASTCENC_CODEC}-shared + astc${ASTCENC_CODEC}-sse4.1-shared + astc${ASTCENC_CODEC}-avx2-shared + astc${ASTCENC_CODEC}-neon-shared) + + install(PROGRAMS $/libastc${ASTCENC_CODEC}-shared.dylib + DESTINATION lib) endif() # - - - - - - - - - - - - - - - - - - # Unit testing -if(${UNITTEST}) +if(${ASTCENC_UNITTEST}) set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) + set(CMAKE_OSX_ARCHITECTURES x86_64;arm64) add_subdirectory(GoogleTest) enable_testing() add_subdirectory(UnitTest) diff --git a/Source/Fuzzers/fuzz_astc_physical_to_symbolic.cpp b/Source/Fuzzers/fuzz_astc_physical_to_symbolic.cpp index 67ef24b..e387108 100644 --- a/Source/Fuzzers/fuzz_astc_physical_to_symbolic.cpp +++ b/Source/Fuzzers/fuzz_astc_physical_to_symbolic.cpp @@ -94,9 +94,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) int i = stream.ConsumeIntegralInRange(0, testSz.size() - 1); // Populate the physical block - physical_compressed_block pcb; + uint8_t pcb[16]; std::vector buffer = stream.ConsumeBytes(16); - std::memcpy(&pcb, buffer.data(), 16); + std::memcpy(pcb, buffer.data(), 16); // Call the function under test symbolic_compressed_block scb; diff --git a/Source/UnitTest/CMakeLists.txt b/Source/UnitTest/CMakeLists.txt index e1e2d0b..a65dc47 100644 --- a/Source/UnitTest/CMakeLists.txt +++ b/Source/UnitTest/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ---------------------------------------------------------------------------- -# Copyright 2020-2021 Arm Limited +# Copyright 2020-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -15,27 +15,25 @@ # under the License. # ---------------------------------------------------------------------------- -if(${UNIVERSAL_BUILD}) - if(${ISA_AVX2}) - set(ISA_SIMD "avx2") - elseif(${ISA_SSE41}) - set(ISA_SIMD "sse4.1") - elseif(${ISA_SSE2}) - set(ISA_SIMD "sse2") - endif() - include(cmake_core.cmake) -else() - set(ARTEFACTS native none neon avx2 sse4.1 sse2) - set(CONFIGS ${ISA_NATIVE} ${ISA_NONE} ${ISA_NEON} ${ISA_AVX2} ${ISA_SSE41} ${ISA_SSE2}) - list(LENGTH ARTEFACTS ARTEFACTS_LEN) - math(EXPR ARTEFACTS_LEN "${ARTEFACTS_LEN} - 1") +set(ASTCENC_ARTIFACTS native none neon avx2 sse4.1 sse2) +set(ASTCENC_CONFIGS ${ASTCENC_ISA_NATIVE} ${ASTCENC_ISA_NONE} ${ASTCENC_ISA_NEON} ${ASTCENC_ISA_AVX2} ${ASTCENC_ISA_SSE41} ${ASTCENC_ISA_SSE2}) +list(LENGTH ASTCENC_ARTIFACTS ASTCENC_ARTIFACTS_LEN) +math(EXPR ASTCENC_ARTIFACTS_LEN "${ASTCENC_ARTIFACTS_LEN} - 1") + +foreach(INDEX RANGE ${ASTCENC_ARTIFACTS_LEN}) + list(GET ASTCENC_ARTIFACTS ${INDEX} ASTCENC_ARTIFACT) + list(GET ASTCENC_CONFIGS ${INDEX} ASTCENC_CONFIG) + if(${ASTCENC_CONFIG}) + set(ASTCENC_ISA_SIMD ${ASTCENC_ARTIFACT}) - foreach(INDEX RANGE ${ARTEFACTS_LEN}) - list(GET ARTEFACTS ${INDEX} ARTEFACT) - list(GET CONFIGS ${INDEX} CONFIG) - if(${CONFIG}) - set(ISA_SIMD ${ARTEFACT}) - include(cmake_core.cmake) + if(${ASTCENC_ISA_SIMD} MATCHES "neon") + set(CMAKE_OSX_ARCHITECTURES arm64) + elseif(${ASTCENC_ISA_SIMD} MATCHES "avx2") + set(CMAKE_OSX_ARCHITECTURES x86_64h) + elseif(NOT ${ASTCENC_ISA_SIMD} MATCHES "none") + set(CMAKE_OSX_ARCHITECTURES x86_64) endif() - endforeach() -endif() + + include(cmake_core.cmake) + endif() +endforeach() diff --git a/Source/UnitTest/cmake_core.cmake b/Source/UnitTest/cmake_core.cmake index 656f352..2fb7a4d 100644 --- a/Source/UnitTest/cmake_core.cmake +++ b/Source/UnitTest/cmake_core.cmake @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ---------------------------------------------------------------------------- -# Copyright 2020-2021 Arm Limited +# Copyright 2020-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -15,25 +15,34 @@ # under the License. # ---------------------------------------------------------------------------- -if(${UNIVERSAL_BUILD}) - set(ASTC_TEST test-unit) -else() - set(ASTC_TEST test-unit-${ISA_SIMD}) -endif() +set(ASTCENC_TEST test-unit-${ASTCENC_ISA_SIMD}) + +add_executable(${ASTCENC_TEST}) -add_executable(${ASTC_TEST}) +# Enable LTO under the conditions where the codec library will use LTO. +# The library link will fail if the settings don't match +if(${ASTCENC_CLI}) + set_property(TARGET ${ASTCENC_TEST} + PROPERTY + INTERPROCEDURAL_OPTIMIZATION_RELEASE True) +endif() -target_sources(${ASTC_TEST} +target_sources(${ASTCENC_TEST} PRIVATE test_simd.cpp test_softfloat.cpp + test_decode.cpp ../astcenc_mathlib_softfloat.cpp) -target_include_directories(${ASTC_TEST} +target_include_directories(${ASTCENC_TEST} PRIVATE ${gtest_SOURCE_DIR}/include) -target_compile_options(${ASTC_TEST} +target_link_libraries(${ASTCENC_TEST} + PRIVATE + astcenc-${ASTCENC_ISA_SIMD}-static) + +target_compile_options(${ASTCENC_TEST} PRIVATE # Use pthreads on Linux/macOS $<$:-pthread> @@ -47,92 +56,83 @@ target_compile_options(${ASTC_TEST} $<$>:-Wpedantic> $<$>:-Werror> $<$>:-Wshadow> - $<$>:-Wdouble-promotion>) + $<$>:-Wno-c++98-compat-pedantic> + $<$>:-Wno-c++98-c++11-compat-pedantic> + $<$>:-Wno-float-equal> + + # Ignore things that the googletest build triggers + $<$>:-Wno-unknown-warning-option> + $<$>:-Wno-double-promotion> + $<$>:-Wno-undef> + $<$>:-Wno-reserved-identifier> + $<$>:-Wno-global-constructors>) # Set up configuration for SIMD ISA builds -if(${ISA_SIMD} MATCHES "none") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${ASTC_TEST} - PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=0 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) - endif() - -elseif(${ISA_SIMD} MATCHES "neon") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${ASTC_TEST} - PRIVATE - ASTCENC_NEON=1 - ASTCENC_SSE=0 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) - endif() - -elseif(${ISA_SIMD} MATCHES "sse2") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${ASTC_TEST} - PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=20 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) - endif() - - target_compile_options(${ASTC_TEST} +if(${ASTCENC_ISA_SIMD} MATCHES "none") + target_compile_definitions(${ASTCENC_TEST} PRIVATE - $<$:-mfpmath=sse -msse2>) - -elseif(${ISA_SIMD} MATCHES "sse4.1") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${ASTC_TEST} - PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=41 - ASTCENC_AVX=0 - ASTCENC_POPCNT=1 - ASTCENC_F16C=0) - endif() - - target_compile_options(${ASTC_TEST} + ASTCENC_NEON=0 + ASTCENC_SSE=0 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) + +elseif(${ASTCENC_ISA_SIMD} MATCHES "neon") + target_compile_definitions(${ASTCENC_TEST} PRIVATE - $<$>:-mfpmath=sse -msse4.1 -mpopcnt>) - -elseif(${ISA_SIMD} MATCHES "avx2") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${ASTC_TEST} - PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=41 - ASTCENC_AVX=2 - ASTCENC_POPCNT=1 - ASTCENC_F16C=1) - endif() - - target_compile_options(${ASTC_TEST} + ASTCENC_NEON=1 + ASTCENC_SSE=0 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) + +elseif(${ASTCENC_ISA_SIMD} MATCHES "sse2") + target_compile_definitions(${ASTCENC_TEST} PRIVATE - $<$>:-mfpmath=sse -mavx2 -mpopcnt -mf16c> - $<$:/arch:AVX2>) + ASTCENC_NEON=0 + ASTCENC_SSE=20 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) -endif() + target_compile_options(${ASTCENC_TEST} + PRIVATE + $<$:-msse2>) -target_compile_options(${ASTC_TEST} - PRIVATE - $<$:-fsanitize=undefined>) +elseif(${ASTCENC_ISA_SIMD} MATCHES "sse4.1") + target_compile_definitions(${ASTCENC_TEST} + PRIVATE + ASTCENC_NEON=0 + ASTCENC_SSE=41 + ASTCENC_AVX=0 + ASTCENC_POPCNT=1 + ASTCENC_F16C=0) -target_link_options(${ASTC_TEST} - PRIVATE - $<$:-fsanitize=undefined>) + target_compile_options(${ASTCENC_TEST} + PRIVATE + $<$>:-msse4.1 -mpopcnt>) + +elseif(${ASTCENC_ISA_SIMD} MATCHES "avx2") + target_compile_definitions(${ASTCENC_TEST} + PRIVATE + ASTCENC_NEON=0 + ASTCENC_SSE=41 + ASTCENC_AVX=2 + ASTCENC_POPCNT=1 + ASTCENC_F16C=1) + + target_compile_options(${ASTCENC_TEST} + PRIVATE + $<$>:-mavx2 -mpopcnt -mf16c> + $<$:/arch:AVX2>) + +endif() -target_link_libraries(${ASTC_TEST} +target_link_libraries(${ASTCENC_TEST} PRIVATE gtest_main) -add_test(NAME ${ASTC_TEST} - COMMAND ${ASTC_TEST}) +add_test(NAME ${ASTCENC_TEST} + COMMAND ${ASTCENC_TEST}) -install(TARGETS ${ASTC_TEST} DESTINATION ${PACKAGE_ROOT}) +install(TARGETS ${ASTCENC_TEST}) diff --git a/Source/UnitTest/test_decode.cpp b/Source/UnitTest/test_decode.cpp new file mode 100644 index 0000000..e1364b6 --- /dev/null +++ b/Source/UnitTest/test_decode.cpp @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2023 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +/** + * @brief Unit tests for the vectorized SIMD functionality. + */ + +#include + +#include "gtest/gtest.h" + +#include "../astcenc.h" + +namespace astcenc +{ + +/** @brief Test harness for exploring issue #447. */ +TEST(decode, decode12x12) +{ + astcenc_error status; + astcenc_config config; + astcenc_context* context; + + static const astcenc_swizzle swizzle { + ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A + }; + + uint8_t data[16] { +#if 0 + 0x84,0x00,0x38,0xC8,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xB3,0x4D,0x78 +#else + 0x29,0x00,0x1A,0x97,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xCF,0x97,0x86 +#endif + }; + + uint8_t output[12*12*4]; + astcenc_config_init(ASTCENC_PRF_LDR, 12, 12, 1, ASTCENC_PRE_MEDIUM, 0, &config); + + status = astcenc_context_alloc(&config, 1, &context); + EXPECT_EQ(status, ASTCENC_SUCCESS); + + astcenc_image image; + image.dim_x = 12; + image.dim_y = 12; + image.dim_z = 1; + image.data_type = ASTCENC_TYPE_U8; + uint8_t* slices = output; + image.data = reinterpret_cast(&slices); + + status = astcenc_decompress_image(context, data, 16, &image, &swizzle, 0); + EXPECT_EQ(status, ASTCENC_SUCCESS); + + for (int y = 0; y < 12; y++) + { + for (int x = 0; x < 12; x++) + { + uint8_t* pixel = output + (12 * 4 * y) + (4 * x); + printf("[%2dx%2d] = %03d, %03d, %03d, %03d\n", x, y, pixel[0], pixel[1], pixel[2], pixel[3]); + } + } +} + +} diff --git a/Source/UnitTest/test_simd.cpp b/Source/UnitTest/test_simd.cpp index 37315b1..9424c99 100644 --- a/Source/UnitTest/test_simd.cpp +++ b/Source/UnitTest/test_simd.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2020-2022 Arm Limited +// Copyright 2020-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -31,15 +31,15 @@ namespace astcenc // Misc utility tests - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static int round_down(int x) +static unsigned int round_down(unsigned int x) { - int remainder = x % ASTCENC_SIMD_WIDTH; + unsigned int remainder = x % ASTCENC_SIMD_WIDTH; return x - remainder; } -static int round_up(int x) +static unsigned int round_up(unsigned int x) { - int remainder = x % ASTCENC_SIMD_WIDTH; + unsigned int remainder = x % ASTCENC_SIMD_WIDTH; if (!remainder) { return x; @@ -52,9 +52,9 @@ static int round_up(int x) TEST(misc, RoundDownVLA) { // Static ones which are valid for all VLA widths - EXPECT_EQ(round_down_to_simd_multiple_vla(0), 0); - EXPECT_EQ(round_down_to_simd_multiple_vla(8), 8); - EXPECT_EQ(round_down_to_simd_multiple_vla(16), 16); + EXPECT_EQ(round_down_to_simd_multiple_vla(0), 0u); + EXPECT_EQ(round_down_to_simd_multiple_vla(8), 8u); + EXPECT_EQ(round_down_to_simd_multiple_vla(16), 16u); // Variable ones which depend on VLA width EXPECT_EQ(round_down_to_simd_multiple_vla(3), round_down(3)); @@ -67,9 +67,9 @@ TEST(misc, RoundDownVLA) TEST(misc, RoundUpVLA) { // Static ones which are valid for all VLA widths - EXPECT_EQ(round_up_to_simd_multiple_vla(0), 0); - EXPECT_EQ(round_up_to_simd_multiple_vla(8), 8); - EXPECT_EQ(round_up_to_simd_multiple_vla(16), 16); + EXPECT_EQ(round_up_to_simd_multiple_vla(0), 0u); + EXPECT_EQ(round_up_to_simd_multiple_vla(8), 8u); + EXPECT_EQ(round_up_to_simd_multiple_vla(16), 16u); // Variable ones which depend on VLA width EXPECT_EQ(round_up_to_simd_multiple_vla(3), round_up(3)); @@ -540,27 +540,27 @@ TEST(vfloat4, ceq) vfloat4 a1(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b1(0.1f, 0.2f, 0.3f, 0.4f); vmask4 r1 = a1 == b1; - EXPECT_EQ(0, mask(r1)); + EXPECT_EQ(0u, mask(r1)); EXPECT_EQ(false, any(r1)); EXPECT_EQ(false, all(r1)); vfloat4 a2(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b2(1.0f, 0.2f, 0.3f, 0.4f); vmask4 r2 = a2 == b2; - EXPECT_EQ(0x1, mask(r2)); + EXPECT_EQ(0x1u, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vfloat4 a3(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b3(1.0f, 0.2f, 3.0f, 0.4f); vmask4 r3 = a3 == b3; - EXPECT_EQ(0x5, mask(r3)); + EXPECT_EQ(0x5u, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vfloat4 a4(1.0f, 2.0f, 3.0f, 4.0f); vmask4 r4 = a4 == a4; - EXPECT_EQ(0xF, mask(r4)); + EXPECT_EQ(0xFu, mask(r4)); EXPECT_EQ(true, any(r4)); EXPECT_EQ(true, all(r4)); } @@ -571,27 +571,27 @@ TEST(vfloat4, cne) vfloat4 a1(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b1(0.1f, 0.2f, 0.3f, 0.4f); vmask4 r1 = a1 != b1; - EXPECT_EQ(0xF, mask(r1)); + EXPECT_EQ(0xFu, mask(r1)); EXPECT_EQ(true, any(r1)); EXPECT_EQ(true, all(r1)); vfloat4 a2(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b2(1.0f, 0.2f, 0.3f, 0.4f); vmask4 r2 = a2 != b2; - EXPECT_EQ(0xE, mask(r2)); + EXPECT_EQ(0xEu, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vfloat4 a3(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b3(1.0f, 0.2f, 3.0f, 0.4f); vmask4 r3 = a3 != b3; - EXPECT_EQ(0xA, mask(r3)); + EXPECT_EQ(0xAu, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vfloat4 a4(1.0f, 2.0f, 3.0f, 4.0f); vmask4 r4 = a4 != a4; - EXPECT_EQ(0, mask(r4)); + EXPECT_EQ(0u, mask(r4)); EXPECT_EQ(false, any(r4)); EXPECT_EQ(false, all(r4)); } @@ -602,7 +602,7 @@ TEST(vfloat4, clt) vfloat4 a(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b(0.9f, 2.1f, 3.0f, 4.1f); vmask4 r = a < b; - EXPECT_EQ(0xA, mask(r)); + EXPECT_EQ(0xAu, mask(r)); } /** @brief Test vfloat4 cle. */ @@ -611,7 +611,7 @@ TEST(vfloat4, cle) vfloat4 a(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b(0.9f, 2.1f, 3.0f, 4.1f); vmask4 r = a <= b; - EXPECT_EQ(0xE, mask(r)); + EXPECT_EQ(0xEu, mask(r)); } /** @brief Test vfloat4 cgt. */ @@ -620,7 +620,7 @@ TEST(vfloat4, cgt) vfloat4 a(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b(0.9f, 2.1f, 3.0f, 4.1f); vmask4 r = a > b; - EXPECT_EQ(0x1, mask(r)); + EXPECT_EQ(0x1u, mask(r)); } /** @brief Test vfloat4 cge. */ @@ -629,7 +629,7 @@ TEST(vfloat4, cge) vfloat4 a(1.0f, 2.0f, 3.0f, 4.0f); vfloat4 b(0.9f, 2.1f, 3.0f, 4.1f); vmask4 r = a >= b; - EXPECT_EQ(0x5, mask(r)); + EXPECT_EQ(0x5u, mask(r)); } /** @brief Test vfloat4 min. */ @@ -894,7 +894,8 @@ TEST(vfloat4, select) /** @brief Test vfloat4 select MSB only. */ TEST(vfloat4, select_msb) { - vint4 msb(0x80000000, 0, 0x80000000, 0); + int msb_set = static_cast(0x80000000); + vint4 msb(msb_set, 0, msb_set, 0); vmask4 cond(msb.m); vfloat4 a(1.0f, 3.0f, 3.0f, 1.0f); @@ -929,7 +930,7 @@ TEST(vfloat4, gatherf) /** @brief Test vfloat4 storea. */ TEST(vfloat4, storea) { - alignas(16) float out[4]; + ASTCENC_ALIGNAS float out[4]; vfloat4 a(f32_data); storea(a, out); EXPECT_EQ(out[0], 0.0f); @@ -941,7 +942,7 @@ TEST(vfloat4, storea) /** @brief Test vfloat4 store. */ TEST(vfloat4, store) { - alignas(16) float out[5]; + ASTCENC_ALIGNAS float out[5]; vfloat4 a(f32_data); store(a, &(out[1])); EXPECT_EQ(out[1], 0.0f); @@ -1439,27 +1440,27 @@ TEST(vint4, ceq) vint4 a1(1, 2, 3, 4); vint4 b1(0, 1, 2, 3); vmask4 r1 = a1 == b1; - EXPECT_EQ(0, mask(r1)); + EXPECT_EQ(0u, mask(r1)); EXPECT_EQ(false, any(r1)); EXPECT_EQ(false, all(r1)); vint4 a2(1, 2, 3, 4); vint4 b2(1, 0, 0, 0); vmask4 r2 = a2 == b2; - EXPECT_EQ(0x1, mask(r2)); + EXPECT_EQ(0x1u, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vint4 a3(1, 2, 3, 4); vint4 b3(1, 0, 3, 0); vmask4 r3 = a3 == b3; - EXPECT_EQ(0x5, mask(r3)); + EXPECT_EQ(0x5u, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vint4 a4(1, 2, 3, 4); vmask4 r4 = a4 == a4; - EXPECT_EQ(0xF, mask(r4)); + EXPECT_EQ(0xFu, mask(r4)); EXPECT_EQ(true, any(r4)); EXPECT_EQ(true, all(r4)); } @@ -1470,27 +1471,27 @@ TEST(vint4, cne) vint4 a1(1, 2, 3, 4); vint4 b1(0, 1, 2, 3); vmask4 r1 = a1 != b1; - EXPECT_EQ(0xF, mask(r1)); + EXPECT_EQ(0xFu, mask(r1)); EXPECT_EQ(true, any(r1)); EXPECT_EQ(true, all(r1)); vint4 a2(1, 2, 3, 4); vint4 b2(1, 0, 0, 0); vmask4 r2 = a2 != b2; - EXPECT_EQ(0xE, mask(r2)); + EXPECT_EQ(0xEu, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vint4 a3(1, 2, 3, 4); vint4 b3(1, 0, 3, 0); vmask4 r3 = a3 != b3; - EXPECT_EQ(0xA, mask(r3)); + EXPECT_EQ(0xAu, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vint4 a4(1, 2, 3, 4); vmask4 r4 = a4 != a4; - EXPECT_EQ(0, mask(r4)); + EXPECT_EQ(0u, mask(r4)); EXPECT_EQ(false, any(r4)); EXPECT_EQ(false, all(r4)); } @@ -1501,7 +1502,7 @@ TEST(vint4, clt) vint4 a(1, 2, 3, 4); vint4 b(0, 3, 3, 5); vmask4 r = a < b; - EXPECT_EQ(0xA, mask(r)); + EXPECT_EQ(0xAu, mask(r)); } /** @brief Test vint4 cgt. */ @@ -1510,7 +1511,7 @@ TEST(vint4, cle) vint4 a(1, 2, 3, 4); vint4 b(0, 3, 3, 5); vmask4 r = a > b; - EXPECT_EQ(0x1, mask(r)); + EXPECT_EQ(0x1u, mask(r)); } /** @brief Test vint4 lsl. */ @@ -1544,7 +1545,7 @@ TEST(vint4, lsr) EXPECT_EQ(a.lane<0>(), 1); EXPECT_EQ(a.lane<1>(), 2); EXPECT_EQ(a.lane<2>(), 4); - EXPECT_EQ(a.lane<3>(), 0xFFFFFFFC); + EXPECT_EQ(a.lane<3>(), static_cast(0xFFFFFFFC)); a = lsr<1>(a); EXPECT_EQ(a.lane<0>(), 0); @@ -1681,7 +1682,8 @@ TEST(vint4, hadd_rgb_s) /** @brief Test vint4 clz. */ TEST(vint4, clz) { - vint4 a1(0x80000000, 0x40000000, 0x20000000, 0x10000000); + int msb_set = static_cast(0x80000000); + vint4 a1(msb_set, 0x40000000, 0x20000000, 0x10000000); vint4 r1 = clz(a1); EXPECT_EQ(r1.lane<0>(), 0); EXPECT_EQ(r1.lane<1>(), 1); @@ -1723,7 +1725,7 @@ TEST(vint4, two_to_the_n) /** @brief Test vint4 storea. */ TEST(vint4, storea) { - alignas(16) int out[4]; + ASTCENC_ALIGNAS int out[4]; vint4 a(s32_data); storea(a, out); EXPECT_EQ(out[0], 0); @@ -1735,7 +1737,7 @@ TEST(vint4, storea) /** @brief Test vint4 store. */ TEST(vint4, store) { - alignas(16) int out[5]; + ASTCENC_ALIGNAS int out[5]; vint4 a(s32_data); store(a, &(out[1])); EXPECT_EQ(out[1], 0); @@ -1747,12 +1749,78 @@ TEST(vint4, store) /** @brief Test vint4 store_nbytes. */ TEST(vint4, store_nbytes) { - alignas(16) int out; + ASTCENC_ALIGNAS int out; vint4 a(42, 314, 75, 90); - store_nbytes(a, (uint8_t*)&out); + store_nbytes(a, reinterpret_cast(&out)); EXPECT_EQ(out, 42); } +/** @brief Test vint4 store_lanes_masked. */ +TEST(vint4, store_lanes_masked) +{ + uint8_t resulta[16] { 0 }; + + // Store nothing + vmask4 mask1 = vint4(0) == vint4(1); + vint4 data1 = vint4(1); + + store_lanes_masked(resulta, data1, mask1); + vint4 result1v = vint4::load(resulta); + vint4 expect1v = vint4::zero(); + EXPECT_TRUE(all(result1v == expect1v)); + + // Store half + vmask4 mask2 = vint4(1, 1, 0, 0) == vint4(1); + vint4 data2 = vint4(2); + + store_lanes_masked(resulta, data2, mask2); + vint4 result2v = vint4::load(resulta); + vint4 expect2v = vint4(2, 2, 0, 0); + EXPECT_TRUE(all(result2v == expect2v)); + + // Store all + vmask4 mask3 = vint4(1) == vint4(1); + vint4 data3 = vint4(3); + + store_lanes_masked(resulta, data3, mask3); + vint4 result3v = vint4::load(resulta); + vint4 expect3v = vint4(3); + EXPECT_TRUE(all(result3v == expect3v)); +} + +/** @brief Test vint4 store_lanes_masked to unaligned address. */ +TEST(vint4, store_lanes_masked_unaligned) +{ + uint8_t resulta[17] { 0 }; + + // Store nothing + vmask4 mask1 = vint4(0) == vint4(1); + vint4 data1 = vint4(1); + + store_lanes_masked(resulta + 1, data1, mask1); + vint4 result1v = vint4::load(resulta + 1); + vint4 expect1v = vint4::zero(); + EXPECT_TRUE(all(result1v == expect1v)); + + // Store half + vmask4 mask2 = vint4(1, 1, 0, 0) == vint4(1); + vint4 data2 = vint4(2); + + store_lanes_masked(resulta + 1, data2, mask2); + vint4 result2v = vint4::load(resulta + 1); + vint4 expect2v = vint4(2, 2, 0, 0); + EXPECT_TRUE(all(result2v == expect2v)); + + // Store all + vmask4 mask3 = vint4(1) == vint4(1); + vint4 data3 = vint4(3); + + store_lanes_masked(resulta + 1, data3, mask3); + vint4 result3v = vint4::load(resulta + 1); + vint4 expect3v = vint4(3); + EXPECT_TRUE(all(result3v == expect3v)); +} + /** @brief Test vint4 gatheri. */ TEST(vint4, gatheri) { @@ -1799,38 +1867,38 @@ TEST(vint4, select) /** @brief Test vmask4 scalar literal constructor. */ TEST(vmask4, scalar_literal_construct) { - vfloat4 m1a(0, 0, 0, 0); - vfloat4 m1b(1, 1, 1, 1); + vfloat4 m1a(0.0f, 0.0f, 0.0f, 0.0f); + vfloat4 m1b(1.0f, 1.0f, 1.0f, 1.0f); vmask4 m1(true); vfloat4 r = select(m1a, m1b, m1); - EXPECT_EQ(r.lane<0>(), 1); - EXPECT_EQ(r.lane<1>(), 1); - EXPECT_EQ(r.lane<2>(), 1); - EXPECT_EQ(r.lane<3>(), 1); + EXPECT_EQ(r.lane<0>(), 1.0f); + EXPECT_EQ(r.lane<1>(), 1.0f); + EXPECT_EQ(r.lane<2>(), 1.0f); + EXPECT_EQ(r.lane<3>(), 1.0f); r = select(m1b, m1a, m1); - EXPECT_EQ(r.lane<0>(), 0); - EXPECT_EQ(r.lane<1>(), 0); - EXPECT_EQ(r.lane<2>(), 0); - EXPECT_EQ(r.lane<3>(), 0); + EXPECT_EQ(r.lane<0>(), 0.0f); + EXPECT_EQ(r.lane<1>(), 0.0f); + EXPECT_EQ(r.lane<2>(), 0.0f); + EXPECT_EQ(r.lane<3>(), 0.0f); } /** @brief Test vmask4 literal constructor. */ TEST(vmask4, literal_construct) { - vfloat4 m1a(0, 0, 0, 0); - vfloat4 m1b(1, 1, 1, 1); + vfloat4 m1a(0.0f, 0.0f, 0.0f, 0.0f); + vfloat4 m1b(1.0f, 1.0f, 1.0f, 1.0f); vmask4 m1(true, false, true, false); vfloat4 r = select(m1a, m1b, m1); - EXPECT_EQ(r.lane<0>(), 1); - EXPECT_EQ(r.lane<1>(), 0); - EXPECT_EQ(r.lane<2>(), 1); - EXPECT_EQ(r.lane<3>(), 0); + EXPECT_EQ(r.lane<0>(), 1.0f); + EXPECT_EQ(r.lane<1>(), 0.0f); + EXPECT_EQ(r.lane<2>(), 1.0f); + EXPECT_EQ(r.lane<3>(), 0.0f); } /** @brief Test vmask4 or. */ @@ -1845,7 +1913,7 @@ TEST(vmask4, or) vmask4 m2 = m2a == m2b; vmask4 r = m1 | m2; - EXPECT_EQ(mask(r), 0xB); + EXPECT_EQ(mask(r), 0xBu); } /** @brief Test vmask4 and. */ @@ -1860,7 +1928,7 @@ TEST(vmask4, and) vmask4 m2 = m2a == m2b; vmask4 r = m1 & m2; - EXPECT_EQ(mask(r), 0x2); + EXPECT_EQ(mask(r), 0x2u); } /** @brief Test vmask4 xor. */ @@ -1875,7 +1943,7 @@ TEST(vmask4, xor) vmask4 m2 = m2a == m2b; vmask4 r = m1 ^ m2; - EXPECT_EQ(mask(r), 0x9); + EXPECT_EQ(mask(r), 0x9u); } /** @brief Test vmask4 not. */ @@ -1885,7 +1953,63 @@ TEST(vmask4, not) vfloat4 m1b(1, 1, 1, 1); vmask4 m1 = m1a == m1b; vmask4 r = ~m1; - EXPECT_EQ(mask(r), 0x5); + EXPECT_EQ(mask(r), 0x5u); +} + +/** @brief Test vint4 table permute. */ +TEST(vint4, vtable_8bt_32bi_32entry) +{ + vint4 table0(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + vint4 table1(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f); + + vint4 table0p, table1p; + vtable_prepare(table0, table1, table0p, table1p); + + vint4 index(0, 7, 4, 31); + + vint4 result = vtable_8bt_32bi(table0p, table1p, index); + + EXPECT_EQ(result.lane<0>(), 3); + EXPECT_EQ(result.lane<1>(), 4); + EXPECT_EQ(result.lane<2>(), 7); + EXPECT_EQ(result.lane<3>(), 28); +} + +/** @brief Test vint4 table permute. */ +TEST(vint4, vtable_8bt_32bi_64entry) +{ + vint4 table0(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + vint4 table1(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f); + vint4 table2(0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f); + vint4 table3(0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f); + + vint4 table0p, table1p, table2p, table3p; + vtable_prepare(table0, table1, table2, table3, table0p, table1p, table2p, table3p); + + vint4 index(0, 7, 38, 63); + + vint4 result = vtable_8bt_32bi(table0p, table1p, table2p, table3p, index); + + EXPECT_EQ(result.lane<0>(), 3); + EXPECT_EQ(result.lane<1>(), 4); + EXPECT_EQ(result.lane<2>(), 37); + EXPECT_EQ(result.lane<3>(), 60); +} + +/** @brief Test vint4 rgba byte interleave. */ +TEST(vint4, interleave_rgba8) +{ + vint4 r(0x01, 0x11, 0x21, 0x31); + vint4 g(0x02, 0x12, 0x22, 0x32); + vint4 b(0x03, 0x13, 0x23, 0x33); + vint4 a(0x04, 0x14, 0x24, 0x34); + + vint4 result = interleave_rgba8(r, g, b, a); + + EXPECT_EQ(result.lane<0>(), 0x04030201); + EXPECT_EQ(result.lane<1>(), 0x14131211); + EXPECT_EQ(result.lane<2>(), 0x24232221); + EXPECT_EQ(result.lane<3>(), 0x34333231); } # if ASTCENC_SIMD_WIDTH == 8 @@ -2142,27 +2266,27 @@ TEST(vfloat8, ceq) vfloat8 a1(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b1(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r1 = a1 == b1; - EXPECT_EQ(0, mask(r1)); + EXPECT_EQ(0u, mask(r1)); EXPECT_EQ(false, any(r1)); EXPECT_EQ(false, all(r1)); vfloat8 a2(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b2(1.0f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r2 = a2 == b2; - EXPECT_EQ(0x1, mask(r2)); + EXPECT_EQ(0x1u, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vfloat8 a3(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b3(1.0f, 0.2f, 3.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r3 = a3 == b3; - EXPECT_EQ(0x5, mask(r3)); + EXPECT_EQ(0x5u, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vfloat8 a4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vmask8 r4 = a4 == a4; - EXPECT_EQ(0xFF, mask(r4)); + EXPECT_EQ(0xFFu, mask(r4)); EXPECT_EQ(true, any(r4)); EXPECT_EQ(true, all(r4)); } @@ -2173,27 +2297,27 @@ TEST(vfloat8, cne) vfloat8 a1(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b1(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r1 = a1 != b1; - EXPECT_EQ(0xFF, mask(r1)); + EXPECT_EQ(0xFFu, mask(r1)); EXPECT_EQ(true, any(r1)); EXPECT_EQ(true, all(r1)); vfloat8 a2(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b2(1.0f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r2 = a2 != b2; - EXPECT_EQ(0xFE, mask(r2)); + EXPECT_EQ(0xFEu, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vfloat8 a3(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vfloat8 b3(1.0f, 0.2f, 3.0f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f); vmask8 r3 = a3 != b3; - EXPECT_EQ(0xFA, mask(r3)); + EXPECT_EQ(0xFAu, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vfloat8 a4(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); vmask8 r4 = a4 != a4; - EXPECT_EQ(0, mask(r4)); + EXPECT_EQ(0u, mask(r4)); EXPECT_EQ(false, any(r4)); EXPECT_EQ(false, all(r4)); } @@ -2204,7 +2328,7 @@ TEST(vfloat8, clt) vfloat8 a(1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f); vfloat8 b(0.9f, 2.1f, 3.0f, 4.1f, 0.9f, 2.1f, 3.0f, 4.1f); vmask8 r = a < b; - EXPECT_EQ(0xAA, mask(r)); + EXPECT_EQ(0xAAu, mask(r)); } /** @brief Test vfloat8 cle. */ @@ -2213,7 +2337,7 @@ TEST(vfloat8, cle) vfloat8 a(1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f); vfloat8 b(0.9f, 2.1f, 3.0f, 4.1f, 0.9f, 2.1f, 3.0f, 4.1f); vmask8 r = a <= b; - EXPECT_EQ(0xEE, mask(r)); + EXPECT_EQ(0xEEu, mask(r)); } /** @brief Test vfloat8 cgt. */ @@ -2222,7 +2346,7 @@ TEST(vfloat8, cgt) vfloat8 a(1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f); vfloat8 b(0.9f, 2.1f, 3.0f, 4.1f, 0.9f, 2.1f, 3.0f, 4.1f); vmask8 r = a > b; - EXPECT_EQ(0x11, mask(r)); + EXPECT_EQ(0x11u, mask(r)); } /** @brief Test vfloat8 cge. */ @@ -2231,7 +2355,7 @@ TEST(vfloat8, cge) vfloat8 a(1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f); vfloat8 b(0.9f, 2.1f, 3.0f, 4.1f, 0.9f, 2.1f, 3.0f, 4.1f); vmask8 r = a >= b; - EXPECT_EQ(0x55, mask(r)); + EXPECT_EQ(0x55u, mask(r)); } /** @brief Test vfloat8 min. */ @@ -2510,7 +2634,8 @@ TEST(vfloat8, select) /** @brief Test vfloat8 select MSB only. */ TEST(vfloat8, select_msb) { - vint8 msb(0x80000000, 0, 0x80000000, 0, 0x80000000, 0, 0x80000000, 0); + int msb_set = static_cast(0x80000000); + vint8 msb(msb_set, 0, msb_set, 0, msb_set, 0, msb_set, 0); vmask8 cond(msb.m); vfloat8 a(1.0f, 3.0f, 3.0f, 1.0f, 1.0f, 3.0f, 3.0f, 1.0f); @@ -2527,7 +2652,6 @@ TEST(vfloat8, select_msb) EXPECT_EQ(r1.lane<6>(), 2.0f); EXPECT_EQ(r1.lane<7>(), 1.0f); - // Select in the other vfloat8 r2 = select(b, a, cond); EXPECT_EQ(r2.lane<0>(), 1.0f); @@ -2867,27 +2991,27 @@ TEST(vint8, ceq) vint8 a1(1, 2, 3, 4, 1, 2, 3, 4); vint8 b1(0, 1, 2, 3, 0, 1, 2, 3); vmask8 r1 = a1 == b1; - EXPECT_EQ(0, mask(r1)); + EXPECT_EQ(0u, mask(r1)); EXPECT_EQ(false, any(r1)); EXPECT_EQ(false, all(r1)); vint8 a2(1, 2, 3, 4, 1, 2, 3, 4); vint8 b2(1, 0, 0, 0, 1, 0, 0, 0); vmask8 r2 = a2 == b2; - EXPECT_EQ(0x11, mask(r2)); + EXPECT_EQ(0x11u, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vint8 a3(1, 2, 3, 4, 1, 2, 3, 4); vint8 b3(1, 0, 3, 0, 1, 0, 3, 0); vmask8 r3 = a3 == b3; - EXPECT_EQ(0x55, mask(r3)); + EXPECT_EQ(0x55u, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vint8 a4(1, 2, 3, 4, 1, 2, 3, 4); vmask8 r4 = a4 == a4; - EXPECT_EQ(0xFF, mask(r4)); + EXPECT_EQ(0xFFu, mask(r4)); EXPECT_EQ(true, any(r4)); EXPECT_EQ(true, all(r4)); } @@ -2898,27 +3022,27 @@ TEST(vint8, cne) vint8 a1(1, 2, 3, 4, 1, 2, 3, 4); vint8 b1(0, 1, 2, 3, 0, 1, 2, 3); vmask8 r1 = a1 != b1; - EXPECT_EQ(0xFF, mask(r1)); + EXPECT_EQ(0xFFu, mask(r1)); EXPECT_EQ(true, any(r1)); EXPECT_EQ(true, all(r1)); vint8 a2(1, 2, 3, 4, 1, 2, 3, 4); vint8 b2(1, 0, 0, 0, 1, 0, 0, 0); vmask8 r2 = a2 != b2; - EXPECT_EQ(0xEE, mask(r2)); + EXPECT_EQ(0xEEu, mask(r2)); EXPECT_EQ(true, any(r2)); EXPECT_EQ(false, all(r2)); vint8 a3(1, 2, 3, 4, 1, 2, 3, 4); vint8 b3(1, 0, 3, 0, 1, 0, 3, 0); vmask8 r3 = a3 != b3; - EXPECT_EQ(0xAA, mask(r3)); + EXPECT_EQ(0xAAu, mask(r3)); EXPECT_EQ(true, any(r3)); EXPECT_EQ(false, all(r3)); vint8 a4(1, 2, 3, 4, 1, 2, 3, 4); vmask8 r4 = a4 != a4; - EXPECT_EQ(0, mask(r4)); + EXPECT_EQ(0u, mask(r4)); EXPECT_EQ(false, any(r4)); EXPECT_EQ(false, all(r4)); } @@ -2929,7 +3053,7 @@ TEST(vint8, clt) vint8 a(1, 2, 3, 4, 1, 2, 3, 4); vint8 b(0, 3, 3, 5, 0, 3, 3, 5); vmask8 r = a < b; - EXPECT_EQ(0xAA, mask(r)); + EXPECT_EQ(0xAAu, mask(r)); } /** @brief Test vint8 cgt. */ @@ -2938,7 +3062,7 @@ TEST(vint8, cgt) vint8 a(1, 2, 3, 4, 1, 2, 3, 4); vint8 b(0, 3, 3, 5, 0, 3, 3, 5); vmask8 r = a > b; - EXPECT_EQ(0x11, mask(r)); + EXPECT_EQ(0x11u, mask(r)); } /** @brief Test vint8 min. */ @@ -2973,30 +3097,66 @@ TEST(vint8, max) EXPECT_EQ(r.lane<7>(), 5); } +/** @brief Test vint8 lsl. */ +TEST(vint8, lsl) +{ + vint8 a(1, 2, 4, -4, 1, 2, 4, -4); + a = lsl<0>(a); + EXPECT_EQ(a.lane<0>(), 1); + EXPECT_EQ(a.lane<1>(), 2); + EXPECT_EQ(a.lane<2>(), 4); + EXPECT_EQ(a.lane<3>(), static_cast(0xFFFFFFFC)); + EXPECT_EQ(a.lane<4>(), 1); + EXPECT_EQ(a.lane<5>(), 2); + EXPECT_EQ(a.lane<6>(), 4); + EXPECT_EQ(a.lane<7>(), static_cast(0xFFFFFFFC)); + + + a = lsl<1>(a); + EXPECT_EQ(a.lane<0>(), 2); + EXPECT_EQ(a.lane<1>(), 4); + EXPECT_EQ(a.lane<2>(), 8); + EXPECT_EQ(a.lane<3>(), static_cast(0xFFFFFFF8)); + EXPECT_EQ(a.lane<4>(), 2); + EXPECT_EQ(a.lane<5>(), 4); + EXPECT_EQ(a.lane<6>(), 8); + EXPECT_EQ(a.lane<7>(), static_cast(0xFFFFFFF8)); + + a = lsl<2>(a); + EXPECT_EQ(a.lane<0>(), 8); + EXPECT_EQ(a.lane<1>(), 16); + EXPECT_EQ(a.lane<2>(), 32); + EXPECT_EQ(a.lane<3>(), static_cast(0xFFFFFFE0)); + EXPECT_EQ(a.lane<4>(), 8); + EXPECT_EQ(a.lane<5>(), 16); + EXPECT_EQ(a.lane<6>(), 32); + EXPECT_EQ(a.lane<7>(), static_cast(0xFFFFFFE0)); +} + /** @brief Test vint8 lsr. */ TEST(vint8, lsr) { vint8 a(1, 2, 4, -4, 1, 2, 4, -4); a = lsr<0>(a); - EXPECT_EQ(a.lane<0>(), 1); - EXPECT_EQ(a.lane<1>(), 2); - EXPECT_EQ(a.lane<2>(), 4); - EXPECT_EQ(a.lane<3>(), 0xFFFFFFFC); - EXPECT_EQ(a.lane<4>(), 1); - EXPECT_EQ(a.lane<5>(), 2); - EXPECT_EQ(a.lane<6>(), 4); - EXPECT_EQ(a.lane<7>(), 0xFFFFFFFC); + EXPECT_EQ(a.lane<0>(), 1); + EXPECT_EQ(a.lane<1>(), 2); + EXPECT_EQ(a.lane<2>(), 4); + EXPECT_EQ(a.lane<3>(), static_cast(0xFFFFFFFC)); + EXPECT_EQ(a.lane<4>(), 1); + EXPECT_EQ(a.lane<5>(), 2); + EXPECT_EQ(a.lane<6>(), 4); + EXPECT_EQ(a.lane<7>(), static_cast(0xFFFFFFFC)); a = lsr<1>(a); - EXPECT_EQ(a.lane<0>(), 0); - EXPECT_EQ(a.lane<1>(), 1); - EXPECT_EQ(a.lane<2>(), 2); - EXPECT_EQ(a.lane<3>(), 0x7FFFFFFE); - EXPECT_EQ(a.lane<4>(), 0); - EXPECT_EQ(a.lane<5>(), 1); - EXPECT_EQ(a.lane<6>(), 2); - EXPECT_EQ(a.lane<7>(), 0x7FFFFFFE); + EXPECT_EQ(a.lane<0>(), 0); + EXPECT_EQ(a.lane<1>(), 1); + EXPECT_EQ(a.lane<2>(), 2); + EXPECT_EQ(a.lane<3>(), 0x7FFFFFFE); + EXPECT_EQ(a.lane<4>(), 0); + EXPECT_EQ(a.lane<5>(), 1); + EXPECT_EQ(a.lane<6>(), 2); + EXPECT_EQ(a.lane<7>(), 0x7FFFFFFE); a = lsr<2>(a); EXPECT_EQ(a.lane<0>(), 0); @@ -3134,11 +3294,77 @@ TEST(vint8, store_nbytes) { alignas(32) int out[2]; vint8 a(42, 314, 75, 90, 42, 314, 75, 90); - store_nbytes(a, (uint8_t*)&out); + store_nbytes(a, reinterpret_cast(&out)); EXPECT_EQ(out[0], 42); EXPECT_EQ(out[1], 314); } +/** @brief Test vint8 store_lanes_masked. */ +TEST(vint8, store_lanes_masked) +{ + uint8_t resulta[32] { 0 }; + + // Store nothing + vmask8 mask1 = vint8(0) == vint8(1); + vint8 data1 = vint8(1); + + store_lanes_masked(resulta, data1, mask1); + vint8 result1v = vint8::load(resulta); + vint8 expect1v = vint8::zero(); + EXPECT_TRUE(all(result1v == expect1v)); + + // Store half + vmask8 mask2 = vint8(1, 1, 1, 1, 0, 0, 0, 0) == vint8(1); + vint8 data2 = vint8(2); + + store_lanes_masked(resulta, data2, mask2); + vint8 result2v = vint8::load(resulta); + vint8 expect2v = vint8(2, 2, 2, 2, 0, 0, 0, 0); + EXPECT_TRUE(all(result2v == expect2v)); + + // Store all + vmask8 mask3 = vint8(1) == vint8(1); + vint8 data3 = vint8(3); + + store_lanes_masked(resulta, data3, mask3); + vint8 result3v = vint8::load(resulta); + vint8 expect3v = vint8(3); + EXPECT_TRUE(all(result3v == expect3v)); +} + +/** @brief Test vint8 store_lanes_masked to unaligned address. */ +TEST(vint8, store_lanes_masked_unaligned) +{ + uint8_t resulta[33] { 0 }; + + // Store nothing + vmask8 mask1 = vint8(0) == vint8(1); + vint8 data1 = vint8(1); + + store_lanes_masked(resulta + 1, data1, mask1); + vint8 result1v = vint8::load(resulta + 1); + vint8 expect1v = vint8::zero(); + EXPECT_TRUE(all(result1v == expect1v)); + + // Store half + vmask8 mask2 = vint8(1, 1, 1, 1, 0, 0, 0, 0) == vint8(1); + vint8 data2 = vint8(2); + + store_lanes_masked(resulta + 1, data2, mask2); + vint8 result2v = vint8::load(resulta + 1); + vint8 expect2v = vint8(2, 2, 2, 2, 0, 0, 0, 0); + EXPECT_TRUE(all(result2v == expect2v)); + + // Store all + vmask8 mask3 = vint8(1) == vint8(1); + vint8 data3 = vint8(3); + + store_lanes_masked(resulta + 1, data3, mask3); + vint8 result3v = vint8::load(resulta + 1); + vint8 expect3v = vint8(3); + EXPECT_TRUE(all(result3v == expect3v)); +} + /** @brief Test vint8 gatheri. */ TEST(vint8, gatheri) { @@ -3225,7 +3451,7 @@ TEST(vmask8, or) vmask8 m2 = m2a == m2b; vmask8 r = m1 | m2; - EXPECT_EQ(mask(r), 0xBB); + EXPECT_EQ(mask(r), 0xBBu); } /** @brief Test vmask8 and. */ @@ -3240,7 +3466,7 @@ TEST(vmask8, and) vmask8 m2 = m2a == m2b; vmask8 r = m1 & m2; - EXPECT_EQ(mask(r), 0x22); + EXPECT_EQ(mask(r), 0x22u); } /** @brief Test vmask8 xor. */ @@ -3255,7 +3481,7 @@ TEST(vmask8, xor) vmask8 m2 = m2a == m2b; vmask8 r = m1 ^ m2; - EXPECT_EQ(mask(r), 0x99); + EXPECT_EQ(mask(r), 0x99u); } /** @brief Test vmask8 not. */ @@ -3265,7 +3491,55 @@ TEST(vmask8, not) vfloat8 m1b(1, 1, 1, 1, 1, 1, 1, 1); vmask8 m1 = m1a == m1b; vmask8 r = ~m1; - EXPECT_EQ(mask(r), 0x55); + EXPECT_EQ(mask(r), 0x55u); +} + +/** @brief Test vint8 table permute. */ +TEST(vint8, vtable_8bt_32bi_32entry) +{ + vint4 table0(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + vint4 table1(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f); + + vint8 table0p, table1p; + vtable_prepare(table0, table1, table0p, table1p); + + vint8 index(0, 7, 4, 15, 16, 20, 23, 31); + + vint8 result = vtable_8bt_32bi(table0p, table1p, index); + + EXPECT_EQ(result.lane<0>(), 3); + EXPECT_EQ(result.lane<1>(), 4); + EXPECT_EQ(result.lane<2>(), 7); + EXPECT_EQ(result.lane<3>(), 12); + EXPECT_EQ(result.lane<4>(), 19); + EXPECT_EQ(result.lane<5>(), 23); + EXPECT_EQ(result.lane<6>(), 20); + EXPECT_EQ(result.lane<7>(), 28); +} + +/** @brief Test vint4 table permute. */ +TEST(vint8, vtable_8bt_32bi_64entry) +{ + vint4 table0(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f); + vint4 table1(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f); + vint4 table2(0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f); + vint4 table3(0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f); + + vint8 table0p, table1p, table2p, table3p; + vtable_prepare(table0, table1, table2, table3, table0p, table1p, table2p, table3p); + + vint8 index(0, 7, 4, 15, 16, 20, 38, 63); + + vint8 result = vtable_8bt_32bi(table0p, table1p, table2p, table3p, index); + + EXPECT_EQ(result.lane<0>(), 3); + EXPECT_EQ(result.lane<1>(), 4); + EXPECT_EQ(result.lane<2>(), 7); + EXPECT_EQ(result.lane<3>(), 12); + EXPECT_EQ(result.lane<4>(), 19); + EXPECT_EQ(result.lane<5>(), 23); + EXPECT_EQ(result.lane<6>(), 37); + EXPECT_EQ(result.lane<7>(), 60); } #endif diff --git a/Source/astcenc.h b/Source/astcenc.h index ac2b0c9..0df7534 100644 --- a/Source/astcenc.h +++ b/Source/astcenc.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2020-2022 Arm Limited +// Copyright 2020-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -43,10 +43,18 @@ * for faster processing. The caller is responsible for creating the worker threads, and * synchronizing between images. * + * Extended instruction set support + * ================================ + * + * This library supports use of extended instruction sets, such as SSE4.1 and AVX2. These are + * enabled at compile time when building the library. There is no runtime checking in the core + * library that the instruction sets used are actually available. Checking compatibility is the + * responsibility of the calling code. + * * Threading * ========= * - * In pseudocode, the usage for manual user threading looks like this: + * In pseudo-code, the usage for manual user threading looks like this: * * // Configure the compressor run * astcenc_config my_config; @@ -74,7 +82,7 @@ * * The codec supports compressing single images, which can be either 2D images or volumetric 3D * images. Calling code is responsible for any handling of aggregate types, such as mipmap chains, - * texture arrays, or sliced 3D textures + * texture arrays, or sliced 3D textures. * * Images are passed in as an astcenc_image structure. Inputs can be either 8-bit unorm, 16-bit * half-float, or 32-bit float, as indicated by the data_type field. @@ -82,7 +90,7 @@ * Images can be any dimension; there is no requirement to be a multiple of the ASTC block size. * * Data is always passed in as 4 color components, and accessed as an array of 2D image slices. Data - * within an image slice is always tightly packed without padding. Addresing looks like this: + * within an image slice is always tightly packed without padding. Addressing looks like this: * * data[z_coord][y_coord * x_dim * 4 + x_coord * 4 ] // Red * data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 1] // Green @@ -112,8 +120,8 @@ * Input images must contain unit-length normalized and should be passed in using a two component * swizzle. The astcenc command line tool defaults to an RRRG swizzle, but some developers prefer * to use GGGR for compatability with BC5n which will work just as well. The Z component can be - * recovered programatically in shader code, using knowledge that the vector is unit length and that - * Z must be positive for a tangent-space normal map. + * recovered programmatically in shader code, using knowledge that the vector is unit length and + * that Z must be positive for a tangent-space normal map. * * Decompress-only usage * ===================== @@ -215,8 +223,6 @@ enum astcenc_error { ASTCENC_ERR_OUT_OF_MEM, /** @brief The call failed due to the build using fast math. */ ASTCENC_ERR_BAD_CPU_FLOAT, - /** @brief The call failed due to the build using an unsupported ISA. */ - ASTCENC_ERR_BAD_CPU_ISA, /** @brief The call failed due to an out-of-spec parameter. */ ASTCENC_ERR_BAD_PARAM, /** @brief The call failed due to an out-of-spec block size. */ @@ -233,6 +239,8 @@ enum astcenc_error { ASTCENC_ERR_BAD_CONTEXT, /** @brief The call failed due to unimplemented functionality. */ ASTCENC_ERR_NOT_IMPLEMENTED, + /** @brief The call failed due to an out-of-spec decode mode flag set. */ + ASTCENC_ERR_BAD_DECODE_MODE, #if defined(ASTCENC_DIAGNOSTICS) /** @brief The call failed due to an issue with diagnostic tracing. */ ASTCENC_ERR_DTRACE_FAILURE, @@ -265,9 +273,12 @@ static const float ASTCENC_PRE_FAST = 10.0f; /** @brief The medium quality search preset. */ static const float ASTCENC_PRE_MEDIUM = 60.0f; -/** @brief The throrough quality search preset. */ +/** @brief The thorough quality search preset. */ static const float ASTCENC_PRE_THOROUGH = 98.0f; +/** @brief The thorough quality search preset. */ +static const float ASTCENC_PRE_VERYTHOROUGH = 99.0f; + /** @brief The exhaustive, highest quality, search preset. */ static const float ASTCENC_PRE_EXHAUSTIVE = 100.0f; @@ -320,6 +331,11 @@ enum astcenc_type ASTCENC_TYPE_F32 = 2 }; +/** + * @brief Function pointer type for compression progress reporting callback. + */ +extern "C" typedef void (*astcenc_progress_callback)(float); + /** * @brief Enable normal map compression. * @@ -331,35 +347,17 @@ enum astcenc_type static const unsigned int ASTCENC_FLG_MAP_NORMAL = 1 << 0; /** - * @brief Enable mask map compression. - * - * Input data will be treated a multi-layer mask map, where is is desirable for the color components - * to be treated independently for the purposes of error analysis. - */ -static const unsigned int ASTCENC_FLG_MAP_MASK = 1 << 1; - -/** - * @brief Enable RGBM map compression. + * @brief Enable compression heuristics that assume use of decode_unorm8 decode mode. * - * Input data will be treated as HDR data that has been stored in an LDR RGBM-encoded wrapper - * format. Data must be preprocessed by the user to be in LDR RGBM format before calling the - * compression function, this flag is only used to control the use of RGBM-specific heuristics and - * error metrics. - * - * IMPORTANT: The ASTC format is prone to bad failure modes with unconstrained RGBM data; very small - * M values can round to zero due to quantization and result in black or white pixels. It is highly - * recommended that the minimum value of M used in the encoding is kept above a lower threshold (try - * 16 or 32). Applying this threshold reduces the number of very dark colors that can be - * represented, but is still higher precision than 8-bit LDR. + * The decode_unorm8 decode mode rounds differently to the decode_fp16 decode mode, so enabling this + * flag during compression will allow the compressor to use the correct rounding when selecting + * encodings. This will improve the compressed image quality if your application is using the + * decode_unorm8 decode mode, but will reduce image quality if using decode_fp16. * - * When this flag is set the value of @c rgbm_m_scale in the context must be set to the RGBM scale - * factor used during reconstruction. This defaults to 5 when in RGBM mode. - * - * It is recommended that the value of @c cw_a_weight is set to twice the value of the multiplier - * scale, ensuring that the M value is accurately encoded. This defaults to 10 when in RGBM mode, - * matching the default scale factor. + * Note that LDR_SRGB images will always use decode_unorm8 for the RGB channels, irrespective of + * this setting. */ -static const unsigned int ASTCENC_FLG_MAP_RGBM = 1 << 6; +static const unsigned int ASTCENC_FLG_USE_DECODE_UNORM8 = 1 << 1; /** * @brief Enable alpha weighting. @@ -396,15 +394,38 @@ static const unsigned int ASTCENC_FLG_DECOMPRESS_ONLY = 1 << 4; */ static const unsigned int ASTCENC_FLG_SELF_DECOMPRESS_ONLY = 1 << 5; +/** + * @brief Enable RGBM map compression. + * + * Input data will be treated as HDR data that has been stored in an LDR RGBM-encoded wrapper + * format. Data must be preprocessed by the user to be in LDR RGBM format before calling the + * compression function, this flag is only used to control the use of RGBM-specific heuristics and + * error metrics. + * + * IMPORTANT: The ASTC format is prone to bad failure modes with unconstrained RGBM data; very small + * M values can round to zero due to quantization and result in black or white pixels. It is highly + * recommended that the minimum value of M used in the encoding is kept above a lower threshold (try + * 16 or 32). Applying this threshold reduces the number of very dark colors that can be + * represented, but is still higher precision than 8-bit LDR. + * + * When this flag is set the value of @c rgbm_m_scale in the context must be set to the RGBM scale + * factor used during reconstruction. This defaults to 5 when in RGBM mode. + * + * It is recommended that the value of @c cw_a_weight is set to twice the value of the multiplier + * scale, ensuring that the M value is accurately encoded. This defaults to 10 when in RGBM mode, + * matching the default scale factor. + */ +static const unsigned int ASTCENC_FLG_MAP_RGBM = 1 << 6; + /** * @brief The bit mask of all valid flags. */ static const unsigned int ASTCENC_ALL_FLAGS = - ASTCENC_FLG_MAP_MASK | ASTCENC_FLG_MAP_NORMAL | ASTCENC_FLG_MAP_RGBM | ASTCENC_FLG_USE_ALPHA_WEIGHT | ASTCENC_FLG_USE_PERCEPTUAL | + ASTCENC_FLG_USE_DECODE_UNORM8 | ASTCENC_FLG_DECOMPRESS_ONLY | ASTCENC_FLG_SELF_DECOMPRESS_ONLY; @@ -452,7 +473,7 @@ struct astcenc_config * * It is recommended that this is set to 1 when using FLG_USE_ALPHA_WEIGHT on a texture that * will be sampled using linear texture filtering to minimize color bleed out of transparent - * texels that are adjcent to non-transparent texels. + * texels that are adjacent to non-transparent texels. */ unsigned int a_scale_radius; @@ -467,11 +488,25 @@ struct astcenc_config unsigned int tune_partition_count_limit; /** - * @brief The maximum number of partitions searched (-partitionindexlimit). + * @brief The maximum number of partitions searched (-2partitionindexlimit). + * + * Valid values are between 1 and 1024. + */ + unsigned int tune_2partition_index_limit; + + /** + * @brief The maximum number of partitions searched (-3partitionindexlimit). + * + * Valid values are between 1 and 1024. + */ + unsigned int tune_3partition_index_limit; + + /** + * @brief The maximum number of partitions searched (-4partitionindexlimit). * * Valid values are between 1 and 1024. */ - unsigned int tune_partition_index_limit; + unsigned int tune_4partition_index_limit; /** * @brief The maximum centile for block modes searched (-blockmodelimit). @@ -491,63 +526,87 @@ struct astcenc_config /** * @brief The number of trial candidates per mode search (-candidatelimit). * - * Valid values are between 1 and TUNE_MAX_TRIAL_CANDIDATES (default 4). + * Valid values are between 1 and TUNE_MAX_TRIAL_CANDIDATES. */ unsigned int tune_candidate_limit; /** - * @brief The dB threshold for stopping block search (-dblimit). + * @brief The number of trial partitionings per search (-2partitioncandidatelimit). * - * This option is ineffective for HDR textures. + * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES. */ - float tune_db_limit; + unsigned int tune_2partitioning_candidate_limit; + + /** + * @brief The number of trial partitionings per search (-3partitioncandidatelimit). + * + * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES. + */ + unsigned int tune_3partitioning_candidate_limit; + + /** + * @brief The number of trial partitionings per search (-4partitioncandidatelimit). + * + * Valid values are between 1 and TUNE_MAX_PARTITIONING_CANDIDATES. + */ + unsigned int tune_4partitioning_candidate_limit; /** - * @brief The amount of overshoot needed to early-out mode 0 fast path. + * @brief The dB threshold for stopping block search (-dblimit). * - * We have a fast-path for mode 0 (1 partition, 1 plane) which uses only essential block modes - * as an initital search. This can short-cut compression for simple blocks, but to avoid - * shortcutting too much we* force this to overshoot the MSE threshold needed to hit the - * block-local db_limit e.g. 1.0 = no overshoot, 2.0 = need half the error to trigger. + * This option is ineffective for HDR textures. */ - float tune_mode0_mse_overshoot; + float tune_db_limit; /** - * @brief The amount of overshoot needed to early-out refinement. + * @brief The amount of MSE overshoot needed to early-out trials. + * + * The first early-out is for 1 partition, 1 plane trials, where we try a minimal encode using + * the high probability block modes. This can short-cut compression for simple blocks. * - * The codec will refine block candidates iteratively to improve the encoding, based on the - * @c tune_refinement_limit count. Earlier implementations will use all refinement iterations, - * even if the target threshold is reached. This tuning parameter allows an early out, but with - * an overshoot MSE threshold. Setting this to 1.0 will early-out as soon as the target is hit, - * but does reduce image quality vs the default behavior of over-refinement. + * The second early-out is for refinement trials, where we can exit refinement once quality is + * reached. */ - float tune_refinement_mse_overshoot; + float tune_mse_overshoot; /** - * @brief The threshold for skipping 2.2/3.1/3.2/4.1 trials (-2partitionlimitfactor). + * @brief The threshold for skipping 3.1/4.1 trials (-2partitionlimitfactor). * * This option is further scaled for normal maps, so it skips less often. */ - float tune_2_partition_early_out_limit_factor; + float tune_2partition_early_out_limit_factor; /** - * @brief The threshold for skipping 3.2/4.1 trials (-3partitionlimitfactor). + * @brief The threshold for skipping 4.1 trials (-3partitionlimitfactor). * * This option is further scaled for normal maps, so it skips less often. */ - float tune_3_partition_early_out_limit_factor; + float tune_3partition_early_out_limit_factor; /** * @brief The threshold for skipping two weight planes (-2planelimitcorrelation). * * This option is ineffective for normal maps. */ - float tune_2_plane_early_out_limit_correlation; + float tune_2plane_early_out_limit_correlation; /** - * @brief The threshold below which (inclusive) we stop testing low/high/low+high cutoffs. + * @brief The config enable for the mode0 fast-path search. + * + * If this is set to TUNE_MIN_TEXELS_MODE0 or higher then the early-out fast mode0 + * search is enabled. This option is ineffective for 3D block sizes. + */ + float tune_search_mode0_enable; + + /** + * @brief The progress callback, can be @c nullptr. + * + * If this is specified the codec will peridocially report progress for + * compression as a percentage between 0 and 100. The callback is called from one + * of the compressor threads, so doing significant work in the callback will + * reduce compression performance. */ - unsigned int tune_low_weight_count_limit; + astcenc_progress_callback progress_callback; #if defined(ASTCENC_DIAGNOSTICS) /** @@ -811,7 +870,7 @@ ASTCENC_PUBLIC void astcenc_context_free( * advanced content packaging pipelines. * * @param context Codec context. - * @param data One block of compressesd ASTC data. + * @param data One block of compressed ASTC data. * @param info The output info structure to populate. * * @return @c ASTCENC_SUCCESS if the block was decoded, or an error otherwise. Note that this diff --git a/Source/astcenc_averages_and_directions.cpp b/Source/astcenc_averages_and_directions.cpp index 2ceb83d..dcff0d2 100644 --- a/Source/astcenc_averages_and_directions.cpp +++ b/Source/astcenc_averages_and_directions.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -390,8 +390,6 @@ void compute_avgs_and_dirs_4_comp( const image_block& blk, partition_metrics pm[BLOCK_MAX_PARTITIONS] ) { - float texel_weight = hadd_s(blk.channel_weight) / 4.0f; - int partition_count = pi.partition_count; promise(partition_count > 0); @@ -434,11 +432,6 @@ void compute_avgs_and_dirs_4_comp( sum_wp += select(zero, texel_datum, tdm3); } - sum_xp = sum_xp * texel_weight; - sum_yp = sum_yp * texel_weight; - sum_zp = sum_zp * texel_weight; - sum_wp = sum_wp * texel_weight; - vfloat4 prod_xp = dot(sum_xp, sum_xp); vfloat4 prod_yp = dot(sum_yp, sum_yp); vfloat4 prod_zp = dot(sum_zp, sum_zp); @@ -473,8 +466,6 @@ void compute_avgs_and_dirs_3_comp( vfloat4 partition_averages[BLOCK_MAX_PARTITIONS]; compute_partition_averages_rgba(pi, blk, partition_averages); - float texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 2>()); - const float* data_vr = blk.data_r; const float* data_vg = blk.data_g; const float* data_vb = blk.data_b; @@ -482,8 +473,6 @@ void compute_avgs_and_dirs_3_comp( // TODO: Data-driven permute would be useful to avoid this ... if (omitted_component == 0) { - texel_weight = hadd_s(blk.channel_weight.swz<1, 2, 3>()); - partition_averages[0] = partition_averages[0].swz<1, 2, 3>(); partition_averages[1] = partition_averages[1].swz<1, 2, 3>(); partition_averages[2] = partition_averages[2].swz<1, 2, 3>(); @@ -495,8 +484,6 @@ void compute_avgs_and_dirs_3_comp( } else if (omitted_component == 1) { - texel_weight = hadd_s(blk.channel_weight.swz<0, 2, 3>()); - partition_averages[0] = partition_averages[0].swz<0, 2, 3>(); partition_averages[1] = partition_averages[1].swz<0, 2, 3>(); partition_averages[2] = partition_averages[2].swz<0, 2, 3>(); @@ -507,8 +494,6 @@ void compute_avgs_and_dirs_3_comp( } else if (omitted_component == 2) { - texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 3>()); - partition_averages[0] = partition_averages[0].swz<0, 1, 3>(); partition_averages[1] = partition_averages[1].swz<0, 1, 3>(); partition_averages[2] = partition_averages[2].swz<0, 1, 3>(); @@ -524,8 +509,6 @@ void compute_avgs_and_dirs_3_comp( partition_averages[3] = partition_averages[3].swz<0, 1, 2>(); } - texel_weight = texel_weight * (1.0f / 3.0f); - unsigned int partition_count = pi.partition_count; promise(partition_count > 0); @@ -563,10 +546,6 @@ void compute_avgs_and_dirs_3_comp( sum_zp += select(zero, texel_datum, tdm2); } - sum_xp = sum_xp * texel_weight; - sum_yp = sum_yp * texel_weight; - sum_zp = sum_zp * texel_weight; - vfloat4 prod_xp = dot(sum_xp, sum_xp); vfloat4 prod_yp = dot(sum_yp, sum_yp); vfloat4 prod_zp = dot(sum_zp, sum_zp); @@ -591,8 +570,6 @@ void compute_avgs_and_dirs_3_comp_rgb( const image_block& blk, partition_metrics pm[BLOCK_MAX_PARTITIONS] ) { - float texel_weight = hadd_s(blk.channel_weight.swz<0, 1, 2>()) * (1.0f / 3.0f); - unsigned int partition_count = pi.partition_count; promise(partition_count > 0); @@ -632,10 +609,6 @@ void compute_avgs_and_dirs_3_comp_rgb( sum_zp += select(zero, texel_datum, tdm2); } - sum_xp = sum_xp * texel_weight; - sum_yp = sum_yp * texel_weight; - sum_zp = sum_zp * texel_weight; - vfloat4 prod_xp = dot(sum_xp, sum_xp); vfloat4 prod_yp = dot(sum_yp, sum_yp); vfloat4 prod_zp = dot(sum_zp, sum_zp); @@ -662,7 +635,6 @@ void compute_avgs_and_dirs_2_comp( unsigned int component2, partition_metrics pm[BLOCK_MAX_PARTITIONS] ) { - float texel_weight; vfloat4 average; const float* data_vr = nullptr; @@ -670,7 +642,6 @@ void compute_avgs_and_dirs_2_comp( if (component1 == 0 && component2 == 1) { - texel_weight = hadd_s(blk.channel_weight.swz<0, 1>()) / 2.0f; average = blk.data_mean.swz<0, 1>(); data_vr = blk.data_r; @@ -678,7 +649,6 @@ void compute_avgs_and_dirs_2_comp( } else if (component1 == 0 && component2 == 2) { - texel_weight = hadd_s(blk.channel_weight.swz<0, 2>()) / 2.0f; average = blk.data_mean.swz<0, 2>(); data_vr = blk.data_r; @@ -688,7 +658,6 @@ void compute_avgs_and_dirs_2_comp( { assert(component1 == 1 && component2 == 2); - texel_weight = hadd_s(blk.channel_weight.swz<1, 2>()) / 2.0f; average = blk.data_mean.swz<1, 2>(); data_vr = blk.data_g; @@ -714,7 +683,7 @@ void compute_avgs_and_dirs_2_comp( average += vfloat2(data_vr[iwt], data_vg[iwt]); } - average = average * (1.0f / static_cast(texel_count)); + average = average / static_cast(texel_count); } pm[partition].avg = average; @@ -737,9 +706,6 @@ void compute_avgs_and_dirs_2_comp( sum_yp += select(zero, texel_datum, tdm1); } - sum_xp = sum_xp * texel_weight; - sum_yp = sum_yp * texel_weight; - vfloat4 prod_xp = dot(sum_xp, sum_xp); vfloat4 prod_yp = dot(sum_yp, sum_yp); @@ -759,8 +725,7 @@ void compute_error_squared_rgba( const image_block& blk, const processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS], const processed_line4 samec_plines[BLOCK_MAX_PARTITIONS], - float uncor_lengths[BLOCK_MAX_PARTITIONS], - float samec_lengths[BLOCK_MAX_PARTITIONS], + float line_lengths[BLOCK_MAX_PARTITIONS], float& uncor_error, float& samec_error ) { @@ -774,12 +739,6 @@ void compute_error_squared_rgba( { const uint8_t *texel_indexes = pi.texels_of_partition[partition]; - float uncor_loparam = 1e10f; - float uncor_hiparam = -1e10f; - - float samec_loparam = 1e10f; - float samec_hiparam = -1e10f; - processed_line4 l_uncor = uncor_plines[partition]; processed_line4 l_samec = samec_plines[partition]; @@ -807,9 +766,6 @@ void compute_error_squared_rgba( vfloat uncor_loparamv(1e10f); vfloat uncor_hiparamv(-1e10f); - vfloat samec_loparamv(1e10f); - vfloat samec_hiparamv(-1e10f); - vfloat ew_r(blk.channel_weight.lane<0>()); vfloat ew_g(blk.channel_weight.lane<1>()); vfloat ew_b(blk.channel_weight.lane<2>()); @@ -822,17 +778,17 @@ void compute_error_squared_rgba( for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH) { vmask mask = lane_ids < vint(texel_count); - vint texel_idxs(&(texel_indexes[i])); + vint texel_idxs(texel_indexes + i); vfloat data_r = gatherf(blk.data_r, texel_idxs); vfloat data_g = gatherf(blk.data_g, texel_idxs); vfloat data_b = gatherf(blk.data_b, texel_idxs); vfloat data_a = gatherf(blk.data_a, texel_idxs); - vfloat uncor_param = (data_r * l_uncor_bs0) - + (data_g * l_uncor_bs1) - + (data_b * l_uncor_bs2) - + (data_a * l_uncor_bs3); + vfloat uncor_param = (data_r * l_uncor_bs0) + + (data_g * l_uncor_bs1) + + (data_b * l_uncor_bs2) + + (data_a * l_uncor_bs3); uncor_loparamv = min(uncor_param, uncor_loparamv); uncor_hiparamv = max(uncor_param, uncor_hiparamv); @@ -859,9 +815,6 @@ void compute_error_squared_rgba( + (data_b * l_samec_bs2) + (data_a * l_samec_bs3); - samec_loparamv = min(samec_param, samec_loparamv); - samec_hiparamv = max(samec_param, samec_hiparamv); - vfloat samec_dist0 = samec_param * l_samec_bs0 - data_r; vfloat samec_dist1 = samec_param * l_samec_bs1 - data_g; vfloat samec_dist2 = samec_param * l_samec_bs2 - data_b; @@ -877,18 +830,9 @@ void compute_error_squared_rgba( lane_ids += vint(ASTCENC_SIMD_WIDTH); } - uncor_loparam = hmin_s(uncor_loparamv); - uncor_hiparam = hmax_s(uncor_hiparamv); - - samec_loparam = hmin_s(samec_loparamv); - samec_hiparam = hmax_s(samec_hiparamv); - - float uncor_linelen = uncor_hiparam - uncor_loparam; - float samec_linelen = samec_hiparam - samec_loparam; - // Turn very small numbers and NaNs into a small number - uncor_lengths[partition] = astc::max(uncor_linelen, 1e-7f); - samec_lengths[partition] = astc::max(samec_linelen, 1e-7f); + float uncor_linelen = hmax_s(uncor_hiparamv) - hmin_s(uncor_loparamv); + line_lengths[partition] = astc::max(uncor_linelen, 1e-7f); } uncor_error = hadd_s(uncor_errorsumv); @@ -916,19 +860,9 @@ void compute_error_squared_rgb( unsigned int texel_count = pi.partition_texel_count[partition]; promise(texel_count > 0); - float uncor_loparam = 1e10f; - float uncor_hiparam = -1e10f; - - float samec_loparam = 1e10f; - float samec_hiparam = -1e10f; - processed_line3 l_uncor = pl.uncor_pline; processed_line3 l_samec = pl.samec_pline; - // This implementation is an example vectorization of this function. - // It works for - the codec is a 2-4% faster than not vectorizing - but - // the benefit is limited by the use of gathers and register pressure - // Vectorize some useful scalar inputs vfloat l_uncor_bs0(l_uncor.bs.lane<0>()); vfloat l_uncor_bs1(l_uncor.bs.lane<1>()); @@ -947,9 +881,6 @@ void compute_error_squared_rgb( vfloat uncor_loparamv(1e10f); vfloat uncor_hiparamv(-1e10f); - vfloat samec_loparamv(1e10f); - vfloat samec_hiparamv(-1e10f); - vfloat ew_r(blk.channel_weight.lane<0>()); vfloat ew_g(blk.channel_weight.lane<1>()); vfloat ew_b(blk.channel_weight.lane<2>()); @@ -961,15 +892,15 @@ void compute_error_squared_rgb( for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH) { vmask mask = lane_ids < vint(texel_count); - vint texel_idxs(&(texel_indexes[i])); + vint texel_idxs(texel_indexes + i); vfloat data_r = gatherf(blk.data_r, texel_idxs); vfloat data_g = gatherf(blk.data_g, texel_idxs); vfloat data_b = gatherf(blk.data_b, texel_idxs); - vfloat uncor_param = (data_r * l_uncor_bs0) - + (data_g * l_uncor_bs1) - + (data_b * l_uncor_bs2); + vfloat uncor_param = (data_r * l_uncor_bs0) + + (data_g * l_uncor_bs1) + + (data_b * l_uncor_bs2); uncor_loparamv = min(uncor_param, uncor_loparamv); uncor_hiparamv = max(uncor_param, uncor_hiparamv); @@ -992,9 +923,6 @@ void compute_error_squared_rgb( + (data_g * l_samec_bs1) + (data_b * l_samec_bs2); - samec_loparamv = min(samec_param, samec_loparamv); - samec_hiparamv = max(samec_param, samec_hiparamv); - vfloat samec_dist0 = samec_param * l_samec_bs0 - data_r; vfloat samec_dist1 = samec_param * l_samec_bs1 - data_g; vfloat samec_dist2 = samec_param * l_samec_bs2 - data_b; @@ -1008,18 +936,9 @@ void compute_error_squared_rgb( lane_ids += vint(ASTCENC_SIMD_WIDTH); } - uncor_loparam = hmin_s(uncor_loparamv); - uncor_hiparam = hmax_s(uncor_hiparamv); - - samec_loparam = hmin_s(samec_loparamv); - samec_hiparam = hmax_s(samec_hiparamv); - - float uncor_linelen = uncor_hiparam - uncor_loparam; - float samec_linelen = samec_hiparam - samec_loparam; - // Turn very small numbers and NaNs into a small number - pl.uncor_line_len = astc::max(uncor_linelen, 1e-7f); - pl.samec_line_len = astc::max(samec_linelen, 1e-7f); + float uncor_linelen = hmax_s(uncor_hiparamv) - hmin_s(uncor_loparamv); + pl.line_length = astc::max(uncor_linelen, 1e-7f); } uncor_error = hadd_s(uncor_errorsumv); diff --git a/Source/astcenc_block_sizes.cpp b/Source/astcenc_block_sizes.cpp index 84d9e34..3f39543 100644 --- a/Source/astcenc_block_sizes.cpp +++ b/Source/astcenc_block_sizes.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -330,17 +330,17 @@ static void init_decimation_info_2d( for (unsigned int j = 0; j < wb.weight_count_of_texel[i]; j++) { - di.texel_weights_int_4t[j][i] = wb.weights_of_texel[i][j]; - di.texel_weights_float_4t[j][i] = static_cast(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM); - di.texel_weights_4t[j][i] = wb.grid_weights_of_texel[i][j]; + di.texel_weight_contribs_int_tr[j][i] = wb.weights_of_texel[i][j]; + di.texel_weight_contribs_float_tr[j][i] = static_cast(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM); + di.texel_weights_tr[j][i] = wb.grid_weights_of_texel[i][j]; } // Init all 4 entries so we can rely on zeros for vectorization for (unsigned int j = wb.weight_count_of_texel[i]; j < 4; j++) { - di.texel_weights_int_4t[j][i] = 0; - di.texel_weights_float_4t[j][i] = 0.0f; - di.texel_weights_4t[j][i] = 0; + di.texel_weight_contribs_int_tr[j][i] = 0; + di.texel_weight_contribs_float_tr[j][i] = 0.0f; + di.texel_weights_tr[j][i] = 0; } } @@ -356,43 +356,30 @@ static void init_decimation_info_2d( uint8_t texel = wb.texels_of_weight[i][j]; // Create transposed versions of these for better vectorization - di.weight_texel[j][i] = texel; - di.weights_flt[j][i] = static_cast(wb.texel_weights_of_weight[i][j]); + di.weight_texels_tr[j][i] = texel; + di.weights_texel_contribs_tr[j][i] = static_cast(wb.texel_weights_of_weight[i][j]); - // perform a layer of array unrolling. An aspect of this unrolling is that - // one of the texel-weight indexes is an identity-mapped index; we will use this - // fact to reorder the indexes so that the first one is the identity index. - int swap_idx = -1; + // Store the per-texel contribution of this weight for each texel it contributes to + di.texel_contrib_for_weight[j][i] = 0.0f; for (unsigned int k = 0; k < 4; k++) { - uint8_t dttw = di.texel_weights_4t[k][texel]; - float dttwf = di.texel_weights_float_4t[k][texel]; + uint8_t dttw = di.texel_weights_tr[k][texel]; + float dttwf = di.texel_weight_contribs_float_tr[k][texel]; if (dttw == i && dttwf != 0.0f) { - swap_idx = k; + di.texel_contrib_for_weight[j][i] = di.texel_weight_contribs_float_tr[k][texel]; + break; } - di.texel_weights_texel[i][j][k] = dttw; - di.texel_weights_float_texel[i][j][k] = dttwf; - } - - if (swap_idx != 0) - { - uint8_t vi = di.texel_weights_texel[i][j][0]; - float vf = di.texel_weights_float_texel[i][j][0]; - di.texel_weights_texel[i][j][0] = di.texel_weights_texel[i][j][swap_idx]; - di.texel_weights_float_texel[i][j][0] = di.texel_weights_float_texel[i][j][swap_idx]; - di.texel_weights_texel[i][j][swap_idx] = vi; - di.texel_weights_float_texel[i][j][swap_idx] = vf; } } // Initialize array tail so we can over-fetch with SIMD later to avoid loop tails // Match last texel in active lane in SIMD group, for better gathers - uint8_t last_texel = di.weight_texel[texel_count_wt - 1][i]; + uint8_t last_texel = di.weight_texels_tr[texel_count_wt - 1][i]; for (unsigned int j = texel_count_wt; j < max_texel_count_of_weight; j++) { - di.weight_texel[j][i] = last_texel; - di.weights_flt[j][i] = 0.0f; + di.weight_texels_tr[j][i] = last_texel; + di.weights_texel_contribs_tr[j][i] = 0.0f; } } @@ -404,16 +391,16 @@ static void init_decimation_info_2d( for (unsigned int j = 0; j < 4; j++) { - di.texel_weights_float_4t[j][i] = 0; - di.texel_weights_4t[j][i] = 0; - di.texel_weights_int_4t[j][i] = 0; + di.texel_weight_contribs_float_tr[j][i] = 0; + di.texel_weights_tr[j][i] = 0; + di.texel_weight_contribs_int_tr[j][i] = 0; } } // Initialize array tail so we can over-fetch with SIMD later to avoid loop tails // Match last texel in active lane in SIMD group, for better gathers unsigned int last_texel_count_wt = wb.texel_count_of_weight[weights_per_block - 1]; - uint8_t last_texel = di.weight_texel[last_texel_count_wt - 1][weights_per_block - 1]; + uint8_t last_texel = di.weight_texels_tr[last_texel_count_wt - 1][weights_per_block - 1]; unsigned int weights_per_block_simd = round_up_to_simd_multiple_vla(weights_per_block); for (unsigned int i = weights_per_block; i < weights_per_block_simd; i++) @@ -422,8 +409,8 @@ static void init_decimation_info_2d( for (unsigned int j = 0; j < max_texel_count_of_weight; j++) { - di.weight_texel[j][i] = last_texel; - di.weights_flt[j][i] = 0.0f; + di.weight_texels_tr[j][i] = last_texel; + di.weights_texel_contribs_tr[j][i] = 0.0f; } } @@ -600,16 +587,16 @@ static void init_decimation_info_3d( // Init all 4 entries so we can rely on zeros for vectorization for (unsigned int j = 0; j < 4; j++) { - di.texel_weights_int_4t[j][i] = 0; - di.texel_weights_float_4t[j][i] = 0.0f; - di.texel_weights_4t[j][i] = 0; + di.texel_weight_contribs_int_tr[j][i] = 0; + di.texel_weight_contribs_float_tr[j][i] = 0.0f; + di.texel_weights_tr[j][i] = 0; } for (unsigned int j = 0; j < wb.weight_count_of_texel[i]; j++) { - di.texel_weights_int_4t[j][i] = wb.weights_of_texel[i][j]; - di.texel_weights_float_4t[j][i] = static_cast(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM); - di.texel_weights_4t[j][i] = wb.grid_weights_of_texel[i][j]; + di.texel_weight_contribs_int_tr[j][i] = wb.weights_of_texel[i][j]; + di.texel_weight_contribs_float_tr[j][i] = static_cast(wb.weights_of_texel[i][j]) * (1.0f / WEIGHTS_TEXEL_SUM); + di.texel_weights_tr[j][i] = wb.grid_weights_of_texel[i][j]; } } @@ -625,43 +612,30 @@ static void init_decimation_info_3d( unsigned int texel = wb.texels_of_weight[i][j]; // Create transposed versions of these for better vectorization - di.weight_texel[j][i] = static_cast(texel); - di.weights_flt[j][i] = static_cast(wb.texel_weights_of_weight[i][j]); + di.weight_texels_tr[j][i] = static_cast(texel); + di.weights_texel_contribs_tr[j][i] = static_cast(wb.texel_weights_of_weight[i][j]); - // perform a layer of array unrolling. An aspect of this unrolling is that - // one of the texel-weight indexes is an identity-mapped index; we will use this - // fact to reorder the indexes so that the first one is the identity index. - int swap_idx = -1; + // Store the per-texel contribution of this weight for each texel it contributes to + di.texel_contrib_for_weight[j][i] = 0.0f; for (unsigned int k = 0; k < 4; k++) { - uint8_t dttw = di.texel_weights_4t[k][texel]; - float dttwf = di.texel_weights_float_4t[k][texel]; + uint8_t dttw = di.texel_weights_tr[k][texel]; + float dttwf = di.texel_weight_contribs_float_tr[k][texel]; if (dttw == i && dttwf != 0.0f) { - swap_idx = k; + di.texel_contrib_for_weight[j][i] = di.texel_weight_contribs_float_tr[k][texel]; + break; } - di.texel_weights_texel[i][j][k] = dttw; - di.texel_weights_float_texel[i][j][k] = dttwf; - } - - if (swap_idx != 0) - { - uint8_t vi = di.texel_weights_texel[i][j][0]; - float vf = di.texel_weights_float_texel[i][j][0]; - di.texel_weights_texel[i][j][0] = di.texel_weights_texel[i][j][swap_idx]; - di.texel_weights_float_texel[i][j][0] = di.texel_weights_float_texel[i][j][swap_idx]; - di.texel_weights_texel[i][j][swap_idx] = vi; - di.texel_weights_float_texel[i][j][swap_idx] = vf; } } // Initialize array tail so we can over-fetch with SIMD later to avoid loop tails // Match last texel in active lane in SIMD group, for better gathers - uint8_t last_texel = di.weight_texel[texel_count_wt - 1][i]; + uint8_t last_texel = di.weight_texels_tr[texel_count_wt - 1][i]; for (unsigned int j = texel_count_wt; j < max_texel_count_of_weight; j++) { - di.weight_texel[j][i] = last_texel; - di.weights_flt[j][i] = 0.0f; + di.weight_texels_tr[j][i] = last_texel; + di.weights_texel_contribs_tr[j][i] = 0.0f; } } @@ -673,16 +647,16 @@ static void init_decimation_info_3d( for (unsigned int j = 0; j < 4; j++) { - di.texel_weights_float_4t[j][i] = 0; - di.texel_weights_4t[j][i] = 0; - di.texel_weights_int_4t[j][i] = 0; + di.texel_weight_contribs_float_tr[j][i] = 0; + di.texel_weights_tr[j][i] = 0; + di.texel_weight_contribs_int_tr[j][i] = 0; } } // Initialize array tail so we can over-fetch with SIMD later to avoid loop tails // Match last texel in active lane in SIMD group, for better gathers int last_texel_count_wt = wb.texel_count_of_weight[weights_per_block - 1]; - uint8_t last_texel = di.weight_texel[last_texel_count_wt - 1][weights_per_block - 1]; + uint8_t last_texel = di.weight_texels_tr[last_texel_count_wt - 1][weights_per_block - 1]; unsigned int weights_per_block_simd = round_up_to_simd_multiple_vla(weights_per_block); for (unsigned int i = weights_per_block; i < weights_per_block_simd; i++) @@ -691,8 +665,8 @@ static void init_decimation_info_3d( for (int j = 0; j < max_texel_count_of_weight; j++) { - di.weight_texel[j][i] = last_texel; - di.weights_flt[j][i] = 0.0f; + di.weight_texels_tr[j][i] = last_texel; + di.weights_texel_contribs_tr[j][i] = 0.0f; } } @@ -802,8 +776,8 @@ static void construct_dt_entry_2d( assert(maxprec_1plane >= 0 || maxprec_2planes >= 0); bsd.decimation_modes[index].maxprec_1plane = static_cast(maxprec_1plane); bsd.decimation_modes[index].maxprec_2planes = static_cast(maxprec_2planes); - bsd.decimation_modes[index].ref_1_plane = 0; - bsd.decimation_modes[index].ref_2_planes = 0; + bsd.decimation_modes[index].refprec_1plane = 0; + bsd.decimation_modes[index].refprec_2planes = 0; } /** @@ -957,23 +931,24 @@ static void construct_block_size_descriptor_2d( } auto& bm = bsd.block_modes[packed_bm_idx]; + + bm.decimation_mode = static_cast(decimation_mode); + bm.quant_mode = static_cast(quant_mode); + bm.is_dual_plane = static_cast(is_dual_plane); + bm.weight_bits = static_cast(weight_bits); + bm.mode_index = static_cast(i); + auto& dm = bsd.decimation_modes[decimation_mode]; if (is_dual_plane) { - dm.ref_2_planes = 1; + dm.set_ref_2plane(bm.get_weight_quant_mode()); } else { - dm.ref_1_plane = 1; + dm.set_ref_1plane(bm.get_weight_quant_mode()); } - bm.decimation_mode = static_cast(decimation_mode); - bm.quant_mode = static_cast(quant_mode); - bm.is_dual_plane = static_cast(is_dual_plane); - bm.weight_bits = static_cast(weight_bits); - bm.mode_index = static_cast(i); - bsd.block_mode_packed_index[i] = static_cast(packed_bm_idx); packed_bm_idx++; @@ -1002,8 +977,8 @@ static void construct_block_size_descriptor_2d( { bsd.decimation_modes[i].maxprec_1plane = -1; bsd.decimation_modes[i].maxprec_2planes = -1; - bsd.decimation_modes[i].ref_1_plane = 0; - bsd.decimation_modes[i].ref_2_planes = 0; + bsd.decimation_modes[i].refprec_1plane = 0; + bsd.decimation_modes[i].refprec_2planes = 0; } // Determine the texels to use for kmeans clustering. @@ -1013,7 +988,7 @@ static void construct_block_size_descriptor_2d( } /** - * @brief Allocate block modes and decimation tables for a single £D block size. + * @brief Allocate block modes and decimation tables for a single 3D block size. * * TODO: This function doesn't include all of the heuristics that we use for 2D block sizes such as * the percentile mode cutoffs. If 3D becomes more widely used we should look at this. @@ -1088,8 +1063,8 @@ static void construct_block_size_descriptor_3d( bsd.decimation_modes[decimation_mode_count].maxprec_1plane = static_cast(maxprec_1plane); bsd.decimation_modes[decimation_mode_count].maxprec_2planes = static_cast(maxprec_2planes); - bsd.decimation_modes[decimation_mode_count].ref_1_plane = maxprec_1plane == -1 ? 0 : 1; - bsd.decimation_modes[decimation_mode_count].ref_2_planes = maxprec_2planes == -1 ? 0 : 1; + bsd.decimation_modes[decimation_mode_count].refprec_1plane = maxprec_1plane == -1 ? 0 : 0xFFFF; + bsd.decimation_modes[decimation_mode_count].refprec_2planes = maxprec_2planes == -1 ? 0 : 0xFFFF; decimation_mode_count++; } } @@ -1100,15 +1075,14 @@ static void construct_block_size_descriptor_3d( { bsd.decimation_modes[i].maxprec_1plane = -1; bsd.decimation_modes[i].maxprec_2planes = -1; - bsd.decimation_modes[i].ref_1_plane = 0; - bsd.decimation_modes[i].ref_2_planes = 0; + bsd.decimation_modes[i].refprec_1plane = 0; + bsd.decimation_modes[i].refprec_2planes = 0; } bsd.decimation_mode_count_always = 0; // Skipped for 3D modes bsd.decimation_mode_count_selected = decimation_mode_count; bsd.decimation_mode_count_all = decimation_mode_count; - // Construct the list of block formats // Construct the list of block formats referencing the decimation tables // Clear the list to a known-bad value diff --git a/Source/astcenc_color_quantize.cpp b/Source/astcenc_color_quantize.cpp index ed495fc..4ac0aff 100644 --- a/Source/astcenc_color_quantize.cpp +++ b/Source/astcenc_color_quantize.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -40,55 +40,117 @@ #include "astcenc_internal.h" +/** + * @brief Compute the error of an LDR RGB or RGBA encoding. + * + * @param uquant0 The original endpoint 0 color. + * @param uquant1 The original endpoint 1 color. + * @param quant0 The unpacked quantized endpoint 0 color. + * @param quant1 The unpacked quantized endpoint 1 color. + * + * @return The MSE of the encoding. + */ +static float get_rgba_encoding_error( + vfloat4 uquant0, + vfloat4 uquant1, + vint4 quant0, + vint4 quant1 +) { + vfloat4 error0 = uquant0 - int_to_float(quant0); + vfloat4 error1 = uquant1 - int_to_float(quant1); + return hadd_s(error0 * error0 + error1 * error1); +} + /** * @brief Determine the quantized value given a quantization level. * * @param quant_level The quantization level to use. - * @param value The value to convert. This may be outside of the 0-255 range and will be - * clamped before the value is looked up. + * @param value The value to convert. This must be in the 0-255 range. * - * @return The encoded quantized value. These are not necessarily in the order; the compressor - * scrambles the values slightly to make hardware implementation easier. + * @return The unpacked quantized value, returned in 0-255 range. */ -static inline int quant_color_clamp( +static inline uint8_t quant_color( quant_method quant_level, int value ) { - value = astc::clamp(value, 0, 255); - return color_quant_tables[quant_level - QUANT_6][value]; + int index = value * 2 + 1; + return color_unquant_to_uquant_tables[quant_level - QUANT_6][index]; } /** * @brief Determine the quantized value given a quantization level. * * @param quant_level The quantization level to use. - * @param value The value to convert. This may be outside of the 0-255 range and will be - * clamped before the value is looked up. + * @param value The value to convert. This must be in the 0-255 range. * - * @return The encoded quantized value. These are not necessarily in the order; the compressor - * scrambles the values slightly to make hardware implementation easier. + * @return The unpacked quantized value, returned in 0-255 range. */ -static inline int quant_color( +static inline vint4 quant_color3( quant_method quant_level, - int value + vint4 value ) { - return color_quant_tables[quant_level - QUANT_6][value]; + vint4 index = value * 2 + 1; + return vint4( + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<0>()], + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<1>()], + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<2>()], + 0); } /** - * @brief Determine the unquantized value given a quantization level. + * @brief Determine the quantized value given a quantization level and residual. * * @param quant_level The quantization level to use. - * @param value The value to convert. + * @param value The value to convert. This must be in the 0-255 range. + * @param valuef The original value before rounding, used to compute a residual. * - * @return The encoded quantized value. These are not necessarily in the order; the compressor - * scrambles the values slightly to make hardware implementation easier. + * @return The unpacked quantized value, returned in 0-255 range. */ -static inline int unquant_color( +static inline uint8_t quant_color( quant_method quant_level, - int value + int value, + float valuef +) { + int index = value * 2; + + // Compute the residual to determine if we should round down or up ties. + // Test should be residual >= 0, but empirical testing shows small bias helps. + float residual = valuef - static_cast(value); + if (residual >= -0.1f) + { + index++; + } + + return color_unquant_to_uquant_tables[quant_level - QUANT_6][index]; +} + +/** + * @brief Determine the quantized value given a quantization level and residual. + * + * @param quant_level The quantization level to use. + * @param value The value to convert. This must be in the 0-255 range. + * @param valuef The original value before rounding, used to compute a residual. + * + * @return The unpacked quantized value, returned in 0-255 range. + */ +static inline vint4 quant_color3( + quant_method quant_level, + vint4 value, + vfloat4 valuef ) { - return color_unquant_tables[quant_level - QUANT_6][value]; + vint4 index = value * 2; + + // Compute the residual to determine if we should round down or up ties. + // Test should be residual >= 0, but empirical testing shows small bias helps. + vfloat4 residual = valuef - int_to_float(value); + vmask4 mask = residual >= vfloat4(-0.1f); + index = select(index, index + 1, mask); + + return vint4( + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<0>()], + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<1>()], + color_unquant_to_uquant_tables[quant_level - QUANT_6][index.lane<2>()], + 0); } /** @@ -100,55 +162,33 @@ static inline int unquant_color( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r0, r1, g0, g1, b0, b1). + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. * @param quant_level The quantization level to use. */ static void quantize_rgb( vfloat4 color0, vfloat4 color1, - uint8_t output[6], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; + vint4 color0i, color1i; + vfloat4 nudge(0.2f); - float r0 = astc::clamp255f(color0.lane<0>() * scale); - float g0 = astc::clamp255f(color0.lane<1>() * scale); - float b0 = astc::clamp255f(color0.lane<2>() * scale); - - float r1 = astc::clamp255f(color1.lane<0>() * scale); - float g1 = astc::clamp255f(color1.lane<1>() * scale); - float b1 = astc::clamp255f(color1.lane<2>() * scale); - - int ri0, gi0, bi0, ri1, gi1, bi1; - int ri0b, gi0b, bi0b, ri1b, gi1b, bi1b; - float rgb0_addon = 0.5f; - float rgb1_addon = 0.5f; do { - ri0 = quant_color_clamp(quant_level, astc::flt2int_rd(r0 + rgb0_addon)); - gi0 = quant_color_clamp(quant_level, astc::flt2int_rd(g0 + rgb0_addon)); - bi0 = quant_color_clamp(quant_level, astc::flt2int_rd(b0 + rgb0_addon)); - ri1 = quant_color_clamp(quant_level, astc::flt2int_rd(r1 + rgb1_addon)); - gi1 = quant_color_clamp(quant_level, astc::flt2int_rd(g1 + rgb1_addon)); - bi1 = quant_color_clamp(quant_level, astc::flt2int_rd(b1 + rgb1_addon)); - - ri0b = unquant_color(quant_level, ri0); - gi0b = unquant_color(quant_level, gi0); - bi0b = unquant_color(quant_level, bi0); - ri1b = unquant_color(quant_level, ri1); - gi1b = unquant_color(quant_level, gi1); - bi1b = unquant_color(quant_level, bi1); - - rgb0_addon -= 0.2f; - rgb1_addon += 0.2f; - } while (ri0b + gi0b + bi0b > ri1b + gi1b + bi1b); - - output[0] = static_cast(ri0); - output[1] = static_cast(ri1); - output[2] = static_cast(gi0); - output[3] = static_cast(gi1); - output[4] = static_cast(bi0); - output[5] = static_cast(bi1); + vint4 color0q = max(float_to_int_rtn(color0), vint4(0)); + color0i = quant_color3(quant_level, color0q, color0); + color0 = color0 - nudge; + + vint4 color1q = min(float_to_int_rtn(color1), vint4(255)); + color1i = quant_color3(quant_level, color1q, color1); + color1 = color1 + nudge; + } while (hadd_rgb_s(color0i) > hadd_rgb_s(color1i)); + + color0_out = color0i; + color1_out = color1i; } /** @@ -161,24 +201,24 @@ static void quantize_rgb( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r0, r1, g0, g1, b0, b1, a0, a1). + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. * @param quant_level The quantization level to use. */ static void quantize_rgba( vfloat4 color0, vfloat4 color1, - uint8_t output[8], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; + quantize_rgb(color0, color1, color0_out, color1_out, quant_level); - float a0 = astc::clamp255f(color0.lane<3>() * scale); - float a1 = astc::clamp255f(color1.lane<3>() * scale); - - output[6] = quant_color(quant_level, astc::flt2int_rtn(a0)); - output[7] = quant_color(quant_level, astc::flt2int_rtn(a1)); + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); - quantize_rgb(color0, color1, output, quant_level); + color0_out.set_lane<3>(quant_color(quant_level, astc::flt2int_rtn(a0), a0)); + color1_out.set_lane<3>(quant_color(quant_level, astc::flt2int_rtn(a1), a1)); } /** @@ -188,7 +228,8 @@ static void quantize_rgba( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r1, r0, g1, g0, b1, b0). + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. @@ -196,63 +237,35 @@ static void quantize_rgba( static bool try_quantize_rgb_blue_contract( vfloat4 color0, vfloat4 color1, - uint8_t output[6], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; - - float r0 = color0.lane<0>() * scale; - float g0 = color0.lane<1>() * scale; - float b0 = color0.lane<2>() * scale; - - float r1 = color1.lane<0>() * scale; - float g1 = color1.lane<1>() * scale; - float b1 = color1.lane<2>() * scale; - - // Apply inverse blue-contraction. This can produce an overflow; which means BC cannot be used. - r0 += (r0 - b0); - g0 += (g0 - b0); - r1 += (r1 - b1); - g1 += (g1 - b1); - - if (r0 < 0.0f || r0 > 255.0f || g0 < 0.0f || g0 > 255.0f || b0 < 0.0f || b0 > 255.0f || - r1 < 0.0f || r1 > 255.0f || g1 < 0.0f || g1 > 255.0f || b1 < 0.0f || b1 > 255.0f) + // Apply inverse blue-contraction + color0 += color0 - color0.swz<2, 2, 2, 3>(); + color1 += color1 - color1.swz<2, 2, 2, 3>(); + + // If anything overflows BC cannot be used + vmask4 color0_error = (color0 < vfloat4(0.0f)) | (color0 > vfloat4(255.0f)); + vmask4 color1_error = (color1 < vfloat4(0.0f)) | (color1 > vfloat4(255.0f)); + if (any(color0_error | color1_error)) { return false; } - // Quantize the inverse-blue-contracted color - int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0)); - int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0)); - int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0)); - - int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1)); - int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1)); - int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1)); - - // Then unquantize again - int ru0 = unquant_color(quant_level, ri0); - int gu0 = unquant_color(quant_level, gi0); - int bu0 = unquant_color(quant_level, bi0); - - int ru1 = unquant_color(quant_level, ri1); - int gu1 = unquant_color(quant_level, gi1); - int bu1 = unquant_color(quant_level, bi1); + // Quantize the inverse blue-contracted color + vint4 color0i = quant_color3(quant_level, float_to_int_rtn(color0), color0); + vint4 color1i = quant_color3(quant_level, float_to_int_rtn(color1), color1); - // If color #1 is not larger than color #0 then blue-contraction cannot be used. Note that - // blue-contraction and quantization change this order, which is why we must test aftwards. - if (ru1 + gu1 + bu1 <= ru0 + gu0 + bu0) + // If color #1 is not larger than color #0 then blue-contraction cannot be used + // We must test afterwards because quantization can change the order + if (hadd_rgb_s(color1i) <= hadd_rgb_s(color0i)) { return false; } - output[0] = static_cast(ri1); - output[1] = static_cast(ri0); - output[2] = static_cast(gi1); - output[3] = static_cast(gi0); - output[4] = static_cast(bi1); - output[5] = static_cast(bi0); - + color0_out = color1i; + color1_out = color0i; return true; } @@ -263,26 +276,31 @@ static bool try_quantize_rgb_blue_contract( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r1, r0, g1, g0, b1, b0, a1, a0). + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. */ -static int try_quantize_rgba_blue_contract( +static bool try_quantize_rgba_blue_contract( vfloat4 color0, vfloat4 color1, - uint8_t output[8], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; + if (try_quantize_rgb_blue_contract(color0, color1, color0_out, color1_out, quant_level)) + { + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); - float a0 = astc::clamp255f(color0.lane<3>() * scale); - float a1 = astc::clamp255f(color1.lane<3>() * scale); + color0_out.set_lane<3>(quant_color(quant_level, astc::flt2int_rtn(a1), a1)); + color1_out.set_lane<3>(quant_color(quant_level, astc::flt2int_rtn(a0), a0)); - output[6] = quant_color(quant_level, astc::flt2int_rtn(a1)); - output[7] = quant_color(quant_level, astc::flt2int_rtn(a0)); + return true; + } - return try_quantize_rgb_blue_contract(color0, color1, output, quant_level); + return false; } /** @@ -294,7 +312,8 @@ static int try_quantize_rgba_blue_contract( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r0, r1, g0, g1, b0, b1). + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. @@ -302,277 +321,166 @@ static int try_quantize_rgba_blue_contract( static bool try_quantize_rgb_delta( vfloat4 color0, vfloat4 color1, - uint8_t output[6], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; - - float r0 = astc::clamp255f(color0.lane<0>() * scale); - float g0 = astc::clamp255f(color0.lane<1>() * scale); - float b0 = astc::clamp255f(color0.lane<2>() * scale); - - float r1 = astc::clamp255f(color1.lane<0>() * scale); - float g1 = astc::clamp255f(color1.lane<1>() * scale); - float b1 = astc::clamp255f(color1.lane<2>() * scale); - - // Transform r0 to unorm9 - int r0a = astc::flt2int_rtn(r0); - int g0a = astc::flt2int_rtn(g0); - int b0a = astc::flt2int_rtn(b0); - - r0a <<= 1; - g0a <<= 1; - b0a <<= 1; + // Transform color0 to unorm9 + vint4 color0a = float_to_int_rtn(color0); + color0.set_lane<3>(0.0f); + color0a = lsl<1>(color0a); // Mask off the top bit - int r0b = r0a & 0xFF; - int g0b = g0a & 0xFF; - int b0b = b0a & 0xFF; + vint4 color0b = color0a & 0xFF; // Quantize then unquantize in order to get a value that we take differences against - int r0be = quant_color(quant_level, r0b); - int g0be = quant_color(quant_level, g0b); - int b0be = quant_color(quant_level, b0b); - - r0b = unquant_color(quant_level, r0be); - g0b = unquant_color(quant_level, g0be); - b0b = unquant_color(quant_level, b0be); - - r0b |= r0a & 0x100; - g0b |= g0a & 0x100; - b0b |= b0a & 0x100; + vint4 color0be = quant_color3(quant_level, color0b); + color0b = color0be | (color0a & 0x100); // Get hold of the second value - int r1d = astc::flt2int_rtn(r1); - int g1d = astc::flt2int_rtn(g1); - int b1d = astc::flt2int_rtn(b1); - - r1d <<= 1; - g1d <<= 1; - b1d <<= 1; + vint4 color1d = float_to_int_rtn(color1); + color1d = lsl<1>(color1d); // ... and take differences - r1d -= r0b; - g1d -= g0b; - b1d -= b0b; + color1d = color1d - color0b; + color1d.set_lane<3>(0); // Check if the difference is too large to be encodable - if (r1d > 63 || g1d > 63 || b1d > 63 || r1d < -64 || g1d < -64 || b1d < -64) + if (any((color1d > vint4(63)) | (color1d < vint4(-64)))) { return false; } // Insert top bit of the base into the offset - r1d &= 0x7F; - g1d &= 0x7F; - b1d &= 0x7F; - - r1d |= (r0b & 0x100) >> 1; - g1d |= (g0b & 0x100) >> 1; - b1d |= (b0b & 0x100) >> 1; + color1d = color1d & 0x7F; + color1d = color1d | lsr<1>(color0b & 0x100); // Then quantize and unquantize; if this causes either top two bits to flip, then encoding fails // since we have then corrupted either the top bit of the base or the sign bit of the offset - int r1de = quant_color(quant_level, r1d); - int g1de = quant_color(quant_level, g1d); - int b1de = quant_color(quant_level, b1d); - - int r1du = unquant_color(quant_level, r1de); - int g1du = unquant_color(quant_level, g1de); - int b1du = unquant_color(quant_level, b1de); + vint4 color1de = quant_color3(quant_level, color1d); - if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0) + vint4 color_flips = (color1d ^ color1de) & 0xC0; + color_flips.set_lane<3>(0); + if (any(color_flips != vint4::zero())) { return false; } - // Check that the sum of the encoded offsets is nonnegative, else encoding fails - r1du &= 0x7f; - g1du &= 0x7f; - b1du &= 0x7f; - - if (r1du & 0x40) - { - r1du -= 0x80; - } - - if (g1du & 0x40) - { - g1du -= 0x80; - } - - if (b1du & 0x40) - { - b1du -= 0x80; - } - - if (r1du + g1du + b1du < 0) + // If the sum of offsets triggers blue-contraction then encoding fails + vint4 ep0 = color0be; + vint4 ep1 = color1de; + bit_transfer_signed(ep1, ep0); + if (hadd_rgb_s(ep1) < 0) { return false; } // Check that the offsets produce legitimate sums as well - r1du += r0b; - g1du += g0b; - b1du += b0b; - if (r1du < 0 || r1du > 0x1FF || g1du < 0 || g1du > 0x1FF || b1du < 0 || b1du > 0x1FF) + ep0 = ep0 + ep1; + if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF)))) { return false; } - output[0] = static_cast(r0be); - output[1] = static_cast(r1de); - output[2] = static_cast(g0be); - output[3] = static_cast(g1de); - output[4] = static_cast(b0be); - output[5] = static_cast(b1de); - + color0_out = color0be; + color1_out = color1de; return true; } +/** + * @brief Try to quantize an LDR RGB color using delta encoding and blue-contraction. + * + * Blue-contraction is only usable if encoded color 1 RGB is larger than color 0 RGB. + * + * @param color0 The input unquantized color0 endpoint. + * @param color1 The input unquantized color1 endpoint. + * @param[out] color0_out The output quantized color0 endpoint. + * @param[out] color1_out The output quantized color1 endpoint. + * @param quant_level The quantization level to use. + * + * @return Returns @c false on failure, @c true on success. + */ static bool try_quantize_rgb_delta_blue_contract( vfloat4 color0, vfloat4 color1, - uint8_t output[6], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { // Note: Switch around endpoint colors already at start - float scale = 1.0f / 257.0f; - - float r1 = color0.lane<0>() * scale; - float g1 = color0.lane<1>() * scale; - float b1 = color0.lane<2>() * scale; + std::swap(color0, color1); - float r0 = color1.lane<0>() * scale; - float g0 = color1.lane<1>() * scale; - float b0 = color1.lane<2>() * scale; + // Apply inverse blue-contraction + color0 += color0 - color0.swz<2, 2, 2, 3>(); + color1 += color1 - color1.swz<2, 2, 2, 3>(); - // Apply inverse blue-contraction. This can produce an overflow; which means BC cannot be used. - r0 += (r0 - b0); - g0 += (g0 - b0); - r1 += (r1 - b1); - g1 += (g1 - b1); - - if (r0 < 0.0f || r0 > 255.0f || g0 < 0.0f || g0 > 255.0f || b0 < 0.0f || b0 > 255.0f || - r1 < 0.0f || r1 > 255.0f || g1 < 0.0f || g1 > 255.0f || b1 < 0.0f || b1 > 255.0f) + // If anything overflows BC cannot be used + vmask4 color0_error = (color0 < vfloat4(0.0f)) | (color0 > vfloat4(255.0f)); + vmask4 color1_error = (color1 < vfloat4(0.0f)) | (color1 > vfloat4(255.0f)); + if (any(color0_error | color1_error)) { return false; } - // Transform r0 to unorm9 - int r0a = astc::flt2int_rtn(r0); - int g0a = astc::flt2int_rtn(g0); - int b0a = astc::flt2int_rtn(b0); - r0a <<= 1; - g0a <<= 1; - b0a <<= 1; + // Transform color0 to unorm9 + vint4 color0a = float_to_int_rtn(color0); + color0.set_lane<3>(0.0f); + color0a = lsl<1>(color0a); // Mask off the top bit - int r0b = r0a & 0xFF; - int g0b = g0a & 0xFF; - int b0b = b0a & 0xFF; - - // Quantize, then unquantize in order to get a value that we take differences against. - int r0be = quant_color(quant_level, r0b); - int g0be = quant_color(quant_level, g0b); - int b0be = quant_color(quant_level, b0b); - - r0b = unquant_color(quant_level, r0be); - g0b = unquant_color(quant_level, g0be); - b0b = unquant_color(quant_level, b0be); + vint4 color0b = color0a & 0xFF; - r0b |= r0a & 0x100; - g0b |= g0a & 0x100; - b0b |= b0a & 0x100; + // Quantize then unquantize in order to get a value that we take differences against + vint4 color0be = quant_color3(quant_level, color0b); + color0b = color0be | (color0a & 0x100); // Get hold of the second value - int r1d = astc::flt2int_rtn(r1); - int g1d = astc::flt2int_rtn(g1); - int b1d = astc::flt2int_rtn(b1); - - r1d <<= 1; - g1d <<= 1; - b1d <<= 1; + vint4 color1d = float_to_int_rtn(color1); + color1d = lsl<1>(color1d); - // .. and take differences! - r1d -= r0b; - g1d -= g0b; - b1d -= b0b; + // ... and take differences + color1d = color1d - color0b; + color1d.set_lane<3>(0); // Check if the difference is too large to be encodable - if (r1d > 63 || g1d > 63 || b1d > 63 || r1d < -64 || g1d < -64 || b1d < -64) + if (any((color1d > vint4(63)) | (color1d < vint4(-64)))) { return false; } // Insert top bit of the base into the offset - r1d &= 0x7F; - g1d &= 0x7F; - b1d &= 0x7F; - - r1d |= (r0b & 0x100) >> 1; - g1d |= (g0b & 0x100) >> 1; - b1d |= (b0b & 0x100) >> 1; - - // Then quantize and unquantize; if this causes any of the top two bits to flip, - // then encoding fails, since we have then corrupted either the top bit of the base - // or the sign bit of the offset. - int r1de = quant_color(quant_level, r1d); - int g1de = quant_color(quant_level, g1d); - int b1de = quant_color(quant_level, b1d); - - int r1du = unquant_color(quant_level, r1de); - int g1du = unquant_color(quant_level, g1de); - int b1du = unquant_color(quant_level, b1de); - - if (((r1d ^ r1du) | (g1d ^ g1du) | (b1d ^ b1du)) & 0xC0) - { - return false; - } + color1d = color1d & 0x7F; + color1d = color1d | lsr<1>(color0b & 0x100); - // Check that the sum of the encoded offsets is negative, else encoding fails - // Note that this is inverse of the test for non-blue-contracted RGB. - r1du &= 0x7f; - g1du &= 0x7f; - b1du &= 0x7f; - - if (r1du & 0x40) - { - r1du -= 0x80; - } - - if (g1du & 0x40) - { - g1du -= 0x80; - } + // Then quantize and unquantize; if this causes either top two bits to flip, then encoding fails + // since we have then corrupted either the top bit of the base or the sign bit of the offset + vint4 color1de = quant_color3(quant_level, color1d); - if (b1du & 0x40) + vint4 color_flips = (color1d ^ color1de) & 0xC0; + color_flips.set_lane<3>(0); + if (any(color_flips != vint4::zero())) { - b1du -= 0x80; + return false; } - if (r1du + g1du + b1du >= 0) + // If the sum of offsets does not trigger blue-contraction then encoding fails + vint4 ep0 = color0be; + vint4 ep1 = color1de; + bit_transfer_signed(ep1, ep0); + if (hadd_rgb_s(ep1) >= 0) { return false; } // Check that the offsets produce legitimate sums as well - r1du += r0b; - g1du += g0b; - b1du += b0b; - - if (r1du < 0 || r1du > 0x1FF || g1du < 0 || g1du > 0x1FF || b1du < 0 || b1du > 0x1FF) + ep0 = ep0 + ep1; + if (any((ep0 < vint4(0)) | (ep0 > vint4(0xFF)))) { return false; } - output[0] = static_cast(r0be); - output[1] = static_cast(r1de); - output[2] = static_cast(g0be); - output[3] = static_cast(g1de); - output[4] = static_cast(b0be); - output[5] = static_cast(b1de); - + color0_out = color0be; + color1_out = color1de; return true; } @@ -587,7 +495,8 @@ static bool try_quantize_rgb_delta_blue_contract( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (x, x, x, x, x, x, a0, a1). + * @param[out] color0_out The output quantized color0 endpoint; must preserve lane 0/1/2. + * @param[out] color1_out The output quantized color1 endpoint; must preserve lane 0/1/2. * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. @@ -595,19 +504,18 @@ static bool try_quantize_rgb_delta_blue_contract( static bool try_quantize_alpha_delta( vfloat4 color0, vfloat4 color1, - uint8_t output[8], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - float scale = 1.0f / 257.0f; - - float a0 = astc::clamp255f(color0.lane<3>() * scale); - float a1 = astc::clamp255f(color1.lane<3>() * scale); + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); int a0a = astc::flt2int_rtn(a0); a0a <<= 1; int a0b = a0a & 0xFF; int a0be = quant_color(quant_level, a0b); - a0b = unquant_color(quant_level, a0be); + a0b = a0be; a0b |= a0a & 0x100; int a1d = astc::flt2int_rtn(a1); a1d <<= 1; @@ -622,7 +530,7 @@ static bool try_quantize_alpha_delta( a1d |= (a0b & 0x100) >> 1; int a1de = quant_color(quant_level, a1d); - int a1du = unquant_color(quant_level, a1de); + int a1du = a1de; if ((a1d ^ a1du) & 0xC0) { return false; @@ -640,8 +548,8 @@ static bool try_quantize_alpha_delta( return false; } - output[6] = static_cast(a0be); - output[7] = static_cast(a1de); + color0_out.set_lane<3>(a0be); + color1_out.set_lane<3>(a1de); return true; } @@ -668,13 +576,11 @@ static bool try_quantize_luminance_alpha_delta( uint8_t output[4], quant_method quant_level ) { - float scale = 1.0f / 257.0f; + float l0 = hadd_rgb_s(color0) * (1.0f / 3.0f); + float l1 = hadd_rgb_s(color1) * (1.0f / 3.0f); - float l0 = astc::clamp255f(hadd_rgb_s(color0) * ((1.0f / 3.0f) * scale)); - float l1 = astc::clamp255f(hadd_rgb_s(color1) * ((1.0f / 3.0f) * scale)); - - float a0 = astc::clamp255f(color0.lane<3>() * scale); - float a1 = astc::clamp255f(color1.lane<3>() * scale); + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); int l0a = astc::flt2int_rtn(l0); int a0a = astc::flt2int_rtn(a0); @@ -685,8 +591,8 @@ static bool try_quantize_luminance_alpha_delta( int a0b = a0a & 0xFF; int l0be = quant_color(quant_level, l0b); int a0be = quant_color(quant_level, a0b); - l0b = unquant_color(quant_level, l0be); - a0b = unquant_color(quant_level, a0be); + l0b = l0be; + a0b = a0be; l0b |= l0a & 0x100; a0b |= a0a & 0x100; @@ -714,8 +620,8 @@ static bool try_quantize_luminance_alpha_delta( int l1de = quant_color(quant_level, l1d); int a1de = quant_color(quant_level, a1d); - int l1du = unquant_color(quant_level, l1de); - int a1du = unquant_color(quant_level, a1de); + int l1du = l1de; + int a1du = a1de; if ((l1d ^ l1du) & 0xC0) { @@ -772,7 +678,8 @@ static bool try_quantize_luminance_alpha_delta( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r0, r1, b0, b1, g0, g1, a0, a1). + * @param[out] color0_out The output quantized color0 endpoint + * @param[out] color1_out The output quantized color1 endpoint * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. @@ -780,14 +687,14 @@ static bool try_quantize_luminance_alpha_delta( static bool try_quantize_rgba_delta( vfloat4 color0, vfloat4 color1, - uint8_t output[8], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { - return try_quantize_rgb_delta(color0, color1, output, quant_level) && - try_quantize_alpha_delta(color0, color1, output, quant_level); + return try_quantize_rgb_delta(color0, color1, color0_out, color1_out, quant_level) && + try_quantize_alpha_delta(color0, color1, color0_out, color1_out, quant_level); } - /** * @brief Try to quantize an LDR RGBA color using delta and blue contract encoding. * @@ -799,7 +706,8 @@ static bool try_quantize_rgba_delta( * * @param color0 The input unquantized color0 endpoint. * @param color1 The input unquantized color1 endpoint. - * @param[out] output The output endpoints, returned as (r0, r1, b0, b1, g0, g1, a0, a1). + * @param[out] color0_out The output quantized color0 endpoint + * @param[out] color1_out The output quantized color1 endpoint * @param quant_level The quantization level to use. * * @return Returns @c false on failure, @c true on success. @@ -807,12 +715,13 @@ static bool try_quantize_rgba_delta( static bool try_quantize_rgba_delta_blue_contract( vfloat4 color0, vfloat4 color1, - uint8_t output[8], + vint4& color0_out, + vint4& color1_out, quant_method quant_level ) { // Note that we swap the color0 and color1 ordering for alpha to match RGB blue-contract - return try_quantize_rgb_delta_blue_contract(color0, color1, output, quant_level) && - try_quantize_alpha_delta(color1, color0, output, quant_level); + return try_quantize_rgb_delta_blue_contract(color0, color1, color0_out, color1_out, quant_level) && + try_quantize_alpha_delta(color1, color0, color0_out, color1_out, quant_level); } /** @@ -833,16 +742,12 @@ static void quantize_rgbs( float g = astc::clamp255f(color.lane<1>() * scale); float b = astc::clamp255f(color.lane<2>() * scale); - int ri = quant_color(quant_level, astc::flt2int_rtn(r)); - int gi = quant_color(quant_level, astc::flt2int_rtn(g)); - int bi = quant_color(quant_level, astc::flt2int_rtn(b)); - - int ru = unquant_color(quant_level, ri); - int gu = unquant_color(quant_level, gi); - int bu = unquant_color(quant_level, bi); + int ri = quant_color(quant_level, astc::flt2int_rtn(r), r); + int gi = quant_color(quant_level, astc::flt2int_rtn(g), g); + int bi = quant_color(quant_level, astc::flt2int_rtn(b), b); float oldcolorsum = hadd_rgb_s(color) * scale; - float newcolorsum = static_cast(ru + gu + bu); + float newcolorsum = static_cast(ri + gi + bi); float scalea = astc::clamp1f(color.lane<3>() * (oldcolorsum + 1e-10f) / (newcolorsum + 1e-10f)); int scale_idx = astc::flt2int_rtn(scalea * 256.0f); @@ -857,6 +762,8 @@ static void quantize_rgbs( /** * @brief Quantize an LDR RGBA color using scale encoding. * + * @param color0 The input unquantized color0 alpha endpoint. + * @param color1 The input unquantized color1 alpha endpoint. * @param color The input unquantized color endpoint and scale factor. * @param[out] output The output endpoints, returned as (r0, g0, b0, s, a0, a1). * @param quant_level The quantization level to use. @@ -868,13 +775,11 @@ static void quantize_rgbs_alpha( uint8_t output[6], quant_method quant_level ) { - float scale = 1.0f / 257.0f; + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); - float a0 = astc::clamp255f(color0.lane<3>() * scale); - float a1 = astc::clamp255f(color1.lane<3>() * scale); - - output[4] = quant_color(quant_level, astc::flt2int_rtn(a0)); - output[5] = quant_color(quant_level, astc::flt2int_rtn(a1)); + output[4] = quant_color(quant_level, astc::flt2int_rtn(a0), a0); + output[5] = quant_color(quant_level, astc::flt2int_rtn(a1), a1); quantize_rgbs(color, output, quant_level); } @@ -893,13 +798,8 @@ static void quantize_luminance( uint8_t output[2], quant_method quant_level ) { - float scale = 1.0f / 257.0f; - - color0 = color0 * scale; - color1 = color1 * scale; - - float lum0 = astc::clamp255f(hadd_rgb_s(color0) * (1.0f / 3.0f)); - float lum1 = astc::clamp255f(hadd_rgb_s(color1) * (1.0f / 3.0f)); + float lum0 = hadd_rgb_s(color0) * (1.0f / 3.0f); + float lum1 = hadd_rgb_s(color1) * (1.0f / 3.0f); if (lum0 > lum1) { @@ -908,8 +808,8 @@ static void quantize_luminance( lum1 = avg; } - output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0)); - output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1)); + output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0); + output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1); } /** @@ -926,59 +826,16 @@ static void quantize_luminance_alpha( uint8_t output[4], quant_method quant_level ) { - float scale = 1.0f / 257.0f; - - color0 = color0 * scale; - color1 = color1 * scale; - - float lum0 = astc::clamp255f(hadd_rgb_s(color0) * (1.0f / 3.0f)); - float lum1 = astc::clamp255f(hadd_rgb_s(color1) * (1.0f / 3.0f)); - - float a0 = astc::clamp255f(color0.lane<3>()); - float a1 = astc::clamp255f(color1.lane<3>()); - - // If endpoints are close then pull apart slightly; this gives > 8 bit normal map precision. - if (quant_level > 18) - { - if (fabsf(lum0 - lum1) < 3.0f) - { - if (lum0 < lum1) - { - lum0 -= 0.5f; - lum1 += 0.5f; - } - else - { - lum0 += 0.5f; - lum1 -= 0.5f; - } - - lum0 = astc::clamp255f(lum0); - lum1 = astc::clamp255f(lum1); - } - - if (fabsf(a0 - a1) < 3.0f) - { - if (a0 < a1) - { - a0 -= 0.5f; - a1 += 0.5f; - } - else - { - a0 += 0.5f; - a1 -= 0.5f; - } + float lum0 = hadd_rgb_s(color0) * (1.0f / 3.0f); + float lum1 = hadd_rgb_s(color1) * (1.0f / 3.0f); - a0 = astc::clamp255f(a0); - a1 = astc::clamp255f(a1); - } - } + float a0 = color0.lane<3>(); + float a1 = color1.lane<3>(); - output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0)); - output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1)); - output[2] = quant_color(quant_level, astc::flt2int_rtn(a0)); - output[3] = quant_color(quant_level, astc::flt2int_rtn(a1)); + output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0); + output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1); + output[2] = quant_color(quant_level, astc::flt2int_rtn(a0), a0); + output[3] = quant_color(quant_level, astc::flt2int_rtn(a1), a1); } /** @@ -987,33 +844,29 @@ static void quantize_luminance_alpha( * @param quant_level The quantization level to use. * @param value The input unquantized value. * @param[out] quant_value The quantized value. - * @param[out] unquant_value The unquantized value after quantization. */ static inline void quantize_and_unquantize_retain_top_two_bits( quant_method quant_level, uint8_t value, - uint8_t& quant_value, - uint8_t& unquant_value + uint8_t& quant_value ) { int perform_loop; uint8_t quantval; - uint8_t uquantval; do { quantval = quant_color(quant_level, value); - uquantval = unquant_color(quant_level, quantval); // Perform looping if the top two bits were modified by quant/unquant - perform_loop = (value & 0xC0) != (uquantval & 0xC0); + perform_loop = (value & 0xC0) != (quantval & 0xC0); - if ((uquantval & 0xC0) > (value & 0xC0)) + if ((quantval & 0xC0) > (value & 0xC0)) { // Quant/unquant rounded UP so that the top two bits changed; // decrement the input in hopes that this will avoid rounding up. value--; } - else if ((uquantval & 0xC0) < (value & 0xC0)) + else if ((quantval & 0xC0) < (value & 0xC0)) { // Quant/unquant rounded DOWN so that the top two bits changed; // decrement the input in hopes that this will avoid rounding down. @@ -1022,7 +875,6 @@ static inline void quantize_and_unquantize_retain_top_two_bits( } while (perform_loop); quant_value = quantval; - unquant_value = uquantval; } /** @@ -1030,34 +882,29 @@ static inline void quantize_and_unquantize_retain_top_two_bits( * * @param quant_level The quantization level to use. * @param value The input unquantized value. - * @param[out] quant_value The quantized value. - * @param[out] unquant_value The unquantized value after quantization. + * @param[out] quant_value The quantized value in 0-255 range. */ static inline void quantize_and_unquantize_retain_top_four_bits( quant_method quant_level, uint8_t value, - uint8_t& quant_value, - uint8_t& unquant_value + uint8_t& quant_value ) { uint8_t perform_loop; uint8_t quantval; - uint8_t uquantval; do { quantval = quant_color(quant_level, value); - uquantval = unquant_color(quant_level, quantval); - // Perform looping if the top four bits were modified by quant/unquant - perform_loop = (value & 0xF0) != (uquantval & 0xF0); + perform_loop = (value & 0xF0) != (quantval & 0xF0); - if ((uquantval & 0xF0) > (value & 0xF0)) + if ((quantval & 0xF0) > (value & 0xF0)) { // Quant/unquant rounded UP so that the top four bits changed; // decrement the input value in hopes that this will avoid rounding up. value--; } - else if ((uquantval & 0xF0) < (value & 0xF0)) + else if ((quantval & 0xF0) < (value & 0xF0)) { // Quant/unquant rounded DOWN so that the top four bits changed; // decrement the input value in hopes that this will avoid rounding down. @@ -1066,7 +913,6 @@ static inline void quantize_and_unquantize_retain_top_four_bits( } while (perform_loop); quant_value = quantval; - unquant_value = uquantval; } /** @@ -1177,11 +1023,10 @@ static void quantize_hdr_rgbo( r_lowbits |= (mode_enc & 3) << 6; uint8_t r_quantval; - uint8_t r_uquantval; quantize_and_unquantize_retain_top_two_bits( - quant_level, static_cast(r_lowbits), r_quantval, r_uquantval); + quant_level, static_cast(r_lowbits), r_quantval); - r_intval = (r_intval & ~0x3f) | (r_uquantval & 0x3f); + r_intval = (r_intval & ~0x3f) | (r_quantval & 0x3f); float r_fval = static_cast(r_intval) * mode_rscale; // Recompute G and B, then quantize and unquantize them @@ -1277,16 +1122,14 @@ static void quantize_hdr_rgbo( uint8_t g_quantval; uint8_t b_quantval; - uint8_t g_uquantval; - uint8_t b_uquantval; quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(g_lowbits), g_quantval, g_uquantval); + quant_level, static_cast(g_lowbits), g_quantval); quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(b_lowbits), b_quantval, b_uquantval); + quant_level, static_cast(b_lowbits), b_quantval); - g_intval = (g_intval & ~0x1f) | (g_uquantval & 0x1f); - b_intval = (b_intval & ~0x1f) | (b_uquantval & 0x1f); + g_intval = (g_intval & ~0x1f) | (g_quantval & 0x1f); + b_intval = (b_intval & ~0x1f) | (b_quantval & 0x1f); g_fval = static_cast(g_intval) * mode_rscale; b_fval = static_cast(b_intval) * mode_rscale; @@ -1350,10 +1193,9 @@ static void quantize_hdr_rgbo( s_lowbits |= bit4 << 7; uint8_t s_quantval; - uint8_t s_uquantval; quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(s_lowbits), s_quantval, s_uquantval); + quant_level, static_cast(s_lowbits), s_quantval); output[0] = r_quantval; output[1] = g_quantval; @@ -1393,9 +1235,8 @@ static void quantize_hdr_rgbo( for (uint8_t i = 0; i < 4; i++) { - uint8_t dummy; quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(encvals[i]), output[i], dummy); + quant_level, static_cast(encvals[i]), output[i]); } return; @@ -1535,7 +1376,7 @@ static void quantize_hdr_rgb( int a_lowbits = a_intval & 0xFF; int a_quantval = quant_color(quant_level, a_lowbits); - int a_uquantval = unquant_color(quant_level, a_quantval); + int a_uquantval = a_quantval; a_intval = (a_intval & ~0xFF) | a_uquantval; float a_fval = static_cast(a_intval) * mode_rscale; @@ -1556,12 +1397,11 @@ static void quantize_hdr_rgb( c_lowbits |= (a_intval & 0x100) >> 2; uint8_t c_quantval; - uint8_t c_uquantval; quantize_and_unquantize_retain_top_two_bits( - quant_level, static_cast(c_lowbits), c_quantval, c_uquantval); + quant_level, static_cast(c_lowbits), c_quantval); - c_intval = (c_intval & ~0x3F) | (c_uquantval & 0x3F); + c_intval = (c_intval & ~0x3F) | (c_quantval & 0x3F); c_fval = static_cast(c_intval) * mode_rscale; // Recompute B0 and B1, then quantize and unquantize them @@ -1625,16 +1465,14 @@ static void quantize_hdr_rgb( uint8_t b0_quantval; uint8_t b1_quantval; - uint8_t b0_uquantval; - uint8_t b1_uquantval; quantize_and_unquantize_retain_top_two_bits( - quant_level, static_cast(b0_lowbits), b0_quantval, b0_uquantval); + quant_level, static_cast(b0_lowbits), b0_quantval); quantize_and_unquantize_retain_top_two_bits( - quant_level, static_cast(b1_lowbits), b1_quantval, b1_uquantval); + quant_level, static_cast(b1_lowbits), b1_quantval); - b0_intval = (b0_intval & ~0x3f) | (b0_uquantval & 0x3f); - b1_intval = (b1_intval & ~0x3f) | (b1_uquantval & 0x3f); + b0_intval = (b0_intval & ~0x3f) | (b0_quantval & 0x3f); + b1_intval = (b1_intval & ~0x3f) | (b1_quantval & 0x3f); b0_fval = static_cast(b0_intval) * mode_rscale; b1_fval = static_cast(b1_intval) * mode_rscale; @@ -1722,13 +1560,11 @@ static void quantize_hdr_rgb( uint8_t d0_quantval; uint8_t d1_quantval; - uint8_t d0_uquantval; - uint8_t d1_uquantval; quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(d0_lowbits), d0_quantval, d0_uquantval); + quant_level, static_cast(d0_lowbits), d0_quantval); quantize_and_unquantize_retain_top_four_bits( - quant_level, static_cast(d1_lowbits), d1_quantval, d1_uquantval); + quant_level, static_cast(d1_lowbits), d1_quantval); output[0] = static_cast(a_quantval); output[1] = c_quantval; @@ -1764,10 +1600,9 @@ static void quantize_hdr_rgb( for (int i = 4; i < 6; i++) { - uint8_t dummy; int idx = astc::flt2int_rtn(vals[i] * 1.0f / 512.0f) + 128; quantize_and_unquantize_retain_top_two_bits( - quant_level, static_cast(idx), output[i], dummy); + quant_level, static_cast(idx), output[i]); } return; @@ -1792,8 +1627,8 @@ static void quantize_hdr_rgb_ldr_alpha( float a0 = astc::clamp255f(color0.lane<3>() * scale); float a1 = astc::clamp255f(color1.lane<3>() * scale); - output[6] = quant_color(quant_level, astc::flt2int_rtn(a0)); - output[7] = quant_color(quant_level, astc::flt2int_rtn(a1)); + output[6] = quant_color(quant_level, astc::flt2int_rtn(a0), a0); + output[7] = quant_color(quant_level, astc::flt2int_rtn(a1), a1); quantize_hdr_rgb(color0, color1, output, quant_level); } @@ -1919,7 +1754,7 @@ static bool try_quantize_hdr_luminance_small_range( v0 = lowval & 0x7F; v0e = quant_color(quant_level, v0); - v0d = unquant_color(quant_level, v0e); + v0d = v0e; if (v0d < 0x80) { @@ -1929,7 +1764,7 @@ static bool try_quantize_hdr_luminance_small_range( { v1 = ((lowval >> 3) & 0xF0) | diffval; v1e = quant_color(quant_level, v1); - v1d = unquant_color(quant_level, v1e); + v1d = v1e; if ((v1d & 0xF0) == (v1 & 0xF0)) { output[0] = static_cast(v0e); @@ -1948,7 +1783,7 @@ static bool try_quantize_hdr_luminance_small_range( v0 = (lowval & 0x7F) | 0x80; v0e = quant_color(quant_level, v0); - v0d = unquant_color(quant_level, v0e); + v0d = v0e; if ((v0d & 0x80) == 0) { return false; @@ -1963,7 +1798,7 @@ static bool try_quantize_hdr_luminance_small_range( v1 = ((lowval >> 2) & 0xE0) | diffval; v1e = quant_color(quant_level, v1); - v1d = unquant_color(quant_level, v1e); + v1d = v1e; if ((v1d & 0xE0) != (v1 & 0xE0)) { return false; @@ -2007,7 +1842,7 @@ static void quantize_hdr_alpha( v6 = (val0 & 0x7F) | ((i & 1) << 7); v6e = quant_color(quant_level, v6); - v6d = unquant_color(quant_level, v6e); + v6d = v6e; if ((v6 ^ v6d) & 0x80) { @@ -2026,7 +1861,7 @@ static void quantize_hdr_alpha( v7 = ((i & 2) << 6) | ((val0 >> 7) << (6 - i)) | (diffval & mask); v7e = quant_color(quant_level, v7); - v7d = unquant_color(quant_level, v7e); + v7d = v7e; static const int testbits[3] { 0xE0, 0xF0, 0xF8 }; @@ -2083,58 +1918,170 @@ uint8_t pack_color_endpoints( ) { assert(QUANT_6 <= quant_level && quant_level <= QUANT_256); - // We do not support negative colors - color0 = max(color0, 0.0f); - color1 = max(color1, 0.0f); + // Clamp colors to a valid LDR range + // Note that HDR has a lower max, handled in the conversion functions + color0 = clamp(0.0f, 65535.0f, color0); + color1 = clamp(0.0f, 65535.0f, color1); + + // Pre-scale the LDR value we need to the 0-255 quantizable range + vfloat4 color0_ldr = color0 * (1.0f / 257.0f); + vfloat4 color1_ldr = color1 * (1.0f / 257.0f); uint8_t retval = 0; + float best_error = ERROR_CALC_DEFAULT; + vint4 color0_out, color1_out; + vint4 color0_out2, color1_out2; switch (format) { case FMT_RGB: - if (quant_level <= 18) + if (quant_level <= QUANT_160) { - if (try_quantize_rgb_delta_blue_contract(color0, color1, output, quant_level)) + if (try_quantize_rgb_delta_blue_contract(color0_ldr, color1_ldr, color0_out, color1_out, quant_level)) { + vint4 color0_unpack; + vint4 color1_unpack; + rgba_delta_unpack(color0_out, color1_out, color0_unpack, color1_unpack); + retval = FMT_RGB_DELTA; - break; + best_error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); } - if (try_quantize_rgb_delta(color0, color1, output, quant_level)) + + if (try_quantize_rgb_delta(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level)) { - retval = FMT_RGB_DELTA; - break; + vint4 color0_unpack; + vint4 color1_unpack; + rgba_delta_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGB_DELTA; + best_error = error; + color0_out = color0_out2; + color1_out = color1_out2; + } } } - if (try_quantize_rgb_blue_contract(color0, color1, output, quant_level)) + + if (quant_level < QUANT_256) { - retval = FMT_RGB; - break; + if (try_quantize_rgb_blue_contract(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level)) + { + vint4 color0_unpack; + vint4 color1_unpack; + rgba_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGB; + best_error = error; + color0_out = color0_out2; + color1_out = color1_out2; + } + } } - quantize_rgb(color0, color1, output, quant_level); - retval = FMT_RGB; + + { + quantize_rgb(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level); + + vint4 color0_unpack; + vint4 color1_unpack; + rgba_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGB; + color0_out = color0_out2; + color1_out = color1_out2; + } + } + + // TODO: Can we vectorize this? + output[0] = static_cast(color0_out.lane<0>()); + output[1] = static_cast(color1_out.lane<0>()); + output[2] = static_cast(color0_out.lane<1>()); + output[3] = static_cast(color1_out.lane<1>()); + output[4] = static_cast(color0_out.lane<2>()); + output[5] = static_cast(color1_out.lane<2>()); break; case FMT_RGBA: - if ((privateProfile == HIGH_QUALITY_PROFILE) && (quant_level <= 18)) // only full quality profile to try + if ((privateProfile == HIGH_QUALITY_PROFILE) && (quant_level <= QUANT_160)) // only full quality profile to try { - if (try_quantize_rgba_delta_blue_contract(color0, color1, output, quant_level)) + if (try_quantize_rgba_delta_blue_contract(color0_ldr, color1_ldr, color0_out, color1_out, quant_level)) { + vint4 color0_unpack; + vint4 color1_unpack; + rgba_delta_unpack(color0_out, color1_out, color0_unpack, color1_unpack); + retval = FMT_RGBA_DELTA; - break; + best_error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); } - if (try_quantize_rgba_delta(color0, color1, output, quant_level)) + + if (try_quantize_rgba_delta(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level)) { - retval = FMT_RGBA_DELTA; - break; + vint4 color0_unpack; + vint4 color1_unpack; + rgba_delta_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGBA_DELTA; + best_error = error; + color0_out = color0_out2; + color1_out = color1_out2; + } } } - if (try_quantize_rgba_blue_contract(color0, color1, output, quant_level)) + + if (quant_level < QUANT_256) { - retval = FMT_RGBA; - break; + if (try_quantize_rgba_blue_contract(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level)) + { + vint4 color0_unpack; + vint4 color1_unpack; + rgba_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGBA; + best_error = error; + color0_out = color0_out2; + color1_out = color1_out2; + } + } } - quantize_rgba(color0, color1, output, quant_level); - retval = FMT_RGBA; + + { + quantize_rgba(color0_ldr, color1_ldr, color0_out2, color1_out2, quant_level); + + vint4 color0_unpack; + vint4 color1_unpack; + rgba_unpack(color0_out2, color1_out2, color0_unpack, color1_unpack); + + float error = get_rgba_encoding_error(color0_ldr, color1_ldr, color0_unpack, color1_unpack); + if (error < best_error) + { + retval = FMT_RGBA; + color0_out = color0_out2; + color1_out = color1_out2; + } + } + + // TODO: Can we vectorize this? + output[0] = static_cast(color0_out.lane<0>()); + output[1] = static_cast(color1_out.lane<0>()); + output[2] = static_cast(color0_out.lane<1>()); + output[3] = static_cast(color1_out.lane<1>()); + output[4] = static_cast(color0_out.lane<2>()); + output[5] = static_cast(color1_out.lane<2>()); + output[6] = static_cast(color0_out.lane<3>()); + output[7] = static_cast(color1_out.lane<3>()); break; case FMT_RGB_SCALE: @@ -2153,7 +2100,7 @@ uint8_t pack_color_endpoints( break; case FMT_RGB_SCALE_ALPHA: - quantize_rgbs_alpha(color0, color1, rgbs_color, output, quant_level); + quantize_rgbs_alpha(color0_ldr, color1_ldr, rgbs_color, output, quant_level); retval = FMT_RGB_SCALE_ALPHA; break; @@ -2169,20 +2116,20 @@ uint8_t pack_color_endpoints( break; case FMT_LUMINANCE: - quantize_luminance(color0, color1, output, quant_level); + quantize_luminance(color0_ldr, color1_ldr, output, quant_level); retval = FMT_LUMINANCE; break; case FMT_LUMINANCE_ALPHA: if (quant_level <= 18) { - if (try_quantize_luminance_alpha_delta(color0, color1, output, quant_level)) + if (try_quantize_luminance_alpha_delta(color0_ldr, color1_ldr, output, quant_level)) { retval = FMT_LUMINANCE_ALPHA_DELTA; break; } } - quantize_luminance_alpha(color0, color1, output, quant_level); + quantize_luminance_alpha(color0_ldr, color1_ldr, output, quant_level); retval = FMT_LUMINANCE_ALPHA; break; diff --git a/Source/astcenc_color_unquantize.cpp b/Source/astcenc_color_unquantize.cpp index bb02d81..2daa515 100644 --- a/Source/astcenc_color_unquantize.cpp +++ b/Source/astcenc_color_unquantize.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -23,43 +23,6 @@ #include "astcenc_internal.h" -/** - * @brief Unquantize a color. - * - * This function uses a lookup table as the quantization is encoded to make - * hardware implementations easier, and is not a simple lerp. - * - * @param quant_level The quantization level to use. - * @param inputq The input quantized color. - * - * @return The unquantized color. - */ -static ASTCENC_SIMD_INLINE vint4 unquant_color( - quant_method quant_level, - vint4 inputq -) { - const uint8_t* unq = color_unquant_tables[quant_level - QUANT_6]; - return vint4(unq[inputq.lane<0>()], unq[inputq.lane<1>()], - unq[inputq.lane<2>()], unq[inputq.lane<3>()]); -} - -/** - * @brief Determine the quantized value given a quantization level. - * - * @param quant_level The quantization level to use. - * @param value The value to convert. This may be outside of the 0-255 range and will be - * clamped before the value is looked up. - * - * @return The encoded quantized value. These are not necessarily in the order; the compressor - * scrambles the values slightly to make hardware implementation easier. - */ -static inline int unquant_color( - quant_method quant_level, - int value -) { - return color_unquant_tables[quant_level - QUANT_6][value]; -} - /** * @brief Un-blue-contract a color. * @@ -77,35 +40,14 @@ static ASTCENC_SIMD_INLINE vint4 uncontract_color( return select(input, bc0, mask); } -/** - * @brief Unpack an LDR RGBA color that uses delta encoding. - * - * @param input0q The raw quantized endpoint 0 color. - * @param input1q The raw quantized endpoint 1 color deltas. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. - */ -static void rgba_delta_unpack( - vint4 input0q, - vint4 input1q, - quant_method quant_level, +void rgba_delta_unpack( + vint4 input0, + vint4 input1, vint4& output0, vint4& output1 ) { - // Unquantize color endpoints - vint4 input0 = unquant_color(quant_level, input0q); - vint4 input1 = unquant_color(quant_level, input1q); - - // Perform bit-transfer - input0 = input0 | lsl<1>(input1 & 0x80); - input1 = input1 & 0x7F; - vmask4 mask = (input1 & 0x40) != vint4::zero(); - input1 = select(input1, input1 - 0x80, mask); - - // Scale - input0 = asr<1>(input0); - input1 = asr<1>(input1); + // Apply bit transfer + bit_transfer_signed(input1, input0); // Apply blue-uncontraction if needed int rgb_sum = hadd_rgb_s(input1); @@ -126,44 +68,28 @@ static void rgba_delta_unpack( * * Output alpha set to 255. * - * @param input0q The raw quantized endpoint 0 color. - * @param input1q The raw quantized endpoint 1 color deltas. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input0 The packed endpoint 0 color. + * @param input1 The packed endpoint 1 color deltas. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void rgb_delta_unpack( - vint4 input0q, - vint4 input1q, - quant_method quant_level, + vint4 input0, + vint4 input1, vint4& output0, vint4& output1 ) { - rgba_delta_unpack(input0q, input1q, quant_level, output0, output1); + rgba_delta_unpack(input0, input1, output0, output1); output0.set_lane<3>(255); output1.set_lane<3>(255); } -/** - * @brief Unpack an LDR RGBA color that uses direct encoding. - * - * @param input0q The raw quantized endpoint 0 color. - * @param input1q The raw quantized endpoint 1 color. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. - */ -static void rgba_unpack( - vint4 input0q, - vint4 input1q, - quant_method quant_level, +void rgba_unpack( + vint4 input0, + vint4 input1, vint4& output0, vint4& output1 ) { - // Unquantize color endpoints - vint4 input0 = unquant_color(quant_level, input0q); - vint4 input1 = unquant_color(quant_level, input1q); - // Apply blue-uncontraction if needed if (hadd_rgb_s(input0) > hadd_rgb_s(input1)) { @@ -181,20 +107,18 @@ static void rgba_unpack( * * Output alpha set to 255. * - * @param input0q The raw quantized endpoint 0 color. - * @param input1q The raw quantized endpoint 1 color. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input0 The packed endpoint 0 color. + * @param input1 The packed endpoint 1 color. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void rgb_unpack( - vint4 input0q, - vint4 input1q, - quant_method quant_level, + vint4 input0, + vint4 input1, vint4& output0, vint4& output1 ) { - rgba_unpack(input0q, input1q, quant_level, output0, output1); + rgba_unpack(input0, input1, output0, output1); output0.set_lane<3>(255); output1.set_lane<3>(255); } @@ -204,31 +128,24 @@ static void rgb_unpack( * * Note only the RGB channels use the scaled encoding, alpha uses direct. * - * @param input0q The raw quantized endpoint 0 color. - * @param alpha1q The raw quantized endpoint 1 alpha value. - * @param scaleq The raw quantized scale. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input0 The packed endpoint 0 color. + * @param alpha1 The packed endpoint 1 alpha value. + * @param scale The packed quantized scale. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void rgb_scale_alpha_unpack( - vint4 input0q, - uint8_t alpha1q, - uint8_t scaleq, - quant_method quant_level, + vint4 input0, + uint8_t alpha1, + uint8_t scale, vint4& output0, vint4& output1 ) { - // Unquantize color endpoints - vint4 input = unquant_color(quant_level, input0q); - uint8_t alpha1 = unquant_color(quant_level, alpha1q); - uint8_t scale = unquant_color(quant_level, scaleq); - - output1 = input; + output1 = input0; output1.set_lane<3>(alpha1); - output0 = asr<8>(input * scale); - output0.set_lane<3>(input.lane<3>()); + output0 = asr<8>(input0 * scale); + output0.set_lane<3>(input0.lane<3>()); } /** @@ -236,26 +153,21 @@ static void rgb_scale_alpha_unpack( * * Output alpha is 255. * - * @param input0q The raw quantized endpoint 0 color. - * @param scaleq The raw quantized scale. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input0 The packed endpoint 0 color. + * @param scale The packed scale. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void rgb_scale_unpack( - vint4 input0q, - int scaleq, - quant_method quant_level, + vint4 input0, + int scale, vint4& output0, vint4& output1 ) { - vint4 input = unquant_color(quant_level, input0q); - int scale = unquant_color(quant_level, scaleq); - - output1 = input; + output1 = input0; output1.set_lane<3>(255); - output0 = asr<8>(input * scale); + output0 = asr<8>(input0 * scale); output0.set_lane<3>(255); } @@ -264,19 +176,17 @@ static void rgb_scale_unpack( * * Output alpha is 255. * - * @param input The raw quantized endpoints. - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void luminance_unpack( const uint8_t input[2], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int lum0 = unquant_color(quant_level, input[0]); - int lum1 = unquant_color(quant_level, input[1]); + int lum0 = input[0]; + int lum1 = input[1]; output0 = vint4(lum0, lum0, lum0, 255); output1 = vint4(lum1, lum1, lum1, 255); } @@ -286,19 +196,17 @@ static void luminance_unpack( * * Output alpha is 255. * - * @param input The raw quantized endpoints (L0, L1). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (L0, L1). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void luminance_delta_unpack( const uint8_t input[2], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int v0 = unquant_color(quant_level, input[0]); - int v1 = unquant_color(quant_level, input[1]); + int v0 = input[0]; + int v1 = input[1]; int l0 = (v0 >> 2) | (v1 & 0xC0); int l1 = l0 + (v1 & 0x3F); @@ -311,21 +219,19 @@ static void luminance_delta_unpack( /** * @brief Unpack an LDR LA color that uses direct encoding. * - * @param input The raw quantized endpoints (L0, L1, A0, A1). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (L0, L1, A0, A1). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void luminance_alpha_unpack( const uint8_t input[4], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int lum0 = unquant_color(quant_level, input[0]); - int lum1 = unquant_color(quant_level, input[1]); - int alpha0 = unquant_color(quant_level, input[2]); - int alpha1 = unquant_color(quant_level, input[3]); + int lum0 = input[0]; + int lum1 = input[1]; + int alpha0 = input[2]; + int alpha1 = input[3]; output0 = vint4(lum0, lum0, lum0, alpha0); output1 = vint4(lum1, lum1, lum1, alpha1); } @@ -333,30 +239,34 @@ static void luminance_alpha_unpack( /** * @brief Unpack an LDR LA color that uses delta encoding. * - * @param input The raw quantized endpoints (L0, L1, A0, A1). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (L0, L1, A0, A1). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void luminance_alpha_delta_unpack( const uint8_t input[4], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int lum0 = unquant_color(quant_level, input[0]); - int lum1 = unquant_color(quant_level, input[1]); - int alpha0 = unquant_color(quant_level, input[2]); - int alpha1 = unquant_color(quant_level, input[3]); + int lum0 = input[0]; + int lum1 = input[1]; + int alpha0 = input[2]; + int alpha1 = input[3]; lum0 |= (lum1 & 0x80) << 1; alpha0 |= (alpha1 & 0x80) << 1; lum1 &= 0x7F; alpha1 &= 0x7F; + if (lum1 & 0x40) + { lum1 -= 0x80; + } + if (alpha1 & 0x40) + { alpha1 -= 0x80; + } lum0 >>= 1; lum1 >>= 1; @@ -375,21 +285,19 @@ static void luminance_alpha_delta_unpack( /** * @brief Unpack an HDR RGB + offset encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_rgbo_unpack( const uint8_t input[4], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int v0 = unquant_color(quant_level, input[0]); - int v1 = unquant_color(quant_level, input[1]); - int v2 = unquant_color(quant_level, input[2]); - int v3 = unquant_color(quant_level, input[3]); + int v0 = input[0]; + int v1 = input[1]; + int v2 = input[2]; + int v3 = input[3]; int modeval = ((v0 & 0xC0) >> 6) | (((v1 & 0x80) >> 7) << 2) | (((v2 & 0x80) >> 7) << 3); @@ -527,24 +435,22 @@ static void hdr_rgbo_unpack( /** * @brief Unpack an HDR RGB direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_rgb_unpack( const uint8_t input[6], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int v0 = unquant_color(quant_level, input[0]); - int v1 = unquant_color(quant_level, input[1]); - int v2 = unquant_color(quant_level, input[2]); - int v3 = unquant_color(quant_level, input[3]); - int v4 = unquant_color(quant_level, input[4]); - int v5 = unquant_color(quant_level, input[5]); + int v0 = input[0]; + int v1 = input[1]; + int v2 = input[2]; + int v3 = input[3]; + int v4 = input[4]; + int v5 = input[5]; // extract all the fixed-placement bitfields int modeval = ((v1 & 0x80) >> 7) | (((v2 & 0x80) >> 7) << 1) | (((v3 & 0x80) >> 7) << 2); @@ -695,21 +601,19 @@ static void hdr_rgb_unpack( /** * @brief Unpack an HDR RGB + LDR A direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_rgb_ldr_alpha_unpack( const uint8_t input[8], - quant_method quant_level, vint4& output0, vint4& output1 ) { - hdr_rgb_unpack(input, quant_level, output0, output1); + hdr_rgb_unpack(input, output0, output1); - int v6 = unquant_color(quant_level, input[6]); - int v7 = unquant_color(quant_level, input[7]); + int v6 = input[6]; + int v7 = input[7]; output0.set_lane<3>(v6); output1.set_lane<3>(v7); } @@ -717,19 +621,17 @@ static void hdr_rgb_ldr_alpha_unpack( /** * @brief Unpack an HDR L (small range) direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_luminance_small_range_unpack( const uint8_t input[2], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int v0 = unquant_color(quant_level, input[0]); - int v1 = unquant_color(quant_level, input[1]); + int v0 = input[0]; + int v1 = input[1]; int y0, y1; if (v0 & 0x80) @@ -745,7 +647,9 @@ static void hdr_luminance_small_range_unpack( y1 += y0; if (y1 > 0xFFF) + { y1 = 0xFFF; + } output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800); output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800); @@ -754,19 +658,17 @@ static void hdr_luminance_small_range_unpack( /** * @brief Unpack an HDR L (large range) direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_luminance_large_range_unpack( const uint8_t input[2], - quant_method quant_level, vint4& output0, vint4& output1 ) { - int v0 = unquant_color(quant_level, input[0]); - int v1 = unquant_color(quant_level, input[1]); + int v0 = input[0]; + int v1 = input[1]; int y0, y1; if (v1 >= v0) @@ -787,20 +689,18 @@ static void hdr_luminance_large_range_unpack( /** * @brief Unpack an HDR A direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_alpha_unpack( const uint8_t input[2], - quant_method quant_level, int& output0, int& output1 ) { - int v6 = unquant_color(quant_level, input[0]); - int v7 = unquant_color(quant_level, input[1]); + int v6 = input[0]; + int v7 = input[1]; int selector = ((v6 >> 7) & 1) | ((v7 >> 6) & 2); v6 &= 0x7F; @@ -821,9 +721,13 @@ static void hdr_alpha_unpack( v7 += v6; if (v7 < 0) + { v7 = 0; + } else if (v7 > 0xFFF) + { v7 = 0xFFF; + } output0 = v6; output1 = v7; @@ -836,21 +740,19 @@ static void hdr_alpha_unpack( /** * @brief Unpack an HDR RGBA direct encoding. * - * @param input The raw quantized endpoints (packed and modal). - * @param quant_level The quantization level to use. - * @param[out] output0 The unpacked and unquantized endpoint 0 color. - * @param[out] output1 The unpacked and unquantized endpoint 1 color. + * @param input The packed endpoints (packed and modal). + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. */ static void hdr_rgb_hdr_alpha_unpack( const uint8_t input[8], - quant_method quant_level, vint4& output0, vint4& output1 ) { - hdr_rgb_unpack(input, quant_level, output0, output1); + hdr_rgb_unpack(input, output0, output1); int alpha0, alpha1; - hdr_alpha_unpack(input + 6, quant_level, alpha0, alpha1); + hdr_alpha_unpack(input + 6, alpha0, alpha1); output0.set_lane<3>(alpha0); output1.set_lane<3>(alpha1); @@ -860,7 +762,6 @@ static void hdr_rgb_hdr_alpha_unpack( void unpack_color_endpoints( astcenc_profile decode_mode, int format, - quant_method quant_level, const uint8_t* input, bool& rgb_hdr, bool& alpha_hdr, @@ -876,38 +777,38 @@ void unpack_color_endpoints( switch (format) { case FMT_LUMINANCE: - luminance_unpack(input, quant_level, output0, output1); + luminance_unpack(input, output0, output1); break; case FMT_LUMINANCE_DELTA: - luminance_delta_unpack(input, quant_level, output0, output1); + luminance_delta_unpack(input, output0, output1); break; case FMT_HDR_LUMINANCE_SMALL_RANGE: rgb_hdr = true; alpha_hdr_default = true; - hdr_luminance_small_range_unpack(input, quant_level, output0, output1); + hdr_luminance_small_range_unpack(input, output0, output1); break; case FMT_HDR_LUMINANCE_LARGE_RANGE: rgb_hdr = true; alpha_hdr_default = true; - hdr_luminance_large_range_unpack(input, quant_level, output0, output1); + hdr_luminance_large_range_unpack(input, output0, output1); break; case FMT_LUMINANCE_ALPHA: - luminance_alpha_unpack(input, quant_level, output0, output1); + luminance_alpha_unpack(input, output0, output1); break; case FMT_LUMINANCE_ALPHA_DELTA: - luminance_alpha_delta_unpack(input, quant_level, output0, output1); + luminance_alpha_delta_unpack(input, output0, output1); break; case FMT_RGB_SCALE: { vint4 input0q(input[0], input[1], input[2], 0); uint8_t scale = input[3]; - rgb_scale_unpack(input0q, scale, quant_level, output0, output1); + rgb_scale_unpack(input0q, scale, output0, output1); } break; @@ -916,21 +817,21 @@ void unpack_color_endpoints( vint4 input0q(input[0], input[1], input[2], input[4]); uint8_t alpha1q = input[5]; uint8_t scaleq = input[3]; - rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, quant_level, output0, output1); + rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, output0, output1); } break; case FMT_HDR_RGB_SCALE: rgb_hdr = true; alpha_hdr_default = true; - hdr_rgbo_unpack(input, quant_level,output0, output1); + hdr_rgbo_unpack(input, output0, output1); break; case FMT_RGB: { vint4 input0q(input[0], input[2], input[4], 0); vint4 input1q(input[1], input[3], input[5], 0); - rgb_unpack(input0q, input1q, quant_level, output0, output1); + rgb_unpack(input0q, input1q, output0, output1); } break; @@ -938,21 +839,21 @@ void unpack_color_endpoints( { vint4 input0q(input[0], input[2], input[4], 0); vint4 input1q(input[1], input[3], input[5], 0); - rgb_delta_unpack(input0q, input1q, quant_level, output0, output1); + rgb_delta_unpack(input0q, input1q, output0, output1); } break; case FMT_HDR_RGB: rgb_hdr = true; alpha_hdr_default = true; - hdr_rgb_unpack(input, quant_level, output0, output1); + hdr_rgb_unpack(input, output0, output1); break; case FMT_RGBA: { vint4 input0q(input[0], input[2], input[4], input[6]); vint4 input1q(input[1], input[3], input[5], input[7]); - rgba_unpack(input0q, input1q, quant_level, output0, output1); + rgba_unpack(input0q, input1q, output0, output1); } break; @@ -960,19 +861,19 @@ void unpack_color_endpoints( { vint4 input0q(input[0], input[2], input[4], input[6]); vint4 input1q(input[1], input[3], input[5], input[7]); - rgba_delta_unpack(input0q, input1q, quant_level, output0, output1); + rgba_delta_unpack(input0q, input1q, output0, output1); } break; case FMT_HDR_RGB_LDR_ALPHA: rgb_hdr = true; - hdr_rgb_ldr_alpha_unpack(input, quant_level, output0, output1); + hdr_rgb_ldr_alpha_unpack(input, output0, output1); break; case FMT_HDR_RGBA: rgb_hdr = true; alpha_hdr = true; - hdr_rgb_hdr_alpha_unpack(input, quant_level, output0, output1); + hdr_rgb_hdr_alpha_unpack(input, output0, output1); break; } @@ -993,32 +894,55 @@ void unpack_color_endpoints( } } - vint4 ldr_scale(257); - vint4 hdr_scale(1); - vint4 output_scale = ldr_scale; + // Handle endpoint errors and expansion - // An LDR profile image - if ((decode_mode == ASTCENC_PRF_LDR) || - (decode_mode == ASTCENC_PRF_LDR_SRGB)) + // Linear LDR 8-bit endpoints are expanded to 16-bit by replication + if (decode_mode == ASTCENC_PRF_LDR) { - // Also matches HDR alpha, as cannot have HDR alpha without HDR RGB - if (rgb_hdr == true) + // Error color - HDR endpoint in an LDR encoding + if (rgb_hdr || alpha_hdr) { - output0 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00); - output1 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00); - output_scale = hdr_scale; + output0 = vint4(0xFF, 0x00, 0xFF, 0xFF); + output1 = vint4(0xFF, 0x00, 0xFF, 0xFF); + rgb_hdr = false; + alpha_hdr = false; + } + output0 = output0 * 257; + output1 = output1 * 257; + } + // sRGB LDR 8-bit endpoints are expanded to 16 bit by: + // - RGB = shift left by 8 bits and OR with 0x80 + // - A = replication + else if (decode_mode == ASTCENC_PRF_LDR_SRGB) + { + // Error color - HDR endpoint in an LDR encoding + if (rgb_hdr || alpha_hdr) + { + output0 = vint4(0xFF, 0x00, 0xFF, 0xFF); + output1 = vint4(0xFF, 0x00, 0xFF, 0xFF); rgb_hdr = false; alpha_hdr = false; } + + vmask4 mask(true, true, true, false); + + vint4 output0rgb = lsl<8>(output0) | vint4(0x80); + vint4 output0a = output0 * 257; + output0 = select(output0a, output0rgb, mask); + + vint4 output1rgb = lsl<8>(output1) | vint4(0x80); + vint4 output1a = output1 * 257; + output1 = select(output1a, output1rgb, mask); } - // An HDR profile image + // An HDR profile decode, but may be using linear LDR endpoints + // Linear LDR 8-bit endpoints are expanded to 16-bit by replication + // HDR endpoints are already 16-bit else { vmask4 hdr_lanes(rgb_hdr, rgb_hdr, rgb_hdr, alpha_hdr); - output_scale = select(ldr_scale, hdr_scale, hdr_lanes); + vint4 output_scale = select(vint4(257), vint4(1), hdr_lanes); + output0 = output0 * output_scale; + output1 = output1 * output_scale; } - - output0 = output0 * output_scale; - output1 = output1 * output_scale; } diff --git a/Source/astcenc_compress_symbolic.cpp b/Source/astcenc_compress_symbolic.cpp index 35bb269..2560f54 100644 --- a/Source/astcenc_compress_symbolic.cpp +++ b/Source/astcenc_compress_symbolic.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -79,10 +79,10 @@ static bool realign_weights_undecimated( // Get the quantization table const block_mode& bm = bsd.get_block_mode(scb.block_mode); unsigned int weight_quant_level = bm.quant_mode; - const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[weight_quant_level]); + const quant_and_transfer_table& qat = quant_and_xfer_tables[weight_quant_level]; unsigned int max_plane = bm.is_dual_plane; - int plane2_component = bm.is_dual_plane ? scb.plane2_component : -1; + int plane2_component = scb.plane2_component; vmask4 plane_mask = vint4::lane_id() == vint4(plane2_component); // Decode the color endpoints @@ -99,14 +99,13 @@ static bool realign_weights_undecimated( { unpack_color_endpoints(decode_mode, scb.color_formats[pa_idx], - scb.get_color_quant_mode(), scb.color_values[pa_idx], rgb_hdr, alpha_hdr, endpnt0[pa_idx], endpnt1[pa_idx]); } - uint8_t* dec_weights_quant_pvalue = scb.weights; + uint8_t* dec_weights_uquant = scb.weights; bool adjustments = false; // For each plane and partition ... @@ -126,50 +125,48 @@ static bool realign_weights_undecimated( promise(bsd.texel_count > 0); for (unsigned int texel = 0; texel < bsd.texel_count; texel++) { - int uqw = qat->unquantized_value[dec_weights_quant_pvalue[texel]]; + int uqw = dec_weights_uquant[texel]; - uint32_t prev_and_next = qat->prev_next_values[uqw]; - int prev_wt_uq = prev_and_next & 0xFF; - int next_wt_uq = (prev_and_next >> 8) & 0xFF; + uint32_t prev_and_next = qat.prev_next_values[uqw]; + int uqw_down = prev_and_next & 0xFF; + int uqw_up = (prev_and_next >> 8) & 0xFF; // Interpolate the colors to create the diffs - unsigned int partition = pi.partition_of_texel[texel]; - - float plane_weight = static_cast(uqw); - float plane_up_weight = static_cast(next_wt_uq - uqw); - float plane_down_weight = static_cast(prev_wt_uq - uqw); + float weight_base = static_cast(uqw); + float weight_down = static_cast(uqw_down - uqw); + float weight_up = static_cast(uqw_up - uqw); + unsigned int partition = pi.partition_of_texel[texel]; vfloat4 color_offset = offset[partition]; vfloat4 color_base = endpnt0f[partition]; - vfloat4 color = color_base + color_offset * plane_weight; - + vfloat4 color = color_base + color_offset * weight_base; vfloat4 orig_color = blk.texel(texel); vfloat4 error_weight = blk.channel_weight; vfloat4 color_diff = color - orig_color; - vfloat4 color_up_diff = color_diff + color_offset * plane_up_weight; - vfloat4 color_down_diff = color_diff + color_offset * plane_down_weight; + vfloat4 color_diff_down = color_diff + color_offset * weight_down; + vfloat4 color_diff_up = color_diff + color_offset * weight_up; - float current_error = dot_s(color_diff * color_diff, error_weight); - float up_error = dot_s(color_up_diff * color_up_diff, error_weight); - float down_error = dot_s(color_down_diff * color_down_diff, error_weight); + float error_base = dot_s(color_diff * color_diff, error_weight); + float error_down = dot_s(color_diff_down * color_diff_down, error_weight); + float error_up = dot_s(color_diff_up * color_diff_up, error_weight); // Check if the prev or next error is better, and if so use it - if ((up_error < current_error) && (up_error < down_error)) + if ((error_up < error_base) && (error_up < error_down) && (uqw < 64)) { - dec_weights_quant_pvalue[texel] = static_cast((prev_and_next >> 24) & 0xFF); + dec_weights_uquant[texel] = static_cast(uqw_up); adjustments = true; } - else if (down_error < current_error) + else if ((error_down < error_base) && (uqw > 0)) { - dec_weights_quant_pvalue[texel] = static_cast((prev_and_next >> 16) & 0xFF); + dec_weights_uquant[texel] = static_cast(uqw_down); adjustments = true; } } // Prepare iteration for plane 2 - dec_weights_quant_pvalue += WEIGHTS_PLANE2_OFFSET; + dec_weights_uquant += WEIGHTS_PLANE2_OFFSET; plane_mask = ~plane_mask; } @@ -201,7 +198,7 @@ static bool realign_weights_decimated( // Get the quantization table const block_mode& bm = bsd.get_block_mode(scb.block_mode); unsigned int weight_quant_level = bm.quant_mode; - const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[weight_quant_level]); + const quant_and_transfer_table& qat = quant_and_xfer_tables[weight_quant_level]; // Get the decimation table const decimation_info& di = bsd.get_decimation_info(bm.decimation_mode); @@ -209,7 +206,7 @@ static bool realign_weights_decimated( assert(weight_count != bsd.texel_count); unsigned int max_plane = bm.is_dual_plane; - int plane2_component = bm.is_dual_plane ? scb.plane2_component : -1; + int plane2_component = scb.plane2_component; vmask4 plane_mask = vint4::lane_id() == vint4(plane2_component); // Decode the color endpoints @@ -227,16 +224,13 @@ static bool realign_weights_decimated( { unpack_color_endpoints(decode_mode, scb.color_formats[pa_idx], - scb.get_color_quant_mode(), scb.color_values[pa_idx], rgb_hdr, alpha_hdr, endpnt0[pa_idx], endpnt1[pa_idx]); } - uint8_t uq_pl_weights[BLOCK_MAX_WEIGHTS]; - float uq_pl_weightsf[BLOCK_MAX_WEIGHTS]; - uint8_t* dec_weights_quant_pvalue = scb.weights; + uint8_t* dec_weights_uquant = scb.weights; bool adjustments = false; // For each plane and partition ... @@ -253,97 +247,90 @@ static bool realign_weights_decimated( } // Create an unquantized weight grid for this decimation level - for (unsigned int we_idx = 0; we_idx < weight_count; we_idx++) + ASTCENC_ALIGNAS float uq_weightsf[BLOCK_MAX_WEIGHTS]; + for (unsigned int we_idx = 0; we_idx < weight_count; we_idx += ASTCENC_SIMD_WIDTH) { - uq_pl_weights[we_idx] = qat->unquantized_value[dec_weights_quant_pvalue[we_idx]]; - uq_pl_weightsf[we_idx] = static_cast(uq_pl_weights[we_idx]); + vint unquant_value(dec_weights_uquant + we_idx); + vfloat unquant_valuef = int_to_float(unquant_value); + storea(unquant_valuef, uq_weightsf + we_idx); } // For each weight compute previous, current, and next errors for (unsigned int we_idx = 0; we_idx < weight_count; we_idx++) { - unsigned int uqw = uq_pl_weights[we_idx]; - float uqwf = uq_pl_weightsf[we_idx]; + int uqw = dec_weights_uquant[we_idx]; + uint32_t prev_and_next = qat.prev_next_values[uqw]; - uint32_t prev_and_next = qat->prev_next_values[uqw]; - unsigned int prev_wt_uq = prev_and_next & 0xFF; - unsigned int next_wt_uq = (prev_and_next >> 8) & 0xFF; + float uqw_base = uq_weightsf[we_idx]; + float uqw_down = static_cast(prev_and_next & 0xFF); + float uqw_up = static_cast((prev_and_next >> 8) & 0xFF); - float uqw_next_dif = static_cast(next_wt_uq) - uqwf; - float uqw_prev_dif = static_cast(prev_wt_uq) - uqwf; + float uqw_diff_down = uqw_down - uqw_base; + float uqw_diff_up = uqw_up - uqw_base; - vfloat4 current_errorv = vfloat4::zero(); - vfloat4 up_errorv = vfloat4::zero(); - vfloat4 down_errorv = vfloat4::zero(); + vfloat4 error_basev = vfloat4::zero(); + vfloat4 error_downv = vfloat4::zero(); + vfloat4 error_upv = vfloat4::zero(); // Interpolate the colors to create the diffs unsigned int texels_to_evaluate = di.weight_texel_count[we_idx]; promise(texels_to_evaluate > 0); for (unsigned int te_idx = 0; te_idx < texels_to_evaluate; te_idx++) { - unsigned int texel = di.weight_texel[te_idx][we_idx]; - float weight_base = uqwf; - - const uint8_t *texel_weights = di.texel_weights_texel[we_idx][te_idx]; - const float *texel_weights_float = di.texel_weights_float_texel[we_idx][te_idx]; - float twf0 = texel_weights_float[0]; + unsigned int texel = di.weight_texels_tr[te_idx][we_idx]; - weight_base = (uqwf * twf0 - + uq_pl_weightsf[texel_weights[1]] * texel_weights_float[1]) - + (uq_pl_weightsf[texel_weights[2]] * texel_weights_float[2] - + uq_pl_weightsf[texel_weights[3]] * texel_weights_float[3]); + float tw_base = di.texel_contrib_for_weight[te_idx][we_idx]; - unsigned int partition = pi.partition_of_texel[texel]; + float weight_base = (uq_weightsf[di.texel_weights_tr[0][texel]] * di.texel_weight_contribs_float_tr[0][texel] + + uq_weightsf[di.texel_weights_tr[1][texel]] * di.texel_weight_contribs_float_tr[1][texel]) + + (uq_weightsf[di.texel_weights_tr[2][texel]] * di.texel_weight_contribs_float_tr[2][texel] + + uq_weightsf[di.texel_weights_tr[3][texel]] * di.texel_weight_contribs_float_tr[3][texel]); // Ideally this is integer rounded, but IQ gain it isn't worth the overhead - // float plane_weight = astc::flt_rd(weight_base + 0.5f); - // float plane_up_weight = astc::flt_rd(weight_base + 0.5f + uqw_next_dif * twf0) - plane_weight; - // float plane_down_weight = astc::flt_rd(weight_base + 0.5f + uqw_prev_dif * twf0) - plane_weight; - - float plane_weight = weight_base; - float plane_up_weight = weight_base + uqw_next_dif * twf0 - plane_weight; - float plane_down_weight = weight_base + uqw_prev_dif * twf0 - plane_weight; + // float weight = astc::flt_rd(weight_base + 0.5f); + // float weight_down = astc::flt_rd(weight_base + 0.5f + uqw_diff_down * tw_base) - weight; + // float weight_up = astc::flt_rd(weight_base + 0.5f + uqw_diff_up * tw_base) - weight; + float weight_down = weight_base + uqw_diff_down * tw_base - weight_base; + float weight_up = weight_base + uqw_diff_up * tw_base - weight_base; + unsigned int partition = pi.partition_of_texel[texel]; vfloat4 color_offset = offset[partition]; vfloat4 color_base = endpnt0f[partition]; - vfloat4 color = color_base + color_offset * plane_weight; - - vfloat4 orig_color = blk.texel(texel); + vfloat4 color = color_base + color_offset * weight_base; + vfloat4 orig_color = blk.texel(texel); vfloat4 color_diff = color - orig_color; - vfloat4 color_up_diff = color_diff + color_offset * plane_up_weight; - vfloat4 color_down_diff = color_diff + color_offset * plane_down_weight; + vfloat4 color_down_diff = color_diff + color_offset * weight_down; + vfloat4 color_up_diff = color_diff + color_offset * weight_up; - current_errorv += color_diff * color_diff; - up_errorv += color_up_diff * color_up_diff; - down_errorv += color_down_diff * color_down_diff; + error_basev += color_diff * color_diff; + error_downv += color_down_diff * color_down_diff; + error_upv += color_up_diff * color_up_diff; } vfloat4 error_weight = blk.channel_weight; - float current_error = hadd_s(current_errorv * error_weight); - float up_error = hadd_s(up_errorv * error_weight); - float down_error = hadd_s(down_errorv * error_weight); + float error_base = hadd_s(error_basev * error_weight); + float error_down = hadd_s(error_downv * error_weight); + float error_up = hadd_s(error_upv * error_weight); // Check if the prev or next error is better, and if so use it - if ((up_error < current_error) && (up_error < down_error)) + if ((error_up < error_base) && (error_up < error_down) && (uqw < 64)) { - uq_pl_weights[we_idx] = static_cast(next_wt_uq); - uq_pl_weightsf[we_idx] = static_cast(next_wt_uq); - dec_weights_quant_pvalue[we_idx] = static_cast((prev_and_next >> 24) & 0xFF); + uq_weightsf[we_idx] = uqw_up; + dec_weights_uquant[we_idx] = static_cast(uqw_up); adjustments = true; } - else if (down_error < current_error) + else if ((error_down < error_base) && (uqw > 0)) { - uq_pl_weights[we_idx] = static_cast(prev_wt_uq); - uq_pl_weightsf[we_idx] = static_cast(prev_wt_uq); - dec_weights_quant_pvalue[we_idx] = static_cast((prev_and_next >> 16) & 0xFF); + uq_weightsf[we_idx] = uqw_down; + dec_weights_uquant[we_idx] = static_cast(uqw_down); adjustments = true; } } // Prepare iteration for plane 2 - dec_weights_quant_pvalue += WEIGHTS_PLANE2_OFFSET; + dec_weights_uquant += WEIGHTS_PLANE2_OFFSET; plane_mask = ~plane_mask; } @@ -373,12 +360,15 @@ static float compress_symbolic_block_for_partition_1plane( unsigned int partition_count, unsigned int partition_index, symbolic_compressed_block& scb, - compression_working_buffers& tmpbuf + compression_working_buffers& tmpbuf, + int quant_limit ) { promise(partition_count > 0); promise(config.tune_candidate_limit > 0); promise(config.tune_refinement_limit > 0); + int max_weight_quant = astc::min(static_cast(QUANT_32), quant_limit); + auto compute_difference = &compute_symbolic_block_difference_1plane; if ((partition_count == 1) && !(config.flags & ASTCENC_FLG_MAP_RGBM)) { @@ -389,13 +379,11 @@ static float compress_symbolic_block_for_partition_1plane( // Compute ideal weights and endpoint colors, with no quantization or decimation endpoints_and_weights& ei = tmpbuf.ei1; - endpoints_and_weights *eix = tmpbuf.eix1; compute_ideal_colors_and_weights_1plane(blk, pi, ei); // Compute ideal weights and endpoint colors for every decimation - float *dec_weights_ideal_value = tmpbuf.dec_weights_ideal_value; - float *dec_weights_quant_uvalue = tmpbuf.dec_weights_quant_uvalue; - uint8_t *dec_weights_quant_pvalue = tmpbuf.dec_weights_quant_pvalue; + float* dec_weights_ideal = tmpbuf.dec_weights_ideal; + uint8_t* dec_weights_uquant = tmpbuf.dec_weights_uquant; // For each decimation mode, compute an ideal set of weights with no quantization unsigned int max_decimation_modes = only_always ? bsd.decimation_mode_count_always @@ -404,7 +392,7 @@ static float compress_symbolic_block_for_partition_1plane( for (unsigned int i = 0; i < max_decimation_modes; i++) { const auto& dm = bsd.get_decimation_mode(i); - if (!dm.ref_1_plane) + if (!dm.is_ref_1plane(static_cast(max_weight_quant))) { continue; } @@ -413,9 +401,8 @@ static float compress_symbolic_block_for_partition_1plane( compute_ideal_weights_for_decimation( ei, - eix[i], di, - dec_weights_ideal_value + i * BLOCK_MAX_WEIGHTS); + dec_weights_ideal + i * BLOCK_MAX_WEIGHTS); } // Compute maximum colors for the endpoints and ideal weights, then for each endpoint and ideal @@ -433,14 +420,11 @@ static float compress_symbolic_block_for_partition_1plane( // For each mode, use the angular method to compute a shift compute_angular_endpoints_1plane( - config.tune_low_weight_count_limit, - only_always, bsd, - dec_weights_ideal_value, - tmpbuf); + only_always, bsd, dec_weights_ideal, max_weight_quant, tmpbuf); float* weight_low_value = tmpbuf.weight_low_value1; float* weight_high_value = tmpbuf.weight_high_value1; - int* qwt_bitcounts = tmpbuf.qwt_bitcounts; + int8_t* qwt_bitcounts = tmpbuf.qwt_bitcounts; float* qwt_errors = tmpbuf.qwt_errors; // For each mode (which specifies a decimation and a quantization): @@ -456,9 +440,16 @@ static float compress_symbolic_block_for_partition_1plane( unsigned int max_block_modes = only_always ? bsd.block_mode_count_1plane_always : bsd.block_mode_count_1plane_selected; promise(max_block_modes > 0); - for (unsigned int i = 0; i < max_block_modes; ++i) + for (unsigned int i = 0; i < max_block_modes; i++) { const block_mode& bm = bsd.block_modes[i]; + + if (bm.quant_mode > max_weight_quant) + { + qwt_errors[i] = 1e38f; + continue; + } + assert(!bm.is_dual_plane); int bitcount = free_bits_for_partition_count[partition_count - 1] - bm.weight_bits; if (bitcount <= 0) @@ -475,26 +466,28 @@ static float compress_symbolic_block_for_partition_1plane( int decimation_mode = bm.decimation_mode; const auto& di = bsd.get_decimation_info(decimation_mode); - qwt_bitcounts[i] = bitcount; + qwt_bitcounts[i] = static_cast(bitcount); + + ASTCENC_ALIGNAS float dec_weights_uquantf[BLOCK_MAX_WEIGHTS]; // Generate the optimized set of weights for the weight mode compute_quantized_weights_for_decimation( di, weight_low_value[i], weight_high_value[i], - dec_weights_ideal_value + BLOCK_MAX_WEIGHTS * decimation_mode, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i, - dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * i, + dec_weights_ideal + BLOCK_MAX_WEIGHTS * decimation_mode, + dec_weights_uquantf, + dec_weights_uquant + BLOCK_MAX_WEIGHTS * i, bm.get_weight_quant_mode()); // Compute weight quantization errors for the block mode qwt_errors[i] = compute_error_of_weight_set_1plane( - eix[decimation_mode], + ei, di, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i); + dec_weights_uquantf); } // Decide the optimal combination of color endpoint encodings and weight encodings - int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS]; + uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS]; int block_mode_index[TUNE_MAX_TRIAL_CANDIDATES]; quant_method color_quant_level[TUNE_MAX_TRIAL_CANDIDATES]; @@ -520,22 +513,22 @@ static float compress_symbolic_block_for_partition_1plane( const block_mode& qw_bm = bsd.block_modes[bm_packed_index]; int decimation_mode = qw_bm.decimation_mode; - int weight_quant_mode = qw_bm.quant_mode; const auto& di = bsd.get_decimation_info(decimation_mode); promise(di.weight_count > 0); trace_add_data("weight_x", di.weight_x); trace_add_data("weight_y", di.weight_y); trace_add_data("weight_z", di.weight_z); - trace_add_data("weight_quant", weight_quant_mode); + trace_add_data("weight_quant", qw_bm.quant_mode); // Recompute the ideal color endpoints before storing them vfloat4 rgbs_colors[BLOCK_MAX_PARTITIONS]; vfloat4 rgbo_colors[BLOCK_MAX_PARTITIONS]; symbolic_compressed_block workscb; + endpoints workep = ei.ep; - uint8_t* u8_weight_src = dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * bm_packed_index; + uint8_t* u8_weight_src = dec_weights_uquant + BLOCK_MAX_WEIGHTS * bm_packed_index; for (unsigned int j = 0; j < di.weight_count; j++) { @@ -545,52 +538,56 @@ static float compress_symbolic_block_for_partition_1plane( for (unsigned int l = 0; l < config.tune_refinement_limit; l++) { recompute_ideal_colors_1plane( - blk, pi, di, - weight_quant_mode, workscb.weights, - eix[decimation_mode].ep, rgbs_colors, rgbo_colors); + blk, pi, di, workscb.weights, + workep, rgbs_colors, rgbo_colors); - // Quantize the chosen color + // Quantize the chosen color, tracking if worth trying the mod value + bool all_same = color_quant_level[i] != color_quant_level_mod[i]; for (unsigned int j = 0; j < partition_count; j++) { workscb.color_formats[j] = pack_color_endpoints( privateProfile, - eix[decimation_mode].ep.endpt0[j], - eix[decimation_mode].ep.endpt1[j], + workep.endpt0[j], + workep.endpt1[j], rgbs_colors[j], rgbo_colors[j], partition_format_specifiers[i][j], workscb.color_values[j], color_quant_level[i]); + + all_same = all_same && workscb.color_formats[j] == workscb.color_formats[0]; } // If all the color endpoint modes are the same, we get a few more bits to store colors; // let's see if we can take advantage of this: requantize all the colors and see if the // endpoint modes remain the same. workscb.color_formats_matched = 0; - - if ((partition_count >= 2 && workscb.color_formats[0] == workscb.color_formats[1] - && color_quant_level[i] != color_quant_level_mod[i]) - && (partition_count == 2 || (workscb.color_formats[0] == workscb.color_formats[2] - && (partition_count == 3 || (workscb.color_formats[0] == workscb.color_formats[3]))))) + if (partition_count >= 2 && all_same) { - uint8_t colorvals[BLOCK_MAX_PARTITIONS][12]; + uint8_t colorvals[BLOCK_MAX_PARTITIONS][8]; uint8_t color_formats_mod[BLOCK_MAX_PARTITIONS] { 0 }; + bool all_same_mod = true; for (unsigned int j = 0; j < partition_count; j++) { color_formats_mod[j] = pack_color_endpoints( privateProfile, - eix[decimation_mode].ep.endpt0[j], - eix[decimation_mode].ep.endpt1[j], + workep.endpt0[j], + workep.endpt1[j], rgbs_colors[j], rgbo_colors[j], partition_format_specifiers[i][j], colorvals[j], color_quant_level_mod[i]); + + // Early out as soon as it's no longer possible to use mod + if (color_formats_mod[j] != color_formats_mod[0]) + { + all_same_mod = false; + break; + } } - if (color_formats_mod[0] == color_formats_mod[1] - && (partition_count == 2 || (color_formats_mod[0] == color_formats_mod[2] - && (partition_count == 3 || (color_formats_mod[0] == color_formats_mod[3]))))) + if (all_same_mod) { workscb.color_formats_matched = 1; for (unsigned int j = 0; j < BLOCK_MAX_PARTITIONS; j++) @@ -631,12 +628,12 @@ static float compress_symbolic_block_for_partition_1plane( trace_add_data("error_prerealign", errorval); best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode); - // Average refinement improvement is 3.5% per iteration (allow 5%), but the first - // iteration can help more so we give it a extra 10% leeway. Use this knowledge to + // Average refinement improvement is 3.5% per iteration (allow 4.5%), but the first + // iteration can help more so we give it a extra 8% leeway. Use this knowledge to // drive a heuristic to skip blocks that are unlikely to catch up with the best // block we have already. unsigned int iters_remaining = config.tune_refinement_limit - l; - float threshold = (0.05f * static_cast(iters_remaining)) + 1.1f; + float threshold = (0.045f * static_cast(iters_remaining)) + 1.08f; if (errorval > (threshold * best_errorval_in_scb)) { break; @@ -681,10 +678,10 @@ static float compress_symbolic_block_for_partition_1plane( best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode); // Average refinement improvement is 3.5% per iteration, so skip blocks that are - // unlikely to catch up with the best block we have already. Assume a 5% per step to + // unlikely to catch up with the best block we have already. Assume a 4.5% per step to // give benefit of the doubt ... unsigned int iters_remaining = config.tune_refinement_limit - 1 - l; - float threshold = (0.05f * static_cast(iters_remaining)) + 1.0f; + float threshold = (0.045f * static_cast(iters_remaining)) + 1.0f; if (errorval > (threshold * best_errorval_in_scb)) { break; @@ -733,29 +730,30 @@ static float compress_symbolic_block_for_partition_2planes( float tune_errorval_threshold, unsigned int plane2_component, symbolic_compressed_block& scb, - compression_working_buffers& tmpbuf + compression_working_buffers& tmpbuf, + int quant_limit ) { promise(config.tune_candidate_limit > 0); promise(config.tune_refinement_limit > 0); promise(bsd.decimation_mode_count_selected > 0); + int max_weight_quant = astc::min(static_cast(QUANT_32), quant_limit); + // Compute ideal weights and endpoint colors, with no quantization or decimation endpoints_and_weights& ei1 = tmpbuf.ei1; endpoints_and_weights& ei2 = tmpbuf.ei2; - endpoints_and_weights* eix1 = tmpbuf.eix1; - endpoints_and_weights* eix2 = tmpbuf.eix2; + compute_ideal_colors_and_weights_2planes(bsd, blk, plane2_component, ei1, ei2); // Compute ideal weights and endpoint colors for every decimation - float *dec_weights_ideal_value = tmpbuf.dec_weights_ideal_value; - float *dec_weights_quant_uvalue = tmpbuf.dec_weights_quant_uvalue; - uint8_t *dec_weights_quant_pvalue = tmpbuf.dec_weights_quant_pvalue; + float* dec_weights_ideal = tmpbuf.dec_weights_ideal; + uint8_t* dec_weights_uquant = tmpbuf.dec_weights_uquant; // For each decimation mode, compute an ideal set of weights with no quantization for (unsigned int i = 0; i < bsd.decimation_mode_count_selected; i++) { const auto& dm = bsd.get_decimation_mode(i); - if (!dm.ref_2_planes) + if (!dm.is_ref_2plane(static_cast(max_weight_quant))) { continue; } @@ -764,15 +762,13 @@ static float compress_symbolic_block_for_partition_2planes( compute_ideal_weights_for_decimation( ei1, - eix1[i], di, - dec_weights_ideal_value + i * BLOCK_MAX_WEIGHTS); + dec_weights_ideal + i * BLOCK_MAX_WEIGHTS); compute_ideal_weights_for_decimation( ei2, - eix2[i], di, - dec_weights_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET); + dec_weights_ideal + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET); } // Compute maximum colors for the endpoints and ideal weights, then for each endpoint and ideal @@ -800,9 +796,7 @@ static float compress_symbolic_block_for_partition_2planes( float min_wt_cutoff2 = hmin_s(select(err_max, min_ep2, err_mask)); compute_angular_endpoints_2planes( - config.tune_low_weight_count_limit, - bsd, dec_weights_ideal_value, - tmpbuf); + bsd, dec_weights_ideal, max_weight_quant, tmpbuf); // For each mode (which specifies a decimation and a quantization): // * Compute number of bits needed for the quantized weights @@ -814,7 +808,7 @@ static float compress_symbolic_block_for_partition_2planes( float* weight_low_value2 = tmpbuf.weight_low_value2; float* weight_high_value2 = tmpbuf.weight_high_value2; - int* qwt_bitcounts = tmpbuf.qwt_bitcounts; + int8_t* qwt_bitcounts = tmpbuf.qwt_bitcounts; float* qwt_errors = tmpbuf.qwt_errors; unsigned int start_2plane = bsd.block_mode_count_1plane_selected; @@ -825,7 +819,13 @@ static float compress_symbolic_block_for_partition_2planes( const block_mode& bm = bsd.block_modes[i]; assert(bm.is_dual_plane); - qwt_bitcounts[i] = 109 - bm.weight_bits; + if (bm.quant_mode > max_weight_quant) + { + qwt_errors[i] = 1e38f; + continue; + } + + qwt_bitcounts[i] = static_cast(109 - bm.weight_bits); if (weight_high_value1[i] > 1.02f * min_wt_cutoff1) { @@ -840,36 +840,38 @@ static float compress_symbolic_block_for_partition_2planes( unsigned int decimation_mode = bm.decimation_mode; const auto& di = bsd.get_decimation_info(decimation_mode); + ASTCENC_ALIGNAS float dec_weights_uquantf[BLOCK_MAX_WEIGHTS]; + // Generate the optimized set of weights for the mode compute_quantized_weights_for_decimation( di, weight_low_value1[i], weight_high_value1[i], - dec_weights_ideal_value + BLOCK_MAX_WEIGHTS * decimation_mode, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i, - dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * i, + dec_weights_ideal + BLOCK_MAX_WEIGHTS * decimation_mode, + dec_weights_uquantf, + dec_weights_uquant + BLOCK_MAX_WEIGHTS * i, bm.get_weight_quant_mode()); compute_quantized_weights_for_decimation( di, weight_low_value2[i], weight_high_value2[i], - dec_weights_ideal_value + BLOCK_MAX_WEIGHTS * decimation_mode + WEIGHTS_PLANE2_OFFSET, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i + WEIGHTS_PLANE2_OFFSET, - dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * i + WEIGHTS_PLANE2_OFFSET, + dec_weights_ideal + BLOCK_MAX_WEIGHTS * decimation_mode + WEIGHTS_PLANE2_OFFSET, + dec_weights_uquantf + WEIGHTS_PLANE2_OFFSET, + dec_weights_uquant + BLOCK_MAX_WEIGHTS * i + WEIGHTS_PLANE2_OFFSET, bm.get_weight_quant_mode()); // Compute weight quantization errors for the block mode qwt_errors[i] = compute_error_of_weight_set_2planes( - eix1[decimation_mode], - eix2[decimation_mode], + ei1, + ei2, di, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i, - dec_weights_quant_uvalue + BLOCK_MAX_WEIGHTS * i + WEIGHTS_PLANE2_OFFSET); + dec_weights_uquantf, + dec_weights_uquantf + WEIGHTS_PLANE2_OFFSET); } // Decide the optimal combination of color endpoint encodings and weight encodings - int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS]; + uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS]; int block_mode_index[TUNE_MAX_TRIAL_CANDIDATES]; quant_method color_quant_level[TUNE_MAX_TRIAL_CANDIDATES]; @@ -901,25 +903,22 @@ static float compress_symbolic_block_for_partition_2planes( const block_mode& qw_bm = bsd.block_modes[bm_packed_index]; int decimation_mode = qw_bm.decimation_mode; - int weight_quant_mode = qw_bm.quant_mode; const auto& di = bsd.get_decimation_info(decimation_mode); promise(di.weight_count > 0); trace_add_data("weight_x", di.weight_x); trace_add_data("weight_y", di.weight_y); trace_add_data("weight_z", di.weight_z); - trace_add_data("weight_quant", weight_quant_mode); - - // Recompute the ideal color endpoints before storing them. - merge_endpoints(eix1[decimation_mode].ep, eix2[decimation_mode].ep, plane2_component, epm); + trace_add_data("weight_quant", qw_bm.quant_mode); vfloat4 rgbs_color; vfloat4 rgbo_color; symbolic_compressed_block workscb; + endpoints workep = epm; - uint8_t* u8_weight1_src = dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * bm_packed_index; - uint8_t* u8_weight2_src = dec_weights_quant_pvalue + BLOCK_MAX_WEIGHTS * bm_packed_index + WEIGHTS_PLANE2_OFFSET; + uint8_t* u8_weight1_src = dec_weights_uquant + BLOCK_MAX_WEIGHTS * bm_packed_index; + uint8_t* u8_weight2_src = dec_weights_uquant + BLOCK_MAX_WEIGHTS * bm_packed_index + WEIGHTS_PLANE2_OFFSET; for (int j = 0; j < di.weight_count; j++) { @@ -930,15 +929,15 @@ static float compress_symbolic_block_for_partition_2planes( for (unsigned int l = 0; l < config.tune_refinement_limit; l++) { recompute_ideal_colors_2planes( - blk, bsd, di, weight_quant_mode, + blk, bsd, di, workscb.weights, workscb.weights + WEIGHTS_PLANE2_OFFSET, - epm, rgbs_color, rgbo_color, plane2_component); + workep, rgbs_color, rgbo_color, plane2_component); // Quantize the chosen color workscb.color_formats[0] = pack_color_endpoints( privateProfile, - epm.endpt0[0], - epm.endpt1[0], + workep.endpt0[0], + workep.endpt1[0], rgbs_color, rgbo_color, partition_format_specifiers[i][0], workscb.color_values[0], @@ -966,12 +965,12 @@ static float compress_symbolic_block_for_partition_2planes( trace_add_data("error_prerealign", errorval); best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode); - // Average refinement improvement is 3.5% per iteration (allow 5%), but the first - // iteration can help more so we give it a extra 10% leeway. Use this knowledge to + // Average refinement improvement is 3.5% per iteration (allow 4.5%), but the first + // iteration can help more so we give it a extra 8% leeway. Use this knowledge to // drive a heuristic to skip blocks that are unlikely to catch up with the best // block we have already. unsigned int iters_remaining = config.tune_refinement_limit - l; - float threshold = (0.05f * static_cast(iters_remaining)) + 1.1f; + float threshold = (0.045f * static_cast(iters_remaining)) + 1.08f; if (errorval > (threshold * best_errorval_in_scb)) { break; @@ -1017,10 +1016,10 @@ static float compress_symbolic_block_for_partition_2planes( best_errorval_in_mode = astc::min(errorval, best_errorval_in_mode); // Average refinement improvement is 3.5% per iteration, so skip blocks that are - // unlikely to catch up with the best block we have already. Assume a 5% per step to + // unlikely to catch up with the best block we have already. Assume a 4.5% per step to // give benefit of the doubt ... unsigned int iters_remaining = config.tune_refinement_limit - 1 - l; - float threshold = (0.05f * static_cast(iters_remaining)) + 1.0f; + float threshold = (0.045f * static_cast(iters_remaining)) + 1.0f; if (errorval > (threshold * best_errorval_in_scb)) { break; @@ -1132,12 +1131,13 @@ static float prepare_block_statistics( aa_var -= as * (as * rpt); - rg_cov *= astc::rsqrt(astc::max(rr_var * gg_var, 1e-30f)); - rb_cov *= astc::rsqrt(astc::max(rr_var * bb_var, 1e-30f)); - ra_cov *= astc::rsqrt(astc::max(rr_var * aa_var, 1e-30f)); - gb_cov *= astc::rsqrt(astc::max(gg_var * bb_var, 1e-30f)); - ga_cov *= astc::rsqrt(astc::max(gg_var * aa_var, 1e-30f)); - ba_cov *= astc::rsqrt(astc::max(bb_var * aa_var, 1e-30f)); + // These will give a NaN if a channel is constant - these are fixed up in the next step + rg_cov *= astc::rsqrt(rr_var * gg_var); + rb_cov *= astc::rsqrt(rr_var * bb_var); + ra_cov *= astc::rsqrt(rr_var * aa_var); + gb_cov *= astc::rsqrt(gg_var * bb_var); + ga_cov *= astc::rsqrt(gg_var * aa_var); + ba_cov *= astc::rsqrt(bb_var * aa_var); if (astc::isnan(rg_cov)) rg_cov = 1.0f; if (astc::isnan(rb_cov)) rb_cov = 1.0f; @@ -1146,7 +1146,7 @@ static float prepare_block_statistics( if (astc::isnan(ga_cov)) ga_cov = 1.0f; if (astc::isnan(ba_cov)) ba_cov = 1.0f; - float lowest_correlation = astc::min(fabsf(rg_cov), fabsf(rb_cov)); + float lowest_correlation = astc::min(fabsf(rg_cov), fabsf(rb_cov)); lowest_correlation = astc::min(lowest_correlation, fabsf(ra_cov)); lowest_correlation = astc::min(lowest_correlation, fabsf(gb_cov)); lowest_correlation = astc::min(lowest_correlation, fabsf(ga_cov)); @@ -1173,9 +1173,9 @@ static float prepare_block_statistics( /* See header for documentation. */ void compress_block( - const astcenc_context& ctx, + const astcenc_contexti& ctx, const image_block& blk, - physical_compressed_block& pcb, + uint8_t pcb[16], #if QUALITY_CONTROL compression_working_buffers& tmpbuf, bool calQualityEnable, @@ -1206,16 +1206,28 @@ void compress_block( bool block_skip_two_plane = false; int max_partitions = (ctx.config.privateProfile == HIGH_SPEED_PROFILE) ? 1 : ctx.config.tune_partition_count_limit; + unsigned int requested_partition_indices[3] { + ctx.config.tune_2partition_index_limit, + ctx.config.tune_3partition_index_limit, + ctx.config.tune_4partition_index_limit + }; + + unsigned int requested_partition_trials[3] { + ctx.config.tune_2partitioning_candidate_limit, + ctx.config.tune_3partitioning_candidate_limit, + ctx.config.tune_4partitioning_candidate_limit + }; + #if defined(ASTCENC_DIAGNOSTICS) // Do this early in diagnostic builds so we can dump uniform metrics // for every block. Do it later in release builds to avoid redundant work! - float error_weight_sum = hadd_s(blk.channel_weight) * bsd->texel_count; + float error_weight_sum = hadd_s(blk.channel_weight) * bsd.texel_count; float error_threshold = ctx.config.tune_db_limit * error_weight_sum * block_is_l_scale * block_is_la_scale; - lowest_correl = prepare_block_statistics(bsd->texel_count, blk); + lowest_correl = prepare_block_statistics(bsd.texel_count, blk); trace_add_data("lowest_correl", lowest_correl); trace_add_data("tune_error_threshold", error_threshold); #endif @@ -1228,6 +1240,7 @@ void compress_block( trace_add_data("plane_count", 1); scb.partition_count = 0; + // Encode as FP16 if using HDR if ((decode_mode == ASTCENC_PRF_HDR) || (decode_mode == ASTCENC_PRF_HDR_RGB_LDR_A)) @@ -1244,6 +1257,7 @@ void compress_block( vint4 color_u16 = float_to_int_rtn(color_f32); store(color_u16, scb.constant_color); } + trace_add_data("exit", "quality hit"); if (ctx.config.privateProfile == HIGH_SPEED_PROFILE) { @@ -1258,7 +1272,7 @@ void compress_block( for (int w = 0; w < 16; w++) { // weights num is 16 when block mode is HIGH_SPEED_PROFILE_BLOCK_MODE scb.weights[w] = 0; } - for (int pixel = 0; pixel < BLOCK_MAX_COMPONENTS; pixel++) { // scb.constant_color[pixel] is 16 bit + for (unsigned int pixel = 0; pixel < BLOCK_MAX_COMPONENTS; pixel++) { // scb.constant_color[pixel] is 16 bit scb.color_values[0][pixel << 1] = scb.constant_color[pixel] & BYTE_MASK; // low byte scb.color_values[0][(pixel << 1) + 1] = (scb.constant_color[pixel] >> 8) & BYTE_MASK; // high byte } @@ -1291,8 +1305,8 @@ void compress_block( float exit_thresholds_for_pcount[BLOCK_MAX_PARTITIONS] { 0.0f, - ctx.config.tune_2_partition_early_out_limit_factor, - ctx.config.tune_3_partition_early_out_limit_factor, + ctx.config.tune_2partition_early_out_limit_factor, + ctx.config.tune_3partition_early_out_limit_factor, 0.0f }; @@ -1304,19 +1318,21 @@ void compress_block( // compression and slightly reduces image quality. float errorval_mult[2] { - 1.0f / ctx.config.tune_mode0_mse_overshoot, + 1.0f / ctx.config.tune_mse_overshoot, 1.0f }; - static const float errorval_overshoot = 1.0f / ctx.config.tune_refinement_mse_overshoot; + static const float errorval_overshoot = 1.0f / ctx.config.tune_mse_overshoot; - // Only enable MODE0 fast path (trial 0) if 2D and more than 25 texels + // Only enable MODE0 fast path if enabled + // Never enable for 3D blocks as no "always" block modes are available int start_trial = 1; - if ((bsd.texel_count >= TUNE_MIN_TEXELS_MODE0_FASTPATH) && (bsd.zdim == 1)) + if ((ctx.config.tune_search_mode0_enable >= TUNE_MIN_SEARCH_MODE0) && (bsd.zdim == 1)) { start_trial = 0; } + int quant_limit = QUANT_32; for (int i = start_trial; i < 2; i++) { TRACE_NODE(node1, "pass"); @@ -1328,7 +1344,11 @@ void compress_block( ctx.config.privateProfile, ctx.config, bsd, blk, i == 0, error_threshold * errorval_mult[i] * errorval_overshoot, - 1, 0, scb, tmpbuf); + 1, 0, scb, tmpbuf, QUANT_32); + + // Record the quant level so we can use the filter later searches + const auto& bm = bsd.get_block_mode(scb.block_mode); + quant_limit = bm.get_weight_quant_mode(); best_errorvals_for_pcount[0] = astc::min(best_errorvals_for_pcount[0], errorval); if ((ctx.config.privateProfile == HIGH_SPEED_PROFILE) || (errorval < (error_threshold * errorval_mult[i]))) @@ -1342,7 +1362,7 @@ void compress_block( lowest_correl = prepare_block_statistics(bsd.texel_count, blk); #endif - block_skip_two_plane = lowest_correl > ctx.config.tune_2_plane_early_out_limit_correlation; + block_skip_two_plane = lowest_correl > ctx.config.tune_2plane_early_out_limit_correlation; // Test the four possible 1-partition, 2-planes modes. Do this in reverse, as // alpha is the most likely to be non-correlated if it is present in the data. @@ -1359,7 +1379,7 @@ void compress_block( if (block_skip_two_plane) { - trace_add_data("skip", "tune_2_plane_early_out_limit_correlation"); + trace_add_data("skip", "tune_2plane_early_out_limit_correlation"); continue; } @@ -1378,11 +1398,11 @@ void compress_block( float errorval = compress_symbolic_block_for_partition_2planes( ctx.config.privateProfile, ctx.config, bsd, blk, error_threshold * errorval_overshoot, - i, scb, tmpbuf); + i, scb, tmpbuf, quant_limit); // If attempting two planes is much worse than the best one plane result // then further two plane searches are unlikely to help so move on ... - if (errorval > (best_errorvals_for_pcount[0] * 2.0f)) + if (errorval > (best_errorvals_for_pcount[0] * 1.85f)) { break; } @@ -1397,13 +1417,19 @@ void compress_block( // Find best blocks for 2, 3 and 4 partitions for (int partition_count = 2; partition_count <= max_partitions; partition_count++) { - unsigned int partition_indices[2] { 0 }; + unsigned int partition_indices[TUNE_MAX_PARTITIONING_CANDIDATES]; + + unsigned int requested_indices = requested_partition_indices[partition_count - 2]; - find_best_partition_candidates(bsd, blk, partition_count, - ctx.config.tune_partition_index_limit, - partition_indices); + unsigned int requested_trials = requested_partition_trials[partition_count - 2]; + requested_trials = astc::min(requested_trials, requested_indices); - for (unsigned int i = 0; i < 2; i++) + unsigned int actual_trials = find_best_partition_candidates( + bsd, blk, partition_count, requested_indices, partition_indices, requested_trials); + + float best_error_in_prev = best_errorvals_for_pcount[partition_count - 2]; + + for (unsigned int i = 0; i < actual_trials; i++) { TRACE_NODE(node1, "pass"); trace_add_data("partition_count", partition_count); @@ -1416,9 +1442,22 @@ void compress_block( ctx.config, bsd, blk, false, error_threshold * errorval_overshoot, partition_count, partition_indices[i], - scb, tmpbuf); + scb, tmpbuf, quant_limit); best_errorvals_for_pcount[partition_count - 1] = astc::min(best_errorvals_for_pcount[partition_count - 1], errorval); + + // If using N partitions doesn't improve much over using N-1 partitions then skip trying + // N+1. Error can dramatically improve if the data is correlated or non-correlated and + // aligns with a partitioning that suits that encoding, so for this inner loop check add + // a large error scale because the "other" trial could be a lot better. + float best_error = best_errorvals_for_pcount[partition_count - 1]; + float best_error_scale = exit_thresholds_for_pcount[partition_count - 1] * 1.85f; + if (best_error > (best_error_in_prev * best_error_scale)) + { + trace_add_data("skip", "tune_partition_early_out_limit_factor"); + goto END_OF_TESTS; + } + if (errorval < error_threshold) { trace_add_data("exit", "quality hit"); @@ -1428,7 +1467,6 @@ void compress_block( // If using N partitions doesn't improve much over using N-1 partitions then skip trying N+1 float best_error = best_errorvals_for_pcount[partition_count - 1]; - float best_error_in_prev = best_errorvals_for_pcount[partition_count - 2]; float best_error_scale = exit_thresholds_for_pcount[partition_count - 1]; if (best_error > (best_error_in_prev * best_error_scale)) { @@ -1455,7 +1493,6 @@ END_OF_TESTS: #endif scb.block_type = SYM_BTYPE_CONST_U16; - scb.block_mode = -2; vfloat4 color_f32 = clamp(0.0f, 1.0f, blk.origin_texel) * 65535.0f; vint4 color_u16 = float_to_int_rtn(color_f32); store(color_u16, scb.constant_color); diff --git a/Source/astcenc_compute_variance.cpp b/Source/astcenc_compute_variance.cpp index 2284e90..dc3ad2c 100644 --- a/Source/astcenc_compute_variance.cpp +++ b/Source/astcenc_compute_variance.cpp @@ -99,17 +99,9 @@ static void brent_kung_prefix_sum( } while (lc_stride > 2); } -/** - * @brief Compute averages for a pixel region. - * - * The routine computes both in a single pass, using a summed-area table to decouple the running - * time from the averaging/variance kernel size. - * - * @param[out] ctx The compressor context storing the output data. - * @param arg The input parameter structure. - */ -static void compute_pixel_region_variance( - astcenc_context& ctx, +/* See header for documentation. */ +void compute_pixel_region_variance( + astcenc_contexti& ctx, const pixel_region_args& arg ) { // Unpack the memory structure into local variables @@ -427,57 +419,6 @@ static void compute_pixel_region_variance( } } -void compute_averages( - astcenc_context& ctx, - const avg_args &ag -) { - pixel_region_args arg = ag.arg; - arg.work_memory = new vfloat4[ag.work_memory_size]; - - int size_x = ag.img_size_x; - int size_y = ag.img_size_y; - int size_z = ag.img_size_z; - - int step_xy = ag.blk_size_xy; - int step_z = ag.blk_size_z; - - int y_tasks = (size_y + step_xy - 1) / step_xy; - - // All threads run this processing loop until there is no work remaining - while (true) - { - unsigned int count; - unsigned int base = ctx.manage_avg.get_task_assignment(16, count); - if (!count) - { - break; - } - - for (unsigned int i = base; i < base + count; i++) - { - int z = (i / (y_tasks)) * step_z; - int y = (i - (z * y_tasks)) * step_xy; - - arg.size_z = astc::min(step_z, size_z - z); - arg.offset_z = z; - - arg.size_y = astc::min(step_xy, size_y - y); - arg.offset_y = y; - - for (int x = 0; x < size_x; x += step_xy) - { - arg.size_x = astc::min(step_xy, size_x - x); - arg.offset_x = x; - compute_pixel_region_variance(ctx, arg); - } - } - - ctx.manage_avg.complete_task_assignment(count); - } - - delete[] arg.work_memory; -} - /* See header for documentation. */ unsigned int init_compute_averages( const astcenc_image& img, diff --git a/Source/astcenc_decompress_symbolic.cpp b/Source/astcenc_decompress_symbolic.cpp index 6d50d51..7463f7e 100644 --- a/Source/astcenc_decompress_symbolic.cpp +++ b/Source/astcenc_decompress_symbolic.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -24,48 +24,18 @@ #include #include -/** - * @brief Compute a vector of texel weights by interpolating the decimated weight grid. - * - * @param base_texel_index The first texel to get; N (SIMD width) consecutive texels are loaded. - * @param di The weight grid decimation to use. - * @param weights The raw weights. - * - * @return The undecimated weight for N (SIMD width) texels. - */ -static vint compute_value_of_texel_weight_int_vla( - int base_texel_index, - const decimation_info& di, - const int* weights -) { - vint summed_value(8); - vint weight_count(di.texel_weight_count + base_texel_index); - int max_weight_count = hmax(weight_count).lane<0>(); - - promise(max_weight_count > 0); - for (int i = 0; i < max_weight_count; i++) - { - vint texel_weights(di.texel_weights_4t[i] + base_texel_index); - vint texel_weights_int(di.texel_weights_int_4t[i] + base_texel_index); - - summed_value += gatheri(weights, texel_weights) * texel_weights_int; - } - - return lsr<4>(summed_value); -} - /** * @brief Compute the integer linear interpolation of two color endpoints. * - * @param decode_mode The ASTC profile (linear or sRGB) + * @param u8_mask The mask for lanes using decode_unorm8 rather than decode_f16. * @param color0 The endpoint0 color. * @param color1 The endpoint1 color. - * @param weights The interpolation weight (between 0 and 64). + * @param weights The interpolation weight (between 0 and 64). * * @return The interpolated color. */ static vint4 lerp_color_int( - astcenc_profile decode_mode, + vmask4 u8_mask, vint4 color0, vint4 color1, vint4 weights @@ -73,24 +43,18 @@ static vint4 lerp_color_int( vint4 weight1 = weights; vint4 weight0 = vint4(64) - weight1; - if (decode_mode == ASTCENC_PRF_LDR_SRGB) - { - color0 = asr<8>(color0); - color1 = asr<8>(color1); - } - vint4 color = (color0 * weight0) + (color1 * weight1) + vint4(32); color = asr<6>(color); - if (decode_mode == ASTCENC_PRF_LDR_SRGB) - { - color = color * vint4(257); - } + // For decode_unorm8 values force the codec to bit replicate. This allows the + // rest of the codec to assume the full 0xFFFF range for everything and ignore + // the decode_mode setting + vint4 color_u8 = asr<8>(color) * vint4(257); + color = select(color, color_u8, u8_mask); return color; } - /** * @brief Convert integer color value into a float value for the decoder. * @@ -127,43 +91,74 @@ void unpack_weights( const symbolic_compressed_block& scb, const decimation_info& di, bool is_dual_plane, - quant_method quant_level, int weights_plane1[BLOCK_MAX_TEXELS], int weights_plane2[BLOCK_MAX_TEXELS] ) { - // First, unquantize the weights ... - int uq_plane1_weights[BLOCK_MAX_WEIGHTS]; - int uq_plane2_weights[BLOCK_MAX_WEIGHTS]; - unsigned int weight_count = di.weight_count; - - const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[quant_level]); - - // Second, undecimate the weights ... // Safe to overshoot as all arrays are allocated to full size if (!is_dual_plane) { - for (unsigned int i = 0; i < weight_count; i++) - { - uq_plane1_weights[i] = qat->unquantized_value[scb.weights[i]]; - } + // Build full 64-entry weight lookup table + vint4 tab0 = vint4::load(scb.weights + 0); + vint4 tab1 = vint4::load(scb.weights + 16); + vint4 tab2 = vint4::load(scb.weights + 32); + vint4 tab3 = vint4::load(scb.weights + 48); + + vint tab0p, tab1p, tab2p, tab3p; + vtable_prepare(tab0, tab1, tab2, tab3, tab0p, tab1p, tab2p, tab3p); for (unsigned int i = 0; i < bsd.texel_count; i += ASTCENC_SIMD_WIDTH) { - store(compute_value_of_texel_weight_int_vla(i, di, uq_plane1_weights), weights_plane1 + i); + vint summed_value(8); + vint weight_count(di.texel_weight_count + i); + int max_weight_count = hmax(weight_count).lane<0>(); + + promise(max_weight_count > 0); + for (int j = 0; j < max_weight_count; j++) + { + vint texel_weights(di.texel_weights_tr[j] + i); + vint texel_weights_int(di.texel_weight_contribs_int_tr[j] + i); + + summed_value += vtable_8bt_32bi(tab0p, tab1p, tab2p, tab3p, texel_weights) * texel_weights_int; + } + + store(lsr<4>(summed_value), weights_plane1 + i); } } else { - for (unsigned int i = 0; i < weight_count; i++) - { - uq_plane1_weights[i] = qat->unquantized_value[scb.weights[i]]; - uq_plane2_weights[i] = qat->unquantized_value[scb.weights[i + WEIGHTS_PLANE2_OFFSET]]; - } + // Build a 32-entry weight lookup table per plane + // Plane 1 + vint4 tab0_plane1 = vint4::load(scb.weights + 0); + vint4 tab1_plane1 = vint4::load(scb.weights + 16); + vint tab0_plane1p, tab1_plane1p; + vtable_prepare(tab0_plane1, tab1_plane1, tab0_plane1p, tab1_plane1p); + + // Plane 2 + vint4 tab0_plane2 = vint4::load(scb.weights + 32); + vint4 tab1_plane2 = vint4::load(scb.weights + 48); + vint tab0_plane2p, tab1_plane2p; + vtable_prepare(tab0_plane2, tab1_plane2, tab0_plane2p, tab1_plane2p); for (unsigned int i = 0; i < bsd.texel_count; i += ASTCENC_SIMD_WIDTH) { - store(compute_value_of_texel_weight_int_vla(i, di, uq_plane1_weights), weights_plane1 + i); - store(compute_value_of_texel_weight_int_vla(i, di, uq_plane2_weights), weights_plane2 + i); + vint sum_plane1(8); + vint sum_plane2(8); + + vint weight_count(di.texel_weight_count + i); + int max_weight_count = hmax(weight_count).lane<0>(); + + promise(max_weight_count > 0); + for (int j = 0; j < max_weight_count; j++) + { + vint texel_weights(di.texel_weights_tr[j] + i); + vint texel_weights_int(di.texel_weight_contribs_int_tr[j] + i); + + sum_plane1 += vtable_8bt_32bi(tab0_plane1p, tab1_plane1p, texel_weights) * texel_weights_int; + sum_plane2 += vtable_8bt_32bi(tab0_plane2p, tab1_plane2p, texel_weights) * texel_weights_int; + } + + store(lsr<4>(sum_plane1), weights_plane1 + i); + store(lsr<4>(sum_plane2), weights_plane2 + i); } } } @@ -228,12 +223,13 @@ void decompress_symbolic_block( { vint4 colori(scb.constant_color); - // For sRGB decoding a real decoder would just use the top 8 bits for color conversion. - // We don't color convert, so rescale the top 8 bits into the full 16 bit dynamic range. - if (decode_mode == ASTCENC_PRF_LDR_SRGB) - { - colori = asr<8>(colori) * 257; - } + // Determine the UNORM8 rounding on the decode + vmask4 u8_mask = get_u8_component_mask(decode_mode, blk); + + // The real decoder would just use the top 8 bits, but we rescale + // in to a 16-bit value that rounds correctly. + vint4 colori_u8 = asr<8>(colori) * 257; + colori = select(colori, colori_u8, u8_mask); vint4 colorf16 = unorm16_to_sf16(colori); color = float16_to_float(colorf16); @@ -277,17 +273,19 @@ void decompress_symbolic_block( const auto& bm = bsd.get_block_mode(scb.block_mode); const auto& di = bsd.get_decimation_info(bm.decimation_mode); - int is_dual_plane = bm.is_dual_plane; + bool is_dual_plane = static_cast(bm.is_dual_plane); // Unquantize and undecimate the weights int plane1_weights[BLOCK_MAX_TEXELS]; int plane2_weights[BLOCK_MAX_TEXELS]; - unpack_weights(bsd, scb, di, is_dual_plane, bm.get_weight_quant_mode(), plane1_weights, plane2_weights); + unpack_weights(bsd, scb, di, is_dual_plane, plane1_weights, plane2_weights); // Now that we have endpoint colors and weights, we can unpack texel colors - int plane2_component = is_dual_plane ? scb.plane2_component : -1; + int plane2_component = scb.plane2_component; vmask4 plane2_mask = vint4::lane_id() == vint4(plane2_component); + vmask4 u8_mask = get_u8_component_mask(decode_mode, blk); + for (int i = 0; i < partition_count; i++) { // Decode the color endpoints for this partition @@ -298,7 +296,6 @@ void decompress_symbolic_block( unpack_color_endpoints(decode_mode, scb.color_formats[i], - scb.get_color_quant_mode(), scb.color_values[i], rgb_lns, a_lns, ep0, ep1); @@ -310,7 +307,7 @@ void decompress_symbolic_block( { int tix = pi.texels_of_partition[i][j]; vint4 weight = select(vint4(plane1_weights[tix]), vint4(plane2_weights[tix]), plane2_mask); - vint4 color = lerp_color_int(decode_mode, ep0, ep1, weight); + vint4 color = lerp_color_int(u8_mask, ep0, ep1, weight); vfloat4 colorf = decode_texel(color, lns_mask); blk.data_r[tix] = colorf.lane<0>(); @@ -347,7 +344,7 @@ float compute_symbolic_block_difference_2plane( // Unquantize and undecimate the weights int plane1_weights[BLOCK_MAX_TEXELS]; int plane2_weights[BLOCK_MAX_TEXELS]; - unpack_weights(bsd, scb, di, true, bm.get_weight_quant_mode(), plane1_weights, plane2_weights); + unpack_weights(bsd, scb, di, true, plane1_weights, plane2_weights); vmask4 plane2_mask = vint4::lane_id() == vint4(scb.plane2_component); @@ -361,17 +358,18 @@ float compute_symbolic_block_difference_2plane( unpack_color_endpoints(config.profile, scb.color_formats[0], - scb.get_color_quant_mode(), scb.color_values[0], rgb_lns, a_lns, ep0, ep1); + vmask4 u8_mask = get_u8_component_mask(config.profile, blk); + // Unpack and compute error for each texel in the partition unsigned int texel_count = bsd.texel_count; for (unsigned int i = 0; i < texel_count; i++) { vint4 weight = select(vint4(plane1_weights[i]), vint4(plane2_weights[i]), plane2_mask); - vint4 colori = lerp_color_int(config.profile, ep0, ep1, weight); + vint4 colori = lerp_color_int(u8_mask, ep0, ep1, weight); vfloat4 color = int_to_float(colori); vfloat4 oldColor = blk.texel(i); @@ -443,7 +441,9 @@ float compute_symbolic_block_difference_1plane( // Unquantize and undecimate the weights int plane1_weights[BLOCK_MAX_TEXELS]; - unpack_weights(bsd, scb, di, false, bm.get_weight_quant_mode(), plane1_weights, nullptr); + unpack_weights(bsd, scb, di, false, plane1_weights, nullptr); + + vmask4 u8_mask = get_u8_component_mask(config.profile, blk); vfloat4 summa = vfloat4::zero(); for (unsigned int i = 0; i < partition_count; i++) @@ -456,7 +456,6 @@ float compute_symbolic_block_difference_1plane( unpack_color_endpoints(config.profile, scb.color_formats[i], - scb.get_color_quant_mode(), scb.color_values[i], rgb_lns, a_lns, ep0, ep1); @@ -466,7 +465,7 @@ float compute_symbolic_block_difference_1plane( for (unsigned int j = 0; j < texel_count; j++) { unsigned int tix = pi.texels_of_partition[i][j]; - vint4 colori = lerp_color_int(config.profile, ep0, ep1, + vint4 colori = lerp_color_int(u8_mask, ep0, ep1, vint4(plane1_weights[tix])); vfloat4 color = int_to_float(colori); @@ -534,8 +533,8 @@ float compute_symbolic_block_difference_1plane_1partition( const decimation_info& di = bsd.get_decimation_info(bm.decimation_mode); // Unquantize and undecimate the weights - alignas(ASTCENC_VECALIGN) int plane1_weights[BLOCK_MAX_TEXELS]; - unpack_weights(bsd, scb, di, false, bm.get_weight_quant_mode(), plane1_weights, nullptr); + ASTCENC_ALIGNAS int plane1_weights[BLOCK_MAX_TEXELS]; + unpack_weights(bsd, scb, di, false, plane1_weights, nullptr); // Decode the color endpoints for this partition vint4 ep0; @@ -545,24 +544,16 @@ float compute_symbolic_block_difference_1plane_1partition( unpack_color_endpoints(config.profile, scb.color_formats[0], - scb.get_color_quant_mode(), scb.color_values[0], rgb_lns, a_lns, ep0, ep1); - - // Pre-shift sRGB so things round correctly - if (config.profile == ASTCENC_PRF_LDR_SRGB) - { - ep0 = asr<8>(ep0); - ep1 = asr<8>(ep1); - } + vmask4 u8_mask = get_u8_component_mask(config.profile, blk); // Unpack and compute error for each texel in the partition vfloatacc summav = vfloatacc::zero(); vint lane_id = vint::lane_id(); - vint srgb_scale(config.profile == ASTCENC_PRF_LDR_SRGB ? 257 : 1); unsigned int texel_count = bsd.texel_count; for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH) @@ -581,11 +572,25 @@ float compute_symbolic_block_difference_1plane_1partition( vint ep0_b = vint(ep0.lane<2>()) * weight0; vint ep0_a = vint(ep0.lane<3>()) * weight0; - // Shift so things round correctly - vint colori_r = asr<6>(ep0_r + ep1_r + vint(32)) * srgb_scale; - vint colori_g = asr<6>(ep0_g + ep1_g + vint(32)) * srgb_scale; - vint colori_b = asr<6>(ep0_b + ep1_b + vint(32)) * srgb_scale; - vint colori_a = asr<6>(ep0_a + ep1_a + vint(32)) * srgb_scale; + // Combine contributions + vint colori_r = asr<6>(ep0_r + ep1_r + vint(32)); + vint colori_g = asr<6>(ep0_g + ep1_g + vint(32)); + vint colori_b = asr<6>(ep0_b + ep1_b + vint(32)); + vint colori_a = asr<6>(ep0_a + ep1_a + vint(32)); + + // If using a U8 decode mode bit replicate top 8 bits + // so rest of codec can assume 0xFFFF max range everywhere + vint colori_r8 = asr<8>(colori_r) * vint(257); + colori_r = select(colori_r, colori_r8, vmask(u8_mask.lane<0>())); + + vint colori_g8 = asr<8>(colori_g) * vint(257); + colori_g = select(colori_g, colori_g8, vmask(u8_mask.lane<1>())); + + vint colori_b8 = asr<8>(colori_b) * vint(257); + colori_b = select(colori_b, colori_b8, vmask(u8_mask.lane<2>())); + + vint colori_a8 = asr<8>(colori_a) * vint(257); + colori_a = select(colori_a, colori_a8, vmask(u8_mask.lane<3>())); // Compute color diff vfloat color_r = int_to_float(colori_r); diff --git a/Source/astcenc_diagnostic_trace.cpp b/Source/astcenc_diagnostic_trace.cpp index fbf01a9..bcd6fa7 100644 --- a/Source/astcenc_diagnostic_trace.cpp +++ b/Source/astcenc_diagnostic_trace.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2021 Arm Limited +// Copyright 2021-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include "astcenc_diagnostic_trace.h" @@ -32,7 +34,7 @@ static TraceLog* g_TraceLog = nullptr; /** @brief The JSON indentation level. */ -static const int g_trace_indent = 2; +static const size_t g_trace_indent = 2; TraceLog::TraceLog( const char* file_name): @@ -55,7 +57,7 @@ TraceNode* TraceLog::get_current_leaf() } /* See header for documentation. */ -int TraceLog::get_depth() +size_t TraceLog::get_depth() { return m_stack.size(); } @@ -82,12 +84,12 @@ TraceNode::TraceNode( vsnprintf (buffer, bufsz, format, args); va_end (args); - // Guarantee there is a nul termintor + // Guarantee there is a nul terminator buffer[bufsz - 1] = 0; // Generate the node TraceNode* parent = g_TraceLog->get_current_leaf(); - int depth = g_TraceLog->get_depth(); + size_t depth = g_TraceLog->get_depth(); g_TraceLog->m_stack.push_back(this); bool comma = parent && parent->m_attrib_count; @@ -108,8 +110,8 @@ TraceNode::TraceNode( out << '\n'; } - int out_indent = (depth * 2) * g_trace_indent; - int in_indent = (depth * 2 + 1) * g_trace_indent; + size_t out_indent = (depth * 2) * g_trace_indent; + size_t in_indent = (depth * 2 + 1) * g_trace_indent; std::string out_indents(""); if (out_indent) @@ -131,8 +133,8 @@ void TraceNode::add_attrib( ) { (void)type; - int depth = g_TraceLog->get_depth(); - int indent = (depth * 2) * g_trace_indent; + size_t depth = g_TraceLog->get_depth(); + size_t indent = (depth * 2) * g_trace_indent; auto& out = g_TraceLog->m_file; bool comma = m_attrib_count; m_attrib_count++; @@ -154,9 +156,9 @@ TraceNode::~TraceNode() g_TraceLog->m_stack.pop_back(); auto& out = g_TraceLog->m_file; - int depth = g_TraceLog->get_depth(); - int out_indent = (depth * 2) * g_trace_indent; - int in_indent = (depth * 2 + 1) * g_trace_indent; + size_t depth = g_TraceLog->get_depth(); + size_t out_indent = (depth * 2) * g_trace_indent; + size_t in_indent = (depth * 2 + 1) * g_trace_indent; std::string out_indents(""); if (out_indent) @@ -189,7 +191,7 @@ void trace_add_data( vsnprintf (buffer, bufsz, format, args); va_end (args); - // Guarantee there is a nul termintor + // Guarantee there is a nul terminator buffer[bufsz - 1] = 0; std::string value = "\"" + std::string(buffer) + "\""; @@ -203,7 +205,20 @@ void trace_add_data( const char* key, float value ) { - char buffer[256]; + // Turn infinities into parseable values + if (std::isinf(value)) + { + if (value > 0.0f) + { + value = std::numeric_limits::max(); + } + else + { + value = -std::numeric_limits::max(); + } + } + + char buffer[256]; sprintf(buffer, "%.20g", (double)value); TraceNode* node = g_TraceLog->get_current_leaf(); node->add_attrib("float", key, buffer); diff --git a/Source/astcenc_diagnostic_trace.h b/Source/astcenc_diagnostic_trace.h index 6148949..f5586b0 100644 --- a/Source/astcenc_diagnostic_trace.h +++ b/Source/astcenc_diagnostic_trace.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2021 Arm Limited +// Copyright 2021-2022 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -148,7 +148,7 @@ public: * * @return The current leaf node stack depth. */ - int get_depth(); + size_t get_depth(); /** * @brief The file stream to write to. diff --git a/Source/astcenc_entry.cpp b/Source/astcenc_entry.cpp index 6f755cc..2126588 100644 --- a/Source/astcenc_entry.cpp +++ b/Source/astcenc_entry.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -24,7 +24,7 @@ #include #include "astcenc.h" -#include "astcenc_internal.h" +#include "astcenc_internal_entry.h" #include "astcenc_diagnostic_trace.h" /** @@ -40,89 +40,96 @@ struct astcenc_preset_config { float quality; unsigned int tune_partition_count_limit; - unsigned int tune_partition_index_limit; + unsigned int tune_2partition_index_limit; + unsigned int tune_3partition_index_limit; + unsigned int tune_4partition_index_limit; unsigned int tune_block_mode_limit; unsigned int tune_refinement_limit; unsigned int tune_candidate_limit; + unsigned int tune_2partitioning_candidate_limit; + unsigned int tune_3partitioning_candidate_limit; + unsigned int tune_4partitioning_candidate_limit; float tune_db_limit_a_base; float tune_db_limit_b_base; - float tune_mode0_mse_overshoot; - float tune_refinement_mse_overshoot; - float tune_2_partition_early_out_limit_factor; - float tune_3_partition_early_out_limit_factor; - float tune_2_plane_early_out_limit_correlation; - unsigned int tune_low_weight_count_limit; + float tune_mse_overshoot; + float tune_2partition_early_out_limit_factor; + float tune_3partition_early_out_limit_factor; + float tune_2plane_early_out_limit_correlation; + float tune_search_mode0_enable; }; - /** - * @brief The static quality presets that are built-in for high bandwidth - * presets (x < 25 texels per block). + * @brief The static presets for high bandwidth encodings (x < 25 texels per block). */ -static const std::array preset_configs_high {{ +static const std::array preset_configs_high {{ { ASTCENC_PRE_FASTEST, - 2, 8, 42, 2, 2, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 25 + 2, 10, 6, 4, 43, 2, 2, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.85f, 0.0f }, { ASTCENC_PRE_FAST, - 3, 12, 55, 3, 3, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.1f, 0.65f, 20 + 3, 18, 10, 8, 55, 3, 3, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.90f, 0.0f }, { ASTCENC_PRE_MEDIUM, - 4, 26, 76, 3, 3 , 95.0f, 70.0f, 2.5f, 2.5f, 1.2f, 1.25f, 0.85f, 16 + 4, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 2.5f, 1.1f, 1.05f, 0.95f, 0.0f }, { ASTCENC_PRE_THOROUGH, - 4, 76, 93, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.95f, 12 + 4, 82, 60, 30, 94, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.35f, 1.15f, 0.97f, 0.0f + }, { + ASTCENC_PRE_VERYTHOROUGH, + 4, 256, 128, 64, 98, 4, 6, 8, 6, 4, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f, 0.0f }, { ASTCENC_PRE_EXHAUSTIVE, - 4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0 + 4, 512, 512, 512, 100, 4, 8, 8, 8, 8, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f, 0.0f } }}; - /** - * @brief The static quality presets that are built-in for medium bandwidth - * presets (25 <= x < 64 texels per block). + * @brief The static presets for medium bandwidth encodings (25 <= x < 64 texels per block). */ -static const std::array preset_configs_mid {{ +static const std::array preset_configs_mid {{ { ASTCENC_PRE_FASTEST, - 2, 8, 40, 2, 2, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 20 + 2, 10, 6, 4, 43, 2, 2, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.80f, 1.0f }, { ASTCENC_PRE_FAST, - 3, 12, 55, 3, 3, 85.2f, 63.2f, 3.5f, 3.5f, 1.0f, 1.1f, 0.5f, 16 + 3, 18, 12, 10, 55, 3, 3, 2, 2, 2, 85.2f, 63.2f, 3.5f, 1.0f, 1.0f, 0.85f, 1.0f }, { ASTCENC_PRE_MEDIUM, - 4, 26, 76, 3, 3, 95.0f, 70.0f, 3.0f, 3.0f, 1.2f, 1.25f, 0.75f, 14 + 3, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 3.0f, 1.1f, 1.05f, 0.90f, 1.0f }, { ASTCENC_PRE_THOROUGH, - 4, 76, 93, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.95f, 10 + 4, 82, 60, 30, 94, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.4f, 1.2f, 0.95f, 0.0f + }, { + ASTCENC_PRE_VERYTHOROUGH, + 4, 256, 128, 64, 98, 4, 6, 8, 6, 3, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f, 0.0f }, { ASTCENC_PRE_EXHAUSTIVE, - 4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0 + 4, 256, 256, 256, 100, 4, 8, 8, 8, 8, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f, 0.0f } }}; - /** - * @brief The static quality presets that are built-in for low bandwidth - * presets (64 <= x texels per block). + * @brief The static presets for low bandwidth encodings (64 <= x texels per block). */ -static const std::array preset_configs_low {{ +static const std::array preset_configs_low {{ { ASTCENC_PRE_FASTEST, - 2, 6, 38, 2, 2, 85.0f, 63.0f, 3.5f, 3.5f, 1.0f, 1.0f, 0.5f, 20 + 2, 10, 6, 4, 40, 2, 2, 2, 2, 2, 85.0f, 63.0f, 3.5f, 1.0f, 1.0f, 0.80f, 1.0f }, { ASTCENC_PRE_FAST, - 3, 10, 53, 3, 3, 85.0f, 63.0f, 3.5f, 3.5f, 1.0f, 1.1f, 0.5f, 16 + 2, 18, 12, 10, 55, 3, 3, 2, 2, 2, 85.0f, 63.0f, 3.5f, 1.0f, 1.0f, 0.85f, 1.0f }, { ASTCENC_PRE_MEDIUM, - 3, 26, 76, 3, 3, 95.0f, 70.0f, 3.5f, 3.5f, 1.2f, 1.25f, 0.65f, 12 + 3, 34, 28, 16, 77, 3, 3, 2, 2, 2, 95.0f, 70.0f, 3.5f, 1.1f, 1.05f, 0.90f, 1.0f }, { ASTCENC_PRE_THOROUGH, - 4, 75, 92, 4, 4, 105.0f, 77.0f, 10.0f, 10.0f, 2.5f, 1.25f, 0.85f, 10 + 4, 82, 60, 30, 93, 4, 4, 3, 2, 2, 105.0f, 77.0f, 10.0f, 1.3f, 1.2f, 0.97f, 1.0f + }, { + ASTCENC_PRE_VERYTHOROUGH, + 4, 256, 128, 64, 98, 4, 6, 8, 5, 2, 200.0f, 200.0f, 10.0f, 1.6f, 1.4f, 0.98f, 1.0f }, { ASTCENC_PRE_EXHAUSTIVE, - 4, 1024, 100, 4, 4, 200.0f, 200.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.99f, 0 + 4, 256, 256, 256, 100, 4, 8, 8, 8, 8, 200.0f, 200.0f, 10.0f, 2.0f, 2.0f, 0.99f, 1.0f } }}; @@ -151,48 +158,6 @@ static astcenc_error validate_cpu_float() return ASTCENC_SUCCESS; } -/** - * @brief Validate CPU ISA support meets the requirements of this build of the library. - * - * Each library build is statically compiled for a particular set of CPU ISA features, such as the - * SIMD support or other ISA extensions such as POPCNT. This function checks that the host CPU - * actually supports everything this build needs. - * - * @return Return @c ASTCENC_SUCCESS if validated, otherwise an error on failure. - */ -static astcenc_error validate_cpu_isa() -{ - #if ASTCENC_SSE >= 41 - if (!cpu_supports_sse41()) - { - return ASTCENC_ERR_BAD_CPU_ISA; - } - #endif - - #if ASTCENC_POPCNT >= 1 - if (!cpu_supports_popcnt()) - { - return ASTCENC_ERR_BAD_CPU_ISA; - } - #endif - - #if ASTCENC_F16C >= 1 - if (!cpu_supports_f16c()) - { - return ASTCENC_ERR_BAD_CPU_ISA; - } - #endif - - #if ASTCENC_AVX >= 2 - if (!cpu_supports_avx2()) - { - return ASTCENC_ERR_BAD_CPU_ISA; - } - #endif - - return ASTCENC_SUCCESS; -} - /** * @brief Validate config profile. * @@ -252,11 +217,13 @@ static astcenc_error validate_block_size( /** * @brief Validate flags. * - * @param flags The flags to check. + * @param profile The profile to check. + * @param flags The flags to check. * * @return Return @c ASTCENC_SUCCESS if validated, otherwise an error on failure. */ static astcenc_error validate_flags( + astcenc_profile profile, unsigned int flags ) { // Flags field must not contain any unknown flag bits @@ -267,14 +234,21 @@ static astcenc_error validate_flags( } // Flags field must only contain at most a single map type - exMask = ASTCENC_FLG_MAP_MASK - | ASTCENC_FLG_MAP_NORMAL + exMask = ASTCENC_FLG_MAP_NORMAL | ASTCENC_FLG_MAP_RGBM; if (popcount(flags & exMask) > 1) { return ASTCENC_ERR_BAD_FLAGS; } + // Decode_unorm8 must only be used with an LDR profile + bool is_unorm8 = flags & ASTCENC_FLG_USE_DECODE_UNORM8; + bool is_hdr = (profile == ASTCENC_PRF_HDR) || (profile == ASTCENC_PRF_HDR_RGB_LDR_A); + if (is_unorm8 && is_hdr) + { + return ASTCENC_ERR_BAD_DECODE_MODE; + } + return ASTCENC_SUCCESS; } @@ -400,7 +374,7 @@ static astcenc_error validate_config( return status; } - status = validate_flags(config.flags); + status = validate_flags(config.profile, config.flags); if (status != ASTCENC_SUCCESS) { return status; @@ -423,16 +397,20 @@ static astcenc_error validate_config( config.rgbm_m_scale = astc::max(config.rgbm_m_scale, 1.0f); config.tune_partition_count_limit = astc::clamp(config.tune_partition_count_limit, 1u, 4u); - config.tune_partition_index_limit = astc::clamp(config.tune_partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS); + config.tune_2partition_index_limit = astc::clamp(config.tune_2partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS); + config.tune_3partition_index_limit = astc::clamp(config.tune_3partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS); + config.tune_4partition_index_limit = astc::clamp(config.tune_4partition_index_limit, 1u, BLOCK_MAX_PARTITIONINGS); config.tune_block_mode_limit = astc::clamp(config.tune_block_mode_limit, 1u, 100u); config.tune_refinement_limit = astc::max(config.tune_refinement_limit, 1u); config.tune_candidate_limit = astc::clamp(config.tune_candidate_limit, 1u, TUNE_MAX_TRIAL_CANDIDATES); + config.tune_2partitioning_candidate_limit = astc::clamp(config.tune_2partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES); + config.tune_3partitioning_candidate_limit = astc::clamp(config.tune_3partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES); + config.tune_4partitioning_candidate_limit = astc::clamp(config.tune_4partitioning_candidate_limit, 1u, TUNE_MAX_PARTITIONING_CANDIDATES); config.tune_db_limit = astc::max(config.tune_db_limit, 0.0f); - config.tune_mode0_mse_overshoot = astc::max(config.tune_mode0_mse_overshoot, 1.0f); - config.tune_refinement_mse_overshoot = astc::max(config.tune_refinement_mse_overshoot, 1.0f); - config.tune_2_partition_early_out_limit_factor = astc::max(config.tune_2_partition_early_out_limit_factor, 0.0f); - config.tune_3_partition_early_out_limit_factor = astc::max(config.tune_3_partition_early_out_limit_factor, 0.0f); - config.tune_2_plane_early_out_limit_correlation = astc::max(config.tune_2_plane_early_out_limit_correlation, 0.0f); + config.tune_mse_overshoot = astc::max(config.tune_mse_overshoot, 1.0f); + config.tune_2partition_early_out_limit_factor = astc::max(config.tune_2partition_early_out_limit_factor, 0.0f); + config.tune_3partition_early_out_limit_factor = astc::max(config.tune_3partition_early_out_limit_factor, 0.0f); + config.tune_2plane_early_out_limit_correlation = astc::max(config.tune_2plane_early_out_limit_correlation, 0.0f); // Specifying a zero weight color component is not allowed; force to small value float max_weight = astc::max(astc::max(config.cw_r_weight, config.cw_g_weight), @@ -465,9 +443,15 @@ astcenc_error astcenc_config_init( astcenc_config* configp ) { astcenc_error status; - astcenc_config& config = *configp; + + status = validate_cpu_float(); + if (status != ASTCENC_SUCCESS) + { + return status; + } // Zero init all config fields; although most of will be over written + astcenc_config& config = *configp; std::memset(&config, 0, sizeof(config)); // Process the block size @@ -494,7 +478,7 @@ astcenc_error astcenc_config_init( return ASTCENC_ERR_BAD_QUALITY; } - static const std::array* preset_configs; + static const std::array* preset_configs; int texels_int = block_x * block_y * block_z; if (texels_int < 25) { @@ -526,21 +510,24 @@ astcenc_error astcenc_config_init( if (start == end) { config.tune_partition_count_limit = (*preset_configs)[start].tune_partition_count_limit; - config.tune_partition_index_limit = (*preset_configs)[start].tune_partition_index_limit; + config.tune_2partition_index_limit = (*preset_configs)[start].tune_2partition_index_limit; + config.tune_3partition_index_limit = (*preset_configs)[start].tune_3partition_index_limit; + config.tune_4partition_index_limit = (*preset_configs)[start].tune_4partition_index_limit; config.tune_block_mode_limit = (*preset_configs)[start].tune_block_mode_limit; config.tune_refinement_limit = (*preset_configs)[start].tune_refinement_limit; - config.tune_candidate_limit = astc::min((*preset_configs)[start].tune_candidate_limit, - TUNE_MAX_TRIAL_CANDIDATES); + config.tune_candidate_limit = (*preset_configs)[start].tune_candidate_limit; + config.tune_2partitioning_candidate_limit = (*preset_configs)[start].tune_2partitioning_candidate_limit; + config.tune_3partitioning_candidate_limit = (*preset_configs)[start].tune_3partitioning_candidate_limit; + config.tune_4partitioning_candidate_limit = (*preset_configs)[start].tune_4partitioning_candidate_limit; config.tune_db_limit = astc::max((*preset_configs)[start].tune_db_limit_a_base - 35 * ltexels, (*preset_configs)[start].tune_db_limit_b_base - 19 * ltexels); - config.tune_mode0_mse_overshoot = (*preset_configs)[start].tune_mode0_mse_overshoot; - config.tune_refinement_mse_overshoot = (*preset_configs)[start].tune_refinement_mse_overshoot; + config.tune_mse_overshoot = (*preset_configs)[start].tune_mse_overshoot; - config.tune_2_partition_early_out_limit_factor = (*preset_configs)[start].tune_2_partition_early_out_limit_factor; - config.tune_3_partition_early_out_limit_factor =(*preset_configs)[start].tune_3_partition_early_out_limit_factor; - config.tune_2_plane_early_out_limit_correlation = (*preset_configs)[start].tune_2_plane_early_out_limit_correlation; - config.tune_low_weight_count_limit = (*preset_configs)[start].tune_low_weight_count_limit; + config.tune_2partition_early_out_limit_factor = (*preset_configs)[start].tune_2partition_early_out_limit_factor; + config.tune_3partition_early_out_limit_factor = (*preset_configs)[start].tune_3partition_early_out_limit_factor; + config.tune_2plane_early_out_limit_correlation = (*preset_configs)[start].tune_2plane_early_out_limit_correlation; + config.tune_search_mode0_enable = (*preset_configs)[start].tune_search_mode0_enable; } // Start and end node are not the same - so interpolate between them else @@ -562,21 +549,24 @@ astcenc_error astcenc_config_init( #define LERPUI(param) static_cast(LERPI(param)) config.tune_partition_count_limit = LERPI(tune_partition_count_limit); - config.tune_partition_index_limit = LERPI(tune_partition_index_limit); + config.tune_2partition_index_limit = LERPI(tune_2partition_index_limit); + config.tune_3partition_index_limit = LERPI(tune_3partition_index_limit); + config.tune_4partition_index_limit = LERPI(tune_4partition_index_limit); config.tune_block_mode_limit = LERPI(tune_block_mode_limit); config.tune_refinement_limit = LERPI(tune_refinement_limit); - config.tune_candidate_limit = astc::min(LERPUI(tune_candidate_limit), - TUNE_MAX_TRIAL_CANDIDATES); + config.tune_candidate_limit = LERPUI(tune_candidate_limit); + config.tune_2partitioning_candidate_limit = LERPUI(tune_2partitioning_candidate_limit); + config.tune_3partitioning_candidate_limit = LERPUI(tune_3partitioning_candidate_limit); + config.tune_4partitioning_candidate_limit = LERPUI(tune_4partitioning_candidate_limit); config.tune_db_limit = astc::max(LERP(tune_db_limit_a_base) - 35 * ltexels, LERP(tune_db_limit_b_base) - 19 * ltexels); - config.tune_mode0_mse_overshoot = LERP(tune_mode0_mse_overshoot); - config.tune_refinement_mse_overshoot = LERP(tune_refinement_mse_overshoot); + config.tune_mse_overshoot = LERP(tune_mse_overshoot); - config.tune_2_partition_early_out_limit_factor = LERP(tune_2_partition_early_out_limit_factor); - config.tune_3_partition_early_out_limit_factor = LERP(tune_3_partition_early_out_limit_factor); - config.tune_2_plane_early_out_limit_correlation = LERP(tune_2_plane_early_out_limit_correlation); - config.tune_low_weight_count_limit = LERPI(tune_low_weight_count_limit); + config.tune_2partition_early_out_limit_factor = LERP(tune_2partition_early_out_limit_factor); + config.tune_3partition_early_out_limit_factor = LERP(tune_3partition_early_out_limit_factor); + config.tune_2plane_early_out_limit_correlation = LERP(tune_2plane_early_out_limit_correlation); + config.tune_search_mode0_enable = LERP(tune_search_mode0_enable); #undef LERP #undef LERPI #undef LERPUI @@ -604,13 +594,14 @@ astcenc_error astcenc_config_init( case ASTCENC_PRF_HDR_RGB_LDR_A: case ASTCENC_PRF_HDR: config.tune_db_limit = 999.0f; + config.tune_search_mode0_enable = 0.0f; break; default: return ASTCENC_ERR_BAD_PROFILE; } // Flags field must not contain any unknown flag bits - status = validate_flags(flags); + status = validate_flags(profile, flags); if (status != ASTCENC_SUCCESS) { return status; @@ -625,20 +616,14 @@ astcenc_error astcenc_config_init( config.cw_g_weight = 0.0f; config.cw_b_weight = 0.0f; - config.tune_2_partition_early_out_limit_factor *= 1.5f; - config.tune_3_partition_early_out_limit_factor *= 1.5f; - config.tune_2_plane_early_out_limit_correlation = 0.99f; + config.tune_2partition_early_out_limit_factor *= 1.5f; + config.tune_3partition_early_out_limit_factor *= 1.5f; + config.tune_2plane_early_out_limit_correlation = 0.99f; // Normals are prone to blocking artifacts on smooth curves // so force compressor to try harder here ... config.tune_db_limit *= 1.03f; } - else if (flags & ASTCENC_FLG_MAP_MASK) - { - // Masks are prone to blocking artifacts on mask edges - // so force compressor to try harder here ... - config.tune_db_limit *= 1.03f; - } else if (flags & ASTCENC_FLG_MAP_RGBM) { config.rgbm_m_scale = 5.0f; @@ -655,7 +640,7 @@ astcenc_error astcenc_config_init( // // ... but we scale these up to keep a better balance between color and alpha. Note // that if the content is using alpha we'd recommend using the -a option to weight - // the color conribution by the alpha transparency. + // the color contribution by the alpha transparency. if (flags & ASTCENC_FLG_USE_PERCEPTUAL) { config.cw_r_weight = 0.30f * 2.25f; @@ -683,12 +668,6 @@ astcenc_error astcenc_context_alloc( return status; } - status = validate_cpu_isa(); - if (status != ASTCENC_SUCCESS) - { - return status; - } - if (thread_count == 0) { return ASTCENC_ERR_BAD_PARAM; @@ -702,7 +681,8 @@ astcenc_error astcenc_context_alloc( } #endif - astcenc_context* ctx = new astcenc_context; + astcenc_context* ctxo = new astcenc_context; + astcenc_contexti* ctx = &ctxo->context; ctx->thread_count = thread_count; ctx->config = config; ctx->working_buffers = nullptr; @@ -714,12 +694,18 @@ astcenc_error astcenc_context_alloc( status = validate_config(ctx->config); if (status != ASTCENC_SUCCESS) { - delete ctx; + delete ctxo; return status; } ctx->bsd = aligned_malloc(sizeof(block_size_descriptor), ASTCENC_VECALIGN); - bool can_omit_modes = config.flags & ASTCENC_FLG_SELF_DECOMPRESS_ONLY; + if (!ctx->bsd) + { + delete ctxo; + return ASTCENC_ERR_OUT_OF_MEM; + } + + bool can_omit_modes = static_cast(config.flags & ASTCENC_FLG_SELF_DECOMPRESS_ONLY); init_block_size_descriptor(ctx->config.privateProfile, config.block_x, config.block_y, config.block_z, can_omit_modes, config.tune_partition_count_limit, @@ -728,7 +714,7 @@ astcenc_error astcenc_context_alloc( #if !defined(ASTCENC_DECOMPRESS_ONLY) // Do setup only needed by compression - if (!(status & ASTCENC_FLG_DECOMPRESS_ONLY)) + if (!(ctx->config.flags & ASTCENC_FLG_DECOMPRESS_ONLY)) { // Turn a dB limit into a per-texel error for faster use later if ((ctx->config.profile == ASTCENC_PRF_LDR) || (ctx->config.profile == ASTCENC_PRF_LDR_SRGB)) @@ -742,12 +728,12 @@ astcenc_error astcenc_context_alloc( size_t worksize = sizeof(compression_working_buffers) * thread_count; ctx->working_buffers = aligned_malloc(worksize, ASTCENC_VECALIGN); - static_assert((sizeof(compression_working_buffers) % ASTCENC_VECALIGN) == 0, + static_assert((ASTCENC_VECALIGN == 0) || ((sizeof(compression_working_buffers) % ASTCENC_VECALIGN) == 0), "compression_working_buffers size must be multiple of vector alignment"); if (!ctx->working_buffers) { aligned_free(ctx->bsd); - delete ctx; + delete ctxo; *context = nullptr; return ASTCENC_ERR_OUT_OF_MEM; } @@ -766,7 +752,7 @@ astcenc_error astcenc_context_alloc( trace_add_data("block_z", config.block_z); #endif - *context = ctx; + *context = ctxo; #if !defined(ASTCENC_DECOMPRESS_ONLY) prepare_angular_tables(); @@ -777,16 +763,17 @@ astcenc_error astcenc_context_alloc( /* See header dor documentation. */ void astcenc_context_free( - astcenc_context* ctx + astcenc_context* ctxo ) { - if (ctx) + if (ctxo) { + astcenc_contexti* ctx = &ctxo->context; aligned_free(ctx->working_buffers); aligned_free(ctx->bsd); #if defined(ASTCENC_DIAGNOSTICS) delete ctx->trace_log; #endif - delete ctx; + delete ctxo; } } @@ -795,14 +782,14 @@ void astcenc_context_free( /** * @brief Compress an image, after any preflight has completed. * - * @param[out] ctx The compressor context. + * @param[out] ctxo The compressor context. * @param thread_index The thread index. * @param image The intput image. * @param swizzle The input swizzle. * @param[out] buffer The output array for the compressed data. */ static void compress_image( - astcenc_context& ctx, + astcenc_context& ctxo, unsigned int thread_index, const astcenc_image& image, const astcenc_swizzle& swizzle, @@ -814,6 +801,7 @@ static void compress_image( uint8_t* buffer #endif ) { + astcenc_contexti& ctx = ctxo.context; const block_size_descriptor& bsd = *ctx.bsd; astcenc_profile decode_mode = ctx.config.profile; @@ -822,7 +810,7 @@ static void compress_image( int block_x = bsd.xdim; int block_y = bsd.ydim; int block_z = bsd.zdim; - blk.texel_count = block_x * block_y * block_z; + blk.texel_count = static_cast(block_x * block_y * block_z); int dim_x = image.dim_x; int dim_y = image.dim_y; @@ -836,6 +824,8 @@ static void compress_image( int row_blocks = xblocks; int plane_blocks = xblocks * yblocks; + blk.decode_unorm8 = ctxo.context.config.flags & ASTCENC_FLG_USE_DECODE_UNORM8; + // Populate the block channel weights blk.channel_weight = vfloat4(ctx.config.cw_r_weight, ctx.config.cw_g_weight, @@ -846,8 +836,7 @@ static void compress_image( auto& temp_buffers = ctx.working_buffers[thread_index]; // Only the first thread actually runs the initializer - ctx.manage_compress.init(block_count); - + ctxo.manage_compress.init(block_count, ctx.config.progress_callback); // Determine if we can use an optimized load function bool needs_swz = (swizzle.r != ASTCENC_SWZ_R) || (swizzle.g != ASTCENC_SWZ_G) || @@ -859,17 +848,17 @@ static void compress_image( bool use_fast_load = !needs_swz && !needs_hdr && block_z == 1 && image.data_type == ASTCENC_TYPE_U8; - auto load_func = fetch_image_block; + auto load_func = load_image_block; if (use_fast_load) { - load_func = fetch_image_block_fast_ldr; + load_func = load_image_block_fast_ldr; } // All threads run this processing loop until there is no work remaining while (true) { unsigned int count; - unsigned int base = ctx.manage_compress.get_task_assignment(16, count); + unsigned int base = ctxo.manage_compress.get_task_assignment(16, count); if (!count) { break; @@ -924,6 +913,18 @@ static void compress_image( if (use_full_block) { load_func(decode_mode, image, blk, bsd, x * block_x, y * block_y, z * block_z, swizzle); + + // Scale RGB error contribution by the maximum alpha in the block + // This encourages preserving alpha accuracy in regions with high + // transparency, and can buy up to 0.5 dB PSNR. + if (ctx.config.flags & ASTCENC_FLG_USE_ALPHA_WEIGHT) + { + float alpha_scale = blk.data_max.lane<3>() * (1.0f / 65535.0f); + blk.channel_weight = vfloat4(ctx.config.cw_r_weight * alpha_scale, + ctx.config.cw_g_weight * alpha_scale, + ctx.config.cw_b_weight * alpha_scale, + ctx.config.cw_a_weight); + } } // Apply alpha scale RDO - substitute constant color block else @@ -937,31 +938,92 @@ static void compress_image( int offset = ((z * yblocks + y) * xblocks + x) * 16; uint8_t *bp = buffer + offset; - physical_compressed_block* pcb = reinterpret_cast(bp); #if QUALITY_CONTROL int32_t *mseBlock[RGBA_COM] = {nullptr, nullptr, nullptr, nullptr}; if (calQualityEnable) { - int offset = (z * yblocks + y) * xblocks + x; + offset = (z * yblocks + y) * xblocks + x; mseBlock[R_COM] = mse[R_COM] + offset; mseBlock[G_COM] = mse[G_COM] + offset; mseBlock[B_COM] = mse[B_COM] + offset; mseBlock[A_COM] = mse[A_COM] + offset; } - compress_block(ctx, blk, *pcb, temp_buffers, calQualityEnable, mseBlock); + compress_block(ctx, blk, bp, temp_buffers, calQualityEnable, mseBlock); #else - compress_block(ctx, blk, *pcb, temp_buffers); + compress_block(ctx, blk, bp, temp_buffers); #endif } - ctx.manage_compress.complete_task_assignment(count); + ctxo.manage_compress.complete_task_assignment(count); } } +/** + * @brief Compute regional averages in an image. + * + * This function can be called by multiple threads, but only after a single + * thread calls the setup function @c init_compute_averages(). + * + * Results are written back into @c img->input_alpha_averages. + * + * @param[out] ctx The context. + * @param ag The average and variance arguments created during setup. + */ +static void compute_averages( + astcenc_context& ctx, + const avg_args &ag +) { + pixel_region_args arg = ag.arg; + arg.work_memory = new vfloat4[ag.work_memory_size]; + + int size_x = ag.img_size_x; + int size_y = ag.img_size_y; + int size_z = ag.img_size_z; + + int step_xy = ag.blk_size_xy; + int step_z = ag.blk_size_z; + + int y_tasks = (size_y + step_xy - 1) / step_xy; + + // All threads run this processing loop until there is no work remaining + while (true) + { + unsigned int count; + unsigned int base = ctx.manage_avg.get_task_assignment(16, count); + if (!count) + { + break; + } + + for (unsigned int i = base; i < base + count; i++) + { + int z = (i / (y_tasks)) * step_z; + int y = (i - (z * y_tasks)) * step_xy; + + arg.size_z = astc::min(step_z, size_z - z); + arg.offset_z = z; + + arg.size_y = astc::min(step_xy, size_y - y); + arg.offset_y = y; + + for (int x = 0; x < size_x; x += step_xy) + { + arg.size_x = astc::min(step_xy, size_x - x); + arg.offset_x = x; + compute_pixel_region_variance(ctx.context, arg); + } + } + + ctx.manage_avg.complete_task_assignment(count); + } + + delete[] arg.work_memory; +} + #endif /* See header for documentation. */ astcenc_error astcenc_compress_image( - astcenc_context* ctx, + astcenc_context* ctxo, astcenc_image* imagep, const astcenc_swizzle* swizzle, uint8_t* data_out, @@ -973,7 +1035,7 @@ astcenc_error astcenc_compress_image( unsigned int thread_index ) { #if defined(ASTCENC_DECOMPRESS_ONLY) - (void)ctx; + (void)ctxo; (void)imagep; (void)swizzle; (void)data_out; @@ -981,6 +1043,7 @@ astcenc_error astcenc_compress_image( (void)thread_index; return ASTCENC_ERR_BAD_CONTEXT; #else + astcenc_contexti* ctx = &ctxo->context; astcenc_error status; astcenc_image& image = *imagep; @@ -1018,7 +1081,7 @@ astcenc_error astcenc_compress_image( // If context thread count is one then implicitly reset if (ctx->thread_count == 1) { - astcenc_compress_reset(ctx); + astcenc_compress_reset(ctxo); } if (ctx->config.a_scale_radius != 0) @@ -1036,21 +1099,21 @@ astcenc_error astcenc_compress_image( }; // Only the first thread actually runs the initializer - ctx->manage_avg.init(init_avg); + ctxo->manage_avg.init(init_avg); // All threads will enter this function and dynamically grab work - compute_averages(*ctx, ctx->avg_preprocess_args); + compute_averages(*ctxo, ctx->avg_preprocess_args); } // Wait for compute_averages to complete before compressing - ctx->manage_avg.wait(); + ctxo->manage_avg.wait(); #if QUALITY_CONTROL - compress_image(*ctx, thread_index, image, *swizzle, data_out, calQualityEnable, mse); + compress_image(*ctxo, thread_index, image, *swizzle, data_out, calQualityEnable, mse); #else - compress_image(*ctx, thread_index, image, *swizzle, data_out); + compress_image(*ctxo, thread_index, image, *swizzle, data_out); #endif // Wait for compress to complete before freeing memory - ctx->manage_compress.wait(); + ctxo->manage_compress.wait(); auto term_compress = [ctx]() { delete[] ctx->input_alpha_averages; @@ -1058,7 +1121,7 @@ astcenc_error astcenc_compress_image( }; // Only the first thread to arrive actually runs the term - ctx->manage_compress.term(term_compress); + ctxo->manage_compress.term(term_compress); return ASTCENC_SUCCESS; #endif @@ -1066,26 +1129,27 @@ astcenc_error astcenc_compress_image( /* See header for documentation. */ astcenc_error astcenc_compress_reset( - astcenc_context* ctx + astcenc_context* ctxo ) { #if defined(ASTCENC_DECOMPRESS_ONLY) - (void)ctx; + (void)ctxo; return ASTCENC_ERR_BAD_CONTEXT; #else + astcenc_contexti* ctx = &ctxo->context; if (ctx->config.flags & ASTCENC_FLG_DECOMPRESS_ONLY) { return ASTCENC_ERR_BAD_CONTEXT; } - ctx->manage_avg.reset(); - ctx->manage_compress.reset(); + ctxo->manage_avg.reset(); + ctxo->manage_compress.reset(); return ASTCENC_SUCCESS; #endif } /* See header for documentation. */ astcenc_error astcenc_decompress_image( - astcenc_context* ctx, + astcenc_context* ctxo, const uint8_t* data, size_t data_len, astcenc_image* image_outp, @@ -1094,6 +1158,7 @@ astcenc_error astcenc_decompress_image( ) { astcenc_error status; astcenc_image& image_out = *image_outp; + astcenc_contexti* ctx = &ctxo->context; // Today this doesn't matter (working set on stack) but might in future ... if (thread_index >= ctx->thread_count) @@ -1114,6 +1179,7 @@ astcenc_error astcenc_decompress_image( unsigned int xblocks = (image_out.dim_x + block_x - 1) / block_x; unsigned int yblocks = (image_out.dim_y + block_y - 1) / block_y; unsigned int zblocks = (image_out.dim_z + block_z - 1) / block_z; + unsigned int block_count = zblocks * yblocks * xblocks; int row_blocks = xblocks; int plane_blocks = xblocks * yblocks; @@ -1126,22 +1192,25 @@ astcenc_error astcenc_decompress_image( } image_block blk; - blk.texel_count = block_x * block_y * block_z; + blk.texel_count = static_cast(block_x * block_y * block_z); + + // Decode mode inferred from the output data type + blk.decode_unorm8 = image_out.data_type == ASTCENC_TYPE_U8; // If context thread count is one then implicitly reset if (ctx->thread_count == 1) { - astcenc_decompress_reset(ctx); + astcenc_decompress_reset(ctxo); } // Only the first thread actually runs the initializer - ctx->manage_decompress.init(zblocks * yblocks * xblocks); + ctxo->manage_decompress.init(block_count, nullptr); // All threads run this processing loop until there is no work remaining while (true) { unsigned int count; - unsigned int base = ctx->manage_decompress.get_task_assignment(128, count); + unsigned int base = ctxo->manage_decompress.get_task_assignment(128, count); if (!count) { break; @@ -1158,20 +1227,19 @@ astcenc_error astcenc_decompress_image( unsigned int offset = (((z * yblocks + y) * xblocks) + x) * 16; const uint8_t* bp = data + offset; - const physical_compressed_block& pcb = *reinterpret_cast(bp); symbolic_compressed_block scb; - physical_to_symbolic(*ctx->bsd, pcb, scb); + physical_to_symbolic(*ctx->bsd, bp, scb); decompress_symbolic_block(ctx->config.profile, *ctx->bsd, x * block_x, y * block_y, z * block_z, scb, blk); - write_image_block(image_out, blk, *ctx->bsd, + store_image_block(image_out, blk, *ctx->bsd, x * block_x, y * block_y, z * block_z, *swizzle); } - ctx->manage_decompress.complete_task_assignment(count); + ctxo->manage_decompress.complete_task_assignment(count); } return ASTCENC_SUCCESS; @@ -1179,28 +1247,29 @@ astcenc_error astcenc_decompress_image( /* See header for documentation. */ astcenc_error astcenc_decompress_reset( - astcenc_context* ctx + astcenc_context* ctxo ) { - ctx->manage_decompress.reset(); + ctxo->manage_decompress.reset(); return ASTCENC_SUCCESS; } /* See header for documentation. */ astcenc_error astcenc_get_block_info( - astcenc_context* ctx, + astcenc_context* ctxo, const uint8_t data[16], astcenc_block_info* info ) { #if defined(ASTCENC_DECOMPRESS_ONLY) - (void)ctx; + (void)ctxo; (void)data; (void)info; return ASTCENC_ERR_BAD_CONTEXT; #else + astcenc_contexti* ctx = &ctxo->context; + // Decode the compressed data into a symbolic form - const physical_compressed_block&pcb = *reinterpret_cast(data); symbolic_compressed_block scb; - physical_to_symbolic(*ctx->bsd, pcb, scb); + physical_to_symbolic(*ctx->bsd, data, scb); // Fetch the appropriate partition and decimation tables block_size_descriptor& bsd = *ctx->bsd; @@ -1260,7 +1329,6 @@ astcenc_error astcenc_get_block_info( unpack_color_endpoints(ctx->config.profile, scb.color_formats[i], - scb.get_color_quant_mode(), scb.color_values[i], rgb_hdr, a_hdr, endpnt[0], endpnt[1]); @@ -1284,7 +1352,7 @@ astcenc_error astcenc_get_block_info( int weight_plane1[BLOCK_MAX_TEXELS]; int weight_plane2[BLOCK_MAX_TEXELS]; - unpack_weights(bsd, scb, di, bm.is_dual_plane, bm.get_weight_quant_mode(), weight_plane1, weight_plane2); + unpack_weights(bsd, scb, di, bm.is_dual_plane, weight_plane1, weight_plane2); for (unsigned int i = 0; i < bsd.texel_count; i++) { info->weight_values_plane1[i] = static_cast(weight_plane1[i]) * (1.0f / WEIGHTS_TEXEL_SUM); @@ -1318,8 +1386,6 @@ const char* astcenc_get_error_string( return "ASTCENC_ERR_OUT_OF_MEM"; case ASTCENC_ERR_BAD_CPU_FLOAT: return "ASTCENC_ERR_BAD_CPU_FLOAT"; - case ASTCENC_ERR_BAD_CPU_ISA: - return "ASTCENC_ERR_BAD_CPU_ISA"; case ASTCENC_ERR_BAD_PARAM: return "ASTCENC_ERR_BAD_PARAM"; case ASTCENC_ERR_BAD_BLOCK_SIZE: @@ -1336,6 +1402,8 @@ const char* astcenc_get_error_string( return "ASTCENC_ERR_BAD_CONTEXT"; case ASTCENC_ERR_NOT_IMPLEMENTED: return "ASTCENC_ERR_NOT_IMPLEMENTED"; + case ASTCENC_ERR_BAD_DECODE_MODE: + return "ASTCENC_ERR_BAD_DECODE_MODE"; #if defined(ASTCENC_DIAGNOSTICS) case ASTCENC_ERR_DTRACE_FAILURE: return "ASTCENC_ERR_DTRACE_FAILURE"; diff --git a/Source/astcenc_find_best_partitioning.cpp b/Source/astcenc_find_best_partitioning.cpp index aa9a8ab..bfbcc35 100644 --- a/Source/astcenc_find_best_partitioning.cpp +++ b/Source/astcenc_find_best_partitioning.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -46,15 +46,16 @@ * lines for endpoint selection. */ +#include #include "astcenc_internal.h" /** - * @brief Pick some initital kmeans cluster centers. + * @brief Pick some initial kmeans cluster centers. * * @param blk The image block color data to compress. * @param texel_count The number of texels in the block. * @param partition_count The number of partitions in the block. - * @param[out] cluster_centers The initital partition cluster center colors. + * @param[out] cluster_centers The initial partition cluster center colors. */ static void kmeans_init( const image_block& blk, @@ -249,13 +250,16 @@ static void kmeans_update( * * @return The number of bit mismatches. */ -static inline unsigned int partition_mismatch2( +static inline uint8_t partition_mismatch2( const uint64_t a[2], const uint64_t b[2] ) { int v1 = popcount(a[0] ^ b[0]) + popcount(a[1] ^ b[1]); int v2 = popcount(a[0] ^ b[1]) + popcount(a[1] ^ b[0]); - return astc::min(v1, v2); + + // Divide by 2 because XOR always counts errors twice, once when missing + // in the expected position, and again when present in the wrong partition + return static_cast(astc::min(v1, v2) / 2); } /** @@ -266,7 +270,7 @@ static inline unsigned int partition_mismatch2( * * @return The number of bit mismatches. */ -static inline unsigned int partition_mismatch3( +static inline uint8_t partition_mismatch3( const uint64_t a[3], const uint64_t b[3] ) { @@ -294,7 +298,9 @@ static inline unsigned int partition_mismatch3( int s5 = p11 + p20; int v2 = astc::min(s4, s5) + p02; - return astc::min(v0, v1, v2); + // Divide by 2 because XOR always counts errors twice, once when missing + // in the expected position, and again when present in the wrong partition + return static_cast(astc::min(v0, v1, v2) / 2); } /** @@ -305,7 +311,7 @@ static inline unsigned int partition_mismatch3( * * @return The number of bit mismatches. */ -static inline unsigned int partition_mismatch4( +static inline uint8_t partition_mismatch4( const uint64_t a[4], const uint64_t b[4] ) { @@ -341,7 +347,9 @@ static inline unsigned int partition_mismatch4( int v2 = p02 + astc::min(p11 + mx03, p10 + mx13, p13 + mx01); int v3 = p03 + astc::min(p11 + mx02, p12 + mx01, p10 + mx12); - return astc::min(v0, v1, v2, v3); + // Divide by 2 because XOR always counts errors twice, once when missing + // in the expected position, and again when present in the wrong partition + return static_cast(astc::min(v0, v1, v2, v3) / 2); } using mismatch_dispatch = unsigned int (*)(const uint64_t*, const uint64_t*); @@ -358,32 +366,36 @@ static void count_partition_mismatch_bits( const block_size_descriptor& bsd, unsigned int partition_count, const uint64_t bitmaps[BLOCK_MAX_PARTITIONS], - unsigned int mismatch_counts[BLOCK_MAX_PARTITIONINGS] + uint8_t mismatch_counts[BLOCK_MAX_PARTITIONINGS] ) { unsigned int active_count = bsd.partitioning_count_selected[partition_count - 1]; + promise(active_count > 0); if (partition_count == 2) { for (unsigned int i = 0; i < active_count; i++) { - int bitcount = partition_mismatch2(bitmaps, bsd.coverage_bitmaps_2[i]); - mismatch_counts[i] = astc::max(bitcount, static_cast(bsd.partitioning_valid_2[i])); + mismatch_counts[i] = partition_mismatch2(bitmaps, bsd.coverage_bitmaps_2[i]); + assert(mismatch_counts[i] < BLOCK_MAX_KMEANS_TEXELS); + assert(mismatch_counts[i] < bsd.texel_count); } } else if (partition_count == 3) { for (unsigned int i = 0; i < active_count; i++) { - int bitcount = partition_mismatch3(bitmaps, bsd.coverage_bitmaps_3[i]); - mismatch_counts[i] = astc::max(bitcount, static_cast(bsd.partitioning_valid_3[i])); + mismatch_counts[i] = partition_mismatch3(bitmaps, bsd.coverage_bitmaps_3[i]); + assert(mismatch_counts[i] < BLOCK_MAX_KMEANS_TEXELS); + assert(mismatch_counts[i] < bsd.texel_count); } } else { for (unsigned int i = 0; i < active_count; i++) { - int bitcount = partition_mismatch4(bitmaps, bsd.coverage_bitmaps_4[i]); - mismatch_counts[i] = astc::max(bitcount, static_cast(bsd.partitioning_valid_4[i])); + mismatch_counts[i] = partition_mismatch4(bitmaps, bsd.coverage_bitmaps_4[i]); + assert(mismatch_counts[i] < BLOCK_MAX_KMEANS_TEXELS); + assert(mismatch_counts[i] < bsd.texel_count); } } } @@ -398,11 +410,13 @@ static void count_partition_mismatch_bits( * @return The number of active partitions in this selection. */ static unsigned int get_partition_ordering_by_mismatch_bits( + unsigned int texel_count, unsigned int partitioning_count, - const unsigned int mismatch_count[BLOCK_MAX_PARTITIONINGS], - unsigned int partition_ordering[BLOCK_MAX_PARTITIONINGS] + const uint8_t mismatch_count[BLOCK_MAX_PARTITIONINGS], + uint16_t partition_ordering[BLOCK_MAX_PARTITIONINGS] ) { - unsigned int mscount[256] { 0 }; + promise(partitioning_count > 0); + uint16_t mscount[BLOCK_MAX_KMEANS_TEXELS] { 0 }; // Create the histogram of mismatch counts for (unsigned int i = 0; i < partitioning_count; i++) @@ -410,16 +424,14 @@ static unsigned int get_partition_ordering_by_mismatch_bits( mscount[mismatch_count[i]]++; } - unsigned int active_count = partitioning_count - mscount[255]; - // Create a running sum from the histogram array // Cells store previous values only; i.e. exclude self after sum - unsigned int summa = 0; - for (unsigned int i = 0; i < 256; i++) + unsigned int sum = 0; + for (unsigned int i = 0; i < texel_count; i++) { - unsigned int cnt = mscount[i]; - mscount[i] = summa; - summa += cnt; + uint16_t cnt = mscount[i]; + mscount[i] = sum; + sum += cnt; } // Use the running sum as the index, incrementing after read to allow @@ -427,10 +439,10 @@ static unsigned int get_partition_ordering_by_mismatch_bits( for (unsigned int i = 0; i < partitioning_count; i++) { unsigned int idx = mscount[mismatch_count[i]]++; - partition_ordering[idx] = i; + partition_ordering[idx] = static_cast(i); } - return active_count; + return partitioning_count; } /** @@ -447,7 +459,7 @@ static unsigned int compute_kmeans_partition_ordering( const block_size_descriptor& bsd, const image_block& blk, unsigned int partition_count, - unsigned int partition_ordering[BLOCK_MAX_PARTITIONINGS] + uint16_t partition_ordering[BLOCK_MAX_PARTITIONINGS] ) { vfloat4 cluster_centers[BLOCK_MAX_PARTITIONS]; uint8_t texel_partitions[BLOCK_MAX_TEXELS]; @@ -478,22 +490,71 @@ static unsigned int compute_kmeans_partition_ordering( } // Count the mismatch between the block and the format's partition tables - unsigned int mismatch_counts[BLOCK_MAX_PARTITIONINGS]; + uint8_t mismatch_counts[BLOCK_MAX_PARTITIONINGS]; count_partition_mismatch_bits(bsd, partition_count, bitmaps, mismatch_counts); // Sort the partitions based on the number of mismatched bits return get_partition_ordering_by_mismatch_bits( + texels_to_process, bsd.partitioning_count_selected[partition_count - 1], mismatch_counts, partition_ordering); } +/** + * @brief Insert a partitioning into an order list of results, sorted by error. + * + * @param max_values The max number of entries in the best result arrays. + * @param this_error The error of the new entry. + * @param this_partition The partition ID of the new entry. + * @param[out] best_errors The array of best error values. + * @param[out] best_partitions The array of best partition values. + */ +static void insert_result( + unsigned int max_values, + float this_error, + unsigned int this_partition, + float* best_errors, + unsigned int* best_partitions) +{ + promise(max_values > 0); + + // Don't bother searching if the current worst error beats the new error + if (this_error >= best_errors[max_values - 1]) + { + return; + } + + // Else insert into the list in error-order + for (unsigned int i = 0; i < max_values; i++) + { + // Existing result is better - move on ... + if (this_error > best_errors[i]) + { + continue; + } + + // Move existing results down one + for (unsigned int j = max_values - 1; j > i; j--) + { + best_errors[j] = best_errors[j - 1]; + best_partitions[j] = best_partitions[j - 1]; + } + + // Insert new result + best_errors[i] = this_error; + best_partitions[i] = this_partition; + break; + } +} + /* See header for documentation. */ -void find_best_partition_candidates( +unsigned int find_best_partition_candidates( const block_size_descriptor& bsd, const image_block& blk, unsigned int partition_count, unsigned int partition_search_limit, - unsigned int best_partitions[2] + unsigned int best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES], + unsigned int requested_candidates ) { // Constant used to estimate quantization error for a given partitioning; the optimal value for // this depends on bitrate. These values have been determined empirically. @@ -517,20 +578,26 @@ void find_best_partition_candidates( weight_imprecision_estim = weight_imprecision_estim * weight_imprecision_estim; - unsigned int partition_sequence[BLOCK_MAX_PARTITIONINGS]; + uint16_t partition_sequence[BLOCK_MAX_PARTITIONINGS]; unsigned int sequence_len = compute_kmeans_partition_ordering(bsd, blk, partition_count, partition_sequence); partition_search_limit = astc::min(partition_search_limit, sequence_len); + requested_candidates = astc::min(partition_search_limit, requested_candidates); bool uses_alpha = !blk.is_constant_channel(3); // Partitioning errors assuming uncorrelated-chrominance endpoints - float uncor_best_error { ERROR_CALC_DEFAULT }; - unsigned int uncor_best_partition { 0 }; + float uncor_best_errors[TUNE_MAX_PARTITIONING_CANDIDATES]; + unsigned int uncor_best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES]; // Partitioning errors assuming same-chrominance endpoints - // Store two so we can always return one different to uncorr - float samec_best_errors[2] { ERROR_CALC_DEFAULT, ERROR_CALC_DEFAULT }; - unsigned int samec_best_partitions[2] { 0, 0 }; + float samec_best_errors[TUNE_MAX_PARTITIONING_CANDIDATES]; + unsigned int samec_best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES]; + + for (unsigned int i = 0; i < requested_candidates; i++) + { + uncor_best_errors[i] = ERROR_CALC_DEFAULT; + samec_best_errors[i] = ERROR_CALC_DEFAULT; + } if (uses_alpha) { @@ -550,8 +617,7 @@ void find_best_partition_candidates( processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS]; processed_line4 samec_plines[BLOCK_MAX_PARTITIONS]; - float uncor_line_lens[BLOCK_MAX_PARTITIONS]; - float samec_line_lens[BLOCK_MAX_PARTITIONS]; + float line_lengths[BLOCK_MAX_PARTITIONS]; for (unsigned int j = 0; j < partition_count; j++) { @@ -561,13 +627,13 @@ void find_best_partition_candidates( uncor_lines[j].b = normalize_safe(pm.dir, unit4()); uncor_plines[j].amod = uncor_lines[j].a - uncor_lines[j].b * dot(uncor_lines[j].a, uncor_lines[j].b); - uncor_plines[j].bs = uncor_lines[j].b; + uncor_plines[j].bs = uncor_lines[j].b; samec_lines[j].a = vfloat4::zero(); samec_lines[j].b = normalize_safe(pm.avg, unit4()); samec_plines[j].amod = vfloat4::zero(); - samec_plines[j].bs = samec_lines[j].b; + samec_plines[j].bs = samec_lines[j].b; } float uncor_error = 0.0f; @@ -577,8 +643,7 @@ void find_best_partition_candidates( blk, uncor_plines, samec_plines, - uncor_line_lens, - samec_line_lens, + line_lengths, uncor_error, samec_error); @@ -597,32 +662,15 @@ void find_best_partition_candidates( float tpp = static_cast(pi.partition_texel_count[j]); vfloat4 error_weights(tpp * weight_imprecision_estim); - vfloat4 uncor_vector = uncor_lines[j].b * uncor_line_lens[j]; - vfloat4 samec_vector = samec_lines[j].b * samec_line_lens[j]; + vfloat4 uncor_vector = uncor_lines[j].b * line_lengths[j]; + vfloat4 samec_vector = samec_lines[j].b * line_lengths[j]; uncor_error += dot_s(uncor_vector * uncor_vector, error_weights); samec_error += dot_s(samec_vector * samec_vector, error_weights); } - if (uncor_error < uncor_best_error) - { - uncor_best_error = uncor_error; - uncor_best_partition = partition; - } - - if (samec_error < samec_best_errors[0]) - { - samec_best_errors[1] = samec_best_errors[0]; - samec_best_partitions[1] = samec_best_partitions[0]; - - samec_best_errors[0] = samec_error; - samec_best_partitions[0] = partition; - } - else if (samec_error < samec_best_errors[1]) - { - samec_best_errors[1] = samec_error; - samec_best_partitions[1] = partition; - } + insert_result(requested_candidates, uncor_error, partition, uncor_best_errors, uncor_best_partitions); + insert_result(requested_candidates, samec_error, partition, samec_best_errors, samec_best_partitions); } } else @@ -644,10 +692,10 @@ void find_best_partition_candidates( partition_lines3& pl = plines[j]; pl.uncor_line.a = pm.avg; - pl.uncor_line.b = normalize_safe(pm.dir.swz<0, 1, 2>(), unit3()); + pl.uncor_line.b = normalize_safe(pm.dir, unit3()); pl.samec_line.a = vfloat4::zero(); - pl.samec_line.b = normalize_safe(pm.avg.swz<0, 1, 2>(), unit3()); + pl.samec_line.b = normalize_safe(pm.avg, unit3()); pl.uncor_pline.amod = pl.uncor_line.a - pl.uncor_line.b * dot3(pl.uncor_line.a, pl.uncor_line.b); pl.uncor_pline.bs = pl.uncor_line.b; @@ -682,57 +730,52 @@ void find_best_partition_candidates( float tpp = static_cast(pi.partition_texel_count[j]); vfloat4 error_weights(tpp * weight_imprecision_estim); - vfloat4 uncor_vector = pl.uncor_line.b * pl.uncor_line_len; - vfloat4 samec_vector = pl.samec_line.b * pl.samec_line_len; + vfloat4 uncor_vector = pl.uncor_line.b * pl.line_length; + vfloat4 samec_vector = pl.samec_line.b * pl.line_length; uncor_error += dot3_s(uncor_vector * uncor_vector, error_weights); samec_error += dot3_s(samec_vector * samec_vector, error_weights); } - if (uncor_error < uncor_best_error) - { - uncor_best_error = uncor_error; - uncor_best_partition = partition; - } - - if (samec_error < samec_best_errors[0]) - { - samec_best_errors[1] = samec_best_errors[0]; - samec_best_partitions[1] = samec_best_partitions[0]; - - samec_best_errors[0] = samec_error; - samec_best_partitions[0] = partition; - } - else if (samec_error < samec_best_errors[1]) - { - samec_best_errors[1] = samec_error; - samec_best_partitions[1] = partition; - } + insert_result(requested_candidates, uncor_error, partition, uncor_best_errors, uncor_best_partitions); + insert_result(requested_candidates, samec_error, partition, samec_best_errors, samec_best_partitions); } } - // Same partition is best for both, so use this first unconditionally - if (uncor_best_partition == samec_best_partitions[0]) - { - best_partitions[0] = samec_best_partitions[0]; - best_partitions[1] = samec_best_partitions[1]; - } - // Uncor is best - else if (uncor_best_error <= samec_best_errors[0]) + unsigned int interleave[2 * TUNE_MAX_PARTITIONING_CANDIDATES]; + for (unsigned int i = 0; i < requested_candidates; i++) { - best_partitions[0] = uncor_best_partition; - best_partitions[1] = samec_best_partitions[0]; + interleave[2 * i] = bsd.get_raw_partition_info(partition_count, uncor_best_partitions[i]).partition_index; + interleave[2 * i + 1] = bsd.get_raw_partition_info(partition_count, samec_best_partitions[i]).partition_index; } - // Samec is best - else + + uint64_t bitmasks[1024/64] { 0 }; + unsigned int emitted = 0; + + // Deduplicate the first "requested" entries + for (unsigned int i = 0; i < requested_candidates * 2; i++) { - best_partitions[0] = samec_best_partitions[0]; - best_partitions[1] = uncor_best_partition; + unsigned int partition = interleave[i]; + + unsigned int word = partition / 64; + unsigned int bit = partition % 64; + + bool written = bitmasks[word] & (1ull << bit); + + if (!written) + { + best_partitions[emitted] = partition; + bitmasks[word] |= 1ull << bit; + emitted++; + + if (emitted == requested_candidates) + { + break; + } + } } - // Convert these back into canonical partition IDs for the rest of the codec - best_partitions[0] = bsd.get_raw_partition_info(partition_count, best_partitions[0]).partition_index; - best_partitions[1] = bsd.get_raw_partition_info(partition_count, best_partitions[1]).partition_index; + return emitted; } #endif diff --git a/Source/astcenc_ideal_endpoints_and_weights.cpp b/Source/astcenc_ideal_endpoints_and_weights.cpp index 9df4417..051782f 100644 --- a/Source/astcenc_ideal_endpoints_and_weights.cpp +++ b/Source/astcenc_ideal_endpoints_and_weights.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -26,6 +26,76 @@ #include "astcenc_internal.h" #include "astcenc_vecmathlib.h" +/** + * @brief Compute the infilled weight for N texel indices in a decimated grid. + * + * @param di The weight grid decimation to use. + * @param weights The decimated weight values to use. + * @param index The first texel index to interpolate. + * + * @return The interpolated weight for the given set of SIMD_WIDTH texels. + */ +static vfloat bilinear_infill_vla( + const decimation_info& di, + const float* weights, + unsigned int index +) { + // Load the bilinear filter texel weight indexes in the decimated grid + vint weight_idx0 = vint(di.texel_weights_tr[0] + index); + vint weight_idx1 = vint(di.texel_weights_tr[1] + index); + vint weight_idx2 = vint(di.texel_weights_tr[2] + index); + vint weight_idx3 = vint(di.texel_weights_tr[3] + index); + + // Load the bilinear filter weights from the decimated grid + vfloat weight_val0 = gatherf(weights, weight_idx0); + vfloat weight_val1 = gatherf(weights, weight_idx1); + vfloat weight_val2 = gatherf(weights, weight_idx2); + vfloat weight_val3 = gatherf(weights, weight_idx3); + + // Load the weight contribution factors for each decimated weight + vfloat tex_weight_float0 = loada(di.texel_weight_contribs_float_tr[0] + index); + vfloat tex_weight_float1 = loada(di.texel_weight_contribs_float_tr[1] + index); + vfloat tex_weight_float2 = loada(di.texel_weight_contribs_float_tr[2] + index); + vfloat tex_weight_float3 = loada(di.texel_weight_contribs_float_tr[3] + index); + + // Compute the bilinear interpolation to generate the per-texel weight + return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1) + + (weight_val2 * tex_weight_float2 + weight_val3 * tex_weight_float3); +} + +/** + * @brief Compute the infilled weight for N texel indices in a decimated grid. + * + * This is specialized version which computes only two weights per texel for + * encodings that are only decimated in a single axis. + * + * @param di The weight grid decimation to use. + * @param weights The decimated weight values to use. + * @param index The first texel index to interpolate. + * + * @return The interpolated weight for the given set of SIMD_WIDTH texels. + */ +static vfloat bilinear_infill_vla_2( + const decimation_info& di, + const float* weights, + unsigned int index +) { + // Load the bilinear filter texel weight indexes in the decimated grid + vint weight_idx0 = vint(di.texel_weights_tr[0] + index); + vint weight_idx1 = vint(di.texel_weights_tr[1] + index); + + // Load the bilinear filter weights from the decimated grid + vfloat weight_val0 = gatherf(weights, weight_idx0); + vfloat weight_val1 = gatherf(weights, weight_idx1); + + // Load the weight contribution factors for each decimated weight + vfloat tex_weight_float0 = loada(di.texel_weight_contribs_float_tr[0] + index); + vfloat tex_weight_float1 = loada(di.texel_weight_contribs_float_tr[1] + index); + + // Compute the bilinear interpolation to generate the per-texel weight + return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1); +} + /** * @brief Compute the ideal endpoints and weights for 1 color component. * @@ -90,7 +160,7 @@ static void compute_ideal_colors_and_weights_1_comp( highvalue = astc::max(value, highvalue); } - if (highvalue < lowvalue) + if (highvalue <= lowvalue) { lowvalue = 0.0f; highvalue = 1e-7f; @@ -198,13 +268,13 @@ static void compute_ideal_colors_and_weights_2_comp( for (unsigned int i = 0; i < partition_count; i++) { - vfloat4 dir = pms[i].dir.swz<0, 1>(); + vfloat4 dir = pms[i].dir; if (hadd_s(dir) < 0.0f) { dir = vfloat4::zero() - dir; } - line2 line { pms[i].avg.swz<0, 1>(), normalize_safe(dir, unit2()) }; + line2 line { pms[i].avg, normalize_safe(dir, unit2()) }; float lowparam { 1e10f }; float highparam { -1e10f }; @@ -222,7 +292,7 @@ static void compute_ideal_colors_and_weights_2_comp( // It is possible for a uniform-color partition to produce length=0; // this causes NaN issues so set to small value to avoid this problem - if (highparam < lowparam) + if (highparam <= lowparam) { lowparam = 0.0f; highparam = 1e-7f; @@ -371,7 +441,7 @@ static void compute_ideal_colors_and_weights_3_comp( // It is possible for a uniform-color partition to produce length=0; // this causes NaN issues so set to small value to avoid this problem - if (highparam < lowparam) + if (highparam <= lowparam) { lowparam = 0.0f; highparam = 1e-7f; @@ -493,7 +563,7 @@ static void compute_ideal_colors_and_weights_4_comp( // It is possible for a uniform-color partition to produce length=0; // this causes NaN issues so set to small value to avoid this problem - if (highparam < lowparam) + if (highparam <= lowparam) { lowparam = 0.0f; highparam = 1e-7f; @@ -621,8 +691,8 @@ float compute_error_of_weight_set_1plane( const float* dec_weight_quant_uvalue ) { vfloatacc error_summav = vfloatacc::zero(); - float error_summa = 0.0f; unsigned int texel_count = di.texel_count; + promise(texel_count > 0); // Process SIMD-width chunks, safe to over-fetch - the extra space is zero initialized if (di.max_texel_weight_count > 2) @@ -675,7 +745,7 @@ float compute_error_of_weight_set_1plane( } // Resolve the final scalar accumulator sum - return error_summa = hadd_s(error_summav); + return hadd_s(error_summav); } /* See header for documentation. */ @@ -688,6 +758,7 @@ float compute_error_of_weight_set_2planes( ) { vfloatacc error_summav = vfloatacc::zero(); unsigned int texel_count = di.texel_count; + promise(texel_count > 0); // Process SIMD-width chunks, safe to over-fetch - the extra space is zero initialized if (di.max_texel_weight_count > 2) @@ -772,8 +843,7 @@ float compute_error_of_weight_set_2planes( /* See header for documentation. */ void compute_ideal_weights_for_decimation( - const endpoints_and_weights& eai_in, - endpoints_and_weights& eai_out, + const endpoints_and_weights& ei, const decimation_info& di, float* dec_weight_ideal_value ) { @@ -783,49 +853,31 @@ void compute_ideal_weights_for_decimation( promise(texel_count > 0); promise(weight_count > 0); - // This function includes a copy of the epw from eai_in to eai_out. We do it here because we - // want to load the data anyway, so we can avoid loading it from memory twice. - eai_out.ep = eai_in.ep; - eai_out.is_constant_weight_error_scale = eai_in.is_constant_weight_error_scale; - // Ensure that the end of the output arrays that are used for SIMD paths later are filled so we // can safely run SIMD elsewhere without a loop tail. Note that this is always safe as weight // arrays always contain space for 64 elements unsigned int prev_weight_count_simd = round_down_to_simd_multiple_vla(weight_count - 1); storea(vfloat::zero(), dec_weight_ideal_value + prev_weight_count_simd); - // If we have a 1:1 mapping just shortcut the computation - clone the weights into both the - // weight set and the output epw copy. - - // Transfer enough to also copy zero initialized SIMD over-fetch region - unsigned int texel_count_simd = round_up_to_simd_multiple_vla(texel_count); - for (unsigned int i = 0; i < texel_count_simd; i += ASTCENC_SIMD_WIDTH) + // If we have a 1:1 mapping just shortcut the computation. Transfer enough to also copy the + // zero-initialized SIMD over-fetch region + if (is_direct) { - vfloat weight(eai_in.weights + i); - vfloat weight_error_scale(eai_in.weight_error_scale + i); - - storea(weight, eai_out.weights + i); - storea(weight_error_scale, eai_out.weight_error_scale + i); - - // Direct 1:1 weight mapping, so clone weights directly - // TODO: Can we just avoid the copy for direct cases? - if (is_direct) + for (unsigned int i = 0; i < texel_count; i += ASTCENC_SIMD_WIDTH) { + vfloat weight(ei.weights + i); storea(weight, dec_weight_ideal_value + i); } - } - if (is_direct) - { return; } // Otherwise compute an estimate and perform single refinement iteration - alignas(ASTCENC_VECALIGN) float infilled_weights[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float infilled_weights[BLOCK_MAX_TEXELS]; // Compute an initial average for each decimated weight - bool constant_wes = eai_in.is_constant_weight_error_scale; - vfloat weight_error_scale(eai_in.weight_error_scale[0]); + bool constant_wes = ei.is_constant_weight_error_scale; + vfloat weight_error_scale(ei.weight_error_scale[0]); // This overshoots - this is OK as we initialize the array tails in the // decimation table structures to safe values ... @@ -842,24 +894,24 @@ void compute_ideal_weights_for_decimation( for (unsigned int j = 0; j < max_texel_count; j++) { - vint texel(di.weight_texel[j] + i); - vfloat weight = loada(di.weights_flt[j] + i); + vint texel(di.weight_texels_tr[j] + i); + vfloat weight = loada(di.weights_texel_contribs_tr[j] + i); if (!constant_wes) { - weight_error_scale = gatherf(eai_in.weight_error_scale, texel); + weight_error_scale = gatherf(ei.weight_error_scale, texel); } vfloat contrib_weight = weight * weight_error_scale; weight_weight += contrib_weight; - initial_weight += gatherf(eai_in.weights, texel) * contrib_weight; + initial_weight += gatherf(ei.weights, texel) * contrib_weight; } storea(initial_weight / weight_weight, dec_weight_ideal_value + i); } - // Populate the interpolated weight grid based on the initital average + // Populate the interpolated weight grid based on the initial average // Process SIMD-width texel coordinates at at time while we can. Safe to // over-process full SIMD vectors - the tail is zeroed. if (di.max_texel_weight_count <= 2) @@ -900,17 +952,17 @@ void compute_ideal_weights_for_decimation( for (unsigned int j = 0; j < max_texel_count; j++) { - vint texel(di.weight_texel[j] + i); - vfloat contrib_weight = loada(di.weights_flt[j] + i); + vint texel(di.weight_texels_tr[j] + i); + vfloat contrib_weight = loada(di.weights_texel_contribs_tr[j] + i); if (!constant_wes) { - weight_error_scale = gatherf(eai_in.weight_error_scale, texel); + weight_error_scale = gatherf(ei.weight_error_scale, texel); } vfloat scale = weight_error_scale * contrib_weight; vfloat old_weight = gatherf(infilled_weights, texel); - vfloat ideal_weight = gatherf(eai_in.weights, texel); + vfloat ideal_weight = gatherf(ei.weights, texel); error_change0 += contrib_weight * scale; error_change1 += (old_weight - ideal_weight) * scale; @@ -919,7 +971,7 @@ void compute_ideal_weights_for_decimation( vfloat step = (error_change1 * chd_scale) / error_change0; step = clamp(-stepsize, stepsize, step); - // Update the weight; note this can store negative values. + // Update the weight; note this can store negative values storea(weight_val + step, dec_weight_ideal_value + i); } } @@ -936,19 +988,20 @@ void compute_quantized_weights_for_decimation( ) { int weight_count = di.weight_count; promise(weight_count > 0); - const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[quant_level]); + const quant_and_transfer_table& qat = quant_and_xfer_tables[quant_level]; // The available quant levels, stored with a minus 1 bias static const float quant_levels_m1[12] { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 7.0f, 9.0f, 11.0f, 15.0f, 19.0f, 23.0f, 31.0f }; + vint steps_m1(get_quant_level(quant_level) - 1); float quant_level_m1 = quant_levels_m1[quant_level]; // Quantize the weight set using both the specified low/high bounds and standard 0..1 bounds // TODO: Oddity to investigate; triggered by test in issue #265. - if (high_bound < low_bound) + if (high_bound <= low_bound) { low_bound = 0.0f; high_bound = 1.0f; @@ -968,29 +1021,72 @@ void compute_quantized_weights_for_decimation( // This runs to the rounded-up SIMD size, which is safe as the loop tail is filled with known // safe data in compute_ideal_weights_for_decimation and arrays are always 64 elements - for (int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) + if (get_quant_level(quant_level) <= 16) { - vfloat ix = loada(&dec_weight_ideal_value[i]) * scalev - scaled_low_boundv; - ix = clampzo(ix); + vint4 tab0 = vint4::load(qat.quant_to_unquant); + vint tab0p; + vtable_prepare(tab0, tab0p); + + for (int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) + { + vfloat ix = loada(dec_weight_ideal_value + i) * scalev - scaled_low_boundv; + ix = clampzo(ix); - // Look up the two closest indexes and return the one that was closest - vfloat ix1 = ix * quant_level_m1v; + // Look up the two closest indexes and return the one that was closest + vfloat ix1 = ix * quant_level_m1v; - vint weightl = float_to_int(ix1); - vint weighth = weightl + vint(1); + vint weightl = float_to_int(ix1); + vint weighth = min(weightl + vint(1), steps_m1); - vfloat ixl = gatherf(qat->unquantized_value_unsc, weightl); - vfloat ixh = gatherf(qat->unquantized_value_unsc, weighth); + vint ixli = vtable_8bt_32bi(tab0p, weightl); + vint ixhi = vtable_8bt_32bi(tab0p, weighth); - vmask mask = (ixl + ixh) < (vfloat(128.0f) * ix); - vint weight = select(weightl, weighth, mask); - ixl = select(ixl, ixh, mask); + vfloat ixl = int_to_float(ixli); + vfloat ixh = int_to_float(ixhi); - // Invert the weight-scaling that was done initially - storea(ixl * rscalev + low_boundv, &weight_set_out[i]); - vint scm = gatheri(qat->scramble_map, weight); - vint scn = pack_low_bytes(scm); - store_nbytes(scn, &quantized_weight_set[i]); + vmask mask = (ixl + ixh) < (vfloat(128.0f) * ix); + vint weight = select(ixli, ixhi, mask); + ixl = select(ixl, ixh, mask); + + // Invert the weight-scaling that was done initially + storea(ixl * rscalev + low_boundv, weight_set_out + i); + vint scn = pack_low_bytes(weight); + store_nbytes(scn, quantized_weight_set + i); + } + } + else + { + vint4 tab0 = vint4::load(qat.quant_to_unquant + 0); + vint4 tab1 = vint4::load(qat.quant_to_unquant + 16); + vint tab0p, tab1p; + vtable_prepare(tab0, tab1, tab0p, tab1p); + + for (int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) + { + vfloat ix = loada(dec_weight_ideal_value + i) * scalev - scaled_low_boundv; + ix = clampzo(ix); + + // Look up the two closest indexes and return the one that was closest + vfloat ix1 = ix * quant_level_m1v; + + vint weightl = float_to_int(ix1); + vint weighth = min(weightl + vint(1), steps_m1); + + vint ixli = vtable_8bt_32bi(tab0p, tab1p, weightl); + vint ixhi = vtable_8bt_32bi(tab0p, tab1p, weighth); + + vfloat ixl = int_to_float(ixli); + vfloat ixh = int_to_float(ixhi); + + vmask mask = (ixl + ixh) < (vfloat(128.0f) * ix); + vint weight = select(ixli, ixhi, mask); + ixl = select(ixl, ixh, mask); + + // Invert the weight-scaling that was done initially + storea(ixl * rscalev + low_boundv, weight_set_out + i); + vint scn = pack_low_bytes(weight); + store_nbytes(scn, quantized_weight_set + i); + } } } @@ -1062,8 +1158,7 @@ void recompute_ideal_colors_1plane( const image_block& blk, const partition_info& pi, const decimation_info& di, - int weight_quant_mode, - const uint8_t* dec_weights_quant_pvalue, + const uint8_t* dec_weights_uquant, endpoints& ep, vfloat4 rgbs_vectors[BLOCK_MAX_PARTITIONS], vfloat4 rgbo_vectors[BLOCK_MAX_PARTITIONS] @@ -1076,15 +1171,15 @@ void recompute_ideal_colors_1plane( promise(total_texel_count > 0); promise(partition_count > 0); - const quantization_and_transfer_table& qat = quant_and_xfer_tables[weight_quant_mode]; - - float dec_weight[BLOCK_MAX_WEIGHTS]; - for (unsigned int i = 0; i < weight_count; i++) + ASTCENC_ALIGNAS float dec_weight[BLOCK_MAX_WEIGHTS]; + for (unsigned int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) { - dec_weight[i] = qat.unquantized_value[dec_weights_quant_pvalue[i]] * (1.0f / 64.0f); + vint unquant_value(dec_weights_uquant + i); + vfloat unquant_valuef = int_to_float(unquant_value) * vfloat(1.0f / 64.0f); + storea(unquant_valuef, dec_weight + i); } - alignas(ASTCENC_VECALIGN) float undec_weight[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float undec_weight[BLOCK_MAX_TEXELS]; float* undec_weight_ref; if (di.max_texel_weight_count == 1) { @@ -1121,7 +1216,7 @@ void recompute_ideal_colors_1plane( // Only compute a partition mean if more than one partition if (partition_count > 1) { - rgba_sum = vfloat4(1e-17f); + rgba_sum = vfloat4::zero(); promise(texel_count > 0); for (unsigned int j = 0; j < texel_count; j++) { @@ -1157,7 +1252,6 @@ void recompute_ideal_colors_1plane( for (unsigned int j = 0; j < texel_count; j++) { unsigned int tix = texel_indexes[j]; - vfloat4 rgba = blk.texel(tix); float idx0 = undec_weight_ref[tix]; @@ -1190,14 +1284,11 @@ void recompute_ideal_colors_1plane( vfloat4 right_sum = vfloat4(right_sum_s) * color_weight; vfloat4 lmrs_sum = vfloat3(left_sum_s, middle_sum_s, right_sum_s) * ls_weight; - vfloat4 weight_weight_sum = vfloat4(weight_weight_sum_s) * color_weight; - float psum = right_sum_s * hadd_rgb_s(color_weight); - color_vec_x = color_vec_x * color_weight; color_vec_y = color_vec_y * color_weight; // Initialize the luminance and scale vectors with a reasonable default - float scalediv = scale_min * (1.0f / astc::max(scale_max, 1e-10f)); + float scalediv = scale_min / astc::max(scale_max, 1e-10f); scalediv = astc::clamp1f(scalediv); vfloat4 sds = scale_dir * scale_max; @@ -1249,32 +1340,38 @@ void recompute_ideal_colors_1plane( if (fabsf(ls_det1) > (ls_mss1 * 1e-4f) && scale_ep0 == scale_ep0 && scale_ep1 == scale_ep1 && scale_ep0 < scale_ep1) { - float scalediv2 = scale_ep0 * (1.0f / scale_ep1); + float scalediv2 = scale_ep0 / scale_ep1; vfloat4 sdsm = scale_dir * scale_ep1; rgbs_vectors[i] = vfloat4(sdsm.lane<0>(), sdsm.lane<1>(), sdsm.lane<2>(), scalediv2); } } - // Calculations specific to mode #7, the HDR RGB-scale mode - vfloat4 rgbq_sum = color_vec_x + color_vec_y; - rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y)); + // Calculations specific to mode #7, the HDR RGB-scale mode - skip if known LDR + if (blk.rgb_lns[0] || blk.alpha_lns[0]) + { + vfloat4 weight_weight_sum = vfloat4(weight_weight_sum_s) * color_weight; + float psum = right_sum_s * hadd_rgb_s(color_weight); - vfloat4 rgbovec = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum); - rgbo_vectors[i] = rgbovec; + vfloat4 rgbq_sum = color_vec_x + color_vec_y; + rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y)); - // We can get a failure due to the use of a singular (non-invertible) matrix - // If it failed, compute rgbo_vectors[] with a different method ... - if (astc::isnan(dot_s(rgbovec, rgbovec))) - { - vfloat4 v0 = ep.endpt0[i]; - vfloat4 v1 = ep.endpt1[i]; + vfloat4 rgbovec = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum); + rgbo_vectors[i] = rgbovec; - float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f); - avgdif = astc::max(avgdif, 0.0f); + // We can get a failure due to the use of a singular (non-invertible) matrix + // If it failed, compute rgbo_vectors[] with a different method ... + if (astc::isnan(dot_s(rgbovec, rgbovec))) + { + vfloat4 v0 = ep.endpt0[i]; + vfloat4 v1 = ep.endpt1[i]; - vfloat4 avg = (v0 + v1) * 0.5f; - vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f; - rgbo_vectors[i] = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif); + float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f); + avgdif = astc::max(avgdif, 0.0f); + + vfloat4 avg = (v0 + v1) * 0.5f; + vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f; + rgbo_vectors[i] = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif); + } } } } @@ -1284,9 +1381,8 @@ void recompute_ideal_colors_2planes( const image_block& blk, const block_size_descriptor& bsd, const decimation_info& di, - int weight_quant_mode, - const uint8_t* dec_weights_quant_pvalue_plane1, - const uint8_t* dec_weights_quant_pvalue_plane2, + const uint8_t* dec_weights_uquant_plane1, + const uint8_t* dec_weights_uquant_plane2, endpoints& ep, vfloat4& rgbs_vector, vfloat4& rgbo_vector, @@ -1298,20 +1394,24 @@ void recompute_ideal_colors_2planes( promise(total_texel_count > 0); promise(weight_count > 0); - const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[weight_quant_mode]); - - float dec_weight_plane1[BLOCK_MAX_WEIGHTS_2PLANE]; - float dec_weight_plane2[BLOCK_MAX_WEIGHTS_2PLANE]; + ASTCENC_ALIGNAS float dec_weight_plane1[BLOCK_MAX_WEIGHTS_2PLANE]; + ASTCENC_ALIGNAS float dec_weight_plane2[BLOCK_MAX_WEIGHTS_2PLANE]; assert(weight_count <= BLOCK_MAX_WEIGHTS_2PLANE); - for (unsigned int i = 0; i < weight_count; i++) + + for (unsigned int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) { - dec_weight_plane1[i] = qat->unquantized_value[dec_weights_quant_pvalue_plane1[i]] * (1.0f / 64.0f); - dec_weight_plane2[i] = qat->unquantized_value[dec_weights_quant_pvalue_plane2[i]] * (1.0f / 64.0f); + vint unquant_value1(dec_weights_uquant_plane1 + i); + vfloat unquant_value1f = int_to_float(unquant_value1) * vfloat(1.0f / 64.0f); + storea(unquant_value1f, dec_weight_plane1 + i); + + vint unquant_value2(dec_weights_uquant_plane2 + i); + vfloat unquant_value2f = int_to_float(unquant_value2) * vfloat(1.0f / 64.0f); + storea(unquant_value2f, dec_weight_plane2 + i); } - alignas(ASTCENC_VECALIGN) float undec_weight_plane1[BLOCK_MAX_TEXELS]; - alignas(ASTCENC_VECALIGN) float undec_weight_plane2[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float undec_weight_plane1[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float undec_weight_plane2[BLOCK_MAX_TEXELS]; float* undec_weight_plane1_ref; float* undec_weight_plane2_ref; @@ -1419,7 +1519,7 @@ void recompute_ideal_colors_2planes( color_vec_x += cwprod - cwiprod; scale_vec += vfloat2(om_idx0, idx0) * (ls_weight * scale); - weight_weight_sum += (color_weight * color_idx); + weight_weight_sum += color_idx; } vfloat4 left1_sum = vfloat4(left1_sum_s) * color_weight; @@ -1431,13 +1531,11 @@ void recompute_ideal_colors_2planes( vfloat4 middle2_sum = vfloat4(middle2_sum_s) * color_weight; vfloat4 right2_sum = vfloat4(right2_sum_s) * color_weight; - float psum = dot3_s(select(right1_sum, right2_sum, p2_mask), color_weight); - color_vec_x = color_vec_x * color_weight; color_vec_y = color_vec_y * color_weight; // Initialize the luminance and scale vectors with a reasonable default - float scalediv = scale_min * (1.0f / astc::max(scale_max, 1e-10f)); + float scalediv = scale_min / astc::max(scale_max, 1e-10f); scalediv = astc::clamp1f(scalediv); vfloat4 sds = scale_dir * scale_max; @@ -1493,7 +1591,7 @@ void recompute_ideal_colors_2planes( if (fabsf(ls_det1) > (ls_mss1 * 1e-4f) && scale_ep0 == scale_ep0 && scale_ep1 == scale_ep1 && scale_ep0 < scale_ep1) { - float scalediv2 = scale_ep0 * (1.0f / scale_ep1); + float scalediv2 = scale_ep0 / scale_ep1; vfloat4 sdsm = scale_dir * scale_ep1; rgbs_vector = vfloat4(sdsm.lane<0>(), sdsm.lane<1>(), sdsm.lane<2>(), scalediv2); } @@ -1533,26 +1631,32 @@ void recompute_ideal_colors_2planes( ep.endpt1[0] = select(ep.endpt1[0], ep1, full_mask); } - // Calculations specific to mode #7, the HDR RGB-scale mode - vfloat4 rgbq_sum = color_vec_x + color_vec_y; - rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y)); + // Calculations specific to mode #7, the HDR RGB-scale mode - skip if known LDR + if (blk.rgb_lns[0] || blk.alpha_lns[0]) + { + weight_weight_sum = weight_weight_sum * color_weight; + float psum = dot3_s(select(right1_sum, right2_sum, p2_mask), color_weight); - rgbo_vector = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum); + vfloat4 rgbq_sum = color_vec_x + color_vec_y; + rgbq_sum.set_lane<3>(hadd_rgb_s(color_vec_y)); - // We can get a failure due to the use of a singular (non-invertible) matrix - // If it failed, compute rgbo_vectors[] with a different method ... - if (astc::isnan(dot_s(rgbo_vector, rgbo_vector))) - { - vfloat4 v0 = ep.endpt0[0]; - vfloat4 v1 = ep.endpt1[0]; + rgbo_vector = compute_rgbo_vector(rgba_weight_sum, weight_weight_sum, rgbq_sum, psum); + + // We can get a failure due to the use of a singular (non-invertible) matrix + // If it failed, compute rgbo_vectors[] with a different method ... + if (astc::isnan(dot_s(rgbo_vector, rgbo_vector))) + { + vfloat4 v0 = ep.endpt0[0]; + vfloat4 v1 = ep.endpt1[0]; - float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f); - avgdif = astc::max(avgdif, 0.0f); + float avgdif = hadd_rgb_s(v1 - v0) * (1.0f / 3.0f); + avgdif = astc::max(avgdif, 0.0f); - vfloat4 avg = (v0 + v1) * 0.5f; - vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f; + vfloat4 avg = (v0 + v1) * 0.5f; + vfloat4 ep0 = avg - vfloat4(avgdif) * 0.5f; - rgbo_vector = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif); + rgbo_vector = vfloat4(ep0.lane<0>(), ep0.lane<1>(), ep0.lane<2>(), avgdif); + } } } diff --git a/Source/astcenc_image.cpp b/Source/astcenc_image.cpp index 1c9f394..8622a92 100644 --- a/Source/astcenc_image.cpp +++ b/Source/astcenc_image.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -109,7 +109,7 @@ static vfloat4 swz_texel( vfloat4 data, const astcenc_swizzle& swz ) { - alignas(16) float datas[6]; + ASTCENC_ALIGNAS float datas[6]; storea(data, datas); datas[ASTCENC_SWZ_0] = 0.0f; @@ -143,12 +143,12 @@ static vfloat4 encode_texel_lns( vmask4 lns_mask ) { vfloat4 datav_unorm = data * 65535.0f; - vfloat4 datav_lns = float_to_lns(data); + vfloat4 datav_lns = float_to_lns(data); return select(datav_unorm, datav_lns, lns_mask); } /* See header for documentation. */ -void fetch_image_block( +void load_image_block( astcenc_profile decode_mode, const astcenc_image& img, image_block& blk, @@ -265,7 +265,7 @@ void fetch_image_block( } /* See header for documentation. */ -void fetch_image_block_fast_ldr( +void load_image_block_fast_ldr( astcenc_profile decode_mode, const astcenc_image& img, image_block& blk, @@ -332,7 +332,7 @@ void fetch_image_block_fast_ldr( } /* See header for documentation. */ -void write_image_block( +void store_image_block( astcenc_image& img, const image_block& blk, const block_size_descriptor& bsd, @@ -341,24 +341,21 @@ void write_image_block( unsigned int zpos, const astcenc_swizzle& swz ) { - unsigned int xsize = img.dim_x; - unsigned int ysize = img.dim_y; - unsigned int zsize = img.dim_z; - + unsigned int x_size = img.dim_x; unsigned int x_start = xpos; - unsigned int x_end = std::min(xsize, xpos + bsd.xdim); - unsigned int x_nudge = bsd.xdim - (x_end - x_start); + unsigned int x_end = astc::min(x_size, xpos + bsd.xdim); + unsigned int x_count = x_end - x_start; + unsigned int x_nudge = bsd.xdim - x_count; + unsigned int y_size = img.dim_y; unsigned int y_start = ypos; - unsigned int y_end = std::min(ysize, ypos + bsd.ydim); - unsigned int y_nudge = (bsd.ydim - (y_end - y_start)) * bsd.xdim; + unsigned int y_end = astc::min(y_size, ypos + bsd.ydim); + unsigned int y_count = y_end - y_start; + unsigned int y_nudge = (bsd.ydim - y_count) * bsd.xdim; + unsigned int z_size = img.dim_z; unsigned int z_start = zpos; - unsigned int z_end = std::min(zsize, zpos + bsd.zdim); - - float data[7]; - data[ASTCENC_SWZ_0] = 0.0f; - data[ASTCENC_SWZ_1] = 1.0f; + unsigned int z_end = astc::min(z_size, zpos + bsd.zdim); // True if any non-identity swizzle bool needs_swz = (swz.r != ASTCENC_SWZ_R) || (swz.g != ASTCENC_SWZ_G) || @@ -378,47 +375,68 @@ void write_image_block( for (unsigned int y = y_start; y < y_end; y++) { - for (unsigned int x = x_start; x < x_end; x++) + uint8_t* data8_row = data8 + (4 * x_size * y) + (4 * x_start); + + for (unsigned int x = 0; x < x_count; x += ASTCENC_SIMD_WIDTH) { - vint4 colori = vint4::zero(); + unsigned int max_texels = ASTCENC_SIMD_WIDTH; + unsigned int used_texels = astc::min(x_count - x, max_texels); - // Errors are NaN encoded - convert to magenta error color - if (blk.data_r[idx] != blk.data_r[idx]) - { - colori = vint4(0xFF, 0x00, 0xFF, 0xFF); - } - else if (needs_swz) + // Unaligned load as rows are not always SIMD_WIDTH long + vfloat data_r(blk.data_r + idx); + vfloat data_g(blk.data_g + idx); + vfloat data_b(blk.data_b + idx); + vfloat data_a(blk.data_a + idx); + + vint data_ri = float_to_int_rtn(min(data_r, 1.0f) * 255.0f); + vint data_gi = float_to_int_rtn(min(data_g, 1.0f) * 255.0f); + vint data_bi = float_to_int_rtn(min(data_b, 1.0f) * 255.0f); + vint data_ai = float_to_int_rtn(min(data_a, 1.0f) * 255.0f); + + if (needs_swz) { - data[ASTCENC_SWZ_R] = blk.data_r[idx]; - data[ASTCENC_SWZ_G] = blk.data_g[idx]; - data[ASTCENC_SWZ_B] = blk.data_b[idx]; - data[ASTCENC_SWZ_A] = blk.data_a[idx]; + vint swizzle_table[7]; + swizzle_table[ASTCENC_SWZ_0] = vint(0); + swizzle_table[ASTCENC_SWZ_1] = vint(255); + swizzle_table[ASTCENC_SWZ_R] = data_ri; + swizzle_table[ASTCENC_SWZ_G] = data_gi; + swizzle_table[ASTCENC_SWZ_B] = data_bi; + swizzle_table[ASTCENC_SWZ_A] = data_ai; if (needs_z) { - float xcoord = (data[0] * 2.0f) - 1.0f; - float ycoord = (data[3] * 2.0f) - 1.0f; - float zcoord = 1.0f - xcoord * xcoord - ycoord * ycoord; - if (zcoord < 0.0f) - { - zcoord = 0.0f; - } - data[ASTCENC_SWZ_Z] = (astc::sqrt(zcoord) * 0.5f) + 0.5f; + vfloat data_x = (data_r * vfloat(2.0f)) - vfloat(1.0f); + vfloat data_y = (data_a * vfloat(2.0f)) - vfloat(1.0f); + vfloat data_z = vfloat(1.0f) - (data_x * data_x) - (data_y * data_y); + data_z = max(data_z, 0.0f); + data_z = (sqrt(data_z) * vfloat(0.5f)) + vfloat(0.5f); + + swizzle_table[ASTCENC_SWZ_Z] = float_to_int_rtn(min(data_z, 1.0f) * 255.0f); } - vfloat4 color = vfloat4(data[swz.r], data[swz.g], data[swz.b], data[swz.a]); - colori = float_to_int_rtn(min(color, 1.0f) * 255.0f); + data_ri = swizzle_table[swz.r]; + data_gi = swizzle_table[swz.g]; + data_bi = swizzle_table[swz.b]; + data_ai = swizzle_table[swz.a]; } - else + + // Errors are NaN encoded - convert to magenta error color + // Branch is OK here - it is almost never true so predicts well + vmask nan_mask = data_r != data_r; + if (any(nan_mask)) { - vfloat4 color = blk.texel(idx); - colori = float_to_int_rtn(min(color, 1.0f) * 255.0f); + data_ri = select(data_ri, vint(0xFF), nan_mask); + data_gi = select(data_gi, vint(0x00), nan_mask); + data_bi = select(data_bi, vint(0xFF), nan_mask); + data_ai = select(data_ai, vint(0xFF), nan_mask); } - colori = pack_low_bytes(colori); - store_nbytes(colori, data8 + (4 * xsize * y) + (4 * x )); + vint data_rgbai = interleave_rgba8(data_ri, data_gi, data_bi, data_ai); + vmask store_mask = vint::lane_id() < vint(used_texels); + store_lanes_masked(data8_row, data_rgbai, store_mask); - idx++; + data8_row += ASTCENC_SIMD_WIDTH * 4; + idx += used_texels; } idx += x_nudge; } @@ -434,13 +452,18 @@ void write_image_block( for (unsigned int y = y_start; y < y_end; y++) { - for (unsigned int x = x_start; x < x_end; x++) + uint16_t* data16_row = data16 + (4 * x_size * y) + (4 * x_start); + + for (unsigned int x = 0; x < x_count; x++) { vint4 color; // NaNs are handled inline - no need to special case if (needs_swz) { + float data[7]; + data[ASTCENC_SWZ_0] = 0.0f; + data[ASTCENC_SWZ_1] = 1.0f; data[ASTCENC_SWZ_R] = blk.data_r[idx]; data[ASTCENC_SWZ_G] = blk.data_g[idx]; data[ASTCENC_SWZ_B] = blk.data_b[idx]; @@ -467,11 +490,12 @@ void write_image_block( color = float_to_float16(colorf); } - data16[(4 * xsize * y) + (4 * x )] = static_cast(color.lane<0>()); - data16[(4 * xsize * y) + (4 * x + 1)] = static_cast(color.lane<1>()); - data16[(4 * xsize * y) + (4 * x + 2)] = static_cast(color.lane<2>()); - data16[(4 * xsize * y) + (4 * x + 3)] = static_cast(color.lane<3>()); - + // TODO: Vectorize with store N shorts? + data16_row[0] = static_cast(color.lane<0>()); + data16_row[1] = static_cast(color.lane<1>()); + data16_row[2] = static_cast(color.lane<2>()); + data16_row[3] = static_cast(color.lane<3>()); + data16_row += 4; idx++; } idx += x_nudge; @@ -490,13 +514,18 @@ void write_image_block( for (unsigned int y = y_start; y < y_end; y++) { - for (unsigned int x = x_start; x < x_end; x++) + float* data32_row = data32 + (4 * x_size * y) + (4 * x_start); + + for (unsigned int x = 0; x < x_count; x++) { vfloat4 color = blk.texel(idx); // NaNs are handled inline - no need to special case if (needs_swz) { + float data[7]; + data[ASTCENC_SWZ_0] = 0.0f; + data[ASTCENC_SWZ_1] = 1.0f; data[ASTCENC_SWZ_R] = color.lane<0>(); data[ASTCENC_SWZ_G] = color.lane<1>(); data[ASTCENC_SWZ_B] = color.lane<2>(); @@ -517,8 +546,8 @@ void write_image_block( color = vfloat4(data[swz.r], data[swz.g], data[swz.b], data[swz.a]); } - store(color, data32 + (4 * xsize * y) + (4 * x )); - + store(color, data32_row); + data32_row += 4; idx++; } idx += x_nudge; diff --git a/Source/astcenc_integer_sequence.cpp b/Source/astcenc_integer_sequence.cpp index 9675ab5..4167503 100644 --- a/Source/astcenc_integer_sequence.cpp +++ b/Source/astcenc_integer_sequence.cpp @@ -24,6 +24,7 @@ #include /** @brief Unpacked quint triplets for each packed value */ +// TODO: Bitpack these into a uint16_t? static const uint8_t quints_of_integer[128][3] { {0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0}, {4, 0, 0}, {0, 4, 0}, {4, 4, 0}, {4, 4, 4}, @@ -99,6 +100,7 @@ static const uint8_t integer_of_quints[5][5][5] { }; /** @brief Unpacked trit quintuplets for each packed value */ +// TODO: Bitpack these into a uint16_t? static const uint8_t trits_of_integer[256][5] { {0, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, {2, 0, 0, 0, 0}, {0, 0, 2, 0, 0}, {0, 1, 0, 0, 0}, {1, 1, 0, 0, 0}, {2, 1, 0, 0, 0}, {1, 0, 2, 0, 0}, @@ -334,44 +336,41 @@ static const uint8_t integer_of_trits[3][3][3][3][3] { */ struct btq_count { - /** @brief The quantization level. */ - uint8_t quant; - /** @brief The number of bits. */ - uint8_t bits; + uint8_t bits:6; /** @brief The number of trits. */ - uint8_t trits; + uint8_t trits:1; /** @brief The number of quints. */ - uint8_t quints; + uint8_t quints:1; }; /** * @brief The table of bits, trits, and quints needed for a quant encode. */ static const std::array btq_counts {{ - { QUANT_2, 1, 0, 0 }, - { QUANT_3, 0, 1, 0 }, - { QUANT_4, 2, 0, 0 }, - { QUANT_5, 0, 0, 1 }, - { QUANT_6, 1, 1, 0 }, - { QUANT_8, 3, 0, 0 }, - { QUANT_10, 1, 0, 1 }, - { QUANT_12, 2, 1, 0 }, - { QUANT_16, 4, 0, 0 }, - { QUANT_20, 2, 0, 1 }, - { QUANT_24, 3, 1, 0 }, - { QUANT_32, 5, 0, 0 }, - { QUANT_40, 3, 0, 1 }, - { QUANT_48, 4, 1, 0 }, - { QUANT_64, 6, 0, 0 }, - { QUANT_80, 4, 0, 1 }, - { QUANT_96, 5, 1, 0 }, - { QUANT_128, 7, 0, 0 }, - { QUANT_160, 5, 0, 1 }, - { QUANT_192, 6, 1, 0 }, - { QUANT_256, 8, 0, 0 } + { 1, 0, 0 }, // QUANT_2 + { 0, 1, 0 }, // QUANT_3 + { 2, 0, 0 }, // QUANT_4 + { 0, 0, 1 }, // QUANT_5 + { 1, 1, 0 }, // QUANT_6 + { 3, 0, 0 }, // QUANT_8 + { 1, 0, 1 }, // QUANT_10 + { 2, 1, 0 }, // QUANT_12 + { 4, 0, 0 }, // QUANT_16 + { 2, 0, 1 }, // QUANT_20 + { 3, 1, 0 }, // QUANT_24 + { 5, 0, 0 }, // QUANT_32 + { 3, 0, 1 }, // QUANT_40 + { 4, 1, 0 }, // QUANT_48 + { 6, 0, 0 }, // QUANT_64 + { 4, 0, 1 }, // QUANT_80 + { 5, 1, 0 }, // QUANT_96 + { 7, 0, 0 }, // QUANT_128 + { 5, 0, 1 }, // QUANT_160 + { 6, 1, 0 }, // QUANT_192 + { 8, 0, 0 } // QUANT_256 }}; /** @@ -382,44 +381,38 @@ static const std::array btq_counts {{ */ struct ise_size { - /** @brief The quantization level. */ - uint8_t quant; - /** @brief The scaling parameter. */ - uint8_t scale; - - /** @brief The rounding parameter. */ - uint8_t round; + uint8_t scale:6; /** @brief The divisor parameter. */ - uint8_t divisor; + uint8_t divisor:2; }; /** * @brief The table of scale, round, and divisors needed for quant sizing. */ static const std::array ise_sizes {{ - { QUANT_2, 1, 0, 1 }, - { QUANT_3, 8, 4, 5 }, - { QUANT_4, 2, 0, 1 }, - { QUANT_5, 7, 2, 3 }, - { QUANT_6, 13, 4, 5 }, - { QUANT_8, 3, 0, 1 }, - { QUANT_10, 10, 2, 3 }, - { QUANT_12, 18, 4, 5 }, - { QUANT_16, 4, 0, 1 }, - { QUANT_20, 13, 2, 3 }, - { QUANT_24, 23, 4, 5 }, - { QUANT_32, 5, 0, 1 }, - { QUANT_40, 16, 2, 3 }, - { QUANT_48, 28, 4, 5 }, - { QUANT_64, 6, 0, 1 }, - { QUANT_80, 19, 2, 3 }, - { QUANT_96, 33, 4, 5 }, - { QUANT_128, 7, 0, 1 }, - { QUANT_160, 22, 2, 3 }, - { QUANT_192, 38, 4, 5 }, - { QUANT_256, 8, 0, 1 } + { 1, 0 }, // QUANT_2 + { 8, 2 }, // QUANT_3 + { 2, 0 }, // QUANT_4 + { 7, 1 }, // QUANT_5 + { 13, 2 }, // QUANT_6 + { 3, 0 }, // QUANT_8 + { 10, 1 }, // QUANT_10 + { 18, 2 }, // QUANT_12 + { 4, 0 }, // QUANT_16 + { 13, 1 }, // QUANT_20 + { 23, 2 }, // QUANT_24 + { 5, 0 }, // QUANT_32 + { 16, 1 }, // QUANT_40 + { 28, 2 }, // QUANT_48 + { 6, 0 }, // QUANT_64 + { 19, 1 }, // QUANT_80 + { 33, 2 }, // QUANT_96 + { 7, 0 }, // QUANT_128 + { 22, 1 }, // QUANT_160 + { 38, 2 }, // QUANT_192 + { 8, 0 } // QUANT_256 }}; /* See header for documentation. */ @@ -435,7 +428,8 @@ unsigned int get_ise_sequence_bitcount( } auto& entry = ise_sizes[quant_level]; - return (entry.scale * character_count + entry.round) / entry.divisor; + unsigned int divisor = (entry.divisor << 1) + 1; + return (entry.scale * character_count + divisor - 1) / divisor; } /** @@ -645,7 +639,6 @@ void encode_ise( // Write out just bits else { - promise(character_count > 0); for (unsigned int i = 0; i < character_count; i++) { write_bits(input_data[i], bits, bit_offset, output_data); @@ -685,10 +678,10 @@ void decode_ise( if (trits) { - static const unsigned int bits_to_read[5] { 2, 2, 1, 2, 1 }; - static const unsigned int block_shift[5] { 0, 2, 4, 5, 7 }; - static const unsigned int next_lcounter[5] { 1, 2, 3, 4, 0 }; - static const unsigned int hcounter_incr[5] { 0, 0, 0, 0, 1 }; + static const uint8_t bits_to_read[5] { 2, 2, 1, 2, 1 }; + static const uint8_t block_shift[5] { 0, 2, 4, 5, 7 }; + static const uint8_t next_lcounter[5] { 1, 2, 3, 4, 0 }; + static const uint8_t hcounter_incr[5] { 0, 0, 0, 0, 1 }; unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data); bit_offset += bits_to_read[lcounter]; tq_blocks[hcounter] |= tdata << block_shift[lcounter]; @@ -698,10 +691,10 @@ void decode_ise( if (quints) { - static const unsigned int bits_to_read[3] { 3, 2, 2 }; - static const unsigned int block_shift[3] { 0, 3, 5 }; - static const unsigned int next_lcounter[3] { 1, 2, 0 }; - static const unsigned int hcounter_incr[3] { 0, 0, 1 }; + static const uint8_t bits_to_read[3] { 3, 2, 2 }; + static const uint8_t block_shift[3] { 0, 3, 5 }; + static const uint8_t next_lcounter[3] { 1, 2, 0 }; + static const uint8_t hcounter_incr[3] { 0, 0, 1 }; unsigned int tdata = read_bits(bits_to_read[lcounter], bit_offset, input_data); bit_offset += bits_to_read[lcounter]; tq_blocks[hcounter] |= tdata << block_shift[lcounter]; @@ -714,6 +707,7 @@ void decode_ise( if (trits) { unsigned int trit_blocks = (character_count + 4) / 5; + promise(trit_blocks > 0); for (unsigned int i = 0; i < trit_blocks; i++) { const uint8_t *tritptr = trits_of_integer[tq_blocks[i]]; @@ -728,6 +722,7 @@ void decode_ise( if (quints) { unsigned int quint_blocks = (character_count + 2) / 3; + promise(quint_blocks > 0); for (unsigned int i = 0; i < quint_blocks; i++) { const uint8_t *quintptr = quints_of_integer[tq_blocks[i]]; diff --git a/Source/astcenc_internal.h b/Source/astcenc_internal.h index 411723e..4d31a5f 100644 --- a/Source/astcenc_internal.h +++ b/Source/astcenc_internal.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -23,15 +23,13 @@ #define ASTCENC_INTERNAL_INCLUDED #include -#include #include #include -#include +#if defined(ASTCENC_DIAGNOSTICS) + #include +#endif #include -#include -#include -#include -#include +#include #include "astcenc.h" #include "astcenc_mathlib.h" @@ -82,7 +80,7 @@ static constexpr unsigned int BLOCK_MAX_PARTITIONS { 4 }; /** @brief The number of partitionings, per partition count, suported by the ASTC format. */ static constexpr unsigned int BLOCK_MAX_PARTITIONINGS { 1024 }; -/** @brief The maximum number of weights used during partition selection for texel clustering. */ +/** @brief The maximum number of texels used during partition selection for texel clustering. */ static constexpr uint8_t BLOCK_MAX_KMEANS_TEXELS { 64 }; /** @brief The maximum number of weights a block can support. */ @@ -122,23 +120,45 @@ static constexpr unsigned int WEIGHTS_MAX_DECIMATION_MODES { 87 }; static constexpr float ERROR_CALC_DEFAULT { 1e30f }; /** - * @brief The minimum texel count for a block to use the one partition fast path. + * @brief The minimum tuning setting threshold for the one partition fast path. + */ +static constexpr float TUNE_MIN_SEARCH_MODE0 { 0.85f }; + +/** + * @brief The maximum number of candidate encodings tested for each encoding mode. * - * This setting skips 4x4 and 5x4 block sizes. + * This can be dynamically reduced by the compression quality preset. */ -static constexpr unsigned int TUNE_MIN_TEXELS_MODE0_FASTPATH { 24 }; +static constexpr unsigned int TUNE_MAX_TRIAL_CANDIDATES { 8 }; /** - * @brief The maximum number of candidate encodings tested for each encoding mode.. + * @brief The maximum number of candidate partitionings tested for each encoding mode. * * This can be dynamically reduced by the compression quality preset. */ -static constexpr unsigned int TUNE_MAX_TRIAL_CANDIDATES { 4 }; +static constexpr unsigned int TUNE_MAX_PARTITIONING_CANDIDATES { 8 }; +/** + * @brief The maximum quant level using full angular endpoint search method. + * + * The angular endpoint search is used to find the min/max weight that should + * be used for a given quantization level. It is effective but expensive, so + * we only use it where it has the most value - low quant levels with wide + * spacing. It is used below TUNE_MAX_ANGULAR_QUANT (inclusive). Above this we + * assume the min weight is 0.0f, and the max weight is 1.0f. + * + * Note the angular algorithm is vectorized, and using QUANT_12 exactly fills + * one 8-wide vector. Decreasing by one doesn't buy much performance, and + * increasing by one is disproportionately expensive. + */ +static constexpr unsigned int TUNE_MAX_ANGULAR_QUANT { 7 }; /* QUANT_12 */ static_assert((BLOCK_MAX_TEXELS % ASTCENC_SIMD_WIDTH) == 0, "BLOCK_MAX_TEXELS must be multiple of ASTCENC_SIMD_WIDTH"); +static_assert(BLOCK_MAX_TEXELS <= 216, + "BLOCK_MAX_TEXELS must not be greater than 216"); + static_assert((BLOCK_MAX_WEIGHTS % ASTCENC_SIMD_WIDTH) == 0, "BLOCK_MAX_WEIGHTS must be multiple of ASTCENC_SIMD_WIDTH"); @@ -146,223 +166,6 @@ static_assert((WEIGHTS_MAX_BLOCK_MODES % ASTCENC_SIMD_WIDTH) == 0, "WEIGHTS_MAX_BLOCK_MODES must be multiple of ASTCENC_SIMD_WIDTH"); -/* ============================================================================ - Parallel execution control -============================================================================ */ - -/** - * @brief A simple counter-based manager for parallel task execution. - * - * The task processing execution consists of: - * - * * A single-threaded init stage. - * * A multi-threaded processing stage. - * * A condition variable so threads can wait for processing completion. - * - * The init stage will be executed by the first thread to arrive in the critical section, there is - * no main thread in the thread pool. - * - * The processing stage uses dynamic dispatch to assign task tickets to threads on an on-demand - * basis. Threads may each therefore executed different numbers of tasks, depending on their - * processing complexity. The task queue and the task tickets are just counters; the caller must map - * these integers to an actual processing partition in a specific problem domain. - * - * The exit wait condition is needed to ensure processing has finished before a worker thread can - * progress to the next stage of the pipeline. Specifically a worker may exit the processing stage - * because there are no new tasks to assign to it while other worker threads are still processing. - * Calling @c wait() will ensure that all other worker have finished before the thread can proceed. - * - * The basic usage model: - * - * // --------- From single-threaded code --------- - * - * // Reset the tracker state - * manager->reset() - * - * // --------- From multi-threaded code --------- - * - * // Run the stage init; only first thread actually runs the lambda - * manager->init() - * - * do - * { - * // Request a task assignment - * uint task_count; - * uint base_index = manager->get_tasks(, task_count); - * - * // Process any tasks we were given (task_count <= granule size) - * if (task_count) - * { - * // Run the user task processing code for N tasks here - * ... - * - * // Flag these tasks as complete - * manager->complete_tasks(task_count); - * } - * } while (task_count); - * - * // Wait for all threads to complete tasks before progressing - * manager->wait() - * - * // Run the stage term; only first thread actually runs the lambda - * manager->term() - */ -class ParallelManager -{ -private: - /** @brief Lock used for critical section and condition synchronization. */ - std::mutex m_lock; - - /** @brief True if the stage init() step has been executed. */ - bool m_init_done; - - /** @brief True if the stage term() step has been executed. */ - bool m_term_done; - - /** @brief Contition variable for tracking stage processing completion. */ - std::condition_variable m_complete; - - /** @brief Number of tasks started, but not necessarily finished. */ - std::atomic m_start_count; - - /** @brief Number of tasks finished. */ - unsigned int m_done_count; - - /** @brief Number of tasks that need to be processed. */ - unsigned int m_task_count; - -public: - /** @brief Create a new ParallelManager. */ - ParallelManager() - { - reset(); - } - - /** - * @brief Reset the tracker for a new processing batch. - * - * This must be called from single-threaded code before starting the multi-threaded procesing - * operations. - */ - void reset() - { - m_init_done = false; - m_term_done = false; - m_start_count = 0; - m_done_count = 0; - m_task_count = 0; - } - - /** - * @brief Trigger the pipeline stage init step. - * - * This can be called from multi-threaded code. The first thread to hit this will process the - * initialization. Other threads will block and wait for it to complete. - * - * @param init_func Callable which executes the stage initialization. It must return the - * total number of tasks in the stage. - */ - void init(std::function init_func) - { - std::lock_guard lck(m_lock); - if (!m_init_done) - { - m_task_count = init_func(); - m_init_done = true; - } - } - - /** - * @brief Trigger the pipeline stage init step. - * - * This can be called from multi-threaded code. The first thread to hit this will process the - * initialization. Other threads will block and wait for it to complete. - * - * @param task_count Total number of tasks needing processing. - */ - void init(unsigned int task_count) - { - std::lock_guard lck(m_lock); - if (!m_init_done) - { - m_task_count = task_count; - m_init_done = true; - } - } - - /** - * @brief Request a task assignment. - * - * Assign up to @c granule tasks to the caller for processing. - * - * @param granule Maximum number of tasks that can be assigned. - * @param[out] count Actual number of tasks assigned, or zero if no tasks were assigned. - * - * @return Task index of the first assigned task; assigned tasks increment from this. - */ - unsigned int get_task_assignment(unsigned int granule, unsigned int& count) - { - unsigned int base = m_start_count.fetch_add(granule, std::memory_order_relaxed); - if (base >= m_task_count) - { - count = 0; - return 0; - } - - count = astc::min(m_task_count - base, granule); - return base; - } - - /** - * @brief Complete a task assignment. - * - * Mark @c count tasks as complete. This will notify all threads blocked on @c wait() if this - * completes the processing of the stage. - * - * @param count The number of completed tasks. - */ - void complete_task_assignment(unsigned int count) - { - // Note: m_done_count cannot use an atomic without the mutex; this has a race between the - // update here and the wait() for other threads - std::unique_lock lck(m_lock); - this->m_done_count += count; - if (m_done_count == m_task_count) - { - lck.unlock(); - m_complete.notify_all(); - } - } - - /** - * @brief Wait for stage processing to complete. - */ - void wait() - { - std::unique_lock lck(m_lock); - m_complete.wait(lck, [this]{ return m_done_count == m_task_count; }); - } - - /** - * @brief Trigger the pipeline stage term step. - * - * This can be called from multi-threaded code. The first thread to hit this will process the - * thread termintion. Caller must have called @c wait() prior to calling this function to ensure - * that processing is complete. - * - * @param term_func Callable which executes the stage termination. - */ - void term(std::function term_func) - { - std::lock_guard lck(m_lock); - if (!m_term_done) - { - term_func(); - m_term_done = true; - } - } -}; - /* ============================================================================ Commonly used data structures ============================================================================ */ @@ -483,17 +286,19 @@ struct partition_lines3 /** @brief Line for correlated chroma, passing though the origin. */ line3 samec_line; - /** @brief Postprocessed line for uncorrelated chroma. */ + /** @brief Post-processed line for uncorrelated chroma. */ processed_line3 uncor_pline; - /** @brief Postprocessed line for correlated chroma, passing though the origin. */ + /** @brief Post-processed line for correlated chroma, passing though the origin. */ processed_line3 samec_pline; - /** @brief The length of the line for uncorrelated chroma. */ - float uncor_line_len; - - /** @brief The length of the line for correlated chroma. */ - float samec_line_len; + /** + * @brief The length of the line for uncorrelated chroma. + * + * This is used for both the uncorrelated and same chroma lines - they are normally very similar + * and only used for the relative ranking of partitionings against one another. + */ + float line_length; }; /** @@ -515,8 +320,8 @@ struct partition_info /** * @brief The number of texels in each partition. * - * Note that some seeds result in zero texels assigned to a partition are valid, but are skipped - * by this compressor as there is no point spending bits encoding an unused color endpoint. + * Note that some seeds result in zero texels assigned to a partition. These are valid, but are + * skipped by this compressor as there is no point spending bits encoding an unused endpoints. */ uint8_t partition_texel_count[BLOCK_MAX_PARTITIONS]; @@ -530,7 +335,7 @@ struct partition_info /** * @brief The weight grid information for a single decimation pattern. * - * ASTC can store one weight per texel, but is also capable of storing lower resoution weight grids + * ASTC can store one weight per texel, but is also capable of storing lower resolution weight grids * that are interpolated during decompression to assign a with to a texel. Storing fewer weights * can free up a substantial amount of bits that we can then spend on more useful things, such as * more accurate endpoints and weights, or additional partitions. @@ -558,38 +363,50 @@ struct decimation_info /** @brief The number of stored weights in the Z dimension. */ uint8_t weight_z; - /** @brief The number of stored weights that contribute to each texel, between 1 and 4. */ + /** + * @brief The number of weights that contribute to each texel. + * Value is between 1 and 4. + */ uint8_t texel_weight_count[BLOCK_MAX_TEXELS]; - /** @brief The weight index of the N weights that need to be interpolated for each texel. */ - uint8_t texel_weights_4t[4][BLOCK_MAX_TEXELS]; + /** + * @brief The weight index of the N weights that are interpolated for each texel. + * Stored transposed to improve vectorization. + */ + uint8_t texel_weights_tr[4][BLOCK_MAX_TEXELS]; - /** @brief The bilinear interpolation weighting of the N input weights for each texel, between 0 and 16. */ - uint8_t texel_weights_int_4t[4][BLOCK_MAX_TEXELS]; + /** + * @brief The bilinear contribution of the N weights that are interpolated for each texel. + * Value is between 0 and 16, stored transposed to improve vectorization. + */ + uint8_t texel_weight_contribs_int_tr[4][BLOCK_MAX_TEXELS]; - /** @brief The bilinear interpolation weighting of the N input weights for each texel, between 0 and 1. */ - alignas(ASTCENC_VECALIGN) float texel_weights_float_4t[4][BLOCK_MAX_TEXELS]; + /** + * @brief The bilinear contribution of the N weights that are interpolated for each texel. + * Value is between 0 and 1, stored transposed to improve vectorization. + */ + ASTCENC_ALIGNAS float texel_weight_contribs_float_tr[4][BLOCK_MAX_TEXELS]; /** @brief The number of texels that each stored weight contributes to. */ uint8_t weight_texel_count[BLOCK_MAX_WEIGHTS]; - /** @brief The list of weights that contribute to each texel. */ - uint8_t weight_texel[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS]; - - /** @brief The list of weight indices that contribute to each texel. */ - alignas(ASTCENC_VECALIGN) float weights_flt[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS]; + /** + * @brief The list of texels that use a specific weight index. + * Stored transposed to improve vectorization. + */ + uint8_t weight_texels_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS]; /** - * @brief Folded structure for faster access: - * texel_weights_texel[i][j][.] = texel_weights[.][weight_texel[i][j]] + * @brief The bilinear contribution to the N texels that use each weight. + * Value is between 0 and 1, stored transposed to improve vectorization. */ - uint8_t texel_weights_texel[BLOCK_MAX_WEIGHTS][BLOCK_MAX_TEXELS][4]; + ASTCENC_ALIGNAS float weights_texel_contribs_tr[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS]; /** - * @brief Folded structure for faster access: - * texel_weights_float_texel[i][j][.] = texel_weights_float[.][weight_texel[i][j]] + * @brief The bilinear contribution to the Nth texel that uses each weight. + * Value is between 0 and 1, stored transposed to improve vectorization. */ - float texel_weights_float_texel[BLOCK_MAX_WEIGHTS][BLOCK_MAX_TEXELS][4]; + float texel_contrib_for_weight[BLOCK_MAX_TEXELS][BLOCK_MAX_WEIGHTS]; }; /** @@ -634,11 +451,61 @@ struct decimation_mode /** @brief The max weight precision for 2 planes, or -1 if not supported. */ int8_t maxprec_2planes; - /** @brief Was this actually referenced by an active 1 plane mode? */ - uint8_t ref_1_plane; + /** + * @brief Bitvector indicating weight quant modes used by active 1 plane block modes. + * + * Bit 0 = QUANT_2, Bit 1 = QUANT_3, etc. + */ + uint16_t refprec_1plane; + + /** + * @brief Bitvector indicating weight quant methods used by active 2 plane block modes. + * + * Bit 0 = QUANT_2, Bit 1 = QUANT_3, etc. + */ + uint16_t refprec_2planes; + + /** + * @brief Set a 1 plane weight quant as active. + * + * @param weight_quant The quant method to set. + */ + void set_ref_1plane(quant_method weight_quant) + { + refprec_1plane |= (1 << weight_quant); + } + + /** + * @brief Test if this mode is active below a given 1 plane weight quant (inclusive). + * + * @param max_weight_quant The max quant method to test. + */ + bool is_ref_1plane(quant_method max_weight_quant) const + { + uint16_t mask = static_cast((1 << (max_weight_quant + 1)) - 1); + return (refprec_1plane & mask) != 0; + } + + /** + * @brief Set a 2 plane weight quant as active. + * + * @param weight_quant The quant method to set. + */ + void set_ref_2plane(quant_method weight_quant) + { + refprec_2planes |= static_cast(1 << weight_quant); + } - /** @brief Was this actually referenced by an active 2 plane mode? */ - uint8_t ref_2_planes; + /** + * @brief Test if this mode is active below a given 2 plane weight quant (inclusive). + * + * @param max_weight_quant The max quant method to test. + */ + bool is_ref_2plane(quant_method max_weight_quant) const + { + uint16_t mask = static_cast((1 << (max_weight_quant + 1)) - 1); + return (refprec_2planes & mask) != 0; + } }; /** @@ -649,7 +516,7 @@ struct decimation_mode * modes will be unused (too many weights for the current block size or disabled by heuristics). The * actual number of weights stored is @c decimation_mode_count, and the @c decimation_modes and * @c decimation_tables arrays store the active modes contiguously at the start of the array. These - * entries are not stored in any particuar order. + * entries are not stored in any particular order. * * The block mode tables store the unpacked block mode settings. Block modes are stored in the * compressed block as an 11 bit field, but for any given block size and set of compressor @@ -713,7 +580,7 @@ struct block_size_descriptor decimation_mode decimation_modes[WEIGHTS_MAX_DECIMATION_MODES]; /** @brief The active decimation tables, stored in low indices. */ - alignas(ASTCENC_VECALIGN) decimation_info decimation_tables[WEIGHTS_MAX_DECIMATION_MODES]; + ASTCENC_ALIGNAS decimation_info decimation_tables[WEIGHTS_MAX_DECIMATION_MODES]; /** @brief The packed block mode array index, or @c BLOCK_BAD_BLOCK_MODE if not active. */ uint16_t block_mode_packed_index[WEIGHTS_MAX_BLOCK_MODES]; @@ -734,13 +601,6 @@ struct block_size_descriptor /** @brief The active texels for k-means partition selection. */ uint8_t kmeans_texels[BLOCK_MAX_KMEANS_TEXELS]; - /** - * @brief Is 0 if this 2-partition is valid for compression 255 otherwise. - * - * Indexed by remapped index, not physical index. - */ - uint8_t partitioning_valid_2[BLOCK_MAX_PARTITIONINGS]; - /** * @brief The canonical 2-partition coverage pattern used during block partition search. * @@ -748,13 +608,6 @@ struct block_size_descriptor */ uint64_t coverage_bitmaps_2[BLOCK_MAX_PARTITIONINGS][2]; - /** - * @brief Is 0 if this 3-partition is valid for compression 255 otherwise. - * - * Indexed by remapped index, not physical index. - */ - uint8_t partitioning_valid_3[BLOCK_MAX_PARTITIONINGS]; - /** * @brief The canonical 3-partition coverage pattern used during block partition search. * @@ -762,13 +615,6 @@ struct block_size_descriptor */ uint64_t coverage_bitmaps_3[BLOCK_MAX_PARTITIONINGS][3]; - /** - * @brief Is 0 if this 4-partition is valid for compression 255 otherwise. - * - * Indexed by remapped index, not physical index. - */ - uint8_t partitioning_valid_4[BLOCK_MAX_PARTITIONINGS]; - /** * @brief The canonical 4-partition coverage pattern used during block partition search. * @@ -894,16 +740,16 @@ struct block_size_descriptor struct image_block { /** @brief The input (compress) or output (decompress) data for the red color component. */ - alignas(ASTCENC_VECALIGN) float data_r[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float data_r[BLOCK_MAX_TEXELS]; /** @brief The input (compress) or output (decompress) data for the green color component. */ - alignas(ASTCENC_VECALIGN) float data_g[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float data_g[BLOCK_MAX_TEXELS]; /** @brief The input (compress) or output (decompress) data for the blue color component. */ - alignas(ASTCENC_VECALIGN) float data_b[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float data_b[BLOCK_MAX_TEXELS]; /** @brief The input (compress) or output (decompress) data for the alpha color component. */ - alignas(ASTCENC_VECALIGN) float data_a[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float data_a[BLOCK_MAX_TEXELS]; /** @brief The number of texels in the block. */ uint8_t texel_count; @@ -926,6 +772,9 @@ struct image_block /** @brief Is this grayscale block where R == G == B for all texels? */ bool grayscale; + /** @brief Is the eventual decode using decode_unorm8 rounding? */ + bool decode_unorm8; + /** @brief Set to 1 if a texel is using HDR RGB endpoints (decompression only). */ uint8_t rgb_lns[BLOCK_MAX_TEXELS]; @@ -1052,10 +901,10 @@ struct endpoints_and_weights endpoints ep; /** @brief The ideal weight for each texel; may be undecimated or decimated. */ - alignas(ASTCENC_VECALIGN) float weights[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float weights[BLOCK_MAX_TEXELS]; /** @brief The ideal weight error scaling for each texel; may be undecimated or decimated. */ - alignas(ASTCENC_VECALIGN) float weight_error_scale[BLOCK_MAX_TEXELS]; + ASTCENC_ALIGNAS float weight_error_scale[BLOCK_MAX_TEXELS]; }; /** @@ -1078,14 +927,14 @@ struct encoding_choice_errors /** @brief Can we use delta offset encoding? */ bool can_offset_encode; - /** @brief CAn we use blue contraction encoding? */ + /** @brief Can we use blue contraction encoding? */ bool can_blue_contract; }; /** * @brief Preallocated working buffers, allocated per thread during context creation. */ -struct alignas(ASTCENC_VECALIGN) compression_working_buffers +struct ASTCENC_ALIGNAS compression_working_buffers { /** @brief Ideal endpoints and weights for plane 1. */ endpoints_and_weights ei1; @@ -1093,47 +942,37 @@ struct alignas(ASTCENC_VECALIGN) compression_working_buffers /** @brief Ideal endpoints and weights for plane 2. */ endpoints_and_weights ei2; - /** @brief Ideal decimated endpoints and weights for plane 1. */ - endpoints_and_weights eix1[WEIGHTS_MAX_DECIMATION_MODES]; - - /** @brief Ideal decimated endpoints and weights for plane 2. */ - endpoints_and_weights eix2[WEIGHTS_MAX_DECIMATION_MODES]; - /** - * @brief Decimated ideal weight values. + * @brief Decimated ideal weight values in the ~0-1 range. * - * For two plane encodings, second plane weights start at @c WEIGHTS_PLANE2_OFFSET offsets. - */ - alignas(ASTCENC_VECALIGN) float dec_weights_ideal_value[WEIGHTS_MAX_DECIMATION_MODES * BLOCK_MAX_WEIGHTS]; - - /** - * @brief Decimated and quantized weight values stored in the unpacked quantized weight range. + * Note that values can be slightly below zero or higher than one due to + * endpoint extents being inside the ideal color representation. * - * For two plane encodings, second plane weights start at @c WEIGHTS_PLANE2_OFFSET offsets. + * For two planes, second plane starts at @c WEIGHTS_PLANE2_OFFSET offsets. */ - alignas(ASTCENC_VECALIGN) float dec_weights_quant_uvalue[WEIGHTS_MAX_BLOCK_MODES * BLOCK_MAX_WEIGHTS]; + ASTCENC_ALIGNAS float dec_weights_ideal[WEIGHTS_MAX_DECIMATION_MODES * BLOCK_MAX_WEIGHTS]; /** - * @brief Decimated and quantized weight values stored in the packed quantized weight range. + * @brief Decimated quantized weight values in the unquantized 0-64 range. * - * For two plane encodings, second plane weights start at @c WEIGHTS_PLANE2_OFFSET offsets. + * For two planes, second plane starts at @c WEIGHTS_PLANE2_OFFSET offsets. */ - alignas(ASTCENC_VECALIGN) uint8_t dec_weights_quant_pvalue[WEIGHTS_MAX_BLOCK_MODES * BLOCK_MAX_WEIGHTS]; + uint8_t dec_weights_uquant[WEIGHTS_MAX_BLOCK_MODES * BLOCK_MAX_WEIGHTS]; /** @brief Error of the best encoding combination for each block mode. */ - alignas(ASTCENC_VECALIGN) float errors_of_best_combination[WEIGHTS_MAX_BLOCK_MODES]; + ASTCENC_ALIGNAS float errors_of_best_combination[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The best color quant for each block mode. */ - alignas(ASTCENC_VECALIGN) quant_method best_quant_levels[WEIGHTS_MAX_BLOCK_MODES]; + uint8_t best_quant_levels[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The best color quant for each block mode if modes are the same and we have spare bits. */ - quant_method best_quant_levels_mod[WEIGHTS_MAX_BLOCK_MODES]; + uint8_t best_quant_levels_mod[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The best endpoint format for each partition. */ - int best_ep_formats[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS]; + uint8_t best_ep_formats[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS]; /** @brief The total bit storage needed for quantized weights for each block mode. */ - int qwt_bitcounts[WEIGHTS_MAX_BLOCK_MODES]; + int8_t qwt_bitcounts[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The cumulative error for quantized weights for each block mode. */ float qwt_errors[WEIGHTS_MAX_BLOCK_MODES]; @@ -1145,10 +984,10 @@ struct alignas(ASTCENC_VECALIGN) compression_working_buffers float weight_high_value1[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The low weight value in plane 1 for each quant level and decimation mode. */ - float weight_low_values1[WEIGHTS_MAX_DECIMATION_MODES][12]; + float weight_low_values1[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1]; /** @brief The high weight value in plane 1 for each quant level and decimation mode. */ - float weight_high_values1[WEIGHTS_MAX_DECIMATION_MODES][12]; + float weight_high_values1[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1]; /** @brief The low weight value in plane 2 for each block mode. */ float weight_low_value2[WEIGHTS_MAX_BLOCK_MODES]; @@ -1157,10 +996,10 @@ struct alignas(ASTCENC_VECALIGN) compression_working_buffers float weight_high_value2[WEIGHTS_MAX_BLOCK_MODES]; /** @brief The low weight value in plane 2 for each quant level and decimation mode. */ - float weight_low_values2[WEIGHTS_MAX_DECIMATION_MODES][12]; + float weight_low_values2[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1]; /** @brief The high weight value in plane 2 for each quant level and decimation mode. */ - float weight_high_values2[WEIGHTS_MAX_DECIMATION_MODES][12]; + float weight_high_values2[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1]; }; struct dt_init_working_buffers @@ -1185,33 +1024,27 @@ struct dt_init_working_buffers * floating-point weight. For each quantized weight, the corresponding unquantized values. For each * quantized weight, a previous-value and a next-value. */ -struct quantization_and_transfer_table +struct quant_and_transfer_table { - /** @brief The quantization level used */ - quant_method method; - /** @brief The unscrambled unquantized value. */ - float unquantized_value_unsc[33]; + uint8_t quant_to_unquant[32]; - /** @brief The scrambling order: value[map[i]] == value_unsc[i] */ - int32_t scramble_map[32]; + /** @brief The scrambling order: scrambled_quant = map[unscrambled_quant]. */ + uint8_t scramble_map[32]; - /** @brief The scrambled unquantized values. */ - uint8_t unquantized_value[32]; + /** @brief The unscrambling order: unscrambled_unquant = map[scrambled_quant]. */ + uint8_t unscramble_and_unquant_map[32]; /** * @brief A table of previous-and-next weights, indexed by the current unquantized value. * * bits 7:0 = previous-index, unquantized * * bits 15:8 = next-index, unquantized - * * bits 23:16 = previous-index, quantized - * * bits 31:24 = next-index, quantized */ - uint32_t prev_next_values[65]; + uint16_t prev_next_values[65]; }; - /** @brief The precomputed quant and transfer table. */ -extern const quantization_and_transfer_table quant_and_xfer_tables[12]; +extern const quant_and_transfer_table quant_and_xfer_tables[12]; /** @brief The block is an error block, and will return error color or NaN. */ static constexpr uint8_t SYM_BTYPE_ERROR { 0 }; @@ -1229,7 +1062,7 @@ static constexpr uint8_t SYM_BTYPE_NONCONST { 3 }; * @brief A symbolic representation of a compressed block. * * The symbolic representation stores the unpacked content of a single - * @c physical_compressed_block, in a form which is much easier to access for + * physical compressed block, in a form which is much easier to access for * the rest of the compressor code. */ struct symbolic_compressed_block @@ -1244,7 +1077,6 @@ struct symbolic_compressed_block uint8_t color_formats_matched; /** @brief The plane 2 color component, or -1 if single plane; valid for @c NONCONST blocks. */ - // Try unsigned sentintel to avoid signext on load int8_t plane2_component; /** @brief The block mode; valid for @c NONCONST blocks. */ @@ -1272,6 +1104,10 @@ struct symbolic_compressed_block }; /** @brief The quantized and decimated weights. + * + * Weights are stored in the 0-64 unpacked range allowing them to be used + * directly in encoding passes without per-use unpacking. Packing happens + * when converting to/from the physical bitstream encoding. * * If dual plane, the second plane starts at @c weights[WEIGHTS_PLANE2_OFFSET]. */ @@ -1289,18 +1125,6 @@ struct symbolic_compressed_block QualityProfile privateProfile; }; -/** - * @brief A physical representation of a compressed block. - * - * The physical representation stores the raw bytes of the format in memory. - */ -struct physical_compressed_block -{ - /** @brief The ASTC encoded data for a single block. */ - uint8_t data[16]; -}; - - /** * @brief Parameter structure for @c compute_pixel_region_variance(). * @@ -1351,7 +1175,6 @@ struct avg_args /** @brief The arguments for the nested variance computation. */ pixel_region_args arg; - // The above has a reference to the image altread? /** @brief The image Stride dimensions. */ unsigned int img_size_stride; @@ -1382,7 +1205,7 @@ class TraceLog; /** * @brief The astcenc compression context. */ -struct astcenc_context +struct astcenc_contexti { /** @brief The configuration this context was created with. */ astcenc_config config; @@ -1400,7 +1223,7 @@ struct astcenc_context */ /** @brief The input image alpha channel averages table, may be @c nullptr if not needed. */ - float *input_alpha_averages; + float* input_alpha_averages; /** @brief The scratch working buffers, one per thread (see @c thread_count). */ compression_working_buffers* working_buffers; @@ -1408,17 +1231,8 @@ struct astcenc_context #if !defined(ASTCENC_DECOMPRESS_ONLY) /** @brief The pixel region and variance worker arguments. */ avg_args avg_preprocess_args; - - /** @brief The parallel manager for averages computation. */ - ParallelManager manage_avg; - - /** @brief The parallel manager for compression. */ - ParallelManager manage_compress; #endif - /** @brief The parallel manager for decompression. */ - ParallelManager manage_decompress; - #if defined(ASTCENC_DIAGNOSTICS) /** * @brief The diagnostic trace logger. @@ -1486,7 +1300,7 @@ void init_partition_tables( * * @return The unpacked table. */ -const float *get_2d_percentile_table( +const float* get_2d_percentile_table( unsigned int xdim, unsigned int ydim); @@ -1516,25 +1330,42 @@ bool is_legal_3d_block_size( /** * @brief The precomputed table for quantizing color values. * - * Returned value is in the ASTC BISE scrambled order. + * Converts unquant value in 0-255 range into quant value in 0-255 range. + * No BISE scrambling is applied at this stage. + * + * The BISE encoding results in ties where available quant<256> values are + * equidistant the available quant values. This table stores two values + * for each input - one for use with a negative residual, and one for use with + * a positive residual. + * + * Indexed by [quant_mode - 4][data_value * 2 + residual]. + */ +extern const uint8_t color_unquant_to_uquant_tables[17][512]; + +/** + * @brief The precomputed table for packing quantized color values. + * + * Converts quant value in 0-255 range into packed quant value in 0-N range, + * with BISE scrambling applied. * * Indexed by [quant_mode - 4][data_value]. */ -extern const uint8_t color_quant_tables[17][256]; +extern const uint8_t color_uquant_to_scrambled_pquant_tables[17][256]; /** - * @brief The precomputed table for unquantizing color values. + * @brief The precomputed table for unpacking color values. * - * Returned value is in the ASTC BISE scrambled order. + * Converts quant value in 0-N range into unpacked value in 0-255 range, + * with BISE unscrambling applied. * * Indexed by [quant_mode - 4][data_value]. */ -extern const uint8_t color_unquant_tables[17][256]; +extern const uint8_t* color_scrambled_pquant_to_uquant_tables[17]; /** * @brief The precomputed quant mode storage table. * - * Indexing by [integercount/2][bits] gives us the quantization level for a given integer count and + * Indexing by [integer_count/2][bits] gives us the quantization level for a given integer count and * number of compressed storage bits. Returns -1 for cases where the requested integer count cannot * ever fit in the supplied storage size. */ @@ -1546,11 +1377,11 @@ extern const int8_t quant_mode_table[10][128]; * Note that BISE can return strings that are not a whole number of bytes in length, and ASTC can * start storing strings in a block at arbitrary bit offsets in the encoded data. * - * @param quant_level The BISE alphabet size. - * @param character_count The number of characters in the string. - * @param input_data The unpacked string, one byte per character. - * @param[in,out] output_data The output packed string. - * @param bit_offset The starting offset in the output storage. + * @param quant_level The BISE alphabet size. + * @param character_count The number of characters in the string. + * @param input_data The unpacked string, one byte per character. + * @param[in,out] output_data The output packed string. + * @param bit_offset The starting offset in the output storage. */ void encode_ise( quant_method quant_level, @@ -1565,11 +1396,11 @@ void encode_ise( * Note that BISE input strings are not a whole number of bytes in length, and ASTC can start * strings at arbitrary bit offsets in the encoded data. * - * @param quant_level The BISE alphabet size. - * @param character_count The number of characters in the string. - * @param input_data The packed string. - * @param[in,out] output_data The output storage, one byte per character. - * @param bit_offset The starting offset in the output storage. + * @param quant_level The BISE alphabet size. + * @param character_count The number of characters in the string. + * @param input_data The packed string. + * @param[in,out] output_data The output storage, one byte per character. + * @param bit_offset The starting offset in the output storage. */ void decode_ise( quant_method quant_level, @@ -1637,11 +1468,11 @@ void compute_avgs_and_dirs_3_comp( * This is a specialization of @c compute_avgs_and_dirs_3_comp where the omitted component is * always alpha, a common case during partition search. * - * @param pi The partition info for the current trial. - * @param blk The image block color data to be compressed. - * @param[out] pm The output partition metrics. - * - Only pi.partition_count array entries actually get initialized. - * - Direction vectors @c pm.dir are not normalized. + * @param pi The partition info for the current trial. + * @param blk The image block color data to be compressed. + * @param[out] pm The output partition metrics. + * - Only pi.partition_count array entries actually get initialized. + * - Direction vectors @c pm.dir are not normalized. */ void compute_avgs_and_dirs_3_comp_rgb( const partition_info& pi, @@ -1672,11 +1503,11 @@ void compute_avgs_and_dirs_4_comp( * * This function computes the squared error when using these two representations. * - * @param pi The partition info for the current trial. - * @param blk The image block color data to be compressed. - * @param[in,out] plines Processed line inputs, and line length outputs. - * @param[out] uncor_error The cumulative error for using the uncorrelated line. - * @param[out] samec_error The cumulative error for using the same chroma line. + * @param pi The partition info for the current trial. + * @param blk The image block color data to be compressed. + * @param[in,out] plines Processed line inputs, and line length outputs. + * @param[out] uncor_error The cumulative error for using the uncorrelated line. + * @param[out] samec_error The cumulative error for using the same chroma line. */ void compute_error_squared_rgb( const partition_info& pi, @@ -1699,8 +1530,7 @@ void compute_error_squared_rgb( * @param blk The image block color data to be compressed. * @param uncor_plines Processed uncorrelated partition lines for each partition. * @param samec_plines Processed same chroma partition lines for each partition. - * @param[out] uncor_lengths The length of each components deviation from the line. - * @param[out] samec_lengths The length of each components deviation from the line. + * @param[out] line_lengths The length of each components deviation from the line. * @param[out] uncor_error The cumulative error for using the uncorrelated line. * @param[out] samec_error The cumulative error for using the same chroma line. */ @@ -1709,8 +1539,7 @@ void compute_error_squared_rgba( const image_block& blk, const processed_line4 uncor_plines[BLOCK_MAX_PARTITIONS], const processed_line4 samec_plines[BLOCK_MAX_PARTITIONS], - float uncor_lengths[BLOCK_MAX_PARTITIONS], - float samec_lengths[BLOCK_MAX_PARTITIONS], + float line_lengths[BLOCK_MAX_PARTITIONS], float& uncor_error, float& samec_error); @@ -1719,25 +1548,57 @@ void compute_error_squared_rgba( * * On return the @c best_partitions list will contain the two best partition * candidates; one assuming data has uncorrelated chroma and one assuming the - * data has corelated chroma. The best candidate is returned first in the list. + * data has correlated chroma. The best candidate is returned first in the list. + * + * @param bsd The block size information. + * @param blk The image block color data to compress. + * @param partition_count The number of partitions in the block. + * @param partition_search_limit The number of candidate partition encodings to trial. + * @param[out] best_partitions The best partition candidates. + * @param requested_candidates The number of requested partitionings. May return fewer if + * candidates are not available. * - * @param bsd The block size information. - * @param blk The image block color data to compress. - * @param partition_count The number of partitions in the block. - * @param partition_search_limit The number of candidate partition encodings to trial. - * @param[out] best_partitions The best partition candidates. + * @return The actual number of candidates returned. */ -void find_best_partition_candidates( +unsigned int find_best_partition_candidates( const block_size_descriptor& bsd, const image_block& blk, unsigned int partition_count, unsigned int partition_search_limit, - unsigned int best_partitions[2]); + unsigned int best_partitions[TUNE_MAX_PARTITIONING_CANDIDATES], + unsigned int requested_candidates); /* ============================================================================ Functionality for managing images and image related data. ============================================================================ */ +/** + * @brief Get a vector mask indicating lanes decompressing into a UNORM8 value. + * + * @param decode_mode The color profile for LDR_SRGB settings. + * @param blk The image block for output image bitness settings. + * + * @return The component mask vector. + */ +static inline vmask4 get_u8_component_mask( + astcenc_profile decode_mode, + const image_block& blk +) { + vmask4 u8_mask(false); + // Decode mode writing to a unorm8 output value + if (blk.decode_unorm8) + { + u8_mask = vmask4(true); + } + // SRGB writing to a unorm8 RGB value + else if (decode_mode == ASTCENC_PRF_LDR_SRGB) + { + u8_mask = vmask4(true, true, true, false); + } + + return u8_mask; +} + /** * @brief Setup computation of regional averages in an image. * @@ -1746,10 +1607,10 @@ void find_best_partition_candidates( * * Results are written back into @c img->input_alpha_averages. * - * @param img The input image data, also holds output data. - * @param alpha_kernel_radius The kernel radius (in pixels) for alpha mods. - * @param swz Input data component swizzle. - * @param[out] ag The average variance arguments to init. + * @param img The input image data, also holds output data. + * @param alpha_kernel_radius The kernel radius (in pixels) for alpha mods. + * @param swz Input data component swizzle. + * @param[out] ag The average variance arguments to init. * * @return The number of tasks in the processing stage. */ @@ -1760,22 +1621,19 @@ unsigned int init_compute_averages( avg_args& ag); /** - * @brief Compute regional averages in an image. + * @brief Compute averages for a pixel region. * - * This function can be called by multiple threads, but only after a single - * thread calls the setup function @c init_compute_averages(). + * The routine computes both in a single pass, using a summed-area table to decouple the running + * time from the averaging/variance kernel size. * - * Results are written back into @c img->input_alpha_averages. - * - * @param[out] ctx The context. - * @param ag The average and variance arguments created during setup. + * @param[out] ctx The compressor context storing the output data. + * @param arg The input parameter structure. */ -void compute_averages( - astcenc_context& ctx, - const avg_args& ag); - +void compute_pixel_region_variance( + astcenc_contexti& ctx, + const pixel_region_args& arg); /** - * @brief Fetch a single image block from the input image. + * @brief Load a single image block from the input image. * * @param decode_mode The compression color profile. * @param img The input image data. @@ -1786,7 +1644,7 @@ void compute_averages( * @param zpos The block Z coordinate in the input image. * @param swz The swizzle to apply on load. */ -void fetch_image_block( +void load_image_block( astcenc_profile decode_mode, const astcenc_image& img, image_block& blk, @@ -1797,7 +1655,7 @@ void fetch_image_block( const astcenc_swizzle& swz); /** - * @brief Fetch a single image block from the input image. + * @brief Load a single image block from the input image. * * This specialized variant can be used only if the block is 2D LDR U8 data, * with no swizzle. @@ -1811,7 +1669,7 @@ void fetch_image_block( * @param zpos The block Z coordinate in the input image. * @param swz The swizzle to apply on load. */ -void fetch_image_block_fast_ldr( +void load_image_block_fast_ldr( astcenc_profile decode_mode, const astcenc_image& img, image_block& blk, @@ -1822,17 +1680,17 @@ void fetch_image_block_fast_ldr( const astcenc_swizzle& swz); /** - * @brief Write a single image block from the output image. + * @brief Store a single image block to the output image. * - * @param[out] img The input image data. - * @param blk The image block to populate. - * @param bsd The block size information. - * @param xpos The block X coordinate in the input image. - * @param ypos The block Y coordinate in the input image. - * @param zpos The block Z coordinate in the input image. - * @param swz The swizzle to apply on store. + * @param[out] img The output image data. + * @param blk The image block to export. + * @param bsd The block size information. + * @param xpos The block X coordinate in the input image. + * @param ypos The block Y coordinate in the input image. + * @param zpos The block Z coordinate in the input image. + * @param swz The swizzle to apply on store. */ -void write_image_block( +void store_image_block( astcenc_image& img, const image_block& blk, const block_size_descriptor& bsd, @@ -1892,14 +1750,12 @@ void compute_ideal_colors_and_weights_2planes( * Then, set step size to and attempt one step towards the original ideal * weight if it helps to reduce error. * - * @param eai_in The non-decimated endpoints and weights. - * @param eai_out A copy of eai_in we can modify later for refinement. + * @param ei The non-decimated endpoints and weights. * @param di The selected weight decimation. * @param[out] dec_weight_ideal_value The ideal values for the decimated weight set. */ void compute_ideal_weights_for_decimation( - const endpoints_and_weights& eai_in, - endpoints_and_weights& eai_out, + const endpoints_and_weights& ei, const decimation_info& di, float* dec_weight_ideal_value); @@ -1914,7 +1770,7 @@ void compute_ideal_weights_for_decimation( * @param high_bound The highest weight allowed. * @param dec_weight_ideal_value The ideal weight set. * @param[out] dec_weight_quant_uvalue The output quantized weight as a float. - * @param[out] dec_weight_quant_pvalue The output quantized weight as encoded int. + * @param[out] dec_weight_uquant The output quantized weight as encoded int. * @param quant_level The desired weight quant level. */ void compute_quantized_weights_for_decimation( @@ -1923,121 +1779,9 @@ void compute_quantized_weights_for_decimation( float high_bound, const float* dec_weight_ideal_value, float* dec_weight_quant_uvalue, - uint8_t* dec_weight_quant_pvalue, + uint8_t* dec_weight_uquant, quant_method quant_level); -/** - * @brief Compute the infilled weight for a texel index in a decimated grid. - * - * @param di The weight grid decimation to use. - * @param weights The decimated weight values to use. - * @param index The texel index to interpolate. - * - * @return The interpolated weight for the given texel. - */ -static inline float bilinear_infill( - const decimation_info& di, - const float* weights, - unsigned int index -) { - return (weights[di.texel_weights_4t[0][index]] * di.texel_weights_float_4t[0][index] + - weights[di.texel_weights_4t[1][index]] * di.texel_weights_float_4t[1][index]) + - (weights[di.texel_weights_4t[2][index]] * di.texel_weights_float_4t[2][index] + - weights[di.texel_weights_4t[3][index]] * di.texel_weights_float_4t[3][index]); -} - -/** - * @brief Compute the infilled weight for a texel index in a decimated grid. - * - * This is specialized version which computes only two weights per texel for - * encodings that are only decimated in a single axis. - * - * @param di The weight grid decimation to use. - * @param weights The decimated weight values to use. - * @param index The texel index to interpolate. - * - * @return The interpolated weight for the given texel. - */ -static inline float bilinear_infill_2( - const decimation_info& di, - const float* weights, - unsigned int index -) { - return (weights[di.texel_weights_4t[0][index]] * di.texel_weights_float_4t[0][index] + - weights[di.texel_weights_4t[1][index]] * di.texel_weights_float_4t[1][index]); -} - - -/** - * @brief Compute the infilled weight for N texel indices in a decimated grid. - * - * @param di The weight grid decimation to use. - * @param weights The decimated weight values to use. - * @param index The first texel index to interpolate. - * - * @return The interpolated weight for the given set of SIMD_WIDTH texels. - */ -static inline vfloat bilinear_infill_vla( - const decimation_info& di, - const float* weights, - unsigned int index -) { - // Load the bilinear filter texel weight indexes in the decimated grid - vint weight_idx0 = vint(di.texel_weights_4t[0] + index); - vint weight_idx1 = vint(di.texel_weights_4t[1] + index); - vint weight_idx2 = vint(di.texel_weights_4t[2] + index); - vint weight_idx3 = vint(di.texel_weights_4t[3] + index); - - // Load the bilinear filter weights from the decimated grid - vfloat weight_val0 = gatherf(weights, weight_idx0); - vfloat weight_val1 = gatherf(weights, weight_idx1); - vfloat weight_val2 = gatherf(weights, weight_idx2); - vfloat weight_val3 = gatherf(weights, weight_idx3); - - // Load the weight contribution factors for each decimated weight - vfloat tex_weight_float0 = loada(di.texel_weights_float_4t[0] + index); - vfloat tex_weight_float1 = loada(di.texel_weights_float_4t[1] + index); - vfloat tex_weight_float2 = loada(di.texel_weights_float_4t[2] + index); - vfloat tex_weight_float3 = loada(di.texel_weights_float_4t[3] + index); - - // Compute the bilinear interpolation to generate the per-texel weight - return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1) + - (weight_val2 * tex_weight_float2 + weight_val3 * tex_weight_float3); -} - -/** - * @brief Compute the infilled weight for N texel indices in a decimated grid. - * - * This is specialized version which computes only two weights per texel for - * encodings that are only decimated in a single axis. - * - * @param di The weight grid decimation to use. - * @param weights The decimated weight values to use. - * @param index The first texel index to interpolate. - * - * @return The interpolated weight for the given set of SIMD_WIDTH texels. - */ -static inline vfloat bilinear_infill_vla_2( - const decimation_info& di, - const float* weights, - unsigned int index -) { - // Load the bilinear filter texel weight indexes in the decimated grid - vint weight_idx0 = vint(di.texel_weights_4t[0] + index); - vint weight_idx1 = vint(di.texel_weights_4t[1] + index); - - // Load the bilinear filter weights from the decimated grid - vfloat weight_val0 = gatherf(weights, weight_idx0); - vfloat weight_val1 = gatherf(weights, weight_idx1); - - // Load the weight contribution factors for each decimated weight - vfloat tex_weight_float0 = loada(di.texel_weights_float_4t[0] + index); - vfloat tex_weight_float1 = loada(di.texel_weights_float_4t[1] + index); - - // Compute the bilinear interpolation to generate the per-texel weight - return (weight_val0 * tex_weight_float0 + weight_val1 * tex_weight_float1); -} - /** * @brief Compute the error of a decimated weight set for 1 plane. * @@ -2084,13 +1828,13 @@ float compute_error_of_weight_set_2planes( * The user requests a base color endpoint mode in @c format, but the quantizer may choose a * delta-based representation. It will report back the format variant it actually used. * - * @param color0 The input unquantized color0 endpoint for absolute endpoint pairs. - * @param color1 The input unquantized color1 endpoint for absolute endpoint pairs. - * @param rgbs_color The input unquantized RGBS variant endpoint for same chroma endpoints. - * @param rgbo_color The input unquantized RGBS variant endpoint for HDR endpoints.. - * @param format The desired base format. - * @param[out] output The output storage for the quantized colors/ - * @param quant_level The quantization level requested. + * @param color0 The input unquantized color0 endpoint for absolute endpoint pairs. + * @param color1 The input unquantized color1 endpoint for absolute endpoint pairs. + * @param rgbs_color The input unquantized RGBS variant endpoint for same chroma endpoints. + * @param rgbo_color The input unquantized RGBS variant endpoint for HDR endpoints. + * @param format The desired base format. + * @param[out] output The output storage for the quantized colors/ + * @param quant_level The quantization level requested. * * @return The actual endpoint mode used. */ @@ -2105,11 +1849,12 @@ uint8_t pack_color_endpoints( quant_method quant_level); /** - * @brief Unpack a single pair of encoded and quantized color endpoints. + * @brief Unpack a single pair of encoded endpoints. + * + * Endpoints must be unscrambled and converted into the 0-255 range before calling this functions. * - * @param decode_mode The decode mode (LDR, HDR). + * @param decode_mode The decode mode (LDR, HDR, etc). * @param format The color endpoint mode used. - * @param quant_level The quantization level used. * @param input The raw array of encoded input integers. The length of this array * depends on @c format; it can be safely assumed to be large enough. * @param[out] rgb_hdr Is the endpoint using HDR for the RGB channels? @@ -2120,21 +1865,50 @@ uint8_t pack_color_endpoints( void unpack_color_endpoints( astcenc_profile decode_mode, int format, - quant_method quant_level, const uint8_t* input, bool& rgb_hdr, bool& alpha_hdr, vint4& output0, vint4& output1); +/** + * @brief Unpack an LDR RGBA color that uses delta encoding. + * + * @param input0 The packed endpoint 0 color. + * @param input1 The packed endpoint 1 color deltas. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. + */ +void rgba_delta_unpack( + vint4 input0, + vint4 input1, + vint4& output0, + vint4& output1); + +/** + * @brief Unpack an LDR RGBA color that uses direct encoding. + * + * @param input0 The packed endpoint 0 color. + * @param input1 The packed endpoint 1 color. + * @param[out] output0 The unpacked endpoint 0 color. + * @param[out] output1 The unpacked endpoint 1 color. + */ +void rgba_unpack( + vint4 input0, + vint4 input1, + vint4& output0, + vint4& output1); + /** * @brief Unpack a set of quantized and decimated weights. * + * TODO: Can we skip this for non-decimated weights now that the @c scb is + * already storing unquantized weights? + * * @param bsd The block size information. * @param scb The symbolic compressed encoding. * @param di The weight grid decimation table. * @param is_dual_plane @c true if this is a dual plane block, @c false otherwise. - * @param quant_level The weight quantization level. * @param[out] weights_plane1 The output array for storing the plane 1 weights. * @param[out] weights_plane2 The output array for storing the plane 2 weights. */ @@ -2143,7 +1917,6 @@ void unpack_weights( const symbolic_compressed_block& scb, const decimation_info& di, bool is_dual_plane, - quant_method quant_level, int weights_plane1[BLOCK_MAX_TEXELS], int weights_plane2[BLOCK_MAX_TEXELS]); @@ -2175,12 +1948,12 @@ unsigned int compute_ideal_endpoint_formats( const partition_info& pi, const image_block& blk, const endpoints& ep, - const int* qwt_bitcounts, + const int8_t* qwt_bitcounts, const float* qwt_errors, unsigned int tune_candidate_limit, unsigned int start_block_mode, unsigned int end_block_mode, - int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS], + uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS], int block_mode[TUNE_MAX_TRIAL_CANDIDATES], quant_method quant_level[TUNE_MAX_TRIAL_CANDIDATES], quant_method quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES], @@ -2192,21 +1965,19 @@ unsigned int compute_ideal_endpoint_formats( * As we quantize and decimate weights the optimal endpoint colors may change slightly, so we must * recompute the ideal colors for a specific weight set. * - * @param blk The image block color data to compress. - * @param pi The partition info for the current trial. - * @param di The weight grid decimation table. - * @param weight_quant_mode The weight grid quantization level. - * @param dec_weights_quant_pvalue The quantized weight set. - * @param[in,out] ep The color endpoints (modifed in place). - * @param[out] rgbs_vectors The RGB+scale vectors for LDR blocks. - * @param[out] rgbo_vectors The RGB+offset vectors for HDR blocks. + * @param blk The image block color data to compress. + * @param pi The partition info for the current trial. + * @param di The weight grid decimation table. + * @param dec_weights_uquant The quantized weight set. + * @param[in,out] ep The color endpoints (modifed in place). + * @param[out] rgbs_vectors The RGB+scale vectors for LDR blocks. + * @param[out] rgbo_vectors The RGB+offset vectors for HDR blocks. */ void recompute_ideal_colors_1plane( const image_block& blk, const partition_info& pi, const decimation_info& di, - int weight_quant_mode, - const uint8_t* dec_weights_quant_pvalue, + const uint8_t* dec_weights_uquant, endpoints& ep, vfloat4 rgbs_vectors[BLOCK_MAX_PARTITIONS], vfloat4 rgbo_vectors[BLOCK_MAX_PARTITIONS]); @@ -2217,24 +1988,22 @@ void recompute_ideal_colors_1plane( * As we quantize and decimate weights the optimal endpoint colors may change slightly, so we must * recompute the ideal colors for a specific weight set. * - * @param blk The image block color data to compress. - * @param bsd The block_size descriptor. - * @param di The weight grid decimation table. - * @param weight_quant_mode The weight grid quantization level. - * @param dec_weights_quant_pvalue_plane1 The quantized weight set for plane 1. - * @param dec_weights_quant_pvalue_plane2 The quantized weight set for plane 2. - * @param[in,out] ep The color endpoints (modifed in place). - * @param[out] rgbs_vector The RGB+scale color for LDR blocks. - * @param[out] rgbo_vector The RGB+offset color for HDR blocks. - * @param plane2_component The component assigned to plane 2. + * @param blk The image block color data to compress. + * @param bsd The block_size descriptor. + * @param di The weight grid decimation table. + * @param dec_weights_uquant_plane1 The quantized weight set for plane 1. + * @param dec_weights_uquant_plane2 The quantized weight set for plane 2. + * @param[in,out] ep The color endpoints (modifed in place). + * @param[out] rgbs_vector The RGB+scale color for LDR blocks. + * @param[out] rgbo_vector The RGB+offset color for HDR blocks. + * @param plane2_component The component assigned to plane 2. */ void recompute_ideal_colors_2planes( const image_block& blk, const block_size_descriptor& bsd, const decimation_info& di, - int weight_quant_mode, - const uint8_t* dec_weights_quant_pvalue_plane1, - const uint8_t* dec_weights_quant_pvalue_plane2, + const uint8_t* dec_weights_uquant_plane1, + const uint8_t* dec_weights_uquant_plane2, endpoints& ep, vfloat4& rgbs_vector, vfloat4& rgbo_vector, @@ -2248,31 +2017,31 @@ void prepare_angular_tables(); /** * @brief Compute the angular endpoints for one plane for each block mode. * - * @param tune_low_weight_limit Weight count cutoff below which we use simpler searches. - * @param only_always Only consider block modes that are always enabled. - * @param bsd The block size descriptor for the current trial. - * @param dec_weight_ideal_value The ideal decimated unquantized weight values. - * @param[out] tmpbuf Preallocated scratch buffers for the compressor. + * @param only_always Only consider block modes that are always enabled. + * @param bsd The block size descriptor for the current trial. + * @param dec_weight_ideal_value The ideal decimated unquantized weight values. + * @param max_weight_quant The maximum block mode weight quantization allowed. + * @param[out] tmpbuf Preallocated scratch buffers for the compressor. */ void compute_angular_endpoints_1plane( - unsigned int tune_low_weight_limit, bool only_always, const block_size_descriptor& bsd, const float* dec_weight_ideal_value, + unsigned int max_weight_quant, compression_working_buffers& tmpbuf); /** * @brief Compute the angular endpoints for two planes for each block mode. * - * @param tune_low_weight_limit Weight count cutoff below which we use simpler searches. - * @param bsd The block size descriptor for the current trial. - * @param dec_weight_ideal_value The ideal decimated unquantized weight values. - * @param[out] tmpbuf Preallocated scratch buffers for the compressor. + * @param bsd The block size descriptor for the current trial. + * @param dec_weight_ideal_value The ideal decimated unquantized weight values. + * @param max_weight_quant The maximum block mode weight quantization allowed. + * @param[out] tmpbuf Preallocated scratch buffers for the compressor. */ void compute_angular_endpoints_2planes( - unsigned int tune_low_weight_limit, const block_size_descriptor& bsd, const float* dec_weight_ideal_value, + unsigned int max_weight_quant, compression_working_buffers& tmpbuf); /* ============================================================================ @@ -2288,9 +2057,9 @@ void compute_angular_endpoints_2planes( * @param[out] tmpbuf Preallocated scratch buffers for the compressor. */ void compress_block( - const astcenc_context& ctx, + const astcenc_contexti& ctx, const image_block& blk, - physical_compressed_block& pcb, + uint8_t pcb[16], #if QUALITY_CONTROL compression_working_buffers& tmpbuf, bool calQualityEnable, @@ -2390,12 +2159,12 @@ float compute_symbolic_block_difference_1plane_1partition( * * @param bsd The block size information. * @param scb The symbolic representation. - * @param[out] pcb The binary encoded data. + * @param[out] pcb The physical compressed block output. */ void symbolic_to_physical( const block_size_descriptor& bsd, const symbolic_compressed_block& scb, - physical_compressed_block& pcb); + uint8_t pcb[16]); /** * @brief Convert a binary physical encoding into a symbolic representation. @@ -2404,52 +2173,25 @@ void symbolic_to_physical( * flagged as an error block if the encoding is invalid. * * @param bsd The block size information. - * @param pcb The binary encoded data. + * @param pcb The physical compresesd block input. * @param[out] scb The output symbolic representation. */ void physical_to_symbolic( const block_size_descriptor& bsd, - const physical_compressed_block& pcb, + const uint8_t pcb[16], symbolic_compressed_block& scb); /* ============================================================================ Platform-specific functions. ============================================================================ */ -/** - * @brief Run-time detection if the host CPU supports the POPCNT extension. - * - * @return @c true if supported, @c false if not. - */ -bool cpu_supports_popcnt(); - -/** - * @brief Run-time detection if the host CPU supports F16C extension. - * - * @return @c true if supported, @c false if not. - */ -bool cpu_supports_f16c(); - -/** - * @brief Run-time detection if the host CPU supports SSE 4.1 extension. - * - * @return @c true if supported, @c false if not. - */ -bool cpu_supports_sse41(); - -/** - * @brief Run-time detection if the host CPU supports AVX 2 extension. - * - * @return @c true if supported, @c false if not. - */ -bool cpu_supports_avx2(); - /** * @brief Allocate an aligned memory buffer. * - * Allocated memory must be freed by aligned_free; + * Allocated memory must be freed by aligned_free. * * @param size The desired buffer size. - * @param align The desired buffer alignment; must be 2^N. + * @param align The desired buffer alignment; must be 2^N, may be increased + * by the implementation to a minimum allowable alignment. * * @return The memory buffer pointer or nullptr on allocation failure. */ @@ -2459,10 +2201,14 @@ T* aligned_malloc(size_t size, size_t align) void* ptr; int error = 0; + // Don't allow this to under-align a type + size_t min_align = astc::max(alignof(T), sizeof(void*)); + size_t real_align = astc::max(min_align, align); + #if defined(_WIN32) - ptr = _aligned_malloc(size, align); + ptr = _aligned_malloc(size, real_align); #else - error = posix_memalign(&ptr, align, size); + error = posix_memalign(&ptr, real_align, size); #endif if (error || (!ptr)) @@ -2482,9 +2228,9 @@ template void aligned_free(T* ptr) { #if defined(_WIN32) - _aligned_free(reinterpret_cast(ptr)); + _aligned_free(ptr); #else - free(reinterpret_cast(ptr)); + free(ptr); #endif } diff --git a/Source/astcenc_internal_entry.h b/Source/astcenc_internal_entry.h new file mode 100644 index 0000000..2667714 --- /dev/null +++ b/Source/astcenc_internal_entry.h @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2011-2024 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +/** + * @brief Functions and data declarations for the outer context. + * + * The outer context includes thread-pool management, which is slower to + * compile due to increased use of C++ stdlib. The inner context used in the + * majority of the codec library does not include this. + */ + +#ifndef ASTCENC_INTERNAL_ENTRY_INCLUDED +#define ASTCENC_INTERNAL_ENTRY_INCLUDED + +#include +#include +#include +#include + +#include "astcenc_internal.h" + +/* ============================================================================ + Parallel execution control +============================================================================ */ + +/** + * @brief A simple counter-based manager for parallel task execution. + * + * The task processing execution consists of: + * + * * A single-threaded init stage. + * * A multi-threaded processing stage. + * * A condition variable so threads can wait for processing completion. + * + * The init stage will be executed by the first thread to arrive in the critical section, there is + * no main thread in the thread pool. + * + * The processing stage uses dynamic dispatch to assign task tickets to threads on an on-demand + * basis. Threads may each therefore executed different numbers of tasks, depending on their + * processing complexity. The task queue and the task tickets are just counters; the caller must map + * these integers to an actual processing partition in a specific problem domain. + * + * The exit wait condition is needed to ensure processing has finished before a worker thread can + * progress to the next stage of the pipeline. Specifically a worker may exit the processing stage + * because there are no new tasks to assign to it while other worker threads are still processing. + * Calling @c wait() will ensure that all other worker have finished before the thread can proceed. + * + * The basic usage model: + * + * // --------- From single-threaded code --------- + * + * // Reset the tracker state + * manager->reset() + * + * // --------- From multi-threaded code --------- + * + * // Run the stage init; only first thread actually runs the lambda + * manager->init() + * + * do + * { + * // Request a task assignment + * uint task_count; + * uint base_index = manager->get_tasks(, task_count); + * + * // Process any tasks we were given (task_count <= granule size) + * if (task_count) + * { + * // Run the user task processing code for N tasks here + * ... + * + * // Flag these tasks as complete + * manager->complete_tasks(task_count); + * } + * } while (task_count); + * + * // Wait for all threads to complete tasks before progressing + * manager->wait() + * + * // Run the stage term; only first thread actually runs the lambda + * manager->term() + */ +class ParallelManager +{ +private: + /** @brief Lock used for critical section and condition synchronization. */ + std::mutex m_lock; + + /** @brief True if the stage init() step has been executed. */ + bool m_init_done; + + /** @brief True if the stage term() step has been executed. */ + bool m_term_done; + + /** @brief Condition variable for tracking stage processing completion. */ + std::condition_variable m_complete; + + /** @brief Number of tasks started, but not necessarily finished. */ + std::atomic m_start_count; + + /** @brief Number of tasks finished. */ + unsigned int m_done_count; + + /** @brief Number of tasks that need to be processed. */ + unsigned int m_task_count; + + /** @brief Progress callback (optional). */ + astcenc_progress_callback m_callback; + + /** @brief Lock used for callback synchronization. */ + std::mutex m_callback_lock; + + /** @brief Minimum progress before making a callback. */ + float m_callback_min_diff; + + /** @brief Last progress callback value. */ + float m_callback_last_value; + +public: + /** @brief Create a new ParallelManager. */ + ParallelManager() + { + reset(); + } + + /** + * @brief Reset the tracker for a new processing batch. + * + * This must be called from single-threaded code before starting the multi-threaded processing + * operations. + */ + void reset() + { + m_init_done = false; + m_term_done = false; + m_start_count = 0; + m_done_count = 0; + m_task_count = 0; + m_callback_last_value = 0.0f; + m_callback_min_diff = 1.0f; + } + + /** + * @brief Trigger the pipeline stage init step. + * + * This can be called from multi-threaded code. The first thread to hit this will process the + * initialization. Other threads will block and wait for it to complete. + * + * @param init_func Callable which executes the stage initialization. It must return the + * total number of tasks in the stage. + */ + void init(std::function init_func) + { + std::lock_guard lck(m_lock); + if (!m_init_done) + { + m_task_count = init_func(); + m_init_done = true; + } + } + + /** + * @brief Trigger the pipeline stage init step. + * + * This can be called from multi-threaded code. The first thread to hit this will process the + * initialization. Other threads will block and wait for it to complete. + * + * @param task_count Total number of tasks needing processing. + * @param callback Function pointer for progress status callbacks. + */ + void init(unsigned int task_count, astcenc_progress_callback callback) + { + std::lock_guard lck(m_lock); + if (!m_init_done) + { + m_callback = callback; + m_task_count = task_count; + m_init_done = true; + + // Report every 1% or 4096 blocks, whichever is larger, to avoid callback overhead + float min_diff = (4096.0f / static_cast(task_count)) * 100.0f; + m_callback_min_diff = astc::max(min_diff, 1.0f); + } + } + + /** + * @brief Request a task assignment. + * + * Assign up to @c granule tasks to the caller for processing. + * + * @param granule Maximum number of tasks that can be assigned. + * @param[out] count Actual number of tasks assigned, or zero if no tasks were assigned. + * + * @return Task index of the first assigned task; assigned tasks increment from this. + */ + unsigned int get_task_assignment(unsigned int granule, unsigned int& count) + { + unsigned int base = m_start_count.fetch_add(granule, std::memory_order_relaxed); + if (base >= m_task_count) + { + count = 0; + return 0; + } + + count = astc::min(m_task_count - base, granule); + return base; + } + + /** + * @brief Complete a task assignment. + * + * Mark @c count tasks as complete. This will notify all threads blocked on @c wait() if this + * completes the processing of the stage. + * + * @param count The number of completed tasks. + */ + void complete_task_assignment(unsigned int count) + { + // Note: m_done_count cannot use an atomic without the mutex; this has a race between the + // update here and the wait() for other threads + unsigned int local_count; + float local_last_value; + { + std::unique_lock lck(m_lock); + m_done_count += count; + local_count = m_done_count; + local_last_value = m_callback_last_value; + + if (m_done_count == m_task_count) + { + // Ensure the progress bar hits 100% + if (m_callback) + { + std::unique_lock cblck(m_callback_lock); + m_callback(100.0f); + m_callback_last_value = 100.0f; + } + + lck.unlock(); + m_complete.notify_all(); + } + } + + // Process progress callback if we have one + if (m_callback) + { + // Initial lockless test - have we progressed enough to emit? + float num = static_cast(local_count); + float den = static_cast(m_task_count); + float this_value = (num / den) * 100.0f; + bool report_test = (this_value - local_last_value) > m_callback_min_diff; + + // Recheck under lock, because another thread might report first + if (report_test) + { + std::unique_lock cblck(m_callback_lock); + bool report_retest = (this_value - m_callback_last_value) > m_callback_min_diff; + if (report_retest) + { + m_callback(this_value); + m_callback_last_value = this_value; + } + } + } + } + + /** + * @brief Wait for stage processing to complete. + */ + void wait() + { + std::unique_lock lck(m_lock); + m_complete.wait(lck, [this]{ return m_done_count == m_task_count; }); + } + + /** + * @brief Trigger the pipeline stage term step. + * + * This can be called from multi-threaded code. The first thread to hit this will process the + * work pool termination. Caller must have called @c wait() prior to calling this function to + * ensure that processing is complete. + * + * @param term_func Callable which executes the stage termination. + */ + void term(std::function term_func) + { + std::lock_guard lck(m_lock); + if (!m_term_done) + { + term_func(); + m_term_done = true; + } + } +}; + +/** + * @brief The astcenc compression context. + */ +struct astcenc_context +{ + /** @brief The context internal state. */ + astcenc_contexti context; + +#if !defined(ASTCENC_DECOMPRESS_ONLY) + /** @brief The parallel manager for averages computation. */ + ParallelManager manage_avg; + + /** @brief The parallel manager for compression. */ + ParallelManager manage_compress; +#endif + + /** @brief The parallel manager for decompression. */ + ParallelManager manage_decompress; +}; + +#endif diff --git a/Source/astcenc_mathlib.h b/Source/astcenc_mathlib.h index 67e989e..562d659 100644 --- a/Source/astcenc_mathlib.h +++ b/Source/astcenc_mathlib.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -48,8 +48,6 @@ #define ASTCENC_SSE 42 #elif defined(__SSE4_1__) #define ASTCENC_SSE 41 - #elif defined(__SSE3__) - #define ASTCENC_SSE 30 #elif defined(__SSE2__) #define ASTCENC_SSE 20 #else @@ -75,10 +73,22 @@ #endif #endif +// Force vector-sized SIMD alignment #if ASTCENC_AVX #define ASTCENC_VECALIGN 32 -#else +#elif ASTCENC_SSE || ASTCENC_NEON #define ASTCENC_VECALIGN 16 +// Use default alignment for non-SIMD builds +#else + #define ASTCENC_VECALIGN 0 +#endif + +// C++11 states that alignas(0) should be ignored but GCC doesn't do +// this on some versions, so workaround and avoid emitting alignas(0) +#if ASTCENC_VECALIGN > 0 + #define ASTCENC_ALIGNAS alignas(ASTCENC_VECALIGN) +#else + #define ASTCENC_ALIGNAS #endif #if ASTCENC_SSE != 0 || ASTCENC_AVX != 0 || ASTCENC_POPCNT != 0 diff --git a/Source/astcenc_mathlib_softfloat.cpp b/Source/astcenc_mathlib_softfloat.cpp index d95fb9d..42db764 100644 --- a/Source/astcenc_mathlib_softfloat.cpp +++ b/Source/astcenc_mathlib_softfloat.cpp @@ -273,7 +273,7 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) of the mantissa is set.) */ p = (inp - 1) & UINT32_C(0x800000); /* zero if INF, nonzero if NaN. */ - return ((inp + vlx) >> 13) | (p >> 14); + return static_cast(((inp + vlx) >> 13) | (p >> 14)); /* positive, exponent = 0, round-mode == UP; need to check whether number actually is 0. If it is, then return 0, else return 1 (the smallest representable nonzero number) @@ -283,7 +283,7 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) -inp will set the MSB if the input number is nonzero. Thus (-inp) >> 31 will turn into 0 if the input number is 0 and 1 otherwise. */ - return static_cast((-static_cast(inp))) >> 31; + return static_cast(static_cast((-static_cast(inp))) >> 31); /* negative, exponent = , round-mode == DOWN, need to check whether number is @@ -296,7 +296,7 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) the MSB set if it isn't. We then right-shift the value by 31 places to get a value that is 0 if the input is -0.0 and 1 otherwise. */ - return ((vlx - inp) >> 31) + UINT32_C(0x8000); + return static_cast(((vlx - inp) >> 31) + UINT32_C(0x8000)); /* for all other cases involving underflow/overflow, we don't need to @@ -330,7 +330,7 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) case 47: case 48: case 49: - return vlx; + return static_cast(vlx); /* for normal numbers, 'vlx' is the difference between the FP32 value of a number and the @@ -349,14 +349,14 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) case 36: case 37: case 39: - return (inp + vlx) >> 13; + return static_cast((inp + vlx) >> 13); /* normal number, round-to-nearest-even. */ case 33: case 38: p = inp + vlx; p += (inp >> 13) & 1; - return p >> 13; + return static_cast(p >> 13); /* the various denormal cases. These are not expected to be common, so their performance is a bit @@ -371,22 +371,22 @@ static sf16 sf32_to_sf16(sf32 inp, roundmode rmode) case 27: /* denormal, round towards zero. */ p = 126 - ((inp >> 23) & 0xFF); - return (((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000)) >> p) | vlx; + return static_cast((((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000)) >> p) | vlx); case 20: case 26: /* denormal, round away from zero. */ p = 126 - ((inp >> 23) & 0xFF); - return rtup_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx; + return static_cast(rtup_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx); case 24: case 29: /* denormal, round to nearest-away */ p = 126 - ((inp >> 23) & 0xFF); - return rtna_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx; + return static_cast(rtna_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx); case 23: case 28: /* denormal, round to nearest-even. */ p = 126 - ((inp >> 23) & 0xFF); - return rtne_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx; + return static_cast(rtne_shift32((inp & UINT32_C(0x7FFFFF)) + UINT32_C(0x800000), p) | vlx); } return 0; diff --git a/Source/astcenc_partition_tables.cpp b/Source/astcenc_partition_tables.cpp index 6b97e49..cad4238 100644 --- a/Source/astcenc_partition_tables.cpp +++ b/Source/astcenc_partition_tables.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -21,6 +21,9 @@ #include "astcenc_internal.h" +/** @brief The number of 64-bit words needed to represent a canonical partition bit pattern. */ +#define BIT_PATTERN_WORDS (((ASTCENC_BLOCK_MAX_TEXELS * 2) + 63) / 64) + /** * @brief Generate a canonical representation of a partition pattern. * @@ -28,22 +31,22 @@ * the remapped texel index. Remapping ensures that we only match on the partition pattern, * independent of the partition order generated by the hash. * - * @param texel_count The number of texels in the block. - * @param partition_of_texel The partition assignments, in hash order. - * @param[out] bit_pattern The output bit pattern representation. + * @param texel_count The number of texels in the block. + * @param partition_of_texel The partition assignments, in hash order. + * @param[out] bit_pattern The output bit pattern representation. */ static void generate_canonical_partitioning( unsigned int texel_count, const uint8_t* partition_of_texel, - uint64_t bit_pattern[7] + uint64_t bit_pattern[BIT_PATTERN_WORDS] ) { // Clear the pattern - for (unsigned int i = 0; i < 7; i++) + for (unsigned int i = 0; i < BIT_PATTERN_WORDS; i++) { bit_pattern[i] = 0; } - // Store a mapping to reorder the raw partitions so that the the partitions are ordered such + // Store a mapping to reorder the raw partitions so that the partitions are ordered such // that the lowest texel index in partition N is smaller than the lowest texel index in // partition N + 1. int mapped_index[BLOCK_MAX_PARTITIONS]; @@ -76,19 +79,35 @@ static void generate_canonical_partitioning( * @return @c true if the patterns are the same, @c false otherwise. */ static bool compare_canonical_partitionings( - const uint64_t part1[7], - const uint64_t part2[7] + const uint64_t part1[BIT_PATTERN_WORDS], + const uint64_t part2[BIT_PATTERN_WORDS] ) { - return (part1[0] == part2[0]) && (part1[1] == part2[1]) && - (part1[2] == part2[2]) && (part1[3] == part2[3]) && - (part1[4] == part2[4]) && (part1[5] == part2[5]) && - (part1[6] == part2[6]); + return (part1[0] == part2[0]) +#if BIT_PATTERN_WORDS > 1 + && (part1[1] == part2[1]) +#endif +#if BIT_PATTERN_WORDS > 2 + && (part1[2] == part2[2]) +#endif +#if BIT_PATTERN_WORDS > 3 + && (part1[3] == part2[3]) +#endif +#if BIT_PATTERN_WORDS > 4 + && (part1[4] == part2[4]) +#endif +#if BIT_PATTERN_WORDS > 5 + && (part1[5] == part2[5]) +#endif +#if BIT_PATTERN_WORDS > 6 + && (part1[6] == part2[6]) +#endif + ; } /** * @brief Hash function used for procedural partition assignment. * - * @param inp The hash seed. + * @param inp The hash seed. * * @return The hashed value. */ @@ -116,7 +135,7 @@ static uint32_t hash52( * @param y The texel Y coordinate in the block. * @param z The texel Z coordinate in the block. * @param partition_count The total partition count of this encoding. - * @param small_block @c true if the blockhas fewer than 32 texels. + * @param small_block @c true if the block has fewer than 32 texels. * * @return The assigned partition index for this texel. */ @@ -316,25 +335,21 @@ static bool generate_one_partition_info_entry( } // Populate the partition index - pi.partition_index = partition_index; + pi.partition_index = static_cast(partition_index); // Populate the coverage bitmaps for 2/3/4 partitions uint64_t* bitmaps { nullptr }; - uint8_t* valids { nullptr }; if (partition_count == 2) { bitmaps = bsd.coverage_bitmaps_2[partition_remap_index]; - valids = bsd.partitioning_valid_2; } else if (partition_count == 3) { bitmaps = bsd.coverage_bitmaps_3[partition_remap_index]; - valids = bsd.partitioning_valid_3; } else if (partition_count == 4) { bitmaps = bsd.coverage_bitmaps_4[partition_remap_index]; - valids = bsd.partitioning_valid_4; } for (unsigned int i = 0; i < BLOCK_MAX_PARTITIONS; i++) @@ -347,9 +362,7 @@ static bool generate_one_partition_info_entry( if (bitmaps) { - // Populate the bitmap validity mask - valids[partition_remap_index] = valid ? 0 : 255; - + // Populate the partition coverage bitmap for (unsigned int i = 0; i < partition_count; i++) { bitmaps[i] = 0ULL; @@ -374,12 +387,6 @@ static void build_partition_table_for_one_partition_count( partition_info* ptab, uint64_t* canonical_patterns ) { - uint8_t* partitioning_valid[3] { - bsd.partitioning_valid_2, - bsd.partitioning_valid_3, - bsd.partitioning_valid_4 - }; - unsigned int next_index = 0; bsd.partitioning_count_selected[partition_count - 1] = 0; bsd.partitioning_count_all[partition_count - 1] = 0; @@ -397,7 +404,7 @@ static void build_partition_table_for_one_partition_count( // Tracker for things we built in the first iteration uint8_t build[BLOCK_MAX_PARTITIONINGS] { 0 }; - for (unsigned int x = 0; x < max_iter; x++) + for (unsigned int x = 0; x < max_iter; x++) { for (unsigned int i = 0; i < BLOCK_MAX_PARTITIONINGS; i++) { @@ -413,11 +420,11 @@ static void build_partition_table_for_one_partition_count( continue; } - generate_canonical_partitioning(bsd.texel_count, ptab[next_index].partition_of_texel, canonical_patterns + next_index * 7); + generate_canonical_partitioning(bsd.texel_count, ptab[next_index].partition_of_texel, canonical_patterns + next_index * BIT_PATTERN_WORDS); bool keep_canonical = true; for (unsigned int j = 0; j < next_index; j++) { - bool match = compare_canonical_partitionings(canonical_patterns + 7 * next_index, canonical_patterns + 7 * j); + bool match = compare_canonical_partitionings(canonical_patterns + next_index * BIT_PATTERN_WORDS, canonical_patterns + j * BIT_PATTERN_WORDS); if (match) { keep_canonical = false; @@ -429,7 +436,7 @@ static void build_partition_table_for_one_partition_count( { if (x == 0) { - bsd.partitioning_packed_index[partition_count - 2][i] = next_index; + bsd.partitioning_packed_index[partition_count - 2][i] = static_cast(next_index); bsd.partitioning_count_selected[partition_count - 1]++; bsd.partitioning_count_all[partition_count - 1]++; build[i] = 1; @@ -440,9 +447,8 @@ static void build_partition_table_for_one_partition_count( { if (x == 1) { - bsd.partitioning_packed_index[partition_count - 2][i] = next_index; + bsd.partitioning_packed_index[partition_count - 2][i] = static_cast(next_index); bsd.partitioning_count_all[partition_count - 1]++; - partitioning_valid[partition_count - 2][next_index] = 255; next_index++; } } @@ -465,7 +471,8 @@ void init_partition_tables( bsd.partitioning_count_selected[0] = 1; bsd.partitioning_count_all[0] = 1; - uint64_t* canonical_patterns = new uint64_t[BLOCK_MAX_PARTITIONINGS * 7]; + uint64_t* canonical_patterns = new uint64_t[BLOCK_MAX_PARTITIONINGS * BIT_PATTERN_WORDS]; + build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 2, par_tab2, canonical_patterns); build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 3, par_tab3, canonical_patterns); build_partition_table_for_one_partition_count(bsd, can_omit_partitionings, partition_count_cutoff, 4, par_tab4, canonical_patterns); diff --git a/Source/astcenc_percentile_tables.cpp b/Source/astcenc_percentile_tables.cpp index 5790305..448ddcc 100644 --- a/Source/astcenc_percentile_tables.cpp +++ b/Source/astcenc_percentile_tables.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2022 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -33,42 +33,47 @@ struct packed_percentile_table { /** The block X dimension. */ uint8_t xdim; + /** The block Y dimension. */ uint8_t ydim; + /** The number of packed items in the 1 and 2 plane data. */ - uint16_t itemcounts[2]; + uint16_t item_count[2]; + /** The accumulator divisor for 1 and 2 plane data. */ uint16_t difscales[2]; - /** The initital accumulator values for 1 and 2 plane data. */ + + /** The initial accumulator values for 1 and 2 plane data. */ uint16_t initial_percs[2]; + /** The packed data for the 1 and 2 plane data. */ const uint16_t *items[2]; }; #if ASTCENC_BLOCK_MAX_TEXELS >= (4 * 4) static const uint16_t percentile_arr_4x4_0[61] { - 0x0242,0x7243,0x6A51,0x6A52,0x5A41,0x4A53,0x8851,0x3842, - 0x3852,0x3853,0x3043,0xFA33,0x1BDF,0x2022,0x1032,0x29CE, - 0x21DE,0x2823,0x0813,0x0A13,0x0A31,0x0A23,0x09CF,0x0833, - 0x0A32,0x01DF,0x0BDD,0x0BCF,0x0221,0x095F,0x0A01,0x0BDE, - 0x0BCD,0x0A22,0x09AF,0x0B5F,0x0B4D,0x0BCE,0x0BBF,0x0A11, - 0x01BF,0x0202,0x0B5D,0x1203,0x034E,0x0B8E,0x035E,0x0212, - 0x032E,0x0B4F,0x03AF,0x03AD,0x03BD,0x0BBE,0x03AE,0x039F, - 0x039E,0x033E,0x033F,0x038F,0x032F + 0x0242, 0x7243, 0x6A51, 0x6A52, 0x5A41, 0x4A53, 0x8851, 0x3842, + 0x3852, 0x3853, 0x3043, 0xFA33, 0x1BDF, 0x2022, 0x1032, 0x29CE, + 0x21DE, 0x2823, 0x0813, 0x0A13, 0x0A31, 0x0A23, 0x09CF, 0x0833, + 0x0A32, 0x01DF, 0x0BDD, 0x0BCF, 0x0221, 0x095F, 0x0A01, 0x0BDE, + 0x0BCD, 0x0A22, 0x09AF, 0x0B5F, 0x0B4D, 0x0BCE, 0x0BBF, 0x0A11, + 0x01BF, 0x0202, 0x0B5D, 0x1203, 0x034E, 0x0B8E, 0x035E, 0x0212, + 0x032E, 0x0B4F, 0x03AF, 0x03AD, 0x03BD, 0x0BBE, 0x03AE, 0x039F, + 0x039E, 0x033E, 0x033F, 0x038F, 0x032F }; static const uint16_t percentile_arr_4x4_1[84] { - 0x0452,0xFFAE,0x2433,0x1DDF,0x17CD,0x1E21,0x1C43,0x1442, - 0x3FBE,0x1FDD,0x0E31,0x0F4F,0x1423,0x0FBD,0x1451,0x0E03, - 0x05CF,0x0C32,0x0DDE,0x27AD,0x274E,0x0E02,0x0F5E,0x07AF, - 0x0F5F,0x0DCE,0x0C41,0x0422,0x0613,0x0E12,0x0611,0x0F3F, - 0x0601,0x0DBF,0x05DD,0x075D,0x0C02,0x054E,0x0431,0x0413, - 0x079F,0x05BE,0x0F4D,0x0403,0x05AF,0x055F,0x05AE,0x054F, - 0x0421,0x05BD,0x0DCD,0x0411,0x0412,0x055E,0x055D,0x073D, - 0x058E,0x072F,0x072D,0x079D,0x0D2E,0x0453,0x078D,0x053E, - 0x053F,0x059E,0x052F,0x058F,0x072E,0x078F,0x059F,0x078E, - 0x071F,0x073E,0x051F,0x070D,0x079E,0x070E,0x071D,0x0622, - 0x070F,0x071E,0x07BF,0x07CE + 0x0452, 0xFFAE, 0x2433, 0x1DDF, 0x17CD, 0x1E21, 0x1C43, 0x1442, + 0x3FBE, 0x1FDD, 0x0E31, 0x0F4F, 0x1423, 0x0FBD, 0x1451, 0x0E03, + 0x05CF, 0x0C32, 0x0DDE, 0x27AD, 0x274E, 0x0E02, 0x0F5E, 0x07AF, + 0x0F5F, 0x0DCE, 0x0C41, 0x0422, 0x0613, 0x0E12, 0x0611, 0x0F3F, + 0x0601, 0x0DBF, 0x05DD, 0x075D, 0x0C02, 0x054E, 0x0431, 0x0413, + 0x079F, 0x05BE, 0x0F4D, 0x0403, 0x05AF, 0x055F, 0x05AE, 0x054F, + 0x0421, 0x05BD, 0x0DCD, 0x0411, 0x0412, 0x055E, 0x055D, 0x073D, + 0x058E, 0x072F, 0x072D, 0x079D, 0x0D2E, 0x0453, 0x078D, 0x053E, + 0x053F, 0x059E, 0x052F, 0x058F, 0x072E, 0x078F, 0x059F, 0x078E, + 0x071F, 0x073E, 0x051F, 0x070D, 0x079E, 0x070E, 0x071D, 0x0622, + 0x070F, 0x071E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_4x4 { @@ -82,34 +87,34 @@ static const packed_percentile_table block_pcd_4x4 { #if ASTCENC_BLOCK_MAX_TEXELS >= (5 * 4) static const uint16_t percentile_arr_5x4_0[91] { - 0x02C1,0xFAD1,0xE8D3,0xDAC2,0xA8D2,0x70D1,0x50C2,0x80C3, - 0xD2C3,0x4AA2,0x2AD2,0x2242,0x2251,0x42A3,0x1A43,0x4A52, - 0x32B3,0x2A41,0x1042,0x1851,0x5892,0x10A2,0x2253,0x10B2, - 0x10B3,0x13DF,0x3083,0x08B1,0x1043,0x12B1,0x0AB2,0x1A93, - 0x1852,0x1A33,0x09CE,0x08A3,0x1022,0x1283,0x0853,0x1AA1, - 0x1093,0x11DE,0x135F,0x1832,0x195F,0x0A81,0x11CF,0x0A31, - 0x09DF,0x0B4D,0x09AF,0x03CF,0x0813,0x03DD,0x0A92,0x0A82, - 0x03CD,0x0023,0x0BDE,0x0BBF,0x1232,0x0221,0x0291,0x0A23, - 0x0833,0x035D,0x0BCE,0x01BF,0x0222,0x134E,0x0213,0x0A01, - 0x0B4F,0x0B5E,0x038E,0x032E,0x03AF,0x0A11,0x03AD,0x0203, - 0x0202,0x0BBD,0x033E,0x03AE,0x03BE,0x0212,0x033F,0x039E, - 0x039F,0x032F,0x038F + 0x02C1, 0xFAD1, 0xE8D3, 0xDAC2, 0xA8D2, 0x70D1, 0x50C2, 0x80C3, + 0xD2C3, 0x4AA2, 0x2AD2, 0x2242, 0x2251, 0x42A3, 0x1A43, 0x4A52, + 0x32B3, 0x2A41, 0x1042, 0x1851, 0x5892, 0x10A2, 0x2253, 0x10B2, + 0x10B3, 0x13DF, 0x3083, 0x08B1, 0x1043, 0x12B1, 0x0AB2, 0x1A93, + 0x1852, 0x1A33, 0x09CE, 0x08A3, 0x1022, 0x1283, 0x0853, 0x1AA1, + 0x1093, 0x11DE, 0x135F, 0x1832, 0x195F, 0x0A81, 0x11CF, 0x0A31, + 0x09DF, 0x0B4D, 0x09AF, 0x03CF, 0x0813, 0x03DD, 0x0A92, 0x0A82, + 0x03CD, 0x0023, 0x0BDE, 0x0BBF, 0x1232, 0x0221, 0x0291, 0x0A23, + 0x0833, 0x035D, 0x0BCE, 0x01BF, 0x0222, 0x134E, 0x0213, 0x0A01, + 0x0B4F, 0x0B5E, 0x038E, 0x032E, 0x03AF, 0x0A11, 0x03AD, 0x0203, + 0x0202, 0x0BBD, 0x033E, 0x03AE, 0x03BE, 0x0212, 0x033F, 0x039E, + 0x039F, 0x032F, 0x038F }; static const uint16_t percentile_arr_5x4_1[104] { - 0x0433,0xB621,0x5452,0x4443,0x7FAE,0xFCA3,0x7CC2,0x24B2, - 0x45DF,0x44B3,0x7631,0x27CD,0x1CD1,0x1E03,0x4FBE,0x774F, - 0x1C42,0x7691,0x24A2,0x2681,0x3C23,0x3C93,0x0FBD,0x1C32, - 0x1E82,0x1E12,0x0F4E,0x1602,0x0FAD,0x0C51,0x1FDD,0x0E13, - 0x0DCF,0x175E,0x0C22,0x175F,0x15DE,0x0CB1,0x17AF,0x1CC1, - 0x1F3F,0x1483,0x0441,0x0C91,0x04D2,0x0DCE,0x154E,0x079F, - 0x0CA1,0x0F5D,0x0431,0x15DD,0x05BF,0x0C92,0x0611,0x0C82, - 0x0402,0x074D,0x0DBD,0x055E,0x05BE,0x0DCD,0x0421,0x05AF, - 0x0403,0x0D4F,0x055F,0x05AE,0x0413,0x0E01,0x055D,0x073D, - 0x0C12,0x0692,0x0411,0x072D,0x078D,0x079D,0x058E,0x0D2E, - 0x0453,0x072F,0x059E,0x052F,0x071F,0x053F,0x053E,0x078F, - 0x058F,0x051F,0x0F2E,0x059F,0x078E,0x073E,0x071D,0x070D, - 0x070E,0x079E,0x0622,0x0683,0x070F,0x071E,0x07BF,0x07CE + 0x0433, 0xB621, 0x5452, 0x4443, 0x7FAE, 0xFCA3, 0x7CC2, 0x24B2, + 0x45DF, 0x44B3, 0x7631, 0x27CD, 0x1CD1, 0x1E03, 0x4FBE, 0x774F, + 0x1C42, 0x7691, 0x24A2, 0x2681, 0x3C23, 0x3C93, 0x0FBD, 0x1C32, + 0x1E82, 0x1E12, 0x0F4E, 0x1602, 0x0FAD, 0x0C51, 0x1FDD, 0x0E13, + 0x0DCF, 0x175E, 0x0C22, 0x175F, 0x15DE, 0x0CB1, 0x17AF, 0x1CC1, + 0x1F3F, 0x1483, 0x0441, 0x0C91, 0x04D2, 0x0DCE, 0x154E, 0x079F, + 0x0CA1, 0x0F5D, 0x0431, 0x15DD, 0x05BF, 0x0C92, 0x0611, 0x0C82, + 0x0402, 0x074D, 0x0DBD, 0x055E, 0x05BE, 0x0DCD, 0x0421, 0x05AF, + 0x0403, 0x0D4F, 0x055F, 0x05AE, 0x0413, 0x0E01, 0x055D, 0x073D, + 0x0C12, 0x0692, 0x0411, 0x072D, 0x078D, 0x079D, 0x058E, 0x0D2E, + 0x0453, 0x072F, 0x059E, 0x052F, 0x071F, 0x053F, 0x053E, 0x078F, + 0x058F, 0x051F, 0x0F2E, 0x059F, 0x078E, 0x073E, 0x071D, 0x070D, + 0x070E, 0x079E, 0x0622, 0x0683, 0x070F, 0x071E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_5x4 { @@ -123,42 +128,42 @@ static const packed_percentile_table block_pcd_5x4 { #if ASTCENC_BLOCK_MAX_TEXELS >= (5 * 5) static const uint16_t percentile_arr_5x5_0[129] { - 0x00F3,0xF8F2,0x70E3,0x62E1,0x60E1,0x4AC1,0x3261,0x38D3, - 0x3271,0x5AF1,0x5873,0x2AD1,0x28E2,0x28F1,0x2262,0x9AC2, - 0x18D2,0x1072,0x1071,0x22A2,0x2062,0x1A51,0x10C2,0x0892, - 0x08D1,0x1AA3,0x23EE,0x08C3,0x0BEF,0x2242,0x0863,0x0AB3, - 0x0BFF,0x0A93,0x08A2,0x0A41,0x1083,0x0842,0x10B3,0x21EE, - 0x10B2,0x00B1,0x1263,0x12C3,0x0A83,0x0851,0x11FE,0x0253, - 0x09FD,0x0A72,0x09FF,0x1AB2,0x0BDF,0x0A33,0x0243,0x0B7F, - 0x0AB1,0x12D2,0x0252,0x096F,0x00A3,0x0893,0x0822,0x0843, - 0x097E,0x097F,0x01EF,0x09CE,0x03FE,0x0A81,0x036F,0x0052, - 0x13FD,0x0AA1,0x1853,0x036D,0x0A92,0x0832,0x01DE,0x0A82, - 0x0BED,0x0231,0x0BBF,0x03DD,0x0B6E,0x01AF,0x0813,0x0023, - 0x0A91,0x015F,0x037E,0x01CF,0x0232,0x0BCD,0x0221,0x0BDE, - 0x0213,0x035F,0x0B7D,0x0223,0x01BF,0x0BCF,0x01DF,0x0033, - 0x0222,0x03CE,0x0A01,0x03AF,0x034D,0x0B8E,0x032E,0x0203, - 0x0211,0x0202,0x0B5D,0x03AD,0x034E,0x03AE,0x034F,0x033F, - 0x039F,0x03BD,0x03BE,0x035E,0x0212,0x033E,0x039E,0x032F, + 0x00F3, 0xF8F2, 0x70E3, 0x62E1, 0x60E1, 0x4AC1, 0x3261, 0x38D3, + 0x3271, 0x5AF1, 0x5873, 0x2AD1, 0x28E2, 0x28F1, 0x2262, 0x9AC2, + 0x18D2, 0x1072, 0x1071, 0x22A2, 0x2062, 0x1A51, 0x10C2, 0x0892, + 0x08D1, 0x1AA3, 0x23EE, 0x08C3, 0x0BEF, 0x2242, 0x0863, 0x0AB3, + 0x0BFF, 0x0A93, 0x08A2, 0x0A41, 0x1083, 0x0842, 0x10B3, 0x21EE, + 0x10B2, 0x00B1, 0x1263, 0x12C3, 0x0A83, 0x0851, 0x11FE, 0x0253, + 0x09FD, 0x0A72, 0x09FF, 0x1AB2, 0x0BDF, 0x0A33, 0x0243, 0x0B7F, + 0x0AB1, 0x12D2, 0x0252, 0x096F, 0x00A3, 0x0893, 0x0822, 0x0843, + 0x097E, 0x097F, 0x01EF, 0x09CE, 0x03FE, 0x0A81, 0x036F, 0x0052, + 0x13FD, 0x0AA1, 0x1853, 0x036D, 0x0A92, 0x0832, 0x01DE, 0x0A82, + 0x0BED, 0x0231, 0x0BBF, 0x03DD, 0x0B6E, 0x01AF, 0x0813, 0x0023, + 0x0A91, 0x015F, 0x037E, 0x01CF, 0x0232, 0x0BCD, 0x0221, 0x0BDE, + 0x0213, 0x035F, 0x0B7D, 0x0223, 0x01BF, 0x0BCF, 0x01DF, 0x0033, + 0x0222, 0x03CE, 0x0A01, 0x03AF, 0x034D, 0x0B8E, 0x032E, 0x0203, + 0x0211, 0x0202, 0x0B5D, 0x03AD, 0x034E, 0x03AE, 0x034F, 0x033F, + 0x039F, 0x03BD, 0x03BE, 0x035E, 0x0212, 0x033E, 0x039E, 0x032F, 0x038F }; static const uint16_t percentile_arr_5x5_1[126] { - 0x0443,0x6452,0xFE21,0x27AE,0x2433,0x1FCD,0x25DF,0x6CC2, - 0x2C62,0x1F4F,0x4C42,0x1FBE,0x0DEF,0x34A3,0x0E03,0x54B2, - 0x1F7D,0x17DD,0x0DFF,0x0CD1,0x0E31,0x0C71,0x1CF1,0x15FE, - 0x1691,0x1681,0x24B3,0x174E,0x0F6E,0x0493,0x175E,0x1C51, - 0x17BD,0x076D,0x2CA2,0x05EE,0x1472,0x2423,0x0DCF,0x0432, - 0x15DE,0x0612,0x0CD2,0x0682,0x0F5F,0x07AD,0x0602,0x0CE1, - 0x0C91,0x0FAF,0x073F,0x0E13,0x0D7F,0x0DCE,0x0422,0x0D7D, - 0x0441,0x05FD,0x0CB1,0x0C83,0x04C1,0x0461,0x0F9F,0x0DDD, - 0x056E,0x0C92,0x0482,0x0431,0x05ED,0x0D6F,0x075D,0x0402, - 0x057E,0x0DBF,0x04A1,0x054E,0x0F4D,0x0403,0x05CD,0x0453, - 0x05AE,0x0421,0x0F1F,0x05BE,0x0601,0x0611,0x05BD,0x05AF, - 0x078D,0x072D,0x073D,0x055E,0x0F9D,0x0411,0x0413,0x0412, - 0x055F,0x077E,0x055D,0x052E,0x054F,0x053E,0x058E,0x078F, - 0x059E,0x071D,0x0E92,0x053F,0x059F,0x051F,0x072F,0x052F, - 0x070D,0x079E,0x058F,0x072E,0x070E,0x078E,0x070F,0x073E, - 0x0622,0x0683,0x071E,0x076F,0x07BF,0x07CE + 0x0443, 0x6452, 0xFE21, 0x27AE, 0x2433, 0x1FCD, 0x25DF, 0x6CC2, + 0x2C62, 0x1F4F, 0x4C42, 0x1FBE, 0x0DEF, 0x34A3, 0x0E03, 0x54B2, + 0x1F7D, 0x17DD, 0x0DFF, 0x0CD1, 0x0E31, 0x0C71, 0x1CF1, 0x15FE, + 0x1691, 0x1681, 0x24B3, 0x174E, 0x0F6E, 0x0493, 0x175E, 0x1C51, + 0x17BD, 0x076D, 0x2CA2, 0x05EE, 0x1472, 0x2423, 0x0DCF, 0x0432, + 0x15DE, 0x0612, 0x0CD2, 0x0682, 0x0F5F, 0x07AD, 0x0602, 0x0CE1, + 0x0C91, 0x0FAF, 0x073F, 0x0E13, 0x0D7F, 0x0DCE, 0x0422, 0x0D7D, + 0x0441, 0x05FD, 0x0CB1, 0x0C83, 0x04C1, 0x0461, 0x0F9F, 0x0DDD, + 0x056E, 0x0C92, 0x0482, 0x0431, 0x05ED, 0x0D6F, 0x075D, 0x0402, + 0x057E, 0x0DBF, 0x04A1, 0x054E, 0x0F4D, 0x0403, 0x05CD, 0x0453, + 0x05AE, 0x0421, 0x0F1F, 0x05BE, 0x0601, 0x0611, 0x05BD, 0x05AF, + 0x078D, 0x072D, 0x073D, 0x055E, 0x0F9D, 0x0411, 0x0413, 0x0412, + 0x055F, 0x077E, 0x055D, 0x052E, 0x054F, 0x053E, 0x058E, 0x078F, + 0x059E, 0x071D, 0x0E92, 0x053F, 0x059F, 0x051F, 0x072F, 0x052F, + 0x070D, 0x079E, 0x058F, 0x072E, 0x070E, 0x078E, 0x070F, 0x073E, + 0x0622, 0x0683, 0x071E, 0x076F, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_5x5 { @@ -172,48 +177,48 @@ static const packed_percentile_table block_pcd_5x5 { #if ASTCENC_BLOCK_MAX_TEXELS >= (6 * 5) static const uint16_t percentile_arr_6x5_0[165] { - 0x0163,0xF8F3,0x9962,0x8972,0x7961,0x7173,0x6953,0x5943, - 0x4B41,0x3AE1,0x38E3,0x6971,0x32C1,0x28D3,0x2A61,0xC8F2, - 0x2271,0x4873,0x5B21,0x3AD1,0x1B13,0x1952,0x1B51,0x12F1, - 0x1A62,0x1322,0x1951,0x10E2,0x1B31,0x20F1,0x2102,0x2072, - 0x10D2,0x1142,0x2912,0x3871,0x2BEE,0x0862,0x1123,0x0AC2, - 0x12A2,0x0A51,0x1922,0x0941,0x1BEF,0x0B42,0x08D1,0x13FF, - 0x1933,0x08C3,0x08C2,0x1131,0x08E1,0x2903,0x0863,0x0B32, - 0x1132,0x1AC3,0x0A42,0x1A41,0x0042,0x21EE,0x09FF,0x03DF, - 0x0AA3,0x11FE,0x02B3,0x0B11,0x10B3,0x0B03,0x11FD,0x0913, - 0x0A53,0x037F,0x1263,0x0051,0x0A33,0x0B01,0x016F,0x0A72, - 0x1312,0x08A2,0x10B1,0x0BFE,0x11EF,0x0B02,0x0A52,0x0043, - 0x0822,0x01CE,0x0A43,0x097F,0x036F,0x08B2,0x03FD,0x0A83, - 0x0B33,0x0AB1,0x017E,0x0B23,0x0852,0x02D2,0x0BBF,0x0BDD, - 0x03ED,0x0AB2,0x02A1,0x0853,0x036D,0x0892,0x0032,0x0A31, - 0x0083,0x09DE,0x0A93,0x08A3,0x1213,0x0BDE,0x03CD,0x036E, - 0x037E,0x0A21,0x0023,0x0BCF,0x01CF,0x0013,0x01AF,0x0A92, - 0x0232,0x035F,0x0093,0x0B7D,0x015F,0x0282,0x01BF,0x09DF, - 0x03CE,0x0223,0x0833,0x0222,0x03AF,0x0A01,0x0291,0x0B4D, - 0x032E,0x038E,0x0203,0x0281,0x035D,0x03AD,0x0B9F,0x0202, - 0x034F,0x03BE,0x0211,0x03AE,0x03BD,0x0212,0x034E,0x033F, - 0x033E,0x035E,0x039E,0x032F,0x038F + 0x0163, 0xF8F3, 0x9962, 0x8972, 0x7961, 0x7173, 0x6953, 0x5943, + 0x4B41, 0x3AE1, 0x38E3, 0x6971, 0x32C1, 0x28D3, 0x2A61, 0xC8F2, + 0x2271, 0x4873, 0x5B21, 0x3AD1, 0x1B13, 0x1952, 0x1B51, 0x12F1, + 0x1A62, 0x1322, 0x1951, 0x10E2, 0x1B31, 0x20F1, 0x2102, 0x2072, + 0x10D2, 0x1142, 0x2912, 0x3871, 0x2BEE, 0x0862, 0x1123, 0x0AC2, + 0x12A2, 0x0A51, 0x1922, 0x0941, 0x1BEF, 0x0B42, 0x08D1, 0x13FF, + 0x1933, 0x08C3, 0x08C2, 0x1131, 0x08E1, 0x2903, 0x0863, 0x0B32, + 0x1132, 0x1AC3, 0x0A42, 0x1A41, 0x0042, 0x21EE, 0x09FF, 0x03DF, + 0x0AA3, 0x11FE, 0x02B3, 0x0B11, 0x10B3, 0x0B03, 0x11FD, 0x0913, + 0x0A53, 0x037F, 0x1263, 0x0051, 0x0A33, 0x0B01, 0x016F, 0x0A72, + 0x1312, 0x08A2, 0x10B1, 0x0BFE, 0x11EF, 0x0B02, 0x0A52, 0x0043, + 0x0822, 0x01CE, 0x0A43, 0x097F, 0x036F, 0x08B2, 0x03FD, 0x0A83, + 0x0B33, 0x0AB1, 0x017E, 0x0B23, 0x0852, 0x02D2, 0x0BBF, 0x0BDD, + 0x03ED, 0x0AB2, 0x02A1, 0x0853, 0x036D, 0x0892, 0x0032, 0x0A31, + 0x0083, 0x09DE, 0x0A93, 0x08A3, 0x1213, 0x0BDE, 0x03CD, 0x036E, + 0x037E, 0x0A21, 0x0023, 0x0BCF, 0x01CF, 0x0013, 0x01AF, 0x0A92, + 0x0232, 0x035F, 0x0093, 0x0B7D, 0x015F, 0x0282, 0x01BF, 0x09DF, + 0x03CE, 0x0223, 0x0833, 0x0222, 0x03AF, 0x0A01, 0x0291, 0x0B4D, + 0x032E, 0x038E, 0x0203, 0x0281, 0x035D, 0x03AD, 0x0B9F, 0x0202, + 0x034F, 0x03BE, 0x0211, 0x03AE, 0x03BD, 0x0212, 0x034E, 0x033F, + 0x033E, 0x035E, 0x039E, 0x032F, 0x038F }; static const uint16_t percentile_arr_6x5_1[145] { - 0x0443,0xEFAE,0x2CC2,0x2E21,0x2C52,0x7C33,0x47CD,0x25DF, - 0x3CA3,0xFFBE,0x2551,0x24B3,0x474F,0x1513,0x2691,0x1603, - 0x1462,0x1D32,0x14B2,0x5442,0x2CD2,0x35EF,0x0CD1,0x3D22, - 0x17BD,0x0FDD,0x0DFF,0x2631,0x177D,0x0CF1,0x1E81,0x0E82, - 0x1DFE,0x0F5E,0x0701,0x2CA2,0x1D03,0x0F4E,0x1471,0x0C51, - 0x1F6E,0x2FAF,0x0561,0x0C72,0x176D,0x0FAD,0x0DEE,0x05CF, - 0x0E13,0x0F5F,0x0E12,0x0C23,0x1E02,0x1D12,0x0CB1,0x0C32, - 0x0C93,0x15DE,0x0F9F,0x0F3F,0x0D41,0x0C41,0x0CC1,0x0D31, - 0x0C22,0x05FD,0x057F,0x0D01,0x0461,0x04E1,0x0D7D,0x05CE, - 0x0502,0x0C31,0x05ED,0x05DD,0x0511,0x0F11,0x0491,0x0D6F, - 0x0521,0x056E,0x0C83,0x0D23,0x04A1,0x0C02,0x075D,0x05BF, - 0x0C21,0x079D,0x0482,0x05BD,0x0DBE,0x05CD,0x054E,0x057E, - 0x0DAE,0x074D,0x078D,0x0542,0x0492,0x05AF,0x0611,0x0F3D, - 0x0601,0x071F,0x055E,0x059E,0x0571,0x054F,0x0412,0x0453, - 0x058E,0x0413,0x0D3E,0x077E,0x072D,0x052E,0x059F,0x055D, - 0x072F,0x0403,0x0411,0x058F,0x055F,0x0692,0x078E,0x053F, - 0x0D2F,0x078F,0x070D,0x071D,0x051F,0x072E,0x079E,0x070E, - 0x070F,0x073E,0x0622,0x0683,0x0702,0x071E,0x076F,0x07BF, + 0x0443, 0xEFAE, 0x2CC2, 0x2E21, 0x2C52, 0x7C33, 0x47CD, 0x25DF, + 0x3CA3, 0xFFBE, 0x2551, 0x24B3, 0x474F, 0x1513, 0x2691, 0x1603, + 0x1462, 0x1D32, 0x14B2, 0x5442, 0x2CD2, 0x35EF, 0x0CD1, 0x3D22, + 0x17BD, 0x0FDD, 0x0DFF, 0x2631, 0x177D, 0x0CF1, 0x1E81, 0x0E82, + 0x1DFE, 0x0F5E, 0x0701, 0x2CA2, 0x1D03, 0x0F4E, 0x1471, 0x0C51, + 0x1F6E, 0x2FAF, 0x0561, 0x0C72, 0x176D, 0x0FAD, 0x0DEE, 0x05CF, + 0x0E13, 0x0F5F, 0x0E12, 0x0C23, 0x1E02, 0x1D12, 0x0CB1, 0x0C32, + 0x0C93, 0x15DE, 0x0F9F, 0x0F3F, 0x0D41, 0x0C41, 0x0CC1, 0x0D31, + 0x0C22, 0x05FD, 0x057F, 0x0D01, 0x0461, 0x04E1, 0x0D7D, 0x05CE, + 0x0502, 0x0C31, 0x05ED, 0x05DD, 0x0511, 0x0F11, 0x0491, 0x0D6F, + 0x0521, 0x056E, 0x0C83, 0x0D23, 0x04A1, 0x0C02, 0x075D, 0x05BF, + 0x0C21, 0x079D, 0x0482, 0x05BD, 0x0DBE, 0x05CD, 0x054E, 0x057E, + 0x0DAE, 0x074D, 0x078D, 0x0542, 0x0492, 0x05AF, 0x0611, 0x0F3D, + 0x0601, 0x071F, 0x055E, 0x059E, 0x0571, 0x054F, 0x0412, 0x0453, + 0x058E, 0x0413, 0x0D3E, 0x077E, 0x072D, 0x052E, 0x059F, 0x055D, + 0x072F, 0x0403, 0x0411, 0x058F, 0x055F, 0x0692, 0x078E, 0x053F, + 0x0D2F, 0x078F, 0x070D, 0x071D, 0x051F, 0x072E, 0x079E, 0x070E, + 0x070F, 0x073E, 0x0622, 0x0683, 0x0702, 0x071E, 0x076F, 0x07BF, 0x07CE }; @@ -228,56 +233,56 @@ static const packed_percentile_table block_pcd_6x5 { #if ASTCENC_BLOCK_MAX_TEXELS >= (6 * 6) static const uint16_t percentile_arr_6x6_0[206] { - 0x006F,0xF908,0xF104,0xE918,0xE963,0xD114,0xB0F3,0xA07E, - 0x7972,0x705F,0x687F,0x6162,0x5953,0x586E,0x610C,0x524D, - 0x5973,0x9943,0x98E3,0x904F,0x8341,0x7AC1,0x3A61,0x70D3, - 0xA073,0x6AE1,0x30F2,0x3313,0x2B21,0x9A2E,0x4322,0x225D, - 0x2331,0x2271,0x22D1,0x1A2D,0x221F,0x22F1,0x1971,0x6952, - 0x1951,0x187D,0x18F1,0x1902,0x185E,0x1B51,0x105D,0x1A3D, - 0x30E2,0x10D2,0x1961,0x12A2,0x6072,0x3942,0x386D,0x33EE, - 0x104E,0x4923,0x101E,0x2122,0x1251,0x1141,0x182F,0x3133, - 0x080E,0x1262,0x123E,0x1B32,0x102E,0x1931,0x10D1,0x1912, - 0x0871,0x12C2,0x08C2,0x1103,0x0B03,0x1062,0x083D,0x08E1, - 0x1132,0x184D,0x0863,0x08C3,0x303F,0x083E,0x10B3,0x12A3, - 0x0BEF,0x0B11,0x1A42,0x2233,0x13FF,0x080F,0x0A41,0x0AC3, - 0x0842,0x1A63,0x0BDF,0x09FF,0x12B3,0x124E,0x0B12,0x0B42, - 0x0A2F,0x1253,0x0913,0x1051,0x0B01,0x120F,0x0B02,0x08A2, - 0x0BBF,0x00B1,0x22B1,0x01EE,0x1B33,0x0B23,0x0283,0x13FD, - 0x0AB2,0x11FD,0x09FE,0x0A43,0x08B2,0x0A1D,0x0A52,0x023F, - 0x101F,0x01CE,0x0A31,0x0BDD,0x0293,0x1822,0x12A1,0x03FE, - 0x121E,0x0843,0x0272,0x0B6F,0x0052,0x0A0D,0x0BED,0x12D2, - 0x1B7F,0x1053,0x0032,0x01DE,0x08A3,0x020E,0x0883,0x09EF, - 0x0892,0x0A21,0x03CD,0x0B5F,0x0213,0x0A32,0x016F,0x1292, - 0x03DE,0x017E,0x0BAF,0x0223,0x1093,0x0BCF,0x037E,0x01DF, - 0x09CF,0x015F,0x09AF,0x0023,0x01BF,0x0222,0x0282,0x03CE, - 0x1013,0x036E,0x097F,0x0033,0x0A01,0x0B6D,0x03BE,0x037D, - 0x0281,0x0BAE,0x0203,0x032E,0x034D,0x034F,0x0291,0x0211, - 0x038E,0x03BD,0x039E,0x0BAD,0x033E,0x034E,0x039F,0x0202, - 0x035D,0x0212,0x033F,0x035E,0x038F,0x032F + 0x006F, 0xF908, 0xF104, 0xE918, 0xE963, 0xD114, 0xB0F3, 0xA07E, + 0x7972, 0x705F, 0x687F, 0x6162, 0x5953, 0x586E, 0x610C, 0x524D, + 0x5973, 0x9943, 0x98E3, 0x904F, 0x8341, 0x7AC1, 0x3A61, 0x70D3, + 0xA073, 0x6AE1, 0x30F2, 0x3313, 0x2B21, 0x9A2E, 0x4322, 0x225D, + 0x2331, 0x2271, 0x22D1, 0x1A2D, 0x221F, 0x22F1, 0x1971, 0x6952, + 0x1951, 0x187D, 0x18F1, 0x1902, 0x185E, 0x1B51, 0x105D, 0x1A3D, + 0x30E2, 0x10D2, 0x1961, 0x12A2, 0x6072, 0x3942, 0x386D, 0x33EE, + 0x104E, 0x4923, 0x101E, 0x2122, 0x1251, 0x1141, 0x182F, 0x3133, + 0x080E, 0x1262, 0x123E, 0x1B32, 0x102E, 0x1931, 0x10D1, 0x1912, + 0x0871, 0x12C2, 0x08C2, 0x1103, 0x0B03, 0x1062, 0x083D, 0x08E1, + 0x1132, 0x184D, 0x0863, 0x08C3, 0x303F, 0x083E, 0x10B3, 0x12A3, + 0x0BEF, 0x0B11, 0x1A42, 0x2233, 0x13FF, 0x080F, 0x0A41, 0x0AC3, + 0x0842, 0x1A63, 0x0BDF, 0x09FF, 0x12B3, 0x124E, 0x0B12, 0x0B42, + 0x0A2F, 0x1253, 0x0913, 0x1051, 0x0B01, 0x120F, 0x0B02, 0x08A2, + 0x0BBF, 0x00B1, 0x22B1, 0x01EE, 0x1B33, 0x0B23, 0x0283, 0x13FD, + 0x0AB2, 0x11FD, 0x09FE, 0x0A43, 0x08B2, 0x0A1D, 0x0A52, 0x023F, + 0x101F, 0x01CE, 0x0A31, 0x0BDD, 0x0293, 0x1822, 0x12A1, 0x03FE, + 0x121E, 0x0843, 0x0272, 0x0B6F, 0x0052, 0x0A0D, 0x0BED, 0x12D2, + 0x1B7F, 0x1053, 0x0032, 0x01DE, 0x08A3, 0x020E, 0x0883, 0x09EF, + 0x0892, 0x0A21, 0x03CD, 0x0B5F, 0x0213, 0x0A32, 0x016F, 0x1292, + 0x03DE, 0x017E, 0x0BAF, 0x0223, 0x1093, 0x0BCF, 0x037E, 0x01DF, + 0x09CF, 0x015F, 0x09AF, 0x0023, 0x01BF, 0x0222, 0x0282, 0x03CE, + 0x1013, 0x036E, 0x097F, 0x0033, 0x0A01, 0x0B6D, 0x03BE, 0x037D, + 0x0281, 0x0BAE, 0x0203, 0x032E, 0x034D, 0x034F, 0x0291, 0x0211, + 0x038E, 0x03BD, 0x039E, 0x0BAD, 0x033E, 0x034E, 0x039F, 0x0202, + 0x035D, 0x0212, 0x033F, 0x035E, 0x038F, 0x032F }; static const uint16_t percentile_arr_6x6_1[164] { - 0x07AE,0x8443,0x7E21,0x77CD,0x6C62,0x9433,0x6452,0x34C2, - 0x5DDF,0xC7BE,0x25EF,0x24A3,0x3CF1,0xFDFF,0x177D,0x1F4F, - 0xC551,0x5CB3,0x1532,0x1513,0x143E,0x245D,0x14B2,0x2472, - 0x14D2,0x1FBD,0x1631,0x2DFE,0x1691,0x17DD,0x2E03,0x376E, - 0x2442,0x0F6D,0x3C71,0x2CD1,0x2522,0x6C51,0x260D,0x17AF, - 0x0DEE,0x1C1F,0x2F01,0x142E,0x0CA2,0x0FAD,0x3D03,0x275E, - 0x1681,0x274E,0x1682,0x1C23,0x273F,0x0F5F,0x05DE,0x15FD, - 0x0DCF,0x1E02,0x04B1,0x144D,0x0E12,0x0D12,0x1CC1,0x0E13, - 0x1C6D,0x0C32,0x043D,0x0C61,0x0F9F,0x04E1,0x0DCE,0x0D41, - 0x1C93,0x0C22,0x061D,0x0D7F,0x0C41,0x0561,0x0531,0x0D21, - 0x0711,0x0C91,0x0501,0x0C1E,0x040F,0x15DD,0x0431,0x0C2F, - 0x057D,0x0C2D,0x0DBE,0x040E,0x0D02,0x0D11,0x054E,0x040D, - 0x0D23,0x0DBF,0x04A1,0x05ED,0x0C1D,0x05BD,0x072D,0x056E, - 0x0483,0x0F3D,0x0482,0x078D,0x0F5D,0x0453,0x0D9E,0x0C4E, - 0x05CD,0x079D,0x0402,0x05AE,0x0F1F,0x0542,0x074D,0x056F, - 0x0421,0x0D4F,0x0601,0x0571,0x0492,0x059F,0x053F,0x05AF, - 0x0611,0x055E,0x0D8E,0x053E,0x055D,0x047D,0x0411,0x052E, - 0x058F,0x051F,0x055F,0x0D7E,0x072F,0x052F,0x0412,0x078F, - 0x0403,0x077E,0x070D,0x070E,0x078E,0x0F1D,0x072E,0x0413, - 0x070F,0x0692,0x079E,0x060E,0x0622,0x0683,0x0702,0x071E, - 0x073E,0x076F,0x07BF,0x07CE + 0x07AE, 0x8443, 0x7E21, 0x77CD, 0x6C62, 0x9433, 0x6452, 0x34C2, + 0x5DDF, 0xC7BE, 0x25EF, 0x24A3, 0x3CF1, 0xFDFF, 0x177D, 0x1F4F, + 0xC551, 0x5CB3, 0x1532, 0x1513, 0x143E, 0x245D, 0x14B2, 0x2472, + 0x14D2, 0x1FBD, 0x1631, 0x2DFE, 0x1691, 0x17DD, 0x2E03, 0x376E, + 0x2442, 0x0F6D, 0x3C71, 0x2CD1, 0x2522, 0x6C51, 0x260D, 0x17AF, + 0x0DEE, 0x1C1F, 0x2F01, 0x142E, 0x0CA2, 0x0FAD, 0x3D03, 0x275E, + 0x1681, 0x274E, 0x1682, 0x1C23, 0x273F, 0x0F5F, 0x05DE, 0x15FD, + 0x0DCF, 0x1E02, 0x04B1, 0x144D, 0x0E12, 0x0D12, 0x1CC1, 0x0E13, + 0x1C6D, 0x0C32, 0x043D, 0x0C61, 0x0F9F, 0x04E1, 0x0DCE, 0x0D41, + 0x1C93, 0x0C22, 0x061D, 0x0D7F, 0x0C41, 0x0561, 0x0531, 0x0D21, + 0x0711, 0x0C91, 0x0501, 0x0C1E, 0x040F, 0x15DD, 0x0431, 0x0C2F, + 0x057D, 0x0C2D, 0x0DBE, 0x040E, 0x0D02, 0x0D11, 0x054E, 0x040D, + 0x0D23, 0x0DBF, 0x04A1, 0x05ED, 0x0C1D, 0x05BD, 0x072D, 0x056E, + 0x0483, 0x0F3D, 0x0482, 0x078D, 0x0F5D, 0x0453, 0x0D9E, 0x0C4E, + 0x05CD, 0x079D, 0x0402, 0x05AE, 0x0F1F, 0x0542, 0x074D, 0x056F, + 0x0421, 0x0D4F, 0x0601, 0x0571, 0x0492, 0x059F, 0x053F, 0x05AF, + 0x0611, 0x055E, 0x0D8E, 0x053E, 0x055D, 0x047D, 0x0411, 0x052E, + 0x058F, 0x051F, 0x055F, 0x0D7E, 0x072F, 0x052F, 0x0412, 0x078F, + 0x0403, 0x077E, 0x070D, 0x070E, 0x078E, 0x0F1D, 0x072E, 0x0413, + 0x070F, 0x0692, 0x079E, 0x060E, 0x0622, 0x0683, 0x0702, 0x071E, + 0x073E, 0x076F, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_6x6 { @@ -291,59 +296,59 @@ static const packed_percentile_table block_pcd_6x6 { #if ASTCENC_BLOCK_MAX_TEXELS >= (8 * 5) static const uint16_t percentile_arr_8x5_0[226] { - 0x0066,0xF865,0xE963,0xA856,0xA1F2,0x9875,0x91C3,0x91E2, - 0x80F3,0x8076,0x61E3,0x6153,0x5172,0x59D2,0x51D3,0x5047, - 0xA943,0x49B3,0x4846,0x4962,0xC037,0x4173,0x39F1,0x7027, - 0xA2C1,0x3AE1,0x9341,0x30D3,0x5225,0x2A61,0x33C1,0x28E3, - 0x53A1,0x49C2,0x2A06,0x4055,0x2006,0x21D1,0x2271,0x4321, - 0x3873,0x18F2,0x2015,0x1A15,0x1857,0x52D1,0x3045,0x4835, - 0x1952,0x29E1,0x3207,0x1036,0x1816,0x2A16,0x2971,0x13B1, - 0x2A17,0x2351,0x1025,0x1826,0x30E2,0x1262,0x20F1,0x1007, - 0x1072,0x1151,0x10D2,0x1235,0x1205,0x1062,0x4AF1,0x1251, - 0x0B31,0x1381,0x13EE,0x1B92,0x13EF,0x0942,0x1AA2,0x13FF, - 0x1161,0x0B93,0x19A2,0x11B1,0x08D1,0x12C2,0x0B13,0x1B22, - 0x2123,0x09A3,0x2071,0x1B7F,0x1817,0x0A42,0x10C2,0x1233, - 0x08C3,0x0A41,0x0B42,0x09C1,0x0933,0x1AB3,0x1382,0x1BDF, - 0x2122,0x0A53,0x0AC3,0x20E1,0x0941,0x0931,0x0042,0x0BA2, - 0x0AA3,0x0992,0x0863,0x08B3,0x11B2,0x0902,0x1283,0x09FF, - 0x0B83,0x0982,0x0932,0x0BFE,0x0B32,0x0BBF,0x11FE,0x036F, - 0x0851,0x08B1,0x18A2,0x11EE,0x0A52,0x0BB2,0x01FD,0x0A43, - 0x1A63,0x1193,0x0B91,0x0043,0x1231,0x0A26,0x0AB1,0x03FD, - 0x096F,0x00B2,0x0983,0x0A72,0x01CE,0x0BDD,0x0022,0x0B11, - 0x1213,0x0B6D,0x017E,0x1333,0x0112,0x0852,0x02D2,0x097F, - 0x01EF,0x0AB2,0x0293,0x0853,0x0BED,0x0B12,0x1303,0x02A1, - 0x0892,0x0032,0x0883,0x0B6E,0x0292,0x0A32,0x037E,0x0B23, - 0x0103,0x0A21,0x0B01,0x0302,0x0BCD,0x00A3,0x0BCF,0x0BDE, - 0x0113,0x01DE,0x0B5F,0x0013,0x0BAF,0x0223,0x0222,0x0A82, - 0x0833,0x0023,0x09CF,0x037D,0x01AF,0x095F,0x03CE,0x09DF, - 0x01BF,0x0893,0x0203,0x0201,0x0B4D,0x03BE,0x032E,0x03AE, - 0x0291,0x0A02,0x0211,0x039F,0x0281,0x038E,0x03AD,0x033F, - 0x035D,0x033E,0x034E,0x034F,0x0212,0x03BD,0x032F,0x035E, - 0x038F,0x039E + 0x0066, 0xF865, 0xE963, 0xA856, 0xA1F2, 0x9875, 0x91C3, 0x91E2, + 0x80F3, 0x8076, 0x61E3, 0x6153, 0x5172, 0x59D2, 0x51D3, 0x5047, + 0xA943, 0x49B3, 0x4846, 0x4962, 0xC037, 0x4173, 0x39F1, 0x7027, + 0xA2C1, 0x3AE1, 0x9341, 0x30D3, 0x5225, 0x2A61, 0x33C1, 0x28E3, + 0x53A1, 0x49C2, 0x2A06, 0x4055, 0x2006, 0x21D1, 0x2271, 0x4321, + 0x3873, 0x18F2, 0x2015, 0x1A15, 0x1857, 0x52D1, 0x3045, 0x4835, + 0x1952, 0x29E1, 0x3207, 0x1036, 0x1816, 0x2A16, 0x2971, 0x13B1, + 0x2A17, 0x2351, 0x1025, 0x1826, 0x30E2, 0x1262, 0x20F1, 0x1007, + 0x1072, 0x1151, 0x10D2, 0x1235, 0x1205, 0x1062, 0x4AF1, 0x1251, + 0x0B31, 0x1381, 0x13EE, 0x1B92, 0x13EF, 0x0942, 0x1AA2, 0x13FF, + 0x1161, 0x0B93, 0x19A2, 0x11B1, 0x08D1, 0x12C2, 0x0B13, 0x1B22, + 0x2123, 0x09A3, 0x2071, 0x1B7F, 0x1817, 0x0A42, 0x10C2, 0x1233, + 0x08C3, 0x0A41, 0x0B42, 0x09C1, 0x0933, 0x1AB3, 0x1382, 0x1BDF, + 0x2122, 0x0A53, 0x0AC3, 0x20E1, 0x0941, 0x0931, 0x0042, 0x0BA2, + 0x0AA3, 0x0992, 0x0863, 0x08B3, 0x11B2, 0x0902, 0x1283, 0x09FF, + 0x0B83, 0x0982, 0x0932, 0x0BFE, 0x0B32, 0x0BBF, 0x11FE, 0x036F, + 0x0851, 0x08B1, 0x18A2, 0x11EE, 0x0A52, 0x0BB2, 0x01FD, 0x0A43, + 0x1A63, 0x1193, 0x0B91, 0x0043, 0x1231, 0x0A26, 0x0AB1, 0x03FD, + 0x096F, 0x00B2, 0x0983, 0x0A72, 0x01CE, 0x0BDD, 0x0022, 0x0B11, + 0x1213, 0x0B6D, 0x017E, 0x1333, 0x0112, 0x0852, 0x02D2, 0x097F, + 0x01EF, 0x0AB2, 0x0293, 0x0853, 0x0BED, 0x0B12, 0x1303, 0x02A1, + 0x0892, 0x0032, 0x0883, 0x0B6E, 0x0292, 0x0A32, 0x037E, 0x0B23, + 0x0103, 0x0A21, 0x0B01, 0x0302, 0x0BCD, 0x00A3, 0x0BCF, 0x0BDE, + 0x0113, 0x01DE, 0x0B5F, 0x0013, 0x0BAF, 0x0223, 0x0222, 0x0A82, + 0x0833, 0x0023, 0x09CF, 0x037D, 0x01AF, 0x095F, 0x03CE, 0x09DF, + 0x01BF, 0x0893, 0x0203, 0x0201, 0x0B4D, 0x03BE, 0x032E, 0x03AE, + 0x0291, 0x0A02, 0x0211, 0x039F, 0x0281, 0x038E, 0x03AD, 0x033F, + 0x035D, 0x033E, 0x034E, 0x034F, 0x0212, 0x03BD, 0x032F, 0x035E, + 0x038F, 0x039E }; static const uint16_t percentile_arr_8x5_1[167] { - 0x0621,0xFCC2,0x3443,0xA433,0x5532,0x2551,0x6CA3,0x27AE, - 0x6452,0x8E03,0x3CB3,0x4DA2,0x6DDF,0x37CD,0x6F01,0x1691, - 0x2E82,0x27BE,0x1513,0x34D2,0x1D22,0x3E31,0x2593,0x2CB2, - 0x1C16,0x374F,0x0DD1,0x2583,0x6613,0x0CD1,0x0C35,0x1462, - 0x3E81,0x2612,0x2C42,0x3407,0x14A2,0x0E02,0x1CF1,0x0C06, - 0x17BD,0x0F7D,0x1D23,0x35B1,0x179F,0x0D92,0x0F5E,0x1451, - 0x04B1,0x1F6E,0x0DEF,0x0D31,0x374E,0x15C1,0x0541,0x2405, - 0x17AD,0x0471,0x1472,0x0DFE,0x0711,0x0FDD,0x0DFF,0x0432, - 0x1D82,0x0423,0x0F6D,0x07AF,0x0F5F,0x04C1,0x1542,0x0561, - 0x0DCF,0x1D03,0x1493,0x0422,0x0445,0x0D12,0x0C25,0x0415, - 0x0DA1,0x1591,0x0DEE,0x05DE,0x0C31,0x0491,0x0441,0x0D21, - 0x078D,0x057D,0x0C61,0x0F3F,0x0581,0x0D6E,0x0501,0x0CA1, - 0x04E1,0x0DFD,0x057F,0x0502,0x0511,0x0C82,0x0483,0x0C03, - 0x079D,0x0402,0x0DDD,0x0611,0x05AE,0x0DCE,0x056F,0x0421, - 0x057E,0x071F,0x0DBF,0x05BE,0x0412,0x059F,0x054E,0x077E, - 0x0C26,0x05ED,0x073D,0x0601,0x0492,0x0453,0x075D,0x058E, - 0x0F2D,0x05CD,0x0571,0x053E,0x0692,0x05BD,0x054F,0x055E, - 0x0411,0x0F1D,0x074D,0x059E,0x05AF,0x070D,0x053F,0x058F, - 0x0413,0x070F,0x055D,0x070E,0x078F,0x052E,0x072F,0x055F, - 0x078E,0x0F2E,0x052F,0x051F,0x0417,0x071E,0x0781,0x0622, - 0x0683,0x0702,0x073E,0x076F,0x079E,0x07BF,0x07CE + 0x0621, 0xFCC2, 0x3443, 0xA433, 0x5532, 0x2551, 0x6CA3, 0x27AE, + 0x6452, 0x8E03, 0x3CB3, 0x4DA2, 0x6DDF, 0x37CD, 0x6F01, 0x1691, + 0x2E82, 0x27BE, 0x1513, 0x34D2, 0x1D22, 0x3E31, 0x2593, 0x2CB2, + 0x1C16, 0x374F, 0x0DD1, 0x2583, 0x6613, 0x0CD1, 0x0C35, 0x1462, + 0x3E81, 0x2612, 0x2C42, 0x3407, 0x14A2, 0x0E02, 0x1CF1, 0x0C06, + 0x17BD, 0x0F7D, 0x1D23, 0x35B1, 0x179F, 0x0D92, 0x0F5E, 0x1451, + 0x04B1, 0x1F6E, 0x0DEF, 0x0D31, 0x374E, 0x15C1, 0x0541, 0x2405, + 0x17AD, 0x0471, 0x1472, 0x0DFE, 0x0711, 0x0FDD, 0x0DFF, 0x0432, + 0x1D82, 0x0423, 0x0F6D, 0x07AF, 0x0F5F, 0x04C1, 0x1542, 0x0561, + 0x0DCF, 0x1D03, 0x1493, 0x0422, 0x0445, 0x0D12, 0x0C25, 0x0415, + 0x0DA1, 0x1591, 0x0DEE, 0x05DE, 0x0C31, 0x0491, 0x0441, 0x0D21, + 0x078D, 0x057D, 0x0C61, 0x0F3F, 0x0581, 0x0D6E, 0x0501, 0x0CA1, + 0x04E1, 0x0DFD, 0x057F, 0x0502, 0x0511, 0x0C82, 0x0483, 0x0C03, + 0x079D, 0x0402, 0x0DDD, 0x0611, 0x05AE, 0x0DCE, 0x056F, 0x0421, + 0x057E, 0x071F, 0x0DBF, 0x05BE, 0x0412, 0x059F, 0x054E, 0x077E, + 0x0C26, 0x05ED, 0x073D, 0x0601, 0x0492, 0x0453, 0x075D, 0x058E, + 0x0F2D, 0x05CD, 0x0571, 0x053E, 0x0692, 0x05BD, 0x054F, 0x055E, + 0x0411, 0x0F1D, 0x074D, 0x059E, 0x05AF, 0x070D, 0x053F, 0x058F, + 0x0413, 0x070F, 0x055D, 0x070E, 0x078F, 0x052E, 0x072F, 0x055F, + 0x078E, 0x0F2E, 0x052F, 0x051F, 0x0417, 0x071E, 0x0781, 0x0622, + 0x0683, 0x0702, 0x073E, 0x076F, 0x079E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_8x5 { @@ -357,68 +362,68 @@ static const packed_percentile_table block_pcd_8x5 { #if ASTCENC_BLOCK_MAX_TEXELS >= (8 * 6) static const uint16_t percentile_arr_8x6_0[273] { - 0x0154,0xF944,0xE066,0xA128,0x9963,0x8118,0x806F,0x79F2, - 0x79E2,0x7108,0xD934,0x6056,0x69C3,0x60F3,0x5972,0x59E3, - 0x5075,0x91B3,0xC9D2,0x807E,0x385F,0x4153,0x3943,0x4162, - 0x3837,0x3847,0x7173,0x31D3,0x6948,0x3046,0x307F,0x5827, - 0x3114,0x32C1,0x3076,0x2A4D,0x58E3,0x306E,0x2924,0x2A61, - 0x29F1,0x50D3,0x704F,0x210C,0x2BA1,0x2225,0x2873,0x4865, - 0x2206,0x8341,0x2006,0x3B21,0x18F2,0x21C2,0x1A1F,0x23C1, - 0x3AE1,0x1855,0x19D1,0x1A15,0x3815,0x1207,0x1835,0x2A2E, - 0x1A16,0x1836,0x2271,0x2845,0x1A2D,0x11E1,0x1816,0x1171, - 0x2217,0x1952,0x12D1,0x3904,0x125D,0x4BB1,0x207D,0x10E2, - 0x1026,0x2025,0x12F1,0x28F1,0x105D,0x1235,0x12A2,0x1007, - 0x123D,0x1A05,0x1072,0x1331,0x101E,0x0951,0x10D2,0x1057, - 0x1B92,0x185E,0x1251,0x19A2,0x186D,0x0B81,0x2BEE,0x080E, - 0x1A33,0x1942,0x0B13,0x0B51,0x11A3,0x0923,0x2322,0x09B1, - 0x184E,0x1161,0x18D1,0x0933,0x0B93,0x4A62,0x1017,0x082F, - 0x0A42,0x0B82,0x0AA3,0x0A41,0x08C2,0x08B3,0x0A3E,0x22B3, - 0x0871,0x1BBF,0x09C1,0x0AC2,0x09B2,0x0BEF,0x082E,0x1062, - 0x0922,0x08C3,0x1063,0x0A53,0x0BDF,0x080F,0x0B42,0x0A83, - 0x084D,0x103F,0x0931,0x08E1,0x0A0F,0x1BA2,0x09FF,0x1332, - 0x03FF,0x0941,0x12C3,0x0A63,0x003D,0x0842,0x083E,0x0B83, - 0x0BB2,0x0A31,0x0932,0x1102,0x0992,0x0982,0x1051,0x08B1, - 0x0A2F,0x121E,0x02B1,0x0A4E,0x11EE,0x00A2,0x1022,0x0043, - 0x0A52,0x0A1D,0x0226,0x1193,0x03DD,0x08B2,0x0BFD,0x0A43, - 0x0A13,0x0AB2,0x01FD,0x09FE,0x020D,0x081F,0x0B33,0x0053, - 0x0B91,0x0293,0x0B11,0x0B7F,0x0AA1,0x0B03,0x0A0E,0x03FE, - 0x01CE,0x0B6F,0x0183,0x0912,0x023F,0x0852,0x0A21,0x0323, - 0x03ED,0x0A32,0x13AF,0x0272,0x08A3,0x0B12,0x0083,0x0832, - 0x13CD,0x0223,0x0A92,0x0092,0x0AD2,0x0301,0x0302,0x0BDE, - 0x0A22,0x01EF,0x0B5F,0x0103,0x0BCF,0x096F,0x017E,0x0113, - 0x01DE,0x0823,0x0282,0x0B6E,0x015F,0x0813,0x01AF,0x01CF, - 0x0B7E,0x0033,0x01DF,0x0BCE,0x01BF,0x036D,0x0A03,0x017F, - 0x03BE,0x0201,0x0893,0x038E,0x034D,0x03AE,0x0202,0x039F, - 0x0291,0x0A11,0x032E,0x033F,0x034F,0x0281,0x037D,0x03BD, - 0x0212,0x033E,0x035E,0x034E,0x035D,0x03AD,0x032F,0x038F, + 0x0154, 0xF944, 0xE066, 0xA128, 0x9963, 0x8118, 0x806F, 0x79F2, + 0x79E2, 0x7108, 0xD934, 0x6056, 0x69C3, 0x60F3, 0x5972, 0x59E3, + 0x5075, 0x91B3, 0xC9D2, 0x807E, 0x385F, 0x4153, 0x3943, 0x4162, + 0x3837, 0x3847, 0x7173, 0x31D3, 0x6948, 0x3046, 0x307F, 0x5827, + 0x3114, 0x32C1, 0x3076, 0x2A4D, 0x58E3, 0x306E, 0x2924, 0x2A61, + 0x29F1, 0x50D3, 0x704F, 0x210C, 0x2BA1, 0x2225, 0x2873, 0x4865, + 0x2206, 0x8341, 0x2006, 0x3B21, 0x18F2, 0x21C2, 0x1A1F, 0x23C1, + 0x3AE1, 0x1855, 0x19D1, 0x1A15, 0x3815, 0x1207, 0x1835, 0x2A2E, + 0x1A16, 0x1836, 0x2271, 0x2845, 0x1A2D, 0x11E1, 0x1816, 0x1171, + 0x2217, 0x1952, 0x12D1, 0x3904, 0x125D, 0x4BB1, 0x207D, 0x10E2, + 0x1026, 0x2025, 0x12F1, 0x28F1, 0x105D, 0x1235, 0x12A2, 0x1007, + 0x123D, 0x1A05, 0x1072, 0x1331, 0x101E, 0x0951, 0x10D2, 0x1057, + 0x1B92, 0x185E, 0x1251, 0x19A2, 0x186D, 0x0B81, 0x2BEE, 0x080E, + 0x1A33, 0x1942, 0x0B13, 0x0B51, 0x11A3, 0x0923, 0x2322, 0x09B1, + 0x184E, 0x1161, 0x18D1, 0x0933, 0x0B93, 0x4A62, 0x1017, 0x082F, + 0x0A42, 0x0B82, 0x0AA3, 0x0A41, 0x08C2, 0x08B3, 0x0A3E, 0x22B3, + 0x0871, 0x1BBF, 0x09C1, 0x0AC2, 0x09B2, 0x0BEF, 0x082E, 0x1062, + 0x0922, 0x08C3, 0x1063, 0x0A53, 0x0BDF, 0x080F, 0x0B42, 0x0A83, + 0x084D, 0x103F, 0x0931, 0x08E1, 0x0A0F, 0x1BA2, 0x09FF, 0x1332, + 0x03FF, 0x0941, 0x12C3, 0x0A63, 0x003D, 0x0842, 0x083E, 0x0B83, + 0x0BB2, 0x0A31, 0x0932, 0x1102, 0x0992, 0x0982, 0x1051, 0x08B1, + 0x0A2F, 0x121E, 0x02B1, 0x0A4E, 0x11EE, 0x00A2, 0x1022, 0x0043, + 0x0A52, 0x0A1D, 0x0226, 0x1193, 0x03DD, 0x08B2, 0x0BFD, 0x0A43, + 0x0A13, 0x0AB2, 0x01FD, 0x09FE, 0x020D, 0x081F, 0x0B33, 0x0053, + 0x0B91, 0x0293, 0x0B11, 0x0B7F, 0x0AA1, 0x0B03, 0x0A0E, 0x03FE, + 0x01CE, 0x0B6F, 0x0183, 0x0912, 0x023F, 0x0852, 0x0A21, 0x0323, + 0x03ED, 0x0A32, 0x13AF, 0x0272, 0x08A3, 0x0B12, 0x0083, 0x0832, + 0x13CD, 0x0223, 0x0A92, 0x0092, 0x0AD2, 0x0301, 0x0302, 0x0BDE, + 0x0A22, 0x01EF, 0x0B5F, 0x0103, 0x0BCF, 0x096F, 0x017E, 0x0113, + 0x01DE, 0x0823, 0x0282, 0x0B6E, 0x015F, 0x0813, 0x01AF, 0x01CF, + 0x0B7E, 0x0033, 0x01DF, 0x0BCE, 0x01BF, 0x036D, 0x0A03, 0x017F, + 0x03BE, 0x0201, 0x0893, 0x038E, 0x034D, 0x03AE, 0x0202, 0x039F, + 0x0291, 0x0A11, 0x032E, 0x033F, 0x034F, 0x0281, 0x037D, 0x03BD, + 0x0212, 0x033E, 0x035E, 0x034E, 0x035D, 0x03AD, 0x032F, 0x038F, 0x039E }; static const uint16_t percentile_arr_8x6_1[186] { - 0x0621,0xFC33,0x37AE,0x1CC2,0x2C43,0xAD32,0x34A3,0x4551, - 0x6452,0x5C62,0x1FCD,0x14F1,0x4CB3,0x24D2,0x15DF,0x0FBE, - 0x2603,0x3DA2,0x2E31,0x25D1,0x25EF,0x0D22,0x2E91,0x1E82, - 0x0FBD,0x1513,0x0CB2,0x0CD1,0x0F4F,0x1F7D,0x1701,0x0C16, - 0x2593,0x2C42,0x0C72,0x14A2,0x0F6E,0x0C35,0x0C71,0x0D83, - 0x0C07,0x1DFF,0x043E,0x1613,0x07DD,0x0FAD,0x1451,0x076D, - 0x0E81,0x05FE,0x0406,0x0E0D,0x045D,0x2612,0x0E02,0x07AF, - 0x0DB1,0x0F5E,0x15C1,0x0C23,0x1523,0x0C1F,0x0D92,0x04B1, - 0x0D31,0x0432,0x0D61,0x0F4E,0x0D41,0x0DEE,0x0D42,0x04C1, - 0x0CE1,0x079F,0x0C2E,0x0405,0x0C22,0x0461,0x0E1D,0x0582, - 0x073F,0x0571,0x0C4D,0x0DFD,0x05CE,0x0C6D,0x05DE,0x0415, - 0x0C45,0x075F,0x0C41,0x0D03,0x05A1,0x0711,0x05CF,0x0425, - 0x0C93,0x0D21,0x0591,0x043D,0x0D12,0x0501,0x040F,0x0511, - 0x0431,0x0C03,0x04A1,0x078D,0x0581,0x041E,0x040D,0x0C02, - 0x040E,0x05DD,0x057F,0x079D,0x042D,0x0D9F,0x0502,0x056E, - 0x0412,0x071F,0x044E,0x05BF,0x0C1D,0x0482,0x05AE,0x042F, - 0x057D,0x0491,0x054E,0x047D,0x0DBE,0x0611,0x0492,0x0601, - 0x05BD,0x05CD,0x0426,0x05ED,0x072D,0x073D,0x0483,0x0F5D, - 0x0421,0x056F,0x053F,0x058E,0x054F,0x078F,0x053E,0x059E, - 0x057E,0x051F,0x055D,0x0413,0x070D,0x05AF,0x0411,0x0453, - 0x0D5E,0x077E,0x052F,0x070F,0x074D,0x0692,0x070E,0x072F, - 0x072E,0x058F,0x071D,0x052E,0x0417,0x073E,0x0781,0x078E, - 0x055F,0x060E,0x0622,0x0683,0x0702,0x071E,0x076F,0x079E, - 0x07BF,0x07CE + 0x0621, 0xFC33, 0x37AE, 0x1CC2, 0x2C43, 0xAD32, 0x34A3, 0x4551, + 0x6452, 0x5C62, 0x1FCD, 0x14F1, 0x4CB3, 0x24D2, 0x15DF, 0x0FBE, + 0x2603, 0x3DA2, 0x2E31, 0x25D1, 0x25EF, 0x0D22, 0x2E91, 0x1E82, + 0x0FBD, 0x1513, 0x0CB2, 0x0CD1, 0x0F4F, 0x1F7D, 0x1701, 0x0C16, + 0x2593, 0x2C42, 0x0C72, 0x14A2, 0x0F6E, 0x0C35, 0x0C71, 0x0D83, + 0x0C07, 0x1DFF, 0x043E, 0x1613, 0x07DD, 0x0FAD, 0x1451, 0x076D, + 0x0E81, 0x05FE, 0x0406, 0x0E0D, 0x045D, 0x2612, 0x0E02, 0x07AF, + 0x0DB1, 0x0F5E, 0x15C1, 0x0C23, 0x1523, 0x0C1F, 0x0D92, 0x04B1, + 0x0D31, 0x0432, 0x0D61, 0x0F4E, 0x0D41, 0x0DEE, 0x0D42, 0x04C1, + 0x0CE1, 0x079F, 0x0C2E, 0x0405, 0x0C22, 0x0461, 0x0E1D, 0x0582, + 0x073F, 0x0571, 0x0C4D, 0x0DFD, 0x05CE, 0x0C6D, 0x05DE, 0x0415, + 0x0C45, 0x075F, 0x0C41, 0x0D03, 0x05A1, 0x0711, 0x05CF, 0x0425, + 0x0C93, 0x0D21, 0x0591, 0x043D, 0x0D12, 0x0501, 0x040F, 0x0511, + 0x0431, 0x0C03, 0x04A1, 0x078D, 0x0581, 0x041E, 0x040D, 0x0C02, + 0x040E, 0x05DD, 0x057F, 0x079D, 0x042D, 0x0D9F, 0x0502, 0x056E, + 0x0412, 0x071F, 0x044E, 0x05BF, 0x0C1D, 0x0482, 0x05AE, 0x042F, + 0x057D, 0x0491, 0x054E, 0x047D, 0x0DBE, 0x0611, 0x0492, 0x0601, + 0x05BD, 0x05CD, 0x0426, 0x05ED, 0x072D, 0x073D, 0x0483, 0x0F5D, + 0x0421, 0x056F, 0x053F, 0x058E, 0x054F, 0x078F, 0x053E, 0x059E, + 0x057E, 0x051F, 0x055D, 0x0413, 0x070D, 0x05AF, 0x0411, 0x0453, + 0x0D5E, 0x077E, 0x052F, 0x070F, 0x074D, 0x0692, 0x070E, 0x072F, + 0x072E, 0x058F, 0x071D, 0x052E, 0x0417, 0x073E, 0x0781, 0x078E, + 0x055F, 0x060E, 0x0622, 0x0683, 0x0702, 0x071E, 0x076F, 0x079E, + 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_8x6 { @@ -432,79 +437,79 @@ static const packed_percentile_table block_pcd_8x6 { #if ASTCENC_BLOCK_MAX_TEXELS >= (8 * 8) static const uint16_t percentile_arr_8x8_0[347] { - 0x0334,0xFD44,0xDD14,0x9154,0x9B08,0x906A,0x8928,0x8108, - 0xE866,0xC918,0x606F,0xC0FE,0x5963,0x58EE,0x6534,0x505A, - 0x51E2,0xA8CF,0x5354,0x5314,0x5134,0x5524,0x48F3,0x504B, - 0x487E,0x5344,0x49C3,0x4972,0x49F2,0x4856,0xD0EF,0x81D2, - 0x78DE,0x4261,0x3AC1,0x71E3,0x6879,0x390C,0x3143,0x31B3, - 0x385F,0x3153,0x306E,0x3037,0x30DF,0x3162,0x304F,0x3075, - 0xB03B,0x2847,0x28E3,0x2914,0x507F,0x28BF,0x5173,0x5073, - 0x20D3,0x2A06,0x2827,0x2508,0x2229,0x29D3,0x204A,0x207A, - 0x2046,0x4148,0x20FD,0x4225,0x23A1,0x3944,0x2065,0x1924, - 0x2324,0x1806,0x19F1,0x2215,0x1876,0x22AD,0x502B,0x1B04, - 0x18F2,0x3A4D,0x3216,0x3504,0x18DD,0x1B21,0x10CE,0x1869, - 0x1B41,0x1855,0x1207,0x1AE1,0x2845,0x19D1,0x2A0A,0x1A2D, - 0x2A1A,0x11C2,0x1A0B,0x1217,0x2816,0x121B,0x1271,0x2AD1, - 0x1035,0x1015,0x287D,0x12F1,0x43C1,0x1171,0x1A05,0x08E2, - 0x11E1,0x3251,0x2049,0x20F1,0x12CD,0x0A39,0x1219,0x1059, - 0x1104,0x1036,0x1872,0x3007,0x08ED,0x205E,0x1026,0x0952, - 0x1392,0x1019,0x0951,0x100A,0x13EE,0x08D2,0x1242,0x0ABD, - 0x22A2,0x0BDF,0x2B81,0x0A35,0x13B1,0x0839,0x13BF,0x0A33, - 0x1B31,0x205D,0x1241,0x183A,0x2025,0x0B93,0x0A3D,0x1017, - 0x1313,0x1253,0x082A,0x204E,0x09A2,0x080B,0x0A1F,0x125D, - 0x0A2E,0x081A,0x08D1,0x082F,0x086D,0x1B82,0x0A09,0x0B22, - 0x1062,0x11A3,0x2161,0x0923,0x129F,0x1A62,0x0871,0x0942, - 0x081B,0x1133,0x18AE,0x0A9E,0x0863,0x09FF,0x18C2,0x0B51, - 0x08BD,0x0AA3,0x09B1,0x1AC2,0x08B3,0x0829,0x0BEF,0x0B83, - 0x0AAE,0x0A8D,0x1857,0x185B,0x08AF,0x103F,0x08C3,0x09B2, - 0x0A4E,0x11C1,0x0A31,0x0B42,0x0A83,0x0BFF,0x13DD,0x00CD, - 0x0AB3,0x0842,0x08BE,0x0922,0x1A8E,0x08E1,0x002E,0x0BA2, - 0x0A8F,0x2263,0x0252,0x0B32,0x0AC3,0x0941,0x0A43,0x083D, - 0x083E,0x0A3E,0x084D,0x1131,0x136F,0x0AB1,0x0193,0x0BFD, - 0x0391,0x0851,0x13AF,0x0843,0x0213,0x1226,0x0932,0x03B2, - 0x0902,0x0BCD,0x0221,0x089E,0x00B1,0x0BDE,0x03FE,0x02A1, - 0x0982,0x009F,0x080E,0x0B5F,0x02BE,0x0A32,0x0A2A,0x01EE, - 0x0053,0x0AB2,0x0192,0x09FD,0x0052,0x0B03,0x0293,0x00A2, - 0x0B7F,0x0BED,0x0311,0x08B2,0x0A72,0x088E,0x0333,0x0B12, - 0x0A23,0x0822,0x0083,0x11CE,0x021D,0x08A3,0x088F,0x029D, - 0x0A22,0x0A3F,0x01FE,0x020F,0x0983,0x02D2,0x0292,0x0B23, - 0x001E,0x0BCF,0x03CE,0x09AF,0x0B02,0x0301,0x022F,0x137E, - 0x021E,0x09EF,0x016F,0x0112,0x097E,0x080F,0x020D,0x0092, - 0x01DE,0x09DF,0x0032,0x0033,0x0A82,0x03BE,0x0B6E,0x001F, - 0x020E,0x0023,0x09CF,0x0113,0x0103,0x0013,0x0BAE,0x0203, - 0x0BAD,0x01BF,0x034F,0x095F,0x036D,0x0202,0x017F,0x0093, - 0x0201,0x034D,0x0212,0x035D,0x03BD,0x0B3F,0x035E,0x0211, - 0x0281,0x0291,0x032E,0x037D,0x034E,0x038E,0x039F,0x032F, - 0x033E,0x038F,0x039E + 0x0334, 0xFD44, 0xDD14, 0x9154, 0x9B08, 0x906A, 0x8928, 0x8108, + 0xE866, 0xC918, 0x606F, 0xC0FE, 0x5963, 0x58EE, 0x6534, 0x505A, + 0x51E2, 0xA8CF, 0x5354, 0x5314, 0x5134, 0x5524, 0x48F3, 0x504B, + 0x487E, 0x5344, 0x49C3, 0x4972, 0x49F2, 0x4856, 0xD0EF, 0x81D2, + 0x78DE, 0x4261, 0x3AC1, 0x71E3, 0x6879, 0x390C, 0x3143, 0x31B3, + 0x385F, 0x3153, 0x306E, 0x3037, 0x30DF, 0x3162, 0x304F, 0x3075, + 0xB03B, 0x2847, 0x28E3, 0x2914, 0x507F, 0x28BF, 0x5173, 0x5073, + 0x20D3, 0x2A06, 0x2827, 0x2508, 0x2229, 0x29D3, 0x204A, 0x207A, + 0x2046, 0x4148, 0x20FD, 0x4225, 0x23A1, 0x3944, 0x2065, 0x1924, + 0x2324, 0x1806, 0x19F1, 0x2215, 0x1876, 0x22AD, 0x502B, 0x1B04, + 0x18F2, 0x3A4D, 0x3216, 0x3504, 0x18DD, 0x1B21, 0x10CE, 0x1869, + 0x1B41, 0x1855, 0x1207, 0x1AE1, 0x2845, 0x19D1, 0x2A0A, 0x1A2D, + 0x2A1A, 0x11C2, 0x1A0B, 0x1217, 0x2816, 0x121B, 0x1271, 0x2AD1, + 0x1035, 0x1015, 0x287D, 0x12F1, 0x43C1, 0x1171, 0x1A05, 0x08E2, + 0x11E1, 0x3251, 0x2049, 0x20F1, 0x12CD, 0x0A39, 0x1219, 0x1059, + 0x1104, 0x1036, 0x1872, 0x3007, 0x08ED, 0x205E, 0x1026, 0x0952, + 0x1392, 0x1019, 0x0951, 0x100A, 0x13EE, 0x08D2, 0x1242, 0x0ABD, + 0x22A2, 0x0BDF, 0x2B81, 0x0A35, 0x13B1, 0x0839, 0x13BF, 0x0A33, + 0x1B31, 0x205D, 0x1241, 0x183A, 0x2025, 0x0B93, 0x0A3D, 0x1017, + 0x1313, 0x1253, 0x082A, 0x204E, 0x09A2, 0x080B, 0x0A1F, 0x125D, + 0x0A2E, 0x081A, 0x08D1, 0x082F, 0x086D, 0x1B82, 0x0A09, 0x0B22, + 0x1062, 0x11A3, 0x2161, 0x0923, 0x129F, 0x1A62, 0x0871, 0x0942, + 0x081B, 0x1133, 0x18AE, 0x0A9E, 0x0863, 0x09FF, 0x18C2, 0x0B51, + 0x08BD, 0x0AA3, 0x09B1, 0x1AC2, 0x08B3, 0x0829, 0x0BEF, 0x0B83, + 0x0AAE, 0x0A8D, 0x1857, 0x185B, 0x08AF, 0x103F, 0x08C3, 0x09B2, + 0x0A4E, 0x11C1, 0x0A31, 0x0B42, 0x0A83, 0x0BFF, 0x13DD, 0x00CD, + 0x0AB3, 0x0842, 0x08BE, 0x0922, 0x1A8E, 0x08E1, 0x002E, 0x0BA2, + 0x0A8F, 0x2263, 0x0252, 0x0B32, 0x0AC3, 0x0941, 0x0A43, 0x083D, + 0x083E, 0x0A3E, 0x084D, 0x1131, 0x136F, 0x0AB1, 0x0193, 0x0BFD, + 0x0391, 0x0851, 0x13AF, 0x0843, 0x0213, 0x1226, 0x0932, 0x03B2, + 0x0902, 0x0BCD, 0x0221, 0x089E, 0x00B1, 0x0BDE, 0x03FE, 0x02A1, + 0x0982, 0x009F, 0x080E, 0x0B5F, 0x02BE, 0x0A32, 0x0A2A, 0x01EE, + 0x0053, 0x0AB2, 0x0192, 0x09FD, 0x0052, 0x0B03, 0x0293, 0x00A2, + 0x0B7F, 0x0BED, 0x0311, 0x08B2, 0x0A72, 0x088E, 0x0333, 0x0B12, + 0x0A23, 0x0822, 0x0083, 0x11CE, 0x021D, 0x08A3, 0x088F, 0x029D, + 0x0A22, 0x0A3F, 0x01FE, 0x020F, 0x0983, 0x02D2, 0x0292, 0x0B23, + 0x001E, 0x0BCF, 0x03CE, 0x09AF, 0x0B02, 0x0301, 0x022F, 0x137E, + 0x021E, 0x09EF, 0x016F, 0x0112, 0x097E, 0x080F, 0x020D, 0x0092, + 0x01DE, 0x09DF, 0x0032, 0x0033, 0x0A82, 0x03BE, 0x0B6E, 0x001F, + 0x020E, 0x0023, 0x09CF, 0x0113, 0x0103, 0x0013, 0x0BAE, 0x0203, + 0x0BAD, 0x01BF, 0x034F, 0x095F, 0x036D, 0x0202, 0x017F, 0x0093, + 0x0201, 0x034D, 0x0212, 0x035D, 0x03BD, 0x0B3F, 0x035E, 0x0211, + 0x0281, 0x0291, 0x032E, 0x037D, 0x034E, 0x038E, 0x039F, 0x032F, + 0x033E, 0x038F, 0x039E }; static const uint16_t percentile_arr_8x8_1[208] { - 0x0621,0x3443,0x47CD,0x97AE,0xFC62,0x14F1,0x24C2,0x25DF, - 0x3C33,0x1C52,0x9C72,0x0FBE,0x0C5D,0x343E,0x24A3,0x1551, - 0x5D32,0x1CD2,0x15EF,0x4E31,0x04DD,0x1FDD,0x174F,0x0DD1, - 0x3E0D,0x15FF,0x0DA2,0x1E03,0x17BD,0x177D,0x14B3,0x0471, - 0x0CAE,0x1C1F,0x04D1,0x0F6E,0x0DFE,0x1C42,0x0C16,0x0D22, - 0x0C9F,0x2C2E,0x0FAD,0x0571,0x147D,0x0C07,0x04B2,0x0F6D, - 0x0F5E,0x07AF,0x146D,0x0C51,0x0593,0x2583,0x0C4E,0x040B, - 0x0C35,0x0513,0x0E91,0x0406,0x073F,0x144D,0x0561,0x048F, - 0x0F01,0x0F4E,0x0CA2,0x075F,0x1682,0x04E1,0x0C1A,0x04BD, - 0x0542,0x0D41,0x0DEE,0x04CD,0x0DCF,0x04B1,0x0C15,0x0C3D, - 0x0423,0x0592,0x0DDE,0x0422,0x0432,0x05FD,0x0DC1,0x05B1, - 0x0DCE,0x0612,0x0C2F,0x0445,0x0602,0x0531,0x0439,0x0E81, - 0x0582,0x0C61,0x061D,0x049E,0x0405,0x0409,0x0DBE,0x079F, - 0x0D21,0x04C1,0x0C0A,0x0E13,0x04AD,0x040E,0x0581,0x0419, - 0x05DD,0x0D03,0x049D,0x0449,0x0429,0x048E,0x0DA1,0x0425, - 0x0512,0x0501,0x0431,0x0523,0x0441,0x042D,0x040F,0x0D7D, - 0x0511,0x0502,0x05BF,0x04A1,0x0C03,0x0402,0x079D,0x05AE, - 0x075D,0x057F,0x041D,0x048D,0x042A,0x0453,0x05AF,0x078D, - 0x0C0D,0x073D,0x0491,0x0591,0x05BD,0x072D,0x057E,0x051F, - 0x0482,0x0492,0x041E,0x0412,0x0D9F,0x0421,0x0493,0x0711, - 0x056E,0x059E,0x054E,0x0611,0x05ED,0x074D,0x070F,0x056F, - 0x052F,0x053F,0x071F,0x054F,0x05CD,0x0483,0x055E,0x072F, - 0x0E01,0x0426,0x058F,0x0413,0x078F,0x071D,0x055F,0x058E, - 0x0411,0x053E,0x071E,0x055D,0x077E,0x052E,0x0692,0x0417, - 0x070D,0x078E,0x070E,0x072E,0x041B,0x060E,0x0622,0x0683, - 0x068D,0x0702,0x073E,0x076F,0x0781,0x079E,0x07BF,0x07CE + 0x0621, 0x3443, 0x47CD, 0x97AE, 0xFC62, 0x14F1, 0x24C2, 0x25DF, + 0x3C33, 0x1C52, 0x9C72, 0x0FBE, 0x0C5D, 0x343E, 0x24A3, 0x1551, + 0x5D32, 0x1CD2, 0x15EF, 0x4E31, 0x04DD, 0x1FDD, 0x174F, 0x0DD1, + 0x3E0D, 0x15FF, 0x0DA2, 0x1E03, 0x17BD, 0x177D, 0x14B3, 0x0471, + 0x0CAE, 0x1C1F, 0x04D1, 0x0F6E, 0x0DFE, 0x1C42, 0x0C16, 0x0D22, + 0x0C9F, 0x2C2E, 0x0FAD, 0x0571, 0x147D, 0x0C07, 0x04B2, 0x0F6D, + 0x0F5E, 0x07AF, 0x146D, 0x0C51, 0x0593, 0x2583, 0x0C4E, 0x040B, + 0x0C35, 0x0513, 0x0E91, 0x0406, 0x073F, 0x144D, 0x0561, 0x048F, + 0x0F01, 0x0F4E, 0x0CA2, 0x075F, 0x1682, 0x04E1, 0x0C1A, 0x04BD, + 0x0542, 0x0D41, 0x0DEE, 0x04CD, 0x0DCF, 0x04B1, 0x0C15, 0x0C3D, + 0x0423, 0x0592, 0x0DDE, 0x0422, 0x0432, 0x05FD, 0x0DC1, 0x05B1, + 0x0DCE, 0x0612, 0x0C2F, 0x0445, 0x0602, 0x0531, 0x0439, 0x0E81, + 0x0582, 0x0C61, 0x061D, 0x049E, 0x0405, 0x0409, 0x0DBE, 0x079F, + 0x0D21, 0x04C1, 0x0C0A, 0x0E13, 0x04AD, 0x040E, 0x0581, 0x0419, + 0x05DD, 0x0D03, 0x049D, 0x0449, 0x0429, 0x048E, 0x0DA1, 0x0425, + 0x0512, 0x0501, 0x0431, 0x0523, 0x0441, 0x042D, 0x040F, 0x0D7D, + 0x0511, 0x0502, 0x05BF, 0x04A1, 0x0C03, 0x0402, 0x079D, 0x05AE, + 0x075D, 0x057F, 0x041D, 0x048D, 0x042A, 0x0453, 0x05AF, 0x078D, + 0x0C0D, 0x073D, 0x0491, 0x0591, 0x05BD, 0x072D, 0x057E, 0x051F, + 0x0482, 0x0492, 0x041E, 0x0412, 0x0D9F, 0x0421, 0x0493, 0x0711, + 0x056E, 0x059E, 0x054E, 0x0611, 0x05ED, 0x074D, 0x070F, 0x056F, + 0x052F, 0x053F, 0x071F, 0x054F, 0x05CD, 0x0483, 0x055E, 0x072F, + 0x0E01, 0x0426, 0x058F, 0x0413, 0x078F, 0x071D, 0x055F, 0x058E, + 0x0411, 0x053E, 0x071E, 0x055D, 0x077E, 0x052E, 0x0692, 0x0417, + 0x070D, 0x078E, 0x070E, 0x072E, 0x041B, 0x060E, 0x0622, 0x0683, + 0x068D, 0x0702, 0x073E, 0x076F, 0x0781, 0x079E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_8x8 { @@ -518,67 +523,67 @@ static const packed_percentile_table block_pcd_8x8 { #if ASTCENC_BLOCK_MAX_TEXELS >= (10 * 5) static const uint16_t percentile_arr_10x5_0[274] { - 0x0165,0xF975,0xD866,0xC056,0xA946,0x90C6,0x90F5,0x8963, - 0x80D6,0x80E6,0x60F3,0x61C3,0x59F2,0xA927,0x5075,0x4847, - 0x5153,0x4955,0x49E2,0x48B6,0x41D2,0x4943,0x8305,0x8172, - 0x4046,0x4037,0x40A7,0x70B7,0x7AC1,0x31E3,0x7027,0x30E5, - 0x69D3,0x99B3,0x3315,0x6115,0x3136,0x3076,0x3173,0x30D5, - 0x3106,0x8962,0x2916,0x30C7,0x5126,0x30D3,0x2956,0x5117, - 0x2B41,0x2AE1,0x2A61,0x29F1,0x2306,0x2145,0x4A85,0x2057, - 0x40E3,0x4137,0x3B21,0x23C1,0x2065,0x1925,0x51C2,0x5225, - 0x4935,0x1AD1,0x23A1,0x19D1,0x1A71,0x4055,0x1873,0x1A86, - 0x1295,0x18F2,0x28A6,0x1952,0x4AA5,0x20B5,0x10C5,0x2AA2, - 0x11E1,0x1107,0x10D2,0x2171,0x1351,0x3036,0x1331,0x1BEE, - 0x2035,0x1045,0x1313,0x0A15,0x1087,0x1296,0x13EF,0x18E2, - 0x1151,0x1086,0x10F1,0x08A5,0x12C2,0x1BFF,0x1095,0x1A62, - 0x1322,0x0942,0x1026,0x1872,0x1062,0x0897,0x1123,0x08D1, - 0x1A06,0x0806,0x137F,0x13B1,0x13DF,0x1A51,0x09B1,0x0A83, - 0x1015,0x22F1,0x0961,0x0B81,0x12B3,0x0A35,0x0AA3,0x20B3, - 0x08C3,0x2342,0x0933,0x0A33,0x09A2,0x10C2,0x0896,0x2205, - 0x0825,0x20E1,0x0922,0x1242,0x0B16,0x0B32,0x09A3,0x0AC3, - 0x0BBF,0x0B93,0x0071,0x0931,0x0A41,0x2392,0x13FE,0x09C1, - 0x0B07,0x0016,0x1182,0x09B2,0x0A26,0x0132,0x0941,0x0A93, - 0x0992,0x1063,0x1217,0x01FF,0x11EE,0x1216,0x0B23,0x0B82, - 0x0042,0x1102,0x0213,0x0B6F,0x09FE,0x1207,0x0807,0x18B1, - 0x0253,0x0AB1,0x08A2,0x13FD,0x01FD,0x1983,0x0AB2,0x0A31, - 0x016F,0x0B11,0x00B2,0x0851,0x0AD2,0x0993,0x0BDD,0x12A1, - 0x017F,0x0A97,0x1022,0x0383,0x0843,0x0A52,0x03A2,0x097E, - 0x0817,0x03B2,0x0A43,0x09EF,0x0A63,0x0B33,0x0B03,0x0292, - 0x0272,0x09CE,0x0287,0x136D,0x0053,0x0B12,0x0083,0x0892, - 0x0112,0x1282,0x03ED,0x0852,0x0301,0x1391,0x0232,0x0B7E, - 0x0221,0x08A3,0x0BCD,0x0BCF,0x036E,0x09DE,0x0103,0x03DE, - 0x0832,0x0BAF,0x0302,0x13CE,0x035F,0x0093,0x0A23,0x01DF, - 0x0013,0x0A22,0x0023,0x0113,0x09AF,0x01BF,0x0033,0x095F, - 0x0203,0x0281,0x09CF,0x037D,0x0201,0x0B4D,0x03AE,0x03BE, - 0x0291,0x035E,0x038E,0x0B9F,0x03AD,0x0202,0x034F,0x0211, - 0x035D,0x0212,0x032E,0x039E,0x033F,0x034E,0x03BD,0x032F, - 0x033E,0x038F + 0x0165, 0xF975, 0xD866, 0xC056, 0xA946, 0x90C6, 0x90F5, 0x8963, + 0x80D6, 0x80E6, 0x60F3, 0x61C3, 0x59F2, 0xA927, 0x5075, 0x4847, + 0x5153, 0x4955, 0x49E2, 0x48B6, 0x41D2, 0x4943, 0x8305, 0x8172, + 0x4046, 0x4037, 0x40A7, 0x70B7, 0x7AC1, 0x31E3, 0x7027, 0x30E5, + 0x69D3, 0x99B3, 0x3315, 0x6115, 0x3136, 0x3076, 0x3173, 0x30D5, + 0x3106, 0x8962, 0x2916, 0x30C7, 0x5126, 0x30D3, 0x2956, 0x5117, + 0x2B41, 0x2AE1, 0x2A61, 0x29F1, 0x2306, 0x2145, 0x4A85, 0x2057, + 0x40E3, 0x4137, 0x3B21, 0x23C1, 0x2065, 0x1925, 0x51C2, 0x5225, + 0x4935, 0x1AD1, 0x23A1, 0x19D1, 0x1A71, 0x4055, 0x1873, 0x1A86, + 0x1295, 0x18F2, 0x28A6, 0x1952, 0x4AA5, 0x20B5, 0x10C5, 0x2AA2, + 0x11E1, 0x1107, 0x10D2, 0x2171, 0x1351, 0x3036, 0x1331, 0x1BEE, + 0x2035, 0x1045, 0x1313, 0x0A15, 0x1087, 0x1296, 0x13EF, 0x18E2, + 0x1151, 0x1086, 0x10F1, 0x08A5, 0x12C2, 0x1BFF, 0x1095, 0x1A62, + 0x1322, 0x0942, 0x1026, 0x1872, 0x1062, 0x0897, 0x1123, 0x08D1, + 0x1A06, 0x0806, 0x137F, 0x13B1, 0x13DF, 0x1A51, 0x09B1, 0x0A83, + 0x1015, 0x22F1, 0x0961, 0x0B81, 0x12B3, 0x0A35, 0x0AA3, 0x20B3, + 0x08C3, 0x2342, 0x0933, 0x0A33, 0x09A2, 0x10C2, 0x0896, 0x2205, + 0x0825, 0x20E1, 0x0922, 0x1242, 0x0B16, 0x0B32, 0x09A3, 0x0AC3, + 0x0BBF, 0x0B93, 0x0071, 0x0931, 0x0A41, 0x2392, 0x13FE, 0x09C1, + 0x0B07, 0x0016, 0x1182, 0x09B2, 0x0A26, 0x0132, 0x0941, 0x0A93, + 0x0992, 0x1063, 0x1217, 0x01FF, 0x11EE, 0x1216, 0x0B23, 0x0B82, + 0x0042, 0x1102, 0x0213, 0x0B6F, 0x09FE, 0x1207, 0x0807, 0x18B1, + 0x0253, 0x0AB1, 0x08A2, 0x13FD, 0x01FD, 0x1983, 0x0AB2, 0x0A31, + 0x016F, 0x0B11, 0x00B2, 0x0851, 0x0AD2, 0x0993, 0x0BDD, 0x12A1, + 0x017F, 0x0A97, 0x1022, 0x0383, 0x0843, 0x0A52, 0x03A2, 0x097E, + 0x0817, 0x03B2, 0x0A43, 0x09EF, 0x0A63, 0x0B33, 0x0B03, 0x0292, + 0x0272, 0x09CE, 0x0287, 0x136D, 0x0053, 0x0B12, 0x0083, 0x0892, + 0x0112, 0x1282, 0x03ED, 0x0852, 0x0301, 0x1391, 0x0232, 0x0B7E, + 0x0221, 0x08A3, 0x0BCD, 0x0BCF, 0x036E, 0x09DE, 0x0103, 0x03DE, + 0x0832, 0x0BAF, 0x0302, 0x13CE, 0x035F, 0x0093, 0x0A23, 0x01DF, + 0x0013, 0x0A22, 0x0023, 0x0113, 0x09AF, 0x01BF, 0x0033, 0x095F, + 0x0203, 0x0281, 0x09CF, 0x037D, 0x0201, 0x0B4D, 0x03AE, 0x03BE, + 0x0291, 0x035E, 0x038E, 0x0B9F, 0x03AD, 0x0202, 0x034F, 0x0211, + 0x035D, 0x0212, 0x032E, 0x039E, 0x033F, 0x034E, 0x03BD, 0x032F, + 0x033E, 0x038F }; static const uint16_t percentile_arr_10x5_1[180] { - 0x0532,0xFCA3,0x3621,0x6E82,0x2CC2,0x3D51,0x3F01,0x2691, - 0x17AE,0x35A2,0x74B3,0x1603,0x4433,0x3C43,0x6C35,0x25D1, - 0x1D13,0x15DF,0x37CD,0x0D93,0x1D22,0x0E81,0x1452,0x0CD2, - 0x37BE,0x0CB2,0x3407,0x1523,0x0C16,0x0CB5,0x0C96,0x1486, - 0x2631,0x1506,0x0F4F,0x1583,0x0CD1,0x2CA2,0x2612,0x1613, - 0x1602,0x1F11,0x179F,0x17BD,0x15B1,0x0406,0x1D41,0x0CF1, - 0x0D31,0x0442,0x1C62,0x0F6E,0x077D,0x0C51,0x0445,0x0D15, - 0x2592,0x0CB1,0x05EF,0x0542,0x17AF,0x1425,0x075E,0x0FAD, - 0x0CC1,0x0503,0x0512,0x15C1,0x0C95,0x0415,0x0505,0x0F4E, - 0x04A5,0x0493,0x0C32,0x0F5F,0x04E1,0x0521,0x0C85,0x07DD, - 0x0582,0x15FF,0x05CF,0x0405,0x0D91,0x05A1,0x05FE,0x0C23, - 0x0561,0x0472,0x0471,0x0C22,0x0DEE,0x076D,0x0502,0x0426, - 0x0C61,0x0D7D,0x0525,0x05DE,0x0DCE,0x079D,0x0692,0x0441, - 0x0C91,0x05DD,0x0511,0x057F,0x0611,0x0DFD,0x078D,0x056E, - 0x0492,0x04A1,0x073F,0x0C31,0x05BE,0x0483,0x0571,0x056F, - 0x0D9F,0x0581,0x0501,0x057E,0x05BF,0x078F,0x0516,0x05ED, - 0x0402,0x0F7E,0x0482,0x054E,0x075D,0x071F,0x05CD,0x0535, - 0x05AE,0x0C11,0x058F,0x05AF,0x0421,0x0413,0x0601,0x054F, - 0x073D,0x059E,0x0487,0x070F,0x078E,0x0781,0x053E,0x0403, - 0x072D,0x055D,0x05BD,0x079E,0x0D8E,0x0412,0x052E,0x074D, - 0x053F,0x051F,0x070E,0x055F,0x072F,0x052F,0x070D,0x055E, - 0x0417,0x0453,0x072E,0x0622,0x0683,0x0702,0x071D,0x071E, - 0x073E,0x076F,0x07BF,0x07CE + 0x0532, 0xFCA3, 0x3621, 0x6E82, 0x2CC2, 0x3D51, 0x3F01, 0x2691, + 0x17AE, 0x35A2, 0x74B3, 0x1603, 0x4433, 0x3C43, 0x6C35, 0x25D1, + 0x1D13, 0x15DF, 0x37CD, 0x0D93, 0x1D22, 0x0E81, 0x1452, 0x0CD2, + 0x37BE, 0x0CB2, 0x3407, 0x1523, 0x0C16, 0x0CB5, 0x0C96, 0x1486, + 0x2631, 0x1506, 0x0F4F, 0x1583, 0x0CD1, 0x2CA2, 0x2612, 0x1613, + 0x1602, 0x1F11, 0x179F, 0x17BD, 0x15B1, 0x0406, 0x1D41, 0x0CF1, + 0x0D31, 0x0442, 0x1C62, 0x0F6E, 0x077D, 0x0C51, 0x0445, 0x0D15, + 0x2592, 0x0CB1, 0x05EF, 0x0542, 0x17AF, 0x1425, 0x075E, 0x0FAD, + 0x0CC1, 0x0503, 0x0512, 0x15C1, 0x0C95, 0x0415, 0x0505, 0x0F4E, + 0x04A5, 0x0493, 0x0C32, 0x0F5F, 0x04E1, 0x0521, 0x0C85, 0x07DD, + 0x0582, 0x15FF, 0x05CF, 0x0405, 0x0D91, 0x05A1, 0x05FE, 0x0C23, + 0x0561, 0x0472, 0x0471, 0x0C22, 0x0DEE, 0x076D, 0x0502, 0x0426, + 0x0C61, 0x0D7D, 0x0525, 0x05DE, 0x0DCE, 0x079D, 0x0692, 0x0441, + 0x0C91, 0x05DD, 0x0511, 0x057F, 0x0611, 0x0DFD, 0x078D, 0x056E, + 0x0492, 0x04A1, 0x073F, 0x0C31, 0x05BE, 0x0483, 0x0571, 0x056F, + 0x0D9F, 0x0581, 0x0501, 0x057E, 0x05BF, 0x078F, 0x0516, 0x05ED, + 0x0402, 0x0F7E, 0x0482, 0x054E, 0x075D, 0x071F, 0x05CD, 0x0535, + 0x05AE, 0x0C11, 0x058F, 0x05AF, 0x0421, 0x0413, 0x0601, 0x054F, + 0x073D, 0x059E, 0x0487, 0x070F, 0x078E, 0x0781, 0x053E, 0x0403, + 0x072D, 0x055D, 0x05BD, 0x079E, 0x0D8E, 0x0412, 0x052E, 0x074D, + 0x053F, 0x051F, 0x070E, 0x055F, 0x072F, 0x052F, 0x070D, 0x055E, + 0x0417, 0x0453, 0x072E, 0x0622, 0x0683, 0x0702, 0x071D, 0x071E, + 0x073E, 0x076F, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_10x5 { @@ -592,75 +597,75 @@ static const packed_percentile_table block_pcd_10x5 { #if ASTCENC_BLOCK_MAX_TEXELS >= (10 * 6) static const uint16_t percentile_arr_10x6_0[325] { - 0x01A4,0xF954,0xA066,0x9975,0x80F5,0x7056,0x6918,0x6963, - 0x58C6,0x5946,0x5928,0x5174,0x586F,0xA0E6,0x5108,0x48D6, - 0x49E2,0x40F3,0x9172,0x41F2,0xB875,0x3927,0x39C3,0xA953, - 0x3934,0x3305,0x30B6,0x6943,0x31D2,0x3876,0x3037,0x2955, - 0x30A7,0x32C1,0x29B3,0x3027,0x287E,0x30B7,0x29E3,0x5846, - 0x2B15,0x2847,0x3162,0x5173,0x4936,0x285F,0x48D3,0x2164, - 0x4906,0x20E5,0x2915,0x2116,0x407F,0x20D5,0x2A61,0x4117, - 0x20E3,0x2126,0x4148,0x206E,0x39D3,0x2145,0x41B4,0x1B06, - 0x2114,0x2165,0x5321,0x5A85,0x1A4D,0x1A1F,0x19F1,0x3341, - 0x184F,0x1956,0x3125,0x30C7,0x28F2,0x1937,0x1AE1,0x1073, - 0x1BA1,0x1935,0x110C,0x1BC1,0x3A25,0x19C2,0x1295,0x122E, - 0x1944,0x11D1,0x1124,0x1857,0x22D1,0x2286,0x1A2D,0x12A2, - 0x2107,0x1055,0x2065,0x0A71,0x2152,0x10C5,0x10D2,0x1331, - 0x08B5,0x1171,0x2836,0x10A6,0x0904,0x123D,0x20F1,0x12A5, - 0x10E2,0x107D,0x1AF1,0x1313,0x0951,0x11E1,0x1B22,0x1B51, - 0x0835,0x101E,0x0A5D,0x0A15,0x3045,0x0A96,0x08A5,0x1142, - 0x12A3,0x1872,0x085D,0x09B1,0x100E,0x0887,0x0886,0x086D, - 0x0933,0x12B3,0x0897,0x08B3,0x0A33,0x0923,0x1095,0x0BEE, - 0x2BB1,0x085E,0x1283,0x0A51,0x1026,0x0A06,0x12C2,0x08D1, - 0x11A2,0x13BF,0x08C3,0x10C2,0x0A3E,0x0BDF,0x0B81,0x13EF, - 0x0A35,0x0B16,0x082F,0x2161,0x1B32,0x0806,0x084E,0x11A3, - 0x1015,0x1122,0x2931,0x0342,0x0825,0x0A0F,0x0896,0x0A05, - 0x0241,0x09C1,0x083F,0x0A42,0x0071,0x0B07,0x082E,0x0393, - 0x12B1,0x0A62,0x0226,0x0A2F,0x0B92,0x0063,0x0932,0x0862, - 0x09FF,0x0A31,0x00E1,0x12B2,0x09B2,0x0AC3,0x0941,0x0293, - 0x1323,0x104D,0x003E,0x083D,0x0992,0x1382,0x03FF,0x0A13, - 0x1016,0x0A53,0x0182,0x1007,0x0AA1,0x080F,0x0A16,0x0A1E, - 0x0042,0x0902,0x13DD,0x0BB2,0x0A63,0x00A2,0x08B1,0x03FE, - 0x1207,0x08B2,0x0B83,0x09EE,0x0311,0x0A87,0x0BAF,0x03A2, - 0x09FD,0x0051,0x0B33,0x020D,0x09CE,0x0217,0x021D,0x0817, - 0x020E,0x0A4E,0x001F,0x0BFD,0x0297,0x0983,0x0A92,0x0252, - 0x0243,0x0B03,0x0193,0x036F,0x0B12,0x0043,0x0822,0x0A21, - 0x01FE,0x0853,0x037F,0x023F,0x0BED,0x02D2,0x0B91,0x0232, - 0x0282,0x0912,0x08A3,0x0852,0x0223,0x0BCD,0x0083,0x0301, - 0x0832,0x01EF,0x0892,0x0302,0x0A72,0x03DE,0x0893,0x0BCF, - 0x09DE,0x03CE,0x035F,0x0833,0x0023,0x0103,0x017E,0x0813, - 0x01CF,0x01BF,0x016F,0x0A22,0x037E,0x0113,0x01AF,0x0B6E, - 0x03BE,0x0201,0x0A03,0x01DF,0x036D,0x03AE,0x015F,0x0281, - 0x033E,0x0A02,0x038E,0x017F,0x0291,0x034D,0x03BD,0x0B7D, - 0x03AD,0x0211,0x0212,0x034F,0x032E,0x039F,0x034E,0x035D, - 0x035E,0x033F,0x039E,0x032F,0x038F + 0x01A4, 0xF954, 0xA066, 0x9975, 0x80F5, 0x7056, 0x6918, 0x6963, + 0x58C6, 0x5946, 0x5928, 0x5174, 0x586F, 0xA0E6, 0x5108, 0x48D6, + 0x49E2, 0x40F3, 0x9172, 0x41F2, 0xB875, 0x3927, 0x39C3, 0xA953, + 0x3934, 0x3305, 0x30B6, 0x6943, 0x31D2, 0x3876, 0x3037, 0x2955, + 0x30A7, 0x32C1, 0x29B3, 0x3027, 0x287E, 0x30B7, 0x29E3, 0x5846, + 0x2B15, 0x2847, 0x3162, 0x5173, 0x4936, 0x285F, 0x48D3, 0x2164, + 0x4906, 0x20E5, 0x2915, 0x2116, 0x407F, 0x20D5, 0x2A61, 0x4117, + 0x20E3, 0x2126, 0x4148, 0x206E, 0x39D3, 0x2145, 0x41B4, 0x1B06, + 0x2114, 0x2165, 0x5321, 0x5A85, 0x1A4D, 0x1A1F, 0x19F1, 0x3341, + 0x184F, 0x1956, 0x3125, 0x30C7, 0x28F2, 0x1937, 0x1AE1, 0x1073, + 0x1BA1, 0x1935, 0x110C, 0x1BC1, 0x3A25, 0x19C2, 0x1295, 0x122E, + 0x1944, 0x11D1, 0x1124, 0x1857, 0x22D1, 0x2286, 0x1A2D, 0x12A2, + 0x2107, 0x1055, 0x2065, 0x0A71, 0x2152, 0x10C5, 0x10D2, 0x1331, + 0x08B5, 0x1171, 0x2836, 0x10A6, 0x0904, 0x123D, 0x20F1, 0x12A5, + 0x10E2, 0x107D, 0x1AF1, 0x1313, 0x0951, 0x11E1, 0x1B22, 0x1B51, + 0x0835, 0x101E, 0x0A5D, 0x0A15, 0x3045, 0x0A96, 0x08A5, 0x1142, + 0x12A3, 0x1872, 0x085D, 0x09B1, 0x100E, 0x0887, 0x0886, 0x086D, + 0x0933, 0x12B3, 0x0897, 0x08B3, 0x0A33, 0x0923, 0x1095, 0x0BEE, + 0x2BB1, 0x085E, 0x1283, 0x0A51, 0x1026, 0x0A06, 0x12C2, 0x08D1, + 0x11A2, 0x13BF, 0x08C3, 0x10C2, 0x0A3E, 0x0BDF, 0x0B81, 0x13EF, + 0x0A35, 0x0B16, 0x082F, 0x2161, 0x1B32, 0x0806, 0x084E, 0x11A3, + 0x1015, 0x1122, 0x2931, 0x0342, 0x0825, 0x0A0F, 0x0896, 0x0A05, + 0x0241, 0x09C1, 0x083F, 0x0A42, 0x0071, 0x0B07, 0x082E, 0x0393, + 0x12B1, 0x0A62, 0x0226, 0x0A2F, 0x0B92, 0x0063, 0x0932, 0x0862, + 0x09FF, 0x0A31, 0x00E1, 0x12B2, 0x09B2, 0x0AC3, 0x0941, 0x0293, + 0x1323, 0x104D, 0x003E, 0x083D, 0x0992, 0x1382, 0x03FF, 0x0A13, + 0x1016, 0x0A53, 0x0182, 0x1007, 0x0AA1, 0x080F, 0x0A16, 0x0A1E, + 0x0042, 0x0902, 0x13DD, 0x0BB2, 0x0A63, 0x00A2, 0x08B1, 0x03FE, + 0x1207, 0x08B2, 0x0B83, 0x09EE, 0x0311, 0x0A87, 0x0BAF, 0x03A2, + 0x09FD, 0x0051, 0x0B33, 0x020D, 0x09CE, 0x0217, 0x021D, 0x0817, + 0x020E, 0x0A4E, 0x001F, 0x0BFD, 0x0297, 0x0983, 0x0A92, 0x0252, + 0x0243, 0x0B03, 0x0193, 0x036F, 0x0B12, 0x0043, 0x0822, 0x0A21, + 0x01FE, 0x0853, 0x037F, 0x023F, 0x0BED, 0x02D2, 0x0B91, 0x0232, + 0x0282, 0x0912, 0x08A3, 0x0852, 0x0223, 0x0BCD, 0x0083, 0x0301, + 0x0832, 0x01EF, 0x0892, 0x0302, 0x0A72, 0x03DE, 0x0893, 0x0BCF, + 0x09DE, 0x03CE, 0x035F, 0x0833, 0x0023, 0x0103, 0x017E, 0x0813, + 0x01CF, 0x01BF, 0x016F, 0x0A22, 0x037E, 0x0113, 0x01AF, 0x0B6E, + 0x03BE, 0x0201, 0x0A03, 0x01DF, 0x036D, 0x03AE, 0x015F, 0x0281, + 0x033E, 0x0A02, 0x038E, 0x017F, 0x0291, 0x034D, 0x03BD, 0x0B7D, + 0x03AD, 0x0211, 0x0212, 0x034F, 0x032E, 0x039F, 0x034E, 0x035D, + 0x035E, 0x033F, 0x039E, 0x032F, 0x038F }; static const uint16_t percentile_arr_10x6_1[199] { - 0x0621,0xBD32,0x5CA3,0x1FAE,0x64C2,0x1D51,0x6C33,0xFC43, - 0x5CB3,0x25A2,0x2E82,0x35D1,0x4F01,0x3FBE,0x3691,0x2DDF, - 0x2E03,0x3FCD,0x14D2,0x1CF1,0x0C52,0x3C35,0x2D22,0x1513, - 0x1462,0x54B2,0x0E31,0x4E81,0x1593,0x1D23,0x1CD1,0x14B5, - 0x2FBD,0x0C07,0x1D06,0x0DEF,0x14A2,0x1612,0x1F4F,0x0C16, - 0x1F7D,0x0C96,0x0486,0x1F9F,0x0D42,0x4583,0x0E02,0x0472, - 0x0DB1,0x1613,0x0FAD,0x0D41,0x0F11,0x0E0D,0x1C42,0x143E, - 0x076E,0x04B1,0x0FAF,0x0D61,0x0531,0x0C71,0x0DFF,0x0DFE, - 0x0406,0x0C45,0x0451,0x0D15,0x05C1,0x2CC1,0x141F,0x0CE1, - 0x0FDD,0x0C22,0x0582,0x0D92,0x0571,0x0F6D,0x0C93,0x045D, - 0x0F5E,0x044D,0x0423,0x0D05,0x0425,0x0C95,0x04A5,0x0DCE, - 0x075F,0x0E1D,0x0503,0x042E,0x0D91,0x0512,0x0DDE,0x05A1, - 0x074E,0x0C32,0x0431,0x0415,0x0D21,0x05EE,0x040E,0x0DDD, - 0x0485,0x1525,0x0491,0x0C26,0x046D,0x0C05,0x05CF,0x05FD, - 0x0E92,0x073F,0x0C0D,0x043D,0x0502,0x0C1E,0x041D,0x0461, - 0x04A1,0x0511,0x0581,0x05BD,0x0C41,0x059F,0x05BF,0x040F, - 0x0C7D,0x0402,0x054E,0x057D,0x0403,0x078D,0x05AE,0x042D, - 0x0483,0x079D,0x0D7F,0x0482,0x0611,0x056E,0x0516,0x05BE, - 0x0535,0x044E,0x05AF,0x0DED,0x042F,0x0492,0x058E,0x078F, - 0x0412,0x057E,0x053E,0x0F1F,0x073D,0x0601,0x0501,0x075D, - 0x059E,0x05CD,0x053F,0x054F,0x055E,0x055D,0x0421,0x074D, - 0x051F,0x072F,0x0781,0x0411,0x0D6F,0x077E,0x0487,0x070E, - 0x070F,0x072D,0x058F,0x078E,0x079E,0x052E,0x0413,0x072E, - 0x071D,0x052F,0x055F,0x073E,0x0417,0x0453,0x060E,0x0622, - 0x0683,0x0702,0x070D,0x071E,0x076F,0x07BF,0x07CE + 0x0621, 0xBD32, 0x5CA3, 0x1FAE, 0x64C2, 0x1D51, 0x6C33, 0xFC43, + 0x5CB3, 0x25A2, 0x2E82, 0x35D1, 0x4F01, 0x3FBE, 0x3691, 0x2DDF, + 0x2E03, 0x3FCD, 0x14D2, 0x1CF1, 0x0C52, 0x3C35, 0x2D22, 0x1513, + 0x1462, 0x54B2, 0x0E31, 0x4E81, 0x1593, 0x1D23, 0x1CD1, 0x14B5, + 0x2FBD, 0x0C07, 0x1D06, 0x0DEF, 0x14A2, 0x1612, 0x1F4F, 0x0C16, + 0x1F7D, 0x0C96, 0x0486, 0x1F9F, 0x0D42, 0x4583, 0x0E02, 0x0472, + 0x0DB1, 0x1613, 0x0FAD, 0x0D41, 0x0F11, 0x0E0D, 0x1C42, 0x143E, + 0x076E, 0x04B1, 0x0FAF, 0x0D61, 0x0531, 0x0C71, 0x0DFF, 0x0DFE, + 0x0406, 0x0C45, 0x0451, 0x0D15, 0x05C1, 0x2CC1, 0x141F, 0x0CE1, + 0x0FDD, 0x0C22, 0x0582, 0x0D92, 0x0571, 0x0F6D, 0x0C93, 0x045D, + 0x0F5E, 0x044D, 0x0423, 0x0D05, 0x0425, 0x0C95, 0x04A5, 0x0DCE, + 0x075F, 0x0E1D, 0x0503, 0x042E, 0x0D91, 0x0512, 0x0DDE, 0x05A1, + 0x074E, 0x0C32, 0x0431, 0x0415, 0x0D21, 0x05EE, 0x040E, 0x0DDD, + 0x0485, 0x1525, 0x0491, 0x0C26, 0x046D, 0x0C05, 0x05CF, 0x05FD, + 0x0E92, 0x073F, 0x0C0D, 0x043D, 0x0502, 0x0C1E, 0x041D, 0x0461, + 0x04A1, 0x0511, 0x0581, 0x05BD, 0x0C41, 0x059F, 0x05BF, 0x040F, + 0x0C7D, 0x0402, 0x054E, 0x057D, 0x0403, 0x078D, 0x05AE, 0x042D, + 0x0483, 0x079D, 0x0D7F, 0x0482, 0x0611, 0x056E, 0x0516, 0x05BE, + 0x0535, 0x044E, 0x05AF, 0x0DED, 0x042F, 0x0492, 0x058E, 0x078F, + 0x0412, 0x057E, 0x053E, 0x0F1F, 0x073D, 0x0601, 0x0501, 0x075D, + 0x059E, 0x05CD, 0x053F, 0x054F, 0x055E, 0x055D, 0x0421, 0x074D, + 0x051F, 0x072F, 0x0781, 0x0411, 0x0D6F, 0x077E, 0x0487, 0x070E, + 0x070F, 0x072D, 0x058F, 0x078E, 0x079E, 0x052E, 0x0413, 0x072E, + 0x071D, 0x052F, 0x055F, 0x073E, 0x0417, 0x0453, 0x060E, 0x0622, + 0x0683, 0x0702, 0x070D, 0x071E, 0x076F, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_10x6 { @@ -674,87 +679,87 @@ static const packed_percentile_table block_pcd_10x6 { #if ASTCENC_BLOCK_MAX_TEXELS >= (10 * 8) static const uint16_t percentile_arr_10x8_0[400] { - 0x0154,0xAB34,0xAD44,0x8308,0x7866,0x7B64,0x79A4,0x7975, - 0x686A,0x6908,0xC514,0x6174,0x6128,0x6118,0x5B54,0x5163, - 0xF856,0x50F5,0x986F,0xDD34,0x48FE,0x4972,0x48E6,0x4146, - 0x48EE,0x40F3,0x4AC1,0x38C6,0x41E2,0xBB05,0x707E,0x38D6, - 0x3927,0x6B14,0x384B,0x3948,0x3153,0x385A,0x3134,0x6B15, - 0x39F2,0x30CF,0x3143,0x91D2,0x31C3,0x60EF,0x5973,0x3076, - 0x28D3,0x3261,0x2875,0x28DE,0x290C,0x51E3,0x28A7,0x20E3, - 0x2962,0x2B06,0x2917,0x483B,0x20B6,0x2D24,0x206E,0x285F, - 0x20B7,0x2936,0x4047,0x2037,0x20DF,0x28BF,0x21B4,0x21B3, - 0x1D08,0x2027,0x404F,0x3846,0x2116,0x187F,0x1879,0x2285, - 0x1A29,0x3915,0x4873,0x1955,0x3114,0x1B44,0x2165,0x107A, - 0x1956,0x6137,0x1106,0x3145,0x1B21,0x19D3,0x12AD,0x1B41, - 0x1AD1,0x1126,0x18F2,0x282B,0x40E5,0x20D5,0x2A0A,0x284A, - 0x1286,0x1295,0x121A,0x2A0B,0x321B,0x122D,0x10FD,0x13A1, - 0x32A2,0x12E1,0x1164,0x13C1,0x124D,0x1239,0x4504,0x10C7, - 0x22F1,0x11F1,0x0AC2,0x2125,0x1225,0x0B04,0x1107,0x1069, - 0x1A19,0x13BF,0x2A96,0x08D2,0x1271,0x0952,0x2BDF,0x0B31, - 0x1251,0x2124,0x0B13,0x12BD,0x1233,0x13EE,0x2144,0x0B16, - 0x0A15,0x18E2,0x08DD,0x1097,0x0857,0x0B24,0x0AA5,0x12A3, - 0x11C2,0x11D1,0x10CE,0x0865,0x123D,0x08B3,0x0B51,0x1971, - 0x0A41,0x0A06,0x1039,0x080A,0x0B22,0x0923,0x0836,0x08C3, - 0x0A1F,0x1072,0x080B,0x0935,0x0855,0x18A6,0x0A42,0x1133, - 0x0A83,0x0A09,0x0ACD,0x0A2E,0x0887,0x083A,0x10C5,0x085E, - 0x13B1,0x087D,0x0819,0x0A9F,0x0049,0x08F1,0x0BEF,0x1161, - 0x0B42,0x09E1,0x0A05,0x0904,0x12AE,0x029E,0x0A31,0x09FF, - 0x0951,0x0859,0x001A,0x082F,0x0B81,0x08B5,0x0A35,0x082A, - 0x08ED,0x1142,0x1262,0x0B32,0x08A5,0x12D2,0x03DD,0x0B07, - 0x18AE,0x083F,0x00AF,0x0AB3,0x086D,0x0287,0x0A93,0x025D, - 0x0816,0x13FF,0x0A8D,0x005D,0x08D1,0x0392,0x0845,0x0AC3, - 0x08C2,0x01A3,0x0AB1,0x09A2,0x005B,0x0B93,0x02B2,0x1086, - 0x001B,0x0863,0x0216,0x0AA1,0x0896,0x0A8F,0x084E,0x0A8E, - 0x0A53,0x0026,0x0A26,0x0382,0x0807,0x0862,0x0029,0x0871, - 0x00BD,0x0835,0x024E,0x0806,0x0941,0x0895,0x03AF,0x0A13, - 0x0932,0x03ED,0x0BFD,0x0207,0x0B83,0x0993,0x09B1,0x03CD, - 0x0A3E,0x03FE,0x0A21,0x0015,0x0B11,0x0A43,0x00E1,0x136F, - 0x00BE,0x00A2,0x0842,0x0043,0x0825,0x082E,0x0A2A,0x03DE, - 0x0BA2,0x0122,0x0BCF,0x004D,0x0323,0x09C1,0x0292,0x083E, - 0x0252,0x0017,0x0A72,0x00CD,0x0182,0x0A63,0x0131,0x09B2, - 0x0303,0x0902,0x0053,0x035F,0x0A32,0x003D,0x0992,0x0A2F, - 0x03B2,0x0ABE,0x009F,0x0183,0x0312,0x08B1,0x0B02,0x0A17, - 0x0B7F,0x0333,0x0297,0x0A23,0x020F,0x0282,0x0851,0x0822, - 0x03CE,0x01EE,0x000E,0x08B2,0x0083,0x0A1D,0x00A3,0x0222, - 0x088F,0x0112,0x029D,0x0092,0x0A3F,0x0391,0x089E,0x0301, - 0x01FD,0x09BF,0x01CE,0x0852,0x01FE,0x0013,0x0903,0x088E, - 0x037E,0x021E,0x01EF,0x095F,0x016F,0x09DE,0x03BE,0x020E, - 0x0113,0x01DF,0x080F,0x020D,0x0833,0x03AE,0x0032,0x03BD, - 0x0823,0x001E,0x01AF,0x0203,0x034F,0x0093,0x0A81,0x036E, - 0x0291,0x038E,0x0A01,0x001F,0x017F,0x01CF,0x017E,0x0202, - 0x0BAD,0x0211,0x035D,0x035E,0x039F,0x0212,0x032E,0x033F, - 0x034D,0x034E,0x036D,0x032F,0x033E,0x037D,0x038F,0x039E + 0x0154, 0xAB34, 0xAD44, 0x8308, 0x7866, 0x7B64, 0x79A4, 0x7975, + 0x686A, 0x6908, 0xC514, 0x6174, 0x6128, 0x6118, 0x5B54, 0x5163, + 0xF856, 0x50F5, 0x986F, 0xDD34, 0x48FE, 0x4972, 0x48E6, 0x4146, + 0x48EE, 0x40F3, 0x4AC1, 0x38C6, 0x41E2, 0xBB05, 0x707E, 0x38D6, + 0x3927, 0x6B14, 0x384B, 0x3948, 0x3153, 0x385A, 0x3134, 0x6B15, + 0x39F2, 0x30CF, 0x3143, 0x91D2, 0x31C3, 0x60EF, 0x5973, 0x3076, + 0x28D3, 0x3261, 0x2875, 0x28DE, 0x290C, 0x51E3, 0x28A7, 0x20E3, + 0x2962, 0x2B06, 0x2917, 0x483B, 0x20B6, 0x2D24, 0x206E, 0x285F, + 0x20B7, 0x2936, 0x4047, 0x2037, 0x20DF, 0x28BF, 0x21B4, 0x21B3, + 0x1D08, 0x2027, 0x404F, 0x3846, 0x2116, 0x187F, 0x1879, 0x2285, + 0x1A29, 0x3915, 0x4873, 0x1955, 0x3114, 0x1B44, 0x2165, 0x107A, + 0x1956, 0x6137, 0x1106, 0x3145, 0x1B21, 0x19D3, 0x12AD, 0x1B41, + 0x1AD1, 0x1126, 0x18F2, 0x282B, 0x40E5, 0x20D5, 0x2A0A, 0x284A, + 0x1286, 0x1295, 0x121A, 0x2A0B, 0x321B, 0x122D, 0x10FD, 0x13A1, + 0x32A2, 0x12E1, 0x1164, 0x13C1, 0x124D, 0x1239, 0x4504, 0x10C7, + 0x22F1, 0x11F1, 0x0AC2, 0x2125, 0x1225, 0x0B04, 0x1107, 0x1069, + 0x1A19, 0x13BF, 0x2A96, 0x08D2, 0x1271, 0x0952, 0x2BDF, 0x0B31, + 0x1251, 0x2124, 0x0B13, 0x12BD, 0x1233, 0x13EE, 0x2144, 0x0B16, + 0x0A15, 0x18E2, 0x08DD, 0x1097, 0x0857, 0x0B24, 0x0AA5, 0x12A3, + 0x11C2, 0x11D1, 0x10CE, 0x0865, 0x123D, 0x08B3, 0x0B51, 0x1971, + 0x0A41, 0x0A06, 0x1039, 0x080A, 0x0B22, 0x0923, 0x0836, 0x08C3, + 0x0A1F, 0x1072, 0x080B, 0x0935, 0x0855, 0x18A6, 0x0A42, 0x1133, + 0x0A83, 0x0A09, 0x0ACD, 0x0A2E, 0x0887, 0x083A, 0x10C5, 0x085E, + 0x13B1, 0x087D, 0x0819, 0x0A9F, 0x0049, 0x08F1, 0x0BEF, 0x1161, + 0x0B42, 0x09E1, 0x0A05, 0x0904, 0x12AE, 0x029E, 0x0A31, 0x09FF, + 0x0951, 0x0859, 0x001A, 0x082F, 0x0B81, 0x08B5, 0x0A35, 0x082A, + 0x08ED, 0x1142, 0x1262, 0x0B32, 0x08A5, 0x12D2, 0x03DD, 0x0B07, + 0x18AE, 0x083F, 0x00AF, 0x0AB3, 0x086D, 0x0287, 0x0A93, 0x025D, + 0x0816, 0x13FF, 0x0A8D, 0x005D, 0x08D1, 0x0392, 0x0845, 0x0AC3, + 0x08C2, 0x01A3, 0x0AB1, 0x09A2, 0x005B, 0x0B93, 0x02B2, 0x1086, + 0x001B, 0x0863, 0x0216, 0x0AA1, 0x0896, 0x0A8F, 0x084E, 0x0A8E, + 0x0A53, 0x0026, 0x0A26, 0x0382, 0x0807, 0x0862, 0x0029, 0x0871, + 0x00BD, 0x0835, 0x024E, 0x0806, 0x0941, 0x0895, 0x03AF, 0x0A13, + 0x0932, 0x03ED, 0x0BFD, 0x0207, 0x0B83, 0x0993, 0x09B1, 0x03CD, + 0x0A3E, 0x03FE, 0x0A21, 0x0015, 0x0B11, 0x0A43, 0x00E1, 0x136F, + 0x00BE, 0x00A2, 0x0842, 0x0043, 0x0825, 0x082E, 0x0A2A, 0x03DE, + 0x0BA2, 0x0122, 0x0BCF, 0x004D, 0x0323, 0x09C1, 0x0292, 0x083E, + 0x0252, 0x0017, 0x0A72, 0x00CD, 0x0182, 0x0A63, 0x0131, 0x09B2, + 0x0303, 0x0902, 0x0053, 0x035F, 0x0A32, 0x003D, 0x0992, 0x0A2F, + 0x03B2, 0x0ABE, 0x009F, 0x0183, 0x0312, 0x08B1, 0x0B02, 0x0A17, + 0x0B7F, 0x0333, 0x0297, 0x0A23, 0x020F, 0x0282, 0x0851, 0x0822, + 0x03CE, 0x01EE, 0x000E, 0x08B2, 0x0083, 0x0A1D, 0x00A3, 0x0222, + 0x088F, 0x0112, 0x029D, 0x0092, 0x0A3F, 0x0391, 0x089E, 0x0301, + 0x01FD, 0x09BF, 0x01CE, 0x0852, 0x01FE, 0x0013, 0x0903, 0x088E, + 0x037E, 0x021E, 0x01EF, 0x095F, 0x016F, 0x09DE, 0x03BE, 0x020E, + 0x0113, 0x01DF, 0x080F, 0x020D, 0x0833, 0x03AE, 0x0032, 0x03BD, + 0x0823, 0x001E, 0x01AF, 0x0203, 0x034F, 0x0093, 0x0A81, 0x036E, + 0x0291, 0x038E, 0x0A01, 0x001F, 0x017F, 0x01CF, 0x017E, 0x0202, + 0x0BAD, 0x0211, 0x035D, 0x035E, 0x039F, 0x0212, 0x032E, 0x033F, + 0x034D, 0x034E, 0x036D, 0x032F, 0x033E, 0x037D, 0x038F, 0x039E }; static const uint16_t percentile_arr_10x8_1[221] { - 0x0621,0xDFAE,0x2443,0x54C2,0x37CD,0x1CF1,0xFCA3,0x14D2, - 0x2D32,0x5551,0x7DDF,0x5C33,0x15D1,0x3462,0x24B3,0x7452, - 0x5FBE,0x6472,0x65A2,0x1D06,0x445D,0x15EF,0x0E31,0x1D71, - 0x343E,0x0D42,0x0CDD,0x1F01,0x4691,0x1435,0x0E82,0x0DFF, - 0x17DD,0x0D22,0x24B2,0x1603,0x04B5,0x24AE,0x060D,0x2D13, - 0x0C7D,0x0496,0x17BD,0x1F4F,0x1F7D,0x1486,0x0593,0x1C16, - 0x0C07,0x15FE,0x041F,0x14D1,0x0C9F,0x0E81,0x0D15,0x27AF, - 0x0C2E,0x0D23,0x176E,0x0FAD,0x1C06,0x1561,0x0DB1,0x040B, - 0x1C4E,0x0D83,0x1711,0x0C42,0x0C71,0x1C1A,0x0D25,0x04A2, - 0x0C45,0x076D,0x0F9F,0x075F,0x0E12,0x046D,0x048F,0x1D92, - 0x0602,0x0C39,0x174E,0x0C51,0x0CA1,0x075E,0x05C1,0x14BD, - 0x0D31,0x0423,0x0F3F,0x0495,0x0C93,0x049E,0x0D05,0x04E1, - 0x0DEE,0x0415,0x04B1,0x0503,0x0CCD,0x042F,0x0DCF,0x044D, - 0x0541,0x1582,0x05DE,0x0D01,0x0487,0x040A,0x0516,0x0CA5, - 0x05FD,0x05BF,0x057D,0x0DA1,0x0426,0x040F,0x071F,0x0613, - 0x0432,0x0D12,0x043D,0x0425,0x0461,0x061D,0x0D21,0x0591, - 0x079D,0x048D,0x0429,0x0C49,0x04C1,0x042A,0x040E,0x0485, - 0x0511,0x0405,0x0502,0x0441,0x0C19,0x0692,0x0535,0x058F, - 0x041D,0x059F,0x072D,0x04AD,0x049D,0x05CE,0x048E,0x0C31, - 0x057F,0x078D,0x0409,0x041E,0x05AE,0x0611,0x058E,0x05DD, - 0x05CD,0x056E,0x0483,0x073D,0x054E,0x0D9E,0x0402,0x0491, - 0x040D,0x056F,0x042D,0x0581,0x0421,0x057E,0x0781,0x053E, - 0x0482,0x078F,0x0413,0x052E,0x0601,0x0422,0x0492,0x055E, - 0x05BE,0x0F9E,0x072F,0x074D,0x0412,0x070F,0x075D,0x05BD, - 0x051F,0x071D,0x073E,0x077E,0x0403,0x0411,0x078E,0x055D, - 0x05AF,0x05ED,0x052F,0x053F,0x070D,0x070E,0x072E,0x054F, - 0x0417,0x041B,0x0453,0x055F,0x060E,0x0622,0x0683,0x068D, - 0x0702,0x071E,0x076F,0x07BF,0x07CE + 0x0621, 0xDFAE, 0x2443, 0x54C2, 0x37CD, 0x1CF1, 0xFCA3, 0x14D2, + 0x2D32, 0x5551, 0x7DDF, 0x5C33, 0x15D1, 0x3462, 0x24B3, 0x7452, + 0x5FBE, 0x6472, 0x65A2, 0x1D06, 0x445D, 0x15EF, 0x0E31, 0x1D71, + 0x343E, 0x0D42, 0x0CDD, 0x1F01, 0x4691, 0x1435, 0x0E82, 0x0DFF, + 0x17DD, 0x0D22, 0x24B2, 0x1603, 0x04B5, 0x24AE, 0x060D, 0x2D13, + 0x0C7D, 0x0496, 0x17BD, 0x1F4F, 0x1F7D, 0x1486, 0x0593, 0x1C16, + 0x0C07, 0x15FE, 0x041F, 0x14D1, 0x0C9F, 0x0E81, 0x0D15, 0x27AF, + 0x0C2E, 0x0D23, 0x176E, 0x0FAD, 0x1C06, 0x1561, 0x0DB1, 0x040B, + 0x1C4E, 0x0D83, 0x1711, 0x0C42, 0x0C71, 0x1C1A, 0x0D25, 0x04A2, + 0x0C45, 0x076D, 0x0F9F, 0x075F, 0x0E12, 0x046D, 0x048F, 0x1D92, + 0x0602, 0x0C39, 0x174E, 0x0C51, 0x0CA1, 0x075E, 0x05C1, 0x14BD, + 0x0D31, 0x0423, 0x0F3F, 0x0495, 0x0C93, 0x049E, 0x0D05, 0x04E1, + 0x0DEE, 0x0415, 0x04B1, 0x0503, 0x0CCD, 0x042F, 0x0DCF, 0x044D, + 0x0541, 0x1582, 0x05DE, 0x0D01, 0x0487, 0x040A, 0x0516, 0x0CA5, + 0x05FD, 0x05BF, 0x057D, 0x0DA1, 0x0426, 0x040F, 0x071F, 0x0613, + 0x0432, 0x0D12, 0x043D, 0x0425, 0x0461, 0x061D, 0x0D21, 0x0591, + 0x079D, 0x048D, 0x0429, 0x0C49, 0x04C1, 0x042A, 0x040E, 0x0485, + 0x0511, 0x0405, 0x0502, 0x0441, 0x0C19, 0x0692, 0x0535, 0x058F, + 0x041D, 0x059F, 0x072D, 0x04AD, 0x049D, 0x05CE, 0x048E, 0x0C31, + 0x057F, 0x078D, 0x0409, 0x041E, 0x05AE, 0x0611, 0x058E, 0x05DD, + 0x05CD, 0x056E, 0x0483, 0x073D, 0x054E, 0x0D9E, 0x0402, 0x0491, + 0x040D, 0x056F, 0x042D, 0x0581, 0x0421, 0x057E, 0x0781, 0x053E, + 0x0482, 0x078F, 0x0413, 0x052E, 0x0601, 0x0422, 0x0492, 0x055E, + 0x05BE, 0x0F9E, 0x072F, 0x074D, 0x0412, 0x070F, 0x075D, 0x05BD, + 0x051F, 0x071D, 0x073E, 0x077E, 0x0403, 0x0411, 0x078E, 0x055D, + 0x05AF, 0x05ED, 0x052F, 0x053F, 0x070D, 0x070E, 0x072E, 0x054F, + 0x0417, 0x041B, 0x0453, 0x055F, 0x060E, 0x0622, 0x0683, 0x068D, + 0x0702, 0x071E, 0x076F, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_10x8 = @@ -769,96 +774,96 @@ static const packed_percentile_table block_pcd_10x8 = #if ASTCENC_BLOCK_MAX_TEXELS >= (10 * 10) static const uint16_t percentile_arr_10x10_0[453] { - 0x0334,0x9514,0x8954,0x806A,0x6F14,0x6724,0x6108,0x6364, - 0x5175,0x5D44,0x5866,0x5118,0x5308,0xA179,0x5128,0xF534, - 0x49A4,0x5354,0x9174,0x486F,0x48EA,0x40F3,0x4963,0x414A, - 0xF8F9,0x3984,0x4172,0x387E,0x405A,0x38DA,0x38F5,0x9B05, - 0x30EE,0x32C1,0x3261,0x3D08,0x31E2,0x3056,0x292B,0x3146, - 0x3127,0x3315,0x58CA,0x58E6,0x290C,0x3314,0x8134,0x28E3, - 0x28FE,0x2948,0x28C6,0x78DE,0x28BB,0x68D6,0x286E,0x2173, - 0x2962,0x21D2,0x205F,0x49F2,0x2917,0x2306,0x207F,0x404F, - 0x2153,0x2943,0x20CF,0x21C3,0x2073,0x20D3,0x2136,0x183B, - 0x430A,0x40A7,0x18B6,0x2079,0x2309,0x2075,0x184B,0x20EF, - 0x187A,0x7837,0x1B19,0x20AB,0x18BA,0x20B7,0x1994,0x19E3, - 0x21B4,0x49B3,0x38BF,0x193B,0x1876,0x182B,0x30F2,0x193A, - 0x1827,0x1965,0x1914,0x184A,0x4047,0x1916,0x1285,0x1937, - 0x122D,0x1915,0x1321,0x1955,0x1046,0x191B,0x2106,0x2919, - 0x1344,0x1524,0x12E1,0x3926,0x10E5,0x2295,0x1159,0x1145, - 0x10DF,0x124D,0x1271,0x092A,0x2169,0x1704,0x22A2,0x1164, - 0x13EE,0x12F1,0x0AD1,0x128A,0x110A,0x11D3,0x1286,0x115A, - 0x2BA1,0x0BBF,0x3956,0x2A89,0x12AD,0x10E9,0x0B41,0x1A29, - 0x2225,0x08FD,0x1107,0x08D5,0x191A,0x1125,0x1A96,0x0B04, - 0x18D9,0x2B16,0x11F1,0x0A33,0x0924,0x131A,0x1149,0x1324, - 0x0BEF,0x0A99,0x08CB,0x123D,0x1331,0x0BDF,0x0872,0x22A3, - 0x0AC2,0x1144,0x0D04,0x08D2,0x08CE,0x0AA9,0x0A9A,0x0B13, - 0x1251,0x0865,0x1069,0x0897,0x1215,0x18B3,0x1A62,0x08C7, - 0x185E,0x10E2,0x0AA5,0x21FF,0x090B,0x0952,0x09E1,0x0A42, - 0x08F1,0x0A06,0x0B22,0x087D,0x1139,0x021F,0x122E,0x082F, - 0x09C2,0x0887,0x0A0A,0x03C1,0x0929,0x0A5D,0x0A83,0x0BFF, - 0x0935,0x085B,0x0104,0x08DD,0x0923,0x083F,0x0241,0x09D1, - 0x0A39,0x0863,0x0A8B,0x08A6,0x008B,0x1133,0x13B1,0x089B, - 0x0AB3,0x0036,0x0BDD,0x08ED,0x0857,0x0971,0x0219,0x1235, - 0x0AB1,0x0ACD,0x036F,0x0A31,0x08AA,0x003A,0x08C3,0x0A05, - 0x02BD,0x0B92,0x0B07,0x12B2,0x08C5,0x0B51,0x0381,0x0A8D, - 0x01A3,0x0896,0x0855,0x0BFD,0x005D,0x0BFE,0x023E,0x08AF, - 0x00B9,0x0A93,0x00B5,0x0862,0x0A0B,0x0A09,0x0A72,0x0332, - 0x0AA1,0x08C9,0x024E,0x1382,0x0951,0x00A5,0x0A2A,0x0059, - 0x0A9E,0x0B42,0x004E,0x0942,0x03ED,0x09B2,0x02D2,0x0849, - 0x0035,0x0216,0x0961,0x0BAF,0x00AE,0x0826,0x0287,0x0A1A, - 0x0393,0x0221,0x09A2,0x086D,0x0226,0x0871,0x0039,0x082A, - 0x08C2,0x08E1,0x0845,0x0207,0x0B23,0x0015,0x00D1,0x0B83, - 0x037F,0x0252,0x08A9,0x0099,0x0A13,0x0053,0x0807,0x03CD, - 0x0BDE,0x0016,0x089A,0x0232,0x035F,0x0A8E,0x0AC3,0x022F, - 0x0263,0x0829,0x004D,0x0132,0x0806,0x0311,0x01B1,0x0941, - 0x0086,0x000B,0x1122,0x0025,0x0842,0x00BD,0x0BCF,0x03A2, - 0x0043,0x0B03,0x0895,0x0A8F,0x008A,0x09EF,0x0253,0x0A1B, - 0x0182,0x0243,0x0A92,0x00CD,0x083E,0x030B,0x0223,0x081A, - 0x0A9F,0x0193,0x00BE,0x0017,0x0931,0x0391,0x037E,0x09C1, - 0x0312,0x0333,0x03B2,0x083D,0x08B1,0x00B2,0x002E,0x021D, - 0x0A9D,0x0192,0x02AE,0x0102,0x0022,0x081B,0x0222,0x009E, - 0x021E,0x000A,0x089F,0x0217,0x0BCE,0x0052,0x020F,0x0A97, - 0x0282,0x008E,0x0A3F,0x01FD,0x00A3,0x0019,0x08A2,0x0301, - 0x036E,0x01FE,0x03BE,0x0ABE,0x01CE,0x0302,0x029B,0x0051, - 0x0883,0x008F,0x0BAE,0x01DF,0x0183,0x0912,0x000E,0x020D, - 0x01EE,0x0B4F,0x0033,0x0103,0x020E,0x0832,0x01AF,0x0913, - 0x01DE,0x0203,0x001E,0x0092,0x0093,0x000F,0x015F,0x0291, - 0x0281,0x0813,0x001F,0x01CF,0x033F,0x0023,0x01BF,0x0202, - 0x016F,0x017E,0x03AD,0x0201,0x034E,0x0BBD,0x036D,0x017F, - 0x0211,0x038E,0x0212,0x032E,0x034D,0x035E,0x037D,0x039E, - 0x032F,0x033E,0x035D,0x038F,0x039F + 0x0334, 0x9514, 0x8954, 0x806A, 0x6F14, 0x6724, 0x6108, 0x6364, + 0x5175, 0x5D44, 0x5866, 0x5118, 0x5308, 0xA179, 0x5128, 0xF534, + 0x49A4, 0x5354, 0x9174, 0x486F, 0x48EA, 0x40F3, 0x4963, 0x414A, + 0xF8F9, 0x3984, 0x4172, 0x387E, 0x405A, 0x38DA, 0x38F5, 0x9B05, + 0x30EE, 0x32C1, 0x3261, 0x3D08, 0x31E2, 0x3056, 0x292B, 0x3146, + 0x3127, 0x3315, 0x58CA, 0x58E6, 0x290C, 0x3314, 0x8134, 0x28E3, + 0x28FE, 0x2948, 0x28C6, 0x78DE, 0x28BB, 0x68D6, 0x286E, 0x2173, + 0x2962, 0x21D2, 0x205F, 0x49F2, 0x2917, 0x2306, 0x207F, 0x404F, + 0x2153, 0x2943, 0x20CF, 0x21C3, 0x2073, 0x20D3, 0x2136, 0x183B, + 0x430A, 0x40A7, 0x18B6, 0x2079, 0x2309, 0x2075, 0x184B, 0x20EF, + 0x187A, 0x7837, 0x1B19, 0x20AB, 0x18BA, 0x20B7, 0x1994, 0x19E3, + 0x21B4, 0x49B3, 0x38BF, 0x193B, 0x1876, 0x182B, 0x30F2, 0x193A, + 0x1827, 0x1965, 0x1914, 0x184A, 0x4047, 0x1916, 0x1285, 0x1937, + 0x122D, 0x1915, 0x1321, 0x1955, 0x1046, 0x191B, 0x2106, 0x2919, + 0x1344, 0x1524, 0x12E1, 0x3926, 0x10E5, 0x2295, 0x1159, 0x1145, + 0x10DF, 0x124D, 0x1271, 0x092A, 0x2169, 0x1704, 0x22A2, 0x1164, + 0x13EE, 0x12F1, 0x0AD1, 0x128A, 0x110A, 0x11D3, 0x1286, 0x115A, + 0x2BA1, 0x0BBF, 0x3956, 0x2A89, 0x12AD, 0x10E9, 0x0B41, 0x1A29, + 0x2225, 0x08FD, 0x1107, 0x08D5, 0x191A, 0x1125, 0x1A96, 0x0B04, + 0x18D9, 0x2B16, 0x11F1, 0x0A33, 0x0924, 0x131A, 0x1149, 0x1324, + 0x0BEF, 0x0A99, 0x08CB, 0x123D, 0x1331, 0x0BDF, 0x0872, 0x22A3, + 0x0AC2, 0x1144, 0x0D04, 0x08D2, 0x08CE, 0x0AA9, 0x0A9A, 0x0B13, + 0x1251, 0x0865, 0x1069, 0x0897, 0x1215, 0x18B3, 0x1A62, 0x08C7, + 0x185E, 0x10E2, 0x0AA5, 0x21FF, 0x090B, 0x0952, 0x09E1, 0x0A42, + 0x08F1, 0x0A06, 0x0B22, 0x087D, 0x1139, 0x021F, 0x122E, 0x082F, + 0x09C2, 0x0887, 0x0A0A, 0x03C1, 0x0929, 0x0A5D, 0x0A83, 0x0BFF, + 0x0935, 0x085B, 0x0104, 0x08DD, 0x0923, 0x083F, 0x0241, 0x09D1, + 0x0A39, 0x0863, 0x0A8B, 0x08A6, 0x008B, 0x1133, 0x13B1, 0x089B, + 0x0AB3, 0x0036, 0x0BDD, 0x08ED, 0x0857, 0x0971, 0x0219, 0x1235, + 0x0AB1, 0x0ACD, 0x036F, 0x0A31, 0x08AA, 0x003A, 0x08C3, 0x0A05, + 0x02BD, 0x0B92, 0x0B07, 0x12B2, 0x08C5, 0x0B51, 0x0381, 0x0A8D, + 0x01A3, 0x0896, 0x0855, 0x0BFD, 0x005D, 0x0BFE, 0x023E, 0x08AF, + 0x00B9, 0x0A93, 0x00B5, 0x0862, 0x0A0B, 0x0A09, 0x0A72, 0x0332, + 0x0AA1, 0x08C9, 0x024E, 0x1382, 0x0951, 0x00A5, 0x0A2A, 0x0059, + 0x0A9E, 0x0B42, 0x004E, 0x0942, 0x03ED, 0x09B2, 0x02D2, 0x0849, + 0x0035, 0x0216, 0x0961, 0x0BAF, 0x00AE, 0x0826, 0x0287, 0x0A1A, + 0x0393, 0x0221, 0x09A2, 0x086D, 0x0226, 0x0871, 0x0039, 0x082A, + 0x08C2, 0x08E1, 0x0845, 0x0207, 0x0B23, 0x0015, 0x00D1, 0x0B83, + 0x037F, 0x0252, 0x08A9, 0x0099, 0x0A13, 0x0053, 0x0807, 0x03CD, + 0x0BDE, 0x0016, 0x089A, 0x0232, 0x035F, 0x0A8E, 0x0AC3, 0x022F, + 0x0263, 0x0829, 0x004D, 0x0132, 0x0806, 0x0311, 0x01B1, 0x0941, + 0x0086, 0x000B, 0x1122, 0x0025, 0x0842, 0x00BD, 0x0BCF, 0x03A2, + 0x0043, 0x0B03, 0x0895, 0x0A8F, 0x008A, 0x09EF, 0x0253, 0x0A1B, + 0x0182, 0x0243, 0x0A92, 0x00CD, 0x083E, 0x030B, 0x0223, 0x081A, + 0x0A9F, 0x0193, 0x00BE, 0x0017, 0x0931, 0x0391, 0x037E, 0x09C1, + 0x0312, 0x0333, 0x03B2, 0x083D, 0x08B1, 0x00B2, 0x002E, 0x021D, + 0x0A9D, 0x0192, 0x02AE, 0x0102, 0x0022, 0x081B, 0x0222, 0x009E, + 0x021E, 0x000A, 0x089F, 0x0217, 0x0BCE, 0x0052, 0x020F, 0x0A97, + 0x0282, 0x008E, 0x0A3F, 0x01FD, 0x00A3, 0x0019, 0x08A2, 0x0301, + 0x036E, 0x01FE, 0x03BE, 0x0ABE, 0x01CE, 0x0302, 0x029B, 0x0051, + 0x0883, 0x008F, 0x0BAE, 0x01DF, 0x0183, 0x0912, 0x000E, 0x020D, + 0x01EE, 0x0B4F, 0x0033, 0x0103, 0x020E, 0x0832, 0x01AF, 0x0913, + 0x01DE, 0x0203, 0x001E, 0x0092, 0x0093, 0x000F, 0x015F, 0x0291, + 0x0281, 0x0813, 0x001F, 0x01CF, 0x033F, 0x0023, 0x01BF, 0x0202, + 0x016F, 0x017E, 0x03AD, 0x0201, 0x034E, 0x0BBD, 0x036D, 0x017F, + 0x0211, 0x038E, 0x0212, 0x032E, 0x034D, 0x035E, 0x037D, 0x039E, + 0x032F, 0x033E, 0x035D, 0x038F, 0x039F }; static const uint16_t percentile_arr_10x10_1[234] { - 0x07CD,0x6E21,0x24F1,0x8443,0xD7AE,0x24C2,0x1C62,0xCCA3, - 0x1C33,0xFDEF,0x2532,0x55DF,0x1472,0x6C3E,0x14D2,0x34DD, - 0x1452,0x745D,0x4D51,0x8DD1,0x247D,0x75FF,0x0CB3,0x17BE, - 0x6CAE,0x17DD,0x1571,0x3D06,0x4E31,0x0DA2,0x67BD,0x160D, - 0x2C4E,0x0D22,0x176E,0x3CB2,0x142E,0x4DFE,0x0F4F,0x1435, - 0x0F01,0x0D42,0x0F7D,0x0CB5,0x1E03,0x149F,0x1C96,0x141F, - 0x14B9,0x0FAF,0x0439,0x0E91,0x2682,0x1D13,0x1FAD,0x0407, - 0x3471,0x0C86,0x0F6D,0x0D15,0x0D61,0x040B,0x0C6D,0x0C16, - 0x0C9A,0x0D0A,0x0593,0x0CD1,0x248F,0x0C2F,0x3C42,0x1523, - 0x0445,0x0E81,0x0CA2,0x1525,0x0406,0x1C8A,0x0C1A,0x04BD, - 0x0F5E,0x0F3F,0x1F4E,0x0E1D,0x0423,0x0DCF,0x044D,0x0D92, - 0x0583,0x0DB1,0x1449,0x15EE,0x0F5F,0x079F,0x0D19,0x0409, - 0x04CD,0x05FD,0x143D,0x0612,0x0D03,0x0D82,0x04B1,0x0C95, - 0x0C2A,0x049E,0x05AF,0x0D31,0x05BE,0x04E1,0x0D05,0x0516, - 0x0711,0x05C1,0x0509,0x0D41,0x0493,0x048E,0x0602,0x05BF, - 0x0CA5,0x0529,0x0535,0x0D12,0x0539,0x0451,0x0C29,0x071F, - 0x040A,0x0F3D,0x0432,0x059F,0x0425,0x0C99,0x05DE,0x05CE, - 0x0C0F,0x0489,0x051A,0x0501,0x0415,0x057F,0x0431,0x0E13, - 0x040D,0x041D,0x075D,0x0C53,0x0502,0x04C1,0x049D,0x0426, - 0x040E,0x05A1,0x055F,0x0781,0x0591,0x04A9,0x048B,0x0D8E, - 0x052E,0x0412,0x0521,0x0405,0x04AD,0x074D,0x0611,0x077E, - 0x078F,0x078D,0x048D,0x041E,0x0487,0x0461,0x0C85,0x05ED, - 0x0402,0x0483,0x0419,0x0511,0x0491,0x0482,0x059E,0x068D, - 0x055D,0x072E,0x05DD,0x054E,0x0441,0x0422,0x052F,0x057D, - 0x072D,0x079D,0x0CA1,0x072F,0x079E,0x0581,0x042D,0x055E, - 0x0601,0x0413,0x0692,0x0403,0x051F,0x053F,0x054F,0x05CD, - 0x070F,0x071D,0x05AE,0x05BD,0x0492,0x056E,0x0411,0x0417, - 0x041B,0x0421,0x053E,0x056F,0x057E,0x058F,0x060E,0x0622, - 0x0683,0x0702,0x070D,0x070E,0x071E,0x073E,0x076F,0x078E, - 0x07BF,0x07CE + 0x07CD, 0x6E21, 0x24F1, 0x8443, 0xD7AE, 0x24C2, 0x1C62, 0xCCA3, + 0x1C33, 0xFDEF, 0x2532, 0x55DF, 0x1472, 0x6C3E, 0x14D2, 0x34DD, + 0x1452, 0x745D, 0x4D51, 0x8DD1, 0x247D, 0x75FF, 0x0CB3, 0x17BE, + 0x6CAE, 0x17DD, 0x1571, 0x3D06, 0x4E31, 0x0DA2, 0x67BD, 0x160D, + 0x2C4E, 0x0D22, 0x176E, 0x3CB2, 0x142E, 0x4DFE, 0x0F4F, 0x1435, + 0x0F01, 0x0D42, 0x0F7D, 0x0CB5, 0x1E03, 0x149F, 0x1C96, 0x141F, + 0x14B9, 0x0FAF, 0x0439, 0x0E91, 0x2682, 0x1D13, 0x1FAD, 0x0407, + 0x3471, 0x0C86, 0x0F6D, 0x0D15, 0x0D61, 0x040B, 0x0C6D, 0x0C16, + 0x0C9A, 0x0D0A, 0x0593, 0x0CD1, 0x248F, 0x0C2F, 0x3C42, 0x1523, + 0x0445, 0x0E81, 0x0CA2, 0x1525, 0x0406, 0x1C8A, 0x0C1A, 0x04BD, + 0x0F5E, 0x0F3F, 0x1F4E, 0x0E1D, 0x0423, 0x0DCF, 0x044D, 0x0D92, + 0x0583, 0x0DB1, 0x1449, 0x15EE, 0x0F5F, 0x079F, 0x0D19, 0x0409, + 0x04CD, 0x05FD, 0x143D, 0x0612, 0x0D03, 0x0D82, 0x04B1, 0x0C95, + 0x0C2A, 0x049E, 0x05AF, 0x0D31, 0x05BE, 0x04E1, 0x0D05, 0x0516, + 0x0711, 0x05C1, 0x0509, 0x0D41, 0x0493, 0x048E, 0x0602, 0x05BF, + 0x0CA5, 0x0529, 0x0535, 0x0D12, 0x0539, 0x0451, 0x0C29, 0x071F, + 0x040A, 0x0F3D, 0x0432, 0x059F, 0x0425, 0x0C99, 0x05DE, 0x05CE, + 0x0C0F, 0x0489, 0x051A, 0x0501, 0x0415, 0x057F, 0x0431, 0x0E13, + 0x040D, 0x041D, 0x075D, 0x0C53, 0x0502, 0x04C1, 0x049D, 0x0426, + 0x040E, 0x05A1, 0x055F, 0x0781, 0x0591, 0x04A9, 0x048B, 0x0D8E, + 0x052E, 0x0412, 0x0521, 0x0405, 0x04AD, 0x074D, 0x0611, 0x077E, + 0x078F, 0x078D, 0x048D, 0x041E, 0x0487, 0x0461, 0x0C85, 0x05ED, + 0x0402, 0x0483, 0x0419, 0x0511, 0x0491, 0x0482, 0x059E, 0x068D, + 0x055D, 0x072E, 0x05DD, 0x054E, 0x0441, 0x0422, 0x052F, 0x057D, + 0x072D, 0x079D, 0x0CA1, 0x072F, 0x079E, 0x0581, 0x042D, 0x055E, + 0x0601, 0x0413, 0x0692, 0x0403, 0x051F, 0x053F, 0x054F, 0x05CD, + 0x070F, 0x071D, 0x05AE, 0x05BD, 0x0492, 0x056E, 0x0411, 0x0417, + 0x041B, 0x0421, 0x053E, 0x056F, 0x057E, 0x058F, 0x060E, 0x0622, + 0x0683, 0x0702, 0x070D, 0x070E, 0x071E, 0x073E, 0x076F, 0x078E, + 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_10x10 { @@ -872,101 +877,101 @@ static const packed_percentile_table block_pcd_10x10 { #if ASTCENC_BLOCK_MAX_TEXELS >= (12 * 10) static const uint16_t percentile_arr_12x10_0[491] { - 0x0334,0x9954,0x8514,0x7128,0x6364,0xC174,0x5D34,0x5866, - 0x5975,0x5354,0xAF14,0x506A,0x5108,0x5724,0x5308,0x4544, - 0x4918,0x4064,0x49E2,0x4179,0x8163,0x4054,0xF81C,0x394A, - 0x38F3,0x4172,0x38F5,0xA06F,0x68EA,0x69F2,0x3134,0x31A4, - 0x305A,0x68DA,0x3056,0x3146,0x31F5,0x3148,0x5A61,0x32C1, - 0x31D2,0x307E,0x29E3,0x30E6,0x59C3,0x2984,0x29B6,0x28F9, - 0x5204,0x28EE,0x50CA,0x2997,0x48C6,0x4838,0x2953,0x200C, - 0x2943,0x2173,0x2D08,0x4162,0x29B4,0x2314,0x21B3,0x212B, - 0x210C,0x48E3,0x60DE,0x205F,0x20FE,0x2028,0x21A6,0x404F, - 0x20D6,0x2214,0x2127,0x1873,0x40CF,0x206E,0x1B09,0x21C6, - 0x2075,0x19D5,0x2305,0x18D3,0x2076,0x1804,0x230A,0x304B, - 0x20BB,0x18B6,0x1936,0x1B19,0x3037,0x187F,0x18A7,0x1B85, - 0x30BA,0x183B,0x1027,0x18EF,0x1B21,0x1879,0x10AB,0x1917, - 0x1114,0x18BF,0x1074,0x1994,0x2847,0x111B,0x28F2,0x11E5, - 0x19A7,0x113A,0x1046,0x28B7,0x207A,0x182B,0x1155,0x104A, - 0x1344,0x293B,0x11D3,0x2014,0x1044,0x1018,0x13A1,0x1315, - 0x2524,0x20DF,0x10E5,0x1126,0x12A2,0x1824,0x2271,0x11F1, - 0x2964,0x12D1,0x115A,0x092A,0x2341,0x1A2D,0x12E1,0x090A, - 0x13BF,0x0A4D,0x2119,0x0BC1,0x1233,0x1A8A,0x2008,0x1159, - 0x1A89,0x08D5,0x1156,0x0834,0x13EE,0x1169,0x1187,0x1AA3, - 0x1229,0x1331,0x0A85,0x0937,0x1704,0x08FD,0x2124,0x0B13, - 0x1251,0x0AAD,0x082C,0x091A,0x18D9,0x0A99,0x1848,0x18E9, - 0x0B95,0x1144,0x0AF1,0x1A25,0x131A,0x09C5,0x0986,0x1BDF, - 0x0B24,0x0965,0x1262,0x0949,0x0872,0x09C2,0x12C2,0x0916, - 0x085E,0x0B06,0x08CB,0x08C7,0x1242,0x1BEF,0x0A9A,0x1152, - 0x08B3,0x0AA9,0x090B,0x08D2,0x1B22,0x0B04,0x0865,0x0A15, - 0x1286,0x0A83,0x0A95,0x09D1,0x0A06,0x0196,0x1139,0x0A3D, - 0x0933,0x13B1,0x0123,0x0D04,0x08E2,0x122E,0x08A6,0x00CE, - 0x0A31,0x1241,0x0B51,0x1057,0x1171,0x007D,0x1145,0x0A0A, - 0x0129,0x09FF,0x089B,0x085B,0x0063,0x0AB1,0x0A1F,0x0A5D, - 0x0AA5,0x0036,0x0904,0x0B86,0x0A8B,0x0897,0x11E1,0x0332, - 0x083F,0x0A19,0x02B3,0x0859,0x08C3,0x0855,0x11B5,0x01A5, - 0x0AB2,0x0392,0x10DD,0x09A3,0x00ED,0x0907,0x1161,0x002F, - 0x0887,0x0216,0x0ABD,0x0B81,0x0A93,0x0A21,0x003A,0x0ACD, - 0x0AA1,0x0A35,0x0272,0x0BDD,0x03FE,0x0BAF,0x0869,0x0213, - 0x088B,0x020B,0x00B5,0x1035,0x08F1,0x0151,0x0A4E,0x0239, - 0x0BA2,0x00AA,0x0896,0x0382,0x0A08,0x0A05,0x0A09,0x0142, - 0x086D,0x004E,0x0B23,0x0106,0x0807,0x036F,0x0995,0x03FD, - 0x08AF,0x08C5,0x0062,0x0053,0x0B42,0x0826,0x021A,0x01A2, - 0x09B1,0x00C9,0x09B2,0x0045,0x0207,0x08B9,0x00A5,0x0AD2, - 0x0095,0x003E,0x0A32,0x0383,0x0849,0x0135,0x029E,0x0A26, - 0x023E,0x0BFF,0x0A52,0x0311,0x001B,0x0915,0x0A8D,0x0223, - 0x022A,0x0BED,0x0086,0x0A96,0x0222,0x035F,0x0A43,0x085D, - 0x0303,0x0393,0x0A63,0x082A,0x037F,0x0932,0x0043,0x0292, - 0x03CD,0x0BDE,0x009F,0x0125,0x08A9,0x0253,0x0015,0x0192, - 0x0A17,0x08C2,0x0316,0x00D1,0x0282,0x0871,0x0312,0x0122, - 0x0A9F,0x02AE,0x0006,0x0A8E,0x08E1,0x0016,0x0B0B,0x00AE, - 0x0025,0x0193,0x0AC3,0x0017,0x0307,0x00BD,0x08BE,0x0039, - 0x0BB2,0x021B,0x01FD,0x084D,0x03CE,0x00A3,0x0302,0x0BCF, - 0x0033,0x0391,0x028F,0x0852,0x0287,0x008A,0x0333,0x080B, - 0x0131,0x01C1,0x037E,0x0A0F,0x00B1,0x002E,0x0099,0x0902, - 0x009A,0x003D,0x0982,0x0301,0x00CD,0x0941,0x0042,0x0183, - 0x029D,0x08A2,0x021D,0x001A,0x0A97,0x01EF,0x01CE,0x0051, - 0x0BAE,0x022F,0x03BE,0x021E,0x000A,0x09DF,0x0029,0x020D, - 0x02BE,0x029B,0x09EE,0x00B2,0x0912,0x036E,0x009E,0x0022, - 0x0019,0x0892,0x0032,0x01FE,0x0083,0x023F,0x0B96,0x000E, - 0x008F,0x0113,0x0103,0x001E,0x0A0E,0x0013,0x008E,0x0281, - 0x09AF,0x017E,0x0203,0x016F,0x0291,0x0023,0x0093,0x03BD, - 0x001F,0x01CF,0x01DE,0x0201,0x01BF,0x0B4F,0x000F,0x0202, - 0x037D,0x038E,0x0211,0x0212,0x034E,0x039F,0x03AD,0x015F, - 0x017F,0x032E,0x033F,0x034D,0x035E,0x036D,0x032F,0x033E, - 0x035D,0x038F,0x039E + 0x0334, 0x9954, 0x8514, 0x7128, 0x6364, 0xC174, 0x5D34, 0x5866, + 0x5975, 0x5354, 0xAF14, 0x506A, 0x5108, 0x5724, 0x5308, 0x4544, + 0x4918, 0x4064, 0x49E2, 0x4179, 0x8163, 0x4054, 0xF81C, 0x394A, + 0x38F3, 0x4172, 0x38F5, 0xA06F, 0x68EA, 0x69F2, 0x3134, 0x31A4, + 0x305A, 0x68DA, 0x3056, 0x3146, 0x31F5, 0x3148, 0x5A61, 0x32C1, + 0x31D2, 0x307E, 0x29E3, 0x30E6, 0x59C3, 0x2984, 0x29B6, 0x28F9, + 0x5204, 0x28EE, 0x50CA, 0x2997, 0x48C6, 0x4838, 0x2953, 0x200C, + 0x2943, 0x2173, 0x2D08, 0x4162, 0x29B4, 0x2314, 0x21B3, 0x212B, + 0x210C, 0x48E3, 0x60DE, 0x205F, 0x20FE, 0x2028, 0x21A6, 0x404F, + 0x20D6, 0x2214, 0x2127, 0x1873, 0x40CF, 0x206E, 0x1B09, 0x21C6, + 0x2075, 0x19D5, 0x2305, 0x18D3, 0x2076, 0x1804, 0x230A, 0x304B, + 0x20BB, 0x18B6, 0x1936, 0x1B19, 0x3037, 0x187F, 0x18A7, 0x1B85, + 0x30BA, 0x183B, 0x1027, 0x18EF, 0x1B21, 0x1879, 0x10AB, 0x1917, + 0x1114, 0x18BF, 0x1074, 0x1994, 0x2847, 0x111B, 0x28F2, 0x11E5, + 0x19A7, 0x113A, 0x1046, 0x28B7, 0x207A, 0x182B, 0x1155, 0x104A, + 0x1344, 0x293B, 0x11D3, 0x2014, 0x1044, 0x1018, 0x13A1, 0x1315, + 0x2524, 0x20DF, 0x10E5, 0x1126, 0x12A2, 0x1824, 0x2271, 0x11F1, + 0x2964, 0x12D1, 0x115A, 0x092A, 0x2341, 0x1A2D, 0x12E1, 0x090A, + 0x13BF, 0x0A4D, 0x2119, 0x0BC1, 0x1233, 0x1A8A, 0x2008, 0x1159, + 0x1A89, 0x08D5, 0x1156, 0x0834, 0x13EE, 0x1169, 0x1187, 0x1AA3, + 0x1229, 0x1331, 0x0A85, 0x0937, 0x1704, 0x08FD, 0x2124, 0x0B13, + 0x1251, 0x0AAD, 0x082C, 0x091A, 0x18D9, 0x0A99, 0x1848, 0x18E9, + 0x0B95, 0x1144, 0x0AF1, 0x1A25, 0x131A, 0x09C5, 0x0986, 0x1BDF, + 0x0B24, 0x0965, 0x1262, 0x0949, 0x0872, 0x09C2, 0x12C2, 0x0916, + 0x085E, 0x0B06, 0x08CB, 0x08C7, 0x1242, 0x1BEF, 0x0A9A, 0x1152, + 0x08B3, 0x0AA9, 0x090B, 0x08D2, 0x1B22, 0x0B04, 0x0865, 0x0A15, + 0x1286, 0x0A83, 0x0A95, 0x09D1, 0x0A06, 0x0196, 0x1139, 0x0A3D, + 0x0933, 0x13B1, 0x0123, 0x0D04, 0x08E2, 0x122E, 0x08A6, 0x00CE, + 0x0A31, 0x1241, 0x0B51, 0x1057, 0x1171, 0x007D, 0x1145, 0x0A0A, + 0x0129, 0x09FF, 0x089B, 0x085B, 0x0063, 0x0AB1, 0x0A1F, 0x0A5D, + 0x0AA5, 0x0036, 0x0904, 0x0B86, 0x0A8B, 0x0897, 0x11E1, 0x0332, + 0x083F, 0x0A19, 0x02B3, 0x0859, 0x08C3, 0x0855, 0x11B5, 0x01A5, + 0x0AB2, 0x0392, 0x10DD, 0x09A3, 0x00ED, 0x0907, 0x1161, 0x002F, + 0x0887, 0x0216, 0x0ABD, 0x0B81, 0x0A93, 0x0A21, 0x003A, 0x0ACD, + 0x0AA1, 0x0A35, 0x0272, 0x0BDD, 0x03FE, 0x0BAF, 0x0869, 0x0213, + 0x088B, 0x020B, 0x00B5, 0x1035, 0x08F1, 0x0151, 0x0A4E, 0x0239, + 0x0BA2, 0x00AA, 0x0896, 0x0382, 0x0A08, 0x0A05, 0x0A09, 0x0142, + 0x086D, 0x004E, 0x0B23, 0x0106, 0x0807, 0x036F, 0x0995, 0x03FD, + 0x08AF, 0x08C5, 0x0062, 0x0053, 0x0B42, 0x0826, 0x021A, 0x01A2, + 0x09B1, 0x00C9, 0x09B2, 0x0045, 0x0207, 0x08B9, 0x00A5, 0x0AD2, + 0x0095, 0x003E, 0x0A32, 0x0383, 0x0849, 0x0135, 0x029E, 0x0A26, + 0x023E, 0x0BFF, 0x0A52, 0x0311, 0x001B, 0x0915, 0x0A8D, 0x0223, + 0x022A, 0x0BED, 0x0086, 0x0A96, 0x0222, 0x035F, 0x0A43, 0x085D, + 0x0303, 0x0393, 0x0A63, 0x082A, 0x037F, 0x0932, 0x0043, 0x0292, + 0x03CD, 0x0BDE, 0x009F, 0x0125, 0x08A9, 0x0253, 0x0015, 0x0192, + 0x0A17, 0x08C2, 0x0316, 0x00D1, 0x0282, 0x0871, 0x0312, 0x0122, + 0x0A9F, 0x02AE, 0x0006, 0x0A8E, 0x08E1, 0x0016, 0x0B0B, 0x00AE, + 0x0025, 0x0193, 0x0AC3, 0x0017, 0x0307, 0x00BD, 0x08BE, 0x0039, + 0x0BB2, 0x021B, 0x01FD, 0x084D, 0x03CE, 0x00A3, 0x0302, 0x0BCF, + 0x0033, 0x0391, 0x028F, 0x0852, 0x0287, 0x008A, 0x0333, 0x080B, + 0x0131, 0x01C1, 0x037E, 0x0A0F, 0x00B1, 0x002E, 0x0099, 0x0902, + 0x009A, 0x003D, 0x0982, 0x0301, 0x00CD, 0x0941, 0x0042, 0x0183, + 0x029D, 0x08A2, 0x021D, 0x001A, 0x0A97, 0x01EF, 0x01CE, 0x0051, + 0x0BAE, 0x022F, 0x03BE, 0x021E, 0x000A, 0x09DF, 0x0029, 0x020D, + 0x02BE, 0x029B, 0x09EE, 0x00B2, 0x0912, 0x036E, 0x009E, 0x0022, + 0x0019, 0x0892, 0x0032, 0x01FE, 0x0083, 0x023F, 0x0B96, 0x000E, + 0x008F, 0x0113, 0x0103, 0x001E, 0x0A0E, 0x0013, 0x008E, 0x0281, + 0x09AF, 0x017E, 0x0203, 0x016F, 0x0291, 0x0023, 0x0093, 0x03BD, + 0x001F, 0x01CF, 0x01DE, 0x0201, 0x01BF, 0x0B4F, 0x000F, 0x0202, + 0x037D, 0x038E, 0x0211, 0x0212, 0x034E, 0x039F, 0x03AD, 0x015F, + 0x017F, 0x032E, 0x033F, 0x034D, 0x035E, 0x036D, 0x032F, 0x033E, + 0x035D, 0x038F, 0x039E }; static const uint16_t percentile_arr_12x10_1[240] { - 0x0621,0xA443,0xFCC2,0x3CA3,0x1D32,0x14F1,0x7462,0x1433, - 0x27CD,0x2571,0x57AE,0x5DD1,0x64B3,0x44D2,0x2C72,0x25A2, - 0x1E31,0x55DF,0x4C52,0x1DEF,0x0D51,0x3C5D,0x3C3E,0x74DD, - 0x347D,0x27BE,0x5CB5,0x17DD,0x2C14,0x0CAE,0x24B2,0x15FF, - 0x2701,0x0D42,0x1FBD,0x0C35,0x1603,0x060D,0x1D93,0x0C96, - 0x1C07,0x1522,0x0D06,0x0F4F,0x0C9F,0x1F6E,0x0D86,0x0C2E, - 0x1DFE,0x0682,0x1E91,0x0F7D,0x0C86,0x040B,0x1513,0x044E, - 0x14D1,0x0C39,0x14B9,0x1C71,0x05B1,0x0C1F,0x0681,0x1445, - 0x0C16,0x0D95,0x1583,0x0D61,0x0FAD,0x1442,0x048F,0x0D0A, - 0x049A,0x0F6D,0x146D,0x0C2F,0x0D25,0x0406,0x0C1A,0x0D23, - 0x0612,0x0FAF,0x0F11,0x0592,0x0515,0x14E1,0x0602,0x048A, - 0x0E1D,0x0CBD,0x0F9F,0x0423,0x075E,0x174E,0x0426,0x0404, - 0x0C22,0x0CA2,0x0DEE,0x0CA5,0x0F3F,0x05C1,0x0CCD,0x0503, - 0x044D,0x0D16,0x0449,0x0D82,0x0613,0x0585,0x0519,0x0C95, - 0x075F,0x0D35,0x04B1,0x0509,0x0531,0x0DA1,0x049E,0x040A, - 0x05CF,0x0D41,0x0415,0x0692,0x05FD,0x0C25,0x04A1,0x0529, - 0x0591,0x0C93,0x057F,0x04C1,0x0512,0x051A,0x078D,0x0451, - 0x0C0F,0x0487,0x0611,0x0432,0x042A,0x05AF,0x0461,0x072D, - 0x0409,0x0405,0x0D39,0x05DE,0x048E,0x0499,0x0483,0x04A9, - 0x0491,0x042D,0x049D,0x0429,0x040E,0x05AE,0x0521,0x043D, - 0x0581,0x05DD,0x0492,0x0CAD,0x041E,0x058F,0x071F,0x072F, - 0x0419,0x073D,0x057D,0x0511,0x05CE,0x041D,0x0485,0x056E, - 0x0412,0x0431,0x05BF,0x0441,0x054E,0x0489,0x0421,0x0502, - 0x0408,0x040D,0x051F,0x059F,0x073E,0x078F,0x0482,0x079D, - 0x0C02,0x05BE,0x048B,0x0411,0x0505,0x057E,0x052E,0x074D, - 0x077E,0x054F,0x0601,0x055F,0x068D,0x070D,0x070F,0x071E, - 0x072E,0x05CD,0x0403,0x0501,0x055D,0x059E,0x0781,0x0413, - 0x0417,0x041B,0x0453,0x048D,0x052F,0x053E,0x053F,0x055E, - 0x056F,0x058E,0x05BD,0x05ED,0x060E,0x0622,0x0683,0x0702, - 0x070E,0x071D,0x075D,0x076F,0x078E,0x079E,0x07BF,0x07CE + 0x0621, 0xA443, 0xFCC2, 0x3CA3, 0x1D32, 0x14F1, 0x7462, 0x1433, + 0x27CD, 0x2571, 0x57AE, 0x5DD1, 0x64B3, 0x44D2, 0x2C72, 0x25A2, + 0x1E31, 0x55DF, 0x4C52, 0x1DEF, 0x0D51, 0x3C5D, 0x3C3E, 0x74DD, + 0x347D, 0x27BE, 0x5CB5, 0x17DD, 0x2C14, 0x0CAE, 0x24B2, 0x15FF, + 0x2701, 0x0D42, 0x1FBD, 0x0C35, 0x1603, 0x060D, 0x1D93, 0x0C96, + 0x1C07, 0x1522, 0x0D06, 0x0F4F, 0x0C9F, 0x1F6E, 0x0D86, 0x0C2E, + 0x1DFE, 0x0682, 0x1E91, 0x0F7D, 0x0C86, 0x040B, 0x1513, 0x044E, + 0x14D1, 0x0C39, 0x14B9, 0x1C71, 0x05B1, 0x0C1F, 0x0681, 0x1445, + 0x0C16, 0x0D95, 0x1583, 0x0D61, 0x0FAD, 0x1442, 0x048F, 0x0D0A, + 0x049A, 0x0F6D, 0x146D, 0x0C2F, 0x0D25, 0x0406, 0x0C1A, 0x0D23, + 0x0612, 0x0FAF, 0x0F11, 0x0592, 0x0515, 0x14E1, 0x0602, 0x048A, + 0x0E1D, 0x0CBD, 0x0F9F, 0x0423, 0x075E, 0x174E, 0x0426, 0x0404, + 0x0C22, 0x0CA2, 0x0DEE, 0x0CA5, 0x0F3F, 0x05C1, 0x0CCD, 0x0503, + 0x044D, 0x0D16, 0x0449, 0x0D82, 0x0613, 0x0585, 0x0519, 0x0C95, + 0x075F, 0x0D35, 0x04B1, 0x0509, 0x0531, 0x0DA1, 0x049E, 0x040A, + 0x05CF, 0x0D41, 0x0415, 0x0692, 0x05FD, 0x0C25, 0x04A1, 0x0529, + 0x0591, 0x0C93, 0x057F, 0x04C1, 0x0512, 0x051A, 0x078D, 0x0451, + 0x0C0F, 0x0487, 0x0611, 0x0432, 0x042A, 0x05AF, 0x0461, 0x072D, + 0x0409, 0x0405, 0x0D39, 0x05DE, 0x048E, 0x0499, 0x0483, 0x04A9, + 0x0491, 0x042D, 0x049D, 0x0429, 0x040E, 0x05AE, 0x0521, 0x043D, + 0x0581, 0x05DD, 0x0492, 0x0CAD, 0x041E, 0x058F, 0x071F, 0x072F, + 0x0419, 0x073D, 0x057D, 0x0511, 0x05CE, 0x041D, 0x0485, 0x056E, + 0x0412, 0x0431, 0x05BF, 0x0441, 0x054E, 0x0489, 0x0421, 0x0502, + 0x0408, 0x040D, 0x051F, 0x059F, 0x073E, 0x078F, 0x0482, 0x079D, + 0x0C02, 0x05BE, 0x048B, 0x0411, 0x0505, 0x057E, 0x052E, 0x074D, + 0x077E, 0x054F, 0x0601, 0x055F, 0x068D, 0x070D, 0x070F, 0x071E, + 0x072E, 0x05CD, 0x0403, 0x0501, 0x055D, 0x059E, 0x0781, 0x0413, + 0x0417, 0x041B, 0x0453, 0x048D, 0x052F, 0x053E, 0x053F, 0x055E, + 0x056F, 0x058E, 0x05BD, 0x05ED, 0x060E, 0x0622, 0x0683, 0x0702, + 0x070E, 0x071D, 0x075D, 0x076F, 0x078E, 0x079E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_12x10 = @@ -981,107 +986,107 @@ static const packed_percentile_table block_pcd_12x10 = #if ASTCENC_BLOCK_MAX_TEXELS >= (12 * 12) static const uint16_t percentile_arr_12x12_0[529] { - 0x0334,0xF534,0x8514,0x8954,0x7F14,0xFB54,0x7B08,0x7128, - 0x7974,0x6179,0x6B64,0x6908,0x606A,0x6724,0xB544,0xB066, - 0xA14A,0x5118,0x9975,0x51F9,0x981C,0x49CA,0x4854,0x886F, - 0x88D4,0x48EE,0x41E2,0x4163,0x40F3,0x4261,0x4064,0x407E, - 0x385A,0x42C1,0x4172,0x38EA,0x3946,0x78CF,0xA056,0x38DE, - 0x3D08,0x38F9,0x3B14,0x38FE,0xA134,0x38B8,0x31A4,0x71D2, - 0x60DA,0x39C3,0x99BA,0x60CA,0x39F2,0x30F5,0x304F,0x31B6, - 0x31F5,0x3204,0x3148,0x305F,0x2953,0x3194,0x3184,0x310C, - 0x889C,0x300C,0x2943,0x30EF,0x28C6,0x2997,0x2838,0x58E6, - 0x20E4,0x28E3,0x2873,0x29E3,0x2A84,0x28D3,0x492B,0x2962, - 0x286E,0x20BF,0x21AA,0x29A6,0x6A14,0x2828,0x89C6,0x21B3, - 0x2305,0x29B4,0x2173,0x2127,0x20D6,0x407F,0x2294,0x21D9, - 0x21D5,0x2004,0x404B,0x18DF,0x2079,0x219B,0x18A8,0x2385, - 0x1936,0x21AB,0x188C,0x1B09,0x18BA,0x203B,0x187A,0x1875, - 0x2344,0x18BB,0x18B6,0x193A,0x1837,0x1914,0x1846,0x1876, - 0x1884,0x1D24,0x182B,0x284A,0x18A7,0x18AB,0x1917,0x322D, - 0x1047,0x1874,0x1818,0x18F2,0x1164,0x1B89,0x2959,0x1B21, - 0x39E5,0x1827,0x10F4,0x18B7,0x11D3,0x1A4D,0x1315,0x12AD, - 0x1AD1,0x3A71,0x1319,0x11A7,0x2044,0x2F04,0x2341,0x10E5, - 0x1155,0x195A,0x1024,0x111B,0x1251,0x1233,0x12E1,0x13A1, - 0x13BF,0x212A,0x22A2,0x113B,0x23DF,0x10D5,0x2399,0x0814, - 0x1126,0x13EE,0x1285,0x10C4,0x18FD,0x20D9,0x0987,0x1242, - 0x29C5,0x2313,0x0898,0x13C1,0x08C8,0x11F1,0x1034,0x1B24, - 0x0B0A,0x11E9,0x0808,0x125D,0x18E9,0x0848,0x1395,0x0965, - 0x123D,0x2186,0x1295,0x18CE,0x098B,0x0BEF,0x1504,0x082C, - 0x0A41,0x1144,0x0A89,0x0956,0x1331,0x085E,0x0B04,0x128A, - 0x12A3,0x1937,0x19C2,0x0952,0x0872,0x08B4,0x1262,0x1124, - 0x1969,0x1063,0x0AF1,0x1225,0x0894,0x11C9,0x18D2,0x0ACD, - 0x0A29,0x0B06,0x09B5,0x18C7,0x0916,0x1088,0x09FF,0x2206, - 0x0A15,0x08B3,0x0B51,0x0A1F,0x18CB,0x0AC2,0x0A2E,0x1865, - 0x08AC,0x0A31,0x08A4,0x138A,0x0A99,0x09D1,0x0A86,0x189B, - 0x0283,0x0BDD,0x0ABD,0x1933,0x083F,0x1386,0x0923,0x0322, - 0x0869,0x10DD,0x13B1,0x082F,0x087D,0x11B9,0x085B,0x08ED, - 0x00C3,0x08E2,0x084E,0x0887,0x0855,0x0A0A,0x0857,0x0B92, - 0x1036,0x12A5,0x0293,0x0945,0x08A6,0x0196,0x19A3,0x036F, - 0x0904,0x1205,0x09E1,0x0381,0x0971,0x1219,0x0BAF,0x0949, - 0x00AF,0x0AA9,0x018A,0x0907,0x0BFD,0x003A,0x0BCD,0x0AB2, - 0x088B,0x0252,0x0A4E,0x03FF,0x0845,0x0897,0x0059,0x090B, - 0x0B42,0x0807,0x0A16,0x0853,0x0A8D,0x01B2,0x0AB1,0x091A, - 0x0195,0x0A35,0x00B5,0x10AA,0x0115,0x0A21,0x0096,0x0A08, - 0x03FE,0x0B7F,0x08B9,0x12B3,0x023E,0x0A23,0x029E,0x08F1, - 0x01A9,0x0BDE,0x0843,0x02D2,0x0A1A,0x08C5,0x0151,0x0A43, - 0x0332,0x0383,0x0826,0x0BED,0x10C2,0x00AE,0x0B82,0x0213, - 0x0232,0x085D,0x02A1,0x101B,0x035F,0x0303,0x0A39,0x0207, - 0x0A53,0x0142,0x01A5,0x082A,0x0099,0x0A17,0x03CF,0x0906, - 0x0125,0x0A96,0x0A9A,0x0209,0x0393,0x0961,0x0131,0x0A88, - 0x0139,0x099A,0x0292,0x0272,0x0862,0x08BE,0x0141,0x02C3, - 0x0886,0x0039,0x08A9,0x01A2,0x01B1,0x0851,0x020B,0x086D, - 0x0312,0x08CD,0x020F,0x0311,0x0BCE,0x0135,0x0006,0x0849, - 0x0132,0x0A8F,0x022F,0x022A,0x0AAE,0x0A8E,0x0263,0x03A2, - 0x083E,0x009A,0x021B,0x0835,0x0323,0x0871,0x0993,0x0226, - 0x0302,0x0922,0x0119,0x0222,0x021D,0x0B07,0x08C9,0x037E, - 0x08BD,0x0042,0x00D1,0x0B33,0x01C1,0x0B9A,0x0282,0x088A, - 0x0182,0x083D,0x004D,0x010A,0x0A1E,0x0019,0x00B2,0x0999, - 0x00A5,0x0095,0x0817,0x0022,0x031A,0x0902,0x00A3,0x01BF, - 0x029F,0x0816,0x03B2,0x0015,0x0391,0x0BBE,0x01FE,0x1129, - 0x002E,0x01DF,0x0301,0x0033,0x0B6E,0x00E1,0x0297,0x00B1, - 0x009F,0x0B16,0x000A,0x001A,0x0052,0x080B,0x030B,0x029D, - 0x0BAE,0x01FD,0x020E,0x00A2,0x0A3F,0x0192,0x0ABE,0x020D, - 0x008F,0x028B,0x0083,0x0025,0x09EE,0x01EF,0x0029,0x0291, - 0x0B4F,0x0396,0x0287,0x008E,0x0092,0x0B4E,0x017E,0x001E, - 0x009E,0x0103,0x080F,0x000E,0x0113,0x0203,0x01CF,0x0183, - 0x01CE,0x001F,0x0112,0x01DE,0x038E,0x0832,0x033E,0x0212, - 0x029B,0x0023,0x016F,0x0201,0x09AF,0x0202,0x0281,0x035E, - 0x034D,0x037D,0x03AD,0x0013,0x0093,0x015F,0x0211,0x033F, - 0x036D,0x039F,0x03BD,0x017F,0x032E,0x032F,0x035D,0x038F, + 0x0334, 0xF534, 0x8514, 0x8954, 0x7F14, 0xFB54, 0x7B08, 0x7128, + 0x7974, 0x6179, 0x6B64, 0x6908, 0x606A, 0x6724, 0xB544, 0xB066, + 0xA14A, 0x5118, 0x9975, 0x51F9, 0x981C, 0x49CA, 0x4854, 0x886F, + 0x88D4, 0x48EE, 0x41E2, 0x4163, 0x40F3, 0x4261, 0x4064, 0x407E, + 0x385A, 0x42C1, 0x4172, 0x38EA, 0x3946, 0x78CF, 0xA056, 0x38DE, + 0x3D08, 0x38F9, 0x3B14, 0x38FE, 0xA134, 0x38B8, 0x31A4, 0x71D2, + 0x60DA, 0x39C3, 0x99BA, 0x60CA, 0x39F2, 0x30F5, 0x304F, 0x31B6, + 0x31F5, 0x3204, 0x3148, 0x305F, 0x2953, 0x3194, 0x3184, 0x310C, + 0x889C, 0x300C, 0x2943, 0x30EF, 0x28C6, 0x2997, 0x2838, 0x58E6, + 0x20E4, 0x28E3, 0x2873, 0x29E3, 0x2A84, 0x28D3, 0x492B, 0x2962, + 0x286E, 0x20BF, 0x21AA, 0x29A6, 0x6A14, 0x2828, 0x89C6, 0x21B3, + 0x2305, 0x29B4, 0x2173, 0x2127, 0x20D6, 0x407F, 0x2294, 0x21D9, + 0x21D5, 0x2004, 0x404B, 0x18DF, 0x2079, 0x219B, 0x18A8, 0x2385, + 0x1936, 0x21AB, 0x188C, 0x1B09, 0x18BA, 0x203B, 0x187A, 0x1875, + 0x2344, 0x18BB, 0x18B6, 0x193A, 0x1837, 0x1914, 0x1846, 0x1876, + 0x1884, 0x1D24, 0x182B, 0x284A, 0x18A7, 0x18AB, 0x1917, 0x322D, + 0x1047, 0x1874, 0x1818, 0x18F2, 0x1164, 0x1B89, 0x2959, 0x1B21, + 0x39E5, 0x1827, 0x10F4, 0x18B7, 0x11D3, 0x1A4D, 0x1315, 0x12AD, + 0x1AD1, 0x3A71, 0x1319, 0x11A7, 0x2044, 0x2F04, 0x2341, 0x10E5, + 0x1155, 0x195A, 0x1024, 0x111B, 0x1251, 0x1233, 0x12E1, 0x13A1, + 0x13BF, 0x212A, 0x22A2, 0x113B, 0x23DF, 0x10D5, 0x2399, 0x0814, + 0x1126, 0x13EE, 0x1285, 0x10C4, 0x18FD, 0x20D9, 0x0987, 0x1242, + 0x29C5, 0x2313, 0x0898, 0x13C1, 0x08C8, 0x11F1, 0x1034, 0x1B24, + 0x0B0A, 0x11E9, 0x0808, 0x125D, 0x18E9, 0x0848, 0x1395, 0x0965, + 0x123D, 0x2186, 0x1295, 0x18CE, 0x098B, 0x0BEF, 0x1504, 0x082C, + 0x0A41, 0x1144, 0x0A89, 0x0956, 0x1331, 0x085E, 0x0B04, 0x128A, + 0x12A3, 0x1937, 0x19C2, 0x0952, 0x0872, 0x08B4, 0x1262, 0x1124, + 0x1969, 0x1063, 0x0AF1, 0x1225, 0x0894, 0x11C9, 0x18D2, 0x0ACD, + 0x0A29, 0x0B06, 0x09B5, 0x18C7, 0x0916, 0x1088, 0x09FF, 0x2206, + 0x0A15, 0x08B3, 0x0B51, 0x0A1F, 0x18CB, 0x0AC2, 0x0A2E, 0x1865, + 0x08AC, 0x0A31, 0x08A4, 0x138A, 0x0A99, 0x09D1, 0x0A86, 0x189B, + 0x0283, 0x0BDD, 0x0ABD, 0x1933, 0x083F, 0x1386, 0x0923, 0x0322, + 0x0869, 0x10DD, 0x13B1, 0x082F, 0x087D, 0x11B9, 0x085B, 0x08ED, + 0x00C3, 0x08E2, 0x084E, 0x0887, 0x0855, 0x0A0A, 0x0857, 0x0B92, + 0x1036, 0x12A5, 0x0293, 0x0945, 0x08A6, 0x0196, 0x19A3, 0x036F, + 0x0904, 0x1205, 0x09E1, 0x0381, 0x0971, 0x1219, 0x0BAF, 0x0949, + 0x00AF, 0x0AA9, 0x018A, 0x0907, 0x0BFD, 0x003A, 0x0BCD, 0x0AB2, + 0x088B, 0x0252, 0x0A4E, 0x03FF, 0x0845, 0x0897, 0x0059, 0x090B, + 0x0B42, 0x0807, 0x0A16, 0x0853, 0x0A8D, 0x01B2, 0x0AB1, 0x091A, + 0x0195, 0x0A35, 0x00B5, 0x10AA, 0x0115, 0x0A21, 0x0096, 0x0A08, + 0x03FE, 0x0B7F, 0x08B9, 0x12B3, 0x023E, 0x0A23, 0x029E, 0x08F1, + 0x01A9, 0x0BDE, 0x0843, 0x02D2, 0x0A1A, 0x08C5, 0x0151, 0x0A43, + 0x0332, 0x0383, 0x0826, 0x0BED, 0x10C2, 0x00AE, 0x0B82, 0x0213, + 0x0232, 0x085D, 0x02A1, 0x101B, 0x035F, 0x0303, 0x0A39, 0x0207, + 0x0A53, 0x0142, 0x01A5, 0x082A, 0x0099, 0x0A17, 0x03CF, 0x0906, + 0x0125, 0x0A96, 0x0A9A, 0x0209, 0x0393, 0x0961, 0x0131, 0x0A88, + 0x0139, 0x099A, 0x0292, 0x0272, 0x0862, 0x08BE, 0x0141, 0x02C3, + 0x0886, 0x0039, 0x08A9, 0x01A2, 0x01B1, 0x0851, 0x020B, 0x086D, + 0x0312, 0x08CD, 0x020F, 0x0311, 0x0BCE, 0x0135, 0x0006, 0x0849, + 0x0132, 0x0A8F, 0x022F, 0x022A, 0x0AAE, 0x0A8E, 0x0263, 0x03A2, + 0x083E, 0x009A, 0x021B, 0x0835, 0x0323, 0x0871, 0x0993, 0x0226, + 0x0302, 0x0922, 0x0119, 0x0222, 0x021D, 0x0B07, 0x08C9, 0x037E, + 0x08BD, 0x0042, 0x00D1, 0x0B33, 0x01C1, 0x0B9A, 0x0282, 0x088A, + 0x0182, 0x083D, 0x004D, 0x010A, 0x0A1E, 0x0019, 0x00B2, 0x0999, + 0x00A5, 0x0095, 0x0817, 0x0022, 0x031A, 0x0902, 0x00A3, 0x01BF, + 0x029F, 0x0816, 0x03B2, 0x0015, 0x0391, 0x0BBE, 0x01FE, 0x1129, + 0x002E, 0x01DF, 0x0301, 0x0033, 0x0B6E, 0x00E1, 0x0297, 0x00B1, + 0x009F, 0x0B16, 0x000A, 0x001A, 0x0052, 0x080B, 0x030B, 0x029D, + 0x0BAE, 0x01FD, 0x020E, 0x00A2, 0x0A3F, 0x0192, 0x0ABE, 0x020D, + 0x008F, 0x028B, 0x0083, 0x0025, 0x09EE, 0x01EF, 0x0029, 0x0291, + 0x0B4F, 0x0396, 0x0287, 0x008E, 0x0092, 0x0B4E, 0x017E, 0x001E, + 0x009E, 0x0103, 0x080F, 0x000E, 0x0113, 0x0203, 0x01CF, 0x0183, + 0x01CE, 0x001F, 0x0112, 0x01DE, 0x038E, 0x0832, 0x033E, 0x0212, + 0x029B, 0x0023, 0x016F, 0x0201, 0x09AF, 0x0202, 0x0281, 0x035E, + 0x034D, 0x037D, 0x03AD, 0x0013, 0x0093, 0x015F, 0x0211, 0x033F, + 0x036D, 0x039F, 0x03BD, 0x017F, 0x032E, 0x032F, 0x035D, 0x038F, 0x039E }; static const uint16_t percentile_arr_12x12_1[246] { - 0x0443,0xFFCD,0x2C62,0x2E21,0x3CF1,0x34C2,0x4CDD,0x2452, - 0xD5DF,0x1DD1,0x0FAE,0x64A3,0x0C7D,0x3433,0x1CD2,0x2DEF, - 0x0C3E,0x1D71,0xA472,0x0D32,0x54B3,0x4D51,0x445D,0x0E31, - 0x1FDD,0x0DFF,0x0CAE,0x45A2,0x2FBE,0xA4B9,0x1C4E,0x2C9F, - 0x160D,0x0D42,0x342E,0x074F,0x1414,0x0F6E,0x0CB2,0x34B5, - 0x0DFE,0x0D86,0x1496,0x1D22,0x0691,0x140B,0x041F,0x0C35, - 0x1D93,0x1506,0x1439,0x0C9A,0x0F01,0x2442,0x0C8F,0x04D1, - 0x1486,0x0C6D,0x0513,0x0C71,0x0E82,0x177D,0x0E03,0x07BD, - 0x0C2F,0x0D83,0x07AF,0x0D61,0x1407,0x0DB1,0x050A,0x0C94, - 0x07AD,0x0D8A,0x0C04,0x0416,0x0C49,0x0445,0x15C1,0x0C1A, - 0x0525,0x0595,0x0C8A,0x075E,0x0CBD,0x0681,0x0F4E,0x075F, - 0x061D,0x1541,0x0CB1,0x0F3F,0x0406,0x076D,0x0DCF,0x05EE, - 0x0D23,0x0599,0x0CCD,0x0711,0x0C23,0x079F,0x0D15,0x0585, - 0x04A2,0x042A,0x0D31,0x05BF,0x0D92,0x0C26,0x043D,0x0C93, - 0x0502,0x0C15,0x048B,0x0D03,0x0613,0x0516,0x0495,0x0C29, - 0x04A5,0x040F,0x0425,0x0539,0x0D19,0x04E1,0x05BE,0x0422, - 0x0432,0x0C0A,0x0431,0x041E,0x0492,0x04A9,0x0582,0x0529, - 0x0487,0x0C4D,0x0512,0x049E,0x0505,0x0451,0x0D7F,0x0489, - 0x0602,0x05DE,0x0591,0x0535,0x074D,0x055E,0x04C1,0x0612, - 0x05DD,0x05FD,0x0C61,0x0521,0x0484,0x05CE,0x0581,0x0491, - 0x051A,0x04A1,0x048E,0x040D,0x0499,0x071F,0x072E,0x075D, - 0x0441,0x0589,0x057E,0x0CAD,0x0501,0x054F,0x0692,0x0511, - 0x049D,0x0509,0x056E,0x040E,0x0409,0x0601,0x048D,0x0413, - 0x053E,0x0419,0x072D,0x0408,0x0485,0x042D,0x041D,0x05A1, - 0x0781,0x0402,0x05ED,0x0C82,0x0403,0x057D,0x05CD,0x0611, - 0x0488,0x0411,0x054E,0x051F,0x053F,0x056F,0x059F,0x070F, - 0x071D,0x073D,0x073E,0x077E,0x078F,0x0405,0x079D,0x079E, - 0x058E,0x0412,0x055D,0x05AE,0x041B,0x0421,0x0453,0x0417, - 0x0483,0x052E,0x052F,0x055F,0x058F,0x059E,0x05AF,0x05BD, - 0x060E,0x0622,0x0683,0x068D,0x0702,0x070D,0x070E,0x071E, - 0x072F,0x076F,0x078D,0x078E,0x07BF,0x07CE + 0x0443, 0xFFCD, 0x2C62, 0x2E21, 0x3CF1, 0x34C2, 0x4CDD, 0x2452, + 0xD5DF, 0x1DD1, 0x0FAE, 0x64A3, 0x0C7D, 0x3433, 0x1CD2, 0x2DEF, + 0x0C3E, 0x1D71, 0xA472, 0x0D32, 0x54B3, 0x4D51, 0x445D, 0x0E31, + 0x1FDD, 0x0DFF, 0x0CAE, 0x45A2, 0x2FBE, 0xA4B9, 0x1C4E, 0x2C9F, + 0x160D, 0x0D42, 0x342E, 0x074F, 0x1414, 0x0F6E, 0x0CB2, 0x34B5, + 0x0DFE, 0x0D86, 0x1496, 0x1D22, 0x0691, 0x140B, 0x041F, 0x0C35, + 0x1D93, 0x1506, 0x1439, 0x0C9A, 0x0F01, 0x2442, 0x0C8F, 0x04D1, + 0x1486, 0x0C6D, 0x0513, 0x0C71, 0x0E82, 0x177D, 0x0E03, 0x07BD, + 0x0C2F, 0x0D83, 0x07AF, 0x0D61, 0x1407, 0x0DB1, 0x050A, 0x0C94, + 0x07AD, 0x0D8A, 0x0C04, 0x0416, 0x0C49, 0x0445, 0x15C1, 0x0C1A, + 0x0525, 0x0595, 0x0C8A, 0x075E, 0x0CBD, 0x0681, 0x0F4E, 0x075F, + 0x061D, 0x1541, 0x0CB1, 0x0F3F, 0x0406, 0x076D, 0x0DCF, 0x05EE, + 0x0D23, 0x0599, 0x0CCD, 0x0711, 0x0C23, 0x079F, 0x0D15, 0x0585, + 0x04A2, 0x042A, 0x0D31, 0x05BF, 0x0D92, 0x0C26, 0x043D, 0x0C93, + 0x0502, 0x0C15, 0x048B, 0x0D03, 0x0613, 0x0516, 0x0495, 0x0C29, + 0x04A5, 0x040F, 0x0425, 0x0539, 0x0D19, 0x04E1, 0x05BE, 0x0422, + 0x0432, 0x0C0A, 0x0431, 0x041E, 0x0492, 0x04A9, 0x0582, 0x0529, + 0x0487, 0x0C4D, 0x0512, 0x049E, 0x0505, 0x0451, 0x0D7F, 0x0489, + 0x0602, 0x05DE, 0x0591, 0x0535, 0x074D, 0x055E, 0x04C1, 0x0612, + 0x05DD, 0x05FD, 0x0C61, 0x0521, 0x0484, 0x05CE, 0x0581, 0x0491, + 0x051A, 0x04A1, 0x048E, 0x040D, 0x0499, 0x071F, 0x072E, 0x075D, + 0x0441, 0x0589, 0x057E, 0x0CAD, 0x0501, 0x054F, 0x0692, 0x0511, + 0x049D, 0x0509, 0x056E, 0x040E, 0x0409, 0x0601, 0x048D, 0x0413, + 0x053E, 0x0419, 0x072D, 0x0408, 0x0485, 0x042D, 0x041D, 0x05A1, + 0x0781, 0x0402, 0x05ED, 0x0C82, 0x0403, 0x057D, 0x05CD, 0x0611, + 0x0488, 0x0411, 0x054E, 0x051F, 0x053F, 0x056F, 0x059F, 0x070F, + 0x071D, 0x073D, 0x073E, 0x077E, 0x078F, 0x0405, 0x079D, 0x079E, + 0x058E, 0x0412, 0x055D, 0x05AE, 0x041B, 0x0421, 0x0453, 0x0417, + 0x0483, 0x052E, 0x052F, 0x055F, 0x058F, 0x059E, 0x05AF, 0x05BD, + 0x060E, 0x0622, 0x0683, 0x068D, 0x0702, 0x070D, 0x070E, 0x071E, + 0x072F, 0x076F, 0x078D, 0x078E, 0x07BF, 0x07CE }; static const packed_percentile_table block_pcd_12x12 { @@ -1161,11 +1166,11 @@ const float *get_2d_percentile_table( unsigned int xdim, unsigned int ydim ) { - float* unpacked_table = new float[2048]; + float* unpacked_table = new float[WEIGHTS_MAX_BLOCK_MODES]; const packed_percentile_table *apt = get_packed_table(xdim, ydim); // Set the default percentile - for (unsigned int i = 0; i < 2048; i++) + for (unsigned int i = 0; i < WEIGHTS_MAX_BLOCK_MODES; i++) { unpacked_table[i] = 1.0f; } @@ -1173,7 +1178,7 @@ const float *get_2d_percentile_table( // Populate the unpacked percentile values for (int i = 0; i < 2; i++) { - unsigned int itemcount = apt->itemcounts[i]; + unsigned int itemcount = apt->item_count[i]; unsigned int difscale = apt->difscales[i]; unsigned int accum = apt->initial_percs[i]; const uint16_t *item_ptr = apt->items[i]; diff --git a/Source/astcenc_pick_best_endpoint_format.cpp b/Source/astcenc_pick_best_endpoint_format.cpp index 48768ed..4d8b4f7 100644 --- a/Source/astcenc_pick_best_endpoint_format.cpp +++ b/Source/astcenc_pick_best_endpoint_format.cpp @@ -289,25 +289,13 @@ static void compute_encoding_choice_errors( vmask4 endpt_can_offset = endpt_diff < vfloat4(0.12f * 65535.0f); bool can_offset_encode = (mask(endpt_can_offset) & 0x7) == 0x7; - // Determine if we can blue contract encode RGB lanes - vfloat4 endpt_diff_bc( - endpt0.lane<0>() + (endpt0.lane<0>() - endpt0.lane<2>()), - endpt1.lane<0>() + (endpt1.lane<0>() - endpt1.lane<2>()), - endpt0.lane<1>() + (endpt0.lane<1>() - endpt0.lane<2>()), - endpt1.lane<1>() + (endpt1.lane<1>() - endpt1.lane<2>()) - ); - - vmask4 endpt_can_bc_lo = endpt_diff_bc > vfloat4(0.01f * 65535.0f); - vmask4 endpt_can_bc_hi = endpt_diff_bc < vfloat4(0.99f * 65535.0f); - bool can_blue_contract = (mask(endpt_can_bc_lo & endpt_can_bc_hi) & 0x7) == 0x7; - // Store out the settings eci[i].rgb_scale_error = (samechroma_rgb_error - uncorr_rgb_error) * 0.7f; // empirical eci[i].rgb_luma_error = (rgb_luma_error - uncorr_rgb_error) * 1.5f; // wild guess eci[i].luminance_error = (luminance_rgb_error - uncorr_rgb_error) * 3.0f; // empirical eci[i].alpha_drop_error = alpha_drop_error * 3.0f; eci[i].can_offset_encode = can_offset_encode; - eci[i].can_blue_contract = can_blue_contract; + eci[i].can_blue_contract = !blk.is_luminance(); } } @@ -333,15 +321,11 @@ static void compute_color_error_for_every_integer_count_and_quant_level( const endpoints& ep, vfloat4 error_weight, float best_error[21][4], - int format_of_choice[21][4] + uint8_t format_of_choice[21][4] ) { int partition_size = pi.partition_texel_count[partition_index]; - static const float baseline_quant_error[21] { - (65536.0f * 65536.0f / 18.0f), // 2 values, 1 step - (65536.0f * 65536.0f / 18.0f) / (2 * 2), // 3 values, 2 steps - (65536.0f * 65536.0f / 18.0f) / (3 * 3), // 4 values, 3 steps - (65536.0f * 65536.0f / 18.0f) / (4 * 4), // 5 values + static const float baseline_quant_error[21 - QUANT_6] { (65536.0f * 65536.0f / 18.0f) / (5 * 5), (65536.0f * 65536.0f / 18.0f) / (7 * 7), (65536.0f * 65536.0f / 18.0f) / (9 * 9), @@ -529,7 +513,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level( best_error[i][1] = ERROR_CALC_DEFAULT; best_error[i][0] = ERROR_CALC_DEFAULT; - format_of_choice[i][3] = encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA; + format_of_choice[i][3] = static_cast(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA); format_of_choice[i][2] = FMT_HDR_RGB; format_of_choice[i][1] = FMT_HDR_RGB_SCALE; format_of_choice[i][0] = FMT_HDR_LUMINANCE_LARGE_RANGE; @@ -540,7 +524,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level( // The base_quant_error should depend on the scale-factor that would be used during // actual encode of the color value - float base_quant_error = baseline_quant_error[i] * static_cast(partition_size); + float base_quant_error = baseline_quant_error[i - QUANT_6] * static_cast(partition_size); float rgb_quantization_error = error_weight_rgbsum * base_quant_error * 2.0f; float alpha_quantization_error = error_weight.lane<3>() * base_quant_error * 2.0f; float rgba_quantization_error = rgb_quantization_error + alpha_quantization_error; @@ -549,7 +533,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level( float full_hdr_rgba_error = rgba_quantization_error + rgb_range_error + alpha_range_error; best_error[i][3] = full_hdr_rgba_error; - format_of_choice[i][3] = encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA; + format_of_choice[i][3] = static_cast(encode_hdr_alpha ? FMT_HDR_RGBA : FMT_HDR_RGB_LDR_ALPHA); // For 6 integers, we have one HDR-RGB encoding float full_hdr_rgb_error = (rgb_quantization_error * mode11mult) + rgb_range_error + eci.alpha_drop_error; @@ -603,7 +587,7 @@ static void compute_color_error_for_every_integer_count_and_quant_level( error_scale_oe_rgb = 1.0f; } - float base_quant_error = baseline_quant_error[i]; + float base_quant_error = baseline_quant_error[i - QUANT_6]; float quant_error_rgb = base_quant_error_rgb * base_quant_error; float quant_error_rgba = base_quant_error_rgba * base_quant_error; @@ -688,10 +672,10 @@ static void compute_color_error_for_every_integer_count_and_quant_level( static float one_partition_find_best_combination_for_bitcount( QualityProfile privateProfile, const float best_combined_error[21][4], - const int best_combined_format[21][4], + const uint8_t best_combined_format[21][4], int bits_available, - quant_method& best_quant_level, - int& best_format + uint8_t& best_quant_level, + uint8_t& best_format ) { int best_integer_count = 0; float best_integer_count_error = ERROR_CALC_DEFAULT; @@ -721,7 +705,7 @@ static float one_partition_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count + 1][bits_available]; - best_quant_level = static_cast(ql); + best_quant_level = static_cast(ql); if (privateProfile == HIGH_SPEED_PROFILE) // keep openSource code style { best_format = FMT_RGBA; @@ -749,9 +733,9 @@ static float one_partition_find_best_combination_for_bitcount( */ static void two_partitions_find_best_combination_for_every_quantization_and_integer_count( const float best_error[2][21][4], // indexed by (partition, quant-level, integer-pair-count-minus-1) - const int best_format[2][21][4], + const uint8_t best_format[2][21][4], float best_combined_error[21][7], // indexed by (quant-level, integer-pair-count-minus-2) - int best_combined_format[21][7][2] + uint8_t best_combined_format[21][7][2] ) { for (int i = QUANT_2; i <= QUANT_256; i++) { @@ -801,11 +785,11 @@ static void two_partitions_find_best_combination_for_every_quantization_and_inte */ static float two_partitions_find_best_combination_for_bitcount( float best_combined_error[21][7], - int best_combined_format[21][7][2], + uint8_t best_combined_format[21][7][2], int bits_available, - quant_method& best_quant_level, - quant_method& best_quant_level_mod, - int* best_formats + uint8_t& best_quant_level, + uint8_t& best_quant_level_mod, + uint8_t* best_formats ) { int best_integer_count = 0; float best_integer_count_error = ERROR_CALC_DEFAULT; @@ -832,8 +816,8 @@ static float two_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 2]; - best_quant_level = static_cast(ql); - best_quant_level_mod = static_cast(ql_mod); + best_quant_level = static_cast(ql); + best_quant_level_mod = static_cast(ql_mod); if (ql >= QUANT_6) { @@ -863,9 +847,9 @@ static float two_partitions_find_best_combination_for_bitcount( */ static void three_partitions_find_best_combination_for_every_quantization_and_integer_count( const float best_error[3][21][4], // indexed by (partition, quant-level, integer-count) - const int best_format[3][21][4], + const uint8_t best_format[3][21][4], float best_combined_error[21][10], - int best_combined_format[21][10][3] + uint8_t best_combined_format[21][10][3] ) { for (int i = QUANT_2; i <= QUANT_256; i++) { @@ -926,11 +910,11 @@ static void three_partitions_find_best_combination_for_every_quantization_and_in */ static float three_partitions_find_best_combination_for_bitcount( const float best_combined_error[21][10], - const int best_combined_format[21][10][3], + const uint8_t best_combined_format[21][10][3], int bits_available, - quant_method& best_quant_level, - quant_method& best_quant_level_mod, - int* best_formats + uint8_t& best_quant_level, + uint8_t& best_quant_level_mod, + uint8_t* best_formats ) { int best_integer_count = 0; float best_integer_count_error = ERROR_CALC_DEFAULT; @@ -957,8 +941,8 @@ static float three_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 5]; - best_quant_level = static_cast(ql); - best_quant_level_mod = static_cast(ql_mod); + best_quant_level = static_cast(ql); + best_quant_level_mod = static_cast(ql_mod); if (ql >= QUANT_6) { @@ -988,9 +972,9 @@ static float three_partitions_find_best_combination_for_bitcount( */ static void four_partitions_find_best_combination_for_every_quantization_and_integer_count( const float best_error[4][21][4], // indexed by (partition, quant-level, integer-count) - const int best_format[4][21][4], + const uint8_t best_format[4][21][4], float best_combined_error[21][13], - int best_combined_format[21][13][4] + uint8_t best_combined_format[21][13][4] ) { for (int i = QUANT_2; i <= QUANT_256; i++) { @@ -1062,11 +1046,11 @@ static void four_partitions_find_best_combination_for_every_quantization_and_int */ static float four_partitions_find_best_combination_for_bitcount( const float best_combined_error[21][13], - const int best_combined_format[21][13][4], + const uint8_t best_combined_format[21][13][4], int bits_available, - quant_method& best_quant_level, - quant_method& best_quant_level_mod, - int* best_formats + uint8_t& best_quant_level, + uint8_t& best_quant_level_mod, + uint8_t* best_formats ) { int best_integer_count = 0; float best_integer_count_error = ERROR_CALC_DEFAULT; @@ -1093,8 +1077,8 @@ static float four_partitions_find_best_combination_for_bitcount( int ql = quant_mode_table[best_integer_count][bits_available]; int ql_mod = quant_mode_table[best_integer_count][bits_available + 8]; - best_quant_level = static_cast(ql); - best_quant_level_mod = static_cast(ql_mod); + best_quant_level = static_cast(ql); + best_quant_level_mod = static_cast(ql_mod); if (ql >= QUANT_6) { @@ -1121,13 +1105,13 @@ unsigned int compute_ideal_endpoint_formats( const image_block& blk, const endpoints& ep, // bitcounts and errors computed for the various quantization methods - const int* qwt_bitcounts, + const int8_t* qwt_bitcounts, const float* qwt_errors, unsigned int tune_candidate_limit, unsigned int start_block_mode, unsigned int end_block_mode, // output data - int partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS], + uint8_t partition_format_specifiers[TUNE_MAX_TRIAL_CANDIDATES][BLOCK_MAX_PARTITIONS], int block_mode[TUNE_MAX_TRIAL_CANDIDATES], quant_method quant_level[TUNE_MAX_TRIAL_CANDIDATES], quant_method quant_level_mod[TUNE_MAX_TRIAL_CANDIDATES], @@ -1137,8 +1121,8 @@ unsigned int compute_ideal_endpoint_formats( promise(partition_count > 0); - int encode_hdr_rgb = blk.rgb_lns[0]; - int encode_hdr_alpha = blk.alpha_lns[0]; + bool encode_hdr_rgb = static_cast(blk.rgb_lns[0]); + bool encode_hdr_alpha = static_cast(blk.alpha_lns[0]); // Compute the errors that result from various encoding choices (such as using luminance instead // of RGB, discarding Alpha, using RGB-scale in place of two separate RGB endpoints and so on) @@ -1146,7 +1130,7 @@ unsigned int compute_ideal_endpoint_formats( compute_encoding_choice_errors(blk, pi, ep, eci); float best_error[BLOCK_MAX_PARTITIONS][21][4]; - int format_of_choice[BLOCK_MAX_PARTITIONS][21][4]; + uint8_t format_of_choice[BLOCK_MAX_PARTITIONS][21][4]; for (int i = 0; i < partition_count; i++) { compute_color_error_for_every_integer_count_and_quant_level( @@ -1156,28 +1140,24 @@ unsigned int compute_ideal_endpoint_formats( } float* errors_of_best_combination = tmpbuf.errors_of_best_combination; - quant_method* best_quant_levels = tmpbuf.best_quant_levels; - quant_method* best_quant_levels_mod = tmpbuf.best_quant_levels_mod; - int (&best_ep_formats)[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS] = tmpbuf.best_ep_formats; + uint8_t* best_quant_levels = tmpbuf.best_quant_levels; + uint8_t* best_quant_levels_mod = tmpbuf.best_quant_levels_mod; + uint8_t (&best_ep_formats)[WEIGHTS_MAX_BLOCK_MODES][BLOCK_MAX_PARTITIONS] = tmpbuf.best_ep_formats; - // Ensure that the "overstep" of the last iteration in the vectorized loop will contain data - // that will never be picked as best candidate - const unsigned int packed_end_block_mode = round_up_to_simd_multiple_vla(end_block_mode); + // Ensure that the first iteration understep contains data that will never be picked + vfloat clear_error(ERROR_CALC_DEFAULT); + vint clear_quant(0); - // TODO: Can we avoid this? - for (unsigned int i = 0; i < start_block_mode; i++) - { - errors_of_best_combination[i] = ERROR_CALC_DEFAULT; - best_quant_levels[i] = QUANT_2; - best_quant_levels_mod[i] = QUANT_2; - } + unsigned int packed_start_block_mode = round_down_to_simd_multiple_vla(start_block_mode); + storea(clear_error, errors_of_best_combination + packed_start_block_mode); + store_nbytes(clear_quant, best_quant_levels + packed_start_block_mode); + store_nbytes(clear_quant, best_quant_levels_mod + packed_start_block_mode); - for (unsigned int i = end_block_mode; i < packed_end_block_mode; i++) - { - errors_of_best_combination[i] = ERROR_CALC_DEFAULT; - best_quant_levels[i] = QUANT_2; - best_quant_levels_mod[i] = QUANT_2; - } + // Ensure that last iteration overstep contains data that will never be picked + unsigned int packed_end_block_mode = round_down_to_simd_multiple_vla(end_block_mode - 1); + storea(clear_error, errors_of_best_combination + packed_end_block_mode); + store_nbytes(clear_quant, best_quant_levels + packed_end_block_mode); + store_nbytes(clear_quant, best_quant_levels_mod + packed_end_block_mode); // Track a scalar best to avoid expensive search at least once ... float error_of_best_combination = ERROR_CALC_DEFAULT; @@ -1186,7 +1166,7 @@ unsigned int compute_ideal_endpoint_formats( // The block contains 1 partition if (partition_count == 1) { - for (unsigned int i = start_block_mode; i < end_block_mode; ++i) + for (unsigned int i = start_block_mode; i < end_block_mode; i++) { if (qwt_errors[i] >= ERROR_CALC_DEFAULT) { @@ -1214,13 +1194,13 @@ unsigned int compute_ideal_endpoint_formats( else if (partition_count == 2) { float combined_best_error[21][7]; - int formats_of_choice[21][7][2]; + uint8_t formats_of_choice[21][7][2]; two_partitions_find_best_combination_for_every_quantization_and_integer_count( best_error, format_of_choice, combined_best_error, formats_of_choice); assert(start_block_mode == 0); - for (unsigned int i = 0; i < end_block_mode; ++i) + for (unsigned int i = 0; i < end_block_mode; i++) { if (qwt_errors[i] >= ERROR_CALC_DEFAULT) { @@ -1247,13 +1227,13 @@ unsigned int compute_ideal_endpoint_formats( else if (partition_count == 3) { float combined_best_error[21][10]; - int formats_of_choice[21][10][3]; + uint8_t formats_of_choice[21][10][3]; three_partitions_find_best_combination_for_every_quantization_and_integer_count( best_error, format_of_choice, combined_best_error, formats_of_choice); assert(start_block_mode == 0); - for (unsigned int i = 0; i < end_block_mode; ++i) + for (unsigned int i = 0; i < end_block_mode; i++) { if (qwt_errors[i] >= ERROR_CALC_DEFAULT) { @@ -1281,13 +1261,13 @@ unsigned int compute_ideal_endpoint_formats( { assert(partition_count == 4); float combined_best_error[21][13]; - int formats_of_choice[21][13][4]; + uint8_t formats_of_choice[21][13][4]; four_partitions_find_best_combination_for_every_quantization_and_integer_count( best_error, format_of_choice, combined_best_error, formats_of_choice); assert(start_block_mode == 0); - for (unsigned int i = 0; i < end_block_mode; ++i) + for (unsigned int i = 0; i < end_block_mode; i++) { if (qwt_errors[i] >= ERROR_CALC_DEFAULT) { @@ -1330,10 +1310,8 @@ unsigned int compute_ideal_endpoint_formats( vint lane_ids = vint::lane_id() + vint(start_block_mode); for (unsigned int j = start_block_mode; j < end_block_mode; j += ASTCENC_SIMD_WIDTH) { - vfloat err = vfloat(&errors_of_best_combination[j]); - vmask mask1 = err < vbest_ep_error; - vmask mask2 = vint(reinterpret_cast(best_quant_levels + j)) > vint(4); - vmask mask = mask1 & mask2; + vfloat err = vfloat(errors_of_best_combination + j); + vmask mask = err < vbest_ep_error; vbest_ep_error = select(vbest_ep_error, err, mask); vbest_error_index = select(vbest_error_index, lane_ids, mask); lane_ids += vint(ASTCENC_SIMD_WIDTH); @@ -1368,8 +1346,8 @@ unsigned int compute_ideal_endpoint_formats( block_mode[i] = best_error_weights[i]; - quant_level[i] = best_quant_levels[best_error_weights[i]]; - quant_level_mod[i] = best_quant_levels_mod[best_error_weights[i]]; + quant_level[i] = static_cast(best_quant_levels[best_error_weights[i]]); + quant_level_mod[i] = static_cast(best_quant_levels_mod[best_error_weights[i]]); assert(quant_level[i] >= QUANT_6 && quant_level[i] <= QUANT_256); assert(quant_level_mod[i] >= QUANT_6 && quant_level_mod[i] <= QUANT_256); diff --git a/Source/astcenc_quantization.cpp b/Source/astcenc_quantization.cpp index 233a933..84d758d 100644 --- a/Source/astcenc_quantization.cpp +++ b/Source/astcenc_quantization.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -23,305 +23,615 @@ #if !defined(ASTCENC_DECOMPRESS_ONLY) +// Not scrambled, starts from QUANT_6 +const uint8_t color_unquant_to_uquant_tables[17][512] { + { // QUANT_6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 67, 67, 67, 67, 67, 67, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_24 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_32 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_40 + 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + 45, 45, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, 255, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_48 + 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 255, 255, 255, 255, 255, 255 + }, + { // QUANT_64 + 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, + 16, 16, 16, 16, 16, 20, 20, 20, 20, 20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 28, 28, 28, 28, 28, 28, 28, 28, 32, 32, 32, + 32, 32, 32, 32, 32, 36, 36, 36, 36, 36, 36, 36, 36, 40, 40, 40, 40, 40, 40, 40, 40, 44, 44, 44, 44, 44, 44, 44, 44, 48, 48, 48, + 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 56, 56, 56, 56, 56, 56, 56, 56, 60, 60, 60, 60, 60, 60, 60, 60, 60, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 69, 69, 69, 69, 69, 69, 69, 69, 73, 73, 73, 73, 73, 73, 73, 73, 77, 77, 77, 77, 77, 77, 77, 77, 81, + 81, 81, 81, 81, 81, 81, 81, 85, 85, 85, 85, 85, 85, 85, 85, 89, 89, 89, 89, 89, 89, 89, 89, 93, 93, 93, 93, 93, 93, 93, 93, 97, + 97, 97, 97, 97, 97, 97, 97, 101, 101, 101, 101, 101, 101, 101, 101, 105, 105, 105, 105, 105, 105, 105, 105, 109, 109, 109, 109, 109, 109, 109, 109, 113, + 113, 113, 113, 113, 113, 113, 113, 117, 117, 117, 117, 117, 117, 117, 117, 121, 121, 121, 121, 121, 121, 121, 121, 125, 125, 125, 125, 125, 125, 125, 125, 125, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 134, 134, 134, 134, 134, 134, 134, 134, 138, 138, 138, 138, 138, 138, 138, 138, 142, 142, 142, 142, 142, 142, 142, + 142, 146, 146, 146, 146, 146, 146, 146, 146, 150, 150, 150, 150, 150, 150, 150, 150, 154, 154, 154, 154, 154, 154, 154, 154, 158, 158, 158, 158, 158, 158, 158, + 158, 162, 162, 162, 162, 162, 162, 162, 162, 166, 166, 166, 166, 166, 166, 166, 166, 170, 170, 170, 170, 170, 170, 170, 170, 174, 174, 174, 174, 174, 174, 174, + 174, 178, 178, 178, 178, 178, 178, 178, 178, 182, 182, 182, 182, 182, 182, 182, 182, 186, 186, 186, 186, 186, 186, 186, 186, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 195, 195, 195, 195, 195, 195, 195, 195, 195, 199, 199, 199, 199, 199, 199, 199, 199, 203, 203, 203, 203, 203, 203, 203, 203, 207, 207, 207, 207, 207, + 207, 207, 207, 211, 211, 211, 211, 211, 211, 211, 211, 215, 215, 215, 215, 215, 215, 215, 215, 219, 219, 219, 219, 219, 219, 219, 219, 223, 223, 223, 223, 223, + 223, 223, 223, 227, 227, 227, 227, 227, 227, 227, 227, 231, 231, 231, 231, 231, 231, 231, 231, 235, 235, 235, 235, 235, 235, 235, 235, 239, 239, 239, 239, 239, + 239, 239, 239, 243, 243, 243, 243, 243, 243, 243, 243, 247, 247, 247, 247, 247, 247, 247, 247, 251, 251, 251, 251, 251, 251, 251, 251, 255, 255, 255, 255, 255 + }, + { // QUANT_80 + 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 9, 9, 13, 13, 13, 13, 13, 13, 13, 16, 16, + 16, 16, 16, 16, 19, 19, 19, 19, 19, 19, 22, 22, 22, 22, 22, 22, 25, 25, 25, 25, 25, 25, 25, 29, 29, 29, 29, 29, 29, 29, 32, 32, + 32, 32, 32, 32, 35, 35, 35, 35, 35, 35, 38, 38, 38, 38, 38, 38, 38, 42, 42, 42, 42, 42, 42, 42, 45, 45, 45, 45, 45, 45, 48, 48, + 48, 48, 48, 48, 51, 51, 51, 51, 51, 51, 54, 54, 54, 54, 54, 54, 54, 58, 58, 58, 58, 58, 58, 58, 61, 61, 61, 61, 61, 61, 64, 64, + 64, 64, 64, 64, 67, 67, 67, 67, 67, 67, 67, 71, 71, 71, 71, 71, 71, 71, 74, 74, 74, 74, 74, 74, 77, 77, 77, 77, 77, 77, 80, 80, + 80, 80, 80, 80, 83, 83, 83, 83, 83, 83, 83, 87, 87, 87, 87, 87, 87, 87, 90, 90, 90, 90, 90, 90, 93, 93, 93, 93, 93, 93, 96, 96, + 96, 96, 96, 96, 96, 100, 100, 100, 100, 100, 100, 100, 103, 103, 103, 103, 103, 103, 106, 106, 106, 106, 106, 106, 109, 109, 109, 109, 109, 109, 112, 112, + 112, 112, 112, 112, 112, 116, 116, 116, 116, 116, 116, 116, 119, 119, 119, 119, 119, 119, 122, 122, 122, 122, 122, 122, 125, 125, 125, 125, 125, 125, 125, 125, + 130, 130, 130, 130, 130, 130, 130, 130, 133, 133, 133, 133, 133, 133, 136, 136, 136, 136, 136, 136, 139, 139, 139, 139, 139, 139, 139, 143, 143, 143, 143, 143, + 143, 143, 146, 146, 146, 146, 146, 146, 149, 149, 149, 149, 149, 149, 152, 152, 152, 152, 152, 152, 155, 155, 155, 155, 155, 155, 155, 159, 159, 159, 159, 159, + 159, 159, 162, 162, 162, 162, 162, 162, 165, 165, 165, 165, 165, 165, 168, 168, 168, 168, 168, 168, 168, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, + 175, 175, 178, 178, 178, 178, 178, 178, 181, 181, 181, 181, 181, 181, 184, 184, 184, 184, 184, 184, 184, 188, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, + 191, 191, 194, 194, 194, 194, 194, 194, 197, 197, 197, 197, 197, 197, 197, 201, 201, 201, 201, 201, 201, 201, 204, 204, 204, 204, 204, 204, 207, 207, 207, 207, + 207, 207, 210, 210, 210, 210, 210, 210, 213, 213, 213, 213, 213, 213, 213, 217, 217, 217, 217, 217, 217, 217, 220, 220, 220, 220, 220, 220, 223, 223, 223, 223, + 223, 223, 226, 226, 226, 226, 226, 226, 226, 230, 230, 230, 230, 230, 230, 230, 233, 233, 233, 233, 233, 233, 236, 236, 236, 236, 236, 236, 239, 239, 239, 239, + 239, 239, 242, 242, 242, 242, 242, 242, 242, 246, 246, 246, 246, 246, 246, 246, 249, 249, 249, 249, 249, 249, 252, 252, 252, 252, 252, 252, 255, 255, 255, 255 + }, + { // QUANT_96 + 0, 0, 0, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 13, 13, 13, 13, 13, 13, 16, 16, + 16, 16, 16, 18, 18, 18, 18, 18, 21, 21, 21, 21, 21, 21, 24, 24, 24, 24, 24, 26, 26, 26, 26, 26, 29, 29, 29, 29, 29, 29, 32, 32, + 32, 32, 32, 32, 35, 35, 35, 35, 35, 37, 37, 37, 37, 37, 40, 40, 40, 40, 40, 40, 43, 43, 43, 43, 43, 45, 45, 45, 45, 45, 48, 48, + 48, 48, 48, 48, 51, 51, 51, 51, 51, 53, 53, 53, 53, 53, 56, 56, 56, 56, 56, 56, 59, 59, 59, 59, 59, 61, 61, 61, 61, 61, 64, 64, + 64, 64, 64, 64, 67, 67, 67, 67, 67, 67, 70, 70, 70, 70, 70, 72, 72, 72, 72, 72, 75, 75, 75, 75, 75, 75, 78, 78, 78, 78, 78, 80, + 80, 80, 80, 80, 83, 83, 83, 83, 83, 83, 86, 86, 86, 86, 86, 88, 88, 88, 88, 88, 91, 91, 91, 91, 91, 91, 94, 94, 94, 94, 94, 96, + 96, 96, 96, 96, 99, 99, 99, 99, 99, 99, 102, 102, 102, 102, 102, 104, 104, 104, 104, 104, 107, 107, 107, 107, 107, 107, 110, 110, 110, 110, 110, 112, + 112, 112, 112, 112, 115, 115, 115, 115, 115, 115, 118, 118, 118, 118, 118, 120, 120, 120, 120, 120, 123, 123, 123, 123, 123, 123, 126, 126, 126, 126, 126, 126, + 129, 129, 129, 129, 129, 129, 132, 132, 132, 132, 132, 132, 135, 135, 135, 135, 135, 137, 137, 137, 137, 137, 140, 140, 140, 140, 140, 140, 143, 143, 143, 143, + 143, 145, 145, 145, 145, 145, 148, 148, 148, 148, 148, 148, 151, 151, 151, 151, 151, 153, 153, 153, 153, 153, 156, 156, 156, 156, 156, 156, 159, 159, 159, 159, + 159, 161, 161, 161, 161, 161, 164, 164, 164, 164, 164, 164, 167, 167, 167, 167, 167, 169, 169, 169, 169, 169, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175, + 175, 177, 177, 177, 177, 177, 180, 180, 180, 180, 180, 180, 183, 183, 183, 183, 183, 185, 185, 185, 185, 185, 188, 188, 188, 188, 188, 188, 191, 191, 191, 191, + 191, 191, 194, 194, 194, 194, 194, 196, 196, 196, 196, 196, 199, 199, 199, 199, 199, 199, 202, 202, 202, 202, 202, 204, 204, 204, 204, 204, 207, 207, 207, 207, + 207, 207, 210, 210, 210, 210, 210, 212, 212, 212, 212, 212, 215, 215, 215, 215, 215, 215, 218, 218, 218, 218, 218, 220, 220, 220, 220, 220, 223, 223, 223, 223, + 223, 223, 226, 226, 226, 226, 226, 226, 229, 229, 229, 229, 229, 231, 231, 231, 231, 231, 234, 234, 234, 234, 234, 234, 237, 237, 237, 237, 237, 239, 239, 239, + 239, 239, 242, 242, 242, 242, 242, 242, 245, 245, 245, 245, 245, 247, 247, 247, 247, 247, 250, 250, 250, 250, 250, 250, 253, 253, 253, 253, 253, 255, 255, 255 + }, + { // QUANT_128 + 0, 0, 0, 2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, + 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 28, 28, 28, 28, 30, 30, 30, 30, 32, + 32, 32, 32, 34, 34, 34, 34, 36, 36, 36, 36, 38, 38, 38, 38, 40, 40, 40, 40, 42, 42, 42, 42, 44, 44, 44, 44, 46, 46, 46, 46, 48, + 48, 48, 48, 50, 50, 50, 50, 52, 52, 52, 52, 54, 54, 54, 54, 56, 56, 56, 56, 58, 58, 58, 58, 60, 60, 60, 60, 62, 62, 62, 62, 64, + 64, 64, 64, 66, 66, 66, 66, 68, 68, 68, 68, 70, 70, 70, 70, 72, 72, 72, 72, 74, 74, 74, 74, 76, 76, 76, 76, 78, 78, 78, 78, 80, + 80, 80, 80, 82, 82, 82, 82, 84, 84, 84, 84, 86, 86, 86, 86, 88, 88, 88, 88, 90, 90, 90, 90, 92, 92, 92, 92, 94, 94, 94, 94, 96, + 96, 96, 96, 98, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102, 104, 104, 104, 104, 106, 106, 106, 106, 108, 108, 108, 108, 110, 110, 110, 110, 112, + 112, 112, 112, 114, 114, 114, 114, 116, 116, 116, 116, 118, 118, 118, 118, 120, 120, 120, 120, 122, 122, 122, 122, 124, 124, 124, 124, 126, 126, 126, 126, 126, + 129, 129, 129, 129, 129, 131, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 135, 137, 137, 137, 137, 139, 139, 139, 139, 141, 141, 141, 141, 143, 143, 143, + 143, 145, 145, 145, 145, 147, 147, 147, 147, 149, 149, 149, 149, 151, 151, 151, 151, 153, 153, 153, 153, 155, 155, 155, 155, 157, 157, 157, 157, 159, 159, 159, + 159, 161, 161, 161, 161, 163, 163, 163, 163, 165, 165, 165, 165, 167, 167, 167, 167, 169, 169, 169, 169, 171, 171, 171, 171, 173, 173, 173, 173, 175, 175, 175, + 175, 177, 177, 177, 177, 179, 179, 179, 179, 181, 181, 181, 181, 183, 183, 183, 183, 185, 185, 185, 185, 187, 187, 187, 187, 189, 189, 189, 189, 191, 191, 191, + 191, 193, 193, 193, 193, 195, 195, 195, 195, 197, 197, 197, 197, 199, 199, 199, 199, 201, 201, 201, 201, 203, 203, 203, 203, 205, 205, 205, 205, 207, 207, 207, + 207, 209, 209, 209, 209, 211, 211, 211, 211, 213, 213, 213, 213, 215, 215, 215, 215, 217, 217, 217, 217, 219, 219, 219, 219, 221, 221, 221, 221, 223, 223, 223, + 223, 225, 225, 225, 225, 227, 227, 227, 227, 229, 229, 229, 229, 231, 231, 231, 231, 233, 233, 233, 233, 235, 235, 235, 235, 237, 237, 237, 237, 239, 239, 239, + 239, 241, 241, 241, 241, 243, 243, 243, 243, 245, 245, 245, 245, 247, 247, 247, 247, 249, 249, 249, 249, 251, 251, 251, 251, 253, 253, 253, 253, 255, 255, 255 + }, + { // QUANT_160 + 0, 0, 1, 1, 1, 3, 3, 3, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 12, 14, 14, 14, 14, 16, + 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 25, 25, 25, 27, 27, 27, 28, 28, 28, 30, 30, 30, 30, 32, + 32, 32, 33, 33, 33, 35, 35, 35, 36, 36, 36, 38, 38, 38, 38, 40, 40, 40, 41, 41, 41, 43, 43, 43, 44, 44, 44, 46, 46, 46, 46, 48, + 48, 48, 49, 49, 49, 51, 51, 51, 52, 52, 52, 54, 54, 54, 54, 56, 56, 56, 57, 57, 57, 59, 59, 59, 60, 60, 60, 62, 62, 62, 62, 64, + 64, 64, 65, 65, 65, 67, 67, 67, 68, 68, 68, 70, 70, 70, 70, 72, 72, 72, 73, 73, 73, 75, 75, 75, 76, 76, 76, 78, 78, 78, 78, 80, + 80, 80, 81, 81, 81, 83, 83, 83, 84, 84, 84, 86, 86, 86, 86, 88, 88, 88, 89, 89, 89, 91, 91, 91, 92, 92, 92, 94, 94, 94, 94, 96, + 96, 96, 97, 97, 97, 99, 99, 99, 100, 100, 100, 102, 102, 102, 102, 104, 104, 104, 105, 105, 105, 107, 107, 107, 108, 108, 108, 110, 110, 110, 110, 112, + 112, 112, 113, 113, 113, 115, 115, 115, 116, 116, 116, 118, 118, 118, 118, 120, 120, 120, 121, 121, 121, 123, 123, 123, 124, 124, 124, 126, 126, 126, 126, 126, + 129, 129, 129, 129, 129, 131, 131, 131, 132, 132, 132, 134, 134, 134, 135, 135, 135, 137, 137, 137, 137, 139, 139, 139, 140, 140, 140, 142, 142, 142, 143, 143, + 143, 145, 145, 145, 145, 147, 147, 147, 148, 148, 148, 150, 150, 150, 151, 151, 151, 153, 153, 153, 153, 155, 155, 155, 156, 156, 156, 158, 158, 158, 159, 159, + 159, 161, 161, 161, 161, 163, 163, 163, 164, 164, 164, 166, 166, 166, 167, 167, 167, 169, 169, 169, 169, 171, 171, 171, 172, 172, 172, 174, 174, 174, 175, 175, + 175, 177, 177, 177, 177, 179, 179, 179, 180, 180, 180, 182, 182, 182, 183, 183, 183, 185, 185, 185, 185, 187, 187, 187, 188, 188, 188, 190, 190, 190, 191, 191, + 191, 193, 193, 193, 193, 195, 195, 195, 196, 196, 196, 198, 198, 198, 199, 199, 199, 201, 201, 201, 201, 203, 203, 203, 204, 204, 204, 206, 206, 206, 207, 207, + 207, 209, 209, 209, 209, 211, 211, 211, 212, 212, 212, 214, 214, 214, 215, 215, 215, 217, 217, 217, 217, 219, 219, 219, 220, 220, 220, 222, 222, 222, 223, 223, + 223, 225, 225, 225, 225, 227, 227, 227, 228, 228, 228, 230, 230, 230, 231, 231, 231, 233, 233, 233, 233, 235, 235, 235, 236, 236, 236, 238, 238, 238, 239, 239, + 239, 241, 241, 241, 241, 243, 243, 243, 244, 244, 244, 246, 246, 246, 247, 247, 247, 249, 249, 249, 249, 251, 251, 251, 252, 252, 252, 254, 254, 254, 255, 255 + }, + { // QUANT_192 + 0, 0, 1, 1, 2, 2, 2, 4, 4, 4, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 10, 10, 10, 12, 12, 12, 13, 13, 14, 14, 14, 16, + 16, 16, 17, 17, 18, 18, 18, 20, 20, 20, 21, 21, 22, 22, 22, 24, 24, 24, 25, 25, 26, 26, 26, 28, 28, 28, 29, 29, 30, 30, 30, 32, + 32, 32, 33, 33, 34, 34, 34, 36, 36, 36, 37, 37, 38, 38, 38, 40, 40, 40, 41, 41, 42, 42, 42, 44, 44, 44, 45, 45, 46, 46, 46, 48, + 48, 48, 49, 49, 50, 50, 50, 52, 52, 52, 53, 53, 54, 54, 54, 56, 56, 56, 57, 57, 58, 58, 58, 60, 60, 60, 61, 61, 62, 62, 62, 64, + 64, 64, 65, 65, 66, 66, 66, 68, 68, 68, 69, 69, 70, 70, 70, 72, 72, 72, 73, 73, 74, 74, 74, 76, 76, 76, 77, 77, 78, 78, 78, 80, + 80, 80, 81, 81, 82, 82, 82, 84, 84, 84, 85, 85, 86, 86, 86, 88, 88, 88, 89, 89, 90, 90, 90, 92, 92, 92, 93, 93, 94, 94, 94, 96, + 96, 96, 97, 97, 98, 98, 98, 100, 100, 100, 101, 101, 102, 102, 102, 104, 104, 104, 105, 105, 106, 106, 106, 108, 108, 108, 109, 109, 110, 110, 110, 112, + 112, 112, 113, 113, 114, 114, 114, 116, 116, 116, 117, 117, 118, 118, 118, 120, 120, 120, 121, 121, 122, 122, 122, 124, 124, 124, 125, 125, 126, 126, 126, 126, + 129, 129, 129, 129, 130, 130, 131, 131, 131, 133, 133, 133, 134, 134, 135, 135, 135, 137, 137, 137, 138, 138, 139, 139, 139, 141, 141, 141, 142, 142, 143, 143, + 143, 145, 145, 145, 146, 146, 147, 147, 147, 149, 149, 149, 150, 150, 151, 151, 151, 153, 153, 153, 154, 154, 155, 155, 155, 157, 157, 157, 158, 158, 159, 159, + 159, 161, 161, 161, 162, 162, 163, 163, 163, 165, 165, 165, 166, 166, 167, 167, 167, 169, 169, 169, 170, 170, 171, 171, 171, 173, 173, 173, 174, 174, 175, 175, + 175, 177, 177, 177, 178, 178, 179, 179, 179, 181, 181, 181, 182, 182, 183, 183, 183, 185, 185, 185, 186, 186, 187, 187, 187, 189, 189, 189, 190, 190, 191, 191, + 191, 193, 193, 193, 194, 194, 195, 195, 195, 197, 197, 197, 198, 198, 199, 199, 199, 201, 201, 201, 202, 202, 203, 203, 203, 205, 205, 205, 206, 206, 207, 207, + 207, 209, 209, 209, 210, 210, 211, 211, 211, 213, 213, 213, 214, 214, 215, 215, 215, 217, 217, 217, 218, 218, 219, 219, 219, 221, 221, 221, 222, 222, 223, 223, + 223, 225, 225, 225, 226, 226, 227, 227, 227, 229, 229, 229, 230, 230, 231, 231, 231, 233, 233, 233, 234, 234, 235, 235, 235, 237, 237, 237, 238, 238, 239, 239, + 239, 241, 241, 241, 242, 242, 243, 243, 243, 245, 245, 245, 246, 246, 247, 247, 247, 249, 249, 249, 250, 250, 251, 251, 251, 253, 253, 253, 254, 254, 255, 255 + }, + { // QUANT_256 + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, + 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, + 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, + 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, + 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, + 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127, + 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143, + 144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 159, + 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, 175, 175, + 176, 176, 177, 177, 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, 189, 190, 190, 191, 191, + 192, 192, 193, 193, 194, 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207, + 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, + 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 239, + 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255 + }, +}; + // Starts from QUANT_6 // Scrambled -const uint8_t color_quant_tables[17][256] { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }, - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 - }, - { - 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1 - }, - { - 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1 - }, - { - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, - 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, - 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, - 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, - 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, - 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, - 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, - 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31 - }, - { - 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, - 16, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 2, 2, - 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 18, 18, 18, 18, 18, - 18, 26, 26, 26, 26, 26, 26, 26, 34, 34, 34, 34, 34, 34, 4, 4, - 4, 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20, - 20, 20, 28, 28, 28, 28, 28, 28, 36, 36, 36, 36, 36, 36, 36, 6, - 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22, - 22, 22, 30, 30, 30, 30, 30, 30, 30, 38, 38, 38, 38, 38, 38, 38, - 39, 39, 39, 39, 39, 39, 39, 31, 31, 31, 31, 31, 31, 31, 23, 23, - 23, 23, 23, 23, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, - 7, 37, 37, 37, 37, 37, 37, 37, 29, 29, 29, 29, 29, 29, 21, 21, - 21, 21, 21, 21, 21, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5, 5, - 5, 5, 35, 35, 35, 35, 35, 35, 27, 27, 27, 27, 27, 27, 27, 19, - 19, 19, 19, 19, 19, 11, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3, - 3, 3, 33, 33, 33, 33, 33, 33, 33, 25, 25, 25, 25, 25, 25, 17, - 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1 - }, - { - 0, 0, 0, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 2, 2, - 2, 2, 2, 18, 18, 18, 18, 18, 18, 34, 34, 34, 34, 34, 4, 4, - 4, 4, 4, 4, 20, 20, 20, 20, 20, 36, 36, 36, 36, 36, 6, 6, - 6, 6, 6, 6, 22, 22, 22, 22, 22, 38, 38, 38, 38, 38, 38, 8, - 8, 8, 8, 8, 24, 24, 24, 24, 24, 24, 40, 40, 40, 40, 40, 10, - 10, 10, 10, 10, 26, 26, 26, 26, 26, 26, 42, 42, 42, 42, 42, 12, - 12, 12, 12, 12, 12, 28, 28, 28, 28, 28, 44, 44, 44, 44, 44, 14, - 14, 14, 14, 14, 14, 30, 30, 30, 30, 30, 46, 46, 46, 46, 46, 46, - 47, 47, 47, 47, 47, 47, 31, 31, 31, 31, 31, 15, 15, 15, 15, 15, - 15, 45, 45, 45, 45, 45, 29, 29, 29, 29, 29, 13, 13, 13, 13, 13, - 13, 43, 43, 43, 43, 43, 27, 27, 27, 27, 27, 27, 11, 11, 11, 11, - 11, 41, 41, 41, 41, 41, 25, 25, 25, 25, 25, 25, 9, 9, 9, 9, - 9, 39, 39, 39, 39, 39, 39, 23, 23, 23, 23, 23, 7, 7, 7, 7, - 7, 7, 37, 37, 37, 37, 37, 21, 21, 21, 21, 21, 5, 5, 5, 5, - 5, 5, 35, 35, 35, 35, 35, 19, 19, 19, 19, 19, 19, 3, 3, 3, - 3, 3, 33, 33, 33, 33, 33, 17, 17, 17, 17, 17, 17, 1, 1, 1 - }, - { - 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, - 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, - 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, - 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, - 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, - 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, - 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, - 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, - 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, - 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, - 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, - 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, - 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, - 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, - 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, - 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63 - }, - { - 0, 0, 16, 16, 16, 32, 32, 32, 48, 48, 48, 48, 64, 64, 64, 2, - 2, 2, 18, 18, 18, 34, 34, 34, 50, 50, 50, 50, 66, 66, 66, 4, - 4, 4, 20, 20, 20, 36, 36, 36, 36, 52, 52, 52, 68, 68, 68, 6, - 6, 6, 22, 22, 22, 38, 38, 38, 38, 54, 54, 54, 70, 70, 70, 8, - 8, 8, 24, 24, 24, 24, 40, 40, 40, 56, 56, 56, 72, 72, 72, 10, - 10, 10, 26, 26, 26, 26, 42, 42, 42, 58, 58, 58, 74, 74, 74, 12, - 12, 12, 12, 28, 28, 28, 44, 44, 44, 60, 60, 60, 76, 76, 76, 14, - 14, 14, 14, 30, 30, 30, 46, 46, 46, 62, 62, 62, 78, 78, 78, 78, - 79, 79, 79, 79, 63, 63, 63, 47, 47, 47, 31, 31, 31, 15, 15, 15, - 15, 77, 77, 77, 61, 61, 61, 45, 45, 45, 29, 29, 29, 13, 13, 13, - 13, 75, 75, 75, 59, 59, 59, 43, 43, 43, 27, 27, 27, 27, 11, 11, - 11, 73, 73, 73, 57, 57, 57, 41, 41, 41, 25, 25, 25, 25, 9, 9, - 9, 71, 71, 71, 55, 55, 55, 39, 39, 39, 39, 23, 23, 23, 7, 7, - 7, 69, 69, 69, 53, 53, 53, 37, 37, 37, 37, 21, 21, 21, 5, 5, - 5, 67, 67, 67, 51, 51, 51, 51, 35, 35, 35, 19, 19, 19, 3, 3, - 3, 65, 65, 65, 49, 49, 49, 49, 33, 33, 33, 17, 17, 17, 1, 1 - }, - { - 0, 0, 32, 32, 64, 64, 64, 2, 2, 2, 34, 34, 66, 66, 66, 4, - 4, 4, 36, 36, 68, 68, 68, 6, 6, 6, 38, 38, 70, 70, 70, 8, - 8, 8, 40, 40, 40, 72, 72, 10, 10, 10, 42, 42, 42, 74, 74, 12, - 12, 12, 44, 44, 44, 76, 76, 14, 14, 14, 46, 46, 46, 78, 78, 16, - 16, 16, 48, 48, 48, 80, 80, 80, 18, 18, 50, 50, 50, 82, 82, 82, - 20, 20, 52, 52, 52, 84, 84, 84, 22, 22, 54, 54, 54, 86, 86, 86, - 24, 24, 56, 56, 56, 88, 88, 88, 26, 26, 58, 58, 58, 90, 90, 90, - 28, 28, 60, 60, 60, 92, 92, 92, 30, 30, 62, 62, 62, 94, 94, 94, - 95, 95, 95, 63, 63, 63, 31, 31, 93, 93, 93, 61, 61, 61, 29, 29, - 91, 91, 91, 59, 59, 59, 27, 27, 89, 89, 89, 57, 57, 57, 25, 25, - 87, 87, 87, 55, 55, 55, 23, 23, 85, 85, 85, 53, 53, 53, 21, 21, - 83, 83, 83, 51, 51, 51, 19, 19, 81, 81, 81, 49, 49, 49, 17, 17, - 17, 79, 79, 47, 47, 47, 15, 15, 15, 77, 77, 45, 45, 45, 13, 13, - 13, 75, 75, 43, 43, 43, 11, 11, 11, 73, 73, 41, 41, 41, 9, 9, - 9, 71, 71, 71, 39, 39, 7, 7, 7, 69, 69, 69, 37, 37, 5, 5, - 5, 67, 67, 67, 35, 35, 3, 3, 3, 65, 65, 65, 33, 33, 1, 1 - }, - { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, - 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, - 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, - 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, - 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, - 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, - 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, - 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, - 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, - 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, - 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, - 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 103, +const uint8_t color_uquant_to_scrambled_pquant_tables[17][256] { + { // QUANT_6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }, + { // QUANT_8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + }, + { // QUANT_10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }, + { // QUANT_12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }, + { // QUANT_16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 + }, + { // QUANT_20 + 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1 + }, + { // QUANT_24 + 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1 + }, + { // QUANT_32 + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, + 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31 + }, + { // QUANT_40 + 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, + 24, 24, 24, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 2, 2, + 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 18, 18, 18, 18, 18, 18, + 18, 26, 26, 26, 26, 26, 26, 34, 34, 34, 34, 34, 34, 34, 4, 4, + 4, 4, 4, 4, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 20, 20, + 20, 28, 28, 28, 28, 28, 28, 28, 36, 36, 36, 36, 36, 36, 36, 6, + 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 22, 22, 22, 22, 22, + 22, 22, 30, 30, 30, 30, 30, 30, 38, 38, 38, 38, 38, 38, 38, 38, + 39, 39, 39, 39, 39, 39, 39, 39, 31, 31, 31, 31, 31, 31, 23, 23, + 23, 23, 23, 23, 23, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, + 7, 37, 37, 37, 37, 37, 37, 37, 29, 29, 29, 29, 29, 29, 29, 21, + 21, 21, 21, 21, 21, 13, 13, 13, 13, 13, 13, 13, 5, 5, 5, 5, + 5, 5, 35, 35, 35, 35, 35, 35, 35, 27, 27, 27, 27, 27, 27, 19, + 19, 19, 19, 19, 19, 19, 11, 11, 11, 11, 11, 11, 3, 3, 3, 3, + 3, 3, 33, 33, 33, 33, 33, 33, 33, 25, 25, 25, 25, 25, 25, 25, + 17, 17, 17, 17, 17, 17, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1 + }, + { // QUANT_48 + 0, 0, 0, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 2, 2, + 2, 2, 2, 18, 18, 18, 18, 18, 34, 34, 34, 34, 34, 34, 4, 4, + 4, 4, 4, 20, 20, 20, 20, 20, 20, 36, 36, 36, 36, 36, 6, 6, + 6, 6, 6, 22, 22, 22, 22, 22, 22, 38, 38, 38, 38, 38, 38, 8, + 8, 8, 8, 8, 24, 24, 24, 24, 24, 40, 40, 40, 40, 40, 40, 10, + 10, 10, 10, 10, 26, 26, 26, 26, 26, 42, 42, 42, 42, 42, 42, 12, + 12, 12, 12, 12, 28, 28, 28, 28, 28, 28, 44, 44, 44, 44, 44, 14, + 14, 14, 14, 14, 30, 30, 30, 30, 30, 30, 46, 46, 46, 46, 46, 46, + 47, 47, 47, 47, 47, 47, 31, 31, 31, 31, 31, 31, 15, 15, 15, 15, + 15, 45, 45, 45, 45, 45, 29, 29, 29, 29, 29, 29, 13, 13, 13, 13, + 13, 43, 43, 43, 43, 43, 43, 27, 27, 27, 27, 27, 11, 11, 11, 11, + 11, 41, 41, 41, 41, 41, 41, 25, 25, 25, 25, 25, 9, 9, 9, 9, + 9, 39, 39, 39, 39, 39, 39, 23, 23, 23, 23, 23, 23, 7, 7, 7, + 7, 7, 37, 37, 37, 37, 37, 21, 21, 21, 21, 21, 21, 5, 5, 5, + 5, 5, 35, 35, 35, 35, 35, 35, 19, 19, 19, 19, 19, 3, 3, 3, + 3, 3, 33, 33, 33, 33, 33, 33, 17, 17, 17, 17, 17, 1, 1, 1 + }, + { // QUANT_64 + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, + 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, + 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, + 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, + 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, + 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, + 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, + 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, + 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, + 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, + 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63 + }, + { // QUANT_80 + 0, 0, 16, 16, 16, 32, 32, 32, 48, 48, 48, 64, 64, 64, 64, 2, + 2, 2, 18, 18, 18, 34, 34, 34, 50, 50, 50, 66, 66, 66, 66, 4, + 4, 4, 20, 20, 20, 36, 36, 36, 52, 52, 52, 52, 68, 68, 68, 6, + 6, 6, 22, 22, 22, 38, 38, 38, 54, 54, 54, 54, 70, 70, 70, 8, + 8, 8, 24, 24, 24, 40, 40, 40, 40, 56, 56, 56, 72, 72, 72, 10, + 10, 10, 26, 26, 26, 42, 42, 42, 42, 58, 58, 58, 74, 74, 74, 12, + 12, 12, 28, 28, 28, 28, 44, 44, 44, 60, 60, 60, 76, 76, 76, 14, + 14, 14, 30, 30, 30, 30, 46, 46, 46, 62, 62, 62, 78, 78, 78, 78, + 79, 79, 79, 79, 63, 63, 63, 47, 47, 47, 31, 31, 31, 31, 15, 15, + 15, 77, 77, 77, 61, 61, 61, 45, 45, 45, 29, 29, 29, 29, 13, 13, + 13, 75, 75, 75, 59, 59, 59, 43, 43, 43, 43, 27, 27, 27, 11, 11, + 11, 73, 73, 73, 57, 57, 57, 41, 41, 41, 41, 25, 25, 25, 9, 9, + 9, 71, 71, 71, 55, 55, 55, 55, 39, 39, 39, 23, 23, 23, 7, 7, + 7, 69, 69, 69, 53, 53, 53, 53, 37, 37, 37, 21, 21, 21, 5, 5, + 5, 67, 67, 67, 67, 51, 51, 51, 35, 35, 35, 19, 19, 19, 3, 3, + 3, 65, 65, 65, 65, 49, 49, 49, 33, 33, 33, 17, 17, 17, 1, 1 + }, + { // QUANT_96 + 0, 32, 32, 32, 64, 64, 64, 2, 2, 34, 34, 34, 66, 66, 66, 4, + 4, 36, 36, 36, 68, 68, 68, 6, 6, 38, 38, 38, 70, 70, 70, 8, + 8, 8, 40, 40, 72, 72, 72, 10, 10, 10, 42, 42, 74, 74, 74, 12, + 12, 12, 44, 44, 76, 76, 76, 14, 14, 14, 46, 46, 78, 78, 78, 16, + 16, 16, 48, 48, 48, 80, 80, 80, 18, 18, 50, 50, 50, 82, 82, 82, + 20, 20, 52, 52, 52, 84, 84, 84, 22, 22, 54, 54, 54, 86, 86, 86, + 24, 24, 56, 56, 56, 88, 88, 88, 26, 26, 58, 58, 58, 90, 90, 90, + 28, 28, 60, 60, 60, 92, 92, 92, 30, 30, 62, 62, 62, 94, 94, 94, + 95, 95, 95, 63, 63, 63, 31, 31, 93, 93, 93, 61, 61, 61, 29, 29, + 91, 91, 91, 59, 59, 59, 27, 27, 89, 89, 89, 57, 57, 57, 25, 25, + 87, 87, 87, 55, 55, 55, 23, 23, 85, 85, 85, 53, 53, 53, 21, 21, + 83, 83, 83, 51, 51, 51, 19, 19, 81, 81, 81, 49, 49, 49, 17, 17, + 17, 79, 79, 79, 47, 47, 15, 15, 15, 77, 77, 77, 45, 45, 13, 13, + 13, 75, 75, 75, 43, 43, 11, 11, 11, 73, 73, 73, 41, 41, 9, 9, + 9, 71, 71, 71, 39, 39, 39, 7, 7, 69, 69, 69, 37, 37, 37, 5, + 5, 67, 67, 67, 35, 35, 35, 3, 3, 65, 65, 65, 33, 33, 33, 1 + }, + { // QUANT_128 + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, + 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, + 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, + 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, + 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, + 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 63, + 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, + 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, + 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, + 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, + 96, 96, 97, 97, 98, 98, 99, 99, 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125, 126, 126, 127, 127 }, - { - 0, 32, 32, 64, 96, 96, 128, 128, 2, 34, 34, 66, 98, 98, 130, 130, - 4, 36, 36, 68, 100, 100, 132, 132, 6, 38, 38, 70, 102, 102, 134, 134, - 8, 40, 40, 72, 104, 104, 136, 136, 10, 42, 42, 74, 106, 106, 138, 138, - 12, 44, 44, 76, 108, 108, 140, 140, 14, 46, 46, 78, 110, 110, 142, 142, - 16, 48, 48, 80, 112, 112, 144, 144, 18, 50, 50, 82, 114, 114, 146, 146, - 20, 52, 52, 84, 116, 116, 148, 148, 22, 54, 54, 86, 118, 118, 150, 150, - 24, 56, 56, 88, 120, 120, 152, 152, 26, 58, 58, 90, 122, 122, 154, 154, - 28, 60, 60, 92, 124, 124, 156, 156, 30, 62, 62, 94, 126, 126, 158, 158, - 159, 159, 127, 127, 95, 63, 63, 31, 157, 157, 125, 125, 93, 61, 61, 29, - 155, 155, 123, 123, 91, 59, 59, 27, 153, 153, 121, 121, 89, 57, 57, 25, - 151, 151, 119, 119, 87, 55, 55, 23, 149, 149, 117, 117, 85, 53, 53, 21, - 147, 147, 115, 115, 83, 51, 51, 19, 145, 145, 113, 113, 81, 49, 49, 17, - 143, 143, 111, 111, 79, 47, 47, 15, 141, 141, 109, 109, 77, 45, 45, 13, - 139, 139, 107, 107, 75, 43, 43, 11, 137, 137, 105, 105, 73, 41, 41, 9, - 135, 135, 103, 103, 71, 39, 39, 7, 133, 133, 101, 101, 69, 37, 37, 5, - 131, 131, 99, 99, 67, 35, 35, 3, 129, 129, 97, 97, 65, 33, 33, 1 - }, - { - 0, 64, 128, 128, 2, 66, 130, 130, 4, 68, 132, 132, 6, 70, 134, 134, - 8, 72, 136, 136, 10, 74, 138, 138, 12, 76, 140, 140, 14, 78, 142, 142, - 16, 80, 144, 144, 18, 82, 146, 146, 20, 84, 148, 148, 22, 86, 150, 150, - 24, 88, 152, 152, 26, 90, 154, 154, 28, 92, 156, 156, 30, 94, 158, 158, - 32, 96, 160, 160, 34, 98, 162, 162, 36, 100, 164, 164, 38, 102, 166, 166, - 40, 104, 168, 168, 42, 106, 170, 170, 44, 108, 172, 172, 46, 110, 174, 174, - 48, 112, 176, 176, 50, 114, 178, 178, 52, 116, 180, 180, 54, 118, 182, 182, - 56, 120, 184, 184, 58, 122, 186, 186, 60, 124, 188, 188, 62, 126, 190, 190, - 191, 191, 127, 63, 189, 189, 125, 61, 187, 187, 123, 59, 185, 185, 121, 57, - 183, 183, 119, 55, 181, 181, 117, 53, 179, 179, 115, 51, 177, 177, 113, 49, - 175, 175, 111, 47, 173, 173, 109, 45, 171, 171, 107, 43, 169, 169, 105, 41, - 167, 167, 103, 39, 165, 165, 101, 37, 163, 163, 99, 35, 161, 161, 97, 33, - 159, 159, 95, 31, 157, 157, 93, 29, 155, 155, 91, 27, 153, 153, 89, 25, - 151, 151, 87, 23, 149, 149, 85, 21, 147, 147, 83, 19, 145, 145, 81, 17, - 143, 143, 79, 15, 141, 141, 77, 13, 139, 139, 75, 11, 137, 137, 73, 9, - 135, 135, 71, 7, 133, 133, 69, 5, 131, 131, 67, 3, 129, 129, 65, 1 - }, - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + { // QUANT_160 + 0, 32, 64, 64, 96, 128, 128, 128, 2, 34, 66, 66, 98, 130, 130, 130, + 4, 36, 68, 68, 100, 132, 132, 132, 6, 38, 70, 70, 102, 134, 134, 134, + 8, 40, 72, 72, 104, 136, 136, 136, 10, 42, 74, 74, 106, 138, 138, 138, + 12, 44, 76, 76, 108, 140, 140, 140, 14, 46, 78, 78, 110, 142, 142, 142, + 16, 48, 80, 80, 112, 144, 144, 144, 18, 50, 82, 82, 114, 146, 146, 146, + 20, 52, 84, 84, 116, 148, 148, 148, 22, 54, 86, 86, 118, 150, 150, 150, + 24, 56, 88, 88, 120, 152, 152, 152, 26, 58, 90, 90, 122, 154, 154, 154, + 28, 60, 92, 92, 124, 156, 156, 156, 30, 62, 94, 94, 126, 158, 158, 158, + 159, 159, 159, 127, 95, 95, 63, 31, 157, 157, 157, 125, 93, 93, 61, 29, + 155, 155, 155, 123, 91, 91, 59, 27, 153, 153, 153, 121, 89, 89, 57, 25, + 151, 151, 151, 119, 87, 87, 55, 23, 149, 149, 149, 117, 85, 85, 53, 21, + 147, 147, 147, 115, 83, 83, 51, 19, 145, 145, 145, 113, 81, 81, 49, 17, + 143, 143, 143, 111, 79, 79, 47, 15, 141, 141, 141, 109, 77, 77, 45, 13, + 139, 139, 139, 107, 75, 75, 43, 11, 137, 137, 137, 105, 73, 73, 41, 9, + 135, 135, 135, 103, 71, 71, 39, 7, 133, 133, 133, 101, 69, 69, 37, 5, + 131, 131, 131, 99, 67, 67, 35, 3, 129, 129, 129, 97, 65, 65, 33, 1 + }, + { // QUANT_192 + 0, 64, 128, 128, 2, 66, 130, 130, 4, 68, 132, 132, 6, 70, 134, 134, + 8, 72, 136, 136, 10, 74, 138, 138, 12, 76, 140, 140, 14, 78, 142, 142, + 16, 80, 144, 144, 18, 82, 146, 146, 20, 84, 148, 148, 22, 86, 150, 150, + 24, 88, 152, 152, 26, 90, 154, 154, 28, 92, 156, 156, 30, 94, 158, 158, + 32, 96, 160, 160, 34, 98, 162, 162, 36, 100, 164, 164, 38, 102, 166, 166, + 40, 104, 168, 168, 42, 106, 170, 170, 44, 108, 172, 172, 46, 110, 174, 174, + 48, 112, 176, 176, 50, 114, 178, 178, 52, 116, 180, 180, 54, 118, 182, 182, + 56, 120, 184, 184, 58, 122, 186, 186, 60, 124, 188, 188, 62, 126, 190, 190, + 191, 191, 127, 63, 189, 189, 125, 61, 187, 187, 123, 59, 185, 185, 121, 57, + 183, 183, 119, 55, 181, 181, 117, 53, 179, 179, 115, 51, 177, 177, 113, 49, + 175, 175, 111, 47, 173, 173, 109, 45, 171, 171, 107, 43, 169, 169, 105, 41, + 167, 167, 103, 39, 165, 165, 101, 37, 163, 163, 99, 35, 161, 161, 97, 33, + 159, 159, 95, 31, 157, 157, 93, 29, 155, 155, 91, 27, 153, 153, 89, 25, + 151, 151, 87, 23, 149, 149, 85, 21, 147, 147, 83, 19, 145, 145, 81, 17, + 143, 143, 79, 15, 141, 141, 77, 13, 139, 139, 75, 11, 137, 137, 73, 9, + 135, 135, 71, 7, 133, 133, 69, 5, 131, 131, 67, 3, 129, 129, 65, 1 + }, + { // QUANT_256 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, @@ -338,122 +648,156 @@ const uint8_t color_quant_tables[17][256] { // Starts from QUANT_6 // Scrambled -const uint8_t color_unquant_tables[17][256] { - { - 0, 255, 51, 204, 102, 153 - }, - { - 0, 36, 73, 109, 146, 182, 219, 255 - }, - { - 0, 255, 28, 227, 56, 199, 84, 171, 113, 142 - }, - { - 0, 255, 69, 186, 23, 232, 92, 163, 46, 209, 116, 139 - }, - { - 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 - }, - { - 0, 255, 67, 188, 13, 242, 80, 175, 27, 228, 94, 161, 40, 215, 107, 148, - 54, 201, 121, 134 - }, - { - 0, 255, 33, 222, 66, 189, 99, 156, 11, 244, 44, 211, 77, 178, 110, 145, - 22, 233, 55, 200, 88, 167, 121, 134 - }, - { - 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, - 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 - }, - { - 0, 255, 32, 223, 65, 190, 97, 158, 6, 249, 39, 216, 71, 184, 104, 151, - 13, 242, 45, 210, 78, 177, 110, 145, 19, 236, 52, 203, 84, 171, 117, 138, - 26, 229, 58, 197, 91, 164, 123, 132 - }, - { - 0, 255, 16, 239, 32, 223, 48, 207, 65, 190, 81, 174, 97, 158, 113, 142, - 5, 250, 21, 234, 38, 217, 54, 201, 70, 185, 86, 169, 103, 152, 119, 136, - 11, 244, 27, 228, 43, 212, 59, 196, 76, 179, 92, 163, 108, 147, 124, 131 - }, - { - 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, - 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, - 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, - 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255 - }, - { - 0, 255, 16, 239, 32, 223, 48, 207, 64, 191, 80, 175, 96, 159, 112, 143, - 3, 252, 19, 236, 35, 220, 51, 204, 67, 188, 83, 172, 100, 155, 116, 139, - 6, 249, 22, 233, 38, 217, 54, 201, 71, 184, 87, 168, 103, 152, 119, 136, - 9, 246, 25, 230, 42, 213, 58, 197, 74, 181, 90, 165, 106, 149, 122, 133, - 13, 242, 29, 226, 45, 210, 61, 194, 77, 178, 93, 162, 109, 146, 125, 130 - }, - { - 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199, - 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135, - 2, 253, 10, 245, 18, 237, 26, 229, 35, 220, 43, 212, 51, 204, 59, 196, - 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132, - 5, 250, 13, 242, 21, 234, 29, 226, 37, 218, 45, 210, 53, 202, 61, 194, - 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129 - }, - { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, - 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, - 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, - 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, - 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, - 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 - }, - { - 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199, - 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135, - 1, 254, 9, 246, 17, 238, 25, 230, 33, 222, 41, 214, 49, 206, 57, 198, - 65, 190, 73, 182, 81, 174, 89, 166, 97, 158, 105, 150, 113, 142, 121, 134, - 3, 252, 11, 244, 19, 236, 27, 228, 35, 220, 43, 212, 51, 204, 59, 196, - 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132, - 4, 251, 12, 243, 20, 235, 28, 227, 36, 219, 44, 211, 52, 203, 60, 195, - 68, 187, 76, 179, 84, 171, 92, 163, 100, 155, 108, 147, 116, 139, 124, 131, - 6, 249, 14, 241, 22, 233, 30, 225, 38, 217, 46, 209, 54, 201, 62, 193, - 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129 - }, - { - 0, 255, 4, 251, 8, 247, 12, 243, 16, 239, 20, 235, 24, 231, 28, 227, - 32, 223, 36, 219, 40, 215, 44, 211, 48, 207, 52, 203, 56, 199, 60, 195, - 64, 191, 68, 187, 72, 183, 76, 179, 80, 175, 84, 171, 88, 167, 92, 163, - 96, 159, 100, 155, 104, 151, 108, 147, 112, 143, 116, 139, 120, 135, 124, 131, - 1, 254, 5, 250, 9, 246, 13, 242, 17, 238, 21, 234, 25, 230, 29, 226, - 33, 222, 37, 218, 41, 214, 45, 210, 49, 206, 53, 202, 57, 198, 61, 194, - 65, 190, 69, 186, 73, 182, 77, 178, 81, 174, 85, 170, 89, 166, 93, 162, - 97, 158, 101, 154, 105, 150, 109, 146, 113, 142, 117, 138, 121, 134, 125, 130, - 2, 253, 6, 249, 10, 245, 14, 241, 18, 237, 22, 233, 26, 229, 30, 225, - 34, 221, 38, 217, 42, 213, 46, 209, 50, 205, 54, 201, 58, 197, 62, 193, - 66, 189, 70, 185, 74, 181, 78, 177, 82, 173, 86, 169, 90, 165, 94, 161, - 98, 157, 102, 153, 106, 149, 110, 145, 114, 141, 118, 137, 122, 133, 126, 129 - }, - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 - } +static const uint8_t color_scrambled_pquant_to_uquant_q6[6] { + 0, 255, 51, 204, 102, 153 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q8[8] { + 0, 36, 73, 109, 146, 182, 219, 255 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q10[10] { + 0, 255, 28, 227, 56, 199, 84, 171, 113, 142 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q12[12] { + 0, 255, 69, 186, 23, 232, 92, 163, 46, 209, 116, 139 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q16[16] { + 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q20[20] { + 0, 255, 67, 188, 13, 242, 80, 175, 27, 228, 94, 161, 40, 215, 107, 148, + 54, 201, 121, 134 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q24[24] { + 0, 255, 33, 222, 66, 189, 99, 156, 11, 244, 44, 211, 77, 178, 110, 145, + 22, 233, 55, 200, 88, 167, 121, 134 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q32[32] { + 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, + 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q40[40] { + 0, 255, 32, 223, 65, 190, 97, 158, 6, 249, 39, 216, 71, 184, 104, 151, + 13, 242, 45, 210, 78, 177, 110, 145, 19, 236, 52, 203, 84, 171, 117, 138, + 26, 229, 58, 197, 91, 164, 123, 132 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q48[48] { + 0, 255, 16, 239, 32, 223, 48, 207, 65, 190, 81, 174, 97, 158, 113, 142, + 5, 250, 21, 234, 38, 217, 54, 201, 70, 185, 86, 169, 103, 152, 119, 136, + 11, 244, 27, 228, 43, 212, 59, 196, 76, 179, 92, 163, 108, 147, 124, 131 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q64[64] { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, + 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, + 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, + 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q80[80] { + 0, 255, 16, 239, 32, 223, 48, 207, 64, 191, 80, 175, 96, 159, 112, 143, + 3, 252, 19, 236, 35, 220, 51, 204, 67, 188, 83, 172, 100, 155, 116, 139, + 6, 249, 22, 233, 38, 217, 54, 201, 71, 184, 87, 168, 103, 152, 119, 136, + 9, 246, 25, 230, 42, 213, 58, 197, 74, 181, 90, 165, 106, 149, 122, 133, + 13, 242, 29, 226, 45, 210, 61, 194, 77, 178, 93, 162, 109, 146, 125, 130 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q96[96] { + 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199, + 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135, + 2, 253, 10, 245, 18, 237, 26, 229, 35, 220, 43, 212, 51, 204, 59, 196, + 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132, + 5, 250, 13, 242, 21, 234, 29, 226, 37, 218, 45, 210, 53, 202, 61, 194, + 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q128[128] { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, + 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, + 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, + 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, + 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, + 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q160[160] { + 0, 255, 8, 247, 16, 239, 24, 231, 32, 223, 40, 215, 48, 207, 56, 199, + 64, 191, 72, 183, 80, 175, 88, 167, 96, 159, 104, 151, 112, 143, 120, 135, + 1, 254, 9, 246, 17, 238, 25, 230, 33, 222, 41, 214, 49, 206, 57, 198, + 65, 190, 73, 182, 81, 174, 89, 166, 97, 158, 105, 150, 113, 142, 121, 134, + 3, 252, 11, 244, 19, 236, 27, 228, 35, 220, 43, 212, 51, 204, 59, 196, + 67, 188, 75, 180, 83, 172, 91, 164, 99, 156, 107, 148, 115, 140, 123, 132, + 4, 251, 12, 243, 20, 235, 28, 227, 36, 219, 44, 211, 52, 203, 60, 195, + 68, 187, 76, 179, 84, 171, 92, 163, 100, 155, 108, 147, 116, 139, 124, 131, + 6, 249, 14, 241, 22, 233, 30, 225, 38, 217, 46, 209, 54, 201, 62, 193, + 70, 185, 78, 177, 86, 169, 94, 161, 102, 153, 110, 145, 118, 137, 126, 129 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q192[192] { + 0, 255, 4, 251, 8, 247, 12, 243, 16, 239, 20, 235, 24, 231, 28, 227, + 32, 223, 36, 219, 40, 215, 44, 211, 48, 207, 52, 203, 56, 199, 60, 195, + 64, 191, 68, 187, 72, 183, 76, 179, 80, 175, 84, 171, 88, 167, 92, 163, + 96, 159, 100, 155, 104, 151, 108, 147, 112, 143, 116, 139, 120, 135, 124, 131, + 1, 254, 5, 250, 9, 246, 13, 242, 17, 238, 21, 234, 25, 230, 29, 226, + 33, 222, 37, 218, 41, 214, 45, 210, 49, 206, 53, 202, 57, 198, 61, 194, + 65, 190, 69, 186, 73, 182, 77, 178, 81, 174, 85, 170, 89, 166, 93, 162, + 97, 158, 101, 154, 105, 150, 109, 146, 113, 142, 117, 138, 121, 134, 125, 130, + 2, 253, 6, 249, 10, 245, 14, 241, 18, 237, 22, 233, 26, 229, 30, 225, + 34, 221, 38, 217, 42, 213, 46, 209, 50, 205, 54, 201, 58, 197, 62, 193, + 66, 189, 70, 185, 74, 181, 78, 177, 82, 173, 86, 169, 90, 165, 94, 161, + 98, 157, 102, 153, 106, 149, 110, 145, 114, 141, 118, 137, 122, 133, 126, 129 +}; + +static const uint8_t color_scrambled_pquant_to_uquant_q256[256] { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 +}; + +const uint8_t* color_scrambled_pquant_to_uquant_tables[17] { + color_scrambled_pquant_to_uquant_q6, + color_scrambled_pquant_to_uquant_q8, + color_scrambled_pquant_to_uquant_q10, + color_scrambled_pquant_to_uquant_q12, + color_scrambled_pquant_to_uquant_q16, + color_scrambled_pquant_to_uquant_q20, + color_scrambled_pquant_to_uquant_q24, + color_scrambled_pquant_to_uquant_q32, + color_scrambled_pquant_to_uquant_q40, + color_scrambled_pquant_to_uquant_q48, + color_scrambled_pquant_to_uquant_q64, + color_scrambled_pquant_to_uquant_q80, + color_scrambled_pquant_to_uquant_q96, + color_scrambled_pquant_to_uquant_q128, + color_scrambled_pquant_to_uquant_q160, + color_scrambled_pquant_to_uquant_q192, + color_scrambled_pquant_to_uquant_q256 }; -// The quant_mode_table[integercount/2][bits] gives us the quantization level for a given integer +// The quant_mode_table[integer_count/2][bits] gives us the quantization level for a given integer // count and number of bits that the integer may fit into. const int8_t quant_mode_table[10][128] { { diff --git a/Source/astcenc_symbolic_physical.cpp b/Source/astcenc_symbolic_physical.cpp index ea9aea5..21803e0 100644 --- a/Source/astcenc_symbolic_physical.cpp +++ b/Source/astcenc_symbolic_physical.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -24,36 +24,21 @@ #include /** - * @brief Write up to 8 bits at an arbitrary bit offset. - * - * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so - * may span two separate bytes in memory. + * @brief Reverse bits in a byte. * - * @param value The value to write. - * @param bitcount The number of bits to write, starting from LSB. - * @param bitoffset The bit offset to store at, between 0 and 7. - * @param[in,out] ptr The data pointer to write to. + * @param p The value to reverse. + * + * @return The reversed result. */ -static inline void write_bits( - int value, - int bitcount, - int bitoffset, - uint8_t* ptr -) { - int mask = (1 << bitcount) - 1; - value &= mask; - ptr += bitoffset >> 3; - bitoffset &= 7; - value <<= bitoffset; - mask <<= bitoffset; - mask = ~mask; - - ptr[0] &= mask; - ptr[0] |= value; - ptr[1] &= mask >> 8; - ptr[1] |= value >> 8; +static inline int bitrev8(int p) +{ + p = ((p & 0x0F) << 4) | ((p >> 4) & 0x0F); + p = ((p & 0x33) << 2) | ((p >> 2) & 0x33); + p = ((p & 0x55) << 1) | ((p >> 1) & 0x55); + return p; } + /** * @brief Read up to 8 bits at an arbitrary bit offset. * @@ -80,19 +65,37 @@ static inline int read_bits( return value; } +#if !defined(ASTCENC_DECOMPRESS_ONLY) + /** - * @brief Reverse bits in a byte. + * @brief Write up to 8 bits at an arbitrary bit offset. * - * @param p The value to reverse. - * - * @return The reversed result. + * The stored value is at most 8 bits, but can be stored at an offset of between 0 and 7 bits so + * may span two separate bytes in memory. + * + * @param value The value to write. + * @param bitcount The number of bits to write, starting from LSB. + * @param bitoffset The bit offset to store at, between 0 and 7. + * @param[in,out] ptr The data pointer to write to. */ -static inline int bitrev8(int p) -{ - p = ((p & 0x0F) << 4) | ((p >> 4) & 0x0F); - p = ((p & 0x33) << 2) | ((p >> 2) & 0x33); - p = ((p & 0x55) << 1) | ((p >> 1) & 0x55); - return p; +static inline void write_bits( + int value, + int bitcount, + int bitoffset, + uint8_t* ptr +) { + int mask = (1 << bitcount) - 1; + value &= mask; + ptr += bitoffset >> 3; + bitoffset &= 7; + value <<= bitoffset; + mask <<= bitoffset; + mask = ~mask; + + ptr[0] &= mask; + ptr[0] |= value; + ptr[1] &= mask >> 8; + ptr[1] |= value >> 8; } static const int HIGH_SPEED_PROFILE_COLOR_BYTES = 8; @@ -101,27 +104,41 @@ static const int HIGH_SPEED_PROFILE_WEIGHT_BYTES = 16; void symbolic_to_physical( const block_size_descriptor& bsd, const symbolic_compressed_block& scb, - physical_compressed_block& pcb + uint8_t pcb[16] ) { assert(scb.block_type != SYM_BTYPE_ERROR); + const auto& bm = bsd.get_block_mode(scb.block_mode); + const auto& di = bsd.get_decimation_info(bm.decimation_mode); + int weight_count = di.weight_count; + quant_method weight_quant_method = bm.get_weight_quant_mode(); + float weight_quant_levels = static_cast(get_quant_level(weight_quant_method)); + const auto& qat = quant_and_xfer_tables[weight_quant_method]; if (scb.privateProfile == HIGH_SPEED_PROFILE) { + uint8_t weights[64]; + for (int i = 0; i < weight_count; i++) + { + float uqw = static_cast(scb.weights[i]); + float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); + int qwi = static_cast(qw + 0.5f); + weights[i] = qat.scramble_map[qwi]; + } uint8_t weightbuf[HIGH_SPEED_PROFILE_WEIGHT_BYTES] = {0}; - encode_ise(QUANT_6, HIGH_SPEED_PROFILE_WEIGHT_BYTES, scb.weights, weightbuf, 0); + encode_ise(QUANT_6, HIGH_SPEED_PROFILE_WEIGHT_BYTES, weights, weightbuf, 0); for (int i = 0; i < HIGH_SPEED_PROFILE_WEIGHT_BYTES; i++) { - pcb.data[i] = static_cast(bitrev8(weightbuf[HIGH_SPEED_PROFILE_WEIGHT_BYTES - 1 - i])); + pcb[i] = static_cast(bitrev8(weightbuf[HIGH_SPEED_PROFILE_WEIGHT_BYTES - 1 - i])); } - pcb.data[0] = 0x43; // the first byte of every block stream is 0x43 for HIGH_SPEED_PROFILE - pcb.data[1] = 0x80; // the second byte of every block stream is 0x80 for HIGH_SPEED_PROFILE - pcb.data[2] = 0x01; // the third (2 idx) byte of every block stream is 0x01 for HIGH_SPEED_PROFILE + pcb[0] = 0x43; // the first byte of every block stream is 0x43 for HIGH_SPEED_PROFILE + pcb[1] = 0x80; // the second byte of every block stream is 0x80 for HIGH_SPEED_PROFILE + pcb[2] = 0x01; // the third (2 idx) byte of every block stream is 0x01 for HIGH_SPEED_PROFILE uint8_t values_to_encode[HIGH_SPEED_PROFILE_COLOR_BYTES]; for (int j = 0; j < HIGH_SPEED_PROFILE_COLOR_BYTES; j++) { values_to_encode[j] = scb.color_values[0][j]; } encode_ise(scb.get_color_quant_mode(), HIGH_SPEED_PROFILE_COLOR_BYTES, - values_to_encode, pcb.data, 17); // the color is starting from 17th bit for HIGH_SPEED_PROFILE + values_to_encode, pcb, 17); // the color is starting from 17th bit for HIGH_SPEED_PROFILE return; } @@ -132,13 +149,13 @@ void symbolic_to_physical( static const uint8_t cbytes[8] { 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; for (unsigned int i = 0; i < 8; i++) { - pcb.data[i] = cbytes[i]; + pcb[i] = cbytes[i]; } for (unsigned int i = 0; i < BLOCK_MAX_COMPONENTS; i++) { - pcb.data[2 * i + 8] = scb.constant_color[i] & 0xFF; - pcb.data[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; + pcb[2 * i + 8] = scb.constant_color[i] & 0xFF; + pcb[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; } return; @@ -151,13 +168,13 @@ void symbolic_to_physical( static const uint8_t cbytes[8] { 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; for (unsigned int i = 0; i < 8; i++) { - pcb.data[i] = cbytes[i]; + pcb[i] = cbytes[i]; } for (unsigned int i = 0; i < BLOCK_MAX_COMPONENTS; i++) { - pcb.data[2 * i + 8] = scb.constant_color[i] & 0xFF; - pcb.data[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; + pcb[2 * i + 8] = scb.constant_color[i] & 0xFF; + pcb[2 * i + 9] = (scb.constant_color[i] >> 8) & 0xFF; } return; @@ -169,50 +186,60 @@ void symbolic_to_physical( // They are encoded as an ordinary integer-sequence, then bit-reversed uint8_t weightbuf[16] { 0 }; - const auto& bm = bsd.get_block_mode(scb.block_mode); - const auto& di = bsd.get_decimation_info(bm.decimation_mode); - int weight_count = di.weight_count; - quant_method weight_quant_method = bm.get_weight_quant_mode(); int is_dual_plane = bm.is_dual_plane; int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count; int bits_for_weights = get_ise_sequence_bitcount(real_weight_count, weight_quant_method); + uint8_t weights[64]; if (is_dual_plane) { - uint8_t weights[64]; for (int i = 0; i < weight_count; i++) { - weights[2 * i] = scb.weights[i]; - weights[2 * i + 1] = scb.weights[i + WEIGHTS_PLANE2_OFFSET]; + float uqw = static_cast(scb.weights[i]); + float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); + int qwi = static_cast(qw + 0.5f); + weights[2 * i] = qat.scramble_map[qwi]; + + uqw = static_cast(scb.weights[i + WEIGHTS_PLANE2_OFFSET]); + qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); + qwi = static_cast(qw + 0.5f); + weights[2 * i + 1] = qat.scramble_map[qwi]; } - encode_ise(weight_quant_method, real_weight_count, weights, weightbuf, 0); } else { - encode_ise(weight_quant_method, weight_count, scb.weights, weightbuf, 0); + for (int i = 0; i < weight_count; i++) + { + float uqw = static_cast(scb.weights[i]); + float qw = (uqw / 64.0f) * (weight_quant_levels - 1.0f); + int qwi = static_cast(qw + 0.5f); + weights[i] = qat.scramble_map[qwi]; + } } + encode_ise(weight_quant_method, real_weight_count, weights, weightbuf, 0); + for (int i = 0; i < 16; i++) { - pcb.data[i] = static_cast(bitrev8(weightbuf[15 - i])); + pcb[i] = static_cast(bitrev8(weightbuf[15 - i])); } - write_bits(scb.block_mode, 11, 0, pcb.data); - write_bits(partition_count - 1, 2, 11, pcb.data); + write_bits(scb.block_mode, 11, 0, pcb); + write_bits(partition_count - 1, 2, 11, pcb); int below_weights_pos = 128 - bits_for_weights; // Encode partition index and color endpoint types for blocks with 2+ partitions if (partition_count > 1) { - write_bits(scb.partition_index, 6, 13, pcb.data); - write_bits(scb.partition_index >> 6, PARTITION_INDEX_BITS - 6, 19, pcb.data); + write_bits(scb.partition_index, 6, 13, pcb); + write_bits(scb.partition_index >> 6, PARTITION_INDEX_BITS - 6, 19, pcb); if (scb.color_formats_matched) { - write_bits(scb.color_formats[0] << 2, 6, 13 + PARTITION_INDEX_BITS, pcb.data); + write_bits(scb.color_formats[0] << 2, 6, 13 + PARTITION_INDEX_BITS, pcb); } else { @@ -251,44 +278,48 @@ void symbolic_to_physical( int encoded_type_highpart = encoded_type >> 6; int encoded_type_highpart_size = (3 * partition_count) - 4; int encoded_type_highpart_pos = 128 - bits_for_weights - encoded_type_highpart_size; - write_bits(encoded_type_lowpart, 6, 13 + PARTITION_INDEX_BITS, pcb.data); - write_bits(encoded_type_highpart, encoded_type_highpart_size, encoded_type_highpart_pos, pcb.data); + write_bits(encoded_type_lowpart, 6, 13 + PARTITION_INDEX_BITS, pcb); + write_bits(encoded_type_highpart, encoded_type_highpart_size, encoded_type_highpart_pos, pcb); below_weights_pos -= encoded_type_highpart_size; } } else { - write_bits(scb.color_formats[0], 4, 13, pcb.data); + write_bits(scb.color_formats[0], 4, 13, pcb); } // In dual-plane mode, encode the color component of the second plane of weights if (is_dual_plane) { - write_bits(scb.plane2_component, 2, below_weights_pos - 2, pcb.data); + write_bits(scb.plane2_component, 2, below_weights_pos - 2, pcb); } // Encode the color components uint8_t values_to_encode[32]; int valuecount_to_encode = 0; + + const uint8_t* pack_table = color_uquant_to_scrambled_pquant_tables[scb.quant_mode - QUANT_6]; for (unsigned int i = 0; i < scb.partition_count; i++) { int vals = 2 * (scb.color_formats[i] >> 2) + 2; assert(vals <= 8); for (int j = 0; j < vals; j++) { - values_to_encode[j + valuecount_to_encode] = scb.color_values[i][j]; + values_to_encode[j + valuecount_to_encode] = pack_table[scb.color_values[i][j]]; } valuecount_to_encode += vals; } - encode_ise(scb.get_color_quant_mode(), valuecount_to_encode, values_to_encode, pcb.data, + encode_ise(scb.get_color_quant_mode(), valuecount_to_encode, values_to_encode, pcb, scb.partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS); } +#endif + /* See header for documentation. */ void physical_to_symbolic( const block_size_descriptor& bsd, - const physical_compressed_block& pcb, + const uint8_t pcb[16], symbolic_compressed_block& scb ) { uint8_t bswapped[16]; @@ -296,7 +327,7 @@ void physical_to_symbolic( scb.block_type = SYM_BTYPE_NONCONST; // Extract header fields - int block_mode = read_bits(11, 0, pcb.data); + int block_mode = read_bits(11, 0, pcb); if ((block_mode & 0x1FF) == 0x1FC) { // Constant color block @@ -314,24 +345,24 @@ void physical_to_symbolic( scb.partition_count = 0; for (int i = 0; i < 4; i++) { - scb.constant_color[i] = pcb.data[2 * i + 8] | (pcb.data[2 * i + 9] << 8); + scb.constant_color[i] = pcb[2 * i + 8] | (pcb[2 * i + 9] << 8); } // Additionally, check that the void-extent if (bsd.zdim == 1) { // 2D void-extent - int rsvbits = read_bits(2, 10, pcb.data); + int rsvbits = read_bits(2, 10, pcb); if (rsvbits != 3) { scb.block_type = SYM_BTYPE_ERROR; return; } - int vx_low_s = read_bits(8, 12, pcb.data) | (read_bits(5, 12 + 8, pcb.data) << 8); - int vx_high_s = read_bits(8, 25, pcb.data) | (read_bits(5, 25 + 8, pcb.data) << 8); - int vx_low_t = read_bits(8, 38, pcb.data) | (read_bits(5, 38 + 8, pcb.data) << 8); - int vx_high_t = read_bits(8, 51, pcb.data) | (read_bits(5, 51 + 8, pcb.data) << 8); + int vx_low_s = read_bits(8, 12, pcb) | (read_bits(5, 12 + 8, pcb) << 8); + int vx_high_s = read_bits(8, 25, pcb) | (read_bits(5, 25 + 8, pcb) << 8); + int vx_low_t = read_bits(8, 38, pcb) | (read_bits(5, 38 + 8, pcb) << 8); + int vx_high_t = read_bits(8, 51, pcb) | (read_bits(5, 51 + 8, pcb) << 8); int all_ones = vx_low_s == 0x1FFF && vx_high_s == 0x1FFF && vx_low_t == 0x1FFF && vx_high_t == 0x1FFF; @@ -344,12 +375,12 @@ void physical_to_symbolic( else { // 3D void-extent - int vx_low_s = read_bits(9, 10, pcb.data); - int vx_high_s = read_bits(9, 19, pcb.data); - int vx_low_t = read_bits(9, 28, pcb.data); - int vx_high_t = read_bits(9, 37, pcb.data); - int vx_low_p = read_bits(9, 46, pcb.data); - int vx_high_p = read_bits(9, 55, pcb.data); + int vx_low_s = read_bits(9, 10, pcb); + int vx_high_s = read_bits(9, 19, pcb); + int vx_low_t = read_bits(9, 28, pcb); + int vx_high_t = read_bits(9, 37, pcb); + int vx_low_p = read_bits(9, 46, pcb); + int vx_high_p = read_bits(9, 55, pcb); int all_ones = vx_low_s == 0x1FF && vx_high_s == 0x1FF && vx_low_t == 0x1FF && vx_high_t == 0x1FF && vx_low_p == 0x1FF && vx_high_p == 0x1FF; @@ -374,38 +405,47 @@ void physical_to_symbolic( const auto& di = bsd.get_decimation_info(bm.decimation_mode); int weight_count = di.weight_count; + promise(weight_count > 0); + quant_method weight_quant_method = static_cast(bm.quant_mode); int is_dual_plane = bm.is_dual_plane; int real_weight_count = is_dual_plane ? 2 * weight_count : weight_count; - int partition_count = read_bits(2, 11, pcb.data) + 1; + int partition_count = read_bits(2, 11, pcb) + 1; + promise(partition_count > 0); scb.block_mode = static_cast(block_mode); scb.partition_count = static_cast(partition_count); for (int i = 0; i < 16; i++) { - bswapped[i] = static_cast(bitrev8(pcb.data[15 - i])); + bswapped[i] = static_cast(bitrev8(pcb[15 - i])); } int bits_for_weights = get_ise_sequence_bitcount(real_weight_count, weight_quant_method); int below_weights_pos = 128 - bits_for_weights; + uint8_t indices[64]; + const auto& qat = quant_and_xfer_tables[weight_quant_method]; + + decode_ise(weight_quant_method, real_weight_count, bswapped, indices, 0); + if (is_dual_plane) { - uint8_t indices[64]; - decode_ise(weight_quant_method, real_weight_count, bswapped, indices, 0); for (int i = 0; i < weight_count; i++) { - scb.weights[i] = indices[2 * i]; - scb.weights[i + WEIGHTS_PLANE2_OFFSET] = indices[2 * i + 1]; + scb.weights[i] = qat.unscramble_and_unquant_map[indices[2 * i]]; + scb.weights[i + WEIGHTS_PLANE2_OFFSET] = qat.unscramble_and_unquant_map[indices[2 * i + 1]]; } } else { - decode_ise(weight_quant_method, weight_count, bswapped, scb.weights, 0); + for (int i = 0; i < weight_count; i++) + { + scb.weights[i] = qat.unscramble_and_unquant_map[indices[i]]; + } } if (is_dual_plane && partition_count == 4) @@ -421,14 +461,15 @@ void physical_to_symbolic( int encoded_type_highpart_size = 0; if (partition_count == 1) { - color_formats[0] = read_bits(4, 13, pcb.data); + color_formats[0] = read_bits(4, 13, pcb); scb.partition_index = 0; } else { encoded_type_highpart_size = (3 * partition_count) - 4; below_weights_pos -= encoded_type_highpart_size; - int encoded_type = read_bits(6, 13 + PARTITION_INDEX_BITS, pcb.data) | (read_bits(encoded_type_highpart_size, below_weights_pos, pcb.data) << 6); + int encoded_type = read_bits(6, 13 + PARTITION_INDEX_BITS, pcb) | + (read_bits(encoded_type_highpart_size, below_weights_pos, pcb) << 6); int baseclass = encoded_type & 0x3; if (baseclass == 0) { @@ -458,7 +499,8 @@ void physical_to_symbolic( bitpos += 2; } } - scb.partition_index = static_cast(read_bits(6, 13, pcb.data) | (read_bits(PARTITION_INDEX_BITS - 6, 19, pcb.data) << 6)); + scb.partition_index = static_cast(read_bits(6, 13, pcb) | + (read_bits(PARTITION_INDEX_BITS - 6, 19, pcb) << 6)); } for (int i = 0; i < partition_count; i++) @@ -502,24 +544,27 @@ void physical_to_symbolic( // Unpack the integer color values and assign to endpoints scb.quant_mode = static_cast(color_quant_level); + uint8_t values_to_decode[32]; - decode_ise(static_cast(color_quant_level), color_integer_count, pcb.data, + decode_ise(static_cast(color_quant_level), color_integer_count, pcb, values_to_decode, (partition_count == 1 ? 17 : 19 + PARTITION_INDEX_BITS)); int valuecount_to_decode = 0; + const uint8_t* unpack_table = color_scrambled_pquant_to_uquant_tables[scb.quant_mode - QUANT_6]; for (int i = 0; i < partition_count; i++) { int vals = 2 * (color_formats[i] >> 2) + 2; for (int j = 0; j < vals; j++) { - scb.color_values[i][j] = values_to_decode[j + valuecount_to_decode]; + scb.color_values[i][j] = unpack_table[values_to_decode[j + valuecount_to_decode]]; } valuecount_to_decode += vals; } // Fetch component for second-plane in the case of dual plane of weights. + scb.plane2_component = -1; if (is_dual_plane) { - scb.plane2_component = static_cast(read_bits(2, below_weights_pos - 2, pcb.data)); + scb.plane2_component = static_cast(read_bits(2, below_weights_pos - 2, pcb)); } } diff --git a/Source/astcenc_vecmathlib.h b/Source/astcenc_vecmathlib.h index 07a2ff3..d48f1d7 100644 --- a/Source/astcenc_vecmathlib.h +++ b/Source/astcenc_vecmathlib.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2021 Arm Limited +// Copyright 2019-2022 Arm Limited // Copyright 2008 Jose Fonseca // // Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -26,7 +26,7 @@ * with that is available at compile time. The current vector width is * accessible for e.g. loop strides via the ASTCENC_SIMD_WIDTH constant. * - * Explicit scalar types are acessible via the vint1, vfloat1, vmask1 types. + * Explicit scalar types are accessible via the vint1, vfloat1, vmask1 types. * These are provided primarily for prototyping and algorithm debug of VLA * implementations. * @@ -60,10 +60,13 @@ #if !defined(__clang__) && defined(_MSC_VER) #define ASTCENC_SIMD_INLINE __forceinline + #define ASTCENC_NO_INLINE #elif defined(__GNUC__) && !defined(__clang__) #define ASTCENC_SIMD_INLINE __attribute__((always_inline)) inline + #define ASTCENC_NO_INLINE __attribute__ ((noinline)) #else #define ASTCENC_SIMD_INLINE __attribute__((always_inline, nodebug)) inline + #define ASTCENC_NO_INLINE __attribute__ ((noinline)) #endif #if ASTCENC_AVX >= 2 @@ -160,7 +163,7 @@ */ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_8(unsigned int count) { - return count & ~(8 - 1); + return count & static_cast(~(8 - 1)); } /** @@ -172,7 +175,7 @@ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_8(unsigned int coun */ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_4(unsigned int count) { - return count & ~(4 - 1); + return count & static_cast(~(4 - 1)); } /** @@ -186,7 +189,7 @@ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_4(unsigned int coun */ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_vla(unsigned int count) { - return count & ~(ASTCENC_SIMD_WIDTH - 1); + return count & static_cast(~(ASTCENC_SIMD_WIDTH - 1)); } /** @@ -200,7 +203,7 @@ ASTCENC_SIMD_INLINE unsigned int round_down_to_simd_multiple_vla(unsigned int co */ ASTCENC_SIMD_INLINE unsigned int round_up_to_simd_multiple_vla(unsigned int count) { - int multiples = (count + ASTCENC_SIMD_WIDTH - 1) / ASTCENC_SIMD_WIDTH; + unsigned int multiples = (count + ASTCENC_SIMD_WIDTH - 1) / ASTCENC_SIMD_WIDTH; return multiples * ASTCENC_SIMD_WIDTH; } @@ -219,7 +222,7 @@ ASTCENC_SIMD_INLINE vfloat change_sign(vfloat a, vfloat b) /** * @brief Return fast, but approximate, vector atan(x). * - * Max error of this implementaiton is 0.004883. + * Max error of this implementation is 0.004883. */ ASTCENC_SIMD_INLINE vfloat atan(vfloat x) { @@ -399,7 +402,7 @@ static ASTCENC_SIMD_INLINE vint4 clz(vint4 a) // the original integer value into a 2^N encoding we can recover easily. // Convert to float without risk of rounding up by keeping only top 8 bits. - // This trick is is guranteed to keep top 8 bits and clear the 9th. + // This trick is is guaranteed to keep top 8 bits and clear the 9th. a = (~lsr<8>(a)) & a; a = float_as_int(int_to_float(a)); @@ -413,7 +416,7 @@ static ASTCENC_SIMD_INLINE vint4 clz(vint4 a) /** * @brief Return lanewise 2^a for each lane in @c a. * - * Use of signed int mean that this is only valid for values in range [0, 31]. + * Use of signed int means that this is only valid for values in range [0, 31]. */ static ASTCENC_SIMD_INLINE vint4 two_to_the_n(vint4 a) { @@ -507,7 +510,7 @@ static ASTCENC_SIMD_INLINE vfloat4 frexp(vfloat4 a, vint4& exp) exp = (lsr<23>(ai) & 0xFF) - 126; // Extract and unbias the mantissa - vint4 manti = (ai & 0x807FFFFF) | 0x3F000000; + vint4 manti = (ai & static_cast(0x807FFFFF)) | 0x3F000000; return int_as_float(manti); } diff --git a/Source/astcenc_vecmathlib_avx2_8.h b/Source/astcenc_vecmathlib_avx2_8.h index fe8a1b1..3ca25e3 100644 --- a/Source/astcenc_vecmathlib_avx2_8.h +++ b/Source/astcenc_vecmathlib_avx2_8.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2021 Arm Limited +// Copyright 2019-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -36,6 +36,9 @@ #include +// Define convenience intrinsics that are missing on older compilers +#define astcenc_mm256_set_m128i(m, n) _mm256_insertf128_si256(_mm256_castsi128_si256((n)), (m), 1) + // ============================================================================ // vfloat8 data type // ============================================================================ @@ -86,7 +89,8 @@ struct vfloat8 /** * @brief Construct from an existing SIMD register. */ - ASTCENC_SIMD_INLINE explicit vfloat8(__m256 a) { + ASTCENC_SIMD_INLINE explicit vfloat8(__m256 a) + { m = a; } @@ -237,6 +241,14 @@ struct vint8 return vint8(_mm256_broadcastd_epi32(a)); } + /** + * @brief Factory that returns a vector loaded from unaligned memory. + */ + static ASTCENC_SIMD_INLINE vint8 load(const uint8_t* p) + { + return vint8(_mm256_lddqu_si256(reinterpret_cast(p))); + } + /** * @brief Factory that returns a vector loaded from 32B aligned memory. */ @@ -340,9 +352,9 @@ ASTCENC_SIMD_INLINE vmask8 operator~(vmask8 a) * * bit0 = lane 0 */ -ASTCENC_SIMD_INLINE unsigned mask(vmask8 a) +ASTCENC_SIMD_INLINE unsigned int mask(vmask8 a) { - return _mm256_movemask_ps(a.m); + return static_cast(_mm256_movemask_ps(a.m)); } /** @@ -354,7 +366,7 @@ ASTCENC_SIMD_INLINE bool any(vmask8 a) } /** - * @brief True if any lanes are enabled, false otherwise. + * @brief True if all lanes are enabled, false otherwise. */ ASTCENC_SIMD_INLINE bool all(vmask8 a) { @@ -461,6 +473,14 @@ ASTCENC_SIMD_INLINE vmask8 operator>(vint8 a, vint8 b) return vmask8(_mm256_cmpgt_epi32(a.m, b.m)); } +/** + * @brief Logical shift left. + */ +template ASTCENC_SIMD_INLINE vint8 lsl(vint8 a) +{ + return vint8(_mm256_slli_epi32(a.m, s)); +} + /** * @brief Arithmetic shift right. */ @@ -503,16 +523,13 @@ ASTCENC_SIMD_INLINE vint8 hmin(vint8 a) m = _mm_min_epi32(m, _mm_shuffle_epi32(m, _MM_SHUFFLE(0,0,0,1))); m = _mm_shuffle_epi32(m, _MM_SHUFFLE(0,0,0,0)); - // This is the most logical implementation, but the convenience intrinsic - // is missing on older compilers (supported in g++ 9 and clang++ 9). - //__m256i r = _mm256_set_m128i(m, m) - __m256i r = _mm256_insertf128_si256(_mm256_castsi128_si256(m), m, 1); + __m256i r = astcenc_mm256_set_m128i(m, m); vint8 vmin(r); return vmin; } /** - * @brief Return the horizontal minimum of a vector. + * @brief Return the horizontal maximum of a vector. */ ASTCENC_SIMD_INLINE vint8 hmax(vint8 a) { @@ -521,10 +538,7 @@ ASTCENC_SIMD_INLINE vint8 hmax(vint8 a) m = _mm_max_epi32(m, _mm_shuffle_epi32(m, _MM_SHUFFLE(0,0,0,1))); m = _mm_shuffle_epi32(m, _MM_SHUFFLE(0,0,0,0)); - // This is the most logical implementation, but the convenience intrinsic - // is missing on older compilers (supported in g++ 9 and clang++ 9). - //__m256i r = _mm256_set_m128i(m, m) - __m256i r = _mm256_insertf128_si256(_mm256_castsi128_si256(m), m, 1); + __m256i r = astcenc_mm256_set_m128i(m, m); vint8 vmax(r); return vmax; } @@ -578,10 +592,7 @@ ASTCENC_SIMD_INLINE vint8 pack_low_bytes(vint8 v) __m128i a1 = _mm256_extracti128_si256(a, 1); __m128i b = _mm_unpacklo_epi32(a0, a1); - // This is the most logical implementation, but the convenience intrinsic - // is missing on older compilers (supported in g++ 9 and clang++ 9). - //__m256i r = _mm256_set_m128i(b, b) - __m256i r = _mm256_insertf128_si256(_mm256_castsi128_si256(b), b, 1); + __m256i r = astcenc_mm256_set_m128i(b, b); return vint8(r); } @@ -731,6 +742,16 @@ ASTCENC_SIMD_INLINE vfloat8 min(vfloat8 a, vfloat8 b) return vfloat8(_mm256_min_ps(a.m, b.m)); } +/** + * @brief Return the min vector of a vector and a scalar. + * + * If either lane value is NaN, @c b will be returned for that lane. + */ +ASTCENC_SIMD_INLINE vfloat8 min(vfloat8 a, float b) +{ + return min(a, vfloat8(b)); +} + /** * @brief Return the max vector of two vectors. * @@ -741,6 +762,16 @@ ASTCENC_SIMD_INLINE vfloat8 max(vfloat8 a, vfloat8 b) return vfloat8(_mm256_max_ps(a.m, b.m)); } +/** + * @brief Return the max vector of a vector and a scalar. + * + * If either lane value is NaN, @c b will be returned for that lane. + */ +ASTCENC_SIMD_INLINE vfloat8 max(vfloat8 a, float b) +{ + return max(a, vfloat8(b)); +} + /** * @brief Return the clamped value between min and max. * @@ -805,13 +836,13 @@ ASTCENC_SIMD_INLINE vfloat8 hmin(vfloat8 a) { __m128 vlow = _mm256_castps256_ps128(a.m); __m128 vhigh = _mm256_extractf128_ps(a.m, 1); - vlow = _mm_min_ps(vlow, vhigh); + vlow = _mm_min_ps(vlow, vhigh); // First do an horizontal reduction. __m128 shuf = _mm_shuffle_ps(vlow, vlow, _MM_SHUFFLE(2, 3, 0, 1)); __m128 mins = _mm_min_ps(vlow, shuf); - shuf = _mm_movehl_ps(shuf, mins); - mins = _mm_min_ss(mins, shuf); + shuf = _mm_movehl_ps(shuf, mins); + mins = _mm_min_ss(mins, shuf); // This is the most logical implementation, but the convenience intrinsic // is missing on older compilers (supported in g++ 9 and clang++ 9). @@ -836,13 +867,13 @@ ASTCENC_SIMD_INLINE vfloat8 hmax(vfloat8 a) { __m128 vlow = _mm256_castps256_ps128(a.m); __m128 vhigh = _mm256_extractf128_ps(a.m, 1); - vhigh = _mm_max_ps(vlow, vhigh); + vhigh = _mm_max_ps(vlow, vhigh); // First do an horizontal reduction. __m128 shuf = _mm_shuffle_ps(vhigh, vhigh, _MM_SHUFFLE(2, 3, 0, 1)); __m128 maxs = _mm_max_ps(vhigh, shuf); - shuf = _mm_movehl_ps(shuf,maxs); - maxs = _mm_max_ss(maxs, shuf); + shuf = _mm_movehl_ps(shuf,maxs); + maxs = _mm_max_ss(maxs, shuf); // This is the most logical implementation, but the convenience intrinsic // is missing on older compilers (supported in g++ 9 and clang++ 9). @@ -972,6 +1003,16 @@ ASTCENC_SIMD_INLINE vint8 float_to_int(vfloat8 a) return vint8(_mm256_cvttps_epi32(a.m)); } +/** + * @brief Return a integer value for a float vector, using round-to-nearest. + */ +ASTCENC_SIMD_INLINE vint8 float_to_int_rtn(vfloat8 a) +{ + a = a + vfloat8(0.5f); + return vint8(_mm256_cvttps_epi32(a.m)); +} + + /** * @brief Return a float value for an integer vector. */ @@ -1004,23 +1045,154 @@ ASTCENC_SIMD_INLINE vfloat8 int_as_float(vint8 a) return vfloat8(_mm256_castsi256_ps(a.m)); } +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint8& t0p) +{ + // AVX2 duplicates the table within each 128-bit lane + __m128i t0n = t0.m; + t0p = vint8(astcenc_mm256_set_m128i(t0n, t0n)); +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint8& t0p, vint8& t1p) +{ + // AVX2 duplicates the table within each 128-bit lane + __m128i t0n = t0.m; + t0p = vint8(astcenc_mm256_set_m128i(t0n, t0n)); + + __m128i t1n = _mm_xor_si128(t0.m, t1.m); + t1p = vint8(astcenc_mm256_set_m128i(t1n, t1n)); +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare( + vint4 t0, vint4 t1, vint4 t2, vint4 t3, + vint8& t0p, vint8& t1p, vint8& t2p, vint8& t3p) +{ + // AVX2 duplicates the table within each 128-bit lane + __m128i t0n = t0.m; + t0p = vint8(astcenc_mm256_set_m128i(t0n, t0n)); + + __m128i t1n = _mm_xor_si128(t0.m, t1.m); + t1p = vint8(astcenc_mm256_set_m128i(t1n, t1n)); + + __m128i t2n = _mm_xor_si128(t1.m, t2.m); + t2p = vint8(astcenc_mm256_set_m128i(t2n, t2n)); + + __m128i t3n = _mm_xor_si128(t2.m, t3.m); + t3p = vint8(astcenc_mm256_set_m128i(t3n, t3n)); +} + +/** + * @brief Perform an 8-bit 16-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint8 vtable_8bt_32bi(vint8 t0, vint8 idx) +{ + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m256i idxx = _mm256_or_si256(idx.m, _mm256_set1_epi32(static_cast(0xFFFFFF00))); + + __m256i result = _mm256_shuffle_epi8(t0.m, idxx); + return vint8(result); +} + +/** + * @brief Perform an 8-bit 32-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint8 vtable_8bt_32bi(vint8 t0, vint8 t1, vint8 idx) +{ + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m256i idxx = _mm256_or_si256(idx.m, _mm256_set1_epi32(static_cast(0xFFFFFF00))); + + __m256i result = _mm256_shuffle_epi8(t0.m, idxx); + idxx = _mm256_sub_epi8(idxx, _mm256_set1_epi8(16)); + + __m256i result2 = _mm256_shuffle_epi8(t1.m, idxx); + result = _mm256_xor_si256(result, result2); + return vint8(result); +} + +/** + * @brief Perform an 8-bit 64-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint8 vtable_8bt_32bi(vint8 t0, vint8 t1, vint8 t2, vint8 t3, vint8 idx) +{ + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m256i idxx = _mm256_or_si256(idx.m, _mm256_set1_epi32(static_cast(0xFFFFFF00))); + + __m256i result = _mm256_shuffle_epi8(t0.m, idxx); + idxx = _mm256_sub_epi8(idxx, _mm256_set1_epi8(16)); + + __m256i result2 = _mm256_shuffle_epi8(t1.m, idxx); + result = _mm256_xor_si256(result, result2); + idxx = _mm256_sub_epi8(idxx, _mm256_set1_epi8(16)); + + result2 = _mm256_shuffle_epi8(t2.m, idxx); + result = _mm256_xor_si256(result, result2); + idxx = _mm256_sub_epi8(idxx, _mm256_set1_epi8(16)); + + result2 = _mm256_shuffle_epi8(t3.m, idxx); + result = _mm256_xor_si256(result, result2); + + return vint8(result); +} + +/** + * @brief Return a vector of interleaved RGBA data. + * + * Input vectors have the value stored in the bottom 8 bits of each lane, + * with high bits set to zero. + * + * Output vector stores a single RGBA texel packed in each lane. + */ +ASTCENC_SIMD_INLINE vint8 interleave_rgba8(vint8 r, vint8 g, vint8 b, vint8 a) +{ + return r + lsl<8>(g) + lsl<16>(b) + lsl<24>(a); +} + +/** + * @brief Store a vector, skipping masked lanes. + * + * All masked lanes must be at the end of vector, after all non-masked lanes. + */ +ASTCENC_SIMD_INLINE void store_lanes_masked(uint8_t* base, vint8 data, vmask8 mask) +{ + _mm256_maskstore_epi32(reinterpret_cast(base), _mm256_castps_si256(mask.m), data.m); +} + /** * @brief Debug function to print a vector of ints. */ ASTCENC_SIMD_INLINE void print(vint8 a) { - alignas(ASTCENC_VECALIGN) int v[8]; + alignas(32) int v[8]; storea(a, v); printf("v8_i32:\n %8d %8d %8d %8d %8d %8d %8d %8d\n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } +/** + * @brief Debug function to print a vector of ints. + */ +ASTCENC_SIMD_INLINE void printx(vint8 a) +{ + alignas(32) int v[8]; + storea(a, v); + printf("v8_i32:\n %08x %08x %08x %08x %08x %08x %08x %08x\n", + v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); +} + /** * @brief Debug function to print a vector of floats. */ ASTCENC_SIMD_INLINE void print(vfloat8 a) { - alignas(ASTCENC_VECALIGN) float v[8]; + alignas(32) float v[8]; storea(a, v); printf("v8_f32:\n %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f %0.4f\n", static_cast(v[0]), static_cast(v[1]), diff --git a/Source/astcenc_vecmathlib_common_4.h b/Source/astcenc_vecmathlib_common_4.h index b7d644d..1e04367 100644 --- a/Source/astcenc_vecmathlib_common_4.h +++ b/Source/astcenc_vecmathlib_common_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2020-2021 Arm Limited +// Copyright 2020-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -361,23 +361,51 @@ static inline int popcount(uint64_t v) #endif +/** + * @brief Apply signed bit transfer. + * + * @param input0 The first encoded endpoint. + * @param input1 The second encoded endpoint. + */ +static ASTCENC_SIMD_INLINE void bit_transfer_signed( + vint4& input0, + vint4& input1 +) { + input1 = lsr<1>(input1) | (input0 & 0x80); + input0 = lsr<1>(input0) & 0x3F; + + vmask4 mask = (input0 & 0x20) != vint4::zero(); + input0 = select(input0, input0 - 0x40, mask); +} + /** * @brief Debug function to print a vector of ints. */ ASTCENC_SIMD_INLINE void print(vint4 a) { - alignas(16) int v[4]; + ASTCENC_ALIGNAS int v[4]; storea(a, v); printf("v4_i32:\n %8d %8d %8d %8d\n", v[0], v[1], v[2], v[3]); } +/** + * @brief Debug function to print a vector of ints. + */ +ASTCENC_SIMD_INLINE void printx(vint4 a) +{ + ASTCENC_ALIGNAS int v[4]; + storea(a, v); + printf("v4_i32:\n %08x %08x %08x %08x\n", + v[0], v[1], v[2], v[3]); +} + /** * @brief Debug function to print a vector of floats. */ ASTCENC_SIMD_INLINE void print(vfloat4 a) { - alignas(16) float v[4]; + ASTCENC_ALIGNAS float v[4]; storea(a, v); printf("v4_f32:\n %0.4f %0.4f %0.4f %0.4f\n", static_cast(v[0]), static_cast(v[1]), diff --git a/Source/astcenc_vecmathlib_neon_4.h b/Source/astcenc_vecmathlib_neon_4.h index 7ac9da3..42545e7 100644 --- a/Source/astcenc_vecmathlib_neon_4.h +++ b/Source/astcenc_vecmathlib_neon_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2022 Arm Limited +// Copyright 2019-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -38,6 +38,7 @@ #endif #include +#include // ============================================================================ // vfloat4 data type @@ -106,7 +107,7 @@ struct vfloat4 */ template ASTCENC_SIMD_INLINE void set_lane(float a) { - m = vld1q_lane_f32(&a, m, l); + m = vsetq_lane_f32(a, m, l); } /** @@ -122,7 +123,7 @@ struct vfloat4 */ static ASTCENC_SIMD_INLINE vfloat4 load1(const float* p) { - return vfloat4(vdupq_n_f32(*p)); + return vfloat4(vld1q_dup_f32(p)); } /** @@ -202,9 +203,8 @@ struct vint4 */ ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p) { - uint32x2_t t8 {}; // Cast is safe - NEON loads are allowed to be unaligned - t8 = vld1_lane_u32((const uint32_t*)p, t8, 0); + uint32x2_t t8 = vld1_dup_u32(reinterpret_cast(p)); uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8))); m = vreinterpretq_s32_u32(vmovl_u16(t16)); } @@ -251,7 +251,7 @@ struct vint4 */ template ASTCENC_SIMD_INLINE void set_lane(int a) { - m = vld1q_lane_s32(&a, m, l); + m = vsetq_lane_s32(a, m, l); } /** @@ -270,6 +270,16 @@ struct vint4 return vint4(*p); } + /** + * @brief Factory that returns a vector loaded from unaligned memory. + */ + static ASTCENC_SIMD_INLINE vint4 load(const uint8_t* p) + { + vint4 data; + std::memcpy(&data.m, p, 4 * sizeof(int)); + return data; + } + /** * @brief Factory that returns a vector loaded from 16B aligned memory. */ @@ -283,7 +293,7 @@ struct vint4 */ static ASTCENC_SIMD_INLINE vint4 lane_id() { - alignas(ASTCENC_VECALIGN) static const int data[4] { 0, 1, 2, 3 }; + alignas(16) static const int data[4] { 0, 1, 2, 3 }; return vint4(vld1q_s32(data)); } @@ -346,6 +356,14 @@ struct vmask4 m = vreinterpretq_u32_s32(ms); } + /** + * @brief Get the scalar from a single lane. + */ + template ASTCENC_SIMD_INLINE bool lane() const + { + return vgetq_lane_u32(m, l) != 0; + } + /** * @brief The vector ... */ @@ -577,12 +595,20 @@ ASTCENC_SIMD_INLINE void store(vint4 a, int* p) vst1q_s32(p, a.m); } +/** + * @brief Store a vector to an unaligned memory address. + */ +ASTCENC_SIMD_INLINE void store(vint4 a, uint8_t* p) +{ + std::memcpy(p, &a.m, sizeof(int) * 4); +} + /** * @brief Store lowest N (vector width) bytes into an unaligned address. */ ASTCENC_SIMD_INLINE void store_nbytes(vint4 a, uint8_t* p) { - vst1q_lane_s32((int32_t*)p, a.m, 0); + vst1q_lane_s32(reinterpret_cast(p), a.m, 0); } /** @@ -842,7 +868,7 @@ ASTCENC_SIMD_INLINE vint4 float_to_int(vfloat4 a) */ ASTCENC_SIMD_INLINE vint4 float_to_int_rtn(vfloat4 a) { - a = round(a); + a = a + vfloat4(0.5f); return vint4(vcvtq_s32_f32(a.m)); } @@ -874,7 +900,7 @@ ASTCENC_SIMD_INLINE vint4 float_to_float16(vfloat4 a) static inline uint16_t float_to_float16(float a) { vfloat4 av(a); - return float_to_float16(av).lane<0>(); + return static_cast(float_to_float16(av).lane<0>()); } /** @@ -924,6 +950,138 @@ ASTCENC_SIMD_INLINE vfloat4 int_as_float(vint4 v) return vfloat4(vreinterpretq_f32_s32(v.m)); } +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4& t0p) +{ + t0p = t0; +} + + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p) +{ + t0p = t0; + t1p = t1; +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare( + vint4 t0, vint4 t1, vint4 t2, vint4 t3, + vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p) +{ + t0p = t0; + t1p = t1; + t2p = t2; + t3p = t3; +} + +/** + * @brief Perform an 8-bit 16-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx) +{ + int8x16_t table { + vreinterpretq_s8_s32(t0.m) + }; + + // Set index byte above max index for unused bytes so table lookup returns zero + int32x4_t idx_masked = vorrq_s32(idx.m, vdupq_n_s32(0xFFFFFF00)); + uint8x16_t idx_bytes = vreinterpretq_u8_s32(idx_masked); + + return vint4(vreinterpretq_s32_s8(vqtbl1q_s8(table, idx_bytes))); +} + +/** + * @brief Perform an 8-bit 32-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx) +{ + int8x16x2_t table { + vreinterpretq_s8_s32(t0.m), + vreinterpretq_s8_s32(t1.m) + }; + + // Set index byte above max index for unused bytes so table lookup returns zero + int32x4_t idx_masked = vorrq_s32(idx.m, vdupq_n_s32(0xFFFFFF00)); + uint8x16_t idx_bytes = vreinterpretq_u8_s32(idx_masked); + + return vint4(vreinterpretq_s32_s8(vqtbl2q_s8(table, idx_bytes))); +} + +/** + * @brief Perform an 8-bit 64-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx) +{ + int8x16x4_t table { + vreinterpretq_s8_s32(t0.m), + vreinterpretq_s8_s32(t1.m), + vreinterpretq_s8_s32(t2.m), + vreinterpretq_s8_s32(t3.m) + }; + + // Set index byte above max index for unused bytes so table lookup returns zero + int32x4_t idx_masked = vorrq_s32(idx.m, vdupq_n_s32(0xFFFFFF00)); + uint8x16_t idx_bytes = vreinterpretq_u8_s32(idx_masked); + + return vint4(vreinterpretq_s32_s8(vqtbl4q_s8(table, idx_bytes))); +} + +/** + * @brief Return a vector of interleaved RGBA data. + * + * Input vectors have the value stored in the bottom 8 bits of each lane, + * with high bits set to zero. + * + * Output vector stores a single RGBA texel packed in each lane. + */ +ASTCENC_SIMD_INLINE vint4 interleave_rgba8(vint4 r, vint4 g, vint4 b, vint4 a) +{ + return r + lsl<8>(g) + lsl<16>(b) + lsl<24>(a); +} + +/** + * @brief Store a single vector lane to an unaligned address. + */ +ASTCENC_SIMD_INLINE void store_lane(uint8_t* base, int data) +{ + std::memcpy(base, &data, sizeof(int)); +} + +/** + * @brief Store a vector, skipping masked lanes. + * + * All masked lanes must be at the end of vector, after all non-masked lanes. + */ +ASTCENC_SIMD_INLINE void store_lanes_masked(uint8_t* base, vint4 data, vmask4 mask) +{ + if (mask.lane<3>()) + { + store(data, base); + } + else if (mask.lane<2>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + store_lane(base + 8, data.lane<2>()); + } + else if (mask.lane<1>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + } + else if (mask.lane<0>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + } +} + #define ASTCENC_USE_NATIVE_POPCOUNT 1 /** diff --git a/Source/astcenc_vecmathlib_none_4.h b/Source/astcenc_vecmathlib_none_4.h index 5a399ef..1c95c2f 100644 --- a/Source/astcenc_vecmathlib_none_4.h +++ b/Source/astcenc_vecmathlib_none_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2021 Arm Limited +// Copyright 2019-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -275,6 +275,16 @@ struct vint4 return vint4(*p); } + /** + * @brief Factory that returns a vector loaded from unaligned memory. + */ + static ASTCENC_SIMD_INLINE vint4 load(const uint8_t* p) + { + vint4 data; + std::memcpy(&data.m, p, 4 * sizeof(int)); + return data; + } + /** * @brief Factory that returns a vector loaded from 16B aligned memory. */ @@ -341,6 +351,13 @@ struct vmask4 m[3] = d == false ? 0 : -1; } + /** + * @brief Get the scalar value of a single lane. + */ + template ASTCENC_SIMD_INLINE float lane() const + { + return m[l] != 0; + } /** * @brief The vector ... @@ -550,10 +567,15 @@ template ASTCENC_SIMD_INLINE vint4 lsl(vint4 a) */ template ASTCENC_SIMD_INLINE vint4 lsr(vint4 a) { - return vint4((int)(((unsigned int)a.m[0]) >> s), - (int)(((unsigned int)a.m[1]) >> s), - (int)(((unsigned int)a.m[2]) >> s), - (int)(((unsigned int)a.m[3]) >> s)); + unsigned int as0 = static_cast(a.m[0]) >> s; + unsigned int as1 = static_cast(a.m[1]) >> s; + unsigned int as2 = static_cast(a.m[2]) >> s; + unsigned int as3 = static_cast(a.m[3]) >> s; + + return vint4(static_cast(as0), + static_cast(as1), + static_cast(as2), + static_cast(as3)); } /** @@ -639,13 +661,20 @@ ASTCENC_SIMD_INLINE void store(vint4 a, int* p) p[3] = a.m[3]; } +/** + * @brief Store a vector to an unaligned memory address. + */ +ASTCENC_SIMD_INLINE void store(vint4 a, uint8_t* p) +{ + std::memcpy(p, a.m, sizeof(int) * 4); +} + /** * @brief Store lowest N (vector width) bytes into an unaligned address. */ ASTCENC_SIMD_INLINE void store_nbytes(vint4 a, uint8_t* p) { - int* pi = (int*)p; - *pi = a.m[0]; + std::memcpy(p, a.m, sizeof(uint8_t) * 4); } /** @@ -678,10 +707,10 @@ ASTCENC_SIMD_INLINE vint4 pack_low_bytes(vint4 a) */ ASTCENC_SIMD_INLINE vint4 select(vint4 a, vint4 b, vmask4 cond) { - return vint4((cond.m[0] & 0x80000000) ? b.m[0] : a.m[0], - (cond.m[1] & 0x80000000) ? b.m[1] : a.m[1], - (cond.m[2] & 0x80000000) ? b.m[2] : a.m[2], - (cond.m[3] & 0x80000000) ? b.m[3] : a.m[3]); + return vint4((cond.m[0] & static_cast(0x80000000)) ? b.m[0] : a.m[0], + (cond.m[1] & static_cast(0x80000000)) ? b.m[1] : a.m[1], + (cond.m[2] & static_cast(0x80000000)) ? b.m[2] : a.m[2], + (cond.m[3] & static_cast(0x80000000)) ? b.m[3] : a.m[3]); } // ============================================================================ @@ -892,10 +921,10 @@ ASTCENC_SIMD_INLINE vfloat4 sqrt(vfloat4 a) */ ASTCENC_SIMD_INLINE vfloat4 select(vfloat4 a, vfloat4 b, vmask4 cond) { - return vfloat4((cond.m[0] & 0x80000000) ? b.m[0] : a.m[0], - (cond.m[1] & 0x80000000) ? b.m[1] : a.m[1], - (cond.m[2] & 0x80000000) ? b.m[2] : a.m[2], - (cond.m[3] & 0x80000000) ? b.m[3] : a.m[3]); + return vfloat4((cond.m[0] & static_cast(0x80000000)) ? b.m[0] : a.m[0], + (cond.m[1] & static_cast(0x80000000)) ? b.m[1] : a.m[1], + (cond.m[2] & static_cast(0x80000000)) ? b.m[2] : a.m[2], + (cond.m[3] & static_cast(0x80000000)) ? b.m[3] : a.m[3]); } /** @@ -903,10 +932,10 @@ ASTCENC_SIMD_INLINE vfloat4 select(vfloat4 a, vfloat4 b, vmask4 cond) */ ASTCENC_SIMD_INLINE vfloat4 select_msb(vfloat4 a, vfloat4 b, vmask4 cond) { - return vfloat4((cond.m[0] & 0x80000000) ? b.m[0] : a.m[0], - (cond.m[1] & 0x80000000) ? b.m[1] : a.m[1], - (cond.m[2] & 0x80000000) ? b.m[2] : a.m[2], - (cond.m[3] & 0x80000000) ? b.m[3] : a.m[3]); + return vfloat4((cond.m[0] & static_cast(0x80000000)) ? b.m[0] : a.m[0], + (cond.m[1] & static_cast(0x80000000)) ? b.m[1] : a.m[1], + (cond.m[2] & static_cast(0x80000000)) ? b.m[2] : a.m[2], + (cond.m[3] & static_cast(0x80000000)) ? b.m[3] : a.m[3]); } /** @@ -947,10 +976,10 @@ ASTCENC_SIMD_INLINE void storea(vfloat4 a, float* ptr) */ ASTCENC_SIMD_INLINE vint4 float_to_int(vfloat4 a) { - return vint4((int)a.m[0], - (int)a.m[1], - (int)a.m[2], - (int)a.m[3]); + return vint4(static_cast(a.m[0]), + static_cast(a.m[1]), + static_cast(a.m[2]), + static_cast(a.m[3])); } /**f @@ -958,10 +987,11 @@ ASTCENC_SIMD_INLINE vint4 float_to_int(vfloat4 a) */ ASTCENC_SIMD_INLINE vint4 float_to_int_rtn(vfloat4 a) { - return vint4((int)(a.m[0] + 0.5f), - (int)(a.m[1] + 0.5f), - (int)(a.m[2] + 0.5f), - (int)(a.m[3] + 0.5f)); + a = a + vfloat4(0.5f); + return vint4(static_cast(a.m[0]), + static_cast(a.m[1]), + static_cast(a.m[2]), + static_cast(a.m[3])); } /** @@ -969,10 +999,10 @@ ASTCENC_SIMD_INLINE vint4 float_to_int_rtn(vfloat4 a) */ ASTCENC_SIMD_INLINE vfloat4 int_to_float(vint4 a) { - return vfloat4((float)a.m[0], - (float)a.m[1], - (float)a.m[2], - (float)a.m[3]); + return vfloat4(static_cast(a.m[0]), + static_cast(a.m[1]), + static_cast(a.m[2]), + static_cast(a.m[3])); } /** @@ -1001,10 +1031,10 @@ static inline uint16_t float_to_float16(float a) ASTCENC_SIMD_INLINE vfloat4 float16_to_float(vint4 a) { return vfloat4( - sf16_to_float(a.lane<0>()), - sf16_to_float(a.lane<1>()), - sf16_to_float(a.lane<2>()), - sf16_to_float(a.lane<3>())); + sf16_to_float(static_cast(a.lane<0>())), + sf16_to_float(static_cast(a.lane<1>())), + sf16_to_float(static_cast(a.lane<2>())), + sf16_to_float(static_cast(a.lane<3>()))); } /** @@ -1025,7 +1055,7 @@ ASTCENC_SIMD_INLINE float float16_to_float(uint16_t a) ASTCENC_SIMD_INLINE vint4 float_as_int(vfloat4 a) { vint4 r; - memcpy(r.m, a.m, 4 * 4); + std::memcpy(r.m, a.m, 4 * 4); return r; } @@ -1039,8 +1069,138 @@ ASTCENC_SIMD_INLINE vint4 float_as_int(vfloat4 a) ASTCENC_SIMD_INLINE vfloat4 int_as_float(vint4 a) { vfloat4 r; - memcpy(r.m, a.m, 4 * 4); + std::memcpy(r.m, a.m, 4 * 4); return r; } +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4& t0p) +{ + t0p = t0; +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p) +{ + t0p = t0; + t1p = t1; +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare( + vint4 t0, vint4 t1, vint4 t2, vint4 t3, + vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p) +{ + t0p = t0; + t1p = t1; + t2p = t2; + t3p = t3; +} + +/** + * @brief Perform an 8-bit 16-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx) +{ + uint8_t table[16]; + + std::memcpy(table + 0, t0.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +} + + +/** + * @brief Perform an 8-bit 32-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx) +{ + uint8_t table[32]; + + std::memcpy(table + 0, t0.m, 4 * sizeof(int)); + std::memcpy(table + 16, t1.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +} + +/** + * @brief Perform an 8-bit 64-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx) +{ + uint8_t table[64]; + + std::memcpy(table + 0, t0.m, 4 * sizeof(int)); + std::memcpy(table + 16, t1.m, 4 * sizeof(int)); + std::memcpy(table + 32, t2.m, 4 * sizeof(int)); + std::memcpy(table + 48, t3.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +} + +/** + * @brief Return a vector of interleaved RGBA data. + * + * Input vectors have the value stored in the bottom 8 bits of each lane, + * with high bits set to zero. + * + * Output vector stores a single RGBA texel packed in each lane. + */ +ASTCENC_SIMD_INLINE vint4 interleave_rgba8(vint4 r, vint4 g, vint4 b, vint4 a) +{ + return r + lsl<8>(g) + lsl<16>(b) + lsl<24>(a); +} + +/** + * @brief Store a single vector lane to an unaligned address. + */ +ASTCENC_SIMD_INLINE void store_lane(uint8_t* base, int data) +{ + std::memcpy(base, &data, sizeof(int)); +} + +/** + * @brief Store a vector, skipping masked lanes. + * + * All masked lanes must be at the end of vector, after all non-masked lanes. + * Input is a byte array of at least 4 bytes per unmasked entry. + */ +ASTCENC_SIMD_INLINE void store_lanes_masked(uint8_t* base, vint4 data, vmask4 mask) +{ + if (mask.m[3]) + { + store(data, base); + } + else if (mask.m[2]) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + store_lane(base + 8, data.lane<2>()); + } + else if (mask.m[1]) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + } + else if (mask.m[0]) + { + store_lane(base + 0, data.lane<0>()); + } +} + #endif // #ifndef ASTC_VECMATHLIB_NONE_4_H_INCLUDED diff --git a/Source/astcenc_vecmathlib_sse_4.h b/Source/astcenc_vecmathlib_sse_4.h index 868522d..b69655f 100644 --- a/Source/astcenc_vecmathlib_sse_4.h +++ b/Source/astcenc_vecmathlib_sse_4.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2019-2021 Arm Limited +// Copyright 2019-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -39,6 +39,7 @@ #endif #include +#include // ============================================================================ // vfloat4 data type @@ -292,6 +293,18 @@ struct vint4 return vint4(*p); } + /** + * @brief Factory that returns a vector loaded from unaligned memory. + */ + static ASTCENC_SIMD_INLINE vint4 load(const uint8_t* p) + { +#if ASTCENC_SSE >= 41 + return vint4(_mm_lddqu_si128(reinterpret_cast(p))); +#else + return vint4(_mm_loadu_si128(reinterpret_cast(p))); +#endif + } + /** * @brief Factory that returns a vector loaded from 16B aligned memory. */ @@ -363,6 +376,14 @@ struct vmask4 m = _mm_castsi128_ps(mask.m); } + /** + * @brief Get the scalar value of a single lane. + */ + template ASTCENC_SIMD_INLINE bool lane() const + { + return _mm_cvtss_f32(_mm_shuffle_ps(m, m, l)) != 0.0f; + } + /** * @brief The vector ... */ @@ -412,7 +433,7 @@ ASTCENC_SIMD_INLINE vmask4 operator~(vmask4 a) */ ASTCENC_SIMD_INLINE unsigned int mask(vmask4 a) { - return _mm_movemask_ps(a.m); + return static_cast(_mm_movemask_ps(a.m)); } // ============================================================================ @@ -625,6 +646,14 @@ ASTCENC_SIMD_INLINE void store(vint4 a, int* p) _mm_storeu_ps(reinterpret_cast(p), _mm_castsi128_ps(a.m)); } +/** + * @brief Store a vector to an unaligned memory address. + */ +ASTCENC_SIMD_INLINE void store(vint4 a, uint8_t* p) +{ + std::memcpy(p, &a.m, sizeof(int) * 4); +} + /** * @brief Store lowest N (vector width) bytes into an unaligned address. */ @@ -801,7 +830,7 @@ ASTCENC_SIMD_INLINE vfloat4 round(vfloat4 a) return vfloat4(_mm_round_ps(a.m, flags)); #else __m128 v = a.m; - __m128 neg_zero = _mm_castsi128_ps(_mm_set1_epi32(0x80000000)); + __m128 neg_zero = _mm_castsi128_ps(_mm_set1_epi32(static_cast(0x80000000))); __m128 no_fraction = _mm_set1_ps(8388608.0f); __m128 abs_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)); __m128 sign = _mm_and_ps(v, neg_zero); @@ -926,7 +955,7 @@ ASTCENC_SIMD_INLINE vint4 float_to_int(vfloat4 a) */ ASTCENC_SIMD_INLINE vint4 float_to_int_rtn(vfloat4 a) { - a = round(a); + a = a + vfloat4(0.5f); return vint4(_mm_cvttps_epi32(a.m)); } @@ -980,10 +1009,10 @@ ASTCENC_SIMD_INLINE vfloat4 float16_to_float(vint4 a) return vfloat4(f32); #else return vfloat4( - sf16_to_float(a.lane<0>()), - sf16_to_float(a.lane<1>()), - sf16_to_float(a.lane<2>()), - sf16_to_float(a.lane<3>())); + sf16_to_float(static_cast(a.lane<0>())), + sf16_to_float(static_cast(a.lane<1>())), + sf16_to_float(static_cast(a.lane<2>())), + sf16_to_float(static_cast(a.lane<3>()))); #endif } @@ -993,7 +1022,7 @@ ASTCENC_SIMD_INLINE vfloat4 float16_to_float(vint4 a) ASTCENC_SIMD_INLINE float float16_to_float(uint16_t a) { #if ASTCENC_F16C >= 1 - __m128i packed = _mm_set1_epi16(a); + __m128i packed = _mm_set1_epi16(static_cast(a)); __m128 f32 = _mm_cvtph_ps(packed); return _mm_cvtss_f32(f32); #else @@ -1025,6 +1054,208 @@ ASTCENC_SIMD_INLINE vfloat4 int_as_float(vint4 v) return vfloat4(_mm_castsi128_ps(v.m)); } +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4& t0p) +{ + t0p = t0; +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p) +{ +#if ASTCENC_SSE >= 41 + t0p = t0; + t1p = t0 ^ t1; +#else + t0p = t0; + t1p = t1; +#endif +} + +/** + * @brief Prepare a vtable lookup table for use with the native SIMD size. + */ +ASTCENC_SIMD_INLINE void vtable_prepare( + vint4 t0, vint4 t1, vint4 t2, vint4 t3, + vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p) +{ +#if ASTCENC_SSE >= 41 + t0p = t0; + t1p = t0 ^ t1; + t2p = t1 ^ t2; + t3p = t2 ^ t3; +#else + t0p = t0; + t1p = t1; + t2p = t2; + t3p = t3; +#endif +} + +/** + * @brief Perform an 8-bit 16-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx) +{ +#if ASTCENC_SSE >= 41 + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast(0xFFFFFF00))); + + __m128i result = _mm_shuffle_epi8(t0.m, idxx); + return vint4(result); +#else + uint8_t table[16]; + + std::memcpy(table + 0, &t0.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +#endif +} + +/** + * @brief Perform an 8-bit 32-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx) +{ +#if ASTCENC_SSE >= 41 + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast(0xFFFFFF00))); + + __m128i result = _mm_shuffle_epi8(t0.m, idxx); + idxx = _mm_sub_epi8(idxx, _mm_set1_epi8(16)); + + __m128i result2 = _mm_shuffle_epi8(t1.m, idxx); + result = _mm_xor_si128(result, result2); + + return vint4(result); +#else + uint8_t table[32]; + + std::memcpy(table + 0, &t0.m, 4 * sizeof(int)); + std::memcpy(table + 16, &t1.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +#endif +} + +/** + * @brief Perform an 8-bit 64-entry table lookup, with 32-bit indexes. + */ +ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx) +{ +#if ASTCENC_SSE >= 41 + // Set index byte MSB to 1 for unused bytes so shuffle returns zero + __m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast(0xFFFFFF00))); + + __m128i result = _mm_shuffle_epi8(t0.m, idxx); + idxx = _mm_sub_epi8(idxx, _mm_set1_epi8(16)); + + __m128i result2 = _mm_shuffle_epi8(t1.m, idxx); + result = _mm_xor_si128(result, result2); + idxx = _mm_sub_epi8(idxx, _mm_set1_epi8(16)); + + result2 = _mm_shuffle_epi8(t2.m, idxx); + result = _mm_xor_si128(result, result2); + idxx = _mm_sub_epi8(idxx, _mm_set1_epi8(16)); + + result2 = _mm_shuffle_epi8(t3.m, idxx); + result = _mm_xor_si128(result, result2); + + return vint4(result); +#else + uint8_t table[64]; + + std::memcpy(table + 0, &t0.m, 4 * sizeof(int)); + std::memcpy(table + 16, &t1.m, 4 * sizeof(int)); + std::memcpy(table + 32, &t2.m, 4 * sizeof(int)); + std::memcpy(table + 48, &t3.m, 4 * sizeof(int)); + + return vint4(table[idx.lane<0>()], + table[idx.lane<1>()], + table[idx.lane<2>()], + table[idx.lane<3>()]); +#endif +} + +/** + * @brief Return a vector of interleaved RGBA data. + * + * Input vectors have the value stored in the bottom 8 bits of each lane, + * with high bits set to zero. + * + * Output vector stores a single RGBA texel packed in each lane. + */ +ASTCENC_SIMD_INLINE vint4 interleave_rgba8(vint4 r, vint4 g, vint4 b, vint4 a) +{ +// Workaround an XCode compiler internal fault; note is slower than slli_epi32 +// so we should revert this when we get the opportunity +#if defined(__APPLE__) + __m128i value = r.m; + value = _mm_add_epi32(value, _mm_bslli_si128(g.m, 1)); + value = _mm_add_epi32(value, _mm_bslli_si128(b.m, 2)); + value = _mm_add_epi32(value, _mm_bslli_si128(a.m, 3)); + return vint4(value); +#else + __m128i value = r.m; + value = _mm_add_epi32(value, _mm_slli_epi32(g.m, 8)); + value = _mm_add_epi32(value, _mm_slli_epi32(b.m, 16)); + value = _mm_add_epi32(value, _mm_slli_epi32(a.m, 24)); + return vint4(value); +#endif +} + +/** + * @brief Store a single vector lane to an unaligned address. + */ +ASTCENC_SIMD_INLINE void store_lane(uint8_t* base, int data) +{ + std::memcpy(base, &data, sizeof(int)); +} + +/** + * @brief Store a vector, skipping masked lanes. + * + * All masked lanes must be at the end of vector, after all non-masked lanes. + */ +ASTCENC_SIMD_INLINE void store_lanes_masked(uint8_t* base, vint4 data, vmask4 mask) +{ +#if ASTCENC_AVX >= 2 + _mm_maskstore_epi32(reinterpret_cast(base), _mm_castps_si128(mask.m), data.m); +#else + // Note - we cannot use _mm_maskmoveu_si128 as the underlying hardware doesn't guarantee + // fault suppression on masked lanes so we can get page faults at the end of an image. + if (mask.lane<3>() != 0.0f) + { + store(data, base); + } + else if (mask.lane<2>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + store_lane(base + 8, data.lane<2>()); + } + else if (mask.lane<1>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + store_lane(base + 4, data.lane<1>()); + } + else if (mask.lane<0>() != 0.0f) + { + store_lane(base + 0, data.lane<0>()); + } +#endif +} + #if defined(ASTCENC_NO_INVARIANCE) && (ASTCENC_SSE >= 41) #define ASTCENC_USE_NATIVE_DOT_PRODUCT 1 diff --git a/Source/astcenc_weight_align.cpp b/Source/astcenc_weight_align.cpp index 96eb6ae..4e993e7 100644 --- a/Source/astcenc_weight_align.cpp +++ b/Source/astcenc_weight_align.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -44,26 +44,24 @@ #include #include - -static constexpr unsigned int ANGULAR_STEPS { 40 }; - -// Store a reduced sin/cos table for 64 possible weight values; this causes slight quality loss -// compared to using sin() and cos() directly. Must be 2^N. -static constexpr unsigned int SINCOS_STEPS { 64 }; +static constexpr unsigned int ANGULAR_STEPS { 32 }; static_assert((ANGULAR_STEPS % ASTCENC_SIMD_WIDTH) == 0, "ANGULAR_STEPS must be multiple of ASTCENC_SIMD_WIDTH"); -static uint8_t max_angular_steps_needed_for_quant_level[13]; +static_assert(ANGULAR_STEPS >= 32, + "ANGULAR_STEPS must be at least max(steps_for_quant_level)"); + +// Store a reduced sin/cos table for 64 possible weight values; this causes +// slight quality loss compared to using sin() and cos() directly. Must be 2^N. +static constexpr unsigned int SINCOS_STEPS { 64 }; -// The next-to-last entry is supposed to have the value 33. This because the 32-weight mode leaves a -// double-sized hole in the middle of the weight space, so we are better off matching 33 weights. -static const uint8_t quantization_steps_for_level[13] { - 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 33, 36 +static const uint8_t steps_for_quant_level[12] { + 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32 }; -alignas(ASTCENC_VECALIGN) static float sin_table[SINCOS_STEPS][ANGULAR_STEPS]; -alignas(ASTCENC_VECALIGN) static float cos_table[SINCOS_STEPS][ANGULAR_STEPS]; +ASTCENC_ALIGNAS static float sin_table[SINCOS_STEPS][ANGULAR_STEPS]; +ASTCENC_ALIGNAS static float cos_table[SINCOS_STEPS][ANGULAR_STEPS]; #if defined(ASTCENC_DIAGNOSTICS) static bool print_once { true }; @@ -72,7 +70,6 @@ alignas(ASTCENC_VECALIGN) static float cos_table[SINCOS_STEPS][ANGULAR_STEPS]; /* See header for documentation. */ void prepare_angular_tables() { - unsigned int max_angular_steps_needed_for_quant_steps[ANGULAR_STEPS + 1]; for (unsigned int i = 0; i < ANGULAR_STEPS; i++) { float angle_step = static_cast(i + 1); @@ -82,13 +79,6 @@ void prepare_angular_tables() sin_table[j][i] = static_cast(sinf((2.0f * astc::PI / (SINCOS_STEPS - 1.0f)) * angle_step * static_cast(j))); cos_table[j][i] = static_cast(cosf((2.0f * astc::PI / (SINCOS_STEPS - 1.0f)) * angle_step * static_cast(j))); } - - max_angular_steps_needed_for_quant_steps[i + 1] = astc::min(i + 1, ANGULAR_STEPS - 1); - } - - for (unsigned int i = 0; i < 13; i++) - { - max_angular_steps_needed_for_quant_level[i] = max_angular_steps_needed_for_quant_steps[quantization_steps_for_level[i]]; } } @@ -109,7 +99,7 @@ static void compute_angular_offsets( promise(weight_count > 0); promise(max_angular_steps > 0); - alignas(ASTCENC_VECALIGN) int isamplev[BLOCK_MAX_WEIGHTS]; + ASTCENC_ALIGNAS int isamplev[BLOCK_MAX_WEIGHTS]; // Precompute isample; arrays are always allocated 64 elements long for (unsigned int i = 0; i < weight_count; i += ASTCENC_SIMD_WIDTH) @@ -165,7 +155,7 @@ static void compute_lowest_and_highest_weight( unsigned int max_angular_steps, unsigned int max_quant_steps, const float* offsets, - int* lowest_weight, + float* lowest_weight, int* weight_span, float* error, float* cut_low_weight_error, @@ -184,11 +174,11 @@ static void compute_lowest_and_highest_weight( vfloat errval = vfloat::zero(); vfloat cut_low_weight_err = vfloat::zero(); vfloat cut_high_weight_err = vfloat::zero(); - vfloat offset = loada(&offsets[sp]); + vfloat offset = loada(offsets + sp); - for (unsigned int j = 0; j < weight_count; ++j) + for (unsigned int j = 0; j < weight_count; j++) { - vfloat sval = load1(&dec_weight_ideal_value[j]) * rcp_stepsize - offset; + vfloat sval = load1(dec_weight_ideal_value + j) * rcp_stepsize - offset; vfloat svalrte = round(sval); vfloat diff = sval - svalrte; errval += diff * diff; @@ -218,16 +208,16 @@ static void compute_lowest_and_highest_weight( vint span = float_to_int(maxidx - minidx + vfloat(1)); span = min(span, vint(max_quant_steps + 3)); span = max(span, vint(2)); - storea(float_to_int(minidx), &lowest_weight[sp]); - storea(span, &weight_span[sp]); + storea(minidx, lowest_weight + sp); + storea(span, weight_span + sp); // The cut_(lowest/highest)_weight_error indicate the error that results from forcing // samples that should have had the weight value one step (up/down). vfloat ssize = 1.0f / rcp_stepsize; vfloat errscale = ssize * ssize; - storea(errval * errscale, &error[sp]); - storea(cut_low_weight_err * errscale, &cut_low_weight_error[sp]); - storea(cut_high_weight_err * errscale, &cut_high_weight_error[sp]); + storea(errval * errscale, error + sp); + storea(cut_low_weight_err * errscale, cut_low_weight_error + sp); + storea(cut_high_weight_err * errscale, cut_high_weight_error + sp); rcp_stepsize = rcp_stepsize + vfloat(ASTCENC_SIMD_WIDTH); } @@ -246,21 +236,22 @@ static void compute_angular_endpoints_for_quant_levels( unsigned int weight_count, const float* dec_weight_ideal_value, unsigned int max_quant_level, - float low_value[12], - float high_value[12] + float low_value[TUNE_MAX_ANGULAR_QUANT + 1], + float high_value[TUNE_MAX_ANGULAR_QUANT + 1] ) { - unsigned int max_quant_steps = quantization_steps_for_level[max_quant_level]; + unsigned int max_quant_steps = steps_for_quant_level[max_quant_level]; + unsigned int max_angular_steps = steps_for_quant_level[max_quant_level]; + + ASTCENC_ALIGNAS float angular_offsets[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) float angular_offsets[ANGULAR_STEPS]; - unsigned int max_angular_steps = max_angular_steps_needed_for_quant_level[max_quant_level]; compute_angular_offsets(weight_count, dec_weight_ideal_value, max_angular_steps, angular_offsets); - alignas(ASTCENC_VECALIGN) int32_t lowest_weight[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) int32_t weight_span[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) float error[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) float cut_low_weight_error[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) float cut_high_weight_error[ANGULAR_STEPS]; + ASTCENC_ALIGNAS float lowest_weight[ANGULAR_STEPS]; + ASTCENC_ALIGNAS int32_t weight_span[ANGULAR_STEPS]; + ASTCENC_ALIGNAS float error[ANGULAR_STEPS]; + ASTCENC_ALIGNAS float cut_low_weight_error[ANGULAR_STEPS]; + ASTCENC_ALIGNAS float cut_high_weight_error[ANGULAR_STEPS]; compute_lowest_and_highest_weight(weight_count, dec_weight_ideal_value, max_angular_steps, max_quant_steps, @@ -270,7 +261,7 @@ static void compute_angular_endpoints_for_quant_levels( // For each quantization level, find the best error terms. Use packed vectors so data-dependent // branches can become selects. This involves some integer to float casts, but the values are // small enough so they never round the wrong way. - vfloat4 best_results[40]; + vfloat4 best_results[36]; // Initialize the array to some safe defaults promise(max_quant_steps > 0); @@ -296,30 +287,30 @@ static void compute_angular_endpoints_for_quant_levels( // Check best error against record N vfloat4 best_result = best_results[idx_span]; vfloat4 new_result = vfloat4(error[i], i_flt, 0.0f, 0.0f); - vmask4 mask1(best_result.lane<0>() > error[i]); - best_results[idx_span] = select(best_result, new_result, mask1); + vmask4 mask = vfloat4(best_result.lane<0>()) > vfloat4(error[i]); + best_results[idx_span] = select(best_result, new_result, mask); // Check best error against record N-1 with either cut low or cut high best_result = best_results[idx_span - 1]; new_result = vfloat4(error_cut_low, i_flt, 1.0f, 0.0f); - vmask4 mask2(best_result.lane<0>() > error_cut_low); - best_result = select(best_result, new_result, mask2); + mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_low); + best_result = select(best_result, new_result, mask); new_result = vfloat4(error_cut_high, i_flt, 0.0f, 0.0f); - vmask4 mask3(best_result.lane<0>() > error_cut_high); - best_results[idx_span - 1] = select(best_result, new_result, mask3); + mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_high); + best_results[idx_span - 1] = select(best_result, new_result, mask); // Check best error against record N-2 with both cut low and high best_result = best_results[idx_span - 2]; new_result = vfloat4(error_cut_low_high, i_flt, 1.0f, 0.0f); - vmask4 mask4(best_result.lane<0>() > error_cut_low_high); - best_results[idx_span - 2] = select(best_result, new_result, mask4); + mask = vfloat4(best_result.lane<0>()) > vfloat4(error_cut_low_high); + best_results[idx_span - 2] = select(best_result, new_result, mask); } for (unsigned int i = 0; i <= max_quant_level; i++) { - unsigned int q = quantization_steps_for_level[i]; + unsigned int q = steps_for_quant_level[i]; int bsi = static_cast(best_results[q].lane<1>()); // Did we find anything? @@ -333,181 +324,28 @@ static void compute_angular_endpoints_for_quant_levels( bsi = astc::max(0, bsi); - float stepsize = 1.0f / (1.0f + static_cast(bsi)); - int lwi = lowest_weight[bsi] + static_cast(best_results[q].lane<2>()); - int hwi = lwi + q - 1; - - float offset = angular_offsets[bsi] * stepsize; - low_value[i] = offset + static_cast(lwi) * stepsize; - high_value[i] = offset + static_cast(hwi) * stepsize; - } -} + float lwi = lowest_weight[bsi] + best_results[q].lane<2>(); + float hwi = lwi + static_cast(q) - 1.0f; -/** - * @brief For a given step size compute the lowest and highest weight, variant for low weight count. - * - * Compute the lowest and highest weight that results from quantizing using the given stepsize and - * offset, and then compute the resulting error. The cut errors indicate the error that results from - * forcing samples that should have had one weight value one step up or down. - * - * @param weight_count The number of (decimated) weights. - * @param dec_weight_quant_uvalue The decimated and quantized weight values. - * @param max_angular_steps The maximum number of steps to be tested. - * @param max_quant_steps The maximum quantization level to be tested. - * @param offsets The angular offsets array. - * @param[out] lowest_weight Per angular step, the lowest weight. - * @param[out] weight_span Per angular step, the span between lowest and highest weight. - * @param[out] error Per angular step, the error. - */ -static void compute_lowest_and_highest_weight_lwc( - unsigned int weight_count, - const float* dec_weight_quant_uvalue, - unsigned int max_angular_steps, - unsigned int max_quant_steps, - const float* offsets, - int* lowest_weight, - int* weight_span, - float* error -) { - promise(weight_count > 0); - promise(max_angular_steps > 0); - - vfloat rcp_stepsize = vfloat::lane_id() + vfloat(1.0f); - - // Arrays are ANGULAR_STEPS long, so always safe to run full vectors - for (unsigned int sp = 0; sp < max_angular_steps; sp += ASTCENC_SIMD_WIDTH) - { - vfloat minidx(128.0f); - vfloat maxidx(-128.0f); - vfloat errval = vfloat::zero(); - vfloat offset = loada(&offsets[sp]); - - for (unsigned int j = 0; j < weight_count; ++j) - { - vfloat sval = load1(&dec_weight_quant_uvalue[j]) * rcp_stepsize - offset; - vfloat svalrte = round(sval); - vfloat diff = sval - svalrte; - errval += diff * diff; - - // Reset tracker on min hit - vmask mask = svalrte < minidx; - minidx = select(minidx, svalrte, mask); - - // Reset tracker on max hit - mask = svalrte > maxidx; - maxidx = select(maxidx, svalrte, mask); - } - - // Write out min weight and weight span; clamp span to a usable range - vint span = float_to_int(maxidx - minidx + vfloat(1.0f)); - span = min(span, vint(max_quant_steps + 3)); - span = max(span, vint(2)); - storea(float_to_int(minidx), &lowest_weight[sp]); - storea(span, &weight_span[sp]); - - // The cut_(lowest/highest)_weight_error indicate the error that results from forcing - // samples that should have had the weight value one step (up/down). - vfloat ssize = 1.0f / rcp_stepsize; - vfloat errscale = ssize * ssize; - storea(errval * errscale, &error[sp]); - - rcp_stepsize = rcp_stepsize + vfloat(ASTCENC_SIMD_WIDTH); - } -} - -/** - * @brief The main function for the angular algorithm, variant for low weight count. - * - * @param weight_count The number of (decimated) weights. - * @param dec_weight_ideal_value The ideal decimated unquantized weight values. - * @param max_quant_level The maximum quantization level to be tested. - * @param[out] low_value Per angular step, the lowest weight value. - * @param[out] high_value Per angular step, the highest weight value. - */ -static void compute_angular_endpoints_for_quant_levels_lwc( - unsigned int weight_count, - const float* dec_weight_ideal_value, - unsigned int max_quant_level, - float low_value[12], - float high_value[12] -) { - unsigned int max_quant_steps = quantization_steps_for_level[max_quant_level]; - unsigned int max_angular_steps = max_angular_steps_needed_for_quant_level[max_quant_level]; - - alignas(ASTCENC_VECALIGN) float angular_offsets[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) int32_t lowest_weight[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) int32_t weight_span[ANGULAR_STEPS]; - alignas(ASTCENC_VECALIGN) float error[ANGULAR_STEPS]; - - compute_angular_offsets(weight_count, dec_weight_ideal_value, - max_angular_steps, angular_offsets); - - - compute_lowest_and_highest_weight_lwc(weight_count, dec_weight_ideal_value, - max_angular_steps, max_quant_steps, - angular_offsets, lowest_weight, weight_span, error); - - // For each quantization level, find the best error terms. Use packed vectors so data-dependent - // branches can become selects. This involves some integer to float casts, but the values are - // small enough so they never round the wrong way. - vfloat4 best_results[ANGULAR_STEPS]; - - // Initialize the array to some safe defaults - promise(max_quant_steps > 0); - for (unsigned int i = 0; i < (max_quant_steps + 4); i++) - { - best_results[i] = vfloat4(ERROR_CALC_DEFAULT, -1.0f, 0.0f, 0.0f); - } - - promise(max_angular_steps > 0); - for (unsigned int i = 0; i < max_angular_steps; i++) - { - int idx_span = weight_span[i]; - - // Check best error against record N - vfloat4 current_best = best_results[idx_span]; - vfloat4 candidate = vfloat4(error[i], static_cast(i), 0.0f, 0.0f); - vmask4 mask(current_best.lane<0>() > error[i]); - best_results[idx_span] = select(current_best, candidate, mask); - } - - for (unsigned int i = 0; i <= max_quant_level; i++) - { - unsigned int q = quantization_steps_for_level[i]; - int bsi = static_cast(best_results[q].lane<1>()); - - // Did we find anything? -#if defined(ASTCENC_DIAGNOSTICS) - if ((bsi < 0) && print_once) - { - print_once = false; - printf("INFO: Unable to find low weight encoding within search error limit.\n\n"); - } -#endif - - bsi = astc::max(0, bsi); - - int lwi = lowest_weight[bsi]; - int hwi = lwi + q - 1; - - low_value[i] = (angular_offsets[bsi] + static_cast(lwi)) / (1.0f + static_cast(bsi)); - high_value[i] = (angular_offsets[bsi] + static_cast(hwi)) / (1.0f + static_cast(bsi)); + float stepsize = 1.0f / (1.0f + static_cast(bsi)); + low_value[i] = (angular_offsets[bsi] + lwi) * stepsize; + high_value[i] = (angular_offsets[bsi] + hwi) * stepsize; } } /* See header for documentation. */ void compute_angular_endpoints_1plane( - unsigned int tune_low_weight_limit, bool only_always, const block_size_descriptor& bsd, const float* dec_weight_ideal_value, + unsigned int max_weight_quant, compression_working_buffers& tmpbuf ) { float (&low_value)[WEIGHTS_MAX_BLOCK_MODES] = tmpbuf.weight_low_value1; float (&high_value)[WEIGHTS_MAX_BLOCK_MODES] = tmpbuf.weight_high_value1; - float (&low_values)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_low_values1; - float (&high_values)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_high_values1; + float (&low_values)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_low_values1; + float (&high_values)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_high_values1; unsigned int max_decimation_modes = only_always ? bsd.decimation_mode_count_always : bsd.decimation_mode_count_selected; @@ -515,33 +353,34 @@ void compute_angular_endpoints_1plane( for (unsigned int i = 0; i < max_decimation_modes; i++) { const decimation_mode& dm = bsd.decimation_modes[i]; - if (!dm.ref_1_plane) + if (!dm.is_ref_1plane(static_cast(max_weight_quant))) { continue; } unsigned int weight_count = bsd.get_decimation_info(i).weight_count; - if (weight_count < tune_low_weight_limit) + unsigned int max_precision = dm.maxprec_1plane; + if (max_precision > TUNE_MAX_ANGULAR_QUANT) { - compute_angular_endpoints_for_quant_levels_lwc( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, - dm.maxprec_1plane, low_values[i], high_values[i]); + max_precision = TUNE_MAX_ANGULAR_QUANT; } - else + + if (max_precision > max_weight_quant) { - compute_angular_endpoints_for_quant_levels( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, - dm.maxprec_1plane, low_values[i], high_values[i]); + max_precision = max_weight_quant; } + + compute_angular_endpoints_for_quant_levels( + weight_count, + dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, + max_precision, low_values[i], high_values[i]); } unsigned int max_block_modes = only_always ? bsd.block_mode_count_1plane_always : bsd.block_mode_count_1plane_selected; promise(max_block_modes > 0); - for (unsigned int i = 0; i < max_block_modes; ++i) + for (unsigned int i = 0; i < max_block_modes; i++) { const block_mode& bm = bsd.block_modes[i]; assert(!bm.is_dual_plane); @@ -549,16 +388,24 @@ void compute_angular_endpoints_1plane( unsigned int quant_mode = bm.quant_mode; unsigned int decim_mode = bm.decimation_mode; - low_value[i] = low_values[decim_mode][quant_mode]; - high_value[i] = high_values[decim_mode][quant_mode]; + if (quant_mode <= TUNE_MAX_ANGULAR_QUANT) + { + low_value[i] = low_values[decim_mode][quant_mode]; + high_value[i] = high_values[decim_mode][quant_mode]; + } + else + { + low_value[i] = 0.0f; + high_value[i] = 1.0f; + } } } /* See header for documentation. */ void compute_angular_endpoints_2planes( - unsigned int tune_low_weight_limit, const block_size_descriptor& bsd, const float* dec_weight_ideal_value, + unsigned int max_weight_quant, compression_working_buffers& tmpbuf ) { float (&low_value1)[WEIGHTS_MAX_BLOCK_MODES] = tmpbuf.weight_low_value1; @@ -566,46 +413,42 @@ void compute_angular_endpoints_2planes( float (&low_value2)[WEIGHTS_MAX_BLOCK_MODES] = tmpbuf.weight_low_value2; float (&high_value2)[WEIGHTS_MAX_BLOCK_MODES] = tmpbuf.weight_high_value2; - float (&low_values1)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_low_values1; - float (&high_values1)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_high_values1; - float (&low_values2)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_low_values2; - float (&high_values2)[WEIGHTS_MAX_DECIMATION_MODES][12] = tmpbuf.weight_high_values2; + float (&low_values1)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_low_values1; + float (&high_values1)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_high_values1; + float (&low_values2)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_low_values2; + float (&high_values2)[WEIGHTS_MAX_DECIMATION_MODES][TUNE_MAX_ANGULAR_QUANT + 1] = tmpbuf.weight_high_values2; promise(bsd.decimation_mode_count_selected > 0); for (unsigned int i = 0; i < bsd.decimation_mode_count_selected; i++) { const decimation_mode& dm = bsd.decimation_modes[i]; - if (!dm.ref_2_planes) + if (!dm.is_ref_2plane(static_cast(max_weight_quant))) { continue; } unsigned int weight_count = bsd.get_decimation_info(i).weight_count; - if (weight_count < tune_low_weight_limit) + unsigned int max_precision = dm.maxprec_2planes; + if (max_precision > TUNE_MAX_ANGULAR_QUANT) { - compute_angular_endpoints_for_quant_levels_lwc( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, - dm.maxprec_2planes, low_values1[i], high_values1[i]); - - compute_angular_endpoints_for_quant_levels_lwc( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET, - dm.maxprec_2planes, low_values2[i], high_values2[i]); + max_precision = TUNE_MAX_ANGULAR_QUANT; } - else + + if (max_precision > max_weight_quant) { - compute_angular_endpoints_for_quant_levels( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, - dm.maxprec_2planes, low_values1[i], high_values1[i]); - - compute_angular_endpoints_for_quant_levels( - weight_count, - dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET, - dm.maxprec_2planes, low_values2[i], high_values2[i]); + max_precision = max_weight_quant; } + + compute_angular_endpoints_for_quant_levels( + weight_count, + dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS, + max_precision, low_values1[i], high_values1[i]); + + compute_angular_endpoints_for_quant_levels( + weight_count, + dec_weight_ideal_value + i * BLOCK_MAX_WEIGHTS + WEIGHTS_PLANE2_OFFSET, + max_precision, low_values2[i], high_values2[i]); } unsigned int start = bsd.block_mode_count_1plane_selected; @@ -616,10 +459,20 @@ void compute_angular_endpoints_2planes( unsigned int quant_mode = bm.quant_mode; unsigned int decim_mode = bm.decimation_mode; - low_value1[i] = low_values1[decim_mode][quant_mode]; - high_value1[i] = high_values1[decim_mode][quant_mode]; - low_value2[i] = low_values2[decim_mode][quant_mode]; - high_value2[i] = high_values2[decim_mode][quant_mode]; + if (quant_mode <= TUNE_MAX_ANGULAR_QUANT) + { + low_value1[i] = low_values1[decim_mode][quant_mode]; + high_value1[i] = high_values1[decim_mode][quant_mode]; + low_value2[i] = low_values2[decim_mode][quant_mode]; + high_value2[i] = high_values2[decim_mode][quant_mode]; + } + else + { + low_value1[i] = 0.0f; + high_value1[i] = 1.0f; + low_value2[i] = 0.0f; + high_value2[i] = 1.0f; + } } } diff --git a/Source/astcenc_weight_quant_xfer_tables.cpp b/Source/astcenc_weight_quant_xfer_tables.cpp index 9501f78..8fdf73a 100644 --- a/Source/astcenc_weight_quant_xfer_tables.cpp +++ b/Source/astcenc_weight_quant_xfer_tables.cpp @@ -23,145 +23,125 @@ #define _ 0 // Using _ to indicate an entry that will not be used. -const quantization_and_transfer_table quant_and_xfer_tables[12] { - // Quantization method 0, range 0..1 +const quant_and_transfer_table quant_and_xfer_tables[12] { + // QUANT2, range 0..1 { - QUANT_2, - {0, 64, 255}, + {0, 64}, {0, 1}, {0, 64}, - {0x01004000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, + {0x4000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, - 0x01004000} + 0x4000} }, - // Quantization method 1, range 0..2 + // QUANT_3, range 0..2 { - QUANT_3, - {0, 32, 64, 255}, + {0, 32, 64}, {0, 1, 2}, {0, 32, 64}, - {0x01002000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, - _,_,0x02004000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, - _,_,_,_,0x02014020} + {0x2000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, + _,_,0x4000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_, + _,_,_,_,0x4020} }, - // Quantization method 2, range 0..3 + // QUANT_4, range 0..3 { - QUANT_4, - {0, 21, 43, 64, 255}, + {0, 21, 43, 64}, {0, 1, 2, 3}, {0, 21, 43, 64}, - {0x01001500,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x02002b00,_,_,_,_, - _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x03014015,_,_,_,_,_,_,_,_,_,_,_,_, - _,_,_,_,_,_,_,_,0x0302402b} + {0x1500,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x2b00,_,_,_,_, + _,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x4015,_,_,_,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_,0x402b} }, - // Quantization method 3, range 0..4 + //QUANT_5, range 0..4 { - QUANT_5, - {0, 16, 32, 48, 64, 255}, + {0, 16, 32, 48, 64}, {0, 1, 2, 3, 4}, {0, 16, 32, 48, 64}, - {0x01001000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x02002000,_,_,_,_,_,_,_,_,_, - _,_,_,_,_,_,0x03013010,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x04024020,_,_,_, - _,_,_,_,_,_,_,_,_,_,_,_,0x04034030} + {0x1000,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x2000,_,_,_,_,_,_,_,_,_, + _,_,_,_,_,_,0x3010,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,0x4020,_,_,_, + _,_,_,_,_,_,_,_,_,_,_,_,0x4030} }, - // Quantization method 4, range 0..5 + // QUANT_6, range 0..5 { - QUANT_6, - {0, 12, 25, 39, 52, 64, 255}, + {0, 12, 25, 39, 52, 64}, {0, 2, 4, 5, 3, 1}, {0, 64, 12, 52, 25, 39}, - {0x02000c00,_,_,_,_,_,_,_,_,_,_,_,0x04001900,_,_,_,_,_,_,_,_,_,_,_,_, - 0x0502270c,_,_,_,_,_,_,_,_,_,_,_,_,_,0x03043419,_,_,_,_,_,_,_,_,_,_, - _,_,0x01054027,_,_,_,_,_,_,_,_,_,_,_,0x01034034} + {0x0c00,_,_,_,_,_,_,_,_,_,_,_,0x1900,_,_,_,_,_,_,_,_,_,_,_,_, + 0x270c,_,_,_,_,_,_,_,_,_,_,_,_,_,0x3419,_,_,_,_,_,_,_,_,_,_, + _,_,0x4027,_,_,_,_,_,_,_,_,_,_,_,0x4034} }, - // Quantization method 5, range 0..7 + // QUANT_8, range 0..7 { - QUANT_8, - {0, 9, 18, 27, 37, 46, 55, 64, 255}, + {0, 9, 18, 27, 37, 46, 55, 64}, {0, 1, 2, 3, 4, 5, 6, 7}, {0, 9, 18, 27, 37, 46, 55, 64}, - {0x01000900,_,_,_,_,_,_,_,_,0x02001200,_,_,_,_,_,_,_,_,0x03011b09,_,_, - _,_,_,_,_,_,0x04022512,_,_,_,_,_,_,_,_,_,0x05032e1b,_,_,_,_,_,_,_,_, - 0x06043725,_,_,_,_,_,_,_,_,0x0705402e,_,_,_,_,_,_,_,_,0x07064037} + {0x0900,_,_,_,_,_,_,_,_,0x1200,_,_,_,_,_,_,_,_,0x1b09,_,_, + _,_,_,_,_,_,0x2512,_,_,_,_,_,_,_,_,_,0x2e1b,_,_,_,_,_,_,_,_, + 0x3725,_,_,_,_,_,_,_,_,0x402e,_,_,_,_,_,_,_,_,0x4037} }, - // Quantization method 6, range 0..9 + // QUANT_10, range 0..9 { - QUANT_10, - {0, 7, 14, 21, 28, 36, 43, 50, 57, 64, 255}, + {0, 7, 14, 21, 28, 36, 43, 50, 57, 64}, {0, 2, 4, 6, 8, 9, 7, 5, 3, 1}, {0, 64, 7, 57, 14, 50, 21, 43, 28, 36}, - {0x02000700,_,_,_,_,_,_,0x04000e00,_,_,_,_,_,_,0x06021507,_,_,_,_,_,_, - 0x08041c0e,_,_,_,_,_,_,0x09062415,_,_,_,_,_,_,_,0x07082b1c,_,_,_,_,_, - _,0x05093224,_,_,_,_,_,_,0x0307392b,_,_,_,_,_,_,0x01054032,_,_,_,_,_, - _,0x01034039} + {0x0700,_,_,_,_,_,_,0x0e00,_,_,_,_,_,_,0x1507,_,_,_,_,_,_, + 0x1c0e,_,_,_,_,_,_,0x2415,_,_,_,_,_,_,_,0x2b1c,_,_,_,_,_, + _,0x3224,_,_,_,_,_,_,0x392b,_,_,_,_,_,_,0x4032,_,_,_,_,_, + _,0x4039} }, - // Quantization method 7, range 0..11 + // QUANT_12, range 0..11 { - QUANT_12, - {0, 5, 11, 17, 23, 28, 36, 41, 47, 53, 59, 64, 255}, + {0, 5, 11, 17, 23, 28, 36, 41, 47, 53, 59, 64}, {0, 4, 8, 2, 6, 10, 11, 7, 3, 9, 5, 1}, {0, 64, 17, 47, 5, 59, 23, 41, 11, 53, 28, 36}, - {0x04000500,_,_,_,_,0x08000b00,_,_,_,_,_,0x02041105,_,_,_,_,_, - 0x0608170b,_,_,_,_,_,0x0a021c11,_,_,_,_,0x0b062417,_,_,_,_,_,_,_, - 0x070a291c,_,_,_,_,0x030b2f24,_,_,_,_,_,0x09073529,_,_,_,_,_, - 0x05033b2f,_,_,_,_,_,0x01094035,_,_,_,_,0x0105403b} + {0x0500,_,_,_,_,0x0b00,_,_,_,_,_,0x1105,_,_,_,_,_, + 0x170b,_,_,_,_,_,0x1c11,_,_,_,_,0x2417,_,_,_,_,_,_,_, + 0x291c,_,_,_,_,0x2f24,_,_,_,_,_,0x3529,_,_,_,_,_, + 0x3b2f,_,_,_,_,_,0x4035,_,_,_,_,0x403b} }, - // Quantization method 8, range 0..15 + // QUANT_16, range 0..15 { - QUANT_16, - {0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64, 255}, + {0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64}, - {0x01000400,_,_,_,0x02000800,_,_,_,0x03010c04,_,_,_,0x04021108,_,_,_,_, - 0x0503150c,_,_,_,0x06041911,_,_,_,0x07051d15,_,_,_,0x08062319,_,_,_,_, - _,0x0907271d,_,_,_,0x0a082b23,_,_,_,0x0b092f27,_,_,_,0x0c0a342b,_,_,_, - _,0x0d0b382f,_,_,_,0x0e0c3c34,_,_,_,0x0f0d4038,_,_,_,0x0f0e403c} + {0x0400,_,_,_,0x0800,_,_,_,0x0c04,_,_,_,0x1108,_,_,_,_, + 0x150c,_,_,_,0x1911,_,_,_,0x1d15,_,_,_,0x2319,_,_,_,_, + _,0x271d,_,_,_,0x2b23,_,_,_,0x2f27,_,_,_,0x342b,_,_,_, + _,0x382f,_,_,_,0x3c34,_,_,_,0x4038,_,_,_,0x403c} }, - // Quantization method 9, range 0..19 + // QUANT_20, range 0..19 { - QUANT_20, - {0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 35, 38, 41, 45, 48, 51, 55, 58, - 61, 64, 255}, + {0, 3, 6, 9, 13, 16, 19, 23, 26, 29, 35, 38, 41, 45, 48, 51, 55, 58, 61, 64}, {0, 4, 8, 12, 16, 2, 6, 10, 14, 18, 19, 15, 11, 7, 3, 17, 13, 9, 5, 1}, - {0, 64, 16, 48, 3, 61, 19, 45, 6, 58, 23, 41, 9, 55, 26, 38, 13, 51, - 29, 35}, - {0x04000300,_,_,0x08000600,_,_,0x0c040903,_,_,0x10080d06,_,_,_, - 0x020c1009,_,_,0x0610130d,_,_,0x0a021710,_,_,_,0x0e061a13,_,_, - 0x120a1d17,_,_,0x130e231a,_,_,_,_,_,0x0f12261d,_,_,0x0b132923,_,_, - 0x070f2d26,_,_,_,0x030b3029,_,_,0x1107332d,_,_,0x0d033730,_,_,_, - 0x09113a33,_,_,0x050d3d37,_,_,0x0109403a,_,_,0x0105403d} + {0, 64, 16, 48, 3, 61, 19, 45, 6, 58, 23, 41, 9, 55, 26, 38, 13, 51, 29, 35}, + {0x0300,_,_,0x0600,_,_,0x0903,_,_,0x0d06,_,_,_, + 0x1009,_,_,0x130d,_,_,0x1710,_,_,_,0x1a13,_,_, + 0x1d17,_,_,0x231a,_,_,_,_,_,0x261d,_,_,0x2923,_,_, + 0x2d26,_,_,_,0x3029,_,_,0x332d,_,_,0x3730,_,_,_, + 0x3a33,_,_,0x3d37,_,_,0x403a,_,_,0x403d} }, - // Quantization method 10, range 0..23 + // QUANT_24, range 0..23 { - QUANT_24, - {0, 2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 34, 37, 40, 42, 45, 48, - 51, 53, 56, 59, 62, 64, 255}, - {0, 8, 16, 2, 10, 18, 4, 12, 20, 6, 14, 22, 23, 15, 7, 21, 13, 5, 19, - 11, 3, 17, 9, 1}, - {0, 64, 8, 56, 16, 48, 24, 40, 2, 62, 11, 53, 19, 45, 27, 37, 5, 59, - 13, 51, 22, 42, 30, 34}, - {0x08000200,_,0x10000500,_,_,0x02080802,_,_,0x0a100b05,_,_,0x12020d08, - _,0x040a100b,_,_,0x0c12130d,_,_,0x14041610,_,_,0x060c1813,_, - 0x0e141b16,_,_,0x16061e18,_,_,0x170e221b,_,_,_,0x0f16251e,_,_, - 0x07172822,_,_,0x150f2a25,_,0x0d072d28,_,_,0x0515302a,_,_,0x130d332d, - _,_,0x0b053530,_,0x03133833,_,_,0x110b3b35,_,_,0x09033e38,_,_, - 0x0111403b,_,0x0109403e} + {0, 2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 34, 37, 40, 42, 45, 48, 51, 53, 56, 59, 62, 64}, + {0, 8, 16, 2, 10, 18, 4, 12, 20, 6, 14, 22, 23, 15, 7, 21, 13, 5, 19, 11, 3, 17, 9, 1}, + {0, 64, 8, 56, 16, 48, 24, 40, 2, 62, 11, 53, 19, 45, 27, 37, 5, 59, 13, 51, 22, 42, 30, 34}, + {0x0200,_,0x0500,_,_,0x0802,_,_,0x0b05,_,_,0x0d08, + _,0x100b,_,_,0x130d,_,_,0x1610,_,_,0x1813,_, + 0x1b16,_,_,0x1e18,_,_,0x221b,_,_,_,0x251e,_,_, + 0x2822,_,_,0x2a25,_,0x2d28,_,_,0x302a,_,_,0x332d, + _,_,0x3530,_,0x3833,_,_,0x3b35,_,_,0x3e38,_,_, + 0x403b,_,0x403e} }, - // Quantization method 11, range 0..31 + // QUANT_32, range 0..31 { - QUANT_32, - {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, - 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 255}, - {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, - 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64}, - {0x01000200,_,0x02000400,_,0x03010602,_,0x04020804,_,0x05030a06,_, - 0x06040c08,_,0x07050e0a,_,0x0806100c,_,0x0907120e,_,0x0a081410,_, - 0x0b091612,_,0x0c0a1814,_,0x0d0b1a16,_,0x0e0c1c18,_,0x0f0d1e1a,_, - 0x100e221c,_,_,_,0x110f241e,_,0x12102622,_,0x13112824,_,0x14122a26,_, - 0x15132c28,_,0x16142e2a,_,0x1715302c,_,0x1816322e,_,0x19173430,_, - 0x1a183632,_,0x1b193834,_,0x1c1a3a36,_,0x1d1b3c38,_,0x1e1c3e3a,_, - 0x1f1d403c,_,0x1f1e403e} + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64}, + {0x0200,_,0x0400,_,0x0602,_,0x0804,_,0x0a06,_, + 0x0c08,_,0x0e0a,_,0x100c,_,0x120e,_,0x1410,_, + 0x1612,_,0x1814,_,0x1a16,_,0x1c18,_,0x1e1a,_, + 0x221c,_,_,_,0x241e,_,0x2622,_,0x2824,_,0x2a26,_, + 0x2c28,_,0x2e2a,_,0x302c,_,0x322e,_,0x3430,_, + 0x3632,_,0x3834,_,0x3a36,_,0x3c38,_,0x3e3a,_, + 0x403c,_,0x403e} } }; diff --git a/Source/astcenc_platform_isa_detection.cpp b/Source/astcenccli_entry.cpp similarity index 57% rename from Source/astcenc_platform_isa_detection.cpp rename to Source/astcenccli_entry.cpp index 4158da3..19aed00 100644 --- a/Source/astcenc_platform_isa_detection.cpp +++ b/Source/astcenccli_entry.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2020-2021 Arm Limited +// Copyright 2020-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -18,14 +18,25 @@ /** * @brief Platform-specific function implementations. * - * This module contains functions for querying the host extended ISA support. + * This module contains the CLI entry point which also performs the role of + * validating the host extended ISA support meets the needs of the tools. */ -// Include before the defines below to pick up any auto-setup based on compiler -// built-in config, if not being set explicitly by the build system -#include "astcenc_internal.h" +#include -#if (ASTCENC_SSE > 0) || (ASTCENC_AVX > 0) || \ +/** + * @brief The main entry point. + * + * @param argc The number of arguments. + * @param argv The vector of arguments. + * + * @return 0 on success, non-zero otherwise. + */ +int astcenc_main( + int argc, + char **argv); + +#if (ASTCENC_SSE > 20) || (ASTCENC_AVX > 0) || \ (ASTCENC_POPCNT > 0) || (ASTCENC_F16C > 0) static bool g_init { false }; @@ -47,7 +58,7 @@ static bool g_cpu_has_f16c { false }; ============================================================================ */ #if !defined(__clang__) && defined(_MSC_VER) #define WIN32_LEAN_AND_MEAN -#include +#include #include /** @@ -119,8 +130,13 @@ static void detect_cpu_isa() } #endif -/* See header for documentation. */ -bool cpu_supports_popcnt() +#if ASTCENC_POPCNT > 0 +/** + * @brief Run-time detection if the host CPU supports the POPCNT extension. + * + * @return @c true if supported, @c false if not. + */ +static bool cpu_supports_popcnt() { if (!g_init) { @@ -129,9 +145,15 @@ bool cpu_supports_popcnt() return g_cpu_has_popcnt; } +#endif -/* See header for documentation. */ -bool cpu_supports_f16c() +#if ASTCENC_F16C > 0 +/** + * @brief Run-time detection if the host CPU supports F16C extension. + * + * @return @c true if supported, @c false if not. + */ +static bool cpu_supports_f16c() { if (!g_init) { @@ -140,9 +162,15 @@ bool cpu_supports_f16c() return g_cpu_has_f16c; } +#endif -/* See header for documentation. */ -bool cpu_supports_sse41() +#if ASTCENC_SSE >= 41 +/** + * @brief Run-time detection if the host CPU supports SSE 4.1 extension. + * + * @return @c true if supported, @c false if not. + */ +static bool cpu_supports_sse41() { if (!g_init) { @@ -151,9 +179,15 @@ bool cpu_supports_sse41() return g_cpu_has_sse41; } +#endif -/* See header for documentation. */ -bool cpu_supports_avx2() +#if ASTCENC_AVX >= 2 +/** + * @brief Run-time detection if the host CPU supports AVX 2 extension. + * + * @return @c true if supported, @c false if not. + */ +static bool cpu_supports_avx2() { if (!g_init) { @@ -162,5 +196,81 @@ bool cpu_supports_avx2() return g_cpu_has_avx2; } +#endif + +/** + * @brief Print a string to stderr. + */ +static inline void print_error( + const char* format +) { + fprintf(stderr, "%s", format); +} + +/** + * @brief Validate CPU ISA support meets the requirements of this build of the library. + * + * Each library build is statically compiled for a particular set of CPU ISA features, such as the + * SIMD support or other ISA extensions such as POPCNT. This function checks that the host CPU + * actually supports everything this build needs. + * + * @return Return @c true if validated, @c false otherwise. + */ +static bool validate_cpu_isa() +{ + #if ASTCENC_AVX >= 2 + if (!cpu_supports_avx2()) + { + print_error("ERROR: Host does not support AVX2 ISA extension\n"); + return false; + } + #endif + + #if ASTCENC_F16C >= 1 + if (!cpu_supports_f16c()) + { + print_error("ERROR: Host does not support F16C ISA extension\n"); + return false; + } + #endif + + #if ASTCENC_SSE >= 41 + if (!cpu_supports_sse41()) + { + print_error("ERROR: Host does not support SSE4.1 ISA extension\n"); + return false; + } + #endif + + #if ASTCENC_POPCNT >= 1 + if (!cpu_supports_popcnt()) + { + print_error("ERROR: Host does not support POPCNT ISA extension\n"); + return false; + } + #endif + + return true; +} + +#else + +// Fallback for cases with no dynamic ISA availability +static bool validate_cpu_isa() +{ + return true; +} #endif + +int main( + int argc, + char **argv +) { + if (!validate_cpu_isa()) + { + return 1; + } + + return astcenc_main(argc, argv); +} diff --git a/Source/astcenccli_error_metrics.cpp b/Source/astcenccli_error_metrics.cpp index 2774770..4e01a9e 100644 --- a/Source/astcenccli_error_metrics.cpp +++ b/Source/astcenccli_error_metrics.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2022 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -25,44 +25,39 @@ #include "astcenccli_internal.h" /** - * @brief An accumulator using Kahan compensated floating-point summation. - * - * This method keeps higher precision than direct summation by keeping track of - * the error compensation factor @c comp which can be added into the next - * calculation. This allows single precision floats to be used in places that - * would otherwise need double precision, which is useful when vectorizing. + * @brief An accumulator for errors. */ -class kahan_accum4 +class error_accum4 { public: /** @brief The running sum. */ - vfloat4 sum { vfloat4::zero() }; - - /** @brief The current compensation factor. */ - vfloat4 comp { vfloat4::zero() }; + double sum_r { 0.0 }; + double sum_g { 0.0 }; + double sum_b { 0.0 }; + double sum_a { 0.0 }; }; /** - * @brief The incremental addition operator for Kahan summation. + * @brief Incremental addition operator for error accumulators. * - * @param val The Kahan accumulator to increment + * @param val The accumulator to increment * @param inc The increment to apply * * @return The updated accumulator */ -static kahan_accum4& operator+=( - kahan_accum4 &val, +static error_accum4& operator+=( + error_accum4 &val, vfloat4 inc ) { - vfloat4 y = inc - val.comp; - vfloat4 t = val.sum + y; - val.comp = (t - val.sum) - y; - val.sum = t; + val.sum_r += static_cast(inc.lane<0>()); + val.sum_g += static_cast(inc.lane<1>()); + val.sum_b += static_cast(inc.lane<2>()); + val.sum_a += static_cast(inc.lane<3>()); return val; } /** - * @brief mPSNR tonemapping operator for HDR images. + * @brief mPSNR tone-mapping operator for HDR images. * * @param val The color value to tone map * @param fstop The exposure fstop; should be in range [-125, 125] @@ -124,10 +119,10 @@ void compute_error_metrics( static const int componentmasks[5] { 0x00, 0x07, 0x0C, 0x07, 0x0F }; int componentmask = componentmasks[input_components]; - kahan_accum4 errorsum; - kahan_accum4 alpha_scaled_errorsum; - kahan_accum4 log_errorsum; - kahan_accum4 mpsnr_errorsum; + error_accum4 errorsum; + error_accum4 alpha_scaled_errorsum; + error_accum4 log_errorsum; + error_accum4 mpsnr_errorsum; double mean_angular_errorsum = 0.0; double worst_angular_errorsum = 0.0; @@ -146,7 +141,7 @@ void compute_error_metrics( img2->dim_x, img2->dim_y, img2->dim_z); } - float rgb_peak = 0.0f; + double rgb_peak = 0.0; unsigned int xsize1 = img1->dim_x; unsigned int xsize2 = img2->dim_x; @@ -237,7 +232,10 @@ void compute_error_metrics( color2 = clamp(0, 65504.0f, color2); } - rgb_peak = astc::max(color1.lane<0>(), color1.lane<1>(), color1.lane<2>(), rgb_peak); + rgb_peak = astc::max(static_cast(color1.lane<0>()), + static_cast(color1.lane<1>()), + static_cast(color1.lane<2>()), + rgb_peak); vfloat4 diffcolor = color1 - color2; vfloat4 diffcolor_sq = diffcolor * diffcolor; @@ -291,106 +289,118 @@ void compute_error_metrics( } } - float pixels = static_cast(dim_x * dim_y * dim_z); - float num = 0.0f; - float alpha_num = 0.0f; - float log_num = 0.0f; - float mpsnr_num = 0.0f; - float samples = 0.0f; + double pixels = static_cast(dim_x * dim_y * dim_z); + double samples = 0.0; + + double num = 0.0; + double alpha_num = 0.0; + double log_num = 0.0; + double mpsnr_num = 0.0; if (componentmask & 1) { - num += errorsum.sum.lane<0>(); - alpha_num += alpha_scaled_errorsum.sum.lane<0>(); - log_num += log_errorsum.sum.lane<0>(); - mpsnr_num += mpsnr_errorsum.sum.lane<0>(); + num += errorsum.sum_r; + alpha_num += alpha_scaled_errorsum.sum_r; + log_num += log_errorsum.sum_r; + mpsnr_num += mpsnr_errorsum.sum_r; samples += pixels; } if (componentmask & 2) { - num += errorsum.sum.lane<1>(); - alpha_num += alpha_scaled_errorsum.sum.lane<1>(); - log_num += log_errorsum.sum.lane<1>(); - mpsnr_num += mpsnr_errorsum.sum.lane<1>(); + num += errorsum.sum_g; + alpha_num += alpha_scaled_errorsum.sum_g; + log_num += log_errorsum.sum_g; + mpsnr_num += mpsnr_errorsum.sum_g; samples += pixels; } if (componentmask & 4) { - num += errorsum.sum.lane<2>(); - alpha_num += alpha_scaled_errorsum.sum.lane<2>(); - log_num += log_errorsum.sum.lane<2>(); - mpsnr_num += mpsnr_errorsum.sum.lane<2>(); + num += errorsum.sum_b; + alpha_num += alpha_scaled_errorsum.sum_b; + log_num += log_errorsum.sum_b; + mpsnr_num += mpsnr_errorsum.sum_b; samples += pixels; } if (componentmask & 8) { - num += errorsum.sum.lane<3>(); - alpha_num += alpha_scaled_errorsum.sum.lane<3>(); + num += errorsum.sum_a; + alpha_num += alpha_scaled_errorsum.sum_a; samples += pixels; } - float denom = samples; - float stopcount = static_cast(fstop_hi - fstop_lo + 1); - float mpsnr_denom = pixels * 3.0f * stopcount * 255.0f * 255.0f; + double denom = samples; + double stopcount = static_cast(fstop_hi - fstop_lo + 1); + double mpsnr_denom = pixels * 3.0 * stopcount * 255.0 * 255.0; - float psnr; - if (num == 0.0f) - psnr = 999.0f; + double psnr; + if (num == 0.0) + { + psnr = 999.0; + } else - psnr = 10.0f * log10f(denom / num); + { + psnr = 10.0 * log10(denom / num); + } - float rgb_psnr = psnr; + double rgb_psnr = psnr; printf("Quality metrics\n"); printf("===============\n\n"); if (componentmask & 8) { - printf(" PSNR (LDR-RGBA): %9.4f dB\n", static_cast(psnr)); + printf(" PSNR (LDR-RGBA): %9.4f dB\n", psnr); - float alpha_psnr; - if (alpha_num == 0.0f) - alpha_psnr = 999.0f; + double alpha_psnr; + if (alpha_num == 0.0) + { + alpha_psnr = 999.0; + } else - alpha_psnr = 10.0f * log10f(denom / alpha_num); - printf(" Alpha-weighted PSNR: %9.4f dB\n", static_cast(alpha_psnr)); + { + alpha_psnr = 10.0 * log10(denom / alpha_num); + } + printf(" Alpha-weighted PSNR: %9.4f dB\n", alpha_psnr); - float rgb_num = hadd_rgb_s(errorsum.sum); - if (rgb_num == 0.0f) - rgb_psnr = 999.0f; + double rgb_num = errorsum.sum_r + errorsum.sum_g + errorsum.sum_b; + if (rgb_num == 0.0) + { + rgb_psnr = 999.0; + } else - rgb_psnr = 10.0f * log10f(pixels * 3.0f / rgb_num); - printf(" PSNR (LDR-RGB): %9.4f dB\n", static_cast(rgb_psnr)); + { + rgb_psnr = 10.0 * log10(pixels * 3.0 / rgb_num); + } + printf(" PSNR (LDR-RGB): %9.4f dB\n", rgb_psnr); } else { - printf(" PSNR (LDR-RGB): %9.4f dB\n", static_cast(psnr)); + printf(" PSNR (LDR-RGB): %9.4f dB\n", psnr); } if (compute_hdr_metrics) { printf(" PSNR (RGB norm to peak): %9.4f dB (peak %f)\n", - static_cast(rgb_psnr + 20.0f * log10f(rgb_peak)), - static_cast(rgb_peak)); + rgb_psnr + 20.0 * log10(rgb_peak), rgb_peak); - float mpsnr; - if (mpsnr_num == 0.0f) + double mpsnr; + if (mpsnr_num == 0.0) { - mpsnr = 999.0f; + mpsnr = 999.0; } else { - mpsnr = 10.0f * log10f(mpsnr_denom / mpsnr_num); + mpsnr = 10.0 * log10(mpsnr_denom / mpsnr_num); } printf(" mPSNR (RGB): %9.4f dB (fstops %+d to %+d)\n", - static_cast(mpsnr), fstop_lo, fstop_hi); + mpsnr, fstop_lo, fstop_hi); - float logrmse = astc::sqrt(log_num / pixels); - printf(" LogRMSE (RGB): %9.4f\n", static_cast(logrmse)); + double logrmse = sqrt(log_num / pixels); + printf(" LogRMSE (RGB): %9.4f\n", logrmse); } if (compute_normal_metrics) diff --git a/Source/astcenccli_image.cpp b/Source/astcenccli_image.cpp index 7f76654..4b1bb63 100644 --- a/Source/astcenccli_image.cpp +++ b/Source/astcenccli_image.cpp @@ -36,12 +36,12 @@ astcenc_image *alloc_image( img->dim_y = dim_y; img->dim_z = dim_z; + void** data = new void*[dim_z]; + img->data = data; + if (bitness == 8) { - void** data = new void*[dim_z]; img->data_type = ASTCENC_TYPE_U8; - img->data = data; - for (unsigned int z = 0; z < dim_z; z++) { data[z] = new uint8_t[dim_x * dim_y * 4]; @@ -49,10 +49,7 @@ astcenc_image *alloc_image( } else if (bitness == 16) { - void** data = new void*[dim_z]; img->data_type = ASTCENC_TYPE_F16; - img->data = data; - for (unsigned int z = 0; z < dim_z; z++) { data[z] = new uint16_t[dim_x * dim_y * 4]; @@ -61,10 +58,7 @@ astcenc_image *alloc_image( else // if (bitness == 32) { assert(bitness == 32); - void** data = new void*[dim_z]; img->data_type = ASTCENC_TYPE_F32; - img->data = data; - for (unsigned int z = 0; z < dim_z; z++) { data[z] = new float[dim_x * dim_y * 4]; @@ -239,15 +233,18 @@ astcenc_image* astc_img_from_unorm8x4_array( /* See header for documentation. */ float* floatx4_array_from_astc_img( const astcenc_image* img, - bool y_flip + bool y_flip, + unsigned int z_index ) { unsigned int dim_x = img->dim_x; unsigned int dim_y = img->dim_y; float *buf = new float[4 * dim_x * dim_y]; + assert(z_index < img->dim_z); + if (img->data_type == ASTCENC_TYPE_U8) { - uint8_t* data8 = static_cast(img->data[0]); + uint8_t* data8 = static_cast(img->data[z_index]); for (unsigned int y = 0; y < dim_y; y++) { unsigned int ymod = y_flip ? dim_y - y - 1 : y; @@ -264,7 +261,7 @@ float* floatx4_array_from_astc_img( } else if (img->data_type == ASTCENC_TYPE_F16) { - uint16_t* data16 = static_cast(img->data[0]); + uint16_t* data16 = static_cast(img->data[z_index]); for (unsigned int y = 0; y < dim_y; y++) { unsigned int ymod = y_flip ? dim_y - y - 1 : y; @@ -287,7 +284,7 @@ float* floatx4_array_from_astc_img( else // if (img->data_type == ASTCENC_TYPE_F32) { assert(img->data_type == ASTCENC_TYPE_F32); - float* data32 = static_cast(img->data[0]); + float* data32 = static_cast(img->data[z_index]); for (unsigned int y = 0; y < dim_y; y++) { unsigned int ymod = y_flip ? dim_y - y - 1 : y; diff --git a/Source/astcenccli_image_external.cpp b/Source/astcenccli_image_external.cpp index bd74496..0c81b8f 100644 --- a/Source/astcenccli_image_external.cpp +++ b/Source/astcenccli_image_external.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -26,7 +26,7 @@ #include "astcenccli_internal.h" -// Configure the STB image imagewrite library build. +// Configure the STB image write library build. #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #define STBI_NO_GIF @@ -61,7 +61,7 @@ static void astcenc_runtime_assert(bool condition) { if (!condition) { - printf("ERROR: Corrupt input image\n"); + print_error("ERROR: Corrupt input image\n"); exit(1); } } @@ -92,7 +92,7 @@ astcenc_image* load_png_with_wuffs( std::ifstream file(filename, std::ios::binary | std::ios::ate); if (!file) { - printf("ERROR: Failed to load image %s (can't fopen)\n", filename); + print_error("ERROR: Failed to load image %s (can't fopen)\n", filename); return nullptr; } diff --git a/Source/astcenccli_image_load_store.cpp b/Source/astcenccli_image_load_store.cpp index 6878a0d..4076466 100644 --- a/Source/astcenccli_image_load_store.cpp +++ b/Source/astcenccli_image_load_store.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "astcenccli_internal.h" @@ -32,8 +34,39 @@ #include "stb_image_write.h" #include "tinyexr.h" +/** + * @brief Determine the output file name to use for a sliced image write. + * + * @param img The source data for the image. + * @param filename The base name of the file to save. + * @param index The slice index to write. + * + * @return The file name to use when saving the file. + */ +static std::string get_output_filename( + const astcenc_image* img, + const char* filename, + unsigned int index +) { + if (img->dim_z <= 1) + { + return filename; + } + + std::string fnmod(filename); + std::string fnext = fnmod.substr(fnmod.find_last_of(".")); + + // Remove the extension + fnmod = fnmod.erase(fnmod.length() - fnext.size()); + + // Insert the file index into the base name, then append the extension + std::stringstream ss; + ss << fnmod << "_" << std::setw(3) << std::setfill('0') << index << fnext; + return ss.str(); +} + /* ============================================================================ - Image load and store through the stb_iamge and tinyexr libraries + Image load and store through the stb_image and tinyexr libraries ============================================================================ */ /** @@ -59,7 +92,7 @@ static astcenc_image* load_image_with_tinyexr( int load_res = LoadEXR(&image, &dim_x, &dim_y, filename, &err); if (load_res != TINYEXR_SUCCESS) { - printf("ERROR: Failed to load image %s (%s)\n", filename, err); + print_error("ERROR: Failed to load image %s (%s)\n", filename, err); free(reinterpret_cast(const_cast(err))); return nullptr; } @@ -115,7 +148,7 @@ static astcenc_image* load_image_with_stb( } } - printf("ERROR: Failed to load image %s (%s)\n", filename, stbi_failure_reason()); + print_error("ERROR: Failed to load image %s (%s)\n", filename, stbi_failure_reason()); return nullptr; } @@ -133,9 +166,21 @@ static bool store_exr_image_with_tinyexr( const char* filename, int y_flip ) { - float *buf = floatx4_array_from_astc_img(img, y_flip); - int res = SaveEXR(buf, img->dim_x, img->dim_y, 4, 1, filename, nullptr); - delete[] buf; + int res { 0 }; + + for (unsigned int i = 0; i < img->dim_z; i++) + { + std::string fnmod = get_output_filename(img, filename, i); + float* buf = floatx4_array_from_astc_img(img, y_flip, i); + + res = SaveEXR(buf, img->dim_x, img->dim_y, 4, 1, fnmod.c_str(), nullptr); + delete[] buf; + if (res < 0) + { + break; + } + } + return res >= 0; } @@ -153,11 +198,23 @@ static bool store_png_image_with_stb( const char* filename, int y_flip ) { + int res { 0 }; + assert(img->data_type == ASTCENC_TYPE_U8); - uint8_t* buf = reinterpret_cast(img->data[0]); - stbi_flip_vertically_on_write(y_flip); - int res = stbi_write_png(filename, img->dim_x, img->dim_y, 4, buf, img->dim_x * 4); + for (unsigned int i = 0; i < img->dim_z; i++) + { + std::string fnmod = get_output_filename(img, filename, i); + uint8_t* buf = reinterpret_cast(img->data[i]); + + stbi_flip_vertically_on_write(y_flip); + res = stbi_write_png(fnmod.c_str(), img->dim_x, img->dim_y, 4, buf, img->dim_x * 4); + if (res == 0) + { + break; + } + } + return res != 0; } @@ -175,11 +232,23 @@ static bool store_tga_image_with_stb( const char* filename, int y_flip ) { + int res { 0 }; + assert(img->data_type == ASTCENC_TYPE_U8); - uint8_t* buf = reinterpret_cast(img->data[0]); - stbi_flip_vertically_on_write(y_flip); - int res = stbi_write_tga(filename, img->dim_x, img->dim_y, 4, buf); + for (unsigned int i = 0; i < img->dim_z; i++) + { + std::string fnmod = get_output_filename(img, filename, i); + uint8_t* buf = reinterpret_cast(img->data[i]); + + stbi_flip_vertically_on_write(y_flip); + res = stbi_write_tga(fnmod.c_str(), img->dim_x, img->dim_y, 4, buf); + if (res == 0) + { + break; + } + } + return res != 0; } @@ -197,11 +266,23 @@ static bool store_bmp_image_with_stb( const char* filename, int y_flip ) { + int res { 0 }; + assert(img->data_type == ASTCENC_TYPE_U8); - uint8_t* buf = reinterpret_cast(img->data[0]); - stbi_flip_vertically_on_write(y_flip); - int res = stbi_write_bmp(filename, img->dim_x, img->dim_y, 4, buf); + for (unsigned int i = 0; i < img->dim_z; i++) + { + std::string fnmod = get_output_filename(img, filename, i); + uint8_t* buf = reinterpret_cast(img->data[i]); + + stbi_flip_vertically_on_write(y_flip); + res = stbi_write_bmp(fnmod.c_str(), img->dim_x, img->dim_y, 4, buf); + if (res == 0) + { + break; + } + } + return res != 0; } @@ -219,9 +300,21 @@ static bool store_hdr_image_with_stb( const char* filename, int y_flip ) { - float* buf = floatx4_array_from_astc_img(img, y_flip); - int res = stbi_write_hdr(filename, img->dim_x, img->dim_y, 4, buf); - delete[] buf; + int res { 0 }; + + for (unsigned int i = 0; i < img->dim_z; i++) + { + std::string fnmod = get_output_filename(img, filename, i); + float* buf = floatx4_array_from_astc_img(img, y_flip, i); + + res = stbi_write_hdr(fnmod.c_str(), img->dim_x, img->dim_y, 4, buf); + delete[] buf; + if (res == 0) + { + break; + } + } + return res != 0; } @@ -625,6 +718,16 @@ static uint32_t u32_byterev(uint32_t v) #define GL_LUMINANCE 0x1909 #define GL_LUMINANCE_ALPHA 0x190A +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 + +#define GL_R16F 0x822D +#define GL_RG16F 0x822F +#define GL_RGB16F 0x881B +#define GL_RGBA16F 0x881A + #define GL_UNSIGNED_BYTE 0x1401 #define GL_UNSIGNED_SHORT 0x1403 #define GL_HALF_FLOAT 0x140B @@ -768,7 +871,7 @@ static unsigned int get_format( ) { for (auto& it : ASTC_FORMATS) { - if ((it.x == x) && (it.y == y) && (it.z == z) && (it.is_srgb == is_srgb)) + if ((it.x == x) && (it.y == y) && (it.z == z) && (it.is_srgb == is_srgb)) { return it.format; } @@ -794,7 +897,7 @@ struct ktx_header uint32_t bytes_of_key_value_data; // size in bytes of the key-and-value area immediately following the header. }; -// magic 12-byte sequence that must appear at the beginning of every KTX file. +// Magic 12-byte sequence that must appear at the beginning of every KTX file. static uint8_t ktx_magic[12] { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; @@ -909,9 +1012,9 @@ static astcenc_image* load_ktx_uncompressed_image( return nullptr; } - // Although these are set up later, we include a default initializer to remove warnings - int bytes_per_component = 1; // bytes per component in the KTX file. - int bitness = 8; // internal precision we will use in the codec. + // Although these are set up later, use default initializer to remove warnings + int bitness = 8; // Internal precision after conversion + int bytes_per_component = 1; // Bytes per component in the KTX file scanline_transfer copy_method = R8_TO_RGBA8; switch (hdr.gl_type) @@ -1017,7 +1120,7 @@ static astcenc_image* load_ktx_uncompressed_image( } case GL_FLOAT: { - bitness = 32; + bitness = 16; bytes_per_component = 4; switch (hdr.gl_format) { @@ -1126,7 +1229,7 @@ static astcenc_image* load_ktx_uncompressed_image( } } - // then transfer data from the surface to our own image-data-structure. + // Transfer data from the surface to our own image data structure astcenc_image *astc_img = alloc_image(bitness, dim_x, dim_y, dim_z); for (unsigned int z = 0; z < dim_z; z++) @@ -1155,7 +1258,7 @@ static astcenc_image* load_ktx_uncompressed_image( } delete[] buf; - is_hdr = bitness == 32; + is_hdr = bitness >= 16; component_count = components; return astc_img; } @@ -1352,7 +1455,15 @@ static bool store_ktx_uncompressed_image( ktx_header hdr; static const int gl_format_of_components[4] { - GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA + GL_RED, GL_RG, GL_RGB, GL_RGBA + }; + + static const int gl_sized_format_of_components_ldr[4] { + GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 + }; + + static const int gl_sized_format_of_components_hdr[4] { + GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F }; memcpy(hdr.magic, ktx_magic, 12); @@ -1360,8 +1471,15 @@ static bool store_ktx_uncompressed_image( hdr.gl_type = (bitness == 16) ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE; hdr.gl_type_size = bitness / 8; hdr.gl_format = gl_format_of_components[image_components - 1]; - hdr.gl_internal_format = gl_format_of_components[image_components - 1]; - hdr.gl_base_internal_format = gl_format_of_components[image_components - 1]; + if (bitness == 16) + { + hdr.gl_internal_format = gl_sized_format_of_components_hdr[image_components - 1]; + } + else + { + hdr.gl_internal_format = gl_sized_format_of_components_ldr[image_components - 1]; + } + hdr.gl_base_internal_format = hdr.gl_format; hdr.pixel_width = dim_x; hdr.pixel_height = dim_y; hdr.pixel_depth = (dim_z == 1) ? 0 : dim_z; @@ -1915,7 +2033,7 @@ static astcenc_image* load_dds_uncompressed_image( } delete[] buf; - is_hdr = bitness == 16; + is_hdr = bitness >= 16; component_count = components; return astc_img; } @@ -2295,7 +2413,7 @@ bool store_ncimage( eptr = ".ktx"; // use KTX file format if we don't have an ending. } - for (int i=0; i < storer_descr_count; i++) + for (int i = 0; i < storer_descr_count; i++) { if (strcmp(eptr, storer_descs[i].ending1) == 0 || strcmp(eptr, storer_descs[i].ending2) == 0) @@ -2338,7 +2456,6 @@ static unsigned int unpack_bytes( } /* See header for documentation. */ -// TODO: Return a bool? int load_cimage( const char* filename, astc_compressed_image& img @@ -2346,22 +2463,22 @@ int load_cimage( std::ifstream file(filename, std::ios::in | std::ios::binary); if (!file) { - printf("ERROR: File open failed '%s'\n", filename); + print_error("ERROR: File open failed '%s'\n", filename); return 1; } astc_header hdr; file.read(reinterpret_cast(&hdr), sizeof(astc_header)); - if (!file) + if (file.fail()) { - printf("ERROR: File read failed '%s'\n", filename); + print_error("ERROR: File read failed '%s'\n", filename); return 1; } unsigned int magicval = unpack_bytes(hdr.magic[0], hdr.magic[1], hdr.magic[2], hdr.magic[3]); if (magicval != ASTC_MAGIC_ID) { - printf("ERROR: File not recognized '%s'\n", filename); + print_error("ERROR: File not recognized '%s'\n", filename); return 1; } @@ -2376,7 +2493,7 @@ int load_cimage( if (dim_x == 0 || dim_y == 0 || dim_z == 0) { - printf("ERROR: File corrupt '%s'\n", filename); + print_error("ERROR: Image header corrupt '%s'\n", filename); return 1; } @@ -2388,9 +2505,10 @@ int load_cimage( uint8_t *buffer = new uint8_t[data_size]; file.read(reinterpret_cast(buffer), data_size); - if (!file) + if (file.fail()) { - printf("ERROR: File read failed '%s'\n", filename); + print_error("ERROR: Image data size exceeded file size '%s'\n", filename); + delete[] buffer; return 1; } @@ -2406,7 +2524,6 @@ int load_cimage( } /* See header for documentation. */ -// TODO: Return a bool? int store_cimage( const astc_compressed_image& img, const char* filename @@ -2436,7 +2553,7 @@ int store_cimage( std::ofstream file(filename, std::ios::out | std::ios::binary); if (!file) { - printf("ERROR: File open failed '%s'\n", filename); + print_error("ERROR: File open failed '%s'\n", filename); return 1; } diff --git a/Source/astcenccli_internal.h b/Source/astcenccli_internal.h index 26a41a0..ee3a44e 100644 --- a/Source/astcenccli_internal.h +++ b/Source/astcenccli_internal.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -68,6 +68,9 @@ struct cli_config_options /** @brief The number of threads to use for processing. */ unsigned int thread_count; + /** @brief The number of repeats to execute for benchmarking. */ + unsigned int repeat_count; + /** @brief The number of image slices to load for a 3D image. */ unsigned int array_size; @@ -77,6 +80,9 @@ struct cli_config_options /** @brief @c true if the images should be y-flipped. */ bool y_flip; + /** @brief @c true if diagnostic images should be stored. */ + bool diagnostic_images; + /** @brief The low exposure fstop for error computation. */ int low_fstop; @@ -90,6 +96,26 @@ struct cli_config_options astcenc_swizzle swz_decode; }; +/** + * @brief Print a string to stderr. + */ +static inline void print_error( + const char* format +) { + fprintf(stderr, "%s", format); +} + +/** + * @brief Print a formatted string to stderr. + */ +template +static inline void print_error( + const char* format, + _Args...args +) { + fprintf(stderr, format, args...); +} + /** * @brief Load uncompressed image. * @@ -271,18 +297,20 @@ astcenc_image* astc_img_from_unorm8x4_array( bool y_flip); /** - * @brief Create a flattened RGBA FLOAT32 data array from an image structure. + * @brief Create a flattened RGBA FLOAT32 data array for a single slice from an image structure. * * The returned data array is allocated with @c new[] and must be freed with a @c delete[] call. * - * @param img The input image. - * @param y_flip Should the data in the array be Y flipped? + * @param img The input image. + * @param y_flip Should the data in the array be Y flipped? + * @param z_index The slice index to convert. * * @return The data array. */ float* floatx4_array_from_astc_img( const astcenc_image* img, - bool y_flip); + bool y_flip, + unsigned int z_index); /** * @brief Create a flattened RGBA UNORM8 data array from an image structure. @@ -357,14 +385,28 @@ int get_cpu_count(); * All threads run the same thread function, and have the same thread payload, but are given a * unique thread ID (0 .. N-1) as a parameter to the run function to allow thread-specific behavior. * -|* @param thread_count The number of threads to spawn. - * @param func The function to execute. Must have the signature: - * void (int thread_count, int thread_id, void* payload) - * @param payload Pointer to an opaque thread payload object. + * @param operation The name of the operation for this async task. + * @param thread_count The number of threads to spawn. + * @param func The function to execute. Must have the signature: + * void (int thread_count, int thread_id, void* payload) + * @param payload Pointer to an opaque thread payload object. */ void launch_threads( + const char* operation, int thread_count, void (*func)(int, int, void*), void *payload); +/** + * @brief The main entry point. + * + * @param argc The number of arguments. + * @param argv The vector of arguments. + * + * @return 0 on success, non-zero otherwise. + */ +int astcenc_main( + int argc, + char **argv); + #endif diff --git a/Source/astcenccli_platform_dependents.cpp b/Source/astcenccli_platform_dependents.cpp index fcca5aa..d5857f1 100644 --- a/Source/astcenccli_platform_dependents.cpp +++ b/Source/astcenccli_platform_dependents.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2021 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -38,7 +38,7 @@ #if defined(_WIN32) && !defined(__CYGWIN__) #define WIN32_LEAN_AND_MEAN -#include +#include /** @brief Alias pthread_t to one of the internal Windows types. */ typedef HANDLE pthread_t; @@ -58,9 +58,61 @@ static int pthread_create( static_cast(attribs); LPTHREAD_START_ROUTINE func = reinterpret_cast(threadfunc); *thread = CreateThread(nullptr, 0, func, thread_arg, 0, nullptr); + + // Ensure we return 0 on success, non-zero on error + if (*thread == NULL) + { + return 1; + } + return 0; } +/** + * @brief Manually set CPU group and thread affinity. + * + * This is needed on Windows 10 or older to allow benefit from large core count + * systems with more than 64 logical CPUs. The assignment is skipped on systems + * with a single processor group, as it is not necessary. + */ +static void set_group_affinity( + pthread_t thread, + int thread_index +) { + // Skip thread assignment for hardware with a single CPU group + int group_count = GetActiveProcessorGroupCount(); + if (group_count == 1) + { + return; + } + + // Ensure we have a valid assign if user creates more threads than cores + int assign_index = thread_index % get_cpu_count(); + int assign_group { 0 }; + int assign_group_cpu_count { 0 }; + + // Determine which core group and core in the group to use for this thread + int group_cpu_count_sum { 0 }; + for (int group = 0; group < group_count; group++) + { + int group_cpu_count = static_cast(GetMaximumProcessorCount(group)); + group_cpu_count_sum += group_cpu_count; + + if (assign_index < group_cpu_count_sum) + { + assign_group = group; + assign_group_cpu_count = group_cpu_count; + break; + } + } + + // Set the affinity to the assigned group, and all supported cores + GROUP_AFFINITY affinity {}; + affinity.Mask = (1 << assign_group_cpu_count) - 1; + affinity.Group = assign_group; + SetThreadGroupAffinity(thread, &affinity, nullptr); +} + /** * @brief Proxy Windows @c WaitForSingleObject underneath a pthreads-like wrapper. */ @@ -76,9 +128,8 @@ static int pthread_join( /* See header for documentation */ int get_cpu_count() { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; + DWORD cpu_count = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + return static_cast(cpu_count); } /* See header for documentation */ @@ -151,6 +202,7 @@ static void* launch_threads_helper( /* See header for documentation */ void launch_threads( + const char* operation, int thread_count, void (*func)(int, int, void*), void *payload @@ -163,22 +215,58 @@ void launch_threads( } // Otherwise spawn worker threads - launch_desc *thread_descs = new launch_desc[thread_count]; + launch_desc *thread_descs = new launch_desc[thread_count]; + int actual_thread_count { 0 }; + for (int i = 0; i < thread_count; i++) { - thread_descs[i].thread_count = thread_count; - thread_descs[i].thread_id = i; - thread_descs[i].payload = payload; - thread_descs[i].func = func; + thread_descs[actual_thread_count].thread_count = thread_count; + thread_descs[actual_thread_count].thread_id = actual_thread_count; + thread_descs[actual_thread_count].payload = payload; + thread_descs[actual_thread_count].func = func; + + // Handle pthread_create failing by simply using fewer threads + int error = pthread_create( + &(thread_descs[actual_thread_count].thread_handle), + nullptr, + launch_threads_helper, + reinterpret_cast(thread_descs + actual_thread_count)); + + // Track how many threads we actually created + if (!error) + { + // Windows needs explicit thread assignment to handle large core count systems + #if defined(_WIN32) && !defined(__CYGWIN__) + set_group_affinity( + thread_descs[actual_thread_count].thread_handle, + actual_thread_count); + #endif - pthread_create(&(thread_descs[i].thread_handle), nullptr, - launch_threads_helper, reinterpret_cast(thread_descs + i)); + actual_thread_count++; + } } - // ... and then wait for them to complete - for (int i = 0; i < thread_count; i++) + // If we did not create thread_count threads then emit a warning + if (actual_thread_count != thread_count) + { + int log_count = actual_thread_count == 0 ? 1 : actual_thread_count; + const char* log_s = log_count == 1 ? "" : "s"; + printf("WARNING: %s using %d thread%s due to thread creation error\n\n", + operation, log_count, log_s); + } + + // If we managed to spawn any threads wait for them to complete + if (actual_thread_count != 0) { - pthread_join(thread_descs[i].thread_handle, nullptr); + for (int i = 0; i < actual_thread_count; i++) + { + pthread_join(thread_descs[i].thread_handle, nullptr); + } + } + // Else fall back to using this thread + else + { + func(1, 0, payload); } delete[] thread_descs; diff --git a/Source/astcenccli_toplevel.cpp b/Source/astcenccli_toplevel.cpp index ef01208..d8360ea 100644 --- a/Source/astcenccli_toplevel.cpp +++ b/Source/astcenccli_toplevel.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2024 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -22,11 +22,19 @@ #include "astcenc.h" #include "astcenccli_internal.h" +#if defined(_WIN32) + #include + #define isatty _isatty +#else + #include +#endif #include #include +#include #include #include #include +#include /* ============================================================================ Data structure definitions @@ -158,6 +166,35 @@ struct decompression_workload astcenc_error error; }; +/** + * @brief Callback emitting a progress bar + */ +extern "C" void progress_emitter( + float value +) { + const unsigned int bar_size = 25; + unsigned int parts = static_cast(value / 4.0f); + + char buffer[bar_size + 3]; + buffer[0] = '['; + + for (unsigned int i = 0; i < parts; i++) + { + buffer[i + 1] = '='; + } + + for (unsigned int i = parts; i < bar_size; i++) + { + buffer[i + 1] = ' '; + } + + buffer[bar_size + 1] = ']'; + buffer[bar_size + 2] = '\0'; + + printf(" Progress: %s %03.1f%%\r", buffer, static_cast(value)); + fflush(stdout); +} + /** * @brief Test if a string argument is a well formed float. */ @@ -312,7 +349,7 @@ static astcenc_image* load_uncomp_file( std::string slice_name = get_slice_filename(filename, image_index, error); if (error) { - printf("ERROR: Image pattern does not contain file extension: %s\n", filename); + print_error("ERROR: Image pattern does not contain file extension: %s\n", filename); break; } @@ -328,7 +365,7 @@ static astcenc_image* load_uncomp_file( // Check it is not a 3D image if (slice->dim_z != 1) { - printf("ERROR: Image arrays do not support 3D sources: %s\n", slice_name.c_str()); + print_error("ERROR: Image arrays do not support 3D sources: %s\n", slice_name.c_str()); break; } @@ -337,7 +374,7 @@ static astcenc_image* load_uncomp_file( { if ((is_hdr != slice_is_hdr) || (component_count != slice_component_count)) { - printf("ERROR: Image array[0] and [%d] are different formats\n", image_index); + print_error("ERROR: Image array[0] and [%d] are different formats\n", image_index); break; } @@ -345,7 +382,7 @@ static astcenc_image* load_uncomp_file( (slices[0]->dim_y != slice->dim_y) || (slices[0]->dim_z != slice->dim_z)) { - printf("ERROR: Image array[0] and [%d] are different dimensions\n", image_index); + print_error("ERROR: Image array[0] and [%d] are different dimensions\n", image_index); break; } } @@ -437,7 +474,7 @@ static int parse_commandline_options( if (operation == ASTCENC_OP_UNKNOWN) { - printf("ERROR: Unrecognized operation '%s'\n", argv[1]); + print_error("ERROR: Unrecognized operation '%s'\n", argv[1]); return 1; } @@ -488,7 +525,7 @@ static int init_astcenc_config( // Read and decode block size if (argc < 5) { - printf("ERROR: Block size must be specified\n"); + print_error("ERROR: Block size must be specified\n"); return 1; } @@ -498,14 +535,14 @@ static int init_astcenc_config( // Character after the last match should be a NUL if (!(((dimensions == 2) && !argv[4][cnt2D]) || ((dimensions == 3) && !argv[4][cnt3D]))) { - printf("ERROR: Block size '%s' is invalid\n", argv[4]); + print_error("ERROR: Block size '%s' is invalid\n", argv[4]); return 1; } // Read and decode search quality if (argc < 6) { - printf("ERROR: Search quality level must be specified\n"); + print_error("ERROR: Search quality level must be specified\n"); return 1; } @@ -525,6 +562,10 @@ static int init_astcenc_config( { quality = ASTCENC_PRE_THOROUGH; } + else if (!strcmp(argv[5], "-verythorough")) + { + quality = ASTCENC_PRE_VERYTHOROUGH; + } else if (!strcmp(argv[5], "-exhaustive")) { quality = ASTCENC_PRE_EXHAUSTIVE; @@ -535,7 +576,7 @@ static int init_astcenc_config( } else { - printf("ERROR: Search quality/preset '%s' is invalid\n", argv[5]); + print_error("ERROR: Search quality/preset '%s' is invalid\n", argv[5]); return 1; } @@ -553,14 +594,14 @@ static int init_astcenc_config( argidx++; flags |= ASTCENC_FLG_USE_ALPHA_WEIGHT; } - else if (!strcmp(argv[argidx], "-mask")) - { - flags |= ASTCENC_FLG_MAP_MASK; - } else if (!strcmp(argv[argidx], "-normal")) { flags |= ASTCENC_FLG_MAP_NORMAL; } + else if (!strcmp(argv[argidx], "-decode_unorm8")) + { + flags |= ASTCENC_FLG_USE_DECODE_UNORM8; + } else if (!strcmp(argv[argidx], "-rgbm")) { // Skip over the data value for now @@ -575,7 +616,7 @@ static int init_astcenc_config( { if (preprocess != ASTCENC_PP_NONE) { - printf("ERROR: Only a single image preprocess can be used\n"); + print_error("ERROR: Only a single image preprocess can be used\n"); return 1; } preprocess = ASTCENC_PP_NORMALIZE; @@ -584,7 +625,7 @@ static int init_astcenc_config( { if (preprocess != ASTCENC_PP_NONE) { - printf("ERROR: Only a single image preprocess can be used\n"); + print_error("ERROR: Only a single image preprocess can be used\n"); return 1; } preprocess = ASTCENC_PP_PREMULTIPLY; @@ -613,22 +654,22 @@ static int init_astcenc_config( quality, flags, &config); if (status == ASTCENC_ERR_BAD_BLOCK_SIZE) { - printf("ERROR: Block size '%s' is invalid\n", argv[4]); + print_error("ERROR: Block size '%s' is invalid\n", argv[4]); return 1; } - else if (status == ASTCENC_ERR_BAD_CPU_ISA) + else if (status == ASTCENC_ERR_BAD_DECODE_MODE) { - printf("ERROR: Required SIMD ISA support missing on this CPU\n"); + print_error("ERROR: Decode_unorm8 is not supported by HDR profiles\n", argv[4]); return 1; } else if (status == ASTCENC_ERR_BAD_CPU_FLOAT) { - printf("ERROR: astcenc must not be compiled with -ffast-math\n"); + print_error("ERROR: astcenc must not be compiled with -ffast-math\n"); return 1; } else if (status != ASTCENC_SUCCESS) { - printf("ERROR: Init config failed with %s\n", astcenc_get_error_string(status)); + print_error("ERROR: Init config failed with %s\n", astcenc_get_error_string(status)); return 1; } @@ -668,7 +709,7 @@ static int edit_astcenc_config( argidx += 5; if (argidx > argc) { - printf("ERROR: -cw switch with less than 4 arguments\n"); + print_error("ERROR: -cw switch with less than 4 arguments\n"); return 1; } @@ -682,7 +723,7 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -a switch with no argument\n"); + print_error("ERROR: -a switch with no argument\n"); return 1; } @@ -693,13 +734,13 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -esw switch with no argument\n"); + print_error("ERROR: -esw switch with no argument\n"); return 1; } if (strlen(argv[argidx - 1]) != 4) { - printf("ERROR: -esw pattern does not contain 4 characters\n"); + print_error("ERROR: -esw pattern does not contain 4 characters\n"); return 1; } @@ -727,7 +768,7 @@ static int edit_astcenc_config( swizzle_components[i] = ASTCENC_SWZ_1; break; default: - printf("ERROR: -esw component '%c' is not valid\n", argv[argidx - 1][i]); + print_error("ERROR: -esw component '%c' is not valid\n", argv[argidx - 1][i]); return 1; } } @@ -737,18 +778,72 @@ static int edit_astcenc_config( cli_config.swz_encode.b = swizzle_components[2]; cli_config.swz_encode.a = swizzle_components[3]; } + else if (!strcmp(argv[argidx], "-ssw")) + { + argidx += 2; + if (argidx > argc) + { + print_error("ERROR: -ssw switch with no argument\n"); + return 1; + } + + size_t char_count = strlen(argv[argidx - 1]); + if (char_count == 0) + { + print_error("ERROR: -ssw pattern contains no characters\n"); + return 1; + } + + if (char_count > 4) + { + print_error("ERROR: -ssw pattern contains more than 4 characters\n"); + return 1; + } + + bool found_r = false; + bool found_g = false; + bool found_b = false; + bool found_a = false; + + for (size_t i = 0; i < char_count; i++) + { + switch (argv[argidx - 1][i]) + { + case 'r': + found_r = true; + break; + case 'g': + found_g = true; + break; + case 'b': + found_b = true; + break; + case 'a': + found_a = true; + break; + default: + print_error("ERROR: -ssw component '%c' is not valid\n", argv[argidx - 1][i]); + return 1; + } + } + + config.cw_r_weight = found_r ? 1.0f : 0.0f; + config.cw_g_weight = found_g ? 1.0f : 0.0f; + config.cw_b_weight = found_b ? 1.0f : 0.0f; + config.cw_a_weight = found_a ? 1.0f : 0.0f; + } else if (!strcmp(argv[argidx], "-dsw")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -dsw switch with no argument\n"); + print_error("ERROR: -dsw switch with no argument\n"); return 1; } if (strlen(argv[argidx - 1]) != 4) { - printf("ERROR: -dsw switch does not contain 4 characters\n"); + print_error("ERROR: -dsw switch does not contain 4 characters\n"); return 1; } @@ -779,7 +874,7 @@ static int edit_astcenc_config( swizzle_components[i] = ASTCENC_SWZ_Z; break; default: - printf("ERROR: ERROR: -dsw component '%c' is not valid\n", argv[argidx - 1][i]); + print_error("ERROR: ERROR: -dsw component '%c' is not valid\n", argv[argidx - 1][i]); return 1; } } @@ -790,10 +885,6 @@ static int edit_astcenc_config( cli_config.swz_decode.a = swizzle_components[3]; } // presets begin here - else if (!strcmp(argv[argidx], "-mask")) - { - argidx++; - } else if (!strcmp(argv[argidx], "-normal")) { argidx++; @@ -813,13 +904,17 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -rgbm switch with no argument\n"); + print_error("ERROR: -rgbm switch with no argument\n"); return 1; } config.rgbm_m_scale = static_cast(atof(argv[argidx - 1])); config.cw_a_weight = 2.0f * config.rgbm_m_scale; } + else if (!strcmp(argv[argidx], "-decode_unorm8")) + { + argidx++; + } else if (!strcmp(argv[argidx], "-perceptual")) { argidx++; @@ -837,7 +932,7 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -blockmodelimit switch with no argument\n"); + print_error("ERROR: -blockmodelimit switch with no argument\n"); return 1; } @@ -848,87 +943,131 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -partitioncountlimit switch with no argument\n"); + print_error("ERROR: -partitioncountlimit switch with no argument\n"); return 1; } config.tune_partition_count_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-partitionindexlimit")) + else if (!strcmp(argv[argidx], "-2partitionindexlimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -partitionindexlimit switch with no argument\n"); + print_error("ERROR: -2partitionindexlimit switch with no argument\n"); return 1; } - config.tune_partition_index_limit = atoi(argv[argidx - 1]); + config.tune_2partition_index_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-dblimit")) + else if (!strcmp(argv[argidx], "-3partitionindexlimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -dblimit switch with no argument\n"); + print_error("ERROR: -3partitionindexlimit switch with no argument\n"); return 1; } - if ((config.profile == ASTCENC_PRF_LDR) || (config.profile == ASTCENC_PRF_LDR_SRGB)) + config.tune_3partition_index_limit = atoi(argv[argidx - 1]); + } + else if (!strcmp(argv[argidx], "-4partitionindexlimit")) + { + argidx += 2; + if (argidx > argc) { - config.tune_db_limit = static_cast(atof(argv[argidx - 1])); + print_error("ERROR: -4partitionindexlimit switch with no argument\n"); + return 1; } + + config.tune_4partition_index_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-2partitionlimitfactor")) + else if (!strcmp(argv[argidx], "-2partitioncandidatelimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -2partitionlimitfactor switch with no argument\n"); + print_error("ERROR: -2partitioncandidatelimit switch with no argument\n"); return 1; } - config.tune_2_partition_early_out_limit_factor = static_cast(atof(argv[argidx - 1])); + config.tune_2partitioning_candidate_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-3partitionlimitfactor")) + else if (!strcmp(argv[argidx], "-3partitioncandidatelimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -3partitionlimitfactor switch with no argument\n"); + print_error("ERROR: -3partitioncandidatelimit switch with no argument\n"); return 1; } - config.tune_3_partition_early_out_limit_factor = static_cast(atof(argv[argidx - 1])); + config.tune_3partitioning_candidate_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-2planelimitcorrelation")) + else if (!strcmp(argv[argidx], "-4partitioncandidatelimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -2planelimitcorrelation switch with no argument\n"); + print_error("ERROR: -4partitioncandidatelimit switch with no argument\n"); return 1; } - config.tune_2_plane_early_out_limit_correlation = static_cast(atof(argv[argidx - 1])); + config.tune_4partitioning_candidate_limit = atoi(argv[argidx - 1]); } - else if (!strcmp(argv[argidx], "-lowweightmodelimit")) + else if (!strcmp(argv[argidx], "-dblimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -lowweightmodelimit switch with no argument\n"); + print_error("ERROR: -dblimit switch with no argument\n"); return 1; } - config.tune_low_weight_count_limit = atoi(argv[argidx - 1]); + if ((config.profile == ASTCENC_PRF_LDR) || (config.profile == ASTCENC_PRF_LDR_SRGB)) + { + config.tune_db_limit = static_cast(atof(argv[argidx - 1])); + } + } + else if (!strcmp(argv[argidx], "-2partitionlimitfactor")) + { + argidx += 2; + if (argidx > argc) + { + print_error("ERROR: -2partitionlimitfactor switch with no argument\n"); + return 1; + } + + config.tune_2partition_early_out_limit_factor = static_cast(atof(argv[argidx - 1])); + } + else if (!strcmp(argv[argidx], "-3partitionlimitfactor")) + { + argidx += 2; + if (argidx > argc) + { + print_error("ERROR: -3partitionlimitfactor switch with no argument\n"); + return 1; + } + + config.tune_3partition_early_out_limit_factor = static_cast(atof(argv[argidx - 1])); + } + else if (!strcmp(argv[argidx], "-2planelimitcorrelation")) + { + argidx += 2; + if (argidx > argc) + { + print_error("ERROR: -2planelimitcorrelation switch with no argument\n"); + return 1; + } + + config.tune_2plane_early_out_limit_correlation = static_cast(atof(argv[argidx - 1])); } else if (!strcmp(argv[argidx], "-refinementlimit")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -refinementlimit switch with no argument\n"); + print_error("ERROR: -refinementlimit switch with no argument\n"); return 1; } @@ -939,7 +1078,7 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -candidatelimit switch with no argument\n"); + print_error("ERROR: -candidatelimit switch with no argument\n"); return 1; } @@ -950,12 +1089,28 @@ static int edit_astcenc_config( argidx += 2; if (argidx > argc) { - printf("ERROR: -j switch with no argument\n"); + print_error("ERROR: -j switch with no argument\n"); return 1; } cli_config.thread_count = atoi(argv[argidx - 1]); } + else if (!strcmp(argv[argidx], "-repeats")) + { + argidx += 2; + if (argidx > argc) + { + print_error("ERROR: -repeats switch with no argument\n"); + return 1; + } + + cli_config.repeat_count = atoi(argv[argidx - 1]); + if (cli_config.repeat_count <= 0) + { + print_error("ERROR: -repeats value must be at least one\n"); + return 1; + } + } else if (!strcmp(argv[argidx], "-yflip")) { argidx++; @@ -966,7 +1121,7 @@ static int edit_astcenc_config( argidx += 3; if (argidx > argc) { - printf("ERROR: -mpsnr switch with less than 2 arguments\n"); + print_error("ERROR: -mpsnr switch with less than 2 arguments\n"); return 1; } @@ -974,24 +1129,24 @@ static int edit_astcenc_config( cli_config.high_fstop = atoi(argv[argidx - 1]); if (cli_config.high_fstop < cli_config.low_fstop) { - printf("ERROR: -mpsnr switch is greater than the \n"); + print_error("ERROR: -mpsnr switch is greater than the \n"); return 1; } } - // Option: Encode a 3D image from an array of 2D images. - else if (!strcmp(argv[argidx], "-array")) + // Option: Encode a 3D image from a sequence of 2D images. + else if (!strcmp(argv[argidx], "-zdim")) { // Only supports compressing if (!(operation & ASTCENC_STAGE_COMPRESS)) { - printf("ERROR: -array switch is only valid for compression\n"); + print_error("ERROR: -zdim switch is only valid for compression\n"); return 1; } // Image depth must be specified. if (argidx + 2 > argc) { - printf("ERROR: -array switch with no argument\n"); + print_error("ERROR: -zdim switch with no argument\n"); return 1; } argidx++; @@ -999,24 +1154,24 @@ static int edit_astcenc_config( // Read array size (image depth). if (!sscanf(argv[argidx], "%u", &cli_config.array_size) || cli_config.array_size == 0) { - printf("ERROR: -array size '%s' is invalid\n", argv[argidx]); + print_error("ERROR: -zdim size '%s' is invalid\n", argv[argidx]); return 1; } if ((cli_config.array_size > 1) && (config.block_z == 1)) { - printf("ERROR: -array with 3D input data for a 2D output format\n"); + print_error("ERROR: -zdim with 3D input data for a 2D output format\n"); return 1; } argidx++; } #if defined(ASTCENC_DIAGNOSTICS) - else if (!strcmp(argv[argidx], "-dtrace-out")) + else if (!strcmp(argv[argidx], "-dtrace")) { argidx += 2; if (argidx > argc) { - printf("ERROR: -dtrace-out switch with no argument\n"); + print_error("ERROR: -dtrace switch with no argument\n"); return 1; } @@ -1028,9 +1183,14 @@ static int edit_astcenc_config( argidx += 2; // skip 2 chatacters to get next parameter config.privateProfile = static_cast(atoi(argv[argidx - 1])); } + else if (!strcmp(argv[argidx], "-dimage")) + { + argidx += 1; + cli_config.diagnostic_images = true; + } else // check others as well { - printf("ERROR: Argument '%s' not recognized\n", argv[argidx]); + print_error("ERROR: Argument '%s' not recognized\n", argv[argidx]); return 1; } } @@ -1046,7 +1206,7 @@ static int edit_astcenc_config( if (!config.trace_file_path) { - printf("ERROR: Diagnostics builds must set -dtrace-out\n"); + print_error("ERROR: Diagnostics builds must set -dtrace\n"); return 1; } #endif @@ -1107,11 +1267,13 @@ static void print_astcenc_config( printf(" B component weight: %g\n", static_cast(config.cw_b_weight)); printf(" A component weight: %g\n", static_cast(config.cw_a_weight)); printf(" Partition cutoff: %u partitions\n", config.tune_partition_count_limit); - printf(" Partition index cutoff: %u partition ids\n", config.tune_partition_index_limit); + printf(" 2 partition index cutoff: %u partition ids\n", config.tune_2partition_index_limit); + printf(" 3 partition index cutoff: %u partition ids\n", config.tune_3partition_index_limit); + printf(" 4 partition index cutoff: %u partition ids\n", config.tune_4partition_index_limit); printf(" PSNR cutoff: %g dB\n", static_cast(config.tune_db_limit)); - printf(" 3 partition cutoff: %g\n", static_cast(config.tune_2_partition_early_out_limit_factor)); - printf(" 4 partition cutoff: %g\n", static_cast(config.tune_3_partition_early_out_limit_factor)); - printf(" 2 plane correlation cutoff: %g\n", static_cast(config.tune_2_plane_early_out_limit_correlation)); + printf(" 3 partition cutoff: %g\n", static_cast(config.tune_2partition_early_out_limit_factor)); + printf(" 4 partition cutoff: %g\n", static_cast(config.tune_3partition_early_out_limit_factor)); + printf(" 2 plane correlation cutoff: %g\n", static_cast(config.tune_2plane_early_out_limit_correlation)); printf(" Block mode centile cutoff: %g%%\n", static_cast(config.tune_block_mode_limit)); printf(" Candidate cutoff: %u candidates\n", config.tune_candidate_limit); printf(" Refinement cutoff: %u iterations\n", config.tune_refinement_limit); @@ -1213,6 +1375,30 @@ static void image_set_pixel( data[(4 * img.dim_x * y) + (4 * x + 3)] = pixel.lane<3>(); } +/** + * @brief Set the value of a single pixel in an image. + * + * @param[out] img The output image; must use F32 texture components. + * @param x The pixel x coordinate. + * @param y The pixel y coordinate. + * @param pixel The pixel color value to write. + */ +static void image_set_pixel_u8( + astcenc_image& img, + size_t x, + size_t y, + vint4 pixel +) { + // We should never escape bounds + assert(x < img.dim_x); + assert(y < img.dim_y); + assert(img.data_type == ASTCENC_TYPE_U8); + + uint8_t* data = static_cast(img.data[0]); + pixel = pack_low_bytes(pixel); + store_nbytes(pixel, data + (4 * img.dim_x * y) + (4 * x )); +} + /** * @brief Create a copy of @c input with forced unit-length normal vectors. * @@ -1342,6 +1528,365 @@ static void image_preprocess_premultiply( } } +/** + * @brief Populate a single diagnostic image showing aspects of the encoding. + * + * @param context The context to use. + * @param image The compressed image to analyze. + * @param diag_image The output visualization image to populate. + * @param texel_func The per-texel callback used to determine output color. + */ +static void print_diagnostic_image( + astcenc_context* context, + const astc_compressed_image& image, + astcenc_image& diag_image, + std::function texel_func +) { + size_t block_cols = (image.dim_x + image.block_x - 1) / image.block_x; + size_t block_rows = (image.dim_y + image.block_y - 1) / image.block_y; + + uint8_t* data = image.data; + for (size_t block_y = 0; block_y < block_rows; block_y++) + { + for (size_t block_x = 0; block_x < block_cols; block_x++) + { + astcenc_block_info block_info; + astcenc_get_block_info(context, data, &block_info); + data += 16; + + size_t start_row = block_y * image.block_y; + size_t start_col = block_x * image.block_x; + + size_t end_row = astc::min(start_row + image.block_y, static_cast(image.dim_y)); + size_t end_col = astc::min(start_col + image.block_x, static_cast(image.dim_x)); + + for (size_t texel_y = start_row; texel_y < end_row; texel_y++) + { + for (size_t texel_x = start_col; texel_x < end_col; texel_x++) + { + vint4 color = texel_func(block_info, texel_x - start_col, texel_y - start_row); + image_set_pixel_u8(diag_image, texel_x, texel_y, color); + } + } + } + } +} + +/** + * @brief Print a set of diagnostic images showing aspects of the encoding. + * + * @param context The context to use. + * @param image The compressed image to analyze. + * @param output_file The output file name to use as a stem for new names. + */ +static void print_diagnostic_images( + astcenc_context* context, + const astc_compressed_image& image, + const std::string& output_file +) { + if (image.dim_z != 1) + { + return; + } + + // Try to find a file extension we know about + size_t index = output_file.find_last_of("."); + std::string stem = output_file; + if (index != std::string::npos) + { + stem = stem.substr(0, index); + } + + auto diag_image = alloc_image(8, image.dim_x, image.dim_y, image.dim_z); + + // ---- ---- ---- ---- Partitioning ---- ---- ---- ---- + auto partition_func = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + const vint4 colors[] { + vint4( 0, 0, 0, 255), + vint4(255, 0, 0, 255), + vint4( 0, 255, 0, 255), + vint4( 0, 0, 255, 255), + vint4(255, 255, 255, 255) + }; + + size_t texel_index = texel_y * info.block_x + texel_x; + + int partition { 0 }; + if (!info.is_constant_block) + { + partition = info.partition_assignment[texel_index] + 1; + } + + return colors[partition]; + }; + + print_diagnostic_image(context, image, *diag_image, partition_func); + std::string fname = stem + "_diag_partitioning.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Weight planes ---- ---- ---- ---- + auto texel_func1 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + const vint4 colors[] { + vint4( 0, 0, 0, 255), + vint4(255, 0, 0, 255), + vint4( 0, 255, 0, 255), + vint4( 0, 0, 255, 255), + vint4(255, 255, 255, 255) + }; + + int component { 0 }; + if (info.is_dual_plane_block) + { + component = info.dual_plane_component + 1; + } + + return colors[component]; + }; + + print_diagnostic_image(context, image, *diag_image, texel_func1); + fname = stem + "_diag_weight_plane2.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Weight density ---- ---- ---- ---- + auto texel_func2 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + float density = 0.0f; + if (!info.is_constant_block) + { + float texel_count = static_cast(info.block_x * info.block_y); + float weight_count = static_cast(info.weight_x * info.weight_y); + density = weight_count / texel_count; + } + + int densityi = static_cast(255.0f * density); + return vint4(densityi, densityi, densityi, 255); + }; + + print_diagnostic_image(context, image, *diag_image, texel_func2); + fname = stem + "_diag_weight_density.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Weight quant ---- ---- ---- ---- + auto texel_func3 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + int quant { 0 }; + if (!info.is_constant_block) + { + quant = info.weight_level_count - 1; + } + + return vint4(quant, quant, quant, 255); + }; + + print_diagnostic_image(context, image, *diag_image, texel_func3); + fname = stem + "_diag_weight_quant.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Color quant ---- ---- ---- ---- + auto texel_func4 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + int quant { 0 }; + if (!info.is_constant_block) + { + quant = info.color_level_count - 1; + } + + return vint4(quant, quant, quant, 255); + }; + + print_diagnostic_image(context, image, *diag_image, texel_func4); + fname = stem + "_diag_color_quant.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Color endpoint mode: Index ---- ---- ---- ---- + auto texel_func5 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + size_t texel_index = texel_y * info.block_x + texel_x; + + int cem { 255 }; + if (!info.is_constant_block) + { + uint8_t partition = info.partition_assignment[texel_index]; + cem = info.color_endpoint_modes[partition] * 16; + } + + return vint4(cem, cem, cem, 255); + }; + + print_diagnostic_image(context, image, *diag_image, texel_func5); + fname = stem + "_diag_cem_index.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Color endpoint mode: Components ---- ---- ---- ---- + auto texel_func6 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + const vint4 colors[] { + vint4( 0, 0, 0, 255), + vint4(255, 0, 0, 255), + vint4( 0, 255, 0, 255), + vint4( 0, 0, 255, 255), + vint4(255, 255, 255, 255) + }; + + size_t texel_index = texel_y * info.block_x + texel_x; + + int components { 0 }; + if (!info.is_constant_block) + { + uint8_t partition = info.partition_assignment[texel_index]; + uint8_t cem = info.color_endpoint_modes[partition]; + + switch (cem) + { + case 0: + case 1: + case 2: + case 3: + components = 1; + break; + case 4: + case 5: + components = 2; + break; + case 6: + case 7: + case 8: + case 9: + case 11: + components = 3; + break; + default: + components = 4; + break; + } + } + + return colors[components]; + }; + + print_diagnostic_image(context, image, *diag_image, texel_func6); + fname = stem + "_diag_cem_components.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Color endpoint mode: Style ---- ---- ---- ---- + auto texel_func7 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + const vint4 colors[] { + vint4( 0, 0, 0, 255), + vint4(255, 0, 0, 255), + vint4( 0, 255, 0, 255), + vint4( 0, 0, 255, 255), + }; + + size_t texel_index = texel_y * info.block_x + texel_x; + + int style { 0 }; + if (!info.is_constant_block) + { + uint8_t partition = info.partition_assignment[texel_index]; + uint8_t cem = info.color_endpoint_modes[partition]; + + switch (cem) + { + // Direct - two absolute endpoints + case 0: + case 1: + case 2: + case 3: + case 4: + case 8: + case 11: + case 12: + case 14: + case 15: + style = 1; + break; + // Offset - one absolute plus delta + case 5: + case 9: + case 13: + style = 2; + break; + // Scale - one absolute plus scale + case 6: + case 7: + case 10: + style = 3; + break; + // Shouldn't happen ... + default: + style = 0; + break; + } + } + + return colors[style]; + }; + + print_diagnostic_image(context, image, *diag_image, texel_func7); + fname = stem + "_diag_cem_style.png"; + store_ncimage(diag_image, fname.c_str(), false); + + // ---- ---- ---- ---- Color endpoint mode: Style ---- ---- ---- ---- + auto texel_func8 = [](astcenc_block_info& info, size_t texel_x, size_t texel_y) { + (void)texel_x; + (void)texel_y; + + size_t texel_index = texel_y * info.block_x + texel_x; + + int style { 0 }; + if (!info.is_constant_block) + { + uint8_t partition = info.partition_assignment[texel_index]; + uint8_t cem = info.color_endpoint_modes[partition]; + + switch (cem) + { + // LDR blocks + case 0: + case 1: + case 4: + case 5: + case 6: + case 8: + case 9: + case 10: + case 12: + case 13: + style = 128; + break; + // HDR blocks + default: + style = 155; + break; + } + } + + return vint4(style, style, style, 255); + }; + + print_diagnostic_image(context, image, *diag_image, texel_func8); + fname = stem + "_diag_cem_hdr.png"; + store_ncimage(diag_image, fname.c_str(), false); + + free_image(diag_image); +} + #if QUALITY_CONTROL constexpr double MAX_PSNR = 99.9; constexpr double MAX_VALUE = 255; @@ -1397,7 +1942,7 @@ bool CheckQuality(int32_t* mseIn[RGBA_COM], int blockNum, int blockXYZ) * * @return 0 on success, non-zero otherwise. */ -int main( +int astcenc_main( int argc, char **argv ) { @@ -1429,19 +1974,18 @@ int main( break; } - std::string input_filename = argc >= 3 ? argv[2] : ""; std::string output_filename = argc >= 4 ? argv[3] : ""; if (input_filename.empty()) { - printf("ERROR: Input file not specified\n"); + print_error("ERROR: Input file not specified\n"); return 1; } if (output_filename.empty()) { - printf("ERROR: Output file not specified\n"); + print_error("ERROR: Output file not specified\n"); return 1; } @@ -1481,7 +2025,7 @@ int main( } else { - printf("ERROR: Unknown compressed input file type\n"); + print_error("ERROR: Unknown compressed input file type\n"); return 1; } } @@ -1495,7 +2039,7 @@ int main( } // Initialize cli_config_options with default values - cli_config_options cli_config { 0, 1, false, false, -10, 10, + cli_config_options cli_config { 0, 1, 1, false, false, false, -10, 10, { ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A }, { ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A } }; @@ -1505,16 +2049,46 @@ int main( return 1; } + // Enable progress callback if not in silent mode and using a terminal + #if defined(_WIN32) + int stdoutfno = _fileno(stdout); + #else + int stdoutfno = STDOUT_FILENO; + #endif + + if ((!cli_config.silentmode) && isatty(stdoutfno)) + { + config.progress_callback = progress_emitter; + } + astcenc_image* image_uncomp_in = nullptr ; unsigned int image_uncomp_in_component_count = 0; bool image_uncomp_in_is_hdr = false; astcenc_image* image_decomp_out = nullptr; + // Determine decompression output bitness, if limited by file type + int out_bitness = 0; + if (operation & ASTCENC_STAGE_DECOMPRESS) + { + out_bitness = get_output_filename_enforced_bitness(output_filename.c_str()); + if (out_bitness == 0) + { + bool is_hdr = (config.profile == ASTCENC_PRF_HDR) || + (config.profile == ASTCENC_PRF_HDR_RGB_LDR_A); + out_bitness = is_hdr ? 16 : 8; + } + + // If decompressed output is unorm8 then force the decode_unorm8 heuristics for compression + if (out_bitness == 8) + { + config.flags |= ASTCENC_FLG_USE_DECODE_UNORM8; + } + } + // TODO: Handle RAII resources so they get freed when out of scope astcenc_error codec_status; astcenc_context* codec_context; - // Preflight - check we have valid extensions for storing a file if (operation & ASTCENC_STAGE_ST_NCOMP) { @@ -1523,7 +2097,7 @@ int main( { const char *eptr = strrchr(output_filename.c_str(), '.'); eptr = eptr ? eptr : ""; - printf("ERROR: Unknown uncompressed output file type '%s'\n", eptr); + print_error("ERROR: Unknown uncompressed output file type '%s'\n", eptr); return 1; } } @@ -1540,7 +2114,7 @@ int main( { const char *eptr = strrchr(output_filename.c_str(), '.'); eptr = eptr ? eptr : ""; - printf("ERROR: Unknown compressed output file type '%s'\n", eptr); + print_error("ERROR: Unknown compressed output file type '%s'\n", eptr); return 1; } } @@ -1548,7 +2122,7 @@ int main( codec_status = astcenc_context_alloc(&config, cli_config.thread_count, &codec_context); if (codec_status != ASTCENC_SUCCESS) { - printf("ERROR: Codec context alloc failed: %s\n", astcenc_get_error_string(codec_status)); + print_error("ERROR: Codec context alloc failed: %s\n", astcenc_get_error_string(codec_status)); return 1; } @@ -1560,7 +2134,7 @@ int main( image_uncomp_in_is_hdr, image_uncomp_in_component_count); if (!image_uncomp_in) { - printf ("ERROR: Failed to load uncompressed image file\n"); + print_error("ERROR: Failed to load uncompressed image file\n"); return 1; } @@ -1575,7 +2149,7 @@ int main( image_uncomp_in->dim_z); if (!image_pp) { - printf ("ERROR: Failed to allocate preprocessed image\n"); + print_error("ERROR: Failed to allocate preprocessed image\n"); return 1; } @@ -1615,8 +2189,6 @@ int main( } } - double start_coding_time = get_time(); - double image_size = 0.0; if (image_uncomp_in) { @@ -1632,6 +2204,8 @@ int main( } // Compress an image + double best_compression_time = 100000.0; + double total_compression_time = 0.0; if (operation & ASTCENC_STAGE_COMPRESS) { print_astcenc_config(cli_config, config); @@ -1665,24 +2239,47 @@ int main( #endif // Only launch worker threads for multi-threaded use - it makes basic // single-threaded profiling and debugging a little less convoluted - if (cli_config.thread_count > 1) + double start_compression_time = get_time(); + for (unsigned int i = 0; i < cli_config.repeat_count; i++) { - launch_threads(cli_config.thread_count, compression_workload_runner, &work); - } - else - { - work.error = astcenc_compress_image( - work.context, work.image, &work.swizzle, - work.data_out, work.data_len, + if (config.progress_callback) + { + printf("Compression\n"); + printf("===========\n"); + printf("\n"); + } + + double start_iter_time = get_time(); + if (cli_config.thread_count > 1) + { + launch_threads("Compression", cli_config.thread_count, compression_workload_runner, &work); + } + else + { + work.error = astcenc_compress_image( + work.context, work.image, &work.swizzle, + work.data_out, work.data_len, #if QUALITY_CONTROL - work.calQualityEnable, work.mse, + work.calQualityEnable, work.mse, #endif - 0); + 0); + } + + astcenc_compress_reset(codec_context); + + if (config.progress_callback) + { + printf("\n\n"); + } + + double iter_time = get_time() - start_iter_time; + best_compression_time = astc::min(iter_time, best_compression_time); } + total_compression_time = get_time() - start_compression_time; if (work.error != ASTCENC_SUCCESS) { - printf("ERROR: Codec compress failed: %s\n", astcenc_get_error_string(work.error)); + print_error("ERROR: Codec compress failed: %s\n", astcenc_get_error_string(work.error)); return 1; } #if QUALITY_CONTROL @@ -1708,15 +2305,10 @@ int main( } // Decompress an image + double best_decompression_time = 100000.0; + double total_decompression_time = 0.0; if (operation & ASTCENC_STAGE_DECOMPRESS) { - int out_bitness = get_output_filename_enforced_bitness(output_filename.c_str()); - if (out_bitness == 0) - { - bool is_hdr = (config.profile == ASTCENC_PRF_HDR) || (config.profile == ASTCENC_PRF_HDR_RGB_LDR_A); - out_bitness = is_hdr ? 16 : 8; - } - image_decomp_out = alloc_image( out_bitness, image_comp.dim_x, image_comp.dim_y, image_comp.dim_z); @@ -1730,27 +2322,42 @@ int main( // Only launch worker threads for multi-threaded use - it makes basic // single-threaded profiling and debugging a little less convoluted - if (cli_config.thread_count > 1) - { - launch_threads(cli_config.thread_count, decompression_workload_runner, &work); - } - else + double start_decompression_time = get_time(); + for (unsigned int i = 0; i < cli_config.repeat_count; i++) { - work.error = astcenc_decompress_image( - work.context, work.data, work.data_len, - work.image_out, &work.swizzle, 0); + double start_iter_time = get_time(); + if (cli_config.thread_count > 1) + { + launch_threads("Decompression", cli_config.thread_count, decompression_workload_runner, &work); + } + else + { + work.error = astcenc_decompress_image( + work.context, work.data, work.data_len, + work.image_out, &work.swizzle, 0); + } + + astcenc_decompress_reset(codec_context); + + double iter_time = get_time() - start_iter_time; + best_decompression_time = astc::min(iter_time, best_decompression_time); } + total_decompression_time = get_time() - start_decompression_time; if (work.error != ASTCENC_SUCCESS) { - printf("ERROR: Codec decompress failed: %s\n", astcenc_get_error_string(codec_status)); + print_error("ERROR: Codec decompress failed: %s\n", astcenc_get_error_string(codec_status)); return 1; } } - double end_coding_time = get_time(); +#if defined(_WIN32) + bool is_null = output_filename == "NUL" || output_filename == "nul"; +#else + bool is_null = output_filename == "/dev/null"; +#endif - // Print metrics in comparison mode + // Print metrics in comparison mode if (operation & ASTCENC_STAGE_COMPARE) { bool is_normal_map = config.flags & ASTCENC_FLG_MAP_NORMAL; @@ -1768,7 +2375,7 @@ int main( error = store_cimage(image_comp, output_filename.c_str()); if (error) { - printf ("ERROR: Failed to store compressed image\n"); + print_error("ERROR: Failed to store compressed image\n"); return 1; } } @@ -1778,20 +2385,15 @@ int main( error = store_ktx_compressed_image(image_comp, output_filename.c_str(), srgb); if (error) { - printf ("ERROR: Failed to store compressed image\n"); + print_error("ERROR: Failed to store compressed image\n"); return 1; } } else { -#if defined(_WIN32) - bool is_null = output_filename == "NUL" || output_filename == "nul"; -#else - bool is_null = output_filename == "/dev/null"; -#endif if (!is_null) { - printf("ERROR: Unknown compressed output file type\n"); + print_error("ERROR: Unknown compressed output file type\n"); return 1; } } @@ -1800,24 +2402,24 @@ int main( // Store decompressed image if (operation & ASTCENC_STAGE_ST_NCOMP) { -#if defined(_WIN32) - bool is_null = output_filename == "NUL" || output_filename == "nul"; -#else - bool is_null = output_filename == "/dev/null"; -#endif - if (!is_null) { bool store_result = store_ncimage(image_decomp_out, output_filename.c_str(), cli_config.y_flip); if (!store_result) { - printf("ERROR: Failed to write output image %s\n", output_filename.c_str()); + print_error("ERROR: Failed to write output image %s\n", output_filename.c_str()); return 1; } } } + // Store diagnostic images + if (cli_config.diagnostic_images && !is_null) + { + print_diagnostic_images(codec_context, image_comp, output_filename); + } + free_image(image_uncomp_in); free_image(image_decomp_out); astcenc_context_free(codec_context); @@ -1827,14 +2429,30 @@ int main( if ((operation & ASTCENC_STAGE_COMPARE) || (!cli_config.silentmode)) { double end_time = get_time(); - double tex_rate = image_size / (end_coding_time - start_coding_time); - tex_rate = tex_rate / 1000000.0; + + double repeats = static_cast(cli_config.repeat_count); + double avg_compression_time = total_compression_time / repeats; + double avg_decompression_time = total_decompression_time / repeats; + double total_time = (end_time - start_time) - ((repeats - 1.0) * avg_compression_time) - ((repeats - 1.0) * avg_decompression_time); printf("Performance metrics\n"); printf("===================\n\n"); - printf(" Total time: %8.4f s\n", end_time - start_time); - printf(" Coding time: %8.4f s\n", end_coding_time - start_coding_time); - printf(" Coding rate: %8.4f MT/s\n", tex_rate); + printf(" Total time: %8.4f s\n", total_time); + + if (operation & ASTCENC_STAGE_COMPRESS) + { + double compression_rate = image_size / (best_compression_time * 1000000.0); + + printf(" Coding time: %8.4f s\n", best_compression_time); + printf(" Coding rate: %8.4f MT/s\n", compression_rate); + } + + if (operation & ASTCENC_STAGE_DECOMPRESS) + { + double decompression_rate = image_size / (best_decompression_time * 1000000.0); + printf(" Decoding time: %8.4f s\n", best_decompression_time); + printf(" Decoding rate: %8.4f MT/s\n", decompression_rate); + } } return 0; diff --git a/Source/astcenccli_toplevel_help.cpp b/Source/astcenccli_toplevel_help.cpp index 2ce0d10..a21750b 100644 --- a/Source/astcenccli_toplevel_help.cpp +++ b/Source/astcenccli_toplevel_help.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // ---------------------------------------------------------------------------- -// Copyright 2011-2022 Arm Limited +// Copyright 2011-2023 Arm Limited // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy @@ -25,7 +25,7 @@ /** @brief The version header. */ static const char *astcenc_copyright_string = R"(astcenc v%s, %u-bit %s%s%s -Copyright 2011-%s Arm Limited, all rights reserved +Copyright (c) 2011-%s Arm Limited. All rights reserved. )"; /** @brief The short-form help text. */ @@ -138,14 +138,15 @@ COMPRESSION The quality level configures the quality-performance tradeoff for the compressor; more complete searches of the search space improve image quality at the expense of compression time. The quality level - can be set to any value between 0 (fastest) and 100 (thorough), or - to a fixed quality preset: + can be set to any value between 0 (fastest) and 100 (exhaustive), + or to a fixed quality preset: - -fastest (equivalent to quality = 0) - -fast (equivalent to quality = 10) - -medium (equivalent to quality = 60) - -thorough (equivalent to quality = 98) - -exhaustive (equivalent to quality = 100) + -fastest (equivalent to quality = 0) + -fast (equivalent to quality = 10) + -medium (equivalent to quality = 60) + -thorough (equivalent to quality = 98) + -verythorough (equivalent to quality = 99) + -exhaustive (equivalent to quality = 100) For compression of production content we recommend using a quality level equivalent to -medium or higher. @@ -158,11 +159,17 @@ COMPRESSION to consider for common usage, based on the type of image data being compressed. - -mask - The input texture is a mask texture with unrelated data stored - in the various color components, so enable error heuristics that - aim to improve quality by minimizing the effect of error - cross-talk across the color components. + -decode_unorm8 + Indicate that an LDR compressed texture will be used with + the decode_unorm8 extension behavior, instead of the default + decode_unorm16 decompression. + + Matching the decode mode used during compression to the mode + used at runtime will improve image quality as the compressor + can ensure that rounding goes the right way. + + This mode is used automatically if you decompress to an 8-bit + per component output image format. -normal The input texture is a three component linear LDR normal map @@ -175,6 +182,9 @@ COMPRESSION nml.xy = nml.xy * 2.0 - 1.0; // Unpack to [-1,1] nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z + Alternative component swizzles can be set with -esw and -dsw + parameters. + -rgbm The input texture is an RGBM encoded texture, storing values HDR values between 0 and in an LDR container format with a @@ -193,8 +203,8 @@ COMPRESSION typically lowers the measured PSNR score. Perceptual methods are currently only available for normal maps and RGB color data. - -array - Loads an array of 2D image slices to use as a 3D image. + -zdim + Load a sequence of 2D image slices to use as a 3D image. The input filename given is used is decorated with the postfix "_" to find the file to load. For example, an input named "input.png" would load as input_0.png, input_1.png, etc. @@ -270,53 +280,71 @@ ADVANCED COMPRESSION Higher numbers give better quality, as more complex blocks can be encoded, but will increase search time. Preset defaults are: - -fastest : 2 - -fast : 3 - -medium : 4 - -thorough : 4 - -exhaustive : 4 - - -partitionindexlimit - Test block partition indices for each partition count. - Higher numbers give better quality, however large values give - diminishing returns especially for smaller block sizes. Preset - defaults are: - - -fastest : 8 - -fast : 12 - -medium : 26 - -thorough : 76 - -exhaustive : 1024 + -fastest : 2 + -fast : 3 + -medium : 4 + -thorough : 4 + -verythorough : 4 + -exhaustive : 4 + + -[2|3|4]partitionindexlimit + Estimate errors for block partition indices for this + partition count. Higher numbers give better quality, however + large values give diminishing returns especially for smaller + block sizes. Preset defaults are: + + -fastest : 10 | 6 | 4 + -fast : 18 | 10 | 8 + -medium : 34 | 28 | 16 + -thorough : 82 | 60 | 30 + -verythorough : 256 | 128 | 64 + -exhaustive : 512 | 512 | 512 + + -[2|3|4]partitioncandidatelimit + Calculate errors for block partition indices for this + partition count. Higher numbers give better quality, however + large values give diminishing returns especially for smaller + block sizes. Preset defaults are: + + -fastest : 2 | 2 | 2 + -fast : 2 | 2 | 2 + -medium : 2 | 2 | 2 + -thorough : 3 | 2 | 2 + -verythorough : 20 | 14 | 8 + -exhaustive : 32 | 32 | 32 -blockmodelimit Test block modes below usage centile in an empirically determined distribution of block mode frequency. This option is ineffective for 3D textures. Preset defaults are: - -fastest : 40 - -fast : 55 - -medium : 76 - -thorough : 93 - -exhaustive : 100 + -fastest : 43 + -fast : 55 + -medium : 77 + -thorough : 94 + -verythorough : 98 + -exhaustive : 100 - -refinementlimit - Iterate only refinement iterations on colors and + -refinementlimit + Iterate refinement iterations on colors and weights. Minimum value is 1. Preset defaults are: - -fastest : 2 - -fast : 3 - -medium : 3 - -thorough : 4 - -exhaustive : 4 + -fastest : 2 + -fast : 3 + -medium : 3 + -thorough : 4 + -verythorough : 4 + -exhaustive : 4 - -candidatelimit - Trial only candidate encodings for each block mode: + -candidatelimit + Trial candidate encodings for each block mode: - -fastest : 2 - -fast : 3 - -medium : 3 - -thorough : 4 - -exhaustive : 4 + -fastest : 2 + -fast : 3 + -medium : 3 + -thorough : 4 + -verythorough : 6 + -exhaustive : 8 -dblimit Stop compression work on a block as soon as the PSNR of the @@ -324,37 +352,26 @@ ADVANCED COMPRESSION ineffective for HDR textures. Preset defaults, where N is the number of texels in a block, are: - -fastest : MAX(63-19*log10(N), 85-35*log10(N)) - -fast : MAX(63-19*log10(N), 85-35*log10(N)) - -medium : MAX(70-19*log10(N), 95-35*log10(N)) - -thorough : MAX(77-19*log10(N), 105-35*log10(N)) - -exhaustive : 999 + -fastest : MAX(63-19*log10(N), 85-35*log10(N)) + -fast : MAX(63-19*log10(N), 85-35*log10(N)) + -medium : MAX(70-19*log10(N), 95-35*log10(N)) + -thorough : MAX(77-19*log10(N), 105-35*log10(N)) + -verythorough : 999 + -exhaustive : 999 - -2partitionlimitfactor + -[2|3]partitionlimitfactor Stop compression work on a block after only testing blocks with - up to two partitions and one plane of weights, unless the two + up to 2/3 partitions and one plane of weights, unless the 2/3 partition error term is lower than the error term from encoding - with one partition by more than the specified factor. Preset + with 1/2 partitions by more than the specified factor. Preset defaults are: - -fastest : 1.0 - -fast : 1.0 - -medium : 1.2 - -thorough : 2.5 - -exhaustive : 10.0 - - -3partitionlimitfactor - Stop compression work on a block after only testing blocks with - up to three partitions and one plane of weights, unless the three - partition error term is lower than the error term from encoding - with two partitions by more than the specified factor. Preset - defaults are: - - -fastest : 1.00 - -fast : 1.10 - -medium : 1.25 - -thorough : 1.25 - -exhaustive : 10.00 + -fastest : 1.00 | 1.00 + -fast : 1.00 | 1.00 + -medium : 1.10 | 1.05 + -thorough : 1.35 | 1.15 + -verythrorough : 1.60 | 1.40 + -exhaustive : 2.00 | 2.00 -2planelimitcorrelation Stop compression after testing only one plane of weights, unless @@ -362,53 +379,57 @@ ADVANCED COMPRESSION components is below this factor. This option is ineffective for normal maps. Preset defaults are: - -fastest : 0.50 - -fast : 0.65 - -medium : 0.85 - -thorough : 0.95 - -exhaustive : 0.99 - - -lowweightmodelimit - Use a simpler weight search for weight counts less than or - equal to this threshold. Preset defaults are bitrate dependent: - - -fastest : 25 - -fast : 20 - -medium : 16 - -thorough : 12 - -exhaustive : 0 - + -fastest : 0.50 + -fast : 0.65 + -medium : 0.85 + -thorough : 0.95 + -verythorough : 0.98 + -exhaustive : 0.99 +)" +// This split in the literals is needed for Visual Studio; the compiler +// will concatenate these two strings together ... +R"( Other options ------------- -esw - Swizzle the color components before compression. The swizzle is - specified using a 4-character string, which defines the output - format ordering. The characters may be taken from the set - [rgba01], selecting either input color components or a literal - zero or one. For example to swap the RG components, and replace - alpha with 1, the swizzle 'grb1' should be used. + Specify an encoding swizzle to reorder the color components + before compression. The swizzle is specified using a four + character string, which defines the format ordering used by + the compressor. - The input swizzle takes place before any compression, and all - error weighting applied using the -cw option is applied to the - post-swizzle component ordering. + The characters may be taken from the set [rgba01], selecting + either input color components or a literal zero or one. For + example to swap the RG components, and replace alpha with 1, + the swizzle 'grb1' should be used. By default all 4 post-swizzle components are included in the - error metrics during compression. When using -esw to map two + compression error metrics. When using -esw to map two component data to the L+A endpoint (e.g. -esw rrrg) the luminance data stored in the RGB components will be weighted 3 times more strongly than the alpha component. This can be - corrected using the -cw option to zero the weights of unused - components; e.g. using -cw 1 0 0 1. + corrected using the -ssw option to specify which components + will be sampled at runtime e.g. -ssw ra. + + -ssw + Specify a sampling swizzle to identify which color components + are actually read by the application shader program. For example, + using -ssw ra tells the compressor that the green and blue error + does not matter because the data is not actually read. + + The sampling swizzle is based on the channel ordering after the + -esw transform has been applied. Note -ssw exposes the same + functionality as -cw, but in a more user-friendly form. -dsw - Swizzle the color components after decompression. The swizzle is - specified using the same method as the -esw option, with support - for an additional "z" character. This is used to specify that - the compressed data stores an X+Y normal map, and that the Z - output component should be reconstructed from the two components - stored in the data. For the typical ASTC normal encoding, which - uses an 'rrrg' compression swizzle, you should specify an 'raz1' + Specify a decompression swizzle used to reorder the color + components after decompression. The swizzle is specified using + the same method as the -esw option, with support for an extra + "z" character. This is used to specify that the compressed data + stores an X+Y normal map, and that the Z output component + should be reconstructed from the two components stored in the + data. For the typical ASTC normal encoding, which uses an + 'rrrg' compression swizzle, you should specify an 'raz1' swizzle for decompression. -yflip @@ -527,7 +548,7 @@ QUICK REFERENCE astcenc {-tl|-ts|-th|-tH} [options] Mode -*l = linear LDR, -*s = sRGB LDR, -*h = HDR RGB/LDR A, -*H = HDR. - Quality = -fastest/-fast/-medium/-thorough/-exhaustive/a float [0-100]. + Quality = -fastest/-fast/-medium/-thorough/-verythorough/-exhaustive/a float [0-100]. )"; /* See header for documentation. */ diff --git a/Source/cmake_core.cmake b/Source/cmake_core.cmake index 067ab19..3c85acc 100644 --- a/Source/cmake_core.cmake +++ b/Source/cmake_core.cmake @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ---------------------------------------------------------------------------- -# Copyright 2020-2022 Arm Limited +# Copyright 2020-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -15,18 +15,32 @@ # under the License. # ---------------------------------------------------------------------------- -if(${UNIVERSAL_BUILD}) - set(ASTC_TARGET astc${CODEC}) -else() - set(ASTC_TARGET astc${CODEC}-${ISA_SIMD}) -endif() +set(ASTCENC_TARGET astc${ASTCENC_CODEC}-${ASTCENC_ISA_SIMD}) -project(${ASTC_TARGET}) +project(${ASTCENC_TARGET}) -set(GNU_LIKE "GNU,Clang,AppleClang") -set(CLANG_LIKE "Clang,AppleClang") +# On CMake 3.25 or older CXX_COMPILER_FRONTEND_VARIANT is not always set +if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "") + set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "${CMAKE_CXX_COMPILER_ID}") +endif() -add_library(${ASTC_TARGET}-static +# Compiler accepts MSVC-style command line options +set(is_msvc_fe "$") +# Compiler accepts GNU-style command line options +set(is_gnu_fe1 "$") +# Compiler accepts AppleClang-style command line options, which is also GNU-style +set(is_gnu_fe2 "$") +# Compiler accepts GNU-style command line options +set(is_gnu_fe "$") + +# Compiler is Visual Studio cl.exe +set(is_msvccl "$>") +# Compiler is Visual Studio clangcl.exe +set(is_clangcl "$>") +# Compiler is upstream clang with the standard frontend +set(is_clang "$>") + +add_library(${ASTCENC_TARGET}-static STATIC astcenc_averages_and_directions.cpp astcenc_block_sizes.cpp @@ -46,19 +60,55 @@ add_library(${ASTC_TARGET}-static astcenc_partition_tables.cpp astcenc_percentile_tables.cpp astcenc_pick_best_endpoint_format.cpp - astcenc_platform_isa_detection.cpp astcenc_quantization.cpp astcenc_symbolic_physical.cpp astcenc_weight_align.cpp astcenc_weight_quant_xfer_tables.cpp) -target_include_directories(${ASTC_TARGET}-static +target_include_directories(${ASTCENC_TARGET}-static PUBLIC $ $) -if(${CLI}) - add_executable(${ASTC_TARGET} +if(${ASTCENC_SHAREDLIB}) + add_library(${ASTCENC_TARGET}-shared + SHARED + astcenc_averages_and_directions.cpp + astcenc_block_sizes.cpp + astcenc_color_quantize.cpp + astcenc_color_unquantize.cpp + astcenc_compress_symbolic.cpp + astcenc_compute_variance.cpp + astcenc_decompress_symbolic.cpp + astcenc_diagnostic_trace.cpp + astcenc_entry.cpp + astcenc_find_best_partitioning.cpp + astcenc_ideal_endpoints_and_weights.cpp + astcenc_image.cpp + astcenc_integer_sequence.cpp + astcenc_mathlib.cpp + astcenc_mathlib_softfloat.cpp + astcenc_partition_tables.cpp + astcenc_percentile_tables.cpp + astcenc_pick_best_endpoint_format.cpp + astcenc_quantization.cpp + astcenc_symbolic_physical.cpp + astcenc_weight_align.cpp + astcenc_weight_quant_xfer_tables.cpp) + + target_include_directories(${ASTCENC_TARGET}-shared + PUBLIC + $ + $) +endif() + +if(${ASTCENC_CLI}) + # Veneer is compiled without any extended ISA so we can safely do + # ISA compatability checks without triggering a SIGILL + add_library(${ASTCENC_TARGET}-veneer + astcenccli_entry.cpp) + + add_executable(${ASTCENC_TARGET} astcenccli_error_metrics.cpp astcenccli_image.cpp astcenccli_image_external.cpp @@ -67,220 +117,313 @@ if(${CLI}) astcenccli_toplevel.cpp astcenccli_toplevel_help.cpp) - target_link_libraries(${ASTC_TARGET} + target_link_libraries(${ASTCENC_TARGET} PRIVATE - ${ASTC_TARGET}-static) + ${ASTCENC_TARGET}-veneer + ${ASTCENC_TARGET}-static) endif() -macro(astcenc_set_properties NAME) +macro(astcenc_set_properties ASTCENC_TARGET_NAME ASTCENC_IS_VENEER) - target_compile_features(${NAME} + target_compile_features(${ASTCENC_TARGET_NAME} PRIVATE cxx_std_14) - target_compile_definitions(${NAME} + target_compile_definitions(${ASTCENC_TARGET_NAME} PRIVATE - # MSVC defines - $<$:_CRT_SECURE_NO_WARNINGS>) + $<${is_msvc_fe}:_CRT_SECURE_NO_WARNINGS>) - if(${DECOMPRESSOR}) - target_compile_definitions(${NAME} + if(${ASTCENC_DECOMPRESSOR}) + target_compile_definitions(${ASTCENC_TARGET_NAME} PRIVATE ASTCENC_DECOMPRESS_ONLY) endif() - if(${BLOCK_MAX_TEXELS}) - target_compile_definitions(${NAME} + if(${ASTCENC_BLOCK_MAX_TEXELS}) + target_compile_definitions(${ASTCENC_TARGET_NAME} PRIVATE - ASTCENC_BLOCK_MAX_TEXELS=${BLOCK_MAX_TEXELS}) + ASTCENC_BLOCK_MAX_TEXELS=${ASTCENC_BLOCK_MAX_TEXELS}) endif() - if(${DIAGNOSTICS}) - target_compile_definitions(${NAME} + if(${ASTCENC_DIAGNOSTICS}) + target_compile_definitions(${ASTCENC_TARGET_NAME} PUBLIC ASTCENC_DIAGNOSTICS) endif() - target_compile_options(${NAME} + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE # Use pthreads on Linux/macOS $<$:-pthread> # MSVC compiler defines - $<$:/EHsc> - $<$:/fp:strict> + $<${is_msvc_fe}:/EHsc> + $<${is_msvccl}:/wd4324> # G++ and Clang++ compiler defines - $<$>:-Wall> - $<$>:-Wextra> - $<$>:-Wpedantic> - $<$>:-Werror> - $<$>:-Wshadow> - $<$>:-Wdouble-promotion> + $<${is_gnu_fe}:-Wall> + $<${is_gnu_fe}:-Wextra> + $<${is_gnu_fe}:-Wpedantic> + $<${is_gnu_fe}:-Werror> + $<${is_gnu_fe}:-Wshadow> + $<${is_gnu_fe}:-Wdouble-promotion> + $<${is_clang}:-Wdocumentation> # Hide noise thrown up by Clang 10 and clang-cl - $<$>:-Wno-unknown-warning-option> - $<$>:-Wno-c++98-compat-pedantic> - $<$>:-Wno-c++98-c++11-compat-pedantic> - $<$>:-Wno-float-equal> - $<$>:-Wno-deprecated-declarations> - $<$>:-Wno-atomic-implicit-seq-cst> + $<${is_gnu_fe}:-Wno-unknown-warning-option> + $<${is_gnu_fe}:-Wno-c++98-compat-pedantic> + $<${is_gnu_fe}:-Wno-c++98-c++11-compat-pedantic> + $<${is_gnu_fe}:-Wno-float-equal> + $<${is_gnu_fe}:-Wno-deprecated-declarations> + $<${is_gnu_fe}:-Wno-atomic-implicit-seq-cst> # Clang 10 also throws up warnings we need to investigate (ours) - $<$>:-Wno-cast-align> - $<$>:-Wno-sign-conversion> - $<$>:-Wno-implicit-int-conversion> - $<$>:-Wno-shift-sign-overflow> - $<$>:-Wno-format-nonliteral> - $<$>:-Wno-reserved-identifier> - $<$>:-Wno-cast-function-type> + $<${is_gnu_fe}:-Wno-cast-align> + $<${is_gnu_fe}:-Wno-sign-conversion> + $<${is_gnu_fe}:-Wno-implicit-int-conversion> + $<${is_gnu_fe}:-Wno-shift-sign-overflow> + $<${is_gnu_fe}:-Wno-format-nonliteral> + $<${is_gnu_fe}:-Wno-reserved-identifier> + $<${is_gnu_fe}:-Wno-cast-function-type> - $<$:-Wdocumentation>) + # Force DWARF4 for Valgrind profiling + $<$,${is_clang}>:-gdwarf-4> - target_link_options(${NAME} + # Disable non-portable Windows.h warning (fixing it fails builds on MinGW) + $<$,${is_clang}>:-Wno-nonportable-system-include-path>) + + target_link_options(${ASTCENC_TARGET_NAME} PRIVATE # Use pthreads on Linux/macOS $<$:-pthread>) - if(${ASAN}) - target_compile_options(${NAME} + if(${ASTCENC_ASAN}) + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE - $<$:-fsanitize=address>) + $<${is_clang}:-fsanitize=address>) - target_link_options(${NAME} + target_link_options(${ASTCENC_TARGET_NAME} PRIVATE - $<$:-fsanitize=address>) + $<${is_clang}:-fsanitize=address>) endif() - if(${NO_INVARIANCE}) - target_compile_definitions(${NAME} - PRIVATE - ASTCENC_NO_INVARIANCE=1) + if(NOT ${ASTCENC_INVARIANCE}) + target_compile_definitions(${ASTCENC_TARGET_NAME} + PRIVATE + ASTCENC_NO_INVARIANCE=1) + + # For Visual Studio prior to 2022 (compiler < 19.30) /fp:precise + # For Visual Studio 2022 (compiler >= 19.30) /fp:precise and /fp:contract + + # For Visual Studio 2022 ClangCL seems to have accidentally enabled contraction by default, + # so behaves differently to CL.exe. Use the -Xclang argument to workaround and allow access + # GNU-style switch to control contraction on the assumption this gets fixed and disabled. + # Note ClangCL does not accept /fp:contract as an argument as of v15.0.7. + target_compile_options(${ASTCENC_TARGET_NAME} + PRIVATE + $<${is_msvccl}:/fp:precise> + $<${is_clangcl}:/fp:precise> + $<$,19.30>>:/fp:contract> + $<$,14.0.0>>:-Xclang -ffp-contract=fast> + $<$,10.0.0>>:-ffp-model=precise> + $<${is_gnu_fe}:-ffp-contract=fast>) + else() + # For Visual Studio prior to 2022 (compiler < 19.30) /fp:strict + # For Visual Studio 2022 (compiler >= 19.30) /fp:precise + + # For Visual Studio 2022 ClangCL seems to have accidentally enabled contraction by default, + # so behaves differently to CL.exe. Use the -Xclang argument to workaround and allow access + # GNU-style switch to control contraction and force disable. + target_compile_options(${ASTCENC_TARGET_NAME} + PRIVATE + $<$,19.30>>:/fp:strict> + $<$,19.30>>:/fp:precise> + $<${is_clangcl}:/fp:precise> + $<$,14.0.0>>:-Xclang -ffp-contract=off> + $<$,10.0.0>>:-ffp-model=precise> + $<${is_gnu_fe}:-ffp-contract=off>) endif() - if(${CLI}) + if(${ASTCENC_CLI}) # Enable LTO on release builds - set_property(TARGET ${NAME} + set_property(TARGET ${ASTCENC_TARGET_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE True) # Use a static runtime on MSVC builds (ignored on non-MSVC compilers) - set_property(TARGET ${NAME} + set_property(TARGET ${ASTCENC_TARGET_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() # Set up configuration for SIMD ISA builds - if(${ISA_SIMD} MATCHES "none") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${NAME} + if(${ASTCENC_ISA_SIMD} MATCHES "none") + target_compile_definitions(${ASTCENC_TARGET_NAME} + PRIVATE + ASTCENC_NEON=0 + ASTCENC_SSE=0 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) + + elseif(${ASTCENC_ISA_SIMD} MATCHES "neon") + target_compile_definitions(${ASTCENC_TARGET_NAME} + PRIVATE + ASTCENC_NEON=1 + ASTCENC_SSE=0 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) + + # Workaround MSVC codegen bug for NEON builds on VS 2022 17.2 or older + # https://developercommunity.visualstudio.com/t/inlining-turns-constant-into-register-operand-for/1394798 + if((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND (MSVC_VERSION LESS 1933)) + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=0 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) + $<${is_msvccl}:/d2ssa-cfg-sink->) endif() - elseif(${ISA_SIMD} MATCHES "neon") - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${NAME} - PRIVATE - ASTCENC_NEON=1 - ASTCENC_SSE=0 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) - endif() + elseif(${ASTCENC_ISA_SIMD} MATCHES "sse2") + target_compile_definitions(${ASTCENC_TARGET_NAME} + PRIVATE + ASTCENC_NEON=0 + ASTCENC_SSE=20 + ASTCENC_AVX=0 + ASTCENC_POPCNT=0 + ASTCENC_F16C=0) + + # Force SSE2 on AppleClang (normally SSE4.1 is the default) + target_compile_options(${ASTCENC_TARGET_NAME} + PRIVATE + $<${is_clangcl}:-msse2> + $<${is_gnu_fe}:-msse2> + $<${is_gnu_fe}:-mno-sse4.1> + $<${is_gnu_fe}:-Wno-unused-command-line-argument>) - elseif((${ISA_SIMD} MATCHES "sse2") OR (${UNIVERSAL_BUILD} AND ${ISA_SSE2})) - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${NAME} + elseif(${ASTCENC_ISA_SIMD} MATCHES "sse4.1") + target_compile_definitions(${ASTCENC_TARGET_NAME} + PRIVATE + ASTCENC_NEON=0 + ASTCENC_SSE=41 + ASTCENC_AVX=0 + ASTCENC_POPCNT=1 + ASTCENC_F16C=0) + + if (${ASTCENC_IS_VENEER}) + # Force SSE2 on AppleClang (normally SSE4.1 is the default) + target_compile_options(${ASTCENC_TARGET_NAME} + PRIVATE + $<${is_gnu_fe}:-msse2> + $<${is_gnu_fe}:-mno-sse4.1> + $<${is_gnu_fe}:-Wno-unused-command-line-argument>) + else() + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=20 - ASTCENC_AVX=0 - ASTCENC_POPCNT=0 - ASTCENC_F16C=0) + $<${is_clangcl}:-msse4.1 -mpopcnt> + $<${is_gnu_fe}:-msse4.1 -mpopcnt> + $<${is_gnu_fe}:-Wno-unused-command-line-argument>) endif() - # These settings are needed on AppleClang as SSE4.1 is on by default - # Suppress unused argument for macOS universal build behavior - target_compile_options(${NAME} + elseif(${ASTCENC_ISA_SIMD} MATCHES "avx2") + target_compile_definitions(${ASTCENC_TARGET_NAME} PRIVATE - $<$:-msse2> - $<$:-mno-sse4.1> - $<$:-Wno-unused-command-line-argument>) - - elseif((${ISA_SIMD} MATCHES "sse4.1") OR (${UNIVERSAL_BUILD} AND ${ISA_SSE41})) - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${NAME} + ASTCENC_NEON=0 + ASTCENC_SSE=41 + ASTCENC_AVX=2 + ASTCENC_POPCNT=1 + ASTCENC_F16C=1) + + if (${ASTCENC_IS_VENEER}) + # Force SSE2 on AppleClang (normally SSE4.1 is the default) + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=41 - ASTCENC_AVX=0 - ASTCENC_POPCNT=1 - ASTCENC_F16C=0) + $<${is_gnu_fe}:-msse2> + $<${is_gnu_fe}:-mno-sse4.1> + $<${is_gnu_fe}:-Wno-unused-command-line-argument>) + else() + target_compile_options(${ASTCENC_TARGET_NAME} + PRIVATE + $<${is_msvc_fe}:/arch:AVX2> + $<${is_clangcl}:-mavx2 -mpopcnt -mf16c> + $<${is_gnu_fe}:-mavx2 -mpopcnt -mf16c> + $<${is_gnu_fe}:-Wno-unused-command-line-argument>) endif() - # Suppress unused argument for macOS universal build behavior - target_compile_options(${NAME} - PRIVATE - $<$>:-msse4.1 -mpopcnt> - $<$:-Wno-unused-command-line-argument>) - - elseif((${ISA_SIMD} MATCHES "avx2") OR (${UNIVERSAL_BUILD} AND ${ISA_AVX2})) - if(NOT ${UNIVERSAL_BUILD}) - target_compile_definitions(${NAME} + # Non-invariant builds enable us to loosen the compiler constraints on + # floating point, but this is only worth doing on CPUs with AVX2 because + # this implies we can also enable the FMA instruction set extensions + # which significantly improve performance. Note that this DOES reduce + # image quality by up to 0.2 dB (normally much less), but buys an + # average of 10-15% performance improvement ... + if((NOT ${ASTCENC_INVARIANCE}) AND (NOT ${ASTCENC_IS_VENEER})) + target_compile_options(${ASTCENC_TARGET_NAME} PRIVATE - ASTCENC_NEON=0 - ASTCENC_SSE=41 - ASTCENC_AVX=2 - ASTCENC_POPCNT=1 - ASTCENC_F16C=1) + $<${is_gnu_fe}:-mfma>) endif() - # Suppress unused argument for macOS universal build behavior - target_compile_options(${NAME} - PRIVATE - $<$>:-mavx2 -mpopcnt -mf16c> - $<$:/arch:AVX2> - $<$:-Wno-unused-command-line-argument>) - endif() endmacro() -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - string(CONCAT EXTERNAL_CXX_FLAGS - " $<$>: -fno-strict-aliasing>" - " $<$>: -Wno-unused-parameter>" - " $<$>: -Wno-old-style-cast>" - " $<$>: -Wno-double-promotion>" - " $<$>: -Wno-zero-as-null-pointer-constant>" - " $<$>: -Wno-disabled-macro-expansion>" - " $<$>: -Wno-reserved-id-macro>" - " $<$>: -Wno-extra-semi-stmt>" - " $<$>: -Wno-implicit-fallthrough>" - " $<$>: -Wno-tautological-type-limit-compare>" - " $<$>: -Wno-cast-qual>" - " $<$>: -Wno-reserved-identifier>" - " $<$: -Wno-missing-prototypes>" - " $<$>: -Wno-suggest-override>" - " $<$>: -Wno-used-but-marked-unused>" - " $<$>: -Wno-noexcept-type>" - " $<$>: -Wno-comma>" - " $<$>: -Wno-c99-extensions>") - - set_source_files_properties(astcenccli_image_external.cpp - PROPERTIES - COMPILE_FLAGS ${EXTERNAL_CXX_FLAGS}) +string(CONCAT EXTERNAL_CXX_FLAGS + " $<${is_gnu_fe}: -fno-strict-aliasing>" + " $<${is_gnu_fe}: -Wno-unused-parameter>" + " $<${is_gnu_fe}: -Wno-old-style-cast>" + " $<${is_gnu_fe}: -Wno-double-promotion>" + " $<${is_gnu_fe}: -Wno-zero-as-null-pointer-constant>" + " $<${is_gnu_fe}: -Wno-disabled-macro-expansion>" + " $<${is_gnu_fe}: -Wno-reserved-id-macro>" + " $<${is_gnu_fe}: -Wno-extra-semi-stmt>" + " $<${is_gnu_fe}: -Wno-implicit-fallthrough>" + " $<${is_gnu_fe}: -Wno-tautological-type-limit-compare>" + " $<${is_gnu_fe}: -Wno-cast-qual>" + " $<${is_gnu_fe}: -Wno-reserved-identifier>" + " $<${is_clang}: -Wno-missing-prototypes>" + " $<${is_gnu_fe}: -Wno-missing-field-initializers>" + " $<${is_gnu_fe}: -Wno-suggest-override>" + " $<${is_gnu_fe}: -Wno-used-but-marked-unused>" + " $<${is_gnu_fe}: -Wno-noexcept-type>" + " $<${is_gnu_fe}: -Wno-comma>" + " $<${is_gnu_fe}: -Wno-c99-extensions>") + +set_source_files_properties(astcenccli_image_external.cpp + PROPERTIES + COMPILE_FLAGS ${EXTERNAL_CXX_FLAGS}) + +astcenc_set_properties(${ASTCENC_TARGET}-static OFF) + +target_compile_options(${ASTCENC_TARGET}-static + PRIVATE + $<${is_msvc_fe}:/W4>) + +if(${ASTCENC_SHAREDLIB}) + astcenc_set_properties(${ASTCENC_TARGET}-shared OFF) + + target_compile_definitions(${ASTCENC_TARGET}-shared + PRIVATE + ASTCENC_DYNAMIC_LIBRARY=1) + + target_compile_options(${ASTCENC_TARGET}-shared + PRIVATE + $<${is_gnu_fe}:-fvisibility=hidden> + $<${is_msvc_fe}:/W4>) + + if(NOT ${ASTCENC_UNIVERSAL_BUILD}) + install(TARGETS ${ASTCENC_TARGET}-shared) + endif() endif() -astcenc_set_properties(${ASTC_TARGET}-static) +if(${ASTCENC_CLI}) + astcenc_set_properties(${ASTCENC_TARGET}-veneer ON) + astcenc_set_properties(${ASTCENC_TARGET} OFF) -if(${CLI}) - astcenc_set_properties(${ASTC_TARGET}) + target_compile_options(${ASTCENC_TARGET} + PRIVATE + $<${is_msvc_fe}:/W3>) + + target_compile_options(${ASTCENC_TARGET}-veneer + PRIVATE + $<${is_msvc_fe}:/W3>) string(TIMESTAMP astcencoder_YEAR "%Y") @@ -289,9 +432,11 @@ if(${CLI}) astcenccli_version.h ESCAPE_QUOTES @ONLY) - target_include_directories(${ASTC_TARGET} + target_include_directories(${ASTCENC_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) - install(TARGETS ${ASTC_TARGET} DESTINATION ${PACKAGE_ROOT}) + if(NOT ${ASTCENC_UNIVERSAL_BUILD}) + install(TARGETS ${ASTCENC_TARGET}) + endif() endif() diff --git a/Source/stb_image.h b/Source/stb_image.h index 0f8459a..5e807a0 100644 --- a/Source/stb_image.h +++ b/Source/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb +/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: @@ -48,6 +48,7 @@ LICENSE RECENT REVISION HISTORY: + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings @@ -108,7 +109,7 @@ RECENT REVISION HISTORY: Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus - Josh Tobin Matthew Gregan github:poppolopoppo + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Brad Weinberger Matvey Cherevko github:mosra @@ -140,7 +141,7 @@ RECENT REVISION HISTORY: // // ... x = width, y = height, n = # 8-bit components per pixel ... // // ... replace '0' with '1'..'4' to force that many components per pixel // // ... but 'n' will always be the number that it would have been if you said 0 -// stbi_image_free(data) +// stbi_image_free(data); // // Standard parameters: // int *x -- outputs image width in pixels @@ -635,7 +636,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch #endif #endif -#ifdef _MSC_VER +#if defined(_MSC_VER) || defined(__SYMBIAN32__) typedef unsigned short stbi__uint16; typedef signed short stbi__int16; typedef unsigned int stbi__uint32; @@ -1032,7 +1033,7 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && @@ -1055,7 +1056,7 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) return stbi__malloc(a*b*c + add); } -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) { if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; @@ -1063,6 +1064,23 @@ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) } #endif +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two signed shorts is valid, 0 on overflow. +static int stbi__mul2shorts_valid(short a, short b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char @@ -1985,9 +2003,12 @@ static int stbi__build_huffman(stbi__huffman *h, int *count) int i,j,k=0; unsigned int code; // build size list for each symbol (from JPEG spec) - for (i=0; i < 16; ++i) - for (j=0; j < count[i]; ++j) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } h->size[k] = 0; // compute actual symbols (from jpeg spec) @@ -2112,6 +2133,8 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) // convert the huffman code to the symbol id c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); // convert the id to a symbol @@ -2130,6 +2153,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n) unsigned int k; int sgn; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) k = stbi_lrot(j->code_buffer, n); @@ -2144,6 +2168,7 @@ stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) { unsigned int k; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; @@ -2155,6 +2180,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) { unsigned int k; if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing k = j->code_buffer; j->code_buffer <<= 1; --j->code_bits; @@ -2192,8 +2218,10 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman memset(data,0,64*sizeof(data[0])); diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * dequant[0]); // decode AC components, see JPEG spec @@ -2207,6 +2235,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; // decode into unzigzag'd location @@ -2246,8 +2275,10 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * (1 << j->succ_low)); } else { // refinement scan for DC coefficient @@ -2282,6 +2313,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__ if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; zig = stbi__jpeg_dezigzag[k++]; @@ -3102,6 +3134,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m) sizes[i] = stbi__get8(z->s); n += sizes[i]; } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! L -= 17; if (tc == 0) { if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; @@ -3267,6 +3300,13 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; } + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + // compute interleaved mcu info z->img_h_max = h_max; z->img_v_max = v_max; @@ -3344,6 +3384,28 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) return 1; } +static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + while (x == 255) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + // decode image to YCbCr format static int stbi__decode_jpeg_image(stbi__jpeg *j) { @@ -3360,25 +3422,22 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) if (!stbi__process_scan_header(j)) return 0; if (!stbi__parse_entropy_coded_data(j)) return 0; if (j->marker == STBI__MARKER_none ) { - // handle 0s at the end of image data from IP Kamera 9060 - while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - if (x == 255) { - j->marker = stbi__get8(j->s); - break; - } - } + j->marker = stbi__skip_jpeg_junk_at_end(j); // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); } else if (stbi__DNL(m)) { int Ld = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); } else { - if (!stbi__process_marker(j, m)) return 0; + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); } - m = stbi__get_marker(j); } if (j->progressive) stbi__jpeg_finish(j); @@ -3969,6 +4028,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); @@ -3982,6 +4042,7 @@ static int stbi__jpeg_test(stbi__context *s) int r; stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); j->s = s; stbi__setup_jpeg(j); r = stbi__decode_jpeg_header(j, STBI__SCAN_type); @@ -4007,6 +4068,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) int result; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); j->s = s; result = stbi__jpeg_info_raw(j, x, y, comp); STBI_FREE(j); @@ -4249,11 +4311,12 @@ static int stbi__parse_huffman_block(stbi__zbuf *a) a->zout = zout; return 1; } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); @@ -4948,7 +5011,7 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; -STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; stbi__unpremultiply_on_load_set = 1; @@ -5057,14 +5120,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!pal_img_n) { s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); - if (scan == STBI__SCAN_header) return 1; } else { // if paletted, then pal_n is our final components, and // img_n is # components to decompress/filter. s->img_n = 1; if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); - // if SCAN_header, have to scan to see if we have a tRNS } + // even with SCAN_header, have to scan to see if we have a tRNS break; } @@ -5096,6 +5158,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (z->depth == 16) { for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { @@ -5108,7 +5172,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); - if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { stbi__uint32 idata_limit_old = idata_limit; @@ -5491,8 +5561,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req psize = (info.offset - info.extra_read - info.hsz) >> 2; } if (psize == 0) { - if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { - return stbi__errpuc("bad offset", "Corrupt BMP"); + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); } } @@ -7180,12 +7264,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re // Run value = stbi__get8(s); count -= 128; - if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump - if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } @@ -7439,10 +7523,17 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); - stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } if (req_comp && req_comp != s->img_n) { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } if (out == NULL) return out; // stbi__convert_format frees input on failure } return out; @@ -7479,6 +7570,8 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { value = value*10 + (*c - '0'); *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); } return value; @@ -7509,9 +7602,13 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) stbi__pnm_skip_whitespace(s, &c); *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); maxv = stbi__pnm_getinteger(s, &c); // read max value diff --git a/Source/stb_image_write.h b/Source/stb_image_write.h index 314e162..e4b32ed 100644 --- a/Source/stb_image_write.h +++ b/Source/stb_image_write.h @@ -511,7 +511,7 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_bmp_core(&s, x, y, comp, data); } @@ -519,7 +519,7 @@ STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_bmp_core(&s, x, y, comp, data); stbi__end_write_file(&s); @@ -610,7 +610,7 @@ static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, v STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_tga_core(&s, x, y, comp, (void *) data); } @@ -618,7 +618,7 @@ STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); stbi__end_write_file(&s); @@ -786,14 +786,14 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); stbi__end_write_file(&s); @@ -1606,7 +1606,7 @@ static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, in STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); } @@ -1615,7 +1615,7 @@ STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) { - stbi__write_context s {}; + stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); stbi__end_write_file(&s); diff --git a/Source/wuffs-v0.3.c b/Source/wuffs-v0.3.c index 11db258..76aea8d 100644 --- a/Source/wuffs-v0.3.c +++ b/Source/wuffs-v0.3.c @@ -21987,15 +21987,25 @@ wuffs_adler32__hasher__up_arm_neon( } v_p.len = 0; } + + static const uint16x4_t table_0 {32, 31, 30, 29}; + static const uint16x4_t table_1 {28, 27, 26, 25}; + static const uint16x4_t table_2 {24, 23, 22, 21}; + static const uint16x4_t table_3 {20, 19, 18, 17}; + static const uint16x4_t table_4 {16, 15, 14, 13}; + static const uint16x4_t table_5 {12, 11, 10, 9}; + static const uint16x4_t table_6 { 8, 7, 6, 5}; + static const uint16x4_t table_7 { 4, 3, 2, 1}; + v_v2 = vshlq_n_u32(v_v2, 5); - v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), ((uint16x4_t){32, 31, 30, 29})); - v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), ((uint16x4_t){28, 27, 26, 25})); - v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), ((uint16x4_t){24, 23, 22, 21})); - v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), ((uint16x4_t){20, 19, 18, 17})); - v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), ((uint16x4_t){16, 15, 14, 13})); - v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), ((uint16x4_t){12, 11, 10, 9})); - v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), ((uint16x4_t){8, 7, 6, 5})); - v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), ((uint16x4_t){4, 3, 2, 1})); + v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), table_0); + v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), table_1); + v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), table_2); + v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), table_3); + v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), table_4); + v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), table_5); + v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), table_6); + v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), table_7); v_sum1 = vpadd_u32(vget_low_u32(v_v1), vget_high_u32(v_v1)); v_sum2 = vpadd_u32(vget_low_u32(v_v2), vget_high_u32(v_v2)); v_sum12 = vpadd_u32(v_sum1, v_sum2); diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index e7bc1f3..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.4642,0.9206,0.1086,5.4306 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6113,0.9023,0.1042,5.6594 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1249,0.9088,0.1151,5.1237 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.8620,0.9039,0.1064,5.5433 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4006,0.9604,0.1386,4.2548 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4855,0.9261,0.1123,5.2511 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8798,0.9130,0.1129,5.2252 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5073,0.9110,0.1164,5.0690 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9690,0.9134,0.1130,5.2194 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8563,0.9531,0.1314,4.4902 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9117,0.9368,0.1226,4.8125 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9417,0.9174,0.1235,4.7743 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6901,0.9159,0.1247,4.7282 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6034,0.9219,0.1237,4.7695 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4690,0.9657,0.1410,4.1836 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6259,1.0036,0.1842,3.2028 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.0949,0.9746,0.1730,3.4098 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4004,0.9796,0.1780,3.3143 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5218,0.9778,0.1735,3.3987 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6552,1.0249,0.1933,3.0509 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2083,1.0440,0.2153,2.7398 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1174,1.0073,0.1992,2.9616 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3098,1.0129,0.2058,2.8664 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7317,1.0167,0.2065,2.8566 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0473,1.0679,0.2263,2.6068 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index 23c1756..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2326,0.8834,0.0732,8.0546 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2416,0.8664,0.0739,7.9788 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4153,0.8676,0.0738,7.9926 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.6138,0.8715,0.0738,7.9920 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.0126,0.9023,0.0794,7.4294 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3165,0.8916,0.0804,7.3356 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4653,0.8779,0.0810,7.2802 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0821,0.8755,0.0807,7.3127 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7249,0.8807,0.0825,7.1537 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.4955,0.9102,0.0845,6.9824 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8196,0.8892,0.0779,7.5716 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6921,0.8750,0.0797,7.4031 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4519,0.8730,0.0779,7.5736 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3978,0.8744,0.0797,7.3992 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3170,0.9022,0.0810,7.2811 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5303,0.9379,0.1203,4.9045 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8147,0.9207,0.1202,4.9074 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1762,0.9168,0.1183,4.9860 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3622,0.9242,0.1215,4.8552 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.5936,0.9590,0.1270,4.6442 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1316,0.9686,0.1448,4.0723 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6209,0.9452,0.1410,4.1826 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0262,0.9435,0.1409,4.1869 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6170,0.9515,0.1447,4.0759 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0061,0.9935,0.1550,3.8064 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index 4d5d22d..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6813,1.0152,0.1984,2.9722 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9798,0.9898,0.1927,3.0610 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5307,1.0064,0.2162,2.7282 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2443,0.9997,0.1979,2.9801 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.7736,1.0887,0.2683,2.1981 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5886,1.0282,0.2159,2.7315 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2735,1.0275,0.2244,2.6287 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0266,1.0367,0.2354,2.5060 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1990,1.0237,0.2220,2.6565 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0853,1.1085,0.2788,2.1153 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9799,1.0462,0.2313,2.5503 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3967,1.0207,0.2245,2.6272 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2283,1.0421,0.2421,2.4367 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7624,1.0325,0.2280,2.5873 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6249,1.1214,0.2926,2.0159 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7193,1.1333,0.3106,1.8989 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5399,1.0800,0.2739,2.1533 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,1.1059,0.3027,1.9487 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6493,1.1016,0.2954,1.9965 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7364,1.1932,0.3560,1.6567 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2550,1.2301,0.3959,1.4897 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3419,1.1312,0.3167,1.8626 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5225,1.1784,0.3665,1.6095 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8200,1.1691,0.3549,1.6619 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0791,1.2708,0.4258,1.3853 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index e682b84..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8140,1.2786,0.4654,1.2672 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3108,1.2803,0.4840,1.2185 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0416,1.2881,0.4957,1.1898 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4415,1.2576,0.4593,1.2841 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9172,1.3825,0.5584,1.0563 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6414,1.3319,0.5165,1.1419 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.5164,1.3635,0.5626,1.0484 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4423,1.3605,0.5630,1.0477 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3342,1.3238,0.5249,1.1236 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2127,1.4354,0.6116,0.9644 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0206,1.4166,0.6002,0.9827 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.5914,1.4251,0.6261,0.9421 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5720,1.4318,0.6347,0.9293 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8656,1.4023,0.6044,0.9758 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7315,1.5346,0.7063,0.8351 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7638,1.5949,0.7743,0.7618 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7385,1.5035,0.6977,0.8454 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0389,1.5403,0.7381,0.7991 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7390,1.5266,0.7178,0.8218 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8113,1.7122,0.8752,0.6739 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2896,1.7554,0.9179,0.6426 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5190,1.5453,0.7246,0.8140 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7063,1.6414,0.8256,0.7145 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8774,1.6395,0.8212,0.7183 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1152,1.8808,1.0319,0.5716 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index 7f7fcfc..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.4642,0.9467,0.1363,4.3277 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6113,0.9284,0.1309,4.5048 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1249,0.9385,0.1436,4.1086 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.8620,0.9319,0.1331,4.4325 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4006,0.9953,0.1724,3.4211 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4855,0.9690,0.1534,3.8461 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8798,0.9525,0.1534,3.8443 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5073,0.9539,0.1578,3.7371 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9690,0.9547,0.1531,3.8532 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8563,1.0047,0.1788,3.2995 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9117,0.9980,0.1808,3.2631 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9417,0.9821,0.1812,3.2554 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6901,0.9781,0.1823,3.2348 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6034,0.9832,0.1806,3.2657 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4690,1.0337,0.2048,2.8804 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6259,1.0986,0.2734,2.1570 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.0949,1.0655,0.2576,2.2900 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4004,1.0731,0.2682,2.1989 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5218,1.0685,0.2607,2.2623 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6552,1.1252,0.2871,2.0544 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2083,1.1537,0.3238,1.8215 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1174,1.1093,0.2999,1.9665 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3098,1.1162,0.3092,1.9078 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7317,1.1237,0.3094,1.9064 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0473,1.1800,0.3385,1.7423 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index 5edf0b2..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2326,0.9060,0.0936,6.3045 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2416,0.8912,0.0937,6.2929 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4153,0.8881,0.0941,6.2703 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.6138,0.8931,0.0942,6.2615 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.0126,0.9247,0.1013,5.8225 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3165,0.9240,0.1109,5.3166 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4653,0.9099,0.1119,5.2715 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0821,0.9071,0.1110,5.3134 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7249,0.9123,0.1121,5.2598 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.4955,0.9404,0.1154,5.1095 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8196,0.9275,0.1130,5.2215 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6921,0.9147,0.1153,5.1166 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4519,0.9091,0.1130,5.2177 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3978,0.9152,0.1149,5.1337 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3170,0.9432,0.1167,5.0546 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5303,0.9951,0.1753,3.3650 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8147,0.9780,0.1750,3.3697 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1762,0.9739,0.1732,3.4059 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3622,0.9824,0.1776,3.3203 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.5936,1.0191,0.1866,3.1608 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1316,1.0419,0.2144,2.7516 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6209,1.0192,0.2113,2.7921 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0262,1.0160,0.2102,2.8064 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6170,1.0268,0.2166,2.7231 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0061,1.0702,0.2301,2.5638 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index 64dbf42..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6813,1.0841,0.2661,2.2164 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9798,1.0610,0.2612,2.2584 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5307,1.0883,0.2923,2.0177 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2443,1.0682,0.2673,2.2069 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.7736,1.1871,0.3598,1.6392 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5886,1.1287,0.3134,1.8818 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2735,1.1319,0.3276,1.8003 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0266,1.1436,0.3455,1.7071 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1990,1.1306,0.3256,1.8118 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0853,1.2347,0.4070,1.4490 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9799,1.1702,0.3495,1.6877 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3967,1.1431,0.3414,1.7275 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2283,1.1688,0.3681,1.6022 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7624,1.1525,0.3465,1.7024 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6249,1.2719,0.4421,1.3342 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7193,1.3044,0.4816,1.2246 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5399,1.2323,0.4252,1.3872 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,1.2743,0.4709,1.2526 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6493,1.2624,0.4562,1.2929 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7364,1.3818,0.5486,1.0752 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2550,1.4356,0.6055,0.9742 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3419,1.3001,0.4875,1.2099 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5225,1.3711,0.5605,1.0523 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8200,1.3601,0.5422,1.0878 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0791,1.4984,0.6513,0.9057 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index 46fe116..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8140,1.4350,0.6193,0.9524 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3108,1.4526,0.6532,0.9030 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0416,1.4670,0.6700,0.8804 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4415,1.4204,0.6200,0.9514 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9172,1.5700,0.7472,0.7894 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6414,1.5601,0.7446,0.7922 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.5164,1.6150,0.8121,0.7263 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4423,1.6092,0.8127,0.7257 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3342,1.5609,0.7556,0.7806 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2127,1.7099,0.8809,0.6696 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0206,1.7151,0.8957,0.6585 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.5914,1.7311,0.9290,0.6349 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5720,1.7488,0.9474,0.6226 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8656,1.7043,0.9018,0.6541 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7315,1.8778,1.0479,0.5629 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7638,2.0126,1.1857,0.4975 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7385,1.8810,1.0719,0.5502 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0389,1.9360,1.1320,0.5210 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7390,1.9138,1.1054,0.5336 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8113,2.1880,1.3469,0.4379 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2896,2.2359,1.3992,0.4215 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5190,1.9326,1.1153,0.5289 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7063,2.0784,1.2631,0.4670 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8774,2.0728,1.2533,0.4706 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1152,2.4112,1.5651,0.3769 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index fd65f8c..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.4642,0.9349,0.1215,4.8552 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6113,0.9154,0.1171,5.0354 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1249,0.9239,0.1284,4.5924 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.8620,0.9187,0.1184,4.9800 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4006,0.9803,0.1542,3.8248 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4855,0.9477,0.1327,4.4461 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8798,0.9348,0.1335,4.4189 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5073,0.9350,0.1373,4.2959 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9690,0.9350,0.1330,4.4341 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8563,0.9812,0.1558,3.7849 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9117,0.9740,0.1576,3.7418 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9417,0.9586,0.1579,3.7349 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6901,0.9566,0.1589,3.7111 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6034,0.9586,0.1571,3.7548 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4690,1.0069,0.1779,3.3146 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6259,1.0635,0.2402,2.4553 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.0949,1.0317,0.2274,2.5933 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4004,1.0395,0.2340,2.5210 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5218,1.0347,0.2271,2.5977 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6552,1.0872,0.2511,2.3487 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2083,1.1156,0.2853,2.0673 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1174,1.0738,0.2647,2.2281 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3098,1.0843,0.2727,2.1627 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7317,1.0871,0.2721,2.1680 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0473,1.1433,0.2984,1.9766 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 7c28cf2..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2326,0.8925,0.0828,7.1221 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2416,0.8796,0.0829,7.1145 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4153,0.8771,0.0830,7.1040 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.6138,0.8800,0.0830,7.1094 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.0126,0.9129,0.0899,6.5637 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3165,0.9087,0.0957,6.1635 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4653,0.8948,0.0965,6.1136 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0821,0.8909,0.0962,6.1328 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7249,0.8958,0.0964,6.1191 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.4955,0.9245,0.0994,5.9329 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8196,0.9113,0.0982,6.0056 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6921,0.8973,0.1003,5.8804 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4519,0.8922,0.0987,5.9764 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3978,0.8989,0.0997,5.9157 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3170,0.9262,0.1018,5.7928 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5303,0.9712,0.1539,3.8330 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8147,0.9563,0.1535,3.8420 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1762,0.9496,0.1499,3.9360 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3622,0.9614,0.1556,3.7901 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.5936,0.9963,0.1630,3.6182 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1316,1.0145,0.1901,3.1022 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6209,0.9923,0.1861,3.1699 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0262,0.9907,0.1852,3.1845 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6170,0.9988,0.1919,3.0730 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0061,1.0422,0.2040,2.8913 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 7908270..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6813,1.0485,0.2338,2.5226 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9798,1.0310,0.2281,2.5855 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5307,1.0563,0.2549,2.3139 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2443,1.0411,0.2330,2.5316 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.7736,1.1405,0.3145,1.8756 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5886,1.0881,0.2695,2.1888 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2735,1.0834,0.2816,2.0946 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0266,1.0971,0.2964,1.9901 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1990,1.0846,0.2788,2.1152 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0853,1.1794,0.3502,1.6841 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9799,1.1205,0.3011,1.9590 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3967,1.0966,0.2921,2.0192 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2283,1.1184,0.3173,1.8590 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7624,1.1048,0.2979,1.9796 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6249,1.2150,0.3838,1.5369 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7193,1.2415,0.4217,1.3986 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5399,1.1818,0.3740,1.5773 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,1.2190,0.4116,1.4330 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6493,1.2074,0.4001,1.4742 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7364,1.3194,0.4816,1.2247 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2550,1.3714,0.5360,1.1005 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3419,1.2455,0.4300,1.3717 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5225,1.3058,0.4948,1.1920 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8200,1.2958,0.4783,1.2333 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0791,1.4251,0.5758,1.0243 diff --git a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 3d7af90..0000000 --- a/Test/Images/HDRIHaven/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,26 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8140,1.3668,0.5496,1.0731 -HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3108,1.3742,0.5744,1.0268 -HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0416,1.3844,0.5893,1.0009 -HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4415,1.3448,0.5442,1.0839 -HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9172,1.4844,0.6601,0.8936 -HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6414,1.4673,0.6500,0.9074 -HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.5164,1.5132,0.7083,0.8327 -HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4423,1.5122,0.7090,0.8319 -HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3342,1.4652,0.6606,0.8928 -HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2127,1.5933,0.7676,0.7684 -HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0206,1.5996,0.7801,0.7561 -HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.5914,1.6176,0.8131,0.7254 -HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5720,1.6268,0.8284,0.7120 -HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8656,1.5934,0.7870,0.7494 -HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7315,1.7475,0.9170,0.6432 -HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7638,1.8698,1.0465,0.5636 -HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7385,1.7500,0.9440,0.6248 -HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0389,1.8071,1.0011,0.5892 -HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7390,1.7833,0.9732,0.6061 -HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8113,2.0260,1.1907,0.4954 -HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2896,2.0752,1.2384,0.4763 -HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5190,1.8057,0.9886,0.5966 -HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7063,1.9364,1.1189,0.5272 -HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8774,1.9304,1.1109,0.5310 -HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1152,2.2427,1.3917,0.4238 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..31933a3 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5183,0.8421,0.0887,6.6478 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6496,0.8315,0.0853,6.9175 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1806,0.8445,0.0956,6.1696 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9442,0.8358,0.0867,6.7996 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4810,0.8674,0.1186,4.9726 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4914,0.8318,0.0778,7.5826 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8696,0.8303,0.0787,7.4941 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5304,0.8328,0.0826,7.1426 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9886,0.8293,0.0781,7.5523 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8769,0.8495,0.0978,6.0323 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9125,0.8253,0.0767,7.6866 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9501,0.8287,0.0809,7.2888 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6974,0.8499,0.0871,6.7739 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6096,0.8252,0.0809,7.2903 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4848,0.8409,0.0923,6.3909 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6322,0.8621,0.1121,5.2605 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2324,0.8611,0.1112,5.3048 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4874,0.8599,0.1111,5.3100 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5558,0.8643,0.1140,5.1743 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6748,0.8745,0.1243,4.7461 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2132,0.8974,0.1455,4.0527 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1310,0.8895,0.1391,4.2388 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3229,0.8925,0.1410,4.1844 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7302,0.8993,0.1480,3.9848 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0516,0.9102,0.1587,3.7176 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..7d23a38 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2906,0.8061,0.0538,10.9559 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2770,0.8041,0.0556,10.6034 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4522,0.8038,0.0559,10.5527 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7385,0.8043,0.0549,10.7346 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1353,0.8130,0.0635,9.2887 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3714,0.8049,0.0532,11.0825 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4977,0.8028,0.0541,10.9037 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0897,0.8034,0.0539,10.9509 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7504,0.8038,0.0534,11.0363 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5270,0.8122,0.0598,9.8646 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8240,0.7991,0.0517,11.4146 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6977,0.7964,0.0511,11.5344 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4615,0.7980,0.0524,11.2538 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3650,0.7951,0.0508,11.6073 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3399,0.8016,0.0561,10.5226 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5378,0.8291,0.0778,7.5804 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8222,0.8210,0.0724,8.1516 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1845,0.8287,0.0744,7.9285 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3350,0.8249,0.0738,7.9934 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6111,0.8318,0.0847,6.9658 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1334,0.8493,0.0981,6.0141 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6166,0.8403,0.0915,6.4462 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0114,0.8417,0.0935,6.3050 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6068,0.8478,0.0977,6.0370 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0090,0.8590,0.1085,5.4348 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..57645e5 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6967,0.8917,0.1381,4.2706 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9872,0.8862,0.1381,4.2711 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5481,0.9086,0.1568,3.7610 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2746,0.8945,0.1438,4.1016 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8015,0.9469,0.1920,3.0717 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5897,0.8797,0.1264,4.6671 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2586,0.8937,0.1397,4.2232 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0351,0.8985,0.1443,4.0874 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.2103,0.8891,0.1370,4.3048 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0865,0.9240,0.1690,3.4898 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9740,0.8824,0.1327,4.4450 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3897,0.8941,0.1464,4.0275 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2248,0.9014,0.1505,3.9200 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7613,0.8937,0.1465,4.0265 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6388,0.9206,0.1685,3.5003 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7174,0.9347,0.1818,3.2437 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5395,0.9313,0.1833,3.2180 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,0.9488,0.1945,3.0318 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6514,0.9423,0.1897,3.1099 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7425,0.9624,0.2081,2.8345 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2551,1.0001,0.2434,2.4234 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3460,0.9773,0.2264,2.6047 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5142,1.0026,0.2488,2.3702 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8241,0.9929,0.2404,2.4538 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0771,1.0092,0.2552,2.3115 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..25e75a0 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8226,1.0510,0.2972,1.9845 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3071,1.0638,0.3161,1.8661 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0457,1.0919,0.3383,1.7434 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4455,1.0613,0.3117,1.8920 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9306,1.1433,0.3936,1.4987 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6472,1.0421,0.2851,2.0687 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4971,1.0836,0.3321,1.7760 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4390,1.0780,0.3304,1.7854 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3310,1.0575,0.3077,1.9169 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2247,1.1193,0.3701,1.5936 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0267,1.0532,0.3053,1.9322 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6037,1.1076,0.3576,1.6492 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5645,1.0999,0.3515,1.6779 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8686,1.0829,0.3357,1.7569 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7460,1.1268,0.3798,1.5528 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7716,1.1755,0.4190,1.4076 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7436,1.1967,0.4434,1.3303 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0304,1.2071,0.4571,1.2905 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7463,1.1927,0.4419,1.3346 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8190,1.2341,0.4767,1.2373 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2963,1.3386,0.5790,1.0187 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5470,1.2630,0.5098,1.1569 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7151,1.3345,0.5789,1.0188 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8836,1.3195,0.5665,1.0412 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1188,1.3807,0.6215,0.9491 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..d2d63fc --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5183,0.8977,0.1136,5.1909 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6496,0.8914,0.1097,5.3777 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1806,0.9059,0.1224,4.8195 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9442,0.8956,0.1116,5.2860 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4810,0.9369,0.1510,3.9056 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4914,0.8935,0.1075,5.4888 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8696,0.8904,0.1081,5.4540 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5304,0.8972,0.1136,5.1936 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9886,0.8909,0.1073,5.4969 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8769,0.9189,0.1341,4.3987 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9125,0.8985,0.1130,5.2191 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9501,0.9012,0.1192,4.9491 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6974,0.9037,0.1202,4.9071 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6096,0.9013,0.1179,5.0030 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4848,0.9190,0.1341,4.3973 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6322,0.9551,0.1705,3.4595 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2324,0.9568,0.1737,3.3965 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4874,0.9558,0.1712,3.4451 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5558,0.9571,0.1754,3.3625 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6748,0.9743,0.1891,3.1189 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2132,1.0035,0.2159,2.7315 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1310,0.9935,0.2095,2.8159 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3229,0.9974,0.2112,2.7923 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7302,1.0055,0.2209,2.6707 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0516,1.0217,0.2356,2.5036 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..ba87b42 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2906,0.8542,0.0694,8.5015 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2770,0.8533,0.0721,8.1804 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4522,0.8534,0.0722,8.1682 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7385,0.8547,0.0714,8.2651 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1353,0.8659,0.0817,7.2185 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3714,0.8568,0.0744,7.9233 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4977,0.8567,0.0752,7.8485 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0897,0.8561,0.0748,7.8864 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7504,0.8567,0.0740,7.9697 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5270,0.8660,0.0828,7.1238 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8240,0.8601,0.0772,7.6419 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6977,0.8557,0.0762,7.7444 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4615,0.8602,0.0778,7.5834 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3650,0.8566,0.0751,7.8532 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3399,0.8670,0.0832,7.0880 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5378,0.9024,0.1177,5.0108 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8222,0.8925,0.1111,5.3085 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1845,0.8973,0.1128,5.2291 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3350,0.8956,0.1121,5.2622 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6111,0.9129,0.1283,4.5972 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1334,0.9332,0.1461,4.0371 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6166,0.9214,0.1369,4.3098 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0114,0.9244,0.1399,4.2166 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6068,0.9291,0.1452,4.0633 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0090,0.9473,0.1609,3.6648 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..be730d5 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6967,0.9688,0.1804,3.2692 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9872,0.9690,0.1843,3.2001 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5481,0.9919,0.2064,2.8580 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2746,0.9747,0.1915,3.0806 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8015,1.0371,0.2509,2.3508 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5897,0.9682,0.1812,3.2544 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2586,0.9877,0.2020,2.9206 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0351,0.9964,0.2064,2.8574 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.2103,0.9845,0.1963,3.0051 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0865,1.0287,0.2410,2.4476 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9740,0.9863,0.1994,2.9584 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3897,1.0056,0.2225,2.6511 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2248,1.0112,0.2255,2.6151 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7613,1.0062,0.2219,2.6583 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6388,1.0355,0.2497,2.3621 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7174,1.0714,0.2815,2.0953 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5395,1.0739,0.2891,2.0405 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,1.0919,0.3016,1.9554 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6514,1.0799,0.2937,2.0080 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7425,1.1059,0.3198,1.8444 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2551,1.1544,0.3623,1.6280 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3460,1.1298,0.3406,1.7318 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5142,1.1642,0.3728,1.5820 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8241,1.1478,0.3600,1.6385 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0771,1.1683,0.3769,1.5650 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..f756bc5 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8226,1.1860,0.3930,1.5008 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3071,1.2120,0.4245,1.3895 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0457,1.2394,0.4491,1.3134 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4455,1.2033,0.4194,1.4065 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9306,1.3087,0.5183,1.1380 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6472,1.1900,0.4010,1.4708 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4971,1.2626,0.4771,1.2364 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4390,1.2636,0.4679,1.2605 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3310,1.2250,0.4385,1.3451 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2247,1.3242,0.5194,1.1355 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0267,1.2729,0.4619,1.2770 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6037,1.3264,0.5368,1.0988 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5645,1.3113,0.5218,1.1304 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8686,1.2886,0.4997,1.1803 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7460,1.3489,0.5572,1.0585 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7716,1.4315,0.6375,0.9253 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7436,1.4856,0.6960,0.8475 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0304,1.4995,0.7046,0.8371 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7463,1.4690,0.6816,0.8654 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8190,1.5179,0.7243,0.8144 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2963,1.6495,0.8518,0.6925 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5470,1.5601,0.7638,0.7723 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7151,1.6553,0.8607,0.6853 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8836,1.6401,0.8407,0.7016 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1188,1.7103,0.9121,0.6467 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..4906028 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5183,0.8375,0.0976,6.0429 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6496,0.8309,0.0941,6.2678 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1806,0.8434,0.1052,5.6072 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9442,0.8347,0.0959,6.1512 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4810,0.8707,0.1303,4.5283 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4914,0.8287,0.0893,6.6069 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8696,0.8280,0.0901,6.5438 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5304,0.8346,0.0943,6.2538 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9886,0.8277,0.0898,6.5657 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8769,0.8531,0.1117,5.2783 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9125,0.8354,0.0936,6.2988 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9501,0.8363,0.0984,5.9934 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6974,0.8382,0.0996,5.9244 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6096,0.8361,0.0983,6.0003 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4848,0.8533,0.1115,5.2893 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6322,0.8826,0.1423,4.1464 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2324,0.8836,0.1443,4.0874 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4874,0.8802,0.1419,4.1555 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5558,0.8856,0.1463,4.0306 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6748,0.8974,0.1580,3.7333 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2132,0.9334,0.1896,3.1109 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1310,0.9244,0.1842,3.2016 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3229,0.9278,0.1864,3.1645 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7302,0.9367,0.1941,3.0392 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0516,0.9506,0.2068,2.8518 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..7120f00 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2906,0.7990,0.0592,9.9612 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2770,0.7989,0.0614,9.6041 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4522,0.7976,0.0616,9.5813 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7385,0.7971,0.0609,9.6894 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1353,0.8086,0.0701,8.4083 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3714,0.8009,0.0614,9.6050 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4977,0.7990,0.0622,9.4774 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0897,0.7989,0.0620,9.5133 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7504,0.7988,0.0615,9.5983 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5270,0.8071,0.0688,8.5710 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8240,0.8015,0.0634,9.3057 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6977,0.7987,0.0623,9.4600 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4615,0.7996,0.0639,9.2372 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3650,0.7977,0.0621,9.5027 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3399,0.8063,0.0685,8.6155 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5378,0.8373,0.0977,6.0388 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8222,0.8319,0.0919,6.4150 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1845,0.8320,0.0935,6.3063 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3350,0.8313,0.0925,6.3766 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6111,0.8468,0.1060,5.5621 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1334,0.8697,0.1281,4.6052 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6166,0.8571,0.1199,4.9173 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0114,0.8608,0.1225,4.8147 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6068,0.8653,0.1269,4.6491 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0090,0.8808,0.1412,4.1757 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..4dfa1b4 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6967,0.8957,0.1550,3.8046 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9872,0.8975,0.1566,3.7654 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5481,0.9174,0.1758,3.3543 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2746,0.9025,0.1628,3.6220 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8015,0.9585,0.2149,2.7447 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5897,0.8930,0.1487,3.9676 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2586,0.9060,0.1659,3.5557 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0351,0.9125,0.1703,3.4632 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.2103,0.9046,0.1621,3.6391 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0865,0.9448,0.1991,2.9627 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9740,0.9065,0.1633,3.6112 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3897,0.9236,0.1812,3.2545 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2248,0.9248,0.1852,3.1844 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7613,0.9188,0.1815,3.2495 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6388,0.9486,0.2071,2.8486 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7174,0.9762,0.2337,2.5237 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5395,0.9840,0.2405,2.4521 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7977,0.9928,0.2513,2.3470 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6514,0.9896,0.2459,2.3984 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7425,1.0085,0.2658,2.2190 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2551,1.0664,0.3183,1.8532 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3460,1.0430,0.2996,1.9688 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5142,1.0712,0.3277,1.7998 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8241,1.0608,0.3158,1.8676 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0771,1.0782,0.3310,1.7820 diff --git a/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..6087f70 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8226,1.0813,0.3362,1.7544 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.3071,1.0993,0.3600,1.6382 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0457,1.1243,0.3837,1.5372 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4455,1.0970,0.3554,1.6594 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9306,1.1874,0.4438,1.3289 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6472,1.0771,0.3339,1.7664 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4971,1.1350,0.3937,1.4982 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4390,1.1311,0.3896,1.5139 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3310,1.1028,0.3635,1.6227 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2247,1.1745,0.4337,1.3599 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0267,1.1158,0.3735,1.5791 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6037,1.1794,0.4390,1.3435 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5645,1.1736,0.4312,1.3680 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8686,1.1539,0.4120,1.4316 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7460,1.2102,0.4646,1.2695 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7716,1.2802,0.5371,1.0981 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7436,1.3283,0.5809,1.0154 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0304,1.3364,0.5920,0.9963 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7463,1.3139,0.5701,1.0346 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8190,1.3580,0.6114,0.9647 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2963,1.4986,0.7526,0.7837 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5470,1.4191,0.6744,0.8747 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7151,1.5040,0.7604,0.7757 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8836,1.4908,0.7417,0.7953 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1188,1.5523,0.8051,0.7327 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..88896f2 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5079,0.8407,0.0886,6.6551 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6274,0.8317,0.0845,6.9837 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1770,0.8462,0.0950,6.2057 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9296,0.8367,0.0861,6.8505 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4914,0.8665,0.1184,4.9802 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4794,0.8293,0.0776,7.6039 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8484,0.8294,0.0779,7.5674 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5278,0.8328,0.0818,7.2112 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9680,0.8298,0.0776,7.6040 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8894,0.8484,0.0974,6.0580 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9079,0.8256,0.0760,7.7585 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9405,0.8255,0.0801,7.3633 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6946,0.8277,0.0812,7.2660 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6017,0.8275,0.0798,7.3903 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4862,0.8389,0.0912,6.4670 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6288,0.8625,0.1105,5.3399 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2302,0.8600,0.1106,5.3329 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4837,0.8614,0.1104,5.3449 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5502,0.8610,0.1128,5.2296 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6749,0.8747,0.1227,4.8062 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2114,0.8978,0.1443,4.0866 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1351,0.8862,0.1386,4.2547 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3187,0.8901,0.1399,4.2174 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7270,0.8968,0.1463,4.0312 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0489,0.9081,0.1586,3.7186 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..3f35047 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2760,0.8027,0.0538,10.9551 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2550,0.8030,0.0553,10.6751 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4452,0.8022,0.0559,10.5591 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7224,0.8045,0.0548,10.7670 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1407,0.8133,0.0636,9.2786 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3592,0.8036,0.0534,11.0475 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4640,0.8012,0.0538,10.9604 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0910,0.8041,0.0538,10.9618 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7259,0.8014,0.0534,11.0390 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5353,0.8093,0.0596,9.8987 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8191,0.7985,0.0513,11.4868 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6923,0.7937,0.0508,11.6103 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4640,0.7996,0.0522,11.2948 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3619,0.8100,0.0502,11.7523 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3392,0.8060,0.0557,10.5967 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5337,0.8270,0.0772,7.6431 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8184,0.8209,0.0718,8.2180 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1809,0.8225,0.0737,7.9988 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3296,0.8234,0.0730,8.0765 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6107,0.8346,0.0840,7.0225 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1314,0.8497,0.0976,6.0440 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6193,0.8403,0.0908,6.4988 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0086,0.8423,0.0930,6.3440 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6060,0.8440,0.0964,6.1166 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0070,0.8576,0.1074,5.4922 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..a19e87c --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6791,0.8908,0.1364,4.3245 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9716,0.8870,0.1358,4.3420 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5447,0.9043,0.1536,3.8388 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2529,0.8923,0.1415,4.1680 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8078,0.9392,0.1896,3.1113 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5769,0.8788,0.1251,4.7150 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2436,0.8902,0.1380,4.2738 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0279,0.8964,0.1425,4.1404 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1830,0.8885,0.1347,4.3794 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0947,0.9251,0.1678,3.5152 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9671,0.8798,0.1300,4.5365 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3855,0.8945,0.1440,4.0955 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2270,0.8975,0.1482,3.9788 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7541,0.8969,0.1440,4.0947 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6367,0.9198,0.1673,3.5261 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7154,0.9334,0.1807,3.2644 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5329,0.9345,0.1812,3.2550 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7962,0.9437,0.1925,3.0646 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6495,0.9419,0.1880,3.1373 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7421,0.9625,0.2052,2.8739 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2539,0.9964,0.2424,2.4337 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3575,0.9781,0.2239,2.6339 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5160,1.0009,0.2458,2.3997 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8203,0.9940,0.2390,2.4678 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0748,1.0084,0.2519,2.3416 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..ccfdc31 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8052,1.0573,0.2937,2.0084 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.2886,1.0596,0.3084,1.9126 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0376,1.0820,0.3303,1.7858 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4310,1.0554,0.3057,1.9295 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9371,1.1396,0.3857,1.5291 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6368,1.0324,0.2805,2.1026 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4796,1.0785,0.3275,1.8012 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4337,1.0743,0.3258,1.8106 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3096,1.0587,0.3027,1.9487 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2314,1.1146,0.3659,1.6120 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0234,1.0523,0.3021,1.9521 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6006,1.0991,0.3517,1.6769 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5616,1.0966,0.3478,1.6961 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8595,1.0803,0.3307,1.7836 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7461,1.1269,0.3760,1.5687 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7688,1.1695,0.4141,1.4243 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7406,1.1961,0.4387,1.3445 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0276,1.2079,0.4543,1.2984 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7391,1.1857,0.4344,1.3578 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8188,1.2270,0.4709,1.2525 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2935,1.3289,0.5749,1.0260 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5420,1.2611,0.5044,1.1693 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7156,1.3290,0.5730,1.0294 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8817,1.3140,0.5596,1.0540 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1183,1.3736,0.6150,0.9591 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..3a14934 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5079,0.9019,0.1132,5.2103 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6274,0.8911,0.1088,5.4209 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1770,0.9042,0.1213,4.8614 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9296,0.8923,0.1106,5.3336 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4914,0.9355,0.1501,3.9290 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4794,0.8922,0.1069,5.5164 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8484,0.8899,0.1072,5.5029 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5278,0.8980,0.1125,5.2438 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9680,0.8906,0.1069,5.5157 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8894,0.9188,0.1333,4.4242 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9079,0.8991,0.1118,5.2773 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9405,0.9004,0.1181,4.9942 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6946,0.9023,0.1187,4.9680 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6017,0.9001,0.1170,5.0402 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4862,0.9182,0.1330,4.4346 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6288,0.9538,0.1692,3.4866 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2302,0.9556,0.1724,3.4207 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4837,0.9546,0.1700,3.4697 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5502,0.9584,0.1738,3.3945 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6749,0.9728,0.1886,3.1270 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2114,1.0019,0.2152,2.7407 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1351,0.9937,0.2092,2.8195 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3187,0.9982,0.2110,2.7948 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7270,1.0055,0.2197,2.6849 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0489,1.0235,0.2359,2.5004 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..e7b60ac --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2760,0.8535,0.0691,8.5310 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2550,0.8518,0.0715,8.2477 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4452,0.8544,0.0716,8.2336 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7224,0.8539,0.0708,8.3274 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1407,0.8657,0.0816,7.2289 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3592,0.8589,0.0740,7.9726 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4640,0.8560,0.0746,7.9083 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0910,0.8569,0.0742,7.9440 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7259,0.8555,0.0736,8.0098 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5353,0.8658,0.0823,7.1673 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8191,0.8585,0.0765,7.7061 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6923,0.8564,0.0756,7.7991 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4640,0.8595,0.0772,7.6429 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3619,0.8553,0.0743,7.9338 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3392,0.8655,0.0826,7.1382 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5337,0.9028,0.1172,5.0329 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8184,0.8944,0.1101,5.3561 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1809,0.8958,0.1122,5.2584 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3296,0.8931,0.1109,5.3191 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6107,0.9134,0.1266,4.6599 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1314,0.9338,0.1454,4.0568 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6193,0.9193,0.1362,4.3316 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0086,0.9252,0.1390,4.2430 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6060,0.9294,0.1445,4.0830 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0070,0.9474,0.1605,3.6756 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..e9b6b4d --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6791,0.9706,0.1779,3.3152 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9716,0.9672,0.1814,3.2524 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5447,0.9915,0.2027,2.9098 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2529,0.9719,0.1886,3.1274 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8078,1.0364,0.2494,2.3649 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5769,0.9657,0.1788,3.2981 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2436,0.9875,0.1988,2.9676 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0279,0.9947,0.2036,2.8976 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1830,0.9804,0.1948,3.0272 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0947,1.0286,0.2386,2.4723 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9671,0.9818,0.1973,2.9889 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3855,1.0069,0.2191,2.6917 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2270,1.0112,0.2236,2.6377 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7541,1.0041,0.2178,2.7084 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6367,1.0342,0.2490,2.3691 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7154,1.0699,0.2798,2.1079 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5329,1.0737,0.2845,2.0730 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7962,1.0883,0.3001,1.9654 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6495,1.0785,0.2914,2.0240 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7421,1.1056,0.3165,1.8637 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2539,1.1522,0.3611,1.6334 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3575,1.1291,0.3396,1.7368 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5160,1.1609,0.3714,1.5881 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8203,1.1494,0.3583,1.6462 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0748,1.1699,0.3765,1.5667 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..fc0c7a2 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8052,1.1680,0.3845,1.5341 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.2886,1.1961,0.4145,1.4230 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0376,1.2213,0.4400,1.3405 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4310,1.1932,0.4117,1.4328 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9371,1.2916,0.5090,1.1589 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6368,1.1790,0.3956,1.4910 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4796,1.2493,0.4682,1.2597 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4337,1.2465,0.4633,1.2732 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3096,1.2139,0.4325,1.3637 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2314,1.3500,0.5283,1.1165 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0234,1.2270,0.4458,1.3232 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6006,1.3058,0.5271,1.1189 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5616,1.2977,0.5154,1.1444 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8595,1.2725,0.4921,1.1987 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7461,1.3343,0.5514,1.0698 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7688,1.4164,0.6310,0.9348 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7406,1.4783,0.6898,0.8551 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0276,1.4825,0.6993,0.8435 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7391,1.4567,0.6721,0.8775 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8188,1.5004,0.7152,0.8247 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2935,1.6361,0.8456,0.6975 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5420,1.5447,0.7590,0.7771 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7156,1.6424,0.8543,0.6904 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8817,1.6191,0.8321,0.7089 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1183,1.6916,0.9037,0.6527 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..72e50f5 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5079,0.8457,0.0978,6.0320 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6274,0.8312,0.0932,6.3275 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1770,0.8442,0.1043,5.6576 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9296,0.8348,0.0950,6.2116 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4914,0.8706,0.1296,4.5510 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4794,0.8310,0.0890,6.6272 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8484,0.8288,0.0896,6.5799 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5278,0.8365,0.0941,6.2671 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9680,0.8306,0.0893,6.6031 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8894,0.8544,0.1111,5.3097 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9079,0.8336,0.0927,6.3623 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9405,0.8358,0.0975,6.0466 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6946,0.8359,0.0990,5.9563 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6017,0.8358,0.0971,6.0753 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4862,0.8529,0.1106,5.3320 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6288,0.8844,0.1419,4.1578 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2302,0.8840,0.1441,4.0939 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4837,0.8825,0.1424,4.1420 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5502,0.8869,0.1465,4.0271 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6749,0.8981,0.1576,3.7424 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2114,0.9343,0.1903,3.0993 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1351,0.9263,0.1852,3.1856 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3187,0.9270,0.1872,3.1501 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7270,0.9351,0.1942,3.0371 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0489,0.9499,0.2081,2.8345 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..b5a54dd --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2760,0.7996,0.0590,10.0045 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2550,0.7967,0.0610,9.6644 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4452,0.7992,0.0613,9.6263 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7224,0.7984,0.0604,9.7585 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1407,0.8092,0.0700,8.4290 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3592,0.8006,0.0611,9.6577 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4640,0.8004,0.0619,9.5299 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0910,0.7997,0.0615,9.5860 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7259,0.7991,0.0612,9.6431 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5353,0.8082,0.0685,8.6083 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8191,0.8023,0.0631,9.3509 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6923,0.7991,0.0619,9.5322 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4640,0.8017,0.0635,9.2842 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3619,0.7970,0.0615,9.5961 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3392,0.8084,0.0682,8.6516 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5337,0.8360,0.0974,6.0584 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8184,0.8303,0.0914,6.4521 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1809,0.8320,0.0936,6.3015 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3296,0.8307,0.0924,6.3825 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6107,0.8464,0.1058,5.5724 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1314,0.8714,0.1288,4.5792 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6193,0.8605,0.1211,4.8692 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0086,0.8637,0.1227,4.8066 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6060,0.8670,0.1281,4.6059 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0070,0.8840,0.1420,4.1531 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..7c298f9 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6791,0.8997,0.1529,3.8574 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9716,0.8938,0.1543,3.8214 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5447,0.9155,0.1733,3.4034 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2529,0.9006,0.1607,3.6702 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8078,0.9585,0.2138,2.7584 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5769,0.8973,0.1477,3.9931 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2436,0.9087,0.1636,3.6048 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0279,0.9116,0.1680,3.5100 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1830,0.9023,0.1603,3.6805 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0947,0.9426,0.1981,2.9778 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9671,0.9067,0.1624,3.6319 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3855,0.9219,0.1804,3.2697 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2270,0.9258,0.1830,3.2235 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7541,0.9189,0.1793,3.2903 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6367,0.9469,0.2048,2.8805 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7154,0.9796,0.2342,2.5189 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5329,0.9837,0.2401,2.4566 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7962,0.9970,0.2508,2.3519 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6495,0.9866,0.2446,2.4111 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7421,1.0097,0.2658,2.2192 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2539,1.0647,0.3198,1.8446 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3575,1.0460,0.3009,1.9604 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5160,1.0729,0.3289,1.7931 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8203,1.0576,0.3170,1.8605 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0748,1.0818,0.3334,1.7693 diff --git a/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..da811bb --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8052,1.0786,0.3292,1.7916 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.2886,1.0905,0.3522,1.6749 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0376,1.1171,0.3752,1.5721 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4310,1.0893,0.3493,1.6886 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9371,1.1804,0.4371,1.3494 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6368,1.0729,0.3290,1.7926 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4796,1.1250,0.3890,1.5162 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4337,1.1292,0.3852,1.5313 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3096,1.0993,0.3559,1.6574 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2314,1.1739,0.4282,1.3775 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0234,1.1155,0.3727,1.5827 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6006,1.1793,0.4357,1.3539 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5616,1.1686,0.4286,1.3761 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8595,1.1499,0.4082,1.4448 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7461,1.2053,0.4604,1.2812 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7688,1.2883,0.5394,1.0935 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7406,1.3215,0.5810,1.0152 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0276,1.3374,0.5928,0.9950 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7391,1.3119,0.5683,1.0380 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8188,1.3614,0.6139,0.9608 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2935,1.5051,0.7522,0.7842 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5420,1.4190,0.6740,0.8751 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7156,1.5078,0.7612,0.7749 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8817,1.4883,0.7420,0.7949 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1183,1.5556,0.8036,0.7339 diff --git a/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..025e99d --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.5079,0.8396,0.0896,6.5794 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.6274,0.8331,0.0852,6.9227 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.1770,0.8468,0.0958,6.1568 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.9296,0.8359,0.0868,6.7923 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.4914,0.8719,0.1195,4.9371 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.4794,0.8296,0.0782,7.5383 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.8484,0.8304,0.0785,7.5144 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.5278,0.8347,0.0827,7.1361 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.9680,0.8281,0.0784,7.5199 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.8894,0.8479,0.0983,5.9994 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9079,0.8267,0.0762,7.7395 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.9405,0.8279,0.0803,7.3473 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.6946,0.8308,0.0815,7.2355 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.6017,0.8292,0.0799,7.3775 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.4862,0.8422,0.0920,6.4083 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.6288,0.8606,0.1109,5.3177 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.2302,0.8621,0.1108,5.3224 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.4837,0.8619,0.1104,5.3407 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.5502,0.8643,0.1133,5.2069 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6749,0.8751,0.1232,4.7861 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2114,0.8965,0.1444,4.0839 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.1351,0.8903,0.1385,4.2579 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.3187,0.8909,0.1413,4.1733 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.7270,0.8951,0.1471,4.0086 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0489,0.9084,0.1587,3.7169 diff --git a/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..91d2c26 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.2760,0.8075,0.0542,10.8787 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.2550,0.8081,0.0558,10.5610 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,48.4452,0.8029,0.0563,10.4707 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,51.7224,0.8057,0.0557,10.5982 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.1407,0.8163,0.0643,9.1734 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.3592,0.8054,0.0542,10.8898 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,51.4640,0.8068,0.0547,10.7886 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,45.0910,0.8044,0.0543,10.8533 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,48.7259,0.8063,0.0540,10.9134 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,30.5353,0.8136,0.0603,9.7805 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.8191,0.8026,0.0517,11.4181 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,48.6923,0.8008,0.0511,11.5375 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,42.4640,0.7975,0.0523,11.2760 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.3619,0.7960,0.0509,11.5786 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.3392,0.8043,0.0560,10.5235 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.5337,0.8293,0.0775,7.6095 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,44.8184,0.8228,0.0718,8.2121 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.1809,0.8227,0.0738,7.9898 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.3296,0.8230,0.0733,8.0426 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.6107,0.8371,0.0842,7.0060 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.1314,0.8518,0.0984,5.9950 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,40.6193,0.8424,0.0912,6.4648 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.0086,0.8432,0.0933,6.3249 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.6060,0.8470,0.0973,6.0591 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0070,0.8621,0.1082,5.4494 diff --git a/Test/Images/HDRIHaven/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..584cc72 --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.6791,0.8959,0.1369,4.3097 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,55.9716,0.8895,0.1368,4.3116 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,49.5447,0.9042,0.1537,3.8377 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.2529,0.8932,0.1427,4.1321 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.8078,0.9405,0.1906,3.0946 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.5769,0.8758,0.1258,4.6900 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.2436,0.8908,0.1383,4.2648 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.0279,0.8939,0.1436,4.1068 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.1830,0.8882,0.1354,4.3555 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.0947,0.9208,0.1685,3.5010 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,37.9671,0.8810,0.1305,4.5182 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.3855,0.8895,0.1446,4.0786 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.2270,0.8974,0.1485,3.9706 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.7541,0.8941,0.1444,4.0844 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.6367,0.9151,0.1666,3.5410 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7154,0.9311,0.1806,3.2656 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.5329,0.9341,0.1805,3.2686 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,39.7962,0.9492,0.1925,3.0637 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.6495,0.9352,0.1874,3.1474 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.7421,0.9606,0.2063,2.8585 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2539,0.9959,0.2422,2.4353 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.3575,0.9777,0.2243,2.6298 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.5160,1.0010,0.2480,2.3782 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8203,0.9906,0.2381,2.4769 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.0748,1.0052,0.2529,2.3321 diff --git a/Test/Images/HDRIHaven/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..24ad49c --- /dev/null +++ b/Test/Images/HDRIHaven/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,26 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +HDRIHaven,4x4,hdr-rgb-arboretum.hdr,45.8052,1.0508,0.2933,2.0110 +HDRIHaven,4x4,hdr-rgb-bellparkpier.hdr,56.2886,1.0551,0.3098,1.9041 +HDRIHaven,4x4,hdr-rgb-canarywharf.hdr,50.0376,1.0821,0.3315,1.7793 +HDRIHaven,4x4,hdr-rgb-eveningroad.hdr,52.4310,1.0545,0.3060,1.9274 +HDRIHaven,4x4,hdr-rgb-riverwalk.hdr,34.9371,1.1360,0.3868,1.5248 +HDRIHaven,5x5,hdr-rgb-arboretum.hdr,41.6368,1.0331,0.2820,2.0914 +HDRIHaven,5x5,hdr-rgb-bellparkpier.hdr,52.4796,1.0777,0.3283,1.7967 +HDRIHaven,5x5,hdr-rgb-canarywharf.hdr,46.4337,1.0727,0.3253,1.8129 +HDRIHaven,5x5,hdr-rgb-eveningroad.hdr,49.3096,1.0524,0.3027,1.9486 +HDRIHaven,5x5,hdr-rgb-riverwalk.hdr,31.2314,1.1149,0.3652,1.6149 +HDRIHaven,6x6,hdr-rgb-arboretum.hdr,38.0234,1.0530,0.3009,1.9599 +HDRIHaven,6x6,hdr-rgb-bellparkpier.hdr,49.6006,1.1000,0.3525,1.6735 +HDRIHaven,6x6,hdr-rgb-canarywharf.hdr,43.5616,1.0984,0.3477,1.6962 +HDRIHaven,6x6,hdr-rgb-eveningroad.hdr,46.8595,1.0786,0.3309,1.7824 +HDRIHaven,6x6,hdr-rgb-riverwalk.hdr,28.7461,1.1291,0.3767,1.5660 +HDRIHaven,8x8,hdr-rgb-arboretum.hdr,33.7688,1.1665,0.4144,1.4234 +HDRIHaven,8x8,hdr-rgb-bellparkpier.hdr,45.7406,1.1944,0.4401,1.3403 +HDRIHaven,8x8,hdr-rgb-canarywharf.hdr,40.0276,1.2074,0.4505,1.3093 +HDRIHaven,8x8,hdr-rgb-eveningroad.hdr,43.7391,1.1857,0.4370,1.3499 +HDRIHaven,8x8,hdr-rgb-riverwalk.hdr,25.8189,1.2248,0.4733,1.2463 +HDRIHaven,12x12,hdr-rgb-arboretum.hdr,30.2935,1.3326,0.5758,1.0244 +HDRIHaven,12x12,hdr-rgb-bellparkpier.hdr,41.5420,1.2580,0.5059,1.1658 +HDRIHaven,12x12,hdr-rgb-canarywharf.hdr,36.7156,1.3286,0.5744,1.0269 +HDRIHaven,12x12,hdr-rgb-eveningroad.hdr,40.8817,1.3204,0.5622,1.0491 +HDRIHaven,12x12,hdr-rgb-riverwalk.hdr,23.1183,1.3739,0.6153,0.9586 diff --git a/Test/Images/Khronos/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/Khronos/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index 1d46dce..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.2943,0.0386,0.0147,71.4537 -Khronos,4x4,ldr-rgb-diffuse.png,52.5337,0.2415,0.0859,48.8158 -Khronos,4x4,ldr-rgb-emissive.png,58.5505,0.0416,0.0154,68.2937 -Khronos,4x4,ldr-rgb-metalrough.png,44.2748,0.0992,0.0575,18.2504 -Khronos,4x4,ldr-rgb-metalrough2.png,42.9160,0.5165,0.3468,12.0938 -Khronos,4x4,ldr-rgba-base.png,43.2384,0.1210,0.0716,14.6384 -Khronos,4x4,ldr-rgba-diffuse.png,43.8337,0.0992,0.0528,19.8488 -Khronos,4x4,ldr-rgba-specgloss.png,41.6515,0.1589,0.1065,9.8465 -Khronos,4x4,ldr-xy-normal1.png,44.9658,0.1682,0.0882,11.8946 -Khronos,4x4,ldr-xy-normal2.png,48.6954,0.4019,0.1394,30.0841 -Khronos,5x5,ldr-l-occlusion.png,54.3853,0.0378,0.0131,79.9107 -Khronos,5x5,ldr-rgb-diffuse.png,47.2206,0.2291,0.0734,57.1516 -Khronos,5x5,ldr-rgb-emissive.png,52.6484,0.0404,0.0133,78.5800 -Khronos,5x5,ldr-rgb-metalrough.png,39.8152,0.0886,0.0456,22.9809 -Khronos,5x5,ldr-rgb-metalrough2.png,37.8813,0.5293,0.3558,11.7871 -Khronos,5x5,ldr-rgba-base.png,38.8783,0.1061,0.0559,18.7530 -Khronos,5x5,ldr-rgba-diffuse.png,39.1281,0.1027,0.0555,18.8830 -Khronos,5x5,ldr-rgba-specgloss.png,38.3729,0.1246,0.0711,14.7450 -Khronos,5x5,ldr-xy-normal1.png,41.8817,0.1494,0.0680,15.4148 -Khronos,5x5,ldr-xy-normal2.png,46.1664,0.3829,0.1028,40.7974 -Khronos,6x6,ldr-l-occlusion.png,48.3853,0.0383,0.0129,81.5072 -Khronos,6x6,ldr-rgb-diffuse.png,43.2790,0.2424,0.0865,48.4902 -Khronos,6x6,ldr-rgb-emissive.png,49.1258,0.0399,0.0121,86.9042 -Khronos,6x6,ldr-rgb-metalrough.png,36.4555,0.0965,0.0541,19.3847 -Khronos,6x6,ldr-rgb-metalrough2.png,35.2939,0.5438,0.3699,11.3389 -Khronos,6x6,ldr-rgba-base.png,36.1037,0.1132,0.0626,16.7630 -Khronos,6x6,ldr-rgba-diffuse.png,36.0866,0.1146,0.0669,15.6714 -Khronos,6x6,ldr-rgba-specgloss.png,36.1059,0.1287,0.0750,13.9719 -Khronos,6x6,ldr-xy-normal1.png,39.6565,0.1452,0.0635,16.5031 -Khronos,6x6,ldr-xy-normal2.png,44.1113,0.3798,0.1007,41.6365 -Khronos,8x8,ldr-l-occlusion.png,43.9509,0.0416,0.0122,85.8775 -Khronos,8x8,ldr-rgb-diffuse.png,38.3579,0.2523,0.0949,44.1743 -Khronos,8x8,ldr-rgb-emissive.png,44.5417,0.0427,0.0109,95.8640 -Khronos,8x8,ldr-rgb-metalrough.png,32.3176,0.1158,0.0690,15.1899 -Khronos,8x8,ldr-rgb-metalrough2.png,32.1727,0.4674,0.2935,14.2886 -Khronos,8x8,ldr-rgba-base.png,32.3786,0.1234,0.0692,15.1452 -Khronos,8x8,ldr-rgba-diffuse.png,32.1163,0.1365,0.0846,12.3892 -Khronos,8x8,ldr-rgba-specgloss.png,32.9674,0.1355,0.0783,13.3935 -Khronos,8x8,ldr-xy-normal1.png,36.4984,0.1438,0.0576,18.2167 -Khronos,8x8,ldr-xy-normal2.png,40.6917,0.3854,0.1034,40.5509 -Khronos,12x12,ldr-l-occlusion.png,40.5785,0.0473,0.0110,95.1340 -Khronos,12x12,ldr-rgb-diffuse.png,33.3691,0.2326,0.0684,61.2780 -Khronos,12x12,ldr-rgb-emissive.png,39.4740,0.0486,0.0103,101.7949 -Khronos,12x12,ldr-rgb-metalrough.png,28.6341,0.0929,0.0384,27.2874 -Khronos,12x12,ldr-rgb-metalrough2.png,29.2524,0.3020,0.1227,34.1910 -Khronos,12x12,ldr-rgba-base.png,29.0205,0.1116,0.0513,20.4413 -Khronos,12x12,ldr-rgba-diffuse.png,28.6231,0.1177,0.0594,17.6626 -Khronos,12x12,ldr-rgba-specgloss.png,29.8092,0.1049,0.0419,25.0203 -Khronos,12x12,ldr-xy-normal1.png,32.7294,0.1286,0.0359,29.2147 -Khronos,12x12,ldr-xy-normal2.png,36.2128,0.3758,0.0876,47.8994 diff --git a/Test/Images/Khronos/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/Khronos/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index ad14980..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.1811,0.0375,0.0144,72.7575 -Khronos,4x4,ldr-rgb-diffuse.png,52.3048,0.2331,0.0787,53.2643 -Khronos,4x4,ldr-rgb-emissive.png,57.9745,0.0387,0.0131,80.3076 -Khronos,4x4,ldr-rgb-metalrough.png,43.8757,0.0817,0.0407,25.7438 -Khronos,4x4,ldr-rgb-metalrough2.png,42.6172,0.3854,0.2183,19.2135 -Khronos,4x4,ldr-rgba-base.png,42.7808,0.0944,0.0460,22.8164 -Khronos,4x4,ldr-rgba-diffuse.png,43.2186,0.0815,0.0354,29.6065 -Khronos,4x4,ldr-rgba-specgloss.png,41.2397,0.1183,0.0669,15.6705 -Khronos,4x4,ldr-xy-normal1.png,44.7980,0.1331,0.0546,19.2216 -Khronos,4x4,ldr-xy-normal2.png,48.3359,0.3786,0.1093,38.3777 -Khronos,5x5,ldr-l-occlusion.png,53.9891,0.0370,0.0131,80.1963 -Khronos,5x5,ldr-rgb-diffuse.png,47.0472,0.2246,0.0715,58.6330 -Khronos,5x5,ldr-rgb-emissive.png,52.3396,0.0389,0.0127,82.5258 -Khronos,5x5,ldr-rgb-metalrough.png,39.2552,0.0759,0.0343,30.6072 -Khronos,5x5,ldr-rgb-metalrough2.png,37.2923,0.3998,0.2309,18.1682 -Khronos,5x5,ldr-rgba-base.png,38.0848,0.0889,0.0383,27.3894 -Khronos,5x5,ldr-rgba-diffuse.png,38.3579,0.0834,0.0363,28.8569 -Khronos,5x5,ldr-rgba-specgloss.png,37.9190,0.1015,0.0493,21.2658 -Khronos,5x5,ldr-xy-normal1.png,41.3049,0.1307,0.0495,21.2035 -Khronos,5x5,ldr-xy-normal2.png,45.6138,0.3686,0.0888,47.2310 -Khronos,6x6,ldr-l-occlusion.png,48.3038,0.0366,0.0122,85.7102 -Khronos,6x6,ldr-rgb-diffuse.png,43.2173,0.2309,0.0732,57.3132 -Khronos,6x6,ldr-rgb-emissive.png,48.9702,0.0376,0.0113,93.0587 -Khronos,6x6,ldr-rgb-metalrough.png,36.2530,0.0792,0.0372,28.1921 -Khronos,6x6,ldr-rgb-metalrough2.png,35.0960,0.3954,0.2243,18.6964 -Khronos,6x6,ldr-rgba-base.png,35.9357,0.0904,0.0405,25.8742 -Khronos,6x6,ldr-rgba-diffuse.png,35.9044,0.0883,0.0413,25.3634 -Khronos,6x6,ldr-rgba-specgloss.png,35.8773,0.1009,0.0485,21.6045 -Khronos,6x6,ldr-xy-normal1.png,38.8396,0.1267,0.0472,22.2335 -Khronos,6x6,ldr-xy-normal2.png,43.4426,0.3650,0.0851,49.2984 -Khronos,8x8,ldr-l-occlusion.png,43.4865,0.0385,0.0111,94.6529 -Khronos,8x8,ldr-rgb-diffuse.png,38.2787,0.2353,0.0790,53.0696 -Khronos,8x8,ldr-rgb-emissive.png,44.2565,0.0390,0.0092,114.1994 -Khronos,8x8,ldr-rgb-metalrough.png,32.2167,0.0934,0.0481,21.7935 -Khronos,8x8,ldr-rgb-metalrough2.png,32.0902,0.3822,0.2106,19.9168 -Khronos,8x8,ldr-rgba-base.png,32.2303,0.1004,0.0483,21.7285 -Khronos,8x8,ldr-rgba-diffuse.png,32.0058,0.1076,0.0577,18.1755 -Khronos,8x8,ldr-rgba-specgloss.png,32.8371,0.1099,0.0539,19.4595 -Khronos,8x8,ldr-xy-normal1.png,36.2071,0.1247,0.0412,25.4632 -Khronos,8x8,ldr-xy-normal2.png,40.2733,0.3631,0.0835,50.2096 -Khronos,12x12,ldr-l-occlusion.png,40.2271,0.0419,0.0100,104.7952 -Khronos,12x12,ldr-rgb-diffuse.png,33.3234,0.2198,0.0591,71.0259 -Khronos,12x12,ldr-rgb-emissive.png,39.2738,0.0428,0.0090,115.9180 -Khronos,12x12,ldr-rgb-metalrough.png,28.5929,0.0781,0.0289,36.2815 -Khronos,12x12,ldr-rgb-metalrough2.png,29.1679,0.2725,0.0972,43.1420 -Khronos,12x12,ldr-rgba-base.png,28.9701,0.0943,0.0376,27.8670 -Khronos,12x12,ldr-rgba-diffuse.png,28.5748,0.0977,0.0435,24.0964 -Khronos,12x12,ldr-rgba-specgloss.png,29.7683,0.0904,0.0313,33.4837 -Khronos,12x12,ldr-xy-normal1.png,32.6096,0.1176,0.0285,36.7871 -Khronos,12x12,ldr-xy-normal2.png,36.0023,0.3571,0.0737,56.9151 diff --git a/Test/Images/Khronos/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/Khronos/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index 606bd7d..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,67.9245,0.0471,0.0224,46.7340 -Khronos,4x4,ldr-rgb-diffuse.png,54.0221,0.4039,0.2498,16.7923 -Khronos,4x4,ldr-rgb-emissive.png,59.8356,0.0507,0.0238,44.0951 -Khronos,4x4,ldr-rgb-metalrough.png,44.8439,0.2333,0.1912,5.4847 -Khronos,4x4,ldr-rgb-metalrough2.png,43.7387,1.4456,1.2744,3.2913 -Khronos,4x4,ldr-rgba-base.png,43.8181,0.2962,0.2473,4.2398 -Khronos,4x4,ldr-rgba-diffuse.png,44.2283,0.2173,0.1704,6.1535 -Khronos,4x4,ldr-rgba-specgloss.png,42.2924,0.3928,0.3399,3.0853 -Khronos,4x4,ldr-xy-normal1.png,46.4815,0.3525,0.2721,3.8542 -Khronos,4x4,ldr-xy-normal2.png,50.2696,0.8003,0.5465,7.6749 -Khronos,5x5,ldr-l-occlusion.png,57.1580,0.0505,0.0245,42.8584 -Khronos,5x5,ldr-rgb-diffuse.png,48.9900,0.4062,0.2519,16.6506 -Khronos,5x5,ldr-rgb-emissive.png,55.3732,0.0528,0.0241,43.5364 -Khronos,5x5,ldr-rgb-metalrough.png,40.2386,0.2521,0.2080,5.0420 -Khronos,5x5,ldr-rgb-metalrough2.png,39.0265,1.6811,1.5087,2.7801 -Khronos,5x5,ldr-rgba-base.png,39.3979,0.3260,0.2742,3.8247 -Khronos,5x5,ldr-rgba-diffuse.png,39.5646,0.2613,0.2127,4.9296 -Khronos,5x5,ldr-rgba-specgloss.png,38.7813,0.4196,0.3647,2.8752 -Khronos,5x5,ldr-xy-normal1.png,43.0494,0.3306,0.2483,4.2224 -Khronos,5x5,ldr-xy-normal2.png,47.2289,0.6889,0.4172,10.0542 -Khronos,6x6,ldr-l-occlusion.png,50.8663,0.0569,0.0305,34.4157 -Khronos,6x6,ldr-rgb-diffuse.png,44.9305,0.4123,0.2568,16.3318 -Khronos,6x6,ldr-rgb-emissive.png,51.5230,0.0516,0.0229,45.8474 -Khronos,6x6,ldr-rgb-metalrough.png,36.8282,0.2588,0.2148,4.8805 -Khronos,6x6,ldr-rgb-metalrough2.png,36.4385,1.6463,1.4733,2.8469 -Khronos,6x6,ldr-rgba-base.png,36.6372,0.2979,0.2463,4.2573 -Khronos,6x6,ldr-rgba-diffuse.png,36.4889,0.2786,0.2295,4.5690 -Khronos,6x6,ldr-rgba-specgloss.png,36.4896,0.4238,0.3685,2.8455 -Khronos,6x6,ldr-xy-normal1.png,40.6311,0.2807,0.1979,5.2993 -Khronos,6x6,ldr-xy-normal2.png,45.1540,0.5110,0.2285,18.3564 -Khronos,8x8,ldr-l-occlusion.png,45.4494,0.0654,0.0352,29.7704 -Khronos,8x8,ldr-rgb-diffuse.png,40.2397,0.5202,0.3586,11.6971 -Khronos,8x8,ldr-rgb-emissive.png,46.7056,0.0587,0.0261,40.2170 -Khronos,8x8,ldr-rgb-metalrough.png,32.6674,0.3371,0.2881,3.6396 -Khronos,8x8,ldr-rgb-metalrough2.png,33.1989,1.8101,1.6358,2.5641 -Khronos,8x8,ldr-rgba-base.png,33.0632,0.3187,0.2642,3.9686 -Khronos,8x8,ldr-rgba-diffuse.png,32.5747,0.3644,0.3118,3.3631 -Khronos,8x8,ldr-rgba-specgloss.png,33.4751,0.4471,0.3893,2.6934 -Khronos,8x8,ldr-xy-normal1.png,37.4171,0.3091,0.2215,4.7342 -Khronos,8x8,ldr-xy-normal2.png,42.0727,0.5276,0.2448,17.1344 -Khronos,12x12,ldr-l-occlusion.png,41.6742,0.0605,0.0220,47.7213 -Khronos,12x12,ldr-rgb-diffuse.png,35.7658,0.4717,0.3044,13.7780 -Khronos,12x12,ldr-rgb-emissive.png,41.3741,0.0694,0.0286,36.6788 -Khronos,12x12,ldr-rgb-metalrough.png,29.0892,0.3004,0.2445,4.2891 -Khronos,12x12,ldr-rgb-metalrough2.png,30.1599,1.1734,0.9917,4.2296 -Khronos,12x12,ldr-rgba-base.png,29.6109,0.3060,0.2439,4.2985 -Khronos,12x12,ldr-rgba-diffuse.png,29.0613,0.4114,0.3503,2.9933 -Khronos,12x12,ldr-rgba-specgloss.png,30.4743,0.3253,0.2578,4.0673 -Khronos,12x12,ldr-xy-normal1.png,33.4993,0.2788,0.1831,5.7260 -Khronos,12x12,ldr-xy-normal2.png,37.8161,0.5493,0.2584,16.2331 diff --git a/Test/Images/Khronos/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/Khronos/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index e22a0ef..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,70.5315,0.0890,0.0644,16.2895 -Khronos,4x4,ldr-rgb-diffuse.png,54.7187,1.8348,1.6789,2.4982 -Khronos,4x4,ldr-rgb-emissive.png,60.8411,0.0771,0.0500,20.9841 -Khronos,4x4,ldr-rgb-metalrough.png,44.9834,0.5172,0.4748,2.2086 -Khronos,4x4,ldr-rgb-metalrough2.png,44.0109,3.0104,2.8367,1.4786 -Khronos,4x4,ldr-rgba-base.png,44.0067,0.6797,0.6302,1.6639 -Khronos,4x4,ldr-rgba-diffuse.png,44.4135,0.4941,0.4464,2.3489 -Khronos,4x4,ldr-rgba-specgloss.png,42.4620,0.8713,0.8182,1.2816 -Khronos,4x4,ldr-xy-normal1.png,46.6816,1.0432,0.9630,1.0889 -Khronos,4x4,ldr-xy-normal2.png,50.5731,2.7388,2.4906,1.6841 -Khronos,5x5,ldr-l-occlusion.png,58.7308,0.1542,0.1278,8.2076 -Khronos,5x5,ldr-rgb-diffuse.png,49.7919,1.5934,1.4369,2.9189 -Khronos,5x5,ldr-rgb-emissive.png,56.1398,0.0879,0.0595,17.6142 -Khronos,5x5,ldr-rgb-metalrough.png,40.4561,0.6178,0.5739,1.8271 -Khronos,5x5,ldr-rgb-metalrough2.png,39.4939,3.5505,3.3775,1.2418 -Khronos,5x5,ldr-rgba-base.png,39.7539,0.7923,0.7392,1.4186 -Khronos,5x5,ldr-rgba-diffuse.png,39.8978,0.5850,0.5359,1.9565 -Khronos,5x5,ldr-rgba-specgloss.png,39.0262,0.9859,0.9311,1.1262 -Khronos,5x5,ldr-xy-normal1.png,43.4105,1.2222,1.1415,0.9186 -Khronos,5x5,ldr-xy-normal2.png,47.7893,3.5399,3.2755,1.2805 -Khronos,6x6,ldr-l-occlusion.png,52.2696,0.2047,0.1784,5.8767 -Khronos,6x6,ldr-rgb-diffuse.png,45.7745,1.4895,1.3304,3.1526 -Khronos,6x6,ldr-rgb-emissive.png,52.6625,0.0966,0.0679,15.4371 -Khronos,6x6,ldr-rgb-metalrough.png,37.0147,0.7595,0.7145,1.4676 -Khronos,6x6,ldr-rgb-metalrough2.png,36.7447,4.2513,4.0776,1.0286 -Khronos,6x6,ldr-rgba-base.png,36.8327,0.9392,0.8874,1.1816 -Khronos,6x6,ldr-rgba-diffuse.png,36.6564,0.7070,0.6575,1.5947 -Khronos,6x6,ldr-rgba-specgloss.png,36.6739,1.1431,1.0886,0.9632 -Khronos,6x6,ldr-xy-normal1.png,41.1133,1.0974,1.0155,1.0325 -Khronos,6x6,ldr-xy-normal2.png,45.8124,2.8938,2.6204,1.6007 -Khronos,8x8,ldr-l-occlusion.png,46.0393,0.2484,0.2170,4.8313 -Khronos,8x8,ldr-rgb-diffuse.png,40.8641,1.5870,1.4261,2.9412 -Khronos,8x8,ldr-rgb-emissive.png,47.6060,0.1006,0.0668,15.6956 -Khronos,8x8,ldr-rgb-metalrough.png,32.8279,0.9382,0.8883,1.1805 -Khronos,8x8,ldr-rgb-metalrough2.png,33.5845,5.2332,5.0573,0.8294 -Khronos,8x8,ldr-rgba-base.png,33.2523,1.1619,1.1053,0.9487 -Khronos,8x8,ldr-rgba-diffuse.png,32.7215,0.9205,0.8662,1.2106 -Khronos,8x8,ldr-rgba-specgloss.png,33.6278,1.4210,1.3596,0.7712 -Khronos,8x8,ldr-xy-normal1.png,37.7223,0.7286,0.6426,1.6319 -Khronos,8x8,ldr-xy-normal2.png,42.5159,1.3968,1.1160,3.7585 -Khronos,12x12,ldr-l-occlusion.png,42.4633,0.2079,0.1684,6.2280 -Khronos,12x12,ldr-rgb-diffuse.png,36.6027,1.7913,1.6187,2.5911 -Khronos,12x12,ldr-rgb-emissive.png,42.3476,0.1380,0.0939,11.1628 -Khronos,12x12,ldr-rgb-metalrough.png,29.2644,1.1208,1.0620,0.9873 -Khronos,12x12,ldr-rgb-metalrough2.png,30.7448,5.7565,5.5722,0.7527 -Khronos,12x12,ldr-rgba-base.png,29.9105,1.2119,1.1465,0.9146 -Khronos,12x12,ldr-rgba-diffuse.png,29.2512,1.1582,1.0952,0.9574 -Khronos,12x12,ldr-rgba-specgloss.png,30.6950,1.6220,1.5533,0.6751 -Khronos,12x12,ldr-xy-normal1.png,33.9598,0.7437,0.6468,1.6212 -Khronos,12x12,ldr-xy-normal2.png,38.4366,1.1253,0.8352,5.0220 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index 4222587..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.2943,0.0433,0.0174,60.1623 -Khronos,4x4,ldr-rgb-diffuse.png,52.5337,0.2688,0.1110,37.7957 -Khronos,4x4,ldr-rgb-emissive.png,58.5505,0.0432,0.0148,70.7684 -Khronos,4x4,ldr-rgb-metalrough.png,44.2748,0.1163,0.0736,14.2373 -Khronos,4x4,ldr-rgb-metalrough2.png,42.9160,0.6176,0.4457,9.4114 -Khronos,4x4,ldr-rgba-base.png,43.2384,0.1418,0.0922,11.3775 -Khronos,4x4,ldr-rgba-diffuse.png,43.8337,0.1160,0.0681,15.3924 -Khronos,4x4,ldr-rgba-specgloss.png,41.6515,0.1904,0.1368,7.6640 -Khronos,4x4,ldr-xy-normal1.png,44.9658,0.1949,0.1137,9.2198 -Khronos,4x4,ldr-xy-normal2.png,48.6954,0.4516,0.1818,23.0719 -Khronos,5x5,ldr-l-occlusion.png,54.3853,0.0414,0.0142,74.0462 -Khronos,5x5,ldr-rgb-diffuse.png,47.2206,0.2468,0.0869,48.2626 -Khronos,5x5,ldr-rgb-emissive.png,52.6484,0.0423,0.0130,80.6345 -Khronos,5x5,ldr-rgb-metalrough.png,39.8152,0.1045,0.0612,17.1235 -Khronos,5x5,ldr-rgb-metalrough2.png,37.8813,0.6623,0.4883,8.5904 -Khronos,5x5,ldr-rgba-base.png,38.8783,0.1251,0.0738,14.2159 -Khronos,5x5,ldr-rgba-diffuse.png,39.1281,0.1216,0.0724,14.4781 -Khronos,5x5,ldr-rgba-specgloss.png,38.3729,0.1507,0.0960,10.9187 -Khronos,5x5,ldr-xy-normal1.png,41.8817,0.1733,0.0897,11.6877 -Khronos,5x5,ldr-xy-normal2.png,46.1664,0.4135,0.1290,32.5027 -Khronos,6x6,ldr-l-occlusion.png,48.3853,0.0427,0.0151,69.3458 -Khronos,6x6,ldr-rgb-diffuse.png,43.2790,0.2766,0.1161,36.1276 -Khronos,6x6,ldr-rgb-emissive.png,49.1258,0.0426,0.0130,80.8777 -Khronos,6x6,ldr-rgb-metalrough.png,36.4555,0.1213,0.0775,13.5237 -Khronos,6x6,ldr-rgb-metalrough2.png,35.2939,0.7031,0.5287,7.9328 -Khronos,6x6,ldr-rgba-base.png,36.1037,0.1404,0.0888,11.8119 -Khronos,6x6,ldr-rgba-diffuse.png,36.0866,0.1435,0.0943,11.1160 -Khronos,6x6,ldr-rgba-specgloss.png,36.1059,0.1627,0.1076,9.7480 -Khronos,6x6,ldr-xy-normal1.png,39.6565,0.1726,0.0885,11.8487 -Khronos,6x6,ldr-xy-normal2.png,44.1113,0.4143,0.1308,32.0729 -Khronos,8x8,ldr-l-occlusion.png,43.9509,0.0469,0.0157,66.6401 -Khronos,8x8,ldr-rgb-diffuse.png,38.3579,0.2976,0.1371,30.6031 -Khronos,8x8,ldr-rgb-emissive.png,44.5417,0.0471,0.0134,78.3630 -Khronos,8x8,ldr-rgb-metalrough.png,32.3176,0.1517,0.1036,10.1257 -Khronos,8x8,ldr-rgb-metalrough2.png,32.1727,0.6083,0.4304,9.7461 -Khronos,8x8,ldr-rgba-base.png,32.3786,0.1574,0.1023,10.2521 -Khronos,8x8,ldr-rgba-diffuse.png,32.1163,0.1786,0.1255,8.3526 -Khronos,8x8,ldr-rgba-specgloss.png,32.9674,0.1749,0.1161,9.0284 -Khronos,8x8,ldr-xy-normal1.png,36.4984,0.1726,0.0846,12.4013 -Khronos,8x8,ldr-xy-normal2.png,40.6917,0.4408,0.1508,27.8198 -Khronos,12x12,ldr-l-occlusion.png,40.5785,0.0524,0.0144,73.0306 -Khronos,12x12,ldr-rgb-diffuse.png,33.3691,0.2643,0.0977,42.9217 -Khronos,12x12,ldr-rgb-emissive.png,39.4740,0.0531,0.0124,84.2844 -Khronos,12x12,ldr-rgb-metalrough.png,28.6341,0.1106,0.0565,18.5717 -Khronos,12x12,ldr-rgb-metalrough2.png,29.2524,0.3622,0.1777,23.6053 -Khronos,12x12,ldr-rgba-base.png,29.0205,0.1365,0.0758,13.8340 -Khronos,12x12,ldr-rgba-diffuse.png,28.6231,0.1462,0.0870,12.0523 -Khronos,12x12,ldr-rgba-specgloss.png,29.8092,0.1255,0.0606,17.2955 -Khronos,12x12,ldr-xy-normal1.png,32.7294,0.1484,0.0526,19.9429 -Khronos,12x12,ldr-xy-normal2.png,36.2128,0.4227,0.1276,32.8798 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index 1cfe659..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.1811,0.0406,0.0150,69.9513 -Khronos,4x4,ldr-rgb-diffuse.png,52.3048,0.2564,0.0993,42.2591 -Khronos,4x4,ldr-rgb-emissive.png,57.9745,0.0422,0.0143,73.1216 -Khronos,4x4,ldr-rgb-metalrough.png,43.8757,0.0951,0.0531,19.7628 -Khronos,4x4,ldr-rgb-metalrough2.png,42.6172,0.4577,0.2873,14.5977 -Khronos,4x4,ldr-rgba-base.png,42.7808,0.1094,0.0601,17.4353 -Khronos,4x4,ldr-rgba-diffuse.png,43.2186,0.0931,0.0456,22.9775 -Khronos,4x4,ldr-rgba-specgloss.png,41.2397,0.1395,0.0868,12.0841 -Khronos,4x4,ldr-xy-normal1.png,44.7980,0.1512,0.0710,14.7739 -Khronos,4x4,ldr-xy-normal2.png,48.3359,0.4176,0.1445,29.0215 -Khronos,5x5,ldr-l-occlusion.png,53.9891,0.0404,0.0141,74.2048 -Khronos,5x5,ldr-rgb-diffuse.png,47.0472,0.2413,0.0828,50.6314 -Khronos,5x5,ldr-rgb-emissive.png,52.3396,0.0414,0.0133,78.7094 -Khronos,5x5,ldr-rgb-metalrough.png,39.2552,0.0880,0.0454,23.1153 -Khronos,5x5,ldr-rgb-metalrough2.png,37.2923,0.4893,0.3160,13.2714 -Khronos,5x5,ldr-rgba-base.png,38.0848,0.1018,0.0518,20.2447 -Khronos,5x5,ldr-rgba-diffuse.png,38.3579,0.0965,0.0492,21.3273 -Khronos,5x5,ldr-rgba-specgloss.png,37.9190,0.1199,0.0670,15.6588 -Khronos,5x5,ldr-xy-normal1.png,41.3049,0.1469,0.0644,16.2853 -Khronos,5x5,ldr-xy-normal2.png,45.6138,0.3923,0.1107,37.8807 -Khronos,6x6,ldr-l-occlusion.png,48.3038,0.0407,0.0140,74.7065 -Khronos,6x6,ldr-rgb-diffuse.png,43.2173,0.2575,0.0996,42.1288 -Khronos,6x6,ldr-rgb-emissive.png,48.9702,0.0404,0.0116,90.5115 -Khronos,6x6,ldr-rgb-metalrough.png,36.2530,0.0952,0.0524,20.0041 -Khronos,6x6,ldr-rgb-metalrough2.png,35.0960,0.4903,0.3160,13.2712 -Khronos,6x6,ldr-rgba-base.png,35.9357,0.1064,0.0573,18.3083 -Khronos,6x6,ldr-rgba-diffuse.png,35.9044,0.1061,0.0580,18.0720 -Khronos,6x6,ldr-rgba-specgloss.png,35.8773,0.1223,0.0684,15.3375 -Khronos,6x6,ldr-xy-normal1.png,38.8396,0.1479,0.0652,16.0763 -Khronos,6x6,ldr-xy-normal2.png,43.4426,0.3881,0.1075,38.9998 -Khronos,8x8,ldr-l-occlusion.png,43.4865,0.0427,0.0133,78.6095 -Khronos,8x8,ldr-rgb-diffuse.png,38.2787,0.2716,0.1124,37.3189 -Khronos,8x8,ldr-rgb-emissive.png,44.2565,0.0428,0.0110,95.5080 -Khronos,8x8,ldr-rgb-metalrough.png,32.2167,0.1168,0.0707,14.8410 -Khronos,8x8,ldr-rgb-metalrough2.png,32.0902,0.4810,0.3045,13.7757 -Khronos,8x8,ldr-rgba-base.png,32.2303,0.1232,0.0695,15.0851 -Khronos,8x8,ldr-rgba-diffuse.png,32.0058,0.1357,0.0839,12.5018 -Khronos,8x8,ldr-rgba-specgloss.png,32.8371,0.1350,0.0778,13.4737 -Khronos,8x8,ldr-xy-normal1.png,36.2071,0.1467,0.0596,17.5847 -Khronos,8x8,ldr-xy-normal2.png,40.2733,0.4062,0.1196,35.0677 -Khronos,12x12,ldr-l-occlusion.png,40.2271,0.0467,0.0132,79.4086 -Khronos,12x12,ldr-rgb-diffuse.png,33.3234,0.2477,0.0846,49.5557 -Khronos,12x12,ldr-rgb-emissive.png,39.2738,0.0467,0.0105,100.2747 -Khronos,12x12,ldr-rgb-metalrough.png,28.5929,0.0923,0.0422,24.8195 -Khronos,12x12,ldr-rgb-metalrough2.png,29.1679,0.3209,0.1408,29.7986 -Khronos,12x12,ldr-rgba-base.png,28.9701,0.1127,0.0549,19.1018 -Khronos,12x12,ldr-rgba-diffuse.png,28.5748,0.1192,0.0633,16.5730 -Khronos,12x12,ldr-rgba-specgloss.png,29.7683,0.1046,0.0448,23.4214 -Khronos,12x12,ldr-xy-normal1.png,32.6096,0.1328,0.0417,25.1710 -Khronos,12x12,ldr-xy-normal2.png,36.0023,0.3974,0.1054,39.7786 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index 8130bbf..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,67.9245,0.0559,0.0290,36.1168 -Khronos,4x4,ldr-rgb-diffuse.png,54.0221,0.5109,0.3524,11.9030 -Khronos,4x4,ldr-rgb-emissive.png,59.8356,0.0577,0.0283,37.0402 -Khronos,4x4,ldr-rgb-metalrough.png,44.8439,0.3091,0.2651,3.9550 -Khronos,4x4,ldr-rgb-metalrough2.png,43.7387,1.9253,1.7504,2.3962 -Khronos,4x4,ldr-rgba-base.png,43.8181,0.3896,0.3391,3.0919 -Khronos,4x4,ldr-rgba-diffuse.png,44.2283,0.2815,0.2329,4.5024 -Khronos,4x4,ldr-rgba-specgloss.png,42.2924,0.5203,0.4661,2.2496 -Khronos,4x4,ldr-xy-normal1.png,46.4815,0.4465,0.3657,2.8675 -Khronos,4x4,ldr-xy-normal2.png,50.2696,1.0112,0.7526,5.5728 -Khronos,5x5,ldr-l-occlusion.png,57.1580,0.0593,0.0312,33.6232 -Khronos,5x5,ldr-rgb-diffuse.png,48.9900,0.5235,0.3637,11.5331 -Khronos,5x5,ldr-rgb-emissive.png,55.3732,0.0613,0.0307,34.1946 -Khronos,5x5,ldr-rgb-metalrough.png,40.2386,0.3521,0.3067,3.4192 -Khronos,5x5,ldr-rgb-metalrough2.png,39.0265,2.3999,2.2243,1.8857 -Khronos,5x5,ldr-rgba-base.png,39.3979,0.4565,0.4029,2.6028 -Khronos,5x5,ldr-rgba-diffuse.png,39.5646,0.3627,0.3122,3.3589 -Khronos,5x5,ldr-rgba-specgloss.png,38.7813,0.5897,0.5342,1.9628 -Khronos,5x5,ldr-xy-normal1.png,43.0494,0.4409,0.3575,2.9331 -Khronos,5x5,ldr-xy-normal2.png,47.2289,0.8760,0.6006,6.9841 -Khronos,6x6,ldr-l-occlusion.png,50.8663,0.0714,0.0423,24.8048 -Khronos,6x6,ldr-rgb-diffuse.png,44.9305,0.5407,0.3803,11.0301 -Khronos,6x6,ldr-rgb-emissive.png,51.5230,0.0613,0.0302,34.7350 -Khronos,6x6,ldr-rgb-metalrough.png,36.8282,0.3705,0.3245,3.2312 -Khronos,6x6,ldr-rgb-metalrough2.png,36.4385,2.3842,2.2069,1.9006 -Khronos,6x6,ldr-rgba-base.png,36.6372,0.4265,0.3735,2.8072 -Khronos,6x6,ldr-rgba-diffuse.png,36.4889,0.3953,0.3437,3.0505 -Khronos,6x6,ldr-rgba-specgloss.png,36.4896,0.6061,0.5502,1.9058 -Khronos,6x6,ldr-xy-normal1.png,40.6311,0.3764,0.2912,3.6012 -Khronos,6x6,ldr-xy-normal2.png,45.1540,0.6099,0.3252,12.8980 -Khronos,8x8,ldr-l-occlusion.png,45.4494,0.0846,0.0524,19.9996 -Khronos,8x8,ldr-rgb-diffuse.png,40.2397,0.7274,0.5646,7.4283 -Khronos,8x8,ldr-rgb-emissive.png,46.7056,0.0725,0.0374,28.0421 -Khronos,8x8,ldr-rgb-metalrough.png,32.6674,0.4987,0.4489,2.3361 -Khronos,8x8,ldr-rgb-metalrough2.png,33.1989,2.7002,2.5186,1.6654 -Khronos,8x8,ldr-rgba-base.png,33.0632,0.4653,0.4085,2.5671 -Khronos,8x8,ldr-rgba-diffuse.png,32.5747,0.5347,0.4814,2.1780 -Khronos,8x8,ldr-rgba-specgloss.png,33.4751,0.6588,0.5997,1.7484 -Khronos,8x8,ldr-xy-normal1.png,37.4171,0.4297,0.3402,3.0819 -Khronos,8x8,ldr-xy-normal2.png,42.0727,0.6618,0.3714,11.2922 -Khronos,12x12,ldr-l-occlusion.png,41.6742,0.0714,0.0315,33.2510 -Khronos,12x12,ldr-rgb-diffuse.png,35.7658,0.6473,0.4764,8.8044 -Khronos,12x12,ldr-rgb-emissive.png,41.3741,0.0836,0.0410,25.5501 -Khronos,12x12,ldr-rgb-metalrough.png,29.0892,0.4308,0.3730,2.8114 -Khronos,12x12,ldr-rgb-metalrough2.png,30.1599,1.7010,1.5141,2.7702 -Khronos,12x12,ldr-rgba-base.png,29.6109,0.4367,0.3722,2.8169 -Khronos,12x12,ldr-rgba-diffuse.png,29.0613,0.5935,0.5312,1.9740 -Khronos,12x12,ldr-rgba-specgloss.png,30.4743,0.4619,0.3937,2.6634 -Khronos,12x12,ldr-xy-normal1.png,33.4993,0.3781,0.2799,3.7467 -Khronos,12x12,ldr-xy-normal2.png,37.8161,0.6928,0.3942,10.6405 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index 4f767df..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,70.5315,0.1152,0.0879,11.9285 -Khronos,4x4,ldr-rgb-diffuse.png,54.7187,2.4752,2.3161,1.8110 -Khronos,4x4,ldr-rgb-emissive.png,60.8411,0.0932,0.0641,16.3633 -Khronos,4x4,ldr-rgb-metalrough.png,44.9834,0.6943,0.6493,1.6148 -Khronos,4x4,ldr-rgb-metalrough2.png,44.0109,4.0555,3.8794,1.0812 -Khronos,4x4,ldr-rgba-base.png,44.0067,0.9142,0.8609,1.2179 -Khronos,4x4,ldr-rgba-diffuse.png,44.4135,0.6521,0.6030,1.7390 -Khronos,4x4,ldr-rgba-specgloss.png,42.4620,1.1507,1.0960,0.9568 -Khronos,4x4,ldr-xy-normal1.png,46.6816,1.3263,1.2459,0.8416 -Khronos,4x4,ldr-xy-normal2.png,50.5731,3.5048,3.2499,1.2906 -Khronos,5x5,ldr-l-occlusion.png,58.7308,0.2119,0.1837,5.7078 -Khronos,5x5,ldr-rgb-diffuse.png,49.7919,2.2626,2.1019,1.9955 -Khronos,5x5,ldr-rgb-emissive.png,56.1398,0.1121,0.0813,12.9019 -Khronos,5x5,ldr-rgb-metalrough.png,40.4561,0.8844,0.8383,1.2508 -Khronos,5x5,ldr-rgb-metalrough2.png,39.4939,5.1171,4.9407,0.8489 -Khronos,5x5,ldr-rgba-base.png,39.7539,1.1256,1.0725,0.9777 -Khronos,5x5,ldr-rgba-diffuse.png,39.8978,0.8279,0.7771,1.3494 -Khronos,5x5,ldr-rgba-specgloss.png,39.0262,1.3952,1.3396,0.7827 -Khronos,5x5,ldr-xy-normal1.png,43.4105,1.6830,1.5991,0.6557 -Khronos,5x5,ldr-xy-normal2.png,47.7893,4.8954,4.6209,0.9077 -Khronos,6x6,ldr-l-occlusion.png,52.2696,0.2970,0.2679,3.9143 -Khronos,6x6,ldr-rgb-diffuse.png,45.7745,2.1797,2.0180,2.0785 -Khronos,6x6,ldr-rgb-emissive.png,52.6625,0.1261,0.0948,11.0630 -Khronos,6x6,ldr-rgb-metalrough.png,37.0147,1.1210,1.0745,0.9758 -Khronos,6x6,ldr-rgb-metalrough2.png,36.7447,6.2531,6.0746,0.6905 -Khronos,6x6,ldr-rgba-base.png,36.8327,1.3906,1.3371,0.7842 -Khronos,6x6,ldr-rgba-diffuse.png,36.6564,1.0332,0.9812,1.0686 -Khronos,6x6,ldr-rgba-specgloss.png,36.6739,1.6520,1.5960,0.6570 -Khronos,6x6,ldr-xy-normal1.png,41.1133,1.5640,1.4790,0.7090 -Khronos,6x6,ldr-xy-normal2.png,45.8124,4.1248,3.8481,1.0900 -Khronos,8x8,ldr-l-occlusion.png,46.0393,0.3707,0.3364,3.1174 -Khronos,8x8,ldr-rgb-diffuse.png,40.8641,2.4013,2.2367,1.8752 -Khronos,8x8,ldr-rgb-emissive.png,47.6060,0.1350,0.0975,10.7554 -Khronos,8x8,ldr-rgb-metalrough.png,32.8279,1.4264,1.3755,0.7623 -Khronos,8x8,ldr-rgb-metalrough2.png,33.5845,7.9530,7.7734,0.5396 -Khronos,8x8,ldr-rgba-base.png,33.2523,1.7583,1.7005,0.6166 -Khronos,8x8,ldr-rgba-diffuse.png,32.7215,1.3905,1.3338,0.7861 -Khronos,8x8,ldr-rgba-specgloss.png,33.6278,2.1263,2.0656,0.5076 -Khronos,8x8,ldr-xy-normal1.png,37.7223,1.0690,0.9792,1.0709 -Khronos,8x8,ldr-xy-normal2.png,42.5159,2.0313,1.7438,2.4052 -Khronos,12x12,ldr-l-occlusion.png,42.4633,0.2987,0.2550,4.1115 -Khronos,12x12,ldr-rgb-diffuse.png,36.6027,2.6774,2.5038,1.6752 -Khronos,12x12,ldr-rgb-emissive.png,42.3476,0.1853,0.1401,7.4844 -Khronos,12x12,ldr-rgb-metalrough.png,29.2644,1.6780,1.6177,0.6482 -Khronos,12x12,ldr-rgb-metalrough2.png,30.7448,8.6487,8.4606,0.4957 -Khronos,12x12,ldr-rgba-base.png,29.9105,1.8067,1.7395,0.6028 -Khronos,12x12,ldr-rgba-diffuse.png,29.2512,1.7249,1.6611,0.6313 -Khronos,12x12,ldr-rgba-specgloss.png,30.6950,2.4073,2.3382,0.4485 -Khronos,12x12,ldr-xy-normal1.png,33.9598,1.0843,0.9860,1.0635 -Khronos,12x12,ldr-xy-normal2.png,38.4366,1.5801,1.2855,3.2628 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index 0448eb1..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.2943,0.0418,0.0164,64.1133 -Khronos,4x4,ldr-rgb-diffuse.png,52.5337,0.2551,0.1003,41.8067 -Khronos,4x4,ldr-rgb-emissive.png,58.5505,0.0431,0.0150,70.0683 -Khronos,4x4,ldr-rgb-metalrough.png,44.2748,0.1075,0.0652,16.0894 -Khronos,4x4,ldr-rgb-metalrough2.png,42.9160,0.5669,0.3952,10.6126 -Khronos,4x4,ldr-rgba-base.png,43.2384,0.1317,0.0820,12.7936 -Khronos,4x4,ldr-rgba-diffuse.png,43.8337,0.1084,0.0611,17.1669 -Khronos,4x4,ldr-rgba-specgloss.png,41.6515,0.1743,0.1218,8.6099 -Khronos,4x4,ldr-xy-normal1.png,44.9658,0.1830,0.1017,10.3109 -Khronos,4x4,ldr-xy-normal2.png,48.6954,0.4304,0.1643,25.5244 -Khronos,5x5,ldr-l-occlusion.png,54.3853,0.0399,0.0139,75.4485 -Khronos,5x5,ldr-rgb-diffuse.png,47.2206,0.2397,0.0823,50.9468 -Khronos,5x5,ldr-rgb-emissive.png,52.6484,0.0419,0.0135,77.9091 -Khronos,5x5,ldr-rgb-metalrough.png,39.8152,0.0980,0.0547,19.1847 -Khronos,5x5,ldr-rgb-metalrough2.png,37.8813,0.6004,0.4239,9.8950 -Khronos,5x5,ldr-rgba-base.png,38.8783,0.1158,0.0655,16.0044 -Khronos,5x5,ldr-rgba-diffuse.png,39.1281,0.1127,0.0648,16.1737 -Khronos,5x5,ldr-rgba-specgloss.png,38.3729,0.1378,0.0849,12.3471 -Khronos,5x5,ldr-xy-normal1.png,41.8817,0.1617,0.0789,13.2972 -Khronos,5x5,ldr-xy-normal2.png,46.1664,0.3947,0.1168,35.9144 -Khronos,6x6,ldr-l-occlusion.png,48.3853,0.0408,0.0141,74.1410 -Khronos,6x6,ldr-rgb-diffuse.png,43.2790,0.2633,0.1061,39.5182 -Khronos,6x6,ldr-rgb-emissive.png,49.1258,0.0415,0.0127,82.4407 -Khronos,6x6,ldr-rgb-metalrough.png,36.4555,0.1111,0.0679,15.4457 -Khronos,6x6,ldr-rgb-metalrough2.png,35.2939,0.6376,0.4623,9.0726 -Khronos,6x6,ldr-rgba-base.png,36.1037,0.1288,0.0779,13.4581 -Khronos,6x6,ldr-rgba-diffuse.png,36.0866,0.1315,0.0829,12.6490 -Khronos,6x6,ldr-rgba-specgloss.png,36.1059,0.1488,0.0941,11.1448 -Khronos,6x6,ldr-xy-normal1.png,39.6565,0.1600,0.0776,13.5120 -Khronos,6x6,ldr-xy-normal2.png,44.1113,0.3988,0.1177,35.6334 -Khronos,8x8,ldr-l-occlusion.png,43.9509,0.0443,0.0143,73.5841 -Khronos,8x8,ldr-rgb-diffuse.png,38.3579,0.2780,0.1203,34.8520 -Khronos,8x8,ldr-rgb-emissive.png,44.5417,0.0454,0.0125,84.0268 -Khronos,8x8,ldr-rgb-metalrough.png,32.3176,0.1369,0.0898,11.6707 -Khronos,8x8,ldr-rgb-metalrough2.png,32.1727,0.5558,0.3785,11.0828 -Khronos,8x8,ldr-rgba-base.png,32.3786,0.1442,0.0896,11.7087 -Khronos,8x8,ldr-rgba-diffuse.png,32.1163,0.1622,0.1093,9.5939 -Khronos,8x8,ldr-rgba-specgloss.png,32.9674,0.1597,0.1015,10.3265 -Khronos,8x8,ldr-xy-normal1.png,36.4984,0.1605,0.0741,14.1512 -Khronos,8x8,ldr-xy-normal2.png,40.6917,0.4154,0.1321,31.7491 -Khronos,12x12,ldr-l-occlusion.png,40.5785,0.0506,0.0134,78.1361 -Khronos,12x12,ldr-rgb-diffuse.png,33.3691,0.2510,0.0868,48.3125 -Khronos,12x12,ldr-rgb-emissive.png,39.4740,0.0517,0.0120,87.2576 -Khronos,12x12,ldr-rgb-metalrough.png,28.6341,0.1032,0.0499,21.0009 -Khronos,12x12,ldr-rgb-metalrough2.png,29.2524,0.3401,0.1578,26.5834 -Khronos,12x12,ldr-rgba-base.png,29.0205,0.1279,0.0674,15.5610 -Khronos,12x12,ldr-rgba-diffuse.png,28.6231,0.1356,0.0774,13.5421 -Khronos,12x12,ldr-rgba-specgloss.png,29.8092,0.1188,0.0540,19.4055 -Khronos,12x12,ldr-xy-normal1.png,32.7294,0.1408,0.0467,22.4423 -Khronos,12x12,ldr-xy-normal2.png,36.2128,0.4050,0.1128,37.1991 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 310f5b6..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,64.1811,0.0390,0.0145,72.1169 -Khronos,4x4,ldr-rgb-diffuse.png,52.3048,0.2421,0.0883,47.4781 -Khronos,4x4,ldr-rgb-emissive.png,57.9745,0.0410,0.0135,77.9146 -Khronos,4x4,ldr-rgb-metalrough.png,43.8757,0.0886,0.0470,22.3206 -Khronos,4x4,ldr-rgb-metalrough2.png,42.6172,0.4240,0.2524,16.6195 -Khronos,4x4,ldr-rgba-base.png,42.7808,0.1027,0.0537,19.5110 -Khronos,4x4,ldr-rgba-diffuse.png,43.2186,0.0884,0.0412,25.4397 -Khronos,4x4,ldr-rgba-specgloss.png,41.2397,0.1293,0.0767,13.6759 -Khronos,4x4,ldr-xy-normal1.png,44.7980,0.1420,0.0629,16.6673 -Khronos,4x4,ldr-xy-normal2.png,48.3359,0.3947,0.1277,32.8429 -Khronos,5x5,ldr-l-occlusion.png,53.9891,0.0390,0.0139,75.4369 -Khronos,5x5,ldr-rgb-diffuse.png,47.0472,0.2339,0.0767,54.6995 -Khronos,5x5,ldr-rgb-emissive.png,52.3396,0.0406,0.0126,83.3927 -Khronos,5x5,ldr-rgb-metalrough.png,39.2552,0.0830,0.0406,25.8282 -Khronos,5x5,ldr-rgb-metalrough2.png,37.2923,0.4472,0.2748,15.2658 -Khronos,5x5,ldr-rgba-base.png,38.0848,0.0952,0.0457,22.9443 -Khronos,5x5,ldr-rgba-diffuse.png,38.3579,0.0912,0.0437,23.9784 -Khronos,5x5,ldr-rgba-specgloss.png,37.9190,0.1117,0.0585,17.9232 -Khronos,5x5,ldr-xy-normal1.png,41.3049,0.1367,0.0564,18.5994 -Khronos,5x5,ldr-xy-normal2.png,45.6138,0.3779,0.1003,41.8306 -Khronos,6x6,ldr-l-occlusion.png,48.3038,0.0387,0.0133,78.7983 -Khronos,6x6,ldr-rgb-diffuse.png,43.2173,0.2492,0.0901,46.5734 -Khronos,6x6,ldr-rgb-emissive.png,48.9702,0.0394,0.0112,93.7490 -Khronos,6x6,ldr-rgb-metalrough.png,36.2530,0.0882,0.0460,22.7719 -Khronos,6x6,ldr-rgb-metalrough2.png,35.0960,0.4539,0.2791,15.0299 -Khronos,6x6,ldr-rgba-base.png,35.9357,0.1001,0.0505,20.7532 -Khronos,6x6,ldr-rgba-diffuse.png,35.9044,0.0990,0.0515,20.3801 -Khronos,6x6,ldr-rgba-specgloss.png,35.8773,0.1136,0.0599,17.5028 -Khronos,6x6,ldr-xy-normal1.png,38.8396,0.1378,0.0574,18.2704 -Khronos,6x6,ldr-xy-normal2.png,43.4426,0.3758,0.0973,43.1273 -Khronos,8x8,ldr-l-occlusion.png,43.4865,0.0405,0.0122,85.8222 -Khronos,8x8,ldr-rgb-diffuse.png,38.2787,0.2538,0.0988,42.4426 -Khronos,8x8,ldr-rgb-emissive.png,44.2565,0.0417,0.0105,99.6837 -Khronos,8x8,ldr-rgb-metalrough.png,32.2167,0.1073,0.0619,16.9330 -Khronos,8x8,ldr-rgb-metalrough2.png,32.0902,0.4417,0.2659,15.7752 -Khronos,8x8,ldr-rgba-base.png,32.2303,0.1141,0.0610,17.1942 -Khronos,8x8,ldr-rgba-diffuse.png,32.0058,0.1246,0.0737,14.2251 -Khronos,8x8,ldr-rgba-specgloss.png,32.8371,0.1246,0.0683,15.3592 -Khronos,8x8,ldr-xy-normal1.png,36.2071,0.1358,0.0524,20.0225 -Khronos,8x8,ldr-xy-normal2.png,40.2733,0.3867,0.1054,39.8104 -Khronos,12x12,ldr-l-occlusion.png,40.2271,0.0444,0.0116,90.6589 -Khronos,12x12,ldr-rgb-diffuse.png,33.3234,0.2338,0.0749,56.0279 -Khronos,12x12,ldr-rgb-emissive.png,39.2738,0.0455,0.0101,103.8721 -Khronos,12x12,ldr-rgb-metalrough.png,28.5929,0.0873,0.0374,28.0316 -Khronos,12x12,ldr-rgb-metalrough2.png,29.1679,0.3039,0.1251,33.5324 -Khronos,12x12,ldr-rgba-base.png,28.9701,0.1059,0.0490,21.4069 -Khronos,12x12,ldr-rgba-diffuse.png,28.5748,0.1109,0.0564,18.5957 -Khronos,12x12,ldr-rgba-specgloss.png,29.7683,0.0994,0.0398,26.3613 -Khronos,12x12,ldr-xy-normal1.png,32.6096,0.1254,0.0368,28.4575 -Khronos,12x12,ldr-xy-normal2.png,36.0023,0.3763,0.0930,45.0908 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 12f6ed2..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,67.9245,0.0526,0.0268,39.1157 -Khronos,4x4,ldr-rgb-diffuse.png,54.0221,0.4617,0.3060,13.7058 -Khronos,4x4,ldr-rgb-emissive.png,59.8356,0.0549,0.0265,39.6406 -Khronos,4x4,ldr-rgb-metalrough.png,44.8439,0.2722,0.2285,4.5886 -Khronos,4x4,ldr-rgb-metalrough2.png,43.7387,1.6815,1.5116,2.7747 -Khronos,4x4,ldr-rgba-base.png,43.8181,0.3440,0.2944,3.5613 -Khronos,4x4,ldr-rgba-diffuse.png,44.2283,0.2512,0.2029,5.1672 -Khronos,4x4,ldr-rgba-specgloss.png,42.2924,0.4609,0.4074,2.5736 -Khronos,4x4,ldr-xy-normal1.png,46.4815,0.4048,0.3227,3.2499 -Khronos,4x4,ldr-xy-normal2.png,50.2696,0.9086,0.6548,6.4054 -Khronos,5x5,ldr-l-occlusion.png,57.1580,0.0560,0.0282,37.2167 -Khronos,5x5,ldr-rgb-diffuse.png,48.9900,0.4727,0.3157,13.2850 -Khronos,5x5,ldr-rgb-emissive.png,55.3732,0.0576,0.0279,37.6442 -Khronos,5x5,ldr-rgb-metalrough.png,40.2386,0.3073,0.2618,4.0051 -Khronos,5x5,ldr-rgb-metalrough2.png,39.0265,2.0781,1.9019,2.2053 -Khronos,5x5,ldr-rgba-base.png,39.3979,0.3988,0.3466,3.0253 -Khronos,5x5,ldr-rgba-diffuse.png,39.5646,0.3194,0.2694,3.8919 -Khronos,5x5,ldr-rgba-specgloss.png,38.7813,0.5136,0.4585,2.2868 -Khronos,5x5,ldr-xy-normal1.png,43.0494,0.3912,0.3093,3.3900 -Khronos,5x5,ldr-xy-normal2.png,47.2289,0.7928,0.5195,8.0732 -Khronos,6x6,ldr-l-occlusion.png,50.8663,0.0660,0.0380,27.6136 -Khronos,6x6,ldr-rgb-diffuse.png,44.9305,0.4927,0.3328,12.6049 -Khronos,6x6,ldr-rgb-emissive.png,51.5230,0.0579,0.0277,37.8493 -Khronos,6x6,ldr-rgb-metalrough.png,36.8282,0.3281,0.2831,3.7041 -Khronos,6x6,ldr-rgb-metalrough2.png,36.4385,2.0877,1.9101,2.1958 -Khronos,6x6,ldr-rgba-base.png,36.6372,0.3749,0.3223,3.2536 -Khronos,6x6,ldr-rgba-diffuse.png,36.4889,0.3492,0.2991,3.5056 -Khronos,6x6,ldr-rgba-specgloss.png,36.4896,0.5348,0.4795,2.1867 -Khronos,6x6,ldr-xy-normal1.png,40.6311,0.3377,0.2536,4.1351 -Khronos,6x6,ldr-xy-normal2.png,45.1540,0.5663,0.2863,14.6496 -Khronos,8x8,ldr-l-occlusion.png,45.4494,0.0777,0.0463,22.6240 -Khronos,8x8,ldr-rgb-diffuse.png,40.2397,0.6532,0.4935,8.4987 -Khronos,8x8,ldr-rgb-emissive.png,46.7056,0.0677,0.0334,31.4086 -Khronos,8x8,ldr-rgb-metalrough.png,32.6674,0.4406,0.3921,2.6742 -Khronos,8x8,ldr-rgb-metalrough2.png,33.1989,2.3871,2.2108,1.8972 -Khronos,8x8,ldr-rgba-base.png,33.0632,0.4168,0.3610,2.9048 -Khronos,8x8,ldr-rgba-diffuse.png,32.5747,0.4764,0.4215,2.4878 -Khronos,8x8,ldr-rgba-specgloss.png,33.4751,0.5866,0.5269,1.9903 -Khronos,8x8,ldr-xy-normal1.png,37.4171,0.3863,0.2968,3.5326 -Khronos,8x8,ldr-xy-normal2.png,42.0727,0.6099,0.3244,12.9311 -Khronos,12x12,ldr-l-occlusion.png,41.6742,0.0675,0.0285,36.7653 -Khronos,12x12,ldr-rgb-diffuse.png,35.7658,0.5883,0.4194,10.0015 -Khronos,12x12,ldr-rgb-emissive.png,41.3741,0.0790,0.0367,28.5380 -Khronos,12x12,ldr-rgb-metalrough.png,29.0892,0.3861,0.3300,3.1779 -Khronos,12x12,ldr-rgb-metalrough2.png,30.1599,1.5251,1.3372,3.1366 -Khronos,12x12,ldr-rgba-base.png,29.6109,0.3927,0.3275,3.2019 -Khronos,12x12,ldr-rgba-diffuse.png,29.0613,0.5317,0.4699,2.2313 -Khronos,12x12,ldr-rgba-specgloss.png,30.4743,0.4166,0.3493,3.0019 -Khronos,12x12,ldr-xy-normal1.png,33.4993,0.3454,0.2490,4.2108 -Khronos,12x12,ldr-xy-normal2.png,37.8161,0.6426,0.3499,11.9875 diff --git a/Test/Images/Khronos/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/Khronos/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 5b33740..0000000 --- a/Test/Images/Khronos/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,51 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Khronos,4x4,ldr-l-occlusion.png,70.5315,0.1035,0.0773,13.5691 -Khronos,4x4,ldr-rgb-diffuse.png,54.7187,2.1796,2.0238,2.0724 -Khronos,4x4,ldr-rgb-emissive.png,60.8411,0.0872,0.0585,17.9238 -Khronos,4x4,ldr-rgb-metalrough.png,44.9834,0.6117,0.5690,1.8429 -Khronos,4x4,ldr-rgb-metalrough2.png,44.0109,3.5575,3.3844,1.2393 -Khronos,4x4,ldr-rgba-base.png,44.0067,0.8048,0.7540,1.3906 -Khronos,4x4,ldr-rgba-diffuse.png,44.4135,0.5796,0.5311,1.9743 -Khronos,4x4,ldr-rgba-specgloss.png,42.4620,1.0263,0.9726,1.0781 -Khronos,4x4,ldr-xy-normal1.png,46.6816,1.1963,1.1171,0.9387 -Khronos,4x4,ldr-xy-normal2.png,50.5731,3.1594,2.9096,1.4415 -Khronos,5x5,ldr-l-occlusion.png,58.7308,0.1880,0.1604,6.5373 -Khronos,5x5,ldr-rgb-diffuse.png,49.7919,1.9859,1.8249,2.2983 -Khronos,5x5,ldr-rgb-emissive.png,56.1398,0.1012,0.0714,14.6841 -Khronos,5x5,ldr-rgb-metalrough.png,40.4561,0.7671,0.7222,1.4520 -Khronos,5x5,ldr-rgb-metalrough2.png,39.4939,4.4480,4.2712,0.9820 -Khronos,5x5,ldr-rgba-base.png,39.7539,0.9879,0.9353,1.1211 -Khronos,5x5,ldr-rgba-diffuse.png,39.8978,0.7282,0.6784,1.5456 -Khronos,5x5,ldr-rgba-specgloss.png,39.0262,1.2268,1.1715,0.8951 -Khronos,5x5,ldr-xy-normal1.png,43.4105,1.4933,1.4107,0.7433 -Khronos,5x5,ldr-xy-normal2.png,47.7893,4.3236,4.0619,1.0326 -Khronos,6x6,ldr-l-occlusion.png,52.2696,0.2620,0.2340,4.4813 -Khronos,6x6,ldr-rgb-diffuse.png,45.7745,1.9165,1.7569,2.3874 -Khronos,6x6,ldr-rgb-emissive.png,52.6625,0.1140,0.0835,12.5527 -Khronos,6x6,ldr-rgb-metalrough.png,37.0147,0.9830,0.9373,1.1187 -Khronos,6x6,ldr-rgb-metalrough2.png,36.7447,5.4681,5.2870,0.7933 -Khronos,6x6,ldr-rgba-base.png,36.8327,1.2103,1.1583,0.9053 -Khronos,6x6,ldr-rgba-diffuse.png,36.6564,0.9085,0.8582,1.2218 -Khronos,6x6,ldr-rgba-specgloss.png,36.6739,1.4683,1.4115,0.7429 -Khronos,6x6,ldr-xy-normal1.png,41.1133,1.3865,1.3025,0.8050 -Khronos,6x6,ldr-xy-normal2.png,45.8124,3.6665,3.3881,1.2380 -Khronos,8x8,ldr-l-occlusion.png,46.0393,0.3299,0.2963,3.5392 -Khronos,8x8,ldr-rgb-diffuse.png,40.8641,2.1190,1.9581,2.1420 -Khronos,8x8,ldr-rgb-emissive.png,47.6060,0.1228,0.0877,11.9625 -Khronos,8x8,ldr-rgb-metalrough.png,32.8279,1.2598,1.2097,0.8668 -Khronos,8x8,ldr-rgb-metalrough2.png,33.5845,7.0352,6.8538,0.6120 -Khronos,8x8,ldr-rgba-base.png,33.2523,1.5600,1.5035,0.6974 -Khronos,8x8,ldr-rgba-diffuse.png,32.7215,1.2334,1.1786,0.8897 -Khronos,8x8,ldr-rgba-specgloss.png,33.6278,1.8922,1.8310,0.5727 -Khronos,8x8,ldr-xy-normal1.png,37.7223,0.9534,0.8633,1.2145 -Khronos,8x8,ldr-xy-normal2.png,42.5159,1.8083,1.5287,2.7436 -Khronos,12x12,ldr-l-occlusion.png,42.4633,0.2682,0.2263,4.6326 -Khronos,12x12,ldr-rgb-diffuse.png,36.6027,2.3875,2.2137,1.8947 -Khronos,12x12,ldr-rgb-emissive.png,42.3476,0.1695,0.1248,8.4039 -Khronos,12x12,ldr-rgb-metalrough.png,29.2644,1.4912,1.4321,0.7322 -Khronos,12x12,ldr-rgb-metalrough2.png,30.7448,7.6917,7.5016,0.5591 -Khronos,12x12,ldr-rgba-base.png,29.9105,1.6103,1.5443,0.6790 -Khronos,12x12,ldr-rgba-diffuse.png,29.2512,1.5374,1.4741,0.7113 -Khronos,12x12,ldr-rgba-specgloss.png,30.6950,2.1464,2.0777,0.5047 -Khronos,12x12,ldr-xy-normal1.png,33.9598,0.9725,0.8733,1.2007 -Khronos,12x12,ldr-xy-normal2.png,38.4366,1.4302,1.1373,3.6878 diff --git a/Test/Images/Khronos/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/Khronos/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..f575796 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0371,0.0070,150.1193 +Khronos,4x4,ldr-rgb-diffuse.png,52.8179,0.2035,0.0544,77.0884 +Khronos,4x4,ldr-rgb-emissive.png,58.5184,0.0390,0.0072,145.7755 +Khronos,4x4,ldr-rgb-metalrough.png,44.3627,0.0860,0.0454,23.1097 +Khronos,4x4,ldr-rgb-metalrough2.png,42.9750,0.4417,0.2885,14.5358 +Khronos,4x4,ldr-rgba-base.png,43.2965,0.1014,0.0571,18.3594 +Khronos,4x4,ldr-rgba-diffuse.png,43.9222,0.0843,0.0404,25.9735 +Khronos,4x4,ldr-rgba-specgloss.png,41.7049,0.1380,0.0911,11.5060 +Khronos,4x4,ldr-xy-normal1.png,44.9872,0.1372,0.0668,15.7066 +Khronos,4x4,ldr-xy-normal2.png,48.6837,0.3518,0.0984,42.6159 +Khronos,5x5,ldr-l-occlusion.png,54.3814,0.0356,0.0054,195.6600 +Khronos,5x5,ldr-rgb-diffuse.png,47.2236,0.1885,0.0418,100.3330 +Khronos,5x5,ldr-rgb-emissive.png,52.6635,0.0377,0.0054,194.4318 +Khronos,5x5,ldr-rgb-metalrough.png,39.9099,0.0743,0.0333,31.5324 +Khronos,5x5,ldr-rgb-metalrough2.png,37.9762,0.4251,0.2700,15.5370 +Khronos,5x5,ldr-rgba-base.png,38.9583,0.0846,0.0396,26.4946 +Khronos,5x5,ldr-rgba-diffuse.png,39.1885,0.0821,0.0381,27.5015 +Khronos,5x5,ldr-rgba-specgloss.png,38.4160,0.1006,0.0538,19.4783 +Khronos,5x5,ldr-xy-normal1.png,41.8334,0.1216,0.0504,20.7874 +Khronos,5x5,ldr-xy-normal2.png,46.1655,0.3323,0.0670,62.6444 +Khronos,6x6,ldr-l-occlusion.png,48.3862,0.0361,0.0062,168.3076 +Khronos,6x6,ldr-rgb-diffuse.png,43.2830,0.1942,0.0540,77.6766 +Khronos,6x6,ldr-rgb-emissive.png,49.1097,0.0368,0.0052,201.0260 +Khronos,6x6,ldr-rgb-metalrough.png,36.5415,0.0768,0.0375,27.9589 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3486,0.4062,0.2557,16.4062 +Khronos,6x6,ldr-rgba-base.png,36.1889,0.0859,0.0427,24.5775 +Khronos,6x6,ldr-rgba-diffuse.png,36.1527,0.0882,0.0450,23.2986 +Khronos,6x6,ldr-rgba-specgloss.png,36.1297,0.1008,0.0554,18.9120 +Khronos,6x6,ldr-xy-normal1.png,39.6460,0.1155,0.0452,23.2103 +Khronos,6x6,ldr-xy-normal2.png,44.1090,0.3196,0.0627,66.8660 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0346,0.0072,145.5536 +Khronos,8x8,ldr-rgb-diffuse.png,38.4150,0.1995,0.0701,59.8528 +Khronos,8x8,ldr-rgb-emissive.png,44.6847,0.0354,0.0062,169.1296 +Khronos,8x8,ldr-rgb-metalrough.png,32.3524,0.0859,0.0481,21.8144 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2210,0.3560,0.2166,19.3615 +Khronos,8x8,ldr-rgba-base.png,32.4716,0.0897,0.0465,22.5326 +Khronos,8x8,ldr-rgba-diffuse.png,32.1743,0.1002,0.0588,17.8350 +Khronos,8x8,ldr-rgba-specgloss.png,32.9565,0.1003,0.0555,18.9045 +Khronos,8x8,ldr-xy-normal1.png,36.5625,0.1082,0.0388,27.0162 +Khronos,8x8,ldr-xy-normal2.png,40.7934,0.3102,0.0693,60.5316 +Khronos,12x12,ldr-l-occlusion.png,40.5804,0.0364,0.0065,161.0239 +Khronos,12x12,ldr-rgb-diffuse.png,33.3731,0.1883,0.0514,81.5869 +Khronos,12x12,ldr-rgb-emissive.png,39.4844,0.0369,0.0054,192.7953 +Khronos,12x12,ldr-rgb-metalrough.png,28.6538,0.0683,0.0289,36.2439 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2618,0.2509,0.1032,40.6540 +Khronos,12x12,ldr-rgba-base.png,29.0434,0.0821,0.0377,27.7944 +Khronos,12x12,ldr-rgba-diffuse.png,28.6314,0.0877,0.0442,23.7283 +Khronos,12x12,ldr-rgba-specgloss.png,29.8201,0.0775,0.0321,32.6577 +Khronos,12x12,ldr-xy-normal1.png,32.7607,0.0971,0.0267,39.2287 +Khronos,12x12,ldr-xy-normal2.png,36.2418,0.3140,0.0622,67.4046 diff --git a/Test/Images/Khronos/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..5988eac --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0360,0.0067,156.0642 +Khronos,4x4,ldr-rgb-diffuse.png,52.5960,0.1928,0.0483,86.8154 +Khronos,4x4,ldr-rgb-emissive.png,57.9317,0.0375,0.0067,155.7547 +Khronos,4x4,ldr-rgb-metalrough.png,43.8926,0.0691,0.0296,35.3854 +Khronos,4x4,ldr-rgb-metalrough2.png,42.6922,0.3298,0.1794,23.3848 +Khronos,4x4,ldr-rgba-base.png,42.8654,0.0804,0.0359,29.2311 +Khronos,4x4,ldr-rgba-diffuse.png,43.3179,0.0688,0.0256,40.9410 +Khronos,4x4,ldr-rgba-specgloss.png,41.4002,0.1026,0.0566,18.5424 +Khronos,4x4,ldr-xy-normal1.png,44.8194,0.1136,0.0434,24.1341 +Khronos,4x4,ldr-xy-normal2.png,48.3518,0.3304,0.0768,54.5843 +Khronos,5x5,ldr-l-occlusion.png,54.2366,0.0351,0.0053,197.1334 +Khronos,5x5,ldr-rgb-diffuse.png,47.0653,0.1820,0.0391,107.3126 +Khronos,5x5,ldr-rgb-emissive.png,52.3476,0.0362,0.0049,214.3924 +Khronos,5x5,ldr-rgb-metalrough.png,39.4280,0.0635,0.0236,44.4126 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4660,0.3255,0.1730,24.2438 +Khronos,5x5,ldr-rgba-base.png,38.3323,0.0713,0.0272,38.5121 +Khronos,5x5,ldr-rgba-diffuse.png,38.5010,0.0680,0.0248,42.3105 +Khronos,5x5,ldr-rgba-specgloss.png,37.9482,0.0819,0.0360,29.1256 +Khronos,5x5,ldr-xy-normal1.png,41.4622,0.1048,0.0349,30.0177 +Khronos,5x5,ldr-xy-normal2.png,45.8286,0.3152,0.0568,73.8252 +Khronos,6x6,ldr-l-occlusion.png,48.3017,0.0345,0.0058,182.2949 +Khronos,6x6,ldr-rgb-diffuse.png,43.2322,0.1868,0.0468,89.6198 +Khronos,6x6,ldr-rgb-emissive.png,49.0036,0.0347,0.0046,229.7590 +Khronos,6x6,ldr-rgb-metalrough.png,36.3590,0.0646,0.0265,39.5554 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1574,0.3081,0.1591,26.3642 +Khronos,6x6,ldr-rgba-base.png,36.0142,0.0711,0.0286,36.6803 +Khronos,6x6,ldr-rgba-diffuse.png,35.9592,0.0705,0.0283,37.0091 +Khronos,6x6,ldr-rgba-specgloss.png,35.9090,0.0807,0.0358,29.2898 +Khronos,6x6,ldr-xy-normal1.png,39.2368,0.1007,0.0320,32.7631 +Khronos,6x6,ldr-xy-normal2.png,43.7398,0.3061,0.0518,81.0009 +Khronos,8x8,ldr-l-occlusion.png,43.5141,0.0338,0.0063,165.8076 +Khronos,8x8,ldr-rgb-diffuse.png,38.2796,0.1852,0.0572,73.2745 +Khronos,8x8,ldr-rgb-emissive.png,44.2626,0.0341,0.0049,213.2179 +Khronos,8x8,ldr-rgb-metalrough.png,32.2702,0.0732,0.0351,29.8357 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1173,0.2956,0.1571,26.6946 +Khronos,8x8,ldr-rgba-base.png,32.3492,0.0758,0.0340,30.7952 +Khronos,8x8,ldr-rgba-diffuse.png,32.0637,0.0829,0.0414,25.3078 +Khronos,8x8,ldr-rgba-specgloss.png,32.8589,0.0849,0.0405,25.8696 +Khronos,8x8,ldr-xy-normal1.png,36.3456,0.0972,0.0297,35.3353 +Khronos,8x8,ldr-xy-normal2.png,40.3507,0.2999,0.0582,72.0731 +Khronos,12x12,ldr-l-occlusion.png,40.2287,0.0349,0.0055,191.7697 +Khronos,12x12,ldr-rgb-diffuse.png,33.3235,0.1786,0.0426,98.4950 +Khronos,12x12,ldr-rgb-emissive.png,39.2827,0.0351,0.0043,246.1961 +Khronos,12x12,ldr-rgb-metalrough.png,28.6080,0.0609,0.0218,48.0204 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1699,0.2255,0.0782,53.6617 +Khronos,12x12,ldr-rgba-base.png,28.9860,0.0704,0.0277,37.8903 +Khronos,12x12,ldr-rgba-diffuse.png,28.5784,0.0739,0.0317,33.0645 +Khronos,12x12,ldr-rgba-specgloss.png,29.7728,0.0689,0.0241,43.4409 +Khronos,12x12,ldr-xy-normal1.png,32.6323,0.0902,0.0204,51.4518 +Khronos,12x12,ldr-xy-normal2.png,36.0168,0.3018,0.0502,83.6154 diff --git a/Test/Images/Khronos/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/Khronos/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..8b9c4b6 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.5687,0.0425,0.0117,89.4694 +Khronos,4x4,ldr-rgb-diffuse.png,54.2509,0.2965,0.1537,27.2964 +Khronos,4x4,ldr-rgb-emissive.png,59.8692,0.0455,0.0135,77.7755 +Khronos,4x4,ldr-rgb-metalrough.png,44.9162,0.1772,0.1370,7.6563 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8012,1.1020,0.9514,4.4085 +Khronos,4x4,ldr-rgba-base.png,43.8387,0.2194,0.1740,6.0251 +Khronos,4x4,ldr-rgba-diffuse.png,44.2480,0.1591,0.1142,9.1805 +Khronos,4x4,ldr-rgba-specgloss.png,42.3086,0.2922,0.2444,4.2902 +Khronos,4x4,ldr-xy-normal1.png,46.5096,0.2679,0.1988,5.2753 +Khronos,4x4,ldr-xy-normal2.png,50.2692,0.6291,0.3897,10.7634 +Khronos,5x5,ldr-l-occlusion.png,57.1506,0.0450,0.0131,80.1846 +Khronos,5x5,ldr-rgb-diffuse.png,49.0125,0.2911,0.1483,28.2778 +Khronos,5x5,ldr-rgb-emissive.png,55.4137,0.0459,0.0131,80.2578 +Khronos,5x5,ldr-rgb-metalrough.png,40.3176,0.1661,0.1243,8.4335 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1297,1.1231,0.9711,4.3190 +Khronos,5x5,ldr-rgba-base.png,39.4682,0.2094,0.1636,6.4078 +Khronos,5x5,ldr-rgba-diffuse.png,39.6061,0.1695,0.1245,8.4253 +Khronos,5x5,ldr-rgba-specgloss.png,38.7834,0.2662,0.2189,4.7905 +Khronos,5x5,ldr-xy-normal1.png,43.0303,0.2425,0.1719,6.0990 +Khronos,5x5,ldr-xy-normal2.png,47.2313,0.5466,0.2903,14.4473 +Khronos,6x6,ldr-l-occlusion.png,50.8594,0.0488,0.0184,56.9135 +Khronos,6x6,ldr-rgb-diffuse.png,44.9402,0.2967,0.1530,27.4216 +Khronos,6x6,ldr-rgb-emissive.png,51.5373,0.0460,0.0132,79.3413 +Khronos,6x6,ldr-rgb-metalrough.png,36.8816,0.1626,0.1218,8.6075 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5008,1.0432,0.8924,4.7001 +Khronos,6x6,ldr-rgba-base.png,36.6975,0.1885,0.1440,7.2806 +Khronos,6x6,ldr-rgba-diffuse.png,36.5302,0.1741,0.1299,8.0716 +Khronos,6x6,ldr-rgba-specgloss.png,36.4921,0.2527,0.2059,5.0926 +Khronos,6x6,ldr-xy-normal1.png,40.6408,0.2053,0.1348,7.7804 +Khronos,6x6,ldr-xy-normal2.png,45.1534,0.4106,0.1556,26.9638 +Khronos,8x8,ldr-l-occlusion.png,45.4584,0.0545,0.0257,40.8706 +Khronos,8x8,ldr-rgb-diffuse.png,40.2308,0.3655,0.2353,17.8269 +Khronos,8x8,ldr-rgb-emissive.png,46.6998,0.0480,0.0173,60.6117 +Khronos,8x8,ldr-rgb-metalrough.png,32.6999,0.2036,0.1645,6.3758 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2345,1.1435,1.0013,4.1888 +Khronos,8x8,ldr-rgba-base.png,33.0850,0.2094,0.1664,6.3023 +Khronos,8x8,ldr-rgba-diffuse.png,32.5888,0.2199,0.1769,5.9280 +Khronos,8x8,ldr-rgba-specgloss.png,33.4811,0.2785,0.2324,4.5116 +Khronos,8x8,ldr-xy-normal1.png,37.4281,0.2143,0.1423,7.3684 +Khronos,8x8,ldr-xy-normal2.png,42.0637,0.4116,0.1671,25.0961 +Khronos,12x12,ldr-l-occlusion.png,41.6347,0.0471,0.0149,70.2709 +Khronos,12x12,ldr-rgb-diffuse.png,35.7680,0.3823,0.2401,17.4677 +Khronos,12x12,ldr-rgb-emissive.png,41.4121,0.0537,0.0195,53.7343 +Khronos,12x12,ldr-rgb-metalrough.png,29.1213,0.1935,0.1513,6.9306 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1727,0.8369,0.6861,6.1130 +Khronos,12x12,ldr-rgba-base.png,29.6476,0.2015,0.1549,6.7688 +Khronos,12x12,ldr-rgba-diffuse.png,29.0758,0.2479,0.2025,5.1779 +Khronos,12x12,ldr-rgba-specgloss.png,30.4831,0.2300,0.1817,5.7696 +Khronos,12x12,ldr-xy-normal1.png,33.5197,0.1870,0.1127,9.3065 +Khronos,12x12,ldr-xy-normal2.png,37.8214,0.4292,0.1730,24.2417 diff --git a/Test/Images/Khronos/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..b0a926f --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.4255,0.0703,0.0393,26.6928 +Khronos,4x4,ldr-rgb-diffuse.png,54.7764,1.0447,0.9019,4.6506 +Khronos,4x4,ldr-rgb-emissive.png,60.8826,0.0620,0.0291,35.9903 +Khronos,4x4,ldr-rgb-metalrough.png,45.0480,0.3578,0.3161,3.3174 +Khronos,4x4,ldr-rgb-metalrough2.png,44.0818,2.2280,2.0757,2.0207 +Khronos,4x4,ldr-rgba-base.png,44.0332,0.4541,0.4087,2.5656 +Khronos,4x4,ldr-rgba-diffuse.png,44.4445,0.3137,0.2693,3.8944 +Khronos,4x4,ldr-rgba-specgloss.png,42.4764,0.5815,0.5333,1.9664 +Khronos,4x4,ldr-xy-normal1.png,46.6603,0.7324,0.6621,1.5837 +Khronos,4x4,ldr-xy-normal2.png,50.5464,1.8337,1.5966,2.6271 +Khronos,5x5,ldr-l-occlusion.png,58.7464,0.1079,0.0761,13.7820 +Khronos,5x5,ldr-rgb-diffuse.png,49.8233,0.9135,0.7696,5.4503 +Khronos,5x5,ldr-rgb-emissive.png,56.1632,0.0672,0.0336,31.2066 +Khronos,5x5,ldr-rgb-metalrough.png,40.5315,0.3661,0.3243,3.2338 +Khronos,5x5,ldr-rgb-metalrough2.png,39.5945,2.3561,2.2027,1.9042 +Khronos,5x5,ldr-rgba-base.png,39.8027,0.4739,0.4273,2.4542 +Khronos,5x5,ldr-rgba-diffuse.png,39.9365,0.3477,0.3026,3.4656 +Khronos,5x5,ldr-rgba-specgloss.png,39.0414,0.5838,0.5361,1.9559 +Khronos,5x5,ldr-xy-normal1.png,43.3853,0.8310,0.7608,1.3783 +Khronos,5x5,ldr-xy-normal2.png,47.7847,2.3680,2.1236,1.9751 +Khronos,6x6,ldr-l-occlusion.png,52.2712,0.1322,0.1011,10.3744 +Khronos,6x6,ldr-rgb-diffuse.png,45.7889,0.8833,0.7430,5.6450 +Khronos,6x6,ldr-rgb-emissive.png,52.6833,0.0703,0.0379,27.6816 +Khronos,6x6,ldr-rgb-metalrough.png,37.0684,0.4037,0.3632,2.8874 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8174,2.5307,2.3791,1.7630 +Khronos,6x6,ldr-rgba-base.png,36.9100,0.5088,0.4625,2.2673 +Khronos,6x6,ldr-rgba-diffuse.png,36.7066,0.3809,0.3367,3.1142 +Khronos,6x6,ldr-rgba-specgloss.png,36.6855,0.6095,0.5610,1.8690 +Khronos,6x6,ldr-xy-normal1.png,41.0976,0.7191,0.6479,1.6185 +Khronos,6x6,ldr-xy-normal2.png,45.7894,1.9277,1.6762,2.5023 +Khronos,8x8,ldr-l-occlusion.png,46.0363,0.1675,0.1372,7.6450 +Khronos,8x8,ldr-rgb-diffuse.png,40.8626,1.0003,0.8646,4.8513 +Khronos,8x8,ldr-rgb-emissive.png,47.5792,0.0739,0.0420,24.9389 +Khronos,8x8,ldr-rgb-metalrough.png,32.8612,0.5115,0.4703,2.2298 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6302,3.0730,2.9331,1.4300 +Khronos,8x8,ldr-rgba-base.png,33.2969,0.6392,0.5940,1.7652 +Khronos,8x8,ldr-rgba-diffuse.png,32.7445,0.5015,0.4578,2.2904 +Khronos,8x8,ldr-rgba-specgloss.png,33.6408,0.7511,0.7036,1.4903 +Khronos,8x8,ldr-xy-normal1.png,37.7175,0.5080,0.4360,2.4047 +Khronos,8x8,ldr-xy-normal2.png,42.5021,1.0866,0.8407,4.9888 +Khronos,12x12,ldr-l-occlusion.png,42.4458,0.1652,0.1305,8.0327 +Khronos,12x12,ldr-rgb-diffuse.png,36.6053,1.2218,1.0791,3.8868 +Khronos,12x12,ldr-rgb-emissive.png,42.3646,0.1050,0.0678,15.4632 +Khronos,12x12,ldr-rgb-metalrough.png,29.3020,0.6908,0.6456,1.6241 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7710,3.6073,3.4534,1.2145 +Khronos,12x12,ldr-rgba-base.png,29.9273,0.7375,0.6885,1.5230 +Khronos,12x12,ldr-rgba-diffuse.png,29.2650,0.6859,0.6377,1.6442 +Khronos,12x12,ldr-rgba-specgloss.png,30.7044,0.9539,0.9027,1.1616 +Khronos,12x12,ldr-xy-normal1.png,33.9544,0.5084,0.4330,2.4219 +Khronos,12x12,ldr-xy-normal2.png,38.4422,0.8885,0.6334,6.6219 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..367c0d4 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0415,0.0096,108.7629 +Khronos,4x4,ldr-rgb-diffuse.png,52.8179,0.2312,0.0800,52.4446 +Khronos,4x4,ldr-rgb-emissive.png,58.5184,0.0420,0.0080,130.4052 +Khronos,4x4,ldr-rgb-metalrough.png,44.3627,0.1039,0.0606,17.2936 +Khronos,4x4,ldr-rgb-metalrough2.png,42.9750,0.5459,0.3818,10.9848 +Khronos,4x4,ldr-rgba-base.png,43.2965,0.1229,0.0758,13.8360 +Khronos,4x4,ldr-rgba-diffuse.png,43.9222,0.0996,0.0538,19.4924 +Khronos,4x4,ldr-rgba-specgloss.png,41.7049,0.1696,0.1209,8.6763 +Khronos,4x4,ldr-xy-normal1.png,44.9872,0.1633,0.0898,11.6789 +Khronos,4x4,ldr-xy-normal2.png,48.6837,0.3941,0.1379,30.4098 +Khronos,5x5,ldr-l-occlusion.png,54.3814,0.0391,0.0071,147.3333 +Khronos,5x5,ldr-rgb-diffuse.png,47.2236,0.2078,0.0587,71.4801 +Khronos,5x5,ldr-rgb-emissive.png,52.6635,0.0406,0.0063,165.4956 +Khronos,5x5,ldr-rgb-metalrough.png,39.9099,0.0889,0.0471,22.2485 +Khronos,5x5,ldr-rgb-metalrough2.png,37.9762,0.5365,0.3757,11.1628 +Khronos,5x5,ldr-rgba-base.png,38.9583,0.1018,0.0557,18.8359 +Khronos,5x5,ldr-rgba-diffuse.png,39.1885,0.0991,0.0537,19.5393 +Khronos,5x5,ldr-rgba-specgloss.png,38.4160,0.1252,0.0768,13.6597 +Khronos,5x5,ldr-xy-normal1.png,41.8334,0.1439,0.0701,14.9498 +Khronos,5x5,ldr-xy-normal2.png,46.1655,0.3565,0.0929,45.1340 +Khronos,6x6,ldr-l-occlusion.png,48.3862,0.0399,0.0088,119.3889 +Khronos,6x6,ldr-rgb-diffuse.png,43.2830,0.2294,0.0829,50.6107 +Khronos,6x6,ldr-rgb-emissive.png,49.1097,0.0401,0.0066,159.9639 +Khronos,6x6,ldr-rgb-metalrough.png,36.5415,0.0985,0.0563,18.6314 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3486,0.5346,0.3765,11.1397 +Khronos,6x6,ldr-rgba-base.png,36.1889,0.1096,0.0635,16.5133 +Khronos,6x6,ldr-rgba-diffuse.png,36.1527,0.1118,0.0670,15.6411 +Khronos,6x6,ldr-rgba-specgloss.png,36.1297,0.1314,0.0833,12.5817 +Khronos,6x6,ldr-xy-normal1.png,39.6460,0.1392,0.0658,15.9467 +Khronos,6x6,ldr-xy-normal2.png,44.1090,0.3527,0.0907,46.2417 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0396,0.0105,99.8830 +Khronos,8x8,ldr-rgb-diffuse.png,38.4150,0.2531,0.1093,38.3654 +Khronos,8x8,ldr-rgb-emissive.png,44.6847,0.0404,0.0088,119.3726 +Khronos,8x8,ldr-rgb-metalrough.png,32.3524,0.1168,0.0745,14.0663 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2210,0.4915,0.3359,12.4855 +Khronos,8x8,ldr-rgba-base.png,32.4716,0.1168,0.0704,14.8929 +Khronos,8x8,ldr-rgba-diffuse.png,32.1743,0.1350,0.0908,11.5490 +Khronos,8x8,ldr-rgba-specgloss.png,32.9565,0.1332,0.0854,12.2801 +Khronos,8x8,ldr-xy-normal1.png,36.5625,0.1320,0.0588,17.8472 +Khronos,8x8,ldr-xy-normal2.png,40.7934,0.3632,0.1046,40.1035 +Khronos,12x12,ldr-l-occlusion.png,40.5804,0.0412,0.0098,106.7928 +Khronos,12x12,ldr-rgb-diffuse.png,33.3731,0.2247,0.0784,53.4654 +Khronos,12x12,ldr-rgb-emissive.png,39.4844,0.0416,0.0079,132.2641 +Khronos,12x12,ldr-rgb-metalrough.png,28.6538,0.0862,0.0432,24.2731 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2618,0.3131,0.1561,26.8656 +Khronos,12x12,ldr-rgba-base.png,29.0434,0.1041,0.0569,18.4333 +Khronos,12x12,ldr-rgba-diffuse.png,28.6314,0.1129,0.0668,15.6912 +Khronos,12x12,ldr-rgba-specgloss.png,29.8201,0.0975,0.0479,21.8991 +Khronos,12x12,ldr-xy-normal1.png,32.7607,0.1147,0.0398,26.3528 +Khronos,12x12,ldr-xy-normal2.png,36.2418,0.3535,0.0922,45.5116 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..aeb95f0 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0399,0.0088,119.3726 +Khronos,4x4,ldr-rgb-diffuse.png,52.5960,0.2194,0.0693,60.5466 +Khronos,4x4,ldr-rgb-emissive.png,57.9317,0.0407,0.0071,148.1872 +Khronos,4x4,ldr-rgb-metalrough.png,43.8926,0.0819,0.0401,26.1561 +Khronos,4x4,ldr-rgb-metalrough2.png,42.6922,0.4025,0.2399,17.4813 +Khronos,4x4,ldr-rgba-base.png,42.8654,0.0942,0.0480,21.8567 +Khronos,4x4,ldr-rgba-diffuse.png,43.3179,0.0799,0.0343,30.5868 +Khronos,4x4,ldr-rgba-specgloss.png,41.4002,0.1237,0.0753,13.9181 +Khronos,4x4,ldr-xy-normal1.png,44.8194,0.1308,0.0581,18.0459 +Khronos,4x4,ldr-xy-normal2.png,48.3518,0.3660,0.1069,39.2258 +Khronos,5x5,ldr-l-occlusion.png,54.2366,0.0381,0.0069,151.4166 +Khronos,5x5,ldr-rgb-diffuse.png,47.0653,0.2030,0.0551,76.1109 +Khronos,5x5,ldr-rgb-emissive.png,52.3476,0.0396,0.0056,186.8805 +Khronos,5x5,ldr-rgb-metalrough.png,39.4280,0.0754,0.0338,31.0579 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4660,0.4040,0.2449,17.1284 +Khronos,5x5,ldr-rgba-base.png,38.3323,0.0846,0.0387,27.0811 +Khronos,5x5,ldr-rgba-diffuse.png,38.5010,0.0796,0.0352,29.8221 +Khronos,5x5,ldr-rgba-specgloss.png,37.9482,0.0995,0.0519,20.2127 +Khronos,5x5,ldr-xy-normal1.png,41.4622,0.1212,0.0485,21.6126 +Khronos,5x5,ldr-xy-normal2.png,45.8286,0.3416,0.0789,53.1569 +Khronos,6x6,ldr-l-occlusion.png,48.3017,0.0384,0.0081,129.9813 +Khronos,6x6,ldr-rgb-diffuse.png,43.2322,0.2172,0.0715,58.7019 +Khronos,6x6,ldr-rgb-emissive.png,49.0036,0.0382,0.0056,188.2887 +Khronos,6x6,ldr-rgb-metalrough.png,36.3590,0.0815,0.0404,25.9619 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1574,0.3966,0.2401,17.4691 +Khronos,6x6,ldr-rgba-base.png,36.0142,0.0881,0.0430,24.3962 +Khronos,6x6,ldr-rgba-diffuse.png,35.9592,0.0871,0.0432,24.2568 +Khronos,6x6,ldr-rgba-specgloss.png,35.9090,0.1026,0.0550,19.0508 +Khronos,6x6,ldr-xy-normal1.png,39.2368,0.1195,0.0468,22.4189 +Khronos,6x6,ldr-xy-normal2.png,43.7398,0.3357,0.0752,55.8080 +Khronos,8x8,ldr-l-occlusion.png,43.5141,0.0378,0.0090,116.2889 +Khronos,8x8,ldr-rgb-diffuse.png,38.2796,0.2314,0.0879,47.7053 +Khronos,8x8,ldr-rgb-emissive.png,44.2626,0.0379,0.0068,154.5180 +Khronos,8x8,ldr-rgb-metalrough.png,32.2702,0.0961,0.0541,19.3743 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1173,0.3955,0.2411,17.3934 +Khronos,8x8,ldr-rgba-base.png,32.3492,0.0964,0.0513,20.4389 +Khronos,8x8,ldr-rgba-diffuse.png,32.0637,0.1077,0.0639,16.4176 +Khronos,8x8,ldr-rgba-specgloss.png,32.8589,0.1096,0.0619,16.9459 +Khronos,8x8,ldr-xy-normal1.png,36.3456,0.1172,0.0445,23.5730 +Khronos,8x8,ldr-xy-normal2.png,40.3507,0.3451,0.0867,48.3968 +Khronos,12x12,ldr-l-occlusion.png,40.2287,0.0388,0.0081,129.1682 +Khronos,12x12,ldr-rgb-diffuse.png,33.3235,0.2097,0.0644,65.1695 +Khronos,12x12,ldr-rgb-emissive.png,39.2827,0.0390,0.0060,174.3596 +Khronos,12x12,ldr-rgb-metalrough.png,28.6080,0.0749,0.0325,32.2657 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1699,0.2733,0.1175,35.6923 +Khronos,12x12,ldr-rgba-base.png,28.9860,0.0877,0.0416,25.2195 +Khronos,12x12,ldr-rgba-diffuse.png,28.5784,0.0932,0.0478,21.9538 +Khronos,12x12,ldr-rgba-specgloss.png,29.7728,0.0845,0.0358,29.2922 +Khronos,12x12,ldr-xy-normal1.png,32.6323,0.1035,0.0299,35.0297 +Khronos,12x12,ldr-xy-normal2.png,36.0168,0.3341,0.0738,56.7964 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..69b02ae --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.5687,0.0497,0.0171,61.1451 +Khronos,4x4,ldr-rgb-diffuse.png,54.2509,0.3701,0.2170,19.3278 +Khronos,4x4,ldr-rgb-emissive.png,59.8692,0.0510,0.0164,64.0778 +Khronos,4x4,ldr-rgb-metalrough.png,44.9162,0.2284,0.1851,5.6652 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8012,1.4463,1.2816,3.2727 +Khronos,4x4,ldr-rgba-base.png,43.8387,0.2828,0.2356,4.4510 +Khronos,4x4,ldr-rgba-diffuse.png,44.2480,0.1984,0.1522,6.8893 +Khronos,4x4,ldr-rgba-specgloss.png,42.3086,0.3810,0.3313,3.1651 +Khronos,4x4,ldr-xy-normal1.png,46.5096,0.3382,0.2657,3.9468 +Khronos,4x4,ldr-xy-normal2.png,50.2692,0.7803,0.5330,7.8688 +Khronos,5x5,ldr-l-occlusion.png,57.1506,0.0520,0.0188,55.7307 +Khronos,5x5,ldr-rgb-diffuse.png,49.0125,0.3701,0.2194,19.1154 +Khronos,5x5,ldr-rgb-emissive.png,55.4137,0.0532,0.0176,59.4974 +Khronos,5x5,ldr-rgb-metalrough.png,40.3176,0.2227,0.1793,5.8471 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1297,1.5655,1.4040,2.9874 +Khronos,5x5,ldr-rgba-base.png,39.4682,0.2843,0.2375,4.4157 +Khronos,5x5,ldr-rgba-diffuse.png,39.6061,0.2268,0.1801,5.8229 +Khronos,5x5,ldr-rgba-specgloss.png,38.7834,0.3660,0.3162,3.3160 +Khronos,5x5,ldr-xy-normal1.png,43.0303,0.3241,0.2496,4.2005 +Khronos,5x5,ldr-xy-normal2.png,47.2313,0.6870,0.4270,9.8238 +Khronos,6x6,ldr-l-occlusion.png,50.8594,0.0607,0.0283,37.0156 +Khronos,6x6,ldr-rgb-diffuse.png,44.9402,0.3870,0.2386,17.5756 +Khronos,6x6,ldr-rgb-emissive.png,51.5373,0.0534,0.0190,55.3081 +Khronos,6x6,ldr-rgb-metalrough.png,36.8816,0.2260,0.1831,5.7272 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5008,1.4848,1.3241,3.1677 +Khronos,6x6,ldr-rgba-base.png,36.6975,0.2627,0.2160,4.8555 +Khronos,6x6,ldr-rgba-diffuse.png,36.5302,0.2411,0.1950,5.3781 +Khronos,6x6,ldr-rgba-specgloss.png,36.4921,0.3535,0.3043,3.4461 +Khronos,6x6,ldr-xy-normal1.png,40.6408,0.2754,0.2011,5.2140 +Khronos,6x6,ldr-xy-normal2.png,45.1534,0.4950,0.2327,18.0256 +Khronos,8x8,ldr-l-occlusion.png,45.4584,0.0713,0.0407,25.7369 +Khronos,8x8,ldr-rgb-diffuse.png,40.2308,0.5254,0.3784,11.0843 +Khronos,8x8,ldr-rgb-emissive.png,46.6998,0.0600,0.0263,39.8442 +Khronos,8x8,ldr-rgb-metalrough.png,32.6999,0.2980,0.2541,4.1260 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2345,1.6888,1.5320,2.7377 +Khronos,8x8,ldr-rgba-base.png,33.0850,0.3040,0.2580,4.0643 +Khronos,8x8,ldr-rgba-diffuse.png,32.5888,0.3173,0.2717,3.8598 +Khronos,8x8,ldr-rgba-specgloss.png,33.4811,0.4078,0.3586,2.9238 +Khronos,8x8,ldr-xy-normal1.png,37.4281,0.2942,0.2188,4.7918 +Khronos,8x8,ldr-xy-normal2.png,42.0637,0.5227,0.2615,16.0414 +Khronos,12x12,ldr-l-occlusion.png,41.6347,0.0563,0.0226,46.3787 +Khronos,12x12,ldr-rgb-diffuse.png,35.7680,0.5245,0.3758,11.1618 +Khronos,12x12,ldr-rgb-emissive.png,41.4121,0.0651,0.0290,36.0978 +Khronos,12x12,ldr-rgb-metalrough.png,29.1213,0.2747,0.2283,4.5931 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1727,1.1983,1.0386,4.0383 +Khronos,12x12,ldr-rgba-base.png,29.6476,0.2832,0.2324,4.5119 +Khronos,12x12,ldr-rgba-diffuse.png,29.0758,0.3493,0.3006,3.4879 +Khronos,12x12,ldr-rgba-specgloss.png,30.4831,0.3257,0.2738,3.8302 +Khronos,12x12,ldr-xy-normal1.png,33.5197,0.2451,0.1668,6.2855 +Khronos,12x12,ldr-xy-normal2.png,37.8214,0.5255,0.2612,16.0602 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..dd88d12 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.4255,0.0879,0.0552,18.9918 +Khronos,4x4,ldr-rgb-diffuse.png,54.7764,1.3799,1.2276,3.4165 +Khronos,4x4,ldr-rgb-emissive.png,60.8826,0.0726,0.0378,27.7423 +Khronos,4x4,ldr-rgb-metalrough.png,45.0480,0.4709,0.4267,2.4574 +Khronos,4x4,ldr-rgb-metalrough2.png,44.0818,2.9605,2.7954,1.5004 +Khronos,4x4,ldr-rgba-base.png,44.0332,0.5959,0.5474,1.9155 +Khronos,4x4,ldr-rgba-diffuse.png,44.4445,0.4050,0.3585,2.9246 +Khronos,4x4,ldr-rgba-specgloss.png,42.4764,0.7701,0.7207,1.4550 +Khronos,4x4,ldr-xy-normal1.png,46.6603,0.9350,0.8627,1.2155 +Khronos,4x4,ldr-xy-normal2.png,50.5464,2.3361,2.0942,2.0028 +Khronos,5x5,ldr-l-occlusion.png,58.7464,0.1443,0.1119,9.3668 +Khronos,5x5,ldr-rgb-diffuse.png,49.8233,1.2770,1.1246,3.7295 +Khronos,5x5,ldr-rgb-emissive.png,56.1632,0.0833,0.0470,22.2912 +Khronos,5x5,ldr-rgb-metalrough.png,40.5315,0.5124,0.4676,2.2425 +Khronos,5x5,ldr-rgb-metalrough2.png,39.5945,3.3313,3.1674,1.3242 +Khronos,5x5,ldr-rgba-base.png,39.8027,0.6606,0.6092,1.7211 +Khronos,5x5,ldr-rgba-diffuse.png,39.9365,0.4799,0.4334,2.4194 +Khronos,5x5,ldr-rgba-specgloss.png,39.0414,0.8176,0.7661,1.3687 +Khronos,5x5,ldr-xy-normal1.png,43.3853,1.1448,1.0709,0.9792 +Khronos,5x5,ldr-xy-normal2.png,47.7847,3.2567,2.9989,1.3986 +Khronos,6x6,ldr-l-occlusion.png,52.2712,0.1879,0.1563,6.7075 +Khronos,6x6,ldr-rgb-diffuse.png,45.7889,1.2844,1.1340,3.6987 +Khronos,6x6,ldr-rgb-emissive.png,52.6833,0.0909,0.0563,18.6314 +Khronos,6x6,ldr-rgb-metalrough.png,37.0684,0.5868,0.5423,1.9336 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8174,3.6645,3.5010,1.1980 +Khronos,6x6,ldr-rgba-base.png,36.9100,0.7278,0.6804,1.5411 +Khronos,6x6,ldr-rgba-diffuse.png,36.7066,0.5483,0.5009,2.0933 +Khronos,6x6,ldr-rgba-specgloss.png,36.6855,0.8641,0.8149,1.2868 +Khronos,6x6,ldr-xy-normal1.png,41.0976,1.0310,0.9567,1.0960 +Khronos,6x6,ldr-xy-normal2.png,45.7894,2.7314,2.4716,1.6970 +Khronos,8x8,ldr-l-occlusion.png,46.0363,0.2467,0.2146,4.8856 +Khronos,8x8,ldr-rgb-diffuse.png,40.8626,1.5129,1.3642,3.0745 +Khronos,8x8,ldr-rgb-emissive.png,47.5792,0.0995,0.0655,16.0100 +Khronos,8x8,ldr-rgb-metalrough.png,32.8612,0.7665,0.7214,1.4536 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6302,4.5766,4.4166,0.9497 +Khronos,8x8,ldr-rgba-base.png,33.2969,0.9471,0.8980,1.1677 +Khronos,8x8,ldr-rgba-diffuse.png,32.7445,0.7457,0.6975,1.5033 +Khronos,8x8,ldr-rgba-specgloss.png,33.6408,1.1120,1.0611,0.9882 +Khronos,8x8,ldr-xy-normal1.png,37.7175,0.7501,0.6727,1.5587 +Khronos,8x8,ldr-xy-normal2.png,42.5021,1.6170,1.3584,3.0877 +Khronos,12x12,ldr-l-occlusion.png,42.4458,0.2357,0.1994,5.2584 +Khronos,12x12,ldr-rgb-diffuse.png,36.6053,1.7785,1.6276,2.5770 +Khronos,12x12,ldr-rgb-emissive.png,42.3646,0.1399,0.1015,10.3354 +Khronos,12x12,ldr-rgb-metalrough.png,29.3020,1.0049,0.9557,1.0971 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7710,5.2208,5.0598,0.8289 +Khronos,12x12,ldr-rgba-base.png,29.9273,1.0669,1.0134,1.0347 +Khronos,12x12,ldr-rgba-diffuse.png,29.2650,0.9900,0.9392,1.1164 +Khronos,12x12,ldr-rgba-specgloss.png,30.7044,1.3718,1.3176,0.7958 +Khronos,12x12,ldr-xy-normal1.png,33.9544,0.7235,0.6441,1.6279 +Khronos,12x12,ldr-xy-normal2.png,38.4422,1.2283,0.9636,4.3528 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..44b5533 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0380,0.0080,131.5835 +Khronos,4x4,ldr-rgb-diffuse.png,52.8179,0.2116,0.0646,64.9173 +Khronos,4x4,ldr-rgb-emissive.png,58.5184,0.0402,0.0075,139.0467 +Khronos,4x4,ldr-rgb-metalrough.png,44.3627,0.0912,0.0507,20.6632 +Khronos,4x4,ldr-rgb-metalrough2.png,42.9750,0.4768,0.3221,13.0213 +Khronos,4x4,ldr-rgba-base.png,43.2965,0.1085,0.0638,16.4473 +Khronos,4x4,ldr-rgba-diffuse.png,43.9222,0.0891,0.0451,23.2593 +Khronos,4x4,ldr-rgba-specgloss.png,41.7049,0.1488,0.1022,10.2611 +Khronos,4x4,ldr-xy-normal1.png,44.9872,0.1459,0.0754,13.9122 +Khronos,4x4,ldr-xy-normal2.png,48.6837,0.3618,0.1138,36.8704 +Khronos,5x5,ldr-l-occlusion.png,54.3814,0.0365,0.0062,168.2819 +Khronos,5x5,ldr-rgb-diffuse.png,47.2236,0.1952,0.0500,83.8378 +Khronos,5x5,ldr-rgb-emissive.png,52.6635,0.0384,0.0057,182.8405 +Khronos,5x5,ldr-rgb-metalrough.png,39.9099,0.0793,0.0390,26.8660 +Khronos,5x5,ldr-rgb-metalrough2.png,37.9762,0.4647,0.3113,13.4739 +Khronos,5x5,ldr-rgba-base.png,38.9583,0.0907,0.0460,22.7886 +Khronos,5x5,ldr-rgba-diffuse.png,39.1885,0.0883,0.0444,23.6214 +Khronos,5x5,ldr-rgba-specgloss.png,38.4160,0.1096,0.0632,16.5977 +Khronos,5x5,ldr-xy-normal1.png,41.8334,0.1304,0.0587,17.8657 +Khronos,5x5,ldr-xy-normal2.png,46.1655,0.3369,0.0789,53.1860 +Khronos,6x6,ldr-l-occlusion.png,48.3862,0.0371,0.0076,138.8491 +Khronos,6x6,ldr-rgb-diffuse.png,43.2830,0.2079,0.0687,61.0088 +Khronos,6x6,ldr-rgb-emissive.png,49.1097,0.0378,0.0058,180.0486 +Khronos,6x6,ldr-rgb-metalrough.png,36.5415,0.0860,0.0464,22.5835 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3486,0.4619,0.3119,13.4457 +Khronos,6x6,ldr-rgba-base.png,36.1889,0.0961,0.0526,19.9269 +Khronos,6x6,ldr-rgba-diffuse.png,36.1527,0.0983,0.0553,18.9564 +Khronos,6x6,ldr-rgba-specgloss.png,36.1297,0.1143,0.0685,15.3043 +Khronos,6x6,ldr-xy-normal1.png,39.6460,0.1255,0.0549,19.0942 +Khronos,6x6,ldr-xy-normal2.png,44.1090,0.3288,0.0767,54.6640 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0364,0.0090,117.1344 +Khronos,8x8,ldr-rgb-diffuse.png,38.4150,0.2246,0.0913,45.9222 +Khronos,8x8,ldr-rgb-emissive.png,44.6847,0.0373,0.0076,137.3188 +Khronos,8x8,ldr-rgb-metalrough.png,32.3524,0.1019,0.0619,16.9288 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2210,0.4244,0.2802,14.9716 +Khronos,8x8,ldr-rgba-base.png,32.4716,0.1020,0.0589,17.7915 +Khronos,8x8,ldr-rgba-diffuse.png,32.1743,0.1175,0.0756,13.8669 +Khronos,8x8,ldr-rgba-specgloss.png,32.9565,0.1166,0.0712,14.7328 +Khronos,8x8,ldr-xy-normal1.png,36.5625,0.1198,0.0490,21.3895 +Khronos,8x8,ldr-xy-normal2.png,40.7934,0.3341,0.0881,47.6274 +Khronos,12x12,ldr-l-occlusion.png,40.5804,0.0384,0.0086,121.6039 +Khronos,12x12,ldr-rgb-diffuse.png,33.3731,0.2051,0.0684,61.3524 +Khronos,12x12,ldr-rgb-emissive.png,39.4844,0.0386,0.0070,149.5019 +Khronos,12x12,ldr-rgb-metalrough.png,28.6538,0.0783,0.0378,27.7651 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2618,0.2840,0.1355,30.9474 +Khronos,12x12,ldr-rgba-base.png,29.0434,0.0941,0.0496,21.1500 +Khronos,12x12,ldr-rgba-diffuse.png,28.6314,0.1019,0.0582,18.0047 +Khronos,12x12,ldr-rgba-specgloss.png,29.8201,0.0889,0.0417,25.1741 +Khronos,12x12,ldr-xy-normal1.png,32.7607,0.1066,0.0349,30.0347 +Khronos,12x12,ldr-xy-normal2.png,36.2418,0.3315,0.0806,52.0199 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..09a5b5a --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0369,0.0074,141.9503 +Khronos,4x4,ldr-rgb-diffuse.png,52.5960,0.1988,0.0566,74.1595 +Khronos,4x4,ldr-rgb-emissive.png,57.9317,0.0385,0.0067,156.5754 +Khronos,4x4,ldr-rgb-metalrough.png,43.8926,0.0733,0.0337,31.1602 +Khronos,4x4,ldr-rgb-metalrough2.png,42.6922,0.3554,0.2022,20.7468 +Khronos,4x4,ldr-rgba-base.png,42.8654,0.0843,0.0404,25.9677 +Khronos,4x4,ldr-rgba-diffuse.png,43.3179,0.0720,0.0289,36.3055 +Khronos,4x4,ldr-rgba-specgloss.png,41.4002,0.1100,0.0639,16.4207 +Khronos,4x4,ldr-xy-normal1.png,44.8194,0.1189,0.0489,21.4516 +Khronos,4x4,ldr-xy-normal2.png,48.3518,0.3399,0.0892,46.9966 +Khronos,5x5,ldr-l-occlusion.png,54.2366,0.0355,0.0061,171.5641 +Khronos,5x5,ldr-rgb-diffuse.png,47.0653,0.1908,0.0472,88.8131 +Khronos,5x5,ldr-rgb-emissive.png,52.3476,0.0374,0.0053,196.7718 +Khronos,5x5,ldr-rgb-metalrough.png,39.4280,0.0673,0.0280,37.4063 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4660,0.3531,0.2032,20.6382 +Khronos,5x5,ldr-rgba-base.png,38.3323,0.0756,0.0322,32.5181 +Khronos,5x5,ldr-rgba-diffuse.png,38.5010,0.0717,0.0292,35.9300 +Khronos,5x5,ldr-rgba-specgloss.png,37.9482,0.0882,0.0427,24.5752 +Khronos,5x5,ldr-xy-normal1.png,41.4622,0.1112,0.0406,25.8455 +Khronos,5x5,ldr-xy-normal2.png,45.8286,0.3234,0.0670,62.5950 +Khronos,6x6,ldr-l-occlusion.png,48.3017,0.0357,0.0070,150.8712 +Khronos,6x6,ldr-rgb-diffuse.png,43.2322,0.1971,0.0596,70.4273 +Khronos,6x6,ldr-rgb-emissive.png,49.0036,0.0360,0.0050,208.8837 +Khronos,6x6,ldr-rgb-metalrough.png,36.3590,0.0722,0.0333,31.5360 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1574,0.3456,0.1975,21.2344 +Khronos,6x6,ldr-rgba-base.png,36.0142,0.0785,0.0355,29.5050 +Khronos,6x6,ldr-rgba-diffuse.png,35.9592,0.0775,0.0354,29.5991 +Khronos,6x6,ldr-rgba-specgloss.png,35.9090,0.0901,0.0451,23.2733 +Khronos,6x6,ldr-xy-normal1.png,39.2368,0.1091,0.0391,26.8288 +Khronos,6x6,ldr-xy-normal2.png,43.7398,0.3147,0.0633,66.2157 +Khronos,8x8,ldr-l-occlusion.png,43.5141,0.0347,0.0078,134.9674 +Khronos,8x8,ldr-rgb-diffuse.png,38.2796,0.2061,0.0735,57.0834 +Khronos,8x8,ldr-rgb-emissive.png,44.2626,0.0355,0.0060,174.3596 +Khronos,8x8,ldr-rgb-metalrough.png,32.2702,0.0846,0.0448,23.3932 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1173,0.3436,0.2008,20.8863 +Khronos,8x8,ldr-rgba-base.png,32.3492,0.0850,0.0426,24.6173 +Khronos,8x8,ldr-rgba-diffuse.png,32.0637,0.0947,0.0529,19.8249 +Khronos,8x8,ldr-rgba-specgloss.png,32.8589,0.0968,0.0516,20.3279 +Khronos,8x8,ldr-xy-normal1.png,36.3456,0.1072,0.0372,28.1935 +Khronos,8x8,ldr-xy-normal2.png,40.3507,0.3191,0.0729,57.5397 +Khronos,12x12,ldr-l-occlusion.png,40.2287,0.0359,0.0072,146.2262 +Khronos,12x12,ldr-rgb-diffuse.png,33.3235,0.1931,0.0560,74.8983 +Khronos,12x12,ldr-rgb-emissive.png,39.2827,0.0367,0.0054,195.3385 +Khronos,12x12,ldr-rgb-metalrough.png,28.6080,0.0684,0.0283,37.0271 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1699,0.2487,0.1022,41.0409 +Khronos,12x12,ldr-rgba-base.png,28.9860,0.0801,0.0362,28.9421 +Khronos,12x12,ldr-rgba-diffuse.png,28.5784,0.0841,0.0415,25.2706 +Khronos,12x12,ldr-rgba-specgloss.png,29.7728,0.0764,0.0312,33.5662 +Khronos,12x12,ldr-xy-normal1.png,32.6323,0.0962,0.0263,39.9394 +Khronos,12x12,ldr-xy-normal2.png,36.0168,0.3150,0.0645,65.0673 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..7348cee --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.5687,0.0451,0.0139,75.5068 +Khronos,4x4,ldr-rgb-diffuse.png,54.2509,0.3274,0.1799,23.3163 +Khronos,4x4,ldr-rgb-emissive.png,59.8692,0.0477,0.0145,72.2460 +Khronos,4x4,ldr-rgb-metalrough.png,44.9162,0.1965,0.1552,6.7570 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8012,1.2299,1.0750,3.9018 +Khronos,4x4,ldr-rgba-base.png,43.8387,0.2422,0.1973,5.3155 +Khronos,4x4,ldr-rgba-diffuse.png,44.2480,0.1735,0.1288,8.1417 +Khronos,4x4,ldr-rgba-specgloss.png,42.3086,0.3270,0.2798,3.7481 +Khronos,4x4,ldr-xy-normal1.png,46.5096,0.2954,0.2256,4.6480 +Khronos,4x4,ldr-xy-normal2.png,50.2692,0.6901,0.4484,9.3538 +Khronos,5x5,ldr-l-occlusion.png,57.1506,0.0469,0.0155,67.7905 +Khronos,5x5,ldr-rgb-diffuse.png,49.0125,0.3214,0.1780,23.5631 +Khronos,5x5,ldr-rgb-emissive.png,55.4137,0.0488,0.0148,70.9786 +Khronos,5x5,ldr-rgb-metalrough.png,40.3176,0.1880,0.1462,7.1736 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1297,1.3031,1.1504,3.6458 +Khronos,5x5,ldr-rgba-base.png,39.4682,0.2393,0.1943,5.3957 +Khronos,5x5,ldr-rgba-diffuse.png,39.6061,0.1915,0.1471,7.1282 +Khronos,5x5,ldr-rgba-specgloss.png,38.7834,0.3081,0.2604,4.0265 +Khronos,5x5,ldr-xy-normal1.png,43.0303,0.2762,0.2047,5.1230 +Khronos,5x5,ldr-xy-normal2.png,47.2313,0.6009,0.3474,12.0737 +Khronos,6x6,ldr-l-occlusion.png,50.8594,0.0532,0.0230,45.5289 +Khronos,6x6,ldr-rgb-diffuse.png,44.9402,0.3331,0.1924,21.8005 +Khronos,6x6,ldr-rgb-emissive.png,51.5373,0.0489,0.0159,66.0645 +Khronos,6x6,ldr-rgb-metalrough.png,36.8816,0.1912,0.1500,6.9889 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5008,1.2350,1.0861,3.8619 +Khronos,6x6,ldr-rgba-base.png,36.6975,0.2219,0.1768,5.9297 +Khronos,6x6,ldr-rgba-diffuse.png,36.5302,0.2039,0.1601,6.5477 +Khronos,6x6,ldr-rgba-specgloss.png,36.4921,0.2968,0.2496,4.2007 +Khronos,6x6,ldr-xy-normal1.png,40.6408,0.2360,0.1650,6.3533 +Khronos,6x6,ldr-xy-normal2.png,45.1534,0.4444,0.1925,21.7868 +Khronos,8x8,ldr-l-occlusion.png,45.4584,0.0620,0.0334,31.3906 +Khronos,8x8,ldr-rgb-diffuse.png,40.2308,0.4444,0.3089,13.5770 +Khronos,8x8,ldr-rgb-emissive.png,46.6998,0.0531,0.0220,47.6407 +Khronos,8x8,ldr-rgb-metalrough.png,32.6999,0.2522,0.2105,4.9818 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2345,1.4209,1.2745,3.2909 +Khronos,8x8,ldr-rgba-base.png,33.0850,0.2586,0.2148,4.8821 +Khronos,8x8,ldr-rgba-diffuse.png,32.5888,0.2691,0.2256,4.6480 +Khronos,8x8,ldr-rgba-specgloss.png,33.4811,0.3436,0.2970,3.5311 +Khronos,8x8,ldr-xy-normal1.png,37.4281,0.2553,0.1824,5.7500 +Khronos,8x8,ldr-xy-normal2.png,42.0637,0.4651,0.2161,19.4095 +Khronos,12x12,ldr-l-occlusion.png,41.6347,0.0517,0.0198,53.0793 +Khronos,12x12,ldr-rgb-diffuse.png,35.7680,0.4698,0.3266,12.8429 +Khronos,12x12,ldr-rgb-emissive.png,41.4121,0.0598,0.0254,41.2076 +Khronos,12x12,ldr-rgb-metalrough.png,29.1213,0.2434,0.1993,5.2610 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1727,1.0563,0.9045,4.6371 +Khronos,12x12,ldr-rgba-base.png,29.6476,0.2514,0.2032,5.1593 +Khronos,12x12,ldr-rgba-diffuse.png,29.0758,0.3109,0.2646,3.9626 +Khronos,12x12,ldr-rgba-specgloss.png,30.4831,0.2885,0.2390,4.3877 +Khronos,12x12,ldr-xy-normal1.png,33.5197,0.2228,0.1469,7.1376 +Khronos,12x12,ldr-xy-normal2.png,37.8214,0.4840,0.2291,18.3113 diff --git a/Test/Images/Khronos/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..70ce9b9 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.4255,0.0765,0.0455,23.0613 +Khronos,4x4,ldr-rgb-diffuse.png,54.7764,1.1733,1.0311,4.0680 +Khronos,4x4,ldr-rgb-emissive.png,60.8826,0.0656,0.0328,31.9600 +Khronos,4x4,ldr-rgb-metalrough.png,45.0480,0.4008,0.3590,2.9205 +Khronos,4x4,ldr-rgb-metalrough2.png,44.0818,2.5010,2.3450,1.7886 +Khronos,4x4,ldr-rgba-base.png,44.0332,0.5085,0.4626,2.2668 +Khronos,4x4,ldr-rgba-diffuse.png,44.4445,0.3498,0.3054,3.4331 +Khronos,4x4,ldr-rgba-specgloss.png,42.4764,0.6586,0.6110,1.7161 +Khronos,4x4,ldr-xy-normal1.png,46.6603,0.8150,0.7452,1.4071 +Khronos,4x4,ldr-xy-normal2.png,50.5464,2.0382,1.8019,2.3277 +Khronos,5x5,ldr-l-occlusion.png,58.7464,0.1214,0.0901,11.6347 +Khronos,5x5,ldr-rgb-diffuse.png,49.8233,1.0584,0.9137,4.5905 +Khronos,5x5,ldr-rgb-emissive.png,56.1632,0.0729,0.0386,27.1617 +Khronos,5x5,ldr-rgb-metalrough.png,40.5315,0.4230,0.3808,2.7533 +Khronos,5x5,ldr-rgb-metalrough2.png,39.5945,2.7561,2.5963,1.6155 +Khronos,5x5,ldr-rgba-base.png,39.8027,0.5516,0.5049,2.0767 +Khronos,5x5,ldr-rgba-diffuse.png,39.9365,0.4010,0.3558,2.9467 +Khronos,5x5,ldr-rgba-specgloss.png,39.0414,0.6822,0.6343,1.6532 +Khronos,5x5,ldr-xy-normal1.png,43.3853,0.9602,0.8893,1.1791 +Khronos,5x5,ldr-xy-normal2.png,47.7847,2.7467,2.4976,1.6794 +Khronos,6x6,ldr-l-occlusion.png,52.2712,0.1565,0.1262,8.3116 +Khronos,6x6,ldr-rgb-diffuse.png,45.7889,1.0673,0.9240,4.5392 +Khronos,6x6,ldr-rgb-emissive.png,52.6833,0.0790,0.0463,22.6348 +Khronos,6x6,ldr-rgb-metalrough.png,37.0684,0.4863,0.4447,2.3577 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8174,3.0393,2.8880,1.4523 +Khronos,6x6,ldr-rgba-base.png,36.9100,0.6096,0.5641,1.8589 +Khronos,6x6,ldr-rgba-diffuse.png,36.7066,0.4552,0.4112,2.5503 +Khronos,6x6,ldr-rgba-specgloss.png,36.6855,0.7266,0.6794,1.5435 +Khronos,6x6,ldr-xy-normal1.png,41.0976,0.8626,0.7904,1.3266 +Khronos,6x6,ldr-xy-normal2.png,45.7894,2.2930,2.0455,2.0505 +Khronos,8x8,ldr-l-occlusion.png,46.0363,0.2092,0.1787,5.8676 +Khronos,8x8,ldr-rgb-diffuse.png,40.8626,1.2696,1.1340,3.6987 +Khronos,8x8,ldr-rgb-emissive.png,47.5792,0.0870,0.0549,19.0889 +Khronos,8x8,ldr-rgb-metalrough.png,32.8612,0.6486,0.6054,1.7321 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6302,3.8740,3.7272,1.1253 +Khronos,8x8,ldr-rgba-base.png,33.2969,0.8026,0.7550,1.3889 +Khronos,8x8,ldr-rgba-diffuse.png,32.7445,0.6319,0.5870,1.7864 +Khronos,8x8,ldr-rgba-specgloss.png,33.6408,0.9413,0.8931,1.1740 +Khronos,8x8,ldr-xy-normal1.png,37.7175,0.6400,0.5677,1.8471 +Khronos,8x8,ldr-xy-normal2.png,42.5021,1.3685,1.1202,3.7442 +Khronos,12x12,ldr-l-occlusion.png,42.4458,0.2088,0.1746,6.0052 +Khronos,12x12,ldr-rgb-diffuse.png,36.6053,1.5706,1.4258,2.9417 +Khronos,12x12,ldr-rgb-emissive.png,42.3646,0.1263,0.0896,11.7094 +Khronos,12x12,ldr-rgb-metalrough.png,29.3020,0.8862,0.8395,1.2490 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7710,4.6028,4.4499,0.9426 +Khronos,12x12,ldr-rgba-base.png,29.9273,0.9429,0.8931,1.1741 +Khronos,12x12,ldr-rgba-diffuse.png,29.2650,0.8764,0.8284,1.2658 +Khronos,12x12,ldr-rgba-specgloss.png,30.7044,1.2141,1.1626,0.9019 +Khronos,12x12,ldr-xy-normal1.png,33.9544,0.6437,0.5680,1.8459 +Khronos,12x12,ldr-xy-normal2.png,38.4422,1.0970,0.8420,4.9811 diff --git a/Test/Images/Khronos/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/Khronos/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..9eedca3 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0371,0.0071,148.5877 +Khronos,4x4,ldr-rgb-diffuse.png,53.0267,0.2015,0.0543,77.2689 +Khronos,4x4,ldr-rgb-emissive.png,58.6381,0.0390,0.0073,144.4730 +Khronos,4x4,ldr-rgb-metalrough.png,44.3920,0.0853,0.0447,23.4429 +Khronos,4x4,ldr-rgb-metalrough2.png,43.0040,0.4393,0.2844,14.7457 +Khronos,4x4,ldr-rgba-base.png,43.3288,0.1012,0.0567,18.4980 +Khronos,4x4,ldr-rgba-diffuse.png,43.9623,0.0834,0.0399,26.2768 +Khronos,4x4,ldr-rgba-specgloss.png,41.7602,0.1375,0.0910,11.5173 +Khronos,4x4,ldr-xy-normal1.png,45.0735,0.1363,0.0657,15.9698 +Khronos,4x4,ldr-xy-normal2.png,48.7816,0.3495,0.0966,43.4004 +Khronos,5x5,ldr-l-occlusion.png,54.3818,0.0361,0.0054,192.9984 +Khronos,5x5,ldr-rgb-diffuse.png,47.3675,0.1902,0.0409,102.6729 +Khronos,5x5,ldr-rgb-emissive.png,52.6737,0.0377,0.0054,195.3385 +Khronos,5x5,ldr-rgb-metalrough.png,39.9283,0.0735,0.0327,32.0291 +Khronos,5x5,ldr-rgb-metalrough2.png,38.0052,0.4177,0.2660,15.7687 +Khronos,5x5,ldr-rgba-base.png,38.9802,0.0843,0.0391,26.8103 +Khronos,5x5,ldr-rgba-diffuse.png,39.2155,0.0824,0.0378,27.7357 +Khronos,5x5,ldr-rgba-specgloss.png,38.4625,0.1004,0.0535,19.5944 +Khronos,5x5,ldr-xy-normal1.png,41.9841,0.1207,0.0498,21.0371 +Khronos,5x5,ldr-xy-normal2.png,46.4301,0.3220,0.0655,63.9951 +Khronos,6x6,ldr-l-occlusion.png,48.3865,0.0359,0.0063,166.2778 +Khronos,6x6,ldr-rgb-diffuse.png,43.3210,0.1936,0.0538,77.9567 +Khronos,6x6,ldr-rgb-emissive.png,49.1136,0.0368,0.0053,198.8627 +Khronos,6x6,ldr-rgb-metalrough.png,36.5537,0.0768,0.0373,28.1007 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3595,0.4053,0.2530,16.5814 +Khronos,6x6,ldr-rgba-base.png,36.2020,0.0857,0.0427,24.5701 +Khronos,6x6,ldr-rgba-diffuse.png,36.1683,0.0875,0.0447,23.4744 +Khronos,6x6,ldr-rgba-specgloss.png,36.1582,0.1009,0.0552,18.9976 +Khronos,6x6,ldr-xy-normal1.png,39.6982,0.1148,0.0449,23.3317 +Khronos,6x6,ldr-xy-normal2.png,44.2645,0.3126,0.0622,67.4770 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0348,0.0072,146.1631 +Khronos,8x8,ldr-rgb-diffuse.png,38.4394,0.1971,0.0698,60.1118 +Khronos,8x8,ldr-rgb-emissive.png,44.6723,0.0355,0.0062,168.3592 +Khronos,8x8,ldr-rgb-metalrough.png,32.3577,0.0852,0.0477,21.9947 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2246,0.3541,0.2153,19.4779 +Khronos,8x8,ldr-rgba-base.png,32.4790,0.0888,0.0462,22.6881 +Khronos,8x8,ldr-rgba-diffuse.png,32.1796,0.0999,0.0583,17.9776 +Khronos,8x8,ldr-rgba-specgloss.png,32.9682,0.0997,0.0552,19.0063 +Khronos,8x8,ldr-xy-normal1.png,36.5942,0.1070,0.0386,27.2003 +Khronos,8x8,ldr-xy-normal2.png,40.8681,0.3118,0.0691,60.7236 +Khronos,12x12,ldr-l-occlusion.png,40.5805,0.0366,0.0065,160.2378 +Khronos,12x12,ldr-rgb-diffuse.png,33.3842,0.1906,0.0514,81.5873 +Khronos,12x12,ldr-rgb-emissive.png,39.4821,0.0369,0.0054,193.2188 +Khronos,12x12,ldr-rgb-metalrough.png,28.6554,0.0678,0.0288,36.4215 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2607,0.2506,0.1025,40.9148 +Khronos,12x12,ldr-rgba-base.png,29.0476,0.0815,0.0378,27.7423 +Khronos,12x12,ldr-rgba-diffuse.png,28.6320,0.0872,0.0440,23.8405 +Khronos,12x12,ldr-rgba-specgloss.png,29.8260,0.0780,0.0320,32.7762 +Khronos,12x12,ldr-xy-normal1.png,32.7642,0.0968,0.0265,39.5003 +Khronos,12x12,ldr-xy-normal2.png,36.2644,0.3126,0.0619,67.7222 diff --git a/Test/Images/Khronos/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..681e876 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0363,0.0067,157.6078 +Khronos,4x4,ldr-rgb-diffuse.png,52.8124,0.1929,0.0478,87.6699 +Khronos,4x4,ldr-rgb-emissive.png,58.0052,0.0377,0.0066,157.9191 +Khronos,4x4,ldr-rgb-metalrough.png,43.9215,0.0693,0.0296,35.4310 +Khronos,4x4,ldr-rgb-metalrough2.png,42.7188,0.3281,0.1766,23.7569 +Khronos,4x4,ldr-rgba-base.png,42.9028,0.0800,0.0358,29.2873 +Khronos,4x4,ldr-rgba-diffuse.png,43.3583,0.0685,0.0253,41.4242 +Khronos,4x4,ldr-rgba-specgloss.png,41.4613,0.1020,0.0565,18.5559 +Khronos,4x4,ldr-xy-normal1.png,44.9379,0.1127,0.0427,24.5460 +Khronos,4x4,ldr-xy-normal2.png,48.5682,0.3276,0.0756,55.5044 +Khronos,5x5,ldr-l-occlusion.png,54.2370,0.0351,0.0054,194.1400 +Khronos,5x5,ldr-rgb-diffuse.png,47.2115,0.1817,0.0387,108.4278 +Khronos,5x5,ldr-rgb-emissive.png,52.3776,0.0365,0.0051,207.3083 +Khronos,5x5,ldr-rgb-metalrough.png,39.4514,0.0634,0.0234,44.8606 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4945,0.3247,0.1709,24.5443 +Khronos,5x5,ldr-rgba-base.png,38.3583,0.0705,0.0271,38.7329 +Khronos,5x5,ldr-rgba-diffuse.png,38.5295,0.0676,0.0246,42.6548 +Khronos,5x5,ldr-rgba-specgloss.png,37.9922,0.0812,0.0356,29.4174 +Khronos,5x5,ldr-xy-normal1.png,41.5416,0.1039,0.0346,30.3224 +Khronos,5x5,ldr-xy-normal2.png,46.0597,0.3077,0.0555,75.5078 +Khronos,6x6,ldr-l-occlusion.png,48.3019,0.0345,0.0058,181.4151 +Khronos,6x6,ldr-rgb-diffuse.png,43.2732,0.1865,0.0467,89.8542 +Khronos,6x6,ldr-rgb-emissive.png,49.0049,0.0351,0.0046,228.8861 +Khronos,6x6,ldr-rgb-metalrough.png,36.3724,0.0642,0.0263,39.9350 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1757,0.3066,0.1577,26.5903 +Khronos,6x6,ldr-rgba-base.png,36.0313,0.0713,0.0285,36.7625 +Khronos,6x6,ldr-rgba-diffuse.png,35.9759,0.0702,0.0283,37.0902 +Khronos,6x6,ldr-rgba-specgloss.png,35.9374,0.0804,0.0357,29.3630 +Khronos,6x6,ldr-xy-normal1.png,39.2788,0.0999,0.0319,32.8821 +Khronos,6x6,ldr-xy-normal2.png,43.8791,0.3027,0.0513,81.6964 +Khronos,8x8,ldr-l-occlusion.png,43.5147,0.0339,0.0063,167.1054 +Khronos,8x8,ldr-rgb-diffuse.png,38.3057,0.1849,0.0572,73.3154 +Khronos,8x8,ldr-rgb-emissive.png,44.2711,0.0342,0.0050,208.6756 +Khronos,8x8,ldr-rgb-metalrough.png,32.2747,0.0723,0.0350,29.9807 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1205,0.2932,0.1565,26.8027 +Khronos,8x8,ldr-rgba-base.png,32.3546,0.0758,0.0340,30.8423 +Khronos,8x8,ldr-rgba-diffuse.png,32.0684,0.0826,0.0414,25.3291 +Khronos,8x8,ldr-rgba-specgloss.png,32.8728,0.0848,0.0404,25.9336 +Khronos,8x8,ldr-xy-normal1.png,36.3792,0.0970,0.0295,35.5378 +Khronos,8x8,ldr-xy-normal2.png,40.4205,0.2988,0.0580,72.2694 +Khronos,12x12,ldr-l-occlusion.png,40.2288,0.0348,0.0055,191.3858 +Khronos,12x12,ldr-rgb-diffuse.png,33.3337,0.1780,0.0424,98.9036 +Khronos,12x12,ldr-rgb-emissive.png,39.2838,0.0352,0.0043,245.5089 +Khronos,12x12,ldr-rgb-metalrough.png,28.6096,0.0608,0.0219,47.9874 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1688,0.2240,0.0778,53.9072 +Khronos,12x12,ldr-rgba-base.png,28.9857,0.0708,0.0275,38.0829 +Khronos,12x12,ldr-rgba-diffuse.png,28.5805,0.0739,0.0316,33.2206 +Khronos,12x12,ldr-rgba-specgloss.png,29.7804,0.0684,0.0240,43.6254 +Khronos,12x12,ldr-xy-normal1.png,32.6324,0.0900,0.0203,51.6536 +Khronos,12x12,ldr-xy-normal2.png,36.0402,0.2994,0.0501,83.8022 diff --git a/Test/Images/Khronos/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/Khronos/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..d0658b2 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.6014,0.0426,0.0116,90.2460 +Khronos,4x4,ldr-rgb-diffuse.png,54.3556,0.2948,0.1500,27.9527 +Khronos,4x4,ldr-rgb-emissive.png,59.9751,0.0459,0.0132,79.2455 +Khronos,4x4,ldr-rgb-metalrough.png,44.9501,0.1759,0.1353,7.7497 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8315,1.0883,0.9347,4.4874 +Khronos,4x4,ldr-rgba-base.png,43.8666,0.2176,0.1721,6.0930 +Khronos,4x4,ldr-rgba-diffuse.png,44.2878,0.1570,0.1123,9.3384 +Khronos,4x4,ldr-rgba-specgloss.png,42.3783,0.2906,0.2431,4.3132 +Khronos,4x4,ldr-xy-normal1.png,46.6467,0.2596,0.1905,5.5032 +Khronos,4x4,ldr-xy-normal2.png,50.3582,0.5960,0.3564,11.7691 +Khronos,5x5,ldr-l-occlusion.png,57.1684,0.0450,0.0130,80.6286 +Khronos,5x5,ldr-rgb-diffuse.png,49.1067,0.2887,0.1437,29.1808 +Khronos,5x5,ldr-rgb-emissive.png,55.4603,0.0462,0.0128,81.8820 +Khronos,5x5,ldr-rgb-metalrough.png,40.3454,0.1636,0.1223,8.5765 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1509,1.1077,0.9541,4.3962 +Khronos,5x5,ldr-rgba-base.png,39.4887,0.2081,0.1624,6.4548 +Khronos,5x5,ldr-rgba-diffuse.png,39.6329,0.1697,0.1239,8.4600 +Khronos,5x5,ldr-rgba-specgloss.png,38.8241,0.2646,0.2168,4.8367 +Khronos,5x5,ldr-xy-normal1.png,43.1673,0.2372,0.1669,6.2821 +Khronos,5x5,ldr-xy-normal2.png,47.3690,0.5252,0.2695,15.5654 +Khronos,6x6,ldr-l-occlusion.png,50.8693,0.0487,0.0183,57.3648 +Khronos,6x6,ldr-rgb-diffuse.png,44.9599,0.2934,0.1512,27.7441 +Khronos,6x6,ldr-rgb-emissive.png,51.5481,0.0457,0.0132,79.7340 +Khronos,6x6,ldr-rgb-metalrough.png,36.8921,0.1601,0.1203,8.7190 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5121,1.0340,0.8828,4.7513 +Khronos,6x6,ldr-rgba-base.png,36.7084,0.1868,0.1422,7.3739 +Khronos,6x6,ldr-rgba-diffuse.png,36.5436,0.1725,0.1284,8.1657 +Khronos,6x6,ldr-rgba-specgloss.png,36.5238,0.2503,0.2033,5.1571 +Khronos,6x6,ldr-xy-normal1.png,40.6992,0.2032,0.1331,7.8781 +Khronos,6x6,ldr-xy-normal2.png,45.2966,0.4069,0.1511,27.7673 +Khronos,8x8,ldr-l-occlusion.png,45.4623,0.0545,0.0256,41.0013 +Khronos,8x8,ldr-rgb-diffuse.png,40.2673,0.3645,0.2326,18.0344 +Khronos,8x8,ldr-rgb-emissive.png,46.6668,0.0481,0.0170,61.8337 +Khronos,8x8,ldr-rgb-metalrough.png,32.7061,0.2027,0.1630,6.4313 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2423,1.1312,0.9903,4.2353 +Khronos,8x8,ldr-rgba-base.png,33.0988,0.2081,0.1640,6.3949 +Khronos,8x8,ldr-rgba-diffuse.png,32.5945,0.2177,0.1748,5.9975 +Khronos,8x8,ldr-rgba-specgloss.png,33.4998,0.2762,0.2303,4.5524 +Khronos,8x8,ldr-xy-normal1.png,37.4662,0.2122,0.1413,7.4199 +Khronos,8x8,ldr-xy-normal2.png,42.1537,0.4088,0.1652,25.3874 +Khronos,12x12,ldr-l-occlusion.png,41.6349,0.0471,0.0149,70.4872 +Khronos,12x12,ldr-rgb-diffuse.png,35.7761,0.3772,0.2373,17.6759 +Khronos,12x12,ldr-rgb-emissive.png,41.4092,0.0534,0.0193,54.3694 +Khronos,12x12,ldr-rgb-metalrough.png,29.1224,0.1932,0.1506,6.9619 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1747,0.8359,0.6838,6.1342 +Khronos,12x12,ldr-rgba-base.png,29.6502,0.2001,0.1530,6.8528 +Khronos,12x12,ldr-rgba-diffuse.png,29.0821,0.2477,0.2016,5.2016 +Khronos,12x12,ldr-rgba-specgloss.png,30.4902,0.2293,0.1802,5.8181 +Khronos,12x12,ldr-xy-normal1.png,33.5383,0.1871,0.1123,9.3396 +Khronos,12x12,ldr-xy-normal2.png,37.8558,0.4269,0.1720,24.3835 diff --git a/Test/Images/Khronos/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..2809a91 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.5078,0.0700,0.0389,26.9267 +Khronos,4x4,ldr-rgb-diffuse.png,55.0173,1.0699,0.9269,4.5251 +Khronos,4x4,ldr-rgb-emissive.png,60.9828,0.0604,0.0292,35.9617 +Khronos,4x4,ldr-rgb-metalrough.png,45.0852,0.3518,0.3102,3.3805 +Khronos,4x4,ldr-rgb-metalrough2.png,44.1151,2.1725,2.0166,2.0798 +Khronos,4x4,ldr-rgba-base.png,44.0576,0.4457,0.4009,2.6155 +Khronos,4x4,ldr-rgba-diffuse.png,44.4803,0.3084,0.2638,3.9749 +Khronos,4x4,ldr-rgba-specgloss.png,42.5365,0.5490,0.5013,2.0918 +Khronos,4x4,ldr-xy-normal1.png,46.8266,0.6649,0.5973,1.7555 +Khronos,4x4,ldr-xy-normal2.png,50.7352,1.4004,1.1721,3.5784 +Khronos,5x5,ldr-l-occlusion.png,58.7745,0.1070,0.0752,13.9359 +Khronos,5x5,ldr-rgb-diffuse.png,49.9407,0.9009,0.7579,5.5340 +Khronos,5x5,ldr-rgb-emissive.png,56.2048,0.0664,0.0329,31.8833 +Khronos,5x5,ldr-rgb-metalrough.png,40.5577,0.3601,0.3185,3.2927 +Khronos,5x5,ldr-rgb-metalrough2.png,39.6175,2.2972,2.1434,1.9569 +Khronos,5x5,ldr-rgba-base.png,39.8200,0.4679,0.4223,2.4828 +Khronos,5x5,ldr-rgba-diffuse.png,39.9566,0.3419,0.2971,3.5290 +Khronos,5x5,ldr-rgba-specgloss.png,39.0743,0.5565,0.5086,2.0617 +Khronos,5x5,ldr-xy-normal1.png,43.5230,0.7853,0.7143,1.4681 +Khronos,5x5,ldr-xy-normal2.png,48.0259,1.8574,1.6153,2.5966 +Khronos,6x6,ldr-l-occlusion.png,52.2896,0.1308,0.1003,10.4583 +Khronos,6x6,ldr-rgb-diffuse.png,45.8228,0.8755,0.7328,5.7240 +Khronos,6x6,ldr-rgb-emissive.png,52.7040,0.0698,0.0373,28.1489 +Khronos,6x6,ldr-rgb-metalrough.png,37.0805,0.3983,0.3573,2.9346 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8317,2.4948,2.3461,1.7878 +Khronos,6x6,ldr-rgba-base.png,36.9234,0.5019,0.4570,2.2945 +Khronos,6x6,ldr-rgba-diffuse.png,36.7153,0.3765,0.3326,3.1527 +Khronos,6x6,ldr-rgba-specgloss.png,36.7092,0.5977,0.5505,1.9047 +Khronos,6x6,ldr-xy-normal1.png,41.1567,0.7009,0.6308,1.6622 +Khronos,6x6,ldr-xy-normal2.png,45.8887,1.7724,1.5210,2.7575 +Khronos,8x8,ldr-l-occlusion.png,46.0437,0.1670,0.1364,7.6856 +Khronos,8x8,ldr-rgb-diffuse.png,40.8943,0.9896,0.8569,4.8949 +Khronos,8x8,ldr-rgb-emissive.png,47.5254,0.0742,0.0419,25.0031 +Khronos,8x8,ldr-rgb-metalrough.png,32.8679,0.5067,0.4652,2.2539 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6388,3.0411,2.9000,1.4463 +Khronos,8x8,ldr-rgba-base.png,33.3019,0.6351,0.5892,1.7796 +Khronos,8x8,ldr-rgba-diffuse.png,32.7485,0.4977,0.4534,2.3129 +Khronos,8x8,ldr-rgba-specgloss.png,33.6585,0.7470,0.6993,1.4994 +Khronos,8x8,ldr-xy-normal1.png,37.7495,0.5018,0.4301,2.4380 +Khronos,8x8,ldr-xy-normal2.png,42.5566,1.0598,0.8158,5.1414 +Khronos,12x12,ldr-l-occlusion.png,42.4497,0.1646,0.1297,8.0822 +Khronos,12x12,ldr-rgb-diffuse.png,36.6128,1.2088,1.0682,3.9267 +Khronos,12x12,ldr-rgb-emissive.png,42.3574,0.1043,0.0676,15.5052 +Khronos,12x12,ldr-rgb-metalrough.png,29.3075,0.6862,0.6394,1.6400 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7751,3.5897,3.4383,1.2199 +Khronos,12x12,ldr-rgba-base.png,29.9281,0.7327,0.6828,1.5358 +Khronos,12x12,ldr-rgba-diffuse.png,29.2672,0.6802,0.6312,1.6613 +Khronos,12x12,ldr-rgba-specgloss.png,30.7132,0.9450,0.8935,1.1736 +Khronos,12x12,ldr-xy-normal1.png,33.9601,0.5052,0.4306,2.4353 +Khronos,12x12,ldr-xy-normal2.png,38.4700,0.8811,0.6217,6.7466 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..9c5ae2c --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0415,0.0097,108.4598 +Khronos,4x4,ldr-rgb-diffuse.png,53.0267,0.2327,0.0799,52.4800 +Khronos,4x4,ldr-rgb-emissive.png,58.6381,0.0416,0.0078,133.6630 +Khronos,4x4,ldr-rgb-metalrough.png,44.3920,0.1031,0.0602,17.4306 +Khronos,4x4,ldr-rgb-metalrough2.png,43.0040,0.5443,0.3786,11.0780 +Khronos,4x4,ldr-rgba-base.png,43.3288,0.1218,0.0755,13.8904 +Khronos,4x4,ldr-rgba-diffuse.png,43.9623,0.0992,0.0535,19.6046 +Khronos,4x4,ldr-rgba-specgloss.png,41.7602,0.1693,0.1202,8.7253 +Khronos,4x4,ldr-xy-normal1.png,45.0735,0.1615,0.0884,11.8680 +Khronos,4x4,ldr-xy-normal2.png,48.7816,0.3903,0.1357,30.9052 +Khronos,5x5,ldr-l-occlusion.png,54.3818,0.0392,0.0071,146.9395 +Khronos,5x5,ldr-rgb-diffuse.png,47.3675,0.2072,0.0575,72.9189 +Khronos,5x5,ldr-rgb-emissive.png,52.6737,0.0407,0.0063,165.6265 +Khronos,5x5,ldr-rgb-metalrough.png,39.9283,0.0892,0.0470,22.3325 +Khronos,5x5,ldr-rgb-metalrough2.png,38.0052,0.5334,0.3726,11.2557 +Khronos,5x5,ldr-rgba-base.png,38.9802,0.1014,0.0554,18.9240 +Khronos,5x5,ldr-rgba-diffuse.png,39.2155,0.0987,0.0532,19.7001 +Khronos,5x5,ldr-rgba-specgloss.png,38.4625,0.1249,0.0762,13.7556 +Khronos,5x5,ldr-xy-normal1.png,41.9841,0.1422,0.0696,15.0614 +Khronos,5x5,ldr-xy-normal2.png,46.4301,0.3470,0.0911,46.0527 +Khronos,6x6,ldr-l-occlusion.png,48.3865,0.0400,0.0088,118.8436 +Khronos,6x6,ldr-rgb-diffuse.png,43.3210,0.2299,0.0825,50.8634 +Khronos,6x6,ldr-rgb-emissive.png,49.1136,0.0401,0.0067,157.5119 +Khronos,6x6,ldr-rgb-metalrough.png,36.5537,0.0986,0.0562,18.6523 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3595,0.5334,0.3742,11.2094 +Khronos,6x6,ldr-rgba-base.png,36.2020,0.1086,0.0633,16.5623 +Khronos,6x6,ldr-rgba-diffuse.png,36.1683,0.1119,0.0668,15.6888 +Khronos,6x6,ldr-rgba-specgloss.png,36.1582,0.1314,0.0830,12.6274 +Khronos,6x6,ldr-xy-normal1.png,39.6982,0.1383,0.0651,16.1086 +Khronos,6x6,ldr-xy-normal2.png,44.2645,0.3460,0.0901,46.5522 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0396,0.0105,100.0830 +Khronos,8x8,ldr-rgb-diffuse.png,38.4394,0.2517,0.1089,38.5099 +Khronos,8x8,ldr-rgb-emissive.png,44.6723,0.0404,0.0089,117.5163 +Khronos,8x8,ldr-rgb-metalrough.png,32.3577,0.1164,0.0739,14.1882 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2246,0.4876,0.3331,12.5923 +Khronos,8x8,ldr-rgba-base.png,32.4790,0.1154,0.0699,15.0065 +Khronos,8x8,ldr-rgba-diffuse.png,32.1796,0.1350,0.0906,11.5716 +Khronos,8x8,ldr-rgba-specgloss.png,32.9682,0.1325,0.0845,12.4078 +Khronos,8x8,ldr-xy-normal1.png,36.5942,0.1312,0.0584,17.9671 +Khronos,8x8,ldr-xy-normal2.png,40.8681,0.3592,0.1040,40.3388 +Khronos,12x12,ldr-l-occlusion.png,40.5805,0.0410,0.0099,106.1330 +Khronos,12x12,ldr-rgb-diffuse.png,33.3842,0.2247,0.0781,53.6740 +Khronos,12x12,ldr-rgb-emissive.png,39.4821,0.0416,0.0080,130.9098 +Khronos,12x12,ldr-rgb-metalrough.png,28.6554,0.0862,0.0432,24.2704 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2607,0.3124,0.1553,27.0017 +Khronos,12x12,ldr-rgba-base.png,29.0476,0.1034,0.0567,18.4931 +Khronos,12x12,ldr-rgba-diffuse.png,28.6320,0.1125,0.0665,15.7624 +Khronos,12x12,ldr-rgba-specgloss.png,29.8260,0.0968,0.0478,21.9184 +Khronos,12x12,ldr-xy-normal1.png,32.7642,0.1140,0.0395,26.5637 +Khronos,12x12,ldr-xy-normal2.png,36.2644,0.3529,0.0919,45.6588 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..854cacf --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0401,0.0088,118.8983 +Khronos,4x4,ldr-rgb-diffuse.png,52.8124,0.2203,0.0689,60.8530 +Khronos,4x4,ldr-rgb-emissive.png,58.0052,0.0408,0.0073,143.9198 +Khronos,4x4,ldr-rgb-metalrough.png,43.9215,0.0819,0.0399,26.2656 +Khronos,4x4,ldr-rgb-metalrough2.png,42.7188,0.3995,0.2380,17.6262 +Khronos,4x4,ldr-rgba-base.png,42.9028,0.0936,0.0479,21.8955 +Khronos,4x4,ldr-rgba-diffuse.png,43.3583,0.0790,0.0340,30.8641 +Khronos,4x4,ldr-rgba-specgloss.png,41.4613,0.1236,0.0752,13.9373 +Khronos,4x4,ldr-xy-normal1.png,44.9379,0.1293,0.0571,18.3770 +Khronos,4x4,ldr-xy-normal2.png,48.5682,0.3584,0.1046,40.0840 +Khronos,5x5,ldr-l-occlusion.png,54.2370,0.0381,0.0070,150.2886 +Khronos,5x5,ldr-rgb-diffuse.png,47.2115,0.2035,0.0540,77.6694 +Khronos,5x5,ldr-rgb-emissive.png,52.3776,0.0392,0.0058,179.8571 +Khronos,5x5,ldr-rgb-metalrough.png,39.4514,0.0752,0.0335,31.2897 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4945,0.4024,0.2428,17.2757 +Khronos,5x5,ldr-rgba-base.png,38.3583,0.0835,0.0385,27.2224 +Khronos,5x5,ldr-rgba-diffuse.png,38.5295,0.0794,0.0351,29.9055 +Khronos,5x5,ldr-rgba-specgloss.png,37.9922,0.0995,0.0517,20.3012 +Khronos,5x5,ldr-xy-normal1.png,41.5416,0.1199,0.0480,21.8658 +Khronos,5x5,ldr-xy-normal2.png,46.0597,0.3308,0.0772,54.3388 +Khronos,6x6,ldr-l-occlusion.png,48.3019,0.0383,0.0080,130.5639 +Khronos,6x6,ldr-rgb-diffuse.png,43.2732,0.2179,0.0710,59.0582 +Khronos,6x6,ldr-rgb-emissive.png,49.0049,0.0381,0.0055,188.9682 +Khronos,6x6,ldr-rgb-metalrough.png,36.3724,0.0817,0.0402,26.0905 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1757,0.3948,0.2392,17.5349 +Khronos,6x6,ldr-rgba-base.png,36.0313,0.0879,0.0432,24.2962 +Khronos,6x6,ldr-rgba-diffuse.png,35.9759,0.0866,0.0432,24.2782 +Khronos,6x6,ldr-rgba-specgloss.png,35.9374,0.1025,0.0550,19.0806 +Khronos,6x6,ldr-xy-normal1.png,39.2788,0.1181,0.0467,22.4578 +Khronos,6x6,ldr-xy-normal2.png,43.8791,0.3302,0.0744,56.3440 +Khronos,8x8,ldr-l-occlusion.png,43.5147,0.0378,0.0090,116.3135 +Khronos,8x8,ldr-rgb-diffuse.png,38.3057,0.2302,0.0876,47.9065 +Khronos,8x8,ldr-rgb-emissive.png,44.2711,0.0383,0.0068,155.0683 +Khronos,8x8,ldr-rgb-metalrough.png,32.2747,0.0962,0.0538,19.4989 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1205,0.3931,0.2401,17.4680 +Khronos,8x8,ldr-rgba-base.png,32.3546,0.0968,0.0511,20.5184 +Khronos,8x8,ldr-rgba-diffuse.png,32.0684,0.1078,0.0635,16.5109 +Khronos,8x8,ldr-rgba-specgloss.png,32.8728,0.1094,0.0617,17.0014 +Khronos,8x8,ldr-xy-normal1.png,36.3792,0.1170,0.0444,23.6181 +Khronos,8x8,ldr-xy-normal2.png,40.4205,0.3417,0.0861,48.7320 +Khronos,12x12,ldr-l-occlusion.png,40.2288,0.0386,0.0081,128.7221 +Khronos,12x12,ldr-rgb-diffuse.png,33.3337,0.2078,0.0640,65.5185 +Khronos,12x12,ldr-rgb-emissive.png,39.2838,0.0389,0.0060,175.2280 +Khronos,12x12,ldr-rgb-metalrough.png,28.6096,0.0752,0.0323,32.4939 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1688,0.2710,0.1171,35.8053 +Khronos,12x12,ldr-rgba-base.png,28.9857,0.0875,0.0415,25.2882 +Khronos,12x12,ldr-rgba-diffuse.png,28.5805,0.0932,0.0476,22.0183 +Khronos,12x12,ldr-rgba-specgloss.png,29.7804,0.0849,0.0358,29.2873 +Khronos,12x12,ldr-xy-normal1.png,32.6324,0.1025,0.0298,35.1647 +Khronos,12x12,ldr-xy-normal2.png,36.0402,0.3308,0.0734,57.1221 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..183eea4 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.6014,0.0497,0.0171,61.4896 +Khronos,4x4,ldr-rgb-diffuse.png,54.3556,0.3668,0.2139,19.6089 +Khronos,4x4,ldr-rgb-emissive.png,59.9751,0.0510,0.0162,64.6429 +Khronos,4x4,ldr-rgb-metalrough.png,44.9501,0.2266,0.1827,5.7379 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8315,1.4256,1.2622,3.3229 +Khronos,4x4,ldr-rgba-base.png,43.8666,0.2809,0.2335,4.4907 +Khronos,4x4,ldr-rgba-diffuse.png,44.2878,0.1969,0.1500,6.9903 +Khronos,4x4,ldr-rgba-specgloss.png,42.3783,0.3814,0.3318,3.1604 +Khronos,4x4,ldr-xy-normal1.png,46.6467,0.3285,0.2563,4.0908 +Khronos,4x4,ldr-xy-normal2.png,50.3582,0.7381,0.4919,8.5262 +Khronos,5x5,ldr-l-occlusion.png,57.1684,0.0519,0.0186,56.2964 +Khronos,5x5,ldr-rgb-diffuse.png,49.1067,0.3745,0.2187,19.1796 +Khronos,5x5,ldr-rgb-emissive.png,55.4603,0.0534,0.0174,60.1007 +Khronos,5x5,ldr-rgb-metalrough.png,40.3454,0.2273,0.1831,5.7270 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1509,1.5583,1.3945,3.0078 +Khronos,5x5,ldr-rgba-base.png,39.4887,0.2827,0.2353,4.4557 +Khronos,5x5,ldr-rgba-diffuse.png,39.6329,0.2258,0.1790,5.8569 +Khronos,5x5,ldr-rgba-specgloss.png,38.8241,0.3626,0.3130,3.3499 +Khronos,5x5,ldr-xy-normal1.png,43.1673,0.3168,0.2436,4.3052 +Khronos,5x5,ldr-xy-normal2.png,47.3690,0.6574,0.4005,10.4725 +Khronos,6x6,ldr-l-occlusion.png,50.8693,0.0601,0.0281,37.3742 +Khronos,6x6,ldr-rgb-diffuse.png,44.9599,0.3828,0.2359,17.7803 +Khronos,6x6,ldr-rgb-emissive.png,51.5481,0.0538,0.0189,55.5064 +Khronos,6x6,ldr-rgb-metalrough.png,36.8921,0.2253,0.1817,5.7702 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5121,1.4769,1.3170,3.1848 +Khronos,6x6,ldr-rgba-base.png,36.7084,0.2624,0.2143,4.8940 +Khronos,6x6,ldr-rgba-diffuse.png,36.5436,0.2399,0.1937,5.4146 +Khronos,6x6,ldr-rgba-specgloss.png,36.5238,0.3526,0.3029,3.4614 +Khronos,6x6,ldr-xy-normal1.png,40.6992,0.2719,0.1986,5.2788 +Khronos,6x6,ldr-xy-normal2.png,45.2966,0.4864,0.2273,18.4561 +Khronos,8x8,ldr-l-occlusion.png,45.4623,0.0708,0.0402,26.1133 +Khronos,8x8,ldr-rgb-diffuse.png,40.2673,0.5195,0.3737,11.2228 +Khronos,8x8,ldr-rgb-emissive.png,46.6668,0.0587,0.0257,40.8054 +Khronos,8x8,ldr-rgb-metalrough.png,32.7061,0.2955,0.2515,4.1700 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2423,1.6798,1.5214,2.7568 +Khronos,8x8,ldr-rgba-base.png,33.0988,0.3034,0.2568,4.0827 +Khronos,8x8,ldr-rgba-diffuse.png,32.5945,0.3161,0.2701,3.8816 +Khronos,8x8,ldr-rgba-specgloss.png,33.4998,0.4062,0.3566,2.9406 +Khronos,8x8,ldr-xy-normal1.png,37.4662,0.2941,0.2194,4.7788 +Khronos,8x8,ldr-xy-normal2.png,42.1537,0.5168,0.2588,16.2091 +Khronos,12x12,ldr-l-occlusion.png,41.6349,0.0564,0.0227,46.1766 +Khronos,12x12,ldr-rgb-diffuse.png,35.7761,0.5224,0.3726,11.2569 +Khronos,12x12,ldr-rgb-emissive.png,41.4092,0.0657,0.0288,36.4215 +Khronos,12x12,ldr-rgb-metalrough.png,29.1224,0.2734,0.2273,4.6127 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1747,1.1973,1.0363,4.0476 +Khronos,12x12,ldr-rgba-base.png,29.6502,0.2804,0.2313,4.5335 +Khronos,12x12,ldr-rgba-diffuse.png,29.0821,0.3486,0.3007,3.4875 +Khronos,12x12,ldr-rgba-specgloss.png,30.4902,0.3237,0.2725,3.8479 +Khronos,12x12,ldr-xy-normal1.png,33.5383,0.2436,0.1664,6.3032 +Khronos,12x12,ldr-xy-normal2.png,37.8558,0.5222,0.2613,16.0508 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..e277d81 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.5078,0.0868,0.0547,19.1843 +Khronos,4x4,ldr-rgb-diffuse.png,55.0173,1.4068,1.2562,3.3390 +Khronos,4x4,ldr-rgb-emissive.png,60.9828,0.0722,0.0374,28.0195 +Khronos,4x4,ldr-rgb-metalrough.png,45.0852,0.4640,0.4200,2.4969 +Khronos,4x4,ldr-rgb-metalrough2.png,44.1151,2.8936,2.7291,1.5369 +Khronos,4x4,ldr-rgba-base.png,44.0576,0.5928,0.5436,1.9289 +Khronos,4x4,ldr-rgba-diffuse.png,44.4803,0.3987,0.3520,2.9790 +Khronos,4x4,ldr-rgba-specgloss.png,42.5365,0.7291,0.6792,1.5437 +Khronos,4x4,ldr-xy-normal1.png,46.8266,0.8588,0.7873,1.3318 +Khronos,4x4,ldr-xy-normal2.png,50.7352,1.8054,1.5688,2.6736 +Khronos,5x5,ldr-l-occlusion.png,58.7745,0.1433,0.1104,9.5022 +Khronos,5x5,ldr-rgb-diffuse.png,49.9407,1.2539,1.1036,3.8005 +Khronos,5x5,ldr-rgb-emissive.png,56.2048,0.0813,0.0458,22.8706 +Khronos,5x5,ldr-rgb-metalrough.png,40.5577,0.5022,0.4583,2.2879 +Khronos,5x5,ldr-rgb-metalrough2.png,39.6175,3.2451,3.0827,1.3606 +Khronos,5x5,ldr-rgba-base.png,39.8200,0.6515,0.6034,1.7377 +Khronos,5x5,ldr-rgba-diffuse.png,39.9566,0.4713,0.4242,2.4718 +Khronos,5x5,ldr-rgba-specgloss.png,39.0743,0.7746,0.7242,1.4480 +Khronos,5x5,ldr-xy-normal1.png,43.5230,1.0744,1.0011,1.0474 +Khronos,5x5,ldr-xy-normal2.png,48.0259,2.5504,2.2992,1.8242 +Khronos,6x6,ldr-l-occlusion.png,52.2896,0.1872,0.1555,6.7441 +Khronos,6x6,ldr-rgb-diffuse.png,45.8228,1.2676,1.1158,3.7590 +Khronos,6x6,ldr-rgb-emissive.png,52.7040,0.0898,0.0551,19.0229 +Khronos,6x6,ldr-rgb-metalrough.png,37.0805,0.5798,0.5348,1.9606 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8317,3.6072,3.4477,1.2165 +Khronos,6x6,ldr-rgba-base.png,36.9234,0.7211,0.6732,1.5577 +Khronos,6x6,ldr-rgba-diffuse.png,36.7153,0.5393,0.4923,2.1300 +Khronos,6x6,ldr-rgba-specgloss.png,36.7092,0.8503,0.7999,1.3108 +Khronos,6x6,ldr-xy-normal1.png,41.1567,0.9988,0.9239,1.1349 +Khronos,6x6,ldr-xy-normal2.png,45.8887,2.5015,2.2450,1.8683 +Khronos,8x8,ldr-l-occlusion.png,46.0437,0.2464,0.2133,4.9161 +Khronos,8x8,ldr-rgb-diffuse.png,40.8943,1.4851,1.3397,3.1308 +Khronos,8x8,ldr-rgb-emissive.png,47.5254,0.0979,0.0638,16.4364 +Khronos,8x8,ldr-rgb-metalrough.png,32.8679,0.7558,0.7099,1.4770 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6388,4.5333,4.3750,0.9587 +Khronos,8x8,ldr-rgba-base.png,33.3019,0.9336,0.8843,1.1857 +Khronos,8x8,ldr-rgba-diffuse.png,32.7485,0.7338,0.6868,1.5268 +Khronos,8x8,ldr-rgba-specgloss.png,33.6585,1.0974,1.0467,1.0017 +Khronos,8x8,ldr-xy-normal1.png,37.7495,0.7397,0.6655,1.5756 +Khronos,8x8,ldr-xy-normal2.png,42.5566,1.5603,1.3049,3.2143 +Khronos,12x12,ldr-l-occlusion.png,42.4497,0.2340,0.1979,5.2984 +Khronos,12x12,ldr-rgb-diffuse.png,36.6128,1.7633,1.6134,2.5996 +Khronos,12x12,ldr-rgb-emissive.png,42.3574,0.1399,0.1009,10.3971 +Khronos,12x12,ldr-rgb-metalrough.png,29.3075,0.9951,0.9457,1.1088 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7751,5.1869,5.0267,0.8344 +Khronos,12x12,ldr-rgba-base.png,29.9281,1.0570,1.0050,1.0433 +Khronos,12x12,ldr-rgba-diffuse.png,29.2672,0.9802,0.9295,1.1281 +Khronos,12x12,ldr-rgba-specgloss.png,30.7132,1.3570,1.3020,0.8054 +Khronos,12x12,ldr-xy-normal1.png,33.9601,0.7186,0.6387,1.6417 +Khronos,12x12,ldr-xy-normal2.png,38.4700,1.2113,0.9493,4.4184 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..5fe2286 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0381,0.0081,129.7589 +Khronos,4x4,ldr-rgb-diffuse.png,53.0267,0.2125,0.0643,65.2384 +Khronos,4x4,ldr-rgb-emissive.png,58.6381,0.0398,0.0074,141.4891 +Khronos,4x4,ldr-rgb-metalrough.png,44.3920,0.0912,0.0504,20.8092 +Khronos,4x4,ldr-rgb-metalrough2.png,43.0040,0.4752,0.3186,13.1646 +Khronos,4x4,ldr-rgba-base.png,43.3288,0.1082,0.0635,16.5195 +Khronos,4x4,ldr-rgba-diffuse.png,43.9623,0.0884,0.0450,23.3276 +Khronos,4x4,ldr-rgba-specgloss.png,41.7602,0.1488,0.1023,10.2541 +Khronos,4x4,ldr-xy-normal1.png,45.0735,0.1451,0.0746,14.0588 +Khronos,4x4,ldr-xy-normal2.png,48.7816,0.3630,0.1126,37.2413 +Khronos,5x5,ldr-l-occlusion.png,54.3818,0.0367,0.0062,168.9866 +Khronos,5x5,ldr-rgb-diffuse.png,47.3675,0.1942,0.0493,85.0410 +Khronos,5x5,ldr-rgb-emissive.png,52.6737,0.0388,0.0059,177.3620 +Khronos,5x5,ldr-rgb-metalrough.png,39.9283,0.0789,0.0386,27.1617 +Khronos,5x5,ldr-rgb-metalrough2.png,38.0052,0.4631,0.3086,13.5928 +Khronos,5x5,ldr-rgba-base.png,38.9802,0.0903,0.0458,22.8747 +Khronos,5x5,ldr-rgba-diffuse.png,39.2155,0.0875,0.0441,23.7890 +Khronos,5x5,ldr-rgba-specgloss.png,38.4625,0.1095,0.0632,16.5823 +Khronos,5x5,ldr-xy-normal1.png,41.9841,0.1289,0.0582,18.0029 +Khronos,5x5,ldr-xy-normal2.png,46.4301,0.3251,0.0778,53.9148 +Khronos,6x6,ldr-l-occlusion.png,48.3865,0.0372,0.0076,137.5335 +Khronos,6x6,ldr-rgb-diffuse.png,43.3210,0.2076,0.0688,60.9435 +Khronos,6x6,ldr-rgb-emissive.png,49.1136,0.0381,0.0060,175.8796 +Khronos,6x6,ldr-rgb-metalrough.png,36.5537,0.0862,0.0466,22.5146 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3595,0.4609,0.3105,13.5084 +Khronos,6x6,ldr-rgba-base.png,36.2020,0.0964,0.0528,19.8624 +Khronos,6x6,ldr-rgba-diffuse.png,36.1683,0.0981,0.0554,18.9229 +Khronos,6x6,ldr-rgba-specgloss.png,36.1582,0.1145,0.0687,15.2644 +Khronos,6x6,ldr-xy-normal1.png,39.6982,0.1249,0.0548,19.1433 +Khronos,6x6,ldr-xy-normal2.png,44.2645,0.3251,0.0767,54.6711 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0359,0.0090,116.4706 +Khronos,8x8,ldr-rgb-diffuse.png,38.4394,0.2237,0.0910,46.1020 +Khronos,8x8,ldr-rgb-emissive.png,44.6723,0.0376,0.0076,137.7532 +Khronos,8x8,ldr-rgb-metalrough.png,32.3577,0.1017,0.0619,16.9376 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2246,0.4242,0.2803,14.9617 +Khronos,8x8,ldr-rgba-base.png,32.4790,0.1019,0.0593,17.6733 +Khronos,8x8,ldr-rgba-diffuse.png,32.1796,0.1174,0.0755,13.8925 +Khronos,8x8,ldr-rgba-specgloss.png,32.9682,0.1163,0.0710,14.7747 +Khronos,8x8,ldr-xy-normal1.png,36.5942,0.1193,0.0490,21.4153 +Khronos,8x8,ldr-xy-normal2.png,40.8681,0.3335,0.0882,47.5432 +Khronos,12x12,ldr-l-occlusion.png,40.5805,0.0383,0.0087,120.4581 +Khronos,12x12,ldr-rgb-diffuse.png,33.3842,0.2069,0.0688,61.0045 +Khronos,12x12,ldr-rgb-emissive.png,39.4821,0.0392,0.0071,148.5475 +Khronos,12x12,ldr-rgb-metalrough.png,28.6554,0.0786,0.0383,27.3994 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2607,0.2859,0.1371,30.5888 +Khronos,12x12,ldr-rgba-base.png,29.0476,0.0943,0.0502,20.8730 +Khronos,12x12,ldr-rgba-diffuse.png,28.6320,0.1019,0.0588,17.8190 +Khronos,12x12,ldr-rgba-specgloss.png,29.8260,0.0888,0.0422,24.8190 +Khronos,12x12,ldr-xy-normal1.png,32.7642,0.1064,0.0351,29.8977 +Khronos,12x12,ldr-xy-normal2.png,36.2644,0.3310,0.0809,51.8436 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..1fb3346 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0366,0.0074,141.4709 +Khronos,4x4,ldr-rgb-diffuse.png,52.8124,0.1993,0.0561,74.7821 +Khronos,4x4,ldr-rgb-emissive.png,58.0052,0.0384,0.0067,155.6720 +Khronos,4x4,ldr-rgb-metalrough.png,43.9215,0.0733,0.0333,31.4830 +Khronos,4x4,ldr-rgb-metalrough2.png,42.7188,0.3526,0.2003,20.9386 +Khronos,4x4,ldr-rgba-base.png,42.9028,0.0843,0.0403,25.9979 +Khronos,4x4,ldr-rgba-diffuse.png,43.3583,0.0716,0.0287,36.5180 +Khronos,4x4,ldr-rgba-specgloss.png,41.4613,0.1100,0.0639,16.4117 +Khronos,4x4,ldr-xy-normal1.png,44.9379,0.1185,0.0487,21.5309 +Khronos,4x4,ldr-xy-normal2.png,48.5682,0.3340,0.0882,47.5416 +Khronos,5x5,ldr-l-occlusion.png,54.2370,0.0356,0.0062,168.6044 +Khronos,5x5,ldr-rgb-diffuse.png,47.2115,0.1897,0.0465,90.2793 +Khronos,5x5,ldr-rgb-emissive.png,52.3776,0.0373,0.0054,195.0872 +Khronos,5x5,ldr-rgb-metalrough.png,39.4514,0.0673,0.0279,37.5898 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4945,0.3512,0.2018,20.7842 +Khronos,5x5,ldr-rgba-base.png,38.3583,0.0753,0.0322,32.5815 +Khronos,5x5,ldr-rgba-diffuse.png,38.5295,0.0718,0.0291,36.0274 +Khronos,5x5,ldr-rgba-specgloss.png,37.9922,0.0882,0.0427,24.5649 +Khronos,5x5,ldr-xy-normal1.png,41.5416,0.1096,0.0405,25.9132 +Khronos,5x5,ldr-xy-normal2.png,46.0597,0.3155,0.0663,63.2797 +Khronos,6x6,ldr-l-occlusion.png,48.3019,0.0358,0.0070,149.9044 +Khronos,6x6,ldr-rgb-diffuse.png,43.2732,0.1970,0.0594,70.6397 +Khronos,6x6,ldr-rgb-emissive.png,49.0049,0.0360,0.0050,208.2211 +Khronos,6x6,ldr-rgb-metalrough.png,36.3724,0.0719,0.0330,31.7347 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1757,0.3448,0.1964,21.3586 +Khronos,6x6,ldr-rgba-base.png,36.0313,0.0781,0.0356,29.4495 +Khronos,6x6,ldr-rgba-diffuse.png,35.9759,0.0770,0.0354,29.6476 +Khronos,6x6,ldr-rgba-specgloss.png,35.9374,0.0899,0.0450,23.3156 +Khronos,6x6,ldr-xy-normal1.png,39.2788,0.1077,0.0391,26.8439 +Khronos,6x6,ldr-xy-normal2.png,43.8791,0.3121,0.0632,66.3403 +Khronos,8x8,ldr-l-occlusion.png,43.5147,0.0348,0.0078,134.5544 +Khronos,8x8,ldr-rgb-diffuse.png,38.3057,0.2049,0.0736,57.0157 +Khronos,8x8,ldr-rgb-emissive.png,44.2711,0.0357,0.0059,176.5929 +Khronos,8x8,ldr-rgb-metalrough.png,32.2747,0.0839,0.0450,23.2955 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1205,0.3443,0.2009,20.8760 +Khronos,8x8,ldr-rgba-base.png,32.3546,0.0853,0.0429,24.4698 +Khronos,8x8,ldr-rgba-diffuse.png,32.0684,0.0945,0.0529,19.8368 +Khronos,8x8,ldr-rgba-specgloss.png,32.8728,0.0965,0.0515,20.3757 +Khronos,8x8,ldr-xy-normal1.png,36.3792,0.1067,0.0371,28.2718 +Khronos,8x8,ldr-xy-normal2.png,40.4205,0.3170,0.0729,57.5634 +Khronos,12x12,ldr-l-occlusion.png,40.2288,0.0364,0.0072,146.0223 +Khronos,12x12,ldr-rgb-diffuse.png,33.3337,0.1942,0.0564,74.4173 +Khronos,12x12,ldr-rgb-emissive.png,39.2838,0.0368,0.0054,195.5209 +Khronos,12x12,ldr-rgb-metalrough.png,28.6096,0.0688,0.0286,36.6531 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1688,0.2497,0.1035,40.5435 +Khronos,12x12,ldr-rgba-base.png,28.9857,0.0798,0.0365,28.7259 +Khronos,12x12,ldr-rgba-diffuse.png,28.5805,0.0849,0.0418,25.0634 +Khronos,12x12,ldr-rgba-specgloss.png,29.7804,0.0771,0.0316,33.2141 +Khronos,12x12,ldr-xy-normal1.png,32.6324,0.0970,0.0264,39.7941 +Khronos,12x12,ldr-xy-normal2.png,36.0402,0.3135,0.0648,64.6950 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..ff350f5 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.6014,0.0447,0.0139,75.1777 +Khronos,4x4,ldr-rgb-diffuse.png,54.3556,0.3216,0.1763,23.7883 +Khronos,4x4,ldr-rgb-emissive.png,59.9751,0.0469,0.0145,72.2911 +Khronos,4x4,ldr-rgb-metalrough.png,44.9501,0.1947,0.1533,6.8419 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8315,1.2104,1.0572,3.9675 +Khronos,4x4,ldr-rgba-base.png,43.8666,0.2414,0.1957,5.3569 +Khronos,4x4,ldr-rgba-diffuse.png,44.2878,0.1716,0.1270,8.2571 +Khronos,4x4,ldr-rgba-specgloss.png,42.3783,0.3266,0.2792,3.7559 +Khronos,4x4,ldr-xy-normal1.png,46.6467,0.2878,0.2181,4.8068 +Khronos,4x4,ldr-xy-normal2.png,50.3582,0.6507,0.4143,10.1247 +Khronos,5x5,ldr-l-occlusion.png,57.1684,0.0469,0.0154,68.0054 +Khronos,5x5,ldr-rgb-diffuse.png,49.1067,0.3166,0.1733,24.2068 +Khronos,5x5,ldr-rgb-emissive.png,55.4603,0.0489,0.0148,70.7969 +Khronos,5x5,ldr-rgb-metalrough.png,40.3454,0.1871,0.1453,7.2174 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1509,1.2914,1.1383,3.6846 +Khronos,5x5,ldr-rgba-base.png,39.4887,0.2387,0.1941,5.4015 +Khronos,5x5,ldr-rgba-diffuse.png,39.6329,0.1924,0.1466,7.1537 +Khronos,5x5,ldr-rgba-specgloss.png,38.8241,0.3073,0.2600,4.0336 +Khronos,5x5,ldr-xy-normal1.png,43.1673,0.2708,0.2002,5.2386 +Khronos,5x5,ldr-xy-normal2.png,47.3690,0.5786,0.3273,12.8164 +Khronos,6x6,ldr-l-occlusion.png,50.8693,0.0534,0.0229,45.7672 +Khronos,6x6,ldr-rgb-diffuse.png,44.9599,0.3300,0.1914,21.9152 +Khronos,6x6,ldr-rgb-emissive.png,51.5481,0.0489,0.0159,66.1400 +Khronos,6x6,ldr-rgb-metalrough.png,36.8921,0.1896,0.1485,7.0609 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5121,1.2324,1.0788,3.8880 +Khronos,6x6,ldr-rgba-base.png,36.7084,0.2215,0.1765,5.9415 +Khronos,6x6,ldr-rgba-diffuse.png,36.5436,0.2031,0.1588,6.6043 +Khronos,6x6,ldr-rgba-specgloss.png,36.5238,0.2964,0.2498,4.1983 +Khronos,6x6,ldr-xy-normal1.png,40.6992,0.2347,0.1640,6.3947 +Khronos,6x6,ldr-xy-normal2.png,45.2966,0.4383,0.1882,22.2878 +Khronos,8x8,ldr-l-occlusion.png,45.4623,0.0621,0.0336,31.2372 +Khronos,8x8,ldr-rgb-diffuse.png,40.2673,0.4435,0.3089,13.5785 +Khronos,8x8,ldr-rgb-emissive.png,46.6668,0.0532,0.0218,48.1350 +Khronos,8x8,ldr-rgb-metalrough.png,32.7061,0.2509,0.2097,4.9997 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2423,1.4203,1.2761,3.2867 +Khronos,8x8,ldr-rgba-base.png,33.0988,0.2602,0.2151,4.8750 +Khronos,8x8,ldr-rgba-diffuse.png,32.5945,0.2699,0.2261,4.6372 +Khronos,8x8,ldr-rgba-specgloss.png,33.4998,0.3439,0.2971,3.5291 +Khronos,8x8,ldr-xy-normal1.png,37.4662,0.2544,0.1823,5.7508 +Khronos,8x8,ldr-xy-normal2.png,42.1537,0.4618,0.2153,19.4817 +Khronos,12x12,ldr-l-occlusion.png,41.6349,0.0516,0.0201,52.2433 +Khronos,12x12,ldr-rgb-diffuse.png,35.7761,0.4705,0.3290,12.7499 +Khronos,12x12,ldr-rgb-emissive.png,41.4092,0.0611,0.0256,41.0002 +Khronos,12x12,ldr-rgb-metalrough.png,29.1224,0.2439,0.2007,5.2254 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1747,1.0665,0.9167,4.5754 +Khronos,12x12,ldr-rgba-base.png,29.6502,0.2538,0.2060,5.0913 +Khronos,12x12,ldr-rgba-diffuse.png,29.0821,0.3112,0.2652,3.9541 +Khronos,12x12,ldr-rgba-specgloss.png,30.4902,0.2910,0.2418,4.3367 +Khronos,12x12,ldr-xy-normal1.png,33.5383,0.2233,0.1474,7.1135 +Khronos,12x12,ldr-xy-normal2.png,37.8558,0.4840,0.2298,18.2509 diff --git a/Test/Images/Khronos/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..c1e36f5 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.5078,0.0761,0.0451,23.2491 +Khronos,4x4,ldr-rgb-diffuse.png,55.0173,1.2039,1.0598,3.9578 +Khronos,4x4,ldr-rgb-emissive.png,60.9828,0.0658,0.0325,32.2676 +Khronos,4x4,ldr-rgb-metalrough.png,45.0852,0.3962,0.3543,2.9594 +Khronos,4x4,ldr-rgb-metalrough2.png,44.1151,2.4540,2.2991,1.8243 +Khronos,4x4,ldr-rgba-base.png,44.0576,0.5032,0.4574,2.2926 +Khronos,4x4,ldr-rgba-diffuse.png,44.4803,0.3452,0.3005,3.4897 +Khronos,4x4,ldr-rgba-specgloss.png,42.5365,0.6260,0.5788,1.8117 +Khronos,4x4,ldr-xy-normal1.png,46.8266,0.7533,0.6836,1.5338 +Khronos,4x4,ldr-xy-normal2.png,50.7352,1.5754,1.3439,3.1209 +Khronos,5x5,ldr-l-occlusion.png,58.7745,0.1208,0.0894,11.7245 +Khronos,5x5,ldr-rgb-diffuse.png,49.9407,1.0464,0.9039,4.6400 +Khronos,5x5,ldr-rgb-emissive.png,56.2048,0.0717,0.0381,27.5124 +Khronos,5x5,ldr-rgb-metalrough.png,40.5577,0.4186,0.3769,2.7822 +Khronos,5x5,ldr-rgb-metalrough2.png,39.6175,2.7013,2.5471,1.6467 +Khronos,5x5,ldr-rgba-base.png,39.8200,0.5469,0.4995,2.0994 +Khronos,5x5,ldr-rgba-diffuse.png,39.9566,0.3955,0.3511,2.9864 +Khronos,5x5,ldr-rgba-specgloss.png,39.0743,0.6522,0.6047,1.7340 +Khronos,5x5,ldr-xy-normal1.png,43.5230,0.9153,0.8425,1.2447 +Khronos,5x5,ldr-xy-normal2.png,48.0259,2.1604,1.9181,2.1867 +Khronos,6x6,ldr-l-occlusion.png,52.2896,0.1559,0.1258,8.3366 +Khronos,6x6,ldr-rgb-diffuse.png,45.8228,1.0543,0.9144,4.5868 +Khronos,6x6,ldr-rgb-emissive.png,52.7040,0.0792,0.0458,22.9168 +Khronos,6x6,ldr-rgb-metalrough.png,37.0805,0.4840,0.4412,2.3767 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8317,3.0200,2.8701,1.4614 +Khronos,6x6,ldr-rgba-base.png,36.9234,0.6087,0.5632,1.8618 +Khronos,6x6,ldr-rgba-diffuse.png,36.7153,0.4531,0.4090,2.5640 +Khronos,6x6,ldr-rgba-specgloss.png,36.7092,0.7170,0.6697,1.5658 +Khronos,6x6,ldr-xy-normal1.png,41.1567,0.8440,0.7727,1.3570 +Khronos,6x6,ldr-xy-normal2.png,45.8887,2.1253,1.8790,2.2322 +Khronos,8x8,ldr-l-occlusion.png,46.0437,0.2095,0.1795,5.8409 +Khronos,8x8,ldr-rgb-diffuse.png,40.8943,1.2651,1.1278,3.7190 +Khronos,8x8,ldr-rgb-emissive.png,47.5254,0.0866,0.0542,19.3386 +Khronos,8x8,ldr-rgb-metalrough.png,32.8679,0.6436,0.6010,1.7447 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6388,3.8676,3.7198,1.1276 +Khronos,8x8,ldr-rgba-base.png,33.3019,0.7957,0.7503,1.3975 +Khronos,8x8,ldr-rgba-diffuse.png,32.7485,0.6298,0.5850,1.7925 +Khronos,8x8,ldr-rgba-specgloss.png,33.6585,0.9435,0.8948,1.1719 +Khronos,8x8,ldr-xy-normal1.png,37.7495,0.6373,0.5648,1.8565 +Khronos,8x8,ldr-xy-normal2.png,42.5566,1.3422,1.0941,3.8334 +Khronos,12x12,ldr-l-occlusion.png,42.4497,0.2097,0.1749,5.9953 +Khronos,12x12,ldr-rgb-diffuse.png,36.6128,1.5722,1.4272,2.9388 +Khronos,12x12,ldr-rgb-emissive.png,42.3574,0.1270,0.0892,11.7531 +Khronos,12x12,ldr-rgb-metalrough.png,29.3075,0.8875,0.8418,1.2457 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7751,4.6276,4.4710,0.9381 +Khronos,12x12,ldr-rgba-base.png,29.9281,0.9456,0.8942,1.1727 +Khronos,12x12,ldr-rgba-diffuse.png,29.2672,0.8751,0.8263,1.2690 +Khronos,12x12,ldr-rgba-specgloss.png,30.7132,1.2148,1.1633,0.9014 +Khronos,12x12,ldr-xy-normal1.png,33.9601,0.6449,0.5683,1.8450 +Khronos,12x12,ldr-xy-normal2.png,38.4700,1.0933,0.8410,4.9871 diff --git a/Test/Images/Khronos/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/Khronos/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..ee7453a --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2220,0.0370,0.0071,147.5409 +Khronos,4x4,ldr-rgb-diffuse.png,53.2418,0.1996,0.0542,77.4185 +Khronos,4x4,ldr-rgb-emissive.png,58.6689,0.0387,0.0071,148.0425 +Khronos,4x4,ldr-rgb-metalrough.png,44.4033,0.0848,0.0448,23.3843 +Khronos,4x4,ldr-rgb-metalrough2.png,43.0113,0.4352,0.2842,14.7602 +Khronos,4x4,ldr-rgba-base.png,43.3485,0.1011,0.0571,18.3796 +Khronos,4x4,ldr-rgba-diffuse.png,43.9699,0.0836,0.0401,26.1281 +Khronos,4x4,ldr-rgba-specgloss.png,41.7678,0.1403,0.0930,11.2738 +Khronos,4x4,ldr-xy-normal1.png,45.0735,0.1362,0.0657,15.9596 +Khronos,4x4,ldr-xy-normal2.png,48.7816,0.3499,0.0974,43.0707 +Khronos,5x5,ldr-l-occlusion.png,54.3818,0.0356,0.0054,195.0786 +Khronos,5x5,ldr-rgb-diffuse.png,47.4493,0.1882,0.0408,102.8675 +Khronos,5x5,ldr-rgb-emissive.png,52.6811,0.0382,0.0060,174.4149 +Khronos,5x5,ldr-rgb-metalrough.png,39.9455,0.0738,0.0331,31.6753 +Khronos,5x5,ldr-rgb-metalrough2.png,38.0100,0.4152,0.2657,15.7830 +Khronos,5x5,ldr-rgba-base.png,38.9836,0.0837,0.0392,26.7337 +Khronos,5x5,ldr-rgba-diffuse.png,39.2167,0.0817,0.0379,27.6692 +Khronos,5x5,ldr-rgba-specgloss.png,38.4684,0.1000,0.0540,19.4170 +Khronos,5x5,ldr-xy-normal1.png,41.9841,0.1210,0.0501,20.9498 +Khronos,5x5,ldr-xy-normal2.png,46.4301,0.3211,0.0661,63.4817 +Khronos,6x6,ldr-l-occlusion.png,48.3865,0.0356,0.0062,167.8772 +Khronos,6x6,ldr-rgb-diffuse.png,43.3495,0.1947,0.0536,78.2344 +Khronos,6x6,ldr-rgb-emissive.png,49.1158,0.0364,0.0051,205.8818 +Khronos,6x6,ldr-rgb-metalrough.png,36.5585,0.0760,0.0371,28.2773 +Khronos,6x6,ldr-rgb-metalrough2.png,35.3616,0.3988,0.2510,16.7120 +Khronos,6x6,ldr-rgba-base.png,36.2055,0.0848,0.0425,24.6862 +Khronos,6x6,ldr-rgba-diffuse.png,36.1693,0.0869,0.0447,23.4680 +Khronos,6x6,ldr-rgba-specgloss.png,36.1633,0.1001,0.0552,18.9893 +Khronos,6x6,ldr-xy-normal1.png,39.6982,0.1145,0.0450,23.3162 +Khronos,6x6,ldr-xy-normal2.png,44.2645,0.3135,0.0622,67.4128 +Khronos,8x8,ldr-l-occlusion.png,44.0109,0.0345,0.0072,145.4140 +Khronos,8x8,ldr-rgb-diffuse.png,38.4528,0.1967,0.0695,60.3516 +Khronos,8x8,ldr-rgb-emissive.png,44.6690,0.0353,0.0061,171.0304 +Khronos,8x8,ldr-rgb-metalrough.png,32.3608,0.0844,0.0474,22.1270 +Khronos,8x8,ldr-rgb-metalrough2.png,32.2252,0.3534,0.2140,19.5996 +Khronos,8x8,ldr-rgba-base.png,32.4791,0.0878,0.0460,22.8051 +Khronos,8x8,ldr-rgba-diffuse.png,32.1803,0.0993,0.0580,18.0714 +Khronos,8x8,ldr-rgba-specgloss.png,32.9700,0.0990,0.0549,19.1168 +Khronos,8x8,ldr-xy-normal1.png,36.5942,0.1072,0.0384,27.3018 +Khronos,8x8,ldr-xy-normal2.png,40.8681,0.3106,0.0688,60.9388 +Khronos,12x12,ldr-l-occlusion.png,40.5805,0.0363,0.0065,162.4694 +Khronos,12x12,ldr-rgb-diffuse.png,33.3907,0.1875,0.0512,81.9537 +Khronos,12x12,ldr-rgb-emissive.png,39.4822,0.0365,0.0054,192.5421 +Khronos,12x12,ldr-rgb-metalrough.png,28.6562,0.0678,0.0287,36.5766 +Khronos,12x12,ldr-rgb-metalrough2.png,29.2641,0.2488,0.1020,41.1287 +Khronos,12x12,ldr-rgba-base.png,29.0480,0.0810,0.0376,27.9069 +Khronos,12x12,ldr-rgba-diffuse.png,28.6322,0.0866,0.0438,23.9172 +Khronos,12x12,ldr-rgba-specgloss.png,29.8272,0.0771,0.0320,32.7794 +Khronos,12x12,ldr-xy-normal1.png,32.7642,0.0964,0.0265,39.5241 +Khronos,12x12,ldr-xy-normal2.png,36.2644,0.3116,0.0618,67.9209 diff --git a/Test/Images/Khronos/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/Khronos/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..3fbb449 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,65.2091,0.0358,0.0067,156.3639 +Khronos,4x4,ldr-rgb-diffuse.png,53.0241,0.1937,0.0486,86.2650 +Khronos,4x4,ldr-rgb-emissive.png,58.0461,0.0376,0.0065,161.6394 +Khronos,4x4,ldr-rgb-metalrough.png,43.9329,0.0694,0.0295,35.5521 +Khronos,4x4,ldr-rgb-metalrough2.png,42.7265,0.3280,0.1772,23.6738 +Khronos,4x4,ldr-rgba-base.png,42.9205,0.0803,0.0362,28.9621 +Khronos,4x4,ldr-rgba-diffuse.png,43.3656,0.0690,0.0254,41.2354 +Khronos,4x4,ldr-rgba-specgloss.png,41.4692,0.1024,0.0574,18.2739 +Khronos,4x4,ldr-xy-normal1.png,44.9379,0.1126,0.0431,24.3509 +Khronos,4x4,ldr-xy-normal2.png,48.5682,0.3269,0.0765,54.8518 +Khronos,5x5,ldr-l-occlusion.png,54.2370,0.0343,0.0054,194.3544 +Khronos,5x5,ldr-rgb-diffuse.png,47.2889,0.1823,0.0385,108.8895 +Khronos,5x5,ldr-rgb-emissive.png,52.3843,0.0361,0.0050,210.2216 +Khronos,5x5,ldr-rgb-metalrough.png,39.4668,0.0631,0.0234,44.8565 +Khronos,5x5,ldr-rgb-metalrough2.png,37.4988,0.3230,0.1711,24.5172 +Khronos,5x5,ldr-rgba-base.png,38.3612,0.0709,0.0272,38.5111 +Khronos,5x5,ldr-rgba-diffuse.png,38.5312,0.0674,0.0247,42.4493 +Khronos,5x5,ldr-rgba-specgloss.png,37.9980,0.0810,0.0360,29.1126 +Khronos,5x5,ldr-xy-normal1.png,41.5416,0.1043,0.0349,30.0805 +Khronos,5x5,ldr-xy-normal2.png,46.0597,0.3101,0.0563,74.4848 +Khronos,6x6,ldr-l-occlusion.png,48.3019,0.0346,0.0058,181.7299 +Khronos,6x6,ldr-rgb-diffuse.png,43.2974,0.1858,0.0464,90.3053 +Khronos,6x6,ldr-rgb-emissive.png,49.0070,0.0347,0.0045,235.1016 +Khronos,6x6,ldr-rgb-metalrough.png,36.3770,0.0646,0.0261,40.1293 +Khronos,6x6,ldr-rgb-metalrough2.png,35.1779,0.3045,0.1566,26.7836 +Khronos,6x6,ldr-rgba-base.png,36.0346,0.0715,0.0285,36.7868 +Khronos,6x6,ldr-rgba-diffuse.png,35.9764,0.0704,0.0284,36.9475 +Khronos,6x6,ldr-rgba-specgloss.png,35.9426,0.0804,0.0359,29.1839 +Khronos,6x6,ldr-xy-normal1.png,39.2788,0.1005,0.0321,32.6485 +Khronos,6x6,ldr-xy-normal2.png,43.8791,0.3007,0.0516,81.2377 +Khronos,8x8,ldr-l-occlusion.png,43.5147,0.0340,0.0064,164.2533 +Khronos,8x8,ldr-rgb-diffuse.png,38.3219,0.1855,0.0568,73.8500 +Khronos,8x8,ldr-rgb-emissive.png,44.2682,0.0339,0.0050,208.5865 +Khronos,8x8,ldr-rgb-metalrough.png,32.2777,0.0717,0.0350,29.9970 +Khronos,8x8,ldr-rgb-metalrough2.png,32.1212,0.2933,0.1551,27.0480 +Khronos,8x8,ldr-rgba-base.png,32.3549,0.0749,0.0341,30.7193 +Khronos,8x8,ldr-rgba-diffuse.png,32.0693,0.0820,0.0414,25.3255 +Khronos,8x8,ldr-rgba-specgloss.png,32.8744,0.0837,0.0402,26.0865 +Khronos,8x8,ldr-xy-normal1.png,36.3792,0.0968,0.0295,35.6028 +Khronos,8x8,ldr-xy-normal2.png,40.4205,0.2981,0.0580,72.3544 +Khronos,12x12,ldr-l-occlusion.png,40.2288,0.0346,0.0055,191.2444 +Khronos,12x12,ldr-rgb-diffuse.png,33.3401,0.1785,0.0423,99.0696 +Khronos,12x12,ldr-rgb-emissive.png,39.2839,0.0349,0.0042,247.6517 +Khronos,12x12,ldr-rgb-metalrough.png,28.6103,0.0605,0.0217,48.2369 +Khronos,12x12,ldr-rgb-metalrough2.png,29.1709,0.2229,0.0774,54.1705 +Khronos,12x12,ldr-rgba-base.png,28.9861,0.0706,0.0274,38.2146 +Khronos,12x12,ldr-rgba-diffuse.png,28.5805,0.0736,0.0316,33.1963 +Khronos,12x12,ldr-rgba-specgloss.png,29.7817,0.0685,0.0240,43.6509 +Khronos,12x12,ldr-xy-normal1.png,32.6324,0.0896,0.0203,51.6154 +Khronos,12x12,ldr-xy-normal2.png,36.0402,0.2995,0.0500,83.8694 diff --git a/Test/Images/Khronos/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/Khronos/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..8f21499 --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,68.6014,0.0421,0.0116,90.3776 +Khronos,4x4,ldr-rgb-diffuse.png,54.3884,0.2978,0.1508,27.8052 +Khronos,4x4,ldr-rgb-emissive.png,60.0039,0.0448,0.0130,80.9268 +Khronos,4x4,ldr-rgb-metalrough.png,44.9558,0.1756,0.1349,7.7733 +Khronos,4x4,ldr-rgb-metalrough2.png,43.8399,1.0890,0.9363,4.4796 +Khronos,4x4,ldr-rgba-base.png,43.8790,0.2207,0.1754,5.9772 +Khronos,4x4,ldr-rgba-diffuse.png,44.2942,0.1571,0.1130,9.2803 +Khronos,4x4,ldr-rgba-specgloss.png,42.3942,0.2928,0.2460,4.2626 +Khronos,4x4,ldr-xy-normal1.png,46.6467,0.2593,0.1908,5.4946 +Khronos,4x4,ldr-xy-normal2.png,50.3582,0.5937,0.3569,11.7517 +Khronos,5x5,ldr-l-occlusion.png,57.1684,0.0441,0.0130,80.8955 +Khronos,5x5,ldr-rgb-diffuse.png,49.1263,0.2869,0.1432,29.2878 +Khronos,5x5,ldr-rgb-emissive.png,55.4722,0.0459,0.0127,82.2926 +Khronos,5x5,ldr-rgb-metalrough.png,40.3564,0.1637,0.1228,8.5394 +Khronos,5x5,ldr-rgb-metalrough2.png,39.1561,1.1059,0.9543,4.3950 +Khronos,5x5,ldr-rgba-base.png,39.4933,0.2083,0.1630,6.4350 +Khronos,5x5,ldr-rgba-diffuse.png,39.6342,0.1686,0.1238,8.4691 +Khronos,5x5,ldr-rgba-specgloss.png,38.8297,0.2647,0.2177,4.8165 +Khronos,5x5,ldr-xy-normal1.png,43.1673,0.2371,0.1671,6.2761 +Khronos,5x5,ldr-xy-normal2.png,47.3689,0.5194,0.2699,15.5388 +Khronos,6x6,ldr-l-occlusion.png,50.8693,0.0481,0.0182,57.5540 +Khronos,6x6,ldr-rgb-diffuse.png,44.9823,0.2923,0.1506,27.8494 +Khronos,6x6,ldr-rgb-emissive.png,51.5547,0.0452,0.0131,79.9107 +Khronos,6x6,ldr-rgb-metalrough.png,36.8953,0.1588,0.1199,8.7480 +Khronos,6x6,ldr-rgb-metalrough2.png,36.5150,1.0277,0.8793,4.7701 +Khronos,6x6,ldr-rgba-base.png,36.7120,0.1865,0.1420,7.3859 +Khronos,6x6,ldr-rgba-diffuse.png,36.5446,0.1720,0.1284,8.1667 +Khronos,6x6,ldr-rgba-specgloss.png,36.5286,0.2501,0.2035,5.1517 +Khronos,6x6,ldr-xy-normal1.png,40.6992,0.2027,0.1326,7.9064 +Khronos,6x6,ldr-xy-normal2.png,45.2966,0.4036,0.1509,27.8024 +Khronos,8x8,ldr-l-occlusion.png,45.4623,0.0545,0.0254,41.2811 +Khronos,8x8,ldr-rgb-diffuse.png,40.2835,0.3618,0.2319,18.0849 +Khronos,8x8,ldr-rgb-emissive.png,46.6675,0.0474,0.0168,62.4226 +Khronos,8x8,ldr-rgb-metalrough.png,32.7090,0.2007,0.1621,6.4670 +Khronos,8x8,ldr-rgb-metalrough2.png,33.2429,1.1252,0.9844,4.2606 +Khronos,8x8,ldr-rgba-base.png,33.1003,0.2062,0.1635,6.4133 +Khronos,8x8,ldr-rgba-diffuse.png,32.5948,0.2175,0.1740,6.0258 +Khronos,8x8,ldr-rgba-specgloss.png,33.5022,0.2758,0.2303,4.5540 +Khronos,8x8,ldr-xy-normal1.png,37.4662,0.2113,0.1408,7.4450 +Khronos,8x8,ldr-xy-normal2.png,42.1537,0.4075,0.1651,25.4059 +Khronos,12x12,ldr-l-occlusion.png,41.6349,0.0473,0.0149,70.3552 +Khronos,12x12,ldr-rgb-diffuse.png,35.7843,0.3762,0.2375,17.6635 +Khronos,12x12,ldr-rgb-emissive.png,41.4092,0.0530,0.0193,54.4596 +Khronos,12x12,ldr-rgb-metalrough.png,29.1232,0.1918,0.1494,7.0163 +Khronos,12x12,ldr-rgb-metalrough2.png,30.1752,0.8267,0.6795,6.1731 +Khronos,12x12,ldr-rgba-base.png,29.6504,0.1987,0.1531,6.8511 +Khronos,12x12,ldr-rgba-diffuse.png,29.0820,0.2461,0.2012,5.2123 +Khronos,12x12,ldr-rgba-specgloss.png,30.4918,0.2278,0.1801,5.8236 +Khronos,12x12,ldr-xy-normal1.png,33.5383,0.1857,0.1114,9.4111 +Khronos,12x12,ldr-xy-normal2.png,37.8558,0.4263,0.1720,24.3785 diff --git a/Test/Images/Khronos/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/Khronos/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..0b97c2b --- /dev/null +++ b/Test/Images/Khronos/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,51 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Khronos,4x4,ldr-l-occlusion.png,70.5078,0.0701,0.0389,26.9224 +Khronos,4x4,ldr-rgb-diffuse.png,55.1174,1.0661,0.9248,4.5352 +Khronos,4x4,ldr-rgb-emissive.png,61.0315,0.0612,0.0290,36.1117 +Khronos,4x4,ldr-rgb-metalrough.png,45.0904,0.3499,0.3090,3.3938 +Khronos,4x4,ldr-rgb-metalrough2.png,44.1252,2.1653,2.0124,2.0843 +Khronos,4x4,ldr-rgba-base.png,44.0698,0.4502,0.4051,2.5887 +Khronos,4x4,ldr-rgba-diffuse.png,44.4863,0.3086,0.2640,3.9715 +Khronos,4x4,ldr-rgba-specgloss.png,42.5520,0.5513,0.5042,2.0797 +Khronos,4x4,ldr-xy-normal1.png,46.8266,0.6656,0.5981,1.7532 +Khronos,4x4,ldr-xy-normal2.png,50.7352,1.4058,1.1740,3.5725 +Khronos,5x5,ldr-l-occlusion.png,58.7745,0.1064,0.0752,13.9501 +Khronos,5x5,ldr-rgb-diffuse.png,49.9726,0.9054,0.7625,5.5005 +Khronos,5x5,ldr-rgb-emissive.png,56.2188,0.0658,0.0327,32.0401 +Khronos,5x5,ldr-rgb-metalrough.png,40.5616,0.3589,0.3178,3.2993 +Khronos,5x5,ldr-rgb-metalrough2.png,39.6224,2.2867,2.1351,1.9644 +Khronos,5x5,ldr-rgba-base.png,39.8238,0.4691,0.4227,2.4804 +Khronos,5x5,ldr-rgba-diffuse.png,39.9581,0.3426,0.2982,3.5162 +Khronos,5x5,ldr-rgba-specgloss.png,39.0811,0.5560,0.5086,2.0616 +Khronos,5x5,ldr-xy-normal1.png,43.5230,0.7848,0.7136,1.4695 +Khronos,5x5,ldr-xy-normal2.png,48.0259,1.8541,1.6128,2.6006 +Khronos,6x6,ldr-l-occlusion.png,52.2896,0.1308,0.1006,10.4203 +Khronos,6x6,ldr-rgb-diffuse.png,45.8474,0.8690,0.7312,5.7360 +Khronos,6x6,ldr-rgb-emissive.png,52.7081,0.0694,0.0372,28.1686 +Khronos,6x6,ldr-rgb-metalrough.png,37.0837,0.3958,0.3555,2.9494 +Khronos,6x6,ldr-rgb-metalrough2.png,36.8344,2.4918,2.3437,1.7896 +Khronos,6x6,ldr-rgba-base.png,36.9273,0.5016,0.4567,2.2958 +Khronos,6x6,ldr-rgba-diffuse.png,36.7165,0.3753,0.3319,3.1590 +Khronos,6x6,ldr-rgba-specgloss.png,36.7141,0.5986,0.5518,1.9003 +Khronos,6x6,ldr-xy-normal1.png,41.1567,0.6986,0.6280,1.6697 +Khronos,6x6,ldr-xy-normal2.png,45.8887,1.7654,1.5207,2.7581 +Khronos,8x8,ldr-l-occlusion.png,46.0437,0.1668,0.1360,7.7095 +Khronos,8x8,ldr-rgb-diffuse.png,40.9077,0.9859,0.8510,4.9286 +Khronos,8x8,ldr-rgb-emissive.png,47.5271,0.0745,0.0420,24.9869 +Khronos,8x8,ldr-rgb-metalrough.png,32.8690,0.5028,0.4623,2.2684 +Khronos,8x8,ldr-rgb-metalrough2.png,33.6394,3.0298,2.8892,1.4517 +Khronos,8x8,ldr-rgba-base.png,33.3032,0.6308,0.5845,1.7938 +Khronos,8x8,ldr-rgba-diffuse.png,32.7488,0.4948,0.4513,2.3233 +Khronos,8x8,ldr-rgba-specgloss.png,33.6613,0.7427,0.6942,1.5104 +Khronos,8x8,ldr-xy-normal1.png,37.7495,0.4995,0.4282,2.4487 +Khronos,8x8,ldr-xy-normal2.png,42.5566,1.0532,0.8113,5.1697 +Khronos,12x12,ldr-l-occlusion.png,42.4497,0.1641,0.1298,8.0800 +Khronos,12x12,ldr-rgb-diffuse.png,36.6186,1.2087,1.0670,3.9308 +Khronos,12x12,ldr-rgb-emissive.png,42.3575,0.1032,0.0672,15.6066 +Khronos,12x12,ldr-rgb-metalrough.png,29.3080,0.6827,0.6386,1.6421 +Khronos,12x12,ldr-rgb-metalrough2.png,30.7754,3.5837,3.4344,1.2213 +Khronos,12x12,ldr-rgba-base.png,29.9285,0.7331,0.6838,1.5334 +Khronos,12x12,ldr-rgba-diffuse.png,29.2674,0.6781,0.6306,1.6629 +Khronos,12x12,ldr-rgba-specgloss.png,30.7150,0.9417,0.8915,1.1762 +Khronos,12x12,ldr-xy-normal1.png,33.9601,0.5027,0.4291,2.4438 +Khronos,12x12,ldr-xy-normal2.png,38.4700,0.8736,0.6224,6.7393 diff --git a/Test/Images/Kodak/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/Kodak/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index a483546..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.8489,0.0350,0.0182,21.5624 -Kodak,4x4,ldr-rgb-kodak02.png,44.2380,0.0435,0.0252,15.6045 -Kodak,4x4,ldr-rgb-kodak03.png,46.6338,0.0304,0.0149,26.3125 -Kodak,4x4,ldr-rgb-kodak04.png,44.5665,0.0433,0.0226,17.3891 -Kodak,4x4,ldr-rgb-kodak05.png,41.5682,0.0514,0.0333,11.8175 -Kodak,4x4,ldr-rgb-kodak06.png,44.7452,0.0346,0.0179,21.9183 -Kodak,4x4,ldr-rgb-kodak07.png,45.0418,0.0397,0.0199,19.7248 -Kodak,4x4,ldr-rgb-kodak08.png,42.0821,0.0562,0.0346,11.3516 -Kodak,4x4,ldr-rgb-kodak09.png,46.2551,0.0330,0.0140,28.1248 -Kodak,4x4,ldr-rgb-kodak10.png,46.0288,0.0349,0.0146,26.9088 -Kodak,4x4,ldr-rgb-kodak11.png,44.2450,0.0378,0.0213,18.4548 -Kodak,4x4,ldr-rgb-kodak12.png,47.0135,0.0295,0.0137,28.6580 -Kodak,4x4,ldr-rgb-kodak13.png,41.4309,0.0479,0.0294,13.3965 -Kodak,4x4,ldr-rgb-kodak14.png,41.8065,0.0449,0.0273,14.3772 -Kodak,4x4,ldr-rgb-kodak15.png,44.5942,0.0433,0.0244,16.0896 -Kodak,4x4,ldr-rgb-kodak16.png,47.1801,0.0280,0.0123,32.0445 -Kodak,4x4,ldr-rgb-kodak17.png,45.7548,0.0336,0.0132,29.7262 -Kodak,4x4,ldr-rgb-kodak18.png,41.6128,0.0546,0.0329,11.9410 -Kodak,4x4,ldr-rgb-kodak19.png,44.8023,0.0383,0.0177,22.2748 -Kodak,4x4,ldr-rgb-kodak20.png,46.3894,0.0310,0.0154,25.4819 -Kodak,4x4,ldr-rgb-kodak21.png,44.5781,0.0353,0.0185,21.2021 -Kodak,4x4,ldr-rgb-kodak22.png,43.1599,0.0470,0.0279,14.1069 -Kodak,4x4,ldr-rgb-kodak23.png,45.5706,0.0348,0.0177,22.1893 -Kodak,4x4,ldr-rgb-kodak24.png,41.8541,0.0466,0.0275,14.2743 -Kodak,5x5,ldr-rgb-kodak01.png,39.6106,0.0354,0.0176,22.3979 -Kodak,5x5,ldr-rgb-kodak02.png,40.6312,0.0360,0.0164,23.9270 -Kodak,5x5,ldr-rgb-kodak03.png,43.0303,0.0282,0.0119,32.9906 -Kodak,5x5,ldr-rgb-kodak04.png,41.2378,0.0376,0.0158,24.9300 -Kodak,5x5,ldr-rgb-kodak05.png,37.4134,0.0484,0.0291,13.5336 -Kodak,5x5,ldr-rgb-kodak06.png,40.5758,0.0319,0.0144,27.3656 -Kodak,5x5,ldr-rgb-kodak07.png,41.4746,0.0357,0.0149,26.4183 -Kodak,5x5,ldr-rgb-kodak08.png,37.7544,0.0520,0.0297,13.2338 -Kodak,5x5,ldr-rgb-kodak09.png,42.9020,0.0309,0.0108,36.5716 -Kodak,5x5,ldr-rgb-kodak10.png,42.6178,0.0322,0.0110,35.7953 -Kodak,5x5,ldr-rgb-kodak11.png,40.2886,0.0340,0.0165,23.8340 -Kodak,5x5,ldr-rgb-kodak12.png,43.4048,0.0273,0.0102,38.4230 -Kodak,5x5,ldr-rgb-kodak13.png,36.8038,0.0451,0.0261,15.0703 -Kodak,5x5,ldr-rgb-kodak14.png,37.9374,0.0442,0.0256,15.3792 -Kodak,5x5,ldr-rgb-kodak15.png,41.1606,0.0366,0.0164,23.9590 -Kodak,5x5,ldr-rgb-kodak16.png,43.4729,0.0266,0.0094,41.7335 -Kodak,5x5,ldr-rgb-kodak17.png,42.0129,0.0325,0.0110,35.7860 -Kodak,5x5,ldr-rgb-kodak18.png,38.0842,0.0482,0.0232,16.9220 -Kodak,5x5,ldr-rgb-kodak19.png,41.1186,0.0348,0.0127,31.0474 -Kodak,5x5,ldr-rgb-kodak20.png,42.3441,0.0280,0.0119,33.0435 -Kodak,5x5,ldr-rgb-kodak21.png,40.4026,0.0331,0.0155,25.3999 -Kodak,5x5,ldr-rgb-kodak22.png,39.7574,0.0387,0.0184,21.3332 -Kodak,5x5,ldr-rgb-kodak23.png,42.4861,0.0308,0.0123,32.0414 -Kodak,5x5,ldr-rgb-kodak24.png,37.7908,0.0415,0.0214,18.3711 -Kodak,6x6,ldr-rgb-kodak01.png,35.7514,0.0421,0.0237,16.6074 -Kodak,6x6,ldr-rgb-kodak02.png,38.1633,0.0367,0.0166,23.6251 -Kodak,6x6,ldr-rgb-kodak03.png,40.5315,0.0284,0.0113,34.9310 -Kodak,6x6,ldr-rgb-kodak04.png,38.5310,0.0384,0.0158,24.9014 -Kodak,6x6,ldr-rgb-kodak05.png,34.3246,0.0542,0.0345,11.4115 -Kodak,6x6,ldr-rgb-kodak06.png,37.2781,0.0353,0.0169,23.2439 -Kodak,6x6,ldr-rgb-kodak07.png,38.8424,0.0367,0.0156,25.2209 -Kodak,6x6,ldr-rgb-kodak08.png,34.4294,0.0577,0.0349,11.2692 -Kodak,6x6,ldr-rgb-kodak09.png,39.9499,0.0325,0.0119,33.1325 -Kodak,6x6,ldr-rgb-kodak10.png,39.7100,0.0334,0.0118,33.4198 -Kodak,6x6,ldr-rgb-kodak11.png,37.1255,0.0366,0.0185,21.2045 -Kodak,6x6,ldr-rgb-kodak12.png,40.7229,0.0274,0.0101,39.0359 -Kodak,6x6,ldr-rgb-kodak13.png,32.7806,0.0571,0.0372,10.5714 -Kodak,6x6,ldr-rgb-kodak14.png,35.2350,0.0479,0.0288,13.6699 -Kodak,6x6,ldr-rgb-kodak15.png,38.5238,0.0366,0.0165,23.8069 -Kodak,6x6,ldr-rgb-kodak16.png,40.4988,0.0272,0.0098,40.0911 -Kodak,6x6,ldr-rgb-kodak17.png,38.9257,0.0337,0.0120,32.7463 -Kodak,6x6,ldr-rgb-kodak18.png,35.0961,0.0484,0.0253,15.5687 -Kodak,6x6,ldr-rgb-kodak19.png,37.9622,0.0380,0.0160,24.6328 -Kodak,6x6,ldr-rgb-kodak20.png,39.1651,0.0300,0.0135,29.1056 -Kodak,6x6,ldr-rgb-kodak21.png,36.8830,0.0369,0.0190,20.7184 -Kodak,6x6,ldr-rgb-kodak22.png,36.9688,0.0407,0.0198,19.8105 -Kodak,6x6,ldr-rgb-kodak23.png,40.0315,0.0305,0.0120,32.8690 -Kodak,6x6,ldr-rgb-kodak24.png,34.7652,0.0448,0.0242,16.2432 -Kodak,8x8,ldr-rgb-kodak01.png,31.3198,0.0554,0.0326,12.0438 -Kodak,8x8,ldr-rgb-kodak02.png,34.8859,0.0407,0.0173,22.7122 -Kodak,8x8,ldr-rgb-kodak03.png,36.5587,0.0338,0.0130,30.2963 -Kodak,8x8,ldr-rgb-kodak04.png,35.1631,0.0419,0.0160,24.5635 -Kodak,8x8,ldr-rgb-kodak05.png,30.2290,0.0686,0.0447,8.8055 -Kodak,8x8,ldr-rgb-kodak06.png,32.8875,0.0456,0.0230,17.0629 -Kodak,8x8,ldr-rgb-kodak07.png,34.9574,0.0430,0.0179,21.9920 -Kodak,8x8,ldr-rgb-kodak08.png,29.9727,0.0754,0.0486,8.0913 -Kodak,8x8,ldr-rgb-kodak09.png,36.0644,0.0386,0.0140,28.1090 -Kodak,8x8,ldr-rgb-kodak10.png,35.8574,0.0393,0.0136,28.9279 -Kodak,8x8,ldr-rgb-kodak11.png,32.9724,0.0455,0.0231,17.0511 -Kodak,8x8,ldr-rgb-kodak12.png,36.6491,0.0338,0.0122,32.1069 -Kodak,8x8,ldr-rgb-kodak13.png,28.2115,0.0787,0.0543,7.2382 -Kodak,8x8,ldr-rgb-kodak14.png,31.4868,0.0585,0.0354,11.0977 -Kodak,8x8,ldr-rgb-kodak15.png,34.9071,0.0418,0.0178,22.0573 -Kodak,8x8,ldr-rgb-kodak16.png,36.0183,0.0351,0.0139,28.2259 -Kodak,8x8,ldr-rgb-kodak17.png,34.8533,0.0409,0.0152,25.8170 -Kodak,8x8,ldr-rgb-kodak18.png,31.2426,0.0578,0.0309,12.7250 -Kodak,8x8,ldr-rgb-kodak19.png,34.0758,0.0455,0.0194,20.2792 -Kodak,8x8,ldr-rgb-kodak20.png,35.2054,0.0361,0.0155,25.3348 -Kodak,8x8,ldr-rgb-kodak21.png,32.7363,0.0464,0.0241,16.3336 -Kodak,8x8,ldr-rgb-kodak22.png,33.4351,0.0457,0.0212,18.5724 -Kodak,8x8,ldr-rgb-kodak23.png,36.4996,0.0345,0.0120,32.8337 -Kodak,8x8,ldr-rgb-kodak24.png,30.8082,0.0548,0.0303,12.9765 -Kodak,12x12,ldr-rgb-kodak01.png,27.1019,0.0531,0.0244,16.1406 -Kodak,12x12,ldr-rgb-kodak02.png,31.0998,0.0397,0.0092,42.8103 -Kodak,12x12,ldr-rgb-kodak03.png,32.6801,0.0359,0.0085,46.4465 -Kodak,12x12,ldr-rgb-kodak04.png,31.5605,0.0410,0.0082,47.7260 -Kodak,12x12,ldr-rgb-kodak05.png,25.8046,0.0599,0.0299,13.1361 -Kodak,12x12,ldr-rgb-kodak06.png,28.6329,0.0469,0.0180,21.8417 -Kodak,12x12,ldr-rgb-kodak07.png,30.8575,0.0422,0.0104,37.9552 -Kodak,12x12,ldr-rgb-kodak08.png,25.3858,0.0684,0.0343,11.4653 -Kodak,12x12,ldr-rgb-kodak09.png,31.8332,0.0403,0.0092,42.5233 -Kodak,12x12,ldr-rgb-kodak10.png,31.5261,0.0423,0.0099,39.7749 -Kodak,12x12,ldr-rgb-kodak11.png,28.9305,0.0431,0.0144,27.2498 -Kodak,12x12,ldr-rgb-kodak12.png,32.2648,0.0363,0.0083,47.4214 -Kodak,12x12,ldr-rgb-kodak13.png,24.3204,0.0711,0.0402,9.7812 -Kodak,12x12,ldr-rgb-kodak14.png,27.5269,0.0490,0.0199,19.7657 -Kodak,12x12,ldr-rgb-kodak15.png,31.2436,0.0418,0.0110,35.6144 -Kodak,12x12,ldr-rgb-kodak16.png,31.4839,0.0375,0.0093,42.2586 -Kodak,12x12,ldr-rgb-kodak17.png,30.8893,0.0430,0.0105,37.3425 -Kodak,12x12,ldr-rgb-kodak18.png,27.4177,0.0535,0.0200,19.7092 -Kodak,12x12,ldr-rgb-kodak19.png,30.1727,0.0460,0.0133,29.4680 -Kodak,12x12,ldr-rgb-kodak20.png,31.0405,0.0383,0.0110,35.7821 -Kodak,12x12,ldr-rgb-kodak21.png,28.7196,0.0459,0.0172,22.9014 -Kodak,12x12,ldr-rgb-kodak22.png,29.8238,0.0425,0.0112,35.2438 -Kodak,12x12,ldr-rgb-kodak23.png,32.5185,0.0375,0.0082,48.0304 -Kodak,12x12,ldr-rgb-kodak24.png,26.7652,0.0545,0.0232,16.9286 diff --git a/Test/Images/Kodak/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/Kodak/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index 8623655..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.5072,0.0298,0.0138,28.5647 -Kodak,4x4,ldr-rgb-kodak02.png,43.8025,0.0349,0.0175,22.4926 -Kodak,4x4,ldr-rgb-kodak03.png,46.0406,0.0260,0.0110,35.6691 -Kodak,4x4,ldr-rgb-kodak04.png,44.1429,0.0360,0.0160,24.5179 -Kodak,4x4,ldr-rgb-kodak05.png,40.9879,0.0385,0.0211,18.6394 -Kodak,4x4,ldr-rgb-kodak06.png,44.4296,0.0298,0.0139,28.3887 -Kodak,4x4,ldr-rgb-kodak07.png,44.6051,0.0333,0.0140,28.0326 -Kodak,4x4,ldr-rgb-kodak08.png,41.5000,0.0423,0.0218,18.0159 -Kodak,4x4,ldr-rgb-kodak09.png,45.9005,0.0292,0.0108,36.2540 -Kodak,4x4,ldr-rgb-kodak10.png,45.6663,0.0312,0.0114,34.4049 -Kodak,4x4,ldr-rgb-kodak11.png,43.8292,0.0314,0.0154,25.4627 -Kodak,4x4,ldr-rgb-kodak12.png,46.4729,0.0263,0.0110,35.7759 -Kodak,4x4,ldr-rgb-kodak13.png,41.1509,0.0387,0.0213,18.4391 -Kodak,4x4,ldr-rgb-kodak14.png,41.0931,0.0340,0.0174,22.6194 -Kodak,4x4,ldr-rgb-kodak15.png,44.1027,0.0344,0.0164,24.0176 -Kodak,4x4,ldr-rgb-kodak16.png,47.0422,0.0255,0.0103,38.1757 -Kodak,4x4,ldr-rgb-kodak17.png,45.4973,0.0304,0.0106,36.9874 -Kodak,4x4,ldr-rgb-kodak18.png,41.2449,0.0426,0.0218,17.9978 -Kodak,4x4,ldr-rgb-kodak19.png,44.5301,0.0335,0.0135,29.2289 -Kodak,4x4,ldr-rgb-kodak20.png,45.8602,0.0261,0.0115,34.3268 -Kodak,4x4,ldr-rgb-kodak21.png,44.2614,0.0300,0.0138,28.5850 -Kodak,4x4,ldr-rgb-kodak22.png,42.7742,0.0372,0.0186,21.1770 -Kodak,4x4,ldr-rgb-kodak23.png,45.2565,0.0294,0.0128,30.7561 -Kodak,4x4,ldr-rgb-kodak24.png,41.2205,0.0365,0.0181,21.7487 -Kodak,5x5,ldr-rgb-kodak01.png,39.3652,0.0315,0.0145,27.0327 -Kodak,5x5,ldr-rgb-kodak02.png,40.3762,0.0314,0.0133,29.5118 -Kodak,5x5,ldr-rgb-kodak03.png,42.6004,0.0250,0.0095,41.3869 -Kodak,5x5,ldr-rgb-kodak04.png,40.7711,0.0334,0.0126,31.1853 -Kodak,5x5,ldr-rgb-kodak05.png,36.9823,0.0389,0.0207,18.9527 -Kodak,5x5,ldr-rgb-kodak06.png,40.4008,0.0289,0.0123,32.0053 -Kodak,5x5,ldr-rgb-kodak07.png,41.1154,0.0318,0.0120,32.6698 -Kodak,5x5,ldr-rgb-kodak08.png,37.3666,0.0427,0.0214,18.3814 -Kodak,5x5,ldr-rgb-kodak09.png,42.5422,0.0284,0.0092,42.7271 -Kodak,5x5,ldr-rgb-kodak10.png,42.3455,0.0298,0.0095,41.1874 -Kodak,5x5,ldr-rgb-kodak11.png,40.0401,0.0299,0.0132,29.8138 -Kodak,5x5,ldr-rgb-kodak12.png,43.1448,0.0248,0.0088,44.4463 -Kodak,5x5,ldr-rgb-kodak13.png,36.6876,0.0389,0.0209,18.8169 -Kodak,5x5,ldr-rgb-kodak14.png,37.3962,0.0341,0.0169,23.2203 -Kodak,5x5,ldr-rgb-kodak15.png,40.8535,0.0309,0.0123,31.9353 -Kodak,5x5,ldr-rgb-kodak16.png,43.3795,0.0245,0.0087,44.9907 -Kodak,5x5,ldr-rgb-kodak17.png,41.8560,0.0295,0.0092,42.6255 -Kodak,5x5,ldr-rgb-kodak18.png,37.9129,0.0391,0.0174,22.5661 -Kodak,5x5,ldr-rgb-kodak19.png,40.8503,0.0321,0.0114,34.5172 -Kodak,5x5,ldr-rgb-kodak20.png,42.0160,0.0252,0.0097,40.5504 -Kodak,5x5,ldr-rgb-kodak21.png,40.1806,0.0294,0.0126,31.2746 -Kodak,5x5,ldr-rgb-kodak22.png,39.4506,0.0332,0.0141,27.8461 -Kodak,5x5,ldr-rgb-kodak23.png,42.1119,0.0277,0.0104,37.8715 -Kodak,5x5,ldr-rgb-kodak24.png,37.5517,0.0349,0.0158,24.8635 -Kodak,6x6,ldr-rgb-kodak01.png,35.6562,0.0347,0.0175,22.4311 -Kodak,6x6,ldr-rgb-kodak02.png,38.0339,0.0310,0.0124,31.7161 -Kodak,6x6,ldr-rgb-kodak03.png,40.3032,0.0242,0.0085,46.1566 -Kodak,6x6,ldr-rgb-kodak04.png,38.2918,0.0328,0.0118,33.4083 -Kodak,6x6,ldr-rgb-kodak05.png,34.0896,0.0404,0.0218,18.0077 -Kodak,6x6,ldr-rgb-kodak06.png,37.2222,0.0299,0.0128,30.7848 -Kodak,6x6,ldr-rgb-kodak07.png,38.6336,0.0314,0.0114,34.4804 -Kodak,6x6,ldr-rgb-kodak08.png,34.2253,0.0439,0.0226,17.3911 -Kodak,6x6,ldr-rgb-kodak09.png,39.7573,0.0286,0.0092,42.7692 -Kodak,6x6,ldr-rgb-kodak10.png,39.5669,0.0298,0.0091,43.0922 -Kodak,6x6,ldr-rgb-kodak11.png,36.9968,0.0303,0.0134,29.2377 -Kodak,6x6,ldr-rgb-kodak12.png,40.5658,0.0245,0.0083,47.3696 -Kodak,6x6,ldr-rgb-kodak13.png,32.7154,0.0436,0.0252,15.6323 -Kodak,6x6,ldr-rgb-kodak14.png,34.8624,0.0351,0.0176,22.3596 -Kodak,6x6,ldr-rgb-kodak15.png,38.3699,0.0309,0.0120,32.6834 -Kodak,6x6,ldr-rgb-kodak16.png,40.4581,0.0246,0.0083,47.0977 -Kodak,6x6,ldr-rgb-kodak17.png,38.8420,0.0302,0.0095,41.2647 -Kodak,6x6,ldr-rgb-kodak18.png,35.0034,0.0397,0.0178,22.1007 -Kodak,6x6,ldr-rgb-kodak19.png,37.8298,0.0332,0.0123,31.9564 -Kodak,6x6,ldr-rgb-kodak20.png,39.0123,0.0257,0.0100,39.2786 -Kodak,6x6,ldr-rgb-kodak21.png,36.8075,0.0308,0.0139,28.3131 -Kodak,6x6,ldr-rgb-kodak22.png,36.8498,0.0337,0.0141,27.9295 -Kodak,6x6,ldr-rgb-kodak23.png,39.8307,0.0267,0.0093,42.4314 -Kodak,6x6,ldr-rgb-kodak24.png,34.6916,0.0362,0.0166,23.6964 -Kodak,8x8,ldr-rgb-kodak01.png,31.1792,0.0449,0.0241,16.2883 -Kodak,8x8,ldr-rgb-kodak02.png,34.7811,0.0351,0.0134,29.3840 -Kodak,8x8,ldr-rgb-kodak03.png,36.4262,0.0293,0.0103,38.3399 -Kodak,8x8,ldr-rgb-kodak04.png,35.0547,0.0370,0.0126,31.2349 -Kodak,8x8,ldr-rgb-kodak05.png,30.0205,0.0516,0.0298,13.2014 -Kodak,8x8,ldr-rgb-kodak06.png,32.7989,0.0381,0.0177,22.1631 -Kodak,8x8,ldr-rgb-kodak07.png,34.8360,0.0373,0.0137,28.6137 -Kodak,8x8,ldr-rgb-kodak08.png,29.7069,0.0569,0.0319,12.3153 -Kodak,8x8,ldr-rgb-kodak09.png,35.8914,0.0340,0.0108,36.3892 -Kodak,8x8,ldr-rgb-kodak10.png,35.7051,0.0347,0.0106,36.9807 -Kodak,8x8,ldr-rgb-kodak11.png,32.8451,0.0373,0.0169,23.2465 -Kodak,8x8,ldr-rgb-kodak12.png,36.5111,0.0297,0.0101,39.1109 -Kodak,8x8,ldr-rgb-kodak13.png,28.1364,0.0592,0.0369,10.6626 -Kodak,8x8,ldr-rgb-kodak14.png,31.2591,0.0447,0.0232,16.9307 -Kodak,8x8,ldr-rgb-kodak15.png,34.7599,0.0357,0.0133,29.5007 -Kodak,8x8,ldr-rgb-kodak16.png,35.9616,0.0310,0.0113,34.8196 -Kodak,8x8,ldr-rgb-kodak17.png,34.7164,0.0360,0.0119,32.9603 -Kodak,8x8,ldr-rgb-kodak18.png,31.1666,0.0474,0.0223,17.6464 -Kodak,8x8,ldr-rgb-kodak19.png,33.8904,0.0392,0.0148,26.5758 -Kodak,8x8,ldr-rgb-kodak20.png,35.0191,0.0310,0.0119,33.0932 -Kodak,8x8,ldr-rgb-kodak21.png,32.6198,0.0379,0.0177,22.2294 -Kodak,8x8,ldr-rgb-kodak22.png,33.3242,0.0388,0.0159,24.7947 -Kodak,8x8,ldr-rgb-kodak23.png,36.3894,0.0305,0.0096,40.9045 -Kodak,8x8,ldr-rgb-kodak24.png,30.7268,0.0444,0.0215,18.2500 -Kodak,12x12,ldr-rgb-kodak01.png,26.9930,0.0436,0.0184,21.3183 -Kodak,12x12,ldr-rgb-kodak02.png,31.0354,0.0340,0.0081,48.3770 -Kodak,12x12,ldr-rgb-kodak03.png,32.6215,0.0305,0.0072,54.9811 -Kodak,12x12,ldr-rgb-kodak04.png,31.4774,0.0358,0.0072,54.9499 -Kodak,12x12,ldr-rgb-kodak05.png,25.6941,0.0479,0.0218,18.0449 -Kodak,12x12,ldr-rgb-kodak06.png,28.4895,0.0387,0.0142,27.7594 -Kodak,12x12,ldr-rgb-kodak07.png,30.8016,0.0362,0.0085,46.3316 -Kodak,12x12,ldr-rgb-kodak08.png,25.2157,0.0542,0.0255,15.4058 -Kodak,12x12,ldr-rgb-kodak09.png,31.6339,0.0348,0.0078,50.4641 -Kodak,12x12,ldr-rgb-kodak10.png,31.4567,0.0364,0.0082,47.6915 -Kodak,12x12,ldr-rgb-kodak11.png,28.8572,0.0360,0.0114,34.5563 -Kodak,12x12,ldr-rgb-kodak12.png,32.1857,0.0307,0.0072,54.9335 -Kodak,12x12,ldr-rgb-kodak13.png,24.2396,0.0550,0.0290,13.5396 -Kodak,12x12,ldr-rgb-kodak14.png,27.4380,0.0403,0.0150,26.1481 -Kodak,12x12,ldr-rgb-kodak15.png,31.1533,0.0357,0.0092,42.8849 -Kodak,12x12,ldr-rgb-kodak16.png,31.3620,0.0318,0.0080,48.9615 -Kodak,12x12,ldr-rgb-kodak17.png,30.8364,0.0369,0.0085,46.1256 -Kodak,12x12,ldr-rgb-kodak18.png,27.3672,0.0444,0.0146,26.9567 -Kodak,12x12,ldr-rgb-kodak19.png,29.8648,0.0395,0.0108,36.3315 -Kodak,12x12,ldr-rgb-kodak20.png,30.9381,0.0322,0.0090,43.5025 -Kodak,12x12,ldr-rgb-kodak21.png,28.6166,0.0380,0.0133,29.6407 -Kodak,12x12,ldr-rgb-kodak22.png,29.7245,0.0364,0.0092,42.9184 -Kodak,12x12,ldr-rgb-kodak23.png,32.4842,0.0324,0.0073,53.8941 -Kodak,12x12,ldr-rgb-kodak24.png,26.6937,0.0440,0.0170,23.1058 diff --git a/Test/Images/Kodak/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/Kodak/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index fae29ae..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.2910,0.1174,0.0994,3.9546 -Kodak,4x4,ldr-rgb-kodak02.png,45.3499,0.1594,0.1401,2.8069 -Kodak,4x4,ldr-rgb-kodak03.png,47.6132,0.0850,0.0686,5.7358 -Kodak,4x4,ldr-rgb-kodak04.png,45.4289,0.1290,0.1074,3.6614 -Kodak,4x4,ldr-rgb-kodak05.png,42.1296,0.1474,0.1284,3.0632 -Kodak,4x4,ldr-rgb-kodak06.png,45.1555,0.1114,0.0934,4.2107 -Kodak,4x4,ldr-rgb-kodak07.png,45.9745,0.1090,0.0879,4.4748 -Kodak,4x4,ldr-rgb-kodak08.png,42.5130,0.1643,0.1419,2.7712 -Kodak,4x4,ldr-rgb-kodak09.png,47.1616,0.1273,0.1069,3.6783 -Kodak,4x4,ldr-rgb-kodak10.png,46.8287,0.1315,0.1102,3.5698 -Kodak,4x4,ldr-rgb-kodak11.png,44.8668,0.1277,0.1097,3.5859 -Kodak,4x4,ldr-rgb-kodak12.png,47.9301,0.0961,0.0793,4.9613 -Kodak,4x4,ldr-rgb-kodak13.png,41.6152,0.1264,0.1072,3.6670 -Kodak,4x4,ldr-rgb-kodak14.png,42.6269,0.1365,0.1180,3.3331 -Kodak,4x4,ldr-rgb-kodak15.png,45.4386,0.1138,0.0938,4.1910 -Kodak,4x4,ldr-rgb-kodak16.png,47.8565,0.0981,0.0810,4.8534 -Kodak,4x4,ldr-rgb-kodak17.png,46.2901,0.1139,0.0924,4.2554 -Kodak,4x4,ldr-rgb-kodak18.png,41.9927,0.1670,0.1441,2.7278 -Kodak,4x4,ldr-rgb-kodak19.png,45.3392,0.1356,0.1135,3.4631 -Kodak,4x4,ldr-rgb-kodak20.png,46.8869,0.0832,0.0670,5.8712 -Kodak,4x4,ldr-rgb-kodak21.png,45.1510,0.1344,0.1166,3.3719 -Kodak,4x4,ldr-rgb-kodak22.png,43.7746,0.1666,0.1460,2.6931 -Kodak,4x4,ldr-rgb-kodak23.png,46.8184,0.1284,0.1102,3.5681 -Kodak,4x4,ldr-rgb-kodak24.png,42.2960,0.1333,0.1130,3.4806 -Kodak,5x5,ldr-rgb-kodak01.png,40.1121,0.1325,0.1129,3.4826 -Kodak,5x5,ldr-rgb-kodak02.png,41.6953,0.1416,0.1210,3.2506 -Kodak,5x5,ldr-rgb-kodak03.png,44.0360,0.0692,0.0513,7.6680 -Kodak,5x5,ldr-rgb-kodak04.png,42.0560,0.1135,0.0899,4.3716 -Kodak,5x5,ldr-rgb-kodak05.png,37.9816,0.1537,0.1331,2.9535 -Kodak,5x5,ldr-rgb-kodak06.png,40.9586,0.1067,0.0874,4.4972 -Kodak,5x5,ldr-rgb-kodak07.png,42.4607,0.0937,0.0710,5.5383 -Kodak,5x5,ldr-rgb-kodak08.png,38.3486,0.1678,0.1440,2.7302 -Kodak,5x5,ldr-rgb-kodak09.png,43.8038,0.0812,0.0592,6.6419 -Kodak,5x5,ldr-rgb-kodak10.png,43.4092,0.0916,0.0684,5.7500 -Kodak,5x5,ldr-rgb-kodak11.png,40.8377,0.1217,0.1023,3.8423 -Kodak,5x5,ldr-rgb-kodak12.png,44.3921,0.0702,0.0515,7.6329 -Kodak,5x5,ldr-rgb-kodak13.png,36.9078,0.1403,0.1192,3.2992 -Kodak,5x5,ldr-rgb-kodak14.png,38.6484,0.1374,0.1174,3.3493 -Kodak,5x5,ldr-rgb-kodak15.png,41.8912,0.1062,0.0847,4.6400 -Kodak,5x5,ldr-rgb-kodak16.png,44.1367,0.0767,0.0582,6.7603 -Kodak,5x5,ldr-rgb-kodak17.png,42.5213,0.0824,0.0589,6.6757 -Kodak,5x5,ldr-rgb-kodak18.png,38.3607,0.1511,0.1269,3.0998 -Kodak,5x5,ldr-rgb-kodak19.png,41.6469,0.1051,0.0818,4.8076 -Kodak,5x5,ldr-rgb-kodak20.png,42.9685,0.0753,0.0573,6.8682 -Kodak,5x5,ldr-rgb-kodak21.png,40.7620,0.1054,0.0859,4.5800 -Kodak,5x5,ldr-rgb-kodak22.png,40.2773,0.1440,0.1222,3.2171 -Kodak,5x5,ldr-rgb-kodak23.png,43.5488,0.0919,0.0723,5.4415 -Kodak,5x5,ldr-rgb-kodak24.png,38.1152,0.1239,0.1022,3.8465 -Kodak,6x6,ldr-rgb-kodak01.png,36.1951,0.1344,0.1142,3.4435 -Kodak,6x6,ldr-rgb-kodak02.png,39.0094,0.1106,0.0894,4.3989 -Kodak,6x6,ldr-rgb-kodak03.png,41.3262,0.0585,0.0398,9.8729 -Kodak,6x6,ldr-rgb-kodak04.png,39.3983,0.0968,0.0727,5.4106 -Kodak,6x6,ldr-rgb-kodak05.png,34.7867,0.1477,0.1264,3.1107 -Kodak,6x6,ldr-rgb-kodak06.png,37.6289,0.0939,0.0739,5.3213 -Kodak,6x6,ldr-rgb-kodak07.png,39.7726,0.0800,0.0570,6.9014 -Kodak,6x6,ldr-rgb-kodak08.png,34.9978,0.1644,0.1393,2.8238 -Kodak,6x6,ldr-rgb-kodak09.png,40.8821,0.0638,0.0414,9.5074 -Kodak,6x6,ldr-rgb-kodak10.png,40.5030,0.0678,0.0445,8.8379 -Kodak,6x6,ldr-rgb-kodak11.png,37.5798,0.1003,0.0805,4.8833 -Kodak,6x6,ldr-rgb-kodak12.png,41.4837,0.0554,0.0363,10.8190 -Kodak,6x6,ldr-rgb-kodak13.png,32.8829,0.1521,0.1307,3.0095 -Kodak,6x6,ldr-rgb-kodak14.png,35.8236,0.1244,0.1038,3.7896 -Kodak,6x6,ldr-rgb-kodak15.png,39.1953,0.0973,0.0756,5.2042 -Kodak,6x6,ldr-rgb-kodak16.png,41.0408,0.0629,0.0439,8.9497 -Kodak,6x6,ldr-rgb-kodak17.png,39.4928,0.0684,0.0448,8.7789 -Kodak,6x6,ldr-rgb-kodak18.png,35.3481,0.1332,0.1082,3.6338 -Kodak,6x6,ldr-rgb-kodak19.png,38.5316,0.0947,0.0707,5.5611 -Kodak,6x6,ldr-rgb-kodak20.png,39.7651,0.0694,0.0509,7.7313 -Kodak,6x6,ldr-rgb-kodak21.png,37.1926,0.0921,0.0721,5.4528 -Kodak,6x6,ldr-rgb-kodak22.png,37.4532,0.1203,0.0978,4.0207 -Kodak,6x6,ldr-rgb-kodak23.png,40.9705,0.0676,0.0471,8.3438 -Kodak,6x6,ldr-rgb-kodak24.png,35.0426,0.1099,0.0876,4.4912 -Kodak,8x8,ldr-rgb-kodak01.png,31.8012,0.1770,0.1531,2.5677 -Kodak,8x8,ldr-rgb-kodak02.png,35.7606,0.1071,0.0824,4.7745 -Kodak,8x8,ldr-rgb-kodak03.png,37.7459,0.0699,0.0478,8.2326 -Kodak,8x8,ldr-rgb-kodak04.png,36.0605,0.1055,0.0776,5.0656 -Kodak,8x8,ldr-rgb-kodak05.png,30.7416,0.1844,0.1595,2.4658 -Kodak,8x8,ldr-rgb-kodak06.png,33.4352,0.1170,0.0932,4.2212 -Kodak,8x8,ldr-rgb-kodak07.png,36.1304,0.0921,0.0652,6.0296 -Kodak,8x8,ldr-rgb-kodak08.png,30.5708,0.1872,0.1590,2.4732 -Kodak,8x8,ldr-rgb-kodak09.png,37.2646,0.0727,0.0467,8.4227 -Kodak,8x8,ldr-rgb-kodak10.png,36.9159,0.0751,0.0479,8.2012 -Kodak,8x8,ldr-rgb-kodak11.png,33.6569,0.1163,0.0923,4.2580 -Kodak,8x8,ldr-rgb-kodak12.png,37.8259,0.0670,0.0443,8.8830 -Kodak,8x8,ldr-rgb-kodak13.png,28.3927,0.2040,0.1789,2.1978 -Kodak,8x8,ldr-rgb-kodak14.png,32.1340,0.1491,0.1252,3.1416 -Kodak,8x8,ldr-rgb-kodak15.png,35.8359,0.0976,0.0720,5.4579 -Kodak,8x8,ldr-rgb-kodak16.png,37.0213,0.0771,0.0543,7.2435 -Kodak,8x8,ldr-rgb-kodak17.png,35.6807,0.0826,0.0552,7.1188 -Kodak,8x8,ldr-rgb-kodak18.png,31.5529,0.1503,0.1214,3.2391 -Kodak,8x8,ldr-rgb-kodak19.png,34.7649,0.1117,0.0836,4.7048 -Kodak,8x8,ldr-rgb-kodak20.png,35.8945,0.0842,0.0621,6.3292 -Kodak,8x8,ldr-rgb-kodak21.png,33.1150,0.1156,0.0916,4.2912 -Kodak,8x8,ldr-rgb-kodak22.png,34.0244,0.1268,0.1004,3.9148 -Kodak,8x8,ldr-rgb-kodak23.png,37.6470,0.0687,0.0447,8.8007 -Kodak,8x8,ldr-rgb-kodak24.png,31.1140,0.1304,0.1044,3.7653 -Kodak,12x12,ldr-rgb-kodak01.png,27.7578,0.1938,0.1613,2.4379 -Kodak,12x12,ldr-rgb-kodak02.png,32.4621,0.0836,0.0501,7.8431 -Kodak,12x12,ldr-rgb-kodak03.png,33.7766,0.0687,0.0381,10.3168 -Kodak,12x12,ldr-rgb-kodak04.png,32.4443,0.0801,0.0443,8.8842 -Kodak,12x12,ldr-rgb-kodak05.png,26.3986,0.2061,0.1731,2.2719 -Kodak,12x12,ldr-rgb-kodak06.png,29.3737,0.1269,0.0949,4.1453 -Kodak,12x12,ldr-rgb-kodak07.png,32.0414,0.0946,0.0594,6.6192 -Kodak,12x12,ldr-rgb-kodak08.png,26.0600,0.2085,0.1721,2.2846 -Kodak,12x12,ldr-rgb-kodak09.png,33.0989,0.0729,0.0386,10.1986 -Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0753,0.0395,9.9463 -Kodak,12x12,ldr-rgb-kodak11.png,29.7433,0.1145,0.0823,4.7767 -Kodak,12x12,ldr-rgb-kodak12.png,33.8819,0.0658,0.0347,11.3306 -Kodak,12x12,ldr-rgb-kodak13.png,24.5282,0.2346,0.2010,1.9561 -Kodak,12x12,ldr-rgb-kodak14.png,28.4176,0.1516,0.1191,3.3017 -Kodak,12x12,ldr-rgb-kodak15.png,32.2342,0.0908,0.0569,6.9104 -Kodak,12x12,ldr-rgb-kodak16.png,32.9807,0.0722,0.0410,9.5958 -Kodak,12x12,ldr-rgb-kodak17.png,31.7805,0.0804,0.0446,8.8068 -Kodak,12x12,ldr-rgb-kodak18.png,27.7783,0.1501,0.1134,3.4671 -Kodak,12x12,ldr-rgb-kodak19.png,30.8882,0.1004,0.0644,6.1055 -Kodak,12x12,ldr-rgb-kodak20.png,31.8562,0.0781,0.0478,8.2278 -Kodak,12x12,ldr-rgb-kodak21.png,29.1771,0.1353,0.1033,3.8072 -Kodak,12x12,ldr-rgb-kodak22.png,30.4983,0.1091,0.0745,5.2800 -Kodak,12x12,ldr-rgb-kodak23.png,33.5464,0.0638,0.0316,12.4613 -Kodak,12x12,ldr-rgb-kodak24.png,27.0976,0.1355,0.1013,3.8835 diff --git a/Test/Images/Kodak/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/Kodak/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index bdb66b4..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.4944,0.3071,0.2885,1.3632 -Kodak,4x4,ldr-rgb-kodak02.png,45.6493,0.3620,0.3425,1.1481 -Kodak,4x4,ldr-rgb-kodak03.png,47.9884,0.3118,0.2948,1.3340 -Kodak,4x4,ldr-rgb-kodak04.png,45.6562,0.3425,0.3206,1.2266 -Kodak,4x4,ldr-rgb-kodak05.png,42.4063,0.3390,0.3199,1.2291 -Kodak,4x4,ldr-rgb-kodak06.png,45.3572,0.3047,0.2867,1.3713 -Kodak,4x4,ldr-rgb-kodak07.png,46.3419,0.3395,0.3177,1.2379 -Kodak,4x4,ldr-rgb-kodak08.png,42.8054,0.3640,0.3414,1.1519 -Kodak,4x4,ldr-rgb-kodak09.png,47.4208,0.3462,0.3254,1.2086 -Kodak,4x4,ldr-rgb-kodak10.png,47.0603,0.3450,0.3228,1.2183 -Kodak,4x4,ldr-rgb-kodak11.png,45.1121,0.3204,0.3026,1.2993 -Kodak,4x4,ldr-rgb-kodak12.png,48.2457,0.3182,0.3006,1.3080 -Kodak,4x4,ldr-rgb-kodak13.png,41.7174,0.3100,0.2907,1.3526 -Kodak,4x4,ldr-rgb-kodak14.png,42.9405,0.3301,0.3112,1.2635 -Kodak,4x4,ldr-rgb-kodak15.png,45.7858,0.3280,0.3077,1.2778 -Kodak,4x4,ldr-rgb-kodak16.png,48.0652,0.3160,0.2990,1.3151 -Kodak,4x4,ldr-rgb-kodak17.png,46.4610,0.3321,0.3106,1.2662 -Kodak,4x4,ldr-rgb-kodak18.png,42.1541,0.3619,0.3389,1.1603 -Kodak,4x4,ldr-rgb-kodak19.png,45.5439,0.3459,0.3240,1.2137 -Kodak,4x4,ldr-rgb-kodak20.png,47.1284,0.2186,0.2017,1.9495 -Kodak,4x4,ldr-rgb-kodak21.png,45.3018,0.3346,0.3166,1.2420 -Kodak,4x4,ldr-rgb-kodak22.png,43.9797,0.3679,0.3472,1.1324 -Kodak,4x4,ldr-rgb-kodak23.png,47.1533,0.3552,0.3368,1.1676 -Kodak,4x4,ldr-rgb-kodak24.png,42.5030,0.3316,0.3113,1.2630 -Kodak,5x5,ldr-rgb-kodak01.png,40.2326,0.3683,0.3481,1.1296 -Kodak,5x5,ldr-rgb-kodak02.png,41.9976,0.4272,0.4062,0.9681 -Kodak,5x5,ldr-rgb-kodak03.png,44.3239,0.3514,0.3329,1.1811 -Kodak,5x5,ldr-rgb-kodak04.png,42.2394,0.3900,0.3660,1.0744 -Kodak,5x5,ldr-rgb-kodak05.png,38.1756,0.4025,0.3820,1.0295 -Kodak,5x5,ldr-rgb-kodak06.png,41.0844,0.3501,0.3307,1.1890 -Kodak,5x5,ldr-rgb-kodak07.png,42.7249,0.3847,0.3619,1.0865 -Kodak,5x5,ldr-rgb-kodak08.png,38.5334,0.4128,0.3883,1.0126 -Kodak,5x5,ldr-rgb-kodak09.png,44.0288,0.3855,0.3632,1.0825 -Kodak,5x5,ldr-rgb-kodak10.png,43.5935,0.3918,0.3686,1.0669 -Kodak,5x5,ldr-rgb-kodak11.png,40.9987,0.3654,0.3462,1.1358 -Kodak,5x5,ldr-rgb-kodak12.png,44.5960,0.3597,0.3406,1.1544 -Kodak,5x5,ldr-rgb-kodak13.png,36.9510,0.3601,0.3392,1.1593 -Kodak,5x5,ldr-rgb-kodak14.png,38.8797,0.3856,0.3658,1.0751 -Kodak,5x5,ldr-rgb-kodak15.png,42.1246,0.3693,0.3474,1.1320 -Kodak,5x5,ldr-rgb-kodak16.png,44.2686,0.3576,0.3390,1.1600 -Kodak,5x5,ldr-rgb-kodak17.png,42.6009,0.3782,0.3549,1.1081 -Kodak,5x5,ldr-rgb-kodak18.png,38.4550,0.4186,0.3942,0.9975 -Kodak,5x5,ldr-rgb-kodak19.png,41.7719,0.3997,0.3761,1.0456 -Kodak,5x5,ldr-rgb-kodak20.png,43.2708,0.2539,0.2360,1.6660 -Kodak,5x5,ldr-rgb-kodak21.png,40.8630,0.3955,0.3760,1.0457 -Kodak,5x5,ldr-rgb-kodak22.png,40.4255,0.4260,0.4035,0.9744 -Kodak,5x5,ldr-rgb-kodak23.png,43.8841,0.4162,0.3965,0.9917 -Kodak,5x5,ldr-rgb-kodak24.png,38.2272,0.3812,0.3588,1.0958 -Kodak,6x6,ldr-rgb-kodak01.png,36.3116,0.4253,0.4049,0.9711 -Kodak,6x6,ldr-rgb-kodak02.png,39.3780,0.4874,0.4656,0.8444 -Kodak,6x6,ldr-rgb-kodak03.png,41.7331,0.3027,0.2838,1.3855 -Kodak,6x6,ldr-rgb-kodak04.png,39.6521,0.4248,0.4004,0.9822 -Kodak,6x6,ldr-rgb-kodak05.png,34.9741,0.4598,0.4384,0.8970 -Kodak,6x6,ldr-rgb-kodak06.png,37.7401,0.3812,0.3610,1.0893 -Kodak,6x6,ldr-rgb-kodak07.png,40.1032,0.3498,0.3260,1.2063 -Kodak,6x6,ldr-rgb-kodak08.png,35.1660,0.4647,0.4397,0.8942 -Kodak,6x6,ldr-rgb-kodak09.png,41.2613,0.4253,0.4030,0.9758 -Kodak,6x6,ldr-rgb-kodak10.png,40.8141,0.4333,0.4094,0.9604 -Kodak,6x6,ldr-rgb-kodak11.png,37.7541,0.3923,0.3722,1.0565 -Kodak,6x6,ldr-rgb-kodak12.png,41.8249,0.3665,0.3470,1.1333 -Kodak,6x6,ldr-rgb-kodak13.png,32.9256,0.4290,0.4073,0.9653 -Kodak,6x6,ldr-rgb-kodak14.png,36.0210,0.4456,0.4247,0.9259 -Kodak,6x6,ldr-rgb-kodak15.png,39.4514,0.3630,0.3405,1.1547 -Kodak,6x6,ldr-rgb-kodak16.png,41.2290,0.3540,0.3349,1.1740 -Kodak,6x6,ldr-rgb-kodak17.png,39.6521,0.4072,0.3837,1.0248 -Kodak,6x6,ldr-rgb-kodak18.png,35.4328,0.4882,0.4629,0.8494 -Kodak,6x6,ldr-rgb-kodak19.png,38.6954,0.4585,0.4343,0.9054 -Kodak,6x6,ldr-rgb-kodak20.png,40.0953,0.2829,0.2642,1.4886 -Kodak,6x6,ldr-rgb-kodak21.png,37.3344,0.4522,0.4314,0.9115 -Kodak,6x6,ldr-rgb-kodak22.png,37.6231,0.4924,0.4696,0.8374 -Kodak,6x6,ldr-rgb-kodak23.png,41.4033,0.4221,0.4015,0.9794 -Kodak,6x6,ldr-rgb-kodak24.png,35.1417,0.4048,0.3816,1.0303 -Kodak,8x8,ldr-rgb-kodak01.png,31.9071,0.5014,0.4760,0.8260 -Kodak,8x8,ldr-rgb-kodak02.png,36.1354,0.4438,0.4173,0.9423 -Kodak,8x8,ldr-rgb-kodak03.png,38.1744,0.2366,0.2124,1.8515 -Kodak,8x8,ldr-rgb-kodak04.png,36.3637,0.3795,0.3504,1.1222 -Kodak,8x8,ldr-rgb-kodak05.png,30.9009,0.5102,0.4837,0.8129 -Kodak,8x8,ldr-rgb-kodak06.png,33.5749,0.4135,0.3886,1.0119 -Kodak,8x8,ldr-rgb-kodak07.png,36.4888,0.2852,0.2569,1.5305 -Kodak,8x8,ldr-rgb-kodak08.png,30.7484,0.5461,0.5166,0.7612 -Kodak,8x8,ldr-rgb-kodak09.png,37.5499,0.2655,0.2376,1.6552 -Kodak,8x8,ldr-rgb-kodak10.png,37.2288,0.2978,0.2686,1.4639 -Kodak,8x8,ldr-rgb-kodak11.png,33.8276,0.4467,0.4214,0.9331 -Kodak,8x8,ldr-rgb-kodak12.png,38.2490,0.2786,0.2544,1.5456 -Kodak,8x8,ldr-rgb-kodak13.png,28.4502,0.5532,0.5267,0.7465 -Kodak,8x8,ldr-rgb-kodak14.png,32.3258,0.5107,0.4851,0.8105 -Kodak,8x8,ldr-rgb-kodak15.png,36.0605,0.3476,0.3207,1.2261 -Kodak,8x8,ldr-rgb-kodak16.png,37.2636,0.3277,0.3031,1.2973 -Kodak,8x8,ldr-rgb-kodak17.png,35.8722,0.3226,0.2936,1.3394 -Kodak,8x8,ldr-rgb-kodak18.png,31.6495,0.5213,0.4908,0.8012 -Kodak,8x8,ldr-rgb-kodak19.png,34.9142,0.3550,0.3261,1.2060 -Kodak,8x8,ldr-rgb-kodak20.png,36.1470,0.2724,0.2490,1.5792 -Kodak,8x8,ldr-rgb-kodak21.png,33.2221,0.3637,0.3384,1.1619 -Kodak,8x8,ldr-rgb-kodak22.png,34.2197,0.4615,0.4336,0.9068 -Kodak,8x8,ldr-rgb-kodak23.png,38.1768,0.2633,0.2377,1.6541 -Kodak,8x8,ldr-rgb-kodak24.png,31.2175,0.4210,0.3931,1.0004 -Kodak,12x12,ldr-rgb-kodak01.png,27.9058,0.5787,0.5435,0.7235 -Kodak,12x12,ldr-rgb-kodak02.png,32.9642,0.3910,0.3547,1.1085 -Kodak,12x12,ldr-rgb-kodak03.png,34.4219,0.2410,0.2068,1.9018 -Kodak,12x12,ldr-rgb-kodak04.png,32.9599,0.3496,0.3106,1.2660 -Kodak,12x12,ldr-rgb-kodak05.png,26.5927,0.6081,0.5713,0.6883 -Kodak,12x12,ldr-rgb-kodak06.png,29.5304,0.4335,0.3985,0.9868 -Kodak,12x12,ldr-rgb-kodak07.png,32.6109,0.2937,0.2558,1.5371 -Kodak,12x12,ldr-rgb-kodak08.png,26.2744,0.5969,0.5574,0.7055 -Kodak,12x12,ldr-rgb-kodak09.png,33.6251,0.2653,0.2278,1.7265 -Kodak,12x12,ldr-rgb-kodak10.png,32.9833,0.2631,0.2245,1.7519 -Kodak,12x12,ldr-rgb-kodak11.png,30.0468,0.4287,0.3930,1.0005 -Kodak,12x12,ldr-rgb-kodak12.png,34.4395,0.2355,0.2012,1.9540 -Kodak,12x12,ldr-rgb-kodak13.png,24.5820,0.6810,0.6443,0.6103 -Kodak,12x12,ldr-rgb-kodak14.png,28.6287,0.5464,0.5106,0.7701 -Kodak,12x12,ldr-rgb-kodak15.png,32.7197,0.3364,0.2995,1.3131 -Kodak,12x12,ldr-rgb-kodak16.png,33.3355,0.3194,0.2853,1.3784 -Kodak,12x12,ldr-rgb-kodak17.png,32.1409,0.2951,0.2561,1.5355 -Kodak,12x12,ldr-rgb-kodak18.png,27.9217,0.5240,0.4838,0.8127 -Kodak,12x12,ldr-rgb-kodak19.png,31.1006,0.4176,0.3786,1.0387 -Kodak,12x12,ldr-rgb-kodak20.png,32.1470,0.3093,0.2756,1.4266 -Kodak,12x12,ldr-rgb-kodak21.png,29.3170,0.3950,0.3604,1.0911 -Kodak,12x12,ldr-rgb-kodak22.png,30.7805,0.4519,0.4144,0.9490 -Kodak,12x12,ldr-rgb-kodak23.png,34.3635,0.2249,0.1894,2.0761 -Kodak,12x12,ldr-rgb-kodak24.png,27.2253,0.4728,0.4354,0.9032 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index bc18ecd..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.8489,0.0410,0.0236,16.6722 -Kodak,4x4,ldr-rgb-kodak02.png,44.2380,0.0519,0.0328,11.9748 -Kodak,4x4,ldr-rgb-kodak03.png,46.6338,0.0357,0.0196,20.0458 -Kodak,4x4,ldr-rgb-kodak04.png,44.5665,0.0508,0.0296,13.2753 -Kodak,4x4,ldr-rgb-kodak05.png,41.5682,0.0622,0.0432,9.1079 -Kodak,4x4,ldr-rgb-kodak06.png,44.7452,0.0409,0.0233,16.8473 -Kodak,4x4,ldr-rgb-kodak07.png,45.0418,0.0467,0.0260,15.1260 -Kodak,4x4,ldr-rgb-kodak08.png,42.0821,0.0672,0.0451,8.7126 -Kodak,4x4,ldr-rgb-kodak09.png,46.2551,0.0381,0.0181,21.7235 -Kodak,4x4,ldr-rgb-kodak10.png,46.0288,0.0399,0.0192,20.5089 -Kodak,4x4,ldr-rgb-kodak11.png,44.2450,0.0453,0.0280,14.0269 -Kodak,4x4,ldr-rgb-kodak12.png,47.0135,0.0348,0.0179,21.9440 -Kodak,4x4,ldr-rgb-kodak13.png,41.4309,0.0577,0.0386,10.1864 -Kodak,4x4,ldr-rgb-kodak14.png,41.8065,0.0541,0.0356,11.0323 -Kodak,4x4,ldr-rgb-kodak15.png,44.5942,0.0511,0.0317,12.3859 -Kodak,4x4,ldr-rgb-kodak16.png,47.1801,0.0328,0.0161,24.4311 -Kodak,4x4,ldr-rgb-kodak17.png,45.7548,0.0383,0.0173,22.7147 -Kodak,4x4,ldr-rgb-kodak18.png,41.6128,0.0655,0.0429,9.1606 -Kodak,4x4,ldr-rgb-kodak19.png,44.8023,0.0444,0.0229,17.1845 -Kodak,4x4,ldr-rgb-kodak20.png,46.3894,0.0364,0.0202,19.4468 -Kodak,4x4,ldr-rgb-kodak21.png,44.5781,0.0419,0.0240,16.3909 -Kodak,4x4,ldr-rgb-kodak22.png,43.1599,0.0561,0.0360,10.9306 -Kodak,4x4,ldr-rgb-kodak23.png,45.5706,0.0411,0.0231,17.0275 -Kodak,4x4,ldr-rgb-kodak24.png,41.8541,0.0555,0.0356,11.0562 -Kodak,5x5,ldr-rgb-kodak01.png,39.6106,0.0423,0.0235,16.7398 -Kodak,5x5,ldr-rgb-kodak02.png,40.6312,0.0422,0.0221,17.7936 -Kodak,5x5,ldr-rgb-kodak03.png,43.0303,0.0327,0.0156,25.2209 -Kodak,5x5,ldr-rgb-kodak04.png,41.2378,0.0435,0.0209,18.7784 -Kodak,5x5,ldr-rgb-kodak05.png,37.4134,0.0601,0.0399,9.8531 -Kodak,5x5,ldr-rgb-kodak06.png,40.5758,0.0381,0.0194,20.2722 -Kodak,5x5,ldr-rgb-kodak07.png,41.4746,0.0411,0.0199,19.8082 -Kodak,5x5,ldr-rgb-kodak08.png,37.7544,0.0640,0.0410,9.5885 -Kodak,5x5,ldr-rgb-kodak09.png,42.9020,0.0350,0.0141,27.9651 -Kodak,5x5,ldr-rgb-kodak10.png,42.6178,0.0366,0.0149,26.4048 -Kodak,5x5,ldr-rgb-kodak11.png,40.2886,0.0405,0.0219,17.9953 -Kodak,5x5,ldr-rgb-kodak12.png,43.4048,0.0309,0.0133,29.5875 -Kodak,5x5,ldr-rgb-kodak13.png,36.8038,0.0567,0.0363,10.8178 -Kodak,5x5,ldr-rgb-kodak14.png,37.9374,0.0537,0.0343,11.4670 -Kodak,5x5,ldr-rgb-kodak15.png,41.1606,0.0420,0.0215,18.2475 -Kodak,5x5,ldr-rgb-kodak16.png,43.4729,0.0301,0.0121,32.5428 -Kodak,5x5,ldr-rgb-kodak17.png,42.0129,0.0357,0.0140,28.0626 -Kodak,5x5,ldr-rgb-kodak18.png,38.0842,0.0549,0.0313,12.5657 -Kodak,5x5,ldr-rgb-kodak19.png,41.1186,0.0394,0.0174,22.6626 -Kodak,5x5,ldr-rgb-kodak20.png,42.3441,0.0325,0.0158,24.8571 -Kodak,5x5,ldr-rgb-kodak21.png,40.4026,0.0395,0.0209,18.8404 -Kodak,5x5,ldr-rgb-kodak22.png,39.7574,0.0457,0.0243,16.1710 -Kodak,5x5,ldr-rgb-kodak23.png,42.4861,0.0351,0.0161,24.4568 -Kodak,5x5,ldr-rgb-kodak24.png,37.7908,0.0497,0.0293,13.4410 -Kodak,6x6,ldr-rgb-kodak01.png,35.7514,0.0540,0.0346,11.3692 -Kodak,6x6,ldr-rgb-kodak02.png,38.1633,0.0444,0.0236,16.6618 -Kodak,6x6,ldr-rgb-kodak03.png,40.5315,0.0333,0.0158,24.9424 -Kodak,6x6,ldr-rgb-kodak04.png,38.5310,0.0450,0.0222,17.7165 -Kodak,6x6,ldr-rgb-kodak05.png,34.3246,0.0706,0.0499,7.8749 -Kodak,6x6,ldr-rgb-kodak06.png,37.2781,0.0434,0.0240,16.3512 -Kodak,6x6,ldr-rgb-kodak07.png,38.8424,0.0437,0.0218,18.0252 -Kodak,6x6,ldr-rgb-kodak08.png,34.4294,0.0752,0.0517,7.6068 -Kodak,6x6,ldr-rgb-kodak09.png,39.9499,0.0378,0.0165,23.8069 -Kodak,6x6,ldr-rgb-kodak10.png,39.7100,0.0385,0.0162,24.2190 -Kodak,6x6,ldr-rgb-kodak11.png,37.1255,0.0456,0.0262,15.0271 -Kodak,6x6,ldr-rgb-kodak12.png,40.7229,0.0323,0.0139,28.2158 -Kodak,6x6,ldr-rgb-kodak13.png,32.7806,0.0766,0.0553,7.1073 -Kodak,6x6,ldr-rgb-kodak14.png,35.2350,0.0612,0.0412,9.5434 -Kodak,6x6,ldr-rgb-kodak15.png,38.5238,0.0438,0.0233,16.8415 -Kodak,6x6,ldr-rgb-kodak16.png,40.4988,0.0317,0.0139,28.3808 -Kodak,6x6,ldr-rgb-kodak17.png,38.9257,0.0393,0.0170,23.1645 -Kodak,6x6,ldr-rgb-kodak18.png,35.0961,0.0603,0.0367,10.7278 -Kodak,6x6,ldr-rgb-kodak19.png,37.9622,0.0453,0.0228,17.2409 -Kodak,6x6,ldr-rgb-kodak20.png,39.1651,0.0360,0.0187,21.0524 -Kodak,6x6,ldr-rgb-kodak21.png,36.8830,0.0469,0.0276,14.2227 -Kodak,6x6,ldr-rgb-kodak22.png,36.9688,0.0496,0.0277,14.1920 -Kodak,6x6,ldr-rgb-kodak23.png,40.0315,0.0356,0.0165,23.8371 -Kodak,6x6,ldr-rgb-kodak24.png,34.7652,0.0562,0.0347,11.3212 -Kodak,8x8,ldr-rgb-kodak01.png,31.3198,0.0725,0.0490,8.0183 -Kodak,8x8,ldr-rgb-kodak02.png,34.8859,0.0484,0.0242,16.2815 -Kodak,8x8,ldr-rgb-kodak03.png,36.5587,0.0401,0.0185,21.2916 -Kodak,8x8,ldr-rgb-kodak04.png,35.1631,0.0495,0.0228,17.2796 -Kodak,8x8,ldr-rgb-kodak05.png,30.2290,0.0919,0.0671,5.8628 -Kodak,8x8,ldr-rgb-kodak06.png,32.8875,0.0577,0.0343,11.4600 -Kodak,8x8,ldr-rgb-kodak07.png,34.9574,0.0517,0.0256,15.3792 -Kodak,8x8,ldr-rgb-kodak08.png,29.9727,0.1012,0.0735,5.3487 -Kodak,8x8,ldr-rgb-kodak09.png,36.0644,0.0452,0.0200,19.7003 -Kodak,8x8,ldr-rgb-kodak10.png,35.8574,0.0454,0.0192,20.5143 -Kodak,8x8,ldr-rgb-kodak11.png,32.9724,0.0568,0.0336,11.6955 -Kodak,8x8,ldr-rgb-kodak12.png,36.6491,0.0395,0.0174,22.5442 -Kodak,8x8,ldr-rgb-kodak13.png,28.2115,0.1062,0.0813,4.8349 -Kodak,8x8,ldr-rgb-kodak14.png,31.4868,0.0767,0.0527,7.4662 -Kodak,8x8,ldr-rgb-kodak15.png,34.9071,0.0497,0.0253,15.5643 -Kodak,8x8,ldr-rgb-kodak16.png,36.0183,0.0420,0.0199,19.7399 -Kodak,8x8,ldr-rgb-kodak17.png,34.8533,0.0475,0.0217,18.0789 -Kodak,8x8,ldr-rgb-kodak18.png,31.2426,0.0731,0.0451,8.7242 -Kodak,8x8,ldr-rgb-kodak19.png,34.0758,0.0550,0.0279,14.0807 -Kodak,8x8,ldr-rgb-kodak20.png,35.2054,0.0435,0.0221,17.8241 -Kodak,8x8,ldr-rgb-kodak21.png,32.7363,0.0588,0.0352,11.1747 -Kodak,8x8,ldr-rgb-kodak22.png,33.4351,0.0562,0.0303,12.9663 -Kodak,8x8,ldr-rgb-kodak23.png,36.4996,0.0395,0.0165,23.8471 -Kodak,8x8,ldr-rgb-kodak24.png,30.8082,0.0696,0.0441,8.9135 -Kodak,12x12,ldr-rgb-kodak01.png,27.1019,0.0660,0.0356,11.0408 -Kodak,12x12,ldr-rgb-kodak02.png,31.0998,0.0435,0.0128,30.6504 -Kodak,12x12,ldr-rgb-kodak03.png,32.6801,0.0397,0.0115,34.2584 -Kodak,12x12,ldr-rgb-kodak04.png,31.5605,0.0444,0.0111,35.3420 -Kodak,12x12,ldr-rgb-kodak05.png,25.8046,0.0746,0.0436,9.0214 -Kodak,12x12,ldr-rgb-kodak06.png,28.6329,0.0556,0.0261,15.0676 -Kodak,12x12,ldr-rgb-kodak07.png,30.8575,0.0469,0.0143,27.4878 -Kodak,12x12,ldr-rgb-kodak08.png,25.3858,0.0874,0.0531,7.3991 -Kodak,12x12,ldr-rgb-kodak09.png,31.8332,0.0441,0.0130,30.3403 -Kodak,12x12,ldr-rgb-kodak10.png,31.5261,0.0464,0.0137,28.7860 -Kodak,12x12,ldr-rgb-kodak11.png,28.9305,0.0501,0.0206,19.0475 -Kodak,12x12,ldr-rgb-kodak12.png,32.2648,0.0399,0.0113,34.8285 -Kodak,12x12,ldr-rgb-kodak13.png,24.3204,0.0915,0.0603,6.5249 -Kodak,12x12,ldr-rgb-kodak14.png,27.5269,0.0594,0.0287,13.7004 -Kodak,12x12,ldr-rgb-kodak15.png,31.2436,0.0472,0.0157,25.0409 -Kodak,12x12,ldr-rgb-kodak16.png,31.4839,0.0421,0.0133,29.6050 -Kodak,12x12,ldr-rgb-kodak17.png,30.8893,0.0473,0.0144,27.2197 -Kodak,12x12,ldr-rgb-kodak18.png,27.4177,0.0622,0.0283,13.9029 -Kodak,12x12,ldr-rgb-kodak19.png,30.1727,0.0523,0.0195,20.1280 -Kodak,12x12,ldr-rgb-kodak20.png,31.0405,0.0435,0.0154,25.4938 -Kodak,12x12,ldr-rgb-kodak21.png,28.7196,0.0546,0.0253,15.5625 -Kodak,12x12,ldr-rgb-kodak22.png,29.8238,0.0475,0.0158,24.8384 -Kodak,12x12,ldr-rgb-kodak23.png,32.5185,0.0415,0.0116,33.9593 -Kodak,12x12,ldr-rgb-kodak24.png,26.7652,0.0653,0.0335,11.7273 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index 3a73149..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.5072,0.0352,0.0182,21.5661 -Kodak,4x4,ldr-rgb-kodak02.png,43.8025,0.0406,0.0226,17.3797 -Kodak,4x4,ldr-rgb-kodak03.png,46.0406,0.0303,0.0147,26.6695 -Kodak,4x4,ldr-rgb-kodak04.png,44.1429,0.0416,0.0210,18.7138 -Kodak,4x4,ldr-rgb-kodak05.png,40.9879,0.0464,0.0279,14.0892 -Kodak,4x4,ldr-rgb-kodak06.png,44.4296,0.0352,0.0182,21.6266 -Kodak,4x4,ldr-rgb-kodak07.png,44.6051,0.0383,0.0187,21.0624 -Kodak,4x4,ldr-rgb-kodak08.png,41.5000,0.0504,0.0287,13.6976 -Kodak,4x4,ldr-rgb-kodak09.png,45.9005,0.0333,0.0145,27.1542 -Kodak,4x4,ldr-rgb-kodak10.png,45.6663,0.0354,0.0152,25.9327 -Kodak,4x4,ldr-rgb-kodak11.png,43.8292,0.0370,0.0201,19.5980 -Kodak,4x4,ldr-rgb-kodak12.png,46.4729,0.0303,0.0142,27.6992 -Kodak,4x4,ldr-rgb-kodak13.png,41.1509,0.0467,0.0285,13.7937 -Kodak,4x4,ldr-rgb-kodak14.png,41.0931,0.0404,0.0224,17.5230 -Kodak,4x4,ldr-rgb-kodak15.png,44.1027,0.0400,0.0212,18.5515 -Kodak,4x4,ldr-rgb-kodak16.png,47.0422,0.0296,0.0136,28.8747 -Kodak,4x4,ldr-rgb-kodak17.png,45.4973,0.0344,0.0143,27.5263 -Kodak,4x4,ldr-rgb-kodak18.png,41.2449,0.0506,0.0286,13.7725 -Kodak,4x4,ldr-rgb-kodak19.png,44.5301,0.0383,0.0177,22.2723 -Kodak,4x4,ldr-rgb-kodak20.png,45.8602,0.0309,0.0154,25.5649 -Kodak,4x4,ldr-rgb-kodak21.png,44.2614,0.0353,0.0183,21.4639 -Kodak,4x4,ldr-rgb-kodak22.png,42.7742,0.0435,0.0244,16.0976 -Kodak,4x4,ldr-rgb-kodak23.png,45.2565,0.0341,0.0170,23.0641 -Kodak,4x4,ldr-rgb-kodak24.png,41.2205,0.0430,0.0239,16.4767 -Kodak,5x5,ldr-rgb-kodak01.png,39.3652,0.0377,0.0198,19.8695 -Kodak,5x5,ldr-rgb-kodak02.png,40.3762,0.0361,0.0178,22.1417 -Kodak,5x5,ldr-rgb-kodak03.png,42.6004,0.0286,0.0124,31.6394 -Kodak,5x5,ldr-rgb-kodak04.png,40.7711,0.0383,0.0171,22.9709 -Kodak,5x5,ldr-rgb-kodak05.png,36.9823,0.0480,0.0291,13.4959 -Kodak,5x5,ldr-rgb-kodak06.png,40.4008,0.0342,0.0168,23.3670 -Kodak,5x5,ldr-rgb-kodak07.png,41.1154,0.0367,0.0163,24.0692 -Kodak,5x5,ldr-rgb-kodak08.png,37.3666,0.0518,0.0296,13.2681 -Kodak,5x5,ldr-rgb-kodak09.png,42.5422,0.0317,0.0120,32.6808 -Kodak,5x5,ldr-rgb-kodak10.png,42.3455,0.0337,0.0127,31.0398 -Kodak,5x5,ldr-rgb-kodak11.png,40.0401,0.0349,0.0175,22.4555 -Kodak,5x5,ldr-rgb-kodak12.png,43.1448,0.0280,0.0113,34.6660 -Kodak,5x5,ldr-rgb-kodak13.png,36.6876,0.0485,0.0296,13.2709 -Kodak,5x5,ldr-rgb-kodak14.png,37.3962,0.0413,0.0227,17.2995 -Kodak,5x5,ldr-rgb-kodak15.png,40.8535,0.0360,0.0167,23.5233 -Kodak,5x5,ldr-rgb-kodak16.png,43.3795,0.0279,0.0111,35.4346 -Kodak,5x5,ldr-rgb-kodak17.png,41.8560,0.0328,0.0122,32.2469 -Kodak,5x5,ldr-rgb-kodak18.png,37.9129,0.0464,0.0242,16.2728 -Kodak,5x5,ldr-rgb-kodak19.png,40.8503,0.0367,0.0155,25.3636 -Kodak,5x5,ldr-rgb-kodak20.png,42.0160,0.0291,0.0129,30.3760 -Kodak,5x5,ldr-rgb-kodak21.png,40.1806,0.0350,0.0174,22.5779 -Kodak,5x5,ldr-rgb-kodak22.png,39.4506,0.0391,0.0192,20.4993 -Kodak,5x5,ldr-rgb-kodak23.png,42.1119,0.0314,0.0137,28.6640 -Kodak,5x5,ldr-rgb-kodak24.png,37.5517,0.0414,0.0217,18.0912 -Kodak,6x6,ldr-rgb-kodak01.png,35.6562,0.0435,0.0250,15.7073 -Kodak,6x6,ldr-rgb-kodak02.png,38.0339,0.0361,0.0171,23.0409 -Kodak,6x6,ldr-rgb-kodak03.png,40.3032,0.0283,0.0118,33.2500 -Kodak,6x6,ldr-rgb-kodak04.png,38.2918,0.0381,0.0161,24.4144 -Kodak,6x6,ldr-rgb-kodak05.png,34.0896,0.0508,0.0312,12.5906 -Kodak,6x6,ldr-rgb-kodak06.png,37.2222,0.0360,0.0181,21.6755 -Kodak,6x6,ldr-rgb-kodak07.png,38.6336,0.0367,0.0159,24.8055 -Kodak,6x6,ldr-rgb-kodak08.png,34.2253,0.0550,0.0324,12.1367 -Kodak,6x6,ldr-rgb-kodak09.png,39.7573,0.0326,0.0126,31.2592 -Kodak,6x6,ldr-rgb-kodak10.png,39.5669,0.0338,0.0123,31.9663 -Kodak,6x6,ldr-rgb-kodak11.png,36.9968,0.0363,0.0186,21.0896 -Kodak,6x6,ldr-rgb-kodak12.png,40.5658,0.0284,0.0110,35.7860 -Kodak,6x6,ldr-rgb-kodak13.png,32.7154,0.0566,0.0369,10.6490 -Kodak,6x6,ldr-rgb-kodak14.png,34.8624,0.0433,0.0244,16.1047 -Kodak,6x6,ldr-rgb-kodak15.png,38.3699,0.0362,0.0168,23.4028 -Kodak,6x6,ldr-rgb-kodak16.png,40.4581,0.0286,0.0116,34.0216 -Kodak,6x6,ldr-rgb-kodak17.png,38.8420,0.0344,0.0131,29.9643 -Kodak,6x6,ldr-rgb-kodak18.png,35.0034,0.0482,0.0251,15.6572 -Kodak,6x6,ldr-rgb-kodak19.png,37.8298,0.0393,0.0176,22.3493 -Kodak,6x6,ldr-rgb-kodak20.png,39.0123,0.0304,0.0139,28.3725 -Kodak,6x6,ldr-rgb-kodak21.png,36.8075,0.0374,0.0196,20.0446 -Kodak,6x6,ldr-rgb-kodak22.png,36.8498,0.0394,0.0194,20.2396 -Kodak,6x6,ldr-rgb-kodak23.png,39.8307,0.0305,0.0127,30.8719 -Kodak,6x6,ldr-rgb-kodak24.png,34.6916,0.0435,0.0237,16.6068 -Kodak,8x8,ldr-rgb-kodak01.png,31.1792,0.0569,0.0349,11.2524 -Kodak,8x8,ldr-rgb-kodak02.png,34.7811,0.0409,0.0183,21.4695 -Kodak,8x8,ldr-rgb-kodak03.png,36.4262,0.0343,0.0142,27.6116 -Kodak,8x8,ldr-rgb-kodak04.png,35.0547,0.0425,0.0173,22.7175 -Kodak,8x8,ldr-rgb-kodak05.png,30.0205,0.0666,0.0438,8.9853 -Kodak,8x8,ldr-rgb-kodak06.png,32.7989,0.0469,0.0252,15.5766 -Kodak,8x8,ldr-rgb-kodak07.png,34.8360,0.0435,0.0194,20.2929 -Kodak,8x8,ldr-rgb-kodak08.png,29.7069,0.0721,0.0466,8.4347 -Kodak,8x8,ldr-rgb-kodak09.png,35.8914,0.0388,0.0154,25.5803 -Kodak,8x8,ldr-rgb-kodak10.png,35.7051,0.0393,0.0147,26.6932 -Kodak,8x8,ldr-rgb-kodak11.png,32.8451,0.0454,0.0239,16.4622 -Kodak,8x8,ldr-rgb-kodak12.png,36.5111,0.0347,0.0139,28.2704 -Kodak,8x8,ldr-rgb-kodak13.png,28.1364,0.0783,0.0551,7.1301 -Kodak,8x8,ldr-rgb-kodak14.png,31.2591,0.0560,0.0336,11.7123 -Kodak,8x8,ldr-rgb-kodak15.png,34.7599,0.0414,0.0186,21.1407 -Kodak,8x8,ldr-rgb-kodak16.png,35.9616,0.0363,0.0158,24.9172 -Kodak,8x8,ldr-rgb-kodak17.png,34.7164,0.0412,0.0165,23.7595 -Kodak,8x8,ldr-rgb-kodak18.png,31.1666,0.0579,0.0318,12.3843 -Kodak,8x8,ldr-rgb-kodak19.png,33.8904,0.0462,0.0211,18.6527 -Kodak,8x8,ldr-rgb-kodak20.png,35.0191,0.0363,0.0165,23.7907 -Kodak,8x8,ldr-rgb-kodak21.png,32.6198,0.0468,0.0253,15.5146 -Kodak,8x8,ldr-rgb-kodak22.png,33.3242,0.0460,0.0222,17.6822 -Kodak,8x8,ldr-rgb-kodak23.png,36.3894,0.0348,0.0133,29.4786 -Kodak,8x8,ldr-rgb-kodak24.png,30.7268,0.0546,0.0307,12.8059 -Kodak,12x12,ldr-rgb-kodak01.png,26.9930,0.0531,0.0267,14.7211 -Kodak,12x12,ldr-rgb-kodak02.png,31.0354,0.0375,0.0109,36.1713 -Kodak,12x12,ldr-rgb-kodak03.png,32.6215,0.0340,0.0097,40.4718 -Kodak,12x12,ldr-rgb-kodak04.png,31.4774,0.0389,0.0096,41.0756 -Kodak,12x12,ldr-rgb-kodak05.png,25.6941,0.0588,0.0320,12.2839 -Kodak,12x12,ldr-rgb-kodak06.png,28.4895,0.0459,0.0204,19.2433 -Kodak,12x12,ldr-rgb-kodak07.png,30.8016,0.0402,0.0119,32.9570 -Kodak,12x12,ldr-rgb-kodak08.png,25.2157,0.0678,0.0373,10.5417 -Kodak,12x12,ldr-rgb-kodak09.png,31.6339,0.0383,0.0108,36.5513 -Kodak,12x12,ldr-rgb-kodak10.png,31.4567,0.0398,0.0112,35.2031 -Kodak,12x12,ldr-rgb-kodak11.png,28.8572,0.0413,0.0160,24.5928 -Kodak,12x12,ldr-rgb-kodak12.png,32.1857,0.0345,0.0098,40.0755 -Kodak,12x12,ldr-rgb-kodak13.png,24.2396,0.0700,0.0424,9.2693 -Kodak,12x12,ldr-rgb-kodak14.png,27.4380,0.0477,0.0213,18.4445 -Kodak,12x12,ldr-rgb-kodak15.png,31.1533,0.0397,0.0128,30.8044 -Kodak,12x12,ldr-rgb-kodak16.png,31.3620,0.0358,0.0112,34.9680 -Kodak,12x12,ldr-rgb-kodak17.png,30.8364,0.0406,0.0117,33.6998 -Kodak,12x12,ldr-rgb-kodak18.png,27.3672,0.0513,0.0211,18.6032 -Kodak,12x12,ldr-rgb-kodak19.png,29.8648,0.0444,0.0156,25.2645 -Kodak,12x12,ldr-rgb-kodak20.png,30.9381,0.0364,0.0126,31.0866 -Kodak,12x12,ldr-rgb-kodak21.png,28.6166,0.0447,0.0194,20.2857 -Kodak,12x12,ldr-rgb-kodak22.png,29.7245,0.0409,0.0130,30.3102 -Kodak,12x12,ldr-rgb-kodak23.png,32.4842,0.0358,0.0101,38.9511 -Kodak,12x12,ldr-rgb-kodak24.png,26.6937,0.0522,0.0242,16.2218 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index ba5ad40..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.2910,0.1572,0.1386,2.8364 -Kodak,4x4,ldr-rgb-kodak02.png,45.3499,0.2118,0.1921,2.0474 -Kodak,4x4,ldr-rgb-kodak03.png,47.6132,0.1130,0.0958,4.1040 -Kodak,4x4,ldr-rgb-kodak04.png,45.4289,0.1709,0.1482,2.6526 -Kodak,4x4,ldr-rgb-kodak05.png,42.1296,0.1972,0.1769,2.2226 -Kodak,4x4,ldr-rgb-kodak06.png,45.1555,0.1498,0.1310,3.0019 -Kodak,4x4,ldr-rgb-kodak07.png,45.9745,0.1440,0.1223,3.2163 -Kodak,4x4,ldr-rgb-kodak08.png,42.5130,0.2190,0.1958,2.0082 -Kodak,4x4,ldr-rgb-kodak09.png,47.1616,0.1704,0.1497,2.6273 -Kodak,4x4,ldr-rgb-kodak10.png,46.8287,0.1749,0.1530,2.5696 -Kodak,4x4,ldr-rgb-kodak11.png,44.8668,0.1700,0.1511,2.6017 -Kodak,4x4,ldr-rgb-kodak12.png,47.9301,0.1286,0.1106,3.5552 -Kodak,4x4,ldr-rgb-kodak13.png,41.6152,0.1694,0.1494,2.6328 -Kodak,4x4,ldr-rgb-kodak14.png,42.6269,0.1819,0.1628,2.4147 -Kodak,4x4,ldr-rgb-kodak15.png,45.4386,0.1510,0.1305,3.0123 -Kodak,4x4,ldr-rgb-kodak16.png,47.8565,0.1319,0.1142,3.4445 -Kodak,4x4,ldr-rgb-kodak17.png,46.2901,0.1502,0.1280,3.0721 -Kodak,4x4,ldr-rgb-kodak18.png,41.9927,0.2219,0.1987,1.9790 -Kodak,4x4,ldr-rgb-kodak19.png,45.3392,0.1803,0.1575,2.4967 -Kodak,4x4,ldr-rgb-kodak20.png,46.8869,0.1105,0.0936,4.2021 -Kodak,4x4,ldr-rgb-kodak21.png,45.1510,0.1803,0.1614,2.4358 -Kodak,4x4,ldr-rgb-kodak22.png,43.7746,0.2231,0.2022,1.9450 -Kodak,4x4,ldr-rgb-kodak23.png,46.8184,0.1720,0.1534,2.5637 -Kodak,4x4,ldr-rgb-kodak24.png,42.2960,0.1761,0.1554,2.5299 -Kodak,5x5,ldr-rgb-kodak01.png,40.1121,0.1895,0.1693,2.3222 -Kodak,5x5,ldr-rgb-kodak02.png,41.6953,0.2006,0.1792,2.1947 -Kodak,5x5,ldr-rgb-kodak03.png,44.0360,0.0941,0.0750,5.2427 -Kodak,5x5,ldr-rgb-kodak04.png,42.0560,0.1571,0.1330,2.9575 -Kodak,5x5,ldr-rgb-kodak05.png,37.9816,0.2195,0.1977,1.9894 -Kodak,5x5,ldr-rgb-kodak06.png,40.9586,0.1509,0.1309,3.0034 -Kodak,5x5,ldr-rgb-kodak07.png,42.4607,0.1278,0.1046,3.7591 -Kodak,5x5,ldr-rgb-kodak08.png,38.3486,0.2388,0.2144,1.8339 -Kodak,5x5,ldr-rgb-kodak09.png,43.8038,0.1103,0.0879,4.4712 -Kodak,5x5,ldr-rgb-kodak10.png,43.4092,0.1244,0.1010,3.8916 -Kodak,5x5,ldr-rgb-kodak11.png,40.8377,0.1723,0.1521,2.5851 -Kodak,5x5,ldr-rgb-kodak12.png,44.3921,0.0952,0.0760,5.1748 -Kodak,5x5,ldr-rgb-kodak13.png,36.9078,0.2029,0.1813,2.1694 -Kodak,5x5,ldr-rgb-kodak14.png,38.6484,0.1957,0.1748,2.2491 -Kodak,5x5,ldr-rgb-kodak15.png,41.8912,0.1458,0.1241,3.1676 -Kodak,5x5,ldr-rgb-kodak16.png,44.1367,0.1065,0.0871,4.5140 -Kodak,5x5,ldr-rgb-kodak17.png,42.5213,0.1117,0.0880,4.4683 -Kodak,5x5,ldr-rgb-kodak18.png,38.3607,0.2141,0.1889,2.0813 -Kodak,5x5,ldr-rgb-kodak19.png,41.6469,0.1469,0.1229,3.1997 -Kodak,5x5,ldr-rgb-kodak20.png,42.9685,0.1045,0.0858,4.5855 -Kodak,5x5,ldr-rgb-kodak21.png,40.7620,0.1484,0.1281,3.0702 -Kodak,5x5,ldr-rgb-kodak22.png,40.2773,0.2028,0.1803,2.1811 -Kodak,5x5,ldr-rgb-kodak23.png,43.5488,0.1273,0.1071,3.6710 -Kodak,5x5,ldr-rgb-kodak24.png,38.1152,0.1738,0.1515,2.5950 -Kodak,6x6,ldr-rgb-kodak01.png,36.1951,0.1957,0.1748,2.2496 -Kodak,6x6,ldr-rgb-kodak02.png,39.0094,0.1554,0.1331,2.9533 -Kodak,6x6,ldr-rgb-kodak03.png,41.3262,0.0790,0.0597,6.5812 -Kodak,6x6,ldr-rgb-kodak04.png,39.3983,0.1336,0.1090,3.6074 -Kodak,6x6,ldr-rgb-kodak05.png,34.7867,0.2140,0.1919,2.0492 -Kodak,6x6,ldr-rgb-kodak06.png,37.6289,0.1337,0.1130,3.4785 -Kodak,6x6,ldr-rgb-kodak07.png,39.7726,0.1100,0.0864,4.5534 -Kodak,6x6,ldr-rgb-kodak08.png,34.9978,0.2367,0.2114,1.8598 -Kodak,6x6,ldr-rgb-kodak09.png,40.8821,0.0849,0.0623,6.3129 -Kodak,6x6,ldr-rgb-kodak10.png,40.5030,0.0911,0.0670,5.8729 -Kodak,6x6,ldr-rgb-kodak11.png,37.5798,0.1433,0.1227,3.2060 -Kodak,6x6,ldr-rgb-kodak12.png,41.4837,0.0744,0.0545,7.2129 -Kodak,6x6,ldr-rgb-kodak13.png,32.8829,0.2215,0.1996,1.9696 -Kodak,6x6,ldr-rgb-kodak14.png,35.8236,0.1789,0.1576,2.4943 -Kodak,6x6,ldr-rgb-kodak15.png,39.1953,0.1344,0.1122,3.5038 -Kodak,6x6,ldr-rgb-kodak16.png,41.0408,0.0870,0.0673,5.8468 -Kodak,6x6,ldr-rgb-kodak17.png,39.4928,0.0926,0.0684,5.7515 -Kodak,6x6,ldr-rgb-kodak18.png,35.3481,0.1891,0.1636,2.4037 -Kodak,6x6,ldr-rgb-kodak19.png,38.5316,0.1332,0.1084,3.6276 -Kodak,6x6,ldr-rgb-kodak20.png,39.7651,0.0956,0.0764,5.1471 -Kodak,6x6,ldr-rgb-kodak21.png,37.1926,0.1315,0.1106,3.5543 -Kodak,6x6,ldr-rgb-kodak22.png,37.4532,0.1686,0.1457,2.6988 -Kodak,6x6,ldr-rgb-kodak23.png,40.9705,0.0903,0.0694,5.6681 -Kodak,6x6,ldr-rgb-kodak24.png,35.0426,0.1559,0.1330,2.9559 -Kodak,8x8,ldr-rgb-kodak01.png,31.8012,0.2638,0.2393,1.6434 -Kodak,8x8,ldr-rgb-kodak02.png,35.7606,0.1516,0.1257,3.1280 -Kodak,8x8,ldr-rgb-kodak03.png,37.7459,0.0960,0.0729,5.3971 -Kodak,8x8,ldr-rgb-kodak04.png,36.0605,0.1462,0.1182,3.3278 -Kodak,8x8,ldr-rgb-kodak05.png,30.7416,0.2737,0.2478,1.5866 -Kodak,8x8,ldr-rgb-kodak06.png,33.4352,0.1694,0.1453,2.7065 -Kodak,8x8,ldr-rgb-kodak07.png,36.1304,0.1293,0.1017,3.8653 -Kodak,8x8,ldr-rgb-kodak08.png,30.5708,0.2757,0.2470,1.5918 -Kodak,8x8,ldr-rgb-kodak09.png,37.2646,0.0983,0.0716,5.4919 -Kodak,8x8,ldr-rgb-kodak10.png,36.9159,0.1019,0.0739,5.3214 -Kodak,8x8,ldr-rgb-kodak11.png,33.6569,0.1670,0.1426,2.7580 -Kodak,8x8,ldr-rgb-kodak12.png,37.8259,0.0918,0.0684,5.7511 -Kodak,8x8,ldr-rgb-kodak13.png,28.3927,0.3063,0.2805,1.4020 -Kodak,8x8,ldr-rgb-kodak14.png,32.1340,0.2180,0.1930,2.0369 -Kodak,8x8,ldr-rgb-kodak15.png,35.8359,0.1355,0.1096,3.5878 -Kodak,8x8,ldr-rgb-kodak16.png,37.0213,0.1075,0.0841,4.6754 -Kodak,8x8,ldr-rgb-kodak17.png,35.6807,0.1127,0.0850,4.6255 -Kodak,8x8,ldr-rgb-kodak18.png,31.5529,0.2194,0.1900,2.0694 -Kodak,8x8,ldr-rgb-kodak19.png,34.7649,0.1566,0.1279,3.0738 -Kodak,8x8,ldr-rgb-kodak20.png,35.8945,0.1173,0.0944,4.1675 -Kodak,8x8,ldr-rgb-kodak21.png,33.1150,0.1665,0.1422,2.7659 -Kodak,8x8,ldr-rgb-kodak22.png,34.0244,0.1827,0.1560,2.5211 -Kodak,8x8,ldr-rgb-kodak23.png,37.6470,0.0922,0.0675,5.8229 -Kodak,8x8,ldr-rgb-kodak24.png,31.1140,0.1886,0.1615,2.4343 -Kodak,12x12,ldr-rgb-kodak01.png,27.7578,0.2813,0.2480,1.5856 -Kodak,12x12,ldr-rgb-kodak02.png,32.4621,0.1102,0.0762,5.1581 -Kodak,12x12,ldr-rgb-kodak03.png,33.7766,0.0890,0.0576,6.8214 -Kodak,12x12,ldr-rgb-kodak04.png,32.4443,0.1043,0.0676,5.8164 -Kodak,12x12,ldr-rgb-kodak05.png,26.3986,0.2996,0.2656,1.4804 -Kodak,12x12,ldr-rgb-kodak06.png,29.3737,0.1796,0.1469,2.6762 -Kodak,12x12,ldr-rgb-kodak07.png,32.0414,0.1261,0.0902,4.3610 -Kodak,12x12,ldr-rgb-kodak08.png,26.0600,0.3002,0.2635,1.4925 -Kodak,12x12,ldr-rgb-kodak09.png,33.0989,0.0939,0.0590,6.6622 -Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0965,0.0606,6.4909 -Kodak,12x12,ldr-rgb-kodak11.png,29.7433,0.1592,0.1266,3.1053 -Kodak,12x12,ldr-rgb-kodak12.png,33.8819,0.0847,0.0527,7.4588 -Kodak,12x12,ldr-rgb-kodak13.png,24.5282,0.3432,0.3092,1.2718 -Kodak,12x12,ldr-rgb-kodak14.png,28.4176,0.2150,0.1818,2.1625 -Kodak,12x12,ldr-rgb-kodak15.png,32.2342,0.1199,0.0857,4.5858 -Kodak,12x12,ldr-rgb-kodak16.png,32.9807,0.0944,0.0626,6.2826 -Kodak,12x12,ldr-rgb-kodak17.png,31.7805,0.1050,0.0690,5.6984 -Kodak,12x12,ldr-rgb-kodak18.png,27.7783,0.2126,0.1750,2.2466 -Kodak,12x12,ldr-rgb-kodak19.png,30.8882,0.1364,0.0998,3.9415 -Kodak,12x12,ldr-rgb-kodak20.png,31.8562,0.1047,0.0732,5.3682 -Kodak,12x12,ldr-rgb-kodak21.png,29.1771,0.1910,0.1584,2.4823 -Kodak,12x12,ldr-rgb-kodak22.png,30.4983,0.1482,0.1131,3.4758 -Kodak,12x12,ldr-rgb-kodak23.png,33.5464,0.0802,0.0475,8.2701 -Kodak,12x12,ldr-rgb-kodak24.png,27.0976,0.1918,0.1567,2.5086 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index 1ae4037..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.4944,0.4098,0.3911,1.0055 -Kodak,4x4,ldr-rgb-kodak02.png,45.6493,0.4895,0.4697,0.8372 -Kodak,4x4,ldr-rgb-kodak03.png,47.9884,0.4219,0.4046,0.9719 -Kodak,4x4,ldr-rgb-kodak04.png,45.6562,0.4617,0.4391,0.8956 -Kodak,4x4,ldr-rgb-kodak05.png,42.4063,0.4574,0.4372,0.8993 -Kodak,4x4,ldr-rgb-kodak06.png,45.3572,0.4090,0.3905,1.0071 -Kodak,4x4,ldr-rgb-kodak07.png,46.3419,0.4590,0.4371,0.8995 -Kodak,4x4,ldr-rgb-kodak08.png,42.8054,0.4859,0.4626,0.8500 -Kodak,4x4,ldr-rgb-kodak09.png,47.4208,0.4680,0.4469,0.8799 -Kodak,4x4,ldr-rgb-kodak10.png,47.0603,0.4647,0.4428,0.8881 -Kodak,4x4,ldr-rgb-kodak11.png,45.1121,0.4325,0.4136,0.9507 -Kodak,4x4,ldr-rgb-kodak12.png,48.2457,0.4337,0.4159,0.9454 -Kodak,4x4,ldr-rgb-kodak13.png,41.7174,0.4160,0.3959,0.9933 -Kodak,4x4,ldr-rgb-kodak14.png,42.9405,0.4440,0.4248,0.9256 -Kodak,4x4,ldr-rgb-kodak15.png,45.7858,0.4420,0.4215,0.9330 -Kodak,4x4,ldr-rgb-kodak16.png,48.0652,0.4279,0.4096,0.9600 -Kodak,4x4,ldr-rgb-kodak17.png,46.4610,0.4467,0.4245,0.9263 -Kodak,4x4,ldr-rgb-kodak18.png,42.1541,0.4868,0.4631,0.8491 -Kodak,4x4,ldr-rgb-kodak19.png,45.5439,0.4639,0.4411,0.8914 -Kodak,4x4,ldr-rgb-kodak20.png,47.1284,0.2937,0.2766,1.4214 -Kodak,4x4,ldr-rgb-kodak21.png,45.3018,0.4541,0.4351,0.9038 -Kodak,4x4,ldr-rgb-kodak22.png,43.9797,0.4945,0.4733,0.8308 -Kodak,4x4,ldr-rgb-kodak23.png,47.1533,0.4800,0.4612,0.8527 -Kodak,4x4,ldr-rgb-kodak24.png,42.5030,0.4462,0.4254,0.9244 -Kodak,5x5,ldr-rgb-kodak01.png,40.2326,0.5264,0.5062,0.7769 -Kodak,5x5,ldr-rgb-kodak02.png,41.9976,0.6133,0.5915,0.6647 -Kodak,5x5,ldr-rgb-kodak03.png,44.3239,0.5081,0.4892,0.8039 -Kodak,5x5,ldr-rgb-kodak04.png,42.2394,0.5551,0.5313,0.7401 -Kodak,5x5,ldr-rgb-kodak05.png,38.1756,0.5761,0.5548,0.7088 -Kodak,5x5,ldr-rgb-kodak06.png,41.0844,0.5040,0.4835,0.8133 -Kodak,5x5,ldr-rgb-kodak07.png,42.7249,0.5528,0.5296,0.7424 -Kodak,5x5,ldr-rgb-kodak08.png,38.5334,0.5896,0.5649,0.6961 -Kodak,5x5,ldr-rgb-kodak09.png,44.0288,0.5546,0.5318,0.7394 -Kodak,5x5,ldr-rgb-kodak10.png,43.5935,0.5625,0.5385,0.7302 -Kodak,5x5,ldr-rgb-kodak11.png,40.9987,0.5261,0.5052,0.7783 -Kodak,5x5,ldr-rgb-kodak12.png,44.5960,0.5166,0.4972,0.7908 -Kodak,5x5,ldr-rgb-kodak13.png,36.9510,0.5165,0.4949,0.7945 -Kodak,5x5,ldr-rgb-kodak14.png,38.8797,0.5528,0.5313,0.7401 -Kodak,5x5,ldr-rgb-kodak15.png,42.1246,0.5281,0.5063,0.7767 -Kodak,5x5,ldr-rgb-kodak16.png,44.2686,0.5183,0.4991,0.7878 -Kodak,5x5,ldr-rgb-kodak17.png,42.6009,0.5407,0.5170,0.7606 -Kodak,5x5,ldr-rgb-kodak18.png,38.4550,0.5980,0.5726,0.6867 -Kodak,5x5,ldr-rgb-kodak19.png,41.7719,0.5753,0.5515,0.7130 -Kodak,5x5,ldr-rgb-kodak20.png,43.2708,0.3636,0.3448,1.1405 -Kodak,5x5,ldr-rgb-kodak21.png,40.8630,0.5701,0.5497,0.7154 -Kodak,5x5,ldr-rgb-kodak22.png,40.4255,0.6132,0.5907,0.6657 -Kodak,5x5,ldr-rgb-kodak23.png,43.8841,0.5957,0.5751,0.6837 -Kodak,5x5,ldr-rgb-kodak24.png,38.2272,0.5480,0.5257,0.7480 -Kodak,6x6,ldr-rgb-kodak01.png,36.3116,0.6281,0.6072,0.6476 -Kodak,6x6,ldr-rgb-kodak02.png,39.3780,0.7153,0.6933,0.5672 -Kodak,6x6,ldr-rgb-kodak03.png,41.7331,0.4458,0.4262,0.9227 -Kodak,6x6,ldr-rgb-kodak04.png,39.6521,0.6231,0.5987,0.6568 -Kodak,6x6,ldr-rgb-kodak05.png,34.9741,0.6786,0.6563,0.5991 -Kodak,6x6,ldr-rgb-kodak06.png,37.7401,0.5643,0.5433,0.7238 -Kodak,6x6,ldr-rgb-kodak07.png,40.1032,0.5147,0.4905,0.8016 -Kodak,6x6,ldr-rgb-kodak08.png,35.1660,0.6866,0.6611,0.5948 -Kodak,6x6,ldr-rgb-kodak09.png,41.2613,0.6273,0.6041,0.6509 -Kodak,6x6,ldr-rgb-kodak10.png,40.8141,0.6426,0.6185,0.6358 -Kodak,6x6,ldr-rgb-kodak11.png,37.7541,0.5795,0.5588,0.7037 -Kodak,6x6,ldr-rgb-kodak12.png,41.8249,0.5422,0.5220,0.7533 -Kodak,6x6,ldr-rgb-kodak13.png,32.9256,0.6354,0.6125,0.6420 -Kodak,6x6,ldr-rgb-kodak14.png,36.0210,0.6551,0.6335,0.6207 -Kodak,6x6,ldr-rgb-kodak15.png,39.4514,0.5306,0.5080,0.7741 -Kodak,6x6,ldr-rgb-kodak16.png,41.2290,0.5256,0.5056,0.7777 -Kodak,6x6,ldr-rgb-kodak17.png,39.6521,0.6038,0.5797,0.6783 -Kodak,6x6,ldr-rgb-kodak18.png,35.4328,0.7180,0.6923,0.5680 -Kodak,6x6,ldr-rgb-kodak19.png,38.6954,0.6789,0.6536,0.6016 -Kodak,6x6,ldr-rgb-kodak20.png,40.0953,0.4182,0.3985,0.9869 -Kodak,6x6,ldr-rgb-kodak21.png,37.3344,0.6675,0.6462,0.6085 -Kodak,6x6,ldr-rgb-kodak22.png,37.6231,0.7261,0.7028,0.5595 -Kodak,6x6,ldr-rgb-kodak23.png,41.4033,0.6239,0.6027,0.6525 -Kodak,6x6,ldr-rgb-kodak24.png,35.1417,0.5973,0.5740,0.6850 -Kodak,8x8,ldr-rgb-kodak01.png,31.9071,0.7634,0.7373,0.5333 -Kodak,8x8,ldr-rgb-kodak02.png,36.1354,0.6667,0.6392,0.6152 -Kodak,8x8,ldr-rgb-kodak03.png,38.1744,0.3553,0.3302,1.1909 -Kodak,8x8,ldr-rgb-kodak04.png,36.3637,0.5707,0.5407,0.7273 -Kodak,8x8,ldr-rgb-kodak05.png,30.9009,0.7740,0.7468,0.5265 -Kodak,8x8,ldr-rgb-kodak06.png,33.5749,0.6285,0.6025,0.6527 -Kodak,8x8,ldr-rgb-kodak07.png,36.4888,0.4268,0.3974,0.9894 -Kodak,8x8,ldr-rgb-kodak08.png,30.7484,0.8272,0.7968,0.4935 -Kodak,8x8,ldr-rgb-kodak09.png,37.5499,0.4015,0.3730,1.0542 -Kodak,8x8,ldr-rgb-kodak10.png,37.2288,0.4474,0.4180,0.9407 -Kodak,8x8,ldr-rgb-kodak11.png,33.8276,0.6812,0.6549,0.6004 -Kodak,8x8,ldr-rgb-kodak12.png,38.2490,0.4203,0.3954,0.9945 -Kodak,8x8,ldr-rgb-kodak13.png,28.4502,0.8473,0.8190,0.4801 -Kodak,8x8,ldr-rgb-kodak14.png,32.3258,0.7754,0.7485,0.5253 -Kodak,8x8,ldr-rgb-kodak15.png,36.0605,0.5259,0.4985,0.7888 -Kodak,8x8,ldr-rgb-kodak16.png,37.2636,0.4983,0.4728,0.8316 -Kodak,8x8,ldr-rgb-kodak17.png,35.8722,0.4829,0.4533,0.8674 -Kodak,8x8,ldr-rgb-kodak18.png,31.6495,0.7859,0.7549,0.5209 -Kodak,8x8,ldr-rgb-kodak19.png,34.9142,0.5389,0.5095,0.7718 -Kodak,8x8,ldr-rgb-kodak20.png,36.1470,0.4117,0.3872,1.0156 -Kodak,8x8,ldr-rgb-kodak21.png,33.2221,0.5529,0.5265,0.7469 -Kodak,8x8,ldr-rgb-kodak22.png,34.2197,0.6997,0.6711,0.5860 -Kodak,8x8,ldr-rgb-kodak23.png,38.1768,0.3932,0.3665,1.0728 -Kodak,8x8,ldr-rgb-kodak24.png,31.2175,0.6389,0.6108,0.6438 -Kodak,12x12,ldr-rgb-kodak01.png,27.9058,0.8665,0.8304,0.4735 -Kodak,12x12,ldr-rgb-kodak02.png,32.9642,0.5741,0.5372,0.7320 -Kodak,12x12,ldr-rgb-kodak03.png,34.4219,0.3530,0.3185,1.2346 -Kodak,12x12,ldr-rgb-kodak04.png,32.9599,0.5146,0.4749,0.8280 -Kodak,12x12,ldr-rgb-kodak05.png,26.5927,0.9079,0.8714,0.4513 -Kodak,12x12,ldr-rgb-kodak06.png,29.5304,0.6499,0.6142,0.6402 -Kodak,12x12,ldr-rgb-kodak07.png,32.6109,0.4292,0.3906,1.0068 -Kodak,12x12,ldr-rgb-kodak08.png,26.2744,0.8942,0.8539,0.4605 -Kodak,12x12,ldr-rgb-kodak09.png,33.6251,0.3877,0.3497,1.1245 -Kodak,12x12,ldr-rgb-kodak10.png,32.9833,0.3845,0.3449,1.1400 -Kodak,12x12,ldr-rgb-kodak11.png,30.0468,0.6591,0.6234,0.6307 -Kodak,12x12,ldr-rgb-kodak12.png,34.4395,0.3650,0.3298,1.1924 -Kodak,12x12,ldr-rgb-kodak13.png,24.5820,1.0253,0.9882,0.3979 -Kodak,12x12,ldr-rgb-kodak14.png,28.6287,0.8154,0.7792,0.5047 -Kodak,12x12,ldr-rgb-kodak15.png,32.7197,0.4926,0.4555,0.8632 -Kodak,12x12,ldr-rgb-kodak16.png,33.3355,0.4772,0.4421,0.8895 -Kodak,12x12,ldr-rgb-kodak17.png,32.1409,0.4333,0.3944,0.9970 -Kodak,12x12,ldr-rgb-kodak18.png,27.9217,0.7837,0.7423,0.5297 -Kodak,12x12,ldr-rgb-kodak19.png,31.1006,0.6179,0.5790,0.6791 -Kodak,12x12,ldr-rgb-kodak20.png,32.1470,0.4558,0.4221,0.9316 -Kodak,12x12,ldr-rgb-kodak21.png,29.3170,0.5895,0.5539,0.7100 -Kodak,12x12,ldr-rgb-kodak22.png,30.7805,0.6694,0.6312,0.6230 -Kodak,12x12,ldr-rgb-kodak23.png,34.3635,0.3280,0.2920,1.3467 -Kodak,12x12,ldr-rgb-kodak24.png,27.2253,0.7025,0.6647,0.5915 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index 5f3e7ba..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.8489,0.0384,0.0211,18.6482 -Kodak,4x4,ldr-rgb-kodak02.png,44.2380,0.0476,0.0292,13.4553 -Kodak,4x4,ldr-rgb-kodak03.png,46.6338,0.0334,0.0177,22.2067 -Kodak,4x4,ldr-rgb-kodak04.png,44.5665,0.0473,0.0264,14.8968 -Kodak,4x4,ldr-rgb-kodak05.png,41.5682,0.0563,0.0383,10.2676 -Kodak,4x4,ldr-rgb-kodak06.png,44.7452,0.0378,0.0208,18.9156 -Kodak,4x4,ldr-rgb-kodak07.png,45.0418,0.0435,0.0227,17.2857 -Kodak,4x4,ldr-rgb-kodak08.png,42.0821,0.0624,0.0399,9.8508 -Kodak,4x4,ldr-rgb-kodak09.png,46.2551,0.0359,0.0166,23.6678 -Kodak,4x4,ldr-rgb-kodak10.png,46.0288,0.0380,0.0173,22.7015 -Kodak,4x4,ldr-rgb-kodak11.png,44.2450,0.0417,0.0247,15.9210 -Kodak,4x4,ldr-rgb-kodak12.png,47.0135,0.0321,0.0162,24.2875 -Kodak,4x4,ldr-rgb-kodak13.png,41.4309,0.0526,0.0340,11.5539 -Kodak,4x4,ldr-rgb-kodak14.png,41.8065,0.0490,0.0313,12.5428 -Kodak,4x4,ldr-rgb-kodak15.png,44.5942,0.0475,0.0282,13.9612 -Kodak,4x4,ldr-rgb-kodak16.png,47.1801,0.0304,0.0145,27.2008 -Kodak,4x4,ldr-rgb-kodak17.png,45.7548,0.0366,0.0158,24.8227 -Kodak,4x4,ldr-rgb-kodak18.png,41.6128,0.0605,0.0380,10.3600 -Kodak,4x4,ldr-rgb-kodak19.png,44.8023,0.0416,0.0205,19.1784 -Kodak,4x4,ldr-rgb-kodak20.png,46.3894,0.0335,0.0182,21.6136 -Kodak,4x4,ldr-rgb-kodak21.png,44.5781,0.0386,0.0216,18.1836 -Kodak,4x4,ldr-rgb-kodak22.png,43.1599,0.0519,0.0319,12.3196 -Kodak,4x4,ldr-rgb-kodak23.png,45.5706,0.0384,0.0205,19.1635 -Kodak,4x4,ldr-rgb-kodak24.png,41.8541,0.0513,0.0315,12.4878 -Kodak,5x5,ldr-rgb-kodak01.png,39.6106,0.0393,0.0205,19.1802 -Kodak,5x5,ldr-rgb-kodak02.png,40.6312,0.0394,0.0200,19.6845 -Kodak,5x5,ldr-rgb-kodak03.png,43.0303,0.0303,0.0138,28.4754 -Kodak,5x5,ldr-rgb-kodak04.png,41.2378,0.0411,0.0190,20.7481 -Kodak,5x5,ldr-rgb-kodak05.png,37.4134,0.0540,0.0345,11.3913 -Kodak,5x5,ldr-rgb-kodak06.png,40.5758,0.0350,0.0173,22.7357 -Kodak,5x5,ldr-rgb-kodak07.png,41.4746,0.0391,0.0176,22.3584 -Kodak,5x5,ldr-rgb-kodak08.png,37.7544,0.0587,0.0357,11.0077 -Kodak,5x5,ldr-rgb-kodak09.png,42.9020,0.0331,0.0126,31.1435 -Kodak,5x5,ldr-rgb-kodak10.png,42.6178,0.0350,0.0134,29.3929 -Kodak,5x5,ldr-rgb-kodak11.png,40.2886,0.0369,0.0192,20.4299 -Kodak,5x5,ldr-rgb-kodak12.png,43.4048,0.0287,0.0118,33.3772 -Kodak,5x5,ldr-rgb-kodak13.png,36.8038,0.0511,0.0319,12.3293 -Kodak,5x5,ldr-rgb-kodak14.png,37.9374,0.0486,0.0300,13.1186 -Kodak,5x5,ldr-rgb-kodak15.png,41.1606,0.0391,0.0193,20.3951 -Kodak,5x5,ldr-rgb-kodak16.png,43.4729,0.0279,0.0109,35.9302 -Kodak,5x5,ldr-rgb-kodak17.png,42.0129,0.0341,0.0123,31.8983 -Kodak,5x5,ldr-rgb-kodak18.png,38.0842,0.0510,0.0275,14.3102 -Kodak,5x5,ldr-rgb-kodak19.png,41.1186,0.0377,0.0155,25.3068 -Kodak,5x5,ldr-rgb-kodak20.png,42.3441,0.0304,0.0142,27.6523 -Kodak,5x5,ldr-rgb-kodak21.png,40.4026,0.0362,0.0185,21.2872 -Kodak,5x5,ldr-rgb-kodak22.png,39.7574,0.0425,0.0219,17.9167 -Kodak,5x5,ldr-rgb-kodak23.png,42.4861,0.0330,0.0145,27.0678 -Kodak,5x5,ldr-rgb-kodak24.png,37.7908,0.0462,0.0252,15.5983 -Kodak,6x6,ldr-rgb-kodak01.png,35.7514,0.0497,0.0302,13.0285 -Kodak,6x6,ldr-rgb-kodak02.png,38.1633,0.0414,0.0212,18.5831 -Kodak,6x6,ldr-rgb-kodak03.png,40.5315,0.0312,0.0141,27.9508 -Kodak,6x6,ldr-rgb-kodak04.png,38.5310,0.0424,0.0198,19.8434 -Kodak,6x6,ldr-rgb-kodak05.png,34.3246,0.0639,0.0438,8.9851 -Kodak,6x6,ldr-rgb-kodak06.png,37.2781,0.0397,0.0210,18.7024 -Kodak,6x6,ldr-rgb-kodak07.png,38.8424,0.0413,0.0193,20.4110 -Kodak,6x6,ldr-rgb-kodak08.png,34.4294,0.0683,0.0446,8.8116 -Kodak,6x6,ldr-rgb-kodak09.png,39.9499,0.0356,0.0148,26.6570 -Kodak,6x6,ldr-rgb-kodak10.png,39.7100,0.0364,0.0142,27.7734 -Kodak,6x6,ldr-rgb-kodak11.png,37.1255,0.0417,0.0232,16.9739 -Kodak,6x6,ldr-rgb-kodak12.png,40.7229,0.0301,0.0122,32.1175 -Kodak,6x6,ldr-rgb-kodak13.png,32.7806,0.0683,0.0483,8.1487 -Kodak,6x6,ldr-rgb-kodak14.png,35.2350,0.0551,0.0359,10.9616 -Kodak,6x6,ldr-rgb-kodak15.png,38.5238,0.0411,0.0205,19.2131 -Kodak,6x6,ldr-rgb-kodak16.png,40.4988,0.0296,0.0122,32.1702 -Kodak,6x6,ldr-rgb-kodak17.png,38.9257,0.0369,0.0148,26.6514 -Kodak,6x6,ldr-rgb-kodak18.png,35.0961,0.0560,0.0317,12.3999 -Kodak,6x6,ldr-rgb-kodak19.png,37.9622,0.0427,0.0202,19.4778 -Kodak,6x6,ldr-rgb-kodak20.png,39.1651,0.0335,0.0167,23.5076 -Kodak,6x6,ldr-rgb-kodak21.png,36.8830,0.0425,0.0244,16.1280 -Kodak,6x6,ldr-rgb-kodak22.png,36.9688,0.0458,0.0244,16.0845 -Kodak,6x6,ldr-rgb-kodak23.png,40.0315,0.0335,0.0145,27.2085 -Kodak,6x6,ldr-rgb-kodak24.png,34.7652,0.0515,0.0303,12.9680 -Kodak,8x8,ldr-rgb-kodak01.png,31.3198,0.0661,0.0427,9.2101 -Kodak,8x8,ldr-rgb-kodak02.png,34.8859,0.0456,0.0216,18.1808 -Kodak,8x8,ldr-rgb-kodak03.png,36.5587,0.0369,0.0161,24.3931 -Kodak,8x8,ldr-rgb-kodak04.png,35.1631,0.0468,0.0200,19.6215 -Kodak,8x8,ldr-rgb-kodak05.png,30.2290,0.0824,0.0584,6.7293 -Kodak,8x8,ldr-rgb-kodak06.png,32.8875,0.0528,0.0301,13.0685 -Kodak,8x8,ldr-rgb-kodak07.png,34.9574,0.0480,0.0229,17.1838 -Kodak,8x8,ldr-rgb-kodak08.png,29.9727,0.0918,0.0640,6.1405 -Kodak,8x8,ldr-rgb-kodak09.png,36.0644,0.0426,0.0176,22.3040 -Kodak,8x8,ldr-rgb-kodak10.png,35.8574,0.0427,0.0166,23.7219 -Kodak,8x8,ldr-rgb-kodak11.png,32.9724,0.0519,0.0299,13.1357 -Kodak,8x8,ldr-rgb-kodak12.png,36.6491,0.0370,0.0157,25.0443 -Kodak,8x8,ldr-rgb-kodak13.png,28.2115,0.0954,0.0715,5.5019 -Kodak,8x8,ldr-rgb-kodak14.png,31.4868,0.0689,0.0456,8.6302 -Kodak,8x8,ldr-rgb-kodak15.png,34.9071,0.0469,0.0224,17.5785 -Kodak,8x8,ldr-rgb-kodak16.png,36.0183,0.0390,0.0177,22.2585 -Kodak,8x8,ldr-rgb-kodak17.png,34.8533,0.0454,0.0192,20.4525 -Kodak,8x8,ldr-rgb-kodak18.png,31.2426,0.0677,0.0398,9.8734 -Kodak,8x8,ldr-rgb-kodak19.png,34.0758,0.0519,0.0248,15.8364 -Kodak,8x8,ldr-rgb-kodak20.png,35.2054,0.0403,0.0194,20.2812 -Kodak,8x8,ldr-rgb-kodak21.png,32.7363,0.0530,0.0309,12.7180 -Kodak,8x8,ldr-rgb-kodak22.png,33.4351,0.0525,0.0267,14.7289 -Kodak,8x8,ldr-rgb-kodak23.png,36.4996,0.0376,0.0145,27.1203 -Kodak,8x8,ldr-rgb-kodak24.png,30.8082,0.0638,0.0387,10.1543 -Kodak,12x12,ldr-rgb-kodak01.png,27.1019,0.0619,0.0317,12.4153 -Kodak,12x12,ldr-rgb-kodak02.png,31.0998,0.0423,0.0115,34.2669 -Kodak,12x12,ldr-rgb-kodak03.png,32.6801,0.0379,0.0102,38.4597 -Kodak,12x12,ldr-rgb-kodak04.png,31.5605,0.0435,0.0100,39.3376 -Kodak,12x12,ldr-rgb-kodak05.png,25.8046,0.0693,0.0385,10.2107 -Kodak,12x12,ldr-rgb-kodak06.png,28.6329,0.0522,0.0233,16.9059 -Kodak,12x12,ldr-rgb-kodak07.png,30.8575,0.0453,0.0128,30.7080 -Kodak,12x12,ldr-rgb-kodak08.png,25.3858,0.0812,0.0464,8.4753 -Kodak,12x12,ldr-rgb-kodak09.png,31.8332,0.0430,0.0116,33.9272 -Kodak,12x12,ldr-rgb-kodak10.png,31.5261,0.0452,0.0121,32.5004 -Kodak,12x12,ldr-rgb-kodak11.png,28.9305,0.0471,0.0183,21.5084 -Kodak,12x12,ldr-rgb-kodak12.png,32.2648,0.0382,0.0102,38.3961 -Kodak,12x12,ldr-rgb-kodak13.png,24.3204,0.0844,0.0532,7.3974 -Kodak,12x12,ldr-rgb-kodak14.png,27.5269,0.0553,0.0258,15.2250 -Kodak,12x12,ldr-rgb-kodak15.png,31.2436,0.0452,0.0141,27.7949 -Kodak,12x12,ldr-rgb-kodak16.png,31.4839,0.0401,0.0118,33.2078 -Kodak,12x12,ldr-rgb-kodak17.png,30.8893,0.0461,0.0132,29.8661 -Kodak,12x12,ldr-rgb-kodak18.png,27.4177,0.0595,0.0253,15.5434 -Kodak,12x12,ldr-rgb-kodak19.png,30.1727,0.0509,0.0174,22.5649 -Kodak,12x12,ldr-rgb-kodak20.png,31.0405,0.0412,0.0138,28.5187 -Kodak,12x12,ldr-rgb-kodak21.png,28.7196,0.0517,0.0225,17.4531 -Kodak,12x12,ldr-rgb-kodak22.png,29.8238,0.0460,0.0142,27.7109 -Kodak,12x12,ldr-rgb-kodak23.png,32.5185,0.0401,0.0106,36.9426 -Kodak,12x12,ldr-rgb-kodak24.png,26.7652,0.0613,0.0296,13.2813 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 8192a51..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,44.5072,0.0328,0.0160,24.5961 -Kodak,4x4,ldr-rgb-kodak02.png,43.8025,0.0379,0.0202,19.4643 -Kodak,4x4,ldr-rgb-kodak03.png,46.0406,0.0281,0.0132,29.7439 -Kodak,4x4,ldr-rgb-kodak04.png,44.1429,0.0394,0.0189,20.8338 -Kodak,4x4,ldr-rgb-kodak05.png,40.9879,0.0425,0.0247,15.8875 -Kodak,4x4,ldr-rgb-kodak06.png,44.4296,0.0323,0.0162,24.2907 -Kodak,4x4,ldr-rgb-kodak07.png,44.6051,0.0362,0.0167,23.5600 -Kodak,4x4,ldr-rgb-kodak08.png,41.5000,0.0468,0.0254,15.4797 -Kodak,4x4,ldr-rgb-kodak09.png,45.9005,0.0316,0.0128,30.6248 -Kodak,4x4,ldr-rgb-kodak10.png,45.6663,0.0337,0.0135,29.0476 -Kodak,4x4,ldr-rgb-kodak11.png,43.8292,0.0340,0.0179,21.9245 -Kodak,4x4,ldr-rgb-kodak12.png,46.4729,0.0281,0.0127,30.9495 -Kodak,4x4,ldr-rgb-kodak13.png,41.1509,0.0425,0.0249,15.7873 -Kodak,4x4,ldr-rgb-kodak14.png,41.0931,0.0370,0.0202,19.5087 -Kodak,4x4,ldr-rgb-kodak15.png,44.1027,0.0373,0.0190,20.7207 -Kodak,4x4,ldr-rgb-kodak16.png,47.0422,0.0273,0.0120,32.6723 -Kodak,4x4,ldr-rgb-kodak17.png,45.4973,0.0326,0.0125,31.4200 -Kodak,4x4,ldr-rgb-kodak18.png,41.2449,0.0468,0.0253,15.5427 -Kodak,4x4,ldr-rgb-kodak19.png,44.5301,0.0365,0.0157,24.9870 -Kodak,4x4,ldr-rgb-kodak20.png,45.8602,0.0285,0.0137,28.6520 -Kodak,4x4,ldr-rgb-kodak21.png,44.2614,0.0325,0.0164,23.9316 -Kodak,4x4,ldr-rgb-kodak22.png,42.7742,0.0410,0.0216,18.2288 -Kodak,4x4,ldr-rgb-kodak23.png,45.2565,0.0320,0.0153,25.7103 -Kodak,4x4,ldr-rgb-kodak24.png,41.2205,0.0400,0.0210,18.7183 -Kodak,5x5,ldr-rgb-kodak01.png,39.3652,0.0351,0.0174,22.6221 -Kodak,5x5,ldr-rgb-kodak02.png,40.3762,0.0342,0.0155,25.3753 -Kodak,5x5,ldr-rgb-kodak03.png,42.6004,0.0264,0.0110,35.6429 -Kodak,5x5,ldr-rgb-kodak04.png,40.7711,0.0361,0.0150,26.1274 -Kodak,5x5,ldr-rgb-kodak05.png,36.9823,0.0434,0.0248,15.8773 -Kodak,5x5,ldr-rgb-kodak06.png,40.4008,0.0314,0.0144,27.3429 -Kodak,5x5,ldr-rgb-kodak07.png,41.1154,0.0344,0.0141,27.8998 -Kodak,5x5,ldr-rgb-kodak08.png,37.3666,0.0478,0.0256,15.3330 -Kodak,5x5,ldr-rgb-kodak09.png,42.5422,0.0301,0.0108,36.5618 -Kodak,5x5,ldr-rgb-kodak10.png,42.3455,0.0321,0.0112,35.0714 -Kodak,5x5,ldr-rgb-kodak11.png,40.0401,0.0319,0.0154,25.5336 -Kodak,5x5,ldr-rgb-kodak12.png,43.1448,0.0262,0.0102,38.7061 -Kodak,5x5,ldr-rgb-kodak13.png,36.6876,0.0436,0.0255,15.4221 -Kodak,5x5,ldr-rgb-kodak14.png,37.3962,0.0374,0.0200,19.6559 -Kodak,5x5,ldr-rgb-kodak15.png,40.8535,0.0337,0.0147,26.7638 -Kodak,5x5,ldr-rgb-kodak16.png,43.3795,0.0261,0.0101,38.9824 -Kodak,5x5,ldr-rgb-kodak17.png,41.8560,0.0317,0.0111,35.4475 -Kodak,5x5,ldr-rgb-kodak18.png,37.9129,0.0431,0.0210,18.6810 -Kodak,5x5,ldr-rgb-kodak19.png,40.8503,0.0349,0.0135,29.0200 -Kodak,5x5,ldr-rgb-kodak20.png,42.0160,0.0271,0.0117,33.5476 -Kodak,5x5,ldr-rgb-kodak21.png,40.1806,0.0323,0.0152,25.8134 -Kodak,5x5,ldr-rgb-kodak22.png,39.4506,0.0367,0.0168,23.3806 -Kodak,5x5,ldr-rgb-kodak23.png,42.1119,0.0299,0.0123,31.8576 -Kodak,5x5,ldr-rgb-kodak24.png,37.5517,0.0386,0.0191,20.5863 -Kodak,6x6,ldr-rgb-kodak01.png,35.6562,0.0399,0.0219,17.9706 -Kodak,6x6,ldr-rgb-kodak02.png,38.0339,0.0342,0.0153,25.7071 -Kodak,6x6,ldr-rgb-kodak03.png,40.3032,0.0264,0.0105,37.4136 -Kodak,6x6,ldr-rgb-kodak04.png,38.2918,0.0360,0.0143,27.4553 -Kodak,6x6,ldr-rgb-kodak05.png,34.0896,0.0460,0.0276,14.2258 -Kodak,6x6,ldr-rgb-kodak06.png,37.2222,0.0334,0.0162,24.2397 -Kodak,6x6,ldr-rgb-kodak07.png,38.6336,0.0348,0.0142,27.6969 -Kodak,6x6,ldr-rgb-kodak08.png,34.2253,0.0505,0.0285,13.8029 -Kodak,6x6,ldr-rgb-kodak09.png,39.7573,0.0311,0.0112,35.1589 -Kodak,6x6,ldr-rgb-kodak10.png,39.5669,0.0325,0.0112,34.9562 -Kodak,6x6,ldr-rgb-kodak11.png,36.9968,0.0335,0.0164,24.0292 -Kodak,6x6,ldr-rgb-kodak12.png,40.5658,0.0262,0.0101,39.1035 -Kodak,6x6,ldr-rgb-kodak13.png,32.7154,0.0511,0.0324,12.1506 -Kodak,6x6,ldr-rgb-kodak14.png,34.8624,0.0394,0.0213,18.4393 -Kodak,6x6,ldr-rgb-kodak15.png,38.3699,0.0341,0.0148,26.4917 -Kodak,6x6,ldr-rgb-kodak16.png,40.4581,0.0266,0.0103,38.1801 -Kodak,6x6,ldr-rgb-kodak17.png,38.8420,0.0327,0.0118,33.4537 -Kodak,6x6,ldr-rgb-kodak18.png,35.0034,0.0449,0.0224,17.5152 -Kodak,6x6,ldr-rgb-kodak19.png,37.8298,0.0371,0.0154,25.5170 -Kodak,6x6,ldr-rgb-kodak20.png,39.0123,0.0280,0.0125,31.4626 -Kodak,6x6,ldr-rgb-kodak21.png,36.8075,0.0343,0.0173,22.7674 -Kodak,6x6,ldr-rgb-kodak22.png,36.8498,0.0372,0.0173,22.7266 -Kodak,6x6,ldr-rgb-kodak23.png,39.8307,0.0290,0.0113,34.8410 -Kodak,6x6,ldr-rgb-kodak24.png,34.6916,0.0408,0.0209,18.8195 -Kodak,8x8,ldr-rgb-kodak01.png,31.1792,0.0521,0.0304,12.9364 -Kodak,8x8,ldr-rgb-kodak02.png,34.7811,0.0387,0.0164,24.0058 -Kodak,8x8,ldr-rgb-kodak03.png,36.4262,0.0319,0.0125,31.4050 -Kodak,8x8,ldr-rgb-kodak04.png,35.0547,0.0404,0.0155,25.4328 -Kodak,8x8,ldr-rgb-kodak05.png,30.0205,0.0602,0.0379,10.3641 -Kodak,8x8,ldr-rgb-kodak06.png,32.7989,0.0429,0.0223,17.6226 -Kodak,8x8,ldr-rgb-kodak07.png,34.8360,0.0412,0.0173,22.6675 -Kodak,8x8,ldr-rgb-kodak08.png,29.7069,0.0665,0.0407,9.6723 -Kodak,8x8,ldr-rgb-kodak09.png,35.8914,0.0371,0.0137,28.7459 -Kodak,8x8,ldr-rgb-kodak10.png,35.7051,0.0378,0.0132,29.8208 -Kodak,8x8,ldr-rgb-kodak11.png,32.8451,0.0417,0.0212,18.5384 -Kodak,8x8,ldr-rgb-kodak12.png,36.5111,0.0320,0.0124,31.8109 -Kodak,8x8,ldr-rgb-kodak13.png,28.1364,0.0699,0.0474,8.2901 -Kodak,8x8,ldr-rgb-kodak14.png,31.2591,0.0510,0.0295,13.3374 -Kodak,8x8,ldr-rgb-kodak15.png,34.7599,0.0393,0.0166,23.6552 -Kodak,8x8,ldr-rgb-kodak16.png,35.9616,0.0336,0.0139,28.2100 -Kodak,8x8,ldr-rgb-kodak17.png,34.7164,0.0390,0.0146,26.9920 -Kodak,8x8,ldr-rgb-kodak18.png,31.1666,0.0541,0.0277,14.1822 -Kodak,8x8,ldr-rgb-kodak19.png,33.8904,0.0437,0.0186,21.1692 -Kodak,8x8,ldr-rgb-kodak20.png,35.0191,0.0336,0.0147,26.7222 -Kodak,8x8,ldr-rgb-kodak21.png,32.6198,0.0428,0.0223,17.6313 -Kodak,8x8,ldr-rgb-kodak22.png,33.3242,0.0432,0.0197,19.9560 -Kodak,8x8,ldr-rgb-kodak23.png,36.3894,0.0331,0.0118,33.2165 -Kodak,8x8,ldr-rgb-kodak24.png,30.7268,0.0503,0.0271,14.4868 -Kodak,12x12,ldr-rgb-kodak01.png,26.9930,0.0498,0.0243,16.1710 -Kodak,12x12,ldr-rgb-kodak02.png,31.0354,0.0363,0.0098,39.9851 -Kodak,12x12,ldr-rgb-kodak03.png,32.6215,0.0322,0.0088,44.7186 -Kodak,12x12,ldr-rgb-kodak04.png,31.4774,0.0377,0.0084,46.8608 -Kodak,12x12,ldr-rgb-kodak05.png,25.6941,0.0547,0.0286,13.7580 -Kodak,12x12,ldr-rgb-kodak06.png,28.4895,0.0430,0.0184,21.3938 -Kodak,12x12,ldr-rgb-kodak07.png,30.8016,0.0389,0.0107,36.5983 -Kodak,12x12,ldr-rgb-kodak08.png,25.2157,0.0633,0.0335,11.7333 -Kodak,12x12,ldr-rgb-kodak09.png,31.6339,0.0370,0.0095,41.1792 -Kodak,12x12,ldr-rgb-kodak10.png,31.4567,0.0389,0.0100,39.1843 -Kodak,12x12,ldr-rgb-kodak11.png,28.8572,0.0389,0.0142,27.6579 -Kodak,12x12,ldr-rgb-kodak12.png,32.1857,0.0327,0.0085,46.0342 -Kodak,12x12,ldr-rgb-kodak13.png,24.2396,0.0644,0.0377,10.4309 -Kodak,12x12,ldr-rgb-kodak14.png,27.4380,0.0445,0.0190,20.7153 -Kodak,12x12,ldr-rgb-kodak15.png,31.1533,0.0382,0.0114,34.5744 -Kodak,12x12,ldr-rgb-kodak16.png,31.3620,0.0338,0.0100,39.3770 -Kodak,12x12,ldr-rgb-kodak17.png,30.8364,0.0395,0.0106,36.9534 -Kodak,12x12,ldr-rgb-kodak18.png,27.3672,0.0491,0.0189,20.8062 -Kodak,12x12,ldr-rgb-kodak19.png,29.8648,0.0431,0.0139,28.2278 -Kodak,12x12,ldr-rgb-kodak20.png,30.9381,0.0347,0.0113,34.8380 -Kodak,12x12,ldr-rgb-kodak21.png,28.6166,0.0418,0.0173,22.6847 -Kodak,12x12,ldr-rgb-kodak22.png,29.7245,0.0392,0.0115,34.1188 -Kodak,12x12,ldr-rgb-kodak23.png,32.4842,0.0344,0.0091,43.2958 -Kodak,12x12,ldr-rgb-kodak24.png,26.6937,0.0492,0.0217,18.0872 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 25297c3..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.2910,0.1376,0.1193,3.2949 -Kodak,4x4,ldr-rgb-kodak02.png,45.3499,0.1867,0.1671,2.3533 -Kodak,4x4,ldr-rgb-kodak03.png,47.6132,0.1002,0.0834,4.7169 -Kodak,4x4,ldr-rgb-kodak04.png,45.4289,0.1508,0.1283,3.0637 -Kodak,4x4,ldr-rgb-kodak05.png,42.1296,0.1729,0.1538,2.5568 -Kodak,4x4,ldr-rgb-kodak06.png,45.1555,0.1312,0.1133,3.4697 -Kodak,4x4,ldr-rgb-kodak07.png,45.9745,0.1280,0.1065,3.6933 -Kodak,4x4,ldr-rgb-kodak08.png,42.5130,0.1922,0.1693,2.3222 -Kodak,4x4,ldr-rgb-kodak09.png,47.1616,0.1495,0.1287,3.0564 -Kodak,4x4,ldr-rgb-kodak10.png,46.8287,0.1543,0.1319,2.9816 -Kodak,4x4,ldr-rgb-kodak11.png,44.8668,0.1486,0.1307,3.0075 -Kodak,4x4,ldr-rgb-kodak12.png,47.9301,0.1128,0.0956,4.1114 -Kodak,4x4,ldr-rgb-kodak13.png,41.6152,0.1479,0.1284,3.0627 -Kodak,4x4,ldr-rgb-kodak14.png,42.6269,0.1601,0.1415,2.7798 -Kodak,4x4,ldr-rgb-kodak15.png,45.4386,0.1330,0.1132,3.4747 -Kodak,4x4,ldr-rgb-kodak16.png,47.8565,0.1150,0.0979,4.0181 -Kodak,4x4,ldr-rgb-kodak17.png,46.2901,0.1329,0.1109,3.5452 -Kodak,4x4,ldr-rgb-kodak18.png,41.9927,0.1953,0.1717,2.2907 -Kodak,4x4,ldr-rgb-kodak19.png,45.3392,0.1592,0.1366,2.8785 -Kodak,4x4,ldr-rgb-kodak20.png,46.8869,0.0973,0.0808,4.8669 -Kodak,4x4,ldr-rgb-kodak21.png,45.1510,0.1574,0.1395,2.8195 -Kodak,4x4,ldr-rgb-kodak22.png,43.7746,0.1958,0.1746,2.2527 -Kodak,4x4,ldr-rgb-kodak23.png,46.8184,0.1507,0.1319,2.9815 -Kodak,4x4,ldr-rgb-kodak24.png,42.2960,0.1548,0.1344,2.9264 -Kodak,5x5,ldr-rgb-kodak01.png,40.1121,0.1640,0.1439,2.7334 -Kodak,5x5,ldr-rgb-kodak02.png,41.6953,0.1737,0.1524,2.5802 -Kodak,5x5,ldr-rgb-kodak03.png,44.0360,0.0823,0.0642,6.1210 -Kodak,5x5,ldr-rgb-kodak04.png,42.0560,0.1377,0.1137,3.4571 -Kodak,5x5,ldr-rgb-kodak05.png,37.9816,0.1895,0.1687,2.3313 -Kodak,5x5,ldr-rgb-kodak06.png,40.9586,0.1310,0.1111,3.5392 -Kodak,5x5,ldr-rgb-kodak07.png,42.4607,0.1132,0.0902,4.3593 -Kodak,5x5,ldr-rgb-kodak08.png,38.3486,0.2082,0.1831,2.1470 -Kodak,5x5,ldr-rgb-kodak09.png,43.8038,0.0976,0.0754,5.2139 -Kodak,5x5,ldr-rgb-kodak10.png,43.4092,0.1107,0.0870,4.5171 -Kodak,5x5,ldr-rgb-kodak11.png,40.8377,0.1498,0.1305,3.0131 -Kodak,5x5,ldr-rgb-kodak12.png,44.3921,0.0839,0.0653,6.0197 -Kodak,5x5,ldr-rgb-kodak13.png,36.9078,0.1742,0.1534,2.5629 -Kodak,5x5,ldr-rgb-kodak14.png,38.6484,0.1702,0.1500,2.6209 -Kodak,5x5,ldr-rgb-kodak15.png,41.8912,0.1283,0.1063,3.6991 -Kodak,5x5,ldr-rgb-kodak16.png,44.1367,0.0939,0.0753,5.2228 -Kodak,5x5,ldr-rgb-kodak17.png,42.5213,0.0990,0.0754,5.2134 -Kodak,5x5,ldr-rgb-kodak18.png,38.3607,0.1872,0.1622,2.4248 -Kodak,5x5,ldr-rgb-kodak19.png,41.6469,0.1292,0.1052,3.7383 -Kodak,5x5,ldr-rgb-kodak20.png,42.9685,0.0913,0.0734,5.3553 -Kodak,5x5,ldr-rgb-kodak21.png,40.7620,0.1289,0.1095,3.5901 -Kodak,5x5,ldr-rgb-kodak22.png,40.2773,0.1765,0.1538,2.5559 -Kodak,5x5,ldr-rgb-kodak23.png,43.5488,0.1111,0.0909,4.3248 -Kodak,5x5,ldr-rgb-kodak24.png,38.1152,0.1524,0.1301,3.0227 -Kodak,6x6,ldr-rgb-kodak01.png,36.1951,0.1720,0.1511,2.6029 -Kodak,6x6,ldr-rgb-kodak02.png,39.0094,0.1369,0.1148,3.4258 -Kodak,6x6,ldr-rgb-kodak03.png,41.3262,0.0704,0.0516,7.6213 -Kodak,6x6,ldr-rgb-kodak04.png,39.3983,0.1184,0.0936,4.1988 -Kodak,6x6,ldr-rgb-kodak05.png,34.7867,0.1868,0.1654,2.3770 -Kodak,6x6,ldr-rgb-kodak06.png,37.6289,0.1179,0.0977,4.0249 -Kodak,6x6,ldr-rgb-kodak07.png,39.7726,0.0977,0.0743,5.2932 -Kodak,6x6,ldr-rgb-kodak08.png,34.9978,0.2092,0.1841,2.1362 -Kodak,6x6,ldr-rgb-kodak09.png,40.8821,0.0769,0.0539,7.2912 -Kodak,6x6,ldr-rgb-kodak10.png,40.5030,0.0822,0.0582,6.7575 -Kodak,6x6,ldr-rgb-kodak11.png,37.5798,0.1261,0.1063,3.7002 -Kodak,6x6,ldr-rgb-kodak12.png,41.4837,0.0666,0.0472,8.3383 -Kodak,6x6,ldr-rgb-kodak13.png,32.8829,0.1934,0.1719,2.2871 -Kodak,6x6,ldr-rgb-kodak14.png,35.8236,0.1575,0.1368,2.8754 -Kodak,6x6,ldr-rgb-kodak15.png,39.1953,0.1195,0.0973,4.0395 -Kodak,6x6,ldr-rgb-kodak16.png,41.0408,0.0774,0.0583,6.7484 -Kodak,6x6,ldr-rgb-kodak17.png,39.4928,0.0838,0.0597,6.5824 -Kodak,6x6,ldr-rgb-kodak18.png,35.3481,0.1665,0.1412,2.7858 -Kodak,6x6,ldr-rgb-kodak19.png,38.5316,0.1174,0.0929,4.2332 -Kodak,6x6,ldr-rgb-kodak20.png,39.7651,0.0841,0.0656,5.9971 -Kodak,6x6,ldr-rgb-kodak21.png,37.1926,0.1151,0.0953,4.1282 -Kodak,6x6,ldr-rgb-kodak22.png,37.4532,0.1499,0.1266,3.1052 -Kodak,6x6,ldr-rgb-kodak23.png,40.9705,0.0815,0.0607,6.4768 -Kodak,6x6,ldr-rgb-kodak24.png,35.0426,0.1379,0.1147,3.4270 -Kodak,8x8,ldr-rgb-kodak01.png,31.8012,0.2348,0.2104,1.8692 -Kodak,8x8,ldr-rgb-kodak02.png,35.7606,0.1367,0.1110,3.5434 -Kodak,8x8,ldr-rgb-kodak03.png,37.7459,0.0863,0.0639,6.1546 -Kodak,8x8,ldr-rgb-kodak04.png,36.0605,0.1334,0.1049,3.7493 -Kodak,8x8,ldr-rgb-kodak05.png,30.7416,0.2430,0.2182,1.8022 -Kodak,8x8,ldr-rgb-kodak06.png,33.4352,0.1512,0.1274,3.0857 -Kodak,8x8,ldr-rgb-kodak07.png,36.1304,0.1157,0.0884,4.4500 -Kodak,8x8,ldr-rgb-kodak08.png,30.5708,0.2448,0.2163,1.8181 -Kodak,8x8,ldr-rgb-kodak09.png,37.2646,0.0890,0.0625,6.2953 -Kodak,8x8,ldr-rgb-kodak10.png,36.9159,0.0926,0.0647,6.0747 -Kodak,8x8,ldr-rgb-kodak11.png,33.6569,0.1495,0.1257,3.1270 -Kodak,8x8,ldr-rgb-kodak12.png,37.8259,0.0826,0.0597,6.5879 -Kodak,8x8,ldr-rgb-kodak13.png,28.3927,0.2704,0.2454,1.6022 -Kodak,8x8,ldr-rgb-kodak14.png,32.1340,0.1937,0.1695,2.3197 -Kodak,8x8,ldr-rgb-kodak15.png,35.8359,0.1224,0.0965,4.0750 -Kodak,8x8,ldr-rgb-kodak16.png,37.0213,0.0968,0.0739,5.3229 -Kodak,8x8,ldr-rgb-kodak17.png,35.6807,0.1028,0.0749,5.2514 -Kodak,8x8,ldr-rgb-kodak18.png,31.5529,0.1948,0.1652,2.3799 -Kodak,8x8,ldr-rgb-kodak19.png,34.7649,0.1419,0.1133,3.4707 -Kodak,8x8,ldr-rgb-kodak20.png,35.8945,0.1045,0.0825,4.7667 -Kodak,8x8,ldr-rgb-kodak21.png,33.1150,0.1486,0.1246,3.1567 -Kodak,8x8,ldr-rgb-kodak22.png,34.0244,0.1634,0.1366,2.8782 -Kodak,8x8,ldr-rgb-kodak23.png,37.6470,0.0842,0.0599,6.5653 -Kodak,8x8,ldr-rgb-kodak24.png,31.1140,0.1710,0.1440,2.7304 -Kodak,12x12,ldr-rgb-kodak01.png,27.7578,0.2518,0.2191,1.7948 -Kodak,12x12,ldr-rgb-kodak02.png,32.4621,0.1012,0.0677,5.8044 -Kodak,12x12,ldr-rgb-kodak03.png,33.7766,0.0822,0.0512,7.6758 -Kodak,12x12,ldr-rgb-kodak04.png,32.4443,0.0964,0.0598,6.5726 -Kodak,12x12,ldr-rgb-kodak05.png,26.3986,0.2678,0.2345,1.6772 -Kodak,12x12,ldr-rgb-kodak06.png,29.3737,0.1622,0.1302,3.0202 -Kodak,12x12,ldr-rgb-kodak07.png,32.0414,0.1160,0.0805,4.8853 -Kodak,12x12,ldr-rgb-kodak08.png,26.0600,0.2698,0.2329,1.6884 -Kodak,12x12,ldr-rgb-kodak09.png,33.0989,0.0882,0.0531,7.4020 -Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0894,0.0533,7.3757 -Kodak,12x12,ldr-rgb-kodak11.png,29.7433,0.1448,0.1126,3.4914 -Kodak,12x12,ldr-rgb-kodak12.png,33.8819,0.0779,0.0469,8.3881 -Kodak,12x12,ldr-rgb-kodak13.png,24.5282,0.3059,0.2723,1.4443 -Kodak,12x12,ldr-rgb-kodak14.png,28.4176,0.1936,0.1607,2.4466 -Kodak,12x12,ldr-rgb-kodak15.png,32.2342,0.1105,0.0764,5.1475 -Kodak,12x12,ldr-rgb-kodak16.png,32.9807,0.0869,0.0556,7.0767 -Kodak,12x12,ldr-rgb-kodak17.png,31.7805,0.0969,0.0608,6.4689 -Kodak,12x12,ldr-rgb-kodak18.png,27.7783,0.1927,0.1553,2.5324 -Kodak,12x12,ldr-rgb-kodak19.png,30.8882,0.1252,0.0884,4.4483 -Kodak,12x12,ldr-rgb-kodak20.png,31.8562,0.0952,0.0649,6.0568 -Kodak,12x12,ldr-rgb-kodak21.png,29.1771,0.1726,0.1406,2.7961 -Kodak,12x12,ldr-rgb-kodak22.png,30.4983,0.1351,0.1001,3.9269 -Kodak,12x12,ldr-rgb-kodak23.png,33.5464,0.0749,0.0423,9.3067 -Kodak,12x12,ldr-rgb-kodak24.png,27.0976,0.1732,0.1386,2.8365 diff --git a/Test/Images/Kodak/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/Kodak/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 4264ae8..0000000 --- a/Test/Images/Kodak/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,121 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Kodak,4x4,ldr-rgb-kodak01.png,45.4944,0.3616,0.3424,1.1485 -Kodak,4x4,ldr-rgb-kodak02.png,45.6493,0.4293,0.4095,0.9603 -Kodak,4x4,ldr-rgb-kodak03.png,47.9884,0.3696,0.3527,1.1150 -Kodak,4x4,ldr-rgb-kodak04.png,45.6562,0.4057,0.3826,1.0278 -Kodak,4x4,ldr-rgb-kodak05.png,42.4063,0.4001,0.3807,1.0328 -Kodak,4x4,ldr-rgb-kodak06.png,45.3572,0.3604,0.3420,1.1496 -Kodak,4x4,ldr-rgb-kodak07.png,46.3419,0.4036,0.3822,1.0288 -Kodak,4x4,ldr-rgb-kodak08.png,42.8054,0.4300,0.4066,0.9672 -Kodak,4x4,ldr-rgb-kodak09.png,47.4208,0.4108,0.3897,1.0090 -Kodak,4x4,ldr-rgb-kodak10.png,47.0603,0.4109,0.3885,1.0120 -Kodak,4x4,ldr-rgb-kodak11.png,45.1121,0.3790,0.3608,1.0900 -Kodak,4x4,ldr-rgb-kodak12.png,48.2457,0.3793,0.3622,1.0857 -Kodak,4x4,ldr-rgb-kodak13.png,41.7174,0.3648,0.3450,1.1399 -Kodak,4x4,ldr-rgb-kodak14.png,42.9405,0.3901,0.3710,1.0599 -Kodak,4x4,ldr-rgb-kodak15.png,45.7858,0.3883,0.3682,1.0680 -Kodak,4x4,ldr-rgb-kodak16.png,48.0652,0.3751,0.3577,1.0993 -Kodak,4x4,ldr-rgb-kodak17.png,46.4610,0.3937,0.3716,1.0583 -Kodak,4x4,ldr-rgb-kodak18.png,42.1541,0.4274,0.4037,0.9739 -Kodak,4x4,ldr-rgb-kodak19.png,45.5439,0.4082,0.3855,1.0200 -Kodak,4x4,ldr-rgb-kodak20.png,47.1284,0.2580,0.2415,1.6282 -Kodak,4x4,ldr-rgb-kodak21.png,45.3018,0.3986,0.3800,1.0347 -Kodak,4x4,ldr-rgb-kodak22.png,43.9797,0.4354,0.4141,0.9495 -Kodak,4x4,ldr-rgb-kodak23.png,47.1533,0.4225,0.4036,0.9743 -Kodak,4x4,ldr-rgb-kodak24.png,42.5030,0.3923,0.3716,1.0583 -Kodak,5x5,ldr-rgb-kodak01.png,40.2326,0.4602,0.4398,0.8940 -Kodak,5x5,ldr-rgb-kodak02.png,41.9976,0.5338,0.5127,0.7670 -Kodak,5x5,ldr-rgb-kodak03.png,44.3239,0.4411,0.4229,0.9298 -Kodak,5x5,ldr-rgb-kodak04.png,42.2394,0.4885,0.4642,0.8471 -Kodak,5x5,ldr-rgb-kodak05.png,38.1756,0.5028,0.4821,0.8157 -Kodak,5x5,ldr-rgb-kodak06.png,41.0844,0.4381,0.4182,0.9402 -Kodak,5x5,ldr-rgb-kodak07.png,42.7249,0.4815,0.4584,0.8577 -Kodak,5x5,ldr-rgb-kodak08.png,38.5334,0.5155,0.4908,0.8012 -Kodak,5x5,ldr-rgb-kodak09.png,44.0288,0.4842,0.4618,0.8515 -Kodak,5x5,ldr-rgb-kodak10.png,43.5935,0.4895,0.4657,0.8443 -Kodak,5x5,ldr-rgb-kodak11.png,40.9987,0.4578,0.4385,0.8966 -Kodak,5x5,ldr-rgb-kodak12.png,44.5960,0.4503,0.4312,0.9119 -Kodak,5x5,ldr-rgb-kodak13.png,36.9510,0.4522,0.4308,0.9128 -Kodak,5x5,ldr-rgb-kodak14.png,38.8797,0.4807,0.4605,0.8539 -Kodak,5x5,ldr-rgb-kodak15.png,42.1246,0.4597,0.4382,0.8973 -Kodak,5x5,ldr-rgb-kodak16.png,44.2686,0.4487,0.4301,0.9142 -Kodak,5x5,ldr-rgb-kodak17.png,42.6009,0.4744,0.4506,0.8727 -Kodak,5x5,ldr-rgb-kodak18.png,38.4550,0.5223,0.4972,0.7908 -Kodak,5x5,ldr-rgb-kodak19.png,41.7719,0.5023,0.4783,0.8221 -Kodak,5x5,ldr-rgb-kodak20.png,43.2708,0.3156,0.2978,1.3203 -Kodak,5x5,ldr-rgb-kodak21.png,40.8630,0.4953,0.4759,0.8263 -Kodak,5x5,ldr-rgb-kodak22.png,40.4255,0.5340,0.5117,0.7685 -Kodak,5x5,ldr-rgb-kodak23.png,43.8841,0.5193,0.4990,0.7881 -Kodak,5x5,ldr-rgb-kodak24.png,38.2272,0.4763,0.4540,0.8660 -Kodak,6x6,ldr-rgb-kodak01.png,36.3116,0.5504,0.5295,0.7426 -Kodak,6x6,ldr-rgb-kodak02.png,39.3780,0.6270,0.6044,0.6506 -Kodak,6x6,ldr-rgb-kodak03.png,41.7331,0.3903,0.3715,1.0584 -Kodak,6x6,ldr-rgb-kodak04.png,39.6521,0.5495,0.5243,0.7500 -Kodak,6x6,ldr-rgb-kodak05.png,34.9741,0.5935,0.5717,0.6878 -Kodak,6x6,ldr-rgb-kodak06.png,37.7401,0.4948,0.4745,0.8287 -Kodak,6x6,ldr-rgb-kodak07.png,40.1032,0.4495,0.4258,0.9234 -Kodak,6x6,ldr-rgb-kodak08.png,35.1660,0.6030,0.5775,0.6809 -Kodak,6x6,ldr-rgb-kodak09.png,41.2613,0.5508,0.5277,0.7451 -Kodak,6x6,ldr-rgb-kodak10.png,40.8141,0.5634,0.5389,0.7296 -Kodak,6x6,ldr-rgb-kodak11.png,37.7541,0.5065,0.4863,0.8087 -Kodak,6x6,ldr-rgb-kodak12.png,41.8249,0.4748,0.4546,0.8650 -Kodak,6x6,ldr-rgb-kodak13.png,32.9256,0.5560,0.5341,0.7362 -Kodak,6x6,ldr-rgb-kodak14.png,36.0210,0.5756,0.5549,0.7086 -Kodak,6x6,ldr-rgb-kodak15.png,39.4514,0.4663,0.4442,0.8853 -Kodak,6x6,ldr-rgb-kodak16.png,41.2290,0.4600,0.4405,0.8926 -Kodak,6x6,ldr-rgb-kodak17.png,39.6521,0.5310,0.5059,0.7773 -Kodak,6x6,ldr-rgb-kodak18.png,35.4328,0.6295,0.6039,0.6512 -Kodak,6x6,ldr-rgb-kodak19.png,38.6954,0.5947,0.5698,0.6902 -Kodak,6x6,ldr-rgb-kodak20.png,40.0953,0.3685,0.3494,1.1254 -Kodak,6x6,ldr-rgb-kodak21.png,37.3344,0.5848,0.5645,0.6966 -Kodak,6x6,ldr-rgb-kodak22.png,37.6231,0.6351,0.6120,0.6426 -Kodak,6x6,ldr-rgb-kodak23.png,41.4033,0.5453,0.5245,0.7497 -Kodak,6x6,ldr-rgb-kodak24.png,35.1417,0.5210,0.4982,0.7893 -Kodak,8x8,ldr-rgb-kodak01.png,31.9071,0.6763,0.6498,0.6051 -Kodak,8x8,ldr-rgb-kodak02.png,36.1354,0.5901,0.5632,0.6982 -Kodak,8x8,ldr-rgb-kodak03.png,38.1744,0.3113,0.2871,1.3698 -Kodak,8x8,ldr-rgb-kodak04.png,36.3637,0.5037,0.4740,0.8295 -Kodak,8x8,ldr-rgb-kodak05.png,30.9009,0.6860,0.6595,0.5963 -Kodak,8x8,ldr-rgb-kodak06.png,33.5749,0.5544,0.5288,0.7436 -Kodak,8x8,ldr-rgb-kodak07.png,36.4888,0.3805,0.3506,1.1214 -Kodak,8x8,ldr-rgb-kodak08.png,30.7484,0.7355,0.7047,0.5580 -Kodak,8x8,ldr-rgb-kodak09.png,37.5499,0.3555,0.3274,1.2010 -Kodak,8x8,ldr-rgb-kodak10.png,37.2288,0.3953,0.3659,1.0748 -Kodak,8x8,ldr-rgb-kodak11.png,33.8276,0.6013,0.5759,0.6828 -Kodak,8x8,ldr-rgb-kodak12.png,38.2490,0.3712,0.3465,1.1350 -Kodak,8x8,ldr-rgb-kodak13.png,28.4502,0.7471,0.7205,0.5458 -Kodak,8x8,ldr-rgb-kodak14.png,32.3258,0.6828,0.6571,0.5984 -Kodak,8x8,ldr-rgb-kodak15.png,36.0605,0.4675,0.4400,0.8938 -Kodak,8x8,ldr-rgb-kodak16.png,37.2636,0.4405,0.4154,0.9466 -Kodak,8x8,ldr-rgb-kodak17.png,35.8722,0.4248,0.3955,0.9941 -Kodak,8x8,ldr-rgb-kodak18.png,31.6495,0.6972,0.6661,0.5903 -Kodak,8x8,ldr-rgb-kodak19.png,34.9142,0.4758,0.4457,0.8823 -Kodak,8x8,ldr-rgb-kodak20.png,36.1470,0.3640,0.3400,1.1564 -Kodak,8x8,ldr-rgb-kodak21.png,33.2221,0.4870,0.4617,0.8517 -Kodak,8x8,ldr-rgb-kodak22.png,34.2197,0.6164,0.5883,0.6684 -Kodak,8x8,ldr-rgb-kodak23.png,38.1768,0.3478,0.3221,1.2209 -Kodak,8x8,ldr-rgb-kodak24.png,31.2175,0.5629,0.5346,0.7356 -Kodak,12x12,ldr-rgb-kodak01.png,27.9058,0.7718,0.7362,0.5341 -Kodak,12x12,ldr-rgb-kodak02.png,32.9642,0.5152,0.4778,0.8230 -Kodak,12x12,ldr-rgb-kodak03.png,34.4219,0.3155,0.2822,1.3935 -Kodak,12x12,ldr-rgb-kodak04.png,32.9599,0.4600,0.4208,0.9345 -Kodak,12x12,ldr-rgb-kodak05.png,26.5927,0.8084,0.7720,0.5093 -Kodak,12x12,ldr-rgb-kodak06.png,29.5304,0.5796,0.5441,0.7227 -Kodak,12x12,ldr-rgb-kodak07.png,32.6109,0.3845,0.3464,1.1352 -Kodak,12x12,ldr-rgb-kodak08.png,26.2744,0.8005,0.7603,0.5172 -Kodak,12x12,ldr-rgb-kodak09.png,33.6251,0.3488,0.3109,1.2647 -Kodak,12x12,ldr-rgb-kodak10.png,32.9833,0.3465,0.3076,1.2784 -Kodak,12x12,ldr-rgb-kodak11.png,30.0468,0.5686,0.5340,0.7364 -Kodak,12x12,ldr-rgb-kodak12.png,34.4395,0.3089,0.2746,1.4321 -Kodak,12x12,ldr-rgb-kodak13.png,24.5820,0.9118,0.8757,0.4491 -Kodak,12x12,ldr-rgb-kodak14.png,28.6287,0.7280,0.6922,0.5681 -Kodak,12x12,ldr-rgb-kodak15.png,32.7197,0.4445,0.4069,0.9663 -Kodak,12x12,ldr-rgb-kodak16.png,33.3355,0.4265,0.3920,1.0031 -Kodak,12x12,ldr-rgb-kodak17.png,32.1409,0.3887,0.3499,1.1237 -Kodak,12x12,ldr-rgb-kodak18.png,27.9217,0.6959,0.6559,0.5995 -Kodak,12x12,ldr-rgb-kodak19.png,31.1006,0.5518,0.5125,0.7672 -Kodak,12x12,ldr-rgb-kodak20.png,32.1470,0.4064,0.3727,1.0550 -Kodak,12x12,ldr-rgb-kodak21.png,29.3170,0.5272,0.4916,0.7998 -Kodak,12x12,ldr-rgb-kodak22.png,30.7805,0.5966,0.5587,0.7037 -Kodak,12x12,ldr-rgb-kodak23.png,34.3635,0.2927,0.2568,1.5311 -Kodak,12x12,ldr-rgb-kodak24.png,27.2253,0.6296,0.5920,0.6642 diff --git a/Test/Images/Kodak/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/Kodak/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..b846389 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.8820,0.0302,0.0138,28.4156 +Kodak,4x4,ldr-rgb-kodak02.png,44.2873,0.0376,0.0205,19.1439 +Kodak,4x4,ldr-rgb-kodak03.png,46.7875,0.0267,0.0112,35.1716 +Kodak,4x4,ldr-rgb-kodak04.png,44.6627,0.0353,0.0181,21.7392 +Kodak,4x4,ldr-rgb-kodak05.png,41.6532,0.0446,0.0275,14.3018 +Kodak,4x4,ldr-rgb-kodak06.png,44.7930,0.0295,0.0136,28.8243 +Kodak,4x4,ldr-rgb-kodak07.png,45.1555,0.0325,0.0154,25.4524 +Kodak,4x4,ldr-rgb-kodak08.png,42.1261,0.0466,0.0284,13.8219 +Kodak,4x4,ldr-rgb-kodak09.png,46.3501,0.0272,0.0102,38.5848 +Kodak,4x4,ldr-rgb-kodak10.png,46.1138,0.0282,0.0108,36.3051 +Kodak,4x4,ldr-rgb-kodak11.png,44.3024,0.0328,0.0168,23.3766 +Kodak,4x4,ldr-rgb-kodak12.png,47.1128,0.0256,0.0100,39.2430 +Kodak,4x4,ldr-rgb-kodak13.png,41.4830,0.0407,0.0234,16.8336 +Kodak,4x4,ldr-rgb-kodak14.png,41.9274,0.0395,0.0228,17.2631 +Kodak,4x4,ldr-rgb-kodak15.png,44.7388,0.0367,0.0198,19.8875 +Kodak,4x4,ldr-rgb-kodak16.png,47.2478,0.0239,0.0086,45.5737 +Kodak,4x4,ldr-rgb-kodak17.png,45.8440,0.0270,0.0098,39.9939 +Kodak,4x4,ldr-rgb-kodak18.png,41.6843,0.0451,0.0271,14.5173 +Kodak,4x4,ldr-rgb-kodak19.png,44.8511,0.0308,0.0135,29.1766 +Kodak,4x4,ldr-rgb-kodak20.png,46.4186,0.0272,0.0115,34.3026 +Kodak,4x4,ldr-rgb-kodak21.png,44.6411,0.0303,0.0142,27.7342 +Kodak,4x4,ldr-rgb-kodak22.png,43.2351,0.0402,0.0227,17.3115 +Kodak,4x4,ldr-rgb-kodak23.png,45.6659,0.0301,0.0136,28.8768 +Kodak,4x4,ldr-rgb-kodak24.png,41.9807,0.0393,0.0219,17.9173 +Kodak,5x5,ldr-rgb-kodak01.png,39.6135,0.0292,0.0127,31.0013 +Kodak,5x5,ldr-rgb-kodak02.png,40.6534,0.0301,0.0126,31.2669 +Kodak,5x5,ldr-rgb-kodak03.png,43.0540,0.0244,0.0086,45.5851 +Kodak,5x5,ldr-rgb-kodak04.png,41.2613,0.0293,0.0116,33.9097 +Kodak,5x5,ldr-rgb-kodak05.png,37.4541,0.0396,0.0223,17.6108 +Kodak,5x5,ldr-rgb-kodak06.png,40.5884,0.0265,0.0104,37.9884 +Kodak,5x5,ldr-rgb-kodak07.png,41.4931,0.0284,0.0110,35.8318 +Kodak,5x5,ldr-rgb-kodak08.png,37.7792,0.0407,0.0223,17.6432 +Kodak,5x5,ldr-rgb-kodak09.png,42.9214,0.0248,0.0074,52.7867 +Kodak,5x5,ldr-rgb-kodak10.png,42.6313,0.0253,0.0079,49.7502 +Kodak,5x5,ldr-rgb-kodak11.png,40.3040,0.0285,0.0122,32.1645 +Kodak,5x5,ldr-rgb-kodak12.png,43.4157,0.0230,0.0071,55.5777 +Kodak,5x5,ldr-rgb-kodak13.png,36.8276,0.0364,0.0190,20.6999 +Kodak,5x5,ldr-rgb-kodak14.png,38.0242,0.0370,0.0202,19.4739 +Kodak,5x5,ldr-rgb-kodak15.png,41.1917,0.0290,0.0122,32.2860 +Kodak,5x5,ldr-rgb-kodak16.png,43.4667,0.0224,0.0065,60.7197 +Kodak,5x5,ldr-rgb-kodak17.png,42.0469,0.0250,0.0074,53.1816 +Kodak,5x5,ldr-rgb-kodak18.png,38.1147,0.0351,0.0171,23.0544 +Kodak,5x5,ldr-rgb-kodak19.png,41.1276,0.0270,0.0093,42.4227 +Kodak,5x5,ldr-rgb-kodak20.png,42.3603,0.0241,0.0083,47.4609 +Kodak,5x5,ldr-rgb-kodak21.png,40.4227,0.0275,0.0112,35.0930 +Kodak,5x5,ldr-rgb-kodak22.png,39.7897,0.0315,0.0137,28.6162 +Kodak,5x5,ldr-rgb-kodak23.png,42.5143,0.0260,0.0092,42.8159 +Kodak,5x5,ldr-rgb-kodak24.png,37.8892,0.0333,0.0159,24.6822 +Kodak,6x6,ldr-rgb-kodak01.png,35.7507,0.0337,0.0177,22.2408 +Kodak,6x6,ldr-rgb-kodak02.png,38.1712,0.0292,0.0124,31.6424 +Kodak,6x6,ldr-rgb-kodak03.png,40.5686,0.0232,0.0080,49.1219 +Kodak,6x6,ldr-rgb-kodak04.png,38.5433,0.0287,0.0115,34.2976 +Kodak,6x6,ldr-rgb-kodak05.png,34.3631,0.0421,0.0255,15.4367 +Kodak,6x6,ldr-rgb-kodak06.png,37.3004,0.0277,0.0122,32.3234 +Kodak,6x6,ldr-rgb-kodak07.png,38.8820,0.0279,0.0111,35.4376 +Kodak,6x6,ldr-rgb-kodak08.png,34.4474,0.0434,0.0253,15.5219 +Kodak,6x6,ldr-rgb-kodak09.png,39.9734,0.0249,0.0085,46.2822 +Kodak,6x6,ldr-rgb-kodak10.png,39.7372,0.0252,0.0083,47.5883 +Kodak,6x6,ldr-rgb-kodak11.png,37.1533,0.0293,0.0135,29.1875 +Kodak,6x6,ldr-rgb-kodak12.png,40.7387,0.0225,0.0072,54.3577 +Kodak,6x6,ldr-rgb-kodak13.png,32.8130,0.0430,0.0259,15.1950 +Kodak,6x6,ldr-rgb-kodak14.png,35.3037,0.0386,0.0222,17.7108 +Kodak,6x6,ldr-rgb-kodak15.png,38.5680,0.0288,0.0120,32.6808 +Kodak,6x6,ldr-rgb-kodak16.png,40.4942,0.0222,0.0070,56.0861 +Kodak,6x6,ldr-rgb-kodak17.png,38.9398,0.0254,0.0084,46.6778 +Kodak,6x6,ldr-rgb-kodak18.png,35.1209,0.0359,0.0181,21.7513 +Kodak,6x6,ldr-rgb-kodak19.png,37.9783,0.0290,0.0117,33.6915 +Kodak,6x6,ldr-rgb-kodak20.png,39.1839,0.0245,0.0093,42.1000 +Kodak,6x6,ldr-rgb-kodak21.png,36.9075,0.0295,0.0136,28.9386 +Kodak,6x6,ldr-rgb-kodak22.png,36.9849,0.0315,0.0143,27.5070 +Kodak,6x6,ldr-rgb-kodak23.png,40.0615,0.0249,0.0085,46.0715 +Kodak,6x6,ldr-rgb-kodak24.png,34.7936,0.0338,0.0166,23.6336 +Kodak,8x8,ldr-rgb-kodak01.png,31.3361,0.0412,0.0251,15.6779 +Kodak,8x8,ldr-rgb-kodak02.png,34.9328,0.0289,0.0122,32.1884 +Kodak,8x8,ldr-rgb-kodak03.png,36.5952,0.0246,0.0090,43.5738 +Kodak,8x8,ldr-rgb-kodak04.png,35.1760,0.0292,0.0118,33.3630 +Kodak,8x8,ldr-rgb-kodak05.png,30.2523,0.0480,0.0309,12.7111 +Kodak,8x8,ldr-rgb-kodak06.png,32.9457,0.0332,0.0176,22.2961 +Kodak,8x8,ldr-rgb-kodak07.png,34.9951,0.0302,0.0132,29.7171 +Kodak,8x8,ldr-rgb-kodak08.png,29.9694,0.0498,0.0317,12.4101 +Kodak,8x8,ldr-rgb-kodak09.png,36.1703,0.0268,0.0098,40.0784 +Kodak,8x8,ldr-rgb-kodak10.png,35.8857,0.0267,0.0093,42.2857 +Kodak,8x8,ldr-rgb-kodak11.png,33.0088,0.0325,0.0165,23.8227 +Kodak,8x8,ldr-rgb-kodak12.png,36.7290,0.0241,0.0087,45.2536 +Kodak,8x8,ldr-rgb-kodak13.png,28.2209,0.0545,0.0371,10.5925 +Kodak,8x8,ldr-rgb-kodak14.png,31.5032,0.0415,0.0251,15.6954 +Kodak,8x8,ldr-rgb-kodak15.png,34.9394,0.0294,0.0123,31.9217 +Kodak,8x8,ldr-rgb-kodak16.png,36.0527,0.0261,0.0107,36.8494 +Kodak,8x8,ldr-rgb-kodak17.png,34.9073,0.0283,0.0107,36.8700 +Kodak,8x8,ldr-rgb-kodak18.png,31.2398,0.0398,0.0218,17.9978 +Kodak,8x8,ldr-rgb-kodak19.png,34.2235,0.0319,0.0143,27.5825 +Kodak,8x8,ldr-rgb-kodak20.png,35.2317,0.0262,0.0107,36.8074 +Kodak,8x8,ldr-rgb-kodak21.png,32.7551,0.0334,0.0174,22.6377 +Kodak,8x8,ldr-rgb-kodak22.png,33.4546,0.0332,0.0157,25.0359 +Kodak,8x8,ldr-rgb-kodak23.png,36.5268,0.0251,0.0084,46.5724 +Kodak,8x8,ldr-rgb-kodak24.png,30.8238,0.0374,0.0201,19.5970 +Kodak,12x12,ldr-rgb-kodak01.png,27.1080,0.0389,0.0210,18.7174 +Kodak,12x12,ldr-rgb-kodak02.png,31.1083,0.0255,0.0068,57.8244 +Kodak,12x12,ldr-rgb-kodak03.png,32.6856,0.0232,0.0059,66.2543 +Kodak,12x12,ldr-rgb-kodak04.png,31.5645,0.0246,0.0056,69.9672 +Kodak,12x12,ldr-rgb-kodak05.png,25.8227,0.0429,0.0241,16.3065 +Kodak,12x12,ldr-rgb-kodak06.png,28.6373,0.0327,0.0148,26.5130 +Kodak,12x12,ldr-rgb-kodak07.png,30.8590,0.0268,0.0079,49.8690 +Kodak,12x12,ldr-rgb-kodak08.png,25.4179,0.0474,0.0274,14.3421 +Kodak,12x12,ldr-rgb-kodak09.png,31.8377,0.0256,0.0067,58.9087 +Kodak,12x12,ldr-rgb-kodak10.png,31.5385,0.0257,0.0066,59.2814 +Kodak,12x12,ldr-rgb-kodak11.png,28.9359,0.0290,0.0112,35.0990 +Kodak,12x12,ldr-rgb-kodak12.png,32.2823,0.0231,0.0057,68.9119 +Kodak,12x12,ldr-rgb-kodak13.png,24.3217,0.0492,0.0302,13.0040 +Kodak,12x12,ldr-rgb-kodak14.png,27.5443,0.0339,0.0159,24.7928 +Kodak,12x12,ldr-rgb-kodak15.png,31.2551,0.0270,0.0084,46.8010 +Kodak,12x12,ldr-rgb-kodak16.png,31.4853,0.0244,0.0073,54.2362 +Kodak,12x12,ldr-rgb-kodak17.png,30.8975,0.0263,0.0072,54.7275 +Kodak,12x12,ldr-rgb-kodak18.png,27.4230,0.0344,0.0149,26.4615 +Kodak,12x12,ldr-rgb-kodak19.png,30.1902,0.0304,0.0110,35.7992 +Kodak,12x12,ldr-rgb-kodak20.png,31.0526,0.0250,0.0080,49.0051 +Kodak,12x12,ldr-rgb-kodak21.png,28.7136,0.0321,0.0144,27.3960 +Kodak,12x12,ldr-rgb-kodak22.png,29.8371,0.0279,0.0088,44.8878 +Kodak,12x12,ldr-rgb-kodak23.png,32.5213,0.0243,0.0059,66.3556 +Kodak,12x12,ldr-rgb-kodak24.png,26.7723,0.0346,0.0153,25.6233 diff --git a/Test/Images/Kodak/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..03d2ef7 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5460,0.0254,0.0099,39.6354 +Kodak,4x4,ldr-rgb-kodak02.png,43.8803,0.0295,0.0133,29.5737 +Kodak,4x4,ldr-rgb-kodak03.png,46.1873,0.0226,0.0080,49.4607 +Kodak,4x4,ldr-rgb-kodak04.png,44.2426,0.0288,0.0119,32.9110 +Kodak,4x4,ldr-rgb-kodak05.png,41.1063,0.0326,0.0163,24.1562 +Kodak,4x4,ldr-rgb-kodak06.png,44.5076,0.0252,0.0098,40.0104 +Kodak,4x4,ldr-rgb-kodak07.png,44.7021,0.0265,0.0103,38.0507 +Kodak,4x4,ldr-rgb-kodak08.png,41.5547,0.0341,0.0167,23.5347 +Kodak,4x4,ldr-rgb-kodak09.png,46.0133,0.0237,0.0076,51.6834 +Kodak,4x4,ldr-rgb-kodak10.png,45.7710,0.0245,0.0080,49.4044 +Kodak,4x4,ldr-rgb-kodak11.png,43.9057,0.0267,0.0113,34.7793 +Kodak,4x4,ldr-rgb-kodak12.png,46.5477,0.0223,0.0075,52.3810 +Kodak,4x4,ldr-rgb-kodak13.png,41.2213,0.0321,0.0156,25.2726 +Kodak,4x4,ldr-rgb-kodak14.png,41.2633,0.0289,0.0134,29.3642 +Kodak,4x4,ldr-rgb-kodak15.png,44.2793,0.0287,0.0125,31.4728 +Kodak,4x4,ldr-rgb-kodak16.png,47.1118,0.0219,0.0071,55.3371 +Kodak,4x4,ldr-rgb-kodak17.png,45.6149,0.0242,0.0074,52.9732 +Kodak,4x4,ldr-rgb-kodak18.png,41.3441,0.0335,0.0162,24.2098 +Kodak,4x4,ldr-rgb-kodak19.png,44.5863,0.0264,0.0095,41.3081 +Kodak,4x4,ldr-rgb-kodak20.png,45.9269,0.0229,0.0082,47.9647 +Kodak,4x4,ldr-rgb-kodak21.png,44.3216,0.0254,0.0100,39.1536 +Kodak,4x4,ldr-rgb-kodak22.png,42.8634,0.0308,0.0141,27.8720 +Kodak,4x4,ldr-rgb-kodak23.png,45.3579,0.0253,0.0096,41.0705 +Kodak,4x4,ldr-rgb-kodak24.png,41.4243,0.0301,0.0134,29.4150 +Kodak,5x5,ldr-rgb-kodak01.png,39.3930,0.0262,0.0105,37.3391 +Kodak,5x5,ldr-rgb-kodak02.png,40.4266,0.0258,0.0096,40.7821 +Kodak,5x5,ldr-rgb-kodak03.png,42.6948,0.0215,0.0067,58.9719 +Kodak,5x5,ldr-rgb-kodak04.png,40.8613,0.0257,0.0090,43.4830 +Kodak,5x5,ldr-rgb-kodak05.png,37.1066,0.0318,0.0155,25.4375 +Kodak,5x5,ldr-rgb-kodak06.png,40.4306,0.0240,0.0086,45.5159 +Kodak,5x5,ldr-rgb-kodak07.png,41.1804,0.0248,0.0085,46.0973 +Kodak,5x5,ldr-rgb-kodak08.png,37.4468,0.0329,0.0158,24.9379 +Kodak,5x5,ldr-rgb-kodak09.png,42.6180,0.0228,0.0064,61.5743 +Kodak,5x5,ldr-rgb-kodak10.png,42.4264,0.0235,0.0066,59.7517 +Kodak,5x5,ldr-rgb-kodak11.png,40.0808,0.0248,0.0093,42.2542 +Kodak,5x5,ldr-rgb-kodak12.png,43.2020,0.0211,0.0060,65.2323 +Kodak,5x5,ldr-rgb-kodak13.png,36.7364,0.0316,0.0149,26.3163 +Kodak,5x5,ldr-rgb-kodak14.png,37.5843,0.0286,0.0129,30.4416 +Kodak,5x5,ldr-rgb-kodak15.png,40.9222,0.0253,0.0090,43.7054 +Kodak,5x5,ldr-rgb-kodak16.png,43.3847,0.0207,0.0059,66.8504 +Kodak,5x5,ldr-rgb-kodak17.png,41.9201,0.0230,0.0064,61.7102 +Kodak,5x5,ldr-rgb-kodak18.png,37.9619,0.0299,0.0126,31.1212 +Kodak,5x5,ldr-rgb-kodak19.png,40.8871,0.0248,0.0080,48.9266 +Kodak,5x5,ldr-rgb-kodak20.png,42.0751,0.0214,0.0068,58.1588 +Kodak,5x5,ldr-rgb-kodak21.png,40.2318,0.0245,0.0091,43.4052 +Kodak,5x5,ldr-rgb-kodak22.png,39.5098,0.0273,0.0103,38.1695 +Kodak,5x5,ldr-rgb-kodak23.png,42.2176,0.0232,0.0074,52.8730 +Kodak,5x5,ldr-rgb-kodak24.png,37.6858,0.0283,0.0114,34.3512 +Kodak,6x6,ldr-rgb-kodak01.png,35.6604,0.0286,0.0134,29.3840 +Kodak,6x6,ldr-rgb-kodak02.png,38.0761,0.0251,0.0093,42.4456 +Kodak,6x6,ldr-rgb-kodak03.png,40.4029,0.0207,0.0062,63.4114 +Kodak,6x6,ldr-rgb-kodak04.png,38.3307,0.0250,0.0086,45.7609 +Kodak,6x6,ldr-rgb-kodak05.png,34.1621,0.0329,0.0169,23.2714 +Kodak,6x6,ldr-rgb-kodak06.png,37.2413,0.0243,0.0095,41.4962 +Kodak,6x6,ldr-rgb-kodak07.png,38.6918,0.0243,0.0083,47.1192 +Kodak,6x6,ldr-rgb-kodak08.png,34.2562,0.0344,0.0173,22.7542 +Kodak,6x6,ldr-rgb-kodak09.png,39.8018,0.0224,0.0066,59.2005 +Kodak,6x6,ldr-rgb-kodak10.png,39.6065,0.0229,0.0066,59.3368 +Kodak,6x6,ldr-rgb-kodak11.png,37.0350,0.0249,0.0099,39.8480 +Kodak,6x6,ldr-rgb-kodak12.png,40.6117,0.0204,0.0059,66.9400 +Kodak,6x6,ldr-rgb-kodak13.png,32.7512,0.0349,0.0187,20.9961 +Kodak,6x6,ldr-rgb-kodak14.png,35.0163,0.0289,0.0136,28.9213 +Kodak,6x6,ldr-rgb-kodak15.png,38.4450,0.0246,0.0088,44.5519 +Kodak,6x6,ldr-rgb-kodak16.png,40.4576,0.0204,0.0060,65.2323 +Kodak,6x6,ldr-rgb-kodak17.png,38.8609,0.0231,0.0068,57.4538 +Kodak,6x6,ldr-rgb-kodak18.png,35.0294,0.0302,0.0132,29.7331 +Kodak,6x6,ldr-rgb-kodak19.png,37.8582,0.0258,0.0092,42.8014 +Kodak,6x6,ldr-rgb-kodak20.png,39.0412,0.0217,0.0072,54.4169 +Kodak,6x6,ldr-rgb-kodak21.png,36.8328,0.0253,0.0102,38.5136 +Kodak,6x6,ldr-rgb-kodak22.png,36.8810,0.0269,0.0105,37.2926 +Kodak,6x6,ldr-rgb-kodak23.png,39.9091,0.0222,0.0067,58.8835 +Kodak,6x6,ldr-rgb-kodak24.png,34.7176,0.0283,0.0121,32.4838 +Kodak,8x8,ldr-rgb-kodak01.png,31.2005,0.0348,0.0187,21.0613 +Kodak,8x8,ldr-rgb-kodak02.png,34.7312,0.0261,0.0095,41.5841 +Kodak,8x8,ldr-rgb-kodak03.png,36.4659,0.0225,0.0072,54.8640 +Kodak,8x8,ldr-rgb-kodak04.png,35.0660,0.0263,0.0091,43.3915 +Kodak,8x8,ldr-rgb-kodak05.png,30.0650,0.0398,0.0228,17.2714 +Kodak,8x8,ldr-rgb-kodak06.png,32.8162,0.0292,0.0134,29.4502 +Kodak,8x8,ldr-rgb-kodak07.png,34.8365,0.0271,0.0102,38.5352 +Kodak,8x8,ldr-rgb-kodak08.png,29.7191,0.0418,0.0238,16.5259 +Kodak,8x8,ldr-rgb-kodak09.png,35.9333,0.0248,0.0078,50.4641 +Kodak,8x8,ldr-rgb-kodak10.png,35.7348,0.0246,0.0074,53.1165 +Kodak,8x8,ldr-rgb-kodak11.png,32.8802,0.0286,0.0126,31.3073 +Kodak,8x8,ldr-rgb-kodak12.png,36.5229,0.0224,0.0071,55.6339 +Kodak,8x8,ldr-rgb-kodak13.png,28.1448,0.0442,0.0270,14.5388 +Kodak,8x8,ldr-rgb-kodak14.png,31.3242,0.0342,0.0180,21.8007 +Kodak,8x8,ldr-rgb-kodak15.png,34.7681,0.0262,0.0094,41.6313 +Kodak,8x8,ldr-rgb-kodak16.png,35.9653,0.0236,0.0084,46.8782 +Kodak,8x8,ldr-rgb-kodak17.png,34.7354,0.0257,0.0084,46.8449 +Kodak,8x8,ldr-rgb-kodak18.png,31.1735,0.0340,0.0162,24.3402 +Kodak,8x8,ldr-rgb-kodak19.png,33.9079,0.0286,0.0112,35.0118 +Kodak,8x8,ldr-rgb-kodak20.png,35.0719,0.0238,0.0084,47.0681 +Kodak,8x8,ldr-rgb-kodak21.png,32.6481,0.0289,0.0131,29.9731 +Kodak,8x8,ldr-rgb-kodak22.png,33.3422,0.0292,0.0119,33.1072 +Kodak,8x8,ldr-rgb-kodak23.png,36.4038,0.0231,0.0068,58.0748 +Kodak,8x8,ldr-rgb-kodak24.png,30.7489,0.0324,0.0152,25.9001 +Kodak,12x12,ldr-rgb-kodak01.png,26.9943,0.0327,0.0152,25.7964 +Kodak,12x12,ldr-rgb-kodak02.png,31.0366,0.0238,0.0055,71.0554 +Kodak,12x12,ldr-rgb-kodak03.png,32.6255,0.0214,0.0049,80.7752 +Kodak,12x12,ldr-rgb-kodak04.png,31.4723,0.0232,0.0047,83.3426 +Kodak,12x12,ldr-rgb-kodak05.png,25.7076,0.0356,0.0174,22.5970 +Kodak,12x12,ldr-rgb-kodak06.png,28.4878,0.0282,0.0110,35.6044 +Kodak,12x12,ldr-rgb-kodak07.png,30.8029,0.0243,0.0063,62.8652 +Kodak,12x12,ldr-rgb-kodak08.png,25.2189,0.0393,0.0202,19.4505 +Kodak,12x12,ldr-rgb-kodak09.png,31.6427,0.0236,0.0054,72.3617 +Kodak,12x12,ldr-rgb-kodak10.png,31.4531,0.0239,0.0053,74.2345 +Kodak,12x12,ldr-rgb-kodak11.png,28.8669,0.0257,0.0085,46.4582 +Kodak,12x12,ldr-rgb-kodak12.png,32.1856,0.0215,0.0047,82.9737 +Kodak,12x12,ldr-rgb-kodak13.png,24.2460,0.0398,0.0216,18.1759 +Kodak,12x12,ldr-rgb-kodak14.png,27.4553,0.0293,0.0117,33.5824 +Kodak,12x12,ldr-rgb-kodak15.png,31.1581,0.0247,0.0065,60.2274 +Kodak,12x12,ldr-rgb-kodak16.png,31.3640,0.0224,0.0058,67.8543 +Kodak,12x12,ldr-rgb-kodak17.png,30.8429,0.0242,0.0057,68.5652 +Kodak,12x12,ldr-rgb-kodak18.png,27.3755,0.0300,0.0110,35.7697 +Kodak,12x12,ldr-rgb-kodak19.png,29.8756,0.0273,0.0085,46.3486 +Kodak,12x12,ldr-rgb-kodak20.png,30.9402,0.0229,0.0064,61.6987 +Kodak,12x12,ldr-rgb-kodak21.png,28.6181,0.0278,0.0106,37.0964 +Kodak,12x12,ldr-rgb-kodak22.png,29.7383,0.0254,0.0068,57.6486 +Kodak,12x12,ldr-rgb-kodak23.png,32.4823,0.0226,0.0049,79.7943 +Kodak,12x12,ldr-rgb-kodak24.png,26.7030,0.0302,0.0116,33.9418 diff --git a/Test/Images/Kodak/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/Kodak/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..ccfd711 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3120,0.0828,0.0656,5.9921 +Kodak,4x4,ldr-rgb-kodak02.png,45.4397,0.1215,0.1036,3.7952 +Kodak,4x4,ldr-rgb-kodak03.png,47.6879,0.0637,0.0474,8.2934 +Kodak,4x4,ldr-rgb-kodak04.png,45.5017,0.0948,0.0767,5.1297 +Kodak,4x4,ldr-rgb-kodak05.png,42.1778,0.1065,0.0887,4.4322 +Kodak,4x4,ldr-rgb-kodak06.png,45.1998,0.0783,0.0615,6.3971 +Kodak,4x4,ldr-rgb-kodak07.png,46.0247,0.0791,0.0611,6.4361 +Kodak,4x4,ldr-rgb-kodak08.png,42.5327,0.1137,0.0949,4.1424 +Kodak,4x4,ldr-rgb-kodak09.png,47.1830,0.0920,0.0742,5.2985 +Kodak,4x4,ldr-rgb-kodak10.png,46.8614,0.0936,0.0756,5.1994 +Kodak,4x4,ldr-rgb-kodak11.png,44.8994,0.0925,0.0757,5.1947 +Kodak,4x4,ldr-rgb-kodak12.png,47.9784,0.0712,0.0547,7.1823 +Kodak,4x4,ldr-rgb-kodak13.png,41.6520,0.0891,0.0710,5.5376 +Kodak,4x4,ldr-rgb-kodak14.png,42.7319,0.0993,0.0819,4.8035 +Kodak,4x4,ldr-rgb-kodak15.png,45.5485,0.0848,0.0671,5.8588 +Kodak,4x4,ldr-rgb-kodak16.png,47.8885,0.0709,0.0545,7.2164 +Kodak,4x4,ldr-rgb-kodak17.png,46.3480,0.0807,0.0626,6.2853 +Kodak,4x4,ldr-rgb-kodak18.png,42.0493,0.1207,0.1018,3.8639 +Kodak,4x4,ldr-rgb-kodak19.png,45.3597,0.0961,0.0778,5.0559 +Kodak,4x4,ldr-rgb-kodak20.png,46.9280,0.0623,0.0461,8.5313 +Kodak,4x4,ldr-rgb-kodak21.png,45.1814,0.0974,0.0806,4.8815 +Kodak,4x4,ldr-rgb-kodak22.png,43.8216,0.1221,0.1039,3.7847 +Kodak,4x4,ldr-rgb-kodak23.png,46.8701,0.0971,0.0798,4.9281 +Kodak,4x4,ldr-rgb-kodak24.png,42.3775,0.0952,0.0772,5.0926 +Kodak,5x5,ldr-rgb-kodak01.png,40.1116,0.0851,0.0672,5.8536 +Kodak,5x5,ldr-rgb-kodak02.png,41.7670,0.0974,0.0789,4.9812 +Kodak,5x5,ldr-rgb-kodak03.png,44.0723,0.0500,0.0330,11.9211 +Kodak,5x5,ldr-rgb-kodak04.png,42.0904,0.0765,0.0577,6.8159 +Kodak,5x5,ldr-rgb-kodak05.png,37.9986,0.1011,0.0826,4.7600 +Kodak,5x5,ldr-rgb-kodak06.png,40.9739,0.0695,0.0520,7.5688 +Kodak,5x5,ldr-rgb-kodak07.png,42.4746,0.0637,0.0452,8.6968 +Kodak,5x5,ldr-rgb-kodak08.png,38.3608,0.1061,0.0864,4.5491 +Kodak,5x5,ldr-rgb-kodak09.png,43.8088,0.0562,0.0377,10.4238 +Kodak,5x5,ldr-rgb-kodak10.png,43.4231,0.0618,0.0428,9.1927 +Kodak,5x5,ldr-rgb-kodak11.png,40.8590,0.0807,0.0630,6.2457 +Kodak,5x5,ldr-rgb-kodak12.png,44.4017,0.0499,0.0331,11.8686 +Kodak,5x5,ldr-rgb-kodak13.png,36.9301,0.0869,0.0681,5.7737 +Kodak,5x5,ldr-rgb-kodak14.png,38.6960,0.0916,0.0738,5.3307 +Kodak,5x5,ldr-rgb-kodak15.png,41.9491,0.0728,0.0545,7.2164 +Kodak,5x5,ldr-rgb-kodak16.png,44.1356,0.0526,0.0357,11.0062 +Kodak,5x5,ldr-rgb-kodak17.png,42.5454,0.0551,0.0365,10.7742 +Kodak,5x5,ldr-rgb-kodak18.png,38.3941,0.0958,0.0764,5.1498 +Kodak,5x5,ldr-rgb-kodak19.png,41.6442,0.0680,0.0490,8.0327 +Kodak,5x5,ldr-rgb-kodak20.png,42.9823,0.0514,0.0345,11.3863 +Kodak,5x5,ldr-rgb-kodak21.png,40.7705,0.0700,0.0520,7.5565 +Kodak,5x5,ldr-rgb-kodak22.png,40.2982,0.0939,0.0749,5.2519 +Kodak,5x5,ldr-rgb-kodak23.png,43.5860,0.0665,0.0485,8.1141 +Kodak,5x5,ldr-rgb-kodak24.png,38.2072,0.0808,0.0618,6.3658 +Kodak,6x6,ldr-rgb-kodak01.png,36.1963,0.0836,0.0663,5.9320 +Kodak,6x6,ldr-rgb-kodak02.png,39.0475,0.0771,0.0592,6.6376 +Kodak,6x6,ldr-rgb-kodak03.png,41.3520,0.0424,0.0259,15.1998 +Kodak,6x6,ldr-rgb-kodak04.png,39.4032,0.0658,0.0475,8.2824 +Kodak,6x6,ldr-rgb-kodak05.png,34.7993,0.0949,0.0770,5.1086 +Kodak,6x6,ldr-rgb-kodak06.png,37.6376,0.0614,0.0445,8.8290 +Kodak,6x6,ldr-rgb-kodak07.png,39.7936,0.0549,0.0371,10.5916 +Kodak,6x6,ldr-rgb-kodak08.png,34.9845,0.1003,0.0813,4.8345 +Kodak,6x6,ldr-rgb-kodak09.png,40.8865,0.0454,0.0273,14.3820 +Kodak,6x6,ldr-rgb-kodak10.png,40.5154,0.0473,0.0291,13.5126 +Kodak,6x6,ldr-rgb-kodak11.png,37.5965,0.0679,0.0509,7.7228 +Kodak,6x6,ldr-rgb-kodak12.png,41.4939,0.0408,0.0243,16.1823 +Kodak,6x6,ldr-rgb-kodak13.png,32.9110,0.0901,0.0719,5.4682 +Kodak,6x6,ldr-rgb-kodak14.png,35.8527,0.0845,0.0670,5.8648 +Kodak,6x6,ldr-rgb-kodak15.png,39.2227,0.0651,0.0473,8.3164 +Kodak,6x6,ldr-rgb-kodak16.png,41.0391,0.0441,0.0278,14.1557 +Kodak,6x6,ldr-rgb-kodak17.png,39.4992,0.0467,0.0285,13.8009 +Kodak,6x6,ldr-rgb-kodak18.png,35.3684,0.0843,0.0656,5.9981 +Kodak,6x6,ldr-rgb-kodak19.png,38.5288,0.0602,0.0418,9.4030 +Kodak,6x6,ldr-rgb-kodak20.png,39.7703,0.0465,0.0301,13.0593 +Kodak,6x6,ldr-rgb-kodak21.png,37.2034,0.0606,0.0437,8.9972 +Kodak,6x6,ldr-rgb-kodak22.png,37.4752,0.0784,0.0598,6.5720 +Kodak,6x6,ldr-rgb-kodak23.png,40.9962,0.0502,0.0327,12.0209 +Kodak,6x6,ldr-rgb-kodak24.png,35.0626,0.0708,0.0523,7.5254 +Kodak,8x8,ldr-rgb-kodak01.png,31.8007,0.1101,0.0922,4.2626 +Kodak,8x8,ldr-rgb-kodak02.png,35.7971,0.0768,0.0582,6.7526 +Kodak,8x8,ldr-rgb-kodak03.png,37.7637,0.0501,0.0332,11.8395 +Kodak,8x8,ldr-rgb-kodak04.png,36.0993,0.0710,0.0522,7.5384 +Kodak,8x8,ldr-rgb-kodak05.png,30.7474,0.1206,0.1019,3.8605 +Kodak,8x8,ldr-rgb-kodak06.png,33.4449,0.0754,0.0579,6.7876 +Kodak,8x8,ldr-rgb-kodak07.png,36.1506,0.0649,0.0462,8.5143 +Kodak,8x8,ldr-rgb-kodak08.png,30.5414,0.1219,0.1020,3.8532 +Kodak,8x8,ldr-rgb-kodak09.png,37.2629,0.0514,0.0329,11.9541 +Kodak,8x8,ldr-rgb-kodak10.png,36.9234,0.0520,0.0332,11.8364 +Kodak,8x8,ldr-rgb-kodak11.png,33.6680,0.0781,0.0605,6.4945 +Kodak,8x8,ldr-rgb-kodak12.png,37.8337,0.0486,0.0315,12.4965 +Kodak,8x8,ldr-rgb-kodak13.png,28.3966,0.1187,0.0997,3.9458 +Kodak,8x8,ldr-rgb-kodak14.png,32.1516,0.1032,0.0851,4.6219 +Kodak,8x8,ldr-rgb-kodak15.png,35.8462,0.0659,0.0474,8.2978 +Kodak,8x8,ldr-rgb-kodak16.png,37.0251,0.0537,0.0367,10.7140 +Kodak,8x8,ldr-rgb-kodak17.png,35.6698,0.0553,0.0365,10.7810 +Kodak,8x8,ldr-rgb-kodak18.png,31.5577,0.0966,0.0768,5.1204 +Kodak,8x8,ldr-rgb-kodak19.png,34.7618,0.0696,0.0504,7.8052 +Kodak,8x8,ldr-rgb-kodak20.png,35.9030,0.0554,0.0383,10.2705 +Kodak,8x8,ldr-rgb-kodak21.png,33.1158,0.0740,0.0564,6.9709 +Kodak,8x8,ldr-rgb-kodak22.png,34.0434,0.0841,0.0650,6.0453 +Kodak,8x8,ldr-rgb-kodak23.png,37.6714,0.0518,0.0335,11.7493 +Kodak,8x8,ldr-rgb-kodak24.png,31.1289,0.0824,0.0635,6.1894 +Kodak,12x12,ldr-rgb-kodak01.png,27.7549,0.1228,0.1022,3.8473 +Kodak,12x12,ldr-rgb-kodak02.png,32.4572,0.0622,0.0407,9.6497 +Kodak,12x12,ldr-rgb-kodak03.png,33.8229,0.0474,0.0274,14.3761 +Kodak,12x12,ldr-rgb-kodak04.png,32.4332,0.0552,0.0334,11.7571 +Kodak,12x12,ldr-rgb-kodak05.png,26.4002,0.1348,0.1128,3.4845 +Kodak,12x12,ldr-rgb-kodak06.png,29.3776,0.0813,0.0609,6.4557 +Kodak,12x12,ldr-rgb-kodak07.png,32.0454,0.0656,0.0444,8.8556 +Kodak,12x12,ldr-rgb-kodak08.png,26.0607,0.1393,0.1168,3.3655 +Kodak,12x12,ldr-rgb-kodak09.png,33.1013,0.0505,0.0289,13.5957 +Kodak,12x12,ldr-rgb-kodak10.png,32.4879,0.0503,0.0286,13.7701 +Kodak,12x12,ldr-rgb-kodak11.png,29.7550,0.0775,0.0569,6.9065 +Kodak,12x12,ldr-rgb-kodak12.png,33.8849,0.0464,0.0266,14.7609 +Kodak,12x12,ldr-rgb-kodak13.png,24.5283,0.1397,0.1176,3.3431 +Kodak,12x12,ldr-rgb-kodak14.png,28.4299,0.1073,0.0864,4.5504 +Kodak,12x12,ldr-rgb-kodak15.png,32.2405,0.0623,0.0408,9.6355 +Kodak,12x12,ldr-rgb-kodak16.png,32.9828,0.0519,0.0320,12.2941 +Kodak,12x12,ldr-rgb-kodak17.png,31.7910,0.0546,0.0327,12.0220 +Kodak,12x12,ldr-rgb-kodak18.png,27.7838,0.0961,0.0735,5.3511 +Kodak,12x12,ldr-rgb-kodak19.png,30.8959,0.0686,0.0466,8.4293 +Kodak,12x12,ldr-rgb-kodak20.png,31.8670,0.0546,0.0347,11.3473 +Kodak,12x12,ldr-rgb-kodak21.png,29.1816,0.0841,0.0635,6.1909 +Kodak,12x12,ldr-rgb-kodak22.png,30.5137,0.0742,0.0523,7.5176 +Kodak,12x12,ldr-rgb-kodak23.png,33.5616,0.0447,0.0235,16.7070 +Kodak,12x12,ldr-rgb-kodak24.png,27.1047,0.0862,0.0641,6.1362 diff --git a/Test/Images/Kodak/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..800d77a --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5115,0.1764,0.1596,2.4645 +Kodak,4x4,ldr-rgb-kodak02.png,45.6982,0.2557,0.2379,1.6529 +Kodak,4x4,ldr-rgb-kodak03.png,48.0607,0.2007,0.1841,2.1363 +Kodak,4x4,ldr-rgb-kodak04.png,45.6858,0.2248,0.2065,1.9042 +Kodak,4x4,ldr-rgb-kodak05.png,42.4370,0.2232,0.2053,1.9149 +Kodak,4x4,ldr-rgb-kodak06.png,45.3960,0.1847,0.1677,2.3444 +Kodak,4x4,ldr-rgb-kodak07.png,46.3753,0.2213,0.2034,1.9330 +Kodak,4x4,ldr-rgb-kodak08.png,42.8242,0.2352,0.2158,1.8219 +Kodak,4x4,ldr-rgb-kodak09.png,47.4389,0.2369,0.2188,1.7972 +Kodak,4x4,ldr-rgb-kodak10.png,47.0911,0.2336,0.2155,1.8248 +Kodak,4x4,ldr-rgb-kodak11.png,45.1383,0.2111,0.1942,2.0250 +Kodak,4x4,ldr-rgb-kodak12.png,48.2774,0.2028,0.1863,2.1101 +Kodak,4x4,ldr-rgb-kodak13.png,41.7584,0.1848,0.1668,2.3570 +Kodak,4x4,ldr-rgb-kodak14.png,42.9859,0.2091,0.1914,2.0539 +Kodak,4x4,ldr-rgb-kodak15.png,45.8334,0.2173,0.1996,1.9701 +Kodak,4x4,ldr-rgb-kodak16.png,48.0940,0.2005,0.1841,2.1363 +Kodak,4x4,ldr-rgb-kodak17.png,46.5075,0.2120,0.1938,2.0285 +Kodak,4x4,ldr-rgb-kodak18.png,42.2101,0.2493,0.2305,1.7062 +Kodak,4x4,ldr-rgb-kodak19.png,45.5658,0.2237,0.2051,1.9174 +Kodak,4x4,ldr-rgb-kodak20.png,47.1799,0.1429,0.1265,3.1077 +Kodak,4x4,ldr-rgb-kodak21.png,45.3342,0.2254,0.2086,1.8849 +Kodak,4x4,ldr-rgb-kodak22.png,44.0086,0.2567,0.2382,1.6510 +Kodak,4x4,ldr-rgb-kodak23.png,47.1907,0.2476,0.2301,1.7091 +Kodak,4x4,ldr-rgb-kodak24.png,42.6019,0.2214,0.2032,1.9356 +Kodak,5x5,ldr-rgb-kodak01.png,40.2236,0.2051,0.1871,2.1012 +Kodak,5x5,ldr-rgb-kodak02.png,42.0380,0.2696,0.2508,1.5678 +Kodak,5x5,ldr-rgb-kodak03.png,44.3676,0.2013,0.1841,2.1358 +Kodak,5x5,ldr-rgb-kodak04.png,42.2612,0.2226,0.2035,1.9322 +Kodak,5x5,ldr-rgb-kodak05.png,38.1929,0.2420,0.2230,1.7635 +Kodak,5x5,ldr-rgb-kodak06.png,41.0984,0.1947,0.1766,2.2264 +Kodak,5x5,ldr-rgb-kodak07.png,42.7456,0.2251,0.2060,1.9087 +Kodak,5x5,ldr-rgb-kodak08.png,38.5418,0.2435,0.2234,1.7602 +Kodak,5x5,ldr-rgb-kodak09.png,44.0366,0.2183,0.1999,1.9668 +Kodak,5x5,ldr-rgb-kodak10.png,43.6071,0.2249,0.2060,1.9086 +Kodak,5x5,ldr-rgb-kodak11.png,41.0130,0.2163,0.1986,1.9798 +Kodak,5x5,ldr-rgb-kodak12.png,44.6149,0.2062,0.1881,2.0909 +Kodak,5x5,ldr-rgb-kodak13.png,36.9748,0.1909,0.1720,2.2864 +Kodak,5x5,ldr-rgb-kodak14.png,38.9092,0.2235,0.2052,1.9160 +Kodak,5x5,ldr-rgb-kodak15.png,42.1668,0.2182,0.1993,1.9734 +Kodak,5x5,ldr-rgb-kodak16.png,44.2715,0.2011,0.1832,2.1461 +Kodak,5x5,ldr-rgb-kodak17.png,42.6407,0.2052,0.1858,2.1159 +Kodak,5x5,ldr-rgb-kodak18.png,38.4820,0.2447,0.2250,1.7478 +Kodak,5x5,ldr-rgb-kodak19.png,41.7841,0.2322,0.2122,1.8528 +Kodak,5x5,ldr-rgb-kodak20.png,43.2953,0.1461,0.1284,3.0614 +Kodak,5x5,ldr-rgb-kodak21.png,40.8774,0.2436,0.2258,1.7417 +Kodak,5x5,ldr-rgb-kodak22.png,40.4425,0.2836,0.2640,1.4893 +Kodak,5x5,ldr-rgb-kodak23.png,43.9057,0.2744,0.2552,1.5406 +Kodak,5x5,ldr-rgb-kodak24.png,38.3273,0.2285,0.2094,1.8778 +Kodak,6x6,ldr-rgb-kodak01.png,36.3105,0.2281,0.2104,1.8689 +Kodak,6x6,ldr-rgb-kodak02.png,39.4083,0.3561,0.3364,1.1688 +Kodak,6x6,ldr-rgb-kodak03.png,41.7533,0.1735,0.1570,2.5046 +Kodak,6x6,ldr-rgb-kodak04.png,39.6674,0.2308,0.2125,1.8503 +Kodak,6x6,ldr-rgb-kodak05.png,34.9944,0.2585,0.2403,1.6363 +Kodak,6x6,ldr-rgb-kodak06.png,37.7608,0.2003,0.1835,2.1429 +Kodak,6x6,ldr-rgb-kodak07.png,40.1279,0.2021,0.1841,2.1359 +Kodak,6x6,ldr-rgb-kodak08.png,35.1750,0.2554,0.2363,1.6639 +Kodak,6x6,ldr-rgb-kodak09.png,41.2718,0.2194,0.2014,1.9525 +Kodak,6x6,ldr-rgb-kodak10.png,40.8412,0.2375,0.2184,1.8006 +Kodak,6x6,ldr-rgb-kodak11.png,37.7820,0.2233,0.2059,1.9101 +Kodak,6x6,ldr-rgb-kodak12.png,41.8395,0.2012,0.1845,2.1314 +Kodak,6x6,ldr-rgb-kodak13.png,32.9600,0.2150,0.1968,1.9977 +Kodak,6x6,ldr-rgb-kodak14.png,36.0500,0.2432,0.2257,1.7425 +Kodak,6x6,ldr-rgb-kodak15.png,39.4760,0.2059,0.1880,2.0917 +Kodak,6x6,ldr-rgb-kodak16.png,41.2318,0.1901,0.1736,2.2657 +Kodak,6x6,ldr-rgb-kodak17.png,39.6707,0.2105,0.1922,2.0461 +Kodak,6x6,ldr-rgb-kodak18.png,35.4565,0.2595,0.2404,1.6354 +Kodak,6x6,ldr-rgb-kodak19.png,38.7066,0.2421,0.2232,1.7619 +Kodak,6x6,ldr-rgb-kodak20.png,40.1121,0.1540,0.1372,2.8669 +Kodak,6x6,ldr-rgb-kodak21.png,37.3497,0.2406,0.2235,1.7596 +Kodak,6x6,ldr-rgb-kodak22.png,37.6441,0.2760,0.2576,1.5265 +Kodak,6x6,ldr-rgb-kodak23.png,41.4416,0.2514,0.2338,1.6815 +Kodak,6x6,ldr-rgb-kodak24.png,35.1795,0.2285,0.2100,1.8722 +Kodak,8x8,ldr-rgb-kodak01.png,31.9076,0.2775,0.2582,1.5229 +Kodak,8x8,ldr-rgb-kodak02.png,36.1658,0.2814,0.2616,1.5034 +Kodak,8x8,ldr-rgb-kodak03.png,38.2015,0.1516,0.1331,2.9543 +Kodak,8x8,ldr-rgb-kodak04.png,36.3849,0.2269,0.2064,1.9050 +Kodak,8x8,ldr-rgb-kodak05.png,30.9159,0.3018,0.2818,1.3954 +Kodak,8x8,ldr-rgb-kodak06.png,33.5799,0.2297,0.2107,1.8662 +Kodak,8x8,ldr-rgb-kodak07.png,36.5075,0.1844,0.1645,2.3904 +Kodak,8x8,ldr-rgb-kodak08.png,30.7382,0.3264,0.3050,1.2894 +Kodak,8x8,ldr-rgb-kodak09.png,37.5585,0.1677,0.1478,2.6611 +Kodak,8x8,ldr-rgb-kodak10.png,37.2383,0.1922,0.1718,2.2890 +Kodak,8x8,ldr-rgb-kodak11.png,33.8328,0.2668,0.2479,1.5864 +Kodak,8x8,ldr-rgb-kodak12.png,38.2628,0.1735,0.1550,2.5370 +Kodak,8x8,ldr-rgb-kodak13.png,28.4607,0.2896,0.2691,1.4611 +Kodak,8x8,ldr-rgb-kodak14.png,32.3242,0.2916,0.2719,1.4462 +Kodak,8x8,ldr-rgb-kodak15.png,36.0684,0.2147,0.1949,2.0175 +Kodak,8x8,ldr-rgb-kodak16.png,37.2660,0.1851,0.1666,2.3601 +Kodak,8x8,ldr-rgb-kodak17.png,35.8716,0.1857,0.1648,2.3859 +Kodak,8x8,ldr-rgb-kodak18.png,31.6551,0.2987,0.2778,1.4153 +Kodak,8x8,ldr-rgb-kodak19.png,34.9274,0.2020,0.1815,2.1669 +Kodak,8x8,ldr-rgb-kodak20.png,36.1555,0.1630,0.1445,2.7220 +Kodak,8x8,ldr-rgb-kodak21.png,33.2255,0.2144,0.1954,2.0123 +Kodak,8x8,ldr-rgb-kodak22.png,34.2304,0.2798,0.2591,1.5174 +Kodak,8x8,ldr-rgb-kodak23.png,38.1991,0.1843,0.1645,2.3908 +Kodak,8x8,ldr-rgb-kodak24.png,31.2348,0.2471,0.2265,1.7362 +Kodak,12x12,ldr-rgb-kodak01.png,27.9132,0.3651,0.3417,1.1506 +Kodak,12x12,ldr-rgb-kodak02.png,33.0052,0.2716,0.2475,1.5884 +Kodak,12x12,ldr-rgb-kodak03.png,34.4542,0.1637,0.1415,2.7793 +Kodak,12x12,ldr-rgb-kodak04.png,32.9738,0.2375,0.2132,1.8447 +Kodak,12x12,ldr-rgb-kodak05.png,26.6073,0.3931,0.3688,1.0662 +Kodak,12x12,ldr-rgb-kodak06.png,29.5310,0.2681,0.2449,1.6056 +Kodak,12x12,ldr-rgb-kodak07.png,32.6281,0.2083,0.1843,2.1338 +Kodak,12x12,ldr-rgb-kodak08.png,26.2616,0.3959,0.3707,1.0606 +Kodak,12x12,ldr-rgb-kodak09.png,33.6343,0.1875,0.1633,2.4082 +Kodak,12x12,ldr-rgb-kodak10.png,32.9910,0.1854,0.1610,2.4424 +Kodak,12x12,ldr-rgb-kodak11.png,30.0541,0.2884,0.2651,1.4834 +Kodak,12x12,ldr-rgb-kodak12.png,34.4512,0.1697,0.1472,2.6718 +Kodak,12x12,ldr-rgb-kodak13.png,24.5887,0.4264,0.4021,0.9779 +Kodak,12x12,ldr-rgb-kodak14.png,28.6476,0.3480,0.3246,1.2115 +Kodak,12x12,ldr-rgb-kodak15.png,32.7352,0.2292,0.2053,1.9154 +Kodak,12x12,ldr-rgb-kodak16.png,33.3387,0.2007,0.1784,2.2039 +Kodak,12x12,ldr-rgb-kodak17.png,32.1425,0.1986,0.1743,2.2561 +Kodak,12x12,ldr-rgb-kodak18.png,27.9244,0.3459,0.3207,1.2262 +Kodak,12x12,ldr-rgb-kodak19.png,31.1081,0.2717,0.2470,1.5921 +Kodak,12x12,ldr-rgb-kodak20.png,32.1616,0.2123,0.1898,2.0717 +Kodak,12x12,ldr-rgb-kodak21.png,29.3265,0.2574,0.2343,1.6782 +Kodak,12x12,ldr-rgb-kodak22.png,30.7890,0.3051,0.2805,1.4020 +Kodak,12x12,ldr-rgb-kodak23.png,34.3835,0.1691,0.1455,2.7023 +Kodak,12x12,ldr-rgb-kodak24.png,27.2381,0.3114,0.2869,1.3706 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..01d5e9c --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.8820,0.0360,0.0188,20.9370 +Kodak,4x4,ldr-rgb-kodak02.png,44.2873,0.0456,0.0275,14.3238 +Kodak,4x4,ldr-rgb-kodak03.png,46.7875,0.0319,0.0152,25.8202 +Kodak,4x4,ldr-rgb-kodak04.png,44.6627,0.0427,0.0242,16.2720 +Kodak,4x4,ldr-rgb-kodak05.png,41.6532,0.0547,0.0364,10.8065 +Kodak,4x4,ldr-rgb-kodak06.png,44.7930,0.0354,0.0185,21.2836 +Kodak,4x4,ldr-rgb-kodak07.png,45.1555,0.0388,0.0207,19.0060 +Kodak,4x4,ldr-rgb-kodak08.png,42.1261,0.0569,0.0377,10.4288 +Kodak,4x4,ldr-rgb-kodak09.png,46.3501,0.0320,0.0141,27.8048 +Kodak,4x4,ldr-rgb-kodak10.png,46.1138,0.0329,0.0149,26.4064 +Kodak,4x4,ldr-rgb-kodak11.png,44.3024,0.0400,0.0226,17.3966 +Kodak,4x4,ldr-rgb-kodak12.png,47.1128,0.0308,0.0138,28.5395 +Kodak,4x4,ldr-rgb-kodak13.png,41.4830,0.0495,0.0310,12.6917 +Kodak,4x4,ldr-rgb-kodak14.png,41.9274,0.0479,0.0302,13.0105 +Kodak,4x4,ldr-rgb-kodak15.png,44.7388,0.0445,0.0263,14.9285 +Kodak,4x4,ldr-rgb-kodak16.png,47.2478,0.0286,0.0121,32.5537 +Kodak,4x4,ldr-rgb-kodak17.png,45.8440,0.0317,0.0135,29.1833 +Kodak,4x4,ldr-rgb-kodak18.png,41.6843,0.0552,0.0359,10.9595 +Kodak,4x4,ldr-rgb-kodak19.png,44.8511,0.0368,0.0182,21.6516 +Kodak,4x4,ldr-rgb-kodak20.png,46.4186,0.0320,0.0155,25.3937 +Kodak,4x4,ldr-rgb-kodak21.png,44.6411,0.0364,0.0191,20.6197 +Kodak,4x4,ldr-rgb-kodak22.png,43.2351,0.0492,0.0303,12.9847 +Kodak,4x4,ldr-rgb-kodak23.png,45.6659,0.0363,0.0185,21.2400 +Kodak,4x4,ldr-rgb-kodak24.png,41.9807,0.0478,0.0292,13.4507 +Kodak,5x5,ldr-rgb-kodak01.png,39.6135,0.0362,0.0184,21.3985 +Kodak,5x5,ldr-rgb-kodak02.png,40.6534,0.0360,0.0176,22.3888 +Kodak,5x5,ldr-rgb-kodak03.png,43.0540,0.0284,0.0118,33.3941 +Kodak,5x5,ldr-rgb-kodak04.png,41.2613,0.0348,0.0162,24.2743 +Kodak,5x5,ldr-rgb-kodak05.png,37.4541,0.0504,0.0316,12.4502 +Kodak,5x5,ldr-rgb-kodak06.png,40.5884,0.0320,0.0148,26.5437 +Kodak,5x5,ldr-rgb-kodak07.png,41.4931,0.0337,0.0153,25.6835 +Kodak,5x5,ldr-rgb-kodak08.png,37.7792,0.0513,0.0318,12.3821 +Kodak,5x5,ldr-rgb-kodak09.png,42.9214,0.0287,0.0105,37.3425 +Kodak,5x5,ldr-rgb-kodak10.png,42.6313,0.0296,0.0111,35.5691 +Kodak,5x5,ldr-rgb-kodak11.png,40.3040,0.0343,0.0169,23.2964 +Kodak,5x5,ldr-rgb-kodak12.png,43.4157,0.0266,0.0097,40.3747 +Kodak,5x5,ldr-rgb-kodak13.png,36.8276,0.0461,0.0271,14.4858 +Kodak,5x5,ldr-rgb-kodak14.png,38.0242,0.0464,0.0282,13.9261 +Kodak,5x5,ldr-rgb-kodak15.png,41.1917,0.0352,0.0168,23.4517 +Kodak,5x5,ldr-rgb-kodak16.png,43.4667,0.0274,0.0092,42.8203 +Kodak,5x5,ldr-rgb-kodak17.png,42.0469,0.0305,0.0106,37.0189 +Kodak,5x5,ldr-rgb-kodak18.png,38.1147,0.0465,0.0250,15.7526 +Kodak,5x5,ldr-rgb-kodak19.png,41.1276,0.0324,0.0131,29.9323 +Kodak,5x5,ldr-rgb-kodak20.png,42.3603,0.0292,0.0116,33.8686 +Kodak,5x5,ldr-rgb-kodak21.png,40.4227,0.0334,0.0158,24.9281 +Kodak,5x5,ldr-rgb-kodak22.png,39.7897,0.0380,0.0190,20.6424 +Kodak,5x5,ldr-rgb-kodak23.png,42.5143,0.0303,0.0125,31.5125 +Kodak,5x5,ldr-rgb-kodak24.png,37.8892,0.0411,0.0222,17.7131 +Kodak,6x6,ldr-rgb-kodak01.png,35.7507,0.0444,0.0269,14.6286 +Kodak,6x6,ldr-rgb-kodak02.png,38.1712,0.0365,0.0182,21.5568 +Kodak,6x6,ldr-rgb-kodak03.png,40.5686,0.0282,0.0115,34.1541 +Kodak,6x6,ldr-rgb-kodak04.png,38.5433,0.0352,0.0168,23.4574 +Kodak,6x6,ldr-rgb-kodak05.png,34.3631,0.0569,0.0382,10.2853 +Kodak,6x6,ldr-rgb-kodak06.png,37.3004,0.0352,0.0181,21.7777 +Kodak,6x6,ldr-rgb-kodak07.png,38.8820,0.0347,0.0163,24.0572 +Kodak,6x6,ldr-rgb-kodak08.png,34.4474,0.0577,0.0380,10.3367 +Kodak,6x6,ldr-rgb-kodak09.png,39.9734,0.0305,0.0124,31.6880 +Kodak,6x6,ldr-rgb-kodak10.png,39.7372,0.0304,0.0120,32.6834 +Kodak,6x6,ldr-rgb-kodak11.png,37.1533,0.0371,0.0197,19.9490 +Kodak,6x6,ldr-rgb-kodak12.png,40.7387,0.0268,0.0102,38.5965 +Kodak,6x6,ldr-rgb-kodak13.png,32.8130,0.0579,0.0393,10.0101 +Kodak,6x6,ldr-rgb-kodak14.png,35.3037,0.0507,0.0328,11.9785 +Kodak,6x6,ldr-rgb-kodak15.png,38.5680,0.0357,0.0175,22.4247 +Kodak,6x6,ldr-rgb-kodak16.png,40.4942,0.0269,0.0102,38.4265 +Kodak,6x6,ldr-rgb-kodak17.png,38.9398,0.0308,0.0124,31.7521 +Kodak,6x6,ldr-rgb-kodak18.png,35.1209,0.0463,0.0269,14.6221 +Kodak,6x6,ldr-rgb-kodak19.png,37.9783,0.0364,0.0176,22.3454 +Kodak,6x6,ldr-rgb-kodak20.png,39.1839,0.0303,0.0137,28.6704 +Kodak,6x6,ldr-rgb-kodak21.png,36.9075,0.0377,0.0202,19.4682 +Kodak,6x6,ldr-rgb-kodak22.png,36.9849,0.0399,0.0210,18.7244 +Kodak,6x6,ldr-rgb-kodak23.png,40.0615,0.0301,0.0123,32.0234 +Kodak,6x6,ldr-rgb-kodak24.png,34.7936,0.0435,0.0246,15.9856 +Kodak,8x8,ldr-rgb-kodak01.png,31.3361,0.0579,0.0401,9.8017 +Kodak,8x8,ldr-rgb-kodak02.png,34.9328,0.0365,0.0181,21.6898 +Kodak,8x8,ldr-rgb-kodak03.png,36.5952,0.0304,0.0135,29.0881 +Kodak,8x8,ldr-rgb-kodak04.png,35.1760,0.0366,0.0177,22.1870 +Kodak,8x8,ldr-rgb-kodak05.png,30.2523,0.0675,0.0488,8.0659 +Kodak,8x8,ldr-rgb-kodak06.png,32.9457,0.0450,0.0275,14.2826 +Kodak,8x8,ldr-rgb-kodak07.png,34.9951,0.0387,0.0202,19.4873 +Kodak,8x8,ldr-rgb-kodak08.png,29.9694,0.0694,0.0499,7.8802 +Kodak,8x8,ldr-rgb-kodak09.png,36.1703,0.0333,0.0150,26.2773 +Kodak,8x8,ldr-rgb-kodak10.png,35.8857,0.0328,0.0139,28.3623 +Kodak,8x8,ldr-rgb-kodak11.png,33.0088,0.0429,0.0252,15.5840 +Kodak,8x8,ldr-rgb-kodak12.png,36.7290,0.0300,0.0129,30.4799 +Kodak,8x8,ldr-rgb-kodak13.png,28.2209,0.0769,0.0580,6.7810 +Kodak,8x8,ldr-rgb-kodak14.png,31.5032,0.0565,0.0384,10.2278 +Kodak,8x8,ldr-rgb-kodak15.png,34.9394,0.0370,0.0184,21.3799 +Kodak,8x8,ldr-rgb-kodak16.png,36.0527,0.0332,0.0163,24.0822 +Kodak,8x8,ldr-rgb-kodak17.png,34.9073,0.0348,0.0160,24.5088 +Kodak,8x8,ldr-rgb-kodak18.png,31.2398,0.0534,0.0337,11.6657 +Kodak,8x8,ldr-rgb-kodak19.png,34.2235,0.0412,0.0221,17.7652 +Kodak,8x8,ldr-rgb-kodak20.png,35.2317,0.0331,0.0161,24.4597 +Kodak,8x8,ldr-rgb-kodak21.png,32.7551,0.0445,0.0268,14.6581 +Kodak,8x8,ldr-rgb-kodak22.png,33.4546,0.0428,0.0238,16.5335 +Kodak,8x8,ldr-rgb-kodak23.png,36.5268,0.0306,0.0126,31.1606 +Kodak,8x8,ldr-rgb-kodak24.png,30.8238,0.0497,0.0307,12.8271 +Kodak,12x12,ldr-rgb-kodak01.png,27.1080,0.0518,0.0321,12.2386 +Kodak,12x12,ldr-rgb-kodak02.png,31.1083,0.0300,0.0098,40.1526 +Kodak,12x12,ldr-rgb-kodak03.png,32.6856,0.0273,0.0087,45.3232 +Kodak,12x12,ldr-rgb-kodak04.png,31.5645,0.0285,0.0081,48.4979 +Kodak,12x12,ldr-rgb-kodak05.png,25.8227,0.0572,0.0368,10.6869 +Kodak,12x12,ldr-rgb-kodak06.png,28.6373,0.0417,0.0224,17.5307 +Kodak,12x12,ldr-rgb-kodak07.png,30.8590,0.0318,0.0117,33.5081 +Kodak,12x12,ldr-rgb-kodak08.png,25.4179,0.0638,0.0423,9.3055 +Kodak,12x12,ldr-rgb-kodak09.png,31.8377,0.0302,0.0099,39.6706 +Kodak,12x12,ldr-rgb-kodak10.png,31.5385,0.0300,0.0095,41.2823 +Kodak,12x12,ldr-rgb-kodak11.png,28.9359,0.0358,0.0167,23.5233 +Kodak,12x12,ldr-rgb-kodak12.png,32.2823,0.0268,0.0083,47.1421 +Kodak,12x12,ldr-rgb-kodak13.png,24.3217,0.0661,0.0454,8.6684 +Kodak,12x12,ldr-rgb-kodak14.png,27.5443,0.0432,0.0234,16.7718 +Kodak,12x12,ldr-rgb-kodak15.png,31.2551,0.0326,0.0124,31.7264 +Kodak,12x12,ldr-rgb-kodak16.png,31.4853,0.0294,0.0107,36.8321 +Kodak,12x12,ldr-rgb-kodak17.png,30.8975,0.0309,0.0104,37.7476 +Kodak,12x12,ldr-rgb-kodak18.png,27.4230,0.0433,0.0221,17.7782 +Kodak,12x12,ldr-rgb-kodak19.png,30.1902,0.0372,0.0165,23.7866 +Kodak,12x12,ldr-rgb-kodak20.png,31.0526,0.0302,0.0118,33.2755 +Kodak,12x12,ldr-rgb-kodak21.png,28.7136,0.0412,0.0217,18.1440 +Kodak,12x12,ldr-rgb-kodak22.png,29.8371,0.0334,0.0128,30.7435 +Kodak,12x12,ldr-rgb-kodak23.png,32.5213,0.0286,0.0087,45.1916 +Kodak,12x12,ldr-rgb-kodak24.png,26.7723,0.0433,0.0227,17.3284 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..6b5967c --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5460,0.0300,0.0134,29.3245 +Kodak,4x4,ldr-rgb-kodak02.png,43.8803,0.0355,0.0179,21.9896 +Kodak,4x4,ldr-rgb-kodak03.png,46.1873,0.0267,0.0109,36.2317 +Kodak,4x4,ldr-rgb-kodak04.png,44.2426,0.0338,0.0160,24.5562 +Kodak,4x4,ldr-rgb-kodak05.png,41.1063,0.0394,0.0217,18.1063 +Kodak,4x4,ldr-rgb-kodak06.png,44.5076,0.0296,0.0134,29.3574 +Kodak,4x4,ldr-rgb-kodak07.png,44.7021,0.0312,0.0138,28.4695 +Kodak,4x4,ldr-rgb-kodak08.png,41.5547,0.0410,0.0222,17.7283 +Kodak,4x4,ldr-rgb-kodak09.png,46.0133,0.0275,0.0104,37.8272 +Kodak,4x4,ldr-rgb-kodak10.png,45.7710,0.0286,0.0109,36.0283 +Kodak,4x4,ldr-rgb-kodak11.png,43.9057,0.0315,0.0151,26.0927 +Kodak,4x4,ldr-rgb-kodak12.png,46.5477,0.0262,0.0103,38.3408 +Kodak,4x4,ldr-rgb-kodak13.png,41.2213,0.0384,0.0206,19.0947 +Kodak,4x4,ldr-rgb-kodak14.png,41.2633,0.0349,0.0178,22.1058 +Kodak,4x4,ldr-rgb-kodak15.png,44.2793,0.0340,0.0166,23.6807 +Kodak,4x4,ldr-rgb-kodak16.png,47.1118,0.0255,0.0096,40.7649 +Kodak,4x4,ldr-rgb-kodak17.png,45.6149,0.0277,0.0102,38.5884 +Kodak,4x4,ldr-rgb-kodak18.png,41.3441,0.0403,0.0216,18.1751 +Kodak,4x4,ldr-rgb-kodak19.png,44.5863,0.0309,0.0130,30.1986 +Kodak,4x4,ldr-rgb-kodak20.png,45.9269,0.0269,0.0110,35.6206 +Kodak,4x4,ldr-rgb-kodak21.png,44.3216,0.0300,0.0135,29.0861 +Kodak,4x4,ldr-rgb-kodak22.png,42.8634,0.0368,0.0187,21.0063 +Kodak,4x4,ldr-rgb-kodak23.png,45.3579,0.0299,0.0128,30.7201 +Kodak,4x4,ldr-rgb-kodak24.png,41.4243,0.0357,0.0177,22.1753 +Kodak,5x5,ldr-rgb-kodak01.png,39.3930,0.0317,0.0151,26.1220 +Kodak,5x5,ldr-rgb-kodak02.png,40.4266,0.0310,0.0135,29.0820 +Kodak,5x5,ldr-rgb-kodak03.png,42.6948,0.0251,0.0092,42.5146 +Kodak,5x5,ldr-rgb-kodak04.png,40.8613,0.0305,0.0127,31.0205 +Kodak,5x5,ldr-rgb-kodak05.png,37.1066,0.0398,0.0220,17.9060 +Kodak,5x5,ldr-rgb-kodak06.png,40.4306,0.0286,0.0122,32.2230 +Kodak,5x5,ldr-rgb-kodak07.png,41.1804,0.0296,0.0120,32.7756 +Kodak,5x5,ldr-rgb-kodak08.png,37.4468,0.0413,0.0226,17.4299 +Kodak,5x5,ldr-rgb-kodak09.png,42.6180,0.0263,0.0088,44.6025 +Kodak,5x5,ldr-rgb-kodak10.png,42.4264,0.0270,0.0092,42.9553 +Kodak,5x5,ldr-rgb-kodak11.png,40.0808,0.0297,0.0131,30.0648 +Kodak,5x5,ldr-rgb-kodak12.png,43.2020,0.0244,0.0083,47.3465 +Kodak,5x5,ldr-rgb-kodak13.png,36.7364,0.0393,0.0216,18.2399 +Kodak,5x5,ldr-rgb-kodak14.png,37.5843,0.0350,0.0180,21.8686 +Kodak,5x5,ldr-rgb-kodak15.png,40.9222,0.0302,0.0126,31.1706 +Kodak,5x5,ldr-rgb-kodak16.png,43.3847,0.0241,0.0082,47.8367 +Kodak,5x5,ldr-rgb-kodak17.png,41.9201,0.0267,0.0088,44.4714 +Kodak,5x5,ldr-rgb-kodak18.png,37.9619,0.0362,0.0179,21.9832 +Kodak,5x5,ldr-rgb-kodak19.png,40.8871,0.0293,0.0113,34.8042 +Kodak,5x5,ldr-rgb-kodak20.png,42.0751,0.0252,0.0094,41.6629 +Kodak,5x5,ldr-rgb-kodak21.png,40.2318,0.0293,0.0128,30.7493 +Kodak,5x5,ldr-rgb-kodak22.png,39.5098,0.0325,0.0145,27.0731 +Kodak,5x5,ldr-rgb-kodak23.png,42.2176,0.0274,0.0102,38.3997 +Kodak,5x5,ldr-rgb-kodak24.png,37.6858,0.0339,0.0161,24.4477 +Kodak,6x6,ldr-rgb-kodak01.png,35.6604,0.0374,0.0206,19.0863 +Kodak,6x6,ldr-rgb-kodak02.png,38.0761,0.0308,0.0135,29.1076 +Kodak,6x6,ldr-rgb-kodak03.png,40.4029,0.0248,0.0089,44.2270 +Kodak,6x6,ldr-rgb-kodak04.png,38.3307,0.0304,0.0127,30.9541 +Kodak,6x6,ldr-rgb-kodak05.png,34.1621,0.0433,0.0256,15.3749 +Kodak,6x6,ldr-rgb-kodak06.png,37.2413,0.0306,0.0142,27.6639 +Kodak,6x6,ldr-rgb-kodak07.png,38.6918,0.0297,0.0124,31.7753 +Kodak,6x6,ldr-rgb-kodak08.png,34.2562,0.0450,0.0263,14.9381 +Kodak,6x6,ldr-rgb-kodak09.png,39.8018,0.0269,0.0097,40.6464 +Kodak,6x6,ldr-rgb-kodak10.png,39.6065,0.0273,0.0096,40.8791 +Kodak,6x6,ldr-rgb-kodak11.png,37.0350,0.0311,0.0145,27.0527 +Kodak,6x6,ldr-rgb-kodak12.png,40.6117,0.0243,0.0084,46.7109 +Kodak,6x6,ldr-rgb-kodak13.png,32.7512,0.0468,0.0289,13.5869 +Kodak,6x6,ldr-rgb-kodak14.png,35.0163,0.0369,0.0201,19.5415 +Kodak,6x6,ldr-rgb-kodak15.png,38.4450,0.0303,0.0130,30.1688 +Kodak,6x6,ldr-rgb-kodak16.png,40.4576,0.0246,0.0088,44.5315 +Kodak,6x6,ldr-rgb-kodak17.png,38.8609,0.0277,0.0101,39.0018 +Kodak,6x6,ldr-rgb-kodak18.png,35.0294,0.0381,0.0199,19.7953 +Kodak,6x6,ldr-rgb-kodak19.png,37.8582,0.0319,0.0140,28.0712 +Kodak,6x6,ldr-rgb-kodak20.png,39.0412,0.0265,0.0107,36.8074 +Kodak,6x6,ldr-rgb-kodak21.png,36.8328,0.0317,0.0153,25.6500 +Kodak,6x6,ldr-rgb-kodak22.png,36.8810,0.0334,0.0155,25.3655 +Kodak,6x6,ldr-rgb-kodak23.png,39.9091,0.0266,0.0096,40.8791 +Kodak,6x6,ldr-rgb-kodak24.png,34.7176,0.0360,0.0183,21.5026 +Kodak,8x8,ldr-rgb-kodak01.png,31.2005,0.0468,0.0291,13.4913 +Kodak,8x8,ldr-rgb-kodak02.png,34.7312,0.0321,0.0139,28.2990 +Kodak,8x8,ldr-rgb-kodak03.png,36.4659,0.0273,0.0106,36.9501 +Kodak,8x8,ldr-rgb-kodak04.png,35.0660,0.0322,0.0135,29.0625 +Kodak,8x8,ldr-rgb-kodak05.png,30.0650,0.0539,0.0352,11.1722 +Kodak,8x8,ldr-rgb-kodak06.png,32.8162,0.0380,0.0206,19.0843 +Kodak,8x8,ldr-rgb-kodak07.png,34.8365,0.0336,0.0154,25.6149 +Kodak,8x8,ldr-rgb-kodak08.png,29.7191,0.0566,0.0371,10.6120 +Kodak,8x8,ldr-rgb-kodak09.png,35.9333,0.0301,0.0118,33.2420 +Kodak,8x8,ldr-rgb-kodak10.png,35.7348,0.0296,0.0111,35.5622 +Kodak,8x8,ldr-rgb-kodak11.png,32.8802,0.0362,0.0189,20.8128 +Kodak,8x8,ldr-rgb-kodak12.png,36.5229,0.0271,0.0104,37.8056 +Kodak,8x8,ldr-rgb-kodak13.png,28.1448,0.0606,0.0419,9.3907 +Kodak,8x8,ldr-rgb-kodak14.png,31.3242,0.0453,0.0274,14.3567 +Kodak,8x8,ldr-rgb-kodak15.png,34.7681,0.0322,0.0140,28.0330 +Kodak,8x8,ldr-rgb-kodak16.png,35.9653,0.0295,0.0128,30.8286 +Kodak,8x8,ldr-rgb-kodak17.png,34.7354,0.0311,0.0125,31.4116 +Kodak,8x8,ldr-rgb-kodak18.png,31.1735,0.0441,0.0247,15.9501 +Kodak,8x8,ldr-rgb-kodak19.png,33.9079,0.0356,0.0171,23.0502 +Kodak,8x8,ldr-rgb-kodak20.png,35.0719,0.0292,0.0125,31.4272 +Kodak,8x8,ldr-rgb-kodak21.png,32.6481,0.0374,0.0201,19.6108 +Kodak,8x8,ldr-rgb-kodak22.png,33.3422,0.0365,0.0177,22.1643 +Kodak,8x8,ldr-rgb-kodak23.png,36.4038,0.0277,0.0099,39.6506 +Kodak,8x8,ldr-rgb-kodak24.png,30.7489,0.0416,0.0228,17.2561 +Kodak,12x12,ldr-rgb-kodak01.png,26.9943,0.0423,0.0231,17.0054 +Kodak,12x12,ldr-rgb-kodak02.png,31.0366,0.0274,0.0078,50.1938 +Kodak,12x12,ldr-rgb-kodak03.png,32.6255,0.0251,0.0070,56.1663 +Kodak,12x12,ldr-rgb-kodak04.png,31.4723,0.0267,0.0066,59.5597 +Kodak,12x12,ldr-rgb-kodak05.png,25.7076,0.0459,0.0260,15.1138 +Kodak,12x12,ldr-rgb-kodak06.png,28.4878,0.0348,0.0166,23.7376 +Kodak,12x12,ldr-rgb-kodak07.png,30.8029,0.0287,0.0091,43.1870 +Kodak,12x12,ldr-rgb-kodak08.png,25.2189,0.0515,0.0306,12.8372 +Kodak,12x12,ldr-rgb-kodak09.png,31.6427,0.0273,0.0078,50.1297 +Kodak,12x12,ldr-rgb-kodak10.png,31.4531,0.0275,0.0077,51.2529 +Kodak,12x12,ldr-rgb-kodak11.png,28.8669,0.0311,0.0125,31.4218 +Kodak,12x12,ldr-rgb-kodak12.png,32.1856,0.0248,0.0068,58.0136 +Kodak,12x12,ldr-rgb-kodak13.png,24.2460,0.0523,0.0324,12.1521 +Kodak,12x12,ldr-rgb-kodak14.png,27.4553,0.0363,0.0172,22.8693 +Kodak,12x12,ldr-rgb-kodak15.png,31.1581,0.0292,0.0096,40.9685 +Kodak,12x12,ldr-rgb-kodak16.png,31.3640,0.0266,0.0085,46.3368 +Kodak,12x12,ldr-rgb-kodak17.png,30.8429,0.0282,0.0082,47.7274 +Kodak,12x12,ldr-rgb-kodak18.png,27.3755,0.0368,0.0162,24.2336 +Kodak,12x12,ldr-rgb-kodak19.png,29.8756,0.0328,0.0127,30.9425 +Kodak,12x12,ldr-rgb-kodak20.png,30.9402,0.0273,0.0093,42.3911 +Kodak,12x12,ldr-rgb-kodak21.png,28.6181,0.0346,0.0160,24.5241 +Kodak,12x12,ldr-rgb-kodak22.png,29.7383,0.0300,0.0099,39.5983 +Kodak,12x12,ldr-rgb-kodak23.png,32.4823,0.0263,0.0070,55.8147 +Kodak,12x12,ldr-rgb-kodak24.png,26.7030,0.0369,0.0170,23.1671 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..df2677c --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3120,0.1054,0.0870,4.5197 +Kodak,4x4,ldr-rgb-kodak02.png,45.4397,0.1588,0.1395,2.8188 +Kodak,4x4,ldr-rgb-kodak03.png,47.6879,0.0819,0.0645,6.0955 +Kodak,4x4,ldr-rgb-kodak04.png,45.5017,0.1226,0.1032,3.8092 +Kodak,4x4,ldr-rgb-kodak05.png,42.1778,0.1370,0.1179,3.3345 +Kodak,4x4,ldr-rgb-kodak06.png,45.1998,0.0997,0.0820,4.7977 +Kodak,4x4,ldr-rgb-kodak07.png,46.0247,0.1012,0.0822,4.7830 +Kodak,4x4,ldr-rgb-kodak08.png,42.5327,0.1463,0.1264,3.1117 +Kodak,4x4,ldr-rgb-kodak09.png,47.1830,0.1213,0.1021,3.8508 +Kodak,4x4,ldr-rgb-kodak10.png,46.8614,0.1220,0.1025,3.8362 +Kodak,4x4,ldr-rgb-kodak11.png,44.8994,0.1195,0.1013,3.8808 +Kodak,4x4,ldr-rgb-kodak12.png,47.9784,0.0914,0.0739,5.3180 +Kodak,4x4,ldr-rgb-kodak13.png,41.6520,0.1134,0.0942,4.1755 +Kodak,4x4,ldr-rgb-kodak14.png,42.7319,0.1280,0.1095,3.5904 +Kodak,4x4,ldr-rgb-kodak15.png,45.5485,0.1095,0.0907,4.3369 +Kodak,4x4,ldr-rgb-kodak16.png,47.8885,0.0918,0.0743,5.2953 +Kodak,4x4,ldr-rgb-kodak17.png,46.3480,0.1037,0.0844,4.6577 +Kodak,4x4,ldr-rgb-kodak18.png,42.0493,0.1559,0.1360,2.8912 +Kodak,4x4,ldr-rgb-kodak19.png,45.3597,0.1237,0.1042,3.7729 +Kodak,4x4,ldr-rgb-kodak20.png,46.9280,0.0794,0.0621,6.3270 +Kodak,4x4,ldr-rgb-kodak21.png,45.1814,0.1265,0.1086,3.6221 +Kodak,4x4,ldr-rgb-kodak22.png,43.8216,0.1591,0.1397,2.8155 +Kodak,4x4,ldr-rgb-kodak23.png,46.8701,0.1265,0.1079,3.6436 +Kodak,4x4,ldr-rgb-kodak24.png,42.3775,0.1224,0.1032,3.8095 +Kodak,5x5,ldr-rgb-kodak01.png,40.1116,0.1171,0.0978,4.0187 +Kodak,5x5,ldr-rgb-kodak02.png,41.7670,0.1343,0.1146,3.4313 +Kodak,5x5,ldr-rgb-kodak03.png,44.0723,0.0661,0.0480,8.1845 +Kodak,5x5,ldr-rgb-kodak04.png,42.0904,0.1043,0.0843,4.6628 +Kodak,5x5,ldr-rgb-kodak05.png,37.9986,0.1403,0.1203,3.2695 +Kodak,5x5,ldr-rgb-kodak06.png,40.9739,0.0944,0.0757,5.1945 +Kodak,5x5,ldr-rgb-kodak07.png,42.4746,0.0857,0.0660,5.9550 +Kodak,5x5,ldr-rgb-kodak08.png,38.3608,0.1463,0.1255,3.1337 +Kodak,5x5,ldr-rgb-kodak09.png,43.8088,0.0755,0.0559,7.0319 +Kodak,5x5,ldr-rgb-kodak10.png,43.4231,0.0832,0.0630,6.2382 +Kodak,5x5,ldr-rgb-kodak11.png,40.8590,0.1110,0.0920,4.2745 +Kodak,5x5,ldr-rgb-kodak12.png,44.4017,0.0671,0.0489,8.0430 +Kodak,5x5,ldr-rgb-kodak13.png,36.9301,0.1182,0.0981,4.0080 +Kodak,5x5,ldr-rgb-kodak14.png,38.6960,0.1267,0.1075,3.6563 +Kodak,5x5,ldr-rgb-kodak15.png,41.9491,0.0992,0.0793,4.9560 +Kodak,5x5,ldr-rgb-kodak16.png,44.1356,0.0710,0.0528,7.4416 +Kodak,5x5,ldr-rgb-kodak17.png,42.5454,0.0737,0.0538,7.3124 +Kodak,5x5,ldr-rgb-kodak18.png,38.3941,0.1328,0.1120,3.5100 +Kodak,5x5,ldr-rgb-kodak19.png,41.6442,0.0921,0.0718,5.4763 +Kodak,5x5,ldr-rgb-kodak20.png,42.9823,0.0685,0.0506,7.7683 +Kodak,5x5,ldr-rgb-kodak21.png,40.7705,0.0953,0.0767,5.1294 +Kodak,5x5,ldr-rgb-kodak22.png,40.2982,0.1304,0.1097,3.5858 +Kodak,5x5,ldr-rgb-kodak23.png,43.5860,0.0906,0.0711,5.5295 +Kodak,5x5,ldr-rgb-kodak24.png,38.2072,0.1096,0.0896,4.3887 +Kodak,6x6,ldr-rgb-kodak01.png,36.1963,0.1205,0.1017,3.8651 +Kodak,6x6,ldr-rgb-kodak02.png,39.0475,0.1085,0.0892,4.4082 +Kodak,6x6,ldr-rgb-kodak03.png,41.3520,0.0567,0.0390,10.0732 +Kodak,6x6,ldr-rgb-kodak04.png,39.4032,0.0914,0.0716,5.4882 +Kodak,6x6,ldr-rgb-kodak05.png,34.7993,0.1373,0.1177,3.3410 +Kodak,6x6,ldr-rgb-kodak06.png,37.6376,0.0873,0.0689,5.7064 +Kodak,6x6,ldr-rgb-kodak07.png,39.7936,0.0762,0.0567,6.9295 +Kodak,6x6,ldr-rgb-kodak08.png,34.9845,0.1447,0.1241,3.1679 +Kodak,6x6,ldr-rgb-kodak09.png,40.8865,0.0609,0.0416,9.4544 +Kodak,6x6,ldr-rgb-kodak10.png,40.5154,0.0643,0.0445,8.8282 +Kodak,6x6,ldr-rgb-kodak11.png,37.5965,0.0964,0.0779,5.0452 +Kodak,6x6,ldr-rgb-kodak12.png,41.4939,0.0551,0.0373,10.5499 +Kodak,6x6,ldr-rgb-kodak13.png,32.9110,0.1293,0.1097,3.5851 +Kodak,6x6,ldr-rgb-kodak14.png,35.8527,0.1226,0.1028,3.8254 +Kodak,6x6,ldr-rgb-kodak15.png,39.2227,0.0907,0.0712,5.5237 +Kodak,6x6,ldr-rgb-kodak16.png,41.0391,0.0615,0.0434,9.0607 +Kodak,6x6,ldr-rgb-kodak17.png,39.4992,0.0637,0.0440,8.9333 +Kodak,6x6,ldr-rgb-kodak18.png,35.3684,0.1206,0.1003,3.9213 +Kodak,6x6,ldr-rgb-kodak19.png,38.5288,0.0833,0.0635,6.1917 +Kodak,6x6,ldr-rgb-kodak20.png,39.7703,0.0638,0.0459,8.5584 +Kodak,6x6,ldr-rgb-kodak21.png,37.2034,0.0849,0.0663,5.9324 +Kodak,6x6,ldr-rgb-kodak22.png,37.4752,0.1108,0.0908,4.3312 +Kodak,6x6,ldr-rgb-kodak23.png,40.9962,0.0690,0.0497,7.9118 +Kodak,6x6,ldr-rgb-kodak24.png,35.0626,0.0991,0.0794,4.9500 +Kodak,8x8,ldr-rgb-kodak01.png,31.8007,0.1658,0.1464,2.6852 +Kodak,8x8,ldr-rgb-kodak02.png,35.7971,0.1113,0.0910,4.3193 +Kodak,8x8,ldr-rgb-kodak03.png,37.7637,0.0703,0.0519,7.5794 +Kodak,8x8,ldr-rgb-kodak04.png,36.0993,0.1021,0.0818,4.8058 +Kodak,8x8,ldr-rgb-kodak05.png,30.7474,0.1807,0.1606,2.4492 +Kodak,8x8,ldr-rgb-kodak06.png,33.4449,0.1121,0.0928,4.2373 +Kodak,8x8,ldr-rgb-kodak07.png,36.1506,0.0932,0.0729,5.3949 +Kodak,8x8,ldr-rgb-kodak08.png,30.5414,0.1828,0.1618,2.4300 +Kodak,8x8,ldr-rgb-kodak09.png,37.2629,0.0721,0.0522,7.5385 +Kodak,8x8,ldr-rgb-kodak10.png,36.9234,0.0734,0.0530,7.4255 +Kodak,8x8,ldr-rgb-kodak11.png,33.6680,0.1155,0.0962,4.0870 +Kodak,8x8,ldr-rgb-kodak12.png,37.8337,0.0689,0.0503,7.8236 +Kodak,8x8,ldr-rgb-kodak13.png,28.3966,0.1777,0.1575,2.4963 +Kodak,8x8,ldr-rgb-kodak14.png,32.1516,0.1539,0.1343,2.9288 +Kodak,8x8,ldr-rgb-kodak15.png,35.8462,0.0938,0.0739,5.3188 +Kodak,8x8,ldr-rgb-kodak16.png,37.0251,0.0777,0.0591,6.6500 +Kodak,8x8,ldr-rgb-kodak17.png,35.6698,0.0787,0.0584,6.7321 +Kodak,8x8,ldr-rgb-kodak18.png,31.5577,0.1426,0.1216,3.2346 +Kodak,8x8,ldr-rgb-kodak19.png,34.7618,0.0998,0.0793,4.9558 +Kodak,8x8,ldr-rgb-kodak20.png,35.9030,0.0784,0.0599,6.5674 +Kodak,8x8,ldr-rgb-kodak21.png,33.1158,0.1080,0.0889,4.4230 +Kodak,8x8,ldr-rgb-kodak22.png,34.0434,0.1226,0.1021,3.8508 +Kodak,8x8,ldr-rgb-kodak23.png,37.6714,0.0721,0.0525,7.4871 +Kodak,8x8,ldr-rgb-kodak24.png,31.1289,0.1208,0.1004,3.9158 +Kodak,12x12,ldr-rgb-kodak01.png,27.7549,0.1761,0.1539,2.5548 +Kodak,12x12,ldr-rgb-kodak02.png,32.4572,0.0844,0.0615,6.3915 +Kodak,12x12,ldr-rgb-kodak03.png,33.8229,0.0625,0.0413,9.5235 +Kodak,12x12,ldr-rgb-kodak04.png,32.4332,0.0746,0.0509,7.7221 +Kodak,12x12,ldr-rgb-kodak05.png,26.4002,0.1918,0.1687,2.3312 +Kodak,12x12,ldr-rgb-kodak06.png,29.3776,0.1145,0.0926,4.2448 +Kodak,12x12,ldr-rgb-kodak07.png,32.0454,0.0900,0.0672,5.8549 +Kodak,12x12,ldr-rgb-kodak08.png,26.0607,0.1985,0.1747,2.2507 +Kodak,12x12,ldr-rgb-kodak09.png,33.1013,0.0669,0.0441,8.9116 +Kodak,12x12,ldr-rgb-kodak10.png,32.4879,0.0669,0.0437,8.9900 +Kodak,12x12,ldr-rgb-kodak11.png,29.7550,0.1083,0.0863,4.5561 +Kodak,12x12,ldr-rgb-kodak12.png,33.8849,0.0621,0.0407,9.6594 +Kodak,12x12,ldr-rgb-kodak13.png,24.5283,0.1991,0.1758,2.2365 +Kodak,12x12,ldr-rgb-kodak14.png,28.4299,0.1517,0.1295,3.0355 +Kodak,12x12,ldr-rgb-kodak15.png,32.2405,0.0842,0.0613,6.4145 +Kodak,12x12,ldr-rgb-kodak16.png,32.9828,0.0711,0.0497,7.9129 +Kodak,12x12,ldr-rgb-kodak17.png,31.7910,0.0732,0.0500,7.8622 +Kodak,12x12,ldr-rgb-kodak18.png,27.7838,0.1348,0.1109,3.5455 +Kodak,12x12,ldr-rgb-kodak19.png,30.8959,0.0951,0.0716,5.4925 +Kodak,12x12,ldr-rgb-kodak20.png,31.8670,0.0741,0.0529,7.4387 +Kodak,12x12,ldr-rgb-kodak21.png,29.1816,0.1172,0.0953,4.1243 +Kodak,12x12,ldr-rgb-kodak22.png,30.5137,0.1019,0.0787,4.9973 +Kodak,12x12,ldr-rgb-kodak23.png,33.5616,0.0580,0.0354,11.1012 +Kodak,12x12,ldr-rgb-kodak24.png,27.1047,0.1197,0.0964,4.0806 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..6143786 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5115,0.2322,0.2144,1.8344 +Kodak,4x4,ldr-rgb-kodak02.png,45.6982,0.3388,0.3193,1.2313 +Kodak,4x4,ldr-rgb-kodak03.png,48.0607,0.2654,0.2477,1.5872 +Kodak,4x4,ldr-rgb-kodak04.png,45.6858,0.3001,0.2806,1.4011 +Kodak,4x4,ldr-rgb-kodak05.png,42.4370,0.2940,0.2750,1.4299 +Kodak,4x4,ldr-rgb-kodak06.png,45.3960,0.2441,0.2262,1.7380 +Kodak,4x4,ldr-rgb-kodak07.png,46.3753,0.2935,0.2745,1.4323 +Kodak,4x4,ldr-rgb-kodak08.png,42.8242,0.3092,0.2892,1.3597 +Kodak,4x4,ldr-rgb-kodak09.png,47.4389,0.3143,0.2953,1.3316 +Kodak,4x4,ldr-rgb-kodak10.png,47.0911,0.3129,0.2933,1.3405 +Kodak,4x4,ldr-rgb-kodak11.png,45.1383,0.2816,0.2632,1.4938 +Kodak,4x4,ldr-rgb-kodak12.png,48.2774,0.2697,0.2514,1.5638 +Kodak,4x4,ldr-rgb-kodak13.png,41.7584,0.2430,0.2235,1.7597 +Kodak,4x4,ldr-rgb-kodak14.png,42.9859,0.2773,0.2582,1.5227 +Kodak,4x4,ldr-rgb-kodak15.png,45.8334,0.2882,0.2692,1.4607 +Kodak,4x4,ldr-rgb-kodak16.png,48.0940,0.2666,0.2487,1.5809 +Kodak,4x4,ldr-rgb-kodak17.png,46.5075,0.2812,0.2619,1.5016 +Kodak,4x4,ldr-rgb-kodak18.png,42.2101,0.3299,0.3095,1.2706 +Kodak,4x4,ldr-rgb-kodak19.png,45.5658,0.2980,0.2782,1.4136 +Kodak,4x4,ldr-rgb-kodak20.png,47.1799,0.1905,0.1730,2.2726 +Kodak,4x4,ldr-rgb-kodak21.png,45.3342,0.3007,0.2825,1.3921 +Kodak,4x4,ldr-rgb-kodak22.png,44.0086,0.3434,0.3239,1.2139 +Kodak,4x4,ldr-rgb-kodak23.png,47.1907,0.3308,0.3120,1.2605 +Kodak,4x4,ldr-rgb-kodak24.png,42.6019,0.2939,0.2743,1.4334 +Kodak,5x5,ldr-rgb-kodak01.png,40.2236,0.2878,0.2688,1.4629 +Kodak,5x5,ldr-rgb-kodak02.png,42.0380,0.3793,0.3591,1.0950 +Kodak,5x5,ldr-rgb-kodak03.png,44.3676,0.2842,0.2653,1.4821 +Kodak,5x5,ldr-rgb-kodak04.png,42.2612,0.3135,0.2931,1.3414 +Kodak,5x5,ldr-rgb-kodak05.png,38.1929,0.3424,0.3222,1.2205 +Kodak,5x5,ldr-rgb-kodak06.png,41.0984,0.2705,0.2516,1.5629 +Kodak,5x5,ldr-rgb-kodak07.png,42.7456,0.3169,0.2964,1.3268 +Kodak,5x5,ldr-rgb-kodak08.png,38.5418,0.3408,0.3192,1.2319 +Kodak,5x5,ldr-rgb-kodak09.png,44.0366,0.3076,0.2880,1.3656 +Kodak,5x5,ldr-rgb-kodak10.png,43.6071,0.3166,0.2961,1.3278 +Kodak,5x5,ldr-rgb-kodak11.png,41.0130,0.3050,0.2860,1.3751 +Kodak,5x5,ldr-rgb-kodak12.png,44.6149,0.2844,0.2659,1.4788 +Kodak,5x5,ldr-rgb-kodak13.png,36.9748,0.2640,0.2440,1.6115 +Kodak,5x5,ldr-rgb-kodak14.png,38.9092,0.3152,0.2952,1.3320 +Kodak,5x5,ldr-rgb-kodak15.png,42.1668,0.3069,0.2870,1.3699 +Kodak,5x5,ldr-rgb-kodak16.png,44.2715,0.2801,0.2616,1.5030 +Kodak,5x5,ldr-rgb-kodak17.png,42.6407,0.2887,0.2686,1.4642 +Kodak,5x5,ldr-rgb-kodak18.png,38.4820,0.3401,0.3189,1.2331 +Kodak,5x5,ldr-rgb-kodak19.png,41.7841,0.3178,0.2973,1.3227 +Kodak,5x5,ldr-rgb-kodak20.png,43.2953,0.2031,0.1849,2.1270 +Kodak,5x5,ldr-rgb-kodak21.png,40.8774,0.3249,0.3054,1.2876 +Kodak,5x5,ldr-rgb-kodak22.png,40.4425,0.3691,0.3484,1.1285 +Kodak,5x5,ldr-rgb-kodak23.png,43.9057,0.3620,0.3426,1.1477 +Kodak,5x5,ldr-rgb-kodak24.png,38.3273,0.3203,0.3003,1.3096 +Kodak,6x6,ldr-rgb-kodak01.png,36.3105,0.3328,0.3138,1.2530 +Kodak,6x6,ldr-rgb-kodak02.png,39.4083,0.4190,0.3996,0.9841 +Kodak,6x6,ldr-rgb-kodak03.png,41.7533,0.2557,0.2378,1.6533 +Kodak,6x6,ldr-rgb-kodak04.png,39.6674,0.3372,0.3175,1.2387 +Kodak,6x6,ldr-rgb-kodak05.png,34.9944,0.3802,0.3608,1.0900 +Kodak,6x6,ldr-rgb-kodak06.png,37.7608,0.2957,0.2773,1.4183 +Kodak,6x6,ldr-rgb-kodak07.png,40.1279,0.2988,0.2788,1.4103 +Kodak,6x6,ldr-rgb-kodak08.png,35.1750,0.3753,0.3548,1.1082 +Kodak,6x6,ldr-rgb-kodak09.png,41.2718,0.3218,0.3022,1.3011 +Kodak,6x6,ldr-rgb-kodak10.png,40.8412,0.3463,0.3266,1.2038 +Kodak,6x6,ldr-rgb-kodak11.png,37.7820,0.3291,0.3106,1.2659 +Kodak,6x6,ldr-rgb-kodak12.png,41.8395,0.2975,0.2794,1.4076 +Kodak,6x6,ldr-rgb-kodak13.png,32.9600,0.3150,0.2955,1.3307 +Kodak,6x6,ldr-rgb-kodak14.png,36.0500,0.3586,0.3397,1.1575 +Kodak,6x6,ldr-rgb-kodak15.png,39.4760,0.3008,0.2813,1.3980 +Kodak,6x6,ldr-rgb-kodak16.png,41.2318,0.2823,0.2644,1.4872 +Kodak,6x6,ldr-rgb-kodak17.png,39.6707,0.3118,0.2922,1.3457 +Kodak,6x6,ldr-rgb-kodak18.png,35.4565,0.3807,0.3603,1.0914 +Kodak,6x6,ldr-rgb-kodak19.png,38.7066,0.3546,0.3346,1.1750 +Kodak,6x6,ldr-rgb-kodak20.png,40.1121,0.2237,0.2059,1.9093 +Kodak,6x6,ldr-rgb-kodak21.png,37.3497,0.3526,0.3341,1.1771 +Kodak,6x6,ldr-rgb-kodak22.png,37.6441,0.4080,0.3874,1.0149 +Kodak,6x6,ldr-rgb-kodak23.png,41.4416,0.3696,0.3505,1.1219 +Kodak,6x6,ldr-rgb-kodak24.png,35.1795,0.3364,0.3165,1.2422 +Kodak,8x8,ldr-rgb-kodak01.png,31.9076,0.4233,0.4027,0.9765 +Kodak,8x8,ldr-rgb-kodak02.png,36.1658,0.4256,0.4042,0.9729 +Kodak,8x8,ldr-rgb-kodak03.png,38.2015,0.2292,0.2094,1.8781 +Kodak,8x8,ldr-rgb-kodak04.png,36.3849,0.3422,0.3201,1.2282 +Kodak,8x8,ldr-rgb-kodak05.png,30.9159,0.4609,0.4393,0.8951 +Kodak,8x8,ldr-rgb-kodak06.png,33.5799,0.3532,0.3324,1.1830 +Kodak,8x8,ldr-rgb-kodak07.png,36.5075,0.2821,0.2608,1.5075 +Kodak,8x8,ldr-rgb-kodak08.png,30.7382,0.4988,0.4764,0.8255 +Kodak,8x8,ldr-rgb-kodak09.png,37.5585,0.2575,0.2360,1.6661 +Kodak,8x8,ldr-rgb-kodak10.png,37.2383,0.2946,0.2727,1.4418 +Kodak,8x8,ldr-rgb-kodak11.png,33.8328,0.4075,0.3867,1.0170 +Kodak,8x8,ldr-rgb-kodak12.png,38.2628,0.2657,0.2453,1.6029 +Kodak,8x8,ldr-rgb-kodak13.png,28.4607,0.4379,0.4155,0.9463 +Kodak,8x8,ldr-rgb-kodak14.png,32.3242,0.4457,0.4248,0.9257 +Kodak,8x8,ldr-rgb-kodak15.png,36.0684,0.3259,0.3043,1.2922 +Kodak,8x8,ldr-rgb-kodak16.png,37.2660,0.2851,0.2654,1.4816 +Kodak,8x8,ldr-rgb-kodak17.png,35.8716,0.2823,0.2604,1.5099 +Kodak,8x8,ldr-rgb-kodak18.png,31.6551,0.4527,0.4303,0.9139 +Kodak,8x8,ldr-rgb-kodak19.png,34.9274,0.3073,0.2852,1.3788 +Kodak,8x8,ldr-rgb-kodak20.png,36.1555,0.2464,0.2264,1.7368 +Kodak,8x8,ldr-rgb-kodak21.png,33.2255,0.3293,0.3087,1.2739 +Kodak,8x8,ldr-rgb-kodak22.png,34.2304,0.4234,0.4016,0.9792 +Kodak,8x8,ldr-rgb-kodak23.png,38.1991,0.2809,0.2597,1.5140 +Kodak,8x8,ldr-rgb-kodak24.png,31.2348,0.3721,0.3504,1.1222 +Kodak,12x12,ldr-rgb-kodak01.png,27.9132,0.5316,0.5070,0.7756 +Kodak,12x12,ldr-rgb-kodak02.png,33.0052,0.3946,0.3695,1.0643 +Kodak,12x12,ldr-rgb-kodak03.png,34.4542,0.2360,0.2122,1.8527 +Kodak,12x12,ldr-rgb-kodak04.png,32.9738,0.3457,0.3192,1.2318 +Kodak,12x12,ldr-rgb-kodak05.png,26.6073,0.5730,0.5477,0.7179 +Kodak,12x12,ldr-rgb-kodak06.png,29.5310,0.3876,0.3634,1.0819 +Kodak,12x12,ldr-rgb-kodak07.png,32.6281,0.3024,0.2770,1.4197 +Kodak,12x12,ldr-rgb-kodak08.png,26.2616,0.5781,0.5515,0.7129 +Kodak,12x12,ldr-rgb-kodak09.png,33.6343,0.2732,0.2477,1.5874 +Kodak,12x12,ldr-rgb-kodak10.png,32.9910,0.2690,0.2433,1.6160 +Kodak,12x12,ldr-rgb-kodak11.png,30.0541,0.4209,0.3966,0.9914 +Kodak,12x12,ldr-rgb-kodak12.png,34.4512,0.2481,0.2237,1.7576 +Kodak,12x12,ldr-rgb-kodak13.png,24.5887,0.6160,0.5906,0.6658 +Kodak,12x12,ldr-rgb-kodak14.png,28.6476,0.5072,0.4826,0.8148 +Kodak,12x12,ldr-rgb-kodak15.png,32.7352,0.3323,0.3071,1.2804 +Kodak,12x12,ldr-rgb-kodak16.png,33.3387,0.2921,0.2685,1.4647 +Kodak,12x12,ldr-rgb-kodak17.png,32.1425,0.2892,0.2632,1.4941 +Kodak,12x12,ldr-rgb-kodak18.png,27.9244,0.5041,0.4780,0.8227 +Kodak,12x12,ldr-rgb-kodak19.png,31.1081,0.3960,0.3699,1.0630 +Kodak,12x12,ldr-rgb-kodak20.png,32.1616,0.3074,0.2836,1.3866 +Kodak,12x12,ldr-rgb-kodak21.png,29.3265,0.3742,0.3492,1.1261 +Kodak,12x12,ldr-rgb-kodak22.png,30.7890,0.4429,0.4169,0.9432 +Kodak,12x12,ldr-rgb-kodak23.png,34.3835,0.2448,0.2193,1.7929 +Kodak,12x12,ldr-rgb-kodak24.png,27.2381,0.4507,0.4249,0.9255 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..d2fba4c --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.8820,0.0324,0.0157,25.1030 +Kodak,4x4,ldr-rgb-kodak02.png,44.2873,0.0404,0.0230,17.0971 +Kodak,4x4,ldr-rgb-kodak03.png,46.7875,0.0286,0.0128,30.7389 +Kodak,4x4,ldr-rgb-kodak04.png,44.6627,0.0380,0.0203,19.3351 +Kodak,4x4,ldr-rgb-kodak05.png,41.6532,0.0480,0.0305,12.9038 +Kodak,4x4,ldr-rgb-kodak06.png,44.7930,0.0316,0.0155,25.3328 +Kodak,4x4,ldr-rgb-kodak07.png,45.1555,0.0345,0.0173,22.7608 +Kodak,4x4,ldr-rgb-kodak08.png,42.1261,0.0500,0.0315,12.4644 +Kodak,4x4,ldr-rgb-kodak09.png,46.3501,0.0287,0.0116,33.8221 +Kodak,4x4,ldr-rgb-kodak10.png,46.1138,0.0297,0.0123,32.0234 +Kodak,4x4,ldr-rgb-kodak11.png,44.3024,0.0352,0.0189,20.7997 +Kodak,4x4,ldr-rgb-kodak12.png,47.1128,0.0271,0.0115,34.1513 +Kodak,4x4,ldr-rgb-kodak13.png,41.4830,0.0435,0.0261,15.0767 +Kodak,4x4,ldr-rgb-kodak14.png,41.9274,0.0422,0.0254,15.4913 +Kodak,4x4,ldr-rgb-kodak15.png,44.7388,0.0393,0.0221,17.8110 +Kodak,4x4,ldr-rgb-kodak16.png,47.2478,0.0259,0.0101,38.8246 +Kodak,4x4,ldr-rgb-kodak17.png,45.8440,0.0288,0.0112,35.2280 +Kodak,4x4,ldr-rgb-kodak18.png,41.6843,0.0485,0.0302,13.0359 +Kodak,4x4,ldr-rgb-kodak19.png,44.8511,0.0329,0.0151,25.9723 +Kodak,4x4,ldr-rgb-kodak20.png,46.4186,0.0284,0.0130,30.3475 +Kodak,4x4,ldr-rgb-kodak21.png,44.6411,0.0321,0.0159,24.7244 +Kodak,4x4,ldr-rgb-kodak22.png,43.2351,0.0433,0.0254,15.4559 +Kodak,4x4,ldr-rgb-kodak23.png,45.6659,0.0320,0.0155,25.3215 +Kodak,4x4,ldr-rgb-kodak24.png,41.9807,0.0422,0.0244,16.0931 +Kodak,5x5,ldr-rgb-kodak01.png,39.6135,0.0316,0.0151,26.0371 +Kodak,5x5,ldr-rgb-kodak02.png,40.6534,0.0323,0.0148,26.5724 +Kodak,5x5,ldr-rgb-kodak03.png,43.0540,0.0261,0.0100,39.2823 +Kodak,5x5,ldr-rgb-kodak04.png,41.2613,0.0314,0.0136,28.9234 +Kodak,5x5,ldr-rgb-kodak05.png,37.4541,0.0437,0.0260,15.1441 +Kodak,5x5,ldr-rgb-kodak06.png,40.5884,0.0285,0.0122,32.1463 +Kodak,5x5,ldr-rgb-kodak07.png,41.4931,0.0304,0.0129,30.5386 +Kodak,5x5,ldr-rgb-kodak08.png,37.7792,0.0447,0.0260,15.1383 +Kodak,5x5,ldr-rgb-kodak09.png,42.9214,0.0263,0.0089,44.3805 +Kodak,5x5,ldr-rgb-kodak10.png,42.6313,0.0271,0.0093,42.3497 +Kodak,5x5,ldr-rgb-kodak11.png,40.3040,0.0308,0.0141,27.7907 +Kodak,5x5,ldr-rgb-kodak12.png,43.4157,0.0243,0.0084,47.0856 +Kodak,5x5,ldr-rgb-kodak13.png,36.8276,0.0401,0.0222,17.7341 +Kodak,5x5,ldr-rgb-kodak14.png,38.0242,0.0405,0.0234,16.8034 +Kodak,5x5,ldr-rgb-kodak15.png,41.1917,0.0315,0.0141,27.8560 +Kodak,5x5,ldr-rgb-kodak16.png,43.4667,0.0235,0.0076,51.5219 +Kodak,5x5,ldr-rgb-kodak17.png,42.0469,0.0264,0.0087,45.1767 +Kodak,5x5,ldr-rgb-kodak18.png,38.1147,0.0386,0.0199,19.7854 +Kodak,5x5,ldr-rgb-kodak19.png,41.1276,0.0287,0.0110,35.6660 +Kodak,5x5,ldr-rgb-kodak20.png,42.3603,0.0257,0.0097,40.5126 +Kodak,5x5,ldr-rgb-kodak21.png,40.4227,0.0298,0.0131,29.9801 +Kodak,5x5,ldr-rgb-kodak22.png,39.7897,0.0339,0.0159,24.7148 +Kodak,5x5,ldr-rgb-kodak23.png,42.5143,0.0277,0.0106,36.9501 +Kodak,5x5,ldr-rgb-kodak24.png,37.8892,0.0363,0.0184,21.3172 +Kodak,6x6,ldr-rgb-kodak01.png,35.7507,0.0388,0.0221,17.8176 +Kodak,6x6,ldr-rgb-kodak02.png,38.1712,0.0325,0.0154,25.5998 +Kodak,6x6,ldr-rgb-kodak03.png,40.5686,0.0256,0.0098,39.9290 +Kodak,6x6,ldr-rgb-kodak04.png,38.5433,0.0317,0.0141,27.9012 +Kodak,6x6,ldr-rgb-kodak05.png,34.3631,0.0489,0.0314,12.5396 +Kodak,6x6,ldr-rgb-kodak06.png,37.3004,0.0314,0.0151,26.0322 +Kodak,6x6,ldr-rgb-kodak07.png,38.8820,0.0310,0.0137,28.6182 +Kodak,6x6,ldr-rgb-kodak08.png,34.4474,0.0499,0.0313,12.5599 +Kodak,6x6,ldr-rgb-kodak09.png,39.9734,0.0275,0.0104,37.8750 +Kodak,6x6,ldr-rgb-kodak10.png,39.7372,0.0276,0.0101,38.9318 +Kodak,6x6,ldr-rgb-kodak11.png,37.1533,0.0330,0.0165,23.7609 +Kodak,6x6,ldr-rgb-kodak12.png,40.7387,0.0245,0.0087,45.2548 +Kodak,6x6,ldr-rgb-kodak13.png,32.8130,0.0499,0.0322,12.2189 +Kodak,6x6,ldr-rgb-kodak14.png,35.3037,0.0442,0.0272,14.4741 +Kodak,6x6,ldr-rgb-kodak15.png,38.5680,0.0319,0.0147,26.8208 +Kodak,6x6,ldr-rgb-kodak16.png,40.4942,0.0243,0.0087,45.1248 +Kodak,6x6,ldr-rgb-kodak17.png,38.9398,0.0279,0.0103,38.0138 +Kodak,6x6,ldr-rgb-kodak18.png,35.1209,0.0408,0.0223,17.6330 +Kodak,6x6,ldr-rgb-kodak19.png,37.9783,0.0324,0.0147,26.8278 +Kodak,6x6,ldr-rgb-kodak20.png,39.1839,0.0272,0.0116,34.0238 +Kodak,6x6,ldr-rgb-kodak21.png,36.9075,0.0331,0.0168,23.4125 +Kodak,6x6,ldr-rgb-kodak22.png,36.9849,0.0352,0.0175,22.4158 +Kodak,6x6,ldr-rgb-kodak23.png,40.0615,0.0273,0.0104,37.8533 +Kodak,6x6,ldr-rgb-kodak24.png,34.7936,0.0379,0.0204,19.2865 +Kodak,8x8,ldr-rgb-kodak01.png,31.3361,0.0500,0.0331,11.8918 +Kodak,8x8,ldr-rgb-kodak02.png,34.9328,0.0327,0.0152,25.8085 +Kodak,8x8,ldr-rgb-kodak03.png,36.5952,0.0275,0.0114,34.4236 +Kodak,8x8,ldr-rgb-kodak04.png,35.1760,0.0329,0.0149,26.3478 +Kodak,8x8,ldr-rgb-kodak05.png,30.2523,0.0581,0.0401,9.8088 +Kodak,8x8,ldr-rgb-kodak06.png,32.9457,0.0395,0.0229,17.1747 +Kodak,8x8,ldr-rgb-kodak07.png,34.9951,0.0343,0.0170,23.1032 +Kodak,8x8,ldr-rgb-kodak08.png,29.9694,0.0599,0.0413,9.5219 +Kodak,8x8,ldr-rgb-kodak09.png,36.1703,0.0299,0.0126,31.1259 +Kodak,8x8,ldr-rgb-kodak10.png,35.8857,0.0295,0.0117,33.5019 +Kodak,8x8,ldr-rgb-kodak11.png,33.0088,0.0377,0.0211,18.6723 +Kodak,8x8,ldr-rgb-kodak12.png,36.7290,0.0269,0.0111,35.5178 +Kodak,8x8,ldr-rgb-kodak13.png,28.2209,0.0660,0.0481,8.1691 +Kodak,8x8,ldr-rgb-kodak14.png,31.5032,0.0491,0.0320,12.2911 +Kodak,8x8,ldr-rgb-kodak15.png,34.9394,0.0328,0.0156,25.2630 +Kodak,8x8,ldr-rgb-kodak16.png,36.0527,0.0296,0.0137,28.6227 +Kodak,8x8,ldr-rgb-kodak17.png,34.9073,0.0316,0.0135,29.0538 +Kodak,8x8,ldr-rgb-kodak18.png,31.2398,0.0466,0.0281,14.0098 +Kodak,8x8,ldr-rgb-kodak19.png,34.2235,0.0364,0.0185,21.2551 +Kodak,8x8,ldr-rgb-kodak20.png,35.2317,0.0292,0.0135,29.0451 +Kodak,8x8,ldr-rgb-kodak21.png,32.7551,0.0389,0.0224,17.5896 +Kodak,8x8,ldr-rgb-kodak22.png,33.4546,0.0378,0.0200,19.6892 +Kodak,8x8,ldr-rgb-kodak23.png,36.5268,0.0280,0.0106,36.9352 +Kodak,8x8,ldr-rgb-kodak24.png,30.8238,0.0434,0.0255,15.4117 +Kodak,12x12,ldr-rgb-kodak01.png,27.1080,0.0467,0.0280,14.0474 +Kodak,12x12,ldr-rgb-kodak02.png,31.1083,0.0278,0.0087,45.4319 +Kodak,12x12,ldr-rgb-kodak03.png,32.6856,0.0253,0.0076,51.7336 +Kodak,12x12,ldr-rgb-kodak04.png,31.5645,0.0268,0.0071,55.3836 +Kodak,12x12,ldr-rgb-kodak05.png,25.8227,0.0513,0.0317,12.4059 +Kodak,12x12,ldr-rgb-kodak06.png,28.6373,0.0378,0.0196,20.0734 +Kodak,12x12,ldr-rgb-kodak07.png,30.8590,0.0293,0.0102,38.4597 +Kodak,12x12,ldr-rgb-kodak08.png,25.4179,0.0573,0.0369,10.6586 +Kodak,12x12,ldr-rgb-kodak09.png,31.8377,0.0279,0.0088,44.9184 +Kodak,12x12,ldr-rgb-kodak10.png,31.5385,0.0280,0.0083,47.1139 +Kodak,12x12,ldr-rgb-kodak11.png,28.9359,0.0329,0.0146,26.9215 +Kodak,12x12,ldr-rgb-kodak12.png,32.2823,0.0250,0.0072,54.4079 +Kodak,12x12,ldr-rgb-kodak13.png,24.3217,0.0592,0.0397,9.9105 +Kodak,12x12,ldr-rgb-kodak14.png,27.5443,0.0390,0.0205,19.2254 +Kodak,12x12,ldr-rgb-kodak15.png,31.2551,0.0300,0.0108,36.2644 +Kodak,12x12,ldr-rgb-kodak16.png,31.4853,0.0270,0.0093,42.1398 +Kodak,12x12,ldr-rgb-kodak17.png,30.8975,0.0288,0.0092,42.7914 +Kodak,12x12,ldr-rgb-kodak18.png,27.4230,0.0395,0.0194,20.3034 +Kodak,12x12,ldr-rgb-kodak19.png,30.1902,0.0342,0.0145,27.1502 +Kodak,12x12,ldr-rgb-kodak20.png,31.0526,0.0281,0.0103,38.1616 +Kodak,12x12,ldr-rgb-kodak21.png,28.7136,0.0373,0.0190,20.6911 +Kodak,12x12,ldr-rgb-kodak22.png,29.8371,0.0309,0.0113,34.8189 +Kodak,12x12,ldr-rgb-kodak23.png,32.5213,0.0265,0.0076,51.4143 +Kodak,12x12,ldr-rgb-kodak24.png,26.7723,0.0396,0.0199,19.7647 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..3306593 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5460,0.0273,0.0113,34.7639 +Kodak,4x4,ldr-rgb-kodak02.png,43.8803,0.0317,0.0150,26.1357 +Kodak,4x4,ldr-rgb-kodak03.png,46.1873,0.0241,0.0091,43.3687 +Kodak,4x4,ldr-rgb-kodak04.png,44.2426,0.0303,0.0135,29.1380 +Kodak,4x4,ldr-rgb-kodak05.png,41.1063,0.0351,0.0183,21.5026 +Kodak,4x4,ldr-rgb-kodak06.png,44.5076,0.0268,0.0112,35.0304 +Kodak,4x4,ldr-rgb-kodak07.png,44.7021,0.0281,0.0116,33.8867 +Kodak,4x4,ldr-rgb-kodak08.png,41.5547,0.0366,0.0187,21.0285 +Kodak,4x4,ldr-rgb-kodak09.png,46.0133,0.0253,0.0087,45.2238 +Kodak,4x4,ldr-rgb-kodak10.png,45.7710,0.0260,0.0091,43.1012 +Kodak,4x4,ldr-rgb-kodak11.png,43.9057,0.0285,0.0128,30.8188 +Kodak,4x4,ldr-rgb-kodak12.png,46.5477,0.0237,0.0086,45.9470 +Kodak,4x4,ldr-rgb-kodak13.png,41.2213,0.0342,0.0173,22.6912 +Kodak,4x4,ldr-rgb-kodak14.png,41.2633,0.0313,0.0151,26.0890 +Kodak,4x4,ldr-rgb-kodak15.png,44.2793,0.0308,0.0140,28.0650 +Kodak,4x4,ldr-rgb-kodak16.png,47.1118,0.0231,0.0081,48.5150 +Kodak,4x4,ldr-rgb-kodak17.png,45.6149,0.0253,0.0086,45.8143 +Kodak,4x4,ldr-rgb-kodak18.png,41.3441,0.0358,0.0182,21.5557 +Kodak,4x4,ldr-rgb-kodak19.png,44.5863,0.0280,0.0109,36.0977 +Kodak,4x4,ldr-rgb-kodak20.png,45.9269,0.0242,0.0093,42.4959 +Kodak,4x4,ldr-rgb-kodak21.png,44.3216,0.0272,0.0113,34.7859 +Kodak,4x4,ldr-rgb-kodak22.png,42.8634,0.0331,0.0159,24.7630 +Kodak,4x4,ldr-rgb-kodak23.png,45.3579,0.0273,0.0109,36.0488 +Kodak,4x4,ldr-rgb-kodak24.png,41.4243,0.0322,0.0151,26.0129 +Kodak,5x5,ldr-rgb-kodak01.png,39.3930,0.0285,0.0127,31.0597 +Kodak,5x5,ldr-rgb-kodak02.png,40.4266,0.0279,0.0113,34.7273 +Kodak,5x5,ldr-rgb-kodak03.png,42.6948,0.0231,0.0079,49.8811 +Kodak,5x5,ldr-rgb-kodak04.png,40.8613,0.0277,0.0106,36.9700 +Kodak,5x5,ldr-rgb-kodak05.png,37.1066,0.0350,0.0182,21.5602 +Kodak,5x5,ldr-rgb-kodak06.png,40.4306,0.0259,0.0103,38.2022 +Kodak,5x5,ldr-rgb-kodak07.png,41.1804,0.0267,0.0101,39.0018 +Kodak,5x5,ldr-rgb-kodak08.png,37.4468,0.0365,0.0186,21.1385 +Kodak,5x5,ldr-rgb-kodak09.png,42.6180,0.0239,0.0075,52.5680 +Kodak,5x5,ldr-rgb-kodak10.png,42.4264,0.0246,0.0078,50.5027 +Kodak,5x5,ldr-rgb-kodak11.png,40.0808,0.0267,0.0110,35.8023 +Kodak,5x5,ldr-rgb-kodak12.png,43.2020,0.0222,0.0071,55.2038 +Kodak,5x5,ldr-rgb-kodak13.png,36.7364,0.0347,0.0176,22.2937 +Kodak,5x5,ldr-rgb-kodak14.png,37.5843,0.0311,0.0151,26.0354 +Kodak,5x5,ldr-rgb-kodak15.png,40.9222,0.0272,0.0105,37.3036 +Kodak,5x5,ldr-rgb-kodak16.png,43.3847,0.0220,0.0070,56.2544 +Kodak,5x5,ldr-rgb-kodak17.png,41.9201,0.0244,0.0075,52.6334 +Kodak,5x5,ldr-rgb-kodak18.png,37.9619,0.0325,0.0149,26.3659 +Kodak,5x5,ldr-rgb-kodak19.png,40.8871,0.0266,0.0095,41.2523 +Kodak,5x5,ldr-rgb-kodak20.png,42.0751,0.0232,0.0080,48.9993 +Kodak,5x5,ldr-rgb-kodak21.png,40.2318,0.0263,0.0107,36.8420 +Kodak,5x5,ldr-rgb-kodak22.png,39.5098,0.0292,0.0123,32.0626 +Kodak,5x5,ldr-rgb-kodak23.png,42.2176,0.0250,0.0088,44.9037 +Kodak,5x5,ldr-rgb-kodak24.png,37.6858,0.0304,0.0134,29.3031 +Kodak,6x6,ldr-rgb-kodak01.png,35.6604,0.0326,0.0168,23.3392 +Kodak,6x6,ldr-rgb-kodak02.png,38.0761,0.0277,0.0113,34.7331 +Kodak,6x6,ldr-rgb-kodak03.png,40.4029,0.0224,0.0076,51.9438 +Kodak,6x6,ldr-rgb-kodak04.png,38.3307,0.0274,0.0106,37.0889 +Kodak,6x6,ldr-rgb-kodak05.png,34.1621,0.0377,0.0209,18.7891 +Kodak,6x6,ldr-rgb-kodak06.png,37.2413,0.0272,0.0119,33.0932 +Kodak,6x6,ldr-rgb-kodak07.png,38.6918,0.0267,0.0103,38.1616 +Kodak,6x6,ldr-rgb-kodak08.png,34.2562,0.0392,0.0215,18.2593 +Kodak,6x6,ldr-rgb-kodak09.png,39.8018,0.0246,0.0082,47.8715 +Kodak,6x6,ldr-rgb-kodak10.png,39.6065,0.0249,0.0080,48.9324 +Kodak,6x6,ldr-rgb-kodak11.png,37.0350,0.0276,0.0122,32.3234 +Kodak,6x6,ldr-rgb-kodak12.png,40.6117,0.0221,0.0071,55.1797 +Kodak,6x6,ldr-rgb-kodak13.png,32.7512,0.0404,0.0236,16.6574 +Kodak,6x6,ldr-rgb-kodak14.png,35.0163,0.0327,0.0167,23.4938 +Kodak,6x6,ldr-rgb-kodak15.png,38.4450,0.0272,0.0108,36.2875 +Kodak,6x6,ldr-rgb-kodak16.png,40.4576,0.0223,0.0074,52.8510 +Kodak,6x6,ldr-rgb-kodak17.png,38.8609,0.0252,0.0085,46.4478 +Kodak,6x6,ldr-rgb-kodak18.png,35.0294,0.0338,0.0164,23.9576 +Kodak,6x6,ldr-rgb-kodak19.png,37.8582,0.0285,0.0115,34.1124 +Kodak,6x6,ldr-rgb-kodak20.png,39.0412,0.0239,0.0090,43.8320 +Kodak,6x6,ldr-rgb-kodak21.png,36.8328,0.0283,0.0127,30.8892 +Kodak,6x6,ldr-rgb-kodak22.png,36.8810,0.0298,0.0130,30.3057 +Kodak,6x6,ldr-rgb-kodak23.png,39.9091,0.0243,0.0081,48.3118 +Kodak,6x6,ldr-rgb-kodak24.png,34.7176,0.0319,0.0151,26.0597 +Kodak,8x8,ldr-rgb-kodak01.png,31.2005,0.0407,0.0242,16.2781 +Kodak,8x8,ldr-rgb-kodak02.png,34.7312,0.0288,0.0117,33.5456 +Kodak,8x8,ldr-rgb-kodak03.png,36.4659,0.0248,0.0090,43.6904 +Kodak,8x8,ldr-rgb-kodak04.png,35.0660,0.0290,0.0114,34.6288 +Kodak,8x8,ldr-rgb-kodak05.png,30.0650,0.0466,0.0291,13.5321 +Kodak,8x8,ldr-rgb-kodak06.png,32.8162,0.0334,0.0172,22.8855 +Kodak,8x8,ldr-rgb-kodak07.png,34.8365,0.0301,0.0129,30.4467 +Kodak,8x8,ldr-rgb-kodak08.png,29.7191,0.0489,0.0304,12.9271 +Kodak,8x8,ldr-rgb-kodak09.png,35.9333,0.0271,0.0099,39.8480 +Kodak,8x8,ldr-rgb-kodak10.png,35.7348,0.0270,0.0093,42.1280 +Kodak,8x8,ldr-rgb-kodak11.png,32.8802,0.0321,0.0158,24.8522 +Kodak,8x8,ldr-rgb-kodak12.png,36.5229,0.0246,0.0088,44.4558 +Kodak,8x8,ldr-rgb-kodak13.png,28.1448,0.0524,0.0345,11.3841 +Kodak,8x8,ldr-rgb-kodak14.png,31.3242,0.0396,0.0228,17.2478 +Kodak,8x8,ldr-rgb-kodak15.png,34.7681,0.0290,0.0118,33.3259 +Kodak,8x8,ldr-rgb-kodak16.png,35.9653,0.0264,0.0107,36.6773 +Kodak,8x8,ldr-rgb-kodak17.png,34.7354,0.0282,0.0105,37.2935 +Kodak,8x8,ldr-rgb-kodak18.png,31.1735,0.0388,0.0205,19.2198 +Kodak,8x8,ldr-rgb-kodak19.png,33.9079,0.0320,0.0141,27.8640 +Kodak,8x8,ldr-rgb-kodak20.png,35.0719,0.0262,0.0105,37.5927 +Kodak,8x8,ldr-rgb-kodak21.png,32.6481,0.0330,0.0167,23.5798 +Kodak,8x8,ldr-rgb-kodak22.png,33.3422,0.0326,0.0148,26.5237 +Kodak,8x8,ldr-rgb-kodak23.png,36.4038,0.0253,0.0084,46.7228 +Kodak,8x8,ldr-rgb-kodak24.png,30.7489,0.0366,0.0190,20.6673 +Kodak,12x12,ldr-rgb-kodak01.png,26.9943,0.0382,0.0201,19.5534 +Kodak,12x12,ldr-rgb-kodak02.png,31.0366,0.0255,0.0070,56.5205 +Kodak,12x12,ldr-rgb-kodak03.png,32.6255,0.0233,0.0062,63.6071 +Kodak,12x12,ldr-rgb-kodak04.png,31.4723,0.0249,0.0059,66.9400 +Kodak,12x12,ldr-rgb-kodak05.png,25.7076,0.0417,0.0227,17.3055 +Kodak,12x12,ldr-rgb-kodak06.png,28.4878,0.0320,0.0145,27.0416 +Kodak,12x12,ldr-rgb-kodak07.png,30.8029,0.0265,0.0080,49.3246 +Kodak,12x12,ldr-rgb-kodak08.png,25.2189,0.0465,0.0267,14.7168 +Kodak,12x12,ldr-rgb-kodak09.png,31.6427,0.0254,0.0070,56.4798 +Kodak,12x12,ldr-rgb-kodak10.png,31.4531,0.0256,0.0068,57.5379 +Kodak,12x12,ldr-rgb-kodak11.png,28.8669,0.0286,0.0110,35.8318 +Kodak,12x12,ldr-rgb-kodak12.png,32.1856,0.0231,0.0060,65.4497 +Kodak,12x12,ldr-rgb-kodak13.png,24.2460,0.0471,0.0282,13.9527 +Kodak,12x12,ldr-rgb-kodak14.png,27.4553,0.0332,0.0151,25.9924 +Kodak,12x12,ldr-rgb-kodak15.png,31.1581,0.0270,0.0085,46.2939 +Kodak,12x12,ldr-rgb-kodak16.png,31.3640,0.0246,0.0075,52.6754 +Kodak,12x12,ldr-rgb-kodak17.png,30.8429,0.0262,0.0073,54.0354 +Kodak,12x12,ldr-rgb-kodak18.png,27.3755,0.0337,0.0142,27.5982 +Kodak,12x12,ldr-rgb-kodak19.png,29.8756,0.0302,0.0111,35.4148 +Kodak,12x12,ldr-rgb-kodak20.png,30.9402,0.0253,0.0081,48.3132 +Kodak,12x12,ldr-rgb-kodak21.png,28.6181,0.0315,0.0139,28.2404 +Kodak,12x12,ldr-rgb-kodak22.png,29.7383,0.0276,0.0087,45.2499 +Kodak,12x12,ldr-rgb-kodak23.png,32.4823,0.0244,0.0062,63.3919 +Kodak,12x12,ldr-rgb-kodak24.png,26.7030,0.0339,0.0149,26.3428 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..e3c9748 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3120,0.0909,0.0737,5.3382 +Kodak,4x4,ldr-rgb-kodak02.png,45.4397,0.1357,0.1174,3.3505 +Kodak,4x4,ldr-rgb-kodak03.png,47.6879,0.0704,0.0539,7.2907 +Kodak,4x4,ldr-rgb-kodak04.png,45.5017,0.1057,0.0871,4.5158 +Kodak,4x4,ldr-rgb-kodak05.png,42.1778,0.1182,0.0999,3.9367 +Kodak,4x4,ldr-rgb-kodak06.png,45.1998,0.0861,0.0692,5.6805 +Kodak,4x4,ldr-rgb-kodak07.png,46.0247,0.0870,0.0690,5.6988 +Kodak,4x4,ldr-rgb-kodak08.png,42.5327,0.1257,0.1065,3.6927 +Kodak,4x4,ldr-rgb-kodak09.png,47.1830,0.1025,0.0844,4.6570 +Kodak,4x4,ldr-rgb-kodak10.png,46.8614,0.1040,0.0856,4.5937 +Kodak,4x4,ldr-rgb-kodak11.png,44.8994,0.1030,0.0858,4.5831 +Kodak,4x4,ldr-rgb-kodak12.png,47.9784,0.0788,0.0618,6.3577 +Kodak,4x4,ldr-rgb-kodak13.png,41.6520,0.0984,0.0796,4.9393 +Kodak,4x4,ldr-rgb-kodak14.png,42.7319,0.1098,0.0923,4.2586 +Kodak,4x4,ldr-rgb-kodak15.png,45.5485,0.0943,0.0763,5.1565 +Kodak,4x4,ldr-rgb-kodak16.png,47.8885,0.0784,0.0619,6.3519 +Kodak,4x4,ldr-rgb-kodak17.png,46.3480,0.0893,0.0710,5.5405 +Kodak,4x4,ldr-rgb-kodak18.png,42.0493,0.1336,0.1145,3.4354 +Kodak,4x4,ldr-rgb-kodak19.png,45.3597,0.1071,0.0881,4.4656 +Kodak,4x4,ldr-rgb-kodak20.png,46.9280,0.0687,0.0523,7.5229 +Kodak,4x4,ldr-rgb-kodak21.png,45.1814,0.1086,0.0912,4.3102 +Kodak,4x4,ldr-rgb-kodak22.png,43.8216,0.1360,0.1175,3.3461 +Kodak,4x4,ldr-rgb-kodak23.png,46.8701,0.1083,0.0906,4.3417 +Kodak,4x4,ldr-rgb-kodak24.png,42.3775,0.1055,0.0870,4.5200 +Kodak,5x5,ldr-rgb-kodak01.png,40.1116,0.0976,0.0795,4.9466 +Kodak,5x5,ldr-rgb-kodak02.png,41.7670,0.1133,0.0941,4.1799 +Kodak,5x5,ldr-rgb-kodak03.png,44.0723,0.0566,0.0393,10.0068 +Kodak,5x5,ldr-rgb-kodak04.png,42.0904,0.0875,0.0685,5.7436 +Kodak,5x5,ldr-rgb-kodak05.png,37.9986,0.1166,0.0974,4.0365 +Kodak,5x5,ldr-rgb-kodak06.png,40.9739,0.0791,0.0614,6.4055 +Kodak,5x5,ldr-rgb-kodak07.png,42.4746,0.0727,0.0539,7.2989 +Kodak,5x5,ldr-rgb-kodak08.png,38.3608,0.1218,0.1019,3.8580 +Kodak,5x5,ldr-rgb-kodak09.png,43.8088,0.0639,0.0453,8.6891 +Kodak,5x5,ldr-rgb-kodak10.png,43.4231,0.0702,0.0510,7.7139 +Kodak,5x5,ldr-rgb-kodak11.png,40.8590,0.0942,0.0760,5.1742 +Kodak,5x5,ldr-rgb-kodak12.png,44.4017,0.0573,0.0397,9.9030 +Kodak,5x5,ldr-rgb-kodak13.png,36.9301,0.0990,0.0798,4.9304 +Kodak,5x5,ldr-rgb-kodak14.png,38.6960,0.1060,0.0877,4.4833 +Kodak,5x5,ldr-rgb-kodak15.png,41.9491,0.0832,0.0645,6.0966 +Kodak,5x5,ldr-rgb-kodak16.png,44.1356,0.0599,0.0426,9.2244 +Kodak,5x5,ldr-rgb-kodak17.png,42.5454,0.0627,0.0435,9.0382 +Kodak,5x5,ldr-rgb-kodak18.png,38.3941,0.1103,0.0906,4.3378 +Kodak,5x5,ldr-rgb-kodak19.png,41.6442,0.0773,0.0581,6.7670 +Kodak,5x5,ldr-rgb-kodak20.png,42.9823,0.0581,0.0409,9.6033 +Kodak,5x5,ldr-rgb-kodak21.png,40.7705,0.0799,0.0621,6.3356 +Kodak,5x5,ldr-rgb-kodak22.png,40.2982,0.1085,0.0892,4.4084 +Kodak,5x5,ldr-rgb-kodak23.png,43.5860,0.0768,0.0577,6.8153 +Kodak,5x5,ldr-rgb-kodak24.png,38.2072,0.0919,0.0727,5.4075 +Kodak,6x6,ldr-rgb-kodak01.png,36.1963,0.1003,0.0826,4.7628 +Kodak,6x6,ldr-rgb-kodak02.png,39.0475,0.0915,0.0730,5.3862 +Kodak,6x6,ldr-rgb-kodak03.png,41.3520,0.0487,0.0320,12.2988 +Kodak,6x6,ldr-rgb-kodak04.png,39.4032,0.0774,0.0587,6.7041 +Kodak,6x6,ldr-rgb-kodak05.png,34.7993,0.1145,0.0959,4.0981 +Kodak,6x6,ldr-rgb-kodak06.png,37.6376,0.0737,0.0560,7.0247 +Kodak,6x6,ldr-rgb-kodak07.png,39.7936,0.0646,0.0460,8.5428 +Kodak,6x6,ldr-rgb-kodak08.png,34.9845,0.1207,0.1009,3.8989 +Kodak,6x6,ldr-rgb-kodak09.png,40.8865,0.0523,0.0339,11.5860 +Kodak,6x6,ldr-rgb-kodak10.png,40.5154,0.0551,0.0362,10.8500 +Kodak,6x6,ldr-rgb-kodak11.png,37.5965,0.0806,0.0632,6.2208 +Kodak,6x6,ldr-rgb-kodak12.png,41.4939,0.0471,0.0303,12.9796 +Kodak,6x6,ldr-rgb-kodak13.png,32.9110,0.1078,0.0891,4.4153 +Kodak,6x6,ldr-rgb-kodak14.png,35.8527,0.1009,0.0829,4.7410 +Kodak,6x6,ldr-rgb-kodak15.png,39.2227,0.0766,0.0582,6.7529 +Kodak,6x6,ldr-rgb-kodak16.png,41.0391,0.0516,0.0348,11.3074 +Kodak,6x6,ldr-rgb-kodak17.png,39.4992,0.0546,0.0356,11.0343 +Kodak,6x6,ldr-rgb-kodak18.png,35.3684,0.1009,0.0815,4.8225 +Kodak,6x6,ldr-rgb-kodak19.png,38.5288,0.0707,0.0519,7.5833 +Kodak,6x6,ldr-rgb-kodak20.png,39.7703,0.0542,0.0374,10.5042 +Kodak,6x6,ldr-rgb-kodak21.png,37.2034,0.0714,0.0540,7.2859 +Kodak,6x6,ldr-rgb-kodak22.png,37.4752,0.0929,0.0738,5.3260 +Kodak,6x6,ldr-rgb-kodak23.png,40.9962,0.0587,0.0406,9.6954 +Kodak,6x6,ldr-rgb-kodak24.png,35.0626,0.0834,0.0646,6.0898 +Kodak,8x8,ldr-rgb-kodak01.png,31.8007,0.1384,0.1203,3.2699 +Kodak,8x8,ldr-rgb-kodak02.png,35.7971,0.0953,0.0760,5.1709 +Kodak,8x8,ldr-rgb-kodak03.png,37.7637,0.0606,0.0429,9.1683 +Kodak,8x8,ldr-rgb-kodak04.png,36.0993,0.0870,0.0676,5.8146 +Kodak,8x8,ldr-rgb-kodak05.png,30.7474,0.1513,0.1320,2.9782 +Kodak,8x8,ldr-rgb-kodak06.png,33.4449,0.0943,0.0763,5.1548 +Kodak,8x8,ldr-rgb-kodak07.png,36.1506,0.0795,0.0604,6.5087 +Kodak,8x8,ldr-rgb-kodak08.png,30.5414,0.1535,0.1334,2.9477 +Kodak,8x8,ldr-rgb-kodak09.png,37.2629,0.0620,0.0428,9.1815 +Kodak,8x8,ldr-rgb-kodak10.png,36.9234,0.0631,0.0437,9.0028 +Kodak,8x8,ldr-rgb-kodak11.png,33.6680,0.0973,0.0791,4.9707 +Kodak,8x8,ldr-rgb-kodak12.png,37.8337,0.0589,0.0413,9.5196 +Kodak,8x8,ldr-rgb-kodak13.png,28.3966,0.1488,0.1295,3.0364 +Kodak,8x8,ldr-rgb-kodak14.png,32.1516,0.1294,0.1111,3.5408 +Kodak,8x8,ldr-rgb-kodak15.png,35.8462,0.0801,0.0611,6.4351 +Kodak,8x8,ldr-rgb-kodak16.png,37.0251,0.0660,0.0483,8.1389 +Kodak,8x8,ldr-rgb-kodak17.png,35.6698,0.0669,0.0476,8.2586 +Kodak,8x8,ldr-rgb-kodak18.png,31.5577,0.1201,0.1002,3.9227 +Kodak,8x8,ldr-rgb-kodak19.png,34.7618,0.0850,0.0654,6.0137 +Kodak,8x8,ldr-rgb-kodak20.png,35.9030,0.0672,0.0494,7.9557 +Kodak,8x8,ldr-rgb-kodak21.png,33.1158,0.0915,0.0732,5.3747 +Kodak,8x8,ldr-rgb-kodak22.png,34.0434,0.1034,0.0840,4.6839 +Kodak,8x8,ldr-rgb-kodak23.png,37.6714,0.0619,0.0434,9.0661 +Kodak,8x8,ldr-rgb-kodak24.png,31.1289,0.1019,0.0824,4.7720 +Kodak,12x12,ldr-rgb-kodak01.png,27.7549,0.1563,0.1349,2.9141 +Kodak,12x12,ldr-rgb-kodak02.png,32.4572,0.0756,0.0538,7.3025 +Kodak,12x12,ldr-rgb-kodak03.png,33.8229,0.0565,0.0363,10.8414 +Kodak,12x12,ldr-rgb-kodak04.png,32.4332,0.0667,0.0443,8.8802 +Kodak,12x12,ldr-rgb-kodak05.png,26.4002,0.1697,0.1477,2.6631 +Kodak,12x12,ldr-rgb-kodak06.png,29.3776,0.1017,0.0809,4.8595 +Kodak,12x12,ldr-rgb-kodak07.png,32.0454,0.0809,0.0589,6.6800 +Kodak,12x12,ldr-rgb-kodak08.png,26.0607,0.1769,0.1540,2.5539 +Kodak,12x12,ldr-rgb-kodak09.png,33.1013,0.0604,0.0384,10.2285 +Kodak,12x12,ldr-rgb-kodak10.png,32.4879,0.0602,0.0380,10.3552 +Kodak,12x12,ldr-rgb-kodak11.png,29.7550,0.0965,0.0756,5.2035 +Kodak,12x12,ldr-rgb-kodak12.png,33.8849,0.0560,0.0355,11.0790 +Kodak,12x12,ldr-rgb-kodak13.png,24.5283,0.1764,0.1543,2.5490 +Kodak,12x12,ldr-rgb-kodak14.png,28.4299,0.1346,0.1133,3.4716 +Kodak,12x12,ldr-rgb-kodak15.png,32.2405,0.0754,0.0537,7.3284 +Kodak,12x12,ldr-rgb-kodak16.png,32.9828,0.0634,0.0431,9.1210 +Kodak,12x12,ldr-rgb-kodak17.png,31.7910,0.0659,0.0437,8.9940 +Kodak,12x12,ldr-rgb-kodak18.png,27.7838,0.1204,0.0976,4.0298 +Kodak,12x12,ldr-rgb-kodak19.png,30.8959,0.0852,0.0628,6.2612 +Kodak,12x12,ldr-rgb-kodak20.png,31.8670,0.0665,0.0462,8.5051 +Kodak,12x12,ldr-rgb-kodak21.png,29.1816,0.1048,0.0837,4.6970 +Kodak,12x12,ldr-rgb-kodak22.png,30.5137,0.0912,0.0688,5.7135 +Kodak,12x12,ldr-rgb-kodak23.png,33.5616,0.0525,0.0310,12.6766 +Kodak,12x12,ldr-rgb-kodak24.png,27.1047,0.1066,0.0844,4.6595 diff --git a/Test/Images/Kodak/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..4624d10 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5115,0.1992,0.1818,2.1632 +Kodak,4x4,ldr-rgb-kodak02.png,45.6982,0.2900,0.2707,1.4525 +Kodak,4x4,ldr-rgb-kodak03.png,48.0607,0.2255,0.2088,1.8829 +Kodak,4x4,ldr-rgb-kodak04.png,45.6858,0.2535,0.2345,1.6771 +Kodak,4x4,ldr-rgb-kodak05.png,42.4370,0.2536,0.2350,1.6732 +Kodak,4x4,ldr-rgb-kodak06.png,45.3960,0.2075,0.1904,2.0655 +Kodak,4x4,ldr-rgb-kodak07.png,46.3753,0.2476,0.2295,1.7134 +Kodak,4x4,ldr-rgb-kodak08.png,42.8242,0.2644,0.2450,1.6048 +Kodak,4x4,ldr-rgb-kodak09.png,47.4389,0.2675,0.2493,1.5776 +Kodak,4x4,ldr-rgb-kodak10.png,47.0911,0.2632,0.2448,1.6063 +Kodak,4x4,ldr-rgb-kodak11.png,45.1383,0.2379,0.2206,1.7822 +Kodak,4x4,ldr-rgb-kodak12.png,48.2774,0.2295,0.2127,1.8487 +Kodak,4x4,ldr-rgb-kodak13.png,41.7584,0.2080,0.1897,2.0732 +Kodak,4x4,ldr-rgb-kodak14.png,42.9859,0.2359,0.2184,1.8008 +Kodak,4x4,ldr-rgb-kodak15.png,45.8334,0.2447,0.2265,1.7357 +Kodak,4x4,ldr-rgb-kodak16.png,48.0940,0.2264,0.2093,1.8790 +Kodak,4x4,ldr-rgb-kodak17.png,46.5075,0.2393,0.2206,1.7822 +Kodak,4x4,ldr-rgb-kodak18.png,42.2101,0.2813,0.2619,1.5013 +Kodak,4x4,ldr-rgb-kodak19.png,45.5658,0.2525,0.2337,1.6823 +Kodak,4x4,ldr-rgb-kodak20.png,47.1799,0.1606,0.1440,2.7304 +Kodak,4x4,ldr-rgb-kodak21.png,45.3342,0.2539,0.2366,1.6616 +Kodak,4x4,ldr-rgb-kodak22.png,44.0086,0.2908,0.2721,1.4451 +Kodak,4x4,ldr-rgb-kodak23.png,47.1907,0.2798,0.2618,1.5019 +Kodak,4x4,ldr-rgb-kodak24.png,42.6019,0.2495,0.2310,1.7020 +Kodak,5x5,ldr-rgb-kodak01.png,40.2236,0.2389,0.2207,1.7820 +Kodak,5x5,ldr-rgb-kodak02.png,42.0380,0.3147,0.2960,1.3286 +Kodak,5x5,ldr-rgb-kodak03.png,44.3676,0.2357,0.2183,1.8012 +Kodak,5x5,ldr-rgb-kodak04.png,42.2612,0.2620,0.2426,1.6205 +Kodak,5x5,ldr-rgb-kodak05.png,38.1929,0.2810,0.2618,1.5018 +Kodak,5x5,ldr-rgb-kodak06.png,41.0984,0.2221,0.2041,1.9269 +Kodak,5x5,ldr-rgb-kodak07.png,42.7456,0.2615,0.2423,1.6230 +Kodak,5x5,ldr-rgb-kodak08.png,38.5418,0.2831,0.2627,1.4968 +Kodak,5x5,ldr-rgb-kodak09.png,44.0366,0.2550,0.2363,1.6640 +Kodak,5x5,ldr-rgb-kodak10.png,43.6071,0.2621,0.2429,1.6186 +Kodak,5x5,ldr-rgb-kodak11.png,41.0130,0.2516,0.2335,1.6837 +Kodak,5x5,ldr-rgb-kodak12.png,44.6149,0.2355,0.2177,1.8063 +Kodak,5x5,ldr-rgb-kodak13.png,36.9748,0.2209,0.2017,1.9496 +Kodak,5x5,ldr-rgb-kodak14.png,38.9092,0.2618,0.2434,1.6157 +Kodak,5x5,ldr-rgb-kodak15.png,42.1668,0.2539,0.2349,1.6742 +Kodak,5x5,ldr-rgb-kodak16.png,44.2715,0.2325,0.2148,1.8304 +Kodak,5x5,ldr-rgb-kodak17.png,42.6407,0.2387,0.2196,1.7903 +Kodak,5x5,ldr-rgb-kodak18.png,38.4820,0.2824,0.2626,1.4976 +Kodak,5x5,ldr-rgb-kodak19.png,41.7841,0.2621,0.2426,1.6212 +Kodak,5x5,ldr-rgb-kodak20.png,43.2953,0.1681,0.1509,2.6050 +Kodak,5x5,ldr-rgb-kodak21.png,40.8774,0.2680,0.2491,1.5787 +Kodak,5x5,ldr-rgb-kodak22.png,40.4425,0.3055,0.2861,1.3745 +Kodak,5x5,ldr-rgb-kodak23.png,43.9057,0.3004,0.2816,1.3966 +Kodak,5x5,ldr-rgb-kodak24.png,38.3273,0.2646,0.2454,1.6023 +Kodak,6x6,ldr-rgb-kodak01.png,36.3105,0.2750,0.2570,1.5298 +Kodak,6x6,ldr-rgb-kodak02.png,39.4083,0.3487,0.3301,1.1913 +Kodak,6x6,ldr-rgb-kodak03.png,41.7533,0.2110,0.1941,2.0263 +Kodak,6x6,ldr-rgb-kodak04.png,39.6674,0.2798,0.2610,1.5064 +Kodak,6x6,ldr-rgb-kodak05.png,34.9944,0.3154,0.2967,1.3254 +Kodak,6x6,ldr-rgb-kodak06.png,37.7608,0.2453,0.2276,1.7278 +Kodak,6x6,ldr-rgb-kodak07.png,40.1279,0.2447,0.2261,1.7388 +Kodak,6x6,ldr-rgb-kodak08.png,35.1750,0.3109,0.2913,1.3497 +Kodak,6x6,ldr-rgb-kodak09.png,41.2718,0.2643,0.2458,1.5999 +Kodak,6x6,ldr-rgb-kodak10.png,40.8412,0.2867,0.2675,1.4699 +Kodak,6x6,ldr-rgb-kodak11.png,37.7820,0.2722,0.2546,1.5444 +Kodak,6x6,ldr-rgb-kodak12.png,41.8395,0.2440,0.2269,1.7326 +Kodak,6x6,ldr-rgb-kodak13.png,32.9600,0.2628,0.2439,1.6124 +Kodak,6x6,ldr-rgb-kodak14.png,36.0500,0.2966,0.2786,1.4115 +Kodak,6x6,ldr-rgb-kodak15.png,39.4760,0.2505,0.2318,1.6967 +Kodak,6x6,ldr-rgb-kodak16.png,41.2318,0.2321,0.2152,1.8271 +Kodak,6x6,ldr-rgb-kodak17.png,39.6707,0.2571,0.2381,1.6515 +Kodak,6x6,ldr-rgb-kodak18.png,35.4565,0.3147,0.2949,1.3333 +Kodak,6x6,ldr-rgb-kodak19.png,38.7066,0.2920,0.2729,1.4410 +Kodak,6x6,ldr-rgb-kodak20.png,40.1121,0.1848,0.1681,2.3385 +Kodak,6x6,ldr-rgb-kodak21.png,37.3497,0.2910,0.2735,1.4375 +Kodak,6x6,ldr-rgb-kodak22.png,37.6441,0.3358,0.3168,1.2413 +Kodak,6x6,ldr-rgb-kodak23.png,41.4416,0.3049,0.2858,1.3759 +Kodak,6x6,ldr-rgb-kodak24.png,35.1795,0.2764,0.2569,1.5308 +Kodak,8x8,ldr-rgb-kodak01.png,31.9076,0.3547,0.3347,1.1748 +Kodak,8x8,ldr-rgb-kodak02.png,36.1658,0.3568,0.3364,1.1689 +Kodak,8x8,ldr-rgb-kodak03.png,38.2015,0.1935,0.1744,2.2551 +Kodak,8x8,ldr-rgb-kodak04.png,36.3849,0.2896,0.2685,1.4646 +Kodak,8x8,ldr-rgb-kodak05.png,30.9159,0.3884,0.3679,1.0689 +Kodak,8x8,ldr-rgb-kodak06.png,33.5799,0.2941,0.2748,1.4309 +Kodak,8x8,ldr-rgb-kodak07.png,36.5075,0.2371,0.2167,1.8148 +Kodak,8x8,ldr-rgb-kodak08.png,30.7382,0.4188,0.3972,0.9899 +Kodak,8x8,ldr-rgb-kodak09.png,37.5585,0.2162,0.1958,2.0085 +Kodak,8x8,ldr-rgb-kodak10.png,37.2383,0.2469,0.2260,1.7396 +Kodak,8x8,ldr-rgb-kodak11.png,33.8328,0.3416,0.3221,1.2206 +Kodak,8x8,ldr-rgb-kodak12.png,38.2628,0.2231,0.2039,1.9281 +Kodak,8x8,ldr-rgb-kodak13.png,28.4607,0.3692,0.3487,1.1278 +Kodak,8x8,ldr-rgb-kodak14.png,32.3242,0.3708,0.3510,1.1201 +Kodak,8x8,ldr-rgb-kodak15.png,36.0684,0.2748,0.2543,1.5465 +Kodak,8x8,ldr-rgb-kodak16.png,37.2660,0.2397,0.2208,1.7812 +Kodak,8x8,ldr-rgb-kodak17.png,35.8716,0.2368,0.2162,1.8188 +Kodak,8x8,ldr-rgb-kodak18.png,31.6551,0.3825,0.3605,1.0909 +Kodak,8x8,ldr-rgb-kodak19.png,34.9274,0.2566,0.2356,1.6693 +Kodak,8x8,ldr-rgb-kodak20.png,36.1555,0.2074,0.1887,2.0839 +Kodak,8x8,ldr-rgb-kodak21.png,33.2255,0.2755,0.2559,1.5365 +Kodak,8x8,ldr-rgb-kodak22.png,34.2304,0.3547,0.3333,1.1798 +Kodak,8x8,ldr-rgb-kodak23.png,38.1991,0.2364,0.2162,1.8186 +Kodak,8x8,ldr-rgb-kodak24.png,31.2348,0.3146,0.2937,1.3388 +Kodak,12x12,ldr-rgb-kodak01.png,27.9132,0.4691,0.4457,0.8823 +Kodak,12x12,ldr-rgb-kodak02.png,33.0052,0.3496,0.3250,1.2099 +Kodak,12x12,ldr-rgb-kodak03.png,34.4542,0.2091,0.1864,2.1092 +Kodak,12x12,ldr-rgb-kodak04.png,32.9738,0.3048,0.2799,1.4050 +Kodak,12x12,ldr-rgb-kodak05.png,26.6073,0.5066,0.4824,0.8152 +Kodak,12x12,ldr-rgb-kodak06.png,29.5310,0.3426,0.3193,1.2315 +Kodak,12x12,ldr-rgb-kodak07.png,32.6281,0.2672,0.2429,1.6185 +Kodak,12x12,ldr-rgb-kodak08.png,26.2616,0.5092,0.4840,0.8124 +Kodak,12x12,ldr-rgb-kodak09.png,33.6343,0.2409,0.2167,1.8142 +Kodak,12x12,ldr-rgb-kodak10.png,32.9910,0.2388,0.2141,1.8368 +Kodak,12x12,ldr-rgb-kodak11.png,30.0541,0.3723,0.3488,1.1272 +Kodak,12x12,ldr-rgb-kodak12.png,34.4512,0.2185,0.1957,2.0093 +Kodak,12x12,ldr-rgb-kodak13.png,24.5887,0.5444,0.5196,0.7568 +Kodak,12x12,ldr-rgb-kodak14.png,28.6476,0.4504,0.4264,0.9222 +Kodak,12x12,ldr-rgb-kodak15.png,32.7352,0.2939,0.2693,1.4603 +Kodak,12x12,ldr-rgb-kodak16.png,33.3387,0.2581,0.2351,1.6725 +Kodak,12x12,ldr-rgb-kodak17.png,32.1425,0.2553,0.2301,1.7090 +Kodak,12x12,ldr-rgb-kodak18.png,27.9244,0.4454,0.4199,0.9364 +Kodak,12x12,ldr-rgb-kodak19.png,31.1081,0.3495,0.3241,1.2132 +Kodak,12x12,ldr-rgb-kodak20.png,32.1616,0.2723,0.2495,1.5760 +Kodak,12x12,ldr-rgb-kodak21.png,29.3265,0.3298,0.3065,1.2828 +Kodak,12x12,ldr-rgb-kodak22.png,30.7890,0.3912,0.3661,1.0740 +Kodak,12x12,ldr-rgb-kodak23.png,34.3835,0.2166,0.1925,2.0432 +Kodak,12x12,ldr-rgb-kodak24.png,27.2381,0.3984,0.3737,1.0523 diff --git a/Test/Images/Kodak/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/Kodak/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..8810939 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.9062,0.0300,0.0137,28.6809 +Kodak,4x4,ldr-rgb-kodak02.png,44.3467,0.0371,0.0202,19.4643 +Kodak,4x4,ldr-rgb-kodak03.png,46.8208,0.0269,0.0112,35.0841 +Kodak,4x4,ldr-rgb-kodak04.png,44.7048,0.0352,0.0179,21.9452 +Kodak,4x4,ldr-rgb-kodak05.png,41.6833,0.0443,0.0272,14.4518 +Kodak,4x4,ldr-rgb-kodak06.png,44.8187,0.0294,0.0136,28.8490 +Kodak,4x4,ldr-rgb-kodak07.png,45.1903,0.0322,0.0154,25.5518 +Kodak,4x4,ldr-rgb-kodak08.png,42.1528,0.0461,0.0281,13.9990 +Kodak,4x4,ldr-rgb-kodak09.png,46.3750,0.0269,0.0101,38.7407 +Kodak,4x4,ldr-rgb-kodak10.png,46.1453,0.0277,0.0107,36.5886 +Kodak,4x4,ldr-rgb-kodak11.png,44.3357,0.0326,0.0167,23.5176 +Kodak,4x4,ldr-rgb-kodak12.png,47.1358,0.0252,0.0100,39.5034 +Kodak,4x4,ldr-rgb-kodak13.png,41.5073,0.0402,0.0231,17.0017 +Kodak,4x4,ldr-rgb-kodak14.png,41.9561,0.0394,0.0225,17.4646 +Kodak,4x4,ldr-rgb-kodak15.png,44.7852,0.0365,0.0196,20.0907 +Kodak,4x4,ldr-rgb-kodak16.png,47.3018,0.0240,0.0086,45.4945 +Kodak,4x4,ldr-rgb-kodak17.png,45.8895,0.0270,0.0097,40.5714 +Kodak,4x4,ldr-rgb-kodak18.png,41.7129,0.0447,0.0268,14.6745 +Kodak,4x4,ldr-rgb-kodak19.png,44.8948,0.0306,0.0133,29.5007 +Kodak,4x4,ldr-rgb-kodak20.png,46.4413,0.0270,0.0114,34.3927 +Kodak,4x4,ldr-rgb-kodak21.png,44.6688,0.0300,0.0141,27.9807 +Kodak,4x4,ldr-rgb-kodak22.png,43.2575,0.0399,0.0224,17.5316 +Kodak,4x4,ldr-rgb-kodak23.png,45.6976,0.0300,0.0136,28.8828 +Kodak,4x4,ldr-rgb-kodak24.png,42.0117,0.0393,0.0219,17.9723 +Kodak,5x5,ldr-rgb-kodak01.png,39.6381,0.0292,0.0126,31.2320 +Kodak,5x5,ldr-rgb-kodak02.png,40.6613,0.0292,0.0124,31.8189 +Kodak,5x5,ldr-rgb-kodak03.png,43.1070,0.0242,0.0084,46.6659 +Kodak,5x5,ldr-rgb-kodak04.png,41.3054,0.0289,0.0111,35.2883 +Kodak,5x5,ldr-rgb-kodak05.png,37.4812,0.0392,0.0219,17.9323 +Kodak,5x5,ldr-rgb-kodak06.png,40.6175,0.0264,0.0103,38.0138 +Kodak,5x5,ldr-rgb-kodak07.png,41.5316,0.0280,0.0108,36.2548 +Kodak,5x5,ldr-rgb-kodak08.png,37.7979,0.0403,0.0220,17.9002 +Kodak,5x5,ldr-rgb-kodak09.png,42.9386,0.0245,0.0075,52.1491 +Kodak,5x5,ldr-rgb-kodak10.png,42.6726,0.0254,0.0078,50.4178 +Kodak,5x5,ldr-rgb-kodak11.png,40.3558,0.0280,0.0119,33.0906 +Kodak,5x5,ldr-rgb-kodak12.png,43.4607,0.0231,0.0071,55.5477 +Kodak,5x5,ldr-rgb-kodak13.png,36.8488,0.0361,0.0185,21.2149 +Kodak,5x5,ldr-rgb-kodak14.png,38.0471,0.0365,0.0199,19.7963 +Kodak,5x5,ldr-rgb-kodak15.png,41.2322,0.0291,0.0119,33.0992 +Kodak,5x5,ldr-rgb-kodak16.png,43.5315,0.0223,0.0063,62.6336 +Kodak,5x5,ldr-rgb-kodak17.png,42.1157,0.0248,0.0072,54.7948 +Kodak,5x5,ldr-rgb-kodak18.png,38.1383,0.0346,0.0167,23.5431 +Kodak,5x5,ldr-rgb-kodak19.png,41.1817,0.0267,0.0091,43.4212 +Kodak,5x5,ldr-rgb-kodak20.png,42.3886,0.0241,0.0082,47.9829 +Kodak,5x5,ldr-rgb-kodak21.png,40.4523,0.0273,0.0110,35.9098 +Kodak,5x5,ldr-rgb-kodak22.png,39.8132,0.0313,0.0134,29.2704 +Kodak,5x5,ldr-rgb-kodak23.png,42.5506,0.0257,0.0090,43.8717 +Kodak,5x5,ldr-rgb-kodak24.png,37.9125,0.0330,0.0156,25.2062 +Kodak,6x6,ldr-rgb-kodak01.png,35.7576,0.0336,0.0175,22.5079 +Kodak,6x6,ldr-rgb-kodak02.png,38.1979,0.0291,0.0125,31.4722 +Kodak,6x6,ldr-rgb-kodak03.png,40.5936,0.0232,0.0080,49.1512 +Kodak,6x6,ldr-rgb-kodak04.png,38.5639,0.0285,0.0114,34.6208 +Kodak,6x6,ldr-rgb-kodak05.png,34.3707,0.0421,0.0252,15.5859 +Kodak,6x6,ldr-rgb-kodak06.png,37.3064,0.0278,0.0120,32.7080 +Kodak,6x6,ldr-rgb-kodak07.png,38.8907,0.0278,0.0111,35.4536 +Kodak,6x6,ldr-rgb-kodak08.png,34.4542,0.0429,0.0252,15.6292 +Kodak,6x6,ldr-rgb-kodak09.png,39.9832,0.0249,0.0084,46.7228 +Kodak,6x6,ldr-rgb-kodak10.png,39.7378,0.0253,0.0083,47.6048 +Kodak,6x6,ldr-rgb-kodak11.png,37.1622,0.0292,0.0133,29.5626 +Kodak,6x6,ldr-rgb-kodak12.png,40.7512,0.0225,0.0071,55.4693 +Kodak,6x6,ldr-rgb-kodak13.png,32.8161,0.0427,0.0256,15.3847 +Kodak,6x6,ldr-rgb-kodak14.png,35.3127,0.0385,0.0220,17.8548 +Kodak,6x6,ldr-rgb-kodak15.png,38.5805,0.0284,0.0119,32.9708 +Kodak,6x6,ldr-rgb-kodak16.png,40.5090,0.0222,0.0070,56.0632 +Kodak,6x6,ldr-rgb-kodak17.png,38.9529,0.0255,0.0084,46.8169 +Kodak,6x6,ldr-rgb-kodak18.png,35.1258,0.0357,0.0179,21.9686 +Kodak,6x6,ldr-rgb-kodak19.png,37.9862,0.0288,0.0116,33.9474 +Kodak,6x6,ldr-rgb-kodak20.png,39.1964,0.0245,0.0092,42.6156 +Kodak,6x6,ldr-rgb-kodak21.png,36.9178,0.0294,0.0134,29.2807 +Kodak,6x6,ldr-rgb-kodak22.png,36.9994,0.0312,0.0141,27.8738 +Kodak,6x6,ldr-rgb-kodak23.png,40.0813,0.0247,0.0085,46.4138 +Kodak,6x6,ldr-rgb-kodak24.png,34.8032,0.0338,0.0164,23.9458 +Kodak,8x8,ldr-rgb-kodak01.png,31.3412,0.0415,0.0251,15.6803 +Kodak,8x8,ldr-rgb-kodak02.png,34.9527,0.0290,0.0121,32.4435 +Kodak,8x8,ldr-rgb-kodak03.png,36.6102,0.0247,0.0089,44.0474 +Kodak,8x8,ldr-rgb-kodak04.png,35.1877,0.0291,0.0117,33.5879 +Kodak,8x8,ldr-rgb-kodak05.png,30.2580,0.0480,0.0308,12.7638 +Kodak,8x8,ldr-rgb-kodak06.png,32.9478,0.0335,0.0175,22.5147 +Kodak,8x8,ldr-rgb-kodak07.png,34.9976,0.0300,0.0132,29.7895 +Kodak,8x8,ldr-rgb-kodak08.png,29.9709,0.0495,0.0314,12.5056 +Kodak,8x8,ldr-rgb-kodak09.png,36.1754,0.0268,0.0099,39.8153 +Kodak,8x8,ldr-rgb-kodak10.png,35.8905,0.0264,0.0092,42.7925 +Kodak,8x8,ldr-rgb-kodak11.png,33.0125,0.0326,0.0164,23.9239 +Kodak,8x8,ldr-rgb-kodak12.png,36.7348,0.0241,0.0086,45.6646 +Kodak,8x8,ldr-rgb-kodak13.png,28.2212,0.0546,0.0369,10.6456 +Kodak,8x8,ldr-rgb-kodak14.png,31.5065,0.0416,0.0250,15.7361 +Kodak,8x8,ldr-rgb-kodak15.png,34.9514,0.0292,0.0123,32.0153 +Kodak,8x8,ldr-rgb-kodak16.png,36.0617,0.0261,0.0106,37.1658 +Kodak,8x8,ldr-rgb-kodak17.png,34.9137,0.0280,0.0106,37.0331 +Kodak,8x8,ldr-rgb-kodak18.png,31.2458,0.0396,0.0217,18.1047 +Kodak,8x8,ldr-rgb-kodak19.png,34.2323,0.0318,0.0143,27.4626 +Kodak,8x8,ldr-rgb-kodak20.png,35.2415,0.0263,0.0107,36.6699 +Kodak,8x8,ldr-rgb-kodak21.png,32.7559,0.0333,0.0173,22.6703 +Kodak,8x8,ldr-rgb-kodak22.png,33.4585,0.0329,0.0156,25.2579 +Kodak,8x8,ldr-rgb-kodak23.png,36.5494,0.0249,0.0085,46.2122 +Kodak,8x8,ldr-rgb-kodak24.png,30.8279,0.0373,0.0200,19.6735 +Kodak,12x12,ldr-rgb-kodak01.png,27.1096,0.0390,0.0209,18.8458 +Kodak,12x12,ldr-rgb-kodak02.png,31.1183,0.0253,0.0068,58.1506 +Kodak,12x12,ldr-rgb-kodak03.png,32.6995,0.0231,0.0059,66.2516 +Kodak,12x12,ldr-rgb-kodak04.png,31.5724,0.0248,0.0057,68.6851 +Kodak,12x12,ldr-rgb-kodak05.png,25.8234,0.0427,0.0239,16.4319 +Kodak,12x12,ldr-rgb-kodak06.png,28.6378,0.0325,0.0148,26.5527 +Kodak,12x12,ldr-rgb-kodak07.png,30.8626,0.0267,0.0080,49.1893 +Kodak,12x12,ldr-rgb-kodak08.png,25.4168,0.0472,0.0275,14.2956 +Kodak,12x12,ldr-rgb-kodak09.png,31.8375,0.0252,0.0068,58.0728 +Kodak,12x12,ldr-rgb-kodak10.png,31.5414,0.0255,0.0065,60.3906 +Kodak,12x12,ldr-rgb-kodak11.png,28.9389,0.0291,0.0112,35.1746 +Kodak,12x12,ldr-rgb-kodak12.png,32.2881,0.0228,0.0056,70.2923 +Kodak,12x12,ldr-rgb-kodak13.png,24.3214,0.0490,0.0301,13.0659 +Kodak,12x12,ldr-rgb-kodak14.png,27.5479,0.0340,0.0159,24.7679 +Kodak,12x12,ldr-rgb-kodak15.png,31.2617,0.0272,0.0085,46.3864 +Kodak,12x12,ldr-rgb-kodak16.png,31.4882,0.0243,0.0072,54.6676 +Kodak,12x12,ldr-rgb-kodak17.png,30.9019,0.0263,0.0072,54.5754 +Kodak,12x12,ldr-rgb-kodak18.png,27.4264,0.0345,0.0147,26.7023 +Kodak,12x12,ldr-rgb-kodak19.png,30.1924,0.0300,0.0108,36.2444 +Kodak,12x12,ldr-rgb-kodak20.png,31.0531,0.0252,0.0080,48.8599 +Kodak,12x12,ldr-rgb-kodak21.png,28.7189,0.0321,0.0143,27.5107 +Kodak,12x12,ldr-rgb-kodak22.png,29.8389,0.0278,0.0087,45.2598 +Kodak,12x12,ldr-rgb-kodak23.png,32.5301,0.0240,0.0059,66.4893 +Kodak,12x12,ldr-rgb-kodak24.png,26.7757,0.0344,0.0154,25.4705 diff --git a/Test/Images/Kodak/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..f53c4ee --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5795,0.0253,0.0099,39.7385 +Kodak,4x4,ldr-rgb-kodak02.png,43.9381,0.0294,0.0132,29.6812 +Kodak,4x4,ldr-rgb-kodak03.png,46.2152,0.0229,0.0079,49.6932 +Kodak,4x4,ldr-rgb-kodak04.png,44.2927,0.0284,0.0118,33.3286 +Kodak,4x4,ldr-rgb-kodak05.png,41.1428,0.0326,0.0162,24.3449 +Kodak,4x4,ldr-rgb-kodak06.png,44.5411,0.0253,0.0099,39.8393 +Kodak,4x4,ldr-rgb-kodak07.png,44.7409,0.0264,0.0101,38.8054 +Kodak,4x4,ldr-rgb-kodak08.png,41.5923,0.0338,0.0165,23.8141 +Kodak,4x4,ldr-rgb-kodak09.png,46.0423,0.0240,0.0076,51.9438 +Kodak,4x4,ldr-rgb-kodak10.png,45.8041,0.0245,0.0078,50.2948 +Kodak,4x4,ldr-rgb-kodak11.png,43.9389,0.0266,0.0112,35.1964 +Kodak,4x4,ldr-rgb-kodak12.png,46.5919,0.0222,0.0074,52.9868 +Kodak,4x4,ldr-rgb-kodak13.png,41.2499,0.0319,0.0153,25.6185 +Kodak,4x4,ldr-rgb-kodak14.png,41.2988,0.0290,0.0132,29.7128 +Kodak,4x4,ldr-rgb-kodak15.png,44.3214,0.0287,0.0123,31.9737 +Kodak,4x4,ldr-rgb-kodak16.png,47.1694,0.0218,0.0070,56.4161 +Kodak,4x4,ldr-rgb-kodak17.png,45.6555,0.0239,0.0073,53.5216 +Kodak,4x4,ldr-rgb-kodak18.png,41.3733,0.0332,0.0160,24.5452 +Kodak,4x4,ldr-rgb-kodak19.png,44.6305,0.0264,0.0096,41.0031 +Kodak,4x4,ldr-rgb-kodak20.png,45.9534,0.0230,0.0081,48.7315 +Kodak,4x4,ldr-rgb-kodak21.png,44.3559,0.0253,0.0099,39.6430 +Kodak,4x4,ldr-rgb-kodak22.png,42.8876,0.0307,0.0140,28.0951 +Kodak,4x4,ldr-rgb-kodak23.png,45.3933,0.0252,0.0095,41.5747 +Kodak,4x4,ldr-rgb-kodak24.png,41.4571,0.0299,0.0132,29.6925 +Kodak,5x5,ldr-rgb-kodak01.png,39.4156,0.0258,0.0104,37.6863 +Kodak,5x5,ldr-rgb-kodak02.png,40.4404,0.0257,0.0095,41.5307 +Kodak,5x5,ldr-rgb-kodak03.png,42.7468,0.0215,0.0065,60.1988 +Kodak,5x5,ldr-rgb-kodak04.png,40.9150,0.0256,0.0088,44.7502 +Kodak,5x5,ldr-rgb-kodak05.png,37.1354,0.0317,0.0153,25.7103 +Kodak,5x5,ldr-rgb-kodak06.png,40.4615,0.0237,0.0086,45.7977 +Kodak,5x5,ldr-rgb-kodak07.png,41.2239,0.0246,0.0084,46.5408 +Kodak,5x5,ldr-rgb-kodak08.png,37.4696,0.0329,0.0156,25.1866 +Kodak,5x5,ldr-rgb-kodak09.png,42.6412,0.0226,0.0063,62.1474 +Kodak,5x5,ldr-rgb-kodak10.png,42.4794,0.0231,0.0065,60.6906 +Kodak,5x5,ldr-rgb-kodak11.png,40.1335,0.0246,0.0092,42.9363 +Kodak,5x5,ldr-rgb-kodak12.png,43.2490,0.0210,0.0061,64.6949 +Kodak,5x5,ldr-rgb-kodak13.png,36.7590,0.0313,0.0147,26.7478 +Kodak,5x5,ldr-rgb-kodak14.png,37.6107,0.0284,0.0127,30.9205 +Kodak,5x5,ldr-rgb-kodak15.png,40.9602,0.0252,0.0089,44.3960 +Kodak,5x5,ldr-rgb-kodak16.png,43.4497,0.0207,0.0058,67.8069 +Kodak,5x5,ldr-rgb-kodak17.png,41.9868,0.0230,0.0062,63.1782 +Kodak,5x5,ldr-rgb-kodak18.png,37.9866,0.0295,0.0125,31.5480 +Kodak,5x5,ldr-rgb-kodak19.png,40.9421,0.0245,0.0078,50.5368 +Kodak,5x5,ldr-rgb-kodak20.png,42.1079,0.0216,0.0067,58.8394 +Kodak,5x5,ldr-rgb-kodak21.png,40.2657,0.0243,0.0089,44.0521 +Kodak,5x5,ldr-rgb-kodak22.png,39.5405,0.0270,0.0101,38.7707 +Kodak,5x5,ldr-rgb-kodak23.png,42.2534,0.0230,0.0073,53.9170 +Kodak,5x5,ldr-rgb-kodak24.png,37.7137,0.0278,0.0113,34.7580 +Kodak,6x6,ldr-rgb-kodak01.png,35.6691,0.0286,0.0135,29.2268 +Kodak,6x6,ldr-rgb-kodak02.png,38.1041,0.0250,0.0092,42.9228 +Kodak,6x6,ldr-rgb-kodak03.png,40.4304,0.0206,0.0061,64.3893 +Kodak,6x6,ldr-rgb-kodak04.png,38.3680,0.0249,0.0086,45.8028 +Kodak,6x6,ldr-rgb-kodak05.png,34.1707,0.0329,0.0168,23.4015 +Kodak,6x6,ldr-rgb-kodak06.png,37.2480,0.0244,0.0095,41.5527 +Kodak,6x6,ldr-rgb-kodak07.png,38.7045,0.0242,0.0083,47.3587 +Kodak,6x6,ldr-rgb-kodak08.png,34.2613,0.0343,0.0172,22.8481 +Kodak,6x6,ldr-rgb-kodak09.png,39.8077,0.0223,0.0066,59.3368 +Kodak,6x6,ldr-rgb-kodak10.png,39.6100,0.0228,0.0066,59.8950 +Kodak,6x6,ldr-rgb-kodak11.png,37.0497,0.0248,0.0099,39.9126 +Kodak,6x6,ldr-rgb-kodak12.png,40.6243,0.0203,0.0058,67.6317 +Kodak,6x6,ldr-rgb-kodak13.png,32.7545,0.0348,0.0187,21.0729 +Kodak,6x6,ldr-rgb-kodak14.png,35.0210,0.0289,0.0135,29.0471 +Kodak,6x6,ldr-rgb-kodak15.png,38.4585,0.0246,0.0088,44.8573 +Kodak,6x6,ldr-rgb-kodak16.png,40.4730,0.0205,0.0061,64.7584 +Kodak,6x6,ldr-rgb-kodak17.png,38.8727,0.0231,0.0068,57.6990 +Kodak,6x6,ldr-rgb-kodak18.png,35.0331,0.0299,0.0131,29.9024 +Kodak,6x6,ldr-rgb-kodak19.png,37.8639,0.0256,0.0092,42.6112 +Kodak,6x6,ldr-rgb-kodak20.png,39.0545,0.0215,0.0072,54.6513 +Kodak,6x6,ldr-rgb-kodak21.png,36.8418,0.0251,0.0102,38.5586 +Kodak,6x6,ldr-rgb-kodak22.png,36.8948,0.0268,0.0105,37.5704 +Kodak,6x6,ldr-rgb-kodak23.png,39.9299,0.0220,0.0067,59.1029 +Kodak,6x6,ldr-rgb-kodak24.png,34.7262,0.0285,0.0121,32.4467 +Kodak,8x8,ldr-rgb-kodak01.png,31.2040,0.0347,0.0186,21.1066 +Kodak,8x8,ldr-rgb-kodak02.png,34.8028,0.0262,0.0094,41.7959 +Kodak,8x8,ldr-rgb-kodak03.png,36.4818,0.0224,0.0072,54.8713 +Kodak,8x8,ldr-rgb-kodak04.png,35.0816,0.0263,0.0090,43.4876 +Kodak,8x8,ldr-rgb-kodak05.png,30.0677,0.0397,0.0227,17.3315 +Kodak,8x8,ldr-rgb-kodak06.png,32.8194,0.0291,0.0133,29.5647 +Kodak,8x8,ldr-rgb-kodak07.png,34.8484,0.0271,0.0102,38.3926 +Kodak,8x8,ldr-rgb-kodak08.png,29.7201,0.0415,0.0237,16.5627 +Kodak,8x8,ldr-rgb-kodak09.png,35.9413,0.0248,0.0079,49.5856 +Kodak,8x8,ldr-rgb-kodak10.png,35.7419,0.0246,0.0075,52.5412 +Kodak,8x8,ldr-rgb-kodak11.png,32.8868,0.0286,0.0126,31.2574 +Kodak,8x8,ldr-rgb-kodak12.png,36.5265,0.0225,0.0070,56.1740 +Kodak,8x8,ldr-rgb-kodak13.png,28.1462,0.0441,0.0269,14.6112 +Kodak,8x8,ldr-rgb-kodak14.png,31.3256,0.0343,0.0180,21.8977 +Kodak,8x8,ldr-rgb-kodak15.png,34.7780,0.0262,0.0094,41.9256 +Kodak,8x8,ldr-rgb-kodak16.png,35.9765,0.0237,0.0084,46.6013 +Kodak,8x8,ldr-rgb-kodak17.png,34.7433,0.0254,0.0084,47.0024 +Kodak,8x8,ldr-rgb-kodak18.png,31.1790,0.0340,0.0162,24.2336 +Kodak,8x8,ldr-rgb-kodak19.png,33.9167,0.0284,0.0111,35.3488 +Kodak,8x8,ldr-rgb-kodak20.png,35.0781,0.0239,0.0084,46.7944 +Kodak,8x8,ldr-rgb-kodak21.png,32.6526,0.0291,0.0131,30.0030 +Kodak,8x8,ldr-rgb-kodak22.png,33.3447,0.0289,0.0117,33.4652 +Kodak,8x8,ldr-rgb-kodak23.png,36.4202,0.0231,0.0068,57.9036 +Kodak,8x8,ldr-rgb-kodak24.png,30.7559,0.0323,0.0151,26.0820 +Kodak,12x12,ldr-rgb-kodak01.png,26.9944,0.0326,0.0152,25.8271 +Kodak,12x12,ldr-rgb-kodak02.png,31.0451,0.0234,0.0055,71.5207 +Kodak,12x12,ldr-rgb-kodak03.png,32.6384,0.0213,0.0049,80.3502 +Kodak,12x12,ldr-rgb-kodak04.png,31.4810,0.0234,0.0048,82.5211 +Kodak,12x12,ldr-rgb-kodak05.png,25.7089,0.0354,0.0172,22.8589 +Kodak,12x12,ldr-rgb-kodak06.png,28.4876,0.0282,0.0110,35.6621 +Kodak,12x12,ldr-rgb-kodak07.png,30.8061,0.0243,0.0063,62.6526 +Kodak,12x12,ldr-rgb-kodak08.png,25.2204,0.0392,0.0201,19.5747 +Kodak,12x12,ldr-rgb-kodak09.png,31.6441,0.0234,0.0055,72.0960 +Kodak,12x12,ldr-rgb-kodak10.png,31.4535,0.0238,0.0053,73.6773 +Kodak,12x12,ldr-rgb-kodak11.png,28.8707,0.0255,0.0085,46.2174 +Kodak,12x12,ldr-rgb-kodak12.png,32.1874,0.0216,0.0047,83.3300 +Kodak,12x12,ldr-rgb-kodak13.png,24.2468,0.0400,0.0215,18.2892 +Kodak,12x12,ldr-rgb-kodak14.png,27.4618,0.0293,0.0117,33.6455 +Kodak,12x12,ldr-rgb-kodak15.png,31.1647,0.0246,0.0066,59.8863 +Kodak,12x12,ldr-rgb-kodak16.png,31.3665,0.0223,0.0058,67.4823 +Kodak,12x12,ldr-rgb-kodak17.png,30.8424,0.0240,0.0057,68.8170 +Kodak,12x12,ldr-rgb-kodak18.png,27.3760,0.0301,0.0110,35.6784 +Kodak,12x12,ldr-rgb-kodak19.png,29.8759,0.0272,0.0085,46.3746 +Kodak,12x12,ldr-rgb-kodak20.png,30.9403,0.0229,0.0064,61.6042 +Kodak,12x12,ldr-rgb-kodak21.png,28.6206,0.0278,0.0106,37.1448 +Kodak,12x12,ldr-rgb-kodak22.png,29.7607,0.0254,0.0068,58.1342 +Kodak,12x12,ldr-rgb-kodak23.png,32.4940,0.0224,0.0049,80.4953 +Kodak,12x12,ldr-rgb-kodak24.png,26.7049,0.0300,0.0115,34.0596 diff --git a/Test/Images/Kodak/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/Kodak/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..dd49542 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3436,0.0820,0.0650,6.0499 +Kodak,4x4,ldr-rgb-kodak02.png,45.5149,0.1208,0.1026,3.8328 +Kodak,4x4,ldr-rgb-kodak03.png,47.7270,0.0629,0.0465,8.4573 +Kodak,4x4,ldr-rgb-kodak04.png,45.5617,0.0957,0.0770,5.1084 +Kodak,4x4,ldr-rgb-kodak05.png,42.2148,0.1058,0.0880,4.4685 +Kodak,4x4,ldr-rgb-kodak06.png,45.2285,0.0778,0.0610,6.4483 +Kodak,4x4,ldr-rgb-kodak07.png,46.0657,0.0776,0.0599,6.5626 +Kodak,4x4,ldr-rgb-kodak08.png,42.5596,0.1129,0.0940,4.1847 +Kodak,4x4,ldr-rgb-kodak09.png,47.2250,0.0918,0.0740,5.3130 +Kodak,4x4,ldr-rgb-kodak10.png,46.9183,0.0940,0.0759,5.1816 +Kodak,4x4,ldr-rgb-kodak11.png,44.9485,0.0932,0.0761,5.1668 +Kodak,4x4,ldr-rgb-kodak12.png,48.0140,0.0710,0.0544,7.2264 +Kodak,4x4,ldr-rgb-kodak13.png,41.6783,0.0883,0.0703,5.5962 +Kodak,4x4,ldr-rgb-kodak14.png,42.7635,0.0980,0.0809,4.8621 +Kodak,4x4,ldr-rgb-kodak15.png,45.6010,0.0841,0.0663,5.9334 +Kodak,4x4,ldr-rgb-kodak16.png,47.9487,0.0700,0.0539,7.3019 +Kodak,4x4,ldr-rgb-kodak17.png,46.3985,0.0801,0.0620,6.3392 +Kodak,4x4,ldr-rgb-kodak18.png,42.0873,0.1206,0.1019,3.8607 +Kodak,4x4,ldr-rgb-kodak19.png,45.4135,0.0957,0.0772,5.0929 +Kodak,4x4,ldr-rgb-kodak20.png,46.9562,0.0619,0.0459,8.5715 +Kodak,4x4,ldr-rgb-kodak21.png,45.2261,0.0967,0.0798,4.9246 +Kodak,4x4,ldr-rgb-kodak22.png,43.8626,0.1216,0.1035,3.7990 +Kodak,4x4,ldr-rgb-kodak23.png,46.9450,0.0953,0.0781,5.0325 +Kodak,4x4,ldr-rgb-kodak24.png,42.4147,0.0947,0.0766,5.1348 +Kodak,5x5,ldr-rgb-kodak01.png,40.1323,0.0843,0.0664,5.9192 +Kodak,5x5,ldr-rgb-kodak02.png,41.7976,0.0962,0.0779,5.0480 +Kodak,5x5,ldr-rgb-kodak03.png,44.1103,0.0492,0.0322,12.1999 +Kodak,5x5,ldr-rgb-kodak04.png,42.1172,0.0759,0.0569,6.9080 +Kodak,5x5,ldr-rgb-kodak05.png,38.0255,0.0999,0.0813,4.8380 +Kodak,5x5,ldr-rgb-kodak06.png,40.9959,0.0684,0.0510,7.7094 +Kodak,5x5,ldr-rgb-kodak07.png,42.5000,0.0632,0.0446,8.8250 +Kodak,5x5,ldr-rgb-kodak08.png,38.3799,0.1044,0.0848,4.6348 +Kodak,5x5,ldr-rgb-kodak09.png,43.8318,0.0558,0.0373,10.5449 +Kodak,5x5,ldr-rgb-kodak10.png,43.4528,0.0607,0.0421,9.3376 +Kodak,5x5,ldr-rgb-kodak11.png,40.8938,0.0787,0.0612,6.4301 +Kodak,5x5,ldr-rgb-kodak12.png,44.4299,0.0496,0.0324,12.1202 +Kodak,5x5,ldr-rgb-kodak13.png,36.9514,0.0852,0.0664,5.9255 +Kodak,5x5,ldr-rgb-kodak14.png,38.7191,0.0903,0.0723,5.4378 +Kodak,5x5,ldr-rgb-kodak15.png,41.9816,0.0719,0.0536,7.3308 +Kodak,5x5,ldr-rgb-kodak16.png,44.1799,0.0518,0.0350,11.2425 +Kodak,5x5,ldr-rgb-kodak17.png,42.5913,0.0542,0.0355,11.0688 +Kodak,5x5,ldr-rgb-kodak18.png,38.4192,0.0948,0.0753,5.2210 +Kodak,5x5,ldr-rgb-kodak19.png,41.6938,0.0672,0.0481,8.1719 +Kodak,5x5,ldr-rgb-kodak20.png,43.0178,0.0511,0.0342,11.4956 +Kodak,5x5,ldr-rgb-kodak21.png,40.7979,0.0690,0.0513,7.6656 +Kodak,5x5,ldr-rgb-kodak22.png,40.3244,0.0926,0.0736,5.3438 +Kodak,5x5,ldr-rgb-kodak23.png,43.6199,0.0657,0.0477,8.2428 +Kodak,5x5,ldr-rgb-kodak24.png,38.2265,0.0794,0.0606,6.4924 +Kodak,6x6,ldr-rgb-kodak01.png,36.2008,0.0831,0.0657,5.9818 +Kodak,6x6,ldr-rgb-kodak02.png,39.0638,0.0764,0.0585,6.7189 +Kodak,6x6,ldr-rgb-kodak03.png,41.3682,0.0422,0.0257,15.2842 +Kodak,6x6,ldr-rgb-kodak04.png,39.4191,0.0657,0.0470,8.3651 +Kodak,6x6,ldr-rgb-kodak05.png,34.8088,0.0942,0.0763,5.1523 +Kodak,6x6,ldr-rgb-kodak06.png,37.6472,0.0610,0.0441,8.9263 +Kodak,6x6,ldr-rgb-kodak07.png,39.8064,0.0548,0.0369,10.6569 +Kodak,6x6,ldr-rgb-kodak08.png,34.9897,0.0999,0.0808,4.8682 +Kodak,6x6,ldr-rgb-kodak09.png,40.8974,0.0450,0.0270,14.5575 +Kodak,6x6,ldr-rgb-kodak10.png,40.5253,0.0472,0.0288,13.6490 +Kodak,6x6,ldr-rgb-kodak11.png,37.6082,0.0671,0.0501,7.8430 +Kodak,6x6,ldr-rgb-kodak12.png,41.5111,0.0407,0.0241,16.2850 +Kodak,6x6,ldr-rgb-kodak13.png,32.9132,0.0899,0.0715,5.5018 +Kodak,6x6,ldr-rgb-kodak14.png,35.8599,0.0838,0.0663,5.9292 +Kodak,6x6,ldr-rgb-kodak15.png,39.2305,0.0646,0.0467,8.4233 +Kodak,6x6,ldr-rgb-kodak16.png,41.0574,0.0439,0.0274,14.3316 +Kodak,6x6,ldr-rgb-kodak17.png,39.5098,0.0465,0.0283,13.9059 +Kodak,6x6,ldr-rgb-kodak18.png,35.3754,0.0837,0.0648,6.0701 +Kodak,6x6,ldr-rgb-kodak19.png,38.5331,0.0597,0.0413,9.5267 +Kodak,6x6,ldr-rgb-kodak20.png,39.7790,0.0460,0.0298,13.2146 +Kodak,6x6,ldr-rgb-kodak21.png,37.2127,0.0600,0.0429,9.1654 +Kodak,6x6,ldr-rgb-kodak22.png,37.4858,0.0776,0.0591,6.6499 +Kodak,6x6,ldr-rgb-kodak23.png,41.0115,0.0497,0.0324,12.1482 +Kodak,6x6,ldr-rgb-kodak24.png,35.0719,0.0699,0.0516,7.6140 +Kodak,8x8,ldr-rgb-kodak01.png,31.8036,0.1099,0.0915,4.2973 +Kodak,8x8,ldr-rgb-kodak02.png,35.8059,0.0759,0.0574,6.8470 +Kodak,8x8,ldr-rgb-kodak03.png,37.7677,0.0498,0.0328,11.9901 +Kodak,8x8,ldr-rgb-kodak04.png,36.1068,0.0705,0.0516,7.6139 +Kodak,8x8,ldr-rgb-kodak05.png,30.7525,0.1195,0.1005,3.9122 +Kodak,8x8,ldr-rgb-kodak06.png,33.4479,0.0751,0.0577,6.8202 +Kodak,8x8,ldr-rgb-kodak07.png,36.1623,0.0640,0.0454,8.6560 +Kodak,8x8,ldr-rgb-kodak08.png,30.5413,0.1211,0.1015,3.8729 +Kodak,8x8,ldr-rgb-kodak09.png,37.2666,0.0511,0.0327,12.0238 +Kodak,8x8,ldr-rgb-kodak10.png,36.9291,0.0518,0.0329,11.9432 +Kodak,8x8,ldr-rgb-kodak11.png,33.6748,0.0780,0.0603,6.5220 +Kodak,8x8,ldr-rgb-kodak12.png,37.8421,0.0485,0.0313,12.5484 +Kodak,8x8,ldr-rgb-kodak13.png,28.3980,0.1175,0.0986,3.9869 +Kodak,8x8,ldr-rgb-kodak14.png,32.1539,0.1026,0.0845,4.6559 +Kodak,8x8,ldr-rgb-kodak15.png,35.8557,0.0653,0.0468,8.3931 +Kodak,8x8,ldr-rgb-kodak16.png,37.0420,0.0534,0.0363,10.8273 +Kodak,8x8,ldr-rgb-kodak17.png,35.6788,0.0550,0.0361,10.8927 +Kodak,8x8,ldr-rgb-kodak18.png,31.5601,0.0958,0.0762,5.1581 +Kodak,8x8,ldr-rgb-kodak19.png,34.7706,0.0691,0.0500,7.8661 +Kodak,8x8,ldr-rgb-kodak20.png,35.9106,0.0548,0.0378,10.3941 +Kodak,8x8,ldr-rgb-kodak21.png,33.1168,0.0736,0.0557,7.0594 +Kodak,8x8,ldr-rgb-kodak22.png,34.0527,0.0836,0.0644,6.1103 +Kodak,8x8,ldr-rgb-kodak23.png,37.6898,0.0514,0.0334,11.7761 +Kodak,8x8,ldr-rgb-kodak24.png,31.1316,0.0821,0.0631,6.2267 +Kodak,12x12,ldr-rgb-kodak01.png,27.7556,0.1224,0.1016,3.8686 +Kodak,12x12,ldr-rgb-kodak02.png,32.4643,0.0616,0.0403,9.7570 +Kodak,12x12,ldr-rgb-kodak03.png,33.8360,0.0470,0.0271,14.5173 +Kodak,12x12,ldr-rgb-kodak04.png,32.4512,0.0548,0.0331,11.8886 +Kodak,12x12,ldr-rgb-kodak05.png,26.3995,0.1337,0.1123,3.5028 +Kodak,12x12,ldr-rgb-kodak06.png,29.3774,0.0810,0.0605,6.4993 +Kodak,12x12,ldr-rgb-kodak07.png,32.0484,0.0654,0.0439,8.9622 +Kodak,12x12,ldr-rgb-kodak08.png,26.0631,0.1388,0.1164,3.3777 +Kodak,12x12,ldr-rgb-kodak09.png,33.1028,0.0500,0.0288,13.6633 +Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0502,0.0285,13.7734 +Kodak,12x12,ldr-rgb-kodak11.png,29.7578,0.0776,0.0569,6.9130 +Kodak,12x12,ldr-rgb-kodak12.png,33.8888,0.0462,0.0263,14.9285 +Kodak,12x12,ldr-rgb-kodak13.png,24.5306,0.1381,0.1165,3.3761 +Kodak,12x12,ldr-rgb-kodak14.png,28.4334,0.1071,0.0861,4.5648 +Kodak,12x12,ldr-rgb-kodak15.png,32.2456,0.0618,0.0405,9.7071 +Kodak,12x12,ldr-rgb-kodak16.png,32.9899,0.0517,0.0318,12.3844 +Kodak,12x12,ldr-rgb-kodak17.png,31.7938,0.0542,0.0326,12.0793 +Kodak,12x12,ldr-rgb-kodak18.png,27.7853,0.0960,0.0735,5.3489 +Kodak,12x12,ldr-rgb-kodak19.png,30.8937,0.0685,0.0464,8.4716 +Kodak,12x12,ldr-rgb-kodak20.png,31.8665,0.0549,0.0346,11.3519 +Kodak,12x12,ldr-rgb-kodak21.png,29.1859,0.0837,0.0632,6.2233 +Kodak,12x12,ldr-rgb-kodak22.png,30.5129,0.0739,0.0521,7.5444 +Kodak,12x12,ldr-rgb-kodak23.png,33.5762,0.0443,0.0234,16.8358 +Kodak,12x12,ldr-rgb-kodak24.png,27.1069,0.0851,0.0634,6.2024 diff --git a/Test/Images/Kodak/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..4468432 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5393,0.1760,0.1590,2.4727 +Kodak,4x4,ldr-rgb-kodak02.png,45.7829,0.2525,0.2345,1.6769 +Kodak,4x4,ldr-rgb-kodak03.png,48.1286,0.2005,0.1840,2.1374 +Kodak,4x4,ldr-rgb-kodak04.png,45.7459,0.2252,0.2070,1.8995 +Kodak,4x4,ldr-rgb-kodak05.png,42.4808,0.2212,0.2033,1.9339 +Kodak,4x4,ldr-rgb-kodak06.png,45.4283,0.1842,0.1673,2.3510 +Kodak,4x4,ldr-rgb-kodak07.png,46.4346,0.2225,0.2043,1.9247 +Kodak,4x4,ldr-rgb-kodak08.png,42.8524,0.2325,0.2137,1.8399 +Kodak,4x4,ldr-rgb-kodak09.png,47.4868,0.2362,0.2180,1.8035 +Kodak,4x4,ldr-rgb-kodak10.png,47.1520,0.2334,0.2155,1.8246 +Kodak,4x4,ldr-rgb-kodak11.png,45.2020,0.2110,0.1934,2.0335 +Kodak,4x4,ldr-rgb-kodak12.png,48.3163,0.2022,0.1856,2.1189 +Kodak,4x4,ldr-rgb-kodak13.png,41.7858,0.1820,0.1638,2.4010 +Kodak,4x4,ldr-rgb-kodak14.png,43.0205,0.2069,0.1896,2.0742 +Kodak,4x4,ldr-rgb-kodak15.png,45.8894,0.2154,0.1978,1.9883 +Kodak,4x4,ldr-rgb-kodak16.png,48.1595,0.2001,0.1838,2.1389 +Kodak,4x4,ldr-rgb-kodak17.png,46.5669,0.2132,0.1950,2.0163 +Kodak,4x4,ldr-rgb-kodak18.png,42.2513,0.2479,0.2284,1.7216 +Kodak,4x4,ldr-rgb-kodak19.png,45.6248,0.2237,0.2053,1.9150 +Kodak,4x4,ldr-rgb-kodak20.png,47.2126,0.1414,0.1250,3.1454 +Kodak,4x4,ldr-rgb-kodak21.png,45.3757,0.2239,0.2068,1.9013 +Kodak,4x4,ldr-rgb-kodak22.png,44.0484,0.2549,0.2362,1.6645 +Kodak,4x4,ldr-rgb-kodak23.png,47.2672,0.2485,0.2307,1.7043 +Kodak,4x4,ldr-rgb-kodak24.png,42.6395,0.2212,0.2031,1.9361 +Kodak,5x5,ldr-rgb-kodak01.png,40.2439,0.2027,0.1848,2.1279 +Kodak,5x5,ldr-rgb-kodak02.png,42.0748,0.2692,0.2507,1.5683 +Kodak,5x5,ldr-rgb-kodak03.png,44.4104,0.2014,0.1845,2.1315 +Kodak,5x5,ldr-rgb-kodak04.png,42.3039,0.2216,0.2024,1.9427 +Kodak,5x5,ldr-rgb-kodak05.png,38.2196,0.2381,0.2193,1.7933 +Kodak,5x5,ldr-rgb-kodak06.png,41.1196,0.1884,0.1711,2.2988 +Kodak,5x5,ldr-rgb-kodak07.png,42.7728,0.2242,0.2058,1.9104 +Kodak,5x5,ldr-rgb-kodak08.png,38.5537,0.2389,0.2193,1.7933 +Kodak,5x5,ldr-rgb-kodak09.png,44.0572,0.2192,0.2007,1.9591 +Kodak,5x5,ldr-rgb-kodak10.png,43.6371,0.2252,0.2060,1.9085 +Kodak,5x5,ldr-rgb-kodak11.png,41.0491,0.2129,0.1953,2.0130 +Kodak,5x5,ldr-rgb-kodak12.png,44.6371,0.1997,0.1827,2.1528 +Kodak,5x5,ldr-rgb-kodak13.png,36.9965,0.1853,0.1666,2.3595 +Kodak,5x5,ldr-rgb-kodak14.png,38.9373,0.2193,0.2013,1.9537 +Kodak,5x5,ldr-rgb-kodak15.png,42.2057,0.2153,0.1968,1.9979 +Kodak,5x5,ldr-rgb-kodak16.png,44.3209,0.1973,0.1804,2.1793 +Kodak,5x5,ldr-rgb-kodak17.png,42.6878,0.2038,0.1847,2.1286 +Kodak,5x5,ldr-rgb-kodak18.png,38.5091,0.2405,0.2208,1.7808 +Kodak,5x5,ldr-rgb-kodak19.png,41.8288,0.2221,0.2032,1.9347 +Kodak,5x5,ldr-rgb-kodak20.png,43.3334,0.1430,0.1262,3.1152 +Kodak,5x5,ldr-rgb-kodak21.png,40.9050,0.2284,0.2106,1.8668 +Kodak,5x5,ldr-rgb-kodak22.png,40.4714,0.2588,0.2398,1.6394 +Kodak,5x5,ldr-rgb-kodak23.png,43.9456,0.2568,0.2388,1.6466 +Kodak,5x5,ldr-rgb-kodak24.png,38.3490,0.2272,0.2079,1.8918 +Kodak,6x6,ldr-rgb-kodak01.png,36.3168,0.2234,0.2061,1.9080 +Kodak,6x6,ldr-rgb-kodak02.png,39.4281,0.2844,0.2666,1.4751 +Kodak,6x6,ldr-rgb-kodak03.png,41.7707,0.1722,0.1553,2.5318 +Kodak,6x6,ldr-rgb-kodak04.png,39.6843,0.2290,0.2105,1.8678 +Kodak,6x6,ldr-rgb-kodak05.png,35.0088,0.2538,0.2355,1.6697 +Kodak,6x6,ldr-rgb-kodak06.png,37.7698,0.1976,0.1805,2.1781 +Kodak,6x6,ldr-rgb-kodak07.png,40.1464,0.2008,0.1828,2.1507 +Kodak,6x6,ldr-rgb-kodak08.png,35.1763,0.2526,0.2335,1.6837 +Kodak,6x6,ldr-rgb-kodak09.png,41.2785,0.2177,0.1999,1.9672 +Kodak,6x6,ldr-rgb-kodak10.png,40.8522,0.2350,0.2165,1.8160 +Kodak,6x6,ldr-rgb-kodak11.png,37.7933,0.2210,0.2038,1.9296 +Kodak,6x6,ldr-rgb-kodak12.png,41.8544,0.1992,0.1828,2.1515 +Kodak,6x6,ldr-rgb-kodak13.png,32.9617,0.2112,0.1930,2.0377 +Kodak,6x6,ldr-rgb-kodak14.png,36.0569,0.2401,0.2226,1.7668 +Kodak,6x6,ldr-rgb-kodak15.png,39.4918,0.2039,0.1861,2.1132 +Kodak,6x6,ldr-rgb-kodak16.png,41.2543,0.1880,0.1714,2.2948 +Kodak,6x6,ldr-rgb-kodak17.png,39.6918,0.2089,0.1907,2.0616 +Kodak,6x6,ldr-rgb-kodak18.png,35.4609,0.2577,0.2384,1.6494 +Kodak,6x6,ldr-rgb-kodak19.png,38.7173,0.2402,0.2215,1.7749 +Kodak,6x6,ldr-rgb-kodak20.png,40.1243,0.1514,0.1351,2.9097 +Kodak,6x6,ldr-rgb-kodak21.png,37.3603,0.2385,0.2215,1.7750 +Kodak,6x6,ldr-rgb-kodak22.png,37.6556,0.2740,0.2553,1.5401 +Kodak,6x6,ldr-rgb-kodak23.png,41.4655,0.2506,0.2329,1.6884 +Kodak,6x6,ldr-rgb-kodak24.png,35.1889,0.2263,0.2080,1.8904 +Kodak,8x8,ldr-rgb-kodak01.png,31.9131,0.2747,0.2551,1.5412 +Kodak,8x8,ldr-rgb-kodak02.png,36.1767,0.2775,0.2574,1.5279 +Kodak,8x8,ldr-rgb-kodak03.png,38.2083,0.1499,0.1312,2.9968 +Kodak,8x8,ldr-rgb-kodak04.png,36.3928,0.2243,0.2038,1.9298 +Kodak,8x8,ldr-rgb-kodak05.png,30.9201,0.2990,0.2785,1.4119 +Kodak,8x8,ldr-rgb-kodak06.png,33.5817,0.2267,0.2075,1.8949 +Kodak,8x8,ldr-rgb-kodak07.png,36.5160,0.1836,0.1637,2.4027 +Kodak,8x8,ldr-rgb-kodak08.png,30.7384,0.3233,0.3022,1.3010 +Kodak,8x8,ldr-rgb-kodak09.png,37.5615,0.1663,0.1464,2.6854 +Kodak,8x8,ldr-rgb-kodak10.png,37.2421,0.1902,0.1700,2.3130 +Kodak,8x8,ldr-rgb-kodak11.png,33.8416,0.2638,0.2446,1.6074 +Kodak,8x8,ldr-rgb-kodak12.png,38.2751,0.1726,0.1540,2.5534 +Kodak,8x8,ldr-rgb-kodak13.png,28.4619,0.2875,0.2670,1.4729 +Kodak,8x8,ldr-rgb-kodak14.png,32.3307,0.2870,0.2676,1.4696 +Kodak,8x8,ldr-rgb-kodak15.png,36.0804,0.2128,0.1927,2.0401 +Kodak,8x8,ldr-rgb-kodak16.png,37.2806,0.1837,0.1649,2.3845 +Kodak,8x8,ldr-rgb-kodak17.png,35.8778,0.1828,0.1621,2.4253 +Kodak,8x8,ldr-rgb-kodak18.png,31.6559,0.2944,0.2733,1.4386 +Kodak,8x8,ldr-rgb-kodak19.png,34.9339,0.2008,0.1802,2.1817 +Kodak,8x8,ldr-rgb-kodak20.png,36.1622,0.1608,0.1424,2.7606 +Kodak,8x8,ldr-rgb-kodak21.png,33.2290,0.2112,0.1923,2.0445 +Kodak,8x8,ldr-rgb-kodak22.png,34.2355,0.2761,0.2558,1.5371 +Kodak,8x8,ldr-rgb-kodak23.png,38.2086,0.1826,0.1630,2.4123 +Kodak,8x8,ldr-rgb-kodak24.png,31.2397,0.2433,0.2227,1.7655 +Kodak,12x12,ldr-rgb-kodak01.png,27.9145,0.3613,0.3380,1.1632 +Kodak,12x12,ldr-rgb-kodak02.png,33.0098,0.2699,0.2463,1.5965 +Kodak,12x12,ldr-rgb-kodak03.png,34.4588,0.1625,0.1404,2.8016 +Kodak,12x12,ldr-rgb-kodak04.png,32.9763,0.2348,0.2107,1.8662 +Kodak,12x12,ldr-rgb-kodak05.png,26.6072,0.3898,0.3655,1.0757 +Kodak,12x12,ldr-rgb-kodak06.png,29.5340,0.2646,0.2417,1.6270 +Kodak,12x12,ldr-rgb-kodak07.png,32.6336,0.2067,0.1828,2.1505 +Kodak,12x12,ldr-rgb-kodak08.png,26.2642,0.3924,0.3676,1.0697 +Kodak,12x12,ldr-rgb-kodak09.png,33.6341,0.1847,0.1611,2.4406 +Kodak,12x12,ldr-rgb-kodak10.png,32.9911,0.1843,0.1600,2.4570 +Kodak,12x12,ldr-rgb-kodak11.png,30.0562,0.2839,0.2607,1.5081 +Kodak,12x12,ldr-rgb-kodak12.png,34.4444,0.1687,0.1460,2.6924 +Kodak,12x12,ldr-rgb-kodak13.png,24.5875,0.4212,0.3968,0.9909 +Kodak,12x12,ldr-rgb-kodak14.png,28.6495,0.3463,0.3229,1.2179 +Kodak,12x12,ldr-rgb-kodak15.png,32.7427,0.2281,0.2040,1.9276 +Kodak,12x12,ldr-rgb-kodak16.png,33.3405,0.1998,0.1771,2.2197 +Kodak,12x12,ldr-rgb-kodak17.png,32.1386,0.1976,0.1732,2.2698 +Kodak,12x12,ldr-rgb-kodak18.png,27.9275,0.3434,0.3187,1.2336 +Kodak,12x12,ldr-rgb-kodak19.png,31.1080,0.2696,0.2453,1.6031 +Kodak,12x12,ldr-rgb-kodak20.png,32.1759,0.2113,0.1888,2.0831 +Kodak,12x12,ldr-rgb-kodak21.png,29.3270,0.2538,0.2306,1.7050 +Kodak,12x12,ldr-rgb-kodak22.png,30.7891,0.3029,0.2783,1.4130 +Kodak,12x12,ldr-rgb-kodak23.png,34.3878,0.1669,0.1434,2.7422 +Kodak,12x12,ldr-rgb-kodak24.png,27.2398,0.3079,0.2830,1.3894 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..00fd14e --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.9062,0.0359,0.0185,21.2792 +Kodak,4x4,ldr-rgb-kodak02.png,44.3467,0.0452,0.0270,14.5604 +Kodak,4x4,ldr-rgb-kodak03.png,46.8208,0.0319,0.0152,25.8952 +Kodak,4x4,ldr-rgb-kodak04.png,44.7048,0.0424,0.0239,16.4265 +Kodak,4x4,ldr-rgb-kodak05.png,41.6833,0.0543,0.0360,10.9206 +Kodak,4x4,ldr-rgb-kodak06.png,44.8187,0.0354,0.0184,21.4065 +Kodak,4x4,ldr-rgb-kodak07.png,45.1903,0.0386,0.0205,19.2180 +Kodak,4x4,ldr-rgb-kodak08.png,42.1528,0.0565,0.0371,10.5860 +Kodak,4x4,ldr-rgb-kodak09.png,46.3750,0.0318,0.0140,28.0526 +Kodak,4x4,ldr-rgb-kodak10.png,46.1453,0.0332,0.0148,26.6226 +Kodak,4x4,ldr-rgb-kodak11.png,44.3357,0.0398,0.0224,17.5684 +Kodak,4x4,ldr-rgb-kodak12.png,47.1358,0.0305,0.0137,28.6854 +Kodak,4x4,ldr-rgb-kodak13.png,41.5073,0.0493,0.0307,12.8271 +Kodak,4x4,ldr-rgb-kodak14.png,41.9561,0.0476,0.0298,13.1859 +Kodak,4x4,ldr-rgb-kodak15.png,44.7852,0.0443,0.0261,15.0548 +Kodak,4x4,ldr-rgb-kodak16.png,47.3018,0.0286,0.0121,32.5563 +Kodak,4x4,ldr-rgb-kodak17.png,45.8895,0.0316,0.0133,29.5737 +Kodak,4x4,ldr-rgb-kodak18.png,41.7129,0.0547,0.0355,11.0918 +Kodak,4x4,ldr-rgb-kodak19.png,44.8948,0.0365,0.0179,22.0240 +Kodak,4x4,ldr-rgb-kodak20.png,46.4413,0.0318,0.0154,25.4902 +Kodak,4x4,ldr-rgb-kodak21.png,44.6688,0.0362,0.0188,20.8736 +Kodak,4x4,ldr-rgb-kodak22.png,43.2575,0.0485,0.0298,13.2102 +Kodak,4x4,ldr-rgb-kodak23.png,45.6976,0.0360,0.0184,21.4090 +Kodak,4x4,ldr-rgb-kodak24.png,42.0117,0.0476,0.0290,13.5713 +Kodak,5x5,ldr-rgb-kodak01.png,39.6381,0.0364,0.0181,21.7017 +Kodak,5x5,ldr-rgb-kodak02.png,40.6613,0.0358,0.0172,22.8747 +Kodak,5x5,ldr-rgb-kodak03.png,43.1070,0.0283,0.0116,33.8395 +Kodak,5x5,ldr-rgb-kodak04.png,41.3054,0.0345,0.0157,24.9976 +Kodak,5x5,ldr-rgb-kodak05.png,37.4812,0.0499,0.0310,12.6770 +Kodak,5x5,ldr-rgb-kodak06.png,40.6175,0.0322,0.0146,26.9713 +Kodak,5x5,ldr-rgb-kodak07.png,41.5316,0.0332,0.0151,26.0408 +Kodak,5x5,ldr-rgb-kodak08.png,37.7979,0.0512,0.0313,12.5713 +Kodak,5x5,ldr-rgb-kodak09.png,42.9386,0.0289,0.0105,37.3349 +Kodak,5x5,ldr-rgb-kodak10.png,42.6726,0.0293,0.0108,36.3379 +Kodak,5x5,ldr-rgb-kodak11.png,40.3558,0.0340,0.0166,23.6437 +Kodak,5x5,ldr-rgb-kodak12.png,43.4607,0.0267,0.0096,40.8923 +Kodak,5x5,ldr-rgb-kodak13.png,36.8488,0.0457,0.0267,14.7410 +Kodak,5x5,ldr-rgb-kodak14.png,38.0471,0.0460,0.0278,14.1390 +Kodak,5x5,ldr-rgb-kodak15.png,41.2322,0.0350,0.0166,23.6620 +Kodak,5x5,ldr-rgb-kodak16.png,43.5315,0.0256,0.0088,44.6230 +Kodak,5x5,ldr-rgb-kodak17.png,42.1157,0.0287,0.0100,39.1918 +Kodak,5x5,ldr-rgb-kodak18.png,38.1383,0.0429,0.0236,16.6822 +Kodak,5x5,ldr-rgb-kodak19.png,41.1817,0.0318,0.0128,30.6938 +Kodak,5x5,ldr-rgb-kodak20.png,42.3886,0.0281,0.0113,34.8447 +Kodak,5x5,ldr-rgb-kodak21.png,40.4523,0.0330,0.0156,25.2483 +Kodak,5x5,ldr-rgb-kodak22.png,39.8132,0.0378,0.0187,21.0535 +Kodak,5x5,ldr-rgb-kodak23.png,42.5506,0.0303,0.0122,32.1777 +Kodak,5x5,ldr-rgb-kodak24.png,37.9125,0.0407,0.0220,17.8581 +Kodak,6x6,ldr-rgb-kodak01.png,35.7576,0.0445,0.0268,14.6739 +Kodak,6x6,ldr-rgb-kodak02.png,38.1979,0.0366,0.0181,21.7785 +Kodak,6x6,ldr-rgb-kodak03.png,40.5936,0.0282,0.0116,33.9824 +Kodak,6x6,ldr-rgb-kodak04.png,38.5639,0.0353,0.0166,23.6424 +Kodak,6x6,ldr-rgb-kodak05.png,34.3707,0.0566,0.0379,10.3630 +Kodak,6x6,ldr-rgb-kodak06.png,37.3064,0.0354,0.0180,21.8634 +Kodak,6x6,ldr-rgb-kodak07.png,38.8907,0.0347,0.0163,24.1906 +Kodak,6x6,ldr-rgb-kodak08.png,34.4542,0.0574,0.0378,10.4094 +Kodak,6x6,ldr-rgb-kodak09.png,39.9832,0.0306,0.0124,31.7515 +Kodak,6x6,ldr-rgb-kodak10.png,39.7378,0.0304,0.0120,32.7678 +Kodak,6x6,ldr-rgb-kodak11.png,37.1622,0.0370,0.0196,20.0692 +Kodak,6x6,ldr-rgb-kodak12.png,40.7512,0.0269,0.0102,38.4974 +Kodak,6x6,ldr-rgb-kodak13.png,32.8161,0.0578,0.0390,10.0734 +Kodak,6x6,ldr-rgb-kodak14.png,35.3127,0.0505,0.0325,12.0881 +Kodak,6x6,ldr-rgb-kodak15.png,38.5805,0.0355,0.0174,22.5689 +Kodak,6x6,ldr-rgb-kodak16.png,40.5090,0.0270,0.0102,38.4337 +Kodak,6x6,ldr-rgb-kodak17.png,38.9529,0.0307,0.0122,32.1488 +Kodak,6x6,ldr-rgb-kodak18.png,35.1258,0.0462,0.0267,14.7003 +Kodak,6x6,ldr-rgb-kodak19.png,37.9862,0.0363,0.0175,22.5107 +Kodak,6x6,ldr-rgb-kodak20.png,39.1964,0.0304,0.0137,28.6769 +Kodak,6x6,ldr-rgb-kodak21.png,36.9178,0.0375,0.0201,19.5931 +Kodak,6x6,ldr-rgb-kodak22.png,36.9994,0.0397,0.0208,18.8636 +Kodak,6x6,ldr-rgb-kodak23.png,40.0813,0.0298,0.0122,32.3075 +Kodak,6x6,ldr-rgb-kodak24.png,34.8032,0.0432,0.0245,16.0516 +Kodak,8x8,ldr-rgb-kodak01.png,31.3412,0.0580,0.0399,9.8617 +Kodak,8x8,ldr-rgb-kodak02.png,34.9527,0.0366,0.0180,21.8330 +Kodak,8x8,ldr-rgb-kodak03.png,36.6102,0.0304,0.0134,29.3908 +Kodak,8x8,ldr-rgb-kodak04.png,35.1877,0.0364,0.0177,22.2270 +Kodak,8x8,ldr-rgb-kodak05.png,30.2580,0.0673,0.0482,8.1550 +Kodak,8x8,ldr-rgb-kodak06.png,32.9478,0.0449,0.0273,14.4077 +Kodak,8x8,ldr-rgb-kodak07.png,34.9976,0.0387,0.0200,19.6599 +Kodak,8x8,ldr-rgb-kodak08.png,29.9709,0.0692,0.0495,7.9409 +Kodak,8x8,ldr-rgb-kodak09.png,36.1754,0.0334,0.0149,26.4777 +Kodak,8x8,ldr-rgb-kodak10.png,35.8905,0.0325,0.0137,28.6123 +Kodak,8x8,ldr-rgb-kodak11.png,33.0125,0.0427,0.0251,15.6416 +Kodak,8x8,ldr-rgb-kodak12.png,36.7348,0.0297,0.0130,30.3358 +Kodak,8x8,ldr-rgb-kodak13.png,28.2212,0.0766,0.0576,6.8223 +Kodak,8x8,ldr-rgb-kodak14.png,31.5065,0.0564,0.0381,10.3095 +Kodak,8x8,ldr-rgb-kodak15.png,34.9514,0.0368,0.0183,21.4709 +Kodak,8x8,ldr-rgb-kodak16.png,36.0617,0.0331,0.0163,24.1237 +Kodak,8x8,ldr-rgb-kodak17.png,34.9137,0.0351,0.0161,24.4445 +Kodak,8x8,ldr-rgb-kodak18.png,31.2458,0.0534,0.0336,11.7109 +Kodak,8x8,ldr-rgb-kodak19.png,34.2323,0.0413,0.0222,17.7467 +Kodak,8x8,ldr-rgb-kodak20.png,35.2415,0.0329,0.0160,24.6424 +Kodak,8x8,ldr-rgb-kodak21.png,32.7559,0.0445,0.0267,14.7063 +Kodak,8x8,ldr-rgb-kodak22.png,33.4585,0.0428,0.0237,16.6104 +Kodak,8x8,ldr-rgb-kodak23.png,36.5494,0.0306,0.0125,31.4848 +Kodak,8x8,ldr-rgb-kodak24.png,30.8279,0.0497,0.0305,12.8814 +Kodak,12x12,ldr-rgb-kodak01.png,27.1096,0.0516,0.0320,12.3041 +Kodak,12x12,ldr-rgb-kodak02.png,31.1183,0.0297,0.0099,39.8441 +Kodak,12x12,ldr-rgb-kodak03.png,32.6995,0.0273,0.0086,45.6330 +Kodak,12x12,ldr-rgb-kodak04.png,31.5724,0.0286,0.0081,48.3543 +Kodak,12x12,ldr-rgb-kodak05.png,25.8234,0.0570,0.0365,10.7819 +Kodak,12x12,ldr-rgb-kodak06.png,28.6378,0.0417,0.0224,17.5519 +Kodak,12x12,ldr-rgb-kodak07.png,30.8626,0.0319,0.0117,33.4761 +Kodak,12x12,ldr-rgb-kodak08.png,25.4168,0.0638,0.0424,9.2815 +Kodak,12x12,ldr-rgb-kodak09.png,31.8375,0.0301,0.0100,39.4477 +Kodak,12x12,ldr-rgb-kodak10.png,31.5414,0.0300,0.0095,41.5056 +Kodak,12x12,ldr-rgb-kodak11.png,28.9389,0.0359,0.0166,23.6834 +Kodak,12x12,ldr-rgb-kodak12.png,32.2881,0.0270,0.0083,47.4036 +Kodak,12x12,ldr-rgb-kodak13.png,24.3214,0.0660,0.0452,8.6970 +Kodak,12x12,ldr-rgb-kodak14.png,27.5479,0.0434,0.0234,16.7789 +Kodak,12x12,ldr-rgb-kodak15.png,31.2617,0.0326,0.0124,31.7674 +Kodak,12x12,ldr-rgb-kodak16.png,31.4882,0.0293,0.0106,36.9949 +Kodak,12x12,ldr-rgb-kodak17.png,30.9019,0.0309,0.0104,37.7079 +Kodak,12x12,ldr-rgb-kodak18.png,27.4264,0.0433,0.0221,17.8232 +Kodak,12x12,ldr-rgb-kodak19.png,30.1924,0.0373,0.0165,23.7767 +Kodak,12x12,ldr-rgb-kodak20.png,31.0531,0.0303,0.0118,33.3091 +Kodak,12x12,ldr-rgb-kodak21.png,28.7189,0.0410,0.0218,18.0268 +Kodak,12x12,ldr-rgb-kodak22.png,29.8389,0.0336,0.0127,30.9182 +Kodak,12x12,ldr-rgb-kodak23.png,32.5301,0.0284,0.0087,45.1088 +Kodak,12x12,ldr-rgb-kodak24.png,26.7757,0.0433,0.0226,17.3774 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..5ce0196 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5795,0.0299,0.0133,29.5833 +Kodak,4x4,ldr-rgb-kodak02.png,43.9381,0.0355,0.0177,22.2357 +Kodak,4x4,ldr-rgb-kodak03.png,46.2152,0.0268,0.0108,36.4600 +Kodak,4x4,ldr-rgb-kodak04.png,44.2927,0.0336,0.0159,24.7727 +Kodak,4x4,ldr-rgb-kodak05.png,41.1428,0.0392,0.0215,18.2874 +Kodak,4x4,ldr-rgb-kodak06.png,44.5411,0.0297,0.0133,29.6386 +Kodak,4x4,ldr-rgb-kodak07.png,44.7409,0.0313,0.0137,28.7604 +Kodak,4x4,ldr-rgb-kodak08.png,41.5923,0.0408,0.0220,17.8728 +Kodak,4x4,ldr-rgb-kodak09.png,46.0423,0.0278,0.0104,37.8602 +Kodak,4x4,ldr-rgb-kodak10.png,45.8041,0.0286,0.0108,36.3619 +Kodak,4x4,ldr-rgb-kodak11.png,43.9389,0.0315,0.0150,26.2422 +Kodak,4x4,ldr-rgb-kodak12.png,46.5919,0.0262,0.0102,38.5929 +Kodak,4x4,ldr-rgb-kodak13.png,41.2499,0.0382,0.0204,19.3102 +Kodak,4x4,ldr-rgb-kodak14.png,41.2988,0.0347,0.0176,22.3366 +Kodak,4x4,ldr-rgb-kodak15.png,44.3214,0.0339,0.0165,23.8575 +Kodak,4x4,ldr-rgb-kodak16.png,47.1694,0.0255,0.0096,40.9898 +Kodak,4x4,ldr-rgb-kodak17.png,45.6555,0.0278,0.0101,39.0840 +Kodak,4x4,ldr-rgb-kodak18.png,41.3733,0.0399,0.0213,18.4263 +Kodak,4x4,ldr-rgb-kodak19.png,44.6305,0.0308,0.0128,30.6242 +Kodak,4x4,ldr-rgb-kodak20.png,45.9534,0.0270,0.0110,35.5952 +Kodak,4x4,ldr-rgb-kodak21.png,44.3559,0.0298,0.0134,29.3710 +Kodak,4x4,ldr-rgb-kodak22.png,42.8876,0.0367,0.0185,21.2067 +Kodak,4x4,ldr-rgb-kodak23.png,45.3933,0.0300,0.0128,30.6293 +Kodak,4x4,ldr-rgb-kodak24.png,41.4571,0.0356,0.0176,22.3420 +Kodak,5x5,ldr-rgb-kodak01.png,39.4156,0.0318,0.0149,26.3988 +Kodak,5x5,ldr-rgb-kodak02.png,40.4404,0.0308,0.0133,29.6588 +Kodak,5x5,ldr-rgb-kodak03.png,42.7468,0.0251,0.0090,43.6661 +Kodak,5x5,ldr-rgb-kodak04.png,40.9150,0.0301,0.0124,31.8262 +Kodak,5x5,ldr-rgb-kodak05.png,37.1354,0.0396,0.0216,18.1774 +Kodak,5x5,ldr-rgb-kodak06.png,40.4615,0.0286,0.0121,32.4595 +Kodak,5x5,ldr-rgb-kodak07.png,41.2239,0.0293,0.0118,33.3968 +Kodak,5x5,ldr-rgb-kodak08.png,37.4696,0.0412,0.0223,17.6298 +Kodak,5x5,ldr-rgb-kodak09.png,42.6412,0.0258,0.0087,45.3482 +Kodak,5x5,ldr-rgb-kodak10.png,42.4794,0.0267,0.0090,43.5991 +Kodak,5x5,ldr-rgb-kodak11.png,40.1335,0.0293,0.0128,30.7946 +Kodak,5x5,ldr-rgb-kodak12.png,43.2490,0.0242,0.0082,47.8187 +Kodak,5x5,ldr-rgb-kodak13.png,36.7590,0.0392,0.0212,18.5392 +Kodak,5x5,ldr-rgb-kodak14.png,37.6107,0.0349,0.0176,22.3001 +Kodak,5x5,ldr-rgb-kodak15.png,40.9602,0.0299,0.0125,31.5384 +Kodak,5x5,ldr-rgb-kodak16.png,43.4497,0.0240,0.0079,49.5112 +Kodak,5x5,ldr-rgb-kodak17.png,41.9868,0.0264,0.0087,45.4068 +Kodak,5x5,ldr-rgb-kodak18.png,37.9866,0.0362,0.0177,22.2153 +Kodak,5x5,ldr-rgb-kodak19.png,40.9421,0.0291,0.0110,35.5952 +Kodak,5x5,ldr-rgb-kodak20.png,42.1079,0.0252,0.0093,42.4314 +Kodak,5x5,ldr-rgb-kodak21.png,40.2657,0.0293,0.0127,31.0304 +Kodak,5x5,ldr-rgb-kodak22.png,39.5405,0.0324,0.0143,27.4974 +Kodak,5x5,ldr-rgb-kodak23.png,42.2534,0.0272,0.0100,39.3451 +Kodak,5x5,ldr-rgb-kodak24.png,37.7137,0.0338,0.0159,24.7415 +Kodak,6x6,ldr-rgb-kodak01.png,35.6691,0.0376,0.0205,19.1439 +Kodak,6x6,ldr-rgb-kodak02.png,38.1041,0.0309,0.0134,29.2766 +Kodak,6x6,ldr-rgb-kodak03.png,40.4304,0.0247,0.0089,44.4211 +Kodak,6x6,ldr-rgb-kodak04.png,38.3680,0.0304,0.0126,31.0919 +Kodak,6x6,ldr-rgb-kodak05.png,34.1707,0.0432,0.0255,15.4221 +Kodak,6x6,ldr-rgb-kodak06.png,37.2480,0.0307,0.0142,27.6602 +Kodak,6x6,ldr-rgb-kodak07.png,38.7045,0.0297,0.0123,31.8650 +Kodak,6x6,ldr-rgb-kodak08.png,34.2613,0.0448,0.0263,14.9683 +Kodak,6x6,ldr-rgb-kodak09.png,39.8077,0.0272,0.0097,40.4957 +Kodak,6x6,ldr-rgb-kodak10.png,39.6100,0.0273,0.0096,40.7821 +Kodak,6x6,ldr-rgb-kodak11.png,37.0497,0.0310,0.0145,27.0625 +Kodak,6x6,ldr-rgb-kodak12.png,40.6243,0.0243,0.0084,46.9342 +Kodak,6x6,ldr-rgb-kodak13.png,32.7545,0.0467,0.0289,13.6249 +Kodak,6x6,ldr-rgb-kodak14.png,35.0210,0.0372,0.0201,19.5543 +Kodak,6x6,ldr-rgb-kodak15.png,38.4585,0.0303,0.0130,30.3403 +Kodak,6x6,ldr-rgb-kodak16.png,40.4730,0.0246,0.0087,45.0054 +Kodak,6x6,ldr-rgb-kodak17.png,38.8727,0.0278,0.0100,39.1378 +Kodak,6x6,ldr-rgb-kodak18.png,35.0331,0.0381,0.0198,19.8403 +Kodak,6x6,ldr-rgb-kodak19.png,37.8639,0.0317,0.0139,28.2100 +Kodak,6x6,ldr-rgb-kodak20.png,39.0545,0.0264,0.0107,36.7279 +Kodak,6x6,ldr-rgb-kodak21.png,36.8418,0.0318,0.0153,25.6955 +Kodak,6x6,ldr-rgb-kodak22.png,36.8948,0.0335,0.0155,25.3917 +Kodak,6x6,ldr-rgb-kodak23.png,39.9299,0.0265,0.0096,41.0245 +Kodak,6x6,ldr-rgb-kodak24.png,34.7262,0.0361,0.0182,21.5720 +Kodak,8x8,ldr-rgb-kodak01.png,31.2040,0.0470,0.0291,13.5181 +Kodak,8x8,ldr-rgb-kodak02.png,34.8028,0.0321,0.0139,28.3340 +Kodak,8x8,ldr-rgb-kodak03.png,36.4818,0.0274,0.0106,36.9667 +Kodak,8x8,ldr-rgb-kodak04.png,35.0816,0.0321,0.0136,29.0088 +Kodak,8x8,ldr-rgb-kodak05.png,30.0677,0.0538,0.0352,11.1766 +Kodak,8x8,ldr-rgb-kodak06.png,32.8194,0.0378,0.0205,19.1637 +Kodak,8x8,ldr-rgb-kodak07.png,34.8484,0.0337,0.0154,25.5301 +Kodak,8x8,ldr-rgb-kodak08.png,29.7201,0.0564,0.0369,10.6658 +Kodak,8x8,ldr-rgb-kodak09.png,35.9413,0.0302,0.0118,33.2105 +Kodak,8x8,ldr-rgb-kodak10.png,35.7419,0.0295,0.0110,35.7371 +Kodak,8x8,ldr-rgb-kodak11.png,32.8868,0.0364,0.0189,20.8194 +Kodak,8x8,ldr-rgb-kodak12.png,36.5265,0.0273,0.0104,37.7545 +Kodak,8x8,ldr-rgb-kodak13.png,28.1462,0.0605,0.0418,9.4019 +Kodak,8x8,ldr-rgb-kodak14.png,31.3256,0.0453,0.0272,14.4596 +Kodak,8x8,ldr-rgb-kodak15.png,34.7780,0.0322,0.0139,28.2133 +Kodak,8x8,ldr-rgb-kodak16.png,35.9765,0.0295,0.0128,30.7734 +Kodak,8x8,ldr-rgb-kodak17.png,34.7433,0.0311,0.0125,31.4878 +Kodak,8x8,ldr-rgb-kodak18.png,31.1790,0.0440,0.0245,16.0325 +Kodak,8x8,ldr-rgb-kodak19.png,33.9167,0.0358,0.0169,23.2043 +Kodak,8x8,ldr-rgb-kodak20.png,35.0781,0.0293,0.0124,31.5837 +Kodak,8x8,ldr-rgb-kodak21.png,32.6526,0.0376,0.0200,19.6953 +Kodak,8x8,ldr-rgb-kodak22.png,33.3447,0.0367,0.0176,22.3112 +Kodak,8x8,ldr-rgb-kodak23.png,36.4202,0.0279,0.0099,39.7586 +Kodak,8x8,ldr-rgb-kodak24.png,30.7559,0.0417,0.0227,17.2926 +Kodak,12x12,ldr-rgb-kodak01.png,26.9944,0.0423,0.0230,17.1127 +Kodak,12x12,ldr-rgb-kodak02.png,31.0451,0.0275,0.0079,50.0415 +Kodak,12x12,ldr-rgb-kodak03.png,32.6384,0.0252,0.0070,55.7996 +Kodak,12x12,ldr-rgb-kodak04.png,31.4810,0.0268,0.0067,58.7325 +Kodak,12x12,ldr-rgb-kodak05.png,25.7089,0.0459,0.0259,15.1622 +Kodak,12x12,ldr-rgb-kodak06.png,28.4876,0.0349,0.0165,23.8124 +Kodak,12x12,ldr-rgb-kodak07.png,30.8061,0.0288,0.0091,43.1113 +Kodak,12x12,ldr-rgb-kodak08.png,25.2204,0.0514,0.0306,12.8641 +Kodak,12x12,ldr-rgb-kodak09.png,31.6441,0.0275,0.0079,49.6872 +Kodak,12x12,ldr-rgb-kodak10.png,31.4535,0.0276,0.0077,51.2465 +Kodak,12x12,ldr-rgb-kodak11.png,28.8707,0.0312,0.0125,31.4950 +Kodak,12x12,ldr-rgb-kodak12.png,32.1874,0.0248,0.0068,58.1937 +Kodak,12x12,ldr-rgb-kodak13.png,24.2468,0.0522,0.0321,12.2364 +Kodak,12x12,ldr-rgb-kodak14.png,27.4618,0.0361,0.0173,22.7611 +Kodak,12x12,ldr-rgb-kodak15.png,31.1647,0.0291,0.0096,40.8619 +Kodak,12x12,ldr-rgb-kodak16.png,31.3665,0.0265,0.0085,46.3798 +Kodak,12x12,ldr-rgb-kodak17.png,30.8424,0.0281,0.0082,47.6736 +Kodak,12x12,ldr-rgb-kodak18.png,27.3760,0.0367,0.0162,24.2621 +Kodak,12x12,ldr-rgb-kodak19.png,29.8759,0.0327,0.0127,31.0766 +Kodak,12x12,ldr-rgb-kodak20.png,30.9403,0.0271,0.0093,42.2261 +Kodak,12x12,ldr-rgb-kodak21.png,28.6206,0.0346,0.0160,24.6498 +Kodak,12x12,ldr-rgb-kodak22.png,29.7607,0.0300,0.0099,39.8076 +Kodak,12x12,ldr-rgb-kodak23.png,32.4940,0.0263,0.0071,55.6489 +Kodak,12x12,ldr-rgb-kodak24.png,26.7049,0.0368,0.0169,23.2082 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..2903e31 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3436,0.1044,0.0861,4.5680 +Kodak,4x4,ldr-rgb-kodak02.png,45.5149,0.1557,0.1367,2.8771 +Kodak,4x4,ldr-rgb-kodak03.png,47.7270,0.0807,0.0631,6.2267 +Kodak,4x4,ldr-rgb-kodak04.png,45.5617,0.1226,0.1031,3.8122 +Kodak,4x4,ldr-rgb-kodak05.png,42.2148,0.1364,0.1172,3.3539 +Kodak,4x4,ldr-rgb-kodak06.png,45.2285,0.0994,0.0814,4.8314 +Kodak,4x4,ldr-rgb-kodak07.png,46.0657,0.1003,0.0812,4.8426 +Kodak,4x4,ldr-rgb-kodak08.png,42.5596,0.1448,0.1248,3.1507 +Kodak,4x4,ldr-rgb-kodak09.png,47.2250,0.1202,0.1013,3.8808 +Kodak,4x4,ldr-rgb-kodak10.png,46.9183,0.1217,0.1025,3.8380 +Kodak,4x4,ldr-rgb-kodak11.png,44.9485,0.1205,0.1022,3.8457 +Kodak,4x4,ldr-rgb-kodak12.png,48.0140,0.0909,0.0735,5.3525 +Kodak,4x4,ldr-rgb-kodak13.png,41.6783,0.1125,0.0931,4.2235 +Kodak,4x4,ldr-rgb-kodak14.png,42.7635,0.1267,0.1082,3.6333 +Kodak,4x4,ldr-rgb-kodak15.png,45.6010,0.1083,0.0894,4.3972 +Kodak,4x4,ldr-rgb-kodak16.png,47.9487,0.0910,0.0729,5.3935 +Kodak,4x4,ldr-rgb-kodak17.png,46.3985,0.1033,0.0840,4.6808 +Kodak,4x4,ldr-rgb-kodak18.png,42.0873,0.1566,0.1366,2.8791 +Kodak,4x4,ldr-rgb-kodak19.png,45.4135,0.1237,0.1042,3.7725 +Kodak,4x4,ldr-rgb-kodak20.png,46.9562,0.0796,0.0621,6.3276 +Kodak,4x4,ldr-rgb-kodak21.png,45.2261,0.1259,0.1077,3.6497 +Kodak,4x4,ldr-rgb-kodak22.png,43.8626,0.1593,0.1397,2.8155 +Kodak,4x4,ldr-rgb-kodak23.png,46.9450,0.1253,0.1067,3.6850 +Kodak,4x4,ldr-rgb-kodak24.png,42.4147,0.1221,0.1026,3.8334 +Kodak,5x5,ldr-rgb-kodak01.png,40.1323,0.1157,0.0965,4.0734 +Kodak,5x5,ldr-rgb-kodak02.png,41.7976,0.1333,0.1135,3.4641 +Kodak,5x5,ldr-rgb-kodak03.png,44.1103,0.0655,0.0474,8.3034 +Kodak,5x5,ldr-rgb-kodak04.png,42.1172,0.1029,0.0826,4.7605 +Kodak,5x5,ldr-rgb-kodak05.png,38.0255,0.1383,0.1182,3.3257 +Kodak,5x5,ldr-rgb-kodak06.png,40.9959,0.0936,0.0748,5.2551 +Kodak,5x5,ldr-rgb-kodak07.png,42.5000,0.0847,0.0649,6.0634 +Kodak,5x5,ldr-rgb-kodak08.png,38.3799,0.1443,0.1233,3.1879 +Kodak,5x5,ldr-rgb-kodak09.png,43.8318,0.0751,0.0552,7.1172 +Kodak,5x5,ldr-rgb-kodak10.png,43.4528,0.0825,0.0622,6.3215 +Kodak,5x5,ldr-rgb-kodak11.png,40.8938,0.1085,0.0896,4.3870 +Kodak,5x5,ldr-rgb-kodak12.png,44.4299,0.0664,0.0481,8.1804 +Kodak,5x5,ldr-rgb-kodak13.png,36.9514,0.1161,0.0959,4.0992 +Kodak,5x5,ldr-rgb-kodak14.png,38.7191,0.1246,0.1055,3.7279 +Kodak,5x5,ldr-rgb-kodak15.png,41.9816,0.0979,0.0779,5.0454 +Kodak,5x5,ldr-rgb-kodak16.png,44.1799,0.0698,0.0514,7.6436 +Kodak,5x5,ldr-rgb-kodak17.png,42.5913,0.0726,0.0524,7.5047 +Kodak,5x5,ldr-rgb-kodak18.png,38.4192,0.1311,0.1102,3.5684 +Kodak,5x5,ldr-rgb-kodak19.png,41.6938,0.0910,0.0705,5.5760 +Kodak,5x5,ldr-rgb-kodak20.png,43.0178,0.0683,0.0499,7.8724 +Kodak,5x5,ldr-rgb-kodak21.png,40.7979,0.0941,0.0752,5.2307 +Kodak,5x5,ldr-rgb-kodak22.png,40.3244,0.1278,0.1075,3.6595 +Kodak,5x5,ldr-rgb-kodak23.png,43.6199,0.0896,0.0701,5.6086 +Kodak,5x5,ldr-rgb-kodak24.png,38.2265,0.1083,0.0880,4.4703 +Kodak,6x6,ldr-rgb-kodak01.png,36.2008,0.1199,0.1012,3.8852 +Kodak,6x6,ldr-rgb-kodak02.png,39.0638,0.1078,0.0883,4.4556 +Kodak,6x6,ldr-rgb-kodak03.png,41.3682,0.0569,0.0388,10.1438 +Kodak,6x6,ldr-rgb-kodak04.png,39.4191,0.0911,0.0713,5.5185 +Kodak,6x6,ldr-rgb-kodak05.png,34.8088,0.1362,0.1168,3.3679 +Kodak,6x6,ldr-rgb-kodak06.png,37.6472,0.0866,0.0682,5.7686 +Kodak,6x6,ldr-rgb-kodak07.png,39.8064,0.0760,0.0564,6.9660 +Kodak,6x6,ldr-rgb-kodak08.png,34.9897,0.1433,0.1228,3.2009 +Kodak,6x6,ldr-rgb-kodak09.png,40.8974,0.0604,0.0412,9.5548 +Kodak,6x6,ldr-rgb-kodak10.png,40.5253,0.0638,0.0442,8.8947 +Kodak,6x6,ldr-rgb-kodak11.png,37.6082,0.0953,0.0769,5.1141 +Kodak,6x6,ldr-rgb-kodak12.png,41.5111,0.0550,0.0372,10.5686 +Kodak,6x6,ldr-rgb-kodak13.png,32.9132,0.1287,0.1089,3.6116 +Kodak,6x6,ldr-rgb-kodak14.png,35.8599,0.1205,0.1016,3.8693 +Kodak,6x6,ldr-rgb-kodak15.png,39.2305,0.0901,0.0708,5.5515 +Kodak,6x6,ldr-rgb-kodak16.png,41.0574,0.0604,0.0425,9.2517 +Kodak,6x6,ldr-rgb-kodak17.png,39.5098,0.0638,0.0438,8.9673 +Kodak,6x6,ldr-rgb-kodak18.png,35.3754,0.1199,0.0995,3.9537 +Kodak,6x6,ldr-rgb-kodak19.png,38.5331,0.0826,0.0628,6.2607 +Kodak,6x6,ldr-rgb-kodak20.png,39.7790,0.0629,0.0452,8.6966 +Kodak,6x6,ldr-rgb-kodak21.png,37.2127,0.0843,0.0658,5.9775 +Kodak,6x6,ldr-rgb-kodak22.png,37.4858,0.1094,0.0895,4.3933 +Kodak,6x6,ldr-rgb-kodak23.png,41.0115,0.0682,0.0490,8.0292 +Kodak,6x6,ldr-rgb-kodak24.png,35.0719,0.0988,0.0790,4.9763 +Kodak,8x8,ldr-rgb-kodak01.png,31.8036,0.1636,0.1441,2.7290 +Kodak,8x8,ldr-rgb-kodak02.png,35.8059,0.1101,0.0900,4.3715 +Kodak,8x8,ldr-rgb-kodak03.png,37.7677,0.0698,0.0513,7.6616 +Kodak,8x8,ldr-rgb-kodak04.png,36.1068,0.1011,0.0808,4.8662 +Kodak,8x8,ldr-rgb-kodak05.png,30.7525,0.1792,0.1588,2.4766 +Kodak,8x8,ldr-rgb-kodak06.png,33.4479,0.1116,0.0924,4.2544 +Kodak,8x8,ldr-rgb-kodak07.png,36.1623,0.0923,0.0724,5.4338 +Kodak,8x8,ldr-rgb-kodak08.png,30.5413,0.1823,0.1611,2.4406 +Kodak,8x8,ldr-rgb-kodak09.png,37.2666,0.0716,0.0517,7.6078 +Kodak,8x8,ldr-rgb-kodak10.png,36.9291,0.0730,0.0526,7.4823 +Kodak,8x8,ldr-rgb-kodak11.png,33.6748,0.1142,0.0950,4.1402 +Kodak,8x8,ldr-rgb-kodak12.png,37.8421,0.0683,0.0497,7.9059 +Kodak,8x8,ldr-rgb-kodak13.png,28.3980,0.1767,0.1564,2.5141 +Kodak,8x8,ldr-rgb-kodak14.png,32.1539,0.1534,0.1336,2.9431 +Kodak,8x8,ldr-rgb-kodak15.png,35.8557,0.0934,0.0733,5.3613 +Kodak,8x8,ldr-rgb-kodak16.png,37.0420,0.0767,0.0583,6.7481 +Kodak,8x8,ldr-rgb-kodak17.png,35.6788,0.0783,0.0577,6.8179 +Kodak,8x8,ldr-rgb-kodak18.png,31.5601,0.1406,0.1197,3.2859 +Kodak,8x8,ldr-rgb-kodak19.png,34.7706,0.0994,0.0787,4.9961 +Kodak,8x8,ldr-rgb-kodak20.png,35.9106,0.0781,0.0595,6.6074 +Kodak,8x8,ldr-rgb-kodak21.png,33.1168,0.1075,0.0885,4.4430 +Kodak,8x8,ldr-rgb-kodak22.png,34.0527,0.1220,0.1015,3.8725 +Kodak,8x8,ldr-rgb-kodak23.png,37.6898,0.0718,0.0520,7.5639 +Kodak,8x8,ldr-rgb-kodak24.png,31.1316,0.1197,0.0993,3.9613 +Kodak,12x12,ldr-rgb-kodak01.png,27.7556,0.1754,0.1532,2.5668 +Kodak,12x12,ldr-rgb-kodak02.png,32.4643,0.0846,0.0616,6.3832 +Kodak,12x12,ldr-rgb-kodak03.png,33.8360,0.0626,0.0411,9.5624 +Kodak,12x12,ldr-rgb-kodak04.png,32.4512,0.0738,0.0505,7.7901 +Kodak,12x12,ldr-rgb-kodak05.png,26.3995,0.1918,0.1687,2.3304 +Kodak,12x12,ldr-rgb-kodak06.png,29.3774,0.1137,0.0919,4.2765 +Kodak,12x12,ldr-rgb-kodak07.png,32.0484,0.0899,0.0667,5.8943 +Kodak,12x12,ldr-rgb-kodak08.png,26.0631,0.1981,0.1743,2.2565 +Kodak,12x12,ldr-rgb-kodak09.png,33.1028,0.0668,0.0440,8.9406 +Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0670,0.0437,9.0073 +Kodak,12x12,ldr-rgb-kodak11.png,29.7578,0.1081,0.0862,4.5616 +Kodak,12x12,ldr-rgb-kodak12.png,33.8888,0.0622,0.0406,9.6925 +Kodak,12x12,ldr-rgb-kodak13.png,24.5306,0.1980,0.1749,2.2481 +Kodak,12x12,ldr-rgb-kodak14.png,28.4334,0.1512,0.1290,3.0492 +Kodak,12x12,ldr-rgb-kodak15.png,32.2456,0.0837,0.0609,6.4533 +Kodak,12x12,ldr-rgb-kodak16.png,32.9899,0.0709,0.0495,7.9431 +Kodak,12x12,ldr-rgb-kodak17.png,31.7938,0.0731,0.0499,7.8837 +Kodak,12x12,ldr-rgb-kodak18.png,27.7853,0.1350,0.1110,3.5440 +Kodak,12x12,ldr-rgb-kodak19.png,30.8937,0.0948,0.0714,5.5080 +Kodak,12x12,ldr-rgb-kodak20.png,31.8665,0.0732,0.0521,7.5469 +Kodak,12x12,ldr-rgb-kodak21.png,29.1859,0.1170,0.0949,4.1431 +Kodak,12x12,ldr-rgb-kodak22.png,30.5129,0.1023,0.0789,4.9867 +Kodak,12x12,ldr-rgb-kodak23.png,33.5762,0.0579,0.0353,11.1298 +Kodak,12x12,ldr-rgb-kodak24.png,27.1069,0.1193,0.0959,4.0984 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..24b6906 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5393,0.2298,0.2117,1.8573 +Kodak,4x4,ldr-rgb-kodak02.png,45.7829,0.3366,0.3176,1.2383 +Kodak,4x4,ldr-rgb-kodak03.png,48.1286,0.2660,0.2485,1.5827 +Kodak,4x4,ldr-rgb-kodak04.png,45.7459,0.2999,0.2803,1.4029 +Kodak,4x4,ldr-rgb-kodak05.png,42.4808,0.2926,0.2735,1.4378 +Kodak,4x4,ldr-rgb-kodak06.png,45.4283,0.2424,0.2244,1.7523 +Kodak,4x4,ldr-rgb-kodak07.png,46.4346,0.2944,0.2752,1.4290 +Kodak,4x4,ldr-rgb-kodak08.png,42.8524,0.3060,0.2860,1.3747 +Kodak,4x4,ldr-rgb-kodak09.png,47.4868,0.3139,0.2948,1.3338 +Kodak,4x4,ldr-rgb-kodak10.png,47.1520,0.3108,0.2915,1.3491 +Kodak,4x4,ldr-rgb-kodak11.png,45.2020,0.2794,0.2608,1.5078 +Kodak,4x4,ldr-rgb-kodak12.png,48.3163,0.2680,0.2503,1.5708 +Kodak,4x4,ldr-rgb-kodak13.png,41.7858,0.2391,0.2197,1.7896 +Kodak,4x4,ldr-rgb-kodak14.png,43.0205,0.2746,0.2559,1.5365 +Kodak,4x4,ldr-rgb-kodak15.png,45.8894,0.2872,0.2681,1.4666 +Kodak,4x4,ldr-rgb-kodak16.png,48.1595,0.2668,0.2490,1.5789 +Kodak,4x4,ldr-rgb-kodak17.png,46.5669,0.2827,0.2632,1.4940 +Kodak,4x4,ldr-rgb-kodak18.png,42.2513,0.3283,0.3082,1.2758 +Kodak,4x4,ldr-rgb-kodak19.png,45.6248,0.2963,0.2767,1.4213 +Kodak,4x4,ldr-rgb-kodak20.png,47.2126,0.1870,0.1696,2.3179 +Kodak,4x4,ldr-rgb-kodak21.png,45.3757,0.2973,0.2792,1.4082 +Kodak,4x4,ldr-rgb-kodak22.png,44.0484,0.3380,0.3183,1.2354 +Kodak,4x4,ldr-rgb-kodak23.png,47.2672,0.3290,0.3103,1.2673 +Kodak,4x4,ldr-rgb-kodak24.png,42.6395,0.2922,0.2727,1.4420 +Kodak,5x5,ldr-rgb-kodak01.png,40.2439,0.2842,0.2647,1.4854 +Kodak,5x5,ldr-rgb-kodak02.png,42.0748,0.3774,0.3573,1.1006 +Kodak,5x5,ldr-rgb-kodak03.png,44.4104,0.2838,0.2654,1.4815 +Kodak,5x5,ldr-rgb-kodak04.png,42.3039,0.3134,0.2933,1.3409 +Kodak,5x5,ldr-rgb-kodak05.png,38.2196,0.3354,0.3152,1.2474 +Kodak,5x5,ldr-rgb-kodak06.png,41.1196,0.2666,0.2477,1.5874 +Kodak,5x5,ldr-rgb-kodak07.png,42.7728,0.3165,0.2967,1.3254 +Kodak,5x5,ldr-rgb-kodak08.png,38.5537,0.3357,0.3146,1.2499 +Kodak,5x5,ldr-rgb-kodak09.png,44.0572,0.3100,0.2899,1.3564 +Kodak,5x5,ldr-rgb-kodak10.png,43.6371,0.3172,0.2970,1.3238 +Kodak,5x5,ldr-rgb-kodak11.png,41.0491,0.2998,0.2810,1.3991 +Kodak,5x5,ldr-rgb-kodak12.png,44.6371,0.2820,0.2638,1.4907 +Kodak,5x5,ldr-rgb-kodak13.png,36.9965,0.2578,0.2374,1.6564 +Kodak,5x5,ldr-rgb-kodak14.png,38.9373,0.3085,0.2892,1.3595 +Kodak,5x5,ldr-rgb-kodak15.png,42.2057,0.3039,0.2841,1.3842 +Kodak,5x5,ldr-rgb-kodak16.png,44.3209,0.2793,0.2606,1.5087 +Kodak,5x5,ldr-rgb-kodak17.png,42.6878,0.2871,0.2669,1.4731 +Kodak,5x5,ldr-rgb-kodak18.png,38.5091,0.3384,0.3174,1.2388 +Kodak,5x5,ldr-rgb-kodak19.png,41.8288,0.3146,0.2939,1.3379 +Kodak,5x5,ldr-rgb-kodak20.png,43.3334,0.2001,0.1818,2.1634 +Kodak,5x5,ldr-rgb-kodak21.png,40.9050,0.3229,0.3041,1.2932 +Kodak,5x5,ldr-rgb-kodak22.png,40.4714,0.3652,0.3447,1.1406 +Kodak,5x5,ldr-rgb-kodak23.png,43.9456,0.3620,0.3419,1.1501 +Kodak,5x5,ldr-rgb-kodak24.png,38.3490,0.3154,0.2950,1.3330 +Kodak,6x6,ldr-rgb-kodak01.png,36.3168,0.3292,0.3106,1.2662 +Kodak,6x6,ldr-rgb-kodak02.png,39.4281,0.4157,0.3960,0.9929 +Kodak,6x6,ldr-rgb-kodak03.png,41.7707,0.2541,0.2363,1.6641 +Kodak,6x6,ldr-rgb-kodak04.png,39.6843,0.3364,0.3166,1.2420 +Kodak,6x6,ldr-rgb-kodak05.png,35.0088,0.3775,0.3576,1.0996 +Kodak,6x6,ldr-rgb-kodak06.png,37.7698,0.2936,0.2750,1.4297 +Kodak,6x6,ldr-rgb-kodak07.png,40.1464,0.2976,0.2780,1.4144 +Kodak,6x6,ldr-rgb-kodak08.png,35.1763,0.3713,0.3510,1.1204 +Kodak,6x6,ldr-rgb-kodak09.png,41.2785,0.3186,0.2987,1.3162 +Kodak,6x6,ldr-rgb-kodak10.png,40.8522,0.3459,0.3260,1.2064 +Kodak,6x6,ldr-rgb-kodak11.png,37.7933,0.3265,0.3079,1.2770 +Kodak,6x6,ldr-rgb-kodak12.png,41.8544,0.2956,0.2777,1.4161 +Kodak,6x6,ldr-rgb-kodak13.png,32.9617,0.3110,0.2910,1.3511 +Kodak,6x6,ldr-rgb-kodak14.png,36.0569,0.3548,0.3360,1.1704 +Kodak,6x6,ldr-rgb-kodak15.png,39.4918,0.3001,0.2801,1.4036 +Kodak,6x6,ldr-rgb-kodak16.png,41.2543,0.2789,0.2608,1.5077 +Kodak,6x6,ldr-rgb-kodak17.png,39.6918,0.3075,0.2878,1.3661 +Kodak,6x6,ldr-rgb-kodak18.png,35.4609,0.3774,0.3569,1.1019 +Kodak,6x6,ldr-rgb-kodak19.png,38.7173,0.3529,0.3325,1.1825 +Kodak,6x6,ldr-rgb-kodak20.png,40.1243,0.2221,0.2043,1.9247 +Kodak,6x6,ldr-rgb-kodak21.png,37.3603,0.3518,0.3329,1.1812 +Kodak,6x6,ldr-rgb-kodak22.png,37.6556,0.4036,0.3830,1.0266 +Kodak,6x6,ldr-rgb-kodak23.png,41.4655,0.3697,0.3502,1.1228 +Kodak,6x6,ldr-rgb-kodak24.png,35.1889,0.3342,0.3137,1.2536 +Kodak,8x8,ldr-rgb-kodak01.png,31.9131,0.4170,0.3964,0.9920 +Kodak,8x8,ldr-rgb-kodak02.png,36.1767,0.4205,0.3988,0.9859 +Kodak,8x8,ldr-rgb-kodak03.png,38.2083,0.2286,0.2083,1.8877 +Kodak,8x8,ldr-rgb-kodak04.png,36.3928,0.3393,0.3173,1.2394 +Kodak,8x8,ldr-rgb-kodak05.png,30.9201,0.4553,0.4338,0.9064 +Kodak,8x8,ldr-rgb-kodak06.png,33.5817,0.3460,0.3254,1.2085 +Kodak,8x8,ldr-rgb-kodak07.png,36.5160,0.2796,0.2583,1.5226 +Kodak,8x8,ldr-rgb-kodak08.png,30.7384,0.4916,0.4693,0.8379 +Kodak,8x8,ldr-rgb-kodak09.png,37.5615,0.2534,0.2322,1.6934 +Kodak,8x8,ldr-rgb-kodak10.png,37.2421,0.2925,0.2710,1.4512 +Kodak,8x8,ldr-rgb-kodak11.png,33.8416,0.4015,0.3808,1.0327 +Kodak,8x8,ldr-rgb-kodak12.png,38.2751,0.2624,0.2423,1.6227 +Kodak,8x8,ldr-rgb-kodak13.png,28.4619,0.4341,0.4122,0.9539 +Kodak,8x8,ldr-rgb-kodak14.png,32.3307,0.4379,0.4168,0.9434 +Kodak,8x8,ldr-rgb-kodak15.png,36.0804,0.3215,0.3001,1.3103 +Kodak,8x8,ldr-rgb-kodak16.png,37.2806,0.2823,0.2626,1.4975 +Kodak,8x8,ldr-rgb-kodak17.png,35.8778,0.2787,0.2570,1.5298 +Kodak,8x8,ldr-rgb-kodak18.png,31.6559,0.4445,0.4219,0.9321 +Kodak,8x8,ldr-rgb-kodak19.png,34.9339,0.3049,0.2830,1.3893 +Kodak,8x8,ldr-rgb-kodak20.png,36.1622,0.2443,0.2240,1.7553 +Kodak,8x8,ldr-rgb-kodak21.png,33.2290,0.3224,0.3015,1.3041 +Kodak,8x8,ldr-rgb-kodak22.png,34.2355,0.4212,0.3993,0.9848 +Kodak,8x8,ldr-rgb-kodak23.png,38.2086,0.2771,0.2559,1.5365 +Kodak,8x8,ldr-rgb-kodak24.png,31.2397,0.3671,0.3453,1.1388 +Kodak,12x12,ldr-rgb-kodak01.png,27.9145,0.5262,0.5016,0.7839 +Kodak,12x12,ldr-rgb-kodak02.png,33.0098,0.3917,0.3665,1.0729 +Kodak,12x12,ldr-rgb-kodak03.png,34.4588,0.2358,0.2120,1.8552 +Kodak,12x12,ldr-rgb-kodak04.png,32.9763,0.3420,0.3163,1.2431 +Kodak,12x12,ldr-rgb-kodak05.png,26.6072,0.5708,0.5451,0.7213 +Kodak,12x12,ldr-rgb-kodak06.png,29.5340,0.3852,0.3607,1.0900 +Kodak,12x12,ldr-rgb-kodak07.png,32.6336,0.3002,0.2744,1.4328 +Kodak,12x12,ldr-rgb-kodak08.png,26.2642,0.5736,0.5474,0.7183 +Kodak,12x12,ldr-rgb-kodak09.png,33.6341,0.2709,0.2456,1.6009 +Kodak,12x12,ldr-rgb-kodak10.png,32.9911,0.2683,0.2427,1.6203 +Kodak,12x12,ldr-rgb-kodak11.png,30.0562,0.4160,0.3908,1.0061 +Kodak,12x12,ldr-rgb-kodak12.png,34.4444,0.2457,0.2216,1.7742 +Kodak,12x12,ldr-rgb-kodak13.png,24.5875,0.6112,0.5854,0.6717 +Kodak,12x12,ldr-rgb-kodak14.png,28.6495,0.5050,0.4801,0.8190 +Kodak,12x12,ldr-rgb-kodak15.png,32.7427,0.3302,0.3047,1.2905 +Kodak,12x12,ldr-rgb-kodak16.png,33.3405,0.2903,0.2665,1.4758 +Kodak,12x12,ldr-rgb-kodak17.png,32.1386,0.2873,0.2618,1.5019 +Kodak,12x12,ldr-rgb-kodak18.png,27.9275,0.5012,0.4746,0.8286 +Kodak,12x12,ldr-rgb-kodak19.png,31.1080,0.3935,0.3674,1.0702 +Kodak,12x12,ldr-rgb-kodak20.png,32.1759,0.3049,0.2810,1.3993 +Kodak,12x12,ldr-rgb-kodak21.png,29.3270,0.3710,0.3464,1.1352 +Kodak,12x12,ldr-rgb-kodak22.png,30.7891,0.4407,0.4146,0.9485 +Kodak,12x12,ldr-rgb-kodak23.png,34.3878,0.2430,0.2178,1.8055 +Kodak,12x12,ldr-rgb-kodak24.png,27.2398,0.4491,0.4232,0.9291 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..2820df9 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.9062,0.0321,0.0156,25.2274 +Kodak,4x4,ldr-rgb-kodak02.png,44.3467,0.0400,0.0227,17.3055 +Kodak,4x4,ldr-rgb-kodak03.png,46.8208,0.0286,0.0126,31.1112 +Kodak,4x4,ldr-rgb-kodak04.png,44.7048,0.0377,0.0201,19.5485 +Kodak,4x4,ldr-rgb-kodak05.png,41.6833,0.0476,0.0302,13.0006 +Kodak,4x4,ldr-rgb-kodak06.png,44.8187,0.0317,0.0155,25.4344 +Kodak,4x4,ldr-rgb-kodak07.png,45.1903,0.0341,0.0172,22.8361 +Kodak,4x4,ldr-rgb-kodak08.png,42.1528,0.0497,0.0313,12.5600 +Kodak,4x4,ldr-rgb-kodak09.png,46.3750,0.0287,0.0116,34.0301 +Kodak,4x4,ldr-rgb-kodak10.png,46.1453,0.0297,0.0123,32.0782 +Kodak,4x4,ldr-rgb-kodak11.png,44.3357,0.0352,0.0188,20.9303 +Kodak,4x4,ldr-rgb-kodak12.png,47.1358,0.0269,0.0114,34.5838 +Kodak,4x4,ldr-rgb-kodak13.png,41.5073,0.0435,0.0259,15.1973 +Kodak,4x4,ldr-rgb-kodak14.png,41.9561,0.0421,0.0251,15.6498 +Kodak,4x4,ldr-rgb-kodak15.png,44.7852,0.0391,0.0219,17.9264 +Kodak,4x4,ldr-rgb-kodak16.png,47.3018,0.0256,0.0099,39.6945 +Kodak,4x4,ldr-rgb-kodak17.png,45.8895,0.0284,0.0110,35.6791 +Kodak,4x4,ldr-rgb-kodak18.png,41.7129,0.0482,0.0299,13.1607 +Kodak,4x4,ldr-rgb-kodak19.png,44.8948,0.0327,0.0150,26.2614 +Kodak,4x4,ldr-rgb-kodak20.png,46.4413,0.0288,0.0130,30.2053 +Kodak,4x4,ldr-rgb-kodak21.png,44.6688,0.0326,0.0158,24.8118 +Kodak,4x4,ldr-rgb-kodak22.png,43.2575,0.0431,0.0252,15.5743 +Kodak,4x4,ldr-rgb-kodak23.png,45.6976,0.0322,0.0154,25.5020 +Kodak,4x4,ldr-rgb-kodak24.png,42.0117,0.0421,0.0244,16.1287 +Kodak,5x5,ldr-rgb-kodak01.png,39.6381,0.0318,0.0150,26.1622 +Kodak,5x5,ldr-rgb-kodak02.png,40.6613,0.0317,0.0145,27.0531 +Kodak,5x5,ldr-rgb-kodak03.png,43.1070,0.0258,0.0098,40.0512 +Kodak,5x5,ldr-rgb-kodak04.png,41.3054,0.0311,0.0133,29.5319 +Kodak,5x5,ldr-rgb-kodak05.png,37.4812,0.0436,0.0257,15.2954 +Kodak,5x5,ldr-rgb-kodak06.png,40.6175,0.0288,0.0122,32.1940 +Kodak,5x5,ldr-rgb-kodak07.png,41.5316,0.0302,0.0127,30.9089 +Kodak,5x5,ldr-rgb-kodak08.png,37.7979,0.0445,0.0257,15.3138 +Kodak,5x5,ldr-rgb-kodak09.png,42.9386,0.0263,0.0090,43.6222 +Kodak,5x5,ldr-rgb-kodak10.png,42.6726,0.0265,0.0090,43.4933 +Kodak,5x5,ldr-rgb-kodak11.png,40.3558,0.0305,0.0139,28.3887 +Kodak,5x5,ldr-rgb-kodak12.png,43.4607,0.0244,0.0083,47.4432 +Kodak,5x5,ldr-rgb-kodak13.png,36.8488,0.0395,0.0219,17.9305 +Kodak,5x5,ldr-rgb-kodak14.png,38.0471,0.0403,0.0231,17.0106 +Kodak,5x5,ldr-rgb-kodak15.png,41.2322,0.0313,0.0139,28.2322 +Kodak,5x5,ldr-rgb-kodak16.png,43.5315,0.0234,0.0075,52.1310 +Kodak,5x5,ldr-rgb-kodak17.png,42.1157,0.0264,0.0086,45.9624 +Kodak,5x5,ldr-rgb-kodak18.png,38.1383,0.0381,0.0197,19.9967 +Kodak,5x5,ldr-rgb-kodak19.png,41.1817,0.0287,0.0108,36.4624 +Kodak,5x5,ldr-rgb-kodak20.png,42.3886,0.0254,0.0096,41.1186 +Kodak,5x5,ldr-rgb-kodak21.png,40.4523,0.0298,0.0130,30.2335 +Kodak,5x5,ldr-rgb-kodak22.png,39.8132,0.0335,0.0157,25.1194 +Kodak,5x5,ldr-rgb-kodak23.png,42.5506,0.0274,0.0105,37.5773 +Kodak,5x5,ldr-rgb-kodak24.png,37.9125,0.0361,0.0182,21.6385 +Kodak,6x6,ldr-rgb-kodak01.png,35.7576,0.0388,0.0220,17.8817 +Kodak,6x6,ldr-rgb-kodak02.png,38.1979,0.0325,0.0152,25.9258 +Kodak,6x6,ldr-rgb-kodak03.png,40.5936,0.0255,0.0097,40.3757 +Kodak,6x6,ldr-rgb-kodak04.png,38.5639,0.0316,0.0139,28.2462 +Kodak,6x6,ldr-rgb-kodak05.png,34.3707,0.0488,0.0313,12.5712 +Kodak,6x6,ldr-rgb-kodak06.png,37.3064,0.0314,0.0149,26.3638 +Kodak,6x6,ldr-rgb-kodak07.png,38.8907,0.0308,0.0136,28.8157 +Kodak,6x6,ldr-rgb-kodak08.png,34.4542,0.0496,0.0312,12.6099 +Kodak,6x6,ldr-rgb-kodak09.png,39.9832,0.0275,0.0105,37.6176 +Kodak,6x6,ldr-rgb-kodak10.png,39.7378,0.0275,0.0101,38.9713 +Kodak,6x6,ldr-rgb-kodak11.png,37.1622,0.0328,0.0164,24.0425 +Kodak,6x6,ldr-rgb-kodak12.png,40.7512,0.0244,0.0087,45.1359 +Kodak,6x6,ldr-rgb-kodak13.png,32.8161,0.0498,0.0321,12.2623 +Kodak,6x6,ldr-rgb-kodak14.png,35.3127,0.0440,0.0270,14.5501 +Kodak,6x6,ldr-rgb-kodak15.png,38.5805,0.0319,0.0147,26.6988 +Kodak,6x6,ldr-rgb-kodak16.png,40.5090,0.0243,0.0086,45.6431 +Kodak,6x6,ldr-rgb-kodak17.png,38.9529,0.0279,0.0104,37.8602 +Kodak,6x6,ldr-rgb-kodak18.png,35.1258,0.0406,0.0222,17.7228 +Kodak,6x6,ldr-rgb-kodak19.png,37.9862,0.0323,0.0146,26.8974 +Kodak,6x6,ldr-rgb-kodak20.png,39.1964,0.0272,0.0115,34.2165 +Kodak,6x6,ldr-rgb-kodak21.png,36.9178,0.0330,0.0168,23.4461 +Kodak,6x6,ldr-rgb-kodak22.png,36.9994,0.0351,0.0175,22.5082 +Kodak,6x6,ldr-rgb-kodak23.png,40.0813,0.0271,0.0103,38.0068 +Kodak,6x6,ldr-rgb-kodak24.png,34.8032,0.0380,0.0204,19.2942 +Kodak,8x8,ldr-rgb-kodak01.png,31.3412,0.0501,0.0331,11.8930 +Kodak,8x8,ldr-rgb-kodak02.png,34.9527,0.0325,0.0152,25.8985 +Kodak,8x8,ldr-rgb-kodak03.png,36.6102,0.0276,0.0114,34.5259 +Kodak,8x8,ldr-rgb-kodak04.png,35.1877,0.0329,0.0150,26.2811 +Kodak,8x8,ldr-rgb-kodak05.png,30.2580,0.0580,0.0403,9.7693 +Kodak,8x8,ldr-rgb-kodak06.png,32.9478,0.0394,0.0228,17.2691 +Kodak,8x8,ldr-rgb-kodak07.png,34.9976,0.0343,0.0170,23.1782 +Kodak,8x8,ldr-rgb-kodak08.png,29.9709,0.0601,0.0414,9.5010 +Kodak,8x8,ldr-rgb-kodak09.png,36.1754,0.0299,0.0126,31.2202 +Kodak,8x8,ldr-rgb-kodak10.png,35.8905,0.0294,0.0118,33.4191 +Kodak,8x8,ldr-rgb-kodak11.png,33.0125,0.0377,0.0211,18.6482 +Kodak,8x8,ldr-rgb-kodak12.png,36.7348,0.0271,0.0111,35.5400 +Kodak,8x8,ldr-rgb-kodak13.png,28.2212,0.0659,0.0480,8.1842 +Kodak,8x8,ldr-rgb-kodak14.png,31.5065,0.0493,0.0320,12.2734 +Kodak,8x8,ldr-rgb-kodak15.png,34.9514,0.0330,0.0156,25.1820 +Kodak,8x8,ldr-rgb-kodak16.png,36.0617,0.0297,0.0137,28.6103 +Kodak,8x8,ldr-rgb-kodak17.png,34.9137,0.0310,0.0135,29.0200 +Kodak,8x8,ldr-rgb-kodak18.png,31.2458,0.0465,0.0280,14.0438 +Kodak,8x8,ldr-rgb-kodak19.png,34.2323,0.0364,0.0186,21.1155 +Kodak,8x8,ldr-rgb-kodak20.png,35.2415,0.0296,0.0135,29.1854 +Kodak,8x8,ldr-rgb-kodak21.png,32.7559,0.0392,0.0223,17.6189 +Kodak,8x8,ldr-rgb-kodak22.png,33.4585,0.0381,0.0199,19.7527 +Kodak,8x8,ldr-rgb-kodak23.png,36.5494,0.0277,0.0107,36.8420 +Kodak,8x8,ldr-rgb-kodak24.png,30.8279,0.0435,0.0257,15.3246 +Kodak,12x12,ldr-rgb-kodak01.png,27.1096,0.0471,0.0283,13.8980 +Kodak,12x12,ldr-rgb-kodak02.png,31.1183,0.0278,0.0089,44.3912 +Kodak,12x12,ldr-rgb-kodak03.png,32.6995,0.0255,0.0078,50.3148 +Kodak,12x12,ldr-rgb-kodak04.png,31.5724,0.0268,0.0072,54.6513 +Kodak,12x12,ldr-rgb-kodak05.png,25.8234,0.0517,0.0322,12.2272 +Kodak,12x12,ldr-rgb-kodak06.png,28.6378,0.0382,0.0198,19.8504 +Kodak,12x12,ldr-rgb-kodak07.png,30.8626,0.0295,0.0104,37.7294 +Kodak,12x12,ldr-rgb-kodak08.png,25.4168,0.0578,0.0372,10.5663 +Kodak,12x12,ldr-rgb-kodak09.png,31.8375,0.0279,0.0089,44.4116 +Kodak,12x12,ldr-rgb-kodak10.png,31.5414,0.0276,0.0085,46.3968 +Kodak,12x12,ldr-rgb-kodak11.png,28.9389,0.0330,0.0147,26.7660 +Kodak,12x12,ldr-rgb-kodak12.png,32.2881,0.0250,0.0073,53.7764 +Kodak,12x12,ldr-rgb-kodak13.png,24.3214,0.0597,0.0400,9.8206 +Kodak,12x12,ldr-rgb-kodak14.png,27.5479,0.0395,0.0208,18.9253 +Kodak,12x12,ldr-rgb-kodak15.png,31.2617,0.0300,0.0110,35.8015 +Kodak,12x12,ldr-rgb-kodak16.png,31.4882,0.0270,0.0095,41.4347 +Kodak,12x12,ldr-rgb-kodak17.png,30.9019,0.0287,0.0093,42.1043 +Kodak,12x12,ldr-rgb-kodak18.png,27.4264,0.0398,0.0196,20.0519 +Kodak,12x12,ldr-rgb-kodak19.png,30.1924,0.0343,0.0146,26.9440 +Kodak,12x12,ldr-rgb-kodak20.png,31.0531,0.0281,0.0105,37.6176 +Kodak,12x12,ldr-rgb-kodak21.png,28.7189,0.0375,0.0192,20.4662 +Kodak,12x12,ldr-rgb-kodak22.png,29.8389,0.0309,0.0114,34.5990 +Kodak,12x12,ldr-rgb-kodak23.png,32.5301,0.0265,0.0077,50.9348 +Kodak,12x12,ldr-rgb-kodak24.png,26.7757,0.0397,0.0202,19.4622 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..7c82d7e --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.5795,0.0272,0.0113,34.9495 +Kodak,4x4,ldr-rgb-kodak02.png,43.9381,0.0314,0.0150,26.2372 +Kodak,4x4,ldr-rgb-kodak03.png,46.2152,0.0242,0.0090,43.5071 +Kodak,4x4,ldr-rgb-kodak04.png,44.2927,0.0304,0.0135,29.2004 +Kodak,4x4,ldr-rgb-kodak05.png,41.1428,0.0348,0.0181,21.6826 +Kodak,4x4,ldr-rgb-kodak06.png,44.5411,0.0268,0.0112,35.1177 +Kodak,4x4,ldr-rgb-kodak07.png,44.7409,0.0280,0.0115,34.2193 +Kodak,4x4,ldr-rgb-kodak08.png,41.5923,0.0362,0.0186,21.1542 +Kodak,4x4,ldr-rgb-kodak09.png,46.0423,0.0252,0.0087,45.3644 +Kodak,4x4,ldr-rgb-kodak10.png,45.8041,0.0259,0.0090,43.7878 +Kodak,4x4,ldr-rgb-kodak11.png,43.9389,0.0285,0.0126,31.0989 +Kodak,4x4,ldr-rgb-kodak12.png,46.5919,0.0237,0.0086,45.9470 +Kodak,4x4,ldr-rgb-kodak13.png,41.2499,0.0340,0.0172,22.8601 +Kodak,4x4,ldr-rgb-kodak14.png,41.2988,0.0311,0.0150,26.2811 +Kodak,4x4,ldr-rgb-kodak15.png,44.3214,0.0304,0.0140,28.1796 +Kodak,4x4,ldr-rgb-kodak16.png,47.1694,0.0230,0.0081,48.7559 +Kodak,4x4,ldr-rgb-kodak17.png,45.6555,0.0253,0.0085,46.4517 +Kodak,4x4,ldr-rgb-kodak18.png,41.3733,0.0357,0.0180,21.8235 +Kodak,4x4,ldr-rgb-kodak19.png,44.6305,0.0279,0.0109,36.2110 +Kodak,4x4,ldr-rgb-kodak20.png,45.9534,0.0245,0.0093,42.1409 +Kodak,4x4,ldr-rgb-kodak21.png,44.3559,0.0270,0.0113,34.8380 +Kodak,4x4,ldr-rgb-kodak22.png,42.8876,0.0328,0.0158,24.9281 +Kodak,4x4,ldr-rgb-kodak23.png,45.3933,0.0269,0.0108,36.2819 +Kodak,4x4,ldr-rgb-kodak24.png,41.4571,0.0320,0.0149,26.4170 +Kodak,5x5,ldr-rgb-kodak01.png,39.4156,0.0285,0.0124,31.8238 +Kodak,5x5,ldr-rgb-kodak02.png,40.4404,0.0279,0.0113,34.7763 +Kodak,5x5,ldr-rgb-kodak03.png,42.7468,0.0229,0.0078,50.6983 +Kodak,5x5,ldr-rgb-kodak04.png,40.9150,0.0272,0.0105,37.6176 +Kodak,5x5,ldr-rgb-kodak05.png,37.1354,0.0350,0.0179,21.9111 +Kodak,5x5,ldr-rgb-kodak06.png,40.4615,0.0259,0.0102,38.4489 +Kodak,5x5,ldr-rgb-kodak07.png,41.2239,0.0265,0.0100,39.4713 +Kodak,5x5,ldr-rgb-kodak08.png,37.4696,0.0361,0.0184,21.3807 +Kodak,5x5,ldr-rgb-kodak09.png,42.6412,0.0238,0.0075,52.5328 +Kodak,5x5,ldr-rgb-kodak10.png,42.4794,0.0244,0.0076,51.5412 +Kodak,5x5,ldr-rgb-kodak11.png,40.1335,0.0266,0.0108,36.2644 +Kodak,5x5,ldr-rgb-kodak12.png,43.2490,0.0222,0.0071,55.7110 +Kodak,5x5,ldr-rgb-kodak13.png,36.7590,0.0344,0.0175,22.4913 +Kodak,5x5,ldr-rgb-kodak14.png,37.6107,0.0309,0.0149,26.4064 +Kodak,5x5,ldr-rgb-kodak15.png,40.9602,0.0270,0.0105,37.3492 +Kodak,5x5,ldr-rgb-kodak16.png,43.4497,0.0221,0.0068,57.9443 +Kodak,5x5,ldr-rgb-kodak17.png,41.9868,0.0242,0.0074,52.7867 +Kodak,5x5,ldr-rgb-kodak18.png,37.9866,0.0324,0.0147,26.6660 +Kodak,5x5,ldr-rgb-kodak19.png,40.9421,0.0264,0.0093,42.1129 +Kodak,5x5,ldr-rgb-kodak20.png,42.1079,0.0230,0.0079,50.0460 +Kodak,5x5,ldr-rgb-kodak21.png,40.2657,0.0264,0.0107,36.7075 +Kodak,5x5,ldr-rgb-kodak22.png,39.5405,0.0291,0.0120,32.6944 +Kodak,5x5,ldr-rgb-kodak23.png,42.2534,0.0247,0.0086,45.8232 +Kodak,5x5,ldr-rgb-kodak24.png,37.7137,0.0303,0.0133,29.5541 +Kodak,6x6,ldr-rgb-kodak01.png,35.6691,0.0326,0.0168,23.3972 +Kodak,6x6,ldr-rgb-kodak02.png,38.1041,0.0277,0.0113,34.8535 +Kodak,6x6,ldr-rgb-kodak03.png,40.4304,0.0225,0.0075,52.3112 +Kodak,6x6,ldr-rgb-kodak04.png,38.3680,0.0274,0.0107,36.7664 +Kodak,6x6,ldr-rgb-kodak05.png,34.1707,0.0377,0.0209,18.7829 +Kodak,6x6,ldr-rgb-kodak06.png,37.2480,0.0274,0.0119,33.1438 +Kodak,6x6,ldr-rgb-kodak07.png,38.7045,0.0266,0.0102,38.3774 +Kodak,6x6,ldr-rgb-kodak08.png,34.2613,0.0389,0.0215,18.3063 +Kodak,6x6,ldr-rgb-kodak09.png,39.8077,0.0245,0.0082,47.6736 +Kodak,6x6,ldr-rgb-kodak10.png,39.6100,0.0248,0.0081,48.5993 +Kodak,6x6,ldr-rgb-kodak11.png,37.0497,0.0278,0.0121,32.4110 +Kodak,6x6,ldr-rgb-kodak12.png,40.6243,0.0222,0.0071,55.1115 +Kodak,6x6,ldr-rgb-kodak13.png,32.7545,0.0405,0.0235,16.7369 +Kodak,6x6,ldr-rgb-kodak14.png,35.0210,0.0328,0.0167,23.5768 +Kodak,6x6,ldr-rgb-kodak15.png,38.4585,0.0274,0.0108,36.5076 +Kodak,6x6,ldr-rgb-kodak16.png,40.4730,0.0225,0.0074,53.1799 +Kodak,6x6,ldr-rgb-kodak17.png,38.8727,0.0253,0.0084,46.5356 +Kodak,6x6,ldr-rgb-kodak18.png,35.0331,0.0339,0.0165,23.8889 +Kodak,6x6,ldr-rgb-kodak19.png,37.8639,0.0284,0.0116,33.8020 +Kodak,6x6,ldr-rgb-kodak20.png,39.0545,0.0238,0.0090,43.8367 +Kodak,6x6,ldr-rgb-kodak21.png,36.8418,0.0282,0.0127,31.0059 +Kodak,6x6,ldr-rgb-kodak22.png,36.8948,0.0298,0.0129,30.4985 +Kodak,6x6,ldr-rgb-kodak23.png,39.9299,0.0241,0.0082,47.9885 +Kodak,6x6,ldr-rgb-kodak24.png,34.7262,0.0318,0.0150,26.1291 +Kodak,8x8,ldr-rgb-kodak01.png,31.2040,0.0410,0.0242,16.2339 +Kodak,8x8,ldr-rgb-kodak02.png,34.8028,0.0290,0.0118,33.3826 +Kodak,8x8,ldr-rgb-kodak03.png,36.4818,0.0249,0.0090,43.7646 +Kodak,8x8,ldr-rgb-kodak04.png,35.0816,0.0290,0.0114,34.4351 +Kodak,8x8,ldr-rgb-kodak05.png,30.0677,0.0468,0.0291,13.5251 +Kodak,8x8,ldr-rgb-kodak06.png,32.8194,0.0336,0.0171,22.9761 +Kodak,8x8,ldr-rgb-kodak07.png,34.8484,0.0300,0.0129,30.4018 +Kodak,8x8,ldr-rgb-kodak08.png,29.7201,0.0489,0.0304,12.9326 +Kodak,8x8,ldr-rgb-kodak09.png,35.9413,0.0272,0.0100,39.4958 +Kodak,8x8,ldr-rgb-kodak10.png,35.7419,0.0268,0.0094,41.9117 +Kodak,8x8,ldr-rgb-kodak11.png,32.8868,0.0321,0.0159,24.7727 +Kodak,8x8,ldr-rgb-kodak12.png,36.5265,0.0247,0.0089,44.2507 +Kodak,8x8,ldr-rgb-kodak13.png,28.1462,0.0522,0.0345,11.3910 +Kodak,8x8,ldr-rgb-kodak14.png,31.3256,0.0397,0.0228,17.2615 +Kodak,8x8,ldr-rgb-kodak15.png,34.7780,0.0290,0.0118,33.3914 +Kodak,8x8,ldr-rgb-kodak16.png,35.9765,0.0264,0.0107,36.7083 +Kodak,8x8,ldr-rgb-kodak17.png,34.7433,0.0282,0.0105,37.4026 +Kodak,8x8,ldr-rgb-kodak18.png,31.1790,0.0389,0.0205,19.1533 +Kodak,8x8,ldr-rgb-kodak19.png,33.9167,0.0319,0.0142,27.6060 +Kodak,8x8,ldr-rgb-kodak20.png,35.0781,0.0263,0.0105,37.2893 +Kodak,8x8,ldr-rgb-kodak21.png,32.6526,0.0331,0.0168,23.4391 +Kodak,8x8,ldr-rgb-kodak22.png,33.3447,0.0326,0.0149,26.4081 +Kodak,8x8,ldr-rgb-kodak23.png,36.4202,0.0253,0.0085,46.4949 +Kodak,8x8,ldr-rgb-kodak24.png,30.7559,0.0368,0.0191,20.5970 +Kodak,12x12,ldr-rgb-kodak01.png,26.9944,0.0385,0.0204,19.2876 +Kodak,12x12,ldr-rgb-kodak02.png,31.0451,0.0256,0.0070,56.3756 +Kodak,12x12,ldr-rgb-kodak03.png,32.6384,0.0233,0.0063,62.7623 +Kodak,12x12,ldr-rgb-kodak04.png,31.4810,0.0247,0.0060,65.7000 +Kodak,12x12,ldr-rgb-kodak05.png,25.7089,0.0418,0.0230,17.0622 +Kodak,12x12,ldr-rgb-kodak06.png,28.4876,0.0322,0.0147,26.7821 +Kodak,12x12,ldr-rgb-kodak07.png,30.8061,0.0265,0.0081,48.4608 +Kodak,12x12,ldr-rgb-kodak08.png,25.2204,0.0468,0.0271,14.5098 +Kodak,12x12,ldr-rgb-kodak09.png,31.6441,0.0255,0.0071,55.6640 +Kodak,12x12,ldr-rgb-kodak10.png,31.4535,0.0257,0.0069,56.9302 +Kodak,12x12,ldr-rgb-kodak11.png,28.8707,0.0289,0.0111,35.3071 +Kodak,12x12,ldr-rgb-kodak12.png,32.1874,0.0233,0.0061,64.7381 +Kodak,12x12,ldr-rgb-kodak13.png,24.2468,0.0477,0.0285,13.7869 +Kodak,12x12,ldr-rgb-kodak14.png,27.4618,0.0335,0.0154,25.5502 +Kodak,12x12,ldr-rgb-kodak15.png,31.1647,0.0271,0.0085,46.0496 +Kodak,12x12,ldr-rgb-kodak16.png,31.3665,0.0247,0.0076,52.0339 +Kodak,12x12,ldr-rgb-kodak17.png,30.8424,0.0262,0.0073,53.5877 +Kodak,12x12,ldr-rgb-kodak18.png,27.3760,0.0338,0.0144,27.2954 +Kodak,12x12,ldr-rgb-kodak19.png,29.8759,0.0302,0.0112,35.1776 +Kodak,12x12,ldr-rgb-kodak20.png,30.9403,0.0253,0.0083,47.5129 +Kodak,12x12,ldr-rgb-kodak21.png,28.6206,0.0319,0.0141,27.8362 +Kodak,12x12,ldr-rgb-kodak22.png,29.7607,0.0277,0.0088,44.8256 +Kodak,12x12,ldr-rgb-kodak23.png,32.4940,0.0243,0.0063,62.5552 +Kodak,12x12,ldr-rgb-kodak24.png,26.7049,0.0341,0.0151,26.1241 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..f6117e6 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3436,0.0901,0.0728,5.4000 +Kodak,4x4,ldr-rgb-kodak02.png,45.5149,0.1330,0.1145,3.4333 +Kodak,4x4,ldr-rgb-kodak03.png,47.7270,0.0700,0.0533,7.3787 +Kodak,4x4,ldr-rgb-kodak04.png,45.5617,0.1058,0.0872,4.5082 +Kodak,4x4,ldr-rgb-kodak05.png,42.2148,0.1174,0.0992,3.9636 +Kodak,4x4,ldr-rgb-kodak06.png,45.2285,0.0858,0.0687,5.7208 +Kodak,4x4,ldr-rgb-kodak07.png,46.0657,0.0861,0.0682,5.7657 +Kodak,4x4,ldr-rgb-kodak08.png,42.5596,0.1246,0.1055,3.7262 +Kodak,4x4,ldr-rgb-kodak09.png,47.2250,0.1027,0.0846,4.6468 +Kodak,4x4,ldr-rgb-kodak10.png,46.9183,0.1045,0.0863,4.5559 +Kodak,4x4,ldr-rgb-kodak11.png,44.9485,0.1044,0.0868,4.5309 +Kodak,4x4,ldr-rgb-kodak12.png,48.0140,0.0785,0.0618,6.3678 +Kodak,4x4,ldr-rgb-kodak13.png,41.6783,0.0975,0.0792,4.9653 +Kodak,4x4,ldr-rgb-kodak14.png,42.7635,0.1093,0.0917,4.2876 +Kodak,4x4,ldr-rgb-kodak15.png,45.6010,0.0934,0.0754,5.2153 +Kodak,4x4,ldr-rgb-kodak16.png,47.9487,0.0777,0.0613,6.4129 +Kodak,4x4,ldr-rgb-kodak17.png,46.3985,0.0892,0.0708,5.5530 +Kodak,4x4,ldr-rgb-kodak18.png,42.0873,0.1345,0.1154,3.4077 +Kodak,4x4,ldr-rgb-kodak19.png,45.4135,0.1065,0.0880,4.4706 +Kodak,4x4,ldr-rgb-kodak20.png,46.9562,0.0691,0.0522,7.5352 +Kodak,4x4,ldr-rgb-kodak21.png,45.2261,0.1075,0.0904,4.3520 +Kodak,4x4,ldr-rgb-kodak22.png,43.8626,0.1361,0.1176,3.3436 +Kodak,4x4,ldr-rgb-kodak23.png,46.9450,0.1074,0.0898,4.3788 +Kodak,4x4,ldr-rgb-kodak24.png,42.4147,0.1050,0.0866,4.5392 +Kodak,5x5,ldr-rgb-kodak01.png,40.1323,0.0966,0.0785,5.0096 +Kodak,5x5,ldr-rgb-kodak02.png,41.7976,0.1121,0.0933,4.2136 +Kodak,5x5,ldr-rgb-kodak03.png,44.1103,0.0561,0.0388,10.1295 +Kodak,5x5,ldr-rgb-kodak04.png,42.1172,0.0867,0.0676,5.8142 +Kodak,5x5,ldr-rgb-kodak05.png,38.0255,0.1157,0.0968,4.0611 +Kodak,5x5,ldr-rgb-kodak06.png,40.9959,0.0786,0.0608,6.4688 +Kodak,5x5,ldr-rgb-kodak07.png,42.5000,0.0720,0.0531,7.3992 +Kodak,5x5,ldr-rgb-kodak08.png,38.3799,0.1203,0.1004,3.9175 +Kodak,5x5,ldr-rgb-kodak09.png,43.8318,0.0636,0.0449,8.7668 +Kodak,5x5,ldr-rgb-kodak10.png,43.4528,0.0697,0.0505,7.7818 +Kodak,5x5,ldr-rgb-kodak11.png,40.8938,0.0914,0.0730,5.3884 +Kodak,5x5,ldr-rgb-kodak12.png,44.4299,0.0566,0.0392,10.0361 +Kodak,5x5,ldr-rgb-kodak13.png,36.9514,0.0977,0.0786,5.0019 +Kodak,5x5,ldr-rgb-kodak14.png,38.7191,0.1046,0.0862,4.5616 +Kodak,5x5,ldr-rgb-kodak15.png,41.9816,0.0827,0.0637,6.1715 +Kodak,5x5,ldr-rgb-kodak16.png,44.1799,0.0593,0.0419,9.3837 +Kodak,5x5,ldr-rgb-kodak17.png,42.5913,0.0620,0.0427,9.2071 +Kodak,5x5,ldr-rgb-kodak18.png,38.4192,0.1094,0.0897,4.3841 +Kodak,5x5,ldr-rgb-kodak19.png,41.6938,0.0771,0.0574,6.8507 +Kodak,5x5,ldr-rgb-kodak20.png,43.0178,0.0577,0.0405,9.7073 +Kodak,5x5,ldr-rgb-kodak21.png,40.7979,0.0791,0.0613,6.4168 +Kodak,5x5,ldr-rgb-kodak22.png,40.3244,0.1073,0.0878,4.4767 +Kodak,5x5,ldr-rgb-kodak23.png,43.6199,0.0755,0.0572,6.8792 +Kodak,5x5,ldr-rgb-kodak24.png,38.2265,0.0911,0.0719,5.4684 +Kodak,6x6,ldr-rgb-kodak01.png,36.2008,0.1000,0.0820,4.7967 +Kodak,6x6,ldr-rgb-kodak02.png,39.0638,0.0910,0.0725,5.4252 +Kodak,6x6,ldr-rgb-kodak03.png,41.3682,0.0485,0.0317,12.3926 +Kodak,6x6,ldr-rgb-kodak04.png,39.4191,0.0770,0.0581,6.7716 +Kodak,6x6,ldr-rgb-kodak05.png,34.8088,0.1135,0.0947,4.1519 +Kodak,6x6,ldr-rgb-kodak06.png,37.6472,0.0727,0.0550,7.1491 +Kodak,6x6,ldr-rgb-kodak07.png,39.8064,0.0644,0.0462,8.5196 +Kodak,6x6,ldr-rgb-kodak08.png,34.9897,0.1194,0.1001,3.9288 +Kodak,6x6,ldr-rgb-kodak09.png,40.8974,0.0520,0.0338,11.6368 +Kodak,6x6,ldr-rgb-kodak10.png,40.5253,0.0546,0.0360,10.9193 +Kodak,6x6,ldr-rgb-kodak11.png,37.6082,0.0798,0.0623,6.3119 +Kodak,6x6,ldr-rgb-kodak12.png,41.5111,0.0472,0.0301,13.0529 +Kodak,6x6,ldr-rgb-kodak13.png,32.9132,0.1077,0.0887,4.4330 +Kodak,6x6,ldr-rgb-kodak14.png,35.8599,0.1009,0.0827,4.7544 +Kodak,6x6,ldr-rgb-kodak15.png,39.2305,0.0763,0.0579,6.7968 +Kodak,6x6,ldr-rgb-kodak16.png,41.0574,0.0514,0.0345,11.3959 +Kodak,6x6,ldr-rgb-kodak17.png,39.5098,0.0544,0.0356,11.0504 +Kodak,6x6,ldr-rgb-kodak18.png,35.3754,0.1002,0.0806,4.8809 +Kodak,6x6,ldr-rgb-kodak19.png,38.5331,0.0705,0.0516,7.6183 +Kodak,6x6,ldr-rgb-kodak20.png,39.7790,0.0538,0.0370,10.6263 +Kodak,6x6,ldr-rgb-kodak21.png,37.2127,0.0713,0.0535,7.3437 +Kodak,6x6,ldr-rgb-kodak22.png,37.4858,0.0923,0.0733,5.3630 +Kodak,6x6,ldr-rgb-kodak23.png,41.0115,0.0584,0.0403,9.7522 +Kodak,6x6,ldr-rgb-kodak24.png,35.0719,0.0830,0.0642,6.1275 +Kodak,8x8,ldr-rgb-kodak01.png,31.8036,0.1386,0.1205,3.2636 +Kodak,8x8,ldr-rgb-kodak02.png,35.8059,0.0945,0.0752,5.2321 +Kodak,8x8,ldr-rgb-kodak03.png,37.7677,0.0605,0.0430,9.1541 +Kodak,8x8,ldr-rgb-kodak04.png,36.1068,0.0871,0.0678,5.8038 +Kodak,8x8,ldr-rgb-kodak05.png,30.7525,0.1526,0.1335,2.9464 +Kodak,8x8,ldr-rgb-kodak06.png,33.4479,0.0941,0.0762,5.1636 +Kodak,8x8,ldr-rgb-kodak07.png,36.1623,0.0795,0.0603,6.5175 +Kodak,8x8,ldr-rgb-kodak08.png,30.5413,0.1540,0.1338,2.9383 +Kodak,8x8,ldr-rgb-kodak09.png,37.2666,0.0619,0.0429,9.1680 +Kodak,8x8,ldr-rgb-kodak10.png,36.9291,0.0627,0.0435,9.0357 +Kodak,8x8,ldr-rgb-kodak11.png,33.6748,0.0967,0.0786,5.0024 +Kodak,8x8,ldr-rgb-kodak12.png,37.8421,0.0590,0.0413,9.5184 +Kodak,8x8,ldr-rgb-kodak13.png,28.3980,0.1488,0.1295,3.0356 +Kodak,8x8,ldr-rgb-kodak14.png,32.1539,0.1296,0.1109,3.5465 +Kodak,8x8,ldr-rgb-kodak15.png,35.8557,0.0802,0.0612,6.4286 +Kodak,8x8,ldr-rgb-kodak16.png,37.0420,0.0655,0.0482,8.1592 +Kodak,8x8,ldr-rgb-kodak17.png,35.6788,0.0667,0.0475,8.2845 +Kodak,8x8,ldr-rgb-kodak18.png,31.5601,0.1199,0.0998,3.9409 +Kodak,8x8,ldr-rgb-kodak19.png,34.7706,0.0846,0.0651,6.0426 +Kodak,8x8,ldr-rgb-kodak20.png,35.9106,0.0670,0.0496,7.9298 +Kodak,8x8,ldr-rgb-kodak21.png,33.1168,0.0914,0.0731,5.3759 +Kodak,8x8,ldr-rgb-kodak22.png,34.0527,0.1034,0.0840,4.6803 +Kodak,8x8,ldr-rgb-kodak23.png,37.6898,0.0620,0.0433,9.0775 +Kodak,8x8,ldr-rgb-kodak24.png,31.1316,0.1017,0.0824,4.7749 +Kodak,12x12,ldr-rgb-kodak01.png,27.7556,0.1567,0.1356,2.9005 +Kodak,12x12,ldr-rgb-kodak02.png,32.4643,0.0760,0.0543,7.2404 +Kodak,12x12,ldr-rgb-kodak03.png,33.8360,0.0569,0.0365,10.7733 +Kodak,12x12,ldr-rgb-kodak04.png,32.4512,0.0670,0.0446,8.8118 +Kodak,12x12,ldr-rgb-kodak05.png,26.3995,0.1704,0.1485,2.6484 +Kodak,12x12,ldr-rgb-kodak06.png,29.3774,0.1022,0.0812,4.8401 +Kodak,12x12,ldr-rgb-kodak07.png,32.0484,0.0810,0.0588,6.6859 +Kodak,12x12,ldr-rgb-kodak08.png,26.0631,0.1773,0.1544,2.5471 +Kodak,12x12,ldr-rgb-kodak09.png,33.1028,0.0608,0.0389,10.0998 +Kodak,12x12,ldr-rgb-kodak10.png,32.4884,0.0604,0.0384,10.2406 +Kodak,12x12,ldr-rgb-kodak11.png,29.7578,0.0972,0.0762,5.1571 +Kodak,12x12,ldr-rgb-kodak12.png,33.8888,0.0562,0.0357,11.0250 +Kodak,12x12,ldr-rgb-kodak13.png,24.5306,0.1767,0.1546,2.5427 +Kodak,12x12,ldr-rgb-kodak14.png,28.4334,0.1355,0.1143,3.4410 +Kodak,12x12,ldr-rgb-kodak15.png,32.2456,0.0757,0.0538,7.3095 +Kodak,12x12,ldr-rgb-kodak16.png,32.9899,0.0641,0.0436,9.0102 +Kodak,12x12,ldr-rgb-kodak17.png,31.7938,0.0663,0.0440,8.9276 +Kodak,12x12,ldr-rgb-kodak18.png,27.7853,0.1226,0.0990,3.9733 +Kodak,12x12,ldr-rgb-kodak19.png,30.8937,0.0851,0.0629,6.2518 +Kodak,12x12,ldr-rgb-kodak20.png,31.8665,0.0668,0.0463,8.4910 +Kodak,12x12,ldr-rgb-kodak21.png,29.1859,0.1056,0.0845,4.6526 +Kodak,12x12,ldr-rgb-kodak22.png,30.5129,0.0922,0.0696,5.6488 +Kodak,12x12,ldr-rgb-kodak23.png,33.5762,0.0527,0.0313,12.5809 +Kodak,12x12,ldr-rgb-kodak24.png,27.1069,0.1071,0.0849,4.6322 diff --git a/Test/Images/Kodak/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..500b136 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5393,0.1981,0.1806,2.1768 +Kodak,4x4,ldr-rgb-kodak02.png,45.7829,0.2881,0.2700,1.4566 +Kodak,4x4,ldr-rgb-kodak03.png,48.1286,0.2259,0.2094,1.8781 +Kodak,4x4,ldr-rgb-kodak04.png,45.7459,0.2548,0.2364,1.6632 +Kodak,4x4,ldr-rgb-kodak05.png,42.4808,0.2561,0.2370,1.6591 +Kodak,4x4,ldr-rgb-kodak06.png,45.4283,0.2067,0.1896,2.0743 +Kodak,4x4,ldr-rgb-kodak07.png,46.4346,0.2507,0.2321,1.6943 +Kodak,4x4,ldr-rgb-kodak08.png,42.8524,0.2607,0.2417,1.6271 +Kodak,4x4,ldr-rgb-kodak09.png,47.4868,0.2682,0.2496,1.5756 +Kodak,4x4,ldr-rgb-kodak10.png,47.1520,0.2637,0.2454,1.6025 +Kodak,4x4,ldr-rgb-kodak11.png,45.2020,0.2374,0.2202,1.7854 +Kodak,4x4,ldr-rgb-kodak12.png,48.3163,0.2296,0.2128,1.8480 +Kodak,4x4,ldr-rgb-kodak13.png,41.7858,0.2050,0.1866,2.1073 +Kodak,4x4,ldr-rgb-kodak14.png,43.0205,0.2337,0.2160,1.8201 +Kodak,4x4,ldr-rgb-kodak15.png,45.8894,0.2444,0.2262,1.7386 +Kodak,4x4,ldr-rgb-kodak16.png,48.1595,0.2256,0.2091,1.8808 +Kodak,4x4,ldr-rgb-kodak17.png,46.5669,0.2406,0.2222,1.7695 +Kodak,4x4,ldr-rgb-kodak18.png,42.2513,0.2792,0.2602,1.5112 +Kodak,4x4,ldr-rgb-kodak19.png,45.6248,0.2529,0.2336,1.6831 +Kodak,4x4,ldr-rgb-kodak20.png,47.2126,0.1597,0.1433,2.7449 +Kodak,4x4,ldr-rgb-kodak21.png,45.3757,0.2526,0.2355,1.6700 +Kodak,4x4,ldr-rgb-kodak22.png,44.0484,0.2880,0.2693,1.4600 +Kodak,4x4,ldr-rgb-kodak23.png,47.2672,0.2795,0.2617,1.5026 +Kodak,4x4,ldr-rgb-kodak24.png,42.6395,0.2501,0.2317,1.6972 +Kodak,5x5,ldr-rgb-kodak01.png,40.2439,0.2369,0.2184,1.8005 +Kodak,5x5,ldr-rgb-kodak02.png,42.0748,0.3161,0.2973,1.3226 +Kodak,5x5,ldr-rgb-kodak03.png,44.4104,0.2367,0.2188,1.7974 +Kodak,5x5,ldr-rgb-kodak04.png,42.3039,0.2605,0.2414,1.6292 +Kodak,5x5,ldr-rgb-kodak05.png,38.2196,0.2795,0.2602,1.5114 +Kodak,5x5,ldr-rgb-kodak06.png,41.1196,0.2216,0.2036,1.9317 +Kodak,5x5,ldr-rgb-kodak07.png,42.7728,0.2630,0.2441,1.6109 +Kodak,5x5,ldr-rgb-kodak08.png,38.5537,0.2773,0.2572,1.5289 +Kodak,5x5,ldr-rgb-kodak09.png,44.0572,0.2572,0.2385,1.6486 +Kodak,5x5,ldr-rgb-kodak10.png,43.6371,0.2637,0.2447,1.6066 +Kodak,5x5,ldr-rgb-kodak11.png,41.0491,0.2500,0.2317,1.6971 +Kodak,5x5,ldr-rgb-kodak12.png,44.6371,0.2353,0.2179,1.8047 +Kodak,5x5,ldr-rgb-kodak13.png,36.9965,0.2156,0.1960,2.0058 +Kodak,5x5,ldr-rgb-kodak14.png,38.9373,0.2578,0.2392,1.6441 +Kodak,5x5,ldr-rgb-kodak15.png,42.2057,0.2520,0.2329,1.6885 +Kodak,5x5,ldr-rgb-kodak16.png,44.3209,0.2327,0.2151,1.8282 +Kodak,5x5,ldr-rgb-kodak17.png,42.6878,0.2396,0.2202,1.7860 +Kodak,5x5,ldr-rgb-kodak18.png,38.5091,0.2814,0.2617,1.5027 +Kodak,5x5,ldr-rgb-kodak19.png,41.8288,0.2608,0.2410,1.6317 +Kodak,5x5,ldr-rgb-kodak20.png,43.3334,0.1680,0.1504,2.6153 +Kodak,5x5,ldr-rgb-kodak21.png,40.9050,0.2689,0.2509,1.5673 +Kodak,5x5,ldr-rgb-kodak22.png,40.4714,0.3017,0.2825,1.3919 +Kodak,5x5,ldr-rgb-kodak23.png,43.9456,0.3024,0.2837,1.3858 +Kodak,5x5,ldr-rgb-kodak24.png,38.3490,0.2650,0.2454,1.6022 +Kodak,6x6,ldr-rgb-kodak01.png,36.3168,0.2737,0.2556,1.5382 +Kodak,6x6,ldr-rgb-kodak02.png,39.4281,0.3488,0.3301,1.1911 +Kodak,6x6,ldr-rgb-kodak03.png,41.7707,0.2116,0.1942,2.0250 +Kodak,6x6,ldr-rgb-kodak04.png,39.6843,0.2797,0.2610,1.5068 +Kodak,6x6,ldr-rgb-kodak05.png,35.0088,0.3137,0.2949,1.3332 +Kodak,6x6,ldr-rgb-kodak06.png,37.7698,0.2443,0.2269,1.7332 +Kodak,6x6,ldr-rgb-kodak07.png,40.1464,0.2450,0.2265,1.7357 +Kodak,6x6,ldr-rgb-kodak08.png,35.1763,0.3106,0.2911,1.3507 +Kodak,6x6,ldr-rgb-kodak09.png,41.2785,0.2651,0.2467,1.5937 +Kodak,6x6,ldr-rgb-kodak10.png,40.8522,0.2872,0.2683,1.4655 +Kodak,6x6,ldr-rgb-kodak11.png,37.7933,0.2712,0.2533,1.5525 +Kodak,6x6,ldr-rgb-kodak12.png,41.8544,0.2438,0.2269,1.7331 +Kodak,6x6,ldr-rgb-kodak13.png,32.9617,0.2597,0.2410,1.6316 +Kodak,6x6,ldr-rgb-kodak14.png,36.0569,0.2959,0.2778,1.4157 +Kodak,6x6,ldr-rgb-kodak15.png,39.4918,0.2497,0.2314,1.6993 +Kodak,6x6,ldr-rgb-kodak16.png,41.2543,0.2301,0.2131,1.8455 +Kodak,6x6,ldr-rgb-kodak17.png,39.6918,0.2579,0.2392,1.6438 +Kodak,6x6,ldr-rgb-kodak18.png,35.4609,0.3166,0.2966,1.3258 +Kodak,6x6,ldr-rgb-kodak19.png,38.7173,0.2959,0.2769,1.4201 +Kodak,6x6,ldr-rgb-kodak20.png,40.1243,0.1862,0.1693,2.3230 +Kodak,6x6,ldr-rgb-kodak21.png,37.3603,0.2918,0.2743,1.4333 +Kodak,6x6,ldr-rgb-kodak22.png,37.6556,0.3368,0.3179,1.2369 +Kodak,6x6,ldr-rgb-kodak23.png,41.4655,0.3095,0.2913,1.3499 +Kodak,6x6,ldr-rgb-kodak24.png,35.1889,0.2771,0.2584,1.5218 +Kodak,8x8,ldr-rgb-kodak01.png,31.9131,0.3554,0.3355,1.1721 +Kodak,8x8,ldr-rgb-kodak02.png,36.1767,0.3591,0.3388,1.1607 +Kodak,8x8,ldr-rgb-kodak03.png,38.2083,0.1927,0.1738,2.2624 +Kodak,8x8,ldr-rgb-kodak04.png,36.3928,0.2898,0.2692,1.4609 +Kodak,8x8,ldr-rgb-kodak05.png,30.9201,0.3850,0.3643,1.0793 +Kodak,8x8,ldr-rgb-kodak06.png,33.5817,0.2939,0.2746,1.4320 +Kodak,8x8,ldr-rgb-kodak07.png,36.5160,0.2393,0.2190,1.7959 +Kodak,8x8,ldr-rgb-kodak08.png,30.7384,0.4190,0.3971,0.9903 +Kodak,8x8,ldr-rgb-kodak09.png,37.5615,0.2149,0.1941,2.0258 +Kodak,8x8,ldr-rgb-kodak10.png,37.2421,0.2466,0.2256,1.7428 +Kodak,8x8,ldr-rgb-kodak11.png,33.8416,0.3435,0.3236,1.2150 +Kodak,8x8,ldr-rgb-kodak12.png,38.2751,0.2230,0.2039,1.9288 +Kodak,8x8,ldr-rgb-kodak13.png,28.4619,0.3689,0.3475,1.1314 +Kodak,8x8,ldr-rgb-kodak14.png,32.3307,0.3717,0.3517,1.1179 +Kodak,8x8,ldr-rgb-kodak15.png,36.0804,0.2746,0.2543,1.5465 +Kodak,8x8,ldr-rgb-kodak16.png,37.2806,0.2390,0.2198,1.7890 +Kodak,8x8,ldr-rgb-kodak17.png,35.8778,0.2361,0.2156,1.8242 +Kodak,8x8,ldr-rgb-kodak18.png,31.6559,0.3798,0.3582,1.0978 +Kodak,8x8,ldr-rgb-kodak19.png,34.9339,0.2578,0.2369,1.6597 +Kodak,8x8,ldr-rgb-kodak20.png,36.1622,0.2061,0.1870,2.1030 +Kodak,8x8,ldr-rgb-kodak21.png,33.2290,0.2725,0.2529,1.5546 +Kodak,8x8,ldr-rgb-kodak22.png,34.2355,0.3549,0.3341,1.1770 +Kodak,8x8,ldr-rgb-kodak23.png,38.2086,0.2362,0.2162,1.8188 +Kodak,8x8,ldr-rgb-kodak24.png,31.2397,0.3135,0.2929,1.3425 +Kodak,12x12,ldr-rgb-kodak01.png,27.9145,0.4694,0.4458,0.8820 +Kodak,12x12,ldr-rgb-kodak02.png,33.0098,0.3500,0.3258,1.2068 +Kodak,12x12,ldr-rgb-kodak03.png,34.4588,0.2098,0.1868,2.1048 +Kodak,12x12,ldr-rgb-kodak04.png,32.9763,0.3061,0.2812,1.3985 +Kodak,12x12,ldr-rgb-kodak05.png,26.6072,0.5078,0.4831,0.8139 +Kodak,12x12,ldr-rgb-kodak06.png,29.5340,0.3430,0.3194,1.2311 +Kodak,12x12,ldr-rgb-kodak07.png,32.6336,0.2670,0.2428,1.6197 +Kodak,12x12,ldr-rgb-kodak08.png,26.2642,0.5100,0.4848,0.8110 +Kodak,12x12,ldr-rgb-kodak09.png,33.6341,0.2413,0.2169,1.8126 +Kodak,12x12,ldr-rgb-kodak10.png,32.9911,0.2399,0.2153,1.8267 +Kodak,12x12,ldr-rgb-kodak11.png,30.0562,0.3696,0.3461,1.1363 +Kodak,12x12,ldr-rgb-kodak12.png,34.4444,0.2193,0.1964,2.0016 +Kodak,12x12,ldr-rgb-kodak13.png,24.5875,0.5441,0.5195,0.7568 +Kodak,12x12,ldr-rgb-kodak14.png,28.6495,0.4497,0.4260,0.9231 +Kodak,12x12,ldr-rgb-kodak15.png,32.7427,0.2943,0.2699,1.4571 +Kodak,12x12,ldr-rgb-kodak16.png,33.3405,0.2597,0.2366,1.6617 +Kodak,12x12,ldr-rgb-kodak17.png,32.1386,0.2559,0.2312,1.7006 +Kodak,12x12,ldr-rgb-kodak18.png,27.9275,0.4466,0.4211,0.9338 +Kodak,12x12,ldr-rgb-kodak19.png,31.1080,0.3509,0.3262,1.2056 +Kodak,12x12,ldr-rgb-kodak20.png,32.1759,0.2725,0.2499,1.5738 +Kodak,12x12,ldr-rgb-kodak21.png,29.3270,0.3296,0.3059,1.2855 +Kodak,12x12,ldr-rgb-kodak22.png,30.7891,0.3921,0.3675,1.0699 +Kodak,12x12,ldr-rgb-kodak23.png,34.3878,0.2166,0.1928,2.0396 +Kodak,12x12,ldr-rgb-kodak24.png,27.2398,0.3997,0.3750,1.0487 diff --git a/Test/Images/Kodak/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/Kodak/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..34b2850 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.9317,0.0301,0.0140,28.1291 +Kodak,4x4,ldr-rgb-kodak02.png,44.3574,0.0373,0.0205,19.1793 +Kodak,4x4,ldr-rgb-kodak03.png,46.8812,0.0265,0.0112,35.1207 +Kodak,4x4,ldr-rgb-kodak04.png,44.7563,0.0352,0.0182,21.6530 +Kodak,4x4,ldr-rgb-kodak05.png,41.6976,0.0448,0.0277,14.2036 +Kodak,4x4,ldr-rgb-kodak06.png,44.8470,0.0298,0.0137,28.6326 +Kodak,4x4,ldr-rgb-kodak07.png,45.2201,0.0323,0.0155,25.3246 +Kodak,4x4,ldr-rgb-kodak08.png,42.1710,0.0466,0.0286,13.7719 +Kodak,4x4,ldr-rgb-kodak09.png,46.4128,0.0271,0.0103,38.0436 +Kodak,4x4,ldr-rgb-kodak10.png,46.1994,0.0278,0.0108,36.2915 +Kodak,4x4,ldr-rgb-kodak11.png,44.3651,0.0331,0.0170,23.1003 +Kodak,4x4,ldr-rgb-kodak12.png,47.2299,0.0254,0.0100,39.3179 +Kodak,4x4,ldr-rgb-kodak13.png,41.5167,0.0404,0.0234,16.7827 +Kodak,4x4,ldr-rgb-kodak14.png,41.9783,0.0391,0.0227,17.3421 +Kodak,4x4,ldr-rgb-kodak15.png,44.8240,0.0366,0.0197,19.9098 +Kodak,4x4,ldr-rgb-kodak16.png,47.3632,0.0239,0.0086,45.6646 +Kodak,4x4,ldr-rgb-kodak17.png,45.9484,0.0267,0.0097,40.3510 +Kodak,4x4,ldr-rgb-kodak18.png,41.7267,0.0453,0.0273,14.3788 +Kodak,4x4,ldr-rgb-kodak19.png,44.9264,0.0306,0.0134,29.2683 +Kodak,4x4,ldr-rgb-kodak20.png,46.4925,0.0269,0.0117,33.7239 +Kodak,4x4,ldr-rgb-kodak21.png,44.6922,0.0302,0.0142,27.6310 +Kodak,4x4,ldr-rgb-kodak22.png,43.2771,0.0401,0.0228,17.2319 +Kodak,4x4,ldr-rgb-kodak23.png,45.7318,0.0301,0.0138,28.5494 +Kodak,4x4,ldr-rgb-kodak24.png,42.0324,0.0391,0.0220,17.9044 +Kodak,5x5,ldr-rgb-kodak01.png,39.6466,0.0290,0.0126,31.3269 +Kodak,5x5,ldr-rgb-kodak02.png,40.6700,0.0293,0.0123,31.9168 +Kodak,5x5,ldr-rgb-kodak03.png,43.1639,0.0242,0.0085,46.3694 +Kodak,5x5,ldr-rgb-kodak04.png,41.3369,0.0286,0.0113,34.8756 +Kodak,5x5,ldr-rgb-kodak05.png,37.4860,0.0399,0.0221,17.7997 +Kodak,5x5,ldr-rgb-kodak06.png,40.6389,0.0264,0.0104,37.7761 +Kodak,5x5,ldr-rgb-kodak07.png,41.5489,0.0278,0.0108,36.3211 +Kodak,5x5,ldr-rgb-kodak08.png,37.8058,0.0406,0.0223,17.6592 +Kodak,5x5,ldr-rgb-kodak09.png,42.9484,0.0244,0.0076,51.8002 +Kodak,5x5,ldr-rgb-kodak10.png,42.6891,0.0251,0.0077,50.7842 +Kodak,5x5,ldr-rgb-kodak11.png,40.3663,0.0278,0.0119,33.0601 +Kodak,5x5,ldr-rgb-kodak12.png,43.5162,0.0226,0.0071,55.6489 +Kodak,5x5,ldr-rgb-kodak13.png,36.8526,0.0363,0.0189,20.8436 +Kodak,5x5,ldr-rgb-kodak14.png,38.0531,0.0367,0.0199,19.7179 +Kodak,5x5,ldr-rgb-kodak15.png,41.2632,0.0288,0.0120,32.8526 +Kodak,5x5,ldr-rgb-kodak16.png,43.5545,0.0220,0.0063,62.4557 +Kodak,5x5,ldr-rgb-kodak17.png,42.1276,0.0247,0.0072,54.8421 +Kodak,5x5,ldr-rgb-kodak18.png,38.1414,0.0349,0.0168,23.4311 +Kodak,5x5,ldr-rgb-kodak19.png,41.1956,0.0266,0.0090,43.7286 +Kodak,5x5,ldr-rgb-kodak20.png,42.5313,0.0240,0.0082,48.0108 +Kodak,5x5,ldr-rgb-kodak21.png,40.4616,0.0271,0.0109,36.0354 +Kodak,5x5,ldr-rgb-kodak22.png,39.8231,0.0309,0.0134,29.4034 +Kodak,5x5,ldr-rgb-kodak23.png,42.5879,0.0255,0.0088,44.5917 +Kodak,5x5,ldr-rgb-kodak24.png,37.9173,0.0331,0.0157,25.0519 +Kodak,6x6,ldr-rgb-kodak01.png,35.7615,0.0336,0.0176,22.3315 +Kodak,6x6,ldr-rgb-kodak02.png,38.1999,0.0289,0.0125,31.5179 +Kodak,6x6,ldr-rgb-kodak03.png,40.6124,0.0230,0.0079,49.6857 +Kodak,6x6,ldr-rgb-kodak04.png,38.5770,0.0283,0.0113,34.8072 +Kodak,6x6,ldr-rgb-kodak05.png,34.3732,0.0421,0.0254,15.4913 +Kodak,6x6,ldr-rgb-kodak06.png,37.3128,0.0276,0.0120,32.6568 +Kodak,6x6,ldr-rgb-kodak07.png,38.8989,0.0277,0.0111,35.5591 +Kodak,6x6,ldr-rgb-kodak08.png,34.4575,0.0431,0.0252,15.6138 +Kodak,6x6,ldr-rgb-kodak09.png,39.9869,0.0249,0.0083,47.2786 +Kodak,6x6,ldr-rgb-kodak10.png,39.7423,0.0252,0.0082,48.0822 +Kodak,6x6,ldr-rgb-kodak11.png,37.1667,0.0291,0.0134,29.4433 +Kodak,6x6,ldr-rgb-kodak12.png,40.7648,0.0222,0.0071,55.2889 +Kodak,6x6,ldr-rgb-kodak13.png,32.8162,0.0426,0.0259,15.1686 +Kodak,6x6,ldr-rgb-kodak14.png,35.3137,0.0382,0.0220,17.8660 +Kodak,6x6,ldr-rgb-kodak15.png,38.5886,0.0281,0.0118,33.3630 +Kodak,6x6,ldr-rgb-kodak16.png,40.5218,0.0221,0.0070,56.5050 +Kodak,6x6,ldr-rgb-kodak17.png,38.9577,0.0252,0.0083,47.1650 +Kodak,6x6,ldr-rgb-kodak18.png,35.1265,0.0356,0.0181,21.7352 +Kodak,6x6,ldr-rgb-kodak19.png,37.9929,0.0287,0.0115,34.0800 +Kodak,6x6,ldr-rgb-kodak20.png,39.2444,0.0244,0.0093,42.1861 +Kodak,6x6,ldr-rgb-kodak21.png,36.9206,0.0291,0.0135,29.2159 +Kodak,6x6,ldr-rgb-kodak22.png,37.0036,0.0312,0.0141,27.8564 +Kodak,6x6,ldr-rgb-kodak23.png,40.0996,0.0246,0.0084,46.6277 +Kodak,6x6,ldr-rgb-kodak24.png,34.8065,0.0334,0.0165,23.8616 +Kodak,8x8,ldr-rgb-kodak01.png,31.3431,0.0413,0.0250,15.7550 +Kodak,8x8,ldr-rgb-kodak02.png,34.9568,0.0287,0.0118,33.2279 +Kodak,8x8,ldr-rgb-kodak03.png,36.6268,0.0244,0.0089,44.0533 +Kodak,8x8,ldr-rgb-kodak04.png,35.2057,0.0293,0.0117,33.7322 +Kodak,8x8,ldr-rgb-kodak05.png,30.2614,0.0479,0.0307,12.8108 +Kodak,8x8,ldr-rgb-kodak06.png,32.9533,0.0333,0.0174,22.5377 +Kodak,8x8,ldr-rgb-kodak07.png,35.0042,0.0299,0.0133,29.6364 +Kodak,8x8,ldr-rgb-kodak08.png,29.9748,0.0496,0.0314,12.5096 +Kodak,8x8,ldr-rgb-kodak09.png,36.1799,0.0264,0.0097,40.4669 +Kodak,8x8,ldr-rgb-kodak10.png,35.8943,0.0264,0.0092,42.5233 +Kodak,8x8,ldr-rgb-kodak11.png,33.0179,0.0324,0.0164,23.9198 +Kodak,8x8,ldr-rgb-kodak12.png,36.7460,0.0242,0.0086,45.8729 +Kodak,8x8,ldr-rgb-kodak13.png,28.2226,0.0540,0.0369,10.6612 +Kodak,8x8,ldr-rgb-kodak14.png,31.5109,0.0413,0.0248,15.8287 +Kodak,8x8,ldr-rgb-kodak15.png,34.9611,0.0290,0.0121,32.4921 +Kodak,8x8,ldr-rgb-kodak16.png,36.0680,0.0259,0.0106,36.9949 +Kodak,8x8,ldr-rgb-kodak17.png,34.9238,0.0277,0.0105,37.3425 +Kodak,8x8,ldr-rgb-kodak18.png,31.2485,0.0394,0.0217,18.1206 +Kodak,8x8,ldr-rgb-kodak19.png,34.2422,0.0316,0.0144,27.3392 +Kodak,8x8,ldr-rgb-kodak20.png,35.2601,0.0257,0.0105,37.4672 +Kodak,8x8,ldr-rgb-kodak21.png,32.7603,0.0334,0.0173,22.6781 +Kodak,8x8,ldr-rgb-kodak22.png,33.4648,0.0329,0.0155,25.3262 +Kodak,8x8,ldr-rgb-kodak23.png,36.5647,0.0247,0.0084,46.7440 +Kodak,8x8,ldr-rgb-kodak24.png,30.8292,0.0372,0.0199,19.7856 +Kodak,12x12,ldr-rgb-kodak01.png,27.1130,0.0387,0.0209,18.8305 +Kodak,12x12,ldr-rgb-kodak02.png,31.1202,0.0251,0.0067,58.8898 +Kodak,12x12,ldr-rgb-kodak03.png,32.7096,0.0236,0.0060,65.3201 +Kodak,12x12,ldr-rgb-kodak04.png,31.5842,0.0247,0.0057,68.9119 +Kodak,12x12,ldr-rgb-kodak05.png,25.8256,0.0427,0.0240,16.3574 +Kodak,12x12,ldr-rgb-kodak06.png,28.6395,0.0323,0.0148,26.6264 +Kodak,12x12,ldr-rgb-kodak07.png,30.8700,0.0265,0.0079,49.7607 +Kodak,12x12,ldr-rgb-kodak08.png,25.4195,0.0471,0.0274,14.3531 +Kodak,12x12,ldr-rgb-kodak09.png,31.8404,0.0252,0.0067,58.3853 +Kodak,12x12,ldr-rgb-kodak10.png,31.5462,0.0255,0.0065,60.9170 +Kodak,12x12,ldr-rgb-kodak11.png,28.9427,0.0291,0.0111,35.4376 +Kodak,12x12,ldr-rgb-kodak12.png,32.2913,0.0226,0.0057,69.4721 +Kodak,12x12,ldr-rgb-kodak13.png,24.3223,0.0486,0.0300,13.1090 +Kodak,12x12,ldr-rgb-kodak14.png,27.5500,0.0339,0.0157,24.9836 +Kodak,12x12,ldr-rgb-kodak15.png,31.2676,0.0272,0.0084,46.5395 +Kodak,12x12,ldr-rgb-kodak16.png,31.4918,0.0244,0.0072,54.6441 +Kodak,12x12,ldr-rgb-kodak17.png,30.9085,0.0257,0.0071,55.4917 +Kodak,12x12,ldr-rgb-kodak18.png,27.4273,0.0344,0.0148,26.5561 +Kodak,12x12,ldr-rgb-kodak19.png,30.1952,0.0300,0.0108,36.3115 +Kodak,12x12,ldr-rgb-kodak20.png,31.0607,0.0250,0.0079,49.5112 +Kodak,12x12,ldr-rgb-kodak21.png,28.7210,0.0323,0.0144,27.3465 +Kodak,12x12,ldr-rgb-kodak22.png,29.8449,0.0276,0.0087,45.4056 +Kodak,12x12,ldr-rgb-kodak23.png,32.5414,0.0239,0.0059,66.6694 +Kodak,12x12,ldr-rgb-kodak24.png,26.7782,0.0344,0.0153,25.6703 diff --git a/Test/Images/Kodak/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/Kodak/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..add8e67 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,44.6051,0.0257,0.0100,39.4090 +Kodak,4x4,ldr-rgb-kodak02.png,43.9476,0.0294,0.0134,29.3929 +Kodak,4x4,ldr-rgb-kodak03.png,46.2731,0.0229,0.0080,48.9629 +Kodak,4x4,ldr-rgb-kodak04.png,44.3450,0.0287,0.0121,32.5974 +Kodak,4x4,ldr-rgb-kodak05.png,41.1549,0.0326,0.0164,23.9632 +Kodak,4x4,ldr-rgb-kodak06.png,44.5686,0.0253,0.0100,39.3648 +Kodak,4x4,ldr-rgb-kodak07.png,44.7650,0.0266,0.0103,38.1545 +Kodak,4x4,ldr-rgb-kodak08.png,41.6103,0.0339,0.0168,23.3985 +Kodak,4x4,ldr-rgb-kodak09.png,46.0788,0.0242,0.0079,49.9702 +Kodak,4x4,ldr-rgb-kodak10.png,45.8575,0.0245,0.0080,49.2627 +Kodak,4x4,ldr-rgb-kodak11.png,43.9663,0.0266,0.0114,34.5230 +Kodak,4x4,ldr-rgb-kodak12.png,46.6837,0.0222,0.0075,52.5345 +Kodak,4x4,ldr-rgb-kodak13.png,41.2562,0.0320,0.0156,25.1866 +Kodak,4x4,ldr-rgb-kodak14.png,41.3164,0.0290,0.0134,29.4480 +Kodak,4x4,ldr-rgb-kodak15.png,44.3578,0.0287,0.0124,31.6728 +Kodak,4x4,ldr-rgb-kodak16.png,47.2324,0.0217,0.0071,55.2963 +Kodak,4x4,ldr-rgb-kodak17.png,45.7128,0.0241,0.0074,52.8510 +Kodak,4x4,ldr-rgb-kodak18.png,41.3877,0.0336,0.0165,23.8675 +Kodak,4x4,ldr-rgb-kodak19.png,44.6609,0.0264,0.0097,40.7227 +Kodak,4x4,ldr-rgb-kodak20.png,46.0012,0.0231,0.0082,47.8367 +Kodak,4x4,ldr-rgb-kodak21.png,44.3779,0.0253,0.0100,39.2786 +Kodak,4x4,ldr-rgb-kodak22.png,42.9051,0.0307,0.0141,27.8918 +Kodak,4x4,ldr-rgb-kodak23.png,45.4275,0.0253,0.0096,40.7599 +Kodak,4x4,ldr-rgb-kodak24.png,41.4746,0.0301,0.0134,29.2854 +Kodak,5x5,ldr-rgb-kodak01.png,39.4243,0.0259,0.0106,37.1591 +Kodak,5x5,ldr-rgb-kodak02.png,40.4498,0.0258,0.0098,40.3224 +Kodak,5x5,ldr-rgb-kodak03.png,42.7990,0.0214,0.0066,59.5511 +Kodak,5x5,ldr-rgb-kodak04.png,40.9468,0.0255,0.0090,43.8169 +Kodak,5x5,ldr-rgb-kodak05.png,37.1407,0.0316,0.0154,25.5720 +Kodak,5x5,ldr-rgb-kodak06.png,40.4855,0.0238,0.0087,45.3332 +Kodak,5x5,ldr-rgb-kodak07.png,41.2422,0.0245,0.0084,46.8449 +Kodak,5x5,ldr-rgb-kodak08.png,37.4788,0.0332,0.0158,24.9281 +Kodak,5x5,ldr-rgb-kodak09.png,42.6511,0.0235,0.0066,59.7214 +Kodak,5x5,ldr-rgb-kodak10.png,42.4955,0.0233,0.0067,58.7325 +Kodak,5x5,ldr-rgb-kodak11.png,40.1431,0.0243,0.0092,42.9642 +Kodak,5x5,ldr-rgb-kodak12.png,43.3005,0.0208,0.0061,64.4195 +Kodak,5x5,ldr-rgb-kodak13.png,36.7632,0.0317,0.0149,26.3672 +Kodak,5x5,ldr-rgb-kodak14.png,37.6159,0.0284,0.0127,30.8482 +Kodak,5x5,ldr-rgb-kodak15.png,40.9893,0.0249,0.0089,44.0180 +Kodak,5x5,ldr-rgb-kodak16.png,43.4719,0.0206,0.0058,68.1234 +Kodak,5x5,ldr-rgb-kodak17.png,41.9982,0.0229,0.0063,62.6526 +Kodak,5x5,ldr-rgb-kodak18.png,37.9906,0.0297,0.0124,31.7338 +Kodak,5x5,ldr-rgb-kodak19.png,40.9548,0.0246,0.0078,50.6065 +Kodak,5x5,ldr-rgb-kodak20.png,42.2419,0.0216,0.0067,58.3832 +Kodak,5x5,ldr-rgb-kodak21.png,40.2762,0.0242,0.0090,43.7251 +Kodak,5x5,ldr-rgb-kodak22.png,39.5485,0.0267,0.0101,38.9015 +Kodak,5x5,ldr-rgb-kodak23.png,42.2922,0.0229,0.0073,53.7396 +Kodak,5x5,ldr-rgb-kodak24.png,37.7182,0.0281,0.0114,34.5136 +Kodak,6x6,ldr-rgb-kodak01.png,35.6736,0.0285,0.0134,29.3882 +Kodak,6x6,ldr-rgb-kodak02.png,38.1064,0.0249,0.0091,43.3915 +Kodak,6x6,ldr-rgb-kodak03.png,40.4479,0.0205,0.0061,64.4522 +Kodak,6x6,ldr-rgb-kodak04.png,38.3808,0.0247,0.0085,46.1682 +Kodak,6x6,ldr-rgb-kodak05.png,34.1732,0.0330,0.0169,23.2921 +Kodak,6x6,ldr-rgb-kodak06.png,37.2543,0.0244,0.0095,41.4389 +Kodak,6x6,ldr-rgb-kodak07.png,38.7125,0.0241,0.0084,47.0185 +Kodak,6x6,ldr-rgb-kodak08.png,34.2641,0.0347,0.0172,22.7963 +Kodak,6x6,ldr-rgb-kodak09.png,39.8130,0.0224,0.0065,60.4017 +Kodak,6x6,ldr-rgb-kodak10.png,39.6157,0.0227,0.0065,60.3376 +Kodak,6x6,ldr-rgb-kodak11.png,37.0550,0.0246,0.0098,40.0337 +Kodak,6x6,ldr-rgb-kodak12.png,40.6384,0.0202,0.0059,66.4224 +Kodak,6x6,ldr-rgb-kodak13.png,32.7544,0.0350,0.0191,20.6380 +Kodak,6x6,ldr-rgb-kodak14.png,35.0224,0.0288,0.0136,28.9961 +Kodak,6x6,ldr-rgb-kodak15.png,38.4672,0.0245,0.0087,45.0570 +Kodak,6x6,ldr-rgb-kodak16.png,40.4858,0.0203,0.0060,65.1447 +Kodak,6x6,ldr-rgb-kodak17.png,38.8772,0.0233,0.0069,56.8321 +Kodak,6x6,ldr-rgb-kodak18.png,35.0337,0.0299,0.0132,29.7712 +Kodak,6x6,ldr-rgb-kodak19.png,37.8697,0.0254,0.0092,42.8994 +Kodak,6x6,ldr-rgb-kodak20.png,39.1009,0.0213,0.0072,54.8513 +Kodak,6x6,ldr-rgb-kodak21.png,36.8444,0.0251,0.0102,38.3631 +Kodak,6x6,ldr-rgb-kodak22.png,36.8981,0.0267,0.0104,37.8420 +Kodak,6x6,ldr-rgb-kodak23.png,39.9470,0.0219,0.0066,59.2005 +Kodak,6x6,ldr-rgb-kodak24.png,34.7290,0.0284,0.0121,32.5994 +Kodak,8x8,ldr-rgb-kodak01.png,31.2060,0.0345,0.0186,21.1258 +Kodak,8x8,ldr-rgb-kodak02.png,34.8063,0.0261,0.0094,41.7959 +Kodak,8x8,ldr-rgb-kodak03.png,36.4991,0.0226,0.0072,54.8640 +Kodak,8x8,ldr-rgb-kodak04.png,35.0979,0.0261,0.0091,43.4441 +Kodak,8x8,ldr-rgb-kodak05.png,30.0700,0.0396,0.0227,17.2867 +Kodak,8x8,ldr-rgb-kodak06.png,32.8235,0.0292,0.0134,29.2969 +Kodak,8x8,ldr-rgb-kodak07.png,34.8554,0.0270,0.0101,39.0064 +Kodak,8x8,ldr-rgb-kodak08.png,29.7239,0.0414,0.0237,16.5697 +Kodak,8x8,ldr-rgb-kodak09.png,35.9451,0.0246,0.0079,49.7862 +Kodak,8x8,ldr-rgb-kodak10.png,35.7446,0.0245,0.0075,52.3527 +Kodak,8x8,ldr-rgb-kodak11.png,32.8923,0.0284,0.0125,31.5076 +Kodak,8x8,ldr-rgb-kodak12.png,36.5389,0.0222,0.0070,56.4412 +Kodak,8x8,ldr-rgb-kodak13.png,28.1470,0.0439,0.0271,14.5328 +Kodak,8x8,ldr-rgb-kodak14.png,31.3282,0.0340,0.0178,22.0856 +Kodak,8x8,ldr-rgb-kodak15.png,34.7865,0.0257,0.0093,42.4500 +Kodak,8x8,ldr-rgb-kodak16.png,35.9827,0.0235,0.0083,47.2610 +Kodak,8x8,ldr-rgb-kodak17.png,34.7536,0.0256,0.0084,46.5566 +Kodak,8x8,ldr-rgb-kodak18.png,31.1816,0.0338,0.0161,24.4720 +Kodak,8x8,ldr-rgb-kodak19.png,33.9260,0.0285,0.0112,35.2408 +Kodak,8x8,ldr-rgb-kodak20.png,35.0947,0.0236,0.0083,47.2895 +Kodak,8x8,ldr-rgb-kodak21.png,32.6566,0.0291,0.0131,30.1269 +Kodak,8x8,ldr-rgb-kodak22.png,33.3499,0.0289,0.0117,33.6833 +Kodak,8x8,ldr-rgb-kodak23.png,36.4367,0.0231,0.0067,58.4101 +Kodak,8x8,ldr-rgb-kodak24.png,30.7581,0.0321,0.0150,26.1519 +Kodak,12x12,ldr-rgb-kodak01.png,26.9975,0.0325,0.0153,25.7593 +Kodak,12x12,ldr-rgb-kodak02.png,31.0470,0.0234,0.0055,72.1496 +Kodak,12x12,ldr-rgb-kodak03.png,32.6477,0.0213,0.0049,80.8266 +Kodak,12x12,ldr-rgb-kodak04.png,31.4913,0.0231,0.0047,84.0220 +Kodak,12x12,ldr-rgb-kodak05.png,25.7103,0.0358,0.0174,22.5896 +Kodak,12x12,ldr-rgb-kodak06.png,28.4887,0.0280,0.0110,35.6560 +Kodak,12x12,ldr-rgb-kodak07.png,30.8142,0.0246,0.0064,61.8955 +Kodak,12x12,ldr-rgb-kodak08.png,25.2212,0.0393,0.0202,19.4565 +Kodak,12x12,ldr-rgb-kodak09.png,31.6462,0.0232,0.0055,71.4278 +Kodak,12x12,ldr-rgb-kodak10.png,31.4588,0.0239,0.0053,73.7894 +Kodak,12x12,ldr-rgb-kodak11.png,28.8739,0.0254,0.0084,46.6066 +Kodak,12x12,ldr-rgb-kodak12.png,32.1905,0.0214,0.0047,83.1326 +Kodak,12x12,ldr-rgb-kodak13.png,24.2484,0.0398,0.0216,18.1768 +Kodak,12x12,ldr-rgb-kodak14.png,27.4629,0.0291,0.0117,33.6895 +Kodak,12x12,ldr-rgb-kodak15.png,31.1696,0.0244,0.0065,60.9463 +Kodak,12x12,ldr-rgb-kodak16.png,31.3703,0.0223,0.0058,67.8543 +Kodak,12x12,ldr-rgb-kodak17.png,30.8499,0.0240,0.0057,68.3861 +Kodak,12x12,ldr-rgb-kodak18.png,27.3767,0.0300,0.0110,35.8973 +Kodak,12x12,ldr-rgb-kodak19.png,29.8781,0.0268,0.0085,46.4242 +Kodak,12x12,ldr-rgb-kodak20.png,30.9470,0.0228,0.0063,62.2765 +Kodak,12x12,ldr-rgb-kodak21.png,28.6223,0.0279,0.0105,37.3070 +Kodak,12x12,ldr-rgb-kodak22.png,29.7651,0.0252,0.0068,57.6909 +Kodak,12x12,ldr-rgb-kodak23.png,32.5037,0.0223,0.0049,80.3462 +Kodak,12x12,ldr-rgb-kodak24.png,26.7066,0.0300,0.0115,34.1484 diff --git a/Test/Images/Kodak/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/Kodak/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..c727ff5 --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.3568,0.0833,0.0662,5.9368 +Kodak,4x4,ldr-rgb-kodak02.png,45.5340,0.1203,0.1028,3.8242 +Kodak,4x4,ldr-rgb-kodak03.png,47.7539,0.0634,0.0470,8.3611 +Kodak,4x4,ldr-rgb-kodak04.png,45.5864,0.0972,0.0792,4.9672 +Kodak,4x4,ldr-rgb-kodak05.png,42.2225,0.1078,0.0900,4.3702 +Kodak,4x4,ldr-rgb-kodak06.png,45.2411,0.0787,0.0621,6.3292 +Kodak,4x4,ldr-rgb-kodak07.png,46.0876,0.0786,0.0610,6.4454 +Kodak,4x4,ldr-rgb-kodak08.png,42.5744,0.1142,0.0956,4.1133 +Kodak,4x4,ldr-rgb-kodak09.png,47.2528,0.0922,0.0746,5.2683 +Kodak,4x4,ldr-rgb-kodak10.png,46.9460,0.0941,0.0762,5.1574 +Kodak,4x4,ldr-rgb-kodak11.png,44.9646,0.0947,0.0780,5.0404 +Kodak,4x4,ldr-rgb-kodak12.png,48.0493,0.0711,0.0548,7.1759 +Kodak,4x4,ldr-rgb-kodak13.png,41.6852,0.0898,0.0720,5.4590 +Kodak,4x4,ldr-rgb-kodak14.png,42.7706,0.0991,0.0822,4.7818 +Kodak,4x4,ldr-rgb-kodak15.png,45.6220,0.0845,0.0671,5.8575 +Kodak,4x4,ldr-rgb-kodak16.png,47.9704,0.0701,0.0542,7.2529 +Kodak,4x4,ldr-rgb-kodak17.png,46.4165,0.0809,0.0631,6.2355 +Kodak,4x4,ldr-rgb-kodak18.png,42.0984,0.1230,0.1044,3.7673 +Kodak,4x4,ldr-rgb-kodak19.png,45.4350,0.0974,0.0789,4.9845 +Kodak,4x4,ldr-rgb-kodak20.png,46.9806,0.0626,0.0466,8.4394 +Kodak,4x4,ldr-rgb-kodak21.png,45.2504,0.0974,0.0805,4.8821 +Kodak,4x4,ldr-rgb-kodak22.png,43.8883,0.1239,0.1059,3.7135 +Kodak,4x4,ldr-rgb-kodak23.png,46.9903,0.0960,0.0789,4.9819 +Kodak,4x4,ldr-rgb-kodak24.png,42.4274,0.0956,0.0776,5.0646 +Kodak,5x5,ldr-rgb-kodak01.png,40.1394,0.0843,0.0667,5.8945 +Kodak,5x5,ldr-rgb-kodak02.png,41.8034,0.0964,0.0783,5.0226 +Kodak,5x5,ldr-rgb-kodak03.png,44.1200,0.0494,0.0324,12.1386 +Kodak,5x5,ldr-rgb-kodak04.png,42.1317,0.0759,0.0573,6.8633 +Kodak,5x5,ldr-rgb-kodak05.png,38.0317,0.1002,0.0820,4.7975 +Kodak,5x5,ldr-rgb-kodak06.png,41.0138,0.0687,0.0513,7.6689 +Kodak,5x5,ldr-rgb-kodak07.png,42.5100,0.0631,0.0447,8.7870 +Kodak,5x5,ldr-rgb-kodak08.png,38.3863,0.1047,0.0852,4.6163 +Kodak,5x5,ldr-rgb-kodak09.png,43.8383,0.0558,0.0376,10.4459 +Kodak,5x5,ldr-rgb-kodak10.png,43.4630,0.0612,0.0426,9.2391 +Kodak,5x5,ldr-rgb-kodak11.png,40.9008,0.0793,0.0617,6.3680 +Kodak,5x5,ldr-rgb-kodak12.png,44.4587,0.0495,0.0326,12.0767 +Kodak,5x5,ldr-rgb-kodak13.png,36.9554,0.0853,0.0667,5.8996 +Kodak,5x5,ldr-rgb-kodak14.png,38.7246,0.0902,0.0722,5.4444 +Kodak,5x5,ldr-rgb-kodak15.png,41.9924,0.0719,0.0536,7.3379 +Kodak,5x5,ldr-rgb-kodak16.png,44.1901,0.0519,0.0351,11.1894 +Kodak,5x5,ldr-rgb-kodak17.png,42.5999,0.0544,0.0358,10.9693 +Kodak,5x5,ldr-rgb-kodak18.png,38.4228,0.0954,0.0763,5.1562 +Kodak,5x5,ldr-rgb-kodak19.png,41.7034,0.0675,0.0486,8.0895 +Kodak,5x5,ldr-rgb-kodak20.png,43.1224,0.0503,0.0335,11.7483 +Kodak,5x5,ldr-rgb-kodak21.png,40.8044,0.0689,0.0515,7.6388 +Kodak,5x5,ldr-rgb-kodak22.png,40.3325,0.0933,0.0743,5.2903 +Kodak,5x5,ldr-rgb-kodak23.png,43.6344,0.0658,0.0481,8.1831 +Kodak,5x5,ldr-rgb-kodak24.png,38.2309,0.0796,0.0610,6.4456 +Kodak,6x6,ldr-rgb-kodak01.png,36.2047,0.0830,0.0660,5.9621 +Kodak,6x6,ldr-rgb-kodak02.png,39.0679,0.0765,0.0585,6.7183 +Kodak,6x6,ldr-rgb-kodak03.png,41.3734,0.0417,0.0255,15.4111 +Kodak,6x6,ldr-rgb-kodak04.png,39.4288,0.0653,0.0470,8.3699 +Kodak,6x6,ldr-rgb-kodak05.png,34.8106,0.0942,0.0762,5.1617 +Kodak,6x6,ldr-rgb-kodak06.png,37.6521,0.0607,0.0438,8.9835 +Kodak,6x6,ldr-rgb-kodak07.png,39.8104,0.0547,0.0368,10.6936 +Kodak,6x6,ldr-rgb-kodak08.png,34.9941,0.0992,0.0805,4.8876 +Kodak,6x6,ldr-rgb-kodak09.png,40.9014,0.0446,0.0269,14.6014 +Kodak,6x6,ldr-rgb-kodak10.png,40.5320,0.0468,0.0287,13.6843 +Kodak,6x6,ldr-rgb-kodak11.png,37.6118,0.0672,0.0504,7.8059 +Kodak,6x6,ldr-rgb-kodak12.png,41.5184,0.0404,0.0240,16.3548 +Kodak,6x6,ldr-rgb-kodak13.png,32.9144,0.0891,0.0711,5.5293 +Kodak,6x6,ldr-rgb-kodak14.png,35.8617,0.0838,0.0663,5.9330 +Kodak,6x6,ldr-rgb-kodak15.png,39.2395,0.0644,0.0467,8.4231 +Kodak,6x6,ldr-rgb-kodak16.png,41.0630,0.0436,0.0274,14.3619 +Kodak,6x6,ldr-rgb-kodak17.png,39.5139,0.0464,0.0282,13.9468 +Kodak,6x6,ldr-rgb-kodak18.png,35.3772,0.0837,0.0650,6.0481 +Kodak,6x6,ldr-rgb-kodak19.png,38.5375,0.0593,0.0411,9.5584 +Kodak,6x6,ldr-rgb-kodak20.png,39.8196,0.0455,0.0295,13.3281 +Kodak,6x6,ldr-rgb-kodak21.png,37.2159,0.0598,0.0430,9.1395 +Kodak,6x6,ldr-rgb-kodak22.png,37.4905,0.0775,0.0591,6.6496 +Kodak,6x6,ldr-rgb-kodak23.png,41.0187,0.0495,0.0322,12.1928 +Kodak,6x6,ldr-rgb-kodak24.png,35.0748,0.0697,0.0515,7.6326 +Kodak,8x8,ldr-rgb-kodak01.png,31.8056,0.1093,0.0916,4.2936 +Kodak,8x8,ldr-rgb-kodak02.png,35.8077,0.0761,0.0576,6.8268 +Kodak,8x8,ldr-rgb-kodak03.png,37.7749,0.0494,0.0325,12.0859 +Kodak,8x8,ldr-rgb-kodak04.png,36.1111,0.0702,0.0513,7.6628 +Kodak,8x8,ldr-rgb-kodak05.png,30.7540,0.1191,0.1006,3.9072 +Kodak,8x8,ldr-rgb-kodak06.png,33.4516,0.0751,0.0575,6.8353 +Kodak,8x8,ldr-rgb-kodak07.png,36.1675,0.0638,0.0453,8.6866 +Kodak,8x8,ldr-rgb-kodak08.png,30.5430,0.1216,0.1021,3.8527 +Kodak,8x8,ldr-rgb-kodak09.png,37.2689,0.0508,0.0324,12.1355 +Kodak,8x8,ldr-rgb-kodak10.png,36.9309,0.0517,0.0328,11.9927 +Kodak,8x8,ldr-rgb-kodak11.png,33.6775,0.0775,0.0599,6.5635 +Kodak,8x8,ldr-rgb-kodak12.png,37.8485,0.0480,0.0311,12.6420 +Kodak,8x8,ldr-rgb-kodak13.png,28.3991,0.1176,0.0988,3.9789 +Kodak,8x8,ldr-rgb-kodak14.png,32.1559,0.1022,0.0841,4.6761 +Kodak,8x8,ldr-rgb-kodak15.png,35.8598,0.0650,0.0466,8.4338 +Kodak,8x8,ldr-rgb-kodak16.png,37.0456,0.0532,0.0361,10.8861 +Kodak,8x8,ldr-rgb-kodak17.png,35.6829,0.0544,0.0358,10.9947 +Kodak,8x8,ldr-rgb-kodak18.png,31.5621,0.0954,0.0755,5.2109 +Kodak,8x8,ldr-rgb-kodak19.png,34.7741,0.0688,0.0496,7.9321 +Kodak,8x8,ldr-rgb-kodak20.png,35.9272,0.0548,0.0378,10.4088 +Kodak,8x8,ldr-rgb-kodak21.png,33.1188,0.0730,0.0555,7.0879 +Kodak,8x8,ldr-rgb-kodak22.png,34.0552,0.0825,0.0638,6.1645 +Kodak,8x8,ldr-rgb-kodak23.png,37.6964,0.0510,0.0330,11.9305 +Kodak,8x8,ldr-rgb-kodak24.png,31.1333,0.0815,0.0627,6.2719 +Kodak,12x12,ldr-rgb-kodak01.png,27.7567,0.1223,0.1016,3.8686 +Kodak,12x12,ldr-rgb-kodak02.png,32.4652,0.0614,0.0403,9.7500 +Kodak,12x12,ldr-rgb-kodak03.png,33.8457,0.0466,0.0269,14.6064 +Kodak,12x12,ldr-rgb-kodak04.png,32.4611,0.0545,0.0329,11.9348 +Kodak,12x12,ldr-rgb-kodak05.png,26.4003,0.1338,0.1120,3.5104 +Kodak,12x12,ldr-rgb-kodak06.png,29.3790,0.0803,0.0602,6.5336 +Kodak,12x12,ldr-rgb-kodak07.png,32.0521,0.0651,0.0438,8.9776 +Kodak,12x12,ldr-rgb-kodak08.png,26.0645,0.1385,0.1159,3.3913 +Kodak,12x12,ldr-rgb-kodak09.png,33.1056,0.0498,0.0287,13.7157 +Kodak,12x12,ldr-rgb-kodak10.png,32.4919,0.0499,0.0283,13.8916 +Kodak,12x12,ldr-rgb-kodak11.png,29.7599,0.0771,0.0567,6.9327 +Kodak,12x12,ldr-rgb-kodak12.png,33.8930,0.0459,0.0262,15.0341 +Kodak,12x12,ldr-rgb-kodak13.png,24.5317,0.1379,0.1159,3.3931 +Kodak,12x12,ldr-rgb-kodak14.png,28.4341,0.1068,0.0860,4.5739 +Kodak,12x12,ldr-rgb-kodak15.png,32.2518,0.0614,0.0403,9.7507 +Kodak,12x12,ldr-rgb-kodak16.png,32.9941,0.0516,0.0318,12.3732 +Kodak,12x12,ldr-rgb-kodak17.png,31.7966,0.0539,0.0324,12.1345 +Kodak,12x12,ldr-rgb-kodak18.png,27.7851,0.0956,0.0732,5.3695 +Kodak,12x12,ldr-rgb-kodak19.png,30.8983,0.0680,0.0463,8.4900 +Kodak,12x12,ldr-rgb-kodak20.png,31.8747,0.0539,0.0342,11.4962 +Kodak,12x12,ldr-rgb-kodak21.png,29.1883,0.0834,0.0628,6.2603 +Kodak,12x12,ldr-rgb-kodak22.png,30.5162,0.0739,0.0520,7.5569 +Kodak,12x12,ldr-rgb-kodak23.png,33.5863,0.0440,0.0233,16.8929 +Kodak,12x12,ldr-rgb-kodak24.png,27.1080,0.0850,0.0634,6.1974 diff --git a/Test/Images/Kodak/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/Kodak/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..edc176e --- /dev/null +++ b/Test/Images/Kodak/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,121 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Kodak,4x4,ldr-rgb-kodak01.png,45.5518,0.1780,0.1612,2.4386 +Kodak,4x4,ldr-rgb-kodak02.png,45.8013,0.2555,0.2380,1.6524 +Kodak,4x4,ldr-rgb-kodak03.png,48.1838,0.2035,0.1872,2.1008 +Kodak,4x4,ldr-rgb-kodak04.png,45.7743,0.2323,0.2143,1.8351 +Kodak,4x4,ldr-rgb-kodak05.png,42.4897,0.2247,0.2070,1.8995 +Kodak,4x4,ldr-rgb-kodak06.png,45.4437,0.1857,0.1693,2.3225 +Kodak,4x4,ldr-rgb-kodak07.png,46.4733,0.2256,0.2081,1.8894 +Kodak,4x4,ldr-rgb-kodak08.png,42.8702,0.2349,0.2161,1.8195 +Kodak,4x4,ldr-rgb-kodak09.png,47.5182,0.2395,0.2218,1.7725 +Kodak,4x4,ldr-rgb-kodak10.png,47.1848,0.2370,0.2191,1.7949 +Kodak,4x4,ldr-rgb-kodak11.png,45.2213,0.2136,0.1969,1.9969 +Kodak,4x4,ldr-rgb-kodak12.png,48.3699,0.2060,0.1899,2.0705 +Kodak,4x4,ldr-rgb-kodak13.png,41.7923,0.1845,0.1666,2.3600 +Kodak,4x4,ldr-rgb-kodak14.png,43.0274,0.2090,0.1919,2.0490 +Kodak,4x4,ldr-rgb-kodak15.png,45.9168,0.2203,0.2027,1.9399 +Kodak,4x4,ldr-rgb-kodak16.png,48.1944,0.2022,0.1860,2.1140 +Kodak,4x4,ldr-rgb-kodak17.png,46.5896,0.2171,0.1990,1.9764 +Kodak,4x4,ldr-rgb-kodak18.png,42.2629,0.2519,0.2329,1.6885 +Kodak,4x4,ldr-rgb-kodak19.png,45.6456,0.2287,0.2102,1.8703 +Kodak,4x4,ldr-rgb-kodak20.png,47.2444,0.1443,0.1282,3.0663 +Kodak,4x4,ldr-rgb-kodak21.png,45.4013,0.2266,0.2100,1.8728 +Kodak,4x4,ldr-rgb-kodak22.png,44.0722,0.2583,0.2403,1.6362 +Kodak,4x4,ldr-rgb-kodak23.png,47.3258,0.2517,0.2346,1.6762 +Kodak,4x4,ldr-rgb-kodak24.png,42.6529,0.2228,0.2049,1.9194 +Kodak,5x5,ldr-rgb-kodak01.png,40.2511,0.2050,0.1870,2.1033 +Kodak,5x5,ldr-rgb-kodak02.png,42.0812,0.2711,0.2525,1.5574 +Kodak,5x5,ldr-rgb-kodak03.png,44.4289,0.2035,0.1867,2.1057 +Kodak,5x5,ldr-rgb-kodak04.png,42.3228,0.2250,0.2062,1.9072 +Kodak,5x5,ldr-rgb-kodak05.png,38.2254,0.2404,0.2218,1.7732 +Kodak,5x5,ldr-rgb-kodak06.png,41.1286,0.1901,0.1728,2.2758 +Kodak,5x5,ldr-rgb-kodak07.png,42.7863,0.2267,0.2084,1.8870 +Kodak,5x5,ldr-rgb-kodak08.png,38.5611,0.2391,0.2198,1.7890 +Kodak,5x5,ldr-rgb-kodak09.png,44.0635,0.2206,0.2023,1.9439 +Kodak,5x5,ldr-rgb-kodak10.png,43.6474,0.2268,0.2075,1.8951 +Kodak,5x5,ldr-rgb-kodak11.png,41.0580,0.2151,0.1976,1.9898 +Kodak,5x5,ldr-rgb-kodak12.png,44.6632,0.2024,0.1856,2.1185 +Kodak,5x5,ldr-rgb-kodak13.png,37.0002,0.1863,0.1677,2.3447 +Kodak,5x5,ldr-rgb-kodak14.png,38.9421,0.2201,0.2023,1.9434 +Kodak,5x5,ldr-rgb-kodak15.png,42.2162,0.2173,0.1988,1.9775 +Kodak,5x5,ldr-rgb-kodak16.png,44.3346,0.2001,0.1829,2.1496 +Kodak,5x5,ldr-rgb-kodak17.png,42.6982,0.2063,0.1874,2.0979 +Kodak,5x5,ldr-rgb-kodak18.png,38.5129,0.2415,0.2220,1.7712 +Kodak,5x5,ldr-rgb-kodak19.png,41.8400,0.2248,0.2060,1.9084 +Kodak,5x5,ldr-rgb-kodak20.png,43.3551,0.1433,0.1265,3.1081 +Kodak,5x5,ldr-rgb-kodak21.png,40.9121,0.2288,0.2115,1.8590 +Kodak,5x5,ldr-rgb-kodak22.png,40.4818,0.2612,0.2423,1.6228 +Kodak,5x5,ldr-rgb-kodak23.png,43.9659,0.2596,0.2418,1.6265 +Kodak,5x5,ldr-rgb-kodak24.png,38.3539,0.2272,0.2086,1.8854 +Kodak,6x6,ldr-rgb-kodak01.png,36.3209,0.2240,0.2066,1.9029 +Kodak,6x6,ldr-rgb-kodak02.png,39.4327,0.2850,0.2671,1.4720 +Kodak,6x6,ldr-rgb-kodak03.png,41.7843,0.1721,0.1559,2.5224 +Kodak,6x6,ldr-rgb-kodak04.png,39.6966,0.2305,0.2118,1.8565 +Kodak,6x6,ldr-rgb-kodak05.png,35.0128,0.2557,0.2377,1.6543 +Kodak,6x6,ldr-rgb-kodak06.png,37.7748,0.1983,0.1813,2.1685 +Kodak,6x6,ldr-rgb-kodak07.png,40.1544,0.2020,0.1841,2.1356 +Kodak,6x6,ldr-rgb-kodak08.png,35.1815,0.2535,0.2345,1.6765 +Kodak,6x6,ldr-rgb-kodak09.png,41.2856,0.2166,0.1989,1.9770 +Kodak,6x6,ldr-rgb-kodak10.png,40.8624,0.2339,0.2158,1.8219 +Kodak,6x6,ldr-rgb-kodak11.png,37.7970,0.2215,0.2047,1.9212 +Kodak,6x6,ldr-rgb-kodak12.png,41.8706,0.1995,0.1832,2.1468 +Kodak,6x6,ldr-rgb-kodak13.png,32.9634,0.2122,0.1940,2.0266 +Kodak,6x6,ldr-rgb-kodak14.png,36.0611,0.2399,0.2227,1.7660 +Kodak,6x6,ldr-rgb-kodak15.png,39.5012,0.2036,0.1857,2.1172 +Kodak,6x6,ldr-rgb-kodak16.png,41.2627,0.1875,0.1712,2.2966 +Kodak,6x6,ldr-rgb-kodak17.png,39.6994,0.2083,0.1900,2.0699 +Kodak,6x6,ldr-rgb-kodak18.png,35.4627,0.2574,0.2387,1.6471 +Kodak,6x6,ldr-rgb-kodak19.png,38.7241,0.2411,0.2226,1.7666 +Kodak,6x6,ldr-rgb-kodak20.png,40.1538,0.1500,0.1337,2.9404 +Kodak,6x6,ldr-rgb-kodak21.png,37.3645,0.2398,0.2225,1.7669 +Kodak,6x6,ldr-rgb-kodak22.png,37.6612,0.2765,0.2581,1.5236 +Kodak,6x6,ldr-rgb-kodak23.png,41.4821,0.2508,0.2334,1.6848 +Kodak,6x6,ldr-rgb-kodak24.png,35.1912,0.2260,0.2075,1.8948 +Kodak,8x8,ldr-rgb-kodak01.png,31.9146,0.2733,0.2541,1.5473 +Kodak,8x8,ldr-rgb-kodak02.png,36.1788,0.2764,0.2568,1.5311 +Kodak,8x8,ldr-rgb-kodak03.png,38.2155,0.1498,0.1316,2.9888 +Kodak,8x8,ldr-rgb-kodak04.png,36.3982,0.2245,0.2043,1.9251 +Kodak,8x8,ldr-rgb-kodak05.png,30.9222,0.2986,0.2783,1.4128 +Kodak,8x8,ldr-rgb-kodak06.png,33.5846,0.2267,0.2080,1.8905 +Kodak,8x8,ldr-rgb-kodak07.png,36.5202,0.1840,0.1639,2.3989 +Kodak,8x8,ldr-rgb-kodak08.png,30.7397,0.3247,0.3035,1.2955 +Kodak,8x8,ldr-rgb-kodak09.png,37.5621,0.1659,0.1461,2.6921 +Kodak,8x8,ldr-rgb-kodak10.png,37.2442,0.1899,0.1699,2.3143 +Kodak,8x8,ldr-rgb-kodak11.png,33.8442,0.2649,0.2458,1.6001 +Kodak,8x8,ldr-rgb-kodak12.png,38.2828,0.1718,0.1534,2.5631 +Kodak,8x8,ldr-rgb-kodak13.png,28.4632,0.2876,0.2674,1.4704 +Kodak,8x8,ldr-rgb-kodak14.png,32.3317,0.2869,0.2677,1.4691 +Kodak,8x8,ldr-rgb-kodak15.png,36.0836,0.2126,0.1929,2.0387 +Kodak,8x8,ldr-rgb-kodak16.png,37.2842,0.1847,0.1660,2.3691 +Kodak,8x8,ldr-rgb-kodak17.png,35.8800,0.1825,0.1624,2.4220 +Kodak,8x8,ldr-rgb-kodak18.png,31.6579,0.2942,0.2735,1.4379 +Kodak,8x8,ldr-rgb-kodak19.png,34.9377,0.2006,0.1801,2.1834 +Kodak,8x8,ldr-rgb-kodak20.png,36.1780,0.1604,0.1422,2.7650 +Kodak,8x8,ldr-rgb-kodak21.png,33.2310,0.2109,0.1921,2.0470 +Kodak,8x8,ldr-rgb-kodak22.png,34.2375,0.2764,0.2556,1.5382 +Kodak,8x8,ldr-rgb-kodak23.png,38.2142,0.1825,0.1631,2.4114 +Kodak,8x8,ldr-rgb-kodak24.png,31.2419,0.2438,0.2237,1.7577 +Kodak,12x12,ldr-rgb-kodak01.png,27.9150,0.3592,0.3362,1.1696 +Kodak,12x12,ldr-rgb-kodak02.png,33.0105,0.2696,0.2460,1.5983 +Kodak,12x12,ldr-rgb-kodak03.png,34.4619,0.1619,0.1396,2.8157 +Kodak,12x12,ldr-rgb-kodak04.png,32.9796,0.2339,0.2096,1.8756 +Kodak,12x12,ldr-rgb-kodak05.png,26.6079,0.3892,0.3655,1.0759 +Kodak,12x12,ldr-rgb-kodak06.png,29.5353,0.2637,0.2406,1.6342 +Kodak,12x12,ldr-rgb-kodak07.png,32.6362,0.2057,0.1819,2.1612 +Kodak,12x12,ldr-rgb-kodak08.png,26.2650,0.3937,0.3680,1.0684 +Kodak,12x12,ldr-rgb-kodak09.png,33.6345,0.1850,0.1610,2.4419 +Kodak,12x12,ldr-rgb-kodak10.png,32.9944,0.1832,0.1594,2.4673 +Kodak,12x12,ldr-rgb-kodak11.png,30.0568,0.2842,0.2606,1.5089 +Kodak,12x12,ldr-rgb-kodak12.png,34.4463,0.1681,0.1460,2.6939 +Kodak,12x12,ldr-rgb-kodak13.png,24.5880,0.4208,0.3965,0.9918 +Kodak,12x12,ldr-rgb-kodak14.png,28.6503,0.3452,0.3218,1.2220 +Kodak,12x12,ldr-rgb-kodak15.png,32.7455,0.2269,0.2032,1.9355 +Kodak,12x12,ldr-rgb-kodak16.png,33.3415,0.1988,0.1761,2.2323 +Kodak,12x12,ldr-rgb-kodak17.png,32.1383,0.1969,0.1726,2.2779 +Kodak,12x12,ldr-rgb-kodak18.png,27.9277,0.3428,0.3178,1.2373 +Kodak,12x12,ldr-rgb-kodak19.png,31.1090,0.2691,0.2446,1.6074 +Kodak,12x12,ldr-rgb-kodak20.png,32.1815,0.2088,0.1865,2.1087 +Kodak,12x12,ldr-rgb-kodak21.png,29.3291,0.2546,0.2317,1.6969 +Kodak,12x12,ldr-rgb-kodak22.png,30.7908,0.3030,0.2788,1.4103 +Kodak,12x12,ldr-rgb-kodak23.png,34.3884,0.1669,0.1438,2.7342 +Kodak,12x12,ldr-rgb-kodak24.png,27.2407,0.3073,0.2831,1.3890 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index e4c781d..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.0285,0.9335,0.4855,19.4397 -KodakMnt,5x5,ldr-rgb-montage.png,40.0752,0.8331,0.3832,24.6246 -KodakMnt,6x6,ldr-rgb-montage.png,36.9706,0.8835,0.4352,21.6869 -KodakMnt,8x8,ldr-rgb-montage.png,32.9355,0.9718,0.5221,18.0745 -KodakMnt,12x12,ldr-rgb-montage.png,28.8476,0.7950,0.3383,27.8987 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index bfe7660..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,43.5838,0.7789,0.3348,28.1869 -KodakMnt,5x5,ldr-rgb-montage.png,39.7683,0.7431,0.2956,31.9224 -KodakMnt,6x6,ldr-rgb-montage.png,36.8150,0.7529,0.3055,30.8934 -KodakMnt,8x8,ldr-rgb-montage.png,32.7960,0.8211,0.3731,25.2920 -KodakMnt,12x12,ldr-rgb-montage.png,28.7205,0.7095,0.2570,36.7156 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index 181aed0..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.6446,2.9943,2.5459,3.7068 -KodakMnt,5x5,ldr-rgb-montage.png,40.6449,2.6102,2.1637,4.3617 -KodakMnt,6x6,ldr-rgb-montage.png,37.4701,2.2729,1.8186,5.1893 -KodakMnt,8x8,ldr-rgb-montage.png,33.5265,2.5586,2.1095,4.4737 -KodakMnt,12x12,ldr-rgb-montage.png,29.5216,2.3645,1.9069,4.9489 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index b2a1c6c..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.8801,7.8539,7.4086,1.2738 -KodakMnt,5x5,ldr-rgb-montage.png,40.8097,9.0340,8.5810,1.0998 -KodakMnt,6x6,ldr-rgb-montage.png,37.6501,9.7971,9.3483,1.0095 -KodakMnt,8x8,ldr-rgb-montage.png,33.6999,8.9916,8.5375,1.1054 -KodakMnt,12x12,ldr-rgb-montage.png,29.7666,9.0339,8.5698,1.1012 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index 3a48b6a..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.0285,1.1007,0.6467,14.5933 -KodakMnt,5x5,ldr-rgb-montage.png,40.0752,0.9750,0.5187,18.1942 -KodakMnt,6x6,ldr-rgb-montage.png,36.9706,1.0866,0.6312,14.9516 -KodakMnt,8x8,ldr-rgb-montage.png,32.9355,1.2433,0.7827,12.0580 -KodakMnt,12x12,ldr-rgb-montage.png,28.8476,0.9715,0.5051,18.6835 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index af21b22..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,43.5838,0.9062,0.4529,20.8360 -KodakMnt,5x5,ldr-rgb-montage.png,39.7683,0.8594,0.4054,23.2783 -KodakMnt,6x6,ldr-rgb-montage.png,36.8150,0.8908,0.4366,21.6174 -KodakMnt,8x8,ldr-rgb-montage.png,32.7960,1.0091,0.5497,17.1667 -KodakMnt,12x12,ldr-rgb-montage.png,28.7205,0.8451,0.3833,24.6179 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index 445840b..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.6446,3.9801,3.5268,2.6759 -KodakMnt,5x5,ldr-rgb-montage.png,40.6449,3.6625,3.2025,2.9468 -KodakMnt,6x6,ldr-rgb-montage.png,37.4701,3.2110,2.7550,3.4255 -KodakMnt,8x8,ldr-rgb-montage.png,33.5265,3.7268,3.2672,2.8884 -KodakMnt,12x12,ldr-rgb-montage.png,29.5216,3.4024,2.9362,3.2141 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index 8615a67..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.8801,10.5664,10.1061,0.9338 -KodakMnt,5x5,ldr-rgb-montage.png,40.8097,12.9904,12.5321,0.7530 -KodakMnt,6x6,ldr-rgb-montage.png,37.6501,14.4621,14.0009,0.6740 -KodakMnt,8x8,ldr-rgb-montage.png,33.6999,13.7376,13.2725,0.7110 -KodakMnt,12x12,ldr-rgb-montage.png,29.7666,13.6335,13.1601,0.7171 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index dbe5cb1..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.0285,1.0270,0.5693,16.5768 -KodakMnt,5x5,ldr-rgb-montage.png,40.0752,0.9151,0.4556,20.7128 -KodakMnt,6x6,ldr-rgb-montage.png,36.9706,1.0055,0.5490,17.1895 -KodakMnt,8x8,ldr-rgb-montage.png,32.9355,1.1473,0.6827,13.8223 -KodakMnt,12x12,ldr-rgb-montage.png,28.8476,0.9152,0.4457,21.1734 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 152b1af..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,43.5838,0.8555,0.3979,23.7169 -KodakMnt,5x5,ldr-rgb-montage.png,39.7683,0.8151,0.3537,26.6832 -KodakMnt,6x6,ldr-rgb-montage.png,36.8150,0.8408,0.3824,24.6811 -KodakMnt,8x8,ldr-rgb-montage.png,32.7960,0.9404,0.4783,19.7320 -KodakMnt,12x12,ldr-rgb-montage.png,28.7205,0.8029,0.3370,27.9999 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 55153c4..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.6446,3.5124,3.0548,3.0893 -KodakMnt,5x5,ldr-rgb-montage.png,40.6449,3.2123,2.7489,3.4331 -KodakMnt,6x6,ldr-rgb-montage.png,37.4701,2.8508,2.3904,3.9480 -KodakMnt,8x8,ldr-rgb-montage.png,33.5265,3.3345,2.8688,3.2896 -KodakMnt,12x12,ldr-rgb-montage.png,29.5216,3.0703,2.5958,3.6356 diff --git a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 2789a56..0000000 --- a/Test/Images/KodakMnt/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,6 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakMnt,4x4,ldr-rgb-montage.png,44.8801,9.3070,8.8486,1.0665 -KodakMnt,5x5,ldr-rgb-montage.png,40.8097,11.3270,10.8648,0.8686 -KodakMnt,6x6,ldr-rgb-montage.png,37.6501,12.6749,12.2157,0.7725 -KodakMnt,8x8,ldr-rgb-montage.png,33.6999,12.1330,11.6650,0.8090 -KodakMnt,12x12,ldr-rgb-montage.png,29.7666,12.1249,11.6488,0.8101 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..a054c14 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1088,0.7492,0.3913,24.1199 +KodakMnt,5x5,ldr-rgb-montage.png,40.1064,0.6363,0.2816,33.5170 +KodakMnt,6x6,ldr-rgb-montage.png,36.9953,0.6636,0.3144,30.0134 +KodakMnt,8x8,ldr-rgb-montage.png,32.9627,0.7208,0.3812,24.7581 +KodakMnt,12x12,ldr-rgb-montage.png,28.8569,0.6145,0.2735,34.5104 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..872a4f8 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.6871,0.6060,0.2524,37.3882 +KodakMnt,5x5,ldr-rgb-montage.png,39.8465,0.5626,0.2124,44.4356 +KodakMnt,6x6,ldr-rgb-montage.png,36.8575,0.5759,0.2269,41.5867 +KodakMnt,8x8,ldr-rgb-montage.png,32.8170,0.6268,0.2860,32.9973 +KodakMnt,12x12,ldr-rgb-montage.png,28.7278,0.5429,0.2030,46.4911 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..f5b6769 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.6971,2.1278,1.7712,5.3281 +KodakMnt,5x5,ldr-rgb-montage.png,40.6736,1.6961,1.3345,7.0716 +KodakMnt,6x6,ldr-rgb-montage.png,37.4854,1.4762,1.1263,8.3787 +KodakMnt,8x8,ldr-rgb-montage.png,33.5323,1.7128,1.3675,6.9010 +KodakMnt,12x12,ldr-rgb-montage.png,29.5339,1.6556,1.3104,7.2019 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..6196704 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9209,5.1230,4.7595,1.9828 +KodakMnt,5x5,ldr-rgb-montage.png,40.8363,5.1785,4.8236,1.9565 +KodakMnt,6x6,ldr-rgb-montage.png,37.6703,5.3110,4.9623,1.9018 +KodakMnt,8x8,ldr-rgb-montage.png,33.7079,5.3417,4.9972,1.8885 +KodakMnt,12x12,ldr-rgb-montage.png,29.7759,6.0849,5.7325,1.6463 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..690cabd --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1088,0.9150,0.5310,17.7737 +KodakMnt,5x5,ldr-rgb-montage.png,40.1064,0.7844,0.4043,23.3446 +KodakMnt,6x6,ldr-rgb-montage.png,36.9953,0.8556,0.4756,19.8411 +KodakMnt,8x8,ldr-rgb-montage.png,32.9627,0.9729,0.5970,15.8080 +KodakMnt,12x12,ldr-rgb-montage.png,28.8569,0.7912,0.4165,22.6597 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..049b48d --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.6871,0.7278,0.3456,27.3082 +KodakMnt,5x5,ldr-rgb-montage.png,39.8465,0.6854,0.3070,30.7383 +KodakMnt,6x6,ldr-rgb-montage.png,36.8575,0.7255,0.3485,27.0786 +KodakMnt,8x8,ldr-rgb-montage.png,32.8170,0.8186,0.4438,21.2624 +KodakMnt,12x12,ldr-rgb-montage.png,28.7278,0.6814,0.3088,30.5579 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..4a1c846 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.6971,2.7703,2.3831,3.9601 +KodakMnt,5x5,ldr-rgb-montage.png,40.6736,2.3406,1.9568,4.8228 +KodakMnt,6x6,ldr-rgb-montage.png,37.4854,2.1096,1.7288,5.4590 +KodakMnt,8x8,ldr-rgb-montage.png,33.5323,2.5367,2.1572,4.3747 +KodakMnt,12x12,ldr-rgb-montage.png,29.5339,2.3587,1.9815,4.7626 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..095e394 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9209,6.7892,6.3960,1.4755 +KodakMnt,5x5,ldr-rgb-montage.png,40.8363,7.3507,6.9659,1.3548 +KodakMnt,6x6,ldr-rgb-montage.png,37.6703,7.8500,7.4645,1.2643 +KodakMnt,8x8,ldr-rgb-montage.png,33.7079,8.1896,7.8091,1.2085 +KodakMnt,12x12,ldr-rgb-montage.png,29.7759,8.9393,8.5576,1.1028 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..79b756f --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1088,0.8074,0.4414,21.3794 +KodakMnt,5x5,ldr-rgb-montage.png,40.1064,0.6932,0.3336,28.2905 +KodakMnt,6x6,ldr-rgb-montage.png,36.9953,0.7506,0.3927,24.0288 +KodakMnt,8x8,ldr-rgb-montage.png,32.9627,0.8479,0.4965,19.0071 +KodakMnt,12x12,ldr-rgb-montage.png,28.8569,0.7135,0.3632,25.9847 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..b8bc4a6 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.6871,0.6524,0.2881,32.7583 +KodakMnt,5x5,ldr-rgb-montage.png,39.8465,0.6126,0.2544,37.0990 +KodakMnt,6x6,ldr-rgb-montage.png,36.8575,0.6433,0.2864,32.9490 +KodakMnt,8x8,ldr-rgb-montage.png,32.8170,0.7196,0.3676,25.6695 +KodakMnt,12x12,ldr-rgb-montage.png,28.7278,0.6178,0.2685,35.1413 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..c70c125 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.6971,2.3669,2.0030,4.7116 +KodakMnt,5x5,ldr-rgb-montage.png,40.6736,1.9526,1.5888,5.9399 +KodakMnt,6x6,ldr-rgb-montage.png,37.4854,1.7613,1.4025,6.7291 +KodakMnt,8x8,ldr-rgb-montage.png,33.5323,2.1315,1.7767,5.3118 +KodakMnt,12x12,ldr-rgb-montage.png,29.5339,2.0881,1.7341,5.4422 diff --git a/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..83c35da --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9209,5.7868,5.4183,1.7417 +KodakMnt,5x5,ldr-rgb-montage.png,40.8363,6.0576,5.6935,1.6575 +KodakMnt,6x6,ldr-rgb-montage.png,37.6703,6.4909,6.1316,1.5391 +KodakMnt,8x8,ldr-rgb-montage.png,33.7079,6.8737,6.5195,1.4475 +KodakMnt,12x12,ldr-rgb-montage.png,29.7759,7.8753,7.5220,1.2546 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..a582a91 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1408,0.7398,0.3868,24.4008 +KodakMnt,5x5,ldr-rgb-montage.png,40.1365,0.6282,0.2765,34.1283 +KodakMnt,6x6,ldr-rgb-montage.png,37.0049,0.6606,0.3121,30.2362 +KodakMnt,8x8,ldr-rgb-montage.png,32.9679,0.7198,0.3794,24.8739 +KodakMnt,12x12,ldr-rgb-montage.png,28.8597,0.6094,0.2725,34.6277 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..f5e83bc --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.7231,0.6040,0.2505,37.6762 +KodakMnt,5x5,ldr-rgb-montage.png,39.8789,0.5572,0.2085,45.2555 +KodakMnt,6x6,ldr-rgb-montage.png,36.8681,0.5724,0.2262,41.7170 +KodakMnt,8x8,ldr-rgb-montage.png,32.8239,0.6238,0.2851,33.0956 +KodakMnt,12x12,ldr-rgb-montage.png,28.7304,0.5409,0.2027,46.5556 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..c40678c --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.7383,2.1161,1.7584,5.3670 +KodakMnt,5x5,ldr-rgb-montage.png,40.7011,1.6696,1.3125,7.1902 +KodakMnt,6x6,ldr-rgb-montage.png,37.4941,1.4637,1.1141,8.4704 +KodakMnt,8x8,ldr-rgb-montage.png,33.5369,1.6946,1.3521,6.9795 +KodakMnt,12x12,ldr-rgb-montage.png,29.5375,1.6430,1.2993,7.2634 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..eb17ba2 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9662,5.0891,4.7321,1.9943 +KodakMnt,5x5,ldr-rgb-montage.png,40.8651,5.1386,4.7785,1.9749 +KodakMnt,6x6,ldr-rgb-montage.png,37.6808,5.2830,4.9360,1.9119 +KodakMnt,8x8,ldr-rgb-montage.png,33.7126,5.2770,4.9333,1.9130 +KodakMnt,12x12,ldr-rgb-montage.png,29.7781,6.0190,5.6758,1.6627 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..e565fe1 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1408,0.9129,0.5252,17.9688 +KodakMnt,5x5,ldr-rgb-montage.png,40.1365,0.7774,0.3972,23.7621 +KodakMnt,6x6,ldr-rgb-montage.png,37.0049,0.8556,0.4727,19.9650 +KodakMnt,8x8,ldr-rgb-montage.png,32.9679,0.9688,0.5929,15.9176 +KodakMnt,12x12,ldr-rgb-montage.png,28.8597,0.7906,0.4158,22.6980 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..766b4a9 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.7231,0.7247,0.3424,27.5585 +KodakMnt,5x5,ldr-rgb-montage.png,39.8789,0.6796,0.3017,31.2782 +KodakMnt,6x6,ldr-rgb-montage.png,36.8681,0.7242,0.3464,27.2403 +KodakMnt,8x8,ldr-rgb-montage.png,32.8239,0.8163,0.4427,21.3164 +KodakMnt,12x12,ldr-rgb-montage.png,28.7304,0.6785,0.3075,30.6877 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..dbbbecb --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.7383,2.7588,2.3707,3.9807 +KodakMnt,5x5,ldr-rgb-montage.png,40.7011,2.3050,1.9220,4.9100 +KodakMnt,6x6,ldr-rgb-montage.png,37.4941,2.0918,1.7101,5.5186 +KodakMnt,8x8,ldr-rgb-montage.png,33.5369,2.5221,2.1445,4.4007 +KodakMnt,12x12,ldr-rgb-montage.png,29.5375,2.3456,1.9707,4.7887 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..00d9dd1 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9662,6.7663,6.3802,1.4791 +KodakMnt,5x5,ldr-rgb-montage.png,40.8651,7.2819,6.8982,1.3681 +KodakMnt,6x6,ldr-rgb-montage.png,37.6808,7.8011,7.4182,1.2722 +KodakMnt,8x8,ldr-rgb-montage.png,33.7126,8.1140,7.7375,1.2197 +KodakMnt,12x12,ldr-rgb-montage.png,29.7781,8.8856,8.5084,1.1092 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..718c372 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1408,0.8005,0.4383,21.5333 +KodakMnt,5x5,ldr-rgb-montage.png,40.1365,0.6862,0.3290,28.6831 +KodakMnt,6x6,ldr-rgb-montage.png,37.0049,0.7480,0.3904,24.1711 +KodakMnt,8x8,ldr-rgb-montage.png,32.9679,0.8432,0.4969,18.9937 +KodakMnt,12x12,ldr-rgb-montage.png,28.8597,0.7200,0.3695,25.5437 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..a2ac140 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.7231,0.6447,0.2852,33.0853 +KodakMnt,5x5,ldr-rgb-montage.png,39.8789,0.6074,0.2509,37.6184 +KodakMnt,6x6,ldr-rgb-montage.png,36.8681,0.6383,0.2855,33.0601 +KodakMnt,8x8,ldr-rgb-montage.png,32.8239,0.7161,0.3676,25.6694 +KodakMnt,12x12,ldr-rgb-montage.png,28.7304,0.6181,0.2711,34.8043 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..6f9e148 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.7383,2.3548,1.9932,4.7347 +KodakMnt,5x5,ldr-rgb-montage.png,40.7011,1.9251,1.5643,6.0328 +KodakMnt,6x6,ldr-rgb-montage.png,37.4941,1.7500,1.3945,6.7676 +KodakMnt,8x8,ldr-rgb-montage.png,33.5369,2.1367,1.7812,5.2981 +KodakMnt,12x12,ldr-rgb-montage.png,29.5375,2.0997,1.7447,5.4092 diff --git a/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..5d52515 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9662,5.7613,5.3998,1.7477 +KodakMnt,5x5,ldr-rgb-montage.png,40.8651,6.0351,5.6727,1.6636 +KodakMnt,6x6,ldr-rgb-montage.png,37.6808,6.4838,6.1253,1.5407 +KodakMnt,8x8,ldr-rgb-montage.png,33.7126,6.8779,6.5156,1.4484 +KodakMnt,12x12,ldr-rgb-montage.png,29.7781,7.8826,7.5287,1.2535 diff --git a/Test/Images/KodakMnt/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/KodakMnt/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..cf75532 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.1692,0.7453,0.3931,24.0049 +KodakMnt,5x5,ldr-rgb-montage.png,40.1531,0.6364,0.2781,33.9353 +KodakMnt,6x6,ldr-rgb-montage.png,37.0104,0.6591,0.3115,30.2948 +KodakMnt,8x8,ldr-rgb-montage.png,32.9733,0.7146,0.3775,24.9972 +KodakMnt,12x12,ldr-rgb-montage.png,28.8630,0.6088,0.2724,34.6489 diff --git a/Test/Images/KodakMnt/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/KodakMnt/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..fd66eb0 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,43.7497,0.6024,0.2536,37.2151 +KodakMnt,5x5,ldr-rgb-montage.png,39.8948,0.5615,0.2110,44.7224 +KodakMnt,6x6,ldr-rgb-montage.png,36.8734,0.5718,0.2259,41.7706 +KodakMnt,8x8,ldr-rgb-montage.png,32.8289,0.6213,0.2843,33.1992 +KodakMnt,12x12,ldr-rgb-montage.png,28.7331,0.5394,0.2022,46.6739 diff --git a/Test/Images/KodakMnt/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/KodakMnt/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..790ae8f --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.7555,2.1382,1.7860,5.2841 +KodakMnt,5x5,ldr-rgb-montage.png,40.7110,1.6752,1.3215,7.1415 +KodakMnt,6x6,ldr-rgb-montage.png,37.4987,1.4586,1.1145,8.4676 +KodakMnt,8x8,ldr-rgb-montage.png,33.5397,1.6911,1.3502,6.9897 +KodakMnt,12x12,ldr-rgb-montage.png,29.5399,1.6391,1.2986,7.2670 diff --git a/Test/Images/KodakMnt/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/KodakMnt/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..9faf5b7 --- /dev/null +++ b/Test/Images/KodakMnt/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,6 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakMnt,4x4,ldr-rgb-montage.png,44.9866,5.1729,4.8184,1.9586 +KodakMnt,5x5,ldr-rgb-montage.png,40.8733,5.2002,4.8447,1.9479 +KodakMnt,6x6,ldr-rgb-montage.png,37.6862,5.2873,4.9399,1.9104 +KodakMnt,8x8,ldr-rgb-montage.png,33.7152,5.2905,4.9492,1.9068 +KodakMnt,12x12,ldr-rgb-montage.png,29.7791,6.0105,5.6706,1.6642 diff --git a/Test/Images/KodakSim/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/KodakSim/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index 2ea5f79..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3904,0.0970,0.0728,5.4050 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6546,0.0502,0.0271,14.4831 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.2501,0.0577,0.0357,11.0259 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0122,0.0387,0.0188,20.8768 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0008,0.0845,0.0591,6.6564 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1586,0.0455,0.0214,18.3713 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.3978,0.0494,0.0268,14.6920 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6115,0.0364,0.0159,24.7772 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0451,0.0878,0.0620,6.3470 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4936,0.0475,0.0235,16.7241 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3128,0.0494,0.0264,14.9109 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1307,0.0375,0.0163,24.1846 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.1671,0.0878,0.0577,6.8109 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.1803,0.0538,0.0257,15.2758 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2197,0.0512,0.0243,16.1923 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.9837,0.0404,0.0152,25.8538 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1854,0.0658,0.0298,13.1961 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7170,0.0501,0.0154,25.5649 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5222,0.0478,0.0145,27.1972 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2506,0.0416,0.0100,39.4043 diff --git a/Test/Images/KodakSim/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index 1cf31f3..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.1024,0.0654,0.0418,9.4179 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4493,0.0424,0.0204,19.2433 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,41.9861,0.0445,0.0236,16.6758 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8288,0.0334,0.0142,27.6774 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.3178,0.0613,0.0370,10.6390 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9569,0.0406,0.0177,22.2748 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.8333,0.0412,0.0193,20.4057 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.3913,0.0328,0.0131,30.0742 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.2760,0.0595,0.0352,11.1703 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3528,0.0406,0.0179,21.9402 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.7630,0.0397,0.0177,22.2495 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8540,0.0325,0.0125,31.4776 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,29.9876,0.0672,0.0394,9.9778 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0581,0.0458,0.0192,20.5003 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.0146,0.0429,0.0178,22.1191 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8083,0.0357,0.0123,31.9873 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1132,0.0534,0.0215,18.2714 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6182,0.0432,0.0124,31.6242 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4797,0.0408,0.0113,34.8911 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.1951,0.0361,0.0085,46.4517 diff --git a/Test/Images/KodakSim/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/KodakSim/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index 44e041b..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.0887,0.2026,0.1775,2.2155 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9182,0.1204,0.0964,4.0793 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.1886,0.1524,0.1297,3.0320 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.6672,0.1099,0.0890,4.4177 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7510,0.2513,0.2241,1.7547 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6013,0.1219,0.0965,4.0735 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.3581,0.1626,0.1378,2.8533 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.8509,0.0985,0.0760,5.1710 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5540,0.2516,0.2242,1.7539 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9809,0.1132,0.0868,4.5322 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2172,0.1386,0.1136,3.4622 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.4889,0.0800,0.0564,6.9717 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7276,0.2657,0.2348,1.6750 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7027,0.1266,0.0970,4.0542 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2516,0.1422,0.1136,3.4610 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2386,0.0847,0.0582,6.7508 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7761,0.2294,0.1898,2.0720 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3165,0.1190,0.0808,4.8662 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5646,0.1078,0.0706,5.5694 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3015,0.0743,0.0393,10.0053 diff --git a/Test/Images/KodakSim/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index da8015d..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.2942,0.4121,0.3868,1.0167 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1423,0.3012,0.2773,1.4182 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5746,0.3746,0.3515,1.1187 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1116,0.2878,0.2667,1.4744 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9652,0.4950,0.4678,0.8405 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7378,0.3728,0.3469,1.1335 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6371,0.4515,0.4271,0.9208 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1312,0.3650,0.3421,1.1493 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.6962,0.5698,0.5419,0.7257 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0965,0.4537,0.4273,0.9202 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.4884,0.5080,0.4831,0.8140 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8247,0.4390,0.4159,0.9454 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8695,0.6628,0.6305,0.6237 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8404,0.4331,0.4019,0.9785 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5648,0.4396,0.4095,0.9603 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7448,0.2907,0.2623,1.4991 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0242,0.7183,0.6768,0.5810 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5619,0.4395,0.3986,0.9866 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1782,0.4213,0.3814,1.0311 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0794,0.2535,0.2157,1.8227 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index 2aab788..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3904,0.1174,0.0928,4.2366 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6546,0.0590,0.0353,11.1415 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.2501,0.0678,0.0457,8.6007 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0122,0.0449,0.0245,16.0438 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0008,0.1071,0.0814,4.8299 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1586,0.0546,0.0296,13.2646 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.3978,0.0590,0.0359,10.9654 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6115,0.0420,0.0209,18.8150 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0451,0.1157,0.0896,4.3910 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4936,0.0599,0.0343,11.4590 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3128,0.0611,0.0369,10.6493 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1307,0.0440,0.0225,17.4408 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.1671,0.1156,0.0853,4.6115 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.1803,0.0667,0.0374,10.5147 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2197,0.0622,0.0343,11.4617 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.9837,0.0469,0.0216,18.1625 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1854,0.0793,0.0424,9.2779 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7170,0.0569,0.0217,18.0841 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5222,0.0541,0.0203,19.3512 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2506,0.0464,0.0141,27.8998 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index 5725ce5..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.1024,0.0784,0.0544,7.2264 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4493,0.0493,0.0263,14.9597 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,41.9861,0.0517,0.0303,12.9928 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8288,0.0379,0.0188,20.9569 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.3178,0.0771,0.0518,7.5871 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9569,0.0482,0.0243,16.2071 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.8333,0.0483,0.0260,15.1191 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.3913,0.0375,0.0172,22.8361 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.2760,0.0756,0.0505,7.7832 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3528,0.0498,0.0255,15.4354 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.7630,0.0469,0.0244,16.1386 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8540,0.0377,0.0173,22.7344 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,29.9876,0.0858,0.0570,6.8951 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0581,0.0551,0.0274,14.3416 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.0146,0.0504,0.0248,15.8863 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8083,0.0408,0.0170,23.1333 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1132,0.0633,0.0309,12.7246 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6182,0.0485,0.0174,22.5794 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4797,0.0453,0.0159,24.7977 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.1951,0.0398,0.0119,33.0992 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index 8fad21e..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.0887,0.2674,0.2429,1.6189 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9182,0.1573,0.1328,2.9600 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.1886,0.2023,0.1795,2.1911 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.6672,0.1450,0.1237,3.1788 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7510,0.3569,0.3300,1.1915 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6013,0.1687,0.1424,2.7605 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.3581,0.2278,0.2030,1.9366 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.8509,0.1353,0.1125,3.4947 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5540,0.3600,0.3324,1.1829 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9809,0.1591,0.1324,2.9704 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2172,0.1947,0.1693,2.3221 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.4889,0.1093,0.0861,4.5689 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7276,0.3902,0.3592,1.0946 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7027,0.1803,0.1501,2.6194 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2516,0.2024,0.1738,2.2624 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2386,0.1157,0.0888,4.4295 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7761,0.3256,0.2863,1.3733 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3165,0.1639,0.1251,3.1421 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5646,0.1443,0.1074,3.6628 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3015,0.0947,0.0596,6.6029 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index da50d87..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.2942,0.5453,0.5196,0.7568 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1423,0.4016,0.3766,1.0442 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5746,0.4998,0.4765,0.8252 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1116,0.3862,0.3649,1.0775 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9652,0.6957,0.6686,0.5881 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7378,0.5260,0.4999,0.7867 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6371,0.6391,0.6145,0.6399 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1312,0.5192,0.4955,0.7935 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.6962,0.8181,0.7901,0.4977 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0965,0.6589,0.6314,0.6227 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.4884,0.7347,0.7096,0.5542 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8247,0.6369,0.6133,0.6412 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8695,0.9919,0.9590,0.4100 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8404,0.6475,0.6155,0.6389 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5648,0.6559,0.6248,0.6293 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7448,0.4297,0.4010,0.9806 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0242,1.0631,1.0208,0.3852 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5619,0.6479,0.6056,0.6493 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1782,0.6180,0.5783,0.6799 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0794,0.3675,0.3292,1.1945 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index 4800bc7..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3904,0.1071,0.0825,4.7685 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6546,0.0550,0.0314,12.5216 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.2501,0.0629,0.0409,9.6199 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0122,0.0421,0.0219,17.9739 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0008,0.0962,0.0704,5.5856 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1586,0.0510,0.0260,15.1149 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.3978,0.0546,0.0313,12.5464 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6115,0.0396,0.0186,21.1931 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0451,0.1043,0.0779,5.0494 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4936,0.0552,0.0299,13.1375 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3128,0.0561,0.0324,12.1389 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1307,0.0412,0.0198,19.8203 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.1671,0.1050,0.0747,5.2617 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.1803,0.0620,0.0326,12.0563 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2197,0.0581,0.0304,12.9338 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.9837,0.0446,0.0193,20.3643 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1854,0.0743,0.0380,10.3560 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7170,0.0550,0.0196,20.0612 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5222,0.0519,0.0183,21.5438 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2506,0.0446,0.0125,31.3519 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 1895c1f..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.1024,0.0719,0.0480,8.1898 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4493,0.0462,0.0232,16.9126 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,41.9861,0.0482,0.0267,14.7272 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8288,0.0360,0.0167,23.5237 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.3178,0.0695,0.0448,8.7779 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9569,0.0449,0.0212,18.5751 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.8333,0.0446,0.0228,17.2253 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.3913,0.0353,0.0153,25.7103 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.2760,0.0691,0.0439,8.9503 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3528,0.0463,0.0226,17.3750 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.7630,0.0437,0.0218,18.0390 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8540,0.0357,0.0153,25.6265 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,29.9876,0.0789,0.0502,7.8272 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0581,0.0516,0.0242,16.2541 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.0146,0.0474,0.0221,17.7780 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8083,0.0386,0.0150,26.1880 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1132,0.0598,0.0276,14.2372 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6182,0.0469,0.0156,25.2205 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4797,0.0439,0.0140,28.0808 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.1951,0.0385,0.0105,37.3391 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 2eaf973..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.0887,0.2369,0.2117,1.8570 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9182,0.1400,0.1156,3.4003 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.1886,0.1792,0.1560,2.5213 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.6672,0.1289,0.1072,3.6680 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7510,0.3097,0.2822,1.3936 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6013,0.1487,0.1225,3.2089 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.3581,0.1994,0.1750,2.2476 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.8509,0.1190,0.0964,4.0777 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5540,0.3186,0.2904,1.3538 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9809,0.1413,0.1147,3.4297 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2172,0.1727,0.1476,2.6640 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.4889,0.0979,0.0747,5.2643 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7276,0.3488,0.3174,1.2389 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7027,0.1616,0.1313,2.9939 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2516,0.1819,0.1532,2.5675 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2386,0.1047,0.0781,5.0324 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7761,0.2953,0.2558,1.5370 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3165,0.1493,0.1108,3.5486 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5646,0.1333,0.0956,4.1129 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3015,0.0879,0.0529,7.4316 diff --git a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/KodakSim/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 57f6941..0000000 --- a/Test/Images/KodakSim/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,21 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.2942,0.4847,0.4596,0.8555 -KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1423,0.3555,0.3306,1.1894 -KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5746,0.4412,0.4181,0.9406 -KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1116,0.3438,0.3224,1.2195 -KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9652,0.6160,0.5888,0.6679 -KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7378,0.4642,0.4381,0.8976 -KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6371,0.5630,0.5384,0.7304 -KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1312,0.4541,0.4308,0.9127 -KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.6962,0.7258,0.6982,0.5632 -KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0965,0.5842,0.5574,0.7055 -KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.4884,0.6491,0.6238,0.6303 -KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8247,0.5602,0.5370,0.7323 -KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8695,0.8844,0.8515,0.4618 -KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8404,0.5758,0.5442,0.7226 -KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5648,0.5837,0.5536,0.7103 -KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7448,0.3833,0.3549,1.1078 -KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0242,0.9534,0.9107,0.4318 -KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5619,0.5808,0.5388,0.7299 -KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1782,0.5531,0.5136,0.7656 -KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0794,0.3297,0.2914,1.3495 diff --git a/Test/Images/KodakSim/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..9794d62 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4688,0.0820,0.0620,6.3413 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6886,0.0416,0.0222,17.7046 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3209,0.0481,0.0291,13.5168 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0545,0.0326,0.0145,27.1954 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0468,0.0662,0.0460,8.5487 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1815,0.0359,0.0164,23.9038 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4661,0.0393,0.0202,19.5069 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6532,0.0297,0.0116,33.9593 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0787,0.0641,0.0443,8.8758 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5119,0.0369,0.0180,21.8843 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3780,0.0385,0.0196,20.0241 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1674,0.0302,0.0123,31.9582 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2278,0.0609,0.0409,9.6052 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2087,0.0391,0.0199,19.8003 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2938,0.0366,0.0178,22.0352 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0493,0.0293,0.0114,34.6354 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1955,0.0447,0.0232,16.9652 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7382,0.0332,0.0123,31.9638 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5348,0.0312,0.0107,36.7836 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2755,0.0271,0.0073,53.6679 diff --git a/Test/Images/KodakSim/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..9b080ea --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3196,0.0555,0.0360,10.9081 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4978,0.0342,0.0157,24.9772 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1158,0.0369,0.0188,20.8858 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8520,0.0278,0.0107,36.9154 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.4962,0.0484,0.0292,13.4829 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9917,0.0308,0.0128,30.7052 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9594,0.0323,0.0145,27.1556 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4137,0.0267,0.0093,42.4085 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4494,0.0450,0.0259,15.2026 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3980,0.0314,0.0133,29.4875 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.8880,0.0309,0.0132,29.8499 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8578,0.0263,0.0092,42.7172 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0854,0.0482,0.0284,13.8276 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0724,0.0338,0.0147,26.7621 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1038,0.0317,0.0132,29.8591 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8469,0.0267,0.0089,43.9687 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1188,0.0376,0.0165,23.8038 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6485,0.0295,0.0092,42.8481 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4981,0.0281,0.0081,48.3954 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2305,0.0253,0.0060,65.7550 diff --git a/Test/Images/KodakSim/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..ab5e76e --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1293,0.1510,0.1308,3.0072 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9525,0.0927,0.0717,5.4821 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.2439,0.1130,0.0934,4.2086 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7191,0.0813,0.0625,6.2927 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7719,0.1645,0.1430,2.7497 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6333,0.0867,0.0661,5.9486 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4004,0.1093,0.0888,4.4282 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9086,0.0723,0.0527,7.4543 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5627,0.1612,0.1402,2.8047 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9968,0.0808,0.0603,6.5180 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2394,0.0963,0.0762,5.1624 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5251,0.0618,0.0425,9.2504 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7402,0.1703,0.1489,2.6400 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7082,0.0922,0.0712,5.5244 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2732,0.1000,0.0797,4.9341 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2742,0.0652,0.0457,8.5997 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7758,0.1435,0.1189,3.3081 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3417,0.0853,0.0617,6.3767 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5760,0.0764,0.0532,7.3907 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3144,0.0538,0.0312,12.5890 diff --git a/Test/Images/KodakSim/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..fce09be --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3073,0.2847,0.2644,1.4874 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1611,0.1812,0.1611,2.4401 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5999,0.2396,0.2196,1.7904 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1266,0.1739,0.1550,2.5362 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9793,0.3195,0.2978,1.3202 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7559,0.2034,0.1824,2.1554 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6657,0.2685,0.2480,1.5852 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1597,0.2039,0.1839,2.1382 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7090,0.3422,0.3210,1.2250 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1208,0.2312,0.2110,1.8635 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5196,0.2870,0.2670,1.4725 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8418,0.2322,0.2131,1.8449 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8800,0.3986,0.3759,1.0462 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8492,0.2692,0.2467,1.5938 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5803,0.2787,0.2570,1.5300 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7694,0.1991,0.1781,2.2077 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0232,0.4519,0.4249,0.9254 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5641,0.3028,0.2764,1.4229 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1778,0.2957,0.2700,1.4566 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0972,0.1922,0.1672,2.3522 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..8f78961 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4688,0.1024,0.0815,4.8243 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6886,0.0498,0.0295,13.3090 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3209,0.0585,0.0386,10.1793 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0545,0.0385,0.0196,20.0343 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0468,0.0858,0.0644,6.1011 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1815,0.0438,0.0233,16.8922 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4661,0.0484,0.0284,13.8442 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6532,0.0353,0.0163,24.1502 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0787,0.0866,0.0654,6.0137 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5119,0.0472,0.0268,14.6915 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3780,0.0489,0.0288,13.6444 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1674,0.0365,0.0176,22.3139 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2278,0.0840,0.0626,6.2812 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2087,0.0513,0.0306,12.8301 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2938,0.0472,0.0270,14.5727 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0493,0.0363,0.0170,23.1479 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1955,0.0577,0.0346,11.3649 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7382,0.0404,0.0181,21.7137 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5348,0.0372,0.0158,24.9202 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2755,0.0318,0.0108,36.5068 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..8ffb488 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3196,0.0681,0.0477,8.2418 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4978,0.0403,0.0208,18.9000 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1158,0.0444,0.0250,15.7016 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8520,0.0324,0.0143,27.5300 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.4962,0.0616,0.0413,9.5247 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9917,0.0376,0.0181,21.6983 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9594,0.0396,0.0204,19.2714 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4137,0.0313,0.0131,30.0555 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4494,0.0590,0.0388,10.1289 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3980,0.0396,0.0201,19.5571 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.8880,0.0382,0.0194,20.2648 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8578,0.0315,0.0134,29.3443 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0854,0.0644,0.0433,9.0720 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0724,0.0426,0.0222,17.6894 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1038,0.0395,0.0198,19.8805 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8469,0.0322,0.0132,29.8278 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1188,0.0465,0.0245,16.0464 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6485,0.0350,0.0136,29.0027 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4981,0.0331,0.0119,32.9715 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2305,0.0290,0.0087,45.3282 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..887dc13 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1293,0.1986,0.1771,2.2201 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9525,0.1176,0.0966,4.0717 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.2439,0.1475,0.1270,3.0959 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7191,0.1036,0.0841,4.6737 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7719,0.2322,0.2097,1.8752 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6333,0.1181,0.0964,4.0788 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4004,0.1529,0.1301,3.0229 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9086,0.0996,0.0788,4.9911 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5627,0.2332,0.2106,1.8674 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9968,0.1141,0.0928,4.2368 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2394,0.1364,0.1154,3.4078 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5251,0.0865,0.0662,5.9413 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7402,0.2517,0.2291,1.7165 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7082,0.1345,0.1124,3.4986 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2732,0.1462,0.1247,3.1544 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2742,0.0937,0.0730,5.3890 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7758,0.2022,0.1769,2.2234 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3417,0.1184,0.0933,4.2158 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5760,0.1042,0.0800,4.9173 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3144,0.0709,0.0471,8.3429 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..7ca998f --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3073,0.3803,0.3591,1.0949 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1611,0.2400,0.2187,1.7976 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5999,0.3186,0.2979,1.3198 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1266,0.2306,0.2103,1.8702 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9793,0.4495,0.4267,0.9214 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7559,0.2855,0.2639,1.4902 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6657,0.3821,0.3603,1.0913 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1597,0.2857,0.2649,1.4844 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7090,0.4995,0.4770,0.8244 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1208,0.3354,0.3141,1.2521 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5196,0.4180,0.3968,0.9909 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8418,0.3366,0.3165,1.2424 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8800,0.6031,0.5790,0.6791 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8492,0.4066,0.3829,1.0269 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5803,0.4199,0.3968,0.9911 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7694,0.3019,0.2798,1.4055 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0232,0.6552,0.6270,0.6271 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5641,0.4394,0.4118,0.9548 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1778,0.4290,0.4019,0.9783 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0972,0.2778,0.2516,1.5630 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..cca2d5f --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4688,0.0891,0.0690,5.6949 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.6886,0.0444,0.0250,15.7382 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3209,0.0516,0.0326,12.0636 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0545,0.0344,0.0164,23.9462 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0468,0.0736,0.0533,7.3753 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1815,0.0385,0.0193,20.4077 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4661,0.0428,0.0236,16.6539 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6532,0.0319,0.0137,28.6685 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0787,0.0739,0.0541,7.2698 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5119,0.0417,0.0222,17.7085 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3780,0.0430,0.0239,16.4291 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1674,0.0329,0.0149,26.3428 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2278,0.0723,0.0522,7.5384 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2087,0.0452,0.0256,15.3864 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.2938,0.0417,0.0226,17.3706 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0493,0.0327,0.0143,27.5148 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1955,0.0521,0.0301,13.0576 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7382,0.0370,0.0158,24.8163 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5348,0.0347,0.0138,28.5104 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2755,0.0293,0.0095,41.5485 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..a04d866 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3196,0.0599,0.0405,9.7179 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.4978,0.0362,0.0176,22.3040 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1158,0.0395,0.0212,18.5419 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.8520,0.0294,0.0121,32.6052 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.4962,0.0536,0.0342,11.4811 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,38.9917,0.0337,0.0151,26.0803 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9594,0.0351,0.0171,23.0625 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4137,0.0283,0.0109,36.1009 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4494,0.0508,0.0319,12.3370 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.3980,0.0350,0.0166,23.6434 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.8880,0.0341,0.0161,24.3917 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8578,0.0285,0.0113,34.8167 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0854,0.0561,0.0360,10.9090 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0724,0.0376,0.0186,21.1147 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1038,0.0351,0.0166,23.6664 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8469,0.0292,0.0111,35.2784 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1188,0.0427,0.0215,18.3189 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6485,0.0324,0.0119,32.9708 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.4981,0.0305,0.0105,37.5388 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2305,0.0269,0.0076,51.5960 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..c70c012 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1293,0.1698,0.1493,2.6345 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9525,0.1021,0.0820,4.7930 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.2439,0.1271,0.1074,3.6608 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7191,0.0905,0.0716,5.4901 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7719,0.1939,0.1724,2.2813 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6333,0.0998,0.0790,4.9777 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4004,0.1269,0.1065,3.6925 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9086,0.0833,0.0636,6.1834 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5627,0.1942,0.1730,2.2728 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.9968,0.0960,0.0754,5.2156 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2394,0.1146,0.0944,4.1672 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5251,0.0743,0.0545,7.2205 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7402,0.2116,0.1901,2.0688 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7082,0.1137,0.0928,4.2366 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2732,0.1238,0.1032,3.8101 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2742,0.0801,0.0602,6.5360 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7758,0.1797,0.1552,2.5338 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3417,0.1054,0.0817,4.8146 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5760,0.0936,0.0702,5.6038 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3144,0.0640,0.0412,9.5413 diff --git a/Test/Images/KodakSim/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..069e932 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3073,0.3227,0.3022,1.3011 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.1611,0.2063,0.1856,2.1188 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.5999,0.2721,0.2522,1.5589 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.1266,0.1968,0.1778,2.2114 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9793,0.3718,0.3497,1.1244 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7559,0.2376,0.2165,1.8166 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6657,0.3165,0.2961,1.3279 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1597,0.2383,0.2188,1.7974 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7090,0.4135,0.3925,1.0019 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1208,0.2808,0.2597,1.5140 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5196,0.3478,0.3277,1.1999 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8418,0.2811,0.2616,1.5029 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8800,0.5094,0.4861,0.8089 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8492,0.3453,0.3228,1.2182 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5803,0.3566,0.3335,1.1791 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7694,0.2567,0.2352,1.6718 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0232,0.5806,0.5531,0.7109 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5641,0.3885,0.3620,1.0862 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1778,0.3796,0.3537,1.1117 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0972,0.2467,0.2215,1.7749 diff --git a/Test/Images/KodakSim/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..9722eb5 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4919,0.0818,0.0619,6.3486 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.7370,0.0409,0.0217,18.1097 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3614,0.0476,0.0289,13.6089 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.1424,0.0320,0.0142,27.7188 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0572,0.0660,0.0459,8.5739 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1918,0.0353,0.0162,24.3205 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4951,0.0390,0.0201,19.5756 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6991,0.0295,0.0114,34.6020 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0839,0.0639,0.0442,8.9036 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5253,0.0368,0.0179,21.9967 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3919,0.0381,0.0195,20.1277 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1835,0.0298,0.0122,32.1232 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2332,0.0608,0.0407,9.6630 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2165,0.0389,0.0197,19.9643 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.3081,0.0365,0.0178,22.1159 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0690,0.0291,0.0113,34.8035 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1972,0.0447,0.0231,17.0490 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7438,0.0330,0.0122,32.2047 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5449,0.0311,0.0107,36.7386 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2854,0.0270,0.0073,53.9541 diff --git a/Test/Images/KodakSim/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..e488200 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3469,0.0553,0.0359,10.9684 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.5543,0.0337,0.0154,25.5752 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1673,0.0367,0.0187,21.0602 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.9925,0.0275,0.0104,37.9003 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.5080,0.0483,0.0291,13.4978 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.0073,0.0310,0.0127,30.9669 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9880,0.0324,0.0143,27.4247 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4665,0.0264,0.0091,43.2436 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4575,0.0446,0.0258,15.2569 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4116,0.0315,0.0134,29.4302 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.9040,0.0307,0.0131,29.9780 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8791,0.0261,0.0092,42.5980 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0901,0.0481,0.0284,13.8637 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0825,0.0335,0.0146,26.8974 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1153,0.0317,0.0131,29.9323 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8645,0.0268,0.0089,44.1323 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1227,0.0373,0.0165,23.8530 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6534,0.0295,0.0092,42.7637 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5037,0.0281,0.0082,47.9592 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2405,0.0251,0.0059,66.1533 diff --git a/Test/Images/KodakSim/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..6f3dc9e --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1568,0.1506,0.1301,3.0218 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9990,0.0936,0.0728,5.4016 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.3027,0.1135,0.0941,4.1808 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7847,0.0821,0.0634,6.2046 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7817,0.1639,0.1427,2.7559 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6513,0.0857,0.0653,6.0237 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4301,0.1085,0.0883,4.4553 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9353,0.0720,0.0526,7.4703 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5685,0.1621,0.1411,2.7866 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0066,0.0804,0.0603,6.5238 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2531,0.0951,0.0751,5.2381 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5379,0.0615,0.0424,9.2654 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7443,0.1692,0.1475,2.6659 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7131,0.0913,0.0706,5.5662 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2822,0.0994,0.0791,4.9681 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2854,0.0647,0.0453,8.6814 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7797,0.1430,0.1186,3.3162 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3434,0.0848,0.0611,6.4394 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5857,0.0762,0.0528,7.4502 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3311,0.0533,0.0309,12.7382 diff --git a/Test/Images/KodakSim/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..5cc24de --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3326,0.2819,0.2612,1.5052 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.2051,0.1791,0.1590,2.4732 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.6518,0.2410,0.2213,1.7768 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.2014,0.1758,0.1568,2.5077 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9922,0.3176,0.2962,1.3276 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7737,0.2012,0.1807,2.1766 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6946,0.2687,0.2486,1.5819 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1908,0.2038,0.1842,2.1350 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7163,0.3381,0.3170,1.2404 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1301,0.2295,0.2093,1.8792 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5367,0.2898,0.2699,1.4570 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8575,0.2338,0.2147,1.8315 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8852,0.3970,0.3741,1.0510 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8558,0.2687,0.2463,1.5964 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5942,0.2774,0.2555,1.5392 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7747,0.1973,0.1765,2.2280 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0247,0.4529,0.4260,0.9231 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5689,0.3006,0.2743,1.4336 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1903,0.2944,0.2686,1.4641 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0987,0.1902,0.1651,2.3816 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..8f2bc32 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4919,0.1025,0.0815,4.8265 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.7370,0.0493,0.0290,13.5663 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3614,0.0583,0.0385,10.2129 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.1424,0.0383,0.0192,20.4332 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0572,0.0858,0.0643,6.1165 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1918,0.0436,0.0230,17.1008 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4951,0.0487,0.0282,13.9645 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6991,0.0351,0.0160,24.6053 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0839,0.0866,0.0653,6.0180 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5253,0.0472,0.0266,14.7581 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3919,0.0487,0.0286,13.7589 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1835,0.0366,0.0175,22.4412 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2332,0.0835,0.0620,6.3431 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2165,0.0512,0.0304,12.9432 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.3081,0.0470,0.0267,14.7156 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0690,0.0359,0.0168,23.3959 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1972,0.0575,0.0344,11.4201 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7438,0.0401,0.0182,21.6576 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5449,0.0377,0.0158,24.8728 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2854,0.0317,0.0108,36.4125 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..ee61c69 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3469,0.0678,0.0474,8.2947 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.5543,0.0401,0.0205,19.2216 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1673,0.0440,0.0247,15.8895 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.9925,0.0322,0.0141,27.9390 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.5080,0.0617,0.0413,9.5173 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.0073,0.0377,0.0180,21.8576 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9880,0.0395,0.0201,19.5163 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4665,0.0311,0.0128,30.7223 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4575,0.0589,0.0386,10.1756 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4116,0.0397,0.0200,19.6334 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.9040,0.0384,0.0192,20.4363 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8791,0.0315,0.0133,29.5721 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0901,0.0644,0.0433,9.0831 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0825,0.0427,0.0222,17.7061 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1153,0.0396,0.0196,20.0283 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8645,0.0323,0.0132,29.8797 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1227,0.0465,0.0246,16.0104 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6534,0.0350,0.0136,28.9620 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5037,0.0330,0.0119,33.0515 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2405,0.0290,0.0087,45.3894 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..0173a3b --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1568,0.1988,0.1771,2.2201 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9990,0.1178,0.0967,4.0667 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.3027,0.1490,0.1284,3.0616 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7847,0.1059,0.0862,4.5634 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7817,0.2296,0.2072,1.8977 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6513,0.1172,0.0954,4.1220 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4301,0.1516,0.1296,3.0347 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9353,0.0994,0.0785,5.0082 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5685,0.2318,0.2098,1.8741 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0066,0.1132,0.0919,4.2778 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2531,0.1351,0.1140,3.4497 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5379,0.0860,0.0659,5.9645 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7443,0.2504,0.2272,1.7310 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7131,0.1338,0.1116,3.5225 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2822,0.1452,0.1234,3.1862 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2854,0.0924,0.0712,5.5200 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7797,0.2018,0.1765,2.2276 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3434,0.1177,0.0928,4.2365 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5857,0.1040,0.0796,4.9398 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3311,0.0703,0.0466,8.4356 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..56305cd --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3326,0.3771,0.3556,1.1059 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.2051,0.2369,0.2158,1.8220 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.6518,0.3209,0.3003,1.3093 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.2014,0.2332,0.2134,1.8428 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9922,0.4452,0.4227,0.9302 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7737,0.2831,0.2614,1.5042 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6946,0.3806,0.3592,1.0947 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1908,0.2881,0.2675,1.4699 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7163,0.4946,0.4724,0.8323 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1301,0.3345,0.3130,1.2562 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5367,0.4216,0.4002,0.9827 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8575,0.3398,0.3196,1.2304 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8852,0.5961,0.5715,0.6881 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8558,0.4057,0.3824,1.0284 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5942,0.4158,0.3928,1.0010 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7747,0.2984,0.2765,1.4224 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0247,0.6535,0.6256,0.6285 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5689,0.4374,0.4099,0.9593 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1903,0.4267,0.3999,0.9832 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0987,0.2764,0.2501,1.5721 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..85abfa9 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4919,0.0905,0.0698,5.6371 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.7370,0.0445,0.0244,16.0857 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3614,0.0516,0.0325,12.0881 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.1424,0.0338,0.0163,24.1488 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0572,0.0743,0.0536,7.3373 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1918,0.0392,0.0192,20.4639 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.4951,0.0432,0.0236,16.6771 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.6991,0.0345,0.0149,26.3070 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0839,0.0767,0.0557,7.0570 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5253,0.0424,0.0224,17.5748 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3919,0.0434,0.0240,16.3847 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1835,0.0333,0.0149,26.4170 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2332,0.0731,0.0525,7.4870 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2165,0.0456,0.0256,15.3583 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.3081,0.0422,0.0226,17.3805 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0690,0.0329,0.0143,27.4745 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1972,0.0532,0.0306,12.8498 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7438,0.0379,0.0161,24.4931 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5449,0.0357,0.0142,27.7753 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2854,0.0299,0.0096,41.0930 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..0296c21 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3469,0.0597,0.0404,9.7415 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.5543,0.0359,0.0173,22.6975 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1673,0.0393,0.0211,18.6508 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,44.9925,0.0293,0.0119,32.9570 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.5080,0.0537,0.0343,11.4673 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.0073,0.0337,0.0149,26.3196 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9880,0.0350,0.0170,23.1769 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4665,0.0282,0.0109,36.2110 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4575,0.0511,0.0318,12.3703 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4116,0.0349,0.0167,23.5603 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.9040,0.0340,0.0161,24.3931 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8791,0.0285,0.0113,34.7763 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0901,0.0561,0.0359,10.9394 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0825,0.0377,0.0186,21.1564 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1153,0.0352,0.0166,23.6478 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8645,0.0289,0.0111,35.3677 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1227,0.0430,0.0216,18.1776 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6534,0.0325,0.0120,32.7242 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5037,0.0305,0.0106,37.0430 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2405,0.0269,0.0077,51.3071 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..02eddfc --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1568,0.1704,0.1497,2.6269 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.9990,0.1018,0.0821,4.7911 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.3027,0.1281,0.1085,3.6231 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.7847,0.0918,0.0731,5.3816 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7817,0.1925,0.1710,2.2996 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6513,0.0989,0.0783,5.0202 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4301,0.1272,0.1063,3.6988 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9353,0.0840,0.0638,6.1595 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5685,0.1947,0.1737,2.2635 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0066,0.0958,0.0753,5.2234 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2531,0.1138,0.0939,4.1867 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5379,0.0743,0.0545,7.2160 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7443,0.2134,0.1919,2.0489 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7131,0.1137,0.0926,4.2445 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2822,0.1242,0.1037,3.7925 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2854,0.0796,0.0597,6.5849 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7797,0.1804,0.1561,2.5191 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3434,0.1060,0.0821,4.7880 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5857,0.0939,0.0705,5.5779 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3311,0.0644,0.0415,9.4689 diff --git a/Test/Images/KodakSim/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..4024ff9 --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3326,0.3232,0.3025,1.2999 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.2051,0.2050,0.1844,2.1327 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.6518,0.2761,0.2564,1.5337 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.2014,0.2009,0.1821,2.1592 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9922,0.3740,0.3520,1.1170 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7737,0.2376,0.2164,1.8168 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.6946,0.3185,0.2981,1.3190 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.1908,0.2419,0.2221,1.7705 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7163,0.4125,0.3915,1.0045 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1301,0.2816,0.2605,1.5094 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5367,0.3497,0.3295,1.1934 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8575,0.2842,0.2651,1.4835 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8852,0.5110,0.4876,0.8064 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8558,0.3454,0.3229,1.2178 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5942,0.3561,0.3337,1.1783 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7747,0.2542,0.2331,1.6867 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0247,0.5847,0.5574,0.7055 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5689,0.3905,0.3643,1.0792 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1903,0.3816,0.3556,1.1058 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.0987,0.2463,0.2213,1.7765 diff --git a/Test/Images/KodakSim/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/KodakSim/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..1a3da5e --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.4947,0.0824,0.0626,6.2861 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.7575,0.0410,0.0219,17.9264 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.3771,0.0478,0.0292,13.4544 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.1921,0.0326,0.0144,27.3275 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.0593,0.0664,0.0463,8.4865 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.1990,0.0354,0.0162,24.3370 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,39.5028,0.0388,0.0202,19.4652 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.7102,0.0296,0.0115,34.2883 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.0839,0.0638,0.0440,8.9469 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.5274,0.0366,0.0178,22.0783 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,37.3933,0.0378,0.0194,20.2752 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,39.1903,0.0295,0.0120,32.6407 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.2338,0.0601,0.0404,9.7420 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.2175,0.0385,0.0196,20.0375 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.3088,0.0360,0.0176,22.3052 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,36.0715,0.0289,0.0113,34.8255 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1983,0.0442,0.0229,17.1344 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.7450,0.0332,0.0121,32.6265 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5473,0.0309,0.0106,36.9882 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2873,0.0268,0.0073,54.0885 diff --git a/Test/Images/KodakSim/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/KodakSim/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..131680a --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,38.3506,0.0556,0.0364,10.7907 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,42.5776,0.0340,0.0158,24.8713 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,42.1927,0.0368,0.0189,20.7677 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.0640,0.0278,0.0106,37.2615 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,34.5082,0.0485,0.0293,13.3979 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.0139,0.0309,0.0128,30.8384 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,38.9982,0.0323,0.0145,27.1896 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,41.4803,0.0264,0.0092,42.7371 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,32.4587,0.0455,0.0261,15.0663 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,36.4142,0.0314,0.0132,29.7798 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,36.9072,0.0309,0.0131,30.0901 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,38.8826,0.0259,0.0092,42.8014 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.0911,0.0475,0.0284,13.8646 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.0838,0.0333,0.0146,26.9642 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,34.1188,0.0315,0.0131,29.9910 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,35.8675,0.0262,0.0089,44.2519 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.1239,0.0373,0.0164,24.0190 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,29.6549,0.0293,0.0092,42.6024 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,30.5059,0.0283,0.0082,47.8076 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,32.2438,0.0249,0.0059,66.2410 diff --git a/Test/Images/KodakSim/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/KodakSim/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..89fee8f --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.1605,0.1523,0.1317,2.9856 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.0186,0.0928,0.0727,5.4105 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.3148,0.1148,0.0955,4.1177 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,45.8205,0.0827,0.0640,6.1424 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.7835,0.1637,0.1427,2.7563 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.6594,0.0861,0.0656,5.9928 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.4362,0.1084,0.0884,4.4489 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,42.9528,0.0716,0.0524,7.5014 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.5684,0.1611,0.1402,2.8048 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.0113,0.0799,0.0597,6.5820 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.2584,0.0947,0.0750,5.2423 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.5591,0.0611,0.0423,9.3020 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.7452,0.1689,0.1469,2.6775 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.7152,0.0912,0.0707,5.5602 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.2848,0.0986,0.0785,5.0121 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.2956,0.0642,0.0447,8.7985 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,27.7812,0.1423,0.1182,3.3263 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.3441,0.0843,0.0608,6.4700 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,31.5868,0.0757,0.0526,7.4715 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,33.3324,0.0530,0.0308,12.7469 diff --git a/Test/Images/KodakSim/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/KodakSim/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..d9eb8af --- /dev/null +++ b/Test/Images/KodakSim/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,21 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +KodakSim,4x4,ldr-rgba-kodak22+24+nca.png,39.3375,0.2833,0.2632,1.4940 +KodakSim,4x4,ldr-rgba-kodak22+ca.png,43.2245,0.1807,0.1607,2.4463 +KodakSim,4x4,ldr-rgba-kodak23+20+nca.png,43.6742,0.2439,0.2243,1.7531 +KodakSim,4x4,ldr-rgba-kodak23+ca.png,46.2511,0.1790,0.1602,2.4538 +KodakSim,5x5,ldr-rgba-kodak22+24+nca.png,35.9948,0.3169,0.2953,1.3314 +KodakSim,5x5,ldr-rgba-kodak22+ca.png,39.7826,0.2023,0.1817,2.1645 +KodakSim,5x5,ldr-rgba-kodak23+20+nca.png,40.7040,0.2699,0.2495,1.5759 +KodakSim,5x5,ldr-rgba-kodak23+ca.png,43.2116,0.2055,0.1859,2.1148 +KodakSim,6x6,ldr-rgba-kodak22+24+nca.png,33.7175,0.3376,0.3170,1.2404 +KodakSim,6x6,ldr-rgba-kodak22+ca.png,37.1343,0.2298,0.2096,1.8759 +KodakSim,6x6,ldr-rgba-kodak23+20+nca.png,38.5425,0.2877,0.2680,1.4673 +KodakSim,6x6,ldr-rgba-kodak23+ca.png,40.8697,0.2333,0.2144,1.8338 +KodakSim,8x8,ldr-rgba-kodak22+24+nca.png,30.8859,0.3958,0.3730,1.0543 +KodakSim,8x8,ldr-rgba-kodak22+ca.png,33.8584,0.2666,0.2444,1.6086 +KodakSim,8x8,ldr-rgba-kodak23+20+nca.png,35.5966,0.2762,0.2547,1.5438 +KodakSim,8x8,ldr-rgba-kodak23+ca.png,37.7790,0.1969,0.1762,2.2317 +KodakSim,12x12,ldr-rgba-kodak22+24+nca.png,28.0253,0.4511,0.4243,0.9268 +KodakSim,12x12,ldr-rgba-kodak22+ca.png,30.5709,0.3001,0.2740,1.4351 +KodakSim,12x12,ldr-rgba-kodak23+20+nca.png,32.1907,0.2930,0.2673,1.4711 +KodakSim,12x12,ldr-rgba-kodak23+ca.png,34.1013,0.1891,0.1641,2.3967 diff --git a/Test/Images/Small/HDR-RGB/hdr-rgb-r16.ktx b/Test/Images/Small/HDR-RGB/hdr-rgb-r16.ktx new file mode 100644 index 0000000000000000000000000000000000000000..c3c2102d8e9821a78be4cb39acd89549d7a02c9c GIT binary patch literal 612 zcmZ4O9TK5nXt)#2^5oL0AEZrGeNb bGdDG_I5R)57_1DY6rvntn9V30$sqs$koQE$ literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGB/hdr-rgb-r32.ktx b/Test/Images/Small/HDR-RGB/hdr-rgb-r32.ktx new file mode 100644 index 0000000000000000000000000000000000000000..a5b660ba17cbebf04802654c88d437e612d90f1b GIT binary patch literal 1124 zcmZ4O9TK5nXtgn@yDfq{Wpl7T_52|^11`5?>)#2^5oL0AEZrGeNb iGdDG_I5R)57_1DY6rvnt7(;{oC>{-i(KIkJ(*OYV9>>T4 literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGB/hdr-rgb-rg16.ktx b/Test/Images/Small/HDR-RGB/hdr-rgb-rg16.ktx new file mode 100644 index 0000000000000000000000000000000000000000..c0f651d96073921de38c8abf325da79019fb52b0 GIT binary patch literal 1124 zcmZ4O9TK5nXtq{4FCYJ*+u36 literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGB/hdr-rgb-rg32.ktx b/Test/Images/Small/HDR-RGB/hdr-rgb-rg32.ktx new file mode 100644 index 0000000000000000000000000000000000000000..6ffb19e25a407784b3e575d31dcf2f7a499c21da GIT binary patch literal 2148 zcmZ4O9TK5nXtgn@yDfq_B2iGjfYh(WXfkPpI)KnwyP8iW;qSQ?03 vGILY&iZk=`icyq8lyd+TfI)-(C=CjM(Qp_|2czj=G#`wX1Eb}@$S4N@{~yTc literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGB/hdr-rgb-rgb16.ktx b/Test/Images/Small/HDR-RGB/hdr-rgb-rgb16.ktx new file mode 100644 index 0000000000000000000000000000000000000000..e75ea021c2bcf1347a4ba824ec2ed720e1ee7dd0 GIT binary patch literal 1636 zcmZ4O9TK5nXt)#2^5oL0AEZrGeNb oGdDG_I5R)57_1DY6r!9BsDOdNW|SNafzc2c4S~@R7gn@yDfq{Wtl7T_A140V``5?>)#2^5oL0AEZrGeNb zGdDG_I5R)57_1DY6r!95r~nKa>|rbhhEeutn2e@@(KIlc21e7sXc`zz1EXnRG!2ZV If#I4406zuC#Q*>R literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGBA/hdr-rgba-rgba16.ktx b/Test/Images/Small/HDR-RGBA/hdr-rgba-rgba16.ktx new file mode 100644 index 0000000000000000000000000000000000000000..8abff2c6065e1e380a04a9956e6f2541774e156c GIT binary patch literal 2148 zcmZ4O9TK5nXt)#2^5oL0AEZrGeNb tGdDG_I5R)57_1DY6r!91sDOdNW)zQx!Dt#7O#`E8U^ESkrh$=_1_1lhfXe^? literal 0 HcmV?d00001 diff --git a/Test/Images/Small/HDR-RGBA/hdr-rgba-rgba32.ktx b/Test/Images/Small/HDR-RGBA/hdr-rgba-rgba32.ktx new file mode 100644 index 0000000000000000000000000000000000000000..e40c3eca3ff63a2ce4d8d895c39122072f58f231 GIT binary patch literal 4196 zcmZ4O9TK5nXtgn@yDfq{WTl7T^_140V``5?>)#2^5oL0AEZrGeNb zGdDG_I5R)57_1DY6rvo&1A_+pQ5qBiqv0@`4o1_#Xg(M%2S&?*(Q;t492hMJM$3WG Sa$vL^7%c}z%Yorp4gdh!BZk=k literal 0 HcmV?d00001 diff --git a/Test/Images/Small/astc_reference-3.6-avx2_fast_results.csv b/Test/Images/Small/astc_reference-3.6-avx2_fast_results.csv deleted file mode 100644 index 81d3cb6..0000000 --- a/Test/Images/Small/astc_reference-3.6-avx2_fast_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.6884,0.1058,0.0154,4.2512 -Small,4x4,ldr-rgb-00.png,38.1103,0.0146,0.0096,6.8216 -Small,4x4,ldr-rgb-01.png,39.8105,0.0132,0.0085,7.7356 -Small,4x4,ldr-rgb-02.png,35.0374,0.0180,0.0133,4.9365 -Small,4x4,ldr-rgb-03.png,45.9704,0.0078,0.0032,20.1893 -Small,4x4,ldr-rgb-04.png,41.9106,0.0108,0.0058,11.3109 -Small,4x4,ldr-rgb-05.png,37.2317,0.0174,0.0125,5.2395 -Small,4x4,ldr-rgb-06.png,35.2059,0.0172,0.0122,5.3613 -Small,4x4,ldr-rgb-07.png,38.0309,0.0182,0.0129,5.0953 -Small,4x4,ldr-rgb-08.png,43.6358,0.0098,0.0049,13.3527 -Small,4x4,ldr-rgb-09.png,41.8533,0.0111,0.0063,10.3630 -Small,4x4,ldr-rgb-10.png,44.3464,0.0044,0.0018,8.8641 -Small,4x4,ldr-rgba-00.png,35.5182,0.0177,0.0123,5.3186 -Small,4x4,ldr-rgba-01.png,38.7956,0.0127,0.0076,8.6277 -Small,4x4,ldr-rgba-02.png,34.8333,0.0161,0.0110,5.9795 -Small,4x4,ldr-xy-00.png,37.5697,0.0135,0.0061,10.7404 -Small,4x4,ldr-xy-01.png,44.1378,0.0142,0.0071,9.2176 -Small,4x4,ldr-xy-02.png,48.1786,0.0120,0.0043,15.1107 -Small,4x4,ldrs-rgba-00.png,35.5254,0.0180,0.0126,5.2066 -Small,4x4,ldrs-rgba-01.png,38.8141,0.0131,0.0080,8.1758 -Small,4x4,ldrs-rgba-02.png,34.8386,0.0161,0.0111,5.8855 -Small,5x5,hdr-rgb-00.hdr,29.4686,0.1105,0.0175,3.7464 -Small,5x5,ldr-rgb-00.png,34.3042,0.0157,0.0096,6.8132 -Small,5x5,ldr-rgb-01.png,36.1808,0.0130,0.0072,9.0495 -Small,5x5,ldr-rgb-02.png,31.0160,0.0171,0.0112,5.8280 -Small,5x5,ldr-rgb-03.png,42.6231,0.0086,0.0031,20.9590 -Small,5x5,ldr-rgb-04.png,37.2434,0.0120,0.0058,11.2738 -Small,5x5,ldr-rgb-05.png,33.1823,0.0193,0.0133,4.9123 -Small,5x5,ldr-rgb-06.png,31.0247,0.0170,0.0109,6.0080 -Small,5x5,ldr-rgb-07.png,35.1883,0.0174,0.0111,5.9282 -Small,5x5,ldr-rgb-08.png,40.0310,0.0102,0.0043,15.0692 -Small,5x5,ldr-rgb-09.png,37.2810,0.0123,0.0065,10.1211 -Small,5x5,ldr-rgb-10.png,40.1234,0.0053,0.0017,9.6303 -Small,5x5,ldr-rgba-00.png,32.0072,0.0194,0.0131,5.0197 -Small,5x5,ldr-rgba-01.png,35.1428,0.0136,0.0076,8.6792 -Small,5x5,ldr-rgba-02.png,31.1062,0.0176,0.0115,5.7017 -Small,5x5,ldr-xy-00.png,36.7258,0.0140,0.0050,13.1546 -Small,5x5,ldr-xy-01.png,39.8638,0.0145,0.0058,11.3958 -Small,5x5,ldr-xy-02.png,43.9171,0.0132,0.0045,14.6321 -Small,5x5,ldrs-rgba-00.png,32.0096,0.0196,0.0133,4.9279 -Small,5x5,ldrs-rgba-01.png,35.1497,0.0139,0.0078,8.3710 -Small,5x5,ldrs-rgba-02.png,31.1070,0.0178,0.0116,5.6711 -Small,6x6,hdr-rgb-00.hdr,26.9904,0.1131,0.0192,3.4221 -Small,6x6,ldr-rgb-00.png,31.5938,0.0186,0.0120,5.4431 -Small,6x6,ldr-rgb-01.png,32.8896,0.0156,0.0094,6.9890 -Small,6x6,ldr-rgb-02.png,27.4079,0.0204,0.0140,4.6769 -Small,6x6,ldr-rgb-03.png,40.4899,0.0093,0.0032,20.4036 -Small,6x6,ldr-rgb-04.png,33.9065,0.0140,0.0075,8.7781 -Small,6x6,ldr-rgb-05.png,29.9329,0.0229,0.0164,4.0024 -Small,6x6,ldr-rgb-06.png,27.4651,0.0202,0.0136,4.8146 -Small,6x6,ldr-rgb-07.png,32.8824,0.0179,0.0112,5.8613 -Small,6x6,ldr-rgb-08.png,37.6380,0.0108,0.0044,14.8880 -Small,6x6,ldr-rgb-09.png,33.4716,0.0140,0.0075,8.7078 -Small,6x6,ldr-rgb-10.png,36.6590,0.0062,0.0021,7.6532 -Small,6x6,ldr-rgba-00.png,29.4788,0.0229,0.0160,4.0919 -Small,6x6,ldr-rgba-01.png,32.0575,0.0159,0.0092,7.1406 -Small,6x6,ldr-rgba-02.png,27.8275,0.0207,0.0138,4.7500 -Small,6x6,ldr-xy-00.png,35.6827,0.0146,0.0051,12.8598 -Small,6x6,ldr-xy-01.png,37.1053,0.0162,0.0071,9.1684 -Small,6x6,ldr-xy-02.png,41.9446,0.0133,0.0042,15.5818 -Small,6x6,ldrs-rgba-00.png,29.4790,0.0231,0.0163,4.0152 -Small,6x6,ldrs-rgba-01.png,32.0640,0.0157,0.0091,7.1749 -Small,6x6,ldrs-rgba-02.png,27.8273,0.0209,0.0144,4.5451 -Small,8x8,hdr-rgb-00.hdr,23.7216,0.1240,0.0256,2.5609 -Small,8x8,ldr-rgb-00.png,27.9814,0.0261,0.0155,4.2408 -Small,8x8,ldr-rgb-01.png,28.7458,0.0226,0.0123,5.3207 -Small,8x8,ldr-rgb-02.png,23.0937,0.0303,0.0199,3.2868 -Small,8x8,ldr-rgb-03.png,37.2544,0.0137,0.0034,19.4123 -Small,8x8,ldr-rgb-04.png,29.3419,0.0214,0.0107,6.1061 -Small,8x8,ldr-rgb-05.png,25.7747,0.0327,0.0223,2.9325 -Small,8x8,ldr-rgb-06.png,23.1468,0.0304,0.0199,3.2967 -Small,8x8,ldr-rgb-07.png,29.6508,0.0214,0.0106,6.1850 -Small,8x8,ldr-rgb-08.png,34.2150,0.0157,0.0053,12.2911 -Small,8x8,ldr-rgb-09.png,28.6635,0.0221,0.0117,5.6201 -Small,8x8,ldr-rgb-10.png,31.9974,0.0110,0.0027,5.9155 -Small,8x8,ldr-rgba-00.png,25.3599,0.0312,0.0203,3.2268 -Small,8x8,ldr-rgba-01.png,28.2399,0.0236,0.0131,4.9924 -Small,8x8,ldr-rgba-02.png,23.9241,0.0309,0.0201,3.2576 -Small,8x8,ldr-xy-00.png,33.3965,0.0206,0.0071,9.2331 -Small,8x8,ldr-xy-01.png,34.2472,0.0219,0.0085,7.6651 -Small,8x8,ldr-xy-02.png,39.9005,0.0167,0.0030,21.5152 -Small,8x8,ldrs-rgba-00.png,25.3610,0.0315,0.0208,3.1511 -Small,8x8,ldrs-rgba-01.png,28.2419,0.0236,0.0131,4.9841 -Small,8x8,ldrs-rgba-02.png,23.9237,0.0309,0.0201,3.2552 -Small,12x12,hdr-rgb-00.hdr,20.5637,0.1398,0.0343,1.9107 -Small,12x12,ldr-rgb-00.png,23.7825,0.0297,0.0123,5.3481 -Small,12x12,ldr-rgb-01.png,24.7588,0.0253,0.0084,7.8028 -Small,12x12,ldr-rgb-02.png,19.2226,0.0391,0.0221,2.9719 -Small,12x12,ldr-rgb-03.png,33.2364,0.0198,0.0027,24.6571 -Small,12x12,ldr-rgb-04.png,24.5606,0.0257,0.0086,7.6338 -Small,12x12,ldr-rgb-05.png,21.4885,0.0354,0.0181,3.6280 -Small,12x12,ldr-rgb-06.png,19.2097,0.0404,0.0233,2.8078 -Small,12x12,ldr-rgb-07.png,25.3456,0.0248,0.0072,9.1110 -Small,12x12,ldr-rgb-08.png,30.1535,0.0211,0.0042,15.5298 -Small,12x12,ldr-rgb-09.png,23.7136,0.0291,0.0120,5.4532 -Small,12x12,ldr-rgb-10.png,27.3052,0.0176,0.0030,5.3577 -Small,12x12,ldr-rgba-00.png,21.3632,0.0385,0.0207,3.1658 -Small,12x12,ldr-rgba-01.png,24.4867,0.0271,0.0096,6.8218 -Small,12x12,ldr-rgba-02.png,20.1666,0.0444,0.0273,2.4036 -Small,12x12,ldr-xy-00.png,29.0651,0.0280,0.0064,10.2079 -Small,12x12,ldr-xy-01.png,30.4241,0.0270,0.0057,11.4290 -Small,12x12,ldr-xy-02.png,37.9951,0.0229,0.0019,34.7507 -Small,12x12,ldrs-rgba-00.png,21.3658,0.0390,0.0213,3.0769 -Small,12x12,ldrs-rgba-01.png,24.4885,0.0273,0.0098,6.7024 -Small,12x12,ldrs-rgba-02.png,20.1665,0.0446,0.0272,2.4081 -Small,3x3x3,ldr-l-00-3.dds,50.7551,0.0179,0.0116,22.5559 -Small,3x3x3,ldr-l-01-3.dds,53.8676,0.0090,0.0051,13.5348 -Small,6x6x6,ldr-l-00-3.dds,32.5264,0.0630,0.0405,6.4724 -Small,6x6x6,ldr-l-01-3.dds,40.7893,0.0366,0.0164,4.1969 diff --git a/Test/Images/Small/astc_reference-3.6-avx2_fastest_results.csv b/Test/Images/Small/astc_reference-3.6-avx2_fastest_results.csv deleted file mode 100644 index 0822f91..0000000 --- a/Test/Images/Small/astc_reference-3.6-avx2_fastest_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.2999,0.0997,0.0097,6.7375 -Small,4x4,ldr-rgb-00.png,37.0084,0.0102,0.0057,11.4614 -Small,4x4,ldr-rgb-01.png,39.4162,0.0097,0.0054,12.0980 -Small,4x4,ldr-rgb-02.png,34.6448,0.0122,0.0080,8.1675 -Small,4x4,ldr-rgb-03.png,45.3559,0.0066,0.0025,25.7618 -Small,4x4,ldr-rgb-04.png,41.6390,0.0086,0.0042,15.6706 -Small,4x4,ldr-rgb-05.png,36.7213,0.0119,0.0076,8.6516 -Small,4x4,ldr-rgb-06.png,34.6994,0.0118,0.0073,8.9249 -Small,4x4,ldr-rgb-07.png,37.1808,0.0122,0.0076,8.6767 -Small,4x4,ldr-rgb-08.png,42.6915,0.0077,0.0035,18.8531 -Small,4x4,ldr-rgb-09.png,41.6433,0.0086,0.0043,15.2617 -Small,4x4,ldr-rgb-10.png,43.8818,0.0034,0.0014,11.2494 -Small,4x4,ldr-rgba-00.png,34.5700,0.0118,0.0070,9.3985 -Small,4x4,ldr-rgba-01.png,38.5857,0.0101,0.0057,11.5953 -Small,4x4,ldr-rgba-02.png,34.5224,0.0127,0.0082,8.0018 -Small,4x4,ldr-xy-00.png,37.5264,0.0109,0.0041,15.9915 -Small,4x4,ldr-xy-01.png,43.8563,0.0112,0.0046,14.1763 -Small,4x4,ldr-xy-02.png,48.1786,0.0105,0.0034,19.0676 -Small,4x4,ldrs-rgba-00.png,34.5750,0.0118,0.0071,9.1942 -Small,4x4,ldrs-rgba-01.png,38.6025,0.0102,0.0057,11.4695 -Small,4x4,ldrs-rgba-02.png,34.5263,0.0125,0.0080,8.1675 -Small,5x5,hdr-rgb-00.hdr,28.8076,0.1032,0.0107,6.1191 -Small,5x5,ldr-rgb-00.png,33.4478,0.0110,0.0058,11.3840 -Small,5x5,ldr-rgb-01.png,35.9999,0.0099,0.0051,12.9287 -Small,5x5,ldr-rgb-02.png,30.8748,0.0129,0.0080,8.2412 -Small,5x5,ldr-rgb-03.png,42.2547,0.0071,0.0024,27.2291 -Small,5x5,ldr-rgb-04.png,36.9224,0.0097,0.0046,14.3285 -Small,5x5,ldr-rgb-05.png,32.6193,0.0137,0.0088,7.4610 -Small,5x5,ldr-rgb-06.png,30.8711,0.0132,0.0081,8.0977 -Small,5x5,ldr-rgb-07.png,34.2652,0.0126,0.0074,8.8756 -Small,5x5,ldr-rgb-08.png,39.3139,0.0081,0.0032,20.4477 -Small,5x5,ldr-rgb-09.png,36.9835,0.0094,0.0044,14.7277 -Small,5x5,ldr-rgb-10.png,39.7373,0.0041,0.0015,10.9460 -Small,5x5,ldr-rgba-00.png,30.7473,0.0127,0.0073,9.0145 -Small,5x5,ldr-rgba-01.png,34.9846,0.0112,0.0062,10.5548 -Small,5x5,ldr-rgba-02.png,31.0020,0.0142,0.0089,7.3289 -Small,5x5,ldr-xy-00.png,36.5568,0.0118,0.0038,17.1960 -Small,5x5,ldr-xy-01.png,38.8334,0.0119,0.0043,15.1531 -Small,5x5,ldr-xy-02.png,43.7233,0.0115,0.0036,18.3681 -Small,5x5,ldrs-rgba-00.png,30.7497,0.0129,0.0073,8.9738 -Small,5x5,ldrs-rgba-01.png,34.9913,0.0111,0.0060,10.8897 -Small,5x5,ldrs-rgba-02.png,31.0030,0.0142,0.0088,7.4854 -Small,6x6,hdr-rgb-00.hdr,26.7122,0.1034,0.0107,6.1220 -Small,6x6,ldr-rgb-00.png,31.1052,0.0119,0.0065,10.1088 -Small,6x6,ldr-rgb-01.png,32.7949,0.0109,0.0057,11.4997 -Small,6x6,ldr-rgb-02.png,27.3228,0.0141,0.0090,7.2956 -Small,6x6,ldr-rgb-03.png,40.2037,0.0073,0.0023,28.2854 -Small,6x6,ldr-rgb-04.png,33.7349,0.0104,0.0049,13.4652 -Small,6x6,ldr-rgb-05.png,29.5304,0.0145,0.0091,7.1978 -Small,6x6,ldr-rgb-06.png,27.3791,0.0143,0.0089,7.3727 -Small,6x6,ldr-rgb-07.png,32.0586,0.0125,0.0067,9.8537 -Small,6x6,ldr-rgb-08.png,37.0422,0.0082,0.0030,21.9990 -Small,6x6,ldr-rgb-09.png,33.2804,0.0105,0.0053,12.3797 -Small,6x6,ldr-rgb-10.png,36.4903,0.0046,0.0016,10.3810 -Small,6x6,ldr-rgba-00.png,28.4787,0.0138,0.0080,8.1503 -Small,6x6,ldr-rgba-01.png,31.9580,0.0121,0.0066,9.9417 -Small,6x6,ldr-rgba-02.png,27.7571,0.0148,0.0092,7.0997 -Small,6x6,ldr-xy-00.png,35.5281,0.0118,0.0039,16.9741 -Small,6x6,ldr-xy-01.png,36.2504,0.0123,0.0046,14.3278 -Small,6x6,ldr-xy-02.png,41.7327,0.0112,0.0031,20.9447 -Small,6x6,ldrs-rgba-00.png,28.4800,0.0136,0.0078,8.3924 -Small,6x6,ldrs-rgba-01.png,31.9643,0.0120,0.0064,10.2368 -Small,6x6,ldrs-rgba-02.png,27.7547,0.0148,0.0092,7.0980 -Small,8x8,hdr-rgb-00.hdr,23.5547,0.1126,0.0163,4.0226 -Small,8x8,ldr-rgb-00.png,27.6188,0.0183,0.0094,7.0092 -Small,8x8,ldr-rgb-01.png,28.6671,0.0169,0.0084,7.8188 -Small,8x8,ldr-rgb-02.png,23.0179,0.0217,0.0129,5.0634 -Small,8x8,ldr-rgb-03.png,37.0089,0.0113,0.0027,24.3621 -Small,8x8,ldr-rgb-04.png,29.0953,0.0164,0.0077,8.5036 -Small,8x8,ldr-rgb-05.png,25.5324,0.0223,0.0133,4.9365 -Small,8x8,ldr-rgb-06.png,23.0523,0.0223,0.0135,4.8692 -Small,8x8,ldr-rgb-07.png,29.3368,0.0166,0.0074,8.8983 -Small,8x8,ldr-rgb-08.png,33.7665,0.0124,0.0037,17.7788 -Small,8x8,ldr-rgb-09.png,28.4590,0.0160,0.0073,9.0230 -Small,8x8,ldr-rgb-10.png,31.8847,0.0088,0.0024,6.8560 -Small,8x8,ldr-rgba-00.png,24.9726,0.0210,0.0118,5.5638 -Small,8x8,ldr-rgba-01.png,28.1236,0.0179,0.0092,7.1375 -Small,8x8,ldr-rgba-02.png,23.8676,0.0232,0.0142,4.6120 -Small,8x8,ldr-xy-00.png,33.2085,0.0173,0.0051,12.7975 -Small,8x8,ldr-xy-01.png,33.9809,0.0175,0.0060,10.8433 -Small,8x8,ldr-xy-02.png,39.7786,0.0143,0.0026,25.2947 -Small,8x8,ldrs-rgba-00.png,24.9730,0.0213,0.0122,5.3635 -Small,8x8,ldrs-rgba-01.png,28.1260,0.0180,0.0089,7.3397 -Small,8x8,ldrs-rgba-02.png,23.8671,0.0230,0.0142,4.6302 -Small,12x12,hdr-rgb-00.hdr,20.4789,0.1228,0.0216,3.0361 -Small,12x12,ldr-rgb-00.png,23.6716,0.0212,0.0083,7.9017 -Small,12x12,ldr-rgb-01.png,24.7037,0.0187,0.0057,11.4138 -Small,12x12,ldr-rgb-02.png,19.1880,0.0277,0.0147,4.4494 -Small,12x12,ldr-rgb-03.png,33.1400,0.0152,0.0027,24.1206 -Small,12x12,ldr-rgb-04.png,24.3898,0.0192,0.0060,10.9282 -Small,12x12,ldr-rgb-05.png,21.3701,0.0254,0.0123,5.3118 -Small,12x12,ldr-rgb-06.png,19.1564,0.0286,0.0156,4.1878 -Small,12x12,ldr-rgb-07.png,25.2598,0.0191,0.0055,11.8359 -Small,12x12,ldr-rgb-08.png,29.9653,0.0161,0.0032,20.5824 -Small,12x12,ldr-rgb-09.png,23.5968,0.0213,0.0081,8.0560 -Small,12x12,ldr-rgb-10.png,27.2554,0.0128,0.0022,7.4844 -Small,12x12,ldr-rgba-00.png,21.1828,0.0267,0.0132,4.9634 -Small,12x12,ldr-rgba-01.png,24.4330,0.0207,0.0074,8.8453 -Small,12x12,ldr-rgba-02.png,20.1371,0.0322,0.0187,3.5059 -Small,12x12,ldr-xy-00.png,28.9405,0.0220,0.0050,12.9874 -Small,12x12,ldr-xy-01.png,29.6034,0.0214,0.0046,14.1639 -Small,12x12,ldr-xy-02.png,37.9716,0.0185,0.0019,33.7978 -Small,12x12,ldrs-rgba-00.png,21.1836,0.0270,0.0136,4.8288 -Small,12x12,ldrs-rgba-01.png,24.4339,0.0208,0.0078,8.4151 -Small,12x12,ldrs-rgba-02.png,20.1367,0.0319,0.0187,3.5140 -Small,3x3x3,ldr-l-00-3.dds,50.6012,0.0159,0.0104,25.1628 -Small,3x3x3,ldr-l-01-3.dds,53.7999,0.0075,0.0044,15.5367 -Small,6x6x6,ldr-l-00-3.dds,32.5074,0.0600,0.0394,6.6588 -Small,6x6x6,ldr-l-01-3.dds,40.7826,0.0340,0.0159,4.3448 diff --git a/Test/Images/Small/astc_reference-3.6-avx2_medium_results.csv b/Test/Images/Small/astc_reference-3.6-avx2_medium_results.csv deleted file mode 100644 index 3f12338..0000000 --- a/Test/Images/Small/astc_reference-3.6-avx2_medium_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.1340,0.1179,0.0259,2.5263 -Small,4x4,ldr-rgb-00.png,38.7318,0.0335,0.0275,2.3851 -Small,4x4,ldr-rgb-01.png,40.1460,0.0304,0.0247,2.6583 -Small,4x4,ldr-rgb-02.png,35.2180,0.0315,0.0259,2.5346 -Small,4x4,ldr-rgb-03.png,47.1925,0.0191,0.0136,4.8178 -Small,4x4,ldr-rgb-04.png,42.1729,0.0260,0.0201,3.2553 -Small,4x4,ldr-rgb-05.png,37.7672,0.0335,0.0277,2.3659 -Small,4x4,ldr-rgb-06.png,35.3468,0.0283,0.0224,2.9263 -Small,4x4,ldr-rgb-07.png,39.2464,0.0394,0.0330,1.9855 -Small,4x4,ldr-rgb-08.png,45.1732,0.0222,0.0165,3.9796 -Small,4x4,ldr-rgb-09.png,42.0914,0.0266,0.0209,3.1357 -Small,4x4,ldr-rgb-10.png,44.8767,0.0069,0.0035,4.6285 -Small,4x4,ldr-rgba-00.png,36.2349,0.0358,0.0296,2.2162 -Small,4x4,ldr-rgba-01.png,38.8941,0.0227,0.0168,3.9005 -Small,4x4,ldr-rgba-02.png,34.9204,0.0253,0.0192,3.4075 -Small,4x4,ldr-xy-00.png,37.7446,0.0236,0.0160,4.0957 -Small,4x4,ldr-xy-01.png,45.1462,0.0320,0.0247,2.6517 -Small,4x4,ldr-xy-02.png,50.9226,0.0382,0.0304,2.1593 -Small,4x4,ldrs-rgba-00.png,36.2418,0.0360,0.0296,2.2111 -Small,4x4,ldrs-rgba-01.png,38.9101,0.0233,0.0171,3.8289 -Small,4x4,ldrs-rgba-02.png,34.9259,0.0253,0.0194,3.3734 -Small,5x5,hdr-rgb-00.hdr,29.8514,0.1270,0.0328,1.9974 -Small,5x5,ldr-rgb-00.png,35.0732,0.0376,0.0301,2.1773 -Small,5x5,ldr-rgb-01.png,36.3975,0.0319,0.0247,2.6561 -Small,5x5,ldr-rgb-02.png,31.0670,0.0335,0.0261,2.5122 -Small,5x5,ldr-rgb-03.png,43.9478,0.0158,0.0086,7.5843 -Small,5x5,ldr-rgb-04.png,37.6667,0.0295,0.0222,2.9518 -Small,5x5,ldr-rgb-05.png,33.5193,0.0422,0.0347,1.8890 -Small,5x5,ldr-rgb-06.png,31.0773,0.0319,0.0244,2.6833 -Small,5x5,ldr-rgb-07.png,36.2042,0.0457,0.0380,1.7256 -Small,5x5,ldr-rgb-08.png,41.5462,0.0226,0.0153,4.2751 -Small,5x5,ldr-rgb-09.png,37.5873,0.0279,0.0206,3.1845 -Small,5x5,ldr-rgb-10.png,40.4902,0.0091,0.0042,3.9104 -Small,5x5,ldr-rgba-00.png,32.7858,0.0446,0.0367,1.7846 -Small,5x5,ldr-rgba-01.png,35.2722,0.0266,0.0191,3.4348 -Small,5x5,ldr-rgba-02.png,31.1225,0.0310,0.0234,2.7967 -Small,5x5,ldr-xy-00.png,37.0726,0.0247,0.0154,4.2446 -Small,5x5,ldr-xy-01.png,40.7191,0.0317,0.0227,2.8854 -Small,5x5,ldr-xy-02.png,49.0675,0.0259,0.0165,3.9832 -Small,5x5,ldrs-rgba-00.png,32.7887,0.0452,0.0371,1.7671 -Small,5x5,ldrs-rgba-01.png,35.2789,0.0270,0.0193,3.3965 -Small,5x5,ldrs-rgba-02.png,31.1234,0.0314,0.0238,2.7535 -Small,6x6,hdr-rgb-00.hdr,27.4769,0.1311,0.0355,1.8453 -Small,6x6,ldr-rgb-00.png,32.3560,0.0400,0.0318,2.0620 -Small,6x6,ldr-rgb-01.png,33.0687,0.0323,0.0246,2.6617 -Small,6x6,ldr-rgb-02.png,27.4381,0.0357,0.0278,2.3546 -Small,6x6,ldr-rgb-03.png,41.6538,0.0146,0.0071,9.2864 -Small,6x6,ldr-rgb-04.png,34.2059,0.0297,0.0217,3.0194 -Small,6x6,ldr-rgb-05.png,30.1377,0.0454,0.0372,1.7634 -Small,6x6,ldr-rgb-06.png,27.5024,0.0353,0.0271,2.4211 -Small,6x6,ldr-rgb-07.png,33.8577,0.0428,0.0343,1.9094 -Small,6x6,ldr-rgb-08.png,39.0752,0.0192,0.0114,5.7732 -Small,6x6,ldr-rgb-09.png,33.6699,0.0292,0.0212,3.0933 -Small,6x6,ldr-rgb-10.png,36.9333,0.0100,0.0045,3.6140 -Small,6x6,ldr-rgba-00.png,30.2558,0.0494,0.0407,1.6101 -Small,6x6,ldr-rgba-01.png,32.1716,0.0280,0.0200,3.2740 -Small,6x6,ldr-rgba-02.png,27.8426,0.0348,0.0267,2.4503 -Small,6x6,ldr-xy-00.png,36.2518,0.0235,0.0135,4.8384 -Small,6x6,ldr-xy-01.png,37.7318,0.0266,0.0172,3.8171 -Small,6x6,ldr-xy-02.png,46.0639,0.0217,0.0120,5.4796 -Small,6x6,ldrs-rgba-00.png,30.2570,0.0494,0.0409,1.6011 -Small,6x6,ldrs-rgba-01.png,32.1777,0.0283,0.0200,3.2699 -Small,6x6,ldrs-rgba-02.png,27.8427,0.0352,0.0270,2.4258 -Small,8x8,hdr-rgb-00.hdr,24.1157,0.1462,0.0450,1.4577 -Small,8x8,ldr-rgb-00.png,28.7123,0.0537,0.0418,1.5690 -Small,8x8,ldr-rgb-01.png,28.9240,0.0418,0.0305,2.1456 -Small,8x8,ldr-rgb-02.png,23.1517,0.0478,0.0363,1.8048 -Small,8x8,ldr-rgb-03.png,38.4615,0.0192,0.0080,8.2105 -Small,8x8,ldr-rgb-04.png,29.6546,0.0396,0.0280,2.3430 -Small,8x8,ldr-rgb-05.png,25.9295,0.0546,0.0431,1.5200 -Small,8x8,ldr-rgb-06.png,23.1918,0.0481,0.0362,1.8097 -Small,8x8,ldr-rgb-07.png,30.5823,0.0483,0.0363,1.8039 -Small,8x8,ldr-rgb-08.png,35.7743,0.0241,0.0126,5.2045 -Small,8x8,ldr-rgb-09.png,29.0115,0.0380,0.0266,2.4653 -Small,8x8,ldr-rgb-10.png,32.1619,0.0156,0.0064,2.5536 -Small,8x8,ldr-rgba-00.png,26.3940,0.0609,0.0486,1.3477 -Small,8x8,ldr-rgba-01.png,28.3383,0.0372,0.0255,2.5706 -Small,8x8,ldr-rgba-02.png,23.9368,0.0501,0.0385,1.7004 -Small,8x8,ldr-xy-00.png,34.0144,0.0347,0.0197,3.3198 -Small,8x8,ldr-xy-01.png,34.9127,0.0339,0.0195,3.3555 -Small,8x8,ldr-xy-02.png,41.7218,0.0262,0.0114,5.7357 -Small,8x8,ldrs-rgba-00.png,26.3943,0.0615,0.0492,1.3308 -Small,8x8,ldrs-rgba-01.png,28.3412,0.0373,0.0257,2.5515 -Small,8x8,ldrs-rgba-02.png,23.9363,0.0506,0.0386,1.6961 -Small,12x12,hdr-rgb-00.hdr,20.7645,0.1705,0.0619,1.0591 -Small,12x12,ldr-rgb-00.png,24.6670,0.0681,0.0475,1.3805 -Small,12x12,ldr-rgb-01.png,25.0227,0.0575,0.0379,1.7303 -Small,12x12,ldr-rgb-02.png,19.2621,0.0762,0.0563,1.1649 -Small,12x12,ldr-rgb-03.png,34.9308,0.0283,0.0085,7.6958 -Small,12x12,ldr-rgb-04.png,24.9126,0.0545,0.0349,1.8754 -Small,12x12,ldr-rgb-05.png,21.6505,0.0778,0.0576,1.1377 -Small,12x12,ldr-rgb-06.png,19.2451,0.0730,0.0530,1.2364 -Small,12x12,ldr-rgb-07.png,26.5693,0.0579,0.0374,1.7516 -Small,12x12,ldr-rgb-08.png,31.4927,0.0341,0.0138,4.7517 -Small,12x12,ldr-rgb-09.png,24.1078,0.0549,0.0354,1.8521 -Small,12x12,ldr-rgb-10.png,27.9831,0.0302,0.0126,1.2924 -Small,12x12,ldr-rgba-00.png,22.0878,0.0754,0.0552,1.1874 -Small,12x12,ldr-rgba-01.png,24.6267,0.0555,0.0351,1.8648 -Small,12x12,ldr-rgba-02.png,20.1804,0.0822,0.0619,1.0594 -Small,12x12,ldr-xy-00.png,30.0722,0.0469,0.0230,2.8522 -Small,12x12,ldr-xy-01.png,31.8391,0.0458,0.0222,2.9566 -Small,12x12,ldr-xy-02.png,38.5216,0.0293,0.0050,13.2077 -Small,12x12,ldrs-rgba-00.png,22.0882,0.0752,0.0546,1.2002 -Small,12x12,ldrs-rgba-01.png,24.6285,0.0556,0.0357,1.8362 -Small,12x12,ldrs-rgba-02.png,20.1803,0.0821,0.0618,1.0609 -Small,3x3x3,ldr-l-00-3.dds,51.9681,0.0240,0.0169,15.5243 -Small,3x3x3,ldr-l-01-3.dds,54.3395,0.0100,0.0052,13.3129 -Small,6x6x6,ldr-l-00-3.dds,32.9129,0.0739,0.0508,5.1617 -Small,6x6x6,ldr-l-01-3.dds,40.8871,0.0369,0.0163,4.2405 diff --git a/Test/Images/Small/astc_reference-3.6-avx2_thorough_results.csv b/Test/Images/Small/astc_reference-3.6-avx2_thorough_results.csv deleted file mode 100644 index 2402002..0000000 --- a/Test/Images/Small/astc_reference-3.6-avx2_thorough_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.3787,0.1460,0.0538,1.2176 -Small,4x4,ldr-rgb-00.png,39.1025,0.0650,0.0588,1.1145 -Small,4x4,ldr-rgb-01.png,40.3344,0.0634,0.0574,1.1420 -Small,4x4,ldr-rgb-02.png,35.3612,0.0595,0.0538,1.2188 -Small,4x4,ldr-rgb-03.png,47.6672,0.0590,0.0535,1.2256 -Small,4x4,ldr-rgb-04.png,42.3135,0.0584,0.0524,1.2507 -Small,4x4,ldr-rgb-05.png,37.9467,0.0673,0.0613,1.0692 -Small,4x4,ldr-rgb-06.png,35.4785,0.0559,0.0498,1.3165 -Small,4x4,ldr-rgb-07.png,39.8676,0.0735,0.0670,0.9779 -Small,4x4,ldr-rgb-08.png,45.7996,0.0564,0.0505,1.2987 -Small,4x4,ldr-rgb-09.png,42.2360,0.0622,0.0561,1.1684 -Small,4x4,ldr-rgb-10.png,44.9865,0.0107,0.0071,2.2809 -Small,4x4,ldr-rgba-00.png,36.7341,0.0670,0.0605,1.0830 -Small,4x4,ldr-rgba-01.png,39.0299,0.0547,0.0487,1.3449 -Small,4x4,ldr-rgba-02.png,34.9857,0.0543,0.0482,1.3603 -Small,4x4,ldr-xy-00.png,37.7552,0.0638,0.0561,1.1691 -Small,4x4,ldr-xy-01.png,45.2171,0.0713,0.0639,1.0249 -Small,4x4,ldr-xy-02.png,50.9992,0.0857,0.0778,0.8426 -Small,4x4,ldrs-rgba-00.png,36.7416,0.0675,0.0611,1.0729 -Small,4x4,ldrs-rgba-01.png,39.0514,0.0556,0.0494,1.3262 -Small,4x4,ldrs-rgba-02.png,34.9915,0.0544,0.0483,1.3559 -Small,5x5,hdr-rgb-00.hdr,30.2499,0.1593,0.0640,1.0237 -Small,5x5,ldr-rgb-00.png,35.3184,0.0780,0.0703,0.9318 -Small,5x5,ldr-rgb-01.png,36.4942,0.0745,0.0670,0.9778 -Small,5x5,ldr-rgb-02.png,31.1169,0.0710,0.0635,1.0328 -Small,5x5,ldr-rgb-03.png,44.4730,0.0685,0.0615,1.0657 -Small,5x5,ldr-rgb-04.png,37.8145,0.0707,0.0631,1.0384 -Small,5x5,ldr-rgb-05.png,33.6567,0.0798,0.0724,0.9055 -Small,5x5,ldr-rgb-06.png,31.1197,0.0677,0.0601,1.0904 -Small,5x5,ldr-rgb-07.png,36.7056,0.0885,0.0806,0.8127 -Small,5x5,ldr-rgb-08.png,42.2684,0.0653,0.0579,1.1310 -Small,5x5,ldr-rgb-09.png,37.6844,0.0730,0.0656,0.9996 -Small,5x5,ldr-rgb-10.png,40.6793,0.0145,0.0094,1.7368 -Small,5x5,ldr-rgba-00.png,33.1233,0.0816,0.0738,0.8886 -Small,5x5,ldr-rgba-01.png,35.3456,0.0673,0.0598,1.0963 -Small,5x5,ldr-rgba-02.png,31.1599,0.0670,0.0594,1.1034 -Small,5x5,ldr-xy-00.png,37.2902,0.0689,0.0596,1.0987 -Small,5x5,ldr-xy-01.png,41.5197,0.0845,0.0755,0.8684 -Small,5x5,ldr-xy-02.png,49.2647,0.0952,0.0856,0.7654 -Small,5x5,ldrs-rgba-00.png,33.1269,0.0828,0.0748,0.8760 -Small,5x5,ldrs-rgba-01.png,35.3541,0.0677,0.0601,1.0903 -Small,5x5,ldrs-rgba-02.png,31.1602,0.0676,0.0599,1.0946 -Small,6x6,hdr-rgb-00.hdr,27.6571,0.1700,0.0747,0.8769 -Small,6x6,ldr-rgb-00.png,32.6208,0.0899,0.0817,0.8018 -Small,6x6,ldr-rgb-01.png,33.1469,0.0829,0.0750,0.8733 -Small,6x6,ldr-rgb-02.png,27.4754,0.0811,0.0730,0.8975 -Small,6x6,ldr-rgb-03.png,42.5226,0.0574,0.0498,1.3170 -Small,6x6,ldr-rgb-04.png,34.3223,0.0801,0.0719,0.9111 -Small,6x6,ldr-rgb-05.png,30.2576,0.0907,0.0827,0.7924 -Small,6x6,ldr-rgb-06.png,27.5394,0.0784,0.0703,0.9323 -Small,6x6,ldr-rgb-07.png,34.3854,0.0954,0.0871,0.7528 -Small,6x6,ldr-rgb-08.png,39.8830,0.0569,0.0487,1.3461 -Small,6x6,ldr-rgb-09.png,33.7955,0.0776,0.0695,0.9436 -Small,6x6,ldr-rgb-10.png,37.1039,0.0177,0.0120,1.3545 -Small,6x6,ldr-rgba-00.png,30.5063,0.0954,0.0868,0.7550 -Small,6x6,ldr-rgba-01.png,32.2316,0.0789,0.0707,0.9263 -Small,6x6,ldr-rgba-02.png,27.8753,0.0815,0.0732,0.8949 -Small,6x6,ldr-xy-00.png,36.3838,0.0582,0.0481,1.3612 -Small,6x6,ldr-xy-01.png,38.0617,0.0824,0.0727,0.9011 -Small,6x6,ldr-xy-02.png,47.4738,0.1021,0.0920,0.7124 -Small,6x6,ldrs-rgba-00.png,30.5081,0.0951,0.0863,0.7590 -Small,6x6,ldrs-rgba-01.png,32.2377,0.0794,0.0712,0.9202 -Small,6x6,ldrs-rgba-02.png,27.8745,0.0817,0.0735,0.8920 -Small,8x8,hdr-rgb-00.hdr,24.3160,0.1959,0.0966,0.6786 -Small,8x8,ldr-rgb-00.png,28.9377,0.1142,0.1010,0.6492 -Small,8x8,ldr-rgb-01.png,28.9883,0.1019,0.0886,0.7399 -Small,8x8,ldr-rgb-02.png,23.1866,0.1062,0.0931,0.7043 -Small,8x8,ldr-rgb-03.png,39.3501,0.0393,0.0264,2.4834 -Small,8x8,ldr-rgb-04.png,29.7749,0.0947,0.0814,0.8054 -Small,8x8,ldr-rgb-05.png,26.0242,0.1114,0.0982,0.6674 -Small,8x8,ldr-rgb-06.png,23.2335,0.1062,0.0927,0.7073 -Small,8x8,ldr-rgb-07.png,31.1039,0.1068,0.0934,0.7018 -Small,8x8,ldr-rgb-08.png,36.4625,0.0551,0.0419,1.5655 -Small,8x8,ldr-rgb-09.png,29.1520,0.0819,0.0688,0.9526 -Small,8x8,ldr-rgb-10.png,32.3031,0.0266,0.0159,1.0210 -Small,8x8,ldr-rgba-00.png,26.6704,0.1200,0.1064,0.6159 -Small,8x8,ldr-rgba-01.png,28.3932,0.0943,0.0810,0.8086 -Small,8x8,ldr-rgba-02.png,23.9599,0.1129,0.0994,0.6596 -Small,8x8,ldr-xy-00.png,34.3120,0.0692,0.0539,1.2150 -Small,8x8,ldr-xy-01.png,35.2097,0.0717,0.0569,1.1515 -Small,8x8,ldr-xy-02.png,44.5878,0.0904,0.0751,0.8724 -Small,8x8,ldrs-rgba-00.png,26.6715,0.1208,0.1072,0.6111 -Small,8x8,ldrs-rgba-01.png,28.3959,0.0950,0.0817,0.8025 -Small,8x8,ldrs-rgba-02.png,23.9597,0.1132,0.0998,0.6566 -Small,12x12,hdr-rgb-00.hdr,21.0019,0.2375,0.1271,0.5158 -Small,12x12,ldr-rgb-00.png,25.0133,0.1454,0.1221,0.5367 -Small,12x12,ldr-rgb-01.png,25.1167,0.1226,0.0997,0.6572 -Small,12x12,ldr-rgb-02.png,19.2912,0.1467,0.1238,0.5295 -Small,12x12,ldr-rgb-03.png,36.1206,0.0493,0.0268,2.4446 -Small,12x12,ldr-rgb-04.png,25.0074,0.1225,0.0993,0.6599 -Small,12x12,ldr-rgb-05.png,21.7140,0.1455,0.1226,0.5345 -Small,12x12,ldr-rgb-06.png,19.2810,0.1436,0.1204,0.5445 -Small,12x12,ldr-rgb-07.png,27.0419,0.1313,0.1080,0.6068 -Small,12x12,ldr-rgb-08.png,32.3840,0.0654,0.0425,1.5438 -Small,12x12,ldr-rgb-09.png,24.3053,0.1157,0.0927,0.7071 -Small,12x12,ldr-rgb-10.png,28.1356,0.0468,0.0265,0.6144 -Small,12x12,ldr-rgba-00.png,22.7010,0.1541,0.1308,0.5012 -Small,12x12,ldr-rgba-01.png,24.7078,0.1159,0.0924,0.7092 -Small,12x12,ldr-rgba-02.png,20.1958,0.1509,0.1276,0.5134 -Small,12x12,ldr-xy-00.png,30.5742,0.0937,0.0687,0.9536 -Small,12x12,ldr-xy-01.png,32.1255,0.0721,0.0475,1.3803 -Small,12x12,ldr-xy-02.png,40.3053,0.0548,0.0300,2.1856 -Small,12x12,ldrs-rgba-00.png,22.7006,0.1559,0.1325,0.4948 -Small,12x12,ldrs-rgba-01.png,24.7093,0.1166,0.0933,0.7025 -Small,12x12,ldrs-rgba-02.png,20.1960,0.1511,0.1278,0.5129 -Small,3x3x3,ldr-l-00-3.dds,52.4159,0.0459,0.0385,6.8145 -Small,3x3x3,ldr-l-01-3.dds,55.3973,0.0203,0.0154,4.4842 -Small,6x6x6,ldr-l-00-3.dds,33.2725,0.1075,0.0821,3.1948 -Small,6x6x6,ldr-l-01-3.dds,41.5751,0.0410,0.0177,3.8888 diff --git a/Test/Images/Small/astc_reference-3.6-sse2_fast_results.csv b/Test/Images/Small/astc_reference-3.6-sse2_fast_results.csv deleted file mode 100644 index 14b3480..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse2_fast_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.6884,0.1115,0.0192,3.4199 -Small,4x4,ldr-rgb-00.png,38.1103,0.0173,0.0121,5.4103 -Small,4x4,ldr-rgb-01.png,39.8105,0.0153,0.0104,6.2726 -Small,4x4,ldr-rgb-02.png,35.0374,0.0215,0.0166,3.9439 -Small,4x4,ldr-rgb-03.png,45.9704,0.0088,0.0042,15.6706 -Small,4x4,ldr-rgb-04.png,41.9106,0.0127,0.0076,8.5803 -Small,4x4,ldr-rgb-05.png,37.2317,0.0207,0.0156,4.1951 -Small,4x4,ldr-rgb-06.png,35.2059,0.0205,0.0152,4.3082 -Small,4x4,ldr-rgb-07.png,38.0309,0.0217,0.0161,4.0587 -Small,4x4,ldr-rgb-08.png,43.6358,0.0109,0.0060,10.8446 -Small,4x4,ldr-rgb-09.png,41.8533,0.0126,0.0076,8.5792 -Small,4x4,ldr-rgb-10.png,44.3464,0.0046,0.0019,8.3752 -Small,4x4,ldr-rgba-00.png,35.5182,0.0208,0.0154,4.2625 -Small,4x4,ldr-rgba-01.png,38.7956,0.0147,0.0095,6.8833 -Small,4x4,ldr-rgba-02.png,34.8333,0.0190,0.0138,4.7645 -Small,4x4,ldr-xy-00.png,37.5697,0.0150,0.0073,8.9715 -Small,4x4,ldr-xy-01.png,44.1378,0.0162,0.0089,7.3960 -Small,4x4,ldr-xy-02.png,48.1786,0.0131,0.0052,12.6666 -Small,4x4,ldrs-rgba-00.png,35.5254,0.0210,0.0155,4.2254 -Small,4x4,ldrs-rgba-01.png,38.8141,0.0149,0.0097,6.7445 -Small,4x4,ldrs-rgba-02.png,34.8386,0.0189,0.0137,4.7704 -Small,5x5,hdr-rgb-00.hdr,29.4686,0.1171,0.0234,2.7990 -Small,5x5,ldr-rgb-00.png,34.3042,0.0189,0.0127,5.1522 -Small,5x5,ldr-rgb-01.png,36.1808,0.0154,0.0096,6.8567 -Small,5x5,ldr-rgb-02.png,31.0160,0.0215,0.0156,4.2010 -Small,5x5,ldr-rgb-03.png,42.6231,0.0093,0.0036,18.2510 -Small,5x5,ldr-rgb-04.png,37.2434,0.0141,0.0080,8.1605 -Small,5x5,ldr-rgb-05.png,33.1823,0.0239,0.0178,3.6842 -Small,5x5,ldr-rgb-06.png,31.0247,0.0211,0.0148,4.4200 -Small,5x5,ldr-rgb-07.png,35.1883,0.0209,0.0144,4.5609 -Small,5x5,ldr-rgb-08.png,40.0310,0.0116,0.0055,11.8748 -Small,5x5,ldr-rgb-09.png,37.2810,0.0139,0.0081,8.0709 -Small,5x5,ldr-rgb-10.png,40.1234,0.0055,0.0020,8.3231 -Small,5x5,ldr-rgba-00.png,32.0072,0.0238,0.0174,3.7613 -Small,5x5,ldr-rgba-01.png,35.1428,0.0163,0.0101,6.4810 -Small,5x5,ldr-rgba-02.png,31.1062,0.0217,0.0154,4.2672 -Small,5x5,ldr-xy-00.png,36.7258,0.0155,0.0061,10.7207 -Small,5x5,ldr-xy-01.png,39.8638,0.0163,0.0074,8.8456 -Small,5x5,ldr-xy-02.png,43.9171,0.0144,0.0056,11.7469 -Small,5x5,ldrs-rgba-00.png,32.0096,0.0240,0.0175,3.7496 -Small,5x5,ldrs-rgba-01.png,35.1497,0.0164,0.0102,6.4064 -Small,5x5,ldrs-rgba-02.png,31.1070,0.0217,0.0155,4.2385 -Small,6x6,hdr-rgb-00.hdr,26.9904,0.1216,0.0273,2.3970 -Small,6x6,ldr-rgb-00.png,31.5938,0.0235,0.0167,3.9293 -Small,6x6,ldr-rgb-01.png,32.8896,0.0190,0.0125,5.2311 -Small,6x6,ldr-rgb-02.png,27.4079,0.0263,0.0196,3.3364 -Small,6x6,ldr-rgb-03.png,40.4899,0.0105,0.0041,16.0588 -Small,6x6,ldr-rgb-04.png,33.9065,0.0166,0.0100,6.5413 -Small,6x6,ldr-rgb-05.png,29.9329,0.0298,0.0230,2.8438 -Small,6x6,ldr-rgb-06.png,27.4651,0.0262,0.0195,3.3579 -Small,6x6,ldr-rgb-07.png,32.8824,0.0224,0.0155,4.2393 -Small,6x6,ldr-rgb-08.png,37.6380,0.0123,0.0060,10.9574 -Small,6x6,ldr-rgb-09.png,33.4716,0.0169,0.0105,6.2707 -Small,6x6,ldr-rgb-10.png,36.6590,0.0067,0.0026,6.2114 -Small,6x6,ldr-rgba-00.png,29.4788,0.0293,0.0222,2.9547 -Small,6x6,ldr-rgba-01.png,32.0575,0.0195,0.0128,5.1171 -Small,6x6,ldr-rgba-02.png,27.8275,0.0267,0.0199,3.2868 -Small,6x6,ldr-xy-00.png,35.6827,0.0165,0.0068,9.6195 -Small,6x6,ldr-xy-01.png,37.1053,0.0189,0.0099,6.6005 -Small,6x6,ldr-xy-02.png,41.9446,0.0146,0.0053,12.3864 -Small,6x6,ldrs-rgba-00.png,29.4790,0.0297,0.0223,2.9354 -Small,6x6,ldrs-rgba-01.png,32.0640,0.0196,0.0127,5.1575 -Small,6x6,ldrs-rgba-02.png,27.8273,0.0269,0.0201,3.2610 -Small,8x8,hdr-rgb-00.hdr,23.7216,0.1376,0.0383,1.7105 -Small,8x8,ldr-rgb-00.png,27.9814,0.0327,0.0219,2.9978 -Small,8x8,ldr-rgb-01.png,28.7458,0.0279,0.0177,3.7035 -Small,8x8,ldr-rgb-02.png,23.0937,0.0395,0.0287,2.2857 -Small,8x8,ldr-rgb-03.png,37.2544,0.0148,0.0045,14.5731 -Small,8x8,ldr-rgb-04.png,29.3419,0.0261,0.0156,4.2086 -Small,8x8,ldr-rgb-05.png,25.7747,0.0431,0.0325,2.0139 -Small,8x8,ldr-rgb-06.png,23.1468,0.0395,0.0288,2.2749 -Small,8x8,ldr-rgb-07.png,29.6508,0.0261,0.0152,4.3195 -Small,8x8,ldr-rgb-08.png,34.2150,0.0179,0.0075,8.7302 -Small,8x8,ldr-rgb-09.png,28.6635,0.0278,0.0174,3.7649 -Small,8x8,ldr-rgb-10.png,31.9974,0.0115,0.0034,4.8152 -Small,8x8,ldr-rgba-00.png,25.3599,0.0403,0.0292,2.2446 -Small,8x8,ldr-rgba-01.png,28.2399,0.0298,0.0189,3.4703 -Small,8x8,ldr-rgba-02.png,23.9241,0.0403,0.0294,2.2322 -Small,8x8,ldr-xy-00.png,33.3965,0.0239,0.0101,6.4670 -Small,8x8,ldr-xy-01.png,34.2472,0.0254,0.0120,5.4659 -Small,8x8,ldr-xy-02.png,39.9005,0.0176,0.0039,16.8823 -Small,8x8,ldrs-rgba-00.png,25.3610,0.0406,0.0294,2.2276 -Small,8x8,ldrs-rgba-01.png,28.2419,0.0296,0.0190,3.4522 -Small,8x8,ldrs-rgba-02.png,23.9237,0.0405,0.0297,2.2089 -Small,12x12,hdr-rgb-00.hdr,20.5637,0.1572,0.0515,1.2736 -Small,12x12,ldr-rgb-00.png,23.7825,0.0345,0.0170,3.8539 -Small,12x12,ldr-rgb-01.png,24.7588,0.0286,0.0116,5.6706 -Small,12x12,ldr-rgb-02.png,19.2226,0.0491,0.0315,2.0796 -Small,12x12,ldr-rgb-03.png,33.2364,0.0203,0.0032,20.4995 -Small,12x12,ldr-rgb-04.png,24.5606,0.0291,0.0116,5.6331 -Small,12x12,ldr-rgb-05.png,21.4885,0.0439,0.0268,2.4479 -Small,12x12,ldr-rgb-06.png,19.2097,0.0511,0.0334,1.9615 -Small,12x12,ldr-rgb-07.png,25.3456,0.0275,0.0100,6.5510 -Small,12x12,ldr-rgb-08.png,30.1535,0.0224,0.0049,13.4382 -Small,12x12,ldr-rgb-09.png,23.7136,0.0344,0.0171,3.8218 -Small,12x12,ldr-rgb-10.png,27.3052,0.0187,0.0041,3.9581 -Small,12x12,ldr-rgba-00.png,21.3632,0.0478,0.0296,2.2128 -Small,12x12,ldr-rgba-01.png,24.4867,0.0312,0.0140,4.6822 -Small,12x12,ldr-rgba-02.png,20.1666,0.0568,0.0392,1.6700 -Small,12x12,ldr-xy-00.png,29.0651,0.0302,0.0088,7.4195 -Small,12x12,ldr-xy-01.png,30.4241,0.0293,0.0081,8.1349 -Small,12x12,ldr-xy-02.png,37.9951,0.0235,0.0023,28.2100 -Small,12x12,ldrs-rgba-00.png,21.3658,0.0476,0.0300,2.1875 -Small,12x12,ldrs-rgba-01.png,24.4885,0.0316,0.0145,4.5250 -Small,12x12,ldrs-rgba-02.png,20.1665,0.0568,0.0393,1.6667 -Small,3x3x3,ldr-l-00-3.dds,50.7551,0.0237,0.0170,15.4639 -Small,3x3x3,ldr-l-01-3.dds,53.8676,0.0112,0.0072,9.5657 -Small,6x6x6,ldr-l-00-3.dds,32.5264,0.0908,0.0675,3.8859 -Small,6x6x6,ldr-l-01-3.dds,40.7893,0.0464,0.0260,2.6471 diff --git a/Test/Images/Small/astc_reference-3.6-sse2_fastest_results.csv b/Test/Images/Small/astc_reference-3.6-sse2_fastest_results.csv deleted file mode 100644 index ee5a446..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse2_fastest_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.2999,0.1039,0.0122,5.3631 -Small,4x4,ldr-rgb-00.png,37.0084,0.0118,0.0073,9.0109 -Small,4x4,ldr-rgb-01.png,39.4162,0.0112,0.0069,9.4626 -Small,4x4,ldr-rgb-02.png,34.6448,0.0145,0.0103,6.3925 -Small,4x4,ldr-rgb-03.png,45.3559,0.0074,0.0033,20.1597 -Small,4x4,ldr-rgb-04.png,41.6390,0.0098,0.0053,12.4763 -Small,4x4,ldr-rgb-05.png,36.7213,0.0144,0.0100,6.5282 -Small,4x4,ldr-rgb-06.png,34.6994,0.0144,0.0098,6.6833 -Small,4x4,ldr-rgb-07.png,37.1808,0.0143,0.0095,6.9307 -Small,4x4,ldr-rgb-08.png,42.6915,0.0087,0.0044,14.8880 -Small,4x4,ldr-rgb-09.png,41.6433,0.0099,0.0054,12.1252 -Small,4x4,ldr-rgb-10.png,43.8818,0.0038,0.0018,8.9361 -Small,4x4,ldr-rgba-00.png,34.5700,0.0135,0.0088,7.4754 -Small,4x4,ldr-rgba-01.png,38.5857,0.0119,0.0072,9.1086 -Small,4x4,ldr-rgba-02.png,34.5224,0.0149,0.0102,6.4466 -Small,4x4,ldr-xy-00.png,37.5264,0.0122,0.0053,12.3419 -Small,4x4,ldr-xy-01.png,43.8563,0.0128,0.0061,10.7399 -Small,4x4,ldr-xy-02.png,48.1786,0.0116,0.0045,14.5377 -Small,4x4,ldrs-rgba-00.png,34.5750,0.0137,0.0087,7.5278 -Small,4x4,ldrs-rgba-01.png,38.6025,0.0120,0.0073,8.9493 -Small,4x4,ldrs-rgba-02.png,34.5263,0.0148,0.0102,6.3974 -Small,5x5,hdr-rgb-00.hdr,28.8076,0.1070,0.0146,4.4838 -Small,5x5,ldr-rgb-00.png,33.4478,0.0129,0.0076,8.6198 -Small,5x5,ldr-rgb-01.png,35.9999,0.0119,0.0069,9.5074 -Small,5x5,ldr-rgb-02.png,30.8748,0.0160,0.0110,5.9740 -Small,5x5,ldr-rgb-03.png,42.2547,0.0078,0.0031,20.8241 -Small,5x5,ldr-rgb-04.png,36.9224,0.0116,0.0064,10.2708 -Small,5x5,ldr-rgb-05.png,32.6193,0.0167,0.0116,5.6717 -Small,5x5,ldr-rgb-06.png,30.8711,0.0161,0.0108,6.0598 -Small,5x5,ldr-rgb-07.png,34.2652,0.0152,0.0098,6.7099 -Small,5x5,ldr-rgb-08.png,39.3139,0.0091,0.0040,16.2342 -Small,5x5,ldr-rgb-09.png,36.9835,0.0112,0.0061,10.7880 -Small,5x5,ldr-rgb-10.png,39.7373,0.0043,0.0016,9.8873 -Small,5x5,ldr-rgba-00.png,30.7473,0.0153,0.0097,6.7724 -Small,5x5,ldr-rgba-01.png,34.9846,0.0132,0.0081,8.0740 -Small,5x5,ldr-rgba-02.png,31.0020,0.0171,0.0119,5.5113 -Small,5x5,ldr-xy-00.png,36.5568,0.0132,0.0049,13.3042 -Small,5x5,ldr-xy-01.png,38.8334,0.0133,0.0054,12.0518 -Small,5x5,ldr-xy-02.png,43.7233,0.0123,0.0044,14.7967 -Small,5x5,ldrs-rgba-00.png,30.7497,0.0154,0.0099,6.6527 -Small,5x5,ldrs-rgba-01.png,34.9913,0.0136,0.0082,7.9728 -Small,5x5,ldrs-rgba-02.png,31.0030,0.0173,0.0120,5.4396 -Small,6x6,hdr-rgb-00.hdr,26.7122,0.1078,0.0151,4.3434 -Small,6x6,ldr-rgb-00.png,31.1052,0.0142,0.0087,7.5720 -Small,6x6,ldr-rgb-01.png,32.7949,0.0132,0.0078,8.4443 -Small,6x6,ldr-rgb-02.png,27.3228,0.0178,0.0126,5.2050 -Small,6x6,ldr-rgb-03.png,40.2037,0.0080,0.0029,22.7869 -Small,6x6,ldr-rgb-04.png,33.7349,0.0123,0.0070,9.4136 -Small,6x6,ldr-rgb-05.png,29.5304,0.0183,0.0129,5.0634 -Small,6x6,ldr-rgb-06.png,27.3791,0.0178,0.0122,5.3604 -Small,6x6,ldr-rgb-07.png,32.0586,0.0151,0.0095,6.8949 -Small,6x6,ldr-rgb-08.png,37.0422,0.0091,0.0038,17.1199 -Small,6x6,ldr-rgb-09.png,33.2804,0.0122,0.0067,9.7278 -Small,6x6,ldr-rgb-10.png,36.4903,0.0049,0.0019,8.5743 -Small,6x6,ldr-rgba-00.png,28.4787,0.0167,0.0109,6.0185 -Small,6x6,ldr-rgba-01.png,31.9580,0.0147,0.0091,7.1899 -Small,6x6,ldr-rgba-02.png,27.7571,0.0187,0.0129,5.0775 -Small,6x6,ldr-xy-00.png,35.5281,0.0135,0.0051,12.8881 -Small,6x6,ldr-xy-01.png,36.2504,0.0142,0.0062,10.5076 -Small,6x6,ldr-xy-02.png,41.7327,0.0122,0.0040,16.5579 -Small,6x6,ldrs-rgba-00.png,28.4800,0.0168,0.0110,5.9747 -Small,6x6,ldrs-rgba-01.png,31.9643,0.0147,0.0092,7.1151 -Small,6x6,ldrs-rgba-02.png,27.7547,0.0186,0.0128,5.1160 -Small,8x8,hdr-rgb-00.hdr,23.5547,0.1194,0.0234,2.8026 -Small,8x8,ldr-rgb-00.png,27.6188,0.0219,0.0129,5.0650 -Small,8x8,ldr-rgb-01.png,28.6671,0.0202,0.0117,5.5932 -Small,8x8,ldr-rgb-02.png,23.0179,0.0277,0.0190,3.4580 -Small,8x8,ldr-rgb-03.png,37.0089,0.0120,0.0035,18.5228 -Small,8x8,ldr-rgb-04.png,29.0953,0.0196,0.0108,6.0767 -Small,8x8,ldr-rgb-05.png,25.5324,0.0280,0.0189,3.4629 -Small,8x8,ldr-rgb-06.png,23.0523,0.0284,0.0191,3.4260 -Small,8x8,ldr-rgb-07.png,29.3368,0.0198,0.0105,6.2410 -Small,8x8,ldr-rgb-08.png,33.7665,0.0139,0.0049,13.4850 -Small,8x8,ldr-rgb-09.png,28.4590,0.0193,0.0105,6.2617 -Small,8x8,ldr-rgb-10.png,31.8847,0.0090,0.0027,6.0655 -Small,8x8,ldr-rgba-00.png,24.9726,0.0263,0.0169,3.8667 -Small,8x8,ldr-rgba-01.png,28.1236,0.0218,0.0125,5.2341 -Small,8x8,ldr-rgba-02.png,23.8676,0.0289,0.0197,3.3199 -Small,8x8,ldr-xy-00.png,33.2085,0.0195,0.0073,9.0245 -Small,8x8,ldr-xy-01.png,33.9809,0.0198,0.0081,8.1207 -Small,8x8,ldr-xy-02.png,39.7786,0.0150,0.0032,20.2697 -Small,8x8,ldrs-rgba-00.png,24.9730,0.0260,0.0167,3.9354 -Small,8x8,ldrs-rgba-01.png,28.1260,0.0218,0.0127,5.1542 -Small,8x8,ldrs-rgba-02.png,23.8671,0.0290,0.0199,3.2905 -Small,12x12,hdr-rgb-00.hdr,20.4789,0.1335,0.0315,2.0777 -Small,12x12,ldr-rgb-00.png,23.6716,0.0248,0.0117,5.6119 -Small,12x12,ldr-rgb-01.png,24.7037,0.0212,0.0084,7.7915 -Small,12x12,ldr-rgb-02.png,19.1880,0.0342,0.0212,3.0928 -Small,12x12,ldr-rgb-03.png,33.1400,0.0157,0.0031,20.8446 -Small,12x12,ldr-rgb-04.png,24.3898,0.0216,0.0087,7.5414 -Small,12x12,ldr-rgb-05.png,21.3701,0.0309,0.0176,3.7255 -Small,12x12,ldr-rgb-06.png,19.1564,0.0362,0.0226,2.9042 -Small,12x12,ldr-rgb-07.png,25.2598,0.0213,0.0077,8.4737 -Small,12x12,ldr-rgb-08.png,29.9653,0.0170,0.0042,15.5439 -Small,12x12,ldr-rgb-09.png,23.5968,0.0247,0.0116,5.6496 -Small,12x12,ldr-rgb-10.png,27.2554,0.0138,0.0032,5.0754 -Small,12x12,ldr-rgba-00.png,21.1828,0.0323,0.0186,3.5231 -Small,12x12,ldr-rgba-01.png,24.4330,0.0239,0.0104,6.2816 -Small,12x12,ldr-rgba-02.png,20.1371,0.0406,0.0271,2.4215 -Small,12x12,ldr-xy-00.png,28.9405,0.0241,0.0071,9.2071 -Small,12x12,ldr-xy-01.png,29.6034,0.0227,0.0063,10.3435 -Small,12x12,ldr-xy-02.png,37.9716,0.0188,0.0022,29.5727 -Small,12x12,ldrs-rgba-00.png,21.1836,0.0325,0.0189,3.4613 -Small,12x12,ldrs-rgba-01.png,24.4339,0.0241,0.0107,6.1163 -Small,12x12,ldrs-rgba-02.png,20.1367,0.0405,0.0271,2.4223 -Small,3x3x3,ldr-l-00-3.dds,50.6012,0.0210,0.0150,17.4379 -Small,3x3x3,ldr-l-01-3.dds,53.7999,0.0097,0.0065,10.6278 -Small,6x6x6,ldr-l-00-3.dds,32.5074,0.0872,0.0658,3.9842 -Small,6x6x6,ldr-l-01-3.dds,40.7826,0.0439,0.0255,2.7029 diff --git a/Test/Images/Small/astc_reference-3.6-sse2_medium_results.csv b/Test/Images/Small/astc_reference-3.6-sse2_medium_results.csv deleted file mode 100644 index 9b2f333..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse2_medium_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.1340,0.1279,0.0350,1.8729 -Small,4x4,ldr-rgb-00.png,38.7318,0.0421,0.0361,1.8164 -Small,4x4,ldr-rgb-01.png,40.1460,0.0391,0.0334,1.9646 -Small,4x4,ldr-rgb-02.png,35.2180,0.0407,0.0349,1.8779 -Small,4x4,ldr-rgb-03.png,47.1925,0.0241,0.0186,3.5295 -Small,4x4,ldr-rgb-04.png,42.1729,0.0334,0.0274,2.3937 -Small,4x4,ldr-rgb-05.png,37.7672,0.0435,0.0376,1.7432 -Small,4x4,ldr-rgb-06.png,35.3468,0.0366,0.0305,2.1457 -Small,4x4,ldr-rgb-07.png,39.2464,0.0506,0.0442,1.4819 -Small,4x4,ldr-rgb-08.png,45.1732,0.0282,0.0224,2.9244 -Small,4x4,ldr-rgb-09.png,42.0914,0.0342,0.0282,2.3269 -Small,4x4,ldr-rgb-10.png,44.8767,0.0079,0.0044,3.7022 -Small,4x4,ldr-rgba-00.png,36.2349,0.0458,0.0395,1.6588 -Small,4x4,ldr-rgba-01.png,38.8941,0.0283,0.0224,2.9266 -Small,4x4,ldr-rgba-02.png,34.9204,0.0321,0.0261,2.5156 -Small,4x4,ldr-xy-00.png,37.7446,0.0288,0.0211,3.1110 -Small,4x4,ldr-xy-01.png,45.1462,0.0398,0.0323,2.0269 -Small,4x4,ldr-xy-02.png,50.9226,0.0478,0.0398,1.6482 -Small,4x4,ldrs-rgba-00.png,36.2418,0.0465,0.0401,1.6357 -Small,4x4,ldrs-rgba-01.png,38.9101,0.0289,0.0228,2.8793 -Small,4x4,ldrs-rgba-02.png,34.9259,0.0326,0.0265,2.4741 -Small,5x5,hdr-rgb-00.hdr,29.8514,0.1424,0.0478,1.3714 -Small,5x5,ldr-rgb-00.png,35.0732,0.0515,0.0437,1.4991 -Small,5x5,ldr-rgb-01.png,36.3975,0.0436,0.0360,1.8218 -Small,5x5,ldr-rgb-02.png,31.0670,0.0459,0.0384,1.7070 -Small,5x5,ldr-rgb-03.png,43.9478,0.0193,0.0122,5.3551 -Small,5x5,ldr-rgb-04.png,37.6667,0.0401,0.0325,2.0193 -Small,5x5,ldr-rgb-05.png,33.5193,0.0593,0.0516,1.2694 -Small,5x5,ldr-rgb-06.png,31.0773,0.0436,0.0360,1.8196 -Small,5x5,ldr-rgb-07.png,36.2042,0.0635,0.0556,1.1785 -Small,5x5,ldr-rgb-08.png,41.5462,0.0291,0.0217,3.0183 -Small,5x5,ldr-rgb-09.png,37.5873,0.0373,0.0300,2.1850 -Small,5x5,ldr-rgb-10.png,40.4902,0.0103,0.0054,3.0329 -Small,5x5,ldr-rgba-00.png,32.7858,0.0608,0.0530,1.2363 -Small,5x5,ldr-rgba-01.png,35.2722,0.0352,0.0276,2.3705 -Small,5x5,ldr-rgba-02.png,31.1225,0.0419,0.0344,1.9064 -Small,5x5,ldr-xy-00.png,37.0726,0.0314,0.0220,2.9753 -Small,5x5,ldr-xy-01.png,40.7191,0.0418,0.0325,2.0150 -Small,5x5,ldr-xy-02.png,49.0675,0.0329,0.0231,2.8332 -Small,5x5,ldrs-rgba-00.png,32.7887,0.0625,0.0547,1.1983 -Small,5x5,ldrs-rgba-01.png,35.2789,0.0358,0.0280,2.3378 -Small,5x5,ldrs-rgba-02.png,31.1234,0.0422,0.0346,1.8950 -Small,6x6,hdr-rgb-00.hdr,27.4769,0.1489,0.0534,1.2276 -Small,6x6,ldr-rgb-00.png,32.3560,0.0546,0.0465,1.4083 -Small,6x6,ldr-rgb-01.png,33.0687,0.0445,0.0367,1.7867 -Small,6x6,ldr-rgb-02.png,27.4381,0.0499,0.0416,1.5756 -Small,6x6,ldr-rgb-03.png,41.6538,0.0174,0.0096,6.8473 -Small,6x6,ldr-rgb-04.png,34.2059,0.0398,0.0316,2.0710 -Small,6x6,ldr-rgb-05.png,30.1377,0.0642,0.0561,1.1675 -Small,6x6,ldr-rgb-06.png,27.5024,0.0487,0.0405,1.6198 -Small,6x6,ldr-rgb-07.png,33.8577,0.0600,0.0516,1.2702 -Small,6x6,ldr-rgb-08.png,39.0752,0.0239,0.0161,4.0784 -Small,6x6,ldr-rgb-09.png,33.6699,0.0389,0.0309,2.1237 -Small,6x6,ldr-rgb-10.png,36.9333,0.0116,0.0060,2.7120 -Small,6x6,ldr-rgba-00.png,30.2558,0.0679,0.0596,1.1001 -Small,6x6,ldr-rgba-01.png,32.1716,0.0378,0.0296,2.2150 -Small,6x6,ldr-rgba-02.png,27.8426,0.0480,0.0398,1.6463 -Small,6x6,ldr-xy-00.png,36.2518,0.0299,0.0197,3.3289 -Small,6x6,ldr-xy-01.png,37.7318,0.0341,0.0243,2.7022 -Small,6x6,ldr-xy-02.png,46.0639,0.0262,0.0161,4.0683 -Small,6x6,ldrs-rgba-00.png,30.2570,0.0694,0.0610,1.0736 -Small,6x6,ldrs-rgba-01.png,32.1777,0.0380,0.0297,2.2032 -Small,6x6,ldrs-rgba-02.png,27.8427,0.0479,0.0398,1.6449 -Small,8x8,hdr-rgb-00.hdr,24.1157,0.1696,0.0700,0.9368 -Small,8x8,ldr-rgb-00.png,28.7123,0.0743,0.0623,1.0512 -Small,8x8,ldr-rgb-01.png,28.9240,0.0576,0.0461,1.4225 -Small,8x8,ldr-rgb-02.png,23.1517,0.0677,0.0560,1.1703 -Small,8x8,ldr-rgb-03.png,38.4615,0.0226,0.0115,5.7217 -Small,8x8,ldr-rgb-04.png,29.6546,0.0549,0.0429,1.5285 -Small,8x8,ldr-rgb-05.png,25.9295,0.0771,0.0654,1.0019 -Small,8x8,ldr-rgb-06.png,23.1918,0.0670,0.0554,1.1836 -Small,8x8,ldr-rgb-07.png,30.5823,0.0669,0.0549,1.1928 -Small,8x8,ldr-rgb-08.png,35.7743,0.0302,0.0187,3.4968 -Small,8x8,ldr-rgb-09.png,29.0115,0.0511,0.0395,1.6584 -Small,8x8,ldr-rgb-10.png,32.1619,0.0185,0.0090,1.7986 -Small,8x8,ldr-rgba-00.png,26.3940,0.0861,0.0741,0.8849 -Small,8x8,ldr-rgba-01.png,28.3383,0.0507,0.0388,1.6886 -Small,8x8,ldr-rgba-02.png,23.9368,0.0707,0.0588,1.1143 -Small,8x8,ldr-xy-00.png,34.0144,0.0441,0.0291,2.2536 -Small,8x8,ldr-xy-01.png,34.9127,0.0433,0.0286,2.2919 -Small,8x8,ldr-xy-02.png,41.7218,0.0312,0.0162,4.0404 -Small,8x8,ldrs-rgba-00.png,26.3943,0.0858,0.0735,0.8910 -Small,8x8,ldrs-rgba-01.png,28.3412,0.0508,0.0389,1.6851 -Small,8x8,ldrs-rgba-02.png,23.9363,0.0710,0.0592,1.1077 -Small,12x12,hdr-rgb-00.hdr,20.7645,0.1993,0.0920,0.7123 -Small,12x12,ldr-rgb-00.png,24.6670,0.0911,0.0707,0.9266 -Small,12x12,ldr-rgb-01.png,25.0227,0.0778,0.0578,1.1329 -Small,12x12,ldr-rgb-02.png,19.2621,0.1046,0.0845,0.7752 -Small,12x12,ldr-rgb-03.png,34.9308,0.0312,0.0120,5.4654 -Small,12x12,ldr-rgb-04.png,24.9126,0.0718,0.0519,1.2637 -Small,12x12,ldr-rgb-05.png,21.6505,0.1057,0.0858,0.7640 -Small,12x12,ldr-rgb-06.png,19.2451,0.1013,0.0812,0.8068 -Small,12x12,ldr-rgb-07.png,26.5693,0.0767,0.0564,1.1621 -Small,12x12,ldr-rgb-08.png,31.4927,0.0400,0.0198,3.3163 -Small,12x12,ldr-rgb-09.png,24.1078,0.0731,0.0532,1.2311 -Small,12x12,ldr-rgb-10.png,27.9831,0.0364,0.0188,0.8651 -Small,12x12,ldr-rgba-00.png,22.0878,0.1026,0.0819,0.8001 -Small,12x12,ldr-rgba-01.png,24.6267,0.0741,0.0540,1.2146 -Small,12x12,ldr-rgba-02.png,20.1804,0.1108,0.0905,0.7244 -Small,12x12,ldr-xy-00.png,30.0722,0.0574,0.0332,1.9725 -Small,12x12,ldr-xy-01.png,31.8391,0.0563,0.0324,2.0225 -Small,12x12,ldr-xy-02.png,38.5216,0.0308,0.0064,10.1939 -Small,12x12,ldrs-rgba-00.png,22.0882,0.1030,0.0825,0.7947 -Small,12x12,ldrs-rgba-01.png,24.6285,0.0739,0.0537,1.2206 -Small,12x12,ldrs-rgba-02.png,20.1803,0.1108,0.0904,0.7246 -Small,3x3x3,ldr-l-00-3.dds,51.9681,0.0322,0.0246,10.6576 -Small,3x3x3,ldr-l-01-3.dds,54.3395,0.0125,0.0076,9.0376 -Small,6x6x6,ldr-l-00-3.dds,32.9129,0.1058,0.0826,3.1733 -Small,6x6x6,ldr-l-01-3.dds,40.8871,0.0467,0.0260,2.6486 diff --git a/Test/Images/Small/astc_reference-3.6-sse2_thorough_results.csv b/Test/Images/Small/astc_reference-3.6-sse2_thorough_results.csv deleted file mode 100644 index 1789210..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse2_thorough_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.3787,0.1650,0.0719,0.9109 -Small,4x4,ldr-rgb-00.png,39.1025,0.0850,0.0788,0.8312 -Small,4x4,ldr-rgb-01.png,40.3344,0.0839,0.0780,0.8397 -Small,4x4,ldr-rgb-02.png,35.3612,0.0789,0.0728,0.9005 -Small,4x4,ldr-rgb-03.png,47.6672,0.0791,0.0735,0.8919 -Small,4x4,ldr-rgb-04.png,42.3135,0.0766,0.0705,0.9302 -Small,4x4,ldr-rgb-05.png,37.9467,0.0883,0.0822,0.7972 -Small,4x4,ldr-rgb-06.png,35.4785,0.0729,0.0668,0.9813 -Small,4x4,ldr-rgb-07.png,39.8676,0.0975,0.0910,0.7202 -Small,4x4,ldr-rgb-08.png,45.7996,0.0752,0.0693,0.9461 -Small,4x4,ldr-rgb-09.png,42.2360,0.0819,0.0759,0.8635 -Small,4x4,ldr-rgb-10.png,44.9865,0.0129,0.0094,1.7305 -Small,4x4,ldr-rgba-00.png,36.7341,0.0876,0.0812,0.8074 -Small,4x4,ldr-rgba-01.png,39.0299,0.0706,0.0644,1.0172 -Small,4x4,ldr-rgba-02.png,34.9857,0.0696,0.0631,1.0381 -Small,4x4,ldr-xy-00.png,37.7552,0.0800,0.0720,0.9101 -Small,4x4,ldr-xy-01.png,45.2171,0.0906,0.0831,0.7890 -Small,4x4,ldr-xy-02.png,50.9992,0.1090,0.1009,0.6495 -Small,4x4,ldrs-rgba-00.png,36.7416,0.0882,0.0818,0.8010 -Small,4x4,ldrs-rgba-01.png,39.0514,0.0709,0.0648,1.0113 -Small,4x4,ldrs-rgba-02.png,34.9915,0.0707,0.0644,1.0182 -Small,5x5,hdr-rgb-00.hdr,30.2499,0.1884,0.0936,0.7000 -Small,5x5,ldr-rgb-00.png,35.3184,0.1087,0.1008,0.6501 -Small,5x5,ldr-rgb-01.png,36.4942,0.1056,0.0981,0.6681 -Small,5x5,ldr-rgb-02.png,31.1169,0.0996,0.0922,0.7107 -Small,5x5,ldr-rgb-03.png,44.4730,0.0957,0.0884,0.7411 -Small,5x5,ldr-rgb-04.png,37.8145,0.0978,0.0902,0.7262 -Small,5x5,ldr-rgb-05.png,33.6567,0.1121,0.1045,0.6273 -Small,5x5,ldr-rgb-06.png,31.1197,0.0949,0.0870,0.7531 -Small,5x5,ldr-rgb-07.png,36.7056,0.1251,0.1172,0.5590 -Small,5x5,ldr-rgb-08.png,42.2684,0.0926,0.0853,0.7683 -Small,5x5,ldr-rgb-09.png,37.6844,0.1041,0.0967,0.6774 -Small,5x5,ldr-rgb-10.png,40.6793,0.0179,0.0130,1.2511 -Small,5x5,ldr-rgba-00.png,33.1233,0.1144,0.1065,0.6155 -Small,5x5,ldr-rgba-01.png,35.3456,0.0915,0.0839,0.7812 -Small,5x5,ldr-rgba-02.png,31.1599,0.0924,0.0847,0.7742 -Small,5x5,ldr-xy-00.png,37.2902,0.0944,0.0849,0.7723 -Small,5x5,ldr-xy-01.png,41.5197,0.1147,0.1055,0.6213 -Small,5x5,ldr-xy-02.png,49.2647,0.1290,0.1194,0.5490 -Small,5x5,ldrs-rgba-00.png,33.1269,0.1157,0.1077,0.6082 -Small,5x5,ldrs-rgba-01.png,35.3541,0.0929,0.0851,0.7697 -Small,5x5,ldrs-rgba-02.png,31.1602,0.0928,0.0850,0.7712 -Small,6x6,hdr-rgb-00.hdr,27.6571,0.2063,0.1111,0.5899 -Small,6x6,ldr-rgb-00.png,32.6208,0.1294,0.1210,0.5416 -Small,6x6,ldr-rgb-01.png,33.1469,0.1211,0.1131,0.5795 -Small,6x6,ldr-rgb-02.png,27.4754,0.1172,0.1090,0.6014 -Small,6x6,ldr-rgb-03.png,42.5226,0.0802,0.0725,0.9038 -Small,6x6,ldr-rgb-04.png,34.3223,0.1154,0.1070,0.6124 -Small,6x6,ldr-rgb-05.png,30.2576,0.1317,0.1234,0.5312 -Small,6x6,ldr-rgb-06.png,27.5394,0.1146,0.1063,0.6164 -Small,6x6,ldr-rgb-07.png,34.3854,0.1380,0.1292,0.5074 -Small,6x6,ldr-rgb-08.png,39.8830,0.0806,0.0724,0.9050 -Small,6x6,ldr-rgb-09.png,33.7955,0.1125,0.1045,0.6270 -Small,6x6,ldr-rgb-10.png,37.1039,0.0227,0.0171,0.9501 -Small,6x6,ldr-rgba-00.png,30.5063,0.1351,0.1263,0.5189 -Small,6x6,ldr-rgba-01.png,32.2316,0.1125,0.1042,0.6287 -Small,6x6,ldr-rgba-02.png,27.8753,0.1161,0.1078,0.6077 -Small,6x6,ldr-xy-00.png,36.3838,0.0803,0.0700,0.9366 -Small,6x6,ldr-xy-01.png,38.0617,0.1164,0.1066,0.6147 -Small,6x6,ldr-xy-02.png,47.4738,0.1436,0.1331,0.4925 -Small,6x6,ldrs-rgba-00.png,30.5081,0.1360,0.1275,0.5141 -Small,6x6,ldrs-rgba-01.png,32.2377,0.1129,0.1047,0.6261 -Small,6x6,ldrs-rgba-02.png,27.8745,0.1175,0.1089,0.6018 -Small,8x8,hdr-rgb-00.hdr,24.3160,0.2483,0.1473,0.4449 -Small,8x8,ldr-rgb-00.png,28.9377,0.1668,0.1528,0.4290 -Small,8x8,ldr-rgb-01.png,28.9883,0.1495,0.1363,0.4809 -Small,8x8,ldr-rgb-02.png,23.1866,0.1572,0.1437,0.4561 -Small,8x8,ldr-rgb-03.png,39.3501,0.0527,0.0395,1.6573 -Small,8x8,ldr-rgb-04.png,29.7749,0.1414,0.1281,0.5118 -Small,8x8,ldr-rgb-05.png,26.0242,0.1650,0.1514,0.4330 -Small,8x8,ldr-rgb-06.png,23.2335,0.1565,0.1432,0.4577 -Small,8x8,ldr-rgb-07.png,31.1039,0.1574,0.1439,0.4555 -Small,8x8,ldr-rgb-08.png,36.4625,0.0773,0.0642,1.0205 -Small,8x8,ldr-rgb-09.png,29.1520,0.1192,0.1056,0.6204 -Small,8x8,ldr-rgb-10.png,32.3031,0.0330,0.0222,0.7315 -Small,8x8,ldr-rgba-00.png,26.6704,0.1756,0.1617,0.4054 -Small,8x8,ldr-rgba-01.png,28.3932,0.1359,0.1225,0.5351 -Small,8x8,ldr-rgba-02.png,23.9599,0.1660,0.1525,0.4298 -Small,8x8,ldr-xy-00.png,34.3120,0.0958,0.0806,0.8127 -Small,8x8,ldr-xy-01.png,35.2097,0.0989,0.0835,0.7847 -Small,8x8,ldr-xy-02.png,44.5878,0.1261,0.1109,0.5911 -Small,8x8,ldrs-rgba-00.png,26.6715,0.1765,0.1627,0.4028 -Small,8x8,ldrs-rgba-01.png,28.3959,0.1378,0.1241,0.5279 -Small,8x8,ldrs-rgba-02.png,23.9597,0.1654,0.1518,0.4317 -Small,12x12,hdr-rgb-00.hdr,21.0019,0.3020,0.1908,0.3435 -Small,12x12,ldr-rgb-00.png,25.0133,0.2074,0.1849,0.3545 -Small,12x12,ldr-rgb-01.png,25.1167,0.1746,0.1514,0.4328 -Small,12x12,ldr-rgb-02.png,19.2912,0.2119,0.1888,0.3471 -Small,12x12,ldr-rgb-03.png,36.1206,0.0624,0.0394,1.6641 -Small,12x12,ldr-rgb-04.png,25.0074,0.1748,0.1512,0.4336 -Small,12x12,ldr-rgb-05.png,21.7140,0.2104,0.1871,0.3503 -Small,12x12,ldr-rgb-06.png,19.2810,0.2060,0.1826,0.3588 -Small,12x12,ldr-rgb-07.png,27.0419,0.1870,0.1639,0.3999 -Small,12x12,ldr-rgb-08.png,32.3840,0.0866,0.0635,1.0324 -Small,12x12,ldr-rgb-09.png,24.3053,0.1656,0.1418,0.4620 -Small,12x12,ldr-rgb-10.png,28.1356,0.0596,0.0388,0.4185 -Small,12x12,ldr-rgba-00.png,22.7010,0.2213,0.1975,0.3318 -Small,12x12,ldr-rgba-01.png,24.7078,0.1637,0.1408,0.4654 -Small,12x12,ldr-rgba-02.png,20.1958,0.2170,0.1937,0.3384 -Small,12x12,ldr-xy-00.png,30.5742,0.1286,0.1034,0.6338 -Small,12x12,ldr-xy-01.png,32.1255,0.0968,0.0718,0.9122 -Small,12x12,ldr-xy-02.png,40.3053,0.0695,0.0444,1.4745 -Small,12x12,ldrs-rgba-00.png,22.7006,0.2215,0.1981,0.3308 -Small,12x12,ldrs-rgba-01.png,24.7093,0.1676,0.1441,0.4547 -Small,12x12,ldrs-rgba-02.png,20.1960,0.2189,0.1954,0.3354 -Small,3x3x3,ldr-l-00-3.dds,52.4159,0.0627,0.0550,4.7653 -Small,3x3x3,ldr-l-01-3.dds,55.3973,0.0269,0.0219,3.1406 -Small,6x6x6,ldr-l-00-3.dds,33.2725,0.1589,0.1327,1.9754 -Small,6x6x6,ldr-l-01-3.dds,41.5751,0.0503,0.0271,2.5473 diff --git a/Test/Images/Small/astc_reference-3.6-sse4.1_fast_results.csv b/Test/Images/Small/astc_reference-3.6-sse4.1_fast_results.csv deleted file mode 100644 index 41c29c2..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse4.1_fast_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.6884,0.1096,0.0172,3.8067 -Small,4x4,ldr-rgb-00.png,38.1103,0.0158,0.0108,6.0732 -Small,4x4,ldr-rgb-01.png,39.8105,0.0142,0.0093,7.0386 -Small,4x4,ldr-rgb-02.png,35.0374,0.0195,0.0146,4.4805 -Small,4x4,ldr-rgb-03.png,45.9704,0.0086,0.0041,16.1731 -Small,4x4,ldr-rgb-04.png,41.9106,0.0119,0.0067,9.7120 -Small,4x4,ldr-rgb-05.png,37.2317,0.0190,0.0140,4.6956 -Small,4x4,ldr-rgb-06.png,35.2059,0.0187,0.0136,4.8220 -Small,4x4,ldr-rgb-07.png,38.0309,0.0199,0.0144,4.5413 -Small,4x4,ldr-rgb-08.png,43.6358,0.0105,0.0056,11.6716 -Small,4x4,ldr-rgb-09.png,41.8533,0.0119,0.0071,9.2343 -Small,4x4,ldr-rgb-10.png,44.3464,0.0045,0.0019,8.4364 -Small,4x4,ldr-rgba-00.png,35.5182,0.0191,0.0138,4.7531 -Small,4x4,ldr-rgba-01.png,38.7956,0.0139,0.0089,7.3894 -Small,4x4,ldr-rgba-02.png,34.8333,0.0175,0.0124,5.2881 -Small,4x4,ldr-xy-00.png,37.5697,0.0141,0.0066,9.8746 -Small,4x4,ldr-xy-01.png,44.1378,0.0150,0.0079,8.2790 -Small,4x4,ldr-xy-02.png,48.1786,0.0128,0.0052,12.5001 -Small,4x4,ldrs-rgba-00.png,35.5254,0.0196,0.0141,4.6519 -Small,4x4,ldrs-rgba-01.png,38.8141,0.0140,0.0088,7.4685 -Small,4x4,ldrs-rgba-02.png,34.8386,0.0176,0.0125,5.2488 -Small,5x5,hdr-rgb-00.hdr,29.4686,0.1130,0.0206,3.1783 -Small,5x5,ldr-rgb-00.png,34.3042,0.0173,0.0113,5.8223 -Small,5x5,ldr-rgb-01.png,36.1808,0.0145,0.0087,7.5555 -Small,5x5,ldr-rgb-02.png,31.0160,0.0193,0.0134,4.8918 -Small,5x5,ldr-rgb-03.png,42.6231,0.0091,0.0036,18.2959 -Small,5x5,ldr-rgb-04.png,37.2434,0.0130,0.0069,9.5258 -Small,5x5,ldr-rgb-05.png,33.1823,0.0217,0.0155,4.2162 -Small,5x5,ldr-rgb-06.png,31.0247,0.0191,0.0129,5.0831 -Small,5x5,ldr-rgb-07.png,35.1883,0.0189,0.0125,5.2479 -Small,5x5,ldr-rgb-08.png,40.0310,0.0108,0.0050,13.1125 -Small,5x5,ldr-rgb-09.png,37.2810,0.0129,0.0070,9.3315 -Small,5x5,ldr-rgb-10.png,40.1234,0.0055,0.0020,8.2766 -Small,5x5,ldr-rgba-00.png,32.0072,0.0218,0.0153,4.2769 -Small,5x5,ldr-rgba-01.png,35.1428,0.0151,0.0091,7.2152 -Small,5x5,ldr-rgba-02.png,31.1062,0.0198,0.0136,4.8334 -Small,5x5,ldr-xy-00.png,36.7258,0.0147,0.0054,12.1028 -Small,5x5,ldr-xy-01.png,39.8638,0.0155,0.0070,9.3050 -Small,5x5,ldr-xy-02.png,43.9171,0.0138,0.0049,13.4962 -Small,5x5,ldrs-rgba-00.png,32.0096,0.0218,0.0153,4.2784 -Small,5x5,ldrs-rgba-01.png,35.1497,0.0153,0.0091,7.2152 -Small,5x5,ldrs-rgba-02.png,31.1070,0.0201,0.0137,4.7708 -Small,6x6,hdr-rgb-00.hdr,26.9904,0.1185,0.0240,2.7328 -Small,6x6,ldr-rgb-00.png,31.5938,0.0215,0.0149,4.3987 -Small,6x6,ldr-rgb-01.png,32.8896,0.0175,0.0111,5.9121 -Small,6x6,ldr-rgb-02.png,27.4079,0.0241,0.0175,3.7502 -Small,6x6,ldr-rgb-03.png,40.4899,0.0100,0.0037,17.8759 -Small,6x6,ldr-rgb-04.png,33.9065,0.0154,0.0089,7.3340 -Small,6x6,ldr-rgb-05.png,29.9329,0.0269,0.0202,3.2384 -Small,6x6,ldr-rgb-06.png,27.4651,0.0235,0.0169,3.8850 -Small,6x6,ldr-rgb-07.png,32.8824,0.0202,0.0132,4.9713 -Small,6x6,ldr-rgb-08.png,37.6380,0.0117,0.0053,12.4003 -Small,6x6,ldr-rgb-09.png,33.4716,0.0157,0.0093,7.0523 -Small,6x6,ldr-rgb-10.png,36.6590,0.0064,0.0023,7.2120 -Small,6x6,ldr-rgba-00.png,29.4788,0.0264,0.0194,3.3763 -Small,6x6,ldr-rgba-01.png,32.0575,0.0180,0.0112,5.8452 -Small,6x6,ldr-rgba-02.png,27.8275,0.0245,0.0175,3.7464 -Small,6x6,ldr-xy-00.png,35.6827,0.0155,0.0061,10.7492 -Small,6x6,ldr-xy-01.png,37.1053,0.0179,0.0090,7.2512 -Small,6x6,ldr-xy-02.png,41.9446,0.0138,0.0045,14.7041 -Small,6x6,ldrs-rgba-00.png,29.4790,0.0266,0.0196,3.3451 -Small,6x6,ldrs-rgba-01.png,32.0640,0.0180,0.0114,5.7715 -Small,6x6,ldrs-rgba-02.png,27.8273,0.0245,0.0177,3.7053 -Small,8x8,hdr-rgb-00.hdr,23.7216,0.1326,0.0335,1.9540 -Small,8x8,ldr-rgb-00.png,27.9814,0.0299,0.0193,3.4030 -Small,8x8,ldr-rgb-01.png,28.7458,0.0259,0.0155,4.2290 -Small,8x8,ldr-rgb-02.png,23.0937,0.0357,0.0252,2.6016 -Small,8x8,ldr-rgb-03.png,37.2544,0.0142,0.0041,16.1181 -Small,8x8,ldr-rgb-04.png,29.3419,0.0247,0.0141,4.6516 -Small,8x8,ldr-rgb-05.png,25.7747,0.0393,0.0290,2.2612 -Small,8x8,ldr-rgb-06.png,23.1468,0.0359,0.0251,2.6119 -Small,8x8,ldr-rgb-07.png,29.6508,0.0245,0.0136,4.8202 -Small,8x8,ldr-rgb-08.png,34.2150,0.0170,0.0067,9.8519 -Small,8x8,ldr-rgb-09.png,28.6635,0.0254,0.0150,4.3735 -Small,8x8,ldr-rgb-10.png,31.9974,0.0113,0.0031,5.1752 -Small,8x8,ldr-rgba-00.png,25.3599,0.0369,0.0259,2.5322 -Small,8x8,ldr-rgba-01.png,28.2399,0.0271,0.0166,3.9570 -Small,8x8,ldr-rgba-02.png,23.9241,0.0365,0.0258,2.5394 -Small,8x8,ldr-xy-00.png,33.3965,0.0227,0.0088,7.4481 -Small,8x8,ldr-xy-01.png,34.2472,0.0244,0.0108,6.0827 -Small,8x8,ldr-xy-02.png,39.9005,0.0173,0.0034,19.0795 -Small,8x8,ldrs-rgba-00.png,25.3610,0.0370,0.0259,2.5259 -Small,8x8,ldrs-rgba-01.png,28.2419,0.0278,0.0169,3.8742 -Small,8x8,ldrs-rgba-02.png,23.9237,0.0370,0.0261,2.5067 -Small,12x12,hdr-rgb-00.hdr,20.5637,0.1512,0.0447,1.4657 -Small,12x12,ldr-rgb-00.png,23.7825,0.0327,0.0154,4.2644 -Small,12x12,ldr-rgb-01.png,24.7588,0.0274,0.0105,6.2345 -Small,12x12,ldr-rgb-02.png,19.2226,0.0456,0.0282,2.3205 -Small,12x12,ldr-rgb-03.png,33.2364,0.0201,0.0031,21.3266 -Small,12x12,ldr-rgb-04.png,24.5606,0.0279,0.0106,6.1611 -Small,12x12,ldr-rgb-05.png,21.4885,0.0408,0.0236,2.7793 -Small,12x12,ldr-rgb-06.png,19.2097,0.0472,0.0298,2.2025 -Small,12x12,ldr-rgb-07.png,25.3456,0.0269,0.0090,7.3013 -Small,12x12,ldr-rgb-08.png,30.1535,0.0220,0.0045,14.4414 -Small,12x12,ldr-rgb-09.png,23.7136,0.0324,0.0154,4.2471 -Small,12x12,ldr-rgb-10.png,27.3052,0.0186,0.0037,4.4211 -Small,12x12,ldr-rgba-00.png,21.3632,0.0442,0.0267,2.4534 -Small,12x12,ldr-rgba-01.png,24.4867,0.0304,0.0131,5.0215 -Small,12x12,ldr-rgba-02.png,20.1666,0.0525,0.0347,1.8879 -Small,12x12,ldr-xy-00.png,29.0651,0.0294,0.0078,8.3935 -Small,12x12,ldr-xy-01.png,30.4241,0.0283,0.0075,8.7815 -Small,12x12,ldr-xy-02.png,37.9951,0.0230,0.0020,32.2513 -Small,12x12,ldrs-rgba-00.png,21.3658,0.0442,0.0266,2.4684 -Small,12x12,ldrs-rgba-01.png,24.4885,0.0301,0.0129,5.0705 -Small,12x12,ldrs-rgba-02.png,20.1665,0.0528,0.0349,1.8759 -Small,3x3x3,ldr-l-00-3.dds,50.7551,0.0218,0.0150,17.4845 -Small,3x3x3,ldr-l-01-3.dds,53.8676,0.0102,0.0062,11.1811 -Small,6x6x6,ldr-l-00-3.dds,32.5264,0.0827,0.0593,4.4177 -Small,6x6x6,ldr-l-01-3.dds,40.7893,0.0435,0.0231,2.9774 diff --git a/Test/Images/Small/astc_reference-3.6-sse4.1_fastest_results.csv b/Test/Images/Small/astc_reference-3.6-sse4.1_fastest_results.csv deleted file mode 100644 index 0ad680d..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse4.1_fastest_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,33.2999,0.1028,0.0107,6.1072 -Small,4x4,ldr-rgb-00.png,37.0084,0.0109,0.0064,10.2193 -Small,4x4,ldr-rgb-01.png,39.4162,0.0105,0.0062,10.5926 -Small,4x4,ldr-rgb-02.png,34.6448,0.0134,0.0092,7.1358 -Small,4x4,ldr-rgb-03.png,45.3559,0.0069,0.0029,22.6535 -Small,4x4,ldr-rgb-04.png,41.6390,0.0093,0.0047,13.8464 -Small,4x4,ldr-rgb-05.png,36.7213,0.0131,0.0087,7.5477 -Small,4x4,ldr-rgb-06.png,34.6994,0.0131,0.0084,7.7651 -Small,4x4,ldr-rgb-07.png,37.1808,0.0133,0.0085,7.7055 -Small,4x4,ldr-rgb-08.png,42.6915,0.0082,0.0039,16.9961 -Small,4x4,ldr-rgb-09.png,41.6433,0.0092,0.0048,13.5155 -Small,4x4,ldr-rgb-10.png,43.8818,0.0036,0.0016,10.0907 -Small,4x4,ldr-rgba-00.png,34.5700,0.0127,0.0078,8.3989 -Small,4x4,ldr-rgba-01.png,38.5857,0.0112,0.0066,9.8998 -Small,4x4,ldr-rgba-02.png,34.5224,0.0138,0.0092,7.1343 -Small,4x4,ldr-xy-00.png,37.5264,0.0117,0.0049,13.3449 -Small,4x4,ldr-xy-01.png,43.8563,0.0119,0.0054,12.2157 -Small,4x4,ldr-xy-02.png,48.1786,0.0110,0.0039,16.5999 -Small,4x4,ldrs-rgba-00.png,34.5750,0.0127,0.0078,8.4267 -Small,4x4,ldrs-rgba-01.png,38.6025,0.0112,0.0066,9.9009 -Small,4x4,ldrs-rgba-02.png,34.5263,0.0138,0.0093,7.0827 -Small,5x5,hdr-rgb-00.hdr,28.8076,0.1055,0.0129,5.0795 -Small,5x5,ldr-rgb-00.png,33.4478,0.0122,0.0069,9.4665 -Small,5x5,ldr-rgb-01.png,35.9999,0.0111,0.0062,10.5212 -Small,5x5,ldr-rgb-02.png,30.8748,0.0145,0.0095,6.8969 -Small,5x5,ldr-rgb-03.png,42.2547,0.0076,0.0029,22.6685 -Small,5x5,ldr-rgb-04.png,36.9224,0.0107,0.0055,12.0202 -Small,5x5,ldr-rgb-05.png,32.6193,0.0151,0.0100,6.5438 -Small,5x5,ldr-rgb-06.png,30.8711,0.0147,0.0095,6.9044 -Small,5x5,ldr-rgb-07.png,34.2652,0.0142,0.0084,7.7649 -Small,5x5,ldr-rgb-08.png,39.3139,0.0088,0.0039,16.6250 -Small,5x5,ldr-rgb-09.png,36.9835,0.0104,0.0055,11.8151 -Small,5x5,ldr-rgb-10.png,39.7373,0.0043,0.0016,9.8758 -Small,5x5,ldr-rgba-00.png,30.7473,0.0140,0.0084,7.7586 -Small,5x5,ldr-rgba-01.png,34.9846,0.0123,0.0070,9.3611 -Small,5x5,ldr-rgba-02.png,31.0020,0.0158,0.0106,6.1884 -Small,5x5,ldr-xy-00.png,36.5568,0.0125,0.0042,15.5044 -Small,5x5,ldr-xy-01.png,38.8334,0.0125,0.0049,13.4513 -Small,5x5,ldr-xy-02.png,43.7233,0.0120,0.0041,16.0195 -Small,5x5,ldrs-rgba-00.png,30.7497,0.0141,0.0087,7.5458 -Small,5x5,ldrs-rgba-01.png,34.9913,0.0125,0.0073,9.0047 -Small,5x5,ldrs-rgba-02.png,31.0030,0.0159,0.0103,6.3394 -Small,6x6,hdr-rgb-00.hdr,26.7122,0.1062,0.0128,5.1029 -Small,6x6,ldr-rgb-00.png,31.1052,0.0133,0.0077,8.4870 -Small,6x6,ldr-rgb-01.png,32.7949,0.0123,0.0072,9.1495 -Small,6x6,ldr-rgb-02.png,27.3228,0.0164,0.0111,5.8920 -Small,6x6,ldr-rgb-03.png,40.2037,0.0077,0.0026,24.8421 -Small,6x6,ldr-rgb-04.png,33.7349,0.0117,0.0063,10.3825 -Small,6x6,ldr-rgb-05.png,29.5304,0.0168,0.0113,5.7828 -Small,6x6,ldr-rgb-06.png,27.3791,0.0163,0.0108,6.0665 -Small,6x6,ldr-rgb-07.png,32.0586,0.0142,0.0083,7.9254 -Small,6x6,ldr-rgb-08.png,37.0422,0.0089,0.0036,18.4086 -Small,6x6,ldr-rgb-09.png,33.2804,0.0115,0.0060,10.8630 -Small,6x6,ldr-rgb-10.png,36.4903,0.0048,0.0019,8.7774 -Small,6x6,ldr-rgba-00.png,28.4787,0.0157,0.0099,6.6494 -Small,6x6,ldr-rgba-01.png,31.9580,0.0138,0.0080,8.1736 -Small,6x6,ldr-rgba-02.png,27.7571,0.0170,0.0113,5.7772 -Small,6x6,ldr-xy-00.png,35.5281,0.0127,0.0045,14.5123 -Small,6x6,ldr-xy-01.png,36.2504,0.0134,0.0056,11.7514 -Small,6x6,ldr-xy-02.png,41.7327,0.0117,0.0036,18.3069 -Small,6x6,ldrs-rgba-00.png,28.4800,0.0156,0.0097,6.7900 -Small,6x6,ldrs-rgba-01.png,31.9643,0.0138,0.0082,7.9612 -Small,6x6,ldrs-rgba-02.png,27.7547,0.0172,0.0116,5.6375 -Small,8x8,hdr-rgb-00.hdr,23.5547,0.1176,0.0204,3.2154 -Small,8x8,ldr-rgb-00.png,27.6188,0.0204,0.0114,5.7247 -Small,8x8,ldr-rgb-01.png,28.6671,0.0189,0.0104,6.3192 -Small,8x8,ldr-rgb-02.png,23.0179,0.0255,0.0167,3.9328 -Small,8x8,ldr-rgb-03.png,37.0089,0.0117,0.0032,20.6800 -Small,8x8,ldr-rgb-04.png,29.0953,0.0183,0.0094,6.9757 -Small,8x8,ldr-rgb-05.png,25.5324,0.0256,0.0166,3.9432 -Small,8x8,ldr-rgb-06.png,23.0523,0.0261,0.0170,3.8555 -Small,8x8,ldr-rgb-07.png,29.3368,0.0186,0.0094,6.9794 -Small,8x8,ldr-rgb-08.png,33.7665,0.0134,0.0047,13.9320 -Small,8x8,ldr-rgb-09.png,28.4590,0.0182,0.0094,6.9653 -Small,8x8,ldr-rgb-10.png,31.8847,0.0088,0.0025,6.5655 -Small,8x8,ldr-rgba-00.png,24.9726,0.0242,0.0149,4.4031 -Small,8x8,ldr-rgba-01.png,28.1236,0.0202,0.0114,5.7695 -Small,8x8,ldr-rgba-02.png,23.8676,0.0264,0.0174,3.7725 -Small,8x8,ldr-xy-00.png,33.2085,0.0185,0.0062,10.5060 -Small,8x8,ldr-xy-01.png,33.9809,0.0189,0.0072,9.0743 -Small,8x8,ldr-xy-02.png,39.7786,0.0148,0.0028,23.3640 -Small,8x8,ldrs-rgba-00.png,24.9730,0.0243,0.0151,4.3298 -Small,8x8,ldrs-rgba-01.png,28.1260,0.0202,0.0112,5.8636 -Small,8x8,ldrs-rgba-02.png,23.8671,0.0268,0.0179,3.6696 -Small,12x12,hdr-rgb-00.hdr,20.4789,0.1292,0.0280,2.3382 -Small,12x12,ldr-rgb-00.png,23.6716,0.0234,0.0103,6.3332 -Small,12x12,ldr-rgb-01.png,24.7037,0.0205,0.0075,8.7113 -Small,12x12,ldr-rgb-02.png,19.1880,0.0320,0.0189,3.4677 -Small,12x12,ldr-rgb-03.png,33.1400,0.0155,0.0028,23.1165 -Small,12x12,ldr-rgb-04.png,24.3898,0.0207,0.0077,8.5400 -Small,12x12,ldr-rgb-05.png,21.3701,0.0294,0.0160,4.0926 -Small,12x12,ldr-rgb-06.png,19.1564,0.0337,0.0204,3.2058 -Small,12x12,ldr-rgb-07.png,25.2598,0.0204,0.0071,9.1917 -Small,12x12,ldr-rgb-08.png,29.9653,0.0167,0.0039,16.7313 -Small,12x12,ldr-rgb-09.png,23.5968,0.0234,0.0106,6.1669 -Small,12x12,ldr-rgb-10.png,27.2554,0.0135,0.0026,6.1860 -Small,12x12,ldr-rgba-00.png,21.1828,0.0304,0.0169,3.8685 -Small,12x12,ldr-rgba-01.png,24.4330,0.0229,0.0095,6.9298 -Small,12x12,ldr-rgba-02.png,20.1371,0.0376,0.0239,2.7374 -Small,12x12,ldr-xy-00.png,28.9405,0.0230,0.0064,10.1954 -Small,12x12,ldr-xy-01.png,29.6034,0.0222,0.0058,11.2085 -Small,12x12,ldr-xy-02.png,37.9716,0.0187,0.0021,31.5082 -Small,12x12,ldrs-rgba-00.png,21.1836,0.0304,0.0170,3.8496 -Small,12x12,ldrs-rgba-01.png,24.4339,0.0226,0.0097,6.7849 -Small,12x12,ldrs-rgba-02.png,20.1367,0.0376,0.0241,2.7191 -Small,3x3x3,ldr-l-00-3.dds,50.6012,0.0193,0.0132,19.9288 -Small,3x3x3,ldr-l-01-3.dds,53.7999,0.0091,0.0059,11.6305 -Small,6x6x6,ldr-l-00-3.dds,32.5074,0.0803,0.0590,4.4415 -Small,6x6x6,ldr-l-01-3.dds,40.7826,0.0411,0.0229,3.0066 diff --git a/Test/Images/Small/astc_reference-3.6-sse4.1_medium_results.csv b/Test/Images/Small/astc_reference-3.6-sse4.1_medium_results.csv deleted file mode 100644 index 8cfd869..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse4.1_medium_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.1340,0.1239,0.0307,2.1365 -Small,4x4,ldr-rgb-00.png,38.7318,0.0378,0.0318,2.0599 -Small,4x4,ldr-rgb-01.png,40.1460,0.0348,0.0291,2.2545 -Small,4x4,ldr-rgb-02.png,35.2180,0.0361,0.0304,2.1562 -Small,4x4,ldr-rgb-03.png,47.1925,0.0216,0.0161,4.0683 -Small,4x4,ldr-rgb-04.png,42.1729,0.0298,0.0238,2.7534 -Small,4x4,ldr-rgb-05.png,37.7672,0.0387,0.0326,2.0087 -Small,4x4,ldr-rgb-06.png,35.3468,0.0327,0.0267,2.4589 -Small,4x4,ldr-rgb-07.png,39.2464,0.0449,0.0386,1.6958 -Small,4x4,ldr-rgb-08.png,45.1732,0.0253,0.0195,3.3534 -Small,4x4,ldr-rgb-09.png,42.0914,0.0302,0.0245,2.6775 -Small,4x4,ldr-rgb-10.png,44.8767,0.0073,0.0039,4.1712 -Small,4x4,ldr-rgba-00.png,36.2349,0.0410,0.0347,1.8895 -Small,4x4,ldr-rgba-01.png,38.8941,0.0257,0.0197,3.3299 -Small,4x4,ldr-rgba-02.png,34.9204,0.0291,0.0230,2.8488 -Small,4x4,ldr-xy-00.png,37.7446,0.0265,0.0188,3.4898 -Small,4x4,ldr-xy-01.png,45.1462,0.0359,0.0286,2.2903 -Small,4x4,ldr-xy-02.png,50.9226,0.0432,0.0350,1.8699 -Small,4x4,ldrs-rgba-00.png,36.2418,0.0413,0.0349,1.8765 -Small,4x4,ldrs-rgba-01.png,38.9101,0.0260,0.0200,3.2788 -Small,4x4,ldrs-rgba-02.png,34.9259,0.0294,0.0232,2.8274 -Small,5x5,hdr-rgb-00.hdr,29.8514,0.1364,0.0409,1.6007 -Small,5x5,ldr-rgb-00.png,35.0732,0.0457,0.0379,1.7312 -Small,5x5,ldr-rgb-01.png,36.3975,0.0384,0.0312,2.1022 -Small,5x5,ldr-rgb-02.png,31.0670,0.0405,0.0330,1.9850 -Small,5x5,ldr-rgb-03.png,43.9478,0.0177,0.0106,6.1646 -Small,5x5,ldr-rgb-04.png,37.6667,0.0357,0.0282,2.3255 -Small,5x5,ldr-rgb-05.png,33.5193,0.0513,0.0438,1.4973 -Small,5x5,ldr-rgb-06.png,31.0773,0.0384,0.0309,2.1195 -Small,5x5,ldr-rgb-07.png,36.2042,0.0549,0.0471,1.3922 -Small,5x5,ldr-rgb-08.png,41.5462,0.0265,0.0189,3.4637 -Small,5x5,ldr-rgb-09.png,37.5873,0.0331,0.0257,2.5489 -Small,5x5,ldr-rgb-10.png,40.4902,0.0098,0.0049,3.3161 -Small,5x5,ldr-rgba-00.png,32.7858,0.0539,0.0459,1.4285 -Small,5x5,ldr-rgba-01.png,35.2722,0.0315,0.0240,2.7328 -Small,5x5,ldr-rgba-02.png,31.1225,0.0375,0.0298,2.1957 -Small,5x5,ldr-xy-00.png,37.0726,0.0287,0.0193,3.3930 -Small,5x5,ldr-xy-01.png,40.7191,0.0372,0.0282,2.3281 -Small,5x5,ldr-xy-02.png,49.0675,0.0295,0.0201,3.2668 -Small,5x5,ldrs-rgba-00.png,32.7887,0.0551,0.0472,1.3894 -Small,5x5,ldrs-rgba-01.png,35.2789,0.0316,0.0241,2.7202 -Small,5x5,ldrs-rgba-02.png,31.1234,0.0376,0.0298,2.1957 -Small,6x6,hdr-rgb-00.hdr,27.4769,0.1416,0.0461,1.4227 -Small,6x6,ldr-rgb-00.png,32.3560,0.0486,0.0404,1.6212 -Small,6x6,ldr-rgb-01.png,33.0687,0.0399,0.0320,2.0509 -Small,6x6,ldr-rgb-02.png,27.4381,0.0441,0.0363,1.8046 -Small,6x6,ldr-rgb-03.png,41.6538,0.0160,0.0085,7.6956 -Small,6x6,ldr-rgb-04.png,34.2059,0.0358,0.0277,2.3653 -Small,6x6,ldr-rgb-05.png,30.1377,0.0567,0.0484,1.3546 -Small,6x6,ldr-rgb-06.png,27.5024,0.0432,0.0351,1.8676 -Small,6x6,ldr-rgb-07.png,33.8577,0.0528,0.0444,1.4768 -Small,6x6,ldr-rgb-08.png,39.0752,0.0221,0.0144,4.5590 -Small,6x6,ldr-rgb-09.png,33.6699,0.0344,0.0267,2.4576 -Small,6x6,ldr-rgb-10.png,36.9333,0.0112,0.0057,2.8671 -Small,6x6,ldr-rgba-00.png,30.2558,0.0607,0.0522,1.2545 -Small,6x6,ldr-rgba-01.png,32.1716,0.0338,0.0258,2.5378 -Small,6x6,ldr-rgba-02.png,27.8426,0.0427,0.0346,1.8935 -Small,6x6,ldr-xy-00.png,36.2518,0.0275,0.0174,3.7582 -Small,6x6,ldr-xy-01.png,37.7318,0.0309,0.0215,3.0496 -Small,6x6,ldr-xy-02.png,46.0639,0.0245,0.0146,4.4777 -Small,6x6,ldrs-rgba-00.png,30.2570,0.0615,0.0531,1.2352 -Small,6x6,ldrs-rgba-01.png,32.1777,0.0342,0.0261,2.5070 -Small,6x6,ldrs-rgba-02.png,27.8427,0.0429,0.0347,1.8888 -Small,8x8,hdr-rgb-00.hdr,24.1157,0.1613,0.0602,1.0891 -Small,8x8,ldr-rgb-00.png,28.7123,0.0666,0.0551,1.1888 -Small,8x8,ldr-rgb-01.png,28.9240,0.0526,0.0409,1.6037 -Small,8x8,ldr-rgb-02.png,23.1517,0.0604,0.0490,1.3377 -Small,8x8,ldr-rgb-03.png,38.4615,0.0213,0.0099,6.5872 -Small,8x8,ldr-rgb-04.png,29.6546,0.0490,0.0370,1.7691 -Small,8x8,ldr-rgb-05.png,25.9295,0.0691,0.0573,1.1441 -Small,8x8,ldr-rgb-06.png,23.1918,0.0606,0.0487,1.3445 -Small,8x8,ldr-rgb-07.png,30.5823,0.0603,0.0483,1.3562 -Small,8x8,ldr-rgb-08.png,35.7743,0.0279,0.0164,3.9854 -Small,8x8,ldr-rgb-09.png,29.0115,0.0462,0.0349,1.8787 -Small,8x8,ldr-rgb-10.png,32.1619,0.0173,0.0079,2.0601 -Small,8x8,ldr-rgba-00.png,26.3940,0.0774,0.0653,1.0042 -Small,8x8,ldr-rgba-01.png,28.3383,0.0462,0.0344,1.9057 -Small,8x8,ldr-rgba-02.png,23.9368,0.0638,0.0520,1.2615 -Small,8x8,ldr-xy-00.png,34.0144,0.0407,0.0258,2.5434 -Small,8x8,ldr-xy-01.png,34.9127,0.0399,0.0253,2.5945 -Small,8x8,ldr-xy-02.png,41.7218,0.0294,0.0149,4.4103 -Small,8x8,ldrs-rgba-00.png,26.3943,0.0772,0.0650,1.0086 -Small,8x8,ldrs-rgba-01.png,28.3412,0.0461,0.0342,1.9175 -Small,8x8,ldrs-rgba-02.png,23.9363,0.0636,0.0517,1.2675 -Small,12x12,hdr-rgb-00.hdr,20.7645,0.1928,0.0827,0.7929 -Small,12x12,ldr-rgb-00.png,24.6670,0.0831,0.0623,1.0517 -Small,12x12,ldr-rgb-01.png,25.0227,0.0712,0.0510,1.2862 -Small,12x12,ldr-rgb-02.png,19.2621,0.0955,0.0756,0.8669 -Small,12x12,ldr-rgb-03.png,34.9308,0.0305,0.0109,6.0075 -Small,12x12,ldr-rgb-04.png,24.9126,0.0670,0.0469,1.3980 -Small,12x12,ldr-rgb-05.png,21.6505,0.0964,0.0764,0.8583 -Small,12x12,ldr-rgb-06.png,19.2451,0.0915,0.0714,0.9175 -Small,12x12,ldr-rgb-07.png,26.5693,0.0706,0.0498,1.3148 -Small,12x12,ldr-rgb-08.png,31.4927,0.0382,0.0180,3.6358 -Small,12x12,ldr-rgb-09.png,24.1078,0.0676,0.0473,1.3847 -Small,12x12,ldr-rgb-10.png,27.9831,0.0338,0.0165,0.9835 -Small,12x12,ldr-rgba-00.png,22.0878,0.0937,0.0732,0.8949 -Small,12x12,ldr-rgba-01.png,24.6267,0.0690,0.0488,1.3428 -Small,12x12,ldr-rgba-02.png,20.1804,0.1020,0.0817,0.8026 -Small,12x12,ldr-xy-00.png,30.0722,0.0538,0.0297,2.2065 -Small,12x12,ldr-xy-01.png,31.8391,0.0525,0.0286,2.2878 -Small,12x12,ldr-xy-02.png,38.5216,0.0303,0.0059,11.1571 -Small,12x12,ldrs-rgba-00.png,22.0882,0.0937,0.0732,0.8947 -Small,12x12,ldrs-rgba-01.png,24.6285,0.0683,0.0480,1.3639 -Small,12x12,ldrs-rgba-02.png,20.1803,0.1013,0.0808,0.8107 -Small,3x3x3,ldr-l-00-3.dds,51.9681,0.0294,0.0215,12.1848 -Small,3x3x3,ldr-l-01-3.dds,54.3395,0.0116,0.0067,10.3175 -Small,6x6x6,ldr-l-00-3.dds,32.9129,0.0970,0.0737,3.5555 -Small,6x6x6,ldr-l-01-3.dds,40.8871,0.0435,0.0234,2.9516 diff --git a/Test/Images/Small/astc_reference-3.6-sse4.1_thorough_results.csv b/Test/Images/Small/astc_reference-3.6-sse4.1_thorough_results.csv deleted file mode 100644 index 26148c7..0000000 --- a/Test/Images/Small/astc_reference-3.6-sse4.1_thorough_results.csv +++ /dev/null @@ -1,110 +0,0 @@ -Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate -Small,4x4,hdr-rgb-00.hdr,34.3787,0.1555,0.0634,1.0332 -Small,4x4,ldr-rgb-00.png,39.1025,0.0752,0.0691,0.9484 -Small,4x4,ldr-rgb-01.png,40.3344,0.0742,0.0683,0.9589 -Small,4x4,ldr-rgb-02.png,35.3612,0.0699,0.0640,1.0247 -Small,4x4,ldr-rgb-03.png,47.6672,0.0694,0.0636,1.0306 -Small,4x4,ldr-rgb-04.png,42.3135,0.0679,0.0619,1.0584 -Small,4x4,ldr-rgb-05.png,37.9467,0.0789,0.0729,0.8994 -Small,4x4,ldr-rgb-06.png,35.4785,0.0645,0.0585,1.1209 -Small,4x4,ldr-rgb-07.png,39.8676,0.0858,0.0794,0.8255 -Small,4x4,ldr-rgb-08.png,45.7996,0.0667,0.0609,1.0756 -Small,4x4,ldr-rgb-09.png,42.2360,0.0729,0.0669,0.9801 -Small,4x4,ldr-rgb-10.png,44.9865,0.0119,0.0083,1.9489 -Small,4x4,ldr-rgba-00.png,36.7341,0.0780,0.0716,0.9154 -Small,4x4,ldr-rgba-01.png,39.0299,0.0642,0.0581,1.1272 -Small,4x4,ldr-rgba-02.png,34.9857,0.0634,0.0572,1.1451 -Small,4x4,ldr-xy-00.png,37.7552,0.0731,0.0650,1.0075 -Small,4x4,ldr-xy-01.png,45.2171,0.0811,0.0737,0.8888 -Small,4x4,ldr-xy-02.png,50.9992,0.0981,0.0901,0.7270 -Small,4x4,ldrs-rgba-00.png,36.7416,0.0786,0.0722,0.9078 -Small,4x4,ldrs-rgba-01.png,39.0514,0.0641,0.0580,1.1298 -Small,4x4,ldrs-rgba-02.png,34.9915,0.0630,0.0568,1.1538 -Small,5x5,hdr-rgb-00.hdr,30.2499,0.1753,0.0809,0.8100 -Small,5x5,ldr-rgb-00.png,35.3184,0.0958,0.0883,0.7425 -Small,5x5,ldr-rgb-01.png,36.4942,0.0921,0.0847,0.7736 -Small,5x5,ldr-rgb-02.png,31.1169,0.0866,0.0792,0.8277 -Small,5x5,ldr-rgb-03.png,44.4730,0.0843,0.0772,0.8493 -Small,5x5,ldr-rgb-04.png,37.8145,0.0865,0.0789,0.8306 -Small,5x5,ldr-rgb-05.png,33.6567,0.0988,0.0914,0.7172 -Small,5x5,ldr-rgb-06.png,31.1197,0.0829,0.0752,0.8715 -Small,5x5,ldr-rgb-07.png,36.7056,0.1097,0.1016,0.6450 -Small,5x5,ldr-rgb-08.png,42.2684,0.0797,0.0723,0.9063 -Small,5x5,ldr-rgb-09.png,37.6844,0.0903,0.0829,0.7904 -Small,5x5,ldr-rgb-10.png,40.6793,0.0164,0.0114,1.4257 -Small,5x5,ldr-rgba-00.png,33.1233,0.1005,0.0925,0.7086 -Small,5x5,ldr-rgba-01.png,35.3456,0.0816,0.0738,0.8876 -Small,5x5,ldr-rgba-02.png,31.1599,0.0814,0.0737,0.8890 -Small,5x5,ldr-xy-00.png,37.2902,0.0831,0.0736,0.8909 -Small,5x5,ldr-xy-01.png,41.5197,0.1024,0.0933,0.7022 -Small,5x5,ldr-xy-02.png,49.2647,0.1145,0.1050,0.6242 -Small,5x5,ldrs-rgba-00.png,33.1269,0.1005,0.0926,0.7079 -Small,5x5,ldrs-rgba-01.png,35.3541,0.0827,0.0751,0.8729 -Small,5x5,ldrs-rgba-02.png,31.1602,0.0827,0.0749,0.8745 -Small,6x6,hdr-rgb-00.hdr,27.6571,0.1910,0.0968,0.6769 -Small,6x6,ldr-rgb-00.png,32.6208,0.1125,0.1043,0.6285 -Small,6x6,ldr-rgb-01.png,33.1469,0.1058,0.0978,0.6699 -Small,6x6,ldr-rgb-02.png,27.4754,0.1029,0.0948,0.6916 -Small,6x6,ldr-rgb-03.png,42.5226,0.0711,0.0632,1.0367 -Small,6x6,ldr-rgb-04.png,34.3223,0.1020,0.0937,0.6992 -Small,6x6,ldr-rgb-05.png,30.2576,0.1151,0.1070,0.6123 -Small,6x6,ldr-rgb-06.png,27.5394,0.0996,0.0913,0.7176 -Small,6x6,ldr-rgb-07.png,34.3854,0.1219,0.1130,0.5801 -Small,6x6,ldr-rgb-08.png,39.8830,0.0697,0.0618,1.0599 -Small,6x6,ldr-rgb-09.png,33.7955,0.0983,0.0903,0.7254 -Small,6x6,ldr-rgb-10.png,37.1039,0.0211,0.0156,1.0417 -Small,6x6,ldr-rgba-00.png,30.5063,0.1194,0.1108,0.5916 -Small,6x6,ldr-rgba-01.png,32.2316,0.1000,0.0916,0.7156 -Small,6x6,ldr-rgba-02.png,27.8753,0.1032,0.0949,0.6908 -Small,6x6,ldr-xy-00.png,36.3838,0.0726,0.0626,1.0473 -Small,6x6,ldr-xy-01.png,38.0617,0.1050,0.0951,0.6890 -Small,6x6,ldr-xy-02.png,47.4738,0.1331,0.1227,0.5340 -Small,6x6,ldrs-rgba-00.png,30.5081,0.1272,0.1186,0.5527 -Small,6x6,ldrs-rgba-01.png,32.2377,0.1047,0.0960,0.6830 -Small,6x6,ldrs-rgba-02.png,27.8745,0.1060,0.0971,0.6753 -Small,8x8,hdr-rgb-00.hdr,24.3160,0.2350,0.1290,0.5078 -Small,8x8,ldr-rgb-00.png,28.9377,0.1472,0.1338,0.4898 -Small,8x8,ldr-rgb-01.png,28.9883,0.1339,0.1207,0.5429 -Small,8x8,ldr-rgb-02.png,23.1866,0.1399,0.1268,0.5167 -Small,8x8,ldr-rgb-03.png,39.3501,0.0476,0.0349,1.8782 -Small,8x8,ldr-rgb-04.png,29.7749,0.1248,0.1113,0.5889 -Small,8x8,ldr-rgb-05.png,26.0242,0.1454,0.1320,0.4966 -Small,8x8,ldr-rgb-06.png,23.2335,0.1378,0.1244,0.5269 -Small,8x8,ldr-rgb-07.png,31.1039,0.1397,0.1260,0.5202 -Small,8x8,ldr-rgb-08.png,36.4625,0.0694,0.0563,1.1645 -Small,8x8,ldr-rgb-09.png,29.1520,0.1056,0.0925,0.7082 -Small,8x8,ldr-rgb-10.png,32.3031,0.0311,0.0203,0.7995 -Small,8x8,ldr-rgba-00.png,26.6704,0.1556,0.1416,0.4628 -Small,8x8,ldr-rgba-01.png,28.3932,0.1236,0.1102,0.5949 -Small,8x8,ldr-rgba-02.png,23.9599,0.1471,0.1334,0.4913 -Small,8x8,ldr-xy-00.png,34.3120,0.0871,0.0717,0.9146 -Small,8x8,ldr-xy-01.png,35.2097,0.0895,0.0744,0.8808 -Small,8x8,ldr-xy-02.png,44.5878,0.1132,0.0978,0.6698 -Small,8x8,ldrs-rgba-00.png,26.6715,0.1570,0.1430,0.4584 -Small,8x8,ldrs-rgba-01.png,28.3959,0.1228,0.1090,0.6010 -Small,8x8,ldrs-rgba-02.png,23.9597,0.1471,0.1338,0.4899 -Small,12x12,hdr-rgb-00.hdr,21.0019,0.2810,0.1700,0.3854 -Small,12x12,ldr-rgb-00.png,25.0133,0.1872,0.1642,0.3991 -Small,12x12,ldr-rgb-01.png,25.1167,0.1575,0.1347,0.4866 -Small,12x12,ldr-rgb-02.png,19.2912,0.1907,0.1677,0.3907 -Small,12x12,ldr-rgb-03.png,36.1206,0.0576,0.0350,1.8725 -Small,12x12,ldr-rgb-04.png,25.0074,0.1572,0.1344,0.4876 -Small,12x12,ldr-rgb-05.png,21.7140,0.1876,0.1645,0.3985 -Small,12x12,ldr-rgb-06.png,19.2810,0.1856,0.1624,0.4036 -Small,12x12,ldr-rgb-07.png,27.0419,0.1702,0.1466,0.4470 -Small,12x12,ldr-rgb-08.png,32.3840,0.0790,0.0561,1.1686 -Small,12x12,ldr-rgb-09.png,24.3053,0.1488,0.1257,0.5213 -Small,12x12,ldr-rgb-10.png,28.1356,0.0548,0.0348,0.4676 -Small,12x12,ldr-rgba-00.png,22.7010,0.2002,0.1765,0.3712 -Small,12x12,ldr-rgba-01.png,24.7078,0.1492,0.1256,0.5219 -Small,12x12,ldr-rgba-02.png,20.1958,0.1957,0.1723,0.3804 -Small,12x12,ldr-xy-00.png,30.5742,0.1175,0.0923,0.7104 -Small,12x12,ldr-xy-01.png,32.1255,0.0886,0.0639,1.0256 -Small,12x12,ldr-xy-02.png,40.3053,0.0645,0.0397,1.6525 -Small,12x12,ldrs-rgba-00.png,22.7006,0.1999,0.1760,0.3723 -Small,12x12,ldrs-rgba-01.png,24.7093,0.1483,0.1249,0.5247 -Small,12x12,ldrs-rgba-02.png,20.1960,0.1979,0.1736,0.3776 -Small,3x3x3,ldr-l-00-3.dds,52.4159,0.0563,0.0484,5.4142 -Small,3x3x3,ldr-l-01-3.dds,55.3973,0.0242,0.0191,3.6079 -Small,6x6x6,ldr-l-00-3.dds,33.2725,0.1434,0.1174,2.2327 -Small,6x6x6,ldr-l-01-3.dds,41.5751,0.0479,0.0245,2.8120 diff --git a/Test/Images/Small/astc_reference-4.3-avx2_fast_results.csv b/Test/Images/Small/astc_reference-4.3-avx2_fast_results.csv new file mode 100644 index 0000000..f9bc6e8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-avx2_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7131,0.0965,0.0119,5.4851 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0028,0.0004,0.6039 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0028,0.0005,0.5639 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0004,0.5845 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0028,0.0004,0.5871 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0028,0.0004,0.5900 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0029,0.0004,0.5779 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0029,0.0004,0.5791 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0028,0.0004,0.5845 +Small,4x4,ldr-rgb-00.png,38.2268,0.0132,0.0079,8.2884 +Small,4x4,ldr-rgb-01.png,39.9056,0.0119,0.0068,9.6054 +Small,4x4,ldr-rgb-02.png,35.1296,0.0156,0.0106,6.2119 +Small,4x4,ldr-rgb-03.png,46.0570,0.0072,0.0024,27.0922 +Small,4x4,ldr-rgb-04.png,41.9409,0.0096,0.0046,14.1216 +Small,4x4,ldr-rgb-05.png,37.3207,0.0155,0.0105,6.2565 +Small,4x4,ldr-rgb-06.png,35.3350,0.0147,0.0096,6.8444 +Small,4x4,ldr-rgb-07.png,38.1282,0.0159,0.0109,6.0352 +Small,4x4,ldr-rgb-08.png,43.8182,0.0085,0.0038,17.1788 +Small,4x4,ldr-rgb-09.png,41.8937,0.0097,0.0048,13.5541 +Small,4x4,ldr-rgb-10.png,44.4076,0.0042,0.0012,13.1424 +Small,4x4,ldr-rgba-00.png,35.5904,0.0158,0.0104,6.2966 +Small,4x4,ldr-rgba-01.png,38.8444,0.0114,0.0061,10.6927 +Small,4x4,ldr-rgba-02.png,34.8609,0.0141,0.0087,7.5198 +Small,4x4,ldr-xy-00.png,37.5753,0.0115,0.0042,15.5668 +Small,4x4,ldr-xy-01.png,44.1942,0.0125,0.0052,12.6125 +Small,4x4,ldr-xy-02.png,48.2321,0.0104,0.0033,19.9259 +Small,4x4,ldrs-rgba-00.png,35.5961,0.0158,0.0106,6.2060 +Small,4x4,ldrs-rgba-01.png,38.8644,0.0115,0.0063,10.4676 +Small,4x4,ldrs-rgba-02.png,34.8622,0.0141,0.0088,7.4430 +Small,5x5,hdr-rgb-00.hdr,29.4941,0.0968,0.0120,5.4532 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.6022 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5955 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5754 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.6125 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.6053 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5926 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5913 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5884 +Small,5x5,ldr-rgb-00.png,34.4207,0.0133,0.0075,8.7080 +Small,5x5,ldr-rgb-01.png,36.2361,0.0107,0.0050,13.1282 +Small,5x5,ldr-rgb-02.png,31.0781,0.0138,0.0080,8.1535 +Small,5x5,ldr-rgb-03.png,42.7340,0.0075,0.0022,30.2696 +Small,5x5,ldr-rgb-04.png,37.2632,0.0099,0.0043,15.2194 +Small,5x5,ldr-rgb-05.png,33.2658,0.0158,0.0102,6.4504 +Small,5x5,ldr-rgb-06.png,31.1162,0.0135,0.0078,8.3753 +Small,5x5,ldr-rgb-07.png,35.0545,0.0140,0.0083,7.8798 +Small,5x5,ldr-rgb-08.png,40.1761,0.0087,0.0032,20.7064 +Small,5x5,ldr-rgb-09.png,37.2884,0.0100,0.0043,15.3409 +Small,5x5,ldr-rgb-10.png,40.1912,0.0048,0.0011,14.4241 +Small,5x5,ldr-rgba-00.png,32.1049,0.0165,0.0107,6.1420 +Small,5x5,ldr-rgba-01.png,35.1901,0.0117,0.0058,11.3207 +Small,5x5,ldr-rgba-02.png,31.1173,0.0141,0.0081,8.0889 +Small,5x5,ldr-xy-00.png,36.7217,0.0118,0.0035,18.5540 +Small,5x5,ldr-xy-01.png,39.7502,0.0123,0.0042,15.4634 +Small,5x5,ldr-xy-02.png,43.9350,0.0113,0.0031,20.9192 +Small,5x5,ldrs-rgba-00.png,32.1059,0.0166,0.0106,6.1880 +Small,5x5,ldrs-rgba-01.png,35.1983,0.0116,0.0057,11.4916 +Small,5x5,ldrs-rgba-02.png,31.1181,0.0142,0.0082,7.9571 +Small,6x6,hdr-rgb-00.hdr,27.0493,0.0970,0.0118,5.5643 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5334 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5820 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5926 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5995 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5845 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5874 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5896 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5887 +Small,6x6,ldr-rgb-00.png,31.7043,0.0146,0.0089,7.3735 +Small,6x6,ldr-rgb-01.png,32.9205,0.0115,0.0060,10.9740 +Small,6x6,ldr-rgb-02.png,27.4737,0.0141,0.0085,7.7402 +Small,6x6,ldr-rgb-03.png,40.5514,0.0073,0.0020,32.3805 +Small,6x6,ldr-rgb-04.png,33.9239,0.0104,0.0049,13.4929 +Small,6x6,ldr-rgb-05.png,29.9695,0.0170,0.0115,5.7191 +Small,6x6,ldr-rgb-06.png,27.5383,0.0140,0.0084,7.8011 +Small,6x6,ldr-rgb-07.png,32.9325,0.0135,0.0079,8.2499 +Small,6x6,ldr-rgb-08.png,37.7991,0.0084,0.0031,21.0328 +Small,6x6,ldr-rgb-09.png,33.4925,0.0107,0.0051,12.8809 +Small,6x6,ldr-rgb-10.png,36.6382,0.0048,0.0013,12.8404 +Small,6x6,ldr-rgba-00.png,29.6020,0.0179,0.0120,5.4505 +Small,6x6,ldr-rgba-01.png,32.0799,0.0122,0.0064,10.2269 +Small,6x6,ldr-rgba-02.png,27.8399,0.0150,0.0090,7.2931 +Small,6x6,ldr-xy-00.png,35.8063,0.0115,0.0035,18.6446 +Small,6x6,ldr-xy-01.png,37.1041,0.0130,0.0050,13.0577 +Small,6x6,ldr-xy-02.png,41.9418,0.0108,0.0029,22.3369 +Small,6x6,ldrs-rgba-00.png,29.5967,0.0179,0.0121,5.4359 +Small,6x6,ldrs-rgba-01.png,32.0856,0.0123,0.0065,10.1401 +Small,6x6,ldrs-rgba-02.png,27.8376,0.0148,0.0091,7.2264 +Small,8x8,hdr-rgb-00.hdr,23.7764,0.0997,0.0142,4.6165 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0036,0.0004,0.5884 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0036,0.0004,0.5727 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0004,0.5845 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5832 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5900 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0004,0.5807 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0004,0.5884 +Small,8x8,ldr-rgb-00.png,28.0488,0.0157,0.0096,6.8110 +Small,8x8,ldr-rgb-01.png,28.7761,0.0132,0.0075,8.7452 +Small,8x8,ldr-rgb-02.png,23.1000,0.0171,0.0113,5.7940 +Small,8x8,ldr-rgb-03.png,37.3080,0.0077,0.0022,29.7358 +Small,8x8,ldr-rgb-04.png,29.3451,0.0127,0.0070,9.3988 +Small,8x8,ldr-rgb-05.png,25.8017,0.0190,0.0132,4.9588 +Small,8x8,ldr-rgb-06.png,23.1661,0.0176,0.0117,5.6231 +Small,8x8,ldr-rgb-07.png,29.8439,0.0134,0.0076,8.6266 +Small,8x8,ldr-rgb-08.png,34.4683,0.0091,0.0034,19.3209 +Small,8x8,ldr-rgb-09.png,28.6358,0.0121,0.0064,10.2689 +Small,8x8,ldr-rgb-10.png,31.9939,0.0053,0.0015,10.6602 +Small,8x8,ldr-rgba-00.png,25.6784,0.0192,0.0131,4.9849 +Small,8x8,ldr-rgba-01.png,28.2720,0.0148,0.0088,7.4693 +Small,8x8,ldr-rgba-02.png,23.9333,0.0187,0.0126,5.1902 +Small,8x8,ldr-xy-00.png,33.3023,0.0130,0.0045,14.6805 +Small,8x8,ldr-xy-01.png,34.4386,0.0138,0.0053,12.2609 +Small,8x8,ldr-xy-02.png,39.9000,0.0104,0.0020,32.4915 +Small,8x8,ldrs-rgba-00.png,25.6786,0.0192,0.0133,4.9401 +Small,8x8,ldrs-rgba-01.png,28.2748,0.0151,0.0089,7.3405 +Small,8x8,ldrs-rgba-02.png,23.9335,0.0188,0.0126,5.2034 +Small,12x12,hdr-rgb-00.hdr,20.5354,0.1082,0.0207,3.1687 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0055,0.0005,0.4716 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0056,0.0005,0.5639 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0056,0.0005,0.5578 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0056,0.0004,0.5804 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0056,0.0005,0.5613 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0055,0.0004,0.5896 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0004,0.5942 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0054,0.0004,0.5896 +Small,12x12,ldr-rgb-00.png,23.7994,0.0164,0.0084,7.7592 +Small,12x12,ldr-rgb-01.png,24.7706,0.0138,0.0061,10.8058 +Small,12x12,ldr-rgb-02.png,19.2291,0.0212,0.0135,4.8466 +Small,12x12,ldr-rgb-03.png,33.2407,0.0090,0.0016,41.1864 +Small,12x12,ldr-rgb-04.png,24.5750,0.0134,0.0057,11.5480 +Small,12x12,ldr-rgb-05.png,21.4889,0.0198,0.0119,5.4999 +Small,12x12,ldr-rgb-06.png,19.2240,0.0218,0.0140,4.6839 +Small,12x12,ldr-rgb-07.png,25.3851,0.0133,0.0057,11.5953 +Small,12x12,ldr-rgb-08.png,30.2920,0.0101,0.0027,24.1206 +Small,12x12,ldr-rgb-09.png,23.7357,0.0150,0.0074,8.9116 +Small,12x12,ldr-rgb-10.png,27.3235,0.0075,0.0019,8.4973 +Small,12x12,ldr-rgba-00.png,21.6066,0.0213,0.0134,4.8751 +Small,12x12,ldr-rgba-01.png,24.5233,0.0152,0.0072,9.0545 +Small,12x12,ldr-rgba-02.png,20.1709,0.0240,0.0159,4.1185 +Small,12x12,ldr-xy-00.png,29.2241,0.0159,0.0047,14.0488 +Small,12x12,ldr-xy-01.png,30.5471,0.0152,0.0041,15.9646 +Small,12x12,ldr-xy-02.png,37.9951,0.0120,0.0010,63.1468 +Small,12x12,ldrs-rgba-00.png,21.6105,0.0215,0.0136,4.8170 +Small,12x12,ldrs-rgba-01.png,24.5251,0.0154,0.0073,8.9738 +Small,12x12,ldrs-rgba-02.png,20.1707,0.0239,0.0158,4.1407 +Small,3x3x3,ldr-l-00-3.dds,50.8346,0.0152,0.0074,35.2577 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0073,0.0032,21.6520 +Small,6x6x6,ldr-l-00-3.dds,32.5376,0.0456,0.0346,7.5767 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0210,0.0133,5.1847 diff --git a/Test/Images/Small/astc_reference-4.3-avx2_fastest_results.csv b/Test/Images/Small/astc_reference-4.3-avx2_fastest_results.csv new file mode 100644 index 0000000..9544232 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-avx2_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3308,0.0916,0.0073,8.9689 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0022,0.0004,0.5955 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0022,0.0004,0.5896 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.5871 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0022,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0023,0.0004,0.5995 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0022,0.0004,0.5858 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.6094 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0022,0.0004,0.5900 +Small,4x4,ldr-rgb-00.png,37.2237,0.0093,0.0046,14.1821 +Small,4x4,ldr-rgb-01.png,39.5245,0.0084,0.0040,16.2659 +Small,4x4,ldr-rgb-02.png,34.7577,0.0103,0.0059,11.1589 +Small,4x4,ldr-rgb-03.png,45.4692,0.0060,0.0018,36.2063 +Small,4x4,ldr-rgb-04.png,41.6640,0.0075,0.0030,21.5591 +Small,4x4,ldr-rgb-05.png,36.8562,0.0106,0.0061,10.6948 +Small,4x4,ldr-rgb-06.png,34.9322,0.0099,0.0055,11.9898 +Small,4x4,ldr-rgb-07.png,37.3406,0.0102,0.0058,11.2664 +Small,4x4,ldr-rgb-08.png,42.9161,0.0067,0.0025,26.0153 +Small,4x4,ldr-rgb-09.png,41.7016,0.0075,0.0031,21.0651 +Small,4x4,ldr-rgb-10.png,43.9130,0.0035,0.0010,15.6167 +Small,4x4,ldr-rgba-00.png,34.7268,0.0105,0.0058,11.3328 +Small,4x4,ldr-rgba-01.png,38.6479,0.0091,0.0044,14.7530 +Small,4x4,ldr-rgba-02.png,34.5493,0.0109,0.0062,10.6373 +Small,4x4,ldr-xy-00.png,37.5056,0.0096,0.0031,21.0925 +Small,4x4,ldr-xy-01.png,43.8548,0.0103,0.0038,17.3688 +Small,4x4,ldr-xy-02.png,48.2399,0.0092,0.0026,25.5796 +Small,4x4,ldrs-rgba-00.png,34.7310,0.0105,0.0058,11.2738 +Small,4x4,ldrs-rgba-01.png,38.6664,0.0091,0.0044,15.0618 +Small,4x4,ldrs-rgba-02.png,34.5527,0.0110,0.0062,10.6373 +Small,5x5,hdr-rgb-00.hdr,28.8495,0.0918,0.0074,8.9032 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5791 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5820 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5939 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5939 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5982 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5900 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5926 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5900 +Small,5x5,ldr-rgb-00.png,33.7101,0.0093,0.0043,15.1248 +Small,5x5,ldr-rgb-01.png,36.0660,0.0084,0.0036,18.4197 +Small,5x5,ldr-rgb-02.png,30.9741,0.0105,0.0057,11.4532 +Small,5x5,ldr-rgb-03.png,42.3108,0.0062,0.0017,39.2627 +Small,5x5,ldr-rgb-04.png,37.0268,0.0081,0.0032,20.4416 +Small,5x5,ldr-rgb-05.png,32.9511,0.0112,0.0064,10.2429 +Small,5x5,ldr-rgb-06.png,31.0218,0.0105,0.0056,11.7339 +Small,5x5,ldr-rgb-07.png,34.4024,0.0101,0.0054,12.1654 +Small,5x5,ldr-rgb-08.png,39.5680,0.0068,0.0022,29.2175 +Small,5x5,ldr-rgb-09.png,37.0647,0.0079,0.0031,20.8509 +Small,5x5,ldr-rgb-10.png,39.8999,0.0038,0.0010,16.4891 +Small,5x5,ldr-rgba-00.png,31.0999,0.0110,0.0059,11.0775 +Small,5x5,ldr-rgba-01.png,35.0302,0.0093,0.0042,15.6190 +Small,5x5,ldr-rgba-02.png,31.0219,0.0114,0.0062,10.5857 +Small,5x5,ldr-xy-00.png,36.6320,0.0099,0.0027,24.3535 +Small,5x5,ldr-xy-01.png,39.1493,0.0104,0.0031,21.3199 +Small,5x5,ldr-xy-02.png,43.8491,0.0097,0.0024,27.1056 +Small,5x5,ldrs-rgba-00.png,31.1012,0.0111,0.0059,11.0557 +Small,5x5,ldrs-rgba-01.png,35.0367,0.0092,0.0043,15.4019 +Small,5x5,ldrs-rgba-02.png,31.0226,0.0114,0.0062,10.5313 +Small,6x6,hdr-rgb-00.hdr,26.7317,0.0912,0.0067,9.7554 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5804 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5926 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5952 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.6125 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.6009 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5926 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5969 +Small,6x6,ldr-rgb-00.png,31.3212,0.0098,0.0049,13.3884 +Small,6x6,ldr-rgb-01.png,32.8336,0.0088,0.0041,16.0823 +Small,6x6,ldr-rgb-02.png,27.3837,0.0107,0.0060,10.9317 +Small,6x6,ldr-rgb-03.png,40.3163,0.0061,0.0016,42.1204 +Small,6x6,ldr-rgb-04.png,33.7482,0.0083,0.0036,18.2911 +Small,6x6,ldr-rgb-05.png,29.7352,0.0118,0.0070,9.3998 +Small,6x6,ldr-rgb-06.png,27.4658,0.0109,0.0060,10.8506 +Small,6x6,ldr-rgb-07.png,32.3326,0.0097,0.0050,13.1313 +Small,6x6,ldr-rgb-08.png,37.4336,0.0067,0.0021,30.6407 +Small,6x6,ldr-rgb-09.png,33.3061,0.0083,0.0036,18.3840 +Small,6x6,ldr-rgb-10.png,36.5144,0.0039,0.0011,15.2363 +Small,6x6,ldr-rgba-00.png,28.8377,0.0110,0.0060,10.8759 +Small,6x6,ldr-rgba-01.png,31.9912,0.0096,0.0046,14.2564 +Small,6x6,ldr-rgba-02.png,27.7796,0.0113,0.0062,10.6233 +Small,6x6,ldr-xy-00.png,35.6056,0.0098,0.0027,24.4445 +Small,6x6,ldr-xy-01.png,36.4953,0.0104,0.0034,19.1566 +Small,6x6,ldr-xy-02.png,41.7981,0.0093,0.0023,28.6690 +Small,6x6,ldrs-rgba-00.png,28.8345,0.0113,0.0062,10.5329 +Small,6x6,ldrs-rgba-01.png,31.9977,0.0097,0.0046,14.1821 +Small,6x6,ldrs-rgba-02.png,27.7778,0.0113,0.0062,10.5669 +Small,8x8,hdr-rgb-00.hdr,23.6038,0.0957,0.0098,6.6975 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5982 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.6185 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5820 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.6053 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5871 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5995 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.6039 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5751 +Small,8x8,ldr-rgb-00.png,27.7031,0.0125,0.0068,9.6350 +Small,8x8,ldr-rgb-01.png,28.6850,0.0113,0.0057,11.4671 +Small,8x8,ldr-rgb-02.png,23.0240,0.0141,0.0084,7.8308 +Small,8x8,ldr-rgb-03.png,37.0258,0.0070,0.0018,36.1634 +Small,8x8,ldr-rgb-04.png,29.1260,0.0108,0.0052,12.6789 +Small,8x8,ldr-rgb-05.png,25.6018,0.0154,0.0097,6.7900 +Small,8x8,ldr-rgb-06.png,23.0810,0.0144,0.0087,7.5458 +Small,8x8,ldr-rgb-07.png,29.4659,0.0111,0.0056,11.7489 +Small,8x8,ldr-rgb-08.png,33.9551,0.0080,0.0026,25.5915 +Small,8x8,ldr-rgb-09.png,28.4493,0.0106,0.0050,13.1414 +Small,8x8,ldr-rgb-10.png,31.9058,0.0049,0.0012,13.0368 +Small,8x8,ldr-rgba-00.png,25.3128,0.0148,0.0089,7.3273 +Small,8x8,ldr-rgba-01.png,28.1781,0.0123,0.0065,10.1435 +Small,8x8,ldr-rgba-02.png,23.8711,0.0148,0.0089,7.3977 +Small,8x8,ldr-xy-00.png,33.2750,0.0119,0.0036,18.3828 +Small,8x8,ldr-xy-01.png,34.1754,0.0124,0.0040,16.2987 +Small,8x8,ldr-xy-02.png,39.7771,0.0099,0.0017,39.4090 +Small,8x8,ldrs-rgba-00.png,25.3134,0.0148,0.0089,7.3520 +Small,8x8,ldrs-rgba-01.png,28.1794,0.0122,0.0064,10.1875 +Small,8x8,ldrs-rgba-02.png,23.8706,0.0147,0.0088,7.4864 +Small,12x12,hdr-rgb-00.hdr,20.4510,0.1015,0.0144,4.5666 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0049,0.0004,0.6111 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0048,0.0004,0.5939 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0049,0.0004,0.6171 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5939 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0004,0.6066 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5730 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5965 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0004,0.6167 +Small,12x12,ldr-rgb-00.png,23.7098,0.0134,0.0061,10.8288 +Small,12x12,ldr-rgb-01.png,24.7256,0.0115,0.0043,15.1107 +Small,12x12,ldr-rgb-02.png,19.1930,0.0167,0.0095,6.8994 +Small,12x12,ldr-rgb-03.png,33.1431,0.0081,0.0013,48.8325 +Small,12x12,ldr-rgb-04.png,24.3870,0.0115,0.0043,15.0692 +Small,12x12,ldr-rgb-05.png,21.3834,0.0158,0.0086,7.6215 +Small,12x12,ldr-rgb-06.png,19.1690,0.0170,0.0098,6.6833 +Small,12x12,ldr-rgb-07.png,25.3142,0.0114,0.0042,15.6599 +Small,12x12,ldr-rgb-08.png,30.1204,0.0090,0.0021,31.6753 +Small,12x12,ldr-rgb-09.png,23.5983,0.0126,0.0055,11.9699 +Small,12x12,ldr-rgb-10.png,27.2834,0.0066,0.0014,11.3600 +Small,12x12,ldr-rgba-00.png,21.3613,0.0167,0.0092,7.1460 +Small,12x12,ldr-rgba-01.png,24.4808,0.0128,0.0053,12.3142 +Small,12x12,ldr-rgba-02.png,20.1381,0.0187,0.0113,5.8115 +Small,12x12,ldr-xy-00.png,28.8908,0.0141,0.0036,18.1390 +Small,12x12,ldr-xy-01.png,29.6770,0.0137,0.0032,20.6287 +Small,12x12,ldr-xy-02.png,37.9716,0.0114,0.0010,64.6315 +Small,12x12,ldrs-rgba-00.png,21.3627,0.0168,0.0094,6.9549 +Small,12x12,ldrs-rgba-01.png,24.4817,0.0128,0.0053,12.2609 +Small,12x12,ldrs-rgba-02.png,20.1379,0.0188,0.0114,5.7721 +Small,3x3x3,ldr-l-00-3.dds,50.6979,0.0141,0.0074,35.6267 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0065,0.0032,21.8781 +Small,6x6x6,ldr-l-00-3.dds,32.5210,0.0455,0.0346,7.5725 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0211,0.0134,5.1472 diff --git a/Test/Images/Small/astc_reference-4.3-avx2_medium_results.csv b/Test/Images/Small/astc_reference-4.3-avx2_medium_results.csv new file mode 100644 index 0000000..1ef9470 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-avx2_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1238,0.1034,0.0181,3.6288 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0037,0.0005,0.4785 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5651 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0005,0.5321 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5423 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5791 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5742 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5714 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5804 +Small,4x4,ldr-rgb-00.png,38.8091,0.0258,0.0198,3.3111 +Small,4x4,ldr-rgb-01.png,40.2008,0.0225,0.0168,3.9082 +Small,4x4,ldr-rgb-02.png,35.2658,0.0231,0.0173,3.7849 +Small,4x4,ldr-rgb-03.png,47.2399,0.0151,0.0098,6.7174 +Small,4x4,ldr-rgb-04.png,42.1842,0.0190,0.0132,4.9751 +Small,4x4,ldr-rgb-05.png,37.7989,0.0249,0.0191,3.4312 +Small,4x4,ldr-rgb-06.png,35.4538,0.0209,0.0151,4.3315 +Small,4x4,ldr-rgb-07.png,39.2651,0.0303,0.0246,2.6676 +Small,4x4,ldr-rgb-08.png,45.1580,0.0176,0.0121,5.4073 +Small,4x4,ldr-rgb-09.png,42.1202,0.0192,0.0135,4.8581 +Small,4x4,ldr-rgb-10.png,44.8973,0.0060,0.0023,7.0648 +Small,4x4,ldr-rgba-00.png,36.2355,0.0279,0.0220,2.9849 +Small,4x4,ldr-rgba-01.png,38.9520,0.0187,0.0126,5.2062 +Small,4x4,ldr-rgba-02.png,34.9310,0.0200,0.0139,4.7176 +Small,4x4,ldr-xy-00.png,37.7517,0.0188,0.0115,5.7063 +Small,4x4,ldr-xy-01.png,45.1812,0.0251,0.0178,3.6886 +Small,4x4,ldr-xy-02.png,50.9688,0.0293,0.0220,2.9851 +Small,4x4,ldrs-rgba-00.png,36.2429,0.0281,0.0221,2.9613 +Small,4x4,ldrs-rgba-01.png,38.9706,0.0187,0.0126,5.1861 +Small,4x4,ldrs-rgba-02.png,34.9330,0.0201,0.0140,4.6708 +Small,5x5,hdr-rgb-00.hdr,29.8792,0.1060,0.0197,3.3260 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0046,0.0005,0.4724 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0004,0.5791 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0005,0.5628 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0004,0.5764 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0046,0.0004,0.5926 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0046,0.0004,0.5913 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0004,0.5955 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5589 +Small,5x5,ldr-rgb-00.png,35.1353,0.0272,0.0202,3.2421 +Small,5x5,ldr-rgb-01.png,36.4365,0.0210,0.0143,4.5880 +Small,5x5,ldr-rgb-02.png,31.1195,0.0215,0.0146,4.4759 +Small,5x5,ldr-rgb-03.png,43.9924,0.0124,0.0060,10.9925 +Small,5x5,ldr-rgb-04.png,37.6527,0.0198,0.0130,5.0257 +Small,5x5,ldr-rgb-05.png,33.5357,0.0280,0.0212,3.0899 +Small,5x5,ldr-rgb-06.png,31.1617,0.0209,0.0140,4.6946 +Small,5x5,ldr-rgb-07.png,36.1275,0.0311,0.0243,2.6947 +Small,5x5,ldr-rgb-08.png,41.6131,0.0166,0.0102,6.4491 +Small,5x5,ldr-rgb-09.png,37.5769,0.0191,0.0122,5.3749 +Small,5x5,ldr-rgb-10.png,40.5644,0.0071,0.0024,6.8505 +Small,5x5,ldr-rgba-00.png,32.7897,0.0314,0.0245,2.6803 +Small,5x5,ldr-rgba-01.png,35.3090,0.0202,0.0131,4.9910 +Small,5x5,ldr-rgba-02.png,31.1309,0.0217,0.0145,4.5083 +Small,5x5,ldr-xy-00.png,37.0786,0.0191,0.0106,6.1985 +Small,5x5,ldr-xy-01.png,40.5669,0.0241,0.0157,4.1613 +Small,5x5,ldr-xy-02.png,49.0821,0.0200,0.0115,5.6973 +Small,5x5,ldrs-rgba-00.png,32.7935,0.0317,0.0247,2.6484 +Small,5x5,ldrs-rgba-01.png,35.3182,0.0203,0.0133,4.9338 +Small,5x5,ldrs-rgba-02.png,31.1320,0.0219,0.0148,4.4380 +Small,6x6,hdr-rgb-00.hdr,27.4934,0.1065,0.0203,3.2333 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0005,0.5495 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0044,0.0004,0.5727 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0005,0.5437 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0044,0.0005,0.5321 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0043,0.0004,0.5858 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0043,0.0004,0.5845 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0004,0.5913 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0043,0.0004,0.5995 +Small,6x6,ldr-rgb-00.png,32.3857,0.0275,0.0208,3.1581 +Small,6x6,ldr-rgb-01.png,33.0813,0.0205,0.0140,4.6972 +Small,6x6,ldr-rgb-02.png,27.5038,0.0212,0.0147,4.4619 +Small,6x6,ldr-rgb-03.png,41.7098,0.0110,0.0047,14.0934 +Small,6x6,ldr-rgb-04.png,34.1976,0.0186,0.0120,5.4451 +Small,6x6,ldr-rgb-05.png,30.1358,0.0280,0.0213,3.0747 +Small,6x6,ldr-rgb-06.png,27.5712,0.0209,0.0143,4.5711 +Small,6x6,ldr-rgb-07.png,33.8773,0.0294,0.0229,2.8611 +Small,6x6,ldr-rgb-08.png,39.1910,0.0140,0.0077,8.5557 +Small,6x6,ldr-rgb-09.png,33.6644,0.0181,0.0114,5.7302 +Small,6x6,ldr-rgb-10.png,36.9239,0.0071,0.0025,6.4021 +Small,6x6,ldr-rgba-00.png,30.2372,0.0334,0.0267,2.4567 +Small,6x6,ldr-rgba-01.png,32.1918,0.0204,0.0136,4.8217 +Small,6x6,ldr-rgba-02.png,27.8514,0.0227,0.0157,4.1871 +Small,6x6,ldr-xy-00.png,36.2476,0.0173,0.0091,7.2399 +Small,6x6,ldr-xy-01.png,37.9375,0.0196,0.0115,5.6741 +Small,6x6,ldr-xy-02.png,46.0669,0.0164,0.0084,7.8431 +Small,6x6,ldrs-rgba-00.png,30.2354,0.0333,0.0266,2.4656 +Small,6x6,ldrs-rgba-01.png,32.1978,0.0204,0.0136,4.8163 +Small,6x6,ldrs-rgba-02.png,27.8496,0.0227,0.0158,4.1468 +Small,8x8,hdr-rgb-00.hdr,24.1284,0.1122,0.0252,2.5996 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0050,0.0006,0.4523 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0050,0.0005,0.5578 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0050,0.0004,0.5767 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0050,0.0004,0.5742 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0050,0.0005,0.5481 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5702 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0050,0.0004,0.5754 +Small,8x8,ldr-rgb-00.png,28.7284,0.0347,0.0274,2.3920 +Small,8x8,ldr-rgb-01.png,28.9370,0.0246,0.0175,3.7529 +Small,8x8,ldr-rgb-02.png,23.1614,0.0261,0.0190,3.4573 +Small,8x8,ldr-rgb-03.png,38.5560,0.0123,0.0054,12.0497 +Small,8x8,ldr-rgb-04.png,29.6453,0.0244,0.0171,3.8260 +Small,8x8,ldr-rgb-05.png,25.9412,0.0330,0.0257,2.5457 +Small,8x8,ldr-rgb-06.png,23.2047,0.0266,0.0192,3.4046 +Small,8x8,ldr-rgb-07.png,30.7489,0.0342,0.0271,2.4222 +Small,8x8,ldr-rgb-08.png,35.9057,0.0164,0.0093,7.0545 +Small,8x8,ldr-rgb-09.png,28.9902,0.0226,0.0155,4.2240 +Small,8x8,ldr-rgb-10.png,32.1710,0.0085,0.0033,4.9201 +Small,8x8,ldr-rgba-00.png,26.4438,0.0400,0.0325,2.0151 +Small,8x8,ldr-rgba-01.png,28.3668,0.0249,0.0174,3.7660 +Small,8x8,ldr-rgba-02.png,23.9414,0.0284,0.0208,3.1467 +Small,8x8,ldr-xy-00.png,33.9206,0.0225,0.0123,5.3126 +Small,8x8,ldr-xy-01.png,34.9386,0.0225,0.0124,5.2771 +Small,8x8,ldr-xy-02.png,41.6877,0.0182,0.0083,7.9360 +Small,8x8,ldrs-rgba-00.png,26.4457,0.0403,0.0328,1.9977 +Small,8x8,ldrs-rgba-01.png,28.3703,0.0248,0.0174,3.7668 +Small,8x8,ldrs-rgba-02.png,23.9416,0.0283,0.0208,3.1461 +Small,12x12,hdr-rgb-00.hdr,20.7755,0.1269,0.0367,1.7853 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0078,0.0005,0.5678 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0078,0.0004,0.5767 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0078,0.0004,0.5817 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0078,0.0004,0.5845 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0080,0.0005,0.5060 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0078,0.0005,0.5437 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0078,0.0004,0.5730 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0078,0.0004,0.5751 +Small,12x12,ldr-rgb-00.png,24.6915,0.0432,0.0329,1.9905 +Small,12x12,ldr-rgb-01.png,25.0393,0.0326,0.0226,2.9057 +Small,12x12,ldr-rgb-02.png,19.2743,0.0377,0.0275,2.3852 +Small,12x12,ldr-rgb-03.png,34.9505,0.0157,0.0058,11.2351 +Small,12x12,ldr-rgb-04.png,24.9006,0.0319,0.0218,3.0125 +Small,12x12,ldr-rgb-05.png,21.6514,0.0432,0.0331,1.9775 +Small,12x12,ldr-rgb-06.png,19.2513,0.0383,0.0281,2.3290 +Small,12x12,ldr-rgb-07.png,26.7396,0.0397,0.0296,2.2117 +Small,12x12,ldr-rgb-08.png,31.6566,0.0201,0.0102,6.4472 +Small,12x12,ldr-rgb-09.png,24.1576,0.0306,0.0206,3.1861 +Small,12x12,ldr-rgb-10.png,28.0433,0.0145,0.0065,2.4941 +Small,12x12,ldr-rgba-00.png,22.2473,0.0479,0.0376,1.7419 +Small,12x12,ldr-rgba-01.png,24.6500,0.0321,0.0217,3.0135 +Small,12x12,ldr-rgba-02.png,20.1848,0.0410,0.0305,2.1494 +Small,12x12,ldr-xy-00.png,30.2110,0.0285,0.0147,4.4471 +Small,12x12,ldr-xy-01.png,31.8412,0.0294,0.0153,4.2857 +Small,12x12,ldr-xy-02.png,38.5222,0.0174,0.0036,18.0996 +Small,12x12,ldrs-rgba-00.png,22.2476,0.0478,0.0372,1.7638 +Small,12x12,ldrs-rgba-01.png,24.6522,0.0322,0.0218,3.0100 +Small,12x12,ldrs-rgba-02.png,20.1848,0.0412,0.0305,2.1503 +Small,3x3x3,ldr-l-00-3.dds,51.8769,0.0193,0.0108,24.3110 +Small,3x3x3,ldr-l-01-3.dds,54.6166,0.0084,0.0034,20.4989 +Small,6x6x6,ldr-l-00-3.dds,32.9597,0.0560,0.0424,6.1774 +Small,6x6x6,ldr-l-01-3.dds,41.0140,0.0235,0.0135,5.1128 diff --git a/Test/Images/Small/astc_reference-4.3-avx2_thorough_results.csv b/Test/Images/Small/astc_reference-4.3-avx2_thorough_results.csv new file mode 100644 index 0000000..7b7cfbb --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-avx2_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.3988,0.1207,0.0354,1.8527 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.4876 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5702 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5459 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5751 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0004,0.5702 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.6012 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0037,0.0005,0.5008 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0037,0.0005,0.5310 +Small,4x4,ldr-rgb-00.png,39.1396,0.0465,0.0407,1.6107 +Small,4x4,ldr-rgb-01.png,40.3879,0.0444,0.0386,1.6983 +Small,4x4,ldr-rgb-02.png,35.4469,0.0419,0.0360,1.8198 +Small,4x4,ldr-rgb-03.png,47.7050,0.0410,0.0356,1.8396 +Small,4x4,ldr-rgb-04.png,42.3343,0.0376,0.0318,2.0585 +Small,4x4,ldr-rgb-05.png,37.9716,0.0455,0.0396,1.6547 +Small,4x4,ldr-rgb-06.png,35.6101,0.0375,0.0315,2.0797 +Small,4x4,ldr-rgb-07.png,39.8550,0.0547,0.0490,1.3378 +Small,4x4,ldr-rgb-08.png,45.8141,0.0403,0.0348,1.8837 +Small,4x4,ldr-rgb-09.png,42.2663,0.0403,0.0345,1.9012 +Small,4x4,ldr-rgb-10.png,45.1134,0.0083,0.0046,3.5501 +Small,4x4,ldr-rgba-00.png,36.7024,0.0484,0.0423,1.5479 +Small,4x4,ldr-rgba-01.png,39.0829,0.0353,0.0293,2.2351 +Small,4x4,ldr-rgba-02.png,35.0183,0.0351,0.0290,2.2620 +Small,4x4,ldr-xy-00.png,37.7753,0.0459,0.0385,1.7007 +Small,4x4,ldr-xy-01.png,45.2569,0.0510,0.0439,1.4938 +Small,4x4,ldr-xy-02.png,50.9912,0.0625,0.0551,1.1890 +Small,4x4,ldrs-rgba-00.png,36.7104,0.0490,0.0429,1.5275 +Small,4x4,ldrs-rgba-01.png,39.1044,0.0357,0.0295,2.2189 +Small,4x4,ldrs-rgba-02.png,35.0233,0.0352,0.0291,2.2516 +Small,5x5,hdr-rgb-00.hdr,30.2809,0.1245,0.0381,1.7200 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0046,0.0005,0.4980 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0047,0.0005,0.5269 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0046,0.0005,0.5266 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0046,0.0004,0.5995 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5807 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0004,0.5817 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0046,0.0004,0.5699 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5613 +Small,5x5,ldr-rgb-00.png,35.3622,0.0520,0.0449,1.4595 +Small,5x5,ldr-rgb-01.png,36.5321,0.0458,0.0390,1.6795 +Small,5x5,ldr-rgb-02.png,31.1870,0.0403,0.0334,1.9607 +Small,5x5,ldr-rgb-03.png,44.5348,0.0447,0.0382,1.7153 +Small,5x5,ldr-rgb-04.png,37.8081,0.0413,0.0345,1.8992 +Small,5x5,ldr-rgb-05.png,33.6835,0.0521,0.0452,1.4495 +Small,5x5,ldr-rgb-06.png,31.2225,0.0377,0.0309,2.1219 +Small,5x5,ldr-rgb-07.png,36.7108,0.0618,0.0550,1.1906 +Small,5x5,ldr-rgb-08.png,42.3675,0.0442,0.0376,1.7435 +Small,5x5,ldr-rgb-09.png,37.6987,0.0452,0.0385,1.7017 +Small,5x5,ldr-rgb-10.png,40.7256,0.0101,0.0053,3.0626 +Small,5x5,ldr-rgba-00.png,33.0991,0.0562,0.0492,1.3317 +Small,5x5,ldr-rgba-01.png,35.4017,0.0394,0.0323,2.0285 +Small,5x5,ldr-rgba-02.png,31.1706,0.0382,0.0310,2.1111 +Small,5x5,ldr-xy-00.png,37.2351,0.0498,0.0415,1.5798 +Small,5x5,ldr-xy-01.png,41.4156,0.0592,0.0507,1.2932 +Small,5x5,ldr-xy-02.png,49.2617,0.0677,0.0590,1.1110 +Small,5x5,ldrs-rgba-00.png,33.1063,0.0564,0.0494,1.3263 +Small,5x5,ldrs-rgba-01.png,35.4095,0.0398,0.0327,2.0036 +Small,5x5,ldrs-rgba-02.png,31.1713,0.0385,0.0313,2.0912 +Small,6x6,hdr-rgb-00.hdr,27.6987,0.1260,0.0399,1.6413 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0004,0.5739 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0045,0.0004,0.5779 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0005,0.5687 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0005,0.5401 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0044,0.0005,0.5412 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5518 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0005,0.5192 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0005,0.5437 +Small,6x6,ldr-rgb-00.png,32.6236,0.0549,0.0480,1.3646 +Small,6x6,ldr-rgb-01.png,33.1855,0.0475,0.0409,1.6029 +Small,6x6,ldr-rgb-02.png,27.5522,0.0412,0.0346,1.8952 +Small,6x6,ldr-rgb-03.png,42.5760,0.0374,0.0311,2.1043 +Small,6x6,ldr-rgb-04.png,34.3279,0.0414,0.0349,1.8800 +Small,6x6,ldr-rgb-05.png,30.2792,0.0527,0.0460,1.4258 +Small,6x6,ldr-rgb-06.png,27.6242,0.0397,0.0330,1.9847 +Small,6x6,ldr-rgb-07.png,34.4221,0.0642,0.0576,1.1382 +Small,6x6,ldr-rgb-08.png,40.0080,0.0383,0.0318,2.0634 +Small,6x6,ldr-rgb-09.png,33.8156,0.0439,0.0373,1.7591 +Small,6x6,ldr-rgb-10.png,37.1747,0.0108,0.0062,2.6257 +Small,6x6,ldr-rgba-00.png,30.4928,0.0606,0.0536,1.2236 +Small,6x6,ldr-rgba-01.png,32.2722,0.0426,0.0357,1.8337 +Small,6x6,ldr-rgba-02.png,27.8884,0.0403,0.0332,1.9743 +Small,6x6,ldr-xy-00.png,36.3580,0.0402,0.0321,2.0441 +Small,6x6,ldr-xy-01.png,38.1144,0.0555,0.0473,1.3861 +Small,6x6,ldr-xy-02.png,47.4637,0.0678,0.0596,1.1002 +Small,6x6,ldrs-rgba-00.png,30.4894,0.0609,0.0541,1.2115 +Small,6x6,ldrs-rgba-01.png,32.2774,0.0432,0.0361,1.8163 +Small,6x6,ldrs-rgba-02.png,27.8865,0.0406,0.0336,1.9486 +Small,8x8,hdr-rgb-00.hdr,24.3310,0.1399,0.0516,1.2711 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0063,0.0005,0.5532 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0063,0.0004,0.5727 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0063,0.0004,0.5730 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0063,0.0004,0.5714 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0063,0.0004,0.5884 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0063,0.0004,0.5845 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0063,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0063,0.0004,0.5804 +Small,8x8,ldr-rgb-00.png,28.9743,0.0712,0.0619,1.0593 +Small,8x8,ldr-rgb-01.png,29.0250,0.0575,0.0490,1.3385 +Small,8x8,ldr-rgb-02.png,23.2010,0.0542,0.0454,1.4432 +Small,8x8,ldr-rgb-03.png,39.4059,0.0278,0.0194,3.3698 +Small,8x8,ldr-rgb-04.png,29.7753,0.0518,0.0431,1.5190 +Small,8x8,ldr-rgb-05.png,26.0443,0.0628,0.0541,1.2121 +Small,8x8,ldr-rgb-06.png,23.2548,0.0525,0.0437,1.5003 +Small,8x8,ldr-rgb-07.png,31.1954,0.0759,0.0672,0.9746 +Small,8x8,ldr-rgb-08.png,36.5527,0.0393,0.0309,2.1193 +Small,8x8,ldr-rgb-09.png,29.1512,0.0452,0.0367,1.7844 +Small,8x8,ldr-rgb-10.png,32.3269,0.0143,0.0076,2.1342 +Small,8x8,ldr-rgba-00.png,26.7456,0.0758,0.0670,0.9786 +Small,8x8,ldr-rgba-01.png,28.4290,0.0557,0.0468,1.3996 +Small,8x8,ldr-rgba-02.png,23.9672,0.0523,0.0432,1.5172 +Small,8x8,ldr-xy-00.png,34.1954,0.0465,0.0363,1.8065 +Small,8x8,ldr-xy-01.png,35.2284,0.0486,0.0384,1.7057 +Small,8x8,ldr-xy-02.png,44.4736,0.0613,0.0512,1.2804 +Small,8x8,ldrs-rgba-00.png,26.7460,0.0765,0.0677,0.9683 +Small,8x8,ldrs-rgba-01.png,28.4323,0.0556,0.0467,1.4022 +Small,8x8,ldrs-rgba-02.png,23.9676,0.0523,0.0433,1.5140 +Small,12x12,hdr-rgb-00.hdr,21.0278,0.1697,0.0771,0.8496 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0103,0.0004,0.5791 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0103,0.0004,0.5955 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0103,0.0004,0.5751 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0104,0.0004,0.5845 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0103,0.0004,0.5767 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0103,0.0004,0.5939 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0103,0.0004,0.5871 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0103,0.0005,0.5628 +Small,12x12,ldr-rgb-00.png,25.0567,0.0941,0.0812,0.8070 +Small,12x12,ldr-rgb-01.png,25.1428,0.0772,0.0646,1.0150 +Small,12x12,ldr-rgb-02.png,19.2937,0.0849,0.0722,0.9076 +Small,12x12,ldr-rgb-03.png,36.1599,0.0330,0.0208,3.1518 +Small,12x12,ldr-rgb-04.png,24.9934,0.0697,0.0571,1.1484 +Small,12x12,ldr-rgb-05.png,21.7356,0.0851,0.0722,0.9076 +Small,12x12,ldr-rgb-06.png,19.2955,0.0824,0.0693,0.9454 +Small,12x12,ldr-rgb-07.png,27.0999,0.0949,0.0823,0.7963 +Small,12x12,ldr-rgb-08.png,32.4850,0.0415,0.0290,2.2585 +Small,12x12,ldr-rgb-09.png,24.3014,0.0652,0.0526,1.2468 +Small,12x12,ldr-rgb-10.png,28.1869,0.0241,0.0135,1.2049 +Small,12x12,ldr-rgba-00.png,22.7181,0.0991,0.0860,0.7617 +Small,12x12,ldr-rgba-01.png,24.7277,0.0791,0.0658,0.9964 +Small,12x12,ldr-rgba-02.png,20.2040,0.0815,0.0685,0.9567 +Small,12x12,ldr-xy-00.png,30.5815,0.0621,0.0476,1.3755 +Small,12x12,ldr-xy-01.png,32.1781,0.0503,0.0359,1.8231 +Small,12x12,ldr-xy-02.png,40.2787,0.0376,0.0233,2.8185 +Small,12x12,ldrs-rgba-00.png,22.7169,0.0992,0.0862,0.7604 +Small,12x12,ldrs-rgba-01.png,24.7295,0.0791,0.0662,0.9903 +Small,12x12,ldrs-rgba-02.png,20.2043,0.0820,0.0690,0.9494 +Small,3x3x3,ldr-l-00-3.dds,52.3138,0.0328,0.0241,10.8638 +Small,3x3x3,ldr-l-01-3.dds,55.2511,0.0145,0.0095,7.2503 +Small,6x6x6,ldr-l-00-3.dds,33.2738,0.0775,0.0616,4.2523 +Small,6x6x6,ldr-l-01-3.dds,41.7409,0.0266,0.0138,4.9792 diff --git a/Test/Images/Small/astc_reference-4.3-sse2_fast_results.csv b/Test/Images/Small/astc_reference-4.3-sse2_fast_results.csv new file mode 100644 index 0000000..00a16c8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse2_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7131,0.1025,0.0151,4.3422 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0028,0.0005,0.5345 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0029,0.0004,0.5829 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0004,0.5699 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0028,0.0004,0.5887 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0028,0.0004,0.5858 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0028,0.0004,0.5776 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0028,0.0004,0.5779 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0028,0.0004,0.5751 +Small,4x4,ldr-rgb-00.png,38.2268,0.0156,0.0101,6.4900 +Small,4x4,ldr-rgb-01.png,39.9056,0.0136,0.0085,7.7027 +Small,4x4,ldr-rgb-02.png,35.1296,0.0188,0.0136,4.8351 +Small,4x4,ldr-rgb-03.png,46.0570,0.0080,0.0031,21.2015 +Small,4x4,ldr-rgb-04.png,41.9409,0.0111,0.0059,11.0313 +Small,4x4,ldr-rgb-05.png,37.3207,0.0186,0.0134,4.8977 +Small,4x4,ldr-rgb-06.png,35.3350,0.0176,0.0123,5.3246 +Small,4x4,ldr-rgb-07.png,38.1282,0.0191,0.0140,4.6888 +Small,4x4,ldr-rgb-08.png,43.8182,0.0098,0.0049,13.4237 +Small,4x4,ldr-rgb-09.png,41.8937,0.0114,0.0061,10.6774 +Small,4x4,ldr-rgb-10.png,44.4076,0.0045,0.0015,10.8588 +Small,4x4,ldr-rgba-00.png,35.5904,0.0189,0.0135,4.8718 +Small,4x4,ldr-rgba-01.png,38.8444,0.0133,0.0080,8.2415 +Small,4x4,ldr-rgba-02.png,34.8609,0.0168,0.0112,5.8264 +Small,4x4,ldr-xy-00.png,37.5753,0.0128,0.0055,11.9393 +Small,4x4,ldr-xy-01.png,44.1942,0.0140,0.0067,9.7219 +Small,4x4,ldr-xy-02.png,48.2321,0.0118,0.0044,14.9382 +Small,4x4,ldrs-rgba-00.png,35.5961,0.0188,0.0134,4.8744 +Small,4x4,ldrs-rgba-01.png,38.8644,0.0134,0.0079,8.2486 +Small,4x4,ldrs-rgba-02.png,34.8622,0.0169,0.0113,5.8033 +Small,5x5,hdr-rgb-00.hdr,29.4941,0.1056,0.0163,4.0327 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5470 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5754 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5714 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5884 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5926 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5764 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5776 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5566 +Small,5x5,ldr-rgb-00.png,34.4207,0.0163,0.0103,6.3820 +Small,5x5,ldr-rgb-01.png,36.2361,0.0126,0.0068,9.6533 +Small,5x5,ldr-rgb-02.png,31.0781,0.0169,0.0110,5.9833 +Small,5x5,ldr-rgb-03.png,42.7340,0.0080,0.0026,25.3531 +Small,5x5,ldr-rgb-04.png,37.2632,0.0118,0.0060,10.9592 +Small,5x5,ldr-rgb-05.png,33.2658,0.0199,0.0139,4.7134 +Small,5x5,ldr-rgb-06.png,31.1162,0.0166,0.0107,6.1479 +Small,5x5,ldr-rgb-07.png,35.0545,0.0172,0.0114,5.7649 +Small,5x5,ldr-rgb-08.png,40.1761,0.0098,0.0042,15.6367 +Small,5x5,ldr-rgb-09.png,37.2884,0.0117,0.0058,11.2044 +Small,5x5,ldr-rgb-10.png,40.1912,0.0050,0.0013,12.1603 +Small,5x5,ldr-rgba-00.png,32.1049,0.0204,0.0143,4.5855 +Small,5x5,ldr-rgba-01.png,35.1901,0.0139,0.0078,8.4171 +Small,5x5,ldr-rgba-02.png,31.1173,0.0173,0.0111,5.9260 +Small,5x5,ldr-xy-00.png,36.7217,0.0128,0.0044,14.8039 +Small,5x5,ldr-xy-01.png,39.7502,0.0140,0.0058,11.3798 +Small,5x5,ldr-xy-02.png,43.9350,0.0125,0.0041,15.8112 +Small,5x5,ldrs-rgba-00.png,32.1059,0.0204,0.0144,4.5606 +Small,5x5,ldrs-rgba-01.png,35.1983,0.0139,0.0079,8.3413 +Small,5x5,ldrs-rgba-02.png,31.1181,0.0174,0.0111,5.8819 +Small,6x6,hdr-rgb-00.hdr,27.0493,0.1054,0.0166,3.9599 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5302 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0034,0.0005,0.5518 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0005,0.5566 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0033,0.0005,0.5470 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0005,0.5388 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0005,0.5578 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5832 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5804 +Small,6x6,ldr-rgb-00.png,31.7043,0.0187,0.0127,5.1753 +Small,6x6,ldr-rgb-01.png,32.9205,0.0142,0.0085,7.6984 +Small,6x6,ldr-rgb-02.png,27.4737,0.0181,0.0123,5.3277 +Small,6x6,ldr-rgb-03.png,40.5514,0.0081,0.0026,24.8354 +Small,6x6,ldr-rgb-04.png,33.9239,0.0129,0.0071,9.2290 +Small,6x6,ldr-rgb-05.png,29.9695,0.0226,0.0168,3.8952 +Small,6x6,ldr-rgb-06.png,27.5383,0.0182,0.0123,5.3433 +Small,6x6,ldr-rgb-07.png,32.9325,0.0172,0.0114,5.7423 +Small,6x6,ldr-rgb-08.png,37.7991,0.0098,0.0043,15.3195 +Small,6x6,ldr-rgb-09.png,33.4925,0.0131,0.0073,8.9298 +Small,6x6,ldr-rgb-10.png,36.6382,0.0052,0.0016,10.1720 +Small,6x6,ldr-rgba-00.png,29.6020,0.0229,0.0171,3.8424 +Small,6x6,ldr-rgba-01.png,32.0799,0.0151,0.0091,7.1995 +Small,6x6,ldr-rgba-02.png,27.8399,0.0190,0.0130,5.0603 +Small,6x6,ldr-xy-00.png,35.8063,0.0131,0.0048,13.5461 +Small,6x6,ldr-xy-01.png,37.1041,0.0151,0.0071,9.2839 +Small,6x6,ldr-xy-02.png,41.9418,0.0119,0.0038,17.0987 +Small,6x6,ldrs-rgba-00.png,29.5967,0.0231,0.0172,3.8207 +Small,6x6,ldrs-rgba-01.png,32.0856,0.0152,0.0091,7.1702 +Small,6x6,ldrs-rgba-02.png,27.8376,0.0191,0.0130,5.0258 +Small,8x8,hdr-rgb-00.hdr,23.7764,0.1095,0.0209,3.1306 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0037,0.0005,0.5518 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0037,0.0005,0.5279 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0005,0.5589 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5589 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5779 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5845 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0004,0.5779 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0004,0.5764 +Small,8x8,ldr-rgb-00.png,28.0488,0.0204,0.0142,4.6201 +Small,8x8,ldr-rgb-01.png,28.7761,0.0173,0.0112,5.8646 +Small,8x8,ldr-rgb-02.png,23.1000,0.0230,0.0170,3.8505 +Small,8x8,ldr-rgb-03.png,37.3080,0.0088,0.0030,21.9481 +Small,8x8,ldr-rgb-04.png,29.3451,0.0165,0.0106,6.1879 +Small,8x8,ldr-rgb-05.png,25.8017,0.0263,0.0203,3.2252 +Small,8x8,ldr-rgb-06.png,23.1661,0.0238,0.0177,3.7051 +Small,8x8,ldr-rgb-07.png,29.8439,0.0175,0.0116,5.6574 +Small,8x8,ldr-rgb-08.png,34.4683,0.0105,0.0048,13.7418 +Small,8x8,ldr-rgb-09.png,28.6358,0.0155,0.0096,6.8041 +Small,8x8,ldr-rgb-10.png,31.9939,0.0058,0.0020,8.2776 +Small,8x8,ldr-rgba-00.png,25.6784,0.0256,0.0195,3.3639 +Small,8x8,ldr-rgba-01.png,28.2720,0.0193,0.0131,5.0047 +Small,8x8,ldr-rgba-02.png,23.9333,0.0254,0.0190,3.4480 +Small,8x8,ldr-xy-00.png,33.3023,0.0153,0.0064,10.1954 +Small,8x8,ldr-xy-01.png,34.4386,0.0166,0.0080,8.2269 +Small,8x8,ldr-xy-02.png,39.9000,0.0111,0.0024,27.4329 +Small,8x8,ldrs-rgba-00.png,25.6786,0.0256,0.0195,3.3669 +Small,8x8,ldrs-rgba-01.png,28.2748,0.0194,0.0132,4.9585 +Small,8x8,ldrs-rgba-02.png,23.9335,0.0253,0.0190,3.4531 +Small,12x12,hdr-rgb-00.hdr,20.5354,0.1217,0.0302,2.1727 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0053,0.0004,0.6111 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0054,0.0004,0.6125 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0054,0.0005,0.5589 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0054,0.0004,0.5714 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0054,0.0004,0.5845 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0054,0.0004,0.5791 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0004,0.5791 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0054,0.0004,0.5779 +Small,12x12,ldr-rgb-00.png,23.7994,0.0203,0.0123,5.3412 +Small,12x12,ldr-rgb-01.png,24.7706,0.0168,0.0088,7.4329 +Small,12x12,ldr-rgb-02.png,19.2291,0.0276,0.0196,3.3397 +Small,12x12,ldr-rgb-03.png,33.2407,0.0096,0.0020,32.0932 +Small,12x12,ldr-rgb-04.png,24.5750,0.0168,0.0085,7.6893 +Small,12x12,ldr-rgb-05.png,21.4889,0.0251,0.0171,3.8276 +Small,12x12,ldr-rgb-06.png,19.2240,0.0286,0.0204,3.2088 +Small,12x12,ldr-rgb-07.png,25.3851,0.0163,0.0083,7.8561 +Small,12x12,ldr-rgb-08.png,30.2920,0.0115,0.0036,18.1031 +Small,12x12,ldr-rgb-09.png,23.7357,0.0188,0.0109,6.0147 +Small,12x12,ldr-rgb-10.png,27.3235,0.0085,0.0027,5.9543 +Small,12x12,ldr-rgba-00.png,21.6066,0.0276,0.0194,3.3769 +Small,12x12,ldr-rgba-01.png,24.5233,0.0187,0.0106,6.2007 +Small,12x12,ldr-rgba-02.png,20.1709,0.0314,0.0232,2.8240 +Small,12x12,ldr-xy-00.png,29.2241,0.0179,0.0065,10.0236 +Small,12x12,ldr-xy-01.png,30.5471,0.0172,0.0059,11.2026 +Small,12x12,ldr-xy-02.png,37.9951,0.0125,0.0012,54.8878 +Small,12x12,ldrs-rgba-00.png,21.6105,0.0277,0.0195,3.3532 +Small,12x12,ldrs-rgba-01.png,24.5251,0.0188,0.0106,6.1542 +Small,12x12,ldrs-rgba-02.png,20.1707,0.0317,0.0233,2.8106 +Small,3x3x3,ldr-l-00-3.dds,50.8346,0.0199,0.0117,22.3555 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0090,0.0048,14.3826 +Small,6x6x6,ldr-l-00-3.dds,32.5376,0.0678,0.0559,4.6895 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0294,0.0213,3.2292 diff --git a/Test/Images/Small/astc_reference-4.3-sse2_fastest_results.csv b/Test/Images/Small/astc_reference-4.3-sse2_fastest_results.csv new file mode 100644 index 0000000..49aa04d --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse2_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3308,0.0962,0.0092,7.1382 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0022,0.0004,0.5982 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0022,0.0004,0.6080 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.5939 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0022,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0022,0.0004,0.5727 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0022,0.0004,0.5829 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5845 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0022,0.0004,0.5900 +Small,4x4,ldr-rgb-00.png,37.2237,0.0105,0.0058,11.3030 +Small,4x4,ldr-rgb-01.png,39.5245,0.0099,0.0052,12.5018 +Small,4x4,ldr-rgb-02.png,34.7577,0.0121,0.0074,8.8252 +Small,4x4,ldr-rgb-03.png,45.4692,0.0067,0.0023,28.1637 +Small,4x4,ldr-rgb-04.png,41.6640,0.0086,0.0040,16.2419 +Small,4x4,ldr-rgb-05.png,36.8562,0.0126,0.0079,8.2737 +Small,4x4,ldr-rgb-06.png,34.9322,0.0117,0.0069,9.4799 +Small,4x4,ldr-rgb-07.png,37.3406,0.0120,0.0074,8.8934 +Small,4x4,ldr-rgb-08.png,42.9161,0.0076,0.0032,20.4553 +Small,4x4,ldr-rgb-09.png,41.7016,0.0086,0.0040,16.3268 +Small,4x4,ldr-rgb-10.png,43.9130,0.0035,0.0011,14.9556 +Small,4x4,ldr-rgba-00.png,34.7268,0.0124,0.0076,8.6781 +Small,4x4,ldr-rgba-01.png,38.6479,0.0104,0.0055,11.9155 +Small,4x4,ldr-rgba-02.png,34.5493,0.0126,0.0078,8.4463 +Small,4x4,ldr-xy-00.png,37.5056,0.0106,0.0040,16.5201 +Small,4x4,ldr-xy-01.png,43.8548,0.0113,0.0046,14.3524 +Small,4x4,ldr-xy-02.png,48.2399,0.0100,0.0033,19.8654 +Small,4x4,ldrs-rgba-00.png,34.7310,0.0124,0.0076,8.6015 +Small,4x4,ldrs-rgba-01.png,38.6664,0.0104,0.0056,11.6365 +Small,4x4,ldrs-rgba-02.png,34.5527,0.0129,0.0079,8.2467 +Small,5x5,hdr-rgb-00.hdr,28.8495,0.0972,0.0099,6.6392 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5779 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5874 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5887 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5817 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5791 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5820 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.6309 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5871 +Small,5x5,ldr-rgb-00.png,33.7101,0.0112,0.0060,10.9066 +Small,5x5,ldr-rgb-01.png,36.0660,0.0099,0.0050,13.1678 +Small,5x5,ldr-rgb-02.png,30.9741,0.0130,0.0079,8.3413 +Small,5x5,ldr-rgb-03.png,42.3108,0.0067,0.0021,31.8146 +Small,5x5,ldr-rgb-04.png,37.0268,0.0095,0.0045,14.4036 +Small,5x5,ldr-rgb-05.png,32.9511,0.0139,0.0088,7.4396 +Small,5x5,ldr-rgb-06.png,31.0218,0.0128,0.0077,8.5123 +Small,5x5,ldr-rgb-07.png,34.4024,0.0123,0.0074,8.8874 +Small,5x5,ldr-rgb-08.png,39.5680,0.0077,0.0029,22.6778 +Small,5x5,ldr-rgb-09.png,37.0647,0.0092,0.0043,15.0725 +Small,5x5,ldr-rgb-10.png,39.8999,0.0039,0.0011,14.6724 +Small,5x5,ldr-rgba-00.png,31.0999,0.0133,0.0080,8.1513 +Small,5x5,ldr-rgba-01.png,35.0302,0.0109,0.0057,11.5383 +Small,5x5,ldr-rgba-02.png,31.0219,0.0137,0.0084,7.7973 +Small,5x5,ldr-xy-00.png,36.6320,0.0110,0.0035,18.7145 +Small,5x5,ldr-xy-01.png,39.1493,0.0115,0.0042,15.5959 +Small,5x5,ldr-xy-02.png,43.8491,0.0107,0.0033,19.5922 +Small,5x5,ldrs-rgba-00.png,31.1012,0.0134,0.0081,8.0442 +Small,5x5,ldrs-rgba-01.png,35.0367,0.0110,0.0058,11.3012 +Small,5x5,ldrs-rgba-02.png,31.0226,0.0137,0.0084,7.7759 +Small,6x6,hdr-rgb-00.hdr,26.7317,0.0983,0.0096,6.8288 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5887 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.6257 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5942 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.6199 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5900 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5926 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.6039 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5887 +Small,6x6,ldr-rgb-00.png,31.3212,0.0121,0.0070,9.3423 +Small,6x6,ldr-rgb-01.png,32.8336,0.0109,0.0059,11.0945 +Small,6x6,ldr-rgb-02.png,27.3837,0.0138,0.0089,7.4019 +Small,6x6,ldr-rgb-03.png,40.3163,0.0068,0.0021,31.1018 +Small,6x6,ldr-rgb-04.png,33.7482,0.0102,0.0052,12.5739 +Small,6x6,ldr-rgb-05.png,29.7352,0.0150,0.0101,6.5159 +Small,6x6,ldr-rgb-06.png,27.4658,0.0138,0.0087,7.4931 +Small,6x6,ldr-rgb-07.png,32.3326,0.0122,0.0073,9.0346 +Small,6x6,ldr-rgb-08.png,37.4336,0.0077,0.0029,22.5125 +Small,6x6,ldr-rgb-09.png,33.3061,0.0102,0.0052,12.6270 +Small,6x6,ldr-rgb-10.png,36.5144,0.0041,0.0013,12.7301 +Small,6x6,ldr-rgba-00.png,28.8377,0.0140,0.0087,7.5354 +Small,6x6,ldr-rgba-01.png,31.9912,0.0118,0.0066,9.9102 +Small,6x6,ldr-rgba-02.png,27.7796,0.0141,0.0089,7.3993 +Small,6x6,ldr-xy-00.png,35.6056,0.0110,0.0038,17.4625 +Small,6x6,ldr-xy-01.png,36.4953,0.0120,0.0047,13.8032 +Small,6x6,ldr-xy-02.png,41.7981,0.0102,0.0030,21.6798 +Small,6x6,ldrs-rgba-00.png,28.8345,0.0141,0.0088,7.4338 +Small,6x6,ldrs-rgba-01.png,31.9977,0.0117,0.0065,10.0255 +Small,6x6,ldrs-rgba-02.png,27.7778,0.0141,0.0089,7.3926 +Small,8x8,hdr-rgb-00.hdr,23.6038,0.1040,0.0143,4.5714 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5884 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5845 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5739 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5779 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5909 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5779 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5939 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5616 +Small,8x8,ldr-rgb-00.png,27.7031,0.0159,0.0099,6.6392 +Small,8x8,ldr-rgb-01.png,28.6850,0.0142,0.0083,7.8721 +Small,8x8,ldr-rgb-02.png,23.0240,0.0183,0.0124,5.2822 +Small,8x8,ldr-rgb-03.png,37.0258,0.0080,0.0024,27.5153 +Small,8x8,ldr-rgb-04.png,29.1260,0.0137,0.0079,8.2842 +Small,8x8,ldr-rgb-05.png,25.6018,0.0203,0.0144,4.5647 +Small,8x8,ldr-rgb-06.png,23.0810,0.0188,0.0129,5.0886 +Small,8x8,ldr-rgb-07.png,29.4659,0.0140,0.0082,7.9739 +Small,8x8,ldr-rgb-08.png,33.9551,0.0092,0.0035,18.4767 +Small,8x8,ldr-rgb-09.png,28.4493,0.0131,0.0073,8.9409 +Small,8x8,ldr-rgb-10.png,31.9058,0.0052,0.0016,10.2561 +Small,8x8,ldr-rgba-00.png,25.3128,0.0190,0.0130,5.0564 +Small,8x8,ldr-rgba-01.png,28.1781,0.0154,0.0094,6.9741 +Small,8x8,ldr-rgba-02.png,23.8711,0.0190,0.0129,5.0997 +Small,8x8,ldr-xy-00.png,33.2750,0.0136,0.0050,13.1546 +Small,8x8,ldr-xy-01.png,34.1754,0.0144,0.0060,10.9846 +Small,8x8,ldr-xy-02.png,39.7771,0.0106,0.0021,30.7229 +Small,8x8,ldrs-rgba-00.png,25.3134,0.0191,0.0130,5.0227 +Small,8x8,ldrs-rgba-01.png,28.1794,0.0156,0.0095,6.9021 +Small,8x8,ldrs-rgba-02.png,23.8706,0.0191,0.0128,5.1009 +Small,12x12,hdr-rgb-00.hdr,20.4510,0.1112,0.0208,3.1456 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0048,0.0004,0.5939 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0048,0.0004,0.5982 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0048,0.0004,0.5832 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0048,0.0004,0.5900 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0048,0.0004,0.5913 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5909 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5871 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0004,0.5858 +Small,12x12,ldr-rgb-00.png,23.7098,0.0163,0.0087,7.5105 +Small,12x12,ldr-rgb-01.png,24.7256,0.0137,0.0064,10.3206 +Small,12x12,ldr-rgb-02.png,19.1930,0.0212,0.0138,4.7489 +Small,12x12,ldr-rgb-03.png,33.1431,0.0088,0.0017,38.1245 +Small,12x12,ldr-rgb-04.png,24.3870,0.0137,0.0062,10.5536 +Small,12x12,ldr-rgb-05.png,21.3834,0.0200,0.0125,5.2425 +Small,12x12,ldr-rgb-06.png,19.1690,0.0218,0.0145,4.5247 +Small,12x12,ldr-rgb-07.png,25.3142,0.0134,0.0061,10.7576 +Small,12x12,ldr-rgb-08.png,30.1204,0.0100,0.0028,23.1652 +Small,12x12,ldr-rgb-09.png,23.5983,0.0155,0.0081,8.0472 +Small,12x12,ldr-rgb-10.png,27.2834,0.0072,0.0020,8.0347 +Small,12x12,ldr-rgba-00.png,21.3613,0.0210,0.0134,4.9047 +Small,12x12,ldr-rgba-01.png,24.4808,0.0153,0.0077,8.5477 +Small,12x12,ldr-rgba-02.png,20.1381,0.0241,0.0164,3.9998 +Small,12x12,ldr-xy-00.png,28.8908,0.0158,0.0050,13.1893 +Small,12x12,ldr-xy-01.png,29.6770,0.0152,0.0045,14.5608 +Small,12x12,ldr-xy-02.png,37.9716,0.0119,0.0011,60.6794 +Small,12x12,ldrs-rgba-00.png,21.3627,0.0211,0.0134,4.8748 +Small,12x12,ldrs-rgba-01.png,24.4817,0.0153,0.0077,8.5057 +Small,12x12,ldrs-rgba-02.png,20.1379,0.0241,0.0164,3.9964 +Small,3x3x3,ldr-l-00-3.dds,50.6979,0.0188,0.0114,22.9189 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0082,0.0048,14.3940 +Small,6x6x6,ldr-l-00-3.dds,32.5210,0.0676,0.0558,4.6978 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0294,0.0213,3.2303 diff --git a/Test/Images/Small/astc_reference-4.3-sse2_medium_results.csv b/Test/Images/Small/astc_reference-4.3-sse2_medium_results.csv new file mode 100644 index 0000000..f42d33f --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse2_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1238,0.1129,0.0234,2.8015 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5377 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5518 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5401 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5845 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5727 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0005,0.5310 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5929 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0005,0.5020 +Small,4x4,ldr-rgb-00.png,38.8091,0.0325,0.0264,2.4827 +Small,4x4,ldr-rgb-01.png,40.2008,0.0279,0.0220,2.9812 +Small,4x4,ldr-rgb-02.png,35.2658,0.0285,0.0225,2.9074 +Small,4x4,ldr-rgb-03.png,47.2399,0.0189,0.0133,4.9398 +Small,4x4,ldr-rgb-04.png,42.1842,0.0232,0.0173,3.7865 +Small,4x4,ldr-rgb-05.png,37.7989,0.0309,0.0250,2.6188 +Small,4x4,ldr-rgb-06.png,35.4538,0.0255,0.0196,3.3456 +Small,4x4,ldr-rgb-07.png,39.2651,0.0383,0.0324,2.0209 +Small,4x4,ldr-rgb-08.png,45.1580,0.0221,0.0164,3.9983 +Small,4x4,ldr-rgb-09.png,42.1202,0.0238,0.0179,3.6639 +Small,4x4,ldr-rgb-10.png,44.8973,0.0064,0.0028,5.7543 +Small,4x4,ldr-rgba-00.png,36.2355,0.0359,0.0295,2.2209 +Small,4x4,ldr-rgba-01.png,38.9520,0.0225,0.0164,3.9932 +Small,4x4,ldr-rgba-02.png,34.9310,0.0246,0.0185,3.5436 +Small,4x4,ldr-xy-00.png,37.7517,0.0225,0.0151,4.3338 +Small,4x4,ldr-xy-01.png,45.1812,0.0308,0.0233,2.8071 +Small,4x4,ldr-xy-02.png,50.9688,0.0364,0.0289,2.2703 +Small,4x4,ldrs-rgba-00.png,36.2429,0.0356,0.0295,2.2222 +Small,4x4,ldrs-rgba-01.png,38.9706,0.0228,0.0166,3.9475 +Small,4x4,ldrs-rgba-02.png,34.9330,0.0247,0.0186,3.5293 +Small,5x5,hdr-rgb-00.hdr,29.8792,0.1168,0.0275,2.3873 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0045,0.0005,0.5575 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0005,0.5269 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0005,0.5390 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0005,0.5401 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5779 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0005,0.5628 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0004,0.5714 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0004,0.5887 +Small,5x5,ldr-rgb-00.png,35.1353,0.0366,0.0291,2.2544 +Small,5x5,ldr-rgb-01.png,36.4365,0.0277,0.0206,3.1743 +Small,5x5,ldr-rgb-02.png,31.1195,0.0280,0.0208,3.1513 +Small,5x5,ldr-rgb-03.png,43.9924,0.0153,0.0086,7.6374 +Small,5x5,ldr-rgb-04.png,37.6527,0.0257,0.0187,3.5138 +Small,5x5,ldr-rgb-05.png,33.5357,0.0373,0.0302,2.1712 +Small,5x5,ldr-rgb-06.png,31.1617,0.0268,0.0197,3.3254 +Small,5x5,ldr-rgb-07.png,36.1275,0.0422,0.0353,1.8560 +Small,5x5,ldr-rgb-08.png,41.6131,0.0213,0.0146,4.4875 +Small,5x5,ldr-rgb-09.png,37.5769,0.0246,0.0176,3.7272 +Small,5x5,ldr-rgb-10.png,40.5644,0.0084,0.0033,4.8831 +Small,5x5,ldr-rgba-00.png,32.7897,0.0430,0.0358,1.8322 +Small,5x5,ldr-rgba-01.png,35.3090,0.0261,0.0187,3.4954 +Small,5x5,ldr-rgba-02.png,31.1309,0.0283,0.0210,3.1138 +Small,5x5,ldr-xy-00.png,37.0786,0.0239,0.0154,4.2490 +Small,5x5,ldr-xy-01.png,40.5669,0.0310,0.0225,2.9188 +Small,5x5,ldr-xy-02.png,49.0821,0.0253,0.0165,3.9611 +Small,5x5,ldrs-rgba-00.png,32.7935,0.0429,0.0356,1.8389 +Small,5x5,ldrs-rgba-01.png,35.3182,0.0260,0.0188,3.4826 +Small,5x5,ldrs-rgba-02.png,31.1320,0.0286,0.0214,3.0587 +Small,6x6,hdr-rgb-00.hdr,27.4934,0.1194,0.0290,2.2571 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0043,0.0005,0.5182 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0005,0.5334 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0043,0.0005,0.5543 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0043,0.0005,0.5495 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0043,0.0005,0.5566 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0043,0.0005,0.5379 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0005,0.5412 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0005,0.5448 +Small,6x6,ldr-rgb-00.png,32.3857,0.0373,0.0305,2.1498 +Small,6x6,ldr-rgb-01.png,33.0813,0.0276,0.0209,3.1414 +Small,6x6,ldr-rgb-02.png,27.5038,0.0286,0.0218,3.0109 +Small,6x6,ldr-rgb-03.png,41.7098,0.0130,0.0066,9.9539 +Small,6x6,ldr-rgb-04.png,34.1976,0.0246,0.0179,3.6565 +Small,6x6,ldr-rgb-05.png,30.1358,0.0388,0.0319,2.0513 +Small,6x6,ldr-rgb-06.png,27.5712,0.0282,0.0214,3.0653 +Small,6x6,ldr-rgb-07.png,33.8773,0.0416,0.0349,1.8802 +Small,6x6,ldr-rgb-08.png,39.1910,0.0177,0.0112,5.8472 +Small,6x6,ldr-rgb-09.png,33.6644,0.0242,0.0174,3.7582 +Small,6x6,ldr-rgb-10.png,36.9239,0.0079,0.0033,4.8936 +Small,6x6,ldr-rgba-00.png,30.2372,0.0468,0.0397,1.6502 +Small,6x6,ldr-rgba-01.png,32.1918,0.0270,0.0202,3.2513 +Small,6x6,ldr-rgba-02.png,27.8514,0.0306,0.0236,2.7824 +Small,6x6,ldr-xy-00.png,36.2476,0.0217,0.0132,4.9532 +Small,6x6,ldr-xy-01.png,37.9375,0.0249,0.0166,3.9368 +Small,6x6,ldr-xy-02.png,46.0669,0.0205,0.0122,5.3741 +Small,6x6,ldrs-rgba-00.png,30.2354,0.0468,0.0398,1.6485 +Small,6x6,ldrs-rgba-01.png,32.1978,0.0272,0.0203,3.2291 +Small,6x6,ldrs-rgba-02.png,27.8496,0.0306,0.0236,2.7821 +Small,8x8,hdr-rgb-00.hdr,24.1284,0.1287,0.0378,1.7356 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0049,0.0005,0.5235 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0049,0.0005,0.5484 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0049,0.0005,0.5687 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5817 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0048,0.0005,0.5504 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0050,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0050,0.0005,0.5675 +Small,8x8,ldr-rgb-00.png,28.7284,0.0488,0.0411,1.5935 +Small,8x8,ldr-rgb-01.png,28.9370,0.0340,0.0265,2.4699 +Small,8x8,ldr-rgb-02.png,23.1614,0.0364,0.0288,2.2741 +Small,8x8,ldr-rgb-03.png,38.5560,0.0152,0.0081,8.1402 +Small,8x8,ldr-rgb-04.png,29.6453,0.0342,0.0269,2.4349 +Small,8x8,ldr-rgb-05.png,25.9412,0.0473,0.0399,1.6418 +Small,8x8,ldr-rgb-06.png,23.2047,0.0374,0.0296,2.2135 +Small,8x8,ldr-rgb-07.png,30.7489,0.0500,0.0426,1.5380 +Small,8x8,ldr-rgb-08.png,35.9057,0.0215,0.0143,4.5775 +Small,8x8,ldr-rgb-09.png,28.9902,0.0310,0.0236,2.7714 +Small,8x8,ldr-rgb-10.png,32.1710,0.0096,0.0046,3.5711 +Small,8x8,ldr-rgba-00.png,26.4438,0.0580,0.0503,1.3023 +Small,8x8,ldr-rgba-01.png,28.3668,0.0343,0.0267,2.4535 +Small,8x8,ldr-rgba-02.png,23.9414,0.0391,0.0314,2.0871 +Small,8x8,ldr-xy-00.png,33.9206,0.0293,0.0189,3.4748 +Small,8x8,ldr-xy-01.png,34.9386,0.0294,0.0191,3.4267 +Small,8x8,ldr-xy-02.png,41.6877,0.0228,0.0126,5.1992 +Small,8x8,ldrs-rgba-00.png,26.4457,0.0573,0.0496,1.3216 +Small,8x8,ldrs-rgba-01.png,28.3703,0.0345,0.0269,2.4378 +Small,8x8,ldrs-rgba-02.png,23.9416,0.0394,0.0316,2.0744 +Small,12x12,hdr-rgb-00.hdr,20.7755,0.1478,0.0535,1.2257 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0077,0.0004,0.5742 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0077,0.0004,0.5751 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0079,0.0005,0.5663 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0078,0.0005,0.5552 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0078,0.0005,0.5334 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0079,0.0005,0.5543 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0079,0.0004,0.5739 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0079,0.0005,0.5235 +Small,12x12,ldr-rgb-00.png,24.6915,0.0593,0.0488,1.3426 +Small,12x12,ldr-rgb-01.png,25.0393,0.0437,0.0333,1.9658 +Small,12x12,ldr-rgb-02.png,19.2743,0.0515,0.0410,1.5983 +Small,12x12,ldr-rgb-03.png,34.9505,0.0187,0.0085,7.7411 +Small,12x12,ldr-rgb-04.png,24.9006,0.0426,0.0323,2.0293 +Small,12x12,ldr-rgb-05.png,21.6514,0.0598,0.0494,1.3264 +Small,12x12,ldr-rgb-06.png,19.2513,0.0523,0.0419,1.5646 +Small,12x12,ldr-rgb-07.png,26.7396,0.0544,0.0441,1.4863 +Small,12x12,ldr-rgb-08.png,31.6566,0.0247,0.0147,4.4646 +Small,12x12,ldr-rgb-09.png,24.1576,0.0408,0.0305,2.1522 +Small,12x12,ldr-rgb-10.png,28.0433,0.0174,0.0092,1.7745 +Small,12x12,ldr-rgba-00.png,22.2473,0.0650,0.0545,1.2021 +Small,12x12,ldr-rgba-01.png,24.6500,0.0423,0.0318,2.0627 +Small,12x12,ldr-rgba-02.png,20.1848,0.0555,0.0448,1.4613 +Small,12x12,ldr-xy-00.png,30.2110,0.0356,0.0213,3.0787 +Small,12x12,ldr-xy-01.png,31.8412,0.0370,0.0228,2.8693 +Small,12x12,ldr-xy-02.png,38.5222,0.0189,0.0047,13.8143 +Small,12x12,ldrs-rgba-00.png,22.2476,0.0656,0.0549,1.1939 +Small,12x12,ldrs-rgba-01.png,24.6522,0.0431,0.0323,2.0290 +Small,12x12,ldrs-rgba-02.png,20.1848,0.0561,0.0454,1.4443 +Small,3x3x3,ldr-l-00-3.dds,51.8769,0.0255,0.0165,15.8472 +Small,3x3x3,ldr-l-01-3.dds,54.6166,0.0103,0.0052,13.3825 +Small,6x6x6,ldr-l-00-3.dds,32.9597,0.0807,0.0667,3.9329 +Small,6x6x6,ldr-l-01-3.dds,41.0140,0.0315,0.0213,3.2399 diff --git a/Test/Images/Small/astc_reference-4.3-sse2_thorough_results.csv b/Test/Images/Small/astc_reference-4.3-sse2_thorough_results.csv new file mode 100644 index 0000000..1dc360c --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse2_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.3988,0.1364,0.0466,1.4072 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.4673 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5334 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5613 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0005,0.5302 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0005,0.5412 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0005,0.5613 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0005,0.5663 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5754 +Small,4x4,ldr-rgb-00.png,39.1396,0.0600,0.0539,1.2164 +Small,4x4,ldr-rgb-01.png,40.3879,0.0574,0.0515,1.2715 +Small,4x4,ldr-rgb-02.png,35.4469,0.0538,0.0478,1.3716 +Small,4x4,ldr-rgb-03.png,47.7050,0.0534,0.0478,1.3718 +Small,4x4,ldr-rgb-04.png,42.3343,0.0485,0.0426,1.5378 +Small,4x4,ldr-rgb-05.png,37.9716,0.0587,0.0526,1.2452 +Small,4x4,ldr-rgb-06.png,35.6101,0.0477,0.0416,1.5738 +Small,4x4,ldr-rgb-07.png,39.8550,0.0720,0.0659,0.9951 +Small,4x4,ldr-rgb-08.png,45.8141,0.0535,0.0478,1.3715 +Small,4x4,ldr-rgb-09.png,42.2663,0.0521,0.0462,1.4193 +Small,4x4,ldr-rgb-10.png,45.1134,0.0097,0.0059,2.7343 +Small,4x4,ldr-rgba-00.png,36.7024,0.0626,0.0565,1.1593 +Small,4x4,ldr-rgba-01.png,39.0829,0.0450,0.0389,1.6867 +Small,4x4,ldr-rgba-02.png,35.0183,0.0454,0.0391,1.6782 +Small,4x4,ldr-xy-00.png,37.7753,0.0580,0.0504,1.2996 +Small,4x4,ldr-xy-01.png,45.2569,0.0643,0.0571,1.1487 +Small,4x4,ldr-xy-02.png,50.9912,0.0801,0.0725,0.9034 +Small,4x4,ldrs-rgba-00.png,36.7104,0.0632,0.0571,1.1478 +Small,4x4,ldrs-rgba-01.png,39.1044,0.0454,0.0392,1.6699 +Small,4x4,ldrs-rgba-02.png,35.0233,0.0456,0.0394,1.6636 +Small,5x5,hdr-rgb-00.hdr,30.2809,0.1451,0.0531,1.2349 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0045,0.0004,0.5702 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0004,0.5714 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0046,0.0005,0.5445 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0005,0.5651 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5764 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0005,0.5601 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0005,0.5345 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5529 +Small,5x5,ldr-rgb-00.png,35.3622,0.0721,0.0647,1.0130 +Small,5x5,ldr-rgb-01.png,36.5321,0.0631,0.0561,1.1692 +Small,5x5,ldr-rgb-02.png,31.1870,0.0541,0.0471,1.3917 +Small,5x5,ldr-rgb-03.png,44.5348,0.0615,0.0547,1.1974 +Small,5x5,ldr-rgb-04.png,37.8081,0.0563,0.0493,1.3285 +Small,5x5,ldr-rgb-05.png,33.6835,0.0716,0.0646,1.0146 +Small,5x5,ldr-rgb-06.png,31.2225,0.0515,0.0444,1.4767 +Small,5x5,ldr-rgb-07.png,36.7108,0.0875,0.0806,0.8127 +Small,5x5,ldr-rgb-08.png,42.3675,0.0609,0.0542,1.2083 +Small,5x5,ldr-rgb-09.png,37.6987,0.0619,0.0549,1.1931 +Small,5x5,ldr-rgb-10.png,40.7256,0.0123,0.0074,2.2105 +Small,5x5,ldr-rgba-00.png,33.0991,0.0786,0.0713,0.9193 +Small,5x5,ldr-rgba-01.png,35.4017,0.0541,0.0468,1.4012 +Small,5x5,ldr-rgba-02.png,31.1706,0.0517,0.0443,1.4793 +Small,5x5,ldr-xy-00.png,37.2351,0.0675,0.0588,1.1136 +Small,5x5,ldr-xy-01.png,41.4156,0.0800,0.0714,0.9173 +Small,5x5,ldr-xy-02.png,49.2617,0.0910,0.0824,0.7949 +Small,5x5,ldrs-rgba-00.png,33.1063,0.0785,0.0713,0.9188 +Small,5x5,ldrs-rgba-01.png,35.4095,0.0534,0.0462,1.4191 +Small,5x5,ldrs-rgba-02.png,31.1713,0.0517,0.0444,1.4757 +Small,6x6,hdr-rgb-00.hdr,27.6987,0.1474,0.0572,1.1459 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0045,0.0005,0.5473 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0048,0.0005,0.5098 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0005,0.5437 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0044,0.0005,0.5601 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0044,0.0005,0.5651 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5687 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0004,0.5727 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0005,0.5663 +Small,6x6,ldr-rgb-00.png,32.6236,0.0791,0.0721,0.9086 +Small,6x6,ldr-rgb-01.png,33.1855,0.0675,0.0608,1.0776 +Small,6x6,ldr-rgb-02.png,27.5522,0.0584,0.0515,1.2721 +Small,6x6,ldr-rgb-03.png,42.5760,0.0532,0.0466,1.4077 +Small,6x6,ldr-rgb-04.png,34.3279,0.0599,0.0529,1.2387 +Small,6x6,ldr-rgb-05.png,30.2792,0.0753,0.0684,0.9575 +Small,6x6,ldr-rgb-06.png,27.6242,0.0557,0.0489,1.3399 +Small,6x6,ldr-rgb-07.png,34.4221,0.0934,0.0865,0.7575 +Small,6x6,ldr-rgb-08.png,40.0080,0.0545,0.0478,1.3714 +Small,6x6,ldr-rgb-09.png,33.8156,0.0635,0.0566,1.1575 +Small,6x6,ldr-rgb-10.png,37.1747,0.0135,0.0088,1.8401 +Small,6x6,ldr-rgba-00.png,30.4928,0.0872,0.0802,0.8176 +Small,6x6,ldr-rgba-01.png,32.2722,0.0607,0.0537,1.2198 +Small,6x6,ldr-rgba-02.png,27.8884,0.0568,0.0497,1.3190 +Small,6x6,ldr-xy-00.png,36.3580,0.0557,0.0473,1.3858 +Small,6x6,ldr-xy-01.png,38.1144,0.0779,0.0693,0.9455 +Small,6x6,ldr-xy-02.png,47.4637,0.0957,0.0870,0.7533 +Small,6x6,ldrs-rgba-00.png,30.4894,0.0863,0.0791,0.8286 +Small,6x6,ldrs-rgba-01.png,32.2774,0.0609,0.0538,1.2174 +Small,6x6,ldrs-rgba-02.png,27.8865,0.0566,0.0496,1.3207 +Small,8x8,hdr-rgb-00.hdr,24.3310,0.1707,0.0768,0.8530 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0063,0.0005,0.5379 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0065,0.0005,0.5120 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0063,0.0005,0.5678 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0063,0.0004,0.5727 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0062,0.0004,0.5955 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0063,0.0005,0.5300 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0063,0.0005,0.5628 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0063,0.0005,0.5663 +Small,8x8,ldr-rgb-00.png,28.9743,0.1013,0.0924,0.7095 +Small,8x8,ldr-rgb-01.png,29.0250,0.0841,0.0754,0.8688 +Small,8x8,ldr-rgb-02.png,23.2010,0.0776,0.0686,0.9551 +Small,8x8,ldr-rgb-03.png,39.4059,0.0389,0.0305,2.1521 +Small,8x8,ldr-rgb-04.png,29.7753,0.0764,0.0676,0.9699 +Small,8x8,ldr-rgb-05.png,26.0443,0.0929,0.0841,0.7793 +Small,8x8,ldr-rgb-06.png,23.2548,0.0756,0.0666,0.9836 +Small,8x8,ldr-rgb-07.png,31.1954,0.1139,0.1052,0.6229 +Small,8x8,ldr-rgb-08.png,36.5527,0.0571,0.0485,1.3499 +Small,8x8,ldr-rgb-09.png,29.1512,0.0658,0.0571,1.1486 +Small,8x8,ldr-rgb-10.png,32.3269,0.0178,0.0113,1.4327 +Small,8x8,ldr-rgba-00.png,26.7456,0.1115,0.1023,0.6405 +Small,8x8,ldr-rgba-01.png,28.4290,0.0814,0.0722,0.9075 +Small,8x8,ldr-rgba-02.png,23.9672,0.0744,0.0652,1.0059 +Small,8x8,ldr-xy-00.png,34.1954,0.0671,0.0566,1.1585 +Small,8x8,ldr-xy-01.png,35.2284,0.0691,0.0587,1.1161 +Small,8x8,ldr-xy-02.png,44.4736,0.0880,0.0777,0.8438 +Small,8x8,ldrs-rgba-00.png,26.7460,0.1115,0.1025,0.6394 +Small,8x8,ldrs-rgba-01.png,28.4323,0.0814,0.0722,0.9076 +Small,8x8,ldrs-rgba-02.png,23.9676,0.0746,0.0654,1.0024 +Small,12x12,hdr-rgb-00.hdr,21.0278,0.2101,0.1129,0.5804 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0102,0.0005,0.5589 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0102,0.0004,0.5754 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0102,0.0004,0.5829 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0102,0.0004,0.5982 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0103,0.0004,0.5817 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0102,0.0005,0.5601 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0104,0.0004,0.5754 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0102,0.0004,0.5791 +Small,12x12,ldr-rgb-00.png,25.0567,0.1320,0.1189,0.5511 +Small,12x12,ldr-rgb-01.png,25.1428,0.1077,0.0946,0.6931 +Small,12x12,ldr-rgb-02.png,19.2937,0.1181,0.1052,0.6228 +Small,12x12,ldr-rgb-03.png,36.1599,0.0432,0.0306,2.1446 +Small,12x12,ldr-rgb-04.png,24.9934,0.0975,0.0847,0.7737 +Small,12x12,ldr-rgb-05.png,21.7356,0.1195,0.1066,0.6145 +Small,12x12,ldr-rgb-06.png,19.2955,0.1159,0.1030,0.6366 +Small,12x12,ldr-rgb-07.png,27.0999,0.1367,0.1237,0.5297 +Small,12x12,ldr-rgb-08.png,32.4850,0.0554,0.0428,1.5298 +Small,12x12,ldr-rgb-09.png,24.3014,0.0906,0.0778,0.8424 +Small,12x12,ldr-rgb-10.png,28.1869,0.0302,0.0195,0.8325 +Small,12x12,ldr-rgba-00.png,22.7181,0.1396,0.1266,0.5178 +Small,12x12,ldr-rgba-01.png,24.7277,0.1109,0.0976,0.6715 +Small,12x12,ldr-rgba-02.png,20.2040,0.1144,0.1013,0.6467 +Small,12x12,ldr-xy-00.png,30.5815,0.0856,0.0711,0.9215 +Small,12x12,ldr-xy-01.png,32.1781,0.0686,0.0542,1.2099 +Small,12x12,ldr-xy-02.png,40.2787,0.0491,0.0347,1.8873 +Small,12x12,ldrs-rgba-00.png,22.7169,0.1401,0.1269,0.5163 +Small,12x12,ldrs-rgba-01.png,24.7295,0.1099,0.0967,0.6774 +Small,12x12,ldrs-rgba-02.png,20.2043,0.1148,0.1013,0.6470 +Small,3x3x3,ldr-l-00-3.dds,52.3138,0.0439,0.0349,7.5137 +Small,3x3x3,ldr-l-01-3.dds,55.2511,0.0189,0.0136,5.0662 +Small,6x6x6,ldr-l-00-3.dds,33.2738,0.1112,0.0944,2.7760 +Small,6x6x6,ldr-l-01-3.dds,41.7409,0.0351,0.0221,3.1159 diff --git a/Test/Images/Small/astc_reference-4.3-sse4.1_fast_results.csv b/Test/Images/Small/astc_reference-4.3-sse4.1_fast_results.csv new file mode 100644 index 0000000..6c857a5 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse4.1_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7131,0.0971,0.0130,5.0393 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0028,0.0004,0.5955 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0028,0.0004,0.5858 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0005,0.5578 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0027,0.0004,0.5884 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0027,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0027,0.0004,0.5955 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0027,0.0004,0.5965 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0027,0.0004,0.5858 +Small,4x4,ldr-rgb-00.png,38.2268,0.0139,0.0087,7.5303 +Small,4x4,ldr-rgb-01.png,39.9056,0.0122,0.0073,9.0109 +Small,4x4,ldr-rgb-02.png,35.1296,0.0166,0.0115,5.6874 +Small,4x4,ldr-rgb-03.png,46.0570,0.0075,0.0027,24.2354 +Small,4x4,ldr-rgb-04.png,41.9409,0.0100,0.0051,12.9160 +Small,4x4,ldr-rgb-05.png,37.3207,0.0165,0.0114,5.7538 +Small,4x4,ldr-rgb-06.png,35.3350,0.0157,0.0105,6.2427 +Small,4x4,ldr-rgb-07.png,38.1282,0.0170,0.0119,5.5174 +Small,4x4,ldr-rgb-08.png,43.8182,0.0090,0.0042,15.5439 +Small,4x4,ldr-rgb-09.png,41.8937,0.0102,0.0053,12.4644 +Small,4x4,ldr-rgb-10.png,44.4076,0.0043,0.0014,11.9976 +Small,4x4,ldr-rgba-00.png,35.5904,0.0166,0.0115,5.7182 +Small,4x4,ldr-rgba-01.png,38.8444,0.0120,0.0068,9.6730 +Small,4x4,ldr-rgba-02.png,34.8609,0.0149,0.0096,6.7990 +Small,4x4,ldr-xy-00.png,37.5753,0.0118,0.0047,14.0094 +Small,4x4,ldr-xy-01.png,44.1942,0.0129,0.0058,11.3736 +Small,4x4,ldr-xy-02.png,48.2321,0.0109,0.0037,17.7949 +Small,4x4,ldrs-rgba-00.png,35.5961,0.0167,0.0115,5.6859 +Small,4x4,ldrs-rgba-01.png,38.8644,0.0121,0.0068,9.6306 +Small,4x4,ldrs-rgba-02.png,34.8622,0.0151,0.0098,6.7127 +Small,5x5,hdr-rgb-00.hdr,29.4941,0.0984,0.0135,4.8495 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.5345 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0034,0.0005,0.5663 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5702 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5714 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5896 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5779 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5995 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5874 +Small,5x5,ldr-rgb-00.png,34.4207,0.0145,0.0087,7.5416 +Small,5x5,ldr-rgb-01.png,36.2361,0.0114,0.0058,11.3760 +Small,5x5,ldr-rgb-02.png,31.0781,0.0148,0.0091,7.2255 +Small,5x5,ldr-rgb-03.png,42.7340,0.0076,0.0023,28.1637 +Small,5x5,ldr-rgb-04.png,37.2632,0.0106,0.0049,13.4428 +Small,5x5,ldr-rgb-05.png,33.2658,0.0173,0.0115,5.6757 +Small,5x5,ldr-rgb-06.png,31.1162,0.0145,0.0088,7.4313 +Small,5x5,ldr-rgb-07.png,35.0545,0.0151,0.0095,6.9284 +Small,5x5,ldr-rgb-08.png,40.1761,0.0091,0.0036,17.9953 +Small,5x5,ldr-rgb-09.png,37.2884,0.0106,0.0050,13.2001 +Small,5x5,ldr-rgb-10.png,40.1912,0.0049,0.0012,13.5256 +Small,5x5,ldr-rgba-00.png,32.1049,0.0180,0.0120,5.4650 +Small,5x5,ldr-rgba-01.png,35.1901,0.0124,0.0066,9.9059 +Small,5x5,ldr-rgba-02.png,31.1173,0.0154,0.0093,7.0334 +Small,5x5,ldr-xy-00.png,36.7217,0.0121,0.0039,16.9291 +Small,5x5,ldr-xy-01.png,39.7502,0.0130,0.0049,13.4790 +Small,5x5,ldr-xy-02.png,43.9350,0.0116,0.0036,18.1533 +Small,5x5,ldrs-rgba-00.png,32.1059,0.0181,0.0122,5.3926 +Small,5x5,ldrs-rgba-01.png,35.1983,0.0125,0.0065,10.0423 +Small,5x5,ldrs-rgba-02.png,31.1181,0.0154,0.0094,6.9593 +Small,6x6,hdr-rgb-00.hdr,27.0493,0.0986,0.0139,4.7087 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0034,0.0005,0.5412 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0033,0.0004,0.5767 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0033,0.0005,0.5639 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0033,0.0004,0.5952 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5779 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0033,0.0004,0.5702 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0033,0.0004,0.5858 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0033,0.0004,0.5779 +Small,6x6,ldr-rgb-00.png,31.7043,0.0162,0.0104,6.2732 +Small,6x6,ldr-rgb-01.png,32.9205,0.0126,0.0070,9.3585 +Small,6x6,ldr-rgb-02.png,27.4737,0.0159,0.0103,6.3857 +Small,6x6,ldr-rgb-03.png,40.5514,0.0077,0.0023,28.1753 +Small,6x6,ldr-rgb-04.png,33.9239,0.0115,0.0059,11.0273 +Small,6x6,ldr-rgb-05.png,29.9695,0.0195,0.0138,4.7549 +Small,6x6,ldr-rgb-06.png,27.5383,0.0159,0.0102,6.4076 +Small,6x6,ldr-rgb-07.png,32.9325,0.0152,0.0096,6.8617 +Small,6x6,ldr-rgb-08.png,37.7991,0.0090,0.0036,18.0000 +Small,6x6,ldr-rgb-09.png,33.4925,0.0115,0.0061,10.8037 +Small,6x6,ldr-rgb-10.png,36.6382,0.0051,0.0016,10.3010 +Small,6x6,ldr-rgba-00.png,29.6020,0.0201,0.0143,4.5727 +Small,6x6,ldr-rgba-01.png,32.0799,0.0134,0.0076,8.5835 +Small,6x6,ldr-rgba-02.png,27.8399,0.0167,0.0108,6.0614 +Small,6x6,ldr-xy-00.png,35.8063,0.0122,0.0041,16.0550 +Small,6x6,ldr-xy-01.png,37.1041,0.0138,0.0059,11.0309 +Small,6x6,ldr-xy-02.png,41.9418,0.0112,0.0034,19.5517 +Small,6x6,ldrs-rgba-00.png,29.5967,0.0202,0.0145,4.5069 +Small,6x6,ldrs-rgba-01.png,32.0856,0.0135,0.0076,8.6142 +Small,6x6,ldrs-rgba-02.png,27.8376,0.0167,0.0108,6.0418 +Small,8x8,hdr-rgb-00.hdr,23.7764,0.1024,0.0177,3.7076 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5589 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5995 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5913 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5926 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5858 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5804 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5779 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,8x8,ldr-rgb-00.png,28.0488,0.0181,0.0119,5.4879 +Small,8x8,ldr-rgb-01.png,28.7761,0.0154,0.0095,6.8799 +Small,8x8,ldr-rgb-02.png,23.1000,0.0200,0.0142,4.6182 +Small,8x8,ldr-rgb-03.png,37.3080,0.0081,0.0026,25.0048 +Small,8x8,ldr-rgb-04.png,29.3451,0.0147,0.0089,7.3743 +Small,8x8,ldr-rgb-05.png,25.8017,0.0228,0.0169,3.8735 +Small,8x8,ldr-rgb-06.png,23.1661,0.0206,0.0147,4.4558 +Small,8x8,ldr-rgb-07.png,29.8439,0.0155,0.0097,6.7654 +Small,8x8,ldr-rgb-08.png,34.4683,0.0098,0.0041,15.8422 +Small,8x8,ldr-rgb-09.png,28.6358,0.0138,0.0080,8.1736 +Small,8x8,ldr-rgb-10.png,31.9939,0.0054,0.0017,9.6933 +Small,8x8,ldr-rgba-00.png,25.6784,0.0223,0.0163,4.0303 +Small,8x8,ldr-rgba-01.png,28.2720,0.0170,0.0110,5.9606 +Small,8x8,ldr-rgba-02.png,23.9333,0.0219,0.0157,4.1642 +Small,8x8,ldr-xy-00.png,33.3023,0.0139,0.0055,12.0029 +Small,8x8,ldr-xy-01.png,34.4386,0.0151,0.0067,9.7814 +Small,8x8,ldr-xy-02.png,39.9000,0.0105,0.0022,29.5854 +Small,8x8,ldrs-rgba-00.png,25.6786,0.0224,0.0164,3.9988 +Small,8x8,ldrs-rgba-01.png,28.2748,0.0170,0.0110,5.9503 +Small,8x8,ldrs-rgba-02.png,23.9335,0.0220,0.0158,4.1392 +Small,12x12,hdr-rgb-00.hdr,20.5354,0.1130,0.0265,2.4712 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0054,0.0005,0.5651 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0054,0.0005,0.5675 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0054,0.0004,0.5714 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0054,0.0005,0.5613 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0054,0.0004,0.5955 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0054,0.0004,0.5832 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0004,0.5795 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0054,0.0004,0.5767 +Small,12x12,ldr-rgb-00.png,23.7994,0.0185,0.0106,6.1553 +Small,12x12,ldr-rgb-01.png,24.7706,0.0156,0.0078,8.3550 +Small,12x12,ldr-rgb-02.png,19.2291,0.0250,0.0173,3.7893 +Small,12x12,ldr-rgb-03.png,33.2407,0.0093,0.0018,35.8521 +Small,12x12,ldr-rgb-04.png,24.5750,0.0152,0.0074,8.8779 +Small,12x12,ldr-rgb-05.png,21.4889,0.0229,0.0152,4.3036 +Small,12x12,ldr-rgb-06.png,19.2240,0.0259,0.0181,3.6304 +Small,12x12,ldr-rgb-07.png,25.3851,0.0150,0.0074,8.8610 +Small,12x12,ldr-rgb-08.png,30.2920,0.0108,0.0033,19.7470 +Small,12x12,ldr-rgb-09.png,23.7357,0.0172,0.0097,6.7843 +Small,12x12,ldr-rgb-10.png,27.3235,0.0080,0.0025,6.5839 +Small,12x12,ldr-rgba-00.png,21.6066,0.0248,0.0169,3.8834 +Small,12x12,ldr-rgba-01.png,24.5233,0.0172,0.0093,7.0559 +Small,12x12,ldr-rgba-02.png,20.1709,0.0284,0.0203,3.2220 +Small,12x12,ldr-xy-00.png,29.2241,0.0169,0.0058,11.2914 +Small,12x12,ldr-xy-01.png,30.5471,0.0163,0.0052,12.6882 +Small,12x12,ldr-xy-02.png,37.9951,0.0121,0.0011,58.2615 +Small,12x12,ldrs-rgba-00.png,21.6105,0.0252,0.0171,3.8283 +Small,12x12,ldrs-rgba-01.png,24.5251,0.0174,0.0094,6.9816 +Small,12x12,ldrs-rgba-02.png,20.1707,0.0285,0.0203,3.2223 +Small,3x3x3,ldr-l-00-3.dds,50.8346,0.0167,0.0088,29.8059 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0080,0.0038,18.2129 +Small,6x6x6,ldr-l-00-3.dds,32.5376,0.0616,0.0502,5.2213 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0269,0.0191,3.6143 diff --git a/Test/Images/Small/astc_reference-4.3-sse4.1_fastest_results.csv b/Test/Images/Small/astc_reference-4.3-sse4.1_fastest_results.csv new file mode 100644 index 0000000..f1c79ed --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse4.1_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3308,0.0914,0.0080,8.2124 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0023,0.0004,0.5690 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0023,0.0004,0.5779 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.6022 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0022,0.0004,0.5995 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0022,0.0004,0.5939 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0022,0.0004,0.5926 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5939 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0022,0.0004,0.5926 +Small,4x4,ldr-rgb-00.png,37.2237,0.0096,0.0049,13.3832 +Small,4x4,ldr-rgb-01.png,39.5245,0.0089,0.0045,14.5407 +Small,4x4,ldr-rgb-02.png,34.7577,0.0109,0.0064,10.2083 +Small,4x4,ldr-rgb-03.png,45.4692,0.0061,0.0020,32.4761 +Small,4x4,ldr-rgb-04.png,41.6640,0.0078,0.0034,19.3781 +Small,4x4,ldr-rgb-05.png,36.8562,0.0111,0.0066,9.8565 +Small,4x4,ldr-rgb-06.png,34.9322,0.0104,0.0059,11.0874 +Small,4x4,ldr-rgb-07.png,37.3406,0.0108,0.0063,10.3599 +Small,4x4,ldr-rgb-08.png,42.9161,0.0070,0.0028,23.6515 +Small,4x4,ldr-rgb-09.png,41.7016,0.0078,0.0034,19.3263 +Small,4x4,ldr-rgb-10.png,43.9130,0.0035,0.0011,15.3946 +Small,4x4,ldr-rgba-00.png,34.7268,0.0111,0.0064,10.2398 +Small,4x4,ldr-rgba-01.png,38.6479,0.0095,0.0048,13.5796 +Small,4x4,ldr-rgba-02.png,34.5493,0.0115,0.0068,9.6533 +Small,4x4,ldr-xy-00.png,37.5056,0.0100,0.0035,18.7464 +Small,4x4,ldr-xy-01.png,43.8548,0.0105,0.0040,16.1902 +Small,4x4,ldr-xy-02.png,48.2399,0.0095,0.0028,23.0351 +Small,4x4,ldrs-rgba-00.png,34.7310,0.0113,0.0066,9.9705 +Small,4x4,ldrs-rgba-01.png,38.6664,0.0096,0.0049,13.4625 +Small,4x4,ldrs-rgba-02.png,34.5527,0.0117,0.0068,9.6222 +Small,5x5,hdr-rgb-00.hdr,28.8495,0.0922,0.0084,7.8402 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5913 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5939 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.6084 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5965 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5896 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5871 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5900 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5896 +Small,5x5,ldr-rgb-00.png,33.7101,0.0099,0.0050,12.9904 +Small,5x5,ldr-rgb-01.png,36.0660,0.0090,0.0042,15.7010 +Small,5x5,ldr-rgb-02.png,30.9741,0.0113,0.0065,10.1308 +Small,5x5,ldr-rgb-03.png,42.3108,0.0064,0.0018,35.8334 +Small,5x5,ldr-rgb-04.png,37.0268,0.0087,0.0038,17.3195 +Small,5x5,ldr-rgb-05.png,32.9511,0.0122,0.0073,9.0219 +Small,5x5,ldr-rgb-06.png,31.0218,0.0114,0.0065,10.1308 +Small,5x5,ldr-rgb-07.png,34.4024,0.0109,0.0061,10.7986 +Small,5x5,ldr-rgb-08.png,39.5680,0.0072,0.0026,25.2158 +Small,5x5,ldr-rgb-09.png,37.0647,0.0085,0.0037,17.6975 +Small,5x5,ldr-rgb-10.png,39.8999,0.0039,0.0010,15.8601 +Small,5x5,ldr-rgba-00.png,31.0999,0.0117,0.0067,9.8195 +Small,5x5,ldr-rgba-01.png,35.0302,0.0099,0.0048,13.5735 +Small,5x5,ldr-rgba-02.png,31.0219,0.0121,0.0070,9.3703 +Small,5x5,ldr-xy-00.png,36.6320,0.0103,0.0030,21.8088 +Small,5x5,ldr-xy-01.png,39.1493,0.0107,0.0035,18.8157 +Small,5x5,ldr-xy-02.png,43.8491,0.0100,0.0028,23.5240 +Small,5x5,ldrs-rgba-00.png,31.1012,0.0120,0.0069,9.4554 +Small,5x5,ldrs-rgba-01.png,35.0367,0.0099,0.0049,13.4048 +Small,5x5,ldrs-rgba-02.png,31.0226,0.0122,0.0071,9.2930 +Small,6x6,hdr-rgb-00.hdr,26.7317,0.0918,0.0080,8.1443 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0026,0.0005,0.5470 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5926 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5871 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5965 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5858 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5955 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5829 +Small,6x6,ldr-rgb-00.png,31.3212,0.0110,0.0059,11.0553 +Small,6x6,ldr-rgb-01.png,32.8336,0.0097,0.0049,13.5042 +Small,6x6,ldr-rgb-02.png,27.3837,0.0122,0.0074,8.8972 +Small,6x6,ldr-rgb-03.png,40.3163,0.0063,0.0018,36.6748 +Small,6x6,ldr-rgb-04.png,33.7482,0.0092,0.0043,15.1181 +Small,6x6,ldr-rgb-05.png,29.7352,0.0131,0.0084,7.8262 +Small,6x6,ldr-rgb-06.png,27.4658,0.0122,0.0073,8.9566 +Small,6x6,ldr-rgb-07.png,32.3326,0.0108,0.0061,10.7757 +Small,6x6,ldr-rgb-08.png,37.4336,0.0071,0.0025,26.3192 +Small,6x6,ldr-rgb-09.png,33.3061,0.0091,0.0043,15.1215 +Small,6x6,ldr-rgb-10.png,36.5144,0.0039,0.0011,14.2463 +Small,6x6,ldr-rgba-00.png,28.8377,0.0123,0.0072,9.0492 +Small,6x6,ldr-rgba-01.png,31.9912,0.0106,0.0056,11.7978 +Small,6x6,ldr-rgba-02.png,27.7796,0.0126,0.0074,8.8240 +Small,6x6,ldr-xy-00.png,35.6056,0.0102,0.0032,20.7080 +Small,6x6,ldr-xy-01.png,36.4953,0.0111,0.0039,16.6795 +Small,6x6,ldr-xy-02.png,41.7981,0.0096,0.0026,25.5700 +Small,6x6,ldrs-rgba-00.png,28.8345,0.0124,0.0074,8.8502 +Small,6x6,ldrs-rgba-01.png,31.9977,0.0106,0.0055,11.9549 +Small,6x6,ldrs-rgba-02.png,27.7778,0.0126,0.0074,8.8051 +Small,8x8,hdr-rgb-00.hdr,23.6038,0.0967,0.0119,5.4892 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.6009 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0033,0.0004,0.6111 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5858 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5952 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5727 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5896 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5699 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0005,0.5678 +Small,8x8,ldr-rgb-00.png,27.7031,0.0140,0.0082,8.0198 +Small,8x8,ldr-rgb-01.png,28.6850,0.0126,0.0070,9.3825 +Small,8x8,ldr-rgb-02.png,23.0240,0.0160,0.0104,6.3216 +Small,8x8,ldr-rgb-03.png,37.0258,0.0075,0.0021,30.7986 +Small,8x8,ldr-rgb-04.png,29.1260,0.0123,0.0066,9.9234 +Small,8x8,ldr-rgb-05.png,25.6018,0.0176,0.0120,5.4773 +Small,8x8,ldr-rgb-06.png,23.0810,0.0164,0.0107,6.1495 +Small,8x8,ldr-rgb-07.png,29.4659,0.0125,0.0069,9.5325 +Small,8x8,ldr-rgb-08.png,33.9551,0.0084,0.0030,21.5709 +Small,8x8,ldr-rgb-09.png,28.4493,0.0119,0.0062,10.4939 +Small,8x8,ldr-rgb-10.png,31.9058,0.0049,0.0014,11.9619 +Small,8x8,ldr-rgba-00.png,25.3128,0.0168,0.0109,6.0229 +Small,8x8,ldr-rgba-01.png,28.1781,0.0137,0.0078,8.3666 +Small,8x8,ldr-rgba-02.png,23.8711,0.0166,0.0107,6.1260 +Small,8x8,ldr-xy-00.png,33.2750,0.0127,0.0042,15.5333 +Small,8x8,ldr-xy-01.png,34.1754,0.0133,0.0050,12.9929 +Small,8x8,ldr-xy-02.png,39.7771,0.0102,0.0020,33.4890 +Small,8x8,ldrs-rgba-00.png,25.3134,0.0169,0.0109,6.0052 +Small,8x8,ldrs-rgba-01.png,28.1794,0.0137,0.0079,8.3433 +Small,8x8,ldrs-rgba-02.png,23.8706,0.0167,0.0108,6.0963 +Small,12x12,hdr-rgb-00.hdr,20.4510,0.1047,0.0184,3.5540 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0048,0.0004,0.5887 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0048,0.0004,0.5939 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0048,0.0004,0.5884 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0048,0.0004,0.5896 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0048,0.0004,0.5909 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0048,0.0004,0.6246 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0048,0.0004,0.5742 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0048,0.0004,0.5887 +Small,12x12,ldr-rgb-00.png,23.7098,0.0151,0.0077,8.5300 +Small,12x12,ldr-rgb-01.png,24.7256,0.0128,0.0057,11.5909 +Small,12x12,ldr-rgb-02.png,19.1930,0.0193,0.0121,5.4067 +Small,12x12,ldr-rgb-03.png,33.1431,0.0085,0.0016,41.4285 +Small,12x12,ldr-rgb-04.png,24.3870,0.0127,0.0055,11.8640 +Small,12x12,ldr-rgb-05.png,21.3834,0.0181,0.0109,6.0087 +Small,12x12,ldr-rgb-06.png,19.1690,0.0199,0.0126,5.1881 +Small,12x12,ldr-rgb-07.png,25.3142,0.0125,0.0053,12.3607 +Small,12x12,ldr-rgb-08.png,30.1204,0.0095,0.0026,25.5297 +Small,12x12,ldr-rgb-09.png,23.5983,0.0145,0.0072,9.1034 +Small,12x12,ldr-rgb-10.png,27.2834,0.0069,0.0018,9.1324 +Small,12x12,ldr-rgba-00.png,21.3613,0.0190,0.0116,5.6657 +Small,12x12,ldr-rgba-01.png,24.4808,0.0143,0.0068,9.6503 +Small,12x12,ldr-rgba-02.png,20.1381,0.0217,0.0142,4.6217 +Small,12x12,ldr-xy-00.png,28.8908,0.0151,0.0044,14.8334 +Small,12x12,ldr-xy-01.png,29.6770,0.0144,0.0040,16.4460 +Small,12x12,ldr-xy-02.png,37.9716,0.0114,0.0010,63.3213 +Small,12x12,ldrs-rgba-00.png,21.3627,0.0192,0.0118,5.5492 +Small,12x12,ldrs-rgba-01.png,24.4817,0.0141,0.0069,9.5576 +Small,12x12,ldrs-rgba-02.png,20.1379,0.0218,0.0144,4.5416 +Small,3x3x3,ldr-l-00-3.dds,50.6979,0.0157,0.0086,30.3825 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0071,0.0037,18.4583 +Small,6x6x6,ldr-l-00-3.dds,32.5210,0.0613,0.0498,5.2645 +Small,6x6x6,ldr-l-01-3.dds,40.9072,0.0269,0.0190,3.6206 diff --git a/Test/Images/Small/astc_reference-4.3-sse4.1_medium_results.csv b/Test/Images/Small/astc_reference-4.3-sse4.1_medium_results.csv new file mode 100644 index 0000000..efb7635 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse4.1_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1238,0.1047,0.0202,3.2389 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0037,0.0005,0.5008 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5751 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5555 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0005,0.5578 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0005,0.5666 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0005,0.5601 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5884 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5939 +Small,4x4,ldr-rgb-00.png,38.8091,0.0280,0.0221,2.9612 +Small,4x4,ldr-rgb-01.png,40.2008,0.0247,0.0188,3.4950 +Small,4x4,ldr-rgb-02.png,35.2658,0.0248,0.0191,3.4370 +Small,4x4,ldr-rgb-03.png,47.2399,0.0168,0.0112,5.8498 +Small,4x4,ldr-rgb-04.png,42.1842,0.0204,0.0146,4.4823 +Small,4x4,ldr-rgb-05.png,37.7989,0.0269,0.0212,3.0881 +Small,4x4,ldr-rgb-06.png,35.4538,0.0227,0.0168,3.8908 +Small,4x4,ldr-rgb-07.png,39.2651,0.0332,0.0275,2.3838 +Small,4x4,ldr-rgb-08.png,45.1580,0.0194,0.0138,4.7566 +Small,4x4,ldr-rgb-09.png,42.1202,0.0210,0.0151,4.3327 +Small,4x4,ldr-rgb-10.png,44.8973,0.0061,0.0025,6.5788 +Small,4x4,ldr-rgba-00.png,36.2355,0.0308,0.0249,2.6363 +Small,4x4,ldr-rgba-01.png,38.9520,0.0201,0.0141,4.6332 +Small,4x4,ldr-rgba-02.png,34.9310,0.0219,0.0159,4.1207 +Small,4x4,ldr-xy-00.png,37.7517,0.0202,0.0129,5.0623 +Small,4x4,ldr-xy-01.png,45.1812,0.0272,0.0200,3.2784 +Small,4x4,ldr-xy-02.png,50.9688,0.0320,0.0247,2.6539 +Small,4x4,ldrs-rgba-00.png,36.2429,0.0308,0.0249,2.6335 +Small,4x4,ldrs-rgba-01.png,38.9706,0.0203,0.0144,4.5657 +Small,4x4,ldrs-rgba-02.png,34.9330,0.0220,0.0159,4.1135 +Small,5x5,hdr-rgb-00.hdr,29.8792,0.1075,0.0228,2.8742 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0044,0.0004,0.5871 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0045,0.0004,0.5804 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0004,0.5871 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0004,0.5900 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5639 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0047,0.0005,0.5334 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0005,0.5495 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0046,0.0005,0.5651 +Small,5x5,ldr-rgb-00.png,35.1353,0.0319,0.0243,2.6939 +Small,5x5,ldr-rgb-01.png,36.4365,0.0235,0.0167,3.9288 +Small,5x5,ldr-rgb-02.png,31.1195,0.0237,0.0169,3.8809 +Small,5x5,ldr-rgb-03.png,43.9924,0.0134,0.0070,9.3540 +Small,5x5,ldr-rgb-04.png,37.6527,0.0219,0.0151,4.3304 +Small,5x5,ldr-rgb-05.png,33.5357,0.0318,0.0249,2.6362 +Small,5x5,ldr-rgb-06.png,31.1617,0.0231,0.0160,4.0862 +Small,5x5,ldr-rgb-07.png,36.1275,0.0356,0.0289,2.2710 +Small,5x5,ldr-rgb-08.png,41.6131,0.0185,0.0119,5.4984 +Small,5x5,ldr-rgb-09.png,37.5769,0.0211,0.0143,4.5848 +Small,5x5,ldr-rgb-10.png,40.5644,0.0073,0.0026,6.1598 +Small,5x5,ldr-rgba-00.png,32.7897,0.0359,0.0290,2.2631 +Small,5x5,ldr-rgba-01.png,35.3090,0.0225,0.0155,4.2186 +Small,5x5,ldr-rgba-02.png,31.1309,0.0245,0.0174,3.7619 +Small,5x5,ldr-xy-00.png,37.0786,0.0209,0.0125,5.2434 +Small,5x5,ldr-xy-01.png,40.5669,0.0268,0.0184,3.5699 +Small,5x5,ldr-xy-02.png,49.0821,0.0220,0.0136,4.8238 +Small,5x5,ldrs-rgba-00.png,32.7935,0.0364,0.0294,2.2318 +Small,5x5,ldrs-rgba-01.png,35.3182,0.0225,0.0155,4.2197 +Small,5x5,ldrs-rgba-02.png,31.1320,0.0245,0.0175,3.7552 +Small,6x6,hdr-rgb-00.hdr,27.4934,0.1098,0.0241,2.7137 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0043,0.0005,0.5470 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0005,0.5616 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0042,0.0004,0.5779 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0042,0.0004,0.5832 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0042,0.0004,0.5702 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0043,0.0004,0.5742 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0004,0.5926 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0042,0.0004,0.5779 +Small,6x6,ldr-rgb-00.png,32.3857,0.0321,0.0253,2.5868 +Small,6x6,ldr-rgb-01.png,33.0813,0.0246,0.0179,3.6684 +Small,6x6,ldr-rgb-02.png,27.5038,0.0253,0.0183,3.5881 +Small,6x6,ldr-rgb-03.png,41.7098,0.0117,0.0055,11.9222 +Small,6x6,ldr-rgb-04.png,34.1976,0.0212,0.0146,4.4805 +Small,6x6,ldr-rgb-05.png,30.1358,0.0327,0.0261,2.5114 +Small,6x6,ldr-rgb-06.png,27.5712,0.0243,0.0177,3.7116 +Small,6x6,ldr-rgb-07.png,33.8773,0.0348,0.0283,2.3144 +Small,6x6,ldr-rgb-08.png,39.1910,0.0158,0.0093,7.0666 +Small,6x6,ldr-rgb-09.png,33.6644,0.0205,0.0140,4.6795 +Small,6x6,ldr-rgb-10.png,36.9239,0.0073,0.0028,5.7626 +Small,6x6,ldr-rgba-00.png,30.2372,0.0394,0.0326,2.0083 +Small,6x6,ldr-rgba-01.png,32.1918,0.0233,0.0166,3.9411 +Small,6x6,ldr-rgba-02.png,27.8514,0.0263,0.0195,3.3648 +Small,6x6,ldr-xy-00.png,36.2476,0.0192,0.0109,5.9922 +Small,6x6,ldr-xy-01.png,37.9375,0.0218,0.0136,4.8057 +Small,6x6,ldr-xy-02.png,46.0669,0.0183,0.0100,6.5760 +Small,6x6,ldrs-rgba-00.png,30.2354,0.0392,0.0325,2.0174 +Small,6x6,ldrs-rgba-01.png,32.1978,0.0234,0.0165,3.9632 +Small,6x6,ldrs-rgba-02.png,27.8496,0.0263,0.0195,3.3596 +Small,8x8,hdr-rgb-00.hdr,24.1284,0.1182,0.0319,2.0570 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0050,0.0006,0.4612 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0049,0.0005,0.5258 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0049,0.0005,0.5563 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5926 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0004,0.5795 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0048,0.0004,0.5952 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0050,0.0005,0.5555 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0005,0.5555 +Small,8x8,ldr-rgb-00.png,28.7284,0.0420,0.0346,1.8933 +Small,8x8,ldr-rgb-01.png,28.9370,0.0294,0.0220,2.9726 +Small,8x8,ldr-rgb-02.png,23.1614,0.0316,0.0243,2.7021 +Small,8x8,ldr-rgb-03.png,38.5560,0.0137,0.0069,9.5272 +Small,8x8,ldr-rgb-04.png,29.6453,0.0292,0.0220,2.9769 +Small,8x8,ldr-rgb-05.png,25.9412,0.0406,0.0332,1.9714 +Small,8x8,ldr-rgb-06.png,23.2047,0.0320,0.0246,2.6594 +Small,8x8,ldr-rgb-07.png,30.7489,0.0422,0.0349,1.8753 +Small,8x8,ldr-rgb-08.png,35.9057,0.0188,0.0119,5.5039 +Small,8x8,ldr-rgb-09.png,28.9902,0.0266,0.0194,3.3748 +Small,8x8,ldr-rgb-10.png,32.1710,0.0090,0.0039,4.2059 +Small,8x8,ldr-rgba-00.png,26.4438,0.0491,0.0418,1.5694 +Small,8x8,ldr-rgba-01.png,28.3668,0.0297,0.0222,2.9539 +Small,8x8,ldr-rgba-02.png,23.9414,0.0335,0.0261,2.5108 +Small,8x8,ldr-xy-00.png,33.9206,0.0258,0.0156,4.1900 +Small,8x8,ldr-xy-01.png,34.9386,0.0260,0.0159,4.1233 +Small,8x8,ldr-xy-02.png,41.6877,0.0204,0.0104,6.2858 +Small,8x8,ldrs-rgba-00.png,26.4457,0.0493,0.0418,1.5688 +Small,8x8,ldrs-rgba-01.png,28.3703,0.0300,0.0224,2.9295 +Small,8x8,ldrs-rgba-02.png,23.9416,0.0338,0.0263,2.4965 +Small,12x12,hdr-rgb-00.hdr,20.7755,0.1368,0.0473,1.3863 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0077,0.0006,0.4361 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0077,0.0005,0.5613 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0077,0.0004,0.5804 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0079,0.0005,0.5331 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0078,0.0005,0.5675 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0077,0.0004,0.5727 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0078,0.0005,0.5388 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0079,0.0005,0.5484 +Small,12x12,ldr-rgb-00.png,24.6915,0.0529,0.0426,1.5398 +Small,12x12,ldr-rgb-01.png,25.0393,0.0395,0.0293,2.2345 +Small,12x12,ldr-rgb-02.png,19.2743,0.0464,0.0361,1.8129 +Small,12x12,ldr-rgb-03.png,34.9505,0.0175,0.0074,8.8051 +Small,12x12,ldr-rgb-04.png,24.9006,0.0383,0.0280,2.3400 +Small,12x12,ldr-rgb-05.png,21.6514,0.0535,0.0433,1.5127 +Small,12x12,ldr-rgb-06.png,19.2513,0.0472,0.0369,1.7754 +Small,12x12,ldr-rgb-07.png,26.7396,0.0488,0.0387,1.6925 +Small,12x12,ldr-rgb-08.png,31.6566,0.0230,0.0130,5.0474 +Small,12x12,ldr-rgb-09.png,24.1576,0.0367,0.0268,2.4478 +Small,12x12,ldr-rgb-10.png,28.0433,0.0160,0.0081,2.0022 +Small,12x12,ldr-rgba-00.png,22.2473,0.0585,0.0481,1.3637 +Small,12x12,ldr-rgba-01.png,24.6500,0.0388,0.0283,2.3154 +Small,12x12,ldr-rgba-02.png,20.1848,0.0499,0.0394,1.6616 +Small,12x12,ldr-xy-00.png,30.2110,0.0329,0.0188,3.4852 +Small,12x12,ldr-xy-01.png,31.8412,0.0340,0.0202,3.2405 +Small,12x12,ldr-xy-02.png,38.5222,0.0180,0.0042,15.7154 +Small,12x12,ldrs-rgba-00.png,22.2476,0.0587,0.0484,1.3546 +Small,12x12,ldrs-rgba-01.png,24.6522,0.0393,0.0287,2.2832 +Small,12x12,ldrs-rgba-02.png,20.1848,0.0502,0.0395,1.6576 +Small,3x3x3,ldr-l-00-3.dds,51.8769,0.0216,0.0126,20.7408 +Small,3x3x3,ldr-l-01-3.dds,54.6166,0.0090,0.0039,17.4520 +Small,6x6x6,ldr-l-00-3.dds,32.9597,0.0735,0.0597,4.3940 +Small,6x6x6,ldr-l-01-3.dds,41.0140,0.0290,0.0191,3.5999 diff --git a/Test/Images/Small/astc_reference-4.3-sse4.1_thorough_results.csv b/Test/Images/Small/astc_reference-4.3-sse4.1_thorough_results.csv new file mode 100644 index 0000000..04aff3e --- /dev/null +++ b/Test/Images/Small/astc_reference-4.3-sse4.1_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.3988,0.1243,0.0398,1.6456 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5829 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5079 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0037,0.0005,0.5481 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0005,0.5470 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0005,0.5555 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5791 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5437 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0005,0.5172 +Small,4x4,ldr-rgb-00.png,39.1396,0.0516,0.0457,1.4328 +Small,4x4,ldr-rgb-01.png,40.3879,0.0491,0.0433,1.5141 +Small,4x4,ldr-rgb-02.png,35.4469,0.0465,0.0406,1.6143 +Small,4x4,ldr-rgb-03.png,47.7050,0.0457,0.0402,1.6286 +Small,4x4,ldr-rgb-04.png,42.3343,0.0418,0.0360,1.8190 +Small,4x4,ldr-rgb-05.png,37.9716,0.0503,0.0444,1.4748 +Small,4x4,ldr-rgb-06.png,35.6101,0.0415,0.0357,1.8363 +Small,4x4,ldr-rgb-07.png,39.8550,0.0612,0.0553,1.1841 +Small,4x4,ldr-rgb-08.png,45.8141,0.0452,0.0397,1.6505 +Small,4x4,ldr-rgb-09.png,42.2663,0.0449,0.0392,1.6738 +Small,4x4,ldr-rgb-10.png,45.1134,0.0088,0.0051,3.1843 +Small,4x4,ldr-rgba-00.png,36.7024,0.0541,0.0482,1.3601 +Small,4x4,ldr-rgba-01.png,39.0829,0.0394,0.0334,1.9629 +Small,4x4,ldr-rgba-02.png,35.0183,0.0393,0.0333,1.9664 +Small,4x4,ldr-xy-00.png,37.7753,0.0508,0.0435,1.5078 +Small,4x4,ldr-xy-01.png,45.2569,0.0574,0.0502,1.3062 +Small,4x4,ldr-xy-02.png,50.9912,0.0716,0.0639,1.0263 +Small,4x4,ldrs-rgba-00.png,36.7104,0.0543,0.0483,1.3566 +Small,4x4,ldrs-rgba-01.png,39.1044,0.0400,0.0339,1.9307 +Small,4x4,ldrs-rgba-02.png,35.0233,0.0395,0.0335,1.9565 +Small,5x5,hdr-rgb-00.hdr,30.2809,0.1304,0.0444,1.4756 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0046,0.0005,0.5377 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0005,0.5266 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0004,0.5913 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0004,0.5845 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5804 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0004,0.5804 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0005,0.5437 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0004,0.5861 +Small,5x5,ldr-rgb-00.png,35.3622,0.0602,0.0532,1.2325 +Small,5x5,ldr-rgb-01.png,36.5321,0.0531,0.0463,1.4159 +Small,5x5,ldr-rgb-02.png,31.1870,0.0461,0.0392,1.6701 +Small,5x5,ldr-rgb-03.png,44.5348,0.0517,0.0450,1.4558 +Small,5x5,ldr-rgb-04.png,37.8081,0.0475,0.0407,1.6118 +Small,5x5,ldr-rgb-05.png,33.6835,0.0600,0.0531,1.2351 +Small,5x5,ldr-rgb-06.png,31.2225,0.0444,0.0368,1.7801 +Small,5x5,ldr-rgb-07.png,36.7108,0.0719,0.0652,1.0059 +Small,5x5,ldr-rgb-08.png,42.3675,0.0508,0.0441,1.4871 +Small,5x5,ldr-rgb-09.png,37.6987,0.0529,0.0459,1.4286 +Small,5x5,ldr-rgb-10.png,40.7256,0.0108,0.0061,2.6724 +Small,5x5,ldr-rgba-00.png,33.0991,0.0654,0.0581,1.1271 +Small,5x5,ldr-rgba-01.png,35.4017,0.0455,0.0385,1.7019 +Small,5x5,ldr-rgba-02.png,31.1706,0.0443,0.0371,1.7679 +Small,5x5,ldr-xy-00.png,37.2351,0.0569,0.0485,1.3526 +Small,5x5,ldr-xy-01.png,41.4156,0.0685,0.0601,1.0898 +Small,5x5,ldr-xy-02.png,49.2617,0.0777,0.0693,0.9457 +Small,5x5,ldrs-rgba-00.png,33.1063,0.0656,0.0585,1.1209 +Small,5x5,ldrs-rgba-01.png,35.4095,0.0460,0.0388,1.6888 +Small,5x5,ldrs-rgba-02.png,31.1713,0.0441,0.0369,1.7780 +Small,6x6,hdr-rgb-00.hdr,27.6987,0.1336,0.0480,1.3651 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0043,0.0005,0.5566 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0044,0.0005,0.5687 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0043,0.0005,0.5651 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0043,0.0005,0.5678 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0043,0.0005,0.5628 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5663 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0005,0.5604 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0043,0.0004,0.5817 +Small,6x6,ldr-rgb-00.png,32.6236,0.0657,0.0590,1.1107 +Small,6x6,ldr-rgb-01.png,33.1855,0.0563,0.0497,1.3179 +Small,6x6,ldr-rgb-02.png,27.5522,0.0493,0.0426,1.5394 +Small,6x6,ldr-rgb-03.png,42.5760,0.0446,0.0383,1.7131 +Small,6x6,ldr-rgb-04.png,34.3279,0.0495,0.0429,1.5289 +Small,6x6,ldr-rgb-05.png,30.2792,0.0633,0.0567,1.1561 +Small,6x6,ldr-rgb-06.png,27.6242,0.0473,0.0406,1.6122 +Small,6x6,ldr-rgb-07.png,34.4221,0.0774,0.0707,0.9270 +Small,6x6,ldr-rgb-08.png,40.0080,0.0453,0.0389,1.6841 +Small,6x6,ldr-rgb-09.png,33.8156,0.0526,0.0460,1.4249 +Small,6x6,ldr-rgb-10.png,37.1747,0.0120,0.0074,2.1850 +Small,6x6,ldr-rgba-00.png,30.4928,0.0726,0.0658,0.9964 +Small,6x6,ldr-rgba-01.png,32.2722,0.0509,0.0441,1.4875 +Small,6x6,ldr-rgba-02.png,27.8884,0.0482,0.0413,1.5884 +Small,6x6,ldr-xy-00.png,36.3580,0.0474,0.0392,1.6738 +Small,6x6,ldr-xy-01.png,38.1144,0.0656,0.0575,1.1396 +Small,6x6,ldr-xy-02.png,47.4637,0.0804,0.0722,0.9082 +Small,6x6,ldrs-rgba-00.png,30.4894,0.0726,0.0658,0.9965 +Small,6x6,ldrs-rgba-01.png,32.2774,0.0516,0.0448,1.4637 +Small,6x6,ldrs-rgba-02.png,27.8865,0.0483,0.0413,1.5852 +Small,8x8,hdr-rgb-00.hdr,24.3310,0.1553,0.0657,0.9975 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0063,0.0006,0.4444 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0064,0.0005,0.5070 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0064,0.0005,0.5225 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0063,0.0004,0.5702 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0062,0.0005,0.5675 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0062,0.0004,0.5742 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0062,0.0004,0.5871 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0062,0.0005,0.5492 +Small,8x8,ldr-rgb-00.png,28.9743,0.0864,0.0776,0.8450 +Small,8x8,ldr-rgb-01.png,29.0250,0.0713,0.0627,1.0460 +Small,8x8,ldr-rgb-02.png,23.2010,0.0667,0.0580,1.1300 +Small,8x8,ldr-rgb-03.png,39.4059,0.0336,0.0253,2.5886 +Small,8x8,ldr-rgb-04.png,29.7753,0.0650,0.0563,1.1631 +Small,8x8,ldr-rgb-05.png,26.0443,0.0786,0.0700,0.9362 +Small,8x8,ldr-rgb-06.png,23.2548,0.0649,0.0559,1.1720 +Small,8x8,ldr-rgb-07.png,31.1954,0.0962,0.0877,0.7470 +Small,8x8,ldr-rgb-08.png,36.5527,0.0486,0.0401,1.6335 +Small,8x8,ldr-rgb-09.png,29.1512,0.0564,0.0477,1.3726 +Small,8x8,ldr-rgb-10.png,32.3269,0.0160,0.0096,1.7012 +Small,8x8,ldr-rgba-00.png,26.7456,0.0952,0.0864,0.7586 +Small,8x8,ldr-rgba-01.png,28.4290,0.0701,0.0611,1.0734 +Small,8x8,ldr-rgba-02.png,23.9672,0.0637,0.0549,1.1943 +Small,8x8,ldr-xy-00.png,34.1954,0.0570,0.0469,1.3988 +Small,8x8,ldr-xy-01.png,35.2284,0.0595,0.0495,1.3250 +Small,8x8,ldr-xy-02.png,44.4736,0.0755,0.0653,1.0033 +Small,8x8,ldrs-rgba-00.png,26.7460,0.0948,0.0861,0.7615 +Small,8x8,ldrs-rgba-01.png,28.4323,0.0694,0.0605,1.0833 +Small,8x8,ldrs-rgba-02.png,23.9676,0.0641,0.0551,1.1900 +Small,12x12,hdr-rgb-00.hdr,21.0278,0.1918,0.0995,0.6588 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0102,0.0004,0.5829 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0100,0.0004,0.5896 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0102,0.0005,0.5575 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0101,0.0004,0.6009 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0104,0.0004,0.5727 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0103,0.0005,0.5470 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0103,0.0005,0.5390 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0102,0.0005,0.5663 +Small,12x12,ldr-rgb-00.png,25.0567,0.1181,0.1053,0.6224 +Small,12x12,ldr-rgb-01.png,25.1428,0.0963,0.0834,0.7857 +Small,12x12,ldr-rgb-02.png,19.2937,0.1061,0.0935,0.7012 +Small,12x12,ldr-rgb-03.png,36.1599,0.0395,0.0271,2.4169 +Small,12x12,ldr-rgb-04.png,24.9934,0.0874,0.0746,0.8788 +Small,12x12,ldr-rgb-05.png,21.7356,0.1070,0.0942,0.6956 +Small,12x12,ldr-rgb-06.png,19.2955,0.1031,0.0904,0.7252 +Small,12x12,ldr-rgb-07.png,27.0999,0.1209,0.1083,0.6049 +Small,12x12,ldr-rgb-08.png,32.4850,0.0504,0.0380,1.7260 +Small,12x12,ldr-rgb-09.png,24.3014,0.0815,0.0690,0.9500 +Small,12x12,ldr-rgb-10.png,28.1869,0.0280,0.0174,0.9317 +Small,12x12,ldr-rgba-00.png,22.7181,0.1243,0.1113,0.5889 +Small,12x12,ldr-rgba-01.png,24.7277,0.0982,0.0854,0.7674 +Small,12x12,ldr-rgba-02.png,20.2040,0.1018,0.0888,0.7379 +Small,12x12,ldr-xy-00.png,30.5815,0.0771,0.0628,1.0431 +Small,12x12,ldr-xy-01.png,32.1781,0.0619,0.0478,1.3703 +Small,12x12,ldr-xy-02.png,40.2787,0.0448,0.0305,2.1488 +Small,12x12,ldrs-rgba-00.png,22.7169,0.1249,0.1120,0.5849 +Small,12x12,ldrs-rgba-01.png,24.7295,0.0993,0.0863,0.7596 +Small,12x12,ldrs-rgba-02.png,20.2043,0.1024,0.0895,0.7322 +Small,3x3x3,ldr-l-00-3.dds,52.3138,0.0370,0.0282,9.3088 +Small,3x3x3,ldr-l-01-3.dds,55.2511,0.0163,0.0111,6.1857 +Small,6x6x6,ldr-l-00-3.dds,33.2738,0.1017,0.0852,3.0754 +Small,6x6x6,ldr-l-01-3.dds,41.7409,0.0321,0.0197,3.5001 diff --git a/Test/Images/Small/astc_reference-4.4-avx2_fast_results.csv b/Test/Images/Small/astc_reference-4.4-avx2_fast_results.csv new file mode 100644 index 0000000..e5591f8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-avx2_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7281,0.0970,0.0120,5.4837 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0029,0.0005,0.5434 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0029,0.0005,0.5518 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0004,0.5939 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0028,0.0004,0.5982 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0029,0.0005,0.5492 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0028,0.0004,0.5779 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0029,0.0004,0.5858 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0028,0.0004,0.5900 +Small,4x4,ldr-rgb-00.png,38.2512,0.0131,0.0078,8.3550 +Small,4x4,ldr-rgb-01.png,39.9266,0.0115,0.0066,9.9796 +Small,4x4,ldr-rgb-02.png,35.1621,0.0157,0.0106,6.2055 +Small,4x4,ldr-rgb-03.png,46.0782,0.0071,0.0024,27.0709 +Small,4x4,ldr-rgb-04.png,41.9798,0.0095,0.0045,14.6648 +Small,4x4,ldr-rgb-05.png,37.3372,0.0154,0.0104,6.2918 +Small,4x4,ldr-rgb-06.png,35.3603,0.0146,0.0095,6.8892 +Small,4x4,ldr-rgb-07.png,38.1442,0.0157,0.0107,6.1134 +Small,4x4,ldr-rgb-08.png,43.8361,0.0086,0.0038,17.1381 +Small,4x4,ldr-rgb-09.png,41.9339,0.0098,0.0047,13.9143 +Small,4x4,ldr-rgb-10.png,44.4590,0.0043,0.0013,12.6993 +Small,4x4,ldr-rgba-00.png,35.6010,0.0160,0.0106,6.1629 +Small,4x4,ldr-rgba-01.png,38.8640,0.0114,0.0061,10.7123 +Small,4x4,ldr-rgba-02.png,34.8755,0.0141,0.0087,7.5111 +Small,4x4,ldr-xy-00.png,37.5551,0.0114,0.0042,15.5888 +Small,4x4,ldr-xy-01.png,44.3046,0.0123,0.0052,12.6689 +Small,4x4,ldr-xy-02.png,48.2608,0.0105,0.0031,20.9991 +Small,4x4,ldrs-rgba-00.png,35.6065,0.0159,0.0105,6.2243 +Small,4x4,ldrs-rgba-01.png,38.8848,0.0114,0.0062,10.5995 +Small,4x4,ldrs-rgba-02.png,34.8762,0.0143,0.0088,7.4559 +Small,5x5,hdr-rgb-00.hdr,29.5480,0.0978,0.0121,5.4086 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.5434 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5566 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0005,0.5390 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5845 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5804 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0004,0.5764 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5807 +Small,5x5,ldr-rgb-00.png,34.4321,0.0134,0.0075,8.7535 +Small,5x5,ldr-rgb-01.png,36.2469,0.0106,0.0049,13.3365 +Small,5x5,ldr-rgb-02.png,31.0931,0.0136,0.0079,8.2633 +Small,5x5,ldr-rgb-03.png,42.7531,0.0075,0.0020,32.8017 +Small,5x5,ldr-rgb-04.png,37.2747,0.0099,0.0043,15.4201 +Small,5x5,ldr-rgb-05.png,33.2744,0.0158,0.0101,6.5197 +Small,5x5,ldr-rgb-06.png,31.1326,0.0136,0.0077,8.4792 +Small,5x5,ldr-rgb-07.png,35.0664,0.0139,0.0083,7.9417 +Small,5x5,ldr-rgb-08.png,40.1866,0.0086,0.0032,20.7330 +Small,5x5,ldr-rgb-09.png,37.3026,0.0099,0.0043,15.3409 +Small,5x5,ldr-rgb-10.png,40.1964,0.0048,0.0012,14.0728 +Small,5x5,ldr-rgba-00.png,32.1470,0.0163,0.0105,6.2653 +Small,5x5,ldr-rgba-01.png,35.1987,0.0117,0.0058,11.3286 +Small,5x5,ldr-rgba-02.png,31.1340,0.0142,0.0081,8.1241 +Small,5x5,ldr-xy-00.png,36.7495,0.0116,0.0035,18.5866 +Small,5x5,ldr-xy-01.png,39.8321,0.0124,0.0043,15.1984 +Small,5x5,ldr-xy-02.png,43.9343,0.0112,0.0030,21.9850 +Small,5x5,ldrs-rgba-00.png,32.1514,0.0166,0.0107,6.1526 +Small,5x5,ldrs-rgba-01.png,35.2069,0.0117,0.0057,11.4959 +Small,5x5,ldrs-rgba-02.png,31.1349,0.0142,0.0081,8.0550 +Small,6x6,hdr-rgb-00.hdr,27.0790,0.0970,0.0118,5.5756 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5900 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5887 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5807 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5829 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5845 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5884 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0005,0.5543 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5754 +Small,6x6,ldr-rgb-00.png,31.7144,0.0146,0.0089,7.3902 +Small,6x6,ldr-rgb-01.png,32.9244,0.0115,0.0059,11.0704 +Small,6x6,ldr-rgb-02.png,27.4795,0.0140,0.0084,7.7862 +Small,6x6,ldr-rgb-03.png,40.5991,0.0073,0.0020,32.9629 +Small,6x6,ldr-rgb-04.png,33.9357,0.0104,0.0049,13.4513 +Small,6x6,ldr-rgb-05.png,29.9800,0.0170,0.0114,5.7700 +Small,6x6,ldr-rgb-06.png,27.5476,0.0140,0.0083,7.8514 +Small,6x6,ldr-rgb-07.png,32.9378,0.0133,0.0078,8.3751 +Small,6x6,ldr-rgb-08.png,37.8129,0.0085,0.0033,20.1273 +Small,6x6,ldr-rgb-09.png,33.4946,0.0106,0.0050,13.0083 +Small,6x6,ldr-rgb-10.png,36.6909,0.0049,0.0013,12.9723 +Small,6x6,ldr-rgba-00.png,29.6086,0.0177,0.0119,5.5063 +Small,6x6,ldr-rgba-01.png,32.0847,0.0122,0.0063,10.3466 +Small,6x6,ldr-rgba-02.png,27.8414,0.0149,0.0090,7.2883 +Small,6x6,ldr-xy-00.png,35.9075,0.0116,0.0035,18.5078 +Small,6x6,ldr-xy-01.png,37.1654,0.0128,0.0050,13.0212 +Small,6x6,ldr-xy-02.png,41.9299,0.0107,0.0029,22.5439 +Small,6x6,ldrs-rgba-00.png,29.6031,0.0180,0.0122,5.3935 +Small,6x6,ldrs-rgba-01.png,32.0904,0.0121,0.0064,10.1939 +Small,6x6,ldrs-rgba-02.png,27.8386,0.0149,0.0090,7.2560 +Small,8x8,hdr-rgb-00.hdr,23.7844,0.0999,0.0141,4.6645 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0037,0.0005,0.5601 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0036,0.0004,0.5739 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0037,0.0005,0.5518 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0037,0.0005,0.5437 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0037,0.0005,0.5470 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0004,0.5832 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0004,0.5791 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0004,0.5727 +Small,8x8,ldr-rgb-00.png,28.0659,0.0158,0.0097,6.7676 +Small,8x8,ldr-rgb-01.png,28.7734,0.0132,0.0074,8.8192 +Small,8x8,ldr-rgb-02.png,23.1042,0.0172,0.0114,5.7716 +Small,8x8,ldr-rgb-03.png,37.3496,0.0077,0.0022,29.4933 +Small,8x8,ldr-rgb-04.png,29.3469,0.0125,0.0068,9.6948 +Small,8x8,ldr-rgb-05.png,25.8034,0.0192,0.0133,4.9260 +Small,8x8,ldr-rgb-06.png,23.1655,0.0175,0.0116,5.6255 +Small,8x8,ldr-rgb-07.png,29.8427,0.0133,0.0076,8.5781 +Small,8x8,ldr-rgb-08.png,34.4844,0.0090,0.0035,18.9075 +Small,8x8,ldr-rgb-09.png,28.6410,0.0120,0.0063,10.3256 +Small,8x8,ldr-rgb-10.png,31.9947,0.0053,0.0016,10.0461 +Small,8x8,ldr-rgba-00.png,25.7010,0.0193,0.0132,4.9505 +Small,8x8,ldr-rgba-01.png,28.2814,0.0149,0.0088,7.4187 +Small,8x8,ldr-rgba-02.png,23.9350,0.0185,0.0124,5.2831 +Small,8x8,ldr-xy-00.png,33.3347,0.0130,0.0045,14.7175 +Small,8x8,ldr-xy-01.png,34.3877,0.0138,0.0053,12.2818 +Small,8x8,ldr-xy-02.png,39.8793,0.0104,0.0020,32.8683 +Small,8x8,ldrs-rgba-00.png,25.7001,0.0192,0.0131,4.9936 +Small,8x8,ldrs-rgba-01.png,28.2840,0.0149,0.0087,7.5114 +Small,8x8,ldrs-rgba-02.png,23.9352,0.0187,0.0125,5.2236 +Small,12x12,hdr-rgb-00.hdr,20.5374,0.1084,0.0205,3.1928 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0055,0.0005,0.5256 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0055,0.0005,0.5540 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0055,0.0005,0.5566 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0055,0.0005,0.5566 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0054,0.0004,0.5739 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0055,0.0004,0.5714 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0005,0.5666 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0055,0.0004,0.5714 +Small,12x12,ldr-rgb-00.png,23.7930,0.0162,0.0083,7.9168 +Small,12x12,ldr-rgb-01.png,24.7698,0.0138,0.0060,10.9044 +Small,12x12,ldr-rgb-02.png,19.2293,0.0211,0.0133,4.9124 +Small,12x12,ldr-rgb-03.png,33.2561,0.0090,0.0016,41.2173 +Small,12x12,ldr-rgb-04.png,24.5727,0.0135,0.0058,11.2701 +Small,12x12,ldr-rgb-05.png,21.4915,0.0196,0.0118,5.5324 +Small,12x12,ldr-rgb-06.png,19.2266,0.0220,0.0142,4.6136 +Small,12x12,ldr-rgb-07.png,25.3769,0.0134,0.0056,11.6139 +Small,12x12,ldr-rgb-08.png,30.2961,0.0102,0.0027,24.5646 +Small,12x12,ldr-rgb-09.png,23.7353,0.0151,0.0074,8.9041 +Small,12x12,ldr-rgb-10.png,27.3243,0.0076,0.0019,8.4794 +Small,12x12,ldr-rgba-00.png,21.6059,0.0215,0.0135,4.8538 +Small,12x12,ldr-rgba-01.png,24.5172,0.0152,0.0073,8.9324 +Small,12x12,ldr-rgba-02.png,20.1746,0.0240,0.0158,4.1434 +Small,12x12,ldr-xy-00.png,29.2247,0.0159,0.0047,13.9087 +Small,12x12,ldr-xy-01.png,30.5463,0.0152,0.0041,15.9720 +Small,12x12,ldr-xy-02.png,37.9988,0.0122,0.0011,59.2537 +Small,12x12,ldrs-rgba-00.png,21.6106,0.0216,0.0137,4.7854 +Small,12x12,ldrs-rgba-01.png,24.5187,0.0154,0.0074,8.8957 +Small,12x12,ldrs-rgba-02.png,20.1751,0.0239,0.0158,4.1494 +Small,3x3x3,ldr-l-00-3.dds,50.8347,0.0152,0.0075,34.9484 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0073,0.0032,21.6325 +Small,6x6x6,ldr-l-00-3.dds,32.5284,0.0457,0.0346,7.5692 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0208,0.0132,5.2323 diff --git a/Test/Images/Small/astc_reference-4.4-avx2_fastest_results.csv b/Test/Images/Small/astc_reference-4.4-avx2_fastest_results.csv new file mode 100644 index 0000000..cee75d7 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-avx2_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3455,0.0916,0.0073,8.9371 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0022,0.0004,0.5982 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0023,0.0004,0.5845 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.5896 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0022,0.0004,0.5832 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0023,0.0004,0.5896 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0023,0.0004,0.5884 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5874 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0023,0.0004,0.6025 +Small,4x4,ldr-rgb-00.png,37.2470,0.0090,0.0044,14.9423 +Small,4x4,ldr-rgb-01.png,39.5439,0.0085,0.0040,16.3103 +Small,4x4,ldr-rgb-02.png,34.7920,0.0103,0.0058,11.2858 +Small,4x4,ldr-rgb-03.png,45.4866,0.0060,0.0019,34.3640 +Small,4x4,ldr-rgb-04.png,41.7158,0.0076,0.0031,20.9574 +Small,4x4,ldr-rgb-05.png,36.8705,0.0106,0.0061,10.6927 +Small,4x4,ldr-rgb-06.png,34.9665,0.0100,0.0055,11.9746 +Small,4x4,ldr-rgb-07.png,37.3645,0.0103,0.0058,11.3091 +Small,4x4,ldr-rgb-08.png,42.9454,0.0067,0.0025,26.2238 +Small,4x4,ldr-rgb-09.png,41.7396,0.0075,0.0031,21.3464 +Small,4x4,ldr-rgb-10.png,43.9436,0.0035,0.0010,15.5989 +Small,4x4,ldr-rgba-00.png,34.7343,0.0106,0.0059,11.1666 +Small,4x4,ldr-rgba-01.png,38.6694,0.0090,0.0044,14.9659 +Small,4x4,ldr-rgba-02.png,34.5634,0.0108,0.0060,10.8880 +Small,4x4,ldr-xy-00.png,37.5260,0.0096,0.0032,20.5639 +Small,4x4,ldr-xy-01.png,43.9781,0.0102,0.0036,18.2911 +Small,4x4,ldr-xy-02.png,48.2748,0.0091,0.0026,25.1581 +Small,4x4,ldrs-rgba-00.png,34.7385,0.0106,0.0060,10.9960 +Small,4x4,ldrs-rgba-01.png,38.6861,0.0093,0.0045,14.5631 +Small,4x4,ldrs-rgba-02.png,34.5669,0.0109,0.0061,10.6927 +Small,5x5,hdr-rgb-00.hdr,28.8745,0.0921,0.0074,8.8805 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5791 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5820 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0027,0.0004,0.5795 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5820 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0027,0.0004,0.6171 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5845 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0027,0.0004,0.5820 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5887 +Small,5x5,ldr-rgb-00.png,33.7228,0.0094,0.0044,14.8945 +Small,5x5,ldr-rgb-01.png,36.0754,0.0084,0.0036,18.1545 +Small,5x5,ldr-rgb-02.png,30.9932,0.0105,0.0056,11.7299 +Small,5x5,ldr-rgb-03.png,42.3634,0.0061,0.0016,39.9126 +Small,5x5,ldr-rgb-04.png,37.0411,0.0081,0.0032,20.3719 +Small,5x5,ldr-rgb-05.png,32.9651,0.0112,0.0064,10.3190 +Small,5x5,ldr-rgb-06.png,31.0371,0.0105,0.0056,11.7701 +Small,5x5,ldr-rgb-07.png,34.4079,0.0102,0.0054,12.1902 +Small,5x5,ldr-rgb-08.png,39.5746,0.0069,0.0022,29.3109 +Small,5x5,ldr-rgb-09.png,37.0834,0.0080,0.0031,20.8115 +Small,5x5,ldr-rgb-10.png,39.9180,0.0038,0.0010,16.0960 +Small,5x5,ldr-rgba-00.png,31.1153,0.0109,0.0059,11.0535 +Small,5x5,ldr-rgba-01.png,35.0411,0.0092,0.0042,15.7388 +Small,5x5,ldr-rgba-02.png,31.0383,0.0112,0.0061,10.8003 +Small,5x5,ldr-xy-00.png,36.5692,0.0099,0.0026,24.8623 +Small,5x5,ldr-xy-01.png,39.2568,0.0103,0.0031,20.8715 +Small,5x5,ldr-xy-02.png,43.8559,0.0096,0.0024,27.2049 +Small,5x5,ldrs-rgba-00.png,31.1160,0.0110,0.0060,10.8992 +Small,5x5,ldrs-rgba-01.png,35.0497,0.0093,0.0043,15.3161 +Small,5x5,ldrs-rgba-02.png,31.0387,0.0112,0.0061,10.7278 +Small,6x6,hdr-rgb-00.hdr,26.7600,0.0914,0.0067,9.7264 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0026,0.0005,0.5675 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5807 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5804 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5913 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5858 +Small,6x6,ldr-rgb-00.png,31.3436,0.0099,0.0049,13.4592 +Small,6x6,ldr-rgb-01.png,32.8352,0.0088,0.0040,16.4381 +Small,6x6,ldr-rgb-02.png,27.3910,0.0108,0.0060,10.8669 +Small,6x6,ldr-rgb-03.png,40.3557,0.0060,0.0016,42.1463 +Small,6x6,ldr-rgb-04.png,33.7632,0.0084,0.0036,18.2643 +Small,6x6,ldr-rgb-05.png,29.7440,0.0116,0.0068,9.6846 +Small,6x6,ldr-rgb-06.png,27.4701,0.0109,0.0060,10.8378 +Small,6x6,ldr-rgb-07.png,32.3394,0.0097,0.0050,13.1887 +Small,6x6,ldr-rgb-08.png,37.4420,0.0067,0.0022,30.2429 +Small,6x6,ldr-rgb-09.png,33.3139,0.0083,0.0035,18.8492 +Small,6x6,ldr-rgb-10.png,36.5787,0.0038,0.0011,15.2227 +Small,6x6,ldr-rgba-00.png,28.8478,0.0111,0.0061,10.6600 +Small,6x6,ldr-rgba-01.png,31.9937,0.0096,0.0046,14.1792 +Small,6x6,ldr-rgba-02.png,27.7812,0.0113,0.0062,10.6098 +Small,6x6,ldr-xy-00.png,35.6139,0.0097,0.0027,24.4271 +Small,6x6,ldr-xy-01.png,36.5248,0.0104,0.0034,19.5337 +Small,6x6,ldr-xy-02.png,41.7978,0.0093,0.0022,29.5187 +Small,6x6,ldrs-rgba-00.png,28.8438,0.0112,0.0062,10.5959 +Small,6x6,ldrs-rgba-01.png,31.9996,0.0096,0.0045,14.4384 +Small,6x6,ldrs-rgba-02.png,27.7798,0.0114,0.0062,10.5345 +Small,8x8,hdr-rgb-00.hdr,23.6156,0.0953,0.0098,6.6913 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5807 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5651 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5690 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0005,0.5675 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5807 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5939 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5832 +Small,8x8,ldr-rgb-00.png,27.7154,0.0125,0.0067,9.7888 +Small,8x8,ldr-rgb-01.png,28.6823,0.0113,0.0057,11.5870 +Small,8x8,ldr-rgb-02.png,23.0282,0.0141,0.0084,7.8093 +Small,8x8,ldr-rgb-03.png,37.0615,0.0071,0.0018,36.0259 +Small,8x8,ldr-rgb-04.png,29.1235,0.0110,0.0053,12.3491 +Small,8x8,ldr-rgb-05.png,25.6005,0.0152,0.0096,6.8259 +Small,8x8,ldr-rgb-06.png,23.0809,0.0143,0.0086,7.6266 +Small,8x8,ldr-rgb-07.png,29.4687,0.0111,0.0055,11.8743 +Small,8x8,ldr-rgb-08.png,33.9575,0.0079,0.0025,26.0375 +Small,8x8,ldr-rgb-09.png,28.4481,0.0105,0.0050,13.2369 +Small,8x8,ldr-rgb-10.png,31.9049,0.0049,0.0013,12.3340 +Small,8x8,ldr-rgba-00.png,25.3472,0.0149,0.0089,7.3536 +Small,8x8,ldr-rgba-01.png,28.1822,0.0126,0.0065,10.1121 +Small,8x8,ldr-rgba-02.png,23.8729,0.0146,0.0087,7.5659 +Small,8x8,ldr-xy-00.png,33.2129,0.0118,0.0035,18.6712 +Small,8x8,ldr-xy-01.png,34.1355,0.0123,0.0041,16.1266 +Small,8x8,ldr-xy-02.png,39.7699,0.0100,0.0016,39.7682 +Small,8x8,ldrs-rgba-00.png,25.3477,0.0148,0.0090,7.3176 +Small,8x8,ldrs-rgba-01.png,28.1833,0.0122,0.0064,10.2835 +Small,8x8,ldrs-rgba-02.png,23.8723,0.0153,0.0092,7.1389 +Small,12x12,hdr-rgb-00.hdr,20.4504,0.1015,0.0142,4.6080 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0049,0.0004,0.5845 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0049,0.0005,0.5601 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0050,0.0005,0.5470 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5754 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0004,0.5727 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5845 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5842 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0004,0.5829 +Small,12x12,ldr-rgb-00.png,23.7157,0.0133,0.0061,10.7669 +Small,12x12,ldr-rgb-01.png,24.7251,0.0115,0.0044,14.7530 +Small,12x12,ldr-rgb-02.png,19.1954,0.0166,0.0094,6.9800 +Small,12x12,ldr-rgb-03.png,33.1615,0.0082,0.0014,48.1145 +Small,12x12,ldr-rgb-04.png,24.3846,0.0115,0.0044,14.9691 +Small,12x12,ldr-rgb-05.png,21.3862,0.0157,0.0086,7.6366 +Small,12x12,ldr-rgb-06.png,19.1691,0.0173,0.0100,6.5852 +Small,12x12,ldr-rgb-07.png,25.3196,0.0113,0.0042,15.7541 +Small,12x12,ldr-rgb-08.png,30.1240,0.0090,0.0021,31.4290 +Small,12x12,ldr-rgb-09.png,23.5957,0.0126,0.0055,11.9616 +Small,12x12,ldr-rgb-10.png,27.2837,0.0065,0.0016,10.4542 +Small,12x12,ldr-rgba-00.png,21.3587,0.0168,0.0094,6.9586 +Small,12x12,ldr-rgba-01.png,24.4758,0.0127,0.0053,12.2845 +Small,12x12,ldr-rgba-02.png,20.1402,0.0187,0.0112,5.8265 +Small,12x12,ldr-xy-00.png,28.8913,0.0142,0.0035,18.7668 +Small,12x12,ldr-xy-01.png,29.6644,0.0137,0.0031,20.9239 +Small,12x12,ldr-xy-02.png,37.9766,0.0114,0.0010,66.7990 +Small,12x12,ldrs-rgba-00.png,21.3601,0.0169,0.0095,6.8940 +Small,12x12,ldrs-rgba-01.png,24.4766,0.0127,0.0053,12.3164 +Small,12x12,ldrs-rgba-02.png,20.1395,0.0188,0.0113,5.8049 +Small,3x3x3,ldr-l-00-3.dds,50.6895,0.0141,0.0073,35.9600 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0064,0.0031,22.1192 +Small,6x6x6,ldr-l-00-3.dds,32.5118,0.0457,0.0346,7.5701 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0210,0.0133,5.1665 diff --git a/Test/Images/Small/astc_reference-4.4-avx2_medium_results.csv b/Test/Images/Small/astc_reference-4.4-avx2_medium_results.csv new file mode 100644 index 0000000..caa358d --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-avx2_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1462,0.1031,0.0180,3.6387 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0035,0.0004,0.5739 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5675 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5663 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5820 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5842 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5730 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5313 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5518 +Small,4x4,ldr-rgb-00.png,38.8432,0.0259,0.0199,3.3006 +Small,4x4,ldr-rgb-01.png,40.2258,0.0225,0.0167,3.9128 +Small,4x4,ldr-rgb-02.png,35.2933,0.0229,0.0172,3.8213 +Small,4x4,ldr-rgb-03.png,47.2820,0.0149,0.0095,6.8878 +Small,4x4,ldr-rgb-04.png,42.2203,0.0189,0.0131,5.0009 +Small,4x4,ldr-rgb-05.png,37.8177,0.0245,0.0188,3.4869 +Small,4x4,ldr-rgb-06.png,35.4758,0.0208,0.0150,4.3831 +Small,4x4,ldr-rgb-07.png,39.2847,0.0297,0.0239,2.7367 +Small,4x4,ldr-rgb-08.png,45.1880,0.0173,0.0118,5.5469 +Small,4x4,ldr-rgb-09.png,42.1624,0.0191,0.0135,4.8621 +Small,4x4,ldr-rgb-10.png,44.9412,0.0059,0.0022,7.3252 +Small,4x4,ldr-rgba-00.png,36.2597,0.0279,0.0218,3.0035 +Small,4x4,ldr-rgba-01.png,38.9707,0.0187,0.0126,5.1951 +Small,4x4,ldr-rgba-02.png,34.9421,0.0200,0.0139,4.7223 +Small,4x4,ldr-xy-00.png,37.7304,0.0182,0.0109,6.0313 +Small,4x4,ldr-xy-01.png,45.3643,0.0240,0.0168,3.9079 +Small,4x4,ldr-xy-02.png,51.1886,0.0269,0.0195,3.3613 +Small,4x4,ldrs-rgba-00.png,36.2659,0.0280,0.0220,2.9747 +Small,4x4,ldrs-rgba-01.png,38.9909,0.0187,0.0127,5.1632 +Small,4x4,ldrs-rgba-02.png,34.9450,0.0201,0.0140,4.6824 +Small,5x5,hdr-rgb-00.hdr,29.9063,0.1054,0.0196,3.3505 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0047,0.0006,0.4444 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0005,0.5212 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0047,0.0005,0.5639 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0047,0.0005,0.5225 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0047,0.0004,0.5884 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0046,0.0005,0.5589 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0047,0.0005,0.5245 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0046,0.0004,0.5702 +Small,5x5,ldr-rgb-00.png,35.1487,0.0268,0.0199,3.2964 +Small,5x5,ldr-rgb-01.png,36.4456,0.0207,0.0141,4.6645 +Small,5x5,ldr-rgb-02.png,31.1355,0.0212,0.0143,4.5942 +Small,5x5,ldr-rgb-03.png,44.0259,0.0125,0.0060,11.0110 +Small,5x5,ldr-rgb-04.png,37.6738,0.0196,0.0129,5.0713 +Small,5x5,ldr-rgb-05.png,33.5459,0.0278,0.0210,3.1254 +Small,5x5,ldr-rgb-06.png,31.1791,0.0207,0.0137,4.7878 +Small,5x5,ldr-rgb-07.png,36.1557,0.0315,0.0246,2.6590 +Small,5x5,ldr-rgb-08.png,41.6368,0.0167,0.0101,6.4862 +Small,5x5,ldr-rgb-09.png,37.5922,0.0190,0.0121,5.4103 +Small,5x5,ldr-rgb-10.png,40.5794,0.0071,0.0024,6.8885 +Small,5x5,ldr-rgba-00.png,32.8173,0.0312,0.0242,2.7093 +Small,5x5,ldr-rgba-01.png,35.3162,0.0202,0.0132,4.9834 +Small,5x5,ldr-rgba-02.png,31.1464,0.0219,0.0148,4.4359 +Small,5x5,ldr-xy-00.png,37.0404,0.0188,0.0104,6.2732 +Small,5x5,ldr-xy-01.png,40.7159,0.0233,0.0150,4.3772 +Small,5x5,ldr-xy-02.png,49.1543,0.0198,0.0112,5.8566 +Small,5x5,ldrs-rgba-00.png,32.8214,0.0316,0.0245,2.6714 +Small,5x5,ldrs-rgba-01.png,35.3251,0.0203,0.0132,4.9751 +Small,5x5,ldrs-rgba-02.png,31.1476,0.0219,0.0147,4.4567 +Small,6x6,hdr-rgb-00.hdr,27.5227,0.1062,0.0199,3.2890 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0045,0.0005,0.5041 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0044,0.0005,0.5331 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0005,0.5518 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0043,0.0004,0.5776 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0044,0.0005,0.5426 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0005,0.5010 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0005,0.5279 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0005,0.5162 +Small,6x6,ldr-rgb-00.png,32.4046,0.0275,0.0208,3.1544 +Small,6x6,ldr-rgb-01.png,33.0877,0.0203,0.0138,4.7535 +Small,6x6,ldr-rgb-02.png,27.5101,0.0211,0.0145,4.5076 +Small,6x6,ldr-rgb-03.png,41.7485,0.0109,0.0047,13.9823 +Small,6x6,ldr-rgb-04.png,34.2066,0.0182,0.0118,5.5454 +Small,6x6,ldr-rgb-05.png,30.1436,0.0277,0.0211,3.1051 +Small,6x6,ldr-rgb-06.png,27.5774,0.0207,0.0140,4.6684 +Small,6x6,ldr-rgb-07.png,33.8833,0.0293,0.0228,2.8750 +Small,6x6,ldr-rgb-08.png,39.2140,0.0139,0.0077,8.5220 +Small,6x6,ldr-rgb-09.png,33.6689,0.0181,0.0116,5.6316 +Small,6x6,ldr-rgb-10.png,36.9896,0.0069,0.0024,6.7401 +Small,6x6,ldr-rgba-00.png,30.2544,0.0333,0.0265,2.4739 +Small,6x6,ldr-rgba-01.png,32.2005,0.0202,0.0134,4.8751 +Small,6x6,ldr-rgba-02.png,27.8556,0.0226,0.0158,4.1602 +Small,6x6,ldr-xy-00.png,36.1662,0.0174,0.0092,7.1142 +Small,6x6,ldr-xy-01.png,38.0135,0.0192,0.0112,5.8415 +Small,6x6,ldr-xy-02.png,46.1312,0.0163,0.0082,7.9913 +Small,6x6,ldrs-rgba-00.png,30.2495,0.0333,0.0267,2.4572 +Small,6x6,ldrs-rgba-01.png,32.2065,0.0203,0.0135,4.8654 +Small,6x6,ldrs-rgba-02.png,27.8520,0.0226,0.0158,4.1410 +Small,8x8,hdr-rgb-00.hdr,24.1390,0.1120,0.0251,2.6143 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0051,0.0005,0.5412 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0051,0.0005,0.5256 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0051,0.0005,0.4664 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0051,0.0005,0.5379 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0052,0.0005,0.5039 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0050,0.0005,0.5401 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0050,0.0005,0.5279 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0050,0.0005,0.5625 +Small,8x8,ldr-rgb-00.png,28.7594,0.0343,0.0270,2.4291 +Small,8x8,ldr-rgb-01.png,28.9369,0.0246,0.0173,3.7797 +Small,8x8,ldr-rgb-02.png,23.1670,0.0259,0.0187,3.5016 +Small,8x8,ldr-rgb-03.png,38.5914,0.0125,0.0055,11.9590 +Small,8x8,ldr-rgb-04.png,29.6483,0.0240,0.0168,3.9002 +Small,8x8,ldr-rgb-05.png,25.9418,0.0329,0.0255,2.5703 +Small,8x8,ldr-rgb-06.png,23.2010,0.0264,0.0191,3.4314 +Small,8x8,ldr-rgb-07.png,30.7551,0.0339,0.0268,2.4483 +Small,8x8,ldr-rgb-08.png,35.9297,0.0163,0.0093,7.0325 +Small,8x8,ldr-rgb-09.png,28.9847,0.0224,0.0153,4.2840 +Small,8x8,ldr-rgb-10.png,32.1811,0.0083,0.0032,5.1054 +Small,8x8,ldr-rgba-00.png,26.4734,0.0399,0.0323,2.0270 +Small,8x8,ldr-rgba-01.png,28.3748,0.0246,0.0173,3.7957 +Small,8x8,ldr-rgba-02.png,23.9432,0.0281,0.0206,3.1777 +Small,8x8,ldr-xy-00.png,33.9578,0.0223,0.0122,5.3644 +Small,8x8,ldr-xy-01.png,34.9740,0.0224,0.0123,5.3295 +Small,8x8,ldr-xy-02.png,41.6833,0.0183,0.0082,7.9456 +Small,8x8,ldrs-rgba-00.png,26.4748,0.0402,0.0326,2.0088 +Small,8x8,ldrs-rgba-01.png,28.3782,0.0248,0.0172,3.8032 +Small,8x8,ldrs-rgba-02.png,23.9434,0.0281,0.0206,3.1882 +Small,12x12,hdr-rgb-00.hdr,20.7679,0.1268,0.0365,1.7935 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0080,0.0006,0.4377 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0079,0.0005,0.5369 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0078,0.0005,0.5434 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0079,0.0005,0.5437 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0080,0.0004,0.5739 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0078,0.0005,0.5423 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0078,0.0005,0.5589 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0079,0.0005,0.5601 +Small,12x12,ldr-rgb-00.png,24.6928,0.0433,0.0328,1.9981 +Small,12x12,ldr-rgb-01.png,25.0361,0.0328,0.0226,2.9011 +Small,12x12,ldr-rgb-02.png,19.2723,0.0378,0.0277,2.3695 +Small,12x12,ldr-rgb-03.png,34.9910,0.0159,0.0060,10.8613 +Small,12x12,ldr-rgb-04.png,24.8973,0.0315,0.0212,3.0893 +Small,12x12,ldr-rgb-05.png,21.6527,0.0434,0.0332,1.9765 +Small,12x12,ldr-rgb-06.png,19.2558,0.0384,0.0281,2.3288 +Small,12x12,ldr-rgb-07.png,26.7423,0.0396,0.0295,2.2207 +Small,12x12,ldr-rgb-08.png,31.6843,0.0198,0.0101,6.5049 +Small,12x12,ldr-rgb-09.png,24.1545,0.0304,0.0204,3.2148 +Small,12x12,ldr-rgb-10.png,28.0447,0.0146,0.0066,2.4758 +Small,12x12,ldr-rgba-00.png,22.2585,0.0477,0.0373,1.7560 +Small,12x12,ldr-rgba-01.png,24.6414,0.0319,0.0215,3.0459 +Small,12x12,ldr-rgba-02.png,20.1882,0.0406,0.0302,2.1730 +Small,12x12,ldr-xy-00.png,30.2558,0.0286,0.0148,4.4332 +Small,12x12,ldr-xy-01.png,31.8636,0.0293,0.0155,4.2170 +Small,12x12,ldr-xy-02.png,38.5089,0.0173,0.0034,19.2249 +Small,12x12,ldrs-rgba-00.png,22.2585,0.0488,0.0381,1.7202 +Small,12x12,ldrs-rgba-01.png,24.6434,0.0321,0.0216,3.0316 +Small,12x12,ldrs-rgba-02.png,20.1890,0.0414,0.0308,2.1267 +Small,3x3x3,ldr-l-00-3.dds,51.8899,0.0193,0.0108,24.2905 +Small,3x3x3,ldr-l-01-3.dds,54.6239,0.0085,0.0034,20.3003 +Small,6x6x6,ldr-l-00-3.dds,32.9631,0.0561,0.0424,6.1879 +Small,6x6x6,ldr-l-01-3.dds,41.0369,0.0234,0.0133,5.1801 diff --git a/Test/Images/Small/astc_reference-4.4-avx2_thorough_results.csv b/Test/Images/Small/astc_reference-4.4-avx2_thorough_results.csv new file mode 100644 index 0000000..c2690c8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-avx2_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.4205,0.1192,0.0351,1.8669 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0038,0.0006,0.4288 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0037,0.0005,0.5079 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0037,0.0005,0.5355 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5289 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0037,0.0005,0.5578 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0037,0.0005,0.4971 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0037,0.0005,0.5321 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0038,0.0005,0.4905 +Small,4x4,ldr-rgb-00.png,39.1635,0.0457,0.0397,1.6495 +Small,4x4,ldr-rgb-01.png,40.4120,0.0437,0.0380,1.7265 +Small,4x4,ldr-rgb-02.png,35.4711,0.0412,0.0354,1.8527 +Small,4x4,ldr-rgb-03.png,47.7527,0.0408,0.0353,1.8591 +Small,4x4,ldr-rgb-04.png,42.3660,0.0373,0.0316,2.0750 +Small,4x4,ldr-rgb-05.png,37.9925,0.0450,0.0391,1.6774 +Small,4x4,ldr-rgb-06.png,35.6403,0.0369,0.0310,2.1138 +Small,4x4,ldr-rgb-07.png,39.8791,0.0544,0.0486,1.3495 +Small,4x4,ldr-rgb-08.png,45.8775,0.0400,0.0344,1.9025 +Small,4x4,ldr-rgb-09.png,42.2993,0.0401,0.0344,1.9052 +Small,4x4,ldr-rgb-10.png,45.1694,0.0083,0.0046,3.5455 +Small,4x4,ldr-rgba-00.png,36.7416,0.0482,0.0421,1.5556 +Small,4x4,ldr-rgba-01.png,39.1154,0.0352,0.0291,2.2555 +Small,4x4,ldr-rgba-02.png,35.0328,0.0348,0.0286,2.2920 +Small,4x4,ldr-xy-00.png,37.7724,0.0430,0.0356,1.8392 +Small,4x4,ldr-xy-01.png,45.4608,0.0474,0.0403,1.6263 +Small,4x4,ldr-xy-02.png,51.1938,0.0613,0.0539,1.2155 +Small,4x4,ldrs-rgba-00.png,36.7495,0.0483,0.0423,1.5497 +Small,4x4,ldrs-rgba-01.png,39.1372,0.0352,0.0292,2.2468 +Small,4x4,ldrs-rgba-02.png,35.0344,0.0349,0.0286,2.2893 +Small,5x5,hdr-rgb-00.hdr,30.3005,0.1237,0.0376,1.7453 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0046,0.0005,0.5434 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0005,0.5639 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0046,0.0005,0.5651 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0048,0.0005,0.5020 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0047,0.0005,0.5390 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0047,0.0004,0.5751 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0047,0.0005,0.5628 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0047,0.0005,0.5663 +Small,5x5,ldr-rgb-00.png,35.3880,0.0526,0.0453,1.4452 +Small,5x5,ldr-rgb-01.png,36.5413,0.0453,0.0383,1.7111 +Small,5x5,ldr-rgb-02.png,31.1967,0.0395,0.0327,2.0044 +Small,5x5,ldr-rgb-03.png,44.5932,0.0447,0.0381,1.7195 +Small,5x5,ldr-rgb-04.png,37.8267,0.0410,0.0342,1.9153 +Small,5x5,ldr-rgb-05.png,33.6963,0.0514,0.0445,1.4717 +Small,5x5,ldr-rgb-06.png,31.2331,0.0373,0.0304,2.1563 +Small,5x5,ldr-rgb-07.png,36.7232,0.0612,0.0544,1.2039 +Small,5x5,ldr-rgb-08.png,42.3949,0.0435,0.0370,1.7717 +Small,5x5,ldr-rgb-09.png,37.7126,0.0450,0.0382,1.7156 +Small,5x5,ldr-rgb-10.png,40.7580,0.0100,0.0052,3.0970 +Small,5x5,ldr-rgba-00.png,33.1240,0.0557,0.0485,1.3499 +Small,5x5,ldr-rgba-01.png,35.4134,0.0393,0.0321,2.0417 +Small,5x5,ldr-rgba-02.png,31.1844,0.0380,0.0308,2.1267 +Small,5x5,ldr-xy-00.png,37.1442,0.0471,0.0386,1.6976 +Small,5x5,ldr-xy-01.png,41.4542,0.0559,0.0475,1.3794 +Small,5x5,ldr-xy-02.png,49.3313,0.0676,0.0587,1.1164 +Small,5x5,ldrs-rgba-00.png,33.1272,0.0571,0.0499,1.3127 +Small,5x5,ldrs-rgba-01.png,35.4217,0.0397,0.0325,2.0142 +Small,5x5,ldrs-rgba-02.png,31.1853,0.0383,0.0310,2.1137 +Small,6x6,hdr-rgb-00.hdr,27.7238,0.1269,0.0396,1.6540 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0045,0.0004,0.5804 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0045,0.0005,0.5398 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0004,0.5779 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0044,0.0005,0.5578 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0044,0.0005,0.5687 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5504 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0005,0.5470 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0004,0.5804 +Small,6x6,ldr-rgb-00.png,32.6509,0.0542,0.0473,1.3846 +Small,6x6,ldr-rgb-01.png,33.1881,0.0468,0.0402,1.6320 +Small,6x6,ldr-rgb-02.png,27.5552,0.0404,0.0337,1.9425 +Small,6x6,ldr-rgb-03.png,42.5885,0.0374,0.0311,2.1069 +Small,6x6,ldr-rgb-04.png,34.3416,0.0409,0.0343,1.9111 +Small,6x6,ldr-rgb-05.png,30.2875,0.0522,0.0456,1.4375 +Small,6x6,ldr-rgb-06.png,27.6306,0.0392,0.0324,2.0205 +Small,6x6,ldr-rgb-07.png,34.4380,0.0636,0.0570,1.1491 +Small,6x6,ldr-rgb-08.png,40.0373,0.0378,0.0314,2.0891 +Small,6x6,ldr-rgb-09.png,33.8118,0.0447,0.0374,1.7511 +Small,6x6,ldr-rgb-10.png,37.1861,0.0108,0.0062,2.6262 +Small,6x6,ldr-rgba-00.png,30.5164,0.0598,0.0530,1.2366 +Small,6x6,ldr-rgba-01.png,32.2794,0.0424,0.0356,1.8417 +Small,6x6,ldr-rgba-02.png,27.8936,0.0399,0.0329,1.9905 +Small,6x6,ldr-xy-00.png,36.2540,0.0393,0.0311,2.1092 +Small,6x6,ldr-xy-01.png,38.0244,0.0543,0.0459,1.4266 +Small,6x6,ldr-xy-02.png,47.5902,0.0668,0.0585,1.1196 +Small,6x6,ldrs-rgba-00.png,30.5127,0.0600,0.0530,1.2366 +Small,6x6,ldrs-rgba-01.png,32.2857,0.0431,0.0363,1.8059 +Small,6x6,ldrs-rgba-02.png,27.8909,0.0402,0.0331,1.9784 +Small,8x8,hdr-rgb-00.hdr,24.3460,0.1394,0.0513,1.2773 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0067,0.0005,0.4681 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0065,0.0005,0.5276 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0064,0.0005,0.5401 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0064,0.0005,0.5345 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0065,0.0005,0.5048 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0064,0.0005,0.5160 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0064,0.0005,0.5289 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0064,0.0005,0.5543 +Small,8x8,ldr-rgb-00.png,28.9780,0.0694,0.0607,1.0803 +Small,8x8,ldr-rgb-01.png,29.0210,0.0578,0.0492,1.3330 +Small,8x8,ldr-rgb-02.png,23.2052,0.0531,0.0445,1.4726 +Small,8x8,ldr-rgb-03.png,39.4314,0.0274,0.0192,3.4157 +Small,8x8,ldr-rgb-04.png,29.7779,0.0514,0.0426,1.5389 +Small,8x8,ldr-rgb-05.png,26.0426,0.0629,0.0542,1.2101 +Small,8x8,ldr-rgb-06.png,23.2530,0.0525,0.0436,1.5030 +Small,8x8,ldr-rgb-07.png,31.2138,0.0751,0.0665,0.9851 +Small,8x8,ldr-rgb-08.png,36.5612,0.0393,0.0308,2.1250 +Small,8x8,ldr-rgb-09.png,29.1484,0.0452,0.0367,1.7861 +Small,8x8,ldr-rgb-10.png,32.3330,0.0142,0.0076,2.1440 +Small,8x8,ldr-rgba-00.png,26.7531,0.0758,0.0671,0.9773 +Small,8x8,ldr-rgba-01.png,28.4341,0.0549,0.0460,1.4237 +Small,8x8,ldr-rgba-02.png,23.9687,0.0516,0.0425,1.5421 +Small,8x8,ldr-xy-00.png,34.2380,0.0469,0.0366,1.7924 +Small,8x8,ldr-xy-01.png,35.3165,0.0482,0.0378,1.7317 +Small,8x8,ldr-xy-02.png,44.6234,0.0592,0.0489,1.3398 +Small,8x8,ldrs-rgba-00.png,26.7540,0.0766,0.0675,0.9706 +Small,8x8,ldrs-rgba-01.png,28.4376,0.0556,0.0467,1.4036 +Small,8x8,ldrs-rgba-02.png,23.9689,0.0516,0.0427,1.5345 +Small,12x12,hdr-rgb-00.hdr,21.0311,0.1696,0.0768,0.8539 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0103,0.0004,0.5727 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0103,0.0005,0.5651 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0103,0.0004,0.5727 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0103,0.0005,0.5552 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0103,0.0005,0.5543 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0104,0.0005,0.5555 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0103,0.0004,0.5779 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0104,0.0005,0.5279 +Small,12x12,ldr-rgb-00.png,25.0530,0.0938,0.0807,0.8121 +Small,12x12,ldr-rgb-01.png,25.1392,0.0763,0.0636,1.0300 +Small,12x12,ldr-rgb-02.png,19.2921,0.0845,0.0718,0.9134 +Small,12x12,ldr-rgb-03.png,36.1864,0.0330,0.0204,3.2061 +Small,12x12,ldr-rgb-04.png,24.9919,0.0693,0.0564,1.1613 +Small,12x12,ldr-rgb-05.png,21.7388,0.0847,0.0719,0.9116 +Small,12x12,ldr-rgb-06.png,19.2959,0.0821,0.0691,0.9478 +Small,12x12,ldr-rgb-07.png,27.1136,0.0949,0.0821,0.7985 +Small,12x12,ldr-rgb-08.png,32.5295,0.0415,0.0290,2.2608 +Small,12x12,ldr-rgb-09.png,24.3026,0.0650,0.0524,1.2513 +Small,12x12,ldr-rgb-10.png,28.1806,0.0239,0.0134,1.2165 +Small,12x12,ldr-rgba-00.png,22.7565,0.0985,0.0854,0.7670 +Small,12x12,ldr-rgba-01.png,24.7322,0.0790,0.0657,0.9968 +Small,12x12,ldr-rgba-02.png,20.2051,0.0818,0.0688,0.9528 +Small,12x12,ldr-xy-00.png,30.5347,0.0630,0.0486,1.3478 +Small,12x12,ldr-xy-01.png,32.2811,0.0507,0.0364,1.8018 +Small,12x12,ldr-xy-02.png,40.3051,0.0373,0.0229,2.8561 +Small,12x12,ldrs-rgba-00.png,22.7551,0.0996,0.0866,0.7571 +Small,12x12,ldrs-rgba-01.png,24.7337,0.0789,0.0659,0.9944 +Small,12x12,ldrs-rgba-02.png,20.2055,0.0819,0.0687,0.9543 +Small,3x3x3,ldr-l-00-3.dds,52.3291,0.0325,0.0240,10.9041 +Small,3x3x3,ldr-l-01-3.dds,55.2576,0.0146,0.0095,7.2634 +Small,6x6x6,ldr-l-00-3.dds,33.2763,0.0772,0.0611,4.2895 +Small,6x6x6,ldr-l-01-3.dds,41.7183,0.0265,0.0140,4.9345 diff --git a/Test/Images/Small/astc_reference-4.4-sse2_fast_results.csv b/Test/Images/Small/astc_reference-4.4-sse2_fast_results.csv new file mode 100644 index 0000000..59cbf55 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse2_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7281,0.1036,0.0151,4.3341 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0029,0.0005,0.5448 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0028,0.0004,0.5767 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0005,0.5666 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0028,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0028,0.0004,0.5767 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0028,0.0004,0.5874 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0029,0.0005,0.5529 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0028,0.0004,0.5779 +Small,4x4,ldr-rgb-00.png,38.2512,0.0156,0.0102,6.4294 +Small,4x4,ldr-rgb-01.png,39.9266,0.0136,0.0084,7.8028 +Small,4x4,ldr-rgb-02.png,35.1621,0.0188,0.0134,4.8918 +Small,4x4,ldr-rgb-03.png,46.0782,0.0080,0.0031,21.1542 +Small,4x4,ldr-rgb-04.png,41.9798,0.0111,0.0059,11.0892 +Small,4x4,ldr-rgb-05.png,37.3372,0.0184,0.0132,4.9544 +Small,4x4,ldr-rgb-06.png,35.3603,0.0175,0.0122,5.3767 +Small,4x4,ldr-rgb-07.png,38.1442,0.0190,0.0138,4.7580 +Small,4x4,ldr-rgb-08.png,43.8361,0.0099,0.0049,13.4185 +Small,4x4,ldr-rgb-09.png,41.9339,0.0111,0.0060,10.9413 +Small,4x4,ldr-rgb-10.png,44.4590,0.0044,0.0015,11.0884 +Small,4x4,ldr-rgba-00.png,35.6010,0.0189,0.0134,4.8780 +Small,4x4,ldr-rgba-01.png,38.8640,0.0134,0.0079,8.2620 +Small,4x4,ldr-rgba-02.png,34.8755,0.0167,0.0112,5.8508 +Small,4x4,ldr-xy-00.png,37.5551,0.0127,0.0055,11.9413 +Small,4x4,ldr-xy-01.png,44.3046,0.0140,0.0067,9.8094 +Small,4x4,ldr-xy-02.png,48.2608,0.0115,0.0041,15.8724 +Small,4x4,ldrs-rgba-00.png,35.6065,0.0190,0.0135,4.8621 +Small,4x4,ldrs-rgba-01.png,38.8848,0.0135,0.0079,8.2529 +Small,4x4,ldrs-rgba-02.png,34.8762,0.0168,0.0113,5.7976 +Small,5x5,hdr-rgb-00.hdr,29.5480,0.1057,0.0162,4.0492 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0035,0.0004,0.5767 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5887 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5690 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5791 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.6039 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.5926 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.6108 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5926 +Small,5x5,ldr-rgb-00.png,34.4321,0.0162,0.0102,6.4460 +Small,5x5,ldr-rgb-01.png,36.2469,0.0127,0.0068,9.6290 +Small,5x5,ldr-rgb-02.png,31.0931,0.0168,0.0109,6.0223 +Small,5x5,ldr-rgb-03.png,42.7531,0.0082,0.0025,25.7593 +Small,5x5,ldr-rgb-04.png,37.2747,0.0117,0.0059,11.0892 +Small,5x5,ldr-rgb-05.png,33.2744,0.0199,0.0139,4.7078 +Small,5x5,ldr-rgb-06.png,31.1326,0.0167,0.0107,6.1466 +Small,5x5,ldr-rgb-07.png,35.0664,0.0172,0.0113,5.8022 +Small,5x5,ldr-rgb-08.png,40.1866,0.0100,0.0043,15.3838 +Small,5x5,ldr-rgb-09.png,37.3026,0.0118,0.0060,10.9978 +Small,5x5,ldr-rgb-10.png,40.1964,0.0051,0.0014,11.5544 +Small,5x5,ldr-rgba-00.png,32.1470,0.0205,0.0143,4.5823 +Small,5x5,ldr-rgba-01.png,35.1987,0.0138,0.0077,8.5146 +Small,5x5,ldr-rgba-02.png,31.1340,0.0175,0.0112,5.8618 +Small,5x5,ldr-xy-00.png,36.7495,0.0128,0.0044,14.9969 +Small,5x5,ldr-xy-01.png,39.8321,0.0139,0.0057,11.5016 +Small,5x5,ldr-xy-02.png,43.9343,0.0124,0.0040,16.4243 +Small,5x5,ldrs-rgba-00.png,32.1514,0.0205,0.0145,4.5219 +Small,5x5,ldrs-rgba-01.png,35.2069,0.0139,0.0078,8.4192 +Small,5x5,ldrs-rgba-02.png,31.1349,0.0175,0.0112,5.8603 +Small,6x6,hdr-rgb-00.hdr,27.0790,0.1060,0.0165,3.9711 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0033,0.0004,0.5845 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0033,0.0004,0.5845 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5871 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0033,0.0004,0.5817 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5751 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0033,0.0004,0.5739 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0005,0.5578 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5639 +Small,6x6,ldr-rgb-00.png,31.7144,0.0185,0.0127,5.1660 +Small,6x6,ldr-rgb-01.png,32.9244,0.0140,0.0083,7.8893 +Small,6x6,ldr-rgb-02.png,27.4795,0.0182,0.0123,5.3389 +Small,6x6,ldr-rgb-03.png,40.5991,0.0082,0.0026,24.7682 +Small,6x6,ldr-rgb-04.png,33.9357,0.0128,0.0070,9.3078 +Small,6x6,ldr-rgb-05.png,29.9800,0.0226,0.0168,3.9040 +Small,6x6,ldr-rgb-06.png,27.5476,0.0182,0.0123,5.3269 +Small,6x6,ldr-rgb-07.png,32.9378,0.0170,0.0114,5.7721 +Small,6x6,ldr-rgb-08.png,37.8129,0.0097,0.0043,15.4054 +Small,6x6,ldr-rgb-09.png,33.4946,0.0130,0.0073,8.9873 +Small,6x6,ldr-rgb-10.png,36.6909,0.0053,0.0017,9.5668 +Small,6x6,ldr-rgba-00.png,29.6086,0.0231,0.0171,3.8381 +Small,6x6,ldr-rgba-01.png,32.0847,0.0151,0.0091,7.2239 +Small,6x6,ldr-rgba-02.png,27.8414,0.0190,0.0130,5.0560 +Small,6x6,ldr-xy-00.png,35.9075,0.0129,0.0048,13.6450 +Small,6x6,ldr-xy-01.png,37.1654,0.0151,0.0070,9.3198 +Small,6x6,ldr-xy-02.png,41.9299,0.0118,0.0039,16.9741 +Small,6x6,ldrs-rgba-00.png,29.6031,0.0231,0.0172,3.8138 +Small,6x6,ldrs-rgba-01.png,32.0904,0.0152,0.0092,7.1577 +Small,6x6,ldrs-rgba-02.png,27.8386,0.0192,0.0130,5.0227 +Small,8x8,hdr-rgb-00.hdr,23.7844,0.1092,0.0207,3.1642 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0036,0.0004,0.5767 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5702 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5742 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5675 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0004,0.5702 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0005,0.5663 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5952 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0005,0.5628 +Small,8x8,ldr-rgb-00.png,28.0659,0.0206,0.0142,4.6113 +Small,8x8,ldr-rgb-01.png,28.7734,0.0171,0.0112,5.8582 +Small,8x8,ldr-rgb-02.png,23.1042,0.0231,0.0171,3.8418 +Small,8x8,ldr-rgb-03.png,37.3496,0.0089,0.0030,21.6935 +Small,8x8,ldr-rgb-04.png,29.3469,0.0166,0.0105,6.2606 +Small,8x8,ldr-rgb-05.png,25.8034,0.0262,0.0201,3.2544 +Small,8x8,ldr-rgb-06.png,23.1655,0.0238,0.0176,3.7150 +Small,8x8,ldr-rgb-07.png,29.8427,0.0176,0.0115,5.6874 +Small,8x8,ldr-rgb-08.png,34.4844,0.0106,0.0048,13.5435 +Small,8x8,ldr-rgb-09.png,28.6410,0.0155,0.0096,6.8245 +Small,8x8,ldr-rgb-10.png,31.9947,0.0058,0.0020,7.9458 +Small,8x8,ldr-rgba-00.png,25.7010,0.0254,0.0193,3.4027 +Small,8x8,ldr-rgba-01.png,28.2814,0.0194,0.0131,4.9986 +Small,8x8,ldr-rgba-02.png,23.9350,0.0249,0.0186,3.5178 +Small,8x8,ldr-xy-00.png,33.3347,0.0151,0.0065,10.0902 +Small,8x8,ldr-xy-01.png,34.3877,0.0165,0.0078,8.3935 +Small,8x8,ldr-xy-02.png,39.8793,0.0112,0.0024,26.7938 +Small,8x8,ldrs-rgba-00.png,25.7001,0.0256,0.0194,3.3817 +Small,8x8,ldrs-rgba-01.png,28.2840,0.0194,0.0132,4.9810 +Small,8x8,ldrs-rgba-02.png,23.9352,0.0251,0.0187,3.4962 +Small,12x12,hdr-rgb-00.hdr,20.5374,0.1218,0.0297,2.2065 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0054,0.0004,0.5817 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0054,0.0004,0.5874 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0054,0.0004,0.5702 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0054,0.0004,0.5730 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0054,0.0004,0.5767 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0054,0.0005,0.5601 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0004,0.5845 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0055,0.0004,0.5804 +Small,12x12,ldr-rgb-00.png,23.7930,0.0204,0.0122,5.3651 +Small,12x12,ldr-rgb-01.png,24.7698,0.0170,0.0089,7.3603 +Small,12x12,ldr-rgb-02.png,19.2293,0.0274,0.0194,3.3719 +Small,12x12,ldr-rgb-03.png,33.2561,0.0098,0.0022,30.2996 +Small,12x12,ldr-rgb-04.png,24.5727,0.0164,0.0084,7.7586 +Small,12x12,ldr-rgb-05.png,21.4915,0.0251,0.0171,3.8256 +Small,12x12,ldr-rgb-06.png,19.2266,0.0285,0.0205,3.2037 +Small,12x12,ldr-rgb-07.png,25.3769,0.0162,0.0083,7.8854 +Small,12x12,ldr-rgb-08.png,30.2961,0.0113,0.0037,17.7421 +Small,12x12,ldr-rgb-09.png,23.7353,0.0186,0.0108,6.0732 +Small,12x12,ldr-rgb-10.png,27.3243,0.0084,0.0027,5.9590 +Small,12x12,ldr-rgba-00.png,21.6059,0.0274,0.0193,3.3918 +Small,12x12,ldr-rgba-01.png,24.5172,0.0188,0.0107,6.1416 +Small,12x12,ldr-rgba-02.png,20.1746,0.0316,0.0234,2.8015 +Small,12x12,ldr-xy-00.png,29.2247,0.0181,0.0066,9.9611 +Small,12x12,ldr-xy-01.png,30.5463,0.0172,0.0059,11.1894 +Small,12x12,ldr-xy-02.png,37.9988,0.0123,0.0012,53.0243 +Small,12x12,ldrs-rgba-00.png,21.6106,0.0277,0.0194,3.3703 +Small,12x12,ldrs-rgba-01.png,24.5187,0.0188,0.0107,6.1416 +Small,12x12,ldrs-rgba-02.png,20.1751,0.0318,0.0235,2.7832 +Small,3x3x3,ldr-l-00-3.dds,50.8347,0.0198,0.0117,22.4152 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0091,0.0048,14.2873 +Small,6x6x6,ldr-l-00-3.dds,32.5284,0.0679,0.0561,4.6718 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0293,0.0213,3.2405 diff --git a/Test/Images/Small/astc_reference-4.4-sse2_fastest_results.csv b/Test/Images/Small/astc_reference-4.4-sse2_fastest_results.csv new file mode 100644 index 0000000..0d86909 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse2_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3455,0.0973,0.0092,7.1289 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0022,0.0004,0.6053 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0022,0.0004,0.5913 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.5820 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0022,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0023,0.0004,0.5742 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0022,0.0004,0.5829 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5871 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0023,0.0004,0.5751 +Small,4x4,ldr-rgb-00.png,37.2470,0.0106,0.0058,11.3483 +Small,4x4,ldr-rgb-01.png,39.5439,0.0099,0.0052,12.5498 +Small,4x4,ldr-rgb-02.png,34.7920,0.0120,0.0074,8.8779 +Small,4x4,ldr-rgb-03.png,45.4866,0.0066,0.0023,28.5321 +Small,4x4,ldr-rgb-04.png,41.7158,0.0085,0.0039,16.6764 +Small,4x4,ldr-rgb-05.png,36.8705,0.0125,0.0079,8.3402 +Small,4x4,ldr-rgb-06.png,34.9665,0.0116,0.0068,9.5686 +Small,4x4,ldr-rgb-07.png,37.3645,0.0120,0.0073,8.9516 +Small,4x4,ldr-rgb-08.png,42.9454,0.0076,0.0032,20.6349 +Small,4x4,ldr-rgb-09.png,41.7396,0.0086,0.0040,16.3676 +Small,4x4,ldr-rgb-10.png,43.9436,0.0036,0.0011,14.2106 +Small,4x4,ldr-rgba-00.png,34.7343,0.0123,0.0074,8.8382 +Small,4x4,ldr-rgba-01.png,38.6694,0.0103,0.0055,11.9502 +Small,4x4,ldr-rgba-02.png,34.5634,0.0127,0.0078,8.4215 +Small,4x4,ldr-xy-00.png,37.5260,0.0106,0.0039,16.9166 +Small,4x4,ldr-xy-01.png,43.9781,0.0113,0.0046,14.3629 +Small,4x4,ldr-xy-02.png,48.2748,0.0100,0.0031,20.8130 +Small,4x4,ldrs-rgba-00.png,34.7385,0.0125,0.0076,8.6404 +Small,4x4,ldrs-rgba-01.png,38.6861,0.0106,0.0057,11.5543 +Small,4x4,ldrs-rgba-02.png,34.5669,0.0130,0.0080,8.2383 +Small,5x5,hdr-rgb-00.hdr,28.8745,0.0988,0.0099,6.5920 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5858 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.6084 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5779 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5952 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5817 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5702 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5767 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5767 +Small,5x5,ldr-rgb-00.png,33.7228,0.0112,0.0059,11.1210 +Small,5x5,ldr-rgb-01.png,36.0754,0.0099,0.0049,13.3391 +Small,5x5,ldr-rgb-02.png,30.9932,0.0129,0.0078,8.4280 +Small,5x5,ldr-rgb-03.png,42.3634,0.0068,0.0021,31.3716 +Small,5x5,ldr-rgb-04.png,37.0411,0.0095,0.0045,14.5963 +Small,5x5,ldr-rgb-05.png,32.9651,0.0139,0.0088,7.4600 +Small,5x5,ldr-rgb-06.png,31.0371,0.0127,0.0076,8.5848 +Small,5x5,ldr-rgb-07.png,34.4079,0.0123,0.0072,9.0719 +Small,5x5,ldr-rgb-08.png,39.5746,0.0077,0.0029,22.7491 +Small,5x5,ldr-rgb-09.png,37.0834,0.0093,0.0043,15.1665 +Small,5x5,ldr-rgb-10.png,39.9180,0.0040,0.0011,14.6033 +Small,5x5,ldr-rgba-00.png,31.1153,0.0132,0.0080,8.2250 +Small,5x5,ldr-rgba-01.png,35.0411,0.0109,0.0057,11.5933 +Small,5x5,ldr-rgba-02.png,31.0383,0.0138,0.0084,7.8288 +Small,5x5,ldr-xy-00.png,36.5692,0.0109,0.0035,18.5340 +Small,5x5,ldr-xy-01.png,39.2568,0.0114,0.0041,16.0513 +Small,5x5,ldr-xy-02.png,43.8559,0.0107,0.0033,20.0964 +Small,5x5,ldrs-rgba-00.png,31.1160,0.0134,0.0081,8.1330 +Small,5x5,ldrs-rgba-01.png,35.0497,0.0109,0.0058,11.3558 +Small,5x5,ldrs-rgba-02.png,31.0387,0.0138,0.0084,7.7686 +Small,6x6,hdr-rgb-00.hdr,26.7600,0.0981,0.0096,6.8359 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0026,0.0004,0.5804 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5858 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5982 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5887 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5942 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5900 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5871 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.6228 +Small,6x6,ldr-rgb-00.png,31.3436,0.0123,0.0070,9.3065 +Small,6x6,ldr-rgb-01.png,32.8352,0.0109,0.0059,11.0950 +Small,6x6,ldr-rgb-02.png,27.3910,0.0137,0.0088,7.4736 +Small,6x6,ldr-rgb-03.png,40.3557,0.0068,0.0021,30.9582 +Small,6x6,ldr-rgb-04.png,33.7632,0.0103,0.0052,12.4882 +Small,6x6,ldr-rgb-05.png,29.7440,0.0150,0.0101,6.5191 +Small,6x6,ldr-rgb-06.png,27.4701,0.0139,0.0088,7.4616 +Small,6x6,ldr-rgb-07.png,32.3394,0.0122,0.0072,9.0668 +Small,6x6,ldr-rgb-08.png,37.4420,0.0077,0.0029,22.2699 +Small,6x6,ldr-rgb-09.png,33.3139,0.0101,0.0051,12.9208 +Small,6x6,ldr-rgb-10.png,36.5787,0.0041,0.0013,12.4285 +Small,6x6,ldr-rgba-00.png,28.8478,0.0140,0.0088,7.4491 +Small,6x6,ldr-rgba-01.png,31.9937,0.0119,0.0066,9.9446 +Small,6x6,ldr-rgba-02.png,27.7812,0.0140,0.0088,7.4736 +Small,6x6,ldr-xy-00.png,35.6139,0.0108,0.0037,17.9506 +Small,6x6,ldr-xy-01.png,36.5248,0.0120,0.0048,13.6789 +Small,6x6,ldr-xy-02.png,41.7978,0.0102,0.0030,21.8887 +Small,6x6,ldrs-rgba-00.png,28.8438,0.0140,0.0088,7.4295 +Small,6x6,ldrs-rgba-01.png,31.9996,0.0118,0.0065,10.0211 +Small,6x6,ldrs-rgba-02.png,27.7798,0.0141,0.0088,7.4456 +Small,8x8,hdr-rgb-00.hdr,23.6156,0.1041,0.0143,4.5980 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5926 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5982 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5926 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5767 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5739 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5832 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5820 +Small,8x8,ldr-rgb-00.png,27.7154,0.0158,0.0098,6.6820 +Small,8x8,ldr-rgb-01.png,28.6823,0.0140,0.0082,7.9767 +Small,8x8,ldr-rgb-02.png,23.0282,0.0182,0.0123,5.3083 +Small,8x8,ldr-rgb-03.png,37.0615,0.0079,0.0024,27.3076 +Small,8x8,ldr-rgb-04.png,29.1235,0.0137,0.0079,8.3390 +Small,8x8,ldr-rgb-05.png,25.6005,0.0202,0.0143,4.5804 +Small,8x8,ldr-rgb-06.png,23.0809,0.0188,0.0129,5.0795 +Small,8x8,ldr-rgb-07.png,29.4687,0.0140,0.0082,8.0069 +Small,8x8,ldr-rgb-08.png,33.9575,0.0091,0.0035,18.7617 +Small,8x8,ldr-rgb-09.png,28.4481,0.0132,0.0074,8.8995 +Small,8x8,ldr-rgb-10.png,31.9049,0.0052,0.0015,10.7020 +Small,8x8,ldr-rgba-00.png,25.3472,0.0191,0.0130,5.0401 +Small,8x8,ldr-rgba-01.png,28.1822,0.0155,0.0094,6.9949 +Small,8x8,ldr-rgba-02.png,23.8729,0.0190,0.0127,5.1449 +Small,8x8,ldr-xy-00.png,33.2129,0.0136,0.0050,13.0286 +Small,8x8,ldr-xy-01.png,34.1355,0.0144,0.0059,11.1039 +Small,8x8,ldr-xy-02.png,39.7699,0.0107,0.0020,31.9700 +Small,8x8,ldrs-rgba-00.png,25.3477,0.0192,0.0131,4.9928 +Small,8x8,ldrs-rgba-01.png,28.1833,0.0155,0.0094,6.9890 +Small,8x8,ldrs-rgba-02.png,23.8723,0.0191,0.0128,5.1176 +Small,12x12,hdr-rgb-00.hdr,20.4504,0.1126,0.0206,3.1885 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0049,0.0004,0.5791 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0048,0.0004,0.5764 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0048,0.0004,0.5874 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0048,0.0004,0.5939 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0048,0.0004,0.5871 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5900 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5845 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0048,0.0005,0.5651 +Small,12x12,ldr-rgb-00.png,23.7157,0.0161,0.0086,7.5782 +Small,12x12,ldr-rgb-01.png,24.7251,0.0137,0.0064,10.2288 +Small,12x12,ldr-rgb-02.png,19.1954,0.0212,0.0138,4.7514 +Small,12x12,ldr-rgb-03.png,33.1615,0.0088,0.0018,36.6748 +Small,12x12,ldr-rgb-04.png,24.3846,0.0137,0.0063,10.4322 +Small,12x12,ldr-rgb-05.png,21.3862,0.0198,0.0125,5.2429 +Small,12x12,ldr-rgb-06.png,19.1691,0.0220,0.0145,4.5209 +Small,12x12,ldr-rgb-07.png,25.3196,0.0135,0.0060,10.8682 +Small,12x12,ldr-rgb-08.png,30.1240,0.0099,0.0028,23.4397 +Small,12x12,ldr-rgb-09.png,23.5957,0.0155,0.0081,8.0690 +Small,12x12,ldr-rgb-10.png,27.2837,0.0072,0.0021,7.9107 +Small,12x12,ldr-rgba-00.png,21.3587,0.0208,0.0132,4.9614 +Small,12x12,ldr-rgba-01.png,24.4758,0.0152,0.0077,8.5488 +Small,12x12,ldr-rgba-02.png,20.1402,0.0240,0.0163,4.0128 +Small,12x12,ldr-xy-00.png,28.8913,0.0158,0.0050,13.1836 +Small,12x12,ldr-xy-01.png,29.6644,0.0152,0.0044,14.8270 +Small,12x12,ldr-xy-02.png,37.9766,0.0118,0.0012,54.8440 +Small,12x12,ldrs-rgba-00.png,21.3601,0.0211,0.0134,4.8864 +Small,12x12,ldrs-rgba-01.png,24.4766,0.0154,0.0077,8.4857 +Small,12x12,ldrs-rgba-02.png,20.1395,0.0243,0.0166,3.9389 +Small,3x3x3,ldr-l-00-3.dds,50.6895,0.0187,0.0114,23.0129 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0082,0.0048,14.3948 +Small,6x6x6,ldr-l-00-3.dds,32.5118,0.0678,0.0558,4.7004 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0292,0.0212,3.2535 diff --git a/Test/Images/Small/astc_reference-4.4-sse2_medium_results.csv b/Test/Images/Small/astc_reference-4.4-sse2_medium_results.csv new file mode 100644 index 0000000..7d9078d --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse2_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1462,0.1123,0.0233,2.8114 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0035,0.0004,0.5817 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5791 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5884 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0005,0.5529 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5779 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0005,0.4867 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5829 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5434 +Small,4x4,ldr-rgb-00.png,38.8432,0.0319,0.0257,2.5506 +Small,4x4,ldr-rgb-01.png,40.2258,0.0277,0.0218,3.0071 +Small,4x4,ldr-rgb-02.png,35.2933,0.0282,0.0222,2.9545 +Small,4x4,ldr-rgb-03.png,47.2820,0.0186,0.0130,5.0564 +Small,4x4,ldr-rgb-04.png,42.2203,0.0230,0.0171,3.8327 +Small,4x4,ldr-rgb-05.png,37.8177,0.0306,0.0247,2.6581 +Small,4x4,ldr-rgb-06.png,35.4758,0.0252,0.0193,3.4033 +Small,4x4,ldr-rgb-07.png,39.2847,0.0376,0.0318,2.0593 +Small,4x4,ldr-rgb-08.png,45.1880,0.0217,0.0160,4.0970 +Small,4x4,ldr-rgb-09.png,42.1624,0.0235,0.0177,3.7022 +Small,4x4,ldr-rgb-10.png,44.9412,0.0065,0.0028,5.8266 +Small,4x4,ldr-rgba-00.png,36.2597,0.0356,0.0291,2.2521 +Small,4x4,ldr-rgba-01.png,38.9707,0.0224,0.0164,4.0078 +Small,4x4,ldr-rgba-02.png,34.9421,0.0246,0.0184,3.5612 +Small,4x4,ldr-xy-00.png,37.7304,0.0217,0.0143,4.5730 +Small,4x4,ldr-xy-01.png,45.3643,0.0293,0.0220,2.9823 +Small,4x4,ldr-xy-02.png,51.1886,0.0333,0.0258,2.5439 +Small,4x4,ldrs-rgba-00.png,36.2659,0.0356,0.0293,2.2348 +Small,4x4,ldrs-rgba-01.png,38.9909,0.0227,0.0166,3.9572 +Small,4x4,ldrs-rgba-02.png,34.9450,0.0249,0.0185,3.5450 +Small,5x5,hdr-rgb-00.hdr,29.9063,0.1161,0.0273,2.3976 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0044,0.0004,0.5791 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0045,0.0004,0.5795 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0004,0.5751 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0005,0.5613 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5613 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0004,0.5727 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0046,0.0005,0.5401 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5566 +Small,5x5,ldr-rgb-00.png,35.1487,0.0358,0.0286,2.2881 +Small,5x5,ldr-rgb-01.png,36.4456,0.0270,0.0201,3.2576 +Small,5x5,ldr-rgb-02.png,31.1355,0.0276,0.0205,3.1948 +Small,5x5,ldr-rgb-03.png,44.0259,0.0153,0.0086,7.6427 +Small,5x5,ldr-rgb-04.png,37.6738,0.0254,0.0185,3.5494 +Small,5x5,ldr-rgb-05.png,33.5459,0.0369,0.0298,2.1968 +Small,5x5,ldr-rgb-06.png,31.1791,0.0265,0.0195,3.3614 +Small,5x5,ldr-rgb-07.png,36.1557,0.0424,0.0354,1.8493 +Small,5x5,ldr-rgb-08.png,41.6368,0.0212,0.0146,4.4980 +Small,5x5,ldr-rgb-09.png,37.5922,0.0242,0.0172,3.8012 +Small,5x5,ldr-rgb-10.png,40.5794,0.0079,0.0032,5.0720 +Small,5x5,ldr-rgba-00.png,32.8173,0.0427,0.0352,1.8611 +Small,5x5,ldr-rgba-01.png,35.3162,0.0259,0.0187,3.4998 +Small,5x5,ldr-rgba-02.png,31.1464,0.0283,0.0211,3.1089 +Small,5x5,ldr-xy-00.png,37.0404,0.0234,0.0150,4.3834 +Small,5x5,ldr-xy-01.png,40.7159,0.0300,0.0214,3.0600 +Small,5x5,ldr-xy-02.png,49.1543,0.0248,0.0161,4.0731 +Small,5x5,ldrs-rgba-00.png,32.8214,0.0427,0.0354,1.8499 +Small,5x5,ldrs-rgba-01.png,35.3251,0.0260,0.0188,3.4813 +Small,5x5,ldrs-rgba-02.png,31.1476,0.0282,0.0210,3.1234 +Small,6x6,hdr-rgb-00.hdr,27.5227,0.1186,0.0288,2.2779 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0043,0.0005,0.5269 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0004,0.5887 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0043,0.0005,0.5518 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0043,0.0004,0.5690 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0043,0.0004,0.5858 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0043,0.0004,0.5791 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0004,0.5739 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0043,0.0005,0.5628 +Small,6x6,ldr-rgb-00.png,32.4046,0.0373,0.0305,2.1479 +Small,6x6,ldr-rgb-01.png,33.0877,0.0276,0.0209,3.1363 +Small,6x6,ldr-rgb-02.png,27.5101,0.0284,0.0217,3.0264 +Small,6x6,ldr-rgb-03.png,41.7485,0.0130,0.0066,9.8923 +Small,6x6,ldr-rgb-04.png,34.2066,0.0244,0.0177,3.7037 +Small,6x6,ldr-rgb-05.png,30.1436,0.0384,0.0316,2.0764 +Small,6x6,ldr-rgb-06.png,27.5774,0.0278,0.0210,3.1203 +Small,6x6,ldr-rgb-07.png,33.8833,0.0414,0.0347,1.8904 +Small,6x6,ldr-rgb-08.png,39.2140,0.0177,0.0112,5.8260 +Small,6x6,ldr-rgb-09.png,33.6689,0.0239,0.0172,3.8196 +Small,6x6,ldr-rgb-10.png,36.9896,0.0079,0.0034,4.8439 +Small,6x6,ldr-rgba-00.png,30.2544,0.0460,0.0391,1.6762 +Small,6x6,ldr-rgba-01.png,32.2005,0.0270,0.0200,3.2830 +Small,6x6,ldr-rgba-02.png,27.8556,0.0307,0.0236,2.7785 +Small,6x6,ldr-xy-00.png,36.1662,0.0215,0.0132,4.9690 +Small,6x6,ldr-xy-01.png,38.0135,0.0249,0.0166,3.9503 +Small,6x6,ldr-xy-02.png,46.1312,0.0205,0.0121,5.4197 +Small,6x6,ldrs-rgba-00.png,30.2495,0.0467,0.0397,1.6519 +Small,6x6,ldrs-rgba-01.png,32.2065,0.0271,0.0201,3.2680 +Small,6x6,ldrs-rgba-02.png,27.8520,0.0308,0.0237,2.7678 +Small,8x8,hdr-rgb-00.hdr,24.1390,0.1283,0.0372,1.7596 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0052,0.0006,0.4070 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0049,0.0005,0.5566 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0049,0.0004,0.5952 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5926 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0004,0.5995 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5807 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5871 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0004,0.5690 +Small,8x8,ldr-rgb-00.png,28.7594,0.0490,0.0415,1.5784 +Small,8x8,ldr-rgb-01.png,28.9369,0.0339,0.0265,2.4749 +Small,8x8,ldr-rgb-02.png,23.1670,0.0362,0.0287,2.2843 +Small,8x8,ldr-rgb-03.png,38.5914,0.0152,0.0081,8.1371 +Small,8x8,ldr-rgb-04.png,29.6483,0.0337,0.0264,2.4865 +Small,8x8,ldr-rgb-05.png,25.9418,0.0472,0.0396,1.6545 +Small,8x8,ldr-rgb-06.png,23.2010,0.0369,0.0293,2.2354 +Small,8x8,ldr-rgb-07.png,30.7551,0.0491,0.0416,1.5761 +Small,8x8,ldr-rgb-08.png,35.9297,0.0214,0.0142,4.6217 +Small,8x8,ldr-rgb-09.png,28.9847,0.0308,0.0234,2.8036 +Small,8x8,ldr-rgb-10.png,32.1811,0.0097,0.0045,3.5854 +Small,8x8,ldr-rgba-00.png,26.4734,0.0573,0.0497,1.3187 +Small,8x8,ldr-rgba-01.png,28.3748,0.0341,0.0264,2.4778 +Small,8x8,ldr-rgba-02.png,23.9432,0.0388,0.0311,2.1099 +Small,8x8,ldr-xy-00.png,33.9578,0.0290,0.0187,3.5059 +Small,8x8,ldr-xy-01.png,34.9740,0.0291,0.0190,3.4582 +Small,8x8,ldr-xy-02.png,41.6833,0.0228,0.0125,5.2304 +Small,8x8,ldrs-rgba-00.png,26.4748,0.0573,0.0497,1.3181 +Small,8x8,ldrs-rgba-01.png,28.3782,0.0342,0.0265,2.4761 +Small,8x8,ldrs-rgba-02.png,23.9434,0.0394,0.0315,2.0772 +Small,12x12,hdr-rgb-00.hdr,20.7679,0.1472,0.0532,1.2314 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0080,0.0006,0.4498 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0078,0.0004,0.5779 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0078,0.0004,0.5779 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0078,0.0004,0.5742 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0078,0.0004,0.5751 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0079,0.0005,0.5678 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0078,0.0005,0.5663 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0078,0.0004,0.5702 +Small,12x12,ldr-rgb-00.png,24.6928,0.0590,0.0481,1.3622 +Small,12x12,ldr-rgb-01.png,25.0361,0.0439,0.0336,1.9530 +Small,12x12,ldr-rgb-02.png,19.2723,0.0513,0.0408,1.6045 +Small,12x12,ldr-rgb-03.png,34.9910,0.0188,0.0087,7.5634 +Small,12x12,ldr-rgb-04.png,24.8973,0.0417,0.0313,2.0948 +Small,12x12,ldr-rgb-05.png,21.6527,0.0590,0.0486,1.3474 +Small,12x12,ldr-rgb-06.png,19.2558,0.0523,0.0418,1.5689 +Small,12x12,ldr-rgb-07.png,26.7423,0.0541,0.0437,1.5007 +Small,12x12,ldr-rgb-08.png,31.6843,0.0246,0.0144,4.5517 +Small,12x12,ldr-rgb-09.png,24.1545,0.0404,0.0301,2.1784 +Small,12x12,ldr-rgb-10.png,28.0447,0.0173,0.0093,1.7519 +Small,12x12,ldr-rgba-00.png,22.2585,0.0649,0.0543,1.2071 +Small,12x12,ldr-rgba-01.png,24.6414,0.0425,0.0317,2.0656 +Small,12x12,ldr-rgba-02.png,20.1882,0.0553,0.0446,1.4684 +Small,12x12,ldr-xy-00.png,30.2558,0.0355,0.0213,3.0718 +Small,12x12,ldr-xy-01.png,31.8636,0.0373,0.0231,2.8379 +Small,12x12,ldr-xy-02.png,38.5089,0.0187,0.0047,13.8848 +Small,12x12,ldrs-rgba-00.png,22.2585,0.0656,0.0549,1.1931 +Small,12x12,ldrs-rgba-01.png,24.6434,0.0428,0.0321,2.0430 +Small,12x12,ldrs-rgba-02.png,20.1890,0.0551,0.0445,1.4743 +Small,3x3x3,ldr-l-00-3.dds,51.8899,0.0255,0.0164,15.9523 +Small,3x3x3,ldr-l-01-3.dds,54.6239,0.0103,0.0052,13.3442 +Small,6x6x6,ldr-l-00-3.dds,32.9631,0.0807,0.0668,3.9266 +Small,6x6x6,ldr-l-01-3.dds,41.0369,0.0318,0.0214,3.2175 diff --git a/Test/Images/Small/astc_reference-4.4-sse2_thorough_results.csv b/Test/Images/Small/astc_reference-4.4-sse2_thorough_results.csv new file mode 100644 index 0000000..e6ff8e6 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse2_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.4205,0.1351,0.0461,1.4213 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.5089 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5120 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0005,0.5140 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5345 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0005,0.5529 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0005,0.5235 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5289 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0005,0.5601 +Small,4x4,ldr-rgb-00.png,39.1635,0.0594,0.0533,1.2288 +Small,4x4,ldr-rgb-01.png,40.4120,0.0564,0.0504,1.2996 +Small,4x4,ldr-rgb-02.png,35.4711,0.0528,0.0468,1.4015 +Small,4x4,ldr-rgb-03.png,47.7527,0.0534,0.0478,1.3703 +Small,4x4,ldr-rgb-04.png,42.3660,0.0479,0.0420,1.5616 +Small,4x4,ldr-rgb-05.png,37.9925,0.0577,0.0516,1.2700 +Small,4x4,ldr-rgb-06.png,35.6403,0.0470,0.0409,1.6030 +Small,4x4,ldr-rgb-07.png,39.8791,0.0701,0.0642,1.0203 +Small,4x4,ldr-rgb-08.png,45.8775,0.0523,0.0466,1.4078 +Small,4x4,ldr-rgb-09.png,42.2993,0.0515,0.0456,1.4387 +Small,4x4,ldr-rgb-10.png,45.1694,0.0096,0.0059,2.7454 +Small,4x4,ldr-rgba-00.png,36.7416,0.0626,0.0564,1.1619 +Small,4x4,ldr-rgba-01.png,39.1154,0.0445,0.0384,1.7065 +Small,4x4,ldr-rgba-02.png,35.0328,0.0449,0.0386,1.6991 +Small,4x4,ldr-xy-00.png,37.7724,0.0543,0.0468,1.4007 +Small,4x4,ldr-xy-01.png,45.4608,0.0602,0.0529,1.2398 +Small,4x4,ldr-xy-02.png,51.1938,0.0787,0.0710,0.9226 +Small,4x4,ldrs-rgba-00.png,36.7495,0.0628,0.0567,1.1560 +Small,4x4,ldrs-rgba-01.png,39.1372,0.0450,0.0388,1.6899 +Small,4x4,ldrs-rgba-02.png,35.0344,0.0448,0.0386,1.6965 +Small,5x5,hdr-rgb-00.hdr,30.3005,0.1429,0.0528,1.2419 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0048,0.0006,0.4485 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0050,0.0005,0.4670 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0046,0.0005,0.5601 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0046,0.0005,0.5651 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5518 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0005,0.5601 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0005,0.5663 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5639 +Small,5x5,ldr-rgb-00.png,35.3880,0.0708,0.0636,1.0309 +Small,5x5,ldr-rgb-01.png,36.5413,0.0618,0.0548,1.1956 +Small,5x5,ldr-rgb-02.png,31.1967,0.0540,0.0469,1.3974 +Small,5x5,ldr-rgb-03.png,44.5932,0.0619,0.0549,1.1927 +Small,5x5,ldr-rgb-04.png,37.8267,0.0559,0.0490,1.3377 +Small,5x5,ldr-rgb-05.png,33.6963,0.0699,0.0629,1.0422 +Small,5x5,ldr-rgb-06.png,31.2331,0.0505,0.0434,1.5087 +Small,5x5,ldr-rgb-07.png,36.7232,0.0865,0.0795,0.8242 +Small,5x5,ldr-rgb-08.png,42.3949,0.0605,0.0537,1.2198 +Small,5x5,ldr-rgb-09.png,37.7126,0.0616,0.0547,1.1992 +Small,5x5,ldr-rgb-10.png,40.7580,0.0119,0.0072,2.2628 +Small,5x5,ldr-rgba-00.png,33.1240,0.0772,0.0699,0.9373 +Small,5x5,ldr-rgba-01.png,35.4134,0.0531,0.0459,1.4283 +Small,5x5,ldr-rgba-02.png,31.1844,0.0516,0.0443,1.4791 +Small,5x5,ldr-xy-00.png,37.1442,0.0638,0.0552,1.1880 +Small,5x5,ldr-xy-01.png,41.4542,0.0756,0.0671,0.9772 +Small,5x5,ldr-xy-02.png,49.3313,0.0904,0.0816,0.8034 +Small,5x5,ldrs-rgba-00.png,33.1272,0.0775,0.0702,0.9330 +Small,5x5,ldrs-rgba-01.png,35.4217,0.0534,0.0462,1.4200 +Small,5x5,ldrs-rgba-02.png,31.1853,0.0514,0.0441,1.4870 +Small,6x6,hdr-rgb-00.hdr,27.7238,0.1476,0.0567,1.1561 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0005,0.4856 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0004,0.5791 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0004,0.5702 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0044,0.0005,0.5566 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5235 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5313 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0005,0.5079 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0004,0.5832 +Small,6x6,ldr-rgb-00.png,32.6509,0.0800,0.0727,0.9017 +Small,6x6,ldr-rgb-01.png,33.1881,0.0666,0.0596,1.0995 +Small,6x6,ldr-rgb-02.png,27.5552,0.0578,0.0510,1.2843 +Small,6x6,ldr-rgb-03.png,42.5885,0.0536,0.0471,1.3916 +Small,6x6,ldr-rgb-04.png,34.3416,0.0592,0.0523,1.2528 +Small,6x6,ldr-rgb-05.png,30.2875,0.0745,0.0677,0.9685 +Small,6x6,ldr-rgb-06.png,27.6306,0.0557,0.0488,1.3419 +Small,6x6,ldr-rgb-07.png,34.4380,0.0930,0.0861,0.7609 +Small,6x6,ldr-rgb-08.png,40.0373,0.0538,0.0472,1.3881 +Small,6x6,ldr-rgb-09.png,33.8118,0.0624,0.0556,1.1790 +Small,6x6,ldr-rgb-10.png,37.1861,0.0133,0.0088,1.8521 +Small,6x6,ldr-rgba-00.png,30.5164,0.0855,0.0785,0.8345 +Small,6x6,ldr-rgba-01.png,32.2794,0.0600,0.0529,1.2383 +Small,6x6,ldr-rgba-02.png,27.8936,0.0564,0.0492,1.3323 +Small,6x6,ldr-xy-00.png,36.2540,0.0547,0.0463,1.4155 +Small,6x6,ldr-xy-01.png,38.0244,0.0762,0.0679,0.9654 +Small,6x6,ldr-xy-02.png,47.5902,0.0946,0.0861,0.7611 +Small,6x6,ldrs-rgba-00.png,30.5127,0.0856,0.0784,0.8354 +Small,6x6,ldrs-rgba-01.png,32.2857,0.0602,0.0531,1.2335 +Small,6x6,ldrs-rgba-02.png,27.8909,0.0564,0.0494,1.3276 +Small,8x8,hdr-rgb-00.hdr,24.3460,0.1700,0.0770,0.8514 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0062,0.0006,0.4324 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0063,0.0005,0.5628 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0063,0.0005,0.5543 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0062,0.0004,0.5727 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0062,0.0005,0.5678 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0062,0.0004,0.5791 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0063,0.0005,0.5215 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0063,0.0005,0.5481 +Small,8x8,ldr-rgb-00.png,28.9780,0.1010,0.0920,0.7123 +Small,8x8,ldr-rgb-01.png,29.0210,0.0837,0.0749,0.8745 +Small,8x8,ldr-rgb-02.png,23.2052,0.0762,0.0673,0.9745 +Small,8x8,ldr-rgb-03.png,39.4314,0.0388,0.0302,2.1689 +Small,8x8,ldr-rgb-04.png,29.7779,0.0752,0.0664,0.9864 +Small,8x8,ldr-rgb-05.png,26.0426,0.0917,0.0829,0.7905 +Small,8x8,ldr-rgb-06.png,23.2530,0.0754,0.0663,0.9891 +Small,8x8,ldr-rgb-07.png,31.2138,0.1125,0.1038,0.6316 +Small,8x8,ldr-rgb-08.png,36.5612,0.0565,0.0480,1.3658 +Small,8x8,ldr-rgb-09.png,29.1484,0.0656,0.0567,1.1563 +Small,8x8,ldr-rgb-10.png,32.3330,0.0181,0.0115,1.4096 +Small,8x8,ldr-rgba-00.png,26.7531,0.1111,0.1020,0.6426 +Small,8x8,ldr-rgba-01.png,28.4341,0.0810,0.0718,0.9134 +Small,8x8,ldr-rgba-02.png,23.9687,0.0739,0.0648,1.0115 +Small,8x8,ldr-xy-00.png,34.2380,0.0661,0.0555,1.1811 +Small,8x8,ldr-xy-01.png,35.3165,0.0676,0.0573,1.1444 +Small,8x8,ldr-xy-02.png,44.6234,0.0858,0.0754,0.8691 +Small,8x8,ldrs-rgba-00.png,26.7540,0.1111,0.1021,0.6417 +Small,8x8,ldrs-rgba-01.png,28.4376,0.0811,0.0721,0.9090 +Small,8x8,ldrs-rgba-02.png,23.9689,0.0736,0.0643,1.0191 +Small,12x12,hdr-rgb-00.hdr,21.0311,0.2083,0.1125,0.5827 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0101,0.0005,0.5532 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0102,0.0005,0.5613 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0102,0.0004,0.5727 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0102,0.0004,0.5767 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0102,0.0005,0.5377 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0102,0.0004,0.5714 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0102,0.0005,0.5289 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0101,0.0004,0.5767 +Small,12x12,ldr-rgb-00.png,25.0530,0.1308,0.1176,0.5571 +Small,12x12,ldr-rgb-01.png,25.1392,0.1073,0.0945,0.6934 +Small,12x12,ldr-rgb-02.png,19.2921,0.1186,0.1057,0.6201 +Small,12x12,ldr-rgb-03.png,36.1864,0.0432,0.0306,2.1388 +Small,12x12,ldr-rgb-04.png,24.9919,0.0969,0.0838,0.7819 +Small,12x12,ldr-rgb-05.png,21.7388,0.1182,0.1052,0.6227 +Small,12x12,ldr-rgb-06.png,19.2959,0.1157,0.1028,0.6377 +Small,12x12,ldr-rgb-07.png,27.1136,0.1355,0.1226,0.5344 +Small,12x12,ldr-rgb-08.png,32.5295,0.0555,0.0430,1.5246 +Small,12x12,ldr-rgb-09.png,24.3026,0.0900,0.0772,0.8484 +Small,12x12,ldr-rgb-10.png,28.1806,0.0302,0.0196,0.8278 +Small,12x12,ldr-rgba-00.png,22.7565,0.1387,0.1256,0.5219 +Small,12x12,ldr-rgba-01.png,24.7322,0.1105,0.0974,0.6725 +Small,12x12,ldr-rgba-02.png,20.2051,0.1150,0.1017,0.6441 +Small,12x12,ldr-xy-00.png,30.5347,0.0871,0.0725,0.9036 +Small,12x12,ldr-xy-01.png,32.2811,0.0689,0.0545,1.2031 +Small,12x12,ldr-xy-02.png,40.3051,0.0487,0.0343,1.9082 +Small,12x12,ldrs-rgba-00.png,22.7551,0.1388,0.1257,0.5214 +Small,12x12,ldrs-rgba-01.png,24.7337,0.1111,0.0981,0.6683 +Small,12x12,ldrs-rgba-02.png,20.2055,0.1148,0.1014,0.6461 +Small,3x3x3,ldr-l-00-3.dds,52.3291,0.0436,0.0346,7.5775 +Small,3x3x3,ldr-l-01-3.dds,55.2576,0.0187,0.0135,5.0924 +Small,6x6x6,ldr-l-00-3.dds,33.2763,0.1113,0.0945,2.7728 +Small,6x6x6,ldr-l-01-3.dds,41.7183,0.0349,0.0221,3.1240 diff --git a/Test/Images/Small/astc_reference-4.4-sse4.1_fast_results.csv b/Test/Images/Small/astc_reference-4.4-sse4.1_fast_results.csv new file mode 100644 index 0000000..158e8c8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse4.1_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7281,0.0989,0.0131,5.0065 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0030,0.0005,0.5412 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0030,0.0005,0.5426 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0029,0.0005,0.5470 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0029,0.0005,0.5552 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0029,0.0005,0.5504 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0029,0.0005,0.5390 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0030,0.0005,0.5300 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0029,0.0005,0.5310 +Small,4x4,ldr-rgb-00.png,38.2512,0.0140,0.0086,7.6446 +Small,4x4,ldr-rgb-01.png,39.9266,0.0125,0.0073,9.0222 +Small,4x4,ldr-rgb-02.png,35.1621,0.0169,0.0115,5.7033 +Small,4x4,ldr-rgb-03.png,46.0782,0.0078,0.0027,23.8651 +Small,4x4,ldr-rgb-04.png,41.9798,0.0102,0.0050,13.1703 +Small,4x4,ldr-rgb-05.png,37.3372,0.0168,0.0116,5.6702 +Small,4x4,ldr-rgb-06.png,35.3603,0.0157,0.0104,6.2756 +Small,4x4,ldr-rgb-07.png,38.1442,0.0172,0.0120,5.4464 +Small,4x4,ldr-rgb-08.png,43.8361,0.0096,0.0048,13.6789 +Small,4x4,ldr-rgb-09.png,41.9339,0.0103,0.0052,12.6859 +Small,4x4,ldr-rgb-10.png,44.4590,0.0044,0.0013,12.1951 +Small,4x4,ldr-rgba-00.png,35.6010,0.0168,0.0115,5.6780 +Small,4x4,ldr-rgba-01.png,38.8640,0.0120,0.0068,9.6959 +Small,4x4,ldr-rgba-02.png,34.8755,0.0151,0.0097,6.7597 +Small,4x4,ldr-xy-00.png,37.5551,0.0123,0.0048,13.7797 +Small,4x4,ldr-xy-01.png,44.3046,0.0128,0.0056,11.7109 +Small,4x4,ldr-xy-02.png,48.2608,0.0109,0.0036,18.3057 +Small,4x4,ldrs-rgba-00.png,35.6065,0.0169,0.0115,5.6795 +Small,4x4,ldrs-rgba-01.png,38.8848,0.0123,0.0069,9.5146 +Small,4x4,ldrs-rgba-02.png,34.8762,0.0155,0.0099,6.6298 +Small,5x5,hdr-rgb-00.hdr,29.5480,0.1016,0.0138,4.7456 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0036,0.0005,0.5470 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0037,0.0005,0.5108 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0037,0.0005,0.5205 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0036,0.0005,0.5279 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0037,0.0006,0.4604 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0005,0.5225 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5323 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0037,0.0005,0.5377 +Small,5x5,ldr-rgb-00.png,34.4321,0.0145,0.0084,7.7770 +Small,5x5,ldr-rgb-01.png,36.2469,0.0117,0.0057,11.4195 +Small,5x5,ldr-rgb-02.png,31.0931,0.0151,0.0092,7.1477 +Small,5x5,ldr-rgb-03.png,42.7531,0.0077,0.0023,28.4082 +Small,5x5,ldr-rgb-04.png,37.2747,0.0109,0.0048,13.7110 +Small,5x5,ldr-rgb-05.png,33.2744,0.0178,0.0118,5.5371 +Small,5x5,ldr-rgb-06.png,31.1326,0.0150,0.0089,7.3314 +Small,5x5,ldr-rgb-07.png,35.0664,0.0153,0.0095,6.8804 +Small,5x5,ldr-rgb-08.png,40.1866,0.0091,0.0036,18.4099 +Small,5x5,ldr-rgb-09.png,37.3026,0.0111,0.0050,13.0132 +Small,5x5,ldr-rgb-10.png,40.1964,0.0049,0.0013,12.8308 +Small,5x5,ldr-rgba-00.png,32.1470,0.0188,0.0128,5.1048 +Small,5x5,ldr-rgba-01.png,35.1987,0.0128,0.0067,9.8034 +Small,5x5,ldr-rgba-02.png,31.1340,0.0159,0.0097,6.7632 +Small,5x5,ldr-xy-00.png,36.7495,0.0121,0.0038,17.0668 +Small,5x5,ldr-xy-01.png,39.8321,0.0130,0.0048,13.7274 +Small,5x5,ldr-xy-02.png,43.9343,0.0118,0.0034,19.0398 +Small,5x5,ldrs-rgba-00.png,32.1514,0.0187,0.0124,5.2946 +Small,5x5,ldrs-rgba-01.png,35.2069,0.0127,0.0066,9.8909 +Small,5x5,ldrs-rgba-02.png,31.1349,0.0157,0.0094,6.9586 +Small,6x6,hdr-rgb-00.hdr,27.0790,0.1006,0.0139,4.6997 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5470 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5518 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5651 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0005,0.5310 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0005,0.5423 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0005,0.5518 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5804 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5235 +Small,6x6,ldr-rgb-00.png,31.7144,0.0166,0.0106,6.1979 +Small,6x6,ldr-rgb-01.png,32.9244,0.0126,0.0070,9.3892 +Small,6x6,ldr-rgb-02.png,27.4795,0.0161,0.0103,6.3682 +Small,6x6,ldr-rgb-03.png,40.5991,0.0078,0.0024,27.2264 +Small,6x6,ldr-rgb-04.png,33.9357,0.0116,0.0059,11.0945 +Small,6x6,ldr-rgb-05.png,29.9800,0.0204,0.0146,4.4937 +Small,6x6,ldr-rgb-06.png,27.5476,0.0160,0.0103,6.3925 +Small,6x6,ldr-rgb-07.png,32.9378,0.0153,0.0096,6.7984 +Small,6x6,ldr-rgb-08.png,37.8129,0.0091,0.0037,17.5944 +Small,6x6,ldr-rgb-09.png,33.4946,0.0123,0.0064,10.2498 +Small,6x6,ldr-rgb-10.png,36.6909,0.0051,0.0015,10.9040 +Small,6x6,ldr-rgba-00.png,29.6086,0.0202,0.0142,4.6133 +Small,6x6,ldr-rgba-01.png,32.0847,0.0136,0.0077,8.5123 +Small,6x6,ldr-rgba-02.png,27.8414,0.0170,0.0109,6.0054 +Small,6x6,ldr-xy-00.png,35.9075,0.0124,0.0042,15.5818 +Small,6x6,ldr-xy-01.png,37.1654,0.0144,0.0060,10.9408 +Small,6x6,ldr-xy-02.png,41.9299,0.0112,0.0033,20.0905 +Small,6x6,ldrs-rgba-00.png,29.6031,0.0205,0.0146,4.5008 +Small,6x6,ldrs-rgba-01.png,32.0904,0.0136,0.0077,8.4978 +Small,6x6,ldrs-rgba-02.png,27.8386,0.0170,0.0109,5.9877 +Small,8x8,hdr-rgb-00.hdr,23.7844,0.1050,0.0176,3.7198 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0038,0.0005,0.5051 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0037,0.0005,0.5300 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0037,0.0005,0.5366 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0037,0.0005,0.5529 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0037,0.0005,0.5613 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0004,0.5832 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5613 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0037,0.0005,0.5470 +Small,8x8,ldr-rgb-00.png,28.0659,0.0185,0.0124,5.2920 +Small,8x8,ldr-rgb-01.png,28.7734,0.0157,0.0097,6.7639 +Small,8x8,ldr-rgb-02.png,23.1042,0.0204,0.0143,4.5740 +Small,8x8,ldr-rgb-03.png,37.3496,0.0083,0.0027,24.4184 +Small,8x8,ldr-rgb-04.png,29.3469,0.0148,0.0088,7.4778 +Small,8x8,ldr-rgb-05.png,25.8034,0.0235,0.0174,3.7560 +Small,8x8,ldr-rgb-06.png,23.1655,0.0207,0.0148,4.4138 +Small,8x8,ldr-rgb-07.png,29.8427,0.0157,0.0098,6.7170 +Small,8x8,ldr-rgb-08.png,34.4844,0.0098,0.0042,15.7163 +Small,8x8,ldr-rgb-09.png,28.6410,0.0140,0.0082,8.0371 +Small,8x8,ldr-rgb-10.png,31.9947,0.0057,0.0019,8.7358 +Small,8x8,ldr-rgba-00.png,25.7010,0.0245,0.0179,3.6621 +Small,8x8,ldr-rgba-01.png,28.2814,0.0172,0.0111,5.9270 +Small,8x8,ldr-rgba-02.png,23.9350,0.0220,0.0158,4.1515 +Small,8x8,ldr-xy-00.png,33.3347,0.0148,0.0059,11.0833 +Small,8x8,ldr-xy-01.png,34.3877,0.0159,0.0068,9.5713 +Small,8x8,ldr-xy-02.png,39.8793,0.0110,0.0023,28.8707 +Small,8x8,ldrs-rgba-00.png,25.7001,0.0229,0.0167,3.9168 +Small,8x8,ldrs-rgba-01.png,28.2840,0.0173,0.0111,5.8882 +Small,8x8,ldrs-rgba-02.png,23.9352,0.0223,0.0159,4.1106 +Small,12x12,hdr-rgb-00.hdr,20.5374,0.1165,0.0269,2.4393 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0055,0.0005,0.5495 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0056,0.0005,0.5518 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0055,0.0005,0.5625 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0056,0.0005,0.5578 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0056,0.0005,0.5456 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0056,0.0005,0.5518 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0057,0.0005,0.4953 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0057,0.0005,0.5345 +Small,12x12,ldr-rgb-00.png,23.7930,0.0190,0.0109,6.0263 +Small,12x12,ldr-rgb-01.png,24.7698,0.0161,0.0082,7.9865 +Small,12x12,ldr-rgb-02.png,19.2293,0.0259,0.0179,3.6555 +Small,12x12,ldr-rgb-03.png,33.2561,0.0096,0.0020,32.3158 +Small,12x12,ldr-rgb-04.png,24.5727,0.0155,0.0075,8.6860 +Small,12x12,ldr-rgb-05.png,21.4915,0.0243,0.0161,4.0741 +Small,12x12,ldr-rgb-06.png,19.2266,0.0265,0.0186,3.5242 +Small,12x12,ldr-rgb-07.png,25.3769,0.0151,0.0074,8.8802 +Small,12x12,ldr-rgb-08.png,30.2961,0.0112,0.0035,18.5980 +Small,12x12,ldr-rgb-09.png,23.7353,0.0175,0.0096,6.8061 +Small,12x12,ldr-rgb-10.png,27.3243,0.0081,0.0024,6.6734 +Small,12x12,ldr-rgba-00.png,21.6059,0.0252,0.0171,3.8271 +Small,12x12,ldr-rgba-01.png,24.5172,0.0177,0.0095,6.8876 +Small,12x12,ldr-rgba-02.png,20.1746,0.0287,0.0206,3.1880 +Small,12x12,ldr-xy-00.png,29.2247,0.0172,0.0059,11.1098 +Small,12x12,ldr-xy-01.png,30.5463,0.0163,0.0053,12.3657 +Small,12x12,ldr-xy-02.png,37.9988,0.0123,0.0011,58.3605 +Small,12x12,ldrs-rgba-00.png,21.6106,0.0252,0.0173,3.7773 +Small,12x12,ldrs-rgba-01.png,24.5187,0.0176,0.0094,6.9565 +Small,12x12,ldrs-rgba-02.png,20.1751,0.0288,0.0207,3.1712 +Small,3x3x3,ldr-l-00-3.dds,50.8347,0.0168,0.0088,29.7181 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0080,0.0038,18.3203 +Small,6x6x6,ldr-l-00-3.dds,32.5284,0.0621,0.0506,5.1780 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0271,0.0193,3.5665 diff --git a/Test/Images/Small/astc_reference-4.4-sse4.1_fastest_results.csv b/Test/Images/Small/astc_reference-4.4-sse4.1_fastest_results.csv new file mode 100644 index 0000000..18c7329 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse4.1_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3455,0.0915,0.0080,8.2198 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0023,0.0005,0.5470 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0023,0.0005,0.5639 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0023,0.0005,0.5506 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0023,0.0005,0.5401 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0023,0.0005,0.5484 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0023,0.0005,0.5552 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5887 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0023,0.0005,0.5616 +Small,4x4,ldr-rgb-00.png,37.2470,0.0096,0.0050,13.2102 +Small,4x4,ldr-rgb-01.png,39.5439,0.0088,0.0044,14.7372 +Small,4x4,ldr-rgb-02.png,34.7920,0.0109,0.0063,10.4271 +Small,4x4,ldr-rgb-03.png,45.4866,0.0061,0.0020,32.6381 +Small,4x4,ldr-rgb-04.png,41.7158,0.0079,0.0034,19.4301 +Small,4x4,ldr-rgb-05.png,36.8705,0.0111,0.0066,9.9658 +Small,4x4,ldr-rgb-06.png,34.9665,0.0104,0.0058,11.2356 +Small,4x4,ldr-rgb-07.png,37.3645,0.0109,0.0064,10.3074 +Small,4x4,ldr-rgb-08.png,42.9454,0.0069,0.0027,24.0236 +Small,4x4,ldr-rgb-09.png,41.7396,0.0079,0.0034,19.3658 +Small,4x4,ldr-rgb-10.png,43.9436,0.0035,0.0010,15.4820 +Small,4x4,ldr-rgba-00.png,34.7343,0.0112,0.0065,10.0405 +Small,4x4,ldr-rgba-01.png,38.6694,0.0095,0.0048,13.7797 +Small,4x4,ldr-rgba-02.png,34.5634,0.0116,0.0068,9.6819 +Small,4x4,ldr-xy-00.png,37.5260,0.0100,0.0034,19.0122 +Small,4x4,ldr-xy-01.png,43.9781,0.0105,0.0039,16.8647 +Small,4x4,ldr-xy-02.png,48.2748,0.0095,0.0029,22.9218 +Small,4x4,ldrs-rgba-00.png,34.7385,0.0112,0.0065,10.1166 +Small,4x4,ldrs-rgba-01.png,38.6861,0.0097,0.0049,13.4237 +Small,4x4,ldrs-rgba-02.png,34.5669,0.0116,0.0068,9.6676 +Small,5x5,hdr-rgb-00.hdr,28.8745,0.0922,0.0083,7.9227 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0027,0.0005,0.5470 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0027,0.0005,0.5369 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5754 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5858 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5820 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5871 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5779 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0027,0.0004,0.5861 +Small,5x5,ldr-rgb-00.png,33.7228,0.0100,0.0050,13.0988 +Small,5x5,ldr-rgb-01.png,36.0754,0.0090,0.0041,15.8294 +Small,5x5,ldr-rgb-02.png,30.9932,0.0114,0.0065,10.0500 +Small,5x5,ldr-rgb-03.png,42.3634,0.0064,0.0018,36.1301 +Small,5x5,ldr-rgb-04.png,37.0411,0.0086,0.0037,17.6930 +Small,5x5,ldr-rgb-05.png,32.9651,0.0122,0.0073,8.9971 +Small,5x5,ldr-rgb-06.png,31.0371,0.0112,0.0063,10.4504 +Small,5x5,ldr-rgb-07.png,34.4079,0.0109,0.0061,10.7753 +Small,5x5,ldr-rgb-08.png,39.5746,0.0072,0.0025,25.8004 +Small,5x5,ldr-rgb-09.png,37.0834,0.0085,0.0037,17.8376 +Small,5x5,ldr-rgb-10.png,39.9180,0.0041,0.0012,14.1340 +Small,5x5,ldr-rgba-00.png,31.1153,0.0119,0.0069,9.5590 +Small,5x5,ldr-rgba-01.png,35.0411,0.0099,0.0048,13.6078 +Small,5x5,ldr-rgba-02.png,31.0383,0.0122,0.0069,9.4567 +Small,5x5,ldr-xy-00.png,36.5692,0.0104,0.0031,20.9511 +Small,5x5,ldr-xy-01.png,39.2568,0.0108,0.0036,18.3582 +Small,5x5,ldr-xy-02.png,43.8559,0.0101,0.0028,23.2494 +Small,5x5,ldrs-rgba-00.png,31.1160,0.0119,0.0067,9.7495 +Small,5x5,ldrs-rgba-01.png,35.0497,0.0100,0.0049,13.3995 +Small,5x5,ldrs-rgba-02.png,31.0387,0.0123,0.0071,9.2592 +Small,6x6,hdr-rgb-00.hdr,26.7600,0.0918,0.0080,8.1870 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0027,0.0005,0.5401 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.5845 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.5727 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5779 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5690 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5730 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.5842 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5858 +Small,6x6,ldr-rgb-00.png,31.3436,0.0108,0.0058,11.3619 +Small,6x6,ldr-rgb-01.png,32.8352,0.0098,0.0050,13.1729 +Small,6x6,ldr-rgb-02.png,27.3910,0.0121,0.0073,8.9654 +Small,6x6,ldr-rgb-03.png,40.3557,0.0063,0.0018,37.3425 +Small,6x6,ldr-rgb-04.png,33.7632,0.0092,0.0043,15.1423 +Small,6x6,ldr-rgb-05.png,29.7440,0.0132,0.0083,7.8626 +Small,6x6,ldr-rgb-06.png,27.4701,0.0123,0.0073,9.0035 +Small,6x6,ldr-rgb-07.png,32.3394,0.0109,0.0061,10.7454 +Small,6x6,ldr-rgb-08.png,37.4420,0.0072,0.0026,25.0915 +Small,6x6,ldr-rgb-09.png,33.3139,0.0092,0.0043,15.3769 +Small,6x6,ldr-rgb-10.png,36.5787,0.0040,0.0012,13.8358 +Small,6x6,ldr-rgba-00.png,28.8478,0.0123,0.0073,8.9467 +Small,6x6,ldr-rgba-01.png,31.9937,0.0105,0.0055,12.0139 +Small,6x6,ldr-rgba-02.png,27.7812,0.0126,0.0074,8.8465 +Small,6x6,ldr-xy-00.png,35.6139,0.0102,0.0031,21.2639 +Small,6x6,ldr-xy-01.png,36.5248,0.0111,0.0040,16.2304 +Small,6x6,ldr-xy-02.png,41.7978,0.0097,0.0026,24.7482 +Small,6x6,ldrs-rgba-00.png,28.8438,0.0123,0.0073,9.0059 +Small,6x6,ldrs-rgba-01.png,31.9996,0.0107,0.0055,11.9351 +Small,6x6,ldrs-rgba-02.png,27.7798,0.0126,0.0074,8.8133 +Small,8x8,hdr-rgb-00.hdr,23.6156,0.0968,0.0120,5.4650 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0034,0.0005,0.5687 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5764 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5791 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5845 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5779 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5791 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5804 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5702 +Small,8x8,ldr-rgb-00.png,27.7154,0.0142,0.0084,7.8177 +Small,8x8,ldr-rgb-01.png,28.6823,0.0126,0.0070,9.3397 +Small,8x8,ldr-rgb-02.png,23.0282,0.0160,0.0103,6.3454 +Small,8x8,ldr-rgb-03.png,37.0615,0.0075,0.0022,30.3833 +Small,8x8,ldr-rgb-04.png,29.1235,0.0123,0.0065,10.0298 +Small,8x8,ldr-rgb-05.png,25.6005,0.0177,0.0120,5.4637 +Small,8x8,ldr-rgb-06.png,23.0809,0.0165,0.0107,6.1123 +Small,8x8,ldr-rgb-07.png,29.4687,0.0125,0.0069,9.5104 +Small,8x8,ldr-rgb-08.png,33.9575,0.0086,0.0031,21.1950 +Small,8x8,ldr-rgb-09.png,28.4481,0.0118,0.0061,10.7223 +Small,8x8,ldr-rgb-10.png,31.9049,0.0051,0.0014,11.7455 +Small,8x8,ldr-rgba-00.png,25.3472,0.0169,0.0110,5.9584 +Small,8x8,ldr-rgba-01.png,28.1822,0.0138,0.0079,8.3030 +Small,8x8,ldr-rgba-02.png,23.8729,0.0168,0.0107,6.1038 +Small,8x8,ldr-xy-00.png,33.2129,0.0126,0.0043,15.3298 +Small,8x8,ldr-xy-01.png,34.1355,0.0133,0.0050,13.0708 +Small,8x8,ldr-xy-02.png,39.7699,0.0101,0.0019,35.2724 +Small,8x8,ldrs-rgba-00.png,25.3477,0.0169,0.0110,5.9524 +Small,8x8,ldrs-rgba-01.png,28.1833,0.0138,0.0079,8.3158 +Small,8x8,ldrs-rgba-02.png,23.8723,0.0167,0.0107,6.1204 +Small,12x12,hdr-rgb-00.hdr,20.4504,0.1050,0.0182,3.5995 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0050,0.0005,0.5625 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0049,0.0005,0.5601 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0050,0.0005,0.5470 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0005,0.5266 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0005,0.5555 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0005,0.5651 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0005,0.5540 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0005,0.5459 +Small,12x12,ldr-rgb-00.png,23.7157,0.0150,0.0077,8.4878 +Small,12x12,ldr-rgb-01.png,24.7251,0.0129,0.0057,11.5320 +Small,12x12,ldr-rgb-02.png,19.1954,0.0195,0.0122,5.3525 +Small,12x12,ldr-rgb-03.png,33.1615,0.0086,0.0016,40.1810 +Small,12x12,ldr-rgb-04.png,24.3846,0.0128,0.0056,11.7701 +Small,12x12,ldr-rgb-05.png,21.3862,0.0185,0.0112,5.8730 +Small,12x12,ldr-rgb-06.png,19.1691,0.0202,0.0129,5.0985 +Small,12x12,ldr-rgb-07.png,25.3196,0.0126,0.0054,12.0937 +Small,12x12,ldr-rgb-08.png,30.1240,0.0095,0.0025,26.3419 +Small,12x12,ldr-rgb-09.png,23.5957,0.0145,0.0073,8.9873 +Small,12x12,ldr-rgb-10.png,27.2837,0.0069,0.0018,9.0813 +Small,12x12,ldr-rgba-00.png,21.3587,0.0192,0.0118,5.5455 +Small,12x12,ldr-rgba-01.png,24.4758,0.0144,0.0069,9.4992 +Small,12x12,ldr-rgba-02.png,20.1402,0.0219,0.0144,4.5438 +Small,12x12,ldr-xy-00.png,28.8913,0.0152,0.0045,14.4955 +Small,12x12,ldr-xy-01.png,29.6644,0.0144,0.0040,16.4047 +Small,12x12,ldr-xy-02.png,37.9766,0.0115,0.0011,58.4101 +Small,12x12,ldrs-rgba-00.png,21.3601,0.0193,0.0119,5.4976 +Small,12x12,ldrs-rgba-01.png,24.4766,0.0143,0.0068,9.5967 +Small,12x12,ldrs-rgba-02.png,20.1395,0.0221,0.0146,4.4900 +Small,3x3x3,ldr-l-00-3.dds,50.6895,0.0158,0.0086,30.3758 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0071,0.0037,18.7080 +Small,6x6x6,ldr-l-00-3.dds,32.5118,0.0620,0.0504,5.1970 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0271,0.0193,3.5770 diff --git a/Test/Images/Small/astc_reference-4.4-sse4.1_medium_results.csv b/Test/Images/Small/astc_reference-4.4-sse4.1_medium_results.csv new file mode 100644 index 0000000..3706ef8 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse4.1_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1462,0.1047,0.0200,3.2693 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5651 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5492 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0036,0.0005,0.5331 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0037,0.0005,0.5651 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0005,0.5150 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0005,0.5355 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0005,0.5506 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0005,0.5345 +Small,4x4,ldr-rgb-00.png,38.8432,0.0295,0.0228,2.8697 +Small,4x4,ldr-rgb-01.png,40.2258,0.0248,0.0188,3.4832 +Small,4x4,ldr-rgb-02.png,35.2933,0.0248,0.0189,3.4622 +Small,4x4,ldr-rgb-03.png,47.2820,0.0166,0.0110,5.9384 +Small,4x4,ldr-rgb-04.png,42.2203,0.0203,0.0146,4.4866 +Small,4x4,ldr-rgb-05.png,37.8177,0.0267,0.0210,3.1240 +Small,4x4,ldr-rgb-06.png,35.4758,0.0226,0.0166,3.9525 +Small,4x4,ldr-rgb-07.png,39.2847,0.0328,0.0270,2.4233 +Small,4x4,ldr-rgb-08.png,45.1880,0.0192,0.0135,4.8374 +Small,4x4,ldr-rgb-09.png,42.1624,0.0208,0.0150,4.3664 +Small,4x4,ldr-rgb-10.png,44.9412,0.0061,0.0024,6.6351 +Small,4x4,ldr-rgba-00.png,36.2597,0.0307,0.0248,2.6449 +Small,4x4,ldr-rgba-01.png,38.9707,0.0200,0.0141,4.6483 +Small,4x4,ldr-rgba-02.png,34.9421,0.0218,0.0157,4.1621 +Small,4x4,ldr-xy-00.png,37.7304,0.0197,0.0123,5.3191 +Small,4x4,ldr-xy-01.png,45.3643,0.0261,0.0189,3.4710 +Small,4x4,ldr-xy-02.png,51.1886,0.0295,0.0221,2.9648 +Small,4x4,ldrs-rgba-00.png,36.2659,0.0309,0.0249,2.6344 +Small,4x4,ldrs-rgba-01.png,38.9909,0.0202,0.0143,4.5945 +Small,4x4,ldrs-rgba-02.png,34.9450,0.0219,0.0159,4.1298 +Small,5x5,hdr-rgb-00.hdr,29.9063,0.1075,0.0229,2.8670 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0045,0.0004,0.5714 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0045,0.0005,0.5529 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0005,0.5529 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0047,0.0005,0.5388 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0047,0.0004,0.5754 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0047,0.0005,0.5323 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0046,0.0005,0.5366 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0005,0.4971 +Small,5x5,ldr-rgb-00.png,35.1487,0.0303,0.0232,2.8267 +Small,5x5,ldr-rgb-01.png,36.4456,0.0234,0.0166,3.9580 +Small,5x5,ldr-rgb-02.png,31.1355,0.0236,0.0167,3.9168 +Small,5x5,ldr-rgb-03.png,44.0259,0.0139,0.0072,9.0809 +Small,5x5,ldr-rgb-04.png,37.6738,0.0220,0.0152,4.3153 +Small,5x5,ldr-rgb-05.png,33.5459,0.0315,0.0245,2.6712 +Small,5x5,ldr-rgb-06.png,31.1791,0.0232,0.0160,4.0850 +Small,5x5,ldr-rgb-07.png,36.1557,0.0357,0.0288,2.2789 +Small,5x5,ldr-rgb-08.png,41.6368,0.0184,0.0118,5.5352 +Small,5x5,ldr-rgb-09.png,37.5922,0.0210,0.0142,4.6188 +Small,5x5,ldr-rgb-10.png,40.5794,0.0074,0.0026,6.1693 +Small,5x5,ldr-rgba-00.png,32.8173,0.0357,0.0287,2.2833 +Small,5x5,ldr-rgba-01.png,35.3162,0.0226,0.0155,4.2173 +Small,5x5,ldr-rgba-02.png,31.1464,0.0245,0.0174,3.7580 +Small,5x5,ldr-xy-00.png,37.0404,0.0208,0.0123,5.3151 +Small,5x5,ldr-xy-01.png,40.7159,0.0262,0.0179,3.6620 +Small,5x5,ldr-xy-02.png,49.1543,0.0219,0.0134,4.8948 +Small,5x5,ldrs-rgba-00.png,32.8214,0.0361,0.0290,2.2602 +Small,5x5,ldrs-rgba-01.png,35.3251,0.0227,0.0156,4.1919 +Small,5x5,ldrs-rgba-02.png,31.1476,0.0247,0.0175,3.7432 +Small,6x6,hdr-rgb-00.hdr,27.5227,0.1101,0.0242,2.7108 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0046,0.0006,0.4392 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0005,0.5628 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0005,0.5459 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0005,0.4796 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5001 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0005,0.5401 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0005,0.4941 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0044,0.0005,0.5448 +Small,6x6,ldr-rgb-00.png,32.4046,0.0322,0.0253,2.5889 +Small,6x6,ldr-rgb-01.png,33.0877,0.0241,0.0174,3.7617 +Small,6x6,ldr-rgb-02.png,27.5101,0.0245,0.0179,3.6625 +Small,6x6,ldr-rgb-03.png,41.7485,0.0118,0.0055,11.9919 +Small,6x6,ldr-rgb-04.png,34.2066,0.0211,0.0145,4.5266 +Small,6x6,ldr-rgb-05.png,30.1436,0.0326,0.0260,2.5217 +Small,6x6,ldr-rgb-06.png,27.5774,0.0242,0.0174,3.7572 +Small,6x6,ldr-rgb-07.png,33.8833,0.0351,0.0282,2.3207 +Small,6x6,ldr-rgb-08.png,39.2140,0.0158,0.0093,7.0348 +Small,6x6,ldr-rgb-09.png,33.6689,0.0206,0.0141,4.6575 +Small,6x6,ldr-rgb-10.png,36.9896,0.0073,0.0028,5.8286 +Small,6x6,ldr-rgba-00.png,30.2544,0.0391,0.0323,2.0309 +Small,6x6,ldr-rgba-01.png,32.2005,0.0235,0.0165,3.9601 +Small,6x6,ldr-rgba-02.png,27.8556,0.0265,0.0196,3.3483 +Small,6x6,ldr-xy-00.png,36.1662,0.0192,0.0110,5.9839 +Small,6x6,ldr-xy-01.png,38.0135,0.0218,0.0137,4.7858 +Small,6x6,ldr-xy-02.png,46.1312,0.0183,0.0101,6.4886 +Small,6x6,ldrs-rgba-00.png,30.2495,0.0391,0.0324,2.0255 +Small,6x6,ldrs-rgba-01.png,32.2065,0.0234,0.0166,3.9572 +Small,6x6,ldrs-rgba-02.png,27.8520,0.0264,0.0195,3.3622 +Small,8x8,hdr-rgb-00.hdr,24.1390,0.1184,0.0318,2.0578 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0052,0.0006,0.4498 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0049,0.0004,0.5795 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0051,0.0005,0.5529 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0051,0.0005,0.5079 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0050,0.0004,0.5887 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0050,0.0005,0.5289 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0050,0.0005,0.5423 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0051,0.0005,0.5470 +Small,8x8,ldr-rgb-00.png,28.7594,0.0419,0.0344,1.9028 +Small,8x8,ldr-rgb-01.png,28.9369,0.0294,0.0222,2.9576 +Small,8x8,ldr-rgb-02.png,23.1670,0.0320,0.0246,2.6591 +Small,8x8,ldr-rgb-03.png,38.5914,0.0138,0.0069,9.5560 +Small,8x8,ldr-rgb-04.png,29.6483,0.0293,0.0220,2.9845 +Small,8x8,ldr-rgb-05.png,25.9418,0.0404,0.0332,1.9761 +Small,8x8,ldr-rgb-06.png,23.2010,0.0320,0.0245,2.6772 +Small,8x8,ldr-rgb-07.png,30.7551,0.0429,0.0354,1.8502 +Small,8x8,ldr-rgb-08.png,35.9297,0.0190,0.0119,5.4924 +Small,8x8,ldr-rgb-09.png,28.9847,0.0268,0.0195,3.3625 +Small,8x8,ldr-rgb-10.png,32.1811,0.0092,0.0039,4.2145 +Small,8x8,ldr-rgba-00.png,26.4734,0.0495,0.0419,1.5657 +Small,8x8,ldr-rgba-01.png,28.3748,0.0299,0.0224,2.9250 +Small,8x8,ldr-rgba-02.png,23.9432,0.0340,0.0264,2.4855 +Small,8x8,ldr-xy-00.png,33.9578,0.0260,0.0157,4.1815 +Small,8x8,ldr-xy-01.png,34.9740,0.0260,0.0158,4.1350 +Small,8x8,ldr-xy-02.png,41.6833,0.0205,0.0105,6.2518 +Small,8x8,ldrs-rgba-00.png,26.4748,0.0493,0.0418,1.5689 +Small,8x8,ldrs-rgba-01.png,28.3782,0.0297,0.0223,2.9409 +Small,8x8,ldrs-rgba-02.png,23.9434,0.0338,0.0263,2.4961 +Small,12x12,hdr-rgb-00.hdr,20.7679,0.1367,0.0473,1.3863 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0080,0.0006,0.4654 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0079,0.0005,0.5321 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0079,0.0005,0.5470 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0081,0.0005,0.5039 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0083,0.0005,0.5412 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0079,0.0005,0.5555 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0080,0.0005,0.5540 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0079,0.0005,0.5651 +Small,12x12,ldr-rgb-00.png,24.6928,0.0530,0.0424,1.5444 +Small,12x12,ldr-rgb-01.png,25.0361,0.0397,0.0295,2.2210 +Small,12x12,ldr-rgb-02.png,19.2723,0.0471,0.0367,1.7872 +Small,12x12,ldr-rgb-03.png,34.9910,0.0175,0.0077,8.4627 +Small,12x12,ldr-rgb-04.png,24.8973,0.0383,0.0280,2.3366 +Small,12x12,ldr-rgb-05.png,21.6527,0.0536,0.0431,1.5202 +Small,12x12,ldr-rgb-06.png,19.2558,0.0472,0.0369,1.7784 +Small,12x12,ldr-rgb-07.png,26.7423,0.0487,0.0385,1.7022 +Small,12x12,ldr-rgb-08.png,31.6843,0.0227,0.0127,5.1401 +Small,12x12,ldr-rgb-09.png,24.1545,0.0369,0.0267,2.4512 +Small,12x12,ldr-rgb-10.png,28.0447,0.0165,0.0084,1.9327 +Small,12x12,ldr-rgba-00.png,22.2585,0.0590,0.0486,1.3498 +Small,12x12,ldr-rgba-01.png,24.6414,0.0388,0.0283,2.3162 +Small,12x12,ldr-rgba-02.png,20.1882,0.0501,0.0396,1.6550 +Small,12x12,ldr-xy-00.png,30.2558,0.0329,0.0189,3.4751 +Small,12x12,ldr-xy-01.png,31.8636,0.0344,0.0206,3.1798 +Small,12x12,ldr-xy-02.png,38.5089,0.0184,0.0045,14.5415 +Small,12x12,ldrs-rgba-00.png,22.2585,0.0596,0.0492,1.3307 +Small,12x12,ldrs-rgba-01.png,24.6434,0.0393,0.0287,2.2833 +Small,12x12,ldrs-rgba-02.png,20.1890,0.0510,0.0403,1.6271 +Small,3x3x3,ldr-l-00-3.dds,51.8899,0.0216,0.0127,20.6171 +Small,3x3x3,ldr-l-01-3.dds,54.6239,0.0092,0.0040,17.2562 +Small,6x6x6,ldr-l-00-3.dds,32.9631,0.0742,0.0604,4.3398 +Small,6x6x6,ldr-l-01-3.dds,41.0369,0.0294,0.0194,3.5602 diff --git a/Test/Images/Small/astc_reference-4.4-sse4.1_thorough_results.csv b/Test/Images/Small/astc_reference-4.4-sse4.1_thorough_results.csv new file mode 100644 index 0000000..d572765 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.4-sse4.1_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.4205,0.1248,0.0397,1.6492 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0037,0.0006,0.4506 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5412 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5832 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5791 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5742 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0005,0.5529 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0037,0.0005,0.5089 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0036,0.0005,0.5321 +Small,4x4,ldr-rgb-00.png,39.1635,0.0510,0.0451,1.4547 +Small,4x4,ldr-rgb-01.png,40.4120,0.0485,0.0427,1.5353 +Small,4x4,ldr-rgb-02.png,35.4711,0.0458,0.0400,1.6398 +Small,4x4,ldr-rgb-03.png,47.7527,0.0459,0.0403,1.6275 +Small,4x4,ldr-rgb-04.png,42.3660,0.0413,0.0355,1.8438 +Small,4x4,ldr-rgb-05.png,37.9925,0.0498,0.0440,1.4890 +Small,4x4,ldr-rgb-06.png,35.6403,0.0408,0.0349,1.8790 +Small,4x4,ldr-rgb-07.png,39.8791,0.0605,0.0546,1.1994 +Small,4x4,ldr-rgb-08.png,45.8775,0.0445,0.0390,1.6814 +Small,4x4,ldr-rgb-09.png,42.2993,0.0445,0.0388,1.6883 +Small,4x4,ldr-rgb-10.png,45.1694,0.0090,0.0053,3.0951 +Small,4x4,ldr-rgba-00.png,36.7416,0.0539,0.0480,1.3641 +Small,4x4,ldr-rgba-01.png,39.1154,0.0389,0.0329,1.9911 +Small,4x4,ldr-rgba-02.png,35.0328,0.0390,0.0329,1.9931 +Small,4x4,ldr-xy-00.png,37.7724,0.0475,0.0402,1.6290 +Small,4x4,ldr-xy-01.png,45.4608,0.0534,0.0462,1.4175 +Small,4x4,ldr-xy-02.png,51.1938,0.0701,0.0626,1.0473 +Small,4x4,ldrs-rgba-00.png,36.7495,0.0549,0.0489,1.3412 +Small,4x4,ldrs-rgba-01.png,39.1372,0.0393,0.0333,1.9693 +Small,4x4,ldrs-rgba-02.png,35.0344,0.0393,0.0331,1.9783 +Small,5x5,hdr-rgb-00.hdr,30.3005,0.1299,0.0439,1.4927 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0047,0.0005,0.4730 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0046,0.0005,0.5412 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0047,0.0005,0.5388 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0046,0.0005,0.5390 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0046,0.0005,0.5377 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0047,0.0005,0.5518 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0046,0.0005,0.5459 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0046,0.0005,0.5401 +Small,5x5,ldr-rgb-00.png,35.3880,0.0592,0.0521,1.2573 +Small,5x5,ldr-rgb-01.png,36.5413,0.0519,0.0449,1.4603 +Small,5x5,ldr-rgb-02.png,31.1967,0.0454,0.0384,1.7050 +Small,5x5,ldr-rgb-03.png,44.5932,0.0523,0.0457,1.4342 +Small,5x5,ldr-rgb-04.png,37.8267,0.0471,0.0402,1.6312 +Small,5x5,ldr-rgb-05.png,33.6963,0.0593,0.0524,1.2498 +Small,5x5,ldr-rgb-06.png,31.2331,0.0434,0.0364,1.8018 +Small,5x5,ldr-rgb-07.png,36.7232,0.0718,0.0648,1.0107 +Small,5x5,ldr-rgb-08.png,42.3949,0.0505,0.0438,1.4949 +Small,5x5,ldr-rgb-09.png,37.7126,0.0521,0.0452,1.4511 +Small,5x5,ldr-rgb-10.png,40.7580,0.0109,0.0060,2.6883 +Small,5x5,ldr-rgba-00.png,33.1240,0.0645,0.0574,1.1408 +Small,5x5,ldr-rgba-01.png,35.4134,0.0451,0.0381,1.7205 +Small,5x5,ldr-rgba-02.png,31.1844,0.0440,0.0368,1.7796 +Small,5x5,ldr-xy-00.png,37.1442,0.0547,0.0462,1.4194 +Small,5x5,ldr-xy-01.png,41.4542,0.0641,0.0557,1.1770 +Small,5x5,ldr-xy-02.png,49.3313,0.0767,0.0682,0.9612 +Small,5x5,ldrs-rgba-00.png,33.1272,0.0648,0.0577,1.1351 +Small,5x5,ldrs-rgba-01.png,35.4217,0.0461,0.0390,1.6806 +Small,5x5,ldrs-rgba-02.png,31.1853,0.0443,0.0371,1.7672 +Small,6x6,hdr-rgb-00.hdr,27.7238,0.1337,0.0478,1.3718 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0005,0.4876 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0004,0.5858 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0044,0.0004,0.5845 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0043,0.0005,0.5578 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0044,0.0005,0.5639 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0046,0.0005,0.4732 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0004,0.5804 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0005,0.5481 +Small,6x6,ldr-rgb-00.png,32.6509,0.0658,0.0590,1.1105 +Small,6x6,ldr-rgb-01.png,33.1881,0.0568,0.0501,1.3090 +Small,6x6,ldr-rgb-02.png,27.5552,0.0491,0.0424,1.5443 +Small,6x6,ldr-rgb-03.png,42.5885,0.0451,0.0387,1.6937 +Small,6x6,ldr-rgb-04.png,34.3416,0.0494,0.0428,1.5317 +Small,6x6,ldr-rgb-05.png,30.2875,0.0631,0.0564,1.1615 +Small,6x6,ldr-rgb-06.png,27.6306,0.0471,0.0403,1.6255 +Small,6x6,ldr-rgb-07.png,34.4380,0.0773,0.0706,0.9282 +Small,6x6,ldr-rgb-08.png,40.0373,0.0454,0.0389,1.6861 +Small,6x6,ldr-rgb-09.png,33.8118,0.0526,0.0459,1.4287 +Small,6x6,ldr-rgb-10.png,37.1861,0.0120,0.0074,2.1932 +Small,6x6,ldr-rgba-00.png,30.5164,0.0728,0.0659,0.9947 +Small,6x6,ldr-rgba-01.png,32.2794,0.0515,0.0444,1.4746 +Small,6x6,ldr-rgba-02.png,27.8936,0.0483,0.0412,1.5911 +Small,6x6,ldr-xy-00.png,36.2540,0.0471,0.0387,1.6928 +Small,6x6,ldr-xy-01.png,38.0244,0.0646,0.0564,1.1619 +Small,6x6,ldr-xy-02.png,47.5902,0.0809,0.0725,0.9034 +Small,6x6,ldrs-rgba-00.png,30.5127,0.0720,0.0651,1.0064 +Small,6x6,ldrs-rgba-01.png,32.2857,0.0514,0.0445,1.4712 +Small,6x6,ldrs-rgba-02.png,27.8909,0.0481,0.0412,1.5916 +Small,8x8,hdr-rgb-00.hdr,24.3460,0.1543,0.0658,0.9964 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0064,0.0005,0.5182 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0063,0.0005,0.5563 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0063,0.0004,0.5791 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0064,0.0005,0.5552 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0063,0.0005,0.5470 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0063,0.0005,0.5390 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0063,0.0004,0.5690 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0068,0.0005,0.4793 +Small,8x8,ldr-rgb-00.png,28.9780,0.0867,0.0779,0.8409 +Small,8x8,ldr-rgb-01.png,29.0210,0.0713,0.0626,1.0463 +Small,8x8,ldr-rgb-02.png,23.2052,0.0667,0.0580,1.1303 +Small,8x8,ldr-rgb-03.png,39.4314,0.0336,0.0252,2.6057 +Small,8x8,ldr-rgb-04.png,29.7779,0.0639,0.0552,1.1873 +Small,8x8,ldr-rgb-05.png,26.0426,0.0790,0.0704,0.9308 +Small,8x8,ldr-rgb-06.png,23.2530,0.0644,0.0557,1.1764 +Small,8x8,ldr-rgb-07.png,31.2138,0.0971,0.0881,0.7435 +Small,8x8,ldr-rgb-08.png,36.5612,0.0487,0.0403,1.6248 +Small,8x8,ldr-rgb-09.png,29.1484,0.0561,0.0475,1.3802 +Small,8x8,ldr-rgb-10.png,32.3330,0.0163,0.0097,1.6792 +Small,8x8,ldr-rgba-00.png,26.7531,0.0964,0.0875,0.7487 +Small,8x8,ldr-rgba-01.png,28.4341,0.0691,0.0602,1.0878 +Small,8x8,ldr-rgba-02.png,23.9687,0.0636,0.0547,1.1984 +Small,8x8,ldr-xy-00.png,34.2380,0.0579,0.0476,1.3782 +Small,8x8,ldr-xy-01.png,35.3165,0.0587,0.0485,1.3523 +Small,8x8,ldr-xy-02.png,44.6234,0.0741,0.0638,1.0266 +Small,8x8,ldrs-rgba-00.png,26.7540,0.0952,0.0863,0.7591 +Small,8x8,ldrs-rgba-01.png,28.4376,0.0696,0.0607,1.0800 +Small,8x8,ldrs-rgba-02.png,23.9689,0.0637,0.0547,1.1978 +Small,12x12,hdr-rgb-00.hdr,21.0311,0.1923,0.1000,0.6555 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0106,0.0006,0.4430 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0104,0.0004,0.5845 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0105,0.0005,0.5589 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0104,0.0004,0.5913 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0103,0.0005,0.5481 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0103,0.0004,0.5751 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0103,0.0005,0.5675 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0102,0.0005,0.5540 +Small,12x12,ldr-rgb-00.png,25.0530,0.1176,0.1046,0.6267 +Small,12x12,ldr-rgb-01.png,25.1392,0.0963,0.0835,0.7853 +Small,12x12,ldr-rgb-02.png,19.2921,0.1060,0.0929,0.7056 +Small,12x12,ldr-rgb-03.png,36.1864,0.0396,0.0273,2.4022 +Small,12x12,ldr-rgb-04.png,24.9919,0.0873,0.0745,0.8792 +Small,12x12,ldr-rgb-05.png,21.7388,0.1060,0.0932,0.7035 +Small,12x12,ldr-rgb-06.png,19.2959,0.1035,0.0904,0.7250 +Small,12x12,ldr-rgb-07.png,27.1136,0.1225,0.1098,0.5969 +Small,12x12,ldr-rgb-08.png,32.5295,0.0506,0.0381,1.7192 +Small,12x12,ldr-rgb-09.png,24.3026,0.0817,0.0690,0.9501 +Small,12x12,ldr-rgb-10.png,28.1806,0.0281,0.0175,0.9296 +Small,12x12,ldr-rgba-00.png,22.7565,0.1241,0.1109,0.5907 +Small,12x12,ldr-rgba-01.png,24.7322,0.1001,0.0870,0.7531 +Small,12x12,ldr-rgba-02.png,20.2051,0.1034,0.0901,0.7271 +Small,12x12,ldr-xy-00.png,30.5347,0.0788,0.0644,1.0172 +Small,12x12,ldr-xy-01.png,32.2811,0.0626,0.0483,1.3567 +Small,12x12,ldr-xy-02.png,40.3051,0.0448,0.0303,2.1614 +Small,12x12,ldrs-rgba-00.png,22.7551,0.1263,0.1133,0.5783 +Small,12x12,ldrs-rgba-01.png,24.7337,0.0999,0.0869,0.7539 +Small,12x12,ldrs-rgba-02.png,20.2055,0.1040,0.0906,0.7231 +Small,3x3x3,ldr-l-00-3.dds,52.3291,0.0370,0.0281,9.3200 +Small,3x3x3,ldr-l-01-3.dds,55.2576,0.0162,0.0110,6.2457 +Small,6x6x6,ldr-l-00-3.dds,33.2763,0.1021,0.0854,3.0691 +Small,6x6x6,ldr-l-01-3.dds,41.7183,0.0330,0.0201,3.4313 diff --git a/Test/Images/Small/astc_reference-4.5-avx2_fast_results.csv b/Test/Images/Small/astc_reference-4.5-avx2_fast_results.csv new file mode 100644 index 0000000..75776a0 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.5-avx2_fast_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.7281,0.0967,0.0120,5.4806 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0030,0.0005,0.5334 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0028,0.0004,0.5955 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0028,0.0004,0.5804 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0029,0.0005,0.5563 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0028,0.0004,0.5939 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0028,0.0004,0.5887 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0028,0.0004,0.5739 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0028,0.0004,0.5979 +Small,4x4,ldr-rgb-00.png,38.2569,0.0132,0.0080,8.1928 +Small,4x4,ldr-rgb-01.png,39.9470,0.0118,0.0069,9.5354 +Small,4x4,ldr-rgb-02.png,35.1660,0.0158,0.0107,6.1197 +Small,4x4,ldr-rgb-03.png,46.1020,0.0072,0.0025,26.0572 +Small,4x4,ldr-rgb-04.png,41.9998,0.0096,0.0046,14.1028 +Small,4x4,ldr-rgb-05.png,37.3375,0.0156,0.0106,6.1582 +Small,4x4,ldr-rgb-06.png,35.3601,0.0148,0.0098,6.6648 +Small,4x4,ldr-rgb-07.png,38.1498,0.0157,0.0108,6.0526 +Small,4x4,ldr-rgb-08.png,43.8943,0.0086,0.0039,16.6250 +Small,4x4,ldr-rgb-09.png,41.9436,0.0096,0.0047,13.8666 +Small,4x4,ldr-rgb-10.png,44.4607,0.0043,0.0014,11.7536 +Small,4x4,ldr-rgba-00.png,35.6023,0.0159,0.0106,6.2101 +Small,4x4,ldr-rgba-01.png,38.8858,0.0114,0.0062,10.5600 +Small,4x4,ldr-rgba-02.png,34.8778,0.0143,0.0089,7.3676 +Small,4x4,ldr-xy-00.png,37.5551,0.0116,0.0045,14.4604 +Small,4x4,ldr-xy-01.png,44.3046,0.0122,0.0051,12.7826 +Small,4x4,ldr-xy-02.png,48.2608,0.0104,0.0032,20.2907 +Small,4x4,ldrs-rgba-00.png,35.6078,0.0159,0.0105,6.2208 +Small,4x4,ldrs-rgba-01.png,38.9075,0.0116,0.0064,10.3159 +Small,4x4,ldrs-rgba-02.png,34.8785,0.0143,0.0089,7.3603 +Small,5x5,hdr-rgb-00.hdr,29.5480,0.0983,0.0121,5.4228 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0035,0.0005,0.5456 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0035,0.0005,0.5481 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5942 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5845 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5965 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.6066 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.6066 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,5x5,ldr-rgb-00.png,34.4341,0.0133,0.0075,8.7720 +Small,5x5,ldr-rgb-01.png,36.2623,0.0106,0.0051,12.9312 +Small,5x5,ldr-rgb-02.png,31.0936,0.0136,0.0080,8.1787 +Small,5x5,ldr-rgb-03.png,42.8088,0.0074,0.0021,30.5386 +Small,5x5,ldr-rgb-04.png,37.2825,0.0099,0.0043,15.2270 +Small,5x5,ldr-rgb-05.png,33.2757,0.0161,0.0103,6.3919 +Small,5x5,ldr-rgb-06.png,31.1333,0.0136,0.0079,8.3413 +Small,5x5,ldr-rgb-07.png,35.0677,0.0138,0.0082,7.9465 +Small,5x5,ldr-rgb-08.png,40.2429,0.0086,0.0032,20.3463 +Small,5x5,ldr-rgb-09.png,37.3051,0.0101,0.0045,14.5438 +Small,5x5,ldr-rgb-10.png,40.2131,0.0048,0.0012,13.2806 +Small,5x5,ldr-rgba-00.png,32.1489,0.0164,0.0106,6.1919 +Small,5x5,ldr-rgba-01.png,35.2139,0.0118,0.0059,11.0927 +Small,5x5,ldr-rgba-02.png,31.1368,0.0143,0.0084,7.7603 +Small,5x5,ldr-xy-00.png,36.7495,0.0115,0.0035,18.7412 +Small,5x5,ldr-xy-01.png,39.8321,0.0123,0.0043,15.2160 +Small,5x5,ldr-xy-02.png,43.9343,0.0111,0.0031,21.4179 +Small,5x5,ldrs-rgba-00.png,32.1529,0.0165,0.0106,6.1617 +Small,5x5,ldrs-rgba-01.png,35.2217,0.0117,0.0058,11.3132 +Small,5x5,ldrs-rgba-02.png,31.1375,0.0145,0.0084,7.8253 +Small,6x6,hdr-rgb-00.hdr,27.0790,0.0982,0.0119,5.5286 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0034,0.0005,0.5540 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0034,0.0005,0.5412 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0033,0.0004,0.5913 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5742 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5871 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5952 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.6066 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.5887 +Small,6x6,ldr-rgb-00.png,31.7166,0.0145,0.0088,7.4329 +Small,6x6,ldr-rgb-01.png,32.9399,0.0113,0.0059,11.0909 +Small,6x6,ldr-rgb-02.png,27.4804,0.0141,0.0086,7.6561 +Small,6x6,ldr-rgb-03.png,40.6162,0.0073,0.0021,31.7045 +Small,6x6,ldr-rgb-04.png,33.9381,0.0104,0.0048,13.5991 +Small,6x6,ldr-rgb-05.png,29.9812,0.0172,0.0116,5.6312 +Small,6x6,ldr-rgb-06.png,27.5471,0.0140,0.0085,7.6902 +Small,6x6,ldr-rgb-07.png,32.9397,0.0133,0.0078,8.3707 +Small,6x6,ldr-rgb-08.png,37.8487,0.0085,0.0032,20.6675 +Small,6x6,ldr-rgb-09.png,33.5003,0.0104,0.0050,13.2178 +Small,6x6,ldr-rgb-10.png,36.6941,0.0049,0.0014,11.5544 +Small,6x6,ldr-rgba-00.png,29.6087,0.0177,0.0120,5.4791 +Small,6x6,ldr-rgba-01.png,32.0982,0.0122,0.0065,10.1573 +Small,6x6,ldr-rgba-02.png,27.8405,0.0149,0.0090,7.2527 +Small,6x6,ldr-xy-00.png,35.9075,0.0113,0.0036,18.2655 +Small,6x6,ldr-xy-01.png,37.1654,0.0128,0.0050,13.1382 +Small,6x6,ldr-xy-02.png,41.9299,0.0109,0.0029,22.6685 +Small,6x6,ldrs-rgba-00.png,29.6033,0.0178,0.0120,5.4769 +Small,6x6,ldrs-rgba-01.png,32.1035,0.0123,0.0065,10.1229 +Small,6x6,ldrs-rgba-02.png,27.8382,0.0148,0.0089,7.3258 +Small,8x8,hdr-rgb-00.hdr,23.7844,0.1000,0.0141,4.6431 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0036,0.0004,0.5939 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.6012 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5965 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0036,0.0005,0.5648 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0036,0.0004,0.5952 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0036,0.0004,0.5926 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5926 +Small,8x8,ldr-rgb-00.png,28.0676,0.0155,0.0095,6.9247 +Small,8x8,ldr-rgb-01.png,28.7806,0.0133,0.0076,8.6242 +Small,8x8,ldr-rgb-02.png,23.1041,0.0172,0.0115,5.6914 +Small,8x8,ldr-rgb-03.png,37.3709,0.0078,0.0023,28.2013 +Small,8x8,ldr-rgb-04.png,29.3495,0.0126,0.0068,9.6462 +Small,8x8,ldr-rgb-05.png,25.8037,0.0190,0.0133,4.9409 +Small,8x8,ldr-rgb-06.png,23.1652,0.0174,0.0115,5.6944 +Small,8x8,ldr-rgb-07.png,29.8451,0.0132,0.0075,8.7185 +Small,8x8,ldr-rgb-08.png,34.5025,0.0089,0.0035,18.8054 +Small,8x8,ldr-rgb-09.png,28.6427,0.0122,0.0065,10.0980 +Small,8x8,ldr-rgb-10.png,31.9962,0.0053,0.0017,9.6823 +Small,8x8,ldr-rgba-00.png,25.7043,0.0189,0.0130,5.0545 +Small,8x8,ldr-rgba-01.png,28.2957,0.0146,0.0088,7.4848 +Small,8x8,ldr-rgba-02.png,23.9357,0.0187,0.0126,5.2141 +Small,8x8,ldr-xy-00.png,33.3347,0.0129,0.0045,14.4993 +Small,8x8,ldr-xy-01.png,34.3877,0.0138,0.0054,12.2157 +Small,8x8,ldr-xy-02.png,39.8793,0.0102,0.0020,33.3024 +Small,8x8,ldrs-rgba-00.png,25.7036,0.0191,0.0132,4.9815 +Small,8x8,ldrs-rgba-01.png,28.2982,0.0150,0.0089,7.3977 +Small,8x8,ldrs-rgba-02.png,23.9357,0.0189,0.0128,5.1188 +Small,12x12,hdr-rgb-00.hdr,20.5374,0.1077,0.0204,3.2108 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0055,0.0005,0.4960 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0054,0.0004,0.6039 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0054,0.0004,0.5939 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0054,0.0004,0.5871 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0055,0.0004,0.5702 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0054,0.0004,0.5845 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0054,0.0004,0.5832 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0054,0.0004,0.5929 +Small,12x12,ldr-rgb-00.png,23.7935,0.0160,0.0084,7.8440 +Small,12x12,ldr-rgb-01.png,24.7788,0.0136,0.0060,10.8759 +Small,12x12,ldr-rgb-02.png,19.2303,0.0211,0.0135,4.8595 +Small,12x12,ldr-rgb-03.png,33.2628,0.0089,0.0016,41.7430 +Small,12x12,ldr-rgb-04.png,24.5747,0.0135,0.0058,11.2296 +Small,12x12,ldr-rgb-05.png,21.4927,0.0194,0.0117,5.5880 +Small,12x12,ldr-rgb-06.png,19.2272,0.0219,0.0140,4.6745 +Small,12x12,ldr-rgb-07.png,25.3785,0.0131,0.0055,11.9940 +Small,12x12,ldr-rgb-08.png,30.3013,0.0101,0.0027,24.6749 +Small,12x12,ldr-rgb-09.png,23.7371,0.0152,0.0075,8.7826 +Small,12x12,ldr-rgb-10.png,27.3251,0.0076,0.0021,7.9025 +Small,12x12,ldr-rgba-00.png,21.6082,0.0213,0.0135,4.8675 +Small,12x12,ldr-rgba-01.png,24.5280,0.0152,0.0073,8.9900 +Small,12x12,ldr-rgba-02.png,20.1750,0.0241,0.0160,4.1004 +Small,12x12,ldr-xy-00.png,29.2247,0.0158,0.0047,14.0876 +Small,12x12,ldr-xy-01.png,30.5463,0.0150,0.0041,16.0232 +Small,12x12,ldr-xy-02.png,37.9988,0.0118,0.0010,65.2762 +Small,12x12,ldrs-rgba-00.png,21.6128,0.0214,0.0136,4.8224 +Small,12x12,ldrs-rgba-01.png,24.5296,0.0152,0.0074,8.8311 +Small,12x12,ldrs-rgba-02.png,20.1745,0.0239,0.0160,4.0917 +Small,3x3x3,ldr-l-00-3.dds,50.8347,0.0152,0.0076,34.5932 +Small,3x3x3,ldr-l-01-3.dds,54.0740,0.0074,0.0032,21.6325 +Small,6x6x6,ldr-l-00-3.dds,32.5284,0.0459,0.0348,7.5407 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0211,0.0135,5.1151 diff --git a/Test/Images/Small/astc_reference-4.5-avx2_fastest_results.csv b/Test/Images/Small/astc_reference-4.5-avx2_fastest_results.csv new file mode 100644 index 0000000..21c8783 --- /dev/null +++ b/Test/Images/Small/astc_reference-4.5-avx2_fastest_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,33.3455,0.0914,0.0074,8.8029 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0024,0.0006,0.4444 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0022,0.0004,0.5982 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0022,0.0004,0.5913 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0023,0.0004,0.5913 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0023,0.0004,0.5779 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0023,0.0004,0.5871 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0022,0.0004,0.5995 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0022,0.0004,0.5900 +Small,4x4,ldr-rgb-00.png,37.2529,0.0091,0.0044,14.7601 +Small,4x4,ldr-rgb-01.png,39.5638,0.0086,0.0043,15.3084 +Small,4x4,ldr-rgb-02.png,34.7942,0.0106,0.0060,10.9649 +Small,4x4,ldr-rgb-03.png,45.5124,0.0061,0.0020,33.0144 +Small,4x4,ldr-rgb-04.png,41.7336,0.0075,0.0031,21.3266 +Small,4x4,ldr-rgb-05.png,36.8693,0.0107,0.0062,10.5552 +Small,4x4,ldr-rgb-06.png,34.9652,0.0101,0.0055,11.8085 +Small,4x4,ldr-rgb-07.png,37.3689,0.0103,0.0059,11.1894 +Small,4x4,ldr-rgb-08.png,43.0306,0.0066,0.0025,26.3621 +Small,4x4,ldr-rgb-09.png,41.7486,0.0075,0.0031,21.0990 +Small,4x4,ldr-rgb-10.png,43.9452,0.0035,0.0011,14.9687 +Small,4x4,ldr-rgba-00.png,34.7374,0.0105,0.0059,11.1834 +Small,4x4,ldr-rgba-01.png,38.6951,0.0092,0.0045,14.4194 +Small,4x4,ldr-rgba-02.png,34.5660,0.0110,0.0062,10.5112 +Small,4x4,ldr-xy-00.png,37.5260,0.0098,0.0033,19.7527 +Small,4x4,ldr-xy-01.png,43.9781,0.0101,0.0035,18.5078 +Small,4x4,ldr-xy-02.png,48.2748,0.0091,0.0026,25.3507 +Small,4x4,ldrs-rgba-00.png,34.7414,0.0107,0.0061,10.8237 +Small,4x4,ldrs-rgba-01.png,38.7117,0.0092,0.0045,14.4225 +Small,4x4,ldrs-rgba-02.png,34.5694,0.0111,0.0064,10.2900 +Small,5x5,hdr-rgb-00.hdr,28.8745,0.0934,0.0074,8.8802 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0027,0.0005,0.5555 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0026,0.0004,0.6012 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0026,0.0004,0.6066 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5896 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.6066 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5969 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0027,0.0005,0.5437 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0026,0.0004,0.5926 +Small,5x5,ldr-rgb-00.png,33.7244,0.0093,0.0043,15.2127 +Small,5x5,ldr-rgb-01.png,36.0878,0.0084,0.0036,18.0579 +Small,5x5,ldr-rgb-02.png,30.9936,0.0106,0.0059,11.1666 +Small,5x5,ldr-rgb-03.png,42.4162,0.0061,0.0018,36.5529 +Small,5x5,ldr-rgb-04.png,37.0506,0.0081,0.0033,19.7158 +Small,5x5,ldr-rgb-05.png,32.9675,0.0111,0.0064,10.2643 +Small,5x5,ldr-rgb-06.png,31.0371,0.0104,0.0055,11.9460 +Small,5x5,ldr-rgb-07.png,34.4113,0.0101,0.0055,11.9982 +Small,5x5,ldr-rgb-08.png,39.6331,0.0068,0.0024,27.5015 +Small,5x5,ldr-rgb-09.png,37.0868,0.0080,0.0033,19.8597 +Small,5x5,ldr-rgb-10.png,39.9339,0.0039,0.0011,15.0381 +Small,5x5,ldr-rgba-00.png,31.1173,0.0108,0.0060,10.9978 +Small,5x5,ldr-rgba-01.png,35.0547,0.0093,0.0043,15.3520 +Small,5x5,ldr-rgba-02.png,31.0412,0.0114,0.0063,10.4207 +Small,5x5,ldr-xy-00.png,36.5692,0.0099,0.0028,23.4298 +Small,5x5,ldr-xy-01.png,39.2568,0.0104,0.0032,20.6086 +Small,5x5,ldr-xy-02.png,43.8559,0.0098,0.0026,25.0321 +Small,5x5,ldrs-rgba-00.png,31.1179,0.0111,0.0061,10.7332 +Small,5x5,ldrs-rgba-01.png,35.0634,0.0094,0.0044,14.8647 +Small,5x5,ldrs-rgba-02.png,31.0416,0.0113,0.0062,10.5604 +Small,6x6,hdr-rgb-00.hdr,26.7600,0.0910,0.0069,9.5660 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0028,0.0005,0.4679 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0028,0.0006,0.4461 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0027,0.0005,0.5663 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0026,0.0004,0.5804 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0026,0.0004,0.5858 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0026,0.0004,0.5939 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0026,0.0004,0.6009 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0027,0.0005,0.5678 +Small,6x6,ldr-rgb-00.png,31.3444,0.0099,0.0049,13.3281 +Small,6x6,ldr-rgb-01.png,32.8499,0.0088,0.0041,16.1779 +Small,6x6,ldr-rgb-02.png,27.3935,0.0110,0.0061,10.7825 +Small,6x6,ldr-rgb-03.png,40.3786,0.0062,0.0018,37.3019 +Small,6x6,ldr-rgb-04.png,33.7681,0.0086,0.0038,17.1338 +Small,6x6,ldr-rgb-05.png,29.7460,0.0117,0.0068,9.5716 +Small,6x6,ldr-rgb-06.png,27.4712,0.0109,0.0061,10.8041 +Small,6x6,ldr-rgb-07.png,32.3405,0.0098,0.0050,13.0732 +Small,6x6,ldr-rgb-08.png,37.4798,0.0068,0.0023,28.8950 +Small,6x6,ldr-rgb-09.png,33.3198,0.0085,0.0037,17.5238 +Small,6x6,ldr-rgb-10.png,36.5819,0.0039,0.0012,14.0757 +Small,6x6,ldr-rgba-00.png,28.8490,0.0111,0.0062,10.6426 +Small,6x6,ldr-rgba-01.png,32.0060,0.0098,0.0047,13.8519 +Small,6x6,ldr-rgba-02.png,27.7806,0.0112,0.0061,10.7808 +Small,6x6,ldr-xy-00.png,35.6139,0.0097,0.0027,23.9712 +Small,6x6,ldr-xy-01.png,36.5248,0.0104,0.0034,19.3481 +Small,6x6,ldr-xy-02.png,41.7978,0.0093,0.0023,27.9575 +Small,6x6,ldrs-rgba-00.png,28.8451,0.0114,0.0063,10.4676 +Small,6x6,ldrs-rgba-01.png,32.0127,0.0099,0.0049,13.5015 +Small,6x6,ldrs-rgba-02.png,27.7795,0.0113,0.0061,10.6649 +Small,8x8,hdr-rgb-00.hdr,23.6156,0.0961,0.0097,6.7367 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0036,0.0006,0.4491 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0035,0.0004,0.5690 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0034,0.0004,0.5982 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5817 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0034,0.0004,0.5913 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5871 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0034,0.0004,0.6084 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0034,0.0004,0.6080 +Small,8x8,ldr-rgb-00.png,27.7167,0.0125,0.0067,9.7682 +Small,8x8,ldr-rgb-01.png,28.6907,0.0112,0.0057,11.5277 +Small,8x8,ldr-rgb-02.png,23.0278,0.0141,0.0085,7.6966 +Small,8x8,ldr-rgb-03.png,37.0821,0.0071,0.0019,34.8609 +Small,8x8,ldr-rgb-04.png,29.1235,0.0108,0.0052,12.6590 +Small,8x8,ldr-rgb-05.png,25.6014,0.0153,0.0096,6.8323 +Small,8x8,ldr-rgb-06.png,23.0812,0.0143,0.0087,7.5416 +Small,8x8,ldr-rgb-07.png,29.4710,0.0112,0.0056,11.6860 +Small,8x8,ldr-rgb-08.png,33.9667,0.0080,0.0027,24.6549 +Small,8x8,ldr-rgb-09.png,28.4474,0.0105,0.0049,13.2612 +Small,8x8,ldr-rgb-10.png,31.9065,0.0048,0.0012,13.3482 +Small,8x8,ldr-rgba-00.png,25.3490,0.0149,0.0090,7.3020 +Small,8x8,ldr-rgba-01.png,28.1981,0.0122,0.0064,10.1825 +Small,8x8,ldr-rgba-02.png,23.8740,0.0149,0.0089,7.3554 +Small,8x8,ldr-xy-00.png,33.2129,0.0118,0.0035,18.9414 +Small,8x8,ldr-xy-01.png,34.1355,0.0124,0.0041,15.8458 +Small,8x8,ldr-xy-02.png,39.7699,0.0099,0.0017,38.3693 +Small,8x8,ldrs-rgba-00.png,25.3494,0.0147,0.0090,7.3125 +Small,8x8,ldrs-rgba-01.png,28.2001,0.0122,0.0065,10.1465 +Small,8x8,ldrs-rgba-02.png,23.8734,0.0147,0.0088,7.4179 +Small,12x12,hdr-rgb-00.hdr,20.4504,0.1013,0.0142,4.6266 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0050,0.0005,0.5423 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0050,0.0005,0.5345 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0050,0.0004,0.6053 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0050,0.0005,0.5687 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0050,0.0004,0.5764 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0050,0.0004,0.5982 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.5871 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0049,0.0005,0.5687 +Small,12x12,ldr-rgb-00.png,23.7161,0.0134,0.0061,10.7593 +Small,12x12,ldr-rgb-01.png,24.7331,0.0115,0.0044,14.8840 +Small,12x12,ldr-rgb-02.png,19.1961,0.0167,0.0096,6.8502 +Small,12x12,ldr-rgb-03.png,33.1683,0.0081,0.0013,48.7632 +Small,12x12,ldr-rgb-04.png,24.3855,0.0114,0.0044,15.0626 +Small,12x12,ldr-rgb-05.png,21.3869,0.0155,0.0086,7.6634 +Small,12x12,ldr-rgb-06.png,19.1690,0.0171,0.0099,6.6057 +Small,12x12,ldr-rgb-07.png,25.3202,0.0113,0.0042,15.5228 +Small,12x12,ldr-rgb-08.png,30.1264,0.0088,0.0020,32.0184 +Small,12x12,ldr-rgb-09.png,23.5982,0.0127,0.0058,11.3675 +Small,12x12,ldr-rgb-10.png,27.2845,0.0065,0.0015,10.6319 +Small,12x12,ldr-rgba-00.png,21.3617,0.0166,0.0093,7.0750 +Small,12x12,ldr-rgba-01.png,24.4897,0.0128,0.0053,12.4188 +Small,12x12,ldr-rgba-02.png,20.1411,0.0187,0.0113,5.7909 +Small,12x12,ldr-xy-00.png,28.8913,0.0141,0.0036,18.3313 +Small,12x12,ldr-xy-01.png,29.6644,0.0135,0.0031,21.0393 +Small,12x12,ldr-xy-02.png,37.9766,0.0115,0.0011,61.2473 +Small,12x12,ldrs-rgba-00.png,21.3630,0.0167,0.0094,7.0061 +Small,12x12,ldrs-rgba-01.png,24.4906,0.0129,0.0053,12.3630 +Small,12x12,ldrs-rgba-02.png,20.1404,0.0188,0.0114,5.7740 +Small,3x3x3,ldr-l-00-3.dds,50.6895,0.0143,0.0074,35.3723 +Small,3x3x3,ldr-l-01-3.dds,54.0388,0.0065,0.0032,21.8253 +Small,6x6x6,ldr-l-00-3.dds,32.5118,0.0454,0.0345,7.5986 +Small,6x6x6,ldr-l-01-3.dds,40.9269,0.0211,0.0135,5.1193 diff --git a/Test/Images/Small/astc_reference-4.5-avx2_medium_results.csv b/Test/Images/Small/astc_reference-4.5-avx2_medium_results.csv new file mode 100644 index 0000000..4c7f55b --- /dev/null +++ b/Test/Images/Small/astc_reference-4.5-avx2_medium_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.1462,0.1032,0.0180,3.6421 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0034,0.0004,0.5807 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0034,0.0004,0.5955 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0005,0.5678 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0034,0.0004,0.5845 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.6053 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0034,0.0004,0.5969 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5871 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0035,0.0004,0.5952 +Small,4x4,ldr-rgb-00.png,38.8447,0.0256,0.0198,3.3171 +Small,4x4,ldr-rgb-01.png,40.2430,0.0226,0.0169,3.8850 +Small,4x4,ldr-rgb-02.png,35.2978,0.0230,0.0173,3.7946 +Small,4x4,ldr-rgb-03.png,47.3064,0.0149,0.0096,6.8473 +Small,4x4,ldr-rgb-04.png,42.2335,0.0189,0.0133,4.9245 +Small,4x4,ldr-rgb-05.png,37.8203,0.0244,0.0188,3.4885 +Small,4x4,ldr-rgb-06.png,35.4765,0.0208,0.0150,4.3720 +Small,4x4,ldr-rgb-07.png,39.2891,0.0297,0.0241,2.7239 +Small,4x4,ldr-rgb-08.png,45.2670,0.0174,0.0121,5.4355 +Small,4x4,ldr-rgb-09.png,42.1643,0.0193,0.0136,4.8029 +Small,4x4,ldr-rgb-10.png,44.9416,0.0060,0.0023,7.1991 +Small,4x4,ldr-rgba-00.png,36.2622,0.0276,0.0217,3.0166 +Small,4x4,ldr-rgba-01.png,38.9940,0.0183,0.0125,5.2571 +Small,4x4,ldr-rgba-02.png,34.9453,0.0200,0.0139,4.7090 +Small,4x4,ldr-xy-00.png,37.7304,0.0181,0.0108,6.0619 +Small,4x4,ldr-xy-01.png,45.3643,0.0240,0.0168,3.9037 +Small,4x4,ldr-xy-02.png,51.1886,0.0269,0.0196,3.3416 +Small,4x4,ldrs-rgba-00.png,36.2683,0.0277,0.0219,2.9990 +Small,4x4,ldrs-rgba-01.png,39.0152,0.0185,0.0126,5.2000 +Small,4x4,ldrs-rgba-02.png,34.9482,0.0200,0.0140,4.6801 +Small,5x5,hdr-rgb-00.hdr,29.9063,0.1065,0.0195,3.3581 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0046,0.0004,0.5858 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0045,0.0004,0.5900 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0004,0.5887 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0004,0.5913 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5791 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0046,0.0005,0.5651 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0046,0.0004,0.5791 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0004,0.5896 +Small,5x5,ldr-rgb-00.png,35.1493,0.0266,0.0197,3.3265 +Small,5x5,ldr-rgb-01.png,36.4584,0.0209,0.0141,4.6506 +Small,5x5,ldr-rgb-02.png,31.1362,0.0214,0.0146,4.5027 +Small,5x5,ldr-rgb-03.png,44.0254,0.0122,0.0059,11.0442 +Small,5x5,ldr-rgb-04.png,37.6864,0.0198,0.0130,5.0435 +Small,5x5,ldr-rgb-05.png,33.5492,0.0276,0.0209,3.1351 +Small,5x5,ldr-rgb-06.png,31.1811,0.0206,0.0137,4.7708 +Small,5x5,ldr-rgb-07.png,36.1585,0.0311,0.0244,2.6829 +Small,5x5,ldr-rgb-08.png,41.6847,0.0167,0.0101,6.4856 +Small,5x5,ldr-rgb-09.png,37.5941,0.0189,0.0122,5.3533 +Small,5x5,ldr-rgb-10.png,40.5906,0.0070,0.0023,7.0590 +Small,5x5,ldr-rgba-00.png,32.8187,0.0311,0.0241,2.7211 +Small,5x5,ldr-rgba-01.png,35.3326,0.0202,0.0131,5.0020 +Small,5x5,ldr-rgba-02.png,31.1493,0.0218,0.0147,4.4607 +Small,5x5,ldr-xy-00.png,37.0404,0.0187,0.0104,6.3032 +Small,5x5,ldr-xy-01.png,40.7159,0.0232,0.0150,4.3807 +Small,5x5,ldr-xy-02.png,49.1543,0.0195,0.0111,5.9101 +Small,5x5,ldrs-rgba-00.png,32.8232,0.0312,0.0243,2.6941 +Small,5x5,ldrs-rgba-01.png,35.3411,0.0202,0.0131,4.9902 +Small,5x5,ldrs-rgba-02.png,31.1502,0.0218,0.0147,4.4519 +Small,6x6,hdr-rgb-00.hdr,27.5227,0.1060,0.0200,3.2775 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0005,0.4766 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0043,0.0004,0.5804 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0043,0.0004,0.5887 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0042,0.0004,0.6122 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0005,0.5355 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0043,0.0004,0.6094 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0044,0.0004,0.5804 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0043,0.0004,0.5858 +Small,6x6,ldr-rgb-00.png,32.4047,0.0269,0.0203,3.2291 +Small,6x6,ldr-rgb-01.png,33.1026,0.0202,0.0137,4.7763 +Small,6x6,ldr-rgb-02.png,27.5112,0.0210,0.0145,4.5094 +Small,6x6,ldr-rgb-03.png,41.7463,0.0108,0.0046,14.3719 +Small,6x6,ldr-rgb-04.png,34.2123,0.0180,0.0117,5.6119 +Small,6x6,ldr-rgb-05.png,30.1467,0.0276,0.0211,3.1001 +Small,6x6,ldr-rgb-06.png,27.5763,0.0207,0.0141,4.6619 +Small,6x6,ldr-rgb-07.png,33.8876,0.0293,0.0228,2.8715 +Small,6x6,ldr-rgb-08.png,39.2539,0.0138,0.0076,8.5827 +Small,6x6,ldr-rgb-09.png,33.6738,0.0179,0.0115,5.7177 +Small,6x6,ldr-rgb-10.png,36.9931,0.0068,0.0023,6.9766 +Small,6x6,ldr-rgba-00.png,30.2533,0.0330,0.0263,2.4935 +Small,6x6,ldr-rgba-01.png,32.2127,0.0201,0.0133,4.9290 +Small,6x6,ldr-rgba-02.png,27.8543,0.0225,0.0157,4.1647 +Small,6x6,ldr-xy-00.png,36.1662,0.0171,0.0090,7.2617 +Small,6x6,ldr-xy-01.png,38.0135,0.0192,0.0112,5.8598 +Small,6x6,ldr-xy-02.png,46.1312,0.0161,0.0080,8.2176 +Small,6x6,ldrs-rgba-00.png,30.2485,0.0331,0.0264,2.4804 +Small,6x6,ldrs-rgba-01.png,32.2188,0.0202,0.0134,4.8914 +Small,6x6,ldrs-rgba-02.png,27.8512,0.0227,0.0158,4.1555 +Small,8x8,hdr-rgb-00.hdr,24.1390,0.1114,0.0250,2.6267 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0051,0.0004,0.5791 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0049,0.0004,0.5884 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0049,0.0004,0.5913 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0049,0.0004,0.5926 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0049,0.0004,0.5926 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0049,0.0004,0.5995 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0049,0.0004,0.6066 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0050,0.0004,0.5982 +Small,8x8,ldr-rgb-00.png,28.7602,0.0339,0.0267,2.4585 +Small,8x8,ldr-rgb-01.png,28.9505,0.0243,0.0173,3.7946 +Small,8x8,ldr-rgb-02.png,23.1668,0.0259,0.0188,3.4942 +Small,8x8,ldr-rgb-03.png,38.5948,0.0125,0.0055,11.8339 +Small,8x8,ldr-rgb-04.png,29.6515,0.0240,0.0169,3.8827 +Small,8x8,ldr-rgb-05.png,25.9410,0.0326,0.0254,2.5757 +Small,8x8,ldr-rgb-06.png,23.2026,0.0261,0.0189,3.4585 +Small,8x8,ldr-rgb-07.png,30.7566,0.0337,0.0265,2.4770 +Small,8x8,ldr-rgb-08.png,35.9377,0.0161,0.0093,7.0597 +Small,8x8,ldr-rgb-09.png,28.9876,0.0221,0.0151,4.3450 +Small,8x8,ldr-rgb-10.png,32.1821,0.0083,0.0032,5.1315 +Small,8x8,ldr-rgba-00.png,26.4742,0.0397,0.0322,2.0324 +Small,8x8,ldr-rgba-01.png,28.3861,0.0244,0.0171,3.8370 +Small,8x8,ldr-rgba-02.png,23.9437,0.0278,0.0204,3.2091 +Small,8x8,ldr-xy-00.png,33.9578,0.0221,0.0121,5.4018 +Small,8x8,ldr-xy-01.png,34.9740,0.0221,0.0122,5.3803 +Small,8x8,ldr-xy-02.png,41.6833,0.0180,0.0081,8.0749 +Small,8x8,ldrs-rgba-00.png,26.4759,0.0397,0.0323,2.0276 +Small,8x8,ldrs-rgba-01.png,28.3894,0.0245,0.0171,3.8385 +Small,8x8,ldrs-rgba-02.png,23.9439,0.0280,0.0206,3.1880 +Small,12x12,hdr-rgb-00.hdr,20.7679,0.1257,0.0360,1.8221 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0077,0.0004,0.5727 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0077,0.0004,0.5871 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0077,0.0004,0.5845 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0079,0.0005,0.5566 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0078,0.0004,0.5829 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0079,0.0004,0.5804 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0078,0.0004,0.5942 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0078,0.0004,0.5739 +Small,12x12,ldr-rgb-00.png,24.6929,0.0431,0.0328,1.9974 +Small,12x12,ldr-rgb-01.png,25.0453,0.0324,0.0224,2.9287 +Small,12x12,ldr-rgb-02.png,19.2722,0.0378,0.0278,2.3610 +Small,12x12,ldr-rgb-03.png,35.0023,0.0155,0.0060,10.9517 +Small,12x12,ldr-rgb-04.png,24.8982,0.0313,0.0213,3.0801 +Small,12x12,ldr-rgb-05.png,21.6540,0.0429,0.0329,1.9948 +Small,12x12,ldr-rgb-06.png,19.2563,0.0384,0.0282,2.3213 +Small,12x12,ldr-rgb-07.png,26.7438,0.0392,0.0291,2.2495 +Small,12x12,ldr-rgb-08.png,31.6917,0.0198,0.0102,6.4365 +Small,12x12,ldr-rgb-09.png,24.1554,0.0303,0.0204,3.2140 +Small,12x12,ldr-rgb-10.png,28.0456,0.0146,0.0065,2.4944 +Small,12x12,ldr-rgba-00.png,22.2625,0.0477,0.0372,1.7613 +Small,12x12,ldr-rgba-01.png,24.6525,0.0317,0.0214,3.0561 +Small,12x12,ldr-rgba-02.png,20.1885,0.0408,0.0303,2.1635 +Small,12x12,ldr-xy-00.png,30.2558,0.0284,0.0146,4.4848 +Small,12x12,ldr-xy-01.png,31.8636,0.0294,0.0156,4.2067 +Small,12x12,ldr-xy-02.png,38.5089,0.0172,0.0036,18.3423 +Small,12x12,ldrs-rgba-00.png,22.2625,0.0474,0.0371,1.7644 +Small,12x12,ldrs-rgba-01.png,24.6544,0.0319,0.0216,3.0317 +Small,12x12,ldrs-rgba-02.png,20.1884,0.0408,0.0302,2.1694 +Small,3x3x3,ldr-l-00-3.dds,51.8899,0.0193,0.0107,24.5224 +Small,3x3x3,ldr-l-01-3.dds,54.6239,0.0084,0.0034,20.2704 +Small,6x6x6,ldr-l-00-3.dds,32.9631,0.0552,0.0420,6.2402 +Small,6x6x6,ldr-l-01-3.dds,41.0369,0.0231,0.0133,5.1755 diff --git a/Test/Images/Small/astc_reference-4.5-avx2_thorough_results.csv b/Test/Images/Small/astc_reference-4.5-avx2_thorough_results.csv new file mode 100644 index 0000000..f1f642f --- /dev/null +++ b/Test/Images/Small/astc_reference-4.5-avx2_thorough_results.csv @@ -0,0 +1,150 @@ +Image Set,Block Size,Name,PSNR,Total Time,Coding Time,Coding Rate +Small,4x4,hdr-rgb-00.hdr,34.4205,0.1204,0.0355,1.8483 +Small,4x4,hdr-rgb-r16.ktx,999.0000,0.0037,0.0005,0.4859 +Small,4x4,hdr-rgb-r32.ktx,999.0000,0.0036,0.0005,0.5412 +Small,4x4,hdr-rgb-rg16.ktx,999.0000,0.0035,0.0004,0.5900 +Small,4x4,hdr-rgb-rg32.ktx,999.0000,0.0035,0.0004,0.5858 +Small,4x4,hdr-rgb-rgb16.ktx,999.0000,0.0035,0.0004,0.5969 +Small,4x4,hdr-rgb-rgb32.ktx,999.0000,0.0035,0.0004,0.6036 +Small,4x4,hdr-rgba-rgba16.ktx,999.0000,0.0035,0.0004,0.5913 +Small,4x4,hdr-rgba-rgba32.ktx,999.0000,0.0037,0.0005,0.5437 +Small,4x4,ldr-rgb-00.png,39.1653,0.0463,0.0403,1.6270 +Small,4x4,ldr-rgb-01.png,40.4305,0.0440,0.0383,1.7127 +Small,4x4,ldr-rgb-02.png,35.4779,0.0412,0.0355,1.8457 +Small,4x4,ldr-rgb-03.png,47.7789,0.0411,0.0358,1.8327 +Small,4x4,ldr-rgb-04.png,42.3777,0.0375,0.0318,2.0616 +Small,4x4,ldr-rgb-05.png,37.9945,0.0446,0.0389,1.6836 +Small,4x4,ldr-rgb-06.png,35.6411,0.0369,0.0311,2.1083 +Small,4x4,ldr-rgb-07.png,39.8829,0.0538,0.0481,1.3627 +Small,4x4,ldr-rgb-08.png,45.9519,0.0400,0.0347,1.8909 +Small,4x4,ldr-rgb-09.png,42.3046,0.0405,0.0347,1.8861 +Small,4x4,ldr-rgb-10.png,45.1703,0.0081,0.0045,3.6269 +Small,4x4,ldr-rgba-00.png,36.7436,0.0482,0.0421,1.5564 +Small,4x4,ldr-rgba-01.png,39.1381,0.0347,0.0288,2.2783 +Small,4x4,ldr-rgba-02.png,35.0377,0.0347,0.0286,2.2899 +Small,4x4,ldr-xy-00.png,37.7724,0.0428,0.0355,1.8449 +Small,4x4,ldr-xy-01.png,45.4608,0.0475,0.0403,1.6244 +Small,4x4,ldr-xy-02.png,51.1939,0.0612,0.0539,1.2162 +Small,4x4,ldrs-rgba-00.png,36.7515,0.0479,0.0420,1.5603 +Small,4x4,ldrs-rgba-01.png,39.1599,0.0354,0.0293,2.2390 +Small,4x4,ldrs-rgba-02.png,35.0390,0.0348,0.0288,2.2750 +Small,5x5,hdr-rgb-00.hdr,30.3005,0.1236,0.0374,1.7522 +Small,5x5,hdr-rgb-r16.ktx,999.0000,0.0045,0.0004,0.5982 +Small,5x5,hdr-rgb-r32.ktx,999.0000,0.0045,0.0004,0.6025 +Small,5x5,hdr-rgb-rg16.ktx,999.0000,0.0045,0.0004,0.6025 +Small,5x5,hdr-rgb-rg32.ktx,999.0000,0.0045,0.0004,0.5982 +Small,5x5,hdr-rgb-rgb16.ktx,999.0000,0.0045,0.0004,0.5952 +Small,5x5,hdr-rgb-rgb32.ktx,999.0000,0.0045,0.0004,0.6022 +Small,5x5,hdr-rgba-rgba16.ktx,999.0000,0.0045,0.0004,0.5939 +Small,5x5,hdr-rgba-rgba32.ktx,999.0000,0.0045,0.0004,0.5979 +Small,5x5,ldr-rgb-00.png,35.3902,0.0511,0.0442,1.4819 +Small,5x5,ldr-rgb-01.png,36.5553,0.0456,0.0389,1.6859 +Small,5x5,ldr-rgb-02.png,31.1974,0.0398,0.0330,1.9862 +Small,5x5,ldr-rgb-03.png,44.5998,0.0452,0.0388,1.6906 +Small,5x5,ldr-rgb-04.png,37.8369,0.0409,0.0342,1.9187 +Small,5x5,ldr-rgb-05.png,33.6969,0.0514,0.0446,1.4701 +Small,5x5,ldr-rgb-06.png,31.2355,0.0375,0.0306,2.1398 +Small,5x5,ldr-rgb-07.png,36.7265,0.0614,0.0546,1.2012 +Small,5x5,ldr-rgb-08.png,42.4358,0.0445,0.0380,1.7249 +Small,5x5,ldr-rgb-09.png,37.7154,0.0449,0.0383,1.7111 +Small,5x5,ldr-rgb-10.png,40.7599,0.0100,0.0052,3.1034 +Small,5x5,ldr-rgba-00.png,33.1255,0.0553,0.0482,1.3587 +Small,5x5,ldr-rgba-01.png,35.4348,0.0391,0.0322,2.0382 +Small,5x5,ldr-rgba-02.png,31.1872,0.0383,0.0312,2.0977 +Small,5x5,ldr-xy-00.png,37.1442,0.0467,0.0384,1.7049 +Small,5x5,ldr-xy-01.png,41.4542,0.0557,0.0475,1.3805 +Small,5x5,ldr-xy-02.png,49.3313,0.0658,0.0574,1.1419 +Small,5x5,ldrs-rgba-00.png,33.1284,0.0560,0.0490,1.3369 +Small,5x5,ldrs-rgba-01.png,35.4408,0.0397,0.0326,2.0130 +Small,5x5,ldrs-rgba-02.png,31.1882,0.0381,0.0311,2.1091 +Small,6x6,hdr-rgb-00.hdr,27.7238,0.1249,0.0394,1.6634 +Small,6x6,hdr-rgb-r16.ktx,999.0000,0.0044,0.0005,0.5495 +Small,6x6,hdr-rgb-r32.ktx,999.0000,0.0044,0.0004,0.5727 +Small,6x6,hdr-rgb-rg16.ktx,999.0000,0.0043,0.0004,0.6039 +Small,6x6,hdr-rgb-rg32.ktx,999.0000,0.0044,0.0004,0.5982 +Small,6x6,hdr-rgb-rgb16.ktx,999.0000,0.0043,0.0004,0.5926 +Small,6x6,hdr-rgb-rgb32.ktx,999.0000,0.0044,0.0004,0.5845 +Small,6x6,hdr-rgba-rgba16.ktx,999.0000,0.0043,0.0004,0.5965 +Small,6x6,hdr-rgba-rgba32.ktx,999.0000,0.0043,0.0004,0.6009 +Small,6x6,ldr-rgb-00.png,32.6511,0.0544,0.0478,1.3713 +Small,6x6,ldr-rgb-01.png,33.2029,0.0469,0.0403,1.6268 +Small,6x6,ldr-rgb-02.png,27.5566,0.0404,0.0339,1.9330 +Small,6x6,ldr-rgb-03.png,42.5941,0.0374,0.0311,2.1067 +Small,6x6,ldr-rgb-04.png,34.3471,0.0413,0.0347,1.8859 +Small,6x6,ldr-rgb-05.png,30.2883,0.0518,0.0453,1.4474 +Small,6x6,ldr-rgb-06.png,27.6307,0.0392,0.0325,2.0185 +Small,6x6,ldr-rgb-07.png,34.4395,0.0637,0.0571,1.1472 +Small,6x6,ldr-rgb-08.png,40.0725,0.0377,0.0314,2.0904 +Small,6x6,ldr-rgb-09.png,33.8181,0.0433,0.0368,1.7815 +Small,6x6,ldr-rgb-10.png,37.1873,0.0105,0.0060,2.7097 +Small,6x6,ldr-rgba-00.png,30.5153,0.0599,0.0531,1.2348 +Small,6x6,ldr-rgba-01.png,32.2918,0.0426,0.0357,1.8338 +Small,6x6,ldr-rgba-02.png,27.8929,0.0398,0.0328,1.9955 +Small,6x6,ldr-xy-00.png,36.2540,0.0391,0.0310,2.1143 +Small,6x6,ldr-xy-01.png,38.0244,0.0538,0.0457,1.4350 +Small,6x6,ldr-xy-02.png,47.5902,0.0671,0.0589,1.1120 +Small,6x6,ldrs-rgba-00.png,30.5116,0.0600,0.0531,1.2341 +Small,6x6,ldrs-rgba-01.png,32.2979,0.0428,0.0360,1.8188 +Small,6x6,ldrs-rgba-02.png,27.8904,0.0400,0.0330,1.9842 +Small,8x8,hdr-rgb-00.hdr,24.3460,0.1381,0.0508,1.2902 +Small,8x8,hdr-rgb-r16.ktx,999.0000,0.0064,0.0005,0.4741 +Small,8x8,hdr-rgb-r32.ktx,999.0000,0.0062,0.0004,0.5939 +Small,8x8,hdr-rgb-rg16.ktx,999.0000,0.0063,0.0004,0.5939 +Small,8x8,hdr-rgb-rg32.ktx,999.0000,0.0063,0.0004,0.5751 +Small,8x8,hdr-rgb-rgb16.ktx,999.0000,0.0063,0.0004,0.5845 +Small,8x8,hdr-rgb-rgb32.ktx,999.0000,0.0063,0.0004,0.5829 +Small,8x8,hdr-rgba-rgba16.ktx,999.0000,0.0063,0.0004,0.5767 +Small,8x8,hdr-rgba-rgba32.ktx,999.0000,0.0062,0.0004,0.5969 +Small,8x8,ldr-rgb-00.png,28.9786,0.0685,0.0598,1.0958 +Small,8x8,ldr-rgb-01.png,29.0317,0.0575,0.0491,1.3358 +Small,8x8,ldr-rgb-02.png,23.2061,0.0536,0.0449,1.4609 +Small,8x8,ldr-rgb-03.png,39.4355,0.0274,0.0191,3.4231 +Small,8x8,ldr-rgb-04.png,29.7808,0.0509,0.0423,1.5491 +Small,8x8,ldr-rgb-05.png,26.0425,0.0623,0.0538,1.2190 +Small,8x8,ldr-rgb-06.png,23.2542,0.0518,0.0432,1.5153 +Small,8x8,ldr-rgb-07.png,31.2165,0.0749,0.0663,0.9886 +Small,8x8,ldr-rgb-08.png,36.5870,0.0389,0.0306,2.1399 +Small,8x8,ldr-rgb-09.png,29.1509,0.0449,0.0363,1.8069 +Small,8x8,ldr-rgb-10.png,32.3332,0.0144,0.0077,2.1065 +Small,8x8,ldr-rgba-00.png,26.7535,0.0753,0.0666,0.9842 +Small,8x8,ldr-rgba-01.png,28.4484,0.0548,0.0461,1.4210 +Small,8x8,ldr-rgba-02.png,23.9699,0.0509,0.0419,1.5625 +Small,8x8,ldr-xy-00.png,34.2380,0.0464,0.0362,1.8083 +Small,8x8,ldr-xy-01.png,35.3165,0.0474,0.0373,1.7571 +Small,8x8,ldr-xy-02.png,44.6234,0.0590,0.0489,1.3413 +Small,8x8,ldrs-rgba-00.png,26.7544,0.0758,0.0671,0.9774 +Small,8x8,ldrs-rgba-01.png,28.4521,0.0553,0.0465,1.4089 +Small,8x8,ldrs-rgba-02.png,23.9700,0.0512,0.0424,1.5472 +Small,12x12,hdr-rgb-00.hdr,21.0311,0.1698,0.0763,0.8589 +Small,12x12,hdr-rgb-r16.ktx,999.0000,0.0104,0.0006,0.4638 +Small,12x12,hdr-rgb-r32.ktx,999.0000,0.0101,0.0004,0.5820 +Small,12x12,hdr-rgb-rg16.ktx,999.0000,0.0102,0.0004,0.5887 +Small,12x12,hdr-rgb-rg32.ktx,999.0000,0.0102,0.0004,0.5754 +Small,12x12,hdr-rgb-rgb16.ktx,999.0000,0.0102,0.0004,0.5887 +Small,12x12,hdr-rgb-rgb32.ktx,999.0000,0.0103,0.0004,0.5817 +Small,12x12,hdr-rgba-rgba16.ktx,999.0000,0.0103,0.0004,0.5727 +Small,12x12,hdr-rgba-rgba32.ktx,999.0000,0.0102,0.0004,0.5896 +Small,12x12,ldr-rgb-00.png,25.0540,0.0931,0.0803,0.8166 +Small,12x12,ldr-rgb-01.png,25.1449,0.0759,0.0634,1.0342 +Small,12x12,ldr-rgb-02.png,19.2913,0.0844,0.0718,0.9132 +Small,12x12,ldr-rgb-03.png,36.1893,0.0331,0.0206,3.1818 +Small,12x12,ldr-rgb-04.png,24.9923,0.0691,0.0563,1.1633 +Small,12x12,ldr-rgb-05.png,21.7396,0.0848,0.0721,0.9087 +Small,12x12,ldr-rgb-06.png,19.2966,0.0818,0.0690,0.9491 +Small,12x12,ldr-rgb-07.png,27.1152,0.0947,0.0821,0.7981 +Small,12x12,ldr-rgb-08.png,32.5339,0.0414,0.0289,2.2676 +Small,12x12,ldr-rgb-09.png,24.3034,0.0648,0.0523,1.2538 +Small,12x12,ldr-rgb-10.png,28.1786,0.0235,0.0133,1.2243 +Small,12x12,ldr-rgba-00.png,22.7580,0.0983,0.0854,0.7677 +Small,12x12,ldr-rgba-01.png,24.7473,0.0784,0.0656,0.9997 +Small,12x12,ldr-rgba-02.png,20.2061,0.0820,0.0691,0.9486 +Small,12x12,ldr-xy-00.png,30.5347,0.0630,0.0487,1.3465 +Small,12x12,ldr-xy-01.png,32.2811,0.0504,0.0361,1.8137 +Small,12x12,ldr-xy-02.png,40.3051,0.0368,0.0229,2.8627 +Small,12x12,ldrs-rgba-00.png,22.7566,0.0991,0.0863,0.7598 +Small,12x12,ldrs-rgba-01.png,24.7489,0.0787,0.0657,0.9969 +Small,12x12,ldrs-rgba-02.png,20.2062,0.0822,0.0692,0.9472 +Small,3x3x3,ldr-l-00-3.dds,52.3291,0.0325,0.0240,10.9081 +Small,3x3x3,ldr-l-01-3.dds,55.2576,0.0144,0.0094,7.3210 +Small,6x6x6,ldr-l-00-3.dds,33.2763,0.0775,0.0616,4.2547 +Small,6x6x6,ldr-l-01-3.dds,41.7183,0.0263,0.0140,4.9381 diff --git a/Test/astc_dump_binary.py b/Test/astc_dump_binary.py index 89b4ca5..1e83991 100644 --- a/Test/astc_dump_binary.py +++ b/Test/astc_dump_binary.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2021 Arm Limited +# Copyright 2021-2022 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -56,7 +56,7 @@ def run_objdump(binary, symbol): result = sp.run(args, stdout=sp.PIPE, stderr=sp.PIPE, check=True, universal_newlines=True) - funcPattern = re.compile(r"^[0-9a-f]{16} <(.*)\(.*\)>:$") + funcPattern = re.compile(r"^[0-9a-f]{16} <(.*?)\(.*\)>:$") funcLines = [] funcActive = False diff --git a/Test/astc_image_sweep.py b/Test/astc_image_sweep.py index 8c829b3..575a75a 100644 --- a/Test/astc_image_sweep.py +++ b/Test/astc_image_sweep.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2021 Arm Limited +# Copyright 2021-2022 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -16,7 +16,7 @@ # under the License. # ----------------------------------------------------------------------------- """ -A benchmarking sweep helper, which can genrate a performance-vs-quality sweep +A benchmarking sweep helper, which can generate a performance-vs-quality sweep for a single input images. Like other test functionality, this uses structured image directory layouts for determining image settings to pass to the codec. """ diff --git a/Test/astc_minify_test.sh b/Test/astc_minify_test.sh index b027425..27b6f50 100755 --- a/Test/astc_minify_test.sh +++ b/Test/astc_minify_test.sh @@ -1,19 +1,21 @@ #!/bin/bash -BLOCK_SIZE=6x6 -QUALITY=-thorough +GOOD=astcenc-good.exe +BAD=astcenc-avx2.exe +BLOCK_SIZE=4x4 +QUALITY=-fastest -./astcenc/astcenc-avx2-good -tl in.png out-good.png ${BLOCK_SIZE} ${QUALITY} -silent +./bin/${GOOD} -tl in.png out-good.png ${BLOCK_SIZE} ${QUALITY} -silent -./astcenc/astcenc-avx2 -tl in.png out-bad.png ${BLOCK_SIZE} ${QUALITY} -silent +./bin/${BAD} -tl in.png out-bad.png ${BLOCK_SIZE} ${QUALITY} -silent compare out-good.png out-bad.png out-vs-out-diff.png compare in.png out-bad.png out-vs-in-diff.png -./astcenc/astc_test_autoextract ${BLOCK_SIZE} in.png out-good.png out-bad.png in-min.png +./bin/astc_test_autoextract ${BLOCK_SIZE} in.png out-good.png out-bad.png in-min.png -./astcenc/astcenc-avx2-good -tl in-min.png out-min-good.png ${BLOCK_SIZE} ${QUALITY} -silent +./bin/${GOOD} -tl in-min.png out-min-good.png ${BLOCK_SIZE} ${QUALITY} -silent -./astcenc/astcenc-avx2 -tl in-min.png out-min-bad.png ${BLOCK_SIZE} ${QUALITY} -silent +./bin/${BAD} -tl in-min.png out-min-bad.png ${BLOCK_SIZE} ${QUALITY} -silent compare out-min-good.png out-min-bad.png out-min-diff.png diff --git a/Test/astc_profile_valgrind.py b/Test/astc_profile_valgrind.py index 82ed0e9..eb9a82a 100644 --- a/Test/astc_profile_valgrind.py +++ b/Test/astc_profile_valgrind.py @@ -33,23 +33,22 @@ import re import subprocess as sp import sys -def postprocess_cga(logfile, outfile): +def postprocess_cga(lines, outfile): """ Postprocess the output of callgrind_annotate. Args: - logfile (str): The output of callgrind_annotate. + lines ([str]): The output of callgrind_annotate. outfile (str): The output file path to write. """ - pattern = re.compile("^\s*([0-9,]+)\s+Source/(\S+):(\S+)\(.*\).*$") - - lines = logfile.splitlines() + pattern = re.compile("^\s*([0-9,]+)\s+\([ 0-9.]+%\)\s+Source/(\S+):(\S+)\(.*\).*$") totalCost = 0.0 functionTable = [] functionMap = {} for line in lines: + line = line.strip() match = pattern.match(line) if not match: continue @@ -82,13 +81,19 @@ def postprocess_cga(logfile, outfile): function[2] *= 100.0 with open(outfile, "w") as fileHandle: + + totals = 0.0 for function in functionTable: # Omit entries less than 1% load if function[2] < 1: break + totals += function[2] fileHandle.write("%5.2f%% %s\n" % (function[2], function[0])) + fileHandle.write("======\n") + fileHandle.write(f"{totals:5.2f}%\n") + def run_pass(image, noStartup, encoder, blocksize, quality): """ @@ -104,7 +109,7 @@ def run_pass(image, noStartup, encoder, blocksize, quality): Raises: CalledProcessException: Any subprocess failed. """ - binary = "./astcenc/astcenc-%s" % encoder + binary = "./bin/astcenc-%s" % encoder args = ["valgrind", "--tool=callgrind", "--callgrind-out-file=callgrind.txt", binary, "-cl", image, "out.astc", blocksize, quality, "-j", "1"] @@ -112,11 +117,15 @@ def run_pass(image, noStartup, encoder, blocksize, quality): args = ["callgrind_annotate", "callgrind.txt"] ret = sp.run(args, stdout=sp.PIPE, check=True, encoding="utf-8") - postprocess_cga(ret.stdout, "perf_%s.txt" % quality.replace("-", "")) + lines = ret.stdout.splitlines() + with open("perf_%s_cga.txt" % quality.replace("-", ""), "w") as handle: + handle.write("\n".join(lines)) + + postprocess_cga(lines, "perf_%s.txt" % quality.replace("-", "")) if noStartup: args = ["gprof2dot", "--format=callgrind", "--output=out.dot", "callgrind.txt", - "-s", "-z", "compress_block(astcenc_context const&, image_block const&, physical_compressed_block&, compression_working_buffers&)"] + "-s", "-z", "compress_block(astcenc_contexti const&, image_block const&, physical_compressed_block&, compression_working_buffers&)"] else: args = ["gprof2dot", "--format=callgrind", "--output=out.dot", "callgrind.txt", "-s", "-z", "main"] diff --git a/Test/astc_quality_test.py b/Test/astc_quality_test.py index 1d5fda8..6d06419 100644 --- a/Test/astc_quality_test.py +++ b/Test/astc_quality_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2021 Arm Limited +# Copyright 2021-2022 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -100,7 +100,7 @@ def main(): for _ in range(0, repeats): command = [ - "./astcenc/astcenc-avx2", + "./bin/astcenc-avx2", "-tl", "./Test/Images/Kodak/LDR-RGB/ldr-rgb-kodak23.png", "/dev/null", diff --git a/Test/astc_test_competitive.py b/Test/astc_test_competitive.py index 1da4e9c..188f432 100644 --- a/Test/astc_test_competitive.py +++ b/Test/astc_test_competitive.py @@ -30,7 +30,7 @@ LOG_PATTERN = re.compile(r"\s*Coding rate:\s*(.*)\s*MT/s") ISPC_BIN = "./Binaries/ISPC/ispc_astc.exe" ISPC_QUALITY = ["rgba", "rgb"] -ASTC_BIN = "./astcenc/astcenc-avx2" +ASTC_BIN = "./bin/astcenc-avx2" ASTC_QUALITY = ["0", "8", "10", "20", "30", "40", "50", "60"] TEST_BLOCK_SIZES = ["4x4", "6x6", "8x8"] diff --git a/Test/astc_test_functional.py b/Test/astc_test_functional.py index 5aa92e9..c545412 100644 --- a/Test/astc_test_functional.py +++ b/Test/astc_test_functional.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2020-2022 Arm Limited +# Copyright 2020-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -649,7 +649,8 @@ class CLIPTest(CLITestBase): """ Test all valid presets are accepted """ - presets = ["-fastest", "-fast", "-medium", "-thorough", "-exhaustive"] + presets = ["-fastest", "-fast", "-medium", + "-thorough", "-verythorough", "-exhaustive"] imIn = self.get_ref_image_path("LDR", "input", "A") imOut = self.get_tmp_image_path("LDR", "decomp") @@ -680,6 +681,19 @@ class CLIPTest(CLITestBase): if tli.Image.is_format_supported(imgFormat): colIn = tli.Image(imIn).get_colors((7, 7)) colOut = tli.Image(imOut).get_colors((7, 7)) + + # Catch exception and add fallback for tga handling + # having unstable origin in ImageMagick + try: + self.assertColorSame(colIn, colOut) + continue + except AssertionError as ex: + if imgFormat != "tga": + raise ex + + # Try yflipped TGA image + colIn = tli.Image(imIn).get_colors((7, 7)) + colOut = tli.Image(imOut).get_colors((7, 1)) self.assertColorSame(colIn, colOut) def test_valid_uncomp_ldr_output_formats(self): @@ -790,27 +804,6 @@ class CLIPTest(CLITestBase): colOut = tli.Image(imOut2).get_colors((7, 7)) self.assertColorSame(colIn, colOut2) - def test_compress_mask(self): - """ - Test compression of mask textures. - """ - decompFile = self.get_tmp_image_path("LDR", "decomp") - - command = [ - self.binary, "-tl", - "./Test/Images/Small/LDR-RGB/ldr-rgb-10.png", - decompFile, "4x4", "-medium"] - - noMaskdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN)) - - command.append("-mask") - maskdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN)) - - # Note that this test simply asserts that the "-mask" is connected and - # affects the output. We don't test it does something useful; that it - # outside the scope of this test case. - self.assertNotEqual(noMaskdB, maskdB) - def test_compress_normal_psnr(self): """ Test compression of normal textures using PSNR error metrics. @@ -1064,7 +1057,29 @@ class CLIPTest(CLITestBase): # RMSE should get worse (higher) if we reduce search space self.assertGreater(testRMSE, refRMSE) - def test_partition_index_limit(self): + def test_2partition_index_limit(self): + """ + Test partition index limit. + """ + inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png" + decompFile = self.get_tmp_image_path("LDR", "decomp") + + # Compute the basic image without any channel weights + command = [ + self.binary, "-tl", + inputFile, decompFile, "4x4", "-medium"] + + self.exec(command) + refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + command += ["-2partitionindexlimit", "1"] + self.exec(command) + testRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + # RMSE should get worse (higher) if we reduce search space + self.assertGreater(testRMSE, refRMSE) + + def test_3partition_index_limit(self): """ Test partition index limit. """ @@ -1079,7 +1094,29 @@ class CLIPTest(CLITestBase): self.exec(command) refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) - command += ["-partitionindexlimit", "1"] + command += ["-3partitionindexlimit", "1"] + self.exec(command) + testRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + # RMSE should get worse (higher) if we reduce search space + self.assertGreater(testRMSE, refRMSE) + + def test_4partition_index_limit(self): + """ + Test partition index limit. + """ + inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png" + decompFile = self.get_tmp_image_path("LDR", "decomp") + + # Compute the basic image without any channel weights + command = [ + self.binary, "-tl", + inputFile, decompFile, "4x4", "-medium"] + + self.exec(command) + refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + command += ["-4partitionindexlimit", "1"] self.exec(command) testRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) @@ -1238,6 +1275,74 @@ class CLIPTest(CLITestBase): # RMSE should get worse (higher) if we reduce search space self.assertGreater(testRMSE, refRMSE) + def test_2partition_candidate_limit(self): + """ + Test 2 partition partitioning candidate limit. + """ + inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png" + decompFile = self.get_tmp_image_path("LDR", "decomp") + + # Compute the basic image without any channel weights + command = [ + self.binary, "-tl", + inputFile, decompFile, "4x4", "-medium"] + + self.exec(command) + refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + command += ["-2partitioncandidatelimit", "1"] + self.exec(command) + testRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + # RMSE should get worse (higher) if we reduce search space + self.assertGreater(testRMSE, refRMSE) + + def test_3partition_candidate_limit(self): + """ + Test 3 partition partitioning candidate limit. + """ + inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png" + decompFile = self.get_tmp_image_path("LDR", "decomp") + + # Compute the basic image without any channel weights + command = [ + self.binary, "-tl", + inputFile, decompFile, "4x4", "-medium"] + + self.exec(command) + refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + command += ["-3partitioncandidatelimit", "1"] + self.exec(command) + testRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + # RMSE should get worse (higher) if we reduce search space + self.assertGreater(testRMSE, refRMSE) + + def test_4partition_candidate_limit(self): + """ + Test 4 partition partitioning candidate limit. + """ + inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png" + decompFile = self.get_tmp_image_path("LDR", "decomp") + + # Compute the basic image without any channel weights + command = [ + self.binary, "-tl", + inputFile, decompFile, "4x4", "-medium"] + + self.exec(command) + refRMSE = sum(self.get_channel_rmse(inputFile, decompFile)) + + command += ["-4partitioncandidatelimit", "1"] + self.exec(command) + + # RMSE should get worse (higher) if we reduce search space + # Don't check this here, as 4 partitions not used in any Small image + # even for -exhaustive, BUT command line option must be accepted and + # not error ... + # self.assertGreater(testRMSE, refRMSE) + @unittest.skipIf(os.cpu_count() == 1, "Cannot test on single core host") def test_thread_count(self): """ @@ -1298,7 +1403,8 @@ class CLIPTest(CLITestBase): self.exec(command) # Compute the first image using a file-based round-trip - command = [self.binary, "-cl", inputFile, p2CompFile, "4x4", "-medium"] + command = [self.binary, "-cl", inputFile, p2CompFile, "4x4", "-medium", + "-decode_unorm8"] self.exec(command) command = [self.binary, "-dl", p2CompFile, p2DecFile] self.exec(command) @@ -1366,7 +1472,7 @@ class CLINTest(CLITestBase): # If we expected a pass, then rcode == 0 if expectPass: self.assertEqual(rcode, 0, "Exec did not pass as expected") - self.assertNotIn("ERROR", result.stdout) + self.assertNotIn("ERROR", result.stderr) return # If we got a negative that's always bad (signal of some kind) @@ -1376,7 +1482,7 @@ class CLINTest(CLITestBase): # Otherwise just assert that we got an error log, and some positive # return code value was returned - self.assertIn("ERROR", result.stdout) + self.assertIn("ERROR", result.stderr) self.assertGreater(rcode, 0, "Exec did not fail as expected") def exec_with_omit(self, command, startOmit): @@ -1437,7 +1543,7 @@ class CLINTest(CLITestBase): self.binary, "-cl", "./Test/Data/Tiles/ldr.png", self.get_tmp_image_path("LDR", "comp"), - "3x3x3", "-fast", "-array", "3"] + "3x3x3", "-fast", "-zdim", "3"] self.exec(command) @@ -1550,7 +1656,7 @@ class CLINTest(CLITestBase): self.binary, "-cl", "./Test/Data/Tiles/ldr.png", self.get_tmp_image_path("LDR", "comp"), - "4x4", "-fast", "-array", "2"] + "4x4", "-fast", "-zdim", "2"] self.exec(command) @@ -1563,7 +1669,7 @@ class CLINTest(CLITestBase): self.binary, "-cl", "./Test/Data/Tiles/ldr.png", self.get_tmp_image_path("LDR", "comp"), - "4x4x4", "-fast", "-array", "2"] + "4x4x4", "-fast", "-zdim", "2"] # Run the command, incrementally omitting arguments self.exec_with_omit(command, 7) @@ -1733,9 +1839,54 @@ class CLINTest(CLITestBase): # Run the command, incrementally omitting arguments self.exec_with_omit(command, 7) - def test_cl_partitionlimit_missing_args(self): + def test_cl_2partitionindexlimit_missing_args(self): + """ + Test -cl with -2partitionindexlimit and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-2partitionindexlimit", "3"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + def test_cl_3partitionindexlimit_missing_args(self): + """ + Test -cl with -3partitionindexlimit and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-3partitionindexlimit", "3"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + def test_cl_4partitionindexlimit_missing_args(self): + """ + Test -cl with -4partitionindexlimit and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-4partitionindexlimit", "3"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + def test_cl_2partitioncandidatelimit_missing_args(self): """ - Test -cl with -partitionindexlimit and missing arguments. + Test -cl with -2partitioncandidatelimit and missing arguments. """ # Build a valid command command = [ @@ -1743,7 +1894,38 @@ class CLINTest(CLITestBase): self.get_ref_image_path("LDR", "input", "A"), self.get_tmp_image_path("LDR", "comp"), "4x4", "-fast", - "-partitionindexlimit", "3"] + "-2partitioncandidatelimit", "1"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + def test_cl_3partitioncandidatelimit_missing_args(self): + """ + Test -cl with -3partitioncandidatelimit and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-3partitioncandidatelimit", "3"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + + def test_cl_4partitioncandidatelimit_missing_args(self): + """ + Test -cl with -4partitioncandidatelimit and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-4partitioncandidatelimit", "3"] # Run the command, incrementally omitting arguments self.exec_with_omit(command, 7) @@ -1885,6 +2067,50 @@ class CLINTest(CLITestBase): command[blockIndex] = badSwizzle self.exec(command) + def test_cl_ssw_missing_args(self): + """ + Test -cl with -ssw and missing arguments. + """ + # Build a valid command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-ssw", "rgba"] + + # Run the command, incrementally omitting arguments + self.exec_with_omit(command, 7) + + def test_cl_ssw_invalid_swizzle(self): + """ + Test -cl with -ssw and invalid swizzles. + """ + badSwizzles = [ + "", # Short swizzles + "rrrrr", # Long swizzles + ] + + # Create swizzles with all invalid printable ascii codes + good = ["r", "g", "b", "a"] + for channel in string.printable: + if channel not in good: + badSwizzles.append(channel * 4) + + # Build a valid base command + command = [ + self.binary, "-cl", + self.get_ref_image_path("LDR", "input", "A"), + self.get_tmp_image_path("LDR", "comp"), + "4x4", "-fast", + "-ssw", "rgba"] + + blockIndex = command.index("rgba") + for badSwizzle in badSwizzles: + with self.subTest(swizzle=badSwizzle): + command[blockIndex] = badSwizzle + self.exec(command) + def test_dl_dsw_missing_args(self): """ Test -dl with -dsw and missing arguments. diff --git a/Test/astc_test_image.py b/Test/astc_test_image.py index cf9d27b..141b701 100644 --- a/Test/astc_test_image.py +++ b/Test/astc_test_image.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2019-2022 Arm Limited +# Copyright 2019-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -47,10 +47,9 @@ RESULT_THRESHOLD_FAIL = -0.00 RESULT_THRESHOLD_3D_FAIL = -0.00 -TEST_BLOCK_SIZES = ["4x4", "5x5", "6x6", "8x8", "12x12", - "3x3x3", "6x6x6"] +TEST_BLOCK_SIZES = ["4x4", "5x5", "6x6", "8x8", "12x12", "3x3x3", "6x6x6"] -TEST_QUALITIES = ["fastest", "fast", "medium", "thorough"] +TEST_QUALITIES = ["fastest", "fast", "medium", "thorough", "verythorough", "exhaustive"] def is_3d(blockSize): @@ -251,16 +250,9 @@ def get_encoder_params(encoderName, referenceName, imageSet): if encoderName.startswith("ref"): _, version, simd = encoderName.split("-") - # 2.x variants - if version.startswith("2."): - encoder = te.Encoder2xRel(version, simd) - name = f"reference-{version}-{simd}" - outDir = "Test/Images/%s" % imageSet - refName = None - return (encoder, name, outDir, refName) - - # 3.x variants - if version.startswith("3."): + # 2.x, 3.x, and 4.x variants + compatible2xPrefixes = ["2.", "3.", "4."] + if any(True for x in compatible2xPrefixes if version.startswith(x)): encoder = te.Encoder2xRel(version, simd) name = f"reference-{version}-{simd}" outDir = "Test/Images/%s" % imageSet @@ -296,21 +288,22 @@ def parse_command_line(): # All reference encoders refcoders = ["ref-1.7", "ref-2.5-neon", "ref-2.5-sse2", "ref-2.5-sse4.1", "ref-2.5-avx2", - "ref-3.6-neon", "ref-3.6-sse2", "ref-3.6-sse4.1", "ref-3.6-avx2", "ref-3.7-neon", "ref-3.7-sse2", "ref-3.7-sse4.1", "ref-3.7-avx2", + "ref-4.4-neon", "ref-4.4-sse2", "ref-4.4-sse4.1", "ref-4.4-avx2", + "ref-4.5-neon", "ref-4.5-sse2", "ref-4.5-sse4.1", "ref-4.5-avx2", "ref-main-neon", "ref-main-sse2", "ref-main-sse4.1", "ref-main-avx2"] # All test encoders - testcoders = ["none", "neon", "sse2", "sse4.1", "avx2", "native"] - testcodersAArch64 = ["none", "neon", "native"] - testcodersX86 = ["none", "sse2", "sse4.1", "avx2", "native"] + testcoders = ["none", "neon", "sse2", "sse4.1", "avx2", "native", "universal"] + testcodersAArch64 = ["neon"] + testcodersX86 = ["sse2", "sse4.1", "avx2"] coders = refcoders + testcoders + ["all-aarch64", "all-x86"] parser.add_argument("--encoder", dest="encoders", default="avx2", choices=coders, help="test encoder variant") - parser.add_argument("--reference", dest="reference", default="ref-3.7-avx2", + parser.add_argument("--reference", dest="reference", default="ref-main-avx2", choices=refcoders, help="reference encoder variant") astcProfile = ["ldr", "ldrs", "hdr", "all"] @@ -341,7 +334,7 @@ def parse_command_line(): parser.add_argument("--test-image", dest="testImage", default=None, help="select a specific test image from the test set") - choices = list(TEST_QUALITIES) + ["all"] + choices = list(TEST_QUALITIES) + ["all", "all+"] parser.add_argument("--test-quality", dest="testQual", default="thorough", choices=choices, help="select a specific test quality") @@ -365,8 +358,14 @@ def parse_command_line(): else: args.encoders = [args.encoders] - args.testQual = TEST_QUALITIES if args.testQual == "all" \ - else [args.testQual] + if args.testQual == "all+": + args.testQual = TEST_QUALITIES + elif args.testQual == "all": + args.testQual = TEST_QUALITIES + args.testQual.remove("verythorough") + args.testQual.remove("exhaustive") + else: + args.testQual = [args.testQual] if not args.blockSizes or ("all" in args.blockSizes): args.blockSizes = TEST_BLOCK_SIZES @@ -416,16 +415,8 @@ def main(): testSet = tts.TestSet(imageSet, testDir, args.profiles, args.formats, args.testImage) - # The fast and fastest presets are now sufficiently fast that - # the results are noisy without more repeats - testRepeats = args.testRepeats - if quality == "fast" and testRepeats > 1: - testRepeats *= 2 - elif quality == "fastest" and testRepeats > 1: - testRepeats *= 4 - resultSet = run_test_set(encoder, testRef, testSet, quality, - args.blockSizes, testRepeats, + args.blockSizes, args.testRepeats, args.keepOutput, args.threads) resultSet.save_to_file(testRes) @@ -446,3 +437,7 @@ def main(): if __name__ == "__main__": sys.exit(main()) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/Test/astc_test_result_plot.py b/Test/astc_test_result_plot.py index 2195025..7d5fdc6 100644 --- a/Test/astc_test_result_plot.py +++ b/Test/astc_test_result_plot.py @@ -245,7 +245,6 @@ def main(): Returns: int: The process return code. """ - absXMin = 0 absXMax = 80 absXLimits = (absXMin, absXMax) @@ -254,101 +253,147 @@ def main(): relXMax = None relXLimits = (relXMin, relXMax) + last1x = "1.7" + last2x = "2.5" + last3x = "3.7" + prev4x = "4.3" + last4x = "4.4" + lastMain = "main" + charts = [ # -------------------------------------------------------- # Latest in stable series charts [ # Relative scores ["thorough", "medium", "fast"], - ["ref-2.5-avx2", "ref-3.7-avx2"], + [f"ref-{last2x}-avx2", f"ref-{last3x}-avx2", f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-1.7", + f"ref-{last1x}", None, - "relative-stable-series.png", + "results-relative-stable-series.png", (None, None) ], [ # Absolute scores ["thorough", "medium", "fast"], - ["ref-1.7", "ref-2.5-avx2", "ref-3.7-avx2"], + [f"ref-{last1x}", f"ref-{last2x}-avx2", f"ref-{last3x}-avx2", f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], False, None, None, - "absolute-stable-series.png", + "results-absolute-stable-series.png", (absXLimits, None) ], # -------------------------------------------------------- - # Latest 2.x vs 1.7 release charts + # Latest 2.x vs 1.x release charts + [ + # Relative scores + ["thorough", "medium", "fast"], + [f"ref-{last2x}-avx2"], + ["4x4", "6x6", "8x8"], + True, + f"ref-{last1x}", + None, + "results-relative-2.x-vs-1.x.png", + (None, None) + ], + # -------------------------------------------------------- + # Latest 3.x vs 1.x release charts [ # Relative scores ["thorough", "medium", "fast"], - ["ref-2.5-avx2"], + [f"ref-{last3x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-1.7", + f"ref-{last1x}", None, - "relative-2.x-vs-1.x.png", + "results-relative-3.x-vs-1.x.png", (None, None) ], # -------------------------------------------------------- - # Latest 3.x vs 1.7 release charts + # Latest 4.x vs 1.x release charts [ # Relative scores ["thorough", "medium", "fast"], - ["ref-3.7-avx2"], + [f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-1.7", + f"ref-{last1x}", None, - "relative-3.x-vs-1.x.png", + "results-relative-4.x-vs-1.x.png", (None, None) ], # -------------------------------------------------------- - # Latest 3.x vs 2.5 release charts + # Latest 3.x vs 2.x release charts [ # Relative scores ["thorough", "medium", "fast", "fastest"], - ["ref-3.7-avx2"], + [f"ref-{last3x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-2.5-avx2", + f"ref-{last2x}-avx2", None, - "relative-3.x-vs-2.x.png", + "results-relative-3.x-vs-2.x.png", (None, None) ], # -------------------------------------------------------- - # Latest 3.x vs 3.0 release charts + # Latest 4.x vs 3.x release charts [ # Relative scores ["thorough", "medium", "fast", "fastest"], - ["ref-3.7-avx2"], + [f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-3.6-avx2", + f"ref-{last3x}-avx2", None, - "relative-3.x-vs-3.x.png", + "results-relative-4.x-vs-3.x.png", (relXLimits, None), ], [ # Relative ISAs of latest ["thorough", "medium", "fast", "fastest"], - ["ref-3.7-sse4.1", "ref-3.7-avx2"], + [f"ref-{last4x}-sse4.1", f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], True, - "ref-3.7-sse2", + f"ref-{last4x}-sse2", None, - "relative-3.x-isa.png", + "results-relative-4.x-isa.png", (None, None) ], [ # Relative quality of latest ["medium", "fast", "fastest"], - ["ref-3.7-avx2"], + [f"ref-{last4x}-avx2"], ["4x4", "6x6", "8x8"], True, None, "thorough", - "relative-3.x-quality.png", + "results-relative-4.x-quality.png", (None, None) + ], + # -------------------------------------------------------- + # Latest 4.x vs previous 4.x release charts + [ + # Relative scores + ["thorough", "medium", "fast", "fastest"], + [f"ref-{last4x}-avx2"], + ["4x4", "6x6", "8x8"], + True, + f"ref-{prev4x}-avx2", + None, + "results-relative-4.x-vs-4.x.png", + (relXLimits, None) + ], + # -------------------------------------------------------- + # Latest 4.x vs previous 4.x release charts + [ + # Relative scores + ["thorough", "medium", "fast", "fastest"], + [f"ref-{lastMain}-avx2"], + ["4x4", "6x6", "8x8"], + True, + f"ref-{last4x}-avx2", + None, + "results-relative-main-vs-4.x.png", + (relXLimits, None) ] ] diff --git a/Test/astc_update_ref.sh b/Test/astc_update_ref.sh index 0591041..bf6c320 100755 --- a/Test/astc_update_ref.sh +++ b/Test/astc_update_ref.sh @@ -8,7 +8,7 @@ fi echo "Generating new ref-$1 results" if [ "$1" = "main" ]; then - echo "Using binary from ./astcenc/${1}/" + echo "Using binary from ./bin/${1}/" else echo "Using binary from ./Binaries/${1}/" fi @@ -17,6 +17,6 @@ echo "" TARGET_ROOT=${1} -python3 ./Test/astc_test_image.py --test-set Small --block-size all --test-quality all --repeats 5 --encoder ref-$1-avx2 -#python3 ./Test/astc_test_image.py --test-set all --block-size all --test-quality all --repeats 8 --encoder ref-$1-sse4.1 -#python3 ./Test/astc_test_image.py --test-set all --block-size all --test-quality all --repeats 8 --encoder ref-$1-sse2 +python3 ./Test/astc_test_image.py --test-set all --block-size all --test-quality all --repeats 6 --encoder ref-$1-avx2 +#python3 ./Test/astc_test_image.py --test-set all --block-size all --test-quality all --repeats 6 --encoder ref-$1-sse4.1 +#python3 ./Test/astc_test_image.py --test-set all --block-size all --test-quality all --repeats 6 --encoder ref-$1-sse2 diff --git a/Test/testlib/encoder.py b/Test/testlib/encoder.py index 8c46e7b..f0bd089 100644 --- a/Test/testlib/encoder.py +++ b/Test/testlib/encoder.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2019-2022 Arm Limited +# Copyright 2019-2023 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -232,7 +232,6 @@ class EncoderBase(): class Encoder2x(EncoderBase): """ This class wraps the latest `astcenc` 2.x series binaries from main branch. - branch. """ VERSION = "main" @@ -252,11 +251,15 @@ class Encoder2x(EncoderBase): def __init__(self, variant, binary=None): name = "astcenc-%s-%s" % (variant, self.VERSION) + if binary is None: - if os.name == 'nt': - binary = "./astcenc/astcenc-%s.exe" % variant + if variant != "universal": + binary = f"./bin/astcenc-{variant}" else: - binary = "./astcenc/astcenc-%s" % variant + binary = "./bin/astcenc" + + if os.name == 'nt': + binary = f"{binary}.exe" super().__init__(name, variant, binary) @@ -286,9 +289,6 @@ class Encoder2x(EncoderBase): if image.colorFormat == "xy": command.append("-normal") - if image.isMask: - command.append("-mask") - if image.isAlphaScaled: command.append("-a") command.append("1") @@ -327,10 +327,13 @@ class Encoder2xRel(Encoder2x): self.VERSION = version - if os.name == 'nt': - binary = f"./Binaries/{version}/astcenc-{variant}.exe" - else: + if variant != "universal": binary = f"./Binaries/{version}/astcenc-{variant}" + else: + binary = f"./Binaries/{version}/astcenc" + + if os.name == 'nt': + binary = f"{binary}.exe" super().__init__(variant, binary) @@ -390,9 +393,6 @@ class Encoder1_7(EncoderBase): if image.colorProfile == "hdr": command.append("-hdr") - if image.isMask: - command.append("-mask") - if image.isAlphaScaled: command.append("-alphablend") diff --git a/Test/testlib/image.py b/Test/testlib/image.py index 8df5cdd..153de09 100644 --- a/Test/testlib/image.py +++ b/Test/testlib/image.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2019-2020 Arm Limited +# Copyright 2019-2022 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -39,36 +39,6 @@ import testlib.misc as misc CONVERT_BINARY = ["convert"] -g_ConvertVersion = None - - -def get_convert_version(): - """ - Get the major/minor version of ImageMagick on the system. - """ - global g_ConvertVersion - - if g_ConvertVersion is None: - command = list(CONVERT_BINARY) - command += ["--version"] - result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE, - check=True, encoding="utf-8") - - # Version is top row - version = result.stdout.splitlines()[0] - # ... third token - version = re.split(" ", version)[2] - # ... major/minor/patch/subpatch - version = re.split("\\.|-", version) - - numericVersion = float(version[0]) - numericVersion += float(version[1]) / 10.0 - - g_ConvertVersion = numericVersion - - return g_ConvertVersion - - class ImageException(Exception): """ Exception thrown for bad image specification. @@ -89,14 +59,13 @@ class TestImage(): colorFormat: The image color format. name: The image human name. is3D: True if the image is 3D, else False. - isMask: True if the image is a non-correlated mask texture, else False. isAlphaScaled: True if the image wants alpha scaling, else False. TEST_EXTS: Expected test image extensions. PROFILES: Tuple of valid color profile values. FORMATS: Tuple of valid color format values. FLAGS: Map of valid flags (key) and their meaning (value). """ - TEST_EXTS = (".jpg", ".png", ".tga", ".dds", ".hdr") + TEST_EXTS = (".jpg", ".png", ".tga", ".dds", ".hdr", ".ktx") PROFILES = ("ldr", "ldrs", "hdr") @@ -180,7 +149,6 @@ class TestImage(): # Set default values for the optional fields self.is3D = False - self.isMask = False self.isAlphaScaled = False # Decode the flags field if present @@ -195,7 +163,6 @@ class TestImage(): seenFlags.add(flag) self.is3D = "3" in seenFlags - self.isMask = "m" in seenFlags self.isAlphaScaled = "a" in seenFlags def get_size(self): @@ -262,14 +229,6 @@ class Image(): Args: filePath (str): The path to the image on disk. """ - convert = get_convert_version() - - # ImageMagick 7 started to use .tga file origin information. By default - # TGA files store data from bottom up, and define the origin as bottom - # left. We want our color samples to always use a top left origin, even - # if the data is stored in alternative layout. - self.invertYCoords = (convert >= 7.0) and filePath.endswith(".tga") - self.filePath = filePath self.proxyPath = None @@ -301,9 +260,8 @@ class Image(): command = list(CONVERT_BINARY) command += [self.filePath] - # Invert coordinates if the format needs it - if self.invertYCoords: - command += ["-flip"] + # Ensure convert factors in format origin if needed + command += ["-auto-orient"] command += [ "-format", "%%[pixel:p{%u,%u}]" % (x, y), diff --git a/Test/testlib/resultset.py b/Test/testlib/resultset.py index 995d093..9b2fb18 100644 --- a/Test/testlib/resultset.py +++ b/Test/testlib/resultset.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # ----------------------------------------------------------------------------- -# Copyright 2020 Arm Limited +# Copyright 2020-2022 Arm Limited # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -300,7 +300,7 @@ class ResultSet(): if not os.path.exists(dirName): os.makedirs(dirName) - with open(filePath, "w") as csvfile: + with open(filePath, "w", newline="") as csvfile: writer = csv.writer(csvfile) self._save_header(writer) for record in self.records: diff --git a/Utils/Example/CMakeLists.txt b/Utils/Example/CMakeLists.txt index dbc1047..00437b0 100644 --- a/Utils/Example/CMakeLists.txt +++ b/Utils/Example/CMakeLists.txt @@ -19,7 +19,7 @@ cmake_minimum_required(VERSION 3.15) include(ExternalProject) -project(astcencoder_example VERSION 1.0.0) +project(astcencoder_example VERSION 1.1.0) # Add the external project and pull out the project directories we need @@ -28,14 +28,14 @@ project(astcencoder_example VERSION 1.0.0) # SIMD enable to the CMAKE_CACHE_ARGS option to force something specific, but # remember to change the link library in target_link_libraries() to match. # -# * Add "-DISA_SSE2:String=ON" and link against "astcenc-sse2-static" -# * Add "-DISA_SSE41:String=ON" and link against "astcenc-sse4.1-static" -# * Add "-DISA_AVX2:String=ON" and link against "astcenc-avx2-static" -# * Add "-DISA_NEON:String=ON" and link against "astcenc-neon-static" +# * Add "-DASTCENC_ISA_SSE2:String=ON" and link against "astcenc-sse2-static" +# * Add "-DASTCENC_ISA_SSE41:String=ON" and link against "astcenc-sse4.1-static" +# * Add "-DASTCENC_ISA_AVX2:String=ON" and link against "astcenc-avx2-static" +# * Add "-DASTCENC_ISA_NEON:String=ON" and link against "astcenc-neon-static" ExternalProject_Add(astcencoder GIT_REPOSITORY https://github.com/ARM-software/astc-encoder GIT_TAG main - CMAKE_CACHE_ARGS -DCLI:STRING=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + CMAKE_CACHE_ARGS -DASTCENC_CLI:STRING=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} INSTALL_COMMAND "") ExternalProject_Get_property(astcencoder diff --git a/Utils/astc_blend_test.cpp b/Utils/astc_blend_test.cpp new file mode 100644 index 0000000..67d27c3 --- /dev/null +++ b/Utils/astc_blend_test.cpp @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2021 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +// This is a utility tool to test blend modes. + +#include +#include +#include + +#include "astcenc_mathlib.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +/** + * @brief Linearize an sRGB value. + * + * @return The linearized value. + */ +static float srgb_to_linear( + float a +) { + if (a <= 0.04045f) + { + return a * (1.0f / 12.92f); + } + + return powf((a + 0.055f) * (1.0f / 1.055f), 2.4f); +} + +/** + * @brief sRGB gamma-encode a linear value. + * + * @return The gamma encoded value. + */ +static float linear_to_srgb( + float a +) { + if (a <= 0.0031308f) + { + return a * 12.92f; + } + + return 1.055f * powf(a, 1.0f / 2.4f) - 0.055f; +} + +int main(int argc, char **argv) +{ + // Parse command line + if (argc != 6) + { + printf("Usage: astc_blend_test \n"); + exit(1); + } + + const char* src_file = argv[1]; + const char* dst_file = argv[2]; + + bool use_linear = false; + if (!strcmp(argv[3], "linear")) + { + use_linear = true; + } + else if (!strcmp(argv[3], "srgb")) + { + use_linear = false; + } + else + { + printf(" must be either 'linear' or 'srgb'\n"); + exit(1); + } + + bool use_post_blend = false; + if (!strcmp(argv[4], "post")) + { + use_post_blend = true; + } + else if (!strcmp(argv[4], "pre")) + { + use_post_blend = false; + } + else + { + printf(" must be either 'post' or 'pre'\n"); + exit(1); + } + + bool use_filter = false; + if (!strcmp(argv[5], "on")) + { + use_filter = true; + } + else if (!strcmp(argv[5], "off")) + { + use_filter == false; + } + else + { + printf(" must be either 'on' or 'off'\n"); + exit(1); + } + + // Load the input image + int dim_x; + int dim_y; + const uint8_t* data_in = stbi_load(src_file, &dim_x, &dim_y, nullptr, 4); + if (!data_in) + { + printf("ERROR: Failed to load input image.\n"); + exit(1); + } + + // Allocate the output image + uint8_t* data_out = (uint8_t*)malloc(4 * dim_y * dim_x); + if (!data_out) + { + printf("ERROR: Failed to allocate output image.\n"); + exit(1); + } + + // For each pixel apply RGBM encoding + if (!use_filter) + { + for (int y = 0; y < dim_y; y++) + { + const uint8_t* row_in = data_in + (4 * dim_x * y); + uint8_t* row_out = data_out + (4 * dim_x * y); + + for (int x = 0; x < dim_x; x++) + { + const uint8_t* pixel_in = row_in + 4 * x; + uint8_t* pixel_out = row_out + 4 * x; + + float r_src = static_cast(pixel_in[0]) / 255.0f; + float g_src = static_cast(pixel_in[1]) / 255.0f; + float b_src = static_cast(pixel_in[2]) / 255.0f; + float a_src = static_cast(pixel_in[3]) / 255.0f; + + if (use_linear == false) + { + r_src = srgb_to_linear(r_src); + g_src = srgb_to_linear(g_src); + b_src = srgb_to_linear(b_src); + } + + float r_dst = 0.8f; + float g_dst = 1.0f; + float b_dst = 0.8f; + + float r_out; + float g_out; + float b_out; + float a_out; + + // Post-multiply blending + if (use_post_blend) + { + r_out = (r_dst * (1.0f - a_src)) + (r_src * a_src); + g_out = (g_dst * (1.0f - a_src)) + (g_src * a_src); + b_out = (b_dst * (1.0f - a_src)) + (b_src * a_src); + a_out = 1.0f; + } + // Pre-multiply blending + else + { + r_out = (r_dst * (1.0f - a_src)) + (r_src * 1.0f); + g_out = (g_dst * (1.0f - a_src)) + (g_src * 1.0f); + b_out = (b_dst * (1.0f - a_src)) + (b_src * 1.0f); + a_out = 1.0f; + } + + // Clamp color between 0 and 1.0f + r_out = astc::min(r_out, 1.0f); + g_out = astc::min(g_out, 1.0f); + b_out = astc::min(b_out, 1.0f); + + if (use_linear == false) + { + r_out = linear_to_srgb(r_out); + g_out = linear_to_srgb(g_out); + b_out = linear_to_srgb(b_out); + } + + pixel_out[0] = (uint8_t)(r_out * 255.0f); + pixel_out[1] = (uint8_t)(g_out * 255.0f); + pixel_out[2] = (uint8_t)(b_out * 255.0f); + pixel_out[3] = (uint8_t)(a_out * 255.0f); + } + } + } + else + { + for (int y = 0; y < dim_y - 1; y++) + { + const uint8_t* row_in_0 = data_in + (4 * dim_x * y); + const uint8_t* row_in_1 = data_in + (4 * dim_x * (y + 1)); + + uint8_t* row_out = data_out + (4 * (dim_x - 1) * y); + + for (int x = 0; x < dim_x - 1; x++) + { + const uint8_t* pixel_in_00 = row_in_0 + 4 * x; + const uint8_t* pixel_in_01 = row_in_0 + 4 * (x + 1); + const uint8_t* pixel_in_10 = row_in_1 + 4 * x; + const uint8_t* pixel_in_11 = row_in_1 + 4 * (x + 1); + + uint8_t* pixel_out = row_out + 4 * x; + + // Bilinear filter with a half-pixel offset + float r_src = static_cast(pixel_in_00[0] + pixel_in_01[0] + pixel_in_10[0] + pixel_in_11[0]) / (255.0f * 4.0f); + float g_src = static_cast(pixel_in_00[1] + pixel_in_01[1] + pixel_in_10[1] + pixel_in_11[1]) / (255.0f * 4.0f); + float b_src = static_cast(pixel_in_00[2] + pixel_in_01[2] + pixel_in_10[2] + pixel_in_11[2]) / (255.0f * 4.0f); + float a_src = static_cast(pixel_in_00[3] + pixel_in_01[3] + pixel_in_10[3] + pixel_in_11[3]) / (255.0f * 4.0f); + + if (use_linear == false) + { + r_src = srgb_to_linear(r_src); + g_src = srgb_to_linear(g_src); + b_src = srgb_to_linear(b_src); + } + + float r_dst = 0.8f; + float g_dst = 1.0f; + float b_dst = 0.8f; + + float r_out; + float g_out; + float b_out; + float a_out; + + // Post-multiply blending + if (use_post_blend) + { + r_out = (r_dst * (1.0f - a_src)) + (r_src * a_src); + g_out = (g_dst * (1.0f - a_src)) + (g_src * a_src); + b_out = (b_dst * (1.0f - a_src)) + (b_src * a_src); + a_out = 1.0f; + } + // Pre-multiply blending + else + { + r_out = (r_dst * (1.0f - a_src)) + (r_src * 1.0f); + g_out = (g_dst * (1.0f - a_src)) + (g_src * 1.0f); + b_out = (b_dst * (1.0f - a_src)) + (b_src * 1.0f); + a_out = 1.0f; + } + + // Clamp color between 0 and 1.0f + r_out = astc::min(r_out, 1.0f); + g_out = astc::min(g_out, 1.0f); + b_out = astc::min(b_out, 1.0f); + + if (use_linear == false) + { + r_out = linear_to_srgb(r_out); + g_out = linear_to_srgb(g_out); + b_out = linear_to_srgb(b_out); + } + + pixel_out[0] = (uint8_t)(r_out * 255.0f); + pixel_out[1] = (uint8_t)(g_out * 255.0f); + pixel_out[2] = (uint8_t)(b_out * 255.0f); + pixel_out[3] = (uint8_t)(a_out * 255.0f); + } + } + } + + // Write out the result + if (!use_filter) + { + stbi_write_png(dst_file, dim_x, dim_y, 4, data_out, 4 * dim_x); + } + else + { + stbi_write_png(dst_file, dim_x - 1, dim_y - 1, 4, data_out, 4 * (dim_x - 1)); + } + + + return 0; +} diff --git a/Utils/astc_quant_generator.cpp b/Utils/astc_quant_generator.cpp new file mode 100644 index 0000000..ae9b4b0 --- /dev/null +++ b/Utils/astc_quant_generator.cpp @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2023 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +// This is a utility tool to generate quant tables +#include +#include +#include +#include + +/** + * @brief The ASTC quantization methods. + * + * Note, the values here are used directly in the encoding in the format so do not rearrange. + */ +enum quant_method +{ + QUANT_2 = 0, + QUANT_3 = 1, + QUANT_4 = 2, + QUANT_5 = 3, + QUANT_6 = 4, + QUANT_8 = 5, + QUANT_10 = 6, + QUANT_12 = 7, + QUANT_16 = 8, + QUANT_20 = 9, + QUANT_24 = 10, + QUANT_32 = 11, + QUANT_40 = 12, + QUANT_48 = 13, + QUANT_64 = 14, + QUANT_80 = 15, + QUANT_96 = 16, + QUANT_128 = 17, + QUANT_160 = 18, + QUANT_192 = 19, + QUANT_256 = 20 +}; + +static inline unsigned int get_quant_level(quant_method method) +{ + switch (method) + { + case QUANT_2: return 2; + case QUANT_3: return 3; + case QUANT_4: return 4; + case QUANT_5: return 5; + case QUANT_6: return 6; + case QUANT_8: return 8; + case QUANT_10: return 10; + case QUANT_12: return 12; + case QUANT_16: return 16; + case QUANT_20: return 20; + case QUANT_24: return 24; + case QUANT_32: return 32; + case QUANT_40: return 40; + case QUANT_48: return 48; + case QUANT_64: return 64; + case QUANT_80: return 80; + case QUANT_96: return 96; + case QUANT_128: return 128; + case QUANT_160: return 160; + case QUANT_192: return 192; + case QUANT_256: return 256; + } + + // Unreachable - the enum is fully described + return 0; +} + +struct quant_config { + quant_method quant; + unsigned int bits; + unsigned int trits; + unsigned int quints; + unsigned int C; + unsigned int masks[6]; +}; + +const std::array quant_configs {{ + { + QUANT_6, + 1, 1, 0, + 204, + { + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_8, + 3, 0, 0, + 0, + { 0 } + }, { + QUANT_10, + 1, 0, 1, + 113, + { + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_12, + 2, 1, 0, + 93, + { + 0b000000000, + 0b100010110, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_16, + 4, 0, 0, + 0, + { 0 } + }, { + QUANT_20, + 2, 0, 1, + 54, + { + 0b000000000, + 0b100001100, + 0b000000000, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_24, + 3, 1, 0, + 44, + { + 0b000000000, + 0b010000101, + 0b100001010, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_32, + 5, 0, 0, + 0, + { 0 } + }, + { + QUANT_40, + 3, 0, 1, + 26, + { + 0b000000000, + 0b010000010, + 0b100000101, + 0b000000000, + 0b000000000, + 0b000000000 + } + }, { + QUANT_48, + 4, 1, 0, + 22, + { + 0b000000000, + 0b001000001, + 0b010000010, + 0b100000100, + 0b000000000, + 0b000000000 + } + }, { + QUANT_64, + 6, 0, 0, + 0, + { 0 } + }, { + QUANT_80, + 4, 0, 1, + 13, + { + 0b000000000, + 0b001000000, + 0b010000001, + 0b100000010, + 0b000000000, + 0b000000000 + } + }, { + QUANT_96, + 5, 1, 0, + 11, + { + 0b000000000, + 0b000100000, + 0b001000000, + 0b010000001, + 0b100000010, + 0b000000000 + } + }, { + QUANT_128, + 7, 0, 0, + 0, + { 0 } + }, { + QUANT_160, + 5, 0, 1, + 6, + { + 0b000000000, + 0b000100000, + 0b001000000, + 0b010000000, + 0b100000001, + 0b000000000 + } + }, { + QUANT_192, + 6, 1, 0, + 5, + { + 0b000000000, + 0b000010000, + 0b000100000, + 0b001000000, + 0b010000000, + 0b100000001 + } + }, { + QUANT_256, + 8, 0, 0, + 0, + { 0 } + } +}}; + +void generate_unpacked_quant( + const quant_config& config, + std::set& set +) { + unsigned int levels = get_quant_level(config.quant); + unsigned int emitted = 0; + + // Value has 1 trit and N bits + if (config.trits) + { + for (unsigned int D = 0; D < 3; D++) + { + unsigned int max_bits = 1 << config.bits; + for (unsigned int bits = 0; bits < max_bits; bits++) + { + unsigned int A = (bits & 1) * 0b111111111; + unsigned int B = 0; + unsigned int bit = bits; + for (const auto& mask_n: config.masks) + { + unsigned int bit_n = bit & 1; + bit >>= 1; + B += bit_n * mask_n; + } + + unsigned int T = D * config.C + B; + T = T ^ A; + T = (A & 0x80) | (T >> 2); + set.insert(T); + } + } + } + // Value has 1 quint and N bits + else if (config.quints) + { + for (unsigned int D = 0; D < 5; D++) + { + unsigned int max_bits = 1 << config.bits; + for (unsigned int bits = 0; bits < max_bits; bits++) + { + unsigned int A = (bits & 1) * 0b111111111; + unsigned int B = 0; + unsigned int bit = bits; + for (const auto& mask_n: config.masks) + { + unsigned int bit_n = bit & 1; + bit >>= 1; + B += bit_n * mask_n; + } + + unsigned int T = D * config.C + B; + T = T ^ A; + T = (A & 0x80) | (T >> 2); + set.insert(T); + } + } + } + // Value has N bits + else + { + unsigned int max_bits = 1 << config.bits; + for (unsigned int bits = 0; bits < max_bits; bits++) + { + unsigned int T = bits << (8 - config.bits); + int bits_remaining = 8 - config.bits; + + while (bits_remaining > 0) + { + int shift = bits_remaining - config.bits; + bits_remaining -= config.bits; + if (shift > 0) + { + T |= bits << shift; + } + else + { + T |= bits >> -shift; + } + } + set.insert(T); + } + } +} + +void generate_unquant_to_unpacked_quant( + const quant_config& config, + const std::set& set +) { + for (unsigned int i = 0; i < 256; i++) + { + unsigned int min_dist = 256; + unsigned int val_lo = 256; + unsigned int val_hi = 0; + + for (const auto& val: set) + { + unsigned int dist = std::max(i, val) - std::min(i, val); + + if (dist < min_dist) + { + min_dist = dist; + val_lo = val; + val_hi = val; + } + else if (dist == min_dist) + { + val_lo = std::min(val_lo, val); + val_hi = std::max(val_hi, val); + } + } + + if ((i % 16) == 0) + { + printf("\t\t"); + } + + printf("%3u, %3u", val_lo, val_hi); + + if (i != 255) + { + printf(", "); + } + + if ((i % 16) == 15) + { + printf("\n"); + } + } +} + +int main(void) +{ + printf("const uint8_t color_unquant_to_uquant_tables[17][512] {\n"); + for (size_t i = 0; i < quant_configs.size(); i++) + { + const auto& config = quant_configs[i]; + std::set set; + + printf("\t{ // QUANT_%u\n", get_quant_level(config.quant)); + generate_unpacked_quant(config, set); + generate_unquant_to_unpacked_quant(config, set); + printf("\t},\n"); + } + printf("};\n"); + return 0; +} diff --git a/Utils/astcenc_u8_test_bench.cpp b/Utils/astcenc_u8_test_bench.cpp new file mode 100644 index 0000000..b44d695 --- /dev/null +++ b/Utils/astcenc_u8_test_bench.cpp @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: Apache-2.0 +// ---------------------------------------------------------------------------- +// Copyright 2023 Arm Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. +// ---------------------------------------------------------------------------- + +// astcenc doesn't use the top 8 integer bits directly for sRGB RGB components +// or when using the decode_unorm8 decode mode. An alterantive is used which +// allows a common code path to be used. This test program shows that the two +// produce equivalent output once rounded to a decode_unorm8 output. + +// Compile with e.g. clang++ astcenc_u8_test_bench.cpp -o astcenc_u8_test_bench -mavx2 -mf16c + +#define ASTCENC_AVX 2 +#define ASTCENC_F16C 1 +#define ASTCENC_SSE 41 + +#include "../Source/astcenc_mathlib.cpp" +#include "../Source/astcenc_color_unquantize.cpp" +#include "../Source/astcenc_decompress_symbolic.cpp" + +int main() +{ + printf("Decode mode test bench\n"); + + for (int ep0 = 0; ep0 < 256; ep0++) + { + for (int ep1 = 0; ep1 < 256; ep1++) + { + for (int wt1 = 0; wt1 < 65; wt1++) + { + // Validate linear data with decode_unorm8 mode + { + // Expand 8 bit to 16 bit + vint4 weights(wt1); + int ep0_v0 = ep0 * 257; + int ep1_v0 = ep1 * 257; + + // Linear with decode_u8 handling + vmask4 decode_u8_v0(true, true, true, true); + vint4 ep0v0(ep0_v0, ep0_v0, ep0_v0, ep0_v0); + vint4 ep1v0(ep1_v0, ep1_v0, ep1_v0, ep1_v0); + + // Linear without decode_u8 handling + vmask4 decode_u8_v1(false, false, false, false); + vint4 ep0v1(ep0_v0, ep0_v0, ep0_v0, ep0_v0); + vint4 ep1v1(ep1_v0, ep1_v0, ep1_v0, ep1_v0); + + // Lerp both styles + vint4 colorv0 = lerp_color_int(decode_u8_v0, ep0v0, ep1v0, weights); + vint4 colorv1 = lerp_color_int(decode_u8_v1, ep0v1, ep1v1, weights); + + // Validate top 8 integer bits match in both cases + // - Shows that astcenc-style U8 doesn't differ from Khronos-style U8 + vint4 cs0 = lsr<8>(colorv0); + vint4 cs1 = lsr<8>(colorv1); + assert(cs0.lane<0>() == cs1.lane<0>()); + assert(cs0.lane<3>() == cs1.lane<3>()); + + // Validate that astcenc output matches the top 8 integer bits + vfloat4 colorv0f = decode_texel(colorv0, vmask4(false)); + vint4 colorv0_out = float_to_int_rtn(colorv0f * 255.0f); + assert(colorv0_out.lane<0>() == cs0.lane<0>()); + } + + // Validate sRGB data with decode_unorm8 mode + { + // Expand 8 bit to 16 bit + vint4 weights(wt1); + int ep0_v0s = (ep0 << 8) | 0x80; + int ep1_v0s = (ep1 << 8) | 0x80; + int ep0_v0 = ep0 * 257; + int ep1_v0 = ep1 * 257; + + // sRGB RGB and linear A with decode_u8 handling + vmask4 decode_u8_v0(true, true, true, true); + vint4 ep0v0(ep0_v0s, ep0_v0s, ep0_v0s, ep0_v0); + vint4 ep1v0(ep1_v0s, ep1_v0s, ep1_v0s, ep1_v0); + + // sRGB RGB and linear A without decode_u8 handling + vmask4 decode_u8_v1(false, false, false, false); + vint4 ep0v1(ep0_v0s, ep0_v0s, ep0_v0s, ep0_v0); + vint4 ep1v1(ep1_v0s, ep1_v0s, ep1_v0s, ep1_v0); + + // Lerp both styles + vint4 colorv0 = lerp_color_int(decode_u8_v0, ep0v0, ep1v0, weights); + vint4 colorv1 = lerp_color_int(decode_u8_v1, ep0v1, ep1v1, weights); + + // Validate top 8 integer bits match in both cases + // - Shows that astcenc-style U8 doesn't differ from Khronos-style U8 + vint4 cs0 = lsr<8>(colorv0); + vint4 cs1 = lsr<8>(colorv1); + assert(cs0.lane<0>() == cs1.lane<0>()); + assert(cs0.lane<3>() == cs1.lane<3>()); + + // Validate that astcenc output matches the top 8 integer bits + vfloat4 colorv0f = decode_texel(colorv0, vmask4(false)); + vint4 colorv0_out = float_to_int_rtn(colorv0f * 255.0f); + assert(colorv0_out.lane<0>() == cs0.lane<0>()); + } + } + } + } + + return 0; +} diff --git a/bundle.json b/bundle.json index 8d55482..93db4fe 100644 --- a/bundle.json +++ b/bundle.json @@ -1,7 +1,7 @@ { "name": "@ohos/astc-encoder", "description": "This is the official repository for Arm ASTC encoders,which are texture compressors for adaptive extensible texture compression data formats.", - "version": "3.7", + "version": "4.7", "license": "Apache-2.0", "publishAs": "code-segment", "segment":{ diff --git a/jenkins/build-image.sh b/jenkins/build-image.sh index 88c7d2e..5c08758 100755 --- a/jenkins/build-image.sh +++ b/jenkins/build-image.sh @@ -2,7 +2,7 @@ ARTIFACTORY_URL=eu-west-1.artifactory.aws.arm.com DOCKER_REGISTRY=mobile-studio--docker.${ARTIFACTORY_URL} IMAGE_NAME=astcenc -IMAGE_VERSION=3.1.0 +IMAGE_VERSION=3.2.0 # Check Artifactory credentials are set if [[ -z "${ARTIFACTORY_CREDENTIALS}" ]] @@ -18,11 +18,12 @@ rm -fr tmp mkdir -p tmp echo "Get static analysis tools" -curl --user ${ARTIFACTORY_CREDENTIALS} https://${ARTIFACTORY_URL}/artifactory/mobile-studio.tools/coverity/cov-analysis-linux64-2020.12.sh --output tmp/coverity_install.sh -curl --user ${ARTIFACTORY_CREDENTIALS} https://${ARTIFACTORY_URL}/artifactory/mobile-studio.tools/coverity/license.dat --output tmp/coverity_license.dat +curl -L --user ${ARTIFACTORY_CREDENTIALS} https://${ARTIFACTORY_URL}/artifactory/mobile-studio.tools/coverity/cov-analysis-linux64-2023.3.0.sh --output tmp/coverity_install.sh +curl -L --user ${ARTIFACTORY_CREDENTIALS} https://${ARTIFACTORY_URL}/artifactory/mobile-studio.tools/coverity/license.dat --output tmp/coverity_license.dat echo "Building image" -docker build -f jenkins/build.Dockerfile \ +docker build --progress=plain \ + -f jenkins/build.Dockerfile \ -t $IMAGE_NAME:latest \ -t $IMAGE_NAME:$IMAGE_VERSION \ -t $DOCKER_REGISTRY/$IMAGE_NAME:latest \ diff --git a/jenkins/build.Dockerfile b/jenkins/build.Dockerfile index 165ac3e..64793ae 100644 --- a/jenkins/build.Dockerfile +++ b/jenkins/build.Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:22.04 RUN useradd -u 1000 -U -m -c Jenkins jenkins @@ -6,10 +6,10 @@ RUN apt update && apt -y upgrade \ && apt install -y \ software-properties-common \ clang \ - clang++-9 \ gcc \ g++ \ git \ + cmake \ imagemagick \ make \ python3 \ @@ -31,10 +31,3 @@ RUN chmod 555 /tmp/coverity_install.sh && \ /tmp/coverity_install.sh -q --license.region=6 --license.agreement=agree --license.cov.path=/tmp/coverity_license.dat -dir /usr/local/cov-analysis && \ rm /tmp/coverity_* ENV PATH="/usr/local/cov-analysis/bin:$PATH" - -# Install up-to-date CMake, as standard Ubuntu 18.04 package is too old -RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null \ - | gpg --dearmor - > /etc/apt/trusted.gpg.d/kitware.gpg -RUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' -RUN apt-get update -RUN apt-get install -y cmake \ No newline at end of file diff --git a/jenkins/nightly.Jenkinsfile b/jenkins/nightly.Jenkinsfile index 4673591..539cec1 100644 --- a/jenkins/nightly.Jenkinsfile +++ b/jenkins/nightly.Jenkinsfile @@ -41,7 +41,7 @@ pipeline { - name: artifactory-ms-docker containers: - name: astcenc - image: mobile-studio--docker.eu-west-1.artifactory.aws.arm.com/astcenc:3.1.0 + image: mobile-studio--docker.eu-west-1.artifactory.aws.arm.com/astcenc:3.2.0 command: - sleep args: @@ -67,22 +67,22 @@ pipeline { ''' } } - stage('Build R') { + stage('Build R x64') { steps { sh ''' mkdir build_rel cd build_rel - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON -DUNITTEST=ON -DPACKAGE=x64 .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_ISA_NONE=ON -DASTCENC_UNITTEST=ON -DASTCENC_PACKAGE=x64 .. make install package -j4 ''' } } - stage('Build D') { + stage('Build D x64') { steps { sh ''' mkdir build_dbg cd build_dbg - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_ISA_NONE=ON .. make -j4 ''' } @@ -101,6 +101,7 @@ pipeline { python3 ./Test/astc_test_functional.py --encoder=sse2 python3 ./Test/astc_test_functional.py --encoder=sse4.1 python3 ./Test/astc_test_functional.py --encoder=avx2 + python3 ./Test/astc_test_image.py --encoder=none --test-set Small --test-quality medium python3 ./Test/astc_test_image.py --encoder=all-x86 --test-set Small --test-quality medium ''' dir('build_rel') { @@ -121,24 +122,24 @@ pipeline { bat 'git clean -ffdx' } } - stage('Build R') { + stage('Build R x64') { steps { bat ''' - call c:\\progra~2\\micros~1\\2019\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat mkdir build_rel cd build_rel - cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DPACKAGE=x64-cl .. + cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_PACKAGE=x64-cl .. nmake install package ''' } } - stage('Build D') { + stage('Build D x64') { steps { bat ''' - call c:\\progra~2\\micros~1\\2019\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat mkdir build_dbg cd build_dbg - cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Debug -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON .. + cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_ISA_NONE=ON .. nmake ''' } @@ -153,7 +154,7 @@ pipeline { stage('Test') { steps { bat ''' - set Path=c:\\Python38;c:\\Python38\\Scripts;%Path% + set Path=c:\\Python3;c:\\Python3\\Scripts;%Path% call python ./Test/astc_test_image.py --test-set Small --test-quality medium ''' } @@ -171,26 +172,50 @@ pipeline { bat 'git clean -ffdx' } } - stage('Build R') { + stage('Build R x64') { steps { bat ''' - call c:\\progra~2\\micros~1\\2019\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat mkdir build_rel cd build_rel - cmake -G "Visual Studio 16 2019" -T ClangCL -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DPACKAGE=x64-clangcl .. + cmake -G "Visual Studio 17 2022" -T ClangCL -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_PACKAGE=x64-clangcl .. msbuild astcencoder.sln -property:Configuration=Release msbuild PACKAGE.vcxproj -property:Configuration=Release msbuild INSTALL.vcxproj -property:Configuration=Release ''' } } - stage('Build D') { + stage('Build D x64') { steps { bat ''' - call c:\\progra~2\\micros~1\\2019\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat mkdir build_dbg cd build_dbg - cmake -G "Visual Studio 16 2019" -T ClangCL -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON .. + cmake -G "Visual Studio 17 2022" -T ClangCL -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON .. + msbuild astcencoder.sln -property:Configuration=Debug + ''' + } + } + stage('Build R Arm64') { + steps { + bat ''' + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvarsall.bat x64_arm64 + mkdir build_rel_arm64 + cd build_rel_arm64 + cmake -G "Visual Studio 17 2022" -A ARM64 -T ClangCL -DASTCENC_ISA_NEON=ON -DASTCENC_PACKAGE=arm64-clangcl .. + msbuild astcencoder.sln -property:Configuration=Release + msbuild PACKAGE.vcxproj -property:Configuration=Release + msbuild INSTALL.vcxproj -property:Configuration=Release + ''' + } + } + stage('Build D Arm64') { + steps { + bat ''' + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvarsall.bat x64_arm64 + mkdir build_dbg_arm64 + cd build_dbg_arm64 + cmake -G "Visual Studio 17 2022" -A ARM64 -T ClangCL -DASTCENC_ISA_NEON=ON .. msbuild astcencoder.sln -property:Configuration=Debug ''' } @@ -200,12 +225,15 @@ pipeline { dir('build_rel') { stash name: 'astcenc-windows-x64-clangcl', includes: '*.zip' } + dir('build_rel_arm64') { + stash name: 'astcenc-windows-arm64-clangcl', includes: '*.zip' + } } } stage('Test') { steps { bat ''' - set Path=c:\\Python38;c:\\Python38\\Scripts;%Path% + set Path=c:\\Python3;c:\\Python3\\Scripts;%Path% call python ./Test/astc_test_image.py --test-set Small --test-quality medium ''' } @@ -215,7 +243,7 @@ pipeline { /* Build for macOS on x86-64 using Clang */ stage('macOS') { agent { - label 'mac' + label 'mac && x86_64' } stages { stage('Clean') { @@ -228,7 +256,7 @@ pipeline { sh ''' mkdir build_rel cd build_rel - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DPACKAGE=x64 .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_UNIVERSAL_BUILD=OFF -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_PACKAGE=x64 .. make install package -j4 ''' } @@ -238,7 +266,7 @@ pipeline { sh ''' mkdir build_dbg cd build_dbg - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DASTCENC_UNIVERSAL_BUILD=OFF -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_ISA_NONE=ON .. make -j4 ''' } @@ -304,6 +332,9 @@ spec: dir('upload/windows-x64-clangcl') { unstash 'astcenc-windows-x64-clangcl' } + dir('upload/windows-arm64-clangcl') { + unstash 'astcenc-windows-arm64-clangcl' + } dir('upload/macos-x64') { unstash 'astcenc-macos-x64' } diff --git a/jenkins/release.Jenkinsfile b/jenkins/release.Jenkinsfile index 8b815ac..2537469 100644 --- a/jenkins/release.Jenkinsfile +++ b/jenkins/release.Jenkinsfile @@ -43,7 +43,7 @@ spec: - name: artifactory-ms-docker containers: - name: astcenc - image: mobile-studio--docker.eu-west-1.artifactory.aws.arm.com/astcenc:3.1.0 + image: mobile-studio--docker.eu-west-1.artifactory.aws.arm.com/astcenc:3.2.0 command: - sleep args: @@ -73,7 +73,7 @@ spec: mkdir build_cov cd build_cov - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON .. cov-configure --config ${WORKSPACE}/coverity.conf --template --compiler cc --comptype gcc cov-configure --config ${WORKSPACE}/coverity.conf --template --compiler c++ --comptype g++ @@ -127,24 +127,24 @@ spec: sh 'git clean -ffdx' } } - stage('Build astcenc R') { + stage('Build astcenc R x64') { steps { sh ''' export CXX=clang++-9 mkdir build_rel cd build_rel - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON -DPACKAGE=x64 .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_PACKAGE=x64 .. make install package -j4 ''' } } - stage('Build astcdec R') { + stage('Build astcdec R x64') { steps { sh ''' export CXX=clang++-9 mkdir build_reldec cd build_reldec - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DISA_NONE=ON -DDECOMPRESSOR=ON .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_DECOMPRESSOR=ON .. make -j4 ''' } @@ -178,25 +178,63 @@ spec: bat 'git clean -ffdx' } } - stage('Build R') { + stage('Build R x64') { steps { bat ''' - call c:\\progra~2\\micros~1\\2019\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvars64.bat mkdir build_rel cd build_rel - cmake -G "Visual Studio 16 2019" -T ClangCL -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DPACKAGE=x64 .. + cmake -G "Visual Studio 17 2022" -T ClangCL -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_AVX2=ON -DASTCENC_ISA_SSE41=ON -DASTCENC_ISA_SSE2=ON -DASTCENC_PACKAGE=x64 .. + msbuild astcencoder.sln -property:Configuration=Release + msbuild PACKAGE.vcxproj -property:Configuration=Release + msbuild INSTALL.vcxproj -property:Configuration=Release + ''' + } + } + stage('Build R Arm64') { + steps { + bat ''' + call c:\\progra~2\\micros~1\\2022\\buildtools\\vc\\auxiliary\\build\\vcvarsall.bat x64_arm64 + mkdir build_rel_arm64 + cd build_rel_arm64 + cmake -G "Visual Studio 17 2022" -A ARM64 -T ClangCL -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_ISA_NEON=ON -DASTCENC_PACKAGE=arm64 .. msbuild astcencoder.sln -property:Configuration=Release msbuild PACKAGE.vcxproj -property:Configuration=Release msbuild INSTALL.vcxproj -property:Configuration=Release ''' } } + stage('Sign') { + steps { + dir('sign_tools') { + checkout changelog: false, + poll: false, + scm: [$class: 'GitSCM', + branches: [[name: '*/main']], + doGenerateSubmoduleConfigurations: false, + extensions: [], + submoduleCfg: [], + userRemoteConfigs: [[credentialsId: 'gerrit-jenkins-ssh', + url: 'ssh://mirror.eu-west-1.gerrit-eu01.aws.arm.com:29418/Hive/shared/signing']]] + } + withCredentials([usernamePassword(credentialsId: 'cepe-artifactory-jenkins', + usernameVariable: 'AF_USER', + passwordVariable: 'APIKEY')]) { + powershell 'C:\\Python311\\python.exe .\\sign_tools\\windows-client-wrapper.py -b $Env:BUILD_NUMBER -t $Env:APIKEY (Get-ChildItem -Filter build_rel\\*.zip)[0].FullName' + powershell 'C:\\Python311\\python.exe .\\sign_tools\\windows-client-wrapper.py -b $Env:BUILD_NUMBER -t $Env:APIKEY (Get-ChildItem -Filter build_rel_arm64\\*.zip)[0].FullName' + } + } + } stage('Stash') { steps { dir('build_rel') { stash name: 'astcenc-windows-x64', includes: '*.zip' stash name: 'astcenc-windows-x64-hash', includes: '*.zip.sha256' } + dir('build_rel_arm64') { + stash name: 'astcenc-windows-arm64', includes: '*.zip' + stash name: 'astcenc-windows-arm64-hash', includes: '*.zip.sha256' + } } } stage('Test') { @@ -212,7 +250,7 @@ spec: /* Build for macOS on x86-64 using Clang */ stage('macOS') { agent { - label 'mac && notarizer' + label 'mac && x86_64 && notarizer' } stages { stage('Clean') { @@ -225,7 +263,7 @@ spec: sh ''' mkdir build_rel cd build_rel - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_AVX2=ON -DISA_SSE41=ON -DISA_SSE2=ON -DPACKAGE=x64 .. + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DASTCENC_PACKAGE=universal .. make install package -j4 ''' } @@ -249,8 +287,8 @@ spec: stage('Stash') { steps { dir('build_rel') { - stash name: 'astcenc-macos-x64', includes: '*.zip' - stash name: 'astcenc-macos-x64-hash', includes: '*.zip.sha256' + stash name: 'astcenc-macos-universal', includes: '*.zip' + stash name: 'astcenc-macos-universal-hash', includes: '*.zip.sha256' } } } @@ -258,58 +296,10 @@ spec: steps { sh ''' export PATH=/usr/local/bin:$PATH - python3 ./Test/astc_test_image.py --test-set Small - ''' - } - } - } - } - /* Build for macOS on x86-64 using Clang */ - stage('macOS arm64') { - agent { - label 'mac && notarizer' - } - stages { - stage('Clean') { - steps { - sh 'git clean -ffdx' - } - } - stage('Build R') { - steps { - sh ''' - mkdir build_rel - cd build_rel - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../ -DISA_NEON=ON -DPACKAGE=aarch64 .. - make install package -j4 + python3 ./Test/astc_test_image.py --test-set Small --encoder universal ''' } } - stage('Sign and notarize') { - environment { - NOTARIZATION_CREDS = credentials('notarization-account') - } - steps { - dir('build_rel') { - sh 'git clone ssh://eu-gerrit-1.euhpc.arm.com:29418/Hive/shared/signing' - withCredentials([usernamePassword(credentialsId: 'win-signing', - usernameVariable: 'USERNAME', - passwordVariable: 'PASSWORD')]) { - sh 'python3 ./signing/macos-client-wrapper.py ${USERNAME} *.zip' - sh 'rm -rf ./signing' - } - } - } - } - stage('Stash') { - steps { - dir('build_rel') { - stash name: 'astcenc-macos-aarch64', includes: '*.zip' - stash name: 'astcenc-macos-aarch64-hash', includes: '*.zip.sha256' - } - } - } - // TODO: Currently can't test automatically } } } @@ -348,37 +338,16 @@ spec: stage('Unstash') { steps { dir('upload') { + unstash 'astcenc-windows-x64-hash' + unstash 'astcenc-windows-arm64-hash' unstash 'astcenc-linux-x64-hash' - unstash 'astcenc-macos-x64-hash' - unstash 'astcenc-macos-aarch64-hash' + unstash 'astcenc-macos-universal-hash' - unstash 'astcenc-linux-x64' - unstash 'astcenc-macos-x64' - unstash 'astcenc-macos-aarch64' - } - dir('upload/windows-x64') { unstash 'astcenc-windows-x64' - dir('signing') { - checkout changelog: false, - poll: false, - scm: [$class: 'GitSCM', - branches: [[name: '*/master']], - doGenerateSubmoduleConfigurations: false, - extensions: [], - submoduleCfg: [], - userRemoteConfigs: [[credentialsId: 'gerrit-jenkins-ssh', - url: 'ssh://mirror.eu-west-1.gerrit-eu01.aws.arm.com:29418/Hive/shared/signing']]] - } - withCredentials([usernamePassword(credentialsId: 'win-signing', - usernameVariable: 'USERNAME', - passwordVariable: 'PASSWORD')]) { - sh 'python3 ./signing/windows-client-wrapper.py ${USERNAME} *.zip' - sh 'mv *.zip.sha256 ../' - sh 'mv *.zip ../' - } - } - dir('upload') { - sh 'rm -rf ./windows-x64' + unstash 'astcenc-windows-arm64' + unstash 'astcenc-linux-x64' + unstash 'astcenc-macos-universal' + sh 'cat *.sha256 > release-sha256.txt' sh 'rm *.sha256' } @@ -398,11 +367,4 @@ spec: } } } - post { - failure { - script { - slackSend channel: '#dsg-eng-astcenc', color: 'danger', message: "Build ${JOB_NAME} ${BUILD_NUMBER} failed. (<${BUILD_URL}|Open>)", teamDomain: 'arm-dsg', tokenCredentialId: 'jenkins-slack', username: 'jenkins' - } - } - } } -- Gitee

1+YuqVGv+QL1&gg?dLEItd6E?IJZZJe2 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 E7y5nug8%>k diff --git a/Docs/ChangeLogImg/absolute-2.5-to-3.0.png b/Docs/ChangeLogImg/absolute-2.5-to-3.0.png deleted file mode 100644 index b3f702331ca71c6cf81a9acfb43adad522440cce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 136735 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�#fWA)IwM^6o&y=H|iV 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 diff --git a/Docs/ChangeLogImg/relative-1.7-to-2.0.png b/Docs/ChangeLogImg/relative-1.7-to-2.0.png deleted file mode 100644 index 65fe4a489ad903263af52027a9cf1cd25cab9422..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114507 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 z zZ#}(f4s5WS2}{s1`3#E>?H&L1I{G0=a>v)>defM{zZ; z15eQDf=d5;U5kR-;L9-J436783SI;iNPfNu_>@0mmC7Tn@cYzGUhYRr+MvtQ;4-AB ztSN45%TawWvih5(ByK|&Htpvq%1l(O|LF|>zBmy*E-w)|K-T*1-MdE%+q=7tKt20> zjnKbs!S>}3Gm%LN0&OGsu;{;UvRm~?#CK=GBhWR!di!?ZdEvu%Kw64!2~;>MI>?t4_o683t$sKL)QbHKdabl1 zf?Jb7=H#q-nTwu%82AA+!RApsq@br32OL4Ri`}o`ayW{l=+qR0*M(LOzqdcU?mwOt z=*x-w;8P`h26oSSkFxgKx4Y+m{BNsIy8r|%fFb#!UrK5x%p!^e5Y!nIS&ZaK@)NNy zs=*Y%ib=BIT-5oOVM1)i(vt{(6fWe-clPXA5cLTLx;`JcoW>`7@9x8ke=~L1nZ+N! zg6lCpD!Kob@(IvlZn>r#3mz;N9D*$QW1xA&bIZITuyR>U#S$?BGG+hcYf*6v$#Y3cgw)8+cif3%78}utM!s@{MioN=GU#ztH`~ZmLoEDNo zRq~&n1;Xw);4uYJp&+=g&9$a!|_IH{dI(IkFK$KyGs%KdS_&p<7D)Z zbFq2r3QI^$&;+HYYq)OpsATo#zGk32kkB!vW>aM*&aT{6vrw<4{q?YXwJel7cJ#U{ zrMM-3mt#I54QRX{1JM~M%{)IZwCiz(+R+0Xb+kc@6R-$!0flxGu!#Kzau>!&VGu{| z$Oe<2Ab|yP)GP)BH-PkW)E!vS(15@l(*snTR{f5EJQw)s&eQ-!*KZFWo_P!`cPQRy zk0O)4Kv4LsNmtDH($;qRF(}!La?SvwBS05))CI!e;NWpvJ`nu)v|tPCCkj$XXjoWS z%vu$sAPlJi&pRyw-21=;i*cEW$rql7(O@k|!EJsDrM(L14J{X#v;g};w^CYD-Nz+9 z_|+>wJ7uba)94l$_F4D_Vnha>YL5{7<44Ir)P+(w%3gXx02erd>beDV9!N`z_ig3A z`7x6?Ct)ZdRg{tga(i*I z5&fIVk<+@@8XSg_9xnOf325ucIz0spLHe z8WLwZk6*t&dod_`3H4*Jfw0un)ZACUrUVW3o!3J(fWKEkrA{F)7JRr7tY{@`gmL+E z7uW8jaV^=qIebii#AAqZR|Gf;wT9!a>xm+PV;7XbKcHADt;_n$?U;a@cLtaT?cA6( zE&2xqL|?sxn{Pmf|KPtp4(G!21E7U#1!lT1@H+sO^uD~K1-%O|ARF%6%X><9@k*hs zrUArja9Lhq|BQvGaP%baqtsngnfEW)fi^Cjm4QI&2U1xmZ-Yqzr1A%p{(JPODSRyW z4Rkv8fCH8nRIlt2BdZQMu<>$Zk~_Z0ToE&bCxGuT1fsNbMqN))uQ&fbkUOe!`k)>l z6?V%Lz%NR)@ANrR5g>auFNuV>2%s$gabc0{{~c=0HOXdywK@WU{rN=Gv8rewlqY6Z zK`CvPP6tYsE+j{yLYa(yDegtJ@@yNBqWJGPmK#Sn+|}7xx|EGT16&9Kg}}`01Oldx z;0}L0#{LqmsAMl1!A}(YM?Bql_v{BS#)JSPc;iL`!rTR@;CL;^J$4*`bpDg$n|mon zchuXouw~CjB%_q({`VjtEHr^^0y?R%n}GX%S1d}!28=;}`pbLNv*xVJL`P21MsS9< z)B_Rs|G-_(*!hg)fo zZvIzfNG^@s%jo(`>h>e3VV}p#A~~b?(gn6YsE4K5xZ_J40(e~KqyxW`*#(otYL)(if-poMx;8e{pwr3 z3NvJoMq_4ud)c;Ns)$l4>^dVV+T!RYAy#0h=1yT9bQSh@Y|LQ!O(7 z@V{~boE6~Ed;&b4@EnjD`~n3HBOtAYALs&YIBJ3D5>ZEc>FFr;&i|g*AN8C^+*g8u z(B^eO0Nu}vHD2Yse~TBQALF+sozIH{R_)u@mcN{G=O<)_2>d^c$Y`rlS5)-*&Sa`* zsYdp`P%H1%A0JFlzYXfu|6`pX3j;}|m65hDUmk-<%He)rwLS=Npk=C;yoGiEU?=|i zvSgj|U9{M%Z*qzsP(148WTG4{|ApM~b|A#94~-p%s9RL_tZoAh?RxCVp$`$062~S3 zxxayQ4Ddn#@}*jw#qKcWrNjp?)-V&Q{kF##&(6lnu=tPthVl?UO*`T)3zse44uq7% z#KZv*^Z=&TO$3U@7?erEfD7}bka*%+g$L-=fD{Prk9-J#6(Btzv6%KFpcRGO_h+pA zd&%VsOT;1*FK;+>oM&_*fv1lP5GZOzNwWE0U6A%pPcJm?dGOy$%1od06?{hx29KH+s zP%l6fD-vApB_bkms4}6lE`W(z0dzmi2aq4I-~KP)G(ffj;*mGO!_1+|Opp-*et!W< zaICdq>Hj%W0~Uo(>luWN}vjG~20-CeebFM?1=LDtAWJr^Z^Nc!Qvbuv!gFRcKIm z!xVu75RmpjgS0yzG8B|Hh$yIqph4;afaWS1u&9Rsg)JK7A>xqWpaC)KRbUJEfP`Bf zq-4iOXa)IGy5KU;M=vNtpn*^kis%~+b=e)XQ9WR5!Y8prl$20h>{#RQNR)(%2k=Xy zR7h$dhyyM6hp=nOHwc1~jeuC+aSHp-xl#W8jUlrHs0M!<_t#_-#tnf7Q@ZQ-lr+t$ z&USlQ737E7;Z}a_U-MLu1mANtH(O*=TuzCKq9jlFB-xDWwT3+Malrse35(bl%cu4e z6tkPYhO=8i!_T;hF8D8$XP{OWE`#mdZ`JQMUsm`Kr2_+G2Do zeggvr>~x?fMu{A*&cCkLSsSwFi$DTAnF z2szSgM-|#KgZe|dD}4mAZh(8Mf0&FMAxh!)5*3vuLvJ$qk2Db0yKKZ92N(DC>(`L< z{+an`u#kw0i`O+YKxS5Z<(KV%(FKQuz!UsiW^jCe+8tz1>FNDQcx_yz3{K`hl2GX` zdPc_2`UT$7kUuhTbBBU6eW{PP1JpS-BX)ftHye;ZuVMKK3nh*v6~%K=y2}v|5=wm? zDxXDgKOjX0i&7k=pvD!6=K%>UYNqZ1WQOW%KzgrPXVo7LTQlVVhxU2n#I2A#6qbf@ z{P43-tN#mv|8aI6@(OypRMkdY+)*fr6D|^eAR`{=PnR!_drPsrOgF93Fd4agd1#X@wmHpXrb{sPgeu= zZ7aj!5VUrQh6o4+eZ4nQF&o^-adjnsfO&e` ziSY3QwYa2jc;5Lhu3(4cyD+DEe7^kR?biImGaqJB&hb5e)AG>vt=k<-d>$TcJN!38 z@87<~Ur8ubVQL#TfsCADb~ zv=tH_o(5dzCLq-SSSASg<5w%A@j_dO#&OU&yjo^DA+u?^@|ZmzJIs?AL;td`2k)1w zk5A{%M`|0CLd{4|Pme)JNGp&7ls_v$z7QTFUo;24W=~n~YC_UEw4eWoE zdH!@^F#7KU`t7)##OI)3146sAU=ExV9WN(KI0{fBB+*188mBsdveItUX$}kdFwnyW z{pX`l6H7Ubdh%v#jzbbu0Tw~N%YVqCPa8IXXL^w=+XQ}p%hVb@054_?uB*NtWM8hp zWMPNB5J1gc)n1RBJ~+&x>=I^4$q?oal;#l#dptOEo?2iDgM#9w-tWUh3v4BkM)u`s z`-9kx4+jXtR033Yo_>E{;nAby85ZV6yNX|6CvS8giuRV4(yYiS>eR zaYhRZLJA}udLe!20qs2zWP zPHN2lb;#}C$LbL~Feo=0tQ{TLL^$m`u?BJxZd#?f#n!SR^8=q*-KF&#}ehl(-!Chpz=E`W~uYOt~ zYGU!%QAW8xt1KA~r$YH!?U5j_HL#M<(II#G_px2x6V_gKIKN|~*+bz7qMNX@2Q=|7 zXpCw|itx};4 zsfHv0&dA5^_xtBq`p8xu3Lh29MDfG}FnzGUheyM2pBcic%_0FhG+Cf06)(wBcI{RV z7lvB%uf@I=*>33$dfdTbVe^$JlV;-QR|h`&Ua&$=$M56LJ5D8$L&##psmmY1(StL3 z@$U=9IRTkaDun&jBM7J?wq4So&JhOb_SWuHfC)&6xRIQ_%n>Ev)VXpA4Q4VK_Vb@J z856Eeu)-253F498N42ZnDnYYpv2qO5mZ(4nAy$(k{IS{k`6#B(pFeW|=Kqfg@H&9R zC>7$ogq*DGd;68)G^U)2&VyZu?A>s*e8OmYY8a^5nAVzKfA85t!ouZjQ=-ZZN5K!+FkWqu2kA$qFErsHrh&<9tg(&6kG zs`Qdj+8=F%auBsYwV)dJu;q&}Z!Ti@96sFNKZlKf+(vRBIN_F^;fxtTEtn2K_lFxA zLiU2>*N5O>F`8R7_x_J3iGL^VPB(nCII&`n*a96N6G+g=Z$D`)gkAt@JPENo3Qu2A zyKc&6%i)e^f~y_W#6Wv5UPJi%WA0Fcd#-2SSUR@@=3xwg3uG&T0kVF0|2`g=tC!#< z&Oi0{fAh!gLTj3ZlN84(Jd^`y{_^D;CZ*TW0cqn1%++f4jdM z!ypyE2{nvS7k5a%;J|Kwt&!%4B{K~&q#s@ne6xlI<-ab-Mn;m9ib@zj#~dJg9z$e< z-qK*XT?S}DQNR1U-#Xc-pEzC~&S#d65l}^0QZ`CjY^CbJ9FT}pA4+8cZk*UuO;5S%k)!2Erw-yO!X&St#Q{w8-i7m$@4;MRYAP2JB&BtLAk zYoQyA_}`yx$Z%JZ?3e8sG7#MQ@d zxw=S)-MRx(pi`=5zQUJkv}97`L1o~&uSe_u@l;g%IXm{JS5&OaJt}Z}RaZ=*BpMm??mPZ|pL~$_fgpnVFe`(t+t! z4sbXI2Z)>@nk>pidI60#4Kpw>;}*rC9JONRj0S5(D#aG+fRsV&o_g#>H7HE?gqTpA z(bbVke%rKQt8{RmnY4k>FP17_4$d0KwXdW{F83 zi$o`A>M5$I&`a#kMp_g)tZGSgLYP(1&|sEm2C)+G#-OSc_z}cy*lsk~%J`?{=gUDZ1Yl14&*|WETK@>5mv-yZO>t!Mx7=j> z7R@JX-r%er!8hBj468yBea%gtQ36D&dca0PDe-+A1{Q3c+pSa0%HVb2=c6+qA_hyp zn!mZh%~q{x4mz96E$b{U0@M%`SM$L@L7q7pS{BxoZuW8EH`IkmQ3Zil15gQCc_w~a z8dSgD;HhfJ&YUM05d9wp1kd>J;R6E~mr{rxR(;s>H5(nNPr^4sTarM5kN(Dud*&tl zzkb^v@@tt7p`lDyu82ac!F|JqH8ock_S{`+VqyZk5~^bKTwf~1T?Quijju2NQpoKF z=~5a#+b?q^*d!X3o)O#@TDnK5mP>vY_*`%@2&;y6YacnDX6^em4oAN zcg!%$*W53vZnJ2AoCAz=C|3zdf{cv;Q~}#U9-)!b{9~W9&7+R&r zdEst2n9l;yoCT<*E6B+OLTazL+GLNWpSGBURipKPV&~JfuWbWoci^SL7fHg3cYwJo z0APVb>oiEz42lH*NIbTdh!WBJef|Nk?AwZi&k_Q3(%(h)WWU&=lc*^J^omMMegPR; z!hF(vK+>mZs;IC~DZpP7A`#+tzq32q-+ci3&R83PAojnaQvZ`1#AU z$Ca3m`CIZ8l#~Fn{7cjcvpm5Peu1_;V_jAVu;pLz(LG7BKXIR!WVpwgqkw%Vnioev zVI;`k_jrq^~=2ggT^xF2zXf93y)KmhF@BS4pvP~T0 z9{={^cV=d0AdLP?-lWzHQSi?T~P!OzCj|ZH}4Tb#(hvoko?h=#E{h8_{ zBuUkL&pP**6{Y~nu3loqn&tt=+%_rYf)UB)0m%!2sKezMmIdO?40vFALk?vtk zA;Rm1)l{5Jxz!^&L<`y?A*1Rksrx^7&d-cjfc+na@cWm78-(Bd*X;mY%Rm0PjP^Is z1ZWI@&o^1gb?lLxoQ})|E?aQgaj19xfQ-VET!SK z77Of#eoGhJU)enA1hjI!dHvex`;w^JXF*g!0wTDrlEr0@8hR!sdC<@*f{;AOkIr@F z?@2kfH?vwu60j>|-1WgX*xG*=Yw5t}US)17B_;Lk_&wTOAc(r=W0U@0AJbnj-~M`_ z4XyXr5JbM{e5U&SeLc{yBf*kQ5x%+V0GmMoIsW_icdNOW{crwsRezQR3}$ngTk;Xu zzkeF7&F;^Ad>Jjw^3Q4f>;Hf5{8{A;bAbi|EX96mmX>f#}4o-Ek zBhd$1Oem@!T|ULZ5ddmtP=HCb8me}8Cr~_hDi)-Gji3v`c%-}t+B`C#UOO{4ckpb) zWwkN|x+qkDb8T^`BnMDKWSrV%$7pF{d3kvgN`k9bu0*8jTy_L_{~NTxym|Xp3BVWd z&u@VqUGy3!C5dN^i6JpB3x>2V9AHDP5y7V0Ko;AWmscJaV+k_#%Ah{G35wR;OM8%j zgAi;Klmye@IHfg=?Jl(L$bxY6Rb`x0)h}oB9=N$xK@6=dfukWVId75g>TsL}qKL^k zRr?RZ!^6`vGrL#acKE>%`}QIrGch{cT`LDA$s(r>{iKf{=|OPZ$;nAth4+F++YR49 zLMWXg!%E@M`9?Y^wpKKsUFYH6MiGcPqY4+wnsy&hovp41$dV$V*r_Yuc*rBfU&EjM z(1N=OjT1}^3=4kkQ~fGIwfW2~D_0_(*G_!9PviO#dV=_3*+Fd+g1+Lxi`^-jlTFH^ z$eIJMODbq-WkbzdEwUS2Y|om)*Xm>xJ4GG2n- z?-bbH(E?6#Ags!zc-kulTC$dsLbW3G{p=hK&}DZK)b6J+XBNCz-zkFC?2;4edA)#wJ#?lBU2gEo|kvy#xOc* z8Z?wcNi=ll7`o*ZA3chLMq(w4s=Z|Y59ptsK+4eE($WP&q01~-*hX8eI$$$J1&2^b zNrzJ55}ZQzLOVDGLh5qr77P{pzU3>%anzJm%pXu&0-b$5I5E9-~I^Nyj@SS@o`gRCIKx3UW`c zp1yueo&l*xa!_Ps1}x){=4s0|NW?&Fxev8P;N-||b#!FTgog{m(}7D>AR6oj7J~=g zwgyU(fSY?8;XkD3q*Mi{8pSW)%C6cshV3B@Q#CpS24Od3Rs!b`B@Iszb$NMQcU)f{ zKvzk+D?$~3Bsh@z#>NaN=Q=OvHEsezo%iP+eRpldb!P-MZq$8*5vxWjNIg5@STX~e z01+?IPWiu_U4xAw4^v~;bUhRrR^^?c5hwV=ha_k}8{#}Q9>r}o$WaO8J8E!w9nO}K z$TSiHf~lkHeIQxT1D%%8#q}`I78I*ZcE3;TLzyKTIw6gqS#dD;$qOx~8KR*E^r$6p zKXBaL0sU{uF!iZ`yWtMOH@MS?s_?>ZoO;nn?IHzHToGhjZ4Y;?etcz_brLlBUW3($ zcyPDi3z#S+WDMC>n(_ayxikNY`n^q27B2ZZewe^%G~8~!m;=<1~BWx+qGl)hs3Ox_?rdFarmp{T1d4VKH=N!&uG% zN#!!uzV}+b-EDg3D(6j00BzKm68VXZMB>HbSWzE8STy-rCwDc|DIy1qpJri^3wya` z^X4ELd8xt>@{R|#mzy^2=M2rRl>Djcz%Nnq&RS3N=wE*Lb;6|o)#Eo4q8>FJ7xcLZ zhqr5LT00UG$4Bl<32T?HT}!tvT3g{`wqL-pLjaj_g7<~QcR4P%A5h+Q>~Lz|;nbj0 z>>NN5!@d9NN=IK@^O>#Jm{Sol4eiE@NhZDr_6dY~c>y*>FXXpP7qvxA7iZVhmKj?7 zBZ?4#gpj&0o=viM)@}nbHl{DPn$Y5h()OnZ)uHzH~qD?N3)k3nxtU)vSr@P_6*#YjtAy?B;SBKzx(Mf-m>y;lFd|0OEnCKv3j_BwL(!b z*o(R^xVxo7+#hOadp2NDfrqt}e<03LD{mgo6pbIFziBD;XpwQ+WqV|g0?L86ZR#_vpdjZZ{Ggq7Xag9zWPWz^dhVsPnVZLNkY zUCEMrK;HX)wO9DUw9HHmttyOD#bWpny(Yc5;%6%g>$nZ*LO((6t{7ZI^cQYNyFRj8 z8{;hED(| zMs!x*5fP_Fci9!E#ElyPw8Fl=kCQF!JUHshmoEJ%QZ?bBwWXr9Ffy_W1or>BY4_8g zw%OD33^V8g0r2|7NfzRox6+{|Mx{w~kKI-sb^74&7FnuSmUA8}die(WRb)w-&XJlw zuFUvGgtS{@W6$g2!TRN_1=k9JQ!uK-%U7=+vZks`p82jn8Gv5w2nSxHGo|s>B=A=K zVJ<$y`}8sRTE!Rc8nQ{ zKtz4|Qt@lXr_JGmhPNe>QtQC?U3wFvTe+#WGJkGb*1efzy90o%qQ{(N;ewngaNR~4 z-iXe?_DV@1>uQ*5k|V*^Za=xCr>>KD6PA~s-#FAnl~eTh3;XnekI7d{fgw;J_9jhF6H|9^KLy3 zub9tzv{Tw#7A}%{1_(RWIbwNO2*pI)%>l^3#_BH01VabcNRb^kRJnJe`SMg+a7=X- z2sVg%jd%6&@Yt7>l=QHr*jgKY+fbEEG#4?7N~$n&<-n)$yN!gkhC>TiFAix~a4lO} zBVUoBv1>7wz`qKl5WE^7rKdEMX%^+%q4Cbc($CBP6-OQ@5~d^TW7UJbr%t`YK5*54 zj6{<8D(5`K9s*s|GhD=g{bn<#&KfhuTV*>%xJ9={9$^x#+Ulecaz6TbS=xg!P3RiG zumEeMIt>-YnzNU=mi;47>O^+E8a)+ukY{PPHKw_vp|n-g&nmNc1R&@Cek0XQz8kR&w7Tg0MGfqDVUL z|MMBU#5H)~fWZUWjzsMQPc+6J9{#CX%Juf8TRXt_dj(NR$#pTOx0koQLI4jY$BXT| zG(S}LGrAqoYA85at+6RCce_zH{U4K+85zIlbG!uQ*mv1x-ss4R&j3+1+Rk6KieR?q zWrI7R{_4@ctVVAk8hq&_ikM?CYVvKm1wre!S9Liob$1U!?JH7glv-*qE`ZUG$EABG zDMemE&4){5!Mzs?#Ah{B&~=A>=Cg}wH2OFiVsi0tsCX3`>Xib}mHTR>kQ@!7o%nIb zazRG}Tz+0&U&Ib}+sZ_$cqlC`7fG2XJ$*f@=5G;(()0Wfe+{Y6PZs$bb0llv?_(dI zn>ZSm7822Ob}+=CQ;2+!Fdj+fSD;jWH~gBQWxiSRvQYP85=%*a5e)wzqO0hdj@FHj zq)@P5zY`{ckENxhb8Nqgf!my~w^z!9uK5kg+9uQV6#~Z)gQ}>UgV+);!ZsmlZ`l)^ zAPBgylJ3?G^>^knPUa4P`dql3jbYD(908of4UBwp%`p_MoWbr^+|x&DGTBh#XeEVY zI;9WH@mnq~YiTP9Awq5PjP#5Q6%#e@k&!wLJF3j+f;50P_Joaje7o-O4NrIX3A;9M zdZz2m4%B|m0~7CLEEJP_@lm7+QAe=Qgq;&yTLdkVsKb?$XWe7mE~4WxRA z`D?2d^Ma#)d)cFVvmH7egbNX;MZ+3Y%O|LvZ{9YGSEz&8Yhv=A$vXnB fUi|t0dpr`aE2}w{qxjrM9H4BemwU0>M|=Ja{J08< diff --git a/Docs/ChangeLogImg/relative-2.0-to-2.1.png b/Docs/ChangeLogImg/relative-2.0-to-2.1.png deleted file mode 100644 index 40f55feecb175e79b7e69d609e51de273e7318cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122453 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