viewport_lib/renderer/paths.rs
1use super::{FrameData, SceneEffects, ViewportId, ViewportRenderer};
2
3/// Token returned by `prepare_scene` and required by `prepare_viewport`.
4///
5/// Enforces call ordering at compile time: `prepare_viewport` cannot be called
6/// without a token from a prior `prepare_scene` in the same frame. A single
7/// token may be borrowed multiple times in the same frame to prepare multiple
8/// viewports over a shared scene.
9pub struct ScenePreparedToken {
10 _private: (),
11}
12
13/// Rendering path for applications that own the window loop and wgpu encoder.
14///
15/// Obtained from [`ViewportRenderer::owned`]. The renderer encodes all GPU work
16/// and returns a [`wgpu::CommandBuffer`] for the caller to submit.
17///
18/// Use this with winit, raw wgpu, or any setup where you control the encoder.
19pub struct OwnedPath<'r> {
20 pub(super) renderer: &'r mut ViewportRenderer,
21}
22
23/// Rendering path for framework callbacks that provide a render pass.
24///
25/// Obtained from [`ViewportRenderer::pass`]. Prepare encodes pre-pass work
26/// and returns command buffers to submit before the surface pass. Paint draws
27/// into the caller-provided render pass.
28///
29/// Use this with eframe (`CallbackTrait`), iced, or any framework that hands
30/// you a render pass. For the eframe `paint` callback where only a `&` reference
31/// to the renderer is available, use [`ViewportRenderer::pass_view`] instead.
32pub struct PassPath<'r> {
33 pub(super) renderer: &'r mut ViewportRenderer,
34}
35
36/// Read-only paint view returned by [`ViewportRenderer::pass_view`].
37///
38/// Identical to [`PassPath`] but constructed from a shared reference, making it
39/// usable in framework paint callbacks where only `&` access to the renderer is
40/// available (e.g. eframe's `CallbackTrait::paint`).
41pub struct PassView<'r> {
42 pub(super) renderer: &'r ViewportRenderer,
43}
44
45impl<'r> OwnedPath<'r> {
46 /// Render a single viewport. Runs prepare internally and returns a command buffer to submit.
47 pub fn render(
48 &mut self,
49 device: &wgpu::Device,
50 queue: &wgpu::Queue,
51 output_view: &wgpu::TextureView,
52 frame: &FrameData,
53 ) -> wgpu::CommandBuffer {
54 self.renderer.render(device, queue, output_view, frame)
55 }
56
57 /// Multi-viewport: upload scene-level GPU data shared across all viewports.
58 ///
59 /// Call once per frame before any `prepare_viewport` or `render_viewport` calls.
60 /// Returns a [`ScenePreparedToken`] that must be passed to each `prepare_viewport`
61 /// call in the same frame. The token may be borrowed multiple times for multi-viewport scenes.
62 pub fn prepare_scene(
63 &mut self,
64 device: &wgpu::Device,
65 queue: &wgpu::Queue,
66 frame: &FrameData,
67 scene_effects: &SceneEffects<'_>,
68 ) -> ScenePreparedToken {
69 self.renderer
70 .prepare_scene(device, queue, frame, scene_effects);
71 ScenePreparedToken { _private: () }
72 }
73
74 /// Multi-viewport: upload per-viewport GPU data for `id`.
75 ///
76 /// Call after `prepare_scene` and before `render_viewport`. The `_token` parameter
77 /// is a borrow of the [`ScenePreparedToken`] returned by `prepare_scene`; it enforces
78 /// that `prepare_scene` has been called earlier in the same frame.
79 pub fn prepare_viewport(
80 &mut self,
81 device: &wgpu::Device,
82 queue: &wgpu::Queue,
83 _token: &ScenePreparedToken,
84 id: ViewportId,
85 frame: &FrameData,
86 ) {
87 self.renderer.prepare_viewport(device, queue, id, frame);
88 }
89
90 /// Multi-viewport: encode draw calls for `id` into its own command buffer.
91 /// Call after `prepare_scene` and `prepare_viewport` for this id.
92 pub fn render_viewport(
93 &mut self,
94 device: &wgpu::Device,
95 queue: &wgpu::Queue,
96 output_view: &wgpu::TextureView,
97 id: ViewportId,
98 frame: &FrameData,
99 ) -> wgpu::CommandBuffer {
100 self.renderer
101 .render_viewport(device, queue, output_view, id, frame)
102 }
103}
104
105impl<'r> PassPath<'r> {
106 /// Single viewport: upload uniforms and encode any HDR pre-pass work.
107 ///
108 /// Returns command buffers that must be submitted before the surface render
109 /// pass begins. Returns an empty vec for LDR with no dynamic resolution.
110 pub fn prepare(
111 &mut self,
112 device: &wgpu::Device,
113 queue: &wgpu::Queue,
114 frame: &FrameData,
115 ) -> Vec<wgpu::CommandBuffer> {
116 self.renderer.prepare_callback(device, queue, frame)
117 }
118
119 /// Single viewport: issue draw calls into `render_pass`.
120 ///
121 /// Call after `prepare` for the same frame. Dispatches to the HDR blit,
122 /// dynamic-resolution blit, or direct draw based on which path `prepare`
123 /// activated. The render pass is expected to have a depth-stencil attachment,
124 /// as provided by eframe and most GUI frameworks.
125 pub fn paint<'rp>(&self, render_pass: &mut wgpu::RenderPass<'rp>, frame: &FrameData) {
126 self.renderer.paint_callback(render_pass, frame);
127 }
128
129 /// Multi-viewport: upload scene-level GPU data shared across all viewports.
130 ///
131 /// Call once per frame before any `prepare_viewport` calls. Returns a
132 /// [`ScenePreparedToken`] that must be passed to each `prepare_viewport` call
133 /// in the same frame. The token may be borrowed multiple times for multi-viewport scenes.
134 pub fn prepare_scene(
135 &mut self,
136 device: &wgpu::Device,
137 queue: &wgpu::Queue,
138 frame: &FrameData,
139 scene_effects: &SceneEffects<'_>,
140 ) -> ScenePreparedToken {
141 self.renderer
142 .prepare_scene(device, queue, frame, scene_effects);
143 ScenePreparedToken { _private: () }
144 }
145
146 /// Multi-viewport: upload per-viewport GPU data for `id`.
147 ///
148 /// Call after `prepare_scene` and before `paint_viewport` or `prepare_hdr_viewport`.
149 /// The `_token` parameter is a borrow of the [`ScenePreparedToken`] returned by
150 /// `prepare_scene`; it enforces that `prepare_scene` has been called earlier in the same frame.
151 pub fn prepare_viewport(
152 &mut self,
153 device: &wgpu::Device,
154 queue: &wgpu::Queue,
155 _token: &ScenePreparedToken,
156 id: ViewportId,
157 frame: &FrameData,
158 ) {
159 self.renderer.prepare_viewport(device, queue, id, frame);
160 }
161
162 /// Multi-viewport: issue draw calls for `id` into `render_pass`.
163 ///
164 /// Set the render pass viewport and scissor rect to the correct region
165 /// before calling. Call after `prepare_scene` and `prepare_viewport`.
166 pub fn paint_viewport<'rp>(
167 &self,
168 render_pass: &mut wgpu::RenderPass<'rp>,
169 id: ViewportId,
170 frame: &FrameData,
171 ) {
172 self.renderer.paint_viewport_to(render_pass, id, frame);
173 }
174
175 /// Multi-viewport HDR: encode the full HDR pipeline for `id` into an intermediate texture.
176 ///
177 /// Call after `prepare_scene` and `prepare_viewport` for this viewport. Returns a
178 /// `CommandBuffer` that eframe must submit before the egui render pass begins.
179 ///
180 /// Call [`PassView::paint_hdr_blit`] from `CallbackTrait::paint` to composite the
181 /// result into the egui render pass. Set the render pass viewport and scissor rect first.
182 pub fn prepare_hdr_viewport(
183 &mut self,
184 device: &wgpu::Device,
185 queue: &wgpu::Queue,
186 id: ViewportId,
187 frame: &FrameData,
188 ) -> wgpu::CommandBuffer {
189 self.renderer
190 .prepare_hdr_callback_viewport(device, queue, id, frame)
191 }
192}
193
194impl<'r> PassView<'r> {
195 /// Single viewport: issue draw calls into `render_pass`.
196 pub fn paint<'rp>(&self, render_pass: &mut wgpu::RenderPass<'rp>, frame: &FrameData) {
197 self.renderer.paint_callback(render_pass, frame);
198 }
199
200 /// Multi-viewport: issue draw calls for `id` into `render_pass`.
201 pub fn paint_viewport<'rp>(
202 &self,
203 render_pass: &mut wgpu::RenderPass<'rp>,
204 id: ViewportId,
205 frame: &FrameData,
206 ) {
207 self.renderer.paint_viewport_to(render_pass, id, frame);
208 }
209
210 /// Multi-viewport HDR: blit the intermediate texture for `frame`'s viewport into `render_pass`.
211 ///
212 /// Call after [`PassPath::prepare_hdr_viewport`] for the same viewport. Set the render
213 /// pass viewport and scissor rect to the correct region before calling.
214 ///
215 /// The render pass must have a `Depth24PlusStencil8` depth-stencil attachment (as eframe
216 /// callbacks always do). For render passes without a depth attachment (e.g. a plain winit
217 /// blit pass), use [`paint_hdr_blit_no_ds`](Self::paint_hdr_blit_no_ds) instead.
218 pub fn paint_hdr_blit<'rp>(&self, render_pass: &mut wgpu::RenderPass<'rp>, frame: &FrameData) {
219 self.renderer.paint_hdr_blit(render_pass, frame);
220 }
221
222 /// Like [`paint_hdr_blit`] but for render passes without a depth-stencil attachment.
223 ///
224 /// Use this when you create the blit render pass yourself (e.g. winit) and the pass
225 /// has no depth attachment. The resulting blit is identical; only the pipeline variant
226 /// differs to match the render pass format.
227 pub fn paint_hdr_blit_no_ds<'rp>(
228 &self,
229 render_pass: &mut wgpu::RenderPass<'rp>,
230 frame: &FrameData,
231 ) {
232 self.renderer.paint_hdr_blit_no_ds(render_pass, frame);
233 }
234}