mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 18:05:35 +00:00
gpu: return and handle errors from Backend.New... methods
"handling" means panicing, but at least the panicing is moved up a layer, leaving future changes to do it properly in GPU. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+3
-3
@@ -18,11 +18,11 @@ type Backend interface {
|
|||||||
// IsContinuousTime reports whether all timer measurements
|
// IsContinuousTime reports whether all timer measurements
|
||||||
// are valid at the point of call.
|
// are valid at the point of call.
|
||||||
IsTimeContinuous() bool
|
IsTimeContinuous() bool
|
||||||
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) Texture
|
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
|
||||||
DefaultFramebuffer() Framebuffer
|
DefaultFramebuffer() Framebuffer
|
||||||
NewFramebuffer(tex Texture) (Framebuffer, error)
|
NewFramebuffer(tex Texture) (Framebuffer, error)
|
||||||
NewImmutableBuffer(typ BufferBinding, data []byte) Buffer
|
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
|
||||||
NewBuffer(typ BufferBinding, size int) Buffer
|
NewBuffer(typ BufferBinding, size int) (Buffer, error)
|
||||||
NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
|
NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error)
|
||||||
NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
|
NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error)
|
||||||
|
|
||||||
|
|||||||
+35
-8
@@ -163,10 +163,15 @@ func (b *Backend) IsTimeContinuous() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) NewFramebuffer(tex gpu.Texture) (gpu.Framebuffer, error) {
|
func (b *Backend) NewFramebuffer(tex gpu.Texture) (gpu.Framebuffer, error) {
|
||||||
|
glErr(b.funcs)
|
||||||
gltex := tex.(*gpuTexture)
|
gltex := tex.(*gpuTexture)
|
||||||
fb := b.funcs.CreateFramebuffer()
|
fb := b.funcs.CreateFramebuffer()
|
||||||
fbo := &gpuFramebuffer{funcs: b.funcs, obj: fb}
|
fbo := &gpuFramebuffer{funcs: b.funcs, obj: fb}
|
||||||
fbo.Bind()
|
fbo.Bind()
|
||||||
|
if err := glErr(b.funcs); err != nil {
|
||||||
|
fbo.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
b.funcs.FramebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, gltex.obj, 0)
|
b.funcs.FramebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, gltex.obj, 0)
|
||||||
if st := b.funcs.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE {
|
if st := b.funcs.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE {
|
||||||
fbo.Release()
|
fbo.Release()
|
||||||
@@ -179,7 +184,8 @@ func (b *Backend) DefaultFramebuffer() gpu.Framebuffer {
|
|||||||
return b.defFBO
|
return b.defFBO
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFilter, magFilter gpu.TextureFilter, binding gpu.BufferBinding) gpu.Texture {
|
func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFilter, magFilter gpu.TextureFilter, binding gpu.BufferBinding) (gpu.Texture, error) {
|
||||||
|
glErr(b.funcs)
|
||||||
tex := &gpuTexture{backend: b, obj: b.funcs.CreateTexture()}
|
tex := &gpuTexture{backend: b, obj: b.funcs.CreateTexture()}
|
||||||
switch format {
|
switch format {
|
||||||
case gpu.TextureFormatFloat:
|
case gpu.TextureFormatFloat:
|
||||||
@@ -187,7 +193,7 @@ func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFil
|
|||||||
case gpu.TextureFormatSRGB:
|
case gpu.TextureFormatSRGB:
|
||||||
tex.triple = b.srgbaTriple
|
tex.triple = b.srgbaTriple
|
||||||
default:
|
default:
|
||||||
panic("unsupported texture format")
|
return nil, errors.New("unsupported texture format")
|
||||||
}
|
}
|
||||||
tex.Bind(0)
|
tex.Bind(0)
|
||||||
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, toTexFilter(magFilter))
|
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, toTexFilter(magFilter))
|
||||||
@@ -195,30 +201,51 @@ func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFil
|
|||||||
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE)
|
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE)
|
||||||
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE)
|
b.funcs.TexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE)
|
||||||
b.funcs.TexImage2D(TEXTURE_2D, 0, tex.triple.internalFormat, width, height, tex.triple.format, tex.triple.typ, nil)
|
b.funcs.TexImage2D(TEXTURE_2D, 0, tex.triple.internalFormat, width, height, tex.triple.format, tex.triple.typ, nil)
|
||||||
return tex
|
if err := glErr(b.funcs); err != nil {
|
||||||
|
tex.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) NewBuffer(typ gpu.BufferBinding, size int) gpu.Buffer {
|
func (b *Backend) NewBuffer(typ gpu.BufferBinding, size int) (gpu.Buffer, error) {
|
||||||
|
glErr(b.funcs)
|
||||||
buf := &gpuBuffer{backend: b, typ: typ, size: size}
|
buf := &gpuBuffer{backend: b, typ: typ, size: size}
|
||||||
if typ&gpu.BufferBindingUniforms != 0 {
|
if typ&gpu.BufferBindingUniforms != 0 {
|
||||||
if typ != gpu.BufferBindingUniforms {
|
if typ != gpu.BufferBindingUniforms {
|
||||||
panic("uniforms buffers cannot be bound as anything else")
|
return nil, errors.New("uniforms buffers cannot be bound as anything else")
|
||||||
}
|
}
|
||||||
// GLES 2 doesn't support uniform buffers.
|
// GLES 2 doesn't support uniform buffers.
|
||||||
buf.data = make([]byte, size)
|
buf.data = make([]byte, size)
|
||||||
}
|
}
|
||||||
if typ&^gpu.BufferBindingUniforms != 0 {
|
if typ&^gpu.BufferBindingUniforms != 0 {
|
||||||
buf.obj = b.funcs.CreateBuffer()
|
buf.obj = b.funcs.CreateBuffer()
|
||||||
|
if err := glErr(b.funcs); err != nil {
|
||||||
|
buf.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return buf
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) NewImmutableBuffer(typ gpu.BufferBinding, data []byte) gpu.Buffer {
|
func (b *Backend) NewImmutableBuffer(typ gpu.BufferBinding, data []byte) (gpu.Buffer, error) {
|
||||||
|
glErr(b.funcs)
|
||||||
obj := b.funcs.CreateBuffer()
|
obj := b.funcs.CreateBuffer()
|
||||||
buf := &gpuBuffer{backend: b, obj: obj, typ: typ, size: len(data)}
|
buf := &gpuBuffer{backend: b, obj: obj, typ: typ, size: len(data)}
|
||||||
buf.Upload(data)
|
buf.Upload(data)
|
||||||
buf.immutable = true
|
buf.immutable = true
|
||||||
return buf
|
if err := glErr(b.funcs); err != nil {
|
||||||
|
buf.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func glErr(f Functions) error {
|
||||||
|
if st := f.GetError(); st != NO_ERROR {
|
||||||
|
return fmt.Errorf("glGetError: %#x", st)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) bindTexture(unit int, t *gpuTexture) {
|
func (b *Backend) bindTexture(unit int, t *gpuTexture) {
|
||||||
|
|||||||
+14
-4
@@ -378,8 +378,12 @@ func (r *renderer) texHandle(t *texture) Texture {
|
|||||||
if t.tex != nil {
|
if t.tex != nil {
|
||||||
return t.tex
|
return t.tex
|
||||||
}
|
}
|
||||||
t.tex = r.ctx.NewTexture(TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), FilterLinear, FilterLinear, BufferBindingTexture)
|
tex, err := r.ctx.NewTexture(TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), FilterLinear, FilterLinear, BufferBindingTexture)
|
||||||
t.tex.Upload(t.src)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
tex.Upload(t.src)
|
||||||
|
t.tex = tex
|
||||||
return t.tex
|
return t.tex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +410,7 @@ func (r *renderer) release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newBlitter(ctx Backend) *blitter {
|
func newBlitter(ctx Backend) *blitter {
|
||||||
quadVerts := ctx.NewImmutableBuffer(BufferBindingVertices,
|
quadVerts, err := ctx.NewImmutableBuffer(BufferBindingVertices,
|
||||||
gunsafe.BytesView([]float32{
|
gunsafe.BytesView([]float32{
|
||||||
-1, +1, 0, 0,
|
-1, +1, 0, 0,
|
||||||
+1, +1, 1, 0,
|
+1, +1, 1, 0,
|
||||||
@@ -414,6 +418,9 @@ func newBlitter(ctx Backend) *blitter {
|
|||||||
+1, -1, 1, 1,
|
+1, -1, 1, 1,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
b := &blitter{
|
b := &blitter{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
quadVerts: quadVerts,
|
quadVerts: quadVerts,
|
||||||
@@ -913,7 +920,10 @@ func newUniformBuffer(b Backend, uniformBlock interface{}) *uniformBuffer {
|
|||||||
size := ref.Elem().Type().Size()
|
size := ref.Elem().Type().Size()
|
||||||
// Map the uniforms structure as a byte slice.
|
// Map the uniforms structure as a byte slice.
|
||||||
ptr := (*[1 << 30]byte)(unsafe.Pointer(ref.Pointer()))[:size:size]
|
ptr := (*[1 << 30]byte)(unsafe.Pointer(ref.Pointer()))[:size:size]
|
||||||
ubuf := b.NewBuffer(BufferBindingUniforms, len(ptr))
|
ubuf, err := b.NewBuffer(BufferBindingUniforms, len(ptr))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return &uniformBuffer{buf: ubuf, ptr: ptr}
|
return &uniformBuffer{buf: ubuf, ptr: ptr}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-5
@@ -150,7 +150,10 @@ func newStenciler(ctx Backend) *stenciler {
|
|||||||
indices[i*6+4] = i*4 + 1
|
indices[i*6+4] = i*4 + 1
|
||||||
indices[i*6+5] = i*4 + 3
|
indices[i*6+5] = i*4 + 3
|
||||||
}
|
}
|
||||||
indexBuf := ctx.NewImmutableBuffer(BufferBindingIndices, gunsafe.BytesView(indices))
|
indexBuf, err := ctx.NewImmutableBuffer(BufferBindingIndices, gunsafe.BytesView(indices))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
progLayout, err := ctx.NewInputLayout(shader_stencil_vert, []InputDesc{
|
progLayout, err := ctx.NewInputLayout(shader_stencil_vert, []InputDesc{
|
||||||
{Type: DataTypeShort, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).CornerX))},
|
{Type: DataTypeShort, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).CornerX))},
|
||||||
{Type: DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).MaxY))},
|
{Type: DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).MaxY))},
|
||||||
@@ -208,13 +211,14 @@ func (s *fboSet) resize(ctx Backend, sizes []image.Point) {
|
|||||||
f.fbo.Release()
|
f.fbo.Release()
|
||||||
f.tex.Release()
|
f.tex.Release()
|
||||||
}
|
}
|
||||||
f.size = sz
|
tex, err := ctx.NewTexture(TextureFormatFloat, sz.X, sz.Y, FilterNearest, FilterNearest,
|
||||||
f.tex = ctx.NewTexture(TextureFormatFloat, sz.X, sz.Y, FilterNearest, FilterNearest,
|
|
||||||
BufferBindingTexture|BufferBindingFramebuffer)
|
BufferBindingTexture|BufferBindingFramebuffer)
|
||||||
fbo, err := ctx.NewFramebuffer(f.tex)
|
fbo, err := ctx.NewFramebuffer(tex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
f.size = sz
|
||||||
|
f.tex = tex
|
||||||
f.fbo = fbo
|
f.fbo = fbo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,7 +263,10 @@ func (c *coverer) release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildPath(ctx Backend, p []byte) *pathData {
|
func buildPath(ctx Backend, p []byte) *pathData {
|
||||||
buf := ctx.NewImmutableBuffer(BufferBindingVertices, p)
|
buf, err := ctx.NewImmutableBuffer(BufferBindingVertices, p)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return &pathData{
|
return &pathData{
|
||||||
ncurves: len(p) / path.VertStride,
|
ncurves: len(p) / path.VertStride,
|
||||||
data: buf,
|
data: buf,
|
||||||
|
|||||||
Reference in New Issue
Block a user