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, is_configured: bool, adapter: wgpu::Adapter, device: wgpu::Device, queue: wgpu::Queue, } pub struct SceneCtx<'view> { view: &'view wgpu::TextureView, encoder: wgpu::CommandEncoder } impl WgpuCtx { pub async fn new( instance: &wgpu::Instance, window: Arc, ) -> 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 { 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: Option<&'static str>) -> wgpu::CommandEncoder { self.create_encoder( &wgpu::CommandEncoderDescriptor { label: 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<'view> SceneCtx<'view> { pub fn from_view_default( wgpuctx: &WgpuCtx, view: &'view wgpu::TextureView, label: Option<&'static str>) -> Self { Self { view: view, encoder: wgpuctx.create_default_encoder(label) } } pub fn view(&self) -> &'view wgpu::TextureView { self.view } pub fn encoder(&self) -> &wgpu::CommandEncoder { &self.encoder } pub fn encoder_mut(&mut self) -> &mut wgpu::CommandEncoder { &mut self.encoder } pub fn submit( self, wgpuctx: &WgpuCtx) { wgpuctx.submit_encoder(self.encoder); } } pub struct RenderPassBuilder<'encoder> { label: Option<&'static str>, view: &'encoder wgpu::TextureView, clear_color: Option } impl<'encoder> RenderPassBuilder<'encoder> { pub fn new( label: Option<&'static str>, view: &'encoder wgpu::TextureView) -> Self { Self { label: label, view: view, clear_color: None } } pub fn clear_color( mut self, color: wgpu::Color) -> Self { self.clear_color = Some(color); self } pub fn build_from_encoder( self, encoder: &'encoder mut wgpu::CommandEncoder) -> wgpu::RenderPass<'encoder> { encoder.begin_render_pass( &wgpu::RenderPassDescriptor { label: self.label, color_attachments: &[Some(wgpu::RenderPassColorAttachment { view: self.view, resolve_target: None, depth_slice: None, ops: wgpu::Operations { load: match self.clear_color { Some(color) => wgpu::LoadOp::Clear(color), None => wgpu::LoadOp::Load }, store: wgpu::StoreOp::Store } })], depth_stencil_attachment: None, occlusion_query_set: None, timestamp_writes: None, } ) } pub fn build_from_scene( self, scene: &'encoder mut SceneCtx) -> wgpu::RenderPass<'encoder> { self.build_from_encoder(scene.encoder_mut()) } }// impl RenderPassBuilder