@@ -64,77 +64,191 @@ class GPUTexture : public m::HybridObject {
6464 inline const wgpu::Texture get () { return _instance; }
6565
6666 size_t getMemoryPressure () override {
67- // Calculate approximate memory usage based on texture properties
68- uint32_t width = getWidth ();
69- uint32_t height = getHeight ();
70- uint32_t depthOrArrayLayers = getDepthOrArrayLayers ();
71- uint32_t mipLevelCount = getMipLevelCount ();
72- uint32_t sampleCount = getSampleCount ();
73-
74- // Estimate bytes per pixel based on format
75- // This is a simplified estimate - actual values depend on the specific
76- // format
77- size_t bytesPerPixel = 4 ; // Default to RGBA8 format
78- wgpu::TextureFormat format = getFormat ();
79- switch (format) {
80- case wgpu::TextureFormat::R8Unorm:
81- case wgpu::TextureFormat::R8Snorm:
82- case wgpu::TextureFormat::R8Uint:
83- case wgpu::TextureFormat::R8Sint:
84- bytesPerPixel = 1 ;
85- break ;
86- case wgpu::TextureFormat::R16Uint:
87- case wgpu::TextureFormat::R16Sint:
88- case wgpu::TextureFormat::R16Float:
89- case wgpu::TextureFormat::RG8Unorm:
90- case wgpu::TextureFormat::RG8Snorm:
91- case wgpu::TextureFormat::RG8Uint:
92- case wgpu::TextureFormat::RG8Sint:
93- bytesPerPixel = 2 ;
94- break ;
95- case wgpu::TextureFormat::RGBA8Unorm:
96- case wgpu::TextureFormat::RGBA8UnormSrgb:
97- case wgpu::TextureFormat::RGBA8Snorm:
98- case wgpu::TextureFormat::RGBA8Uint:
99- case wgpu::TextureFormat::RGBA8Sint:
100- case wgpu::TextureFormat::BGRA8Unorm:
101- case wgpu::TextureFormat::BGRA8UnormSrgb:
102- case wgpu::TextureFormat::RGB10A2Unorm:
103- case wgpu::TextureFormat::R32Float:
104- case wgpu::TextureFormat::R32Uint:
105- case wgpu::TextureFormat::R32Sint:
106- case wgpu::TextureFormat::RG16Uint:
107- case wgpu::TextureFormat::RG16Sint:
108- case wgpu::TextureFormat::RG16Float:
109- bytesPerPixel = 4 ;
110- break ;
111- case wgpu::TextureFormat::RG32Float:
112- case wgpu::TextureFormat::RG32Uint:
113- case wgpu::TextureFormat::RG32Sint:
114- case wgpu::TextureFormat::RGBA16Uint:
115- case wgpu::TextureFormat::RGBA16Sint:
116- case wgpu::TextureFormat::RGBA16Float:
117- bytesPerPixel = 8 ;
118- break ;
119- case wgpu::TextureFormat::RGBA32Float:
120- case wgpu::TextureFormat::RGBA32Uint:
121- case wgpu::TextureFormat::RGBA32Sint:
122- bytesPerPixel = 16 ;
123- break ;
124- default :
125- bytesPerPixel = 4 ; // Safe default
126- break ;
127- }
67+ struct FormatMemoryInfo {
68+ uint32_t blockWidth;
69+ uint32_t blockHeight;
70+ size_t bytesPerBlock;
71+ bool isCompressed;
72+ };
73+
74+ auto getFormatInfo = [](wgpu::TextureFormat format) -> FormatMemoryInfo {
75+ using Info = FormatMemoryInfo;
76+ switch (format) {
77+ case wgpu::TextureFormat::R8Unorm:
78+ case wgpu::TextureFormat::R8Snorm:
79+ case wgpu::TextureFormat::R8Uint:
80+ case wgpu::TextureFormat::R8Sint:
81+ case wgpu::TextureFormat::Stencil8:
82+ return {1 , 1 , 1 , false };
83+ case wgpu::TextureFormat::R16Unorm:
84+ case wgpu::TextureFormat::R16Snorm:
85+ case wgpu::TextureFormat::R16Uint:
86+ case wgpu::TextureFormat::R16Sint:
87+ case wgpu::TextureFormat::R16Float:
88+ case wgpu::TextureFormat::RG8Unorm:
89+ case wgpu::TextureFormat::RG8Snorm:
90+ case wgpu::TextureFormat::RG8Uint:
91+ case wgpu::TextureFormat::RG8Sint:
92+ case wgpu::TextureFormat::Depth16Unorm:
93+ return {1 , 1 , 2 , false };
94+ case wgpu::TextureFormat::R32Float:
95+ case wgpu::TextureFormat::R32Uint:
96+ case wgpu::TextureFormat::R32Sint:
97+ case wgpu::TextureFormat::RG16Unorm:
98+ case wgpu::TextureFormat::RG16Snorm:
99+ case wgpu::TextureFormat::RG16Uint:
100+ case wgpu::TextureFormat::RG16Sint:
101+ case wgpu::TextureFormat::RG16Float:
102+ case wgpu::TextureFormat::RGBA8Unorm:
103+ case wgpu::TextureFormat::RGBA8UnormSrgb:
104+ case wgpu::TextureFormat::RGBA8Snorm:
105+ case wgpu::TextureFormat::RGBA8Uint:
106+ case wgpu::TextureFormat::RGBA8Sint:
107+ case wgpu::TextureFormat::BGRA8Unorm:
108+ case wgpu::TextureFormat::BGRA8UnormSrgb:
109+ case wgpu::TextureFormat::RGB10A2Unorm:
110+ case wgpu::TextureFormat::RGB10A2Uint:
111+ case wgpu::TextureFormat::RG11B10Ufloat:
112+ case wgpu::TextureFormat::RGB9E5Ufloat:
113+ case wgpu::TextureFormat::Depth24Plus:
114+ case wgpu::TextureFormat::Depth24PlusStencil8:
115+ case wgpu::TextureFormat::Depth32Float:
116+ case wgpu::TextureFormat::External:
117+ return {1 , 1 , 4 , false };
118+ case wgpu::TextureFormat::RG32Float:
119+ case wgpu::TextureFormat::RG32Uint:
120+ case wgpu::TextureFormat::RG32Sint:
121+ case wgpu::TextureFormat::RGBA16Unorm:
122+ case wgpu::TextureFormat::RGBA16Snorm:
123+ case wgpu::TextureFormat::RGBA16Uint:
124+ case wgpu::TextureFormat::RGBA16Sint:
125+ case wgpu::TextureFormat::RGBA16Float:
126+ case wgpu::TextureFormat::Depth32FloatStencil8:
127+ return {1 , 1 , 8 , false };
128+ case wgpu::TextureFormat::RGBA32Float:
129+ case wgpu::TextureFormat::RGBA32Uint:
130+ case wgpu::TextureFormat::RGBA32Sint:
131+ return {1 , 1 , 16 , false };
132+ case wgpu::TextureFormat::BC1RGBAUnorm:
133+ case wgpu::TextureFormat::BC1RGBAUnormSrgb:
134+ case wgpu::TextureFormat::BC4RUnorm:
135+ case wgpu::TextureFormat::BC4RSnorm:
136+ case wgpu::TextureFormat::ETC2RGB8Unorm:
137+ case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
138+ case wgpu::TextureFormat::ETC2RGB8A1Unorm:
139+ case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
140+ case wgpu::TextureFormat::EACR11Unorm:
141+ case wgpu::TextureFormat::EACR11Snorm:
142+ return {4 , 4 , 8 , true };
143+ case wgpu::TextureFormat::BC2RGBAUnorm:
144+ case wgpu::TextureFormat::BC2RGBAUnormSrgb:
145+ case wgpu::TextureFormat::BC3RGBAUnorm:
146+ case wgpu::TextureFormat::BC3RGBAUnormSrgb:
147+ case wgpu::TextureFormat::BC5RGUnorm:
148+ case wgpu::TextureFormat::BC5RGSnorm:
149+ case wgpu::TextureFormat::BC6HRGBUfloat:
150+ case wgpu::TextureFormat::BC6HRGBFloat:
151+ case wgpu::TextureFormat::BC7RGBAUnorm:
152+ case wgpu::TextureFormat::BC7RGBAUnormSrgb:
153+ case wgpu::TextureFormat::ETC2RGBA8Unorm:
154+ case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
155+ case wgpu::TextureFormat::EACRG11Unorm:
156+ case wgpu::TextureFormat::EACRG11Snorm:
157+ return {4 , 4 , 16 , true };
158+ case wgpu::TextureFormat::ASTC4x4Unorm:
159+ case wgpu::TextureFormat::ASTC4x4UnormSrgb:
160+ return {4 , 4 , 16 , true };
161+ case wgpu::TextureFormat::ASTC5x4Unorm:
162+ case wgpu::TextureFormat::ASTC5x4UnormSrgb:
163+ return {5 , 4 , 16 , true };
164+ case wgpu::TextureFormat::ASTC5x5Unorm:
165+ case wgpu::TextureFormat::ASTC5x5UnormSrgb:
166+ return {5 , 5 , 16 , true };
167+ case wgpu::TextureFormat::ASTC6x5Unorm:
168+ case wgpu::TextureFormat::ASTC6x5UnormSrgb:
169+ return {6 , 5 , 16 , true };
170+ case wgpu::TextureFormat::ASTC6x6Unorm:
171+ case wgpu::TextureFormat::ASTC6x6UnormSrgb:
172+ return {6 , 6 , 16 , true };
173+ case wgpu::TextureFormat::ASTC8x5Unorm:
174+ case wgpu::TextureFormat::ASTC8x5UnormSrgb:
175+ return {8 , 5 , 16 , true };
176+ case wgpu::TextureFormat::ASTC8x6Unorm:
177+ case wgpu::TextureFormat::ASTC8x6UnormSrgb:
178+ return {8 , 6 , 16 , true };
179+ case wgpu::TextureFormat::ASTC8x8Unorm:
180+ case wgpu::TextureFormat::ASTC8x8UnormSrgb:
181+ return {8 , 8 , 16 , true };
182+ case wgpu::TextureFormat::ASTC10x5Unorm:
183+ case wgpu::TextureFormat::ASTC10x5UnormSrgb:
184+ return {10 , 5 , 16 , true };
185+ case wgpu::TextureFormat::ASTC10x6Unorm:
186+ case wgpu::TextureFormat::ASTC10x6UnormSrgb:
187+ return {10 , 6 , 16 , true };
188+ case wgpu::TextureFormat::ASTC10x8Unorm:
189+ case wgpu::TextureFormat::ASTC10x8UnormSrgb:
190+ return {10 , 8 , 16 , true };
191+ case wgpu::TextureFormat::ASTC10x10Unorm:
192+ case wgpu::TextureFormat::ASTC10x10UnormSrgb:
193+ return {10 , 10 , 16 , true };
194+ case wgpu::TextureFormat::ASTC12x10Unorm:
195+ case wgpu::TextureFormat::ASTC12x10UnormSrgb:
196+ return {12 , 10 , 16 , true };
197+ case wgpu::TextureFormat::ASTC12x12Unorm:
198+ case wgpu::TextureFormat::ASTC12x12UnormSrgb:
199+ return {12 , 12 , 16 , true };
200+ case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
201+ case wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm:
202+ case wgpu::TextureFormat::R8BG8A8Triplanar420Unorm:
203+ case wgpu::TextureFormat::R8BG8Biplanar422Unorm:
204+ case wgpu::TextureFormat::R8BG8Biplanar444Unorm:
205+ case wgpu::TextureFormat::R10X6BG10X6Biplanar422Unorm:
206+ case wgpu::TextureFormat::R10X6BG10X6Biplanar444Unorm:
207+ return {1 , 1 , 2 , false };
208+ case wgpu::TextureFormat::Undefined:
209+ default :
210+ return {1 , 1 , 4 , false };
211+ }
212+ };
213+
214+ const uint32_t width = getWidth ();
215+ const uint32_t height = getHeight ();
216+ const uint32_t depthOrArrayLayers = getDepthOrArrayLayers ();
217+ const uint32_t mipLevelCount = getMipLevelCount ();
218+ const uint32_t sampleCount = std::max (1u , getSampleCount ());
219+ const bool is3D = getDimension () == wgpu::TextureDimension::e3D;
220+
221+ FormatMemoryInfo info = getFormatInfo (getFormat ());
128222
129- // Calculate total memory for all mip levels
130223 size_t totalMemory = 0 ;
131224 for (uint32_t mip = 0 ; mip < mipLevelCount; ++mip) {
132- uint32_t mipWidth = std::max (1u , width >> mip);
133- uint32_t mipHeight = std::max (1u , height >> mip);
134- totalMemory += static_cast <size_t >(mipWidth) * mipHeight *
135- depthOrArrayLayers * bytesPerPixel * sampleCount;
225+ const uint32_t mipWidth = std::max (1u , width >> mip);
226+ const uint32_t mipHeight = std::max (1u , height >> mip);
227+ const uint32_t mipDepthOrLayers =
228+ is3D ? std::max (1u , depthOrArrayLayers >> mip) : depthOrArrayLayers;
229+ const size_t layerMultiplier =
230+ static_cast <size_t >(mipDepthOrLayers) * sampleCount;
231+
232+ if (info.isCompressed ) {
233+ const uint32_t blocksWide =
234+ (mipWidth + info.blockWidth - 1 ) / info.blockWidth ;
235+ const uint32_t blocksHigh =
236+ (mipHeight + info.blockHeight - 1 ) / info.blockHeight ;
237+ totalMemory += static_cast <size_t >(blocksWide) * blocksHigh *
238+ info.bytesPerBlock * layerMultiplier;
239+ } else {
240+ totalMemory += static_cast <size_t >(mipWidth) * mipHeight *
241+ info.bytesPerBlock * layerMultiplier;
242+ }
136243 }
137244
245+ constexpr size_t kAlignment = 4 * 1024 ; // keep GC pressure conservative
246+ if (totalMemory == 0 ) {
247+ totalMemory = kAlignment ;
248+ } else {
249+ totalMemory =
250+ ((totalMemory + kAlignment - 1 ) / kAlignment ) * kAlignment ;
251+ }
138252 return totalMemory;
139253 }
140254
0 commit comments