~lrewega


#131 gpu: display artifacts when using a large atlas size 27 days ago

Comment by ~lrewega on ~eliasnaur/gio

I can't actually reproduce this in headless mode.

I lied, math is hard. I updated the patch series, though the test doesn't feel great, it will at least likely catch regressions.

#131 gpu: display artifacts when using a large atlas size 29 days ago

Comment by ~lrewega on ~eliasnaur/gio

So, funny story: I can't actually reproduce this in headless mode. The issue doesn't seem to happen there.

#131 gpu: display artifacts when using a large atlas size 29 days ago

Comment by ~lrewega on ~eliasnaur/gio

FWIW I tried abusing glslcc to use highp everywhere in addition to manually adding highp everywhere possible to the input shaders, and saw no discernible improvement. I have begun to suspect either the loss of precision is not happening in the shader, or it is innate to the profile being used.

#127 When there are too many rectangles they are not drawn 29 days ago

Comment by ~lrewega on ~eliasnaur/gio

How do we feel about adding an Op to influence z-index? In some cases, the user (or widget or whatever) might know that there is no overlap and be able to skip out on z-index management (e.g. this would solve for the reproducer). It does feel leaky, though.

Alternatively, might there be some way to avoid incrementing the buffer if we can somehow track that the current path doesn't clip with anything else drawn at the current z-index?

Lastly, is there any reason we couldn't simply use ALWAYS for the depth test func and let last-writer-win?

#131 gpu: display artifacts when using a large atlas size 29 days ago

Comment by ~lrewega on ~eliasnaur/gio

Yes, patch submitted: https://lists.sr.ht/~eliasnaur/gio-patches/patches/10968

I will add a test and update the series.

#131 gpu: display artifacts when using a large atlas size 29 days ago

Ticket created by ~lrewega on ~eliasnaur/gio

Paths rasterized to the atlas with a texture coordinate beyond 8192 pixels in either dimension degrades the output in various ways. For example, some paths are clipped significantly, entirely invisible, or rendered as a mashup of multiple adjacent paths in the atlas. This is particularly easy to trigger when drawing many moderately sized paths that fill a window on a high-resolution display. An example program demonstrates the issue:

package main

import (
        "image/color"
        "log"

        "gioui.org/app"
        "gioui.org/f32"
        "gioui.org/io/system"
        "gioui.org/op"
        "gioui.org/op/clip"
        "gioui.org/op/paint"
        "gioui.org/unit"
)

const tiles = 4096
const stride = 64
const width = 32

func main() {
        go func() {
                w := app.NewWindow(
                        app.Size(unit.Dp(640), unit.Dp(480)),
                )
                ops := new(op.Ops)
                for {   
                        e := <-w.Events()
                        switch e := e.(type) {
                        case system.DestroyEvent:
                                log.Fatal(e.Err)
                        case system.FrameEvent:
                                ops.Reset()
                                for i := 0; i < tiles; i++ {
                                        stack := op.Push(ops)
                                        pt := f32.Pt(float32(i%stride)*width, float32(i/stride)*width)
                                        rect := f32.Rectangle{Min: pt, Max: pt.Add(f32.Pt(width, width))}
                                        clip.Rect{Rect: rect, SE: width / 4, SW: width / 4, NW: width / 4, NE: width / 4}.Add(ops)
                                        paint.ColorOp{Color: color.RGBA{R: 0xFF, A: 0xFF}}.Add(ops)
                                        paint.PaintOp{Rect: rect}.Add(ops)
                                        stack.Pop()
                                }
                                e.Frame(ops)
                        }
                }
        }()
        app.Main()
}

At first I thought this was a symptom #127 but it appears to be unrelated, as it can be reproduced with much fewer draw calls than are necessary to exhaust the z-buffer.

My current hypothesis is that some precision is getting lost somewhere during stenciling, but I haven't yet been able to narrow it down further. I'm still trying to understand the shaders themselves, as well as how the GL profile chooses precision, in conjunction with glslcc's SPIR-V compilation. The stencil shader inputs and outputs appear to be correct, when analyzed in RenderDoc, despite the results on the atlas appearing incorrect, but I did not perform an exhaustive analysis.

I am running a Gio application on Linux/X11 with the OpenGL 3.0 ES profile (with a Radeon RX 5700 XT), which reports a MAX_TEXTURE_SIZE of 16384.

A workaround is to artificially cap the max texture size to something reasonable, like 4k or 8k, which resolves the issue entirely.

I would probably have not encountered this/noticed except for:

  • The atlas grows for each shape drawn, despite every shape being the same.
  • The atlas packing algorithm prefers to grow in one direction until reaching the buffer bounds.

Example incorrect output (the entire screen should be full of red squares): https://user-images.githubusercontent.com/639066/84194562-3247a480-aa6b-11ea-841a-2ed7985608ec.png

The same program/output as above, but with a wider window: https://user-images.githubusercontent.com/639066/84194585-3c69a300-aa6b-11ea-8e0e-0f2b0b298d82.png

Atlas extracted from RenderDoc (notice the large gap): https://user-images.githubusercontent.com/639066/84194599-4095c080-aa6b-11ea-82ee-c445093c70b9.png