| Name |
| |
| EXT_occlusion_query_boolean |
| |
| Name Strings |
| |
| GL_EXT_occlusion_query_boolean |
| |
| Contributors |
| |
| All those who have contributed to the definition of occlusion |
| query functionality in the OpenGL ARB and OpenGL ES workgroups, |
| upon which this extension spec is entirely dependent. |
| |
| Contact |
| |
| Benj Lipchak, Apple (lipchak 'at' apple.com) |
| |
| Status |
| |
| Complete |
| |
| Version |
| |
| Date: July 22, 2011 |
| Revision: 2 |
| |
| Number |
| |
| OpenGL ES Extension #100 |
| |
| Dependencies |
| |
| Written based on the wording of the OpenGL ES 2.0.25 Full Specification |
| (November 2, 2010). |
| |
| Overview |
| |
| This extension defines a mechanism whereby an application can |
| query whether any pixels (or, more precisely, samples) are drawn |
| by a primitive or group of primitives. |
| |
| The primary purpose of such a query (hereafter referred to as an |
| "occlusion query") is to determine the visibility of an object. |
| Typically, the application will render the major occluders in the |
| scene, then perform an occlusion query for each detail object in |
| the scene. On subsequent frames, the previous results of the |
| occlusion queries can be used to decide whether to draw an object |
| or not. |
| |
| New Procedures and Functions |
| |
| void GenQueriesEXT(sizei n, uint *ids); |
| void DeleteQueriesEXT(sizei n, const uint *ids); |
| boolean IsQueryEXT(uint id); |
| void BeginQueryEXT(enum target, uint id); |
| void EndQueryEXT(enum target); |
| void GetQueryivEXT(enum target, enum pname, int *params); |
| void GetQueryObjectuivEXT(uint id, enum pname, uint *params); |
| |
| New Tokens |
| |
| Accepted by the <target> parameter of BeginQueryEXT, EndQueryEXT, |
| and GetQueryivEXT: |
| |
| ANY_SAMPLES_PASSED_EXT 0x8C2F |
| ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A |
| |
| Accepted by the <pname> parameter of GetQueryivEXT: |
| |
| CURRENT_QUERY_EXT 0x8865 |
| |
| Accepted by the <pname> parameter of GetQueryObjectivEXT and |
| GetQueryObjectuivEXT: |
| |
| QUERY_RESULT_EXT 0x8866 |
| QUERY_RESULT_AVAILABLE_EXT 0x8867 |
| |
| Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL ES Operation) |
| |
| Add a new section "Asynchronous Queries" between sections 2.12 and 2.13 |
| and renumber subsequent sections: |
| |
| "2.13 Asynchronous Queries |
| |
| Asynchronous queries provide a mechanism to return information about the |
| processing of a sequence of GL commands. There is one query type |
| supported by the GL. Occlusion queries (see section 4.1.6) set a boolean |
| to true when any fragments or samples 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.6 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 and made active by calling |
| |
| void BeginQueryEXT(enum target, uint id); |
| |
| <target> indicates the type of query to be performed; valid values of |
| <target> are defined in subsequent sections. If the query object name <id> |
| has not been created, the name is marked as used and associated with a new |
| query object of the type specified by <target>. Otherwise <id> must be the |
| name of an existing query object of that type. |
| |
| BeginQueryEXT fails and an INVALID_OPERATION error is generated if <id> |
| is not a name returned from a previous call to GenQueriesEXT, or if such |
| a name has since been deleted with DeleteQueriesEXT. |
| |
| BeginQueryEXT sets the active query object name for the query type given |
| by <target> to <id>. If BeginQueryEXT is called with an <id> of zero, if |
| the active query object name for <target> is non-zero (for the targets |
| ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the |
| active query for either target is non-zero), if <id> is the name of an |
| existing query object whose type does not match <target>, or if <id> is the |
| active query object name for any query type, the error INVALID_OPERATION is |
| generated. |
| |
| The command |
| |
| void EndQueryEXT(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 |
| EndQueryEXT have completed and a final query result is available, the |
| query object active when EndQueryEXT 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 EndQueryEXT is called, the error INVALID_OPERATION |
| is generated. |
| |
| The command |
| |
| void GenQueriesEXT(sizei n, uint *ids); |
| |
| returns <n> previously unused query object names in <ids>. These names are |
| marked as used, for the purposes of GenQueriesEXT only, but no object is |
| associated with them until the first time they are used by BeginQueryEXT. |
| |
| Query objects are deleted by calling |
| |
| void DeleteQueriesEXT(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, as is the value zero. If an active query object is |
| deleted its name immediately becomes unused, but the underlying object is |
| not deleted until it is no longer active (see section C.1). |
| |
| 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 and may vary by query object type. 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. |
| Only a single type of occlusion query can be active at one time, so the |
| required state for occlusion queries is shared." |
| |
| Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization) |
| |
| None |
| |
| Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment |
| Operations and the Frame Buffer) |
| |
| Add a new section "Occlusion Queries" between sections 4.1.5 and |
| 4.1.6 and renumber subsequent sections: |
| |
| "4.1.6 Occlusion Queries |
| |
| 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 BeginQueryEXT and EndQueryEXT, respectively, with a |
| target of ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. |
| |
| When an occlusion query is started with the target |
| ANY_SAMPLES_PASSED_EXT, the samples-boolean state maintained by the GL is |
| set to FALSE. While that occlusion query is active, the samples-boolean |
| state is set to TRUE if any fragment or sample passes the depth test. When |
| the occlusion query finishes, the samples-boolean state of FALSE or TRUE 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 target of |
| the query is ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, an implementation may |
| choose to use a less precise version of the test which can additionally set |
| the samples-boolean state to TRUE in some other implementation dependent |
| cases." |
| |
| Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) |
| |
| None |
| |
| Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and |
| State Requests) |
| |
| Add a new section "Asynchronous Queries" between sections 6.1.5 and |
| 6.1.6 and renumber subsequent sections: |
| |
| "6.1.6 Asynchronous Queries |
| |
| The command |
| |
| boolean IsQueryEXT(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, IsQueryEXT returns FALSE. |
| |
| Information about a query target can be queried with the command |
| |
| void GetQueryivEXT(enum target, enum pname, int *params); |
| |
| <target> identifies the query target, and must be one of |
| ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. |
| |
| <pname> must be CURRENT_QUERY_EXT. The name of the currently active |
| query for <target>, or zero if no query is active, will be placed in |
| <params>. |
| |
| The state of a query object can be queried with the command |
| |
| void GetQueryObjectuivEXT(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. <pname> must be QUERY_RESULT_EXT or QUERY_RESULT_AVAILABLE_EXT. |
| |
| If <pname> is QUERY_RESULT_EXT, 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. |
| |
| There may be an indeterminate delay before the above query returns. If |
| <pname> is QUERY_RESULT_AVAILABLE_EXT, FALSE is returned if such a delay |
| would be required; otherwise TRUE is returned. 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 that occlusion query |
| to complete within a finite amount of time. Repeatedly querying the |
| QUERY_RESULT_AVAILABLE_EXT state for any given query object is guaranteed |
| to return true eventually. Note that multiple queries to the same occlusion |
| object may result in a significant performance loss. For better performance |
| it is recommended to wait N frames before querying this state. N is |
| implementation dependent but is generally between one and three. |
| |
| If multiple queries are issued using the same object name prior to calling |
| GetQueryObjectuivEXT, 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>." |
| |
| Additions to Appendix C of the OpenGL ES 2.0 Specification (Shared Object and |
| Multiple Contexts) |
| |
| Change the first sentence of the first paragraph of section C.1.2 to read: |
| |
| "When a buffer, texture, renderbuffer, or query is deleted, ..." |
| |
| Add the following sentence to the end of section C.1.2: |
| |
| "A query object is in use so long as it is the active query object for a |
| query type and index, as described in section 2.13." |
| |
| Errors |
| |
| The error INVALID_OPERATION is generated if BeginQueryEXT is called |
| where <id> is not a name returned from a previous call to GenQueriesEXT, |
| or if such a name has since been deleted with DeleteQueriesEXT. |
| |
| The error INVALID_OPERATION is generated if BeginQueryEXT is called |
| where <id> is zero. |
| |
| The error INVALID_OPERATION is generated if BeginQueryEXT is called |
| where <id> is the name of an existing query object whose type does not |
| match <target>. |
| |
| The error INVALID_OPERATION is generated if BeginQueryEXT is called |
| where <id> is the active query object name for any query type. |
| |
| The error INVALID_OPERATION is generated if BeginQueryEXT is called |
| when the active query object name for either ANY_SAMPLES_PASSED_EXT or |
| ANY_SAMPLES_PASSED_CONSERVATIVE_EXT is non-zero. |
| |
| The error INVALID_OPERATION is generated if EndQueryEXT is called |
| when the active query object name for <target> is zero. |
| |
| The error INVALID_OPERATION is generated if GetQueryObjectuivEXT is |
| called where <id> is not the name of a query object. |
| |
| The error INVALID_OPERATION is generated if GetQueryObjectuivEXT is |
| called where <id> is the name of a currently active query object. |
| |
| The error INVALID_VALUE is generated if GenQueriesEXT is called where |
| <n> is negative. |
| |
| The error INVALID_VALUE is generated if DeleteQueriesEXT is called |
| where <n> is negative. |
| |
| The error INVALID_ENUM is generated if BeginQueryEXT, EndQueryEXT, |
| or GetQueryivEXT is called where <target> is not |
| ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT. |
| |
| The error INVALID_ENUM is generated if GetQueryivEXT is called where |
| <pname> is not CURRENT_QUERY_EXT. |
| |
| The error INVALID_ENUM is generated if GetQueryObjectuivEXT is called |
| where <pname> is not QUERY_RESULT_EXT or QUERY_RESULT_AVAILABLE_EXT. |
| |
| New State |
| |
| (table 6.18, p. 233) |
| |
| Int'l |
| Get Value Type Get Command Value Description Sec |
| -------------------------- ---- -------------------- ----- ---------------------- ----- |
| - B - FALSE query active 4.1.6 |
| CURRENT_QUERY_EXT Z+ GetQueryivEXT 0 active query ID 4.1.6 |
| QUERY_RESULT_EXT B GetQueryObjectuivEXT FALSE samples-passed 4.1.6 |
| QUERY_RESULT_AVAILABLE_EXT B GetQueryObjectuivEXT FALSE query result available 4.1.6 |
| |
| Issues |
| |
| (1) What should the enum be called? |
| |
| RESOLVED: The enum should be called ANY_SAMPLES_PASSED as in |
| ARB_occlusion_query2 to retain compatibility between the two |
| extensions. |
| |
| (2) Can application-provided names be used as query object names? |
| |
| ARB_occlusion_query allows application-provided names, but this |
| was later removed in core OpenGL. |
| |
| RESOLVED: No, we will follow core OpenGL on this. |
| |
| (3) Should calling GenQueries or DeleteQueries when a query is |
| active produce an error? |
| |
| This behavior is in ARB_occlusion_query but was |
| removed in OpenGL 3.0. |
| |
| RESOLVED: Not an error. Calling DeleteQueries marks the name |
| as no longer used, but the object is not deleted until it is no |
| longer in use (i.e. no longer active). |
| |
| (4) What is the interaction with multisample? |
| |
| RESOLVED: The query result is set to true if at least one |
| sample passes the depth test. |
| |
| (5) Exactly what stage in the pipeline are we counting samples at? |
| |
| RESOLVED: We are counting immediately after _both_ the depth and |
| stencil tests, i.e., samples that pass both. Note that the depth |
| test comes after the stencil test, so to say that it is the |
| number that pass the depth test is sufficient; though it is often |
| conceptually helpful to think of the depth and stencil tests as |
| being combined, because the depth test's result impacts the |
| stencil operation used. |
| |
| (6) Is it guaranteed that occlusion queries return in order? |
| |
| RESOLVED: Yes. |
| |
| If occlusion test X occurred before occlusion query Y, and the driver |
| informs the app that occlusion query Y is done, the app can infer that |
| occlusion query X is also done. |
| |
| (7) Will polling a query for QUERY_RESULT_AVAILABLE without a Flush |
| possibly cause an infinite loop? |
| |
| RESOLVED: No. |
| |
| (8) Should there be a "target" parameter to BeginQuery? |
| |
| RESOLVED: Yes. This distinguishes the boolean queries |
| defined by this extension (and ARB_occlusion_query2) from |
| the counter queries defined by ARB_occlusion_query. |
| |
| (9) Are query objects shareable between multiple contexts? |
| |
| RESOLVED: No. Query objects are lightweight and we normally share |
| large data across contexts. Also, being able to share query objects |
| across contexts is not particularly useful. In order to do the async |
| query across contexts, a query on one context would have to be finished |
| before the other context could query it. |
| |
| (10) Should there be a limit on how many queries can be outstanding? |
| |
| RESOLVED: No. If an implementation has an internal limit, it can |
| flush the pipeline when it runs out. |
| |
| (11) Can an implementation sometimes return a conservative result, |
| i.e. return true even though no samples were drawn? |
| |
| RESOLVED: Yes, but only when explicitly enabled by the |
| application. |
| |
| Allowing such results with no restrictions effectively makes |
| the functionality of the extension optional, which decreases |
| its value. Precise restrictions are presumably hard to |
| specify. |
| |
| One situation where this restriction could be relevant is if |
| an implementation performs a conservative early depth test at |
| a lower precision and wants to base the occlusion query result |
| on that whenever the early depth test can be used. |
| |
| (12) Should the restrictions in issue 11 be explicitly enabled |
| by the application in order to be in effect? |
| |
| RESOLVED: Yes. |
| |
| The restrictions could be enabled by a hint call or by using |
| a different enum in the BeginQuery call. |
| |
| This would enable the application to choose whether it wants a |
| precise (but possibly slow) version or an approximate (but |
| possibly faster) version. |
| |
| (13) Can the restrictions in issue 18 be applied nondeterministically? |
| |
| An implementation might benefit from taking the decision of |
| whether to apply a particular restriction on a case by case |
| basis. Some of these decisions could depend on |
| nondeterministic effects such as memory bus timing. |
| |
| RESOLVED: No. This would violate the GL repeatability |
| principle. |
| |
| (14) How does an application request that the result is allowed to |
| be conservative (as defined in issue 11)? |
| |
| RESOLVED: It is specified as a separate query target, |
| ANY_SAMPLES_PASSED_CONSERVATIVE. |
| |
| |
| Revision History |
| |
| Date: 5/03/2011 |
| Revision: 1 (Benj Lipchak) |
| - Initial draft based on XXX_occlusion_query_boolean |
| |
| Date: 7/22/2011 |
| Revision: 2 (Benj Lipchak) |
| - Rename from APPLE to EXT |