forked from 1b-agent/opencadstudio-upstream
perf: account for the device memory the renderer holds
Stage 0 of the roadmap asks for a memory baseline before any more
optimisation, and explicitly not from RSS: the allocator and the driver
both retain high-water memory that RSS cannot tell apart from live
resources.
`gpu-live` counts from the sizes this renderer allocated, in the
categories large enough to decide where the next fix goes:
slots total shadow targets text_atlas wire_arena block_geometry
It is partial by construction and says so, rather than presenting itself
as a total. Hatches, images, meshes and Face3D are not counted yet.
Three of the numbers needed a size that was not reachable before: the
block-geometry chunk records its bytes at build because in storage mode
the buffer belongs to the bind group, the arena exposes its allocation
rather than its occupied prefix — headroom is what a budget has to answer
for — and the text atlas reports its `R8` texel count.
Emitted only when a number moves. `prepare` runs thousands of times in a
session and these change a handful of times, so a per-frame line would
bury the log it is meant to explain.
This answers the question the previous fix left open: whether the arena's
52 MiB per slot, the 16 MiB shadow map every slot allocates whether or not
shadows are on, or the render targets dominate once a paper layout has
four or five viewports on screen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a9a2c82478
commit
d81a858040
5 files changed
+142
No files matched your search
@@ -703,6 +703,15 @@ pub struct BlockWireTarget<'a> {
|
||||
pub mode: WirePipelineMode,
|
||||
}
|
||||
|
||||
/// Device bytes held by a whole block-geometry cache.
|
||||
pub fn block_geometry_bytes(cache: &BlockGeometryCache) -> u64 {
|
||||
cache
|
||||
.values()
|
||||
.flat_map(|chunks| chunks.iter())
|
||||
.map(|chunk| chunk.gpu_bytes)
|
||||
.sum()
|
||||
}
|
||||
|
||||
/// `(source_id, mesh_edge, colour bits, base translation bits)`.
|
||||
pub type BlockGeometryKey = (u64, bool, [u32; 4], [u64; 3]);
|
||||
|
||||
@@ -722,6 +731,9 @@ pub struct BlockGeometryChunk {
|
||||
pub vertex_buffer: Option<wgpu::Buffer>,
|
||||
pub vertex_count: u32,
|
||||
pub bind_group: std::sync::Arc<wgpu::BindGroup>,
|
||||
/// Device bytes this chunk holds. Recorded at build because in storage mode
|
||||
/// the buffer is owned by `bind_group` and cannot be measured from here.
|
||||
pub gpu_bytes: u64,
|
||||
}
|
||||
|
||||
impl BlockWireGpu {
|
||||
@@ -856,6 +868,7 @@ impl BlockWireGpu {
|
||||
BlockGeometryChunk {
|
||||
vertex_buffer: None,
|
||||
vertex_count: chunk.len() as u32 * 6,
|
||||
gpu_bytes: std::mem::size_of_val(chunk) as u64,
|
||||
bind_group: std::sync::Arc::new(device.create_bind_group(
|
||||
&wgpu::BindGroupDescriptor {
|
||||
label: Some("block_wire.const.bg"),
|
||||
@@ -897,6 +910,7 @@ impl BlockWireGpu {
|
||||
vertices
|
||||
.chunks(max_verts)
|
||||
.map(|chunk| BlockGeometryChunk {
|
||||
gpu_bytes: std::mem::size_of_val(chunk) as u64,
|
||||
vertex_buffer: Some(super::gpu_upload::upload_buffer(
|
||||
device,
|
||||
queue,
|
||||
|
||||
Reference in new issue
Block a user