Name ATI_vertex_array_object Name Strings GL_ATI_vertex_array_object Contact Rick Hammerstone, AMD (rick.hammerstone 'at' amd.com) Version 1.11 - 11/04/06 Updated contact info after ATI/AMD merger. 1.1 - 01/08/02 Changed DeleteObjectBufferATI to FreeObjectBufferATI to match the glati.h header file. Removed objbuf attribute. 1.01 - 09/18/01 Added clarification that ArrayObectATI and VariantArrayObjectATI are not allowed between Begin/End but may not return an error. 1.0 - 09/06/01 Changed references to ATI_vertex_shader to EXT_vertex_shader. 0.9 - 08/15/01 Added support for variant arrays. 0.8 - 07/06/01 Added table of new state. 0.7 - 07/02/01 Added official enumerants. 0.6 - 05/07/01 Chopped out most of the new entry points. Back to just object buffers and one call to define vertex arrays in an object buffer. 0.5 - 04/18/01 The great renaming. Added sample usage section. Expanded issues section. 0.4 - 04/09/01 Rewrote to use new entry points. 0.3 - 04/06/01 Changed Allocate and Free to New and Delete. 0.2 - 03/26/01 Added error description, additions to section 5 and 6 of the spec. 0.1 Original version Number 247 Dependencies This extension is written against the OpenGL 1.2.1 Specification. OpenGL 1.1 is required. GL_EXT_vertex_shader affects the definition of this extension. Overview This extension defines an interface that allows multiple sets of vertex array data to be cached in persistent server-side memory. It is intended to allow client data to be stored in memory that can be directly accessed by graphics hardware. Issues Should this extension include support for allowing vertex indices to be stored on the server? RESOLUTION: NO. This might not be universally supported, and seems simple enough to layer on top of this extension. Is there a better name for this extension? RESOLUTION: YES. The ArrayStore vs. StoredArray terminology was confusing. StoredArrays have been changed to be ArrayObjects. Since any type of object could be stored in the ArrayStore, these have been changed to ObjectBuffers. Should the layout of an array store be defined at array store creation time? RESOLUTION: NO. This could provide better performance if the client specifies a data type that the hardware doesn't support, but this isn't a performance path anyways, and it adds a cumbersome interface on top of the extension. Should the client be able to retrieve a pointer to the array store instead of a handle? RESOLUTION: NO. For now, it doesn't seem like this is a big win, and it presents problems on certain OS's. It also requires using an explicit synchronization mechanism. This would be pretty trivial to add, however. Should this just sit on top of the existing vertex array implementation, instead of introducing a new set of API calls? RESOLUTION: NO. Trying to fit something on top existing vertex arrays introduces a lot of confusion as to where the data is stored (on the client side vs. on the server side). Adding new API that mirrors traditional vertex arrays doesn't seem to cumbersome. New Procedures and Functions For creating, updating, and querying object buffers: uint NewObjectBufferATI(sizei size, const void *pointer, enum usage) boolean IsObjectBufferATI(uint buffer) void UpdateObjectBufferATI(uint buffer, uint offset, sizei size, const void *pointer, enum preserve) void GetObjectBufferfvATI(uint buffer, enum pname, float *params) void GetObjectBufferivATI(uint buffer, enum pname, int *params) void FreeObjectBufferATI(uint buffer) For defining vertex arrays inside an object buffer: void ArrayObjectATI(enum array, int size, enum type, sizei stride, uint buffer, uint offset) For querying vertex arrays inside an object buffer: void GetArrayObjectfvATI(enum array, enum pname, float *params) void GetArrayObjectivATI(enum array, enum pname, int *params) If EXT_vertex_shader is defined, for defining variant arrays inside an object buffer: void VariantArrayObjectATI(uint id, enum type, sizei stride, uint buffer, uint offset) If EXT_vertex_shader is defined, for querying variant arrays inside an object buffer: void GetVariantArrayObjectfvATI(uint id, enum pname, float *params) void GetVariantArrayObjectivATI(uint id, enum pname, int *params) New Tokens Accepted by the parameter of NewObjectBufferATI: STATIC_ATI 0x8760 DYNAMIC_ATI 0x8761 Accepted by the parameter of UpdateObjectBufferATI: PRESERVE_ATI 0x8762 DISCARD_ATI 0x8763 Accepted by the parameter of GetObjectBufferivATI and GetObjectBufferfvATI: OBJECT_BUFFER_SIZE_ATI 0x8764 OBJECT_BUFFER_USAGE_ATI 0x8765 Accepted by the parameter of GetArrayObjectivATI and GetArrayObjectfvATI: ARRAY_OBJECT_BUFFER_ATI 0x8766 ARRAY_OBJECT_OFFSET_ATI 0x8767 Additions to Chapter 2 of the GL Specification (OpenGL Operation) In section 2.6.3, GL Commands within Begin/End, add ArrayObjectATI to the list of commands that are not allowed within any Begin/End pair, but may or may not generate an error. If EXT_vertex_shader is defined, add VariantArrayObjectATI to the list of commands that are not allowed within any Begin/End pair, but may or may not generate an error. Inserted between section 2.8, Vertex Arrays, and section 2.9, Rectangles, a new section titled Vertex Array Objects. In order to provide more a more efficient mechanism for storing frequently used vertex array data on the server side, a client may use the command uint NewObjectBufferATI(sizei size, const void *pointer, enum usage); to allocate a persistent buffer in which client data may be stored. specifies the size of the allocation in machine units (hereafter assumed to be unsigned bytes). specifies a region of client memory that contains data to initialize the object buffer. If is null, then the object buffer is created but not initialized. provides a hint to the implementation of whether the contents of the object buffer will be static or dynamic. must be either STATIC_ATI or DYNAMIC_ATI. If the client specifies an object buffer as static, its contents may still be updated, however this may result in reduced performance. The return value is a positive integer that uniquely identifies the object buffer. If the object buffer cannot be allocated, the return value is zero. When the client creates an object buffer using NewObjectBufferATI, the implementation can provide more efficient transfers of data between the client and the graphics controller by allocating the object buffer in memory that can be directly addressed by the graphics controller. In addition, because the object buffer is persistent across multiple drawing commands, static data must only be copied to the object buffer once. To modify the data contained in the object buffer, the client may use the command void UpdateObjectBufferATI(uint buffer, uint offset, sizei size, const void *pointer, enum preserve); identifies the object buffer to be updated. and indicate the range of data in the object buffer that is to be updated. specifies a region of client memory that contains data to update the object buffer. The client can use the parameter of UpdateObjectBufferATI to indicate whether data outside the region being updated must be preserved. must be one of PRESERVE_ATI or DISCARD_ATI. If a client specifies that data outside the range being updated may be discarded, the implementation may be able process updates in a more optimal fashion. Whenever UpdateObjectBufferATI is called, the byte values in the object buffer from to + - 1 are updated with the data referenced by . If the client specifies PRESERVE_ATI, all other byte values in the object buffer remain unchanged. If the client specifies DISCARD_ATI, then all byte values outside the range that has been updated become undefined. Once created, an object buffer remains available for use until it is destroyed by calling void FreeObjectBufferATI(uint buffer); identifies the object buffer to be destroyed. After creating an object buffer, the client can use the command void ArrayObjectATI(enum array, int size, enum type, sizei stride, uint buffer, uint offset); to allow a portion of the object buffer to be used as a vertex array. specifies the array to be defined. This must match one of the allowable enumerants accepted by EnableClientState and DisableClientState. , , and specify the format and packing of the data stored in the array in the same manner as the corresponding vertex array pointer command. and must match the allowed sizes and types given for the corresponding commands in table 2.4. specifies the object buffer that contains the data to be used as a vertex array. specifies the offset in machine units into the object buffer at which the vertex array data begins. When a vertex array is specified in this manner, the memory pointer that is part of the client state for the vertex array is set to null to indicate that the vertex array has been defined using ArrayObjectATI instead of one of the pointer commands. Vertex arrays that are defined to reside within an object buffer function in the same manner as normal vertex arrays. They are enabled and disabled by using the commands EnableClientState and DisableClientState. Primitives can be constructed using ArrayElement, DrawArrays, DrawElements, and DrawRangeElements. Clients may use mix of traditional vertex arrays and vertex array objects to specify geometry. There is no explicit mechanism to define interleaved vertex arrays in an object buffer. This can be implicitly done by storing the arrays in an interleaved fashion during NewObjectBufferATI or UpdateObjectBufferATI. If EXT_vertex_shader is defined, then a client can define an array of variant data using the command: void VariantArrayObjectATI(uint id, enum type, sizei stride, uint buffer, uint offset); indicates the variant that this array should be associated with. The , , , and parameters have the same meaning as the corresponding parameters of ArrayObjectATI. As always, variant arrays have a fixed size of 4 components. Variant arrays defined by VariantArrayObjectATI are enabled and disabled in the same way as variant arrays defined by VariantPointerATI, by using EnableVariantClientStateATI and DisableVariantClientStateATI. Additions to Chapter 3 of the 1.2.1 Specification (Rasterization) None Additions to Chapter 4 of the 1.2.1 Specification (Per-Fragment Operations and the Frame Buffer) None Additions to Chapter 5 of the 1.2.1 Specification (Special Functions) Added to section 5.4, as part of the discussion of what commands are compiled into display lists: The commands defined by this extension function in the same manner as the traditional vertex array commands when they are compiled into a display list. Commands that are used to create and manage memory for stored arrays are not included in display lists, but are executed immediately. These include NewObjectBufferATI, IsObjectBufferATI, UpdateObjectBufferATI, GetObjectBufferfvATI, GetObjectBufferivATI, and FreeObjectBufferATI. Commands that are used to define and query vertex arrays within an object buffer are not included in display lists, but are executed immediately. These include ArrayObjectATI, GetArrayObjectfvATI, and GetArrayObjectivATI. Additions to Chapter 6 of the 1.2.1 Specification (State and State Requests) Added to section 6.1 in a subsection titled Object Buffer Queries: The command boolean IsObjectBufferATI(uint buffer) returns TRUE if is the name of an object buffer. If is zero, or if is a non-zero value that is not the name of an object buffer, IsObjectBufferATI return FALSE. Added to the list of queries in section 6.1.3, Enumerated Queries: void GetObjectBuffer{if}vATI(uint buffer, enum value, T data); void GetArrayObject{if}vATI(enum array, enum value, T data); If EXT_vertex_shader is defined: void GetVariantArrayObject{if}vATI(uint id, enum value, T data); Appended to the description of the queries in section 6.1.3, Enumerated Queries: GetObjectBuffer is used to retrieve information about an object buffer. must identify a valid object buffer. must be one of OBJECT_BUFFER_SIZE_ATI or OBJECT_BUFFER_USAGE_ATI. If is OBJECT_BUFFER_SIZE_ATI, then the size of the object buffer in bytes is returned in . The exact size of the object buffer is an implementation dependent value, but is guaranteed to be at least as large as the value specified by the parameter of NewObjectBufferATI. If is OBJECT_BUFFER_USAGE_ATI, then the value returned in will be either STATIC_ATI or DYNAMIC_ATI. The return value will match the value specified by the parameter of NewObjectBufferATI. GetArrayObjectATI is used to retrieve information on a vertex array located in an object buffer. indicates the vertex array that is to be queried. It must match one of the allowable enumerants accepted by EnableClientState and DisableClientState. If EXT_vertex_shader is defined, GetVariantArrayObjectATI is used to retrieve information on a variant array located in an object buffer. indicates the variant that is to be queried. For both queries, must be one of ARRAY_OBJECT_BUFFER_ATI, or ARRAY_OBJECT_OFFSET_ATI. For each of these enumerants, the value returned in represents the object buffer that contains the vertex data, or the byte offset from the object buffer at which the first vertex starts, respectively. If the specified vertex array or variant array has not been defined to reside in an object buffer, GetArrayObjectATI will return zero for both enumerants. Errors INVALID_ENUM is generated if the parameter of NewObjectBufferATI is not STATIC_ATI or DYNAMIC_ATI. OUT_OF_MEMORY may be generated if an object buffer cannot be allocated because the argument of NewObjectBufferATI is too large. INVALID_VALUE is generated if the argument of UpdateObjectBufferATI, GetObjectBufferfvATI, GetObjectBufferivATI, FreeObjectBufferATI, and ArrayObjectATI does not identify a valid object buffer. INVALID_VALUE is generated if the and parameters of UpdateObjectBufferATI would reference a region of memory outside that allocated by the call to NewObjectBufferATI. INVALID_ENUM is generated if the parameter of GetObjectBufferfvATI and GetObjectBufferivATI is not OBJECT_BUFFER_SIZE_ATI or OBJECT_BUFFER_USAGE_ATI. INVALID_ENUM is generated if the parameter of ArrayObjectATI, GetArrayObjectfvATI, and GetArrayObjectivATI does not match one of the enumerants allowed by EnableClientState and DisableClientState. INVALID_VALUE is generated if the parameter of VariantArrayObjectATI, GetVariantArrayObjectfvATI, and GetVariantArrayObjectivATI does not correspond to a previously defined variant. INVALID_VALUE is generated if the and parameters of ArrayObjectATI do not match the allowable sizes and types given for the pointer command corresponding to the parameter. INVALID_VALUE is generated if the parameter of ArrayObjectATI is larger than the size of the object buffer as specified by NewObjectBufferATI. INVALID_ENUM is generated if the parameter of GetArrayObjectfvATI and GetArrayObjectivATI is not ARRAY_OBJECT_BUFFER_ATI or ARRAY_OBJECT_OFFSET_ATI. New State In a new table, Object Buffers Get Value Get Command Type Initial Value Attrib --------- ----------- ---- ------------- ------ OBJECT_BUFFER_SIZE_ATI GetIntegerv Z+ 0 - OBJECT_BUFFER_USAGE_ATI GetIntegerv Z4 STATIC_ATI - ARRAY_OBJECT_BUFFER_ATI GetIntegerv Z+ 0 - ARRAY_OBJECT_OFFSET_ATI GetIntegerv Z+ 0 - Usage Example Here is a simple example that demonstrates usage of the extension. The example provides a comparison between traditional vertex arrays and vertex array objects. Note that this is not a particularly efficient use of vertex array objects, since the array object are only used once before being destroyed. Typically the client will create many array objects and transfer all of its vertex data to the server before beginning any rendering. Traditional vertex arrays: // Define VertexPointer(4, FLOAT, 16, data); ColorPointer(4, UNSIGNED_BYTE, 4, data + 256); // Enable EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Draw DrawArrays(TRIANGLES, 0, 16); // Disable DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); Vertex array objects: // Create object buffer buffer = NewObjectBufferATI(320, data, STATIC_ATI); // Define ArrayObjectATI(VERTEX_ARRAY, 4, FLOAT, 16, buffer, 0); ArrayObjectATI(COLOR_ARRAY, 4, UNSIGNED_BYTE, 4, buffer, 256); // Enable EnableClientState(VERTEX_ARRAY); EnableClientState(COLOR_ARRAY); // Draw DrawArrays(TRIANGLES, 0, 16); // Disable DisableClientState(VERTEX_ARRAY); DisableClientState(COLOR_ARRAY); // Free object buffer FreeObjectBufferATI(buffer); Implementation Notes For maximum hardware performance, all vertex arrays except for color and secondary color should always be specified to use float as the component type. Color and secondary color arrays may be specified to use either float or 4-component unsigned byte as the component type. Typically, an object buffer will contain all of the vertex information associated with a given object in a scene. This can include multiple arrays of geometry, color, and texture data. If portions of this data are static, and portions are dynamic, greater performance can be achieved by placing the dynamic vertex data in a separate object buffer and updating the entire object buffer at once.