From bb52139e173d75dcdb05c55e4cd3a57860315486 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 28 Jun 2024 06:08:03 -0400 Subject: [PATCH] 2 ms improvement from lru optimizations --- code/font/VEFontCache/LRU.odin | 49 +++++++++++++++++++++------------ code/font/VEFontCache/draw.odin | 49 +++++++++++++++------------------ code/font/VEFontCache/misc.odin | 16 +++++++---- 3 files changed, 65 insertions(+), 49 deletions(-) diff --git a/code/font/VEFontCache/LRU.odin b/code/font/VEFontCache/LRU.odin index 441bc97..ea97a6b 100644 --- a/code/font/VEFontCache/LRU.odin +++ b/code/font/VEFontCache/LRU.odin @@ -120,6 +120,23 @@ pool_list_erase :: proc( pool : ^PoolList, iter : PoolListIter ) } } +pool_list_move_to_front :: #force_inline proc( pool : ^PoolList, iter : PoolListIter ) +{ + using pool + + if front == iter do return + + item := & items[iter] + if item.prev != -1 do items[ item.prev ].next = item.next + if item.next != -1 do items[ item.next ].prev = item.prev + if back == iter do back = item.prev + + item.prev = -1 + item.next = front + items[ front ].prev = iter + front = iter +} + pool_list_peek_back :: #force_inline proc ( pool : ^PoolList ) -> PoolListValue { assert( pool.back != - 1 ) value := pool.items[ pool.back ].value @@ -180,13 +197,12 @@ LRU_find :: #force_inline proc "contextless" ( cache : ^LRU_Cache, key : u64, mu return link, success } -LRU_get :: #force_inline proc( cache : ^LRU_Cache, key : u64 ) -> i32 { - iter, success := LRU_find( cache, key ) - if success == false { - return -1 +LRU_get :: #force_inline proc( cache: ^LRU_Cache, key : u64 ) -> i32 { + if link, ok := &cache.table[ key ]; ok { + pool_list_move_to_front(&cache.key_queue, link.ptr) + return link.value } - LRU_refresh( cache, key ) - return iter.value + return -1 } LRU_get_next_evicted :: #force_inline proc ( cache : ^LRU_Cache ) -> u64 @@ -206,26 +222,25 @@ LRU_peek :: #force_inline proc ( cache : ^LRU_Cache, key : u64, must_find := fal return iter.value } -LRU_put :: #force_inline proc ( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64 +LRU_put :: #force_inline proc( cache : ^LRU_Cache, key : u64, value : i32 ) -> u64 { - iter, success := cache.table[key] - if success { - LRU_refresh( cache, key ) - iter.value = value + if link, ok := & cache.table[ key ]; ok { + pool_list_move_to_front( & cache.key_queue, link.ptr ) + link.value = value return key } evict := key if cache.key_queue.size >= cache.capacity { - evict = pool_list_pop_back( & cache.key_queue ) - delete_key( & cache.table, evict ) + evict = pool_list_pop_back(&cache.key_queue) + delete_key(&cache.table, evict) cache.num -= 1 } - pool_list_push_front( & cache.key_queue, key ) - cache.table[key] = LRU_Link { - value = value, - ptr = cache.key_queue.front + pool_list_push_front(&cache.key_queue, key) + cache.table[key] = LRU_Link{ + value = value, + ptr = cache.key_queue.front, } cache.num += 1 return evict diff --git a/code/font/VEFontCache/draw.odin b/code/font/VEFontCache/draw.odin index 3508c14..3f52eb9 100644 --- a/code/font/VEFontCache/draw.odin +++ b/code/font/VEFontCache/draw.odin @@ -699,39 +699,34 @@ merge_draw_list :: proc( dst, src : ^DrawList ) } } -optimize_draw_list :: proc( draw_list : ^DrawList, call_offset : int ) -{ +optimize_draw_list :: proc(draw_list: ^DrawList, call_offset: int) { // profile(#procedure) - assert( draw_list != nil ) + assert(draw_list != nil) - write_index : int = call_offset - for index : int = 1 + call_offset; index < len(draw_list.calls); index += 1 + can_merge_draw_calls :: #force_inline proc "contextless" ( a, b : ^DrawCall ) -> bool { + result := \ + a.pass == b.pass && + a.end_index == b.start_index && + a.region == b.region && + a.colour == b.colour && + ! b.clear_before_draw + return result + } + + write_index := call_offset + for read_index := call_offset + 1; read_index < len(draw_list.calls); read_index += 1 { - assert( write_index <= index ) - draw_0 := & draw_list.calls[ write_index ] - draw_1 := & draw_list.calls[ index ] + draw_current := & draw_list.calls[write_index] + draw_next := & draw_list.calls[read_index] - merge : b32 = true - if draw_0.pass != draw_1.pass do merge = false - if draw_0.end_index != draw_1.start_index do merge = false - if draw_0.region != draw_1.region do merge = false - if draw_1.clear_before_draw do merge = false - if draw_0.colour != draw_1.colour do merge = false - - if merge - { - // logf("merging %v : %v %v", draw_0.pass, write_index, index ) - draw_0.end_index = draw_1.end_index - draw_1.start_index = 0 - draw_1.end_index = 0 + if can_merge_draw_calls(draw_current, draw_next) { + draw_current.end_index = draw_next.end_index } - else - { - // logf("can't merge %v : %v %v", draw_0.pass, write_index, index ) + else { + // Move to the next write position and copy the draw call write_index += 1 - if write_index != index { - draw_2 := & draw_list.calls[ write_index ] - draw_2^ = draw_1^ + if write_index != read_index { + draw_list.calls[write_index] = (draw_next^) } } } diff --git a/code/font/VEFontCache/misc.odin b/code/font/VEFontCache/misc.odin index 733ebdc..3ca9c12 100644 --- a/code/font/VEFontCache/misc.odin +++ b/code/font/VEFontCache/misc.odin @@ -116,7 +116,7 @@ reset_batch_codepoint_state :: #force_inline proc( ctx : ^Context ) { } screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) { - when true + if true { pos_64 := vec2_64_from_vec2(position^) scale_64 := vec2_64_from_vec2(scale^) @@ -130,14 +130,20 @@ screenspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2 } else { + pos := position^ + scale_32 := scale^ + quotient : Vec2 = 1.0 / size - (position^) *= quotient * 2.0 - 1.0 - (scale^) *= quotient * 2.0 + pos = pos * quotient * 2.0 - 1.0 + scale_32 = scale_32 * quotient * 2.0 + + (position^) = pos + (scale^) = scale_32 } } textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, size : Vec2 ) { - when true + if true { pos_64 := vec2_64_from_vec2(position^) scale_64 := vec2_64_from_vec2(scale^) @@ -151,7 +157,7 @@ textspace_x_form :: #force_inline proc "contextless" ( position, scale : ^Vec2, } else { - quotient : Vec2 = 1.0 / size + quotient : Vec2 = 1.0 / size (position^) *= quotient (scale^) *= quotient }