Commit Graph

93 Commits

Author SHA1 Message Date
Elias Naur cf9832ffcb gpu/internal/vulkan: support novulkan tag, FreeBSD
The novulkan tag didn't completely disable the Vulkan backend, and
the backend wouldn't register on FreeBSD. This change fixes both
issues.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-11-26 22:02:41 +01:00
Pierre Curto 9d05f35341 op/paint: fix subimage rendering by ImageOp
This change is a follow-up to bcf3ff77ff, fixing the two renderers to
properly render images with non-zero origins.

Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-11 10:13:26 +01:00
Pierre Curto bcf3ff77ff op/paint: remove unnecessary check in ImageOp
Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
2021-11-10 17:31:50 +01:00
Elias Naur aac53ad0b5 gpu: don't alias stroked paths with outline paths
The default renderer caches pre-processed paths for efficient re-use,
but failed to distinguish outline paths from stroke paths.

Fixes gio#294

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-20 10:07:22 +02:00
Elias Naur bd1ef92dc4 op/clip: remove complex stroke support
In a discussion with Raph Levien, the author of our compute renderer
implementation, it became clear to me that it's not at all certain that
complex strokes will ever be efficiently supported by a GPU renderer.

At the same time, the machinery for converting a complex stroke to a
GPU-friendly outline has a significant maintenance cost. Further, it is
surprising to users that complex strokes are significantly slower and
allocate memory.

This change removes support for complex strokes, leaving only
round-capped, round-joined strokes supported by the compute renderer.
The default renderer still converts all strokes to outline, but it also
caches the result.

This is an API change. The complex stroke conversion code has been moved
to the external gioui.org/x/stroke package, with a similar API.

Updats gio#282 (Inkeliz brought up the allocation issue)

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 18:10:47 +02:00
Elias Naur 936c266b03 all: [API] split operation stack into per-state stacks
The op.Save and Load methods exist to support the need for
transformation, clip, pointer area state to behave as stacks. For
example, layout needs to apply an offset to its children but not
subsequent operations.

