1Name 2 3 EXT_texture_shared_exponent 4 5Name Strings 6 7 GL_EXT_texture_shared_exponent 8 9Contact 10 11 Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com) 12 13Contributors 14 15 Pat Brown, NVIDIA 16 Jon Leech 17 Bruce Merry, ARM 18 19Status 20 21 Shipping 22 23Version 24 25 Date: July 18, 2008 26 Revision: 1.0 27 28Number 29 30 333 31 32Dependencies 33 34 OpenGL 1.1 required 35 36 ARB_color_buffer_float affects this extension. 37 38 EXT_framebuffer_object affects this extension. 39 40 This extension is written against the OpenGL 2.0 (September 7, 41 2004) specification. 42 43Overview 44 45 Existing texture formats provide either fixed-point formats with 46 limited range and precision but with compact encodings (allowing 32 47 or fewer bits per multi-component texel), or floating-point formats 48 with tremendous range and precision but without compact encodings 49 (typically 16 or 32 bits per component). 50 51 This extension adds a new packed format and new internal texture 52 format for encoding 3-component vectors (typically RGB colors) with 53 a single 5-bit exponent (biased up by 15) and three 9-bit mantissas 54 for each respective component. There is no sign bit so all three 55 components must be non-negative. The fractional mantissas are 56 stored without an implied 1 to the left of the decimal point. 57 Neither infinity nor not-a-number (NaN) are representable in this 58 shared exponent format. 59 60 This 32 bits/texel shared exponent format is particularly well-suited 61 to high dynamic range (HDR) applications where light intensity is 62 typically stored as non-negative red, green, and blue components 63 with considerable range. 64 65New Procedures and Functions 66 67 None 68 69New Tokens 70 71 Accepted by the <internalformat> parameter of TexImage1D, 72 TexImage2D, TexImage3D, CopyTexImage1D, CopyTexImage2D, and 73 RenderbufferStorageEXT: 74 75 RGB9_E5_EXT 0x8C3D 76 77 Accepted by the <type> parameter of DrawPixels, ReadPixels, 78 TexImage1D, TexImage2D, GetTexImage, TexImage3D, TexSubImage1D, 79 TexSubImage2D, TexSubImage3D, GetHistogram, GetMinmax, 80 ConvolutionFilter1D, ConvolutionFilter2D, ConvolutionFilter3D, 81 GetConvolutionFilter, SeparableFilter2D, GetSeparableFilter, 82 ColorTable, ColorSubTable, and GetColorTable: 83 84 UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E 85 86 Accepted by the <pname> parameter of GetTexLevelParameterfv and 87 GetTexLevelParameteriv: 88 89 TEXTURE_SHARED_SIZE_EXT 0x8C3F 90 91Additions to Chapter 2 of the 2.0 Specification (OpenGL Operation) 92 93 None 94 95Additions to Chapter 3 of the 2.0 Specification (Rasterization) 96 97 -- Section 3.6.4, Rasterization of Pixel Rectangles 98 99 Add a new row to Table 3.5 (page 128): 100 101 type Parameter Corresponding Special 102 Token Name GL Data Type Interpretation 103 ----------------------------- ------------- -------------- 104 UNSIGNED_INT_5_9_9_9_REV_EXT uint yes 105 106 Add a new row to table 3.8: Packed pixel formats (page 132): 107 108 type Parameter GL Data Number of Matching 109 Token Name Type Components Pixel Formats 110 ----------------------------- ------- ---------- ------------- 111 UNSIGNED_INT_5_9_9_9_REV_EXT uint 4 RGB 112 113 Add a new entry to table 3.11: UNSIGNED_INT formats (page 134): 114 115 UNSIGNED_INT_5_9_9_9_REV_EXT: 116 117 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 118 +-------------+--------------------------+---------------------------+--------------------------+ 119 | 4th | 3rd | 2nd | 1st | 120 +-------------+--------------------------+---------------------------+--------------------------+ 121 122 Add to the end of the 2nd paragraph starting "Pixels are draw using": 123 124 "If type is UNSIGNED_INT_5_9_9_9_REV_EXT and format is not RGB then 125 the error INVALID_ENUM occurs." 126 127 Add UNSIGNED_INT_5_9_9_9_REV_EXT to the list of packed formats in 128 the 10th paragraph after the "Packing" subsection (page 130). 129 130 Add before the 3rd paragraph (page 135, starting "Calling DrawPixels 131 with a type of BITMAP...") from the end of the "Packing" subsection: 132 133 "Calling DrawPixels with a type of UNSIGNED_INT_5_9_9_9_REV_EXT and 134 format of RGB is a special case in which the data are a series of GL 135 uint values. Each uint value specifies 4 packed components as shown 136 in table 3.11. The 1st, 2nd, 3rd, and 4th components are called 137 p_red, p_green, p_blue, and p_exp respectively and are treated as 138 unsigned integers. These are then used to compute floating-point 139 RGB components (ignoring the "Conversion to floating-point" section 140 below in this case) as follows: 141 142 red = p_red * 2^(p_exp - B - N) 143 green = p_green * 2^(p_exp - B - N) 144 blue = p_blue * 2^(p_exp - B - N) 145 146 where B is 15 (the exponent bias) and N is 9 (the number of mantissa 147 bits)." 148 149 -- Section 3.8.1, Texture Image Specification: 150 151 "Alternatively if the internalformat is RGB9_E5_EXT, the red, green, 152 and blue bits are converted to a shared exponent format according 153 to the following procedure: 154 155 Components red, green, and blue are first clamped (in the process, 156 mapping NaN to zero) so: 157 158 red_c = max(0, min(sharedexp_max, red)) 159 green_c = max(0, min(sharedexp_max, green)) 160 blue_c = max(0, min(sharedexp_max, blue)) 161 162 where sharedexp_max is (2^N-1)/2^N * 2^(Emax-B), N is the number 163 of mantissa bits per component, Emax is the maximum allowed biased 164 exponent value (careful: not necessarily 2^E-1 when E is the number of 165 exponent bits), bits, and B is the exponent bias. For the RGB9_E5_EXT 166 format, N=9, Emax=31, and B=15. 167 168 The largest clamped component, max_c, is determined: 169 170 max_c = max(red_c, green_c, blue_c) 171 172 A preliminary shared exponent is computed: 173 174 exp_shared_p = max(-B-1, floor(log2(max_c))) + 1 + B 175 176 A refined shared exponent is then computed as: 177 178 max_s = floor(max_c / 2^(exp_shared_p - B - N) + 0.5) 179 180 { exp_shared_p, 0 <= max_s < 2^N 181 exp_shared = { 182 { exp_shared_p+1, max_s == 2^N 183 184 These integers values in the range 0 to 2^N-1 are then computed: 185 186 red_s = floor(red_c / 2^(exp_shared - B - N) + 0.5) 187 green_s = floor(green_c / 2^(exp_shared - B - N) + 0.5) 188 blue_s = floor(blue_c / 2^(exp_shared - B - N) + 0.5) 189 190 Then red_s, green_s, and blue_s are stored along with exp_shared in 191 the red, green, blue, and shared bits respectively of the texture 192 image. 193 194 An implementation accepting pixel data of type 195 UNSIGNED_INT_5_9_9_9_REV_EXT with a format of RGB is allowed to store 196 the components "as is" if the implementation can determine the current 197 pixel transfer state act as an identity transform on the components." 198 199 Add a new row and the "shared bits" column (blank for all existing 200 rows) to Table 3.16 (page 154). 201 202 Sized Base R G B A L I D shared 203 Internal Format Internal Format bits bits bits bits bits bits bits bits 204 --------------------- --------------- ---- ---- ---- ---- ---- ---- ---- ------ 205 RGB9_E5_EXT RGB 9 9 9 5 206 207 -- Section 3.8.x, Shared Exponent Texture Color Conversion 208 209 Insert this section AFTER section 3.8.14 Texture Comparison Modes 210 and BEFORE section 3.8.15 Texture Application (and after the "sRGB 211 Texture Color Conversion" if EXT_texture_sRGB is supported). 212 213 "If the currently bound texture's internal format is RGB9_E5_EXT, the 214 red, green, blue, and shared bits are converted to color components 215 (prior to filtering) using the following shared exponent decoding. 216 217 The components red_s, green_s, blue_s, and exp_shared values (see 218 section 3.8.1) are treated as unsigned integers and are converted 219 to red, green, blue as follows: 220 221 red = red_s * 2^(exp_shared - B) 222 green = green_s * 2^(exp_shared - B) 223 blue = blue_s * 2^(exp_shared - B)" 224 225Additions to Chapter 4 of the 2.0 Specification (Per-Fragment Operations 226and the Frame Buffer) 227 228 -- Section 4.3.2, Reading Pixels 229 230 Add a row to table 4.7 (page 224); 231 232 Component 233 type Parameter GL Data Type Conversion Formula 234 ----------------------------- ------------ ------------------ 235 UNSIGNED_INT_5_9_9_9_REV_EXT uint special 236 237 Replace second paragraph of "Final Conversion" (page 222) to read: 238 239 For an RGBA color, if <type> is not FLOAT or 240 UNSIGNED_INT_5_9_9_9_REV_EXT, or if the CLAMP_READ_COLOR_ARB is 241 TRUE, or CLAMP_READ_COLOR_ARB is FIXED_ONLY_ARB and the selected 242 color (or texture) buffer is a fixed-point buffer, each component 243 is first clamped to [0,1]. Then the appropriate conversion formula 244 from table 4.7 is applied the component. 245 246 In the special case when calling ReadPixels with a type of 247 UNSIGNED_INT_5_9_9_9_REV_EXT and format of RGB, the conversion 248 is done as follows: The returned data are packed into a series of 249 GL uint values. The red, green, and blue components are converted 250 to red_s, green_s, blue_s, and exp_shared integers as described in 251 section 3.8.1 when the internalformat is RGB9_E5_EXT. The red_s, 252 green_s, blue_s, and exp_shared are then packed as the 1st, 2nd, 253 3rd, and 4th components of the UNSIGNED_INT_5_9_9_9_REV_EXT format 254 as shown in table 3.11." 255 256Additions to Chapter 5 of the 2.0 Specification (Special Functions) 257 258 None 259 260Additions to Chapter 6 of the 2.0 Specification (State and State Requests) 261 262 -- Section 6.1.3, Enumerated Queries 263 264 Add TEXTURE_SHARED_SIZE_EXT to the list of queries in the first 265 sentence of the fifth paragraph (page 247) so it reads: 266 267 "For texture images with uncompressed internal formats, queries of 268 value of TEXTURE_RED_SIZE, TEXTURE_GREEN_SIZE, TEXTURE_BLUE_SIZE, 269 TEXTURE_ALPHA_SIZE, TEXTURE_LUMINANCE_SIZE, TEXTURE_DEPTH_SIZE, 270 TEXTURE_SHARED_SIZE_EXTT, and TEXTURE_INTENSITY_SIZE return the 271 actual resolutions of the stored image array components, not the 272 resolutions specified when the image array was defined." 273 274Additions to the OpenGL Shading Language specification 275 276 None 277 278Additions to the GLX Specification 279 280 None 281 282GLX Protocol 283 284 None. 285 286Dependencies on ARB_color_buffer_float 287 288 If ARB_color_buffer_float is not supported, replace this amended 289 sentence from 4.3.2 above 290 291 "For an RGBA color, if <type> is not FLOAT or 292 UNSIGNED_INT_5_9_9_9_REV_EXT, or if the CLAMP_READ_COLOR_ARB is TRUE, or 293 CLAMP_READ_COLOR_ARB is FIXED_ONLY_ARB and the selected color buffer 294 (or texture image for GetTexImage) is a fixed-point buffer (or texture 295 image for GetTexImage), each component is first clamped to [0,1]." 296 297 with 298 299 "For an RGBA color, if <type> is not FLOAT or 300 UNSIGNED_INT_5_9_9_9_REV_EXT and the selected color buffer (or 301 texture image for GetTexImage) is a fixed-point buffer (or texture 302 image for GetTexImage), each component is first clamped to [0,1]." 303 304Dependencies on EXT_framebuffer_object 305 306 If EXT_framebuffer_object is not supported, then 307 RenderbufferStorageEXT is not supported and the RGB9_E5_EXT 308 internalformat is therefore not supported by RenderbufferStorageEXT. 309 310Errors 311 312 Relaxation of INVALID_ENUM errors 313 --------------------------------- 314 315 TexImage1D, TexImage2D, TexImage3D, CopyTexImage1D, CopyTexImage2D, 316 and RenderbufferStorageEXT accept the new RGB9_E5_EXT token for 317 internalformat. 318 319 DrawPixels, ReadPixels, TexImage1D, TexImage2D, GetTexImage, 320 TexImage3D, TexSubImage1D, TexSubImage2D, TexSubImage3D, 321 GetHistogram, GetMinmax, ConvolutionFilter1D, ConvolutionFilter2D, 322 ConvolutionFilter3D, GetConvolutionFilter, SeparableFilter2D, 323 GetSeparableFilter, ColorTable, ColorSubTable, and GetColorTable 324 accept the new UNSIGNED_INT_5_9_9_9_REV_EXT token for type. 325 326 GetTexLevelParameterfv and GetTexLevelParameteriv accept the new 327 TEXTURE_SHARED_SIZE_EXT token for <pname>. 328 329 New errors 330 ---------- 331 332 INVALID_OPERATION is generated by DrawPixels, ReadPixels, TexImage1D, 333 TexImage2D, GetTexImage, TexImage3D, TexSubImage1D, TexSubImage2D, 334 TexSubImage3D, GetHistogram, GetMinmax, ConvolutionFilter1D, 335 ConvolutionFilter2D, ConvolutionFilter3D, GetConvolutionFilter, 336 SeparableFilter2D, GetSeparableFilter, ColorTable, ColorSubTable, 337 and GetColorTable if <type> is UNSIGNED_INT_5_9_9_9_REV_EXT 338 and <format> is not RGB. 339 340New State 341 342 In table 6.17, Textures (page 278), increment the 42 in "n x Z42*" 343 by 1 for the RGB9_E5_EXT format. 344 345 [NOTE: The OpenGL 2.0 specification actually should read "n x Z48*" 346 because of the 6 generic compressed internal formats in table 3.18.] 347 348 Add the following entry to table 6.17: 349 350Get Value Type Get Command Value Description Sec. Attribute 351----------------------- ------ -------------------- ------- ------------------------------------ ---- --------- 352TEXTURE_SHARED_SIZE_EXT n x Z+ GetTexLevelParameter 0 xD texture image i's shared exponent 3.8 - 353 field size 354 355New Implementation Dependent State 356 357 None 358 359Appendix 360 361 This source code provides ANSI C routines. It assumes the C "float" 362 data type is stored with the IEEE 754 32-bit floating-point format. 363 Make sure you define __LITTLE_ENDIAN or __BIG_ENDIAN appropriate 364 for your target system. 365 366 XXX: code below not tested on big-endian platform... 367 368------------------- start of source code ------------------------ 369 370#include <assert.h> 371#include <math.h> 372#include <stdio.h> 373#include <stdlib.h> 374 375#define __LITTLE_ENDIAN 1 376#define __BIG_ENDIAN 2 377 378#ifdef _WIN32 379#define __BYTE_ORDER __LITTLE_ENDIAN 380#endif 381 382#define RGB9E5_EXPONENT_BITS 5 383#define RGB9E5_MANTISSA_BITS 9 384#define RGB9E5_EXP_BIAS 15 385#define RGB9E5_MAX_VALID_BIASED_EXP 31 386 387#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) 388#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS) 389#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1) 390#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP)) 391#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS)) 392 393typedef struct { 394#ifdef __BYTE_ORDER 395#if __BYTE_ORDER == __BIG_ENDIAN 396 unsigned int negative:1; 397 unsigned int biasedexponent:8; 398 unsigned int mantissa:23; 399#elif __BYTE_ORDER == __LITTLE_ENDIAN 400 unsigned int mantissa:23; 401 unsigned int biasedexponent:8; 402 unsigned int negative:1; 403#endif 404#endif 405} BitsOfIEEE754; 406 407typedef union { 408 unsigned int raw; 409 float value; 410 BitsOfIEEE754 field; 411} float754; 412 413typedef struct { 414#ifdef __BYTE_ORDER 415#if __BYTE_ORDER == __BIG_ENDIAN 416 unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 417 unsigned int b:RGB9E5_MANTISSA_BITS; 418 unsigned int g:RGB9E5_MANTISSA_BITS; 419 unsigned int r:RGB9E5_MANTISSA_BITS; 420#elif __BYTE_ORDER == __LITTLE_ENDIAN 421 unsigned int r:RGB9E5_MANTISSA_BITS; 422 unsigned int g:RGB9E5_MANTISSA_BITS; 423 unsigned int b:RGB9E5_MANTISSA_BITS; 424 unsigned int biasedexponent:RGB9E5_EXPONENT_BITS; 425#endif 426#endif 427} BitsOfRGB9E5; 428 429typedef union { 430 unsigned int raw; 431 BitsOfRGB9E5 field; 432} rgb9e5; 433 434float ClampRange_for_rgb9e5(float x) 435{ 436 if (x > 0.0) { 437 if (x >= MAX_RGB9E5) { 438 return MAX_RGB9E5; 439 } else { 440 return x; 441 } 442 } else { 443 /* NaN gets here too since comparisons with NaN always fail! */ 444 return 0.0; 445 } 446} 447 448float MaxOf3(float x, float y, float z) 449{ 450 if (x > y) { 451 if (x > z) { 452 return x; 453 } else { 454 return z; 455 } 456 } else { 457 if (y > z) { 458 return y; 459 } else { 460 return z; 461 } 462 } 463} 464 465/* Ok, FloorLog2 is not correct for the denorm and zero values, but we 466 are going to do a max of this value with the minimum rgb9e5 exponent 467 that will hide these problem cases. */ 468int FloorLog2(float x) 469{ 470 float754 f; 471 472 f.value = x; 473 return (f.field.biasedexponent - 127); 474} 475 476int Max(int x, int y) 477{ 478 if (x > y) { 479 return x; 480 } else { 481 return y; 482 } 483} 484 485rgb9e5 float3_to_rgb9e5(const float rgb[3]) 486{ 487 rgb9e5 retval; 488 float maxrgb; 489 int rm, gm, bm; 490 float rc, gc, bc; 491 int exp_shared; 492 double denom; 493 494 rc = ClampRange_for_rgb9e5(rgb[0]); 495 gc = ClampRange_for_rgb9e5(rgb[1]); 496 bc = ClampRange_for_rgb9e5(rgb[2]); 497 498 maxrgb = MaxOf3(rc, gc, bc); 499 exp_shared = Max(-RGB9E5_EXP_BIAS-1, FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; 500 assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 501 assert(exp_shared >= 0); 502 /* This pow function could be replaced by a table. */ 503 denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); 504 505 maxm = (int) floor(maxrgb / denom + 0.5); 506 if (maxm == MAX_RGB9E5_MANTISSA+1) { 507 denom *= 2; 508 exp_shared += 1; 509 assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); 510 } else { 511 assert(maxm <= MAX_RGB9E5_MANTISSA); 512 } 513 514 rm = (int) floor(rc / denom + 0.5); 515 gm = (int) floor(gc / denom + 0.5); 516 bm = (int) floor(bc / denom + 0.5); 517 518 assert(rm <= MAX_RGB9E5_MANTISSA); 519 assert(gm <= MAX_RGB9E5_MANTISSA); 520 assert(bm <= MAX_RGB9E5_MANTISSA); 521 assert(rm >= 0); 522 assert(gm >= 0); 523 assert(bm >= 0); 524 525 retval.field.r = rm; 526 retval.field.g = gm; 527 retval.field.b = bm; 528 retval.field.biasedexponent = exp_shared; 529 530 return retval; 531} 532 533void rgb9e5_to_float3(rgb9e5 v, float retval[3]) 534{ 535 int exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; 536 float scale = (float) pow(2, exponent); 537 538 retval[0] = v.field.r * scale; 539 retval[1] = v.field.g * scale; 540 retval[2] = v.field.b * scale; 541} 542 543------------------- end of source code ------------------------ 544 545Issues 546 547 1) What should this extension be called? 548 549 RESOLVED: EXT_texture_shared_exponent 550 551 The "EXT_texture" part indicates the extension is in the texture 552 domain and "shared_exponent" indicates the extension is adding 553 a new shared exponent formats. 554 555 EXT_texture_rgb9e5 was considered but there's no precedent for 556 extension names to be so explicit (or cryptic?) about format 557 specifics in the extension name. 558 559 2) There are many possible encodings for a shared exponent format. 560 Which encoding does this extension specify? 561 562 RESOLVED: A single 5-bit exponent stored as an unsigned 563 value biased by 15 and three 9-bit mantissas for each of 3 564 components. There are no sign bits so all three components 565 must be non-negative. The fractional mantissas assume an implied 566 0 left of the decimal point because having an implied leading 567 1 is inconsistent with sharing the exponent. Neither Infinity 568 nor Not-a-Number (NaN) are representable in this shared exponent 569 format. 570 571 We chose this format because it closely matches the range and 572 precision of the s10e5 half-precision floating-point described 573 in the ARB_half_float_pixel and ARB_texture_float specifications. 574 575 3) Why not an 8-bit shared exponent? 576 577 RESOLVED: Greg Ward's RGBE shared exponent encoding uses an 578 8-bit exponent (same as a single-precision IEEE value) but we 579 believe the rgb9e5 is more generally useful than rgb8e8. 580 581 An 8-bit exponent provides far more range than is typically 582 required for graphics applications. However, an extra bit 583 of precision for each component helps in situations where a 584 high magnitude component dominates a low magnitude component. 585 Having an 8-bit shared exponent and 8-bit mantissas are amenable 586 to CPUs that facilitate 8-bit sized reads and writes over non-byte 587 aligned fields, but GPUs do not suffer from this issue. 588 589 Indeed GPUs with s10e5 texture filtering can use that same 590 filtering hardware for rgb9e5 textures. 591 592 However, future extensions could add other shared exponent formats 593 so we name the tokens to indicate the 594 595 4) Should there be an external format and type for rgb9e5? 596 597 RESOLVED: Yes, hence the external format GL_RGB9_E5_EXT and 598 type GL_UNSIGNED_INT_5_9_9_9_REV_EXT. This makes it fast to load 599 GL_RGB9_E5_EXT textures without any translation by the driver. 600 601 5) Why is the exponent bias 15? 602 603 RESOLVED: The best technical choice of 15. Hopefully, this 604 discussion sheds insight into the numerics of the shared exponent 605 format in general. 606 607 With conventional floating-point formats, the number corresponding 608 to a finite, non-denorm, non-zero floating-point value is 609 610 value = -1^sgn * 2^(exp-bias) * 1.frac 611 612 where sgn is the sign bit (so 1 for sgn negative because -1^-1 613 == -1 and 0 means positive because -1^0 == +1), exp is an 614 (unsigned) BIASED exponent and bias is the format's constant bias 615 to subtract to get the unbiased (possibly negative) exponent; 616 and frac is the fractional portion of the mantissa with the 617 "1." indicating an implied leading 1. 618 619 An exp value of zero indicates so-called denormalized values 620 (denorms). With conventional floating-point formats, the number 621 corresponding to a denorm floating-point value is 622 623 value = -1^sgn * 2^(exp-bias+1) * 0.frac 624 625 where the only difference between the denorm and non-denorm case 626 is the bias is one greater in the denorm case and the implied 627 leading digit is a zero instead of a one. 628 629 Ideally, the rgb9e5 shared exponent format would represent 630 roughly the same range of finite values as the s10e5 format 631 specified by the ARB_texture_float extension. The s10e5 format 632 has an exponent bias of 15. 633 634 While conventional floating-point formats cleverly use an implied 635 leading 1 for non-denorm, finite values, a shared exponent format 636 cannot use an implied leading 1 because each component may have 637 a different magnitude for its most-significant binary digit. 638 The implied leading 1 assumes we have the flexibility to adjust 639 the mantissa and exponent together to ensure an implied leading 1. 640 That flexibility is not present when the exponent is shared. 641 642 So the rgb9e5 format cannot assume an implied leading one. 643 Instead, an implied leading zero is assumed (much like the 644 conventional denorm case). 645 646 The rgb9e5 format eliminate support representing negative, 647 Infinite, not-a-number (NaN), and denorm values. 648 649 We've already discussed how the BIASED zero exponent is used to 650 encode denorm values (and zero) with conventional floating-point 651 formats. The largest BIASED exponent (31 for s10e5, 127 for 652 s23e8) for conventional floating-point fomats indicates Infinity 653 and NaN values. This means these two extrema exponent values are 654 "off limits" for run-of-the-mill values. 655 656 The numbers corresponding to a shared exponent format value are: 657 658 value_r = 2^(exp-bias) * 0.frac_r 659 value_g = 2^(exp-bias) * 0.frac_g 660 value_b = 2^(exp-bias) * 0.frac_b 661 662 where there is no sgn since all values are non-negative, exp is 663 the (unsigned) BIASED exponent and bias is the format's constant 664 bias to subtract to get the unbiased (possibly negative) exponent; 665 and frac_r, frac_g, and frac_b are the fractional portion of 666 the mantissas of the r, g, and b components respectively with 667 "0." indicating an implied leading 0. 668 669 There should be no "off limits" exponents for the shared exponent 670 format since there is no requirement for representing Infinity 671 or NaN values and denorm is not a special case. Because of 672 the implied leading zero, any component with all zeros for its 673 mantissa is zero, no matter the shared exponent's value. 674 675 So the run-of-the-mill BIASED range of exponents for s10e5 is 676 1 to 30. But the rgb9e5 shared exponent format consistently 677 uses the same rule for all exponents from 0 to 31. 678 679 What exponent bias best allows us to represent the range of 680 s10e5 with the rgb9e5 format? 15. 681 682 Consider the maximum representable finite s10e5 magnitude. 683 The exponent would be 30 (31 would encode an Infinite or NaN 684 value) and the binary mantissa would be 1 followed by ten 685 fractional 1's. Effectively: 686 687 s10e5_max = 1.1111111111 * 2^(30-15) 688 = 1.1111111111 * 2^15 689 690 For an rgb9e5 value with a bias of 15, the largest representable 691 value is: 692 693 rgb9e5_max = 0.111111111 * 2^(31-15) 694 = 0.111111111 * 2^16 695 = 1.11111111 * 2^15 696 697 If you ignore two LSBs, these values are nearly identical. 698 The rgb9e5_max value is exactly representable as an s10e5 value. 699 700 For an rgb9e5 value with a bias of 15, the smallest non-zero 701 representable value is: 702 703 rgb9e5_min = 0.000000001 * 2^(0-15) 704 rgb9e5_min = 0.000000001 * 2^-15 705 rgb9e5_min = 0.0000000001 * 2^-14 706 707 So the s10e5_min and rgb9e5_min values exactly match (of course, 708 this assumes the shared exponent bias is 15 which might not be 709 the case if other components demand higher exponents). 710 711 8) Should there be an rgb9e5 framebuffer format? 712 713 RESOLVED: No. Rendering to rgb9e5 is better left to another 714 extension and would require the hardware to convert from a 715 (floating-point) RGBA value into an rgb9e5 encoding. 716 717 Interactions with EXT_framebuffer_object are specified, 718 but the expectation is this is not a renderable 719 format and glCheckFramebufferStatusEXT would return 720 GL_FRAMEBUFFER_UNSUPPORTED_EXT. 721 722 An implementation certainly could make this texture internal 723 format renderable when used with a framebuffer object. Note that 724 the shared exponent means masked components may be lossy in 725 their masking. For example, a very small but non-zero value in 726 a masked component could get flushed to zero if a large enough 727 value is written into an unmasked component. 728 729 9) Should automatic mipmap generation be supported for rgb9e5 730 textures? 731 732 RESOLVED: Yes. 733 734 10) Should non-texture and non-framebuffer commands for loading 735 pixel data accept the GL_UNSIGNED_INT_5_9_9_9_REV_EXT type? 736 737 RESOLVED: Yes. 738 739 Once the pixel path has to support the new type/format combination 740 of GL_UNSIGNED_INT_5_9_9_9_REV_EXT / GL_RGB for specifying and 741 querying texture images, it might as well be supported for all 742 commands that pack and unpack RGB pixel data. 743 744 The specification is written such that the glDrawPixels 745 type/format parameters are accepted by glReadPixels, 746 glTexGetImage, glTexImage2D, and other commands that are specified 747 in terms of glDrawPixels. 748 749 11) Should non-texture internal formats (such as for color tables, 750 convolution kernels, histogram bins, and min/max tables) accept 751 GL_RGB9_E5_EXT format? 752 753 RESOLVED: No. 754 755 That's pointless. No hardware is ever likely to support 756 GL_RGB9_E5_EXT internalformats for anything other than textures 757 and maybe color buffers in the future. This format is not 758 interesting for color tables, convolution kernels, etc. 759 760 12) Should a format be supported with sign bits for each component? 761 762 RESOLVED: No. 763 764 An srgb8e5 format with a sign bit per component could be useful 765 but is better left to another extension. 766 767 13) The rgb9e5 allows two 32-bit values encoded as rgb9e5 to 768 correspond to the exact same 3 components when expanded to 769 floating-point. Is this a problem? 770 771 RESOLVED: No, there's no problem here. 772 773 An encoder is likely to always pack components so at least 774 one mantissa will have an explicit leading one, but there's no 775 requirement for that. 776 777 Applications might be able to take advantage of this by quickly 778 dividing all three components by a power-of-two by simply 779 subtracting log2 of the power-of-two from the shared exponent (as 780 long as the exponent is greater than zero prior to the subtract). 781 782 Arguably, the shared exponent format could maintain a slight 783 amount of extra precision (one bit per mantissa) if the format 784 said if the most significant bits of all three mantissas are 785 either all one or all zero and the biased shared exponent was not 786 zero, then an implied leading 1 should be assumed and the shared 787 exponent should be treated as one smaller than it really is. 788 While this would preserve an extra least-significant bit of 789 mantissa precision for components of approximately the same 790 magnitude, it would complicate the encoding and decoding of 791 shared exponent values. 792 793 14) Can you provide some C code for encoding three floating-point 794 values into the rgb9e5 format? 795 796 RESOLVED: Sure. See the Appendix. 797 798 15) Should we support a non-REV version of the 799 GL_UNSIGNED_INT_5_9_9_9_REV_EXT token? 800 801 RESOLVED: No. The shared exponent is always the 5 most 802 significant bits of the 32 bit word. The first (red) mantissa 803 is in the least significant 9 bits, followed by 9 bits for the 804 second (green) mantissa, followed by 9 bits for the third (blue) 805 mantissa. We don't want to promote different arrangements of 806 the bitfields for rgb9e5 values. 807 808 16) Can you use the GL_UNSIGNED_INT_5_9_9_9_REV_EXT format with 809 just any format? 810 811 RESOLVED: You can only use the GL_UNSIGNED_INT_5_9_9_9_REV_EXT 812 format with GL_RGB. Otherwise, the GL generates 813 a GL_INVALID_OPERATION error. Conceptually, 814 GL_UNSIGNED_INT_5_9_9_9_REV_EXT is a 3-component format 815 that just happens to have 5 shared bits too. Just as the 816 GL_UNSIGNED_BYTE_3_3_2 format just works with GL_RGB (or else 817 the GL generates a GL_INVALID_OPERATION error), so should 818 GL_UNSIGNED_INT_5_9_9_9_REV_EXT. 819 820 17) What should GL_TEXTURE_SHARED_SIZE_EXT return when queried with 821 GetTexLevelParameter? 822 823 RESOLVED: Return 5 for the RGB9_E5_EXT internal format and 0 824 for all other existing formats. 825 826 This is a count of the number of bits in the shared exponent. 827 828 18) What should GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, and 829 GL_TEXTURE_BLUE_SIZE return when queried with GetTexLevelParameter 830 for a GL_RGB9_E5_EXT texture? 831 832 RESOLVED: Return 9 for each. 833 834Revision History 835 836 Rev. Date Author Changes 837 ---- -------- -------- -------------------------------------------- 838 0.5 02/18/07 mjk Initial public version 839 1.0 07/18/08 mjk correct significant errors in spec language 840 and C code 841