release(0.3): substantially improve API ergonomics and remove build-time bindgen

This commit is contained in:
chyyran 2023-02-06 19:13:42 -05:00
parent 70b57831d3
commit e0fe82716e
18 changed files with 546 additions and 423 deletions

36
Cargo.lock generated
View file

@ -24,6 +24,14 @@ dependencies = [
"which", "which",
] ]
[[package]]
name = "bindings_generator"
version = "0.1.0"
dependencies = [
"bindgen",
"cmake",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -207,18 +215,18 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]] [[package]]
name = "spirv-to-dxil" name = "spirv-to-dxil"
version = "0.2.5" version = "0.3.0"
dependencies = [ dependencies = [
"bitflags",
"bytemuck", "bytemuck",
"spirv-to-dxil-sys", "spirv-to-dxil-sys",
"thiserror",
] ]
[[package]] [[package]]
name = "spirv-to-dxil-sys" name = "spirv-to-dxil-sys"
version = "0.2.3" version = "0.3.0"
dependencies = [ dependencies = [
"bindgen", "bytemuck",
"cmake", "cmake",
] ]
@ -233,6 +241,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.6"

View file

@ -3,4 +3,5 @@
members = [ members = [
"spirv-to-dxil", "spirv-to-dxil",
"spirv-to-dxil-sys", "spirv-to-dxil-sys",
"bindings_generator"
] ]

View file

@ -0,0 +1,11 @@
fn main() {
println!(
"cargo:rustc-env=TARGET={}",
std::env::var("TARGET").unwrap()
);
println!("cargo:rustc-env=HOST={}", std::env::var("HOST").unwrap());
println!(
"cargo:rustc-env=OUT_DIR={}",
std::env::var("OUT_DIR").unwrap()
);
}

View file

@ -0,0 +1,72 @@
use bindgen::callbacks::{EnumVariantValue, ParseCallbacks};
#[derive(Debug)]
pub struct SpirvToDxilCallbacks;
impl SpirvToDxilCallbacks {
pub fn rename_shader_stage(variant: &str) -> Option<String> {
match variant {
"DXIL_SPIRV_SHADER_NONE" => Some("None".into()),
"DXIL_SPIRV_SHADER_VERTEX" => Some("Vertex".into()),
"DXIL_SPIRV_SHADER_TESS_CTRL" => Some("TesselationControl".into()),
"DXIL_SPIRV_SHADER_TESS_EVAL" => Some("TesselationEvaluation".into()),
"DXIL_SPIRV_SHADER_GEOMETRY" => Some("Geometry".into()),
"DXIL_SPIRV_SHADER_FRAGMENT" => Some("Fragment".into()),
"DXIL_SPIRV_SHADER_COMPUTE" => Some("Compute".into()),
"DXIL_SPIRV_SHADER_KERNEL" => Some("Kernel".into()),
_ => None
}
}
pub fn rename_shader_model(variant: &str) -> Option<String> {
Some(variant.replace("SHADER_MODEL_", "ShaderModel"))
}
pub fn rename_flip_mode(variant: &str) -> Option<String> {
Some(variant.replace("DXIL_SPIRV_", ""))
}
pub fn rename_validator_version(variant: &str, value: EnumVariantValue) -> Option<String> {
match value {
EnumVariantValue::Unsigned(0)
| EnumVariantValue::Signed(0) => Some("None".into()),
_ => Some(variant.replace("DXIL_VALIDATOR_", "Validator"))
}
}
}
impl ParseCallbacks for SpirvToDxilCallbacks {
fn enum_variant_name(
&self,
enum_name: Option<&str>,
original_variant_name: &str,
variant_value: EnumVariantValue,
) -> Option<String> {
match enum_name {
Some("dxil_spirv_shader_stage") => {
SpirvToDxilCallbacks::rename_shader_stage(original_variant_name)
}
Some("enum dxil_shader_model") => {
SpirvToDxilCallbacks::rename_shader_model(original_variant_name)
}
Some("enum dxil_validator_version") => {
SpirvToDxilCallbacks::rename_validator_version(original_variant_name, variant_value)
}
Some("enum dxil_spirv_yz_flip_mode") => {
SpirvToDxilCallbacks::rename_flip_mode(original_variant_name)
}
_ => {
eprintln!("skipping {:?}", enum_name);
None
},
}
}
fn item_name(&self, original_item_name: &str) -> Option<String> {
match original_item_name {
"dxil_spirv_runtime_conf__bindgen_ty_1" => Some("dxil_spirv_runtime_conf_runtime_cbv".into()),
"dxil_spirv_runtime_conf__bindgen_ty_2" => Some("dxil_spirv_runtime_conf_push_cbv".into()),
"dxil_spirv_runtime_conf__bindgen_ty_3" => Some("dxil_spirv_runtime_conf_flip_conf".into()),
_ => None
}
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "spirv-to-dxil-sys" name = "spirv-to-dxil-sys"
version = "0.2.6" version = "0.3.0"
edition = "2021" edition = "2021"
description = "Raw bindings to spirv-to-dxil" description = "Raw bindings to spirv-to-dxil"
license = "MIT" license = "MIT"
@ -10,12 +10,8 @@ readme = "../README.md"
[lib] [lib]
[dependencies]
bytemuck = "1.13.0"
[build-dependencies] [build-dependencies]
bindgen = "0.63.0"
cmake = "0.1" cmake = "0.1"
[features]
included-bindings = []
[package.metadata.docs.rs]
features = ["included-bindings"]

View file

@ -1,11 +1,12 @@
use cmake::Config; use cmake::Config;
use std::{env, fs::File, path::{Path, PathBuf}}; use std::{
env,
path::Path
};
fn main() { fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
if env::var("DOCS_RS").is_ok() { if env::var("DOCS_RS").is_ok() {
println!("cargo:warning=Skipping spirv-to-dxil native build for docs.rs."); println!("cargo:warning=Skipping spirv-to-dxil native build for docs.rs.");
File::create(out_dir.join("bindings.rs")).unwrap();
return; return;
} }
@ -16,9 +17,6 @@ fn main() {
let object_dst = cmake_dst.join("build/mesa/lib"); let object_dst = cmake_dst.join("build/mesa/lib");
let header_dst = cmake_dst.join("build/mesa/src/mesa/src/microsoft/spirv_to_dxil");
let header_compiler_dst = cmake_dst.join("build/mesa/src/mesa/src/microsoft/compiler");
println!("cargo:rustc-link-search=native={}", object_dst.display()); println!("cargo:rustc-link-search=native={}", object_dst.display());
println!("cargo:rustc-link-lib=static=spirv_to_dxil"); println!("cargo:rustc-link-lib=static=spirv_to_dxil");
@ -51,19 +49,4 @@ fn main() {
println!("cargo:rustc-link-search=native={}", search_dir); println!("cargo:rustc-link-search=native={}", search_dir);
println!("cargo:rustc-link-lib=dylib=stdc++"); println!("cargo:rustc-link-lib=dylib=stdc++");
} }
let bindings = bindgen::Builder::default()
.header("native/wrapper.h")
.clang_arg(format!("-F{}", header_dst.display()))
.clang_arg(format!("-F{}", header_compiler_dst.display()))
.clang_arg(format!("-I{}", header_dst.display()))
.clang_arg(format!("-I{}", header_compiler_dst.display()))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_dir.join("bindings.rs"))
.expect("Couldn't write bindings!");
} }

View file

@ -20,25 +20,33 @@ pub const WCHAR_MAX: u32 = 65535;
pub const WINT_MIN: u32 = 0; pub const WINT_MIN: u32 = 0;
pub const WINT_MAX: u32 = 65535; pub const WINT_MAX: u32 = 65535;
pub const DXIL_SPIRV_MAX_VIEWPORT: u32 = 16; pub const DXIL_SPIRV_MAX_VIEWPORT: u32 = 16;
pub const dxil_shader_model_SHADER_MODEL_6_0: dxil_shader_model = 393216; #[repr(i32)]
pub const dxil_shader_model_SHADER_MODEL_6_1: dxil_shader_model = 393217; #[non_exhaustive]
pub const dxil_shader_model_SHADER_MODEL_6_2: dxil_shader_model = 393218; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub const dxil_shader_model_SHADER_MODEL_6_3: dxil_shader_model = 393219; pub enum dxil_shader_model {
pub const dxil_shader_model_SHADER_MODEL_6_4: dxil_shader_model = 393220; ShaderModel6_0 = 393216,
pub const dxil_shader_model_SHADER_MODEL_6_5: dxil_shader_model = 393221; ShaderModel6_1 = 393217,
pub const dxil_shader_model_SHADER_MODEL_6_6: dxil_shader_model = 393222; ShaderModel6_2 = 393218,
pub const dxil_shader_model_SHADER_MODEL_6_7: dxil_shader_model = 393223; ShaderModel6_3 = 393219,
pub type dxil_shader_model = ::std::os::raw::c_int; ShaderModel6_4 = 393220,
pub const dxil_validator_version_NO_DXIL_VALIDATION: dxil_validator_version = 0; ShaderModel6_5 = 393221,
pub const dxil_validator_version_DXIL_VALIDATOR_1_0: dxil_validator_version = 65536; ShaderModel6_6 = 393222,
pub const dxil_validator_version_DXIL_VALIDATOR_1_1: dxil_validator_version = 65537; ShaderModel6_7 = 393223,
pub const dxil_validator_version_DXIL_VALIDATOR_1_2: dxil_validator_version = 65538; }
pub const dxil_validator_version_DXIL_VALIDATOR_1_3: dxil_validator_version = 65539; #[repr(i32)]
pub const dxil_validator_version_DXIL_VALIDATOR_1_4: dxil_validator_version = 65540; #[non_exhaustive]
pub const dxil_validator_version_DXIL_VALIDATOR_1_5: dxil_validator_version = 65541; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub const dxil_validator_version_DXIL_VALIDATOR_1_6: dxil_validator_version = 65542; pub enum dxil_validator_version {
pub const dxil_validator_version_DXIL_VALIDATOR_1_7: dxil_validator_version = 65543; None = 0,
pub type dxil_validator_version = ::std::os::raw::c_int; Validator1_0 = 65536,
Validator1_1 = 65537,
Validator1_2 = 65538,
Validator1_3 = 65539,
Validator1_4 = 65540,
Validator1_5 = 65541,
Validator1_6 = 65542,
Validator1_7 = 65543,
}
pub type wchar_t = ::std::os::raw::c_ushort; pub type wchar_t = ::std::os::raw::c_ushort;
pub type max_align_t = f64; pub type max_align_t = f64;
pub type va_list = *mut ::std::os::raw::c_char; pub type va_list = *mut ::std::os::raw::c_char;
@ -76,15 +84,18 @@ pub type uint_fast32_t = ::std::os::raw::c_uint;
pub type uint_fast64_t = ::std::os::raw::c_ulonglong; pub type uint_fast64_t = ::std::os::raw::c_ulonglong;
pub type intmax_t = ::std::os::raw::c_longlong; pub type intmax_t = ::std::os::raw::c_longlong;
pub type uintmax_t = ::std::os::raw::c_ulonglong; pub type uintmax_t = ::std::os::raw::c_ulonglong;
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_NONE: dxil_spirv_shader_stage = -1; #[repr(i32)]
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_VERTEX: dxil_spirv_shader_stage = 0; #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_TESS_CTRL: dxil_spirv_shader_stage = 1; pub enum dxil_spirv_shader_stage {
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_TESS_EVAL: dxil_spirv_shader_stage = 2; None = -1,
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_GEOMETRY: dxil_spirv_shader_stage = 3; Vertex = 0,
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_FRAGMENT: dxil_spirv_shader_stage = 4; TesselationControl = 1,
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_COMPUTE: dxil_spirv_shader_stage = 5; TesselationEvaluation = 2,
pub const dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_KERNEL: dxil_spirv_shader_stage = 14; Geometry = 3,
pub type dxil_spirv_shader_stage = ::std::os::raw::c_int; Fragment = 4,
Compute = 5,
Kernel = 14,
}
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub union dxil_spirv_const_value { pub union dxil_spirv_const_value {
@ -495,7 +506,7 @@ pub struct dxil_spirv_vertex_runtime_data {
pub first_vertex: u32, pub first_vertex: u32,
pub base_instance: u32, pub base_instance: u32,
pub is_indexed_draw: bool, pub is_indexed_draw: bool,
pub __bindgen_anon_1: dxil_spirv_vertex_runtime_data__bindgen_ty_1, pub _dxil_spirv_anon1: dxil_spirv_vertex_runtime_data__bindgen_ty_1,
pub draw_id: u32, pub draw_id: u32,
pub viewport_width: f32, pub viewport_width: f32,
pub viewport_height: f32, pub viewport_height: f32,
@ -505,7 +516,7 @@ pub struct dxil_spirv_vertex_runtime_data {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub union dxil_spirv_vertex_runtime_data__bindgen_ty_1 { pub union dxil_spirv_vertex_runtime_data__bindgen_ty_1 {
pub yz_flip_mask: u32, pub yz_flip_mask: u32,
pub __bindgen_anon_1: dxil_spirv_vertex_runtime_data__bindgen_ty_1__bindgen_ty_1, pub _dxil_spirv_anon1: dxil_spirv_vertex_runtime_data__bindgen_ty_1__bindgen_ty_1,
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -674,22 +685,64 @@ fn bindgen_test_layout_dxil_spirv_vertex_runtime_data() {
) )
); );
} }
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_NONE: dxil_spirv_yz_flip_mode = 0; impl dxil_spirv_yz_flip_mode {
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_Y_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = 1; pub const YZ_FLIP_NONE: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(0);
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_Z_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = 2; }
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = 3; impl dxil_spirv_yz_flip_mode {
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_Y_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = 4; pub const Y_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(1);
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_Z_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = 8; }
pub const dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = 12; impl dxil_spirv_yz_flip_mode {
pub type dxil_spirv_yz_flip_mode = ::std::os::raw::c_int; pub const Z_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(2);
}
impl dxil_spirv_yz_flip_mode {
pub const YZ_FLIP_UNCONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(3);
}
impl dxil_spirv_yz_flip_mode {
pub const Y_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(4);
}
impl dxil_spirv_yz_flip_mode {
pub const Z_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(8);
}
impl dxil_spirv_yz_flip_mode {
pub const YZ_FLIP_CONDITIONAL: dxil_spirv_yz_flip_mode = dxil_spirv_yz_flip_mode(12);
}
impl ::std::ops::BitOr<dxil_spirv_yz_flip_mode> for dxil_spirv_yz_flip_mode {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
dxil_spirv_yz_flip_mode(self.0 | other.0)
}
}
impl ::std::ops::BitOrAssign for dxil_spirv_yz_flip_mode {
#[inline]
fn bitor_assign(&mut self, rhs: dxil_spirv_yz_flip_mode) {
self.0 |= rhs.0;
}
}
impl ::std::ops::BitAnd<dxil_spirv_yz_flip_mode> for dxil_spirv_yz_flip_mode {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
dxil_spirv_yz_flip_mode(self.0 & other.0)
}
}
impl ::std::ops::BitAndAssign for dxil_spirv_yz_flip_mode {
#[inline]
fn bitand_assign(&mut self, rhs: dxil_spirv_yz_flip_mode) {
self.0 &= rhs.0;
}
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct dxil_spirv_yz_flip_mode(pub ::std::os::raw::c_int);
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct dxil_spirv_runtime_conf { pub struct dxil_spirv_runtime_conf {
pub runtime_data_cbv: dxil_spirv_runtime_conf__bindgen_ty_1, pub runtime_data_cbv: dxil_spirv_runtime_conf_runtime_cbv,
pub push_constant_cbv: dxil_spirv_runtime_conf__bindgen_ty_2, pub push_constant_cbv: dxil_spirv_runtime_conf_push_cbv,
pub zero_based_vertex_instance_id: bool, pub zero_based_vertex_instance_id: bool,
pub zero_based_compute_workgroup_id: bool, pub zero_based_compute_workgroup_id: bool,
pub yz_flip: dxil_spirv_runtime_conf__bindgen_ty_3, pub yz_flip: dxil_spirv_runtime_conf_flip_conf,
pub read_only_images_as_srvs: bool, pub read_only_images_as_srvs: bool,
pub force_sample_rate_shading: bool, pub force_sample_rate_shading: bool,
pub lower_view_index: bool, pub lower_view_index: bool,
@ -697,29 +750,26 @@ pub struct dxil_spirv_runtime_conf {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct dxil_spirv_runtime_conf__bindgen_ty_1 { pub struct dxil_spirv_runtime_conf_runtime_cbv {
pub register_space: u32, pub register_space: u32,
pub base_shader_register: u32, pub base_shader_register: u32,
} }
#[test] #[test]
fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_1() { fn bindgen_test_layout_dxil_spirv_runtime_conf_runtime_cbv() {
const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf__bindgen_ty_1> = const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf_runtime_cbv> =
::std::mem::MaybeUninit::uninit(); ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr(); let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<dxil_spirv_runtime_conf__bindgen_ty_1>(), ::std::mem::size_of::<dxil_spirv_runtime_conf_runtime_cbv>(),
8usize, 8usize,
concat!( concat!("Size of: ", stringify!(dxil_spirv_runtime_conf_runtime_cbv))
"Size of: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_1)
)
); );
assert_eq!( assert_eq!(
::std::mem::align_of::<dxil_spirv_runtime_conf__bindgen_ty_1>(), ::std::mem::align_of::<dxil_spirv_runtime_conf_runtime_cbv>(),
4usize, 4usize,
concat!( concat!(
"Alignment of ", "Alignment of ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_1) stringify!(dxil_spirv_runtime_conf_runtime_cbv)
) )
); );
assert_eq!( assert_eq!(
@ -727,7 +777,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_1() {
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_1), stringify!(dxil_spirv_runtime_conf_runtime_cbv),
"::", "::",
stringify!(register_space) stringify!(register_space)
) )
@ -737,7 +787,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_1() {
4usize, 4usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_1), stringify!(dxil_spirv_runtime_conf_runtime_cbv),
"::", "::",
stringify!(base_shader_register) stringify!(base_shader_register)
) )
@ -745,29 +795,26 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_1() {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct dxil_spirv_runtime_conf__bindgen_ty_2 { pub struct dxil_spirv_runtime_conf_push_cbv {
pub register_space: u32, pub register_space: u32,
pub base_shader_register: u32, pub base_shader_register: u32,
} }
#[test] #[test]
fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_2() { fn bindgen_test_layout_dxil_spirv_runtime_conf_push_cbv() {
const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf__bindgen_ty_2> = const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf_push_cbv> =
::std::mem::MaybeUninit::uninit(); ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr(); let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<dxil_spirv_runtime_conf__bindgen_ty_2>(), ::std::mem::size_of::<dxil_spirv_runtime_conf_push_cbv>(),
8usize, 8usize,
concat!( concat!("Size of: ", stringify!(dxil_spirv_runtime_conf_push_cbv))
"Size of: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_2)
)
); );
assert_eq!( assert_eq!(
::std::mem::align_of::<dxil_spirv_runtime_conf__bindgen_ty_2>(), ::std::mem::align_of::<dxil_spirv_runtime_conf_push_cbv>(),
4usize, 4usize,
concat!( concat!(
"Alignment of ", "Alignment of ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_2) stringify!(dxil_spirv_runtime_conf_push_cbv)
) )
); );
assert_eq!( assert_eq!(
@ -775,7 +822,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_2() {
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_2), stringify!(dxil_spirv_runtime_conf_push_cbv),
"::", "::",
stringify!(register_space) stringify!(register_space)
) )
@ -785,7 +832,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_2() {
4usize, 4usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_2), stringify!(dxil_spirv_runtime_conf_push_cbv),
"::", "::",
stringify!(base_shader_register) stringify!(base_shader_register)
) )
@ -793,30 +840,27 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_2() {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct dxil_spirv_runtime_conf__bindgen_ty_3 { pub struct dxil_spirv_runtime_conf_flip_conf {
pub mode: dxil_spirv_yz_flip_mode, pub mode: dxil_spirv_yz_flip_mode,
pub y_mask: u16, pub y_mask: u16,
pub z_mask: u16, pub z_mask: u16,
} }
#[test] #[test]
fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_3() { fn bindgen_test_layout_dxil_spirv_runtime_conf_flip_conf() {
const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf__bindgen_ty_3> = const UNINIT: ::std::mem::MaybeUninit<dxil_spirv_runtime_conf_flip_conf> =
::std::mem::MaybeUninit::uninit(); ::std::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr(); let ptr = UNINIT.as_ptr();
assert_eq!( assert_eq!(
::std::mem::size_of::<dxil_spirv_runtime_conf__bindgen_ty_3>(), ::std::mem::size_of::<dxil_spirv_runtime_conf_flip_conf>(),
8usize, 8usize,
concat!( concat!("Size of: ", stringify!(dxil_spirv_runtime_conf_flip_conf))
"Size of: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_3)
)
); );
assert_eq!( assert_eq!(
::std::mem::align_of::<dxil_spirv_runtime_conf__bindgen_ty_3>(), ::std::mem::align_of::<dxil_spirv_runtime_conf_flip_conf>(),
4usize, 4usize,
concat!( concat!(
"Alignment of ", "Alignment of ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_3) stringify!(dxil_spirv_runtime_conf_flip_conf)
) )
); );
assert_eq!( assert_eq!(
@ -824,7 +868,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_3() {
0usize, 0usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_3), stringify!(dxil_spirv_runtime_conf_flip_conf),
"::", "::",
stringify!(mode) stringify!(mode)
) )
@ -834,7 +878,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_3() {
4usize, 4usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_3), stringify!(dxil_spirv_runtime_conf_flip_conf),
"::", "::",
stringify!(y_mask) stringify!(y_mask)
) )
@ -844,7 +888,7 @@ fn bindgen_test_layout_dxil_spirv_runtime_conf__bindgen_ty_3() {
6usize, 6usize,
concat!( concat!(
"Offset of field: ", "Offset of field: ",
stringify!(dxil_spirv_runtime_conf__bindgen_ty_3), stringify!(dxil_spirv_runtime_conf_flip_conf),
"::", "::",
stringify!(z_mask) stringify!(z_mask)
) )

View file

@ -2,22 +2,65 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
#[cfg(feature = "included-bindings")]
mod bindings; mod bindings;
#[cfg(feature = "included-bindings")] use bytemuck::NoUninit;
pub use bindings::*; pub use bindings::*;
#[cfg(test)] impl Default for dxil_spirv_yz_flip_mode {
mod tests { fn default() -> Self {
use super::*; dxil_spirv_yz_flip_mode::YZ_FLIP_NONE
}
}
#[test] // runtime cbv
fn it_works() { impl Default for dxil_spirv_runtime_conf_runtime_cbv {
unsafe { fn default() -> Self {
eprintln!("{:x?}", spirv_to_dxil_get_version()); Self {
register_space: 0,
base_shader_register: 0,
} }
} }
} }
// push cbv
impl Default for dxil_spirv_runtime_conf_push_cbv {
fn default() -> Self {
Self {
register_space: 0,
base_shader_register: 0,
}
}
}
// flip options
impl Default for dxil_spirv_runtime_conf_flip_conf {
fn default() -> Self {
Self {
mode: Default::default(),
y_mask: 0,
z_mask: 0,
}
}
}
impl Default for dxil_spirv_runtime_conf {
fn default() -> Self {
Self {
runtime_data_cbv: Default::default(),
push_constant_cbv: Default::default(),
zero_based_vertex_instance_id: true,
zero_based_compute_workgroup_id: false,
yz_flip: Default::default(),
read_only_images_as_srvs: false,
force_sample_rate_shading: false,
lower_view_index: false,
lower_view_index_to_rt_layer: false,
}
}
}
unsafe impl NoUninit for dxil_spirv_vertex_runtime_data { }
unsafe impl NoUninit for dxil_spirv_vertex_runtime_data__bindgen_ty_1 { }
unsafe impl NoUninit for dxil_spirv_vertex_runtime_data__bindgen_ty_1__bindgen_ty_1 { }
unsafe impl NoUninit for dxil_spirv_compute_runtime_data { }

View file

@ -1,17 +1,16 @@
[package] [package]
name = "spirv-to-dxil" name = "spirv-to-dxil"
version = "0.2.6" version = "0.3.0"
edition = "2021" edition = "2021"
description = "Rust bindings to spirv-to-dxil" description = "Rust bindings to spirv-to-dxil"
license = "MIT" license = "MIT"
repository = "https://github.com/SnowflakePowered/spirv-to-dxil-rs" repository = "https://github.com/SnowflakePowered/spirv-to-dxil-rs"
keywords = ["SPIR-V", "DXIL"] keywords = ["SPIR-V", "DXIL"]
readme = "../README.md" readme = "../README.md"
[lib] [lib]
[dependencies] [dependencies]
spirv-to-dxil-sys = { version = "0.2", path = "../spirv-to-dxil-sys" } spirv-to-dxil-sys = { version = "0.3", path = "../spirv-to-dxil-sys" }
bitflags = "1.3.2" thiserror = "1.0.38"
[dev-dependencies]
bytemuck = "1.13.0" bytemuck = "1.13.0"

View file

@ -1,81 +0,0 @@
/// Configuration options for CBVs
#[derive(Default, Debug, Clone)]
pub struct ConstantBufferConfig {
pub register_space: u32,
pub base_shader_register: u32,
}
/// Configuration options for SPIR-V YZ flip mode.
#[derive(Default, Debug, Clone)]
pub struct FlipConfig {
pub mode: crate::FlipMode,
pub y_mask: u16,
pub z_mask: u16,
}
#[derive(Debug, Clone)]
/// Runtime configuration options for the SPIR-V compilation.
pub struct RuntimeConfig {
pub runtime_data_cbv: ConstantBufferConfig,
pub push_constant_cbv: ConstantBufferConfig,
/// Set true if vertex and instance ids have already been converted to
/// zero-based. Otherwise, runtime_data will be required to lower them.
pub zero_based_vertex_instance_id: bool,
/// Set true if workgroup base is known to be zero
pub zero_based_compute_workgroup_id: bool,
pub yz_flip: FlipConfig,
/// The caller supports read-only images to be turned into SRV accesses,
/// which allows us to run the nir_opt_access() pass
pub read_only_images_as_srvs: bool,
/// Force sample rate shading on a fragment shader
pub force_sample_rate_shading: bool,
/// View index needs to be lowered to a UBO lookup
pub lower_view_index: bool,
/// View index also needs to be forwarded to RT layer output
pub lower_view_index_to_rt_layer: bool,
}
impl Default for RuntimeConfig {
fn default() -> Self {
RuntimeConfig {
runtime_data_cbv: ConstantBufferConfig {
register_space: 31,
base_shader_register: 0,
},
push_constant_cbv: Default::default(),
zero_based_vertex_instance_id: true,
zero_based_compute_workgroup_id: false,
yz_flip: Default::default(),
read_only_images_as_srvs: false,
force_sample_rate_shading: false,
lower_view_index: false,
lower_view_index_to_rt_layer: false,
}
}
}
impl From<RuntimeConfig> for spirv_to_dxil_sys::dxil_spirv_runtime_conf {
fn from(value: RuntimeConfig) -> Self {
spirv_to_dxil_sys::dxil_spirv_runtime_conf {
runtime_data_cbv: spirv_to_dxil_sys::dxil_spirv_runtime_conf__bindgen_ty_1 {
register_space: value.runtime_data_cbv.register_space,
base_shader_register: value.runtime_data_cbv.base_shader_register,
},
push_constant_cbv: spirv_to_dxil_sys::dxil_spirv_runtime_conf__bindgen_ty_2 {
register_space: value.push_constant_cbv.register_space,
base_shader_register: value.push_constant_cbv.base_shader_register,
},
zero_based_vertex_instance_id: value.zero_based_vertex_instance_id,
zero_based_compute_workgroup_id: value.zero_based_compute_workgroup_id,
yz_flip: spirv_to_dxil_sys::dxil_spirv_runtime_conf__bindgen_ty_3 {
mode: value.yz_flip.mode.bits(),
y_mask: value.yz_flip.y_mask,
z_mask: value.yz_flip.z_mask,
},
read_only_images_as_srvs: value.read_only_images_as_srvs,
force_sample_rate_shading: value.force_sample_rate_shading,
lower_view_index: value.lower_view_index,
lower_view_index_to_rt_layer: value.lower_view_index_to_rt_layer,
}
}
}

View file

@ -0,0 +1,23 @@
/// Configuration options for the runtime data constant buffer if required.
pub use spirv_to_dxil_sys::dxil_spirv_runtime_conf_runtime_cbv as RuntimeDataBufferConfig;
/// Configuration options for the push constant buffer if required
pub use spirv_to_dxil_sys::dxil_spirv_runtime_conf_push_cbv as PushConstantBufferConfig;
/// Configuration options for SPIR-V YZ flip mode.
pub use spirv_to_dxil_sys::dxil_spirv_runtime_conf_flip_conf as FlipConfig;
/// Runtime configuration options for the SPIR-V compilation.
pub use spirv_to_dxil_sys::dxil_spirv_runtime_conf as RuntimeConfig;
/// The DXIL shader model to target.
pub use spirv_to_dxil_sys::dxil_shader_model as ShaderModel;
/// The validator version to target. Requires `dxil.dll` in path.
pub use spirv_to_dxil_sys::dxil_validator_version as ValidatorVersion;
/// The shader stage of the input.
pub use spirv_to_dxil_sys::dxil_spirv_shader_stage as ShaderStage;
/// The flip mode to use when compiling the shader.
pub use spirv_to_dxil_sys::dxil_spirv_yz_flip_mode as FlipMode;

View file

@ -1,133 +0,0 @@
use bitflags::bitflags;
#[derive(Copy, Clone, Debug)]
pub enum ShaderStage {
None,
Vertex,
TesselationControl,
TesselationEvaluation,
Geometry,
Fragment,
Compute,
Kernel,
}
impl From<ShaderStage> for spirv_to_dxil_sys::dxil_spirv_shader_stage {
fn from(value: ShaderStage) -> Self {
match value {
ShaderStage::None => spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_NONE,
ShaderStage::Vertex => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_VERTEX
}
ShaderStage::TesselationControl => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_TESS_CTRL
}
ShaderStage::TesselationEvaluation => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_TESS_EVAL
}
ShaderStage::Geometry => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_GEOMETRY
}
ShaderStage::Fragment => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_FRAGMENT
}
ShaderStage::Compute => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_COMPUTE
}
ShaderStage::Kernel => {
spirv_to_dxil_sys::dxil_spirv_shader_stage_DXIL_SPIRV_SHADER_KERNEL
}
}
}
}
#[derive(Copy, Clone, Debug)]
#[non_exhaustive]
pub enum ShaderModel {
ShaderModel6_0,
ShaderModel6_1,
ShaderModel6_2,
ShaderModel6_3,
ShaderModel6_4,
ShaderModel6_5,
ShaderModel6_6,
ShaderModel6_7,
}
impl From<ShaderModel> for spirv_to_dxil_sys::dxil_shader_model {
fn from(value: ShaderModel) -> Self {
match value {
ShaderModel::ShaderModel6_0 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_0,
ShaderModel::ShaderModel6_1 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_1,
ShaderModel::ShaderModel6_2 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_2,
ShaderModel::ShaderModel6_3 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_3,
ShaderModel::ShaderModel6_4 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_4,
ShaderModel::ShaderModel6_5 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_5,
ShaderModel::ShaderModel6_6 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_6,
ShaderModel::ShaderModel6_7 => spirv_to_dxil_sys::dxil_shader_model_SHADER_MODEL_6_7,
}
}
}
#[derive(Copy, Clone, Debug)]
#[non_exhaustive]
pub enum ValidatorVersion {
None,
Validator1_0,
Validator1_1,
Validator1_2,
Validator1_3,
Validator1_4,
Validator1_5,
Validator1_6,
Validator1_7,
}
impl From<ValidatorVersion> for spirv_to_dxil_sys::dxil_validator_version {
fn from(value: ValidatorVersion) -> Self {
match value {
ValidatorVersion::None => spirv_to_dxil_sys::dxil_validator_version_NO_DXIL_VALIDATION,
ValidatorVersion::Validator1_0 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_0
}
ValidatorVersion::Validator1_1 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_1
}
ValidatorVersion::Validator1_2 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_2
}
ValidatorVersion::Validator1_3 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_3
}
ValidatorVersion::Validator1_4 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_4
}
ValidatorVersion::Validator1_5 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_5
}
ValidatorVersion::Validator1_6 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_6
}
ValidatorVersion::Validator1_7 => {
spirv_to_dxil_sys::dxil_validator_version_DXIL_VALIDATOR_1_7
}
}
}
}
bitflags! {
#[derive(Default)]
pub struct FlipMode: spirv_to_dxil_sys::dxil_spirv_yz_flip_mode {
/// No YZ flip
const NONE = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_NONE;
/// Y-flip is unconditional: pos.y = -pos.y
const Y_FLIP_UNCONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_Y_FLIP_UNCONDITIONAL;
/// Z-flip is unconditional: pos.z = -pos.z + 1.0f
const Z_FLIP_UNCONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_Z_FLIP_UNCONDITIONAL;
const YZ_FLIP_UNCONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_UNCONDITIONAL;
const Y_FLIP_CONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_Y_FLIP_CONDITIONAL;
/// Z-flip is unconditional: pos.z = -pos.z + 1.0f
const Z_FLIP_CONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_Z_FLIP_CONDITIONAL;
const YZ_FLIP_CONDITIONAL = spirv_to_dxil_sys::dxil_spirv_yz_flip_mode_DXIL_SPIRV_YZ_FLIP_CONDITIONAL;
}
}

