Framebuffer

Struct Framebuffer 

Source
pub struct Framebuffer { /* private fields */ }
Expand description

An offscreen render target with optional depth and MSAA attachments.

Implementations§

Source§

impl Framebuffer

Source

pub fn builder(width: u32, height: u32) -> FramebufferBuilder

Create a new framebuffer builder.

Examples found in repository?
examples/renderer_api.rs (line 172)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync_or_panic();
34        let renderer = Renderer::new(graphics_ctx.clone());
35
36        let window = ctx
37            .create_window(WindowDescriptor {
38                title: "Renderer API Example".to_string(),
39                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
40                ..Default::default()
41            })
42            .expect("Failed to create window");
43
44        let window = RenderableWindow::new_with_descriptor(
45            window,
46            graphics_ctx.clone(),
47            WindowContextDescriptor {
48                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
49                ..Default::default()
50            },
51        ).expect("Failed to create renderable window");
52
53        let window_id = window.id();
54
55        // Create shader using Renderer API
56        let shader = renderer.create_shader(Some("Color Shader"), SHADER_SOURCE);
57
58        // Create texture using Renderer helper
59        let texture_data = create_gradient_texture();
60        let texture = renderer.create_texture_2d(
61            Some("Gradient Texture"),
62            256,
63            256,
64            wgpu::TextureFormat::Rgba8UnormSrgb,
65            wgpu::TextureUsages::TEXTURE_BINDING,
66            &texture_data,
67        );
68
69        let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
70        let sampler = renderer.create_linear_sampler(Some("Linear Sampler"));
71
72        // Create bind group using Renderer API
73        let bind_group_layout = renderer.create_bind_group_layout(
74            Some("Texture Bind Group Layout"),
75            &[
76                wgpu::BindGroupLayoutEntry {
77                    binding: 0,
78                    visibility: wgpu::ShaderStages::FRAGMENT,
79                    ty: wgpu::BindingType::Texture {
80                        multisampled: false,
81                        view_dimension: wgpu::TextureViewDimension::D2,
82                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
83                    },
84                    count: None,
85                },
86                wgpu::BindGroupLayoutEntry {
87                    binding: 1,
88                    visibility: wgpu::ShaderStages::FRAGMENT,
89                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
90                    count: None,
91                },
92            ],
93        );
94
95        let bind_group = renderer.create_bind_group(
96            Some("Texture Bind Group"),
97            &bind_group_layout,
98            &[
99                wgpu::BindGroupEntry {
100                    binding: 0,
101                    resource: wgpu::BindingResource::TextureView(&texture_view),
102                },
103                wgpu::BindGroupEntry {
104                    binding: 1,
105                    resource: wgpu::BindingResource::Sampler(&sampler),
106                },
107            ],
108        );
109
110        let pipeline_layout = renderer.create_pipeline_layout(
111            Some("Render Pipeline Layout"),
112            &[&bind_group_layout],
113            &[],
114        );
115
116        // Create pipeline using Renderer API with BlendMode
117        let pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
118            label: Some("Render Pipeline"),
119            layout: Some(&pipeline_layout),
120            vertex: wgpu::VertexState {
121                module: &shader,
122                entry_point: Some("vs_main"),
123                buffers: &[wgpu::VertexBufferLayout {
124                    array_stride: 4 * 4,
125                    step_mode: wgpu::VertexStepMode::Vertex,
126                    attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
127                }],
128                compilation_options: wgpu::PipelineCompilationOptions::default(),
129            },
130            fragment: Some(wgpu::FragmentState {
131                module: &shader,
132                entry_point: Some("fs_main"),
133                // Use BlendMode for transparent rendering
134                targets: &[Some(
135                    BlendMode::Alpha.to_color_target_state(wgpu::TextureFormat::Rgba8UnormSrgb),
136                )],
137                compilation_options: wgpu::PipelineCompilationOptions::default(),
138            }),
139            primitive: wgpu::PrimitiveState {
140                topology: wgpu::PrimitiveTopology::TriangleList,
141                strip_index_format: None,
142                front_face: wgpu::FrontFace::Ccw,
143                cull_mode: Some(wgpu::Face::Back),
144                polygon_mode: wgpu::PolygonMode::Fill,
145                unclipped_depth: false,
146                conservative: false,
147            },
148            depth_stencil: None,
149            multisample: wgpu::MultisampleState {
150                count: 1,
151                mask: !0,
152                alpha_to_coverage_enabled: false,
153            },
154            multiview: None,
155            cache: None,
156        });
157
158        #[rustfmt::skip]
159        let vertices: &[f32] = &[
160            -0.8, -0.8,  0.0, 1.0,
161             0.8, -0.8,  1.0, 1.0,
162             0.8,  0.8,  1.0, 0.0,
163            -0.8, -0.8,  0.0, 1.0,
164             0.8,  0.8,  1.0, 0.0,
165            -0.8,  0.8,  0.0, 0.0,
166        ];
167
168        // Create vertex buffer using Renderer helper
169        let vertex_buffer = renderer.create_vertex_buffer(Some("Vertex Buffer"), vertices);
170
171        // Create offscreen framebuffer using the new Framebuffer abstraction
172        let offscreen_fb = Framebuffer::builder(400, 300)
173            .format(wgpu::TextureFormat::Rgba8UnormSrgb)
174            .label("Offscreen FB")
175            .build(&graphics_ctx);
176
177        // Create blit shader and pipeline for rendering framebuffer to surface
178        let blit_shader = renderer.create_shader(Some("Blit Shader"), BLIT_SHADER_SOURCE);
179
180        let blit_bind_group_layout = renderer.create_bind_group_layout(
181            Some("Blit Bind Group Layout"),
182            &[
183                wgpu::BindGroupLayoutEntry {
184                    binding: 0,
185                    visibility: wgpu::ShaderStages::FRAGMENT,
186                    ty: wgpu::BindingType::Texture {
187                        multisampled: false,
188                        view_dimension: wgpu::TextureViewDimension::D2,
189                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
190                    },
191                    count: None,
192                },
193                wgpu::BindGroupLayoutEntry {
194                    binding: 1,
195                    visibility: wgpu::ShaderStages::FRAGMENT,
196                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
197                    count: None,
198                },
199            ],
200        );
201
202        let blit_bind_group = renderer.create_bind_group(
203            Some("Blit Bind Group"),
204            &blit_bind_group_layout,
205            &[
206                wgpu::BindGroupEntry {
207                    binding: 0,
208                    resource: wgpu::BindingResource::TextureView(offscreen_fb.color_view()),
209                },
210                wgpu::BindGroupEntry {
211                    binding: 1,
212                    resource: wgpu::BindingResource::Sampler(&sampler),
213                },
214            ],
215        );
216
217        let blit_pipeline_layout = renderer.create_pipeline_layout(
218            Some("Blit Pipeline Layout"),
219            &[&blit_bind_group_layout],
220            &[],
221        );
222
223        let blit_pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
224            label: Some("Blit Pipeline"),
225            layout: Some(&blit_pipeline_layout),
226            vertex: wgpu::VertexState {
227                module: &blit_shader,
228                entry_point: Some("vs_main"),
229                buffers: &[],
230                compilation_options: wgpu::PipelineCompilationOptions::default(),
231            },
232            fragment: Some(wgpu::FragmentState {
233                module: &blit_shader,
234                entry_point: Some("fs_main"),
235                // Use PremultipliedAlpha for framebuffer blitting
236                targets: &[Some(
237                    BlendMode::PremultipliedAlpha
238                        .to_color_target_state(wgpu::TextureFormat::Bgra8UnormSrgb),
239                )],
240                compilation_options: wgpu::PipelineCompilationOptions::default(),
241            }),
242            primitive: wgpu::PrimitiveState {
243                topology: wgpu::PrimitiveTopology::TriangleList,
244                ..Default::default()
245            },
246            depth_stencil: None,
247            multisample: wgpu::MultisampleState::default(),
248            multiview: None,
249            cache: None,
250        });
251
252        tracing::info!("Renderer initialized successfully");
253        tracing::info!("Device: {:?}", renderer.context().info());
254
255        Box::new(RendererApp {
256            context: graphics_ctx,
257            renderer,
258            window,
259            window_id,
260            pipeline,
261            bind_group,
262            vertex_buffer,
263            offscreen_fb,
264            blit_pipeline,
265            blit_bind_group,
266            time: 0.0,
267        })
268    });
269}
Source

