@solidtv/renderer 1.4.1 → 1.5.0-0

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.
Files changed (37) hide show
  1. package/dist/src/core/Stage.js +2 -1
  2. package/dist/src/core/Stage.js.map +1 -1
  3. package/dist/src/core/lib/WebGlContextWrapper.d.ts +53 -3
  4. package/dist/src/core/lib/WebGlContextWrapper.js +96 -2
  5. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  6. package/dist/src/core/renderers/CoreRenderer.d.ts +37 -0
  7. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  8. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +2 -1
  9. package/dist/src/core/renderers/canvas/CanvasRenderer.js +10 -1
  10. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +1 -1
  11. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +10 -1
  12. package/dist/src/core/renderers/webgl/WebGlRenderer.js +20 -2
  13. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +1 -1
  14. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +22 -0
  15. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +61 -0
  16. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +1 -1
  17. package/dist/src/core/renderers/webgl/internal/RendererUtils.d.ts +1 -1
  18. package/dist/src/core/renderers/webgl/internal/RendererUtils.js +1 -0
  19. package/dist/src/core/renderers/webgl/internal/RendererUtils.js.map +1 -1
  20. package/dist/src/main-api/Renderer.d.ts +26 -0
  21. package/dist/src/main-api/Renderer.js +19 -0
  22. package/dist/src/main-api/Renderer.js.map +1 -1
  23. package/dist/src/utils.d.ts +1 -1
  24. package/dist/src/utils.js +2 -2
  25. package/dist/src/utils.js.map +1 -1
  26. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  27. package/package.json +1 -1
  28. package/src/core/Stage.ts +2 -0
  29. package/src/core/lib/WebGlContextWrapper.ts +103 -3
  30. package/src/core/renderers/CoreRenderer.ts +38 -0
  31. package/src/core/renderers/canvas/CanvasRenderer.test.ts +14 -0
  32. package/src/core/renderers/canvas/CanvasRenderer.ts +15 -1
  33. package/src/core/renderers/webgl/WebGlRenderer.ts +27 -2
  34. package/src/core/renderers/webgl/WebGlShaderProgram.ts +70 -0
  35. package/src/core/renderers/webgl/internal/RendererUtils.ts +5 -1
  36. package/src/main-api/Renderer.ts +32 -0
  37. package/src/utils.ts +2 -1
