Skip to content

Commit

Permalink
improve api
Browse files Browse the repository at this point in the history
  • Loading branch information
boralg committed Jun 24, 2024
1 parent 1d10614 commit 50db4ae
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 105 deletions.
16 changes: 6 additions & 10 deletions examples/src/hello_triangle/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use sursface::{app::{App, State}, wgpu::{self, Color, CommandEncoder, RenderPass, RenderPipeline, Surface, SurfaceTexture, TextureView}};
use sursface::{app::App, wgpu::{self, Color, CommandEncoder, RenderPass, RenderPipeline, Surface, SurfaceTexture, TextureView}};

#[cfg(not(target_arch = "wasm32"))]
fn main() {
use sursface::winit::dpi::PhysicalSize;
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), init, render);
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render);
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -15,17 +15,14 @@ fn main() {}
pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) {
use sursface::{start, wasm_bindgen};

start::create_window_browser(canvas, init, render);
start::create_window_browser(canvas, &init, &render);
}

struct TriangleState {
render_pipeline: RenderPipeline,
}

impl State for TriangleState {}


fn init(app: &mut App) -> Box<dyn State> {
fn init(app: &mut App<TriangleState>) -> TriangleState {
use std::borrow::Cow;

let display = app.display.as_ref().unwrap();
Expand Down Expand Up @@ -63,10 +60,10 @@ fn init(app: &mut App) -> Box<dyn State> {
multiview: None,
});

Box::new(TriangleState { render_pipeline })
TriangleState { render_pipeline }
}

fn render(app: &mut App, state: &mut Box<dyn State>) {
fn render(app: &mut App<TriangleState>, state: &mut TriangleState) {
let clear_color = Color {
r: 100.0 / 255.0,
g: 149.0 / 255.0,
Expand All @@ -75,7 +72,6 @@ fn render(app: &mut App, state: &mut Box<dyn State>) {
};

let display = app.display.as_ref().unwrap();
let state = unsafe { core::mem::transmute::<&mut Box<dyn State>, &mut Box<TriangleState>>(state) };

let mut encoder = display.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Encoder"),
Expand Down
19 changes: 8 additions & 11 deletions examples/src/hello_window/main.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
use sursface::{app::{App, State}, wgpu};
use sursface::{app::App, wgpu};
#[cfg(target_arch = "wasm32")]
use sursface::wasm_bindgen;

#[cfg(not(target_arch = "wasm32"))]
fn main() {
use sursface::winit::dpi::PhysicalSize;
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), init, render);
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render);
}


#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) {
use sursface::{start, wasm_bindgen};
start::create_window_browser(canvas, init, render);
start::create_window_browser(canvas, &init, &render);
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -22,15 +22,12 @@ fn main() {}

#[derive(Clone)]
struct EmptyState {}
impl State for EmptyState {}



pub fn init<'a>(app: &mut App<'a>) -> Box<dyn State> {
Box::new(EmptyState {})
fn init<'a>(_app: &mut App<EmptyState>) -> EmptyState {
EmptyState {}
}

pub fn render<'a>(app: &mut App<'a>, _state: &mut Box<dyn State>) {
fn render<'a>(app: &mut App<EmptyState>, _state: &mut EmptyState) {
let output = clear_screen(app, wgpu::Color {
r: 100.0 / 255.0,
g: 149.0 / 255.0,
Expand All @@ -41,7 +38,7 @@ pub fn render<'a>(app: &mut App<'a>, _state: &mut Box<dyn State>) {
}


fn clear_screen<'a>(app: &mut App<'a>, color: sursface::wgpu::Color) -> Result<wgpu::SurfaceTexture, wgpu::SurfaceError> {
fn clear_screen<'a>(app: &mut App<EmptyState>, color: sursface::wgpu::Color) -> Result<wgpu::SurfaceTexture, wgpu::SurfaceError> {
let display = app.display.as_ref().unwrap();
let output = display.surface.get_current_texture()?;
let view = output
Expand Down Expand Up @@ -74,7 +71,7 @@ fn clear_screen<'a>(app: &mut App<'a>, color: sursface::wgpu::Color) -> Result<w
Ok(output)
}

fn present<'a>(app: &mut App<'a>, output: sursface::wgpu::SurfaceTexture) -> Result<(), wgpu::SurfaceError> {
fn present<'a>(app: &mut App<EmptyState>, output: sursface::wgpu::SurfaceTexture) -> Result<(), wgpu::SurfaceError> {
output.present();
Ok(())
}
16 changes: 6 additions & 10 deletions examples/src/spinning_cube/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use sursface::{app::App, wgpu};
use wgpu::{util::DeviceExt, Color, CommandEncoder, RenderPipeline, SurfaceTexture, TextureView};
use cgmath::{Deg, Matrix4, Point3, Rad, Vector3, perspective};
use cgmath::SquareMatrix;
use sursface::app::State;
use image::{GenericImageView, ImageFormat};