pub fn color_texture(&self) -> &Texture

Get the color texture (resolved, non-MSAA).

Source

pub fn color_view(&self) -> &TextureView

Get the color texture view (resolved, non-MSAA).

Examples found in repository?
examples/renderer_api.rs (line 208)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync_or_panic();
34        let renderer = Renderer::new(graphics_ctx.clone());
35
36        let window = ctx
37            .create_window(WindowDescriptor {
38                title: "Renderer API Example".to_string(),
39                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
40                ..Default::default()
41            })
42            .expect("Failed to create window");
43
44        let window = RenderableWindow::new_with_descriptor(
45            window,
46            graphics_ctx.clone(),
47            WindowContextDescriptor {
48                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
49                ..Default::default()
50            },
51        ).expect("Failed to create renderable window");
52
53        let window_id = window.id();
54
55        // Create shader using Renderer API
56        let shader = renderer.create_shader(Some("Color Shader"), SHADER_SOURCE);
57
58        // Create texture using Renderer helper
59        let texture_data = create_gradient_texture();
60        let texture = renderer.create_texture_2d(
61            Some("Gradient Texture"),
62            256,
63            256,
64            wgpu::TextureFormat::Rgba8UnormSrgb,
65            wgpu::TextureUsages::TEXTURE_BINDING,
66            &texture_data,
67        );
68
69        let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
70        let sampler = renderer.create_linear_sampler(Some("Linear Sampler"));
71
72        // Create bind group using Renderer API
73        let bind_group_layout = renderer.create_bind_group_layout(
74            Some("Texture Bind Group Layout"),
75            &[
76                wgpu::BindGroupLayoutEntry {
77                    binding: 0,
78                    visibility: wgpu::ShaderStages::FRAGMENT,
79                    ty: wgpu::BindingType::Texture {
80                        multisampled: false,
81                        view_dimension: wgpu::TextureViewDimension::D2,
82                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
83                    },
84                    count: None,
85                },
86                wgpu::BindGroupLayoutEntry {
87                    binding: 1,
88                    visibility: wgpu::ShaderStages::FRAGMENT,
89                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
90                    count: None,
91                },
92            ],
93        );
94
95        let bind_group = renderer.create_bind_group(
96            Some("Texture Bind Group"),
97            &bind_group_layout,
98            &[
99                wgpu::BindGroupEntry {
100                    binding: 0,
101                    resource: wgpu::BindingResource::TextureView(&texture_view),
102                },
103                wgpu::BindGroupEntry {
104                    binding: 1,
105                    resource: wgpu::BindingResource::Sampler(&sampler),
106                },
107            ],
108        );
109
110        let pipeline_layout = renderer.create_pipeline_layout(
111            Some("Render Pipeline Layout"),
112            &[&bind_group_layout],
113            &[],
114        );
115
116        // Create pipeline using Renderer API with BlendMode
117        let pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
118            label: Some("Render Pipeline"),
119            layout: Some(&pipeline_layout),
120            vertex: wgpu::VertexState {
121                module: &shader,
122                entry_point: Some("vs_main"),
123                buffers: &[wgpu::VertexBufferLayout {
124                    array_stride: 4 * 4,
125                    step_mode: wgpu::VertexStepMode::Vertex,
126                    attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
127                }],
128                compilation_options: wgpu::PipelineCompilationOptions::default(),
129            },
130            fragment: Some(wgpu::FragmentState {
131                module: &shader,
132                entry_point: Some("fs_main"),
133                // Use BlendMode for transparent rendering
134                targets: &[Some(
135                    BlendMode::Alpha.to_color_target_state(wgpu::TextureFormat::Rgba8UnormSrgb),
136                )],
137                compilation_options: wgpu::PipelineCompilationOptions::default(),
138            }),
139            primitive: wgpu::PrimitiveState {
140                topology: wgpu::PrimitiveTopology::TriangleList,
141                strip_index_format: None,
142                front_face: wgpu::FrontFace::Ccw,
143                cull_mode: Some(wgpu::Face::Back),
144                polygon_mode: wgpu::PolygonMode::Fill,
145                unclipped_depth: false,
146                conservative: false,
147            },
148            depth_stencil: None,
149            multisample: wgpu::MultisampleState {
150                count: 1,
151                mask: !0,
152                alpha_to_coverage_enabled: false,
153            },
154            multiview: None,
155            cache: None,
156        });
157
158        #[rustfmt::skip]
159        let vertices: &[f32] = &[
160            -0.8, -0.8,  0.0, 1.0,
161             0.8, -0.8,  1.0, 1.0,
162             0.8,  0.8,  1.0, 0.0,
163            -0.8, -0.8,  0.0, 1.0,
164             0.8,  0.8,  1.0, 0.0,
165            -0.8,  0.8,  0.0, 0.0,
166        ];
167
168        // Create vertex buffer using Renderer helper
169        let vertex_buffer = renderer.create_vertex_buffer(Some("Vertex Buffer"), vertices);
170
171        // Create offscreen framebuffer using the new Framebuffer abstraction
172        let offscreen_fb = Framebuffer::builder(400, 300)
173            .format(wgpu::TextureFormat::Rgba8UnormSrgb)
174            .label("Offscreen FB")
175            .build(&graphics_ctx);
176
177        // Create blit shader and pipeline for rendering framebuffer to surface
178        let blit_shader = renderer.create_shader(Some("Blit Shader"), BLIT_SHADER_SOURCE);
179
180        let blit_bind_group_layout = renderer.create_bind_group_layout(
181            Some("Blit Bind Group Layout"),
182            &[
183                wgpu::BindGroupLayoutEntry {
184                    binding: 0,
185                    visibility: wgpu::ShaderStages::FRAGMENT,
186                    ty: wgpu::BindingType::Texture {
187                        multisampled: false,
188                        view_dimension: wgpu::TextureViewDimension::D2,
189                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
190                    },
191                    count: None,
192                },
193                wgpu::BindGroupLayoutEntry {
194                    binding: 1,
195                    visibility: wgpu::ShaderStages::FRAGMENT,
196                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
197                    count: None,
198                },
199            ],
200        );
201
202        let blit_bind_group = renderer.create_bind_group(
203            Some("Blit Bind Group"),
204            &blit_bind_group_layout,
205            &[
206                wgpu::BindGroupEntry {
207                    binding: 0,
208                    resource: wgpu::BindingResource::TextureView(offscreen_fb.color_view()),
209                },
210                wgpu::BindGroupEntry {
211                    binding: 1,
212                    resource: wgpu::BindingResource::Sampler(&sampler),
213                },
214            ],
215        );
216
217        let blit_pipeline_layout = renderer.create_pipeline_layout(
218            Some("Blit Pipeline Layout"),
219            &[&blit_bind_group_layout],
220            &[],
221        );
222
223        let blit_pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
224            label: Some("Blit Pipeline"),
225            layout: Some(&blit_pipeline_layout),
226            vertex: wgpu::VertexState {
227                module: &blit_shader,
228                entry_point: Some("vs_main"),
229                buffers: &[],
230                compilation_options: wgpu::PipelineCompilationOptions::default(),
231            },
232            fragment: Some(wgpu::FragmentState {
233                module: &blit_shader,
234                entry_point: Some("fs_main"),
235                // Use PremultipliedAlpha for framebuffer blitting
236                targets: &[Some(
237                    BlendMode::PremultipliedAlpha
238                        .to_color_target_state(wgpu::TextureFormat::Bgra8UnormSrgb),
239                )],
240                compilation_options: wgpu::PipelineCompilationOptions::default(),
241            }),
242            primitive: wgpu::PrimitiveState {
243                topology: wgpu::PrimitiveTopology::TriangleList,
244                ..Default::default()
245            },
246            depth_stencil: None,
247            multisample: wgpu::MultisampleState::default(),
248            multiview: None,
249            cache: None,
250        });
251
252        tracing::info!("Renderer initialized successfully");
253        tracing::info!("Device: {:?}", renderer.context().info());
254
255        Box::new(RendererApp {
256            context: graphics_ctx,
257            renderer,
258            window,
259            window_id,
260            pipeline,
261            bind_group,
262            vertex_buffer,
263            offscreen_fb,
264            blit_pipeline,
265            blit_bind_group,
266            time: 0.0,
267        })
268    });
269}
Source

