-
Notifications
You must be signed in to change notification settings - Fork 136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
elements.comp scene traversal may leave gaps in paths #62
Comments
Gaps may be introduced by the redundant path segment endpoints. Track each segment's successor and use a single endpoint per pair of segments. The last segment in a path uses the first segment's endpoint. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
Gaps may be introduced by the redundant path segment endpoints. Track each segment's successor and use a single endpoint per pair of segments. The last segment in a path uses the first segment's endpoint. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
See linebender/vello#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>
Gaps may be introduced by the redundant path segment endpoints. Track each segment's successor and use a single endpoint per pair of segments. The last segment in a path uses the first segment's endpoint. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
This is a very interesting problem, thanks for bringing it to my attention. I will study your solution, but also consider some alternatives. Just to brainstorm, one is to represent the affine transformation using fixed point arithmetic, which should make the math deterministic, but with limitations. |
@raphlinus I'd like to take a stab at implementing your idea of combining transformations in their own monoid in elements.comp. Are you currently (or anyone else) working on this? Related, is the comment about shared arrays of structs in elements.comp still relevant? If we're going to have two monoid passes, it would be a big readability to work on structs. FWIW, the malloc functionality (example) uses shared arrays of structs, and I haven't heard you complain. |
I'm open to you having a crack at it. If you would like to write a brief design doc before digging into the code, I'll try to prioritize it (I've had difficulty switching gears to focus on piet-gpu, but plan for it to be my main work over the next weeks). I think we can do shared structs now, the bug in the NV shader compiler has been fixed a while ago and we're not at the point where we have to accumulate workarounds for driver bugs - yet. |
The non-deterministic evaluation order of the state monoid may end up assigning inconsistent transformations to path endpoints. This change avoids that problem by evaluating transformation state before all other state. Fixes #62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
Please review #71 which contains an implementation of your separate transformation monoid. It works for me in Gio, and the piet-gpu tiger. EDIT: I lied. It doesn't always work correctly. Stay tuned. |
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] linebender/vello#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
This is an alternative and better implementation of [0] and fixes rendering glitches caused by inconsistent transformations of otherwise closed paths. See [1] for a detailed description. [0] https://gioui.org/commit/2feec23561cd84d6b8ddbab84a202df66b123208 [1] linebender/vello#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
The non-deterministic evaluation order of the state monoid may end up assigning inconsistent transformations to path endpoints. This change avoids that problem by evaluating transformation state before all other state. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#62, the non-deterministic scene monoid may result in slightly different transformations for path segments in an otherwise closed path. This change ensure 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 path 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 shared a single transformation reference, the inconsistency in linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
Gaps may be introduced by the redundant path segment endpoints. Track each segment's successor and use a single endpoint per pair of segments. The last segment in a path uses the first segment's endpoint. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
Ok, I believe I found a correct (and simpler) fix, a hybrid between your resolved transforms and my tracking of path endpoints. I abandoned the second pass, because I ended up needing both the resolved transformations (for path segments) and the relative transformations (for the bounding box monoid). The new approach keeps a single pass, and doesn't need an end path flag. Tested with Gio and the piet-gpu tiger. Please review at #72. |
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
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] linebender/vello#62 [1] https://gioui.org/commit/2b21b48a7c5c4451deb642c164548a134bb9ad06 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
As described in linebender#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 linebender#62 is avoided. Fixes linebender#62 Signed-off-by: Elias Naur <mail@eliasnaur.com>
The fill algorithm implemented by path_coarse.comp assumes that closed paths contain no gaps. Unfortunately, the non-deterministic scene tracersal in elements.comp may introduce gaps in otherwise gap-less paths.
Consider two fill path segments through endpoints
A
,B
,C
in a scene fragment with three preceding transforms. The segments are initialized with the identity transform,I
.T₁·T₂·T₃·S(I, A, B)·S(I, B, C)
Since scene element operations are associative, elements.comp evaluates them in a GPU-friendly but non-deterministic order. In particular, it may use the ordering
S((T₁·T₂)·T₃, A, B)·S(T₁·(T₂·T₃), B, C)
Because of numerical imprecision, the path segments may end up with slightly different transformations,
S(M₁, A, B)·S(M₂, B, C)
Finally,
M₁·B
is not in general equal toM₂·B
, leading to a gap in the path that includes the two segments.To verify my claim, I made the following change,
which removes the non-deterministic evaluation order. As expected, the path gaps disappeared.
I don't have a good fix yet. It's possible that the endpoints can be propagated in the scene traversal, at the cost of state memory. Perhaps a PathSeparator scene element should be added to delimit closed paths. It may also be a good idea to make path scene segment have implicit start points, saving a bit of memory.
The text was updated successfully, but these errors were encountered: