qualia_core_db/wgsl_forge/emit/
dxc.rs1use crate::wgsl_forge::ForgeError;
2#[cfg(feature = "dxc")]
3use std::process::Command;
4
5#[cfg(feature = "dxc")]
7pub fn compile_hlsl_to_spirv(hlsl_source: &str, entry_point: &str) -> Result<Vec<u8>, ForgeError> {
8 let temp_dir = std::env::temp_dir();
12 let in_path = temp_dir.join(format!(
13 "qualia_dxc_in_{}_{}.hlsl",
14 std::process::id(),
15 entry_point
16 ));
17 let out_path = temp_dir.join(format!(
18 "qualia_dxc_out_{}_{}.spv",
19 std::process::id(),
20 entry_point
21 ));
22
23 std::fs::write(&in_path, hlsl_source)
24 .map_err(|e| ForgeError::Emission(format!("Failed to write HLSL temp file: {:?}", e)))?;
25
26 let in_path_str = in_path.to_str().unwrap();
27 let out_path_str = out_path.to_str().unwrap();
28
29 let dxc_path = resolve_dxc_cli_path();
39
40 let output = Command::new(&dxc_path)
43 .arg("-spirv")
44 .arg("-fspv-target-env=vulkan1.1")
45 .arg("-fvk-use-dx-layout")
46 .arg("-O3")
47 .arg("-T")
48 .arg("cs_6_0")
49 .arg("-E")
50 .arg(entry_point)
51 .arg(in_path_str)
52 .arg("-Fo")
53 .arg(out_path_str)
54 .output()
55 .map_err(|e| {
56 ForgeError::Emission(format!(
57 "Failed to execute DXC CLI at {}: {:?}",
58 dxc_path, e
59 ))
60 })?;
61
62 if !output.status.success() {
63 let _ = std::fs::remove_file(&in_path);
64 let _ = std::fs::remove_file(&out_path);
65 let err_str = String::from_utf8_lossy(&output.stderr);
66 let out_str = String::from_utf8_lossy(&output.stdout);
67 return Err(ForgeError::Emission(format!(
68 "DXC Compilation Failed:\nStdout: {}\nStderr: {}",
69 out_str, err_str
70 )));
71 }
72
73 let spirv_blob = std::fs::read(&out_path)
74 .map_err(|e| ForgeError::Emission(format!("Failed to read SPIRV output: {:?}", e)))?;
75 let _ = std::fs::remove_file(&in_path);
77 let _ = std::fs::remove_file(&out_path);
78 Ok(spirv_blob)
79}
80
81#[cfg(feature = "dxc")]
88fn resolve_dxc_cli_path() -> String {
89 if let Ok(p) = std::env::var("QUALIA_DXC_CLI_PATH") {
90 if !p.trim().is_empty() {
91 return p;
92 }
93 }
94 if let Ok(exe) = std::env::current_exe() {
96 if let Some(dir) = exe.parent() {
97 let dxc_exe = dir.join("dxc.exe");
98 if dxc_exe.exists() {
99 return dxc_exe.to_string_lossy().into_owned();
100 }
101 }
102 }
103 "dxc".to_string()
104}
105
106#[cfg(not(feature = "dxc"))]
108pub fn compile_hlsl_to_spirv(
109 _hlsl_source: &str,
110 _entry_point: &str,
111) -> Result<Vec<u8>, ForgeError> {
112 Err(ForgeError::Emission(
113 "HLSL compilation requires the 'dxc' feature".to_string(),
114 ))
115}