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] - EntityRenderCommand and PhaseItemRenderCommand #3111

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions assets/shaders/custom.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ var<uniform> view: View;
struct Mesh {
transform: mat4x4<f32>;
};
[[group(2), binding(0)]]
[[group(1), binding(0)]]
var<uniform> mesh: Mesh;

struct Vertex {
Expand All @@ -37,7 +37,7 @@ fn vertex(vertex: Vertex) -> VertexOutput {
struct CustomMaterial {
color: vec4<f32>;
};
[[group(1), binding(0)]]
[[group(2), binding(0)]]
var<uniform> material: CustomMaterial;

[[stage(fragment)]]
Expand Down
67 changes: 42 additions & 25 deletions examples/shader/custom_shader_pipelined.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
core_pipeline::{SetItemPipeline, Transparent3d},
core_pipeline::Transparent3d,
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
ecs::{
prelude::*,
Expand All @@ -19,11 +19,12 @@ use bevy::{
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
render_component::ExtractComponentPlugin,
render_phase::{
AddRenderCommand, DrawFunctions, RenderCommand, RenderPhase, TrackedRenderPass,
AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderPhase, SetItemPipeline,
TrackedRenderPass,
},
render_resource::*,
renderer::RenderDevice,
view::ExtractedView,
view::{ComputedVisibility, ExtractedView, Msaa, Visibility},
RenderApp, RenderStage,
},
PipelinedDefaultPlugins,
Expand Down Expand Up @@ -51,6 +52,8 @@ fn setup(
meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
Transform::from_xyz(0.0, 0.5, 0.0),
GlobalTransform::default(),
Visibility::default(),
ComputedVisibility::default(),
materials.add(CustomMaterial {
color: Color::GREEN,
}),
Expand Down Expand Up @@ -118,21 +121,36 @@ impl Plugin for CustomMaterialPlugin {
app.sub_app(RenderApp)
.add_render_command::<Transparent3d, DrawCustom>()
.init_resource::<CustomPipeline>()
.init_resource::<SpecializedPipelines<CustomPipeline>>()
.add_system_to_stage(RenderStage::Queue, queue_custom);
}
}

pub struct CustomPipeline {
material_layout: BindGroupLayout,
pipeline: CachedPipelineId,
shader: Handle<Shader>,
pbr_pipeline: PbrPipeline,
}

impl SpecializedPipeline for CustomPipeline {
type Key = PbrPipelineKey;

fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
let mut descriptor = self.pbr_pipeline.specialize(key);
descriptor.vertex.shader = self.shader.clone();
descriptor.fragment.as_mut().unwrap().shader = self.shader.clone();
descriptor.layout = Some(vec![
self.pbr_pipeline.view_layout.clone(),
self.pbr_pipeline.mesh_layout.clone(),
self.material_layout.clone(),
]);
descriptor
}
}

impl FromWorld for CustomPipeline {
fn from_world(world: &mut World) -> Self {
let world = world.cell();
let asset_server = world.get_resource::<AssetServer>().unwrap();
let shader = asset_server.load("shaders/custom.wgsl");

let render_device = world.get_resource::<RenderDevice>().unwrap();
let material_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
entries: &[BindGroupLayoutEntry {
Expand All @@ -148,43 +166,42 @@ impl FromWorld for CustomPipeline {
label: None,
});

let pbr_pipeline = world.get_resource::<PbrPipeline>().unwrap();
let mut descriptor = pbr_pipeline.specialize(PbrPipelineKey::empty());
descriptor.vertex.shader = shader.clone();
descriptor.fragment.as_mut().unwrap().shader = shader;
descriptor.layout = Some(vec![
pbr_pipeline.view_layout.clone(),
material_layout.clone(),
pbr_pipeline.mesh_layout.clone(),
]);

let mut pipeline_cache = world.get_resource_mut::<RenderPipelineCache>().unwrap();
CustomPipeline {
pipeline: pipeline_cache.queue(descriptor),
pbr_pipeline: world.get_resource::<PbrPipeline>().unwrap().clone(),
shader: asset_server.load("shaders/custom.wgsl"),
material_layout,
}
}
}

#[allow(clippy::too_many_arguments)]
pub fn queue_custom(
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
materials: Res<RenderAssets<CustomMaterial>>,
custom_pipeline: Res<CustomPipeline>,
mut pipeline_cache: ResMut<RenderPipelineCache>,
mut specialized_pipelines: ResMut<SpecializedPipelines<CustomPipeline>>,
msaa: Res<Msaa>,
material_meshes: Query<(Entity, &Handle<CustomMaterial>, &MeshUniform), With<Handle<Mesh>>>,
mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>,
) {
let draw_custom = transparent_3d_draw_functions
.read()
.get_id::<DrawCustom>()
.unwrap();
let key = PbrPipelineKey::from_msaa_samples(msaa.samples);
for (view, mut transparent_phase) in views.iter_mut() {
let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2);
for (entity, material_handle, mesh_uniform) in material_meshes.iter() {
if materials.contains_key(material_handle) {
transparent_phase.add(Transparent3d {
entity,
pipeline: custom_pipeline.pipeline,
pipeline: specialized_pipelines.specialize(
&mut pipeline_cache,
&custom_pipeline,
key,
),
draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
});
Expand All @@ -196,25 +213,25 @@ pub fn queue_custom(
type DrawCustom = (
SetItemPipeline,
SetMeshViewBindGroup<0>,
SetTransformBindGroup<1>,
SetCustomMaterialBindGroup,
SetTransformBindGroup<2>,
DrawMesh,
);

struct SetCustomMaterialBindGroup;
impl RenderCommand<Transparent3d> for SetCustomMaterialBindGroup {
impl EntityRenderCommand for SetCustomMaterialBindGroup {
type Param = (
SRes<RenderAssets<CustomMaterial>>,
SQuery<Read<Handle<CustomMaterial>>>,
);
fn render<'w>(
_view: Entity,
item: &Transparent3d,
item: Entity,
(materials, query): SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) {
let material_handle = query.get(item.entity).unwrap();
let material_handle = query.get(item).unwrap();
let material = materials.into_inner().get(material_handle).unwrap();
pass.set_bind_group(1, &material.bind_group, &[]);
pass.set_bind_group(2, &material.bind_group, &[]);
}
}
23 changes: 15 additions & 8 deletions examples/shader/shader_defs_pipelined.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
core_pipeline::{SetItemPipeline, Transparent3d},
core_pipeline::Transparent3d,
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
ecs::prelude::*,
math::Vec3,
Expand All @@ -12,9 +12,9 @@ use bevy::{
camera::PerspectiveCameraBundle,
mesh::{shape, Mesh},
render_component::{ExtractComponent, ExtractComponentPlugin},
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase},
render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline},
render_resource::*,
view::ExtractedView,
view::{ComputedVisibility, ExtractedView, Msaa, Visibility},
RenderApp, RenderStage,
},
PipelinedDefaultPlugins,
Expand Down Expand Up @@ -64,6 +64,8 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
IsRed(true),
Transform::from_xyz(-1.0, 0.5, 0.0),
GlobalTransform::default(),
Visibility::default(),
ComputedVisibility::default(),
));

// blue cube
Expand All @@ -72,6 +74,8 @@ fn setup(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>) {
IsRed(false),
Transform::from_xyz(1.0, 0.5, 0.0),
GlobalTransform::default(),
Visibility::default(),
ComputedVisibility::default(),
));

// camera
Expand Down Expand Up @@ -99,14 +103,14 @@ impl FromWorld for IsRedPipeline {
}

impl SpecializedPipeline for IsRedPipeline {
type Key = IsRed;
type Key = (IsRed, PbrPipelineKey);

fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
fn specialize(&self, (is_red, pbr_pipeline_key): Self::Key) -> RenderPipelineDescriptor {
let mut shader_defs = Vec::new();
if key.0 {
if is_red.0 {
shader_defs.push("IS_RED".to_string());
}
let mut descriptor = self.pbr_pipeline.specialize(PbrPipelineKey::empty());
let mut descriptor = self.pbr_pipeline.specialize(pbr_pipeline_key);
descriptor.vertex.shader = self.shader.clone();
descriptor.vertex.shader_defs = shader_defs.clone();
let fragment = descriptor.fragment.as_mut().unwrap();
Expand All @@ -130,6 +134,7 @@ type DrawIsRed = (
fn queue_custom(
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
custom_pipeline: Res<IsRedPipeline>,
msaa: Res<Msaa>,
mut pipelines: ResMut<SpecializedPipelines<IsRedPipeline>>,
mut pipeline_cache: ResMut<RenderPipelineCache>,
material_meshes: Query<(Entity, &MeshUniform, &IsRed), With<Handle<Mesh>>>,
Expand All @@ -139,11 +144,13 @@ fn queue_custom(
.read()
.get_id::<DrawIsRed>()
.unwrap();
let key = PbrPipelineKey::from_msaa_samples(msaa.samples);
for (view, mut transparent_phase) in views.iter_mut() {
let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2);
for (entity, mesh_uniform, is_red) in material_meshes.iter() {
let pipeline = pipelines.specialize(&mut pipeline_cache, &custom_pipeline, *is_red);
let pipeline =
pipelines.specialize(&mut pipeline_cache, &custom_pipeline, (*is_red, key));
transparent_phase.add(Transparent3d {
entity,
pipeline,
Expand Down
42 changes: 9 additions & 33 deletions pipelined/bevy_core_pipeline/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ pub use main_pass_driver::*;

use bevy_app::{App, Plugin};
use bevy_core::FloatOrd;
use bevy_ecs::{
prelude::*,
system::{lifetimeless::SRes, SystemParamItem},
};
use bevy_ecs::prelude::*;
use bevy_render2::{
camera::{ActiveCameras, CameraPlugin},
color::Color,
render_graph::{EmptyNode, RenderGraph, SlotInfo, SlotType},
render_phase::{
sort_phase_system, DrawFunctionId, DrawFunctions, PhaseItem, RenderCommand, RenderPhase,
TrackedRenderPass,
sort_phase_system, CachedPipelinePhaseItem, DrawFunctionId, DrawFunctions, EntityPhaseItem,
PhaseItem, RenderPhase,
},
render_resource::*,
renderer::RenderDevice,
Expand Down Expand Up @@ -171,38 +168,17 @@ impl PhaseItem for Transparent3d {
}
}

pub struct SetItemPipeline;
impl RenderCommand<Transparent3d> for SetItemPipeline {
type Param = SRes<RenderPipelineCache>;
impl EntityPhaseItem for Transparent3d {
#[inline]
fn render<'w>(
_view: Entity,
item: &Transparent3d,
pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) {
let pipeline = pipeline_cache
.into_inner()
.get_state(item.pipeline)
.unwrap();
pass.set_render_pipeline(pipeline);
fn entity(&self) -> Entity {
self.entity
}
}

impl RenderCommand<Transparent2d> for SetItemPipeline {
type Param = SRes<RenderPipelineCache>;
impl CachedPipelinePhaseItem for Transparent3d {
#[inline]
fn render<'w>(
_view: Entity,
item: &Transparent2d,
pipeline_cache: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) {
let pipeline = pipeline_cache
.into_inner()
.get_state(item.pipeline)
.unwrap();
pass.set_render_pipeline(pipeline);
fn cached_pipeline(&self) -> CachedPipelineId {
self.pipeline
}
}

Expand Down
9 changes: 2 additions & 7 deletions pipelined/bevy_pbr2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,10 @@ impl Plugin for PbrPlugin {
.init_resource::<SpecializedPipelines<PbrPipeline>>()
.init_resource::<SpecializedPipelines<ShadowPipeline>>();

let draw_shadow_mesh = DrawShadowMesh::new(&mut render_app.world);
let shadow_pass_node = ShadowPassNode::new(&mut render_app.world);
render_app.add_render_command::<Transparent3d, DrawPbr>();
let render_world = render_app.world.cell();
let draw_functions = render_world
.get_resource::<DrawFunctions<Shadow>>()
.unwrap();
draw_functions.write().add(draw_shadow_mesh);
let mut graph = render_world.get_resource_mut::<RenderGraph>().unwrap();
render_app.add_render_command::<Shadow, DrawShadowMesh>();
let mut graph = render_app.world.get_resource_mut::<RenderGraph>().unwrap();
let draw_3d_graph = graph
.get_sub_graph_mut(bevy_core_pipeline::draw_3d_graph::NAME)
.unwrap();
Expand Down
Loading