Name

    APPLE_vertex_array_range

Name Strings

    GL_APPLE_vertex_array_range

Contact

    Geoff Stahl, Apple Computer (gstahl 'at' apple.com)

Status

    Complete

Version

    $Date: 2005/06/02 18:11:10 $ $Revision: 1.1 $

Number

    274

Dependencies

    APPLE_fence can affect this extension.

Overview

    This extension is designed to allow very high vertex processing rates which
    are facilitated both by relieving the CPU of as much processing burden as
    possible and by allowing graphics hardware to directly access vertex data.
    Because this extension is implemented as an addition to the vertex array
    specification provided by OpenGL 1.1, applications can continue to use
    existing vertex submission logic while taking advantage of vertex array
    ranges to more efficiently process those arrays.

    The vertex array coherency model provided by OpenGL 1.1 requires that
    vertex data specified in vertex arrays be transferred from system memory
    each time Begin, DrawArrays, or DrawElements is called.  Further, OpenGL
    1.1 requires that the transfer of data be completed by the time End,
    DrawArrays, or DrawElements returns.  Both of these requirements are
    relaxed by the vertex array range extension.  Vertex data may be cached
    by the GL so there is no guarantee that changes to the vertex data will
    be reflected in following drawing commands unless it is flushed with
    FlushVertexArrayRangeAPPLE.  The reading of vertex data may be deferred 
    by the GL so there is no guarantee that the GL will be finished reading
    the data until completion is forced by the use of Finish or the APPLE_fence
    extension.

    EnableClientState must be used with the VERTEX_ARRAY_RANGE_APPLE param to
    enable vertex array range.  Once this is done use of vertex array range
    requires the definition of a specific memory range for vertex data through
    VertexArrayRangeAPPLE.  It is recommended this data be page aligned (4096
    byte boundaries) and a multiple of page size in length for maximum
    efficiency in data handling and internal flushing, but this is not a
    requirement and any location and length of data can be defined as a vertex
    array.  This extension provides no memory allocators as any convenient
    memory allocator can be used.

    Once a data set is established, using VertexArrayRangeAPPLE, it can be can
    be drawn using standard OpenGL vertex array commands, as one would do
    without this extension.  Note, if any the data for any enabled array for a
    given array element index falls outside of the vertex array range, an
    undefined vertex is generated.  One should also understand removing or
    replacing all calls to vertex array range functions with no-ops or disabling
    the vertex array range by disabling the VERTEX_ARRAY_RANGE_APPLE client
    state should not change the results of an application's OpenGL drawing.

    For static data no addition coherency nor synchronization must be done and
    the client is free to draw with the specified draw as it sees fit.

    If data is dynamic, thus to be modified, FlushVertexArrayRangeAPPLE should
    be used.  The command is issued when data has been modified since the last
    call to VertexArrayRangeAPPLE or FlushVertexArrayRangeAPPLE and prior to
    drawing with such data. FlushVertexArrayRangeAPPLE only provides memory
    coherency prior to drawing (such as ensuring CPU caches are flushed or VRAM
    cached copies are updated) and does not provide any synchronization with
    previously issued drawing commands. The range flushed can be the specific
    range modified and does not have to be the entire vertex array range.
    Additionally, data maybe read immediately after a flush without need for
    further synchronization, thus overlapping areas of data maybe read, modified
    and written between two successive flushings and the data will be
    consistent.

    To synchronize data modification after drawing two methods can be used. A
    Finish command can be issued which will not return until all previously
    issued commands are complete, forcing completely synchronous operation.
    While this guarantees all drawing is complete it may not be the optimal
    solution for clients which just need to ensure drawing with the vertex array
    range or a specific range with the array is compete.  The APPLE_fence
    extension can be used when dynamic data modifications need to be
    synchronized with drawing commands. Specifically, if data is to be modified,
    a fence can be set immediately after drawing with the data.  Once it comes
    time to modify the data, the application must test (or finish) this fence to
    ensure the drawing command has completed. Failure to do this could result in
    new data being used by the previously issued drawing commands.  It should be
    noted that providing the maximum time between the drawing set fence and the
    modification test/finish fence allows the most asynchronous behavior and
    will result in the least stalling waiting for drawing completion. Techniques
    such as double buffering vertex data can be used to help further prevent
    stalls based on fence completion but are beyond the scope of this extension.

    Once an application is finished with a specific vertex array range or at
    latest prior to exit, and prior to freeing the memory associated with this
    vertex array, the client should call VertexArrayRangeAPPLE with a data
    location and length of 0 to allow the internal memory managers to complete
    any commitments for the array range.  In this case once
    VertexArrayRangeAPPLE returns it is safe to de-allocate the memory.

    An additional option is presented for vertex array ranges, the ability of
    the client to hint to OpenGL the type of access and/or use the vertex array
    memory is expected to have, by using VertexArrayParameteriAPPLE with either
    of the STORAGE_CACHED_APPLE or STORAGE_SHARED_APPLE parameter.  By default,
    all vertex array ranges are considered to be "shared".  These options allow
    the tuning of memory handling by OpenGL.  "Shared" memory is normally used
    for dynamic data that is expected to be modified and is likely mapped to AGP
    space for access by the graphics hardware and client.  "Cached" memory is
    designed to support static data and could be cached into to VRAM to provide
    the maximum access bandwidth for the vertex array.  Note, these hints can
    affect how array flushes are handled and the overhead associated with
    flushing the array, it is recommended that data be left as "shared" unless
    it really is static and there are no plans to modify it.

    To summarize the vertex array range extension provides relaxed
    synchronization rules for handling vertex array data allowing high bandwidth
    asynchronous data transfer from client memory to graphics hardware.
    Different flushing and synchronization rules are required to ensure data
    coherency when modifying data.  Lastly, memory handling hints are provided
    to allow the tunning of memory storage and access for maximum efficiency.

