Use a StagingBelt
for regular buffer uploads
`Queue::write_buffer` allocates very regularly. A `StagingBelt` gives us much more control.
This commit is contained in:
parent
b411ea71e7
commit
c69090f74b
2 changed files with 39 additions and 9 deletions
|
@ -101,6 +101,9 @@ async fn run() {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
|
let mut encoder = device
|
||||||
|
.create_command_encoder(&CommandEncoderDescriptor { label: None });
|
||||||
|
|
||||||
viewport.update(
|
viewport.update(
|
||||||
&queue,
|
&queue,
|
||||||
Resolution {
|
Resolution {
|
||||||
|
@ -113,6 +116,7 @@ async fn run() {
|
||||||
.prepare(
|
.prepare(
|
||||||
&device,
|
&device,
|
||||||
&queue,
|
&queue,
|
||||||
|
&mut encoder,
|
||||||
&mut font_system,
|
&mut font_system,
|
||||||
&mut atlas,
|
&mut atlas,
|
||||||
&viewport,
|
&viewport,
|
||||||
|
@ -135,8 +139,6 @@ async fn run() {
|
||||||
|
|
||||||
let frame = surface.get_current_texture().unwrap();
|
let frame = surface.get_current_texture().unwrap();
|
||||||
let view = frame.texture.create_view(&TextureViewDescriptor::default());
|
let view = frame.texture.create_view(&TextureViewDescriptor::default());
|
||||||
let mut encoder = device
|
|
||||||
.create_command_encoder(&CommandEncoderDescriptor { label: None });
|
|
||||||
{
|
{
|
||||||
let mut pass = encoder.begin_render_pass(&RenderPassDescriptor {
|
let mut pass = encoder.begin_render_pass(&RenderPassDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
|
|
|
@ -2,15 +2,17 @@ use crate::{
|
||||||
ColorMode, FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError,
|
ColorMode, FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError,
|
||||||
SwashCache, SwashContent, TextArea, TextAtlas, Viewport,
|
SwashCache, SwashContent, TextArea, TextAtlas, Viewport,
|
||||||
};
|
};
|
||||||
use std::{iter, slice, sync::Arc};
|
use std::{iter, num::NonZeroU64, slice, sync::Arc};
|
||||||
|
use wgpu::util::StagingBelt;
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
|
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, DepthStencilState, Device, Extent3d,
|
||||||
ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline,
|
ImageCopyTexture, ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass,
|
||||||
TextureAspect, COPY_BUFFER_ALIGNMENT,
|
RenderPipeline, TextureAspect, COPY_BUFFER_ALIGNMENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A text renderer that uses cached glyphs to render text into an existing render pass.
|
/// A text renderer that uses cached glyphs to render text into an existing render pass.
|
||||||
pub struct TextRenderer {
|
pub struct TextRenderer {
|
||||||
|
staging_belt: StagingBelt,
|
||||||
vertex_buffer: Buffer,
|
vertex_buffer: Buffer,
|
||||||
vertex_buffer_size: u64,
|
vertex_buffer_size: u64,
|
||||||
index_buffer: Buffer,
|
index_buffer: Buffer,
|
||||||
|
@ -48,6 +50,7 @@ impl TextRenderer {
|
||||||
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
staging_belt: StagingBelt::new(vertex_buffer_size),
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
vertex_buffer_size,
|
vertex_buffer_size,
|
||||||
index_buffer,
|
index_buffer,
|
||||||
|
@ -64,6 +67,7 @@ impl TextRenderer {
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
queue: &Queue,
|
queue: &Queue,
|
||||||
|
encoder: &mut CommandEncoder,
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
atlas: &mut TextAtlas,
|
atlas: &mut TextAtlas,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
|
@ -71,10 +75,11 @@ impl TextRenderer {
|
||||||
cache: &mut SwashCache,
|
cache: &mut SwashCache,
|
||||||
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
||||||
) -> Result<(), PrepareError> {
|
) -> Result<(), PrepareError> {
|
||||||
|
self.staging_belt.recall();
|
||||||
self.glyph_vertices.clear();
|
self.glyph_vertices.clear();
|
||||||
self.glyph_indices.clear();
|
self.glyph_indices.clear();
|
||||||
let mut glyphs_added = 0;
|
|
||||||
|
|
||||||
|
let mut glyphs_added = 0;
|
||||||
let resolution = viewport.resolution();
|
let resolution = viewport.resolution();
|
||||||
|
|
||||||
for text_area in text_areas {
|
for text_area in text_areas {
|
||||||
|
@ -307,7 +312,15 @@ impl TextRenderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.vertex_buffer_size >= vertices_raw.len() as u64 {
|
if self.vertex_buffer_size >= vertices_raw.len() as u64 {
|
||||||
queue.write_buffer(&self.vertex_buffer, 0, vertices_raw);
|
self.staging_belt
|
||||||
|
.write_buffer(
|
||||||
|
encoder,
|
||||||
|
&self.vertex_buffer,
|
||||||
|
0,
|
||||||
|
NonZeroU64::new(vertices_raw.len() as u64).expect("Non-empty vertices"),
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
.copy_from_slice(vertices_raw);
|
||||||
} else {
|
} else {
|
||||||
self.vertex_buffer.destroy();
|
self.vertex_buffer.destroy();
|
||||||
|
|
||||||
|
@ -320,6 +333,9 @@ impl TextRenderer {
|
||||||
|
|
||||||
self.vertex_buffer = buffer;
|
self.vertex_buffer = buffer;
|
||||||
self.vertex_buffer_size = buffer_size;
|
self.vertex_buffer_size = buffer_size;
|
||||||
|
|
||||||
|
self.staging_belt.finish();
|
||||||
|
self.staging_belt = StagingBelt::new(buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
let indices = self.glyph_indices.as_slice();
|
let indices = self.glyph_indices.as_slice();
|
||||||
|
@ -331,7 +347,15 @@ impl TextRenderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.index_buffer_size >= indices_raw.len() as u64 {
|
if self.index_buffer_size >= indices_raw.len() as u64 {
|
||||||
queue.write_buffer(&self.index_buffer, 0, indices_raw);
|
self.staging_belt
|
||||||
|
.write_buffer(
|
||||||
|
encoder,
|
||||||
|
&self.index_buffer,
|
||||||
|
0,
|
||||||
|
NonZeroU64::new(indices_raw.len() as u64).expect("Non-empty indices"),
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
.copy_from_slice(indices_raw);
|
||||||
} else {
|
} else {
|
||||||
self.index_buffer.destroy();
|
self.index_buffer.destroy();
|
||||||
|
|
||||||
|
@ -346,6 +370,8 @@ impl TextRenderer {
|
||||||
self.index_buffer_size = buffer_size;
|
self.index_buffer_size = buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.staging_belt.finish();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +379,7 @@ impl TextRenderer {
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
queue: &Queue,
|
queue: &Queue,
|
||||||
|
encoder: &mut CommandEncoder,
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
atlas: &mut TextAtlas,
|
atlas: &mut TextAtlas,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
|
@ -362,6 +389,7 @@ impl TextRenderer {
|
||||||
self.prepare_with_depth(
|
self.prepare_with_depth(
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
|
encoder,
|
||||||
font_system,
|
font_system,
|
||||||
atlas,
|
atlas,
|
||||||
viewport,
|
viewport,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue