Vertex Rendering

From OpenGL.org
Revision as of 20:56, 1 September 2012 by Alfonse (Talk | contribs) (Possible rendering failure causes)

Jump to: navigation, search

Vertex Rendering is the process of taking vertex data specified in arrays and rendering one or more Primitives with this vertex data.

Prerequisites

Direct rendering

Transform feedback rendering

Transform feedback rendering
Core in version 4.5
Core since version 4.0
Core ARB extension ARB_transform_feedback2, ARB_transform_feedback3, ARB_transform_feedback_instanced

Transform Feedback objects can be used to render the results of a feedback operation. These are the effective equivalent of a glDrawArrays or glDrawArraysInstanced call, where appropriate.

The most important thing to note is that the only thing these functions do is issue the rendering call. They do not bind the transform feedback buffers. They do not modify any VAO state. The only thing pulled from the transform feedback object is the number of primitives that were rendered to that stream. It is your responsibility to set up the vertex arrays for actually rendering before making these calls.

The purpose of this feature is to avoid the GPU->CPU->GPU round-trip for the number of vertices written to a transform feedback stream. This is better even than using a Query Object, as any waiting will happen on the GPU rather than the CPU.

To perform non-instanced rendering from a transform feedback object, these functions are used:

void glDrawTransformFeedback(GLenum mode​, GLuint id​);
void glDrawTransformFeedbackStream(GLenum mode​, GLuint id​, GLuint stream​);

mode​ is the usual Primitive type. The id​ is the transform feedback object to draw from. The stream​ is the stream in the feedback object to get the vertex count from. Note that glDrawTransformFeedback is equivalent to calling glDrawTransformFeedbackStream with a stream​ of zero.

If GL 4.2 or ARB_transform_feedback_instanced is available, then the instanced version of these functions can be used:

void glDrawTransformFeedbackInstanced(GLenum mode​, GLuint id​, GLsizei instancecount​);
void glDrawTransformFeedbackStreamInstanced(GLenum mode​, GLuint id​, GLuint stream​, GLsizei instancecount​);

These function as glDrawArraysInstanced. There are no BaseInstance versions of these.

Indirect rendering

Indirect rendering
Core in version 4.5
Core since version 4.0
Core ARB extension ARB_draw_indirect, ARB_multi_draw_indirect, ARB_base_instance

Indirect rendering is the process of issuing a rendering command to OpenGL, except that most of the parameters to that command come from GPU storage provided by a Buffer Object. For example, glDrawArrays takes a primitive type, the number of vertices, and the starting vertex. When using the indirect rendering command glDrawArraysIndirect, the starting vertex and number of vertices to render would instead be stored in a buffer object.

The purpose of this is to allow GPU processes to fill these values in. This could be a compute shader, a specially designed geometry shader coupled with transform feedback, or an OpenCL/CUDA process. The idea is to avoid the GPU->CPU->GPU round-trip; the GPU decides what range of vertices to render with. All the CPU does is decide when to issue the rendering command, as well as which Primitive is used with that command.

The indirect rendering functions take their data from the buffer currently bound to the GL_DRAW_INDIRECT_BUFFER binding. Thus, any of these functions will fail if no buffer is bound to that binding.

All of the indirect rendering functions allow the following features:

  • Indexed rendering
    • Base vertex (for indexed rendering)
  • Instanced rendering
  • Base instance (if GL 4.2 or ARB_base_instance is available)

Thus, they act as the largest combination of features of the supported implementation.

For non-indexed rendering, the indirect equivalent to glDrawArraysInstancedBaseInstance is this:

void glDrawArraysIndirect(GLenum mode​, const void *indirect​);

The mode​ is the usual primitive type. indirect​ is the offset into the GL_DRAW_INDIRECT_BUFFER to find the beginning of the data.

The data is provided as if in a C struct of the following definition:

typedef  struct {
   GLuint  count;
   GLuint  instanceCount;
   GLuint  first;
   GLuint  baseInstance;
} DrawArraysIndirectCommand;

This represents a draw call equivalent to:

glDrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, cmd->instanceCount, cmd->baseInstance);
Note: if GL 4.2 or ARB_base_instance are not available, then the baseInstance​ field must be 0 or undefined behavior results.

If GL 4.3 or ARB_multi_draw_indirect are available, then multiple indirect array rendering commands can be issued in one call with this:

