Commit Graph

211 Commits

Author SHA1 Message Date
Elias Naur e6c31a02fd gpu: [compute] cache and re-use drawing operations from the previous frame
The compute renderer is more expensive to run than the old renderer on
low-end GPUs, and even more so on CPUs. To ensure good performance
regardless of the end-user device, this change implements automatic
re-use of content rendered in the frame before the current.

The basic idea is that every drawing operation (PaintOp), along with its
transform and clipping, can be hashed and efficiently looked up. A naïve
caching approach is then to rasterize every operation to separate
sections of several large texture atlases, turning a cache hit into a
very cheap texture copy.

However, for scenes with lots of overlapping operations, the resulting
texture memory from separating the operations would be much larger than
the memory for just the window framebuffer.

So instead of caching individual operations, this change caches layers,
which are sequences of drawing operations. It starts by putting all
operations into a single layer. Then, if the subsequent frame re-uses a
sub-sequence of that larger layer, it is split.

For example, consider a UI similar to the kitchen sample:

Hello, Gio

<Editor>

<Line Editor>

<Button> <Button> <Button>

<ProgressBar>

<Checkbox> <Toggle>

In the first frame, all of the drawing operations comprising the UI will
be stored and cached in a single layer. In the second frame the
progress bar will have moved and the renderer splits the UI into three
layers: layer A for everything up to (but not including) the progress
bar, layer B with just the progress bar, and layer C for the rest. Note
that nothing has been re-used yet. In the third frame, the progress bar
moves again, and this time layer A and C can be copied from the cache
only the progress bar needs redrawing through the compute programs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur 938e51f111 gpu: [compute] clear viewport through glClear, not through compute
The performance difference is negligible, but is useful when the compute
pipeline can skip rendering to empty tiles.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur 89ab5ebf4f gpu: [compute] unify resource cleanup
Rename all resource release methods to "Release", and release all
resources with a slice and loop.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur b87cbc04f3 gpu: [compute] add compute renderer specific decoding of ops
Until now, the two renderers have shared structures and code for
decoding drawing ops and convert them to GPU-friendly structures.

However, the decoder is tailored to the old renderer and use
structures that poorly fits the new compute renderer.

This change copies the decoder and specializes the copy for the compute
renderer, avoiding a round-trip through the old renderer decoder.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur 60a47e7de5 gpu/internal,internal/gl: add support for strided texture uploads
The CPU fallback of the compute renderer needs to upload subtextures
from a larger image.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur abfbeb87cc gpu/internal/d3d11: stub BlitFramebuffer for D3D11
The compute renderer doesn't run on Windows yet, but the d3d11 backend needs
the method to satisfy the driver interface.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
Elias Naur 9188690e9e gpu: [compute] don't leak a texture if its framebuffer allocation fails
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 12:57:53 +02:00
Elias Naur 060ae1cdf9 all: add //go:build lines
They're automatically added by Go 1.17 source formatters. This change
adds them all now.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-26 15:17:51 +02:00
Elias Naur 4f40b58e0d gpu/shaders: fix GPU hang
This is a port of https://github.com/linebender/piet-gpu/pull/108.

Updates gio#214
Updates gio#219

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-19 19:20:05 +02:00
Elias Naur 62a8b80c81 internal/ops,gpu: remove transform fields from ops.Key
The transformation information in ops.Key is a layer violation.
Introduce a key type specific to package gpu and use that instead.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-19 16:37:06 +02:00
Elias Naur e4fe56c456 gpu: release all resources in resourceCache.release
Fixes gio#245

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-18 17:57:39 +01:00
Elias Naur d9a0b4be76 gpu: refresh shaders.go
For some reason, commit d331f63d20 didn't
update the generated code for material.vert properly. The outdated
version is equivalent to the new, so I only discovered this discrepancy
while changing some other shader.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-13 09:57:36 +02:00
Elias Naur d331f63d20 gpu: [compute] move material clip space transformation to the GPU
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-28 08:35:41 +02:00
Elias Naur 75c9736708 op/paint: skip zero images
Updates gio#235

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-16 12:01:42 +02:00
Elias Naur 9b5e9ae607 gpu/internal/opengl: restore BeginFrame state in EndFrame
To ease the integration with foreign OpenGL contexts, carefully save the
context state before rendering a frame and restore it afterwards. Gio
rendering can then be mixed with OpenGL code that expects exclusive
control over context state.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-11 21:02:18 +02:00
Elias Naur 200957f924 gpu/headless: remove macOS context preparation no longer necessary
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-11 09:48:25 +02:00
Elias Naur 476d2269a6 gpu/internal/opengl,app/internal/wm: generalize desktop OpenGL support
This changes moves the macOS specific setup for desktop OpenGL to the
portable opengl package. The opengl package already takes care of the
desktop OpenGL setup for sRGB framebuffers, and by moving the code we
avoid calling the wrong OpenGL functions in case both OpenGL.framework
and ANGLE libGLESv2.dylib is linked into the program.

