Skip to main content

rein/core/
render_target.rs

1//! Render target abstraction
2//!
3//! Provides a convenient interface for rendering to textures or the screen.
4
5use crate::context::WgpuContext;
6use crate::core::render_states::ClearState;
7use crate::core::texture::DepthTexture;
8
9/// A render target that can be rendered to.
10pub struct RenderTarget<'a> {
11    pub(crate) ctx: &'a WgpuContext,
12    pub(crate) color_view: &'a wgpu::TextureView,
13    pub(crate) depth_view: Option<&'a wgpu::TextureView>,
14    pub(crate) width: u32,
15    pub(crate) height: u32,
16    pub(crate) format: wgpu::TextureFormat,
17}
18
19impl<'a> RenderTarget<'a> {
20    /// Create a new render target.
21    pub fn new(
22        ctx: &'a WgpuContext,
23        color_view: &'a wgpu::TextureView,
24        depth_view: Option<&'a wgpu::TextureView>,
25        width: u32,
26        height: u32,
27        format: wgpu::TextureFormat,
28    ) -> Self {
29        Self {
30            ctx,
31            color_view,
32            depth_view,
33            width,
34            height,
35            format,
36        }
37    }
38
39    /// Create a render target from a surface texture.
40    pub fn from_surface(
41        ctx: &'a WgpuContext,
42        surface_view: &'a wgpu::TextureView,
43        depth_texture: Option<&'a DepthTexture>,
44        width: u32,
45        height: u32,
46        format: wgpu::TextureFormat,
47    ) -> Self {
48        Self {
49            ctx,
50            color_view: surface_view,
51            depth_view: depth_texture.map(|d| d.view()),
52            width,
53            height,
54            format,
55        }
56    }
57
58    /// Get the render target width.
59    pub fn width(&self) -> u32 {
60        self.width
61    }
62
63    /// Get the render target height.
64    pub fn height(&self) -> u32 {
65        self.height
66    }
67
68    /// Get the aspect ratio.
69    pub fn aspect(&self) -> f32 {
70        self.width as f32 / self.height as f32
71    }
72
73    /// Get the texture format.
74    pub fn format(&self) -> wgpu::TextureFormat {
75        self.format
76    }
77
78    /// Create a render pass with the given clear state.
79    pub fn begin_render_pass<'p>(
80        &'a self,
81        encoder: &'p mut wgpu::CommandEncoder,
82        clear: ClearState,
83    ) -> wgpu::RenderPass<'p>
84    where
85        'a: 'p,
86    {
87        let color_attachment = wgpu::RenderPassColorAttachment {
88            view: self.color_view,
89            resolve_target: None,
90            ops: wgpu::Operations {
91                load: clear.color_load_op(),
92                store: wgpu::StoreOp::Store,
93            },
94        };
95
96        let depth_attachment = self
97            .depth_view
98            .map(|view| wgpu::RenderPassDepthStencilAttachment {
99                view,
100                depth_ops: Some(wgpu::Operations {
101                    load: clear.depth_load_op(),
102                    store: wgpu::StoreOp::Store,
103                }),
104                stencil_ops: None,
105            });
106
107        encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
108            label: Some("render pass"),
109            color_attachments: &[Some(color_attachment)],
110            depth_stencil_attachment: depth_attachment,
111            timestamp_writes: None,
112            occlusion_query_set: None,
113        })
114    }
115
116    /// Clear the render target with the given clear state.
117    pub fn clear(&self, clear: ClearState) {
118        let mut encoder = self.ctx.create_encoder(Some("clear encoder"));
119        {
120            let _pass = self.begin_render_pass(&mut encoder, clear);
121            // Pass drops immediately, just clearing
122        }
123        self.ctx.submit([encoder.finish()]);
124    }
125
126    /// Get a reference to the context.
127    pub fn context(&self) -> &WgpuContext {
128        self.ctx
129    }
130
131    /// Get the color view.
132    pub fn color_view(&self) -> &wgpu::TextureView {
133        self.color_view
134    }
135
136    /// Get the depth view if available.
137    pub fn depth_view(&self) -> Option<&wgpu::TextureView> {
138        self.depth_view
139    }
140}