mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Load FXC dynamically to remove the dependency on d3dcompiler_47.dll (#7588)
This commit is contained in:
parent
97794f12a9
commit
d190106c3f
@ -57,7 +57,7 @@ impl super::Adapter {
|
|||||||
library: &Arc<D3D12Lib>,
|
library: &Arc<D3D12Lib>,
|
||||||
instance_flags: wgt::InstanceFlags,
|
instance_flags: wgt::InstanceFlags,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||||
// Create the device so that we can get the capabilities.
|
// Create the device so that we can get the capabilities.
|
||||||
let device = {
|
let device = {
|
||||||
@ -224,8 +224,8 @@ impl super::Adapter {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let shader_model = if let Some(ref dxc_container) = dxc_container {
|
let shader_model = if let Some(max_shader_model) = compiler_container.max_shader_model() {
|
||||||
let max_shader_model = match dxc_container.max_shader_model {
|
let max_shader_model = match max_shader_model {
|
||||||
wgt::DxcShaderModel::V6_0 => Direct3D12::D3D_SHADER_MODEL_6_0,
|
wgt::DxcShaderModel::V6_0 => Direct3D12::D3D_SHADER_MODEL_6_0,
|
||||||
wgt::DxcShaderModel::V6_1 => Direct3D12::D3D_SHADER_MODEL_6_1,
|
wgt::DxcShaderModel::V6_1 => Direct3D12::D3D_SHADER_MODEL_6_1,
|
||||||
wgt::DxcShaderModel::V6_2 => Direct3D12::D3D_SHADER_MODEL_6_2,
|
wgt::DxcShaderModel::V6_2 => Direct3D12::D3D_SHADER_MODEL_6_2,
|
||||||
@ -519,7 +519,7 @@ impl super::Adapter {
|
|||||||
presentation_timer,
|
presentation_timer,
|
||||||
workarounds,
|
workarounds,
|
||||||
memory_budget_thresholds,
|
memory_budget_thresholds,
|
||||||
dxc_container,
|
compiler_container,
|
||||||
},
|
},
|
||||||
info,
|
info,
|
||||||
features,
|
features,
|
||||||
@ -658,7 +658,7 @@ impl crate::Adapter for super::Adapter {
|
|||||||
self.private_caps,
|
self.private_caps,
|
||||||
&self.library,
|
&self.library,
|
||||||
self.memory_budget_thresholds,
|
self.memory_budget_thresholds,
|
||||||
self.dxc_container.clone(),
|
self.compiler_container.clone(),
|
||||||
)?;
|
)?;
|
||||||
Ok(crate::OpenDevice {
|
Ok(crate::OpenDevice {
|
||||||
device,
|
device,
|
||||||
|
|||||||
@ -46,7 +46,7 @@ impl super::Device {
|
|||||||
private_caps: super::PrivateCapabilities,
|
private_caps: super::PrivateCapabilities,
|
||||||
library: &Arc<D3D12Lib>,
|
library: &Arc<D3D12Lib>,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
) -> Result<Self, crate::DeviceError> {
|
) -> Result<Self, crate::DeviceError> {
|
||||||
if private_caps
|
if private_caps
|
||||||
.instance_flags
|
.instance_flags
|
||||||
@ -202,7 +202,7 @@ impl super::Device {
|
|||||||
render_doc: Default::default(),
|
render_doc: Default::default(),
|
||||||
null_rtv_handle,
|
null_rtv_handle,
|
||||||
mem_allocator,
|
mem_allocator,
|
||||||
dxc_container,
|
compiler_container,
|
||||||
counters: Default::default(),
|
counters: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -325,27 +325,14 @@ impl super::Device {
|
|||||||
|
|
||||||
let source_name = stage.module.raw_name.as_deref();
|
let source_name = stage.module.raw_name.as_deref();
|
||||||
|
|
||||||
// Compile with DXC if available, otherwise fall back to FXC
|
let result = self.compiler_container.compile(
|
||||||
let result = if let Some(ref dxc_container) = self.dxc_container {
|
|
||||||
shader_compilation::compile_dxc(
|
|
||||||
self,
|
self,
|
||||||
&source,
|
&source,
|
||||||
source_name,
|
source_name,
|
||||||
raw_ep,
|
raw_ep,
|
||||||
stage_bit,
|
stage_bit,
|
||||||
&full_stage,
|
&full_stage,
|
||||||
dxc_container,
|
);
|
||||||
)
|
|
||||||
} else {
|
|
||||||
shader_compilation::compile_fxc(
|
|
||||||
self,
|
|
||||||
&source,
|
|
||||||
source_name,
|
|
||||||
raw_ep,
|
|
||||||
stage_bit,
|
|
||||||
&full_stage,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let log_level = if result.is_ok() {
|
let log_level = if result.is_ok() {
|
||||||
log::Level::Info
|
log::Level::Info
|
||||||
|
|||||||
@ -10,7 +10,10 @@ use windows::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::SurfaceTarget;
|
use super::SurfaceTarget;
|
||||||
use crate::{auxil, dx12::D3D12Lib};
|
use crate::{
|
||||||
|
auxil,
|
||||||
|
dx12::{shader_compilation::CompilerContainer, D3D12Lib},
|
||||||
|
};
|
||||||
|
|
||||||
impl crate::Instance for super::Instance {
|
impl crate::Instance for super::Instance {
|
||||||
type A = super::Api;
|
type A = super::Api;
|
||||||
@ -66,39 +69,34 @@ impl crate::Instance for super::Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize DXC shader compiler
|
// Initialize the shader compiler
|
||||||
let dxc_container = match desc.backend_options.dx12.shader_compiler.clone() {
|
let compiler_container = match desc.backend_options.dx12.shader_compiler.clone() {
|
||||||
wgt::Dx12Compiler::DynamicDxc {
|
wgt::Dx12Compiler::DynamicDxc {
|
||||||
dxc_path,
|
dxc_path,
|
||||||
max_shader_model,
|
max_shader_model,
|
||||||
} => {
|
} => CompilerContainer::new_dynamic_dxc(dxc_path.into(), max_shader_model).map_err(
|
||||||
let container = super::shader_compilation::get_dynamic_dxc_container(
|
|e| {
|
||||||
dxc_path.into(),
|
|
||||||
max_shader_model,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
|
||||||
crate::InstanceError::with_source(String::from("Failed to load dynamic DXC"), e)
|
crate::InstanceError::with_source(String::from("Failed to load dynamic DXC"), e)
|
||||||
})?;
|
},
|
||||||
|
)?,
|
||||||
Some(Arc::new(container))
|
wgt::Dx12Compiler::StaticDxc => CompilerContainer::new_static_dxc().map_err(|e| {
|
||||||
}
|
crate::InstanceError::with_source(String::from("Failed to load static DXC"), e)
|
||||||
wgt::Dx12Compiler::StaticDxc => {
|
})?,
|
||||||
let container =
|
wgt::Dx12Compiler::Fxc => CompilerContainer::new_fxc().map_err(|e| {
|
||||||
super::shader_compilation::get_static_dxc_container().map_err(|e| {
|
crate::InstanceError::with_source(String::from("Failed to load FXC"), e)
|
||||||
crate::InstanceError::with_source(
|
})?,
|
||||||
String::from("Failed to load static DXC"),
|
|
||||||
e,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Some(Arc::new(container))
|
|
||||||
}
|
|
||||||
wgt::Dx12Compiler::Fxc => None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match dxc_container {
|
match compiler_container {
|
||||||
Some(_) => log::debug!("Using DXC for shader compilation"),
|
CompilerContainer::DynamicDxc(..) => {
|
||||||
None => log::debug!("Using FXC for shader compilation"),
|
log::debug!("Using dynamic DXC for shader compilation")
|
||||||
|
}
|
||||||
|
CompilerContainer::StaticDxc(..) => {
|
||||||
|
log::debug!("Using static DXC for shader compilation")
|
||||||
|
}
|
||||||
|
CompilerContainer::Fxc(..) => {
|
||||||
|
log::debug!("Using FXC for shader compilation")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -110,7 +108,7 @@ impl crate::Instance for super::Instance {
|
|||||||
supports_allow_tearing,
|
supports_allow_tearing,
|
||||||
flags: desc.flags,
|
flags: desc.flags,
|
||||||
memory_budget_thresholds: desc.memory_budget_thresholds,
|
memory_budget_thresholds: desc.memory_budget_thresholds,
|
||||||
dxc_container,
|
compiler_container: Arc::new(compiler_container),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +146,7 @@ impl crate::Instance for super::Instance {
|
|||||||
&self.library,
|
&self.library,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.memory_budget_thresholds,
|
self.memory_budget_thresholds,
|
||||||
self.dxc_container.clone(),
|
self.compiler_container.clone(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
@ -460,7 +460,7 @@ pub struct Instance {
|
|||||||
_lib_dxgi: DxgiLib,
|
_lib_dxgi: DxgiLib,
|
||||||
flags: wgt::InstanceFlags,
|
flags: wgt::InstanceFlags,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
@ -592,7 +592,7 @@ pub struct Adapter {
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
workarounds: Workarounds,
|
workarounds: Workarounds,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Adapter {}
|
unsafe impl Send for Adapter {}
|
||||||
@ -655,7 +655,7 @@ pub struct Device {
|
|||||||
render_doc: auxil::renderdoc::RenderDoc,
|
render_doc: auxil::renderdoc::RenderDoc,
|
||||||
null_rtv_handle: descriptor::Handle,
|
null_rtv_handle: descriptor::Handle,
|
||||||
mem_allocator: Allocator,
|
mem_allocator: Allocator,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
counters: Arc<wgt::HalCounters>,
|
counters: Arc<wgt::HalCounters>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,19 +6,224 @@ use crate::auxil::dxgi::result::HResult;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use windows::{
|
use windows::{
|
||||||
core::{Interface, PCSTR, PCWSTR},
|
core::{Interface, PCSTR, PCWSTR},
|
||||||
Win32::Graphics::Direct3D::{Dxc, Fxc},
|
Win32::Graphics::Direct3D::{Dxc, Fxc, ID3DBlob, D3D_SHADER_MACRO},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn compile_fxc(
|
pub(super) enum CompilerContainer {
|
||||||
|
Fxc(CompilerFxc),
|
||||||
|
DynamicDxc(CompilerDynamicDxc),
|
||||||
|
#[cfg_attr(not(static_dxc), allow(unused))]
|
||||||
|
StaticDxc(CompilerStaticDxc),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct CompilerFxc {
|
||||||
|
fxc: FxcLib,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct CompilerDynamicDxc {
|
||||||
|
max_shader_model: wgt::DxcShaderModel,
|
||||||
|
compiler: Dxc::IDxcCompiler3,
|
||||||
|
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile.
|
||||||
|
// Only needed when using dynamic linking.
|
||||||
|
_dxc: DxcLib,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct CompilerStaticDxc {
|
||||||
|
max_shader_model: wgt::DxcShaderModel,
|
||||||
|
compiler: Dxc::IDxcCompiler3,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub(super) enum GetContainerError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Device(#[from] crate::DeviceError),
|
||||||
|
#[error("Failed to load {0}: {1}")]
|
||||||
|
FailedToLoad(&'static str, libloading::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompilerContainer {
|
||||||
|
pub(super) fn new_fxc() -> Result<Self, GetContainerError> {
|
||||||
|
FxcLib::new_dynamic().map(|fxc| Self::Fxc(CompilerFxc { fxc }))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn new_dynamic_dxc(
|
||||||
|
dxc_path: PathBuf,
|
||||||
|
max_shader_model: wgt::DxcShaderModel,
|
||||||
|
) -> Result<Self, GetContainerError> {
|
||||||
|
let dxc = DxcLib::new_dynamic(dxc_path)
|
||||||
|
.map_err(|e| GetContainerError::FailedToLoad("dxcompiler.dll", e))?;
|
||||||
|
|
||||||
|
let compiler = dxc.create_instance::<Dxc::IDxcCompiler3>()?;
|
||||||
|
|
||||||
|
Ok(Self::DynamicDxc(CompilerDynamicDxc {
|
||||||
|
max_shader_model,
|
||||||
|
compiler,
|
||||||
|
_dxc: dxc,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [`CompilerContainer`] that delegates to the statically-linked version of DXC.
|
||||||
|
pub(super) fn new_static_dxc() -> Result<CompilerContainer, crate::DeviceError> {
|
||||||
|
#[cfg(static_dxc)]
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let compiler = dxc_create_instance::<Dxc::IDxcCompiler3>(|clsid, iid, ppv| {
|
||||||
|
windows_core::HRESULT(mach_dxcompiler_rs::DxcCreateInstance(
|
||||||
|
clsid.cast(),
|
||||||
|
iid.cast(),
|
||||||
|
ppv,
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(CompilerContainer::StaticDxc(CompilerStaticDxc {
|
||||||
|
max_shader_model: wgt::DxcShaderModel::V6_7,
|
||||||
|
compiler,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(static_dxc))]
|
||||||
|
{
|
||||||
|
panic!("Attempted to create a static DXC shader compiler, but the static-dxc feature was not enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn max_shader_model(&self) -> Option<wgt::DxcShaderModel> {
|
||||||
|
match self {
|
||||||
|
CompilerContainer::Fxc(..) => None,
|
||||||
|
CompilerContainer::DynamicDxc(CompilerDynamicDxc {
|
||||||
|
max_shader_model, ..
|
||||||
|
})
|
||||||
|
| CompilerContainer::StaticDxc(CompilerStaticDxc {
|
||||||
|
max_shader_model, ..
|
||||||
|
}) => Some(max_shader_model.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn compile(
|
||||||
|
&self,
|
||||||
device: &super::Device,
|
device: &super::Device,
|
||||||
source: &str,
|
source: &str,
|
||||||
source_name: Option<&CStr>,
|
source_name: Option<&CStr>,
|
||||||
raw_ep: &str,
|
raw_ep: &str,
|
||||||
stage_bit: wgt::ShaderStages,
|
stage_bit: wgt::ShaderStages,
|
||||||
full_stage: &str,
|
full_stage: &str,
|
||||||
|
) -> Result<super::CompiledShader, crate::PipelineError> {
|
||||||
|
match self {
|
||||||
|
CompilerContainer::Fxc(CompilerFxc { fxc }) => compile_fxc(
|
||||||
|
device,
|
||||||
|
source,
|
||||||
|
source_name,
|
||||||
|
raw_ep,
|
||||||
|
stage_bit,
|
||||||
|
full_stage,
|
||||||
|
fxc,
|
||||||
|
),
|
||||||
|
CompilerContainer::DynamicDxc(CompilerDynamicDxc { compiler, .. })
|
||||||
|
| CompilerContainer::StaticDxc(CompilerStaticDxc { compiler, .. }) => compile_dxc(
|
||||||
|
device,
|
||||||
|
source,
|
||||||
|
source_name,
|
||||||
|
raw_ep,
|
||||||
|
stage_bit,
|
||||||
|
full_stage,
|
||||||
|
compiler,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type D3DCompileFn = unsafe extern "system" fn(
|
||||||
|
psrcdata: *const core::ffi::c_void,
|
||||||
|
srcdatasize: usize,
|
||||||
|
psourcename: PCSTR,
|
||||||
|
pdefines: *const D3D_SHADER_MACRO,
|
||||||
|
pinclude: *mut core::ffi::c_void,
|
||||||
|
pentrypoint: PCSTR,
|
||||||
|
ptarget: PCSTR,
|
||||||
|
flags1: u32,
|
||||||
|
flags2: u32,
|
||||||
|
ppcode: *mut *mut core::ffi::c_void,
|
||||||
|
pperrormsgs: *mut *mut core::ffi::c_void,
|
||||||
|
) -> windows_core::HRESULT;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct FxcLib {
|
||||||
|
// `d3dcompile_fn` points into `_lib`, so `_lib` must be held for as long
|
||||||
|
// as we want to keep compiling shaders with FXC.
|
||||||
|
_lib: crate::dx12::DynLib,
|
||||||
|
d3dcompile_fn: D3DCompileFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FxcLib {
|
||||||
|
const PATH: &str = "d3dcompiler_47.dll";
|
||||||
|
|
||||||
|
fn new_dynamic() -> Result<Self, GetContainerError> {
|
||||||
|
unsafe {
|
||||||
|
let lib = crate::dx12::DynLib::new(Self::PATH)
|
||||||
|
.map_err(|e| GetContainerError::FailedToLoad(FxcLib::PATH, e))?;
|
||||||
|
let d3dcompile_fn: D3DCompileFn = *lib.get::<D3DCompileFn>(c"D3DCompile".to_bytes())?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
_lib: lib,
|
||||||
|
d3dcompile_fn,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn compile(
|
||||||
|
&self,
|
||||||
|
source: &str,
|
||||||
|
source_name: Option<&CStr>,
|
||||||
|
raw_ep: &str,
|
||||||
|
full_stage: &str,
|
||||||
|
compile_flags: u32,
|
||||||
|
shader_data: &mut Option<ID3DBlob>,
|
||||||
|
error: &mut Option<ID3DBlob>,
|
||||||
|
) -> Result<windows_core::Result<()>, crate::DeviceError> {
|
||||||
|
unsafe {
|
||||||
|
let raw_ep = alloc::ffi::CString::new(raw_ep).unwrap();
|
||||||
|
let full_stage = alloc::ffi::CString::new(full_stage).unwrap();
|
||||||
|
|
||||||
|
// If no name has been set, D3DCompile wants the null pointer.
|
||||||
|
let source_name = source_name
|
||||||
|
.map(|cstr| cstr.as_ptr().cast())
|
||||||
|
.unwrap_or(core::ptr::null());
|
||||||
|
|
||||||
|
let shader_data: *mut Option<ID3DBlob> = shader_data;
|
||||||
|
let error: *mut Option<ID3DBlob> = error;
|
||||||
|
|
||||||
|
{
|
||||||
|
profiling::scope!("Fxc::D3DCompile");
|
||||||
|
Ok((self.d3dcompile_fn)(
|
||||||
|
source.as_ptr().cast(),
|
||||||
|
source.len(),
|
||||||
|
PCSTR(source_name),
|
||||||
|
core::ptr::null(),
|
||||||
|
core::ptr::null_mut(),
|
||||||
|
PCSTR(raw_ep.as_ptr().cast()),
|
||||||
|
PCSTR(full_stage.as_ptr().cast()),
|
||||||
|
compile_flags,
|
||||||
|
0,
|
||||||
|
shader_data.cast(),
|
||||||
|
error.cast(),
|
||||||
|
)
|
||||||
|
.ok())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_fxc(
|
||||||
|
device: &super::Device,
|
||||||
|
source: &str,
|
||||||
|
source_name: Option<&CStr>,
|
||||||
|
raw_ep: &str,
|
||||||
|
stage_bit: wgt::ShaderStages,
|
||||||
|
full_stage: &str,
|
||||||
|
fxc: &FxcLib,
|
||||||
) -> Result<super::CompiledShader, crate::PipelineError> {
|
) -> Result<super::CompiledShader, crate::PipelineError> {
|
||||||
profiling::scope!("compile_fxc");
|
profiling::scope!("compile_fxc");
|
||||||
let mut shader_data = None;
|
|
||||||
let mut compile_flags = Fxc::D3DCOMPILE_ENABLE_STRICTNESS;
|
let mut compile_flags = Fxc::D3DCOMPILE_ENABLE_STRICTNESS;
|
||||||
if device
|
if device
|
||||||
.shared
|
.shared
|
||||||
@ -29,32 +234,17 @@ pub(super) fn compile_fxc(
|
|||||||
compile_flags |= Fxc::D3DCOMPILE_DEBUG | Fxc::D3DCOMPILE_SKIP_OPTIMIZATION;
|
compile_flags |= Fxc::D3DCOMPILE_DEBUG | Fxc::D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw_ep = alloc::ffi::CString::new(raw_ep).unwrap();
|
let mut shader_data = None;
|
||||||
let full_stage = alloc::ffi::CString::new(full_stage).unwrap();
|
|
||||||
|
|
||||||
// If no name has been set, D3DCompile wants the null pointer.
|
|
||||||
let source_name = source_name
|
|
||||||
.map(|cstr| cstr.as_ptr().cast())
|
|
||||||
.unwrap_or(core::ptr::null());
|
|
||||||
|
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
let hr = unsafe {
|
let hr = fxc.compile(
|
||||||
profiling::scope!("Fxc::D3DCompile");
|
source,
|
||||||
Fxc::D3DCompile(
|
source_name,
|
||||||
// TODO: Update low-level bindings to accept a slice here
|
raw_ep,
|
||||||
source.as_ptr().cast(),
|
full_stage,
|
||||||
source.len(),
|
|
||||||
PCSTR(source_name),
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
PCSTR(raw_ep.as_ptr().cast()),
|
|
||||||
PCSTR(full_stage.as_ptr().cast()),
|
|
||||||
compile_flags,
|
compile_flags,
|
||||||
0,
|
|
||||||
&mut shader_data,
|
&mut shader_data,
|
||||||
Some(&mut error),
|
&mut error,
|
||||||
)
|
)?;
|
||||||
};
|
|
||||||
|
|
||||||
match hr {
|
match hr {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@ -132,64 +322,6 @@ unsafe fn dxc_create_instance<T: DxcObj>(
|
|||||||
result__.ok_or(crate::DeviceError::Unexpected)
|
result__.ok_or(crate::DeviceError::Unexpected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct DxcContainer {
|
|
||||||
pub(super) max_shader_model: wgt::DxcShaderModel,
|
|
||||||
compiler: Dxc::IDxcCompiler3,
|
|
||||||
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile.
|
|
||||||
// Only needed when using dynamic linking.
|
|
||||||
_dxc: Option<DxcLib>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub(super) enum GetDynamicDXCContainerError {
|
|
||||||
#[error(transparent)]
|
|
||||||
Device(#[from] crate::DeviceError),
|
|
||||||
#[error("Failed to load {0}: {1}")]
|
|
||||||
FailedToLoad(&'static str, libloading::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn get_dynamic_dxc_container(
|
|
||||||
dxc_path: PathBuf,
|
|
||||||
max_shader_model: wgt::DxcShaderModel,
|
|
||||||
) -> Result<DxcContainer, GetDynamicDXCContainerError> {
|
|
||||||
let dxc = DxcLib::new_dynamic(dxc_path)
|
|
||||||
.map_err(|e| GetDynamicDXCContainerError::FailedToLoad("dxcompiler.dll", e))?;
|
|
||||||
|
|
||||||
let compiler = dxc.create_instance::<Dxc::IDxcCompiler3>()?;
|
|
||||||
|
|
||||||
Ok(DxcContainer {
|
|
||||||
max_shader_model,
|
|
||||||
compiler,
|
|
||||||
_dxc: Some(dxc),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a [`DxcContainer`] that delegates to the statically-linked version of DXC.
|
|
||||||
pub(super) fn get_static_dxc_container() -> Result<DxcContainer, crate::DeviceError> {
|
|
||||||
#[cfg(static_dxc)]
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
let compiler = dxc_create_instance::<Dxc::IDxcCompiler3>(|clsid, iid, ppv| {
|
|
||||||
windows_core::HRESULT(mach_dxcompiler_rs::DxcCreateInstance(
|
|
||||||
clsid.cast(),
|
|
||||||
iid.cast(),
|
|
||||||
ppv,
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(DxcContainer {
|
|
||||||
max_shader_model: wgt::DxcShaderModel::V6_7,
|
|
||||||
compiler,
|
|
||||||
_dxc: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(static_dxc))]
|
|
||||||
{
|
|
||||||
panic!("Attempted to create a static DXC shader compiler, but the static-dxc feature was not enabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Owned PCWSTR
|
/// Owned PCWSTR
|
||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
struct OPCWSTR {
|
struct OPCWSTR {
|
||||||
@ -225,14 +357,14 @@ fn as_err_str(blob: &Dxc::IDxcBlobUtf8) -> Result<&str, crate::DeviceError> {
|
|||||||
.map_err(|_| crate::DeviceError::Unexpected)
|
.map_err(|_| crate::DeviceError::Unexpected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn compile_dxc(
|
fn compile_dxc(
|
||||||
device: &crate::dx12::Device,
|
device: &crate::dx12::Device,
|
||||||
source: &str,
|
source: &str,
|
||||||
source_name: Option<&CStr>,
|
source_name: Option<&CStr>,
|
||||||
raw_ep: &str,
|
raw_ep: &str,
|
||||||
stage_bit: wgt::ShaderStages,
|
stage_bit: wgt::ShaderStages,
|
||||||
full_stage: &str,
|
full_stage: &str,
|
||||||
dxc_container: &DxcContainer,
|
compiler: &Dxc::IDxcCompiler3,
|
||||||
) -> Result<crate::dx12::CompiledShader, crate::PipelineError> {
|
) -> Result<crate::dx12::CompiledShader, crate::PipelineError> {
|
||||||
profiling::scope!("compile_dxc");
|
profiling::scope!("compile_dxc");
|
||||||
|
|
||||||
@ -279,11 +411,8 @@ pub(super) fn compile_dxc(
|
|||||||
Encoding: Dxc::DXC_CP_UTF8.0,
|
Encoding: Dxc::DXC_CP_UTF8.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let compile_res: Dxc::IDxcResult = unsafe {
|
let compile_res: Dxc::IDxcResult =
|
||||||
dxc_container
|
unsafe { compiler.Compile(&buffer, Some(&compile_args), None) }
|
||||||
.compiler
|
|
||||||
.Compile(&buffer, Some(&compile_args), None)
|
|
||||||
}
|
|
||||||
.into_device_result("Compile")?;
|
.into_device_result("Compile")?;
|
||||||
|
|
||||||
drop(compile_args);
|
drop(compile_args);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user