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

Closed
wants to merge 9 commits into 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
3 changes: 3 additions & 0 deletions include/ktx.h
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,9 @@ ktxTexture2_CompressAstcEx(ktxTexture2* This, ktxAstcParams* params);
KTX_API KTX_error_code KTX_APIENTRY
ktxTexture2_CompressAstc(ktxTexture2* This, ktx_uint32_t quality);

KTX_API KTX_error_code KTX_APIENTRY
ktxTexture2_DecodeAstc(ktxTexture2* This, ktx_uint32_t vkformat);

/**
* @memberof ktxTexture2
* @~English
Expand Down
312 changes: 311 additions & 1 deletion lib/astc_encode.cpp

Large diffs are not rendered by default.

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
114 changes: 8 additions & 106 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 @@ -94,10 +95,11 @@ struct OptionsCreate {

void init(cxxopts::Options& opts) {
opts.add_options()
(kFormat, "KTX format enum that specifies the image data format."
(kFormat, "VkFormat enum that specifies the data format of the images in the output KTX file."
" The enum names are matching the VkFormats without the VK_FORMAT_ prefix."
" The VK_FORMAT_ prefix is ignored if present."
"\nWhen used with --encode it specifies the format of the input files before the encoding step."
"\nWhen used with --encode it specifies the format of the texture object created as input to "
" the encoding step before the encoding step."
" In this case it must be one of:"
"\n R8_UNORM"
"\n R8_SRGB"
Expand Down Expand Up @@ -551,84 +553,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 @@ -659,10 +583,11 @@ Create a KTX2 file from various input files.
The following options are available:
<dl>
<dt>\--format &lt;enum&gt;</dt>
<dd>KTX format enum that specifies the image data format.
<dd>VkFormat enum that specifies the data format of the images in the output KTX file.
The enum names are matching the VkFormats without the VK_FORMAT_ prefix.
The VK_FORMAT_ prefix is ignored if present.<br />
When used with --encode it specifies the format of the input files before the encoding step.
When used with --encode it specifies the format of the texture object created as input
to the encoding step before the encoding step.
In this case it must be one of:
<ul>
<li>R8_UNORM</li>
Expand All @@ -678,30 +603,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
<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