Commit Graph

286 Commits

Author SHA1 Message Date
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 0ba984c19c gpu: [compute] don't change vertex buffers during render passes
Vulkan doesn't support it, so move vertex buffer updates outside render
passes. Splitting render passes is another approach, but not as
efficient.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-21 17:53:05 +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 41e812d5e8 gpu: [compute] always bind valid materials texture
Currently, we run kernel4.comp with whatever texture was
bound (or none) when there are no materials in the set of layers.

However, Vulkan require every image binding to a compute shader to be
non-null and valid. This change works around that limitation by binding
a small dummy texture when no materials are needed.

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 78b6268f9b gpu/headless: plug resource leaks in tests
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-20 13:26:43 +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 fc5637804f gpu: plug another GPU resource leak
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-12 18:27:29 +02:00
Elias Naur 173f14be78 gpu: [compute] don't leak driver.Device instance
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-09 12:39:02 +02:00
Elias Naur f3f4bacb1c gpu: don't leak GPU buffer from sizedBuffer.Release
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-09-07 16:31:49 +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 2749eb91f3 gpu: [compute] clip image materials to their rendered size
Before this change, transformed images would take up as much atlas
texture space to fit them. However, we can easily run out of space for
large images or images with large scaling applied.

This change limits transformed images to their rendered bounds which is
the window size in the worst case.

Updates gio#219 (fixes the chat kitchen example)

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 12:59:01 +02:00
Elias Naur 9e9cb17a5d gpu: [compute] clip transformed images to their bounds
A follow-up change will cause some transformed images to render outside
their allocated atlas bounds. This change uses the GPU viewport to clip
them so they won't overwrite other atlas content.

Updates gio#219

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 12:59:01 +02:00
Elias Naur 6818af9390 gpu: [compute] get rid of material regions
The atlas allocations contains enough information to replace regions.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 12:59:01 +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 06ffa42d16 gpu: [compute] support unlimited number of materials and images
This change extends the atlas allocation machinery to images and
materials.

Updates gio#219

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 12:59:01 +02:00
Elias Naur 1d7ed55c29 gpu: support rectangular atlas packers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 07:48:26 +02:00
Elias Naur 8c2913c2e6 gpu: tolerate changing maximum dimensions in packer.tryAdd
This change allows atlas packer clients to start with large maximum
atlas dimensions, then shrink the maximum once the underlying atlas has
been allocated.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 07:48:26 +02:00
Elias Naur 589c94e64b gpu: optimize atlas packer for smallest sizes
Previously, the packer optimized for the smalles space where the image
fits. Empirically, smaller atlases can be achieved by greedily picking the
smallest total area.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-27 07:48:26 +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 414be0a0b3 gpu: Merge GPU.Collect and GPU.Frame
There's no meaningful reason to have them separate. The intention was to
enable rendering concurrent with other processing, but that's gaining
framerate at the expense of input latency and complicating ImageOp
semantics.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-24 08:30:52 +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 0f81bf02c1 gpu: don't invoke GPU backend outside BeginFrame/EndFrame
The Metal backend is particularly sensitive because its staging buffers
are synchronized to BeginFrame.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-23 17:47:14 +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 d80992fc66 go.*,gpu: don't (badly) re-implement Go module versioning
Changes to the gioui.org/shader module are generally breaking changes,
which means that a particular version of gioui.org must be build with a
particular version of gioui.org/shader. Until now, the gpu package
checked the module version against an expected version and would fail at
runtime if there's a mismatch.

This change replaces all that complexity with a simple procedural
change: bump the module major version of gioui.org/shader at each such
incompatible change. It doesn't matter that we'll eventually reach
gioui.org/v1234/shader; the module is internal and won't break clients.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-22 09:18:41 +02:00
Elias Naur 64ccb1c06d gpu: [compute] add missing error handling
Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 16:48:50 +02:00
Elias Naur 86e474688b gpu: [compute] don't round atlas dimensions to power-of-twos
There is no clear benefit and the rounding tends to waste texture
memory.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 16:40:21 +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 44adf01768 go.*,gpu: update gioui.org/shader version
Pulls in a compatiblity fix for OpenGL ES 2.0 devices.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-21 10:04:56 +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