diff --git a/docs/api-reference/core/resources/query-set.md b/docs/api-reference/core/resources/query-set.md new file mode 100644 index 0000000000..67b6a3cb42 --- /dev/null +++ b/docs/api-reference/core/resources/query-set.md @@ -0,0 +1,81 @@ +# QuerySet + +:::caution +This page is incomplete. +::: + +A `QuerySet` object provides an API for using asynchronous GPU queries of the following types +- timer queries. +- 'Occlusion' +- 'Transform Feedback' + +A `QuerySet` holds a number of 64 bit values. + +Timer queries are available if the `timestamp-query` extension is available. (On WebGL 2 this is equivalent to the +[`EXT_disjoint_timer_query_webgl2`](https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/) +being supported on the current browser. + +Note that 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. + +## Usage + +Create a timestamp query set: + +```typescript +import {QuerySet} from '@luma.gl/core'; +... +const timestampQuery = device.createQuerySet({type: 'timestamp'}}); +``` + +## Types + +### `QueryProps` + +- `type`: `occlusion` | `timestamp` - type of timer +- `count`: `number` - number of query results held by this `QuerySet` + +| Query Type | Usage | Description | +| ---------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------- | +| `timestamp` (`RenderPass begin/end`) | `beginRenderPass({timestampQuery: ...})` | Time taken by GPU to execute RenderPass commands | +| `timestamp` (`ComputePass begin/end`) | `beginComputePass({timestampQuery: ...})` | Time taken by GPU to execute ComputePass commands | +| `occlusion` | `beginOcclusionQuery({conservative: false})` | Occlusion query how many fragment samples pass tests (depth, stencil, ...) | +| `occlusion` | `beginOcclusionQuery({conservative: true})` | Same as above above, but less accurate and faster | +| `transform-feedback` (Not yet supported) | `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. + +## DeviceFeatures + +`timestamp-query`: Whether `QuerySet` can be created with type `timestamp`. + +## Methods + + + +### `constructor(device: Device, props: Object)` + +`new Query(gl, {})` +- options.timers=false Object - If true, checks if 'TIME_ELAPSED_EXT' queries are supported + +### `destroy()` + +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) + +## RenderPass + + +### `RenderPass.beginOcclusionQuery({conservative = false})` + +Shortcut for occlusion query (dependent on WebGL 2) + +### `RenderPass.beginTransformFeedbackQuery()` + +WebGL 2 only. not yet implemented. + diff --git a/docs/developer-guide/profiling.md b/docs/developer-guide/profiling.md index 3f72996749..3b911175c0 100644 --- a/docs/developer-guide/profiling.md +++ b/docs/developer-guide/profiling.md @@ -1,7 +1,7 @@ # Profiling GPU programming is all about performance, so having tools to systematically -measure the performance impact of code changes are critical. luma.gl offers +measure the performance impact of code changes is critical. luma.gl offers several built-in facilities. ## probe.gl Stats @@ -31,4 +31,12 @@ however tracking allocations can help spot resource leaks or unnecessary work be ## Performance Profiling -Queries are supported if available. +`device.createQuerySet()` can be used to create GPU queries that + +- Occlusion Queries always supported. +- Timestamp Queries are supported if the `timestamp-query` feature is available, check with `device.features.has('timestamp-query')`. + +`QuerySet` instances can be supplied when creating `RenderPass` and `ComputePass` instances. + +Results are available through +`commandEncoder.resolveQuerySet()` diff --git a/docs/sidebar.json b/docs/sidebar.json index 8627be713e..4fcc73b3bc 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -94,7 +94,8 @@ "api-reference/core/resources/shader", "api-reference/core/shader-logs", "api-reference/core/resources/texture", - "api-reference/core/resources/vertex-array" + "api-reference/core/resources/vertex-array", + "api-reference/core/resources/query-set" ] }, { diff --git a/modules/core-tests/test/adapter/resources/query-set.spec.ts b/modules/core-tests/test/adapter/resources/query-set.spec.ts index 6b1e96a7fd..3012597f66 100644 --- a/modules/core-tests/test/adapter/resources/query-set.spec.ts +++ b/modules/core-tests/test/adapter/resources/query-set.spec.ts @@ -6,8 +6,7 @@ import test from 'tape-promise/tape'; import {getTestDevices} from '@luma.gl/test-utils'; import {QuerySet} from '@luma.gl/core'; - -test('QuerySet construct/delete', async (t) => { +test('QuerySet construct/delete', async t => { for (const device of await getTestDevices()) { const querySet = device.createQuerySet({type: 'occlusion', count: 1}); t.ok(querySet instanceof QuerySet, 'QuerySet construction successful');