gpu: cache path data for compute

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-01-02 20:13:06 +01:00
parent 23f710910f
commit bb9252f9d4
3 changed files with 22 additions and 12 deletions
+4 -3
View File
@@ -27,9 +27,10 @@ type opCache struct {
type opCacheValue struct { type opCacheValue struct {
data pathData data pathData
// cpuData is the retained data, if kept by the compute renderer. // computePath is the encoded path for compute.
cpuData []byte computePath encoder
bounds f32.Rectangle
bounds f32.Rectangle
// the fields below are handled by opCache // the fields below are handled by opCache
key ops.Key key ops.Key
keep bool keep bool
+13 -3
View File
@@ -409,7 +409,9 @@ func (g *compute) encodeClipStack(clip, bounds f32.Rectangle, p *pathOp) int {
} }
if p != nil && p.path { if p != nil && p.path {
pathData, _ := g.drawOps.pathCache.get(p.pathKey) pathData, _ := g.drawOps.pathCache.get(p.pathKey)
g.encodePath(p.off, pathData.cpuData) g.enc.transform(f32.Affine2D{}.Offset(p.off))
g.enc.append(pathData.computePath)
g.enc.transform(f32.Affine2D{}.Offset(p.off.Mul(-1)))
} else { } else {
g.enc.rect(bounds, false) g.enc.rect(bounds, false)
} }
@@ -419,7 +421,8 @@ func (g *compute) encodeClipStack(clip, bounds f32.Rectangle, p *pathOp) int {
// encodePath takes a Path encoded with quadSplitter and encode it for elements.comp. // encodePath takes a Path encoded with quadSplitter and encode it for elements.comp.
// This is certainly wasteful, but minimizes implementation differences to the old // This is certainly wasteful, but minimizes implementation differences to the old
// renderer. // renderer.
func (g *compute) encodePath(off f32.Point, p []byte) { func encodePath(p []byte) encoder {
var enc encoder
for len(p) > 0 { for len(p) > 0 {
// p contains quadratic curves encoded in vertex structs. // p contains quadratic curves encoded in vertex structs.
vertex := p[:vertStride] vertex := p[:vertStride]
@@ -436,12 +439,13 @@ func (g *compute) encodePath(off f32.Point, p []byte) {
math.Float32frombits(bo.Uint32(vertex[24:])), math.Float32frombits(bo.Uint32(vertex[24:])),
math.Float32frombits(bo.Uint32(vertex[28:])), math.Float32frombits(bo.Uint32(vertex[28:])),
) )
g.enc.quad(from.Add(off), ctrl.Add(off), to.Add(off), false) enc.quad(from, ctrl, to, false)
// The vertex is duplicated 4 times, one for each corner of quads drawn // The vertex is duplicated 4 times, one for each corner of quads drawn
// by the old renderer. // by the old renderer.
p = p[vertStride*4:] p = p[vertStride*4:]
} }
return enc
} }
func (g *compute) render(tileDims image.Point) error { func (g *compute) render(tileDims image.Point) error {
@@ -696,6 +700,12 @@ func (e *encoder) numElements() int {
return len(e.scene) / sceneElemSize return len(e.scene) / sceneElemSize
} }
func (e *encoder) append(e2 encoder) {
e.scene = append(e.scene, e2.scene...)
e.npath += e2.npath
e.npathseg += e2.npathseg
}
func (e *encoder) transform(m f32.Affine2D) { func (e *encoder) transform(m f32.Affine2D) {
sx, hx, ox, hy, sy, oy := m.Elems() sx, hx, ox, hy, sy, oy := m.Elems()
cmd := make([]byte, sceneElemSize) cmd := make([]byte, sceneElemSize)
+5 -6
View File
@@ -824,15 +824,14 @@ func (d *drawOps) collect(ctx backend.Device, cache *resourceCache, root *op.Ops
for _, p := range d.pathOps { for _, p := range d.pathOps {
if v, exists := d.pathCache.get(p.pathKey); !exists || v.data.data == nil { if v, exists := d.pathCache.get(p.pathKey); !exists || v.data.data == nil {
data := buildPath(ctx, p.pathVerts) data := buildPath(ctx, p.pathVerts)
var pathVerts []byte var computePath encoder
if d.retainPathData { if d.retainPathData {
pathVerts = make([]byte, len(p.pathVerts)) computePath = encodePath(p.pathVerts)
copy(pathVerts, p.pathVerts)
} }
d.pathCache.put(p.pathKey, opCacheValue{ d.pathCache.put(p.pathKey, opCacheValue{
data: data, data: data,
bounds: p.bounds, bounds: p.bounds,
cpuData: pathVerts, computePath: computePath,
}) })
} }
p.pathVerts = nil p.pathVerts = nil