internal/atlas: reland: clarify the logic when to update usedAsDestination

This is a reland of 2c9f5d9dad.

As the name is `usedAsDestination`, this should be updated whenever
the image is used as a rendering destination.

Confirmed that this change didn't cause a performance regression
like #2586.

Updates #2586
Updates #2676
This commit is contained in:
Hajime Hoshi 2023-08-06 15:39:26 +09:00
parent dcc8794883
commit 0433dfac99
2 changed files with 21 additions and 4 deletions

View File

@ -90,6 +90,10 @@ func putImagesOnSourceBackend(graphicsDriver graphicsdriver.Graphics) error {
for k := range imagesToPutOnSourceBackend { for k := range imagesToPutOnSourceBackend {
delete(imagesToPutOnSourceBackend, k) delete(imagesToPutOnSourceBackend, k)
} }
for i := range imagesBackendJustCreated {
delete(imagesBackendJustCreated, i)
}
return nil return nil
} }
@ -136,6 +140,8 @@ var (
imagesUsedAsDestination = map[*Image]struct{}{} imagesUsedAsDestination = map[*Image]struct{}{}
imagesBackendJustCreated = map[*Image]struct{}{}
deferred []func() deferred []func()
// deferredM is a mutex for the slice operations. This must not be used for other usages. // deferredM is a mutex for the slice operations. This must not be used for other usages.
@ -238,15 +244,21 @@ func (i *Image) ensureIsolatedFromSource(backends []*backend) {
bs = append(bs, b) bs = append(bs, b)
} }
i.allocate(bs, false) i.allocate(bs, false)
imagesBackendJustCreated[i] = struct{}{}
return return
} }
// imagesUsedAsDestination affects the counter usedAsDestination.
// The larger this counter is, the harder it is for the image to be transferred to the source backend.
// This counter is not updated when the backend is created in this frame.
if _, ok := imagesBackendJustCreated[i]; !ok {
imagesUsedAsDestination[i] = struct{}{}
}
if !i.isOnAtlas() { if !i.isOnAtlas() {
return return
} }
imagesUsedAsDestination[i] = struct{}{}
// Check if i has the same backend as the given backends. // Check if i has the same backend as the given backends.
var needsIsolation bool var needsIsolation bool
for _, b := range backends { for _, b := range backends {

View File

@ -676,8 +676,13 @@ func TestImageIsNotReputOnSourceBackendWithoutUsingAsSource(t *testing.T) {
Height: size, Height: size,
} }
// Use src2 as a rendering target, and make src2 an independent image. // Use src2 as a rendering target, and make src2 on a destination backend.
//
// Call DrawTriangles multiple times.
// The number of DrawTriangles doesn't matter as long as these are called in one frame.
for i := 0; i < 2; i++ {
src2.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false) src2.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
}
if got, want := src2.IsOnSourceBackendForTesting(), false; got != want { if got, want := src2.IsOnSourceBackendForTesting(), false; got != want {
t.Errorf("got: %v, want: %v", got, want) t.Errorf("got: %v, want: %v", got, want)
} }