From c73c1a7f43e3093b883fd3a24a0a78c619d82c56 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 16 Mar 2024 22:58:38 -0400 Subject: [PATCH] render: fix segfault in LightCullCompute --- examples/testbed/testbed-renderdoc.cap | 4 +- lyra-game/src/game.rs | 1 + lyra-game/src/render/light/mod.rs | 12 ++-- lyra-game/src/render/light_cull_compute.rs | 56 +++++-------------- lyra-game/src/render/material.rs | 8 +-- lyra-game/src/render/render_buffer.rs | 16 +++--- lyra-game/src/render/renderer.rs | 19 ++++--- .../src/render/shaders/light_cull.comp.wgsl | 5 +- lyra-game/src/render/texture.rs | 10 ++-- 9 files changed, 51 insertions(+), 80 deletions(-) diff --git a/examples/testbed/testbed-renderdoc.cap b/examples/testbed/testbed-renderdoc.cap index 7b81a15..cd8a585 100644 --- a/examples/testbed/testbed-renderdoc.cap +++ b/examples/testbed/testbed-renderdoc.cap @@ -5,7 +5,7 @@ "commandLine": "", "environment": [ ], - "executable": "/media/data_drive/Development/Rust/lyra-test/engine/target/debug/testbed", + "executable": "/media/data_drive/Development/Rust/lyra-engine/target/debug/testbed", "inject": false, "numQueuedFrames": 1, "options": { @@ -23,6 +23,6 @@ "verifyBufferAccess": false }, "queuedFrameCap": 5, - "workingDir": "/media/data_drive/Development/Rust/lyra-test/engine/examples/testbed" + "workingDir": "/media/data_drive/Development/Rust/lyra-engine/examples/testbed" } } diff --git a/lyra-game/src/game.rs b/lyra-game/src/game.rs index fe9f9d9..32f7cbd 100755 --- a/lyra-game/src/game.rs +++ b/lyra-game/src/game.rs @@ -350,6 +350,7 @@ impl Game { // done by prefix, so it includes all lyra subpackages .with_target("lyra", Level::DEBUG) .with_target("wgpu", Level::WARN) + .with_target("winit", Level::DEBUG) .with_default(Level::INFO)) .init(); diff --git a/lyra-game/src/render/light/mod.rs b/lyra-game/src/render/light/mod.rs index 9cdc09b..1f5cfc9 100644 --- a/lyra-game/src/render/light/mod.rs +++ b/lyra-game/src/render/light/mod.rs @@ -6,14 +6,14 @@ use lyra_ecs::{Entity, Tick, World, query::{Entities, TickOf}}; pub use point::*; pub use spotlight::*; -use std::{collections::{VecDeque, HashMap}, marker::PhantomData}; - -use std::mem; +use std::{collections::{HashMap, VecDeque}, marker::PhantomData}; use crate::math::Transform; use self::directional::DirectionalLight; +use super::render_buffer::BindGroupPair; + const MAX_LIGHT_COUNT: usize = 16; /// A struct that stores a list of lights in a wgpu::Buffer. @@ -101,8 +101,7 @@ impl LightBuffer { pub(crate) struct LightUniformBuffers { pub buffer: wgpu::Buffer, - pub bindgroup_layout: wgpu::BindGroupLayout, - pub bindgroup: wgpu::BindGroup, + pub bind_group_pair: BindGroupPair, pub light_indexes: HashMap, pub current_light_idx: u32, } @@ -159,8 +158,7 @@ impl LightUniformBuffers { Self { buffer, - bindgroup_layout, - bindgroup, + bind_group_pair: BindGroupPair::new(bindgroup, bindgroup_layout), light_indexes: Default::default(), current_light_idx: 0, } diff --git a/lyra-game/src/render/light_cull_compute.rs b/lyra-game/src/render/light_cull_compute.rs index 4cca981..c928751 100644 --- a/lyra-game/src/render/light_cull_compute.rs +++ b/lyra-game/src/render/light_cull_compute.rs @@ -1,44 +1,28 @@ -use std::{borrow::Cow, mem, ptr::NonNull, rc::Rc}; +use std::{borrow::Cow, mem, rc::Rc}; use glam::UVec2; use wgpu::{util::DeviceExt, ComputePipeline}; use winit::dpi::PhysicalSize; -use super::{light::LightUniformBuffers, render_buffer::BufferWrapper, texture::RenderTexture}; +use super::{light::LightUniformBuffers, render_buffer::{BindGroupPair, BufferWrapper}, texture::RenderTexture}; struct LightIndicesGridBuffer { indices_buffer: wgpu::Buffer, grid_texture: wgpu::Texture, grid_texture_view: wgpu::TextureView, - bind_group_layout: wgpu::BindGroupLayout, - bind_group: wgpu::BindGroup, + bg_pair: BindGroupPair, } pub(crate) struct LightCullCompute { device: Rc, queue: Rc, pipeline: ComputePipeline, - lights: NonNull, - camera: NonNull, light_indices_grid: LightIndicesGridBuffer, screen_size_buffer: BufferWrapper, - depth_tex: NonNull, } impl LightCullCompute { fn create_grid(device: &wgpu::Device, screen_size: PhysicalSize) -> LightIndicesGridBuffer { - let limits = device.limits(); - //let max_buffer_sizes = (limits.max_uniform_buffer_binding_size as u64) / 2; - - /* let light_indices_buffer = device.create_buffer( - &wgpu::BufferDescriptor { - label: Some("B_LightIndices"), - usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST, - size: (mem::size_of::() * 16 * 16) as u64, - mapped_at_creation: false, - } - ); */ - let light_indices_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("B_LightIndices"), contents: &[0; mem::size_of::() * 16 * 16], @@ -128,12 +112,11 @@ impl LightCullCompute { indices_buffer: light_indices_buffer, grid_texture, grid_texture_view, - bind_group_layout: light_indices_bg_layout, - bind_group: light_indices_bg, + bg_pair: BindGroupPair::new(light_indices_bg, light_indices_bg_layout), } } - pub fn new(device: Rc, queue: Rc, screen_size: PhysicalSize, lights: &LightUniformBuffers, camera_buffers: &BufferWrapper, depth_texture: &mut RenderTexture) -> Self { + pub fn new(device: Rc, queue: Rc, screen_size: PhysicalSize, lights_buffers: &LightUniformBuffers, camera_buffers: &BufferWrapper, depth_texture: &mut RenderTexture) -> Self { let screen_size_buffer = BufferWrapper::builder() .buffer_usage(wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST) .label_prefix("ScreenSize") @@ -150,16 +133,16 @@ impl LightCullCompute { let light_grid = Self::create_grid(&device, screen_size); + let depth_tex_pair = depth_texture.create_bind_group(&device); let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("PipeLay_LightCull"), bind_group_layouts: &[ - //&depth_texture.bindgroup_pair.as_ref().unwrap().layout, &depth_tex_pair.layout, - camera_buffers.bindgroup_layout().unwrap(), - &lights.bindgroup_layout, - &light_grid.bind_group_layout, + &camera_buffers.bindgroup_layout().unwrap(), + &lights_buffers.bind_group_pair.layout, + &light_grid.bg_pair.layout, screen_size_buffer.bindgroup_layout().unwrap(), ], push_constant_ranges: &[], @@ -176,11 +159,8 @@ impl LightCullCompute { device, queue, pipeline, - lights: NonNull::from(lights), - camera: NonNull::from(camera_buffers), light_indices_grid: light_grid, screen_size_buffer, - depth_tex: NonNull::from(depth_texture), } } @@ -189,9 +169,7 @@ impl LightCullCompute { &[UVec2::new(size.width, size.height)]); } - pub fn compute(&mut self) { - //self.queue.write_buffer(&self.light_indices_grid.indices_buffer, 0, &[0; mem::size_of::() * 16 * 16]); - + pub fn compute(&mut self, camera_buffers: &BufferWrapper, lights_buffers: &LightUniformBuffers, depth_texture: &RenderTexture) { let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("LightCullCompute"), }); @@ -202,17 +180,11 @@ impl LightCullCompute { }); pass.set_pipeline(&self.pipeline); - - let depth = unsafe { self.depth_tex.as_ref() }; - pass.set_bind_group(0, depth.bind_group(), &[]); - let cam = unsafe { self.camera.as_ref() }; - pass.set_bind_group(1, cam.bindgroup(), &[]); - - let lights = unsafe { self.lights.as_ref() }; - pass.set_bind_group(2, &lights.bindgroup, &[]); - - pass.set_bind_group(3, &self.light_indices_grid.bind_group, &[]); + pass.set_bind_group(0, depth_texture.bind_group(), &[]); + pass.set_bind_group(1, &camera_buffers.bindgroup(), &[]); + pass.set_bind_group(2, &lights_buffers.bind_group_pair.bindgroup, &[]); + pass.set_bind_group(3, &self.light_indices_grid.bg_pair.bindgroup, &[]); pass.set_bind_group(4, self.screen_size_buffer.bindgroup(), &[]); pass.dispatch_workgroups(16, 16, 1); diff --git a/lyra-game/src/render/material.rs b/lyra-game/src/render/material.rs index aa452d2..b505ffc 100755 --- a/lyra-game/src/render/material.rs +++ b/lyra-game/src/render/material.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::rc::Rc; use lyra_resource::{ResHandle, Texture}; @@ -11,7 +11,7 @@ pub struct MaterialSpecular { pub color_texture: Option, } -fn texture_to_render(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: &Arc, i: &Option>) -> Option { +fn texture_to_render(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: &Rc, i: &Option>) -> Option { if let Some(tex) = i { RenderTexture::from_resource(device, queue, bg_layout.clone(), tex, None).ok() } else { @@ -20,7 +20,7 @@ fn texture_to_render(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: &Arc } impl MaterialSpecular { - pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc, value: &lyra_resource::gltf::Specular) -> Self { + pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Rc, value: &lyra_resource::gltf::Specular) -> Self { let tex = texture_to_render(device, queue, &bg_layout, &value.texture); let color_tex = texture_to_render(device, queue, &bg_layout, &value.color_texture); @@ -45,7 +45,7 @@ pub struct Material { } impl Material { - pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc, value: &lyra_resource::gltf::Material) -> Self { + pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Rc, value: &lyra_resource::gltf::Material) -> Self { let diffuse_texture = texture_to_render(device, queue, &bg_layout, &value.base_color_texture); let specular = value.specular.as_ref().map(|s| MaterialSpecular::from_resource(device, queue, bg_layout.clone(), s)); diff --git a/lyra-game/src/render/render_buffer.rs b/lyra-game/src/render/render_buffer.rs index df174e0..794e09e 100755 --- a/lyra-game/src/render/render_buffer.rs +++ b/lyra-game/src/render/render_buffer.rs @@ -1,4 +1,4 @@ -use std::{num::NonZeroU32, ops::Deref, sync::Arc}; +use std::{num::NonZeroU32, rc::Rc}; use wgpu::util::DeviceExt; @@ -23,13 +23,13 @@ impl RenderBuffer { pub struct BindGroupPair { pub bindgroup: wgpu::BindGroup, - pub layout: Arc, + pub layout: Rc, } impl BindGroupPair { - pub fn new_from_layout(device: &wgpu::Device, layout: Arc, entries: &[wgpu::BindGroupEntry<'_>]) -> Self { + pub fn create_bind_group(device: &wgpu::Device, layout: Rc, entries: &[wgpu::BindGroupEntry<'_>]) -> Self { let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: layout.as_ref(), + layout: &layout, entries, label: None, }); @@ -43,7 +43,7 @@ impl BindGroupPair { pub fn new(bindgroup: wgpu::BindGroup, layout: wgpu::BindGroupLayout) -> Self { Self { bindgroup, - layout: Arc::new(layout), + layout: Rc::new(layout), } } } @@ -92,7 +92,7 @@ impl BufferWrapper { /// /// Returns None if this buffer object was not provided a bindgroup. pub fn bindgroup_layout(&self) -> Option<&wgpu::BindGroupLayout> { - self.bindgroup_pair.as_ref().map(|bg| bg.layout.deref()) + self.bindgroup_pair.as_ref().map(|bg| &*bg.layout) } /// Queue's the data to be written to `buffer` starting at `offset`. @@ -272,7 +272,7 @@ impl BufferWrapperBuilder { ], label: self.format_label("BGL_").as_deref(), }); - let bg_layout = Arc::new(bg_layout); + //let bg_layout = Arc::new(bg_layout); let bg = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -288,7 +288,7 @@ impl BufferWrapperBuilder { BindGroupPair { bindgroup: bg, - layout: bg_layout, + layout: Rc::new(bg_layout), } } }; diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index 74db284..67172f3 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -1,5 +1,4 @@ use std::collections::{HashMap, VecDeque, HashSet}; -use std::ops::Deref; use std::rc::Rc; use std::sync::Arc; use std::borrow::Cow; @@ -11,7 +10,6 @@ use lyra_ecs::query::filter::{Has, Or}; use lyra_ecs::{Entity, Tick}; use lyra_ecs::query::{Entities, TickOf}; use lyra_ecs::World; -use lyra_reflect::resource; use lyra_resource::gltf::GltfScene; use tracing::{debug, warn}; use uuid::Uuid; @@ -22,7 +20,6 @@ use winit::window::Window; use crate::math::Transform; use crate::render::material::MaterialUniform; use crate::render::render_buffer::BufferWrapperBuilder; -use crate::resources; use crate::scene::CameraComponent; use super::camera::{RenderCamera, CameraUniform}; @@ -103,7 +100,7 @@ pub struct BasicRenderer { camera_buffer: BufferWrapper, //camera_bind_group: wgpu::BindGroup, - bgl_texture: Arc, + bgl_texture: Rc, default_texture: RenderTexture, depth_buffer_texture: RenderTexture, @@ -176,7 +173,7 @@ impl BasicRenderer { }; surface.configure(&device, &config); - let bgl_texture = Arc::new(RenderTexture::create_layout(&device)); + let bgl_texture = Rc::new(RenderTexture::create_layout(&device)); let shader_src = include_str!("shaders/base.wgsl"); let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { @@ -252,7 +249,7 @@ impl BasicRenderer { vec![super::vertex::Vertex::desc(),], vec![&s.bgl_texture, &s.transform_buffers.bindgroup_layout, s.camera_buffer.bindgroup_layout().unwrap(), - &s.light_buffers.bindgroup_layout, &s.material_buffer.bindgroup_pair.as_ref().unwrap().layout, + &s.light_buffers.bind_group_pair.layout, &s.material_buffer.bindgroup_pair.as_ref().unwrap().layout, &s.bgl_texture]))); s.render_pipelines = pipelines; @@ -520,7 +517,7 @@ impl Renderer for BasicRenderer { let output = self.surface.get_current_texture()?; let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default()); - //self.light_cull_compute.compute(); + self.light_cull_compute.compute(&self.camera_buffer, &self.light_buffers, &self.depth_buffer_texture); let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Basic Renderer's Encoder") @@ -582,7 +579,7 @@ impl Renderer for BasicRenderer { render_pass.set_bind_group(1, bindgroup, &[ offset, offset, ]); render_pass.set_bind_group(2, &self.camera_buffer.bindgroup(), &[]); - render_pass.set_bind_group(3, &self.light_buffers.bindgroup, &[]); + render_pass.set_bind_group(3, &self.light_buffers.bind_group_pair.bindgroup, &[]); render_pass.set_bind_group(4, &self.material_buffer.bindgroup_pair.as_ref().unwrap().bindgroup, &[]); // if this mesh uses indices, use them to draw the mesh @@ -616,7 +613,13 @@ impl Renderer for BasicRenderer { // tell other things of updated resize self.surface.configure(&self.device, &self.config); + + let create_bindgroup = self.depth_buffer_texture.bindgroup_pair.is_some(); self.depth_buffer_texture = RenderTexture::create_depth_texture(&self.device, &self.config, "Depth Buffer Texture"); + if create_bindgroup { + self.depth_buffer_texture.create_bind_group(&self.device); + } + self.inuse_camera.update_aspect_ratio(self.size); self.light_cull_compute.update_screen_size(new_size); } diff --git a/lyra-game/src/render/shaders/light_cull.comp.wgsl b/lyra-game/src/render/shaders/light_cull.comp.wgsl index 54df3c5..d5dc8d5 100644 --- a/lyra-game/src/render/shaders/light_cull.comp.wgsl +++ b/lyra-game/src/render/shaders/light_cull.comp.wgsl @@ -62,11 +62,8 @@ var u_lights: Lights; @group(3) @binding(0) var u_light_indices: array; -/*@group(3) @binding(1) -var u_light_grid: array>>;*/ - @group(3) @binding(1) -var t_light_grid: texture_storage_2d; // rg32uint = vec2 or vec4(r, g, 0.0, 1.0) +var t_light_grid: texture_storage_2d; @group(4) @binding(0) var u_screen_size: vec2; diff --git a/lyra-game/src/render/texture.rs b/lyra-game/src/render/texture.rs index 154ad11..64e2b59 100755 --- a/lyra-game/src/render/texture.rs +++ b/lyra-game/src/render/texture.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::rc::Rc; use image::GenericImageView; use lyra_resource::{FilterMode, ResHandle, Texture, WrappingMode}; @@ -44,7 +44,7 @@ impl RenderTexture { }) } - fn create_bind_group_pair(device: &wgpu::Device, layout: Arc, view: &wgpu::TextureView, sampler: &wgpu::Sampler) -> BindGroupPair { + fn create_bind_group_pair(device: &wgpu::Device, layout: Rc, view: &wgpu::TextureView, sampler: &wgpu::Sampler) -> BindGroupPair { let bg = device.create_bind_group( &wgpu::BindGroupDescriptor { layout: &layout, @@ -68,12 +68,12 @@ impl RenderTexture { } } - pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc, bytes: &[u8], label: &str) -> anyhow::Result { + pub fn from_bytes(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Rc, bytes: &[u8], label: &str) -> anyhow::Result { let img = image::load_from_memory(bytes)?; Self::from_image(device, queue, bg_layout, &img, Some(label)) } - pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc, img: &image::DynamicImage, label: Option<&str>) -> anyhow::Result { + pub fn from_image(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Rc, img: &image::DynamicImage, label: Option<&str>) -> anyhow::Result { let rgba = img.to_rgba8(); let dimensions = img.dimensions(); @@ -134,7 +134,7 @@ impl RenderTexture { }) } - pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Arc, texture_res: &ResHandle, label: Option<&str>) -> anyhow::Result { + pub fn from_resource(device: &wgpu::Device, queue: &wgpu::Queue, bg_layout: Rc, texture_res: &ResHandle, label: Option<&str>) -> anyhow::Result { let texture_ref = texture_res.data_ref().unwrap(); let img = texture_ref.image.data_ref().unwrap();