~whereswaldon

North Carolina

https://waldon.blog

Interested in Linux, decentralization, cryptography, golang/rust/c, and communication.

I spend most of my free time on:

  • Arbor, a tree-based, decentralizable chat platform
  • Gio, an immediate-mode UI framework for Go
  • Gio-Extras, my collection of libraries to extend Gio

If you get value out of my work, please consider sponsoring me on Liberapay or GitHub.

Trackers

~whereswaldon/arbor-dev

Last active 2 months ago

~whereswaldon/gio-extras

Last active 10 months ago

~whereswaldon/pointstar

Last active 1 year, 5 months ago

~whereswaldon/github-action-replication-testing

Last active 1 year, 11 months ago

~whereswaldon/Capital-Letters

Last active 1 year, 11 months ago

~whereswaldon/trellis

Last active 2 years ago

#294 can't reuse a PathSpec for stroke painting after filling 10 hours ago

Comment by ~whereswaldon on ~eliasnaur/gio

Isolating the clips doesn't actually help, though I had the same thought as Lucas. This is definitely not an expected behavior.

#292 Older intel CPU vulkan corruption 5 days ago

Ticket created by ~whereswaldon on ~eliasnaur/gio

Clayton Craft reported on slack that he sees a consistent (and very weird) artifact on A Haswell-generation Intel CPU.

This code can reproduce the problem:

package main

// A simple Gio program. See https://gioui.org for more information.

import (
	"log"
	"os"

	"gioui.org/app"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/widget"
	"gioui.org/widget/material"

	"gioui.org/font/gofont"
)

func main() {
	go func() {
		w := app.NewWindow()
		if err := loop(w); err != nil {
			log.Fatal(err)
		}
		os.Exit(0)
	}()
	app.Main()
}

func loop(w *app.Window) error {
	th := material.NewTheme(gofont.Collection())
	var ops op.Ops
	var button widget.Clickable

	for {
		e := <-w.Events()
		switch e := e.(type) {
		case system.DestroyEvent:
			return e.Err
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, e)
			layout.Flex{
				Axis: layout.Vertical,
			}.Layout(gtx,
				layout.Rigid(material.H1(th, "Hello, Gio").Layout),
				layout.Rigid(material.Button(th, &button, "Saluton").Layout),
			)
			e.Frame(gtx.Ops)
		}
	}
}

If you're signed into Slack, you can see a video of the artifact here.

Seems like vulkan support is potentially incomplete on this platform, but we aren't detecting that correctly.

#287 don't use vulkan on intel gpus with incomplete support for it 11 days ago

Comment by ~whereswaldon on ~eliasnaur/gio

Looks like there are several incomplete vulkan implementations in the wild, as reported by Christophe.

#285 Scrollbar missing on flexed content with ridid siblings 13 days ago

Comment by ~whereswaldon on ~eliasnaur/gio

So you can clone gio's source code into an adjacent directory and tell your project to use that instead of the configured Gio version like so:

# assuming we start in your project
# first tell your project to replace upstream gio with a local copy
echo -e "\nreplace gioui.org => ../gio" >> go.mod
# go up a directory
cd ..
# put gio where we said it was
git clone https://git.sr.ht/~eliasnaur/gio

Now you can just build your project normally and it will use the local Gio. You can modify the local Gio's source code and you will see the changes in your project. When you want to switch your project back to published Gio versions, delete the line starting with replace in your go.mod.

#286 Mysterious gogio failure on macOS 13 days ago

Ticket created by ~whereswaldon on ~eliasnaur/gio

This problem was reported on slack by Olanrewaju Collins.

An attempt to run gogio -target android github.com/planetdecred/godcr results in the cryptic error:

gogio: open /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-844496459/apk/classes.dex: no such file or directory

We've had a similar error reported on the mailing list recently.

However, this time we have details on the system in question:

OS: macOS big sur 11.6
go: 1.16.5
javac: 11.0.8
Ndk: 21.0.6113669
Sdk build tools: 	30.0.3, 30.0.2, 30.0.0 rc4, 29.0.2, 28.0.3 installed

They also tried java 1.8.0_302 with the same results. Using -x to gogio yields:

go list -f {{.ImportPath}} github.com/planetdecred/godcr
go list -f {{.Dir}} github.com/planetdecred/godcr
go build -ldflags=-w -s -X gioui.org/app/internal/log.appID=com.github.godcr -buildmode=c-shared -tags  -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/jni/armeabi-v7a/libgio.so github.com/planetdecred/godcr
go build -ldflags=-w -s -X gioui.org/app/internal/log.appID=com.github.godcr -buildmode=c-shared -tags  -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/jni/arm64-v8a/libgio.so github.com/planetdecred/godcr
go build -ldflags=-w -s -X gioui.org/app/internal/log.appID=com.github.godcr -buildmode=c-shared -tags  -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/jni/x86/libgio.so github.com/planetdecred/godcr
go list -f {{.Dir}} gioui.org/app/
go build -ldflags=-w -s -X gioui.org/app/internal/log.appID=com.github.godcr -buildmode=c-shared -tags  -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/jni/x86_64/libgio.so github.com/planetdecred/godcr
/Users/collins/Library/Android/sdk/build-tools/30.0.3/aapt2 compile -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/resources.zip --dir /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/res
/Users/collins/Library/Android/sdk/build-tools/30.0.3/aapt2 link --manifest /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/AndroidManifest.xml -I /Users/collins/Library/Android/sdk/platforms/android-30/android.jar -o /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/link.apk /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/resources.zip
gogio: open /var/folders/9q/r02_nrdn6jxf6sf8pjjbmv2m0000gn/T/gogio-342864185/apk/classes.dex: no such file or directory

I still don't understand this error, but at least two people have hit it, so it's worth trying to investigate.

#285 Scrollbar missing on flexed content with ridid siblings 13 days ago

Ticket created by ~whereswaldon on ~eliasnaur/gio

Clayton Craft reported this on slack, and it either seems like a bug or a very counterintuitive behavior. I'm out of time to debug it right now, so I'm opening a ticket so it isn't lost in the mists of time.

The following code will not present a scrollbar unless you delete the layout.Rigid child in the layout.Flex:

I do not understand why (yet).

package main

// A simple Gio program. See https://gioui.org for more information.

import (
	"image"
	"log"
	"os"
	"strconv"

	"gioui.org/app"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/widget"
	"gioui.org/widget/material"

	"gioui.org/font/gofont"
	"gioui.org/x/outlay"
)

type (
	C = layout.Context
	D = layout.Dimensions
)

func main() {
	go func() {
		w := app.NewWindow()
		if err := loop(w); err != nil {
			log.Fatal(err)
		}
		os.Exit(0)
	}()
	app.Main()
}

func loop(w *app.Window) error {
	th := material.NewTheme(gofont.Collection())
	var list widget.List
	list.Axis = layout.Vertical
	var ops op.Ops
	for {
		e := <-w.Events()
		switch e := e.(type) {
		case system.DestroyEvent:
			return e.Err
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, e)
			// hold elements in a single-item list so it's scrollable if it wraps
			// below the window's visible area

			layout.Flex{
				Axis:      layout.Vertical,
				Alignment: layout.Middle,
				Spacing:   layout.SpaceEnd,
			}.Layout(gtx,
                layout.Rigid(material.Body1(th, "Please select a device:").Layout),
				layout.Flexed(1, func(gtx C) D {
					return material.List(th, &list).Layout(gtx, 1, func(gtx C, _ int) D {
						// Device list
						hWrap := outlay.GridWrap{
							Axis:      layout.Horizontal,
							Alignment: layout.End,
						}
						return hWrap.Layout(gtx, 100, func(gtx C, i int) D {
							material.Body1(th, " "+strconv.Itoa(i)+" ").Layout(gtx)
							return D{
								Size: image.Pt(200, 200),
							}
						})
					})
				}),
			)
			e.Frame(gtx.Ops)
		}
	}
}

#281 w.Invalidate() stops working if called frequently enough? 19 days ago

Comment by ~whereswaldon on ~eliasnaur/gio

Muhammad Hassan reports that it appears fixed, and I can no longer replicate it either. Thanks for the quick fix ~eliasnaur!

REPORTED RESOLVED FIXED

#280 compute renderer fails on NVIDIA on Linux/Vulkan 19 days ago

Comment by ~whereswaldon on ~eliasnaur/gio

Computer renderer on NVIDIA still crashes with vkQueueSubmit on 6c1fc19:

chris@pop-os:/tmp/gio-example$ GIORENDERER=forcecompute go run ./kitchen/
panic: vulkan: vkQueueSubmit: error -4

