mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 17:05:38 +00:00
app,gpu,internal/vk: add Vulkan port for Wayland, X11, Android
This change implements a Vulkan port for the two renderers, old and compute. Run with GIORENDERER=forcecompute to test the compute renderer. To shake out bugs faster, it is also made the default on systems that support it. To disable Vulkan and force the use of OpenGL, use the `novulkan` tag: $ go run -tags novulkan gioui.org/example/kitchen Don't forget to file an issue describing the issue that prompted the use of the tag. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
package headless
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"runtime"
|
||||
@@ -30,6 +31,33 @@ type context interface {
|
||||
Release()
|
||||
}
|
||||
|
||||
var (
|
||||
newContextPrimary func() (context, error)
|
||||
newContextFallback func() (context, error)
|
||||
)
|
||||
|
||||
func newContext() (context, error) {
|
||||
funcs := []func() (context, error){newContextPrimary, newContextFallback}
|
||||
var firstErr error
|
||||
for _, f := range funcs {
|
||||
if f == nil {
|
||||
continue
|
||||
}
|
||||
c, err := f()
|
||||
if err != nil {
|
||||
if firstErr == nil {
|
||||
firstErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
if firstErr != nil {
|
||||
return nil, firstErr
|
||||
}
|
||||
return nil, errors.New("x11: no available GPU backends")
|
||||
}
|
||||
|
||||
// NewWindow creates a new headless window.
|
||||
func NewWindow(width, height int) (*Window, error) {
|
||||
ctx, err := newContext()
|
||||
|
||||
@@ -37,17 +37,19 @@ type mtlContext struct {
|
||||
queue C.CFTypeRef
|
||||
}
|
||||
|
||||
func newContext() (context, error) {
|
||||
dev := C.createDevice()
|
||||
if dev == 0 {
|
||||
return nil, errors.New("headless: failed to create Metal device")
|
||||
func init() {
|
||||
newContextPrimary = func() (context, error) {
|
||||
dev := C.createDevice()
|
||||
if dev == 0 {
|
||||
return nil, errors.New("headless: failed to create Metal device")
|
||||
}
|
||||
queue := C.newCommandQueue(dev)
|
||||
if queue == 0 {
|
||||
C.CFRelease(dev)
|
||||
return nil, errors.New("headless: failed to create MTLQueue")
|
||||
}
|
||||
return &mtlContext{dev: dev, queue: queue}, nil
|
||||
}
|
||||
queue := C.newCommandQueue(dev)
|
||||
if queue == 0 {
|
||||
C.CFRelease(dev)
|
||||
return nil, errors.New("headless: failed to create MTLQueue")
|
||||
}
|
||||
return &mtlContext{dev: dev, queue: queue}, nil
|
||||
}
|
||||
|
||||
func (c *mtlContext) API() gpu.API {
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"gioui.org/internal/egl"
|
||||
)
|
||||
|
||||
func newContext() (context, error) {
|
||||
return egl.NewContext(egl.EGL_DEFAULT_DISPLAY)
|
||||
func init() {
|
||||
newContextFallback = func() (context, error) {
|
||||
return egl.NewContext(egl.EGL_DEFAULT_DISPLAY)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-13
@@ -14,20 +14,22 @@ type jsContext struct {
|
||||
ctx js.Value
|
||||
}
|
||||
|
||||
func newContext() (context, error) {
|
||||
doc := js.Global().Get("document")
|
||||
cnv := doc.Call("createElement", "canvas")
|
||||
ctx := cnv.Call("getContext", "webgl2")
|
||||
if ctx.IsNull() {
|
||||
ctx = cnv.Call("getContext", "webgl")
|
||||
func init() {
|
||||
newContextPrimary = func() (context, error) {
|
||||
doc := js.Global().Get("document")
|
||||
cnv := doc.Call("createElement", "canvas")
|
||||
ctx := cnv.Call("getContext", "webgl2")
|
||||
if ctx.IsNull() {
|
||||
ctx = cnv.Call("getContext", "webgl")
|
||||
}
|
||||
if ctx.IsNull() {
|
||||
return nil, errors.New("headless: webgl is not supported")
|
||||
}
|
||||
c := &jsContext{
|
||||
ctx: ctx,
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
if ctx.IsNull() {
|
||||
return nil, errors.New("headless: webgl is not supported")
|
||||
}
|
||||
c := &jsContext{
|
||||
ctx: ctx,
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *jsContext) API() gpu.API {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
//go:build (linux || freebsd) && !novulkan
|
||||
// +build linux freebsd
|
||||
// +build !novulkan
|
||||
|
||||
package headless
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"gioui.org/gpu"
|
||||
"gioui.org/internal/vk"
|
||||
)
|
||||
|
||||
type vkContext struct {
|
||||
physDev vk.PhysicalDevice
|
||||
inst vk.Instance
|
||||
dev vk.Device
|
||||
queueFam int
|
||||
}
|
||||
|
||||
func init() {
|
||||
newContextPrimary = newVulkanContext
|
||||
}
|
||||
|
||||
func newVulkanContext() (context, error) {
|
||||
inst, err := vk.CreateInstance()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
physDev, qFam, err := vk.ChoosePhysicalDevice(inst, 0)
|
||||
if err != nil {
|
||||
vk.DestroyInstance(inst)
|
||||
return nil, err
|
||||
}
|
||||
dev, err := vk.CreateDeviceAndQueue(physDev, qFam)
|
||||
if err != nil {
|
||||
vk.DestroyInstance(inst)
|
||||
return nil, err
|
||||
}
|
||||
ctx := &vkContext{
|
||||
physDev: physDev,
|
||||
inst: inst,
|
||||
dev: dev,
|
||||
queueFam: qFam,
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (c *vkContext) API() gpu.API {
|
||||
return gpu.Vulkan{
|
||||
PhysDevice: unsafe.Pointer(c.physDev),
|
||||
Device: unsafe.Pointer(c.dev),
|
||||
Format: int(vk.FORMAT_R8G8B8A8_SRGB),
|
||||
QueueFamily: c.queueFam,
|
||||
QueueIndex: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *vkContext) MakeCurrent() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *vkContext) ReleaseCurrent() {
|
||||
}
|
||||
|
||||
func (c *vkContext) Release() {
|
||||
vk.DeviceWaitIdle(c.dev)
|
||||
|
||||
vk.DestroyDevice(c.dev)
|
||||
vk.DestroyInstance(c.inst)
|
||||
*c = vkContext{}
|
||||
}
|
||||
@@ -13,17 +13,19 @@ type d3d11Context struct {
|
||||
dev *d3d11.Device
|
||||
}
|
||||
|
||||
func newContext() (context, error) {
|
||||
dev, ctx, _, err := d3d11.CreateDevice(
|
||||
d3d11.DRIVER_TYPE_HARDWARE,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func init() {
|
||||
newContextPrimary = func() (context, error) {
|
||||
dev, ctx, _, err := d3d11.CreateDevice(
|
||||
d3d11.DRIVER_TYPE_HARDWARE,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Don't need it.
|
||||
d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
|
||||
return &d3d11Context{dev: dev}, nil
|
||||
}
|
||||
// Don't need it.
|
||||
d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
|
||||
return &d3d11Context{dev: dev}, nil
|
||||
}
|
||||
|
||||
func (c *d3d11Context) API() gpu.API {
|
||||
|
||||
Reference in New Issue
Block a user