From 10484d26f3f453f9b8a8989668495c4c0a4031b0 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 22 Feb 2020 07:31:55 +0100 Subject: [PATCH] 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 --- gpu/backend.go | 6 +++--- gpu/gl/backend.go | 43 +++++++++++++++++++++++++++++++++++-------- gpu/gpu.go | 18 ++++++++++++++---- gpu/path.go | 17 ++++++++++++----- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/gpu/backend.go b/gpu/backend.go index 95e84d39..6006867d 100644 --- a/gpu/backend.go +++ b/gpu/backend.go @@ -18,11 +18,11 @@ type Backend interface { // IsContinuousTime reports whether all timer measurements // are valid at the point of call. 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 NewFramebuffer(tex Texture) (Framebuffer, error) - NewImmutableBuffer(typ BufferBinding, data []byte) Buffer - NewBuffer(typ BufferBinding, size int) Buffer + NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error) + NewBuffer(typ BufferBinding, size int) (Buffer, error) NewProgram(vertexShader, fragmentShader ShaderSources) (Program, error) NewInputLayout(vertexShader ShaderSources, layout []InputDesc) (InputLayout, error) diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go index 2417629c..86ae539c 100644 --- a/gpu/gl/backend.go +++ b/gpu/gl/backend.go @@ -163,10 +163,15 @@ func (b *Backend) IsTimeContinuous() bool { } func (b *Backend) NewFramebuffer(tex gpu.Texture) (gpu.Framebuffer, error) { + glErr(b.funcs) gltex := tex.(*gpuTexture) fb := b.funcs.CreateFramebuffer() fbo := &gpuFramebuffer{funcs: b.funcs, obj: fb} 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) if st := b.funcs.CheckFramebufferStatus(FRAMEBUFFER); st != FRAMEBUFFER_COMPLETE { fbo.Release() @@ -179,7 +184,8 @@ func (b *Backend) DefaultFramebuffer() gpu.Framebuffer { 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()} switch format { case gpu.TextureFormatFloat: @@ -187,7 +193,7 @@ func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFil case gpu.TextureFormatSRGB: tex.triple = b.srgbaTriple default: - panic("unsupported texture format") + return nil, errors.New("unsupported texture format") } tex.Bind(0) 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_T, CLAMP_TO_EDGE) 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} if typ&gpu.BufferBindingUniforms != 0 { 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. buf.data = make([]byte, size) } if typ&^gpu.BufferBindingUniforms != 0 { 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() buf := &gpuBuffer{backend: b, obj: obj, typ: typ, size: len(data)} buf.Upload(data) 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) { diff --git a/gpu/gpu.go b/gpu/gpu.go index d777f0c5..a8cbad7d 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -378,8 +378,12 @@ func (r *renderer) texHandle(t *texture) Texture { if t.tex != nil { return t.tex } - t.tex = r.ctx.NewTexture(TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), FilterLinear, FilterLinear, BufferBindingTexture) - t.tex.Upload(t.src) + tex, err := r.ctx.NewTexture(TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), FilterLinear, FilterLinear, BufferBindingTexture) + if err != nil { + panic(err) + } + tex.Upload(t.src) + t.tex = tex return t.tex } @@ -406,7 +410,7 @@ func (r *renderer) release() { } func newBlitter(ctx Backend) *blitter { - quadVerts := ctx.NewImmutableBuffer(BufferBindingVertices, + quadVerts, err := ctx.NewImmutableBuffer(BufferBindingVertices, gunsafe.BytesView([]float32{ -1, +1, 0, 0, +1, +1, 1, 0, @@ -414,6 +418,9 @@ func newBlitter(ctx Backend) *blitter { +1, -1, 1, 1, }), ) + if err != nil { + panic(err) + } b := &blitter{ ctx: ctx, quadVerts: quadVerts, @@ -913,7 +920,10 @@ func newUniformBuffer(b Backend, uniformBlock interface{}) *uniformBuffer { size := ref.Elem().Type().Size() // Map the uniforms structure as a byte slice. 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} } diff --git a/gpu/path.go b/gpu/path.go index 4ed88f6e..72be166a 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -150,7 +150,10 @@ func newStenciler(ctx Backend) *stenciler { indices[i*6+4] = i*4 + 1 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{ {Type: DataTypeShort, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).CornerX))}, {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.tex.Release() } - f.size = sz - f.tex = ctx.NewTexture(TextureFormatFloat, sz.X, sz.Y, FilterNearest, FilterNearest, + tex, err := ctx.NewTexture(TextureFormatFloat, sz.X, sz.Y, FilterNearest, FilterNearest, BufferBindingTexture|BufferBindingFramebuffer) - fbo, err := ctx.NewFramebuffer(f.tex) + fbo, err := ctx.NewFramebuffer(tex) if err != nil { panic(err) } + f.size = sz + f.tex = tex f.fbo = fbo } } @@ -259,7 +263,10 @@ func (c *coverer) release() { } 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{ ncurves: len(p) / path.VertStride, data: buf,