1Name 2 3 IMG_framebuffer_downsample 4 5Name Strings 6 7 GL_IMG_framebuffer_downsample 8 9Contributors 10 11 Tobias Hector, Imagination Technologies (tobias.hector 'at' imgtec.com) 12 13Contact 14 15 Tobias Hector (tobias.hector 'at' imgtec.com) 16 17Status 18 19 Complete 20 21Version 22 23 Last Modified Date: August 20, 2015 24 Revision: 11 25 26Number 27 28 OpenGL ES Extension #255 29 30Dependencies 31 32 OpenGL ES 2.0 or OES_framebuffer_object are required. 33 34 This extension is written against the OpenGL ES 3.0.4 Specification 35 (August 27, 2014). 36 37 This extension has interactions with GL_EXT_multisampled_render_to_texture. 38 39 This extension has interactions with OpenGL ES 3.1. 40 41 This extension has interactions with GL_EXT_color_buffer_float. 42 43 This extension has interactions with GL_EXT_color_buffer_half_float. 44 45Overview 46 47 This extension introduces the ability to attach color buffers to a 48 framebuffer that are at a lower resolution than the framebuffer itself, with 49 the GPU automatically downsampling the color attachment to fit. 50 51 This can be useful for various post-process rendering techniques where it is 52 desirable to generate downsampled images in an efficient manner, or for a 53 lower resolution post-process technique. 54 55 This extension exposes at least a 2 x 2 downscale. Other downsampling modes 56 may be exposed on the system and this can be queried. 57 58IP Status 59 60 No known IP claims. 61 62New Procedures and Functions 63 64 void FramebufferTexture2DDownsampleIMG( 65 enum target, enum attachment, 66 enum textarget, uint texture, 67 int level, int xscale, int yscale); 68 69 void FramebufferTextureLayerDownsampleIMG( 70 enum target, enum attachment, 71 uint texture, int level, 72 int layer, int xscale, int yscale); 73 74New Tokens 75 76 Returned by CheckFramebufferStatus: 77 78 FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C 79 80 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, 81 GetInteger64v, and GetInternalFormativ: 82 83 NUM_DOWNSAMPLE_SCALES_IMG 0x913D 84 85 Accepted by the <target> parameter of GetIntegerv, GetInteger64v, 86 GetIntegeri_v, GetInteger64i_v and GetInternalFormativ: 87 88 DOWNSAMPLE_SCALES_IMG 0x913E 89 90 Accepted by the <pname> parameter of GetFramebufferAttachmentParameteriv: 91 92 FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F 93 94Additions to Chapter 4 of the OpenGL ES 3.0 Specification: 95 96 Modify figure 4.1, "Per-Fragment Operations.", to add an additional box 97 "Downscaling" after "Additional Multisample Fragment Operations". 98 99 Add a new section 4.1.11, "Downscaling": 100 101 If no multisampling was performed, and downscaling is enabled, fragment 102 outputs may be optionally downscaled in a similar way to how multiple 103 samples are resolved. If the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_- 104 SCALE_IMG is not {1,1}, fragment values are written to an intermediate 105 buffer. After all other fragment operations have completed, they are 106 then combined to a produce a single color value, and that value is 107 written into the corresponding color buffer selected by DrawBuffers. An 108 implementation may defer the writing of color buffers until a later 109 time, but the state of the framebuffer must behave as if the color 110 buffers were updated as each fragment is processed. The method of 111 combination is not specified. If the framebuffer contains sRGB values, 112 then it is recommended that an average of samples is computed in a 113 linearized space, as for blending (see section 4.1.7). Otherwise, a 114 simple average computed independently for each color component is 115 recommended. 116 117 Add the following to Section 4.4.2 "Attaching Images to Framebuffer Objects" 118 after the paragraph describing FramebufferTexture2D: 119 120 The command 121 122 void FramebufferTexture2DDownsampleIMG( 123 enum target, enum attachment, 124 enum textarget, uint texture, 125 int level, uint xscale, uint yscale); 126 127 allows a rendering into the image of a texture object that has a lower 128 resolution than the framebuffer. 129 130 target, textarget, texture, and level correspond to the same 131 parameters for FramebufferTexture2D and have the same restrictions. 132 133 attachment corresponds to the same parameter for FramebufferTexture2D, 134 but must be COLOR_ATTACHMENTn. 135 136 xscale and yscale are multiplied by texture's width and height, 137 respectively, to produce the effective size of the attachment when 138 rendering. For example, a texture width of 128 with an xscale of 2 would 139 produce a color attachment with the effective width of 256. xscale and 140 yscale must be one of the value pairs in DOWNSAMPLE_SCALES_IMG. If the 141 xscale and yscale value pair is not available on the implementation, 142 then the error INVALID_VALUE is generated. 143 144 The implementation allocates an implicit color buffer for the same 145 internalformat as the specified texture, and widths and heights from the 146 specified texture level, multiplied by xscale and yscale. This buffer is 147 used as the target for rendering instead of the specified texture level. 148 The buffer is associated with the attachment and gets deleted after the 149 attachment is broken. 150 151 When the texture level is used as a source or destination for any 152 operation, the attachment is flushed, or when the attachment is broken, 153 an implicit downsample of the color data from the color buffer to the 154 texture level may be performed. After such a downsample, the contents 155 of the color buffer become undefined. 156 157 The operations which may cause a resolve include: 158 * Drawing with the texture bound to an active texture unit 159 * ReadPixels or CopyTex[Sub]Image* while the texture is 160 attached to the framebuffer 161 * CopyTex[Sub]Image*, Tex[Sub]Image*, 162 CompressedTex[Sub]Image* with the specified level as 163 destination 164 * GenerateMipmap 165 * Flush or Finish while the texture is attached to the 166 framebuffer 167 * BindFramebuffer while the texture is attached to the currently 168 bound framebuffer. 169 170 Whether each of the above cause a resolve or not is implementation- 171 dependent. 172 173 Add the following to the sub-section "Attaching Texture Images to a 174 Framebuffer" after the paragraph describing FramebufferTextureLayer: 175 176 The command 177 178 void FramebufferTextureLayerDownsampleIMG( 179 enum target, enum attachment, 180 uint texture, int level, 181 int layer, uint xscale, uint yscale); 182 183 allows a rendering into a single layer of a texture object that has a 184 lower resolution than the framebuffer. It operates like a combination of 185 FramebufferTexture2DDownsampleIMG and FramebufferTextureLayer; it allows 186 the developer to set scaling values and attaches a single layer of a 187 three-dimensional or two-dimensional array texture level. 188 189 target, attachment, level, xscale and yscale correspond to the same 190 parameters for FramebufferTexture2DDownsampleIMG and have the same 191 restrictions. 192 193 texture can only be a two-dimensional array texture, but otherwise has 194 the same restrictions as it does for FramebufferTextureLayer. 195 196 layer corresponds to the same parameter for FramebufferTextureLayer and 197 has the same restrictions. 198 199 In the sub-section "Effects of Attaching a Texture Image", change the bullet 200 list to the following: 201 202 * The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is set to TEXTURE. 203 * The value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME is set to texture. 204 * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is set to level. 205 * If FramebufferTexture2D is called and texture is a cube map texture, 206 then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE is set 207 to textarget; otherwise it is set to the default (NONE). 208 * If FramebufferTextureLayer is called, then the value of FRAMEBUFFER_- 209 ATTACHMENT_TEXTURE_LAYER is set to layer; otherwise it is set to zero. 210 * If FramebufferTexture2DDownsampleIMG or 211 FramebufferTextureLayerDownsampleIMG is called, then the value of 212 FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG is set to {xscale, yscale}; 213 otherwise it is set to {1, 1}. 214 215 In section 4.4.4 "Framebuffer Completeness", add the following bullet to the 216 end of the list in subsection "Framebuffer Attachment Completeness": 217 218 219 * If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the 220 value of FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG is supported by the 221 internal format of the attachment (see GetInternalFormativ in section 222 6.1.15). 223 224 In section 4.4.4 "Framebuffer Completeness", add the following bullet to the 225 end of the list in subsection "Whole Framebuffer Completeness": 226 227 * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG for all 228 attachments is {1,1}, or if not, the value of TEXTURE_SAMPLES_EXT or 229 RENDERBUFFER_SAMPLES for all attachments is zero. 230 FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 231 232Additions to Chapter 6 of the OpenGL ES 3.0 Specification: 233 234 Add the following bullet point to the list in Section 6.1.13 "Framebuffer 235 Object Queries" describing valid pname values when FRAMEBUFFER_ATTACHMENT_- 236 OBJECT_TYPE is TEXTURE: 237 238 * If pname is FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG, then params will 239 contain two integer values - the downsample scale pair for that 240 attachment. 241 242 Change the paragraph in Section 6.1.15 "Internal Format Queries" describing 243 valid target values to: 244 245 target indicates the usage of the internalformat, and must be one of 246 RENDERBUFFER, TEXTURE_2D, TEXTURE_CUBE_MAP or TEXTURE_2D_ARRAY. 247 248 Add the following paragraphs to Section 6.1.15 "Internal Format Queries" to 249 the paragraphs describing valid pname values: 250 251 If pname is NUM_DOWNSAMPLE_SCALES_IMG, the number of downscales that 252 would be returned by querying DOWNSAMPLE_SCALES_IMG is returned in params. 253 If pname is DOWNSAMPLE_SCALES_IMG, the available downscale pairs for the 254 format are written into params. 255 Formats that don't support downsampling will still return one valid 256 downsample scale pair - {1,1}. A value of one for NUM_DOWNSAMPLE_SCALES_IMG 257 will always mean no downscaling available, as {1,1} must be supported by 258 every format. Targets that don't support downscaling (e.g. RENDERBUFFER) 259 will return no downsample scale pairs. 260 261Interactions with OpenGL ES 2.0 262 263 In section 4.4.5 of the OpenGL ES 2.0 Specification "Framebuffer 264 Completeness", subsection "Framebuffer Attachment Completeness", replace: 265 266 * All attached images have the same width and height. 267 FRAMEBUFFER_INCOMPLETE_DIMENSIONS 268 269 with: 270 271 * All attached images have the same value of width * xscale and 272 height * yscale. 273 FRAMEBUFFER_INCOMPLETE_DIMENSIONS 274 275Interactions with OpenGL ES 3.1 276 277 If OpenGL ES 3.1 is supported, replace TEXTURE_SAMPLES_EXT with TEXTURE_- 278 SAMPLES, and add TEXTURE_2D_MULTISAMPLE to the list of valid targets for 279 GetInternalFormativ. 280 281Interactions with EXT_multisampled_render_to_texture 282 283 If EXT_multisampled_render_to_texture is not supported: 284 - ignore references to TEXTURE_SAMPLES_EXT 285 - the sample counts returned by GetInternalFormativ with a target of 286 TEXTURE* will be the sample values available to be used with 287 FramebufferTexture2DMultisampleEXT 288 289Dependencies on OpenGL ES 3.0 290 291 If OpenGL ES 3.0 or higher is not supported, ignore references to 292 glFramebufferTextureLayerDownsample and glGetIntegeri_v. 293 294Interactions with EXT_color_buffer_float and EXT_color_buffer_half_float 295 296 If either of these extensions are supported, it is not guaranteed that 297 downscale of these formats is supported, but it may be - users will have to 298 check with the GetInternalFormat query. 299 300 This equally applies to any other additional render formats provided by 301 extension. 302 303Errors 304 305 The error INVALID_VALUE is generated if FramebufferTextureLayerDownsampleIMG 306 or FramebufferTexture2DDownsampleIMG are are called with an <xscale> and 307 <yscale> value pair that isn't reported by DOWNSAMPLE_SCALES_IMG. 308 309 The error INVALID_ENUM is generated if FramebufferTextureLayerDownsampleIMG 310 or FramebufferTexture2DDownsampleIMG are called with an <attachment> that is 311 not COLOR_ATTACHMENTn. 312 313New State 314 315 Add to Table 6.14 "Framebuffer (state per attachment point)" 316 317 Initial 318 Get Value Type Get Command Value Description Sec. 319 ----------------- ----------- --------------------- ------- --------------- ---- 320 FRAMEBUFFER_- 2 x Z+ GetFramebuffer- {1,1} Framebuffer 4.4.2 321 ATTACHMENT_- AttachmentParameteriv texture scale 322 TEXTURE_SCALE_IMG 323 324New Implementation Dependent State 325 326 Add to Table 6.35 "Framebuffer Dependent Values" 327 Minimum 328 Get Value Type Get Command Value Description Sec. 329 ----------------- ----------- ------------------ ------- --------------- ---- 330 NUM_DOWNSAMPLE_- 2 x Z+ GetIntegerv 2 Number of 4.4.2 331 SCALES_IMG scale value 332 pairs available 333 334 DOWNSAMPLE_- 1* x 2 x Z+ GetIntegeri_v ** Scale value 4.4.2 335 SCALES_IMG pairs available 336 337 338 ** At least {1,1} and {2,2} must be supported as a minimum to support this extension. 339 340Example 341 342 GLint xDownscale = 1; 343 GLint yDownscale = 1; 344 345 // Select a downscale amount if possible 346 if (extension_is_supported("GL_IMG_framebuffer_downsample") 347 { 348 // Query the number of available scales 349 GLint numScales; 350 glGetIntegerv(GL_NUM_DOWNSAMPLE_SCALES_IMG, &numScales); 351 352 // 2 scale modes are supported as minimum, so only need to check for 353 // better than 2x2 if more modes are exposed. 354 if (numScales > 2) 355 { 356 // Try to select most aggressive scaling. 357 GLint bestScale = 1; 358 GLint tempScale[2]; 359 GLint i; 360 for (i = 0; i < numScales; ++i) 361 { 362 glGetIntegeri_v(GL_DOWNSAMPLE_SCALES_IMG, i, tempScale); 363 364 // If the scaling is more aggressive, update our x/y scale values. 365 if (tempScale[0] * tempScale[1] > bestScale) 366 { 367 xDownscale = tempScale[0]; 368 yDownscale = tempScale[1]; 369 } 370 } 371 } 372 else 373 { 374 xDownscale = 2; 375 yDownscale = 2; 376 } 377 } 378 379 // Create depth texture. Depth and stencil buffers must be full size 380 GLuint depthTexture; 381 glGenTextures(1, &depthTexture); 382 glBindTexture(GL_TEXTURE_2D, depthTexture); 383 glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, width, height); 384 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 385 glBindTexture(GL_TEXTURE_2D, 0); 386 387 // Create a full size RGBA texture with single mipmap level 388 GLuint texture; 389 glGenTextures(1, &texture); 390 glBindTexture(GL_TEXTURE_2D, texture); 391 glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height); 392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 393 glBindTexture(GL_TEXTURE_2D, 0); 394 395 // Scale the width and height appropriately. 396 GLint scaledWidth = width / xDownscale; 397 GLint scaledHeight = height / yDownscale; 398 399 // Create a reduced size RGBA texture with single mipmap level 400 GLuint scaledTexture; 401 glGenTextures(1, &scaledTexture); 402 glBindTexture(GL_TEXTURE_2D, scaledTexture); 403 glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGBA4, scaledWidth, scaledHeight); 404 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 405 glBindTexture(GL_TEXTURE_2D, 0); 406 407 // Create framebuffer object, attach textures 408 GLuint framebuffer; 409 glGenFramebuffers(1, &framebuffer); 410 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 411 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 412 GL_TEXTURE_2D, depthTexture); 413 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 414 GL_TEXTURE_2D, texture, 0); 415 glFramebufferTexture2DDownsampleIMG(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, 416 GL_TEXTURE_2D, scaledTexture, 0, xDownscale, yDownscale); 417 418 // Handle unsupported cases 419 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 420 { 421 ... 422 } 423 424 // Draw to the texture 425 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 426 ... 427 428 // Discard the depth renderbuffer contents if possible/available 429 if (extension_supported("GL_EXT_discard_framebuffer")) 430 { 431 GLenum discard_attachments[] = { GL_DEPTH_ATTACHMENT }; 432 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discard_attachments); 433 } 434 435 /* 436 Draw to the default framebuffer using the textures with various post 437 processing effects. 438 */ 439 glBindFramebuffer(GL_FRAMEBUFFER, 0); 440 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 441 glActiveTexture(GL_TEXTURE0); 442 glBindTexture(GL_TEXTURE_2D, texture); 443 glActiveTexture(GL_TEXTURE1); 444 glBindTexture(GL_TEXTURE_2D, scaledTexture); 445 ... 446 447Issues 448 449 1) Should renderbuffers be resolvable in this way too? 450 451 RESOLVED 452 453 No, renderbuffers are considered somewhat legacy and thus will 454 not be supported by this extension. 455 456 2) Should any scale values other than {1,1} be mandated as minimum? 457 458 RESOLVED 459 460 Yes, {2,2} will also be required. Implementations may support additional 461 values though, so a query is also added for other values. 462 463 3) What formats support downscaling? 464 465 RESOLVED 466 467 Formats that are guaranteed color-renderable by the core ES 3.1 468 specification, excluding integer and signed integer formats, support all 469 available downscale modes. Other formats only support {1,1} (no 470 downscaling). 471 472 4) What should happen if an application calls GetInternalFormativ with a 473 target of TEXTURE* (not TEXTURE_2D_MULTISAMPLE)? 474 475 RESOLVED 476 477 For standard OpenGL ES, NUM_SAMPLE_COUNTS should be zero. However, if 478 EXT_multisampled_render_to_texture is supported, valid configurations 479 for FramebufferTexture2DMultisampleEXT should be returned here. 480 481Revision History 482 483 Revision 1, 2014/08/27 484 - First draft 485 486 Revision 2, 2015/03/16 487 - Mandated {2,2} as a required downsample scale. 488 - Coupled x and y scale values into pairs 489 490 Revision 3, 2015/03/19 491 - Moved framebuffer completeness information to correct (whole framebuffer 492 completeness) section, and corrected wording. 493 - Added note about minimum support in the overview. 494 495 Revision 4, 2015/03/19 496 - Added a specific revision of the OpenGL ES 3.0 specification 497 - Added an error that only COLOR_ATTACHMENTn can be used as an attachment 498 point 499 500 Revision 5, 2015/06/02 501 - Added internalformat query capability, so that formats can opt into 502 downscaling support 503 - Added section on downscaling to per-fragment operations. 504 - Added issue about what formats support downscaling. 505 - Restricted layer downscaling to 2D array textures. 506 507 Revision 6, 2015/06/03 508 - Fixed typo in incomplete framebuffer condition 509 - Added a bullet point to describe the FRAMEBUFFER_ATTACHMENT_TEXTURE_- 510 SCALE_IMG parameter to GetFramebufferAttachmentiv 511 - Clarified targets to GetInternalFormativ 512 513 Revision 7, 2015/06/17 514 - Clarified interactions with EXT_color_buffer_float and 515 EXT_color_buffer_half_float 516 517 Revision 8, 2015/06/22 518 - Added NUM_DOWNSAMPLE_SCALES_IMG as a parameter to GetInternalFormativ 519 - Added framebuffer attachment incomplete message and removed error when 520 scale pair isn't supported by textures' internalformat, as 521 internalformat is not necessarily known at attachment time. 522 523 Revision 9, 2015/08/19 524 - Assigned enum values 525 526 Revision 10, 2015/08/20 527 - Allowed DOWNSAMPLE_SCALES_IMG to be used with GetIntegerv/GetInteger64v 528 529 Revision 11, 2015/12/18 530 - Fixed example - "tempScale" is an array so doesn't need to be dereferenced. 531