From 432d11f57b295056bb3ad828b88ed4d4846fd150 Mon Sep 17 00:00:00 2001 From: Junkui Zhang <364772080@qq.com> Date: Thu, 17 Jul 2025 19:30:49 +0800 Subject: [PATCH] implement gpu driver version for nvidia --- .../src/platform/windows/directx_renderer.rs | 116 +++++++++++++++++- crates/gpui/src/platform/windows/window.rs | 3 +- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/crates/gpui/src/platform/windows/directx_renderer.rs b/crates/gpui/src/platform/windows/directx_renderer.rs index 4bc80851beb3b4c511749d3478e0f6b6e6888fb1..22bd5b0b95d7cc5e5c444a87b342b584913ced5c 100644 --- a/crates/gpui/src/platform/windows/directx_renderer.rs +++ b/crates/gpui/src/platform/windows/directx_renderer.rs @@ -32,6 +32,7 @@ pub(crate) struct DirectXRenderer { /// Direct3D objects #[derive(Clone)] pub(crate) struct DirectXDevices { + adapter: IDXGIAdapter1, dxgi_factory: IDXGIFactory6, #[cfg(not(feature = "enable-renderdoc"))] dxgi_device: IDXGIDevice, @@ -97,6 +98,7 @@ impl DirectXDevices { let dxgi_device: IDXGIDevice = device.cast()?; Ok(Self { + adapter, dxgi_factory, #[cfg(not(feature = "enable-renderdoc"))] dxgi_device, @@ -396,6 +398,34 @@ impl DirectXRenderer { } Ok(()) } + + pub(crate) fn gpu_specs(&self) -> Result { + let desc = unsafe { self.devices.adapter.GetDesc1() }?; + let is_software_emulated = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE.0 as u32) != 0; + let device_name = String::from_utf16_lossy(&desc.Description) + .trim_matches(char::from(0)) + .to_string(); + let driver_name = match desc.VendorId { + 0x10DE => "NVIDIA Corporation".to_string(), + 0x1002 => "AMD Corporation".to_string(), + 0x8086 => "Intel Corporation".to_string(), + _ => "Unknown Vendor".to_string(), + }; + let driver_version = match desc.VendorId { + 0x10DE => nvidia::get_driver_version().context("Failed to get NVIDIA driver info"), + 0x1002 => Err(anyhow::anyhow!("AMD driver info not implemented yet")), + 0x8086 => Err(anyhow::anyhow!("Intel driver info not implemented yet")), + _ => Err(anyhow::anyhow!("Unknown vendor detected.")), + } + .log_err() + .unwrap_or("Unknown Driver".to_string()); + Ok(GpuSpecs { + is_software_emulated, + device_name, + driver_name, + driver_info: driver_version, + }) + } } impl DirectXResources { @@ -936,12 +966,11 @@ fn get_adapter(dxgi_factory: &IDXGIFactory6) -> Result { dxgi_factory .EnumAdapterByGpuPreference(adapter_index, DXGI_GPU_PREFERENCE_MINIMUM_POWER) }?; - { - let desc = unsafe { adapter.GetDesc1() }?; - println!( - "Select GPU: {}", - String::from_utf16_lossy(&desc.Description) - ); + if let Ok(desc) = unsafe { adapter.GetDesc1() } { + let gpu_name = String::from_utf16_lossy(&desc.Description) + .trim_matches(char::from(0)) + .to_string(); + log::info!("Using GPU: {}", gpu_name); } // Check to see whether the adapter supports Direct3D 11, but don't // create the actual device yet. @@ -1339,3 +1368,78 @@ mod shader_resources { } } } + +mod nvidia { + use std::os::raw::{c_char, c_int, c_uint}; + + use anyhow::{Context, Result}; + use windows::{ + Win32::System::LibraryLoader::{GetProcAddress, LoadLibraryA}, + core::s, + }; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L180 + const NVAPI_SHORT_STRING_MAX: usize = 64; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L235 + #[allow(non_camel_case_types)] + type NvAPI_ShortString = [c_char; NVAPI_SHORT_STRING_MAX]; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi.h#L87 + #[allow(non_camel_case_types)] + type NvAPI_Initialize_t = unsafe extern "C" fn() -> c_int; + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_lite_common.h#L447 + #[allow(non_camel_case_types)] + type NvAPI_SYS_GetDriverAndBranchVersion_t = unsafe extern "C" fn( + driver_version: *mut c_uint, + build_branch_string: *mut NvAPI_ShortString, + ) -> c_int; + + pub(super) fn get_driver_version() -> Result { + unsafe { + // Try to load the NVIDIA driver DLL + let nvidia_dll = LoadLibraryA(s!("nvapi64.dll")).context("Can't load nvapi64.dll")?; + let nvapi_query_addr = GetProcAddress(nvidia_dll, s!("nvapi_QueryInterface")) + .ok_or_else(|| anyhow::anyhow!("Failed to get nvapi_QueryInterface address"))?; + let nvapi_query: extern "C" fn(u32) -> *mut () = std::mem::transmute(nvapi_query_addr); + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_interface.h#L33 + let nvapi_init_ptr = nvapi_query(0x0150e828); + if nvapi_init_ptr.is_null() { + anyhow::bail!("Failed to get NVIDIA API function pointer"); + } + let nvapi_init: NvAPI_Initialize_t = std::mem::transmute(nvapi_init_ptr); + + let result = nvapi_init(); + if result != 0 { + anyhow::bail!("Failed to initialize NVIDIA API, error code: {}", result); + } + + // https://github.com/NVIDIA/nvapi/blob/7cb76fce2f52de818b3da497af646af1ec16ce27/nvapi_interface.h#L41 + let nvapi_get_driver_version_ptr = nvapi_query(0x2926aaad); + if nvapi_get_driver_version_ptr.is_null() { + anyhow::bail!("Failed to get NVIDIA driver version function pointer"); + } + let nvapi_get_driver_version: NvAPI_SYS_GetDriverAndBranchVersion_t = + std::mem::transmute(nvapi_get_driver_version_ptr); + + let mut driver_version: c_uint = 0; + let mut build_branch_string: NvAPI_ShortString = [0; NVAPI_SHORT_STRING_MAX]; + let result = nvapi_get_driver_version( + &mut driver_version as *mut c_uint, + &mut build_branch_string as *mut NvAPI_ShortString, + ); + + if result != 0 { + anyhow::bail!( + "Failed to get NVIDIA driver version, error code: {}", + result + ); + } + let major = driver_version / 100; + let minor = driver_version % 100; + Ok(format!("{}.{}", major, minor)) + } + } +} diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index e712d939c87742ee3f7c5df043112853a8ae7a39..a2bc854484cb1e696f950bea07756258091d831a 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -104,6 +104,7 @@ impl WindowsWindowState { let restore_from_minimized = None; // let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?; let renderer = DirectXRenderer::new(gpu_context, hwnd)?; + println!("GPU specs: {:#?}", renderer.gpu_specs()); let callbacks = Callbacks::default(); let input_handler = None; let pending_surrogate = None; @@ -801,7 +802,7 @@ impl PlatformWindow for WindowsWindow { } fn update_ime_position(&self, _bounds: Bounds) { - // todo(windows) + // There is no such thing on Windows. } }