use std::num::NonZeroU64; use winapi::um::{d3d11, d3dcommon}; impl crate::Adapter for super::Adapter { unsafe fn open( &self, features: wgt::Features, limits: &wgt::Limits, ) -> Result, crate::DeviceError> { todo!() } unsafe fn texture_format_capabilities( &self, format: wgt::TextureFormat, ) -> crate::TextureFormatCapabilities { todo!() } unsafe fn surface_capabilities( &self, surface: &super::Surface, ) -> Option { todo!() } unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp { todo!() } } impl super::Adapter { pub(super) fn expose( instance: &super::library::D3D11Lib, adapter: d3d12::DxgiAdapter, ) -> Option> { 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_D3D9_OPTIONS1, ) }; let d3d10_features = unsafe { device.check_feature_support::( d3d11::D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, ) }; let d3d11_features = unsafe { device.check_feature_support::( d3d11::D3D11_FEATURE_D3D11_OPTIONS, ) }; let d3d11_features1 = unsafe { device.check_feature_support::( d3d11::D3D11_FEATURE_D3D11_OPTIONS1, ) }; let d3d11_features2 = unsafe { device.check_feature_support::( d3d11::D3D11_FEATURE_D3D11_OPTIONS2, ) }; let d3d11_features3 = unsafe { device.check_feature_support::( 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 | wgt::DownlevelFlags::UNRESTRICTED_INDEX_BUFFER | wgt::DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES; // 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; // this is actually the first FL that supports u32 at all downlevel |= wgt::DownlevelFlags::FULL_DRAW_INDEX_UINT32; } if feature_level >= FL9_3 { downlevel |= wgt::DownlevelFlags::COMPARISON_SAMPLERS; } if feature_level >= FL10_0 { downlevel |= wgt::DownlevelFlags::FRAGMENT_STORAGE; downlevel |= wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE; downlevel |= wgt::DownlevelFlags::DEPTH_BIAS_CLAMP; downlevel |= wgt::DownlevelFlags::VERTEX_STORAGE; features |= wgt::Features::DEPTH_CLIP_CONTROL; features |= wgt::Features::TIMESTAMP_QUERY; features |= wgt::Features::PIPELINE_STATISTICS_QUERY; features |= wgt::Features::SHADER_PRIMITIVE_INDEX; } if feature_level >= FL10_1 { downlevel |= wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES; downlevel |= wgt::DownlevelFlags::MULTISAMPLED_SHADING; } if feature_level >= FL11_0 { downlevel |= wgt::DownlevelFlags::INDIRECT_EXECUTION; downlevel |= wgt::DownlevelFlags::WEBGPU_TEXTURE_FORMAT_SUPPORT; features |= wgt::Features::TEXTURE_COMPRESSION_BC; } if feature_level >= FL11_1 { features |= wgt::Features::VERTEX_WRITABLE_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_3d, max_texture_array_layers: max_texture_dimension_3d, max_bind_groups: u32::MAX, max_bindings_per_bind_group: 65535, 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_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, // D3D11_BUFFER_DESC represents the buffer size as a 32 bit int. max_buffer_size: u32::MAX as u64, }; // // 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!(), }, driver: String::new(), driver_info: String::new(), 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, }) } }