View file

@ -1,4 +1,13 @@
use thiserror::Error;
#[derive(Debug, Error)]
/// Error type for spirv-to-dxil.
pub enum SpirvToDxilError { pub enum SpirvToDxilError {
/// An error occurred when compiling SPIR-V to DXIL.
#[error("An error occurred when compiled to DXIL: {0}.")]
CompilerError(String), CompilerError(String),
RegisterSpaceOverflow(usize) /// The requested register space for a push or runtime constant block is beyond
/// the limit of 31.
#[error("Register space {0} is beyond the limit of 31.")]
RegisterSpaceOverflow(u32)
} }

View file

@ -1,20 +1,37 @@
mod config; //! Rust bindings for [spirv-to-dxil](https://gitlab.freedesktop.org/mesa/mesa/-/tree/main/src/microsoft/spirv_to_dxil).
mod enums; //!
//! For the lower-level C interface, see the [spirv-to-dxil-sys](https://docs.rs/spirv-to-dxil-sys/) crate.
//!
//! ## Push Constant Buffers
//! SPIR-V shaders that use Push Constants must choose register assignments that correspond with the Root Descriptor that the compiled shader will
//! use for a constant buffer to store push constants with [PushConstantBufferConfig](crate::PushConstantBufferConfig).
//!
//! ## Runtime Data
//! For some vertex and compute shaders, a constant buffer provided at runtime is required to be bound.
//!
//! You can check if the compiled shader requires runtime data with
//! [`DxilObject::requires_runtime_data`](crate::DxilObject::requires_runtime_data).
//!
//! If your shader requires runtime data, then register assignments must be chosen in
//! [RuntimeDataBufferConfig](crate::RuntimeDataBufferConfig).
//!
//! See the [`runtime`](crate::runtime) module for how to construct the expected runtime data to be bound in a constant buffer.
mod ctypes;
mod logger;
mod object; mod object;
mod specialization; mod specialization;
mod logger; mod error;
pub mod runtime;
pub use config::*; pub use ctypes::*;
pub use enums::*;
pub use object::*; pub use object::*;
pub use specialization::*; pub use specialization::*;
pub use crate::error::SpirvToDxilError;
pub use spirv_to_dxil_sys::DXIL_SPIRV_MAX_VIEWPORT;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use spirv_to_dxil_sys::dxil_spirv_object;
pub use spirv_to_dxil_sys::DXIL_SPIRV_MAX_VIEWPORT;
use crate::logger::Logger; use crate::logger::Logger;
use spirv_to_dxil_sys::dxil_spirv_object;
fn spirv_to_dxil_inner( fn spirv_to_dxil_inner(
spirv_words: &[u32], spirv_words: &[u32],
@ -23,45 +40,43 @@ fn spirv_to_dxil_inner(
stage: ShaderStage, stage: ShaderStage,
shader_model_max: ShaderModel, shader_model_max: ShaderModel,
validator_version_max: ValidatorVersion, validator_version_max: ValidatorVersion,
runtime_conf: RuntimeConfig, runtime_conf: &RuntimeConfig,
dump_nir: bool, dump_nir: bool,
logger: &spirv_to_dxil_sys::dxil_spirv_logger, logger: &spirv_to_dxil_sys::dxil_spirv_logger,
out: &mut MaybeUninit<dxil_spirv_object>, out: &mut MaybeUninit<dxil_spirv_object>,
) -> bool { ) -> Result<bool, SpirvToDxilError> {
if runtime_conf.push_constant_cbv.register_space > 31 if runtime_conf.push_constant_cbv.register_space > 31
|| runtime_conf.runtime_data_cbv.register_space > 31 { || runtime_conf.runtime_data_cbv.register_space > 31
panic!("register space can not be greater than 31") {
return Err(SpirvToDxilError::RegisterSpaceOverflow(std::cmp::max(runtime_conf.push_constant_cbv.register_space, runtime_conf.runtime_data_cbv.register_space)))
} }
let num_specializations = specializations.map(|o| o.len()).unwrap_or(0) as u32; let num_specializations = specializations.map(|o| o.len()).unwrap_or(0) as u32;
let mut specializations: Option<Vec<spirv_to_dxil_sys::dxil_spirv_specialization>> = let mut specializations: Option<Vec<spirv_to_dxil_sys::dxil_spirv_specialization>> =
specializations.map(|o| o.into_iter().map(|o| (*o).into()).collect()); specializations.map(|o| o.into_iter().map(|o| (*o).into()).collect());
let runtime_conf: spirv_to_dxil_sys::dxil_spirv_runtime_conf =
runtime_conf.into();
let debug = spirv_to_dxil_sys::dxil_spirv_debug_options { dump_nir }; let debug = spirv_to_dxil_sys::dxil_spirv_debug_options { dump_nir };
unsafe { unsafe {
spirv_to_dxil_sys::spirv_to_dxil( Ok(spirv_to_dxil_sys::spirv_to_dxil(
spirv_words.as_ptr(), spirv_words.as_ptr(),
spirv_words.len(), spirv_words.len(),
specializations specializations
.as_mut() .as_mut()
.map_or(std::ptr::null_mut(), |x| x.as_mut_ptr()), .map_or(std::ptr::null_mut(), |x| x.as_mut_ptr()),
num_specializations, num_specializations,
stage.into(), stage,
entry_point.as_ptr().cast(), entry_point.as_ptr().cast(),
shader_model_max.into(), shader_model_max,
validator_version_max.into(), validator_version_max,
&debug, &debug,
&runtime_conf, runtime_conf,
logger, logger,
out.as_mut_ptr(), out.as_mut_ptr(),
) ))
} }
} }
/// Dump NIR to stdout. /// Dump the parsed NIR output of the SPIR-V to stdout.
pub fn dump_nir( pub fn dump_nir(
spirv_words: &[u32], spirv_words: &[u32],
specializations: Option<&[Specialization]>, specializations: Option<&[Specialization]>,
@ -69,13 +84,12 @@ pub fn dump_nir(
stage: ShaderStage, stage: ShaderStage,
shader_model_max: ShaderModel, shader_model_max: ShaderModel,
validator_version_max: ValidatorVersion, validator_version_max: ValidatorVersion,
runtime_conf: RuntimeConfig, runtime_conf: &RuntimeConfig,
) -> bool { ) -> Result<bool, SpirvToDxilError> {
let entry_point = entry_point.as_ref(); let entry_point = entry_point.as_ref();
let mut entry_point = String::from(entry_point).into_bytes(); let mut entry_point = String::from(entry_point).into_bytes();
entry_point.push(0); entry_point.push(0);
let mut out = MaybeUninit::uninit(); let mut out = MaybeUninit::uninit();
spirv_to_dxil_inner( spirv_to_dxil_inner(
spirv_words, spirv_words,
@ -99,8 +113,8 @@ pub fn spirv_to_dxil(
stage: ShaderStage, stage: ShaderStage,
shader_model_max: ShaderModel, shader_model_max: ShaderModel,
validator_version_max: ValidatorVersion, validator_version_max: ValidatorVersion,
runtime_conf: RuntimeConfig, runtime_conf: &RuntimeConfig,
) -> Result<DxilObject, String> { ) -> Result<DxilObject, SpirvToDxilError> {
let entry_point = entry_point.as_ref(); let entry_point = entry_point.as_ref();
let mut entry_point = String::from(entry_point).into_bytes(); let mut entry_point = String::from(entry_point).into_bytes();
entry_point.push(0); entry_point.push(0);
@ -120,18 +134,16 @@ pub fn spirv_to_dxil(
false, false,
&logger, &logger,
&mut out, &mut out,
); )?;
let logger = unsafe { let logger = unsafe { Logger::finalize(logger) };
Logger::finalize(logger)
};
if result { if result {
let out = unsafe { out.assume_init() }; let out = unsafe { out.assume_init() };
Ok(DxilObject::new(out)) Ok(DxilObject::new(out))
} else { } else {
Err(logger) Err(SpirvToDxilError::CompilerError(logger))
} }
} }
@ -145,11 +157,15 @@ mod tests {
let fragment = Vec::from(fragment); let fragment = Vec::from(fragment);
let fragment = bytemuck::cast_slice(&fragment); let fragment = bytemuck::cast_slice(&fragment);
super::dump_nir(&fragment, super::dump_nir(
None, "main", &fragment,
None,
"main",
ShaderStage::Fragment, ShaderStage::Fragment,
ShaderModel::ShaderModel6_0, ValidatorVersion::None, ShaderModel::ShaderModel6_0,
RuntimeConfig::default()); ValidatorVersion::None,
&RuntimeConfig::default(),
).expect("failed to compile");
} }
#[test] #[test]
@ -158,21 +174,25 @@ mod tests {
let fragment = Vec::from(fragment); let fragment = Vec::from(fragment);
let fragment = bytemuck::cast_slice(&fragment); let fragment = bytemuck::cast_slice(&fragment);
super::spirv_to_dxil(&fragment, super::spirv_to_dxil(
None, "main", &fragment,
None,
"main",
ShaderStage::Fragment, ShaderStage::Fragment,
ShaderModel::ShaderModel6_0, ValidatorVersion::None, ShaderModel::ShaderModel6_0,
RuntimeConfig { ValidatorVersion::None,
runtime_data_cbv: ConstantBufferConfig { &RuntimeConfig {
runtime_data_cbv: RuntimeDataBufferConfig {
register_space: 0, register_space: 0,
base_shader_register: 0, base_shader_register: 0,
}, },
push_constant_cbv: ConstantBufferConfig { push_constant_cbv: PushConstantBufferConfig {
register_space: 128, register_space: 31,
base_shader_register: 1, base_shader_register: 1,
}, },
..RuntimeConfig::default() ..RuntimeConfig::default()
}) },
)
.expect("failed to compile"); .expect("failed to compile");
} }
@ -182,11 +202,15 @@ mod tests {
let fragment = Vec::from(fragment); let fragment = Vec::from(fragment);
let fragment = bytemuck::cast_slice(&fragment); let fragment = bytemuck::cast_slice(&fragment);
super::spirv_to_dxil(&fragment, super::spirv_to_dxil(
None, "main", &fragment,
None,
"main",
ShaderStage::Vertex, ShaderStage::Vertex,
ShaderModel::ShaderModel6_0, ValidatorVersion::None, ShaderModel::ShaderModel6_0,
RuntimeConfig::default()) ValidatorVersion::None,
&RuntimeConfig::default(),
)
.expect("failed to compile"); .expect("failed to compile");
} }
} }