use crate::cube::Vertex;
Expand All @@ -18,15 +17,15 @@ use sursface::wasm_bindgen;
#[cfg(not(target_arch = "wasm32"))]
fn main() {
use sursface::winit::dpi::PhysicalSize;
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), init, render);
sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render);
}


#[cfg(target_arch = "wasm32")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) {
use sursface::{start, wasm_bindgen};
start::create_window_browser(canvas, init, render);
start::create_window_browser(canvas, &init, &render);
}

#[cfg(target_arch = "wasm32")]
Expand All @@ -43,8 +42,6 @@ struct CubeState {
texture_bind_group: wgpu::BindGroup,
}

impl State for CubeState {}

#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct Uniforms {
Expand Down Expand Up @@ -182,7 +179,7 @@ fn create_uniforms(device: &Device) -> (Buffer, BindGroupLayout, BindGroup) {
(uniform_buffer, uniform_bind_group_layout, uniform_bind_group)
}

fn init(app: &mut App) -> Box<dyn State> {
fn init(app: &mut App<CubeState>) -> CubeState {
use std::borrow::Cow;

let display = app.display.as_ref().unwrap();
Expand Down Expand Up @@ -262,7 +259,7 @@ fn init(app: &mut App) -> Box<dyn State> {
usage: wgpu::BufferUsages::INDEX,
});

Box::new(CubeState {
CubeState {
render_pipeline,
start_time,
uniform_buffer,
Expand All @@ -271,10 +268,10 @@ fn init(app: &mut App) -> Box<dyn State> {
index_buffer,
num_indices: 36,
texture_bind_group,
})
}
}

fn render(app: &mut App, state: &mut Box<dyn State>) {
fn render(app: &mut App<CubeState>, state: &mut CubeState) {
let clear_color = Color {
r: 100.0 / 255.0,
g: 149.0 / 255.0,
Expand All @@ -295,7 +292,6 @@ fn render(app: &mut App, state: &mut Box<dyn State>) {
let mut rpass = clear_screen(&view, &mut encoder, clear_color);

let display = app.display.as_ref().unwrap();
let state = unsafe { core::mem::transmute::<&mut Box<dyn State>, &mut Box<CubeState>>(state) };

let now = Instant::now();
let elapsed = (now - state.start_time).as_secs_f32();
Expand Down
80 changes: 35 additions & 45 deletions sursface/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ extern crate console_error_panic_hook;

use super::display::Display;

pub trait State {}

#[derive(Default)]
pub struct App<'a> {
pub struct App<'a, State> {
pub display: Option<Display<'a>>,
pub initial_size: PhysicalSize<u32>,
#[cfg(target_arch = "wasm32")]
pub canvas: Option<wgpu::web_sys::HtmlCanvasElement>,
pub state: Option<Arc<Mutex<Box<dyn State>>>>,
pub init: Option<Box<dyn Fn(&mut App<'a>) -> Box<dyn State + 'static>>>,
pub render: Option<Box<dyn Fn(&mut App<'a>, &mut Box<dyn State + 'static>)>>,
pub canvas: wgpu::web_sys::HtmlCanvasElement,
pub state: Option<Arc<Mutex<State>>>,
pub init: Arc<dyn Fn(&mut App<State>) -> State>,
pub render: Arc<dyn Fn(&mut App<State>, &mut State)>,
}


Expand Down Expand Up @@ -61,44 +58,44 @@ fn init_logger() {
}
}

impl<'a> App<'a> {
impl<'a, State> App<'a, State> {
#[cfg(not(target_arch = "wasm32"))]
pub fn from_window_size(size: PhysicalSize<u32>) -> Self {
pub fn from_window_size(
size: PhysicalSize<u32>,
init_func: &'static dyn Fn(&mut App<State>) -> State,
render_func: &'static dyn Fn(&mut App<State>, &mut State)) -> Self
{
log::debug!("Setting window size");
App {
initial_size: size,
..Default::default()
display: None,
state: None,
init: Arc::new(init_func),
render: Arc::new(render_func),
}
}

#[cfg(target_arch = "wasm32")]
pub fn from_canvas(canvas: wgpu::web_sys::HtmlCanvasElement) -> Self {
pub fn from_canvas(
canvas: wgpu::web_sys::HtmlCanvasElement,
init_func: &'static dyn Fn(&mut App<State>) -> State,
render_func: &'static dyn Fn(&mut App<State>, &mut State) -> Self) -> Self
{
log::debug!("Setting canvas size");
App {
initial_size: PhysicalSize::new(canvas.width(), canvas.height()),
canvas: Some(canvas),
..Default::default()
display: None,
state: None,
init: init_func,
render: render_func,
}
}

pub fn set_init_function<F>(&mut self, init_func: F)
where
F: Fn(&mut App<'a>) -> Box<dyn State + 'static> + 'static,
{
self.init = Some(Box::new(init_func));
}

pub fn set_render_function<F>(&mut self, render_func: F)
where
F: Fn(&mut App<'a>, &mut Box<dyn State + 'static>) + 'static,
{
self.render = Some(Box::new(render_func));
}
}

impl<'a> ApplicationHandler for App<'a> {
impl<'a, State> ApplicationHandler for App<'a, State> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
init_logger();

#[cfg(not(target_arch = "wasm32"))]
{
self.display = Some(Display::from_window_size(event_loop, self.initial_size));
Expand All @@ -112,12 +109,15 @@ impl<'a> ApplicationHandler for App<'a> {
}
}

if let Some(init) = self.init.take() {
self.state = Some(Arc::new(Mutex::new(init(self))));
self.init = Some(init);
}
}
let new_state = {
let init_fn = Arc::clone(&self.init);
init_fn(self)
};

// Now, set the state with a mutable borrow
self.state = Some(Arc::new(Mutex::new(new_state)));
}

fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
match event {
WindowEvent::CloseRequested
Expand All @@ -139,17 +139,7 @@ impl<'a> ApplicationHandler for App<'a> {
}
}
WindowEvent::RedrawRequested => {
if let Some(render) = self.render.take() {
log::debug!("Locking state");
let state_arc = Arc::clone(self.state.as_ref().unwrap());
let mut state_lock = state_arc.lock().unwrap();
log::debug!("State locked");

log::debug!("rendering");
render(self, &mut *state_lock);

self.render = Some(render);
}
(Arc::clone(&self.render))(self, &mut self.state.clone().unwrap().lock().unwrap());

if let Some(display) = self.display.as_mut() {
display.window.as_ref().request_redraw();
Expand Down
10 changes: 0 additions & 10 deletions sursface/src/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,6 @@ impl<'a> Display<'a> {
}
}

fn window(&self) -> &Window {
&self.window
}

pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
Expand All @@ -125,12 +121,6 @@ impl<'a> Display<'a> {
}
}

fn input(&mut self, event: &WindowEvent) -> bool {
false
}

fn update(&mut self) {}

pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
Ok(())
}
Expand Down
28 changes: 9 additions & 19 deletions sursface/src/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,29 @@ use pollster;
#[cfg(target_arch = "wasm32")]
extern crate console_error_panic_hook;

use crate::app::State;

#[cfg(not(target_arch = "wasm32"))]
pub fn create_window_desktop<'a>(
pub fn create_window_desktop<State: 'static>(
window_size: winit::dpi::PhysicalSize<u32>,
init: fn(&mut App) -> Box<dyn State>,
render: fn(&mut App, &mut Box<dyn State>)
init: &'static (dyn Fn(&mut App<State>) -> State),
render: &'static (dyn Fn(&mut App<State>, &mut State))
) {
use crate::app::App;
let event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(ControlFlow::Poll);
let mut app = App::from_window_size(window_size);

app.set_init_function(init);
app.set_render_function(render);

let mut app = App::from_window_size(window_size, init, render);
event_loop.run_app(&mut app).unwrap();
}


#[cfg(target_arch = "wasm32")]
pub fn create_window_browser<'a>(
pub fn create_window_browser<State: 'static>(
canvas: HtmlCanvasElement,
init: fn(&mut App) -> Box<dyn State + 'static>,
render: fn(&mut App, &mut Box<dyn State + 'static>)
init: &'static (dyn Fn(&mut App<State>) -> State),
render: &'static (dyn Fn(&mut App<State>, &mut State))
) {
use crate::app::App;

let event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(ControlFlow::Poll);
let mut app = App::from_canvas(canvas);

app.set_init_function(init);
app.set_render_function(render);

let mut app = App::from_canvas(canvas, init, render);
event_loop.run_app(&mut app).unwrap();
}

0 comments on commit 50db4ae

Please sign in to comment.