mirror of
https://github.com/visgl/luma.gl.git
synced 2025-12-08 17:36:19 +00:00
150 lines
6.2 KiB
Markdown
150 lines
6.2 KiB
Markdown
# Query
|
|
|
|
A `Query` object provides single unified API for using WebGL asynchronus queries, which include query objects ('Occlusion' and 'Transform Feedback') and timer queries.
|
|
|
|
See also:
|
|
|
|
- WebGL 1 timer extension: [`EXT_disjoint_timer_query`](https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query/)
|
|
- WebGL 2 timer extension: [`EXT_disjoint_timer_query_webgl2`](https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/)
|
|
|
|
## Usage
|
|
|
|
Use a query to time GPU calls
|
|
|
|
```js
|
|
import {GL} from '@luma.gl/constants';
|
|
import {Query} from '@luma.gl/webgl';
|
|
...
|
|
const timerQuery = new Query(gl);
|
|
|
|
|
|
// In animation loop
|
|
if (timerQuery.isResultAvailable() && !timerQuery.isTimerDisjoin()) {
|
|
result = timerQuery.getResult();
|
|
}
|
|
|
|
|
|
// Option #1
|
|
timerQuery.beginTimeElapsedQuery();
|
|
// Option #2
|
|
// timerQuery.begin(GL.TIME_ELAPSED_EXT)
|
|
|
|
// Issue GPU calls
|
|
|
|
timerQuery.end();
|
|
```
|
|
|
|
## Query Types
|
|
|
|
A query can be started by passing following query type to to `begin()` or by using corresponding begin\* method.
|
|
|
|
| Query Type | begin method | Description |
|
|
| ------------------------------------------ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `GL_TIME_ELAPSED_EXT` | `beginTimeElapsedQuery()` | Time taken by GPU to fully complete a set of GL commands |
|
|
| `GL.ANY_SAMPLES_PASSED` | `beginOcclusionQuery({conservative: false})` | Occlusion query: these queries detect whether an object is visible (whether the scoped drawing commands pass the depth test and if so, how many samples pass). |
|
|
| `GL.ANY_SAMPLES_PASSED_CONSERVATIVE` | `beginOcclusionQuery({conservative: true})` | Same as above above, but less accurate and faster version. |
|
|
| `GL.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN` | `beginTransformFeedbackQuery()` | Number of primitives that are written to transform feedback buffers. |
|
|
|
|
In addition to above queries, Query object also provides `getTimeStamp` which returns GPU time stamp at the time this query is executed by GPU. Two sets of these methods can be used to calculate time taken by GPU for a set of GL commands.
|
|
|
|
## Methods
|
|
|
|
### static Query.isSupported(gl : WebGLRenderingContext, options : Object)
|
|
|
|
Returns true if Query is supported by the WebGL implementation
|
|
(depends on the EXT_disjoint_timer_query extension)/
|
|
Can also check whether timestamp queries are available.
|
|
|
|
- options.queries=false {Object} - If true, checks if Query objects (occlusion/transform feedback) are supported
|
|
- options.timers=false {Object} - If true, checks if 'TIME_ELAPSED_EXT' queries are supported
|
|
|
|
Returns: {Boolean} - Query API is supported with specified configuration
|
|
|
|
Options
|
|
|
|
- queries = false,
|
|
- timers = false,
|
|
|
|
### constructor(gl : WebGLRenderingContext, props : Object)
|
|
|
|
`new Query(gl, {})`
|
|
|
|
### delete()
|
|
|
|
Destroys the WebGL object. Rejects any pending query.
|
|
|
|
- return {Query} - returns itself, to enable chaining of calls.
|
|
|
|
### beginTimeElapsedQuery()
|
|
|
|
Shortcut for timer query (dependent on extension in both WebGL 1 and 2)
|
|
|
|
### Query.beginOcclusionQuery({conservative = false})
|
|
|
|
Shortcut for occlusion query (dependent on WebGL 2)
|
|
|
|
### beginTransformFeedbackQuery()
|
|
|
|
Shortcut for transform feedback query (dependent on WebGL 2)
|
|
|
|
### Query.begin(target)
|
|
|
|
Measures GPU time delta between this call and a matching `end` call in the GPU instruction stream.
|
|
|
|
Remarks:
|
|
|
|
- Due to OpenGL API limitations, after calling `begin()` on one Query
|
|
instance, `end()` must be called on that same instance before
|
|
calling `begin()` on another query. While there can be multiple
|
|
outstanding queries representing disjoint `begin()`/`end()` intervals.
|
|
It is not possible to interleave or overlap `begin` and `end` calls.
|
|
- Triggering a new query when a Query is already tracking an
|
|
unresolved query causes that query to be cancelled.
|
|
|
|
- target {GLenum} - target to query
|
|
- return {Query} - returns itself, to enable chaining of calls.
|
|
|
|
### end
|
|
|
|
Inserts a query end marker into the GPU instruction stream.
|
|
Note: Can be called multiple times.
|
|
|
|
return {Query} - returns itself, to enable chaining of calls.
|
|
|
|
### isResultAvailable
|
|
|
|
return {Boolean} - true if query result is available
|
|
|
|
### getResult
|
|
|
|
Returns the query result
|
|
|
|
return {Number} - query result. Semantics depend on query type
|
|
|
|
### getTimerMilliseconds
|
|
|
|
Shorthand for getting timer query results and converting to milliseconds to match JavaScript conventions.
|
|
|
|
return {Number} - measured time or timestamp, in milliseconds
|
|
|
|
### isTimerDisjoint
|
|
|
|
Returns `true` if the timer query was disjoint, indicating that timing results are invalid.
|
|
This is rare and might occur, for example, if the GPU was throttled while timing.
|
|
|
|
return {Boolean} - true if timer query was disjoint
|
|
|
|
### createPoll(limit = Number.POSITIVE_INFINITY)
|
|
|
|
Begins polling `Query` once per frame to check if results are available.
|
|
|
|
- limit {Number} - Maximum number of frames to poll before rejecting the `Promise`.
|
|
|
|
return {Promise} - Resolves to the `Query` result if it becomes available before `limit`
|
|
frames have elapsed, and is rejected otherwise.
|
|
|
|
## Remarks
|
|
|
|
- Even when supported, timer queries can fail whenever a change in the GPU occurs that will make the values returned by this extension unusable for performance metrics, for example if the GPU is throttled mid-frame. This occurance is captured in `isTimerDisjoint` method.
|
|
- Note that from a JavaScript perspective, where callback driven APIs are the norm, the functionality of the WebGL `Query` class seems limited. Many operations that require expensive roundtrips to the GPU (such as `readPixels`) that would obviously benefit from asynchronous queries, are not covered by the `Query` class.
|