Remove the interface casting expressions for gl.Functions; it wasn't
worth the trouble to keep updated.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-06-01 18:26:11 +02:00
Elias Naur 03ee75fd72 gpu/internal/opengl: support sRGB emulation for desktop OpenGL
Desktop OpenGL implements a GL_FRAMEBUFFER_SRGB setting; query that instead
of the frambuffer color encoding.

With this change it is no longer necessary to enable FRAMEBUFFER_SRGB
in the macOS setup; remove it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-18 14:26:45 +01:00
Elias Naur b622412ac6 gpu: support forced OpenGL ES mode, for ANGLE on macOS
macOS is the only platform where desktop OpenGL is used. To support
foreign ANGLE contexts add a setting to override Gio's selection of
OpenGL implementation.

The bulk of this change is making all function pointers per-context
instead of global, and loading the OpenGL library dynamically. As a side
effect we're closer to Gio tolerating a platform without any OpenGL
implementation. For example, Apple has deprecated OpenGL and OpenGL ES
on its platforms and may remove them in the future.

Note that as a side-effect of this change, Gio needs Go 1.16 or newer to
run on iOS.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-18 14:26:45 +01:00
Elias Naur 39775f555a gp/internal/opengl: support sRGB emulation for embedded content
Programs such as gio-example/glfw rely on Gio drawing blending with
the framebuffer background. This change makes it so when sRGB emulation
is active.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-16 18:17:00 +02:00
Elias Naur 566b4b166b gpu/internal/opengl: remove unused type alias
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-16 11:18:42 +02:00
Elias Naur 21c319ace5 gpu/internal/opengl,internal: move sRGB emulation to OpenGL driver
There is only one driver but several backends (EGL, WebGL).

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-16 10:44:45 +02:00
Elias Naur 82fff0178b gpu: [compute] generalize sizedBuffer to cover vertex buffers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-04 21:35:39 +02:00
Elias Naur 2c07b2dc0e headless: clear background to transparent, not white
The clear background is the most useful, and the old behaviour can
be achieved by filling the entire viewport with a white paint.ColorOp.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-03 11:31:45 +02:00
Elias Naur f655027110 gpu: [compute] add materials and blit timers to profiling output
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
Elias Naur 53aad36ac1 gpu: [compute] move encoding to Collect
Collect is for converting ops to GPU commands, Frame is for actual
rendering. There's little practical difference, but makes profiling
easier to distinguish between conversion and rendering.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
Elias Naur 06ce077436 op/clip: compute bounds during Path build
The current renderer transforms and processes paths before sending them
to the GPU. It can compute bounds during processing.

The new renderer passes paths verbatim to the GPU, but needs the bounds
for constructing clip bounds.

This change computes the bounds during construction, so it is available
at use. As a bonus for storing the bounds with the path, path caches
(such as for storing text fragments) automatically reuse the bounds
calculations as well.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
Elias Naur 157430a3d2 gpu: [compute] move timer initialization from Collect to Frame
GPU operations logically belong in the Frame method, and it's probably
best to keep them inside BeginFrame/EndFrame as well.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
Elias Naur 3322e211c9 f32: handle empty rectangles in Union and Intersect
The old renderer depends on the old behaviour of Union, so change that
reference to a copy.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-27 16:49:06 +02:00
Elias Naur 22f16d7b02 gpu/shaders: use mediump precision for kernel4 colors, areas
Improves performance on Pixel 1.

Add restrict qualifiers while we're here.

Also sync with piet-gpu.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-20 10:39:10 +02:00
Elias Naur ff7d224a0b gpu/shaders: use mediump precision for sRGB copy shader
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-20 10:39:10 +02:00
Elias Naur ee519351f7 gpu/shaders: ensure dynamically uniform barriers when malloc fails
GPU APIs require that barrier() calls are dynamically uniform, that is
for every barrier in the code, every shader invocation in a workgroup
must all call it, or all not call it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-18 17:20:19 +02:00
Elias Naur 3b69b5ed05 gpu/internal/opengl: fix package name
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-18 17:16:03 +02:00
Elias Naur 9bf4e559bc gpu/internal/opengl: use uniform blocks on macOS
The reflected uniform names are for the shader versions that don't use uniform
buffer objects. For UBO shaders, the names won't resolve.

