Name NV_primitive_restart Name Strings GL_NV_primitive_restart Contact Matt Craighead, NVIDIA Corporation (mcraighead 'at' nvidia.com) Notice Copyright NVIDIA Corporation, 2002. IP Status NVIDIA Proprietary. Status Implemented in CineFX (NV30) Emulation driver, August 2002. Shipping in Release 40 NVIDIA driver for CineFX hardware, January 2003. Version NVIDIA Date: August 29, 2002 (version 0.1) Number 285 Dependencies Written based on the wording of the OpenGL 1.3 specification. Overview This extension allows applications to easily and inexpensively restart a primitive in its middle. A "primitive restart" is simply the same as an End command, followed by another Begin command with the same mode as the original. The typical expected use of this feature is to draw a mesh with many triangle strips, though primitive restarts are legal for all primitive types, even for points (where they are not useful). Although the EXT_multi_draw_arrays extension did reduce the overhead of such drawing techniques, they still remain more expensive than one would like. This extension provides an extremely lightweight primitive restart, which is accomplished by allowing the application to choose a special index number that signals that a primitive restart should occur, rather than a vertex being provoked. This index can be an arbitrary 32-bit integer for maximum application convenience. In addition, for full orthogonality, a special OpenGL command is provided to restart primitives when in immediate mode. This command is not likely to increase performance in any significant fashion, but providing it greatly simplifies the specification and implementation of display list compilation and indirect rendering. Issues * What should the default primitive restart index be? RESOLVED: Zero. It's tough to pick another number that is meaningful for all three element data types. In practice, apps are likely to set it to 0xFFFF or 0xFFFFFFFF. * Are primitives other than triangle strips supported? RESOLVED: Yes. One example of how this can be useful is for rendering a heightfield. The "standard" way to render a heightfield uses a number of triangle strips, one for each row of the grid. Another method, which can produce higher-quality meshes, is to render a number of 8-triangle triangle fans. This has the effect of alternating the direction of tessellation, as shown in the diagram below. Primitive restarts enhance the performance of both techniques. ------------------------- ------------------------- | /| /| /| /| /| /| /| /| |\ | /|\ | /|\ | /|\ | /| |/ |/ |/ |/ |/ |/ |/ |/ | | \|/ | \|/ | \|/ | \|/ | ------------------------- ---*-----*-----*-----*--- | /| /| /| /| /| /| /| /| | /|\ | /|\ | /|\ | /|\ | |/ |/ |/ |/ |/ |/ |/ |/ | |/ | \|/ | \|/ | \|/ | \| ------------------------- ------------------------- Two strips Four fans (centers marked '*') * How is this feature turned on and off? RESOLVED: Via a glEnable/DisableClientState setting. It is not possible to select a restart index that is guaranteed to be unused. * Is the immediate mode PrimitiveRestartNV needed? RESOLVED: Yes. It is difficult to make indirect rendering to work without it, and it is near impossible to make display lists work without it. It is a very clean way to resolve these issues. * How is indirect rendering handled? RESOLVED: Because of PrimitiveRestartNV, it works very easily. PrimitiveRestartNV has a wire protocol and therefore it can easily be inserted as needed. The server tracks the current Begin mode, relieving the client of this burden. Note that in practice, we expect that this feature is essentially useless for indirect rendering. * How does this extension interact with NV_element_array and NV_vertex_array_range? RESOLVED: It doesn't, not even for performance. It should be fast on hardware that supports the feature with or without the use of element arrays, with or without vertex array range. XXXmjc Is it feasible to guarantee fast performance even in the non-VAR, non-CVA, non-DRE case??? Possibly not. * Does this extension affect ArrayElement and DrawArrays, or just DrawElements? RESOLVED: All of them. It applies to ArrayElement and to the rest as a consequence. It is likely not useful with any other than DrawElements, but nevertheless not prohibited. * In the case of ArrayElement, what happens if the restart index is used outside Begin/End? RESOLVED: Since this is defined as being equivalent to a call to PrimitiveRestartNV, and PrimitiveRestartNV is an INVALID_OPERATION when not inside Begin/End, this is just an error. * For DrawRangeElements/LockArrays purposes, must the restart index lie within the start/end range? RESOLVED: No, this would to some extent defeat the point if the restart index was, e.g., 0xFFFFFFFF. I don't believe any spec language is required here, since hitting this index does not cause a vertex to be dereferenced. * Should this state push/pop? RESOLVED: Yes, as vertex array client state. New Procedures and Functions void PrimitiveRestartNV(void); void PrimitiveRestartIndexNV(uint index); New Tokens Accepted by the parameter of EnableClientState and DisableClientState, by the parameter of IsEnabled, and by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: PRIMITIVE_RESTART_NV 0x8558 Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: PRIMITIVE_RESTART_INDEX_NV 0x8559 Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation) Add a section 2.6.X "Primitive Restarts", immediately after section 2.6.2 "Polygon Edges" (page 19): "2.6.X Primitive Restarts An OpenGL primitive may be restarted with the command void PrimitiveRestartNV(void) Between the execution of a Begin and its corresponding End, this command is equivalent to a call to End, followed by a call to Begin where the mode argument is the same mode as that used by the previous Begin. Outside the execution of a Begin and its corresponding End, this command generates the error INVALID_OPERATION." Add PrimitiveRestartNV to the list of commands that are allowed between Begin and End in section 2.6.3 "GL Commands within Begin/End" (page 19). Add to section 2.8 "Vertex Arrays", after the description of ArrayElement (page 24): "Primitive restarting is enabled or disabled by calling EnableClientState or DisableClientState with parameter PRIMITIVE_RESTART_NV. The command void PrimitiveRestartIndexNV(uint index) specifies the index of a vertex array element that is treated specially when primitive restarting is enabled. When ArrayElement is called between an execution of Begin and the corresponding execution of End, if i is equal to PRIMITIVE_RESTART_INDEX_NV, then no vertex data is derefererenced, and no current vertex state is modified. Instead, it is as if PrimitiveRestartNV had been called." Replace the last paragraph of section 2.8 "Vertex Arrays" (page 28) with the following: "If the number of supported texture units (the value of MAX_TEXTURE_UNITS) is k, then the client state required to implement vertex arrays consists of 7+k boolean values, 5+k memory pointers, 5+k integer stride values, 4+k symbolic constants representing array types, 3+k integers representing values per element, and an unsigned integer representing the restart index. In the initial state, the boolean values are each disabled, the memory pointers are each null, the strides are each zero, the array types are each FLOAT, the integers representing values per element are each four, and the restart index is zero." Additions to Chapter 3 of the OpenGL 1.3 Specification (Rasterization) None. Additions to Chapter 4 of the OpenGL 1.3 Specification (Per-Fragment Operations and the Frame Buffer) None. Additions to Chapter 5 of the OpenGL 1.3 Specification (Special Functions) Add to the end of Section 5.4 "Display Lists": "PrimitiveRestartIndexNV is not compiled into display lists, but is executed immediately." Additions to Chapter 6 of the OpenGL 1.3 Specification (State and State Requests) None. GLX Protocol The following rendering commands are sent to the server as part of glXRender requests: PrimitiveRestartNV 2 4 rendering command length 2 364 rendering command opcode PrimitiveRestartIndexNV 2 8 rendering command length 2 365 rendering command opcode 4 CARD32 index Errors The error INVALID_OPERATION is generated if PrimitiveRestartNV is called outside the execution of Begin and the corresponding execution of End. The error INVALID_OPERATION is generated if PrimitiveRestartIndexNV is called between the execution of Begin and the corresponding execution of End. New State Initial Get Value Get Command Type Value Sec Attrib --------- ----------- ---- ------- ---- ------------ PRIMITIVE_RESTART_NV IsEnabled B FALSE 2.8 vertex-array PRIMITIVE_RESTART_INDEX_NV GetIntegerv Z+ 0 2.8 vertex-array Revision History none yet