Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 25 additions & 0 deletions src/nodes/pmrem/PMREMNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,31 @@ function _getPMREMFromTexture( texture, renderer, generator ) {

cacheTexture.pmremVersion = texture.pmremVersion;

// add dispose event listener for new PMREMs

if ( cache.has( texture ) === false ) {

const onDispose = () => {

texture.removeEventListener( 'dispose', onDispose );

const pmrem = cache.get( texture );

if ( pmrem !== undefined ) {

pmrem.dispose();
cache.delete( texture );

}

};

texture.addEventListener( 'dispose', onDispose );

}

//

cache.set( texture, cacheTexture );

}
Expand Down
13 changes: 10 additions & 3 deletions src/renderers/common/Backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,18 @@ class Backend {
* Updates a GPU sampler for the given texture.
*
* @abstract
* @param {Texture} texture - The texture to update the sampler for.
* @param {TextureNode} textureNode - The texture node to update the sampler with.
* @param {Sampler} binding - The sampler binding to update.
* @return {string} The current sampler key.
*/
updateSampler( /*texture, textureNode*/ ) { }
updateSampler( /*binding*/ ) { }

/**
* Frees the GPU sampler for the given sampler binding.
*
* @abstract
* @param {Sampler} binding - The sampler binding to free.
*/
destroySampler( /*binding*/ ) { }

/**
* Creates a default texture for the given texture that can be used
Expand Down
10 changes: 8 additions & 2 deletions src/renderers/common/Bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class Bindings extends DataMap {

} else if ( binding.isSampler ) {

this.textures.updateSampler( binding.texture, binding.textureNode );
this.textures.updateSampler( binding );

} else if ( binding.isStorageBuffer ) {

Expand Down Expand Up @@ -267,6 +267,12 @@ class Bindings extends DataMap {

} else if ( binding.isSampler ) {

if ( binding.isSampledTexture !== true ) {

this.backend.destroySampler( binding );

}

binding.release();

}
Expand Down Expand Up @@ -422,7 +428,7 @@ class Bindings extends DataMap {

if ( updated ) {

const samplerKey = this.textures.updateSampler( binding.texture, binding.textureNode );
const samplerKey = this.textures.updateSampler( binding );

if ( binding.samplerKey !== samplerKey ) {

Expand Down
13 changes: 9 additions & 4 deletions src/renderers/common/Textures.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,13 +426,12 @@ class Textures extends DataMap {
* In WebGPU, samplers are objects like textures and it's possible to share
* them when the texture parameters match.
*
* @param {Texture} texture - The texture to update the sampler for.
* @param {TextureNode} textureNode - The texture node to update the sampler with.
* @param {Sampler} binding - The sampler binding to update.
* @return {string} The current sampler key.
*/
updateSampler( texture, textureNode ) {
updateSampler( binding ) {

return this.backend.updateSampler( texture, textureNode );
return this.backend.updateSampler( binding );

}

Expand Down Expand Up @@ -625,6 +624,12 @@ class Textures extends DataMap {

if ( binding.isSampler && binding.texture === texture ) {

if ( binding.isSampledTexture !== true ) {

this.backend.destroySampler( binding );

}

binding.reset();
binding.release();

Expand Down
5 changes: 2 additions & 3 deletions src/renderers/webgl-fallback/WebGLBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -1429,11 +1429,10 @@ class WebGLBackend extends Backend {
/**
* This method does nothing since WebGL 2 has no concept of samplers.
*
* @param {Texture} texture - The texture to update the sampler for.
* @param {TextureNode} textureNode - The texture node to update the sampler with.
* @param {Sampler} binding - The sampler binding to update.
* @return {string} The current sampler key.
*/
updateSampler( /*texture, textureNode*/ ) {
updateSampler( /*binding*/ ) {

return '';

Expand Down
18 changes: 14 additions & 4 deletions src/renderers/webgpu/WebGPUBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -2147,13 +2147,23 @@ class WebGPUBackend extends Backend {
/**
* Updates a GPU sampler for the given texture.
*
* @param {Texture} texture - The texture to update the sampler for.
* @param {TextureNode} textureNode - The texture node to update the sampler with.
* @param {Sampler} binding - The sampler binding to update.
* @return {string} The current sampler key.
*/
updateSampler( texture, textureNode ) {
updateSampler( binding ) {

return this.textureUtils.updateSampler( texture, textureNode );
return this.textureUtils.updateSampler( binding );

}

/**
* Frees the GPU sampler for the given sampler binding.
*
* @param {Sampler} binding - The sampler binding to free.
*/
destroySampler( binding ) {

this.textureUtils.destroySampler( binding );

}

Expand Down
4 changes: 2 additions & 2 deletions src/renderers/webgpu/utils/WebGPUBindingUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ class WebGPUBindingUtils {

} else if ( binding.isSampler ) {

const textureGPU = backend.get( binding.texture );
const bindingData = backend.get( binding );

_bindGroupDescriptor.entries.push( { binding: bindingPoint, resource: textureGPU.sampler } );
_bindGroupDescriptor.entries.push( { binding: bindingPoint, resource: bindingData.sampler } );

}

Expand Down
66 changes: 47 additions & 19 deletions src/renderers/webgpu/utils/WebGPUTextureUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,14 @@ class WebGPUTextureUtils {
/**
* Creates a GPU sampler for the given texture.
*
* @param {Texture} texture - The texture to create the sampler for.
* @param {TextureNode} textureNode - The texture node to update the sampler with.
* @param {Sampler} binding - The sampler binding to update.
* @return {string} The current sampler key.
*/
updateSampler( texture, textureNode ) {
updateSampler( binding ) {

const backend = this.backend;
const texture = binding.texture;
const textureNode = binding.textureNode;

const samplerKey = texture.minFilter + '-' + texture.magFilter + '-' +
texture.wrapS + '-' + texture.wrapT + '-' + ( texture.wrapR || '0' ) + '-' +
Expand Down Expand Up @@ -205,35 +206,62 @@ class WebGPUTextureUtils {

}

const textureData = backend.get( texture );
const bindingData = backend.get( binding );

if ( textureData.sampler !== samplerData.sampler ) {
if ( bindingData.sampler !== samplerData.sampler ) {

// check if previous sampler is unused so it can be deleted
// release the previous sampler (if any) so it can be deleted when unused

if ( textureData.sampler !== undefined ) {
this._releaseSampler( bindingData );

const oldSamplerData = this._samplerCache.get( textureData.samplerKey );
oldSamplerData.usedTimes --;
// update to new sampler data

if ( oldSamplerData.usedTimes === 0 ) {
bindingData.samplerKey = samplerKey;
bindingData.sampler = samplerData.sampler;

this._samplerCache.delete( textureData.samplerKey );
samplerData.usedTimes ++;

}
}

}
return samplerKey;

// update to new sampler data
}

textureData.samplerKey = samplerKey;
textureData.sampler = samplerData.sampler;
/**
* Frees the GPU sampler referenced by the given sampler binding.
*
* @param {Sampler} binding - The sampler binding to free.
*/
destroySampler( binding ) {

samplerData.usedTimes ++;
this._releaseSampler( this.backend.get( binding ) );

}
}

return samplerKey;
/**
* Releases the pooled sampler referenced by the given binding data and
* removes it from the cache when no binding references it anymore.
*
* @private
* @param {Object} bindingData - The binding data holding the sampler reference.
*/
_releaseSampler( bindingData ) {

if ( bindingData.sampler !== undefined ) {

const samplerData = this._samplerCache.get( bindingData.samplerKey );
samplerData.usedTimes --;

if ( samplerData.usedTimes === 0 ) {

this._samplerCache.delete( bindingData.samplerKey );

}

bindingData.sampler = undefined;
bindingData.samplerKey = undefined;

}

}

Expand Down