|
|
@@ -103,45 +103,94 @@ class WebGPUTextureUtils {
|
|
|
this.depthTexture = new DepthTexture();
|
|
|
this.depthTexture.name = 'depthBuffer';
|
|
|
|
|
|
+ /**
|
|
|
+ * A cache of shared texture samplers.
|
|
|
+ *
|
|
|
+ * @type {Map<string, Object>}
|
|
|
+ */
|
|
|
+ this._samplerCache = new Map();
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Creates a GPU sampler for the given texture.
|
|
|
*
|
|
|
* @param {Texture} texture - The texture to create the sampler for.
|
|
|
+ * @return {string} The current sampler key.
|
|
|
*/
|
|
|
- createSampler( texture ) {
|
|
|
+ updateSampler( texture ) {
|
|
|
|
|
|
const backend = this.backend;
|
|
|
- const device = backend.device;
|
|
|
-
|
|
|
- const textureGPU = backend.get( texture );
|
|
|
-
|
|
|
- const samplerDescriptorGPU = {
|
|
|
- addressModeU: this._convertAddressMode( texture.wrapS ),
|
|
|
- addressModeV: this._convertAddressMode( texture.wrapT ),
|
|
|
- addressModeW: this._convertAddressMode( texture.wrapR ),
|
|
|
- magFilter: this._convertFilterMode( texture.magFilter ),
|
|
|
- minFilter: this._convertFilterMode( texture.minFilter ),
|
|
|
- mipmapFilter: this._convertFilterMode( texture.minFilter ),
|
|
|
- maxAnisotropy: 1
|
|
|
- };
|
|
|
|
|
|
- // anisotropy can only be used when all filter modes are set to linear.
|
|
|
+ const samplerKey = texture.minFilter + '-' + texture.magFilter + '-' +
|
|
|
+ texture.wrapS + '-' + texture.wrapT + '-' + ( texture.wrapR || '0' ) + '-' +
|
|
|
+ texture.anisotropy + '-' + ( texture.compareFunction || 0 );
|
|
|
+
|
|
|
+ let samplerData = this._samplerCache.get( samplerKey );
|
|
|
+
|
|
|
+ if ( samplerData === undefined ) {
|
|
|
+
|
|
|
+ const samplerDescriptorGPU = {
|
|
|
+ addressModeU: this._convertAddressMode( texture.wrapS ),
|
|
|
+ addressModeV: this._convertAddressMode( texture.wrapT ),
|
|
|
+ addressModeW: this._convertAddressMode( texture.wrapR ),
|
|
|
+ magFilter: this._convertFilterMode( texture.magFilter ),
|
|
|
+ minFilter: this._convertFilterMode( texture.minFilter ),
|
|
|
+ mipmapFilter: this._convertFilterMode( texture.minFilter ),
|
|
|
+ maxAnisotropy: 1
|
|
|
+ };
|
|
|
+
|
|
|
+ // anisotropy can only be used when all filter modes are set to linear.
|
|
|
+
|
|
|
+ if ( samplerDescriptorGPU.magFilter === GPUFilterMode.Linear && samplerDescriptorGPU.minFilter === GPUFilterMode.Linear && samplerDescriptorGPU.mipmapFilter === GPUFilterMode.Linear ) {
|
|
|
+
|
|
|
+ samplerDescriptorGPU.maxAnisotropy = texture.anisotropy;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( texture.isDepthTexture && texture.compareFunction !== null ) {
|
|
|
+
|
|
|
+ samplerDescriptorGPU.compare = _compareToWebGPU[ texture.compareFunction ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const sampler = backend.device.createSampler( samplerDescriptorGPU );
|
|
|
|
|
|
- if ( samplerDescriptorGPU.magFilter === GPUFilterMode.Linear && samplerDescriptorGPU.minFilter === GPUFilterMode.Linear && samplerDescriptorGPU.mipmapFilter === GPUFilterMode.Linear ) {
|
|
|
+ samplerData = { sampler, usedTimes: 0 };
|
|
|
|
|
|
- samplerDescriptorGPU.maxAnisotropy = texture.anisotropy;
|
|
|
+ this._samplerCache.set( samplerKey, samplerData );
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( texture.isDepthTexture && texture.compareFunction !== null ) {
|
|
|
+ const textureData = backend.get( texture );
|
|
|
+
|
|
|
+ if ( textureData.sampler !== samplerData.sampler ) {
|
|
|
+
|
|
|
+ // check if previous sampler is unused so it can be deleted
|
|
|
+
|
|
|
+ if ( textureData.sampler !== undefined ) {
|
|
|
+
|
|
|
+ const oldSamplerData = this._samplerCache.get( textureData.samplerKey );
|
|
|
+ oldSamplerData.usedTimes --;
|
|
|
+
|
|
|
+ if ( oldSamplerData.usedTimes === 0 ) {
|
|
|
|
|
|
- samplerDescriptorGPU.compare = _compareToWebGPU[ texture.compareFunction ];
|
|
|
+ this._samplerCache.delete( textureData.samplerKey );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // update to new sampler data
|
|
|
+
|
|
|
+ textureData.samplerKey = samplerKey;
|
|
|
+ textureData.sampler = samplerData.sampler;
|
|
|
+
|
|
|
+ samplerData.usedTimes ++;
|
|
|
|
|
|
}
|
|
|
|
|
|
- textureGPU.sampler = device.createSampler( samplerDescriptorGPU );
|
|
|
+ return samplerKey;
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -308,20 +357,6 @@ class WebGPUTextureUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Destroys the GPU sampler for the given texture.
|
|
|
- *
|
|
|
- * @param {Texture} texture - The texture to destroy the sampler for.
|
|
|
- */
|
|
|
- destroySampler( texture ) {
|
|
|
-
|
|
|
- const backend = this.backend;
|
|
|
- const textureData = backend.get( texture );
|
|
|
-
|
|
|
- delete textureData.sampler;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Generates mipmaps for the given texture.
|
|
|
*
|
|
|
@@ -577,6 +612,15 @@ class WebGPUTextureUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Frees all internal resources.
|
|
|
+ */
|
|
|
+ dispose() {
|
|
|
+
|
|
|
+ this._samplerCache.clear();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Returns the default GPU texture for the given format.
|
|
|
*
|