Name

    NV_conditional_render

Name Strings

    GL_NV_conditional_render

Contact

    Eric Werness, NVIDIA (ewerness 'at' nvidia.com)
    Pat Brown, NVIDIA (pbrown 'at' nvidia.com)

Contributors

    Daniel Koch, NVIDIA

Status

    Shipping.

Version

    Last Modified Date:         05/26/2014
    NVIDIA Revision:            6

Number

    OpenGL Extension #346
    OpenGL ES Extension #198

Dependencies

    The extension is written against the OpenGL 2.0 Specification.

    ARB_occlusion_query or OpenGL 1.5 is required in an OpenGL
    implementation.

    This extension interacts with NVX_conditional_render.

    This extension interacts with ARB_occlusion_query2.

    This extension interacts with ARB_ES3_compatibility.

    This extension interacts trivially with the OpenGL compatibility profile.

    This extension interacts with OpenGL 3.0, 3.2, 3.3, and 4.3

    EXT_occlusion_query_boolean or OpenGL ES 3.0 is required in an OpenGL ES
    implementation.

    This extension interacts with EXT_occlusion_query_boolean.

    This extension interacts with NV_occlusion_query_samples.

    This extension interacts with OpenGL ES 3.0.

Overview

    This extension provides support for conditional rendering based on the
    results of an occlusion query.  This mechanism allows an application to
    potentially reduce the latency between the completion of an occlusion
    query and the rendering commands depending on its result.  It additionally
    allows the decision of whether to render to be made without application
    intervention.

    This extension defines two new functions, BeginConditionalRenderNV and
    EndConditionalRenderNV, between which rendering commands may be discarded
    based on the results of an occlusion query.  If the specified occlusion
    query returns a non-zero value, rendering commands between these calls are
    executed.  If the occlusion query returns a value of zero, all rendering
    commands between the calls are discarded.

    If the occlusion query results are not available when
    BeginConditionalRenderNV is executed, the <mode> parameter specifies
    whether the GL should wait for the query to complete or should simply
    render the subsequent geometry unconditionally.

    Additionally, the extension provides a set of "by region" modes, allowing
    for implementations that divide rendering work by screen regions to
    perform the conditional query test on a region-by-region basis without
    checking the query results from other regions.  Such a mode is useful for
    cases like split-frame SLI, where a frame is divided between multiple
    GPUs, each of which has its own occlusion query hardware.


New Procedures and Functions

    void BeginConditionalRenderNV(uint id, enum mode);
    void EndConditionalRenderNV(void);


New Tokens

    Accepted by the <mode> parameter of BeginConditionalRenderNV:

        QUERY_WAIT_NV                                   0x8E13
        QUERY_NO_WAIT_NV                                0x8E14
        QUERY_BY_REGION_WAIT_NV                         0x8E15
        QUERY_BY_REGION_NO_WAIT_NV                      0x8E16


