add amd gpu version support

This commit is contained in:
Junkui Zhang 2025-07-18 15:11:49 +08:00
parent c7342a9df5
commit 0b57c86e07
5 changed files with 137 additions and 10 deletions

View file

@ -9,7 +9,10 @@ fn main() {
let target = env::var("CARGO_CFG_TARGET_OS");
println!("cargo::rustc-check-cfg=cfg(gles)");
#[cfg(any(not(target_os = "macos"), feature = "macos-blade"))]
#[cfg(any(
not(any(target_os = "macos", target_os = "windows")),
feature = "macos-blade"
))]
check_wgsl_shaders();
match target.as_deref() {
@ -17,15 +20,9 @@ fn main() {
#[cfg(target_os = "macos")]
macos::build();
}
#[cfg(all(target_os = "windows", feature = "windows-manifest"))]
Ok("windows") => {
let manifest = std::path::Path::new("resources/windows/gpui.manifest.xml");
let rc_file = std::path::Path::new("resources/windows/gpui.rc");
println!("cargo:rerun-if-changed={}", manifest.display());
println!("cargo:rerun-if-changed={}", rc_file.display());
embed_resource::compile(rc_file, embed_resource::NONE)
.manifest_required()
.unwrap();
#[cfg(target_os = "windows")]
windows::build();
}
_ => (),
};
@ -243,3 +240,45 @@ mod macos {
}
}
}
#[cfg(target_os = "windows")]
mod windows {
use std::path::PathBuf;
pub(super) fn build() {
// Link the AMD AGS library
link_amd_ags();
// Embed the Windows manifest and resource file
#[cfg(feature = "windows-manifest")]
embed_resource();
}
fn link_amd_ags() {
// We can not use relative paths in `cargo:rustc-link-search`, so we need to use the absolute path.
// See: https://stackoverflow.com/questions/41917096/how-do-i-make-rustc-link-search-relative-to-the-project-location
let lib_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("libs");
#[cfg(target_pointer_width = "64")]
let lib_name = "amd_ags_x64_2022_MT";
#[cfg(target_pointer_width = "32")]
let lib_name = "amd_ags_x86_2022_MT";
println!("cargo:rustc-link-lib=static={}", lib_name);
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!(
"cargo:rerun-if-changed={}/{}.lib",
lib_dir.display(),
lib_name
);
}
#[cfg(feature = "windows-manifest")]
fn embed_resource() {
let manifest = std::path::Path::new("resources/windows/gpui.manifest.xml");
let rc_file = std::path::Path::new("resources/windows/gpui.rc");
println!("cargo:rerun-if-changed={}", manifest.display());
println!("cargo:rerun-if-changed={}", rc_file.display());
embed_resource::compile(rc_file, embed_resource::NONE)
.manifest_required()
.unwrap();
}
}

View file

@ -0,0 +1,10 @@
The files in this folder are required for the Windows platform support in the gpui library.
#### amd_ags_x64.lib & amd_ags_x86.lib
These libraries are used for AMD GPU support, currently only used on Windows, mainly for retrieving GPU information and capabilities. They are linked against the AMD AGS (AMD GPU Services) library.
The official AMD AGS documentation can be found [here](https://gpuopen.com/amd-gpu-services-ags-library). And these two files are grabbed from the [official AMD AGS repository](https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK), currently at version 6.3.0.
If you want to update these files, don't forget to update the value of `AGS_CURRENT_VERSION` in `gpui/src/platform/windows/directx_renderer.rs` as well.

Binary file not shown.

Binary file not shown.

View file

@ -413,7 +413,7 @@ impl DirectXRenderer {
};
let driver_version = match desc.VendorId {
0x10DE => nvidia::get_driver_version(),
0x1002 => Err(anyhow::anyhow!("AMD driver info not implemented yet")),
0x1002 => amd::get_driver_version(),
0x8086 => intel::get_driver_version(&self.devices.adapter),
_ => Err(anyhow::anyhow!("Unknown vendor detected.")),
}
@ -1438,6 +1438,84 @@ mod nvidia {
}
}
mod amd {
use std::os::raw::{c_char, c_int, c_void};
// https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L145
const AGS_CURRENT_VERSION: i32 = (6 << 22) | (3 << 12) | 0;
// https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/blob/5d8812d703d0335741b6f7ffc37838eeb8b967f7/ags_lib/inc/amd_ags.h#L204
// This is an opaque type, using struct to represent it properly for FFI
#[repr(C)]
struct AGSContext {
_private: [u8; 0],
}
#[repr(C)]
pub struct AGSGPUInfo {
pub driver_version: *const c_char,
pub radeon_software_version: *const c_char,
pub num_devices: c_int,
pub devices: *mut c_void,
}
unsafe extern "C" {
fn agsInitialize(
version: c_int,
config: *const c_void,
context: *mut *mut AGSContext,
gpu_info: *mut AGSGPUInfo,
) -> c_int;
fn agsDeInitialize(context: *mut AGSContext) -> c_int;
}
pub(super) fn get_driver_version() -> anyhow::Result<String> {
unsafe {
let mut context: *mut AGSContext = std::ptr::null_mut();
let mut gpu_info: AGSGPUInfo = AGSGPUInfo {
driver_version: std::ptr::null(),
radeon_software_version: std::ptr::null(),
num_devices: 0,
devices: std::ptr::null_mut(),
};
let result = agsInitialize(
AGS_CURRENT_VERSION,
std::ptr::null(),
&mut context,
&mut gpu_info,
);
if result != 0 {
return Err(anyhow::anyhow!(
"Failed to initialize AGS, error code: {}",
result
));
}
// Vulkan acctually returns this as the driver version
let software_version = if !gpu_info.radeon_software_version.is_null() {
std::ffi::CStr::from_ptr(gpu_info.radeon_software_version)
.to_string_lossy()
.into_owned()
} else {
"Unknown Radeon Software Version".to_string()
};
let driver_version = if !gpu_info.driver_version.is_null() {
std::ffi::CStr::from_ptr(gpu_info.driver_version)
.to_string_lossy()
.into_owned()
} else {
"Unknown Radeon Driver Version".to_string()
};
agsDeInitialize(context);
Ok(format!("{} ({})", software_version, driver_version))
}
}
}
mod intel {
use windows::{
Win32::Graphics::Dxgi::{IDXGIAdapter1, IDXGIDevice},