From 7d022b25e5af0279a697ad69bf4e3e238eaaa31b Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Sat, 18 Jan 2025 10:30:30 -0800 Subject: [PATCH 1/4] start on unsupported webgpu logic --- gpu/gpu.go | 38 +++++++++++++++++++++++++++++++------ system/driver/web/drawer.go | 17 +++++++++++------ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/gpu/gpu.go b/gpu/gpu.go index 39c9862b80..fd132408f8 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "cogentcore.org/core/base/errors" "cogentcore.org/core/base/reflectx" "github.com/cogentcore/webgpu/wgpu" ) @@ -38,6 +39,10 @@ var ( // are listed in order 0..n-1. SelectAdapter = -1 + // Unsupported is set to true if the first attempt to get a valid GPU + // device fails. + Unsupported = false + // theInstance is the initialized WebGPU instance, initialized // for the first call to NewGPU. theInstance *wgpu.Instance @@ -109,34 +114,55 @@ type GPU struct { // NewGPU returns a new GPU, configured and ready to use. // If only doing compute, use [NewComputeGPU]. -// The surface is used to select an appropriate adapter, and -// is recommended but not essential. +// The surface can be used to select an appropriate adapter, and +// is recommended but not essential. Returns nil and sets +// Unsupported = true if the current platform is not supported by WebGPU. func NewGPU(sf *wgpu.Surface) *GPU { gp := &GPU{} - gp.init(sf) - return gp + if errors.Log(gp.init(sf)) == nil { + return gp + } + Unsupported = true + return nil } // NewComputeGPU returns a new GPU, configured and ready to use, // for purely compute use, which causes it to listen to // use the GPU_COMPUTE_DEVICE variable for which GPU device to use. +// Returns nil and sets Unsupported = true if the current platform +// is not supported by WebGPU. func NewComputeGPU() *GPU { gp := &GPU{} gp.ComputeOnly = true - gp.init(nil) - return gp + if errors.Log(gp.init(nil)) == nil { + return gp + } + Unsupported = true + return nil } // init configures the GPU func (gp *GPU) init(sf *wgpu.Surface) error { + fmt.Println("trying to get gpu") inst := Instance() + if inst == nil { + return errors.New("WebGPU is not supported on this machine: could not create an instance") + } gpIndex := 0 if gp.ComputeOnly { gpus := inst.EnumerateAdapters(nil) + if len(gpus) == 0 { + return errors.New("WebGPU is not supported on this machine: no adapters available") + } gpIndex = gp.SelectComputeGPU(gpus) gp.GPU = gpus[gpIndex] } else { + fmt.Println("trying to get adapters") gpus := inst.EnumerateAdapters(nil) + fmt.Println("got gpus:", gpus) + if len(gpus) == 0 { + return errors.New("WebGPU is not supported on this machine: no adapters available") + } gpIndex = gp.SelectGraphicsGPU(gpus) gp.GPU = gpus[gpIndex] // note: below is a more standard way of doing it, but until we fix the issues diff --git a/system/driver/web/drawer.go b/system/driver/web/drawer.go index 147a1ae593..82d9d82346 100644 --- a/system/driver/web/drawer.go +++ b/system/driver/web/drawer.go @@ -7,9 +7,9 @@ package web import ( + "fmt" "image" "image/draw" - "strings" "syscall/js" "cogentcore.org/core/gpu" @@ -42,14 +42,19 @@ func (dw *Drawer) AsGPUDrawer() *gpudraw.Drawer { // supports WebGPU and a backup 2D image drawer otherwise. func (a *App) InitDrawer() { // TODO(wgpu): various mobile and Linux browsers do not fully support WebGPU yet. - isMobile := a.SystemPlatform().IsMobile() || a.SystemPlatform() == system.Linux - // TODO(wgpu): Firefox currently does not support WebGPU in release builds. - isFirefox := strings.Contains(js.Global().Get("navigator").Get("userAgent").String(), "Firefox") - if isMobile || isFirefox || !js.Global().Get("navigator").Get("gpu").Truthy() { + // isMobile := a.SystemPlatform().IsMobile() || a.SystemPlatform() == system.Linux + // // TODO(wgpu): Firefox currently does not support WebGPU in release builds. + // isFirefox := strings.Contains(js.Global().Get("navigator").Get("userAgent").String(), "Firefox") + // if isMobile || isFirefox || !js.Global().Get("navigator").Get("gpu").Truthy() { + // a.Draw.context2D = js.Global().Get("document").Call("querySelector", "canvas").Call("getContext", "2d") + // return + // } + gp := gpu.NewGPU(nil) + fmt.Println("gpu is nil:", (gp == nil)) + if gp == nil { a.Draw.context2D = js.Global().Get("document").Call("querySelector", "canvas").Call("getContext", "2d") return } - gp := gpu.NewGPU(nil) surf := gpu.Instance().CreateSurface(nil) sf := gpu.NewSurface(gp, surf, a.Scrn.PixelSize, 1, gpu.UndefinedType) a.Draw.wgpu = gpudraw.NewDrawer(gp, sf) From 90fceec91f0ba533ceb5c914560fec42866365ce Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Sat, 18 Jan 2025 10:47:56 -0800 Subject: [PATCH 2/4] remove debug prints and use updated webgpu --- go.mod | 2 +- go.sum | 4 ++-- gpu/gpu.go | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6551da10e4..baaaa58ae8 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/bramvdbogaerde/go-scp v1.4.0 github.com/chewxy/math32 v1.10.1 github.com/cogentcore/reisen v0.0.0-20240814194831-4d884b6e7666 - github.com/cogentcore/webgpu v0.0.0-20250117020559-3809548f4891 + github.com/cogentcore/webgpu v0.0.0-20250118183535-3dd1436165cf github.com/cogentcore/yaegi v0.0.0-20240724064145-e32a03faad56 github.com/coreos/go-oidc/v3 v3.10.0 github.com/ericchiang/css v1.3.0 diff --git a/go.sum b/go.sum index 1bdb06ad1e..8c4c3db4b1 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,8 @@ github.com/chewxy/math32 v1.10.1 h1:LFpeY0SLJXeaiej/eIp2L40VYfscTvKh/FSEZ68uMkU= github.com/chewxy/math32 v1.10.1/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs= github.com/cogentcore/reisen v0.0.0-20240814194831-4d884b6e7666 h1:gmXMw/Xcva/2V5qRO920q4am1odNE0xFEGBzG7y7cus= github.com/cogentcore/reisen v0.0.0-20240814194831-4d884b6e7666/go.mod h1:HoDh/nWYrLffGjfVxUmbJHb0yZvcV3TwrN73WurddNs= -github.com/cogentcore/webgpu v0.0.0-20250117020559-3809548f4891 h1:cIwWHCSlztHgtm6YSrKuRJqeLVtski0jXttMa1j4TLc= -github.com/cogentcore/webgpu v0.0.0-20250117020559-3809548f4891/go.mod h1:ciqaxChrmRRMU1SnI5OE12Cn3QWvOKO+e5nSy+N9S1o= +github.com/cogentcore/webgpu v0.0.0-20250118183535-3dd1436165cf h1:efac1kg29kwhSLyMd9EjwHbNX8jJpiRG5Dm2QIb56YQ= +github.com/cogentcore/webgpu v0.0.0-20250118183535-3dd1436165cf/go.mod h1:ciqaxChrmRRMU1SnI5OE12Cn3QWvOKO+e5nSy+N9S1o= github.com/cogentcore/yaegi v0.0.0-20240724064145-e32a03faad56 h1:Fz1uHiFCHnijFcMXzn36KLamcx5q4pxoR5rKCrcXIcQ= github.com/cogentcore/yaegi v0.0.0-20240724064145-e32a03faad56/go.mod h1:+MGpZ0srBmeJ7aaOLTdVss8WLolt0/y/plVHLpxgd3A= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= diff --git a/gpu/gpu.go b/gpu/gpu.go index fd132408f8..d8976cf701 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -143,7 +143,6 @@ func NewComputeGPU() *GPU { // init configures the GPU func (gp *GPU) init(sf *wgpu.Surface) error { - fmt.Println("trying to get gpu") inst := Instance() if inst == nil { return errors.New("WebGPU is not supported on this machine: could not create an instance") @@ -157,9 +156,7 @@ func (gp *GPU) init(sf *wgpu.Surface) error { gpIndex = gp.SelectComputeGPU(gpus) gp.GPU = gpus[gpIndex] } else { - fmt.Println("trying to get adapters") gpus := inst.EnumerateAdapters(nil) - fmt.Println("got gpus:", gpus) if len(gpus) == 0 { return errors.New("WebGPU is not supported on this machine: no adapters available") } From 0a13cff7a6186c2d6e9dec46e4a9f4f9c3cd7da0 Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Sat, 18 Jan 2025 10:48:58 -0800 Subject: [PATCH 3/4] remove old logic from web/drawer --- system/driver/web/drawer.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/system/driver/web/drawer.go b/system/driver/web/drawer.go index 82d9d82346..700d221c51 100644 --- a/system/driver/web/drawer.go +++ b/system/driver/web/drawer.go @@ -7,7 +7,6 @@ package web import ( - "fmt" "image" "image/draw" "syscall/js" @@ -41,16 +40,7 @@ func (dw *Drawer) AsGPUDrawer() *gpudraw.Drawer { // InitDrawer sets the [Drawer] to a WebGPU-based drawer if the browser // supports WebGPU and a backup 2D image drawer otherwise. func (a *App) InitDrawer() { - // TODO(wgpu): various mobile and Linux browsers do not fully support WebGPU yet. - // isMobile := a.SystemPlatform().IsMobile() || a.SystemPlatform() == system.Linux - // // TODO(wgpu): Firefox currently does not support WebGPU in release builds. - // isFirefox := strings.Contains(js.Global().Get("navigator").Get("userAgent").String(), "Firefox") - // if isMobile || isFirefox || !js.Global().Get("navigator").Get("gpu").Truthy() { - // a.Draw.context2D = js.Global().Get("document").Call("querySelector", "canvas").Call("getContext", "2d") - // return - // } gp := gpu.NewGPU(nil) - fmt.Println("gpu is nil:", (gp == nil)) if gp == nil { a.Draw.context2D = js.Global().Get("document").Call("querySelector", "canvas").Call("getContext", "2d") return From a7a345c802dec0220d58c428ada2652f7cfc5963 Mon Sep 17 00:00:00 2001 From: "Randall C. O'Reilly" Date: Sat, 18 Jan 2025 11:07:22 -0800 Subject: [PATCH 4/4] remove Unsupported state --- gpu/gpu.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/gpu/gpu.go b/gpu/gpu.go index d8976cf701..27bef9df28 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -39,10 +39,6 @@ var ( // are listed in order 0..n-1. SelectAdapter = -1 - // Unsupported is set to true if the first attempt to get a valid GPU - // device fails. - Unsupported = false - // theInstance is the initialized WebGPU instance, initialized // for the first call to NewGPU. theInstance *wgpu.Instance @@ -115,21 +111,20 @@ type GPU struct { // NewGPU returns a new GPU, configured and ready to use. // If only doing compute, use [NewComputeGPU]. // The surface can be used to select an appropriate adapter, and -// is recommended but not essential. Returns nil and sets -// Unsupported = true if the current platform is not supported by WebGPU. +// is recommended but not essential. Returns nil and logs an error +// if the current platform is not supported by WebGPU. func NewGPU(sf *wgpu.Surface) *GPU { gp := &GPU{} if errors.Log(gp.init(sf)) == nil { return gp } - Unsupported = true return nil } // NewComputeGPU returns a new GPU, configured and ready to use, // for purely compute use, which causes it to listen to // use the GPU_COMPUTE_DEVICE variable for which GPU device to use. -// Returns nil and sets Unsupported = true if the current platform +// Returns nil and logs an error if the current platform // is not supported by WebGPU. func NewComputeGPU() *GPU { gp := &GPU{} @@ -137,7 +132,6 @@ func NewComputeGPU() *GPU { if errors.Log(gp.init(nil)) == nil { return gp } - Unsupported = true return nil }