Additions to Chapter 2 of the OpenGL 2.0 Specification (OpenGL Operation)

    (Incorporate the spec edits from the EXT_transform_feedback specification
    that move the "Occlusion Queries" Section 4.1.7 -- to between Section 2.11,
    Coordinate Transforms and Section 2.12, Clipping, and rename it to
    "Asynchronous Queries".  Insert a new section immediately after the moved
    "Asynchronous Queries" section.  If EXT_transform_feedback is incorporated,
    this section should be inserted prior the the "Transform Feedback"
    section.)

    (also modify the BeginQuery language to disallow BeginQuery while the
     query object is being used for conditional rendering)
    ...
    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, if <id> is the active
    query object name for any query type, or if <id> is the active query
    object for condtional rendering (Section 2.X), the error INVALID OPERATION
    is generated.


    Section 2.X, Conditional Rendering

    Conditional rendering can be used to discard rendering commands based on
    the result of an occlusion query.  Conditional rendering is started and
    stopped using the commands

        void BeginConditionalRenderNV(uint id, enum mode);
        void EndConditionalRenderNV(void);

    <id> specifies the name of an occlusion query object whose results are
    used to determine if the rendering commands are discarded.  If the result
    (SAMPLES_PASSED) of the query is zero, or if the result
    (ANY_SAMPLES_PASSED or ANY_SAMPLES_PASSED_CONSERVATIVE) is false, all
    rendering commands between BeginConditionalRenderNV and the corresponding
    EndConditionalRenderNV are discarded.  In this case, Begin, End, all
    vertex array commands performing an implicit Begin and End, DrawPixels
    (section 3.6), Bitmap (section 3.7), Clear (section 4.2.3), Accum
    (section 4.2.4), CopyPixels (section 4.3.3), EvalMesh1 and EvalMesh2
    (section 5.1), BlitFramebuffer, ClearBuffer*, and DispatchCompute* have
    no effect.

    The effect of commands setting current vertex state (e.g., Color or
    VertexAttrib) is undefined.  If the result (SAMPLES_PASSED) of the
    query is non-zero, or if the result (ANY_SAMPLES_PASSED or
    ANY_SAMPLES_PASSED_CONSERVATIVE) is true, such commands are not discarded.

    <mode> specifies how BeginConditionalRenderNV interprets the results of
    the occlusion query given by <id>.  If <mode> is QUERY_WAIT_NV, the GL
    waits for the results of the query to be available and then uses the
    results to determine if subsequent rendering commands are discarded.  If
    <mode> is QUERY_NO_WAIT_NV, the GL may choose to unconditionally execute
    the subsequent rendering commands without waiting for the query to
    complete.

    If <mode> is QUERY_BY_REGION_WAIT_NV, the GL will also wait for occlusion
    query results and discard rendering commands if the result of the
    occlusion query is zero.  If the query result is non-zero, subsequent
    rendering commands are executed, but the GL may discard the results of the
    commands for any region of the framebuffer that did not contribute to the
    sample count in the specified occlusion query.  Any such discarding is
    done in an implementation-dependent manner, but the rendering command
    results may not be discarded for any samples that contributed to the
    occlusion query sample count.  If <mode> is QUERY_BY_REGION_NO_WAIT_NV,
    the GL operates as in QUERY_BY_REGION_WAIT_NV, but may choose to
    unconditionally execute the subsequent rendering commands without waiting
    for the query to complete.

    If BeginConditionalRenderNV is called while conditional rendering is in
    progress, or if EndConditionalRenderNV is called while conditional
    rendering is not in progress, the error INVALID_OPERATION is generated.
    The error INVALID_VALUE is generated if <id> is not the name of an
    existing query object query.  The error INVALID_OPERATION is generated if
    <id> is the name of a query object with a target other than
    SAMPLES_PASSED, ANY_SAMPLES_PASSED, or ANY_SAMPLES_PASSED_CONSERVATIVE, or
    if <id> is the name of a query currently in progress.


Additions to Chapter 3 of the OpenGL 2.0 Specification (Rasterization)

    None.

Additions to Chapter 4 of the OpenGL 2.0 Specification (Per-Fragment
Operations and the Frame Buffer)

    None.

Additions to Chapter 5 of the OpenGL 2.0 Specification (Special Functions)

    None.

Additions to Chapter 6 of the OpenGL 2.0 Specification (State and State
Requests)

    None.

Additions to Appendix A of the OpenGL 2.0 Specification (Invariance)

    None.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    The following rendering commands are sent to the server as part of
    glXRender requests:

        BeginConditionalRenderNV
            2           12              rendering command length
            2           348             rendering command opcode
            4           CARD32          id
            4           ENUM            mode

        EndConditionalRenderNV
            2           4               rendering command length
            2           349             rendering command opcode

Dependencies on NVX_conditional_render

    NVX_conditional_render was an early version of this extension.  This
    extension provides several conditional rendering modes (QUERY_WAIT_NV,
    QUERY_NO_WAIT_NV, QUERY_BY_REGION_WAIT_NV, QUERY_BY_REGION_NO_WAIT_NV) not
    present in the NVX extension.  The NVX extension's commands:

      glBeginConditionalRenderNVX(id);
      glEndConditionalRenderNVX();

    are equivalent to the following commands from this extension:

      glBeginConditionalRenderNV(id, QUERY_WAIT_NV);
      glEndConditionalRenderNV();

Dependencies on ARB_occlusion_query2 and OpenGL 3.3

    If ARB_occlusion_query2 or OpenGL 3.3 is not supported in an OpenGL
    implementation, ignore references to the ANY_SAMPLES_PASSED query type.

Dependencies on ARB_ES3_compatibility and OpenGL 4.3

    If ARB_ES3_compatibility or OpenGL 4.3 is not supported in an OpenGL
    implementation, ignore references to the ANY_SAMPLES_PASSED_CONSERVATIVE
    query type.

