Skip to content

Commit

Permalink
Support multiple layers in quad pipeline (#178)
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex authored Jun 6, 2024
1 parent 9899528 commit df3f093
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 108 deletions.
26 changes: 13 additions & 13 deletions neothesia-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct Recorder {

playback: midi_file::PlaybackState,

bg_quad_pipeline: QuadPipeline,
quad_pipeline: QuadPipeline,
keyboard: KeyboardRenderer,
waterfall: WaterfallRenderer,
Expand Down Expand Up @@ -76,8 +75,9 @@ impl Recorder {
wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
);

let bg_quad_pipeline = QuadPipeline::new(&gpu, &transform_uniform);
let quad_pipeline = QuadPipeline::new(&gpu, &transform_uniform);
let mut quad_pipeline = QuadPipeline::new(&gpu, &transform_uniform);
quad_pipeline.init_layer(&gpu, 30); // BG
quad_pipeline.init_layer(&gpu, 150); // FG

let keyboard_layout = get_layout(
width as f32,
Expand Down Expand Up @@ -117,7 +117,6 @@ impl Recorder {

playback,

bg_quad_pipeline,
quad_pipeline,
keyboard,
waterfall,
Expand All @@ -136,20 +135,21 @@ impl Recorder {

let time = time_without_lead_in(&self.playback);

self.bg_quad_pipeline.clear();
self.quad_pipeline.clear();

self.guidelines.update(
&mut self.bg_quad_pipeline,
&mut self.quad_pipeline,
0,
self.config.animation_speed,
time,
);
self.bg_quad_pipeline.prepare(&self.gpu.queue);

self.waterfall.update(&self.gpu.queue, time);

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

self.text.update((self.width, self.height), &self.gpu);
}
Expand Down Expand Up @@ -183,11 +183,11 @@ impl Recorder {
occlusion_query_set: None,
});

self.bg_quad_pipeline
.render(&self.transform_uniform, &mut rpass);
self.quad_pipeline
.render(0, &self.transform_uniform, &mut rpass);
self.waterfall.render(&self.transform_uniform, &mut rpass);
self.quad_pipeline
.render(&self.transform_uniform, &mut rpass);
.render(1, &self.transform_uniform, &mut rpass);
self.text.render(&mut rpass);
}

Expand Down
15 changes: 11 additions & 4 deletions neothesia-core/src/render/guidelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl GuidelineRenderer {
fn update_horizontal_guidelines(
&mut self,
quads: &mut QuadPipeline,
layer: usize,
animation_speed: f32,
time: f32,
) {
Expand All @@ -98,7 +99,7 @@ impl GuidelineRenderer {
break;
}

quads.instances().push(QuadInstance {
quads.instances(layer).push(QuadInstance {
position: [x, y],
size: [w, h],
color: [0.05, 0.05, 0.05, 1.0],
Expand All @@ -107,17 +108,23 @@ impl GuidelineRenderer {
}
}

pub fn update(&mut self, quads: &mut QuadPipeline, animation_speed: f32, time: f32) {
pub fn update(
&mut self,
quads: &mut QuadPipeline,
layer: usize,
animation_speed: f32,
time: f32,
) {
if self.cache.is_empty() {
self.reupload();
}

if self.horizontal_guidelines {
self.update_horizontal_guidelines(quads, animation_speed, time);
self.update_horizontal_guidelines(quads, layer, animation_speed, time);
}

for quad in self.cache.iter() {
quads.instances().push(*quad);
quads.instances(layer).push(*quad);
}
}
}
4 changes: 2 additions & 2 deletions neothesia-core/src/render/keyboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ impl KeyboardRenderer {
}
}

pub fn update(&mut self, quads: &mut QuadPipeline, text: &mut TextRenderer) {
pub fn update(&mut self, quads: &mut QuadPipeline, layer: usize, text: &mut TextRenderer) {
if self.cache.is_empty() {
self.reupload();
}

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

let range_start = self.layout.range.start() as usize;
Expand Down
53 changes: 36 additions & 17 deletions neothesia-core/src/render/quad/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use wgpu_jumpstart::{wgpu, Gpu, Instances, Shape, TransformUniform, Uniform};
pub struct QuadPipeline {
render_pipeline: wgpu::RenderPipeline,
quad: Shape,
instances: Instances<QuadInstance>,
instances: Vec<Instances<QuadInstance>>,
}

impl<'a> QuadPipeline {
Expand Down Expand Up @@ -44,58 +44,77 @@ impl<'a> QuadPipeline {
});

let quad = Shape::new_quad(&gpu.device);
let instances = Instances::new(&gpu.device, 100_000);

Self {
render_pipeline,
quad,
instances,
instances: Vec::new(),
}
}

pub fn init_layer(&mut self, gpu: &Gpu, size: usize) {
self.instances.push(Instances::new(&gpu.device, size));
}

pub fn render(
&'a self,
batch_id: usize,
transform_uniform: &'a Uniform<TransformUniform>,
render_pass: &mut wgpu::RenderPass<'a>,
) {
let instances = &self.instances[batch_id];
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &transform_uniform.bind_group, &[]);

render_pass.set_vertex_buffer(0, self.quad.vertex_buffer.slice(..));
render_pass.set_vertex_buffer(1, self.instances.buffer.slice(..));
render_pass.set_vertex_buffer(1, instances.buffer.slice(..));

render_pass.set_index_buffer(self.quad.index_buffer.slice(..), wgpu::IndexFormat::Uint16);

render_pass.draw_indexed(0..self.quad.indices_len, 0, 0..self.instances.len());
render_pass.draw_indexed(0..self.quad.indices_len, 0, 0..instances.len());
}

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

pub fn instances(&mut self) -> &mut Vec<QuadInstance> {
&mut self.instances.data
pub fn instances(&mut self, batch_id: usize) -> &mut Vec<QuadInstance> {
&mut self.instances[batch_id].data
}

pub fn push(&mut self, quad: QuadInstance) {
self.instances.data.push(quad)
pub fn push(&mut self, batch_id: usize, quad: QuadInstance) {
self.instances[batch_id].data.push(quad)
}

pub fn prepare(&self, queue: &wgpu::Queue) {
self.instances.update(queue);
pub fn prepare(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) {
for instances in self.instances.iter_mut() {
instances.update(device, queue);
}
}

pub fn update_instance_buffer(&mut self, queue: &wgpu::Queue, instances: Vec<QuadInstance>) {
self.instances.data = instances;
self.instances.update(queue);
pub fn update_instance_buffer(
&mut self,
batch_id: usize,
device: &wgpu::Device,
queue: &wgpu::Queue,
instances: Vec<QuadInstance>,
) {
let batch = &mut self.instances[batch_id];
batch.data = instances;
batch.update(device, queue);
}

pub fn with_instances_mut<F: FnOnce(&mut Vec<QuadInstance>)>(
&mut self,
batch_id: usize,
device: &wgpu::Device,
queue: &wgpu::Queue,
cb: F,
) {
cb(&mut self.instances.data);
self.instances.update(queue);
let batch = &mut self.instances[batch_id];
cb(&mut batch.data);
batch.update(device, queue);
}
}
5 changes: 3 additions & 2 deletions neothesia-core/src/render/waterfall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl WaterfallRenderer {
notes
.notes_pipeline
.set_speed(&gpu.queue, config.animation_speed);
notes.resize(&gpu.queue, config, layout);
notes.resize(&gpu.device, &gpu.queue, config, layout);
notes
}

Expand All @@ -49,6 +49,7 @@ impl WaterfallRenderer {

pub fn resize(
&mut self,
device: &wgpu::Device,
queue: &wgpu::Queue,
config: &Config,
layout: piano_math::KeyboardLayout,
Expand Down Expand Up @@ -96,7 +97,7 @@ impl WaterfallRenderer {
);
}

self.notes_pipeline.prepare(queue);
self.notes_pipeline.prepare(device, queue);
}

pub fn update(&mut self, queue: &wgpu::Queue, time: f32) {
Expand Down
4 changes: 2 additions & 2 deletions neothesia-core/src/render/waterfall/pipeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ impl<'a> WaterfallPipeline {
&mut self.instances.data
}

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

pub fn speed(&self) -> f32 {
Expand Down
6 changes: 4 additions & 2 deletions neothesia/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,10 @@ impl ApplicationHandler<NeothesiaEvent> for NeothesiaBootstrap {
}

fn main() {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("neothesia=info"))
.init();
env_logger::Builder::from_env(
env_logger::Env::default().default_filter_or("warn, wgpu_hal=error, oxisynth=error"),
)
.init();

let event_loop: EventLoop<NeothesiaEvent> = EventLoop::with_user_event().build().unwrap();
let proxy = event_loop.create_proxy();
Expand Down
4 changes: 2 additions & 2 deletions neothesia/src/scene/playing_scene/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ impl Keyboard {
self.position_on_bottom_of_parent(ctx.window_state.logical_size.height);
}

pub fn update(&mut self, quads: &mut QuadPipeline, brush: &mut TextRenderer) {
self.renderer.update(quads, brush)
pub fn update(&mut self, quads: &mut QuadPipeline, layer: usize, brush: &mut TextRenderer) {
self.renderer.update(quads, layer, brush)
}

pub fn reset_notes(&mut self) {
Expand Down
41 changes: 26 additions & 15 deletions neothesia/src/scene/playing_scene/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ mod top_bar;
const EVENT_CAPTURED: bool = true;
const EVENT_IGNORED: bool = false;

const LAYER_BG: usize = 0;
const LAYER_FG: usize = 1;

pub struct PlayingScene {
keyboard: Keyboard,
waterfall: WaterfallRenderer,
guidelines: GuidelineRenderer,

player: MidiPlayer,
rewind_controller: RewindController,
bg_quad_pipeline: QuadPipeline,
fg_quad_pipeline: QuadPipeline,
quad_pipeline: QuadPipeline,
toast_manager: ToastManager,

top_bar: TopBar,
Expand Down Expand Up @@ -82,15 +84,18 @@ impl PlayingScene {
);
waterfall.update(&ctx.gpu.queue, player.time_without_lead_in());

let mut quad_pipeline = QuadPipeline::new(&ctx.gpu, &ctx.transform);
quad_pipeline.init_layer(&ctx.gpu, 50); // BG
quad_pipeline.init_layer(&ctx.gpu, 150); // FG

Self {
keyboard,
guidelines,

waterfall,
player,
rewind_controller: RewindController::new(),
bg_quad_pipeline: QuadPipeline::new(&ctx.gpu, &ctx.transform),
fg_quad_pipeline: QuadPipeline::new(&ctx.gpu, &ctx.transform),
quad_pipeline,
toast_manager: ToastManager::default(),
top_bar: TopBar::new(),
}
Expand All @@ -117,30 +122,36 @@ impl PlayingScene {
self.guidelines.set_layout(self.keyboard.layout().clone());
self.guidelines.set_pos(*self.keyboard.pos());

self.waterfall
.resize(&ctx.gpu.queue, &ctx.config, self.keyboard.layout().clone());
self.waterfall.resize(
&ctx.gpu.device,
&ctx.gpu.queue,
&ctx.config,
self.keyboard.layout().clone(),
);
}
}

impl Scene for PlayingScene {
fn update(&mut self, ctx: &mut Context, delta: Duration) {
self.bg_quad_pipeline.clear();
self.fg_quad_pipeline.clear();
self.quad_pipeline.clear();

self.rewind_controller.update(&mut self.player, ctx);
self.toast_manager.update(&mut ctx.text_renderer);

let time = self.update_midi_player(ctx, delta);
self.waterfall.update(&ctx.gpu.queue, time);
self.guidelines
.update(&mut self.bg_quad_pipeline, ctx.config.animation_speed, time);
self.guidelines.update(
&mut self.quad_pipeline,
LAYER_BG,
ctx.config.animation_speed,
time,
);
self.keyboard
.update(&mut self.fg_quad_pipeline, &mut ctx.text_renderer);
.update(&mut self.quad_pipeline, LAYER_FG, &mut ctx.text_renderer);

TopBar::update(self, &ctx.window_state, &mut ctx.text_renderer);

self.bg_quad_pipeline.prepare(&ctx.gpu.queue);
self.fg_quad_pipeline.prepare(&ctx.gpu.queue);
self.quad_pipeline.prepare(&ctx.gpu.device, &ctx.gpu.queue);

if self.player.is_finished() {
ctx.proxy.send_event(NeothesiaEvent::MainMenu).ok();
Expand All @@ -152,9 +163,9 @@ impl Scene for PlayingScene {
transform: &'pass Uniform<TransformUniform>,
rpass: &mut wgpu::RenderPass<'pass>,
) {
self.bg_quad_pipeline.render(transform, rpass);
self.quad_pipeline.render(LAYER_BG, transform, rpass);
self.waterfall.render(transform, rpass);
self.fg_quad_pipeline.render(transform, rpass);
self.quad_pipeline.render(LAYER_FG, transform, rpass);
}

fn window_event(&mut self, ctx: &mut Context, event: &WindowEvent) {
Expand Down
Loading

0 comments on commit df3f093

Please sign in to comment.