diff --git a/src/render/state.rs b/src/render/state.rs index 94b33d7..c32e4e5 100644 --- a/src/render/state.rs +++ b/src/render/state.rs @@ -1,28 +1,28 @@ +use std::{iter, num::NonZeroU32, ops::Range, rc::Rc}; use std::cell::RefCell; use std::sync::{Arc, Mutex}; use std::thread::current; use std::time::Duration; -use std::{iter, num::NonZeroU32, ops::Range, rc::Rc}; -use bytemuck::__core::mem; use bytemuck::{Pod, Zeroable}; +use bytemuck::__core::mem; use cgmath::{ - vec3, Decomposed, Deg, Euler, InnerSpace, Matrix4, Point3, Quaternion, Rad, Rotation3, - Transform, Vector3, + Decomposed, Deg, Euler, InnerSpace, Matrix4, Point3, Quaternion, Rad, Rotation3, Transform, + vec3, Vector3, }; use futures::executor::LocalPool; -use imgui::sys::ImGuiContext; use imgui::*; +use imgui::sys::ImGuiContext; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; -use legion::world::SubWorld; use legion::*; +use legion::world::SubWorld; use rapier3d::parry::motion::RigidMotionComposition; -use wgpu::util::DeviceExt; use wgpu::{ BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device, Features, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, }; +use wgpu::util::DeviceExt; use winit_24::dpi::PhysicalSize; use winit_24::platform::unix::x11::ffi::Time; use winit_24::window::Window; @@ -33,7 +33,7 @@ use crate::current_ui; use crate::geometry::{load_obj, RawMesh, Vertex}; use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform}; use crate::light::{DirectionalLight, LightRaw}; -use crate::render::{EntityUniforms, ForwardUniforms, ShadowUniforms, CameraProjectionView}; +use crate::render::{CameraProjectionView, EntityUniforms, ForwardUniforms, ShadowUniforms}; /// A render pass consists of a pipeline, bindgroup, and uniform buf /// The uniform buf is just the ShadowUniforms or ForwardUniforms @@ -47,7 +47,6 @@ pub struct Pass { } pub struct RenderState { - swapchain: SwapChain, swapchain_description: SwapChainDescriptor, instance: Arc, @@ -84,12 +83,14 @@ pub struct RenderState { impl RenderState { const MAX_LIGHTS: usize = 10; const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; + const G_BUFFER_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba32Float; + const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; + const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d { width: 1024, height: 1024, depth: Self::MAX_LIGHTS as u32, }; - const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; /// Generate a projection matrix with no look-at yet pub fn generate_matrix(&self) -> cgmath::Matrix4 { @@ -220,6 +221,113 @@ impl RenderState { } } + + // Create a render pass with the ability to add external bindings + pub fn create_render_pass( + device: &Device, + external_binding_layout: &BindGroupLayout, + vertex_description: &wgpu::VertexBufferLayout, + uniform_size: u64, + label: Option<&str>, + ) -> Option { + + + // The g-buffers camera projection matrix that we stream data to + let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { + label: Some(format!("{} uniform-buffer", label.unwrap_or("unnamed")).as_str()), + size: uniform_size, + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + mapped_at_creation: false, + }); + + // Uniform bind group for the view matrix + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + label: Some(format!("{} bind group layout", label.unwrap_or("unnamed")).as_str()), + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, // global + visibility: wgpu::ShaderStage::VERTEX, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + min_binding_size: wgpu::BufferSize::new(uniform_size), + has_dynamic_offset: false, + }, + count: None, + }], + }); + + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some(format!("{} uniform bind group", label.unwrap_or("unnamed")).as_str()), + layout: &bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer { + buffer: &uniform_buf, + offset: 0, + size: wgpu::BufferSize::new(uniform_size), + }, + }, + ], + }); + + let vs_module = + device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.vert.spv")); + let fs_module = + device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.frag.spv")); + + // The bind group layouts are accessed by layout(set = X, binding = x) + // in the shader. + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some(format!("{} pipeline layout", label.unwrap_or("unnamed")).as_str()), + bind_group_layouts: &[&bind_group_layout, external_binding_layout], + push_constant_ranges: &[], + }); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some(format!("{} render pipeline", label.unwrap_or("unnamed")).as_str()), + layout: Some(&pipeline_layout), + + vertex: VertexState { + module: &vs_module, + entry_point: "main", + buffers: &[vertex_description.clone()], + }, + fragment: Some(FragmentState { + module: &fs_module, + entry_point: "main", + targets: &[], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + ..Default::default() + }, + depth_stencil: Some(wgpu::DepthStencilState { + format: wgpu::TextureFormat::Depth32Float, + depth_write_enabled: true, + depth_compare: wgpu::CompareFunction::LessEqual, + stencil: wgpu::StencilState::default(), + bias: wgpu::DepthBiasState { + constant: 2, // corresponds to bilinear filtering + slope_scale: 2.0, + clamp: 0.0, + }, + clamp_depth: device.features().contains( + wgpu::Features::DEPTH_CLAMPING + ), + }), + multisample: wgpu::MultisampleState::default(), + }); + + Some(Pass { + pipeline, + bind_group, + uniform_buf, + }) + } + pub fn init(window: &Window, imgui_context: &mut ImguiContext) -> RenderState { // Grab the GPU instance, and query its features let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); @@ -314,8 +422,23 @@ impl RenderState { // This pass is just going to forward the vertex info to the fragments // And they are going to render to the gbuffer - let g_buffer_pass = { + let g_buffer_pass = Self::create_render_pass( + &device, + &entity_bind_group_layout, + &vb_desc, + mem::size_of::() as wgpu::BufferAddress, + Some("g-buffer"), + ); + + let shadow_pass = Self::create_render_pass( + &device, + &entity_bind_group_layout, + &vb_desc, + mem::size_of::() as wgpu::BufferAddress, + Some("shadow-pass"), + ); + let g_buffer_pass = { let uniform_size = mem::size_of::() as wgpu::BufferAddress; // The g-buffers camera projection matrix that we stream data to @@ -342,6 +465,10 @@ impl RenderState { }], }); + //sudo rm /usr/bin/ld + //sudo ln -s /usr/bin/lld /usr/bin/ld + //sudo ln -s /usr/bin/x86_64-linux-gnu-ld /usr/bin/ld + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("g-buffers uniform bind group"), layout: &bind_group_layout, @@ -355,7 +482,6 @@ impl RenderState { }, }, ], - }); let vs_module = @@ -392,7 +518,7 @@ impl RenderState { ..Default::default() }, depth_stencil: Some(wgpu::DepthStencilState { - format: Self::SHADOW_FORMAT, + format: wgpu::TextureFormat::Depth32Float, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::LessEqual, stencil: wgpu::StencilState::default(), @@ -401,7 +527,9 @@ impl RenderState { slope_scale: 2.0, clamp: 0.0, }, - clamp_depth: device.features().contains(wgpu::Features::DEPTH_CLAMPING), + clamp_depth: device.features().contains( + wgpu::Features::DEPTH_CLAMPING + ), }), multisample: wgpu::MultisampleState::default(), }); @@ -413,6 +541,7 @@ impl RenderState { } }; + let shadow_pass = { let uniform_size = mem::size_of::() as wgpu::BufferAddress; @@ -591,8 +720,7 @@ impl RenderState { ty: wgpu::BufferBindingType::Uniform, min_binding_size: wgpu::BufferSize::new(mem::size_of::< ForwardUniforms, - >( - ) + >() as _), has_dynamic_offset: false, }, @@ -760,20 +888,20 @@ impl RenderState { size: wgpu::Extent3d { width: sc_desc.width, height: sc_desc.height, - depth: 1, + depth: 5, }, mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, format: Self::DEPTH_FORMAT, - usage: wgpu::TextureUsage::RENDER_ATTACHMENT, + usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED, label: Some("g-buffer depth texture"), }); // I need one of these for each of the g-buffer elements I'm calculating let mut g_buffer_depth_texture_views = (0..4) .map(|i| { - Arc::new(shadow_texture.create_view(&wgpu::TextureViewDescriptor { + Arc::new(g_buffer_depth_texture.create_view(&wgpu::TextureViewDescriptor { label: Some("g-buffer depth texture"), format: None, dimension: Some(wgpu::TextureViewDimension::D2), @@ -795,7 +923,6 @@ impl RenderState { ImguiRenderer::new(&mut imgui_context.context, &device, &queue, renderer_config); RenderState { - gbuffer_pass: g_buffer_pass, gbuffer_cam_projection_buffer: g_buffer_camera_projection_uniform, gbuffer_depth: g_buffer_depth_texture.create_view(&wgpu::TextureViewDescriptor::default()),