Skip to content

Commit

Permalink
perf(tilemap): ⚡ Use push constants instead of uniforms
Browse files Browse the repository at this point in the history
  • Loading branch information
melody-rs committed Sep 15, 2023
1 parent 4c25ee0 commit bdf0801
Show file tree
Hide file tree
Showing 20 changed files with 172 additions and 346 deletions.
34 changes: 12 additions & 22 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ egui-notify = { version = "0.9" } # temporary patch
egui_dock = { version = "0.6" }
catppuccin-egui = "3.0.0"

cgmath = "0.18" # FIXME: switch to glam
glam = { version = "0.24", features = ["bytemuck"] }

image = { version = "0.24", features = ["jpeg", "png"] }

Expand Down Expand Up @@ -67,7 +67,7 @@ notify = "6.0"
rfd = "0.12"
camino = "1.1"

bytemuck = "1"
bytemuck = { version = "1.14", features = ["derive", "min_const_generics"] }

color-eyre = "0.6"
eyre = "0.6"
Expand Down Expand Up @@ -146,7 +146,7 @@ opt-level = 3
[profile.dev.package.image]
opt-level = 3

[profile.dev.package.cgmath]
[profile.dev.package.glam]
opt-level = 3

# See why config is set up this way.
Expand Down
4 changes: 2 additions & 2 deletions src/cache/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ macro_rules! nested_ref_getter {
);*) => {
$(
#[allow(unsafe_code, dead_code)]
pub fn $name<'a>(&'a self) -> impl core::ops::Deref<Target = $typ> + core::ops::DerefMut + 'a {
pub fn $name<'a>(&'a self) -> impl core::ops::DerefMut<Target = $typ> + 'a {
struct _Ref<'b> {
_this_ref: atomic_refcell::AtomicRef<'b, State>,
_other_ref: atomic_refcell::AtomicRefMut<'b, $typ>,
Expand Down Expand Up @@ -407,7 +407,7 @@ impl Cache {
/// Load a map.
#[allow(unsafe_code)]
#[allow(clippy::panic)]
pub fn map<'a>(&'a self, id: usize) -> impl Deref<Target = rpg::Map> + DerefMut + 'a {
pub fn map<'a>(&'a self, id: usize) -> impl DerefMut<Target = rpg::Map> + 'a {
struct Ref<'b> {
_state: atomic_refcell::AtomicRef<'b, State>,
map_ref: dashmap::mapref::one::RefMut<'b, usize, rpg::Map>,
Expand Down
5 changes: 2 additions & 3 deletions src/components/tilepicker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Tilepicker {
tilepicker_data,
);

