215 lines
6.7 KiB
Rust
Raw Normal View History

2025-05-05 15:42:37 +02:00
use std::sync::{Arc};
use log::info;
use pollster::FutureExt;
use wgpu::{Adapter, Device, Instance, PresentMode, Queue, Surface, SurfaceCapabilities, SurfaceConfiguration, SurfaceError};
use winit::dpi::PhysicalSize;
2025-05-05 15:42:37 +02:00
use winit::window::{Window};
2025-05-05 20:07:20 +02:00
use crate::camera::Camera;
use crate::geometry_manager::GeometryManager;
use crate::globals::GlobalsManager;
use crate::instance_manager::InstanceManager;
use crate::light::{LightManager};
use crate::renderer::{RenderInstance, Renderer};
pub struct SampleCount(pub u32);
impl SampleCount {
pub fn get(&self) -> u32 {
self.0
}
}
pub struct State<'a> {
surface: Surface<'a>,
device: Device,
queue: Queue,
config: SurfaceConfiguration,
sample_count: SampleCount,
size: PhysicalSize<u32>,
2025-05-05 20:07:20 +02:00
window: Arc<Window>,
pub camera: Camera,
2025-05-06 17:12:22 +02:00
pub globals: GlobalsManager,
pub geometry_manager: GeometryManager,
pub instance_manager: InstanceManager,
2025-05-06 17:12:22 +02:00
pub light_manager: LightManager,
pub renderer: Renderer,
}
impl<'a> State<'a> {
pub(crate) fn new(window: Window) -> Self {
let window = Arc::new(window);
let size = window.inner_size();
let instance = Self::create_gpu_instance();
let surface = instance.create_surface(window.clone()).unwrap();
2025-05-05 20:07:20 +02:00
let adapter = Self::create_adapter(instance, &surface);
let (device, queue) = Self::create_device(&adapter);
2025-05-06 17:12:22 +02:00
let capabilities = surface.get_capabilities(&adapter);
let config = Self::create_surface_config(size, capabilities);
surface.configure(&device, &config);
let sample_count = SampleCount(Self::probe_msaa_support(&device, &config));
info!("MSAA sample count: {}", sample_count.get());
let camera = Camera::new(config.width as f32 / config.height as f32);
let globals = GlobalsManager::new(&device, config.width, config.height, &camera);
let geometry_manager = GeometryManager::new(&device);
let instance_manager = InstanceManager::new(&device);
let mut light_manager = LightManager::new(&device, 100);
let renderer = Renderer::new(
&device,
&config,
globals.layout(),
&mut light_manager,
&camera,
sample_count.get(),
);
Self {
surface,
device,
queue,
config,
sample_count,
size,
window,
2025-05-05 20:07:20 +02:00
camera,
globals,
geometry_manager,
instance_manager,
light_manager,
renderer,
}
}
fn probe_msaa_support(device: &Device, config: &SurfaceConfiguration) -> u32 {
pollster::block_on(async {
for &count in &[16, 8, 4, 2] {
device.push_error_scope(wgpu::ErrorFilter::Validation);
let _ = device.create_texture(&wgpu::TextureDescriptor {
label: Some("MSAA Probe"),
size: wgpu::Extent3d {
width: 4,
height: 4,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: count,
dimension: wgpu::TextureDimension::D2,
format: config.format,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
view_formats: &[],
});
if device.pop_error_scope().await.is_none() {
return count;
}
}
2025-05-10 12:12:00 +02:00
2 // fallback
})
}
fn create_surface_config(size: PhysicalSize<u32>, capabilities: SurfaceCapabilities) -> wgpu::SurfaceConfiguration {
let surface_format = capabilities.formats.iter()
.find(|f| f.is_srgb())
.copied()
.unwrap_or(capabilities.formats[0]);
SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: PresentMode::AutoVsync,
alpha_mode: capabilities.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 2,
}
}
fn create_device(adapter: &Adapter) -> (Device, Queue) {
adapter.request_device(
&wgpu::DeviceDescriptor {
required_features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
required_limits: wgpu::Limits::default(),
memory_hints: Default::default(),
label: None,
trace: Default::default(),
}).block_on().unwrap()
}
fn create_adapter(instance: Instance, surface: &Surface) -> Adapter {
instance.request_adapter(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&surface),
force_fallback_adapter: false,
}
).block_on().unwrap()
}
fn create_gpu_instance() -> Instance {
Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::PRIMARY,
..Default::default()
})
}
pub(crate) fn resize(&mut self, new_size: PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
self.camera.set_aspect(new_size.width as f32 / new_size.height as f32);
self.globals.resize(new_size.width, new_size.height);
self.renderer.resize(&self.device, new_size.width, new_size.height);
}
}
pub fn render(&mut self) -> Result<(), SurfaceError> {
let output = self.surface.get_current_texture()?;
let view = output.texture.create_view(&Default::default());
self.renderer.render_frame(
&self.device,
&self.queue,
output,
&view,
self.config.format,
&mut self.globals,
&self.camera,
&mut self.light_manager,
&self.geometry_manager,
&self.instance_manager,
2025-05-06 17:12:22 +02:00
)
}
pub fn set_instances(&mut self, instances: Vec<RenderInstance>) {
self.instance_manager.set_instances(&self.device, &self.queue, instances);
}
pub fn window(&self) -> &Window {
&self.window
}
2025-05-05 21:29:51 +02:00
pub fn camera_mut(&mut self) -> &mut crate::camera::Camera {
&mut self.camera
}
pub fn camera(&self) -> &crate::camera::Camera {
&self.camera
}
}