Commit Graph

49 Commits

Author SHA1 Message Date
Elias Naur f14c151883 gpu,gpu/internal: generate hashes of compute programs
The CPU fallback for the compute renderer is contained in a separate
module for space reasons, but the CPU binaries must exactly match the
compute programs. However, there is no way to express that constraint
in go.mod.

This change generates hashes of every compute program so that a
following change can verify the CPU binaries match the programs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-07-27 14:34:18 +02:00
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 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 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 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 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 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 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 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 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
Elias Naur 258033d0b0 gpu: eliminate gaps by ensuring consistent transformations
This is another attempt at fixing the issue described in [0], the
previous attempt was reverted[1].

This change fixes the issue by tracking resolved transformations and
ensure that all segments within a path share a single transformation.

[0] https://github.com/linebender/piet-gpu/issues/62
[1] https://gioui.org/commit/2b21b48a7c5c4451deb642c164548a134bb9ad06

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-15 14:05:15 +01:00
Elias Naur 2b21b48a7c gpu,gpu/shaders: revert attempt to fix path gaps
This is effectively a revert of [0], reintroducing the path gaps
described in [1]. A follow-up change will implement another attempt.

[0] https://gioui.org/commit/2feec23561cd84d6b8ddbab84a202df66b123208
[1] https://github.com/linebender/piet-gpu/issues/62

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-13 15:23:25 +01:00
Elias Naur c799452c57 gpu/internal/driver: rename gpu/backend
There are no longer any importers of package backend outside of
gioui.org/gpu. Move it internally, and rename it to the slightly more
specific "driver" while we're at it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-06 14:27:34 +01:00
Egon Elbre 8571433707 internal/cmd/convertshaders: parallelize compilation
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-03-01 09:59:32 +01:00
Egon Elbre f6fba73885 internal/cmd/convertshaders: add Windows comp shader compilation
Use dxc (DirectXShaderCompiler) for compiling, which is newer than fxc
and doesn't not fail compilation with dynamically uniform flows with
barriers.

Currently requires -directcompute to enable generating the shaders.

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2021-02-25 13:01:18 +01:00
Elias Naur cfb6f477de gpu: [compute] remove even more unused commands
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-02-24 13:42:39 +01:00
Elias Naur 51ba55071b gpu: [compute] remove more unused commands
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-02-24 10:04:34 +01:00
Elias Naur 284659d3ea gpu/shaders: [compute] remove unused command from kernel4
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-02-22 18:25:43 +01:00
Elias Naur 2feec23561 gpu: [compute] fix path gaps by eliminating redundant path points
See https://github.com/linebender/piet-gpu/issues/62 for description
of the issue. The fix is the Gio copy of the piet-gpu fix.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-02-18 10:30:05 +01:00
Elias Naur c9a8265126 gpu: [compute] pre-transform images before rendering
We're about to change the last stage of the compute pipeline to only
accept images, not sampled textures. This change prepares materials
for pixel-aligned image copying by pre-rendering images to a texture,
applying transforms.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-02-18 10:30:05 +01:00
Elias Naur 74eb0a4a34 gpu/shaders: clamp clip coverage to [0.0, 1.0]
Fixes the "bleaching" artifacts of the painting program by ~wrnrlr.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-01-21 12:39:02 +00:00
Elias Naur d23514fd58 gpu: add compute implementation
The old renderer is still the default, so the new compute renderer will only be
used in the rare case the old renderer is not supported but the new is. That
happens on the Samsung J2 Prime and Moto C Android phones. Or set the
GIORENDERER environment variable to "forcecompute" to disable the old renderer:

$ GIORENDERER=forcecompute go run ...

Missing features:
- Gradients are not supported yet, and render as a solid color.
- Draw timers are not added, and profile.Events are not emitted.
- Stroked paths may in some cases appear corrupted because their clip
  outlines are not continuous when generated by Gio. Sebastien is
  working on a fix.
- The new renderer shares most CPU-side logic with the old renderer,
  resulting in several inefficient conversion steps between the old
  operations representation and the new. This is slower, but minimizes
  divergence in features and bugs between the two renderers.

Roadmap:
- The compute renderer supports features that Gio does not yet
exploit: stroked paths with round caps, transformations, lines,
cubic beziér curves.
- More stroke styles and maybe dashed strokes natively in shaders.
- Metal and Direct3D ports.

The most important feature is porting the renderer to run on the CPU. A
CPU renderer will both support Gio on devices with insufficient GPU
support, and allow us to remove the old renderer. Two renderers is twice
the maintenance but the feature set of the weakest implementation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-12-31 17:21:35 +01:00
Egon Elbre f00f3a3359 gpu: add linear gradient
Signed-off-by: Egon Elbre <egonelbre@gmail.com>
2020-11-03 15:39:06 +01:00
Viktor cfb9565895 gpu: reintroduce reuse of offset-only stenciling
Reintroduce support for offset in stencil vertex so we can reuse
cached values if the only difference in transform is offset. Split
current transform into a pure-offset part and the rest and use
only the complex part as cache key.

