Skip to content

Commit 53451ad

Browse files
committed
NodeMaterialObserver: Speed up geometry comparisons.
1 parent a7495fd commit 53451ad

File tree

1 file changed

+107
-49
lines changed

1 file changed

+107
-49
lines changed

src/materials/nodes/manager/NodeMaterialObserver.js

Lines changed: 107 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ const _lightsCache = new WeakMap();
7373
*/
7474
const _materialCache = new WeakMap();
7575

76+
/**
77+
* Holds the geometry data for comparison.
78+
*
79+
* @private
80+
* @type {WeakMap<BufferGeometry,Object>}
81+
*/
82+
const _geometryCache = new WeakMap();
83+
7684
/**
7785
* This class is used by {@link WebGPURenderer} as management component.
7886
* It's primary purpose is to determine whether render objects require a
@@ -177,13 +185,7 @@ class NodeMaterialObserver {
177185
const { geometry, object } = renderObject;
178186

179187
data = {
180-
geometry: {
181-
id: geometry.id,
182-
attributes: this.getAttributesData( geometry.attributes ),
183-
indexId: geometry.index ? geometry.index.id : null,
184-
indexVersion: geometry.index ? geometry.index.version : null,
185-
drawRange: { start: geometry.drawRange.start, count: geometry.drawRange.count }
186-
},
188+
geometryId: geometry.id,
187189
worldMatrix: object.matrixWorld.clone()
188190
};
189191

@@ -275,6 +277,37 @@ class NodeMaterialObserver {
275277

276278
}
277279

280+
/**
281+
* Returns a geometry data structure holding the geometry property values for
282+
* monitoring.
283+
*
284+
* @param {BufferGeometry} geometry - The geometry.
285+
* @return {Object} An object for monitoring geometry properties.
286+
*/
287+
getGeometryData( geometry ) {
288+
289+
let data = _geometryCache.get( geometry );
290+
291+
if ( data === undefined ) {
292+
293+
data = {
294+
_renderId: - 1,
295+
_equal: false,
296+
297+
attributes: this.getAttributesData( geometry.attributes ),
298+
indexId: geometry.index ? geometry.index.id : null,
299+
indexVersion: geometry.index ? geometry.index.version : null,
300+
drawRange: { start: geometry.drawRange.start, count: geometry.drawRange.count }
301+
};
302+
303+
_geometryCache.set( geometry, data );
304+
305+
}
306+
307+
return data;
308+
309+
}
310+
278311
/**
279312
* Returns a material data structure holding the material property values for
280313
* monitoring.
@@ -426,79 +459,104 @@ class NodeMaterialObserver {
426459

427460
// geometry
428461

429-
const storedGeometryData = renderObjectData.geometry;
430-
const attributes = geometry.attributes;
431-
const storedAttributes = storedGeometryData.attributes;
432-
433-
if ( storedGeometryData.id !== geometry.id ) {
462+
if ( renderObjectData.geometryId !== geometry.id ) {
434463

435-
storedGeometryData.id = geometry.id;
464+
renderObjectData.geometryId = geometry.id;
436465
return false;
437466

438467
}
439468

440-
// attributes
469+
const geometryData = this.getGeometryData( renderObject.geometry );
441470

442-
let currentAttributeCount = 0;
443-
let storedAttributeCount = 0;
471+
// check the geoemtry for the "equal" state just once per render for all render objects
444472

445-
for ( const _ in attributes ) currentAttributeCount ++; // eslint-disable-line no-unused-vars
473+
if ( geometryData._renderId !== renderId ) {
446474

447-
for ( const name in storedAttributes ) {
475+
geometryData._renderId = renderId;
448476

449-
storedAttributeCount ++;
477+
// attributes
450478

451-
const storedAttributeData = storedAttributes[ name ];
452-
const attribute = attributes[ name ];
479+
const attributes = geometry.attributes;
480+
const storedAttributes = geometryData.attributes;
453481

454-
if ( attribute === undefined ) {
482+
let currentAttributeCount = 0;
483+
let storedAttributeCount = 0;
455484

456-
// attribute was removed
457-
delete storedAttributes[ name ];
458-
return false;
485+
for ( const _ in attributes ) currentAttributeCount ++; // eslint-disable-line no-unused-vars
486+
487+
for ( const name in storedAttributes ) {
488+
489+
storedAttributeCount ++;
490+
491+
const storedAttributeData = storedAttributes[ name ];
492+
const attribute = attributes[ name ];
493+
494+
if ( attribute === undefined ) {
495+
496+
// attribute was removed
497+
delete storedAttributes[ name ];
498+
499+
geometryData._equal = false;
500+
return false;
501+
502+
}
503+
504+
if ( storedAttributeData.id !== attribute.id || storedAttributeData.version !== attribute.version ) {
505+
506+
storedAttributeData.id = attribute.id;
507+
storedAttributeData.version = attribute.version;
508+
509+
geometryData._equal = false;
510+
return false;
511+
512+
}
459513

460514
}
461515

462-
if ( storedAttributeData.id !== attribute.id || storedAttributeData.version !== attribute.version ) {
516+
if ( storedAttributeCount !== currentAttributeCount ) {
463517

464-
storedAttributeData.id = attribute.id;
465-
storedAttributeData.version = attribute.version;
518+
geometryData.attributes = this.getAttributesData( attributes );
519+
520+
geometryData._equal = false;
466521
return false;
467522

468523
}
469524

470-
}
525+
// check index
471526

472-
if ( storedAttributeCount !== currentAttributeCount ) {
527+
const index = geometry.index;
528+
const storedIndexId = geometryData.indexId;
529+
const storedIndexVersion = geometryData.indexVersion;
530+
const currentIndexId = index ? index.id : null;
531+
const currentIndexVersion = index ? index.version : null;
473532

474-
renderObjectData.geometry.attributes = this.getAttributesData( attributes );
475-
return false;
533+
if ( storedIndexId !== currentIndexId || storedIndexVersion !== currentIndexVersion ) {
476534

477-
}
535+
geometryData.indexId = currentIndexId;
536+
geometryData.indexVersion = currentIndexVersion;
478537

479-
// check index
538+
geometryData._equal = false;
539+
return false;
480540

481-
const index = geometry.index;
482-
const storedIndexId = storedGeometryData.indexId;
483-
const storedIndexVersion = storedGeometryData.indexVersion;
484-
const currentIndexId = index ? index.id : null;
485-
const currentIndexVersion = index ? index.version : null;
541+
}
486542

487-
if ( storedIndexId !== currentIndexId || storedIndexVersion !== currentIndexVersion ) {
543+
// check drawRange
488544

489-
storedGeometryData.indexId = currentIndexId;
490-
storedGeometryData.indexVersion = currentIndexVersion;
491-
return false;
545+
if ( geometryData.drawRange.start !== geometry.drawRange.start || geometryData.drawRange.count !== geometry.drawRange.count ) {
492546

493-
}
547+
geometryData.drawRange.start = geometry.drawRange.start;
548+
geometryData.drawRange.count = geometry.drawRange.count;
494549

495-
// check drawRange
550+
geometryData._equal = false;
551+
return false;
496552

497-
if ( storedGeometryData.drawRange.start !== geometry.drawRange.start || storedGeometryData.drawRange.count !== geometry.drawRange.count ) {
553+
}
498554

499-
storedGeometryData.drawRange.start = geometry.drawRange.start;
500-
storedGeometryData.drawRange.count = geometry.drawRange.count;
501-
return false;
555+
geometryData._equal = true;
556+
557+
} else {
558+
559+
if ( geometryData._equal === false ) return false;
502560

503561
}
504562

0 commit comments

Comments
 (0)