Skip to main content

scenix_renderer/
config.rs

1use scenix_core::ValidationError;
2
3/// Render target backing used by a renderer instance.
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub enum RenderTargetMode {
7    /// Frames are presented to a platform surface.
8    Surface,
9    /// Frames are rendered to an offscreen texture for tests, tools, or captures.
10    Headless,
11}
12
13/// Renderer initialization and resize configuration.
14#[derive(Clone, Debug, PartialEq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct RendererConfig {
17    /// Render target width in pixels.
18    pub width: u32,
19    /// Render target height in pixels.
20    pub height: u32,
21    /// MSAA sample count. v0.6 supports `1` and `4`.
22    pub sample_count: u32,
23    /// Whether presentation should synchronize to display refresh.
24    pub vsync: bool,
25    /// Whether the renderer should use an HDR intermediate color target.
26    pub hdr: bool,
27    /// Surface present mode.
28    pub present_mode: wgpu::PresentMode,
29    /// Backends requested from wgpu.
30    pub backends: wgpu::Backends,
31    /// Clear color used before drawing.
32    pub clear_color: wgpu::Color,
33}
34
35impl RendererConfig {
36    /// Creates a renderer configuration for the supplied size.
37    #[inline]
38    pub fn new(width: u32, height: u32) -> Self {
39        Self {
40            width,
41            height,
42            ..Self::default()
43        }
44    }
45
46    /// Validates render-target dimensions and MSAA count.
47    pub fn validate(&self) -> Result<(), ValidationError> {
48        if self.width == 0 || self.height == 0 {
49            return Err(ValidationError::OutOfRange);
50        }
51        if !matches!(self.sample_count, 1 | 4) {
52            return Err(ValidationError::OutOfRange);
53        }
54        if self.backends.is_empty() {
55            return Err(ValidationError::InvalidState);
56        }
57        Ok(())
58    }
59
60    /// Returns the preferred color format for this configuration.
61    #[inline]
62    pub const fn preferred_color_format(&self) -> wgpu::TextureFormat {
63        if self.hdr {
64            wgpu::TextureFormat::Rgba16Float
65        } else {
66            wgpu::TextureFormat::Bgra8UnormSrgb
67        }
68    }
69
70    /// Returns a copy with the dimensions changed.
71    #[inline]
72    pub fn resized(mut self, width: u32, height: u32) -> Self {
73        self.width = width;
74        self.height = height;
75        self
76    }
77
78    /// Returns a copy configured for vsync.
79    #[inline]
80    pub fn vsync(mut self, vsync: bool) -> Self {
81        self.vsync = vsync;
82        self.present_mode = if vsync {
83            wgpu::PresentMode::Fifo
84        } else {
85            wgpu::PresentMode::Immediate
86        };
87        self
88    }
89
90    /// Returns a copy configured for HDR intermediates.
91    #[inline]
92    pub const fn hdr(mut self, hdr: bool) -> Self {
93        self.hdr = hdr;
94        self
95    }
96}
97
98impl Default for RendererConfig {
99    #[inline]
100    fn default() -> Self {
101        Self {
102            width: 1280,
103            height: 720,
104            sample_count: 1,
105            vsync: true,
106            hdr: false,
107            present_mode: wgpu::PresentMode::Fifo,
108            backends: wgpu::Backends::all(),
109            clear_color: wgpu::Color {
110                r: 0.02,
111                g: 0.025,
112                b: 0.035,
113                a: 1.0,
114            },
115        }
116    }
117}