pub fn depth_texture(&self) -> Option<&Texture>

Get the depth texture, if present.

Source

pub fn depth_view(&self) -> Option<&TextureView>

Get the depth texture view, if present.

Source

pub fn msaa_texture(&self) -> Option<&Texture>

Get the MSAA texture (render target when MSAA enabled).

Source

pub fn msaa_view(&self) -> Option<&TextureView>

Get the MSAA texture view (render target when MSAA enabled).

Source

pub fn render_view(&self) -> &TextureView

Get the view to render to (MSAA view if enabled, otherwise color view).

Source

pub fn resolve_target(&self) -> Option<&TextureView>

Get the resolve target (color view if MSAA enabled, None otherwise).

Source

pub fn width(&self) -> u32

Get the framebuffer width.

Source

pub fn height(&self) -> u32

Get the framebuffer height.

Source

pub fn size(&self) -> (u32, u32)

Get the framebuffer size as (width, height).

Source

pub fn format(&self) -> TextureFormat

Get the color format.

Source

pub fn sample_count(&self) -> u32

Get the sample count (1 if no MSAA).

Source

pub fn has_msaa(&self) -> bool

Check if MSAA is enabled.

Source

pub fn has_depth(&self) -> bool

Check if depth buffer is enabled.

Source

pub fn resize(&mut self, context: &GraphicsContext, width: u32, height: u32)

Resize the framebuffer, recreating all textures.

Trait Implementations§

Source§

impl AsWgpu for Framebuffer

Source§

type WgpuType = Texture

The underlying wgpu type.
Source§

fn as_wgpu(&self) -> &Self::WgpuType

Get a reference to the underlying wgpu type.
Source§

impl Debug for Framebuffer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> From<&'a Framebuffer> for RenderTarget<'a>

Source§

fn from(fb: &'a Framebuffer) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,