Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple layers in quad pipeline #178

Merged
merged 1 commit into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading