diff options
Diffstat (limited to 'src/wgpuctx/mod.rs')
| -rw-r--r-- | src/wgpuctx/mod.rs | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/wgpuctx/mod.rs b/src/wgpuctx/mod.rs new file mode 100644 index 0000000..f8aa3ec --- /dev/null +++ b/src/wgpuctx/mod.rs @@ -0,0 +1,245 @@ +use std::sync::Arc; +use std::error::Error; +use wgpu::util::DeviceExt; +use winit::window::{Window}; + +use crate::texture::Texture; + +pub mod pipeline; + +pub struct WgpuCtx +{ + surface: wgpu::Surface<'static>, + surface_conf: wgpu::SurfaceConfiguration, + surface_texture: Option<wgpu::SurfaceTexture>, + is_configured: bool, + + adapter: wgpu::Adapter, + device: wgpu::Device, + queue: wgpu::Queue, +} + +pub struct RenderPassBuilder<'encoder> +{ + label: &'static str, + view: &'encoder wgpu::TextureView, + clear_color: wgpu::Color +} + +impl WgpuCtx +{ + pub async fn new( + instance: &wgpu::Instance, + window: Arc<Window>, + ) -> Self { + let surface = instance.create_surface(window.clone()).unwrap(); + + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + compatible_surface: Some(&surface), + ..Default::default() + }).await.expect("Failed to find valid adapter"); + + let (device, queue) = adapter + .request_device(&wgpu::DeviceDescriptor { + label: None, + required_features: wgpu::Features::empty(), + required_limits: wgpu::Limits::downlevel_defaults(), + experimental_features: wgpu::ExperimentalFeatures::disabled(), + memory_hints: wgpu::MemoryHints::Performance, + trace: wgpu::Trace::Off + }).await.expect("Failed to find device and queue"); + + let size = window.inner_size(); + let surface_config = surface.get_default_config(&adapter, size.width, size.height).unwrap(); + + Self { + surface: surface, + surface_conf: surface_config, + surface_texture: None, + is_configured: false, + adapter: adapter, + device: device, + queue: queue + } + } + + pub fn resize( + &mut self, + width: u32, + height: u32) + { + self.surface_conf.width = width; + self.surface_conf.height = height; + self.surface.configure(&self.device, &self.surface_conf); + self.is_configured = true; + } + + pub fn is_ready( + &self) + -> bool { + self.is_configured + } + + pub fn surface_config( + &self) + -> wgpu::SurfaceConfiguration { + self.surface_conf.clone() + } + + pub fn adapter( + &self) + -> &wgpu::Adapter { + &self.adapter + } + + pub fn device( + &self) + -> &wgpu::Device { + &self.device + } + + pub fn queue( + &self) + -> &wgpu::Queue { + &self.queue + } + + pub fn prepare_surface( + &mut self, + view_descr: &wgpu::TextureViewDescriptor) + -> Result<wgpu::TextureView, wgpu::SurfaceError> + { + let texture = self.surface.get_current_texture()?; + let view = texture.texture.create_view(view_descr); + + self.surface_texture = Some(texture); + Ok(view) + } + + pub fn create_encoder( + &self, + descr: &wgpu::CommandEncoderDescriptor) + -> wgpu::CommandEncoder + { + self.device.create_command_encoder(descr) + } + + pub fn create_default_encoder( + &self, + label: &'static str) + -> wgpu::CommandEncoder { + self.create_encoder( + &wgpu::CommandEncoderDescriptor { + label: Some(label) + } + ) + } + + pub fn submit_encoder( + &self, + encoder: wgpu::CommandEncoder) + { + self.queue.submit(std::iter::once(encoder.finish())); + } + + pub fn present_surface( + &mut self) + { + let texture = self.surface_texture.take(); + match texture { + Some(t) => t.present(), + None => {} + } + } + + pub fn create_shader( + &self, + module_descr: wgpu::ShaderModuleDescriptor) + -> wgpu::ShaderModule { + self.device.create_shader_module(module_descr) + } + + pub fn create_pipeline_layout( + &self, + layout_descr: &wgpu::PipelineLayoutDescriptor) + -> wgpu::PipelineLayout { + self.device.create_pipeline_layout(layout_descr) + } + + pub fn create_render_pipeline( + &self, + pipeline_layout: &wgpu::RenderPipelineDescriptor) + -> wgpu::RenderPipeline { + self.device.create_render_pipeline(pipeline_layout) + } + + pub fn create_buffer_init( + &self, + descr: &wgpu::util::BufferInitDescriptor + ) -> wgpu::Buffer { + self.device.create_buffer_init(descr) + } + + pub fn create_buffer( + &self, + descr: &wgpu::BufferDescriptor) + -> wgpu::Buffer { + self.device.create_buffer(descr) + } + + pub fn new_texture( + &self, + descr: wgpu::TextureDescriptor) + -> Texture + { + Texture::new(&self.device, descr) + } + +} //impl WgpuCtx + +impl<'encoder> RenderPassBuilder<'encoder> +{ + pub fn new( + label: &'static str, + view: &'encoder wgpu::TextureView) + -> Self { + Self { + label: label, + view: view, + clear_color: wgpu::Color { r: 0.0, g: 0.0, b: 0.0, a: 1.0 } + } + } + + pub fn clear_color( + mut self, + color: wgpu::Color) + -> Self { + self.clear_color = color; + self + } + + pub fn build( + self, + encoder: &'encoder mut wgpu::CommandEncoder) + -> wgpu::RenderPass<'encoder> + { + encoder.begin_render_pass( + &wgpu::RenderPassDescriptor { + label: Some(self.label), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: self.view, + resolve_target: None, + depth_slice: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(self.clear_color), + store: wgpu::StoreOp::Store + } + })], + depth_stencil_attachment: None, + occlusion_query_set: None, + timestamp_writes: None, + } + ) + } +} |
