Skip to content

Commit ddf4d9e

Browse files
authored
Fix meshlet shaders for bindless mode. (#16825)
We have to extract the material ID from the mesh and stuff it in the vertex during visibility buffer resolution.
1 parent 460de77 commit ddf4d9e

File tree

5 files changed

+29
-10
lines changed

5 files changed

+29
-10
lines changed

crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct VertexOutput {
9494
world_tangent: vec4<f32>,
9595
mesh_flags: u32,
9696
cluster_id: u32,
97+
material_bind_group_slot: u32,
9798
#ifdef PREPASS_FRAGMENT
9899
#ifdef MOTION_VECTOR_PREPASS
99100
motion_vector: vec2<f32>,
@@ -173,6 +174,7 @@ fn resolve_vertex_output(frag_coord: vec4<f32>) -> VertexOutput {
173174
world_tangent,
174175
instance_uniform.flags,
175176
instance_id ^ meshlet_id,
177+
instance_uniform.material_and_lightmap_bind_group_slot & 0xffffu,
176178
#ifdef PREPASS_FRAGMENT
177179
#ifdef MOTION_VECTOR_PREPASS
178180
motion_vector,

crates/bevy_pbr/src/render/mesh_bindings.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
#import bevy_pbr::mesh_types::Mesh
44

5+
#ifndef MESHLET_MESH_MATERIAL_PASS
56
#ifdef PER_OBJECT_BUFFER_BATCH_SIZE
67
@group(1) @binding(0) var<uniform> mesh: array<Mesh, #{PER_OBJECT_BUFFER_BATCH_SIZE}u>;
78
#else
89
@group(1) @binding(0) var<storage> mesh: array<Mesh>;
910
#endif // PER_OBJECT_BUFFER_BATCH_SIZE
11+
#endif // MESHLET_MESH_MATERIAL_PASS

crates/bevy_pbr/src/render/mesh_functions.wgsl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
}
1313
#import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack}
1414

15+
#ifndef MESHLET_MESH_MATERIAL_PASS
1516

1617
fn get_world_from_local(instance_index: u32) -> mat4x4<f32> {
1718
return affine3_to_square(mesh[instance_index].world_from_local);
@@ -21,6 +22,8 @@ fn get_previous_world_from_local(instance_index: u32) -> mat4x4<f32> {
2122
return affine3_to_square(mesh[instance_index].previous_world_from_local);
2223
}
2324

25+
#endif // MESHLET_MESH_MATERIAL_PASS
26+
2427
fn mesh_position_local_to_world(world_from_local: mat4x4<f32>, vertex_position: vec4<f32>) -> vec4<f32> {
2528
return world_from_local * vertex_position;
2629
}
@@ -33,6 +36,8 @@ fn mesh_position_local_to_clip(world_from_local: mat4x4<f32>, vertex_position: v
3336
return position_world_to_clip(world_position.xyz);
3437
}
3538

39+
#ifndef MESHLET_MESH_MATERIAL_PASS
40+
3641
fn mesh_normal_local_to_world(vertex_normal: vec3<f32>, instance_index: u32) -> vec3<f32> {
3742
// NOTE: The mikktspace method of normal mapping requires that the world normal is
3843
// re-normalized in the vertex shader to match the way mikktspace bakes vertex tangents
@@ -53,6 +58,8 @@ fn mesh_normal_local_to_world(vertex_normal: vec3<f32>, instance_index: u32) ->
5358
}
5459
}
5560

61+
#endif // MESHLET_MESH_MATERIAL_PASS
62+
5663
// Calculates the sign of the determinant of the 3x3 model matrix based on a
5764
// mesh flag
5865
fn sign_determinant_model_3x3m(mesh_flags: u32) -> f32 {
@@ -62,6 +69,8 @@ fn sign_determinant_model_3x3m(mesh_flags: u32) -> f32 {
6269
return f32(bool(mesh_flags & MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT)) * 2.0 - 1.0;
6370
}
6471

72+
#ifndef MESHLET_MESH_MATERIAL_PASS
73+
6574
fn mesh_tangent_local_to_world(world_from_local: mat4x4<f32>, vertex_tangent: vec4<f32>, instance_index: u32) -> vec4<f32> {
6675
// NOTE: The mikktspace method of normal mapping requires that the world tangent is
6776
// re-normalized in the vertex shader to match the way mikktspace bakes vertex tangents
@@ -88,6 +97,8 @@ fn mesh_tangent_local_to_world(world_from_local: mat4x4<f32>, vertex_tangent: ve
8897
}
8998
}
9099

100+
#endif // MESHLET_MESH_MATERIAL_PASS
101+
91102
// Returns an appropriate dither level for the current mesh instance.
92103
//
93104
// This looks up the LOD range in the `visibility_ranges` table and compares the

crates/bevy_pbr/src/render/parallax_mapping.wgsl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
mesh_bindings::mesh
66
}
77

8-
fn sample_depth_map(uv: vec2<f32>, instance_index: u32) -> f32 {
9-
let slot = mesh[instance_index].material_and_lightmap_bind_group_slot & 0xffffu;
8+
fn sample_depth_map(uv: vec2<f32>, material_bind_group_slot: u32) -> f32 {
109
// We use `textureSampleLevel` over `textureSample` because the wgpu DX12
1110
// backend (Fxc) panics when using "gradient instructions" inside a loop.
1211
// It results in the whole loop being unrolled by the shader compiler,
@@ -19,8 +18,8 @@ fn sample_depth_map(uv: vec2<f32>, instance_index: u32) -> f32 {
1918
// See https://stackoverflow.com/questions/56581141/direct3d11-gradient-instruction-used-in-a-loop-with-varying-iteration-forcing
2019
return textureSampleLevel(
2120
#ifdef BINDLESS
22-
depth_map_texture[slot],
23-
depth_map_sampler[slot],
21+
depth_map_texture[material_bind_group_slot],
22+
depth_map_sampler[material_bind_group_slot],
2423
#else // BINDLESS
2524
depth_map_texture,
2625
depth_map_sampler,
@@ -40,7 +39,7 @@ fn parallaxed_uv(
4039
original_uv: vec2<f32>,
4140
// The vector from the camera to the fragment at the surface in tangent space
4241
Vt: vec3<f32>,
43-
instance_index: u32,
42+
material_bind_group_slot: u32,
4443
) -> vec2<f32> {
4544
if max_layer_count < 1.0 {
4645
return original_uv;
@@ -68,15 +67,15 @@ fn parallaxed_uv(
6867
var delta_uv = depth_scale * layer_depth * Vt.xy * vec2(1.0, -1.0) / view_steepness;
6968

7069
var current_layer_depth = 0.0;
71-
var texture_depth = sample_depth_map(uv, instance_index);
70+
var texture_depth = sample_depth_map(uv, material_bind_group_slot);
7271

7372
// texture_depth > current_layer_depth means the depth map depth is deeper
7473
// than the depth the ray would be at this UV offset so the ray has not
7574
// intersected the surface
7675
for (var i: i32 = 0; texture_depth > current_layer_depth && i <= i32(layer_count); i++) {
7776
current_layer_depth += layer_depth;
7877
uv += delta_uv;
79-
texture_depth = sample_depth_map(uv, instance_index);
78+
texture_depth = sample_depth_map(uv, material_bind_group_slot);
8079
}
8180

8281
#ifdef RELIEF_MAPPING
@@ -94,7 +93,7 @@ fn parallaxed_uv(
9493
current_layer_depth -= delta_depth;
9594

9695
for (var i: u32 = 0u; i < max_steps; i++) {
97-
texture_depth = sample_depth_map(uv, instance_index);
96+
texture_depth = sample_depth_map(uv, material_bind_group_slot);
9897

9998
// Halve the deltas for the next step
10099
delta_uv *= 0.5;
@@ -118,7 +117,8 @@ fn parallaxed_uv(
118117
// may skip small details and result in writhing material artifacts.
119118
let previous_uv = uv - delta_uv;
120119
let next_depth = texture_depth - current_layer_depth;
121-
let previous_depth = sample_depth_map(previous_uv, instance_index) - current_layer_depth + layer_depth;
120+
let previous_depth = sample_depth_map(previous_uv, material_bind_group_slot) -
121+
current_layer_depth + layer_depth;
122122

123123
let weight = next_depth / (next_depth - previous_depth);
124124

crates/bevy_pbr/src/render/pbr_fragment.wgsl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ fn pbr_input_from_standard_material(
7171
is_front: bool,
7272
) -> pbr_types::PbrInput {
7373
#ifdef BINDLESS
74+
#ifdef MESHLET_MESH_MATERIAL_PASS
75+
let slot = in.material_bind_group_slot;
76+
#else // MESHLET_MESH_MATERIAL_PASS
7477
let slot = mesh[in.instance_index].material_and_lightmap_bind_group_slot & 0xffffu;
78+
#endif // MESHLET_MESH_MATERIAL_PASS
7579
let flags = pbr_bindings::material[slot].flags;
7680
let base_color = pbr_bindings::material[slot].base_color;
7781
let deferred_lighting_pass_id = pbr_bindings::material[slot].deferred_lighting_pass_id;
@@ -146,7 +150,7 @@ fn pbr_input_from_standard_material(
146150
// parallax mapping algorithm easier to understand and reason
147151
// about.
148152
-Vt,
149-
in.instance_index,
153+
slot,
150154
);
151155
#endif
152156

0 commit comments

Comments
 (0)