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
// 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)
+35 -8
View File
@@ -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) {
+14 -4
View File
@@ -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}
}
+12 -5
View File
@@ -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,