diff --git a/Source/astcenc_compress_symbolic.cpp b/Source/astcenc_compress_symbolic.cpp index 98d24951..eb4fc917 100644 --- a/Source/astcenc_compress_symbolic.cpp +++ b/Source/astcenc_compress_symbolic.cpp @@ -368,8 +368,9 @@ static float compress_symbolic_block_for_partition_1plane( int max_weight_quant = astc::min(static_cast(QUANT_32), quant_limit); + bool is_hdr = (config.profile == ASTCENC_PRF_HDR) || (config.profile == ASTCENC_PRF_HDR_RGB_LDR_A); auto compute_difference = &compute_symbolic_block_difference_1plane; - if ((partition_count == 1) && !(config.flags & ASTCENC_FLG_MAP_RGBM)) + if ((partition_count == 1) && !(config.flags & ASTCENC_FLG_MAP_RGBM) && !is_hdr) { compute_difference = &compute_symbolic_block_difference_1plane_1partition; } diff --git a/Source/astcenc_decompress_symbolic.cpp b/Source/astcenc_decompress_symbolic.cpp index e7791eef..91e6b444 100644 --- a/Source/astcenc_decompress_symbolic.cpp +++ b/Source/astcenc_decompress_symbolic.cpp @@ -354,6 +354,7 @@ float compute_symbolic_block_difference_2plane( ep0, ep1); vmask4 u8_mask = get_u8_component_mask(config.profile, blk); + bool any_lns = rgb_lns || a_lns; // Unpack and compute error for each texel in the partition unsigned int texel_count = bsd.texel_count; @@ -395,11 +396,20 @@ float compute_symbolic_block_difference_2plane( ); } - vfloat4 error = oldColor - color; - error = min(abs(error), 1e15f); - error = error * error; + // Compute sum of squared errors, weighted by channel weight + vfloat4 error = (oldColor - color); + error = dot(error, error * blk.channel_weight); - summa += min(dot(error, blk.channel_weight), ERROR_CALC_DEFAULT); + // Convert this relative sum of squared error for HDR to avoid light + // channels dominating the error calculations. + // See https://fgiesen.wordpress.com/2024/11/14/mrsse/ + if (any_lns) + { + // TODO: Divisor could be precomputed at load time + error = error / (dot(oldColor, oldColor) + 1e-10f); + } + + summa += min(error, ERROR_CALC_DEFAULT); } return summa.lane<0>(); @@ -451,6 +461,8 @@ float compute_symbolic_block_difference_1plane( rgb_lns, a_lns, ep0, ep1); + bool any_lns = rgb_lns || a_lns; + // Unpack and compute error for each texel in the partition unsigned int texel_count = pi.partition_texel_count[i]; for (unsigned int j = 0; j < texel_count; j++) @@ -492,11 +504,20 @@ float compute_symbolic_block_difference_1plane( ); } - vfloat4 error = oldColor - color; - error = min(abs(error), 1e15f); - error = error * error; + // Compute sum of squared errors, weighted by channel weight + vfloat4 error = (oldColor - color); + error = dot(error, error * blk.channel_weight); + + // Convert this relative sum of squared error for HDR to avoid light + // channels dominating the error calculations + // See https://fgiesen.wordpress.com/2024/11/14/mrsse/ + if (any_lns) + { + // TODO: Divisor could be precomputed at load time + error = error / (dot(oldColor, oldColor) + 1e-10f); + } - summa += min(dot(error, blk.channel_weight), ERROR_CALC_DEFAULT); + summa += min(error, ERROR_CALC_DEFAULT); } }