Support multi viewport rendering with reusable text atlas (#88)

This commit is contained in:
Pēteris Pakalns 2024-03-26 02:25:57 +02:00 committed by GitHub
parent 4700e54f16
commit f95e66f612
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 83 deletions

View file

@ -4,20 +4,22 @@ use crate::{
};
use std::{iter, mem::size_of, slice, sync::Arc};
use wgpu::{
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline,
TextureAspect, COPY_BUFFER_ALIGNMENT,
BindGroupDescriptor, BindGroupEntry, Buffer, BufferDescriptor, BufferUsages, 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 {
params: Params,
params_buffer: Buffer,
vertex_buffer: Buffer,
vertex_buffer_size: u64,
index_buffer: Buffer,
index_buffer_size: u64,
vertices_to_render: u32,
screen_resolution: Resolution,
pipeline: Arc<RenderPipeline>,
bind_group: wgpu::BindGroup,
}
impl TextRenderer {
@ -46,17 +48,40 @@ impl TextRenderer {
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
let params = Params {
screen_resolution: Resolution {
width: 0,
height: 0,
},
_pad: [0, 0],
};
let params_buffer = device.create_buffer(&BufferDescriptor {
label: Some("glyphon params"),
size: size_of::<Params>() as u64,
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let bind_group = device.create_bind_group(&BindGroupDescriptor {
layout: &atlas.text_render_bind_group_layout,
entries: &[BindGroupEntry {
binding: 0,
resource: params_buffer.as_entire_binding(),
}],
label: Some("glyphon text render bind group"),
});
Self {
params,
params_buffer,
vertex_buffer,
vertex_buffer_size,
index_buffer,
index_buffer_size,
vertices_to_render: 0,
screen_resolution: Resolution {
width: 0,
height: 0,
},
pipeline,
bind_group,
}
}
@ -72,15 +97,11 @@ impl TextRenderer {
cache: &mut SwashCache,
mut metadata_to_depth: impl FnMut(usize) -> f32,
) -> Result<(), PrepareError> {
self.screen_resolution = screen_resolution;
let atlas_current_resolution = { atlas.params.screen_resolution };
if screen_resolution != atlas_current_resolution {
atlas.params.screen_resolution = screen_resolution;
queue.write_buffer(&atlas.params_buffer, 0, unsafe {
if self.params.screen_resolution != screen_resolution {
self.params.screen_resolution = screen_resolution;
queue.write_buffer(&self.params_buffer, 0, unsafe {
slice::from_raw_parts(
&atlas.params as *const Params as *const u8,
&self.params as *const Params as *const u8,
size_of::<Params>(),
)
});
@ -394,15 +415,9 @@ impl TextRenderer {
return Ok(());
}
{
// Validate that screen resolution hasn't changed since `prepare`
if self.screen_resolution != atlas.params.screen_resolution {
return Err(RenderError::ScreenResolutionChanged);
}
}
pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &atlas.bind_group, &[]);
pass.set_bind_group(0, &self.bind_group, &[]);
pass.set_bind_group(1, &atlas.bind_group, &[]);
pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
pass.set_index_buffer(self.index_buffer.slice(..), IndexFormat::Uint32);
pass.draw_indexed(0..self.vertices_to_render, 0, 0..1);