1Name 2 3 EXT_multisampled_render_to_texture 4 5Name Strings 6 7 GL_EXT_multisampled_render_to_texture 8 9Contributors 10 11 Georg Kolling, Imagination Technologies (georg.kolling 'at' imgtec.com) 12 Ben Bowman, Imagination Technologies (benji.bowman 'at' imgtec.com) 13 14Contact 15 16 Jan-Harald Fredriksen (jan-harald.fredriksen 'at' arm.com) 17 18Status 19 20 Complete 21 22Version 23 24 Last Modified Date: June 28, 2016 25 Revision: 7 26 27Number 28 29 OpenGL ES Extension #106 30 31Dependencies 32 33 OpenGL ES 2.0 or OES_framebuffer_object are required. This 34 extension is written against the OpenGL ES 2.0 Specification. 35 36 This extension interacts with OpenGL ES 3.0 and later versions. 37 38Overview 39 40 This extension introduces functionality to perform multisampled 41 rendering to a color renderable texture, without requiring an 42 explicit resolve of multisample data. 43 44 Some GPU architectures - such as tile-based renderers - are 45 capable of performing multisampled rendering by storing 46 multisample data in internal high-speed memory and downsampling the 47 data when writing out to external memory after rendering has 48 finished. Since per-sample data is never written out to external 49 memory, this approach saves bandwidth and storage space. In this 50 case multisample data gets discarded, however this is acceptable 51 in most cases. 52 53 The extension provides a new command, FramebufferTexture2DMultisampleEXT, 54 which attaches a texture level to a framebuffer and enables 55 multisampled rendering to that texture level. 56 57 When the texture level is flushed or used as a source or destination 58 for any operation other than drawing to it, an implicit resolve of 59 multisampled color data may be performed. After such a resolve, the 60 multisampled color data is discarded. 61 62 In order to allow the use of multisampled depth and stencil buffers 63 when performing multisampled rendering to a texture, the extension 64 also adds the command RenderbufferStorageMultisampleEXT. 65 66IP Status 67 68 No known IP claims. 69 70New Procedures and Functions 71 72 void RenderbufferStorageMultisampleEXT( 73 enum target, sizei samples, 74 enum internalformat, 75 sizei width, sizei height); 76 77 void FramebufferTexture2DMultisampleEXT( 78 enum target, enum attachment, 79 enum textarget, uint texture, 80 int level, sizei samples); 81 82New Tokens 83 84 Accepted by the <pname> parameter of GetRenderbufferParameteriv: 85 86 RENDERBUFFER_SAMPLES_EXT 0x8CAB 87 88 Returned by CheckFramebufferStatus: 89 90 FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 91 92 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, 93 and GetFloatv: 94 95 MAX_SAMPLES_EXT 0x8D57 96 97 Accepted by the <pname> parameter of GetFramebufferAttachmentParameteriv: 98 99 FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C 100 101 102Additions to Section 4.4.3 of the OpenGL ES 2.0 Specification 103(Renderbuffer Objects) 104 105 Replace the paragraph describing the command RenderbufferStorage 106 with the following: 107 108 The command 109 void RenderbufferStorageMultisampleEXT( enum target, 110 sizei samples, enum internalformat, sizei width, 111 sizei height ); 112 establishes the data storage, format, dimensions, and number of 113 samples of a renderbuffer object's image. target must be RENDERBUFFER. 114 internalformat must be one of the color-renderable, depth-renderable, 115 or stencil-renderable formats described in table 4.5. width and height 116 are the dimensions in pixels of the renderbuffer. If either width or 117 height is greater than the value of MAX_RENDERBUFFER_SIZE, or if 118 samples is greater than the value of MAX_SAMPLES_EXT, then the error 119 INVALID_VALUE is generated. If OpenGL ES is unable to create a data 120 store of the requested size, the error OUT_OF_MEMORY is generated. 121 Upon success, RenderbufferStorageMultisampleEXT deletes any existing 122 data store for the renderbuffer image and the contents of the data 123 store after calling RenderbufferStorageMultisampleEXT are undefined. 124 RENDERBUFFER_WIDTH is set to width, RENDERBUFFER_HEIGHT is set to 125 height, and RENDERBUFFER_INTERNAL_FORMAT is set to internalformat. 126 If samples is zero, then RENDERBUFFER_SAMPLES_EXT is set to zero. 127 Otherwise samples represents a request for a desired minimum number 128 of samples. Since different implementations may support different 129 sample counts for multisampled rendering, the actual number of samples 130 allocated for the renderbuffer image is implementation-dependent. 131 However, the resulting value for RENDERBUFFER_SAMPLES_EXT is 132 guaranteed to be greater than or equal to samples and no more than the 133 next larger sample count supported by the implementation. 134 135 When the renderbuffer is used as a source or destination for any 136 operation, when the attachment is flushed, or when the attachment is 137 broken, an implicit resolve of the multisample data may be performed. 138 After such a resolve, the contents of the multisample buffer become 139 undefined. The operations that may cause an implicit resolve are the 140 same as for FramebufferTexture2DMultisampleEXT. 141 142 An OpenGL ES implementation may vary its allocation of internal 143 component resolution based on any RenderbufferStorageMultisampleEXT 144 parameter (except target), but the allocation and chosen internal format 145 must not be a function of any other state and cannot be changed once 146 they are established. 147 148 The command 149 void RenderbufferStorage( enum target, enum internalformat, 150 sizei width, sizei height ); 151 is equivalent to calling RenderbufferStorageMultisampleEXT with 152 samples equal to zero. 153 154 Add the following after the paragraph describing FramebufferTexture2D: 155 156 The command 157 void FramebufferTexture2DMultisampleEXT( enum target, 158 enum attachment, enum textarget, uint texture, 159 int level, sizei samples ); 160 enables multisampled rendering into the images of a texture object. 161 162 target, textarget, texture, and level correspond to the same 163 parameters for FramebufferTexture2D and have the same restrictions. 164 attachment must be COLOR_ATTACHMENT0. If samples is greater than the 165 value of MAX_SAMPLES_EXT, then the error INVALID_VALUE is generated. 166 An INVALID_OPERATION error is generated if samples is greater than 167 the maximum number of samples supported for target and its 168 internalformat. If samples is zero, then TEXTURE_SAMPLES_EXT is set 169 to zero, and FramebufferTexture2DMultisampleEXT behaves like 170 FramebufferTexture2D. 171 172 Otherwise samples represents a request for a desired minimum number 173 of samples. Since different implementations may support different 174 sample counts for multisampled rendering, the actual number of samples 175 allocated for the image is implementation-dependent. However, the 176 resulting value for TEXTURE_SAMPLES_EXT is guaranteed to be greater 177 than or equal to samples and no more than the next larger sample count 178 supported by the implementation. 179 180 The implementation allocates an implicit multisample buffer with 181 TEXTURE_SAMPLES_EXT samples and the same internalformat, width, and 182 height as the specified texture level. This buffer is used as the 183 target for rendering instead of the specified texture level. The 184 buffer is associated with the attachment and gets deleted after the 185 attachment is broken. 186 187 While the implicit multisample buffer is attached, color sample values 188 are automatically resolved to a single color in the texture level each 189 time a pixel is updated. This has the effect of making the antialiasing 190 appear to be automatic at the application level. 191 192 When the texture level is used as a source or destination for any 193 operation, the attachment is flushed, or when the attachment is broken, 194 the GL implementation may discard the contents of the implicit multisample 195 buffer. If the contents are discarded, the subsequent operations on the 196 multisample buffer will behave as if all samples within a pixel have the 197 value most recently written to the color buffer for that pixel. 198 199 The operations which may cause the contents of the implicit multisample 200 buffer to be discarded include: 201 - Drawing with the texture bound to an active texture unit 202 - ReadPixels or CopyTex[Sub]Image* while the texture is 203 attached to the framebuffer 204 - CopyTex[Sub]Image*, Tex[Sub]Image*, 205 CompressedTex[Sub]Image* with the specified level as 206 destination 207 - GenerateMipmap 208 - Flush or Finish while the texture is attached to the 209 framebuffer 210 - BindFramebuffer while the texture is attached to the currently 211 bound framebuffer. 212 213 214Additions to section 4.4.5 of the OpenGL ES 2.0 Specification 215(Framebuffer Completeness) 216 217 Add the following bullet point to the list of conditions for 218 Framebuffer Attachment Completeness: 219 220 * The number of texture samples (as set by FramebufferTexture2DMultisampleEXT) 221 must be less than or equal to the maximum number of samples supported for 222 the internal format of _image_. 223 224 Add the following bullet point after 225 * All attached images have the same width and height. 226 FRAMEBUFFER_INCOMPLETE_DIMENSIONS 227 on page 116: 228 229 * The value of RENDERBUFFER_SAMPLES_EXT is the same for all 230 attached renderbuffers; the value of TEXTURE_SAMPLES_EXT 231 is the same for all texture attachments; and, if the attached 232 images are a mix of renderbuffers and textures, the value of 233 RENDERBUFFER_SAMPLES_EXT matches the value of TEXTURE_- 234 SAMPLES_EXT. 235 FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 236 237Dependencies on GL and ES profiles, versions, and other extensions 238 239 Interactions with OpenGL ES 3.0 and later versions: 240 241 If OpenGL ES 3.0 or later is not supported, ignore all references 242 to DRAW_FRAMEBUFFER and READ_FRAMEBUFFER. 243 244 The OpenGL ES 3.1 specification states that: 245 "An INVALID_OPERATION error is generated by CopyTexSubImage3D, 246 CopyTexImage2D, or CopyTexSubImage2D if 247 ... 248 * the value of READ_FRAMEBUFFER_BINDING is non-zero, and 249 - the read buffer selects an attachment that has no image attached, 250 or 251 - the value of SAMPLE_BUFFERS for the read framebuffer is one." 252 253 Similarly, for ReadPixels: 254 "An INVALID_OPERATION error is generated if the value of READ_- 255 FRAMEBUFFER_BINDING (see section 9) is non-zero, the read framebuffer 256 is framebuffer complete, and the value of SAMPLE_BUFFERS for the read 257 framebuffer is one." 258 259 These errors do not apply to textures and renderbuffers that have 260 associated multisample data specified by the mechanisms described in 261 this extension, i.e., the above operations are allowed even when 262 SAMPLE_BUFFERS is non-zero for renderbuffers created via Renderbuffer- 263 StorageMultisampleEXT or textures attached via FramebufferTexture2D- 264 MultisampleEXT. 265 266 Also, FBOs cannot combine attachments that have associated multisample 267 data specified by the mechanisms described in this extension with 268 attachments allocated using the core OpenGL ES 3.1 mechanisms, such as 269 TexStorage2DMultisample. Add to section 9.4.2 "Whole Framebuffer 270 Completeness": 271 "* If the value of RENDERBUFFER_SAMPLES is non-zero, all or none of the 272 attached renderbuffers have been allocated using RenderbufferStorage- 273 MultisampleEXT; if the value of TEXTURES_SAMPLES is non-zero, all or 274 none of the attached textures have been attached using Framebuffer- 275 Texture2DMultisampleEXT. 276 { GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT }" 277 278 Add to the description of FramebufferTexture2DMultisampleEXT (first 279 paragraph): 280 "The maximum number of samples supported can be determined by calling 281 GetInternalformativ with a pname of SAMPLES." 282 283Errors 284 285 The error OUT_OF_MEMORY is generated when 286 RenderbufferStorageMultisampleEXT cannot create storage of the 287 specified size. 288 289 If RenderbufferStorageMultisampleEXT is called with a value of 290 <samples> that is greater than MAX_SAMPLES_EXT, then the error 291 INVALID_VALUE is generated. 292 293 The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT 294 is called with a <target> that is not FRAMEBUFFER, DRAW_FRAMEBUFFER, or 295 READ_FRAMEBUFFER. 296 297 The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT 298 is called with an <attachment> that is not COLOR_ATTACHMENT0. 299 300 The error INVALID_ENUM is generated if FramebufferTexture2DMultisampleEXT 301 is called with a <textarget> that is not TEXTURE_2D, 302 TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, 303 TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X, 304 TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z. 305 306 The error INVALID_OPERATION is generated if FramebufferTexture2DMultisampleEXT 307 is called with <samples> greater than the maximum number of samples supported 308 for <target> and its internalformat. 309 310New State 311 312 Changes to table 6.22, p. 154 (Renderbuffer State) 313 314 Initial 315 Get Value Type Get Command Value Description Sec. 316 --------- ---- ---------------- ------- ------------ ----- 317 RENDERBUFFER_SAMPLES_EXT Z+ GetRenderbuffer- 0 Renderbuffer 4.4.3 318 Parameteriv samples 319 320 Changes to table 6.23, p. 155 (Framebuffer State) 321 322 Initial 323 Get Value Type Get Command Value Description Sec. 324 --------- ------ --------------------- ------- --------------- ---- 325 TEXTURE_SAMPLES_EXT n * Z+ GetFramebuffer- 0 Framebuffer 4.4 326 AttachmentParameteriv texture samples 327 328New Implementation Dependent State 329 330 Changes to table 6.17, p. 149 (Implementation Dependent Values) 331 332 Minimum 333 Get Value Type Get Command Value Description Sec. 334 --------- ---- ----------- ------- ----------- ---- 335 MAX_SAMPLES_EXT Z+ GetIntegerv 2 Max. # of 4.4 336 samples. 337 338Sample Code 339 340 GLsizei width = ...; 341 GLsizei height = ...; 342 GLint samples; 343 glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples); 344 345 /* Create multisampled depth renderbuffer */ 346 GLuint depthbuffer; 347 glGenRenderbuffers(1, &depthbuffer); 348 glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer); 349 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, 350 GL_DEPTH_COMPONENT16, width, height); 351 glBindRenderbuffer(GL_RENDERBUFFER, 0); 352 353 /* Create RGBA texture with single mipmap level */ 354 GLuint texture; 355 glGenTextures(1, &texture); 356 glBindTexture(GL_TEXTURE_2D, texture); 357 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 358 GL_UNSIGNED_SHORT_4_4_4_4, NULL); 359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 360 glBindTexture(GL_TEXTURE_2D, 0); 361 362 /* Create framebuffer object, attach texture and depth renderbuffer */ 363 GLuint framebuffer; 364 glGenFramebuffers(1, &framebuffer); 365 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 366 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 367 GL_RENDERBUFFER, depthbuffer); 368 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, 369 GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0, samples); 370 371 /* handle unsupported cases */ 372 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != 373 GL_FRAMEBUFFER_COMPLETE) 374 { 375 ... 376 } 377 378 /* draw to the texture */ 379 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 380 ... 381 382 /* Discard the depth renderbuffer contents if possible */ 383 if (extension_supported("GL_EXT_discard_framebuffer")) 384 { 385 GLenum discard_attachments[] = { GL_DEPTH_ATTACHMENT }; 386 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, 387 discard_attachments); 388 } 389 390 /* Draw to the default framebuffer using the antialiased texture */ 391 /* Color data is implicitly resolved before the texture gets used */ 392 glBindFramebuffer(GL_FRAMEBUFFER, 0); 393 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | 394 GL_STENCIL_BUFFER_BIT); 395 glBindTexture(GL_TEXTURE_2D, texture); 396 ... 397 398Conformance Tests 399 400 No conformance test has been defined yet 401 402Issues 403 404 1. Which operations can cause a resolve? 405 The IMG_multisampled_render_to_texture includes this list: 406 - Drawing with the texture bound to an active texture unit 407 - ReadPixels or CopyTex[Sub]Image* while the texture is 408 attached to the framebuffer 409 - CopyTex[Sub]Image*, Tex[Sub]Image*, 410 CompressedTex[Sub]Image* with the specified level as 411 destination 412 - GenerateMipmap 413 An implementation may also want to resolve the multisample buffer on 414 operations such as: 415 - Flush and Finish when a multisampled texture or render- 416 buffer is attached to the current framebuffer. 417 - BindFramebuffer when the currently bound framebuffer has a 418 multisampled texture or renderbuffer attachment. 419 420 RESOLVED: Allow, but don't require, all of the above to cause a resolve. 421 422 2. Should there be a way for applications to query if the multisample 423 buffer has been resolved - and therefore is undefined? 424 425 This may be useful if the operations that cause the multisample 426 buffer to be resolved is allowed to vary between implementations. 427 428 RESOLVED: No, for two reasons: 1) This extension aims to be backwards 429 compatible with the IMG_multisampled_render_to_texture extension, which 430 did not include such a query, and 2) Given the resolution of issue 3 this 431 is not very useful as the application cannot control whether multisample 432 information is preserved or not. 433 434 3. Should there be a way for applications to preserve the multisample 435 buffer after a resolve? 436 437 This would be similar in spirit to the EGL_BUFFER_PRESERVED options in 438 EGL 1.4. Applications could - at a performance and memory cost - choose 439 to make the multisample buffer _not_ undefined after a resolve. 440 441 RESOLVED: No. The purpose of this extension is to support multisampled 442 rendering in a lightway manner. Preserving the multisample buffer goes 443 against this intent. 444 445 4. Should TEXTURE_SAMPLES_EXT rather be called FRAMEBUFFER_ATTACHMENT_- 446 TEXTURE_SAMPLES_EXT? 447 448 TEXTURE_SAMPLES is used in desktop GL to refer to the number of samples in 449 a multisampled texture. This extension does not introduce multisampled 450 textures, but rather allows multisampled rendering to non-multisampled 451 textures. For the purposes of this extension, the texture sample count 452 should be considered framebuffer attachment state rather than texture 453 state, thus FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT is a more 454 appropriate name. 455 456 RESOLVED: Use FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT. 457 458 5. Is CopyTex[Sub]Image2D allowed if the texture has implicit multisamples? 459 And is ReadPixels allowed if the texture or renderbuffer has implicit 460 multisamples? 461 462 RESOLVED: Yes. 463 464 This extension is written against OpenGL ES 2.0, which did not have multi- 465 sampled textures or renderbuffers. With this extension, an application can 466 use FramebufferTexture2DMultisampleEXT to associate multisample data with 467 an existing texture, or use RenderbufferStorageMultisampleEXT to allocate 468 a renderbuffer with associated multisample data. This does not add any 469 restrictions on the usage of such texture and renderbuffers beyond what 470 ES 2.0 defines, but any operations (such as CopyTexImage2D and ReadPixels) 471 may cause the multisample data to be resolved and lost. That is, the intent 472 of this extension is that implementations do not have to allocate multi- 473 sample data in system memory, but can store these data in internal high- 474 speed memory only, and implicitly downsample whenever those data need to 475 by visible is system memory. 476 477 6. What are the interactions with OpenGL ES 3.0 and later? 478 479 RESOLVED. 480 481 If this extension is supported in OpenGL ES 3.0 or later then 482 DRAW_FRAMEBUFFER and READ_FRAMEBUFFER are valid values for the <target> 483 parameter to FramebufferTexture2DMultisampleEXT. Since this parameter is 484 defined to correspond to - and have the same restrictions as - the <target> 485 parameter to FramebufferTexture2D, this also implies that FRAMEBUFFER is 486 equivalent to DRAW_FRAMEBUFFER for this command. 487 488 Note that this behavior was first described in revision 6 of this extension, 489 and was undefined in earlier revisions of this spec. Drivers written against 490 these earlier versions may generate errors if DRAW_FRAMEBUFFER and READ_- 491 FRAMEBUFFER are used for the <target> parameter to 492 FramebufferTexture2DMultisampleEXT. 493 494 7. What is the language about automatic resolves about? 495 496 RESOLVED. 497 498 The GL specification is written as if the multisample buffer is a separate 499 buffer from the color buffer. This is not quite how modern GPUs work, but 500 was true for some historic systems. This extension builds on the existing 501 specification wording and uses the existing terminology. 502 503 In the Multisampling section, the GL specification says that: 504 505 "The color sample values are resolved to a single, displayable color. For 506 window system-provided framebuffers, this occurs each time a pixel is 507 updated, so the antialiasing appears to be automatic at the application 508 level." 509 510 In practice, most GPUs will only resolve the color sample values once 511 (e.g. at the end of a frame), but from the application's point of view that 512 does not make any observable difference. 513 514 This extension inherits this behavor. The application does not (and cannot) 515 do anything to resolve the multisamples - this is always done automatically. 516 517 Further, this extension does not change any of the semantics around how 518 resources are synchronized. E.g. an attachment will always see the most 519 recent change made to the attached texture, whether that was done by 520 rendering into an attachment or by a texture update operation. 521 522 This implies that the multisample buffer and the color buffer are always 523 "in sync". The only behavior that is implementation-defined in this 524 extension is when the implicit multisample buffer is discarded. After the 525 operations that may (or may not) cause such a discard, an application can 526 observe either 1 or n distinct values in the multisample buffer depending 527 on whether the discard happened or not. As described in Issue 2, there's 528 no way for the application to query whether the discard happened. 529 530 531Revision History 532 533 Revision 8, 2018/04/11 534 - Clarified wording around implicit resolves, and added Issue 7. 535 536 Revision 7, 2016/06/28 537 - Clarified that it is an error to call FramebufferTexture2DMultisampleEXT 538 with a sample count higher than what is supported for the given internalformat. 539 - Added Framebuffer Attachment Completeness rule. 540 541 Revision 6, 2016/04/06 542 - Updating interactions with OpenGL ES 3.0 and added the related 543 Issue 6. 544 545 Revision 5, 2015/01/05 546 - Clarified that multisampled data is also implictly resolved for render- 547 buffers. 548 - Clarified interactions with multisampled textures in OpenGL ES 3.x. 549 - Added interaction with OpenGL ES 3.1. 550 - Added Issue 5. 551 552 Revision 4, 2012/07/04 553 - Fixing bug where enum names clashed with enums in the GL extension 554 EXT_framebuffer_multisample, but with different values defined. 555 This causes obvious problems. As a consequence, values have been 556 updated for the following enums: 557 * RENDERBUFFER_SAMPLES_EXT 558 * FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 559 * MAX_SAMPLES_EXT 560 The values now match the values in EXT_framebuffer_multisample. 561 562 Revision 3, 2011/11/21 563 - Fixing a bug in Sample Code where GL_DEPTH_EXT was used instead of 564 GL_DEPTH_ATTACHMENT. 565 566 Revision 2, 2011/10/30 567 - Renaming to EXT extension. Resolving issues 1-4. 568 569 Revision 1, 2011/10/02 570 - First draft of XXX extension (based on IMG extension with the same name) 571