mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
gpu,gpu/backend: implement generic backend.NewDevice
NewDevice creates a Device given an API, which is the necessary GPU resources for a backend. Convert gpu.New to take an API instead of a backend.Device directly. In turn, this frees us to later unexport the backend package along with the backend implementations (for now just gioui.org/gpu/gl for OpenGL). It also allows programs that embed Gio (such as gioui.org/example/glfw) to freely choose a backend, not just OpenGL. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -170,7 +170,7 @@ func newBackend(t *testing.T) backend.Device {
|
|||||||
if err := ctx.MakeCurrent(); err != nil {
|
if err := ctx.MakeCurrent(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b, err := ctx.Backend()
|
b, err := backend.NewDevice(ctx.API())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type Window struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type context interface {
|
type context interface {
|
||||||
Backend() (backend.Device, error)
|
API() gpu.API
|
||||||
MakeCurrent() error
|
MakeCurrent() error
|
||||||
ReleaseCurrent()
|
ReleaseCurrent()
|
||||||
Release()
|
Release()
|
||||||
@@ -42,7 +42,8 @@ func NewWindow(width, height int) (*Window, error) {
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
err = contextDo(ctx, func() error {
|
err = contextDo(ctx, func() error {
|
||||||
dev, err := ctx.Backend()
|
api := ctx.API()
|
||||||
|
dev, err := backend.NewDevice(api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -62,7 +63,7 @@ func NewWindow(width, height int) (*Window, error) {
|
|||||||
fboTex.Release()
|
fboTex.Release()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gp, err := gpu.New(dev)
|
gp, err := gpu.New(api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fbo.Release()
|
fbo.Release()
|
||||||
fboTex.Release()
|
fboTex.Release()
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
package headless
|
package headless
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
|
|
||||||
_ "gioui.org/app/internal/cocoainit"
|
_ "gioui.org/app/internal/cocoainit"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,6 +30,10 @@ func newGLContext() (context, error) {
|
|||||||
return &nsContext{ctx: ctx}, nil
|
return &nsContext{ctx: ctx}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *nsContext) API() gpu.API {
|
||||||
|
return gpu.OpenGL{}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *nsContext) MakeCurrent() error {
|
func (c *nsContext) MakeCurrent() error {
|
||||||
C.gio_headless_makeCurrentContext(c.ctx)
|
C.gio_headless_makeCurrentContext(c.ctx)
|
||||||
if !c.prepared {
|
if !c.prepared {
|
||||||
@@ -45,10 +47,6 @@ func (c *nsContext) ReleaseCurrent() {
|
|||||||
C.gio_headless_clearCurrentContext(c.ctx)
|
C.gio_headless_clearCurrentContext(c.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nsContext) Backend() (backend.Device, error) {
|
|
||||||
return gl.NewBackend(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *nsContext) Release() {
|
func (d *nsContext) Release() {
|
||||||
if d.ctx != 0 {
|
if d.ctx != 0 {
|
||||||
C.gio_headless_releaseContext(d.ctx)
|
C.gio_headless_releaseContext(d.ctx)
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
"gioui.org/internal/glimpl"
|
"gioui.org/internal/glimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,8 +30,8 @@ func newGLContext() (context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *jsContext) Backend() (backend.Device, error) {
|
func (c *jsContext) API() gpu.API {
|
||||||
return gl.NewBackend(glimpl.Context(c.ctx))
|
return gpu.OpenGL{Context: glimpl.Context(c.ctx)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *jsContext) Release() {
|
func (c *jsContext) Release() {
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
package headless
|
package headless
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"gioui.org/gpu"
|
||||||
"gioui.org/app/internal/d3d11"
|
"gioui.org/app/internal/d3d11"
|
||||||
"gioui.org/gpu/backend"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type d3d11Context struct {
|
type d3d11Context struct {
|
||||||
@@ -19,12 +21,8 @@ func newContext() (context, error) {
|
|||||||
return &d3d11Context{dev: dev}, nil
|
return &d3d11Context{dev: dev}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *d3d11Context) Backend() (backend.Device, error) {
|
func (c *d3d11Context) API() gpu.API {
|
||||||
backend, err := d3d11.NewBackend(c.dev.Handle)
|
return gpu.Direct3D11{Device: unsafe.Pointer(c.dev.Handle)}
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return backend, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *d3d11Context) MakeCurrent() error {
|
func (c *d3d11Context) MakeCurrent() error {
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ type SwapChain struct {
|
|||||||
fbo *Framebuffer
|
fbo *Framebuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
backend.NewDirect3D11Device = newDirect3D11Device
|
||||||
|
}
|
||||||
|
|
||||||
func NewDevice() (*Device, error) {
|
func NewDevice() (*Device, error) {
|
||||||
var flags uint32
|
var flags uint32
|
||||||
if debug {
|
if debug {
|
||||||
@@ -237,7 +241,8 @@ func (s *SwapChain) Present() error {
|
|||||||
return s.swchain.Present(1, 0)
|
return s.swchain.Present(1, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBackend(dev *_ID3D11Device) (*Backend, error) {
|
func newDirect3D11Device(api backend.Direct3D11) (backend.Device, error) {
|
||||||
|
dev := (*_ID3D11Device)(api.Device)
|
||||||
b := &Backend{
|
b := &Backend{
|
||||||
dev: dev,
|
dev: dev,
|
||||||
ctx: dev.GetImmediateContext(),
|
ctx: dev.GetImmediateContext(),
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gioui.org/app/internal/srgb"
|
"gioui.org/app/internal/srgb"
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
"gioui.org/internal/glimpl"
|
"gioui.org/internal/glimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -118,8 +117,8 @@ func NewContext(disp NativeDisplayType) (*Context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) Backend() (backend.Device, error) {
|
func (c *Context) API() gpu.API {
|
||||||
return gl.NewBackend(nil)
|
return gpu.OpenGL{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) ReleaseSurface() {
|
func (c *Context) ReleaseSurface() {
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
package window
|
package window
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"gioui.org/gpu"
|
||||||
"gioui.org/app/internal/d3d11"
|
"gioui.org/app/internal/d3d11"
|
||||||
"gioui.org/gpu/backend"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type d3d11Context struct {
|
type d3d11Context struct {
|
||||||
@@ -34,8 +36,8 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *d3d11Context) Backend() (backend.Device, error) {
|
func (c *d3d11Context) API() gpu.API {
|
||||||
return d3d11.NewBackend(c.dev.Handle)
|
return gpu.Direct3D11{Device: unsafe.Pointer(c.dev.Handle)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *d3d11Context) Present() error {
|
func (c *d3d11Context) Present() error {
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
"gioui.org/internal/glimpl"
|
"gioui.org/internal/glimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,8 +55,8 @@ func newContext(w *window) (*context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Backend() (backend.Device, error) {
|
func (c *context) API() gpu.API {
|
||||||
return gl.NewBackend(nil)
|
return gpu.OpenGL{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Release() {
|
func (c *context) Release() {
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import (
|
|||||||
"syscall/js"
|
"syscall/js"
|
||||||
|
|
||||||
"gioui.org/app/internal/srgb"
|
"gioui.org/app/internal/srgb"
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
"gioui.org/internal/glimpl"
|
"gioui.org/internal/glimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,8 +38,8 @@ func newContext(w *window) (*context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Backend() (backend.Device, error) {
|
func (c *context) API() gpu.API {
|
||||||
return gl.NewBackend(glimpl.Context(c.ctx))
|
return gpu.OpenGL{Context: glimpl.Context(c.ctx)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Release() {
|
func (c *context) Release() {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
package window
|
package window
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/gpu/gl"
|
|
||||||
"gioui.org/internal/glimpl"
|
"gioui.org/internal/glimpl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,8 +47,8 @@ func newContext(w *window) (*context, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Backend() (backend.Device, error) {
|
func (c *context) API() gpu.API {
|
||||||
return gl.NewBackend(nil)
|
return gpu.OpenGL{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Release() {
|
func (c *context) Release() {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package window
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"gioui.org/gpu/backend"
|
"gioui.org/gpu"
|
||||||
"gioui.org/io/event"
|
"gioui.org/io/event"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
"gioui.org/io/system"
|
"gioui.org/io/system"
|
||||||
@@ -33,7 +33,7 @@ type Callbacks interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Context interface {
|
type Context interface {
|
||||||
Backend() (backend.Device, error)
|
API() gpu.API
|
||||||
Present() error
|
Present() error
|
||||||
MakeCurrent() error
|
MakeCurrent() error
|
||||||
Release()
|
Release()
|
||||||
|
|||||||
+1
-6
@@ -67,12 +67,7 @@ func (l *renderLoop) renderLoop(ctx window.Context) error {
|
|||||||
initErr <- err
|
initErr <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b, err := ctx.Backend()
|
g, err := gpu.New(ctx.API())
|
||||||
if err != nil {
|
|
||||||
initErr <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
g, err := gpu.New(b)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initErr <- err
|
initErr <- err
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
"golang.org/x/tools/go/packages"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -18,6 +16,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
type androidTools struct {
|
type androidTools struct {
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/akavel/rsrc/binutil"
|
|
||||||
"github.com/akavel/rsrc/coff"
|
|
||||||
"golang.org/x/text/encoding/unicode"
|
|
||||||
"image/png"
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -17,6 +14,10 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/akavel/rsrc/binutil"
|
||||||
|
"github.com/akavel/rsrc/coff"
|
||||||
|
"golang.org/x/text/encoding/unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildWindows(tmpDir string, bi *buildInfo) error {
|
func buildWindows(tmpDir string, bi *buildInfo) error {
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
package gpu
|
||||||
|
|
||||||
|
import "gioui.org/gpu/backend"
|
||||||
|
|
||||||
|
// An API carries the necessary GPU API specific resources to create a Device.
|
||||||
|
// There is an API type for each supported GPU API such as OpenGL and Direct3D.
|
||||||
|
type API = backend.API
|
||||||
|
|
||||||
|
// OpenGL denotes the OpenGL or OpenGL ES API.
|
||||||
|
type OpenGL = backend.OpenGL
|
||||||
|
|
||||||
|
// Direct3D11 denotes the Direct3D API.
|
||||||
|
type Direct3D11 = backend.Direct3D11
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"gioui.org/internal/glimpl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// See gpu/api.go for documentation for the API types
|
||||||
|
|
||||||
|
type API interface {
|
||||||
|
implementsAPI()
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpenGL struct {
|
||||||
|
// Context contains the WebGL context for WebAssembly platforms. It is
|
||||||
|
// empty for all other platforms; an OpenGL context is assumed current when
|
||||||
|
// calling NewDevice.
|
||||||
|
Context glimpl.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
type Direct3D11 struct {
|
||||||
|
// Device contains a *ID3D11Device.
|
||||||
|
Device unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// API specific device constructors.
|
||||||
|
var (
|
||||||
|
NewOpenGLDevice func(api OpenGL) (Device, error)
|
||||||
|
NewDirect3D11Device func(api Direct3D11) (Device, error)
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDevice creates a new Device given the api.
|
||||||
|
//
|
||||||
|
// Note that the device does not assume ownership of the resources contained in
|
||||||
|
// api; the caller must ensure the resources are valid until the device is
|
||||||
|
// released.
|
||||||
|
func NewDevice(api API) (Device, error) {
|
||||||
|
switch api := api.(type) {
|
||||||
|
case OpenGL:
|
||||||
|
if NewOpenGLDevice != nil {
|
||||||
|
return NewOpenGLDevice(api)
|
||||||
|
}
|
||||||
|
case Direct3D11:
|
||||||
|
if NewDirect3D11Device != nil {
|
||||||
|
return NewDirect3D11Device(api)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("backend: no backend available for the API %T", api)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (OpenGL) implementsAPI() {}
|
||||||
|
func (Direct3D11) implementsAPI() {}
|
||||||
+6
-6
@@ -123,12 +123,12 @@ const (
|
|||||||
storageBindings = 32
|
storageBindings = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBackend returns a new Backend.
|
func init() {
|
||||||
//
|
backend.NewOpenGLDevice = newOpenGLDevice
|
||||||
// Pass a WebGL context if GOOS is "js", otherwise pass nil for the current
|
}
|
||||||
// context.
|
|
||||||
func NewBackend(ctx Context) (*Backend, error) {
|
func newOpenGLDevice(api backend.OpenGL) (backend.Device, error) {
|
||||||
f, err := glimpl.NewFunctions(ctx)
|
f, err := glimpl.NewFunctions(api.Context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-4
@@ -28,6 +28,9 @@ import (
|
|||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
|
|
||||||
|
// Register backend.
|
||||||
|
_ "gioui.org/gpu/gl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GPU interface {
|
type GPU interface {
|
||||||
@@ -380,14 +383,18 @@ const (
|
|||||||
materialTexture
|
materialTexture
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(ctx backend.Device) (GPU, error) {
|
func New(api API) (GPU, error) {
|
||||||
|
d, err := backend.NewDevice(api)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
forceCompute := os.Getenv("GIORENDERER") == "forcecompute"
|
forceCompute := os.Getenv("GIORENDERER") == "forcecompute"
|
||||||
feats := ctx.Caps().Features
|
feats := d.Caps().Features
|
||||||
switch {
|
switch {
|
||||||
case !forceCompute && feats.Has(backend.FeatureFloatRenderTargets):
|
case !forceCompute && feats.Has(backend.FeatureFloatRenderTargets):
|
||||||
return newGPU(ctx)
|
return newGPU(d)
|
||||||
case feats.Has(backend.FeatureCompute):
|
case feats.Has(backend.FeatureCompute):
|
||||||
return newCompute(ctx)
|
return newCompute(d)
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("gpu: no support for float render targets nor compute")
|
return nil, errors.New("gpu: no support for float render targets nor compute")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user