~eliasnaur/gio#472: 
Longer paths converting to horizontal/vertical lines

When drawing big triangle I get a weird shape: https://gyazo.com/4f13346ff08ef9d912a935ede5be2e67

Longer path lines converting to horizontal/vertical lines.

My OS: Fedora 31

Test script:

package main

import (
	"image/color"
	"log"
	"os"

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

func main() {

	var path clip.Path
	Layout(func(gtx layout.Context) layout.Dimensions {
		log.Println("opa")

		path.Begin(gtx.Ops)
		path.MoveTo(f32.Pt(10, 10))
		path.LineTo(f32.Pt(1000, 100))
		path.LineTo(f32.Pt(200, 500))
		path.Close()
		paint.FillShape(gtx.Ops, color.NRGBA{0, 255, 0, 255}, clip.Outline{Path: path.End()}.Op()) // fill polygon

		path.Begin(gtx.Ops)
		path.MoveTo(f32.Pt(10, 10))
		path.LineTo(f32.Pt(100, 50))
		path.LineTo(f32.Pt(20, 100))
		path.Close()
		paint.FillShape(gtx.Ops, color.NRGBA{255, 0, 0, 255}, clip.Outline{Path: path.End()}.Op()) // fill polygon

		// log.Println(gtx.Constraints.Max)
		return layout.Dimensions{Size: gtx.Constraints.Max}
	})

}

func Layout(lay func(gtx layout.Context) layout.Dimensions) {
	go func() {
		w := app.NewWindow(
			app.Title("oGio"),
			app.Size(unit.Dp(1920/2), unit.Dp(1080/2)),
		)
		// ops will be used to encode different operations.
		var ops op.Ops

		// listen for events happening on the window.
		for e := range w.Events() {
			// detect the type of the event.
			switch e := e.(type) {
			// this is sent when the application should re-render.
			case system.FrameEvent:
				// gtx is used to pass around rendering and event information.
				gtx := layout.NewContext(&ops, e)
				// render content
				lay(gtx)
				// render and handle the operations from the UI.
				e.Frame(gtx.Ops)

			// this is sent when the application is closed.
			case system.DestroyEvent:
				if e.Err != nil {
					log.Println(e.Err)
					os.Exit(1)
				}
				os.Exit(0)
			}
		}
	}()
	app.Main()
}
Status
REPORTED
Submitter
~olablt
Assigned to
No-one
Submitted
1 year, 5 months ago
Updated
a month ago
Labels
No labels applied.

~eliasnaur 1 year, 5 months ago

On macOS M1 13.1 I get https://pasteboard.co/uw6hy8kQhXWF.png. I don't currently have a Linux system to debug on. What's your GPU and driver version? You can try building with -tags noopengl to see whether the Vulkan backend behaves better.

~olablt 1 year, 5 months ago

$ nvidia-smi  -q
Driver Version: 455.38
CUDA Version: 11.1
Attached GPU: GeForce RTX 2080 Ti

~olablt 1 year, 5 months ago

$ go build -tags noopengl main.go && ./main
2023/01/19 16:48:22 x11: no available GPU backends

~olablt 1 year, 5 months ago*

I can confirm there is no such bug on Fedora 37 Asus laptop.

Any chance to make it work on my main machine with Fedora 31 GeForce RTX 2080 Ti?

~olablt 3 months ago*

I was having this problem with my old Linux system. Now upgraded to a new hardware&OS with an RTX 4090 and the latest Nvidia drivers, but the issue persists :( . Any hints on how to fix this issue would be welcome. Maybe it is common to Linux OSes with proprietary Nvidia drivers? I am developing a Gio UI app and I am loving it, but this bug is driving me crazy. gioui.org v0.5.0 OS: Rocky Linux 9.3 (Blue Onyx) x86_64 Host: B760I AORUS PRO DDR4 -CF Kernel: 5.14.0-362.13.1.el9_3.x86_64 Resolution: 3840x2160 WM: i3 CPU: 13th Gen Intel i7-13700KF (24) @ 5.300GHz GPU: NVIDIA GeForce RTX 4090 Memory: 7398MiB / 31659MiB Nvidia Driver Version: 545.23.08 CUDA Version: 12.3

~schnwalter 2 months ago

I was able to reproduce this on an NVIDIA laptop with openSUSE Leap using the official non-free nvidia.com driver repository and also on Debian inside QubesOS.

> inxi -G
Graphics:
  Device-1: Intel TigerLake-H GT1 [UHD Graphics] driver: i915 v: kernel
  Device-2: NVIDIA GA104M [GeForce RTX 3070 Mobile / Max-Q] driver: nvidia
    v: 550.54.14
  Display: x11 server: X.Org v: 1.21.1.4 with: Xwayland v: 22.1.5 driver: X:
    loaded: modesetting,nvidia dri: iris gpu: i915 resolution: 1: 1920x1080~60Hz
    2: 1920x1080~240Hz
  API: OpenGL v: N/A renderer: N/A

To reproduce the bug you just need to render any polygon that has an edge which is at least 512px on X, it's not about the total length, it's about the length on the X axis, I wasn't able to reproduce this on Y.

The RenderDoc snapshots that I caught showed the error on the same laptop, but the numbers were correct and the same snapshots looked correct on a different non-NVIDIA laptop. I would say that the error is on the rendering side and outside the scope of Gio.

Basically on NVIDIA you can't have edges that are wider than 511px on X.

~olablt 2 months ago

Hey,

I appreciate your detailed investigation and the clarity of your findings.

Regarding the limitation with rendering edges wider than 511px on the X axis, I am keen to understand if there are any possible workarounds or future plans to address this issue with NVIDIA GPUs. Are there specific driver updates, Gio patches, or configuration changes that might mitigate this problem? Any guidance or suggestions would be greatly appreciated as I continue to develop applications with Gio on NVIDIA-equipped Linux systems.

On Wed, Mar 27, 2024 at 10:37 AM ~schnwalter outgoing@sr.ht wrote:

I was able to reproduce this on an NVIDIA laptop with openSUSE Leap using the official non-free nvidia.com driver repository and also on Debian inside QubesOS.

> inxi -G
Graphics:
  Device-1: Intel TigerLake-H GT1 [UHD Graphics] driver: i915 v: kernel
  Device-2: NVIDIA GA104M [GeForce RTX 3070 Mobile / Max-Q] driver: nvidia
    v: 550.54.14
  Display: x11 server: X.Org v: 1.21.1.4 with: Xwayland v: 22.1.5 driver: X:
    loaded: modesetting,nvidia dri: iris gpu: i915 resolution: 1: 1920x1080~60Hz
    2: 1920x1080~240Hz
  API: OpenGL v: N/A renderer: N/A

To reproduce the bug you just need to render any polygon that has an edge which is at least 512px on X, it's not about the total length, it's about the length on the X axis, I wasn't able to reproduce this on Y.

The RenderDoc snapshots that I caught showed the error on the same laptop, but the numbers were correct and the same snapshots looked correct on a different non-NVIDIA laptop. I would say that the error is on the rendering side and outside the scope of Gio.

Basically on NVIDIA you can't have edges that are wider than 511px on X.

-- View on the web: https://todo.sr.ht/~eliasnaur/gio/472#event-338257

~olablt referenced this from #472 2 months ago

~eliasnaur 2 months ago

Hi!

Sorry for not addressing this issue.

The graphics situation is complicated on Gio. For years, I've wanted to redo our GPU compute renderer (based on an older version of https://github.com/linebender/vello/). However, time and the fact that we need a fallback for platforms without compute has stalled those efforts.

For those reasons, I consider the current renderer, while adequate for most uses, as a dead end and not worth spending much (of my) time fixing, in particular issues that seem driver specific. I don't mind contributor patches, of course, but for the time being you're pretty much on your own.

~schnwalter 2 months ago

~olablt, I'm thinking that you can search for the RenderDoc snapshots that I've added on the Slack channel and try to report the issue on the mesa freedesktop gitlab instance, maybe somebody there can help, who knows, this might fix many visual bugs that nobody knew where they came from.

~gedw99 a month ago

Speaking of compute support and vello which is webgpu dependent.

I was playing with https://github.com/rajveermalviya/go-webgpu

https://github.com/rajveermalviya/go-webgpu-examples

go run github.com/rajveermalviya/go-webgpu-examples/compute@latest go: downloading github.com/rajveermalviya/go-webgpu-examples v0.0.0-20230730112648-c29c7b8006e5 go: downloading github.com/rajveermalviya/go-webgpu/wgpu v0.17.1 Steps: []string{"0", "1", "7", "2"}

got it working with gio too. worth a look ?

~schnwalter a month ago

I'm trying to reproduce the bug without Gio. I've got the X11 window, the EGLSurface is there and it should show its background color, but I doesn't show up, here's what I have so far:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>


void paint() {

    GLenum glErrors;

    eglBindAPI(EGL_OPENGL_ES_API);
    glViewport(0, 0, 600, 600);

    glErrors = glGetError();
    if (glErrors != 0) {
        printf("ERROR: glGetError\n");
        exit(1);
    }
    glClearColor(1,1,0,1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glFlush();
}

//int argc char **argv;
void main() {
    Display *myDisplay;
    int myScreen;
    int myDepth;
    XSetWindowAttributes myWindowAttributes;
    unsigned long myWindowMask;
    Window myWindow;
    XSizeHints theSizeHints;
    const int x = 200;
    const int y = 150;
    const unsigned int width = 800;
    const unsigned int height = 800;


    myDisplay = XOpenDisplay("");
    if (myDisplay == NULL) {
        fprintf(stderr,
                "ERROR: Could not open a connection to X on display %s\n",
                XDisplayName(NULL)
        );
        exit(0);
    }


    myScreen = DefaultScreen(myDisplay);
    myDepth = DefaultDepth(myDisplay, myScreen);

    myWindowAttributes.background_pixmap = None;
    myWindowAttributes.border_pixel = BlackPixel(myDisplay, myScreen);
    myWindowAttributes.background_pixel = 0xFF808080;
    myWindowAttributes.override_redirect = False;

    myWindowMask = CWBackPixel | CWBackPixmap | CWBorderPixel | CWOverrideRedirect;

    const XID window = RootWindow(myDisplay, myScreen);
    myWindow = XCreateWindow(myDisplay,
                             window,
                             x, y, width, height, 0,
                             myDepth, InputOutput, CopyFromParent,
                             myWindowMask, &myWindowAttributes);

    theSizeHints.flags = PPosition | PSize;
    theSizeHints.x = x;
    theSizeHints.y = y;
    theSizeHints.width = width;
    theSizeHints.height = height;
    XSetWMNormalHints(myDisplay, myWindow, &theSizeHints);
    XMapWindow(myDisplay, myWindow);
    XFlush(myDisplay);


    const EGLDisplay _eglDisplay = eglGetDisplay(myDisplay);
    if( _eglDisplay == EGL_NO_DISPLAY ){
        printf( "ERROR: eglGetDisplay\n" );
        exit(1);
    }
    const EGLBoolean emcRet = eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
    if (emcRet != EGL_TRUE) {
        printf( "ERROR: eglMakeCurrent\n" );
        exit(1);
    }

    EGLint majorVersion;
    EGLint minorVersion;
    const EGLBoolean eglInitRet = eglInitialize(_eglDisplay, &majorVersion, &minorVersion);
    if (!eglInitRet) {
        printf("ERROR: eglInitialize\n");
        exit(1);
    }

    const XID _eglWindow = window;

    const EGLint defaultAttribList[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_CONFIG_CAVEAT, EGL_NONE,
        EGL_NONE
    };
    EGLConfig eglCfg;
    EGLint ncfg;
    const EGLBoolean eglCfgRet = eglChooseConfig(_eglDisplay, defaultAttribList, &eglCfg, 1, &ncfg);
    if (!eglCfgRet || ncfg != 1) {
        printf("ERROR: eglChooseConfig\n");
        return;
    }

    const EGLint surfAttribs[] = {
        EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB,
        EGL_NONE,
    };
    const EGLSurface _eglSurface = eglCreateWindowSurface(_eglDisplay, eglCfg, _eglWindow, surfAttribs);
    if (_eglSurface == EGL_NO_SURFACE) {
        printf("ERROR: eglCreateWindowSurface\n");
        exit(1);
    }

    const EGLint ctxAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE,
    };
    const EGLContext nilEGLContext = 0;
    //EGL_CONTEXT_OPENGL_DEBUG
    const EGLContext _eglCtx = eglCreateContext(_eglDisplay, eglCfg, NULL, ctxAttribs);
    if (_eglCtx == nilEGLContext) {
        printf("ERROR: eglCreateContext\n");
        exit(1);
    }

    EGLBoolean eglMakeCurentRet;
    eglMakeCurentRet = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglCtx);
    if (!eglMakeCurentRet) {
        printf("ERROR: eglMakeCurrent\n");
        exit(1);
    }

    paint();

    const EGLBoolean eglSwapBuffersRet = eglSwapBuffers(_eglDisplay, _eglSurface);
    if (!eglSwapBuffersRet) {
        printf("Error eglSwapBuffers!\n");
        exit(1);
    }

    eglMakeCurentRet = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglCtx);
    if (!eglMakeCurentRet) {
        printf("ERROR: eglMakeCurrent\n");
        exit(1);
    }

    sleep(10);
    eglDestroySurface(_eglDisplay, _eglSurface);
    XDestroyWindow(myDisplay, myWindow);
    XCloseDisplay(myDisplay);
    exit(0);
}
Register here or Log in to comment, or comment via email.