View file

@ -2,41 +2,33 @@ use std::ffi::CStr;
use std::os::raw::{c_char, c_void}; use std::os::raw::{c_char, c_void};
extern "C" fn stdout_logger(_: *mut c_void, msg: *const c_char) { extern "C" fn stdout_logger(_: *mut c_void, msg: *const c_char) {
let msg = unsafe { let msg = unsafe { CStr::from_ptr(msg) };
CStr::from_ptr(msg)
};
println!("[spirv-to-dxil] {:?}", msg) println!("[spirv-to-dxil] {:?}", msg)
} }
pub(crate) const DEBUG_LOGGER: spirv_to_dxil_sys::dxil_spirv_logger = spirv_to_dxil_sys::dxil_spirv_logger { pub(crate) const DEBUG_LOGGER: spirv_to_dxil_sys::dxil_spirv_logger =
spirv_to_dxil_sys::dxil_spirv_logger {
priv_: std::ptr::null_mut(), priv_: std::ptr::null_mut(),
log: Some(stdout_logger), log: Some(stdout_logger),
}; };
extern "C" fn string_logger(out: *mut c_void, msg: *const c_char) { extern "C" fn string_logger(out: *mut c_void, msg: *const c_char) {
let logger = out.cast::<Logger>(); let logger = out.cast::<Logger>();
let str = unsafe { let str = unsafe { std::ptr::addr_of_mut!((*logger).msg).as_mut().unwrap() };
std::ptr::addr_of_mut!((*logger).msg)
.as_mut().unwrap()
};
let msg = unsafe { let msg = unsafe { CStr::from_ptr(msg) };
CStr::from_ptr(msg)
};
str.push_str(msg.to_string_lossy().as_ref()) str.push_str(msg.to_string_lossy().as_ref())
} }
pub(crate) struct Logger { pub(crate) struct Logger {
msg: String msg: String,
} }
impl Logger { impl Logger {
pub fn new() -> Logger { pub fn new() -> Logger {
Logger { Logger { msg: String::new() }
msg: String::new()
}
} }
pub fn into_logger(self) -> spirv_to_dxil_sys::dxil_spirv_logger { pub fn into_logger(self) -> spirv_to_dxil_sys::dxil_spirv_logger {
@ -47,9 +39,7 @@ impl Logger {
} }
pub unsafe fn finalize(logger: spirv_to_dxil_sys::dxil_spirv_logger) -> String { pub unsafe fn finalize(logger: spirv_to_dxil_sys::dxil_spirv_logger) -> String {
let logger: Box<Logger> = unsafe { let logger: Box<Logger> = unsafe { Box::from_raw(logger.priv_.cast()) };
Box::from_raw(logger.priv_.cast())
};
logger.msg logger.msg
} }

View file

@ -21,6 +21,7 @@ impl DxilObject {
Self { inner: raw } Self { inner: raw }
} }
/// Returns if the compiled shader requires runtime data to be bound.
pub fn requires_runtime_data(&self) -> bool { pub fn requires_runtime_data(&self) -> bool {
self.inner.metadata.requires_runtime_data self.inner.metadata.requires_runtime_data
} }

View file

@ -0,0 +1,111 @@
//! Higher level helpers for runtime data.
//!
//! Builder structs should not be used directly. Instead, call [`build`](RuntimeDataBuilder::build) to consume
//! the builder and yield an object referenceable as a byte buffer that can be uploaded to a mapped constant buffer.
use spirv_to_dxil_sys::{dxil_spirv_vertex_runtime_data__bindgen_ty_1, dxil_spirv_vertex_runtime_data__bindgen_ty_1__bindgen_ty_1};
/// A vector of three items.
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Vec3<T> {
pub x: T,
pub y: T,
pub z: T
}
/// Trait for runtime data builders.
pub trait RuntimeDataBuilder<T> {
/// Consumes the builder and finalizes the bytes.
fn build(self) -> T;
}
/// Runtime data builder for compute shaders.
#[derive(Debug, Clone)]
pub struct ComputeRuntimeDataBuilder {
pub group_count: Vec3<u32>,
pub base_group: Vec3<u32>
}
/// Runtime data buffer for compute shaders.
pub struct ComputeRuntimeData(spirv_to_dxil_sys::dxil_spirv_compute_runtime_data);
impl RuntimeDataBuilder<ComputeRuntimeData> for ComputeRuntimeDataBuilder {
fn build(self) -> ComputeRuntimeData {
let data = spirv_to_dxil_sys::dxil_spirv_compute_runtime_data {
group_count_x: self.group_count.x,
group_count_y: self.group_count.y,
group_count_z: self.group_count.z,
padding0: 0,
base_group_x: self.base_group.x,
base_group_y: self.base_group.y,
base_group_z: self.base_group.z,
};
ComputeRuntimeData(data)
}
}
impl From<ComputeRuntimeDataBuilder> for ComputeRuntimeData {
fn from(value: ComputeRuntimeDataBuilder) -> Self {
value.build()
}
}
impl AsRef<[u8]> for ComputeRuntimeData {
fn as_ref(&self) -> &[u8] {
bytemuck::bytes_of(&self.0)
}
}
/// Runtime data builder for vertex shaders.
#[derive(Debug, Clone)]
pub struct VertexRuntimeDataBuilder {
pub first_vertex: u32,
pub base_instance: u32,
pub is_indexed_draw: bool,
pub y_flip_mask: u16,
pub z_flip_mask: u16,
pub draw_id: u32,
pub viewport_width: f32,
pub viewport_height: f32,
pub view_index: u32,
}
/// Runtime data buffer for vertex shaders.
pub struct VertexRuntimeData(spirv_to_dxil_sys::dxil_spirv_vertex_runtime_data);
impl RuntimeDataBuilder<VertexRuntimeData> for VertexRuntimeDataBuilder {
fn build(self) -> VertexRuntimeData {
let data = spirv_to_dxil_sys::dxil_spirv_vertex_runtime_data {
first_vertex: self.first_vertex,
base_instance: self.base_instance,
is_indexed_draw: self.is_indexed_draw,
_dxil_spirv_anon1: dxil_spirv_vertex_runtime_data__bindgen_ty_1 {
_dxil_spirv_anon1: dxil_spirv_vertex_runtime_data__bindgen_ty_1__bindgen_ty_1 {
y_flip_mask: self.y_flip_mask,
z_flip_mask: self.z_flip_mask,
}
},
draw_id: self.draw_id,
viewport_width: self.viewport_width,
viewport_height: self.viewport_height,
view_index: self.view_index,
};
VertexRuntimeData(data)
}
}
impl From<VertexRuntimeDataBuilder> for VertexRuntimeData {
fn from(value: VertexRuntimeDataBuilder) -> Self {
value.build()
}
}
impl AsRef<[u8]> for VertexRuntimeData {
fn as_ref(&self) -> &[u8] {
bytemuck::bytes_of(&self.0)
}
}

View file

@ -1,3 +1,4 @@
/// The value of a SPIR-V specialization constant.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum ConstValue { pub enum ConstValue {
Bool(bool), Bool(bool),
@ -31,6 +32,7 @@ impl From<ConstValue> for spirv_to_dxil_sys::dxil_spirv_const_value {
} }
} }
/// SPIR-V specialization constant definition.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Specialization { pub struct Specialization {
pub id: u32, pub id: u32,