Search code examples
indexingopengl-eswebglindexoutofboundsexception

Out-of-bounds index in indices OpenGL


What happens if I use an out-of-bounds index in my indices buffer, then a call to glDrawElements?!

It seems in OpenGL ES, it will use the default constant value, for example if three colors with four positions are provided, when I use index 3, it will use solid black for the color.

But in WebGL, it will throw invalid operation. However, these results are just in my device and I couldn't find any thing related to this in official documents. What is the documented behavior of this in all OpenGL APIs (core, ES, and WebGL)?


Solution

  • The behaviour for out-of-bounds buffer accesses are clearly worded in all specifications:

    WebGL

    For WebGL, the relevant section is "6.6 Enabled Vertex Attributes and Range Checking":

    It is possible for draw commands to request data outside the bounds of a WebGLBuffer by calling a drawing command that requires fetching data for an active vertex attribute, when it is enabled as an array, either directly (drawArrays), or indirectly from an indexed draw (drawElements). If this occurs, then one of the following behaviors will result:

    1. The WebGL implementation may generate an INVALID_OPERATION error and draw no geometry.
    2. Out-of-range vertex fetches may return any of the following values:
      • Values from anywhere within the buffer object.
      • Zero values, or (0,0,0,x) vectors for vector reads where x is a valid value represented in the type of the vector components and may be any of: 0, 1, or the maximum representable positive integer value, for signed or unsigned integer components 0.0 or 1.0, for floating-point components

    So, a compliant WebGL implementation may do either of the above. The implementation used by you seems to throw an error (which is permitted). Other implementations may behave differently and return some constant value for a fetched vertex attribute.

    OpenGL Desktop

    For OpenGL Desktop, the relevant section is "6.4 Effects of Accessing Outside Buffer Bounds":

    Most, but not all GL commands operating on buffer objects will detect attempts to read from or write to a location in a bound buffer object at an offset less than zero, or greater than or equal to the buffer’s size. When such an attempt is detected, a GL error is generated. Any command which does not detect these attempts, and performs such an invalid read or write, has undefined results, and may result in GL interruption or termination.

    So, here, an implementation is quite free to do whatever on an out-of-bounds buffer access, such as with an out-of-bounds index in an element buffer when doing an indexed draw call.

    There is also the "robust buffer access" feature, which previously was exposed as the extensions KHR_robust_buffer_access_behaviour/ARB_robust_buffer_access_behavior, but becoming core in OpenGL 4.3, which clearly defines the behaviour of indexing out of the bounds of a vertex buffer:

    Robust buffer access can be enabled by creating a context with robust access enabled through the window system binding APIs. When enabled, indices within the elements array that reference vertex data that lies outside the enabled attributes vertex buffer objects, result in reading zero.

    See also section "10.3.7 Robust Buffer Access" in the OpenGL 4.6 core specification.

    OpenGL ES

    Before OpenGL ES 3.2 accessing out-of-bounds vertices from indexed draw calls seem to be completely undefined behaviour, which also may result in program termination.

    Starting with OpenGL ES 3.2, there is the same "Robust Buffer Access" capability that can be enabled as with OpenGL since 4.3 or with the ARB_robust_buffer_access_behaviour. See section "10.3.5 Robust Buffer Access" in the OpenGL ES 3.2 specification:

    Robust buffer access is enabled by creating a context with robust access enabled through the window system binding APIs. When enabled, indices within the element array (see section 10.3.8) that reference vertex data that lies outside the enabled attribute’s vertex buffer object result in undefined values for the corresponding attributes, but cannot result in application failure.

    Before OpenGL ES 3.2 there is still the extension KHR_robust_buffer_access_behaviour that can be used if available.