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