@geastack/native-webgl-angle 0.1.11 → 0.1.13
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/geatsc-plugin-readback.mjs +46 -0
- package/geatsc-plugin-uniforms.mjs +214 -59
- package/geatsc-plugin-uploads.mjs +7 -2
- package/geatsc-plugin.mjs +919 -68
- package/native/angle_webgl_host.mm +267 -23
- package/native/webgl_readback.h +29 -0
- package/package.json +9 -7
- package/src/inflate.ts +252 -0
- package/src/nativeWebGL.ts +88 -17
- package/src/nativeWebGLHost.ts +28 -2
- package/src/text/atlas-sans.ts +19 -178
- package/src/text/atlas-serif-italic.ts +26 -178
- package/src/text/atlas-serif.ts +22 -178
- package/src/text/native-text-types.ts +28 -0
- package/src/text/native-text.ts +154 -50
- package/src/troika-three-text.ts +49 -4
- package/NOTICE +0 -4
package/geatsc-plugin.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
transformCanonicalInstanceHooks,
|
|
4
4
|
} from "./geatsc-plugin-instancing.mjs";
|
|
5
5
|
import fs from "node:fs";
|
|
6
|
+
import { nativeReadbackFunctions } from "./geatsc-plugin-readback.mjs";
|
|
6
7
|
import { nativeUploadFunctions } from "./geatsc-plugin-uploads.mjs";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
|
|
@@ -74,6 +75,8 @@ function nativeVoidMemberCallContract(
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
const hostFunctions = [
|
|
78
|
+
['threeWebGLCopyTexImage2D','gea_three_webgl_copy_tex_image_2d','void','extern "C" void gea_three_webgl_copy_tex_image_2d(double,double,double,double,double,double,double,double);'],
|
|
79
|
+
['threeWebGLCopyTexSubImage2D','gea_three_webgl_copy_tex_sub_image_2d','void','extern "C" void gea_three_webgl_copy_tex_sub_image_2d(double,double,double,double,double,double,double,double);'],
|
|
77
80
|
[
|
|
78
81
|
"threeWebGLVertexAttribDivisor",
|
|
79
82
|
"gea_three_webgl_vertex_attrib_divisor",
|
|
@@ -93,6 +96,16 @@ const hostFunctions = [
|
|
|
93
96
|
'extern "C" void gea_three_webgl_draw_arrays_instanced(double mode, double first, double count, double instanceCount);',
|
|
94
97
|
],
|
|
95
98
|
...nativeUploadFunctions,
|
|
99
|
+
...nativeReadbackFunctions,
|
|
100
|
+
['threeWebGLBlitFramebuffer','gea_three_webgl_blit_framebuffer','void','extern "C" void gea_three_webgl_blit_framebuffer(double,double,double,double,double,double,double,double,double,double);'],
|
|
101
|
+
['threeWebGLReadPixelsPack','gea_three_webgl_read_pixels_pack','void','extern "C" void gea_three_webgl_read_pixels_pack(double,double,double,double,double,double,double);'],
|
|
102
|
+
['threeWebGLFenceSync','gea_three_webgl_fence_sync','double','extern "C" double gea_three_webgl_fence_sync();'],
|
|
103
|
+
['threeWebGLClientWaitSync','gea_three_webgl_client_wait_sync','double','extern "C" double gea_three_webgl_client_wait_sync(double,double,double);'],
|
|
104
|
+
['threeWebGLDeleteSync','gea_three_webgl_delete_sync','void','extern "C" void gea_three_webgl_delete_sync(double);'],
|
|
105
|
+
['threeWebGLTimerBegin','gea_three_webgl_timer_begin','double','extern "C" double gea_three_webgl_timer_begin();'],
|
|
106
|
+
['threeWebGLTimerEnd','gea_three_webgl_timer_end','void','extern "C" void gea_three_webgl_timer_end();'],
|
|
107
|
+
['threeWebGLTimerResult','gea_three_webgl_timer_result','double','extern "C" double gea_three_webgl_timer_result(double);'],
|
|
108
|
+
['threeWebGLRenderbufferStorageMultisample','gea_three_webgl_renderbuffer_storage_multisample','void','extern "C" void gea_three_webgl_renderbuffer_storage_multisample(double,double,double,double,double);'],
|
|
96
109
|
[
|
|
97
110
|
"threeNativeProfilePhase",
|
|
98
111
|
"gea_three_native_profile_phase",
|
|
@@ -507,6 +520,18 @@ const hostFunctions = [
|
|
|
507
520
|
"void",
|
|
508
521
|
'extern "C" void gea_three_webgl_tex_storage_2d(double target, double levels, double internalFormat, double width, double height);',
|
|
509
522
|
],
|
|
523
|
+
[
|
|
524
|
+
"threeWebGLTexStorage3D",
|
|
525
|
+
"gea_three_webgl_tex_storage_3d",
|
|
526
|
+
"void",
|
|
527
|
+
'extern "C" void gea_three_webgl_tex_storage_3d(double target, double levels, double internalFormat, double width, double height, double depth);',
|
|
528
|
+
],
|
|
529
|
+
[
|
|
530
|
+
"threeWebGLFramebufferTextureLayer",
|
|
531
|
+
"gea_three_webgl_framebuffer_texture_layer",
|
|
532
|
+
"void",
|
|
533
|
+
'extern "C" void gea_three_webgl_framebuffer_texture_layer(double target, double attachment, double texture, double level, double layer);',
|
|
534
|
+
],
|
|
510
535
|
|
|
511
536
|
[
|
|
512
537
|
"threeWebGLCreateVertexArray",
|
|
@@ -2670,7 +2695,81 @@ class WebGLRenderer {
|
|
|
2670
2695
|
}
|
|
2671
2696
|
transformed = transformed.replaceAll(
|
|
2672
2697
|
rendererUniformUploadSource,
|
|
2673
|
-
"\t\t\t\tWebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures, materialProperties.clippingPlanes );",
|
|
2698
|
+
"\t\t\t\tWebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures, materialProperties.clippingPlanes, getUniformSlots( materialProperties ) );",
|
|
2699
|
+
);
|
|
2700
|
+
// Each upload looked every uniform's value cell up by name in the
|
|
2701
|
+
// material's uniforms dictionary. Resolve the cells once beside the
|
|
2702
|
+
// uniform list they belong to; both are rebuilt together, and a list
|
|
2703
|
+
// only ever changes by being recomputed.
|
|
2704
|
+
transformed = replaceOne(
|
|
2705
|
+
transformed,
|
|
2706
|
+
"\t\tfunction getUniformList( materialProperties ) {",
|
|
2707
|
+
`\t\t/** @param {import('./webgl/WebGLProperties.js').NativeWebGLPropertyBag} materialProperties */
|
|
2708
|
+
\t\tfunction getUniformSlots( materialProperties ) {
|
|
2709
|
+
|
|
2710
|
+
\t\t\tconst list = getUniformList( materialProperties );
|
|
2711
|
+
|
|
2712
|
+
\t\t\tif ( materialProperties.nativeUniformSlotsList !== list ) {
|
|
2713
|
+
|
|
2714
|
+
\t\t\t\tmaterialProperties.nativeUniformSlots = WebGLUniforms.slotsOf( list, materialProperties.uniforms );
|
|
2715
|
+
\t\t\t\tmaterialProperties.nativeUniformSlotsList = list;
|
|
2716
|
+
|
|
2717
|
+
\t\t\t}
|
|
2718
|
+
|
|
2719
|
+
\t\t\treturn materialProperties.nativeUniformSlots;
|
|
2720
|
+
|
|
2721
|
+
\t\t}
|
|
2722
|
+
|
|
2723
|
+
\t\tfunction getUniformList( materialProperties ) {`,
|
|
2724
|
+
fileName,
|
|
2725
|
+
"WebGLRenderer resolved uniform slots",
|
|
2726
|
+
);
|
|
2727
|
+
// envMapIntensity and dfgLUT were looked up by name on every draw, and the
|
|
2728
|
+
// ten light cells on every refresh; resolve them once per uniforms object.
|
|
2729
|
+
transformed = replaceOne(
|
|
2730
|
+
transformed,
|
|
2731
|
+
"import { WebGLProperties } from './webgl/WebGLProperties.js';",
|
|
2732
|
+
"import { WebGLProperties, NativeMaterialCells } from './webgl/WebGLProperties.js';",
|
|
2733
|
+
fileName,
|
|
2734
|
+
"WebGLRenderer material cells import",
|
|
2735
|
+
);
|
|
2736
|
+
transformed = replaceOne(
|
|
2737
|
+
transformed,
|
|
2738
|
+
"\t\t/** @param {import('./webgl/WebGLProperties.js').NativeWebGLPropertyBag} materialProperties */\n\t\tfunction getUniformSlots( materialProperties ) {",
|
|
2739
|
+
`\t\t/** @param {import('./webgl/WebGLProperties.js').NativeWebGLPropertyBag} materialProperties @param {import('./shaders/UniformsLib.js').NativeUniforms} uniforms @return {NativeMaterialCells} */
|
|
2740
|
+
\t\tfunction nativeCells( materialProperties, uniforms ) {
|
|
2741
|
+
|
|
2742
|
+
\t\t\tlet cells = materialProperties.nativeCells;
|
|
2743
|
+
|
|
2744
|
+
\t\t\tif ( cells === undefined || cells.uniforms !== uniforms ) {
|
|
2745
|
+
|
|
2746
|
+
\t\t\t\tcells = new NativeMaterialCells( uniforms );
|
|
2747
|
+
\t\t\t\tmaterialProperties.nativeCells = cells;
|
|
2748
|
+
|
|
2749
|
+
\t\t\t}
|
|
2750
|
+
|
|
2751
|
+
\t\t\treturn cells;
|
|
2752
|
+
|
|
2753
|
+
\t\t}
|
|
2754
|
+
|
|
2755
|
+
\t\t/** @param {import('./webgl/WebGLProperties.js').NativeWebGLPropertyBag} materialProperties */
|
|
2756
|
+
\t\tfunction getUniformSlots( materialProperties ) {`,
|
|
2757
|
+
fileName,
|
|
2758
|
+
"WebGLRenderer material cells helper",
|
|
2759
|
+
);
|
|
2760
|
+
transformed = replaceOne(
|
|
2761
|
+
transformed,
|
|
2762
|
+
"\t\t\t\tm_uniforms.envMapIntensity.value = scene.environmentIntensity;",
|
|
2763
|
+
"\t\t\t\tconst envMapIntensity = nativeCells( materialProperties, m_uniforms ).envMapIntensity;\n\t\t\t\tif ( envMapIntensity !== undefined ) envMapIntensity.value = scene.environmentIntensity;",
|
|
2764
|
+
fileName,
|
|
2765
|
+
"WebGLRenderer envMapIntensity cell",
|
|
2766
|
+
);
|
|
2767
|
+
transformed = replaceOne(
|
|
2768
|
+
transformed,
|
|
2769
|
+
"\t\t\tif ( m_uniforms.dfgLUT !== undefined ) {\n\n\t\t\t\tm_uniforms.dfgLUT.value = getDFGLUT();",
|
|
2770
|
+
"\t\t\tconst dfgLUT = nativeCells( materialProperties, m_uniforms ).dfgLUT;\n\n\t\t\tif ( dfgLUT !== undefined ) {\n\n\t\t\t\tdfgLUT.value = getDFGLUT();",
|
|
2771
|
+
fileName,
|
|
2772
|
+
"WebGLRenderer dfgLUT cell",
|
|
2674
2773
|
);
|
|
2675
2774
|
transformed = replaceOne(
|
|
2676
2775
|
transformed,
|
|
@@ -2797,7 +2896,7 @@ class WebGLRenderer {
|
|
|
2797
2896
|
);
|
|
2798
2897
|
}
|
|
2799
2898
|
for (const name of nativeUniformNamesEnabled
|
|
2800
|
-
? ["toneMappingExposure", "cameraPosition"]
|
|
2899
|
+
? ["toneMappingExposure", "cameraPosition", "receiveShadow", "isOrthographic"]
|
|
2801
2900
|
: []) {
|
|
2802
2901
|
transformed = replaceOne(
|
|
2803
2902
|
transformed,
|
|
@@ -2836,6 +2935,89 @@ class WebGLRenderer {
|
|
|
2836
2935
|
`WebGLRenderer ${field} uniform`,
|
|
2837
2936
|
);
|
|
2838
2937
|
}
|
|
2938
|
+
if (nativeUniformNamesEnabled && nativeUniformBindingsEnabled) {
|
|
2939
|
+
// Every lit draw re-bound every shadow map: a unit allocation, a sampler
|
|
2940
|
+
// uniform check and a texture bind per map, all redundant while the same
|
|
2941
|
+
// program draws again with the same maps and nothing has rebound their
|
|
2942
|
+
// units since. The program remembers what it bound and the slot stamps
|
|
2943
|
+
// (WebGLState) of the units it used; when both still hold, the draw only
|
|
2944
|
+
// allocates the same units, so later textures keep their unit numbers.
|
|
2945
|
+
const shadowSetters =
|
|
2946
|
+
"\t\t\t\tif ( directionalShadowMaps.length > 0 ) {\n\n\t\t\t\t\tp_uniforms.set_directionalShadowMap( _gl, directionalShadowMaps, textures );\n\n\t\t\t\t}\n\n" +
|
|
2947
|
+
"\t\t\t\tif ( spotShadowMaps.length > 0 ) {\n\n\t\t\t\t\tp_uniforms.set_spotShadowMap( _gl, spotShadowMaps, textures );\n\n\t\t\t\t}\n\n" +
|
|
2948
|
+
"\t\t\t\tif ( pointShadowMaps.length > 0 ) {\n\n\t\t\t\t\tp_uniforms.set_pointShadowMap( _gl, pointShadowMaps, textures );\n\n\t\t\t\t}\n";
|
|
2949
|
+
transformed = replaceOne(
|
|
2950
|
+
transformed,
|
|
2951
|
+
shadowSetters,
|
|
2952
|
+
"\t\t\t\tif ( nativeShadowMapsBound( program, directionalShadowMaps, spotShadowMaps, pointShadowMaps ) ) {\n\n" +
|
|
2953
|
+
"\t\t\t\t\tfor ( let unit = 0; unit < program.nativeShadowUnits; unit ++ ) textures.allocateTextureUnit();\n\n" +
|
|
2954
|
+
"\t\t\t\t} else {\n\n" +
|
|
2955
|
+
shadowSetters.replaceAll("\n\t\t\t\t", "\n\t\t\t\t\t").replace(/^\t\t\t\t/, "\t\t\t\t\t") +
|
|
2956
|
+
"\n\t\t\t\t\tnativeShadowMapsRecord( program, p_uniforms, directionalShadowMaps, spotShadowMaps, pointShadowMaps );\n\n" +
|
|
2957
|
+
"\t\t\t\t}\n",
|
|
2958
|
+
fileName,
|
|
2959
|
+
"WebGLRenderer shadow-map binding fast path",
|
|
2960
|
+
);
|
|
2961
|
+
transformed = replaceOne(
|
|
2962
|
+
transformed,
|
|
2963
|
+
"\t\tfunction setProgram( camera, scene, geometry, material, object ) {",
|
|
2964
|
+
`\t\t/**
|
|
2965
|
+
\t\t * @param {import('./webgl/WebGLProgram.js').WebGLProgram} program
|
|
2966
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} directional
|
|
2967
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} spot
|
|
2968
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} point
|
|
2969
|
+
\t\t * @return {boolean}
|
|
2970
|
+
\t\t */
|
|
2971
|
+
\t\tfunction nativeShadowMapsBound( program, directional, spot, point ) {
|
|
2972
|
+
|
|
2973
|
+
\t\t\tconst counts = program.nativeShadowCounts;
|
|
2974
|
+
\t\t\tif ( counts[ 0 ] !== directional.length || counts[ 1 ] !== spot.length || counts[ 2 ] !== point.length ) return false;
|
|
2975
|
+
\t\t\tconst maps = program.nativeShadowMaps;
|
|
2976
|
+
\t\t\tlet k = 0;
|
|
2977
|
+
\t\t\tfor ( let i = 0; i < directional.length; i ++ ) if ( maps[ k ++ ] !== directional[ i ] ) return false;
|
|
2978
|
+
\t\t\tfor ( let i = 0; i < spot.length; i ++ ) if ( maps[ k ++ ] !== spot[ i ] ) return false;
|
|
2979
|
+
\t\t\tfor ( let i = 0; i < point.length; i ++ ) if ( maps[ k ++ ] !== point[ i ] ) return false;
|
|
2980
|
+
\t\t\tconst stamps = program.nativeShadowStamps;
|
|
2981
|
+
\t\t\tfor ( let unit = 0; unit < stamps.length; unit ++ ) if ( state.nativeSlotStamp( _gl.TEXTURE0 + unit ) !== stamps[ unit ] ) return false;
|
|
2982
|
+
\t\t\treturn true;
|
|
2983
|
+
|
|
2984
|
+
\t\t}
|
|
2985
|
+
|
|
2986
|
+
\t\t/**
|
|
2987
|
+
\t\t * @param {import('./webgl/WebGLProgram.js').WebGLProgram} program
|
|
2988
|
+
\t\t * @param {import('./webgl/WebGLUniforms.js').WebGLUniforms} p_uniforms
|
|
2989
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} directional
|
|
2990
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} spot
|
|
2991
|
+
\t\t * @param {Array<import('../textures/Texture.js').Texture|null>} point
|
|
2992
|
+
\t\t */
|
|
2993
|
+
\t\tfunction nativeShadowMapsRecord( program, p_uniforms, directional, spot, point ) {
|
|
2994
|
+
|
|
2995
|
+
\t\t\tprogram.nativeShadowCounts[ 0 ] = directional.length;
|
|
2996
|
+
\t\t\tprogram.nativeShadowCounts[ 1 ] = spot.length;
|
|
2997
|
+
\t\t\tprogram.nativeShadowCounts[ 2 ] = point.length;
|
|
2998
|
+
\t\t\t/** @type {Array<import('../textures/Texture.js').Texture|null>} */
|
|
2999
|
+
\t\t\tconst maps = [];
|
|
3000
|
+
\t\t\tfor ( let i = 0; i < directional.length; i ++ ) maps.push( directional[ i ] );
|
|
3001
|
+
\t\t\tfor ( let i = 0; i < spot.length; i ++ ) maps.push( spot[ i ] );
|
|
3002
|
+
\t\t\tfor ( let i = 0; i < point.length; i ++ ) maps.push( point[ i ] );
|
|
3003
|
+
\t\t\tprogram.nativeShadowMaps = maps;
|
|
3004
|
+
\t\t\t// A setter whose uniform the program lacks allocates nothing.
|
|
3005
|
+
\t\t\tconst units = ( p_uniforms.fixed_directionalShadowMap !== undefined ? directional.length : 0 ) +
|
|
3006
|
+
\t\t\t\t( p_uniforms.fixed_spotShadowMap !== undefined ? spot.length : 0 ) +
|
|
3007
|
+
\t\t\t\t( p_uniforms.fixed_pointShadowMap !== undefined ? point.length : 0 );
|
|
3008
|
+
\t\t\tprogram.nativeShadowUnits = units;
|
|
3009
|
+
\t\t\t/** @type {number[]} */
|
|
3010
|
+
\t\t\tconst stamps = [];
|
|
3011
|
+
\t\t\tfor ( let unit = 0; unit < units; unit ++ ) stamps.push( state.nativeSlotStamp( _gl.TEXTURE0 + unit ) );
|
|
3012
|
+
\t\t\tprogram.nativeShadowStamps = stamps;
|
|
3013
|
+
|
|
3014
|
+
\t\t}
|
|
3015
|
+
|
|
3016
|
+
\t\tfunction setProgram( camera, scene, geometry, material, object ) {`,
|
|
3017
|
+
fileName,
|
|
3018
|
+
"WebGLRenderer shadow-map binding fast path helpers",
|
|
3019
|
+
);
|
|
3020
|
+
}
|
|
2839
3021
|
// Three tests a tag and then reads fields off the untyped object; a
|
|
2840
3022
|
// class test narrows the object to the class that declares those fields,
|
|
2841
3023
|
// so each read has a type and each uniform value arrives already typed.
|
|
@@ -3017,6 +3199,27 @@ class WebGLRenderer {
|
|
|
3017
3199
|
fileName,
|
|
3018
3200
|
"WebGLRenderer native framebuffer selection",
|
|
3019
3201
|
);
|
|
3202
|
+
// The typed property bag keeps cube and mipmap framebuffers in their own arrays, so `__webglFramebuffer`
|
|
3203
|
+
// stays undefined for those targets. three asks exactly that to decide whether a target is set up yet, so
|
|
3204
|
+
// every setRenderTarget of a cube target ran setupRenderTarget again: six new framebuffers (and six face
|
|
3205
|
+
// allocations) per call, never deleted (probe faces and each sky-cube step at a lighting change).
|
|
3206
|
+
const setUpTarget = (name) =>
|
|
3207
|
+
`${name}.__webglFramebuffer === undefined && ${name}.__webglMipmapFramebuffers.length === 0 && ` +
|
|
3208
|
+
`${name}.__webglCubeFramebuffers.length === 0 && ${name}.__webglCubeMipmapFramebuffers.length === 0`;
|
|
3209
|
+
transformed = replaceOne(
|
|
3210
|
+
transformed,
|
|
3211
|
+
"\t\t\t\t} else if ( renderTargetProperties.__webglFramebuffer === undefined ) {\n\n\t\t\t\t\ttextures.setupRenderTarget( renderTarget );",
|
|
3212
|
+
`\t\t\t\t} else if ( ${setUpTarget("renderTargetProperties")} ) {\n\n\t\t\t\t\ttextures.setupRenderTarget( renderTarget );`,
|
|
3213
|
+
fileName,
|
|
3214
|
+
"WebGLRenderer render target set up once",
|
|
3215
|
+
);
|
|
3216
|
+
transformed = replaceOne(
|
|
3217
|
+
transformed,
|
|
3218
|
+
"\t\t\tif ( properties.get( target ).__webglFramebuffer === undefined ) {\n\n\t\t\t\ttextures.setupRenderTarget( target );",
|
|
3219
|
+
`\t\t\tconst targetProperties = properties.get( target );\n\n\t\t\tif ( ${setUpTarget("targetProperties")} ) {\n\n\t\t\t\ttextures.setupRenderTarget( target );`,
|
|
3220
|
+
fileName,
|
|
3221
|
+
"WebGLRenderer initRenderTarget set up once",
|
|
3222
|
+
);
|
|
3020
3223
|
transformed = replaceOne(
|
|
3021
3224
|
transformed,
|
|
3022
3225
|
"\t\tthis.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex, textureIndex = 0 ) {",
|
|
@@ -4841,12 +5044,14 @@ function requireWebGLStateTextureImageSource( value ) {
|
|
|
4841
5044
|
|
|
4842
5045
|
\t\t\t} else {
|
|
4843
5046
|
|
|
4844
|
-
\t\t\t\tgl.texImage2D( ${sourceArguments(9, 8, true)} );
|
|
5047
|
+
\t\t\t\tgl.texImage2D( ${sourceArguments(9, 8, true).replace("arguments[ 5 ]", "0")} );
|
|
4845
5048
|
|
|
4846
5049
|
\t\t\t}`,
|
|
4847
5050
|
fileName,
|
|
4848
5051
|
"WebGLState native TexImageSource image expansion",
|
|
4849
5052
|
);
|
|
5053
|
+
// The pixel form above passes border 0 (WebGL requires it): forwarding `arguments[ 5 ]` types it from
|
|
5054
|
+
// every caller's sixth argument (border or image), a nested union the compiler's emitter recasts to undefined.
|
|
4850
5055
|
// Preserve the actual argument count (and Function#length) while stating
|
|
4851
5056
|
// the native upload protocol at the forwarding boundary. An arguments
|
|
4852
5057
|
// object with no formal parameters otherwise erases every pixel source
|
|
@@ -5023,21 +5228,34 @@ function requireWebGLStateTextureImageSource( value ) {
|
|
|
5023
5228
|
transformed = replaceOne(
|
|
5024
5229
|
transformed,
|
|
5025
5230
|
"\tlet currentBoundTextures = {};",
|
|
5026
|
-
|
|
5231
|
+
// Indexed by slot - TEXTURE0 in a dense array: a texture bind on every
|
|
5232
|
+
// sampler of every draw read this table, and an object keyed by 33984+
|
|
5233
|
+
// is a hashed dictionary natively.
|
|
5234
|
+
"\t/** @typedef {{ type: number|undefined, texture: import('@geastack/native-webgl-angle/nativeWebGL').NativeHandle|null|undefined }} NativeBoundTexture */\n" +
|
|
5235
|
+
"\t/** @type {Array<NativeBoundTexture|undefined>} */\n\tlet currentBoundTextures = [];\n\n" +
|
|
5236
|
+
"\t/** @param {number} slot @return {NativeBoundTexture|undefined} */\n" +
|
|
5237
|
+
"\tfunction boundTextureAt( slot ) {\n\n\t\tconst index = slot - 0x84C0;\n\t\treturn index >= 0 && index < currentBoundTextures.length ? currentBoundTextures[ index ] : undefined;\n\n\t}\n\n" +
|
|
5238
|
+
"\t/** @param {number} slot @param {NativeBoundTexture} bound */\n" +
|
|
5239
|
+
"\tfunction setBoundTextureAt( slot, bound ) {\n\n\t\tconst index = slot - 0x84C0;\n\t\twhile ( currentBoundTextures.length <= index ) currentBoundTextures.push( undefined );\n\t\tcurrentBoundTextures[ index ] = bound;\n\n\t}\n\n" +
|
|
5240
|
+
"\t/** @type {number[]} */\n\tlet slotStamps = [];\n\tlet nextSlotStamp = 0;\n\n" +
|
|
5241
|
+
"\t/** @param {number} slot */\n" +
|
|
5242
|
+
"\tfunction stampSlot( slot ) {\n\n\t\tconst index = slot - 0x84C0;\n\t\twhile ( slotStamps.length <= index ) slotStamps.push( - 1 );\n\t\tslotStamps[ index ] = ++ nextSlotStamp;\n\n\t}\n\n" +
|
|
5243
|
+
"\t/** @param {number} slot @return {number} The slot's stamp, -1 if never bound since the last reset. */\n" +
|
|
5244
|
+
"\tfunction slotStamp( slot ) {\n\n\t\tconst index = slot - 0x84C0;\n\t\treturn index >= 0 && index < slotStamps.length ? slotStamps[ index ] : - 1;\n\n\t}",
|
|
5027
5245
|
fileName,
|
|
5028
5246
|
"WebGLState bound texture table",
|
|
5029
5247
|
);
|
|
5030
5248
|
transformed = replaceOne(
|
|
5031
5249
|
transformed,
|
|
5032
5250
|
"\tfunction unbindTexture() {\n\n\t\tconst boundTexture = currentBoundTextures[ currentTextureSlot ];",
|
|
5033
|
-
"\tfunction unbindTexture() {\n\n\t\tif ( typeof currentTextureSlot !== 'number' ) return;\n\n\t\tconst textureSlot = currentTextureSlot;\n\t\tconst boundTexture =
|
|
5251
|
+
"\tfunction unbindTexture() {\n\n\t\tif ( typeof currentTextureSlot !== 'number' ) return;\n\n\t\tconst textureSlot = currentTextureSlot;\n\t\tconst boundTexture = boundTextureAt( textureSlot );",
|
|
5034
5252
|
fileName,
|
|
5035
5253
|
"WebGLState current texture slot narrowing",
|
|
5036
5254
|
);
|
|
5037
5255
|
transformed = replaceOne(
|
|
5038
5256
|
transformed,
|
|
5039
5257
|
"\t\tcurrentBoundTextures = {};",
|
|
5040
|
-
"\t\tcurrentBoundTextures =
|
|
5258
|
+
"\t\tcurrentBoundTextures = [];",
|
|
5041
5259
|
fileName,
|
|
5042
5260
|
"WebGLState bound texture reset",
|
|
5043
5261
|
);
|
|
@@ -5107,7 +5325,7 @@ function requireWebGLStateTextureImageSource( value ) {
|
|
|
5107
5325
|
transformed = replaceOne(
|
|
5108
5326
|
transformed,
|
|
5109
5327
|
"\t\tlet boundTexture = currentBoundTextures[ webglSlot ];",
|
|
5110
|
-
"\t\tconst textureSlot = /** @type {number} */ ( webglSlot );\n\n\t\tlet boundTexture =
|
|
5328
|
+
"\t\tconst textureSlot = /** @type {number} */ ( webglSlot );\n\n\t\tlet boundTexture = boundTextureAt( textureSlot );",
|
|
5111
5329
|
fileName,
|
|
5112
5330
|
"WebGLState required texture slot",
|
|
5113
5331
|
);
|
|
@@ -5127,7 +5345,7 @@ function requireWebGLStateTextureImageSource( value ) {
|
|
|
5127
5345
|
.slice(bindTextureStart, bindTextureEnd)
|
|
5128
5346
|
.replace(
|
|
5129
5347
|
"currentBoundTextures[ webglSlot ] = boundTexture;",
|
|
5130
|
-
"
|
|
5348
|
+
"setBoundTextureAt( textureSlot, boundTexture );",
|
|
5131
5349
|
)
|
|
5132
5350
|
.replaceAll(
|
|
5133
5351
|
"currentTextureSlot !== webglSlot",
|
|
@@ -5148,10 +5366,34 @@ function requireWebGLStateTextureImageSource( value ) {
|
|
|
5148
5366
|
transformed = replaceOne(
|
|
5149
5367
|
transformed,
|
|
5150
5368
|
"\t\t\tgl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );",
|
|
5151
|
-
"\t\t\tconst textureToBind = webglTexture || emptyTextures[ webglType ];\n\n\t\t\tif ( textureToBind === undefined ) throw new Error( 'THREE.WebGLState: Missing empty texture for binding target.' );\n\n\t\t\tgl.bindTexture( webglType, textureToBind );",
|
|
5369
|
+
"\t\t\tconst textureToBind = webglTexture || emptyTextures[ webglType ];\n\n\t\t\tif ( textureToBind === undefined ) throw new Error( 'THREE.WebGLState: Missing empty texture for binding target.' );\n\n\t\t\tgl.bindTexture( webglType, textureToBind );\n\t\t\tstampSlot( textureSlot );",
|
|
5152
5370
|
fileName,
|
|
5153
5371
|
"WebGLState bound texture fallback",
|
|
5154
5372
|
);
|
|
5373
|
+
// Each texture slot carries a stamp that changes whenever the slot is
|
|
5374
|
+
// rebound, so a caller can tell its earlier binds are still in place
|
|
5375
|
+
// (WebGLRenderer's shadow-map fast path).
|
|
5376
|
+
transformed = replaceOne(
|
|
5377
|
+
transformed,
|
|
5378
|
+
"\t\t\tgl.bindTexture( boundTexture.type, null );",
|
|
5379
|
+
"\t\t\tgl.bindTexture( boundTexture.type, null );\n\t\t\tstampSlot( textureSlot );",
|
|
5380
|
+
fileName,
|
|
5381
|
+
"WebGLState unbind slot stamp",
|
|
5382
|
+
);
|
|
5383
|
+
transformed = replaceOne(
|
|
5384
|
+
transformed,
|
|
5385
|
+
"\t\tcurrentBoundTextures = [];",
|
|
5386
|
+
"\t\tcurrentBoundTextures = [];\n\t\tslotStamps = [];",
|
|
5387
|
+
fileName,
|
|
5388
|
+
"WebGLState slot stamp reset",
|
|
5389
|
+
);
|
|
5390
|
+
transformed = replaceOne(
|
|
5391
|
+
transformed,
|
|
5392
|
+
"\t\tbindTexture: bindTexture,\n",
|
|
5393
|
+
"\t\tbindTexture: bindTexture,\n\t\tnativeSlotStamp: slotStamp,\n",
|
|
5394
|
+
fileName,
|
|
5395
|
+
"WebGLState slot stamp export",
|
|
5396
|
+
);
|
|
5155
5397
|
transformed = replaceOne(
|
|
5156
5398
|
transformed,
|
|
5157
5399
|
"\t\tcurrentDrawbuffers = new WeakMap();",
|
|
@@ -5743,8 +5985,331 @@ ${transformed}`;
|
|
|
5743
5985
|
);
|
|
5744
5986
|
transformed = transformed.slice(0, start) + body + transformed.slice(end);
|
|
5745
5987
|
}
|
|
5988
|
+
// Every render pass updates every drawn geometry's attributes, and each
|
|
5989
|
+
// update hashed the attribute into `buffers`. The WeakMap stays the
|
|
5990
|
+
// authority; each data attribute also carries the entry its owning
|
|
5991
|
+
// WebGLAttributes stored, tagged with that instance's number, so the
|
|
5992
|
+
// per-draw read is a field load. Every write and delete of `buffers`
|
|
5993
|
+
// keeps the field in step.
|
|
5994
|
+
transformed = replaceOne(
|
|
5995
|
+
transformed,
|
|
5996
|
+
"function WebGLAttributes( gl ) {\n",
|
|
5997
|
+
"let nextNativeAttributesOwner = 1;\n\nfunction WebGLAttributes( gl ) {\n\n\tconst nativeOwner = nextNativeAttributesOwner ++;\n",
|
|
5998
|
+
fileName,
|
|
5999
|
+
"WebGLAttributes front cache owner",
|
|
6000
|
+
);
|
|
6001
|
+
transformed = replaceOne(
|
|
6002
|
+
transformed,
|
|
6003
|
+
"\t\treturn buffers.get( dataAttribute );",
|
|
6004
|
+
"\t\tif ( dataAttribute.__nativeBufferOwner === nativeOwner ) return dataAttribute.__nativeBuffer;\n\n\t\treturn buffers.get( dataAttribute );",
|
|
6005
|
+
fileName,
|
|
6006
|
+
"WebGLAttributes front cache get",
|
|
6007
|
+
);
|
|
6008
|
+
transformed = replaceOne(
|
|
6009
|
+
transformed,
|
|
6010
|
+
"\t\t\tbuffers.delete( dataAttribute );",
|
|
6011
|
+
"\t\t\tbuffers.delete( dataAttribute );\n\n\t\t\tif ( dataAttribute.__nativeBufferOwner === nativeOwner ) {\n\n\t\t\t\tdataAttribute.__nativeBufferOwner = 0;\n\t\t\t\tdataAttribute.__nativeBuffer = undefined;\n\n\t\t\t}",
|
|
6012
|
+
fileName,
|
|
6013
|
+
"WebGLAttributes front cache delete",
|
|
6014
|
+
);
|
|
6015
|
+
transformed = replaceOne(
|
|
6016
|
+
transformed,
|
|
6017
|
+
`\t\t\t\tbuffers.set( dataAttribute, {
|
|
6018
|
+
\t\t\t\t\tbuffer: dataAttribute.buffer,
|
|
6019
|
+
\t\t\t\t\ttype: dataAttribute.type,
|
|
6020
|
+
\t\t\t\t\tbytesPerElement: dataAttribute.elementSize,
|
|
6021
|
+
\t\t\t\t\tversion: dataAttribute.version
|
|
6022
|
+
\t\t\t\t} );`,
|
|
6023
|
+
`\t\t\t\t/** @type {NativeAttributeBufferCache} */
|
|
6024
|
+
\t\t\t\tconst entry = {
|
|
6025
|
+
\t\t\t\t\tbuffer: dataAttribute.buffer,
|
|
6026
|
+
\t\t\t\t\ttype: dataAttribute.type,
|
|
6027
|
+
\t\t\t\t\tbytesPerElement: dataAttribute.elementSize,
|
|
6028
|
+
\t\t\t\t\tversion: dataAttribute.version
|
|
6029
|
+
\t\t\t\t};
|
|
6030
|
+
\t\t\t\tbuffers.set( dataAttribute, entry );
|
|
6031
|
+
\t\t\t\tdataAttribute.__nativeBufferOwner = nativeOwner;
|
|
6032
|
+
\t\t\t\tdataAttribute.__nativeBuffer = entry;`,
|
|
6033
|
+
fileName,
|
|
6034
|
+
"WebGLAttributes front cache GL attribute write",
|
|
6035
|
+
);
|
|
6036
|
+
transformed = replaceOne(
|
|
6037
|
+
transformed,
|
|
6038
|
+
`\t\tconst data = buffers.get( dataAttribute );
|
|
6039
|
+
|
|
6040
|
+
\t\tif ( data === undefined ) {
|
|
6041
|
+
|
|
6042
|
+
\t\t\tbuffers.set( dataAttribute, createBuffer( dataAttribute, bufferType ) );`,
|
|
6043
|
+
`\t\tconst data = dataAttribute.__nativeBufferOwner === nativeOwner ? dataAttribute.__nativeBuffer : buffers.get( dataAttribute );
|
|
6044
|
+
|
|
6045
|
+
\t\tif ( data === undefined ) {
|
|
6046
|
+
|
|
6047
|
+
\t\t\tconst entry = createBuffer( dataAttribute, bufferType );
|
|
6048
|
+
\t\t\tbuffers.set( dataAttribute, entry );
|
|
6049
|
+
\t\t\tdataAttribute.__nativeBufferOwner = nativeOwner;
|
|
6050
|
+
\t\t\tdataAttribute.__nativeBuffer = entry;`,
|
|
6051
|
+
fileName,
|
|
6052
|
+
"WebGLAttributes front cache update",
|
|
6053
|
+
);
|
|
6054
|
+
}
|
|
6055
|
+
if (
|
|
6056
|
+
normalized.endsWith("/three/src/core/BufferAttribute.js") ||
|
|
6057
|
+
normalized.endsWith("/three/src/core/InterleavedBuffer.js") ||
|
|
6058
|
+
normalized.endsWith("/three/src/core/GLBufferAttribute.js")
|
|
6059
|
+
) {
|
|
6060
|
+
// The native WebGLAttributes front cache (see WebGLAttributes above).
|
|
6061
|
+
transformed = replaceOne(
|
|
6062
|
+
transformed,
|
|
6063
|
+
"\t\tthis.version = 0;\n",
|
|
6064
|
+
`\t\tthis.version = 0;
|
|
6065
|
+
|
|
6066
|
+
\t\t/** @type {number} The WebGLAttributes instance whose entry \`__nativeBuffer\` holds; 0 when none. */
|
|
6067
|
+
\t\tthis.__nativeBufferOwner = 0;
|
|
6068
|
+
\t\t/** @type {{ buffer: import('@geastack/native-webgl-angle/nativeWebGL').NativeHandle, type: number, bytesPerElement: number, version: number, size?: number }|undefined} */
|
|
6069
|
+
\t\tthis.__nativeBuffer = undefined;
|
|
6070
|
+
`,
|
|
6071
|
+
fileName,
|
|
6072
|
+
"native attribute buffer front cache fields",
|
|
6073
|
+
);
|
|
6074
|
+
}
|
|
6075
|
+
if (
|
|
6076
|
+
normalized.endsWith("/three/src/materials/Material.js") ||
|
|
6077
|
+
normalized.endsWith("/three/src/textures/Texture.js") ||
|
|
6078
|
+
normalized.endsWith("/three/src/textures/Source.js")
|
|
6079
|
+
) {
|
|
6080
|
+
// The native WebGLProperties front cache (see WebGLProperties).
|
|
6081
|
+
transformed = replaceOne(
|
|
6082
|
+
transformed,
|
|
6083
|
+
"\t\tthis.version = 0;\n",
|
|
6084
|
+
`\t\tthis.version = 0;
|
|
6085
|
+
|
|
6086
|
+
\t\t/** @type {number} The WebGLProperties instance whose bag \`__nativeProperties\` holds; 0 when none. */
|
|
6087
|
+
\t\tthis.__nativePropertiesOwner = 0;
|
|
6088
|
+
\t\t/** @type {import('../renderers/webgl/WebGLProperties.js').NativeWebGLPropertyBag|undefined} */
|
|
6089
|
+
\t\tthis.__nativeProperties = undefined;
|
|
6090
|
+
`,
|
|
6091
|
+
fileName,
|
|
6092
|
+
"native property bag front cache fields",
|
|
6093
|
+
);
|
|
6094
|
+
}
|
|
6095
|
+
if (normalized.endsWith("/three/src/core/Object3D.js") || normalized.endsWith("/three/src/core/BufferGeometry.js")) {
|
|
6096
|
+
// The native WebGLObjects front cache (see WebGLObjects).
|
|
6097
|
+
transformed = replaceOne(
|
|
6098
|
+
transformed,
|
|
6099
|
+
"\t\tthis.uuid = generateUUID();\n",
|
|
6100
|
+
`\t\tthis.uuid = generateUUID();
|
|
6101
|
+
|
|
6102
|
+
\t\t/** @type {number} The WebGLObjects instance whose update frame \`__nativeObjectsFrame\` holds; 0 when none. */
|
|
6103
|
+
\t\tthis.__nativeObjectsOwner = 0;
|
|
6104
|
+
\t\t/** @type {number} */
|
|
6105
|
+
\t\tthis.__nativeObjectsFrame = - 1;
|
|
6106
|
+
`,
|
|
6107
|
+
fileName,
|
|
6108
|
+
"native objects update front cache fields",
|
|
6109
|
+
);
|
|
6110
|
+
}
|
|
6111
|
+
if (normalized.endsWith("/three/src/core/BufferGeometry.js")) {
|
|
6112
|
+
// The attribute-set stamp WebGLBindingStates' needsUpdate fast path reads.
|
|
6113
|
+
transformed = replaceOne(
|
|
6114
|
+
transformed,
|
|
6115
|
+
"\t\t */\n\t\tthis.attributes = {};\n",
|
|
6116
|
+
"\t\t */\n\t\tthis.attributes = {};\n\n\t\t/** @type {number} Bumped whenever the attribute set changes. */\n\t\tthis.__nativeAttributeStamp = 0;\n",
|
|
6117
|
+
fileName,
|
|
6118
|
+
"native attribute-set stamp field",
|
|
6119
|
+
);
|
|
6120
|
+
transformed = replaceOne(
|
|
6121
|
+
transformed,
|
|
6122
|
+
"\t\tthis.index = null;\n\t\tthis.attributes = {};\n",
|
|
6123
|
+
"\t\tthis.index = null;\n\t\tthis.attributes = {};\n\t\tthis.__nativeAttributeStamp ++;\n",
|
|
6124
|
+
fileName,
|
|
6125
|
+
"native attribute-set stamp on copy",
|
|
6126
|
+
);
|
|
6127
|
+
transformed = replaceOne(
|
|
6128
|
+
transformed,
|
|
6129
|
+
"\t\tthis.attributes[ name ] = attribute;\n",
|
|
6130
|
+
"\t\tthis.attributes[ name ] = attribute;\n\t\tthis.__nativeAttributeStamp ++;\n",
|
|
6131
|
+
fileName,
|
|
6132
|
+
"native attribute-set stamp on set",
|
|
6133
|
+
);
|
|
6134
|
+
transformed = replaceOne(
|
|
6135
|
+
transformed,
|
|
6136
|
+
"\t\tdelete this.attributes[ name ];\n",
|
|
6137
|
+
"\t\tdelete this.attributes[ name ];\n\t\tthis.__nativeAttributeStamp ++;\n",
|
|
6138
|
+
fileName,
|
|
6139
|
+
"native attribute-set stamp on delete",
|
|
6140
|
+
);
|
|
6141
|
+
}
|
|
6142
|
+
// Light uniforms (the light, shadow, ambient and probe structures
|
|
6143
|
+
// markUniformsLightsNeedsUpdate flags) are written only by WebGLLights.setup
|
|
6144
|
+
// and setupView. three re-uploads them whenever the program changes, which
|
|
6145
|
+
// natively is a walk over every light struct member on nearly every draw.
|
|
6146
|
+
// Each setup/setupView takes a new stamp; a program records the stamp whose
|
|
6147
|
+
// values it last received and skips the upload while that stamp is current,
|
|
6148
|
+
// because its GL uniforms already hold exactly those values. Shadow-map
|
|
6149
|
+
// samplers are bound separately and still every draw.
|
|
6150
|
+
if (normalized.endsWith("/three/src/renderers/webgl/WebGLLights.js")) {
|
|
6151
|
+
transformed = replaceOne(
|
|
6152
|
+
transformed,
|
|
6153
|
+
"\tconst state = {\n\n\t\tversion: 0,\n",
|
|
6154
|
+
"\tconst state = {\n\n\t\tversion: 0,\n\n\t\tnativeStamp: 0,\n",
|
|
6155
|
+
fileName,
|
|
6156
|
+
"WebGLLights native upload stamp field",
|
|
6157
|
+
);
|
|
6158
|
+
transformed = replaceOne(
|
|
6159
|
+
transformed,
|
|
6160
|
+
"\tfunction setup( lights ) {\n",
|
|
6161
|
+
"\tfunction setup( lights ) {\n\n\t\tstate.nativeStamp = ++ nativeLightsStamp;\n",
|
|
6162
|
+
fileName,
|
|
6163
|
+
"WebGLLights.setup native upload stamp",
|
|
6164
|
+
);
|
|
6165
|
+
transformed = replaceOne(
|
|
6166
|
+
transformed,
|
|
6167
|
+
"\tfunction setupView( lights, camera ) {\n",
|
|
6168
|
+
"\tfunction setupView( lights, camera ) {\n\n\t\tstate.nativeStamp = ++ nativeLightsStamp;\n",
|
|
6169
|
+
fileName,
|
|
6170
|
+
"WebGLLights.setupView native upload stamp",
|
|
6171
|
+
);
|
|
6172
|
+
transformed = replaceOne(
|
|
6173
|
+
transformed,
|
|
6174
|
+
"function WebGLLights(",
|
|
6175
|
+
`let nativeLightsStamp = 0;
|
|
6176
|
+
|
|
6177
|
+
// Every render state (the main view, and each nested render such as a mirror)
|
|
6178
|
+
// owns a WebGLLights whose version counts its own hash changes, so a material
|
|
6179
|
+
// drawn in two states sees a "new" version on every switch and three rebuilds
|
|
6180
|
+
// its program parameters to find the same program. Equal hashes (light and
|
|
6181
|
+
// shadow counts) share one structure id, which lets the renderer tell a
|
|
6182
|
+
// re-wire from a real program change.
|
|
6183
|
+
/** @type {Map<string, number>} */
|
|
6184
|
+
const nativeLightStructures = new Map();
|
|
6185
|
+
/** @param {{ directionalLength: number, pointLength: number, spotLength: number, rectAreaLength: number, hemiLength: number, numDirectionalShadows: number, numPointShadows: number, numSpotShadows: number, numSpotMaps: number, numLightProbes: number }} hash @return {number} */
|
|
6186
|
+
function nativeLightStructure( hash ) {
|
|
6187
|
+
|
|
6188
|
+
\tconst key = [ hash.directionalLength, hash.pointLength, hash.spotLength, hash.rectAreaLength, hash.hemiLength,
|
|
6189
|
+
\t\thash.numDirectionalShadows, hash.numPointShadows, hash.numSpotShadows, hash.numSpotMaps, hash.numLightProbes ].join( ',' );
|
|
6190
|
+
\tlet structure = nativeLightStructures.get( key );
|
|
6191
|
+
|
|
6192
|
+
\tif ( structure === undefined ) {
|
|
6193
|
+
|
|
6194
|
+
\t\tstructure = nativeLightStructures.size + 1;
|
|
6195
|
+
\t\tnativeLightStructures.set( key, structure );
|
|
6196
|
+
|
|
6197
|
+
\t}
|
|
6198
|
+
|
|
6199
|
+
\treturn structure;
|
|
6200
|
+
|
|
6201
|
+
}
|
|
6202
|
+
|
|
6203
|
+
function WebGLLights(`,
|
|
6204
|
+
fileName,
|
|
6205
|
+
"WebGLLights native upload stamp counter",
|
|
6206
|
+
);
|
|
6207
|
+
transformed = replaceOne(
|
|
6208
|
+
transformed,
|
|
6209
|
+
"\t\tnativeStamp: 0,\n",
|
|
6210
|
+
"\t\tnativeStamp: 0,\n\n\t\tnativeStructure: 0,\n",
|
|
6211
|
+
fileName,
|
|
6212
|
+
"WebGLLights native structure field",
|
|
6213
|
+
);
|
|
6214
|
+
transformed = replaceOne(
|
|
6215
|
+
transformed,
|
|
6216
|
+
"\t\t\tstate.version = nextVersion ++;",
|
|
6217
|
+
"\t\t\tstate.version = nextVersion ++;\n\t\t\tstate.nativeStructure = nativeLightStructure( hash );",
|
|
6218
|
+
fileName,
|
|
6219
|
+
"WebGLLights native structure on hash change",
|
|
6220
|
+
);
|
|
6221
|
+
}
|
|
6222
|
+
if (normalized.endsWith("/three/src/renderers/webgl/WebGLProgram.js")) {
|
|
6223
|
+
transformed = replaceOne(
|
|
6224
|
+
transformed,
|
|
6225
|
+
"\tthis.cacheKey = cacheKey;\n",
|
|
6226
|
+
"\tthis.cacheKey = cacheKey;\n\t/** The WebGLLights stamp whose light uniforms this program holds; 0 when none. */\n\tthis.nativeLightsStamp = 0;\n" +
|
|
6227
|
+
"\t/** @type {Array<import('../../textures/Texture.js').Texture|null>} The shadow maps (directional, spot, point, in order) this program last bound, see WebGLRenderer's shadow-map fast path. */\n\tthis.nativeShadowMaps = [];\n" +
|
|
6228
|
+
"\t/** @type {number[]} Lengths of the three arrays in nativeShadowMaps. */\n\tthis.nativeShadowCounts = [ - 1, - 1, - 1 ];\n" +
|
|
6229
|
+
"\t/** @type {number[]} WebGLState slot stamps of the units those maps were bound to. */\n\tthis.nativeShadowStamps = [];\n" +
|
|
6230
|
+
"\t/** The texture units the shadow-map setters allocated. */\n\tthis.nativeShadowUnits = 0;\n",
|
|
6231
|
+
fileName,
|
|
6232
|
+
"WebGLProgram native light upload stamp",
|
|
6233
|
+
);
|
|
6234
|
+
}
|
|
6235
|
+
if (normalized.endsWith("/three/src/renderers/WebGLRenderer.js")) {
|
|
6236
|
+
transformed = replaceOne(
|
|
6237
|
+
transformed,
|
|
6238
|
+
"\t\t\t\t\tmarkUniformsLightsNeedsUpdate( m_uniforms, refreshLights );",
|
|
6239
|
+
`\t\t\t\t\tconst lightsStamp = lights.state.nativeStamp;
|
|
6240
|
+
\t\t\t\t\tconst uploadLights = refreshLights && program.nativeLightsStamp !== lightsStamp;
|
|
6241
|
+
\t\t\t\t\t// The ten light cells, resolved once per uniforms object (nativeCells).
|
|
6242
|
+
\t\t\t\t\tfor ( const cell of nativeCells( materialProperties, m_uniforms ).lights ) cell.needsUpdate = uploadLights;
|
|
6243
|
+
\t\t\t\t\tif ( uploadLights ) program.nativeLightsStamp = lightsStamp;`,
|
|
6244
|
+
fileName,
|
|
6245
|
+
"WebGLRenderer light uniform upload stamp",
|
|
6246
|
+
);
|
|
6247
|
+
const lightWiring = [
|
|
6248
|
+
["ambientLightColor", "ambient"], ["lightProbe", "probe"],
|
|
6249
|
+
["directionalLights", "directional"], ["directionalLightShadows", "directionalShadow"],
|
|
6250
|
+
["spotLights", "spot"], ["spotLightShadows", "spotShadow"], ["rectAreaLights", "rectArea"],
|
|
6251
|
+
["ltc_1", "rectAreaLTC1"], ["ltc_2", "rectAreaLTC2"],
|
|
6252
|
+
["pointLights", "point"], ["pointLightShadows", "pointShadow"], ["hemisphereLights", "hemi"],
|
|
6253
|
+
["directionalShadowMatrix", "directionalShadowMatrix"], ["spotLightMatrix", "spotLightMatrix"],
|
|
6254
|
+
["spotLightMap", "spotLightMap"], ["pointShadowMatrix", "pointShadowMatrix"],
|
|
6255
|
+
];
|
|
6256
|
+
const wiringText = lightWiring.map(([u, s]) => `\t\t\t\tuniforms.${u}.value = lights.state.${s};\n`).join("");
|
|
6257
|
+
// getProgram's wiring must still be exactly this list, or the re-wire below would miss a field.
|
|
6258
|
+
if (!transformed.includes(wiringText.replace("\t\t\t\tuniforms.directionalShadowMatrix", "\n\t\t\t\tuniforms.directionalShadowMatrix"))) {
|
|
6259
|
+
throw new Error(`Three WebGLRenderer light wiring at ${fileName} no longer matches the native re-wire list`);
|
|
6260
|
+
}
|
|
6261
|
+
transformed = replaceOne(
|
|
6262
|
+
transformed,
|
|
6263
|
+
"\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n",
|
|
6264
|
+
"\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n\t\t\tmaterialProperties.nativeLightsStructure = lights.state.nativeStructure;\n\t\t\tmaterialProperties.nativeShadowCount = shadowsArray.length;\n",
|
|
6265
|
+
fileName,
|
|
6266
|
+
"WebGLRenderer program light structure",
|
|
6267
|
+
);
|
|
6268
|
+
// A lights version from another render state with the same structure and
|
|
6269
|
+
// shadow count selects the same program: point the material's light
|
|
6270
|
+
// uniforms at this state's arrays (getProgram's wiring) instead of
|
|
6271
|
+
// rebuilding the program parameters. Every other program check still runs.
|
|
6272
|
+
transformed = replaceOne(
|
|
6273
|
+
transformed,
|
|
6274
|
+
"\t\t\tif ( material.version === materialProperties.__version ) {\n\n\t\t\t\tif ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {",
|
|
6275
|
+
`\t\t\tif ( material.version === materialProperties.__version && materialProperties.needsLights &&
|
|
6276
|
+
\t\t\t\tmaterialProperties.lightsStateVersion !== lights.state.version &&
|
|
6277
|
+
\t\t\t\tmaterialProperties.nativeLightsStructure === lights.state.nativeStructure &&
|
|
6278
|
+
\t\t\t\tmaterialProperties.nativeShadowCount === currentRenderState.state.shadowsArray.length ) {
|
|
6279
|
+
|
|
6280
|
+
\t\t\t\tconst uniforms = materialProperties.uniforms;
|
|
6281
|
+
${wiringText.replace(/\t\t\t\t/g, "\t\t\t\t")}
|
|
6282
|
+
\t\t\t\tmaterialProperties.lightsStateVersion = lights.state.version;
|
|
6283
|
+
|
|
6284
|
+
\t\t\t}
|
|
6285
|
+
|
|
6286
|
+
\t\t\tif ( material.version === materialProperties.__version ) {
|
|
6287
|
+
|
|
6288
|
+
\t\t\t\tif ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {`,
|
|
6289
|
+
fileName,
|
|
6290
|
+
"WebGLRenderer light re-wire across render states",
|
|
6291
|
+
);
|
|
5746
6292
|
}
|
|
5747
6293
|
if (normalized.endsWith("/three/src/renderers/webgl/WebGLShadowMap.js")) {
|
|
6294
|
+
// An app that replaces `shadowMap.render` (the browser's cached sun shadow)
|
|
6295
|
+
// cannot do so natively: the field holds a `this`-bound function expression
|
|
6296
|
+
// no app function converts to. This hook is an ordinary function-typed
|
|
6297
|
+
// field instead; render() offers each call to it first, and a hook that
|
|
6298
|
+
// returns true has rendered the shadows itself.
|
|
6299
|
+
transformed = replaceOne(
|
|
6300
|
+
transformed,
|
|
6301
|
+
"\tconst scope = this;\n",
|
|
6302
|
+
"\tconst scope = this;\n\n\t/** @type {((lights: Array<import('../../lights/Light.js').Light>, scene: import('../../scenes/Scene.js').Scene, camera: import('../../cameras/Camera.js').Camera) => boolean)|null} */\n\tthis.nativeRenderHook = null;\n",
|
|
6303
|
+
fileName,
|
|
6304
|
+
"WebGLShadowMap native render hook field",
|
|
6305
|
+
);
|
|
6306
|
+
transformed = replaceOne(
|
|
6307
|
+
transformed,
|
|
6308
|
+
"\t\tif ( scope.enabled === false ) return;\n",
|
|
6309
|
+
"\t\tconst nativeRenderHook = scope.nativeRenderHook;\n\t\tif ( nativeRenderHook !== null && nativeRenderHook( lights, scene, camera ) ) return;\n\n\t\tif ( scope.enabled === false ) return;\n",
|
|
6310
|
+
fileName,
|
|
6311
|
+
"WebGLShadowMap native render hook call",
|
|
6312
|
+
);
|
|
5748
6313
|
transformed = replaceOne(
|
|
5749
6314
|
transformed,
|
|
5750
6315
|
"\t\tuniforms: {\n\t\t\tshadow_pass:",
|
|
@@ -6151,13 +6716,9 @@ class WebGLBackgroundCubeMaterial extends ShaderMaterial {
|
|
|
6151
6716
|
\tsetEnvironment( texture ) {
|
|
6152
6717
|
|
|
6153
6718
|
\t\tthis.uniforms.envMap.value = texture;
|
|
6154
|
-
|
|
6155
|
-
\t
|
|
6156
|
-
|
|
6157
|
-
\t/** @this {WebGLBackgroundCubeMaterial} */
|
|
6158
|
-
\tget envMap() {
|
|
6159
|
-
|
|
6160
|
-
\t\treturn uniformTexture( this.uniforms.envMap );
|
|
6719
|
+
\t\t// The renderer reads material.envMap as the base Material field (a subclass getter is not
|
|
6720
|
+
\t\t// dispatched through that read), so keep the field itself in step.
|
|
6721
|
+
\t\tthis.envMap = texture;
|
|
6161
6722
|
|
|
6162
6723
|
\t}
|
|
6163
6724
|
|
|
@@ -6169,13 +6730,7 @@ class WebGLBackgroundPlaneMaterial extends ShaderMaterial {
|
|
|
6169
6730
|
\tsetMap( texture ) {
|
|
6170
6731
|
|
|
6171
6732
|
\t\tthis.uniforms.t2D.value = texture;
|
|
6172
|
-
|
|
6173
|
-
\t}
|
|
6174
|
-
|
|
6175
|
-
\t/** @this {WebGLBackgroundPlaneMaterial} */
|
|
6176
|
-
\tget map() {
|
|
6177
|
-
|
|
6178
|
-
\t\treturn uniformTexture( this.uniforms.t2D );
|
|
6733
|
+
\t\tthis.map = texture;
|
|
6179
6734
|
|
|
6180
6735
|
\t}
|
|
6181
6736
|
|
|
@@ -6545,23 +7100,31 @@ class WebGLBackgroundPlaneMaterial extends ShaderMaterial {
|
|
|
6545
7100
|
transformed = transformUniformsUtils(transformed, fileName);
|
|
6546
7101
|
}
|
|
6547
7102
|
if (normalized.endsWith("/three/src/utils.js")) {
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
const
|
|
6552
|
-
if (
|
|
6553
|
-
probeStartIndex < 0 ||
|
|
6554
|
-
probeEndIndex < 0 ||
|
|
6555
|
-
transformed.indexOf(probeStart, probeStartIndex + 1) >= 0
|
|
6556
|
-
) {
|
|
7103
|
+
// probeAsync keeps three's fence polling (the host implements fenceSync/clientWaitSync, so the
|
|
7104
|
+
// async readback resolves when the GPU has finished the copy), once per frame: setTimeout's result
|
|
7105
|
+
// types as Node's Timeout, which has no native boundary.
|
|
7106
|
+
const probeRetries = transformed.split("setTimeout( probe, interval );").length - 1;
|
|
7107
|
+
if (probeRetries !== 2) {
|
|
6557
7108
|
throw new Error(
|
|
6558
|
-
`Three async WebGL probe source at ${fileName}
|
|
7109
|
+
`Three async WebGL probe source at ${fileName} has ${probeRetries} probe timers; expected 2`,
|
|
6559
7110
|
);
|
|
6560
7111
|
}
|
|
7112
|
+
transformed = transformed.replaceAll("setTimeout( probe, interval );", "requestAnimationFrame( probe );");
|
|
7113
|
+
// Resolve with the sync status: a value-less resolve() of a Promise<void> lowers its optional
|
|
7114
|
+
// payload incorrectly, and the callers only await completion.
|
|
7115
|
+
const probeAt = transformed.indexOf("function probeAsync( gl, sync, interval ) {");
|
|
7116
|
+
const probeDocAt = transformed.lastIndexOf(" * @return {Promise<void>}", probeAt);
|
|
7117
|
+
const probeEndAt = transformed.indexOf("\n}\n", probeAt);
|
|
7118
|
+
const probeBody = transformed.slice(probeAt, probeEndAt);
|
|
7119
|
+
if (probeAt < 0 || probeDocAt < 0 || probeDocAt < transformed.lastIndexOf("/**", probeAt) || probeBody.split("resolve();").length !== 2) {
|
|
7120
|
+
throw new Error(`Three async WebGL probe source at ${fileName} no longer matches the native adaptation`);
|
|
7121
|
+
}
|
|
6561
7122
|
transformed =
|
|
6562
|
-
transformed.slice(0,
|
|
6563
|
-
"
|
|
6564
|
-
transformed.slice(
|
|
7123
|
+
transformed.slice(0, probeDocAt) +
|
|
7124
|
+
" * @return {Promise<number>}" +
|
|
7125
|
+
transformed.slice(probeDocAt + " * @return {Promise<void>}".length, probeAt) +
|
|
7126
|
+
probeBody.replace("resolve();", "resolve( 1 );") +
|
|
7127
|
+
transformed.slice(probeEndAt);
|
|
6565
7128
|
transformed = replaceOne(
|
|
6566
7129
|
transformed,
|
|
6567
7130
|
"\t\t\tparams[ 0 ] += ' ' + stackTrace.getLocation();",
|
|
@@ -6627,13 +7190,6 @@ class WebGLBackgroundPlaneMaterial extends ShaderMaterial {
|
|
|
6627
7190
|
`Three utils source at ${fileName} has ${warnCalls} console.warn calls; expected 2`,
|
|
6628
7191
|
);
|
|
6629
7192
|
transformed = transformed.replaceAll("console.warn(", "console.error(");
|
|
6630
|
-
transformed = replaceOne(
|
|
6631
|
-
transformed,
|
|
6632
|
-
"@param {number} interval - The polling interval in milliseconds.\n * @return {Promise<void>} A promise that resolves when the sync completes or rejects if it fails.",
|
|
6633
|
-
"@param {number} interval - The polling interval in milliseconds.\n * @return {Promise<undefined>} A promise that resolves when the sync completes or rejects if it fails.",
|
|
6634
|
-
fileName,
|
|
6635
|
-
"probeAsync resolved payload",
|
|
6636
|
-
);
|
|
6637
7193
|
}
|
|
6638
7194
|
if (
|
|
6639
7195
|
normalized.endsWith("/three/src/renderers/webgl/WebGLClipping.js") &&
|
|
@@ -7313,6 +7869,76 @@ ${indent}}`,
|
|
|
7313
7869
|
fileName,
|
|
7314
7870
|
"WebGLBindingStates wireframe cache write",
|
|
7315
7871
|
);
|
|
7872
|
+
// The nested cache is keyed by ids spelled as strings, so every draw formats
|
|
7873
|
+
// three numbers and hashes them through string dictionaries. A numeric front
|
|
7874
|
+
// cache answers repeat lookups: geometry id, then one exact integer packing
|
|
7875
|
+
// object id, program id and wireframe (program ids past 2^16 skip it). Any
|
|
7876
|
+
// release clears it before the nested states are deleted, so it never holds a
|
|
7877
|
+
// state the nested cache no longer has.
|
|
7878
|
+
transformed = replaceOne(
|
|
7879
|
+
transformed,
|
|
7880
|
+
"\tconst bindingStates = {};",
|
|
7881
|
+
"\tconst bindingStates = {};\n\t/** @type {Map<number, Map<number, NativeBindingState>>} */\n\tconst fastBindingStates = new Map();",
|
|
7882
|
+
fileName,
|
|
7883
|
+
"WebGLBindingStates numeric front cache",
|
|
7884
|
+
);
|
|
7885
|
+
transformed = replaceOne(
|
|
7886
|
+
transformed,
|
|
7887
|
+
"\t\tconst wireframe = ( material.wireframe === true );\n\n\t\tlet objectMap = bindingStates[ geometry.id ];",
|
|
7888
|
+
`\t\tconst wireframe = ( material.wireframe === true );
|
|
7889
|
+
\t\tconst fastKey = program.id < 65536 ? ( ( ( object.isInstancedMesh === true ) ? object.id : 0 ) * 65536 + program.id ) * 2 + ( wireframe ? 1 : 0 ) : - 1;
|
|
7890
|
+
\t\tlet fastGeometry = fastBindingStates.get( geometry.id );
|
|
7891
|
+
|
|
7892
|
+
\t\tif ( fastKey >= 0 && fastGeometry !== undefined ) {
|
|
7893
|
+
|
|
7894
|
+
\t\t\tconst cached = fastGeometry.get( fastKey );
|
|
7895
|
+
|
|
7896
|
+
\t\t\tif ( cached !== undefined ) return cached;
|
|
7897
|
+
|
|
7898
|
+
\t\t}
|
|
7899
|
+
|
|
7900
|
+
\t\tlet objectMap = bindingStates[ geometry.id ];`,
|
|
7901
|
+
fileName,
|
|
7902
|
+
"WebGLBindingStates numeric front cache read",
|
|
7903
|
+
);
|
|
7904
|
+
transformed = replaceOne(
|
|
7905
|
+
transformed,
|
|
7906
|
+
"\t\t\tstateMap[ wireframeKey ] = state;\n\n\t\t}\n\n\t\treturn state;",
|
|
7907
|
+
`\t\t\tstateMap[ wireframeKey ] = state;
|
|
7908
|
+
|
|
7909
|
+
\t\t}
|
|
7910
|
+
|
|
7911
|
+
\t\tif ( fastKey >= 0 ) {
|
|
7912
|
+
|
|
7913
|
+
\t\t\tif ( fastGeometry === undefined ) {
|
|
7914
|
+
|
|
7915
|
+
\t\t\t\tfastGeometry = new Map();
|
|
7916
|
+
\t\t\t\tfastBindingStates.set( geometry.id, fastGeometry );
|
|
7917
|
+
|
|
7918
|
+
\t\t\t}
|
|
7919
|
+
|
|
7920
|
+
\t\t\tfastGeometry.set( fastKey, state );
|
|
7921
|
+
|
|
7922
|
+
\t\t}
|
|
7923
|
+
|
|
7924
|
+
\t\treturn state;`,
|
|
7925
|
+
fileName,
|
|
7926
|
+
"WebGLBindingStates numeric front cache write",
|
|
7927
|
+
);
|
|
7928
|
+
for (const header of [
|
|
7929
|
+
"\tfunction dispose() {\n\n\t\treset();",
|
|
7930
|
+
"\tfunction releaseStatesOfGeometry( geometry ) {",
|
|
7931
|
+
"\tfunction releaseStatesOfProgram( program ) {",
|
|
7932
|
+
"\tfunction releaseStatesOfObject( object ) {",
|
|
7933
|
+
]) {
|
|
7934
|
+
transformed = replaceOne(
|
|
7935
|
+
transformed,
|
|
7936
|
+
header,
|
|
7937
|
+
`${header}\n\n\t\tfastBindingStates.clear();`,
|
|
7938
|
+
fileName,
|
|
7939
|
+
"WebGLBindingStates numeric front cache release",
|
|
7940
|
+
);
|
|
7941
|
+
}
|
|
7316
7942
|
transformed = replaceOne(
|
|
7317
7943
|
transformed,
|
|
7318
7944
|
"\tfunction releaseStatesOfGeometry( geometry ) {",
|
|
@@ -7407,9 +8033,48 @@ ${indent}}`,
|
|
|
7407
8033
|
"geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;",
|
|
7408
8034
|
"geometry._maxInstanceCount = requireVertexScalar( geometryAttribute.meshPerAttribute ) * requireVertexScalar( geometryAttribute.count );",
|
|
7409
8035
|
);
|
|
8036
|
+
// needsUpdate walked the program's attributes by name on every draw: two
|
|
8037
|
+
// string-keyed lookups per attribute. A binding state is already specific
|
|
8038
|
+
// to its geometry and program, so the set it cached can only change when
|
|
8039
|
+
// the geometry's attribute set changes (setAttribute/deleteAttribute bump
|
|
8040
|
+
// __nativeAttributeStamp) or the object's instance attributes are replaced.
|
|
8041
|
+
// With both unchanged the walk's answer is the index comparison alone.
|
|
8042
|
+
transformed = replaceOne(
|
|
8043
|
+
transformed,
|
|
8044
|
+
"\t\t\tindex: /** @type {import('../../core/BufferAttribute.js').BufferAttribute|null} */ ( null )\n",
|
|
8045
|
+
"\t\t\tindex: /** @type {import('../../core/BufferAttribute.js').BufferAttribute|null} */ ( null ),\n" +
|
|
8046
|
+
"\t\t\tnativeAttributeStamp: - 1,\n" +
|
|
8047
|
+
"\t\t\t/** @type {import('../../core/InstancedBufferAttribute.js').InstancedBufferAttribute|null} */\n" +
|
|
8048
|
+
"\t\t\tnativeInstanceMatrix: null,\n" +
|
|
8049
|
+
"\t\t\t/** @type {import('../../core/InstancedBufferAttribute.js').InstancedBufferAttribute|null} */\n" +
|
|
8050
|
+
"\t\t\tnativeInstanceColor: null\n",
|
|
8051
|
+
fileName,
|
|
8052
|
+
"WebGLBindingStates attribute-set stamp fields",
|
|
8053
|
+
);
|
|
8054
|
+
transformed = replaceOne(
|
|
8055
|
+
transformed,
|
|
8056
|
+
"\tfunction needsUpdate( object, geometry, program, index ) {\n",
|
|
8057
|
+
"\tfunction needsUpdate( object, geometry, program, index ) {\n\n" +
|
|
8058
|
+
"\t\tconst instanced = object instanceof InstancedMesh ? object : null;\n" +
|
|
8059
|
+
"\t\tif ( currentState.nativeAttributeStamp === geometry.__nativeAttributeStamp &&\n" +
|
|
8060
|
+
"\t\t\tcurrentState.nativeInstanceMatrix === ( instanced !== null ? instanced.instanceMatrix : null ) &&\n" +
|
|
8061
|
+
"\t\t\tcurrentState.nativeInstanceColor === ( instanced !== null ? instanced.instanceColor : null ) ) return currentState.index !== index;\n",
|
|
8062
|
+
fileName,
|
|
8063
|
+
"WebGLBindingStates attribute-set fast path",
|
|
8064
|
+
);
|
|
8065
|
+
transformed = replaceOne(
|
|
8066
|
+
transformed,
|
|
8067
|
+
"\t\tcurrentState.attributes = cache;\n\t\tcurrentState.attributesNum = attributesNum;\n",
|
|
8068
|
+
"\t\tcurrentState.attributes = cache;\n\t\tcurrentState.attributesNum = attributesNum;\n" +
|
|
8069
|
+
"\t\tcurrentState.nativeAttributeStamp = geometry.__nativeAttributeStamp;\n" +
|
|
8070
|
+
"\t\tcurrentState.nativeInstanceMatrix = object instanceof InstancedMesh ? object.instanceMatrix : null;\n" +
|
|
8071
|
+
"\t\tcurrentState.nativeInstanceColor = object instanceof InstancedMesh ? object.instanceColor : null;\n",
|
|
8072
|
+
fileName,
|
|
8073
|
+
"WebGLBindingStates attribute-set stamp record",
|
|
8074
|
+
);
|
|
7410
8075
|
}
|
|
7411
8076
|
if (normalized.endsWith("/three/src/renderers/webgl/WebGLObjects.js")) {
|
|
7412
|
-
transformed = `import { BufferGeometry } from '../../core/BufferGeometry.js';\n\n${transformed}`;
|
|
8077
|
+
transformed = `import { BufferGeometry } from '../../core/BufferGeometry.js';\nimport { Object3D } from '../../core/Object3D.js';\n\n${transformed}`;
|
|
7413
8078
|
transformed = replaceOne(
|
|
7414
8079
|
transformed,
|
|
7415
8080
|
"\t\tconst instancedMesh = event.target;",
|
|
@@ -7454,13 +8119,52 @@ ${indent}}`,
|
|
|
7454
8119
|
"updateMap.set( skeleton, frame )",
|
|
7455
8120
|
"skeletonUpdateMap.set( skeleton, frame )",
|
|
7456
8121
|
);
|
|
8122
|
+
// Every pass updates every drawn object, and each update read the geometry's
|
|
8123
|
+
// (and an instanced mesh's) frame out of a WeakMap. The maps stay the
|
|
8124
|
+
// authority; the geometry and object also carry the frame this instance
|
|
8125
|
+
// stored, tagged with its number, so the per-draw read is a field load.
|
|
8126
|
+
transformed = replaceOne(
|
|
8127
|
+
transformed,
|
|
8128
|
+
"function WebGLObjects( gl, geometries, attributes, bindingStates, info ) {\n",
|
|
8129
|
+
"let nextNativeObjectsOwner = 1;\n\nfunction WebGLObjects( gl, geometries, attributes, bindingStates, info ) {\n\n\tconst nativeOwner = nextNativeObjectsOwner ++;\n",
|
|
8130
|
+
fileName,
|
|
8131
|
+
"WebGLObjects front cache owner",
|
|
8132
|
+
);
|
|
7457
8133
|
transformed = replaceOne(
|
|
7458
8134
|
transformed,
|
|
7459
8135
|
"\t\tif ( geometryUpdateMap.get( buffergeometry ) !== frame ) {",
|
|
7460
|
-
"\t\tconst geometryFrame = geometryUpdateMap.get( buffergeometry );\n\n\t\tif ( geometryFrame !== frame ) {",
|
|
8136
|
+
"\t\tconst geometryFrame = buffergeometry.__nativeObjectsOwner === nativeOwner ? buffergeometry.__nativeObjectsFrame : geometryUpdateMap.get( buffergeometry );\n\n\t\tif ( geometryFrame !== frame ) {",
|
|
7461
8137
|
fileName,
|
|
7462
8138
|
"WebGLObjects stable geometry frame lookup",
|
|
7463
8139
|
);
|
|
8140
|
+
transformed = replaceOne(
|
|
8141
|
+
transformed,
|
|
8142
|
+
"\t\t\tgeometryUpdateMap.set( buffergeometry, frame );",
|
|
8143
|
+
"\t\t\tgeometryUpdateMap.set( buffergeometry, frame );\n\t\t\tbuffergeometry.__nativeObjectsOwner = nativeOwner;\n\t\t\tbuffergeometry.__nativeObjectsFrame = frame;",
|
|
8144
|
+
fileName,
|
|
8145
|
+
"WebGLObjects geometry frame front cache",
|
|
8146
|
+
);
|
|
8147
|
+
transformed = replaceOne(
|
|
8148
|
+
transformed,
|
|
8149
|
+
"\t\t\tif ( instancedMeshUpdateMap.get( object ) !== frame ) {",
|
|
8150
|
+
"\t\t\tif ( ( object.__nativeObjectsOwner === nativeOwner ? object.__nativeObjectsFrame : instancedMeshUpdateMap.get( object ) ) !== frame ) {",
|
|
8151
|
+
fileName,
|
|
8152
|
+
"WebGLObjects instanced frame lookup",
|
|
8153
|
+
);
|
|
8154
|
+
transformed = replaceOne(
|
|
8155
|
+
transformed,
|
|
8156
|
+
"\t\t\t\tinstancedMeshUpdateMap.set( object, frame );",
|
|
8157
|
+
"\t\t\t\tinstancedMeshUpdateMap.set( object, frame );\n\t\t\t\tobject.__nativeObjectsOwner = nativeOwner;\n\t\t\t\tobject.__nativeObjectsFrame = frame;",
|
|
8158
|
+
fileName,
|
|
8159
|
+
"WebGLObjects instanced frame front cache",
|
|
8160
|
+
);
|
|
8161
|
+
transformed = replaceOne(
|
|
8162
|
+
transformed,
|
|
8163
|
+
"\t\tinstancedMeshUpdateMap.delete( instancedMesh );",
|
|
8164
|
+
"\t\tinstancedMeshUpdateMap.delete( instancedMesh );\n\n\t\tif ( instancedMesh instanceof Object3D && instancedMesh.__nativeObjectsOwner === nativeOwner ) instancedMesh.__nativeObjectsOwner = 0;",
|
|
8165
|
+
fileName,
|
|
8166
|
+
"WebGLObjects instanced front cache cleanup",
|
|
8167
|
+
);
|
|
7464
8168
|
transformed = replaceOne(
|
|
7465
8169
|
transformed,
|
|
7466
8170
|
"\t\t\tgeometries.update( buffergeometry );",
|
|
@@ -7487,6 +8191,7 @@ ${indent}}`,
|
|
|
7487
8191
|
|
|
7488
8192
|
\t\tbuffergeometry.removeEventListener( 'dispose', onBufferGeometryDispose );
|
|
7489
8193
|
\t\tgeometryUpdateMap.delete( buffergeometry );
|
|
8194
|
+
\t\tif ( buffergeometry.__nativeObjectsOwner === nativeOwner ) buffergeometry.__nativeObjectsOwner = 0;
|
|
7490
8195
|
|
|
7491
8196
|
\t}
|
|
7492
8197
|
|
|
@@ -7582,12 +8287,22 @@ class NativeWebGLPropertyBag {
|
|
|
7582
8287
|
\t\tthis.needsLights = undefined;
|
|
7583
8288
|
\t\t/** @type {number} */
|
|
7584
8289
|
\t\tthis.lightsStateVersion = -1;
|
|
8290
|
+
\t\t/** @type {number} light structure (WebGLLights nativeStructure) the program was built for */
|
|
8291
|
+
\t\tthis.nativeLightsStructure = -1;
|
|
8292
|
+
\t\t/** @type {number} shadow caster count the program was built for */
|
|
8293
|
+
\t\tthis.nativeShadowCount = -1;
|
|
7585
8294
|
\t\t/** @type {boolean|import('./WebGLRenderStates.js').NativeLightProbeGrid|null} */
|
|
7586
8295
|
\t\tthis.lightProbeGrid = null;
|
|
7587
8296
|
\t\t/** @type {import('../shaders/UniformsLib.js').NativeUniforms} */
|
|
7588
8297
|
\t\tthis.uniforms = {};
|
|
7589
8298
|
\t\t/** @type {Array<import('./WebGLUniforms.js').NativeUniform>|null} */
|
|
7590
8299
|
\t\tthis.uniformsList = null;
|
|
8300
|
+
\t\t/** @type {Array<import('../shaders/UniformsLib.js').NativeUniformSlot|undefined>|undefined} The value cells of \`uniformsList\`, in order. */
|
|
8301
|
+
\t\tthis.nativeUniformSlots = undefined;
|
|
8302
|
+
\t\t/** @type {Array<import('./WebGLUniforms.js').NativeUniform>|null} The list \`nativeUniformSlots\` was resolved for. */
|
|
8303
|
+
\t\tthis.nativeUniformSlotsList = null;
|
|
8304
|
+
\t\t/** @type {NativeMaterialCells|undefined} */
|
|
8305
|
+
\t\tthis.nativeCells = undefined;
|
|
7591
8306
|
\t\t/** @type {string} */
|
|
7592
8307
|
\t\tthis.outputColorSpace = '';
|
|
7593
8308
|
\t\t/** @type {boolean} */
|
|
@@ -7651,49 +8366,148 @@ class NativeWebGLPropertyBag {
|
|
|
7651
8366
|
|
|
7652
8367
|
}
|
|
7653
8368
|
|
|
8369
|
+
/**
|
|
8370
|
+
* The value cells of one material uniforms object that WebGLRenderer touches on
|
|
8371
|
+
* every draw or every refresh, resolved once instead of by name each time.
|
|
8372
|
+
* Built for one uniforms object; a material given another gets a new one.
|
|
8373
|
+
*/
|
|
8374
|
+
class NativeMaterialCells {
|
|
8375
|
+
|
|
8376
|
+
\t/** @param {import('../shaders/UniformsLib.js').NativeUniforms} uniforms */
|
|
8377
|
+
\tconstructor( uniforms ) {
|
|
8378
|
+
|
|
8379
|
+
\t\tthis.uniforms = uniforms;
|
|
8380
|
+
\t\t/** @type {import('../shaders/UniformsLib.js').NativeUniformSlot|undefined} */
|
|
8381
|
+
\t\tthis.envMapIntensity = uniforms.envMapIntensity;
|
|
8382
|
+
\t\t/** @type {import('../shaders/UniformsLib.js').NativeUniformSlot|undefined} */
|
|
8383
|
+
\t\tthis.dfgLUT = uniforms.dfgLUT;
|
|
8384
|
+
\t\t/** @type {Array<import('../shaders/UniformsLib.js').NativeUniformSlot>} The light cells markUniformsLightsNeedsUpdate flags. */
|
|
8385
|
+
\t\tthis.lights = [];
|
|
8386
|
+
\t\tfor ( const name of [ 'ambientLightColor', 'lightProbe', 'directionalLights', 'directionalLightShadows', 'pointLights', 'pointLightShadows', 'spotLights', 'spotLightShadows', 'rectAreaLights', 'hemisphereLights' ] ) {
|
|
8387
|
+
|
|
8388
|
+
\t\t\tconst cell = uniforms[ name ];
|
|
8389
|
+
\t\t\tif ( cell !== undefined ) this.lights.push( cell );
|
|
8390
|
+
|
|
8391
|
+
\t\t}
|
|
8392
|
+
|
|
8393
|
+
\t}
|
|
8394
|
+
|
|
8395
|
+
}
|
|
8396
|
+
|
|
8397
|
+
let nextNativePropertiesOwner = 1;
|
|
8398
|
+
|
|
7654
8399
|
function WebGLProperties() {
|
|
7655
8400
|
|
|
7656
|
-
\
|
|
7657
|
-
\tconst properties = new Map();
|
|
8401
|
+
\tlet nativeOwner = nextNativePropertiesOwner ++;
|
|
7658
8402
|
|
|
7659
|
-
\t
|
|
7660
|
-
\
|
|
8403
|
+
\t// One map per owner kind, keyed by the owner's numeric id: a lookup per draw
|
|
8404
|
+
\t// hashes a number instead of building and hashing a 'kind:id' string. A render
|
|
8405
|
+
\t// target is keyed by its texture's id in its own map, as before.
|
|
8406
|
+
\t/** @type {Map<number, NativeWebGLPropertyBag>} */
|
|
8407
|
+
\tconst materials = new Map();
|
|
8408
|
+
\t/** @type {Map<number, NativeWebGLPropertyBag>} */
|
|
8409
|
+
\tconst sources = new Map();
|
|
8410
|
+
\t/** @type {Map<number, NativeWebGLPropertyBag>} */
|
|
8411
|
+
\tconst textures = new Map();
|
|
8412
|
+
\t/** @type {Map<number, NativeWebGLPropertyBag>} */
|
|
8413
|
+
\tconst targets = new Map();
|
|
8414
|
+
|
|
8415
|
+
\t/** @param {WebGLPropertyOwner} object @return {Map<number, NativeWebGLPropertyBag>} */
|
|
8416
|
+
\tfunction propertyMap( object ) {
|
|
8417
|
+
|
|
8418
|
+
\t\tif ( object instanceof Material ) return materials;
|
|
8419
|
+
\t\tif ( object instanceof Source ) return sources;
|
|
8420
|
+
\t\tif ( object instanceof Texture ) return textures;
|
|
8421
|
+
\t\treturn targets;
|
|
8422
|
+
|
|
8423
|
+
\t}
|
|
8424
|
+
|
|
8425
|
+
\t/** @param {WebGLPropertyOwner} object @return {number} */
|
|
8426
|
+
\tfunction propertyId( object ) {
|
|
8427
|
+
|
|
8428
|
+
\t\tif ( object instanceof Material ) return object.id;
|
|
8429
|
+
\t\tif ( object instanceof Source ) return object.id;
|
|
8430
|
+
\t\tif ( object instanceof Texture ) return object.id;
|
|
8431
|
+
\t\treturn object.texture.id;
|
|
8432
|
+
|
|
8433
|
+
\t}
|
|
8434
|
+
|
|
8435
|
+
\t/** @param {Map<number, NativeWebGLPropertyBag>} map @param {number} id @return {NativeWebGLPropertyBag} */
|
|
8436
|
+
\tfunction bagIn( map, id ) {
|
|
8437
|
+
|
|
8438
|
+
\t\tlet bag = map.get( id );
|
|
8439
|
+
|
|
8440
|
+
\t\tif ( bag === undefined ) {
|
|
8441
|
+
|
|
8442
|
+
\t\t\tbag = new NativeWebGLPropertyBag();
|
|
8443
|
+
\t\t\tmap.set( id, bag );
|
|
8444
|
+
|
|
8445
|
+
\t\t}
|
|
7661
8446
|
|
|
7662
|
-
\t\
|
|
7663
|
-
\t\tif ( object instanceof Source ) return 'source:' + object.id;
|
|
7664
|
-
\t\tif ( object instanceof Texture ) return 'texture:' + object.id;
|
|
7665
|
-
\t\treturn 'target:' + object.texture.id;
|
|
8447
|
+
\t\treturn bag;
|
|
7666
8448
|
|
|
7667
8449
|
\t}
|
|
7668
8450
|
|
|
7669
8451
|
\t/** @param {WebGLPropertyOwner} object */
|
|
7670
8452
|
\tfunction has( object ) {
|
|
7671
8453
|
|
|
7672
|
-
\t\treturn
|
|
8454
|
+
\t\treturn propertyMap( object ).has( propertyId( object ) );
|
|
7673
8455
|
|
|
7674
8456
|
\t}
|
|
7675
8457
|
|
|
7676
8458
|
\t/** @param {WebGLPropertyOwner} object */
|
|
7677
8459
|
\tfunction get( object ) {
|
|
7678
8460
|
|
|
7679
|
-
\t\
|
|
7680
|
-
\t\
|
|
8461
|
+
\t\t// Materials, sources and textures are read on every draw (textures once per
|
|
8462
|
+
\t\t// bound sampler). Each also carries the bag this instance stored for it,
|
|
8463
|
+
\t\t// tagged with the instance's number, so the read is a field load; the maps
|
|
8464
|
+
\t\t// stay the authority and remove/dispose keep the fields in step.
|
|
8465
|
+
\t\tif ( object instanceof Material ) {
|
|
8466
|
+
|
|
8467
|
+
\t\t\tif ( object.__nativePropertiesOwner === nativeOwner && object.__nativeProperties !== undefined ) return object.__nativeProperties;
|
|
8468
|
+
\t\t\tconst bag = bagIn( materials, object.id );
|
|
8469
|
+
\t\t\tobject.__nativePropertiesOwner = nativeOwner;
|
|
8470
|
+
\t\t\tobject.__nativeProperties = bag;
|
|
8471
|
+
\t\t\treturn bag;
|
|
7681
8472
|
|
|
7682
|
-
\t\
|
|
8473
|
+
\t\t}
|
|
8474
|
+
\t\tif ( object instanceof Source ) {
|
|
7683
8475
|
|
|
7684
|
-
\t\t\
|
|
7685
|
-
\t\t\
|
|
8476
|
+
\t\t\tif ( object.__nativePropertiesOwner === nativeOwner && object.__nativeProperties !== undefined ) return object.__nativeProperties;
|
|
8477
|
+
\t\t\tconst bag = bagIn( sources, object.id );
|
|
8478
|
+
\t\t\tobject.__nativePropertiesOwner = nativeOwner;
|
|
8479
|
+
\t\t\tobject.__nativeProperties = bag;
|
|
8480
|
+
\t\t\treturn bag;
|
|
7686
8481
|
|
|
7687
8482
|
\t\t}
|
|
8483
|
+
\t\tif ( object instanceof Texture ) {
|
|
7688
8484
|
|
|
7689
|
-
\t\
|
|
8485
|
+
\t\t\tif ( object.__nativePropertiesOwner === nativeOwner && object.__nativeProperties !== undefined ) return object.__nativeProperties;
|
|
8486
|
+
\t\t\tconst bag = bagIn( textures, object.id );
|
|
8487
|
+
\t\t\tobject.__nativePropertiesOwner = nativeOwner;
|
|
8488
|
+
\t\t\tobject.__nativeProperties = bag;
|
|
8489
|
+
\t\t\treturn bag;
|
|
8490
|
+
|
|
8491
|
+
\t\t}
|
|
8492
|
+
\t\treturn bagIn( targets, object.texture.id );
|
|
7690
8493
|
|
|
7691
8494
|
\t}
|
|
7692
8495
|
|
|
7693
8496
|
\t/** @param {WebGLPropertyOwner} object */
|
|
7694
8497
|
\tfunction remove( object ) {
|
|
7695
8498
|
|
|
7696
|
-
\t\
|
|
8499
|
+
\t\tpropertyMap( object ).delete( propertyId( object ) );
|
|
8500
|
+
|
|
8501
|
+
\t\tif ( object instanceof Material || object instanceof Source || object instanceof Texture ) {
|
|
8502
|
+
|
|
8503
|
+
\t\t\tif ( object.__nativePropertiesOwner === nativeOwner ) {
|
|
8504
|
+
|
|
8505
|
+
\t\t\t\tobject.__nativePropertiesOwner = 0;
|
|
8506
|
+
\t\t\t\tobject.__nativeProperties = undefined;
|
|
8507
|
+
|
|
8508
|
+
\t\t\t}
|
|
8509
|
+
|
|
8510
|
+
\t\t}
|
|
7697
8511
|
|
|
7698
8512
|
\t}
|
|
7699
8513
|
|
|
@@ -7710,7 +8524,12 @@ function WebGLProperties() {
|
|
|
7710
8524
|
|
|
7711
8525
|
\tfunction dispose() {
|
|
7712
8526
|
|
|
7713
|
-
\t\
|
|
8527
|
+
\t\tmaterials.clear();
|
|
8528
|
+
\t\tsources.clear();
|
|
8529
|
+
\t\ttextures.clear();
|
|
8530
|
+
\t\ttargets.clear();
|
|
8531
|
+
\t\t// Every field still tagged with the old number is now stale.
|
|
8532
|
+
\t\tnativeOwner = nextNativePropertiesOwner ++;
|
|
7714
8533
|
|
|
7715
8534
|
\t}
|
|
7716
8535
|
|
|
@@ -7718,7 +8537,7 @@ function WebGLProperties() {
|
|
|
7718
8537
|
|
|
7719
8538
|
}
|
|
7720
8539
|
|
|
7721
|
-
export { WebGLProperties };
|
|
8540
|
+
export { WebGLProperties, NativeWebGLPropertyBag, NativeMaterialCells };
|
|
7722
8541
|
`;
|
|
7723
8542
|
}
|
|
7724
8543
|
if (normalized.endsWith("/three/src/renderers/webgl/WebGLInfo.js")) {
|
|
@@ -8842,9 +9661,31 @@ function WebGLRenderState( extensions ) {`,
|
|
|
8842
9661
|
|
|
8843
9662
|
\t\t\trenderTarget.depthTexture.image.width = renderTarget.width;
|
|
8844
9663
|
\t\t\trenderTarget.depthTexture.image.height = renderTarget.height;`,
|
|
8845
|
-
`\t\
|
|
9664
|
+
`\t\t// A render target disposed before it was set up again has no onRenderTargetDispose listener, so a
|
|
9665
|
+
\t\t// second dispose (RenderTarget.setSize) leaves its depth texture alone; and a material that samples
|
|
9666
|
+
\t\t// that depth texture meanwhile re-uploads it at its old image size (setSize does not resize
|
|
9667
|
+
\t\t// depthTexture.image). The size check below then only marks it needsUpdate, which never re-specifies
|
|
9668
|
+
\t\t// immutable texStorage2D storage: the target was set up with a depth attachment of the old size (a
|
|
9669
|
+
\t\t// multisample resolve past it removes the D3D12 device; WebGL reports FRAMEBUFFER_INCOMPLETE_DIMENSIONS).
|
|
9670
|
+
\t\t// Release that storage here so the upload below allocates it at the target's size.
|
|
9671
|
+
\t\tif ( ! isCube && properties.has( renderTarget.depthTexture ) ) {
|
|
9672
|
+
|
|
9673
|
+
\t\t\tconst allocated = properties.get( renderTarget.depthTexture );
|
|
9674
|
+
\t\t\tconst allocatedImage = requireTextureImageRecord( renderTarget.depthTexture.image );
|
|
9675
|
+
|
|
9676
|
+
\t\t\tif ( allocated.__webglTexture !== undefined && allocated.__webglTexture !== null &&
|
|
9677
|
+
\t\t\t\t( allocatedImage.width !== renderTarget.width || allocatedImage.height !== renderTarget.height ) ) {
|
|
9678
|
+
|
|
9679
|
+
\t\t\t\tdeallocateTexture( renderTarget.depthTexture );
|
|
9680
|
+
|
|
9681
|
+
\t\t\t}
|
|
9682
|
+
|
|
9683
|
+
\t\t}
|
|
9684
|
+
|
|
9685
|
+
\t\tconst textureProperties = properties.get( renderTarget.depthTexture );
|
|
8846
9686
|
\t\ttextureProperties.__renderTarget = renderTarget;
|
|
8847
|
-
\t\
|
|
9687
|
+
\t\t// A CubeDepthTexture's image is its six face records (one shared object); size it through face 0.
|
|
9688
|
+
\t\tconst depthTextureImage = isCube ? requireTextureImageRecords( renderTarget.depthTexture.image )[ 0 ] : requireTextureImageRecord( renderTarget.depthTexture.image );
|
|
8848
9689
|
|
|
8849
9690
|
\t\t// upload an empty depth texture with framebuffer size
|
|
8850
9691
|
\t\tif ( ! textureProperties.__webglTexture ||
|
|
@@ -8852,7 +9693,10 @@ function WebGLRenderState( extensions ) {`,
|
|
|
8852
9693
|
\t\t\t\tdepthTextureImage.height !== renderTarget.height ) {
|
|
8853
9694
|
|
|
8854
9695
|
\t\t\tdepthTextureImage.width = renderTarget.width;
|
|
8855
|
-
\t\t\tdepthTextureImage.height = renderTarget.height
|
|
9696
|
+
\t\t\tdepthTextureImage.height = renderTarget.height;
|
|
9697
|
+
\t\t\t// requireTextureImageRecord returns a copy, so a 2D depth texture's own image must be replaced
|
|
9698
|
+
\t\t\t// for the upload below to use the new size (upstream writes the image in place).
|
|
9699
|
+
\t\t\tif ( ! isCube ) renderTarget.depthTexture.image = { width: renderTarget.width, height: renderTarget.height, depth: depthTextureImage.depth !== undefined ? depthTextureImage.depth : 1 };`,
|
|
8856
9700
|
fileName,
|
|
8857
9701
|
"WebGLTextures depth image record narrowing",
|
|
8858
9702
|
);
|
|
@@ -8933,7 +9777,9 @@ function WebGLRenderState( extensions ) {`,
|
|
|
8933
9777
|
);
|
|
8934
9778
|
transformed =
|
|
8935
9779
|
transformed.slice(0, dimensionsStartIndex) +
|
|
8936
|
-
|
|
9780
|
+
// The records reaching here already carry width and height; passing them through
|
|
9781
|
+
// requireTextureImageRecord recasts them into a nested union the emitter drops to undefined.
|
|
9782
|
+
"\tfunction getDimensions( image ) {\n\n\t\t_imageDimensions.width = image.width;\n\t\t_imageDimensions.height = image.height;\n\n\t\treturn _imageDimensions;" +
|
|
8937
9783
|
transformed.slice(dimensionsEndIndex);
|
|
8938
9784
|
transformed = replaceOne(
|
|
8939
9785
|
transformed,
|
|
@@ -10210,6 +11056,11 @@ class Texture extends EventDispatcher {`,
|
|
|
10210
11056
|
fileName,
|
|
10211
11057
|
"native volume texture source image",
|
|
10212
11058
|
);
|
|
11059
|
+
// Same JSDoc defect as DataTexture: a number documented as `boolean`. Without
|
|
11060
|
+
// the correction an array texture is not a Texture and cannot be a uniform.
|
|
11061
|
+
transformed = transformed
|
|
11062
|
+
.replace(dataTextureUnpackAlignmentSource, nativeDataTextureUnpackAlignmentSource)
|
|
11063
|
+
.replace(dataTextureOverlayUnpackAlignmentSource, nativeDataTextureOverlayUnpackAlignmentSource);
|
|
10213
11064
|
}
|
|
10214
11065
|
if (normalized.endsWith("/three/src/textures/ExternalTexture.js")) {
|
|
10215
11066
|
transformed = replaceOne(
|
|
@@ -10468,7 +11319,7 @@ export default {
|
|
|
10468
11319
|
embeddedHostNoThrowFunctions,
|
|
10469
11320
|
hostNativeArrayFunctions: hostFunctions
|
|
10470
11321
|
.filter(([, , , declaration]) =>
|
|
10471
|
-
declaration.includes("HostNumericArgument<"),
|
|
11322
|
+
declaration.includes("HostNumericArgument<") || declaration.includes("void* bytes"),
|
|
10472
11323
|
)
|
|
10473
11324
|
.map(([, cppName]) => cppName),
|
|
10474
11325
|
hostArraySnapshotFunctions: hostFunctions
|