diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index b9496cc01426485cbef625c7e697bbf6082d1a67..6bb63ee67fd2b33675f864f22620988325666636 100644 --- a/crates/gpui/build.rs +++ b/crates/gpui/build.rs @@ -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(); } _ => (), }; @@ -242,3 +239,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(); + } +} diff --git a/crates/gpui/libs/README.md b/crates/gpui/libs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2be286ee5352c21dc2bb5e2d1ca04cf25b8f746d --- /dev/null +++ b/crates/gpui/libs/README.md @@ -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. diff --git a/crates/gpui/libs/amd_ags_x64_2022_MT.lib b/crates/gpui/libs/amd_ags_x64_2022_MT.lib new file mode 100644 index 0000000000000000000000000000000000000000..a25d772160ddadcc98ce777c0e73a57e9f05a59a Binary files /dev/null and b/crates/gpui/libs/amd_ags_x64_2022_MT.lib differ diff --git a/crates/gpui/libs/amd_ags_x86_2022_MT.lib b/crates/gpui/libs/amd_ags_x86_2022_MT.lib new file mode 100644 index 0000000000000000000000000000000000000000..cdb1305378fa058b0e3ffcdeeca8d4ee4e28318b Binary files /dev/null and b/crates/gpui/libs/amd_ags_x86_2022_MT.lib differ diff --git a/crates/gpui/src/platform/windows/directx_renderer.rs b/crates/gpui/src/platform/windows/directx_renderer.rs index 54478e9b02dc4a982e72d0fdd487cea158d7dae7..4e804e74dcb2b99a566a727a3826bb47886fcfb1 100644 --- a/crates/gpui/src/platform/windows/directx_renderer.rs +++ b/crates/gpui/src/platform/windows/directx_renderer.rs @@ -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 { + 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},