mirror of
https://github.com/drewcassidy/quicktex.git
synced 2024-09-13 06:37:34 +00:00
Header file reorganization
This commit is contained in:
parent
f097f71ba9
commit
abfe0b8d10
@ -12,10 +12,12 @@ find_package(OpenMP)
|
||||
|
||||
add_subdirectory(external/xsimd)
|
||||
include_directories(external/utest)
|
||||
include_directories(quicktex) # include source root for project-relative includes
|
||||
|
||||
# Collect source files
|
||||
file(GLOB SOURCE_FILES
|
||||
"quicktex/*.cpp"
|
||||
"quicktex/util/*.cpp"
|
||||
"quicktex/ctests/*.cpp"
|
||||
"quicktex/s3tc/*.cpp"
|
||||
"quicktex/s3tc/bc1/*.cpp"
|
||||
@ -27,6 +29,7 @@ file(GLOB SOURCE_FILES
|
||||
|
||||
file(GLOB HEADER_FILES
|
||||
"quicktex/*.h"
|
||||
"quicktex/util/*.h"
|
||||
"quicktex/ctests/*.h"
|
||||
"quicktex/s3tc/*.h"
|
||||
"quicktex/s3tc/bc1/*.h"
|
||||
@ -65,7 +68,7 @@ set_simd_flags(_quicktex)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(_quicktex PUBLIC /DWIN32_LEAN_AND_MEAN=1 /DNOMINMAX=1) # prevent windows macros from stepping on everything
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
message("RELEASE FLAGS=${CMAKE_CXX_FLAGS}")
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "Vec.h"
|
||||
#include "bitbash.h"
|
||||
|
||||
namespace quicktex::color {
|
||||
|
||||
|
@ -23,10 +23,13 @@
|
||||
|
||||
#include "Vector4.h"
|
||||
#include "Vector4Int.h"
|
||||
#include "util.h" // for scale_to_8<5>, scale_from_8<5>, assert5bit, scale_to_8<6>
|
||||
#include "util/bitbash.h"
|
||||
#include "util/math.h" // for scale_to_8<5>, scale_from_8<5>, assert5bit, scale_to_8<6>
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
OldColor::OldColor(Vector4Int v) {
|
||||
if (v.MaxAbs() > 0xFF) throw std::invalid_argument("Vector members out of range");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -24,7 +24,8 @@
|
||||
#include <numeric>
|
||||
#include <xsimd/xsimd.hpp>
|
||||
|
||||
#include "util.h"
|
||||
#include "util/math.h"
|
||||
#include "util/types.h"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
|
@ -24,14 +24,16 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ColorBlock.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "util.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace pybind11::detail {
|
||||
using namespace quicktex;
|
||||
@ -85,8 +87,27 @@ template <> struct type_caster<OldColor> {
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
|
||||
using namespace pybind11::literals;
|
||||
|
||||
template <typename... Args> std::string Format(const char* str, const Args&... args) {
|
||||
auto output = std::string(str);
|
||||
|
||||
std::vector<std::string> values = {{args...}};
|
||||
|
||||
for (unsigned i = 0; i < values.size(); i++) {
|
||||
auto key = "{" + std::to_string(i) + "}";
|
||||
auto value = values[i];
|
||||
while (true) {
|
||||
size_t where = output.find(key);
|
||||
if (where == output.npos) break;
|
||||
output.replace(where, key.length(), value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
|
||||
static_assert(std::is_base_of<Texture, T>::value);
|
||||
static_assert(std::is_constructible<T, int, int>::value);
|
||||
@ -95,11 +116,15 @@ template <typename T> T BufferToTexture(py::buffer buf, int width, int height) {
|
||||
auto output = T(width, height);
|
||||
auto dst_size = output.NBytes();
|
||||
|
||||
if (info.format != py::format_descriptor<uint8_t>::format()) throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
|
||||
if (info.size < (Py_ssize_t)dst_size) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
|
||||
if (info.format != py::format_descriptor<uint8_t>::format())
|
||||
throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
|
||||
if (info.size < (Py_ssize_t)dst_size)
|
||||
std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
|
||||
if (info.ndim == 1) {
|
||||
if (info.shape[0] < (Py_ssize_t)dst_size) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
|
||||
if (info.strides[0] != 1) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
|
||||
if (info.shape[0] < (Py_ssize_t)dst_size)
|
||||
throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
|
||||
if (info.strides[0] != 1)
|
||||
throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
|
||||
} else {
|
||||
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");
|
||||
}
|
||||
@ -114,11 +139,15 @@ template <typename T> T BufferToPOD(py::buffer buf) {
|
||||
|
||||
auto info = buf.request(false);
|
||||
|
||||
if (info.format != py::format_descriptor<uint8_t>::format()) throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
|
||||
if (info.size < (Py_ssize_t)sizeof(T)) std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
|
||||
if (info.format != py::format_descriptor<uint8_t>::format())
|
||||
throw std::runtime_error("Incompatible format in python buffer: expected a byte array.");
|
||||
if (info.size < (Py_ssize_t)sizeof(T))
|
||||
std::runtime_error("Incompatible format in python buffer: Input data is smaller than texture size.");
|
||||
if (info.ndim == 1) {
|
||||
if (info.shape[0] < (Py_ssize_t)sizeof(T)) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
|
||||
if (info.strides[0] != 1) throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
|
||||
if (info.shape[0] < (Py_ssize_t)sizeof(T))
|
||||
throw std::runtime_error("Incompatible format in python buffer: 1-D buffer has incorrect length.");
|
||||
if (info.strides[0] != 1)
|
||||
throw std::runtime_error("Incompatible format in python buffer: 1-D buffer is not contiguous.");
|
||||
} else {
|
||||
throw std::runtime_error("Incompatible format in python buffer: Incorrect number of dimensions.");
|
||||
}
|
||||
@ -133,15 +162,18 @@ inline int PyIndex(int val, int size, std::string name = "index") {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T, typename Getter, typename Setter, typename Extent> void DefSubscript(py::class_<T> t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
template <typename T, typename Getter, typename Setter, typename Extent>
|
||||
void DefSubscript(py::class_<T> t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
using V = typename std::invoke_result<Getter, T*, int>::type;
|
||||
t.def(
|
||||
"__getitem__", [get, ext](T& self, int index) { return (self.*get)(PyIndex(index, (self.*ext)())); }, "key"_a);
|
||||
t.def(
|
||||
"__setitem__", [set, ext](T& self, int index, V val) { (self.*set)(PyIndex(index, (self.*ext)()), val); }, "key"_a, "value"_a);
|
||||
"__setitem__", [set, ext](T& self, int index, V val) { (self.*set)(PyIndex(index, (self.*ext)()), val); },
|
||||
"key"_a, "value"_a);
|
||||
}
|
||||
|
||||
template <typename Tpy, typename Getter, typename Setter, typename Extent> void DefSubscript2D(Tpy t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
template <typename Tpy, typename Getter, typename Setter, typename Extent>
|
||||
void DefSubscript2D(Tpy t, Getter&& get, Setter&& set, Extent&& ext) {
|
||||
using T = typename Tpy::type;
|
||||
using V = typename std::invoke_result<Getter, T*, int, int>::type;
|
||||
using Coords = std::tuple<int, int>;
|
||||
@ -184,7 +216,8 @@ template <typename B> py::class_<B> BindBlock(py::module_& m, const char* name)
|
||||
block.def_readonly_static("width", &B::Width, "The width of the block in pixels.");
|
||||
block.def_readonly_static("height", &B::Height, "The height of the block in pixels.");
|
||||
block.def_property_readonly_static(
|
||||
"size", [](py::object) { return std::make_tuple(B::Width, B::Height); }, "The dimensions of the block in pixels.");
|
||||
"size", [](py::object) { return std::make_tuple(B::Width, B::Height); },
|
||||
"The dimensions of the block in pixels.");
|
||||
block.def_property_readonly_static(
|
||||
"nbytes", [](py::object) { return sizeof(B); }, "The size of the block in bytes.");
|
||||
|
||||
@ -223,7 +256,8 @@ template <typename B> py::class_<BlockTexture<B>> BindBlockTexture(py::module_&
|
||||
py::class_<BTex, Texture> block_texture(m, name);
|
||||
|
||||
block_texture.def(py::init<int, int>(), "width"_a, "height"_a, Format(constructor_str, name).c_str());
|
||||
block_texture.def_static("from_bytes", &BufferToTexture<BTex>, "data"_a, "width"_a, "height"_a, Format(from_bytes_str, name).c_str());
|
||||
block_texture.def_static("from_bytes", &BufferToTexture<BTex>, "data"_a, "width"_a, "height"_a,
|
||||
Format(from_bytes_str, name).c_str());
|
||||
|
||||
block_texture.def_property_readonly("width_blocks", &BTex::BlocksX, "The width of the texture in blocks.");
|
||||
block_texture.def_property_readonly("height_blocks", &BTex::BlocksY, "The height of the texture in blocks.");
|
||||
|
@ -26,11 +26,14 @@
|
||||
#include <vector>
|
||||
#include <xsimd/xsimd.hpp>
|
||||
|
||||
#include "../VecUtil.h"
|
||||
#include "../util.h"
|
||||
#include "util/math.h"
|
||||
#include "util/simd.h"
|
||||
#include "util/types.h"
|
||||
|
||||
namespace quicktex::tests {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
template <typename T> constexpr auto make_arrays() {
|
||||
std::vector<std::array<T, xsimd::batch<T>::size>> arrays;
|
||||
std::array<T, xsimd::batch<T>::size> buffer;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <array> // for operator==
|
||||
|
||||
#include "../Vec.h" // for Vec, ope...
|
||||
#include "../util.h" // for abs
|
||||
#include "util/math.h" // for abs
|
||||
|
||||
namespace quicktex::tests {
|
||||
|
||||
|
@ -19,12 +19,16 @@
|
||||
|
||||
#include "BC1Block.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../../util.h"
|
||||
#include "util/ranges.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
uint16_t BC1Block::GetColor0Raw() const { return pack<uint16_t>(_color0, 8); }
|
||||
uint16_t BC1Block::GetColor1Raw() const { return pack<uint16_t>(_color1, 8); }
|
||||
|
||||
@ -32,7 +36,7 @@ void BC1Block::SetColor0Raw(uint16_t c) { _color0 = unpack<uint8_t, EndpointSize
|
||||
void BC1Block::SetColor1Raw(uint16_t c) { _color1 = unpack<uint8_t, EndpointSize>(c, 8); }
|
||||
|
||||
BC1Block::SelectorArray BC1Block::GetSelectors() const {
|
||||
return MapArray(_selectors, [](auto row) { return unpack<uint8_t, Width>(row, SelectorBits); });
|
||||
return map(_selectors, [](auto row) { return unpack<uint8_t, Width>(row, SelectorBits); });
|
||||
}
|
||||
|
||||
void BC1Block::SetSelectors(const BC1Block::SelectorArray& unpacked) {
|
||||
@ -40,7 +44,7 @@ void BC1Block::SetSelectors(const BC1Block::SelectorArray& unpacked) {
|
||||
// if (std::any_of(unpacked[y].begin(), unpacked[y].end(), [](uint8_t i) { return i > SelectorMax; }))
|
||||
// throw std::invalid_argument("Selector value out of bounds.");
|
||||
// }
|
||||
_selectors = MapArray(unpacked, [](auto row) { return pack<uint8_t>(row, SelectorBits, true); });
|
||||
_selectors = map(unpacked, [](auto row) { return pack<uint8_t>(row, SelectorBits, true); });
|
||||
}
|
||||
|
||||
bool BC1Block::operator==(const BC1Block& Rhs) const {
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
|
||||
#include "../../OldColor.h"
|
||||
#include "OldColor.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../OldColor.h"
|
||||
#include "BC1Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "OldColor.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -21,18 +21,19 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC1Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
class BC1Decoder final : public BlockDecoder<BlockTexture<BC1Block>> {
|
||||
public:
|
||||
using InterpolatorPtr = std::shared_ptr<Interpolator>;
|
||||
|
||||
BC1Decoder(bool vwrite_alpha, InterpolatorPtr interpolator) : write_alpha(vwrite_alpha), _interpolator(interpolator) {}
|
||||
BC1Decoder(bool vwrite_alpha, InterpolatorPtr interpolator)
|
||||
: write_alpha(vwrite_alpha), _interpolator(interpolator) {}
|
||||
|
||||
BC1Decoder(bool vwrite_alpha = false) : BC1Decoder(vwrite_alpha, std::make_shared<Interpolator>()) {}
|
||||
|
||||
|
@ -29,21 +29,24 @@
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Matrix4x4.h"
|
||||
#include "../../OldColor.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../../VecUtil.h"
|
||||
#include "../../Vector4.h"
|
||||
#include "../../Vector4Int.h"
|
||||
#include "../../bitwiseEnums.h"
|
||||
#include "../../util.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Histogram.h"
|
||||
#include "OrderTable.h"
|
||||
#include "SingleColorTable.h"
|
||||
#include "Matrix4x4.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "Vector4.h"
|
||||
#include "Vector4Int.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc1/OrderTable.h"
|
||||
#include "s3tc/bc1/SingleColorTable.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/bitwiseEnums.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
// constructors
|
||||
|
||||
BC1Encoder::BC1Encoder(unsigned int level, ColorMode color_mode, InterpolatorPtr interpolator)
|
||||
|
@ -26,13 +26,13 @@
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../../OldColor.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC1Block.h"
|
||||
#include "SingleColorTable.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "OldColor.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc1/SingleColorTable.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace quicktex {
|
||||
class Vector4;
|
||||
@ -79,7 +79,8 @@ class BC1Encoder final : public BlockEncoder<BlockTexture<BC1Block>> {
|
||||
};
|
||||
|
||||
enum class EndpointMode {
|
||||
// Use 2D least squares+inset+optimal rounding (the method used in Humus's GPU texture encoding demo), instead of PCA.
|
||||
// Use 2D least squares+inset+optimal rounding (the method used in Humus's GPU texture encoding demo), instead
|
||||
// of PCA.
|
||||
// Around 18% faster, very slightly lower average quality to better (depends on the content).
|
||||
LeastSquares,
|
||||
|
||||
@ -101,7 +102,8 @@ class BC1Encoder final : public BlockEncoder<BlockTexture<BC1Block>> {
|
||||
|
||||
BC1Encoder(unsigned level, ColorMode color_mode, InterpolatorPtr interpolator);
|
||||
|
||||
BC1Encoder(unsigned int level = 5, ColorMode color_mode = ColorMode::FourColor) : BC1Encoder(level, color_mode, std::make_shared<Interpolator>()) {}
|
||||
BC1Encoder(unsigned int level = 5, ColorMode color_mode = ColorMode::FourColor)
|
||||
: BC1Encoder(level, color_mode, std::make_shared<Interpolator>()) {}
|
||||
|
||||
// Getters and Setters
|
||||
void SetLevel(unsigned level);
|
||||
@ -172,21 +174,26 @@ class BC1Encoder final : public BlockEncoder<BlockTexture<BC1Block>> {
|
||||
BC1Block WriteBlockSolid(OldColor color) const;
|
||||
BC1Block WriteBlock(EncodeResults &result) const;
|
||||
|
||||
void FindEndpoints(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics, EndpointMode endpoint_mode, bool ignore_black = false) const;
|
||||
void FindEndpoints(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics,
|
||||
EndpointMode endpoint_mode, bool ignore_black = false) const;
|
||||
void FindEndpointsSingleColor(EncodeResults &result, OldColor color, bool is_3color = false) const;
|
||||
void FindEndpointsSingleColor(EncodeResults &result, const CBlock &pixels, OldColor color, bool is_3color) const;
|
||||
|
||||
template <ColorMode M> void FindSelectors(EncodeResults &result, const CBlock &pixels, ErrorMode error_mode) const;
|
||||
|
||||
template <ColorMode M> bool RefineEndpointsLS(EncodeResults &result, const CBlock &pixels, BlockMetrics metrics) const;
|
||||
|
||||
template <ColorMode M> void RefineEndpointsLS(EncodeResults &result, std::array<Vector4, 17> &sums, Vector4 &matrix, Hash hash) const;
|
||||
template <ColorMode M>
|
||||
bool RefineEndpointsLS(EncodeResults &result, const CBlock &pixels, BlockMetrics metrics) const;
|
||||
|
||||
template <ColorMode M>
|
||||
void RefineBlockLS(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics, ErrorMode error_mode, unsigned passes) const;
|
||||
void RefineEndpointsLS(EncodeResults &result, std::array<Vector4, 17> &sums, Vector4 &matrix, Hash hash) const;
|
||||
|
||||
template <ColorMode M>
|
||||
void RefineBlockCF(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics, ErrorMode error_mode, unsigned orderings) const;
|
||||
void RefineBlockLS(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics, ErrorMode error_mode,
|
||||
unsigned passes) const;
|
||||
|
||||
template <ColorMode M>
|
||||
void RefineBlockCF(EncodeResults &result, const CBlock &pixels, const BlockMetrics &metrics, ErrorMode error_mode,
|
||||
unsigned orderings) const;
|
||||
|
||||
void EndpointSearch(EncodeResults &result, const CBlock &pixels) const;
|
||||
};
|
||||
|
@ -27,10 +27,10 @@
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
|
||||
#include "../../Vector4.h"
|
||||
#include "../../util.h"
|
||||
#include "Vector4.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
namespace quicktex::s3tc {
|
||||
template <size_t N> class Histogram {
|
||||
public:
|
||||
using Hash = uint16_t;
|
||||
@ -71,7 +71,7 @@ template <size_t N> class Histogram {
|
||||
unsigned GetPacked() const {
|
||||
Hash packed = 0;
|
||||
|
||||
for (unsigned i = 0; i < (N-1); i++) {
|
||||
for (unsigned i = 0; i < (N - 1); i++) {
|
||||
assert(_bins[i] <= (1U << 4) - 1U);
|
||||
packed |= static_cast<uint16_t>(_bins[i]) << (i * 4U);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "../../Vector4.h"
|
||||
#include "Vector4.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
using Hash = uint16_t;
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../Vector4.h"
|
||||
#include "Histogram.h"
|
||||
#include "Vector4.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
template <size_t N> class OrderTable {
|
||||
@ -113,7 +113,9 @@ template <size_t N> class OrderTable {
|
||||
return factors->at(hash);
|
||||
}
|
||||
|
||||
static bool IsSingleColor(Hash hash) { return (std::find(SingleColorHashes.begin(), SingleColorHashes.end(), hash) != SingleColorHashes.end()); }
|
||||
static bool IsSingleColor(Hash hash) {
|
||||
return (std::find(SingleColorHashes.begin(), SingleColorHashes.end(), hash) != SingleColorHashes.end());
|
||||
}
|
||||
|
||||
private:
|
||||
static std::mutex table_mutex;
|
||||
|
@ -23,11 +23,14 @@
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "../../util.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
struct BC1MatchEntry {
|
||||
uint8_t high;
|
||||
uint8_t low;
|
||||
|
@ -23,16 +23,12 @@
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC1Decoder.h"
|
||||
#include "BC1Encoder.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc1/BC1Decoder.h"
|
||||
#include "s3tc/bc1/BC1Encoder.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
@ -58,7 +54,8 @@ void InitBC1(py::module_ &s3tc) {
|
||||
:param selectors: the selectors as a 4x4 list of integers, between 0 and 3 inclusive.
|
||||
)doc");
|
||||
|
||||
bc1_block.def_property("endpoints", &BC1Block::GetColors, &BC1Block::SetColors, "The block's endpoint colors as a 2-tuple.");
|
||||
bc1_block.def_property("endpoints", &BC1Block::GetColors, &BC1Block::SetColors,
|
||||
"The block's endpoint colors as a 2-tuple.");
|
||||
bc1_block.def_property("selectors", &BC1Block::GetSelectors, &BC1Block::SetSelectors, R"doc(
|
||||
The block's selectors as a 4x4 list of integers between 0 and 3 inclusive.
|
||||
|
||||
@ -83,27 +80,42 @@ void InitBC1(py::module_ &s3tc) {
|
||||
// region BC1Encoder
|
||||
py::class_<BC1Encoder> bc1_encoder(bc1, "BC1Encoder", "Encodes RGB textures to BC1.");
|
||||
|
||||
py::enum_<BC1Encoder::EndpointMode>(bc1_encoder, "EndpointMode", "Enum representing various methods of finding endpoints in a block.")
|
||||
.value("LeastSquares", BC1Encoder::EndpointMode::LeastSquares, "Find endpoints using a 2D least squares approach.")
|
||||
.value("BoundingBox", BC1Encoder::EndpointMode::BoundingBox, "Find endpoints using a simple bounding box. Fast but inaccurate.")
|
||||
.value("BoundingBoxInt", BC1Encoder::EndpointMode::BoundingBoxInt, "Same as BoundingBox but using integers, slightly faster.")
|
||||
.value("PCA", BC1Encoder::EndpointMode::PCA, "Find endpoints using Principle Component Analysis. Slowest but highest quality method.");
|
||||
py::enum_<BC1Encoder::EndpointMode>(bc1_encoder, "EndpointMode",
|
||||
"Enum representing various methods of finding endpoints in a block.")
|
||||
.value("LeastSquares", BC1Encoder::EndpointMode::LeastSquares,
|
||||
"Find endpoints using a 2D least squares approach.")
|
||||
.value("BoundingBox", BC1Encoder::EndpointMode::BoundingBox,
|
||||
"Find endpoints using a simple bounding box. Fast but inaccurate.")
|
||||
.value("BoundingBoxInt", BC1Encoder::EndpointMode::BoundingBoxInt,
|
||||
"Same as BoundingBox but using integers, slightly faster.")
|
||||
.value("PCA", BC1Encoder::EndpointMode::PCA,
|
||||
"Find endpoints using Principle Component Analysis. Slowest but highest quality method.");
|
||||
|
||||
py::enum_<BC1Encoder::ErrorMode>(bc1_encoder, "ErrorMode", "Enum representing various methods of finding selectors in a block.")
|
||||
.value("None", BC1Encoder::ErrorMode::None, "The same as Faster but error is not calculated. This disables any cluster-fit options")
|
||||
.value("Faster", BC1Encoder::ErrorMode::Faster, "Use a slightly lower quality, but ~30% faster MSE evaluation function for 4-color blocks.")
|
||||
py::enum_<BC1Encoder::ErrorMode>(bc1_encoder, "ErrorMode",
|
||||
"Enum representing various methods of finding selectors in a block.")
|
||||
.value("None", BC1Encoder::ErrorMode::None,
|
||||
"The same as Faster but error is not calculated. This disables any cluster-fit options")
|
||||
.value("Faster", BC1Encoder::ErrorMode::Faster,
|
||||
"Use a slightly lower quality, but ~30% faster MSE evaluation function for 4-color blocks.")
|
||||
.value("Check2", BC1Encoder::ErrorMode::Check2, "Default error-checking method.")
|
||||
.value("Full", BC1Encoder::ErrorMode::Full, "Examine all colors to compute selectors/MSE. Slower but slightly higher quality.");
|
||||
.value("Full", BC1Encoder::ErrorMode::Full,
|
||||
"Examine all colors to compute selectors/MSE. Slower but slightly higher quality.");
|
||||
|
||||
py::enum_<BC1Encoder::ColorMode>(bc1_encoder, "ColorMode", "Enum representing various methods of writing BC1 blocks.")
|
||||
.value("FourColor", BC1Encoder::ColorMode::FourColor, "Default color mode. Only 4-color blocks will be output, where color0 > color1")
|
||||
.value("ThreeColor", BC1Encoder::ColorMode::ThreeColor, "Additionally use 3-color blocks when they have a lower error, where color0 <= color1")
|
||||
py::enum_<BC1Encoder::ColorMode>(bc1_encoder, "ColorMode",
|
||||
"Enum representing various methods of writing BC1 blocks.")
|
||||
.value("FourColor", BC1Encoder::ColorMode::FourColor,
|
||||
"Default color mode. Only 4-color blocks will be output, where color0 > color1")
|
||||
.value("ThreeColor", BC1Encoder::ColorMode::ThreeColor,
|
||||
"Additionally use 3-color blocks when they have a lower error, where color0 <= color1")
|
||||
.value("ThreeColorBlack", BC1Encoder::ColorMode::ThreeColorBlack,
|
||||
"Additionally use 3-color blocks with black pixels (selector 3). Note that this requires your shader/engine to not sample the alpha channel "
|
||||
"Additionally use 3-color blocks with black pixels (selector 3). Note that this requires your "
|
||||
"shader/engine to not sample the alpha channel "
|
||||
"when using a BC1 texture.");
|
||||
|
||||
bc1_encoder.def(py::init<unsigned, BC1Encoder::ColorMode>(), "level"_a = 5, "color_mode"_a = BC1Encoder::ColorMode::FourColor);
|
||||
bc1_encoder.def(py::init<unsigned, BC1Encoder::ColorMode, InterpolatorPtr>(), "level"_a, "color_mode"_a, "interpolator"_a, R"doc(
|
||||
bc1_encoder.def(py::init<unsigned, BC1Encoder::ColorMode>(), "level"_a = 5,
|
||||
"color_mode"_a = BC1Encoder::ColorMode::FourColor);
|
||||
bc1_encoder.def(py::init<unsigned, BC1Encoder::ColorMode, InterpolatorPtr>(), "level"_a, "color_mode"_a,
|
||||
"interpolator"_a, R"doc(
|
||||
Create a new BC1 encoder with the specified preset level, color mode, and interpolator.
|
||||
|
||||
:param int level: The preset level of the resulting encoder, between 0 and 18 inclusive. See :py:meth:`set_level` for more information. Default: 5.
|
||||
@ -125,44 +137,56 @@ void InitBC1(py::module_ &s3tc) {
|
||||
:param int level: The preset level of the resulting encoder, between 0 and 18 inclusive. Default: 5.
|
||||
)doc");
|
||||
|
||||
bc1_encoder.def_property_readonly("interpolator", &BC1Encoder::GetInterpolator,
|
||||
"The :py:class:`~quicktex.s3tc.interpolator.Interpolator` used by this encoder. This is a readonly property.");
|
||||
bc1_encoder.def_property_readonly("color_mode", &BC1Encoder::GetColorMode,
|
||||
"The :py:class:`~quicktex.s3tc.bc1.BC1Encoder.ColorMode` used by this encoder. This is a readonly property.");
|
||||
bc1_encoder.def_property_readonly(
|
||||
"interpolator", &BC1Encoder::GetInterpolator,
|
||||
"The :py:class:`~quicktex.s3tc.interpolator.Interpolator` used by this encoder. This is a readonly property.");
|
||||
bc1_encoder.def_property_readonly(
|
||||
"color_mode", &BC1Encoder::GetColorMode,
|
||||
"The :py:class:`~quicktex.s3tc.bc1.BC1Encoder.ColorMode` used by this encoder. This is a readonly property.");
|
||||
|
||||
// Advanced API
|
||||
|
||||
bc1_encoder.def_property("error_mode", &BC1Encoder::GetErrorMode, &BC1Encoder::SetErrorMode, "The error mode used by this encoder for finding selectors.");
|
||||
bc1_encoder.def_property("endpoint_mode", &BC1Encoder::GetEndpointMode, &BC1Encoder::SetEndpointMode, "The endpoint mode used by this encoder.");
|
||||
bc1_encoder.def_property("error_mode", &BC1Encoder::GetErrorMode, &BC1Encoder::SetErrorMode,
|
||||
"The error mode used by this encoder for finding selectors.");
|
||||
bc1_encoder.def_property("endpoint_mode", &BC1Encoder::GetEndpointMode, &BC1Encoder::SetEndpointMode,
|
||||
"The endpoint mode used by this encoder.");
|
||||
|
||||
bc1_encoder.def_readwrite("two_ls_passes", &BC1Encoder::two_ls_passes,
|
||||
"Use 2 least squares pass, instead of one (same as stb_dxt's HIGHQUAL option).\n"
|
||||
"Recommended if you're setting the orderings settings greater than 0.");
|
||||
|
||||
bc1_encoder.def_readwrite("two_ep_passes", &BC1Encoder::two_ep_passes, "Try 2 different ways of choosing the initial endpoints.");
|
||||
bc1_encoder.def_readwrite("two_ep_passes", &BC1Encoder::two_ep_passes,
|
||||
"Try 2 different ways of choosing the initial endpoints.");
|
||||
|
||||
bc1_encoder.def_readwrite("two_cf_passes", &BC1Encoder::two_cf_passes,
|
||||
"Greatly increase encode time, with very slightly higher quality.\n"
|
||||
"Same as squish's iterative cluster fit option. Not really worth the tiny boost in quality, "
|
||||
"unless you just don't care about performance at all.");
|
||||
bc1_encoder.def_readwrite(
|
||||
"two_cf_passes", &BC1Encoder::two_cf_passes,
|
||||
"Greatly increase encode time, with very slightly higher quality.\n"
|
||||
"Same as squish's iterative cluster fit option. Not really worth the tiny boost in quality, "
|
||||
"unless you just don't care about performance at all.");
|
||||
|
||||
bc1_encoder.def_readwrite("exhaustive", &BC1Encoder::exhaustive,
|
||||
"Check all total orderings - *very* slow. The encoder is not designed to be used in this way");
|
||||
bc1_encoder.def_readwrite(
|
||||
"exhaustive", &BC1Encoder::exhaustive,
|
||||
"Check all total orderings - *very* slow. The encoder is not designed to be used in this way");
|
||||
|
||||
bc1_encoder.def_property("search_rounds", &BC1Encoder::GetSearchRounds, &BC1Encoder::SetSearchRounds,
|
||||
"Setting search rounds > 0 enables refining the final endpoints by examining nearby colors. A higher value has a higher quality "
|
||||
"Setting search rounds > 0 enables refining the final endpoints by examining nearby "
|
||||
"colors. A higher value has a higher quality "
|
||||
"at the expense of performance.");
|
||||
|
||||
bc1_encoder.def_property("orderings", &BC1Encoder::GetOrderings, &BC1Encoder::SetOrderings,
|
||||
"setting the orderings > 0 enables ordered cluster fit using a lookup table of similar blocks. Value is a tuple of (4 color "
|
||||
"orders, 3 color orders), where higher values have a higher quality at the expense of performance.");
|
||||
bc1_encoder.def_property(
|
||||
"orderings", &BC1Encoder::GetOrderings, &BC1Encoder::SetOrderings,
|
||||
"setting the orderings > 0 enables ordered cluster fit using a lookup table of similar blocks. Value is a "
|
||||
"tuple of (4 color "
|
||||
"orders, 3 color orders), where higher values have a higher quality at the expense of performance.");
|
||||
|
||||
bc1_encoder.def_readonly_static("max_power_iterations", &BC1Encoder::max_power_iterations);
|
||||
bc1_encoder.def_readonly_static("min_power_iterations", &BC1Encoder::min_power_iterations);
|
||||
|
||||
bc1_encoder.def_property("power_iterations", &BC1Encoder::GetPowerIterations, &BC1Encoder::SetPowerIterations,
|
||||
"Number of power iterations used with the PCA endpoint mode. Value should be around 4 to 6. "
|
||||
"Automatically clamped to between :py:const:`BC1Encoder.min_power_iterations` and :py:const:`BC1Encoder.max_power_iterations`");
|
||||
bc1_encoder.def_property(
|
||||
"power_iterations", &BC1Encoder::GetPowerIterations, &BC1Encoder::SetPowerIterations,
|
||||
"Number of power iterations used with the PCA endpoint mode. Value should be around 4 to 6. "
|
||||
"Automatically clamped to between :py:const:`BC1Encoder.min_power_iterations` and "
|
||||
":py:const:`BC1Encoder.max_power_iterations`");
|
||||
// endregion
|
||||
|
||||
// region BC1Decoder
|
||||
@ -185,8 +209,10 @@ void InitBC1(py::module_ &s3tc) {
|
||||
:returns: A new RawTexture with the same dimensions as the input
|
||||
)doc");
|
||||
|
||||
bc1_decoder.def_property_readonly("interpolator", &BC1Decoder::GetInterpolator, "The interpolator used by this decoder. This is a readonly property.");
|
||||
bc1_decoder.def_readwrite("write_alpha", &BC1Decoder::write_alpha, "Determines if the alpha channel of the output is written to.");
|
||||
bc1_decoder.def_property_readonly("interpolator", &BC1Decoder::GetInterpolator,
|
||||
"The interpolator used by this decoder. This is a readonly property.");
|
||||
bc1_decoder.def_readwrite("write_alpha", &BC1Decoder::write_alpha,
|
||||
"Determines if the alpha channel of the output is written to.");
|
||||
// endregion
|
||||
}
|
||||
} // namespace quicktex::bindings
|
@ -21,8 +21,8 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "../bc1/BC1Block.h"
|
||||
#include "../bc4/BC4Block.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
@ -54,7 +54,9 @@ class alignas(8) BC3Block {
|
||||
color_block = blocks.second;
|
||||
}
|
||||
|
||||
bool operator==(const BC3Block &Rhs) const { return alpha_block == Rhs.alpha_block && color_block == Rhs.color_block; }
|
||||
bool operator==(const BC3Block &Rhs) const {
|
||||
return alpha_block == Rhs.alpha_block && color_block == Rhs.color_block;
|
||||
}
|
||||
bool operator!=(const BC3Block &Rhs) const { return !(Rhs == *this); }
|
||||
};
|
||||
} // namespace quicktex::s3tc
|
@ -21,13 +21,13 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../bc1/BC1Decoder.h"
|
||||
#include "../bc4/BC4Decoder.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC3Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Decoder.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
#include "s3tc/bc4/BC4Decoder.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
@ -37,7 +37,8 @@ class BC3Decoder : public BlockDecoder<BlockTexture<BC3Block>> {
|
||||
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
|
||||
using InterpolatorPtr = std::shared_ptr<Interpolator>;
|
||||
|
||||
BC3Decoder(InterpolatorPtr interpolator) : _bc1_decoder(std::make_shared<BC1Decoder>(interpolator)), _bc4_decoder(std::make_shared<BC4Decoder>(3)) {}
|
||||
BC3Decoder(InterpolatorPtr interpolator)
|
||||
: _bc1_decoder(std::make_shared<BC1Decoder>(interpolator)), _bc4_decoder(std::make_shared<BC4Decoder>(3)) {}
|
||||
|
||||
BC3Decoder() : BC3Decoder(std::make_shared<Interpolator>()) {}
|
||||
|
||||
|
@ -19,10 +19,8 @@
|
||||
|
||||
#include "BC3Encoder.h"
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../bc1/BC1Block.h"
|
||||
#include "../bc4/BC4Block.h"
|
||||
#include "BC3Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
BC3Block BC3Encoder::EncodeBlock(const ColorBlock<4, 4> &pixels) const {
|
||||
|
@ -21,13 +21,13 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../bc1/BC1Encoder.h"
|
||||
#include "../bc4/BC4Encoder.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC3Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc1/BC1Encoder.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
#include "s3tc/bc4/BC4Encoder.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
@ -38,7 +38,8 @@ class BC3Encoder : public BlockEncoder<BlockTexture<BC3Block>> {
|
||||
using InterpolatorPtr = std::shared_ptr<Interpolator>;
|
||||
|
||||
BC3Encoder(unsigned level, InterpolatorPtr interpolator)
|
||||
: _bc1_encoder(std::make_shared<BC1Encoder>(level, BC1Encoder::ColorMode::FourColor, interpolator)), _bc4_encoder(std::make_shared<BC4Encoder>(3)) {}
|
||||
: _bc1_encoder(std::make_shared<BC1Encoder>(level, BC1Encoder::ColorMode::FourColor, interpolator)),
|
||||
_bc4_encoder(std::make_shared<BC4Encoder>(3)) {}
|
||||
|
||||
BC3Encoder(unsigned level = 5) : BC3Encoder(level, std::make_shared<Interpolator>()) {}
|
||||
|
||||
|
@ -22,16 +22,14 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../interpolator/Interpolator.h"
|
||||
#include "BC3Decoder.h"
|
||||
#include "BC3Encoder.h"
|
||||
#include "s3tc/bc1/BC1Block.h"
|
||||
#include "s3tc/bc3/BC3Block.h"
|
||||
#include "s3tc/bc3/BC3Decoder.h"
|
||||
#include "s3tc/bc3/BC3Encoder.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
#include "s3tc/interpolator/Interpolator.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
@ -59,7 +57,8 @@ void InitBC3(py::module_ &s3tc) {
|
||||
|
||||
bc3_block.def_readwrite("alpha_block", &BC3Block::alpha_block, "The BC4 block used for alpha data.");
|
||||
bc3_block.def_readwrite("color_block", &BC3Block::color_block, "The BC1 block used for rgb data.");
|
||||
bc3_block.def_property("blocks", &BC3Block::GetBlocks, &BC3Block::SetBlocks, "The BC4 and BC1 blocks that make up this block as a 2-tuple.");
|
||||
bc3_block.def_property("blocks", &BC3Block::GetBlocks, &BC3Block::SetBlocks,
|
||||
"The BC4 and BC1 blocks that make up this block as a 2-tuple.");
|
||||
// endregion
|
||||
|
||||
// region BC3Texture
|
||||
@ -88,10 +87,12 @@ void InitBC3(py::module_ &s3tc) {
|
||||
:returns: A new BC3Texture with the same dimension as the input.
|
||||
)doc");
|
||||
|
||||
bc3_encoder.def_property_readonly("bc1_encoder", &BC3Encoder::GetBC1Encoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc1.BC1Encoder` used for RGB data. Readonly.");
|
||||
bc3_encoder.def_property_readonly("bc4_encoder", &BC3Encoder::GetBC4Encoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc4.BC4Encoder` used for alpha data. Readonly.");
|
||||
bc3_encoder.def_property_readonly(
|
||||
"bc1_encoder", &BC3Encoder::GetBC1Encoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc1.BC1Encoder` used for RGB data. Readonly.");
|
||||
bc3_encoder.def_property_readonly(
|
||||
"bc4_encoder", &BC3Encoder::GetBC4Encoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc4.BC4Encoder` used for alpha data. Readonly.");
|
||||
// endregion
|
||||
|
||||
// region BC3Decoder
|
||||
@ -113,10 +114,12 @@ void InitBC3(py::module_ &s3tc) {
|
||||
:returns: A new RawTexture with the same dimensions as the input
|
||||
)doc");
|
||||
|
||||
bc3_decoder.def_property_readonly("bc1_decoder", &BC3Decoder::GetBC1Decoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc1.BC1Decoder` used for RGB data. Readonly.");
|
||||
bc3_decoder.def_property_readonly("bc4_decoder", &BC3Decoder::GetBC4Decoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc4.BC4Decoder` used for alpha data. Readonly.");
|
||||
bc3_decoder.def_property_readonly(
|
||||
"bc1_decoder", &BC3Decoder::GetBC1Decoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc1.BC1Decoder` used for RGB data. Readonly.");
|
||||
bc3_decoder.def_property_readonly(
|
||||
"bc4_decoder", &BC3Decoder::GetBC4Decoder,
|
||||
"Internal :py:class:`~quicktex.s3tc.bc4.BC4Decoder` used for alpha data. Readonly.");
|
||||
// endregion
|
||||
}
|
||||
} // namespace quicktex::bindings
|
@ -22,14 +22,18 @@
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../../util.h"
|
||||
#include "util/ranges.h"
|
||||
#include "util/bitbash.h"
|
||||
#include "util/math.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
BC4Block::SelectorArray BC4Block::GetSelectors() const {
|
||||
auto packed = pack<uint64_t>(_selectors, 8);
|
||||
auto rows = unpack<uint16_t, Height>(packed, SelectorBits * Width);
|
||||
return MapArray(rows, [](auto row) { return unpack<uint8_t, Width>(row, SelectorBits); });
|
||||
return map(rows, [](auto row) { return unpack<uint8_t, Width>(row, SelectorBits); });
|
||||
}
|
||||
|
||||
void BC4Block::SetSelectors(const BC4Block::SelectorArray& unpacked) {
|
||||
@ -37,7 +41,7 @@ void BC4Block::SetSelectors(const BC4Block::SelectorArray& unpacked) {
|
||||
if (std::any_of(unpacked[y].begin(), unpacked[y].end(), [](uint8_t i) { return i > SelectorMax; }))
|
||||
throw std::invalid_argument("Selector value out of bounds.");
|
||||
}
|
||||
auto rows = MapArray(unpacked, [](auto r) { return pack<uint16_t>(r, SelectorBits); });
|
||||
auto rows = map(unpacked, [](auto r) { return pack<uint16_t>(r, SelectorBits); });
|
||||
auto packed = pack<uint64_t>(rows, SelectorBits * Width);
|
||||
_selectors = unpack<uint8_t, SelectorSize>(packed, 8);
|
||||
}
|
||||
|
@ -23,15 +23,11 @@
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "BC4Decoder.h"
|
||||
#include "BC4Encoder.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
#include "s3tc/bc4/BC4Decoder.h"
|
||||
#include "s3tc/bc4/BC4Encoder.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
@ -46,7 +42,8 @@ void InitBC4(py::module_ &s3tc) {
|
||||
bc4_block.doc() = "A single BC4 block.";
|
||||
|
||||
bc4_block.def(py::init<>());
|
||||
bc4_block.def(py::init<uint8_t, uint8_t, BC4Block::SelectorArray>(), "endpoint0"_a, "endpoint1"_a, "selectors"_a, R"doc(
|
||||
bc4_block.def(py::init<uint8_t, uint8_t, BC4Block::SelectorArray>(), "endpoint0"_a, "endpoint1"_a, "selectors"_a,
|
||||
R"doc(
|
||||
Create a new BC4Block with the specified endpoints and selectors.
|
||||
|
||||
:param int endpoint0: The first endpoint.
|
||||
@ -54,7 +51,8 @@ void InitBC4(py::module_ &s3tc) {
|
||||
:param selectors: the selectors as a 4x4 list of integers, between 0 and 7 inclusive.
|
||||
)doc");
|
||||
|
||||
bc4_block.def_property("endpoints", &BC4Block::GetAlphas, &BC4Block::SetAlphas, "The block's endpoint values as a 2-tuple.");
|
||||
bc4_block.def_property("endpoints", &BC4Block::GetAlphas, &BC4Block::SetAlphas,
|
||||
"The block's endpoint values as a 2-tuple.");
|
||||
bc4_block.def_property("selectors", &BC4Block::GetSelectors, &BC4Block::SetSelectors, R"doc(
|
||||
The block's selectors as a 4x4 list of integers between 0 and 7 inclusive.
|
||||
|
||||
@ -96,8 +94,9 @@ void InitBC4(py::module_ &s3tc) {
|
||||
:param RawTexture texture: Input texture to encode.
|
||||
:returns: A new BC4Texture with the same dimension as the input.
|
||||
)doc");
|
||||
|
||||
bc4_encoder.def_property_readonly("channel", &BC4Encoder::GetChannel, "The channel that will be read from. 0 to 3 inclusive. Readonly.");
|
||||
|
||||
bc4_encoder.def_property_readonly("channel", &BC4Encoder::GetChannel,
|
||||
"The channel that will be read from. 0 to 3 inclusive. Readonly.");
|
||||
// endregion
|
||||
|
||||
// region BC4Decoder
|
||||
@ -117,8 +116,9 @@ void InitBC4(py::module_ &s3tc) {
|
||||
:param RawTexture texture: Input texture to encode.
|
||||
:returns: A new RawTexture with the same dimensions as the input
|
||||
)doc");
|
||||
|
||||
bc4_decoder.def_property_readonly("channel", &BC4Decoder::GetChannel, "The channel that will be written to. 0 to 3 inclusive. Readonly.");
|
||||
|
||||
bc4_decoder.def_property_readonly("channel", &BC4Decoder::GetChannel,
|
||||
"The channel that will be written to. 0 to 3 inclusive. Readonly.");
|
||||
// endregion
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "../bc4/BC4Block.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
@ -53,7 +51,9 @@ class alignas(8) BC5Block {
|
||||
chan1_block = pair.second;
|
||||
}
|
||||
|
||||
bool operator==(const BC5Block &Rhs) const { return chan0_block == Rhs.chan0_block && chan1_block == Rhs.chan1_block; }
|
||||
bool operator==(const BC5Block &Rhs) const {
|
||||
return chan0_block == Rhs.chan0_block && chan1_block == Rhs.chan1_block;
|
||||
}
|
||||
bool operator!=(const BC5Block &Rhs) const { return !(Rhs == *this); }
|
||||
};
|
||||
} // namespace quicktex::s3tc
|
@ -19,8 +19,8 @@
|
||||
|
||||
#include "BC5Decoder.h"
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "BC5Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
ColorBlock<4, 4> BC5Decoder::DecodeBlock(const BC5Block &block) const {
|
||||
|
@ -24,11 +24,11 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../bc4/BC4Decoder.h"
|
||||
#include "BC5Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Decoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc4/BC4Decoder.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
@ -38,8 +38,10 @@ class BC5Decoder : public BlockDecoder<BlockTexture<BC5Block>> {
|
||||
using BC4DecoderPtr = std::shared_ptr<BC4Decoder>;
|
||||
using BC4DecoderPair = std::tuple<BC4DecoderPtr, BC4DecoderPtr>;
|
||||
|
||||
BC5Decoder(uint8_t chan0 = 0, uint8_t chan1 = 1) : BC5Decoder(std::make_shared<BC4Decoder>(chan0), std::make_shared<BC4Decoder>(chan1)) {}
|
||||
BC5Decoder(BC4DecoderPtr chan0_decoder, BC4DecoderPtr chan1_decoder) : _chan0_decoder(chan0_decoder), _chan1_decoder(chan1_decoder) {}
|
||||
BC5Decoder(uint8_t chan0 = 0, uint8_t chan1 = 1)
|
||||
: BC5Decoder(std::make_shared<BC4Decoder>(chan0), std::make_shared<BC4Decoder>(chan1)) {}
|
||||
BC5Decoder(BC4DecoderPtr chan0_decoder, BC4DecoderPtr chan1_decoder)
|
||||
: _chan0_decoder(chan0_decoder), _chan1_decoder(chan1_decoder) {}
|
||||
|
||||
ColorBlock<4, 4> DecodeBlock(const BC5Block &block) const override;
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
#include "BC5Encoder.h"
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../bc4/BC4Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
BC5Block BC5Encoder::EncodeBlock(const ColorBlock<4, 4> &pixels) const {
|
||||
|
@ -24,11 +24,11 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../ColorBlock.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "../../Texture.h"
|
||||
#include "../bc4/BC4Encoder.h"
|
||||
#include "BC5Block.h"
|
||||
#include "ColorBlock.h"
|
||||
#include "Encoder.h"
|
||||
#include "Texture.h"
|
||||
#include "s3tc/bc4/BC4Encoder.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
class BC5Encoder : public BlockEncoder<BlockTexture<BC5Block>> {
|
||||
@ -37,8 +37,10 @@ class BC5Encoder : public BlockEncoder<BlockTexture<BC5Block>> {
|
||||
using BC4EncoderPtr = std::shared_ptr<BC4Encoder>;
|
||||
using BC4EncoderPair = std::tuple<BC4EncoderPtr, BC4EncoderPtr>;
|
||||
|
||||
BC5Encoder(uint8_t chan0 = 0, uint8_t chan1 = 1) : BC5Encoder(std::make_shared<BC4Encoder>(chan0), std::make_shared<BC4Encoder>(chan1)) {}
|
||||
BC5Encoder(BC4EncoderPtr chan0_encoder, BC4EncoderPtr chan1_encoder) : _chan0_encoder(chan0_encoder), _chan1_encoder(chan1_encoder) {}
|
||||
BC5Encoder(uint8_t chan0 = 0, uint8_t chan1 = 1)
|
||||
: BC5Encoder(std::make_shared<BC4Encoder>(chan0), std::make_shared<BC4Encoder>(chan1)) {}
|
||||
BC5Encoder(BC4EncoderPtr chan0_encoder, BC4EncoderPtr chan1_encoder)
|
||||
: _chan0_encoder(chan0_encoder), _chan1_encoder(chan1_encoder) {}
|
||||
|
||||
BC5Block EncodeBlock(const ColorBlock<4, 4> &pixels) const override;
|
||||
|
||||
|
@ -24,10 +24,10 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../../Decoder.h"
|
||||
#include "../../Encoder.h"
|
||||
#include "BC5Decoder.h"
|
||||
#include "BC5Encoder.h"
|
||||
#include "s3tc/bc4/BC4Block.h"
|
||||
#include "s3tc/bc5/BC5Block.h"
|
||||
#include "s3tc/bc5/BC5Decoder.h"
|
||||
#include "s3tc/bc5/BC5Encoder.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
namespace quicktex::bindings {
|
||||
@ -52,7 +52,8 @@ void InitBC5(py::module_ &s3tc) {
|
||||
|
||||
bc5_block.def_readwrite("chan0_block", &BC5Block::chan0_block, "The BC4 block used for the first channel.");
|
||||
bc5_block.def_readwrite("chan1_block", &BC5Block::chan1_block, "The BC4 block used for the second channel.");
|
||||
bc5_block.def_property("blocks", &BC5Block::GetBlocks, &BC5Block::SetBlocks, "The BC4 and BC1 blocks that make up this block as a 2-tuple.");
|
||||
bc5_block.def_property("blocks", &BC5Block::GetBlocks, &BC5Block::SetBlocks,
|
||||
"The BC4 and BC1 blocks that make up this block as a 2-tuple.");
|
||||
// endregion
|
||||
|
||||
// region BC5Texture
|
||||
@ -79,9 +80,11 @@ void InitBC5(py::module_ &s3tc) {
|
||||
:returns: A new BC5Texture with the same dimension as the input.
|
||||
)doc");
|
||||
|
||||
bc5_encoder.def_property_readonly("channels", &BC5Encoder::GetChannels, "A 2-tuple of channels that will be read from. 0 to 3 inclusive. Readonly.");
|
||||
bc5_encoder.def_property_readonly("bc4_encoders", &BC5Encoder::GetBC4Encoders,
|
||||
"2-tuple of internal :py:class:`~quicktex.s3tc.bc4.BC4Encoder` s used for each channel. Readonly.");
|
||||
bc5_encoder.def_property_readonly("channels", &BC5Encoder::GetChannels,
|
||||
"A 2-tuple of channels that will be read from. 0 to 3 inclusive. Readonly.");
|
||||
bc5_encoder.def_property_readonly(
|
||||
"bc4_encoders", &BC5Encoder::GetBC4Encoders,
|
||||
"2-tuple of internal :py:class:`~quicktex.s3tc.bc4.BC4Encoder` s used for each channel. Readonly.");
|
||||
// endregion
|
||||
|
||||
// region BC5Decoder
|
||||
@ -103,9 +106,11 @@ void InitBC5(py::module_ &s3tc) {
|
||||
:returns: A new RawTexture with the same dimensions as the input
|
||||
)doc");
|
||||
|
||||
bc5_decoder.def_property_readonly("channels", &BC5Decoder::GetChannels, "A 2-tuple of channels that will be written to. 0 to 3 inclusive. Readonly.");
|
||||
bc5_decoder.def_property_readonly("bc4_decoders", &BC5Decoder::GetBC4Decoders,
|
||||
"2-tuple of internal :py:class:`~quicktex.s3tc.bc4.BC4Decoder` s used for each channel. Readonly.");
|
||||
bc5_decoder.def_property_readonly("channels", &BC5Decoder::GetChannels,
|
||||
"A 2-tuple of channels that will be written to. 0 to 3 inclusive. Readonly.");
|
||||
bc5_decoder.def_property_readonly(
|
||||
"bc4_decoders", &BC5Decoder::GetBC4Decoders,
|
||||
"2-tuple of internal :py:class:`~quicktex.s3tc.bc4.BC4Decoder` s used for each channel. Readonly.");
|
||||
// endregion
|
||||
}
|
||||
} // namespace quicktex::bindings
|
@ -24,11 +24,13 @@
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../../OldColor.h"
|
||||
#include "../../util.h"
|
||||
#include "OldColor.h"
|
||||
#include "util/bitbash.h"
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
using namespace quicktex::util;
|
||||
|
||||
// region Interpolator implementation
|
||||
std::unique_ptr<Interpolator> Interpolator::MakeInterpolator(Interpolator::Type type) {
|
||||
switch (type) {
|
||||
@ -45,10 +47,18 @@ std::unique_ptr<Interpolator> Interpolator::MakeInterpolator(Interpolator::Type
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Interpolator::Interpolate5(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1)); }
|
||||
uint8_t Interpolator::Interpolate6(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1)); }
|
||||
uint8_t Interpolator::InterpolateHalf5(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale_to_8<5>(v0), scale_to_8<5>(v1)); }
|
||||
uint8_t Interpolator::InterpolateHalf6(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale_to_8<6>(v0), scale_to_8<6>(v1)); }
|
||||
uint8_t Interpolator::Interpolate5(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1));
|
||||
}
|
||||
uint8_t Interpolator::Interpolate6(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1));
|
||||
}
|
||||
uint8_t Interpolator::InterpolateHalf5(uint8_t v0, uint8_t v1) const {
|
||||
return InterpolateHalf8(scale_to_8<5>(v0), scale_to_8<5>(v1));
|
||||
}
|
||||
uint8_t Interpolator::InterpolateHalf6(uint8_t v0, uint8_t v1) const {
|
||||
return InterpolateHalf8(scale_to_8<6>(v0), scale_to_8<6>(v1));
|
||||
}
|
||||
|
||||
std::array<OldColor, 4> Interpolator::Interpolate565BC1(uint16_t low, uint16_t high, bool allow_3color) const {
|
||||
bool use_3color = allow_3color && (high >= low);
|
||||
@ -79,8 +89,12 @@ uint8_t Interpolator::InterpolateHalf8(uint8_t v0, uint8_t v1) const { return (v
|
||||
// endregion
|
||||
|
||||
// region InterpolatorRound implementation
|
||||
uint8_t InterpolatorRound::Interpolate5(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1)); }
|
||||
uint8_t InterpolatorRound::Interpolate6(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1)); }
|
||||
uint8_t InterpolatorRound::Interpolate5(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1));
|
||||
}
|
||||
uint8_t InterpolatorRound::Interpolate6(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1));
|
||||
}
|
||||
|
||||
uint8_t InterpolatorRound::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 * 2 + v1 + 1) / 3; }
|
||||
// endregion
|
||||
@ -129,10 +143,18 @@ std::array<OldColor, 4> InterpolatorNvidia::InterpolateBC1(OldColor low, OldColo
|
||||
// endregion
|
||||
|
||||
// region InterpolatorAMD implementation
|
||||
uint8_t InterpolatorAMD::Interpolate5(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1)); }
|
||||
uint8_t InterpolatorAMD::Interpolate6(uint8_t v0, uint8_t v1) const { return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1)); }
|
||||
uint8_t InterpolatorAMD::InterpolateHalf5(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale_to_8<5>(v0), scale_to_8<5>(v1)); }
|
||||
uint8_t InterpolatorAMD::InterpolateHalf6(uint8_t v0, uint8_t v1) const { return InterpolateHalf8(scale_to_8<6>(v0), scale_to_8<6>(v1)); }
|
||||
uint8_t InterpolatorAMD::Interpolate5(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<5>(v0), scale_to_8<5>(v1));
|
||||
}
|
||||
uint8_t InterpolatorAMD::Interpolate6(uint8_t v0, uint8_t v1) const {
|
||||
return Interpolate8(scale_to_8<6>(v0), scale_to_8<6>(v1));
|
||||
}
|
||||
uint8_t InterpolatorAMD::InterpolateHalf5(uint8_t v0, uint8_t v1) const {
|
||||
return InterpolateHalf8(scale_to_8<5>(v0), scale_to_8<5>(v1));
|
||||
}
|
||||
uint8_t InterpolatorAMD::InterpolateHalf6(uint8_t v0, uint8_t v1) const {
|
||||
return InterpolateHalf8(scale_to_8<6>(v0), scale_to_8<6>(v1));
|
||||
}
|
||||
|
||||
uint8_t InterpolatorAMD::Interpolate8(uint8_t v0, uint8_t v1) const { return (v0 * 43 + v1 * 21 + 32) >> 6; }
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <cstdint> // for uint8_t, uint16_t
|
||||
#include <memory> // for unique_ptr
|
||||
|
||||
#include "../../OldColor.h" // for Color
|
||||
#include "OldColor.h" // for Color
|
||||
|
||||
namespace quicktex::s3tc {
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||
and licenced under the public domain
|
||||
|
||||
@ -18,15 +18,16 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <concepts>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <xsimd/xsimd.hpp>
|
||||
|
||||
#include "util/math.h"
|
||||
#include "util/ranges.h"
|
||||
|
||||
#define UINT5_MAX 0x1FU // 31
|
||||
#define UINT6_MAX 0x3FU // 63
|
||||
@ -34,65 +35,7 @@
|
||||
#define assert5bit(x) assert(x <= UINT5_MAX)
|
||||
#define assert6bit(x) assert(x <= UINT6_MAX)
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
// std::ranges::range is currently not usable by default in libc++
|
||||
template <class T>
|
||||
concept range = requires(T &t) {
|
||||
std::begin(t);
|
||||
std::end(t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
concept sized_range = range<T> && requires(T &t) { std::size(t); };
|
||||
|
||||
template <class T>
|
||||
requires range<T>
|
||||
size_t distance(T range) {
|
||||
return std::distance(range.begin(), range.end());
|
||||
}
|
||||
|
||||
template <typename T> class const_iterator {
|
||||
public:
|
||||
typedef long long difference_type;
|
||||
typedef T value_type;
|
||||
|
||||
const_iterator() : _value(T{}), _index(0) {}
|
||||
const_iterator(T value, size_t index = 0) : _value(value), _index(index) {}
|
||||
|
||||
const_iterator &operator++() {
|
||||
_index++;
|
||||
return *this;
|
||||
}
|
||||
const_iterator operator++(int) {
|
||||
const_iterator old = *this;
|
||||
_index++;
|
||||
return old;
|
||||
}
|
||||
const_iterator &operator--() {
|
||||
_index++;
|
||||
return *this;
|
||||
}
|
||||
const_iterator operator--(int) {
|
||||
const_iterator old = *this;
|
||||
_index++;
|
||||
return old;
|
||||
}
|
||||
|
||||
T operator*() const { return _value; }
|
||||
|
||||
difference_type operator-(const_iterator rhs) const { return (difference_type)_index - rhs._index; }
|
||||
const_iterator operator+(size_t rhs) const { return const_iterator(rhs + _index); }
|
||||
const_iterator operator-(size_t rhs) const { return const_iterator(rhs - _index); }
|
||||
|
||||
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) {
|
||||
return (lhs._value == rhs._value) && (lhs._index == rhs._index);
|
||||
}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
size_t _index;
|
||||
};
|
||||
namespace quicktex::util {
|
||||
|
||||
template <size_t N, typename S> S scale_from_8(S v) {
|
||||
static_assert(N < 8);
|
||||
@ -366,55 +309,4 @@ template <typename P, typename IR>
|
||||
inline constexpr P pack(IR r, size_t width, bool little_endian = true) {
|
||||
return pack<P>(r.begin(), r.end(), const_iterator(width), little_endian);
|
||||
}
|
||||
|
||||
template <typename Seq, typename Fn> constexpr auto MapArray(const Seq &input, Fn op) {
|
||||
using I = typename Seq::value_type;
|
||||
using O = decltype(op(I{}));
|
||||
constexpr size_t N = std::tuple_size<Seq>::value;
|
||||
|
||||
std::array<O, N> output;
|
||||
for (unsigned i = 0; i < N; i++) { output[i] = op(input[i]); }
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename S> constexpr S clamp(S value, S low, S high) {
|
||||
assert(low <= high);
|
||||
if (value < low) return low;
|
||||
if (value > high) return high;
|
||||
return value;
|
||||
}
|
||||
|
||||
using std::abs; // abs overload for builtin types
|
||||
using xsimd::abs; // provides overload for abs<xsimd::batch>
|
||||
|
||||
template <typename... Args> std::string Format(const char *str, const Args &...args) {
|
||||
auto output = std::string(str);
|
||||
|
||||
std::vector<std::string> values = {{args...}};
|
||||
|
||||
for (unsigned i = 0; i < values.size(); i++) {
|
||||
auto key = "{" + std::to_string(i) + "}";
|
||||
auto value = values[i];
|
||||
while (true) {
|
||||
size_t where = output.find(key);
|
||||
if (where == output.npos) break;
|
||||
output.replace(where, key.length(), value);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
template <class> struct next_size;
|
||||
template <class T> using next_size_t = typename next_size<T>::type;
|
||||
template <class T> struct Tag { using type = T; };
|
||||
|
||||
template <> struct next_size<int8_t> : Tag<int16_t> {};
|
||||
template <> struct next_size<int16_t> : Tag<int32_t> {};
|
||||
template <> struct next_size<int32_t> : Tag<int64_t> {};
|
||||
|
||||
template <> struct next_size<uint8_t> : Tag<uint16_t> {};
|
||||
template <> struct next_size<uint16_t> : Tag<uint32_t> {};
|
||||
template <> struct next_size<uint32_t> : Tag<uint64_t> {};
|
||||
|
||||
} // namespace quicktex
|
||||
} // namespace quicktex::util
|
@ -21,38 +21,48 @@
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace quicktex::util {
|
||||
|
||||
// Thanks dkavolis
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator~(E a) noexcept -> E {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator~(E a) noexcept -> E {
|
||||
using Base = std::underlying_type_t<E>;
|
||||
return static_cast<E>(~static_cast<Base>(a));
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator|(E a, E b) noexcept -> E {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator|(E a, E b) noexcept -> E {
|
||||
using Base = std::underlying_type_t<E>;
|
||||
return static_cast<E>(static_cast<Base>(a) | static_cast<Base>(b));
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator&(E a, E b) noexcept -> E {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator&(E a, E b) noexcept -> E {
|
||||
using Base = std::underlying_type_t<E>;
|
||||
return static_cast<E>(static_cast<Base>(a) & static_cast<Base>(b));
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator^(E a, E b) noexcept -> E {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator^(E a, E b) noexcept -> E {
|
||||
using Base = std::underlying_type_t<E>;
|
||||
return static_cast<E>(static_cast<Base>(a) ^ static_cast<Base>(b));
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator|=(E& a, E b) noexcept -> E& {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator|=(E& a, E b) noexcept -> E& {
|
||||
a = a | b;
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator&=(E& a, E b) noexcept -> E& {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator&=(E& a, E b) noexcept -> E& {
|
||||
a = a & b;
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> constexpr inline auto operator^=(E& a, E b) noexcept -> E& {
|
||||
template <typename E> requires std::is_enum_v<E>
|
||||
constexpr inline auto operator^=(E& a, E b) noexcept -> E& {
|
||||
a = a ^ b;
|
||||
return a;
|
||||
}
|
||||
}
|
||||
} // namespace quicktex::util
|
43
quicktex/util/math.h
Normal file
43
quicktex/util/math.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
Copyright (C) 2021-2022 Andrew Cassidy <drewcassidy@me.com>
|
||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||
and licenced under the public domain
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "xsimd/xsimd.hpp"
|
||||
|
||||
namespace quicktex {
|
||||
|
||||
using std::abs; // abs overload for builtin types
|
||||
using xsimd::abs; // abs overload for xsimd buffers
|
||||
|
||||
template <typename S> constexpr S clamp(S value, S low, S high) {
|
||||
assert(low <= high);
|
||||
if (value < low) return low;
|
||||
if (value > high) return high;
|
||||
return value;
|
||||
}
|
||||
} // namespace quicktex
|
104
quicktex/util/ranges.h
Normal file
104
quicktex/util/ranges.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||
and licenced under the public domain
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "xsimd/xsimd.hpp"
|
||||
|
||||
namespace quicktex::util {
|
||||
|
||||
// std::ranges::range is currently not usable by default in libc++
|
||||
template <class T>
|
||||
concept range = requires(T &t) {
|
||||
std::begin(t);
|
||||
std::end(t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
concept sized_range = range<T> && requires(T &t) { std::size(t); };
|
||||
|
||||
template <class T>
|
||||
requires range<T>
|
||||
size_t distance(T range) {
|
||||
return std::distance(range.begin(), range.end());
|
||||
}
|
||||
|
||||
template <typename T> class const_iterator {
|
||||
public:
|
||||
typedef long long difference_type;
|
||||
typedef T value_type;
|
||||
|
||||
const_iterator() : _value(T{}), _index(0) {}
|
||||
const_iterator(T value, size_t index = 0) : _value(value), _index(index) {}
|
||||
|
||||
const_iterator &operator++() {
|
||||
_index++;
|
||||
return *this;
|
||||
}
|
||||
const_iterator operator++(int) {
|
||||
const_iterator old = *this;
|
||||
_index++;
|
||||
return old;
|
||||
}
|
||||
const_iterator &operator--() {
|
||||
_index++;
|
||||
return *this;
|
||||
}
|
||||
const_iterator operator--(int) {
|
||||
const_iterator old = *this;
|
||||
_index++;
|
||||
return old;
|
||||
}
|
||||
|
||||
T operator*() const { return _value; }
|
||||
|
||||
difference_type operator-(const_iterator rhs) const { return (difference_type)_index - rhs._index; }
|
||||
const_iterator operator+(size_t rhs) const { return const_iterator(rhs + _index); }
|
||||
const_iterator operator-(size_t rhs) const { return const_iterator(rhs - _index); }
|
||||
|
||||
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) {
|
||||
return (lhs._value == rhs._value) && (lhs._index == rhs._index);
|
||||
}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
template <typename Seq, typename Fn> constexpr auto map(const Seq &input, Fn op) {
|
||||
using I = typename Seq::value_type;
|
||||
using O = decltype(op(I{}));
|
||||
constexpr size_t N = std::tuple_size<Seq>::value;
|
||||
|
||||
std::array<O, N> output;
|
||||
for (unsigned i = 0; i < N; i++) { output[i] = op(input[i]); }
|
||||
return output;
|
||||
}
|
||||
} // namespace quicktex::util
|
@ -21,13 +21,14 @@
|
||||
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <xsimd/xsimd.hpp>
|
||||
|
||||
#include "util.h"
|
||||
#include "util/math.h"
|
||||
#include "util/types.h"
|
||||
#include "xsimd/xsimd.hpp"
|
||||
|
||||
template <typename T> using requires_arch = xsimd::kernel::requires_arch<T>;
|
||||
|
||||
namespace quicktex::simd {
|
||||
namespace quicktex::util::simd {
|
||||
|
||||
namespace kernel {
|
||||
|
||||
@ -93,4 +94,4 @@ template <class A, class T> inline next_size_t<T> whadd(xsimd::batch<T, A> const
|
||||
return kernel::whadd(arg, A{});
|
||||
}
|
||||
|
||||
} // namespace quicktex::simd
|
||||
} // namespace quicktex::util::simd
|
35
quicktex/util/types.h
Normal file
35
quicktex/util/types.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Quicktex Texture Compression Library
|
||||
Copyright (C) 2021 Andrew Cassidy <drewcassidy@me.com>
|
||||
Partially derived from rgbcx.h written by Richard Geldreich <richgel99@gmail.com>
|
||||
and licenced under the public domain
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace quicktex::util {
|
||||
template <class> struct next_size;
|
||||
template <class T> using next_size_t = typename next_size<T>::type;
|
||||
template <class T> struct next_size_tag { using type = T; };
|
||||
|
||||
template <> struct next_size<int8_t> : next_size_tag<int16_t> {};
|
||||
template <> struct next_size<int16_t> : next_size_tag<int32_t> {};
|
||||
template <> struct next_size<int32_t> : next_size_tag<int64_t> {};
|
||||
|
||||
template <> struct next_size<uint8_t> : next_size_tag<uint16_t> {};
|
||||
template <> struct next_size<uint16_t> : next_size_tag<uint32_t> {};
|
||||
template <> struct next_size<uint32_t> : next_size_tag<uint64_t> {};
|
||||
} // namespace quicktex::util
|
Loading…
Reference in New Issue
Block a user