use std::ffi::c_void;
use windows::Win32::Graphics::Direct3D::{Fxc::*, ID3DBlob, ID3DInclude};
pub(crate) unsafe fn compile_shader(
source: &[u8],
file_name: windows::core::PCSTR,
entry: windows::core::PCSTR,
target: windows::core::PCSTR,
) -> windows::core::Result<ID3DBlob> {
let mut shader = None;
let mut errors = None;
let flags = if cfg!(debug_assertions) {
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION
} else {
D3DCOMPILE_OPTIMIZATION_LEVEL3
};
let result = unsafe {
D3DCompile(
source.as_ptr().cast::<c_void>(),
source.len(),
file_name,
None,
None::<&ID3DInclude>,
entry,
target,
flags,
0,
&mut shader,
Some(&mut errors),
)
};
if let Err(error) = result {
let message = errors
.map(|blob| unsafe {
let bytes = std::slice::from_raw_parts(
blob.GetBufferPointer().cast::<u8>(),
blob.GetBufferSize(),
);
String::from_utf8_lossy(bytes).into_owned()
})
.unwrap_or_else(|| error.message());
return Err(windows::core::Error::new(
windows::Win32::Foundation::E_FAIL,
message,
));
}
Ok(shader.expect("D3DCompile succeeded without producing a blob"))
}