internal/atlas: replace a map with a set with a slice

Updates #2601
This commit is contained in:
Hajime Hoshi 2023-08-19 14:57:55 +09:00
parent 3b2251a858
commit a9d9143d90
2 changed files with 66 additions and 11 deletions

View File

@ -66,16 +66,16 @@ const baseCountToPutOnSourceBackend = 10
func putImagesOnSourceBackend(graphicsDriver graphicsdriver.Graphics) {
// The counter usedAsDestinationCount is updated at most once per frame (#2676).
for i := range imagesUsedAsDestination {
imagesUsedAsDestination.forEach(func(i *Image) {
// This counter is not updated when the backend is created in this frame.
if !i.backendCreatedInThisFrame && i.usedAsDestinationCount < math.MaxInt {
i.usedAsDestinationCount++
}
i.backendCreatedInThisFrame = false
delete(imagesUsedAsDestination, i)
}
})
imagesUsedAsDestination.clear()
for i := range imagesToPutOnSourceBackend {
imagesToPutOnSourceBackend.forEach(func(i *Image) {
if i.usedAsSourceCount < math.MaxInt {
i.usedAsSourceCount++
}
@ -83,8 +83,8 @@ func putImagesOnSourceBackend(graphicsDriver graphicsdriver.Graphics) {
i.putOnSourceBackend(graphicsDriver)
i.usedAsSourceCount = 0
}
delete(imagesToPutOnSourceBackend, i)
}
})
imagesToPutOnSourceBackend.clear()
}
type backend struct {
@ -126,9 +126,9 @@ var (
// theBackends is a set of atlases.
theBackends []*backend
imagesToPutOnSourceBackend = map[*Image]struct{}{}
imagesToPutOnSourceBackend smallImageSet
imagesUsedAsDestination = map[*Image]struct{}{}
imagesUsedAsDestination smallImageSet
deferred []func()
@ -213,7 +213,7 @@ func (i *Image) isOnSourceBackend() bool {
func (i *Image) resetUsedAsSourceCount() {
i.usedAsSourceCount = 0
delete(imagesToPutOnSourceBackend, i)
imagesToPutOnSourceBackend.remove(i)
}
func (i *Image) paddingSize() int {
@ -228,7 +228,7 @@ func (i *Image) ensureIsolatedFromSource(backends []*backend) {
// imagesUsedAsDestination affects the counter usedAsDestination.
// The larger this counter is, the harder it is for the image to be transferred to the source backend.
imagesUsedAsDestination[i] = struct{}{}
imagesUsedAsDestination.add(i)
if i.backend == nil {
// `sourceInThisFrame` of `backends` should be true, so `backends` should be in `bs`.
@ -453,7 +453,7 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
}
if !src.isOnSourceBackend() && src.canBePutOnAtlas() {
// src might already registered, but assigning it again is not harmful.
imagesToPutOnSourceBackend[src] = struct{}{}
imagesToPutOnSourceBackend.add(src)
}
}
}

55
internal/atlas/set.go Normal file
View File

@ -0,0 +1,55 @@
// Copyright 2023 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package atlas
// smallImageSet is a set for images.
// smallImageSet uses a slice assuming the number of items is not so big (smaller than 100 or so).
// If the number of items is big, a map might be better than a slice.
type smallImageSet struct {
s []*Image
}
func (s *smallImageSet) add(image *Image) {
for _, img := range s.s {
if img == image {
return
}
}
s.s = append(s.s, image)
}
func (s *smallImageSet) remove(image *Image) {
for i, img := range s.s {
if img == image {
copy(s.s[i:], s.s[i+1:])
s.s[len(s.s)-1] = nil
s.s = s.s[:len(s.s)-1]
return
}
}
}
func (s *smallImageSet) forEach(f func(*Image)) {
for _, img := range s.s {
f(img)
}
}
func (s *smallImageSet) clear() {
for i := range s.s {
s.s[i] = nil
}
s.s = s.s[:0]
}