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:
Elias Naur
2020-02-22 07:31:55 +01:00
parent 9c984e03b8
commit 10484d26f3
4 changed files with 64 additions and 20 deletions
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,