Skip to content

Commit

Permalink
Use single QuadPipeline (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex authored Sep 28, 2023
1 parent d3ade50 commit da0570f
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 129 deletions.
24 changes: 14 additions & 10 deletions neothesia-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{default::Default, time::Duration};

use neothesia_core::{
config::Config,
render::{KeyboardRenderer, TextRenderer, WaterfallRenderer},
render::{KeyboardRenderer, QuadPipeline, TextRenderer, WaterfallRenderer},
};
use wgpu_jumpstart::{wgpu, Gpu, TransformUniform, Uniform};

Expand All @@ -12,6 +12,7 @@ struct Recorder {

playback: midi_file::PlaybackState,

quad_pipeline: QuadPipeline,
keyboard: KeyboardRenderer,
waterfall: WaterfallRenderer,
text: TextRenderer,
Expand Down Expand Up @@ -70,14 +71,12 @@ impl Recorder {
wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
);

let quad_pipeline = QuadPipeline::new(&gpu, &transform_uniform);

let keyboard_layout = get_layout(width as f32, height as f32);

let mut keyboard = KeyboardRenderer::new(
&gpu,
&transform_uniform,
keyboard_layout.clone(),
config.vertical_guidelines,
);
let mut keyboard =
KeyboardRenderer::new(keyboard_layout.clone(), config.vertical_guidelines);

keyboard.position_on_bottom_of_parent(height as f32);

Expand All @@ -101,6 +100,7 @@ impl Recorder {

playback,

quad_pipeline,
keyboard,
waterfall,
text,
Expand All @@ -118,7 +118,10 @@ impl Recorder {
self.waterfall
.update(&self.gpu.queue, time_without_lead_in(&self.playback));

self.keyboard.update(&self.gpu.queue, &mut self.text);
self.quad_pipeline.clear();
self.keyboard
.update(&mut self.quad_pipeline, &mut self.text);
self.quad_pipeline.prepare(&self.gpu.queue);

self.text.update((self.width, self.height), &self.gpu);
}
Expand Down Expand Up @@ -151,7 +154,8 @@ impl Recorder {
});

self.waterfall.render(&self.transform_uniform, &mut rpass);
self.keyboard.render(&self.transform_uniform, &mut rpass);
self.quad_pipeline
.render(&self.transform_uniform, &mut rpass);
self.text.render(&mut rpass);
}

Expand Down Expand Up @@ -296,7 +300,7 @@ fn file_midi_events(
key.pressed_by_file_off();
}

keyboard.queue_reupload();
keyboard.invalidate_cache();
}
}
}
150 changes: 67 additions & 83 deletions neothesia-core/src/render/keyboard/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use crate::{
render::{QuadInstance, QuadPipeline},
utils::Point,
TransformUniform, Uniform,
};

use piano_math::range::KeyboardRange;

mod key_state;
pub use key_state::KeyState;
use wgpu_jumpstart::Gpu;

use super::TextRenderer;

Expand All @@ -17,45 +15,38 @@ pub struct KeyboardRenderer {

key_states: Vec<KeyState>,

quad_pipeline: QuadPipeline,
should_reupload: bool,

layout: piano_math::KeyboardLayout,
vertical_guidelines: bool,

cache: Vec<QuadInstance>,
}

