internal/affine: Change UnsafeElements to take arguments

This will enable to suppress unnecessary array allocations in the
future.

Updates #1796
This commit is contained in:
Hajime Hoshi 2021-09-04 17:29:42 +09:00
parent 65e148700f
commit df710a5c63
5 changed files with 75 additions and 27 deletions

View File

@ -44,7 +44,7 @@ var (
type ColorM interface { type ColorM interface {
IsIdentity() bool IsIdentity() bool
ScaleOnly() bool ScaleOnly() bool
UnsafeElements() (*[16]float32, *[4]float32) UnsafeElements(body *[16]float32, translate *[4]float32)
Apply(clr color.Color) color.Color Apply(clr color.Color) color.Color
// IsInvertible returns a boolean value indicating // IsInvertible returns a boolean value indicating
@ -71,7 +71,9 @@ type ColorM interface {
} }
func ColorMString(c ColorM) string { func ColorMString(c ColorM) string {
b, t := c.UnsafeElements() var b [16]float32
var t [4]float32
c.UnsafeElements(&b, &t)
return fmt.Sprintf("[[%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f]]", return fmt.Sprintf("[[%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f]]",
b[0], b[4], b[8], b[12], t[0], b[0], b[4], b[8], b[12], t[0],
b[1], b[5], b[9], b[13], t[1], b[1], b[5], b[9], b[13], t[1],
@ -238,21 +240,55 @@ func (c *colorMImplBodyTranslate) Apply(clr color.Color) color.Color {
} }
} }
func (c ColorMIdentity) UnsafeElements() (*[16]float32, *[4]float32) { func (c ColorMIdentity) UnsafeElements(body *[16]float32, translate *[4]float32) {
return &colorMIdentityBody, &colorMIdentityTranslate body[0] = 1
body[1] = 0
body[2] = 0
body[3] = 0
body[4] = 0
body[5] = 1
body[6] = 0
body[7] = 0
body[8] = 0
body[9] = 0
body[10] = 1
body[11] = 0
body[12] = 0
body[13] = 0
body[14] = 0
body[15] = 1
translate[0] = 0
translate[1] = 0
translate[2] = 0
translate[3] = 0
} }
func (c colorMImplScale) UnsafeElements() (*[16]float32, *[4]float32) { func (c colorMImplScale) UnsafeElements(body *[16]float32, translate *[4]float32) {
return &[...]float32{ body[0] = c.scale[0]
c.scale[0], 0, 0, 0, body[1] = 0
0, c.scale[1], 0, 0, body[2] = 0
0, 0, c.scale[2], 0, body[3] = 0
0, 0, 0, c.scale[3], body[4] = 0
}, &colorMIdentityTranslate body[5] = c.scale[1]
body[6] = 0
body[7] = 0
body[8] = 0
body[9] = 0
body[10] = c.scale[2]
body[11] = 0
body[12] = 0
body[13] = 0
body[14] = 0
body[15] = c.scale[3]
translate[0] = 0
translate[1] = 0
translate[2] = 0
translate[3] = 0
} }
func (c *colorMImplBodyTranslate) UnsafeElements() (*[16]float32, *[4]float32) { func (c *colorMImplBodyTranslate) UnsafeElements(body *[16]float32, translate *[4]float32) {
return &c.body, &c.translate copy(body[:], c.body[:])
copy(translate[:], c.translate[:])
} }
func (c *colorMImplBodyTranslate) det() float32 { func (c *colorMImplBodyTranslate) det() float32 {
@ -420,7 +456,9 @@ func (c *colorMImplBodyTranslate) Invert() ColorM {
// ColorMElement returns a value of a matrix at (i, j). // ColorMElement returns a value of a matrix at (i, j).
func ColorMElement(c ColorM, i, j int) float32 { func ColorMElement(c ColorM, i, j int) float32 {
b, t := c.UnsafeElements() var b [16]float32
var t [4]float32
c.UnsafeElements(&b, &t)
if j < ColorMDim-1 { if j < ColorMDim-1 {
return b[i+j*(ColorMDim-1)] return b[i+j*(ColorMDim-1)]
} }
@ -433,9 +471,7 @@ func ColorMSetElement(c ColorM, i, j int, element float32) ColorM {
body: colorMIdentityBody, body: colorMIdentityBody,
} }
if !c.IsIdentity() { if !c.IsIdentity() {
b, t := c.UnsafeElements() c.UnsafeElements(&newImpl.body, &newImpl.translate)
newImpl.body = *b
newImpl.translate = *t
} }
if j < (ColorMDim - 1) { if j < (ColorMDim - 1) {
newImpl.body[i+j*(ColorMDim-1)] = element newImpl.body[i+j*(ColorMDim-1)] = element
@ -471,10 +507,12 @@ func (c colorMImplScale) Equals(other ColorM) bool {
} }
func (c *colorMImplBodyTranslate) Equals(other ColorM) bool { func (c *colorMImplBodyTranslate) Equals(other ColorM) bool {
lhsb, lhst := other.UnsafeElements() var lhsb [16]float32
var lhst [4]float32
other.UnsafeElements(&lhsb, &lhst)
rhsb := &c.body rhsb := &c.body
rhst := &c.translate rhst := &c.translate
return *lhsb == *rhsb && *lhst == *rhst return lhsb == *rhsb && lhst == *rhst
} }
func (c ColorMIdentity) Concat(other ColorM) ColorM { func (c ColorMIdentity) Concat(other ColorM) ColorM {
@ -490,7 +528,9 @@ func (c colorMImplScale) Concat(other ColorM) ColorM {
return c.Scale(other.scaleElements()) return c.Scale(other.scaleElements())
} }
lhsb, lhst := other.UnsafeElements() var lhsb [16]float32
var lhst [4]float32
other.UnsafeElements(&lhsb, &lhst)
s := &c.scale s := &c.scale
return &colorMImplBodyTranslate{ return &colorMImplBodyTranslate{
body: [...]float32{ body: [...]float32{
@ -499,7 +539,7 @@ func (c colorMImplScale) Concat(other ColorM) ColorM {
lhsb[8] * s[2], lhsb[9] * s[2], lhsb[10] * s[2], lhsb[11] * s[2], lhsb[8] * s[2], lhsb[9] * s[2], lhsb[10] * s[2], lhsb[11] * s[2],
lhsb[12] * s[3], lhsb[13] * s[3], lhsb[14] * s[3], lhsb[15] * s[3], lhsb[12] * s[3], lhsb[13] * s[3], lhsb[14] * s[3], lhsb[15] * s[3],
}, },
translate: *lhst, translate: lhst,
} }
} }
@ -508,14 +548,16 @@ func (c *colorMImplBodyTranslate) Concat(other ColorM) ColorM {
return c return c
} }
lhsb, lhst := other.UnsafeElements() var lhsb [16]float32
var lhst [4]float32
other.UnsafeElements(&lhsb, &lhst)
rhsb := &c.body rhsb := &c.body
rhst := &c.translate rhst := &c.translate
return &colorMImplBodyTranslate{ return &colorMImplBodyTranslate{
// TODO: This is a temporary hack to calculate multiply of transposed matrices. // TODO: This is a temporary hack to calculate multiply of transposed matrices.
// Fix mulSquare implmentation and swap the arguments. // Fix mulSquare implmentation and swap the arguments.
body: mulSquare(rhsb, lhsb, ColorMDim-1), body: mulSquare(rhsb, &lhsb, ColorMDim-1),
translate: [...]float32{ translate: [...]float32{
lhsb[0]*rhst[0] + lhsb[4]*rhst[1] + lhsb[8]*rhst[2] + lhsb[12]*rhst[3] + lhst[0], lhsb[0]*rhst[0] + lhsb[4]*rhst[1] + lhsb[8]*rhst[2] + lhsb[12]*rhst[3] + lhst[0],
lhsb[1]*rhst[0] + lhsb[5]*rhst[1] + lhsb[9]*rhst[2] + lhsb[13]*rhst[3] + lhst[1], lhsb[1]*rhst[0] + lhsb[5]*rhst[1] + lhsb[9]*rhst[2] + lhsb[13]*rhst[3] + lhst[1],

View File

@ -35,7 +35,7 @@ const (
type ColorM interface { type ColorM interface {
IsIdentity() bool IsIdentity() bool
UnsafeElements() (*[16]float32, *[4]float32) UnsafeElements(body *[16]float32, translate *[4]float32)
} }
type Graphics interface { type Graphics interface {

View File

@ -908,7 +908,9 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
sourceSize[0] = float32(w) sourceSize[0] = float32(w)
sourceSize[1] = float32(h) sourceSize[1] = float32(h)
} }
esBody, esTranslate := colorM.UnsafeElements() var esBody [16]float32
var esTranslate [4]float32
colorM.UnsafeElements(&esBody, &esTranslate)
scale := float32(0) scale := float32(0)
if filter == driver.FilterScreen { if filter == driver.FilterScreen {
scale = float32(dst.width) / float32(srcs[0].width) scale = float32(dst.width) / float32(srcs[0].width)

View File

@ -188,7 +188,9 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
if !colorM.IsIdentity() { if !colorM.IsIdentity() {
// ColorM's elements are immutable. It's OK to hold the reference without copying. // ColorM's elements are immutable. It's OK to hold the reference without copying.
esBody, esTranslate := colorM.UnsafeElements() var esBody [16]float32
var esTranslate [4]float32
colorM.UnsafeElements(&esBody, &esTranslate)
uniformVars = append(uniformVars, uniformVariable{ uniformVars = append(uniformVars, uniformVariable{
name: "color_matrix_body", name: "color_matrix_body",
value: esBody[:], value: esBody[:],

View File

@ -124,7 +124,9 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices [
} }
if colorm.ScaleOnly() { if colorm.ScaleOnly() {
body, _ := colorm.UnsafeElements() var body [16]float32
var translate [4]float32
colorm.UnsafeElements(&body, &translate)
cr := body[0] cr := body[0]
cg := body[5] cg := body[5]
cb := body[10] cb := body[10]