@luma.gl/webgl 9.3.0-alpha.2 → 9.3.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/converters/webgl-texture-table.d.ts +7 -1
- package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
- package/dist/adapter/converters/webgl-texture-table.js +121 -43
- package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
- package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
- package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
- package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
- package/dist/adapter/device-helpers/webgl-device-info.js +5 -0
- package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
- package/dist/adapter/helpers/get-shader-layout-from-glsl.js +23 -21
- package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
- package/dist/adapter/helpers/parse-shader-compiler-log.d.ts +1 -1
- package/dist/adapter/helpers/parse-shader-compiler-log.d.ts.map +1 -1
- package/dist/adapter/helpers/parse-shader-compiler-log.js +20 -0
- package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -1
- package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-buffer.js +19 -4
- package/dist/adapter/resources/webgl-buffer.js.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.d.ts +3 -4
- package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.js +11 -7
- package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
- package/dist/adapter/resources/webgl-command-encoder.d.ts +5 -4
- package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-encoder.js +20 -7
- package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgl-query-set.d.ts +29 -31
- package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-query-set.js +193 -97
- package/dist/adapter/resources/webgl-query-set.js.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.js +17 -0
- package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.d.ts +13 -19
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +36 -154
- package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
- package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
- package/dist/adapter/resources/webgl-shared-render-pipeline.js +152 -0
- package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
- package/dist/adapter/resources/webgl-texture.d.ts +23 -4
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +203 -100
- package/dist/adapter/resources/webgl-texture.js.map +1 -1
- package/dist/adapter/resources/webgl-transform-feedback.js +5 -5
- package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
- package/dist/adapter/webgl-adapter.d.ts.map +1 -1
- package/dist/adapter/webgl-adapter.js +3 -4
- package/dist/adapter/webgl-adapter.js.map +1 -1
- package/dist/adapter/webgl-device.d.ts +6 -3
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +56 -14
- package/dist/adapter/webgl-device.js.map +1 -1
- package/dist/adapter/webgl-presentation-context.d.ts +21 -0
- package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
- package/dist/adapter/webgl-presentation-context.js +64 -0
- package/dist/adapter/webgl-presentation-context.js.map +1 -0
- package/dist/context/debug/spector.d.ts.map +1 -1
- package/dist/context/debug/spector.js +4 -4
- package/dist/context/debug/spector.js.map +1 -1
- package/dist/context/debug/webgl-developer-tools.js +2 -0
- package/dist/context/debug/webgl-developer-tools.js.map +1 -1
- package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
- package/dist/context/helpers/create-browser-context.js +6 -8
- package/dist/context/helpers/create-browser-context.js.map +1 -1
- package/dist/context/helpers/webgl-context-data.d.ts +5 -1
- package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
- package/dist/context/helpers/webgl-context-data.js +9 -10
- package/dist/context/helpers/webgl-context-data.js.map +1 -1
- package/dist/context/parameters/unified-parameter-api.d.ts +1 -1
- package/dist/context/parameters/unified-parameter-api.js +2 -2
- package/dist/context/parameters/unified-parameter-api.js.map +1 -1
- package/dist/context/state-tracker/webgl-state-tracker.js +2 -2
- package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -1
- package/dist/dist.dev.js +1427 -828
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +1325 -811
- package/dist/index.cjs.map +4 -4
- package/dist/utils/fill-array.js +1 -1
- package/dist/utils/fill-array.js.map +1 -1
- package/package.json +4 -4
- package/src/adapter/converters/webgl-texture-table.ts +159 -47
- package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
- package/src/adapter/device-helpers/webgl-device-info.ts +6 -0
- package/src/adapter/helpers/get-shader-layout-from-glsl.ts +25 -24
- package/src/adapter/helpers/parse-shader-compiler-log.ts +23 -1
- package/src/adapter/resources/webgl-buffer.ts +16 -4
- package/src/adapter/resources/webgl-command-buffer.ts +21 -24
- package/src/adapter/resources/webgl-command-encoder.ts +22 -7
- package/src/adapter/resources/webgl-query-set.ts +229 -102
- package/src/adapter/resources/webgl-render-pass.ts +19 -0
- package/src/adapter/resources/webgl-render-pipeline.ts +46 -181
- package/src/adapter/resources/webgl-shared-render-pipeline.ts +208 -0
- package/src/adapter/resources/webgl-texture.ts +326 -121
- package/src/adapter/resources/webgl-transform-feedback.ts +5 -5
- package/src/adapter/webgl-adapter.ts +3 -4
- package/src/adapter/webgl-device.ts +66 -19
- package/src/adapter/webgl-presentation-context.ts +93 -0
- package/src/context/debug/spector.ts +4 -4
- package/src/context/debug/webgl-developer-tools.ts +2 -0
- package/src/context/helpers/create-browser-context.ts +8 -8
- package/src/context/helpers/webgl-context-data.ts +17 -11
- package/src/context/parameters/unified-parameter-api.ts +2 -2
- package/src/context/state-tracker/webgl-state-tracker.ts +2 -2
- package/src/utils/fill-array.ts +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {CommandEncoder, CommandEncoderProps} from '@luma.gl/core';
|
|
5
|
+
import {CommandBufferProps, CommandEncoder, CommandEncoderProps} from '@luma.gl/core';
|
|
6
6
|
import type {
|
|
7
7
|
RenderPassProps,
|
|
8
8
|
ComputePass,
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
import {WEBGLCommandBuffer} from './webgl-command-buffer';
|
|
21
21
|
import {WEBGLRenderPass} from './webgl-render-pass';
|
|
22
22
|
import {WebGLDevice} from '../webgl-device';
|
|
23
|
+
import {WEBGLQuerySet} from './webgl-query-set';
|
|
23
24
|
|
|
24
25
|
export class WEBGLCommandEncoder extends CommandEncoder {
|
|
25
26
|
readonly device: WebGLDevice;
|
|
@@ -30,20 +31,29 @@ export class WEBGLCommandEncoder extends CommandEncoder {
|
|
|
30
31
|
constructor(device: WebGLDevice, props: CommandEncoderProps) {
|
|
31
32
|
super(device, props);
|
|
32
33
|
this.device = device;
|
|
33
|
-
this.commandBuffer = new WEBGLCommandBuffer(device
|
|
34
|
+
this.commandBuffer = new WEBGLCommandBuffer(device, {
|
|
35
|
+
id: `${this.props.id}-command-buffer`
|
|
36
|
+
});
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
override destroy(): void {
|
|
39
|
+
override destroy(): void {
|
|
40
|
+
this.destroyResource();
|
|
41
|
+
}
|
|
37
42
|
|
|
38
|
-
override finish(): WEBGLCommandBuffer {
|
|
43
|
+
override finish(props?: CommandBufferProps): WEBGLCommandBuffer {
|
|
44
|
+
if (props?.id && this.commandBuffer.id !== props.id) {
|
|
45
|
+
this.commandBuffer.id = props.id;
|
|
46
|
+
this.commandBuffer.props.id = props.id;
|
|
47
|
+
}
|
|
48
|
+
this.destroy();
|
|
39
49
|
return this.commandBuffer;
|
|
40
50
|
}
|
|
41
51
|
|
|
42
|
-
beginRenderPass(props: RenderPassProps): WEBGLRenderPass {
|
|
43
|
-
return new WEBGLRenderPass(this.device, props);
|
|
52
|
+
beginRenderPass(props: RenderPassProps = {}): WEBGLRenderPass {
|
|
53
|
+
return new WEBGLRenderPass(this.device, this._applyTimeProfilingToPassProps(props));
|
|
44
54
|
}
|
|
45
55
|
|
|
46
|
-
beginComputePass(props: ComputePassProps): ComputePass {
|
|
56
|
+
beginComputePass(props: ComputePassProps = {}): ComputePass {
|
|
47
57
|
throw new Error('ComputePass not supported in WebGL');
|
|
48
58
|
}
|
|
49
59
|
|
|
@@ -81,4 +91,9 @@ export class WEBGLCommandEncoder extends CommandEncoder {
|
|
|
81
91
|
destinationOffset?: number;
|
|
82
92
|
}
|
|
83
93
|
): void {}
|
|
94
|
+
|
|
95
|
+
writeTimestamp(querySet: QuerySet, queryIndex: number): void {
|
|
96
|
+
const webglQuerySet = querySet as WEBGLQuerySet;
|
|
97
|
+
webglQuerySet.writeTimestamp(queryIndex);
|
|
98
|
+
}
|
|
84
99
|
}
|
|
@@ -1,175 +1,302 @@
|
|
|
1
|
-
// WebGL2
|
|
1
|
+
// WebGL2 QuerySet (also handles disjoint timer extensions)
|
|
2
2
|
import {QuerySet, QuerySetProps} from '@luma.gl/core';
|
|
3
3
|
import {GL} from '@luma.gl/constants';
|
|
4
4
|
import {WebGLDevice} from '../webgl-device';
|
|
5
5
|
|
|
6
|
+
type WebGLPendingQuery = {
|
|
7
|
+
handle: WebGLQuery;
|
|
8
|
+
promise: Promise<bigint> | null;
|
|
9
|
+
result: bigint | null;
|
|
10
|
+
disjoint: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type WebGLTimestampPair = {
|
|
14
|
+
activeQuery: WebGLPendingQuery | null;
|
|
15
|
+
completedQueries: WebGLPendingQuery[];
|
|
16
|
+
};
|
|
17
|
+
|
|
6
18
|
/**
|
|
7
19
|
* Asynchronous queries for different kinds of information
|
|
8
20
|
*/
|
|
9
21
|
export class WEBGLQuerySet extends QuerySet {
|
|
10
22
|
readonly device: WebGLDevice;
|
|
11
|
-
readonly handle: WebGLQuery;
|
|
23
|
+
readonly handle: WebGLQuery | null;
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
protected _timestampPairs: WebGLTimestampPair[] = [];
|
|
26
|
+
protected _occlusionQuery: WebGLPendingQuery | null = null;
|
|
27
|
+
protected _occlusionActive = false;
|
|
16
28
|
|
|
17
29
|
override get [Symbol.toStringTag](): string {
|
|
18
|
-
return '
|
|
30
|
+
return 'QuerySet';
|
|
19
31
|
}
|
|
20
32
|
|
|
21
|
-
// Create a query class
|
|
22
33
|
constructor(device: WebGLDevice, props: QuerySetProps) {
|
|
23
34
|
super(device, props);
|
|
24
35
|
this.device = device;
|
|
25
36
|
|
|
26
|
-
if (props.
|
|
27
|
-
|
|
37
|
+
if (props.type === 'timestamp') {
|
|
38
|
+
if (props.count < 2) {
|
|
39
|
+
throw new Error('Timestamp QuerySet requires at least two query slots');
|
|
40
|
+
}
|
|
41
|
+
this._timestampPairs = new Array(Math.ceil(props.count / 2))
|
|
42
|
+
.fill(null)
|
|
43
|
+
.map(() => ({activeQuery: null, completedQueries: []}));
|
|
44
|
+
this.handle = null;
|
|
45
|
+
} else {
|
|
46
|
+
if (props.count > 1) {
|
|
47
|
+
throw new Error('WebGL occlusion QuerySet can only have one value');
|
|
48
|
+
}
|
|
49
|
+
const handle = this.device.gl.createQuery();
|
|
50
|
+
if (!handle) {
|
|
51
|
+
throw new Error('WebGL query not supported');
|
|
52
|
+
}
|
|
53
|
+
this.handle = handle;
|
|
28
54
|
}
|
|
29
55
|
|
|
30
|
-
const handle = this.device.gl.createQuery();
|
|
31
|
-
if (!handle) {
|
|
32
|
-
throw new Error('WebGL query not supported');
|
|
33
|
-
}
|
|
34
|
-
this.handle = handle;
|
|
35
56
|
Object.seal(this);
|
|
36
57
|
}
|
|
37
58
|
|
|
38
|
-
override destroy() {
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
override destroy(): void {
|
|
60
|
+
if (this.destroyed) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
41
63
|
|
|
42
|
-
|
|
64
|
+
if (this.handle) {
|
|
65
|
+
this.device.gl.deleteQuery(this.handle);
|
|
66
|
+
}
|
|
43
67
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
for (const pair of this._timestampPairs) {
|
|
69
|
+
if (pair.activeQuery) {
|
|
70
|
+
this.device.gl.deleteQuery(pair.activeQuery.handle);
|
|
71
|
+
}
|
|
72
|
+
for (const query of pair.completedQueries) {
|
|
73
|
+
this.device.gl.deleteQuery(query.handle);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (this._occlusionQuery) {
|
|
78
|
+
this.device.gl.deleteQuery(this._occlusionQuery.handle);
|
|
79
|
+
}
|
|
52
80
|
|
|
53
|
-
|
|
54
|
-
this._end();
|
|
81
|
+
this.destroyResource();
|
|
55
82
|
}
|
|
56
83
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
isResultAvailable(queryIndex?: number): boolean {
|
|
85
|
+
if (this.props.type === 'timestamp') {
|
|
86
|
+
if (queryIndex === undefined) {
|
|
87
|
+
return this._timestampPairs.some((_, pairIndex) =>
|
|
88
|
+
this._isTimestampPairAvailable(pairIndex)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return this._isTimestampPairAvailable(this._getTimestampPairIndex(queryIndex));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!this._occlusionQuery) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return this._pollQueryAvailability(this._occlusionQuery);
|
|
62
99
|
}
|
|
63
100
|
|
|
64
|
-
|
|
65
|
-
|
|
101
|
+
async readResults(options?: {firstQuery?: number; queryCount?: number}): Promise<bigint[]> {
|
|
102
|
+
const firstQuery = options?.firstQuery || 0;
|
|
103
|
+
const queryCount = options?.queryCount || this.props.count - firstQuery;
|
|
104
|
+
this._validateRange(firstQuery, queryCount);
|
|
105
|
+
|
|
106
|
+
if (this.props.type === 'timestamp') {
|
|
107
|
+
const results = new Array<bigint>(queryCount).fill(0n);
|
|
108
|
+
const startPairIndex = Math.floor(firstQuery / 2);
|
|
109
|
+
const endPairIndex = Math.floor((firstQuery + queryCount - 1) / 2);
|
|
110
|
+
|
|
111
|
+
for (let pairIndex = startPairIndex; pairIndex <= endPairIndex; pairIndex++) {
|
|
112
|
+
const duration = await this._consumeTimestampPairResult(pairIndex);
|
|
113
|
+
const beginSlot = pairIndex * 2;
|
|
114
|
+
const endSlot = beginSlot + 1;
|
|
115
|
+
|
|
116
|
+
if (beginSlot >= firstQuery && beginSlot < firstQuery + queryCount) {
|
|
117
|
+
results[beginSlot - firstQuery] = 0n;
|
|
118
|
+
}
|
|
119
|
+
if (endSlot >= firstQuery && endSlot < firstQuery + queryCount) {
|
|
120
|
+
results[endSlot - firstQuery] = duration;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!this._occlusionQuery) {
|
|
128
|
+
throw new Error('Occlusion query has not been started');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return [await this._consumeQueryResult(this._occlusionQuery)];
|
|
66
132
|
}
|
|
67
133
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
134
|
+
async readTimestampDuration(beginIndex: number, endIndex: number): Promise<number> {
|
|
135
|
+
if (this.props.type !== 'timestamp') {
|
|
136
|
+
throw new Error('Timestamp durations require a timestamp QuerySet');
|
|
137
|
+
}
|
|
138
|
+
if (beginIndex < 0 || endIndex >= this.props.count || endIndex <= beginIndex) {
|
|
139
|
+
throw new Error('Timestamp duration range is out of bounds');
|
|
140
|
+
}
|
|
141
|
+
if (beginIndex % 2 !== 0 || endIndex !== beginIndex + 1) {
|
|
142
|
+
throw new Error('WebGL timestamp durations require adjacent even/odd query indices');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const result = await this._consumeTimestampPairResult(this._getTimestampPairIndex(beginIndex));
|
|
146
|
+
return Number(result) / 1e6;
|
|
71
147
|
}
|
|
72
148
|
|
|
73
|
-
|
|
74
|
-
this.
|
|
149
|
+
beginOcclusionQuery(): void {
|
|
150
|
+
if (this.props.type !== 'occlusion') {
|
|
151
|
+
throw new Error('Occlusion queries require an occlusion QuerySet');
|
|
152
|
+
}
|
|
153
|
+
if (!this.handle) {
|
|
154
|
+
throw new Error('WebGL occlusion query is not available');
|
|
155
|
+
}
|
|
156
|
+
if (this._occlusionActive) {
|
|
157
|
+
throw new Error('Occlusion query is already active');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.device.gl.beginQuery(GL.ANY_SAMPLES_PASSED, this.handle);
|
|
161
|
+
this._occlusionQuery = {
|
|
162
|
+
handle: this.handle,
|
|
163
|
+
promise: null,
|
|
164
|
+
result: null,
|
|
165
|
+
disjoint: false
|
|
166
|
+
};
|
|
167
|
+
this._occlusionActive = true;
|
|
75
168
|
}
|
|
76
169
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
170
|
+
endOcclusionQuery(): void {
|
|
171
|
+
if (!this._occlusionActive) {
|
|
172
|
+
throw new Error('Occlusion query is not active');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
this.device.gl.endQuery(GL.ANY_SAMPLES_PASSED);
|
|
176
|
+
this._occlusionActive = false;
|
|
80
177
|
}
|
|
81
178
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
179
|
+
writeTimestamp(queryIndex: number): void {
|
|
180
|
+
if (this.props.type !== 'timestamp') {
|
|
181
|
+
throw new Error('Timestamp writes require a timestamp QuerySet');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const pairIndex = this._getTimestampPairIndex(queryIndex);
|
|
185
|
+
const pair = this._timestampPairs[pairIndex];
|
|
186
|
+
|
|
187
|
+
if (queryIndex % 2 === 0) {
|
|
188
|
+
if (pair.activeQuery) {
|
|
189
|
+
throw new Error('Timestamp query pair is already active');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const handle = this.device.gl.createQuery();
|
|
193
|
+
if (!handle) {
|
|
194
|
+
throw new Error('WebGL query not supported');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const query: WebGLPendingQuery = {
|
|
198
|
+
handle,
|
|
199
|
+
promise: null,
|
|
200
|
+
result: null,
|
|
201
|
+
disjoint: false
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
this.device.gl.beginQuery(GL.TIME_ELAPSED_EXT, handle);
|
|
205
|
+
pair.activeQuery = query;
|
|
94
206
|
return;
|
|
95
207
|
}
|
|
96
208
|
|
|
97
|
-
|
|
98
|
-
|
|
209
|
+
if (!pair.activeQuery) {
|
|
210
|
+
throw new Error('Timestamp query pair was ended before it was started');
|
|
211
|
+
}
|
|
99
212
|
|
|
100
|
-
|
|
213
|
+
this.device.gl.endQuery(GL.TIME_ELAPSED_EXT);
|
|
214
|
+
pair.completedQueries.push(pair.activeQuery);
|
|
215
|
+
pair.activeQuery = null;
|
|
101
216
|
}
|
|
102
217
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (this._queryPending) {
|
|
107
|
-
return;
|
|
218
|
+
protected _validateRange(firstQuery: number, queryCount: number): void {
|
|
219
|
+
if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
|
|
220
|
+
throw new Error('Query read range is out of bounds');
|
|
108
221
|
}
|
|
222
|
+
}
|
|
109
223
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this._queryPending = true;
|
|
224
|
+
protected _getTimestampPairIndex(queryIndex: number): number {
|
|
225
|
+
if (queryIndex < 0 || queryIndex >= this.props.count) {
|
|
226
|
+
throw new Error('Query index is out of bounds');
|
|
114
227
|
}
|
|
115
|
-
|
|
228
|
+
|
|
229
|
+
return Math.floor(queryIndex / 2);
|
|
116
230
|
}
|
|
117
231
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (!
|
|
232
|
+
protected _isTimestampPairAvailable(pairIndex: number): boolean {
|
|
233
|
+
const pair = this._timestampPairs[pairIndex];
|
|
234
|
+
if (!pair || pair.completedQueries.length === 0) {
|
|
121
235
|
return false;
|
|
122
236
|
}
|
|
123
237
|
|
|
238
|
+
return this._pollQueryAvailability(pair.completedQueries[0]);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
protected _pollQueryAvailability(query: WebGLPendingQuery): boolean {
|
|
242
|
+
if (query.result !== null || query.disjoint) {
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
124
246
|
const resultAvailable = this.device.gl.getQueryParameter(
|
|
125
|
-
|
|
247
|
+
query.handle,
|
|
126
248
|
GL.QUERY_RESULT_AVAILABLE
|
|
127
249
|
);
|
|
128
|
-
if (resultAvailable) {
|
|
129
|
-
|
|
250
|
+
if (!resultAvailable) {
|
|
251
|
+
return false;
|
|
130
252
|
}
|
|
131
|
-
return resultAvailable;
|
|
132
|
-
}
|
|
133
253
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
254
|
+
const isDisjoint = Boolean(this.device.gl.getParameter(GL.GPU_DISJOINT_EXT));
|
|
255
|
+
query.disjoint = isDisjoint;
|
|
256
|
+
query.result = isDisjoint
|
|
257
|
+
? 0n
|
|
258
|
+
: BigInt(this.device.gl.getQueryParameter(query.handle, GL.QUERY_RESULT));
|
|
259
|
+
return true;
|
|
137
260
|
}
|
|
138
261
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
262
|
+
protected async _consumeTimestampPairResult(pairIndex: number): Promise<bigint> {
|
|
263
|
+
const pair = this._timestampPairs[pairIndex];
|
|
264
|
+
if (!pair || pair.completedQueries.length === 0) {
|
|
265
|
+
throw new Error('Timestamp query pair has no completed result');
|
|
266
|
+
}
|
|
143
267
|
|
|
144
|
-
|
|
145
|
-
getTimerMilliseconds() {
|
|
146
|
-
return this.getResult() / 1e6;
|
|
147
|
-
}
|
|
268
|
+
const query = pair.completedQueries.shift()!;
|
|
148
269
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
270
|
+
try {
|
|
271
|
+
return await this._consumeQueryResult(query);
|
|
272
|
+
} finally {
|
|
273
|
+
this.device.gl.deleteQuery(query.handle);
|
|
153
274
|
}
|
|
275
|
+
}
|
|
154
276
|
|
|
155
|
-
|
|
277
|
+
protected _consumeQueryResult(query: WebGLPendingQuery): Promise<bigint> {
|
|
278
|
+
if (query.promise) {
|
|
279
|
+
return query.promise;
|
|
280
|
+
}
|
|
156
281
|
|
|
157
|
-
|
|
282
|
+
query.promise = new Promise((resolve, reject) => {
|
|
158
283
|
const poll = () => {
|
|
159
|
-
if (this.
|
|
160
|
-
resolve(this.getResult());
|
|
161
|
-
this._pollingPromise = null;
|
|
162
|
-
} else if (counter++ > limit) {
|
|
163
|
-
reject('Timed out');
|
|
164
|
-
this._pollingPromise = null;
|
|
165
|
-
} else {
|
|
284
|
+
if (!this._pollQueryAvailability(query)) {
|
|
166
285
|
requestAnimationFrame(poll);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
query.promise = null;
|
|
290
|
+
if (query.disjoint) {
|
|
291
|
+
reject(new Error('GPU timestamp query was invalidated by a disjoint event'));
|
|
292
|
+
} else {
|
|
293
|
+
resolve(query.result || 0n);
|
|
167
294
|
}
|
|
168
295
|
};
|
|
169
296
|
|
|
170
|
-
|
|
297
|
+
poll();
|
|
171
298
|
});
|
|
172
299
|
|
|
173
|
-
return
|
|
300
|
+
return query.promise;
|
|
174
301
|
}
|
|
175
302
|
}
|
|
@@ -24,6 +24,12 @@ export class WEBGLRenderPass extends RenderPass {
|
|
|
24
24
|
super(device, props);
|
|
25
25
|
this.device = device;
|
|
26
26
|
|
|
27
|
+
if (!props?.framebuffer) {
|
|
28
|
+
// Default-framebuffer rendering bypasses CanvasContext.getCurrentFramebuffer(),
|
|
29
|
+
// so flush any deferred canvas resize before deriving viewport state.
|
|
30
|
+
device.getDefaultCanvasContext()._resizeDrawingBufferIfNeeded();
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// If no viewport is provided, apply reasonably defaults
|
|
28
34
|
let viewport: NumberArray4 | undefined;
|
|
29
35
|
if (!props?.parameters?.viewport) {
|
|
@@ -57,11 +63,24 @@ export class WEBGLRenderPass extends RenderPass {
|
|
|
57
63
|
|
|
58
64
|
// Hack - for now WebGL draws in "immediate mode" (instead of queueing the operations)...
|
|
59
65
|
this.clear();
|
|
66
|
+
|
|
67
|
+
if (this.props.timestampQuerySet && this.props.beginTimestampIndex !== undefined) {
|
|
68
|
+
const webglQuerySet = this.props.timestampQuerySet as WEBGLQuerySet;
|
|
69
|
+
webglQuerySet.writeTimestamp(this.props.beginTimestampIndex);
|
|
70
|
+
}
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
end(): void {
|
|
74
|
+
if (this.destroyed) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (this.props.timestampQuerySet && this.props.endTimestampIndex !== undefined) {
|
|
78
|
+
const webglQuerySet = this.props.timestampQuerySet as WEBGLQuerySet;
|
|
79
|
+
webglQuerySet.writeTimestamp(this.props.endTimestampIndex);
|
|
80
|
+
}
|
|
63
81
|
this.device.popState();
|
|
64
82
|
// should add commands to CommandEncoder.
|
|
83
|
+
this.destroy();
|
|
65
84
|
}
|
|
66
85
|
|
|
67
86
|
pushDebugGroup(groupLabel: string): void {}
|