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
4 changes: 2 additions & 2 deletions ci_scripts/build_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ 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" "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
117 changes: 117 additions & 0 deletions tools/ktx/astc_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// 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 {

/**
//! [command options_astc]
<dl>
Copy link
Collaborator

@MarkCallow MarkCallow Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the <dl> should be here. Is it in the other snippets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In encode_utils.h it has, and from the source c4cc963#diff-8ca48860d1bd768774f38f0f522ba91ef7dbb887e660917c74b7088da850752aL604 where I brought this from, it had it too.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. When this PR is further along we can build the docs and check what it looks like. I'll leave this conversation open to remind us.

<dt>\--astc-quality &lt;level&gt;</dt>
<dd>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:
<table>
<tr><th>Level </th> <th> Quality </th></tr>
<tr><td>fastest </td> <td>(equivalent to quality = 0) </td></tr>
<tr><td>fast </td> <td>(equivalent to quality = 10) </td></tr>
<tr><td>medium </td> <td>(equivalent to quality = 60) </td></tr>
<tr><td>thorough </td> <td>(equivalent to quality = 98) </td></tr>
<tr><td>exhaustive </td> <td>(equivalent to quality = 100) </td></tr>
</table>
</dd>
<dt>\--astc-perceptual</dt>
<dd>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.</dd>
</dl>
//! [command options_astc]
*/
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
104 changes: 2 additions & 102 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 Expand Up @@ -678,30 +601,7 @@ Create a KTX2 file from various input files.
otherwise they are ignored.<br />
The format will be used to verify and load all input files into a texture before encoding.<br />
Case insensitive. Required.</dd>
<dl>
<dt>\--astc-quality &lt;level&gt;</dt>
<dd>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:
<table>
<tr><th>Level </th> <th> Quality </th></tr>
<tr><td>fastest </td> <td>(equivalent to quality = 0) </td></tr>
<tr><td>fast </td> <td>(equivalent to quality = 10) </td></tr>
<tr><td>medium </td> <td>(equivalent to quality = 60) </td></tr>
<tr><td>thorough </td> <td>(equivalent to quality = 98) </td></tr>
<tr><td>exhaustive </td> <td>(equivalent to quality = 100) </td></tr>
</table>
</dd>
<dt>\--astc-perceptual</dt>
<dd>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.</dd>
</dl>
@snippet{doc} ktx/astc_utils.h command options_astc
wasimabbas-arm marked this conversation as resolved.
Show resolved Hide resolved
<dt>\--1d</dt>
<dd>Create a 1D texture. If not set the texture will be a 2D or 3D texture.</dd>
<dt>\--cubemap</dt>
Expand Down
Loading
Loading