Skip to content

Commit

Permalink
hal/dx11: fully expose wgpu adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
cwfitzgerald committed Mar 12, 2022
1 parent 7b3eaa6 commit 6394ac6
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ default-members = ["wgpu", "wgpu-hal", "wgpu-info"]
[patch.crates-io]
#naga = { path = "../naga" }
#glow = { path = "../glow" }
d3d12 = { git = "https://github.com/cwfitzgerald/d3d12-rs.git", rev = "83d6486819887eb01266b2f86a2decb492acf12e" }
d3d12 = { git = "https://github.com/cwfitzgerald/d3d12-rs.git", rev = "02364666fa287df99d17df9f3c493519b12e8338" }
# d3d12 = { path = "../d3d12-rs" }
#metal = { path = "../metal-rs" }
#web-sys = { path = "../wasm-bindgen/crates/web-sys" }
Expand Down
4 changes: 2 additions & 2 deletions wgpu-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
242 changes: 241 additions & 1 deletion wgpu-hal/src/dx11/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use std::num::NonZeroU64;

use winapi::um::{d3d11, d3dcommon};

impl crate::Adapter<super::Api> for super::Adapter {
unsafe fn open(
&self,
Expand Down Expand Up @@ -27,8 +31,244 @@ impl super::Adapter {
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)?;

todo!()
//
// 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,
})
}
}
21 changes: 21 additions & 0 deletions wgpu-hal/src/dx11/device.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
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!()
Expand Down Expand Up @@ -217,3 +223,18 @@ impl crate::Queue<super::Api> for super::Queue {
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
}
}
9 changes: 9 additions & 0 deletions wgpu-hal/src/dx11/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ 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(
Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/dx11/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type D3D11CreateDeviceFun = unsafe extern "system" fn(
*mut *mut d3d11::ID3D11DeviceContext,
) -> native::HRESULT;

pub struct D3D11Lib {
pub(super) struct D3D11Lib {
// We use the os specific symbol to drop the lifetime parameter.
//
// SAFETY: we must ensure this outlives the Library.
Expand Down
12 changes: 10 additions & 2 deletions wgpu-hal/src/dx11/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,16 @@ unsafe impl Sync for Instance {}

pub struct Surface {}

pub struct Adapter {}
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)]
pub enum D3D11Device {
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;
Expand All @@ -62,6 +67,9 @@ native::weak_com_inheritance_chain! {

pub struct Device {}

unsafe impl Send for Device {}
unsafe impl Sync for Device {}

pub struct Queue {}

pub struct CommandEncoder {}
Expand Down
1 change: 0 additions & 1 deletion wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,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),
Expand Down

0 comments on commit 6394ac6

Please sign in to comment.