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();
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
let mut encoder = device
|
||||
.create_command_encoder(&CommandEncoderDescriptor { label: None });
|
||||
|
||||
viewport.update(
|
||||
&queue,
|
||||
Resolution {
|
||||
|
@ -113,6 +116,7 @@ async fn run() {
|
|||
.prepare(
|
||||
&device,
|
||||
&queue,
|
||||
&mut encoder,
|
||||
&mut font_system,
|
||||
&mut atlas,
|
||||
&viewport,
|
||||
|
@ -135,8 +139,6 @@ async fn run() {
|
|||
|
||||
let frame = surface.get_current_texture().unwrap();
|
||||
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 {
|
||||
label: None,
|
||||
|
|
|
@ -2,15 +2,17 @@ use crate::{
|
|||
ColorMode, FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError,
|
||||
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::{
|
||||
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
|
||||
ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline,
|
||||
TextureAspect, COPY_BUFFER_ALIGNMENT,
|
||||
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, DepthStencilState, Device, Extent3d,
|
||||
ImageCopyTexture, ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass,
|
||||
RenderPipeline, TextureAspect, COPY_BUFFER_ALIGNMENT,
|
||||
};
|
||||
|
||||
/// A text renderer that uses cached glyphs to render text into an existing render pass.
|
||||
pub struct TextRenderer {
|
||||
staging_belt: StagingBelt,
|
||||
vertex_buffer: Buffer,
|
||||
vertex_buffer_size: u64,
|
||||
index_buffer: Buffer,
|
||||
|
@ -48,6 +50,7 @@ impl TextRenderer {
|
|||
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
||||
|
||||
Self {
|
||||
staging_belt: StagingBelt::new(vertex_buffer_size),
|
||||
vertex_buffer,
|
||||
vertex_buffer_size,
|
||||
index_buffer,
|
||||
|
@ -64,6 +67,7 @@ impl TextRenderer {
|
|||
&mut self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
encoder: &mut CommandEncoder,
|
||||
font_system: &mut FontSystem,
|
||||
atlas: &mut TextAtlas,
|
||||
viewport: &Viewport,
|
||||
|
@ -71,10 +75,11 @@ impl TextRenderer {
|
|||
cache: &mut SwashCache,
|
||||
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
||||
) -> Result<(), PrepareError> {
|
||||
self.staging_belt.recall();
|
||||
self.glyph_vertices.clear();
|
||||
self.glyph_indices.clear();
|
||||
let mut glyphs_added = 0;
|
||||
|
||||
let mut glyphs_added = 0;
|
||||
let resolution = viewport.resolution();
|
||||
|
||||
for text_area in text_areas {
|
||||
|
@ -307,7 +312,15 @@ impl TextRenderer {
|
|||
};
|
||||
|
||||
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 {
|
||||
self.vertex_buffer.destroy();
|
||||
|
||||
|
@ -320,6 +333,9 @@ impl TextRenderer {
|
|||
|
||||
self.vertex_buffer = buffer;
|
||||
self.vertex_buffer_size = buffer_size;
|
||||
|
||||
self.staging_belt.finish();
|
||||
self.staging_belt = StagingBelt::new(buffer_size);
|
||||
}
|
||||
|
||||
let indices = self.glyph_indices.as_slice();
|
||||
|
@ -331,7 +347,15 @@ impl TextRenderer {
|
|||
};
|
||||
|
||||
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 {
|
||||
self.index_buffer.destroy();
|
||||
|
||||
|
@ -346,6 +370,8 @@ impl TextRenderer {
|
|||
self.index_buffer_size = buffer_size;
|
||||
}
|
||||
|
||||
self.staging_belt.finish();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -353,6 +379,7 @@ impl TextRenderer {
|
|||
&mut self,
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
encoder: &mut CommandEncoder,
|
||||
font_system: &mut FontSystem,
|
||||
atlas: &mut TextAtlas,
|
||||
viewport: &Viewport,
|
||||
|
@ -362,6 +389,7 @@ impl TextRenderer {
|
|||
self.prepare_with_depth(
|
||||
device,
|
||||
queue,
|
||||
encoder,
|
||||
font_system,
|
||||
atlas,
|
||||
viewport,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue