@@ -103,45 +103,94 @@ class WebGPUTextureUtils {
103
103
this . depthTexture = new DepthTexture ( ) ;
104
104
this . depthTexture . name = 'depthBuffer' ;
105
105
106
+ /**
107
+ * A cache of shared texture samplers.
108
+ *
109
+ * @type {Map<string, Object> }
110
+ */
111
+ this . _samplerCache = new Map ( ) ;
112
+
106
113
}
107
114
108
115
/**
109
116
* Creates a GPU sampler for the given texture.
110
117
*
111
118
* @param {Texture } texture - The texture to create the sampler for.
119
+ * @return {string } The current sampler key.
112
120
*/
113
- createSampler ( texture ) {
121
+ updateSampler ( texture ) {
114
122
115
123
const backend = this . backend ;
116
- const device = backend . device ;
117
-
118
- const textureGPU = backend . get ( texture ) ;
119
-
120
- const samplerDescriptorGPU = {
121
- addressModeU : this . _convertAddressMode ( texture . wrapS ) ,
122
- addressModeV : this . _convertAddressMode ( texture . wrapT ) ,
123
- addressModeW : this . _convertAddressMode ( texture . wrapR ) ,
124
- magFilter : this . _convertFilterMode ( texture . magFilter ) ,
125
- minFilter : this . _convertFilterMode ( texture . minFilter ) ,
126
- mipmapFilter : this . _convertFilterMode ( texture . minFilter ) ,
127
- maxAnisotropy : 1
128
- } ;
129
124
130
- // anisotropy can only be used when all filter modes are set to linear.
125
+ const samplerKey = texture . minFilter + '-' + texture . magFilter + '-' +
126
+ texture . wrapS + '-' + texture . wrapT + '-' + ( texture . wrapR || '0' ) + '-' +
127
+ texture . anisotropy + '-' + ( texture . compareFunction || 0 ) ;
128
+
129
+ let samplerData = this . _samplerCache . get ( samplerKey ) ;
130
+
131
+ if ( samplerData === undefined ) {
132
+
133
+ const samplerDescriptorGPU = {
134
+ addressModeU : this . _convertAddressMode ( texture . wrapS ) ,
135
+ addressModeV : this . _convertAddressMode ( texture . wrapT ) ,
136
+ addressModeW : this . _convertAddressMode ( texture . wrapR ) ,
137
+ magFilter : this . _convertFilterMode ( texture . magFilter ) ,
138
+ minFilter : this . _convertFilterMode ( texture . minFilter ) ,
139
+ mipmapFilter : this . _convertFilterMode ( texture . minFilter ) ,
140
+ maxAnisotropy : 1
141
+ } ;
142
+
143
+ // anisotropy can only be used when all filter modes are set to linear.
144
+
145
+ if ( samplerDescriptorGPU . magFilter === GPUFilterMode . Linear && samplerDescriptorGPU . minFilter === GPUFilterMode . Linear && samplerDescriptorGPU . mipmapFilter === GPUFilterMode . Linear ) {
146
+
147
+ samplerDescriptorGPU . maxAnisotropy = texture . anisotropy ;
148
+
149
+ }
150
+
151
+ if ( texture . isDepthTexture && texture . compareFunction !== null ) {
152
+
153
+ samplerDescriptorGPU . compare = _compareToWebGPU [ texture . compareFunction ] ;
154
+
155
+ }
156
+
157
+ const sampler = backend . device . createSampler ( samplerDescriptorGPU ) ;
131
158
132
- if ( samplerDescriptorGPU . magFilter === GPUFilterMode . Linear && samplerDescriptorGPU . minFilter === GPUFilterMode . Linear && samplerDescriptorGPU . mipmapFilter === GPUFilterMode . Linear ) {
159
+ samplerData = { sampler , usedTimes : 0 } ;
133
160
134
- samplerDescriptorGPU . maxAnisotropy = texture . anisotropy ;
161
+ this . _samplerCache . set ( samplerKey , samplerData ) ;
135
162
136
163
}
137
164
138
- if ( texture . isDepthTexture && texture . compareFunction !== null ) {
165
+ const textureData = backend . get ( texture ) ;
166
+
167
+ if ( textureData . sampler !== samplerData . sampler ) {
168
+
169
+ // check if previous sampler is unused so it can be deleted
170
+
171
+ if ( textureData . sampler !== undefined ) {
172
+
173
+ const oldSamplerData = this . _samplerCache . get ( textureData . samplerKey ) ;
174
+ oldSamplerData . usedTimes -- ;
175
+
176
+ if ( oldSamplerData . usedTimes === 0 ) {
139
177
140
- samplerDescriptorGPU . compare = _compareToWebGPU [ texture . compareFunction ] ;
178
+ this . _samplerCache . delete ( textureData . samplerKey ) ;
179
+
180
+ }
181
+
182
+ }
183
+
184
+ // update to new sampler data
185
+
186
+ textureData . samplerKey = samplerKey ;
187
+ textureData . sampler = samplerData . sampler ;
188
+
189
+ samplerData . usedTimes ++ ;
141
190
142
191
}
143
192
144
- textureGPU . sampler = device . createSampler ( samplerDescriptorGPU ) ;
193
+ return samplerKey ;
145
194
146
195
}
147
196
@@ -308,20 +357,6 @@ class WebGPUTextureUtils {
308
357
309
358
}
310
359
311
- /**
312
- * Destroys the GPU sampler for the given texture.
313
- *
314
- * @param {Texture } texture - The texture to destroy the sampler for.
315
- */
316
- destroySampler ( texture ) {
317
-
318
- const backend = this . backend ;
319
- const textureData = backend . get ( texture ) ;
320
-
321
- delete textureData . sampler ;
322
-
323
- }
324
-
325
360
/**
326
361
* Generates mipmaps for the given texture.
327
362
*
@@ -577,6 +612,15 @@ class WebGPUTextureUtils {
577
612
578
613
}
579
614
615
+ /**
616
+ * Frees all internal resources.
617
+ */
618
+ dispose ( ) {
619
+
620
+ this . _samplerCache . clear ( ) ;
621
+
622
+ }
623
+
580
624
/**
581
625
* Returns the default GPU texture for the given format.
582
626
*
0 commit comments