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

Meshlet prep #11442

Merged
merged 3 commits into from
Jan 22, 2024
Merged
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
5 changes: 3 additions & 2 deletions crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ pub fn prepare_prepass_textures(
.clone()
});

let deferred_lighting_pass_id_texture = deferred_prepass.then(|| {
let cached_deferred_lighting_pass_id_texture = deferred_prepass.then(|| {
deferred_lighting_id_textures
.entry(camera.target.clone())
.or_insert_with(|| {
Expand Down Expand Up @@ -836,7 +836,8 @@ pub fn prepare_prepass_textures(
motion_vectors: cached_motion_vectors_texture
.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
deferred: cached_deferred_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
deferred_lighting_pass_id: deferred_lighting_pass_id_texture,
deferred_lighting_pass_id: cached_deferred_lighting_pass_id_texture
.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
size,
});
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl ViewNode for CopyDeferredLightingIdNode {
let bind_group = render_context.render_device().create_bind_group(
"copy_deferred_lighting_id_bind_group",
&copy_deferred_lighting_id_pipeline.layout,
&BindGroupEntries::single(&deferred_lighting_pass_id_texture.default_view),
&BindGroupEntries::single(&deferred_lighting_pass_id_texture.texture.default_view),
);

let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
Expand Down
18 changes: 5 additions & 13 deletions crates/bevy_core_pipeline/src/deferred/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ use bevy_render::render_graph::ViewNode;
use bevy_render::render_resource::StoreOp;
use bevy_render::{
camera::ExtractedCamera,
prelude::Color,
render_graph::{NodeRunError, RenderGraphContext},
render_phase::RenderPhase,
render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor},
render_resource::RenderPassDescriptor,
renderer::RenderContext,
view::ViewDepthTexture,
};
Expand Down Expand Up @@ -83,11 +82,11 @@ impl ViewNode for DeferredGBufferPrepassNode {
.map(|deferred_texture| {
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
{
RenderPassColorAttachment {
bevy_render::render_resource::RenderPassColorAttachment {
view: &deferred_texture.texture.default_view,
resolve_target: None,
ops: Operations {
load: LoadOp::Load,
ops: bevy_render::render_resource::Operations {
load: bevy_render::render_resource::LoadOp::Load,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why qualify instead of import?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import would be unused on non wasm platforms and give a warning.

store: StoreOp::Store,
},
}
Expand All @@ -101,14 +100,7 @@ impl ViewNode for DeferredGBufferPrepassNode {
view_prepass_textures
.deferred_lighting_pass_id
.as_ref()
.map(|deferred_lighting_pass_id| RenderPassColorAttachment {
view: &deferred_lighting_pass_id.default_view,
resolve_target: None,
ops: Operations {
load: LoadOp::Clear(Color::BLACK.into()),
store: StoreOp::Store,
},
}),
.map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()),
);

if color_attachments.iter().all(Option::is_none) {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use bevy_reflect::Reflect;
use bevy_render::{
render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem},
render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat, TextureView},
texture::{CachedTexture, ColorAttachment},
texture::ColorAttachment,
};
use bevy_utils::{nonmax::NonMaxU32, FloatOrd};

Expand Down Expand Up @@ -78,7 +78,7 @@ pub struct ViewPrepassTextures {
pub deferred: Option<ColorAttachment>,
/// A texture that specifies the deferred lighting pass id for a material.
/// Exists only if [`DeferredPrepass`] is added to the `ViewTarget`
pub deferred_lighting_pass_id: Option<CachedTexture>,
pub deferred_lighting_pass_id: Option<ColorAttachment>,
/// The size of the textures.
pub size: Extent3d,
}
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// Creates the deferred gbuffer from a PbrInput.
fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
// Only monochrome occlusion supported. May not be worth including at all.
// Some models have baked occlusion, GLTF only supports monochrome.
// Some models have baked occlusion, GLTF only supports monochrome.
// Real time occlusion is applied in the deferred lighting pass.
// Deriving luminance via Rec. 709. coefficients
// https://en.wikipedia.org/wiki/Rec._709
Expand All @@ -27,7 +27,7 @@ fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
var props = deferred_types::pack_unorm3x4_plus_unorm_20_(vec4(
in.material.reflectance,
in.material.metallic,
diffuse_occlusion,
diffuse_occlusion,
in.frag_coord.z));
#else
var props = deferred_types::pack_unorm4x8_(vec4(
Expand Down Expand Up @@ -79,7 +79,7 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4<f32>, gbuffer: vec4<u32>) ->
#ifdef WEBGL2 // More crunched for webgl so we can also fit depth.
let props = deferred_types::unpack_unorm3x4_plus_unorm_20_(gbuffer.b);
// Bias to 0.5 since that's the value for almost all materials.
pbr.material.reflectance = saturate(props.r - 0.03333333333);
pbr.material.reflectance = saturate(props.r - 0.03333333333);
#else
let props = deferred_types::unpack_unorm4x8_(gbuffer.b);
pbr.material.reflectance = props.r;
Expand All @@ -92,9 +92,9 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4<f32>, gbuffer: vec4<u32>) ->
let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0);
let is_orthographic = view.projection[3].w == 1.0;
let V = pbr_functions::calculate_view(world_position, is_orthographic);

pbr.frag_coord = frag_coord;
pbr.world_normal = N;
pbr.world_normal = N;
pbr.world_position = world_position;
pbr.N = N;
pbr.V = V;
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,8 +639,8 @@ pub fn prepare_previous_view_projection_uniforms(

#[derive(Default, Resource)]
pub struct PrepassViewBindGroup {
motion_vectors: Option<BindGroup>,
no_motion_vectors: Option<BindGroup>,
pub motion_vectors: Option<BindGroup>,
pub no_motion_vectors: Option<BindGroup>,
}

pub fn prepare_prepass_view_bind_group<M: Material>(
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput {
#ifdef DEFERRED_PREPASS
// There isn't any material info available for this default prepass shader so we are just writing 
// emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer.
// The is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
// This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
// as an example to show that a user could write to the deferred gbuffer if they were to start from this shader.
out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u);
out.deferred_lighting_pass_id = 1u;
Expand Down
57 changes: 44 additions & 13 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bevy_render::{
camera::Camera,
color::Color,
mesh::Mesh,
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::*,
Expand Down Expand Up @@ -48,6 +49,7 @@ pub struct ExtractedDirectionalLight {
shadow_normal_bias: f32,
cascade_shadow_config: CascadeShadowConfig,
cascades: EntityHashMap<Entity, Vec<Cascade>>,
frusta: EntityHashMap<Entity, Vec<Frustum>>,
render_layers: RenderLayers,
}

Expand Down Expand Up @@ -296,6 +298,7 @@ pub fn extract_lights(
&CubemapVisibleEntities,
&GlobalTransform,
&ViewVisibility,
&CubemapFrusta,
)>,
>,
spot_lights: Extract<
Expand All @@ -304,6 +307,7 @@ pub fn extract_lights(
&VisibleEntities,
&GlobalTransform,
&ViewVisibility,
&Frustum,
)>,
>,
directional_lights: Extract<
Expand All @@ -314,6 +318,7 @@ pub fn extract_lights(
&CascadesVisibleEntities,
&Cascades,
&CascadeShadowConfig,
&CascadesFrusta,
&GlobalTransform,
&ViewVisibility,
Option<&RenderLayers>,
Expand Down Expand Up @@ -343,7 +348,7 @@ pub fn extract_lights(

let mut point_lights_values = Vec::with_capacity(*previous_point_lights_len);
for entity in global_point_lights.iter().copied() {
let Ok((point_light, cubemap_visible_entities, transform, view_visibility)) =
let Ok((point_light, cubemap_visible_entities, transform, view_visibility, frusta)) =
point_lights.get(entity)
else {
continue;
Expand Down Expand Up @@ -373,15 +378,19 @@ pub fn extract_lights(
};
point_lights_values.push((
entity,
(extracted_point_light, render_cubemap_visible_entities),
(
extracted_point_light,
render_cubemap_visible_entities,
(*frusta).clone(),
),
));
}
*previous_point_lights_len = point_lights_values.len();
commands.insert_or_spawn_batch(point_lights_values);

let mut spot_lights_values = Vec::with_capacity(*previous_spot_lights_len);
for entity in global_point_lights.iter().copied() {
if let Ok((spot_light, visible_entities, transform, view_visibility)) =
if let Ok((spot_light, visible_entities, transform, view_visibility, frustum)) =
spot_lights.get(entity)
{
if !view_visibility.get() {
Expand Down Expand Up @@ -417,6 +426,7 @@ pub fn extract_lights(
spot_light_angles: Some((spot_light.inner_angle, spot_light.outer_angle)),
},
render_visible_entities,
*frustum,
),
));
}
Expand All @@ -430,6 +440,7 @@ pub fn extract_lights(
visible_entities,
cascades,
cascade_config,
frusta,
transform,
view_visibility,
maybe_layers,
Expand All @@ -452,6 +463,7 @@ pub fn extract_lights(
shadow_normal_bias: directional_light.shadow_normal_bias * std::f32::consts::SQRT_2,
cascade_shadow_config: cascade_config.clone(),
cascades: cascades.cascades.clone(),
frusta: frusta.frusta.clone(),
render_layers: maybe_layers.copied().unwrap_or_default(),
},
render_visible_entities,
Expand Down Expand Up @@ -656,7 +668,11 @@ pub fn prepare_lights(
directional_light_shadow_map: Res<DirectionalLightShadowMap>,
mut max_directional_lights_warning_emitted: Local<bool>,
mut max_cascades_per_light_warning_emitted: Local<bool>,
point_lights: Query<(Entity, &ExtractedPointLight)>,
point_lights: Query<(
Entity,
&ExtractedPointLight,
AnyOf<(&CubemapFrusta, &Frustum)>,
)>,
directional_lights: Query<(Entity, &ExtractedDirectionalLight)>,
) {
let views_iter = views.iter();
Expand Down Expand Up @@ -733,7 +749,7 @@ pub fn prepare_lights(

let spot_light_shadow_maps_count = point_lights
.iter()
.filter(|(_, light)| light.shadows_enabled && light.spot_light_angles.is_some())
.filter(|(_, light, _)| light.shadows_enabled && light.spot_light_angles.is_some())
.count()
.min(max_texture_array_layers - directional_shadow_enabled_count * MAX_CASCADES_PER_LIGHT);

Expand All @@ -742,7 +758,7 @@ pub fn prepare_lights(
// - then those with shadows enabled first, so that the index can be used to render at most `point_light_shadow_maps_count`
// point light shadows and `spot_light_shadow_maps_count` spot light shadow maps,
// - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded.
point_lights.sort_by(|(entity_1, light_1), (entity_2, light_2)| {
point_lights.sort_by(|(entity_1, light_1, _), (entity_2, light_2, _)| {
point_light_order(
(
entity_1,
Expand Down Expand Up @@ -775,7 +791,7 @@ pub fn prepare_lights(
}

let mut gpu_point_lights = Vec::new();
for (index, &(entity, light)) in point_lights.iter().enumerate() {
for (index, &(entity, light, _)) in point_lights.iter().enumerate() {
let mut flags = PointLightFlags::NONE;

// Lights are sorted, shadow enabled lights are first
Expand Down Expand Up @@ -952,11 +968,11 @@ pub fn prepare_lights(
};

// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
for &(light_entity, light) in point_lights
for &(light_entity, light, (point_light_frusta, _)) in point_lights
.iter()
// Lights are sorted, shadow enabled lights are first
.take(point_light_shadow_maps_count)
.filter(|(_, light)| light.shadows_enabled)
.filter(|(_, light, _)| light.shadows_enabled)
{
let light_index = *global_light_meta
.entity_to_index
Expand All @@ -967,7 +983,11 @@ pub fn prepare_lights(
// and ignore rotation because we want the shadow map projections to align with the axes
let view_translation = GlobalTransform::from_translation(light.transform.translation());

for (face_index, view_rotation) in cube_face_rotations.iter().enumerate() {
for (face_index, (view_rotation, frustum)) in cube_face_rotations
.iter()
.zip(&point_light_frusta.unwrap().frusta)
.enumerate()
{
let depth_texture_view =
point_light_depth_texture
.texture
Expand Down Expand Up @@ -1005,6 +1025,7 @@ pub fn prepare_lights(
hdr: false,
color_grading: Default::default(),
},
*frustum,
RenderPhase::<Shadow>::default(),
LightEntity::Point {
light_entity,
Expand All @@ -1017,7 +1038,7 @@ pub fn prepare_lights(
}

// spot lights
for (light_index, &(light_entity, light)) in point_lights
for (light_index, &(light_entity, light, (_, spot_light_frustum))) in point_lights
.iter()
.skip(point_light_count)
.take(spot_light_shadow_maps_count)
Expand Down Expand Up @@ -1063,6 +1084,7 @@ pub fn prepare_lights(
hdr: false,
color_grading: Default::default(),
},
*spot_light_frustum.unwrap(),
RenderPhase::<Shadow>::default(),
LightEntity::Spot { light_entity },
))
Expand All @@ -1078,12 +1100,20 @@ pub fn prepare_lights(
.enumerate()
.take(directional_shadow_enabled_count)
{
for (cascade_index, (cascade, bound)) in light
let cascades = light
.cascades
.get(&entity)
.unwrap()
.iter()
.take(MAX_CASCADES_PER_LIGHT)
.take(MAX_CASCADES_PER_LIGHT);
let frusta = light
.frusta
.get(&entity)
.unwrap()
.iter()
.take(MAX_CASCADES_PER_LIGHT);
for (cascade_index, ((cascade, frusta), bound)) in cascades
.zip(frusta)
.zip(&light.cascade_shadow_config.bounds)
.enumerate()
{
Expand Down Expand Up @@ -1129,6 +1159,7 @@ pub fn prepare_lights(
hdr: false,
color_grading: Default::default(),
},
*frusta,
RenderPhase::<Shadow>::default(),
LightEntity::Directional {
light_entity,
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_render/src/mesh/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,13 @@ pub struct InnerMeshVertexBufferLayout {
}

impl InnerMeshVertexBufferLayout {
pub fn new(attribute_ids: Vec<MeshVertexAttributeId>, layout: VertexBufferLayout) -> Self {
Self {
attribute_ids,
layout,
}
}

#[inline]
pub fn contains(&self, attribute_id: impl Into<MeshVertexAttributeId>) -> bool {
self.attribute_ids.contains(&attribute_id.into())
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ impl Frustum {
}
}

#[derive(Component, Debug, Default, Reflect)]
#[derive(Component, Clone, Debug, Default, Reflect)]
#[reflect(Component)]
pub struct CubemapFrusta {
#[reflect(ignore)]
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/render_resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use uniform_buffer::*;

// TODO: decide where re-exports should go
pub use wgpu::{
util::{BufferInitDescriptor, DrawIndexedIndirect},
util::{BufferInitDescriptor, DrawIndexedIndirect, DrawIndirect},
AdapterInfo as WgpuAdapterInfo, AddressMode, BindGroupDescriptor, BindGroupEntry,
BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent,
BlendFactor, BlendOperation, BlendState, BufferAddress, BufferAsyncError, BufferBinding,
Expand Down
Loading