From 55b80da8e5fbb276fc96e22768caf821003f9fde Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 23 Jun 2024 03:04:38 -0400 Subject: [PATCH] Fixed input event buffer issues Queue doesn't properly act as a ring buffer had to roll my own. I want to make a allocated ring buffer as well... --- code/font/VEFontCache/LRU.odin | 4 +- code/font/VEFontCache/VEFontCache.odin | 2 +- code/grime/.ring_buffer.odin | 96 ++++++++++ code/grime/array.odin | 16 +- code/grime/growing_sub_arena.odin | 1 - code/grime/hashmap_zpl.odin | 2 +- code/grime/mappings.odin | 1 + code/grime/queue.odin | 4 + code/grime/ring_buffer_fixed.odin | 168 ++++++++++++++++++ code/grime/stack_fixed.odin | 2 +- code/sectr/app/event.odin | 3 - code/sectr/engine/client_api.odin | 20 +-- .../engine/client_api_sokol_callbacks.odin | 3 +- code/sectr/engine/render.odin | 71 +++++--- code/sectr/grime/arena.odin | 60 ------- code/sectr/grime/mappings.odin | 49 +++-- code/sectr/input/events.odin | 27 +-- 17 files changed, 390 insertions(+), 139 deletions(-) create mode 100644 code/grime/.ring_buffer.odin delete mode 100644 code/grime/growing_sub_arena.odin create mode 100644 code/grime/ring_buffer_fixed.odin delete mode 100644 code/sectr/app/event.odin delete mode 100644 code/sectr/grime/arena.odin diff --git a/code/font/VEFontCache/LRU.odin b/code/font/VEFontCache/LRU.odin index 3a18901..b631779 100644 --- a/code/font/VEFontCache/LRU.odin +++ b/code/font/VEFontCache/LRU.odin @@ -172,8 +172,8 @@ LRU_reload :: proc( cache : ^LRU_Cache, allocator : Allocator ) LRU_hash_key :: #force_inline proc( key : u64 ) -> ( hash : u64 ) { bytes := transmute( [8]byte ) key - // hash = fnv64a( bytes[:] ) - hash = cast(u64) crc64( bytes[:] ) + hash = fnv64a( bytes[:] ) + // hash = cast(u64) crc64( bytes[:] ) return } diff --git a/code/font/VEFontCache/VEFontCache.odin b/code/font/VEFontCache/VEFontCache.odin index b1e36e2..27e18f4 100644 --- a/code/font/VEFontCache/VEFontCache.odin +++ b/code/font/VEFontCache/VEFontCache.odin @@ -754,7 +754,7 @@ reset_batch_codepoint_state :: proc( ctx : ^Context ) { shape_text_cached :: proc( ctx : ^Context, font : FontID, text_utf8 : string ) -> ^ShapedText { font := font - hash := cast(u64) crc32( transmute([]u8) text_utf8 ) + hash := cast(u64) crc64( transmute([]u8) text_utf8 ) // hash := label_hash( text_utf8 ) shape_cache := & ctx.shape_cache diff --git a/code/grime/.ring_buffer.odin b/code/grime/.ring_buffer.odin new file mode 100644 index 0000000..9d7fd99 --- /dev/null +++ b/code/grime/.ring_buffer.odin @@ -0,0 +1,96 @@ +package grime + +import "core:mem" + +RingBuffer :: struct($T: typeid) { + data: []T, + head: int, + tail: int, + len: int, + is_full: bool, +} + +init :: proc(rb: ^RingBuffer($T), capacity: int, allocator := context.allocator) -> mem.Allocator_Error { + data, err := make([]T, capacity, allocator) + if err != nil { + return err + } + rb.data = data + rb.head = 0 + rb.tail = 0 + rb.len = 0 + rb.is_full = false + return nil +} + +destroy :: proc(rb: ^RingBuffer($T)) { + delete(rb.data) + rb^ = {} +} + +len :: proc(rb: RingBuffer($T)) -> int { + return rb.len +} + +cap :: proc(rb: RingBuffer($T)) -> int { + return len(rb.data) +} + +is_empty :: proc(rb: RingBuffer($T)) -> bool { + return rb.len == 0 +} + +is_full :: proc(rb: RingBuffer($T)) -> bool { + return rb.is_full +} + +push_back :: proc(rb: ^RingBuffer($T), value: T) { + if rb.is_full { + rb.data[rb.head] = value + rb.head = (rb.head + 1) % len(rb.data) + rb.tail = rb.head + } else { + rb.data[rb.tail] = value + rb.tail = (rb.tail + 1) % len(rb.data) + rb.len += 1 + rb.is_full = rb.len == len(rb.data) + } +} + +pop_front :: proc(rb: ^RingBuffer($T)) -> (T, bool) { + if rb.len == 0 { + return T{}, false + } + + value := rb.data[rb.head] + rb.head = (rb.head + 1) % len(rb.data) + rb.len -= 1 + rb.is_full = false + return value, true +} + +get :: proc(rb: RingBuffer($T), index: int) -> (T, bool) { + if index < 0 || index >= rb.len { + return T{}, false + } + actual_index := (rb.head + index) % len(rb.data) + return rb.data[actual_index], true +} + +RingBufferIterator :: struct($T: typeid) { + rb: ^RingBuffer(T), + current: int, +} + +iterator :: proc(rb: ^RingBuffer($T)) -> RingBufferIterator(T) { + return RingBufferIterator(T){rb = rb, current = 0} +} + +next :: proc(it: ^RingBufferIterator($T)) -> (T, bool) { + if it.current >= it.rb.len { + return T{}, false + } + value, _ := get(it.rb^, it.current) + it.current += 1 + return value, true +} diff --git a/code/grime/array.odin b/code/grime/array.odin index b4e1f53..9b533a3 100644 --- a/code/grime/array.odin +++ b/code/grime/array.odin @@ -186,15 +186,15 @@ array_back :: proc( self : Array($Type) ) -> Type { return value } -// array_push_back :: proc( using self : Array( $ Type)) -> b32 { -// if num == capacity { -// return false -// } +array_push_back :: proc( using self : Array( $ Type)) -> b32 { + if num == capacity { + return false + } -// data[ num ] = value -// num += 1 -// return true -// } + data[ num ] = value + num += 1 + return true +} array_clear :: proc "contextless" ( using self : Array( $ Type ), zero_data : b32 = false ) { if zero_data { diff --git a/code/grime/growing_sub_arena.odin b/code/grime/growing_sub_arena.odin deleted file mode 100644 index a4d05c8..0000000 --- a/code/grime/growing_sub_arena.odin +++ /dev/null @@ -1 +0,0 @@ -package grime \ No newline at end of file diff --git a/code/grime/hashmap_zpl.odin b/code/grime/hashmap_zpl.odin index 1abb328..bf920eb 100644 --- a/code/grime/hashmap_zpl.odin +++ b/code/grime/hashmap_zpl.odin @@ -8,7 +8,7 @@ was I believe exclusively when I didn't set the base addresss of vmem OR when I was attempting to use Casey's brute force replay feature with memory. 5-26-2024 Update: TODO(Ed): There is a Raw_Map structure defined in base:runtime/core.odin -We can use the regulare dynamic +We can use the regulare dynamic --------------------------------------------------------------------------------------------------------- This implementation uses two ZPL-Based Arrays to hold entires and the actual hash table. diff --git a/code/grime/mappings.odin b/code/grime/mappings.odin index 824789a..669f776 100644 --- a/code/grime/mappings.odin +++ b/code/grime/mappings.odin @@ -148,6 +148,7 @@ is_power_of_two :: proc { iterator :: proc { iterator_queue, + iterator_ringbuf_fixed, } make :: proc { diff --git a/code/grime/queue.odin b/code/grime/queue.odin index 113cce5..7da8cb4 100644 --- a/code/grime/queue.odin +++ b/code/grime/queue.odin @@ -1,7 +1,9 @@ package grime +import "base:runtime" import "core:container/queue" +// Note(Ed): Fixed size queue DOES NOT act as a RING BUFFER make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_CAPACITY, allocator := context.allocator, fixed_cap : bool = false ) -> (result : Queue(Type), error : AllocatorError) { allocator := allocator @@ -19,7 +21,9 @@ make_queue :: proc( $QueueType : typeid/Queue($Type), capacity := queue.DEFAULT_ push_back_slice_queue :: proc( self : ^$QueueType / Queue($Type), slice : []Type ) -> ( error : AllocatorError ) { + if len(slice) == 0 do return queue.push_back_elems( self, ..slice ) + return } diff --git a/code/grime/ring_buffer_fixed.odin b/code/grime/ring_buffer_fixed.odin new file mode 100644 index 0000000..e28319f --- /dev/null +++ b/code/grime/ring_buffer_fixed.odin @@ -0,0 +1,168 @@ +package grime + +RingBufferFixed :: struct( $Type: typeid, $Size: u32 ) { + head : u32, + tail : u32, + num : u32, + items : [Size] Type, +} + +ringbuf_fixed_clear :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size)) { + head = 0 + tail = 0 + num = 0 +} + +ringbuf_fixed_is_full :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> bool { + return num == Size +} + +ringbuf_fixed_is_empty :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> bool { + return num == 0 +} + +ringbuf_fixed_peek_front_ref :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size)) -> ^Type { + assert(num > 0, "Attempted to peek an empty ring buffer") + return & items[ head ] +} + +ringbuf_fixed_peek_front :: #force_inline proc "contextless" ( using buffer : RingBufferFixed( $Type, $Size)) -> Type { + assert(num > 0, "Attempted to peek an empty ring buffer") + return items[ head ] +} + +ringbuf_fixed_peak_back :: #force_inline proc ( using buffer : RingBufferFixed( $Type, $Size)) -> Type { + assert(num > 0, "Attempted to peek an empty ring buffer") + + buf_size := u32(Size) + index := (tail - 1 + buf_size) % buf_size + return items[ index ] +} + +ringbuf_fixed_push :: #force_inline proc(using buffer: ^RingBufferFixed($Type, $Size), value: Type) { + if num == Size do head = (head + 1) % Size + else do num += 1 + + items[ tail ] = value + tail = (tail + 1) % Size +} + +ringbuf_fixed_push_slice :: proc(buffer: ^RingBufferFixed($Type, $Size), slice: []Type) -> u32 +{ + size := u32(Size) + slice_size := u32(len(slice)) + + // assert( slice_size <= size, "Attempting to append a slice that is larger than the ring buffer!" ) + if slice_size == 0 do return 0 + + items_to_add := min( slice_size, size) + items_added : u32 = 0 + + if items_to_add > Size - buffer.num + { + // Some or all existing items will be overwritten + overwrite_count := items_to_add - (Size - buffer.num) + buffer.head = (buffer.head + overwrite_count) % size + buffer.num = size + } + else + { + buffer.num += items_to_add + } + + if items_to_add <= size + { + // Case 1: Slice fits entirely or partially in the buffer + space_to_end := size - buffer.tail + first_chunk := min(items_to_add, space_to_end) + + // First copy: from tail to end of buffer + copy( buffer.items[ buffer.tail: ] , slice[ :first_chunk ] ) + + if first_chunk < items_to_add { + // Second copy: wrap around to start of buffer + second_chunk := items_to_add - first_chunk + copy( buffer.items[:], slice[ first_chunk : items_to_add ] ) + } + + buffer.tail = (buffer.tail + items_to_add) % Size + items_added = items_to_add + } + else + { + // Case 2: Slice is larger than buffer, only keep last Size elements + to_add := slice[ slice_size - size: ] + + // First copy: from start of buffer to end + first_chunk := min(Size, u32(len(to_add))) + copy( buffer.items[:], to_add[ :first_chunk ] ) + + if first_chunk < Size + { + // Second copy: wrap around + copy( buffer.items[ first_chunk: ], to_add[ first_chunk: ] ) + } + + buffer.head = 0 + buffer.tail = 0 + buffer.num = Size + items_added = Size + } + + return items_added +} + +ringbuf_fixed_pop :: #force_inline proc "contextless" ( using buffer : ^RingBufferFixed( $Type, $Size )) -> Type { + assert(num > 0, "Attempted to pop an empty ring buffer") + value := items[ head ] + head = ( head + 1 ) % Size + num -= 1 + return value +} + +RingBufferFixedIterator :: struct( $Type : typeid) { + items : []Type, + head : u32, + tail : u32, + index : u32, + remaining : u32, +} + +iterator_ringbuf_fixed :: proc(buffer: ^RingBufferFixed($Type, $Size)) -> RingBufferFixedIterator(Type) +{ + iter := RingBufferFixedIterator(Type){ + items = buffer.items[:], + head = buffer.head, + tail = buffer.tail, + remaining = buffer.num, + } + + buff_size := u32(Size) + + if buffer.num > 0 { + // Start from the last pushed item (one before tail) + iter.index = (buffer.tail - 1 + buff_size) % buff_size + } else { + iter.index = buffer.tail // This will not be used as remaining is 0 + } + + return iter +} + +next_ringbuf_fixed_iterator :: proc(iter : ^RingBufferFixedIterator( $Type)) -> ^Type +{ + using iter + if remaining == 0 { + return nil // If there are no items left to iterate over + } + + buf_size := cast(u32) len(items) + + result := &items[index] + + // Decrement index and wrap around if necessary + index = (index - 1 + buf_size) % buf_size + + remaining -= 1 + return result +} diff --git a/code/grime/stack_fixed.odin b/code/grime/stack_fixed.odin index f829233..5625091 100644 --- a/code/grime/stack_fixed.odin +++ b/code/grime/stack_fixed.odin @@ -12,7 +12,7 @@ stack_clear :: #force_inline proc ( using stack : ^StackFixed( $Type, $Size)) { } stack_push :: #force_inline proc( using stack : ^ StackFixed( $ Type, $ Size ), value : Type ) { - assert( idx < len( items ), "Attempted to push on a full stack" ) + assert( idx < u32(len( items )), "Attempted to push on a full stack" ) items[ idx ] = value idx += 1 diff --git a/code/sectr/app/event.odin b/code/sectr/app/event.odin deleted file mode 100644 index 7ba6dc6..0000000 --- a/code/sectr/app/event.odin +++ /dev/null @@ -1,3 +0,0 @@ -package sectr - - diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index 9c0c14a..3560277 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -112,14 +112,14 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem using input_events error : AllocatorError - events, error = make( Queue(InputEvent), 4 * Kilo, persistent_allocator(), fixed_cap = true ) - ensure(error == AllocatorError.None, "Failed to allocate input.events array") + // events, error = make( RingBuffer(InputEvent), 4 * Kilo, persistent_allocator(), fixed_cap = true ) + // ensure(error == AllocatorError.None, "Failed to allocate input.events array") - key_events, error = make( Queue(InputKeyEvent), Kilo, persistent_allocator(), fixed_cap = true ) - ensure(error == AllocatorError.None, "Failed to allocate key_events array") + // key_events, error = make( RingBuffer(InputKeyEvent), Kilo, persistent_allocator(), fixed_cap = true ) + // ensure(error == AllocatorError.None, "Failed to allocate key_events array") - mouse_events, error = make( Queue(InputMouseEvent), 2 * Kilo, persistent_allocator(), fixed_cap = true ) - ensure(error == AllocatorError.None, "Failed to allocate mouse_events array") + // mouse_events, error = make( RingBuffer(InputMouseEvent), 3 * Kilo, persistent_allocator(), fixed_cap = true ) + // ensure(error == AllocatorError.None, "Failed to allocate mouse_events array") codes_pressed, error = make( Array(rune), Kilo, persistent_slab_allocator() ) ensure(error == AllocatorError.None, "Failed to allocate codes_pressed array") @@ -422,9 +422,9 @@ hot_reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_ // input_reload() { using input_events - reload( & events, runtime.nil_allocator()) - reload( & key_events, runtime.nil_allocator()) - reload( & mouse_events, runtime.nil_allocator()) + // reload( & events, runtime.nil_allocator()) + // reload( & key_events, runtime.nil_allocator()) + // reload( & mouse_events, runtime.nil_allocator()) codes_pressed.backing = persistent_slab_allocator() staged_input_events.backing = persistent_slab_allocator() } @@ -532,7 +532,7 @@ tick_frametime :: #force_inline proc( client_tick : ^time.Tick, host_delta_time_ // profile("Client tick timing processing") - config.engine_refresh_hz = uint(monitor_refresh_hz) + // config.engine_refresh_hz = uint(monitor_refresh_hz) // config.engine_refresh_hz = 10 frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS diff --git a/code/sectr/engine/client_api_sokol_callbacks.odin b/code/sectr/engine/client_api_sokol_callbacks.odin index 6d08538..e9f2eba 100644 --- a/code/sectr/engine/client_api_sokol_callbacks.odin +++ b/code/sectr/engine/client_api_sokol_callbacks.odin @@ -73,7 +73,8 @@ sokol_app_log_callback :: proc "c" ( message_or_null: cstring, line_nr: u32, filename_or_null: cstring, - user_data: rawptr) { + user_data: rawptr) +{ context = get_state().sokol_context odin_level : LogLevel diff --git a/code/sectr/engine/render.odin b/code/sectr/engine/render.odin index 8d8d193..b934a06 100644 --- a/code/sectr/engine/render.odin +++ b/code/sectr/engine/render.odin @@ -80,13 +80,13 @@ render :: proc() profile(#procedure) state := get_state(); using state // TODO(Ed): Prefer passing static context to through the callstack + clear_pass := gfx.Pass { action = render_data.pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() } + clear_pass.action.colors[0].clear_value = transmute(gfx.Color) normalize_rgba8( config.color_theme.bg ) // TODO(Ed): Eventually we want to only update when state is dirty/user has done an action - gfx.begin_pass(gfx.Pass { action = render_data.pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() }) + gfx.begin_pass(clear_pass) gfx.end_pass(); - // render_mode_3d() - render_mode_2d_workspace() render_mode_screenspace() @@ -133,25 +133,35 @@ render_mode_screenspace :: proc() cam := & project.workspace.cam win_extent := state.app_window.extent - ve.configure_snap( & font_provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) ) - - render_screen_ui() - screen_extent := app_window.extent screen_size := app_window.extent * 2 screen_ratio := screen_size.x * ( 1.0 / screen_size.y ) - gp.begin( i32(screen_size.x), i32(screen_size.y) ) - gp.viewport(0, 0, i32(screen_size.x), i32(screen_size.y)) - gp.project( -screen_extent.x, screen_extent.x, screen_extent.y, -screen_extent.y ) + ve.configure_snap( & font_provider_data.ve_font_cache, u32(state.app_window.extent.x * 2.0), u32(state.app_window.extent.y * 2.0) ) - gp_set_color(Color_Screen_Center_Dot) - draw_filled_circle(0, 0, 2, 24) + render_screen_ui() - gfx.begin_pass( gfx.Pass { action = render_data.pass_actions.empty_action, swapchain = sokol_glue.swapchain() }) - gp.flush() - gp.end() - gfx.end_pass() + Render_Reference_Dots: + { + gp.begin( i32(screen_size.x), i32(screen_size.y) ) + gp.viewport(0, 0, i32(screen_size.x), i32(screen_size.y)) + gp.project( -screen_extent.x, screen_extent.x, screen_extent.y, -screen_extent.y ) + + gp_set_color(Color_Screen_Center_Dot) + draw_filled_circle(0, 0, 2, 24) + + Mouse_Position: + { + mouse_pos := input.mouse.pos + gp_set_color({ 180, 180, 180, 20}) + draw_filled_circle( mouse_pos.x, mouse_pos.y, 4, 24 ) + } + + gfx.begin_pass( gfx.Pass { action = render_data.pass_actions.empty_action, swapchain = sokol_glue.swapchain() }) + gp.flush() + gp.end() + gfx.end_pass() + } debug_draw_text :: proc( content : string, pos : Vec2, size : f32, color := Color_White, font : FontID = Font_Default ) @@ -183,8 +193,8 @@ render_mode_screenspace :: proc() cam := & project.workspace.cam screen_corners := screen_get_corners() - position := screen_corners.top_right - position.x -= app_window.extent.x * 0.5 + position := screen_corners.top_left + position.x = 0 position.y -= debug.draw_debug_text_y content := str_fmt_buffer( draw_text_scratch[:], format, ..args ) @@ -201,18 +211,33 @@ render_mode_screenspace :: proc() fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 } debug_draw_text( fps_msg, fps_msg_pos, 38.0, color = Color_Red ) - // debug_text( "Screen Width : %v", rl.GetScreenWidth () ) - // debug_text( "Screen Height: %v", rl.GetScreenHeight() ) - // debug_text( "frametime_target_ms : %f ms", frametime_target_ms ) + debug_text( "Screen Width : %v", screen_size.x ) + debug_text( "Screen Height: %v", screen_size.y ) + debug_text( "frametime_target_ms : %f ms", frametime_target_ms ) debug_text( "frametime : %0.3f ms", frametime_delta32() ) - // debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms ) + debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms ) if replay.mode == ReplayMode.Record { debug_text( "Recording Input") } if replay.mode == ReplayMode.Playback { debug_text( "Replaying Input") } - // debug_text("Zoom Target: %v", project.workspace.zoom_target) + debug_text("Zoom Target: %v", project.workspace.zoom_target) + + if true + { + using input_events + + id := 0 + iter_obj := iterator( & mouse_events ); iter := & iter_obj + for event := next( iter ); event != nil; event = next( iter ) + { + if id >= 4 do break + id += 1 + + debug_text("Mouse Event: %v", event ) + } + } if debug.mouse_vis { debug_text("Mouse scroll: %v", input.mouse.scroll ) diff --git a/code/sectr/grime/arena.odin b/code/sectr/grime/arena.odin deleted file mode 100644 index 0384397..0000000 --- a/code/sectr/grime/arena.odin +++ /dev/null @@ -1,60 +0,0 @@ -/* -The default arena allocator Odin provides does fragmented resizes even for the last most allocated block getting resized. -This is an alternative to alleviates that. - -TODO(Ed): Implement? Maybe we should trash this I' haven't seen a need to step away from using odin's -*/ -package sectr - -import "core:mem" - -// Initialize a sub-section of our virtual memory as a sub-arena -sub_arena_init :: proc( address : ^byte, size : int ) -> ( ^ Arena) { - Arena :: mem.Arena - - arena_size :: size_of( Arena) - sub_arena := cast( ^ Arena ) address - mem_slice := slice_ptr( ptr_offset( address, arena_size), size ) - arena_init( sub_arena, mem_slice ) - return sub_arena -} - -ArenaFixedHeader :: struct { - data : []byte, - offset : uint, - peak_used : uint, -} - -ArenaFixed :: struct { - using header : ^ArenaFixedHeader, -} - -arena_fixed_init :: proc( backing : []byte ) -> (arena : ArenaFixed) { - header_size := size_of(ArenaFixedHeader) - - verify(len(backing) >= (header_size + Kilobyte), "Attempted to init an arena with less than kilobyte of memory...") - - arena.header = cast(^ArenaFixedHeader) raw_data(backing) - using arena.header - data_ptr := cast([^]byte) (cast( [^]ArenaFixedHeader) arena.header)[ 1:] - data = slice_ptr( data_ptr, len(backing) - header_size ) - offset = 0 - peak_used = 0 - return -} - -arena_fixed_allocator_proc :: proc( - allocator_data : rawptr, - mode : AllocatorMode, - size : int, - alignment : int, - old_memory : rawptr, - old_size : int, - location := #caller_location -) -> ([]byte, AllocatorError) -{ - - - return nil, .Out_Of_Memory -} - diff --git a/code/sectr/grime/mappings.odin b/code/sectr/grime/mappings.odin index 8aa86d3..d7a4a4c 100644 --- a/code/sectr/grime/mappings.odin +++ b/code/sectr/grime/mappings.odin @@ -30,8 +30,8 @@ import "base:runtime" import c "core:c/libc" -import "core:container/queue" - Queue :: queue.Queue +// import "core:container/queue" + // Queue :: queue.Queue // import "core:dynlib" @@ -188,12 +188,26 @@ import "codebase:grime" hmap_zpl_reload :: grime.hmap_zpl_reload hmap_zpl_set :: grime.hmap_zpl_set - make_queue :: grime.make_queue + // make_queue :: grime.make_queue - next_queue_iterator :: grime.next_queue_iterator + // next_queue_iterator :: grime.next_queue_iterator Pool :: grime.Pool + RingBufferFixed :: grime.RingBufferFixed + RingBufferFixedIterator :: grime.RingBufferFixedIterator + + ringbuf_fixed_clear :: grime.ringbuf_fixed_clear + ringbuf_fixed_is_full :: grime.ringbuf_fixed_is_full + ringbuf_fixed_is_empty :: grime.ringbuf_fixed_is_empty + ringbuf_fixed_peak_back :: grime.ringbuf_fixed_peak_back + ringbuf_fixed_push :: grime.ringbuf_fixed_push + ringbuf_fixed_push_slice :: grime.ringbuf_fixed_push_slice + ringbuf_fixed_pop :: grime.ringbuf_fixed_pop + + iterator_ringbuf_fixed :: grime.iterator_ringbuf_fixed + next_ringbuf_fixed_iterator :: grime.next_ringbuf_fixed_iterator + Slab :: grime.Slab SlabPolicy :: grime.SlabPolicy SlabSizeClass :: grime.SlabSizeClass @@ -368,14 +382,15 @@ is_power_of_two :: proc { } iterator :: proc { - grime.iterator_queue, + // grime.iterator_queue, + grime.iterator_ringbuf_fixed, } make :: proc { array_init, hmap_chained_init, hmap_zpl_init, - make_queue, + // make_queue, // Usual make_slice, @@ -396,16 +411,17 @@ mov_avg_exp :: proc { } next :: proc { - next_queue_iterator, + // next_queue_iterator, + next_ringbuf_fixed_iterator, } peek_back :: proc { - queue.peek_back, + ringbuf_fixed_peak_back, } -peek_front :: proc { - queue.peek_front, -} +// peek_front :: proc { +// queue.peek_front, +// } pixels_to_cm :: proc { f32_pixels_to_cm, @@ -444,8 +460,11 @@ pressed :: proc { } push :: proc { - queue.push_back, - grime.push_back_slice_queue, + ringbuf_fixed_push, + ringbuf_fixed_push_slice, + + // queue.push_back, + // grime.push_back_slice_queue, stack_push, stack_allocator_push, @@ -476,10 +495,6 @@ reload :: proc { grime.reload_map, } -space_left :: proc { - queue.space, -} - scope :: proc { ui_layout_scope_via_layout, ui_layout_scope_via_combo, diff --git a/code/sectr/input/events.odin b/code/sectr/input/events.odin index 646765a..2d726ab 100644 --- a/code/sectr/input/events.odin +++ b/code/sectr/input/events.odin @@ -53,9 +53,9 @@ InputMouseEvent :: struct { } InputEvents :: struct { - events : Queue(InputEvent), - key_events : Queue(InputKeyEvent), - mouse_events : Queue(InputMouseEvent), + events : RingBufferFixed(InputEvent, 640), + key_events : RingBufferFixed(InputKeyEvent, 128), + mouse_events : RingBufferFixed(InputMouseEvent, 512), codes_pressed : Array(rune), } @@ -138,6 +138,8 @@ pull_staged_input_events :: proc( input : ^InputState, input_events : ^InputEve scroll = event.mouse.scroll, modifiers = event.modifiers, }) + // logf("Detected scroll: %v", event.mouse.scroll) + case .Mouse_Move: push( & mouse_events, InputMouseEvent { frame_id = event.frame_id, @@ -200,8 +202,8 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input @static prev_frame : u64 = 0 last_frame : u64 = 0 - if events.len > 0 { - last_frame = peek_back( & events).frame_id + if events.num > 0 { + last_frame = peek_back( events).frame_id } // No new events, don't update @@ -209,18 +211,19 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input Iterate_Key_Events: { - iter_obj := iterator( key_events ); iter := & iter_obj + iter_obj := iterator( & key_events ); iter := & iter_obj for event := next( iter ); event != nil; event = next( iter ) { + // logf("last_frame (iter): %v", last_frame) + // logf("frame (iter): %v", event.frame_id ) if last_frame > event.frame_id { break } - // logf("last_frame (iter): %v", last_frame) - // logf("frame (iter): %v", event.frame_id ) - key := & input.keyboard.keys[event.key] prev_key := prev_input.keyboard.keys[event.key] + // logf("key event: %v", event) + first_transition := key.half_transitions == 0 #partial switch event.type { @@ -237,7 +240,7 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input Iterate_Mouse_Events: { - iter_obj := iterator( mouse_events ); iter := & iter_obj + iter_obj := iterator( & mouse_events ); iter := & iter_obj for event := next( iter ); event != nil; event = next( iter ) { if last_frame > event.frame_id { @@ -252,6 +255,8 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input btn.ended_down = ended_down } + // logf("mouse event: %v", event) + #partial switch event.type { case .Mouse_Pressed: btn := & input.mouse.btns[event.btn] @@ -264,7 +269,7 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input process_digital_btn( btn, prev_btn, false ) case .Mouse_Scroll: - input.mouse.scroll += event.scroll.x + input.mouse.scroll += event.scroll case .Mouse_Move: case .Mouse_Enter: