Commit Graph

1990 Commits

Author SHA1 Message Date
Benjamin Otte
9836389fde vulkan: Repurpose debug flags for image uploads
Now that we don't use the old environment variables anymore to force
staging buffer/image uploads, we don't need them.

However, we do autodetect the fast path for avoiding a staging buffer
now, and we might want to be able to turn that off for testing.

So add GSK_DEBUG=staging that does exactly that.
2023-06-14 03:34:07 +02:00
Benjamin Otte
7f26f5a160 vulkan: Remove gsk_vulkan_image_new_from_data()
This is unused now that all the code uses map/unmap.

The only thing that map/unmap doesn't do that the old code did, was use
a staging image instead as alternative to a staging buffer for image
uploads.

However, that code is not necessary for anything, so I'm sure we can do
without.
2023-06-14 03:34:07 +02:00
Benjamin Otte
6a009b7182 vulkan: Add upload fastpath
If the memory heap that the GPU uses allows CPU access
(which is the case on basically every integrated GPU, including phones),
we can avoid a staging buffer and write directly into the image memory.

Check for this case and do that automatically.

Unfortunately we need to change the image format we use from
VK_IMAGE_TILING_OPTIMAL to VK_IMAGE_TILING_LINEAR, I haven't found a way
around that yet.
2023-06-14 03:34:07 +02:00
Benjamin Otte
17dd100f43 vulkan: Add gsk_vulkan_memory_can_map()
.. nd use it to assert memory is mappable when mapping it.
2023-06-14 03:34:07 +02:00
Benjamin Otte
49c2c2da1a vulkan: Use map/unmap for fallback images 2023-06-14 03:34:07 +02:00
Benjamin Otte
f88b1cef21 vulkan: Render fallback into vulkan memory
Use the new map/unmap image upload method for Cairo node drawing:
1. map() the memory
2. create an image surface or that memory
3. draw to that image surface
4. success

There's no longer a need for Cairo to allocate image memory.
2023-06-14 03:34:07 +02:00
Benjamin Otte
c27e412ff1 vulkan: Use new upload method for texture uploads
gsk_vulkan_image_new_from_texture() now uses the direct copy via
gdk_texture_downloader_download_into().
2023-06-14 03:34:07 +02:00
Benjamin Otte
0c72f19cb1 vulkan: Add a new way to upload data into images
As an alternative to gsk_vulkan_image_new_from_data() that
takes a given data and creates an image from it, add a 3 step process:
  gsk_vulkan_image_new_for_upload()
  gsk_vulkan_image_map_memory()
  /* put data into memory */
  gsk_vulkan_image_unmap_memory()

The benefit of this approach is that it potentially avoids a copy;
instead of creating a buffer to pass and writing the data into it before
then memcpy()ing it into the image, the data can be written straight
into image memory.

So far, only the staging buffer upload is implemented.

There are also no users, those come in the next commit(s).
2023-06-14 03:34:07 +02:00
Benjamin Otte
cb4e92946b vulkan: Move some code
Add gsk_vulkan_image_new_from_texture() and use it.

Also rewrite the actual code from using Cairo surfaces to using
GdkTextureDownloader.
2023-06-14 03:34:07 +02:00
Benjamin Otte
e7c86f4608 vulkan: Constify upload function 2023-06-14 03:34:07 +02:00
Benjamin Otte
9df935591c vulkan: Handle new nodes being added correctly
When nodes are added, nothing was warning us that we need to bump
N_RENDER_NODES.

Make sure that that's no longer necessary by refactoring the code to
remove the define.
2023-06-11 03:54:50 +02:00
Benjamin Otte
1f8045ddbe vulkan: Do intersection check for every node
This is more expensive, but it finds more cases, and in particular it
catches corner cases like empty nodes or fully clipped nodes that might
otherwise make the kernel throw signals in our direction.
2023-06-11 03:54:50 +02:00
Benjamin Otte
82ba8c848b vulkan: Handle empty rects in intersects_rect()
Apart from the none case, this was already handled, so we just check if
the rect is empty now.
2023-06-11 03:15:08 +02:00
Matthias Clasen
5f02631812 gsk: Fully free mask nodes
We were forgetting to chain up in finalize.  Oops
2023-06-09 22:40:38 -04:00
Matthias Clasen
c8133ecb50 gsk: Plug a memory leak 2023-06-09 22:40:38 -04:00
Benjamin Otte
2883f4b7a2 vulkan: Antialiasing for linear gradients
Shaders are complicated now...
2023-06-08 22:16:18 +02:00
Benjamin Otte
e3cc3f7841 vulkan: Make gradient shader use buffers
This allows putting any number of color stops into the buffer, so
fallbacks with too many stops are no longer necessary.
2023-06-08 21:53:06 +02:00
Benjamin Otte
d1135f9e3c vulkan: Add support for storage buffers
And add a default storage buffer that is used for per-frame temporary
data.

