pub struct Framebuffer { /* private fields */ }Expand description
An offscreen render target with optional depth and MSAA attachments.
Implementations§
Source§impl Framebuffer
impl Framebuffer
Sourcepub fn builder(width: u32, height: u32) -> FramebufferBuilder
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}Sourcepub fn color_texture(&self) -> &Texture
pub fn color_texture(&self) -> &Texture
Get the color texture (resolved, non-MSAA).
Sourcepub fn color_view(&self) -> &TextureView
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}Sourcepub fn depth_texture(&self) -> Option<&Texture>
pub fn depth_texture(&self) -> Option<&Texture>
Get the depth texture, if present.
Sourcepub fn depth_view(&self) -> Option<&TextureView>
pub fn depth_view(&self) -> Option<&TextureView>
Get the depth texture view, if present.
Sourcepub fn msaa_texture(&self) -> Option<&Texture>
pub fn msaa_texture(&self) -> Option<&Texture>
Get the MSAA texture (render target when MSAA enabled).
Sourcepub fn msaa_view(&self) -> Option<&TextureView>
pub fn msaa_view(&self) -> Option<&TextureView>
Get the MSAA texture view (render target when MSAA enabled).
Sourcepub fn render_view(&self) -> &TextureView
pub fn render_view(&self) -> &TextureView
Get the view to render to (MSAA view if enabled, otherwise color view).
Sourcepub fn resolve_target(&self) -> Option<&TextureView>
pub fn resolve_target(&self) -> Option<&TextureView>
Get the resolve target (color view if MSAA enabled, None otherwise).
Sourcepub fn format(&self) -> TextureFormat
pub fn format(&self) -> TextureFormat
Get the color format.
Sourcepub fn sample_count(&self) -> u32
pub fn sample_count(&self) -> u32
Get the sample count (1 if no MSAA).
Sourcepub fn resize(&mut self, context: &GraphicsContext, width: u32, height: u32)
pub fn resize(&mut self, context: &GraphicsContext, width: u32, height: u32)
Resize the framebuffer, recreating all textures.
Trait Implementations§
Source§impl AsWgpu for Framebuffer
impl AsWgpu for Framebuffer
Source§impl Debug for Framebuffer
impl Debug for Framebuffer
Source§impl<'a> From<&'a Framebuffer> for RenderTarget<'a>
impl<'a> From<&'a Framebuffer> for RenderTarget<'a>
Source§fn from(fb: &'a Framebuffer) -> Self
fn from(fb: &'a Framebuffer) -> Self
Converts to this type from the input type.
Auto Trait Implementations§
impl Freeze for Framebuffer
impl !RefUnwindSafe for Framebuffer
impl Send for Framebuffer
impl Sync for Framebuffer
impl Unpin for Framebuffer
impl !UnwindSafe for Framebuffer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
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>
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)
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)
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
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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