astrelis_render/
target.rs

1//! Render target abstraction for unified surface/framebuffer rendering.
2
3use crate::framebuffer::Framebuffer;
4
5/// A render target that can be either a window surface or an offscreen framebuffer.
6///
7/// This enum simplifies render pass setup by providing a unified interface
8/// for different rendering destinations.
9#[derive(Debug, Clone, Copy)]
10pub enum RenderTarget<'a> {
11    /// Render to the window surface.
12    ///
13    /// The surface view is obtained from the FrameContext during render pass creation.
14    Surface,
15
16    /// Render to an offscreen framebuffer.
17    ///
18    /// The framebuffer manages its own color, depth, and MSAA textures.
19    Framebuffer(&'a Framebuffer),
20}
21
22impl<'a> RenderTarget<'a> {
23    /// Check if this target is a surface.
24    pub fn is_surface(&self) -> bool {
25        matches!(self, RenderTarget::Surface)
26    }
27
28    /// Check if this target is a framebuffer.
29    pub fn is_framebuffer(&self) -> bool {
30        matches!(self, RenderTarget::Framebuffer(_))
31    }
32
33    /// Get the framebuffer if this is a framebuffer target.
34    pub fn framebuffer(&self) -> Option<&'a Framebuffer> {
35        match self {
36            RenderTarget::Framebuffer(fb) => Some(fb),
37            _ => None,
38        }
39    }
40
41    /// Get the texture format for this target.
42    ///
43    /// For framebuffers, returns the framebuffer's format.
44    /// For surfaces, returns None (format must be obtained from surface config).
45    pub fn format(&self) -> Option<wgpu::TextureFormat> {
46        match self {
47            RenderTarget::Surface => None,
48            RenderTarget::Framebuffer(fb) => Some(fb.format()),
49        }
50    }
51
52    /// Get the sample count for this target.
53    ///
54    /// For framebuffers, returns the framebuffer's sample count.
55    /// For surfaces, returns 1 (surfaces don't support MSAA directly).
56    pub fn sample_count(&self) -> u32 {
57        match self {
58            RenderTarget::Surface => 1,
59            RenderTarget::Framebuffer(fb) => fb.sample_count(),
60        }
61    }
62
63    /// Check if this target has MSAA enabled.
64    pub fn has_msaa(&self) -> bool {
65        self.sample_count() > 1
66    }
67
68    /// Check if this target has a depth buffer.
69    pub fn has_depth(&self) -> bool {
70        match self {
71            RenderTarget::Surface => false,
72            RenderTarget::Framebuffer(fb) => fb.has_depth(),
73        }
74    }
75
76    /// Get the depth view if available.
77    pub fn depth_view(&self) -> Option<&wgpu::TextureView> {
78        match self {
79            RenderTarget::Surface => None,
80            RenderTarget::Framebuffer(fb) => fb.depth_view(),
81        }
82    }
83}
84
85impl Default for RenderTarget<'_> {
86    fn default() -> Self {
87        RenderTarget::Surface
88    }
89}
90
91impl<'a> From<&'a Framebuffer> for RenderTarget<'a> {
92    fn from(fb: &'a Framebuffer) -> Self {
93        RenderTarget::Framebuffer(fb)
94    }
95}