So far nothing is using this code, this is just infrastructure.
2023-06-08 21:53:06 +02:00
Benjamin Otte
2d89dfea29 vulkan: Switch GLSL version to 450
We need more modern features soon.
2023-06-08 21:53:06 +02:00
Benjamin Otte
89f20c2fb6 vulkan: Only update descriptor sets with contents
If one of the descriptor sets doesn't have any items, don't include it
in the sets passed to vkUpdateDescriptorSets().

This has no effect right now, because we either have both images and
samplers or neither, but it will become relevant once we also support
buffers.
2023-06-08 21:53:06 +02:00
Benjamin Otte
bba324ce30 rendernode: Scale repeat offscreens properly
Respect the matrix in use at time of encountering a repeat node so that
the offscreen uses roughly the same device pixel density as the target.

Fixes the handling of the clipped-repeat test.
2023-06-05 05:33:07 +02:00
Benjamin Otte
c322ab34c7 rendernode: Use cairo_set_device_offset()
Simplifies the code.
2023-06-05 05:33:07 +02:00
Benjamin Otte
5409f0b350 vulkan: Create multiple render objects
Sometimes the GPU is still busy when the next frame starts (like when
no-vsync benchmarking), so we need to keep all those resources alone and
create new ones.
That's what the render object is for, so we just create another one.

However, when we create too many, we'll starve the CPU. So we'll limit
it. Currently, that limit is at 4, but I've never reached it (I've also
not starved the GPU yet), so that number may want to be set lower/higher
in the future.

Note that this is different from the number of outstanding buffers, as
those are not busy on the GPU but on the compositor, and as such a
buffer may have not finished rendering but have been returend from the
compositor (very busy GPU) or have finished rendering but not been
returned from the compositor (very idle GPU).
2023-06-04 19:42:01 +02:00
Benjamin Otte
f1b1aacc34 vulkan: Stop differentiating rounded from cicular corners
Our shaders can handle both, so don'ttry to tell them apart anymore.

Removes a lot of unnecessary fallbacks.
2023-06-04 19:42:01 +02:00
Benjamin Otte
e7201968d6 vulkan: Cleanup: Initialize constants at the top 2023-06-04 19:42:01 +02:00
Benjamin Otte
67f2ad817e vulkan: Add support for texture-scale nodes 2023-06-04 19:42:01 +02:00
Benjamin Otte
f420c143e0 vulkan: Split textures and samplers
The idea here is that we can do more complex combinations and use that
to support texture-scale nodes or use fancy texture formats (suc as
YUV).

I'm not sure this is actually necessary, but for now it gives more
flexibility.
2023-06-04 19:42:01 +02:00
Benjamin Otte
1cf6dfab2f vulkan: Add a hackish way to handle empty children
For blend and crossfade nodes, one of the children may exist and
influence the rendering, while the other does not.

Previously, we would skip the node, which would cause the required
rendering to not happen. We now send a valid texture id for the
invalid offscreen, thereby actually rendering the required parts.

Fixes the blend-invisible-child compare test

Current state for compare tests:
Ok:                 397
Expected Fail:      0
Fail:               26
Unexpected Pass:    0
Skipped:            2
Timeout:            0
2023-06-04 19:42:01 +02:00
Benjamin Otte
330a8b1cdb vulkan: Convert blend shader
Same work as crossfade shader pretty much.
2023-06-04 19:42:01 +02:00
Benjamin Otte
8d19db6732 vulkan: Update the cross-fade shader
This also fixes it rendering weird things when the bounds of start and
end node don't match.
2023-06-04 19:42:01 +02:00
Benjamin Otte
0f1b039306 vulkan: Implement bindless texture rendering
Instead of having a descriptor set per operation, we just have one
descriptor set and bind all our images into it.

Then the shaders get to use an index into the large texture array
instead.