Dependencies on the OpenGL compatibility profile

    In contexts which support the core profile only (for GL) or OpenGL ES,
    ignore references to the following commands: Begin, End, DrawPixels,
    Bitmap, Accum, Color, CopyPixels, EvalMesh1 and EvalMesh2.

Dependencies on OpenGL 3.0 and OpenGL ES 3.0

    If OpenGL 3.0 or OpenGL ES 3.0 is not supported, ignore references to
    the BlitFramebuffer and ClearBuffer* commands, unless provided by
    other extensions.

Dependencies on OpenGL 4.3 and OpenGL ES 3.1

    If OpenGL 4.3 or OpenGL ES 3.1 is not supported, ignore references to
    DispatchCompute* commands.

Dependencies on EXT_occlusion_query_boolean and OpenGL ES 3.0

    In an OpenGL ES implementation, if OpenGL ES 3.0 is not supported
    replace references to query functionality in OpenGL ES 3.0 with
    the query functionality provided by EXT_occlusion_query_boolean.

Dependencies on NV_occlusion_query_samples

    If NV_occlusion_query_samples is not supported in an OpenGL ES
    implementation, ignore all references to SAMPLES_PASSED.

    If NV_occlusion_query_samples is supported, replaces references to
    SAMPLES_PASSED with SAMPLES_PASSED_NV.

Errors

    INVALID_OPERATION is generated by BeginConditionalRenderNV if a previous
    BeginConditionalRenderNV command has been executed without a
    corresponding EndConditionalRenderNV command.

    INVALID_OPERATION is generated by EndConditionalRenderNV if no
    corresponding BeginConditionalRenderNV command has been executed.

    INVALID_VALUE is generated by BeginConditionalRenderNV if <id> is not the
    name of an existing occlusion query object.

    INVALID_OPERATION is generated by BeginConditionalRenderNV if <id> is the
    name of a query object with a <target> other than SAMPLES_PASSED,
    ANY_SAMPLES_PASSED, or ANY_SAMPLES_PASSED_CONSERVATIVE.

    INVALID_OPERATION is generated by BeginConditionalRenderNV if the query
    identified by <id> is still in progress.

