astc_encoding_choice_error.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*----------------------------------------------------------------------------*/
  2. /**
  3. * This confidential and proprietary software may be used only as
  4. * authorised by a licensing agreement from ARM Limited
  5. * (C) COPYRIGHT 2011-2012 ARM Limited
  6. * ALL RIGHTS RESERVED
  7. *
  8. * The entire notice above must be reproduced on all authorised
  9. * copies and copies may only be made to the extent permitted
  10. * by a licensing agreement from ARM Limited.
  11. *
  12. * @brief Determine color errors for ASTC compression.
  13. *
  14. * We assume that there are two independent sources of color error in
  15. * any given partition.
  16. *
  17. * These are:
  18. * * quantization errors
  19. * * encoding choice errors
  20. *
  21. * Encoding choice errors are errors that come due to encoding choice,
  22. * such as:
  23. * * using luminance instead of RGB
  24. * * using RGB-scale instead of two RGB endpoints.
  25. * * dropping Alpha
  26. *
  27. * Quantization errors occur due to the limited precision we use for
  28. * storing numbers.
  29. *
  30. * Quantization errors generally scale with quantization level, but are
  31. * not actually independent of color encoding. In particular:
  32. * * if we can use offset encoding then quantization error is halved.
  33. * * if we can use blue-contraction, quantization error for red and
  34. * green is halved.
  35. * * quantization error is higher for the HDR endpoint modes.
  36. *
  37. * Other than these errors, quantization error is assumed to be
  38. * proportional to the quantization step.
  39. */
  40. /*----------------------------------------------------------------------------*/
  41. #include "astc_codec_internals.h"
  42. #include <math.h>
  43. #ifdef DEBUG_PRINT_DIAGNOSTICS
  44. #include <stdio.h>
  45. #endif
  46. // helper function to merge two endpoint-colors
  47. void merge_endpoints(const endpoints * ep1, // contains three of the color components
  48. const endpoints * ep2, // contains the remaining color component
  49. int separate_component, endpoints * res)
  50. {
  51. int i;
  52. int partition_count = ep1->partition_count;
  53. res->partition_count = partition_count;
  54. for (i = 0; i < partition_count; i++)
  55. {
  56. res->endpt0[i] = ep1->endpt0[i];
  57. res->endpt1[i] = ep1->endpt1[i];
  58. }
  59. switch (separate_component)
  60. {
  61. case 0:
  62. for (i = 0; i < partition_count; i++)
  63. {
  64. res->endpt0[i].x = ep2->endpt0[i].x;
  65. res->endpt1[i].x = ep2->endpt1[i].x;
  66. }
  67. break;
  68. case 1:
  69. for (i = 0; i < partition_count; i++)
  70. {
  71. res->endpt0[i].y = ep2->endpt0[i].y;
  72. res->endpt1[i].y = ep2->endpt1[i].y;
  73. }
  74. break;
  75. case 2:
  76. for (i = 0; i < partition_count; i++)
  77. {
  78. res->endpt0[i].z = ep2->endpt0[i].z;
  79. res->endpt1[i].z = ep2->endpt1[i].z;
  80. }
  81. break;
  82. case 3:
  83. for (i = 0; i < partition_count; i++)
  84. {
  85. res->endpt0[i].w = ep2->endpt0[i].w;
  86. res->endpt1[i].w = ep2->endpt1[i].w;
  87. }
  88. break;
  89. }
  90. }
  91. /*
  92. for a given set of input colors and a given partitioning, determine: color error that results
  93. from RGB-scale encoding (relevant for LDR only) color error that results from RGB-lumashift encoding
  94. (relevant for HDR only) color error that results from luminance-encoding color error that results
  95. form dropping alpha. whether we are eligible for offset encoding whether we are eligible for
  96. blue-contraction
  97. The input data are: color data partitioning error-weight data
  98. */
  99. void compute_encoding_choice_errors(int xdim, int ydim, int zdim, const imageblock * pb, const partition_info * pi, const error_weight_block * ewb,
  100. int separate_component, // component that is separated out in 2-plane mode, -1 in 1-plane mode
  101. encoding_choice_errors * eci)
  102. {
  103. int i;
  104. int partition_count = pi->partition_count;
  105. int texels_per_block = xdim * ydim * zdim;
  106. #ifdef DEBUG_PRINT_DIAGNOSTICS
  107. if (print_diagnostics)
  108. {
  109. printf("%s : texels-per-block=%dx%dx%d, separate_component=%d, partition-count=%d\n", __func__, xdim, ydim, zdim, separate_component, partition_count);
  110. }
  111. #endif
  112. float3 averages[4];
  113. float3 directions_rgb[4];
  114. float2 directions_rg[4];
  115. float2 directions_rb[4];
  116. float2 directions_gb[4];
  117. float4 error_weightings[4];
  118. float4 color_scalefactors[4];
  119. float4 inverse_color_scalefactors[4];
  120. compute_partition_error_color_weightings(xdim, ydim, zdim, ewb, pi, error_weightings, color_scalefactors);
  121. compute_averages_and_directions_rgb(pi, pb, ewb, color_scalefactors, averages, directions_rgb, directions_rg, directions_rb, directions_gb);
  122. line3 uncorr_rgb_lines[4];
  123. line3 samechroma_rgb_lines[4]; // for LDR-RGB-scale
  124. line3 rgb_luma_lines[4]; // for HDR-RGB-scale
  125. line3 luminance_lines[4];
  126. processed_line3 proc_uncorr_rgb_lines[4];
  127. processed_line3 proc_samechroma_rgb_lines[4]; // for LDR-RGB-scale
  128. processed_line3 proc_rgb_luma_lines[4]; // for HDR-RGB-scale
  129. processed_line3 proc_luminance_lines[4];
  130. for (i = 0; i < partition_count; i++)
  131. {
  132. inverse_color_scalefactors[i].x = 1.0f / MAX(color_scalefactors[i].x, 1e-7f);
  133. inverse_color_scalefactors[i].y = 1.0f / MAX(color_scalefactors[i].y, 1e-7f);
  134. inverse_color_scalefactors[i].z = 1.0f / MAX(color_scalefactors[i].z, 1e-7f);
  135. inverse_color_scalefactors[i].w = 1.0f / MAX(color_scalefactors[i].w, 1e-7f);
  136. uncorr_rgb_lines[i].a = averages[i];
  137. if (dot(directions_rgb[i], directions_rgb[i]) == 0.0f)
  138. uncorr_rgb_lines[i].b = normalize(float3(color_scalefactors[i].xyz));
  139. else
  140. uncorr_rgb_lines[i].b = normalize(directions_rgb[i]);
  141. samechroma_rgb_lines[i].a = float3(0, 0, 0);
  142. if (dot(averages[i], averages[i]) < 1e-20)
  143. samechroma_rgb_lines[i].b = normalize(float3(color_scalefactors[i].xyz));
  144. else
  145. samechroma_rgb_lines[i].b = normalize(averages[i]);
  146. rgb_luma_lines[i].a = averages[i];
  147. rgb_luma_lines[i].b = normalize(color_scalefactors[i].xyz);
  148. luminance_lines[i].a = float3(0, 0, 0);
  149. luminance_lines[i].b = normalize(color_scalefactors[i].xyz);
  150. #ifdef DEBUG_PRINT_DIAGNOSTICS
  151. if (print_diagnostics)
  152. {
  153. printf("Partition %d\n", i);
  154. printf("Average = <%g %g %g>\n", averages[i].x, averages[i].y, averages[i].z);
  155. printf("Uncorr-rgb-line = <%g %g %g> + t<%g %g %g>\n",
  156. uncorr_rgb_lines[i].a.x, uncorr_rgb_lines[i].a.y, uncorr_rgb_lines[i].a.z, uncorr_rgb_lines[i].b.x, uncorr_rgb_lines[i].b.y, uncorr_rgb_lines[i].b.z);
  157. printf("Samechroma-line = t<%g %g %g>\n", samechroma_rgb_lines[i].b.x, samechroma_rgb_lines[i].b.y, samechroma_rgb_lines[i].b.z);
  158. }
  159. #endif
  160. proc_uncorr_rgb_lines[i].amod = (uncorr_rgb_lines[i].a - uncorr_rgb_lines[i].b * dot(uncorr_rgb_lines[i].a, uncorr_rgb_lines[i].b)) * inverse_color_scalefactors[i].xyz;
  161. proc_uncorr_rgb_lines[i].bs = uncorr_rgb_lines[i].b * color_scalefactors[i].xyz;
  162. proc_uncorr_rgb_lines[i].bis = uncorr_rgb_lines[i].b * inverse_color_scalefactors[i].xyz;
  163. proc_samechroma_rgb_lines[i].amod = (samechroma_rgb_lines[i].a - samechroma_rgb_lines[i].b * dot(samechroma_rgb_lines[i].a, samechroma_rgb_lines[i].b)) * inverse_color_scalefactors[i].xyz;
  164. proc_samechroma_rgb_lines[i].bs = samechroma_rgb_lines[i].b * color_scalefactors[i].xyz;
  165. proc_samechroma_rgb_lines[i].bis = samechroma_rgb_lines[i].b * inverse_color_scalefactors[i].xyz;
  166. proc_rgb_luma_lines[i].amod = (rgb_luma_lines[i].a - rgb_luma_lines[i].b * dot(rgb_luma_lines[i].a, rgb_luma_lines[i].b)) * inverse_color_scalefactors[i].xyz;
  167. proc_rgb_luma_lines[i].bs = rgb_luma_lines[i].b * color_scalefactors[i].xyz;
  168. proc_rgb_luma_lines[i].bis = rgb_luma_lines[i].b * inverse_color_scalefactors[i].xyz;
  169. proc_luminance_lines[i].amod = (luminance_lines[i].a - luminance_lines[i].b * dot(luminance_lines[i].a, luminance_lines[i].b)) * inverse_color_scalefactors[i].xyz;
  170. proc_luminance_lines[i].bs = luminance_lines[i].b * color_scalefactors[i].xyz;
  171. proc_luminance_lines[i].bis = luminance_lines[i].b * inverse_color_scalefactors[i].xyz;
  172. }
  173. float uncorr_rgb_error[4];
  174. float samechroma_rgb_error[4];
  175. float rgb_luma_error[4];
  176. float luminance_rgb_error[4];
  177. for (i = 0; i < partition_count; i++)
  178. {
  179. uncorr_rgb_error[i] = compute_error_squared_rgb_single_partition(i, xdim, ydim, zdim, pi, pb, ewb, &(proc_uncorr_rgb_lines[i]));
  180. samechroma_rgb_error[i] = compute_error_squared_rgb_single_partition(i, xdim, ydim, zdim, pi, pb, ewb, &(proc_samechroma_rgb_lines[i]));
  181. rgb_luma_error[i] = compute_error_squared_rgb_single_partition(i, xdim, ydim, zdim, pi, pb, ewb, &(proc_rgb_luma_lines[i]));
  182. luminance_rgb_error[i] = compute_error_squared_rgb_single_partition(i, xdim, ydim, zdim, pi, pb, ewb, &(proc_luminance_lines[i]));
  183. #ifdef DEBUG_PRINT_DIAGNOSTICS
  184. if (print_diagnostics)
  185. {
  186. printf("Partition %d : uncorr-error=%g samechroma-error=%g rgb-luma-error=%g lum-error=%g\n",
  187. i, uncorr_rgb_error[i], samechroma_rgb_error[i], rgb_luma_error[i], luminance_rgb_error[i]);
  188. }
  189. #endif
  190. }
  191. // compute the error that arises from just ditching alpha and RGB
  192. float alpha_drop_error[4];
  193. float rgb_drop_error[4];
  194. for (i = 0; i < partition_count; i++)
  195. {
  196. alpha_drop_error[i] = 0;
  197. rgb_drop_error[i] = 0;
  198. }
  199. for (i = 0; i < texels_per_block; i++)
  200. {
  201. int partition = pi->partition_of_texel[i];
  202. float alpha = pb->work_data[4 * i + 3];
  203. float default_alpha = pb->alpha_lns[i] ? (float)0x7800 : (float)0xFFFF;
  204. float omalpha = alpha - default_alpha;
  205. alpha_drop_error[partition] += omalpha * omalpha * ewb->error_weights[i].w;
  206. float red = pb->work_data[4 * i];
  207. float green = pb->work_data[4 * i + 1];
  208. float blue = pb->work_data[4 * i + 2];
  209. rgb_drop_error[partition] += red * red * ewb->error_weights[i].x + green * green * ewb->error_weights[i].y + blue * blue * ewb->error_weights[i].z;
  210. }
  211. // check if we are eligible for blue-contraction and offset-encoding
  212. endpoints ep;
  213. if (separate_component == -1)
  214. {
  215. endpoints_and_weights ei;
  216. compute_endpoints_and_ideal_weights_1_plane(xdim, ydim, zdim, pi, pb, ewb, &ei);
  217. ep = ei.ep;
  218. }
  219. else
  220. {
  221. endpoints_and_weights ei1, ei2;
  222. compute_endpoints_and_ideal_weights_2_planes(xdim, ydim, zdim, pi, pb, ewb, separate_component, &ei1, &ei2);
  223. merge_endpoints(&(ei1.ep), &(ei2.ep), separate_component, &ep);
  224. }
  225. int eligible_for_offset_encode[4];
  226. int eligible_for_blue_contraction[4];
  227. for (i = 0; i < partition_count; i++)
  228. {
  229. float4 endpt0 = ep.endpt0[i];
  230. float4 endpt1 = ep.endpt1[i];
  231. float4 endpt_dif = endpt1 - endpt0;
  232. if (fabs(endpt_dif.x) < (0.12 * 65535.0f) && fabs(endpt_dif.y) < (0.12 * 65535.0f) && fabs(endpt_dif.z) < (0.12 * 65535.0f))
  233. eligible_for_offset_encode[i] = 1;
  234. else
  235. eligible_for_offset_encode[i] = 0;
  236. endpt0.x += (endpt0.x - endpt0.z);
  237. endpt0.y += (endpt0.y - endpt0.z);
  238. endpt1.x += (endpt1.x - endpt1.z);
  239. endpt1.y += (endpt1.y - endpt1.z);
  240. if (endpt0.x > (0.01f * 65535.0f) && endpt0.x < (0.99f * 65535.0f)
  241. && endpt1.x > (0.01f * 65535.0f) && endpt1.x < (0.99f * 65535.0f)
  242. && endpt0.y > (0.01f * 65535.0f) && endpt0.y < (0.99f * 65535.0f) && endpt1.y > (0.01f * 65535.0f) && endpt1.y < (0.99f * 65535.0f))
  243. eligible_for_blue_contraction[i] = 1;
  244. else
  245. eligible_for_blue_contraction[i] = 0;
  246. }
  247. // finally, gather up our results
  248. for (i = 0; i < partition_count; i++)
  249. {
  250. eci[i].rgb_scale_error = (samechroma_rgb_error[i] - uncorr_rgb_error[i]) * 0.7f; // empirical
  251. eci[i].rgb_luma_error = (rgb_luma_error[i] - uncorr_rgb_error[i]) * 1.5f; // wild guess
  252. eci[i].luminance_error = (luminance_rgb_error[i] - uncorr_rgb_error[i]) * 3.0f; // empirical
  253. eci[i].alpha_drop_error = alpha_drop_error[i] * 3.0f;
  254. eci[i].rgb_drop_error = rgb_drop_error[i] * 3.0f;
  255. eci[i].can_offset_encode = eligible_for_offset_encode[i];
  256. eci[i].can_blue_contract = eligible_for_blue_contraction[i];
  257. }
  258. }