Simplify rendering pipeline, reduce gpu memory usage, remove duplicated data (#86)
This commit is contained in:
parent
b411ea71e7
commit
0fdbd90c55
3 changed files with 38 additions and 104 deletions
13
src/cache.rs
13
src/cache.rs
|
@ -5,9 +5,9 @@ use wgpu::{
|
||||||
BindingResource, BindingType, BlendState, Buffer, BufferBindingType, ColorTargetState,
|
BindingResource, BindingType, BlendState, Buffer, BufferBindingType, ColorTargetState,
|
||||||
ColorWrites, DepthStencilState, Device, FilterMode, FragmentState, MultisampleState,
|
ColorWrites, DepthStencilState, Device, FilterMode, FragmentState, MultisampleState,
|
||||||
PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PrimitiveState,
|
PipelineCompilationOptions, PipelineLayout, PipelineLayoutDescriptor, PrimitiveState,
|
||||||
RenderPipeline, RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor,
|
PrimitiveTopology, RenderPipeline, RenderPipelineDescriptor, Sampler, SamplerBindingType,
|
||||||
ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, TextureFormat,
|
SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages,
|
||||||
TextureSampleType, TextureView, TextureViewDimension, VertexFormat, VertexState,
|
TextureFormat, TextureSampleType, TextureView, TextureViewDimension, VertexFormat, VertexState,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -56,7 +56,7 @@ impl Cache {
|
||||||
|
|
||||||
let vertex_buffer_layout = wgpu::VertexBufferLayout {
|
let vertex_buffer_layout = wgpu::VertexBufferLayout {
|
||||||
array_stride: mem::size_of::<GlyphToRender>() as wgpu::BufferAddress,
|
array_stride: mem::size_of::<GlyphToRender>() as wgpu::BufferAddress,
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
step_mode: wgpu::VertexStepMode::Instance,
|
||||||
attributes: &[
|
attributes: &[
|
||||||
wgpu::VertexAttribute {
|
wgpu::VertexAttribute {
|
||||||
format: VertexFormat::Sint32x2,
|
format: VertexFormat::Sint32x2,
|
||||||
|
@ -232,7 +232,10 @@ impl Cache {
|
||||||
})],
|
})],
|
||||||
compilation_options: PipelineCompilationOptions::default(),
|
compilation_options: PipelineCompilationOptions::default(),
|
||||||
}),
|
}),
|
||||||
primitive: PrimitiveState::default(),
|
primitive: PrimitiveState {
|
||||||
|
topology: PrimitiveTopology::TriangleStrip,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
depth_stencil: depth_stencil.clone(),
|
depth_stencil: depth_stencil.clone(),
|
||||||
multisample,
|
multisample,
|
||||||
multiview: None,
|
multiview: None,
|
||||||
|
|
|
@ -47,25 +47,17 @@ fn vs_main(in_vert: VertexInput) -> VertexOutput {
|
||||||
let height = (in_vert.dim & 0xffff0000u) >> 16u;
|
let height = (in_vert.dim & 0xffff0000u) >> 16u;
|
||||||
let color = in_vert.color;
|
let color = in_vert.color;
|
||||||
var uv = vec2<u32>(in_vert.uv & 0xffffu, (in_vert.uv & 0xffff0000u) >> 16u);
|
var uv = vec2<u32>(in_vert.uv & 0xffffu, (in_vert.uv & 0xffff0000u) >> 16u);
|
||||||
let v = in_vert.vertex_idx % 4u;
|
let v = in_vert.vertex_idx;
|
||||||
|
|
||||||
switch v {
|
let corner_position = vec2<u32>(
|
||||||
case 1u: {
|
in_vert.vertex_idx & 1u,
|
||||||
pos.x += i32(width);
|
(in_vert.vertex_idx >> 1u) & 1u,
|
||||||
uv.x += width;
|
);
|
||||||
}
|
|
||||||
case 2u: {
|
let corner_offset = vec2<u32>(width, height) * corner_position;
|
||||||
pos.x += i32(width);
|
|
||||||
pos.y += i32(height);
|
uv = uv + corner_offset;
|
||||||
uv.x += width;
|
pos = pos + vec2<i32>(corner_offset);
|
||||||
uv.y += height;
|
|
||||||
}
|
|
||||||
case 3u: {
|
|
||||||
pos.y += i32(height);
|
|
||||||
uv.y += height;
|
|
||||||
}
|
|
||||||
default: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
var vert_output: VertexOutput;
|
var vert_output: VertexOutput;
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,19 @@ 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::{slice, sync::Arc};
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
|
Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
|
||||||
ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline,
|
ImageDataLayout, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline, TextureAspect,
|
||||||
TextureAspect, COPY_BUFFER_ALIGNMENT,
|
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 {
|
||||||
vertex_buffer: Buffer,
|
vertex_buffer: Buffer,
|
||||||
vertex_buffer_size: u64,
|
vertex_buffer_size: u64,
|
||||||
index_buffer: Buffer,
|
|
||||||
index_buffer_size: u64,
|
|
||||||
vertices_to_render: u32,
|
|
||||||
pipeline: Arc<RenderPipeline>,
|
pipeline: Arc<RenderPipeline>,
|
||||||
glyph_vertices: Vec<GlyphToRender>,
|
glyph_vertices: Vec<GlyphToRender>,
|
||||||
glyph_indices: Vec<u32>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextRenderer {
|
impl TextRenderer {
|
||||||
|
@ -37,25 +33,13 @@ impl TextRenderer {
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
let index_buffer_size = next_copy_buffer_size(4096);
|
|
||||||
let index_buffer = device.create_buffer(&BufferDescriptor {
|
|
||||||
label: Some("glyphon indices"),
|
|
||||||
size: index_buffer_size,
|
|
||||||
usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
|
|
||||||
mapped_at_creation: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
vertex_buffer,
|
vertex_buffer,
|
||||||
vertex_buffer_size,
|
vertex_buffer_size,
|
||||||
index_buffer,
|
|
||||||
index_buffer_size,
|
|
||||||
vertices_to_render: 0,
|
|
||||||
pipeline,
|
pipeline,
|
||||||
glyph_vertices: Vec::new(),
|
glyph_vertices: Vec::new(),
|
||||||
glyph_indices: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +56,6 @@ impl TextRenderer {
|
||||||
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
||||||
) -> Result<(), PrepareError> {
|
) -> Result<(), PrepareError> {
|
||||||
self.glyph_vertices.clear();
|
self.glyph_vertices.clear();
|
||||||
self.glyph_indices.clear();
|
|
||||||
let mut glyphs_added = 0;
|
|
||||||
|
|
||||||
let resolution = viewport.resolution();
|
let resolution = viewport.resolution();
|
||||||
|
|
||||||
|
@ -257,8 +239,7 @@ impl TextRenderer {
|
||||||
|
|
||||||
let depth = metadata_to_depth(glyph.metadata);
|
let depth = metadata_to_depth(glyph.metadata);
|
||||||
|
|
||||||
self.glyph_vertices.extend(
|
self.glyph_vertices.push(GlyphToRender {
|
||||||
iter::repeat(GlyphToRender {
|
|
||||||
pos: [x, y],
|
pos: [x, y],
|
||||||
dim: [width as u16, height as u16],
|
dim: [width as u16, height as u16],
|
||||||
uv: [atlas_x, atlas_y],
|
uv: [atlas_x, atlas_y],
|
||||||
|
@ -271,29 +252,12 @@ impl TextRenderer {
|
||||||
} as u16,
|
} as u16,
|
||||||
],
|
],
|
||||||
depth,
|
depth,
|
||||||
})
|
});
|
||||||
.take(4),
|
|
||||||
);
|
|
||||||
|
|
||||||
let start = 4 * glyphs_added as u32;
|
|
||||||
self.glyph_indices.extend([
|
|
||||||
start,
|
|
||||||
start + 1,
|
|
||||||
start + 2,
|
|
||||||
start,
|
|
||||||
start + 2,
|
|
||||||
start + 3,
|
|
||||||
]);
|
|
||||||
|
|
||||||
glyphs_added += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERTICES_PER_GLYPH: u32 = 6;
|
let will_render = !self.glyph_vertices.is_empty();
|
||||||
self.vertices_to_render = glyphs_added as u32 * VERTICES_PER_GLYPH;
|
|
||||||
|
|
||||||
let will_render = glyphs_added > 0;
|
|
||||||
if !will_render {
|
if !will_render {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -322,30 +286,6 @@ impl TextRenderer {
|
||||||
self.vertex_buffer_size = buffer_size;
|
self.vertex_buffer_size = buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
let indices = self.glyph_indices.as_slice();
|
|
||||||
let indices_raw = unsafe {
|
|
||||||
slice::from_raw_parts(
|
|
||||||
indices as *const _ as *const u8,
|
|
||||||
std::mem::size_of_val(indices),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.index_buffer_size >= indices_raw.len() as u64 {
|
|
||||||
queue.write_buffer(&self.index_buffer, 0, indices_raw);
|
|
||||||
} else {
|
|
||||||
self.index_buffer.destroy();
|
|
||||||
|
|
||||||
let (buffer, buffer_size) = create_oversized_buffer(
|
|
||||||
device,
|
|
||||||
Some("glyphon indices"),
|
|
||||||
indices_raw,
|
|
||||||
BufferUsages::INDEX | BufferUsages::COPY_DST,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.index_buffer = buffer;
|
|
||||||
self.index_buffer_size = buffer_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +318,7 @@ impl TextRenderer {
|
||||||
viewport: &'pass Viewport,
|
viewport: &'pass Viewport,
|
||||||
pass: &mut RenderPass<'pass>,
|
pass: &mut RenderPass<'pass>,
|
||||||
) -> Result<(), RenderError> {
|
) -> Result<(), RenderError> {
|
||||||
if self.vertices_to_render == 0 {
|
if self.glyph_vertices.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,8 +326,7 @@ impl TextRenderer {
|
||||||
pass.set_bind_group(0, &atlas.bind_group, &[]);
|
pass.set_bind_group(0, &atlas.bind_group, &[]);
|
||||||
pass.set_bind_group(1, &viewport.bind_group, &[]);
|
pass.set_bind_group(1, &viewport.bind_group, &[]);
|
||||||
pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||||
pass.set_index_buffer(self.index_buffer.slice(..), IndexFormat::Uint32);
|
pass.draw(0..4, 0..self.glyph_vertices.len() as u32);
|
||||||
pass.draw_indexed(0..self.vertices_to_render, 0, 0..1);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue