Compare commits
3 Commits
arm_github
...
gpu-prefer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ab1475f26 | ||
|
|
aef9751e05 | ||
|
|
c68c8928c2 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -13699,6 +13699,7 @@ dependencies = [
|
||||
"release_channel",
|
||||
"repl",
|
||||
"rope",
|
||||
"schemars",
|
||||
"search",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -67,5 +67,6 @@ fn notification_window_options(
|
||||
app_id: Some(app_id.to_owned()),
|
||||
window_min_size: None,
|
||||
window_decorations: Some(WindowDecorations::Client),
|
||||
gpu: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ fn build_window_options(display_id: DisplayId, bounds: Bounds<Pixels>) -> Window
|
||||
app_id: None,
|
||||
window_min_size: None,
|
||||
window_decorations: None,
|
||||
gpu: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +252,16 @@ pub enum Decorations {
|
||||
},
|
||||
}
|
||||
|
||||
/// A type to describe which GPU to prefer.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
|
||||
pub enum Gpu {
|
||||
/// The window is rendered using the integrated (lower-power) GPU
|
||||
#[default]
|
||||
Integrated,
|
||||
/// The window is rendered using the discrete GPU
|
||||
Discrete,
|
||||
}
|
||||
|
||||
/// What window controls this platform supports
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
|
||||
pub struct WindowControls {
|
||||
@@ -679,6 +689,10 @@ pub struct WindowOptions {
|
||||
/// Whether to use client or server side decorations. Wayland only
|
||||
/// Note that this may be ignored.
|
||||
pub window_decorations: Option<WindowDecorations>,
|
||||
|
||||
/// Whether to prefer one GPU over another. macOS only
|
||||
/// Note that this may be ignored.
|
||||
pub gpu: Option<Gpu>,
|
||||
}
|
||||
|
||||
/// The variables that can be configured when creating a new window
|
||||
@@ -707,6 +721,11 @@ pub(crate) struct WindowParams {
|
||||
|
||||
#[cfg_attr(target_os = "linux", allow(dead_code))]
|
||||
pub window_min_size: Option<Size<Pixels>>,
|
||||
|
||||
/// Whether to prefer one GPU over another. macOS only
|
||||
/// Note that this may be ignored.
|
||||
#[cfg_attr(target_os = "linux", allow(dead_code))]
|
||||
pub gpu: Option<Gpu>,
|
||||
}
|
||||
|
||||
/// Represents the status of how a window should be opened.
|
||||
@@ -757,6 +776,7 @@ impl Default for WindowOptions {
|
||||
app_id: None,
|
||||
window_min_size: None,
|
||||
window_decorations: None,
|
||||
gpu: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
use super::{BladeAtlas, PATH_TEXTURE_FORMAT};
|
||||
use crate::{
|
||||
AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, Hsla, MonochromeSprite, Path,
|
||||
PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size,
|
||||
Underline,
|
||||
AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, Gpu, Hsla, MonochromeSprite,
|
||||
Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow,
|
||||
Size, Underline,
|
||||
};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use collections::HashMap;
|
||||
@@ -32,6 +32,7 @@ pub unsafe fn new_renderer(
|
||||
native_view: *mut c_void,
|
||||
bounds: crate::Size<f32>,
|
||||
transparent: bool,
|
||||
_gpu: Option<Gpu>,
|
||||
) -> Renderer {
|
||||
use raw_window_handle as rwh;
|
||||
struct RawWindow {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::metal_atlas::MetalAtlas;
|
||||
use crate::{
|
||||
point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels,
|
||||
Hsla, MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad,
|
||||
Gpu, Hsla, MonochromeSprite, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad,
|
||||
ScaledPixels, Scene, Shadow, Size, Surface, Underline,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
@@ -38,8 +38,9 @@ pub unsafe fn new_renderer(
|
||||
_native_view: *mut c_void,
|
||||
_bounds: crate::Size<f32>,
|
||||
_transparent: bool,
|
||||
gpu: Option<Gpu>,
|
||||
) -> Renderer {
|
||||
MetalRenderer::new(context)
|
||||
MetalRenderer::new(context, gpu)
|
||||
}
|
||||
|
||||
pub(crate) struct InstanceBufferPool {
|
||||
@@ -108,13 +109,19 @@ pub(crate) struct MetalRenderer {
|
||||
}
|
||||
|
||||
impl MetalRenderer {
|
||||
pub fn new(instance_buffer_pool: Arc<Mutex<InstanceBufferPool>>) -> Self {
|
||||
// Prefer low‐power integrated GPUs on Intel Mac. On Apple
|
||||
// Silicon, there is only ever one GPU, so this is equivalent to
|
||||
// `metal::Device::system_default()`.
|
||||
let mut devices = metal::Device::all();
|
||||
devices.sort_by_key(|device| (!device.is_removable(), device.is_low_power()));
|
||||
let Some(device) = devices.pop() else {
|
||||
pub fn new(instance_buffer_pool: Arc<Mutex<InstanceBufferPool>>, gpu: Option<Gpu>) -> Self {
|
||||
let device = match gpu {
|
||||
Some(Gpu::Discrete) => metal::Device::system_default(),
|
||||
_ => {
|
||||
// By default, prefer low‐power integrated GPUs on Intel Mac. On Apple
|
||||
// Silicon, there is only ever one GPU, so this is equivalent to
|
||||
// `metal::Device::system_default()`.
|
||||
let mut devices = metal::Device::all();
|
||||
devices.sort_by_key(|device| (!device.is_removable(), device.is_low_power()));
|
||||
devices.pop()
|
||||
}
|
||||
};
|
||||
let Some(device) = device else {
|
||||
log::error!("unable to access a compatible graphics device");
|
||||
std::process::exit(1);
|
||||
};
|
||||
|
||||
@@ -505,6 +505,7 @@ impl MacWindow {
|
||||
show,
|
||||
display_id,
|
||||
window_min_size,
|
||||
gpu,
|
||||
}: WindowParams,
|
||||
executor: ForegroundExecutor,
|
||||
renderer_context: renderer::Context,
|
||||
@@ -603,6 +604,7 @@ impl MacWindow {
|
||||
native_view as *mut _,
|
||||
bounds.size.map(|pixels| pixels.0),
|
||||
false,
|
||||
gpu,
|
||||
),
|
||||
request_frame_callback: None,
|
||||
event_callback: None,
|
||||
|
||||
@@ -645,6 +645,7 @@ impl Window {
|
||||
app_id,
|
||||
window_min_size,
|
||||
window_decorations,
|
||||
gpu,
|
||||
} = options;
|
||||
|
||||
let bounds = window_bounds
|
||||
@@ -661,6 +662,7 @@ impl Window {
|
||||
show,
|
||||
display_id,
|
||||
window_min_size,
|
||||
gpu,
|
||||
},
|
||||
)?;
|
||||
let display_id = platform_window.display().map(|display| display.id());
|
||||
|
||||
@@ -86,6 +86,7 @@ serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
settings.workspace = true
|
||||
simplelog.workspace = true
|
||||
schemars.workspace = true
|
||||
smol.workspace = true
|
||||
snippet_provider.workspace = true
|
||||
tab_switcher.workspace = true
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod app_menus;
|
||||
mod gpu;
|
||||
pub mod inline_completion_registry;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) mod linux_prompts;
|
||||
@@ -11,6 +12,7 @@ use breadcrumbs::Breadcrumbs;
|
||||
use client::ZED_URL_SCHEME;
|
||||
use collections::VecDeque;
|
||||
use editor::{scroll::Autoscroll, Editor, MultiBuffer};
|
||||
use gpu::GpuSettings;
|
||||
use gpui::{
|
||||
actions, point, px, AppContext, AsyncAppContext, Context, FocusableView, MenuItem, PromptLevel,
|
||||
ReadGlobal, TitlebarOptions, View, ViewContext, VisualContext, WindowKind, WindowOptions,
|
||||
@@ -78,6 +80,7 @@ pub fn init(cx: &mut AppContext) {
|
||||
cx.on_action(|_: &ShowAll, cx| cx.unhide_other_apps());
|
||||
cx.on_action(quit);
|
||||
|
||||
GpuSettings::register(cx);
|
||||
if ReleaseChannel::global(cx) == ReleaseChannel::Dev {
|
||||
cx.on_action(test_panic);
|
||||
}
|
||||
@@ -115,6 +118,7 @@ pub fn build_window_options(display_uuid: Option<Uuid>, cx: &mut AppContext) ->
|
||||
width: px(360.0),
|
||||
height: px(240.0),
|
||||
}),
|
||||
gpu: GpuSettings::get_global(cx).gpu.map(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
46
crates/zed/src/zed/gpu.rs
Normal file
46
crates/zed/src/zed/gpu.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings, SettingsSources};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, PartialEq, Eq, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Gpu {
|
||||
Discrete,
|
||||
#[default]
|
||||
Integrated,
|
||||
}
|
||||
|
||||
impl Into<gpui::Gpu> for Gpu {
|
||||
fn into(self) -> gpui::Gpu {
|
||||
match self {
|
||||
Gpu::Discrete => gpui::Gpu::Discrete,
|
||||
Gpu::Integrated => gpui::Gpu::Integrated,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings related to the machine's GPU and how Zed uses it.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
|
||||
pub struct GpuSettings {
|
||||
/// Which GPU to prefer: discrete or integrated.
|
||||
/// Integrated are often lower-power and thus more battery-efficient.
|
||||
///
|
||||
/// Default: 0.2
|
||||
pub gpu: Option<Gpu>,
|
||||
}
|
||||
|
||||
impl Settings for GpuSettings {
|
||||
const KEY: Option<&'static str> = None;
|
||||
|
||||
type FileContent = Option<Self>;
|
||||
|
||||
fn load(
|
||||
sources: SettingsSources<Self::FileContent>,
|
||||
_: &mut gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
if let Some(Some(user_value)) = sources.user.copied() {
|
||||
return Ok(user_value);
|
||||
}
|
||||
Ok(Self::default())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user