diff --git a/examples/dxc/Cargo.toml b/examples/dxc/Cargo.toml new file mode 100644 index 0000000000..f44ac4fe24 --- /dev/null +++ b/examples/dxc/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "dxc" +version = "0.9.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies] +bindings = { package = "dxc_bindings", path = "bindings" } +libloading = "0.7" +windows = { path = "../.." } diff --git a/examples/dxc/bindings/Cargo.toml b/examples/dxc/bindings/Cargo.toml new file mode 100644 index 0000000000..e66848c598 --- /dev/null +++ b/examples/dxc/bindings/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "dxc_bindings" +version = "0.9.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies] +windows = { path = "../../.." } + +[build-dependencies] +windows = { path = "../../.." } diff --git a/examples/dxc/bindings/build.rs b/examples/dxc/bindings/build.rs new file mode 100644 index 0000000000..794357c2c0 --- /dev/null +++ b/examples/dxc/bindings/build.rs @@ -0,0 +1,6 @@ +fn main() { + windows::build!( + Windows::Win32::Globalization::CP_UTF8, + Windows::Win32::Graphics::Hlsl::*, + ); +} diff --git a/examples/dxc/bindings/src/lib.rs b/examples/dxc/bindings/src/lib.rs new file mode 100644 index 0000000000..d9ddca77a8 --- /dev/null +++ b/examples/dxc/bindings/src/lib.rs @@ -0,0 +1 @@ +windows::include_bindings!(); diff --git a/examples/dxc/src/copy.hlsl b/examples/dxc/src/copy.hlsl new file mode 100644 index 0000000000..1d36a625ad --- /dev/null +++ b/examples/dxc/src/copy.hlsl @@ -0,0 +1,8 @@ +Texture2D g_input : register(t0, space0); +RWTexture2D g_output : register(u0, space0); + +[numthreads(8, 8, 1)] +void copyCs(uint3 dispatchThreadId : SV_DispatchThreadID) +{ + g_output[dispatchThreadId.xy] = g_input[dispatchThreadId.xy]; +} diff --git a/examples/dxc/src/main.rs b/examples/dxc/src/main.rs new file mode 100644 index 0000000000..8c44c1b54e --- /dev/null +++ b/examples/dxc/src/main.rs @@ -0,0 +1,108 @@ +use bindings::Windows::Win32::{ + Globalization::CP_UTF8, Graphics::Hlsl::*, System::SystemServices::BOOL, +}; +use libloading::{Library, Symbol}; +use std::path::Path; +use windows::*; + +// Only exists in newer DXC headers +const DXC_CP_UTF8: u32 = CP_UTF8; + +#[cfg(target_os = "windows")] +fn dxcompiler_lib_name() -> &'static Path { + Path::new("dxcompiler.dll") +} + +#[cfg(target_os = "linux")] +fn dxcompiler_lib_name() -> &'static Path { + Path::new("./libdxcompiler.so") +} + +#[cfg(target_os = "macos")] +fn dxcompiler_lib_name() -> &'static Path { + Path::new("./libdxcompiler.dynlib") +} + +fn blob_encoding_as_str(blob: &IDxcBlobEncoding) -> &str { + let mut known: BOOL = false.into(); + let mut cp = 0; + unsafe { blob.GetEncoding(known.set_abi(), cp.set_abi()) }.unwrap(); + assert!(bool::from(known)); + assert_eq!(cp, DXC_CP_UTF8); + unsafe { + let slice = std::slice::from_raw_parts( + blob.GetBufferPointer() as *const u8, + blob.GetBufferSize() - 1, + ); + std::str::from_utf8_unchecked(slice) + } +} + +fn main() -> windows::Result<()> { + let lib = unsafe { Library::new(dxcompiler_lib_name()) }.unwrap(); + let create: Symbol = unsafe { lib.get(b"DxcCreateInstance\0") }.unwrap(); + dbg!(&create); + + // let mut compiler: Option = None; + // let compiler = unsafe { create(&CLSID_DxcCompiler, &IDxcCompiler2::IID, compiler.set_abi()) } + // .and_some(compiler) + // .unwrap(); + let compiler: IDxcCompiler2 = unsafe { DxcCreateInstanceProc(&create, &CLSID_DxcCompiler) }?; + let library: IDxcLibrary = unsafe { DxcCreateInstanceProc(&create, &CLSID_DxcLibrary) }?; + + dbg!(&compiler, &library); + + let main_shader = include_str!("copy.hlsl"); + + let mut blob = None; + let shader_blob = unsafe { + library.CreateBlobWithEncodingFromPinned( + main_shader.as_ptr() as *const _, + main_shader.len() as u32, + DXC_CP_UTF8, + &mut blob, + ) + } + .and_some(blob)?; + dbg!(&shader_blob); + + let mut args = vec![]; + let defines = vec![]; + + let mut result = None; + let result = unsafe { + compiler.Compile( + shader_blob, + "copy.hlsl", + "copyCs", + "cs_6_5", + args.as_mut_ptr(), // Should not be mut? + args.len() as u32, + defines.as_ptr(), + defines.len() as u32, + None, + &mut result, + ) + } + .and_some(result)?; + + let mut status = HRESULT::default(); + unsafe { result.GetStatus(&mut status) }.ok()?; + if status.is_err() { + let mut errors = None; + let errors = unsafe { result.GetErrorBuffer(&mut errors) }.and_some(errors)?; + let errors = blob_encoding_as_str(&errors); + eprintln!("Compilation failed with {:?}: `{}`", status, errors); + status.ok() + } else { + let mut blob = None; + let blob = unsafe { result.GetResult(&mut blob) }.and_some(blob)?; + let shader = unsafe { + std::slice::from_raw_parts(blob.GetBufferPointer().cast::(), blob.GetBufferSize()) + }; + for c in shader.chunks(16) { + println!("{:02x?}", c); + } + Ok(()) + } +}