Getting this to work - because it's a Vulkan extension that needs to be
manually enabled, even though it's officially part of Vulkan 1.2 - is
insane.
2023-06-04 19:42:01 +02:00
Benjamin Otte
b791aa0301 vulkan: Clip using scissors
If we have a rectangular clip without transforms, we can use
scissoring. This works particularly well because it allows intersecting
rounded rectangles with regular rectangles in all cases:
Use the scissor rect for the rectangle and the normal clipping code for
the rounded rectangle.
2023-06-04 19:42:01 +02:00
Benjamin Otte
7fd94c1828 vulkan: Make scissoring an explicit operation
The idea is to use it for clip nodes when they are integer-aligned.

To do that, we need to track the scissor rect in the parse state, so we
do that, too.

Also move the viewport offset out of the projection matrix, as it is
part of the transform between clip and scissor, so it needs to live in
the offset.
2023-06-04 19:42:01 +02:00
Benjamin Otte
dd4c1167b2 vulkan: Remove unneeded struct member
We can use gsk_vulkan_pipeline_get_vertex_stride() whenever we need that
value.
2023-06-04 19:42:01 +02:00
Benjamin Otte
d411912396 vulkan: Bind vertex buffers only once
We can index into the same buffer from every pipeline due to the aligned
buffer writes (see previous commit).

So we do that.
2023-06-04 19:42:01 +02:00
Benjamin Otte
0e93ad8671 vulkan: Align vertex data
We align the data to a multiple of vertex stride, that way we use more
memory, but we could compute an offset into the vertex buffer without
changing the offset.
2023-06-04 19:42:01 +02:00
Benjamin Otte
d98991a0ad vulkan: Set offsets when counting
We can set the vertex offset while counting the data, this gets rid of
the need of passing all the counting machinery into the actual data
collection code.
2023-06-04 19:42:01 +02:00
Benjamin Otte
1f7dcc1286 vulkan: Simplify switch statement
All branches do the same thing now, so pull them all into the same
branch.
2023-06-04 19:42:01 +02:00
Benjamin Otte
328cdf7b2a vulkan: Simplify collect_vertex_data()
We don't have any size arguments to it, so don't use them.
2023-06-04 19:42:01 +02:00
Benjamin Otte
79a227bc64 vulkan: Remove a function from pipeline impls
That function is available already in the structs we feed to Vulkan.

Store it from there and reuse it.
2023-06-04 19:42:01 +02:00
Benjamin Otte
0fee26252c vulkan: Don't draw fully clipped nodes
... if they are container nodes. Other nodes will get culled by the
vertex shader.
2023-06-04 19:42:01 +02:00
Benjamin Otte
d48b6b9ad5 vulkan: Add optimization for transforms
When attempting a complex transform, check if the clip can be ignored
and do that if possible.

That way we don't cause fallbacks when transforming the clip is too
complex.
2023-06-04 19:42:01 +02:00
Benjamin Otte
d4618ea8a6 vulkan: Don't crash with overly large nodes
... when these nodes are used as children of a complex transform nodes
and we lose the clip.
2023-06-04 19:42:01 +02:00
Benjamin Otte
a73530f952 vulkan: Update texture shader to do AA 2023-06-04 19:42:01 +02:00
Benjamin Otte
3e620a8fe5 vulkan: Split generic code off
No need to duplicate code in shaders when it can be shared.
2023-06-04 19:42:01 +02:00
Benjamin Otte
6d8c8199d9 vulkan: Use rounded rect APIs to improve clips
There are a bunch of intersection APIs available these days.
Let's use them.
2023-06-04 19:42:01 +02:00
Benjamin Otte
968ceb71d5 gsk: Add (private) gsk_rounded_rect_intersection()
The idea is that for a rectangle intersection, each corner of the
result is either entirely part of one original rectangle or it is
an intersection point.

By detecting those 2 cases and treating them differently, we can
simplify the code to compare rounded rectangles.
2023-06-04 19:42:01 +02:00
Benjamin Otte
7f5504bea4 vulkan: Set the initial clip rect
Instead of rendering unclipped, set the clip region to the extents of
the current clip region.
2023-06-04 19:42:01 +02:00
Benjamin Otte
4b2b239550 vulkan: Only draw one rect
Instead of emitting the render commands once per rectangle of the clip
region, just emit them once with the region's extents.

This is generally faster because it emits fewer commands to the GPU,
even though it may touch significantly more pixels.

For a proper method, we'd need to record the commands per clip rectangle
instead of emitting all of them all the time.
2023-06-04 19:42:01 +02:00
Benjamin Otte
23c10d434c vulkan: Use CLAMP_TO_EDGE in sampler
We don't want to clamp to the border, that causes fade-outs at the
edges.
2023-06-04 19:42:01 +02:00