Don't run extensions unless they're available. This includes querying
for descriptor indexing, and running one of two versions of kernel4
depending on whether it's enabled.
Part of the support needed for #78
The BeginClip and EndClip bounding boxes are absolute and must pairwise
match. I mistakenly modified the BeginClip bounding box for stroked
clips.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Adds an example binary that can be run with `cargo apk`.
One thing that will still need manual tuning (for now) is the size of
the canvas. A good followup is to sense that from the window size.
Don't run extensions unless they're available. This includes querying
for descriptor indexing, and running one of two versions of kernel4
depending on whether it's enabled.
Part of the support needed for #78
coarse.comp knows the maximum stack depth, and can pre-allocate scratch
space for kernel4.comp. Kernel4 no longer contains allocations nor
control barriers.
The invocation local blend stack is gone as well; it didn't seem to make
any difference in performance to always use global memory for pushing
and popping.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
See http://ssp.impulsetrain.com/gamma-premult.html for a description of
the format.
Pre-multiplied alpha only matters for translucent objects; draw a few
such shapes in the test render.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Reclaims the space waste from splitting fill mode commands from fill
commands.
For example, a CmdStroke + CmdColor use an extra tag word compared to
the former combined CmdStroke. This change shaves off that one word.
In the future, we can pack several command tags into one tag word,
saving even more space.
Fixes#66
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This change completes general support for stroked fills for clips and
images.
Annotated_size increases from 28 to 32, because of the linewidth field
added to AnnoImage. Stroked image fills are presumably rare, and if
memory pressure turns out to be a bottleneck, we could replace the
linewidth field with a separate AnnoLinewidth elements.
Updates #70
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Before this change, every command (FillColor, FillImage, BeginClip)
had (or would need) stroke, (non-zero) fill and solid variants.
This change adds a command for each fill mode and their parameters,
reducing code duplication and adds support for stroked FillImage and
BeginClip as a side-effect.
The rest of the pipeline doesn't yet support Stroked FillImage and
BeginClip. That's a follow-up change.
Since each command includes a tag, this change adds an extra word for
each fill and stroke. That waste is also addressed in a follow-up.
Updates #70
Signed-off-by: Elias Naur <mail@eliasnaur.com>
capabilities.min_image_count is 4 on my system, which is larger than
the hard-coded 2.
Use a default swapchain size if we're not getting any size information
from the surface capabilities.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Encode stroke vs fill as tag flags, thereby reducing the number of scene
elements. Encoding change only, no functional changes.
The previous Stroke and Fill commands are merged to one command,
FillColor. The encoding to annotated element is divergent, which is
fixed when annotated elements move to tag flags.
Updates #70
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Commit 9afa9b86b6 added Rust support for
encoding flags into elements. This change adds support to shaders by
introducing variant tag structs:
struct VariantTag {
uint tag;
uint flags;
}
and returning them from Variant_tag functions.
It also adds a flags argument to write functions for enum variants that
include TagFlags.
No functionality changes.
Updates #70
Signed-off-by: Elias Naur <mail@eliasnaur.com>
FillImage is like Fill, except that it takes its color from one or
more image atlases.
kernel4 uses a single image for non-Vulkan hosts, and the dynamic sized array
of image descriptors on Vulkan.
A previous version of this commit used textures. I think images are a better
choice for piet-gpu, for several reasons:
- Texture sampling, in particular textureGrad, is slow on lower spec devices
such as Google Pixel. Texture sampling is particularly slow and difficult to
implement for CPU fallbacks.
- Texture sampling need more parameters, in particular the full u,v
transformation matrix, leading to a large increase in the command size. Since
all commands use the same size, that memory penalty is paid by all scenes, not
just scenes with textures.
- It is unlikely that piet-gpu will support every kind of fill for every
client, because each kind must be added to kernel4.
With FillImage, a client will prepare the image(s) in separate shader stages,
sampling and applying transformations and special effects as needed. Textures
that align with the output pixel grid can be used directly, without
pre-processing.
Note that the pre-processing step can run concurrently with the piet-gpu pipeline;
Only the last stage, kernel4, needs the images.
Pre-processing most likely uses fixed function vertex/fragment programs,
which on some GPUs may run in parallel with piet-gpu's compute programs.
While here, fix a few validation errors:
- Explicitly enable EXT_descriptor_indexing, KHR_maintenance3,
KHR_get_physical_device_properties2.
- Specify a vkDescriptorSetVariableDescriptorCountAllocateInfo for
vkAllocateDescriptorSets. Otherwise, variable image2D arrays won't work (but
sampler2D arrays do, at least on my setup).
Updates #38
Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in #62, the non-deterministic scene monoid may result in
slightly different transformations for path segments in an otherwise
closed path.
This change ensures consistent transformation across paths in three steps.
First, absolute transformations computed by the scene monoid is stored
along with path segments and annotated elements.
Second, elements.comp no longer transforms path segments. Instead, each
segment is stored untransformed along with a reference to its absolute
transformation.
Finally, path_coarse performs the transformation of path segments.
Because all segments in a path share a single transformation reference,
the inconsistency in #62 is avoided.
Fixes#62
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The NVIDIA shader compiler bug that forced splitting of the state struct
into primitive types is now fixed.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Defining MEM_DEBUG in mem.h will add a size field to Alloc and enable
bounds and alignment checks for every memory read and write.
Notes:
- Deriving an Alloc from Path.tiles is unsound, but it's more trouble to
convert Path.tiles from TileRef to a variable sized Alloc.
- elements.comp note that "We should be able to use an array of structs but the
NV shader compiler doesn't seem to like it". If that's still relevant, does
the shared arrays of Allocs work?
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The binning shader supports up to N_TILE bins. To efficiently cover wide or
tall viewports, convert the rigid N_TILE_X x N_TILE_Y bin layout to a variable
width_in_bins x height_in_bins layout.
Signed-off-by: Elias Naur <mail@eliasnaur.com>