Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@
"webgpu_materials_displacementmap",
"webgpu_materials_envmaps_bpcem",
"webgpu_materials_envmaps",
"webgpu_materials_debug_rebuild",
"webgpu_materials_lightmap",
"webgpu_materials_matcap",
"webgpu_materials_sss",
Expand Down
65 changes: 63 additions & 2 deletions examples/jsm/inspector/Inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import { Settings } from './tabs/Settings.js';
import { Viewer } from './tabs/Viewer.js';
import { Timeline } from './tabs/Timeline.js';
import { setText } from './ui/utils.js';
import NodeMaterialDebug from './NodeMaterialDebug.js';

import { setConsoleFunction, REVISION } from 'three/webgpu';

class Inspector extends RendererInspector {

constructor() {
constructor( options = {} ) {

super();

Expand Down Expand Up @@ -43,7 +44,12 @@ class Inspector extends RendererInspector {
const timeline = new Timeline();
profiler.addTab( timeline );

const consoleTab = new Console();
const consoleTab = new Console( { traceNodeMaterialInvalidation: options.traceNodeMaterialInvalidation } );
consoleTab.addEventListener( 'trace-node-material-invalidation', ( event ) => {

this.setTraceNodeMaterialInvalidation( event.enabled );

} );
profiler.addTab( consoleTab );

const settings = new Settings();
Expand All @@ -68,6 +74,9 @@ class Inspector extends RendererInspector {
this.settings = settings;
this.once = {};
this.extensionsData = new WeakMap();
this.nodeMaterialDebug = null;
this.onNodeMaterialInvalidation = null;
this.traceNodeMaterialInvalidation = options.traceNodeMaterialInvalidation === true;

this.displayCycle = {
text: {
Expand Down Expand Up @@ -257,21 +266,32 @@ class Inspector extends RendererInspector {

}

this.updateNodeMaterialDebug();

}

setRenderer( renderer ) {

if ( this.nodeMaterialDebug !== null ) {

this.nodeMaterialDebug.dispose();
this.nodeMaterialDebug = null;

}

super.setRenderer( renderer );

if ( renderer !== null ) {

setConsoleFunction( this.resolveConsole.bind( this ) );
this.setTraceNodeMaterialInvalidation( this.traceNodeMaterialInvalidation );

if ( this.isAvailable ) {

renderer.init().then( () => {

renderer.backend.trackTimestamp = true;
this.updateNodeMaterialDebug();

if ( renderer.hasFeature( 'timestamp-query' ) !== true ) {

Expand All @@ -291,6 +311,47 @@ class Inspector extends RendererInspector {

}

updateNodeMaterialDebug() {

if ( this.nodeMaterialDebug !== null ) this.nodeMaterialDebug.updateRenderer();

return this;

}

setTraceNodeMaterialInvalidation( enabled ) {

this.traceNodeMaterialInvalidation = enabled === true;

const renderer = this.getRenderer();

if ( this.traceNodeMaterialInvalidation === true && renderer !== null ) {

if ( this.nodeMaterialDebug === null ) this.nodeMaterialDebug = new NodeMaterialDebug( renderer );
this.nodeMaterialDebug.onNodeMaterialInvalidation = ( event ) => {

const property = event.property !== undefined ? ` via ${ event.property }` : '';
const values = event.previousValue !== undefined && event.value !== undefined ? ` (${ event.previousValue } -> ${ event.value })` : '';
const source = event.sourceProperty !== undefined && event.sourceProperty !== event.property ? ` [${ event.sourceProperty }]` : '';

this.console.addMessage( 'warn', `Renderer: NodeMaterial needs rebuild for "${ event.materialLabel }"${ property }${ values }${ source }.` );

if ( typeof this.onNodeMaterialInvalidation === 'function' ) this.onNodeMaterialInvalidation( event );

};
this.nodeMaterialDebug.updateRenderer();

} else if ( this.nodeMaterialDebug !== null ) {

this.nodeMaterialDebug.dispose();
this.nodeMaterialDebug = null;

}

return this;

}

createParameters( name ) {

if ( this.parameters.isVisible === false ) {
Expand Down
94 changes: 94 additions & 0 deletions examples/jsm/inspector/NodeMaterialDebug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import NodeMaterialDebugAnalyzer from './NodeMaterialDebugAnalyzer.js';

class NodeMaterialDebug {

constructor( renderer ) {

this.renderer = renderer;
this.analyzer = new NodeMaterialDebugAnalyzer( renderer );
this.onNodeMaterialInvalidation = null;

this._objects = null;
this._originalGet = null;

this.updateRenderer();

}

updateRenderer() {

const renderObjects = this.renderer._objects;

if ( renderObjects === null || renderObjects === undefined || this._objects === renderObjects ) return this;

this.dispose();

const originalGet = renderObjects.get;
const nodeMaterialDebug = this;

renderObjects.get = function ( object, material, scene, camera, lightsNode, renderContext, clippingContext, passId ) {

const chainMap = this.getChainMap( passId );
const previousRenderObject = chainMap.get( [ object, material, renderContext, lightsNode ] );

if ( previousRenderObject !== undefined ) {

previousRenderObject.camera = camera;
previousRenderObject.updateClipping( clippingContext );

if ( previousRenderObject.needsGeometryUpdate ) previousRenderObject.setGeometry( object.geometry );

if ( ( previousRenderObject.version !== material.version || previousRenderObject.needsUpdate ) && previousRenderObject.initialCacheKey !== previousRenderObject.getCacheKey() ) {

nodeMaterialDebug.report( previousRenderObject );

}

}

const renderObject = originalGet.call( this, object, material, scene, camera, lightsNode, renderContext, clippingContext, passId );

nodeMaterialDebug.analyzer.update( renderObject );

return renderObject;

};

this._objects = renderObjects;
this._originalGet = originalGet;

return this;

}

report( renderObject ) {

const previousCallback = this.analyzer.onNodeMaterialInvalidation;

this.analyzer.onNodeMaterialInvalidation = ( event ) => {

if ( typeof this.onNodeMaterialInvalidation === 'function' ) this.onNodeMaterialInvalidation( event );

};

this.analyzer.report( renderObject );
this.analyzer.onNodeMaterialInvalidation = previousCallback;

}

dispose() {

if ( this._objects !== null && this._originalGet !== null ) {

this._objects.get = this._originalGet;

}

this._objects = null;
this._originalGet = null;

}

}

export default NodeMaterialDebug;
Loading
Loading