diff options
| -rw-r--r-- | adapters/fparkan-render-vulkan/Cargo.toml | 1 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/build.rs | 92 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/shader_manifest.rs | 36 |
3 files changed, 123 insertions, 6 deletions
diff --git a/adapters/fparkan-render-vulkan/Cargo.toml b/adapters/fparkan-render-vulkan/Cargo.toml index 2d6db04..e8f9817 100644 --- a/adapters/fparkan-render-vulkan/Cargo.toml +++ b/adapters/fparkan-render-vulkan/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true repository.workspace = true +build = "build.rs" [dependencies] ash = "0.38" diff --git a/adapters/fparkan-render-vulkan/build.rs b/adapters/fparkan-render-vulkan/build.rs new file mode 100644 index 0000000..d66c022 --- /dev/null +++ b/adapters/fparkan-render-vulkan/build.rs @@ -0,0 +1,92 @@ +//! Build-time shader tool metadata for Vulkan reports. + +use std::env; +use std::path::Path; +use std::process::Command; + +const SHADER_COMPILER_NAME: &str = "glslangValidator"; +const SPIRV_VALIDATOR_NAME: &str = "spirv-val"; + +fn main() { + println!("cargo:rerun-if-env-changed=PATH"); + println!("cargo:rerun-if-env-changed=FPARKAN_GLSLANG_VALIDATOR"); + println!("cargo:rerun-if-env-changed=FPARKAN_SPIRV_VAL"); + + emit_tool_metadata( + "FPARKAN_BUILD_SHADER_COMPILER", + &tool_path("FPARKAN_GLSLANG_VALIDATOR", SHADER_COMPILER_NAME), + ); + emit_tool_metadata( + "FPARKAN_BUILD_SPIRV_VALIDATOR", + &tool_path("FPARKAN_SPIRV_VAL", SPIRV_VALIDATOR_NAME), + ); +} + +fn tool_path(env_var: &str, fallback: &str) -> String { + env::var(env_var).unwrap_or_else(|_| fallback.to_string()) +} + +fn emit_tool_metadata(prefix: &str, tool: &str) { + let Some(path) = resolve_tool(tool) else { + return; + }; + println!("cargo:rerun-if-changed={}", path.display()); + let Some(version) = tool_version(&path) else { + return; + }; + let Some(binary_sha256) = tool_sha256(&path) else { + return; + }; + let name = path + .file_name() + .and_then(|value| value.to_str()) + .unwrap_or(tool) + .to_string(); + println!("cargo:rustc-env={prefix}_NAME={name}"); + println!("cargo:rustc-env={prefix}_VERSION={version}"); + println!("cargo:rustc-env={prefix}_SHA256={binary_sha256}"); +} + +fn resolve_tool(tool: &str) -> Option<std::path::PathBuf> { + let candidate = Path::new(tool); + if candidate.components().count() > 1 { + return candidate.is_file().then(|| candidate.to_path_buf()); + } + let output = Command::new("which").arg(tool).output().ok()?; + if !output.status.success() { + return None; + } + let path = String::from_utf8(output.stdout).ok()?; + let path = path.trim(); + (!path.is_empty()).then(|| path.into()) +} + +fn tool_version(path: &Path) -> Option<String> { + let output = Command::new(path).arg("--version").output().ok()?; + if !output.status.success() { + return None; + } + let stdout = String::from_utf8(output.stdout).ok()?; + stdout + .lines() + .find(|line| !line.trim().is_empty()) + .map(str::trim) + .map(|line| { + line.strip_prefix("Glslang Version: ") + .unwrap_or(line) + .to_string() + }) +} + +fn tool_sha256(path: &Path) -> Option<String> { + let output = Command::new("shasum") + .args(["-a", "256"]) + .arg(path) + .output() + .ok()?; + if !output.status.success() { + return None; + } + let stdout = String::from_utf8(output.stdout).ok()?; + stdout.split_whitespace().next().map(ToString::to_string) +} diff --git a/adapters/fparkan-render-vulkan/src/shader_manifest.rs b/adapters/fparkan-render-vulkan/src/shader_manifest.rs index 5c589cb..80b47a6 100644 --- a/adapters/fparkan-render-vulkan/src/shader_manifest.rs +++ b/adapters/fparkan-render-vulkan/src/shader_manifest.rs @@ -37,6 +37,30 @@ const TRIANGLE_FRAGMENT_COMPILE_COMMAND: &str = const TRIANGLE_FRAGMENT_VALIDATE_COMMAND: &str = "spirv-val --target-env vulkan1.0 adapters/fparkan-render-vulkan/shaders/triangle.frag.spv"; +fn shader_compiler_name() -> &'static str { + option_env!("FPARKAN_BUILD_SHADER_COMPILER_NAME").unwrap_or(SHADER_COMPILER_NAME) +} + +fn shader_compiler_version() -> &'static str { + option_env!("FPARKAN_BUILD_SHADER_COMPILER_VERSION").unwrap_or(SHADER_COMPILER_VERSION) +} + +fn shader_compiler_binary_sha256() -> &'static str { + option_env!("FPARKAN_BUILD_SHADER_COMPILER_SHA256").unwrap_or(SHADER_COMPILER_BINARY_SHA256) +} + +fn spirv_validator_name() -> &'static str { + option_env!("FPARKAN_BUILD_SPIRV_VALIDATOR_NAME").unwrap_or(SPIRV_VALIDATOR_NAME) +} + +fn spirv_validator_version() -> &'static str { + option_env!("FPARKAN_BUILD_SPIRV_VALIDATOR_VERSION").unwrap_or(SPIRV_VALIDATOR_VERSION) +} + +fn spirv_validator_binary_sha256() -> &'static str { + option_env!("FPARKAN_BUILD_SPIRV_VALIDATOR_SHA256").unwrap_or(SPIRV_VALIDATOR_BINARY_SHA256) +} + /// Shader tool metadata pinned in the Stage 0 manifest. #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct VulkanShaderToolManifest { @@ -247,14 +271,14 @@ pub fn validate_shader_manifest( schema: SHADER_MANIFEST_SCHEMA, target_env: SHADER_TARGET_ENV, compiler: VulkanShaderToolManifest { - name: SHADER_COMPILER_NAME, - version: SHADER_COMPILER_VERSION, - binary_sha256: SHADER_COMPILER_BINARY_SHA256, + name: shader_compiler_name(), + version: shader_compiler_version(), + binary_sha256: shader_compiler_binary_sha256(), }, validator: VulkanShaderToolManifest { - name: SPIRV_VALIDATOR_NAME, - version: SPIRV_VALIDATOR_VERSION, - binary_sha256: SPIRV_VALIDATOR_BINARY_SHA256, + name: spirv_validator_name(), + version: spirv_validator_version(), + binary_sha256: spirv_validator_binary_sha256(), }, modules: reports, manifest_hash: sha256_hex(&sha256(normalized.as_bytes())), |
