Skip to content

Commit c3ee3a0

Browse files
authored
Introduce TextRendererFactory (#274)
1 parent 37ebe1d commit c3ee3a0

7 files changed

Lines changed: 129 additions & 137 deletions

File tree

neothesia-cli/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use std::{default::Default, time::Duration};
33
use neothesia_core::{
44
config::Config,
55
piano_layout,
6-
render::{GuidelineRenderer, KeyboardRenderer, QuadRenderer, TextRenderer, WaterfallRenderer},
6+
render::{
7+
GuidelineRenderer, KeyboardRenderer, QuadRenderer, TextRenderer, TextRendererFactory,
8+
WaterfallRenderer,
9+
},
710
};
811
use wgpu_jumpstart::{wgpu, Gpu, TransformUniform, Uniform};
912

@@ -107,7 +110,8 @@ impl Recorder {
107110

108111
waterfall.update(time_without_lead_in(&playback));
109112

110-
let text = TextRenderer::new(&gpu);
113+
let text = TextRendererFactory::new(&gpu);
114+
let text = text.new_renderer();
111115

112116
let mut synth = oxisynth::Synth::new(oxisynth::SynthDescriptor {
113117
sample_rate: 44100.0,

neothesia-core/src/render/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ pub use guidelines::GuidelineRenderer;
1313
pub use keyboard::{KeyState as KeyboardKeyState, KeyboardRenderer};
1414
pub use note_labels::NoteLabels;
1515
pub use quad::{QuadInstance, QuadRenderer};
16-
pub use text::{TextRenderer, TextRendererInstance};
16+
pub use text::{TextRenderer, TextRendererFactory};
1717
pub use waterfall::WaterfallRenderer;

neothesia-core/src/render/note_labels/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::utils::Point;
22

3-
use super::{waterfall::NoteList, KeyboardRenderer, TextRendererInstance};
3+
use super::{waterfall::NoteList, KeyboardRenderer, TextRenderer};
44

55
#[derive(Default)]
66
struct LabelsCache {
@@ -62,11 +62,11 @@ pub struct NoteLabels {
6262
pos: Point<f32>,
6363
notes: NoteList,
6464
labels_cache: LabelsCache,
65-
text_renderer: TextRendererInstance,
65+
text_renderer: TextRenderer,
6666
}
6767

6868
impl NoteLabels {
69-
pub fn new(pos: Point<f32>, notes: &NoteList, text_renderer: TextRendererInstance) -> Self {
69+
pub fn new(pos: Point<f32>, notes: &NoteList, text_renderer: TextRenderer) -> Self {
7070
Self {
7171
pos,
7272
notes: notes.clone(),

neothesia-core/src/render/text/mod.rs

Lines changed: 110 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ struct TextShared {
2828
swash_cache: glyphon::SwashCache,
2929
}
3030

31-
pub struct TextRendererInstance {
31+
pub struct TextRenderer {
3232
text_renderer: glyphon::TextRenderer,
3333
text_areas: Vec<TextArea>,
3434
shared: Rc<RefCell<TextShared>>,
3535
device: wgpu::Device,
3636
queue: wgpu::Queue,
3737
}
3838

39-
impl TextRendererInstance {
39+
impl TextRenderer {
4040
fn new(device: &wgpu::Device, queue: &wgpu::Queue, shared: Rc<RefCell<TextShared>>) -> Self {
4141
let text_renderer = glyphon::TextRenderer::new(
4242
&mut shared.borrow_mut().atlas,
@@ -54,126 +54,6 @@ impl TextRendererInstance {
5454
}
5555
}
5656

57-
pub fn queue(&mut self, area: TextArea) {
58-
self.text_areas.push(area);
59-
}
60-
61-
pub fn update(&mut self, logical_size: (u32, u32)) {
62-
let shared = &mut *self.shared.borrow_mut();
63-
let elements = self.text_areas.iter().map(|area| glyphon::TextArea {
64-
buffer: &area.buffer,
65-
left: area.left,
66-
top: area.top,
67-
scale: area.scale,
68-
bounds: area.bounds,
69-
default_color: area.default_color,
70-
custom_glyphs: &[],
71-
});
72-
73-
shared.viewport.update(
74-
&self.queue,
75-
glyphon::Resolution {
76-
width: logical_size.0,
77-
height: logical_size.1,
78-
},
79-
);
80-
81-
self.text_renderer
82-
.prepare(
83-
&self.device,
84-
&self.queue,
85-
&mut crate::font_system::font_system().borrow_mut(),
86-
&mut shared.atlas,
87-
&shared.viewport,
88-
elements,
89-
&mut shared.swash_cache,
90-
)
91-
.unwrap();
92-
93-
self.text_areas.clear();
94-
}
95-
96-
pub fn render<'rpass>(&'rpass mut self, render_pass: &mut wgpu::RenderPass<'rpass>) {
97-
let shared = self.shared.borrow();
98-
self.text_renderer
99-
.render(&shared.atlas, &shared.viewport, render_pass)
100-
.unwrap();
101-
}
102-
}
103-
104-
pub struct TextRenderer {
105-
_cache: glyphon::Cache,
106-
107-
default_instance: TextRendererInstance,
108-
}
109-
110-
impl TextRenderer {
111-
pub fn new(gpu: &Gpu) -> Self {
112-
let swash_cache = glyphon::SwashCache::new();
113-
let cache = glyphon::Cache::new(&gpu.device);
114-
let atlas = glyphon::TextAtlas::new(&gpu.device, &gpu.queue, &cache, gpu.texture_format);
115-
116-
let viewport = glyphon::Viewport::new(&gpu.device, &cache);
117-
118-
let shared = Rc::new(RefCell::new(TextShared {
119-
viewport,
120-
atlas,
121-
swash_cache,
122-
}));
123-
124-
let default_instance = TextRendererInstance::new(&gpu.device, &gpu.queue, shared);
125-
126-
Self {
127-
_cache: cache,
128-
default_instance,
129-
}
130-
}
131-
132-
pub fn new_renderer(&mut self) -> TextRendererInstance {
133-
TextRendererInstance::new(
134-
&self.default_instance.device,
135-
&self.default_instance.queue,
136-
self.default_instance.shared.clone(),
137-
)
138-
}
139-
140-
pub fn queue_mut(&mut self) -> &mut Vec<TextArea> {
141-
&mut self.default_instance.text_areas
142-
}
143-
144-
pub fn queue(&mut self, area: TextArea) {
145-
self.default_instance.queue(area);
146-
}
147-
148-
pub fn queue_text(&mut self, text: &str) {
149-
let font_system = crate::font_system::font_system();
150-
let font_system = &mut font_system.borrow_mut();
151-
152-
let mut buffer = glyphon::Buffer::new(font_system, glyphon::Metrics::new(15.0, 15.0));
153-
buffer.set_size(font_system, Some(f32::MAX), Some(f32::MAX));
154-
buffer.set_text(
155-
font_system,
156-
text,
157-
&glyphon::Attrs::new().family(glyphon::Family::SansSerif),
158-
glyphon::Shaping::Basic,
159-
);
160-
buffer.shape_until_scroll(font_system, false);
161-
162-
#[cfg(debug_assertions)]
163-
let top = 20.0;
164-
#[cfg(not(debug_assertions))]
165-
let top = 5.0;
166-
167-
self.queue(TextArea {
168-
buffer,
169-
left: 0.0,
170-
top,
171-
scale: 1.0,
172-
bounds: glyphon::TextBounds::default(),
173-
default_color: glyphon::Color::rgb(255, 255, 255),
174-
});
175-
}
176-
17757
pub fn measure(buffer: &glyphon::cosmic_text::Buffer) -> (f32, f32) {
17858
buffer
17959
.layout_runs()
@@ -276,6 +156,35 @@ impl TextRenderer {
276156
self.queue_buffer(x, y, buffer);
277157
}
278158

159+
pub fn queue_text(&mut self, text: &str) {
160+
let font_system = crate::font_system::font_system();
161+
let font_system = &mut font_system.borrow_mut();
162+
163+
let mut buffer = glyphon::Buffer::new(font_system, glyphon::Metrics::new(15.0, 15.0));
164+
buffer.set_size(font_system, Some(f32::MAX), Some(f32::MAX));
165+
buffer.set_text(
166+
font_system,
167+
text,
168+
&glyphon::Attrs::new().family(glyphon::Family::SansSerif),
169+
glyphon::Shaping::Basic,
170+
);
171+
buffer.shape_until_scroll(font_system, false);
172+
173+
#[cfg(debug_assertions)]
174+
let top = 20.0;
175+
#[cfg(not(debug_assertions))]
176+
let top = 5.0;
177+
178+
self.queue(TextArea {
179+
buffer,
180+
left: 0.0,
181+
top,
182+
scale: 1.0,
183+
bounds: glyphon::TextBounds::default(),
184+
default_color: glyphon::Color::rgb(255, 255, 255),
185+
});
186+
}
187+
279188
pub fn queue_fps(&mut self, fps: f64, y: f32) {
280189
let font_system = crate::font_system::font_system();
281190
let font_system = &mut font_system.borrow_mut();
@@ -301,16 +210,89 @@ impl TextRenderer {
301210
});
302211
}
303212

304-
#[profiling::function]
305-
pub fn update(&mut self, logical_size: (u32, u32)) {
306-
self.default_instance.update(logical_size);
213+
pub fn queue_mut(&mut self) -> &mut Vec<TextArea> {
214+
&mut self.text_areas
307215
}
308216

309-
pub fn end_frame(&mut self) {
310-
self.default_instance.shared.borrow_mut().atlas.trim();
217+
pub fn queue(&mut self, area: TextArea) {
218+
self.text_areas.push(area);
219+
}
220+
221+
pub fn update(&mut self, logical_size: (u32, u32)) {
222+
let shared = &mut *self.shared.borrow_mut();
223+
let elements = self.text_areas.iter().map(|area| glyphon::TextArea {
224+
buffer: &area.buffer,
225+
left: area.left,
226+
top: area.top,
227+
scale: area.scale,
228+
bounds: area.bounds,
229+
default_color: area.default_color,
230+
custom_glyphs: &[],
231+
});
232+
233+
shared.viewport.update(
234+
&self.queue,
235+
glyphon::Resolution {
236+
width: logical_size.0,
237+
height: logical_size.1,
238+
},
239+
);
240+
241+
self.text_renderer
242+
.prepare(
243+
&self.device,
244+
&self.queue,
245+
&mut crate::font_system::font_system().borrow_mut(),
246+
&mut shared.atlas,
247+
&shared.viewport,
248+
elements,
249+
&mut shared.swash_cache,
250+
)
251+
.unwrap();
252+
253+
self.text_areas.clear();
311254
}
312255

313256
pub fn render<'rpass>(&'rpass mut self, render_pass: &mut wgpu::RenderPass<'rpass>) {
314-
self.default_instance.render(render_pass);
257+
let shared = self.shared.borrow();
258+
self.text_renderer
259+
.render(&shared.atlas, &shared.viewport, render_pass)
260+
.unwrap();
261+
}
262+
}
263+
264+
pub struct TextRendererFactory {
265+
shared: Rc<RefCell<TextShared>>,
266+
device: wgpu::Device,
267+
queue: wgpu::Queue,
268+
}
269+
270+
impl TextRendererFactory {
271+
pub fn new(gpu: &Gpu) -> Self {
272+
let swash_cache = glyphon::SwashCache::new();
273+
let cache = glyphon::Cache::new(&gpu.device);
274+
let atlas = glyphon::TextAtlas::new(&gpu.device, &gpu.queue, &cache, gpu.texture_format);
275+
276+
let viewport = glyphon::Viewport::new(&gpu.device, &cache);
277+
278+
let shared = Rc::new(RefCell::new(TextShared {
279+
viewport,
280+
atlas,
281+
swash_cache,
282+
}));
283+
284+
Self {
285+
shared,
286+
device: gpu.device.clone(),
287+
queue: gpu.queue.clone(),
288+
}
289+
}
290+
291+
pub fn new_renderer(&self) -> TextRenderer {
292+
TextRenderer::new(&self.device, &self.queue, self.shared.clone())
293+
}
294+
295+
pub fn end_frame(&mut self) {
296+
self.shared.borrow_mut().atlas.trim();
315297
}
316298
}

neothesia/src/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::config::Config;
44
use crate::input_manager::InputManager;
55
use crate::utils::window::WindowState;
66
use crate::{output_manager::OutputManager, NeothesiaEvent, TransformUniform};
7+
use neothesia_core::render::TextRendererFactory;
78
use wgpu_jumpstart::{Gpu, Uniform};
89
use winit::event_loop::EventLoopProxy;
910

@@ -18,6 +19,7 @@ pub struct Context {
1819
pub gpu: Gpu,
1920

2021
pub transform: Uniform<TransformUniform>,
22+
pub text_renderer_factory: TextRendererFactory,
2123

2224
pub output_manager: OutputManager,
2325
pub input_manager: InputManager,
@@ -65,13 +67,16 @@ impl Context {
6567

6668
let config = Config::new();
6769

70+
let text_renderer_factory = TextRendererFactory::new(&gpu);
71+
6872
Self {
6973
window,
7074
iced_manager,
7175

7276
window_state,
7377
gpu,
7478
transform: transform_uniform,
79+
text_renderer_factory,
7580

7681
output_manager: Default::default(),
7782
input_manager: InputManager::new(proxy.clone()),

neothesia/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ impl Neothesia {
219219

220220
self.context.window.pre_present_notify();
221221
frame.present();
222+
223+
self.context.text_renderer_factory.end_frame();
222224
}
223225
}
224226

neothesia/src/scene/playing_scene/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ impl PlayingScene {
9090
keyboard_layout.clone(),
9191
);
9292

93-
let mut text_renderer = TextRenderer::new(&ctx.gpu);
93+
let text_renderer = ctx.text_renderer_factory.new_renderer();
9494

9595
let note_labels = ctx.config.note_labels().then_some(NoteLabels::new(
9696
*keyboard.pos(),
9797
waterfall.notes(),
98-
text_renderer.new_renderer(),
98+
ctx.text_renderer_factory.new_renderer(),
9999
));
100100

101101
let player = MidiPlayer::new(
@@ -206,7 +206,6 @@ impl PlayingScene {
206206
impl Scene for PlayingScene {
207207
#[profiling::function]
208208
fn update(&mut self, ctx: &mut Context, delta: Duration) {
209-
self.text_renderer.end_frame();
210209
self.quad_pipeline.clear();
211210

212211
self.rewind_controller.update(&mut self.player, ctx, delta);

0 commit comments

Comments
 (0)