Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Encode astc support #810

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
5 changes: 3 additions & 2 deletions ci_scripts/build_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ cmake_args=("-G" "Xcode" \
"-D" "KTX_FEATURE_TESTS=$FEATURE_TESTS" \
"-D" "KTX_FEATURE_TOOLS=$FEATURE_TOOLS" \
"-D" "KTX_FEATURE_TOOLS_CTS=$FEATURE_TOOLS_CTS" \
"-D" "KTX_LOADTEST_APPS_USE_LOCAL_DEPENDENCIES=$LOADTESTS_USE_LOCAL_DEPENDENCIES"
"-D" "KTX_WERROR=$WERROR"
"-D" "KTX_LOADTEST_APPS_USE_LOCAL_DEPENDENCIES=$LOADTESTS_USE_LOCAL_DEPENDENCIES" \
"-D" "KTX_WERROR=$WERROR" \
"-D" "CMAKE_EXPORT_COMPILE_COMMANDS=ON" \
MarkCallow marked this conversation as resolved.
Show resolved Hide resolved
"-D" "BASISU_SUPPORT_OPENCL=$SUPPORT_OPENCL" \
"-D" "BASISU_SUPPORT_SSE=$SUPPORT_SSE" \
)
Expand Down
1 change: 1 addition & 0 deletions tools/ktx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_executable(ktxtools
command.h
command_create.cpp
command_encode.cpp
command_encode_astc.cpp
command_extract.cpp
command_help.cpp
command_info.cpp
Expand Down
89 changes: 89 additions & 0 deletions tools/ktx/astc_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2022-2023 The Khronos Group Inc.
// Copyright 2022-2023 RasterGrid Kft.
// SPDX-License-Identifier: Apache-2.0

#include "command.h"
#include "utility.h"
#include <thread>

namespace ktx {

struct OptionsASTC : public ktxAstcParams {
inline static const char* kAstcQuality = "astc-quality";
inline static const char* kAstcPerceptual = "astc-perceptual";

std::string astcOptions{};
bool encodeASTC = false;
ClampedOption<ktx_uint32_t> qualityLevel{ktxAstcParams::qualityLevel, 0, KTX_PACK_ASTC_QUALITY_LEVEL_MAX};

OptionsASTC() : ktxAstcParams() {
threadCount = std::thread::hardware_concurrency();
if (threadCount == 0)
threadCount = 1;
structSize = sizeof(ktxAstcParams);
normalMap = false;
for (int i = 0; i < 4; i++)
inputSwizzle[i] = 0;
qualityLevel.clear();
}

void init(cxxopts::Options& opts) {
opts.add_options("Encode ASTC")
(kAstcQuality,
"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. Default "
"is 'medium'. The quality level can be set between fastest (0) and "
"exhaustive (100) via the following fixed quality presets:\n\n"
" Level | Quality\n"
" ---------- | -----------------------------\n"
" fastest | (equivalent to quality = 0)\n"
" fast | (equivalent to quality = 10)\n"
" medium | (equivalent to quality = 60)\n"
" thorough | (equivalent to quality = 98)\n"
" exhaustive | (equivalent to quality = 100)",
cxxopts::value<std::string>(), "<level>")
(kAstcPerceptual,
"The codec should optimize for perceptual error, instead of direct "
"RMS error. This aims to improve perceived image quality, but "
"typically lowers the measured PSNR score. Perceptual methods are "
"currently only available for normal maps and RGB color data.");
}

void captureASTCOption(const char* name) {
astcOptions += fmt::format(" --{}", name);
}

template <typename T>
T captureASTCOption(cxxopts::ParseResult& args, const char* name) {
const T value = args[name].as<T>();
astcOptions += fmt::format(" --{} {}", name, value);
return value;
}

void process(cxxopts::Options&, cxxopts::ParseResult& args, Reporter& report) {
if (args[kAstcQuality].count()) {
static std::unordered_map<std::string, ktx_pack_astc_quality_levels_e> astc_quality_mapping{
{"fastest", KTX_PACK_ASTC_QUALITY_LEVEL_FASTEST},
{"fast", KTX_PACK_ASTC_QUALITY_LEVEL_FAST},
{"medium", KTX_PACK_ASTC_QUALITY_LEVEL_MEDIUM},
{"thorough", KTX_PACK_ASTC_QUALITY_LEVEL_THOROUGH},
{"exhaustive", KTX_PACK_ASTC_QUALITY_LEVEL_EXHAUSTIVE}
};
const auto qualityLevelStr = to_lower_copy(captureASTCOption<std::string>(args, kAstcQuality));
const auto it = astc_quality_mapping.find(qualityLevelStr);
if (it == astc_quality_mapping.end())
report.fatal_usage("Invalid astc-quality: \"{}\"", qualityLevelStr);
qualityLevel = it->second;
} else {
qualityLevel = KTX_PACK_ASTC_QUALITY_LEVEL_MEDIUM;
}

if (args[kAstcPerceptual].count()) {
captureASTCOption(kAstcPerceptual);
perceptual = KTX_TRUE;
}
}
};

} // namespace ktx
79 changes: 1 addition & 78 deletions tools/ktx/command_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <fmt/ostream.h>
#include <fmt/printf.h>
#include "ktx.h"
#include "astc_utils.h"
#include "image.hpp"
#include "imageio.h"

Expand Down Expand Up @@ -551,84 +552,6 @@ struct OptionsCreate {
}
};

struct OptionsASTC : public ktxAstcParams {
inline static const char* kAstcQuality = "astc-quality";
inline static const char* kAstcPerceptual = "astc-perceptual";

std::string astcOptions{};
bool encodeASTC = false;
ClampedOption<ktx_uint32_t> qualityLevel{ktxAstcParams::qualityLevel, 0, KTX_PACK_ASTC_QUALITY_LEVEL_MAX};

OptionsASTC() : ktxAstcParams() {
threadCount = std::thread::hardware_concurrency();
if (threadCount == 0)
threadCount = 1;
structSize = sizeof(ktxAstcParams);
normalMap = false;
for (int i = 0; i < 4; i++)
inputSwizzle[i] = 0;
qualityLevel.clear();
}

void init(cxxopts::Options& opts) {
opts.add_options("Encode ASTC")
(kAstcQuality,
"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. Default "
"is 'medium'. The quality level can be set between fastest (0) and "
"exhaustive (100) via the following fixed quality presets:\n\n"
" Level | Quality\n"
" ---------- | -----------------------------\n"
" fastest | (equivalent to quality = 0)\n"
" fast | (equivalent to quality = 10)\n"
" medium | (equivalent to quality = 60)\n"
" thorough | (equivalent to quality = 98)\n"
" exhaustive | (equivalent to quality = 100)",
cxxopts::value<std::string>(), "<level>")
(kAstcPerceptual,
"The codec should optimize for perceptual error, instead of direct "
"RMS error. This aims to improve perceived image quality, but "
"typically lowers the measured PSNR score. Perceptual methods are "
"currently only available for normal maps and RGB color data.");
}

void captureASTCOption(const char* name) {
astcOptions += fmt::format(" --{}", name);
}

template <typename T>
T captureASTCOption(cxxopts::ParseResult& args, const char* name) {
const T value = args[name].as<T>();
astcOptions += fmt::format(" --{} {}", name, value);
return value;
}

void process(cxxopts::Options&, cxxopts::ParseResult& args, Reporter& report) {
if (args[kAstcQuality].count()) {
static std::unordered_map<std::string, ktx_pack_astc_quality_levels_e> astc_quality_mapping{
{"fastest", KTX_PACK_ASTC_QUALITY_LEVEL_FASTEST},
{"fast", KTX_PACK_ASTC_QUALITY_LEVEL_FAST},
{"medium", KTX_PACK_ASTC_QUALITY_LEVEL_MEDIUM},
{"thorough", KTX_PACK_ASTC_QUALITY_LEVEL_THOROUGH},
{"exhaustive", KTX_PACK_ASTC_QUALITY_LEVEL_EXHAUSTIVE}
};
const auto qualityLevelStr = to_lower_copy(captureASTCOption<std::string>(args, kAstcQuality));
const auto it = astc_quality_mapping.find(qualityLevelStr);
if (it == astc_quality_mapping.end())
report.fatal_usage("Invalid astc-quality: \"{}\"", qualityLevelStr);
qualityLevel = it->second;
} else {
qualityLevel = KTX_PACK_ASTC_QUALITY_LEVEL_MEDIUM;
}

if (args[kAstcPerceptual].count()) {
captureASTCOption(kAstcPerceptual);
perceptual = KTX_TRUE;
}
}
};

// -------------------------------------------------------------------------------------------------

/** @page ktx_create ktx create
Expand Down
Loading
Loading