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}