Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f557966
Abstract encode common options
wasimabbas-arm Dec 9, 2023
db37f0d
Removes OptionsCodec because these are all just basis options
wasimabbas-arm Dec 9, 2023
4dc1223
Rename EncodeCodec to BasisCodec in preparation for separating encode…
wasimabbas-arm Dec 9, 2023
f77c969
Finally rename the utils file to basis_utils.h
wasimabbas-arm Dec 9, 2023
ca5113d
Updae cts tests part of rebase
wasimabbas-arm Apr 19, 2024
ac7446a
Rename compress_utils.h to deflate_utils.h
wasimabbas-arm Apr 19, 2024
5a43fdf
Rename OptionsCodec to OptionsBasis
wasimabbas-arm Apr 19, 2024
870f2f9
Fix bug, now the program will use ktxBasisParam's noSSE directly
wasimabbas-arm Apr 19, 2024
844705e
Update cts tests
wasimabbas-arm Apr 22, 2024
5de36e7
Rename encode_utils.h to basis_utils.h in doxygen
wasimabbas-arm Apr 23, 2024
f616910
Put noSSE back into common options
wasimabbas-arm Apr 24, 2024
8475985
Fill codec common options separately for astc and basis in create
wasimabbas-arm Apr 25, 2024
dd12a5e
Further changes related to compress to deflate
wasimabbas-arm Apr 26, 2024
b33f540
Move astc options into astc_encode.h
wasimabbas-arm Apr 29, 2024
4595078
Change options_codec to options_codec_basis after changing it in the …
wasimabbas-arm Apr 29, 2024
3691222
Refactor Option names
wasimabbas-arm Apr 29, 2024
8c6cb1d
Fix build issues
wasimabbas-arm Apr 29, 2024
3bc9bfd
Merge branch 'main' into refactor_common_options
wasimabbas-arm Apr 30, 2024
93f6d1f
Rename validateEncodeCodec to validateBasisCodec
wasimabbas-arm Apr 30, 2024
1018e31
Rename captureCodeOption to captureCommonOption
wasimabbas-arm Apr 30, 2024
cf0617e
Documentation adition for no-sse
wasimabbas-arm May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions tools/ktx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ add_executable(ktxtools
command_info.cpp
command_transcode.cpp
command_validate.cpp
compress_utils.h
encode_utils.h
deflate_utils.h
basis_utils.h
format_descriptor.h
formats.h
fragment_uri.h
Expand Down
257 changes: 91 additions & 166 deletions tools/ktx/encode_utils.h → tools/ktx/basis_utils.h

Large diffs are not rendered by default.

28 changes: 16 additions & 12 deletions tools/ktx/command_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
// SPDX-License-Identifier: Apache-2.0

#include "command.h"
#include "encode_utils_common.h"
#include "platform_utils.h"
#include "metrics_utils.h"
#include "compress_utils.h"
#include "encode_utils.h"
#include "deflate_utils.h"
#include "basis_utils.h"
#include "format_descriptor.h"
#include "formats.h"
#include "utility.h"
Expand Down Expand Up @@ -768,7 +769,8 @@ Create a KTX2 file from various input files.
With each encoding option the following encoder specific options become valid,
otherwise they are ignored. Case-insensitive.</dd>

@snippet{doc} ktx/encode_utils.h command options_codec
@snippet{doc} ktx/basis_utils.h command options_codec
@snippet{doc} ktx/encode_utils_common.h command options_codec_common
@snippet{doc} ktx/metrics_utils.h command options_metrics
</dl>
<dl>
Expand Down Expand Up @@ -830,7 +832,7 @@ Create a KTX2 file from various input files.
*/
class CommandCreate : public Command {
private:
Combine<OptionsCreate, OptionsASTC, OptionsCodec<false>, OptionsMetrics, OptionsCompress, OptionsMultiInSingleOut, OptionsGeneric> options;
Combine<OptionsCreate, OptionsASTC, OptionsBasis<false>, OptionsCodecCommon, OptionsMetrics, OptionsCompress, OptionsMultiInSingleOut, OptionsGeneric> options;

uint32_t targetChannelCount = 0; // Derived from VkFormat

Expand All @@ -846,7 +848,7 @@ class CommandCreate : public Command {

private:
void executeCreate();
void encode(KTXTexture2& texture, OptionsCodec<false>& opts);
void encode(KTXTexture2& texture, OptionsBasis<false>& opts);
void encodeASTC(KTXTexture2& texture, OptionsASTC& opts);
void compress(KTXTexture2& texture, const OptionsCompress& opts);

Expand Down Expand Up @@ -895,6 +897,8 @@ void CommandCreate::initOptions(cxxopts::Options& opts) {
void CommandCreate::processOptions(cxxopts::Options& opts, cxxopts::ParseResult& args) {
options.process(opts, args, *this);

fillCodecOptions<decltype(options), ktxBasisParams>(options);

numLevels = options.levels.value_or(1);
numLayers = options.layers.value_or(1);
numFaces = options.cubemap ? 6 : 1;
Expand Down Expand Up @@ -923,15 +927,15 @@ void CommandCreate::processOptions(cxxopts::Options& opts, cxxopts::ParseResult&
fatal_usage("--{} can only be used with ASTC formats.", astcOption);
}

if (options.codec == EncodeCodec::BasisLZ) {
if (options.codec == BasisCodec::BasisLZ) {
if (options.zstd.has_value())
fatal_usage("Cannot encode to BasisLZ and supercompress with Zstd.");

if (options.zlib.has_value())
fatal_usage("Cannot encode to BasisLZ and supercompress with ZLIB.");
}

if (options.codec != EncodeCodec::NONE) {
if (options.codec != BasisCodec::NONE) {
switch (options.vkFormat) {
case VK_FORMAT_R8_UNORM:
case VK_FORMAT_R8_SRGB:
Expand All @@ -950,7 +954,7 @@ void CommandCreate::processOptions(cxxopts::Options& opts, cxxopts::ParseResult&
}
}

const auto canCompare = options.codec == EncodeCodec::BasisLZ || options.codec == EncodeCodec::UASTC;
const auto canCompare = options.codec == BasisCodec::BasisLZ || options.codec == BasisCodec::UASTC;
if (options.compare_ssim && !canCompare)
fatal_usage("--compare-ssim can only be used with BasisLZ or UASTC encoding.");
if (options.compare_psnr && !canCompare)
Expand Down Expand Up @@ -1263,7 +1267,7 @@ void CommandCreate::executeCreate() {
compress(texture, options);

// Add KTXwriterScParams metadata if ASTC encoding, BasisU encoding, or other supercompression was used
const auto writerScParams = fmt::format("{}{}{}", options.astcOptions, options.codecOptions, options.compressOptions);
const auto writerScParams = fmt::format("{}{}{}{}", options.astcOptions, options.codecOptions, options.commonOptions, options.compressOptions);
if (writerScParams.size() > 0) {
// Options always contain a leading space
assert(writerScParams[0] == ' ');
Expand All @@ -1283,12 +1287,12 @@ void CommandCreate::executeCreate() {

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

void CommandCreate::encode(KTXTexture2& texture, OptionsCodec<false>& opts) {
void CommandCreate::encode(KTXTexture2& texture, OptionsBasis<false>& opts) {
MetricsCalculator metrics;
metrics.saveReferenceImages(texture, options, *this);

if (opts.codec != EncodeCodec::NONE) {
auto ret = ktxTexture2_CompressBasisEx(texture, &opts.basisOpts);
if (opts.codec != BasisCodec::NONE) {
auto ret = ktxTexture2_CompressBasisEx(texture, &opts);
if (ret != KTX_SUCCESS)
fatal(rc::KTX_FAILURE, "Failed to encode KTX2 file with codec \"{}\". KTX Error: {}",
to_underlying(opts.codec), ktxErrorString(ret));
Expand Down
2 changes: 1 addition & 1 deletion tools/ktx/command_deflate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "command.h"
#include "platform_utils.h"
#include "compress_utils.h"
#include "deflate_utils.h"
#include "formats.h"
#include "sbufstream.h"
#include "utility.h"
Expand Down
26 changes: 13 additions & 13 deletions tools/ktx/command_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
// SPDX-License-Identifier: Apache-2.0

#include "command.h"
#include "encode_utils_common.h"
#include "platform_utils.h"
#include "metrics_utils.h"
#include "compress_utils.h"
#include "encode_utils.h"
#include "deflate_utils.h"
#include "basis_utils.h"
#include "formats.h"
#include "sbufstream.h"
#include "utility.h"
Expand Down Expand Up @@ -53,7 +54,8 @@ Encode a KTX2 file.
With each encoding option the following encoder specific options become valid,
otherwise they are ignored. Case-insensitive.</dd>

@snippet{doc} ktx/encode_utils.h command options_codec
@snippet{doc} ktx/basis_utils.h command options_codec
@snippet{doc} ktx/encode_utils_common.h command options_codec_common
@snippet{doc} ktx/metrics_utils.h command options_metrics
</dl>
@snippet{doc} ktx/compress_utils.h command options_compress
Expand All @@ -72,16 +74,12 @@ Encode a KTX2 file.
- Daniel Rákos, RasterGrid www.rastergrid.com
*/
class CommandEncode : public Command {
enum {
all = -1,
};

struct OptionsEncode {
void init(cxxopts::Options& opts);
void process(cxxopts::Options& opts, cxxopts::ParseResult& args, Reporter& report);
};

Combine<OptionsEncode, OptionsCodec<true>, OptionsMetrics, OptionsCompress, OptionsSingleInSingleOut, OptionsGeneric> options;
Combine<OptionsEncode, OptionsBasis<true>, OptionsCodecCommon, OptionsMetrics, OptionsCompress, OptionsSingleInSingleOut, OptionsGeneric> options;

public:
virtual int main(int argc, char* argv[]) override;
Expand Down Expand Up @@ -128,15 +126,17 @@ void CommandEncode::initOptions(cxxopts::Options& opts) {
void CommandEncode::processOptions(cxxopts::Options& opts, cxxopts::ParseResult& args) {
options.process(opts, args, *this);

if (options.codec == EncodeCodec::BasisLZ) {
fillCodecOptions<decltype(options), ktxBasisParams>(options);

if (options.codec == BasisCodec::BasisLZ) {
if (options.zstd.has_value())
fatal_usage("Cannot encode to BasisLZ and supercompress with Zstd.");

if (options.zlib.has_value())
fatal_usage("Cannot encode to BasisLZ and supercompress with ZLIB.");
}

const auto canCompare = options.codec == EncodeCodec::BasisLZ || options.codec == EncodeCodec::UASTC;
const auto canCompare = options.codec == BasisCodec::BasisLZ || options.codec == BasisCodec::UASTC;
if (options.compare_ssim && !canCompare)
fatal_usage("--compare-ssim can only be used with BasisLZ or UASTC encoding.");
if (options.compare_psnr && !canCompare)
Expand Down Expand Up @@ -185,14 +185,14 @@ void CommandEncode::executeEncode() {
writer.c_str());

ktx_uint32_t oetf = ktxTexture2_GetOETF(texture);
if (options.basisOpts.normalMap && oetf != KHR_DF_TRANSFER_LINEAR)
if (options.ktxBasisParams::normalMap && oetf != KHR_DF_TRANSFER_LINEAR)
fatal(rc::INVALID_FILE,
"--normal-mode specified but the input file uses non-linear transfer function {}.",
toString(khr_df_transfer_e(oetf)));

MetricsCalculator metrics;
metrics.saveReferenceImages(texture, options, *this);
ret = ktxTexture2_CompressBasisEx(texture, &options.basisOpts);
ret = ktxTexture2_CompressBasisEx(texture, &options);
if (ret != KTX_SUCCESS)
fatal(rc::IO_FAILURE, "Failed to encode KTX2 file with codec \"{}\". KTX Error: {}", ktxErrorString(ret));
metrics.decodeAndCalculateMetrics(texture, options, *this);
Expand All @@ -210,7 +210,7 @@ void CommandEncode::executeEncode() {
}

// Add KTXwriterScParams metadata
const auto writerScParams = fmt::format("{}{}", options.codecOptions, options.compressOptions);
const auto writerScParams = fmt::format("{}{}{}", options.codecOptions, options.commonOptions, options.compressOptions);
ktxHashList_DeleteKVPair(&texture->kvDataHead, KTX_WRITER_SCPARAMS_KEY);
if (writerScParams.size() > 0) {
// Options always contain a leading space
Expand Down
2 changes: 1 addition & 1 deletion tools/ktx/command_transcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "command.h"
#include "platform_utils.h"
#include "compress_utils.h"
#include "deflate_utils.h"
#include "transcode_utils.h"
#include "formats.h"
#include "sbufstream.h"
Expand Down
File renamed without changes.
114 changes: 114 additions & 0 deletions tools/ktx/encode_utils_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2022-2023 The Khronos Group Inc.
// Copyright 2022-2023 RasterGrid Kft.
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "command.h"
#include "utility.h"

#include <thread>
#include <unordered_map>

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

namespace ktx {

/**
//! [command options_codec_common]
<dt>
common:
</dt>
<dd>
Common options.
</dd>

<dl>
<dt>\--normal-mode</dt>
<dd>Only valid for linear textures with two or more components.
If the input texture has three or four linear components it is
assumed to be a three component linear normal map storing unit
length normals as (R=X, G=Y, B=Z). A fourth component will be
ignored. The map will be converted to a two component X+Y
normal map stored as (RGB=X, A=Y) prior to encoding. If unsure
that your normals are unit length, use @b --normalize. If the
input has 2 linear components it is assumed to be an X+Y map
of unit normals.

The Z component can be recovered programmatically in shader
code by using the equations:
<pre>
nml.xy = texture(...).ga; // Load in [0,1]
nml.xy = nml.xy * 2.0 - 1.0; // Unpack to [-1,1]
nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z
</pre>
For ETC1S / BasisLZ encoding, @b '--encode basis-lz', RDO is disabled
(no selector RDO, no endpoint RDO) to provide better quality.</dd>
<dt>\--threads &lt;count&gt;</dt>
<dd>Explicitly set the number of threads to use during
compression. By default, ETC1S / BasisLZ will use the number of
threads reported by thread::hardware_concurrency or 1 if value
returned is 0.</dd>
</dl>
//! [command options_codec_common]
*/
struct OptionsCodecCommon {
inline static const char* kNormalMode = "normal-mode";
inline static const char* kThreads = "threads";

std::string commonOptions{};
bool normalMap{false};
ktx_uint32_t threadCount{1};

OptionsCodecCommon() {
threadCount = std::clamp<ktx_uint32_t>(threadCount, std::thread::hardware_concurrency(), 10000);
}

void init(cxxopts::Options& opts) {
opts.add_options("Encode common")
(kNormalMode, "Optimizes for encoding textures with normal data. If the input texture has "
"three or four linear components it is assumed to be a three component linear normal "
"map storing unit length normals as (R=X, G=Y, B=Z). A fourth component will be ignored. "
"The map will be converted to a two component X+Y normal map stored as (RGB=X, A=Y) "
"prior to encoding. If unsure that your normals are unit length, use --normalize. "
"If the input has 2 linear components it is assumed to be an X+Y map of unit normals.\n"
"The Z component can be recovered programmatically in shader code by using the equations:\n"
" nml.xy = texture(...).ga; // Load in [0,1]\n"
" nml.xy = nml.xy * 2.0 - 1.0; // Unpack to [-1,1]\n"
" nml.z = sqrt(1 - dot(nml.xy, nml.xy)); // Compute Z\n"
"ETC1S / BasisLZ encoding, RDO is disabled (no selector RDO, no endpoint RDO) to provide better quality.")
(kThreads, "Sets the number of threads to use during encoding. By default, encoding "
"will use the number of threads reported by thread::hardware_concurrency or 1 if "
"value returned is 0.", cxxopts::value<uint32_t>(), "<count>");
}

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

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

void process(cxxopts::Options&, cxxopts::ParseResult& args, Reporter&) {
if (args[kNormalMode].count()) {
captureCodecOption(kNormalMode);
normalMap = true;
}

if (args[kThreads].count()) {
threadCount = captureCodecOption<uint32_t>(args, kThreads);
}
}
};

template <typename Options, typename Codec>
void fillCodecOptions(Options &options) {
options.Codec::threadCount = options.OptionsCodecCommon::threadCount;
options.Codec::normalMap = options.OptionsCodecCommon::normalMap;
}

} // namespace ktx