diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-26 15:10:37 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-26 15:10:37 +0100 |
commit | 66930534a0647e2613360658a6a99eed945e2f0f (patch) | |
tree | 31a769910ef924a11206f1024b4004f74b1e396f | |
parent | 0163f8486ceca8bd6897c1074f6846f36827d040 (diff) | |
download | weareserver-66930534a0647e2613360658a6a99eed945e2f0f.tar weareserver-66930534a0647e2613360658a6a99eed945e2f0f.tar.bz2 weareserver-66930534a0647e2613360658a6a99eed945e2f0f.tar.zst |
move files around, graphics config, msaa
17 files changed, 175 insertions, 79 deletions
diff --git a/client/src/interfaces/mod.rs b/client/src/interfaces/mod.rs index d7e8c7e..5fb9e6e 100644 --- a/client/src/interfaces/mod.rs +++ b/client/src/interfaces/mod.rs @@ -18,7 +18,9 @@ pub mod prefabindex; pub mod profiler; use crate::{ - download::Downloader, network::Network, render::scene::ScenePreparer, ui::UI_POSITION_OFFSET, + download::Downloader, + network::Network, + render::{scene::ScenePreparer, ui::UI_POSITION_OFFSET}, }; use egui::{Pos2, Widget}; use prefabindex::PrefabIndexInterface; diff --git a/client/src/main.rs b/client/src/main.rs index 4d696b7..e5141c7 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -22,9 +22,7 @@ pub mod download; pub mod interfaces; pub mod network; pub mod render; -pub mod shaders; pub mod state; -pub mod ui; pub mod window; use anyhow::Result; diff --git a/client/src/render/mod.rs b/client/src/render/mod.rs index 6964337..db961f4 100644 --- a/client/src/render/mod.rs +++ b/client/src/render/mod.rs @@ -15,10 +15,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ pub mod scene; +pub mod shaders; +pub mod ui; use crate::{ camera::Camera, download::Downloader, interfaces::profiler::TimingProfiler, state::InputState, - ui::UiRenderer, }; use anyhow::{Result, anyhow}; use log::{info, warn}; @@ -30,6 +31,7 @@ use std::{ thread::{sleep, spawn}, time::Duration, }; +use ui::UiRenderer; use weareshared::tree::SceneTree; use wgpu::{ AdapterInfo, Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Extent3d, Features, @@ -52,7 +54,18 @@ pub struct Renderer<'a> { pub timing: TimingProfiler, pub timing_submit: Arc<Mutex<TimingProfiler>>, pub adapter_info: Arc<AdapterInfo>, + + color_msaa: TextureView, + config: GraphicsConfig, +} + +#[derive(Debug, Clone)] +pub struct GraphicsConfig { + max_anisotropy: u16, + max_mip_count: u32, + sample_count: u32, } + impl<'a> Renderer<'a> { pub fn new(window: &'a Window, downloader: Arc<Downloader>) -> Result<Self> { info!("wgpu init"); @@ -95,31 +108,60 @@ impl<'a> Renderer<'a> { let device = Arc::new(device); let queue = Arc::new(queue); + let config = GraphicsConfig { + max_anisotropy: 16, + max_mip_count: 16, + sample_count: 4, + }; + + let depth = device + .create_texture(&TextureDescriptor { + label: None, + size: Extent3d { + height: 256, + width: 256, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: config.sample_count, + dimension: TextureDimension::D2, + format: TextureFormat::Depth32Float, + usage: TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }) + .create_view(&TextureViewDescriptor::default()); + + let color_msaa = device + .create_texture(&TextureDescriptor { + label: None, + size: Extent3d { + height: 256, + width: 256, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: config.sample_count, + dimension: TextureDimension::D2, + format: surface_configuration.format, + usage: TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }) + .create_view(&TextureViewDescriptor::default()); + let scene_prepare = Arc::new(ScenePreparer::new( device.clone(), queue.clone(), surface_configuration.format, downloader, + config.clone(), )); - let ui_renderer = - UiRenderer::new(device.clone(), queue.clone(), surface_configuration.format); - - let depth = device.create_texture(&TextureDescriptor { - label: None, - size: Extent3d { - height: 256, - width: 256, - depth_or_array_layers: 1, - }, - mip_level_count: 1, - sample_count: 1, - dimension: TextureDimension::D2, - format: TextureFormat::Depth32Float, - usage: TextureUsages::RENDER_ATTACHMENT, - view_formats: &[], - }); - let depth = depth.create_view(&TextureViewDescriptor::default()); + let ui_renderer = UiRenderer::new( + device.clone(), + queue.clone(), + surface_configuration.format, + config.clone(), + ); // TODO multithreading introduces double-loading some resources. fix that before increasing thread count for _ in 0..1 { @@ -146,9 +188,11 @@ impl<'a> Renderer<'a> { queue, surface_configuration, ui_renderer, + config, surface_needs_reconfigure: false, timing: Default::default(), timing_submit: Default::default(), + color_msaa, }) } @@ -158,23 +202,38 @@ impl<'a> Renderer<'a> { self.surface .configure(&self.device, &self.surface_configuration); + let size = Extent3d { + height, + width, + depth_or_array_layers: 1, + }; self.depth = self .device .create_texture(&TextureDescriptor { label: None, - size: Extent3d { - height, - width, - depth_or_array_layers: 1, - }, + size, mip_level_count: 1, - sample_count: 1, + sample_count: self.config.sample_count, dimension: TextureDimension::D2, format: TextureFormat::Depth32Float, usage: TextureUsages::RENDER_ATTACHMENT, view_formats: &[], }) .create_view(&TextureViewDescriptor::default()); + + self.color_msaa = self + .device + .create_texture(&TextureDescriptor { + label: None, + size, + mip_level_count: 1, + sample_count: self.config.sample_count, + dimension: TextureDimension::D2, + format: self.surface_configuration.format, + usage: TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], + }) + .create_view(&TextureViewDescriptor::default()); } pub fn draw( @@ -189,12 +248,12 @@ impl<'a> Renderer<'a> { .configure(&self.device, &self.surface_configuration); self.surface_needs_reconfigure = false } - let target = self.surface.get_current_texture()?; - if target.suboptimal { + let surface = self.surface.get_current_texture()?; + if surface.suboptimal { warn!("suboptimal swapchain texture"); self.surface_needs_reconfigure = true; } - let target_view = target + let target_view = surface .texture .create_view(&TextureViewDescriptor::default()); @@ -205,10 +264,17 @@ impl<'a> Renderer<'a> { let view = camera.view_matrix(); let project = camera.project_matrix(); + let (target, resolve_target) = if self.config.sample_count == 1 { + (&target_view, None) + } else { + (&self.color_msaa, Some(&target_view)) + }; + self.timing.checkpoint("draw scene"); self.scene_pipeline.draw( &mut commands, - &target_view, + target, + resolve_target, &self.depth, scene, &self.scene_prepare.prefabs, @@ -219,7 +285,8 @@ impl<'a> Renderer<'a> { self.timing.checkpoint("draw ui"); self.ui_renderer.draw( &mut commands, - &target_view, + target, + resolve_target, &self.depth, project * view, input_state, @@ -232,10 +299,9 @@ impl<'a> Renderer<'a> { self.device.poll(MaintainBase::WaitForSubmissionIndex(i)); self.timing.checkpoint("present"); - target.present(); + surface.present(); self.timing.checkpoint(""); - let mut ts = self.timing_submit.lock().unwrap(); swap(&mut *ts, &mut self.timing); diff --git a/client/src/render/scene/draw.rs b/client/src/render/scene/draw.rs index d133d3b..1109401 100644 --- a/client/src/render/scene/draw.rs +++ b/client/src/render/scene/draw.rs @@ -14,7 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ -use super::{demand_map::DemandMap, RPrefab}; +use super::{RPrefab, demand_map::DemandMap}; use glam::{EulerRot, Mat3, Mat4}; use std::sync::Arc; use weareshared::{packets::Resource, resources::Prefab, tree::SceneTree}; @@ -30,6 +30,7 @@ impl ScenePipeline { &mut self, commands: &mut CommandEncoder, target: &TextureView, + resolve_target: Option<&TextureView>, depth: &TextureView, scene: &SceneTree, prefabs: &DemandMap<Resource<Prefab>, Arc<RPrefab>>, @@ -40,7 +41,7 @@ impl ScenePipeline { label: None, color_attachments: &[Some(RenderPassColorAttachment { view: target, - resolve_target: None, + resolve_target, ops: Operations { store: StoreOp::Store, load: LoadOp::Clear(Color { diff --git a/client/src/render/scene/mod.rs b/client/src/render/scene/mod.rs index 7471fc8..ad7e0ce 100644 --- a/client/src/render/scene/mod.rs +++ b/client/src/render/scene/mod.rs @@ -21,7 +21,8 @@ pub mod pipelines; pub mod textures; pub mod vertex_buffers; -use crate::{armature::RArmature, download::Downloader, shaders::SceneShaders}; +use super::{shaders::SceneShaders, GraphicsConfig}; +use crate::{armature::RArmature, download::Downloader}; use anyhow::Result; use bytemuck::{Pod, Zeroable}; use demand_map::DemandMap; @@ -42,11 +43,6 @@ use wgpu::{ util::{BufferInitDescriptor, DeviceExt}, }; -struct GraphicsConfig { - max_anisotropy: u16, - max_mip_count: u32, -} - pub struct ScenePreparer { device: Arc<Device>, queue: Arc<Queue>, @@ -143,13 +139,11 @@ impl ScenePreparer { queue: Arc<Queue>, render_format: TextureFormat, downloader: Arc<Downloader>, + config: GraphicsConfig, ) -> Self { Self { render_format, - config: GraphicsConfig { - max_anisotropy: 16, - max_mip_count: 16, - }, + config, layouts: SceneBgLayouts::load(&device), shaders: SceneShaders::load(&device), device, @@ -210,7 +204,7 @@ impl ScenePreparer { for spec in self.pipelines.needed() { self.pipelines.insert( spec.clone(), - Arc::new(spec.create(&self.device, &self.layouts, &self.shaders)), + Arc::new(spec.create(&self.device, &self.layouts, &self.shaders, &self.config)), 0, ); } diff --git a/client/src/render/scene/pipelines.rs b/client/src/render/scene/pipelines.rs index dfc5d19..53064c9 100644 --- a/client/src/render/scene/pipelines.rs +++ b/client/src/render/scene/pipelines.rs @@ -14,6 +14,8 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ +use super::{GraphicsConfig, PipelineSpec}; +use crate::render::shaders::SceneShaders; use wgpu::{ BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState, BufferBindingType, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, @@ -25,10 +27,6 @@ use wgpu::{ VertexStepMode, }; -use crate::shaders::SceneShaders; - -use super::PipelineSpec; - pub struct SceneBgLayouts { pub texture: BindGroupLayout, pub material: BindGroupLayout, @@ -95,6 +93,7 @@ impl PipelineSpec { device: &Device, layouts: &SceneBgLayouts, shaders: &SceneShaders, + config: &GraphicsConfig, ) -> RenderPipeline { let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { label: None, @@ -188,7 +187,10 @@ impl PipelineSpec { bias: DepthBiasState::default(), stencil: StencilState::default(), }), - multisample: MultisampleState::default(), + multisample: MultisampleState { + count: config.sample_count, + ..Default::default() + }, multiview: None, cache: None, }) diff --git a/client/src/render/scene/textures.rs b/client/src/render/scene/textures.rs index 463e8f1..f85f21f 100644 --- a/client/src/render/scene/textures.rs +++ b/client/src/render/scene/textures.rs @@ -32,7 +32,7 @@ pub struct MipGenerationPipeline { } impl MipGenerationPipeline { pub fn load(device: &Device, format: TextureFormat) -> Self { - let shader = device.create_shader_module(include_wgsl!("../../shaders/texture_copy.wgsl")); + let shader = device.create_shader_module(include_wgsl!("../shaders/texture_copy.wgsl")); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("mip generator"), layout: None, diff --git a/client/src/shaders/fragment_pbr.wgsl b/client/src/render/shaders/fragment_pbr.wgsl index c8fb857..c8fb857 100644 --- a/client/src/shaders/fragment_pbr.wgsl +++ b/client/src/render/shaders/fragment_pbr.wgsl diff --git a/client/src/shaders/fragment_ui.wgsl b/client/src/render/shaders/fragment_ui.wgsl index 7cb66ab..7cb66ab 100644 --- a/client/src/shaders/fragment_ui.wgsl +++ b/client/src/render/shaders/fragment_ui.wgsl diff --git a/client/src/render/shaders/mod.rs b/client/src/render/shaders/mod.rs new file mode 100644 index 0000000..7e4e3be --- /dev/null +++ b/client/src/render/shaders/mod.rs @@ -0,0 +1,37 @@ +/* + wearechat - generic multiplayer game with voip + Copyright (C) 2025 metamuffin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ +use log::info; +use wgpu::{Device, ShaderModule, include_wgsl}; + +pub struct SceneShaders { + pub fragment_pbr: ShaderModule, + pub vertex_world: ShaderModule, + pub vertex_world_skin: ShaderModule, +} + +impl SceneShaders { + pub fn load(device: &Device) -> Self { + info!("compiling shaders..."); + let s = Self { + fragment_pbr: device.create_shader_module(include_wgsl!("fragment_pbr.wgsl")), + vertex_world: device.create_shader_module(include_wgsl!("vertex_world.wgsl")), + vertex_world_skin: device.create_shader_module(include_wgsl!("vertex_world_skin.wgsl")), + }; + info!("done"); + s + } +} diff --git a/client/src/shaders/texture_copy.wgsl b/client/src/render/shaders/texture_copy.wgsl index be38a76..be38a76 100644 --- a/client/src/shaders/texture_copy.wgsl +++ b/client/src/render/shaders/texture_copy.wgsl diff --git a/client/src/shaders/vertex_ui.wgsl b/client/src/render/shaders/vertex_ui.wgsl index 7cbac8b..7cbac8b 100644 --- a/client/src/shaders/vertex_ui.wgsl +++ b/client/src/render/shaders/vertex_ui.wgsl diff --git a/client/src/shaders/vertex_world.wgsl b/client/src/render/shaders/vertex_world.wgsl index 4f342fd..4f342fd 100644 --- a/client/src/shaders/vertex_world.wgsl +++ b/client/src/render/shaders/vertex_world.wgsl diff --git a/client/src/shaders/vertex_world_skin.wgsl b/client/src/render/shaders/vertex_world_skin.wgsl index 6e2b308..6e2b308 100644 --- a/client/src/shaders/vertex_world_skin.wgsl +++ b/client/src/render/shaders/vertex_world_skin.wgsl diff --git a/client/src/ui.rs b/client/src/render/ui.rs index fd94dfb..e27b9cb 100644 --- a/client/src/ui.rs +++ b/client/src/render/ui.rs @@ -14,6 +14,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ +use super::GraphicsConfig; use crate::state::InputState; use egui::{ Context, Event, ImageData, PointerButton, TextureId, ViewportId, ViewportInfo, @@ -50,6 +51,7 @@ pub const UI_POSITION_OFFSET: f32 = 1000.; pub struct UiRenderer { device: Arc<Device>, queue: Arc<Queue>, + _config: GraphicsConfig, ctx: Context, pipeline: RenderPipeline, bind_group_layout: BindGroupLayout, @@ -74,7 +76,12 @@ pub enum UiEvent { } impl UiRenderer { - pub fn new(device: Arc<Device>, queue: Arc<Queue>, format: TextureFormat) -> Self { + pub fn new( + device: Arc<Device>, + queue: Arc<Queue>, + format: TextureFormat, + config: GraphicsConfig, + ) -> Self { let frag_shader = device.create_shader_module(include_wgsl!("shaders/fragment_ui.wgsl")); let vert_shader = device.create_shader_module(include_wgsl!("shaders/vertex_ui.wgsl")); @@ -144,7 +151,10 @@ impl UiRenderer { stencil: Default::default(), bias: Default::default(), }), - multisample: MultisampleState::default(), + multisample: MultisampleState { + count: config.sample_count, + ..Default::default() + }, multiview: None, cache: None, }); @@ -154,6 +164,7 @@ impl UiRenderer { device, queue, bind_group_layout, + _config: config, last_pointer: Vec2::ZERO, textures: HashMap::new().into(), surfaces: HashMap::new().into(), @@ -285,6 +296,7 @@ impl UiRenderer { &mut self, commands: &mut CommandEncoder, target: &TextureView, + resolve_target: Option<&TextureView>, depth: &TextureView, projection: Mat4, input_state: &mut InputState, @@ -299,7 +311,7 @@ impl UiRenderer { label: None, color_attachments: &[Some(RenderPassColorAttachment { view: target, - resolve_target: None, + resolve_target, ops: Operations { load: LoadOp::Load, store: StoreOp::Store, diff --git a/client/src/shaders/mod.rs b/client/src/shaders/mod.rs deleted file mode 100644 index 42b2164..0000000 --- a/client/src/shaders/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -use log::info; -use wgpu::{Device, ShaderModule, include_wgsl}; - -pub struct SceneShaders { - pub fragment_pbr: ShaderModule, - pub vertex_world: ShaderModule, - pub vertex_world_skin: ShaderModule, -} - -impl SceneShaders { - pub fn load(device: &Device) -> Self { - info!("compiling shaders..."); - let s = Self { - fragment_pbr: device.create_shader_module(include_wgsl!("fragment_pbr.wgsl")), - vertex_world: device.create_shader_module(include_wgsl!("vertex_world.wgsl")), - vertex_world_skin: device.create_shader_module(include_wgsl!("vertex_world_skin.wgsl")), - }; - info!("done"); - s - } -} diff --git a/client/src/state.rs b/client/src/state.rs index d132e3e..ae29bae 100644 --- a/client/src/state.rs +++ b/client/src/state.rs @@ -15,7 +15,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ use crate::{ - audio::Audio, camera::Camera, download::Downloader, interfaces::{ui_selector, InterfaceData}, network::Network, render::Renderer, ui::UiEvent + audio::Audio, + camera::Camera, + download::Downloader, + interfaces::{ui_selector, InterfaceData}, + network::Network, + render::{ui::UiEvent, Renderer}, }; use anyhow::{Context, Result}; use glam::{Vec2, Vec3}; |