let viewport = primitives::Viewport::new(cgmath::ortho(
let viewport = primitives::Viewport::new(glam::Mat4::orthographic_rh(
0.0,
256.,
atlas.tileset_height as f32,
Expand Down Expand Up @@ -117,8 +117,7 @@ impl Tilepicker {
tiles, viewport, ..
} = resources.as_ref();

viewport.bind(render_pass);
tiles.draw(render_pass, None);
tiles.draw(viewport, &[true], render_pass);
}),
),
});
Expand Down
11 changes: 6 additions & 5 deletions src/graphics/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ impl Event {

let (quads, viewport, sprite_size) = if let Some(id) = page.graphic.tile_id {
// Why does this have to be + 1?
let quad = atlas.calc_quad((id + 1) as i16, event.x as usize, event.y as usize);
let quad = atlas.calc_quad((id + 1) as i16);

let viewport = primitives::Viewport::new(cgmath::ortho(0.0, 32., 32., 0., -1., 1.));
let viewport =
primitives::Viewport::new(glam::Mat4::orthographic_rh(0.0, 32., 32., 0., -1., 1.));

(quad, viewport, egui::vec2(32., 32.))
} else {
Expand All @@ -75,7 +76,8 @@ impl Event {
);
let quad = primitives::Quad::new(pos, tex_coords, 0.0);

let viewport = primitives::Viewport::new(cgmath::ortho(0.0, cw, ch, 0., -1., 1.));
let viewport =
primitives::Viewport::new(glam::Mat4::orthographic_rh(0.0, cw, ch, 0., -1., 1.));

(quad, viewport, egui::vec2(cw, ch))
};
Expand Down Expand Up @@ -115,8 +117,7 @@ impl Event {
let resources = &res_hash[id];
let Resources { viewport, sprite } = resources.as_ref();

viewport.bind(render_pass);
sprite.draw(render_pass);
sprite.draw(viewport, render_pass);
});
painter.add(egui::PaintCallback {
callback: Arc::new(callback),
Expand Down
10 changes: 4 additions & 6 deletions src/graphics/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl Map {
} else {
None
};
let viewport = primitives::Viewport::new(cgmath::ortho(
let viewport = primitives::Viewport::new(glam::Mat4::orthographic_rh(
0.0,
map.width as f32 * 32.,
map.height as f32 * 32.,
Expand Down Expand Up @@ -145,18 +145,16 @@ impl Map {
..
} = resources.as_ref();

viewport.bind(render_pass);

if pano_enabled {
if let Some(panorama) = panorama {
panorama.draw(render_pass);
panorama.draw(viewport, render_pass);
}
}

tiles.draw(render_pass, Some(&enabled_layers));
tiles.draw(viewport, &enabled_layers, render_pass);
if fog_enabled {
if let Some(fog) = fog {
fog.draw(render_pass);
fog.draw(viewport, render_pass);
}
}
});
Expand Down
8 changes: 6 additions & 2 deletions src/graphics/plane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ impl Plane {
Self { sprite }
}

pub fn draw<'rpass>(&'rpass self, render_pass: &mut wgpu::RenderPass<'rpass>) {
self.sprite.draw(render_pass);
pub fn draw<'rpass>(
&'rpass self,
viewport: &primitives::Viewport,
render_pass: &mut wgpu::RenderPass<'rpass>,
) {
self.sprite.draw(viewport, render_pass);
}
}
16 changes: 8 additions & 8 deletions src/graphics/primitives/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,32 @@ impl Quad {
let position = pos.left_top();
let tex_coords = tex_coords.left_top();
Vertex {
position: [position.x, position.y, z],
tex_coords: [tex_coords.x, tex_coords.y],
position: glam::vec3(position.x, position.y, z),
tex_coords: glam::vec2(tex_coords.x, tex_coords.y),
}
};
let top_right = {
let position = pos.right_top();
let tex_coords = tex_coords.right_top();
Vertex {
position: [position.x, position.y, z],
tex_coords: [tex_coords.x, tex_coords.y],
position: glam::vec3(position.x, position.y, z),
tex_coords: glam::vec2(tex_coords.x, tex_coords.y),
}
};
let bottom_right = {
let position = pos.right_bottom();
let tex_coords = tex_coords.right_bottom();
Vertex {
position: [position.x, position.y, z],
tex_coords: [tex_coords.x, tex_coords.y],
position: glam::vec3(position.x, position.y, z),
tex_coords: glam::vec2(tex_coords.x, tex_coords.y),
}
};
let bottom_left = {
let position = pos.left_bottom();
let tex_coords = tex_coords.left_bottom();
Vertex {
position: [position.x, position.y, z],
tex_coords: [tex_coords.x, tex_coords.y],
position: glam::vec3(position.x, position.y, z),
tex_coords: glam::vec2(tex_coords.x, tex_coords.y),
}
};
[top_left, top_right, bottom_right, bottom_left]
Expand Down
71 changes: 6 additions & 65 deletions src/graphics/primitives/sprite/graphic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
//
// You should have received a copy of the GNU General Public License
// along with Luminol. If not, see <http://www.gnu.org/licenses/>.
use crate::prelude::*;

use crossbeam::atomic::AtomicCell;
use wgpu::util::DeviceExt;

#[derive(Debug)]
pub struct Graphic {
data: AtomicCell<Data>,
buffer: wgpu::Buffer,
bind_group: wgpu::BindGroup,
}

#[repr(C)]
Expand All @@ -37,29 +34,8 @@ impl Graphic {
let hue = (hue % 360) as f32 / 360.0;
let opacity = opacity as f32 / 255.;
let data = Data { hue, opacity };
let render_state = &state!().render_state;

let buffer = render_state
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("tilemap sprite graphic buffer"),
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let bind_group = render_state
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("tilemap sprite graphic bind group"),
layout: &LAYOUT,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: buffer.as_entire_binding(),
}],
});

Self {
bind_group,
buffer,
data: AtomicCell::new(data),
}
}
Expand All @@ -71,10 +47,8 @@ impl Graphic {
pub fn set_hue(&self, hue: i32) {
let hue = (hue % 360) as f32 / 360.0;
let data = self.data.load();
if data.hue != hue {
self.data.store(Data { hue, ..data });
self.regen_buffer();
}

self.data.store(Data { hue, ..data });
}

pub fn opacity(&self) -> i32 {
Expand All @@ -84,44 +58,11 @@ impl Graphic {
pub fn set_opacity(&self, opacity: i32) {
let opacity = opacity as f32 / 255.0;
let data = self.data.load();
if data.opacity != opacity {
self.data.store(Data { opacity, ..data });
self.regen_buffer();
}
}

fn regen_buffer(&self) {
let render_state = &state!().render_state;
render_state
.queue
.write_buffer(&self.buffer, 0, bytemuck::cast_slice(&[self.data.load()]));
}

pub fn bind<'rpass>(&'rpass self, render_pass: &mut wgpu::RenderPass<'rpass>) {
render_pass.set_bind_group(2, &self.bind_group, &[]);
self.data.store(Data { opacity, ..data });
}

pub fn layout() -> &'static wgpu::BindGroupLayout {
&LAYOUT
pub fn as_bytes(&self) -> [u8; std::mem::size_of::<Data>()] {
bytemuck::cast(self.data.load())
}
}

static LAYOUT: Lazy<wgpu::BindGroupLayout> = Lazy::new(|| {
let render_state = &state!().render_state;

render_state
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
label: Some("tilemap sprite graphic bind group layout"),
})
});
10 changes: 8 additions & 2 deletions src/graphics/primitives/sprite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,16 @@ impl Sprite {
);
}

pub fn draw<'rpass>(&'rpass self, render_pass: &mut wgpu::RenderPass<'rpass>) {
pub fn draw<'rpass>(
&'rpass self,
viewport: &primitives::Viewport,
render_pass: &mut wgpu::RenderPass<'rpass>,
) {
shader::Shader::bind(self.blend_mode, render_pass);
render_pass.set_push_constants(wgpu::ShaderStages::VERTEX, 0, &viewport.as_bytes());
render_pass.set_push_constants(wgpu::ShaderStages::FRAGMENT, 64, &self.graphic.as_bytes());

self.texture.bind(render_pass);
self.graphic.bind(render_pass);
self.vertices.draw(render_pass);
}
}
Loading

0 comments on commit bdf0801

Please sign in to comment.