Skip to content

Commit

Permalink
examples: Add DirectXShaderCompiler
Browse files Browse the repository at this point in the history
  • Loading branch information
MarijnS95 committed May 13, 2021
1 parent 3b9262d commit fee70fb
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 0 deletions.
10 changes: 10 additions & 0 deletions examples/dxc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 = "../.." }
11 changes: 11 additions & 0 deletions examples/dxc/bindings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "dxc_bindings"
version = "0.9.0"
authors = ["Microsoft"]
edition = "2018"

[dependencies]
windows = { path = "../../.." }

[build-dependencies]
windows = { path = "../../.." }
6 changes: 6 additions & 0 deletions examples/dxc/bindings/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
windows::build!(
Windows::Win32::Globalization::CP_UTF8,
Windows::Win32::Graphics::Hlsl::*,
);
}
1 change: 1 addition & 0 deletions examples/dxc/bindings/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
windows::include_bindings!();
8 changes: 8 additions & 0 deletions examples/dxc/src/copy.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Texture2D<float4> g_input : register(t0, space0);
RWTexture2D<float4> g_output : register(u0, space0);

[numthreads(8, 8, 1)]
void copyCs(uint3 dispatchThreadId : SV_DispatchThreadID)
{
g_output[dispatchThreadId.xy] = g_input[dispatchThreadId.xy];
}
108 changes: 108 additions & 0 deletions examples/dxc/src/main.rs
Original file line number Diff line number Diff line change
@@ -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<DxcCreateInstanceProc> = unsafe { lib.get(b"DxcCreateInstance\0") }.unwrap();
dbg!(&create);

// let mut compiler: Option<IDxcCompiler2> = 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::<u8>(), blob.GetBufferSize())
};
for c in shader.chunks(16) {
println!("{:02x?}", c);
}
Ok(())
}
}

0 comments on commit fee70fb

Please sign in to comment.