mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-14 19:27:01 -04:00
Merge PR #484
This commit is contained in:
commit
7e350eccb8
6 files changed
+69
-1
No files matched your search
@@ -83,11 +83,13 @@ impl eframe::App for App {
|
||||
|
||||
/// The window's renderer (egui-wgpu): eframe's defaults, with LightCraft's backend choice — DX12
|
||||
/// alone on Windows unless `LIGHTCRAFT_GPU_BACKEND` / `WGPU_BACKEND` say otherwise (issue #136:
|
||||
/// with Vulkan in the set, wgpu loads the Vulkan driver even when it then picks DX12).
|
||||
/// with Vulkan in the set, wgpu loads the Vulkan driver even when it then picks DX12) — and DX12
|
||||
/// shaders compiled with FXC, never a stray `dxcompiler.dll` (issue #471).
|
||||
fn window_wgpu_options() -> eframe::egui_wgpu::WgpuConfiguration {
|
||||
let mut c = eframe::egui_wgpu::WgpuConfiguration::default();
|
||||
if let eframe::egui_wgpu::WgpuSetup::CreateNew(n) = &mut c.wgpu_setup {
|
||||
n.instance_descriptor.backends = lightcraft_engine::gpu::backend::window_backends();
|
||||
n.instance_descriptor.backend_options = lightcraft_engine::gpu::backend::backend_options();
|
||||
}
|
||||
c
|
||||
}
|
||||
@@ -905,6 +907,16 @@ mod tests {
|
||||
assert!(!b.is_empty());
|
||||
}
|
||||
|
||||
/// Issue #471: the window's DX12 shaders compile with FXC — wgpu's default loaded any
|
||||
/// `dxcompiler.dll` on the search path, and one without `dxil.dll` kept the window from opening.
|
||||
#[test]
|
||||
fn window_compiles_dx12_shaders_with_fxc() {
|
||||
let eframe::egui_wgpu::WgpuSetup::CreateNew(n) = window_wgpu_options().wgpu_setup else { panic!("expected CreateNew") };
|
||||
if std::env::var_os("WGPU_DX12_COMPILER").is_none() {
|
||||
assert!(matches!(n.instance_descriptor.backend_options.dx12.shader_compiler, eframe::wgpu::Dx12Compiler::Fxc));
|
||||
}
|
||||
}
|
||||
|
||||
/// Issue #234: Windows opens links with the URL protocol handler (the default browser), not
|
||||
/// File Explorer, and passes the whole map link, `?`, `&` and `#` included, as one argument.
|
||||
#[test]
|
||||
|
||||
@@ -121,6 +121,30 @@ pub fn window_backends() -> Backends {
|
||||
resolve(choice, default, wgpu::Instance::enabled_backend_features()).unwrap_or(default)
|
||||
}
|
||||
|
||||
/// The DX12 shader compiler: FXC (`d3dcompiler_47.dll`, part of Windows) unless
|
||||
/// `WGPU_DX12_COMPILER` (`wgpu`, wgpu's own variable: `fxc`, `dxc`, `auto`…) names another.
|
||||
///
|
||||
/// Issue #471: wgpu's default (`Auto`) loads whichever `dxcompiler.dll` the DLL search path finds
|
||||
/// first — LightCraft ships none, so it is some other program's (an SDK's, a folder on `PATH`). A
|
||||
/// copy without its `dxil.dll` beside it warns that the DXIL is unsigned; wgpu takes the warning for
|
||||
/// a compile error, its own validation pipelines fail, the device is lost and the window never
|
||||
/// opens. FXC is always there and compiles everything LightCraft's shaders need.
|
||||
pub fn dx12_compiler(env: Option<&str>) -> wgpu::Dx12Compiler {
|
||||
let Some(v) = env else { return wgpu::Dx12Compiler::Fxc };
|
||||
v.parse().unwrap_or_else(|e| {
|
||||
log::warn!("gpu: WGPU_DX12_COMPILER={v} ignored: {e}");
|
||||
wgpu::Dx12Compiler::Fxc
|
||||
})
|
||||
}
|
||||
|
||||
/// wgpu's backend options for every instance LightCraft creates — the window's and the compute
|
||||
/// devices': wgpu's environment variables, with the DX12 compiler from [`dx12_compiler`].
|
||||
pub fn backend_options() -> wgpu::BackendOptions {
|
||||
let mut o = wgpu::BackendOptions::from_env_or_default();
|
||||
o.dx12.shader_compiler = dx12_compiler(std::env::var("WGPU_DX12_COMPILER").ok().as_deref());
|
||||
o
|
||||
}
|
||||
|
||||
/// `LIGHTCRAFT_GPU_BACKEND=off`.
|
||||
pub(crate) fn env_off() -> bool {
|
||||
env_choice() == BackendChoice::Off
|
||||
@@ -211,6 +235,20 @@ mod tests {
|
||||
assert!(default_window_backends("linux").contains(Backends::VULKAN | Backends::GL));
|
||||
}
|
||||
|
||||
/// Issue #471: DX12 shaders compile with FXC, never a `dxcompiler.dll` found on the search path,
|
||||
/// unless `WGPU_DX12_COMPILER` asks for it.
|
||||
#[test]
|
||||
fn dx12_compiles_with_fxc_unless_asked() {
|
||||
assert!(matches!(dx12_compiler(None), wgpu::Dx12Compiler::Fxc));
|
||||
assert!(matches!(dx12_compiler(Some("bogus")), wgpu::Dx12Compiler::Fxc));
|
||||
assert!(matches!(dx12_compiler(Some("FXC")), wgpu::Dx12Compiler::Fxc));
|
||||
assert!(matches!(dx12_compiler(Some("dxc")), wgpu::Dx12Compiler::DynamicDxc { .. }));
|
||||
assert!(matches!(dx12_compiler(Some("auto")), wgpu::Dx12Compiler::Auto));
|
||||
if std::env::var_os("WGPU_DX12_COMPILER").is_none() {
|
||||
assert!(matches!(backend_options().dx12.shader_compiler, wgpu::Dx12Compiler::Fxc));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolves_against_the_build() {
|
||||
let compiled = Backends::DX12 | Backends::VULKAN;
|
||||
|
||||
@@ -282,6 +282,8 @@ impl Gpu {
|
||||
let mut desc = wgpu::InstanceDescriptor::new_without_display_handle();
|
||||
// only these drivers are loaded (`crate::backend`: never Vulkan on Windows unless asked)
|
||||
desc.backends = backends;
|
||||
// DX12 shaders compile with FXC (issue #471)
|
||||
desc.backend_options = crate::backend::backend_options();
|
||||
let instance = wgpu::Instance::new(desc);
|
||||
let adapter = pollster::block_on(
|
||||
instance.request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::HighPerformance, ..Default::default() }),
|
||||
|
||||
@@ -76,6 +76,8 @@ fn create_device() -> Result<Dev, String> {
|
||||
fn make_device(backends: wgpu::Backends) -> Result<Dev, String> {
|
||||
let mut desc = wgpu::InstanceDescriptor::new_without_display_handle();
|
||||
desc.backends = backends;
|
||||
// DX12 shaders compile with FXC (issue #471)
|
||||
desc.backend_options = crate::backend::backend_options();
|
||||
let instance = wgpu::Instance::new(desc);
|
||||
let wanted = std::env::var("LIGHTCRAFT_GPU_ADAPTER").ok().map(|s| s.trim().to_lowercase()).filter(|s| !s.is_empty());
|
||||
let adapter = match &wanted {
|
||||
|
||||
@@ -44,6 +44,17 @@ Overrides (read once at launch):
|
||||
the compute device always used Vulkan + DX12 (+ Metal).
|
||||
- `LIGHTCRAFT_GPU=0`: GPU rendering off for the process (the window is unaffected).
|
||||
|
||||
**DX12 shader compiler (issue #471).** Every instance (window and compute) compiles DX12 shaders with
|
||||
FXC (`d3dcompiler_47.dll`, part of Windows; `lightcraft_gpu::backend::backend_options`). wgpu's
|
||||
default, `Auto`, loads whichever `dxcompiler.dll` the DLL search path finds first. LightCraft ships
|
||||
none, so that copy belongs to another program (a Windows SDK, a folder on `PATH`). An older copy without
|
||||
`dxil.dll` beside it (e.g. DXC 1.7) warns that the DXIL is unsigned, wgpu treats the warning as a
|
||||
compile error, its indirect-validation pipelines fail, the device is lost, and the window never opened
|
||||
(`WGPU error: Parent device is lost`). `WGPU_DX12_COMPILER=dxc | auto | fxc` (wgpu's variable) still
|
||||
chooses; with `dxc`, put `dxcompiler.dll` *and* `dxil.dll` (DXC ≥ 1.8.2502) next to `lightcraft.exe`.
|
||||
FXC builds the compute kernels somewhat slower than DXC (≈ 9 s vs 7.5 s for the GPU test suite on an
|
||||
RTX 4080), off the startup path.
|
||||
|
||||
**Off the startup path.** The compute device is created on a background thread once the window is
|
||||
up (`gpu::warm_up` from the first frame's settings), and never while GPU rendering is off: with
|
||||
Settings ▸ Performance ▸ *Use the GPU for rendering* unchecked (applied before the window opens),
|
||||
|
||||
@@ -151,6 +151,9 @@
|
||||
ignored before) chooses the graphics backend; `off` renders on the CPU. The GPU now starts after the window
|
||||
is up, and only when Settings ▸ Performance ▸ Use the GPU for rendering is on; if LightCraft ever dies while
|
||||
starting the GPU, the next launch starts with GPU rendering off and says how to turn it back on.
|
||||
- The Windows app no longer quits at launch with "Parent device is lost" when another program's `dxcompiler.dll` is
|
||||
on the DLL search path without its `dxil.dll` (issue #471): DirectX 12 shaders now always compile with the
|
||||
compiler built into Windows (FXC). `WGPU_DX12_COMPILER=dxc` uses a `dxcompiler.dll` instead.
|
||||
- Exports and renders never write over a photo's original (issue #93): exporting into the photo's own folder with
|
||||
the same name and "Overwrite" (or Export with Previous repeating it), an exact output path from the control
|
||||
channel or MCP, a merge preview path or `lightcraft-cli render IMG.jpg -o IMG.jpg` is refused with a clear
|
||||
|
||||
Reference in new issue
Block a user