Skip to content

Commit d44e865

Browse files
committed
Shader defs can now have a value (#5900)
# Objective - shaders defs can now have a `bool` or `int` value - `#if SHADER_DEF <operator> 3` - ok if `SHADER_DEF` is defined, has the correct type and pass the comparison - `==`, `!=`, `>=`, `>`, `<`, `<=` supported - `#SHADER_DEF` or `#{SHADER_DEF}` - will be replaced by the value in the shader code --- ## Migration Guide - replace `shader_defs.push(String::from("NAME"));` by `shader_defs.push("NAME".into());` - if you used shader def `NO_STORAGE_BUFFERS_SUPPORT`, check how `AVAILABLE_STORAGE_BUFFER_BINDINGS` is now used in Bevy default shaders
1 parent daa57fe commit d44e865

File tree

14 files changed

+719
-83
lines changed

14 files changed

+719
-83
lines changed

crates/bevy_core_pipeline/src/fxaa/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ impl SpecializedRenderPipeline for FxaaPipeline {
203203
fragment: Some(FragmentState {
204204
shader: FXAA_SHADER_HANDLE.typed(),
205205
shader_defs: vec![
206-
format!("EDGE_THRESH_{}", key.edge_threshold.get_str()),
207-
format!("EDGE_THRESH_MIN_{}", key.edge_threshold_min.get_str()),
206+
format!("EDGE_THRESH_{}", key.edge_threshold.get_str()).into(),
207+
format!("EDGE_THRESH_MIN_{}", key.edge_threshold_min.get_str()).into(),
208208
],
209209
entry_point: "fragment".into(),
210210
targets: vec![Some(ColorTargetState {

crates/bevy_core_pipeline/src/tonemapping/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline {
6666
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
6767
let mut shader_defs = Vec::new();
6868
if key.deband_dither {
69-
shader_defs.push("DEBAND_DITHER".to_string());
69+
shader_defs.push("DEBAND_DITHER".into());
7070
}
7171
RenderPipelineDescriptor {
7272
label: Some("tonemapping pipeline".into()),

crates/bevy_pbr/src/pbr_material.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl Material for StandardMaterial {
419419
.as_mut()
420420
.unwrap()
421421
.shader_defs
422-
.push(String::from("STANDARDMATERIAL_NORMAL_MAP"));
422+
.push("STANDARDMATERIAL_NORMAL_MAP".into());
423423
}
424424
descriptor.primitive.cull_mode = key.bind_group_data.cull_mode;
425425
if let Some(label) = &mut descriptor.label {

crates/bevy_pbr/src/render/clustered_forward.wgsl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ fn fragment_cluster_index(frag_coord: vec2<f32>, view_z: f32, is_orthographic: b
2929
// this must match CLUSTER_COUNT_SIZE in light.rs
3030
let CLUSTER_COUNT_SIZE = 9u;
3131
fn unpack_offset_and_counts(cluster_index: u32) -> vec3<u32> {
32-
#ifdef NO_STORAGE_BUFFERS_SUPPORT
32+
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
33+
return cluster_offsets_and_counts.data[cluster_index].xyz;
34+
#else
3335
let offset_and_counts = cluster_offsets_and_counts.data[cluster_index >> 2u][cluster_index & ((1u << 2u) - 1u)];
3436
// [ 31 .. 18 | 17 .. 9 | 8 .. 0 ]
3537
// [ offset | point light count | spot light count ]
@@ -38,20 +40,18 @@ fn unpack_offset_and_counts(cluster_index: u32) -> vec3<u32> {
3840
(offset_and_counts >> CLUSTER_COUNT_SIZE) & ((1u << CLUSTER_COUNT_SIZE) - 1u),
3941
offset_and_counts & ((1u << CLUSTER_COUNT_SIZE) - 1u),
4042
);
41-
#else
42-
return cluster_offsets_and_counts.data[cluster_index].xyz;
4343
#endif
4444
}
4545

4646
fn get_light_id(index: u32) -> u32 {
47-
#ifdef NO_STORAGE_BUFFERS_SUPPORT
47+
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
48+
return cluster_light_index_lists.data[index];
49+
#else
4850
// The index is correct but in cluster_light_index_lists we pack 4 u8s into a u32
4951
// This means the index into cluster_light_index_lists is index / 4
5052
let indices = cluster_light_index_lists.data[index >> 4u][(index >> 2u) & ((1u << 2u) - 1u)];
5153
// And index % 4 gives the sub-index of the u8 within the u32 so we shift by 8 * sub-index
5254
return (indices >> (8u * (index & ((1u << 2u) - 1u)))) & ((1u << 8u) - 1u);
53-
#else
54-
return cluster_light_index_lists.data[index];
5555
#endif
5656
}
5757

crates/bevy_pbr/src/render/light.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,15 @@ impl SpecializedMeshPipeline for ShadowPipeline {
321321

322322
let mut bind_group_layout = vec![self.view_layout.clone()];
323323
let mut shader_defs = Vec::new();
324+
shader_defs.push(ShaderDefVal::Int(
325+
"MAX_DIRECTIONAL_LIGHTS".to_string(),
326+
MAX_DIRECTIONAL_LIGHTS as i32,
327+
));
324328

325329
if layout.contains(Mesh::ATTRIBUTE_JOINT_INDEX)
326330
&& layout.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
327331
{
328-
shader_defs.push(String::from("SKINNED"));
332+
shader_defs.push("SKINNED".into());
329333
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(4));
330334
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(5));
331335
bind_group_layout.push(self.skinned_mesh_layout.clone());

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
GlobalLightMeta, GpuLights, GpuPointLights, LightMeta, NotShadowCaster, NotShadowReceiver,
33
ShadowPipeline, ViewClusterBindings, ViewLightsUniformOffset, ViewShadowBindings,
4-
CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT,
4+
CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT, MAX_DIRECTIONAL_LIGHTS,
55
};
66
use bevy_app::Plugin;
77
use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped};
@@ -581,35 +581,40 @@ impl SpecializedMeshPipeline for MeshPipeline {
581581
let mut vertex_attributes = Vec::new();
582582

583583
if layout.contains(Mesh::ATTRIBUTE_POSITION) {
584-
shader_defs.push(String::from("VERTEX_POSITIONS"));
584+
shader_defs.push("VERTEX_POSITIONS".into());
585585
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
586586
}
587587

588588
if layout.contains(Mesh::ATTRIBUTE_NORMAL) {
589-
shader_defs.push(String::from("VERTEX_NORMALS"));
589+
shader_defs.push("VERTEX_NORMALS".into());
590590
vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(1));
591591
}
592592

593+
shader_defs.push(ShaderDefVal::Int(
594+
"MAX_DIRECTIONAL_LIGHTS".to_string(),
595+
MAX_DIRECTIONAL_LIGHTS as i32,
596+
));
597+
593598
if layout.contains(Mesh::ATTRIBUTE_UV_0) {
594-
shader_defs.push(String::from("VERTEX_UVS"));
599+
shader_defs.push("VERTEX_UVS".into());
595600
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(2));
596601
}
597602

598603
if layout.contains(Mesh::ATTRIBUTE_TANGENT) {
599-
shader_defs.push(String::from("VERTEX_TANGENTS"));
604+
shader_defs.push("VERTEX_TANGENTS".into());
600605
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(3));
601606
}
602607

603608
if layout.contains(Mesh::ATTRIBUTE_COLOR) {
604-
shader_defs.push(String::from("VERTEX_COLORS"));
609+
shader_defs.push("VERTEX_COLORS".into());
605610
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(4));
606611
}
607612

608613
let mut bind_group_layout = vec![self.view_layout.clone()];
609614
if layout.contains(Mesh::ATTRIBUTE_JOINT_INDEX)
610615
&& layout.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
611616
{
612-
shader_defs.push(String::from("SKINNED"));
617+
shader_defs.push("SKINNED".into());
613618
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(5));
614619
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(6));
615620
bind_group_layout.push(self.skinned_mesh_layout.clone());
@@ -636,11 +641,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
636641
}
637642

638643
if key.contains(MeshPipelineKey::TONEMAP_IN_SHADER) {
639-
shader_defs.push("TONEMAP_IN_SHADER".to_string());
644+
shader_defs.push("TONEMAP_IN_SHADER".into());
640645

641646
// Debanding is tied to tonemapping in the shader, cannot run without it.
642647
if key.contains(MeshPipelineKey::DEBAND_DITHER) {
643-
shader_defs.push("DEBAND_DITHER".to_string());
648+
shader_defs.push("DEBAND_DITHER".into());
644649
}
645650
}
646651

crates/bevy_pbr/src/render/mesh_view_bindings.wgsl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,20 @@ var directional_shadow_textures: texture_depth_2d_array;
2525
@group(0) @binding(5)
2626
var directional_shadow_textures_sampler: sampler_comparison;
2727

28-
#ifdef NO_STORAGE_BUFFERS_SUPPORT
28+
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
2929
@group(0) @binding(6)
30-
var<uniform> point_lights: PointLights;
30+
var<storage> point_lights: PointLights;
3131
@group(0) @binding(7)
32-
var<uniform> cluster_light_index_lists: ClusterLightIndexLists;
32+
var<storage> cluster_light_index_lists: ClusterLightIndexLists;
3333
@group(0) @binding(8)
34-
var<uniform> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
34+
var<storage> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
3535
#else
3636
@group(0) @binding(6)
37-
var<storage> point_lights: PointLights;
37+
var<uniform> point_lights: PointLights;
3838
@group(0) @binding(7)
39-
var<storage> cluster_light_index_lists: ClusterLightIndexLists;
39+
var<uniform> cluster_light_index_lists: ClusterLightIndexLists;
4040
@group(0) @binding(8)
41-
var<storage> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
41+
var<uniform> cluster_offsets_and_counts: ClusterOffsetsAndCounts;
4242
#endif
4343

4444
@group(0) @binding(9)

crates/bevy_pbr/src/render/mesh_view_types.wgsl

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ let DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u;
4242

4343
struct Lights {
4444
// NOTE: this array size must be kept in sync with the constants defined in bevy_pbr/src/render/light.rs
45-
directional_lights: array<DirectionalLight, 10u>,
45+
directional_lights: array<DirectionalLight, #{MAX_DIRECTIONAL_LIGHTS}u>,
4646
ambient_color: vec4<f32>,
4747
// x/y/z dimensions and n_clusters in w
4848
cluster_dimensions: vec4<u32>,
@@ -61,28 +61,28 @@ struct Lights {
6161
spot_light_shadowmap_offset: i32,
6262
};
6363

64-
#ifdef NO_STORAGE_BUFFERS_SUPPORT
64+
#if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3
6565
struct PointLights {
66-
data: array<PointLight, 256u>,
66+
data: array<PointLight>,
6767
};
6868
struct ClusterLightIndexLists {
69-
// each u32 contains 4 u8 indices into the PointLights array
70-
data: array<vec4<u32>, 1024u>,
69+
data: array<u32>,
7170
};
7271
struct ClusterOffsetsAndCounts {
73-
// each u32 contains a 24-bit index into ClusterLightIndexLists in the high 24 bits
74-
// and an 8-bit count of the number of lights in the low 8 bits
75-
data: array<vec4<u32>, 1024u>,
72+
data: array<vec4<u32>>,
7673
};
7774
#else
7875
struct PointLights {
79-
data: array<PointLight>,
76+
data: array<PointLight, 256u>,
8077
};
8178
struct ClusterLightIndexLists {
82-
data: array<u32>,
79+
// each u32 contains 4 u8 indices into the PointLights array
80+
data: array<vec4<u32>, 1024u>,
8381
};
8482
struct ClusterOffsetsAndCounts {
85-
data: array<vec4<u32>>,
83+
// each u32 contains a 24-bit index into ClusterLightIndexLists in the high 24 bits
84+
// and an 8-bit count of the number of lights in the low 8 bits
85+
data: array<vec4<u32>, 1024u>,
8686
};
8787
#endif
8888

crates/bevy_render/src/render_resource/pipeline.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use wgpu::{
77
VertexAttribute, VertexFormat, VertexStepMode,
88
};
99

10+
use super::ShaderDefVal;
1011
use crate::render_resource::resource_macros::*;
1112

1213
/// A [`RenderPipeline`] identifier.
@@ -115,7 +116,7 @@ pub struct RenderPipelineDescriptor {
115116
pub struct VertexState {
116117
/// The compiled shader module for this stage.
117118
pub shader: Handle<Shader>,
118-
pub shader_defs: Vec<String>,
119+
pub shader_defs: Vec<ShaderDefVal>,
119120
/// The name of the entry point in the compiled shader. There must be a
120121
/// function with this name in the shader.
121122
pub entry_point: Cow<'static, str>,
@@ -167,7 +168,7 @@ impl VertexBufferLayout {
167168
pub struct FragmentState {
168169
/// The compiled shader module for this stage.
169170
pub shader: Handle<Shader>,
170-
pub shader_defs: Vec<String>,
171+
pub shader_defs: Vec<ShaderDefVal>,
171172
/// The name of the entry point in the compiled shader. There must be a
172173
/// function with this name in the shader.
173174
pub entry_point: Cow<'static, str>,
@@ -182,7 +183,7 @@ pub struct ComputePipelineDescriptor {
182183
pub layout: Option<Vec<BindGroupLayout>>,
183184
/// The compiled shader module for this stage.
184185
pub shader: Handle<Shader>,
185-
pub shader_defs: Vec<String>,
186+
pub shader_defs: Vec<ShaderDefVal>,
186187
/// The name of the entry point in the compiled shader. There must be a
187188
/// function with this name in the shader.
188189
pub entry_point: Cow<'static, str>,

crates/bevy_render/src/render_resource/pipeline_cache.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl CachedPipelineState {
107107
#[derive(Default)]
108108
struct ShaderData {
109109
pipelines: HashSet<CachedPipelineId>,
110-
processed_shaders: HashMap<Vec<String>, ErasedShaderModule>,
110+
processed_shaders: HashMap<Vec<ShaderDefVal>, ErasedShaderModule>,
111111
resolved_imports: HashMap<ShaderImport, Handle<Shader>>,
112112
dependents: HashSet<Handle<Shader>>,
113113
}
@@ -121,13 +121,31 @@ struct ShaderCache {
121121
processor: ShaderProcessor,
122122
}
123123

124+
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
125+
pub enum ShaderDefVal {
126+
Bool(String, bool),
127+
Int(String, i32),
128+
}
129+
130+
impl From<&str> for ShaderDefVal {
131+
fn from(key: &str) -> Self {
132+
ShaderDefVal::Bool(key.to_string(), true)
133+
}
134+
}
135+
136+
impl From<String> for ShaderDefVal {
137+
fn from(key: String) -> Self {
138+
ShaderDefVal::Bool(key, true)
139+
}
140+
}
141+
124142
impl ShaderCache {
125143
fn get(
126144
&mut self,
127145
render_device: &RenderDevice,
128146
pipeline: CachedPipelineId,
129147
handle: &Handle<Shader>,
130-
shader_defs: &[String],
148+
shader_defs: &[ShaderDefVal],
131149
) -> Result<ErasedShaderModule, PipelineCacheError> {
132150
let shader = self
133151
.shaders
@@ -156,21 +174,20 @@ impl ShaderCache {
156174
let mut shader_defs = shader_defs.to_vec();
157175
#[cfg(feature = "webgl")]
158176
{
159-
shader_defs.push(String::from("NO_ARRAY_TEXTURES_SUPPORT"));
160-
shader_defs.push(String::from("SIXTEEN_BYTE_ALIGNMENT"));
177+
shader_defs.push("NO_ARRAY_TEXTURES_SUPPORT".into());
178+
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());
161179
}
162180

163-
// TODO: 3 is the value from CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT declared in bevy_pbr
164-
// consider exposing this in shaders in a more generally useful way, such as:
165-
// # if AVAILABLE_STORAGE_BUFFER_BINDINGS == 3
166-
// /* use storage buffers here */
167-
// # elif
168-
// /* use uniforms here */
169-
if !matches!(
181+
// 3 is the value from CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT declared in bevy_pbr
182+
// Using the value directly here to avoid the cyclic dependency
183+
if matches!(
170184
render_device.get_supported_read_only_binding_type(3),
171185
BufferBindingType::Storage { .. }
172186
) {
173-
shader_defs.push(String::from("NO_STORAGE_BUFFERS_SUPPORT"));
187+
shader_defs.push(ShaderDefVal::Int(
188+
String::from("AVAILABLE_STORAGE_BUFFER_BINDINGS"),
189+
3,
190+
));
174191
}
175192

176193
debug!(

0 commit comments

Comments
 (0)