build(vulkan-shaders): source tool metadata at build time
This commit is contained in:
@@ -4,6 +4,7 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
ash = "0.38"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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())),
|
||||
|
||||
Reference in New Issue
Block a user