Signed-off-by: Viktor <viktor.ogeman@gmail.com>
2020-06-21 11:20:36 +02:00
Viktor 24951a7ee7 gpu, op, internal/ops: add affine transformations
Add support for affine transformations. The key changes are outlined
below.

- Painting/clipping with rectangles is handled by, for complex
  transforms, creating clipping paths representing the transformed
  rectangle and using a larger bounding box. Cover/Blit shaders updated
  correspondingly to correctly map texture cordinates from the new
  bounding boxes.
- Since path splitting must happen on CPU the transforms must happen CPU
  side as well - offsets removed from shaders.
- Complex transforms will lead to different path splitting which means
  that GPU arrays can no longer be cached if the transform has changed.
  Thus the current transform is added as a key to the cache.
- Add a public API to op for setting Affine transformations.

There are a number of optimizations that could be explored further but
which are left out now:
- Caching also of CPU operations (e.g path splitting & transforms) and
  not only caching the GPU arrays.
- Allow for re-use of cached GPU vertices if the transformation change
  is a pure offset / scaling since the splitting is then the same.

Signed-off-by: Viktor <viktor.ogeman@gmail.com>
2020-06-21 11:17:53 +02:00
Elias Naur 1062d4e79d gpu/shaders: avoid first-class arrays
Safari's WebGL1 implementation (rightly) complains that first-class
array types are not supported as function result types. Define and
use a struct type instead.

While we're here, use const variables instead of functions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-04-28 14:46:33 +01:00
Elias Naur 61529c2cb6 gpu: fix clip intersection with the D3D backend
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-03-11 16:23:35 +01:00
Elias Naur 8405bf0e47 gpu/shaders: be more robust against floating point inaccuracies
We're forced by compatibility to encode an integer state into a
floating point. Make the implicit conversion from floating point to
integer more robust against GPUs with low precision floats.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-29 14:27:50 +00:00
Elias Naur b194a0ce58 internal/cmd/convertshaders: target 9.1 compatibility shader model
Direct3D 11 supports Direct3D 9.1 level hardware, but only if the shaders are
compiled for target 4_0_level_9_1.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-28 15:22:58 +01:00
Elias Naur e03b3cd808 app/internal/d3d11: add Direct3D backend
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:41:35 +01:00
Elias Naur d65bfdc275 internal/cmd/convertshaders: use gofmt to format output
In particular, the simplifying "-s" flag to gofmt ensures that the automatic
test for unformatted Go source files won't complain.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:41:31 +01:00
Elias Naur 591c89ab0a gpu: drop use of integer shader inputs
They're a pain to support. Encode the single integer value we have
as a float instead.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur 3043c4243a gpu/backend: add support for GLSL 1.50
Apple's OpenGL 3.2 Core implementation doesn't accept 1.30.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur dd6a247326 gpu/backend: add support for desktop OpenGL 3
In particular, add the GLSL 1.30 shader variant. Sigh.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur 8dce81d8fd gpu/shaders: introduce toClipSpace to map to GPU native clip space
OpenGL use the [-1; 1] range for clip depths, Direct3D [0; 1].
Use toClipSpace to encapsulate the difference.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur c34c350a52 gpu: pack 2D transforms in vec4 values
Instead of separate 2d scale and transform, pack them into a single
4d value.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur c20c1ab96f gpu/shaders: compensate for GPU Framebuffer => texture transformation
Add fboTextureTransform shader function for cancelling the
implied transformation from fragments output by the fragment
shader and the (u, v) coordinates used to sample from it in a
later pass.

For OpenGL the transformation is the identity.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur 29d36e11ee gpu/shaders: use correct type for integer vector
OpenGL supports casting from int to float during vertex array
reading. Direct3D doesn't. Since we're transpiling from GLSL, we can't
directly use the Direct3D builtin "asint". So that leaves using
"ivec2" instead of vec2.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 21:22:59 +01:00
Elias Naur 0d266c413d gpu,gpu/backend: implement GLSL 300 es shader variants
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:58 +01:00
Elias Naur 0be4dd9af0 app/internal/cmd/convertshaders: use backend types directly
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00
Elias Naur 5cd5d49108 gpu/backend: move backend interface types to a separate package
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00
Elias Naur 4e3bfd5b1b gpu: setup OpenGL ES texture uniforms automatically from shader metadata
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00
Elias Naur 5c359bbf89 gpu/shaders: delete unused uniform
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00
Elias Naur 646a767665 gpu,gpu/gl: implement shader uniform buffers
Emulate them for the OpenGL ES backend because 2.0 doesn't support uniform
buffers. The future d3d backend only supports uniform (constant) buffers.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00
Elias Naur ac7029fa24 gpu/internal/shaders: generate shader variants
We're about to add Direct3D support, where shaders are written in
HLSL. Rather than write shaders twice (or more), convert them to
a GLSL variant understood by the glslcc cross-compiler and generate
the OpenGL ES 2.0 and HLSL variants. The HLSL is used by a future
change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2020-02-27 20:34:22 +01:00