@swf2es/render 0.1.7 → 0.1.10

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.
@@ -13,6 +13,8 @@ export declare const ORIGIN_AT = 4;
13
13
  export declare const GLYPH_AT = 5;
14
14
  export declare const RUN_AT = 6;
15
15
  export declare const TINT_AT = 7;
16
+ /** A merged fill's packed row, in the streaming vertex buffer. */
17
+ export declare const DRAW_AT = 8;
16
18
  /** The most cutoff table entries a text's draw takes, as the player's text/saffron.ts builds them. */
17
19
  export declare const TABLE_ENTRIES = 48;
18
20
  /** Segments a row of the outlines' texture, as the player's text/saffron.ts stores them. */
@@ -51,7 +53,8 @@ export declare const RUN_UNIT: number;
51
53
  * space), and passes on its straight colour, the row's colour transform
52
54
  * and the texture it samples. uRow names the draw's row (FILL_SLOT); with
53
55
  * `multi` (WEBGL_multi_draw), uRunTable names each draw's of a multi-draw by
54
- * gl_DrawID, which is 0 in a draw of its own.
56
+ * gl_DrawID, which is 0 in a draw of its own. Merged fills supply the packed
57
+ * row as aDraw; the atlas leaves that attribute disabled and negative.
55
58
  */
56
59
  export declare const fillVertex: (multi: boolean) => string;
57
60
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"programs.d.ts","sourceRoot":"","sources":["../../src/webgl/programs.ts"],"names":[],"mappings":"AAkBA,2CAA2C;AAC3C,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B;;;GAGG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,oGAAoG;AACpG,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,MAAM,IAAI,CAAC;AACxB,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB,sGAAsG;AACtG,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,4FAA4F;AAC5F,eAAO,MAAM,WAAW,OAAO,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,qFAAqF;AACrF,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,QAAQ,QAAU,CAAC;AAEhC,sGAAsG;AACtG,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,oEAAoE;AACpE,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,0FAA0F;AAC1F,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,uFAAuF;AACvF,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,+DAA+D;AAC/D,eAAO,MAAM,QAAQ,QAA4B,CAAC;AAElD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,UAAW,OAAO,WAkCxC,CAAC;AAiBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAkCxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,QAsBtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,0qEAqExB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,QAmGxB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,QAwD1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,wPAO3B,CAAC;AAeF,kHAAkH;AAClH,eAAO,MAAM,WAAW,QAAqB,CAAC;AAuD9C;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,QAmB7B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QA0C7B,CAAC"}
1
+ {"version":3,"file":"programs.d.ts","sourceRoot":"","sources":["../../src/webgl/programs.ts"],"names":[],"mappings":"AAkBA,2CAA2C;AAC3C,eAAO,MAAM,UAAU,IAAI,CAAC;AAE5B;;;GAGG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,oGAAoG;AACpG,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,MAAM,IAAI,CAAC;AACxB,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,kEAAkE;AAClE,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB,sGAAsG;AACtG,eAAO,MAAM,aAAa,KAAK,CAAC;AAChC,4FAA4F;AAC5F,eAAO,MAAM,WAAW,OAAO,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,qFAAqF;AACrF,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,QAAQ,QAAU,CAAC;AAEhC,sGAAsG;AACtG,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,oEAAoE;AACpE,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,0FAA0F;AAC1F,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,uFAAuF;AACvF,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,+DAA+D;AAC/D,eAAO,MAAM,QAAQ,QAA4B,CAAC;AAElD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,UAAW,OAAO,WAkCxC,CAAC;AAiBF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAkCxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,QAsBtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,0qEAqExB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,QAmGxB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,QAwD1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,wPAO3B,CAAC;AAeF,kHAAkH;AAClH,eAAO,MAAM,WAAW,QAAqB,CAAC;AAuD9C;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,QAmB7B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QA0C7B,CAAC"}
@@ -15,6 +15,8 @@ export const ORIGIN_AT = 4;
15
15
  export const GLYPH_AT = 5;
16
16
  export const RUN_AT = 6;
17
17
  export const TINT_AT = 7;
18
+ /** A merged fill's packed row, in the streaming vertex buffer. */
19
+ export const DRAW_AT = 8;
18
20
  /** The most cutoff table entries a text's draw takes, as the player's text/saffron.ts builds them. */
