Fix meshlet interactions with regular shading passes (#13816)
* Fixes https://github.com/bevyengine/bevy/issues/13813 * Fixes https://github.com/bevyengine/bevy/issues/13810 Tested a combined scene with both regular meshes and meshlet meshes with: * Regular forward setup * Forward + normal/motion vector prepasses * Deferred (with depth prepass since that's required) * Deferred + depth/normal/motion vector prepasses Still broken: * Using meshlet meshes rendering in deferred and regular meshes rendering in forward + depth/normal prepass. I don't know how to fix this at the moment, so for now I've just add instructions to not mix them.
This commit is contained in:
parent
073db8cf36
commit
b56a693c34
@ -122,17 +122,17 @@ impl ViewNode for DeferredGBufferPrepassNode {
|
|||||||
let view_entity = graph.view_entity();
|
let view_entity = graph.view_entity();
|
||||||
render_context.add_command_buffer_generation_task(move |render_device| {
|
render_context.add_command_buffer_generation_task(move |render_device| {
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let _deferred_span = info_span!("deferred").entered();
|
let _deferred_span = info_span!("deferred_prepass").entered();
|
||||||
|
|
||||||
// Command encoder setup
|
// Command encoder setup
|
||||||
let mut command_encoder =
|
let mut command_encoder =
|
||||||
render_device.create_command_encoder(&CommandEncoderDescriptor {
|
render_device.create_command_encoder(&CommandEncoderDescriptor {
|
||||||
label: Some("deferred_command_encoder"),
|
label: Some("deferred_prepass_command_encoder"),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Render pass setup
|
// Render pass setup
|
||||||
let render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor {
|
let render_pass = command_encoder.begin_render_pass(&RenderPassDescriptor {
|
||||||
label: Some("deferred"),
|
label: Some("deferred_prepass"),
|
||||||
color_attachments: &color_attachments,
|
color_attachments: &color_attachments,
|
||||||
depth_stencil_attachment,
|
depth_stencil_attachment,
|
||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
@ -148,20 +148,20 @@ impl ViewNode for DeferredGBufferPrepassNode {
|
|||||||
|| !opaque_deferred_phase.unbatchable_keys.is_empty()
|
|| !opaque_deferred_phase.unbatchable_keys.is_empty()
|
||||||
{
|
{
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let _opaque_prepass_span = info_span!("opaque_deferred").entered();
|
let _opaque_prepass_span = info_span!("opaque_deferred_prepass").entered();
|
||||||
opaque_deferred_phase.render(&mut render_pass, world, view_entity);
|
opaque_deferred_phase.render(&mut render_pass, world, view_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alpha masked draws
|
// Alpha masked draws
|
||||||
if !alpha_mask_deferred_phase.is_empty() {
|
if !alpha_mask_deferred_phase.is_empty() {
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let _alpha_mask_deferred_span = info_span!("alpha_mask_deferred").entered();
|
let _alpha_mask_deferred_span = info_span!("alpha_mask_deferred_prepass").entered();
|
||||||
alpha_mask_deferred_phase.render(&mut render_pass, world, view_entity);
|
alpha_mask_deferred_phase.render(&mut render_pass, world, view_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(render_pass);
|
drop(render_pass);
|
||||||
|
|
||||||
// Copy prepass depth to the main depth texture
|
// After rendering to the view depth texture, copy it to the prepass depth texture
|
||||||
if let Some(prepass_depth_texture) = &view_prepass_textures.depth {
|
if let Some(prepass_depth_texture) = &view_prepass_textures.depth {
|
||||||
command_encoder.copy_texture_to_texture(
|
command_encoder.copy_texture_to_texture(
|
||||||
view_depth_texture.texture.as_image_copy(),
|
view_depth_texture.texture.as_image_copy(),
|
||||||
|
@ -162,7 +162,7 @@ impl ViewNode for PrepassNode {
|
|||||||
pass_span.end(&mut render_pass);
|
pass_span.end(&mut render_pass);
|
||||||
drop(render_pass);
|
drop(render_pass);
|
||||||
|
|
||||||
// Copy prepass depth to the main depth texture if deferred isn't going to
|
// After rendering to the view depth texture, copy it to the prepass depth texture if deferred isn't going to
|
||||||
if deferred_prepass.is_none() {
|
if deferred_prepass.is_none() {
|
||||||
if let Some(prepass_depth_texture) = &view_prepass_textures.depth {
|
if let Some(prepass_depth_texture) = &view_prepass_textures.depth {
|
||||||
command_encoder.copy_texture_to_texture(
|
command_encoder.copy_texture_to_texture(
|
||||||
|
@ -10,8 +10,13 @@ use crate::{
|
|||||||
MeshViewBindGroup, PrepassViewBindGroup, ViewFogUniformOffset, ViewLightProbesUniformOffset,
|
MeshViewBindGroup, PrepassViewBindGroup, ViewFogUniformOffset, ViewLightProbesUniformOffset,
|
||||||
ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,
|
ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,
|
||||||
};
|
};
|
||||||
use bevy_core_pipeline::prepass::{PreviousViewUniformOffset, ViewPrepassTextures};
|
use bevy_core_pipeline::prepass::{
|
||||||
use bevy_ecs::{query::QueryItem, world::World};
|
MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures,
|
||||||
|
};
|
||||||
|
use bevy_ecs::{
|
||||||
|
query::{Has, QueryItem},
|
||||||
|
world::World,
|
||||||
|
};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::ExtractedCamera,
|
camera::ExtractedCamera,
|
||||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||||
@ -138,7 +143,8 @@ impl ViewNode for MeshletPrepassNode {
|
|||||||
&'static ExtractedCamera,
|
&'static ExtractedCamera,
|
||||||
&'static ViewPrepassTextures,
|
&'static ViewPrepassTextures,
|
||||||
&'static ViewUniformOffset,
|
&'static ViewUniformOffset,
|
||||||
Option<&'static PreviousViewUniformOffset>,
|
&'static PreviousViewUniformOffset,
|
||||||
|
Has<MotionVectorPrepass>,
|
||||||
&'static MeshletViewMaterialsPrepass,
|
&'static MeshletViewMaterialsPrepass,
|
||||||
&'static MeshletViewBindGroups,
|
&'static MeshletViewBindGroups,
|
||||||
&'static MeshletViewResources,
|
&'static MeshletViewResources,
|
||||||
@ -153,6 +159,7 @@ impl ViewNode for MeshletPrepassNode {
|
|||||||
view_prepass_textures,
|
view_prepass_textures,
|
||||||
view_uniform_offset,
|
view_uniform_offset,
|
||||||
previous_view_uniform_offset,
|
previous_view_uniform_offset,
|
||||||
|
view_has_motion_vector_prepass,
|
||||||
meshlet_view_materials,
|
meshlet_view_materials,
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
meshlet_view_resources,
|
meshlet_view_resources,
|
||||||
@ -212,7 +219,7 @@ impl ViewNode for MeshletPrepassNode {
|
|||||||
render_pass.set_camera_viewport(viewport);
|
render_pass.set_camera_viewport(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(previous_view_uniform_offset) = previous_view_uniform_offset {
|
if view_has_motion_vector_prepass {
|
||||||
render_pass.set_bind_group(
|
render_pass.set_bind_group(
|
||||||
0,
|
0,
|
||||||
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
|
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
|
||||||
@ -259,7 +266,8 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
|||||||
&'static ExtractedCamera,
|
&'static ExtractedCamera,
|
||||||
&'static ViewPrepassTextures,
|
&'static ViewPrepassTextures,
|
||||||
&'static ViewUniformOffset,
|
&'static ViewUniformOffset,
|
||||||
Option<&'static PreviousViewUniformOffset>,
|
&'static PreviousViewUniformOffset,
|
||||||
|
Has<MotionVectorPrepass>,
|
||||||
&'static MeshletViewMaterialsDeferredGBufferPrepass,
|
&'static MeshletViewMaterialsDeferredGBufferPrepass,
|
||||||
&'static MeshletViewBindGroups,
|
&'static MeshletViewBindGroups,
|
||||||
&'static MeshletViewResources,
|
&'static MeshletViewResources,
|
||||||
@ -274,6 +282,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
|||||||
view_prepass_textures,
|
view_prepass_textures,
|
||||||
view_uniform_offset,
|
view_uniform_offset,
|
||||||
previous_view_uniform_offset,
|
previous_view_uniform_offset,
|
||||||
|
view_has_motion_vector_prepass,
|
||||||
meshlet_view_materials,
|
meshlet_view_materials,
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
meshlet_view_resources,
|
meshlet_view_resources,
|
||||||
@ -338,7 +347,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
|||||||
render_pass.set_camera_viewport(viewport);
|
render_pass.set_camera_viewport(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(previous_view_uniform_offset) = previous_view_uniform_offset {
|
if view_has_motion_vector_prepass {
|
||||||
render_pass.set_bind_group(
|
render_pass.set_bind_group(
|
||||||
0,
|
0,
|
||||||
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
|
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
|
||||||
|
@ -142,7 +142,8 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if material.properties.alpha_mode != AlphaMode::Opaque
|
if material.properties.render_method != OpaqueRendererMethod::Forward
|
||||||
|
|| material.properties.alpha_mode != AlphaMode::Opaque
|
||||||
|| material.properties.reads_view_transmission_texture
|
|| material.properties.reads_view_transmission_texture
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -109,6 +109,10 @@ const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> =
|
|||||||
///
|
///
|
||||||
/// This plugin does not work on WASM.
|
/// This plugin does not work on WASM.
|
||||||
///
|
///
|
||||||
|
/// Mixing forward+prepass and deferred rendering for opaque materials is not currently supported when using this plugin.
|
||||||
|
/// You must use one or the other by setting [`crate::DefaultOpaqueRendererMethod`].
|
||||||
|
/// Do not override [`crate::Material::opaque_render_method`] for any material when using this plugin.
|
||||||
|
///
|
||||||
/// 
|
/// 
|
||||||
pub struct MeshletPlugin;
|
pub struct MeshletPlugin;
|
||||||
|
|
||||||
@ -206,18 +210,18 @@ impl Plugin for MeshletPlugin {
|
|||||||
.add_render_graph_edges(
|
.add_render_graph_edges(
|
||||||
Core3d,
|
Core3d,
|
||||||
(
|
(
|
||||||
// TODO: Meshlet VisibilityBufferRaster should be after main pass when not using depth prepass
|
// Non-meshlet shading passes _must_ come before meshlet shading passes
|
||||||
NodePbr::ShadowPass,
|
NodePbr::ShadowPass,
|
||||||
Node3d::Prepass,
|
|
||||||
Node3d::DeferredPrepass,
|
|
||||||
NodeMeshlet::VisibilityBufferRasterPass,
|
NodeMeshlet::VisibilityBufferRasterPass,
|
||||||
NodeMeshlet::Prepass,
|
NodeMeshlet::Prepass,
|
||||||
|
Node3d::Prepass,
|
||||||
NodeMeshlet::DeferredPrepass,
|
NodeMeshlet::DeferredPrepass,
|
||||||
|
Node3d::DeferredPrepass,
|
||||||
Node3d::CopyDeferredLightingId,
|
Node3d::CopyDeferredLightingId,
|
||||||
Node3d::EndPrepasses,
|
Node3d::EndPrepasses,
|
||||||
Node3d::StartMainPass,
|
Node3d::StartMainPass,
|
||||||
Node3d::MainOpaquePass,
|
|
||||||
NodeMeshlet::MainOpaquePass,
|
NodeMeshlet::MainOpaquePass,
|
||||||
|
Node3d::MainOpaquePass,
|
||||||
Node3d::EndMainPass,
|
Node3d::EndMainPass,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user