Skip to content

Commit 14ce281

Browse files
committed
bevy_render2: Support nested shader defs (#3113)
# Objective Fix nested shader defs. For example, in: ```rust #ifdef A #ifdef B some code here #endif #endif ``` ...before this PR, if `A` *is not* defined, and `B` *is* defined, then `some code here` will be output. ## Solution - Combine the logic of whether the parent and child scope guards are defined and use that as the resulting child scope guard boolean value
1 parent 213839f commit 14ce281

File tree

1 file changed

+181
-2
lines changed
  • pipelined/bevy_render2/src/render_resource

1 file changed

+181
-2
lines changed

pipelined/bevy_render2/src/render_resource/shader.rs

Lines changed: 181 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,10 @@ impl ShaderProcessor {
268268
for line in shader.split('\n') {
269269
if let Some(cap) = self.ifdef_regex.captures(line) {
270270
let def = cap.get(1).unwrap();
271-
scopes.push(shader_defs.contains(def.as_str()));
271+
scopes.push(*scopes.last().unwrap() && shader_defs.contains(def.as_str()));
272272
} else if let Some(cap) = self.ifndef_regex.captures(line) {
273273
let def = cap.get(1).unwrap();
274-
scopes.push(!shader_defs.contains(def.as_str()));
274+
scopes.push(*scopes.last().unwrap() && !shader_defs.contains(def.as_str()));
275275
} else if self.endif_regex.is_match(line) {
276276
scopes.pop();
277277
if scopes.is_empty() {
@@ -315,6 +315,38 @@ struct VertexOutput {
315315
[[builtin(position)]] position: vec4<f32>;
316316
};
317317
318+
[[stage(vertex)]]
319+
fn vertex(
320+
[[location(0)]] vertex_position: vec3<f32>,
321+
[[location(1)]] vertex_uv: vec2<f32>
322+
) -> VertexOutput {
323+
var out: VertexOutput;
324+
out.uv = vertex_uv;
325+
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
326+
return out;
327+
}
328+
";
329+
const WGSL_NESTED_IFDEF: &str = r"
330+
[[block]]
331+
struct View {
332+
view_proj: mat4x4<f32>;
333+
world_position: vec3<f32>;
334+
};
335+
[[group(0), binding(0)]]
336+
var<uniform> view: View;
337+
338+
# ifdef TEXTURE
339+
# ifdef ATTRIBUTE
340+
[[group(1), binding(0)]]
341+
var sprite_texture: texture_2d<f32>;
342+
# endif
343+
# endif
344+
345+
struct VertexOutput {
346+
[[location(0)]] uv: vec2<f32>;
347+
[[builtin(position)]] position: vec4<f32>;
348+
};
349+
318350
[[stage(vertex)]]
319351
fn vertex(
320352
[[location(0)]] vertex_position: vec3<f32>,
@@ -432,4 +464,151 @@ fn foo() { }
432464
let result = processor.process_str(INPUT, &[]).unwrap();
433465
assert_eq!(result, INPUT);
434466
}
467+
468+
#[test]
469+
fn process_nested_shader_def_outer_defined_inner_not() {
470+
#[rustfmt::skip]
471+
const EXPECTED: &str = r"
472+
[[block]]
473+
struct View {
474+
view_proj: mat4x4<f32>;
475+
world_position: vec3<f32>;
476+
};
477+
[[group(0), binding(0)]]
478+
var<uniform> view: View;
479+
480+
481+
struct VertexOutput {
482+
[[location(0)]] uv: vec2<f32>;
483+
[[builtin(position)]] position: vec4<f32>;
484+
};
485+
486+
[[stage(vertex)]]
487+
fn vertex(
488+
[[location(0)]] vertex_position: vec3<f32>,
489+
[[location(1)]] vertex_uv: vec2<f32>
490+
) -> VertexOutput {
491+
var out: VertexOutput;
492+
out.uv = vertex_uv;
493+
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
494+
return out;
495+
}
496+
";
497+
let processor = ShaderProcessor::default();
498+
let result = processor
499+
.process_str(WGSL_NESTED_IFDEF, &["TEXTURE".to_string()])
500+
.unwrap();
501+
assert_eq!(result, EXPECTED);
502+
}
503+
504+
#[test]
505+
fn process_nested_shader_def_neither_defined() {
506+
#[rustfmt::skip]
507+
const EXPECTED: &str = r"
508+
[[block]]
509+
struct View {
510+
view_proj: mat4x4<f32>;
511+
world_position: vec3<f32>;
512+
};
513+
[[group(0), binding(0)]]
514+
var<uniform> view: View;
515+
516+
517+
struct VertexOutput {
518+
[[location(0)]] uv: vec2<f32>;
519+
[[builtin(position)]] position: vec4<f32>;
520+
};
521+
522+
[[stage(vertex)]]
523+
fn vertex(
524+
[[location(0)]] vertex_position: vec3<f32>,
525+
[[location(1)]] vertex_uv: vec2<f32>
526+
) -> VertexOutput {
527+
var out: VertexOutput;
528+
out.uv = vertex_uv;
529+
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
530+
return out;
531+
}
532+
";
533+
let processor = ShaderProcessor::default();
534+
let result = processor.process_str(WGSL_NESTED_IFDEF, &[]).unwrap();
535+
assert_eq!(result, EXPECTED);
536+
}
537+
538+
#[test]
539+
fn process_nested_shader_def_inner_defined_outer_not() {
540+
#[rustfmt::skip]
541+
const EXPECTED: &str = r"
542+
[[block]]
543+
struct View {
544+
view_proj: mat4x4<f32>;
545+
world_position: vec3<f32>;
546+
};
547+
[[group(0), binding(0)]]
548+
var<uniform> view: View;
549+
550+
551+
struct VertexOutput {
552+
[[location(0)]] uv: vec2<f32>;
553+
[[builtin(position)]] position: vec4<f32>;
554+
};
555+
556+
[[stage(vertex)]]
557+
fn vertex(
558+
[[location(0)]] vertex_position: vec3<f32>,
559+
[[location(1)]] vertex_uv: vec2<f32>
560+
) -> VertexOutput {
561+
var out: VertexOutput;
562+
out.uv = vertex_uv;
563+
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
564+
return out;
565+
}
566+
";
567+
let processor = ShaderProcessor::default();
568+
let result = processor
569+
.process_str(WGSL_NESTED_IFDEF, &["ATTRIBUTE".to_string()])
570+
.unwrap();
571+
assert_eq!(result, EXPECTED);
572+
}
573+
574+
#[test]
575+
fn process_nested_shader_def_both_defined() {
576+
#[rustfmt::skip]
577+
const EXPECTED: &str = r"
578+
[[block]]
579+
struct View {
580+
view_proj: mat4x4<f32>;
581+
world_position: vec3<f32>;
582+
};
583+
[[group(0), binding(0)]]
584+
var<uniform> view: View;
585+
586+
[[group(1), binding(0)]]
587+
var sprite_texture: texture_2d<f32>;
588+
589+
struct VertexOutput {
590+
[[location(0)]] uv: vec2<f32>;
591+
[[builtin(position)]] position: vec4<f32>;
592+
};
593+
594+
[[stage(vertex)]]
595+
fn vertex(
596+
[[location(0)]] vertex_position: vec3<f32>,
597+
[[location(1)]] vertex_uv: vec2<f32>
598+
) -> VertexOutput {
599+
var out: VertexOutput;
600+
out.uv = vertex_uv;
601+
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
602+
return out;
603+
}
604+
";
605+
let processor = ShaderProcessor::default();
606+
let result = processor
607+
.process_str(
608+
WGSL_NESTED_IFDEF,
609+
&["TEXTURE".to_string(), "ATTRIBUTE".to_string()],
610+
)
611+
.unwrap();
612+
assert_eq!(result, EXPECTED);
613+
}
435614
}

0 commit comments

Comments
 (0)