Issues

    (1) How should rendering commands other than "normal" Begin/End-style
    geometry be affected by conditional rendering?

      RESOLVED:  All rendering commands (DrawPixels, Bitmap, Clear, Accum,
      etc...) are performed conditionally.

    (2) What does NO_WAIT do, and why would anyone care?

      RESOLVED:  Hardware OpenGL implementations are heavily pipelined.  After
      vertices are transformed, they are assembled into primitives and
      rasterized.  While a GPU is rasterizing a primitive, it may be
      simultaneously transforming the vertices of the next primitive provided
      to the GL.  At the same time, the CPU may be preparing hardware commands
      to process primitives following that one.

      Conditional rendering uses the results of rasterizing one primitive (an
      occlusion query) to determine whether it will process subsequent ones.
      In a pipelined implementation, the initial set of primitives may not be
      finished drawing by the time the GL needs the occlusion query results.
      Waiting for the query results will leave portions of the GPU temporarily
      idle.  It may be preferable to avoid the idle time by proceeding with a
      conservative assumption that the primitives rendered during the
      occlusion query will hit at least one sample.  The NO_WAIT <mode>
      parameter tells the driver move ahead in that case.

      For best performance, applications should attempt to insert some amount
      of non-dependent rendering between an occlusion query and the
      conditionally-rendered primitives that depend on the query result.

    (3) What does BY_REGION do, and why should anyone care?

      RESOLVED:  Conditional rendering may be used for a variety of effects.
      Some of these use conditional rendering only for performance.  One
      common use would be to draw a bounding box for a primitive
      unconditionally with an occlusion query active, and then conditionally
      execute a DrawElements call to draw the full (complex) primitive.  If
      the bounding box is not visible, any work needed to process the full
      primitive can be skipped in the conditional rendering pass.

      In a split-screen SLI implementation, one GPU might draw the top half of
      the scene while a second might draw the bottom half.  The results of the
      occlusion query would normally be obtained by combining individual
      occlusion query results from each half of the screen.  However, it is
      not necessary to do this for the bounding box algorithm.  We could skip
      this synchronization point, and each region could instead use only its
      local occlusion query results.  If the bounding box hits only the bottom
      half of the screen, the complex primitive need not be drawn on the top
      half, because that portion is known not to be visible.  The bottom half
      would still be drawn, but the GPU used for the top half could skip it
      and start drawing the next primitive specified.  The
      QUERY_BY_REGION_*_NV modes would be useful in that case.

      However, some algorithms may require conditional rendering for
      correctness.  For example, an application may want to render a
      post-processing effect that should be drawn if and only if a point is
      visible in the scene.  Drawing only half of such an effect due to
      BY_REGION tests would not be desirable.

      For QUERY_BY_REGION_NO_WAIT_NV, we expect that GL implementations using
      region-based rendering will discard rendering commands in any region
      where query results are available and the region's sample count is zero.
      Rendering would proceed normally in all other regions.  The spec
      language doesn't require such behavior, however.

    (4) Should the <mode> parameter passed to BeginConditionalRenderNV be
    specified as a hint instead?

      RESOLVED:  The "wait" or "don't wait" portion of the <mode> parameter
      could be a hint.  But it doesn't fit nicely with the FASTEST or NICEST
      values that are normally passed to Hint.  Providing this functionality
      via a <mode> parameter to BeginConditionalRenderNV seems to make the
      most sense.  Note that the <mode> parameter is specified such that
      QUERY_NO_WAIT_NV can be implemented as though QUERY_WAIT_NV were
      specified, which makes the "NO_WAIT" part of the mode a hint.

      The "BY_REGION" part is also effectively a hint.  These modes may be
      implemented as though the equivalent non-BY_REGION mode were provided.
      Many OpenGL implementations will do all of their processing in a single
      region.

    (5) What happens if BeginQuery is called while the specified occlusion
    query is begin used for conditional rendering?

      RESOLVED:  An INVALID_OPERATION error is generated.

    (6) Should conditional rendering work with any type of query other than
    SAMPLES_PASSED (occlusion)?

      RESOLVED:  Not in this extension.  The spec currently requires that <id>
      be the name of an occlusion query.  There might be other query types
      where such an operation would make sense, but there aren't any in the
      current OpenGL spec.

    (7) What is the effect on current state for immediate mode attribute calls
    (e.g., Color, VertexAttrib) made during conditional rendering if the
    corresponding occlusion query failed?

      RESOLVED:  The effect of these calls is undefined.  If subsequent
      primitives depend on a vertex attribute set inside a conditional
      rendering block, and application should re-send the values after
      EndConditionalRenderNV.

    (8) Should we provide any new query object types for conditional
    rendering?

      RESOLVED:  No.  It may be useful to some GL implementations to provide
      an occlusion query type that only returns "zero" or "non-zero", or to
      provide a query type that is used only for conditional rendering but
      doesn't have to maintain results that can be returned to the
      application.  However, performing conditional rendering using only the
      occlusion query mechanisms already in core OpenGL is sufficient for
      the platforms targeted by this extension.

   (9) What happens if QUERY_BY_REGION_* is used, and the application switches
   between windows or FBOs between the occlusion query and conditional
   rendering blocks?  The "regions" used for the two operations may not be
   identical.

     RESOLVED:  The spec language doesn't specifically address this issue, and
     implementations may choose to define regions arbitrarily in this case.

     We strongly recommend that applications using QUERY_BY_REGION_* should
     not change windows or FBO configuration between the occlusion query and
     the dependent rendering.


Usage Example

    GLuint queryID = 0x12345678;

    // Use an occlusion query while rendering the bounding box of the real
    // object.
    glBeginQuery(GL_SAMPLES_PASSED, queryID);
       drawBoundingBox();
    glEndQuery(GL_SAMPLES_PASSED);

    // Do some unrelated rendering in hope that the query result will be
    // available by the time we call glBeginConditionalRenderNV.

    // Now conditionally render the real object if any portion of its
    // bounding box is visible.
    glBeginConditionalRenderNV(queryID, GL_QUERY_WAIT_NV);
       drawComplicatedObject();
    glEndConditionalRenderNV();


Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  --------------------------------------------
     6    05/26/14  dkoch     Add interactions with later GL extensions and
                              core versions.
                              Add interactions with OpenGL ES extensions
                              and versions.

     5    08/07/12  pbrown    Fix minor typos; added interaction with the
                              older NVX_conditional_render extension.

     4    09/22/10  srahman   Added GLX protocol.

     3    02/19/08  pbrown    Document the INVALID_OPERATION error from
                              calling BeginQuery while the query is used
                              for conditional rendering in the spec body.

     2    11/29/07  ewerness  First public release

     1                        Internal revisions
