PVRTC1 apparently always use wrap addressing when fetching the adjacent block colors (even when clamp texture addressing is being used), so we don't need the wrap vs. clamp option anymore. It's always wrap and that's that.

This commit is contained in:
richgel999
2019-09-29 19:34:00 -07:00
parent 9be4e210ff
commit 01d391cc2a
9 changed files with 50 additions and 85 deletions

View File

@@ -1042,7 +1042,7 @@ namespace basisu
return true;
}
bool gpu_image::unpack(image& img, bool pvrtc_wrap_addressing) const
bool gpu_image::unpack(image& img) const
{
img.resize(get_pixel_width(), get_pixel_height());
img.set_all(g_black_color);
@@ -1052,7 +1052,7 @@ namespace basisu
if ((m_fmt == texture_format::cPVRTC1_4_RGB) || (m_fmt == texture_format::cPVRTC1_4_RGBA))
{
pvrtc4_image pi(m_width, m_height, pvrtc_wrap_addressing);
pvrtc4_image pi(m_width, m_height);
if (get_total_blocks() != pi.get_total_blocks())
return false;

View File

@@ -101,7 +101,7 @@ namespace basisu
m_blocks.resize(m_blocks_x * m_blocks_y * m_qwords_per_block);
}
bool unpack(image& img, bool pvrtc_wrap_addressing = true) const;
bool unpack(image& img) const;
void override_dimensions(uint32_t w, uint32_t h)
{

View File

@@ -193,21 +193,12 @@ namespace basisu
int block_x1 = block_x0 + 1;
int block_y0 = (static_cast<int>(y) - 2) >> 2;
int block_y1 = block_y0 + 1;
if (m_wrap_addressing)
{
block_x0 = posmod(block_x0, m_block_width);
block_x1 = posmod(block_x1, m_block_width);
block_y0 = posmod(block_y0, m_block_height);
block_y1 = posmod(block_y1, m_block_height);
}
else
{
block_x0 = clamp<int>(block_x0, 0, m_block_width - 1);
block_x1 = clamp<int>(block_x1, 0, m_block_width - 1);
block_y0 = clamp<int>(block_y0, 0, m_block_height - 1);
block_y1 = clamp<int>(block_y1, 0, m_block_height - 1);
}
block_x0 = posmod(block_x0, m_block_width);
block_x1 = posmod(block_x1, m_block_width);
block_y0 = posmod(block_y0, m_block_height);
block_y1 = posmod(block_y1, m_block_height);
pColors[0] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(0), m_blocks(block_x1, block_y0).get_endpoint_5554(0), m_blocks(block_x0, block_y1).get_endpoint_5554(0), m_blocks(block_x1, block_y1).get_endpoint_5554(0));
pColors[3] = interpolate(x, y, m_blocks(block_x0, block_y0).get_endpoint_5554(1), m_blocks(block_x1, block_y0).get_endpoint_5554(1), m_blocks(block_x0, block_y1).get_endpoint_5554(1), m_blocks(block_x1, block_y1).get_endpoint_5554(1));
@@ -240,21 +231,12 @@ namespace basisu
int block_x1 = block_x0 + 1;
int block_y0 = (static_cast<int>(y) - 2) >> 2;
int block_y1 = block_y0 + 1;
if (m_wrap_addressing)
{
block_x0 = posmod(block_x0, m_block_width);
block_x1 = posmod(block_x1, m_block_width);
block_y0 = posmod(block_y0, m_block_height);
block_y1 = posmod(block_y1, m_block_height);
}
else
{
block_x0 = clamp<int>(block_x0, 0, m_block_width - 1);
block_x1 = clamp<int>(block_x1, 0, m_block_width - 1);
block_y0 = clamp<int>(block_y0, 0, m_block_height - 1);
block_y1 = clamp<int>(block_y1, 0, m_block_height - 1);
}
block_x0 = posmod(block_x0, m_block_width);
block_x1 = posmod(block_x1, m_block_width);
block_y0 = posmod(block_y0, m_block_height);
block_y1 = posmod(block_y1, m_block_height);
if (get_block_uses_transparent_modulation(x >> 2, y >> 2))
{
if (m == 0)

View File

@@ -168,15 +168,14 @@ namespace basisu
{
public:
inline pvrtc4_image() :
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_wrap_addressing(false), m_uses_alpha(false)
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
{
}
inline pvrtc4_image(uint32_t width, uint32_t height, bool wrap_addressing = false) :
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_wrap_addressing(false), m_uses_alpha(false)
inline pvrtc4_image(uint32_t width, uint32_t height) :
m_width(0), m_height(0), m_block_width(0), m_block_height(0), m_uses_alpha(false)
{
resize(width, height);
set_wrap_addressing(wrap_addressing);
}
inline void clear()
@@ -187,7 +186,6 @@ namespace basisu
m_block_height = 0;
m_blocks.clear();
m_uses_alpha = false;
m_wrap_addressing = false;
}
inline void resize(uint32_t width, uint32_t height)
@@ -218,9 +216,6 @@ namespace basisu
inline bool get_uses_alpha() const { return m_uses_alpha; }
inline void set_uses_alpha(bool uses_alpha) { m_uses_alpha = uses_alpha; }
inline void set_wrap_addressing(bool wrapping) { m_wrap_addressing = wrapping; }
inline bool get_wrap_addressing() const { return m_wrap_addressing; }
inline bool are_blocks_equal(const pvrtc4_image& rhs) const
{
return m_blocks == rhs.m_blocks;
@@ -298,24 +293,24 @@ namespace basisu
dst(x, y) = get_pixel(block_x * 4 + x, block_y * 4 + y);
}
inline int wrap_or_clamp_x(int x) const
inline int wrap_x(int x) const
{
return m_wrap_addressing ? posmod(x, m_width) : clamp<int>(x, 0, m_width - 1);
return posmod(x, m_width);
}
inline int wrap_or_clamp_y(int y) const
inline int wrap_y(int y) const
{
return m_wrap_addressing ? posmod(y, m_height) : clamp<int>(y, 0, m_height - 1);
return posmod(y, m_height);
}
inline int wrap_or_clamp_block_x(int bx) const
inline int wrap_block_x(int bx) const
{
return m_wrap_addressing ? posmod(bx, m_block_width) : clamp<int>(bx, 0, m_block_width - 1);
return posmod(bx, m_block_width);
}
inline int wrap_or_clamp_block_y(int by) const
inline int wrap_block_y(int by) const
{
return m_wrap_addressing ? posmod(by, m_block_height) : clamp<int>(by, 0, m_block_height - 1);
return posmod(by, m_block_height);
}
inline vec2F get_interpolation_factors(uint32_t x, uint32_t y) const
@@ -362,7 +357,6 @@ namespace basisu
pvrtc4_block_vector2D m_blocks;
uint32_t m_block_width, m_block_height;
bool m_wrap_addressing;
bool m_uses_alpha;
};

View File

@@ -88,7 +88,6 @@ static void print_usage()
" -etc1_only: Only unpack to ETC1, skipping the other texture formats during -unpack\n"
" -disable_hierarchical_endpoint_codebooks: Disable hierarchical endpoint codebook usage, slower but higher quality on some compression levels\n"
" -compare_ssim: Compute and display SSIM of image comparison (slow)\n"
" -pvrtc_clamp: Use clamp addressing when transcoding and unpacking PVRTC1 textures\n"
"\n"
"Mipmap generation options:\n"
" -mipmap: Generate mipmaps for each source image\n"
@@ -228,8 +227,7 @@ public:
m_no_ktx(false),
m_etc1_only(false),
m_fuzz_testing(false),
m_compare_ssim(false),
m_pvrtc_clamp(false)
m_compare_ssim(false)
{
}
@@ -254,8 +252,6 @@ public:
m_mode = cValidate;
else if (strcasecmp(pArg, "-compare_ssim") == 0)
m_compare_ssim = true;
else if (strcasecmp(pArg, "-pvrtc_clamp") == 0)
m_pvrtc_clamp = true;
else if (strcasecmp(pArg, "-file") == 0)
{
REMAINING_ARGS_CHECK(1);
@@ -584,7 +580,6 @@ public:
bool m_etc1_only;
bool m_fuzz_testing;
bool m_compare_ssim;
bool m_pvrtc_clamp;
};
static bool expand_multifile(command_line_params &opts)
@@ -1016,7 +1011,7 @@ static bool unpack_and_validate_mode(command_line_params &opts, bool validate_fl
// Fill the buffer with psuedo-random bytes, to help more visibly detect cases where the transcoder fails to write to part of the output.
fill_buffer_with_random_bytes(gi.get_ptr(), gi.get_size_in_bytes());
uint32_t decode_flags = (opts.m_pvrtc_clamp ? 0 : basist::basisu_transcoder::cDecodeFlagsPVRTCWrapAddressing);
uint32_t decode_flags = 0;
tm.start();
@@ -1103,8 +1098,7 @@ static bool unpack_and_validate_mode(command_line_params &opts, bool validate_fl
}
image u;
const bool pvrtc_wrap_addressing = !opts.m_pvrtc_clamp;
if (!gi[level_index].unpack(u, pvrtc_wrap_addressing))
if (!gi[level_index].unpack(u))
{
printf("Warning: Failed unpacking GPU texture data (%u %u %u). Unpacking as much as possible.\n", format_iter, image_index, level_index);
total_unpack_warnings++;

View File

@@ -3402,7 +3402,7 @@ namespace basist
}
// TODO: Support decoding a non-pow2 ETC1S texture into the next larger pow2 PVRTC texture.
static void fixup_pvrtc1_4_modulation_rgb(const decoder_etc_block* pETC_Blocks, const uint32_t* pPVRTC_endpoints, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool pvrtc_wrap_addressing)
static void fixup_pvrtc1_4_modulation_rgb(const decoder_etc_block* pETC_Blocks, const uint32_t* pPVRTC_endpoints, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y)
{
const uint32_t x_mask = num_blocks_x - 1;
const uint32_t y_mask = num_blocks_y - 1;
@@ -3423,7 +3423,7 @@ namespace basist
for (int ey = 0; ey < 3; ey++)
{
int by = y + ey - 1; if (!pvrtc_wrap_addressing) by = basisu::clamp<int>(by, 0, y_mask);
int by = y + ey - 1;
const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x];
@@ -3431,7 +3431,7 @@ namespace basist
for (int ex = 0; ex < 3; ex++)
{
int bx = 0 + ex - 1; if (!pvrtc_wrap_addressing) bx = basisu::clamp<int>(bx, 0, x_mask);
int bx = 0 + ex - 1;
const uint32_t e = pE[bx & x_mask];
@@ -3477,8 +3477,6 @@ namespace basist
{
const uint32_t ex = 2;
int bx = x + ex - 1;
if (!pvrtc_wrap_addressing)
bx = basisu::clamp<int>(bx, 0, x_mask);
bx &= x_mask;
#define DO_ROW(ey) \
@@ -3584,7 +3582,7 @@ namespace basist
static void fixup_pvrtc1_4_modulation_rgba(
const decoder_etc_block* pETC_Blocks,
const uint32_t* pPVRTC_endpoints,
void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool pvrtc_wrap_addressing, void *pAlpha_blocks,
void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, void *pAlpha_blocks,
const endpoint* pEndpoints, const selector* pSelectors)
{
const uint32_t x_mask = num_blocks_x - 1;
@@ -3606,7 +3604,7 @@ namespace basist
for (int ey = 0; ey < 3; ey++)
{
int by = y + ey - 1; if (!pvrtc_wrap_addressing) by = basisu::clamp<int>(by, 0, y_mask);
int by = y + ey - 1;
const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x];
@@ -3614,7 +3612,7 @@ namespace basist
for (int ex = 0; ex < 3; ex++)
{
int bx = 0 + ex - 1; if (!pvrtc_wrap_addressing) bx = basisu::clamp<int>(bx, 0, x_mask);
int bx = 0 + ex - 1;
const uint32_t e = pE[bx & x_mask];
@@ -3674,8 +3672,6 @@ namespace basist
{
const uint32_t ex = 2;
int bx = x + ex - 1;
if (!pvrtc_wrap_addressing)
bx = basisu::clamp<int>(bx, 0, x_mask);
bx &= x_mask;
#define DO_ROW(ey) \
@@ -8138,12 +8134,11 @@ namespace basist
}
bool basisu_lowlevel_transcoder::transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
uint32_t output_block_or_pixel_stride_in_bytes, bool pvrtc_wrap_addressing, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels,
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels,
basisu_transcoder_state* pState, bool transcode_alpha, void *pAlpha_blocks, uint32_t output_rows_in_pixels)
{
(void)transcode_alpha;
(void)pAlpha_blocks;
(void)pvrtc_wrap_addressing;
if (!pState)
pState = &m_def_state;
@@ -8915,9 +8910,9 @@ namespace basist
#if BASISD_SUPPORT_PVRTC1
// PVRTC post process - create per-pixel modulation values.
if (fmt == block_format::cPVRTC1_4_RGB)
fixup_pvrtc1_4_modulation_rgb((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y, pvrtc_wrap_addressing);
fixup_pvrtc1_4_modulation_rgb((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y);
else if (fmt == block_format::cPVRTC1_4_RGBA)
fixup_pvrtc1_4_modulation_rgba((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y, pvrtc_wrap_addressing, pAlpha_blocks, &m_endpoints[0], &m_selectors[0]);
fixup_pvrtc1_4_modulation_rgba((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y, pAlpha_blocks, &m_endpoints[0], &m_selectors[0]);
#endif // BASISD_SUPPORT_PVRTC1
if (pPVRTC_work_mem)
@@ -9535,7 +9530,7 @@ namespace basist
return m_lowlevel_decoder.transcode_slice(pOutput_blocks, slice_desc.m_num_blocks_x, slice_desc.m_num_blocks_y,
pDataU8 + slice_desc.m_file_ofs, slice_desc.m_file_size,
fmt, output_block_or_pixel_stride_in_bytes, (decode_flags & cDecodeFlagsPVRTCWrapAddressing) != 0, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0, *pHeader, slice_desc, output_row_pitch_in_blocks_or_pixels, pState,
fmt, output_block_or_pixel_stride_in_bytes, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0, *pHeader, slice_desc, output_row_pitch_in_blocks_or_pixels, pState,
(decode_flags & cDecodeFlagsOutputHasAlphaIndices) != 0, pAlpha_blocks, output_rows_in_pixels);
}

View File

@@ -139,7 +139,7 @@ namespace basist
bool decode_tables(const uint8_t *pTable_data, uint32_t table_data_size);
bool transcode_slice(void *pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t *pImage_data, uint32_t image_data_size, block_format fmt,
uint32_t output_block_or_pixel_stride_in_bytes, bool wrap_addressing, bool bc1_allow_threecolor_blocks, const basis_file_header &header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header &header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
basisu_transcoder_state *pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0);
private:
@@ -304,9 +304,6 @@ namespace basist
enum
{
// PVRTC1: texture will use wrap addressing vs. clamp (most PVRTC viewer tools assume wrap addressing, so we default to wrap although that can cause edge artifacts)
cDecodeFlagsPVRTCWrapAddressing = 1,
// PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2.
cDecodeFlagsPVRTCDecodeToNextPow2 = 2,
@@ -339,7 +336,7 @@ namespace basist
uint32_t image_index, uint32_t level_index,
void *pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
transcoder_texture_format fmt,
uint32_t decode_flags = cDecodeFlagsPVRTCWrapAddressing, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state *pState = nullptr, uint32_t output_rows_in_pixels = 0) const;
uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state *pState = nullptr, uint32_t output_rows_in_pixels = 0) const;
// Finds the basis slice corresponding to the specified image/level/alpha params, or -1 if the slice can't be found.
int find_slice(const void *pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const;
@@ -355,7 +352,7 @@ namespace basist
// - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
bool transcode_slice(const void *pData, uint32_t data_size, uint32_t slice_index,
void *pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
block_format fmt, uint32_t output_block_stride_in_bytes, uint32_t decode_flags = cDecodeFlagsPVRTCWrapAddressing, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state * pState = nullptr, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0) const;
block_format fmt, uint32_t output_block_stride_in_bytes, uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state * pState = nullptr, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0) const;
private:
mutable basisu_lowlevel_transcoder m_lowlevel_decoder;

View File

@@ -236,7 +236,8 @@ function dataLoaded(data)
const dstSize = basisFile.getImageTranscodedSizeInBytes(0, 0, format);
const dst = new Uint8Array(dstSize);
if (!basisFile.transcodeImage(dst, 0, 0, format, 1, 0)) {
// if (!basisFile.transcodeImage(dst, 0, 0, format, 1, 0)) {
if (!basisFile.transcodeImage(dst, 0, 0, format, 0, 0)) {
log('basisFile.transcodeImage failed');
console.warn('transcodeImage failed');
basisFile.close();

View File

@@ -154,7 +154,9 @@ struct basis_file
return m_transcoder.start_transcoding(m_file.data(), m_file.size());
}
uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t pvrtc_wrap_addressing, uint32_t get_alpha_for_opaque_formats) {
uint32_t transcodeImage(const emscripten::val& dst, uint32_t image_index, uint32_t level_index, uint32_t format, uint32_t unused, uint32_t get_alpha_for_opaque_formats) {
(void)unused;
assert(m_magic == MAGIC);
if (m_magic != MAGIC)
return 0;
@@ -170,7 +172,7 @@ struct basis_file
std::vector<uint8_t> dst_data;
uint32_t flags = (pvrtc_wrap_addressing ? basisu_transcoder::cDecodeFlagsPVRTCWrapAddressing : 0) | (get_alpha_for_opaque_formats ? basisu_transcoder::cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0);
uint32_t flags = get_alpha_for_opaque_formats ? basisu_transcoder::cDecodeFlagsTranscodeAlphaDataToOpaqueFormats : 0;
uint32_t status;
@@ -255,8 +257,8 @@ EMSCRIPTEN_BINDINGS(basis_transcoder) {
.function("startTranscoding", optional_override([](basis_file& self) {
return self.startTranscoding();
}))
.function("transcodeImage", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t levelIndex, uint32_t format, uint32_t pvrtcWrapAddressing, uint32_t getAlphaForOpaqueFormats) {
return self.transcodeImage(dst, imageIndex, levelIndex, format, pvrtcWrapAddressing, getAlphaForOpaqueFormats);
.function("transcodeImage", optional_override([](basis_file& self, const emscripten::val& dst, uint32_t imageIndex, uint32_t levelIndex, uint32_t format, uint32_t unused, uint32_t getAlphaForOpaqueFormats) {
return self.transcodeImage(dst, imageIndex, levelIndex, format, unused, getAlphaForOpaqueFormats);
}))
;