diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index 7ab44a73f5532f3a37fd07f16a384535b5909485..8f0c0da6dd0f906975c74a03463f22300287918d 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(); } _ => (), }; @@ -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(); + } +} 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},