internal/graphicscommand: bug fix: call End even if an error causes

Without calling End, the graphics driver (especially Metal) state
might be stale and might cause another error.

Closes #2388
This commit is contained in:
Hajime Hoshi 2022-10-15 15:23:02 +09:00
parent 35e9f26681
commit e42ee8c506

View File

@ -167,7 +167,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
} }
// flush must be called the main thread. // flush must be called the main thread.
func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) error { func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) (err error) {
if len(q.commands) == 0 { if len(q.commands) == 0 {
return nil return nil
} }
@ -179,6 +179,29 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
if err := graphicsDriver.Begin(); err != nil { if err := graphicsDriver.Begin(); err != nil {
return err return err
} }
defer func() {
// Call End even if an error causes, or the graphics driver's state might be stale (#2388).
if err1 := graphicsDriver.End(endFrame); err1 != nil && err == nil {
err = err1
}
// Release the commands explicitly (#1803).
// Apparently, the part of a slice between len and cap-1 still holds references.
// Then, resetting the length by [:0] doesn't release the references.
for i, c := range q.commands {
if c, ok := c.(*drawTrianglesCommand); ok {
q.drawTrianglesCommandPool.put(c)
}
q.commands[i] = nil
}
q.commands = q.commands[:0]
q.vertices = q.vertices[:0]
q.indices = q.indices[:0]
q.tmpNumVertexFloats = 0
q.tmpNumIndices = 0
}()
cs := q.commands cs := q.commands
for len(cs) > 0 { for len(cs) > 0 {
nv := 0 nv := 0
@ -219,24 +242,7 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
} }
cs = cs[nc:] cs = cs[nc:]
} }
if err := graphicsDriver.End(endFrame); err != nil {
return err
}
// Release the commands explicitly (#1803).
// Apparently, the part of a slice between len and cap-1 still holds references.
// Then, resetting the length by [:0] doesn't release the references.
for i, c := range q.commands {
if c, ok := c.(*drawTrianglesCommand); ok {
q.drawTrianglesCommandPool.put(c)
}
q.commands[i] = nil
}
q.commands = q.commands[:0]
q.vertices = q.vertices[:0]
q.indices = q.indices[:0]
q.tmpNumVertexFloats = 0
q.tmpNumIndices = 0
return nil return nil
} }