Name ANGLE_multiview Name Strings GL_ANGLE_multiview Contributors Martin Radev, NVIDIA Corporation Olli Etuaho, NVIDIA Corporation Corentin Wallez, Google Geoff Lang, Google Jamie Madill, Google Contact Olli Etuaho (oetuaho 'at' nvidia.com) Status Incomplete Version Last Modified Date: July 14, 2017 Author Revision: 1 Number OpenGL ES Extension XX Dependencies OpenGL ES 3.0 is required. Overview Multi-view rendering, achieved through the functionality exposed by ANGLE, expects the user to issue for each view almost the same drawing commands and state changes sequentially. This rendering method scales with the number of views and can be detrimental for performance in scenes with many draw calls. This extension addresses the issue by adding means for multi-view side-by-side rendering onto a single 2D texture and layered rendering onto the many layers of a 2D texture array. The new vertex and fragment shader built-in - ViewID_OVR - is added which signifies the view for which the current vertex or fragment is being processed, so that per-view transformations can be applied. IP Status No known IP claims. New Tokens Accepted by the parameter of GetFramebufferAttachmentParameteriv: FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE 0x9630 FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE 0x969B FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE 0x9632 FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE 0x969C Returned in by GetFramebufferAttachmentParameteriv: FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE 0x969D FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE 0x969E Accepted by the parameter of GetIntegerv: MAX_VIEWS_ANGLE 0x9631 Returned by CheckFramebufferStatus: FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE 0x9633 New Procedures and Functions void FramebufferTextureMultiviewLayeredANGLE(enum target, enum attachment, uint texture, int level, int baseViewIndex, sizei numViews); void FramebufferTextureMultiviewSideBySideANGLE(enum target, enum attachment, uint texture, int level, sizei numViews, const int *viewportOffsets); Additions to Chapter 2 of the OpenGL ES 3.0 Specification (OpenGL ES Operation) Modify section 2.9.3 Drawing commands, p. 28 Append to the end of the section: " If any drawing command is called the number of views specified in the program must match the number of views in the draw framebuffer. If there is a mismatch, an INVALID_OPERATION error is generated. If the active draw framebuffer has a side-by-side multi-view layout and the scissor test is not enabled, the result of any draw command is undefined, but is not followed by program termination. " Modify section 2.15.2 Transform Feedback Primitive Capture, p. 91 In the list just after "The error INVALID_OPERATION is generated:" do the following: - Add another bullet point: " * by any Draw* command if the number of views in the draw framebuffer is greater than 1 and there is an active transform feedback object. " Additions to Chapter 3 of the OpenGL ES 3.0 Specification (Rasterization) Modify section 3.8.5 (Alternate Texture Image Specification Commands), p. 145 Add at the end of the section: "Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer is not NONE." Additions to Chapter 4 of the OpenGL ES 3.0 Specification (Per-Fragment Operations and the Framebuffer) Modify section 4.1.6 (Occlusion queries), p. 177 Replace the first sentence with: "Occlusion queries use query objects to track whether any fragments or samples pass the depth test for any of the views." Append to the sentence "While that occlusion query is active, the samples-boolean state is set to TRUE if any fragment or sample passes the depth test" the text " for any of the views." Modify section 4.2.3 (Clearing the Buffers), p. 190 Add a new subsection at the end: "4.2.3.2 Clearing Multi-view Buffers Clearing commands are applied to each view in the current multi-view framebuffer object and have the same constraints as described in section 4.2.3 Clearing the Buffers. If the active draw framebuffer has a side-by-side multi-view layout and the scissor test is not enabled, the clearing command clears the whole content of the specified buffers. " Modify section 4.3.2 (Reading pixels), p. 193 Add to the end of the section: " ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer is not NONE." Modify section 4.3.3 (Copying pixels), p. 198 After the paragraph "Calling BlitFramebuffer will result in an INVALID_OPERATION error if filter is LINEAR and read buffer contains integer data." add a new paragraph: "Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current draw framebuffer or read framebuffer is not NONE." Modify section 4.4.2 (Attaching Images to Framebuffer Objects), p. 202 Add the following bullet point: "* Layers of a two-dimensional array texture which can be used for multi-view rendering." Modify section 4.4.2.4 (Attaching Texture Images to a Framebuffer), p. 207 Add just before the sentence "Effects of Attaching a Texture Image": " The command SelectView( id ); does not exist in the GL, but it is used to describe the multi-view functionality in the rest of this section. The effect of this function is to select the view specified by and set the value to the vertex and fragment shader built-in gl_ViewID_OVR. The command void FramebufferTextureMultiviewLayeredANGLE(enum target, enum attachment, uint texture, int level, int baseViewIndex, sizei numViews); can be used to attach a 2D texture array object as one of the logical buffers of a framebuffer object which is to be used for layered multi-view rendering. basicViewIndex specifies the View-id offset. numViews specifies the number of views associated with the attachment. Any command, while a layered multi-view framebuffer is bound, has the same effect as: for( int id = 0; i < numViews; id++ ) { for ( framebufferAttachment : framebuffer.getAllAttachments() ) { attachment = framebufferAttachment.attachment texture = framebufferAttachment.texture level = framebufferAttachment.level baseViewIndex = framebufferAttachment.baseViewIndex FramebufferTextureLayer( target, attachment, texture, level, baseViewIndex + id ); } SelectView( id ); } Errors: An INVALID_ENUM error is generated if target is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. An INVALID_OPERATION error is generated if attachment is COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. An INVALID_ENUM error is generated if attachment is not one of the attachments in table 4.6, and attachment is not COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. An INVALID_OPERATION error is generated if zero is bound to target. An INVALID_VALUE error is generated if texture is not zero, and level is less than zero or greater than log2 of the value of MAX_TEXTURE_SIZE. An INVALID_OPERATION error is generated if texture is not zero, and does not name an existing texture object of type TEXTURE_2D_ARRAY. An INVALID_OPERATION error is generated if texture is not zero, and names a texture with a compressed texture format. An INVALID_VALUE error is generated if texture is not zero, and baseViewIndex+numViews is greater than GL_MAX_ARRAY_TEXTURE_LAYERS. An INVALID_VALUE error is generated if texture is not zero, and numViews is less than 1 or greater than MAX_VIEWS_ANGLE. An INVALID_VALUE error is generated if texture is not zero, and baseViewIndex is less than 0. The command void FramebufferTextureMultiviewSideBySideANGLE(enum target, enum attachment, uint texture, int level, sizei numViews, const int *viewportOffsets); can be used to attach a 2D texture object as one of the logical buffers of a framebuffer object which is to be used for side-by-side multi-view rendering. numViews specifies the number of views associated with the attachment. viewportOffsets specifies the address of an array of integers containing the x and y viewport offset of each view. Any command, while a side-by-side multi-view framebuffer is bound, has the same effect as: // Retrieve viewport and scissor state. Rectangle viewport GetIntegerv(VIEWPORT, viewport) Rectangle scissor GetIntegerv(SCISSOR_BOX, scissor) for ( int id = 0; id < numViews; id++ ) { // Setup view state. for ( framebufferAttachment : framebuffer.getAllAttachments() ) { attachment = framebufferAttachment.attachment texture = framebufferAttachment.texture level = framebufferAttachment.level FramebufferTexture2D( target, attachment, TEXTURE_2D, texture, level ) } Viewport(viewport.x + viewportOffsets[id].x, viewport.y + viewportOffsets[id].y, viewport.width, viewport.height) Scissor(scissor.x + viewportOffsets[id].x, scissor.y + viewportOffsets[id].y, scissor.width, scissor.height) SelectView(id) // Draw. } // Restore viewport and scissor state. Viewport(viewport.x, viewport.y, viewport.width, viewport.height) Scissor(scissor.x, scissor.y, scissor.width, scissor.height) Errors: An INVALID_ENUM error is generated if target is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER. An INVALID_OPERATION error is generated if attachment is COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. An INVALID_ENUM error is generated if attachment is not one of the attachments in table 4.6, and attachment is not COLOR_ATTACHMENTm where m is greater than or equal to the value of MAX_COLOR_ATTACHMENTS. An INVALID_OPERATION error is generated if zero is bound to target. An INVALID_VALUE error is generated if texture is not zero and level is less than zero or greater than log2 of the value of MAX_TEXTURE_SIZE. An INVALID_OPERATION error is generated if texture is not zero, and does not name an existing texture object of type TEXTURE_2D. An INVALID_OPERATION error is generated if texture is not zero, and names a texture with a compressed texture format. An INVALID_VALUE error is generated if texture is not zero, and numViews is less than 1 or greater than MAX_VIEWS_ANGLE. An INVALID_VALUE error is generated if texture is not zero, and any of the first numViews * 2 values in viewportOffsets is negative. Having overlapping scissor rectangles after viewport offsets are applied causes undefined behavior. " Add the following bullet points in the list after "Effects of Attaching a Texture Image": " * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE is set to . * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE is set to: ** FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE if the texture is attached via a call to FramebufferTextureMultiviewSideBySideANGLE. ** FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE if the texture is attached via a call to FramebufferTextureMultiviewLayeredANGLE. ** NONE otherwise. * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE is set to if FramebufferTextureMultiviewLayeredANGLE is called. Otherwise, the default value remains. * The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE is set to . " Modify section 4.4.4.1 (Framebuffer Attachment Completeness), p. 213 Add a bullet point to the end of the list: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a two-dimensional array texture, then the sum of FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE and FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE must be less than the number of layers in the texture." Modify section 4.4.4.2 (Whole Framebuffer Completeness), p. 214 Add a bullet point after "{ FRAMEBUFFER_INCOMPLETE_MULTISAMPLE }": " * All populated framebuffer attachments have the same number of views, same multi-view layout and same viewport offsets. { FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE } " Additions to Chapter 5 of the OpenGL ES 3.0 Specification (Special Functions) None Additions to Chapter 6 of the OpenGL ES 3.0 Specification (State and State Requests) Modify section 6.1.13 (Framebuffer Object Queries), p. 242 Add a bullet point to the first list: " * If is FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE, then will contain the number of views for the specified attachment. * If is FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE, then will contain the viewport offsets for the specified attachment. It is undefined behavior to provide an array with size less than 2 x . * If is FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE, then will contain FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE or NONE. * If is FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE, then will contain the base view index offset for the specified attachment." Changes to table 6.14, p. 259 (Framebuffer (state per attachment point)) Get Value Type Get Command Value Description Sec. --------- ----- ----------- ------- ----------- ---- FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE Z+ GetFramebuffer- Attachment- 1 Number of views 4.4.2.4 Parameteriv FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE n x Z^{2} GetFramebuffer- 0,0 Viewport offset 4.4.2.4 Attachment- of each view Parameteriv FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE Z+ GetFramebuffer- NONE Layout type - 4.4.2.4 Attachment- non-multiview, Parameteriv layered or side-by-side FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE Z GetFramebuffer- 0 Base view offset 4.4.2.4 Attachment- Parameteriv Changes to table 6.28, p. 273 (Implementation Dependent Values): Add the following entry after MAX_VIEWPORT_DIMS: Get Value Type Get Command Value Description Sec. --------- ----- ----------- ------- ----------- ---- MAX_VIEWS_ANGLE Z+ GetIntegerv 4 Maximum number of 4.4 views Additions to the OpenGL ES 3.0 Shading Language Specification Including the following line in a shader can be used to control the language features described in this extension: #extension GL_OVR_multiview : where is as specified in section 3.5. New preprocessor #defines are added to the OpenGL Shading Language: #define GL_OVR_multiview 1 Modify section 4.3.8.1 (Input Layout Qualifiers) Replace the first sentence by: "Input variable declarations in the vertex shader can have input layout qualifiers." Add the following text just before the sentence "Fragment shaders cannot ...": "The number of views to which to the program must render to is specified through the num_views layout qualifier: layout-qualifier-id num_views = integer-constant For example, the following declaration in a vertex shader layout (num_views=4) in; is used to specify that the program renders to 4 views. If num_views is less than 1 or greater than the maximum number of supported views, a compile-time error is generated. If the layout qualifier is declared multiple times and not all declarations specify the same number of views, a compile-time error is generated." Modify section 7.1 (Vertex Shader Special Variables) Add to the list of built-ins just after the entry for gl_InstanceID: " in highp uint gl_ViewID_OVR;" Add a description for gl_ViewID_OVR just after the paragraph for gl_InstanceID: "The variable gl_ViewID_OVR is a vertex shader input variable that holds the view id which designates the view which the current vertex is being processed for." Modify section 7.2 (Fragment Shader Special Variables) Add to the list of built-ins just after the entry for gl_InstanceID: " in highp uint gl_ViewID_OVR;" Add a description for gl_ViewID_OVR just after the paragraph for gl_PointCoord: "The variable gl_ViewID_OVR is a fragment shader input variable that holds the view id which designates the view which the current fragment is being processed for." Additions to Chapter 10 of the OpenGL ES 3.1 Specification (Vertex Specification and Drawing Commands) Modify section 10.5 (Drawing Commands Using Vertex Arrays), p. 254 Append to the list of errors for the command DrawArraysIndirect: "* An INVALID_OPERATION if the number of views in the draw framebuffer is greater than 1." Append to the list of errors for the command DrawElementsIndirect: "* An INVALID_OPERATION if the number of views in the draw framebuffer is greater than 1." Additions to the AGL/EGL/GLX/WGL Specifications None Interactions with EXT_disjoint_timer_query An INVALID_OPERATION error is generated by any Draw* command, if there is an active query object for target TIME_ELAPSED_EXT and the number of views in the draw framebuffer is greater than 1. Errors None Issues