diff --git a/gpu/compute.go b/gpu/compute.go index d630818f..a27ca675 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -411,7 +411,7 @@ func newCompute(ctx driver.Device) (*compute, error) { } // Large enough for reasonable fill sizes, yet still spannable by the compute programs. - g.output.packer.maxDim = 4096 + g.output.packer.maxDims = image.Pt(4096, 4096) copyVert, copyFrag, err := newShaders(ctx, gio.Shader_copy_vert, gio.Shader_copy_frag) if err != nil { g.Release() @@ -863,9 +863,10 @@ restart: // after clearing existing maps. reclaimed = true } else { - m.packer.maxDim += 256 + m.packer.maxDims.X += 256 + m.packer.maxDims.Y += 256 resize = true - if m.packer.maxDim > g.maxTextureDim { + if m.packer.maxDims.X > g.maxTextureDim { return errors.New("compute: no space left in material atlas") } } @@ -896,7 +897,7 @@ restart: if len(m.quads) == 0 { return nil } - texSize := m.packer.maxDim + texSize := m.packer.maxDims if resize { if m.fbo != nil { m.fbo.Release() @@ -907,7 +908,7 @@ restart: m.tex = nil } m.cpuTex.Free() - handle, err := g.ctx.NewTexture(driver.TextureFormatRGBA8, texSize, texSize, + handle, err := g.ctx.NewTexture(driver.TextureFormatRGBA8, texSize.X, texSize.Y, driver.FilterNearest, driver.FilterNearest, driver.BufferBindingShaderStorageRead|driver.BufferBindingFramebuffer) if err != nil { @@ -921,12 +922,12 @@ restart: m.tex = handle m.fbo = fbo if g.useCPU { - m.cpuTex = cpu.NewImageRGBA(texSize, texSize) + m.cpuTex = cpu.NewImageRGBA(texSize.X, texSize.Y) } } // Transform to clip space: [-1, -1] - [1, 1] and flip Y-axis to cancel the implied transformation // between framebuffer and texture space. - m.vert.uniforms.scale = [2]float32{2 / float32(texSize), -2 / float32(texSize)} + m.vert.uniforms.scale = [2]float32{2 / float32(texSize.X), -2 / float32(texSize.Y)} m.vert.uniforms.pos = [2]float32{-1, +1} m.vert.buf.Upload(byteslice.Struct(m.vert.uniforms)) g.ctx.BindVertexUniforms(m.vert.buf) @@ -941,7 +942,7 @@ restart: d.Action = driver.LoadActionClear } g.ctx.BindFramebuffer(m.fbo, d) - g.ctx.Viewport(0, 0, texSize, texSize) + g.ctx.Viewport(0, 0, texSize.X, texSize.Y) g.ctx.BindPipeline(m.pipeline) g.ctx.BindVertexBuffer(m.buffer.buffer, 0) g.ctx.DrawArrays(driver.DrawModeTriangles, 0, len(m.quads)) @@ -975,9 +976,10 @@ restart: // after clearing existing maps. reclaimed = true } else { - a.packer.maxDim += 256 + a.packer.maxDims.X += 256 + a.packer.maxDims.Y += 256 resize = true - if a.packer.maxDim > g.maxTextureDim { + if a.packer.maxDims.X > g.maxTextureDim { return errors.New("compute: no space left in image atlas") } } @@ -1004,12 +1006,12 @@ restart: a.tex.Release() a.tex = nil } - sz := a.packer.maxDim + sz := a.packer.maxDims format := driver.TextureFormatSRGBA if !g.srgb { format = driver.TextureFormatRGBA8 } - handle, err := g.ctx.NewTexture(format, sz, sz, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture) + handle, err := g.ctx.NewTexture(format, sz.X, sz.Y, driver.FilterLinear, driver.FilterLinear, driver.BufferBindingTexture) if err != nil { return fmt.Errorf("compute: failed to create image atlas: %v", err) } @@ -1066,7 +1068,7 @@ func (g *compute) materialQuad(M f32.Affine2D, img imageOpData, uvPos image.Poin bounds := boundRectF(boundsf) uvPosf := layout.FPt(uvPos) - atlasScale := 1 / float32(g.images.packer.maxDim) + atlasScale := 1 / float32(g.images.packer.maxDims.X) uvBounds := f32.Rectangle{ Min: uvPosf.Mul(atlasScale), Max: uvPosf.Add(imgSize).Mul(atlasScale), @@ -1264,7 +1266,7 @@ func (g *compute) downloadMaterials() { m.scratch = make([]byte, n) } copyFBO.ReadPixels(r, m.scratch) - stride := m.packer.maxDim * 4 + stride := m.packer.maxDims.X * 4 col := r.Min.X * 4 row := stride * r.Min.Y off := col + row diff --git a/gpu/gpu.go b/gpu/gpu.go index f3bc42fb..3c6849b3 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -505,8 +505,8 @@ func newRenderer(ctx driver.Device) *renderer { maxDim = cap } - r.packer.maxDim = maxDim - r.intersections.maxDim = maxDim + r.packer.maxDims = image.Pt(maxDim, maxDim) + r.intersections.maxDims = image.Pt(maxDim, maxDim) return r } @@ -774,7 +774,7 @@ func (r *renderer) packStencils(pops *[]*pathOp) { if !ok { // The clip area is at most the entire screen. Hopefully no // screen is larger than GL_MAX_TEXTURE_SIZE. - panic(fmt.Errorf("clip area %v is larger than maximum texture size %dx%d", p.clip, r.packer.maxDim, r.packer.maxDim)) + panic(fmt.Errorf("clip area %v is larger than maximum texture size %v", p.clip, r.packer.maxDims)) } p.place = place i++ diff --git a/gpu/pack.go b/gpu/pack.go index bfa77a1a..3f8c9250 100644 --- a/gpu/pack.go +++ b/gpu/pack.go @@ -9,8 +9,8 @@ import ( // packer packs a set of many smaller rectangles into // much fewer larger atlases. type packer struct { - maxDim int - spaces []image.Rectangle + maxDims image.Point + spaces []image.Rectangle sizes []image.Point pos image.Point @@ -49,7 +49,7 @@ func (p *packer) tryAdd(s image.Point) (placement, bool) { var ( bestIdx = -1 bestSpace image.Rectangle - bestSize = image.Pt(p.maxDim, p.maxDim) + bestSize = p.maxDims ) // Go backwards to prioritize smaller spaces. for i, space := range p.spaces { @@ -61,13 +61,13 @@ func (p *packer) tryAdd(s image.Point) (placement, bool) { idx := len(p.sizes) - 1 size := p.sizes[idx] if x := space.Min.X + s.X; x > size.X { - if x > p.maxDim { + if x > p.maxDims.X { continue } size.X = x } if y := space.Min.Y + s.Y; y > size.Y { - if y > p.maxDim { + if y > p.maxDims.Y { continue } size.Y = y