Meshlet texture atomics (#17765)
* Use texture atomics rather than buffer atomics for the visbuffer (haven't tested perf on a raster-heavy scene yet) * Unfortunately to clear the visbuffer we now need a compute pass to clear it. Using wgpu's clear_texture function internally uses a buffer -> image copy that's insanely expensive. Ideally it should be using vkCmdClearColorImage, which I've opened an issue for https://github.com/gfx-rs/wgpu/issues/7090. For now we'll have to stick with a custom compute pass and all the extra code that brings. * Faster resolve depth pass by discarding 0 depth pixels instead of redundantly writing zero (2x faster for big depth textures like shadow views)
This commit is contained in:
parent
2f9613f22c
commit
2fd4cc4937
@ -1,8 +1,8 @@
|
|||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
@group(0) @binding(0) var<storage, read> mip_0: array<u64>; // Per pixel
|
@group(0) @binding(0) var mip_0: texture_storage_2d<r64uint, read>;
|
||||||
#else
|
#else
|
||||||
#ifdef MESHLET
|
#ifdef MESHLET
|
||||||
@group(0) @binding(0) var<storage, read> mip_0: array<u32>; // Per pixel
|
@group(0) @binding(0) var mip_0: texture_storage_2d<r32uint, read>;
|
||||||
#else // MESHLET
|
#else // MESHLET
|
||||||
#ifdef MULTISAMPLE
|
#ifdef MULTISAMPLE
|
||||||
@group(0) @binding(0) var mip_0: texture_depth_multisampled_2d;
|
@group(0) @binding(0) var mip_0: texture_depth_multisampled_2d;
|
||||||
@ -24,7 +24,7 @@
|
|||||||
@group(0) @binding(11) var mip_11: texture_storage_2d<r32float, write>;
|
@group(0) @binding(11) var mip_11: texture_storage_2d<r32float, write>;
|
||||||
@group(0) @binding(12) var mip_12: texture_storage_2d<r32float, write>;
|
@group(0) @binding(12) var mip_12: texture_storage_2d<r32float, write>;
|
||||||
@group(0) @binding(13) var samplr: sampler;
|
@group(0) @binding(13) var samplr: sampler;
|
||||||
struct Constants { max_mip_level: u32, view_width: u32 }
|
struct Constants { max_mip_level: u32 }
|
||||||
var<push_constant> constants: Constants;
|
var<push_constant> constants: Constants;
|
||||||
|
|
||||||
/// Generates a hierarchical depth buffer.
|
/// Generates a hierarchical depth buffer.
|
||||||
@ -39,7 +39,6 @@ var<workgroup> intermediate_memory: array<array<f32, 16>, 16>;
|
|||||||
@compute
|
@compute
|
||||||
@workgroup_size(256, 1, 1)
|
@workgroup_size(256, 1, 1)
|
||||||
fn downsample_depth_first(
|
fn downsample_depth_first(
|
||||||
@builtin(num_workgroups) num_workgroups: vec3u,
|
|
||||||
@builtin(workgroup_id) workgroup_id: vec3u,
|
@builtin(workgroup_id) workgroup_id: vec3u,
|
||||||
@builtin(local_invocation_index) local_invocation_index: u32,
|
@builtin(local_invocation_index) local_invocation_index: u32,
|
||||||
) {
|
) {
|
||||||
@ -309,12 +308,13 @@ fn reduce_load_mip_6(tex: vec2u) -> f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_mip_0(x: u32, y: u32) -> f32 {
|
fn load_mip_0(x: u32, y: u32) -> f32 {
|
||||||
let i = y * constants.view_width + x;
|
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
return bitcast<f32>(u32(mip_0[i] >> 32u));
|
let visibility = textureLoad(mip_0, vec2(x, y)).r;
|
||||||
|
return bitcast<f32>(u32(visibility >> 32u));
|
||||||
#else // MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#else // MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
#ifdef MESHLET
|
#ifdef MESHLET
|
||||||
return bitcast<f32>(mip_0[i]);
|
let visibility = textureLoad(mip_0, vec2(x, y)).r;
|
||||||
|
return bitcast<f32>(visibility);
|
||||||
#else // MESHLET
|
#else // MESHLET
|
||||||
// Downsample the top level.
|
// Downsample the top level.
|
||||||
#ifdef MULTISAMPLE
|
#ifdef MULTISAMPLE
|
||||||
|
@ -427,7 +427,7 @@ impl SpecializedComputePipeline for DownsampleDepthPipeline {
|
|||||||
layout: vec![self.bind_group_layout.clone()],
|
layout: vec![self.bind_group_layout.clone()],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..8,
|
range: 0..4,
|
||||||
}],
|
}],
|
||||||
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
||||||
shader_defs,
|
shader_defs,
|
||||||
@ -627,9 +627,8 @@ impl ViewDepthPyramid {
|
|||||||
timestamp_writes: None,
|
timestamp_writes: None,
|
||||||
});
|
});
|
||||||
downsample_pass.set_pipeline(downsample_depth_first_pipeline);
|
downsample_pass.set_pipeline(downsample_depth_first_pipeline);
|
||||||
// Pass the mip count and the texture width as push constants, for
|
// Pass the mip count as a push constant, for simplicity.
|
||||||
// simplicity.
|
downsample_pass.set_push_constants(0, &self.mip_count.to_le_bytes());
|
||||||
downsample_pass.set_push_constants(0, bytemuck::cast_slice(&[self.mip_count, view_size.x]));
|
|
||||||
downsample_pass.set_bind_group(0, downsample_depth_bind_group, &[]);
|
downsample_pass.set_bind_group(0, downsample_depth_bind_group, &[]);
|
||||||
downsample_pass.dispatch_workgroups(view_size.x.div_ceil(64), view_size.y.div_ceil(64), 1);
|
downsample_pass.dispatch_workgroups(view_size.x.div_ceil(64), view_size.y.div_ceil(64), 1);
|
||||||
|
|
||||||
|
18
crates/bevy_pbr/src/meshlet/clear_visibility_buffer.wgsl
Normal file
18
crates/bevy_pbr/src/meshlet/clear_visibility_buffer.wgsl
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
|
@group(0) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r64uint, write>;
|
||||||
|
#else
|
||||||
|
@group(0) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r32uint, write>;
|
||||||
|
#endif
|
||||||
|
var<push_constant> view_size: vec2<u32>;
|
||||||
|
|
||||||
|
@compute
|
||||||
|
@workgroup_size(16, 16, 1)
|
||||||
|
fn clear_visibility_buffer(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
||||||
|
if any(global_id.xy >= view_size) { return; }
|
||||||
|
|
||||||
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
|
textureStore(meshlet_visibility_buffer, global_id.xy, vec4(0lu));
|
||||||
|
#else
|
||||||
|
textureStore(meshlet_visibility_buffer, global_id.xy, vec4(0u));
|
||||||
|
#endif
|
||||||
|
}
|
@ -100,9 +100,9 @@ fn cluster_is_second_pass_candidate(cluster_id: u32) -> bool {
|
|||||||
@group(0) @binding(6) var<storage, read> meshlet_raster_clusters: array<u32>; // Single object shared between all workgroups
|
@group(0) @binding(6) var<storage, read> meshlet_raster_clusters: array<u32>; // Single object shared between all workgroups
|
||||||
@group(0) @binding(7) var<storage, read> meshlet_software_raster_cluster_count: u32;
|
@group(0) @binding(7) var<storage, read> meshlet_software_raster_cluster_count: u32;
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
@group(0) @binding(8) var<storage, read_write> meshlet_visibility_buffer: array<atomic<u64>>; // Per pixel
|
@group(0) @binding(8) var meshlet_visibility_buffer: texture_storage_2d<r64uint, atomic>;
|
||||||
#else
|
#else
|
||||||
@group(0) @binding(8) var<storage, read_write> meshlet_visibility_buffer: array<atomic<u32>>; // Per pixel
|
@group(0) @binding(8) var meshlet_visibility_buffer: texture_storage_2d<r32uint, atomic>;
|
||||||
#endif
|
#endif
|
||||||
@group(0) @binding(9) var<uniform> view: View;
|
@group(0) @binding(9) var<uniform> view: View;
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ fn get_meshlet_vertex_position(meshlet: ptr<function, Meshlet>, vertex_id: u32)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MESHLET_MESH_MATERIAL_PASS
|
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||||
@group(1) @binding(0) var<storage, read> meshlet_visibility_buffer: array<u64>; // Per pixel
|
@group(1) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r64uint, read>;
|
||||||
@group(1) @binding(1) var<storage, read> meshlet_cluster_meshlet_ids: array<u32>; // Per cluster
|
@group(1) @binding(1) var<storage, read> meshlet_cluster_meshlet_ids: array<u32>; // Per cluster
|
||||||
@group(1) @binding(2) var<storage, read> meshlets: array<Meshlet>; // Per meshlet
|
@group(1) @binding(2) var<storage, read> meshlets: array<Meshlet>; // Per meshlet
|
||||||
@group(1) @binding(3) var<storage, read> meshlet_indices: array<u32>; // Many per meshlet
|
@group(1) @binding(3) var<storage, read> meshlet_indices: array<u32>; // Many per meshlet
|
||||||
|
@ -106,9 +106,9 @@ const MESHLET_MESH_MATERIAL_SHADER_HANDLE: Handle<Shader> =
|
|||||||
/// * Requires preprocessing meshes. See [`MeshletMesh`] for details.
|
/// * Requires preprocessing meshes. See [`MeshletMesh`] for details.
|
||||||
/// * Limitations on the kinds of materials you can use. See [`MeshletMesh`] for details.
|
/// * Limitations on the kinds of materials you can use. See [`MeshletMesh`] for details.
|
||||||
///
|
///
|
||||||
/// This plugin requires a fairly recent GPU that supports [`WgpuFeatures::SHADER_INT64_ATOMIC_MIN_MAX`].
|
/// This plugin requires a fairly recent GPU that supports [`WgpuFeatures::TEXTURE_INT64_ATOMIC`].
|
||||||
///
|
///
|
||||||
/// This plugin currently works only on the Vulkan backend.
|
/// This plugin currently works only on the Vulkan and Metal backends.
|
||||||
///
|
///
|
||||||
/// This plugin is not compatible with [`Msaa`]. Any camera rendering a [`MeshletMesh`] must have
|
/// This plugin is not compatible with [`Msaa`]. Any camera rendering a [`MeshletMesh`] must have
|
||||||
/// [`Msaa`] set to [`Msaa::Off`].
|
/// [`Msaa`] set to [`Msaa::Off`].
|
||||||
@ -133,7 +133,8 @@ pub struct MeshletPlugin {
|
|||||||
impl MeshletPlugin {
|
impl MeshletPlugin {
|
||||||
/// [`WgpuFeatures`] required for this plugin to function.
|
/// [`WgpuFeatures`] required for this plugin to function.
|
||||||
pub fn required_wgpu_features() -> WgpuFeatures {
|
pub fn required_wgpu_features() -> WgpuFeatures {
|
||||||
WgpuFeatures::SHADER_INT64_ATOMIC_MIN_MAX
|
WgpuFeatures::TEXTURE_INT64_ATOMIC
|
||||||
|
| WgpuFeatures::TEXTURE_ATOMIC
|
||||||
| WgpuFeatures::SHADER_INT64
|
| WgpuFeatures::SHADER_INT64
|
||||||
| WgpuFeatures::SUBGROUP
|
| WgpuFeatures::SUBGROUP
|
||||||
| WgpuFeatures::DEPTH_CLIP_CONTROL
|
| WgpuFeatures::DEPTH_CLIP_CONTROL
|
||||||
@ -151,6 +152,12 @@ impl Plugin for MeshletPlugin {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_internal_asset!(
|
||||||
|
app,
|
||||||
|
MESHLET_CLEAR_VISIBILITY_BUFFER_SHADER_HANDLE,
|
||||||
|
"clear_visibility_buffer.wgsl",
|
||||||
|
Shader::from_wgsl
|
||||||
|
);
|
||||||
load_internal_asset!(
|
load_internal_asset!(
|
||||||
app,
|
app,
|
||||||
MESHLET_BINDINGS_SHADER_HANDLE,
|
MESHLET_BINDINGS_SHADER_HANDLE,
|
||||||
|
@ -10,6 +10,8 @@ use bevy_ecs::{
|
|||||||
};
|
};
|
||||||
use bevy_render::render_resource::*;
|
use bevy_render::render_resource::*;
|
||||||
|
|
||||||
|
pub const MESHLET_CLEAR_VISIBILITY_BUFFER_SHADER_HANDLE: Handle<Shader> =
|
||||||
|
weak_handle!("a4bf48e4-5605-4d1c-987e-29c7b1ec95dc");
|
||||||
pub const MESHLET_FILL_CLUSTER_BUFFERS_SHADER_HANDLE: Handle<Shader> =
|
pub const MESHLET_FILL_CLUSTER_BUFFERS_SHADER_HANDLE: Handle<Shader> =
|
||||||
weak_handle!("80ccea4a-8234-4ee0-af74-77b3cad503cf");
|
weak_handle!("80ccea4a-8234-4ee0-af74-77b3cad503cf");
|
||||||
pub const MESHLET_CULLING_SHADER_HANDLE: Handle<Shader> =
|
pub const MESHLET_CULLING_SHADER_HANDLE: Handle<Shader> =
|
||||||
@ -26,6 +28,8 @@ pub const MESHLET_REMAP_1D_TO_2D_DISPATCH_SHADER_HANDLE: Handle<Shader> =
|
|||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct MeshletPipelines {
|
pub struct MeshletPipelines {
|
||||||
fill_cluster_buffers: CachedComputePipelineId,
|
fill_cluster_buffers: CachedComputePipelineId,
|
||||||
|
clear_visibility_buffer: CachedComputePipelineId,
|
||||||
|
clear_visibility_buffer_shadow_view: CachedComputePipelineId,
|
||||||
cull_first: CachedComputePipelineId,
|
cull_first: CachedComputePipelineId,
|
||||||
cull_second: CachedComputePipelineId,
|
cull_second: CachedComputePipelineId,
|
||||||
downsample_depth_first: CachedComputePipelineId,
|
downsample_depth_first: CachedComputePipelineId,
|
||||||
@ -33,10 +37,10 @@ pub struct MeshletPipelines {
|
|||||||
downsample_depth_first_shadow_view: CachedComputePipelineId,
|
downsample_depth_first_shadow_view: CachedComputePipelineId,
|
||||||
downsample_depth_second_shadow_view: CachedComputePipelineId,
|
downsample_depth_second_shadow_view: CachedComputePipelineId,
|
||||||
visibility_buffer_software_raster: CachedComputePipelineId,
|
visibility_buffer_software_raster: CachedComputePipelineId,
|
||||||
visibility_buffer_software_raster_depth_only: CachedComputePipelineId,
|
visibility_buffer_software_raster_shadow_view: CachedComputePipelineId,
|
||||||
visibility_buffer_hardware_raster: CachedRenderPipelineId,
|
visibility_buffer_hardware_raster: CachedRenderPipelineId,
|
||||||
visibility_buffer_hardware_raster_depth_only: CachedRenderPipelineId,
|
visibility_buffer_hardware_raster_shadow_view: CachedRenderPipelineId,
|
||||||
visibility_buffer_hardware_raster_depth_only_unclipped: CachedRenderPipelineId,
|
visibility_buffer_hardware_raster_shadow_view_unclipped: CachedRenderPipelineId,
|
||||||
resolve_depth: CachedRenderPipelineId,
|
resolve_depth: CachedRenderPipelineId,
|
||||||
resolve_depth_shadow_view: CachedRenderPipelineId,
|
resolve_depth_shadow_view: CachedRenderPipelineId,
|
||||||
resolve_material_depth: CachedRenderPipelineId,
|
resolve_material_depth: CachedRenderPipelineId,
|
||||||
@ -49,12 +53,27 @@ impl FromWorld for MeshletPipelines {
|
|||||||
let fill_cluster_buffers_bind_group_layout = resource_manager
|
let fill_cluster_buffers_bind_group_layout = resource_manager
|
||||||
.fill_cluster_buffers_bind_group_layout
|
.fill_cluster_buffers_bind_group_layout
|
||||||
.clone();
|
.clone();
|
||||||
|
let clear_visibility_buffer_bind_group_layout = resource_manager
|
||||||
|
.clear_visibility_buffer_bind_group_layout
|
||||||
|
.clone();
|
||||||
|
let clear_visibility_buffer_shadow_view_bind_group_layout = resource_manager
|
||||||
|
.clear_visibility_buffer_shadow_view_bind_group_layout
|
||||||
|
.clone();
|
||||||
let cull_layout = resource_manager.culling_bind_group_layout.clone();
|
let cull_layout = resource_manager.culling_bind_group_layout.clone();
|
||||||
let downsample_depth_layout = resource_manager.downsample_depth_bind_group_layout.clone();
|
let downsample_depth_layout = resource_manager.downsample_depth_bind_group_layout.clone();
|
||||||
|
let downsample_depth_shadow_view_layout = resource_manager
|
||||||
|
.downsample_depth_shadow_view_bind_group_layout
|
||||||
|
.clone();
|
||||||
let visibility_buffer_raster_layout = resource_manager
|
let visibility_buffer_raster_layout = resource_manager
|
||||||
.visibility_buffer_raster_bind_group_layout
|
.visibility_buffer_raster_bind_group_layout
|
||||||
.clone();
|
.clone();
|
||||||
|
let visibility_buffer_raster_shadow_view_layout = resource_manager
|
||||||
|
.visibility_buffer_raster_shadow_view_bind_group_layout
|
||||||
|
.clone();
|
||||||
let resolve_depth_layout = resource_manager.resolve_depth_bind_group_layout.clone();
|
let resolve_depth_layout = resource_manager.resolve_depth_bind_group_layout.clone();
|
||||||
|
let resolve_depth_shadow_view_layout = resource_manager
|
||||||
|
.resolve_depth_shadow_view_bind_group_layout
|
||||||
|
.clone();
|
||||||
let resolve_material_depth_layout = resource_manager
|
let resolve_material_depth_layout = resource_manager
|
||||||
.resolve_material_depth_bind_group_layout
|
.resolve_material_depth_bind_group_layout
|
||||||
.clone();
|
.clone();
|
||||||
@ -67,7 +86,7 @@ impl FromWorld for MeshletPipelines {
|
|||||||
fill_cluster_buffers: pipeline_cache.queue_compute_pipeline(
|
fill_cluster_buffers: pipeline_cache.queue_compute_pipeline(
|
||||||
ComputePipelineDescriptor {
|
ComputePipelineDescriptor {
|
||||||
label: Some("meshlet_fill_cluster_buffers_pipeline".into()),
|
label: Some("meshlet_fill_cluster_buffers_pipeline".into()),
|
||||||
layout: vec![fill_cluster_buffers_bind_group_layout.clone()],
|
layout: vec![fill_cluster_buffers_bind_group_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..4,
|
range: 0..4,
|
||||||
@ -79,6 +98,36 @@ impl FromWorld for MeshletPipelines {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
clear_visibility_buffer: pipeline_cache.queue_compute_pipeline(
|
||||||
|
ComputePipelineDescriptor {
|
||||||
|
label: Some("meshlet_clear_visibility_buffer_pipeline".into()),
|
||||||
|
layout: vec![clear_visibility_buffer_bind_group_layout],
|
||||||
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
|
stages: ShaderStages::COMPUTE,
|
||||||
|
range: 0..8,
|
||||||
|
}],
|
||||||
|
shader: MESHLET_CLEAR_VISIBILITY_BUFFER_SHADER_HANDLE,
|
||||||
|
shader_defs: vec!["MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT".into()],
|
||||||
|
entry_point: "clear_visibility_buffer".into(),
|
||||||
|
zero_initialize_workgroup_memory: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
clear_visibility_buffer_shadow_view: pipeline_cache.queue_compute_pipeline(
|
||||||
|
ComputePipelineDescriptor {
|
||||||
|
label: Some("meshlet_clear_visibility_buffer_shadow_view_pipeline".into()),
|
||||||
|
layout: vec![clear_visibility_buffer_shadow_view_bind_group_layout],
|
||||||
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
|
stages: ShaderStages::COMPUTE,
|
||||||
|
range: 0..8,
|
||||||
|
}],
|
||||||
|
shader: MESHLET_CLEAR_VISIBILITY_BUFFER_SHADER_HANDLE,
|
||||||
|
shader_defs: vec![],
|
||||||
|
entry_point: "clear_visibility_buffer".into(),
|
||||||
|
zero_initialize_workgroup_memory: false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
cull_first: pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
cull_first: pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
||||||
label: Some("meshlet_culling_first_pipeline".into()),
|
label: Some("meshlet_culling_first_pipeline".into()),
|
||||||
layout: vec![cull_layout.clone()],
|
layout: vec![cull_layout.clone()],
|
||||||
@ -117,7 +166,7 @@ impl FromWorld for MeshletPipelines {
|
|||||||
layout: vec![downsample_depth_layout.clone()],
|
layout: vec![downsample_depth_layout.clone()],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..8,
|
range: 0..4,
|
||||||
}],
|
}],
|
||||||
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
||||||
shader_defs: vec![
|
shader_defs: vec![
|
||||||
@ -135,7 +184,7 @@ impl FromWorld for MeshletPipelines {
|
|||||||
layout: vec![downsample_depth_layout.clone()],
|
layout: vec![downsample_depth_layout.clone()],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..8,
|
range: 0..4,
|
||||||
}],
|
}],
|
||||||
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
||||||
shader_defs: vec![
|
shader_defs: vec![
|
||||||
@ -150,10 +199,10 @@ impl FromWorld for MeshletPipelines {
|
|||||||
downsample_depth_first_shadow_view: pipeline_cache.queue_compute_pipeline(
|
downsample_depth_first_shadow_view: pipeline_cache.queue_compute_pipeline(
|
||||||
ComputePipelineDescriptor {
|
ComputePipelineDescriptor {
|
||||||
label: Some("meshlet_downsample_depth_first_pipeline".into()),
|
label: Some("meshlet_downsample_depth_first_pipeline".into()),
|
||||||
layout: vec![downsample_depth_layout.clone()],
|
layout: vec![downsample_depth_shadow_view_layout.clone()],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..8,
|
range: 0..4,
|
||||||
}],
|
}],
|
||||||
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
||||||
shader_defs: vec!["MESHLET".into()],
|
shader_defs: vec!["MESHLET".into()],
|
||||||
@ -165,10 +214,10 @@ impl FromWorld for MeshletPipelines {
|
|||||||
downsample_depth_second_shadow_view: pipeline_cache.queue_compute_pipeline(
|
downsample_depth_second_shadow_view: pipeline_cache.queue_compute_pipeline(
|
||||||
ComputePipelineDescriptor {
|
ComputePipelineDescriptor {
|
||||||
label: Some("meshlet_downsample_depth_second_pipeline".into()),
|
label: Some("meshlet_downsample_depth_second_pipeline".into()),
|
||||||
layout: vec![downsample_depth_layout],
|
layout: vec![downsample_depth_shadow_view_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::COMPUTE,
|
stages: ShaderStages::COMPUTE,
|
||||||
range: 0..8,
|
range: 0..4,
|
||||||
}],
|
}],
|
||||||
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
shader: DOWNSAMPLE_DEPTH_SHADER_HANDLE,
|
||||||
shader_defs: vec!["MESHLET".into()],
|
shader_defs: vec!["MESHLET".into()],
|
||||||
@ -198,12 +247,12 @@ impl FromWorld for MeshletPipelines {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
visibility_buffer_software_raster_depth_only: pipeline_cache.queue_compute_pipeline(
|
visibility_buffer_software_raster_shadow_view: pipeline_cache.queue_compute_pipeline(
|
||||||
ComputePipelineDescriptor {
|
ComputePipelineDescriptor {
|
||||||
label: Some(
|
label: Some(
|
||||||
"meshlet_visibility_buffer_software_raster_depth_only_pipeline".into(),
|
"meshlet_visibility_buffer_software_raster_shadow_view_pipeline".into(),
|
||||||
),
|
),
|
||||||
layout: vec![visibility_buffer_raster_layout.clone()],
|
layout: vec![visibility_buffer_raster_shadow_view_layout.clone()],
|
||||||
push_constant_ranges: vec![],
|
push_constant_ranges: vec![],
|
||||||
shader: MESHLET_VISIBILITY_BUFFER_SOFTWARE_RASTER_SHADER_HANDLE,
|
shader: MESHLET_VISIBILITY_BUFFER_SOFTWARE_RASTER_SHADER_HANDLE,
|
||||||
shader_defs: vec![
|
shader_defs: vec![
|
||||||
@ -265,12 +314,12 @@ impl FromWorld for MeshletPipelines {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
visibility_buffer_hardware_raster_depth_only: pipeline_cache.queue_render_pipeline(
|
visibility_buffer_hardware_raster_shadow_view: pipeline_cache.queue_render_pipeline(
|
||||||
RenderPipelineDescriptor {
|
RenderPipelineDescriptor {
|
||||||
label: Some(
|
label: Some(
|
||||||
"meshlet_visibility_buffer_hardware_raster_depth_only_pipeline".into(),
|
"meshlet_visibility_buffer_hardware_raster_shadow_view_pipeline".into(),
|
||||||
),
|
),
|
||||||
layout: vec![visibility_buffer_raster_layout.clone()],
|
layout: vec![visibility_buffer_raster_shadow_view_layout.clone()],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::VERTEX,
|
stages: ShaderStages::VERTEX,
|
||||||
range: 0..4,
|
range: 0..4,
|
||||||
@ -306,13 +355,13 @@ impl FromWorld for MeshletPipelines {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
visibility_buffer_hardware_raster_depth_only_unclipped: pipeline_cache
|
visibility_buffer_hardware_raster_shadow_view_unclipped: pipeline_cache
|
||||||
.queue_render_pipeline(RenderPipelineDescriptor {
|
.queue_render_pipeline(RenderPipelineDescriptor {
|
||||||
label: Some(
|
label: Some(
|
||||||
"meshlet_visibility_buffer_hardware_raster_depth_only_unclipped_pipeline"
|
"meshlet_visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline"
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
layout: vec![visibility_buffer_raster_layout],
|
layout: vec![visibility_buffer_raster_shadow_view_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![PushConstantRange {
|
||||||
stages: ShaderStages::VERTEX,
|
stages: ShaderStages::VERTEX,
|
||||||
range: 0..4,
|
range: 0..4,
|
||||||
@ -349,17 +398,14 @@ impl FromWorld for MeshletPipelines {
|
|||||||
|
|
||||||
resolve_depth: pipeline_cache.queue_render_pipeline(RenderPipelineDescriptor {
|
resolve_depth: pipeline_cache.queue_render_pipeline(RenderPipelineDescriptor {
|
||||||
label: Some("meshlet_resolve_depth_pipeline".into()),
|
label: Some("meshlet_resolve_depth_pipeline".into()),
|
||||||
layout: vec![resolve_depth_layout.clone()],
|
layout: vec![resolve_depth_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![],
|
||||||
stages: ShaderStages::FRAGMENT,
|
|
||||||
range: 0..4,
|
|
||||||
}],
|
|
||||||
vertex: fullscreen_shader_vertex_state(),
|
vertex: fullscreen_shader_vertex_state(),
|
||||||
primitive: PrimitiveState::default(),
|
primitive: PrimitiveState::default(),
|
||||||
depth_stencil: Some(DepthStencilState {
|
depth_stencil: Some(DepthStencilState {
|
||||||
format: CORE_3D_DEPTH_FORMAT,
|
format: CORE_3D_DEPTH_FORMAT,
|
||||||
depth_write_enabled: true,
|
depth_write_enabled: true,
|
||||||
depth_compare: CompareFunction::GreaterEqual,
|
depth_compare: CompareFunction::Always,
|
||||||
stencil: StencilState::default(),
|
stencil: StencilState::default(),
|
||||||
bias: DepthBiasState::default(),
|
bias: DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
@ -376,17 +422,14 @@ impl FromWorld for MeshletPipelines {
|
|||||||
resolve_depth_shadow_view: pipeline_cache.queue_render_pipeline(
|
resolve_depth_shadow_view: pipeline_cache.queue_render_pipeline(
|
||||||
RenderPipelineDescriptor {
|
RenderPipelineDescriptor {
|
||||||
label: Some("meshlet_resolve_depth_pipeline".into()),
|
label: Some("meshlet_resolve_depth_pipeline".into()),
|
||||||
layout: vec![resolve_depth_layout],
|
layout: vec![resolve_depth_shadow_view_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![],
|
||||||
stages: ShaderStages::FRAGMENT,
|
|
||||||
range: 0..4,
|
|
||||||
}],
|
|
||||||
vertex: fullscreen_shader_vertex_state(),
|
vertex: fullscreen_shader_vertex_state(),
|
||||||
primitive: PrimitiveState::default(),
|
primitive: PrimitiveState::default(),
|
||||||
depth_stencil: Some(DepthStencilState {
|
depth_stencil: Some(DepthStencilState {
|
||||||
format: CORE_3D_DEPTH_FORMAT,
|
format: CORE_3D_DEPTH_FORMAT,
|
||||||
depth_write_enabled: true,
|
depth_write_enabled: true,
|
||||||
depth_compare: CompareFunction::GreaterEqual,
|
depth_compare: CompareFunction::Always,
|
||||||
stencil: StencilState::default(),
|
stencil: StencilState::default(),
|
||||||
bias: DepthBiasState::default(),
|
bias: DepthBiasState::default(),
|
||||||
}),
|
}),
|
||||||
@ -405,10 +448,7 @@ impl FromWorld for MeshletPipelines {
|
|||||||
RenderPipelineDescriptor {
|
RenderPipelineDescriptor {
|
||||||
label: Some("meshlet_resolve_material_depth_pipeline".into()),
|
label: Some("meshlet_resolve_material_depth_pipeline".into()),
|
||||||
layout: vec![resolve_material_depth_layout],
|
layout: vec![resolve_material_depth_layout],
|
||||||
push_constant_ranges: vec![PushConstantRange {
|
push_constant_ranges: vec![],
|
||||||
stages: ShaderStages::FRAGMENT,
|
|
||||||
range: 0..4,
|
|
||||||
}],
|
|
||||||
vertex: fullscreen_shader_vertex_state(),
|
vertex: fullscreen_shader_vertex_state(),
|
||||||
primitive: PrimitiveState::default(),
|
primitive: PrimitiveState::default(),
|
||||||
depth_stencil: Some(DepthStencilState {
|
depth_stencil: Some(DepthStencilState {
|
||||||
@ -460,6 +500,8 @@ impl MeshletPipelines {
|
|||||||
&ComputePipeline,
|
&ComputePipeline,
|
||||||
&ComputePipeline,
|
&ComputePipeline,
|
||||||
&ComputePipeline,
|
&ComputePipeline,
|
||||||
|
&ComputePipeline,
|
||||||
|
&ComputePipeline,
|
||||||
&RenderPipeline,
|
&RenderPipeline,
|
||||||
&RenderPipeline,
|
&RenderPipeline,
|
||||||
&RenderPipeline,
|
&RenderPipeline,
|
||||||
@ -472,6 +514,8 @@ impl MeshletPipelines {
|
|||||||
let pipeline = world.get_resource::<Self>()?;
|
let pipeline = world.get_resource::<Self>()?;
|
||||||
Some((
|
Some((
|
||||||
pipeline_cache.get_compute_pipeline(pipeline.fill_cluster_buffers)?,
|
pipeline_cache.get_compute_pipeline(pipeline.fill_cluster_buffers)?,
|
||||||
|
pipeline_cache.get_compute_pipeline(pipeline.clear_visibility_buffer)?,
|
||||||
|
pipeline_cache.get_compute_pipeline(pipeline.clear_visibility_buffer_shadow_view)?,
|
||||||
pipeline_cache.get_compute_pipeline(pipeline.cull_first)?,
|
pipeline_cache.get_compute_pipeline(pipeline.cull_first)?,
|
||||||
pipeline_cache.get_compute_pipeline(pipeline.cull_second)?,
|
pipeline_cache.get_compute_pipeline(pipeline.cull_second)?,
|
||||||
pipeline_cache.get_compute_pipeline(pipeline.downsample_depth_first)?,
|
pipeline_cache.get_compute_pipeline(pipeline.downsample_depth_first)?,
|
||||||
@ -480,12 +524,12 @@ impl MeshletPipelines {
|
|||||||
pipeline_cache.get_compute_pipeline(pipeline.downsample_depth_second_shadow_view)?,
|
pipeline_cache.get_compute_pipeline(pipeline.downsample_depth_second_shadow_view)?,
|
||||||
pipeline_cache.get_compute_pipeline(pipeline.visibility_buffer_software_raster)?,
|
pipeline_cache.get_compute_pipeline(pipeline.visibility_buffer_software_raster)?,
|
||||||
pipeline_cache
|
pipeline_cache
|
||||||
.get_compute_pipeline(pipeline.visibility_buffer_software_raster_depth_only)?,
|
.get_compute_pipeline(pipeline.visibility_buffer_software_raster_shadow_view)?,
|
||||||
pipeline_cache.get_render_pipeline(pipeline.visibility_buffer_hardware_raster)?,
|
pipeline_cache.get_render_pipeline(pipeline.visibility_buffer_hardware_raster)?,
|
||||||
pipeline_cache
|
pipeline_cache
|
||||||
.get_render_pipeline(pipeline.visibility_buffer_hardware_raster_depth_only)?,
|
.get_render_pipeline(pipeline.visibility_buffer_hardware_raster_shadow_view)?,
|
||||||
pipeline_cache.get_render_pipeline(
|
pipeline_cache.get_render_pipeline(
|
||||||
pipeline.visibility_buffer_hardware_raster_depth_only_unclipped,
|
pipeline.visibility_buffer_hardware_raster_shadow_view_unclipped,
|
||||||
)?,
|
)?,
|
||||||
pipeline_cache.get_render_pipeline(pipeline.resolve_depth)?,
|
pipeline_cache.get_render_pipeline(pipeline.resolve_depth)?,
|
||||||
pipeline_cache.get_render_pipeline(pipeline.resolve_depth_shadow_view)?,
|
pipeline_cache.get_render_pipeline(pipeline.resolve_depth_shadow_view)?,
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
#import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput
|
#import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput
|
||||||
|
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
@group(0) @binding(0) var<storage, read> meshlet_visibility_buffer: array<u64>; // Per pixel
|
@group(0) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r64uint, read>;
|
||||||
#else
|
#else
|
||||||
@group(0) @binding(0) var<storage, read> meshlet_visibility_buffer: array<u32>; // Per pixel
|
@group(0) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r32uint, read>;
|
||||||
#endif
|
#endif
|
||||||
@group(0) @binding(1) var<storage, read> meshlet_cluster_instance_ids: array<u32>; // Per cluster
|
@group(0) @binding(1) var<storage, read> meshlet_cluster_instance_ids: array<u32>; // Per cluster
|
||||||
@group(0) @binding(2) var<storage, read> meshlet_instance_material_ids: array<u32>; // Per entity instance
|
@group(0) @binding(2) var<storage, read> meshlet_instance_material_ids: array<u32>; // Per entity instance
|
||||||
var<push_constant> view_width: u32;
|
|
||||||
|
|
||||||
/// This pass writes out the depth texture.
|
/// This pass writes out the depth texture.
|
||||||
@fragment
|
@fragment
|
||||||
fn resolve_depth(in: FullscreenVertexOutput) -> @builtin(frag_depth) f32 {
|
fn resolve_depth(in: FullscreenVertexOutput) -> @builtin(frag_depth) f32 {
|
||||||
let frag_coord_1d = u32(in.position.y) * view_width + u32(in.position.x);
|
let visibility = textureLoad(meshlet_visibility_buffer, vec2<u32>(in.position.xy)).r;
|
||||||
let visibility = meshlet_visibility_buffer[frag_coord_1d];
|
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
return bitcast<f32>(u32(visibility >> 32u));
|
let depth = u32(visibility >> 32u);
|
||||||
#else
|
#else
|
||||||
return bitcast<f32>(visibility);
|
let depth = visibility;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if depth == 0u { discard; }
|
||||||
|
|
||||||
|
return bitcast<f32>(depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This pass writes out the material depth texture.
|
/// This pass writes out the material depth texture.
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
@fragment
|
@fragment
|
||||||
fn resolve_material_depth(in: FullscreenVertexOutput) -> @builtin(frag_depth) f32 {
|
fn resolve_material_depth(in: FullscreenVertexOutput) -> @builtin(frag_depth) f32 {
|
||||||
let frag_coord_1d = u32(in.position.y) * view_width + u32(in.position.x);
|
let visibility = textureLoad(meshlet_visibility_buffer, vec2<u32>(in.position.xy)).r;
|
||||||
let visibility = meshlet_visibility_buffer[frag_coord_1d];
|
|
||||||
|
|
||||||
let depth = visibility >> 32u;
|
let depth = visibility >> 32u;
|
||||||
if depth == 0lu { return 0.0; }
|
if depth == 0lu { discard; }
|
||||||
|
|
||||||
let cluster_id = u32(visibility) >> 7u;
|
let cluster_id = u32(visibility) >> 7u;
|
||||||
let instance_id = meshlet_cluster_instance_ids[cluster_id];
|
let instance_id = meshlet_cluster_instance_ids[cluster_id];
|
||||||
|
@ -50,10 +50,15 @@ pub struct ResourceManager {
|
|||||||
|
|
||||||
// Bind group layouts
|
// Bind group layouts
|
||||||
pub fill_cluster_buffers_bind_group_layout: BindGroupLayout,
|
pub fill_cluster_buffers_bind_group_layout: BindGroupLayout,
|
||||||
|
pub clear_visibility_buffer_bind_group_layout: BindGroupLayout,
|
||||||
|
pub clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayout,
|
||||||
pub culling_bind_group_layout: BindGroupLayout,
|
pub culling_bind_group_layout: BindGroupLayout,
|
||||||
pub visibility_buffer_raster_bind_group_layout: BindGroupLayout,
|
pub visibility_buffer_raster_bind_group_layout: BindGroupLayout,
|
||||||
|
pub visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayout,
|
||||||
pub downsample_depth_bind_group_layout: BindGroupLayout,
|
pub downsample_depth_bind_group_layout: BindGroupLayout,
|
||||||
|
pub downsample_depth_shadow_view_bind_group_layout: BindGroupLayout,
|
||||||
pub resolve_depth_bind_group_layout: BindGroupLayout,
|
pub resolve_depth_bind_group_layout: BindGroupLayout,
|
||||||
|
pub resolve_depth_shadow_view_bind_group_layout: BindGroupLayout,
|
||||||
pub resolve_material_depth_bind_group_layout: BindGroupLayout,
|
pub resolve_material_depth_bind_group_layout: BindGroupLayout,
|
||||||
pub material_shade_bind_group_layout: BindGroupLayout,
|
pub material_shade_bind_group_layout: BindGroupLayout,
|
||||||
pub remap_1d_to_2d_dispatch_bind_group_layout: Option<BindGroupLayout>,
|
pub remap_1d_to_2d_dispatch_bind_group_layout: Option<BindGroupLayout>,
|
||||||
@ -108,6 +113,21 @@ impl ResourceManager {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
clear_visibility_buffer_bind_group_layout: render_device.create_bind_group_layout(
|
||||||
|
"meshlet_clear_visibility_buffer_bind_group_layout",
|
||||||
|
&BindGroupLayoutEntries::single(
|
||||||
|
ShaderStages::COMPUTE,
|
||||||
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::WriteOnly),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
clear_visibility_buffer_shadow_view_bind_group_layout: render_device
|
||||||
|
.create_bind_group_layout(
|
||||||
|
"meshlet_clear_visibility_buffer_shadow_view_bind_group_layout",
|
||||||
|
&BindGroupLayoutEntries::single(
|
||||||
|
ShaderStages::COMPUTE,
|
||||||
|
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
|
||||||
|
),
|
||||||
|
),
|
||||||
culling_bind_group_layout: render_device.create_bind_group_layout(
|
culling_bind_group_layout: render_device.create_bind_group_layout(
|
||||||
"meshlet_culling_bind_group_layout",
|
"meshlet_culling_bind_group_layout",
|
||||||
&BindGroupLayoutEntries::sequential(
|
&BindGroupLayoutEntries::sequential(
|
||||||
@ -136,7 +156,34 @@ impl ResourceManager {
|
|||||||
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)
|
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
storage_buffer_read_only_sized(false, None),
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
texture_storage_2d(
|
||||||
|
TextureFormat::R32Float,
|
||||||
|
StorageTextureAccess::ReadWrite,
|
||||||
|
),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
write_only_r32float(),
|
||||||
|
sampler(SamplerBindingType::NonFiltering),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
downsample_depth_shadow_view_bind_group_layout: render_device.create_bind_group_layout(
|
||||||
|
"meshlet_downsample_depth_shadow_view_bind_group_layout",
|
||||||
|
&BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {
|
||||||
|
let write_only_r32float = || {
|
||||||
|
texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)
|
||||||
|
};
|
||||||
|
(
|
||||||
|
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),
|
||||||
write_only_r32float(),
|
write_only_r32float(),
|
||||||
write_only_r32float(),
|
write_only_r32float(),
|
||||||
write_only_r32float(),
|
write_only_r32float(),
|
||||||
@ -169,7 +216,29 @@ impl ResourceManager {
|
|||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_sized(false, None),
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::Atomic),
|
||||||
|
uniform_buffer::<ViewUniform>(true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
visibility_buffer_raster_shadow_view_bind_group_layout: render_device
|
||||||
|
.create_bind_group_layout(
|
||||||
|
"meshlet_visibility_buffer_raster_shadow_view_bind_group_layout",
|
||||||
|
&BindGroupLayoutEntries::sequential(
|
||||||
|
ShaderStages::all(),
|
||||||
|
(
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
storage_buffer_read_only_sized(false, None),
|
||||||
|
texture_storage_2d(
|
||||||
|
TextureFormat::R32Uint,
|
||||||
|
StorageTextureAccess::Atomic,
|
||||||
|
),
|
||||||
uniform_buffer::<ViewUniform>(true),
|
uniform_buffer::<ViewUniform>(true),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -178,7 +247,14 @@ impl ResourceManager {
|
|||||||
"meshlet_resolve_depth_bind_group_layout",
|
"meshlet_resolve_depth_bind_group_layout",
|
||||||
&BindGroupLayoutEntries::single(
|
&BindGroupLayoutEntries::single(
|
||||||
ShaderStages::FRAGMENT,
|
ShaderStages::FRAGMENT,
|
||||||
storage_buffer_read_only_sized(false, None),
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
resolve_depth_shadow_view_bind_group_layout: render_device.create_bind_group_layout(
|
||||||
|
"meshlet_resolve_depth_shadow_view_bind_group_layout",
|
||||||
|
&BindGroupLayoutEntries::single(
|
||||||
|
ShaderStages::FRAGMENT,
|
||||||
|
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
resolve_material_depth_bind_group_layout: render_device.create_bind_group_layout(
|
resolve_material_depth_bind_group_layout: render_device.create_bind_group_layout(
|
||||||
@ -186,7 +262,7 @@ impl ResourceManager {
|
|||||||
&BindGroupLayoutEntries::sequential(
|
&BindGroupLayoutEntries::sequential(
|
||||||
ShaderStages::FRAGMENT,
|
ShaderStages::FRAGMENT,
|
||||||
(
|
(
|
||||||
storage_buffer_read_only_sized(false, None),
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
),
|
),
|
||||||
@ -197,7 +273,7 @@ impl ResourceManager {
|
|||||||
&BindGroupLayoutEntries::sequential(
|
&BindGroupLayoutEntries::sequential(
|
||||||
ShaderStages::FRAGMENT,
|
ShaderStages::FRAGMENT,
|
||||||
(
|
(
|
||||||
storage_buffer_read_only_sized(false, None),
|
texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
storage_buffer_read_only_sized(false, None),
|
storage_buffer_read_only_sized(false, None),
|
||||||
@ -234,7 +310,7 @@ pub struct MeshletViewResources {
|
|||||||
pub second_pass_candidates_buffer: Buffer,
|
pub second_pass_candidates_buffer: Buffer,
|
||||||
instance_visibility: Buffer,
|
instance_visibility: Buffer,
|
||||||
pub dummy_render_target: CachedTexture,
|
pub dummy_render_target: CachedTexture,
|
||||||
pub visibility_buffer: Buffer,
|
pub visibility_buffer: CachedTexture,
|
||||||
pub visibility_buffer_software_raster_indirect_args_first: Buffer,
|
pub visibility_buffer_software_raster_indirect_args_first: Buffer,
|
||||||
pub visibility_buffer_software_raster_indirect_args_second: Buffer,
|
pub visibility_buffer_software_raster_indirect_args_second: Buffer,
|
||||||
pub visibility_buffer_hardware_raster_indirect_args_first: Buffer,
|
pub visibility_buffer_hardware_raster_indirect_args_first: Buffer,
|
||||||
@ -244,12 +320,14 @@ pub struct MeshletViewResources {
|
|||||||
pub material_depth: Option<CachedTexture>,
|
pub material_depth: Option<CachedTexture>,
|
||||||
pub view_size: UVec2,
|
pub view_size: UVec2,
|
||||||
pub raster_cluster_rightmost_slot: u32,
|
pub raster_cluster_rightmost_slot: u32,
|
||||||
|
not_shadow_view: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct MeshletViewBindGroups {
|
pub struct MeshletViewBindGroups {
|
||||||
pub first_node: Arc<AtomicBool>,
|
pub first_node: Arc<AtomicBool>,
|
||||||
pub fill_cluster_buffers: BindGroup,
|
pub fill_cluster_buffers: BindGroup,
|
||||||
|
pub clear_visibility_buffer: BindGroup,
|
||||||
pub culling_first: BindGroup,
|
pub culling_first: BindGroup,
|
||||||
pub culling_second: BindGroup,
|
pub culling_second: BindGroup,
|
||||||
pub downsample_depth: BindGroup,
|
pub downsample_depth: BindGroup,
|
||||||
@ -419,18 +497,27 @@ pub fn prepare_meshlet_per_frame_resources(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let type_size = if not_shadow_view {
|
let visibility_buffer = texture_cache.get(
|
||||||
size_of::<u64>()
|
&render_device,
|
||||||
} else {
|
TextureDescriptor {
|
||||||
size_of::<u32>()
|
|
||||||
} as u64;
|
|
||||||
// TODO: Cache
|
|
||||||
let visibility_buffer = render_device.create_buffer(&BufferDescriptor {
|
|
||||||
label: Some("meshlet_visibility_buffer"),
|
label: Some("meshlet_visibility_buffer"),
|
||||||
size: type_size * (view.viewport.z * view.viewport.w) as u64,
|
size: Extent3d {
|
||||||
usage: BufferUsages::STORAGE,
|
width: view.viewport.z,
|
||||||
mapped_at_creation: false,
|
height: view.viewport.w,
|
||||||
});
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: 1,
|
||||||
|
dimension: TextureDimension::D2,
|
||||||
|
format: if not_shadow_view {
|
||||||
|
TextureFormat::R64Uint
|
||||||
|
} else {
|
||||||
|
TextureFormat::R32Uint
|
||||||
|
},
|
||||||
|
usage: TextureUsages::STORAGE_ATOMIC | TextureUsages::STORAGE_BINDING,
|
||||||
|
view_formats: &[],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let visibility_buffer_software_raster_indirect_args_first = render_device
|
let visibility_buffer_software_raster_indirect_args_first = render_device
|
||||||
.create_buffer_with_data(&BufferInitDescriptor {
|
.create_buffer_with_data(&BufferInitDescriptor {
|
||||||
@ -520,6 +607,7 @@ pub fn prepare_meshlet_per_frame_resources(
|
|||||||
.then(|| texture_cache.get(&render_device, material_depth)),
|
.then(|| texture_cache.get(&render_device, material_depth)),
|
||||||
view_size: view.viewport.zw(),
|
view_size: view.viewport.zw(),
|
||||||
raster_cluster_rightmost_slot: resource_manager.raster_cluster_rightmost_slot,
|
raster_cluster_rightmost_slot: resource_manager.raster_cluster_rightmost_slot,
|
||||||
|
not_shadow_view,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -577,6 +665,16 @@ pub fn prepare_meshlet_view_bind_groups(
|
|||||||
&entries,
|
&entries,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let clear_visibility_buffer = render_device.create_bind_group(
|
||||||
|
"meshlet_clear_visibility_buffer_bind_group",
|
||||||
|
if view_resources.not_shadow_view {
|
||||||
|
&resource_manager.clear_visibility_buffer_bind_group_layout
|
||||||
|
} else {
|
||||||
|
&resource_manager.clear_visibility_buffer_shadow_view_bind_group_layout
|
||||||
|
},
|
||||||
|
&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),
|
||||||
|
);
|
||||||
|
|
||||||
let entries = BindGroupEntries::sequential((
|
let entries = BindGroupEntries::sequential((
|
||||||
cluster_meshlet_ids.as_entire_binding(),
|
cluster_meshlet_ids.as_entire_binding(),
|
||||||
meshlet_mesh_manager.meshlet_bounding_spheres.binding(),
|
meshlet_mesh_manager.meshlet_bounding_spheres.binding(),
|
||||||
@ -638,8 +736,12 @@ pub fn prepare_meshlet_view_bind_groups(
|
|||||||
let downsample_depth = view_resources.depth_pyramid.create_bind_group(
|
let downsample_depth = view_resources.depth_pyramid.create_bind_group(
|
||||||
&render_device,
|
&render_device,
|
||||||
"meshlet_downsample_depth_bind_group",
|
"meshlet_downsample_depth_bind_group",
|
||||||
&resource_manager.downsample_depth_bind_group_layout,
|
if view_resources.not_shadow_view {
|
||||||
view_resources.visibility_buffer.as_entire_binding(),
|
&resource_manager.downsample_depth_bind_group_layout
|
||||||
|
} else {
|
||||||
|
&resource_manager.downsample_depth_shadow_view_bind_group_layout
|
||||||
|
},
|
||||||
|
&view_resources.visibility_buffer.default_view,
|
||||||
&resource_manager.depth_pyramid_sampler,
|
&resource_manager.depth_pyramid_sampler,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -656,24 +758,32 @@ pub fn prepare_meshlet_view_bind_groups(
|
|||||||
resource_manager
|
resource_manager
|
||||||
.software_raster_cluster_count
|
.software_raster_cluster_count
|
||||||
.as_entire_binding(),
|
.as_entire_binding(),
|
||||||
view_resources.visibility_buffer.as_entire_binding(),
|
&view_resources.visibility_buffer.default_view,
|
||||||
view_uniforms.clone(),
|
view_uniforms.clone(),
|
||||||
));
|
));
|
||||||
let visibility_buffer_raster = render_device.create_bind_group(
|
let visibility_buffer_raster = render_device.create_bind_group(
|
||||||
"meshlet_visibility_raster_buffer_bind_group",
|
"meshlet_visibility_raster_buffer_bind_group",
|
||||||
&resource_manager.visibility_buffer_raster_bind_group_layout,
|
if view_resources.not_shadow_view {
|
||||||
|
&resource_manager.visibility_buffer_raster_bind_group_layout
|
||||||
|
} else {
|
||||||
|
&resource_manager.visibility_buffer_raster_shadow_view_bind_group_layout
|
||||||
|
},
|
||||||
&entries,
|
&entries,
|
||||||
);
|
);
|
||||||
|
|
||||||
let resolve_depth = render_device.create_bind_group(
|
let resolve_depth = render_device.create_bind_group(
|
||||||
"meshlet_resolve_depth_bind_group",
|
"meshlet_resolve_depth_bind_group",
|
||||||
&resource_manager.resolve_depth_bind_group_layout,
|
if view_resources.not_shadow_view {
|
||||||
&BindGroupEntries::single(view_resources.visibility_buffer.as_entire_binding()),
|
&resource_manager.resolve_depth_bind_group_layout
|
||||||
|
} else {
|
||||||
|
&resource_manager.resolve_depth_shadow_view_bind_group_layout
|
||||||
|
},
|
||||||
|
&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),
|
||||||
);
|
);
|
||||||
|
|
||||||
let resolve_material_depth = view_resources.material_depth.as_ref().map(|_| {
|
let resolve_material_depth = view_resources.material_depth.as_ref().map(|_| {
|
||||||
let entries = BindGroupEntries::sequential((
|
let entries = BindGroupEntries::sequential((
|
||||||
view_resources.visibility_buffer.as_entire_binding(),
|
&view_resources.visibility_buffer.default_view,
|
||||||
cluster_instance_ids.as_entire_binding(),
|
cluster_instance_ids.as_entire_binding(),
|
||||||
instance_manager.instance_material_ids.binding().unwrap(),
|
instance_manager.instance_material_ids.binding().unwrap(),
|
||||||
));
|
));
|
||||||
@ -686,7 +796,7 @@ pub fn prepare_meshlet_view_bind_groups(
|
|||||||
|
|
||||||
let material_shade = view_resources.material_depth.as_ref().map(|_| {
|
let material_shade = view_resources.material_depth.as_ref().map(|_| {
|
||||||
let entries = BindGroupEntries::sequential((
|
let entries = BindGroupEntries::sequential((
|
||||||
view_resources.visibility_buffer.as_entire_binding(),
|
&view_resources.visibility_buffer.default_view,
|
||||||
cluster_meshlet_ids.as_entire_binding(),
|
cluster_meshlet_ids.as_entire_binding(),
|
||||||
meshlet_mesh_manager.meshlets.binding(),
|
meshlet_mesh_manager.meshlets.binding(),
|
||||||
meshlet_mesh_manager.indices.binding(),
|
meshlet_mesh_manager.indices.binding(),
|
||||||
@ -738,6 +848,7 @@ pub fn prepare_meshlet_view_bind_groups(
|
|||||||
commands.entity(view_entity).insert(MeshletViewBindGroups {
|
commands.entity(view_entity).insert(MeshletViewBindGroups {
|
||||||
first_node: Arc::clone(&first_node),
|
first_node: Arc::clone(&first_node),
|
||||||
fill_cluster_buffers,
|
fill_cluster_buffers,
|
||||||
|
clear_visibility_buffer,
|
||||||
culling_first,
|
culling_first,
|
||||||
culling_second,
|
culling_second,
|
||||||
downsample_depth,
|
downsample_depth,
|
||||||
|
@ -54,16 +54,13 @@ fn vertex(@builtin(instance_index) instance_index: u32, @builtin(vertex_index) v
|
|||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fragment(vertex_output: VertexOutput) {
|
fn fragment(vertex_output: VertexOutput) {
|
||||||
let frag_coord_1d = u32(vertex_output.position.y) * u32(view.viewport.z) + u32(vertex_output.position.x);
|
let depth = bitcast<u32>(vertex_output.position.z);
|
||||||
|
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#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);
|
let visibility = (u64(depth) << 32u) | u64(vertex_output.packed_ids);
|
||||||
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], visibility);
|
|
||||||
#else
|
#else
|
||||||
let depth = bitcast<u32>(vertex_output.position.z);
|
let visibility = depth;
|
||||||
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
|
|
||||||
#endif
|
#endif
|
||||||
|
textureAtomicMax(meshlet_visibility_buffer, vec2<u32>(vertex_output.position.xy), visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dummy_vertex() -> VertexOutput {
|
fn dummy_vertex() -> VertexOutput {
|
||||||
|
@ -9,7 +9,7 @@ use bevy_ecs::{
|
|||||||
query::QueryState,
|
query::QueryState,
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
};
|
};
|
||||||
use bevy_math::ops;
|
use bevy_math::{ops, UVec2};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::ExtractedCamera,
|
camera::ExtractedCamera,
|
||||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
render_graph::{Node, NodeRunError, RenderGraphContext},
|
||||||
@ -77,6 +77,8 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
|
|
||||||
let Some((
|
let Some((
|
||||||
fill_cluster_buffers_pipeline,
|
fill_cluster_buffers_pipeline,
|
||||||
|
clear_visibility_buffer_pipeline,
|
||||||
|
clear_visibility_buffer_shadow_view_pipeline,
|
||||||
culling_first_pipeline,
|
culling_first_pipeline,
|
||||||
culling_second_pipeline,
|
culling_second_pipeline,
|
||||||
downsample_depth_first_pipeline,
|
downsample_depth_first_pipeline,
|
||||||
@ -84,10 +86,10 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
downsample_depth_first_shadow_view_pipeline,
|
downsample_depth_first_shadow_view_pipeline,
|
||||||
downsample_depth_second_shadow_view_pipeline,
|
downsample_depth_second_shadow_view_pipeline,
|
||||||
visibility_buffer_software_raster_pipeline,
|
visibility_buffer_software_raster_pipeline,
|
||||||
visibility_buffer_software_raster_depth_only_pipeline,
|
visibility_buffer_software_raster_shadow_view_pipeline,
|
||||||
visibility_buffer_hardware_raster_pipeline,
|
visibility_buffer_hardware_raster_pipeline,
|
||||||
visibility_buffer_hardware_raster_depth_only_pipeline,
|
visibility_buffer_hardware_raster_shadow_view_pipeline,
|
||||||
visibility_buffer_hardware_raster_depth_only_unclipped_pipeline,
|
visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline,
|
||||||
resolve_depth_pipeline,
|
resolve_depth_pipeline,
|
||||||
resolve_depth_shadow_view_pipeline,
|
resolve_depth_shadow_view_pipeline,
|
||||||
resolve_material_depth_pipeline,
|
resolve_material_depth_pipeline,
|
||||||
@ -107,11 +109,6 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
render_context
|
render_context
|
||||||
.command_encoder()
|
.command_encoder()
|
||||||
.push_debug_group("meshlet_visibility_buffer_raster");
|
.push_debug_group("meshlet_visibility_buffer_raster");
|
||||||
render_context.command_encoder().clear_buffer(
|
|
||||||
&meshlet_view_resources.second_pass_candidates_buffer,
|
|
||||||
0,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
if first_node {
|
if first_node {
|
||||||
fill_cluster_buffers_pass(
|
fill_cluster_buffers_pass(
|
||||||
render_context,
|
render_context,
|
||||||
@ -120,6 +117,17 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
meshlet_view_resources.scene_instance_count,
|
meshlet_view_resources.scene_instance_count,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
clear_visibility_buffer_pass(
|
||||||
|
render_context,
|
||||||
|
&meshlet_view_bind_groups.clear_visibility_buffer,
|
||||||
|
clear_visibility_buffer_pipeline,
|
||||||
|
meshlet_view_resources.view_size,
|
||||||
|
);
|
||||||
|
render_context.command_encoder().clear_buffer(
|
||||||
|
&meshlet_view_resources.second_pass_candidates_buffer,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
cull_pass(
|
cull_pass(
|
||||||
"culling_first",
|
"culling_first",
|
||||||
render_context,
|
render_context,
|
||||||
@ -189,7 +197,6 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
resolve_depth(
|
resolve_depth(
|
||||||
render_context,
|
render_context,
|
||||||
view_depth.get_attachment(StoreOp::Store),
|
view_depth.get_attachment(StoreOp::Store),
|
||||||
meshlet_view_resources,
|
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
resolve_depth_pipeline,
|
resolve_depth_pipeline,
|
||||||
camera,
|
camera,
|
||||||
@ -226,15 +233,21 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
|
|
||||||
let shadow_visibility_buffer_hardware_raster_pipeline =
|
let shadow_visibility_buffer_hardware_raster_pipeline =
|
||||||
if let LightEntity::Directional { .. } = light_type {
|
if let LightEntity::Directional { .. } = light_type {
|
||||||
visibility_buffer_hardware_raster_depth_only_unclipped_pipeline
|
visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline
|
||||||
} else {
|
} else {
|
||||||
visibility_buffer_hardware_raster_depth_only_pipeline
|
visibility_buffer_hardware_raster_shadow_view_pipeline
|
||||||
};
|
};
|
||||||
|
|
||||||
render_context.command_encoder().push_debug_group(&format!(
|
render_context.command_encoder().push_debug_group(&format!(
|
||||||
"meshlet_visibility_buffer_raster: {}",
|
"meshlet_visibility_buffer_raster: {}",
|
||||||
shadow_view.pass_name
|
shadow_view.pass_name
|
||||||
));
|
));
|
||||||
|
clear_visibility_buffer_pass(
|
||||||
|
render_context,
|
||||||
|
&meshlet_view_bind_groups.clear_visibility_buffer,
|
||||||
|
clear_visibility_buffer_shadow_view_pipeline,
|
||||||
|
meshlet_view_resources.view_size,
|
||||||
|
);
|
||||||
render_context.command_encoder().clear_buffer(
|
render_context.command_encoder().clear_buffer(
|
||||||
&meshlet_view_resources.second_pass_candidates_buffer,
|
&meshlet_view_resources.second_pass_candidates_buffer,
|
||||||
0,
|
0,
|
||||||
@ -264,7 +277,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
&meshlet_view_resources.dummy_render_target.default_view,
|
&meshlet_view_resources.dummy_render_target.default_view,
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
view_offset,
|
view_offset,
|
||||||
visibility_buffer_software_raster_depth_only_pipeline,
|
visibility_buffer_software_raster_shadow_view_pipeline,
|
||||||
shadow_visibility_buffer_hardware_raster_pipeline,
|
shadow_visibility_buffer_hardware_raster_pipeline,
|
||||||
None,
|
None,
|
||||||
meshlet_view_resources.raster_cluster_rightmost_slot,
|
meshlet_view_resources.raster_cluster_rightmost_slot,
|
||||||
@ -301,7 +314,7 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
&meshlet_view_resources.dummy_render_target.default_view,
|
&meshlet_view_resources.dummy_render_target.default_view,
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
view_offset,
|
view_offset,
|
||||||
visibility_buffer_software_raster_depth_only_pipeline,
|
visibility_buffer_software_raster_shadow_view_pipeline,
|
||||||
shadow_visibility_buffer_hardware_raster_pipeline,
|
shadow_visibility_buffer_hardware_raster_pipeline,
|
||||||
None,
|
None,
|
||||||
meshlet_view_resources.raster_cluster_rightmost_slot,
|
meshlet_view_resources.raster_cluster_rightmost_slot,
|
||||||
@ -309,7 +322,6 @@ impl Node for MeshletVisibilityBufferRasterPassNode {
|
|||||||
resolve_depth(
|
resolve_depth(
|
||||||
render_context,
|
render_context,
|
||||||
shadow_view.depth_attachment.get_attachment(StoreOp::Store),
|
shadow_view.depth_attachment.get_attachment(StoreOp::Store),
|
||||||
meshlet_view_resources,
|
|
||||||
meshlet_view_bind_groups,
|
meshlet_view_bind_groups,
|
||||||
resolve_depth_shadow_view_pipeline,
|
resolve_depth_shadow_view_pipeline,
|
||||||
camera,
|
camera,
|
||||||
@ -362,6 +374,29 @@ fn fill_cluster_buffers_pass(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Replace this with vkCmdClearColorImage once wgpu supports it
|
||||||
|
fn clear_visibility_buffer_pass(
|
||||||
|
render_context: &mut RenderContext,
|
||||||
|
clear_visibility_buffer_bind_group: &BindGroup,
|
||||||
|
clear_visibility_buffer_pipeline: &ComputePipeline,
|
||||||
|
view_size: UVec2,
|
||||||
|
) {
|
||||||
|
let command_encoder = render_context.command_encoder();
|
||||||
|
let mut clear_visibility_buffer_pass =
|
||||||
|
command_encoder.begin_compute_pass(&ComputePassDescriptor {
|
||||||
|
label: Some("clear_visibility_buffer"),
|
||||||
|
timestamp_writes: None,
|
||||||
|
});
|
||||||
|
clear_visibility_buffer_pass.set_pipeline(clear_visibility_buffer_pipeline);
|
||||||
|
clear_visibility_buffer_pass.set_push_constants(0, bytemuck::bytes_of(&view_size));
|
||||||
|
clear_visibility_buffer_pass.set_bind_group(0, clear_visibility_buffer_bind_group, &[]);
|
||||||
|
clear_visibility_buffer_pass.dispatch_workgroups(
|
||||||
|
view_size.x.div_ceil(16),
|
||||||
|
view_size.y.div_ceil(16),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn cull_pass(
|
fn cull_pass(
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
render_context: &mut RenderContext,
|
render_context: &mut RenderContext,
|
||||||
@ -478,7 +513,6 @@ fn raster_pass(
|
|||||||
fn resolve_depth(
|
fn resolve_depth(
|
||||||
render_context: &mut RenderContext,
|
render_context: &mut RenderContext,
|
||||||
depth_stencil_attachment: RenderPassDepthStencilAttachment,
|
depth_stencil_attachment: RenderPassDepthStencilAttachment,
|
||||||
meshlet_view_resources: &MeshletViewResources,
|
|
||||||
meshlet_view_bind_groups: &MeshletViewBindGroups,
|
meshlet_view_bind_groups: &MeshletViewBindGroups,
|
||||||
resolve_depth_pipeline: &RenderPipeline,
|
resolve_depth_pipeline: &RenderPipeline,
|
||||||
camera: &ExtractedCamera,
|
camera: &ExtractedCamera,
|
||||||
@ -494,11 +528,6 @@ fn resolve_depth(
|
|||||||
resolve_pass.set_camera_viewport(viewport);
|
resolve_pass.set_camera_viewport(viewport);
|
||||||
}
|
}
|
||||||
resolve_pass.set_render_pipeline(resolve_depth_pipeline);
|
resolve_pass.set_render_pipeline(resolve_depth_pipeline);
|
||||||
resolve_pass.set_push_constants(
|
|
||||||
ShaderStages::FRAGMENT,
|
|
||||||
0,
|
|
||||||
&meshlet_view_resources.view_size.x.to_le_bytes(),
|
|
||||||
);
|
|
||||||
resolve_pass.set_bind_group(0, &meshlet_view_bind_groups.resolve_depth, &[]);
|
resolve_pass.set_bind_group(0, &meshlet_view_bind_groups.resolve_depth, &[]);
|
||||||
resolve_pass.draw(0..3, 0..1);
|
resolve_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
@ -532,11 +561,6 @@ fn resolve_material_depth(
|
|||||||
resolve_pass.set_camera_viewport(viewport);
|
resolve_pass.set_camera_viewport(viewport);
|
||||||
}
|
}
|
||||||
resolve_pass.set_render_pipeline(resolve_material_depth_pipeline);
|
resolve_pass.set_render_pipeline(resolve_material_depth_pipeline);
|
||||||
resolve_pass.set_push_constants(
|
|
||||||
ShaderStages::FRAGMENT,
|
|
||||||
0,
|
|
||||||
&meshlet_view_resources.view_size.x.to_le_bytes(),
|
|
||||||
);
|
|
||||||
resolve_pass.set_bind_group(0, resolve_material_depth_bind_group, &[]);
|
resolve_pass.set_bind_group(0, resolve_material_depth_bind_group, &[]);
|
||||||
resolve_pass.draw(0..3, 0..1);
|
resolve_pass.draw(0..3, 0..1);
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,7 @@ struct VertexOutput {
|
|||||||
|
|
||||||
/// Load the visibility buffer texture and resolve it into a VertexOutput.
|
/// Load the visibility buffer texture and resolve it into a VertexOutput.
|
||||||
fn resolve_vertex_output(frag_coord: vec4<f32>) -> VertexOutput {
|
fn resolve_vertex_output(frag_coord: vec4<f32>) -> VertexOutput {
|
||||||
let frag_coord_1d = u32(frag_coord.y) * u32(view.viewport.z) + u32(frag_coord.x);
|
let packed_ids = u32(textureLoad(meshlet_visibility_buffer, vec2<u32>(frag_coord.xy)).r);
|
||||||
let packed_ids = u32(meshlet_visibility_buffer[frag_coord_1d]); // TODO: Might be faster to load the correct u32 directly
|
|
||||||
let cluster_id = packed_ids >> 7u;
|
let cluster_id = packed_ids >> 7u;
|
||||||
let meshlet_id = meshlet_cluster_meshlet_ids[cluster_id];
|
let meshlet_id = meshlet_cluster_meshlet_ids[cluster_id];
|
||||||
var meshlet = meshlets[meshlet_id];
|
var meshlet = meshlets[meshlet_id];
|
||||||
|
@ -167,16 +167,13 @@ fn rasterize_cluster(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_visibility_buffer_pixel(x: f32, y: f32, z: f32, packed_ids: u32) {
|
fn write_visibility_buffer_pixel(x: f32, y: f32, z: f32, packed_ids: u32) {
|
||||||
let frag_coord_1d = u32(y * view.viewport.z + x);
|
let depth = bitcast<u32>(z);
|
||||||
|
|
||||||
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
#ifdef MESHLET_VISIBILITY_BUFFER_RASTER_PASS_OUTPUT
|
||||||
let depth = bitcast<u32>(z);
|
|
||||||
let visibility = (u64(depth) << 32u) | u64(packed_ids);
|
let visibility = (u64(depth) << 32u) | u64(packed_ids);
|
||||||
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], visibility);
|
|
||||||
#else
|
#else
|
||||||
let depth = bitcast<u32>(z);
|
let visibility = depth;
|
||||||
atomicMax(&meshlet_visibility_buffer[frag_coord_1d], depth);
|
|
||||||
#endif
|
#endif
|
||||||
|
textureAtomicMax(meshlet_visibility_buffer, vec2(u32(x), u32(y)), visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edge_function(a: vec2<f32>, b: vec2<f32>, c: vec2<f32>) -> f32 {
|
fn edge_function(a: vec2<f32>, b: vec2<f32>, c: vec2<f32>) -> f32 {
|
||||||
|
Loading…
Reference in New Issue
Block a user