use crate::backend::{GpuBackend, ShaderHandle};
use crate::device::Device;
use anyhow::{Context, Result};
use std::sync::{Arc, Mutex};
pub struct ShaderModule {
backend: Arc<Mutex<Box<dyn GpuBackend>>>,
pub(crate) handle: ShaderHandle,
}
impl ShaderModule {
pub fn from_slang(device: &Device, source: &str) -> Result<Self> {
Self::from_slang_with_paths(device, source, &[])
}
pub fn from_slang_with_paths(device: &Device, source: &str, extra_paths: &[&str]) -> Result<Self> {
let library_paths = device.get_shader_search_paths()
.context("Failed to prepare shader library paths")?;
let all_paths: Vec<String> = library_paths
.iter()
.map(|p| p.to_string_lossy().into_owned())
.chain(extra_paths.iter().map(|s| s.to_string()))
.collect();
let path_refs: Vec<&str> = all_paths.iter().map(|s| s.as_str()).collect();
let mut backend = device.backend.lock().unwrap();
let handle = backend.create_shader_with_paths(device.handle, source, &path_refs)?;
Ok(Self {
backend: Arc::clone(&device.backend),
handle,
})
}
}
impl Drop for ShaderModule {
fn drop(&mut self) {
let mut backend = self.backend.lock().unwrap();
backend.destroy_shader(self.handle);
}
}
pub mod builtins {
pub const VERTEX_COLOR_2D: &str = r#"
struct VertexInput {
float2 position : POSITION;
float4 color : COLOR;
};
struct VertexOutput {
float4 position : SV_Position;
float4 color : COLOR;
};
[shader("vertex")]
VertexOutput vs_main(VertexInput input) {
VertexOutput output;
output.position = float4(input.position, 0.0, 1.0);
output.color = input.color;
return output;
}
[shader("fragment")]
float4 fs_main(VertexOutput input) : SV_Target {
return input.color;
}
"#;
pub const SOLID_COLOR: &str = r#"
struct VertexInput {
float2 position : POSITION;
};
struct VertexOutput {
float4 position : SV_Position;
};
cbuffer Uniforms {
float4 color;
};
[shader("vertex")]
VertexOutput vs_main(VertexInput input) {
VertexOutput output;
output.position = float4(input.position, 0.0, 1.0);
return output;
}
[shader("fragment")]
float4 fs_main(VertexOutput input) : SV_Target {
return color;
}
"#;
}