Skip to content

Commit 153a63b

Browse files
hecrjgrovesNL
authored andcommitted
Use a StagingBelt for regular buffer uploads
`Queue::write_buffer` allocates very regularly, specially on Metal. See: iced-rs/iced#2357 A `StagingBelt` gives us more control and predictability.
1 parent 0fdbd90 commit 153a63b

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

examples/hello-world.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use glyphon::{
22
Attrs, Buffer, Cache, Color, Family, FontSystem, Metrics, Resolution, Shaping, SwashCache,
33
TextArea, TextAtlas, TextBounds, TextRenderer, Viewport,
44
};
5+
use std::sync::Arc;
56
use wgpu::{
67
CommandEncoderDescriptor, CompositeAlphaMode, DeviceDescriptor, Features, Instance,
78
InstanceDescriptor, Limits, LoadOp, MultisampleState, Operations, PresentMode,
@@ -15,8 +16,6 @@ use winit::{
1516
window::WindowBuilder,
1617
};
1718

18-
use std::sync::Arc;
19-
2019
fn main() {
2120
pollster::block_on(run());
2221
}
@@ -109,10 +108,14 @@ async fn run() {
109108
},
110109
);
111110

111+
let mut encoder = device
112+
.create_command_encoder(&CommandEncoderDescriptor { label: None });
113+
112114
text_renderer
113115
.prepare(
114116
&device,
115117
&queue,
118+
&mut encoder,
116119
&mut font_system,
117120
&mut atlas,
118121
&viewport,
@@ -135,8 +138,6 @@ async fn run() {
135138

136139
let frame = surface.get_current_texture().unwrap();
137140
let view = frame.texture.create_view(&TextureViewDescriptor::default());
138-
let mut encoder = device
139-
.create_command_encoder(&CommandEncoderDescriptor { label: None });
140141
{
141142
let mut pass = encoder.begin_render_pass(&RenderPassDescriptor {
142143
label: None,

src/text_render.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ use crate::{
22
ColorMode, FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError,
33
SwashCache, SwashContent, TextArea, TextAtlas, Viewport,
44
};
5-
use std::{slice, sync::Arc};
5+
use std::{num::NonZeroU64, slice, sync::Arc};
66
use wgpu::{
7-
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
8-
ImageDataLayout, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline, TextureAspect,
9-
COPY_BUFFER_ALIGNMENT,
7+
util::StagingBelt, Buffer, BufferDescriptor, BufferUsages, CommandEncoder, DepthStencilState,
8+
Device, Extent3d, ImageCopyTexture, ImageDataLayout, MultisampleState, Origin3d, Queue,
9+
RenderPass, RenderPipeline, TextureAspect, COPY_BUFFER_ALIGNMENT,
1010
};
1111

1212
/// A text renderer that uses cached glyphs to render text into an existing render pass.
1313
pub struct TextRenderer {
1414
vertex_buffer: Buffer,
1515
vertex_buffer_size: u64,
16+
staging_belt: StagingBelt,
1617
pipeline: Arc<RenderPipeline>,
1718
glyph_vertices: Vec<GlyphToRender>,
1819
}
@@ -38,6 +39,7 @@ impl TextRenderer {
3839
Self {
3940
vertex_buffer,
4041
vertex_buffer_size,
42+
staging_belt: StagingBelt::new(vertex_buffer_size),
4143
pipeline,
4244
glyph_vertices: Vec::new(),
4345
}
@@ -48,6 +50,7 @@ impl TextRenderer {
4850
&mut self,
4951
device: &Device,
5052
queue: &Queue,
53+
encoder: &mut CommandEncoder,
5154
font_system: &mut FontSystem,
5255
atlas: &mut TextAtlas,
5356
viewport: &Viewport,
@@ -56,6 +59,7 @@ impl TextRenderer {
5659
mut metadata_to_depth: impl FnMut(usize) -> f32,
5760
) -> Result<(), PrepareError> {
5861
self.glyph_vertices.clear();
62+
self.staging_belt.recall();
5963

6064
let resolution = viewport.resolution();
6165

@@ -271,7 +275,16 @@ impl TextRenderer {
271275
};
272276

273277
if self.vertex_buffer_size >= vertices_raw.len() as u64 {
274-
queue.write_buffer(&self.vertex_buffer, 0, vertices_raw);
278+
self.staging_belt
279+
.write_buffer(
280+
encoder,
281+
&self.vertex_buffer,
282+
0,
283+
NonZeroU64::new(vertices_raw.len() as u64).expect("Non-empty vertices"),
284+
device,
285+
)
286+
.copy_from_slice(vertices_raw);
287+
self.staging_belt.finish();
275288
} else {
276289
self.vertex_buffer.destroy();
277290

@@ -284,6 +297,9 @@ impl TextRenderer {
284297

285298
self.vertex_buffer = buffer;
286299
self.vertex_buffer_size = buffer_size;
300+
301+
self.staging_belt.finish();
302+
self.staging_belt = StagingBelt::new(buffer_size);
287303
}
288304

289305
Ok(())
@@ -293,6 +309,7 @@ impl TextRenderer {
293309
&mut self,
294310
device: &Device,
295311
queue: &Queue,
312+
encoder: &mut CommandEncoder,
296313
font_system: &mut FontSystem,
297314
atlas: &mut TextAtlas,
298315
viewport: &Viewport,
@@ -302,6 +319,7 @@ impl TextRenderer {
302319
self.prepare_with_depth(
303320
device,
304321
queue,
322+
encoder,
305323
font_system,
306324
atlas,
307325
viewport,

0 commit comments

Comments
 (0)