mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Add dependency on mach-dxcompiler-rs and support statically linking DXC
This commit is contained in:
parent
00a6032eb7
commit
61bfc96f40
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1778,6 +1778,15 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach-dxcompiler-rs"
|
||||||
|
version = "2023.12.14+0b7073b.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b7857414cb65eb5f03cf0365ac801f089fdbfbb0c47f3f257941eda735aebdf"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "malloc_buf"
|
name = "malloc_buf"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
@ -3692,6 +3701,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"log",
|
"log",
|
||||||
|
"mach-dxcompiler-rs",
|
||||||
"metal",
|
"metal",
|
||||||
"naga",
|
"naga",
|
||||||
"ndk-sys",
|
"ndk-sys",
|
||||||
|
@ -149,6 +149,7 @@ gpu-descriptor = "0.3"
|
|||||||
bit-set = "0.8"
|
bit-set = "0.8"
|
||||||
gpu-allocator = { version = "0.27", default-features = false }
|
gpu-allocator = { version = "0.27", default-features = false }
|
||||||
range-alloc = "0.1"
|
range-alloc = "0.1"
|
||||||
|
mach-dxcompiler-rs = { version = "2023.12.14+0b7073b.1", default-features = false }
|
||||||
windows-core = { version = "0.58", default-features = false }
|
windows-core = { version = "0.58", default-features = false }
|
||||||
|
|
||||||
# Gles dependencies
|
# Gles dependencies
|
||||||
|
@ -91,6 +91,8 @@ dx12 = [
|
|||||||
"windows/Win32_System_Threading",
|
"windows/Win32_System_Threading",
|
||||||
"windows/Win32_UI_WindowsAndMessaging",
|
"windows/Win32_UI_WindowsAndMessaging",
|
||||||
]
|
]
|
||||||
|
## Enables the static DXC compiler using the `mach-dxcompiler-rs` crate.
|
||||||
|
mach-dxcompiler-rs = ["dep:mach-dxcompiler-rs"]
|
||||||
renderdoc = ["dep:libloading", "dep:renderdoc-sys"]
|
renderdoc = ["dep:libloading", "dep:renderdoc-sys"]
|
||||||
fragile-send-sync-non-atomic-wasm = ["wgt/fragile-send-sync-non-atomic-wasm"]
|
fragile-send-sync-non-atomic-wasm = ["wgt/fragile-send-sync-non-atomic-wasm"]
|
||||||
# Panic when running into an out-of-memory error (for debugging purposes).
|
# Panic when running into an out-of-memory error (for debugging purposes).
|
||||||
@ -158,6 +160,7 @@ windows = { workspace = true, optional = true }
|
|||||||
bit-set = { workspace = true, optional = true }
|
bit-set = { workspace = true, optional = true }
|
||||||
range-alloc = { workspace = true, optional = true }
|
range-alloc = { workspace = true, optional = true }
|
||||||
gpu-allocator = { workspace = true, optional = true }
|
gpu-allocator = { workspace = true, optional = true }
|
||||||
|
mach-dxcompiler-rs = { workspace = true, optional = true }
|
||||||
# For core macros. This crate is also reexported as windows::core.
|
# For core macros. This crate is also reexported as windows::core.
|
||||||
windows-core = { workspace = true, optional = true }
|
windows-core = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
@ -80,10 +80,22 @@ impl crate::Instance for super::Instance {
|
|||||||
dxil_path,
|
dxil_path,
|
||||||
dxc_path,
|
dxc_path,
|
||||||
} => {
|
} => {
|
||||||
let container = super::shader_compilation::get_dxc_container(dxc_path, dxil_path)
|
let container =
|
||||||
.map_err(|e| {
|
super::shader_compilation::get_dynamic_dxc_container(dxc_path, dxil_path)
|
||||||
crate::InstanceError::with_source(String::from("Failed to load DXC"), e)
|
.map_err(|e| {
|
||||||
})?;
|
crate::InstanceError::with_source(String::from("Failed to load DXC"), e)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
container.map(Arc::new)
|
||||||
|
}
|
||||||
|
wgt::Dx12Compiler::MachDxc => {
|
||||||
|
let container =
|
||||||
|
super::shader_compilation::get_mach_dxc_container().map_err(|e| {
|
||||||
|
crate::InstanceError::with_source(
|
||||||
|
String::from("Failed to load Mach DXC"),
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
container.map(Arc::new)
|
container.map(Arc::new)
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,12 @@ pub(super) fn compile_fxc(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DxcCreateInstanceFn = unsafe extern "system" fn(
|
||||||
|
rclsid: *const windows_core::GUID,
|
||||||
|
riid: *const windows_core::GUID,
|
||||||
|
ppv: *mut *mut core::ffi::c_void,
|
||||||
|
) -> windows_core::HRESULT;
|
||||||
|
|
||||||
trait DxcObj: Interface {
|
trait DxcObj: Interface {
|
||||||
const CLSID: windows::core::GUID;
|
const CLSID: windows::core::GUID;
|
||||||
}
|
}
|
||||||
@ -97,7 +103,10 @@ struct DxcLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DxcLib {
|
impl DxcLib {
|
||||||
fn new(lib_path: Option<PathBuf>, lib_name: &'static str) -> Result<Self, libloading::Error> {
|
fn new_dynamic(
|
||||||
|
lib_path: Option<PathBuf>,
|
||||||
|
lib_name: &'static str,
|
||||||
|
) -> Result<Self, libloading::Error> {
|
||||||
let lib_path = if let Some(lib_path) = lib_path {
|
let lib_path = if let Some(lib_path) = lib_path {
|
||||||
if lib_path.is_file() {
|
if lib_path.is_file() {
|
||||||
lib_path
|
lib_path
|
||||||
@ -111,15 +120,19 @@ impl DxcLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_instance<T: DxcObj>(&self) -> Result<T, crate::DeviceError> {
|
pub fn create_instance<T: DxcObj>(&self) -> Result<T, crate::DeviceError> {
|
||||||
type Fun = extern "system" fn(
|
unsafe {
|
||||||
rclsid: *const windows_core::GUID,
|
let func: libloading::Symbol<DxcCreateInstanceFn> =
|
||||||
riid: *const windows_core::GUID,
|
self.lib.get(b"DxcCreateInstance\0")?;
|
||||||
ppv: *mut *mut core::ffi::c_void,
|
dxc_create_instance::<T>(*func)
|
||||||
) -> windows_core::HRESULT;
|
}
|
||||||
let func: libloading::Symbol<Fun> = unsafe { self.lib.get(b"DxcCreateInstance\0") }?;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invokes the provided library function to create a DXC object.
|
||||||
|
unsafe fn dxc_create_instance<T: DxcObj>(f: DxcCreateInstanceFn) -> Result<T, crate::DeviceError> {
|
||||||
|
unsafe {
|
||||||
let mut result__ = None;
|
let mut result__ = None;
|
||||||
(func)(&T::CLSID, &T::IID, <*mut _>::cast(&mut result__))
|
f(&T::CLSID, &T::IID, <*mut _>::cast(&mut result__))
|
||||||
.ok()
|
.ok()
|
||||||
.into_device_result("DxcCreateInstance")?;
|
.into_device_result("DxcCreateInstance")?;
|
||||||
result__.ok_or(crate::DeviceError::Unexpected)
|
result__.ok_or(crate::DeviceError::Unexpected)
|
||||||
@ -130,18 +143,20 @@ impl DxcLib {
|
|||||||
pub(super) struct DxcContainer {
|
pub(super) struct DxcContainer {
|
||||||
compiler: Dxc::IDxcCompiler3,
|
compiler: Dxc::IDxcCompiler3,
|
||||||
utils: Dxc::IDxcUtils,
|
utils: Dxc::IDxcUtils,
|
||||||
validator: Dxc::IDxcValidator,
|
validator: Option<Dxc::IDxcValidator>,
|
||||||
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile.
|
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile.
|
||||||
_dxc: DxcLib,
|
// Only needed when using dynamic linking.
|
||||||
|
_dxc: Option<DxcLib>,
|
||||||
// Also Has to be held onto for the lifetime of the device otherwise shaders will fail to validate.
|
// Also Has to be held onto for the lifetime of the device otherwise shaders will fail to validate.
|
||||||
_dxil: DxcLib,
|
// Only needed when using dynamic linking.
|
||||||
|
_dxil: Option<DxcLib>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_dxc_container(
|
pub(super) fn get_dynamic_dxc_container(
|
||||||
dxc_path: Option<PathBuf>,
|
dxc_path: Option<PathBuf>,
|
||||||
dxil_path: Option<PathBuf>,
|
dxil_path: Option<PathBuf>,
|
||||||
) -> Result<Option<DxcContainer>, crate::DeviceError> {
|
) -> Result<Option<DxcContainer>, crate::DeviceError> {
|
||||||
let dxc = match DxcLib::new(dxc_path, "dxcompiler.dll") {
|
let dxc = match DxcLib::new_dynamic(dxc_path, "dxcompiler.dll") {
|
||||||
Ok(dxc) => dxc,
|
Ok(dxc) => dxc,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@ -153,7 +168,7 @@ pub(super) fn get_dxc_container(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let dxil = match DxcLib::new(dxil_path, "dxil.dll") {
|
let dxil = match DxcLib::new_dynamic(dxil_path, "dxil.dll") {
|
||||||
Ok(dxil) => dxil,
|
Ok(dxil) => dxil,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@ -172,12 +187,37 @@ pub(super) fn get_dxc_container(
|
|||||||
Ok(Some(DxcContainer {
|
Ok(Some(DxcContainer {
|
||||||
compiler,
|
compiler,
|
||||||
utils,
|
utils,
|
||||||
validator,
|
validator: Some(validator),
|
||||||
_dxc: dxc,
|
_dxc: Some(dxc),
|
||||||
_dxil: dxil,
|
_dxil: Some(dxil),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a [`DxcContainer`] that delegates to the statically-linked `mach-dxcompiler` library.
|
||||||
|
pub(super) fn get_mach_dxc_container() -> Result<Option<DxcContainer>, crate::DeviceError> {
|
||||||
|
#[cfg(feature = "mach-dxcompiler-rs")]
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let compiler =
|
||||||
|
dxc_create_instance::<Dxc::IDxcCompiler3>(mach_dxcompiler_rs::DxcCreateInstance)?;
|
||||||
|
let utils =
|
||||||
|
dxc_create_instance::<Dxc::IDxcUtils>(mach_dxcompiler_rs::DxcCreateInstance)?;
|
||||||
|
|
||||||
|
Ok(Some(DxcContainer {
|
||||||
|
compiler,
|
||||||
|
utils,
|
||||||
|
validator: None,
|
||||||
|
_dxc: None,
|
||||||
|
_dxil: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "mach-dxcompiler-rs"))]
|
||||||
|
{
|
||||||
|
panic!("Attempted to create a Mach DXC shader compiler, but the mach-dxcompiler-rs feature was not enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Owned PCWSTR
|
/// Owned PCWSTR
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
struct OPCWSTR {
|
struct OPCWSTR {
|
||||||
@ -288,26 +328,24 @@ pub(super) fn compile_dxc(
|
|||||||
|
|
||||||
let blob = get_output::<Dxc::IDxcBlob>(&compile_res, Dxc::DXC_OUT_OBJECT)?;
|
let blob = get_output::<Dxc::IDxcBlob>(&compile_res, Dxc::DXC_OUT_OBJECT)?;
|
||||||
|
|
||||||
let err_blob = {
|
if let Some(validator) = &dxc_container.validator {
|
||||||
let res = unsafe {
|
let err_blob = {
|
||||||
dxc_container
|
let res = unsafe { validator.Validate(&blob, Dxc::DxcValidatorFlags_InPlaceEdit) }
|
||||||
.validator
|
.into_device_result("Validate")?;
|
||||||
.Validate(&blob, Dxc::DxcValidatorFlags_InPlaceEdit)
|
|
||||||
|
unsafe { res.GetErrorBuffer() }.into_device_result("GetErrorBuffer")?
|
||||||
|
};
|
||||||
|
|
||||||
|
let size = unsafe { err_blob.GetBufferSize() };
|
||||||
|
if size != 0 {
|
||||||
|
let err_blob = unsafe { dxc_container.utils.GetBlobAsUtf8(&err_blob) }
|
||||||
|
.into_device_result("GetBlobAsUtf8")?;
|
||||||
|
let err = as_err_str(&err_blob)?;
|
||||||
|
return Err(crate::PipelineError::Linkage(
|
||||||
|
stage_bit,
|
||||||
|
format!("DXC validation error: {err}"),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
.into_device_result("Validate")?;
|
|
||||||
|
|
||||||
unsafe { res.GetErrorBuffer() }.into_device_result("GetErrorBuffer")?
|
|
||||||
};
|
|
||||||
|
|
||||||
let size = unsafe { err_blob.GetBufferSize() };
|
|
||||||
if size != 0 {
|
|
||||||
let err_blob = unsafe { dxc_container.utils.GetBlobAsUtf8(&err_blob) }
|
|
||||||
.into_device_result("GetBlobAsUtf8")?;
|
|
||||||
let err = as_err_str(&err_blob)?;
|
|
||||||
return Err(crate::PipelineError::Linkage(
|
|
||||||
stage_bit,
|
|
||||||
format!("DXC validation error: {err}"),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(crate::dx12::CompiledShader::Dxc(blob))
|
Ok(crate::dx12::CompiledShader::Dxc(blob))
|
||||||
|
@ -7401,6 +7401,9 @@ pub enum Dx12Compiler {
|
|||||||
/// Path to the `dxcompiler.dll` file, or path to the directory containing `dxcompiler.dll` file. Passing `None` will use standard platform specific dll loading rules.
|
/// Path to the `dxcompiler.dll` file, or path to the directory containing `dxcompiler.dll` file. Passing `None` will use standard platform specific dll loading rules.
|
||||||
dxc_path: Option<PathBuf>,
|
dxc_path: Option<PathBuf>,
|
||||||
},
|
},
|
||||||
|
/// The statically-linked variant of Dxc, sourced from the [`mach-dxcompiler-rs`](https://crates.io/crates/mach-dxcompiler-rs) crate.
|
||||||
|
/// The `mach-dxcompiler-rs` feature is required to use this.
|
||||||
|
MachDxc,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Selects which OpenGL ES 3 minor version to request.
|
/// Selects which OpenGL ES 3 minor version to request.
|
||||||
|
@ -73,6 +73,9 @@ glsl = ["naga/glsl-in", "wgc/glsl"]
|
|||||||
## Enable accepting WGSL shaders as input.
|
## Enable accepting WGSL shaders as input.
|
||||||
wgsl = ["wgc?/wgsl"]
|
wgsl = ["wgc?/wgsl"]
|
||||||
|
|
||||||
|
## Enables the static DXC compiler using the `mach-dxcompiler-rs` crate.
|
||||||
|
mach-dxcompiler-rs = ["hal/mach-dxcompiler-rs"]
|
||||||
|
|
||||||
## Enable accepting naga IR shaders as input.
|
## Enable accepting naga IR shaders as input.
|
||||||
naga-ir = ["dep:naga"]
|
naga-ir = ["dep:naga"]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user