Skip to content

Commit

Permalink
UASTC HDR merge
Browse files Browse the repository at this point in the history
  • Loading branch information
richgel999 committed Sep 10, 2024
1 parent ec5396c commit 8318d0c
Show file tree
Hide file tree
Showing 10 changed files with 2,481 additions and 90 deletions.
105 changes: 99 additions & 6 deletions transcoder/basisu.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// basisu.h
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -117,13 +117,26 @@ namespace basisu
typedef basisu::vector<uint64_t> uint64_vec;
typedef basisu::vector<int> int_vec;
typedef basisu::vector<bool> bool_vec;
typedef basisu::vector<float> float_vec;

void enable_debug_printf(bool enabled);
void debug_printf(const char *pFmt, ...);


#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif

template <typename T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }

#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif

template <typename T0, typename T1> inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; }

template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
Expand Down Expand Up @@ -162,10 +175,45 @@ namespace basisu
template<typename T> inline T open_range_check(T v, T minv, T maxv) { assert(v >= minv && v < maxv); BASISU_NOTE_UNUSED(minv); BASISU_NOTE_UNUSED(maxv); return v; }
template<typename T> inline T open_range_check(T v, T maxv) { assert(v < maxv); BASISU_NOTE_UNUSED(maxv); return v; }

// Open interval
inline bool in_bounds(int v, int l, int h)
{
return (v >= l) && (v < h);
}

// Closed interval
inline bool in_range(int v, int l, int h)
{
return (v >= l) && (v <= h);
}

inline uint32_t total_bits(uint32_t v) { uint32_t l = 0; for ( ; v > 0U; ++l) v >>= 1; return l; }

template<typename T> inline T saturate(T val) { return clamp(val, 0.0f, 1.0f); }

inline uint32_t get_bit(uint32_t src, int ndx)
{
assert(in_bounds(ndx, 0, 32));
return (src >> ndx) & 1;
}

inline bool is_bit_set(uint32_t src, int ndx)
{
return get_bit(src, ndx) != 0;
}

inline uint32_t get_bits(uint32_t val, int low, int high)
{
const int num_bits = (high - low) + 1;
assert(in_range(num_bits, 1, 32));

val >>= low;
if (num_bits != 32)
val &= ((1u << num_bits) - 1);

return val;
}

template<typename T, typename R> inline void append_vector(T &vec, const R *pObjs, size_t n)
{
if (n)
Expand Down Expand Up @@ -267,6 +315,11 @@ namespace basisu
return true;
}

static inline uint32_t read_le_word(const uint8_t* pBytes)
{
return (pBytes[1] << 8U) | (pBytes[0]);
}

static inline uint32_t read_le_dword(const uint8_t *pBytes)
{
return (pBytes[3] << 24U) | (pBytes[2] << 16U) | (pBytes[1] << 8U) | (pBytes[0]);
Expand Down Expand Up @@ -303,6 +356,10 @@ namespace basisu
return *this;
}

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
inline operator uint32_t() const
{
switch (NumBytes)
Expand Down Expand Up @@ -354,6 +411,9 @@ namespace basisu
}
}
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
};

enum eZero { cZero };
Expand Down Expand Up @@ -402,8 +462,11 @@ namespace basisu
cBC3, // DXT5 (BC4/DXT5A block followed by a BC1/DXT1 block)
cBC4, // DXT5A
cBC5, // 3DC/DXN (two BC4/DXT5A blocks)
cBC6HSigned, // HDR
cBC6HUnsigned, // HDR
cBC7,
cASTC4x4, // LDR only
cASTC_LDR_4x4, // ASTC 4x4 LDR only
cASTC_HDR_4x4, // ASTC 4x4 HDR only (but may use LDR ASTC blocks internally)
cPVRTC1_4_RGB,
cPVRTC1_4_RGBA,
cATC_RGB,
Expand All @@ -413,17 +476,22 @@ namespace basisu
cETC2_R11_EAC,
cETC2_RG11_EAC,
cUASTC4x4,
cUASTC_HDR_4x4,
cBC1_NV,
cBC1_AMD,

// Uncompressed/raw pixels
cRGBA32,
cRGB565,
cBGR565,
cRGBA4444,
cABGR4444
cABGR4444,
cRGBA_HALF,
cRGB_HALF,
cRGB_9E5
};

// This is bytes per block for GPU formats, or bytes per texel for uncompressed formats.
inline uint32_t get_bytes_per_block(texture_format fmt)
{
switch (fmt)
Expand All @@ -443,13 +511,27 @@ namespace basisu
case texture_format::cETC2_R11_EAC:
return 8;
case texture_format::cRGBA32:
return sizeof(uint32_t) * 16;
case texture_format::cRGB_9E5:
return sizeof(uint32_t);
case texture_format::cRGB_HALF:
return sizeof(uint16_t) * 3;
case texture_format::cRGBA_HALF:
return sizeof(uint16_t) * 4;
case texture_format::cRGB565:
case texture_format::cBGR565:
case texture_format::cRGBA4444:
case texture_format::cABGR4444:
return sizeof(uint16_t);

default:
break;
}

// Everything else is 16 bytes/block.
return 16;
}

// This is qwords per block for GPU formats, or not valid for uncompressed formats.
inline uint32_t get_qwords_per_block(texture_format fmt)
{
return get_bytes_per_block(fmt) >> 3;
Expand All @@ -473,6 +555,17 @@ namespace basisu
BASISU_NOTE_UNUSED(fmt);
return 4;
}

