@swf2es/render 0.1.8 → 0.1.11
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/webgl/atlas.d.ts +8 -1
- package/dist/webgl/atlas.d.ts.map +1 -1
- package/dist/webgl/atlas.js +10 -0
- package/dist/webgl/atlas.js.map +1 -1
- package/dist/webgl/backend.d.ts.map +1 -1
- package/dist/webgl/backend.js +0 -1
- package/dist/webgl/backend.js.map +1 -1
- package/dist/webgl/batches.d.ts +69 -0
- package/dist/webgl/batches.d.ts.map +1 -0
- package/dist/webgl/batches.js +277 -0
- package/dist/webgl/batches.js.map +1 -0
- package/dist/webgl/draws.d.ts +3 -1
- package/dist/webgl/draws.d.ts.map +1 -1
- package/dist/webgl/draws.js +36 -7
- package/dist/webgl/draws.js.map +1 -1
- package/dist/webgl/programs.d.ts +4 -1
- package/dist/webgl/programs.d.ts.map +1 -1
- package/dist/webgl/programs.js +6 -3
- package/dist/webgl/programs.js.map +1 -1
- package/package.json +2 -2
- package/src/webgl/atlas.ts +13 -0
- package/src/webgl/backend.ts +0 -1
- package/src/webgl/batches.ts +344 -0
- package/src/webgl/draws.ts +39 -7
- package/src/webgl/programs.ts +6 -3
package/dist/webgl/programs.d.ts
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/webgl/programs.js
CHANGED
|
@@ -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 ?
|
|
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":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,MAAM,EACN,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,aAAa,CAAC;AAErB,2CAA2C;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC;AACxB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AAEzB,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAChC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAE5B,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;AAEhC,sGAAsG;AACtG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,uFAAuF;AACvF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+DAA+D;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAElD
|
|
1
|
+
{"version":3,"file":"programs.js","sourceRoot":"","sources":["../../src/webgl/programs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,UAAU,EACV,KAAK,EACL,SAAS,EACT,MAAM,EACN,KAAK,EACL,OAAO,EACP,QAAQ,EACR,MAAM,EACN,OAAO,EACP,MAAM,EACN,QAAQ,GACT,MAAM,aAAa,CAAC;AAErB,2CAA2C;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC1B,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC;AACxB,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,kEAAkE;AAClE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AAEzB,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAChC,4FAA4F;AAC5F,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAE5B,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;AAEhC,sGAAsG;AACtG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAC9B,uFAAuF;AACvF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,+DAA+D;AAC/D,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC;EAC5C,KAAK,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,EAAE;;oBAErC,WAAW;oBACX,QAAQ;oBACR,QAAQ;;EAE1B,KAAK,CAAC,CAAC,CAAC,qBAAqB,OAAO,6EAA6E,CAAC,CAAC,CAAC,mBAAmB;;;;;;;;;;eAU1H,KAAK,CAAC,CAAC,CAAC,6EAA6E,QAAQ,GAAG,CAAC,+BAA+B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;qBAC/J,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC;qBACpB,SAAS;4BACF,WAAW,GAAG,CAAC,OAAO,UAAU,YAAY,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;gBAM9E,QAAQ;;;;;;;;CAQvB,CAAC;AAEF;;;;GAIG;AACH,4EAA4E;AAC5E,0EAA0E;AAC1E,wEAAwE;AACxE,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAC1B,EAAE,MAAM,EAAE,aAAa,EAAE,EACzB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC;iCACI,CAAC,sCAAsC,CAAC;aAC5D,CACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;8BAOE,aAAa;;;;;;EAMzC,SAAS;;;;;;;;;;;;;;;;;;;;;CAqBV,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;;oBAEN,WAAW;oBACX,QAAQ;oBACR,QAAQ;;;;;;;;;6BASC,WAAW,GAAG,CAAC,OAAO,UAAU,aAAa,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;;;;CAS/F,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqE3B,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;oBAER,WAAW;oBACX,SAAS;oBACT,QAAQ;oBACR,MAAM;oBACN,OAAO;;;;;;sBAML,aAAa;;;;;;;;;;;;;;;;0BAgBT,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;6BA0BV,WAAW,GAAG,CAAC,OAAO,UAAU,aAAa,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6C/F,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;+CAwBiB,WAAW,GAAG,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgC7F,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;CAO9B,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,SAAS,GAAG;yBACvB,GAAG,MAAM,WAAW,GAAG,CAAC,OAAO,UAAU,KAAK,GAAG,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;;;;;;CAMtG,CAAC;AAEF,kHAAkH;AAClH,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAE9C;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,kBAAkB,MAAM,gBAAgB,KAAK,gBAAgB,MAAM,gBAAgB,GAAG;;;;;;;;;;WAU/F,QAAQ;WACR,OAAO;WACP,MAAM;WACN,UAAU;WACV,OAAO;WACP,SAAS;WACT,QAAQ;;;WAGR,MAAM;;;WAGN,KAAK;;;WAGL,KAAK;;;;;;;;;;CAUf,CAAC;AAEF,6BAA6B;AAC7B,MAAM,aAAa,GAAG;;;;;;CAMrB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;EAY/B,aAAa;;;;;EAKb,WAAW;EACX,WAAW;CACZ,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;8BAOH,aAAa;;;;;;;;EAQzC,aAAa;;;;EAIb,SAAS;;;;;;;;;;;;;;;;;;;;;EAqBT,UAAU,CAAC,WAAW,CAAC;EACvB,WAAW;CACZ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swf2es/render",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
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.
|
|
36
|
+
"@swf2es/context3d": "0.1.11"
|
|
37
37
|
}
|
|
38
38
|
}
|
package/src/webgl/atlas.ts
CHANGED
|
@@ -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;
|
package/src/webgl/backend.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/webgl/draws.ts
CHANGED
|
@@ -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
|
|
56
|
-
const RUN_STRIDE =
|
|
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 +
|
|
340
|
-
this.runs[run +
|
|
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
|
|
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
|
-
|
|
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);
|