Issues

    How does this extension interact with the compiled_vertex_array extension?

       RESOLUTION:  They are independent and not interfere with each other.  In
       practice, if you use APPLE_vertex_array_range, you can surpass the
       performance of compiled_vertex_array

    Should we give a programmer a sense of how big a vertex array range they can
    specify?

       RESOLUTION:  Not completely resolved.  There should be a query for
       determining the maximum safe size of a vertex array range which, we do
       not have as of yet.  Currently, the vertex array range size plus the
       command buffers must not exceed available GART space, which in real world
       terms, means the smallest maximum vertex array range size is about 24 MB
       on any currently supported hardware on Mac OS X and get's larger normally
       with more RAM and/or more advanced graphics hardware. Failure modes are
       likely either failure to speed up the vertex processing or failure to
       draw all the vertex data.  So clients should plan on single vertex array
       ranges of less than 24 MB if they intend to run on all Mac OS X hardware.

    Should Flush be the same as FlushVertexArrayRangeAPPLE?

       RESOLUTION:  No.  A Flush is a different concept than
       FlushVertexArrayRangeAPPLE.  a Flush submits pending OpenGL commands to the
       OpenGL engine for processing while, a FlushVertexArrayRangeAPPLE just ensures
       memory coherency for the vertex array range and does not perform a Flush
       in OpenGL terms.

New Procedures and Functions

    void VertexArrayRangeAPPLE(sizei length, void *pointer);
    void FlushVertexArrayRangeAPPLE(sizei length, void *pointer);
    void VertexArrayParameteriAPPLE(enum pname, int param);

New Tokens

    Accepted by the <cap> parameter of EnableClientState, DisableClientState,
    and IsEnabled:

        VERTEX_ARRAY_RANGE_APPLE              0x851D

    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
    and GetDoublev:

        VERTEX_ARRAY_RANGE_LENGTH_APPLE       0x851E
        MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE  0x8520

    Accepted by the <pname> parameter of GetPointerv:

        VERTEX_ARRAY_RANGE_POINTER_APPLE      0x8521

    Accepted by the <pname> parameter of VertexArrayParameteriAPPLE,
	GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev:

        VERTEX_ARRAY_STORAGE_HINT_APPLE       0x851F

    Accepted by the <param> parameter of VertexArrayParameteriAPPLE:

        STORAGE_CACHED_APPLE                  0x85BE
        STORAGE_SHARED_APPLE                  0x85BF

