Started implementing Wgpu renderer
+ implemented basic setup code + implemented basic resize code ! renderer will default to GLES backend due to NV prime (Wgpu bug)
This commit is contained in:
parent
091454922b
commit
8fb74a0381
1347
Cargo.lock
generated
1347
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -9,4 +9,11 @@ edition = "2021"
|
||||
log = "^0.4.17"
|
||||
chrono = "^0.4.19"
|
||||
fern = { version = "^0.6.1", features = ["colored"] }
|
||||
bitflags = "^1.3.2"
|
||||
cgmath = "^0.18.0"
|
||||
pollster = "^0.2.5"
|
||||
|
||||
winit = "^0.26.1"
|
||||
raw-window-handle = "^0.4.3"
|
||||
|
||||
wgpu = "^0.13.0"
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
sprite::{Sprite, TextureSprite, TextSprite, ShapeSprite},
|
||||
texture::Texture,
|
||||
utils::{Size, Pixel, Position, Color},
|
||||
renderer::Renderer,
|
||||
renderer::WgpuRenderer,
|
||||
};
|
||||
|
||||
use std::{
|
||||
@ -26,15 +26,16 @@ pub trait Application {
|
||||
|
||||
//--Canvas struct-----------------------------------------------------------------------------------
|
||||
pub struct Canvas {
|
||||
renderer: Renderer,
|
||||
renderer: WgpuRenderer,
|
||||
clear_color: Pixel,
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
|
||||
pub fn create<W: HasRawWindowHandle>(window: &W) -> Result<Canvas, &'static str> {
|
||||
|
||||
let renderer = Renderer::create(window)?;
|
||||
pub async fn create<W: HasRawWindowHandle>(window: &W, size: Size)
|
||||
-> Result<Canvas, &'static str>
|
||||
{
|
||||
let renderer = WgpuRenderer::create(window, size).await?;
|
||||
|
||||
Ok(Self {
|
||||
renderer,
|
||||
@ -73,13 +74,17 @@ impl Canvas {
|
||||
//--Output functions--
|
||||
pub fn draw<S: Sprite>(&mut self, sprite: &S) {
|
||||
//update texture
|
||||
self.renderer.draw(sprite);
|
||||
self.renderer.render(sprite);
|
||||
}
|
||||
|
||||
pub fn set_clear_color(&mut self, color: Pixel) {
|
||||
self.clear_color = color;
|
||||
}
|
||||
|
||||
pub fn set_size(&mut self, size: Size) {
|
||||
self.renderer.resize(size);
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.renderer.clear(&self.clear_color);
|
||||
}
|
||||
@ -114,7 +119,7 @@ impl Canvas {
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
self.renderer.finish_frame();
|
||||
self.renderer.present();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
42
src/lib.rs
42
src/lib.rs
@ -1,6 +1,8 @@
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use pollster::FutureExt;
|
||||
|
||||
mod canvas;
|
||||
pub use canvas::Canvas;
|
||||
pub use canvas::Application;
|
||||
@ -29,8 +31,8 @@ pub fn run_canvas<A: 'static + Application>(title: &'static str, size: Size, mut
|
||||
.expect("Failed to create window");
|
||||
|
||||
// construct canvas
|
||||
let mut canvas = Canvas::create(&window)
|
||||
.unwrap();
|
||||
let size = window.inner_size();
|
||||
let mut canvas = Canvas::create(&window, size.into()).block_on().unwrap();
|
||||
|
||||
// init application
|
||||
app.init(&mut canvas).unwrap();
|
||||
@ -46,22 +48,32 @@ pub fn run_canvas<A: 'static + Application>(title: &'static str, size: Size, mut
|
||||
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
let _ = match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
info!("Close requested, shutting down...");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
Ok(())
|
||||
match event {
|
||||
|
||||
Event::WindowEvent {event, ..} => match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
info!("Close requested, shutting down...");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
},
|
||||
WindowEvent::Resized (size) => {
|
||||
canvas.set_size(size.into());
|
||||
},
|
||||
WindowEvent::ScaleFactorChanged {new_inner_size, ..} => {
|
||||
// new_inner_size is &&mut so we have to dereference it twice
|
||||
canvas.set_size((*new_inner_size).into());
|
||||
},
|
||||
_ => (),
|
||||
},
|
||||
|
||||
Event::MainEventsCleared => {
|
||||
let _ = app.tick(&mut canvas);
|
||||
},
|
||||
Event::MainEventsCleared => app.tick(&mut canvas),
|
||||
Event::RedrawRequested(_) => {
|
||||
canvas.update();
|
||||
Ok(())
|
||||
let _ = canvas.update();
|
||||
},
|
||||
_ => Ok(())
|
||||
}.unwrap();
|
||||
|
||||
_ => ()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ fn setup_logger() -> Result<(), fern::InitError> {
|
||||
message
|
||||
))
|
||||
})
|
||||
.level(log::LevelFilter::Trace)
|
||||
.level(log::LevelFilter::Debug)
|
||||
.chain(std::io::stdout())
|
||||
.chain(fern::log_file("output.log")?)
|
||||
.apply()?;
|
||||
|
||||
93
src/renderer.rs
Normal file
93
src/renderer.rs
Normal file
@ -0,0 +1,93 @@
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
use wgpu;
|
||||
|
||||
use crate::{
|
||||
sprite::Sprite,
|
||||
utils::{Pixel, Size},
|
||||
};
|
||||
|
||||
//--Renderer struct---------------------------------------------------------------------------------
|
||||
pub struct WgpuRenderer {
|
||||
surface: wgpu::Surface,
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
config: wgpu::SurfaceConfiguration,
|
||||
size: Size,
|
||||
}
|
||||
|
||||
impl WgpuRenderer {
|
||||
|
||||
pub async fn create<W: HasRawWindowHandle>(window: &W, size: Size)
|
||||
-> Result<Self, &'static str>
|
||||
{
|
||||
if size.w == 0 || size.h == 0 {
|
||||
return Err("window has zero as at least one of its dimensions");
|
||||
}
|
||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
||||
let surface = unsafe { instance.create_surface(window) };
|
||||
|
||||
let adapter = instance.request_adapter(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
//for now, integrated GPU is enough, may be revised later
|
||||
power_preference: wgpu::PowerPreference::LowPower,
|
||||
compatible_surface: Some(&surface),
|
||||
force_fallback_adapter: false,
|
||||
},
|
||||
).await.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
//using minimum requirements possible since 2D isn't very demanding anyway
|
||||
features: wgpu::Features::empty(),
|
||||
limits: wgpu::Limits::downlevel_webgl2_defaults(),
|
||||
label: None,
|
||||
},
|
||||
None, // Trace path
|
||||
).await.unwrap();
|
||||
|
||||
let config = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
//first format in the list is preferred
|
||||
format: *surface.get_supported_formats(&adapter).first()
|
||||
.ok_or_else(|| { "Surface is incompatible with current adapter" })?,
|
||||
width: size.w,
|
||||
height: size.h,
|
||||
present_mode: wgpu::PresentMode::Fifo,
|
||||
};
|
||||
surface.configure(&device, &config);
|
||||
|
||||
Ok(Self {
|
||||
surface,
|
||||
device,
|
||||
queue,
|
||||
config,
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render<S: Sprite>(&mut self, _sprite: &S) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, size: Size) {
|
||||
if size.w == 0 || size.h == 0 {
|
||||
panic!("window has zero as at least one of its dimensions");
|
||||
}
|
||||
self.size = size;
|
||||
self.config.width = size.w;
|
||||
self.config.height = size.h;
|
||||
self.surface.configure(&self.device, &self.config);
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, _color: &Pixel) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn present(&mut self) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
19
src/utils.rs
19
src/utils.rs
@ -10,6 +10,7 @@ pub struct Position {
|
||||
}
|
||||
|
||||
//--Size struct-------------------------------------------------------------------------------------
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Size {
|
||||
pub w: u32,
|
||||
pub h: u32,
|
||||
@ -18,14 +19,24 @@ pub struct Size {
|
||||
impl From<Size> for winit::dpi::Size {
|
||||
|
||||
fn from(size: Size) -> Self {
|
||||
winit::dpi::Size::Logical (
|
||||
winit::dpi::LogicalSize {
|
||||
width: size.w.into(),
|
||||
height: size.h.into()
|
||||
winit::dpi::Size::Physical (
|
||||
winit::dpi::PhysicalSize {
|
||||
width: size.w,
|
||||
height: size.h,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<winit::dpi::PhysicalSize<u32>> for Size {
|
||||
|
||||
fn from(size: winit::dpi::PhysicalSize<u32>) -> Self {
|
||||
Self {
|
||||
w: size.width,
|
||||
h: size.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--Pixel struct------------------------------------------------------------------------------------
|
||||
#[derive(Copy, Clone)]
|
||||
struct Rgba {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user