Merge pull request #198 from itrycodinganditsbad/fxc
Windows: compile DX12 shaders with FXC
This commit is contained in:
commit
f68e6c438a
|
|
@ -277,6 +277,10 @@ Remove-Item Env:WGPU_BACKEND # restore the default for later
|
||||||
An explicit `gl` override can bring the driver crash back on affected systems. The macOS, Linux
|
An explicit `gl` override can bring the driver crash back on affected systems. The macOS, Linux
|
||||||
and web backend defaults are unchanged.
|
and web backend defaults are unchanged.
|
||||||
|
|
||||||
|
DirectX 12 shaders are compiled with FXC, which is part of Windows, so no `dxcompiler.dll` or
|
||||||
|
`dxil.dll` is needed ("Parent device is lost" at start, #185). `$env:WGPU_DX12_COMPILER = "dxc"`
|
||||||
|
(or `"auto"`) selects wgpu's DXC handling again for troubleshooting.
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
| Build | File | Notes |
|
| Build | File | Notes |
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
//! Windows graphics instance configuration, applied before wgpu can initialize any driver.
|
//! Windows graphics instance configuration, applied before wgpu can initialize any driver.
|
||||||
|
|
||||||
use eframe::{NativeOptions, egui_wgpu::WgpuSetup, wgpu::Backends};
|
use eframe::{
|
||||||
|
NativeOptions,
|
||||||
|
egui_wgpu::WgpuSetup,
|
||||||
|
wgpu::{Backends, Dx12Compiler},
|
||||||
|
};
|
||||||
|
|
||||||
/// Restrict the wgpu instance to DirectX 12 unless `backend_override` (normally
|
/// Default to DirectX 12 with FXC before creating the wgpu instance. Explicit
|
||||||
/// `Backends::from_env()`, i.e. `WGPU_BACKEND`) names other backends.
|
/// `WGPU_BACKEND` and `WGPU_DX12_COMPILER` choices, read by the caller, take precedence.
|
||||||
pub fn configure(options: &mut NativeOptions, backend_override: Option<Backends>) {
|
pub fn configure(options: &mut NativeOptions, backend_override: Option<Backends>, compiler_override: Option<Dx12Compiler>) {
|
||||||
if let WgpuSetup::CreateNew(create) = &mut options.wgpu_options.wgpu_setup {
|
if let WgpuSetup::CreateNew(create) = &mut options.wgpu_options.wgpu_setup {
|
||||||
// eframe's default includes GL. Creating that backend can crash inside AMD's
|
// eframe's default includes GL. Creating that backend can crash inside AMD's
|
||||||
// atio6axx.dll before adapter selection or any Rust error handling runs, so the
|
// atio6axx.dll before adapter selection or any Rust error handling runs, so the
|
||||||
|
|
@ -12,6 +16,16 @@ pub fn configure(options: &mut NativeOptions, backend_override: Option<Backends>
|
||||||
// out of the instance avoids it. This matches the verified WGPU_BACKEND=dx12
|
// out of the instance avoids it. This matches the verified WGPU_BACKEND=dx12
|
||||||
// workaround without mutating process environment variables.
|
// workaround without mutating process environment variables.
|
||||||
create.instance_descriptor.backends = backend_override.unwrap_or(Backends::DX12);
|
create.instance_descriptor.backends = backend_override.unwrap_or(Backends::DX12);
|
||||||
|
// Auto loads whichever dxcompiler.dll the DLL search path finds; SoundCraft ships
|
||||||
|
// none, and without a matching dxil.dll the unsigned-DXIL warning fails wgpu's
|
||||||
|
// indirect-validation pipeline and loses the device before the first frame
|
||||||
|
// (issue #185). FXC uses the compiler that is part of Windows.
|
||||||
|
create.instance_descriptor.backend_options.dx12.shader_compiler = compiler_override.unwrap_or(Dx12Compiler::Fxc);
|
||||||
|
log::info!(
|
||||||
|
"Windows graphics: backends={:?}, DX12 compiler={:?}",
|
||||||
|
create.instance_descriptor.backends,
|
||||||
|
create.instance_descriptor.backend_options.dx12.shader_compiler
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,7 +35,7 @@ mod tests {
|
||||||
|
|
||||||
fn configured_backends(backend_override: Option<Backends>) -> Backends {
|
fn configured_backends(backend_override: Option<Backends>) -> Backends {
|
||||||
let mut options = NativeOptions::default();
|
let mut options = NativeOptions::default();
|
||||||
configure(&mut options, backend_override);
|
configure(&mut options, backend_override, None);
|
||||||
let WgpuSetup::CreateNew(create) = options.wgpu_options.wgpu_setup else {
|
let WgpuSetup::CreateNew(create) = options.wgpu_options.wgpu_setup else {
|
||||||
panic!("default native options must create a wgpu instance");
|
panic!("default native options must create a wgpu instance");
|
||||||
};
|
};
|
||||||
|
|
@ -38,6 +52,38 @@ mod tests {
|
||||||
assert_eq!(configured_backends(None), Backends::DX12);
|
assert_eq!(configured_backends(None), Backends::DX12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn windows_default_uses_fxc_instead_of_searching_for_dxc() {
|
||||||
|
let mut options = NativeOptions::default();
|
||||||
|
if let WgpuSetup::CreateNew(create) = &mut options.wgpu_options.wgpu_setup {
|
||||||
|
// Auto can find an unrelated DXC without its matching DXIL runtime (issue #185).
|
||||||
|
create.instance_descriptor.backend_options.dx12.shader_compiler = Dx12Compiler::Auto;
|
||||||
|
}
|
||||||
|
configure(&mut options, None, None);
|
||||||
|
let WgpuSetup::CreateNew(create) = options.wgpu_options.wgpu_setup else {
|
||||||
|
panic!("default native options must create a wgpu instance");
|
||||||
|
};
|
||||||
|
assert!(matches!(create.instance_descriptor.backend_options.dx12.shader_compiler, Dx12Compiler::Fxc));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn explicit_compiler_override_is_preserved() {
|
||||||
|
for compiler in [Dx12Compiler::Fxc, Dx12Compiler::Auto, Dx12Compiler::DynamicDxc { dxc_path: "custom/dxcompiler.dll".into() }] {
|
||||||
|
let mut options = NativeOptions::default();
|
||||||
|
configure(&mut options, None, Some(compiler.clone()));
|
||||||
|
let WgpuSetup::CreateNew(create) = options.wgpu_options.wgpu_setup else {
|
||||||
|
panic!("default native options must create a wgpu instance");
|
||||||
|
};
|
||||||
|
match (compiler, create.instance_descriptor.backend_options.dx12.shader_compiler) {
|
||||||
|
(Dx12Compiler::Fxc, Dx12Compiler::Fxc) | (Dx12Compiler::Auto, Dx12Compiler::Auto) => {}
|
||||||
|
(Dx12Compiler::DynamicDxc { dxc_path: expected }, Dx12Compiler::DynamicDxc { dxc_path: actual }) => {
|
||||||
|
assert_eq!(actual, expected);
|
||||||
|
}
|
||||||
|
(expected, actual) => panic!("compiler override changed from {expected:?} to {actual:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn explicit_backend_override_is_preserved() {
|
fn explicit_backend_override_is_preserved() {
|
||||||
for backends in [Backends::VULKAN, Backends::GL, Backends::DX12, Backends::VULKAN | Backends::DX12, Backends::empty()] {
|
for backends in [Backends::VULKAN, Backends::GL, Backends::DX12, Backends::VULKAN | Backends::DX12, Backends::empty()] {
|
||||||
|
|
|
||||||
|
|
@ -225,9 +225,9 @@ fn main() -> eframe::Result {
|
||||||
if let Some(icon) = app_icon() {
|
if let Some(icon) = app_icon() {
|
||||||
options.viewport = options.viewport.with_icon(icon);
|
options.viewport = options.viewport.with_icon(icon);
|
||||||
}
|
}
|
||||||
// Before eframe creates the wgpu instance: default Windows to DirectX 12 only (see graphics.rs).
|
// Before eframe creates the wgpu instance: default Windows to DirectX 12 with FXC (see graphics.rs).
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
graphics::configure(&mut options, eframe::wgpu::Backends::from_env());
|
graphics::configure(&mut options, eframe::wgpu::Backends::from_env(), eframe::wgpu::Dx12Compiler::from_env());
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"SoundCraft",
|
"SoundCraft",
|
||||||
options,
|
options,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue