draw with wgpu

This commit is contained in:
Chance 2024-12-01 22:58:52 -05:00 committed by BitSyndicate
parent ef45558272
commit 7ceaa5e177
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 443E4198D6BBA6DE
4 changed files with 129 additions and 16 deletions

View file

@ -8,7 +8,7 @@ use winit::event_loop::{ControlFlow, EventLoop};
pub fn init_render() -> Result<()> { pub fn init_renderer() -> Result<()> {
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(ControlFlow::Poll); event_loop.set_control_flow(ControlFlow::Poll);
let mut app = App::default(); let mut app = App::default();

View file

@ -0,0 +1,100 @@
use std::sync::Arc;
use anyhow::Result;
use tokio::task::spawn_blocking;
use winit::window::Window;
pub struct WgpuCtx<'window> {
device: wgpu::Device,
queue: wgpu::Queue,
surface: wgpu::Surface<'window>,
surface_config: wgpu::SurfaceConfiguration,
adapter: wgpu::Adapter,
}
impl<'window> WgpuCtx<'window> {
pub async fn new(window: Arc<Window>) -> Result<WgpuCtx<'window>> {
let instnace = wgpu::Instance::default();
let surface = instnace.create_surface(Arc::clone(&window))?;
let adapter = instnace
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
force_fallback_adapter: false,
compatible_surface: Some(&surface),
})
.await
.expect("Failed to obtain render adapter");
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: None,
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::downlevel_webgl2_defaults()
.using_resolution(adapter.limits()),
memory_hints: wgpu::MemoryHints::Performance,
},
None,
)
.await
.expect("Failed to create rendering device");
let size = window.inner_size();
let width = size.width.max(1);
let height = size.height.max(1);
let surface_config = surface.get_default_config(&adapter, width, height).unwrap();
surface.configure(&device, &surface_config);
Ok(WgpuCtx {
device: device,
queue: queue,
surface: surface,
surface_config: surface_config,
adapter: adapter,
})
}
pub fn new_blocking(window: Arc<Window>) -> Result<WgpuCtx<'window>> {
tokio::task::block_in_place(|| {
tokio::runtime::Runtime::new()
.unwrap()
.block_on(async { WgpuCtx::new(window).await })
})
}
pub fn resize(&mut self, new_size: (u32, u32)) {
let (width, height) = new_size;
self.surface_config.width = width.max(1);
self.surface_config.height = height.max(1);
self.surface.configure(&self.device, &self.surface_config);
}
pub fn draw(&mut self) {
let surface_texture = self
.surface
.get_current_texture()
.expect("Failed to get surface texture");
let view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
{
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
}
self.queue.submit(Some(encoder.finish()));
surface_texture.present();
}
}

View file

@ -1,22 +1,28 @@
use log2::{debug, error}; use std::sync::Arc;
use ctx::WgpuCtx;
use log2::{debug, error, trace};
use winit::application::ApplicationHandler; use winit::application::ApplicationHandler;
use winit::event::WindowEvent; use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop; use winit::event_loop::ActiveEventLoop;
use winit::window::{Window, WindowId}; use winit::window::{self, Window, WindowId};
pub mod ctx;
#[derive(Default)] #[derive(Default)]
pub struct App { pub struct App<'window> {
window: Option<Window>, window: Option<Arc<Window>>,
ctx: Option<WgpuCtx<'window>>,
} }
impl ApplicationHandler for App { impl ApplicationHandler for App<'_> {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn resumed(&mut self, event_loop: &ActiveEventLoop) {
if self.window.is_none() { if self.window.is_none() {
let win_attr = Window::default_attributes().with_title("Zenyx"); let win_attr = Window::default_attributes().with_title("Zenyx");
let window = event_loop let window = Arc::new(event_loop
.create_window(win_attr) .create_window(win_attr)
.expect("create window err."); .expect("create window err."));
self.window = Some(window); self.window = Some(window.clone());
let wgpu_ctx = WgpuCtx::new_blocking(window.clone()).unwrap();
self.ctx = Some(wgpu_ctx)
} }
} }
@ -32,12 +38,21 @@ impl ApplicationHandler for App {
debug!("Window closed, exiting"); debug!("Window closed, exiting");
std::process::exit(0) std::process::exit(0)
} }
WindowEvent::RedrawRequested => {
if let Some(ctx) = &mut self.ctx {
ctx.draw();
}
}
WindowEvent::Resized(size) => { WindowEvent::Resized(size) => {
if let (Some(wgpu_ctx),Some(window)) = (&mut self.ctx, &self.window) {
wgpu_ctx.resize(size.into());
window.request_redraw();
let size_str: String = size.height.to_string() + "x" + &size.width.to_string(); let size_str: String = size.height.to_string() + "x" + &size.width.to_string();
//self.window.as_ref().unwrap().set_title(&format!("you reszed the window to {size_str}")); //self.window.as_ref().unwrap().set_title(&format!("you reszed the window to {size_str}"));
debug!("Window resized to {:?}", size_str); debug!("Window resized to {:?}", size_str);
} }
_ => error!("Unhandled window event"), }
_ => trace!("Unhandled window event"),
} }
} }
} }

View file

@ -1,4 +1,3 @@
use anyhow::Result; use anyhow::Result;
use log2::info; use log2::info;
@ -6,17 +5,16 @@ pub mod core;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let _log2 = log2::open("z.log").tee(true).level("trace").start(); let _log2 = log2::open("z.log").tee(true).level("debug").start();
info!("Initalizing Engine"); info!("Initalizing Engine");
let shell_thread = tokio::task::spawn(async { let shell_thread = tokio::task::spawn(async {
info!("Shell thread started"); info!("Shell thread started");
core::repl::handle_repl().await; core::repl::handle_repl().await;
} });
);
core::splash::print_splash(); core::splash::print_splash();
info!("Engine Initalized"); info!("Engine Initalized");
core::init_render()?; core::init_renderer()?;
shell_thread.await?; shell_thread.await?;
Ok(()) Ok(())
} }