This change adds a panic when shader uniforms are not found, and fixes

Fixes gio#216

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-17 11:10:33 +02:00
Elias Naur c19ce8e1d7 gpu/internal/convertshaders: don't require GL_ARB_shading_language_420pack
It's not supported on macOS.

Updates gio#216

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-17 11:10:20 +02:00
Elias Naur 3a94f7bf70 gpu/shaders: update piet-gpu
Changes:

- fix BeginClip bounding box
- replace continue not supported by HLSL

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 13:56:41 +02:00
Elias Naur e9a020f774 gpu/internal/convertshaders: build compute shaders in HLSL cs_5_0 profile
The recent changes to the compute shaders have fixed all errors
previously reported by fxc. Switch from dxc to fxc to target shader
model 5.0, supported by Direct3D 11.

Because we know dxc must be available, always build compute shaders even
though the result is not yet used.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:49:49 +02:00
Elias Naur e3bb153274 gpu/internal/convertshaders: don't wait for winepath to exit
Apparently, exec.Command.Output waits for winepath's grandchildren to
exit. However, that may take several seconds if wineserver was started
by winepath.

exec.Command.StdoutPipe works better, in that it is closed when the
winepath process exits.

A similar change may help run the fxc.exe tool under Wine, if that ever
turns out to have the same problem.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00
Elias Naur 8adcf25049 gpu/internal/convertshaders: batch calls to winepath
Wine tools can be slow to run, so it makes sense to batch their use.
Fortunately, winepath supports resolving multiple paths in one
execution.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00
Elias Naur 3b3d41a7ea gpu/internal/convertshaders: don't use Wine for the dxc tool
dxc exists for Linux, and seems to work.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00
Elias Naur 23e0c898ef gpu/internal/driver: use strings for generated DXIL assembly
Literal strings are a more compact than literal byte slices. A future
change will switch to go:embed to save even more space.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:44:06 +02:00
Elias Naur fbee13a07d gpu/internal/convertshaders,gpu: represent converted shaders with raw literals
Raw strings with linebreaks are easier to read and produce smaller
diffs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-04-12 12:43:46 +02:00
Elias Naur ebf2dcea50 gpu/shaders: update piet-gpu
Changes:
- faster implementation of RGBA output
- fix stroked clips and images

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-31 19:56:50 +02:00
Elias Naur bc2c3db43e op/clip,gpu: move approximation of complex strokes to op/clip.Op.Add
Before this change, the two renderers both had special case code for
approximating strokes they don't support natively. This change moves
that conversion to clip.Op.Add, for several reasons:

- The compute renderer no longer need fallback logic and caches for
  strokes it doesn't support.
- The approximation logic is slow. Moving it to clip.Op.Add will not
  speed it up, but will make the cost easier to spot in profiles. Until all
  strokes are supported natively, users can use macros to cache
  expensive strokes.
- Reduced garbage: Op.Add takes an op.Ops anyway, and can use that for
  storing the approximated stroke outline.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-23 19:37:45 +01:00
Elias Naur 0a4b6549da internal/stroke,gpu: move stroking of path data to package internal/strokg
Pure refactor, preparing for use in op/clip.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-23 15:42:43 +01:00
Elias Naur 7825bda8f8 internal/stroke,op/clip: don't import op/clip from internal/stroke
To avoid an import cycle in a future change, internal/stroke can no
longer import op/clip. Move required op/clip functionality to
internal/stroke and duplicate the remaining types.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-23 15:28:52 +01:00
Elias Naur 8c8d1dc16f internal/stroke,gpu: create internal package for stroke to path conversion
Complex strokes are not yet supported in either of the current renderers,
so they are converted to filled outlines in package gpu.

We're about to move that complexity up to the op/clip package, so we're
going to need the converter available from outside package gpu. This
change extracts the conversion code and related types to the separate,
internal package stroke.

No functional changes; a follow-up moves the stroke conversion.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-23 12:35:41 +01:00
Elias Naur 8750828c69 gpu,gpu/shaders: [compute] add alpha to output
Fixes the glfw example where Gio content is composited (alpha blended)
on top of custom content.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-22 16:27:26 +01:00
Elias Naur 1dde94d8dd gpu: [compute] use support for simple strokes
In the old renderer, all strokes are converted to filled paths. The new
renderer can draw simple strokes natively. Do that, and avoid the costly
conversions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-19 21:46:32 +01:00
Elias Naur 13da40f601 gpu,op/clip: [compute] get rid of stroke vs fill flags
The fill mode is now controlled by a SetFillMode command, not by flags
on each path segment and fill command.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-19 21:46:31 +01:00