]> git.nega.tv - josh/narcissus/commitdiff
shark: Add support for shader includes
authorJosh Simmons <josh@nega.tv>
Sat, 18 May 2024 08:39:21 +0000 (10:39 +0200)
committerJosh Simmons <josh@nega.tv>
Sat, 18 May 2024 08:39:21 +0000 (10:39 +0200)
title/shark-shaders/build.rs
title/shark-shaders/shaders/display_transform.comp.glsl
title/shark-shaders/shaders/primitive_types.h [new file with mode: 0644]

index 149caf14f4e85079c7fce94b62657279442f1147..6f1947fce466056e13583b675fb67912ab5d2420 100644 (file)
@@ -3,40 +3,23 @@ use std::process::Command;
 
 const SHADER_ROOT: &str = "shaders";
 
-#[derive(Clone, Copy)]
-enum ShaderStage {
-    Vertex,
-    Fragment,
-    Compute,
-}
-
-impl ShaderStage {
-    fn name(self) -> &'static str {
-        match self {
-            ShaderStage::Vertex => "vert",
-            ShaderStage::Fragment => "frag",
-            ShaderStage::Compute => "comp",
-        }
-    }
-}
-
 #[derive(Clone, Copy)]
 struct Shader {
-    stage: ShaderStage,
+    stage: &'static str,
     name: &'static str,
 }
 
 const SHADERS: [Shader; 3] = [
     Shader {
-        stage: ShaderStage::Vertex,
+        stage: "vert",
         name: "basic",
     },
     Shader {
-        stage: ShaderStage::Fragment,
+        stage: "frag",
         name: "basic",
     },
     Shader {
-        stage: ShaderStage::Compute,
+        stage: "comp",
         name: "display_transform",
     },
 ];
@@ -48,19 +31,14 @@ fn main() {
         _ => "0",
     };
 
-    let commands = SHADERS.map(|shader| {
+    let commands = SHADERS.map(|Shader { stage, name }| {
         Command::new("glslangValidator")
             .args(["--target-env", "vulkan1.3"])
+            .arg("--quiet")
             .arg(&format!("-g{debug}"))
-            .args([
-                "-o",
-                &format!("{out_dir}/{}.{}.spv", shader.name, shader.stage.name()),
-            ])
-            .arg(&format!(
-                "{SHADER_ROOT}/{}.{}.glsl",
-                shader.name,
-                shader.stage.name()
-            ))
+            .args(["--depfile", &format!("{out_dir}/{name}.{stage}.d")])
+            .args(["-o", &format!("{out_dir}/{name}.{stage}.spv")])
+            .arg(&format!("{SHADER_ROOT}/{name}.{stage}.glsl"))
             .spawn()
             .unwrap()
     });
@@ -74,14 +52,12 @@ fn main() {
     )
     .unwrap();
 
-    for shader in SHADERS {
+    for Shader { stage, name } in SHADERS {
         writeln!(
             file,
-            "pub const {}_{}_SPV: &[u8] = &SpirvBytes(*include_bytes!(\"{out_dir}/{}.{}.spv\")).0;",
-            shader.name.to_ascii_uppercase(),
-            shader.stage.name().to_ascii_uppercase(),
-            shader.name,
-            shader.stage.name()
+            "pub const {}_{}_SPV: &[u8] = &SpirvBytes(*include_bytes!(\"{out_dir}/{name}.{stage}.spv\")).0;",
+            name.to_ascii_uppercase(),
+            stage.to_ascii_uppercase(),
         )
         .unwrap();
     }
@@ -91,12 +67,84 @@ fn main() {
         assert!(status.success());
     }
 
-    for shader in SHADERS {
-        println!(
-            "cargo::rerun-if-changed={SHADER_ROOT}/{}.{}.glsl",
-            shader.name,
-            shader.stage.name()
-        )
+    for Shader { stage, name } in SHADERS {
+        let depfile = std::fs::read_to_string(format!("{out_dir}/{name}.{stage}.d")).unwrap();
+
+        struct Lexer<'a> {
+            bytes: &'a [u8],
+            index: usize,
+        }
+
+        impl<'a> Lexer<'a> {
+            fn new(bytes: &'a [u8]) -> Self {
+                Self { bytes, index: 0 }
+            }
+
+            fn is_empty(&self) -> bool {
+                self.index >= self.bytes.len()
+            }
+
+            fn skip(&mut self, b: u8) -> bool {
+                if self.bytes.get(self.index).is_some_and(|&x| x == b) {
+                    self.index += 1;
+                    true
+                } else {
+                    false
+                }
+            }
+
+            fn skip_to(&mut self, escape: u8, needle: u8) -> bool {
+                let mut escape_count = 0;
+                while let Some(&b) = self.bytes.get(self.index) {
+                    if b == escape {
+                        escape_count += 1;
+                    } else if b == needle {
+                        if escape_count & 1 == 0 {
+                            self.index += 1;
+                            return true;
+                        }
+                        escape_count = 0;
+                    } else {
+                        escape_count = 0;
+                    }
+                    self.index += 1;
+                }
+                false
+            }
+
+            fn read_to(&mut self, escape: u8, needle: u8) -> &[u8] {
+                let start = self.index;
+                let mut escape_count = 0;
+                while let Some(&b) = self.bytes.get(self.index) {
+                    if b == escape {
+                        escape_count += 1;
+                    } else if b == needle {
+                        if escape_count & 1 == 0 {
+                            break;
+                        }
+                        escape_count = 0;
+                    } else {
+                        escape_count = 0;
+                    }
+                    self.index += 1;
+                }
+                &self.bytes[start..self.index]
+            }
+        }
+
+        for line in depfile.lines() {
+            let mut lexer = Lexer::new(line.as_bytes());
+            if lexer.skip_to(b'\\', b':') {
+                lexer.skip(b' ');
+                while !lexer.is_empty() {
+                    let path = lexer.read_to(b'\\', b' ');
+                    if let Ok(path) = std::str::from_utf8(path) {
+                        println!("cargo::rerun-if-changed={path}");
+                    }
+                    lexer.skip(b' ');
+                }
+            }
+        }
     }
 
     println!("cargo::rerun-if-changed=build.rs");
index a616dee40a26a7ffd507dbaf0ff89504983a6a9a..bbefb7af11aa907e86258ee9ea5a821eb3419f29 100644 (file)
@@ -1,26 +1,11 @@
 #version 460
 
+#extension GL_GOOGLE_include_directive : require
+
 #extension GL_EXT_scalar_block_layout : require
 #extension GL_EXT_control_flow_attributes : require
 
-struct CachedGlyph {
-    uint x0;
-    uint x1;
-    uint y0;
-    uint y1;
-
-    float offset_x0;
-    float offset_x1;
-    float offset_y0;
-    float offset_y1;
-};
-
-struct GlyphInstance {
-    float x;
-    float y;
-    uint index;
-    uint color;
-};
+#include "primitive_types.h"
 
 layout(std430, set = 0, binding = 0) uniform uniformBuffer {
     uint screen_width;
diff --git a/title/shark-shaders/shaders/primitive_types.h b/title/shark-shaders/shaders/primitive_types.h
new file mode 100644 (file)
index 0000000..3b746bd
--- /dev/null
@@ -0,0 +1,19 @@
+
+struct CachedGlyph {
+    uint x0;
+    uint x1;
+    uint y0;
+    uint y1;
+
+    float offset_x0;
+    float offset_x1;
+    float offset_y0;
+    float offset_y1;
+};
+
+struct GlyphInstance {
+    float x;
+    float y;
+    uint index;
+    uint color;
+};