Skip to content

Commit f605ca4

Browse files
committed
🔧
1 parent 7be0ab7 commit f605ca4

5 files changed

Lines changed: 200 additions & 87 deletions

File tree

packages/webgpu/cpp/rnwgpu/api/GPUComputePipeline.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,9 @@ class GPUComputePipeline : public m::HybridObject {
4444
inline const wgpu::ComputePipeline get() { return _instance; }
4545

4646
size_t getMemoryPressure() override {
47-
// Compute pipelines contain compiled compute shader state and
48-
// driver-specific optimized code
49-
// Estimate: 16KB for a typical compute pipeline (single compute shader)
50-
return 16 * 1024;
47+
// Compute pipelines retain compiled shader state and backend caches.
48+
// Overshoot intentionally to reflect the native resources they fan out to.
49+
return 3 * 1024 * 1024; // 3MB
5150
}
5251

5352
private:

packages/webgpu/cpp/rnwgpu/api/GPUQuerySet.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,23 @@ class GPUQuerySet : public m::HybridObject {
4343
inline const wgpu::QuerySet get() { return _instance; }
4444

4545
size_t getMemoryPressure() override {
46-
uint32_t count = getCount();
47-
wgpu::QueryType type = getType();
46+
const uint32_t count = getCount();
47+
const wgpu::QueryType type = getType();
4848

49-
// Estimate bytes per query based on type
50-
size_t bytesPerQuery = 8; // Default estimate
49+
size_t bytesPerQuery = 16; // default to an overshoot
5150
switch (type) {
5251
case wgpu::QueryType::Occlusion:
53-
bytesPerQuery = 8; // 64-bit counter
52+
bytesPerQuery = 16; // occlusion result is 64-bit; pad to 16 for safety
5453
break;
5554
case wgpu::QueryType::Timestamp:
56-
bytesPerQuery = 8; // 64-bit timestamp
55+
bytesPerQuery = 16; // timestamps are 64-bit; double to overshoot
5756
break;
57+
case wgpu::QueryType::PipelineStatistics: {
58+
constexpr size_t kAssumedCountersPerQuery = 8;
59+
bytesPerQuery = 8 * kAssumedCountersPerQuery;
60+
break;
61+
}
5862
default:
59-
bytesPerQuery = 8; // Safe default
6063
break;
6164
}
6265

packages/webgpu/cpp/rnwgpu/api/GPURenderPipeline.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ class GPURenderPipeline : public m::HybridObject {
4343
inline const wgpu::RenderPipeline get() { return _instance; }
4444

4545
size_t getMemoryPressure() override {
46-
// Render pipelines contain compiled shader state, vertex/fragment shaders,
47-
// render state, and driver-specific optimized code
48-
// Estimate: 24KB for a typical render pipeline with vertex + fragment
49-
// shaders
50-
return 24 * 1024;
46+
// Render pipelines combine multiple compiled stages plus fixed-function
47+
// state baked by the driver. Reserve several megabytes to signal that to
48+
// the GC.
49+
return 3 * 1024 * 1024; // 3MB
5150
}
5251

5352
private:

packages/webgpu/cpp/rnwgpu/api/GPUShaderModule.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,9 @@ class GPUShaderModule : public m::HybridObject {
4949
inline const wgpu::ShaderModule get() { return _instance; }
5050

5151
size_t getMemoryPressure() override {
52-
// Estimate memory usage for compiled shader module
53-
// Shaders can vary widely, but a reasonable estimate is 8-16KB for typical
54-
// shaders Complex shaders (with many uniforms, textures, or computations)
55-
// can be much larger
56-
return 12 * 1024; // 12KB estimate for average shader
52+
// Shader modules can fan out into compiled IR, reflection data and backend
53+
// caches. Report a conservative 1MB to reflect that cost.
54+
return 1 * 1024 * 1024; // 1MB
5755
}
5856

5957
private:

packages/webgpu/cpp/rnwgpu/api/GPUTexture.h

Lines changed: 180 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)