mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 08:13:27 +00:00
Updated Dxc integration for DX12 backend (#3356)
Co-authored-by: unknown <alimilhim5@gmail.com> Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com> Closes https://github.com/gfx-rs/wgpu/issues/2722 closes https://github.com/gfx-rs/wgpu/pull/3147
This commit is contained in:
parent
0849e78600
commit
81569dd6c3
44
CHANGELOG.md
44
CHANGELOG.md
@ -103,10 +103,54 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non
|
|||||||
|
|
||||||
`Instance::create_surface()` now returns `Result<Surface, CreateSurfaceError>` instead of `Surface`. This allows an error to be returned instead of panicking if the given window is a HTML canvas and obtaining a WebGPU or WebGL 2 context fails. (No other platforms currently report any errors through this path.) By @kpreid in [#3052](https://github.com/gfx-rs/wgpu/pull/3052/)
|
`Instance::create_surface()` now returns `Result<Surface, CreateSurfaceError>` instead of `Surface`. This allows an error to be returned instead of panicking if the given window is a HTML canvas and obtaining a WebGPU or WebGL 2 context fails. (No other platforms currently report any errors through this path.) By @kpreid in [#3052](https://github.com/gfx-rs/wgpu/pull/3052/)
|
||||||
|
|
||||||
|
#### Instance creation now takes `InstanceDescriptor` instead of `Backends`
|
||||||
|
|
||||||
|
`Instance::new()` and `hub::Global::new()` now take an `InstanceDescriptor` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- let instance = Instance::new(wgpu::Backends::all());
|
||||||
|
+ let instance = Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
+ backends: wgpu::Backends::all(),
|
||||||
|
+ dx12_shader_compiler: wgpu::Dx12Compiler::Fxc,
|
||||||
|
+ });
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- let global = wgc::hub::Global::new(
|
||||||
|
- "player",
|
||||||
|
- IdentityPassThroughFactory,
|
||||||
|
- wgpu::Backends::all(),
|
||||||
|
- );
|
||||||
|
+ let global = wgc::hub::Global::new(
|
||||||
|
+ "player",
|
||||||
|
+ IdentityPassThroughFactory,
|
||||||
|
+ wgpu::InstanceDescriptor {
|
||||||
|
+ backends: wgpu::Backends::all(),
|
||||||
|
+ dx12_shader_compiler: wgpu::Dx12Compiler::Fxc,
|
||||||
|
+ },
|
||||||
|
+ );
|
||||||
|
```
|
||||||
|
|
||||||
|
`Instance` now also also implements `Default`, which uses `wgpu::Backends::all()` and `wgpu::Dx12Compiler::Fxc` for `InstanceDescriptor`
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- let instance = Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
- backends: wgpu::Backends::all(),
|
||||||
|
- dx12_shader_compiler: wgpu::Dx12Compiler::Fxc,
|
||||||
|
- });
|
||||||
|
+ let instance = Instance::default();
|
||||||
|
```
|
||||||
|
|
||||||
|
By @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356)
|
||||||
|
|
||||||
#### Suballocate DX12 buffers and textures
|
#### Suballocate DX12 buffers and textures
|
||||||
|
|
||||||
`wgpu`'s DX12 backend can now suballocate buffers and textures when the `windows_rs` feature is enabled, which can give a significant increase in performance (in testing I've seen a 10000%+ improvement in a simple scene with 200 `write_buffer` calls per frame, and a 40%+ improvement in [Bistro using Bevy](https://github.com/vleue/bevy_bistro_playground)). Previously `wgpu-hal`'s DX12 backend created a new heap on the GPU every time you called write_buffer (by calling `CreateCommittedResource`), whereas now with the `windows_rs` feature enabled it uses [`gpu_allocator`](https://crates.io/crates/gpu-allocator) to manage GPU memory (and calls `CreatePlacedResource` with a suballocated heap). By @Elabajaba in [#3163](https://github.com/gfx-rs/wgpu/pull/3163)
|
`wgpu`'s DX12 backend can now suballocate buffers and textures when the `windows_rs` feature is enabled, which can give a significant increase in performance (in testing I've seen a 10000%+ improvement in a simple scene with 200 `write_buffer` calls per frame, and a 40%+ improvement in [Bistro using Bevy](https://github.com/vleue/bevy_bistro_playground)). Previously `wgpu-hal`'s DX12 backend created a new heap on the GPU every time you called write_buffer (by calling `CreateCommittedResource`), whereas now with the `windows_rs` feature enabled it uses [`gpu_allocator`](https://crates.io/crates/gpu-allocator) to manage GPU memory (and calls `CreatePlacedResource` with a suballocated heap). By @Elabajaba in [#3163](https://github.com/gfx-rs/wgpu/pull/3163)
|
||||||
|
|
||||||
|
#### DXC Shader Compiler Support for DX12
|
||||||
|
|
||||||
|
You can now choose to use the DXC compiler for DX12 instead of FXC. The DXC compiler is faster, less buggy, and allows for new features compared to the old, unmaintained FXC compiler. You can choose which compiler to use at `Instance` creation using the `Dx12Compiler` field in the `InstanceDescriptor` struct. Note that DXC requires both `dxcompiler.dll` and `dxil.dll`, which can be downloaded from https://github.com/microsoft/DirectXShaderCompiler/releases. Both .dlls need to be shipped with your application when targeting DX12 and using the `DXC` compiler. If the .dlls can't be loaded, then it will fall back to the FXC compiler. By @39ali and @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356)
|
||||||
|
|
||||||
#### Texture Format Reinterpretation
|
#### Texture Format Reinterpretation
|
||||||
|
|
||||||
The `view_formats` field is used to specify formats that are compatible with the texture format to allow the creation of views with different formats, currently, only changing srgb-ness is allowed.
|
The `view_formats` field is used to specify formats that are compatible with the texture format to allow the creation of views with different formats, currently, only changing srgb-ness is allowed.
|
||||||
|
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -340,6 +340,12 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "com-rs"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@ -1178,6 +1184,21 @@ dependencies = [
|
|||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hassle-rs"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90601c6189668c7345fc53842cb3f3a3d872203d523be1b3cb44a36a3e62fb85"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"com-rs",
|
||||||
|
"libc",
|
||||||
|
"libloading",
|
||||||
|
"thiserror",
|
||||||
|
"widestring",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@ -2971,6 +2992,7 @@ dependencies = [
|
|||||||
"gpu-alloc",
|
"gpu-alloc",
|
||||||
"gpu-allocator",
|
"gpu-allocator",
|
||||||
"gpu-descriptor",
|
"gpu-descriptor",
|
||||||
|
"hassle-rs",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"khronos-egl",
|
"khronos-egl",
|
||||||
"libc",
|
"libc",
|
||||||
@ -3021,6 +3043,12 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -100,6 +100,7 @@ gpu-allocator = { version = "0.21", default_features = false, features = ["d3d12
|
|||||||
native = { package = "d3d12", version = "0.5.0" }
|
native = { package = "d3d12", version = "0.5.0" }
|
||||||
range-alloc = "0.1"
|
range-alloc = "0.1"
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
|
hassle-rs = "0.9.0"
|
||||||
|
|
||||||
# Gles dependencies
|
# Gles dependencies
|
||||||
egl = { package = "khronos-egl", version = "4.1" }
|
egl = { package = "khronos-egl", version = "4.1" }
|
||||||
|
@ -130,6 +130,7 @@ All testing and example infrastructure shares the same set of environment variab
|
|||||||
- `WGPU_ADAPTER_NAME` with a substring of the name of the adapter you want to use (ex. `1080` will match `NVIDIA GeForce 1080ti`).
|
- `WGPU_ADAPTER_NAME` with a substring of the name of the adapter you want to use (ex. `1080` will match `NVIDIA GeForce 1080ti`).
|
||||||
- `WGPU_BACKEND` with a comma separated list of the backends you want to use (`vulkan`, `metal`, `dx12`, `dx11`, or `gl`).
|
- `WGPU_BACKEND` with a comma separated list of the backends you want to use (`vulkan`, `metal`, `dx12`, `dx11`, or `gl`).
|
||||||
- `WGPU_POWER_PREF` with the power preference to choose when a specific adapter name isn't specified (`high` or `low`)
|
- `WGPU_POWER_PREF` with the power preference to choose when a specific adapter name isn't specified (`high` or `low`)
|
||||||
|
- `WGPU_DX12_COMPILER` with the DX12 shader compiler you wish to use (`dxc` or `fxc`, note that `dxc` requires `dxil.dll` and `dxcompiler.dll` to be in the working directory otherwise it will fall back to `fxc`)
|
||||||
|
|
||||||
When running the CTS, use the variables `DENO_WEBGPU_ADAPTER_NAME`, `DENO_WEBGPU_BACKEND`, `DENO_WEBGPU_POWER_PREFERENCE`.
|
When running the CTS, use the variables `DENO_WEBGPU_ADAPTER_NAME`, `DENO_WEBGPU_BACKEND`, `DENO_WEBGPU_POWER_PREFERENCE`.
|
||||||
|
|
||||||
|
@ -252,7 +252,10 @@ pub async fn op_webgpu_request_adapter(
|
|||||||
state.put(wgpu_core::hub::Global::new(
|
state.put(wgpu_core::hub::Global::new(
|
||||||
"webgpu",
|
"webgpu",
|
||||||
wgpu_core::hub::IdentityManagerFactory,
|
wgpu_core::hub::IdentityManagerFactory,
|
||||||
|
wgpu_types::InstanceDescriptor {
|
||||||
backends,
|
backends,
|
||||||
|
dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc,
|
||||||
|
},
|
||||||
));
|
));
|
||||||
state.borrow::<Instance>()
|
state.borrow::<Instance>()
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,11 @@ fn main() {
|
|||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let global = wgc::hub::Global::new("player", IdentityPassThroughFactory, wgt::Backends::all());
|
let global = wgc::hub::Global::new(
|
||||||
|
"player",
|
||||||
|
IdentityPassThroughFactory,
|
||||||
|
wgt::InstanceDescriptor::default(),
|
||||||
|
);
|
||||||
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
let mut command_buffer_id_manager = wgc::hub::IdentityManager::default();
|
||||||
|
|
||||||
#[cfg(feature = "winit")]
|
#[cfg(feature = "winit")]
|
||||||
|
@ -178,7 +178,14 @@ impl Corpus {
|
|||||||
let dir = path.parent().unwrap();
|
let dir = path.parent().unwrap();
|
||||||
let corpus: Corpus = ron::de::from_reader(File::open(&path).unwrap()).unwrap();
|
let corpus: Corpus = ron::de::from_reader(File::open(&path).unwrap()).unwrap();
|
||||||
|
|
||||||
let global = wgc::hub::Global::new("test", IdentityPassThroughFactory, corpus.backends);
|
let global = wgc::hub::Global::new(
|
||||||
|
"test",
|
||||||
|
IdentityPassThroughFactory,
|
||||||
|
wgt::InstanceDescriptor {
|
||||||
|
backends: corpus.backends,
|
||||||
|
dx12_shader_compiler: wgt::Dx12Compiler::Fxc,
|
||||||
|
},
|
||||||
|
);
|
||||||
for &backend in BACKENDS {
|
for &backend in BACKENDS {
|
||||||
if !corpus.backends.contains(backend.into()) {
|
if !corpus.backends.contains(backend.into()) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1108,10 +1108,10 @@ pub struct Global<G: GlobalIdentityHandlerFactory> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||||
pub fn new(name: &str, factory: G, backends: wgt::Backends) -> Self {
|
pub fn new(name: &str, factory: G, instance_desc: wgt::InstanceDescriptor) -> Self {
|
||||||
profiling::scope!("Global::new");
|
profiling::scope!("Global::new");
|
||||||
Self {
|
Self {
|
||||||
instance: Instance::new(name, backends),
|
instance: Instance::new(name, instance_desc),
|
||||||
surfaces: Registry::without_backend(&factory, "Surface"),
|
surfaces: Registry::without_backend(&factory, "Surface"),
|
||||||
hubs: Hubs::new(&factory),
|
hubs: Hubs::new(&factory),
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,9 @@ pub struct Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn new(name: &str, backends: Backends) -> Self {
|
pub fn new(name: &str, instance_desc: wgt::InstanceDescriptor) -> Self {
|
||||||
fn init<A: HalApi>(_: A, mask: Backends) -> Option<A::Instance> {
|
fn init<A: HalApi>(_: A, instance_desc: &wgt::InstanceDescriptor) -> Option<A::Instance> {
|
||||||
if mask.contains(A::VARIANT.into()) {
|
if instance_desc.backends.contains(A::VARIANT.into()) {
|
||||||
let mut flags = hal::InstanceFlags::empty();
|
let mut flags = hal::InstanceFlags::empty();
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
flags |= hal::InstanceFlags::VALIDATION;
|
flags |= hal::InstanceFlags::VALIDATION;
|
||||||
@ -78,6 +78,7 @@ impl Instance {
|
|||||||
let hal_desc = hal::InstanceDescriptor {
|
let hal_desc = hal::InstanceDescriptor {
|
||||||
name: "wgpu",
|
name: "wgpu",
|
||||||
flags,
|
flags,
|
||||||
|
dx12_shader_compiler: instance_desc.dx12_shader_compiler.clone(),
|
||||||
};
|
};
|
||||||
unsafe { hal::Instance::init(&hal_desc).ok() }
|
unsafe { hal::Instance::init(&hal_desc).ok() }
|
||||||
} else {
|
} else {
|
||||||
@ -88,15 +89,15 @@ impl Instance {
|
|||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
vulkan: init(hal::api::Vulkan, backends),
|
vulkan: init(hal::api::Vulkan, &instance_desc),
|
||||||
#[cfg(feature = "metal")]
|
#[cfg(feature = "metal")]
|
||||||
metal: init(hal::api::Metal, backends),
|
metal: init(hal::api::Metal, &instance_desc),
|
||||||
#[cfg(feature = "dx12")]
|
#[cfg(feature = "dx12")]
|
||||||
dx12: init(hal::api::Dx12, backends),
|
dx12: init(hal::api::Dx12, &instance_desc),
|
||||||
#[cfg(feature = "dx11")]
|
#[cfg(feature = "dx11")]
|
||||||
dx11: init(hal::api::Dx11, backends),
|
dx11: init(hal::api::Dx11, &instance_desc),
|
||||||
#[cfg(feature = "gles")]
|
#[cfg(feature = "gles")]
|
||||||
gl: init(hal::api::Gles, backends),
|
gl: init(hal::api::Gles, &instance_desc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ dx11 = ["naga/hlsl-out", "native", "libloading", "winapi/d3d11", "winapi/d3d11_1
|
|||||||
dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6"]
|
dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6"]
|
||||||
# TODO: This is a separate feature until Mozilla okays windows-rs, see https://github.com/gfx-rs/wgpu/issues/3207 for the tracking issue.
|
# TODO: This is a separate feature until Mozilla okays windows-rs, see https://github.com/gfx-rs/wgpu/issues/3207 for the tracking issue.
|
||||||
windows_rs = ["gpu-allocator"]
|
windows_rs = ["gpu-allocator"]
|
||||||
|
dxc_shader_compiler = ["hassle-rs"]
|
||||||
renderdoc = ["libloading", "renderdoc-sys"]
|
renderdoc = ["libloading", "renderdoc-sys"]
|
||||||
emscripten = ["gles"]
|
emscripten = ["gles"]
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ glow = { git = "https://github.com/grovesNL/glow", rev = "c8a011fcd57a5c68cc917e
|
|||||||
bit-set = { version = "0.5", optional = true }
|
bit-set = { version = "0.5", optional = true }
|
||||||
range-alloc = { version = "0.1", optional = true }
|
range-alloc = { version = "0.1", optional = true }
|
||||||
gpu-allocator = { version = "0.21", default_features = false, features = ["d3d12", "windows", "public-winapi"], optional = true }
|
gpu-allocator = { version = "0.21", default_features = false, features = ["d3d12", "windows", "public-winapi"], optional = true }
|
||||||
|
hassle-rs = { version = "0.9", optional = true }
|
||||||
|
|
||||||
[dependencies.wgt]
|
[dependencies.wgt]
|
||||||
package = "wgpu-types"
|
package = "wgpu-types"
|
||||||
|
@ -96,6 +96,8 @@ impl<A: hal::Api> Example<A> {
|
|||||||
} else {
|
} else {
|
||||||
hal::InstanceFlags::empty()
|
hal::InstanceFlags::empty()
|
||||||
},
|
},
|
||||||
|
// Can't rely on having DXC available, so use FXC instead
|
||||||
|
dx12_shader_compiler: wgt::Dx12Compiler::Fxc,
|
||||||
};
|
};
|
||||||
let instance = unsafe { A::Instance::init(&instance_desc)? };
|
let instance = unsafe { A::Instance::init(&instance_desc)? };
|
||||||
let mut surface = unsafe {
|
let mut surface = unsafe {
|
||||||
|
@ -52,6 +52,7 @@ impl super::Adapter {
|
|||||||
adapter: native::DxgiAdapter,
|
adapter: native::DxgiAdapter,
|
||||||
library: &Arc<native::D3D12Lib>,
|
library: &Arc<native::D3D12Lib>,
|
||||||
instance_flags: crate::InstanceFlags,
|
instance_flags: crate::InstanceFlags,
|
||||||
|
dx12_shader_compiler: &wgt::Dx12Compiler,
|
||||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||||
// Create the device so that we can get the capabilities.
|
// Create the device so that we can get the capabilities.
|
||||||
let device = {
|
let device = {
|
||||||
@ -243,6 +244,7 @@ impl super::Adapter {
|
|||||||
private_caps,
|
private_caps,
|
||||||
presentation_timer,
|
presentation_timer,
|
||||||
workarounds,
|
workarounds,
|
||||||
|
dx12_shader_compiler: dx12_shader_compiler.clone(),
|
||||||
},
|
},
|
||||||
info,
|
info,
|
||||||
features,
|
features,
|
||||||
@ -347,7 +349,13 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
|||||||
.into_device_result("Queue creation")?
|
.into_device_result("Queue creation")?
|
||||||
};
|
};
|
||||||
|
|
||||||
let device = super::Device::new(self.device, queue, self.private_caps, &self.library)?;
|
let device = super::Device::new(
|
||||||
|
self.device,
|
||||||
|
queue,
|
||||||
|
self.private_caps,
|
||||||
|
&self.library,
|
||||||
|
self.dx12_shader_compiler.clone(),
|
||||||
|
)?;
|
||||||
Ok(crate::OpenDevice {
|
Ok(crate::OpenDevice {
|
||||||
device,
|
device,
|
||||||
queue: super::Queue {
|
queue: super::Queue {
|
||||||
|
@ -5,10 +5,10 @@ use crate::{
|
|||||||
|
|
||||||
use super::{conv, descriptor, view};
|
use super::{conv, descriptor, view};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{ffi, mem, num::NonZeroU32, ptr, slice, sync::Arc};
|
use std::{ffi, mem, num::NonZeroU32, ptr, sync::Arc};
|
||||||
use winapi::{
|
use winapi::{
|
||||||
shared::{dxgiformat, dxgitype, minwindef::BOOL, winerror},
|
shared::{dxgiformat, dxgitype, minwindef::BOOL, winerror},
|
||||||
um::{d3d12, d3dcompiler, synchapi, winbase},
|
um::{d3d12, synchapi, winbase},
|
||||||
Interface,
|
Interface,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,9 +21,18 @@ impl super::Device {
|
|||||||
present_queue: native::CommandQueue,
|
present_queue: native::CommandQueue,
|
||||||
private_caps: super::PrivateCapabilities,
|
private_caps: super::PrivateCapabilities,
|
||||||
library: &Arc<native::D3D12Lib>,
|
library: &Arc<native::D3D12Lib>,
|
||||||
|
dx12_shader_compiler: wgt::Dx12Compiler,
|
||||||
) -> Result<Self, crate::DeviceError> {
|
) -> Result<Self, crate::DeviceError> {
|
||||||
let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?;
|
let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?;
|
||||||
|
|
||||||
|
let dxc_container = match dx12_shader_compiler {
|
||||||
|
wgt::Dx12Compiler::Dxc {
|
||||||
|
dxil_path,
|
||||||
|
dxc_path,
|
||||||
|
} => super::shader_compilation::get_dxc_container(dxc_path, dxil_path)?,
|
||||||
|
wgt::Dx12Compiler::Fxc => None,
|
||||||
|
};
|
||||||
|
|
||||||
let mut idle_fence = native::Fence::null();
|
let mut idle_fence = native::Fence::null();
|
||||||
let hr = unsafe {
|
let hr = unsafe {
|
||||||
profiling::scope!("ID3D12Device::CreateFence");
|
profiling::scope!("ID3D12Device::CreateFence");
|
||||||
@ -166,6 +175,7 @@ impl super::Device {
|
|||||||
render_doc: Default::default(),
|
render_doc: Default::default(),
|
||||||
null_rtv_handle,
|
null_rtv_handle,
|
||||||
mem_allocator,
|
mem_allocator,
|
||||||
|
dxc_container,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +202,7 @@ impl super::Device {
|
|||||||
stage: &crate::ProgrammableStage<super::Api>,
|
stage: &crate::ProgrammableStage<super::Api>,
|
||||||
layout: &super::PipelineLayout,
|
layout: &super::PipelineLayout,
|
||||||
naga_stage: naga::ShaderStage,
|
naga_stage: naga::ShaderStage,
|
||||||
) -> Result<native::Blob, crate::PipelineError> {
|
) -> Result<super::CompiledShader, crate::PipelineError> {
|
||||||
use naga::back::hlsl;
|
use naga::back::hlsl;
|
||||||
|
|
||||||
let stage_bit = crate::auxil::map_naga_stage(naga_stage);
|
let stage_bit = crate::auxil::map_naga_stage(naga_stage);
|
||||||
@ -212,73 +222,45 @@ impl super::Device {
|
|||||||
naga_stage.to_hlsl_str(),
|
naga_stage.to_hlsl_str(),
|
||||||
layout.naga_options.shader_model.to_str()
|
layout.naga_options.shader_model.to_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
let ep_index = module
|
let ep_index = module
|
||||||
.entry_points
|
.entry_points
|
||||||
.iter()
|
.iter()
|
||||||
.position(|ep| ep.stage == naga_stage && ep.name == stage.entry_point)
|
.position(|ep| ep.stage == naga_stage && ep.name == stage.entry_point)
|
||||||
.ok_or(crate::PipelineError::EntryPoint(naga_stage))?;
|
.ok_or(crate::PipelineError::EntryPoint(naga_stage))?;
|
||||||
|
|
||||||
let raw_ep = reflection_info.entry_point_names[ep_index]
|
let raw_ep = reflection_info.entry_point_names[ep_index]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|name| ffi::CString::new(name.as_str()).unwrap())
|
|
||||||
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?;
|
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?;
|
||||||
|
|
||||||
let mut shader_data = native::Blob::null();
|
let source_name = stage
|
||||||
let mut error = native::Blob::null();
|
.module
|
||||||
let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS;
|
.raw_name
|
||||||
if self
|
.as_ref()
|
||||||
.private_caps
|
.and_then(|cstr| cstr.to_str().ok())
|
||||||
.instance_flags
|
.unwrap_or_default();
|
||||||
.contains(crate::InstanceFlags::DEBUG)
|
|
||||||
{
|
|
||||||
compile_flags |=
|
|
||||||
d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
let source_name = match stage.module.raw_name {
|
// Compile with DXC if available, otherwise fall back to FXC
|
||||||
Some(ref cstr) => cstr.as_c_str().as_ptr(),
|
let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container {
|
||||||
None => ptr::null(),
|
super::shader_compilation::compile_dxc(
|
||||||
};
|
self,
|
||||||
|
&source,
|
||||||
let hr = unsafe {
|
|
||||||
profiling::scope!("d3dcompiler::D3DCompile");
|
|
||||||
d3dcompiler::D3DCompile(
|
|
||||||
source.as_ptr() as *const _,
|
|
||||||
source.len(),
|
|
||||||
source_name,
|
source_name,
|
||||||
ptr::null(),
|
raw_ep,
|
||||||
ptr::null_mut(),
|
stage_bit,
|
||||||
raw_ep.as_ptr(),
|
full_stage,
|
||||||
full_stage.as_ptr() as *const i8,
|
dxc_container,
|
||||||
compile_flags,
|
|
||||||
0,
|
|
||||||
shader_data.mut_void() as *mut *mut _,
|
|
||||||
error.mut_void() as *mut *mut _,
|
|
||||||
)
|
)
|
||||||
};
|
} else {
|
||||||
|
super::shader_compilation::compile_fxc(
|
||||||
let (result, log_level) = match hr.into_result() {
|
self,
|
||||||
Ok(()) => (Ok(shader_data), log::Level::Info),
|
&source,
|
||||||
Err(e) => {
|
source_name,
|
||||||
let mut full_msg = format!("D3DCompile error ({})", e);
|
&ffi::CString::new(raw_ep.as_str()).unwrap(),
|
||||||
if !error.is_null() {
|
stage_bit,
|
||||||
use std::fmt::Write as _;
|
full_stage,
|
||||||
let message = unsafe {
|
|
||||||
slice::from_raw_parts(
|
|
||||||
error.GetBufferPointer() as *const u8,
|
|
||||||
error.GetBufferSize(),
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let _ = write!(full_msg, ": {}", String::from_utf8_lossy(message));
|
|
||||||
unsafe {
|
|
||||||
error.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(
|
|
||||||
Err(crate::PipelineError::Linkage(stage_bit, full_msg)),
|
|
||||||
log::Level::Warn,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
log::log!(
|
log::log!(
|
||||||
log_level,
|
log_level,
|
||||||
@ -1078,7 +1060,12 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
},
|
},
|
||||||
bind_group_infos,
|
bind_group_infos,
|
||||||
naga_options: hlsl::Options {
|
naga_options: hlsl::Options {
|
||||||
shader_model: hlsl::ShaderModel::V5_1,
|
shader_model: match self.dxc_container {
|
||||||
|
// DXC
|
||||||
|
Some(_) => hlsl::ShaderModel::V6_0,
|
||||||
|
// FXC doesn't support SM 6.0
|
||||||
|
None => hlsl::ShaderModel::V5_1,
|
||||||
|
},
|
||||||
binding_map,
|
binding_map,
|
||||||
fake_missing_bindings: false,
|
fake_missing_bindings: false,
|
||||||
special_constants_binding,
|
special_constants_binding,
|
||||||
@ -1294,9 +1281,9 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
let blob_fs = match desc.fragment_stage {
|
let blob_fs = match desc.fragment_stage {
|
||||||
Some(ref stage) => {
|
Some(ref stage) => {
|
||||||
shader_stages |= wgt::ShaderStages::FRAGMENT;
|
shader_stages |= wgt::ShaderStages::FRAGMENT;
|
||||||
self.load_shader(stage, desc.layout, naga::ShaderStage::Fragment)?
|
Some(self.load_shader(stage, desc.layout, naga::ShaderStage::Fragment)?)
|
||||||
}
|
}
|
||||||
None => native::Blob::null(),
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut vertex_strides = [None; crate::MAX_VERTEX_BUFFERS];
|
let mut vertex_strides = [None; crate::MAX_VERTEX_BUFFERS];
|
||||||
@ -1369,11 +1356,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
|
|
||||||
let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC {
|
||||||
pRootSignature: desc.layout.shared.signature.as_mut_ptr(),
|
pRootSignature: desc.layout.shared.signature.as_mut_ptr(),
|
||||||
VS: *native::Shader::from_blob(blob_vs),
|
VS: *blob_vs.create_native_shader(),
|
||||||
PS: if blob_fs.is_null() {
|
PS: match blob_fs {
|
||||||
*native::Shader::null()
|
Some(ref shader) => *shader.create_native_shader(),
|
||||||
} else {
|
None => *native::Shader::null(),
|
||||||
*native::Shader::from_blob(blob_fs)
|
|
||||||
},
|
},
|
||||||
GS: *native::Shader::null(),
|
GS: *native::Shader::null(),
|
||||||
DS: *native::Shader::null(),
|
DS: *native::Shader::null(),
|
||||||
@ -1445,9 +1431,9 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsafe { blob_vs.destroy() };
|
unsafe { blob_vs.destroy() };
|
||||||
if !blob_fs.is_null() {
|
if let Some(blob_fs) = blob_fs {
|
||||||
unsafe { blob_fs.destroy() };
|
unsafe { blob_fs.destroy() };
|
||||||
}
|
};
|
||||||
|
|
||||||
hr.into_result()
|
hr.into_result()
|
||||||
.map_err(|err| crate::PipelineError::Linkage(shader_stages, err.into_owned()))?;
|
.map_err(|err| crate::PipelineError::Linkage(shader_stages, err.into_owned()))?;
|
||||||
@ -1478,7 +1464,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||||||
profiling::scope!("ID3D12Device::CreateComputePipelineState");
|
profiling::scope!("ID3D12Device::CreateComputePipelineState");
|
||||||
self.raw.create_compute_pipeline_state(
|
self.raw.create_compute_pipeline_state(
|
||||||
desc.layout.shared.signature,
|
desc.layout.shared.signature,
|
||||||
native::Shader::from_blob(blob_cs),
|
blob_cs.create_native_shader(),
|
||||||
0,
|
0,
|
||||||
native::CachedPSO::null(),
|
native::CachedPSO::null(),
|
||||||
native::PipelineStateFlags::empty(),
|
native::PipelineStateFlags::empty(),
|
||||||
|
@ -64,6 +64,7 @@ impl crate::Instance<super::Api> for super::Instance {
|
|||||||
_lib_dxgi: lib_dxgi,
|
_lib_dxgi: lib_dxgi,
|
||||||
supports_allow_tearing,
|
supports_allow_tearing,
|
||||||
flags: desc.flags,
|
flags: desc.flags,
|
||||||
|
dx12_shader_compiler: desc.dx12_shader_compiler.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +92,9 @@ impl crate::Instance<super::Api> for super::Instance {
|
|||||||
|
|
||||||
adapters
|
adapters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|raw| super::Adapter::expose(raw, &self.library, self.flags))
|
.filter_map(|raw| {
|
||||||
|
super::Adapter::expose(raw, &self.library, self.flags, &self.dx12_shader_compiler)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ mod conv;
|
|||||||
mod descriptor;
|
mod descriptor;
|
||||||
mod device;
|
mod device;
|
||||||
mod instance;
|
mod instance;
|
||||||
|
mod shader_compilation;
|
||||||
mod suballocation;
|
mod suballocation;
|
||||||
mod view;
|
mod view;
|
||||||
|
|
||||||
@ -92,6 +93,7 @@ pub struct Instance {
|
|||||||
supports_allow_tearing: bool,
|
supports_allow_tearing: bool,
|
||||||
_lib_dxgi: native::DxgiLib,
|
_lib_dxgi: native::DxgiLib,
|
||||||
flags: crate::InstanceFlags,
|
flags: crate::InstanceFlags,
|
||||||
|
dx12_shader_compiler: wgt::Dx12Compiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
@ -173,6 +175,7 @@ pub struct Adapter {
|
|||||||
//Note: this isn't used right now, but we'll need it later.
|
//Note: this isn't used right now, but we'll need it later.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
workarounds: Workarounds,
|
workarounds: Workarounds,
|
||||||
|
dx12_shader_compiler: wgt::Dx12Compiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Adapter {}
|
unsafe impl Send for Adapter {}
|
||||||
@ -241,6 +244,7 @@ pub struct Device {
|
|||||||
render_doc: crate::auxil::renderdoc::RenderDoc,
|
render_doc: crate::auxil::renderdoc::RenderDoc,
|
||||||
null_rtv_handle: descriptor::Handle,
|
null_rtv_handle: descriptor::Handle,
|
||||||
mem_allocator: Option<Mutex<suballocation::GpuAllocatorWrapper>>,
|
mem_allocator: Option<Mutex<suballocation::GpuAllocatorWrapper>>,
|
||||||
|
dxc_container: Option<shader_compilation::DxcContainer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Device {}
|
unsafe impl Send for Device {}
|
||||||
@ -538,6 +542,30 @@ pub struct ShaderModule {
|
|||||||
raw_name: Option<ffi::CString>,
|
raw_name: Option<ffi::CString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) enum CompiledShader {
|
||||||
|
#[allow(unused)]
|
||||||
|
Dxc(Vec<u8>),
|
||||||
|
Fxc(native::Blob),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompiledShader {
|
||||||
|
fn create_native_shader(&self) -> native::Shader {
|
||||||
|
match *self {
|
||||||
|
CompiledShader::Dxc(ref shader) => native::Shader::from_raw(shader),
|
||||||
|
CompiledShader::Fxc(shader) => native::Shader::from_blob(shader),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn destroy(self) {
|
||||||
|
match self {
|
||||||
|
CompiledShader::Dxc(_) => {}
|
||||||
|
CompiledShader::Fxc(shader) => unsafe {
|
||||||
|
shader.destroy();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
raw: native::PipelineState,
|
raw: native::PipelineState,
|
||||||
layout: PipelineLayoutShared,
|
layout: PipelineLayoutShared,
|
||||||
|
255
wgpu-hal/src/dx12/shader_compilation.rs
Normal file
255
wgpu-hal/src/dx12/shader_compilation.rs
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
pub(super) use dxc::{compile_dxc, get_dxc_container, DxcContainer};
|
||||||
|
use winapi::um::d3dcompiler;
|
||||||
|
|
||||||
|
use crate::auxil::dxgi::result::HResult;
|
||||||
|
|
||||||
|
// This exists so that users who don't want to use dxc can disable the dxc_shader_compiler feature
|
||||||
|
// and not have to compile hassle_rs.
|
||||||
|
// Currently this will use Dxc if it is chosen as the dx12 compiler at `Instance` creation time, and will
|
||||||
|
// fallback to FXC if the Dxc libraries (dxil.dll and dxcompiler.dll) are not found, or if Fxc is chosen at'
|
||||||
|
// `Instance` creation time.
|
||||||
|
|
||||||
|
pub(super) fn compile_fxc(
|
||||||
|
device: &super::Device,
|
||||||
|
source: &String,
|
||||||
|
source_name: &str,
|
||||||
|
raw_ep: &std::ffi::CString,
|
||||||
|
stage_bit: wgt::ShaderStages,
|
||||||
|
full_stage: String,
|
||||||
|
) -> (
|
||||||
|
Result<super::CompiledShader, crate::PipelineError>,
|
||||||
|
log::Level,
|
||||||
|
) {
|
||||||
|
profiling::scope!("compile_fxc");
|
||||||
|
let mut shader_data = native::Blob::null();
|
||||||
|
let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS;
|
||||||
|
if device
|
||||||
|
.private_caps
|
||||||
|
.instance_flags
|
||||||
|
.contains(crate::InstanceFlags::DEBUG)
|
||||||
|
{
|
||||||
|
compile_flags |= d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
|
}
|
||||||
|
let mut error = native::Blob::null();
|
||||||
|
let hr = unsafe {
|
||||||
|
profiling::scope!("d3dcompiler::D3DCompile");
|
||||||
|
d3dcompiler::D3DCompile(
|
||||||
|
source.as_ptr().cast(),
|
||||||
|
source.len(),
|
||||||
|
source_name.as_ptr().cast(),
|
||||||
|
ptr::null(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
raw_ep.as_ptr(),
|
||||||
|
full_stage.as_ptr().cast(),
|
||||||
|
compile_flags,
|
||||||
|
0,
|
||||||
|
shader_data.mut_void().cast(),
|
||||||
|
error.mut_void().cast(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match hr.into_result() {
|
||||||
|
Ok(()) => (
|
||||||
|
Ok(super::CompiledShader::Fxc(shader_data)),
|
||||||
|
log::Level::Info,
|
||||||
|
),
|
||||||
|
Err(e) => {
|
||||||
|
let mut full_msg = format!("FXC D3DCompile error ({})", e);
|
||||||
|
if !error.is_null() {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
let message = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
error.GetBufferPointer() as *const u8,
|
||||||
|
error.GetBufferSize(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let _ = write!(full_msg, ": {}", String::from_utf8_lossy(message));
|
||||||
|
unsafe {
|
||||||
|
error.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(
|
||||||
|
Err(crate::PipelineError::Linkage(stage_bit, full_msg)),
|
||||||
|
log::Level::Warn,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Dxc implementation is behind a feature flag so that users who don't want to use dxc can disable the feature.
|
||||||
|
#[cfg(feature = "dxc_shader_compiler")]
|
||||||
|
mod dxc {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub(crate) struct DxcContainer {
|
||||||
|
pub compiler: hassle_rs::DxcCompiler,
|
||||||
|
pub library: hassle_rs::DxcLibrary,
|
||||||
|
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile
|
||||||
|
_dxc: hassle_rs::Dxc,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_dxc_container(
|
||||||
|
dxc_path: Option<PathBuf>,
|
||||||
|
dxil_path: Option<PathBuf>,
|
||||||
|
) -> Result<Option<DxcContainer>, crate::DeviceError> {
|
||||||
|
// Make sure that dxil.dll exists.
|
||||||
|
match hassle_rs::Dxil::new(dxil_path) {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to load dxil.dll. Defaulting to Fxc instead: {}", e);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let dxc = match hassle_rs::Dxc::new(dxc_path) {
|
||||||
|
Ok(dxc) => dxc,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(
|
||||||
|
"Failed to load dxcompiler.dll. Defaulting to Fxc instead: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let dxc_compiler = dxc.create_compiler()?;
|
||||||
|
let dxc_library = dxc.create_library()?;
|
||||||
|
|
||||||
|
Ok(Some(DxcContainer {
|
||||||
|
_dxc: dxc,
|
||||||
|
compiler: dxc_compiler,
|
||||||
|
library: dxc_library,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn compile_dxc(
|
||||||
|
device: &crate::dx12::Device,
|
||||||
|
source: &str,
|
||||||
|
source_name: &str,
|
||||||
|
raw_ep: &str,
|
||||||
|
stage_bit: wgt::ShaderStages,
|
||||||
|
full_stage: String,
|
||||||
|
dxc_container: &DxcContainer,
|
||||||
|
) -> (
|
||||||
|
Result<crate::dx12::CompiledShader, crate::PipelineError>,
|
||||||
|
log::Level,
|
||||||
|
) {
|
||||||
|
profiling::scope!("compile_dxc");
|
||||||
|
let mut compile_flags = arrayvec::ArrayVec::<&str, 3>::new_const();
|
||||||
|
compile_flags.push("-Ges"); // d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS
|
||||||
|
if device
|
||||||
|
.private_caps
|
||||||
|
.instance_flags
|
||||||
|
.contains(crate::InstanceFlags::DEBUG)
|
||||||
|
{
|
||||||
|
compile_flags.push("-Zi"); // d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION
|
||||||
|
compile_flags.push("-Od"); // d3dcompiler::D3DCOMPILE_DEBUG
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = match dxc_container
|
||||||
|
.library
|
||||||
|
.create_blob_with_encoding_from_str(source)
|
||||||
|
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)))
|
||||||
|
{
|
||||||
|
Ok(blob) => blob,
|
||||||
|
Err(e) => return (Err(e), log::Level::Error),
|
||||||
|
};
|
||||||
|
|
||||||
|
// DXC will automatically validate the shaders during compilation as long as dxil.dll is available, so we don't need to do it ourselves.
|
||||||
|
let compiled = dxc_container.compiler.compile(
|
||||||
|
&blob,
|
||||||
|
source_name,
|
||||||
|
raw_ep,
|
||||||
|
&full_stage,
|
||||||
|
&compile_flags,
|
||||||
|
None,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
|
let (result, log_level) = match compiled {
|
||||||
|
Ok(dxc_result) => match dxc_result.get_result() {
|
||||||
|
Ok(dxc_blob) => (
|
||||||
|
Ok(crate::dx12::CompiledShader::Dxc(dxc_blob.to_vec())),
|
||||||
|
log::Level::Info,
|
||||||
|
),
|
||||||
|
Err(e) => (
|
||||||
|
Err(crate::PipelineError::Linkage(
|
||||||
|
stage_bit,
|
||||||
|
format!("DXC compile error: {}", e),
|
||||||
|
)),
|
||||||
|
log::Level::Error,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Err(e) => (
|
||||||
|
Err(crate::PipelineError::Linkage(
|
||||||
|
stage_bit,
|
||||||
|
format!("DXC compile error: {:?}", e),
|
||||||
|
)),
|
||||||
|
log::Level::Error,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
(result, log_level)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hassle_rs::HassleError> for crate::DeviceError {
|
||||||
|
fn from(value: hassle_rs::HassleError) -> Self {
|
||||||
|
match value {
|
||||||
|
hassle_rs::HassleError::Win32Error(e) => {
|
||||||
|
// TODO: This returns an HRESULT, should we try and use the associated Windows error message?
|
||||||
|
log::error!("Win32 error: {e:?}");
|
||||||
|
crate::DeviceError::Lost
|
||||||
|
}
|
||||||
|
hassle_rs::HassleError::LoadLibraryError { filename, inner } => {
|
||||||
|
log::error!("Failed to load dxc library {filename:?}. Inner error: {inner:?}");
|
||||||
|
crate::DeviceError::Lost
|
||||||
|
}
|
||||||
|
hassle_rs::HassleError::LibLoadingError(e) => {
|
||||||
|
log::error!("Failed to load dxc library. {e:?}");
|
||||||
|
crate::DeviceError::Lost
|
||||||
|
}
|
||||||
|
hassle_rs::HassleError::WindowsOnly(e) => {
|
||||||
|
log::error!("Signing with dxil.dll is only supported on Windows. {e:?}");
|
||||||
|
crate::DeviceError::Lost
|
||||||
|
}
|
||||||
|
// `ValidationError` and `CompileError` should never happen in a context involving `DeviceError`
|
||||||
|
hassle_rs::HassleError::ValidationError(_e) => unimplemented!(),
|
||||||
|
hassle_rs::HassleError::CompileError(_e) => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are stubs for when the `dxc_shader_compiler` feature is disabled.
|
||||||
|
#[cfg(not(feature = "dxc_shader_compiler"))]
|
||||||
|
mod dxc {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub(crate) struct DxcContainer {}
|
||||||
|
|
||||||
|
pub(crate) fn get_dxc_container(
|
||||||
|
_dxc_path: Option<PathBuf>,
|
||||||
|
_dxil_path: Option<PathBuf>,
|
||||||
|
) -> Result<Option<DxcContainer>, crate::DeviceError> {
|
||||||
|
// Falls back to Fxc and logs an error.
|
||||||
|
log::error!("DXC shader compiler was requested on Instance creation, but the DXC feature is disabled. Enable the `dxc_shader_compiler` feature on wgpu_hal to use DXC.");
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It shouldn't be possible that this gets called with the `dxc_shader_compiler` feature disabled.
|
||||||
|
pub(crate) fn compile_dxc(
|
||||||
|
_device: &crate::dx12::Device,
|
||||||
|
_source: &str,
|
||||||
|
_source_name: &str,
|
||||||
|
_raw_ep: &str,
|
||||||
|
_stage_bit: wgt::ShaderStages,
|
||||||
|
_full_stage: String,
|
||||||
|
_dxc_container: &DxcContainer,
|
||||||
|
) -> (
|
||||||
|
Result<crate::dx12::CompiledShader, crate::PipelineError>,
|
||||||
|
log::Level,
|
||||||
|
) {
|
||||||
|
unimplemented!("Something went really wrong, please report this. Attempted to compile shader with DXC, but the DXC feature is disabled. Enable the `dxc_shader_compiler` feature on wgpu_hal to use DXC.");
|
||||||
|
}
|
||||||
|
}
|
@ -743,6 +743,7 @@ bitflags::bitflags! {
|
|||||||
pub struct InstanceDescriptor<'a> {
|
pub struct InstanceDescriptor<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub flags: InstanceFlags,
|
pub flags: InstanceFlags,
|
||||||
|
pub dx12_shader_compiler: wgt::Dx12Compiler,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -281,7 +281,7 @@ mod inner {
|
|||||||
env_logger::init();
|
env_logger::init();
|
||||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
let instance = wgpu::Instance::default();
|
||||||
let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect();
|
let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect();
|
||||||
let adapter_count = adapters.len();
|
let adapter_count = adapters.len();
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#[cfg(any(feature = "serde", test))]
|
#[cfg(any(feature = "serde", test))]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::{num::NonZeroU32, ops::Range};
|
use std::{num::NonZeroU32, ops::Range};
|
||||||
|
|
||||||
pub mod assertions;
|
pub mod assertions;
|
||||||
@ -5362,3 +5363,50 @@ impl Default for ShaderBoundChecks {
|
|||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Selects which DX12 shader compiler to use.
|
||||||
|
///
|
||||||
|
/// If the `wgpu-hal/dx12-shader-compiler` feature isn't enabled then this will fall back
|
||||||
|
/// to the Fxc compiler at runtime and log an error.
|
||||||
|
/// This feature is always enabled when using `wgpu`.
|
||||||
|
///
|
||||||
|
/// If the `Dxc` option is selected, but `dxcompiler.dll` and `dxil.dll` files aren't found,
|
||||||
|
/// then this will fall back to the Fxc compiler at runtime and log an error.
|
||||||
|
///
|
||||||
|
/// `wgpu::utils::init::dx12_shader_compiler_from_env` can be used to set the compiler
|
||||||
|
/// from the `WGPU_DX12_SHADER_COMPILER` environment variable, but this should only be used for testing.
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub enum Dx12Compiler {
|
||||||
|
/// The Fxc compiler (default) is old, slow and unmaintained.
|
||||||
|
///
|
||||||
|
/// However, it doesn't require any additional .dlls to be shipped with the application.
|
||||||
|
#[default]
|
||||||
|
Fxc,
|
||||||
|
/// The Dxc compiler is new, fast and maintained.
|
||||||
|
///
|
||||||
|
/// However, it requires both `dxcompiler.dll` and `dxil.dll` to be shipped with the application.
|
||||||
|
/// These files can be downloaded from https://github.com/microsoft/DirectXShaderCompiler/releases
|
||||||
|
Dxc {
|
||||||
|
/// Path to the `dxcompiler.dll` file. Passing `None` will use standard platform specific dll loading rules.
|
||||||
|
dxil_path: Option<PathBuf>,
|
||||||
|
/// Path to the `dxil.dll` file. Passing `None` will use standard platform specific dll loading rules.
|
||||||
|
dxc_path: Option<PathBuf>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Options for creating an instance.
|
||||||
|
pub struct InstanceDescriptor {
|
||||||
|
/// Which `Backends` to enable.
|
||||||
|
pub backends: Backends,
|
||||||
|
/// Which DX12 shader compiler to use.
|
||||||
|
pub dx12_shader_compiler: Dx12Compiler,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InstanceDescriptor {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
backends: Backends::all(),
|
||||||
|
dx12_shader_compiler: Dx12Compiler::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -141,7 +141,7 @@ hal = { workspace = true }
|
|||||||
hal = { workspace = true, features = ["renderdoc"] }
|
hal = { workspace = true, features = ["renderdoc"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
hal = { workspace = true, features = ["renderdoc", "windows_rs"] }
|
hal = { workspace = true, features = ["dxc_shader_compiler", "renderdoc", "windows_rs"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies.hal]
|
[target.'cfg(target_arch = "wasm32")'.dependencies.hal]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
@ -36,9 +36,12 @@ async fn create_red_image_with_dimensions(
|
|||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
) -> (Device, Buffer, BufferDimensions, SubmissionIndex) {
|
) -> (Device, Buffer, BufferDimensions, SubmissionIndex) {
|
||||||
let adapter = wgpu::Instance::new(
|
let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all);
|
||||||
wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
)
|
backends,
|
||||||
|
dx12_shader_compiler: wgpu::Dx12Compiler::default(),
|
||||||
|
});
|
||||||
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions::default())
|
.request_adapter(&wgpu::RequestAdapterOptions::default())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -157,9 +157,13 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
|||||||
|
|
||||||
log::info!("Initializing the surface...");
|
log::info!("Initializing the surface...");
|
||||||
|
|
||||||
let backend = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all);
|
let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all);
|
||||||
|
let dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default();
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(backend);
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends,
|
||||||
|
dx12_shader_compiler,
|
||||||
|
});
|
||||||
let (size, surface) = unsafe {
|
let (size, surface) = unsafe {
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
|
|
||||||
@ -180,7 +184,7 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
|||||||
(size, surface)
|
(size, surface)
|
||||||
};
|
};
|
||||||
let adapter =
|
let adapter =
|
||||||
wgpu::util::initialize_adapter_from_env_or_default(&instance, backend, Some(&surface))
|
wgpu::util::initialize_adapter_from_env_or_default(&instance, backends, Some(&surface))
|
||||||
.await
|
.await
|
||||||
.expect("No suitable GPU adapters found on the system!");
|
.expect("No suitable GPU adapters found on the system!");
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ async fn run() {
|
|||||||
|
|
||||||
async fn execute_gpu(numbers: &[u32]) -> Option<Vec<u32>> {
|
async fn execute_gpu(numbers: &[u32]) -> Option<Vec<u32>> {
|
||||||
// Instantiates instance of WebGPU
|
// Instantiates instance of WebGPU
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
let instance = wgpu::Instance::default();
|
||||||
|
|
||||||
// `request_adapter` instantiates the general connection to the GPU
|
// `request_adapter` instantiates the general connection to the GPU
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
|
@ -7,7 +7,9 @@ use winit::{
|
|||||||
|
|
||||||
async fn run(event_loop: EventLoop<()>, window: Window) {
|
async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||||
let size = window.inner_size();
|
let size = window.inner_size();
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
|
||||||
|
let instance = wgpu::Instance::default();
|
||||||
|
|
||||||
let surface = unsafe { instance.create_surface(&window) }.unwrap();
|
let surface = unsafe { instance.create_surface(&window) }.unwrap();
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
|
@ -62,7 +62,7 @@ impl Viewport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
|
async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
let instance = wgpu::Instance::default();
|
||||||
let viewports: Vec<_> = viewports
|
let viewports: Vec<_> = viewports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(window, color)| ViewportDesc::new(window, color, &instance))
|
.map(|(window, color)| ViewportDesc::new(window, color, &instance))
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
async fn run() {
|
async fn run() {
|
||||||
#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
|
#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
|
||||||
let adapter = {
|
let adapter = {
|
||||||
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
let instance = wgpu::Instance::default();
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
{
|
{
|
||||||
log::info!("Available adapters:");
|
log::info!("Available adapters:");
|
||||||
|
@ -511,11 +511,11 @@ impl crate::Context for Context {
|
|||||||
|
|
||||||
type PopErrorScopeFuture = Ready<Option<crate::Error>>;
|
type PopErrorScopeFuture = Ready<Option<crate::Error>>;
|
||||||
|
|
||||||
fn init(backends: wgt::Backends) -> Self {
|
fn init(instance_desc: wgt::InstanceDescriptor) -> Self {
|
||||||
Self(wgc::hub::Global::new(
|
Self(wgc::hub::Global::new(
|
||||||
"wgpu",
|
"wgpu",
|
||||||
wgc::hub::IdentityManagerFactory,
|
wgc::hub::IdentityManagerFactory,
|
||||||
backends,
|
instance_desc,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,7 +805,7 @@ impl crate::context::Context for Context {
|
|||||||
type PopErrorScopeFuture =
|
type PopErrorScopeFuture =
|
||||||
MakeSendFuture<wasm_bindgen_futures::JsFuture, fn(JsFutureResult) -> Option<crate::Error>>;
|
MakeSendFuture<wasm_bindgen_futures::JsFuture, fn(JsFutureResult) -> Option<crate::Error>>;
|
||||||
|
|
||||||
fn init(_backends: wgt::Backends) -> Self {
|
fn init(_instance_desc: wgt::InstanceDescriptor) -> Self {
|
||||||
let global: Global = js_sys::global().unchecked_into();
|
let global: Global = js_sys::global().unchecked_into();
|
||||||
let gpu = if !global.window().is_undefined() {
|
let gpu = if !global.window().is_undefined() {
|
||||||
global.unchecked_into::<web_sys::Window>().navigator().gpu()
|
global.unchecked_into::<web_sys::Window>().navigator().gpu()
|
||||||
|
@ -95,7 +95,7 @@ pub trait Context: Debug + Send + Sized + Sync {
|
|||||||
+ 'static;
|
+ 'static;
|
||||||
type PopErrorScopeFuture: Future<Output = Option<Error>> + Send + 'static;
|
type PopErrorScopeFuture: Future<Output = Option<Error>> + Send + 'static;
|
||||||
|
|
||||||
fn init(backends: wgt::Backends) -> Self;
|
fn init(instance_desc: wgt::InstanceDescriptor) -> Self;
|
||||||
fn instance_create_surface(
|
fn instance_create_surface(
|
||||||
&self,
|
&self,
|
||||||
display_handle: raw_window_handle::RawDisplayHandle,
|
display_handle: raw_window_handle::RawDisplayHandle,
|
||||||
|
@ -33,18 +33,18 @@ pub use wgt::{
|
|||||||
BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress,
|
BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress,
|
||||||
BufferBindingType, BufferSize, BufferUsages, Color, ColorTargetState, ColorWrites,
|
BufferBindingType, BufferSize, BufferUsages, Color, ColorTargetState, ColorWrites,
|
||||||
CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState,
|
CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState,
|
||||||
DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, DynamicOffset, Extent3d,
|
DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler,
|
||||||
Face, Features, FilterMode, FrontFace, ImageDataLayout, ImageSubresourceRange, IndexFormat,
|
DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, ImageDataLayout,
|
||||||
Limits, MultisampleState, Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference,
|
ImageSubresourceRange, IndexFormat, InstanceDescriptor, Limits, MultisampleState, Origin3d,
|
||||||
PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange,
|
PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PresentationTimestamp,
|
||||||
QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, ShaderLocation,
|
PrimitiveState, PrimitiveTopology, PushConstantRange, QueryType, RenderBundleDepthStencil,
|
||||||
ShaderModel, ShaderStages, StencilFaceState, StencilOperation, StencilState,
|
SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, ShaderStages,
|
||||||
StorageTextureAccess, SurfaceCapabilities, SurfaceConfiguration, SurfaceStatus, TextureAspect,
|
StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, SurfaceCapabilities,
|
||||||
TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures,
|
SurfaceConfiguration, SurfaceStatus, TextureAspect, TextureDimension, TextureFormat,
|
||||||
TextureSampleType, TextureUsages, TextureViewDimension, VertexAttribute, VertexFormat,
|
TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType, TextureUsages,
|
||||||
VertexStepMode, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT,
|
TextureViewDimension, VertexAttribute, VertexFormat, VertexStepMode, COPY_BUFFER_ALIGNMENT,
|
||||||
PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE,
|
COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT,
|
||||||
VERTEX_STRIDE_ALIGNMENT,
|
QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Filter for error scopes.
|
/// Filter for error scopes.
|
||||||
@ -1286,16 +1286,25 @@ impl Display for SurfaceError {
|
|||||||
|
|
||||||
impl error::Error for SurfaceError {}
|
impl error::Error for SurfaceError {}
|
||||||
|
|
||||||
|
impl Default for Instance {
|
||||||
|
/// Creates a new instance of wgpu with default options.
|
||||||
|
///
|
||||||
|
/// Backends are set to `Backends::all()`, and FXC is chosen as the `dx12_shader_compiler`.
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(InstanceDescriptor::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/// Create an new instance of wgpu.
|
/// Create an new instance of wgpu.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `backends` - Controls from which [backends][Backends] wgpu will choose
|
/// - `instance_desc` - Has fields for which [backends][Backends] wgpu will choose
|
||||||
/// during instantiation.
|
/// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
|
||||||
pub fn new(backends: Backends) -> Self {
|
pub fn new(instance_desc: InstanceDescriptor) -> Self {
|
||||||
Self {
|
Self {
|
||||||
context: Arc::from(crate::backend::Context::init(backends)),
|
context: Arc::from(crate::backend::Context::init(instance_desc)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,3 +86,23 @@ pub async fn initialize_adapter_from_env_or_default(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Choose which DX12 shader compiler to use from the environment variable `WGPU_DX12_COMPILER`.
|
||||||
|
///
|
||||||
|
/// Possible values are `dxc` and `fxc`. Case insensitive.
|
||||||
|
pub fn dx12_shader_compiler_from_env() -> Option<wgt::Dx12Compiler> {
|
||||||
|
Some(
|
||||||
|
match std::env::var("WGPU_DX12_COMPILER")
|
||||||
|
.as_deref()
|
||||||
|
.map(str::to_lowercase)
|
||||||
|
.as_deref()
|
||||||
|
{
|
||||||
|
Ok("dxc") => wgt::Dx12Compiler::Dxc {
|
||||||
|
dxil_path: None,
|
||||||
|
dxc_path: None,
|
||||||
|
},
|
||||||
|
Ok("fxc") => wgt::Dx12Compiler::Fxc,
|
||||||
|
_ => return None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -331,8 +331,12 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_adapter() -> (Adapter, SurfaceGuard) {
|
fn initialize_adapter() -> (Adapter, SurfaceGuard) {
|
||||||
let backend_bits = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all);
|
let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all);
|
||||||
let instance = Instance::new(backend_bits);
|
let dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default();
|
||||||
|
let instance = Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends,
|
||||||
|
dx12_shader_compiler,
|
||||||
|
});
|
||||||
let surface_guard;
|
let surface_guard;
|
||||||
let compatible_surface;
|
let compatible_surface;
|
||||||
|
|
||||||
@ -358,7 +362,7 @@ fn initialize_adapter() -> (Adapter, SurfaceGuard) {
|
|||||||
let compatible_surface: Option<&Surface> = compatible_surface.as_ref();
|
let compatible_surface: Option<&Surface> = compatible_surface.as_ref();
|
||||||
let adapter = pollster::block_on(wgpu::util::initialize_adapter_from_env_or_default(
|
let adapter = pollster::block_on(wgpu::util::initialize_adapter_from_env_or_default(
|
||||||
&instance,
|
&instance,
|
||||||
backend_bits,
|
backends,
|
||||||
compatible_surface,
|
compatible_surface,
|
||||||
))
|
))
|
||||||
.expect("could not find suitable adapter on the system");
|
.expect("could not find suitable adapter on the system");
|
||||||
|
@ -3,15 +3,17 @@ use wasm_bindgen_test::*;
|
|||||||
#[test]
|
#[test]
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn initialize() {
|
fn initialize() {
|
||||||
let _ = wgpu::Instance::new(
|
let _ = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
|
backends: wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
|
||||||
);
|
dx12_shader_compiler: wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_adapter_inner(power: wgt::PowerPreference) {
|
fn request_adapter_inner(power: wgt::PowerPreference) {
|
||||||
let instance = wgpu::Instance::new(
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
|
backends: wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all),
|
||||||
);
|
dx12_shader_compiler: wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(),
|
||||||
|
});
|
||||||
|
|
||||||
let _adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
let _adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
power_preference: power,
|
power_preference: power,
|
||||||
|
Loading…
Reference in New Issue
Block a user