From 49365dbcc5a8a6ad5d5fa631dab456fb18d6b9de Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sun, 16 Feb 2020 17:39:26 +0100 Subject: [PATCH] gpu: allocate path draw index buffer once Before this change, the index buffer would start empty and grow up to the maximum size (128kb). It would never shrink. We're about to tighten the GPU buffer API to be immutable for performance and to better match Direct3D, so allocate the index buffer once at startup, and limit it to a reasonable size. Signed-off-by: Elias Naur --- gpu/path.go | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/gpu/path.go b/gpu/path.go index 46223583..28e904f4 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -38,7 +38,6 @@ type coverer struct { type stenciler struct { ctx Backend defFBO Framebuffer - indexBufQuads int prog Program iprog Program fbos fboSet @@ -70,6 +69,11 @@ var ( intersectAttribs = []string{"pos", "uv"} ) +const ( + // Number of path quads per draw batch. + pathBatchSize = 10000 +) + const ( attribPathCorner = 0 attribPathMaxY = 1 @@ -128,6 +132,19 @@ func newStenciler(ctx Backend) *stenciler { } coverLoc := iprog.UniformFor("cover") iprog.Uniform1i(coverLoc, 0) + // Allocate a suitably large index buffer for drawing paths. + indices := make([]uint16, pathBatchSize*6) + for i := 0; i < pathBatchSize; i++ { + i := uint16(i) + indices[i*6+0] = i*4 + 0 + indices[i*6+1] = i*4 + 1 + indices[i*6+2] = i*4 + 2 + indices[i*6+3] = i*4 + 2 + indices[i*6+4] = i*4 + 1 + indices[i*6+5] = i*4 + 3 + } + indexBuf := ctx.NewBuffer(BufferTypeIndices) + indexBuf.Upload(BufferUsageStaticDraw, gunsafe.BytesView(indices)) return &stenciler{ ctx: ctx, defFBO: defFBO, @@ -138,7 +155,7 @@ func newStenciler(ctx Backend) *stenciler { uPathOffset: prog.UniformFor("pathOffset"), uIntersectUVScale: iprog.UniformFor("uvScale"), uIntersectUVOffset: iprog.UniformFor("uvOffset"), - indexBuf: ctx.NewBuffer(BufferTypeIndices), + indexBuf: indexBuf, } } @@ -274,24 +291,9 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima nquads := data.ncurves / 4 for start < nquads { batch := nquads - start - if max := int(^uint16(0)) / 6; batch > max { + if max := pathBatchSize; batch > max { batch = max } - // Enlarge VBO if necessary. - if batch > s.indexBufQuads { - indices := make([]uint16, batch*6) - for i := 0; i < batch; i++ { - i := uint16(i) - indices[i*6+0] = i*4 + 0 - indices[i*6+1] = i*4 + 1 - indices[i*6+2] = i*4 + 2 - indices[i*6+3] = i*4 + 2 - indices[i*6+4] = i*4 + 1 - indices[i*6+5] = i*4 + 3 - } - s.indexBuf.Upload(BufferUsageStaticDraw, gunsafe.BytesView(indices)) - s.indexBufQuads = batch - } off := path.VertStride * start * 4 s.ctx.SetupVertexArray(attribPathCorner, 2, DataTypeShort, path.VertStride, off+int(unsafe.Offsetof((*(*path.Vertex)(nil)).CornerX))) s.ctx.SetupVertexArray(attribPathMaxY, 1, DataTypeFloat, path.VertStride, off+int(unsafe.Offsetof((*(*path.Vertex)(nil)).MaxY)))