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.