1
1
import * as THREE from 'three' ;
2
2
import { Blp , BLP_IMAGE_FORMAT } from '@wowserhq/format' ;
3
- import FormatManager from './FormatManager.js' ;
4
- import { normalizePath } from './util.js' ;
3
+ import ManagedCompressedTexture from './ManagedCompressedTexture.js' ;
4
+ import ManagedDataTexture from './ManagedDataTexture.js' ;
5
+ import FormatManager from '../FormatManager.js' ;
6
+ import { normalizePath } from '../util.js' ;
5
7
6
8
const THREE_TEXTURE_FORMAT : Record < number , THREE . PixelFormat | THREE . CompressedPixelFormat > = {
7
9
[ BLP_IMAGE_FORMAT . IMAGE_DXT1 ] : THREE . RGBA_S3TC_DXT1_Format ,
@@ -14,6 +16,7 @@ class TextureManager {
14
16
#formatManager: FormatManager ;
15
17
#loaded = new Map < string , THREE . Texture > ( ) ;
16
18
#loading = new Map < string , Promise < THREE . Texture > > ( ) ;
19
+ #refs = new Map < string , number > ( ) ;
17
20
18
21
constructor ( formatManager : FormatManager ) {
19
22
this . #formatManager = formatManager ;
@@ -26,26 +29,64 @@ class TextureManager {
26
29
minFilter : THREE . MinificationTextureFilter = THREE . LinearMipmapLinearFilter ,
27
30
magFilter : THREE . MagnificationTextureFilter = THREE . LinearFilter ,
28
31
) {
29
- const cacheKey = [ normalizePath ( path ) , wrapS , wrapT , minFilter , magFilter ] . join ( ':' ) ;
32
+ const refId = [ normalizePath ( path ) , wrapS , wrapT , minFilter , magFilter ] . join ( ':' ) ;
33
+ this . #ref( refId ) ;
30
34
31
- const loaded = this . #loaded. get ( cacheKey ) ;
35
+ const loaded = this . #loaded. get ( refId ) ;
32
36
if ( loaded ) {
33
37
return Promise . resolve ( loaded ) ;
34
38
}
35
39
36
- const alreadyLoading = this . #loading. get ( cacheKey ) ;
40
+ const alreadyLoading = this . #loading. get ( refId ) ;
37
41
if ( alreadyLoading ) {
38
42
return alreadyLoading ;
39
43
}
40
44
41
- const loading = this . #load( cacheKey , path , wrapS , wrapT , minFilter , magFilter ) ;
42
- this . #loading. set ( cacheKey , loading ) ;
45
+ const loading = this . #load( refId , path , wrapS , wrapT , minFilter , magFilter ) ;
46
+ this . #loading. set ( refId , loading ) ;
43
47
44
48
return loading ;
45
49
}
46
50
51
+ deref ( refId : string ) {
52
+ let refCount = this . #refs. get ( refId ) ;
53
+
54
+ // Unknown ref
55
+
56
+ if ( refCount === undefined ) {
57
+ return ;
58
+ }
59
+
60
+ // Decrement
61
+
62
+ refCount -- ;
63
+
64
+ if ( refCount > 0 ) {
65
+ this . #refs. set ( refId , refCount ) ;
66
+ return ;
67
+ }
68
+
69
+ // Dispose
70
+
71
+ const texture = this . #loaded. get ( refId ) ;
72
+ if ( texture ) {
73
+ this . #loaded. delete ( refId ) ;
74
+ texture . dispose ( ) ;
75
+ }
76
+
77
+ this . #refs. delete ( refId ) ;
78
+ }
79
+
80
+ #ref( refId : string ) {
81
+ let refCount = this . #refs. get ( refId ) || 0 ;
82
+
83
+ refCount ++ ;
84
+
85
+ this . #refs. set ( refId , refCount ) ;
86
+ }
87
+
47
88
async #load(
48
- cacheKey : string ,
89
+ refId : string ,
49
90
path : string ,
50
91
wrapS : THREE . Wrapping ,
51
92
wrapT : THREE . Wrapping ,
@@ -56,7 +97,7 @@ class TextureManager {
56
97
try {
57
98
blp = await this . #formatManager. get ( path , Blp ) ;
58
99
} catch ( error ) {
59
- this . #loading. delete ( cacheKey ) ;
100
+ this . #loading. delete ( refId ) ;
60
101
throw error ;
61
102
}
62
103
@@ -66,24 +107,28 @@ class TextureManager {
66
107
67
108
const threeFormat = THREE_TEXTURE_FORMAT [ imageFormat ] ;
68
109
if ( threeFormat === undefined ) {
69
- this . #loading. delete ( cacheKey ) ;
110
+ this . #loading. delete ( refId ) ;
70
111
throw new Error ( `Unsupported texture format: ${ imageFormat } ` ) ;
71
112
}
72
113
73
- let texture : THREE . CompressedTexture | THREE . DataTexture ;
114
+ let texture : ManagedCompressedTexture | ManagedDataTexture ;
74
115
if (
75
116
imageFormat === BLP_IMAGE_FORMAT . IMAGE_DXT1 ||
76
117
imageFormat === BLP_IMAGE_FORMAT . IMAGE_DXT3 ||
77
118
imageFormat === BLP_IMAGE_FORMAT . IMAGE_DXT5
78
119
) {
79
- texture = new THREE . CompressedTexture (
120
+ texture = new ManagedCompressedTexture (
121
+ this ,
122
+ refId ,
80
123
null ,
81
124
blp . width ,
82
125
blp . height ,
83
126
threeFormat as THREE . CompressedPixelFormat ,
84
127
) ;
85
128
} else if ( imageFormat === BLP_IMAGE_FORMAT . IMAGE_ABGR8888 ) {
86
- texture = new THREE . DataTexture (
129
+ texture = new ManagedDataTexture (
130
+ this ,
131
+ refId ,
87
132
null ,
88
133
blp . width ,
89
134
blp . height ,
@@ -98,18 +143,16 @@ class TextureManager {
98
143
texture . magFilter = magFilter ;
99
144
texture . anisotropy = 16 ;
100
145
texture . name = normalizePath ( path ) . split ( '/' ) . at ( - 1 ) ;
101
- texture . userData . cacheKey = cacheKey ;
102
146
103
147
// All newly loaded textures need to be flagged for upload to the GPU
104
148
texture . needsUpdate = true ;
105
149
106
- this . #loaded. set ( cacheKey , texture ) ;
107
- this . #loading. delete ( cacheKey ) ;
150
+ this . #loaded. set ( refId , texture ) ;
151
+ this . #loading. delete ( refId ) ;
108
152
109
153
return texture ;
110
154
}
111
155
}
112
156
113
157
export default TextureManager ;
114
-
115
158
export { TextureManager } ;
0 commit comments