What should this extension be called? #
RESOLVED: By unanimous consent among the working group members, the name was chosen to be "ARB_vertex_buffer_object". A large number of other names were considered throughout the lifetime of the proposal, especially "vertex_array_object" (originally), "buffer_object" (later on), and "memory_object" (near the end), but the name "vertex_buffer_object" was ultimately chosen.
In particular, this name emphasizes not only that we have created a new type of object that encapsulates arbitrary data (buffer objects), but also, in particular, that these objects are used in this extension to source vertex data. The name also is intentionally similar to "vertex buffers", although it should be emphasized that there is no such thing as a "vertex buffer" in the terminology of this extension. The term "buffer object" is the correct noun.
이 확장과 ATI_vertex_array_object + ATI_map_object_buffer를 사용하는 것과 어떤 차이가 있나요? #
아래는 핵심 차이점을 요약한 것입니다.
- VAOs renamed to "buffer objects", to signify that they can be used for more than just vertex data. Other renaming and API changes to try to better match OpenGL conventions.
- The standard GL pointer APIs have been overloaded to be able to refer to offsets within these buffers, rather than adding new entry points.
- The usage modes permitted for buffers have been augmented significantly, to reflect a broader class of application behaviors.
- A new entry point allows reading back the contents of a buffer object.
이 확장과 NV_vertex_array_range와의 차이점은 무엇입니까? #
아래는 핵심 차이점을 요약한 것입니다.
- 어플리케이션은 더이상 메모리 관리와 동기화를 책임질 필요가 없습니다.
- 어플리케이션에서는 아직도 고성능 메모리에 접근하려하지도 모르지만, 이것은 선택사항이며 이러한 접근방식은 더 제한을 받게 되었습니다.
- 버퍼 변경(glBindBufferARB)은 일반적으로 엄청 무거운 처리방식(glVertexArrayRangeNV)보다는 매우 가벼운 처리로 간주되도록 되어있습니다.
- wgl/glXAllocateMemoryNV와 같은 특정 플렛폼 전용 메모리 할당명령이 더이상 필요하지 않습니다.
이 확장은 NV_pixel_data_range과 어떻게 관련되어있죠? #
A future extension could be created based on the framework created here that would support analogous functionality to that provided by NV_pixel_data_range. Presumably, this extension would require little more than two new targets for BindBuffer, named (say) UNPACK_PIXELS and PACK_PIXELS. The lists of commands affected by these bindings could easily be taken verbatim out of the NV_pixel_data_range specification.
Should this extension include support for allowing vertex indices to be stored in buffer objects? #
RESOLVED: YES. It is easily and cleanly added with just the addition of a binding point for the index buffer object. Since our approach of overloading pointers works for any pointer in GL, no additional APIs need be defined, unlike in the various *_element_array extensions.
Note that it is expected that implementations may have different memory type requirements for efficient storage of indices and vertices. For example, some systems may prefer indices in AGP memory and vertices in video memory, or vice versa; or, on systems where DMA of index data is not supported, index data must be stored in (cacheable) system memory for acceptable performance. As a result, applications are strongly urged to put their models' vertex and index data in separate buffers, to assist drivers in choosing the most efficient locations.
Should the layout of an array store be defined at array store creation time? #
RESOLVED: 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 there be some sort of scheme for allowing applications to stream vertex data efficiently? #
RESOLVED: YES. Applications that generate their data on the fly end up doing an extra data copy unless they are given a pointer into memory that the graphics hardware can DMA from. The performance win from doing this can be significant.
Should the client be able to retrieve a pointer to a buffer object? #
RESOLVED: YES. This solves the previous problem. Since GL vertex array formats are already user-visible, this does not suffer from the sorts of formatting issues that would arise if the GL allowed applications to retrieve pointers to texture objects or to the framebuffer. Synchronization can be a concern, but proper usage of this extension will minimize its overhead.
Should this extension sit on top of the existing vertex array implementation, instead of introducing a new set of API calls? #
RESOLVED: YES. This simplifies the API, and separating out the buffer binding from the offset/stride within the buffer leads to an elegant "BindBufferARB" command that can be used for other parts of GL like the pixel path.
Should buffer object state overlap with existing vertex array pointer state, or should there be new drawing commands, e.g., DrawArrayObject? #
Does the buffer binding state push/pop? #
RESOLVED: YES. It pushes/pops on the client with the rest of the vertex array state. Some revisions of the ATI VAO spec listed a push/pop attrib "objbuf", but no new bit was defined; all this has been moved into the standard "vertex-array" bit.
Note that both the user-controlled binding ARRAY_BUFFER_ARB binding point and the per-array bindings push and pop.
Note that additional binding points, such as ones for pixel or texture transfers, would not be part of the vertex array state, and thus would likely push and pop as part of the pixel store (client) state when they are defined.
How is the decision whether to use the array pointer as an offset or as a real pointer made? #
RESOLVED: When the default buffer object (object zero) is bound, all pointers behave as real pointers. When any other object is bound, all pointers are treated as offsets. Conceptually, one can imagine that buffer object zero is a buffer object sitting at base NULL and with an extent large enough that it covers all of the system's virtual address space.
Note that this approach essentially requires that binding points be client (not server) state.
Can buffer objects be shared between contexts in the same way that display lists are? #
RESOLVED: YES. All potentially large OpenGL objects, such as display lists and textures, can be shared, and this is an important capability. Note, however, that sharing requires that buffer objects be server (not client) state, since it is not possible to share client state.
Should buffer objects be client state or server state? #
RESOLVED: Server state. Arguments for client state include:
- Buffer data are stored in client-side format, making server storage complex when client and server endianness differ.
- Vertex arrays are client state.
- Server state can be shared between contexts, and this is expected to be an important capability (sharing of texture objects is very common).
- In the case of indirect rendering, performance may be very significantly greater for data stored on the server side of the wire.
How is synchronization enforced when buffer objects are shared by multiple OpenGL contexts? #
RESOLVED: It is generally the clients' responsibility to synchronize modifications made to shared buffer objects. GL implementations will make some effort to avoid deletion of in-use buffer objects, but may not be able to ensure this handling.
What happens if a currently bound buffer object is deleted? #
RESOLVED: Orphan. To avoid chasing invalid pointers OpenGL implementations will attempt to defer the deletion of any buffer object until that object is not bound by any client in the share list. It should be possible to implement this behavior efficiently in the direct rendering case, but the implementation may be difficult/impossible in the indirect rendering case. Since synchronization during sharing is a client responsibility, this behavior is acceptable.
Should there be a way to query the data in a buffer object? #
RESOLVED: YES. Almost all objects in OpenGL are fully queriable, and since these objects are simply byte arrays, there does not seem to be any reason to do things otherwise here. The primary exceptions to GL queriability are cases where such functionality would be extremely burdensome to provide, as is the case with display lists.
Do buffer objects survive screen resolution changes, etc.? #
RESOLVED: YES. This is not mentioned in the spec, so by default they behave just like other OpenGL state, like texture objects -- the data is unmodified by external events like modeswitches, switching the system into standby or hibernate mode, etc.
What happens to a mapped buffer when a screen resolution change or other such window-system-specific system event occurs? #
RESOLVED: The buffer's contents may become undefined. The application will then be notified at Unmap time that the buffer's contents have been destroyed. However, for the remaining duration of the map, the pointer returned from Map must continue to point to valid memory, in order to ensure that the application cannot crash if it continues to read or write after the system event has been handled.
What happens to the pointer returned by MapBufferARB after a call to UnmapBufferARB? #
RESOLVED: The pointer becomes totally invalid. Note that drivers are free to move the underlying buffer or even unmap the memory, leaving the virtual addresses in question pointing at nothing. Such flexibility is necessary to enable efficient implementations on systems with no virtual memory; with limited control over virtual memory from graphics drivers; or where virtual address space is at a premium.
How does indirect rendering work? #
It is not currently specified, but the basic planned outline is as follows.
All of the object management commands -- Gen, Is, Delete -- go to the server immediately with normal protocol. So does Bind. However, when someone does an implicit bind via one of the pointer commands (e.g. VertexPointer), the server may not necessarily be notified immediately of the new object bound to the (in this case) VERTEX_ARRAY_BUFFER_BINDING.
BufferData and BufferSubData are sent over the wire just as TexImage2D and TexSubImage2D, and GetBufferSubData does a round trip, just like GetTexImage. MapBuffer goes over the wire with a request to map; the server replies to tell the client whether the map succeeded or failed, and the client returns a pointer to a system memory buffer in the event of success. If the map is readable, the server passes back the contents of the buffer, while if the map is writeable, at Unmap time, the client passes back the new contents. Unmap would always return TRUE.
Whenever the application sources data from a buffer object, several new protocols are defined to specify where to obtain the data from. One new command might be called "BindArray", which would have arguments <array>, <buffer>, offset>, <type>, <size>, <stride>, and <normalized>. <array> might be VERTEX_ARRAY, NORMAL_ARRAY, etc. <buffer> would be the ID of the buffer object to be used as source, or zero if no buffer object. <offset> would be a 64-bit (?) integer. <type>, <size>, <stride>, and <normalized> would all be the same as the various arguments to the *Pointer commands. Another new command might be "ArrayElementServer", which would dereference all arrays with a nonzero <buffer> on the server side, just as if immediate mode had been used. If only some arrays were coming from buffer objects and some from user memory, the client would dereference the ones in user memory and pass them in as immediate mode protocol.
If all arrays came from the server, additional optimized APIs could be provided. A "DrawArraysServer" and "DrawElementsServer" would be cheaper than a sequence of "ArrayElementServer" commands. For indices coming from a buffer object, a "DrawElementArrayServer" might be added.
At initialization time, the client and server would exchange a handshake to see if the server can understand the client's storage of the various GL data types. It is expected that nearly all clients and servers would use just two data type representations, namely, "standard little endian with IEEE floats" and "standard big endian with IEEE floats".
Are any of these commands allowed inside Begin/End? #
RESOLVED: NO, with the possible exception of BindBuffer, which should not be used inside a Begin/End but will have undefined error behavior, like most vertex array commands.
What happens when an attempt is made to access data outside the bounds of the buffer object with a command that dereferences the arrays? #
RESOLVED: ALLOW PROGRAM TERMINATION. In the event of a software fallback, bounds checking can become impractical. Since applications don't know the actual address of the buffer object and only provide an offset, they can't ever guarantee that out-of-bounds offsets will fall on valid memory. So it's hard to do any better than this.
Of course, such an event should not be able to bring down the system, only terminate the program.
What type should <offset> and <size> arguments use? #
RESOLVED: We define new types that will work well on 64-bit systems, analogous to C's "intptr_t". The new type "GLintptrARB" should be used in place of GLint whenever it is expected that values might exceed 2 billion. The new type "GLsizeiptrARB" should be used in place of GLsizei whenever it is expected that counts might exceed 2 billion. Both types are defined as signed integers large enough to contain any pointer value. As a result, they naturally scale to larger numbers of bits on systems with 64-bit or even larger pointers.
The offsets introduced in this extension are typed GLintptrARB, consistent with other GL parameters that must be non-negative, but are arithmetic in nature (not uint), and are not sizes; for example, the xoffset argument to TexSubImage*D is of type GLint. Buffer sizes are typed GLsizeiptrARB.
The idea of making these types unsigned was considered, but was ultimately rejected on the grounds that supporting buffers larger than 2 GB was not deemed important on 32-bit systems.
Should buffer maps be client or server state? #
RESOLVED: Server. If a buffer is being shared by multiple clients, it will also be desirable to share the mappings of that buffer. In cases where the mapping cannot shared (for example, in the case of indirect rendering) queries of the map pointer by clients other than the one that created the map will return a null pointer.
Should "usage" be a parameter to BufferDataARB, or specified separately using a parameter specification command, e.g., BufferParameteriARB? #
RESOLVED: Parameter to BufferDataARB. It is desirable for the implementation to know the usage when the buffer is initialized, so including it in the initialization command makes sense. This avoids manpage notes such as "Please specify the usage before you initialize the buffer".
Should it be possible to change the usage of an initialized buffer? #
RESOLVED: NO. Unless it is shown that this flexibility is necessary, it will be easier for implementations to be efficient if usage cannot be changed. (Except by re-initializing the buffer completely.)
Should we allow for the possibility of multiple simultaneous maps for a single buffer? #
RESOLVED: NO. If multiple maps are allowed, the mapping semantics become very difficult to understand and to specify. It is also unclear that there are any benefits to offering such functionality. Therefore, only one map per buffer is permitted.
Note: the limit of one map per buffer eliminates any need for "sub-region" mapping. The single map always maps the entire data store of the buffer.
Should it be an error to render from a currently mapped buffer? #
RESOLVED: YES. Making this an error rather than undefined makes the API much more bulletproof.
Should it be possible for the application to query the "viability" of the data store of a buffer? #
RESOLVED: NO. UnmapBuffer can return FALSE to indicate this, but there is no additional query to check whether the data has been lost. In general, most/all GL state is queriable, unless there is a compelling reason otherwise. However, on examination, it appears that there are several compelling reasons otherwise in this case. In particular, the default for this state variable is non-obvious (is the data "valid" when no data has been specified yet?), and it's unclear when it should be reset (BufferData only? BufferSubData? A successful UnmapBuffer?). After these issues came to light, the query was removed from the spec.
Should UnmapBufferARB return a boolean indicating data integrity? #
RESOLVED: YES, since the Unmap is precisely the point at which the buffer can no longer be lost.
How is unaligned data handled? #
RESOLVED: All client restrictions on data alignment must be met, and in addition to that, all offsets must be multiples of the size of the underlying data type. So, for example, float data in a buffer object must have an offset that is (typically) a multiple of 4. This should make the server implementation easier, since this additional rule will guarantee that no alignment checking is required on most platforms.
Should MapBufferARB return the pointer to the map, or should there be a separate call to ask for the pointer? #
RESOLVED: BOTH. For convenience, MapBufferARB returns a pointer or NULL in the event of failure; but since most/all GL state is queriable, you can also query the pointer at a later point in time. If the buffer is not mapped, querying the pointer should return NULL.
Should there be one binding point for all arrays or several binding points, one for each array? #
RESOLVED: One binding point for all arrays. Index data uses a separate target.
Should there be a PRESERVE/DISCARD option on BufferSubDataARB? On MapBufferARB? #
RESOLVED: NO, NO. ATI_vertex_array_object had this option for UpdateObjectBufferATI, which is the equivalent of BufferSubDataARB, but it's unclear whether this has any utility. There might be some utility for MapBufferARB, but forcing the user to call BufferDataARB again with a NULL data pointer has some advantages of its own, such as forcing the user to respecify the size.
Should there be an option for MapBufferARB that guarantees nonvolatile memory? #
RESOLVED: NO. On systems where volatile memory spaces are a concern, there is little or no way to supply nonvolatile memory without crippling performance badly. In some cases, it might not even be possible to implement Map except by returning system memory. Systems that do not have problems with volatility are, of course, welcome to return TRUE from UnmapBufferARB all the time. If applications want the ease of use that results from not having to check for lost data, they can still use BufferDataARB and BufferSubDataARB, so the burden is not too great.
What new usages do we need to add? #
RESOLVED. We have defined a 3x3 matrix of usages. The pixel-related terms draw, read, and copy are used to distinguish between three basic data paths: application to GL (draw), GL to application (read), and GL to GL (copy). The terms stream, static, and dynamic are used to identify three data access patterns: specify once and use once or perhaps only a few times (stream), specify once and use many times (static), and specify and use repeatedly (dynamic).
Note that the "copy" and "read" usage token values will become meaningful only when pixel transfer capability is added to buffer objects by a (presumed) subsequent extension.
Note that the data paths "draw", "read", and "copy" are analogous in both name and meaning to the GL commands DrawPixels, ReadPixels, and CopyPixels, respectively.
Is it legal C to use pointers as offsets? #
We haven't come to any definitive conclusion about this. The proposal is to convert to pointer as:
pointer = (char *)NULL + offset;And convert back to offset as:
offset = (char *)pointer - (char *)NULL;Varying opinions have been expressed as to whether this is legal, although no one could provide an example of a real system where any problems would occur.
Should we add new Offset commands, e.g., VertexOffset, if the pointer approach has some compatibility concerns? #
RESOLVED: NO. The working group voted that the existing pointer-as-offset approach is acceptable.
Which commands are compiled into display lists? #
RESOLVED: None of the commands in this extension are compiled into display lists. The reasoning is that the server may not have up-to-date buffer bindings, since BindBuffer is a client command.
Just as without this extension, vertex data is dereferenced when ArrayElement, etc. are compiled into a display list.
Should there be a new command "DiscardAndMapBuffer" that is equivalent to BufferDataARB with NULL pointer followed by MapBufferARB? #
RESOLVED: NO, no one has come up with a clearly superior proposal that everyone can agree on.
Are any GL commands disallowed when at least one buffer object is mapped? #
RESOLVED: NO. In general, applications may use whatever GL commands they wish when a buffer is mapped. However, several other restrictions on the application do apply: the application must not attempt to source data out of, or sink data into, a currently mapped buffer. Furthermore, the application may not use the pointer returned by Map as an argument to a GL command. (Note that this last restriction is unlikely to be enforced in practice, but it violates reasonable expectations about how the extension should be used, and it doesn't seem to be a very interesting usage model anyhow. Maps are for the user, not for the GL.)
More restrictive rules were considered (for example, "after calling MapBuffer, all GL commands except for UnmapBuffer produce errors"), but this was considered far too restrictive. The expectation is that an application might map a buffer and start filling it in a different thread, but continue to render in its main thread (using a different buffer or no buffer at all). So no commands are disallowed simply because a buffer happens to be mapped.
Should the usage and data arguments to BufferDataARB be swapped? #
RESOLVED: NO. This would be more consistent with other things in GL if they were swapped, but no one seems to care. If we had caught this earlier, maybe, but it's just too late.
How does MultiDrawElements work? #
The language gets a little confusing, but I believe it is quite clearly specified in the end. The argument <indices> to MultiDrawElements, which is of type "const void **", is an honest-to-goodness pointer to regular old system memory, no matter whether a buffer is bound or not. That memory in turn consists of an array of <primcount> pointers. If no buffer is bound, each of those <primcount> pointers is a regular pointer. If a buffer is bound, each of those <primcount> pointers is a fake pointer that represents an offset in the buffer object.
If you wanted to put the array of <primcount> offsets in a buffer object, you'd have to define a new extension with a new target.









![[http]](/wiki/imgs/http.png)
