gamnit: cache sprite GPU index, as index_of is very costly
authorAlexis Laferrière <alexis.laf@xymus.net>
Fri, 23 Jun 2017 02:28:39 +0000 (22:28 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Fri, 23 Jun 2017 12:30:21 +0000 (08:30 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/gamnit/flat.nit

index b278029..f9710ab 100644 (file)
@@ -253,6 +253,9 @@ class Sprite
        # Current context to which `self` was sorted
        private var context: nullable SpriteContext = null
 
+       # Index in `context`
+       private var context_index: Int = -1
+
        # Current context to which `self` belongs
        private var sprite_set: nullable SpriteSet = null
 end
@@ -768,7 +771,7 @@ private class SpriteContext
        var usage: GLBufferUsage
 
        # Sprites drawn by this context
-       var sprites = new GroupedArray[Sprite]
+       var sprites = new GroupedSprites
 
        # Sprites to update since last `draw`
        var sprites_to_update = new Set[Sprite]
@@ -878,8 +881,11 @@ private class SpriteContext
        # Update GPU data of `sprite`
        fun update_sprite(sprite: Sprite)
        do
-               var sprite_index = sprites.index_of(sprite)
-               if sprite_index == -1 then return
+               var context = sprite.context
+               if context != self then return
+
+               var sprite_index = sprite.context_index
+               assert sprite_index != -1
 
                # Vertices data
 
@@ -1169,9 +1175,6 @@ private class GroupedArray[E]
        # Number of item slots in the array
        fun capacity: Int do return items.length
 
-       # Index of `item`
-       fun index_of(item: E): Int do return items.index_of(item)
-
        # List of available slots
        var available = new MinHeap[Int].default
 
@@ -1181,8 +1184,8 @@ private class GroupedArray[E]
        # Index of the spots after filled chunks
        var ends = new List[Int]
 
-       # Add `item` to the first available slot
-       fun add(item: E)
+       # Add `item` to the first available slot and return its index
+       fun add(item: E): Int
        do
                length += 1
 
@@ -1207,7 +1210,7 @@ private class GroupedArray[E]
                                # at end of first chunk
                                ends.first += 1
                        end
-                       return
+                       return i
                end
 
                items.add item
@@ -1215,13 +1218,20 @@ private class GroupedArray[E]
                        starts.add 0
                        ends.add 1
                else ends.last += 1
+               return ends.last - 1
        end
 
        # Remove the first instance of `item`
        fun remove(item: E)
        do
-               var i = items.index_of(item)
-               assert i != -1
+               var index = items.index_of(item)
+               remove_at(item, index)
+       end
+
+       # Remove `item` at `index`
+       fun remove_at(item: E, index: Int)
+       do
+               var i = index
                length -= 1
                items[i] = null
 
@@ -1296,6 +1306,7 @@ private class GroupedArray[E]
                while max > 0 and (starts.length > 1 or starts.first != 0) do
                        var i = ends.last - 1
                        var e = items[i]
+                       assert e != null
                        remove e
                        add e
                        moved.add e
@@ -1328,6 +1339,20 @@ private class GroupedArray[E]
        end
 end
 
+# Optimized `GroupedArray` to use `Sprite::context_index` and avoid using `index_of`
+private class GroupedSprites
+       super GroupedArray[Sprite]
+
+       redef fun add(item)
+       do
+               var index = super
+               item.context_index = index
+               return index
+       end
+
+       redef fun remove(item) do remove_at(item, item.context_index)
+end
+
 redef class GLfloatArray
        private fun fill_from_matrix(matrix: Matrix, dst_offset: nullable Int)
        do