From 99aa681a8ca82547940d46a893479b2a64a17372 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Oct 2022 20:13:18 +0300 Subject: [PATCH 01/32] DXC Integration in DX12 Backend --- Cargo.lock | 28 +++++ Cargo.toml | 1 + wgpu-hal/Cargo.toml | 3 +- wgpu-hal/src/dx12/device.rs | 213 +++++++++++++++++++++++++----------- wgpu-hal/src/dx12/mod.rs | 5 + 5 files changed, 187 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb01f676ed..e7d3b170ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,6 +340,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "com-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" + [[package]] name = "concurrent-queue" version = "2.0.0" @@ -1177,6 +1183,21 @@ dependencies = [ "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]] name = "heck" version = "0.3.3" @@ -2970,6 +2991,7 @@ dependencies = [ "gpu-alloc", "gpu-allocator", "gpu-descriptor", + "hassle-rs", "js-sys", "khronos-egl", "libc", @@ -3020,6 +3042,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "widestring" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index bf4231ddec..c4e199bbcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,6 +100,7 @@ gpu-allocator = { version = "0.21", default_features = false, features = ["d3d12 native = { package = "d3d12", version = "0.5.0" } range-alloc = "0.1" winapi = "0.3" +hassle-rs = "0.9.0" # Gles dependencies egl = { package = "khronos-egl", version = "4.1" } diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index b5d6b6e645..775155ba93 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -32,7 +32,7 @@ metal = ["naga/msl-out", "block", "foreign-types"] vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "smallvec"] gles = ["naga/glsl-out", "glow", "egl", "libloading"] dx11 = ["naga/hlsl-out", "native", "libloading", "winapi/d3d11", "winapi/d3d11_1", "winapi/d3d11_2", "winapi/d3d11sdklayers", "winapi/dxgi1_6"] -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", "hassle-rs"] # 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"] renderdoc = ["libloading", "renderdoc-sys"] @@ -75,6 +75,7 @@ glow = { git = "https://github.com/grovesNL/glow", rev = "c8a011fcd57a5c68cc917e bit-set = { version = "0.5", optional = true } range-alloc = { version = "0.1", 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] package = "wgpu-types" diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index b9a0c7e566..215868a798 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -192,7 +192,7 @@ impl super::Device { stage: &crate::ProgrammableStage, layout: &super::PipelineLayout, naga_stage: naga::ShaderStage, - ) -> Result { + ) -> Result { use naga::back::hlsl; let stage_bit = crate::auxil::map_naga_stage(naga_stage); @@ -212,6 +212,7 @@ impl super::Device { naga_stage.to_hlsl_str(), layout.naga_options.shader_model.to_str() ); + let ep_index = module .entry_points .iter() @@ -222,64 +223,137 @@ impl super::Device { .map(|name| ffi::CString::new(name.as_str()).unwrap()) .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?; - let mut shader_data = native::Blob::null(); - let mut error = native::Blob::null(); - let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; - if self - .private_caps - .instance_flags - .contains(crate::InstanceFlags::DEBUG) - { - compile_flags |= - d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; - } - + let empty_str = ""; let source_name = match stage.module.raw_name { - Some(ref cstr) => cstr.as_c_str().as_ptr(), - None => ptr::null(), + Some(ref cstr) => cstr.to_str().unwrap_or(empty_str), + None => empty_str, }; - let hr = unsafe { - profiling::scope!("d3dcompiler::D3DCompile"); - d3dcompiler::D3DCompile( - source.as_ptr() as *const _, - source.len(), - source_name, - ptr::null(), - ptr::null_mut(), - raw_ep.as_ptr(), - full_stage.as_ptr() as *const i8, - compile_flags, - 0, - shader_data.mut_void() as *mut *mut _, - error.mut_void() as *mut *mut _, - ) - }; + let load_shader_fxc = || { + let mut shader_data = native::Blob::null(); + let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; + + if self + .private_caps + .instance_flags + .contains(crate::InstanceFlags::DEBUG) + { + compile_flags |= + d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; + } + + let full_stage = format!( + "{}_{}\0", + naga_stage.to_hlsl_str(), + hlsl::ShaderModel::V5_1.to_str() + ); + let mut error = native::Blob::null(); + + let hr = unsafe { + profiling::scope!("d3dcompiler::D3DCompile"); + d3dcompiler::D3DCompile( + source.as_ptr() as *const _, + source.len(), + source_name.as_ptr() as *const i8, + ptr::null(), + ptr::null_mut(), + raw_ep.as_ptr(), + full_stage.as_ptr() as *const i8, + compile_flags, + 0, + shader_data.mut_void() as *mut *mut _, + error.mut_void() as *mut *mut _, + ) + }; - let (result, log_level) = match hr.into_result() { - Ok(()) => (Ok(shader_data), log::Level::Info), - Err(e) => { - let mut full_msg = format!("D3DCompile error ({})", e); - if !error.is_null() { - use std::fmt::Write as _; - 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(); + match hr.into_result() { + Ok(()) => (Ok(super::ShaderDXIL::FXC(shader_data)), log::Level::Info), + Err(e) => { + let mut full_msg = format!("D3DCompile error ({})", e); + if !error.is_null() { + use std::fmt::Write as _; + 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, + ) } - ( - Err(crate::PipelineError::Linkage(stage_bit, full_msg)), - log::Level::Warn, - ) } }; + // hassle_rs doesn't check for `dxil.dll` if you only call `hassle_rs::compile_hlsl` but calling hassle_rs::Dxil::new will . + profiling::scope!("hassle_rs::compile_hlsl"); + let (result, log_level) = match hassle_rs::Dxil::new(None).and(hassle_rs::compile_hlsl( + source_name, + &source, + /*this is safe because `raw_ep` was converted from `String`*/ + raw_ep.to_str().unwrap(), + &full_stage, + &vec![], + &vec![], + )) { + Ok(dxil) => (Ok(super::ShaderDXIL::DXC(dxil)), log::Level::Info), + Err(err) => match err { + hassle_rs::HassleError::Win32Error(err) => { + let err_str = i32::into_result(err.0).unwrap_err(); + ( + Err(crate::PipelineError::Linkage( + stage_bit, + format!( + "hassle_rs::compile_hlsl failed with error:({}) :{}", + err, err_str + ), + )), + log::Level::Warn, + ) + } + hassle_rs::HassleError::WindowsOnly(err) => ( + Err(crate::PipelineError::Linkage( + stage_bit, + format!("hassle_rs::compile_hlsl failed with error: {}", err), + )), + log::Level::Warn, + ), + + hassle_rs::HassleError::LoadLibraryError { filename, inner: _ } => { + log::warn!("{:?} was not found ,falling back to FXC ,in order to use the new hlsl compiler `DXC`,`dxcompiler.dll` and `dxil.dll` should be included in the current execution environment" ,filename ); + load_shader_fxc() + } + hassle_rs::HassleError::LibLoadingError(err) => ( + Err(crate::PipelineError::Linkage( + stage_bit, + format!("hassle_rs::compile_hlsl failed with error: {}", err), + )), + log::Level::Warn, + ), + + hassle_rs::HassleError::CompileError(err) => ( + Err(crate::PipelineError::Linkage( + stage_bit, + format!("hassle_rs::compile_hlsl failed with error: {}", err), + )), + log::Level::Warn, + ), + hassle_rs::HassleError::ValidationError(err) => ( + Err(crate::PipelineError::Linkage( + stage_bit, + format!("hassle_rs::compile_hlsl failed with error: {}", err), + )), + log::Level::Warn, + ), + }, + }; + log::log!( log_level, "Naga generated shader for {:?} at {:?}:\n{}", @@ -1078,7 +1152,7 @@ impl crate::Device for super::Device { }, bind_group_infos, naga_options: hlsl::Options { - shader_model: hlsl::ShaderModel::V5_1, + shader_model: hlsl::ShaderModel::V6_0, binding_map, fake_missing_bindings: false, special_constants_binding, @@ -1296,7 +1370,7 @@ impl crate::Device for super::Device { shader_stages |= wgt::ShaderStages::FRAGMENT; self.load_shader(stage, desc.layout, naga::ShaderStage::Fragment)? } - None => native::Blob::null(), + None => crate::dx12::ShaderDXIL::DXC(vec![]), }; let mut vertex_strides = [None; crate::MAX_VERTEX_BUFFERS]; @@ -1369,11 +1443,19 @@ impl crate::Device for super::Device { let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC { pRootSignature: desc.layout.shared.signature.as_mut_ptr(), - VS: *native::Shader::from_blob(blob_vs), - PS: if blob_fs.is_null() { - *native::Shader::null() - } else { - *native::Shader::from_blob(blob_fs) + VS: match blob_vs { + super::ShaderDXIL::DXC(ref blob_vs) => *native::Shader::from_raw(&blob_vs), + super::ShaderDXIL::FXC(blob_vs) => *native::Shader::from_blob(blob_vs), + }, + PS: match blob_fs { + super::ShaderDXIL::DXC(ref blob_fs) => *native::Shader::from_raw(&blob_fs), + super::ShaderDXIL::FXC(blob_fs) => { + if blob_fs.is_null() { + *native::Shader::null() + } else { + *native::Shader::from_blob(blob_fs) + } + } }, GS: *native::Shader::null(), DS: *native::Shader::null(), @@ -1444,9 +1526,11 @@ impl crate::Device for super::Device { } }; - unsafe { blob_vs.destroy() }; - if !blob_fs.is_null() { - unsafe { blob_fs.destroy() }; + if let super::ShaderDXIL::FXC(vs_fxc) = &blob_vs { + unsafe { vs_fxc.destroy() }; + if !vs_fxc.is_null() { + unsafe { vs_fxc.destroy() }; + } } hr.into_result() @@ -1478,14 +1562,19 @@ impl crate::Device for super::Device { profiling::scope!("ID3D12Device::CreateComputePipelineState"); self.raw.create_compute_pipeline_state( desc.layout.shared.signature, - native::Shader::from_blob(blob_cs), + match blob_cs { + crate::dx12::ShaderDXIL::DXC(ref blob_cs) => native::Shader::from_raw(&blob_cs), + crate::dx12::ShaderDXIL::FXC(blob_cs) => native::Shader::from_blob(blob_cs), + }, 0, native::CachedPSO::null(), native::PipelineStateFlags::empty(), ) }; - unsafe { blob_cs.destroy() }; + if let super::ShaderDXIL::FXC(cs_fxc) = blob_cs { + unsafe { cs_fxc.destroy() }; + } let raw = pair.into_result().map_err(|err| { crate::PipelineError::Linkage(wgt::ShaderStages::COMPUTE, err.into_owned()) diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index b3be9e722c..e15aed327e 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -537,6 +537,11 @@ pub struct ShaderModule { raw_name: Option, } +enum ShaderDXIL { + DXC(Vec), + FXC(native::Blob), +} + pub struct RenderPipeline { raw: native::PipelineState, layout: PipelineLayoutShared, From c3d3dba8c134a58d390356604ab18a2871730edd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 30 Oct 2022 00:45:31 +0300 Subject: [PATCH 02/32] Added DXC compile flags --- wgpu-hal/src/dx12/device.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 215868a798..6060b664c4 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -229,6 +229,16 @@ impl super::Device { None => empty_str, }; + let mut compile_flags = vec!["-Ges"]/* d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS */; + if self + .private_caps + .instance_flags + .contains(crate::InstanceFlags::DEBUG) + { + compile_flags.push("-Zi"); /* d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION */ + compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ + } + let load_shader_fxc = || { let mut shader_data = native::Blob::null(); let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; @@ -299,7 +309,7 @@ impl super::Device { /*this is safe because `raw_ep` was converted from `String`*/ raw_ep.to_str().unwrap(), &full_stage, - &vec![], + &compile_flags, &vec![], )) { Ok(dxil) => (Ok(super::ShaderDXIL::DXC(dxil)), log::Level::Info), From 402c611769b251a5939b9149e135268fa128e2b2 Mon Sep 17 00:00:00 2001 From: 39ali Date: Tue, 1 Nov 2022 21:02:17 +0200 Subject: [PATCH 03/32] Replaced `and` with `and_then` so that `hassle_rs::compile_hlsl` isn't called if `Dxil` fails && Refactored `source_name` calculation . --- wgpu-hal/src/dx12/device.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 6060b664c4..207e4e31b7 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -223,11 +223,12 @@ impl super::Device { .map(|name| ffi::CString::new(name.as_str()).unwrap()) .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?; - let empty_str = ""; - let source_name = match stage.module.raw_name { - Some(ref cstr) => cstr.to_str().unwrap_or(empty_str), - None => empty_str, - }; + let source_name = stage + .module + .raw_name + .as_ref() + .and_then(|cstr| cstr.to_str().ok()) + .unwrap_or_default(); let mut compile_flags = vec!["-Ges"]/* d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS */; if self @@ -303,15 +304,17 @@ impl super::Device { // hassle_rs doesn't check for `dxil.dll` if you only call `hassle_rs::compile_hlsl` but calling hassle_rs::Dxil::new will . profiling::scope!("hassle_rs::compile_hlsl"); - let (result, log_level) = match hassle_rs::Dxil::new(None).and(hassle_rs::compile_hlsl( - source_name, - &source, - /*this is safe because `raw_ep` was converted from `String`*/ - raw_ep.to_str().unwrap(), - &full_stage, - &compile_flags, - &vec![], - )) { + let (result, log_level) = match hassle_rs::Dxil::new(None).and_then(|_| { + hassle_rs::compile_hlsl( + source_name, + &source, + /*this is safe because `raw_ep` was converted from `String`*/ + raw_ep.to_str().unwrap(), + &full_stage, + &compile_flags, + &vec![], + ) + }) { Ok(dxil) => (Ok(super::ShaderDXIL::DXC(dxil)), log::Level::Info), Err(err) => match err { hassle_rs::HassleError::Win32Error(err) => { From 85cfc3893201d1ca3887f6946f6b356a7aab8cdd Mon Sep 17 00:00:00 2001 From: 39ali Date: Thu, 3 Nov 2022 18:20:57 +0200 Subject: [PATCH 04/32] Fixed clippy warnings --- wgpu-hal/src/dx12/device.rs | 37 ++++++++++++++++++++----------------- wgpu-hal/src/dx12/mod.rs | 4 ++-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 207e4e31b7..3d933eb2e7 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -240,6 +240,9 @@ impl super::Device { compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ } + // This closure gets called if `hassle_rs::compile_hlsl() fails due to a `hassle_rs::HassleError::LoadLibraryError`, + // + // This usually means that `dxcompiler.dll` and/or `dxil.dll` could not be found in the current execution environment. let load_shader_fxc = || { let mut shader_data = native::Blob::null(); let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; @@ -263,22 +266,22 @@ impl super::Device { let hr = unsafe { profiling::scope!("d3dcompiler::D3DCompile"); d3dcompiler::D3DCompile( - source.as_ptr() as *const _, + source.as_ptr().cast(), source.len(), - source_name.as_ptr() as *const i8, + source_name.as_ptr().cast(), ptr::null(), ptr::null_mut(), raw_ep.as_ptr(), - full_stage.as_ptr() as *const i8, + full_stage.as_ptr().cast(), compile_flags, 0, - shader_data.mut_void() as *mut *mut _, - error.mut_void() as *mut *mut _, + shader_data.mut_void().cast(), + error.mut_void().cast(), ) }; match hr.into_result() { - Ok(()) => (Ok(super::ShaderDXIL::FXC(shader_data)), log::Level::Info), + Ok(()) => (Ok(super::ShaderDXIL::Fxc(shader_data)), log::Level::Info), Err(e) => { let mut full_msg = format!("D3DCompile error ({})", e); if !error.is_null() { @@ -312,10 +315,10 @@ impl super::Device { raw_ep.to_str().unwrap(), &full_stage, &compile_flags, - &vec![], + &[], ) }) { - Ok(dxil) => (Ok(super::ShaderDXIL::DXC(dxil)), log::Level::Info), + Ok(dxil) => (Ok(super::ShaderDXIL::Dxc(dxil)), log::Level::Info), Err(err) => match err { hassle_rs::HassleError::Win32Error(err) => { let err_str = i32::into_result(err.0).unwrap_err(); @@ -1383,7 +1386,7 @@ impl crate::Device for super::Device { shader_stages |= wgt::ShaderStages::FRAGMENT; self.load_shader(stage, desc.layout, naga::ShaderStage::Fragment)? } - None => crate::dx12::ShaderDXIL::DXC(vec![]), + None => crate::dx12::ShaderDXIL::Dxc(vec![]), }; let mut vertex_strides = [None; crate::MAX_VERTEX_BUFFERS]; @@ -1457,12 +1460,12 @@ impl crate::Device for super::Device { let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC { pRootSignature: desc.layout.shared.signature.as_mut_ptr(), VS: match blob_vs { - super::ShaderDXIL::DXC(ref blob_vs) => *native::Shader::from_raw(&blob_vs), - super::ShaderDXIL::FXC(blob_vs) => *native::Shader::from_blob(blob_vs), + super::ShaderDXIL::Dxc(ref blob_vs) => *native::Shader::from_raw(blob_vs), + super::ShaderDXIL::Fxc(blob_vs) => *native::Shader::from_blob(blob_vs), }, PS: match blob_fs { - super::ShaderDXIL::DXC(ref blob_fs) => *native::Shader::from_raw(&blob_fs), - super::ShaderDXIL::FXC(blob_fs) => { + super::ShaderDXIL::Dxc(ref blob_fs) => *native::Shader::from_raw(blob_fs), + super::ShaderDXIL::Fxc(blob_fs) => { if blob_fs.is_null() { *native::Shader::null() } else { @@ -1539,7 +1542,7 @@ impl crate::Device for super::Device { } }; - if let super::ShaderDXIL::FXC(vs_fxc) = &blob_vs { + if let super::ShaderDXIL::Fxc(vs_fxc) = &blob_vs { unsafe { vs_fxc.destroy() }; if !vs_fxc.is_null() { unsafe { vs_fxc.destroy() }; @@ -1576,8 +1579,8 @@ impl crate::Device for super::Device { self.raw.create_compute_pipeline_state( desc.layout.shared.signature, match blob_cs { - crate::dx12::ShaderDXIL::DXC(ref blob_cs) => native::Shader::from_raw(&blob_cs), - crate::dx12::ShaderDXIL::FXC(blob_cs) => native::Shader::from_blob(blob_cs), + crate::dx12::ShaderDXIL::Dxc(ref blob_cs) => native::Shader::from_raw(blob_cs), + crate::dx12::ShaderDXIL::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), }, 0, native::CachedPSO::null(), @@ -1585,7 +1588,7 @@ impl crate::Device for super::Device { ) }; - if let super::ShaderDXIL::FXC(cs_fxc) = blob_cs { + if let super::ShaderDXIL::Fxc(cs_fxc) = blob_cs { unsafe { cs_fxc.destroy() }; } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index e15aed327e..4b8864422c 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -538,8 +538,8 @@ pub struct ShaderModule { } enum ShaderDXIL { - DXC(Vec), - FXC(native::Blob), + Dxc(Vec), + Fxc(native::Blob), } pub struct RenderPipeline { From b41a66264e88e6c4296875666e19d6d44bd05894 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 03:56:37 -0500 Subject: [PATCH 05/32] why doesn't this work... --- wgpu-hal/src/dx12/device.rs | 308 +++++++++++++++++++++--------------- wgpu-hal/src/dx12/mod.rs | 20 +++ 2 files changed, 199 insertions(+), 129 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 3d933eb2e7..67cadfbaad 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -24,6 +24,27 @@ impl super::Device { ) -> Result { let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?; + // TODO: dxc path + // TODO: handle this not existing + let dxc = hassle_rs::Dxc::new(None)?; + let dxc_compiler = match dxc.create_compiler() { + Ok(compiler) => Some(Mutex::new(compiler)), + Err(err) => { + panic!("TODO: error handling"); + + log::warn!("Failed to create DXC compiler: {}", err); + None + } + }; + let dxc_library = match dxc.create_library() { + Ok(library) => Some(Mutex::new(library)), + Err(err) => { + panic!("make sure dxc exists"); + log::warn!("Failed to create DXC library: {}", err); + None + } + }; + let mut idle_fence = native::Fence::null(); let hr = unsafe { profiling::scope!("ID3D12Device::CreateFence"); @@ -166,6 +187,8 @@ impl super::Device { render_doc: Default::default(), null_rtv_handle, mem_allocator, + dxc_compiler, + dxc_library, }) } @@ -218,9 +241,9 @@ impl super::Device { .iter() .position(|ep| ep.stage == naga_stage && ep.name == stage.entry_point) .ok_or(crate::PipelineError::EntryPoint(naga_stage))?; + let raw_ep = reflection_info.entry_point_names[ep_index] .as_ref() - .map(|name| ffi::CString::new(name.as_str()).unwrap()) .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("{}", e)))?; let source_name = stage @@ -240,134 +263,94 @@ impl super::Device { compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ } - // This closure gets called if `hassle_rs::compile_hlsl() fails due to a `hassle_rs::HassleError::LoadLibraryError`, - // - // This usually means that `dxcompiler.dll` and/or `dxil.dll` could not be found in the current execution environment. - let load_shader_fxc = || { - let mut shader_data = native::Blob::null(); - let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; - - if self - .private_caps - .instance_flags - .contains(crate::InstanceFlags::DEBUG) - { - compile_flags |= - d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; - } - - let full_stage = format!( - "{}_{}\0", - naga_stage.to_hlsl_str(), - hlsl::ShaderModel::V5_1.to_str() - ); - 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::ShaderDXIL::Fxc(shader_data)), log::Level::Info), - Err(e) => { - let mut full_msg = format!("D3DCompile error ({})", e); - if !error.is_null() { - use std::fmt::Write as _; - 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, - ) - } - } - }; - - // hassle_rs doesn't check for `dxil.dll` if you only call `hassle_rs::compile_hlsl` but calling hassle_rs::Dxil::new will . - profiling::scope!("hassle_rs::compile_hlsl"); - let (result, log_level) = match hassle_rs::Dxil::new(None).and_then(|_| { - hassle_rs::compile_hlsl( + let (result, log_level) = if let (Some(dxc_library), Some(dxc_compiler)) = + (&self.dxc_library, &self.dxc_compiler) + { + profiling::scope!("hassle_rs::compile_hlsl"); + let dxc_library = dxc_library.lock(); + let dxc_compiler = dxc_compiler.lock(); + + // let compiled = hassle_rs::utils::compile_hlsl( + // source_name, + // &source, + // raw_ep, + // &full_stage, + // &compile_flags, + // &[], + // ); + + // let (result, log_level) = match compiled { + // Ok(dxc_result) => { + // let validated = hassle_rs::validate_dxil(&dxc_result).map_err(|e| { + // crate::PipelineError::Linkage(stage_bit, format!("DXC validate error: {}", e)) + // })?; + // (Ok(super::ShaderDXIL::Dxc(validated)), log::Level::Info) + // } + // Err(e) => ( + // Err(crate::PipelineError::Linkage( + // stage_bit, + // format!("DXC compile error: {:?}", e), + // )), + // log::Level::Warn, + // ), + // }; + + // This is broken and I don't know why... + let blob = dxc_library.create_blob_with_encoding(source.as_bytes()).map_err(|e| { + crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) + })?; + + // let blob = dxc_library + // .create_blob_with_encoding_from_str(&source) + // .map_err(|e| { + // crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) + // })?; + + let compiled = dxc_compiler.compile( + &blob, source_name, - &source, - /*this is safe because `raw_ep` was converted from `String`*/ - raw_ep.to_str().unwrap(), + raw_ep, &full_stage, &compile_flags, + None, // Some(hassle_rs::DxcIncludeHandler {}), // TODO: idk what the include handler does &[], - ) - }) { - Ok(dxil) => (Ok(super::ShaderDXIL::Dxc(dxil)), log::Level::Info), - Err(err) => match err { - hassle_rs::HassleError::Win32Error(err) => { - let err_str = i32::into_result(err.0).unwrap_err(); - ( + ); + + + let (result, log_level) = match compiled { + Ok(dxc_result) => match dxc_result.get_result() { + Ok(dxc_blob) => ( + Ok(super::ShaderDXIL::Dxc(dxc_blob.to_vec())), + log::Level::Info, + ), + Err(e) => ( Err(crate::PipelineError::Linkage( stage_bit, - format!( - "hassle_rs::compile_hlsl failed with error:({}) :{}", - err, err_str - ), + format!("DXC compile error: {}", e), )), log::Level::Warn, - ) - } - hassle_rs::HassleError::WindowsOnly(err) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - format!("hassle_rs::compile_hlsl failed with error: {}", err), - )), - log::Level::Warn, - ), - - hassle_rs::HassleError::LoadLibraryError { filename, inner: _ } => { - log::warn!("{:?} was not found ,falling back to FXC ,in order to use the new hlsl compiler `DXC`,`dxcompiler.dll` and `dxil.dll` should be included in the current execution environment" ,filename ); - load_shader_fxc() - } - hassle_rs::HassleError::LibLoadingError(err) => ( + ), + }, + Err(e) => ( Err(crate::PipelineError::Linkage( stage_bit, - format!("hassle_rs::compile_hlsl failed with error: {}", err), + format!("DXC compile error: {:?}", e), )), log::Level::Warn, ), + }; - hassle_rs::HassleError::CompileError(err) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - format!("hassle_rs::compile_hlsl failed with error: {}", err), - )), - log::Level::Warn, - ), - hassle_rs::HassleError::ValidationError(err) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - format!("hassle_rs::compile_hlsl failed with error: {}", err), - )), - log::Level::Warn, - ), - }, + (result, log_level) + } else { + profiling::scope!("wgpu::backend::directx12::compile_fxc"); + let (fxc_result, log_level) = self.compile_fxc( + naga_stage, + &source, + source_name, + &ffi::CString::new(raw_ep.as_str()).unwrap(), + stage_bit, + ); + (fxc_result, log_level) }; log::log!( @@ -380,6 +363,77 @@ impl super::Device { result } + // This function gets called if `device::dxc_compiler` is None, or if TODO: flag is set that disables DXC. + fn compile_fxc( + &self, + naga_stage: naga::ShaderStage, + source: &String, + source_name: &str, + raw_ep: &ffi::CString, + stage_bit: wgt::ShaderStages, + ) -> (Result, log::Level) { + use naga::back::hlsl; + + let mut shader_data = native::Blob::null(); + let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; + if self + .private_caps + .instance_flags + .contains(crate::InstanceFlags::DEBUG) + { + compile_flags |= + d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; + } + let full_stage = format!( + "{}_{}\0", + naga_stage.to_hlsl_str(), + hlsl::ShaderModel::V5_1.to_str() + ); + 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::ShaderDXIL::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 { + 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, + ) + } + } + } + pub fn raw_device(&self) -> &native::Device { &self.raw } @@ -1168,7 +1222,7 @@ impl crate::Device for super::Device { }, bind_group_infos, naga_options: hlsl::Options { - shader_model: hlsl::ShaderModel::V6_0, + shader_model: hlsl::ShaderModel::V6_0, // TODO: Set this based on whether fxc or dxc is used binding_map, fake_missing_bindings: false, special_constants_binding, @@ -1384,9 +1438,9 @@ impl crate::Device for super::Device { let blob_fs = match desc.fragment_stage { Some(ref stage) => { 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 => crate::dx12::ShaderDXIL::Dxc(vec![]), + None => None, }; let mut vertex_strides = [None; crate::MAX_VERTEX_BUFFERS]; @@ -1464,14 +1518,9 @@ impl crate::Device for super::Device { super::ShaderDXIL::Fxc(blob_vs) => *native::Shader::from_blob(blob_vs), }, PS: match blob_fs { - super::ShaderDXIL::Dxc(ref blob_fs) => *native::Shader::from_raw(blob_fs), - super::ShaderDXIL::Fxc(blob_fs) => { - if blob_fs.is_null() { - *native::Shader::null() - } else { - *native::Shader::from_blob(blob_fs) - } - } + Some(super::ShaderDXIL::Dxc(ref blob_fs)) => *native::Shader::from_raw(blob_fs), + Some(super::ShaderDXIL::Fxc(blob_fs)) => *native::Shader::from_blob(blob_fs), + None => *native::Shader::null(), }, GS: *native::Shader::null(), DS: *native::Shader::null(), @@ -1544,9 +1593,10 @@ impl crate::Device for super::Device { if let super::ShaderDXIL::Fxc(vs_fxc) = &blob_vs { unsafe { vs_fxc.destroy() }; - if !vs_fxc.is_null() { - unsafe { vs_fxc.destroy() }; - } + } + + if let Some(super::ShaderDXIL::Fxc(fs_fxc)) = &blob_fs { + unsafe { fs_fxc.destroy() }; } hr.into_result() diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 4b8864422c..80c7738387 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -241,6 +241,10 @@ pub struct Device { render_doc: crate::auxil::renderdoc::RenderDoc, null_rtv_handle: descriptor::Handle, mem_allocator: Option>, + // todo: mutex is just for testing, remove later + dxc_compiler: Option>, + // todo: mutex is just for testing, remove later + dxc_library: Option>, } unsafe impl Send for Device {} @@ -839,3 +843,19 @@ impl crate::Queue for Queue { (1_000_000_000.0 / frequency as f64) as f32 } } + +impl From for crate::DeviceError { + fn from(value: hassle_rs::HassleError) -> Self { + match value { + hassle_rs::HassleError::Win32Error(_) => todo!(), + hassle_rs::HassleError::CompileError(_) => todo!(), + hassle_rs::HassleError::ValidationError(_) => todo!(), + hassle_rs::HassleError::LoadLibraryError { filename, inner } => { + println!("Failed to load library {filename:?}, {inner:?}"); + crate::DeviceError::Lost + } + hassle_rs::HassleError::LibLoadingError(_) => todo!(), + hassle_rs::HassleError::WindowsOnly(_) => todo!(), + } + } +} From 49fb214aea379340b74d83f9118311caf75243c8 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 18:20:51 -0500 Subject: [PATCH 06/32] error handling --- wgpu-hal/src/dx12/mod.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 80c7738387..95b04c419c 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -847,15 +847,26 @@ impl crate::Queue for Queue { impl From for crate::DeviceError { fn from(value: hassle_rs::HassleError) -> Self { match value { - hassle_rs::HassleError::Win32Error(_) => todo!(), - hassle_rs::HassleError::CompileError(_) => todo!(), - hassle_rs::HassleError::ValidationError(_) => todo!(), + 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 } => { - println!("Failed to load library {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 } - hassle_rs::HassleError::LibLoadingError(_) => todo!(), - hassle_rs::HassleError::WindowsOnly(_) => todo!(), + // `ValidationError` and `CompileError` should never happen in a context involving `DeviceError` + hassle_rs::HassleError::ValidationError(e) => unimplemented!(), + hassle_rs::HassleError::CompileError(e) => unimplemented!(), } } } From f0a426a6a8f6083ebc0864cdff740b2fdf88b9c7 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 18:22:45 -0500 Subject: [PATCH 07/32] store dxc related stuff in `DxcContainer` to make it work --- wgpu-hal/src/dx12/device.rs | 113 ++++++++++++++---------------------- wgpu-hal/src/dx12/mod.rs | 15 +++-- 2 files changed, 53 insertions(+), 75 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 67cadfbaad..bef8a2ae77 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -26,23 +26,22 @@ impl super::Device { // TODO: dxc path // TODO: handle this not existing - let dxc = hassle_rs::Dxc::new(None)?; - let dxc_compiler = match dxc.create_compiler() { - Ok(compiler) => Some(Mutex::new(compiler)), - Err(err) => { - panic!("TODO: error handling"); - - log::warn!("Failed to create DXC compiler: {}", err); - None - } - }; - let dxc_library = match dxc.create_library() { - Ok(library) => Some(Mutex::new(library)), - Err(err) => { - panic!("make sure dxc exists"); - log::warn!("Failed to create DXC library: {}", err); - None - } + let dxc_container = if true { + let dxc = hassle_rs::Dxc::new(Some("./".into()))?; + let dxc_compiler = dxc.create_compiler()?; + let dxc_library = dxc.create_library()?; + + let dxil = hassle_rs::Dxil::new(Some("./".into()))?; + let dxc_validator = dxil.create_validator()?; + Some(super::DxcContainer { + _dxc: dxc, + dxc_compiler, + dxc_library, + // _dxil: dxil, + dxc_validator, + }) + } else { + None }; let mut idle_fence = native::Fence::null(); @@ -187,8 +186,7 @@ impl super::Device { render_doc: Default::default(), null_rtv_handle, mem_allocator, - dxc_compiler, - dxc_library, + dxc_container, }) } @@ -263,66 +261,41 @@ impl super::Device { compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ } - let (result, log_level) = if let (Some(dxc_library), Some(dxc_compiler)) = - (&self.dxc_library, &self.dxc_compiler) - { + let (result, log_level) = if let Some(dxc_container) = &self.dxc_container { profiling::scope!("hassle_rs::compile_hlsl"); - let dxc_library = dxc_library.lock(); - let dxc_compiler = dxc_compiler.lock(); - - // let compiled = hassle_rs::utils::compile_hlsl( - // source_name, - // &source, - // raw_ep, - // &full_stage, - // &compile_flags, - // &[], - // ); - - // let (result, log_level) = match compiled { - // Ok(dxc_result) => { - // let validated = hassle_rs::validate_dxil(&dxc_result).map_err(|e| { - // crate::PipelineError::Linkage(stage_bit, format!("DXC validate error: {}", e)) - // })?; - // (Ok(super::ShaderDXIL::Dxc(validated)), log::Level::Info) - // } - // Err(e) => ( - // Err(crate::PipelineError::Linkage( - // stage_bit, - // format!("DXC compile error: {:?}", e), - // )), - // log::Level::Warn, - // ), - // }; - - // This is broken and I don't know why... - let blob = dxc_library.create_blob_with_encoding(source.as_bytes()).map_err(|e| { - crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) - })?; - - // let blob = dxc_library - // .create_blob_with_encoding_from_str(&source) - // .map_err(|e| { - // crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) - // })?; - - let compiled = dxc_compiler.compile( + let blob = dxc_container + .dxc_library + .create_blob_with_encoding_from_str(&source) + .map_err(|e| { + crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) + })?; + + let compiled = dxc_container.dxc_compiler.compile( &blob, source_name, raw_ep, &full_stage, &compile_flags, - None, // Some(hassle_rs::DxcIncludeHandler {}), // TODO: idk what the include handler does + None, // TODO: idk what the include handler does &[], ); - let (result, log_level) = match compiled { Ok(dxc_result) => match dxc_result.get_result() { - Ok(dxc_blob) => ( - Ok(super::ShaderDXIL::Dxc(dxc_blob.to_vec())), - log::Level::Info, - ), + Ok(dxc_blob) => match dxc_container.dxc_validator.validate(dxc_blob) { + Ok(validated) => ( + Ok(super::ShaderDXIL::Dxc(validated.to_vec())), + log::Level::Info, + ), + Err(e) => ( + Err(crate::PipelineError::Linkage( + stage_bit, + // I don't like this, but the nested matches are already too deep + format!("DXC validation error: {:?}. {}", e.0, e.1), + )), + log::Level::Warn, + ), + }, Err(e) => ( Err(crate::PipelineError::Linkage( stage_bit, @@ -408,9 +381,7 @@ impl super::Device { }; match hr.into_result() { - Ok(()) => { - (Ok(super::ShaderDXIL::Fxc(shader_data)), log::Level::Info) - } + Ok(()) => (Ok(super::ShaderDXIL::Fxc(shader_data)), log::Level::Info), Err(e) => { let mut full_msg = format!("FXC D3DCompile error ({})", e); if !error.is_null() { diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 95b04c419c..a3ecdeee01 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -241,10 +241,7 @@ pub struct Device { render_doc: crate::auxil::renderdoc::RenderDoc, null_rtv_handle: descriptor::Handle, mem_allocator: Option>, - // todo: mutex is just for testing, remove later - dxc_compiler: Option>, - // todo: mutex is just for testing, remove later - dxc_library: Option>, + dxc_container: Option, } unsafe impl Send for Device {} @@ -564,6 +561,16 @@ pub struct ComputePipeline { unsafe impl Send for ComputePipeline {} unsafe impl Sync for ComputePipeline {} +pub(crate) struct DxcContainer { + dxc_compiler: hassle_rs::DxcCompiler, + dxc_library: hassle_rs::DxcLibrary, + dxc_validator: hassle_rs::DxcValidator, + // Has to be held onto for the lifetime of the device otherwise shaders will fail to compile + _dxc: hassle_rs::Dxc, + // Has to be held onto for the lifetime of the device otherwise shaders will fail to compile + // _dxil: hassle_rs::Dxil, +} + impl SwapChain { unsafe fn release_resources(self) -> native::WeakPtr { for resource in self.resources { From de254f426bbff30daa246c9b4b1b8cb67571fd4c Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 20:48:00 -0500 Subject: [PATCH 08/32] clippy --- wgpu-hal/src/dx12/device.rs | 6 +++--- wgpu-hal/src/dx12/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index bef8a2ae77..aafca0aede 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -261,7 +261,7 @@ impl super::Device { compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ } - let (result, log_level) = if let Some(dxc_container) = &self.dxc_container { + let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { profiling::scope!("hassle_rs::compile_hlsl"); let blob = dxc_container .dxc_library @@ -1562,11 +1562,11 @@ impl crate::Device for super::Device { } }; - if let super::ShaderDXIL::Fxc(vs_fxc) = &blob_vs { + if let super::ShaderDXIL::Fxc(ref vs_fxc) = blob_vs { unsafe { vs_fxc.destroy() }; } - if let Some(super::ShaderDXIL::Fxc(fs_fxc)) = &blob_fs { + if let Some(super::ShaderDXIL::Fxc(ref fs_fxc)) = blob_fs { unsafe { fs_fxc.destroy() }; } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index a3ecdeee01..c43dc6b5c7 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -872,8 +872,8 @@ impl From for crate::DeviceError { 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!(), + hassle_rs::HassleError::ValidationError(_e) => unimplemented!(), + hassle_rs::HassleError::CompileError(_e) => unimplemented!(), } } } From f31917c986a5464e2e5adce14fe6afa98df03b88 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 21:28:05 -0500 Subject: [PATCH 09/32] Rename ShaderDXIL to CompiledShader, don't re-validate/re-sign after dxc compilation. --- wgpu-hal/src/dx12/device.rs | 97 ++++++++++++++++++------------------- wgpu-hal/src/dx12/mod.rs | 5 +- 2 files changed, 47 insertions(+), 55 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index aafca0aede..4e8c64a292 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -24,21 +24,19 @@ impl super::Device { ) -> Result { let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?; - // TODO: dxc path + // TODO: path to dxcompiler.dll and dxil.dll should be configurable // TODO: handle this not existing let dxc_container = if true { let dxc = hassle_rs::Dxc::new(Some("./".into()))?; let dxc_compiler = dxc.create_compiler()?; let dxc_library = dxc.create_library()?; + // Make sure that dxil.dll exists. + let _ = hassle_rs::Dxil::new(Some("./".into()))?; - let dxil = hassle_rs::Dxil::new(Some("./".into()))?; - let dxc_validator = dxil.create_validator()?; Some(super::DxcContainer { _dxc: dxc, dxc_compiler, dxc_library, - // _dxil: dxil, - dxc_validator, }) } else { None @@ -213,7 +211,7 @@ impl super::Device { stage: &crate::ProgrammableStage, layout: &super::PipelineLayout, naga_stage: naga::ShaderStage, - ) -> Result { + ) -> Result { use naga::back::hlsl; let stage_bit = crate::auxil::map_naga_stage(naga_stage); @@ -251,18 +249,19 @@ impl super::Device { .and_then(|cstr| cstr.to_str().ok()) .unwrap_or_default(); - let mut compile_flags = vec!["-Ges"]/* d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS */; - if self - .private_caps - .instance_flags - .contains(crate::InstanceFlags::DEBUG) - { - compile_flags.push("-Zi"); /* d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION */ - compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ - } - + // Compile with DXC if available, otherwise fall back to FXC let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { profiling::scope!("hassle_rs::compile_hlsl"); + let mut compile_flags = vec!["-Ges"]/* d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS */; + if self + .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 = dxc_container .dxc_library .create_blob_with_encoding_from_str(&source) @@ -282,20 +281,10 @@ impl super::Device { let (result, log_level) = match compiled { Ok(dxc_result) => match dxc_result.get_result() { - Ok(dxc_blob) => match dxc_container.dxc_validator.validate(dxc_blob) { - Ok(validated) => ( - Ok(super::ShaderDXIL::Dxc(validated.to_vec())), - log::Level::Info, - ), - Err(e) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - // I don't like this, but the nested matches are already too deep - format!("DXC validation error: {:?}. {}", e.0, e.1), - )), - log::Level::Warn, - ), - }, + Ok(dxc_blob) => ( + Ok(super::CompiledShader::Dxc(dxc_blob.to_vec())), + log::Level::Info, + ), Err(e) => ( Err(crate::PipelineError::Linkage( stage_bit, @@ -317,11 +306,11 @@ impl super::Device { } else { profiling::scope!("wgpu::backend::directx12::compile_fxc"); let (fxc_result, log_level) = self.compile_fxc( - naga_stage, &source, source_name, &ffi::CString::new(raw_ep.as_str()).unwrap(), stage_bit, + full_stage, ); (fxc_result, log_level) }; @@ -339,14 +328,15 @@ impl super::Device { // This function gets called if `device::dxc_compiler` is None, or if TODO: flag is set that disables DXC. fn compile_fxc( &self, - naga_stage: naga::ShaderStage, source: &String, source_name: &str, raw_ep: &ffi::CString, stage_bit: wgt::ShaderStages, - ) -> (Result, log::Level) { - use naga::back::hlsl; - + full_stage: String, + ) -> ( + Result, + log::Level, + ) { let mut shader_data = native::Blob::null(); let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; if self @@ -357,11 +347,6 @@ impl super::Device { compile_flags |= d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION; } - let full_stage = format!( - "{}_{}\0", - naga_stage.to_hlsl_str(), - hlsl::ShaderModel::V5_1.to_str() - ); let mut error = native::Blob::null(); let hr = unsafe { profiling::scope!("d3dcompiler::D3DCompile"); @@ -381,7 +366,10 @@ impl super::Device { }; match hr.into_result() { - Ok(()) => (Ok(super::ShaderDXIL::Fxc(shader_data)), log::Level::Info), + 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() { @@ -1193,7 +1181,12 @@ impl crate::Device for super::Device { }, bind_group_infos, naga_options: hlsl::Options { - shader_model: hlsl::ShaderModel::V6_0, // TODO: Set this based on whether fxc or dxc is used + 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, fake_missing_bindings: false, special_constants_binding, @@ -1485,12 +1478,12 @@ impl crate::Device for super::Device { let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC { pRootSignature: desc.layout.shared.signature.as_mut_ptr(), VS: match blob_vs { - super::ShaderDXIL::Dxc(ref blob_vs) => *native::Shader::from_raw(blob_vs), - super::ShaderDXIL::Fxc(blob_vs) => *native::Shader::from_blob(blob_vs), + super::CompiledShader::Dxc(ref blob_vs) => *native::Shader::from_raw(blob_vs), + super::CompiledShader::Fxc(blob_vs) => *native::Shader::from_blob(blob_vs), }, PS: match blob_fs { - Some(super::ShaderDXIL::Dxc(ref blob_fs)) => *native::Shader::from_raw(blob_fs), - Some(super::ShaderDXIL::Fxc(blob_fs)) => *native::Shader::from_blob(blob_fs), + Some(super::CompiledShader::Dxc(ref blob_fs)) => *native::Shader::from_raw(blob_fs), + Some(super::CompiledShader::Fxc(blob_fs)) => *native::Shader::from_blob(blob_fs), None => *native::Shader::null(), }, GS: *native::Shader::null(), @@ -1562,11 +1555,11 @@ impl crate::Device for super::Device { } }; - if let super::ShaderDXIL::Fxc(ref vs_fxc) = blob_vs { + if let super::CompiledShader::Fxc(ref vs_fxc) = blob_vs { unsafe { vs_fxc.destroy() }; } - if let Some(super::ShaderDXIL::Fxc(ref fs_fxc)) = blob_fs { + if let Some(super::CompiledShader::Fxc(ref fs_fxc)) = blob_fs { unsafe { fs_fxc.destroy() }; } @@ -1600,8 +1593,10 @@ impl crate::Device for super::Device { self.raw.create_compute_pipeline_state( desc.layout.shared.signature, match blob_cs { - crate::dx12::ShaderDXIL::Dxc(ref blob_cs) => native::Shader::from_raw(blob_cs), - crate::dx12::ShaderDXIL::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), + crate::dx12::CompiledShader::Dxc(ref blob_cs) => { + native::Shader::from_raw(blob_cs) + } + crate::dx12::CompiledShader::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), }, 0, native::CachedPSO::null(), @@ -1609,7 +1604,7 @@ impl crate::Device for super::Device { ) }; - if let super::ShaderDXIL::Fxc(cs_fxc) = blob_cs { + if let super::CompiledShader::Fxc(cs_fxc) = blob_cs { unsafe { cs_fxc.destroy() }; } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index c43dc6b5c7..5590b104e9 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -538,7 +538,7 @@ pub struct ShaderModule { raw_name: Option, } -enum ShaderDXIL { +enum CompiledShader { Dxc(Vec), Fxc(native::Blob), } @@ -564,11 +564,8 @@ unsafe impl Sync for ComputePipeline {} pub(crate) struct DxcContainer { dxc_compiler: hassle_rs::DxcCompiler, dxc_library: hassle_rs::DxcLibrary, - dxc_validator: hassle_rs::DxcValidator, // Has to be held onto for the lifetime of the device otherwise shaders will fail to compile _dxc: hassle_rs::Dxc, - // Has to be held onto for the lifetime of the device otherwise shaders will fail to compile - // _dxil: hassle_rs::Dxil, } impl SwapChain { From 2145dfd44dcbc64649f871124d8102d443b3c21d Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 5 Jan 2023 22:40:33 -0500 Subject: [PATCH 10/32] arrayvec and clippy --- wgpu-hal/src/dx12/device.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 4e8c64a292..057bfd389b 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -252,7 +252,8 @@ impl super::Device { // Compile with DXC if available, otherwise fall back to FXC let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { profiling::scope!("hassle_rs::compile_hlsl"); - let mut compile_flags = vec!["-Ges"]/* d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS */; + let mut compile_flags = arrayvec::ArrayVec::<&str, 3>::new_const(); + compile_flags.push("-Ges"); // d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS if self .private_caps .instance_flags @@ -1181,7 +1182,7 @@ impl crate::Device for super::Device { }, bind_group_infos, naga_options: hlsl::Options { - shader_model: match &self.dxc_container { + shader_model: match self.dxc_container { // DXC Some(_) => hlsl::ShaderModel::V6_0, // FXC doesn't support SM 6.0 From 89b76b586b24ff194d8fb39419fb2fa6fc294576 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Wed, 11 Jan 2023 03:14:25 -0500 Subject: [PATCH 11/32] add dx12compiler option to Instance::new() --- deno_webgpu/src/lib.rs | 1 + player/src/bin/play.rs | 7 ++++- player/tests/test.rs | 8 +++++- wgpu-core/src/hub.rs | 4 +-- wgpu-core/src/instance.rs | 15 ++++++----- wgpu-hal/Cargo.toml | 1 + wgpu-hal/examples/halmark/main.rs | 1 + wgpu-hal/src/dx12/adapter.rs | 10 ++++++- wgpu-hal/src/dx12/device.rs | 40 +++++++++++++++++----------- wgpu-hal/src/dx12/instance.rs | 10 ++++++- wgpu-hal/src/dx12/mod.rs | 6 +++-- wgpu-hal/src/lib.rs | 1 + wgpu-info/src/main.rs | 2 +- wgpu-types/src/lib.rs | 17 ++++++++++++ wgpu/Cargo.toml | 2 +- wgpu/examples/capture/main.rs | 1 + wgpu/examples/framework.rs | 2 +- wgpu/examples/hello-compute/main.rs | 2 +- wgpu/examples/hello-triangle/main.rs | 2 +- wgpu/examples/hello-windows/main.rs | 2 +- wgpu/examples/hello/main.rs | 2 +- wgpu/src/backend/direct.rs | 3 ++- wgpu/src/context.rs | 2 +- wgpu/src/lib.rs | 6 ++--- wgpu/tests/common/mod.rs | 2 +- wgpu/tests/instance.rs | 2 ++ 26 files changed, 107 insertions(+), 44 deletions(-) diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 287e340920..72c7f48532 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -241,6 +241,7 @@ pub async fn op_webgpu_request_adapter( "webgpu", wgpu_core::hub::IdentityManagerFactory, backends, + wgpu_types::Dx12Compiler::Fxc, )); state.borrow::() }; diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index 3ccc11c270..e76acc63cb 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -43,7 +43,12 @@ fn main() { .build(&event_loop) .unwrap(); - let global = wgc::hub::Global::new("player", IdentityPassThroughFactory, wgt::Backends::all()); + let global = wgc::hub::Global::new( + "player", + IdentityPassThroughFactory, + wgt::Backends::all(), + wgt::Dx12Compiler::Fxc, + ); let mut command_buffer_id_manager = wgc::hub::IdentityManager::default(); #[cfg(feature = "winit")] diff --git a/player/tests/test.rs b/player/tests/test.rs index 06da011a49..9f9cfbd299 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -178,7 +178,13 @@ impl Corpus { let dir = path.parent().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, + corpus.backends, + // TODO: Allow this to be configurable + wgt::Dx12Compiler::Fxc, + ); for &backend in BACKENDS { if !corpus.backends.contains(backend.into()) { continue; diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 290df3c716..f2654abc5c 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -1108,10 +1108,10 @@ pub struct Global { } impl Global { - pub fn new(name: &str, factory: G, backends: wgt::Backends) -> Self { + pub fn new(name: &str, factory: G, backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self { profiling::scope!("Global::new"); Self { - instance: Instance::new(name, backends), + instance: Instance::new(name, backends, dxc_option), surfaces: Registry::without_backend(&factory, "Surface"), hubs: Hubs::new(&factory), } diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 5bbf03543f..bd08ac833c 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -67,8 +67,8 @@ pub struct Instance { } impl Instance { - pub fn new(name: &str, backends: Backends) -> Self { - fn init(_: A, mask: Backends) -> Option { + pub fn new(name: &str, backends: Backends, dxc_option: wgt::Dx12Compiler) -> Self { + fn init(_: A, mask: Backends, dxc_option: Option) -> Option { if mask.contains(A::VARIANT.into()) { let mut flags = hal::InstanceFlags::empty(); if cfg!(debug_assertions) { @@ -78,6 +78,7 @@ impl Instance { let hal_desc = hal::InstanceDescriptor { name: "wgpu", flags, + dxc_option }; unsafe { hal::Instance::init(&hal_desc).ok() } } else { @@ -88,15 +89,15 @@ impl Instance { Self { name: name.to_string(), #[cfg(feature = "vulkan")] - vulkan: init(hal::api::Vulkan, backends), + vulkan: init(hal::api::Vulkan, backends, None), #[cfg(feature = "metal")] - metal: init(hal::api::Metal, backends), + metal: init(hal::api::Metal, backends, None), #[cfg(feature = "dx12")] - dx12: init(hal::api::Dx12, backends), + dx12: init(hal::api::Dx12, backends, Some(dxc_option)), #[cfg(feature = "dx11")] - dx11: init(hal::api::Dx11, backends), + dx11: init(hal::api::Dx11, backends, None), #[cfg(feature = "gles")] - gl: init(hal::api::Gles, backends), + gl: init(hal::api::Gles, backends, None), } } diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 775155ba93..3d9dad82db 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -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", "hassle-rs"] # 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"] +dxc_shader_compiler = [] renderdoc = ["libloading", "renderdoc-sys"] emscripten = ["gles"] diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 7b3ea12c0a..820842019b 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -96,6 +96,7 @@ impl Example { } else { hal::InstanceFlags::empty() }, + dxc_option: None, }; let instance = unsafe { A::Instance::init(&instance_desc)? }; let mut surface = unsafe { diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 2119ebd522..ba1fe1e974 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -52,6 +52,7 @@ impl super::Adapter { adapter: native::DxgiAdapter, library: &Arc, instance_flags: crate::InstanceFlags, + dxc_option: &wgt::Dx12Compiler, ) -> Option> { // Create the device so that we can get the capabilities. let device = { @@ -243,6 +244,7 @@ impl super::Adapter { private_caps, presentation_timer, workarounds, + dxc_option: dxc_option.clone(), }, info, features, @@ -347,7 +349,13 @@ impl crate::Adapter for super::Adapter { .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.dxc_option.clone(), // TODO: Don't clone this + )?; Ok(crate::OpenDevice { device, queue: super::Queue { diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 057bfd389b..49192ed179 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -21,26 +21,34 @@ impl super::Device { present_queue: native::CommandQueue, private_caps: super::PrivateCapabilities, library: &Arc, + dxc_option: wgt::Dx12Compiler, ) -> Result { let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?; // TODO: path to dxcompiler.dll and dxil.dll should be configurable // TODO: handle this not existing - let dxc_container = if true { - let dxc = hassle_rs::Dxc::new(Some("./".into()))?; - let dxc_compiler = dxc.create_compiler()?; - let dxc_library = dxc.create_library()?; - // Make sure that dxil.dll exists. - let _ = hassle_rs::Dxil::new(Some("./".into()))?; - - Some(super::DxcContainer { - _dxc: dxc, - dxc_compiler, - dxc_library, - }) - } else { - None + #[cfg(feature = "dxc_shader_compiler")] + let dxc_container = match dxc_option { + wgt::Dx12Compiler::Dxc { + dxil_path, + dxc_path, + } => { + let dxc = hassle_rs::Dxc::new(dxc_path)?; + let dxc_compiler = dxc.create_compiler()?; + let dxc_library = dxc.create_library()?; + // Make sure that dxil.dll exists. + let _ = hassle_rs::Dxil::new(dxil_path)?; + + Some(super::DxcContainer { + _dxc: dxc, + compiler: dxc_compiler, + library: dxc_library, + }) + } + wgt::Dx12Compiler::Fxc => None, }; + #[cfg(not(feature = "dxc_shader_compiler"))] + let dxc_container = None; let mut idle_fence = native::Fence::null(); let hr = unsafe { @@ -264,13 +272,13 @@ impl super::Device { } let blob = dxc_container - .dxc_library + .library .create_blob_with_encoding_from_str(&source) .map_err(|e| { crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) })?; - let compiled = dxc_container.dxc_compiler.compile( + let compiled = dxc_container.compiler.compile( &blob, source_name, raw_ep, diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 71f53e140e..b131cbe439 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -57,6 +57,11 @@ impl crate::Instance for super::Instance { } } + let dxc_option = match &desc.dxc_option { + Some(opt) => opt.clone(), + None => wgt::Dx12Compiler::default(), + }; + Ok(Self { // The call to create_factory will only succeed if we get a factory4, so this is safe. factory, @@ -64,6 +69,7 @@ impl crate::Instance for super::Instance { _lib_dxgi: lib_dxgi, supports_allow_tearing, flags: desc.flags, + dxc_option, }) } @@ -91,7 +97,9 @@ impl crate::Instance for super::Instance { adapters .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.dxc_option) + }) .collect() } } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 5590b104e9..777f99c502 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -92,6 +92,7 @@ pub struct Instance { supports_allow_tearing: bool, _lib_dxgi: native::DxgiLib, flags: crate::InstanceFlags, + dxc_option: wgt::Dx12Compiler, } impl Instance { @@ -173,6 +174,7 @@ pub struct Adapter { //Note: this isn't used right now, but we'll need it later. #[allow(unused)] workarounds: Workarounds, + dxc_option: wgt::Dx12Compiler, } unsafe impl Send for Adapter {} @@ -562,8 +564,8 @@ unsafe impl Send for ComputePipeline {} unsafe impl Sync for ComputePipeline {} pub(crate) struct DxcContainer { - dxc_compiler: hassle_rs::DxcCompiler, - dxc_library: hassle_rs::DxcLibrary, + compiler: hassle_rs::DxcCompiler, + 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, } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index db15ecf24e..68abf0a644 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -743,6 +743,7 @@ bitflags::bitflags! { pub struct InstanceDescriptor<'a> { pub name: &'a str, pub flags: InstanceFlags, + pub dxc_option: Option, } #[derive(Clone, Debug)] diff --git a/wgpu-info/src/main.rs b/wgpu-info/src/main.rs index 9d477e7cd5..33ed5c31f2 100644 --- a/wgpu-info/src/main.rs +++ b/wgpu-info/src/main.rs @@ -281,7 +281,7 @@ mod inner { env_logger::init(); let args: Vec<_> = std::env::args().skip(1).collect(); - let instance = wgpu::Instance::new(wgpu::Backends::all()); + let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect(); let adapter_count = adapters.len(); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 6a12bad9c1..98a9b60a55 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -12,6 +12,7 @@ #[cfg(any(feature = "serde", test))] use serde::{Deserialize, Serialize}; use std::hash::{Hash, Hasher}; +use std::path::PathBuf; use std::{num::NonZeroU32, ops::Range}; pub mod assertions; @@ -5293,3 +5294,19 @@ impl Default for ShaderBoundChecks { Self::new() } } + +// TODO: What happens if the user selects dxc, but the dxc feature is disabled? +#[derive(Clone, Debug)] +pub enum Dx12Compiler { + Fxc, + Dxc { + dxil_path: Option, + dxc_path: Option, + }, +} + +impl Default for Dx12Compiler { + fn default() -> Self { + Self::Fxc + } +} \ No newline at end of file diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index b2e90793fd..9f59a7baa8 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -137,7 +137,7 @@ hal = { workspace = true } hal = { workspace = true, features = ["renderdoc"] } [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] workspace = true diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 747b361de2..3e7449c593 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -38,6 +38,7 @@ async fn create_red_image_with_dimensions( ) -> (Device, Buffer, BufferDimensions, SubmissionIndex) { let adapter = wgpu::Instance::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), + wgpu::Dx12Compiler::default(), ) .request_adapter(&wgpu::RequestAdapterOptions::default()) .await diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 9af044bf66..f3b632f568 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -159,7 +159,7 @@ async fn setup(title: &str) -> Setup { let backend = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); - let instance = wgpu::Instance::new(backend); + let instance = wgpu::Instance::new(backend, wgpu::Dx12Compiler::default()); let (size, surface) = unsafe { let size = window.inner_size(); diff --git a/wgpu/examples/hello-compute/main.rs b/wgpu/examples/hello-compute/main.rs index 3e21ee11be..014ed44d20 100644 --- a/wgpu/examples/hello-compute/main.rs +++ b/wgpu/examples/hello-compute/main.rs @@ -33,7 +33,7 @@ async fn run() { async fn execute_gpu(numbers: &[u32]) -> Option> { // Instantiates instance of WebGPU - let instance = wgpu::Instance::new(wgpu::Backends::all()); + let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); // `request_adapter` instantiates the general connection to the GPU let adapter = instance diff --git a/wgpu/examples/hello-triangle/main.rs b/wgpu/examples/hello-triangle/main.rs index 58e7ba1a90..feb97e8d69 100644 --- a/wgpu/examples/hello-triangle/main.rs +++ b/wgpu/examples/hello-triangle/main.rs @@ -7,7 +7,7 @@ use winit::{ async fn run(event_loop: EventLoop<()>, window: Window) { let size = window.inner_size(); - let instance = wgpu::Instance::new(wgpu::Backends::all()); + let instance = wgpu::Instance::new(wgpu::Backends::all(), wgt::Dx12Compiler::default()); let surface = unsafe { instance.create_surface(&window) }.unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { diff --git a/wgpu/examples/hello-windows/main.rs b/wgpu/examples/hello-windows/main.rs index 4a93cf6b7f..e268514fcb 100644 --- a/wgpu/examples/hello-windows/main.rs +++ b/wgpu/examples/hello-windows/main.rs @@ -62,7 +62,7 @@ impl Viewport { } async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) { - let instance = wgpu::Instance::new(wgpu::Backends::all()); + let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); let viewports: Vec<_> = viewports .into_iter() .map(|(window, color)| ViewportDesc::new(window, color, &instance)) diff --git a/wgpu/examples/hello/main.rs b/wgpu/examples/hello/main.rs index f74c5d1f8e..e804a794d5 100644 --- a/wgpu/examples/hello/main.rs +++ b/wgpu/examples/hello/main.rs @@ -2,7 +2,7 @@ async fn run() { #[cfg_attr(target_arch = "wasm32", allow(unused_variables))] let adapter = { - let instance = wgpu::Instance::new(wgpu::Backends::all()); + let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); #[cfg(not(target_arch = "wasm32"))] { log::info!("Available adapters:"); diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index d9632843d4..24682cd849 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -516,11 +516,12 @@ impl crate::Context for Context { type PopErrorScopeFuture = Ready>; - fn init(backends: wgt::Backends) -> Self { + fn init(backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self { Self(wgc::hub::Global::new( "wgpu", wgc::hub::IdentityManagerFactory, backends, + dxc_option, )) } diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index 410ed2c0b7..e9ec48b02e 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -97,7 +97,7 @@ pub trait Context: Debug + Send + Sized + Sync { + 'static; type PopErrorScopeFuture: Future> + Send + 'static; - fn init(backends: wgt::Backends) -> Self; + fn init(backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self; fn instance_create_surface( &self, display_handle: raw_window_handle::RawDisplayHandle, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 809b27e9d9..416cdc673d 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -33,7 +33,7 @@ pub use wgt::{ BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBindingType, BufferSize, BufferUsages, Color, ColorTargetState, ColorWrites, CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState, - DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, DynamicOffset, Extent3d, + DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler, DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, ImageDataLayout, ImageSubresourceRange, IndexFormat, Limits, MultisampleState, Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange, @@ -1284,9 +1284,9 @@ impl Instance { /// /// - `backends` - Controls from which [backends][Backends] wgpu will choose /// during instantiation. - pub fn new(backends: Backends) -> Self { + pub fn new(backends: Backends, dxc_option: wgt::Dx12Compiler) -> Self { Self { - context: Arc::from(crate::backend::Context::init(backends)), + context: Arc::from(crate::backend::Context::init(backends, dxc_option)), } } diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index cdcf8f94ea..57ee8a8f9b 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -332,7 +332,7 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te fn initialize_adapter() -> (Adapter, SurfaceGuard) { let backend_bits = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all); - let instance = Instance::new(backend_bits); + let instance = Instance::new(backend_bits, wgpu::Dx12Compiler::default()); let surface_guard; let compatible_surface; diff --git a/wgpu/tests/instance.rs b/wgpu/tests/instance.rs index 1ead17c57e..0dad3f9220 100644 --- a/wgpu/tests/instance.rs +++ b/wgpu/tests/instance.rs @@ -5,12 +5,14 @@ use wasm_bindgen_test::*; fn initialize() { let _ = wgpu::Instance::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), + wgpu::Dx12Compiler::default(), ); } fn request_adapter_inner(power: wgt::PowerPreference) { let instance = wgpu::Instance::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), + wgpu::Dx12Compiler::default(), ); let _adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { From c2bdc390d654cf19eda9a87d40633b12f69ca6ec Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Wed, 11 Jan 2023 17:52:22 -0500 Subject: [PATCH 12/32] use InstanceOptions struct when creating an Instance --- deno_webgpu/src/lib.rs | 3 +-- player/src/bin/play.rs | 3 +-- player/tests/test.rs | 4 +--- wgpu-core/src/hub.rs | 4 ++-- wgpu-core/src/instance.rs | 24 ++++++++++++------- wgpu-hal/examples/halmark/main.rs | 2 +- wgpu-hal/src/dx12/adapter.rs | 6 ++--- wgpu-hal/src/dx12/device.rs | 4 ++-- wgpu-hal/src/dx12/instance.rs | 8 +++---- wgpu-hal/src/dx12/mod.rs | 4 ++-- wgpu-hal/src/lib.rs | 2 +- wgpu-info/src/main.rs | 2 +- wgpu-types/src/lib.rs | 25 ++++++++++++++++++- wgpu/examples/capture/main.rs | 14 ++++++----- wgpu/examples/framework.rs | 4 +++- wgpu/examples/hello-compute/main.rs | 2 +- wgpu/examples/hello-triangle/main.rs | 4 +++- wgpu/examples/hello-windows/main.rs | 2 +- wgpu/examples/hello/main.rs | 2 +- wgpu/src/backend/direct.rs | 5 ++-- wgpu/src/context.rs | 2 +- wgpu/src/lib.rs | 36 +++++++++++++++++----------- wgpu/src/util/init.rs | 15 ++++++++++++ wgpu/tests/common/mod.rs | 7 +++++- wgpu/tests/instance.rs | 10 ++++---- 25 files changed, 127 insertions(+), 67 deletions(-) diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 72c7f48532..66e93129b9 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -240,8 +240,7 @@ pub async fn op_webgpu_request_adapter( state.put(wgpu_core::hub::Global::new( "webgpu", wgpu_core::hub::IdentityManagerFactory, - backends, - wgpu_types::Dx12Compiler::Fxc, + wgpu_types::InstanceOptions::new(backends, wgpu_types::Dx12Compiler::Fxc), )); state.borrow::() }; diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index e76acc63cb..8a3f722818 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -46,8 +46,7 @@ fn main() { let global = wgc::hub::Global::new( "player", IdentityPassThroughFactory, - wgt::Backends::all(), - wgt::Dx12Compiler::Fxc, + wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc), ); let mut command_buffer_id_manager = wgc::hub::IdentityManager::default(); diff --git a/player/tests/test.rs b/player/tests/test.rs index 9f9cfbd299..4ab1086676 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -181,9 +181,7 @@ impl Corpus { let global = wgc::hub::Global::new( "test", IdentityPassThroughFactory, - corpus.backends, - // TODO: Allow this to be configurable - wgt::Dx12Compiler::Fxc, + wgt::InstanceOptions::new(corpus.backends, wgt::Dx12Compiler::Fxc), ); for &backend in BACKENDS { if !corpus.backends.contains(backend.into()) { diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index f2654abc5c..5fa4cace4b 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -1108,10 +1108,10 @@ pub struct Global { } impl Global { - pub fn new(name: &str, factory: G, backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self { + pub fn new(name: &str, factory: G, instance_options: wgt::InstanceOptions) -> Self { profiling::scope!("Global::new"); Self { - instance: Instance::new(name, backends, dxc_option), + instance: Instance::new(name, instance_options), surfaces: Registry::without_backend(&factory, "Surface"), hubs: Hubs::new(&factory), } diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index bd08ac833c..e9c530563c 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -67,8 +67,12 @@ pub struct Instance { } impl Instance { - pub fn new(name: &str, backends: Backends, dxc_option: wgt::Dx12Compiler) -> Self { - fn init(_: A, mask: Backends, dxc_option: Option) -> Option { + pub fn new(name: &str, instance_options: wgt::InstanceOptions) -> Self { + fn init( + _: A, + mask: Backends, + dx12_shader_compiler: Option, + ) -> Option { if mask.contains(A::VARIANT.into()) { let mut flags = hal::InstanceFlags::empty(); if cfg!(debug_assertions) { @@ -78,7 +82,7 @@ impl Instance { let hal_desc = hal::InstanceDescriptor { name: "wgpu", flags, - dxc_option + dx12_shader_compiler, }; unsafe { hal::Instance::init(&hal_desc).ok() } } else { @@ -89,15 +93,19 @@ impl Instance { Self { name: name.to_string(), #[cfg(feature = "vulkan")] - vulkan: init(hal::api::Vulkan, backends, None), + vulkan: init(hal::api::Vulkan, instance_options.backends, None), #[cfg(feature = "metal")] - metal: init(hal::api::Metal, backends, None), + metal: init(hal::api::Metal, instance_options.backends, None), #[cfg(feature = "dx12")] - dx12: init(hal::api::Dx12, backends, Some(dxc_option)), + dx12: init( + hal::api::Dx12, + instance_options.backends, + Some(instance_options.dx12_shader_compiler), + ), #[cfg(feature = "dx11")] - dx11: init(hal::api::Dx11, backends, None), + dx11: init(hal::api::Dx11, instance_options.backends, None), #[cfg(feature = "gles")] - gl: init(hal::api::Gles, backends, None), + gl: init(hal::api::Gles, instance_options.backends, None), } } diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 820842019b..1e11dc1395 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -96,7 +96,7 @@ impl Example { } else { hal::InstanceFlags::empty() }, - dxc_option: None, + dx12_shader_compiler: None, }; let instance = unsafe { A::Instance::init(&instance_desc)? }; let mut surface = unsafe { diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index ba1fe1e974..d697bbbfdc 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -52,7 +52,7 @@ impl super::Adapter { adapter: native::DxgiAdapter, library: &Arc, instance_flags: crate::InstanceFlags, - dxc_option: &wgt::Dx12Compiler, + dx12_shader_compiler: &wgt::Dx12Compiler, ) -> Option> { // Create the device so that we can get the capabilities. let device = { @@ -244,7 +244,7 @@ impl super::Adapter { private_caps, presentation_timer, workarounds, - dxc_option: dxc_option.clone(), + dx12_shader_compiler: dx12_shader_compiler.clone(), }, info, features, @@ -354,7 +354,7 @@ impl crate::Adapter for super::Adapter { queue, self.private_caps, &self.library, - self.dxc_option.clone(), // TODO: Don't clone this + self.dx12_shader_compiler.clone(), // TODO: Don't clone this )?; Ok(crate::OpenDevice { device, diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 49192ed179..81fb3bcc5f 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -21,14 +21,14 @@ impl super::Device { present_queue: native::CommandQueue, private_caps: super::PrivateCapabilities, library: &Arc, - dxc_option: wgt::Dx12Compiler, + dx12_shader_compiler: wgt::Dx12Compiler, ) -> Result { let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?; // TODO: path to dxcompiler.dll and dxil.dll should be configurable // TODO: handle this not existing #[cfg(feature = "dxc_shader_compiler")] - let dxc_container = match dxc_option { + let dxc_container = match dx12_shader_compiler { wgt::Dx12Compiler::Dxc { dxil_path, dxc_path, diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index b131cbe439..1f3c7074f3 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -57,8 +57,8 @@ impl crate::Instance for super::Instance { } } - let dxc_option = match &desc.dxc_option { - Some(opt) => opt.clone(), + let dx12_shader_compiler = match &desc.dx12_shader_compiler { + Some(compiler_option) => compiler_option.clone(), None => wgt::Dx12Compiler::default(), }; @@ -69,7 +69,7 @@ impl crate::Instance for super::Instance { _lib_dxgi: lib_dxgi, supports_allow_tearing, flags: desc.flags, - dxc_option, + dx12_shader_compiler, }) } @@ -98,7 +98,7 @@ impl crate::Instance for super::Instance { adapters .into_iter() .filter_map(|raw| { - super::Adapter::expose(raw, &self.library, self.flags, &self.dxc_option) + super::Adapter::expose(raw, &self.library, self.flags, &self.dx12_shader_compiler) }) .collect() } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 777f99c502..38f36ac470 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -92,7 +92,7 @@ pub struct Instance { supports_allow_tearing: bool, _lib_dxgi: native::DxgiLib, flags: crate::InstanceFlags, - dxc_option: wgt::Dx12Compiler, + dx12_shader_compiler: wgt::Dx12Compiler, } impl Instance { @@ -174,7 +174,7 @@ pub struct Adapter { //Note: this isn't used right now, but we'll need it later. #[allow(unused)] workarounds: Workarounds, - dxc_option: wgt::Dx12Compiler, + dx12_shader_compiler: wgt::Dx12Compiler, } unsafe impl Send for Adapter {} diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 68abf0a644..aa31f4da09 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -743,7 +743,7 @@ bitflags::bitflags! { pub struct InstanceDescriptor<'a> { pub name: &'a str, pub flags: InstanceFlags, - pub dxc_option: Option, + pub dx12_shader_compiler: Option, } #[derive(Clone, Debug)] diff --git a/wgpu-info/src/main.rs b/wgpu-info/src/main.rs index 33ed5c31f2..d8a2fe64ca 100644 --- a/wgpu-info/src/main.rs +++ b/wgpu-info/src/main.rs @@ -281,7 +281,7 @@ mod inner { env_logger::init(); let args: Vec<_> = std::env::args().skip(1).collect(); - let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); + let instance = wgpu::Instance::new(wgpu::InstanceOptions::default()); let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect(); let adapter_count = adapters.len(); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 98a9b60a55..9156ecda91 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5309,4 +5309,27 @@ impl Default for Dx12Compiler { fn default() -> Self { Self::Fxc } -} \ No newline at end of file +} + +pub struct InstanceOptions { + pub backends: Backends, + pub dx12_shader_compiler: Dx12Compiler, +} + +impl Default for InstanceOptions { + fn default() -> Self { + Self { + backends: Backends::all(), + dx12_shader_compiler: Dx12Compiler::default(), + } + } +} + +impl InstanceOptions { + pub fn new(backends: Backends, dx12_shader_compiler: Dx12Compiler) -> Self { + Self { + backends, + dx12_shader_compiler, + } + } +} diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 3e7449c593..8487376911 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -36,13 +36,15 @@ async fn create_red_image_with_dimensions( width: usize, height: usize, ) -> (Device, Buffer, BufferDimensions, SubmissionIndex) { - let adapter = wgpu::Instance::new( - wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), + let backend = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); + let instance = wgpu::Instance::new(wgpu::InstanceOptions::new( + backend, wgpu::Dx12Compiler::default(), - ) - .request_adapter(&wgpu::RequestAdapterOptions::default()) - .await - .unwrap(); + )); + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions::default()) + .await + .unwrap(); let (device, queue) = adapter .request_device( diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index f3b632f568..f10f13ef1b 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -158,8 +158,10 @@ async fn setup(title: &str) -> Setup { log::info!("Initializing the surface..."); let backend = 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(wgpu::Dx12Compiler::default()); - let instance = wgpu::Instance::new(backend, wgpu::Dx12Compiler::default()); + let instance = wgpu::Instance::new(wgpu::InstanceOptions::new(backend, dx12_shader_compiler)); let (size, surface) = unsafe { let size = window.inner_size(); diff --git a/wgpu/examples/hello-compute/main.rs b/wgpu/examples/hello-compute/main.rs index 014ed44d20..b46cabe06b 100644 --- a/wgpu/examples/hello-compute/main.rs +++ b/wgpu/examples/hello-compute/main.rs @@ -33,7 +33,7 @@ async fn run() { async fn execute_gpu(numbers: &[u32]) -> Option> { // Instantiates instance of WebGPU - let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); + let instance = wgpu::Instance::default(); // `request_adapter` instantiates the general connection to the GPU let adapter = instance diff --git a/wgpu/examples/hello-triangle/main.rs b/wgpu/examples/hello-triangle/main.rs index feb97e8d69..9b00992170 100644 --- a/wgpu/examples/hello-triangle/main.rs +++ b/wgpu/examples/hello-triangle/main.rs @@ -7,7 +7,9 @@ use winit::{ async fn run(event_loop: EventLoop<()>, window: Window) { let size = window.inner_size(); - let instance = wgpu::Instance::new(wgpu::Backends::all(), wgt::Dx12Compiler::default()); + + let instance = wgpu::Instance::default(); + let surface = unsafe { instance.create_surface(&window) }.unwrap(); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { diff --git a/wgpu/examples/hello-windows/main.rs b/wgpu/examples/hello-windows/main.rs index e268514fcb..df1057b27c 100644 --- a/wgpu/examples/hello-windows/main.rs +++ b/wgpu/examples/hello-windows/main.rs @@ -62,7 +62,7 @@ impl Viewport { } async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) { - let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); + let instance = wgpu::Instance::default(); let viewports: Vec<_> = viewports .into_iter() .map(|(window, color)| ViewportDesc::new(window, color, &instance)) diff --git a/wgpu/examples/hello/main.rs b/wgpu/examples/hello/main.rs index e804a794d5..71d947cdc6 100644 --- a/wgpu/examples/hello/main.rs +++ b/wgpu/examples/hello/main.rs @@ -2,7 +2,7 @@ async fn run() { #[cfg_attr(target_arch = "wasm32", allow(unused_variables))] let adapter = { - let instance = wgpu::Instance::new(wgpu::Backends::all(), wgpu::Dx12Compiler::default()); + let instance = wgpu::Instance::default(); #[cfg(not(target_arch = "wasm32"))] { log::info!("Available adapters:"); diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 24682cd849..b045a08bd6 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -516,12 +516,11 @@ impl crate::Context for Context { type PopErrorScopeFuture = Ready>; - fn init(backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self { + fn init(instance_options: wgt::InstanceOptions) -> Self { Self(wgc::hub::Global::new( "wgpu", wgc::hub::IdentityManagerFactory, - backends, - dxc_option, + instance_options, )) } diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index e9ec48b02e..9b00e50cbe 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -97,7 +97,7 @@ pub trait Context: Debug + Send + Sized + Sync { + 'static; type PopErrorScopeFuture: Future> + Send + 'static; - fn init(backends: wgt::Backends, dxc_option: wgt::Dx12Compiler) -> Self; + fn init(instance_options: wgt::InstanceOptions) -> Self; fn instance_create_surface( &self, display_handle: raw_window_handle::RawDisplayHandle, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 416cdc673d..9404f5b2c7 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -33,18 +33,18 @@ pub use wgt::{ BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBindingType, BufferSize, BufferUsages, Color, ColorTargetState, ColorWrites, CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState, - DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler, DynamicOffset, Extent3d, - Face, Features, FilterMode, FrontFace, ImageDataLayout, ImageSubresourceRange, IndexFormat, - Limits, MultisampleState, Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference, - PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange, - QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, ShaderLocation, - ShaderModel, ShaderStages, StencilFaceState, StencilOperation, StencilState, - StorageTextureAccess, SurfaceCapabilities, SurfaceConfiguration, SurfaceStatus, TextureAspect, - TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, - TextureSampleType, TextureUsages, TextureViewDimension, VertexAttribute, VertexFormat, - VertexStepMode, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, - PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, - VERTEX_STRIDE_ALIGNMENT, + DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler, + DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, ImageDataLayout, + ImageSubresourceRange, IndexFormat, InstanceOptions, Limits, MultisampleState, Origin3d, + PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PresentationTimestamp, + PrimitiveState, PrimitiveTopology, PushConstantRange, QueryType, RenderBundleDepthStencil, + SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, ShaderStages, + StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, SurfaceCapabilities, + SurfaceConfiguration, SurfaceStatus, TextureAspect, TextureDimension, TextureFormat, + TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType, TextureUsages, + TextureViewDimension, VertexAttribute, VertexFormat, VertexStepMode, COPY_BUFFER_ALIGNMENT, + COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT, + QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT, }; /// Filter for error scopes. @@ -1277,6 +1277,14 @@ impl Display 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(InstanceOptions::default()) + } +} + impl Instance { /// Create an new instance of wgpu. /// @@ -1284,9 +1292,9 @@ impl Instance { /// /// - `backends` - Controls from which [backends][Backends] wgpu will choose /// during instantiation. - pub fn new(backends: Backends, dxc_option: wgt::Dx12Compiler) -> Self { + pub fn new(instance_options: InstanceOptions) -> Self { Self { - context: Arc::from(crate::backend::Context::init(backends, dxc_option)), + context: Arc::from(crate::backend::Context::init(instance_options)), } } diff --git a/wgpu/src/util/init.rs b/wgpu/src/util/init.rs index 7f442332dc..06dddc7859 100644 --- a/wgpu/src/util/init.rs +++ b/wgpu/src/util/init.rs @@ -86,3 +86,18 @@ pub async fn initialize_adapter_from_env_or_default( } } } + +/// Choose which DX12 shader compiler to use from the environment variable WGPU_DX12_COMPILER +pub fn dx12_shader_compiler_from_env() -> Option { + 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, + }, + ) +} \ No newline at end of file diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 57ee8a8f9b..7868688756 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -332,7 +332,12 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te fn initialize_adapter() -> (Adapter, SurfaceGuard) { let backend_bits = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all); - let instance = Instance::new(backend_bits, wgpu::Dx12Compiler::default()); + let dx12_shader_compiler = + wgpu::util::dx12_shader_compiler_from_env().unwrap_or(wgpu::Dx12Compiler::default()); + let instance = Instance::new(wgpu::InstanceOptions::new( + backend_bits, + dx12_shader_compiler, + )); let surface_guard; let compatible_surface; diff --git a/wgpu/tests/instance.rs b/wgpu/tests/instance.rs index 0dad3f9220..4a8b4e1b94 100644 --- a/wgpu/tests/instance.rs +++ b/wgpu/tests/instance.rs @@ -3,17 +3,17 @@ use wasm_bindgen_test::*; #[test] #[wasm_bindgen_test] fn initialize() { - let _ = wgpu::Instance::new( + let _ = wgpu::Instance::new(wgpu::InstanceOptions::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), - wgpu::Dx12Compiler::default(), - ); + wgpu::util::dx12_shader_compiler_from_env().unwrap_or(wgpu::Dx12Compiler::default()), + )); } fn request_adapter_inner(power: wgt::PowerPreference) { - let instance = wgpu::Instance::new( + let instance = wgpu::Instance::new(wgpu::InstanceOptions::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), wgpu::Dx12Compiler::default(), - ); + )); let _adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions { power_preference: power, From 02617bbebb604fa22b461b275098728c3324c353 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Wed, 11 Jan 2023 17:54:30 -0500 Subject: [PATCH 13/32] Move dx12 shader compilation to a separate file and put hassle-rs behind the dxc_shader_compiler flag --- wgpu-hal/Cargo.toml | 4 +- wgpu-hal/src/dx12/device.rs | 156 ++------------- wgpu-hal/src/dx12/mod.rs | 40 +--- wgpu-hal/src/dx12/shader_compilation.rs | 252 ++++++++++++++++++++++++ 4 files changed, 272 insertions(+), 180 deletions(-) create mode 100644 wgpu-hal/src/dx12/shader_compilation.rs diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 3d9dad82db..837a5bb9d2 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -32,10 +32,10 @@ metal = ["naga/msl-out", "block", "foreign-types"] vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "smallvec"] gles = ["naga/glsl-out", "glow", "egl", "libloading"] dx11 = ["naga/hlsl-out", "native", "libloading", "winapi/d3d11", "winapi/d3d11_1", "winapi/d3d11_2", "winapi/d3d11sdklayers", "winapi/dxgi1_6"] -dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6", "hassle-rs"] +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. windows_rs = ["gpu-allocator"] -dxc_shader_compiler = [] +dxc_shader_compiler = ["hassle-rs"] renderdoc = ["libloading", "renderdoc-sys"] emscripten = ["gles"] diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 81fb3bcc5f..4e6883cc20 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -5,10 +5,10 @@ use crate::{ use super::{conv, descriptor, view}; 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::{ shared::{dxgiformat, dxgitype, minwindef::BOOL, winerror}, - um::{d3d12, d3dcompiler, synchapi, winbase}, + um::{d3d12, synchapi, winbase}, Interface, }; @@ -25,30 +25,13 @@ impl super::Device { ) -> Result { let mem_allocator = super::suballocation::create_allocator_wrapper(&raw)?; - // TODO: path to dxcompiler.dll and dxil.dll should be configurable - // TODO: handle this not existing - #[cfg(feature = "dxc_shader_compiler")] let dxc_container = match dx12_shader_compiler { wgt::Dx12Compiler::Dxc { dxil_path, dxc_path, - } => { - let dxc = hassle_rs::Dxc::new(dxc_path)?; - let dxc_compiler = dxc.create_compiler()?; - let dxc_library = dxc.create_library()?; - // Make sure that dxil.dll exists. - let _ = hassle_rs::Dxil::new(dxil_path)?; - - Some(super::DxcContainer { - _dxc: dxc, - compiler: dxc_compiler, - library: dxc_library, - }) - } + } => super::shader_compilation::get_dxc_container(dxc_path, dxil_path)?, wgt::Dx12Compiler::Fxc => None, }; - #[cfg(not(feature = "dxc_shader_compiler"))] - let dxc_container = None; let mut idle_fence = native::Fence::null(); let hr = unsafe { @@ -259,69 +242,26 @@ impl super::Device { // Compile with DXC if available, otherwise fall back to FXC let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { - profiling::scope!("hassle_rs::compile_hlsl"); - let mut compile_flags = arrayvec::ArrayVec::<&str, 3>::new_const(); - compile_flags.push("-Ges"); // d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS - if self - .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 = dxc_container - .library - .create_blob_with_encoding_from_str(&source) - .map_err(|e| { - crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e)) - })?; - - let compiled = dxc_container.compiler.compile( - &blob, + profiling::scope!("wgpu::backend::directx12::compile_dxc"); + crate::dx12::shader_compilation::compile_dxc( + self, + &source, source_name, raw_ep, - &full_stage, - &compile_flags, - None, // TODO: idk what the include handler does - &[], - ); - - let (result, log_level) = match compiled { - Ok(dxc_result) => match dxc_result.get_result() { - Ok(dxc_blob) => ( - Ok(super::CompiledShader::Dxc(dxc_blob.to_vec())), - log::Level::Info, - ), - Err(e) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - format!("DXC compile error: {}", e), - )), - log::Level::Warn, - ), - }, - Err(e) => ( - Err(crate::PipelineError::Linkage( - stage_bit, - format!("DXC compile error: {:?}", e), - )), - log::Level::Warn, - ), - }; - - (result, log_level) + stage_bit, + full_stage, + dxc_container, + ) } else { profiling::scope!("wgpu::backend::directx12::compile_fxc"); - let (fxc_result, log_level) = self.compile_fxc( + crate::dx12::shader_compilation::compile_fxc( + self, &source, source_name, &ffi::CString::new(raw_ep.as_str()).unwrap(), stage_bit, full_stage, - ); - (fxc_result, log_level) + ) }; log::log!( @@ -334,74 +274,6 @@ impl super::Device { result } - // This function gets called if `device::dxc_compiler` is None, or if TODO: flag is set that disables DXC. - fn compile_fxc( - &self, - source: &String, - source_name: &str, - raw_ep: &ffi::CString, - stage_bit: wgt::ShaderStages, - full_stage: String, - ) -> ( - Result, - log::Level, - ) { - let mut shader_data = native::Blob::null(); - let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; - if self - .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 { - 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, - ) - } - } - } - pub fn raw_device(&self) -> &native::Device { &self.raw } diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 38f36ac470..1e58a2be4e 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -39,6 +39,7 @@ mod conv; mod descriptor; mod device; mod instance; +mod shader_compilation; mod suballocation; mod view; @@ -243,7 +244,7 @@ pub struct Device { render_doc: crate::auxil::renderdoc::RenderDoc, null_rtv_handle: descriptor::Handle, mem_allocator: Option>, - dxc_container: Option, + dxc_container: Option, } unsafe impl Send for Device {} @@ -540,7 +541,8 @@ pub struct ShaderModule { raw_name: Option, } -enum CompiledShader { +pub(super) enum CompiledShader { + #[allow(unused)] Dxc(Vec), Fxc(native::Blob), } @@ -563,13 +565,6 @@ pub struct ComputePipeline { unsafe impl Send for ComputePipeline {} unsafe impl Sync for ComputePipeline {} -pub(crate) struct DxcContainer { - compiler: hassle_rs::DxcCompiler, - 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, -} - impl SwapChain { unsafe fn release_resources(self) -> native::WeakPtr { for resource in self.resources { @@ -849,30 +844,3 @@ impl crate::Queue for Queue { (1_000_000_000.0 / frequency as f64) as f32 } } - -impl From 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!(), - } - } -} diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs new file mode 100644 index 0000000000..9262d0b579 --- /dev/null +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -0,0 +1,252 @@ +use std::ptr; + +pub(super) use shader::{compile_dxc, get_dxc_container, DxcContainer}; +use winapi::um::d3dcompiler; + +use crate::auxil::dxgi::result::HResult; + +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, + log::Level, +) { + 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, + ) + } + } +} + +#[cfg(feature = "dxc_shader_compiler")] +mod shader { + 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, + dxil_path: Option, + ) -> Result, crate::DeviceError> { + // Make sure that dxil.dll exists. + let _ = 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: &String, + source_name: &str, + raw_ep: &String, + stage_bit: wgt::ShaderStages, + full_stage: String, + dxc_container: &DxcContainer, + ) -> ( + Result, + log::Level, + ) { + 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), + }; + + let compiled = dxc_container.compiler.compile( + &blob, + source_name, + raw_ep, + &full_stage, + &compile_flags, + None, // TODO: idk what the include handler does + &[], + ); + + 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 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!(), + } + } + } +} + +// Stub in case the feature is not enabled +#[cfg(not(feature = "dxc_shader_compiler"))] +mod shader { + use std::path::PathBuf; + + pub(crate) struct DxcContainer {} + + pub(crate) fn get_dxc_container( + _dxc_path: Option, + _dxil_path: Option, + ) -> Result, crate::DeviceError> { + 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) + } + + pub(crate) fn compile_dxc( + device: &crate::dx12::Device, + source: &String, + source_name: &str, + raw_ep: &String, + stage_bit: wgt::ShaderStages, + full_stage: String, + _dxc_container: &DxcContainer, + ) -> ( + Result, + log::Level, + ) { + // This should never be called unless something goes really wrong. + log::warn!("Attempted to compile shader with DXC, but the DXC feature is disabled. Enable the `dxc_shader_compiler` feature on wgpu_hal to use DXC. Falling back to FXC."); + super::compile_fxc( + device, + source, + source_name, + &std::ffi::CString::new(raw_ep.as_str()).unwrap(), + stage_bit, + full_stage, + ) + } +} From e4e66229ce71cec2d71c4d35fa6285dba8aec03e Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Wed, 11 Jan 2023 18:03:29 -0500 Subject: [PATCH 14/32] clippy --- wgpu-hal/src/dx12/instance.rs | 4 ++-- wgpu-hal/src/dx12/shader_compilation.rs | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 1f3c7074f3..2714395fd7 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -57,8 +57,8 @@ impl crate::Instance for super::Instance { } } - let dx12_shader_compiler = match &desc.dx12_shader_compiler { - Some(compiler_option) => compiler_option.clone(), + let dx12_shader_compiler = match desc.dx12_shader_compiler { + Some(ref compiler_option) => compiler_option.clone(), None => wgt::Dx12Compiler::default(), }; diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 9262d0b579..b71ac9c8f2 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -87,7 +87,7 @@ mod shader { dxil_path: Option, ) -> Result, crate::DeviceError> { // Make sure that dxil.dll exists. - let _ = match hassle_rs::Dxil::new(dxil_path) { + match hassle_rs::Dxil::new(dxil_path) { Ok(_) => (), Err(e) => { log::warn!("Failed to load dxil.dll. Defaulting to Fxc instead: {}", e); @@ -117,9 +117,9 @@ mod shader { pub(crate) fn compile_dxc( device: &crate::dx12::Device, - source: &String, + source: &str, source_name: &str, - raw_ep: &String, + raw_ep: &str, stage_bit: wgt::ShaderStages, full_stage: String, dxc_container: &DxcContainer, @@ -140,7 +140,7 @@ mod shader { let blob = match dxc_container .library - .create_blob_with_encoding_from_str(&source) + .create_blob_with_encoding_from_str(source) .map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("DXC blob error: {}", e))) { Ok(blob) => blob, @@ -228,9 +228,9 @@ mod shader { pub(crate) fn compile_dxc( device: &crate::dx12::Device, - source: &String, + source: &str, source_name: &str, - raw_ep: &String, + raw_ep: &str, stage_bit: wgt::ShaderStages, full_stage: String, _dxc_container: &DxcContainer, @@ -242,9 +242,9 @@ mod shader { log::warn!("Attempted to compile shader with DXC, but the DXC feature is disabled. Enable the `dxc_shader_compiler` feature on wgpu_hal to use DXC. Falling back to FXC."); super::compile_fxc( device, - source, + &source.to_string(), source_name, - &std::ffi::CString::new(raw_ep.as_str()).unwrap(), + &std::ffi::CString::new(raw_ep).unwrap(), stage_bit, full_stage, ) From 124f2bdd8ce753eddaf110c0f04495ff450ed16f Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 01:44:05 -0500 Subject: [PATCH 15/32] docs and minor cleanup --- wgpu-hal/src/dx12/device.rs | 10 ++++------ wgpu-hal/src/dx12/shader_compilation.rs | 14 +++++++++++--- wgpu-types/src/lib.rs | 12 +++++++++++- wgpu/src/util/init.rs | 7 +++++-- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 4e6883cc20..7fe619da1a 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -243,7 +243,7 @@ impl super::Device { // Compile with DXC if available, otherwise fall back to FXC let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { profiling::scope!("wgpu::backend::directx12::compile_dxc"); - crate::dx12::shader_compilation::compile_dxc( + super::shader_compilation::compile_dxc( self, &source, source_name, @@ -254,7 +254,7 @@ impl super::Device { ) } else { profiling::scope!("wgpu::backend::directx12::compile_fxc"); - crate::dx12::shader_compilation::compile_fxc( + super::shader_compilation::compile_fxc( self, &source, source_name, @@ -1474,10 +1474,8 @@ impl crate::Device for super::Device { self.raw.create_compute_pipeline_state( desc.layout.shared.signature, match blob_cs { - crate::dx12::CompiledShader::Dxc(ref blob_cs) => { - native::Shader::from_raw(blob_cs) - } - crate::dx12::CompiledShader::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), + super::CompiledShader::Dxc(ref blob_cs) => native::Shader::from_raw(blob_cs), + super::CompiledShader::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), }, 0, native::CachedPSO::null(), diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index b71ac9c8f2..700438432d 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -5,6 +5,12 @@ 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, @@ -71,6 +77,7 @@ pub(super) fn compile_fxc( } } +// 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 shader { use std::path::PathBuf; @@ -211,7 +218,7 @@ mod shader { } } -// Stub in case the feature is not enabled +// These are stubs for when the `dxc_shader_compiler` feature is disabled. #[cfg(not(feature = "dxc_shader_compiler"))] mod shader { use std::path::PathBuf; @@ -222,10 +229,12 @@ mod shader { _dxc_path: Option, _dxil_path: Option, ) -> Result, 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, but just in case... pub(crate) fn compile_dxc( device: &crate::dx12::Device, source: &str, @@ -238,8 +247,7 @@ mod shader { Result, log::Level, ) { - // This should never be called unless something goes really wrong. - log::warn!("Attempted to compile shader with DXC, but the DXC feature is disabled. Enable the `dxc_shader_compiler` feature on wgpu_hal to use DXC. Falling back to FXC."); + log::error!("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. Falling back to FXC."); super::compile_fxc( device, &source.to_string(), diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 9156ecda91..803872cdfb 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5295,12 +5295,18 @@ impl Default for ShaderBoundChecks { } } -// TODO: What happens if the user selects dxc, but the dxc feature is disabled? +/// Selects which DX12 shader compiler to use. #[derive(Clone, Debug)] 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. Fxc, + /// The Dxc compiler is new, fast and maintained. However, it requires both `dxcompiler.dll` and `dxil.dll` + /// to be shipped with the application. Dxc { + /// Path to the `dxcompiler.dll` file. Passing `None` will check the local scope for the file. dxil_path: Option, + /// Path to the `dxil.dll` file. Passing `None` will check the local scope for the file. dxc_path: Option, }, } @@ -5311,8 +5317,11 @@ impl Default for Dx12Compiler { } } +/// Options for creating an instance. pub struct InstanceOptions { + /// Which `Backends` to enable. pub backends: Backends, + /// Which DX12 shader compiler to use. pub dx12_shader_compiler: Dx12Compiler, } @@ -5326,6 +5335,7 @@ impl Default for InstanceOptions { } impl InstanceOptions { + /// Creates a new `InstanceOptions` with the given `Backends` and `Dx12Compiler`. pub fn new(backends: Backends, dx12_shader_compiler: Dx12Compiler) -> Self { Self { backends, diff --git a/wgpu/src/util/init.rs b/wgpu/src/util/init.rs index 06dddc7859..7afbf71497 100644 --- a/wgpu/src/util/init.rs +++ b/wgpu/src/util/init.rs @@ -95,9 +95,12 @@ pub fn dx12_shader_compiler_from_env() -> Option { .map(str::to_lowercase) .as_deref() { - Ok("dxc") => wgt::Dx12Compiler::Dxc { dxil_path: None, dxc_path: None }, + Ok("dxc") => wgt::Dx12Compiler::Dxc { + dxil_path: None, + dxc_path: None, + }, Ok("fxc") => wgt::Dx12Compiler::Fxc, _ => return None, }, ) -} \ No newline at end of file +} From 84584e217d6b6cb4c5bc1a0bd4d9a58f500b1f81 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 01:51:54 -0500 Subject: [PATCH 16/32] use InstanceOptions instead of Backends for web init --- wgpu/src/backend/web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 8b55f4fc6b..43c1e86ae4 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -764,7 +764,7 @@ impl crate::context::Context for Context { type PopErrorScopeFuture = MakeSendFuture Option>; - fn init(_backends: wgt::Backends) -> Self { + fn init(_instance_options: wgt::InstanceOptions) -> Self { let global: Global = js_sys::global().unchecked_into(); let gpu = if !global.window().is_undefined() { global.unchecked_into::().navigator().gpu() From 50d8479018f4c568702d71dada442655b43a26ec Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 01:58:13 -0500 Subject: [PATCH 17/32] unwrap_or_default() --- wgpu/examples/framework.rs | 2 +- wgpu/tests/common/mod.rs | 2 +- wgpu/tests/instance.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index f10f13ef1b..dc08b2d6b0 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -159,7 +159,7 @@ async fn setup(title: &str) -> Setup { let backend = 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(wgpu::Dx12Compiler::default()); + wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); let instance = wgpu::Instance::new(wgpu::InstanceOptions::new(backend, dx12_shader_compiler)); let (size, surface) = unsafe { diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 7868688756..562f0e30ad 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -333,7 +333,7 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te fn initialize_adapter() -> (Adapter, SurfaceGuard) { let backend_bits = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all); let dx12_shader_compiler = - wgpu::util::dx12_shader_compiler_from_env().unwrap_or(wgpu::Dx12Compiler::default()); + wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); let instance = Instance::new(wgpu::InstanceOptions::new( backend_bits, dx12_shader_compiler, diff --git a/wgpu/tests/instance.rs b/wgpu/tests/instance.rs index 4a8b4e1b94..60d0971516 100644 --- a/wgpu/tests/instance.rs +++ b/wgpu/tests/instance.rs @@ -5,7 +5,7 @@ use wasm_bindgen_test::*; fn initialize() { let _ = wgpu::Instance::new(wgpu::InstanceOptions::new( wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), - wgpu::util::dx12_shader_compiler_from_env().unwrap_or(wgpu::Dx12Compiler::default()), + wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(), )); } From 1313757c437bb83f8ba3d0836d050337b1f24764 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 02:05:11 -0500 Subject: [PATCH 18/32] fmt --- wgpu/examples/framework.rs | 3 +-- wgpu/tests/common/mod.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index dc08b2d6b0..c84c80a2da 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -158,8 +158,7 @@ async fn setup(title: &str) -> Setup { log::info!("Initializing the surface..."); let backend = 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 dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); let instance = wgpu::Instance::new(wgpu::InstanceOptions::new(backend, dx12_shader_compiler)); let (size, surface) = unsafe { diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 562f0e30ad..10f3ca6524 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -332,8 +332,7 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te fn initialize_adapter() -> (Adapter, SurfaceGuard) { let backend_bits = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all); - let dx12_shader_compiler = - wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); + let dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); let instance = Instance::new(wgpu::InstanceOptions::new( backend_bits, dx12_shader_compiler, From 21f04c8aa26c82c03ff5ec526b0c3b6854ef5ed0 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 02:14:21 -0500 Subject: [PATCH 19/32] Link to where to download the .dlls from Microsoft --- wgpu-types/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 803872cdfb..a613ea866c 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5302,7 +5302,7 @@ pub enum Dx12Compiler { /// any additional .dlls to be shipped with the application. Fxc, /// The Dxc compiler is new, fast and maintained. However, it requires both `dxcompiler.dll` and `dxil.dll` - /// to be shipped with the application. + /// 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 check the local scope for the file. dxil_path: Option, From 1fde6fcee945baa7587e3feba5ebfdd1b98cdfcb Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 02:20:38 -0500 Subject: [PATCH 20/32] derive default for enum --- wgpu-types/src/lib.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index a613ea866c..fcfea32665 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5296,10 +5296,11 @@ impl Default for ShaderBoundChecks { } /// Selects which DX12 shader compiler to use. -#[derive(Clone, Debug)] +#[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 @@ -5311,12 +5312,6 @@ pub enum Dx12Compiler { }, } -impl Default for Dx12Compiler { - fn default() -> Self { - Self::Fxc - } -} - /// Options for creating an instance. pub struct InstanceOptions { /// Which `Backends` to enable. From 7034749942025193b806614e246b78f6db649620 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 02:30:53 -0500 Subject: [PATCH 21/32] more docs --- wgpu-types/src/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index fcfea32665..0bae176335 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5296,14 +5296,22 @@ impl Default for ShaderBoundChecks { } /// Selects which DX12 shader compiler to use. +/// If the `wgpu-hal/dx12-shader-compiler` isn't enabled, +/// then this will fall back to the Fxc compiler at runtime and log an error. +/// If the `Dxc` option is selected, but the `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 + /// 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 check the local scope for the file. dxil_path: Option, From c2e43f2684f287b7d3d485ef2e9cc471a208f400 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 02:53:29 -0500 Subject: [PATCH 22/32] changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba0e7d3cf5..9cbf7a9417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,10 +107,15 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non `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 `InstanceOptions` 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) + ### Changes #### General +- `Instance` creation now takes an `InstanceOptions` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use. By @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356) - Convert all `Default` Implementations on Enums to `derive(Default)` - Implement `Default` for `CompositeAlphaMode` - Improve compute shader validation error message. By @haraldreingruber in [#3139](https://github.com/gfx-rs/wgpu/pull/3139) From 11835acda85962c8b318838c9d9ae6b2b32dcd72 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 16:32:50 -0500 Subject: [PATCH 23/32] changelog --- CHANGELOG.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cbf7a9417..50f5bf7fb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,6 +103,37 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non `Instance::create_surface()` now returns `Result` 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 `InstanceOptions` instead of `Backends` + +`Instance::new()` and `hub::Global::new()` now take an `InstanceOptions` 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(wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)); +``` + +```diff +- let global = wgc::hub::Global::new( +- "player", +- IdentityPassThroughFactory, +- wgt::Backends::all(), +- ); ++ let global = wgc::hub::Global::new( ++ "player", ++ IdentityPassThroughFactory, ++ wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc), ++ ); +``` + +`Instance` now also also implements `Default`, which is equivalent to `wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)` + +```diff +- let instance = Instance::new(wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)); ++ let instance = Instance::default(); +``` + +By @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356) + #### 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) @@ -115,7 +146,6 @@ You can now choose to use the DXC compiler for DX12 instead of FXC. The DXC comp #### General -- `Instance` creation now takes an `InstanceOptions` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use. By @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356) - Convert all `Default` Implementations on Enums to `derive(Default)` - Implement `Default` for `CompositeAlphaMode` - Improve compute shader validation error message. By @haraldreingruber in [#3139](https://github.com/gfx-rs/wgpu/pull/3139) From ecf46bca15ddde782bc9b67137dfd6947b413875 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 16:57:27 -0500 Subject: [PATCH 24/32] misc cleanup --- player/src/bin/play.rs | 2 +- wgpu-hal/src/dx12/adapter.rs | 2 +- wgpu-hal/src/dx12/shader_compilation.rs | 5 +++-- wgpu-info/src/main.rs | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index 8a3f722818..b2e403f9c0 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -46,7 +46,7 @@ fn main() { let global = wgc::hub::Global::new( "player", IdentityPassThroughFactory, - wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc), + wgt::InstanceOptions::default(), ); let mut command_buffer_id_manager = wgc::hub::IdentityManager::default(); diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index d697bbbfdc..a3136b55d6 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -354,7 +354,7 @@ impl crate::Adapter for super::Adapter { queue, self.private_caps, &self.library, - self.dx12_shader_compiler.clone(), // TODO: Don't clone this + self.dx12_shader_compiler.clone(), )?; Ok(crate::OpenDevice { device, diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 700438432d..27d45bf026 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -141,8 +141,8 @@ mod shader { .instance_flags .contains(crate::InstanceFlags::DEBUG) { - compile_flags.push("-Zi"); /* d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION */ - compile_flags.push("-Od"); /* d3dcompiler::D3DCOMPILE_DEBUG */ + compile_flags.push("-Zi"); // d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION + compile_flags.push("-Od"); // d3dcompiler::D3DCOMPILE_DEBUG } let blob = match dxc_container @@ -154,6 +154,7 @@ mod shader { 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, diff --git a/wgpu-info/src/main.rs b/wgpu-info/src/main.rs index d8a2fe64ca..723d137df3 100644 --- a/wgpu-info/src/main.rs +++ b/wgpu-info/src/main.rs @@ -281,7 +281,7 @@ mod inner { env_logger::init(); let args: Vec<_> = std::env::args().skip(1).collect(); - let instance = wgpu::Instance::new(wgpu::InstanceOptions::default()); + let instance = wgpu::Instance::default(); let adapters: Vec<_> = instance.enumerate_adapters(wgpu::Backends::all()).collect(); let adapter_count = adapters.len(); From 458eb8ff57ddd48c75298b3e5b54f22faa2cce0b Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Thu, 12 Jan 2023 17:01:05 -0500 Subject: [PATCH 25/32] Replace compile_dxc stub fallback with unimplemented!() as it is definitely an error. --- wgpu-hal/src/dx12/shader_compilation.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 27d45bf026..88a35a3401 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -235,27 +235,19 @@ mod shader { Ok(None) } - // It shouldn't be possible that this gets called with the `dxc_shader_compiler` feature disabled, but just in case... + // 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, + _device: &crate::dx12::Device, + _source: &str, + _source_name: &str, + _raw_ep: &str, + _stage_bit: wgt::ShaderStages, + _full_stage: String, _dxc_container: &DxcContainer, ) -> ( Result, log::Level, ) { - log::error!("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. Falling back to FXC."); - super::compile_fxc( - device, - &source.to_string(), - source_name, - &std::ffi::CString::new(raw_ep).unwrap(), - stage_bit, - full_stage, - ) + 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."); } } From 6d01198ec23b0a3058b49a94e8bc9d8e74bfc35b Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 01:32:43 -0500 Subject: [PATCH 26/32] document `WGPU_DX12_COMPILER` in the readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6cc44d0184..fb725d0604 100644 --- a/README.md +++ b/README.md @@ -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_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_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`. From 879adb891e7c8326b616ea0e78d3357f81aa928f Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 01:33:28 -0500 Subject: [PATCH 27/32] move shader compilation profiling to the functions where it happens --- wgpu-hal/src/dx12/device.rs | 2 -- wgpu-hal/src/dx12/shader_compilation.rs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 7fe619da1a..4294136c83 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -242,7 +242,6 @@ impl super::Device { // Compile with DXC if available, otherwise fall back to FXC let (result, log_level) = if let Some(ref dxc_container) = self.dxc_container { - profiling::scope!("wgpu::backend::directx12::compile_dxc"); super::shader_compilation::compile_dxc( self, &source, @@ -253,7 +252,6 @@ impl super::Device { dxc_container, ) } else { - profiling::scope!("wgpu::backend::directx12::compile_fxc"); super::shader_compilation::compile_fxc( self, &source, diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 88a35a3401..5d0d210813 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -22,6 +22,7 @@ pub(super) fn compile_fxc( Result, log::Level, ) { + profiling::scope!("compile_fxc"); let mut shader_data = native::Blob::null(); let mut compile_flags = d3dcompiler::D3DCOMPILE_ENABLE_STRICTNESS; if device @@ -134,6 +135,7 @@ mod shader { Result, 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 From dbc1dc959cf0b17d4b5313e92b1b6b52d20972d7 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 01:40:14 -0500 Subject: [PATCH 28/32] add CompiledShader helpers --- wgpu-hal/src/dx12/device.rs | 28 ++++++++-------------------- wgpu-hal/src/dx12/mod.rs | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/wgpu-hal/src/dx12/device.rs b/wgpu-hal/src/dx12/device.rs index 4294136c83..fb2c3f92fc 100644 --- a/wgpu-hal/src/dx12/device.rs +++ b/wgpu-hal/src/dx12/device.rs @@ -1356,13 +1356,9 @@ impl crate::Device for super::Device { let raw_desc = d3d12::D3D12_GRAPHICS_PIPELINE_STATE_DESC { pRootSignature: desc.layout.shared.signature.as_mut_ptr(), - VS: match blob_vs { - super::CompiledShader::Dxc(ref blob_vs) => *native::Shader::from_raw(blob_vs), - super::CompiledShader::Fxc(blob_vs) => *native::Shader::from_blob(blob_vs), - }, + VS: *blob_vs.create_native_shader(), PS: match blob_fs { - Some(super::CompiledShader::Dxc(ref blob_fs)) => *native::Shader::from_raw(blob_fs), - Some(super::CompiledShader::Fxc(blob_fs)) => *native::Shader::from_blob(blob_fs), + Some(ref shader) => *shader.create_native_shader(), None => *native::Shader::null(), }, GS: *native::Shader::null(), @@ -1434,13 +1430,10 @@ impl crate::Device for super::Device { } }; - if let super::CompiledShader::Fxc(ref vs_fxc) = blob_vs { - unsafe { vs_fxc.destroy() }; - } - - if let Some(super::CompiledShader::Fxc(ref fs_fxc)) = blob_fs { - unsafe { fs_fxc.destroy() }; - } + unsafe { blob_vs.destroy() }; + if let Some(blob_fs) = blob_fs { + unsafe { blob_fs.destroy() }; + }; hr.into_result() .map_err(|err| crate::PipelineError::Linkage(shader_stages, err.into_owned()))?; @@ -1471,19 +1464,14 @@ impl crate::Device for super::Device { profiling::scope!("ID3D12Device::CreateComputePipelineState"); self.raw.create_compute_pipeline_state( desc.layout.shared.signature, - match blob_cs { - super::CompiledShader::Dxc(ref blob_cs) => native::Shader::from_raw(blob_cs), - super::CompiledShader::Fxc(blob_cs) => native::Shader::from_blob(blob_cs), - }, + blob_cs.create_native_shader(), 0, native::CachedPSO::null(), native::PipelineStateFlags::empty(), ) }; - if let super::CompiledShader::Fxc(cs_fxc) = blob_cs { - unsafe { cs_fxc.destroy() }; - } + unsafe { blob_cs.destroy() }; let raw = pair.into_result().map_err(|err| { crate::PipelineError::Linkage(wgt::ShaderStages::COMPUTE, err.into_owned()) diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 1e58a2be4e..34db1ed5b6 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -547,6 +547,24 @@ pub(super) enum CompiledShader { 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 { raw: native::PipelineState, layout: PipelineLayoutShared, From b90908f1f9bab3ff6b612ad60ba05cc7702bddf0 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 01:41:28 -0500 Subject: [PATCH 29/32] rename `shader` mod to `dxc` --- wgpu-hal/src/dx12/shader_compilation.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 5d0d210813..368efb068a 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -1,6 +1,6 @@ use std::ptr; -pub(super) use shader::{compile_dxc, get_dxc_container, DxcContainer}; +pub(super) use dxc::{compile_dxc, get_dxc_container, DxcContainer}; use winapi::um::d3dcompiler; use crate::auxil::dxgi::result::HResult; @@ -80,7 +80,7 @@ pub(super) fn compile_fxc( // 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 shader { +mod dxc { use std::path::PathBuf; pub(crate) struct DxcContainer { @@ -223,7 +223,7 @@ mod shader { // These are stubs for when the `dxc_shader_compiler` feature is disabled. #[cfg(not(feature = "dxc_shader_compiler"))] -mod shader { +mod dxc { use std::path::PathBuf; pub(crate) struct DxcContainer {} From 221db56d0e50f651dbbe40f1ef90298d7edb51e8 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 02:11:35 -0500 Subject: [PATCH 30/32] remove InstanceOptions::new(...) in favour of using the struct --- CHANGELOG.md | 19 ++++++++++++++----- deno_webgpu/src/lib.rs | 5 ++++- player/tests/test.rs | 5 ++++- wgpu-types/src/lib.rs | 10 ---------- wgpu/examples/capture/main.rs | 10 +++++----- wgpu/examples/framework.rs | 9 ++++++--- wgpu/tests/common/mod.rs | 10 +++++----- wgpu/tests/instance.rs | 16 ++++++++-------- 8 files changed, 46 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50f5bf7fb5..4452ec2285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -109,26 +109,35 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non ```diff - let instance = Instance::new(wgpu::Backends::all()); -+ let instance = Instance::new(wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)); ++ let instance = Instance::new(wgpu::InstanceOptions { ++ backends: wgpu::Backends::all(), ++ dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, ++ }); ``` ```diff - let global = wgc::hub::Global::new( - "player", - IdentityPassThroughFactory, -- wgt::Backends::all(), +- wgpu::Backends::all(), - ); + let global = wgc::hub::Global::new( + "player", + IdentityPassThroughFactory, -+ wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc), ++ wgpu::InstanceOptions { ++ backends: wgpu::Backends::all(), ++ dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, ++ }, + ); ``` -`Instance` now also also implements `Default`, which is equivalent to `wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)` +`Instance` now also also implements `Default`, which uses `wgpu::Backends::all()` and `wgpu::Dx12Compiler::Fxc` for `InstanceOptions` ```diff -- let instance = Instance::new(wgt::InstanceOptions::new(wgt::Backends::all(), wgt::Dx12Compiler::Fxc)); +- let instance = Instance::new(wgpu::InstanceOptions { +- backends: wgpu::Backends::all(), +- dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, +- }); + let instance = Instance::default(); ``` diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 66e93129b9..058764a757 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -240,7 +240,10 @@ pub async fn op_webgpu_request_adapter( state.put(wgpu_core::hub::Global::new( "webgpu", wgpu_core::hub::IdentityManagerFactory, - wgpu_types::InstanceOptions::new(backends, wgpu_types::Dx12Compiler::Fxc), + wgpu_types::InstanceOptions { + backends, + dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc, + }, )); state.borrow::() }; diff --git a/player/tests/test.rs b/player/tests/test.rs index 4ab1086676..ceb6a56d87 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -181,7 +181,10 @@ impl Corpus { let global = wgc::hub::Global::new( "test", IdentityPassThroughFactory, - wgt::InstanceOptions::new(corpus.backends, wgt::Dx12Compiler::Fxc), + wgt::InstanceOptions { + backends: corpus.backends, + dx12_shader_compiler: wgt::Dx12Compiler::Fxc, + }, ); for &backend in BACKENDS { if !corpus.backends.contains(backend.into()) { diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 0bae176335..213ba737ac 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5336,13 +5336,3 @@ impl Default for InstanceOptions { } } } - -impl InstanceOptions { - /// Creates a new `InstanceOptions` with the given `Backends` and `Dx12Compiler`. - pub fn new(backends: Backends, dx12_shader_compiler: Dx12Compiler) -> Self { - Self { - backends, - dx12_shader_compiler, - } - } -} diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 8487376911..4dec73bd84 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -36,11 +36,11 @@ async fn create_red_image_with_dimensions( width: usize, height: usize, ) -> (Device, Buffer, BufferDimensions, SubmissionIndex) { - let backend = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); - let instance = wgpu::Instance::new(wgpu::InstanceOptions::new( - backend, - wgpu::Dx12Compiler::default(), - )); + let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); + let instance = wgpu::Instance::new(wgpu::InstanceOptions { + backends, + dx12_shader_compiler: wgpu::Dx12Compiler::default(), + }); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions::default()) .await diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index c84c80a2da..bcc7582062 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -157,10 +157,13 @@ async fn setup(title: &str) -> Setup { 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(wgpu::InstanceOptions::new(backend, dx12_shader_compiler)); + let instance = wgpu::Instance::new(wgpu::InstanceOptions { + backends, + dx12_shader_compiler, + }); let (size, surface) = unsafe { let size = window.inner_size(); @@ -181,7 +184,7 @@ async fn setup(title: &str) -> Setup { (size, surface) }; 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 .expect("No suitable GPU adapters found on the system!"); diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index 10f3ca6524..d2b058b265 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -331,12 +331,12 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te } 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 dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); - let instance = Instance::new(wgpu::InstanceOptions::new( - backend_bits, + let instance = Instance::new(wgpu::InstanceOptions { + backends, dx12_shader_compiler, - )); + }); let surface_guard; let compatible_surface; @@ -362,7 +362,7 @@ fn initialize_adapter() -> (Adapter, SurfaceGuard) { let compatible_surface: Option<&Surface> = compatible_surface.as_ref(); let adapter = pollster::block_on(wgpu::util::initialize_adapter_from_env_or_default( &instance, - backend_bits, + backends, compatible_surface, )) .expect("could not find suitable adapter on the system"); diff --git a/wgpu/tests/instance.rs b/wgpu/tests/instance.rs index 60d0971516..3894d16bc4 100644 --- a/wgpu/tests/instance.rs +++ b/wgpu/tests/instance.rs @@ -3,17 +3,17 @@ use wasm_bindgen_test::*; #[test] #[wasm_bindgen_test] fn initialize() { - let _ = wgpu::Instance::new(wgpu::InstanceOptions::new( - wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), - wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(), - )); + let _ = wgpu::Instance::new(wgpu::InstanceOptions { + 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) { - let instance = wgpu::Instance::new(wgpu::InstanceOptions::new( - wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all), - wgpu::Dx12Compiler::default(), - )); + let instance = wgpu::Instance::new(wgpu::InstanceOptions { + 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 { power_preference: power, From 37e60b4f245673ca73e96ee24e340f04893877f9 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Fri, 13 Jan 2023 02:24:32 -0500 Subject: [PATCH 31/32] misc cleanup --- wgpu-hal/src/dx12/shader_compilation.rs | 2 +- wgpu-types/src/lib.rs | 23 ++++++++++++++--------- wgpu/src/lib.rs | 1 + wgpu/src/util/init.rs | 4 +++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/wgpu-hal/src/dx12/shader_compilation.rs b/wgpu-hal/src/dx12/shader_compilation.rs index 368efb068a..bc81d10fd0 100644 --- a/wgpu-hal/src/dx12/shader_compilation.rs +++ b/wgpu-hal/src/dx12/shader_compilation.rs @@ -163,7 +163,7 @@ mod dxc { raw_ep, &full_stage, &compile_flags, - None, // TODO: idk what the include handler does + None, &[], ); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 213ba737ac..64eb1a98c8 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5296,26 +5296,31 @@ impl Default for ShaderBoundChecks { } /// Selects which DX12 shader compiler to use. -/// If the `wgpu-hal/dx12-shader-compiler` isn't enabled, -/// then this will fall back to the Fxc compiler at runtime and log an error. -/// If the `Dxc` option is selected, but the `dxcompiler.dll` and `dxil.dll` files aren't found, +/// +/// 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. +/// 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. + /// 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 check the local scope for the file. + /// Path to the `dxcompiler.dll` file. Passing `None` will use standard platform specific dll loading rules. dxil_path: Option, - /// Path to the `dxil.dll` file. Passing `None` will check the local scope for the file. + /// Path to the `dxil.dll` file. Passing `None` will use standard platform specific dll loading rules. dxc_path: Option, }, } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 9404f5b2c7..4ac40e173f 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1279,6 +1279,7 @@ 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(InstanceOptions::default()) diff --git a/wgpu/src/util/init.rs b/wgpu/src/util/init.rs index 7afbf71497..d5c7c6ad47 100644 --- a/wgpu/src/util/init.rs +++ b/wgpu/src/util/init.rs @@ -87,7 +87,9 @@ pub async fn initialize_adapter_from_env_or_default( } } -/// Choose which DX12 shader compiler to use from the environment variable WGPU_DX12_COMPILER +/// 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 { Some( match std::env::var("WGPU_DX12_COMPILER") From 84f19c2c420c6afd2f1aaa829e113ec195ba8595 Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Mon, 16 Jan 2023 17:57:25 -0500 Subject: [PATCH 32/32] rename InstanceOptions to InstanceDescriptor, dx12_shader_compiler is no longer Optional in hal --- CHANGELOG.md | 14 +++++++------- deno_webgpu/src/lib.rs | 2 +- player/src/bin/play.rs | 2 +- player/tests/test.rs | 2 +- wgpu-core/src/hub.rs | 4 ++-- wgpu-core/src/instance.rs | 26 +++++++++----------------- wgpu-hal/examples/halmark/main.rs | 3 ++- wgpu-hal/src/dx12/instance.rs | 7 +------ wgpu-hal/src/lib.rs | 2 +- wgpu-types/src/lib.rs | 4 ++-- wgpu/examples/capture/main.rs | 2 +- wgpu/examples/framework.rs | 2 +- wgpu/src/backend/direct.rs | 4 ++-- wgpu/src/backend/web.rs | 2 +- wgpu/src/context.rs | 2 +- wgpu/src/lib.rs | 12 ++++++------ wgpu/tests/common/mod.rs | 2 +- wgpu/tests/instance.rs | 4 ++-- 18 files changed, 42 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4452ec2285..0744ec482e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -103,13 +103,13 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non `Instance::create_surface()` now returns `Result` 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 `InstanceOptions` instead of `Backends` +#### Instance creation now takes `InstanceDescriptor` instead of `Backends` -`Instance::new()` and `hub::Global::new()` now take an `InstanceOptions` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use. +`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::InstanceOptions { ++ let instance = Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, + }); @@ -124,17 +124,17 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non + let global = wgc::hub::Global::new( + "player", + IdentityPassThroughFactory, -+ wgpu::InstanceOptions { ++ 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 `InstanceOptions` +`Instance` now also also implements `Default`, which uses `wgpu::Backends::all()` and `wgpu::Dx12Compiler::Fxc` for `InstanceDescriptor` ```diff -- let instance = Instance::new(wgpu::InstanceOptions { +- let instance = Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::all(), - dx12_shader_compiler: wgpu::Dx12Compiler::Fxc, - }); @@ -149,7 +149,7 @@ By @Elabajaba in [#3356](https://github.com/gfx-rs/wgpu/pull/3356) #### 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 `InstanceOptions` 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) +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) ### Changes diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 058764a757..95fe5d5bae 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -240,7 +240,7 @@ pub async fn op_webgpu_request_adapter( state.put(wgpu_core::hub::Global::new( "webgpu", wgpu_core::hub::IdentityManagerFactory, - wgpu_types::InstanceOptions { + wgpu_types::InstanceDescriptor { backends, dx12_shader_compiler: wgpu_types::Dx12Compiler::Fxc, }, diff --git a/player/src/bin/play.rs b/player/src/bin/play.rs index b2e403f9c0..fb2665e3a3 100644 --- a/player/src/bin/play.rs +++ b/player/src/bin/play.rs @@ -46,7 +46,7 @@ fn main() { let global = wgc::hub::Global::new( "player", IdentityPassThroughFactory, - wgt::InstanceOptions::default(), + wgt::InstanceDescriptor::default(), ); let mut command_buffer_id_manager = wgc::hub::IdentityManager::default(); diff --git a/player/tests/test.rs b/player/tests/test.rs index ceb6a56d87..750b823648 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -181,7 +181,7 @@ impl Corpus { let global = wgc::hub::Global::new( "test", IdentityPassThroughFactory, - wgt::InstanceOptions { + wgt::InstanceDescriptor { backends: corpus.backends, dx12_shader_compiler: wgt::Dx12Compiler::Fxc, }, diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 5fa4cace4b..17748b5773 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -1108,10 +1108,10 @@ pub struct Global { } impl Global { - pub fn new(name: &str, factory: G, instance_options: wgt::InstanceOptions) -> Self { + pub fn new(name: &str, factory: G, instance_desc: wgt::InstanceDescriptor) -> Self { profiling::scope!("Global::new"); Self { - instance: Instance::new(name, instance_options), + instance: Instance::new(name, instance_desc), surfaces: Registry::without_backend(&factory, "Surface"), hubs: Hubs::new(&factory), } diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index e9c530563c..d8ecd49056 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -67,13 +67,9 @@ pub struct Instance { } impl Instance { - pub fn new(name: &str, instance_options: wgt::InstanceOptions) -> Self { - fn init( - _: A, - mask: Backends, - dx12_shader_compiler: Option, - ) -> Option { - if mask.contains(A::VARIANT.into()) { + pub fn new(name: &str, instance_desc: wgt::InstanceDescriptor) -> Self { + fn init(_: A, instance_desc: &wgt::InstanceDescriptor) -> Option { + if instance_desc.backends.contains(A::VARIANT.into()) { let mut flags = hal::InstanceFlags::empty(); if cfg!(debug_assertions) { flags |= hal::InstanceFlags::VALIDATION; @@ -82,7 +78,7 @@ impl Instance { let hal_desc = hal::InstanceDescriptor { name: "wgpu", flags, - dx12_shader_compiler, + dx12_shader_compiler: instance_desc.dx12_shader_compiler.clone(), }; unsafe { hal::Instance::init(&hal_desc).ok() } } else { @@ -93,19 +89,15 @@ impl Instance { Self { name: name.to_string(), #[cfg(feature = "vulkan")] - vulkan: init(hal::api::Vulkan, instance_options.backends, None), + vulkan: init(hal::api::Vulkan, &instance_desc), #[cfg(feature = "metal")] - metal: init(hal::api::Metal, instance_options.backends, None), + metal: init(hal::api::Metal, &instance_desc), #[cfg(feature = "dx12")] - dx12: init( - hal::api::Dx12, - instance_options.backends, - Some(instance_options.dx12_shader_compiler), - ), + dx12: init(hal::api::Dx12, &instance_desc), #[cfg(feature = "dx11")] - dx11: init(hal::api::Dx11, instance_options.backends, None), + dx11: init(hal::api::Dx11, &instance_desc), #[cfg(feature = "gles")] - gl: init(hal::api::Gles, instance_options.backends, None), + gl: init(hal::api::Gles, &instance_desc), } } diff --git a/wgpu-hal/examples/halmark/main.rs b/wgpu-hal/examples/halmark/main.rs index 1e11dc1395..849be37c60 100644 --- a/wgpu-hal/examples/halmark/main.rs +++ b/wgpu-hal/examples/halmark/main.rs @@ -96,7 +96,8 @@ impl Example { } else { hal::InstanceFlags::empty() }, - dx12_shader_compiler: None, + // 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 mut surface = unsafe { diff --git a/wgpu-hal/src/dx12/instance.rs b/wgpu-hal/src/dx12/instance.rs index 2714395fd7..7829c6fe87 100644 --- a/wgpu-hal/src/dx12/instance.rs +++ b/wgpu-hal/src/dx12/instance.rs @@ -57,11 +57,6 @@ impl crate::Instance for super::Instance { } } - let dx12_shader_compiler = match desc.dx12_shader_compiler { - Some(ref compiler_option) => compiler_option.clone(), - None => wgt::Dx12Compiler::default(), - }; - Ok(Self { // The call to create_factory will only succeed if we get a factory4, so this is safe. factory, @@ -69,7 +64,7 @@ impl crate::Instance for super::Instance { _lib_dxgi: lib_dxgi, supports_allow_tearing, flags: desc.flags, - dx12_shader_compiler, + dx12_shader_compiler: desc.dx12_shader_compiler.clone(), }) } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index aa31f4da09..9d5a2b79e4 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -743,7 +743,7 @@ bitflags::bitflags! { pub struct InstanceDescriptor<'a> { pub name: &'a str, pub flags: InstanceFlags, - pub dx12_shader_compiler: Option, + pub dx12_shader_compiler: wgt::Dx12Compiler, } #[derive(Clone, Debug)] diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 64eb1a98c8..2bf27da170 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5326,14 +5326,14 @@ pub enum Dx12Compiler { } /// Options for creating an instance. -pub struct InstanceOptions { +pub struct InstanceDescriptor { /// Which `Backends` to enable. pub backends: Backends, /// Which DX12 shader compiler to use. pub dx12_shader_compiler: Dx12Compiler, } -impl Default for InstanceOptions { +impl Default for InstanceDescriptor { fn default() -> Self { Self { backends: Backends::all(), diff --git a/wgpu/examples/capture/main.rs b/wgpu/examples/capture/main.rs index 4dec73bd84..18a04d60c3 100644 --- a/wgpu/examples/capture/main.rs +++ b/wgpu/examples/capture/main.rs @@ -37,7 +37,7 @@ async fn create_red_image_with_dimensions( height: usize, ) -> (Device, Buffer, BufferDimensions, SubmissionIndex) { let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(wgpu::Backends::all); - let instance = wgpu::Instance::new(wgpu::InstanceOptions { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends, dx12_shader_compiler: wgpu::Dx12Compiler::default(), }); diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index bcc7582062..99b6aeb331 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -160,7 +160,7 @@ async fn setup(title: &str) -> Setup { 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(wgpu::InstanceOptions { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends, dx12_shader_compiler, }); diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index b045a08bd6..ed47dcf0ff 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -516,11 +516,11 @@ impl crate::Context for Context { type PopErrorScopeFuture = Ready>; - fn init(instance_options: wgt::InstanceOptions) -> Self { + fn init(instance_desc: wgt::InstanceDescriptor) -> Self { Self(wgc::hub::Global::new( "wgpu", wgc::hub::IdentityManagerFactory, - instance_options, + instance_desc, )) } diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 43c1e86ae4..bf34d22442 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -764,7 +764,7 @@ impl crate::context::Context for Context { type PopErrorScopeFuture = MakeSendFuture Option>; - fn init(_instance_options: wgt::InstanceOptions) -> Self { + fn init(_instance_desc: wgt::InstanceDescriptor) -> Self { let global: Global = js_sys::global().unchecked_into(); let gpu = if !global.window().is_undefined() { global.unchecked_into::().navigator().gpu() diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index 9b00e50cbe..65dd86abd2 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -97,7 +97,7 @@ pub trait Context: Debug + Send + Sized + Sync { + 'static; type PopErrorScopeFuture: Future> + Send + 'static; - fn init(instance_options: wgt::InstanceOptions) -> Self; + fn init(instance_desc: wgt::InstanceDescriptor) -> Self; fn instance_create_surface( &self, display_handle: raw_window_handle::RawDisplayHandle, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 4ac40e173f..9ef1a74466 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -35,7 +35,7 @@ pub use wgt::{ CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState, DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler, DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, ImageDataLayout, - ImageSubresourceRange, IndexFormat, InstanceOptions, Limits, MultisampleState, Origin3d, + ImageSubresourceRange, IndexFormat, InstanceDescriptor, Limits, MultisampleState, Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference, PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange, QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel, ShaderStages, @@ -1282,7 +1282,7 @@ impl Default for Instance { /// /// Backends are set to `Backends::all()`, and FXC is chosen as the `dx12_shader_compiler`. fn default() -> Self { - Self::new(InstanceOptions::default()) + Self::new(InstanceDescriptor::default()) } } @@ -1291,11 +1291,11 @@ impl Instance { /// /// # Arguments /// - /// - `backends` - Controls from which [backends][Backends] wgpu will choose - /// during instantiation. - pub fn new(instance_options: InstanceOptions) -> Self { + /// - `instance_desc` - Has fields for which [backends][Backends] wgpu will choose + /// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use. + pub fn new(instance_desc: InstanceDescriptor) -> Self { Self { - context: Arc::from(crate::backend::Context::init(instance_options)), + context: Arc::from(crate::backend::Context::init(instance_desc)), } } diff --git a/wgpu/tests/common/mod.rs b/wgpu/tests/common/mod.rs index d2b058b265..1aa54fa0b8 100644 --- a/wgpu/tests/common/mod.rs +++ b/wgpu/tests/common/mod.rs @@ -333,7 +333,7 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te fn initialize_adapter() -> (Adapter, SurfaceGuard) { let backends = wgpu::util::backend_bits_from_env().unwrap_or_else(Backends::all); let dx12_shader_compiler = wgpu::util::dx12_shader_compiler_from_env().unwrap_or_default(); - let instance = Instance::new(wgpu::InstanceOptions { + let instance = Instance::new(wgpu::InstanceDescriptor { backends, dx12_shader_compiler, }); diff --git a/wgpu/tests/instance.rs b/wgpu/tests/instance.rs index 3894d16bc4..e9ff6afff0 100644 --- a/wgpu/tests/instance.rs +++ b/wgpu/tests/instance.rs @@ -3,14 +3,14 @@ use wasm_bindgen_test::*; #[test] #[wasm_bindgen_test] fn initialize() { - let _ = wgpu::Instance::new(wgpu::InstanceOptions { + let _ = wgpu::Instance::new(wgpu::InstanceDescriptor { 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) { - let instance = wgpu::Instance::new(wgpu::InstanceOptions { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { 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(), });