Repository navigation
gpu: redraw only what changed into a framebuffer the renderer keeps - #5
Merged
Merged
Conversation
Partial redraw relied on EGL_BUFFER_AGE, which NVIDIA 595 on COSMIC reports for a buffer that does not hold that frame, so a whole window showed stale pixels. Keep the frame in an sRGB texture the renderer owns, redraw only the damaged rectangles there and blit it whole to the output; the swap stays a plain full swap. The buffer age and swap-with-damage paths go away. It stays behind GIO_DAMAGE=on. A frame goes straight to the output and whole on backends without FeatureBlitFramebuffer, on a frame that did not clear, and on a translucent clear, whose ground would blend over the kept frame. Paths the rectangles do not reach keep their place in the atlas and only lose their stencil, as the place changes a path's coverage by a rounding. Measured in lich on a real NVIDIA GPU on a private headless compositor, a terminal line updating at 19 fps: 1.2-2.0 ms of GL work per frame, from 2.0-3.6 ms drawn whole. A scrolling log, two thirds of the window dirty, costs 0.1-0.4 ms more than drawn whole. The texture is width x height x 4 bytes.
The retained framebuffer no longer reads it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Partial redraw trusted
EGL_BUFFER_AGE, and NVIDIA 595 on COSMIC reports an age its buffer does not hold, so the whole window showed stale pixels. This keeps the frame in an sRGB texture the renderer owns, redraws only the damaged rectangles there, and blits it whole to the output with a plain full swap. Buffer age and swap-with-damage are gone. The behaviour stays behindGIO_DAMAGE=on.Non-OpenGL backends keep drawing whole frames straight to the output (
FeatureBlitFramebuffer), as does any frame without a clear or with a translucent clear, whose ground would blend over the kept frame. Paths the rectangles do not reach keep their place in the atlas and only lose their stencil, because a path's place changes its coverage by a rounding.A second commit logs once when
GL_RENDERERnames a software renderer.Pixel test
gpu/headless/retained_test.godraws 12 seeds of 30 frames changing a little at a time into the retained framebuffer and compares each frame with the same frame drawn whole straight to the output, dropping the retained contents every 11 frames (resize) and requiring a whole redraw. Without stencilled paths the frames match byte for byte. With paths a channel may differ by 1: whole frames drawn with their paths at other atlas positions differ from each other by the same one level (measured, 185 of 3,072,000 bytes across 10 seeds, max delta 1), so byte equality against a whole frame is not defined there.On a real NVIDIA surface, a private headless compositor screenshot of the same window with
GIO_DAMAGEoff and on has 0 differing pixels.Measurements
Real NVIDIA GPU, private headless umbriel, one shell session, 1260x700. GL work per frame is GPU and driver time for the passes and the blit, between two
glFinishcalls, from an uncommitted local instrumentation; render isLICH_NATIVE_FRAME_LOG.The retained texture costs width x height x 4 bytes (3.5 MB at 1260x700). The tracker adds about 47 KiB of allocations per frame.
Test plan
go test ./gpu/... ./app/... ./internal/..., alsoTestPartialFramesMatchWholeandTestPartialPathFramesMatchWholeon NVIDIA and on llvmpipe, 5 repeats on NVIDIAGOOS=windows go build ./...,GOOS=js GOARCH=wasm go build ./gpu/... ./internal/gl/...native/go vet ./...andgo test ./...withreplace gioui.orgpointed at this branch