impl KeyboardRenderer {
pub fn new(
gpu: &Gpu,
transform_uniform: &Uniform<TransformUniform>,
layout: piano_math::KeyboardLayout,
vertical_guidelines: bool,
) -> Self {
let quad_pipeline = QuadPipeline::new(gpu, transform_uniform);
pub fn new(layout: piano_math::KeyboardLayout, vertical_guidelines: bool) -> Self {
let key_states: Vec<KeyState> = layout
.range
.iter()
.map(|id| KeyState::new(id.is_black()))
.collect();

let cache = Vec::with_capacity(key_states.len() + 1);

Self {
pos: Default::default(),

key_states,

quad_pipeline,
should_reupload: false,

layout,
vertical_guidelines,
cache,
}
}

pub fn reset_notes(&mut self) {
for key in self.key_states.iter_mut() {
key.pressed_by_file_off();
}
self.queue_reupload();
self.invalidate_cache();
}

pub fn range(&self) -> &KeyboardRange {
Expand All @@ -79,7 +70,7 @@ impl KeyboardRenderer {

pub fn set_pos(&mut self, pos: Point<f32>) {
self.pos = pos;
self.queue_reupload();
self.invalidate_cache();
}

pub fn layout(&self) -> &piano_math::KeyboardLayout {
Expand All @@ -88,76 +79,77 @@ impl KeyboardRenderer {

pub fn set_layout(&mut self, layout: piano_math::KeyboardLayout) {
self.layout = layout;
self.queue_reupload();
self.invalidate_cache();
}

pub fn queue_reupload(&mut self) {
self.should_reupload = true;
pub fn invalidate_cache(&mut self) {
self.cache.clear();
}

/// Reupload instances to GPU
fn reupload(&mut self, queue: &wgpu::Queue) {
self.quad_pipeline.with_instances_mut(queue, |instances| {
instances.clear();

// black_background
instances.push(QuadInstance {
position: self.pos.into(),
size: [self.layout.width, self.layout.height],
color: [0.0, 0.0, 0.0, 1.0],
..Default::default()
});
fn reupload(&mut self) {
let instances = &mut self.cache;

// black_background
instances.push(QuadInstance {
position: self.pos.into(),
size: [self.layout.width, self.layout.height],
color: [0.0, 0.0, 0.0, 1.0],
..Default::default()
});

for key in self
.layout
.keys
.iter()
.filter(|key| key.kind().is_neutral())
{
let id = key.id();
let color = self.key_states[id].color();

if self.vertical_guidelines {
// Horizontal guides
// TODO: Does not really fit in keyboard renderer
if key.note_id() == 0 || key.note_id() == 5 {
let x = self.pos.x + key.x();
let y = 0.0;

let w = 1.0;
let h = f32::MAX;

let color = if key.note_id() == 0 {
[0.2, 0.2, 0.2, 1.0]
} else {
[0.05, 0.05, 0.05, 1.0]
};

instances.push(QuadInstance {
position: [x, y],
size: [w, h],
color,
border_radius: [0.0, 0.0, 0.0, 0.0],
});
}
for key in self
.layout
.keys
.iter()
.filter(|key| key.kind().is_neutral())
{
let id = key.id();
let color = self.key_states[id].color();

if self.vertical_guidelines {
// Horizontal guides
// TODO: Does not really fit in keyboard renderer
if key.note_id() == 0 || key.note_id() == 5 {
let x = self.pos.x + key.x();
let y = 0.0;

let w = 1.0;
let h = f32::MAX;

let color = if key.note_id() == 0 {
[0.2, 0.2, 0.2, 1.0]
} else {
[0.05, 0.05, 0.05, 1.0]
};

instances.push(QuadInstance {
position: [x, y],
size: [w, h],
color,
border_radius: [0.0, 0.0, 0.0, 0.0],
});
}

instances.push(key_state::to_quad(key, color, self.pos));
}

for key in self.layout.keys.iter().filter(|key| key.kind().is_sharp()) {
let id = key.id();
let color = self.key_states[id].color();
instances.push(key_state::to_quad(key, color, self.pos));
}

instances.push(key_state::to_quad(key, color, self.pos));
}
});
self.should_reupload = false;
for key in self.layout.keys.iter().filter(|key| key.kind().is_sharp()) {
let id = key.id();
let color = self.key_states[id].color();

instances.push(key_state::to_quad(key, color, self.pos));
}
}

pub fn update(&mut self, queue: &wgpu::Queue, text: &mut TextRenderer) {
if self.should_reupload {
self.reupload(queue);
pub fn update(&mut self, quads: &mut QuadPipeline, text: &mut TextRenderer) {
if self.cache.is_empty() {
self.reupload();
}

for quad in self.cache.iter() {
quads.instances().push(*quad);
}

for (id, key) in self
Expand Down Expand Up @@ -203,12 +195,4 @@ impl KeyboardRenderer {
});
}
}

pub fn render<'rpass>(
&'rpass mut self,
transform_uniform: &'rpass Uniform<TransformUniform>,
render_pass: &mut wgpu::RenderPass<'rpass>,
) {
self.quad_pipeline.render(transform_uniform, render_pass);
}
}
12 changes: 12 additions & 0 deletions neothesia-core/src/render/quad/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ impl<'a> QuadPipeline {
render_pass.draw_indexed(0..self.quad.indices_len, 0, 0..self.instances.len());
}

pub fn clear(&mut self) {
self.instances.data.clear();
}

pub fn instances(&mut self) -> &mut Vec<QuadInstance> {
&mut self.instances.data
}

pub fn prepare(&self, queue: &wgpu::Queue) {
self.instances.update(queue);
}

pub fn update_instance_buffer(&mut self, queue: &wgpu::Queue, instances: Vec<QuadInstance>) {
self.instances.data = instances;
self.instances.update(queue);
Expand Down
26 changes: 6 additions & 20 deletions neothesia/src/scene/playing_scene/keyboard.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use midi_file::midly::MidiMessage;
use neothesia_core::render::TextRenderer;
use neothesia_core::render::{QuadPipeline, TextRenderer};
use piano_math::KeyboardRange;
use wgpu_jumpstart::{TransformUniform, Uniform};

use crate::{config::Config, render::KeyboardRenderer, target::Target};

Expand All @@ -25,12 +24,7 @@ impl Keyboard {
target.window_state.logical_size.height,
);

let mut renderer = KeyboardRenderer::new(
&target.gpu,
&target.transform,
layout,
target.config.vertical_guidelines,
);
let mut renderer = KeyboardRenderer::new(layout, target.config.vertical_guidelines);
renderer.position_on_bottom_of_parent(target.window_state.logical_size.height);

Self { renderer }
Expand Down Expand Up @@ -62,22 +56,14 @@ impl Keyboard {
self.position_on_bottom_of_parent(target.window_state.logical_size.height);
}

pub fn update(&mut self, queue: &wgpu::Queue, brush: &mut TextRenderer) {
self.renderer.update(queue, brush)
pub fn update(&mut self, quads: &mut QuadPipeline, brush: &mut TextRenderer) {
self.renderer.update(quads, brush)
}

pub fn reset_notes(&mut self) {
self.renderer.reset_notes()
}

pub fn render<'rpass>(
&'rpass mut self,
transform_uniform: &'rpass Uniform<TransformUniform>,
render_pass: &mut wgpu::RenderPass<'rpass>,
) {
self.renderer.render(transform_uniform, render_pass)
}

pub fn user_midi_event(&mut self, message: &MidiMessage) {
let range_start = self.range().start() as usize;

Expand All @@ -92,7 +78,7 @@ impl Keyboard {
let key = &mut self.renderer.key_states_mut()[id];

key.set_pressed_by_user(is_on);
self.renderer.queue_reupload();
self.renderer.invalidate_cache();
}
}

Expand All @@ -117,7 +103,7 @@ impl Keyboard {
key.pressed_by_file_off();
}

self.renderer.queue_reupload();
self.renderer.invalidate_cache();
}
}
}
Expand Down
Loading

0 comments on commit da0570f

Please sign in to comment.