Skip to content

Commit

Permalink
WebGPURenderer: Fix missing updates to geometry attributes (#29589)
Browse files Browse the repository at this point in the history
* WebGPURenderer: Fix geometry attribute not updated regardless of version

* BufferAttributes don't have uuid

* small cleanup

* more cleanup

* improve geometry comparison performance

* cleanup previous implementation

* attributes have no uuid
  • Loading branch information
RenaudRohlinger authored Oct 9, 2024
1 parent e6e4398 commit 0e17a92
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 10 deletions.
89 changes: 87 additions & 2 deletions src/materials/nodes/manager/NodeMaterialObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,15 @@ class NodeMaterialObserver {

if ( data === undefined ) {

const { geometry, material } = renderObject;

data = {
material: this.getMaterialData( renderObject.material ),
material: this.getMaterialData( material ),
geometry: {
attributes: this.getAttributesData( geometry.attributes ),
indexVersion: geometry.index ? geometry.index.version : null,
drawRange: { start: geometry.drawRange.start, count: geometry.drawRange.count }
},
worldMatrix: renderObject.object.matrixWorld.clone()
};

Expand Down Expand Up @@ -116,6 +123,24 @@ class NodeMaterialObserver {

}

getAttributesData( attributes ) {

const attributesData = {};

for ( const name in attributes ) {

const attribute = attributes[ name ];

attributesData[ name ] = {
version: attribute.version
};

}

return attributesData;

}

containsNode( builder ) {

const material = builder.material;
Expand Down Expand Up @@ -170,7 +195,7 @@ class NodeMaterialObserver {

equals( renderObject ) {

const { object, material } = renderObject;
const { object, material, geometry } = renderObject;

const renderObjectData = this.getRenderObjectData( renderObject );

Expand Down Expand Up @@ -224,6 +249,66 @@ class NodeMaterialObserver {

}

// geometry

const storedGeometryData = renderObjectData.geometry;
const attributes = geometry.attributes;
const storedAttributes = storedGeometryData.attributes;

const storedAttributeNames = Object.keys( storedAttributes );
const currentAttributeNames = Object.keys( attributes );

if ( storedAttributeNames.length !== currentAttributeNames.length ) {

renderObjectData.geometry.attributes = this.getAttributesData( attributes );
return false;

}

// Compare each attribute
for ( const name of storedAttributeNames ) {

const storedAttributeData = storedAttributes[ name ];
const attribute = attributes[ name ];

if ( attribute === undefined ) {

// Attribute was removed
delete storedAttributes[ name ];
return false;

}

if ( storedAttributeData.version !== attribute.version ) {

storedAttributeData.version = attribute.version;
return false;

}

}

// Check index
const index = geometry.index;
const storedIndexVersion = storedGeometryData.indexVersion;
const currentIndexVersion = index ? index.version : null;

if ( storedIndexVersion !== currentIndexVersion ) {

storedGeometryData.indexVersion = currentIndexVersion;
return false;

}

// Check drawRange
if ( storedGeometryData.drawRange.start !== geometry.drawRange.start || storedGeometryData.drawRange.count !== geometry.drawRange.count ) {

storedGeometryData.drawRange.start = geometry.drawRange.start;
storedGeometryData.drawRange.count = geometry.drawRange.count;
return false;

}

// morph targets

if ( renderObjectData.morphTargetInfluences ) {
Expand Down
8 changes: 4 additions & 4 deletions src/renderers/webgl-fallback/WebGLBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,9 +622,9 @@ class WebGLBackend extends Backend {

const contextData = this.get( context );

const drawParms = renderObject.getDrawParameters();
const drawParams = renderObject.getDrawParameters();

if ( drawParms === null ) return;
if ( drawParams === null ) return;

//

Expand Down Expand Up @@ -717,8 +717,8 @@ class WebGLBackend extends Backend {

//

const { vertexCount, instanceCount } = drawParms;
let { firstVertex } = drawParms;
const { vertexCount, instanceCount } = drawParams;
let { firstVertex } = drawParams;

renderer.object = object;

Expand Down
8 changes: 4 additions & 4 deletions src/renderers/webgpu/WebGPUBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -846,9 +846,9 @@ class WebGPUBackend extends Backend {
const currentSets = renderContextData.currentSets;
const passEncoderGPU = renderContextData.currentPass;

const drawParms = renderObject.getDrawParameters();
const drawParams = renderObject.getDrawParameters();

if ( drawParms === null ) return;
if ( drawParams === null ) return;

// pipeline

Expand Down Expand Up @@ -970,15 +970,15 @@ class WebGPUBackend extends Backend {

} else if ( hasIndex === true ) {

const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParms;
const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParams;

passEncoderGPU.drawIndexed( indexCount, instanceCount, firstIndex, 0, 0 );

info.update( object, indexCount, instanceCount );

} else {

const { vertexCount, instanceCount, firstVertex } = drawParms;
const { vertexCount, instanceCount, firstVertex } = drawParams;

passEncoderGPU.draw( vertexCount, instanceCount, firstVertex, 0 );

Expand Down

0 comments on commit 0e17a92

Please sign in to comment.