Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions deno_webgpu/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ impl GPU {
noop: wgpu_types::NoopBackendOptions::default(),
},
},
None,
)));
state.borrow::<Instance>()
};
Expand Down
2 changes: 1 addition & 1 deletion player/src/bin/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn main() {
.unwrap();

let instance_desc = wgt::InstanceDescriptor::from_env_or_default();
let instance = wgc::instance::Instance::new("player", &instance_desc);
let instance = wgc::instance::Instance::new("player", &instance_desc, None);

#[cfg(feature = "winit")]
let surface = unsafe {
Expand Down
2 changes: 1 addition & 1 deletion player/tests/player/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl Corpus {
println!("\t\tTest '{test_path:?}'");

let instance_desc = wgt::InstanceDescriptor::from_env_or_default();
let instance = wgc::instance::Instance::new("test", &instance_desc);
let instance = wgc::instance::Instance::new("test", &instance_desc, None);
let adapter = match instance.request_adapter(
&wgt::RequestAdapterOptions {
power_preference: wgt::PowerPreference::None,
Expand Down
8 changes: 6 additions & 2 deletions wgpu-core/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ pub struct Global {
}

impl Global {
pub fn new(name: &str, instance_desc: &wgt::InstanceDescriptor) -> Self {
pub fn new(
name: &str,
instance_desc: &wgt::InstanceDescriptor,
telemetry: Option<hal::Telemetry>,
) -> Self {
profiling::scope!("Global::new");
Self {
instance: Instance::new(name, instance_desc),
instance: Instance::new(name, instance_desc, telemetry),
surfaces: Registry::new(),
hub: Hub::new(),
}
Expand Down
24 changes: 17 additions & 7 deletions wgpu-core/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ pub struct Instance {
}

impl Instance {
pub fn new(name: &str, instance_desc: &wgt::InstanceDescriptor) -> Self {
pub fn new(
name: &str,
instance_desc: &wgt::InstanceDescriptor,
telemetry: Option<hal::Telemetry>,
) -> Self {
let mut this = Self {
name: name.to_owned(),
instance_per_backend: Vec::new(),
Expand All @@ -102,21 +106,26 @@ impl Instance {
};

#[cfg(vulkan)]
this.try_add_hal(hal::api::Vulkan, instance_desc);
this.try_add_hal(hal::api::Vulkan, instance_desc, telemetry);
#[cfg(metal)]
this.try_add_hal(hal::api::Metal, instance_desc);
this.try_add_hal(hal::api::Metal, instance_desc, telemetry);
#[cfg(dx12)]
this.try_add_hal(hal::api::Dx12, instance_desc);
this.try_add_hal(hal::api::Dx12, instance_desc, telemetry);
#[cfg(gles)]
this.try_add_hal(hal::api::Gles, instance_desc);
this.try_add_hal(hal::api::Gles, instance_desc, telemetry);
#[cfg(feature = "noop")]
this.try_add_hal(hal::api::Noop, instance_desc);
this.try_add_hal(hal::api::Noop, instance_desc, telemetry);

this
}

/// Helper for `Instance::new()`; attempts to add a single `wgpu-hal` backend to this instance.
fn try_add_hal<A: hal::Api>(&mut self, _: A, instance_desc: &wgt::InstanceDescriptor) {
fn try_add_hal<A: hal::Api>(
&mut self,
_: A,
instance_desc: &wgt::InstanceDescriptor,
telemetry: Option<hal::Telemetry>,
) {
// Whether or not the backend was requested, and whether or not it succeeds,
// note that we *could* try it.
self.supported_backends |= A::VARIANT.into();
Expand All @@ -131,6 +140,7 @@ impl Instance {
flags: self.flags,
memory_budget_thresholds: instance_desc.memory_budget_thresholds,
backend_options: instance_desc.backend_options.clone(),
telemetry,
};

use hal::Instance as _;
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/examples/halmark/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl<A: hal::Api> Example<A> {
memory_budget_thresholds: wgpu_types::MemoryBudgetThresholds::default(),
// Can't rely on having DXC available, so use FXC instead
backend_options: wgpu_types::BackendOptions::default(),
telemetry: None,
};
let instance = unsafe { A::Instance::init(&instance_desc)? };
let surface = {
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/examples/ray-traced-triangle/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ impl<A: hal::Api> Example<A> {
},
..Default::default()
},
telemetry: None,
};
let instance = unsafe { A::Instance::init(&instance_desc)? };
let surface = {
Expand Down
177 changes: 125 additions & 52 deletions wgpu-hal/src/dx12/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ impl super::Adapter {
&self.raw
}

#[allow(clippy::too_many_arguments)]
pub(super) fn expose(
adapter: DxgiAdapter,
library: &Arc<D3D12Lib>,
Expand All @@ -66,19 +67,62 @@ impl super::Adapter {
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
compiler_container: Arc<shader_compilation::CompilerContainer>,
backend_options: wgt::Dx12BackendOptions,
telemetry: Option<crate::Telemetry>,
) -> Option<crate::ExposedAdapter<super::Api>> {
let desc = unsafe { adapter.GetDesc2() }.unwrap();
let driver_version =
unsafe { adapter.CheckInterfaceSupport(&Dxgi::IDXGIDevice::IID) }.unwrap() as u64;
let driver_version = [
(driver_version >> 48) as u16,
(driver_version >> 32) as u16,
(driver_version >> 16) as u16,
driver_version as u16,
];

let get_telemetry_key = || {
// The key must be under 111 bytes:
// - backend identifier 'D' = 1 byte
// - 4 * u32's formatted as hex = 4 * 8 = 32 bytes
// - 4 * u16's formatted as dec = 4 * 5 = 20 bytes
// - separators = 8 bytes
// total = 61 bytes
format!(
"D:{:X}:{:X}:{:X}:{:X}:{}.{}.{}.{}",
desc.VendorId,
desc.DeviceId,
desc.SubSysId,
desc.Revision,
driver_version[0],
driver_version[1],
driver_version[2],
driver_version[3],
)
};
Comment on lines +72 to +100
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a pretty long function already, it would be nice if we could isolate this in a function elsewhere - perhaps in a new telemetry module.

It seems like we should be able to collect res, and then have something like:

if let Some(telemetry) = telemetry {
    telemetry::expose_adapter(telemetry, adapter, res)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, wait - now I see that desc and driver_version are all used later in the function. But it does still seem better to have at least the error analysis out of the way. And simply seeing a name like telemetry::expose_adapter(blah blah blah) will help people skip this code more quickly.


// Create the device so that we can get the capabilities.
let device = {
let res = {
profiling::scope!("ID3D12Device::create_device");
library
.create_device(&adapter, Direct3D::D3D_FEATURE_LEVEL_11_0)
.ok()??
library.create_device(&adapter, Direct3D::D3D_FEATURE_LEVEL_11_0)
};
if let Some(telemetry) = telemetry {
if let Err(ref err) = res {
let category = match err {
crate::dx12::CreateDeviceError::GetProcAddress => "NONE:GetProcAddress",
crate::dx12::CreateDeviceError::D3D12CreateDevice(hresult) => {
&format!("NONE:D3D12CreateDevice:{:X}", hresult.0)
}
crate::dx12::CreateDeviceError::RetDeviceIsNull => "NONE:RetDeviceIsNull",
};
(telemetry.expose_adapter)(&get_telemetry_key(), category);
}
}
let device = res.ok()?;

profiling::scope!("feature queries");

// Detect the highest supported feature level.
let d3d_feature_level = [
Direct3D::D3D_FEATURE_LEVEL_12_2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know D3D12, but does this change belong in this PR?

Direct3D::D3D_FEATURE_LEVEL_12_1,
Direct3D::D3D_FEATURE_LEVEL_12_0,
Direct3D::D3D_FEATURE_LEVEL_11_1,
Expand All @@ -99,10 +143,6 @@ impl super::Adapter {
.unwrap();
let max_feature_level = device_levels.MaxSupportedFeatureLevel;

// We have found a possible adapter.
// Acquire the device information.
let desc = unsafe { adapter.GetDesc2() }.unwrap();

let device_name = auxil::dxgi::conv::map_adapter_name(desc.Description);

let mut features_architecture = Direct3D12::D3D12_FEATURE_DATA_ARCHITECTURE::default();
Expand All @@ -116,14 +156,6 @@ impl super::Adapter {
}
.unwrap();

let driver_version = unsafe { adapter.CheckInterfaceSupport(&Dxgi::IDXGIDevice::IID) }
.ok()
.map(|i| {
const MASK: i64 = 0xFFFF;
(i >> 48, (i >> 32) & MASK, (i >> 16) & MASK, i & MASK)
})
.unwrap_or((0, 0, 0, 0));

let mut workarounds = super::Workarounds::default();

let is_warp = device_name.contains("Microsoft Basic Render Driver");
Expand All @@ -132,7 +164,7 @@ impl super::Adapter {
// use a version that starts with 10.x.x.x. Versions that ship from Nuget use 1.0.x.x.
//
// As far as we know, this is only an issue on the Nuget versions.
if is_warp && driver_version >= (1, 0, 13, 0) && driver_version.0 < 10 {
if is_warp && driver_version >= [1, 0, 13, 0] && driver_version[0] < 10 {
workarounds.avoid_shader_debug_info = true;
}

Expand All @@ -153,7 +185,7 @@ impl super::Adapter {
device_pci_bus_id: get_adapter_pci_info(desc.VendorId, desc.DeviceId),
driver: format!(
"{}.{}.{}.{}",
driver_version.0, driver_version.1, driver_version.2, driver_version.3
driver_version[0], driver_version[1], driver_version[2], driver_version[3]
),
driver_info: String::new(),
transient_saves_memory: false,
Expand All @@ -170,6 +202,10 @@ impl super::Adapter {
.unwrap();

if options.ResourceBindingTier.0 < Direct3D12::D3D12_RESOURCE_BINDING_TIER_2.0 {
if let Some(telemetry) = telemetry {
let category = "NONE:REQ_RBT2";
(telemetry.expose_adapter)(&get_telemetry_key(), category);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps these other categories could be handled with separate functions in the telemetry module. Or maybe that's too much fuss. But it seems like the telemetry could be a little less conspicuous; if that perception isn't correct then this is fine.

}
// We require Tier 2 or higher for the ability to make samplers bindless in all cases.
return None;
}
Expand Down Expand Up @@ -263,6 +299,40 @@ impl super::Adapter {
}
};

let mut all_shader_models = [
Direct3D12::D3D_SHADER_MODEL_6_9,
Direct3D12::D3D_SHADER_MODEL_6_8,
Direct3D12::D3D_SHADER_MODEL_6_7,
Direct3D12::D3D_SHADER_MODEL_6_6,
Direct3D12::D3D_SHADER_MODEL_6_5,
Direct3D12::D3D_SHADER_MODEL_6_4,
Direct3D12::D3D_SHADER_MODEL_6_3,
Direct3D12::D3D_SHADER_MODEL_6_2,
Direct3D12::D3D_SHADER_MODEL_6_1,
Direct3D12::D3D_SHADER_MODEL_6_0,
]
.iter();
let highest_shader_model = loop {
if let Some(&sm) = all_shader_models.next() {
let mut sm = Direct3D12::D3D12_FEATURE_DATA_SHADER_MODEL {
HighestShaderModel: sm,
};
if unsafe {
device.CheckFeatureSupport(
Direct3D12::D3D12_FEATURE_SHADER_MODEL,
<*mut _>::cast(&mut sm),
size_of_val(&sm) as u32,
)
}
.is_ok()
{
break sm.HighestShaderModel;
}
} else {
break Direct3D12::D3D_SHADER_MODEL_5_1;
}
};

let shader_model = if let Some(max_shader_model) = compiler_container.max_shader_model() {
let max_shader_model = match max_shader_model {
wgt::DxcShaderModel::V6_0 => Direct3D12::D3D_SHADER_MODEL_6_0,
Expand All @@ -275,42 +345,18 @@ impl super::Adapter {
wgt::DxcShaderModel::V6_7 => Direct3D12::D3D_SHADER_MODEL_6_7,
};

let mut versions = [
Direct3D12::D3D_SHADER_MODEL_6_7,
Direct3D12::D3D_SHADER_MODEL_6_6,
Direct3D12::D3D_SHADER_MODEL_6_5,
Direct3D12::D3D_SHADER_MODEL_6_4,
Direct3D12::D3D_SHADER_MODEL_6_3,
Direct3D12::D3D_SHADER_MODEL_6_2,
Direct3D12::D3D_SHADER_MODEL_6_1,
Direct3D12::D3D_SHADER_MODEL_6_0,
]
.iter()
.filter(|shader_model| shader_model.0 <= max_shader_model.0);

let highest_shader_model = loop {
if let Some(&sm) = versions.next() {
let mut sm = Direct3D12::D3D12_FEATURE_DATA_SHADER_MODEL {
HighestShaderModel: sm,
};
if unsafe {
device.CheckFeatureSupport(
Direct3D12::D3D12_FEATURE_SHADER_MODEL,
<*mut _>::cast(&mut sm),
size_of_val(&sm) as u32,
)
}
.is_ok()
{
break sm.HighestShaderModel;
let shader_model =
Direct3D12::D3D_SHADER_MODEL(highest_shader_model.0.min(max_shader_model.0));

match shader_model {
Direct3D12::D3D_SHADER_MODEL_5_1 => {
if let Some(telemetry) = telemetry {
let category = "NONE:REQ_SM6";
(telemetry.expose_adapter)(&get_telemetry_key(), category);
}
} else {
break Direct3D12::D3D_SHADER_MODEL_5_1;
// don't expose this adapter if it doesn't support DXIL
return None;
}
};

match highest_shader_model {
Direct3D12::D3D_SHADER_MODEL_5_1 => return None, // don't expose this adapter if it doesn't support DXIL
Direct3D12::D3D_SHADER_MODEL_6_0 => naga::back::hlsl::ShaderModel::V6_0,
Direct3D12::D3D_SHADER_MODEL_6_1 => naga::back::hlsl::ShaderModel::V6_1,
Direct3D12::D3D_SHADER_MODEL_6_2 => naga::back::hlsl::ShaderModel::V6_2,
Expand Down Expand Up @@ -646,6 +692,33 @@ impl super::Adapter {
// See https://microsoft.github.io/DirectX-Specs/d3d/ViewInstancing.html#maximum-viewinstancecount
let max_multiview_view_count = if view_instancing { 4 } else { 0 };

if let Some(telemetry) = telemetry {
let fl = match max_feature_level {
Direct3D::D3D_FEATURE_LEVEL_12_2 => "12_2",
Direct3D::D3D_FEATURE_LEVEL_12_1 => "12_1",
Direct3D::D3D_FEATURE_LEVEL_12_0 => "12_0",
Direct3D::D3D_FEATURE_LEVEL_11_1 => "11_1",
Direct3D::D3D_FEATURE_LEVEL_11_0 => "11_0",
_ => unreachable!(),
};
let sm = match highest_shader_model {
Direct3D12::D3D_SHADER_MODEL_6_9 => "6.9",
Direct3D12::D3D_SHADER_MODEL_6_8 => "6.8",
Direct3D12::D3D_SHADER_MODEL_6_7 => "6.7",
Direct3D12::D3D_SHADER_MODEL_6_6 => "6.6",
Direct3D12::D3D_SHADER_MODEL_6_5 => "6.5",
Direct3D12::D3D_SHADER_MODEL_6_4 => "6.4",
Direct3D12::D3D_SHADER_MODEL_6_3 => "6.3",
Direct3D12::D3D_SHADER_MODEL_6_2 => "6.2",
Direct3D12::D3D_SHADER_MODEL_6_1 => "6.1",
Direct3D12::D3D_SHADER_MODEL_6_0 => "6.0",
Direct3D12::D3D_SHADER_MODEL_5_1 => "5.1",
_ => unreachable!(),
};
let category = &format!("SOME:FL{fl}:SM{sm}");
(telemetry.expose_adapter)(&get_telemetry_key(), category);
}

Some(crate::ExposedAdapter {
adapter: super::Adapter {
raw: adapter,
Expand Down
2 changes: 2 additions & 0 deletions wgpu-hal/src/dx12/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ impl crate::Instance for super::Instance {
memory_budget_thresholds: desc.memory_budget_thresholds,
compiler_container: Arc::new(compiler_container),
options: desc.backend_options.dx12.clone(),
telemetry: desc.telemetry,
})
}

Expand Down Expand Up @@ -164,6 +165,7 @@ impl crate::Instance for super::Instance {
self.memory_budget_thresholds,
self.compiler_container.clone(),
self.options.clone(),
self.telemetry,
)
})
.collect()
Expand Down
Loading
Loading