void glMultiDrawArraysIndirect(GLenum mode​, const void *indirect​, GLsizei drawcount​, GLsizei stride​);

The drawcount​ is the number of indirect rendering commands to issue; the stride​ is the byte offset from one rendering command to the next. It can be set to zero; if so, then the array of indirect commands is assumed to be tightly backed (ie: 16-byte stride). The stride​ must be a multiple of 4.

For indexed rendering, the indirect equivalent to glDrawElementsInstancedBaseVertexBaseInstance is this:

void glDrawElementsIndirect}(GLenum mode​, GLenum type​, const void *indirect​);

The mode​ and type​ parameters work as they do in regular glDrawElements-style functions. As with other indirect functions, the indirect​ is the byte-offset into the GL_DRAW_INDIRECT_BUFFER to find the indirect data structure.

In indexed rendering, the structure is defined as follows:

    typedef  struct {
        uint  count;
        uint  instanceCount;
        uint  firstIndex;
        uint  baseVertex;
        uint  baseInstance;
    } DrawElementsIndirectCommand;

This represents a draw call equivalent to:

glDrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count, type,
  cmd->firstIndex * size-of-type, cmd->instanceCount, cmd->baseVertex, cmd->baseInstance);

Where size-of-type​ is the size in bytes of type​.

Note: if GL 4.2 or ARB_base_instance are not available, then the baseInstance​ field must be 0 or undefined behavior results.

If GL 4.3 or ARB_multi_draw_indirect are available, then multiple indirect indexed rendering commands can be issued in one call with this:

 void glMultiDrawElementsIndirect(GLenum mode​, GLenum type​, const void *indirect​, GLsizei drawcount​, GLsizei stride​);

The drawcount​ is the number of indirect rendering commands to issue; the stride​ is the byte offset from one rendering command to the next. It can be set to zero; if so, then the array of indirect commands is assumed to be tightly backed (ie: 20-byte stride). The stride​ must be a multiple of 4.

Conditional rendering

Conditional Rendering
Core in version 3.0
Vendor extension NV_conditional_render

Conditional rendering is a mechanism for making the execution of one or more rendering commands conditional on the result of an Occlusion Query operation. This is done with the following functions:


glBeginConditionalRender(GLuint id​, GLenum mode​);
glEndConditionalRender();

All rendering commands issued within the boundaries of these two functions will only execute if the occlusion condition specified by id​ is tested to be true. For GL_SAMPLES_PASSED queries, it is considered true (and thus rendering commands are executed) if the number of samples is not zero.

The commands that can be conditioned are:

The mode​ parameter determines how the discarding of the rendering functions is performed. It can be one of the following:

  • GL_QUERY_WAIT​: OpenGL will wait until the query result is returned, then decide whether to execute the rendering command. This ensures that the rendering commands will only be executed if the query fails.
  • GL_QUERY_NO_WAIT​: OpenGL may execute the rendering commands anyway. It will not wait to see if the query test is true or not. This is used to prevent pipeline stalls if the time between the query test and the execution of the rendering commands is too short.
  • GL_QUERY_BY_REGION_WAIT: OpenGL will wait until the query result is returned, then decide whether to execute the rendering command. However, the rendered results will be clipped to the samples that were actually rasterized in the occlusion query. Thus, the rendered result can never appear outside of the occlusion query area.
  • GL_QUERY_BY_REGION_NO_WAIT: As above, except that it may not wait until the occlusion query is finished. The region clipping still holds.

Note that "wait" in this case does not mean that glEndConditionalRender itself will stall on the CPU. It means that the first command within the conditional rendering scope will not be executed by the GPU until the query has returned. So the CPU will continue processing, but the GPU itself may have a pipeline stall.

Possible rendering failure causes

The GL_INVALID_OPERATION error can happen when issuing rendering commands for many reasons, most of which have little to do with the actual rendering command itself. The following represent conditions that can cause this error when rendering commands are issued:

  • The current framebuffer is incomplete. The Default Framebuffer (if present) is always complete, so this usually happens with Framebuffer Objects.
  • The current program was not successfully linked, or the current program pipeline is not valid.
  • Textures used by the current programs' sampler and/or image objects are not complete.
  • The prim​ primitive type is incompatible with the primitive input that the
  • The prim​ is GL_PATCH, but no Tessellation Shader is active in the current program.

This list is not comprehensive. If you know of more, please add them here.

See Also

Reference