|
@@ -3,13 +3,13 @@ import WebGPUProgrammableStage from './WebGPUProgrammableStage.js';
|
|
|
|
|
|
class WebGPURenderPipelines {
|
|
class WebGPURenderPipelines {
|
|
|
|
|
|
- constructor( renderer, properties, device, sampleCount, nodes ) {
|
|
|
|
|
|
+ constructor( renderer, device, sampleCount, nodes, bindings = null ) {
|
|
|
|
|
|
this.renderer = renderer;
|
|
this.renderer = renderer;
|
|
- this.properties = properties;
|
|
|
|
this.device = device;
|
|
this.device = device;
|
|
this.sampleCount = sampleCount;
|
|
this.sampleCount = sampleCount;
|
|
this.nodes = nodes;
|
|
this.nodes = nodes;
|
|
|
|
+ this.bindings = bindings;
|
|
|
|
|
|
this.pipelines = [];
|
|
this.pipelines = [];
|
|
this.objectCache = new WeakMap();
|
|
this.objectCache = new WeakMap();
|
|
@@ -24,10 +24,7 @@ class WebGPURenderPipelines {
|
|
get( object ) {
|
|
get( object ) {
|
|
|
|
|
|
const device = this.device;
|
|
const device = this.device;
|
|
- const properties = this.properties;
|
|
|
|
-
|
|
|
|
const material = object.material;
|
|
const material = object.material;
|
|
- const materialProperties = properties.get( material );
|
|
|
|
|
|
|
|
const cache = this._getCache( object );
|
|
const cache = this._getCache( object );
|
|
|
|
|
|
@@ -35,6 +32,14 @@ class WebGPURenderPipelines {
|
|
|
|
|
|
if ( this._needsUpdate( object, cache ) ) {
|
|
if ( this._needsUpdate( object, cache ) ) {
|
|
|
|
|
|
|
|
+ // release previous cache
|
|
|
|
+
|
|
|
|
+ if ( cache.currentPipeline !== undefined ) {
|
|
|
|
+
|
|
|
|
+ this._releaseObject( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
// get shader
|
|
// get shader
|
|
|
|
|
|
const nodeBuilder = this.nodes.get( object );
|
|
const nodeBuilder = this.nodes.get( object );
|
|
@@ -64,37 +69,15 @@ class WebGPURenderPipelines {
|
|
currentPipeline = this._acquirePipeline( stageVertex, stageFragment, object, nodeBuilder );
|
|
currentPipeline = this._acquirePipeline( stageVertex, stageFragment, object, nodeBuilder );
|
|
cache.currentPipeline = currentPipeline;
|
|
cache.currentPipeline = currentPipeline;
|
|
|
|
|
|
- // keep track of all pipelines which are used by a material
|
|
|
|
-
|
|
|
|
- let materialPipelines = materialProperties.pipelines;
|
|
|
|
-
|
|
|
|
- if ( materialPipelines === undefined ) {
|
|
|
|
-
|
|
|
|
- materialPipelines = new Set();
|
|
|
|
- materialProperties.pipelines = materialPipelines;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ( materialPipelines.has( currentPipeline ) === false ) {
|
|
|
|
|
|
+ // keep track of all used times
|
|
|
|
|
|
- materialPipelines.add( currentPipeline );
|
|
|
|
|
|
+ currentPipeline.usedTimes ++;
|
|
|
|
+ stageVertex.usedTimes ++;
|
|
|
|
+ stageFragment.usedTimes ++;
|
|
|
|
|
|
- currentPipeline.usedTimes ++;
|
|
|
|
- stageVertex.usedTimes ++;
|
|
|
|
- stageFragment.usedTimes ++;
|
|
|
|
|
|
+ // events
|
|
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // dispose
|
|
|
|
-
|
|
|
|
- if ( materialProperties.disposeCallback === undefined ) {
|
|
|
|
-
|
|
|
|
- const disposeCallback = onMaterialDispose.bind( this );
|
|
|
|
- materialProperties.disposeCallback = disposeCallback;
|
|
|
|
-
|
|
|
|
- material.addEventListener( 'dispose', disposeCallback );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
|
|
+ material.addEventListener( 'dispose', cache.dispose );
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
@@ -182,7 +165,20 @@ class WebGPURenderPipelines {
|
|
|
|
|
|
if ( cache === undefined ) {
|
|
if ( cache === undefined ) {
|
|
|
|
|
|
- cache = {};
|
|
|
|
|
|
+ cache = {
|
|
|
|
+
|
|
|
|
+ dispose: () => {
|
|
|
|
+
|
|
|
|
+ this._releaseObject( object );
|
|
|
|
+
|
|
|
|
+ this.objectCache.delete( object );
|
|
|
|
+
|
|
|
|
+ object.material.removeEventListener( 'dispose', cache.dispose );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
this.objectCache.set( object, cache );
|
|
this.objectCache.set( object, cache );
|
|
|
|
|
|
}
|
|
}
|
|
@@ -191,6 +187,18 @@ class WebGPURenderPipelines {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ _releaseObject( object ) {
|
|
|
|
+
|
|
|
|
+ const cache = this.objectCache.get( object );
|
|
|
|
+
|
|
|
|
+ this._releasePipeline( cache.currentPipeline );
|
|
|
|
+ delete cache.currentPipeline;
|
|
|
|
+
|
|
|
|
+ this.nodes.remove( object );
|
|
|
|
+ this.bindings.remove( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
_releasePipeline( pipeline ) {
|
|
_releasePipeline( pipeline ) {
|
|
|
|
|
|
if ( -- pipeline.usedTimes === 0 ) {
|
|
if ( -- pipeline.usedTimes === 0 ) {
|
|
@@ -282,31 +290,4 @@ class WebGPURenderPipelines {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-function onMaterialDispose( event ) {
|
|
|
|
-
|
|
|
|
- const properties = this.properties;
|
|
|
|
-
|
|
|
|
- const material = event.target;
|
|
|
|
- const materialProperties = properties.get( material );
|
|
|
|
-
|
|
|
|
- material.removeEventListener( 'dispose', materialProperties.disposeCallback );
|
|
|
|
-
|
|
|
|
- properties.remove( material );
|
|
|
|
-
|
|
|
|
- // remove references to pipelines
|
|
|
|
-
|
|
|
|
- const pipelines = materialProperties.pipelines;
|
|
|
|
-
|
|
|
|
- if ( pipelines !== undefined ) {
|
|
|
|
-
|
|
|
|
- for ( const pipeline of pipelines ) {
|
|
|
|
-
|
|
|
|
- this._releasePipeline( pipeline );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
export default WebGPURenderPipelines;
|
|
export default WebGPURenderPipelines;
|