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

Native unclipped depth on supported platforms #16095

Merged
merged 11 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions crates/bevy_pbr/src/meshlet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ impl MeshletPlugin {
WgpuFeatures::SHADER_INT64_ATOMIC_MIN_MAX
| WgpuFeatures::SHADER_INT64
| WgpuFeatures::SUBGROUP
| WgpuFeatures::DEPTH_CLIP_CONTROL
| WgpuFeatures::PUSH_CONSTANTS
}
}
Expand Down
37 changes: 5 additions & 32 deletions crates/bevy_pbr/src/meshlet/pipelines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ pub struct MeshletPipelines {
downsample_depth_second_shadow_view: CachedComputePipelineId,
visibility_buffer_software_raster: CachedComputePipelineId,
visibility_buffer_software_raster_depth_only: CachedComputePipelineId,
visibility_buffer_software_raster_depth_only_clamp_ortho: CachedComputePipelineId,
visibility_buffer_hardware_raster: CachedRenderPipelineId,
visibility_buffer_hardware_raster_depth_only: CachedRenderPipelineId,
visibility_buffer_hardware_raster_depth_only_clamp_ortho: CachedRenderPipelineId,
visibility_buffer_hardware_raster_depth_only_unclipped: CachedRenderPipelineId,
resolve_depth: CachedRenderPipelineId,
resolve_depth_shadow_view: CachedRenderPipelineId,
resolve_material_depth: CachedRenderPipelineId,
Expand Down Expand Up @@ -206,28 +205,6 @@ impl FromWorld for MeshletPipelines {
},
),

visibility_buffer_software_raster_depth_only_clamp_ortho: pipeline_cache
.queue_compute_pipeline(ComputePipelineDescriptor {
label: Some(
"meshlet_visibility_buffer_software_raster_depth_only_clamp_ortho_pipeline"
.into(),
),
layout: vec![visibility_buffer_raster_layout.clone()],
push_constant_ranges: vec![],
shader: MESHLET_VISIBILITY_BUFFER_SOFTWARE_RASTER_SHADER_HANDLE,
shader_defs: vec![
"MESHLET_VISIBILITY_BUFFER_RASTER_PASS".into(),
"DEPTH_CLAMP_ORTHO".into(),
if remap_1d_to_2d_dispatch_layout.is_some() {
"MESHLET_2D_DISPATCH"
} else {
""
}
.into(),
],
entry_point: "rasterize_cluster".into(),
}),

