shareable: Update page sizes dynamically

Also, all the images cannot use the shareable backends before the
game starts, but it is expected that read-only images will use
shareable backends later.

Fixes #879
This commit is contained in:
Hajime Hoshi 2019-06-22 20:17:52 +09:00
parent f48a72a43e
commit 7a399c1b82
3 changed files with 56 additions and 12 deletions

View File

@ -145,6 +145,13 @@ func (p *Page) Size() int {
return p.size return p.size
} }
func (p *Page) SetMaxSize(size int) {
if p.maxSize > size {
panic("packing: maxSize cannot be decreased")
}
p.maxSize = size
}
func (p *Page) Alloc(width, height int) *Node { func (p *Page) Alloc(width, height int) *Node {
if width <= 0 || height <= 0 { if width <= 0 || height <= 0 {
panic("packing: width and height must > 0") panic("packing: width and height must > 0")

View File

@ -21,28 +21,58 @@ import (
"sync" "sync"
"github.com/hajimehoshi/ebiten/internal/affine" "github.com/hajimehoshi/ebiten/internal/affine"
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/hooks" "github.com/hajimehoshi/ebiten/internal/hooks"
"github.com/hajimehoshi/ebiten/internal/packing" "github.com/hajimehoshi/ebiten/internal/packing"
"github.com/hajimehoshi/ebiten/internal/restorable" "github.com/hajimehoshi/ebiten/internal/restorable"
) )
var graphicsDriver driver.Graphics
func SetGraphicsDriver(graphics driver.Graphics) {
graphicsDriver = graphics
}
func init() { func init() {
var once sync.Once
hooks.AppendHookOnBeforeUpdate(func() error { hooks.AppendHookOnBeforeUpdate(func() error {
backendsM.Lock()
defer backendsM.Unlock()
once.Do(func() {
if len(theBackends) != 0 {
panic("shareable: all the images must be not-shared before the game starts")
}
shareable = true
updateSizeLimit()
})
makeImagesShared() makeImagesShared()
return nil return nil
}) })
} }
var (
minSize = 512
maxSize = 512
)
func updateSizeLimit() {
if !graphicsDriver.HasHighPrecisionFloat() {
return
}
// Before the game starts, the texture sizes are set in a very conservative way.
// If the graphics driver supports high precision float values, allow bigger texture sizes.
minSize = 1024
maxSize = 4096
}
// MaxCountForShare represents the time duration when the image can become shared. // MaxCountForShare represents the time duration when the image can become shared.
// //
// This value is expoted for testing. // This value is expoted for testing.
const MaxCountForShare = 10 const MaxCountForShare = 10
func makeImagesShared() { func makeImagesShared() {
backendsM.Lock()
defer backendsM.Unlock()
for i := range imagesToMakeShared { for i := range imagesToMakeShared {
i.nonUpdatedCount++ i.nonUpdatedCount++
if i.nonUpdatedCount >= MaxCountForShare { if i.nonUpdatedCount >= MaxCountForShare {
@ -56,14 +86,6 @@ func MakeImagesSharedForTesting() {
makeImagesShared() makeImagesShared()
} }
// TODO: These values should be 512/512 on some machines that don't have highp (#879).
// In this case, Ebiten needs to care the number of drawing commands since small shareable images would increase the
// number.
const (
initSize = 1024
maxSize = 4096
)
type backend struct { type backend struct {
restorable *restorable.Image restorable *restorable.Image
@ -119,8 +141,19 @@ var (
theBackends = []*backend{} theBackends = []*backend{}
imagesToMakeShared = map[*Image]struct{}{} imagesToMakeShared = map[*Image]struct{}{}
shareable = false
) )
// isShareable reports whether the new allocation can use the shareable backends.
//
// isShareable retruns false before the graphics driver is available.
// After the graphics driver is available, read-only images will be automatically on the shareable backends by
// makeShared().
func isShareable() bool {
return shareable
}
type Image struct { type Image struct {
width int width int
height int height int
@ -405,6 +438,9 @@ func NewImage(width, height int) *Image {
} }
func (i *Image) shareable() bool { func (i *Image) shareable() bool {
if !isShareable() {
return false
}
if i.neverShared { if i.neverShared {
return false return false
} }
@ -432,7 +468,7 @@ func (i *Image) allocate(shareable bool) {
return return
} }
} }
size := initSize size := minSize
for i.width > size || i.height > size { for i.width > size || i.height > size {
if size == maxSize { if size == maxSize {
panic(fmt.Sprintf("shareable: the image being shared is too big: width: %d, height: %d", i.width, i.height)) panic(fmt.Sprintf("shareable: the image being shared is too big: width: %d, height: %d", i.width, i.height))

View File

@ -26,6 +26,7 @@ import (
) )
func init() { func init() {
shareable.SetGraphicsDriver(graphicsDriver())
graphicscommand.SetGraphicsDriver(graphicsDriver()) graphicscommand.SetGraphicsDriver(graphicsDriver())
} }