blob: f30d2ee518e99fe99ad31b8c384b9d5a158ce367 [file] [log] [blame]
Name
NV_transform_feedback
Name Strings
GL_NV_transform_feedback
Contributors
Cliff Woolley
Nick Carter
Contact
Barthold Lichtenbelt (blichtenbelt 'at' nvidia.com)
Pat Brown (pbrown 'at' nvidia.com)
Eric Werness (ewerness 'at' nvidia.com)
Status
Shipping for GeForce 8 Series (November 2006)
Version
Last Modified Date: 03/09/2011
NVIDIA Revision: 18
Number
341
Dependencies
OpenGL 1.5 is required.
This extension interacts with EXT_timer_query.
NV_vertex_program4, NV_geometry_program4 and NV_gpu_program4 affect this
extension.
EXT_geometry_shader4 trivially interacts with this extension.
This extension has an OpenGL Shading Language component. As such it
interacts with ARB_shader_objects and OpenGL 2.0.
This extension is written against the OpenGL 2.0 specification.
Overview
This extension provides a new mode to the GL, called transform feedback,
which records vertex attributes of the primitives processed by the GL.
The selected attributes are written into buffer objects, and can be
written with each attribute in a separate buffer object or with all
attributes interleaved into a single buffer object. If a geometry program
or shader is active, the primitives recorded are those emitted by the
geometry program. Otherwise, transform feedback captures primitives whose
vertex are transformed by a vertex program or shader, or by fixed-function
vertex processing. In either case, the primitives captured are those
generated prior to clipping. Transform feedback mode is capable of
capturing transformed vertex data generated by fixed-function vertex
processing, outputs from assembly vertex or geometry programs, or varying
variables emitted from GLSL vertex or geometry shaders.
The vertex data recorded in transform feedback mode is stored into buffer
objects as an array of vertex attributes. The regular representation and
the use of buffer objects allows the recorded data to be processed
directly by the GL without requiring CPU intervention to copy data. In
particular, transform feedback data can be used for vertex arrays (via
vertex buffer objects), as the source for pixel data (via pixel buffer
objects), as program constant data (via the NV_parameter_buffer_object or
EXT_bindable_uniform extension), or via any other extension that makes use
of buffer objects.
This extension introduces new query object support to allow transform
feedback mode to operate asynchronously. Query objects allow applications
to determine when transform feedback results are complete, as well as the
number of primitives processed and written back to buffer objects while in
transform feedback mode. This extension also provides a new rasterizer
discard enable, which allows applications to use transform feedback to
capture vertex attributes without rendering anything.
New Procedures and Functions
void BindBufferRangeNV(enum target, uint index, uint buffer,
intptr offset, sizeiptr size)
void BindBufferOffsetNV(enum target, uint index, uint buffer,
intptr offset)
void BindBufferBaseNV(enum target, uint index, uint buffer)
void TransformFeedbackAttribsNV(sizei count, const int *attribs,
enum bufferMode)
void TransformFeedbackVaryingsNV(uint program, sizei count,
const int *locations,
enum bufferMode)
void BeginTransformFeedbackNV(enum primitiveMode)
void EndTransformFeedbackNV()
int GetVaryingLocationNV(uint program, const char *name)
void GetActiveVaryingNV(uint program, uint index,
sizei bufSize, sizei *length, sizei *size,
enum *type, char *name)
void ActiveVaryingNV(uint program, const char *name)
void GetTransformFeedbackVaryingNV(uint program, uint index,
int *location)
void GetIntegerIndexedvEXT(enum param, uint index, int *values);
void GetBooleanIndexedvEXT(enum param, uint index, boolean *values);
(Note: These indexed query functions are provided in the EXT_draw_buffers2
extension. The boolean query is not useful for any queryable value in
this extension, but is supported for completeness and consistency with
base GL typed "Get" functions.)
New Tokens
Accepted by the <target> parameters of BindBuffer, BufferData,
BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData,
GetBufferPointerv, BindBufferRangeNV, BindBufferOffsetNV and
BindBufferBaseNV:
TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
Accepted by the <param> parameter of GetIntegerIndexedvEXT and
GetBooleanIndexedvEXT:
TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
Accepted by the <param> parameter of GetIntegerIndexedvEXT and
GetBooleanIndexedvEXT, and by the <pname> parameter of GetBooleanv,
GetDoublev, GetIntegerv, and GetFloatv:
TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
Accepted by the <bufferMode> parameter of TransformFeedbackAttribsNV and
TransformFeedbackVaryingsNV:
INTERLEAVED_ATTRIBS_NV 0x8C8C
SEPARATE_ATTRIBS_NV 0x8C8D
Accepted by the <target> parameter of BeginQuery, EndQuery, and
GetQueryiv:
PRIMITIVES_GENERATED_NV 0x8C87
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
Accepted by the <cap> parameter of Enable, Disable, and IsEnabled, and by
the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and
GetDoublev:
RASTERIZER_DISCARD_NV 0x8C89
Accepted by the <pname> parameter of GetBooleanv, GetDoublev, GetIntegerv,
and GetFloatv:
MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
Accepted by the <pname> parameter of GetProgramiv:
ACTIVE_VARYINGS_NV 0x8C81
ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
Accepted by the <pname> parameter of GetBooleanv, GetDoublev, GetIntegerv,
GetFloatv, and GetProgramiv:
TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
Accepted by the <attribs> parameter of TransformFeedbackAttribsNV:
BACK_PRIMARY_COLOR_NV 0x8C77
BACK_SECONDARY_COLOR_NV 0x8C78
TEXTURE_COORD_NV 0x8C79
CLIP_DISTANCE_NV 0x8C7A
VERTEX_ID_NV 0x8C7B
PRIMITIVE_ID_NV 0x8C7C
GENERIC_ATTRIB_NV 0x8C7D
POINT_SIZE 0x0B11
FOG_COORDINATE 0x8451
SECONDARY_COLOR_NV 0x852D
PRIMARY_COLOR 0x8577
POSITION 0x1203
LAYER_NV 0x8DAA
(note: POINT_SIZE, FOG_COORDINATE, PRIMARY_COLOR, and POSITION are
defined in the core OpenGL specification; SECONDARY_COLOR_NV is defined
in NV_register_combiners.)
Returned by the <type> parameter of GetActiveVaryingNV:
UNSIGNED_INT_VEC2_EXT 0x8DC6
UNSIGNED_INT_VEC3_EXT 0x8DC7
UNSIGNED_INT_VEC4_EXT 0x8DC8
(note: All three of these are defined in the EXT_gpu_shader4
extension.)
Additions to Chapter 2 of the OpenGL 2.0 Specification (OpenGL
Operation)
Insert three new sections between Sections 2.11, Coordinate Transforms and
2.12, Clipping:
(Move the "Asynchronous Queries" language out of Section 4.1.7)
Section 2.X, Asynchronous Queries
Asynchronous queries provide a mechanism to return information about the
processing of a sequence of GL commands. There are two query types
supported by the GL. Transform feedback queries (section 2.Y) returns
information on the number of vertices and primitives processed by the GL
and written to one or more buffer objects. Occlusion queries (section
4.1.7.1) count the number of fragments or samples that pass the depth
test.
The results of asynchronous queries are not returned by the GL immediately
after the completion of the last command in the set; subsequent commands
can be processed while the query results are not complete. When
available, the query results are stored in an associated query object.
The commands described in section 6.1.12 provide mechanisms to determine
when query results are available and return the actual results of the
query. The name space for query objects is the unsigned integers, with
zero reserved by the GL.
Each type of query supported by the GL has an active query object name. If
the active query object name for a query type is non-zero, the GL is
currently tracking the information corresponding to that query type and
the query results will be written into the corresponding query object. If
the active query object for a query type name is zero, no such information
is being tracked.
A query object is created by calling
void BeginQuery(enum target, uint id);
with an unused name <id>. <target> indicates the type of query to be
performed; valid values of <target> are defined in subsequent
sections. When a query object is created, the name <id> is marked as used
and associated with a new query object.
BeginQuery sets the active query object name for the query type given by
<target> to <id>. If BeginQuery is called with an <id> of zero, if the
active query object name for <target> is non-zero, or if <id> is the
active query object name for any query type, the error INVALID OPERATION
is generated.
The command
void EndQuery(enum target);
marks the end of the sequence of commands to be tracked for the query type
given by <target>. The active query object for <target> is updated to
indicate that query results are not available, and the active query object
name for <target> is reset to zero. When the commands issued prior to
EndQuery have completed and a final query result is available, the query
object, active when EndQuery is, called is updated by the GL. The query
object is updated to indicate that the query results are available and to
contain the query result. If the active query object name for <target> is
zero when EndQuery is called, the error INVALID_OPERATION is generated.
The command
void GenQueries(sizei n, uint *ids);
returns <n> previously unused query object names in <ids>. These names are
marked as used, but no object is associated with them until the first time
they are used by BeginQuery.
Query objects are deleted by calling
void DeleteQueries(sizei n, const uint *ids);
<ids> contains <n> names of query objects to be deleted. After a query
object is deleted, its name is again unused. Unused names in <ids> are
silently ignored.
Calling either GenQueries or DeleteQueries while any query of any target
is active causes an INVALID_OPERATION error to be generated.
Query objects contain two pieces of state: a single bit indicating
whether a query result is available, and an integer containing the query
result value. The number of bits used to represent the query result is
implementation-dependent. In the initial state of a query object, the
result is available and its value is zero.
The necessary state for each query type is an unsigned integer holding the
active query object name (zero if no query object is active), and any
state necessary to keep the current results of an asynchronous query in
progress.
Section 2.Y, Transform Feedback
In 'transform feedback' mode the vertices of transformed primitives are
written out to one or more buffer objects. The vertices are fed back after
the geometry shader stage, if it exists, or otherwise after vertex
processing right before clipping (section 2.12) but after color
clamping. Optionally the transformed vertices can be discarded after being
stored into one or more buffer objects, or they can be passed on down to
the clipping stage for further processing.
Transform feedback is started and finished by calling
void BeginTransformFeedbackNV(enum primitiveMode)
and
void EndTransformFeedbackNV(),
respectively. Transform feedback is said to be active after a call to
BeginTransformFeedbackNV and inactive after a call to
EndTransformFeedbackNV. Transform feedback is initially inactive.
Transform feedback is performed after color clamping, but immediately
before clipping in the OpenGL pipeline. <primitiveMode> is one of
TRIANGLES, LINES, or POINTS, and specifies the output type of primitives
that will be recorded into the buffer objects bound for transform feedback
(see below). <primitiveMode> places a restriction on the primitive types
that may be rendered during an instance of transform feedback. See table
X.1.
Transform Feedback
primitiveMode allowed render primitive modes
---------------------- ---------------------------------
POINTS POINTS
LINES LINES, LINE_LOOP, and LINE_STRIP
TRIANGLES TRIANGLES, TRIANGLE_STRIP,
TRIANGLE_FAN, QUADS, QUAD_STRIP,
and POLYGON
Table X.1 Legal combinations between the transform feedback primitive
mode, as passed to BeginTransformFeedbackNV and the current primitive
mode.
If a geometry program or geometry shader is active, the output primitive
type of the currently active program is used as the render primitive in
table X.1, otherwise the Begin mode is used.
Quads and polygons will be tessellated and recorded as triangles (the
order of tessellation within a primitive is undefined); primitives
specified in strips or fans will be assembled and recorded as individual
primitives. Incomplete primitives are not recorded. Begin or any operation
that implicitly calls Begin (such as DrawElements) will generate
INVALID_OPERATION if the begin mode is not an allowed begin mode for the
current transform feedback buffer state. If a geometry program or geometry
shader is active, its output primitive mode is used for the error check
instead of the begin mode.
It is an invalid operation error to call BeginTransformFeedbackNV,
TransformFeedbackVaryingsNV, TransformFeedbackAttribsNV, or UseProgram or
LinkProgram on the currently active program object while transform
feedback is active. It is an invalid operation error to call
EndTransformFeedbackNV while transform feedback is inactive.
Transform feedback can operate in either INTERLEAVED_ATTRIBS_NV or
SEPARATE_ATTRIBS_NV mode. In the INTERLEAVED_ATTRIBS_NV mode, several
vertex attributes can be written, interleaved, into a single buffer
object. In the SEPARATE_ATTRIBS_NV mode, vertex attributes are recorded,
non-interleaved, into several buffer objects simultaneously.
It is an INVALID_OPERATION error to call BeginTransformFeedbackNV if there
is no buffer object bound to index 0 (see the description of the
BindBuffer* commands below) in INTERLEAVED_ATTRIBS_NV mode. It is also an
INVALID_OPERATION error to call BeginTransformFeedbackNV if the number of
buffer objects bound in SEPARATE_ATTRIBS_NV mode is less than the number
of buffer objects required, as given by the current transform feedback
state. It is also an INVALID_OPERATION error to call
BeginTransformFeedbackNV if no attributes are specified to be captured in
either separate or interleaved mode.
Buffer objects are made to be targets of transform feedback by calling one
of
void BindBufferRangeNV(enum target, uint index, uint buffer,
intptr offset, sizeiptr size)
void BindBufferOffsetNV(enum target, uint index, uint buffer,
intptr offset)
void BindBufferBaseNV(enum target, uint index, uint buffer)
where <target> is set to TRANSFORM_FEEDBACK_BUFFER_NV. Any of the three
BindBuffer* commands perform the equivalent of BindBuffer(target,
buffer). <buffer> specifies which buffer object to bind to the target at
index number <index>. <index> exists for use with the SEPARATE_ATTRIBS_NV
mode and must be less than the value of
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV. <offset> specifies a starting
offset into the buffer object <buffer>. <size> specifies the number of
elements that can be written during transform feedback mode. This is
useful to prevent the GL from writing past a certain position in the
buffer object. Both <offset> and <size> are in basic machine units. The
error INVALID_VALUE is generated if the value of <size> is less than or
equal to zero. The error INVALID_VALUE is generated if <offset> or <size>
are not word-aligned. The error INVALID_OPERATION is generated when any of
the BindBuffer* commands is called while transform feedback is active.
BindBufferBaseNV is equivalent to calling BindBufferOffsetNV with an
<offset> of 0. BindBufferOffsetNV is the equivalent of calling
BindBufferRangeNV with <size> = sizeof(buffer) - <offset> and rounding
<size> down so that it is word-aligned.
If recording the vertices of a primitive to the buffer objects being used
for transform feedback purposes would result in either exceeding the
limits of any buffer object's size, or in exceeding the end position
<offset> + <size> - 1, as set by BindBufferRangeNV, then no vertices of
the primitive are recorded, and the counter corresponding to the
asynchronous query target TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV (see
Section 2.Z) is not incremented.
Two methods exist to specify which transformed vertex attributes are
streamed to one, or more, buffer objects in transform feedback mode. If
an OpenGL Shading Language vertex and/or geometry shader is active, then
the state set with the TransformFeedbackVaryingsNV() command determines
which attributes to record. If neither a vertex nor geometry shader is
active, the state set with the TransformFeedbackAttribsNV() command
determines which attributes to record.
When a program object containing a vertex shader and/or geometry shader is
active, the set of vertex attributes recorded in transform feedback mode
is specified by
void TransformFeedbackVaryingsNV(uint program, sizei count,
const int *locations,
enum bufferMode)
This command sets the transform feedback state for <program> and specifies
which varying variables to record when transform feedback is active. The
array <locations> contains <count> locations of active varying variables,
as queried with GetActiveVaryingNV(), to stream to a buffer object. See
section 2.15.3. <bufferMode> is one of INTERLEAVED_ATTRIBS_NV or
SEPARATE_ATTRIBS_NV. The error INVALID_OPERATION is generated if any
value in <locations> does not reference an active varying variable, or if
any value in <locations> appears more than once in the array. The same
error is generated if <program> has not been linked successfully. The
program object's state value TRANSFORM_FEEDBACK_BUFFER_MODE_NV will be set
to <bufferMode> and the program object's state value
TRANSFORM_FEEDBACK_VARYINGS_NV set to <count>. These values can be queried
with GetProgramiv (see section 6.1.14).
In the INTERLEAVED_ATTRIBS_NV mode, varying variables are written,
interleaved, into one buffer object. This is the buffer object bound to
index 0. Varying variables are written out to that buffer object in the
order that they appear in the array <locations>. The error
INVALID_OPERATION is generated if the total number of components of all
varying variables specified in the array <locations> is greater than
MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV.
In the SEPARATE_ATTRIBS_NV mode, varying variables are recorded,
non-interleaved, into several buffer objects simultaneously. The first
varying variable in the array <locations> is written to the buffer bound
to index 0. The last varying variable is written to the buffer object
bound to index <count> - 1. No more than
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV buffer objects can be written
to simultaneously. The error INVALID_VALUE is generated if <count> is
greater than that limit. Furthermore, the number of components for each
varying variable in the array <locations> cannot exceed
MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV. The error INVALID_VALUE is
generated if any varying variable in <locations> exceeds this limit.
It is not necessary to (re-)link <program> after calling
TransformFeedbackVaryingsNV(). Changes to the transform feedback state
will be picked up right away after calling TransformFeedbackVaryingsNV().
The value for any attribute specified to be streamed to a buffer object
but not actually written by a vertex or geometry shader is undefined.
When neither a vertex nor geometry shader is active, the vertex attributes
produced by fixed-function vertex processing or an assembly vertex or
geometry program can be recorded in transform feedback mode. The set of
attributes to record is specified by
void TransformFeedbackAttribsNV(sizei count, const int *attribs,
enum bufferMode)
This command specifies which attributes to record into one, or more,
buffer objects. The value TRANSFORM_FEEDBACK_BUFFER_MODE_NV will be set
to <bufferMode> and the value TRANSFORM_FEEDBACK_ATTRIBS_NV set to
<count>. The array <attribs> contains an interleaved representation of
the attributes desired to be fed back containing 3*count values. For
attrib i, the value at 3*i+0 is the enum corresponding to the attrib, as
given in table X.2. The value at 3*i+1 is the number of components of the
provided attrib to be fed back and is between 1 and 4. The value at 3*i+2
is the index for attribute enumerants corresponding to more than one real
attribute. For an attribute enumerant corresponding to only one attribute,
the index is ignored. For an attribute enumerant corresponding to more
than one attribute, the error INVALID_VALUE is generated if the index
value is outside the allowable range for that attribute.
permitted GPU_program_4
attrib sizes index? result name
--------------------- -------- -------- --------------
POSITION 1,2,3,4 no position
PRIMARY_COLOR 1,2,3,4 no color.front.primary
SECONDARY_COLOR_NV 1,2,3,4 no color.front.secondary
BACK_PRIMARY_COLOR_NV 1,2,3,4 no color.back.primary
BACK_SECONDARY_COLOR_NV 1,2,3,4 no color.back.secondary
FOG_COORDINATE 1 no fogcoord
POINT_SIZE 1 no pointsize
TEXTURE_COORD_NV 1,2,3,4 yes texcoord[index]
CLIP_DISTANCE_NV 1 yes clip[index]
VERTEX_ID_NV 1 no vertexid
PRIMITIVE_ID_NV 1 no primid
GENERIC_ATTRIB_NV 1,2,3,4 yes attrib[index]
LAYER_NV 1 no layer
Table X.2: Transform Feedback Attribute Specifiers.The 'attrib' column
specifies which attribute to record. The 'permitted sizes' column
indicates how many components of the attribute can be recorded. The
'index' column indicates if the attribute is indexed. The 'gpu program 4'
column shows which result variable of a vertex or geometry program
corresponds to the attribute to record.
The TransformFeedbackAttribsNV() command sets transform feedback state
which is used both when the GL is in fixed-function vertex processing
mode, as well as when an assembly vertex and/or geometry program is
active.
The parameter <bufferMode> has the same meaning as described for
TransformFeedbackVaryingsNV(). Attributes are either written interleaved,
or into separate buffer objects, in the same manner as described earlier
for TransformFeedbackVaryingsNV().
In the INTERLEAVED_ATTRIBS_NV mode, the error INVALID_VALUE is generated
if the sum of the values of elements 3*i+1 in the array <attribs> is
greater than MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV.
In the SEPARATE_ATTRIBS_NV mode, no more than
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV buffer objects can be written
to simultaneously. The error INVALID_VALUE is generated if <count> is
greater than that limit.
The error INVALID_OPERATION is generated if any attribute appears more
than once in the array <attribs>.
The value for any attribute specified to be streamed to a buffer object
but not actually written by a vertex or geometry program is undefined.
The values of PRIMITIVE_ID_NV or LAYER_NV for a vertex is defined if and
only if a geometry program is active and that program writes to the result
variables "result.primid" or "result.layer", respectively. The value of
VERTEX_ID_NV is only defined if and only if a vertex program is active, no
geometry program is active, and the vertex program writes to the output
attribute "result.id".
Section 2.Z, Primitive Queries
Primitive queries use query objects to track the number of primitives
generated by the GL and to track the number of primitives written to
transform feedback buffers.
When BeginQuery is called with a <target> of PRIMITIVES_GENERATED_NV, the
primitives-generated count maintained by the GL is set to zero. When the
generated primitive query is active, the primitives-generated count is
incremented every time a primitive reaches the Discarding Rasterization
stage (see Section 3.x) right before rasterization. This counter counts
the number of primitives emitted by a geometry shader, if active, possibly
further tessellated into separate primitives during the transform-feedback
stage, if active.
When BeginQuery is called with a <target> of
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV, the transform-feedback-
primitives-written count maintained by the GL is set to zero. When the
transform feedback primitive written query is active, the
transform-feedback-primitives-written count is incremented every time a
primitive is recorded into a buffer object. If transform feedback is not
active, this counter is not incremented. If the primitive does not fit in
the buffer object, the counter is not incremented.
These two queries can be used together to determine if all primitives have
been written to the bound feedback buffers; if both queries are run
simultaneously and the query results are equal, all primitives have been
written to the buffer(s). If the number of primitives written is less than
the number of primitives generated, the buffer is full.
Modify section 2.15.3 "Shader Variables", page 75.
Change the second sentence in the first paragraph on p. 84 as follows:
. . . or read by a fragment shader, will count against this limit. The
transformed vertex position (gl_Position) does not count against this
limit.
Add the following paragraphs on p.84:
A varying variable is considered active if it is determined by the linker
that the varying will actually be used when the executable code in a
program object is executed. The linker will make this determination
regardless of the transform-feedback state set with the
TransformFeedbackVaryingsNV() command. In cases where the linker cannot
make a conclusive determination, the varying will be considered active. It
is possible to override this determination and force the linker to
consider a varying variable as active by calling ActiveVaryingNV(). This
can be useful in transform feedback mode if there are varying variables to
be recorded but not otherwise needed.
To find the location of an active varying variable, call
int GetVaryingLocationNV(uint program, const char *name)
This command will return the location of varying variable <name>. <name>
is a null-terminated string without whitespace. If <name> is not the name
of an active varying variable in <program>, -1 is returned. Locations for
both user-defined as well as built-in varying variables can be queried. If
<program> has not been successfully linked, the error INVALID_OPERATION is
generated. After a program is linked, the location will not change, unless
the program is re- linked. A valid name cannot be any portion of a single
vector or matrix, but can be a single element of an array or the whole
array. Note that varying variables cannot be structures.
To determine the set of active varying variables used by a program object,
and their data types, use the command:
void GetActiveVaryingNV(uint program, uint index,
sizei bufSize, sizei *length, sizei *size,
enum *type, char *name);
This command provides information about the varying selected by
<index>. An <index> of 0 selects the first active varying variable, and an
<index> of ACTIVE_VARYINGS_NV-1 selects the last active varying
variable. The value of ACTIVE_VARYINGS_NV can be queried with
GetProgramiv (see section 6.1.14). If <index> is greater than or equal to
ACTIVE_VARYINGS_NV, the error INVALID_VALUE is generated. The parameter
<program> is the name of a program object for which the command
LinkProgram has been issued in the past. It is not necessary for <program>
to have been linked successfully. The link could have failed because the
number of active varying variables exceeded the limit.
The name of the selected varying is returned as a null-terminated string
in <name>. The actual number of characters written into <name>, excluding
the null terminator, is returned in <length>. If <length> is NULL, no
length is returned. The maximum number of characters that may be written
into <name>, including the null terminator, is specified by <bufSize>. The
returned varying name can be the name of a user defined varying variable
or the name of a built- in varying (which begin with the prefix "gl_", see
the OpenGL Shading Language specification for a complete list). The length
of the longest varying name in program is given by
ACTIVE_VARYING_MAX_LENGTH_NV, which can be queried with GetProgramiv (see
section 6.1.14).
For the selected varying variable, its type is returned into <type>. The
size of the varying is returned into <size>. The value in <size> is in
units of the type returned in <type>. The type returned can be any of
FLOAT, FLOAT_VEC2, FLOAT_VEC3, FLOAT_VEC4, INT, INT_VEC2, INT_VEC3,
INT_VEC4, UNSIGNED_INT, UNSIGNED_INT_VEC2_EXT, UNSIGNED_INT_VEC3_EXT,
UNSIGNED_INT_VEC4_EXT, FLOAT_MAT2, FLOAT_MAT3, or FLOAT_MAT4. If an error
occurred, the return parameters <length>, <size>, <type> and <name> will
be unmodified. This command will return as much information about active
varying variables as possible. If no information is available, <length>
will be set to zero and <name> will be an empty string. This situation
could arise if GetActiveVaryingNV is issued after a failed link.
To force the linker to mark a varying variable as active, call
void ActiveVaryingNV(uint program, const char *name)
to specify that the varying variable <name> in <program> should be marked
as active when the program is next linked. In particular, it does not
modify the list of active varying variables in a program object that has
already been linked. For any varying variable in <program> not passed to
ActiveVaryingNV, the linker will determine their active status. <name>
must be a null-terminated string without whitespace. A valid name cannot
be an element of an array, or any portion of a single vector or
matrix. ActiveVaryingNV may be issued before any shader objects are
attached to <program>. Hence, <name> can contain any string, including a
name that is never used as a varying variable in any shader object. Such
names are ignored by the GL.
The application is advised to force any varying variable live that it
needs for transform feedback purposes. The set of active varying variables
are linker dependent.
Additions to Chapter 3 of the OpenGL 2.0 Specification (Rasterization)
(Add new section 3.X, Discarding Rasterization)
Primitives can be optionally discarded before rasterization by calling
Enable and Disable with RASTERIZER_DISCARD_NV. When enabled, primitives
are discarded right before the rasterization stage, but after the optional
transform feedback stage. When disabled, primitives are passed through to
the rasterization stage to be processed normally. RASTERIZER_DISCARD_NV
applies to the DrawPixels, CopyPixels, Bitmap, Clear and Accum commands as
well.
Additions to Chapter 4 of the OpenGL 2.0 Specification (Per-Fragment
Operations and the Frame Buffer)
(Replace section 4.1.7, "Occlusion Queries", p. 204, with the following)
Occlusion queries use query objects to track the number of fragments or
samples that pass the depth test. An occlusion query can be started and
finished by calling BeginQuery and EndQuery, respectively, with a <target>
of SAMPLES_PASSED.
When an occlusion query starts, the samples-passed count maintained by the
GL is set to zero. When an occlusion query is active, the samples-passed
count is incremented for each fragment that passes the depth test. If the
value of SAMPLE BUFFERS is 0, then the samples- passed count is
incremented by 1 for each fragment. If the value of SAMPLE BUFFERS is 1,
then the samples-passed count is incremented by the number of samples
whose coverage bit is set. However, implementations, at their discretion,
may instead increase the samples-passed count by the value of SAMPLES if
any sample in the fragment is covered. When an occlusion query finishes
and all fragments generated by the commands issued prior to EndQuery have
been generated, the samples-passed count is written to the corresponding
query object as the query result value, and the query result for that
object is marked as available.
If the samples-passed count overflows, (i.e., exceeds the value 2^n - 1,
where n is the number of bits in the samples-passed count), its value
becomes undefined. It is recommended, but not required, that
implementations handle this overflow case by saturating at 2^n - 1 and
incrementing no further.
Additions to Chapter 5 of the OpenGL 2.0 Specification (Special Functions)
(Add to section 5.4, Display Lists p. 237)
On p. 241, add the following to the list of vertex buffer object commands
not compiled into a display list: BindBufferRangeNV, BindBufferOffsetNV,
BindBufferBaseNV, TransformFeedbackAttribsNV,
TransformFeedbackVaryingsNV, and ActiveVaryingNV.
Additions to Chapter 6 of the OpenGL 2.0 Specification (State and State
Requests)
Modify the second paragraph of section 6.1.1 (Simple Queries) p244 to read
as follows:
...<data> is a pointer to a scalar or array of the indicated type in which
to place the returned data. The commands
void GetIntegerIndexedvEXT(enum param, uint index, int *values);
void GetBooleanIndexedvEXT(enum param, uint index, boolean *values);
are used to query indexed state. <target> is the name of the indexed
state and <index> is the index of the particular element being queried.
<data> is a pointer to a scalar or array of the indicated type in which to
place the returned data. In addition ...
(Replace Section 6.1.12, Occlusion Queries, p. 254)
Section 6.1.12, Asynchronous Queries
The command
boolean IsQuery(uint id);
returns TRUE if <id> is the name of a query object. If <id> is zero, or if
<id> is a non-zero value that is not the name of a query object, IsQuery
returns FALSE.
Information about a query target can be queried with the command
void GetQueryiv(enum target, enum pname, int *params);
<target> identifies the query target and can be SAMPLES_PASSED for
occlusion queries or PRIMITIVES_GENERATED_NV and
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV for primitive queries.
If <pname> is CURRENT_QUERY, the name of the currently active query for
<target>, or zero if no query is active, will be placed in <params>.
If <pname> is QUERY_COUNTER_BITS, the implementation-dependent number of
bits used to hold the query result for <target> will be placed in
params. The number of query counter bits may be zero, in which case the
counter contains no useful information.
For primitive queries (PRIMITIVES_GENERATED_NV and
TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV) if the number of bits is
non-zero, the minimum number of bits allowed is 32.
For occlusion queries (SAMPLES_PASSED), if the number of bits is non-
zero, the minimum number of bits allowed is a function of the
implementation's maximum viewport dimensions (MAX_VIEWPORT_DIMS). The
counter must be able to represent at least two overdraws for every pixel
in the viewport. The formula to compute the allowable minimum value (where
n is the minimum number of bits) is:
n = min(32, ceil(log_2(maxViewportWidth *
maxViewportHeight * 2))).
The state of a query object can be queried with the commands
void GetQueryObjectiv(uint id, enum pname, int *params);
void GetQueryObjectuiv(uint id, enum pname, uint *params);
If <id> is not the name of a query object, or if the query object named by
<id> is currently active, then an INVALID_OPERATION error is generated.
If <pname> is QUERY_RESULT, then the query object's result value is
returned as a single integer in <params>. If the value is so large in
magnitude that it cannot be represented with the requested type, then the
nearest value representable using the requested type is returned. If the
number of query counter bits for any <target> is zero, then the result is
returned as a single integer with a value of 0.
There may be an indeterminate delay before the above query returns. If
<pname> is QUERY_RESULT_AVAILABLE, FALSE is returned if such a delay would
be required, TRUE is returned otherwise. It must always be true that if
any query object returns a result available of TRUE, all queries of the
same type issued prior to that query must also return TRUE.
Querying the state for any given query object forces the corresponding
query to complete within a finite amount of time.
If multiple queries are issued using the same object name prior to calling
GetQueryObject[u]iv, the result and availability information returned will
always be from the last query issued. The results from any queries before
the last one will be lost if they are not retrieved before starting a new
query on the same <target> and <id>.
(Add to Section 6.1.13, Buffer Objects, p. 255)
Add the following paragraph to the bottom of this section, p. 256.
To query which buffer objects are the target(s) when transform feedback is
active, call GetIntegerIndexedvEXT() with <param> set to
TRANSFORM_FEEDBACK_BUFFER_BINDING_NV. <index> has to be in the range 0 to
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV - 1, otherwise the error
INVALID_VALUE is generated. The name of the buffer object bound to <index>
is returned in <values>. If no buffer object is bound for <index>, zero is
returned in <values>.
To query the starting offset or size of the range of each buffer object
binding used for transform feedback, call GetIntegerIndexedvEXT() with
<param> set to TRANSFORM_FEEDBACK_BUFFER_START_NV or
TRANSFORM_FEEDBACK_BUFFER_SIZE_NV respectively. The error INVALID_VALUE
is generated if <index> not in the range 0 to
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV - 1. If the parameter
(starting offset or size) was not specified when the buffer object was
bound, or if no buffer object is bound to <index>, zero is returned.
(Add a new Section 6.1.14 "Transform Feedback " and rename 6.1.14 to
6.1.15)
To query the attributes to stream to a buffer object when neither an
OpenGL Shading Language vertex nor geometry shader is active, call
GetIntegerIndexedvEXT() with <param> set to
TRANSFORM_FEEDBACK_RECORD_NV. This will return three values in <values>
for each <index>. The first value returned is the attribute. The second
value the number of components of the attribute, and the third value the
index of the attribute, if applicable. If the attribute is not indexed,
the third component will return 0. The parameter <index> has to be in the
range 0 to TRANSFORM_FEEDBACK_ATTRIBS_NV - 1, otherwise the error
INVALID_VALUE is generated. If no data exists for <index> 0 is returned
three times in <values>.
To query the attributes to stream to a buffer object when a vertex and/or
geometry shader is active, use the command
GetTransformFeedbackVaryingNV(), as explained in section 6.1.14.
(add to Section 6.1.14, Shader and Program Queries, p. 256)
Add the following paragraph to the bottom of page 257:
If <pname> is TRANSFORM_FEEDBACK_BUFFER_MODE_NV, the buffer mode,
used when transform feedback is active, is returned. It can be one of
SEPARATE_ATTRIBS_NV or INTERLEAVED_ATTRIBS_NV. If <pname> is
TRANSFORM_FEEDBACK_VARINGS_NV, the number of varying variables to stream
to one, or more, buffer objects are returned. If <pname> is
ACTIVE_VARYINGS_NV, the number of active varying variables is
returned. If no active varyings exist, 0 is returned. If <pname> is
ACTIVE_VARYINGS_MAX_LENGTH_NV, the length of the longest active varying
name, including a null terminator, is returned. If no active varying
variable exists, 0 is returned.
The command
void GetTransformFeedbackVaryingNV(uint program, uint index,
int *location)
returns, for each <index>, the location of a varying variable to stream to
a buffer object in <location>. The <index> element of the array
<locations>, as passed to TransformFeedbackVaryingsNV, is
returned. <index> has to be in the program object specific range 0 to
TRANSFORM_FEEDBACK_VARYINGS_NV - 1, otherwise the error INVALID_VALUE is
generated. If no location exists for <index>, -1 is returned. If <program>
is not the name of a program object, or if program object has not been
linked successfully, the error INVALID_OPERATION is generated.
Additions to Appendix A of the OpenGL 2.0 Specification (Invariance)
None.
Additions to the AGL/GLX/WGL Specifications
None.
GLX Protocol
UNDER DEVELOPMENT
Interactions with EXT_timer_query
EXT_timer_query is the first extension to generalize the BeginQuery and
EndQuery mechanism introduced by ARB_occlusion_query and OpenGL 1.5 to
cover an additional query type. This extension is the second. This
extension is written against the OpenGL 2.0 specification and uses most of
the modifications in the EXT_timer_query specification. If
EXT_timer_query is supported, timer queries need to be added as a third
query type.
Dependencies on NV_geometry_program4 and EXT_geometry_shader4
If NV_geometry_program4 is not supported, delete the reference to the
output primitive type in Section 2.Y. Delete the reference to
PRIMITIVE_ID_NV and LAYER_NV.
If EXT_geometry_shader4 is not supported, delete any reference to a
geometry shader.
Dependencies on NV_vertex_program4 and NV_gpu_program4
If NV_vertex_program4 is not supported, delete any reference to
VERTEX_ID_NV. If NV_gpu_program4 is not supported, table X.2 needs to
refer to the "result" variables defined in the ARB_vertex_program
specification instead.
Interactions with ARB_shader_objects and OpenGL 2.0
If neither ARB_shader_objects nor OpenGL 2.0 is supported, all references
to shader and program objects, as well as varying variables, should be
removed. This also means that functions including
TransformFeedbackVaryingsNV, GetVaryingLocationNV, GetActiveVaryingNV,
ActiveVaryingNV, and GetTransformFeedbackVaryingNV will not be
supported, and enums that are relevant only in the context of shader and
program objects will not be accepted.
Errors
The error INVALID_OPERATION is generated by BeginQuery if called with an
<id> of zero, if the active query object name for <target> is non- zero,
or if <id> is the active query object name for any query type.
The error INVALID_OPERATION is generated by EndQuery if the active query
object name for <target> is zero.
The error INVALID_OPERATION is generated if Begin, or any command that
performs an explicit Begin, is called when:
* A geometry program or shader is not active AND the begin mode does not
match the allowed begin modes for the current transform feedback state
as given by table X.1.
* A geometry program or shader is active AND the output primitive type
(of the geometry program / shader) does not match the allowed begin
modes for the current transform feedback state as given by table X.1.
The error INVALID_OPERATION is generated by BeginTransformFeedbackNV if
there is no buffer object bound to index 0 in INTERLEAVED_ATTRIBS_NV
mode.
The error INVALID_OPERATION is generated by BeginTransformFeedbackNV if
the number of buffer objects bound in SEPARATE_ATTRIBS_NV mode is less
than the number of buffer objects required, as given by the current
transform feedback state.
The error INVALID_OPERATION is generated by BeginTransformFeedbackNV if
no attributes are specified to be captured.
The error INVALID_OPERATION is generated by BeginTransformFeedbackNV,
TransformFeedbackVaryingsNV, TransformFeedbackAttribsNV, or UseProgram or
LinkProgram, called on the currently in use program object, while
transform feedback is active.
The error INVALID_OPERATION is generated by EndTransformFeedbackNV while
transform feedback is inactive.
The error INVALID_OPERATION is generated by BindBufferRangeNV,
BindBufferOffsetNV or BindBufferBaseNV if <target> is
TRANSFORM_FEEDBACK_BUFFER_NV and <index> is greater or equal
than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV.
The error INVALID_VALUE is generated by BindBufferRangeNV if the value of
<size> <= 0.
The error INVALID_VALUE is generated by BindBufferRangeNV or
BindBufferOffsetNV if <start> or <end> are not word-aligned.
The error INVALID_OPERATION is generated when any of the BindBuffer*
commands is called while transform feedback is active.
The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV
commands if any location appears more than once in the array <locations.
The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV
if any location in <locations> references a non-existing varying variable.
The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV
if <program> has not been linked successfully.
The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV
in INTERLEAVED_ATTRIBS_NV mode if the total number of components of all
varying variables specified in the array <locations> is greater than
MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV.
The error INVALID_VALUE is generated by TransformFeedbackVaryingsNV or
TransformFeedbackAttribsNV in SEPARATE_ATTRIBS_NV mode if <count> is
greater than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV.
The error INVALID_VALUE is generated by TransformFeedbackVaryingsNV in
SEPARATE_ATTRIBS_NV mode if the number of components for each varying
variable in the array <locations> is greater than
MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV.
The error INVALID_VALUE is generated by TransformFeedbackAttribsNV in
INTERLEAVED_ATTRIBS_NV mode if the sum of the values of the components of
the attributes in the array <attribs> is greater than
MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV.
The error INVALID_OPERATION is generated by TransformFeedbackAttribsNV if
an enum value is specified more than once in the array <attribs>.
The error INVALID_OPERATION is generated by TransformFeedbackAttribsNV if
the number of components for each attribute in the array <attribs> is
outside the range [0,4].
The error INVALID_VALUE is generated by TransformFeedbackAttribsNV if the
index value is in the array <attribs> is outside the allowable range for
an attribute enumerant corresponding to more than one real attribute.
The error INVALID_OPERATION is generated by GetVaryingLocationNV if
<program> is not the name of a program object or if <program> has not been
linked successfully.
The error INVALID_OPERATION is generated by GetActiveVaryingNV or
ActiveVaryingNV if <program> is not the name of a program object.
The error INVALID_VALUE is generated by GetActiveVaryingNV if <index> is
greater than or equal to ACTIVE_VARYINGS_NV.
The error INVALID_VALUE is generated by GetIntegerIndexedvEXT() or
GetBooleanIndexedv() with <param> set to TRANSFORM_FEEDBACK_RECORD_NV if
<index> is greater than or equal to TRANSFORM_FEEDBACK_ATTRIBS_NV.
The error INVALID_VALUE is generated by GetIntegerIndexedvEXT() or
GetBooleanIndexedvEXT() with <param> set to
TRANSFORM_FEEDBACK_BUFFER_BINDING_NV if <index> is greater than or equal
to MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV.
The error INVALID_VALUE is generated by GetTransformFeedbackVaryingsNV if
<index> is greater than the program object specific value
TRANSFORM_FEEDBACK_VARYINGS_NV - 1.
The error INVALID_OPERATION is generated by
GetTransformFeedbackVaryingsNV if <program> is not the name of a program
object, or if program object has not been linked successfully.
New State
(Add a new table: Table 6.X, Transform Feedback State)
Get Value Type Get Command Init. Value Description Sec Attrib
------------------ ------ -------------- ------------ ------------------------- ----- ------
TRANSFORM_FEEDBACK_ Z2 GetIntegerv INTERLEAVED_ Transform feedback mode 2.Y -
BUFFER_MODE_NV ATTRIBS_NV
TRANSFORM_FEEDBACK_ Z2 GetIntegerv 0 Number of attributes to 2.Y -
ATTRIBS_NV capture in transform
feedback mode
TRANSFORM_FEEDBACK_ Z+ GetIntegerv 0 Buffer object bound to 6.1.13 -
BUFFER_BINDING_NV generic bind point for
transform feedback.
TRANSFORM_FEEDBACK_ nx3*Z+ GetInteger- 0 Name, component count, 6.1.14 -
RECORD_NV IndexedvEXT and index of each
attribute captured
TRANSFORM_FEEDBACK_ nxZ+ GetInteger- 0 Buffer object bound to 6.1.13 -
BUFFER_BINDING_NV IndexedvEXT each transform feedback
attribute stream.
TRANSFORM_FEEDBACK_ nxZ+ GetInteger- 0 Start offset of binding 6.1.13 -
BUFFER_START_NV IndexedvEXT range for each transform
feedback attrib. stream
TRANSFORM_FEEDBACK_ nxZ+ GetInteger- 0 Size of binding range 6.1.13 -
BUFFER_SIZE_NV IndexedvEXT for each transform
feedback attrib. stream
(Modify Table 6.37, p 298, updating the query object state to cover
transform feedback.)
Get Value Type Get Command Init. Value Description Sec Attribute
---------------- ---- ---------------- ----------- ------------------------- ----- ---------
CURRENT_QUERY 3xZ+ GetQueryiv 0 Active query object name 2.X -
(occlusion, timer, xform
feedback)
QUERY_RESULT 3xZ+ GetQueryObjectiv 0 Query object result 2.X -
(samples passed, Time
elapsed, feedback data amount)
QUERY_RESULT_AVAILABLE 3xZ+ GetQueryObjectiv TRUE Query object result 2.X -
available?
(Modify Table 6.29, p. 290, Program Object State. Add the following state.)
Get Value Type Get Command Init. Value Description Sec Attribute
---------------- ---- ------------ ----------- ------------------------- ----- ---------
ACTIVE_VARYINGS_NV Z+ GetProgramiv 0 Number of active varyings 2.15.3 -
ACTIVE_VARYING_MAX_ Z+ GetProgramiv 0 Maximum active varying 2.15.3 -
LENGTH_NV name length
TRANSFORM_FEEDBACK_ Z2 GetProgramiv INTERLEAVED_ Transform feedback mode 6.1.14 -
BUFFER_MODE_NV ATTRIBS_NV for the program
TRANSFORM_FEEDBACK_ Z+ GetProgramiv 0 Number of varyings to 6.1.14 -
VARYINGS_NV stream to buffer object(s)
- nxZ+ GetVarying- - Location of each active 2.15.3 -
LocationNV varying variable
- Z+ GetActive- - Size of each active 2.15.3 -
VaryingNV varying variable
- Z+ GetActive- - Type of each active 2.15.3 -
VaryingNV varying variable
- 0+x- GetActive- - Name of each active 2.15.3 -
char VaryingNV varying variable
- Z+ GetTransform- - Varying location for one 6.1.14 -
Feedback- of the multiple varyings
VaryingNV to capture
New Implementation Dependent State
(Modify Table 6.34, p. 295. Update the query object state to cover
transform feedback.)
Get Value Type Get Command Minimum Value Description Sec Attribute
-------------------- ---- ----------- ------------- -------------------------- ------ ---------
QUERY_COUNTER_BITS 2xZ+ GetQueryiv see 6.1.12 Asynchronous query counter 6.1.12 -
bits (occlusion, timer,
transform feedback queries)
(Add a new table, Table 6.X. Transform Feedback State.)
NOTE: In the "GetValue" columns below, MXFB stands for
"MAX_TRANSFORM_FEEDBACK".
Get Value Type Get Command Minimum Value Description Sec Attribute
-------------------- ---- ----------- ------------- -------------------------- ------ ---------
MXFB_INTERLEAVED_ Z+ GetIntegerv 64 Max number of components to 2.Y -
COMPONENTS_NV write to a single buffer in
interleaved mode
MXFB_SEPARATE_ Z+ GetIntegerv 4 Max number of separate 2.Y -
ATTRIBS_NV attributes or varyings that
can be captured in transform
feedback
MXFB_SEPARATE Z+ GetIntegerv 4 Max number of components 2.Y -
COMPONENTS_NV per attribute or varying
in separate mode
Issues
1. How does transform feedback differ from core GL feedback?
* Transform feedback writes vertex data to buffer objects, which allows
the data returned to be used directly by vertex pulling. GL feedback
mode writes vertex data to a buffer in system memory.
* Transform feedback is done after transformation, but prior to
clipping. The primitives returned contain the original transformed
vertices produced by vertex or geometry program execution, and does
not contain any primitives inserted by clipping.
* Transform feedback supports only a single basic output primitive type
(points, lines, or triangles), while core GL feedback mode supports
all primitive types. Since only one primitive type is supported, the
data returned does not contain tokens describing each primitive being
fed back. Primitive tokens make the data returned by GL feedback mode
irregular and unsuitable for vertex pulling.
2. What should this extension be called?
RESOLVED: The current name is "NV_transform_feedback", playing off the
fact that it is transformed primitives that are handled and the
similarities to GL feedback mode.
3. What happens if you bind a buffer for transform feedback that is
currently bound for other purposes? Should we somehow detect this case
and produce an error?
!!! NBC I feel strongly that we should follow the precedent for
Map/Unmap. The reason that MapBuffer and UnmapBuffer are a precedent
here is because while a buffer object is in the mapped state, no GL
commands are allowed to operate on the buffer object's data. So by
analogy, while a buffer is being used for transform feedback, no other
GL commands should be allowed to operate on the buffer object's data.
This includes initiating any rendering which would cause the GL to
source data from an active transform feedback buffer object.
UNRESOLVED
4. Should this extension include any new buffer object binding targets, or
should it overload ARRAY_BUFFER, or should we skip the binding target
altogether in favor of a buffer object name accepted directly by the
new GL commands?
RESOLVED: There are new binding points for XFB along with a new API
(BindBufferBase etc) to set the internal binding points. A new binding
point, TRANSFORM_FEEDBACK_BUFFER_NV is also introduced.
5. Previous buffer object extensions provided a way to have existing GL
commands reference a buffer object instead of a user-supplied buffer.
Should the new commands introduced here allow referencing a
user-supplied buffer in addition to a buffer object?
RESOLVED: No. A program can get the contents of the feedback buffer back
to the CPU using MapBuffer and GetBufferSubData
6. Is BeginTransformFeedback really necessary? Could the query just
initiate the transform feedback mode?
RESOLUTION: Using BeginTransformFeedback and EndTransformFeedback gives
a clean place to spec all of the transform-feedback-specific issues
without cluttering up the query language. Also, the queries don't have
to be done at the same time as beginning and ending the feedback
process.
7. What usage enums should be provided to glBufferData for use in
conjunction with transform feedback?
RESOLVED: STREAM_COPY or STREAM_READ are expected to be the most common
usages. If a buffer object is being written by the GL through transform
feedback, and the contents of the buffer object are subsequently being
consumed by the GL (e.g. by being used as a vertex buffer object), then
this is a *_COPY usage. If the buffer object is being written by the GL
through transform feedback, but is being consumed by the application
(e.g. being mapped for read), this is a *_READ usage. The temporal
(STREAM, STATIC, or DYNAMIC) component of the usage enum is determined
by the ratio between how often the contents of the buffer object are
modified and how often operations that source data from the buffer
object occur.
8. What should the behavior be when a buffer object is the active target
of transform feedback, and it is deleted via DeleteBuffers?
RESOLVED: Deletion is deferred until the EndTransformFeedback if
transform feedback is active.
9. Should we allow more buffers to be bound than are used?
RESOLVED: Yes. The extra buffers are not in the way and can stay bound.
10. Should we allow feedback to buffer lists with holes (i.e. 0 and 2
bound)?
RESOLVED: No. This makes for an ugly API with the potential for bugs,
without any real benefit. The application can as well bind all buffers
needed to incremented indices. It is an invalid operation to not have a
buffer bound where one is required.
11. Why only one feedback primitive mode per feedback invocation?
RESOLVED: Having primitive tokens breaks up the stream and makes it less
amenable to being read back in as a vertex buffer. Also, mixing multiple
primitive types makes the counting of primitives less clear for the
application.
12. Is RasterPos fed back?
RESOLVED: No.
13. Is DrawPixels/CopyPixels/Bitmap fed back?
RESOLVED: No. Rasterization occurs as normal, but there is no
output to the feedback buffer. This is consistent with taking a
tap out of the pipe before clipping.
14. Why do we need new BindBuffer* functions?
RESOLVED: All previous buffer object extensions have been retrofits of
existing pointer-based APIs. New extensions built assuming buffer
objects don't have that history, so need a new API. The functionality of
these new functions combines the functionality of BindBuffer, to set the
external bind point used by calls like MapBuffer and BufferSubData, with
the functionality to set an internal bind point like VertexAttribPointer
does.
15. How do the transform feedback indices, passed to the BindBuffer*
commands, work with multiple bindings?
RESOLVED: The same way that they work with vertex arrays. There is one
external bind point, TRANSFORM_FEEDBACK_BUFFER_NV. There are n internal
bind points, selected with the <index> parameter to the BindBuffer*
commands, where n is some implementation dependent limit. The
BindBuffer* commands take the buffer passed and bind it to the external
bind point, as well as to the selected internal bind point.
For example:
BindBufferOffsetNV(TRANSFORM_FEEDBACK_BUFFER_NV, 0, 1, 12);
// XFB index 0 points at buffer 1 with offset 12
BindBuffer(TRANSFORM_FEEDBACK_BUFFER_NV, 2);
// Buffer 2 is now bound to the external bind point. XFB index 0 still
// points at buffer 1
MapBuffer(TRANSFORM_FEEDBACK_BUFFER_NV, ...);
// Maps buffer 2
16. How are quads/quadstrips/polygons tessellated into triangles?
RESOLVED: In an implementation-dependent manner. OpenGL doesn't define
quads or polygons in terms of triangles, so there is no one correct way
to do it, and different GPUs may implement the behavior differently. A
quad may be split into two triangles in several different ways, and an
application may not rely on this behavior.
17. How does this extension interact with display lists?
RESOLVED: Just like the VBO extension, none of the BindBuffer* commands
are compiled into a display list.
18. Does polygon mode state affect the logic that determines if the
transform feed back primitive mode and the render mode states are
valid at the start of transform feedback mode?
RESOLVED: PolygonMode has no influence on the BeginTransFormFeedback
primitiveMode check since it is performed later, in raster.
19. What to do with incomplete primitives?
RESOLVED: If there is no room to store one or more vertices of a
primitive in a buffer object, none of the vertices in that primitive are
written to the buffer. If a partial primitive enters transform feedback
(i.e. only two vertices sent in triangles mode), none of the vertices in
that primitive are written to the buffer object.
20. Why does TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV have a
TRANSFORM_FEEDBACK prefix but PRIMITIVES_GENERATED_NV doesn't?
RESOLVED: The number of primitives generated is independent of any
feedback that is active. The number of primitives that are written is
only valid for transform feedback - another extension could conceivably
have a different way of writing out primitives that would require a
similar but distinct token.
21. When a GLSL vertex shader is active, what happens in transform
feedback mode if non-active varying variables are specified?
DISCUSSION: Active varying variables are varying variables, declared in
the shader, that the linker determined are actually needed. As an
optimization, the linker can discard the ones declared, but not
needed. If non-active varying variables need to be fed into a buffer
object, the linker should not perform this optimization.
There are three suggested resolutions to this problem:
1. The set of varying variables that need to be streamed to a buffer
object in transform feedback mode are set as a property of the
program object, and are taken into account during the link step.
This means that changing the set means the application will have to
re-link the program object in order to have the change take effect.
2. The set of varying variables that need to be streamed to a buffer
object in transform feedback mode are specified after the program
object has been linked. This is the most flexible option from the
applications perspective, but this might mean that a) specifying
this set could force the GL to re-link 'under the covers', and b)
could mean that the GL runs out of varying variable slots because
the combined total of the set of active varyings and the varyings
to stream in transform feedback mode is too large.
3. This solution is a hybrid of the above two approaches. The set of
potential varying variables that need to be streamed to a buffer
object are set as a property of the program object. These varying
variables are marked as active by the application and therefore
cannot be eliminated during the link step. However, a sub-set of
varying variables to actually stream to a buffer object can be
changed without the application having to re-link the program
object. This approach gives the application flexibility to change
the set of varying variables to stream, while it eliminates the
need for the GL to compile 'under the covers'.
RESOLUTION: Option 3 offers a good compromise, and therefore we'll go
with that.
22. Given option 3 in the previous resolution, how to specify that a
varying variable has to be considered active by the linker?
DISCUSSION: There are two approaches to the application specifying which
varying variables are active. We can either provide a simple flag that
specifies that all varying variables are considered active, or we can
provide a more complex mechanism where the application can specify an
individual varying variable as being active.
RESOLUTION: RESOLVED. The 'all or nothing' flag is a simple idea, but
has a drawback when used with a 'uber-shader' that implements many paths
to achieve an effect, but only one path is used during any run of the
shader. In this case, a lot more varying variables might be flagged as
active then really is necessary, running the risk of running out of
resources. Therefore, we'll provide a mechanism for the application to
specify on a per varying variable basis if it is active.
23. Given the discussion in the previous issues, should a
GetActiveVarying() command be added, modeled after the existing
getActiveUniform() command?
DISCUSSION: Such a command will return the list of active uniforms,
after the program object has been linked. As per issue 22's resolution,
the complete set of varying variables that could be streamed to a buffer
object needs to be specified before the program object is linked.
It can be useful to an application to stream out a subset of the active
varying variables or to find out the whole set of active varyings,
especially since the set can be implementation dependent.
RESOLUTION: YES.
24. What is proper use of the command ActiveVaryingNV()?
RESOLVED: The application is well advised to force any varying variable
live that it needs for transform feedback purposes. The set of active
varying variables are linker dependent. For example, if a program object
has no fragment shader, then the LinkProgram command cannot typically
determine which built-in varying variables, output by a geometry or
vertex shader, are active. This is because the fragment processing state
can change, and therefore such a determination cannot be made until a
render command is issued. Furthermore, any user-defined varyings are
likely to be marked as non-active if there is no fragment shader because
they are guaranteed to have no effect on fixed-function fragment
processing. If there is both a vertex (or geometry) and fragment shader
in a program object, the application can probably deduce what will be an
active varying variable, or not. But beware of any (static) flow-control
that the linker can use to do cross vertex- fragment optimization to
cull any varying variables.
25. Are primitives sent down the pipeline after transform feedback, or
discarded?
RESOLVED: Primitives can be optionally discarded before rasterization by
calling Enable and Disable with RASTERIZER_DISCARD_NV. When enabled,
primitives are discarded after vertex attributes are recorded into the
buffer objects bound to transform feedback. When disabled, primitives
are passed through to the rasterization stage to be clipped and
rasterized normally. All rasterization operations are discarded, not
just those that are fed back into the buffer.
This applies to DrawPixels, CopyPixels, Bitmap, Clear, Accum as well.
26. If a varying is declared as an array, is the whole array streamed out?
RESOLVED: No, the application has to specify which elements of an array
it wants to stream out. Implementations might not be able to stream out
a large number of components to a single buffer object. If that is the
case, the application can stream each element of an array to a different
buffer object in TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS mode.
27. Is it possible to capture attributes when using the fixed-function
pipeline?
RESOLVED: Yes, there is nothing that precludes this. The application is
responsible for sending down the needed vertex attributes and setting
the GL state, as desired, for the attributes it wants to stream to a
buffer object. Note that VERTEX_ID_NV is not defined in fixed-function.
28. Is it possible to record hardware-generated primitive ID values that
would be available to a pixel shader?
RESOLVED: Transform feedback can only record the primitive ID values
emitted per-vertex by a geometry shader or program. While each
primitive recorded for transform-feedback has a well-defined primitive
ID, transform feedback is only capable of recording the attributes of
individual vertices.
29. Does transform feedback support the ability to capture per-vertex
layer outputs, as provided by EXT_geometry_shader4 and
NV_geometry_program4?
RESOLVED: Yes. For GLSL shaders, it is sufficient to reference the
built-in varying "gl_Layer". For assembly geometry programs, the
original version of the spec did not provide an enum allowing you to
name "result.layer" in TransformFeedbackAttribsNV. This was an
oversight in the original spec, which was fixed by version 14. An
updated driver will be required to take advantage of this capability;
NVIDIA drivers supporting this extension published prior to February
2008 will not be able to capture "result.layer". The value captured for
LAYER_NV will be undefined unless a geometry program that writes
"result.layer" is active.
Revision History
Rev. Date Author Changes
---- -------- -------- -----------------------------------------
18 03/09/11 mjk Minor typo fixes.
17 01/28/11 pbrown Change return value for start/size queries
when no buffer bound from -1 to zero, to
match state tables (Bug 7318), as done by
Jon Leech in related EXT/ARB extensions and
the core API specification.
16 08/17/08 pbrown Remove a non-existent function from the
set of functions that can generate invalid
operation errors while XFB is active.
15 02/20/08 pbrown Fix incorrect minimum for MAX_TRANSFORM_
FEEDBACK_SEPARATE_COMPONENTS_NV. Should be
4, not 16.
14 02/04/08 pbrown Fixed a problem with the spec where we were
unable to record "result.layer" using the
assembly interface. Added a new enum to
address.
13 11/28/07 pbrown Specified the captured primitive ID to be
undefined unless a geometry shader emits it
as a vertex output. XFB can only record
per-vertex data.
12 09/27/07 pbrown Removed incorrect error description from
the errors section -- buffer objects don't
need to be bound before calling Transform-
Feedback{Attribs,Varyings}NV, just before
BeginTransformFeedbackNV.
11 08/28/07 pbrown Added an error calling BeginTransformFeedback
if no attributes would be captured (i.e.,
attribute count is 0 for ASM or no attributes
specified in the active GLSL program).
10 02/09/07 pbrown Updated status section (now released).
9 10/23/06 pbrown Fixed prototype for GetIntegerIndexedEXT and
GetBooleanIndexedEXT: <index> is unsigned.
8 10/19/06 pbrown Removed stray addition of GetFloatIndexedvEXT
and GetDoubleIndexedvEXT. Minor wording
fixes.
7 10/17/06 pbrown Rename from EXT to NV while working on
standardizing a functional subset extension
that will be named EXT_transform_feedback. We
expect that the EXT should be equivalent to
the NV, except that it (a) removes support for
non-GLSL usage, (b) removes the ability to
change the set of varyings captured without
relinking. NVIDIA expects to support both the
NV and EXT forms of this extension going
forward. Fix state table formatting. Removed
GetFloatIndexedvEXT and GetDoubleIndexedvEXT,
which are not needed by this and related
extensions.
6 09/11/06 pbrown Fix bad prototype for GetActiveVaryingEXT
and bad references to "GetActiveVaryingsEXT".
Fix enum names for INTERLEAVED_ATTRIBS_EXT and
SEPARATE_ATTRIBS_EXT (no TRANSFORM_ FEEDBACK
prefix). Remove erroneous state table entries
that were obsoleted by the introduction of the
TRANSFORM_FEEDBACK_RECORD_EXT query.
5 08/31/06 pbrown Fix miscellaneous spec errata. Record enum
values that weren't documented in previous
spec versions. Use correct function names for
indexed "Get" functions. Clarify that GLSL
interactions mean that some functions and
enums defined here aren't supported if GLSL
isn't supported. Fixed the double-assignment
of several TransformFeedbackAttribsEXT enums
and re-packed that portion of the enum range.
Clarify that several new functions are
non-listable. Fix the query tokens for buffer
object range bindings to match the API
(start/size, not start/end).
4 08/30/06 pbrown Reformatting as a plaintext document
instead of an exported MS Word document.
3 07/26/06 barthold Forgot a few changes w.r.t. version 2.
2 07/14/06 barthold Change BindBufferRangeEXT to take an
offset and size parameter. Change
BindBufferOffsetEXT to take an offset
parameter.
1 barthold Internal spec development.