Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Support recording multiple CommandBuffers in RenderContext #7248

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl Node for MainPass2dNode {
};

render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_3d/main_pass_3d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl Node for MainPass3dNode {
};

render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);
}

Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_core_pipeline/src/fxaa/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl Node for FxaaNode {
Some((id, bind_group)) if source.id() == *id => bind_group,
cached_bind_group => {
let sampler = render_context
.render_device
.render_device()
.create_sampler(&SamplerDescriptor {
mipmap_filter: FilterMode::Linear,
mag_filter: FilterMode::Linear,
Expand All @@ -88,7 +88,7 @@ impl Node for FxaaNode {

let bind_group =
render_context
.render_device
.render_device()
.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &fxaa_pipeline.texture_bind_group,
Expand Down Expand Up @@ -120,7 +120,7 @@ impl Node for FxaaNode {
};

let mut render_pass = render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);

render_pass.set_pipeline(pipeline);
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_core_pipeline/src/tonemapping/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ impl Node for TonemappingNode {
Some((id, bind_group)) if source.id() == *id => bind_group,
cached_bind_group => {
let sampler = render_context
.render_device
.render_device()
.create_sampler(&SamplerDescriptor::default());

let bind_group =
render_context
.render_device
.render_device()
.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &tonemapping_pipeline.texture_bind_group,
Expand Down Expand Up @@ -112,7 +112,7 @@ impl Node for TonemappingNode {
};

let mut render_pass = render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);

render_pass.set_pipeline(pipeline);
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_core_pipeline/src/upscaling/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ impl Node for UpscalingNode {
Some((id, bind_group)) if upscaled_texture.id() == *id => bind_group,
cached_bind_group => {
let sampler = render_context
.render_device
.render_device()
.create_sampler(&SamplerDescriptor::default());

let bind_group =
render_context
.render_device
.render_device()
.create_bind_group(&BindGroupDescriptor {
label: None,
layout: &upscaling_pipeline.texture_bind_group,
Expand Down Expand Up @@ -108,7 +108,7 @@ impl Node for UpscalingNode {
};

let mut render_pass = render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);

render_pass.set_pipeline(pipeline);
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/camera/camera_driver_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Node for CameraDriverNode {
};

render_context
.command_encoder
.command_encoder()
.begin_render_pass(&pass_descriptor);
}

Expand Down
10 changes: 2 additions & 8 deletions crates/bevy_render/src/renderer/graph_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,12 @@ impl RenderGraphRunner {
queue: &wgpu::Queue,
world: &World,
) -> Result<(), RenderGraphRunnerError> {
let command_encoder =
render_device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default());
let mut render_context = RenderContext {
render_device,
command_encoder,
};

let mut render_context = RenderContext::new(render_device);
Self::run_graph(graph, None, &mut render_context, world, &[])?;
{
#[cfg(feature = "trace")]
let _span = info_span!("submit_graph_commands").entered();
queue.submit(vec![render_context.command_encoder.finish()]);
queue.submit(render_context.finish());
james7132 marked this conversation as resolved.
Show resolved Hide resolved
}
Ok(())
}
Expand Down
64 changes: 57 additions & 7 deletions crates/bevy_render/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use bevy_ecs::prelude::*;
use bevy_time::TimeSender;
use bevy_utils::Instant;
use std::sync::Arc;
use wgpu::{Adapter, AdapterInfo, CommandEncoder, Instance, Queue, RequestAdapterOptions};
use wgpu::{
Adapter, AdapterInfo, CommandBuffer, CommandEncoder, Instance, Queue, RequestAdapterOptions,
};

/// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame.
pub fn render_system(world: &mut World) {
Expand Down Expand Up @@ -278,20 +280,68 @@ pub async fn initialize_renderer(
/// The [`RenderDevice`] is used to create render resources and the
/// the [`CommandEncoder`] is used to record a series of GPU operations.
pub struct RenderContext {
pub render_device: RenderDevice,
pub command_encoder: CommandEncoder,
render_device: RenderDevice,
command_encoder: Option<CommandEncoder>,
command_buffers: Vec<CommandBuffer>,
james7132 marked this conversation as resolved.
Show resolved Hide resolved
}

impl RenderContext {
/// Creates a new [`RenderContext`] from a [`RenderDevice`].
pub fn new(render_device: RenderDevice) -> Self {
Self {
render_device,
command_encoder: None,
command_buffers: Vec::new(),
}
}

/// Gets the underlying [`RenderDevice`].
pub fn render_device(&self) -> &RenderDevice {
&self.render_device
}

/// Gets the current [`CommandEncoder`].
pub fn command_encoder(&mut self) -> &mut CommandEncoder {
self.command_encoder.get_or_insert_with(|| {
self.render_device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default())
})
}

/// Creates a new [`TrackedRenderPass`] for the context,
/// configured using the provided `descriptor`.
pub fn begin_tracked_render_pass<'a>(
&'a mut self,
descriptor: RenderPassDescriptor<'a, '_>,
) -> TrackedRenderPass<'a> {
TrackedRenderPass::new(
&self.render_device,
self.command_encoder.begin_render_pass(&descriptor),
)
// Cannot use command_encoder() as we need to split the borrow on self
let command_encoder = self.command_encoder.get_or_insert_with(|| {
self.render_device
.create_command_encoder(&wgpu::CommandEncoderDescriptor::default())
});
let render_pass = command_encoder.begin_render_pass(&descriptor);
TrackedRenderPass::new(&self.render_device, render_pass)
}

/// Append a [`CommandBuffer`] to the queue.
///
/// If present, this will flush the currently unflushed [`CommandEncoder`]
/// into a [`CommandBuffer`] into the queue before append the provided
/// buffer.
pub fn add_command_buffer(&mut self, command_buffer: CommandBuffer) {
self.flush_encoder();
self.command_buffers.push(command_buffer);
}

/// Finalizes the queue and returns the queue of [`CommandBuffer`]s.
pub fn finish(mut self) -> Vec<CommandBuffer> {
self.flush_encoder();
self.command_buffers
}

fn flush_encoder(&mut self) {
if let Some(encoder) = self.command_encoder.take() {
self.command_buffers.push(encoder.finish());
}
}
}
2 changes: 1 addition & 1 deletion examples/shader/compute_shader_game_of_life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl render_graph::Node for GameOfLifeNode {
let pipeline = world.resource::<GameOfLifePipeline>();

let mut pass = render_context
.command_encoder
.command_encoder()
.begin_compute_pass(&ComputePassDescriptor::default());

pass.set_bind_group(0, texture_bind_group, &[]);
Expand Down