Additions to Chapter 2 of the OpenGL 1.1 Specification (OpenGL Operation)

    After the discussion of vertex arrays (Section 2.8) add a
    description of the vertex array range:

    "The command 

       void VertexArrayRangeAPPLE(sizei length, void *pointer)

    specifies the current vertex array range.  When the vertex array range is
    specified and valid, vertex array vertex transfers from within the vertex
    array range are potentially faster.  The vertex array range is a contiguous
    region of address space for placing vertex arrays.  The "pointer" parameter
    is a pointer to the base of the vertex array range.  The "length" pointer is
    the length of the vertex array range in basic machine units (typically
    unsigned bytes).  Memory associated with a vertex array range should be
    allocated by the client and the responsibility for maintaining it rests with
    the client as long as it is being used as a vertex array range.

    The vertex array range address space region extends from "pointer" to
    "pointer + length - 1" inclusive.  When specified, vertex array vertex
    transfers from within the vertex array range are potentially faster.

    There is some system burden associated with establishing a vertex array
    range (typically, the memory range must be locked down). If either the
    vertex array range pointer or size is set to zero, the previously
    established vertex array range is released (typically, unlocking the
    memory).  This should always be done prior to freeing of the memory by the
    client.

    The vertex array range may not be established for operating system dependent
    reasons, and therefore, not valid.  Reasons that a vertex array range cannot
    be established include exceeding the maximum vertex array range size, the
    memory could not be locked down, etc.

    The vertex array range is considered enabled after VERTEX_ARRAY_RANGE_APPLE
    client state is enabled and as soon as a valid vertex array range is
    specified and disabled once the size length and/or pointer is set to zero or
    VERTEX_ARRAY_RANGE_APPLE client state is disabled.

    When the vertex array range is enabled, ArrayElement commands may generate
    undefined vertices if and only if any indexed elements of the enabled arrays
    are not within the vertex array range or if the index is negative or greater
    or equal to the implementation-dependent value of
    MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE.  If an undefined vertex is generated,
    an INVALID_OPERATION error may or may not be generated.

    The vertex array coherency model specifies when vertex data must be extracted
    from the vertex array memory.  When the vertex array range is not valid,
    (quoting the specification) `Changes made to array data between the
    execution of Begin and the corresponding execution of End may effect calls
    to ArrayElement that are made within the same Begin/End period in
    non-sequential ways.  That is, a call to ArrayElement that precedes a change
    to array data may access the changed data, and a call that follows a change
    to array data may access the original data.'

    When the vertex array range is valid, the vertex array coherency model is
    relaxed so that changes made to array data may affect calls to ArrayElement
    in non-sequential ways. That is a call to ArrayElement that precedes a
    change to array data may access the changed data, and a call that follows a
    change to array data may access original data.  This requires in two points
    of synchronization to maintain coherency.

    The first point where synchronization must occur to maintain coherency is
    post data modification, prior to drawing.  FlushVertexArrayRangeAPPLE should
    be used by the client on all ranges of memory which have been modified since
    the last call to VertexArrayRangeAPPLE or FlushVertexArrayRangeAPPLE.

    The second point of synchronization is after drawing with a vertex array
    range and prior to modifying it's data.  In this case either Finish or a
    fence must be used.  Finish will create a synchronization point for all
    drawing an may not be the optimal method to ensure drawing completion prior
    to data modification.  A fence, defined in the APPLE_fence extension, on the
    other hand allows more selective synchronization. The client can set a fence
    immediately after drawing with the data in question and test or finish that
    fence prior to modifying the data.  See the APPLE_fence extension for more
    details.

    To maintain full coherency, once a vertex array range is enabled, requires
    the client to both flush the vertex array after data modification, prior to
    drawing, and synchronize with Finish or a fence after drawing, prior to
    modifying the data.

    The command 

        void VertexArrayParameteriAPPLE(enum pname, int param)

    allows the client to hint at the expected use of the vertex array range.
    pname must be VERTEX_ARRAY_STORAGE_HINT_APPLE.  param can either be
    STORAGE_CACHED_APPLE or STORAGE_SHARED_APPLE and can be used by the system
    to tune the handling of the vertex array range data. These
    parameters are just hints and require no specific handling by the system. 
    The default state is STORAGE_SHARED_APPLE which, indicates that the vertex
    data is expected to be dynamic and should be handled in a way to optimize
    modification and flushing of the vertex array range, if possible.
    STORAGE_CACHED_APPLE indicates the data is expected to static and techniques
    such as VRAM caching could be employed to optimize memory bandwidth to the
    vertex array range.  Proper use of FlushVertexArrayRangeAPPLE guarantees
    memory coherency in all cases and will result in deterministic defined
    behavior in all cases, whether hints are employed or not.

    The client state required to implement the vertex array range consists of an
    enable bit, a memory pointer, an integer size, and a valid bit."

Additions to Chapter 5 of the OpenGL 1.1 Specification (Special Functions)

    Add to the end of Section 5.4 "Display Lists"

    "VertexArrayRangeAPPLE and FlushVertexArrayRangeAPPLE are not complied into
    display lists but are executed immediately.

    If a display list is compiled while VERTEX_ARRAY_RANGE_APPLE is enabled, the
    commands ArrayElement, DrawArrays, DrawElements, and DrawRangeElements are
    accumulated into a display list as if VERTEX_ARRAY_RANGE_APPLE is disabled."

Additions to the CGL interface:

    None

Additions to the WGL interface:

    None

Additions to the GLX Specification

    None

GLX Protocol

    None

Errors

    INVALID_OPERATION is generated if VertexArrayRangeAPPLE or
    FlushVertexArrayRangeAPPLE is called between the execution of Begin and the
    corresponding execution of End.

    INVALID_OPERATION may be generated if an undefined vertex is generated.

New State

                                                              Initial
   Get Value                          Get Command     Type    Value    Attrib
   ---------                          -----------     ----    -------  ------------
   VERTEX_ARRAY_RANGE_APPLE           IsEnabled       B       False    vertex-array
   VERTEX_ARRAY_RANGE_POINTER_APPLE   GetPointerv     Z+      0        vertex-array
   VERTEX_ARRAY_RANGE_LENGTH_APPLE    GetIntegerv     Z+      0        vertex-array

New Implementation Dependent State

    Get Value                              Get Command     Type    Minimum Value
    ---------                              -----------     -----   -------------
    MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE   GetIntegerv     Z+      65535

Revision History

    None