19
21
  export const TABLE_ENTRIES = 48;
20
22
  /** Segments a row of the outlines' texture, as the player's text/saffron.ts stores them. */
@@ -53,7 +55,8 @@ export const RUN_UNIT = FILL_UNIT + FILL_TEXTURES;
53
55
  * space), and passes on its straight colour, the row's colour transform
54
56
  * and the texture it samples. uRow names the draw's row (FILL_SLOT); with
55
57
  * `multi` (WEBGL_multi_draw), uRunTable names each draw's of a multi-draw by
56
- * gl_DrawID, which is 0 in a draw of its own.
58
+ * gl_DrawID, which is 0 in a draw of its own. Merged fills supply the packed
59
+ * row as aDraw; the atlas leaves that attribute disabled and negative.
57
60
  */
58
61
  export const fillVertex = (multi) => `#version 300 es
59
62
  ${multi ? "#extension GL_ANGLE_multi_draw : require" : ""}
@@ -62,7 +65,7 @@ layout(location = ${POSITION_AT}) in vec2 aPosition;
62
65
  layout(location = ${TEXEL_AT}) in vec2 aTexel;
63
66
  layout(location = ${COLOR_AT}) in vec4 aColor;
64
67
  uniform highp sampler2D uRows;
65
- ${multi ? "uniform highp isampler2D uRunTable;\nuniform int uRunBase;" : "uniform int uRow;"}
68
+ ${multi ? `layout(location = ${DRAW_AT}) in int aDraw;\nuniform highp isampler2D uRunTable;\nuniform int uRunBase;` : "uniform int uRow;"}
66
69
  uniform vec4 uView;
67
70
  uniform float uUnit;
68
71
  out vec4 vColor;
@@ -72,7 +75,7 @@ flat out vec4 vAdd;
72
75
  flat out int vSlot;
73
76
 
74
77
  void main(void) {
75
- int draw = ${multi ? `texelFetch(uRunTable, ivec2((uRunBase + gl_DrawID) & ${RUN_MOST - 1}, (uRunBase + gl_DrawID) >> ${Math.log2(RUN_MOST)}), 0).r` : "uRow"};
78
+ int draw = ${multi ? `aDraw >= 0 ? aDraw : texelFetch(uRunTable, ivec2((uRunBase + gl_DrawID) & ${RUN_MOST - 1}, (uRunBase + gl_DrawID) >> ${Math.log2(RUN_MOST)}), 0).r` : "uRow"};
76
79
  int row = draw & ${(1 << FILL_SLOT) - 1};
77
80
  vSlot = (draw >> ${FILL_SLOT}) & 15;
78
81
  ivec2 at = ivec2((row & ${ROWS_A_LINE - 1}) * ${ROW_TEXELS}, row >> ${Math.log2(ROWS_A_LINE)});
@@ -1 +1 @@
1
- {"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/webgl/programs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/webgl/programs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swf2es/render",
3
- "version": "0.1.7",
3
+ "version": "0.1.10",
4
4
  "description": "swf2es's own renderer: a scene list, a planner and a WebGL 2 backend (docs/renderer.md)",
5
5
  "keywords": [
6
6
  "swf",
@@ -33,6 +33,6 @@
33
33
  "src"
34
34
  ],
35
35
  "dependencies": {
36
- "@swf2es/context3d": "0.1.7"
36
+ "@swf2es/context3d": "0.1.10"
37
37
  }
38
38
  }
@@ -34,6 +34,8 @@ export interface Place {
34
34
  glyphs: { mode: Float32Array; table: Float32Array } | null;
35
35
  /** Its geometry's flat (GeometryData.flat). */
36
36
  flat: boolean;
37
+ /** Small, unchanged geometries may be copied into a run's streaming buffer. */
38
+ batch: { data: GeometryData; frame: number } | null;
37
39
  }
38
40
 
39
41
  /**
@@ -44,6 +46,7 @@ export interface Place {
44
46
  * holes outweigh what is live.
45
47
  */
46
48
  export class GeometryAtlas {
49
+ frame = 0;
47
50
  private readonly gl: WebGL2RenderingContext;
48
51
  private readonly state: GlState;
49
52
  vertexArray!: WebGLVertexArrayObject;
@@ -129,6 +132,7 @@ export class GeometryAtlas {
129
132
  * grown to twice what is live.
130
133
  */
131
134
  place(geometries: Geometries): void {
135
+ this.frame++;
132
136
  for (const id of geometries.removed) {
133
137
  const place = this.places[id];
134
138
  if (place?.glyphs) {
@@ -149,6 +153,7 @@ export class GeometryAtlas {
149
153
  const data = geometries.get(id);
150
154
  if (place && data && !data.glyphs && place.vertices === data.positions.length / 2) {
151
155
  this.copyVertices(data, place.vertexStart);
156
+ place.batch = this.batch(data);
152
157
  } else if (place && data) {
153
158
  this.places[id] = null;
154
159
  if (place.glyphs) {
@@ -298,6 +303,7 @@ export class GeometryAtlas {
298
303
  indices: indices.length,
299
304
  glyphs: null,
300
305
  flat: data.flat === true,
306
+ batch: this.batch(data),
301
307
  };
302
308
  this.vertexTop += count;
303
309
  this.indexTop += indices.length;
@@ -329,6 +335,12 @@ export class GeometryAtlas {
329
335
  gl.bufferSubData(gl.ARRAY_BUFFER, base * VERTEX_BYTES, floats);
330
336
  }
331
337
 
338
+ private batch(data: GeometryData): Place["batch"] {
339
+ return data.positions.length <= 512 && data.indices.length <= 1024 && !data.depths
340
+ ? { data, frame: this.frame }
341
+ : null;
342
+ }
343
+
332
344
  /** Glyph quads copied in at the top of the glyph atlas, their indices made absolute in it. */
333
345
  private copyGlyphs(id: number, data: GeometryData): void {
334
346
  const gl = this.gl;
@@ -351,6 +363,7 @@ export class GeometryAtlas {
351
363
  indices: indices.length,
352
364
  glyphs: { mode: glyphs.mode, table: glyphs.table },
353
365
  flat: false,
366
+ batch: null,
354
367
  };
355
368
  g.top += count;
356
369
  g.indexTop += indices.length;
@@ -263,7 +263,6 @@ export class WebGLBackend {
263
263
  state.scissor(null);
264
264
  state.colorMask(15);
265
265
  state.useProgram(this.draws.program);
266
- state.bindVertexArray(this.atlas.vertexArray);
267
266
  state.bindTexture(0, this.gpu.rowsTexture);
268
267
  // As many samples as the GPU takes; a BitmapData's frame supersamples instead, as Flash's draw
269
268
  // does. Its layers take the stage's, so that their edges are the stage's.
@@ -0,0 +1,344 @@
1
+ import type { GlState } from "@swf2es/context3d/device";
2
+ import type { Place } from "./atlas.js";
3
+ import { COLOR_AT, DRAW_AT, POSITION_AT, TEXEL_AT } from "./programs.js";
4
+
5
+ /** Atlas attributes followed by the packed row: transforms and snapping stay in the shader. */
6
+ const WORDS = 6;
7
+ /** Bound the extra CPU and GPU storage, falling back to the atlas after it fills. */
8
+ const VERTICES_MOST = 2 << 20;
9
+ const INDICES_MOST = 6 << 20;
10
+ /** The least room the GPU buffers and the staging keep, which shrinking stops at. */
11
+ const VERTICES_LEAST = 1 << 14;
12
+ const INDICES_LEAST = 3 << 14;
13
+ /** Frames over which the most used is watched; room four times that is let go of after them. */
14
+ const SHRINK_FRAMES = 240;
15
+
16
+ /**
17
+ * Small stable geometries merged in painter's order; unchanged streams reuse
18
+ * their GPU buffers. Only what changed since the last frame, from the first
19
+ * draw that differs to the stream's end, is staged on the CPU and uploaded
20
+ * where it lies: the stream before it stays on the GPU alone, and a buffer
21
+ * grown keeps it by a copy there.
22
+ */
23
+ export class FillBatches {
24
+ vertexArray!: WebGLVertexArrayObject;
25
+ private vertexBuffer!: WebGLBuffer;
26
+ private indexBuffer!: WebGLBuffer;
27
+ /** The staged words, the same bytes as floats, and indices: the stream from fromVertex and fromIndex. */
28
+ private words = new Uint32Array(0);
29
+ private floats = new Float32Array(0);
30
+ private indices = new Uint32Array(0);
31
+ private vertexCapacity = 0;
32
+ private indexCapacity = 0;
33
+ private vertexTop = 0;
34
+ indexTop = 0;
35
+ /** Where this frame's staging starts in the stream: the first draw that differs from the last frame's. */
36
+ private fromVertex = 0;
37
+ private fromIndex = 0;
38
+ private readonly previous: NonNullable<Place["batch"]>[] = [];
39
+ private readonly previousRows: number[] = [];
40
+ private cursor = 0;
41
+ /** Stays dirty if preparation aborts before upload, as an overflowing run table can do. */
42
+ private changed = false;
43
+ /** The frames of the current watch, and the most of the stream and of the staging they used. */
44
+ private frames = 0;
45
+ private mostVertices = 0;
46
+ private mostIndices = 0;
47
+ private mostStaged = 0;
48
+ private mostStagedIndices = 0;
49
+
50
+ constructor(
51
+ private readonly gl: WebGL2RenderingContext,
52
+ private readonly state: GlState,
53
+ ) {}
54
+
55
+ setUp(): void {
56
+ const gl = this.gl;
57
+ this.vertexArray = gl.createVertexArray() as WebGLVertexArrayObject;
58
+ this.vertexBuffer = gl.createBuffer() as WebGLBuffer;
59
+ this.indexBuffer = gl.createBuffer() as WebGLBuffer;
60
+ this.state.bindVertexArray(this.vertexArray);
61
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
62
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
63
+ gl.enableVertexAttribArray(POSITION_AT);
64
+ gl.vertexAttribPointer(POSITION_AT, 2, gl.FLOAT, false, WORDS * 4, 0);
65
+ gl.enableVertexAttribArray(TEXEL_AT);
66
+ gl.vertexAttribPointer(TEXEL_AT, 2, gl.FLOAT, false, WORDS * 4, 8);
67
+ gl.enableVertexAttribArray(COLOR_AT);
68
+ gl.vertexAttribPointer(COLOR_AT, 4, gl.UNSIGNED_BYTE, true, WORDS * 4, 16);
69
+ gl.enableVertexAttribArray(DRAW_AT);
70
+ gl.vertexAttribIPointer(DRAW_AT, 1, gl.INT, WORDS * 4, 20);
71
+ // Disabled in the atlas VAO: a negative attribute selects the existing run-table path.
72
+ gl.vertexAttribI4i(DRAW_AT, -1, 0, 0, 0);
73
+ this.vertexCapacity = 0;
74
+ this.indexCapacity = 0;
75
+ this.previous.length = 0;
76
+ this.previousRows.length = 0;
77
+ this.changed = false;
78
+ this.reset();
79
+ }
80
+
81
+ reset(): void {
82
+ this.vertexTop = 0;
83
+ this.indexTop = 0;
84
+ this.cursor = 0;
85
+ // A preparation that aborted left the whole stream to stage again.
86
+ this.fromVertex = 0;
87
+ this.fromIndex = 0;
88
+ }
89
+
90
+ /** Append the whole run, or leave it to multi-draw if copying would cost too much. */
91
+ add(places: Place[], rows: Int32Array, count: number, frame: number): void {
92
+ if (count < 32) {
93
+ return;
94
+ }
95
+
96
+ let vertices = this.vertexTop;
97
+ let indices = this.indexTop;
98
+ for (let i = 0; i < count; i++) {
99
+ const place = places[i];
100
+ if (!place.batch || place.batch.frame === frame) {
101
+ return;
102
+ }
103
+
104
+ vertices += place.vertices;
105
+ indices += place.indices;
106
+ }
107
+
108
+ if (vertices > VERTICES_MOST || indices > INDICES_MOST) {
109
+ return;
110
+ }
111
+
112
+ for (let i = 0; i < count; i++) {
113
+ const place = places[i];
114
+ const batch = place.batch as NonNullable<Place["batch"]>;
115
+ // An unchanged prefix has the same offsets. After a mismatch, stage the rest in order.
116
+ if (
117
+ !this.changed &&
118
+ (this.previous[this.cursor] !== batch || this.previousRows[this.cursor] !== rows[i])
119
+ ) {
120
+ this.changed = true;
121
+ this.fromVertex = this.vertexTop;
122
+ this.fromIndex = this.indexTop;
123
+ }
124
+
125
+ this.previous[this.cursor] = batch;
126
+ this.previousRows[this.cursor++] = rows[i];
127
+ if (!this.changed) {
128
+ this.vertexTop += place.vertices;
129
+ this.indexTop += place.indices;
130
+ continue;
131
+ }
132
+
133
+ this.stageRoom(vertices - this.fromVertex, indices - this.fromIndex);
134
+ const data = batch.data;
135
+ const base = this.vertexTop;
136
+ const floats = this.floats;
137
+ const words = this.words;
138
+ for (let j = 0; j < place.vertices; j++) {
139
+ const at = (base - this.fromVertex + j) * WORDS;
140
+ floats[at] = data.positions[j * 2];
141
+ floats[at + 1] = data.positions[j * 2 + 1];
142
+ floats[at + 2] = data.texels ? data.texels[j * 2] : 0;
143
+ floats[at + 3] = data.texels ? data.texels[j * 2 + 1] : 0;
144
+ words[at + 4] = data.colors[j];
145
+ words[at + 5] = rows[i];
146
+ }
147
+
148
+ const staged = this.indices;
149
+ let at = this.indexTop - this.fromIndex;
150
+ for (let j = 0; j < place.indices; j++) {
151
+ staged[at++] = base + data.indices[j];
152
+ }
153
+
154
+ this.vertexTop += place.vertices;
155
+ this.indexTop += place.indices;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * The staged part of the stream uploaded where it lies, the buffers grown
161
+ * to fit it first, keeping what is before it; and, once a watch of
162
+ * SHRINK_FRAMES has used a quarter of the room or less, the buffers and
163
+ * the staging made smaller.
164
+ */
165
+ upload(): void {
166
+ this.previous.length = this.cursor;
167
+ this.previousRows.length = this.cursor;
168
+ const staging = this.changed && this.indexTop > 0;
169
+ if (staging) {
170
+ this.uploadStaged();
171
+ }
172
+
173
+ this.watch(staging);
174
+ }
175
+
176
+ /** What add staged uploaded where it lies, the buffers grown first to fit the stream. */
177
+ private uploadStaged(): void {
178
+ const gl = this.gl;
179
+ this.state.bindVertexArray(this.vertexArray);
180
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
181
+ if (this.vertexTop > this.vertexCapacity) {
182
+ this.vertexCapacity = Math.min(
183
+ VERTICES_MOST,
184
+ Math.max(this.vertexTop, this.vertexCapacity * 2),
185
+ );
186
+ this.resize(
187
+ gl.ARRAY_BUFFER,
188
+ this.vertexBuffer,
189
+ this.vertexCapacity * WORDS * 4,
190
+ this.fromVertex * WORDS * 4,
191
+ );
192
+ }
193
+
194
+ if (this.indexTop > this.indexCapacity) {
195
+ this.indexCapacity = Math.min(INDICES_MOST, Math.max(this.indexTop, this.indexCapacity * 2));
196
+ this.resize(
197
+ gl.ELEMENT_ARRAY_BUFFER,
198
+ this.indexBuffer,
199
+ this.indexCapacity * 4,
200
+ this.fromIndex * 4,
201
+ );
202
+ }
203
+
204
+ gl.bufferSubData(
205
+ gl.ARRAY_BUFFER,
206
+ this.fromVertex * WORDS * 4,
207
+ this.words,
208
+ 0,
209
+ (this.vertexTop - this.fromVertex) * WORDS,
210
+ );
211
+ gl.bufferSubData(
212
+ gl.ELEMENT_ARRAY_BUFFER,
213
+ this.fromIndex * 4,
214
+ this.indices,
215
+ 0,
216
+ this.indexTop - this.fromIndex,
217
+ );
218
+ this.changed = false;
219
+ }
220
+
221
+ destroy(): void {
222
+ this.gl.deleteVertexArray(this.vertexArray);
223
+ this.gl.deleteBuffer(this.vertexBuffer);
224
+ this.gl.deleteBuffer(this.indexBuffer);
225
+ this.words = new Uint32Array(0);
226
+ this.floats = new Float32Array(0);
227
+ this.indices = new Uint32Array(0);
228
+ }
229
+
230
+ /** Staging for at least `vertices` and `indices` from its start, what is staged kept. */
231
+ private stageRoom(vertices: number, indices: number): void {
232
+ if (vertices * WORDS > this.words.length) {
233
+ const grown = new Uint32Array(
234
+ Math.min(VERTICES_MOST * WORDS, Math.max(vertices * WORDS, this.words.length * 2)),
235
+ );
236
+ grown.set(this.words);
237
+ this.words = grown;
238
+ this.floats = new Float32Array(grown.buffer);
239
+ }
240
+
241
+ if (indices > this.indices.length) {
242
+ const grown = new Uint32Array(
243
+ Math.min(INDICES_MOST, Math.max(indices, this.indices.length * 2)),
244
+ );
245
+ grown.set(this.indices);
246
+ this.indices = grown;
247
+ }
248
+ }
249
+
250
+ /**
251
+ * A frame's use counted, after its upload; at a watch's end, room four
252
+ * times what it used at most let go of: the GPU buffers keep the stream,
253
+ * all of it there now, and the staging, whose bytes matter only between
254
+ * add and upload, is made anew.
255
+ */
256
+ private watch(staging: boolean): void {
257
+ this.mostVertices = Math.max(this.mostVertices, this.vertexTop);
258
+ this.mostIndices = Math.max(this.mostIndices, this.indexTop);
259
+ if (staging) {
260
+ this.mostStaged = Math.max(this.mostStaged, this.vertexTop - this.fromVertex);
261
+ this.mostStagedIndices = Math.max(this.mostStagedIndices, this.indexTop - this.fromIndex);
262
+ }
263
+
264
+ if (++this.frames < SHRINK_FRAMES) {
265
+ return;
266
+ }
267
+
268
+ const gl = this.gl;
269
+ // With nothing uploaded for a change, as for a stream of no draws, nothing on the GPU is kept.
270
+ const kept = !this.changed;
271
+ const keepVertices = kept ? this.vertexTop : 0;
272
+ const keepIndices = kept ? this.indexTop : 0;
273
+ const vertices = Math.max(VERTICES_LEAST, this.mostVertices * 2);
274
+ if (this.mostVertices * 4 <= this.vertexCapacity && vertices < this.vertexCapacity) {
275
+ this.state.bindVertexArray(this.vertexArray);
276
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
277
+ this.vertexCapacity = vertices;
278
+ this.resize(
279
+ gl.ARRAY_BUFFER,
280
+ this.vertexBuffer,
281
+ vertices * WORDS * 4,
282
+ keepVertices * WORDS * 4,
283
+ );
284
+ }
285
+
286
+ const indices = Math.max(INDICES_LEAST, this.mostIndices * 2);
287
+ if (this.mostIndices * 4 <= this.indexCapacity && indices < this.indexCapacity) {
288
+ this.state.bindVertexArray(this.vertexArray);
289
+ this.indexCapacity = indices;
290
+ this.resize(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer, indices * 4, keepIndices * 4);
291
+ }
292
+
293
+ const staged = Math.max(VERTICES_LEAST, this.mostStaged * 2) * WORDS;
294
+ if (this.mostStaged * 4 * WORDS <= this.words.length && staged < this.words.length) {
295
+ this.words = new Uint32Array(staged);
296
+ this.floats = new Float32Array(this.words.buffer);
297
+ }
298
+
299
+ const stagedIndices = Math.max(INDICES_LEAST, this.mostStagedIndices * 2);
300
+ if (this.mostStagedIndices * 4 <= this.indices.length && stagedIndices < this.indices.length) {
301
+ this.indices = new Uint32Array(stagedIndices);
302
+ }
303
+
304
+ this.frames = 0;
305
+ this.mostVertices = 0;
306
+ this.mostIndices = 0;
307
+ this.mostStaged = 0;
308
+ this.mostStagedIndices = 0;
309
+ }
310
+
311
+ /**
312
+ * `buffer`, bound to `target` (the index buffer through this VAO), made
313
+ * `bytes` long, its first `keep` bytes kept by copies on the GPU, through
314
+ * a buffer of their own, as a new store loses the old one's.
315
+ */
316
+ private resize(target: number, buffer: WebGLBuffer, bytes: number, keep: number): void {
317
+ const gl = this.gl;
318
+ if (keep <= 0) {
319
+ gl.bufferData(target, bytes, gl.DYNAMIC_DRAW);
320
+ return;
321
+ }
322
+
323
+ const copy = gl.createBuffer() as WebGLBuffer;
324
+ if (target === gl.ELEMENT_ARRAY_BUFFER) {
325
+ // WebGL copies only between buffers of one kind: the copy becomes an index buffer by a
326
+ // binding as one, outside this VAO, whose own it would replace.
327
+ this.state.bindVertexArray(null);
328
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, copy);
329
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
330
+ this.state.bindVertexArray(this.vertexArray);
331
+ }
332
+
333
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, copy);
334
+ gl.bufferData(gl.COPY_WRITE_BUFFER, keep, gl.STREAM_COPY);
335
+ gl.bindBuffer(gl.COPY_READ_BUFFER, buffer);
336
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, keep);
337
+ gl.bufferData(target, bytes, gl.DYNAMIC_DRAW);
338
+ gl.bindBuffer(gl.COPY_READ_BUFFER, copy);
339
+ gl.copyBufferSubData(gl.COPY_READ_BUFFER, target, 0, 0, keep);
340
+ gl.bindBuffer(gl.COPY_READ_BUFFER, null);
341
+ gl.bindBuffer(gl.COPY_WRITE_BUFFER, null);
342
+ gl.deleteBuffer(copy);
343
+ }
344
+ }
@@ -16,6 +16,7 @@ import {
16
16
  SNAP,
17
17
  } from "../scene.js";
18
18
  import type { GeometryAtlas, Place } from "./atlas.js";
19
+ import { FillBatches } from "./batches.js";
19
20
  import { setModeBlend } from "./composite.js";
20
21
  import type { GpuTextures } from "./gpu-textures.js";
21
22
  import type { KernelHost, KernelPrograms } from "./kernels.js";
@@ -52,8 +53,8 @@ interface MultiDraw {
52
53
  ): void;
53
54
  }
54
55
 
55
- /** Last scene entry, table start, draw count, used units, then each unit's texture and sampling. */
56
- const RUN_STRIDE = 4 + FILL_TEXTURES * 2;
56
+ /** Last entry, table start, draws, units, batch start/count, then each unit's texture and sampling. */
57
+ const RUN_STRIDE = 6 + FILL_TEXTURES * 2;
57
58
 
58
59
  /** The most masks the stencil's eight bits count. */
59
60
  const STENCIL_MOST = 255;
@@ -79,6 +80,7 @@ export class Draws {
79
80
  private readonly gl: WebGL2RenderingContext;
80
81
  private readonly state: GlState;
81
82
  private readonly atlas: GeometryAtlas;
83
+ private readonly batches: FillBatches;
82
84
  private readonly gpu: GpuTextures;
83
85
  private readonly pool: TargetPool;
84
86
  /** The fill program, and where it takes its row, view and Flash's pixels a stage pixel. */
@@ -116,6 +118,7 @@ export class Draws {
116
118
  private readonly runCounts = new Int32Array(RUN_MOST);
117
119
  private readonly runOffsets = new Int32Array(RUN_MOST);
118
120
  private readonly runRows = new Int32Array(RUN_MOST);
121
+ private readonly runPlaces: Place[] = [];
119
122
  /** Draws gathered by gatherRun, and the fill units they sample, a bit each. */
120
123
  private runCount = 0;
121
124
  private runUnits = 0;
@@ -185,6 +188,7 @@ export class Draws {
185
188
  this.gl = gl;
186
189
  this.state = state;
187
190
  this.atlas = atlas;
191
+ this.batches = new FillBatches(gl, state);
188
192
  this.gpu = gpu;
189
193
  this.pool = pool;
190
194
  }
@@ -220,6 +224,7 @@ export class Draws {
220
224
  this.prepared = false;
221
225
  this.runBaseLocation = gl.getUniformLocation(this.program, "uRunBase");
222
226
  if (this.multi) {
227
+ this.batches.setUp();
223
228
  this.sizeRunTable(1);
224
229
  gl.uniform1i(gl.getUniformLocation(this.program, "uRunTable"), RUN_UNIT);
225
230
  }
@@ -270,6 +275,7 @@ export class Draws {
270
275
  return;
271
276
  }
272
277
 
278
+ this.batches.reset();
273
279
  if (commands.length > this.commandStarts.length) {
274
280
  this.commandStarts = new Uint32Array(commands.ops.length / 4);
275
281
  }
@@ -334,10 +340,17 @@ export class Draws {
334
340
  this.runs[run + 1] = count;
335
341
  this.runs[run + 2] = this.runCount;
336
342
  this.runs[run + 3] = this.runUnits;
343
+ const batchStart = this.batches.indexTop;
344
+ if (!stencil) {
345
+ this.batches.add(this.runPlaces, this.runRows, this.runCount, this.atlas.frame);
346
+ }
347
+
348
+ this.runs[run + 4] = batchStart;
349
+ this.runs[run + 5] = this.batches.indexTop - batchStart;
337
350
  for (let j = 0; j < FILL_TEXTURES; j++) {
338
351
  if (this.runUnits & (1 << j)) {
339
- this.runs[run + 4 + j * 2] = this.unitIds[j];
340
- this.runs[run + 5 + j * 2] = this.unitSampling[j];
352
+ this.runs[run + 6 + j * 2] = this.unitIds[j];
353
+ this.runs[run + 7 + j * 2] = this.unitSampling[j];
341
354
  }
342
355
  }
343
356
 
@@ -369,6 +382,7 @@ export class Draws {
369
382
  );
370
383
  }
371
384
 
385
+ this.batches.upload();
372
386
  this.prepared = true;
373
387
  }
374
388
 
@@ -430,10 +444,9 @@ export class Draws {
430
444
  this.lastRow = -1;
431
445
  }
432
446
 
433
- /** The fill program, its vertex array and rows bound, as runs and masks draw with them. */
447
+ /** The fill program and rows bound; each run selects its vertex array. */
434
448
  useFill(): void {
435
449
  this.state.useProgram(this.program);
436
- this.state.bindVertexArray(this.atlas.vertexArray);
437
450
  this.state.bindTexture(0, this.gpu.rowsTexture);
438
451
  }
439
452
 
@@ -596,12 +609,16 @@ export class Draws {
596
609
  let base = 0;
597
610
  let draws: number;
598
611
  let units: number;
599
- const bindings = run + 4;
612
+ let batchStart = 0;
613
+ let batchCount = 0;
614
+ const bindings = run + 6;
600
615
  if (this.prepared) {
601
616
  i = this.runs[run];
602
617
  base = this.runs[run + 1];
603
618
  draws = this.runs[run + 2];
604
619
  units = this.runs[run + 3];
620
+ batchStart = this.runs[run + 4];
621
+ batchCount = this.runs[run + 5];
605
622
  run += RUN_STRIDE;
606
623
  } else {
607
624
  i = this.gatherRun(scene, i, end, stencil);
@@ -622,6 +639,15 @@ export class Draws {
622
639
  }
623
640
  }
624
641
 
642
+ if (batchCount > 0) {
643
+ state.bindVertexArray(this.batches.vertexArray);
644
+ state.bindTexture(RUN_UNIT, this.runTable);
645
+ state.bindSampler(RUN_UNIT, null);
646
+ gl.drawElements(gl.TRIANGLES, batchCount, gl.UNSIGNED_INT, batchStart * 4);
647
+ continue;
648
+ }
649
+
650
+ state.bindVertexArray(this.atlas.vertexArray);
625
651
  if (!this.multi) {
626
652
  if (this.runRows[0] !== this.lastRow) {
627
653
  this.lastRow = this.runRows[0];
@@ -701,6 +727,7 @@ export class Draws {
701
727
  }
702
728
 
703
729
  this.runCounts[draws] = place.indices;
730
+ this.runPlaces[draws] = place;
704
731
  this.runOffsets[draws] = place.indexStart * 4;
705
732
  this.runRows[draws] =
706
733
  scene.row[j] | (slot << FILL_SLOT) | (scene.sampler[j] & SNAP ? SNAP_BIT : 0);
@@ -709,6 +736,7 @@ export class Draws {
709
736
  }
710
737
 
711
738
  this.runCount = draws;
739
+ this.runPlaces.length = draws;
712
740
 
713
741
  return last;
714
742
  }
@@ -888,6 +916,10 @@ export class Draws {
888
916
 
889
917
  /** The programs and draw table made on the context, deleted. */
890
918
  destroy(): void {
919
+ if (this.multi) {
920
+ this.batches.destroy();
921
+ }
922
+
891
923
  if (this.runTable) {
892
924
  this.state.dropTexture(this.runTable);
893
925
  this.gl.deleteTexture(this.runTable);