inline bool is_hdr_texture_format(texture_format fmt)
{
if (fmt == texture_format::cASTC_HDR_4x4)
return true;
if (fmt == texture_format::cUASTC_HDR_4x4)
return true;
if ((fmt == texture_format::cBC6HSigned) || (fmt == texture_format::cBC6HUnsigned))
return true;
return false;
}

} // namespace basisu

60 changes: 56 additions & 4 deletions transcoder/basisu_containers.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ namespace basisu
#define BASISU_IS_SCALAR_TYPE(T) (scalar_type<T>::cFlag)

#if !defined(BASISU_HAVE_STD_TRIVIALLY_COPYABLE) && defined(__GNUC__) && __GNUC__<5
#define BASISU_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
//#define BASISU_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
#define BASISU_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
#else
#define BASISU_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value
#endif
Expand Down Expand Up @@ -286,8 +287,19 @@ namespace basisu

if (BASISU_IS_BITWISE_COPYABLE(T))
{
#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif
if ((m_p) && (other.m_p))
memcpy(m_p, other.m_p, m_size * sizeof(T));
#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif
}
else
{
Expand Down Expand Up @@ -330,8 +342,19 @@ namespace basisu

if (BASISU_IS_BITWISE_COPYABLE(T))
{
#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif
if ((m_p) && (other.m_p))
memcpy(m_p, other.m_p, other.m_size * sizeof(T));
#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif
}
else
{
Expand Down Expand Up @@ -501,15 +524,16 @@ namespace basisu

if (new_capacity > m_capacity)
{
if (!increase_capacity(new_capacity, false))
if (!increase_capacity(new_capacity, false, true))
return false;
}
else if (new_capacity < m_capacity)
{
// Must work around the lack of a "decrease_capacity()" method.
// This case is rare enough in practice that it's probably not worth implementing an optimized in-place resize.
vector tmp;
tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false);
if (!tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false, true))
return false;
tmp = *this;
swap(tmp);
}
Expand Down Expand Up @@ -750,7 +774,21 @@ namespace basisu
}

// Copy "down" the objects to preserve, filling in the empty slots.

#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif

memmove(pDst, pSrc, num_to_move * sizeof(T));

#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif
}
else
{
Expand Down Expand Up @@ -1003,7 +1041,21 @@ namespace basisu
inline void set_all(const T& o)
{
if ((sizeof(T) == 1) && (scalar_type<T>::cFlag))
{
#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
#endif
memset(m_p, *reinterpret_cast<const uint8_t*>(&o), m_size);

#ifndef __EMSCRIPTEN__
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif
}
else
{
T* pDst = m_p;
Expand All @@ -1029,7 +1081,7 @@ namespace basisu
// Important: This method is used in Basis Universal. If you change how this container allocates memory, you'll need to change any users of this method.
inline bool grant_ownership(T* p, uint32_t size, uint32_t capacity)
{
// To to prevent the caller from obviously shooting themselves in the foot.
// To prevent the caller from obviously shooting themselves in the foot.
if (((p + capacity) > m_p) && (p < (m_p + m_capacity)))
{
// Can grant ownership of a block inside the container itself!
Expand Down
47 changes: 23 additions & 24 deletions transcoder/basisu_containers_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,30 @@ namespace basisu
if (m_capacity >= min_new_capacity)
return true;

size_t new_capacity = min_new_capacity;
if ((grow_hint) && (!helpers::is_power_of_2((uint64_t)new_capacity)))
{
new_capacity = (size_t)helpers::next_pow2((uint64_t)new_capacity);

assert(new_capacity && (new_capacity > m_capacity));
uint64_t new_capacity_u64 = min_new_capacity;
if ((grow_hint) && (!helpers::is_power_of_2(new_capacity_u64)))
new_capacity_u64 = helpers::next_pow2(new_capacity_u64);

if (new_capacity < min_new_capacity)
{
if (nofail)
return false;
fprintf(stderr, "vector too large\n");
abort();
}
size_t new_capacity = (size_t)new_capacity_u64;
if (new_capacity != new_capacity_u64)
{
if (nofail)
return false;
fprintf(stderr, "elemental_vector::increase_capacity: vector too large\n");
abort();
}

const size_t desired_size = element_size * new_capacity;
const uint64_t desired_size_u64 = (uint64_t)element_size * new_capacity;

const size_t desired_size = (size_t)desired_size_u64;
if (desired_size_u64 != desired_size)
{
if (nofail)
return false;
fprintf(stderr, "elemental_vector::increase_capacity: vector too large\n");
abort();
}

size_t actual_size = 0;
if (!pMover)
{
Expand All @@ -46,11 +53,7 @@ namespace basisu
return false;

char buf[256];
#ifdef _MSC_VER
sprintf_s(buf, sizeof(buf), "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
#else
sprintf(buf, "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
#endif
snprintf(buf, sizeof(buf), "elemental_vector::increase_capacity: realloc() failed allocating %zu bytes", desired_size);
fprintf(stderr, "%s", buf);
abort();
}
Expand All @@ -75,11 +78,7 @@ namespace basisu
return false;

char buf[256];
#ifdef _MSC_VER
sprintf_s(buf, sizeof(buf), "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
#else
sprintf(buf, "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
#endif
snprintf(buf, sizeof(buf), "elemental_vector::increase_capacity: malloc() failed allocating %zu bytes", desired_size);
fprintf(stderr, "%s", buf);
abort();
}
Expand Down
Loading

0 comments on commit 8318d0c

Please sign in to comment.