Name NV_vertex_buffer_unified_memory Name Strings GL_NV_vertex_buffer_unified_memory Contact Jeff Bolz, NVIDIA Corporation (jbolz 'at' nvidia.com) Contributors Mark Kilgard, NVIDIA Jason Sams, NVIDIA Eric Werness, NVIDIA Christoph Kubisch, NVIDIA Status Complete Version Last Modified Date: July 8, 2015 Author Revision: 4 Number 380 Dependencies Written based on the wording of the OpenGL 3.0 specification. This extension interacts with NV_shader_buffer_load. This extension interacts with EXT_direct_state_access. This extension interacts with ARB_compatibility. This extension interacts with OpenGL 3.2 Overview This extension provides a mechanism to specify vertex attrib and element array locations using GPU addresses. Binding vertex buffers is one of the most frequent and expensive operations in many GL applications, due to the cost of chasing pointers and binding objects described in the Overview of NV_shader_buffer_load. The intent of this extension is to enable a way for the application to specify vertex attrib state that alleviates the overhead of object binds and driver memory management. New Procedures and Functions void BufferAddressRangeNV(enum pname, uint index, uint64EXT address, sizeiptr length); void VertexFormatNV(int size, enum type, sizei stride); void NormalFormatNV(enum type, sizei stride); void ColorFormatNV(int size, enum type, sizei stride); void IndexFormatNV(enum type, sizei stride); void TexCoordFormatNV(int size, enum type, sizei stride); void EdgeFlagFormatNV(sizei stride); void SecondaryColorFormatNV(int size, enum type, sizei stride); void FogCoordFormatNV(enum type, sizei stride); void VertexAttribFormatNV(uint index, int size, enum type, boolean normalized, sizei stride); void VertexAttribIFormatNV(uint index, int size, enum type, sizei stride); void GetIntegerui64i_vNV(enum value, uint index, uint64EXT result[]); New Tokens Accepted by the parameter of DisableClientState, EnableClientState, IsEnabled: VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E ELEMENT_ARRAY_UNIFIED_NV 0x8F1F Accepted by the parameter of BufferAddressRangeNV and the parameter of GetIntegerui64i_vNV: VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20 TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25 Accepted by the parameter of BufferAddressRangeNV and the parameter of GetIntegerui64vNV: VERTEX_ARRAY_ADDRESS_NV 0x8F21 NORMAL_ARRAY_ADDRESS_NV 0x8F22 COLOR_ARRAY_ADDRESS_NV 0x8F23 INDEX_ARRAY_ADDRESS_NV 0x8F24 EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26 SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27 FOG_COORD_ARRAY_ADDRESS_NV 0x8F28 ELEMENT_ARRAY_ADDRESS_NV 0x8F29 Accepted by the parameter of GetIntegeri_vNV or GetIntegerui64i_vNV: VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F Accepted by the parameter of GetIntegerv or GetIntegerui64vNV: VERTEX_ARRAY_LENGTH_NV 0x8F2B NORMAL_ARRAY_LENGTH_NV 0x8F2C COLOR_ARRAY_LENGTH_NV 0x8F2D INDEX_ARRAY_LENGTH_NV 0x8F2E EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30 SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31 FOG_COORD_ARRAY_LENGTH_NV 0x8F32 ELEMENT_ARRAY_LENGTH_NV 0x8F33 Additions to Chapter 2 of the OpenGL 3.0 Specification (OpenGL Operation) Add to Section 2.9 (end of p. 29) The commands: void VertexFormatNV(int size, enum type, sizei stride); void NormalFormatNV(enum type, sizei stride); void ColorFormatNV(int size, enum type, sizei stride); void IndexFormatNV(enum type, sizei stride); void TexCoordFormatNV(int size, enum type, sizei stride); void EdgeFlagFormatNV(sizei stride); void SecondaryColorFormatNV(int size, enum type, sizei stride); void FogCoordFormatNV(enum type, sizei stride); void VertexAttribFormatNV(uint index, int size, enum type, boolean normalized, sizei stride); void VertexAttribIFormatNV(uint index, int size, enum type, sizei stride); set the same vertex array format state as the corresponding command where "Format" is changed to "Pointer" (and extension suffixes are dropped or updated appropriately). They do not inspect the current ARRAY_BUFFER binding for any error checks, nor do they modify the pointer state or vertex attribute buffer bindings. The parameters are interpreted as they are in the corresponding functions. Add to Section 2.9.1 (p. 46) While VERTEX_ATTRIB_ARRAY_UNIFIED_NV is enabled, the rendering commands ArrayElement, DrawArrays, DrawElements, DrawRangeElements, MultiDrawArrays, DrawArraysInstanced, and DrawElementsInstanced operate as previously defined, except that data for enabled vertex and attrib arrays are sourced from GPU addresses specified by the command: void BufferAddressRangeNV(enum pname, uint index, uint64EXT address, sizeiptr length); where is VERTEX_ARRAY_ADDRESS_NV, NORMAL_ARRAY_ADDRESS_NV, COLOR_ARRAY_ADDRESS_NV, INDEX_ARRAY_ADDRESS_NV, EDGE_FLAG_ARRAY_ADDRESS_NV, SECONDARY_COLOR_ARRAY_ADDRESS_NV, or FOG_COORD_ARRAY_ADDRESS_NV and is ignored, or is TEXTURE_COORD_ARRAY_ADDRESS_NV and is the texture unit, or is VERTEX_ATTRIB_ARRAY_ADDRESS_NV and identifies the generic vertex attribute whose address is being specified.
specifies the GPU address from which arrays will be sourced, and addresses beyond and including (
+ ) will return undefined values. If the address range of an enabled vertex attrib does not belong to a buffer object that is resident at the time of the Draw, undefined results, possibly including program termination, may occur. It is not possible to mix vertex or attrib arrays sourced from GPU addresses with either vertex or attrib arrays in client memory or specified with classic VBO bindings. Add to Section 2.9.2 (p. 47) While ELEMENT_ARRAY_UNIFIED_NV is enabled, DrawElements, DrawElementsRange, MultiDrawElements, and DrawElementsInstanced source their indices from the address specified by the command BufferAddressRange where is ELEMENT_ARRAY_ADDRESS_NV and is zero, added to the parameter. If a Draw command sources indices beyond and including (
+ ), the index values will be undefined. If the element array address range does not belong to a buffer object that is resident at the time of the Draw, undefined results, possibly including program termination, may occur. Modify the language of NV_shader_buffer_load, replacing "made (in)accessible to the GL via shader buffer loads" with "made (in)accessible to the GL via shader buffer loads or via vertex attrib and/or element array reads". Additions to Chapter 5 of the OpenGL 3.0 Specification (Special Functions) Add to Section 5.4, p. 310 (Display Lists) Add to the list of excluded Vertex Array commands: BufferAddressRangeNV, and all VertexFormat* entry points added by this extension. Additions to Chapter 6 of the OpenGL 3.0 Specification (State and State Requests) Add to Section 6.1.11, p. 314 (Pointer, String, and 64-bit Queries) Indexed 64-bit state variables are queried with the command: void GetIntegerui64i_vNV(enum value, uint index, uint64EXT *data); Legal values of are only those that specify GetIntegerui64i_vNV in the state tables in Chapter 6. Additions to the AGL/EGL/GLX/WGL Specifications None. Errors The error INVALID_VALUE is generated by BufferAddressRange if is negative. The error INVALID_VALUE is generated by BufferAddressRange if is VERTEX_ATTRIB_ARRAY_ADDRESS_NV and is greater than the supported number of numbered vertex attribs, or if is TEXTURE_COORD_ARRAY_ADDRESS_NV and is greater than MAX_TEXTURE_COORDS. New State Update Table 6.9, p. 347 (Vertex Array Object State) Get Value Type Get Command Initial Value Sec Attribute --------- ---- ----------- ------------- --- --------- VERTEX_ATTRIB_ARRAY_UNIFIED_NV B IsEnabled FALSE 2.9 none ELEMENT_ARRAY_UNIFIED_NV B IsEnabled FALSE 2.9 none VERTEX_ATTRIB_ARRAY_ADDRESS_NV 16*Z64+ GetIntegerui64i_vNV 0 2.9 none VERTEX_ATTRIB_ARRAY_LENGTH_NV 16*Z64+ GetIntegeri_v 0 2.9 none VERTEX_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none VERTEX_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none NORMAL_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none NORMAL_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none COLOR_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none COLOR_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none INDEX_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none INDEX_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none TEXTURE_COORD_ARRAY_ADDRESS_NV 8*Z64+ GetIntegerui64i_vNV 0 2.9 none TEXTURE_COORD_ARRAY_LENGTH_NV 8*Z64+ GetIntegeri_v 0 2.9 none EDGE_FLAG_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none EDGE_FLAG_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none SECONDARY_COLOR_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none SECONDARY_COLOR_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none FOG_COORD_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none FOG_COORD_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none ELEMENT_ARRAY_ADDRESS_NV Z64+ GetIntegerui64vNV 0 2.9 none ELEMENT_ARRAY_LENGTH_NV Z64+ GetIntegerv 0 2.9 none Interactions with OpenGL 3.2 If the context version is greater or equal version 3.2, querying all *_LENGTH_NV values can be done via GetInteger64v as well as GetInteger64i_v. Dependencies on NV_shader_buffer_load: This extension relies on the mechanisms to get addresses and make buffers resident that NV_shader_buffer_load provides, but does not rely on either the LOAD instruction or the changes to the Shading Language. Dependencies on ARB_compatibility If the context version is greater than 3.0 and does not include ARB_compatibility functionality, then EnableClientState and DisableClientState have been deprecated and removed. This extension adds back those commands, but only requires that they accept the VERTEX_ATTRIB_ARRAY_UNIFIED_NV and ELEMENT_ARRAY_UNIFIED_NV tokens. Examples Creating several interleaved vertex buffers of the same format and switching between them efficiently. GenBuffers(N, vbos); // initialize buffers GLuint64EXT gpuAddrs[N]; for (i = 0; i < N; ++i) { BindBuffer(target, vbos[i]); BufferData(target, vboSizes[i], vboData[i], STATIC_DRAW); // get the address of this buffer and make it resident. GetBufferParameterui64vNV(target, BUFFER_GPU_ADDRESS_NV, &gpuAddrs[i]); MakeBufferResidentNV(target, READ_ONLY); } // setup format - 4-ubyte color, 4-float position EnableClientState(COLOR_ARRAY); EnableClientState(VERTEX_ARRAY); ColorFormatNV(4, UNSIGNED_BYTE, 20); VertexFormatNV(4, FLOAT, 20); // enable vertex address use EnableClientState(VERTEX_ATTRIB_ARRAY_UNIFIED_NV); for (i = 0; i < N; ++i) { // point at buffer i BufferAddressRangeNV(COLOR_ARRAY_ADDRESS_NV, 0, gpuAddrs[i], vboSizes[i]); BufferAddressRangeNV(VERTEX_ARRAY_ADDRESS_NV, 0, gpuAddrs[i]+4, vboSizes[i]-4); DrawArrays(POINTS, 0, vboSizes[i]/20); } Issues 1) Should any of the new commands be compiled into display lists? RESOLVED: NO. It should be straightforward to allow any of the vertex format commands or BufferAddressRangeNV to be compiled, but as long as DrawElements/DrawArrays are not compiled it's not clear that it's useful. It's easier to relax the restriction later than to add a new restriction later if deemed necessary, so they are not compiled. 2) What should be client state and what should be server state? RESOLVED: The new enables should be client state as the client needs to know them to determine whether to read from client vertex arrays. For all the other new state, it's not clear that there's any reason to make them client state. Vertex and attrib array formats remain client state. 3) What about other buffer object uses (PBO, XFB, etc)? RESOLVED: Deferred to separate extensions, if deemed necessary. 4) How should the use of GPU addresses be enabled and how should it interact with classic VBO and client vertex arrays? RESOLVED: A single enable for all vertex attribs (both named and generic), and an enable for element array. This precludes mixing with classic VBO and client vertex arrays, which is not particularly desirable in the first place. Requiring implementations to mix with classic VBO may re-introduce a significant amount of the CPU overhead that this extension is intended to remove. These enables are not problematic for middleware because the enables are per-VAO and middleware libraries can/should use their own VAOs if they need to avoid polluting the application's state. 5) Should ArrayElement be supported? RESOLVED: YES. ArrayElement updates the current vertex state in the context which is not naturally a "GPU" operation, so this may be inefficient, but we should support it anyway. 6) Should there be a separate BindBufferAddressNV and BindBufferAddressIndexedNV? RESOLVED: NO. There's no particularly strong argument in either direction. 7) What happens if an invalid address is fetched? UNRESOLVED: If
and correctly specify a range of a resident buffer object, then the implementation *might* support replacing reads from beyond
+ with undefined results. However, a genuinely invalid address may cause system errors including program termination. A "debug context" could potentially check on each draw call whether all the address ranges are within a resident buffer object. 8) Should this be limited to generic vertex attribs? RESOLVED: NO. Named attribs are deprecated, and it would make the spec and implementation shorter. But the interactions are clean and easy to specify, and many legacy apps use the named attribs. The answer may have to change to "yes" if this extension is ever promoted. 9) Should the parameter to DrawElements and friends be used? RESOLVED: YES. This is required for MultiDrawElements to be useful and hence to provide an easy porting path for existing applications. This is unfortunately inconsistent with ignoring the vertex attrib pointer state, but the vertex attrib pointers are "latched" state and is "immediate" state so they're already semantically different. 10) Are there alignment requirements on vertex attrib and element array addresses? RESOLVED: No more so than with existing VBO functionality. The spec has the following vague language about using VBOs: "Clients must align data elements consistent with the requirements of the client platform, with an additional base-level requirement that an offset within a buffer to a datum comprising N basic machine units be a multiple of N." However, the consequences of ignoring this advice aren't specified. Since this extension still uses buffer objects, presumably it should inherit the same restrictions. However, if we split out the Format API from the Address API, then it becomes impossible to do an error check to enforce this. But, our implementation has never had such an error check in the first place... Follow the quoted advice from the core spec, and this extension adds no new error checks to enforce it. The GL should ensure that the base address of a buffer is at least 16-byte aligned (see issue 16 of NV_shader_buffer_load). 11) Does MAX_SHADER_BUFFER_ADDRESS_NV imply any restriction on vertex attrib or element array addresses? RESOLVED: No, it is only a restriction on shader loads. The entire address space is available for vertex/element fetches. 12) How does the new vertex state interact with EXT_direct_state_access's ClientAttribDefaultEXT? RESOLVED: All the new state is reset to the initial values. Revision History Rev. Date Author Changes ---- -------- -------- ----------------------------------------- 1 jbolz Internal revisions. 2 06/30/09 jbolz Defined interaction with deprecated client state commands. 3 09/09/09 mjk Assigned number + fixed typos 4 07/08/15 ckubisch 64-bit Gets for *_LENGTH_NV, interaction with 3.2