goroutine 21 [running, locked to thread]:
gioui.org/gpu/internal/vulkan.(*Backend).submitCmdBuf(0xc000194000, 0x0)
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/gpu/internal/vulkan/vulkan.go:1058 +0x1a5
gioui.org/gpu/internal/vulkan.(*Backend).EndFrame(0x0)
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/gpu/internal/vulkan/vulkan.go:236 +0xb6
gioui.org/gpu.(*compute).frame(0xc000198000, {0x713980, 0xc0002a4420})
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/gpu/compute.go:641 +0x6ed
gioui.org/gpu.(*compute).Frame(0xc000198000, 0x10, {0x713980, 0xc0002a4420}, {0x2, 0x0})
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/gpu/compute.go:577 +0x4f
gioui.org/app.(*Window).render(0xc0000ce000, 0x70, {0xc000180000, 0x0})
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/app/window.go:215 +0x11b
gioui.org/app.(*Window).validateAndProcess(0xc0000ce000, {0xc000121e30, 0x1, 0xa4c800}, {0x0, 0x1}, 0x0, 0x0)
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/app/window.go:181 +0x3e5
gioui.org/app.(*Window).run(0xc0000ce000, {0xc0000cc000, 0x3, 0x4})
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/app/window.go:572 +0x59c
created by gioui.org/app.NewWindow
	/home/chris/go/pkg/mod/gioui.org@v0.0.0-20210930154623-6c1f9c19f539/app/window.go:118 +0x42f
exit status 2

#280 compute renderer fails on NVIDIA on Linux/Vulkan 19 days ago

Comment by ~whereswaldon on ~eliasnaur/gio

https://gioui.org/commit/9e8fe530 does fix the uniform panic for me.

#281 w.Invalidate() stops working if called frequently enough? 19 days ago

Ticket created by ~whereswaldon on ~eliasnaur/gio

This bug was initially reported in this slack thread.

Essentially, applications relying on w.Invalidate() to redraw video-like input can trigger a state in which the window stops emitting new frame events even though w.Invalidate() is being invoked.

Thanks to Muhammad Hassan, ~inkeliz, and ~jackmordaunt, we have a fairly small reproducer for the problem:

package main

import (
	"image"
	"image/color"
	"log"
	"math"
	"time"

	"gioui.org/app"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/paint"
	"gioui.org/widget"
)

func main() {
	go func() {
		window := app.NewWindow()
		defer window.Close()

		if err := loop(window); err != nil {
			panic(err)
		}
	}()

	app.Main()
}

func loop(w *app.Window) error {
	var ops op.Ops
	var img widget.Image
	img.Fit = widget.Contain

	imageChan := make(chan image.Image, 1)
	go func() {
		var nextFrame image.Image
		start := time.Now()
		gen := func() {
			sin := math.Sin((float64(time.Since(start).Milliseconds()) / 1000)) + 1
			color := color.NRGBA{R: uint8(sin * 127), A: 255}
			img := image.NewRGBA(image.Rectangle{Max: image.Pt(800, 600)})
			for x := 0; x < img.Bounds().Dx(); x++ {
				for y := 0; y < img.Bounds().Dy(); y++ {
					img.Set(x, y, color)
				}
			}
			nextFrame = img
		}

		gen()
		for range time.Tick(time.Millisecond) {
			imageChan <- nextFrame
			gen()
		}
	}()

	for {
		select {
		case e := <-w.Events():
			switch e := e.(type) {
			case system.DestroyEvent:
				return e.Err
			case system.FrameEvent:
				log.Println("frame")
				gtx := layout.NewContext(&ops, e)
				paint.Fill(gtx.Ops, color.NRGBA{A: 255})
				img.Layout(gtx)
				e.Frame(gtx.Ops)
			}
		case frame := <-imageChan:
			img.Src = paint.NewImageOp(frame)
			w.Invalidate()
			log.Println("invalidate")
		}
	}
}

This program will try to pulse between red and black in a sine wave, but will stop animating randomly. The log will fill with invalidate messages, but no frame events will be issued. You can fix it by interacting with the window in any way, but the issue can recur if you leave the window alone. We've observed this problem on both X11 and Windows 1{0,1}, so it doesn't appear to be platform specific.

You may need to wait up to a minute before the program gets stuck. It's unpredictable.

The issue did not occur if we used image.Uniform images, so it appears that this may have something to do with the volume of image data?