visibility_buffer_hardware_raster: pipeline_cache.queue_render_pipeline(
RenderPipelineDescriptor {
label: Some("meshlet_visibility_buffer_hardware_raster_pipeline".into()),
Expand Down Expand Up @@ -312,10 +289,10 @@ impl FromWorld for MeshletPipelines {
},
),

visibility_buffer_hardware_raster_depth_only_clamp_ortho: pipeline_cache
visibility_buffer_hardware_raster_depth_only_unclipped: pipeline_cache
.queue_render_pipeline(RenderPipelineDescriptor {
label: Some(
"meshlet_visibility_buffer_hardware_raster_depth_only_clamp_ortho_pipeline"
"meshlet_visibility_buffer_hardware_raster_depth_only_unclipped_pipeline"
.into(),
),
layout: vec![visibility_buffer_raster_layout],
Expand All @@ -337,7 +314,7 @@ impl FromWorld for MeshletPipelines {
strip_index_format: None,
front_face: FrontFace::Ccw,
cull_mode: Some(Face::Back),
unclipped_depth: false,
unclipped_depth: true,
polygon_mode: PolygonMode::Fill,
conservative: false,
},
Expand Down Expand Up @@ -467,7 +444,6 @@ impl MeshletPipelines {
&ComputePipeline,
&ComputePipeline,
&ComputePipeline,
&ComputePipeline,
&RenderPipeline,
&RenderPipeline,
&RenderPipeline,
Expand All @@ -489,14 +465,11 @@ impl MeshletPipelines {
pipeline_cache.get_compute_pipeline(pipeline.visibility_buffer_software_raster)?,
pipeline_cache
.get_compute_pipeline(pipeline.visibility_buffer_software_raster_depth_only)?,
pipeline_cache.get_compute_pipeline(
pipeline.visibility_buffer_software_raster_depth_only_clamp_ortho,
)?,
pipeline_cache.get_render_pipeline(pipeline.visibility_buffer_hardware_raster)?,
pipeline_cache
.get_render_pipeline(pipeline.visibility_buffer_hardware_raster_depth_only)?,
pipeline_cache.get_render_pipeline(
pipeline.visibility_buffer_hardware_raster_depth_only_clamp_ortho,
pipeline.visibility_buffer_hardware_raster_depth_only_unclipped,
)?,
pipeline_cache.get_render_pipeline(pipeline.resolve_depth)?,
pipeline_cache.get_render_pipeline(pipeline.resolve_depth_shadow_view)?,
Expand Down
20 changes: 2 additions & 18 deletions crates/bevy_pbr/src/meshlet/visibility_buffer_hardware_raster.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ struct VertexOutput {
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
@location(0) @interpolate(flat) packed_ids: u32,
#endif
#ifdef DEPTH_CLAMP_ORTHO
@location(0) unclamped_clip_depth: f32,
#endif
}

@vertex
Expand All @@ -45,34 +42,24 @@ fn vertex(@builtin(instance_index) instance_index: u32, @builtin(vertex_index) v
let vertex_position = get_meshlet_vertex_position(&meshlet, vertex_id);
let world_from_local = affine3_to_square(instance_uniform.world_from_local);
let world_position = mesh_position_local_to_world(world_from_local, vec4(vertex_position, 1.0));
var clip_position = view.clip_from_world * vec4(world_position.xyz, 1.0);
#ifdef DEPTH_CLAMP_ORTHO
let unclamped_clip_depth = clip_position.z;
clip_position.z = min(clip_position.z, 1.0);
#endif
let clip_position = view.clip_from_world * vec4(world_position.xyz, 1.0);

return VertexOutput(
clip_position,
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
(cluster_id << 7u) | triangle_id,
#endif
#ifdef DEPTH_CLAMP_ORTHO
unclamped_clip_depth,
#endif
);
}

@fragment
fn fragment(vertex_output: VertexOutput) {
let frag_coord_1d = u32(vertex_output.position.y) * u32(view.viewport.z) + u32(vertex_output.position.x);
let frag_coord_1d = u32(vertex_output.position.y * view.viewport.z + vertex_output.position.x);

#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
let depth = bitcast<u32>(vertex_output.position.z);
let visibility = (u64(depth) << 32u) | u64(vertex_output.packed_ids);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], visibility);
#else ifdef DEPTH_CLAMP_ORTHO
let depth = bitcast<u32>(vertex_output.unclamped_clip_depth);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
#else
let depth = bitcast<u32>(vertex_output.position.z);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
Expand All @@ -84,9 +71,6 @@ fn dummy_vertex() -> VertexOutput {
vec4(divide(0.0, 0.0)), // NaN vertex position
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
0u,
#endif
#ifdef DEPTH_CLAMP_ORTHO
0.0,
#endif
);
}
Expand Down
26 changes: 9 additions & 17 deletions crates/bevy_pbr/src/meshlet/visibility_buffer_raster_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,9 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
downsample_depth_second_shadow_view_pipeline,
visibility_buffer_software_raster_pipeline,
visibility_buffer_software_raster_depth_only_pipeline,
visibility_buffer_software_raster_depth_only_clamp_ortho,
visibility_buffer_hardware_raster_pipeline,
visibility_buffer_hardware_raster_depth_only_pipeline,
visibility_buffer_hardware_raster_depth_only_clamp_ortho,
visibility_buffer_hardware_raster_depth_only_unclipped_pipeline,
resolve_depth_pipeline,
resolve_depth_shadow_view_pipeline,
resolve_material_depth_pipeline,
Expand Down Expand Up @@ -223,19 +222,12 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
continue;
};

let (
shadow_visibility_buffer_software_raster_pipeline,
shadow_visibility_buffer_hardware_raster_pipeline,
) = match light_type {
LightEntity::Directional { .. } => (
visibility_buffer_software_raster_depth_only_clamp_ortho,
visibility_buffer_hardware_raster_depth_only_clamp_ortho,
),
_ => (
visibility_buffer_software_raster_depth_only_pipeline,
visibility_buffer_hardware_raster_depth_only_pipeline,
),
};
let shadow_visibility_buffer_hardware_raster_pipeline =
if let LightEntity::Directional { .. } = light_type {
visibility_buffer_hardware_raster_depth_only_unclipped_pipeline
} else {
visibility_buffer_hardware_raster_depth_only_pipeline
};

render_context.command_encoder().push_debug_group(&format!(
"meshlet_visibility_buffer_raster: {}",
Expand Down Expand Up @@ -270,7 +262,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
&meshlet_view_resources.dummy_render_target.default_view,
meshlet_view_bind_groups,
view_offset,
shadow_visibility_buffer_software_raster_pipeline,
visibility_buffer_software_raster_depth_only_pipeline,
shadow_visibility_buffer_hardware_raster_pipeline,
None,
meshlet_view_resources.raster_cluster_rightmost_slot,
Expand Down Expand Up @@ -306,7 +298,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
&meshlet_view_resources.dummy_render_target.default_view,
meshlet_view_bind_groups,
view_offset,
shadow_visibility_buffer_software_raster_pipeline,
visibility_buffer_software_raster_depth_only_pipeline,
shadow_visibility_buffer_hardware_raster_pipeline,
None,
meshlet_view_resources.raster_cluster_rightmost_slot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ fn rasterize_cluster(
// Project vertex to viewport space
let world_position = mesh_position_local_to_world(world_from_local, vec4(vertex_position, 1.0));
let clip_position = view.clip_from_world * vec4(world_position.xyz, 1.0);
var ndc_position = clip_position.xyz / clip_position.w;
#ifdef DEPTH_CLAMP_ORTHO
ndc_position.z = 1.0 / clip_position.z;
#endif
let ndc_position = clip_position.xyz / clip_position.w;
let viewport_position_xy = ndc_to_uv(ndc_position.xy) * view.viewport.zw;

// Write vertex to workgroup shared memory
Expand Down Expand Up @@ -176,9 +173,6 @@ fn write_visibility_buffer_pixel(x: f32, y: f32, z: f32, packed_ids: u32) {
let depth = bitcast<u32>(z);
let visibility = (u64(depth) << 32u) | u64(packed_ids);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], visibility);
#else ifdef DEPTH_CLAMP_ORTHO
let depth = bitcast<u32>(1.0 / z);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
#else
let depth = bitcast<u32>(z);
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
Expand Down
21 changes: 18 additions & 3 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ pub struct PrepassPipeline<M: Material> {
pub deferred_material_vertex_shader: Option<Handle<Shader>>,
pub deferred_material_fragment_shader: Option<Handle<Shader>>,
pub material_pipeline: MaterialPipeline<M>,
pub depth_clip_control_supported: bool,
_marker: PhantomData<M>,
}

Expand Down Expand Up @@ -289,6 +290,10 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {

let mesh_pipeline = world.resource::<MeshPipeline>();

let depth_clip_control_supported = render_device
.features()
.contains(WgpuFeatures::DEPTH_CLIP_CONTROL);

PrepassPipeline {
view_layout_motion_vectors,
view_layout_no_motion_vectors,
Expand All @@ -315,6 +320,7 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
},
material_layout: M::bind_group_layout(render_device),
material_pipeline: world.resource::<MaterialPipeline<M>>().clone(),
depth_clip_control_supported,
_marker: PhantomData,
}
}
Expand All @@ -328,7 +334,7 @@ where

fn specialize(
&self,
key: Self::Key,
mut key: Self::Key,
JMS55 marked this conversation as resolved.
Show resolved Hide resolved
layout: &MeshVertexBufferLayoutRef,
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
let mut bind_group_layouts = vec![if key
Expand All @@ -341,6 +347,15 @@ where
}];
let mut shader_defs = Vec::new();
let mut vertex_attributes = Vec::new();
let mut unclipped_depth = false;

// Remove depth clamp in fragment shader if GPU supports it natively
if key.mesh_key.contains(MeshPipelineKey::DEPTH_CLAMP_ORTHO)
&& self.depth_clip_control_supported
{
key.mesh_key.remove(MeshPipelineKey::DEPTH_CLAMP_ORTHO);
unclipped_depth = true;
}

// Let the shader code know that it's running in a prepass pipeline.
// (PBR code will use this to detect that it's running in deferred mode,
Expand Down Expand Up @@ -489,7 +504,7 @@ where

// The fragment shader is only used when the normal prepass or motion vectors prepass
// is enabled or the material uses alpha cutoff values and doesn't rely on the standard
// prepass shader or we are clamping the orthographic depth.
// prepass shader or we are clamping the orthographic depth in the fragment shader.
let fragment_required = !targets.is_empty()
|| key.mesh_key.contains(MeshPipelineKey::DEPTH_CLAMP_ORTHO)
|| (key.mesh_key.contains(MeshPipelineKey::MAY_DISCARD)
Expand Down Expand Up @@ -544,7 +559,7 @@ where
strip_index_format: None,
front_face: FrontFace::Ccw,
cull_mode: None,
unclipped_depth: false,
unclipped_depth,
polygon_mode: PolygonMode::Fill,
conservative: false,
},
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
out.position = position_world_to_clip(out.world_position.xyz);
#ifdef DEPTH_CLAMP_ORTHO
out.clip_position_unclamped = out.position;
out.unclamped_clip_depth = out.position.z;
out.position.z = min(out.position.z, 1.0);
#endif // DEPTH_CLAMP_ORTHO

Expand Down Expand Up @@ -174,7 +174,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput {
#endif

#ifdef DEPTH_CLAMP_ORTHO
out.frag_depth = in.clip_position_unclamped.z;
out.frag_depth = in.unclamped_clip_depth;
#endif // DEPTH_CLAMP_ORTHO

#ifdef MOTION_VECTOR_PREPASS
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/prepass/prepass_io.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct VertexOutput {
#endif

#ifdef DEPTH_CLAMP_ORTHO
@location(6) clip_position_unclamped: vec4<f32>,
@location(6) unclamped_clip_depth: f32,
#endif // DEPTH_CLAMP_ORTHO
#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
@location(7) instance_index: u32,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/pbr_prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn fragment(
var out: prepass_io::FragmentOutput;

#ifdef DEPTH_CLAMP_ORTHO
out.frag_depth = in.clip_position_unclamped.z;
out.frag_depth = in.unclamped_clip_depth;
#endif // DEPTH_CLAMP_ORTHO

#ifdef NORMAL_PREPASS
Expand Down