mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
internal/shareable: Use an exponential way to determine the image sharing
When an image was used in both ways source and destination, Ebiten worked ineffectively since Ebiten tried to make the image on a texture atlas after the image was used as a source for a while, which tried to create a new internal texture every time. This fix mitigates this issue by using an exponential way to determine whether the image should be on a texture atlas again or not, so that an image often used as a destination will require much longer time to become on a texture atlas again. Updates #1464
This commit is contained in:
parent
2c0108e178
commit
df3e74533b
@ -15,7 +15,7 @@
|
|||||||
package shareable
|
package shareable
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MaxCountForShare = maxCountForShare
|
BaseCountForShare = baseCountForShare
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeImagesSharedForTesting() error {
|
func MakeImagesSharedForTesting() error {
|
||||||
|
@ -66,13 +66,21 @@ func resolveDeferred() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxCountForShare represents the time duration when the image can become shared.
|
// baseCountForShare represents the base time duration when the image can become shared.
|
||||||
const maxCountForShare = 10
|
// Actual time duration is increased in an exponential way for each usages as a rendering target.
|
||||||
|
const baseCountForShare = 10
|
||||||
|
|
||||||
|
func min(a, b uint) uint {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func makeImagesShared() error {
|
func makeImagesShared() error {
|
||||||
for i := range imagesToMakeShared {
|
for i := range imagesToMakeShared {
|
||||||
i.usedAsSourceCount++
|
i.usedAsSourceCount++
|
||||||
if i.usedAsSourceCount >= maxCountForShare {
|
if i.usedAsSourceCount >= baseCountForShare*(1<<min(uint(i.notSharedCount), 31)) {
|
||||||
if err := i.makeShared(); err != nil {
|
if err := i.makeShared(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -176,6 +184,10 @@ type Image struct {
|
|||||||
//
|
//
|
||||||
// ReplacePixels doesn't affect this value since ReplacePixels can be done on shared images.
|
// ReplacePixels doesn't affect this value since ReplacePixels can be done on shared images.
|
||||||
usedAsSourceCount int
|
usedAsSourceCount int
|
||||||
|
|
||||||
|
// notSharedCount represents how many times the image on a texture atlas is changed into an isolated image.
|
||||||
|
// notSharedCount affects the calculation when to make the image onto a texture atlas again.
|
||||||
|
notSharedCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) moveTo(dst *Image) {
|
func (i *Image) moveTo(dst *Image) {
|
||||||
@ -240,6 +252,8 @@ func (i *Image) ensureNotShared() {
|
|||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
restorable: newImg,
|
restorable: newImg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.notSharedCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) makeShared() error {
|
func (i *Image) makeShared() error {
|
||||||
|
@ -185,7 +185,9 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img1 as a render source.
|
// Use img1 as a render source.
|
||||||
for i := 0; i < MaxCountForShare; i++ {
|
// Use the doubled count since img1 was on a texture atlas and became an isolated image once.
|
||||||
|
// Then, img1 requires longer time to recover to be on a textur atlas again.
|
||||||
|
for i := 0; i < BaseCountForShare*2; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -247,7 +249,8 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img1 as a render source, but call ReplacePixels.
|
// Use img1 as a render source, but call ReplacePixels.
|
||||||
for i := 0; i < MaxCountForShare; i++ {
|
// Now use 4x count as img1 became an isolated image again.
|
||||||
|
for i := 0; i < BaseCountForShare*4; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -268,7 +271,7 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img3 as a render source. As img3 is volatile, img3 never uses a shared texture.
|
// Use img3 as a render source. As img3 is volatile, img3 never uses a shared texture.
|
||||||
for i := 0; i < MaxCountForShare*2; i++ {
|
for i := 0; i < BaseCountForShare*2; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -562,7 +565,7 @@ func TestDisposedAndReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use src as a render source.
|
// Use src as a render source.
|
||||||
for i := 0; i < MaxCountForShare/2; i++ {
|
for i := 0; i < BaseCountForShare/2; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -613,7 +616,7 @@ func TestImageIsNotResharedWithoutUsingAsSource(t *testing.T) {
|
|||||||
|
|
||||||
// Update the count without using src2 as a rendering source.
|
// Update the count without using src2 as a rendering source.
|
||||||
// This should not affect whether src2 is on a shareable image or not.
|
// This should not affect whether src2 is on a shareable image or not.
|
||||||
for i := 0; i < MaxCountForShare; i++ {
|
for i := 0; i < BaseCountForShare; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -623,7 +626,7 @@ func TestImageIsNotResharedWithoutUsingAsSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the count with using src2 as a rendering source.
|
// Update the count with using src2 as a rendering source.
|
||||||
for i := 0; i < MaxCountForShare; i++ {
|
for i := 0; i < BaseCountForShare; i++ {
|
||||||
if err := MakeImagesSharedForTesting(); err != nil {
|
if err := MakeImagesSharedForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user