1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! macOS-specific CAMetalLayer configuration
//!
//! This module accesses the underlying CAMetalLayer created by wgpu/winit
//! to ensure per-pixel transparency is honored and to disable VSync throttling.
use anyhow::Result;
/// Configure CAMetalLayer for optimal transparency + performance on macOS
///
/// This function:
/// 1. Extracts the NSView from the winit window
/// 2. Gets the CAMetalLayer from the view
/// 3. Sets `opaque = false` so per-pixel alpha (content only) is respected
/// 4. Keeps layer `opacity = 1.0` so only rendered pixels control alpha (window chrome untouched)
/// 5. Sets `displaySyncEnabled = false` to disable VSync throttling
/// 6. This allows `surface.present()` to return immediately instead of blocking
pub fn configure_metal_layer_for_performance(window: &winit::window::Window) -> Result<()> {
#[cfg(target_os = "macos")]
{
use objc2::rc::Retained;
use objc2::runtime::AnyObject;
use objc2_app_kit::NSView;
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
log::info!("🎯 Configuring CAMetalLayer for 60 FPS performance");
// Get the raw window handle
let window_handle = window.window_handle()?;
// Extract NSView pointer from AppKit handle
let ns_view_ptr = match window_handle.as_raw() {
RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr(),
_ => anyhow::bail!("Not a macOS AppKit window"),
};
// SAFETY: `ns_view_ptr` is a non-null NSView pointer obtained from winit's AppKit
// window handle. winit guarantees the pointer is valid and that this function is
// called on the main thread (required by AppKit/Objective-C). Casting to
// `*mut NSView` and creating a shared reference is valid because the type matches
// and the pointer is aligned and properly initialized by the runtime.
//
// `msg_send![view, layer]` is a safe Objective-C message on a valid NSView;
// it returns a retained `AnyObject` whose lifetime is managed by `Retained<T>`.
// `msg_send![metal_layer_ptr, class]` returns the metaclass object — non-null
// for any live Objective-C object. Dereferencing `class_obj` is safe because
// every Objective-C object has an associated class.
//
// The `setOpaque:`, `setOpacity:`, `setDisplaySyncEnabled:`, and
// `displaySyncEnabled` messages are only sent after verifying the layer is a
// `CAMetalLayer` by name check, so the Metal-specific selectors are valid.
unsafe {
// Cast to NSView
let ns_view = ns_view_ptr as *mut NSView;
let view = &*ns_view;
// Get the layer (should be CAMetalLayer, created by wgpu)
let layer: Retained<AnyObject> = objc2::msg_send![view, layer];
// Get raw pointer to layer
let metal_layer_ptr = Retained::as_ptr(&layer);
// Check if this is actually a CAMetalLayer before calling Metal-specific methods
// Get the class object
let class_obj: *const objc2::runtime::AnyClass =
objc2::msg_send![metal_layer_ptr, class];
// Get the class name from the class object
let class_name = objc2::runtime::AnyClass::name(&*class_obj);
let class_name_str = class_name.to_str().unwrap_or("Unknown");
log::info!("Layer class: {}", class_name_str);
if class_name_str == "CAMetalLayer" {
// Allow per-pixel transparency (content only)
let _: () = objc2::msg_send![metal_layer_ptr, setOpaque: false];
// Keep global layer opacity at 1.0; we rely on per-pixel alpha instead
let _: () = objc2::msg_send![metal_layer_ptr, setOpacity: 1.0_f32];
// Set displaySyncEnabled to false
// This is the KEY to bypassing macOS VSync throttling
let _: () = objc2::msg_send![metal_layer_ptr, setDisplaySyncEnabled: false];
// Verify the setting was applied
let display_sync_enabled: bool =
objc2::msg_send![metal_layer_ptr, displaySyncEnabled];
log::info!(
"✅ CAMetalLayer configured: displaySyncEnabled = {}",
display_sync_enabled
);
if display_sync_enabled {
log::warn!(
" ⚠️ displaySyncEnabled is still true! Setting may not have taken effect."
);
} else {
log::info!(" Expected: present() will no longer block for VSync");
log::info!(" Target: 60+ FPS instead of ~20 FPS");
}
} else {
log::warn!(
"❌ Layer is not CAMetalLayer (found: {}), skipping configuration",
class_name_str
);
log::warn!(" This is normal if called before wgpu creates the Metal surface");
log::warn!(" Will retry after renderer initialization");
anyhow::bail!("Layer is not yet a CAMetalLayer");
}
}
}
#[cfg(not(target_os = "macos"))]
{
let _ = window; // Silence unused warning
}
Ok(())
}
/// Update CAMetalLayer opacity (affects rendered content only, not window chrome)
pub fn set_layer_opacity(window: &winit::window::Window, opacity: f32) -> Result<()> {
#[cfg(target_os = "macos")]
{
use objc2::rc::Retained;
use objc2::runtime::AnyObject;
use objc2_app_kit::NSView;
use raw_window_handle::{HasWindowHandle, RawWindowHandle};
let clamped = opacity.clamp(0.0, 1.0);
let window_handle = window.window_handle()?;
let ns_view_ptr = match window_handle.as_raw() {
RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr(),
_ => anyhow::bail!("Not a macOS AppKit window"),
};
if ns_view_ptr.is_null() {
anyhow::bail!("NSView pointer is null");
}
// SAFETY: ns_view_ptr is a non-null NSView pointer obtained from winit's AppKit
// window handle. winit guarantees it is valid for the lifetime of the window.
// We are on the main thread (required by AppKit/winit), so Objective-C message
// sends are safe. The layer obtained via `msg_send![view, layer]` is retained
// by the view and remains valid for the duration of this block.
unsafe {
let ns_view = ns_view_ptr as *mut NSView;
let layer: Retained<AnyObject> = objc2::msg_send![ns_view, layer];
let metal_layer_ptr = Retained::as_ptr(&layer);
// Ensure per-pixel alpha is allowed and set content opacity
let _: () = objc2::msg_send![metal_layer_ptr, setOpaque: false];
let _: () = objc2::msg_send![metal_layer_ptr, setOpacity: clamped];
let current_opacity: f32 = objc2::msg_send![metal_layer_ptr, opacity];
log::debug!(
"CAMetalLayer content opacity set to {:.3} (reported {:.3})",
clamped,
current_opacity
);
}
}
#[cfg(not(target_os = "macos"))]
{
let _ = (window, opacity);
}
Ok(())
}
// (Layer opacity remains fixed at 1.0; per-pixel transparency handled in renderer.)