gpui/blade: Allow forcing use of a specific GPU with `ZED_DEVICE_ID` env var (#27531)

Ben Kunkle created

Workaround for users affected by #25899

Thanks to the work done by @kvark in
https://github.com/kvark/blade/pull/210, we have the ability to tell
Vulkan (through blade) a specific GPU to use.

This will hopefully allow some of the users affected by #25899 to use
Zed by allowing them to use a specific GPU, if the primary/default GPU
will not work

Release Notes:

- Added the ability to specify which GPU Zed uses on Linux by setting
the `ZED_DEVICE_ID` environment variable. You can obtain the device ID
of your GPU by running `lspci -nn | grep VGA` which will output each GPU
on one line like:
  ```
08:00.0 VGA compatible controller [0300]: NVIDIA Corporation GA104
[GeForce RTX 3070] [10de:2484] (rev a1)
  ````
where the device ID here is `2484`. This value is in hexadecimal, so to
force Zed to use this specific GPU you would set the environment
variable like so:
  ```
  ZED_DEVICE_ID=0x2484
  ```
Make sure to export the variable if you choose to define it globally in
a `.bashrc` or similar

Change summary

crates/gpui/src/platform/blade/blade_context.rs | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)

Detailed changes

crates/gpui/src/platform/blade/blade_context.rs 🔗

@@ -1,5 +1,7 @@
+use anyhow::Context as _;
 use blade_graphics as gpu;
 use std::sync::Arc;
+use util::ResultExt;
 
 #[cfg_attr(target_os = "macos", derive(Clone))]
 pub struct BladeContext {
@@ -8,12 +10,24 @@ pub struct BladeContext {
 
 impl BladeContext {
     pub fn new() -> anyhow::Result<Self> {
+        let device_id_forced = match std::env::var("ZED_DEVICE_ID") {
+            Ok(val) => val
+                .parse()
+                .context("Failed to parse device ID from `ZED_DEVICE_ID` environment variable")
+                .log_err(),
+            Err(std::env::VarError::NotPresent) => None,
+            err => {
+                err.context("Failed to read value of `ZED_DEVICE_ID` environment variable")
+                    .log_err();
+                None
+            }
+        };
         let gpu = Arc::new(
             unsafe {
                 gpu::Context::init(gpu::ContextDesc {
                     presentation: true,
                     validation: false,
-                    device_id: 0, //TODO: hook up to user settings
+                    device_id: device_id_forced.unwrap_or(0),
                     ..Default::default()
                 })
             }