Move initializing the ComputePipeline and adding to the render graph to build
for gpu_readback
example.
This commit is contained in:
parent
4fc5e440aa
commit
ab5a35a677
@ -15,7 +15,7 @@ use bevy::{
|
|||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderContext, RenderDevice},
|
||||||
storage::{GpuShaderStorageBuffer, ShaderStorageBuffer},
|
storage::{GpuShaderStorageBuffer, ShaderStorageBuffer},
|
||||||
texture::GpuImage,
|
texture::GpuImage,
|
||||||
Render, RenderApp, RenderSystems,
|
Render, RenderApp, RenderStartup, RenderSystems,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,24 +41,22 @@ fn main() {
|
|||||||
// We need a plugin to organize all the systems and render node required for this example
|
// We need a plugin to organize all the systems and render node required for this example
|
||||||
struct GpuReadbackPlugin;
|
struct GpuReadbackPlugin;
|
||||||
impl Plugin for GpuReadbackPlugin {
|
impl Plugin for GpuReadbackPlugin {
|
||||||
fn build(&self, _app: &mut App) {}
|
fn build(&self, app: &mut App) {
|
||||||
|
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||||
fn finish(&self, app: &mut App) {
|
return;
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
};
|
||||||
render_app.init_resource::<ComputePipeline>().add_systems(
|
|
||||||
Render,
|
|
||||||
prepare_bind_group
|
|
||||||
.in_set(RenderSystems::PrepareBindGroups)
|
|
||||||
// We don't need to recreate the bind group every frame
|
|
||||||
.run_if(not(resource_exists::<GpuBufferBindGroup>)),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add the compute node as a top level node to the render graph
|
|
||||||
// This means it will only execute once per frame
|
|
||||||
render_app
|
render_app
|
||||||
.world_mut()
|
.add_systems(
|
||||||
.resource_mut::<RenderGraph>()
|
RenderStartup,
|
||||||
.add_node(ComputeNodeLabel, ComputeNode::default());
|
(init_compute_pipeline, add_compute_render_graph_node),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
Render,
|
||||||
|
prepare_bind_group
|
||||||
|
.in_set(RenderSystems::PrepareBindGroups)
|
||||||
|
// We don't need to recreate the bind group every frame
|
||||||
|
.run_if(not(resource_exists::<GpuBufferBindGroup>)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +125,13 @@ fn setup(
|
|||||||
commands.insert_resource(ReadbackImage(image));
|
commands.insert_resource(ReadbackImage(image));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_compute_render_graph_node(mut render_graph: ResMut<RenderGraph>) {
|
||||||
|
// Add the compute node as a top-level node to the render graph. This means it will only execute
|
||||||
|
// once per frame. Normally, adding a node would use the `RenderGraphApp::add_render_graph_node`
|
||||||
|
// method, but it does not allow adding as a top-level node.
|
||||||
|
render_graph.add_node(ComputeNodeLabel, ComputeNode::default());
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct GpuBufferBindGroup(BindGroup);
|
struct GpuBufferBindGroup(BindGroup);
|
||||||
|
|
||||||
@ -158,29 +163,30 @@ struct ComputePipeline {
|
|||||||
pipeline: CachedComputePipelineId,
|
pipeline: CachedComputePipelineId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for ComputePipeline {
|
fn init_compute_pipeline(
|
||||||
fn from_world(world: &mut World) -> Self {
|
mut commands: Commands,
|
||||||
let render_device = world.resource::<RenderDevice>();
|
render_device: Res<RenderDevice>,
|
||||||
let layout = render_device.create_bind_group_layout(
|
asset_server: Res<AssetServer>,
|
||||||
None,
|
pipeline_cache: Res<PipelineCache>,
|
||||||
&BindGroupLayoutEntries::sequential(
|
) {
|
||||||
ShaderStages::COMPUTE,
|
let layout = render_device.create_bind_group_layout(
|
||||||
(
|
None,
|
||||||
storage_buffer::<Vec<u32>>(false),
|
&BindGroupLayoutEntries::sequential(
|
||||||
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
|
ShaderStages::COMPUTE,
|
||||||
),
|
(
|
||||||
|
storage_buffer::<Vec<u32>>(false),
|
||||||
|
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
let shader = world.load_asset(SHADER_ASSET_PATH);
|
);
|
||||||
let pipeline_cache = world.resource::<PipelineCache>();
|
let shader = asset_server.load(SHADER_ASSET_PATH);
|
||||||
let pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
let pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
||||||
label: Some("GPU readback compute shader".into()),
|
label: Some("GPU readback compute shader".into()),
|
||||||
layout: vec![layout.clone()],
|
layout: vec![layout.clone()],
|
||||||
shader: shader.clone(),
|
shader: shader.clone(),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
ComputePipeline { layout, pipeline }
|
commands.insert_resource(ComputePipeline { layout, pipeline });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Label to identify the node in the render graph
|
/// Label to identify the node in the render graph
|
||||||
|
Loading…
Reference in New Issue
Block a user