mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-25 08:13:27 +00:00
Dx11 Backend (#2443)
This commit is contained in:
parent
c314c55788
commit
73f42352f3
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -436,8 +436,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c"
|
||||
source = "git+https://github.com/gfx-rs/d3d12-rs.git?rev=ffe5e261da0a6cb85332b82ab310abd2a7e849f6#ffe5e261da0a6cb85332b82ab310abd2a7e849f6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libloading",
|
||||
|
@ -28,6 +28,7 @@ default-members = ["wgpu", "wgpu-hal", "wgpu-info"]
|
||||
[patch.crates-io]
|
||||
#naga = { path = "../naga" }
|
||||
#glow = { path = "../glow" }
|
||||
#d3d12 = { path = "../d3d12-rs" }
|
||||
#metal = { path = "../metal-rs" }
|
||||
#web-sys = { path = "../wasm-bindgen/crates/web-sys" }
|
||||
#js-sys = { path = "../wasm-bindgen/crates/js-sys" }
|
||||
|
@ -65,7 +65,7 @@ hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features =
|
||||
hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["vulkan", "gles", "renderdoc"] }
|
||||
|
||||
[target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies]
|
||||
hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["vulkan", "dx12", "renderdoc"] }
|
||||
hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["vulkan", "dx12", "dx11", "renderdoc"] }
|
||||
|
||||
[target.'cfg(target_os = "emscripten")'.dependencies]
|
||||
hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["emscripten"] }
|
||||
|
@ -10,7 +10,7 @@ fn main() {
|
||||
vulkan: { all(not(wasm), any(windows, unix_wo_apple, feature = "vulkan-portability")) },
|
||||
metal: { all(not(wasm), apple) },
|
||||
dx12: { all(not(wasm), windows) },
|
||||
dx11: { all(false, not(wasm), windows) },
|
||||
dx11: { all(not(wasm), windows) },
|
||||
gl: {
|
||||
any(
|
||||
unix_wo_apple,
|
||||
|
@ -1042,10 +1042,16 @@ impl HalApi for hal::api::Dx12 {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(dx11)]
|
||||
impl HalApi for hal::api::Dx11 {
|
||||
const VARIANT: Backend = Backend::Dx11;
|
||||
fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance {
|
||||
Instance {
|
||||
name: name.to_owned(),
|
||||
dx11: Some(hal_instance),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
fn hub<G: GlobalIdentityHandlerFactory>(global: &Global<G>) -> &Hub<Self, G> {
|
||||
&global.hubs.dx11
|
||||
}
|
||||
@ -1056,7 +1062,6 @@ impl HalApi for hal::api::Dx11 {
|
||||
surface.dx11.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(gl)]
|
||||
impl HalApi for hal::api::Gles {
|
||||
|
@ -508,6 +508,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
dx12: self.instance.dx12.as_ref().map(|inst| HalSurface {
|
||||
raw: { inst.create_surface_from_visual(visual as _) },
|
||||
}),
|
||||
dx11: None,
|
||||
#[cfg(gl)]
|
||||
gl: None,
|
||||
};
|
||||
|
@ -211,8 +211,8 @@ macro_rules! gfx_select {
|
||||
wgt::Backend::Metal => $global.$method::<$crate::api::Metal>( $($param),* ),
|
||||
#[cfg(all(not(target_arch = "wasm32"), windows))]
|
||||
wgt::Backend::Dx12 => $global.$method::<$crate::api::Dx12>( $($param),* ),
|
||||
//#[cfg(all(not(target_arch = "wasm32"), windows))]
|
||||
//wgt::Backend::Dx11 => $global.$method::<$crate::api::Dx11>( $($param),* ),
|
||||
#[cfg(all(not(target_arch = "wasm32"), windows))]
|
||||
wgt::Backend::Dx11 => $global.$method::<$crate::api::Dx11>( $($param),* ),
|
||||
#[cfg(any(
|
||||
all(unix, not(target_os = "macos"), not(target_os = "ios")),
|
||||
feature = "angle",
|
||||
|
@ -16,6 +16,7 @@ default = []
|
||||
metal = ["naga/msl-out", "block", "foreign-types"]
|
||||
vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "inplace_it"]
|
||||
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"]
|
||||
renderdoc = ["libloading", "renderdoc-sys"]
|
||||
emscripten = ["gles"]
|
||||
@ -74,7 +75,8 @@ libloading = { version = "0.7", optional = true }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["libloaderapi", "windef", "winuser", "dcomp"] }
|
||||
native = { package = "d3d12", version = "0.4.1", features = ["libloading"], optional = true }
|
||||
# native = { package = "d3d12", version = "0.4.1", features = ["libloading"], optional = true }
|
||||
native = { package = "d3d12", git = "https://github.com/gfx-rs/d3d12-rs.git", rev = "ffe5e261da0a6cb85332b82ab310abd2a7e849f6", features = ["libloading"], optional = true }
|
||||
|
||||
[target.'cfg(any(target_os="macos", target_os="ios"))'.dependencies]
|
||||
mtl = { package = "metal", git = "https://github.com/gfx-rs/metal-rs", rev = "a357159" }
|
||||
|
175
wgpu-hal/src/auxil/dxgi/conv.rs
Normal file
175
wgpu-hal/src/auxil/dxgi/conv.rs
Normal file
@ -0,0 +1,175 @@
|
||||
use winapi::shared::dxgiformat;
|
||||
|
||||
pub fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
use wgt::TextureFormat as Tf;
|
||||
use winapi::shared::dxgiformat::*;
|
||||
|
||||
match format {
|
||||
Tf::R8Unorm => DXGI_FORMAT_R8_UNORM,
|
||||
Tf::R8Snorm => DXGI_FORMAT_R8_SNORM,
|
||||
Tf::R8Uint => DXGI_FORMAT_R8_UINT,
|
||||
Tf::R8Sint => DXGI_FORMAT_R8_SINT,
|
||||
Tf::R16Uint => DXGI_FORMAT_R16_UINT,
|
||||
Tf::R16Sint => DXGI_FORMAT_R16_SINT,
|
||||
Tf::R16Unorm => DXGI_FORMAT_R16_UNORM,
|
||||
Tf::R16Snorm => DXGI_FORMAT_R16_SNORM,
|
||||
Tf::R16Float => DXGI_FORMAT_R16_FLOAT,
|
||||
Tf::Rg8Unorm => DXGI_FORMAT_R8G8_UNORM,
|
||||
Tf::Rg8Snorm => DXGI_FORMAT_R8G8_SNORM,
|
||||
Tf::Rg8Uint => DXGI_FORMAT_R8G8_UINT,
|
||||
Tf::Rg8Sint => DXGI_FORMAT_R8G8_SINT,
|
||||
Tf::Rg16Unorm => DXGI_FORMAT_R16G16_UNORM,
|
||||
Tf::Rg16Snorm => DXGI_FORMAT_R16G16_SNORM,
|
||||
Tf::R32Uint => DXGI_FORMAT_R32_UINT,
|
||||
Tf::R32Sint => DXGI_FORMAT_R32_SINT,
|
||||
Tf::R32Float => DXGI_FORMAT_R32_FLOAT,
|
||||
Tf::Rg16Uint => DXGI_FORMAT_R16G16_UINT,
|
||||
Tf::Rg16Sint => DXGI_FORMAT_R16G16_SINT,
|
||||
Tf::Rg16Float => DXGI_FORMAT_R16G16_FLOAT,
|
||||
Tf::Rgba8Unorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
Tf::Rgba8UnormSrgb => DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
Tf::Bgra8UnormSrgb => DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
Tf::Rgba8Snorm => DXGI_FORMAT_R8G8B8A8_SNORM,
|
||||
Tf::Bgra8Unorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
Tf::Rgba8Uint => DXGI_FORMAT_R8G8B8A8_UINT,
|
||||
Tf::Rgba8Sint => DXGI_FORMAT_R8G8B8A8_SINT,
|
||||
Tf::Rgb10a2Unorm => DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
Tf::Rg11b10Float => DXGI_FORMAT_R11G11B10_FLOAT,
|
||||
Tf::Rg32Uint => DXGI_FORMAT_R32G32_UINT,
|
||||
Tf::Rg32Sint => DXGI_FORMAT_R32G32_SINT,
|
||||
Tf::Rg32Float => DXGI_FORMAT_R32G32_FLOAT,
|
||||
Tf::Rgba16Uint => DXGI_FORMAT_R16G16B16A16_UINT,
|
||||
Tf::Rgba16Sint => DXGI_FORMAT_R16G16B16A16_SINT,
|
||||
Tf::Rgba16Unorm => DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
Tf::Rgba16Snorm => DXGI_FORMAT_R16G16B16A16_SNORM,
|
||||
Tf::Rgba16Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
Tf::Rgba32Uint => DXGI_FORMAT_R32G32B32A32_UINT,
|
||||
Tf::Rgba32Sint => DXGI_FORMAT_R32G32B32A32_SINT,
|
||||
Tf::Rgba32Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT,
|
||||
Tf::Depth24Plus => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
Tf::Depth24PlusStencil8 => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
Tf::Rgb9e5Ufloat => DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
|
||||
Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
|
||||
Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
|
||||
Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM,
|
||||
Tf::Bc2RgbaUnormSrgb => DXGI_FORMAT_BC2_UNORM_SRGB,
|
||||
Tf::Bc3RgbaUnorm => DXGI_FORMAT_BC3_UNORM,
|
||||
Tf::Bc3RgbaUnormSrgb => DXGI_FORMAT_BC3_UNORM_SRGB,
|
||||
Tf::Bc4RUnorm => DXGI_FORMAT_BC4_UNORM,
|
||||
Tf::Bc4RSnorm => DXGI_FORMAT_BC4_SNORM,
|
||||
Tf::Bc5RgUnorm => DXGI_FORMAT_BC5_UNORM,
|
||||
Tf::Bc5RgSnorm => DXGI_FORMAT_BC5_SNORM,
|
||||
Tf::Bc6hRgbUfloat => DXGI_FORMAT_BC6H_UF16,
|
||||
Tf::Bc6hRgbSfloat => DXGI_FORMAT_BC6H_SF16,
|
||||
Tf::Bc7RgbaUnorm => DXGI_FORMAT_BC7_UNORM,
|
||||
Tf::Bc7RgbaUnormSrgb => DXGI_FORMAT_BC7_UNORM_SRGB,
|
||||
Tf::Etc2Rgb8Unorm
|
||||
| Tf::Etc2Rgb8UnormSrgb
|
||||
| Tf::Etc2Rgb8A1Unorm
|
||||
| Tf::Etc2Rgb8A1UnormSrgb
|
||||
| Tf::Etc2Rgba8Unorm
|
||||
| Tf::Etc2Rgba8UnormSrgb
|
||||
| Tf::EacR11Unorm
|
||||
| Tf::EacR11Snorm
|
||||
| Tf::EacRg11Unorm
|
||||
| Tf::EacRg11Snorm
|
||||
| Tf::Astc {
|
||||
block: _,
|
||||
channel: _,
|
||||
} => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Note: DXGI doesn't allow sRGB format on the swapchain,
|
||||
// but creating RTV of swapchain buffers with sRGB works.
|
||||
pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Bgra8UnormSrgb => dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
wgt::TextureFormat::Rgba8UnormSrgb => dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
_ => map_texture_format(format),
|
||||
}
|
||||
}
|
||||
|
||||
//Note: SRV and UAV can't use the depth formats directly
|
||||
//TODO: stencil views?
|
||||
pub fn map_texture_format_nodepth(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_FLOAT,
|
||||
wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
|
||||
dxgiformat::DXGI_FORMAT_R24_UNORM_X8_TYPELESS
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(
|
||||
crate::FormatAspects::from(format),
|
||||
crate::FormatAspects::COLOR
|
||||
);
|
||||
map_texture_format(format)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_texture_format_depth_typeless(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
|
||||
dxgiformat::DXGI_FORMAT_R24G8_TYPELESS
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_index_format(format: wgt::IndexFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::IndexFormat::Uint16 => dxgiformat::DXGI_FORMAT_R16_UINT,
|
||||
wgt::IndexFormat::Uint32 => dxgiformat::DXGI_FORMAT_R32_UINT,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
use wgt::VertexFormat as Vf;
|
||||
use winapi::shared::dxgiformat::*;
|
||||
|
||||
match format {
|
||||
Vf::Unorm8x2 => DXGI_FORMAT_R8G8_UNORM,
|
||||
Vf::Snorm8x2 => DXGI_FORMAT_R8G8_SNORM,
|
||||
Vf::Uint8x2 => DXGI_FORMAT_R8G8_UINT,
|
||||
Vf::Sint8x2 => DXGI_FORMAT_R8G8_SINT,
|
||||
Vf::Unorm8x4 => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
Vf::Snorm8x4 => DXGI_FORMAT_R8G8B8A8_SNORM,
|
||||
Vf::Uint8x4 => DXGI_FORMAT_R8G8B8A8_UINT,
|
||||
Vf::Sint8x4 => DXGI_FORMAT_R8G8B8A8_SINT,
|
||||
Vf::Unorm16x2 => DXGI_FORMAT_R16G16_UNORM,
|
||||
Vf::Snorm16x2 => DXGI_FORMAT_R16G16_SNORM,
|
||||
Vf::Uint16x2 => DXGI_FORMAT_R16G16_UINT,
|
||||
Vf::Sint16x2 => DXGI_FORMAT_R16G16_SINT,
|
||||
Vf::Float16x2 => DXGI_FORMAT_R16G16_FLOAT,
|
||||
Vf::Unorm16x4 => DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
Vf::Snorm16x4 => DXGI_FORMAT_R16G16B16A16_SNORM,
|
||||
Vf::Uint16x4 => DXGI_FORMAT_R16G16B16A16_UINT,
|
||||
Vf::Sint16x4 => DXGI_FORMAT_R16G16B16A16_SINT,
|
||||
Vf::Float16x4 => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
Vf::Uint32 => DXGI_FORMAT_R32_UINT,
|
||||
Vf::Sint32 => DXGI_FORMAT_R32_SINT,
|
||||
Vf::Float32 => DXGI_FORMAT_R32_FLOAT,
|
||||
Vf::Uint32x2 => DXGI_FORMAT_R32G32_UINT,
|
||||
Vf::Sint32x2 => DXGI_FORMAT_R32G32_SINT,
|
||||
Vf::Float32x2 => DXGI_FORMAT_R32G32_FLOAT,
|
||||
Vf::Uint32x3 => DXGI_FORMAT_R32G32B32_UINT,
|
||||
Vf::Sint32x3 => DXGI_FORMAT_R32G32B32_SINT,
|
||||
Vf::Float32x3 => DXGI_FORMAT_R32G32B32_FLOAT,
|
||||
Vf::Uint32x4 => DXGI_FORMAT_R32G32B32A32_UINT,
|
||||
Vf::Sint32x4 => DXGI_FORMAT_R32G32B32A32_SINT,
|
||||
Vf::Float32x4 => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_acomposite_alpha_mode(mode: crate::CompositeAlphaMode) -> native::AlphaMode {
|
||||
use crate::CompositeAlphaMode as Cam;
|
||||
match mode {
|
||||
Cam::Opaque => native::AlphaMode::Ignore,
|
||||
Cam::PreMultiplied => native::AlphaMode::Premultiplied,
|
||||
Cam::PostMultiplied => native::AlphaMode::Straight,
|
||||
}
|
||||
}
|
98
wgpu-hal/src/auxil/dxgi/exception.rs
Normal file
98
wgpu-hal/src/auxil/dxgi/exception.rs
Normal file
@ -0,0 +1,98 @@
|
||||
use std::{borrow::Cow, slice};
|
||||
|
||||
use parking_lot::{lock_api::RawMutex, Mutex};
|
||||
use winapi::{
|
||||
um::{errhandlingapi, winnt},
|
||||
vc::excpt,
|
||||
};
|
||||
|
||||
// This is a mutex as opposed to an atomic as we need to completely
|
||||
// lock everyone out until we have registered or unregistered the
|
||||
// exception handler, otherwise really nasty races could happen.
|
||||
//
|
||||
// By routing all the registration through these functions we can guarentee
|
||||
// there is either 1 or 0 exception handlers registered, not multiple.
|
||||
static EXCEPTION_HANLDER_COUNT: Mutex<usize> = Mutex::const_new(parking_lot::RawMutex::INIT, 0);
|
||||
|
||||
pub fn register_exception_handler() {
|
||||
let mut count_guard = EXCEPTION_HANLDER_COUNT.lock();
|
||||
if *count_guard == 0 {
|
||||
unsafe {
|
||||
errhandlingapi::AddVectoredExceptionHandler(0, Some(output_debug_string_handler))
|
||||
};
|
||||
}
|
||||
*count_guard += 1;
|
||||
}
|
||||
|
||||
pub fn unregister_exception_handler() {
|
||||
let mut count_guard = EXCEPTION_HANLDER_COUNT.lock();
|
||||
if *count_guard == 1 {
|
||||
unsafe {
|
||||
errhandlingapi::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _)
|
||||
};
|
||||
}
|
||||
*count_guard -= 1;
|
||||
}
|
||||
|
||||
const MESSAGE_PREFIXES: &[(&str, log::Level)] = &[
|
||||
("CORRUPTION", log::Level::Error),
|
||||
("ERROR", log::Level::Error),
|
||||
("WARNING", log::Level::Warn),
|
||||
("INFO", log::Level::Info),
|
||||
("MESSAGE", log::Level::Debug),
|
||||
];
|
||||
|
||||
unsafe extern "system" fn output_debug_string_handler(
|
||||
exception_info: *mut winnt::EXCEPTION_POINTERS,
|
||||
) -> i32 {
|
||||
// See https://stackoverflow.com/a/41480827
|
||||
let record = &*(*exception_info).ExceptionRecord;
|
||||
if record.NumberParameters != 2 {
|
||||
return excpt::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
let message = match record.ExceptionCode {
|
||||
winnt::DBG_PRINTEXCEPTION_C => String::from_utf8_lossy(slice::from_raw_parts(
|
||||
record.ExceptionInformation[1] as *const u8,
|
||||
record.ExceptionInformation[0],
|
||||
)),
|
||||
winnt::DBG_PRINTEXCEPTION_WIDE_C => {
|
||||
Cow::Owned(String::from_utf16_lossy(slice::from_raw_parts(
|
||||
record.ExceptionInformation[1] as *const u16,
|
||||
record.ExceptionInformation[0],
|
||||
)))
|
||||
}
|
||||
_ => return excpt::EXCEPTION_CONTINUE_SEARCH,
|
||||
};
|
||||
|
||||
let message = match message.strip_prefix("D3D12 ") {
|
||||
Some(msg) => msg
|
||||
.trim_end_matches("\n\0")
|
||||
.trim_end_matches("[ STATE_CREATION WARNING #0: UNKNOWN]"),
|
||||
None => return excpt::EXCEPTION_CONTINUE_SEARCH,
|
||||
};
|
||||
|
||||
let (message, level) = match MESSAGE_PREFIXES
|
||||
.iter()
|
||||
.find(|&&(prefix, _)| message.starts_with(prefix))
|
||||
{
|
||||
Some(&(prefix, level)) => (&message[prefix.len() + 2..], level),
|
||||
None => (message, log::Level::Debug),
|
||||
};
|
||||
|
||||
if level == log::Level::Warn && message.contains("#82") {
|
||||
// This is are useless spammy warnings (#820, #821):
|
||||
// "The application did not pass any clear value to resource creation"
|
||||
return excpt::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
let _ = std::panic::catch_unwind(|| {
|
||||
log::log!(level, "{}", message);
|
||||
});
|
||||
|
||||
if cfg!(debug_assertions) && level == log::Level::Error {
|
||||
// Set canary and continue
|
||||
crate::VALIDATION_CANARY.set();
|
||||
}
|
||||
|
||||
excpt::EXCEPTION_CONTINUE_EXECUTION
|
||||
}
|
210
wgpu-hal/src/auxil/dxgi/factory.rs
Normal file
210
wgpu-hal/src/auxil/dxgi/factory.rs
Normal file
@ -0,0 +1,210 @@
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_4, dxgi1_6, winerror},
|
||||
Interface,
|
||||
};
|
||||
|
||||
use super::result::HResult as _;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum DxgiFactoryType {
|
||||
Factory1,
|
||||
Factory2,
|
||||
Factory4,
|
||||
Factory6,
|
||||
}
|
||||
|
||||
pub fn enumerate_adapters(factory: native::DxgiFactory) -> Vec<native::DxgiAdapter> {
|
||||
let mut adapters = Vec::with_capacity(8);
|
||||
|
||||
for cur_index in 0.. {
|
||||
if let Some(factory6) = factory.as_factory6() {
|
||||
profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference");
|
||||
// We're already at dxgi1.6, we can grab IDXGIAdapater4 directly
|
||||
let mut adapter4 = native::WeakPtr::<dxgi1_6::IDXGIAdapter4>::null();
|
||||
let hr = unsafe {
|
||||
factory6.EnumAdapterByGpuPreference(
|
||||
cur_index,
|
||||
dxgi1_6::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||
&dxgi1_6::IDXGIAdapter4::uuidof(),
|
||||
adapter4.mut_void(),
|
||||
)
|
||||
};
|
||||
|
||||
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
||||
break;
|
||||
}
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("Failed enumerating adapters: {}", err);
|
||||
break;
|
||||
}
|
||||
|
||||
adapters.push(native::DxgiAdapter::Adapter4(adapter4));
|
||||
continue;
|
||||
}
|
||||
|
||||
profiling::scope!("IDXGIFactory1::EnumAdapters1");
|
||||
let mut adapter1 = native::WeakPtr::<dxgi::IDXGIAdapter1>::null();
|
||||
let hr = unsafe { factory.EnumAdapters1(cur_index, adapter1.mut_void() as *mut *mut _) };
|
||||
|
||||
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
||||
break;
|
||||
}
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("Failed enumerating adapters: {}", err);
|
||||
break;
|
||||
}
|
||||
|
||||
// Do the most aggressive casts first, skipping Adpater4 as we definitely don't have dxgi1_6.
|
||||
|
||||
// Adapter1 -> Adapter3
|
||||
unsafe {
|
||||
match adapter1.cast::<dxgi1_4::IDXGIAdapter3>().into_result() {
|
||||
Ok(adapter3) => {
|
||||
adapter1.destroy();
|
||||
adapters.push(native::DxgiAdapter::Adapter3(adapter3));
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Failed casting Adapter1 to Adapter3: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adapter1 -> Adapter2
|
||||
unsafe {
|
||||
match adapter1.cast::<dxgi1_2::IDXGIAdapter2>().into_result() {
|
||||
Ok(adapter2) => {
|
||||
adapter1.destroy();
|
||||
adapters.push(native::DxgiAdapter::Adapter2(adapter2));
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Failed casting Adapter1 to Adapter2: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adapters.push(native::DxgiAdapter::Adapter1(adapter1));
|
||||
}
|
||||
|
||||
adapters
|
||||
}
|
||||
|
||||
/// Tries to create a IDXGIFactory6, then a IDXGIFactory4, then a IDXGIFactory2, then a IDXGIFactory1,
|
||||
/// returning the one that succeeds, or if the required_factory_type fails to be
|
||||
/// created.
|
||||
pub fn create_factory(
|
||||
required_factory_type: DxgiFactoryType,
|
||||
instance_flags: crate::InstanceFlags,
|
||||
) -> Result<(native::DxgiLib, native::DxgiFactory), crate::InstanceError> {
|
||||
let lib_dxgi = native::DxgiLib::new().map_err(|_| crate::InstanceError)?;
|
||||
|
||||
let mut factory_flags = native::FactoryCreationFlags::empty();
|
||||
|
||||
if instance_flags.contains(crate::InstanceFlags::VALIDATION) {
|
||||
// The `DXGI_CREATE_FACTORY_DEBUG` flag is only allowed to be passed to
|
||||
// `CreateDXGIFactory2` if the debug interface is actually available. So
|
||||
// we check for whether it exists first.
|
||||
match lib_dxgi.get_debug_interface1() {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(debug_controller) => {
|
||||
unsafe { debug_controller.destroy() };
|
||||
factory_flags |= native::FactoryCreationFlags::DEBUG;
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Unable to enable DXGI debug interface: {}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
log::warn!("Debug interface function for DXGI not found: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Intercept `OutputDebugString` calls
|
||||
super::exception::register_exception_handler();
|
||||
}
|
||||
|
||||
// Try to create IDXGIFactory4
|
||||
let factory4 = match lib_dxgi.create_factory2(factory_flags) {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(factory) => Some(factory),
|
||||
// We hard error here as we _should have_ been able to make a factory4 but couldn't.
|
||||
Err(err) => {
|
||||
log::error!("Failed to create IDXGIFactory4: {}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
},
|
||||
// If we require factory4, hard error.
|
||||
Err(err) if required_factory_type == DxgiFactoryType::Factory4 => {
|
||||
log::error!("IDXGIFactory1 creation function not found: {:?}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
// If we don't print it to info as all win7 will hit this case.
|
||||
Err(err) => {
|
||||
log::info!("IDXGIFactory1 creation function not found: {:?}", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(factory4) = factory4 {
|
||||
// Try to cast the IDXGIFactory4 into IDXGIFactory6
|
||||
let factory6 = unsafe { factory4.cast::<dxgi1_6::IDXGIFactory6>().into_result() };
|
||||
match factory6 {
|
||||
Ok(factory6) => {
|
||||
unsafe {
|
||||
factory4.destroy();
|
||||
}
|
||||
return Ok((lib_dxgi, native::DxgiFactory::Factory6(factory6)));
|
||||
}
|
||||
// If we require factory6, hard error.
|
||||
Err(err) if required_factory_type == DxgiFactoryType::Factory6 => {
|
||||
log::warn!("Failed to cast IDXGIFactory4 to IDXGIFactory6: {:?}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
// If we don't print it to info.
|
||||
Err(err) => {
|
||||
log::info!("Failed to cast IDXGIFactory4 to IDXGIFactory6: {:?}", err);
|
||||
return Ok((lib_dxgi, native::DxgiFactory::Factory4(factory4)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to create IDXGIFactory1
|
||||
let factory1 = match lib_dxgi.create_factory1() {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(factory) => factory,
|
||||
Err(err) => {
|
||||
log::error!("Failed to create IDXGIFactory1: {}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
},
|
||||
// We always require at least factory1, so hard error
|
||||
Err(err) => {
|
||||
log::error!("IDXGIFactory1 creation function not found: {:?}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
};
|
||||
|
||||
// Try to cast the IDXGIFactory1 into IDXGIFactory2
|
||||
let factory2 = unsafe { factory1.cast::<dxgi1_2::IDXGIFactory2>().into_result() };
|
||||
match factory2 {
|
||||
Ok(factory2) => {
|
||||
unsafe {
|
||||
factory1.destroy();
|
||||
}
|
||||
return Ok((lib_dxgi, native::DxgiFactory::Factory2(factory2)));
|
||||
}
|
||||
// If we require factory2, hard error.
|
||||
Err(err) if required_factory_type == DxgiFactoryType::Factory2 => {
|
||||
log::warn!("Failed to cast IDXGIFactory1 to IDXGIFactory2: {:?}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
// If we don't print it to info.
|
||||
Err(err) => {
|
||||
log::info!("Failed to cast IDXGIFactory1 to IDXGIFactory2: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// We tried to create 4 and 2, but only succeeded with 1.
|
||||
Ok((lib_dxgi, native::DxgiFactory::Factory1(factory1)))
|
||||
}
|
4
wgpu-hal/src/auxil/dxgi/mod.rs
Normal file
4
wgpu-hal/src/auxil/dxgi/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod conv;
|
||||
pub mod exception;
|
||||
pub mod factory;
|
||||
pub mod result;
|
42
wgpu-hal/src/auxil/dxgi/result.rs
Normal file
42
wgpu-hal/src/auxil/dxgi/result.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use winapi::shared::winerror;
|
||||
|
||||
pub(crate) trait HResult<O> {
|
||||
fn into_result(self) -> Result<O, Cow<'static, str>>;
|
||||
fn into_device_result(self, description: &str) -> Result<O, crate::DeviceError>;
|
||||
}
|
||||
impl HResult<()> for i32 {
|
||||
fn into_result(self) -> Result<(), Cow<'static, str>> {
|
||||
if self >= 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let description = match self {
|
||||
winerror::E_UNEXPECTED => "unexpected",
|
||||
winerror::E_NOTIMPL => "not implemented",
|
||||
winerror::E_OUTOFMEMORY => "out of memory",
|
||||
winerror::E_INVALIDARG => "invalid argument",
|
||||
_ => return Err(Cow::Owned(format!("0x{:X}", self as u32))),
|
||||
};
|
||||
Err(Cow::Borrowed(description))
|
||||
}
|
||||
fn into_device_result(self, description: &str) -> Result<(), crate::DeviceError> {
|
||||
self.into_result().map_err(|err| {
|
||||
log::error!("{} failed: {}", description, err);
|
||||
if self == winerror::E_OUTOFMEMORY {
|
||||
crate::DeviceError::OutOfMemory
|
||||
} else {
|
||||
crate::DeviceError::Lost
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HResult<T> for (T, i32) {
|
||||
fn into_result(self) -> Result<T, Cow<'static, str>> {
|
||||
self.1.into_result().map(|()| self.0)
|
||||
}
|
||||
fn into_device_result(self, description: &str) -> Result<T, crate::DeviceError> {
|
||||
self.1.into_device_result(description).map(|()| self.0)
|
||||
}
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
#[cfg(any(feature = "dx11", feature = "dx12"))]
|
||||
pub(super) mod dxgi;
|
||||
|
||||
#[cfg(feature = "renderdoc")]
|
||||
pub(super) mod renderdoc;
|
||||
|
||||
|
274
wgpu-hal/src/dx11/adapter.rs
Normal file
274
wgpu-hal/src/dx11/adapter.rs
Normal file
@ -0,0 +1,274 @@
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
use winapi::um::{d3d11, d3dcommon};
|
||||
|
||||
impl crate::Adapter<super::Api> for super::Adapter {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
features: wgt::Features,
|
||||
limits: &wgt::Limits,
|
||||
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn texture_format_capabilities(
|
||||
&self,
|
||||
format: wgt::TextureFormat,
|
||||
) -> crate::TextureFormatCapabilities {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn surface_capabilities(
|
||||
&self,
|
||||
surface: &super::Surface,
|
||||
) -> Option<crate::SurfaceCapabilities> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Adapter {
|
||||
pub(super) fn expose(
|
||||
instance: &super::library::D3D11Lib,
|
||||
adapter: native::DxgiAdapter,
|
||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||
use d3dcommon::{
|
||||
D3D_FEATURE_LEVEL_10_0 as FL10_0, D3D_FEATURE_LEVEL_10_1 as FL10_1,
|
||||
D3D_FEATURE_LEVEL_11_0 as FL11_0, D3D_FEATURE_LEVEL_11_1 as FL11_1,
|
||||
D3D_FEATURE_LEVEL_9_1 as FL9_1, D3D_FEATURE_LEVEL_9_2 as FL9_2,
|
||||
D3D_FEATURE_LEVEL_9_3 as FL9_3,
|
||||
};
|
||||
|
||||
let (device, feature_level) = instance.create_device(adapter)?;
|
||||
|
||||
//
|
||||
// Query Features from d3d11
|
||||
//
|
||||
|
||||
let d3d9_features = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D9_OPTIONS1>(
|
||||
d3d11::D3D11_FEATURE_D3D9_OPTIONS1,
|
||||
)
|
||||
};
|
||||
|
||||
let d3d10_features = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS>(
|
||||
d3d11::D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS,
|
||||
)
|
||||
};
|
||||
|
||||
let d3d11_features = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D11_OPTIONS>(
|
||||
d3d11::D3D11_FEATURE_D3D11_OPTIONS,
|
||||
)
|
||||
};
|
||||
|
||||
let d3d11_features1 = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D11_OPTIONS1>(
|
||||
d3d11::D3D11_FEATURE_D3D11_OPTIONS1,
|
||||
)
|
||||
};
|
||||
|
||||
let d3d11_features2 = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D11_OPTIONS2>(
|
||||
d3d11::D3D11_FEATURE_D3D11_OPTIONS2,
|
||||
)
|
||||
};
|
||||
|
||||
let d3d11_features3 = unsafe {
|
||||
device.check_feature_support::<d3d11::D3D11_FEATURE_DATA_D3D11_OPTIONS3>(
|
||||
d3d11::D3D11_FEATURE_D3D11_OPTIONS3,
|
||||
)
|
||||
};
|
||||
|
||||
//
|
||||
// Fill out features and downlevel features
|
||||
//
|
||||
// TODO(cwfitzgerald): Needed downlevel features: 3D dispatch
|
||||
|
||||
let mut features = wgt::Features::DEPTH_CLIP_CONTROL
|
||||
| wgt::Features::PUSH_CONSTANTS
|
||||
| wgt::Features::POLYGON_MODE_LINE
|
||||
| wgt::Features::CLEAR_TEXTURE
|
||||
| wgt::Features::TEXTURE_FORMAT_16BIT_NORM
|
||||
| wgt::Features::ADDRESS_MODE_CLAMP_TO_ZERO;
|
||||
let mut downlevel =
|
||||
wgt::DownlevelFlags::BASE_VERTEX | wgt::DownlevelFlags::READ_ONLY_DEPTH_STENCIL;
|
||||
|
||||
// Features from queries
|
||||
downlevel.set(
|
||||
wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES,
|
||||
d3d9_features.FullNonPow2TextureSupported == 1,
|
||||
);
|
||||
downlevel.set(
|
||||
wgt::DownlevelFlags::COMPUTE_SHADERS,
|
||||
d3d10_features.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x == 1,
|
||||
);
|
||||
|
||||
// Features from feature level
|
||||
if feature_level >= FL9_2 {
|
||||
downlevel |= wgt::DownlevelFlags::INDEPENDENT_BLEND;
|
||||
// formally FL9_1 supports aniso 2, but we don't support that level of distinction
|
||||
downlevel |= wgt::DownlevelFlags::ANISOTROPIC_FILTERING;
|
||||
}
|
||||
|
||||
if feature_level >= FL9_3 {
|
||||
downlevel |= wgt::DownlevelFlags::COMPARISON_SAMPLERS;
|
||||
}
|
||||
|
||||
if feature_level >= FL10_0 {
|
||||
downlevel |= wgt::DownlevelFlags::INDEPENDENT_BLEND;
|
||||
downlevel |= wgt::DownlevelFlags::FRAGMENT_STORAGE;
|
||||
downlevel |= wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE;
|
||||
features |= wgt::Features::DEPTH_CLIP_CONTROL;
|
||||
features |= wgt::Features::TIMESTAMP_QUERY;
|
||||
features |= wgt::Features::PIPELINE_STATISTICS_QUERY;
|
||||
}
|
||||
|
||||
if feature_level >= FL10_1 {
|
||||
downlevel |= wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES;
|
||||
}
|
||||
|
||||
if feature_level >= FL11_0 {
|
||||
downlevel |= wgt::DownlevelFlags::INDIRECT_EXECUTION;
|
||||
features |= wgt::Features::TEXTURE_COMPRESSION_BC;
|
||||
}
|
||||
|
||||
if feature_level >= FL11_1 {
|
||||
downlevel |= wgt::DownlevelFlags::VERTEX_STORAGE;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill out limits and alignments
|
||||
//
|
||||
|
||||
let max_texture_dimension_2d = match feature_level {
|
||||
FL9_1 | FL9_2 => 2048,
|
||||
FL9_3 => 4096,
|
||||
FL10_0 | FL10_1 => 8192,
|
||||
_ => d3d11::D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION,
|
||||
};
|
||||
|
||||
let max_texture_dimension_3d = match feature_level {
|
||||
FL9_1..=FL9_3 => 256,
|
||||
_ => d3d11::D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION,
|
||||
};
|
||||
let max_vertex_buffers = match feature_level {
|
||||
FL9_1..=FL9_3 => 16,
|
||||
_ => 32,
|
||||
};
|
||||
let max_compute_workgroup_storage_size = match feature_level {
|
||||
FL9_1..=FL9_3 => 0,
|
||||
FL10_0 | FL10_1 => 4096 * 4, // This doesn't have an equiv SM4 constant :\
|
||||
_ => d3d11::D3D11_CS_TGSM_REGISTER_COUNT * 4,
|
||||
};
|
||||
let max_workgroup_size_xy = match feature_level {
|
||||
FL9_1..=FL9_3 => 0,
|
||||
FL10_0 | FL10_1 => d3d11::D3D11_CS_4_X_THREAD_GROUP_MAX_X,
|
||||
_ => d3d11::D3D11_CS_THREAD_GROUP_MAX_X,
|
||||
};
|
||||
let max_workgroup_size_z = match feature_level {
|
||||
FL9_1..=FL9_3 => 0,
|
||||
FL10_0 | FL10_1 => 1,
|
||||
_ => d3d11::D3D11_CS_THREAD_GROUP_MAX_Z,
|
||||
};
|
||||
// let max_workgroup_count_z = match feature_level {
|
||||
// FL9_1..=FL9_3 => 0,
|
||||
// FL10_0 | FL10_1 => 1,
|
||||
// _ => d3d11::D3D11_CS_THREAD_GROUP_MAX_Z,
|
||||
// };
|
||||
|
||||
let max_sampled_textures = d3d11::D3D11_COMMONSHADER_INPUT_RESOURCE_REGISTER_COUNT;
|
||||
let max_samplers = d3d11::D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
|
||||
let max_constant_buffers = d3d11::D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1;
|
||||
let max_uavs = if device.as_device1().is_some() {
|
||||
d3d11::D3D11_1_UAV_SLOT_COUNT
|
||||
} else {
|
||||
d3d11::D3D11_PS_CS_UAV_REGISTER_COUNT
|
||||
};
|
||||
let max_output_registers = d3d11::D3D11_VS_OUTPUT_REGISTER_COMPONENTS;
|
||||
let max_compute_invocations_per_workgroup =
|
||||
d3d11::D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
|
||||
let max_compute_workgroups_per_dimension =
|
||||
d3d11::D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
|
||||
|
||||
let limits = wgt::Limits {
|
||||
max_texture_dimension_1d: max_texture_dimension_2d,
|
||||
max_texture_dimension_2d: max_texture_dimension_2d,
|
||||
max_texture_dimension_3d: max_texture_dimension_3d,
|
||||
max_texture_array_layers: max_texture_dimension_3d,
|
||||
max_bind_groups: u32::MAX,
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout: max_constant_buffers,
|
||||
max_dynamic_storage_buffers_per_pipeline_layout: 0,
|
||||
max_sampled_textures_per_shader_stage: max_sampled_textures,
|
||||
max_samplers_per_shader_stage: max_samplers,
|
||||
max_storage_buffers_per_shader_stage: max_uavs,
|
||||
max_storage_textures_per_shader_stage: max_uavs,
|
||||
max_uniform_buffers_per_shader_stage: max_constant_buffers,
|
||||
max_uniform_buffer_binding_size: 1 << 16,
|
||||
max_storage_buffer_binding_size: u32::MAX,
|
||||
max_vertex_buffers: max_vertex_buffers,
|
||||
max_vertex_attributes: max_vertex_buffers,
|
||||
max_vertex_buffer_array_stride: u32::MAX,
|
||||
max_push_constant_size: 1 << 16,
|
||||
min_uniform_buffer_offset_alignment: 256,
|
||||
min_storage_buffer_offset_alignment: 1,
|
||||
max_inter_stage_shader_components: max_output_registers,
|
||||
max_compute_workgroup_storage_size,
|
||||
max_compute_invocations_per_workgroup,
|
||||
max_compute_workgroup_size_x: max_workgroup_size_xy,
|
||||
max_compute_workgroup_size_y: max_workgroup_size_xy,
|
||||
max_compute_workgroup_size_z: max_workgroup_size_z,
|
||||
max_compute_workgroups_per_dimension,
|
||||
};
|
||||
|
||||
//
|
||||
// Other capabilities
|
||||
//
|
||||
|
||||
let shader_model = match feature_level {
|
||||
FL9_1..=FL9_3 => wgt::ShaderModel::Sm2,
|
||||
FL10_0 | FL10_1 => wgt::ShaderModel::Sm4,
|
||||
_ => wgt::ShaderModel::Sm5,
|
||||
};
|
||||
|
||||
let device_info = wgt::AdapterInfo {
|
||||
name: String::new(),
|
||||
vendor: 0,
|
||||
device: 0,
|
||||
device_type: match d3d11_features2.UnifiedMemoryArchitecture {
|
||||
0 => wgt::DeviceType::DiscreteGpu,
|
||||
1 => wgt::DeviceType::IntegratedGpu,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
backend: wgt::Backend::Dx11,
|
||||
};
|
||||
|
||||
//
|
||||
// Build up the structs
|
||||
//
|
||||
|
||||
let api_adapter = super::Adapter { device };
|
||||
|
||||
let alignments = crate::Alignments {
|
||||
buffer_copy_offset: NonZeroU64::new(1).unwrap(), // todo
|
||||
buffer_copy_pitch: NonZeroU64::new(1).unwrap(), // todo
|
||||
};
|
||||
|
||||
let capabilities = crate::Capabilities {
|
||||
limits,
|
||||
alignments,
|
||||
downlevel: wgt::DownlevelCapabilities {
|
||||
flags: downlevel,
|
||||
limits: wgt::DownlevelLimits {},
|
||||
shader_model,
|
||||
},
|
||||
};
|
||||
|
||||
Some(crate::ExposedAdapter {
|
||||
adapter: api_adapter,
|
||||
info: device_info,
|
||||
features,
|
||||
capabilities,
|
||||
})
|
||||
}
|
||||
}
|
268
wgpu-hal/src/dx11/command.rs
Normal file
268
wgpu-hal/src/dx11/command.rs
Normal file
@ -0,0 +1,268 @@
|
||||
impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn discard_encoding(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn end_encoding(&mut self) -> Result<super::CommandBuffer, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn reset_all<I>(&mut self, command_buffers: I)
|
||||
where
|
||||
I: Iterator<Item = super::CommandBuffer>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
|
||||
where
|
||||
T: Iterator<Item = crate::BufferBarrier<'a, super::Api>>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
|
||||
where
|
||||
T: Iterator<Item = crate::TextureBarrier<'a, super::Api>>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn clear_buffer(&mut self, buffer: &super::Buffer, range: crate::MemoryRange) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn copy_buffer_to_buffer<T>(
|
||||
&mut self,
|
||||
src: &super::Buffer,
|
||||
dst: &super::Buffer,
|
||||
regions: T,
|
||||
) where
|
||||
T: Iterator<Item = crate::BufferCopy>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn copy_texture_to_texture<T>(
|
||||
&mut self,
|
||||
src: &super::Texture,
|
||||
src_usage: crate::TextureUses,
|
||||
dst: &super::Texture,
|
||||
regions: T,
|
||||
) where
|
||||
T: Iterator<Item = crate::TextureCopy>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn copy_buffer_to_texture<T>(
|
||||
&mut self,
|
||||
src: &super::Buffer,
|
||||
dst: &super::Texture,
|
||||
regions: T,
|
||||
) where
|
||||
T: Iterator<Item = crate::BufferTextureCopy>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn copy_texture_to_buffer<T>(
|
||||
&mut self,
|
||||
src: &super::Texture,
|
||||
src_usage: crate::TextureUses,
|
||||
dst: &super::Buffer,
|
||||
regions: T,
|
||||
) where
|
||||
T: Iterator<Item = crate::BufferTextureCopy>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_bind_group(
|
||||
&mut self,
|
||||
layout: &super::PipelineLayout,
|
||||
index: u32,
|
||||
group: &super::BindGroup,
|
||||
dynamic_offsets: &[wgt::DynamicOffset],
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_push_constants(
|
||||
&mut self,
|
||||
layout: &super::PipelineLayout,
|
||||
stages: wgt::ShaderStages,
|
||||
offset: u32,
|
||||
data: &[u32],
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn insert_debug_marker(&mut self, label: &str) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn begin_debug_marker(&mut self, group_label: &str) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn end_debug_marker(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn begin_query(&mut self, set: &super::QuerySet, index: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn end_query(&mut self, set: &super::QuerySet, index: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn reset_queries(&mut self, set: &super::QuerySet, range: std::ops::Range<u32>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn copy_query_results(
|
||||
&mut self,
|
||||
set: &super::QuerySet,
|
||||
range: std::ops::Range<u32>,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
stride: wgt::BufferSize,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn end_render_pass(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_render_pipeline(&mut self, pipeline: &super::RenderPipeline) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_index_buffer<'a>(
|
||||
&mut self,
|
||||
binding: crate::BufferBinding<'a, super::Api>,
|
||||
format: wgt::IndexFormat,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_vertex_buffer<'a>(
|
||||
&mut self,
|
||||
index: u32,
|
||||
binding: crate::BufferBinding<'a, super::Api>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_viewport(&mut self, rect: &crate::Rect<f32>, depth_range: std::ops::Range<f32>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect<u32>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_stencil_reference(&mut self, value: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw(
|
||||
&mut self,
|
||||
start_vertex: u32,
|
||||
vertex_count: u32,
|
||||
start_instance: u32,
|
||||
instance_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw_indexed(
|
||||
&mut self,
|
||||
start_index: u32,
|
||||
index_count: u32,
|
||||
base_vertex: i32,
|
||||
start_instance: u32,
|
||||
instance_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw_indirect(
|
||||
&mut self,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw_indexed_indirect(
|
||||
&mut self,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
draw_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw_indirect_count(
|
||||
&mut self,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
count_buffer: &super::Buffer,
|
||||
count_offset: wgt::BufferAddress,
|
||||
max_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn draw_indexed_indirect_count(
|
||||
&mut self,
|
||||
buffer: &super::Buffer,
|
||||
offset: wgt::BufferAddress,
|
||||
count_buffer: &super::Buffer,
|
||||
count_offset: wgt::BufferAddress,
|
||||
max_count: u32,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn end_compute_pass(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn dispatch(&mut self, count: [u32; 3]) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn dispatch_indirect(&mut self, buffer: &super::Buffer, offset: wgt::BufferAddress) {
|
||||
todo!()
|
||||
}
|
||||
}
|
240
wgpu-hal/src/dx11/device.rs
Normal file
240
wgpu-hal/src/dx11/device.rs
Normal file
@ -0,0 +1,240 @@
|
||||
use std::{ffi::c_void, mem};
|
||||
|
||||
use winapi::um::d3d11;
|
||||
|
||||
use crate::auxil::dxgi::result::HResult;
|
||||
|
||||
impl crate::Device<super::Api> for super::Device {
|
||||
unsafe fn exit(self, queue: super::Queue) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_buffer(
|
||||
&self,
|
||||
desc: &crate::BufferDescriptor,
|
||||
) -> Result<super::Buffer, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn map_buffer(
|
||||
&self,
|
||||
buffer: &super::Buffer,
|
||||
range: crate::MemoryRange,
|
||||
) -> Result<crate::BufferMapping, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn unmap_buffer(&self, buffer: &super::Buffer) -> Result<(), crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn flush_mapped_ranges<I>(&self, buffer: &super::Buffer, ranges: I)
|
||||
where
|
||||
I: Iterator<Item = crate::MemoryRange>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &super::Buffer, ranges: I)
|
||||
where
|
||||
I: Iterator<Item = crate::MemoryRange>,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_texture(
|
||||
&self,
|
||||
desc: &crate::TextureDescriptor,
|
||||
) -> Result<super::Texture, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_texture(&self, texture: super::Texture) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_texture_view(
|
||||
&self,
|
||||
texture: &super::Texture,
|
||||
desc: &crate::TextureViewDescriptor,
|
||||
) -> Result<super::TextureView, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_sampler(
|
||||
&self,
|
||||
desc: &crate::SamplerDescriptor,
|
||||
) -> Result<super::Sampler, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_command_encoder(
|
||||
&self,
|
||||
desc: &crate::CommandEncoderDescriptor<super::Api>,
|
||||
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_command_encoder(&self, pool: super::CommandEncoder) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_bind_group_layout(
|
||||
&self,
|
||||
desc: &crate::BindGroupLayoutDescriptor,
|
||||
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_bind_group_layout(&self, bg_layout: super::BindGroupLayout) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_pipeline_layout(
|
||||
&self,
|
||||
desc: &crate::PipelineLayoutDescriptor<super::Api>,
|
||||
) -> Result<super::PipelineLayout, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_bind_group(
|
||||
&self,
|
||||
desc: &crate::BindGroupDescriptor<super::Api>,
|
||||
) -> Result<super::BindGroup, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_shader_module(
|
||||
&self,
|
||||
desc: &crate::ShaderModuleDescriptor,
|
||||
shader: crate::ShaderInput,
|
||||
) -> Result<super::ShaderModule, crate::ShaderError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_render_pipeline(
|
||||
&self,
|
||||
desc: &crate::RenderPipelineDescriptor<super::Api>,
|
||||
) -> Result<super::RenderPipeline, crate::PipelineError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_compute_pipeline(
|
||||
&self,
|
||||
desc: &crate::ComputePipelineDescriptor<super::Api>,
|
||||
) -> Result<super::ComputePipeline, crate::PipelineError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_query_set(
|
||||
&self,
|
||||
desc: &wgt::QuerySetDescriptor<crate::Label>,
|
||||
) -> Result<super::QuerySet, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_fence(&self, fence: super::Fence) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn get_fence_value(
|
||||
&self,
|
||||
fence: &super::Fence,
|
||||
) -> Result<crate::FenceValue, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn wait(
|
||||
&self,
|
||||
fence: &super::Fence,
|
||||
value: crate::FenceValue,
|
||||
timeout_ms: u32,
|
||||
) -> Result<bool, crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn start_capture(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn stop_capture(&self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Queue<super::Api> for super::Queue {
|
||||
unsafe fn submit(
|
||||
&mut self,
|
||||
command_buffers: &[&super::CommandBuffer],
|
||||
signal_fence: Option<(&mut super::Fence, crate::FenceValue)>,
|
||||
) -> Result<(), crate::DeviceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn present(
|
||||
&mut self,
|
||||
surface: &mut super::Surface,
|
||||
texture: super::SurfaceTexture,
|
||||
) -> Result<(), crate::SurfaceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn get_timestamp_period(&self) -> f32 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl super::D3D11Device {
|
||||
#[allow(trivial_casts)] // come on
|
||||
pub unsafe fn check_feature_support<T>(&self, feature: d3d11::D3D11_FEATURE) -> T {
|
||||
let mut value = mem::zeroed::<T>();
|
||||
let ret = self.CheckFeatureSupport(
|
||||
feature,
|
||||
&mut value as *mut T as *mut c_void,
|
||||
mem::size_of::<T>() as u32,
|
||||
);
|
||||
assert_eq!(ret.into_result(), Ok(()));
|
||||
|
||||
value
|
||||
}
|
||||
}
|
47
wgpu-hal/src/dx11/instance.rs
Normal file
47
wgpu-hal/src/dx11/instance.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use crate::auxil;
|
||||
|
||||
impl crate::Instance<super::Api> for super::Instance {
|
||||
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
|
||||
let enable_dx11 = match std::env::var("WGPU_UNSTABLE_DX11_BACKEND") {
|
||||
Ok(string) => string == "1" || string == "true",
|
||||
Err(_) => false,
|
||||
};
|
||||
|
||||
if !enable_dx11 {
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
|
||||
let lib_d3d11 = super::library::D3D11Lib::new().ok_or(crate::InstanceError)?;
|
||||
|
||||
let (lib_dxgi, factory) = auxil::dxgi::factory::create_factory(
|
||||
auxil::dxgi::factory::DxgiFactoryType::Factory1,
|
||||
desc.flags,
|
||||
)?;
|
||||
|
||||
Ok(super::Instance {
|
||||
lib_d3d11,
|
||||
lib_dxgi,
|
||||
factory,
|
||||
})
|
||||
}
|
||||
|
||||
unsafe fn create_surface(
|
||||
&self,
|
||||
rwh: &impl raw_window_handle::HasRawWindowHandle,
|
||||
) -> Result<super::Surface, crate::InstanceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn destroy_surface(&self, surface: super::Surface) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn enumerate_adapters(&self) -> Vec<crate::ExposedAdapter<super::Api>> {
|
||||
let adapters = auxil::dxgi::factory::enumerate_adapters(self.factory);
|
||||
|
||||
adapters
|
||||
.into_iter()
|
||||
.filter_map(|adapter| super::Adapter::expose(&self.lib_d3d11, adapter))
|
||||
.collect()
|
||||
}
|
||||
}
|
144
wgpu-hal/src/dx11/library.rs
Normal file
144
wgpu-hal/src/dx11/library.rs
Normal file
@ -0,0 +1,144 @@
|
||||
use std::ptr;
|
||||
|
||||
use winapi::{
|
||||
shared::{
|
||||
dxgi,
|
||||
minwindef::{HMODULE, UINT},
|
||||
winerror,
|
||||
},
|
||||
um::{d3d11, d3d11_1, d3d11_2, d3dcommon},
|
||||
};
|
||||
|
||||
use crate::auxil::dxgi::result::HResult;
|
||||
|
||||
type D3D11CreateDeviceFun = unsafe extern "system" fn(
|
||||
*mut dxgi::IDXGIAdapter,
|
||||
d3dcommon::D3D_DRIVER_TYPE,
|
||||
HMODULE,
|
||||
UINT,
|
||||
*const d3dcommon::D3D_FEATURE_LEVEL,
|
||||
UINT,
|
||||
UINT,
|
||||
*mut *mut d3d11::ID3D11Device,
|
||||
*mut d3dcommon::D3D_FEATURE_LEVEL,
|
||||
*mut *mut d3d11::ID3D11DeviceContext,
|
||||
) -> native::HRESULT;
|
||||
|
||||
pub(super) struct D3D11Lib {
|
||||
// We use the os specific symbol to drop the lifetime parameter.
|
||||
//
|
||||
// SAFETY: we must ensure this outlives the Library.
|
||||
d3d11_create_device: libloading::os::windows::Symbol<D3D11CreateDeviceFun>,
|
||||
|
||||
lib: libloading::Library,
|
||||
}
|
||||
impl D3D11Lib {
|
||||
pub fn new() -> Option<Self> {
|
||||
unsafe {
|
||||
let lib = libloading::Library::new("d3d11.dll").ok()?;
|
||||
|
||||
let d3d11_create_device = lib
|
||||
.get::<D3D11CreateDeviceFun>(b"D3D11CreateDevice")
|
||||
.ok()?
|
||||
.into_raw();
|
||||
|
||||
Some(Self {
|
||||
lib,
|
||||
d3d11_create_device,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_device(
|
||||
&self,
|
||||
adapter: native::DxgiAdapter,
|
||||
) -> Option<(super::D3D11Device, d3dcommon::D3D_FEATURE_LEVEL)> {
|
||||
let feature_levels = [
|
||||
d3dcommon::D3D_FEATURE_LEVEL_11_1,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_11_0,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_10_1,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_10_0,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_9_3,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_9_2,
|
||||
d3dcommon::D3D_FEATURE_LEVEL_9_1,
|
||||
];
|
||||
|
||||
let mut device = native::WeakPtr::<d3d11::ID3D11Device>::null();
|
||||
let mut feature_level: d3dcommon::D3D_FEATURE_LEVEL = 0;
|
||||
|
||||
// We need to try this twice. If the first time fails due to E_INVALIDARG
|
||||
// we are running on a machine without a D3D11.1 runtime, and need to
|
||||
// retry without the feature level 11_1 feature level.
|
||||
//
|
||||
// Why they thought this was a good API, who knows.
|
||||
|
||||
let mut hr = unsafe {
|
||||
(self.d3d11_create_device)(
|
||||
adapter.as_mut_ptr() as *mut _,
|
||||
d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
ptr::null_mut(), // software implementation DLL???
|
||||
0, // flags
|
||||
feature_levels.as_ptr(),
|
||||
feature_levels.len() as u32,
|
||||
d3d11::D3D11_SDK_VERSION,
|
||||
device.mut_self(),
|
||||
&mut feature_level,
|
||||
ptr::null_mut(), // device context
|
||||
)
|
||||
};
|
||||
|
||||
// Try again without FL11_1
|
||||
if hr == winerror::E_INVALIDARG {
|
||||
hr = unsafe {
|
||||
(self.d3d11_create_device)(
|
||||
adapter.as_mut_ptr() as *mut _,
|
||||
d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
ptr::null_mut(), // software implementation DLL???
|
||||
0, // flags
|
||||
feature_levels[1..].as_ptr(),
|
||||
feature_levels[1..].len() as u32,
|
||||
d3d11::D3D11_SDK_VERSION,
|
||||
device.mut_self(),
|
||||
&mut feature_level,
|
||||
ptr::null_mut(), // device context
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Any errors here are real and we should complain about
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("Failed to make a D3D11 device: {}", err);
|
||||
return None;
|
||||
}
|
||||
|
||||
// We always try to upcast in highest -> lowest order
|
||||
|
||||
// Device -> Device2
|
||||
unsafe {
|
||||
match device.cast::<d3d11_2::ID3D11Device2>().into_result() {
|
||||
Ok(device2) => {
|
||||
device.destroy();
|
||||
return Some((super::D3D11Device::Device2(device2), feature_level));
|
||||
}
|
||||
Err(hr) => {
|
||||
log::info!("Failed to cast device to ID3D11Device2: {}", hr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Device -> Device1
|
||||
unsafe {
|
||||
match device.cast::<d3d11_1::ID3D11Device1>().into_result() {
|
||||
Ok(device1) => {
|
||||
device.destroy();
|
||||
return Some((super::D3D11Device::Device1(device1), feature_level));
|
||||
}
|
||||
Err(hr) => {
|
||||
log::info!("Failed to cast device to ID3D11Device1: {}", hr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some((super::D3D11Device::Device(device), feature_level))
|
||||
}
|
||||
}
|
135
wgpu-hal/src/dx11/mod.rs
Normal file
135
wgpu-hal/src/dx11/mod.rs
Normal file
@ -0,0 +1,135 @@
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use winapi::um::{d3d11, d3d11_1, d3d11_2};
|
||||
|
||||
mod adapter;
|
||||
mod command;
|
||||
mod device;
|
||||
mod instance;
|
||||
mod library;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Api;
|
||||
|
||||
impl crate::Api for Api {
|
||||
type Instance = Instance;
|
||||
type Surface = Surface;
|
||||
type Adapter = Adapter;
|
||||
type Device = Device;
|
||||
|
||||
type Queue = Queue;
|
||||
type CommandEncoder = CommandEncoder;
|
||||
type CommandBuffer = CommandBuffer;
|
||||
|
||||
type Buffer = Buffer;
|
||||
type Texture = Texture;
|
||||
type SurfaceTexture = SurfaceTexture;
|
||||
type TextureView = TextureView;
|
||||
type Sampler = Sampler;
|
||||
type QuerySet = QuerySet;
|
||||
type Fence = Fence;
|
||||
|
||||
type BindGroupLayout = BindGroupLayout;
|
||||
type BindGroup = BindGroup;
|
||||
type PipelineLayout = PipelineLayout;
|
||||
type ShaderModule = ShaderModule;
|
||||
type RenderPipeline = RenderPipeline;
|
||||
type ComputePipeline = ComputePipeline;
|
||||
}
|
||||
|
||||
pub struct Instance {
|
||||
lib_d3d11: library::D3D11Lib,
|
||||
lib_dxgi: native::DxgiLib,
|
||||
factory: native::DxgiFactory,
|
||||
}
|
||||
|
||||
unsafe impl Send for Instance {}
|
||||
unsafe impl Sync for Instance {}
|
||||
|
||||
pub struct Surface {}
|
||||
|
||||
pub struct Adapter {
|
||||
device: D3D11Device,
|
||||
}
|
||||
|
||||
unsafe impl Send for Adapter {}
|
||||
unsafe impl Sync for Adapter {}
|
||||
|
||||
native::weak_com_inheritance_chain! {
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
enum D3D11Device {
|
||||
Device(d3d11::ID3D11Device), from_device, as_device, device;
|
||||
Device1(d3d11_1::ID3D11Device1), from_device1, as_device1, unwrap_device1;
|
||||
Device2(d3d11_2::ID3D11Device2), from_device2, as_device2, unwrap_device2;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Device {}
|
||||
|
||||
unsafe impl Send for Device {}
|
||||
unsafe impl Sync for Device {}
|
||||
|
||||
pub struct Queue {}
|
||||
|
||||
pub struct CommandEncoder {}
|
||||
|
||||
pub struct CommandBuffer {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Buffer {}
|
||||
#[derive(Debug)]
|
||||
pub struct Texture {}
|
||||
#[derive(Debug)]
|
||||
pub struct SurfaceTexture {}
|
||||
|
||||
impl std::borrow::Borrow<Texture> for SurfaceTexture {
|
||||
fn borrow(&self) -> &Texture {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TextureView {}
|
||||
#[derive(Debug)]
|
||||
pub struct Sampler {}
|
||||
#[derive(Debug)]
|
||||
pub struct QuerySet {}
|
||||
#[derive(Debug)]
|
||||
pub struct Fence {}
|
||||
#[derive(Debug)]
|
||||
|
||||
pub struct BindGroupLayout {}
|
||||
#[derive(Debug)]
|
||||
pub struct BindGroup {}
|
||||
#[derive(Debug)]
|
||||
pub struct PipelineLayout {}
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderModule {}
|
||||
pub struct RenderPipeline {}
|
||||
pub struct ComputePipeline {}
|
||||
|
||||
impl crate::Surface<Api> for Surface {
|
||||
unsafe fn configure(
|
||||
&mut self,
|
||||
device: &Device,
|
||||
config: &crate::SurfaceConfiguration,
|
||||
) -> Result<(), crate::SurfaceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn unconfigure(&mut self, device: &Device) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn acquire_texture(
|
||||
&mut self,
|
||||
timeout_ms: u32,
|
||||
) -> Result<Option<crate::AcquiredSurfaceTexture<Api>>, crate::SurfaceError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
unsafe fn discard_texture(&mut self, texture: SurfaceTexture) {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
use super::{conv, HResult as _, SurfaceTarget};
|
||||
use crate::{
|
||||
auxil::{self, dxgi::result::HResult as _},
|
||||
dx12::SurfaceTarget,
|
||||
};
|
||||
use std::{mem, sync::Arc, thread};
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_5, minwindef, windef, winerror},
|
||||
@ -40,14 +43,14 @@ impl super::Adapter {
|
||||
|
||||
#[allow(trivial_casts)]
|
||||
pub(super) fn expose(
|
||||
adapter: native::WeakPtr<dxgi1_2::IDXGIAdapter2>,
|
||||
adapter: native::DxgiAdapter,
|
||||
library: &Arc<native::D3D12Lib>,
|
||||
instance_flags: crate::InstanceFlags,
|
||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||
// Create the device so that we can get the capabilities.
|
||||
let device = {
|
||||
profiling::scope!("ID3D12Device::create_device");
|
||||
match library.create_device(adapter, native::FeatureLevel::L11_0) {
|
||||
match library.create_device(*adapter, native::FeatureLevel::L11_0) {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(device) => device,
|
||||
Err(err) => {
|
||||
@ -68,7 +71,7 @@ impl super::Adapter {
|
||||
// Acquire the device information.
|
||||
let mut desc: dxgi1_2::DXGI_ADAPTER_DESC2 = unsafe { mem::zeroed() };
|
||||
unsafe {
|
||||
adapter.GetDesc2(&mut desc);
|
||||
adapter.unwrap_adapter2().GetDesc2(&mut desc);
|
||||
}
|
||||
|
||||
let device_name = {
|
||||
@ -317,7 +320,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
) -> crate::TextureFormatCapabilities {
|
||||
use crate::TextureFormatCapabilities as Tfc;
|
||||
|
||||
let raw_format = conv::map_texture_format(format);
|
||||
let raw_format = auxil::dxgi::conv::map_texture_format(format);
|
||||
let mut data = d3d12::D3D12_FEATURE_DATA_FORMAT_SUPPORT {
|
||||
Format: raw_format,
|
||||
Support1: mem::zeroed(),
|
||||
@ -409,11 +412,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
|
||||
let mut present_modes = vec![wgt::PresentMode::Fifo];
|
||||
#[allow(trivial_casts)]
|
||||
if let Ok(factory5) = surface
|
||||
.factory
|
||||
.cast::<dxgi1_5::IDXGIFactory5>()
|
||||
.into_result()
|
||||
{
|
||||
if let Some(factory5) = surface.factory.as_factory5() {
|
||||
let mut allow_tearing: minwindef::BOOL = minwindef::FALSE;
|
||||
let hr = factory5.CheckFeatureSupport(
|
||||
dxgi1_5::DXGI_FEATURE_PRESENT_ALLOW_TEARING,
|
||||
@ -421,7 +420,6 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
mem::size_of::<minwindef::BOOL>() as _,
|
||||
);
|
||||
|
||||
factory5.destroy();
|
||||
match hr.into_result() {
|
||||
Err(err) => log::warn!("Unable to check for tearing support: {}", err),
|
||||
Ok(()) => present_modes.push(wgt::PresentMode::Immediate),
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::{conv, HResult as _};
|
||||
use crate::auxil::{self, dxgi::result::HResult as _};
|
||||
|
||||
use super::conv;
|
||||
use std::{mem, ops::Range, ptr};
|
||||
use winapi::um::d3d12;
|
||||
|
||||
@ -22,7 +24,7 @@ impl crate::BufferTextureCopy {
|
||||
d3d12::D3D12_PLACED_SUBRESOURCE_FOOTPRINT {
|
||||
Offset: self.buffer_layout.offset,
|
||||
Footprint: d3d12::D3D12_SUBRESOURCE_FOOTPRINT {
|
||||
Format: conv::map_texture_format(format),
|
||||
Format: auxil::dxgi::conv::map_texture_format(format),
|
||||
Width: self.size.width,
|
||||
Height: self
|
||||
.buffer_layout
|
||||
@ -834,7 +836,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
||||
self.list.unwrap().set_index_buffer(
|
||||
binding.resolve_address(),
|
||||
binding.resolve_size() as u32,
|
||||
conv::map_index_format(format),
|
||||
auxil::dxgi::conv::map_index_format(format),
|
||||
);
|
||||
}
|
||||
unsafe fn set_vertex_buffer<'a>(
|
||||
|
@ -1,182 +1,5 @@
|
||||
use std::iter;
|
||||
use winapi::{
|
||||
shared::{dxgi1_2, dxgiformat},
|
||||
um::{d3d12, d3dcommon},
|
||||
};
|
||||
|
||||
pub(super) fn map_texture_format(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
use wgt::TextureFormat as Tf;
|
||||
use winapi::shared::dxgiformat::*;
|
||||
|
||||
match format {
|
||||
Tf::R8Unorm => DXGI_FORMAT_R8_UNORM,
|
||||
Tf::R8Snorm => DXGI_FORMAT_R8_SNORM,
|
||||
Tf::R8Uint => DXGI_FORMAT_R8_UINT,
|
||||
Tf::R8Sint => DXGI_FORMAT_R8_SINT,
|
||||
Tf::R16Uint => DXGI_FORMAT_R16_UINT,
|
||||
Tf::R16Sint => DXGI_FORMAT_R16_SINT,
|
||||
Tf::R16Unorm => DXGI_FORMAT_R16_UNORM,
|
||||
Tf::R16Snorm => DXGI_FORMAT_R16_SNORM,
|
||||
Tf::R16Float => DXGI_FORMAT_R16_FLOAT,
|
||||
Tf::Rg8Unorm => DXGI_FORMAT_R8G8_UNORM,
|
||||
Tf::Rg8Snorm => DXGI_FORMAT_R8G8_SNORM,
|
||||
Tf::Rg8Uint => DXGI_FORMAT_R8G8_UINT,
|
||||
Tf::Rg8Sint => DXGI_FORMAT_R8G8_SINT,
|
||||
Tf::Rg16Unorm => DXGI_FORMAT_R16G16_UNORM,
|
||||
Tf::Rg16Snorm => DXGI_FORMAT_R16G16_SNORM,
|
||||
Tf::R32Uint => DXGI_FORMAT_R32_UINT,
|
||||
Tf::R32Sint => DXGI_FORMAT_R32_SINT,
|
||||
Tf::R32Float => DXGI_FORMAT_R32_FLOAT,
|
||||
Tf::Rg16Uint => DXGI_FORMAT_R16G16_UINT,
|
||||
Tf::Rg16Sint => DXGI_FORMAT_R16G16_SINT,
|
||||
Tf::Rg16Float => DXGI_FORMAT_R16G16_FLOAT,
|
||||
Tf::Rgba8Unorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
Tf::Rgba8UnormSrgb => DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
Tf::Bgra8UnormSrgb => DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
Tf::Rgba8Snorm => DXGI_FORMAT_R8G8B8A8_SNORM,
|
||||
Tf::Bgra8Unorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
Tf::Rgba8Uint => DXGI_FORMAT_R8G8B8A8_UINT,
|
||||
Tf::Rgba8Sint => DXGI_FORMAT_R8G8B8A8_SINT,
|
||||
Tf::Rgb10a2Unorm => DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
Tf::Rg11b10Float => DXGI_FORMAT_R11G11B10_FLOAT,
|
||||
Tf::Rg32Uint => DXGI_FORMAT_R32G32_UINT,
|
||||
Tf::Rg32Sint => DXGI_FORMAT_R32G32_SINT,
|
||||
Tf::Rg32Float => DXGI_FORMAT_R32G32_FLOAT,
|
||||
Tf::Rgba16Uint => DXGI_FORMAT_R16G16B16A16_UINT,
|
||||
Tf::Rgba16Sint => DXGI_FORMAT_R16G16B16A16_SINT,
|
||||
Tf::Rgba16Unorm => DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
Tf::Rgba16Snorm => DXGI_FORMAT_R16G16B16A16_SNORM,
|
||||
Tf::Rgba16Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
Tf::Rgba32Uint => DXGI_FORMAT_R32G32B32A32_UINT,
|
||||
Tf::Rgba32Sint => DXGI_FORMAT_R32G32B32A32_SINT,
|
||||
Tf::Rgba32Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT,
|
||||
Tf::Depth24Plus => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
Tf::Depth24PlusStencil8 => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
Tf::Rgb9e5Ufloat => DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
|
||||
Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM,
|
||||
Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB,
|
||||
Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM,
|
||||
Tf::Bc2RgbaUnormSrgb => DXGI_FORMAT_BC2_UNORM_SRGB,
|
||||
Tf::Bc3RgbaUnorm => DXGI_FORMAT_BC3_UNORM,
|
||||
Tf::Bc3RgbaUnormSrgb => DXGI_FORMAT_BC3_UNORM_SRGB,
|
||||
Tf::Bc4RUnorm => DXGI_FORMAT_BC4_UNORM,
|
||||
Tf::Bc4RSnorm => DXGI_FORMAT_BC4_SNORM,
|
||||
Tf::Bc5RgUnorm => DXGI_FORMAT_BC5_UNORM,
|
||||
Tf::Bc5RgSnorm => DXGI_FORMAT_BC5_SNORM,
|
||||
Tf::Bc6hRgbUfloat => DXGI_FORMAT_BC6H_UF16,
|
||||
Tf::Bc6hRgbSfloat => DXGI_FORMAT_BC6H_SF16,
|
||||
Tf::Bc7RgbaUnorm => DXGI_FORMAT_BC7_UNORM,
|
||||
Tf::Bc7RgbaUnormSrgb => DXGI_FORMAT_BC7_UNORM_SRGB,
|
||||
Tf::Etc2Rgb8Unorm
|
||||
| Tf::Etc2Rgb8UnormSrgb
|
||||
| Tf::Etc2Rgb8A1Unorm
|
||||
| Tf::Etc2Rgb8A1UnormSrgb
|
||||
| Tf::Etc2Rgba8Unorm
|
||||
| Tf::Etc2Rgba8UnormSrgb
|
||||
| Tf::EacR11Unorm
|
||||
| Tf::EacR11Snorm
|
||||
| Tf::EacRg11Unorm
|
||||
| Tf::EacRg11Snorm => unreachable!(),
|
||||
Tf::Astc {
|
||||
block: _,
|
||||
channel: _,
|
||||
} => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
//Note: DXGI doesn't allow sRGB format on the swapchain,
|
||||
// but creating RTV of swapchain buffers with sRGB works.
|
||||
pub fn map_texture_format_nosrgb(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Bgra8UnormSrgb => dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
wgt::TextureFormat::Rgba8UnormSrgb => dxgiformat::DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
_ => map_texture_format(format),
|
||||
}
|
||||
}
|
||||
|
||||
//Note: SRV and UAV can't use the depth formats directly
|
||||
//TODO: stencil views?
|
||||
pub fn map_texture_format_nodepth(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_FLOAT,
|
||||
wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
|
||||
dxgiformat::DXGI_FORMAT_R24_UNORM_X8_TYPELESS
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(
|
||||
crate::FormatAspects::from(format),
|
||||
crate::FormatAspects::COLOR
|
||||
);
|
||||
map_texture_format(format)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_texture_format_depth_typeless(format: wgt::TextureFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::TextureFormat::Depth32Float => dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
wgt::TextureFormat::Depth24Plus | wgt::TextureFormat::Depth24PlusStencil8 => {
|
||||
dxgiformat::DXGI_FORMAT_R24G8_TYPELESS
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_index_format(format: wgt::IndexFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
match format {
|
||||
wgt::IndexFormat::Uint16 => dxgiformat::DXGI_FORMAT_R16_UINT,
|
||||
wgt::IndexFormat::Uint32 => dxgiformat::DXGI_FORMAT_R32_UINT,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_vertex_format(format: wgt::VertexFormat) -> dxgiformat::DXGI_FORMAT {
|
||||
use wgt::VertexFormat as Vf;
|
||||
use winapi::shared::dxgiformat::*;
|
||||
|
||||
match format {
|
||||
Vf::Unorm8x2 => DXGI_FORMAT_R8G8_UNORM,
|
||||
Vf::Snorm8x2 => DXGI_FORMAT_R8G8_SNORM,
|
||||
Vf::Uint8x2 => DXGI_FORMAT_R8G8_UINT,
|
||||
Vf::Sint8x2 => DXGI_FORMAT_R8G8_SINT,
|
||||
Vf::Unorm8x4 => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
Vf::Snorm8x4 => DXGI_FORMAT_R8G8B8A8_SNORM,
|
||||
Vf::Uint8x4 => DXGI_FORMAT_R8G8B8A8_UINT,
|
||||
Vf::Sint8x4 => DXGI_FORMAT_R8G8B8A8_SINT,
|
||||
Vf::Unorm16x2 => DXGI_FORMAT_R16G16_UNORM,
|
||||
Vf::Snorm16x2 => DXGI_FORMAT_R16G16_SNORM,
|
||||
Vf::Uint16x2 => DXGI_FORMAT_R16G16_UINT,
|
||||
Vf::Sint16x2 => DXGI_FORMAT_R16G16_SINT,
|
||||
Vf::Float16x2 => DXGI_FORMAT_R16G16_FLOAT,
|
||||
Vf::Unorm16x4 => DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
Vf::Snorm16x4 => DXGI_FORMAT_R16G16B16A16_SNORM,
|
||||
Vf::Uint16x4 => DXGI_FORMAT_R16G16B16A16_UINT,
|
||||
Vf::Sint16x4 => DXGI_FORMAT_R16G16B16A16_SINT,
|
||||
Vf::Float16x4 => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
Vf::Uint32 => DXGI_FORMAT_R32_UINT,
|
||||
Vf::Sint32 => DXGI_FORMAT_R32_SINT,
|
||||
Vf::Float32 => DXGI_FORMAT_R32_FLOAT,
|
||||
Vf::Uint32x2 => DXGI_FORMAT_R32G32_UINT,
|
||||
Vf::Sint32x2 => DXGI_FORMAT_R32G32_SINT,
|
||||
Vf::Float32x2 => DXGI_FORMAT_R32G32_FLOAT,
|
||||
Vf::Uint32x3 => DXGI_FORMAT_R32G32B32_UINT,
|
||||
Vf::Sint32x3 => DXGI_FORMAT_R32G32B32_SINT,
|
||||
Vf::Float32x3 => DXGI_FORMAT_R32G32B32_FLOAT,
|
||||
Vf::Uint32x4 => DXGI_FORMAT_R32G32B32A32_UINT,
|
||||
Vf::Sint32x4 => DXGI_FORMAT_R32G32B32A32_SINT,
|
||||
Vf::Float32x4 => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_acomposite_alpha_mode(mode: crate::CompositeAlphaMode) -> dxgi1_2::DXGI_ALPHA_MODE {
|
||||
use crate::CompositeAlphaMode as Cam;
|
||||
match mode {
|
||||
Cam::Opaque => dxgi1_2::DXGI_ALPHA_MODE_IGNORE,
|
||||
Cam::PreMultiplied => dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
|
||||
Cam::PostMultiplied => dxgi1_2::DXGI_ALPHA_MODE_STRAIGHT,
|
||||
}
|
||||
}
|
||||
use winapi::um::{d3d12, d3dcommon};
|
||||
|
||||
pub fn map_buffer_usage_to_resource_flags(usage: crate::BufferUses) -> d3d12::D3D12_RESOURCE_FLAGS {
|
||||
let mut flags = 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::HResult as _;
|
||||
use crate::auxil::dxgi::result::HResult as _;
|
||||
use bit_set::BitSet;
|
||||
use parking_lot::Mutex;
|
||||
use range_alloc::RangeAllocator;
|
||||
|
@ -1,6 +1,9 @@
|
||||
use crate::FormatAspects;
|
||||
use crate::{
|
||||
auxil::{self, dxgi::result::HResult as _},
|
||||
FormatAspects,
|
||||
};
|
||||
|
||||
use super::{conv, descriptor, view, HResult as _};
|
||||
use super::{conv, descriptor, view};
|
||||
use parking_lot::Mutex;
|
||||
use std::{ffi, mem, num::NonZeroU32, ptr, slice, sync::Arc};
|
||||
use winapi::{
|
||||
@ -432,13 +435,13 @@ impl crate::Device<super::Api> for super::Device {
|
||||
| crate::TextureUses::STORAGE_READ
|
||||
| crate::TextureUses::STORAGE_WRITE,
|
||||
) {
|
||||
conv::map_texture_format(desc.format)
|
||||
auxil::dxgi::conv::map_texture_format(desc.format)
|
||||
} else {
|
||||
// This branch is needed if it's a depth texture, and it's ever needed to be viewed as SRV or UAV,
|
||||
// because then we'd create a non-depth format view of it.
|
||||
// Note: we can skip this branch if
|
||||
// `D3D12_FEATURE_D3D12_OPTIONS3::CastingFullyTypedFormatSupported`
|
||||
conv::map_texture_format_depth_typeless(desc.format)
|
||||
auxil::dxgi::conv::map_texture_format_depth_typeless(desc.format)
|
||||
},
|
||||
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
|
||||
Count: desc.sample_count,
|
||||
@ -1249,7 +1252,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
input_element_descs.push(d3d12::D3D12_INPUT_ELEMENT_DESC {
|
||||
SemanticName: NAGA_LOCATION_SEMANTIC.as_ptr() as *const _,
|
||||
SemanticIndex: attribute.shader_location,
|
||||
Format: conv::map_vertex_format(attribute.format),
|
||||
Format: auxil::dxgi::conv::map_vertex_format(attribute.format),
|
||||
InputSlot: i as u32,
|
||||
AlignedByteOffset: attribute.offset as u32,
|
||||
InputSlotClass: slot_class,
|
||||
@ -1261,7 +1264,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
let mut rtv_formats = [dxgiformat::DXGI_FORMAT_UNKNOWN;
|
||||
d3d12::D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT as usize];
|
||||
for (rtv_format, ct) in rtv_formats.iter_mut().zip(desc.color_targets) {
|
||||
*rtv_format = conv::map_texture_format(ct.format);
|
||||
*rtv_format = auxil::dxgi::conv::map_texture_format(ct.format);
|
||||
}
|
||||
|
||||
let bias = desc
|
||||
@ -1350,7 +1353,7 @@ impl crate::Device<super::Api> for super::Device {
|
||||
.depth_stencil
|
||||
.as_ref()
|
||||
.map_or(dxgiformat::DXGI_FORMAT_UNKNOWN, |ds| {
|
||||
conv::map_texture_format(ds.format)
|
||||
auxil::dxgi::conv::map_texture_format(ds.format)
|
||||
}),
|
||||
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
|
||||
Count: desc.multisample.count,
|
||||
|
@ -1,81 +1,11 @@
|
||||
use super::{HResult as _, SurfaceTarget};
|
||||
use std::{borrow::Cow, slice, sync::Arc};
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_6, winerror},
|
||||
um::{errhandlingapi, winnt},
|
||||
vc::excpt,
|
||||
Interface,
|
||||
};
|
||||
|
||||
const MESSAGE_PREFIXES: &[(&str, log::Level)] = &[
|
||||
("CORRUPTION", log::Level::Error),
|
||||
("ERROR", log::Level::Error),
|
||||
("WARNING", log::Level::Warn),
|
||||
("INFO", log::Level::Info),
|
||||
("MESSAGE", log::Level::Debug),
|
||||
];
|
||||
|
||||
unsafe extern "system" fn output_debug_string_handler(
|
||||
exception_info: *mut winnt::EXCEPTION_POINTERS,
|
||||
) -> i32 {
|
||||
// See https://stackoverflow.com/a/41480827
|
||||
let record = &*(*exception_info).ExceptionRecord;
|
||||
if record.NumberParameters != 2 {
|
||||
return excpt::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
let message = match record.ExceptionCode {
|
||||
winnt::DBG_PRINTEXCEPTION_C => String::from_utf8_lossy(slice::from_raw_parts(
|
||||
record.ExceptionInformation[1] as *const u8,
|
||||
record.ExceptionInformation[0],
|
||||
)),
|
||||
winnt::DBG_PRINTEXCEPTION_WIDE_C => {
|
||||
Cow::Owned(String::from_utf16_lossy(slice::from_raw_parts(
|
||||
record.ExceptionInformation[1] as *const u16,
|
||||
record.ExceptionInformation[0],
|
||||
)))
|
||||
}
|
||||
_ => return excpt::EXCEPTION_CONTINUE_SEARCH,
|
||||
};
|
||||
|
||||
let message = match message.strip_prefix("D3D12 ") {
|
||||
Some(msg) => msg
|
||||
.trim_end_matches("\n\0")
|
||||
.trim_end_matches("[ STATE_CREATION WARNING #0: UNKNOWN]"),
|
||||
None => return excpt::EXCEPTION_CONTINUE_SEARCH,
|
||||
};
|
||||
|
||||
let (message, level) = match MESSAGE_PREFIXES
|
||||
.iter()
|
||||
.find(|&&(prefix, _)| message.starts_with(prefix))
|
||||
{
|
||||
Some(&(prefix, level)) => (&message[prefix.len() + 2..], level),
|
||||
None => (message, log::Level::Debug),
|
||||
};
|
||||
|
||||
if level == log::Level::Warn && message.contains("#82") {
|
||||
// This is are useless spammy warnings (#820, #821):
|
||||
// "The application did not pass any clear value to resource creation"
|
||||
return excpt::EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
let _ = std::panic::catch_unwind(|| {
|
||||
log::log!(level, "{}", message);
|
||||
});
|
||||
|
||||
if cfg!(debug_assertions) && level == log::Level::Error {
|
||||
// Set canary and continue
|
||||
crate::VALIDATION_CANARY.set();
|
||||
}
|
||||
|
||||
excpt::EXCEPTION_CONTINUE_EXECUTION
|
||||
}
|
||||
use super::SurfaceTarget;
|
||||
use crate::auxil::{self, dxgi::result::HResult as _};
|
||||
use std::sync::Arc;
|
||||
|
||||
impl Drop for super::Instance {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.factory.destroy();
|
||||
errhandlingapi::RemoveVectoredExceptionHandler(output_debug_string_handler as *mut _);
|
||||
}
|
||||
unsafe { self.factory.destroy() };
|
||||
crate::auxil::dxgi::exception::unregister_exception_handler();
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,9 +13,6 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
|
||||
let lib_main = native::D3D12Lib::new().map_err(|_| crate::InstanceError)?;
|
||||
|
||||
let lib_dxgi = native::DxgiLib::new().map_err(|_| crate::InstanceError)?;
|
||||
let mut factory_flags = native::FactoryCreationFlags::empty();
|
||||
|
||||
if desc.flags.contains(crate::InstanceFlags::VALIDATION) {
|
||||
// Enable debug layer
|
||||
match lib_main.get_debug_interface() {
|
||||
@ -102,45 +29,16 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
log::warn!("Debug interface function for D3D12 not found: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// The `DXGI_CREATE_FACTORY_DEBUG` flag is only allowed to be passed to
|
||||
// `CreateDXGIFactory2` if the debug interface is actually available. So
|
||||
// we check for whether it exists first.
|
||||
match lib_dxgi.get_debug_interface1() {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(debug_controller) => {
|
||||
debug_controller.destroy();
|
||||
factory_flags |= native::FactoryCreationFlags::DEBUG;
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Unable to enable DXGI debug interface: {}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
log::warn!("Debug interface function for DXGI not found: {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Intercept `OutputDebugString` calls
|
||||
errhandlingapi::AddVectoredExceptionHandler(0, Some(output_debug_string_handler));
|
||||
}
|
||||
|
||||
// Create DXGI factory
|
||||
let factory = match lib_dxgi.create_factory2(factory_flags) {
|
||||
Ok(pair) => match pair.into_result() {
|
||||
Ok(factory) => factory,
|
||||
Err(err) => {
|
||||
log::warn!("Failed to create DXGI factory: {}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
log::warn!("Factory creation function for DXGI not found: {:?}", err);
|
||||
return Err(crate::InstanceError);
|
||||
}
|
||||
};
|
||||
// Create DXGIFactory4
|
||||
let (lib_dxgi, factory) = auxil::dxgi::factory::create_factory(
|
||||
auxil::dxgi::factory::DxgiFactoryType::Factory4,
|
||||
desc.flags,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
// The call to create_factory will only succeed if we get a factory4, so this is safe.
|
||||
factory,
|
||||
library: Arc::new(lib_main),
|
||||
_lib_dxgi: lib_dxgi,
|
||||
@ -166,74 +64,11 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
}
|
||||
|
||||
unsafe fn enumerate_adapters(&self) -> Vec<crate::ExposedAdapter<super::Api>> {
|
||||
// Try to use high performance order by default (returns None on Windows < 1803)
|
||||
let factory6 = match self.factory.cast::<dxgi1_6::IDXGIFactory6>().into_result() {
|
||||
Ok(f6) => {
|
||||
// It's okay to decrement the refcount here because we
|
||||
// have another reference to the factory already owned by `self`.
|
||||
f6.destroy();
|
||||
Some(f6)
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Failed to cast DXGI to 1.6: {}", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
let adapters = auxil::dxgi::factory::enumerate_adapters(self.factory);
|
||||
|
||||
// Enumerate adapters
|
||||
let mut adapters = Vec::new();
|
||||
for cur_index in 0.. {
|
||||
let raw = match factory6 {
|
||||
Some(factory) => {
|
||||
profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference");
|
||||
let mut adapter2 = native::WeakPtr::<dxgi1_2::IDXGIAdapter2>::null();
|
||||
let hr = factory.EnumAdapterByGpuPreference(
|
||||
cur_index,
|
||||
dxgi1_6::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||
&dxgi1_2::IDXGIAdapter2::uuidof(),
|
||||
adapter2.mut_void(),
|
||||
);
|
||||
|
||||
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
||||
break;
|
||||
}
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("Failed enumerating adapters: {}", err);
|
||||
break;
|
||||
}
|
||||
|
||||
adapter2
|
||||
}
|
||||
None => {
|
||||
profiling::scope!("IDXGIFactory1::EnumAdapters1");
|
||||
let mut adapter1 = native::WeakPtr::<dxgi::IDXGIAdapter1>::null();
|
||||
let hr = self
|
||||
.factory
|
||||
.EnumAdapters1(cur_index, adapter1.mut_void() as *mut *mut _);
|
||||
|
||||
if hr == winerror::DXGI_ERROR_NOT_FOUND {
|
||||
break;
|
||||
}
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("Failed enumerating adapters: {}", err);
|
||||
break;
|
||||
}
|
||||
|
||||
match adapter1.cast::<dxgi1_2::IDXGIAdapter2>().into_result() {
|
||||
Ok(adapter2) => {
|
||||
adapter1.destroy();
|
||||
adapter2
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Failed casting to Adapter2: {}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
adapters.extend(super::Adapter::expose(raw, &self.library, self.flags));
|
||||
}
|
||||
adapters
|
||||
.into_iter()
|
||||
.filter_map(|raw| super::Adapter::expose(raw, &self.library, self.flags))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
@ -41,11 +41,13 @@ mod device;
|
||||
mod instance;
|
||||
mod view;
|
||||
|
||||
use crate::auxil::{self, dxgi::result::HResult as _};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use parking_lot::Mutex;
|
||||
use std::{borrow::Cow, ffi, mem, num::NonZeroU32, ptr, sync::Arc};
|
||||
use std::{ffi, mem, num::NonZeroU32, sync::Arc};
|
||||
use winapi::{
|
||||
shared::{dxgi, dxgi1_2, dxgi1_4, dxgitype, windef, winerror},
|
||||
shared::{dxgi, dxgi1_4, dxgitype, windef, winerror},
|
||||
um::{d3d12, dcomp, synchapi, winbase, winnt},
|
||||
Interface as _,
|
||||
};
|
||||
@ -79,51 +81,12 @@ impl crate::Api for Api {
|
||||
type ComputePipeline = ComputePipeline;
|
||||
}
|
||||
|
||||
trait HResult<O> {
|
||||
fn into_result(self) -> Result<O, Cow<'static, str>>;
|
||||
fn into_device_result(self, description: &str) -> Result<O, crate::DeviceError>;
|
||||
}
|
||||
impl HResult<()> for i32 {
|
||||
fn into_result(self) -> Result<(), Cow<'static, str>> {
|
||||
if self >= 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let description = match self {
|
||||
winerror::E_UNEXPECTED => "unexpected",
|
||||
winerror::E_NOTIMPL => "not implemented",
|
||||
winerror::E_OUTOFMEMORY => "out of memory",
|
||||
winerror::E_INVALIDARG => "invalid argument",
|
||||
_ => return Err(Cow::Owned(format!("0x{:X}", self as u32))),
|
||||
};
|
||||
Err(Cow::Borrowed(description))
|
||||
}
|
||||
fn into_device_result(self, description: &str) -> Result<(), crate::DeviceError> {
|
||||
self.into_result().map_err(|err| {
|
||||
log::error!("{} failed: {}", description, err);
|
||||
if self == winerror::E_OUTOFMEMORY {
|
||||
crate::DeviceError::OutOfMemory
|
||||
} else {
|
||||
crate::DeviceError::Lost
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HResult<T> for (T, i32) {
|
||||
fn into_result(self) -> Result<T, Cow<'static, str>> {
|
||||
self.1.into_result().map(|()| self.0)
|
||||
}
|
||||
fn into_device_result(self, description: &str) -> Result<T, crate::DeviceError> {
|
||||
self.1.into_device_result(description).map(|()| self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// Limited by D3D12's root signature size of 64. Each element takes 1 or 2 entries.
|
||||
const MAX_ROOT_ELEMENTS: usize = 64;
|
||||
const ZERO_BUFFER_SIZE: wgt::BufferAddress = 256 << 10;
|
||||
|
||||
pub struct Instance {
|
||||
factory: native::Factory4,
|
||||
factory: native::DxgiFactory,
|
||||
library: Arc<native::D3D12Lib>,
|
||||
_lib_dxgi: native::DxgiLib,
|
||||
flags: crate::InstanceFlags,
|
||||
@ -163,7 +126,7 @@ enum SurfaceTarget {
|
||||
}
|
||||
|
||||
pub struct Surface {
|
||||
factory: native::WeakPtr<dxgi1_4::IDXGIFactory4>,
|
||||
factory: native::DxgiFactory,
|
||||
target: SurfaceTarget,
|
||||
swap_chain: Option<SwapChain>,
|
||||
}
|
||||
@ -197,7 +160,7 @@ struct Workarounds {
|
||||
}
|
||||
|
||||
pub struct Adapter {
|
||||
raw: native::WeakPtr<dxgi1_2::IDXGIAdapter2>,
|
||||
raw: native::DxgiAdapter,
|
||||
device: native::Device,
|
||||
library: Arc<native::D3D12Lib>,
|
||||
private_caps: PrivateCapabilities,
|
||||
@ -592,7 +555,7 @@ impl crate::Surface<Api> for Surface {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let non_srgb_format = conv::map_texture_format_nosrgb(config.format);
|
||||
let non_srgb_format = auxil::dxgi::conv::map_texture_format_nosrgb(config.format);
|
||||
|
||||
let swap_chain = match self.swap_chain.take() {
|
||||
//Note: this path doesn't properly re-initialize all of the things
|
||||
@ -615,54 +578,56 @@ impl crate::Surface<Api> for Surface {
|
||||
raw
|
||||
}
|
||||
None => {
|
||||
let mut swap_chain1 = native::WeakPtr::<dxgi1_2::IDXGISwapChain1>::null();
|
||||
|
||||
let raw_desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 {
|
||||
AlphaMode: conv::map_acomposite_alpha_mode(config.composite_alpha_mode),
|
||||
BufferCount: config.swap_chain_size,
|
||||
Width: config.extent.width,
|
||||
Height: config.extent.height,
|
||||
Format: non_srgb_format,
|
||||
Flags: flags,
|
||||
BufferUsage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
SampleDesc: dxgitype::DXGI_SAMPLE_DESC {
|
||||
Count: 1,
|
||||
Quality: 0,
|
||||
let desc = native::SwapchainDesc {
|
||||
alpha_mode: auxil::dxgi::conv::map_acomposite_alpha_mode(
|
||||
config.composite_alpha_mode,
|
||||
),
|
||||
width: config.extent.width,
|
||||
height: config.extent.height,
|
||||
format: non_srgb_format,
|
||||
stereo: false,
|
||||
sample: native::SampleDesc {
|
||||
count: 1,
|
||||
quality: 0,
|
||||
},
|
||||
Scaling: dxgi1_2::DXGI_SCALING_STRETCH,
|
||||
Stereo: 0,
|
||||
SwapEffect: dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||
buffer_usage: dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
buffer_count: config.swap_chain_size,
|
||||
scaling: native::Scaling::Stretch,
|
||||
swap_effect: native::SwapEffect::FlipDiscard,
|
||||
flags,
|
||||
};
|
||||
|
||||
let hr = {
|
||||
match self.target {
|
||||
SurfaceTarget::WndHandle(wnd_handle) => {
|
||||
profiling::scope!("IDXGIFactory4::CreateSwapChainForHwnd");
|
||||
self.factory.CreateSwapChainForHwnd(
|
||||
let swap_chain1 = match self.target {
|
||||
SurfaceTarget::Visual(_) => {
|
||||
profiling::scope!("IDXGIFactory4::CreateSwapChainForComposition");
|
||||
self.factory
|
||||
.unwrap_factory2()
|
||||
.create_swapchain_for_composition(
|
||||
device.present_queue.as_mut_ptr() as *mut _,
|
||||
wnd_handle,
|
||||
&raw_desc,
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
swap_chain1.mut_void() as *mut *mut _,
|
||||
&desc,
|
||||
)
|
||||
}
|
||||
SurfaceTarget::Visual(_) => {
|
||||
profiling::scope!("IDXGIFactory4::CreateSwapChainForComposition");
|
||||
self.factory.CreateSwapChainForComposition(
|
||||
.into_result()
|
||||
}
|
||||
SurfaceTarget::WndHandle(hwnd) => {
|
||||
profiling::scope!("IDXGIFactory4::CreateSwapChainForHwnd");
|
||||
self.factory
|
||||
.as_factory2()
|
||||
.unwrap()
|
||||
.create_swapchain_for_hwnd(
|
||||
device.present_queue.as_mut_ptr() as *mut _,
|
||||
&raw_desc,
|
||||
ptr::null_mut(),
|
||||
swap_chain1.mut_void() as *mut *mut _,
|
||||
hwnd,
|
||||
&desc,
|
||||
)
|
||||
}
|
||||
.into_result()
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(err) = hr.into_result() {
|
||||
log::error!("SwapChain creation error: {}", err);
|
||||
return Err(crate::SurfaceError::Other("swap chain creation"));
|
||||
}
|
||||
let swap_chain1 = match swap_chain1 {
|
||||
Ok(s) => s,
|
||||
Err(err) => {
|
||||
log::error!("SwapChain creation error: {}", err);
|
||||
return Err(crate::SurfaceError::Other("swap chain creation"));
|
||||
}
|
||||
};
|
||||
|
||||
match self.target {
|
||||
SurfaceTarget::WndHandle(_) => {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::conv;
|
||||
use crate::auxil;
|
||||
use std::mem;
|
||||
use winapi::um::d3d12;
|
||||
|
||||
@ -19,8 +19,8 @@ impl crate::TextureViewDescriptor<'_> {
|
||||
pub(super) fn to_internal(&self, texture: &super::Texture) -> ViewDescriptor {
|
||||
ViewDescriptor {
|
||||
dimension: self.dimension,
|
||||
format: conv::map_texture_format(self.format),
|
||||
format_nodepth: conv::map_texture_format_nodepth(self.format),
|
||||
format: auxil::dxgi::conv::map_texture_format(self.format),
|
||||
format_nodepth: auxil::dxgi::conv::map_texture_format_nodepth(self.format),
|
||||
multisampled: texture.sample_count > 1,
|
||||
mip_level_base: self.range.base_mip_level,
|
||||
mip_level_count: match self.range.mip_level_count {
|
||||
|
@ -52,6 +52,8 @@ compile_error!("Metal API enabled on non-Apple OS. If your project is not using
|
||||
#[cfg(all(feature = "dx12", not(windows)))]
|
||||
compile_error!("DX12 API enabled on non-Windows OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
|
||||
|
||||
#[cfg(all(feature = "dx11", windows))]
|
||||
mod dx11;
|
||||
#[cfg(all(feature = "dx12", windows))]
|
||||
mod dx12;
|
||||
mod empty;
|
||||
@ -64,6 +66,8 @@ mod vulkan;
|
||||
|
||||
pub mod auxil;
|
||||
pub mod api {
|
||||
#[cfg(feature = "dx11")]
|
||||
pub use super::dx11::Api as Dx11;
|
||||
#[cfg(feature = "dx12")]
|
||||
pub use super::dx12::Api as Dx12;
|
||||
pub use super::empty::Api as Empty;
|
||||
|
Loading…
Reference in New Issue
Block a user