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 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 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 to . If BeginQuery is called with an of zero, if the active query object name for is non-zero, if is the active query object name for any query type, or if 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); 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. specifies how BeginConditionalRenderNV interprets the results of the occlusion query given by . If 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 is QUERY_NO_WAIT_NV, the GL may choose to unconditionally execute the subsequent rendering commands without waiting for the query to complete. If 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 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 is not the name of an existing query object query. The error INVALID_OPERATION is generated if is the name of a query object with a target other than SAMPLES_PASSED, ANY_SAMPLES_PASSED, or ANY_SAMPLES_PASSED_CONSERVATIVE, or if 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 is not the name of an existing occlusion query object. INVALID_OPERATION is generated by BeginConditionalRenderNV if is the name of a query object with a other than SAMPLES_PASSED, ANY_SAMPLES_PASSED, or ANY_SAMPLES_PASSED_CONSERVATIVE. INVALID_OPERATION is generated by BeginConditionalRenderNV if the query identified by 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 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 parameter passed to BeginConditionalRenderNV be specified as a hint instead? RESOLVED: The "wait" or "don't wait" portion of the 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 parameter to BeginConditionalRenderNV seems to make the most sense. Note that the 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 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