forked from joejulian/gio
gpu: support rectangular atlas packers
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+16
-14
@@ -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
|
||||
|
||||
+3
-3
@@ -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++
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user