Skip to content

Commit

Permalink
EntityRenderCommand and PhaseItemRenderCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
cart committed Nov 12, 2021
1 parent 290b7dd commit 33a26a7
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 150 deletions.
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

0 comments on commit 33a26a7

Please sign in to comment.