Before this change, op.Save and Load were used to save and restore the
state:

    ops := new(op.Ops)
    // Save state.
    state := op.Save(ops)
    // Apply offset.
    op.Offset(...).Add(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    state.Load()

A drawback with the op.Save mechanism is that there is no direct
connection between the state change and the saving and loading of state.
This causes confusion as to when a Save/Load is needed and who is
responsible for performing them, which leads to subtle bugs and over-use
of Save/Loads.

This change gets rid of the general state stack and replaces it with
per-state stacks. There is now a stack for transformation, clip, pointer
areas, and they can only be restored by the code pushing state to them.
The example above now becomes:

    ops := new(op.Ops)
    // Push offset to the transformation stack.
    stack := op.Offset(...).Push(ops)
    // Draw with offset applied.
    draw(ops)
    // Restore state.
    stack.Pop()

For convenience, transformation also be Add'ed if the stack operation is
not required.

Simple state such as the current material no longer has a way to be
restored; it is assumed the client of a PaintOp adds their desired
material operation before it.

API change: replace op.Save/Load with explicit Push/Pop scopes for
op.TransformOps, pointer.AreaOps, clip.Ops.

To ease porting, this change retains a version of op.Save/Load that
saves and restores the transformation and clip stacks. It also retains
an Add method for clip.Op.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-08 17:21:56 +02:00
Elias Naur 794b7854ea gpu/internal/rendertest: add missing license headers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-07 17:03:28 +02:00
Elias Naur 30ecf75a0f gpu/internal/opengl: save and restore GL state only for shared contexts
Most Gio programs have exlusive access to their OpenGL contexts, where
saving and restoring of the GL state is not required.

This change applies to all OpenGL platforms, but matters most for WASM
where syscalls are slow.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-05 08:41:12 +02:00
Elias Naur 3abc891680 gpu/internal/opengl: [OpenGL] respect render target when emulating sRGB
Before this change, the sRGB emulation target would always be the
current framebuffer. Now it's the render target passed to BeginFrame.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-10-05 08:22:52 +02:00
Elias Naur 6c1f9c19f5 app,internal/vk: [Vulkan] skip frame with stale window dimensions
While here, add a missing nil check.

Updates gio#280

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-30 17:46:23 +02:00
Elias Naur 9e8fe5305b gpu/internal/opengl: don't panic when uniforms are optimized out
glGetUniformLocation can return -1 (not found) for uniforms that have
been optimized out during linking of a GPU program. This happens because
the default renderer compile multiple program from the same generic
template.

Updates gio#280

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-30 16:39:22 +02:00
Elias Naur 3434bf8af1 internal/ops: don't run deferred macros twice
Discovered while debugging #277.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-24 15:14:45 +02:00
Elias Naur bdafb3564f gpu,app: [Metal] don't store CFTypeRef values in pointer types
CFTypeRefs may not always contain valid pointers, so they must not be
stored in pointer types lest the Go runtime treats them as such.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-23 15:32:58 +02:00
Elias Naur 53fe2e5235 gpu/internal/opengl: give up on OpenGL ES 3.1 compute
There are too many driver issues with ES 3.1 compute shaders. Most
devices support Vulkan but some, such as the Samsung J2, will fall back
to the CPU renderer.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-23 10:03:55 +02:00
Elias Naur d9effdad8e gpu/internal/opengl: fix glCopyTexSubImage2D on Samsung J2
To use glCopyTexSubImage2D on the Samsung J2 it's not enough to
set GL_READ_FRAMEBUFFER. This change binds GL_FRAMEBUFFER, setting both
READ_FRAMEBUFFER and DRAW_FRAMEBUFFER, fixing the issue.

Setting only GL_READ_FRAMEBUFFER was also a genuine bug, because OpenGL
ES 2.0 doesn't support it.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-23 09:53:45 +02:00
Elias Naur 8999747ad2 app,gpu,internal/vk: add Vulkan port for Wayland, X11, Android
This change implements a Vulkan port for the two renderers, old and
compute. Run with GIORENDERER=forcecompute to test the compute renderer.

To shake out bugs faster, it is also made the default on systems that
support it. To disable Vulkan and force the use of OpenGL, use the
`novulkan` tag:

$ go run -tags novulkan gioui.org/example/kitchen

Don't forget to file an issue describing the issue that prompted the use
of the tag.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 18:40:05 +02:00
Elias Naur bdd0893dd0 app,gpu: move errDeviceLost from package app to package gpu
The Vulkan backend can return device lost error from more than just
Present.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:58 +02:00
Elias Naur b5e3756ee8 gpu/internal/driver: get rid of Device.MemoryBarrier
MemoryBarrier is meant to stand in for OpenGL ES 3.1's glMemoryBarrier.
However, it badly fits with the other backends: Metal and D3D11 have
automatic memory barriers, and Vulkan needs barriers for graphics as
well.

This change removes MemoryBarrier, and puts the burden on the backends.
The OpenGL backend simply adds a barrier between every compute dispatch.

This change only adds a single memory barrier compared to the manual
barriers before this change, which is unlikely to affect performance
much.. We can revisit the automatic barriers if they ever become a
performance problem.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:58 +02:00
Elias Naur 1f0f88dbd3 gpu: drop access flags and format from driver.Device.BindImageTexture
They can be deferred in the drivers that need them.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:58 +02:00
Elias Naur 0bdd24c51e gpu: fold driver.Framebuffer functionality into driver.Texture
driver.Device.NewFramebuffer doesn't provide additional information over
driver.Device.NewTexture, so Texture can hold its (optional) framebuffer
on behalf of the renderers. Metal don't even need a separate framebuffer
object.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:58 +02:00
Elias Naur b599a6d1c5 gpu: introduce driver.Device.PrepareTexture and use it in renderers
Vulkan textures (VkImage) are always in a particular layout, where each
layout is optimized for a particular use (transfer, sampling, compute
storage). Vulkan allows layout transitions everywhere except inside
render passes. This change adds driver.Device.PrepareTexture for
instructing the driver to switch a texture to a layout for sampling
in preparation for using it in a render pass.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:36 +02:00
Elias Naur 21ca9d13a8 gpu: switch from uniform buffers to combined push buffers
Vulkan doesn't support changing uniforms during a render pass. However,
push constants *can* be changed. The gio-shader repository was changed
to use push constants instead of uniforms, this change implements the
corresponding driver and renderer change.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:02 +02:00
Elias Naur 3a98f004f9 gpu/internal/opengl: reduce number of glsl shader variants
With the use of uniform buffers gone, we don't need the glsl 3.00 es
variant any longer.

We only support desktop OpenGL on macOS which is guaranteed to be
at least version 3.2, so we don't need the glsl 1.30 variant either.

Remove a test that depended on gl_VertexID which is not support in glsl
1.00 es.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:47:11 +02:00
Elias Naur 3d1e9b0856 gpu: rename DrawMode to Topology and move it to pipeline descriptors
Vulkan needs the topology stated in its pipeline descriptor, not at
draw time.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur cc2edbaa51 gpu: introduce render passes
Modern GPU API such as Metal and Vulkan use explicit render passes
and command buffers for recording rendering commands. They don't have
global state; each render pass starts with a clean set of bound
textures, pipeline etc.

Change our GPU abstraction to better match newer API and modify our two
renderers to explicitly describe their render passes.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur 9e6ed3cb96 gpu/internal/rendertest: clean up headless context immediately
GPU contexts can hold on to a significant amount of resources. Clean
them up immediately instead of at test cleanup.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur f842178ac7 gpu/internal/metal: don't copy padding during images transfers
Don't copy the padding when stride is larger than the width. Applies to
Texture.Upload and Framebuffer.ReadPixels.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur da1c4a60e0 gpu/internal/rendertest: only dump images when -saveimages is set
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 15:13:00 +02:00
Elias Naur f896a72ea1 app,gpu/internal/opengl: move glFlush to macOS context present
A previous change[0] moved all OpenGL function calls to the internal
opengl package, so that Gio can use desktop OpenGL and OpenGL ES (ANGLE)
in the same program without confusing the function pointers.

However the change also moved the glFlush that constitutes a buffer
swap, or present, on macOS. Other platforms don't need the flush, so
this change moves it back to macOS-specific code, in glContext.Present
where it belongs. It also uses dlopen and dlsym to avoid symbol
confusion between Apple's OpenGL framework and ANGLE's libGLESv2.dylib.

The motivation is that we're getting rid of the desktop OpenGL backend
on macOS in favor of Metal, and so should reduce the number of global
special-cases catering to that platform.

[0] https://gioui.org/commit/476d2269a

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-15 21:12:29 +02:00
Elias Naur bde046de54 gpu/internal/opengl: avoid PACK/UNPACK_ROW_LENGTH on WebGL 1
Fixes gio#259

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-05 13:58:19 +02:00
Elias Naur 1362acb85a gpu/internal/d3d11,internal/d3d11: add DirectCompute support
This change implements support for compute programs in the Direct3D 11
driver. The compute renderer doesn't work for me yet; my NVIDIA GTX 970
and Intel GPUs both display corrupted output and hangs.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-28 16:13:06 +02:00
Elias Naur e841288b88 gpu/internal/d3d11: introduce newBuffer for common buffer creation
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-28 13:32:35 +01:00
Elias Naur d724f61d06 gpu/internal/d3d11: fix partial uploads in Buffer.Upload
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-28 12:38:00 +01:00
Elias Naur 32a4885c00 gpu/internal: fix AccessBits to be a bitset and support read+write
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-28 10:41:00 +02:00
Elias Naur 7f6e376424 gpu,gpu/internal: support variable strides in ReadPixels
It saves a roundtrip to scratch memory when the CPU fallback renderer
downloads rendered materials.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 12:59:01 +02:00
Elias Naur b9ede6d735 gpu/internal/opengl,internal/gl: avoid glBufferSubData after glBufferData
On my Fedora Intel GPU, issuing a glBufferSubData immediately after a
glBufferData with no data may leave the buffer cleared.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-25 14:29:09 +02:00
Elias Naur 7acc031ccf gpu/internal/metal: merge buffer address and size calls
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-23 17:56:57 +02:00
Elias Naur b47653b808 gpu/internal/metal: don't double-buffer staging memory
One staging buffer is enough because BeginFrame waits for the completion
of the staging operatoins from the previous frame.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-23 17:48:59 +02:00
Elias Naur 43a7030f6e gpu/internal/metal: use optimal CPU cache mode for staging buffers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-22 17:46:28 +02:00
Elias Naur 0d009bd534 gpu/internal/d3d11: remove unused method
Invalidate is no longer part of the driver contract.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-22 09:34:17 +02:00
Elias Naur 6ee8a1cb7c gpu/internal/opengl: avoid crash when uniform buffers are not supported
Found by Dan Kortschak.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 16:06:45 +02:00
Elias Naur c9970cb8e3 gpu,gpu/internal,internal/gl: replace BlitFramebuffer with CopyTexture
OpenGL ES 2.0 doesn't support glBlitFramebuffer, but does support
glCopyTexSubImage2D. Fortunately, we don't need the extra features of
glBlitFramebuffer anyway.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 11:16:28 +02:00
Elias Naur 3b2992c37e gpu,app/internal/wm: add Metal port
The OpenGL (ES) implementations on Apple platforms are deprecated and
don't support GPU compute programs. This change adds support for the
replacement, the Metal GPU API.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur a7f08eedf3 gpu,gpu/internal: split shader storage usage into read and write
Metal has texture write usage flags for read and write.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 07fdc1a2de gpu,gpu/internal: drop implied transformation from BlitFramebuffer
The Metal (and presumably the D3D11) backend doesn't support transformed
framebuffer blits. The only caller doesn't need it either, so drop that
capability from the driver abstraction.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 58cc817e5f gpu,gpu/internal: move vertex buffer stride to pipeline state
Metal needs the vertex stride at pipeline creation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur 1af910959b gpu: fold buffer clearing into framebuffer bind
In Metal, clearing a framebuffer is most efficiently done during bind.
Modify our driver accordingly.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur d38c78d7ac gpu,gpu/internal: move InputDesc back from gioui.org/shader module
It was moved to gioui.org/shader by mistake.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur afaa31eca8 gpu: introduce pipeline abstraction
Modern API such as Metal and Vulkan want clients to compile expensive
state changes into pipeline objects. Change our GPU driver abstraction
to match, thereby paving the way for future drivers.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 08:31:46 +02:00
Elias Naur f475087296 gpu/internal/opengl: handle switch from non-sRGB output to sRGB output
The opengl example has a screenshot functionality that renders to a
non-sRGB texture, whereas window rendering is to a sRGB capable EGL
surface. The opengl driver detects the switch from an sRGB capable
output to a non-sRGB capable output, but not the switch back. This
change releases the emulation framebuffer on the switch back.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-19 10:25:05 +02:00