@@ -30,6 +30,19 @@ export class WebGlShaderProgram implements CoreShaderProgram {
30
30
  public isDestroyed = false;
31
31
  supportsIndexedTextures = false;
32
32
 
33
+ /**
34
+ * Cached Vertex Array Objects, keyed by the buffer collection they capture.
35
+ *
36
+ * @remarks
37
+ * A VAO records this program's attribute layout (enabled arrays, pointers and
38
+ * their source buffers) plus the shared element index buffer, so a draw only
39
+ * needs a single `bindVertexArray` instead of re-pointing every attribute. In
40
+ * practice a program only ever binds one collection, but keying by collection
41
+ * keeps it correct if that ever changes. Empty / unused when the context has
42
+ * no VAO support (see {@link WebGlContextWrapper.canUseVertexArrayObject}).
43
+ */
44
+ protected vaos = new Map<BufferCollection, WebGLVertexArrayObject | null>();
45
+
33
46
  constructor(
34
47
  renderer: WebGlRenderer,
35
48
  config: WebGlShaderType,
@@ -259,6 +272,30 @@ export class WebGlShaderProgram implements CoreShaderProgram {
259
272
 
260
273
  bindBufferCollection(buffer: BufferCollection) {
261
274
  const { glw } = this;
275
+
276
+ if (glw.canUseVertexArrayObject === true) {
277
+ let vao = this.vaos.get(buffer);
278
+ if (vao === undefined) {
279
+ // First draw with this collection: record the attribute layout into a
280
+ // VAO. createVao leaves the new VAO bound, so there's nothing more to do.
281
+ vao = this.createVao(buffer);
282
+ this.vaos.set(buffer, vao);
283
+ return;
284
+ }
285
+ glw.bindVertexArray(vao);
286
+ return;
287
+ }
288
+
289
+ // No VAO support: re-point every attribute on each draw.
290
+ this.bindAttributes(buffer);
291
+ }
292
+
293
+ /**
294
+ * Point this program's vertex attributes at the given buffer collection.
295
+ * When a VAO is bound this records into it; otherwise it mutates global state.
296
+ */
297
+ private bindAttributes(buffer: BufferCollection) {
298
+ const { glw } = this;
262
299
  const attribs = this.attributeLocations;
263
300
  const attribLen = attribs.length;
264
301
 
@@ -282,6 +319,25 @@ export class WebGlShaderProgram implements CoreShaderProgram {
282
319
  }
283
320
  }
284
321
 
322
+ /**
323
+ * Create and populate a Vertex Array Object capturing this program's
324
+ * attribute layout for the given buffer collection. The new VAO is left bound.
325
+ */
326
+ private createVao(buffer: BufferCollection): WebGLVertexArrayObject | null {
327
+ const { glw } = this;
328
+ const vao = glw.createVertexArray();
329
+ glw.bindVertexArray(vao);
330
+
331
+ this.bindAttributes(buffer);
332
+
333
+ // The element-array binding is part of VAO state and starts out null on a
334
+ // fresh VAO, so record the shared index buffer into it or indexed
335
+ // drawElements would read from no buffer.
336
+ glw.bindElementArrayBuffer(this.renderer.indexBuffer);
337
+
338
+ return vao;
339
+ }
340
+
285
341
  bindTextures(textures: WebGlCtxTexture[]) {
286
342
  const t = textures[0];
287
343
  if (t === undefined) {
@@ -299,6 +355,13 @@ export class WebGlShaderProgram implements CoreShaderProgram {
299
355
  }
300
356
 
301
357
  detach(): void {
358
+ // With VAOs the enabled-attribute state lives in each per-collection VAO,
359
+ // not in global context state. Disabling here would mutate whichever VAO is
360
+ // currently bound and corrupt it for the next draw, so there's nothing to
361
+ // do on a program switch.
362
+ if (this.glw.canUseVertexArrayObject === true) {
363
+ return;
364
+ }
302
365
  this.disableAttributes();
303
366
  }
304
367
 
@@ -310,6 +373,13 @@ export class WebGlShaderProgram implements CoreShaderProgram {
310
373
 
311
374
  this.detach();
312
375
 
376
+ for (const vao of this.vaos.values()) {
377
+ if (vao !== null) {
378
+ glw.deleteVertexArray(vao);
379
+ }
380
+ }
381
+ this.vaos.clear();
382
+
313
383
  glw.deleteProgram(this.program!);
314
384
  this.program = null;
315
385
  this.uniformLocations = null;
@@ -7,7 +7,10 @@ import type { WebGlContextWrapper } from '../../../lib/WebGlContextWrapper.js';
7
7
  * @param glw
8
8
  * @param size
9
9
  */
10
- export function createIndexBuffer(glw: WebGlContextWrapper, size: number) {
10
+ export function createIndexBuffer(
11
+ glw: WebGlContextWrapper,
12
+ size: number,
13
+ ): WebGLBuffer | null {
11
14
  const maxQuads = ~~(size / 80);
12
15
  const indices = new Uint16Array(maxQuads * 6);
13
16
 
@@ -22,6 +25,7 @@ export function createIndexBuffer(glw: WebGlContextWrapper, size: number) {
22
25
 
23
26
  const buffer = glw.createBuffer();
24
27
  glw.elementArrayBufferData(buffer, indices, glw.STATIC_DRAW);
28
+ return buffer;
25
29
  }
26
30
 
27
31
  /**
@@ -14,6 +14,7 @@ import type { CanvasRenderer } from '../core/renderers/canvas/CanvasRenderer.js'
14
14
  import type { WebGlRenderer } from '../core/renderers/webgl/WebGlRenderer.js';
15
15
  import type { Inspector, InspectorOptions } from './Inspector.js';
16
16
  import type { CoreShaderNode } from '../core/renderers/CoreShaderNode.js';
17
+ import type { RendererCapabilities } from '../core/renderers/CoreRenderer.js';
17
18
  import type {
18
19
  ExtractShaderProps,
19
20
  OptionalShaderProps,
@@ -514,6 +515,17 @@ export type RendererMainSettings = RendererRuntimeSettings & {
514
515
  */
515
516
  textBaselineMode: TextBaselineMode;
516
517
 
518
+ /**
519
+ * Force WebGL2
520
+ *
521
+ * @remarks
522
+ * Force the renderer to use WebGL2. This can be used to force the renderer to
523
+ * use WebGL2 even if the browser supports WebGL1.
524
+ *
525
+ * @defaultValue `false`
526
+ */
527
+ forceWebGL2: boolean;
528
+
517
529
  /**
518
530
  * Canvas object to use for rendering
519
531
  *
@@ -688,6 +700,7 @@ export class RendererMain extends EventEmitter {
688
700
  numImageWorkers:
689
701
  settings.numImageWorkers !== undefined ? settings.numImageWorkers : 2,
690
702
  enableContextSpy: settings.enableContextSpy ?? false,
703
+ forceWebGL2: settings.forceWebGL2 ?? false,
691
704
  inspector: settings.inspector ?? false,
692
705
  inspectorOptions: settings.inspectorOptions ?? {},
693
706
  renderEngine: settings.renderEngine,
@@ -749,6 +762,7 @@ export class RendererMain extends EventEmitter {
749
762
  deviceLogicalPixelRatio,
750
763
  devicePhysicalPixelRatio,
751
764
  enableContextSpy: settings.enableContextSpy!,
765
+ forceWebGL2: settings.forceWebGL2!,
752
766
  fpsUpdateInterval: settings.fpsUpdateInterval!,
753
767
  enableClear: settings.enableClear!,
754
768
  numImageWorkers: settings.numImageWorkers!,
@@ -1022,6 +1036,24 @@ export class RendererMain extends EventEmitter {
1022
1036
  return this.stage.renderer.getBufferInfo();
1023
1037
  }
1024
1038
 
1039
+ /**
1040
+ * Report the active rendering backend and device capabilities.
1041
+ *
1042
+ * @remarks
1043
+ * Useful for diagnostics and field logging — e.g. confirming which WebGL
1044
+ * version a device negotiated and whether Vertex Array Objects engaged.
1045
+ * Reads live GL parameters (CPU↔GPU round-trips), so call once at startup
1046
+ * rather than per frame.
1047
+ *
1048
+ * @example
1049
+ * ```ts
1050
+ * console.table(renderer.getCapabilities());
1051
+ * ```
1052
+ */
1053
+ getCapabilities(): RendererCapabilities {
1054
+ return this.stage.renderer.getCapabilities();
1055
+ }
1056
+
1025
1057
  /**
1026
1058
  * Re-render the current frame without advancing any running animations.
1027
1059
  *
package/src/utils.ts CHANGED
@@ -2,6 +2,7 @@ import type { ContextSpy } from './core/lib/ContextSpy.js';
2
2
 
3
3
  export function createWebGLContext(
4
4
  canvas: HTMLCanvasElement | OffscreenCanvas,
5
+ forceWebGL2 = false,
5
6
  contextSpy: ContextSpy | null,
6
7
  ): WebGLRenderingContext {
7
8
  const config: WebGLContextAttributes = {
@@ -19,7 +20,7 @@ export function createWebGLContext(
19
20
  const gl =
20
21
  // TODO: Remove this assertion once this issue is fixed in TypeScript
21
22
  // https://github.com/microsoft/TypeScript/issues/53614
22
- (canvas.getContext('webgl', config) ||
23
+ (canvas.getContext(forceWebGL2 ? 'webgl2' : 'webgl', config) ||
23
24
  canvas.getContext(
24
25
  'experimental-webgl' as 'webgl',
25
26
  config,