From 01d391cc2a00291319801085016d321d1cd85559 Mon Sep 17 00:00:00 2001 From: richgel999 Date: Sun, 29 Sep 2019 19:34:00 -0700 Subject: [PATCH] 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. --- basisu_gpu_texture.cpp | 4 +-- basisu_gpu_texture.h | 2 +- basisu_pvrtc1_4.cpp | 42 +++++++++-------------------- basisu_pvrtc1_4.h | 28 ++++++++----------- basisu_tool.cpp | 12 +++------ transcoder/basisu_transcoder.cpp | 25 +++++++---------- transcoder/basisu_transcoder.h | 9 +++---- webgl/texture/index.html | 3 ++- webgl/transcoder/basis_wrappers.cpp | 10 ++++--- 9 files changed, 50 insertions(+), 85 deletions(-) diff --git a/basisu_gpu_texture.cpp b/basisu_gpu_texture.cpp index fb9c392..117668c 100644 --- a/basisu_gpu_texture.cpp +++ b/basisu_gpu_texture.cpp @@ -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; diff --git a/basisu_gpu_texture.h b/basisu_gpu_texture.h index 26a507e..8a49757 100644 --- a/basisu_gpu_texture.h +++ b/basisu_gpu_texture.h @@ -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) { diff --git a/basisu_pvrtc1_4.cpp b/basisu_pvrtc1_4.cpp index 5a732b2..f0122fc 100644 --- a/basisu_pvrtc1_4.cpp +++ b/basisu_pvrtc1_4.cpp @@ -193,21 +193,12 @@ namespace basisu int block_x1 = block_x0 + 1; int block_y0 = (static_cast(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(block_x0, 0, m_block_width - 1); - block_x1 = clamp(block_x1, 0, m_block_width - 1); - block_y0 = clamp(block_y0, 0, m_block_height - 1); - block_y1 = clamp(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(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(block_x0, 0, m_block_width - 1); - block_x1 = clamp(block_x1, 0, m_block_width - 1); - block_y0 = clamp(block_y0, 0, m_block_height - 1); - block_y1 = clamp(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) diff --git a/basisu_pvrtc1_4.h b/basisu_pvrtc1_4.h index 71c4fba..80b4413 100644 --- a/basisu_pvrtc1_4.h +++ b/basisu_pvrtc1_4.h @@ -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(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(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(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(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; }; diff --git a/basisu_tool.cpp b/basisu_tool.cpp index f90f398..4003a01 100644 --- a/basisu_tool.cpp +++ b/basisu_tool.cpp @@ -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++; diff --git a/transcoder/basisu_transcoder.cpp b/transcoder/basisu_transcoder.cpp index d7386d1..ddaf949 100644 --- a/transcoder/basisu_transcoder.cpp +++ b/transcoder/basisu_transcoder.cpp @@ -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(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(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(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(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(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(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); } diff --git a/transcoder/basisu_transcoder.h b/transcoder/basisu_transcoder.h index 6d96255..770c641 100644 --- a/transcoder/basisu_transcoder.h +++ b/transcoder/basisu_transcoder.h @@ -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; diff --git a/webgl/texture/index.html b/webgl/texture/index.html index 97191eb..8991f80 100644 --- a/webgl/texture/index.html +++ b/webgl/texture/index.html @@ -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(); diff --git a/webgl/transcoder/basis_wrappers.cpp b/webgl/transcoder/basis_wrappers.cpp index c281af0..356a4f9 100644 --- a/webgl/transcoder/basis_wrappers.cpp +++ b/webgl/transcoder/basis_wrappers.cpp @@ -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 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); })) ;