This re-introduces the changes of #7305 but this time we create a
display link using the `NSScreen` associated with the window. We're
hoping we'll get these frame requests more reliably, and this seems
supported by the fact that awakening my laptop restores the frame
requests.
Release Notes:
- See #7305.
Co-authored-by: Nathan <nathan@zed.dev>
This pull request decreases the size of each instance buffer and shares
instance buffers across windows.
Release Notes:
- Improved GPU memory usage.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
This is achieved by starting a `CADisplayLink` that will invoke the
`on_request_frame` callback at the refresh interval of the display.
We only actually draw frames when the window was dirty, or for 2 extra
seconds after the last input event to ensure ProMotion doesn't downclock
the refresh rate when the user is actively interacting with the window.
Release Notes:
- Improved performance when using a ProMotion display with fast key
repeat rates.
---------
Co-authored-by: Nathan Sobo <nathan@zed.dev>
This fixes a panic happening when releasing an instance buffer.
Releasing the buffer happens on a different thread but the borrow
checker was not catching it because the metal buffer completion handler
API doesn't have a `Send` marker on it.
Release Notes:
- N/A
This commit goes back to using `wait_until_scheduled` as opposed to
`wait_until_completed`. What this means, however, is that another draw
could take place before the previous one finished. When that happens we
don't want to reuse the same instance buffer because the GPU is actively
reading from it, so we use a pool instead.
Release Notes:
- Fixed a bug that caused inconsistent frame rate when scrolling on
certain hardware.
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Antonio <antonio@zed.dev>
Release Notes:
- Fixed a bug that caused inconsistent frame rate when scrolling on
certain hardware.
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Nathan Sobo <nathan@zed.dev>
The fonts we embed in Zed binary (Zed Sans & Zed Mono) weigh about 30Mb in total and we are cloning them several times during startup and loading of embedded assets (once explicitly in Zed and then under the hood in font-kit). Moreover, after loading we have at least 2 copies of each font in our program; one in .rdata and the other on the heap for use by font-kit.
This commit does away with that distinction (we're no longer allocating the font data) and slightly relaxes the interface of `TextSystem::add_fonts` by expecting one to pass `Cow<[u8]>` instead of `Arc<Vec<u8>>`. Additionally, `AssetSource::get` now returns `Cow<'static, [u8]>` instead of `Cow<'self, [u8]>`; all existing implementations conform with that change.
Note that this optimization takes effect only in Release builds, as the library we use for asset embedding - rust-embed - embeds the assets only in Release mode and in Dev builds it simply loads data from disk. Thus it returns `Cow<[u8]>` in it's interface. Therefore, we still copy that memory around in Dev builds, but that's not really an issue.
This patch makes no assumptions about the build profile we're running under, that's just an intrinsic property of rust-embed.
Tl;dr: this should shave off about 30Mb of memory usage and a fair chunk (~30ms) of startup time.
Release Notes:
- Improved startup time and memory usage.
Sometimes Cocoa calls app delegate methods (notably the display link)
while we're calling Cocoa methods. This causes a deadlock unless we
are careful to run cocao methods while we're not holding our internal
locks
- it seems like layer.drawable_size() is 0,0 in metal_renderer.rs:189
- we set this in two places:
- in response to a CALayerDelegate setFrameSize: event
- in response to a CALayerDelegate viewDidChangeBackingProperties:
event.
- it looks like if we don't set it in either of these cases we get a
different failure mode: the view is zoomed just wrong.
- That said, I can reproduce the screenshot if .scale_factor() returns
0.
- This might happen if [nativeWindow screen] is nil, which happens when
the window is off screen.
- possible that zed started with offscreen window?
- I would expect that viewDidChangeBackingProperties would fire when
that changed.
- potential fix: default to 2.0
Release Notes:
- Fixed Zed occasionally rendering blank on laungh
([#2422](https://github.com/zed-industries/community/issues/2422)).
Before this change if you had a matching binding and a pending key,
the matching binding happened unconditionally.
Now we will wait a second before triggering that binding to give you
time to complete the action.
CGDisplayBounds returns data in "global display coordinates" (which are
the same as Zed's coordinates), different from the NS APIs which use
"screen coordinates" (which have the Y axis inverted)
Also remove some transmutes while we're at it
Adding the typos crate to our CI will take some doing, as we have
several tests which rely on typos in various ways (e.g. checking state
as the user types), but I thought I'd take a first stab at fixing what
it finds.
Release Notes:
- N/A
When the `List` element's state is `ListState::reset()`, it eagerly
trashes it's cached element heights in anticipation of a prompt render.
But, due to the recent `display_layer` changes, that re-render is not
always forthcoming. This is a problem for `ListState::scroll()`, which
depends on these cached elements to correctly calculate the new logical
scroll offset.
Solutions we attempted:
- Cache the element heights and continue the scroll calculation
- This was conceptually incorrect, reset should only be called when the
underlying data has been changed, making any calculation with the old
results meaningless.
- Lazily re-compute the element heights in scroll
- Beyond being a non-trivial refactor, this would probably also cause us
to double-render the list in a single frame, which is bad.
- Cache the scroll offset and only calculate it in paint
- This solution felt awkward to implement and meant we can't supply
synchronous list scroll events.
- Delay resetting until paint
- This means that all of the other APIs that `ListState` supplies would
give temporarily incorrect results, worsening the problem
Given these issues, we settled on the solution with the least
compromises: drop scroll events if the state has been `reset()` between
`paint()` and `scroll()`. This shifts the responsibility for the problem
out of the List element and into consumers of `List`, if you want
perfectly smooth scrolling then you need to use `reset()` judiciously
and prefer `splice()`.
That said, I tested this by aggressively scrolling the Collab panel, and
it seems to work as well as it did before.
This PR also includes some initial testing infrastructure for working
with input from the platform and rendered elements.
Release Notes:
- N/A
Previously, we were using `size_of` but passing the wrong type in
(MonochromeSprite instead of PathSprite). This caused us to read outside
of the `sprites` smallvec and triggered the segfault.
We're occasionally seeing a crash in MetalRenderer::draw.
Looking at the backtrace, it seems almost certainly to be happening in
the call to `ptr::copy_nonoverlapping` on line 604 (see `#Don't Panic!`
channel notes)
As we already have added bounds checking to the destination, it seems
most
likely (however improbable) that somehow we're getting an invalid Ptr
and
length from the SmallVec.
To try and make progress on this, let's try a Vec for a bit lest there
is a subtle issue in SmallVec (though I couldn't spot one).
Release Notes:
- (maybe) Fixes SEGFAULT in MetalRenderer::draw
According to Chromium source, `NSScreen::screens` should always get us
one display.
We made this change because we ran into panics caused by the previous
`unwrap()` when `CGGetActiveDisplayList` might return an empty list.
Previously we called CGGetActiveDisplayList twice: once to get the
number of displays and then to get the displays.
We saw a panic due to no displays being returned here. As a first
attempt to fix the panic, we're reducing the amount of calls to
CGGetActiveDisplayList and just do one with the trade-off being that we
pre-allocate 32 pointers in a Vec.