From 62979b480ead20996ed89662d484798572cfaab4 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 18 Oct 2025 15:01:19 -0400 Subject: [PATCH] Code2 Progress: more sokol stuff --- code2/grime/allocator_interface.odin | 2 +- code2/grime/dynamic_array.odin | 2 +- code2/grime/memory.odin | 37 ++- code2/grime/pkg_mappings.odin | 22 +- code2/grime/ring_buffer_fixed.odin | 130 ++++------- code2/grime/static_memory.odin | 6 +- code2/grime/stirngs.odin | 10 + code2/host/host.odin | 1 - code2/sectr/engine/client_api.odin | 19 +- .../engine/client_api_sokol_callbacks.odin | 220 ++++++++++++++++++ code2/sectr/pkg_mappings.odin | 93 +++++--- scripts/build.ps1 | 19 +- 12 files changed, 388 insertions(+), 173 deletions(-) diff --git a/code2/grime/allocator_interface.odin b/code2/grime/allocator_interface.odin index 04d3376..3395533 100644 --- a/code2/grime/allocator_interface.odin +++ b/code2/grime/allocator_interface.odin @@ -205,7 +205,7 @@ mem_save_point :: proc(ainfo := context.allocator, loc := #caller_location) -> A resolve_allocator_proc(ainfo.procedure)({data = ainfo.data, op = .SavePoint, loc = loc}, & out) return out.save_point } -mem_alloc :: proc(size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo : $Type = context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { +mem_alloc :: proc(size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo: $Type = context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, diff --git a/code2/grime/dynamic_array.odin b/code2/grime/dynamic_array.odin index da3a98b..6f21127 100644 --- a/code2/grime/dynamic_array.odin +++ b/code2/grime/dynamic_array.odin @@ -159,7 +159,7 @@ array_append_at_value :: proc(self: ^Array($Type), item: Type, id: int) -> Alloc return AllocatorError.None } -array_back :: #force_inline proc "contextless" (self : Array($Type)) -> Type { assert(self.num > 0); return self.data[self.num - 1] } +array_back :: #force_inline proc "contextless" (self : Array($Type)) -> Type { assert_contextless(self.num > 0); return self.data[self.num - 1] } array_clear :: #force_inline proc "contextless" (self: Array($Type), zero_data: bool = false) { if zero_data do zero(self.data, int(self.num) * size_of(Type)) diff --git a/code2/grime/memory.odin b/code2/grime/memory.odin index 287940e..e2aaa61 100644 --- a/code2/grime/memory.odin +++ b/code2/grime/memory.odin @@ -15,9 +15,9 @@ align_pow2 :: #force_inline proc "contextless" (ptr, align: int) -> int { return ptr & ~(align-1) } -memory_zero_explicit :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr { - mem_zero_volatile(data, len) // Use the volatile mem_zero - atomic_thread_fence(.Seq_Cst) // Prevent reordering +sync_mem_zero :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr { + mem_zero_volatile(data, len) // Use the volatile mem_zero + sync_fence(.Seq_Cst) // Prevent reordering return data } @@ -38,11 +38,14 @@ slice_assert :: #force_inline proc "contextless" (s: $SliceType / []$Type) { slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return cursor(s)[len(s):] } slice_byte_end :: #force_inline proc "contextless" (s : SliceByte) -> ^byte { return s.data[s.len:] } +slice_zero :: #force_inline proc "contextless" (s: $SliceType / []$Type) { + assert_contextless(len(s) > 0) + mem_zero(raw_data(s), size_of(Type) * len(s)) +} slice_copy :: #force_inline proc "contextless" (dst, src: $SliceType / []$Type) -> int { n := max(0, min(len(dst), len(src))) - if n > 0 { - mem_copy(raw_data(dst), raw_data(src), n * size_of(Type)) - } + assert_contextless(n > 0) + mem_copy(raw_data(dst), raw_data(src), n * size_of(Type)) return n } @@ -84,37 +87,33 @@ calc_padding_with_header :: proc "contextless" (pointer: uintptr, alignment: uin } // Helper to get the the beginning of memory after a slice -memory_after :: #force_inline proc "contextless" ( s: []byte ) -> ( ^ byte) { +@(require_results) +memory_after :: #force_inline proc "contextless" (s: []byte ) -> (^byte) { return cursor(s)[len(s):] } - -memory_after_header :: #force_inline proc "contextless" ( header : ^($ Type) ) -> ( [^]byte) { +memory_after_header :: #force_inline proc "contextless" (header: ^($Type)) -> ([^]byte) { result := cast( [^]byte) ptr_offset( header, 1 ) // result := cast( [^]byte) (cast( [^]Type) header)[ 1:] return result } - @(require_results) -memory_align_formula :: #force_inline proc "contextless" ( size, align : uint) -> uint { +memory_align_formula :: #force_inline proc "contextless" (size, align: uint) -> uint { result := size + align - 1 return result - result % align } - // This is here just for docs -memory_misalignment :: #force_inline proc ( address, alignment : uintptr) -> uint { +memory_misalignment :: #force_inline proc "contextless" (address, alignment: uintptr) -> uint { // address % alignment - assert(is_power_of_two(alignment)) + assert_contextless(is_power_of_two(alignment)) return uint( address & (alignment - 1) ) } - // This is here just for docs @(require_results) -memory_aign_forward :: #force_inline proc( address, alignment : uintptr) -> uintptr +memory_aign_forward :: #force_inline proc "contextless" (address, alignment : uintptr) -> uintptr { - assert(is_power_of_two(alignment)) - + assert_contextless(is_power_of_two(alignment)) aligned_address := address - misalignment := cast(uintptr) memory_misalignment( address, alignment ) + misalignment := transmute(uintptr) memory_misalignment( address, alignment ) if misalignment != 0 { aligned_address += alignment - misalignment } diff --git a/code2/grime/pkg_mappings.odin b/code2/grime/pkg_mappings.odin index b676672..a470618 100644 --- a/code2/grime/pkg_mappings.odin +++ b/code2/grime/pkg_mappings.odin @@ -80,7 +80,7 @@ import "core:os" file_truncate :: os.truncate file_write :: os.write - file_read_entire_from_filename :: #force_inline proc(name: string, allocator := context.allocator, loc := #caller_location) -> (data: []byte, success: bool) { return os.read_entire_file_from_filename(name, resolve_odin_allocator(allocator), loc) } + file_read_entire_from_filename :: #force_inline proc(name: string, allocator := context.allocator, loc := #caller_location) -> ([]byte, bool) { return os.read_entire_file_from_filename(name, resolve_odin_allocator(allocator), loc) } file_write_entire :: os.write_entire_file file_read_entire :: proc { @@ -91,15 +91,13 @@ import "core:strings" StrBuilder :: strings.Builder strbuilder_from_bytes :: strings.builder_from_bytes -import "core:slice" - slice_zero :: slice.zero - import "core:prof/spall" Spall_Context :: spall.Context Spall_Buffer :: spall.Buffer import "core:sync" Mutex :: sync.Mutex + sync_fence :: sync.atomic_thread_fence sync_load :: sync.atomic_load_explicit sync_store :: sync.atomic_store_explicit @@ -122,54 +120,50 @@ array_append :: proc { array_append_array, array_append_slice, } - array_append_at :: proc { // array_append_at_array, array_append_at_slice, array_append_at_value, } - cursor :: proc { raw_cursor, ptr_cursor, slice_cursor, string_cursor, } - end :: proc { slice_end, slice_byte_end, string_end, } - copy :: proc { mem_copy, slice_copy, } - copy_non_overlaping :: proc { mem_copy_non_overlapping, slice_copy_overlapping, } - fill :: proc { mem_fill, slice_fill, } - +iterator :: proc { + iterator_ringbuf_fixed, +} make :: proc { array_init, } - +peek_back :: proc { + ringbuf_fixed_peak_back, +} to_bytes :: proc { slice_to_bytes, type_to_bytes, } - to_string :: proc { strings.to_string, } - zero :: proc { mem_zero, slice_zero, diff --git a/code2/grime/ring_buffer_fixed.odin b/code2/grime/ring_buffer_fixed.odin index e28319f..c690f0b 100644 --- a/code2/grime/ring_buffer_fixed.odin +++ b/code2/grime/ring_buffer_fixed.odin @@ -1,126 +1,96 @@ package grime -RingBufferFixed :: struct( $Type: typeid, $Size: u32 ) { +FRingBuffer :: 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_cslear :: #force_inline proc "contextless" (ring: ^FRingBuffer($Type, $Size)) { ring.head = 0; ring.tail = 0; ring.num = 0 } +ringbuf_fixed_is_full :: #force_inline proc "contextless" (ring: FRingBuffer($Type, $Size)) -> bool { return ring.num == ring.Size } +ringbuf_fixed_is_empty :: #force_inline proc "contextless" (ring: FRingBuffer($Type, $Size)) -> bool { return ring.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") +ringbuf_fixed_peek_front_ref :: #force_inline proc "contextless" (using buffer: ^FRingBuffer($Type, $Size)) -> ^Type { + assert_contextless(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") +ringbuf_fixed_peek_front :: #force_inline proc "contextless" ( using buffer : FRingBuffer( $Type, $Size)) -> Type { + assert_contextless(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") - +ringbuf_fixed_peak_back :: #force_inline proc (using buffer : FRingBuffer( $Type, $Size)) -> Type { + assert_contextless(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) { +ringbuf_fixed_push :: #force_inline proc(using buffer: ^FRingBuffer($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 +ringbuf_fixed_push_slice :: proc "contextless" (buffer: ^FRingBuffer($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!" ) + assert_contextless( 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 + 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 + 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 + 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 - { + 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") +ringbuf_fixed_pop :: #force_inline proc "contextless" (using buffer: ^FRingBuffer($Type, $Size)) -> Type { + assert_contextless(num > 0, "Attempted to pop an empty ring buffer") value := items[ head ] head = ( head + 1 ) % Size - num -= 1 + num -= 1 return value } -RingBufferFixedIterator :: struct( $Type : typeid) { +FRingBufferIterator :: struct($Type : typeid) { items : []Type, head : u32, tail : u32, @@ -128,41 +98,29 @@ RingBufferFixedIterator :: struct( $Type : typeid) { remaining : u32, } -iterator_ringbuf_fixed :: proc(buffer: ^RingBufferFixed($Type, $Size)) -> RingBufferFixedIterator(Type) +iterator_ringbuf_fixed :: proc "contextless" (buffer: ^FRingBuffer($Type, $Size)) -> FRingBufferIterator(Type) { - iter := RingBufferFixedIterator(Type){ + iter := FRingBufferIterator(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 - } - +next_ringbuf_fixed_iterator :: proc(iter: ^FRingBufferIterator($Type)) -> ^Type { + using iter; if remaining == 0 do return nil // If there are no items left to iterate over buf_size := cast(u32) len(items) - - result := &items[index] - + result := &items[index] // Decrement index and wrap around if necessary - index = (index - 1 + buf_size) % buf_size - + index = (index - 1 + buf_size) % buf_size remaining -= 1 return result } diff --git a/code2/grime/static_memory.odin b/code2/grime/static_memory.odin index 3809e61..703a572 100644 --- a/code2/grime/static_memory.odin +++ b/code2/grime/static_memory.odin @@ -1,9 +1,7 @@ package grime -//region STATIC MEMORY - grime_memory: StaticMemory -@thread_local grime_thread: ThreadMemory -//endregion STATIC MEMORY +@(private) grime_memory: StaticMemory +@(private, thread_local) grime_thread: ThreadMemory StaticMemory :: struct { spall_context: ^Spall_Context, diff --git a/code2/grime/stirngs.odin b/code2/grime/stirngs.odin index fabcb1a..e999d38 100644 --- a/code2/grime/stirngs.odin +++ b/code2/grime/stirngs.odin @@ -8,3 +8,13 @@ string_cursor :: #force_inline proc "contextless" (s: string) -> [^]u8 { return string_copy :: #force_inline proc "contextless" (dst, src: string) { slice_copy (transmute([]byte) dst, transmute([]byte) src) } string_end :: #force_inline proc "contextless" (s: string) -> ^u8 { return slice_end (transmute([]byte) s) } string_assert :: #force_inline proc "contextless" (s: string) { slice_assert(transmute([]byte) s) } + +str_to_cstr_capped :: proc(content: string, mem: []byte) -> cstring { + copy_len := min(len(content), len(mem) - 1) + if copy_len > 0 do copy(mem[:copy_len], transmute([]byte) content) + mem[copy_len] = 0 + return transmute(cstring) raw_data(mem) +} + +cstr_len_capped :: #force_inline proc "contextless" (content: cstring, cap: int) -> (len: int) { for len = 0; (len <= cap) && (transmute([^]byte)content)[len] != 0; len += 1 {} return } +cstr_to_str_capped :: #force_inline proc "contextless" (content: cstring, mem: []byte) -> string { return transmute(string) Raw_String { cursor(mem), cstr_len_capped (content, len(mem)) } } diff --git a/code2/host/host.odin b/code2/host/host.odin index 33dd5c8..b80875b 100644 --- a/code2/host/host.odin +++ b/code2/host/host.odin @@ -271,7 +271,6 @@ host_job_worker_entrypoint :: proc(worker_thread: ^SysThread) leader := barrier_wait(& host_memory.lane_job_sync) } -@export sync_client_api :: proc() { profile(#procedure) diff --git a/code2/sectr/engine/client_api.odin b/code2/sectr/engine/client_api.odin index a155832..2eb2273 100644 --- a/code2/sectr/engine/client_api.odin +++ b/code2/sectr/engine/client_api.odin @@ -35,12 +35,11 @@ then prepare for multi-threaded "laned" tick: thread_wide_startup. @export startup :: proc(host_mem: ^ProcessMemory, thread_mem: ^ThreadMemory) { - // Rad Debugger driving me crazy.. - // NOTE(Ed): This is not necessary, they're just loops for my sanity. - for ; memory == nil; { memory = host_mem } - for ; thread == nil; { thread = thread_mem } - grime_set_profiler_module_context(& memory.spall_context) - grime_set_profiler_thread_buffer(& thread.spall_buffer) + // (Ignore RAD Debugger's values being null) + memory = host_mem + thread = thread_mem + // grime_set_profiler_module_context(& memory.spall_context) + // grime_set_profiler_thread_buffer(& thread.spall_buffer) profile(#procedure) startup_tick := tick_now() @@ -126,14 +125,14 @@ hot_reload :: proc(host_mem: ^ProcessMemory, thread_mem: ^ThreadMemory) thread = thread_mem if thread.id == .Master_Prepper { sync_store(& memory, host_mem, .Release) - grime_set_profiler_module_context(& memory.spall_context) + // grime_set_profiler_module_context(& memory.spall_context) } else { // NOTE(Ed): This is problably not necessary, they're just loops for my sanity. for ; memory == nil; { sync_load(& memory, .Acquire) } for ; thread == nil; { thread = thread_mem } } - grime_set_profiler_thread_buffer(& thread.spall_buffer) + // grime_set_profiler_thread_buffer(& thread.spall_buffer) } profile(#procedure) // Do hot-reload stuff... @@ -177,7 +176,7 @@ tick_lane_startup :: proc(thread_mem: ^ThreadMemory) { if thread_mem.id != .Master_Prepper { thread = thread_mem - grime_set_profiler_thread_buffer(& thread.spall_buffer) + // grime_set_profiler_thread_buffer(& thread.spall_buffer) } profile(#procedure) } @@ -187,7 +186,7 @@ job_worker_startup :: proc(thread_mem: ^ThreadMemory) { if thread_mem.id != .Master_Prepper { thread = thread_mem - grime_set_profiler_thread_buffer(& thread.spall_buffer) + // grime_set_profiler_thread_buffer(& thread.spall_buffer) } profile(#procedure) } diff --git a/code2/sectr/engine/client_api_sokol_callbacks.odin b/code2/sectr/engine/client_api_sokol_callbacks.odin index 0924da3..c191b82 100644 --- a/code2/sectr/engine/client_api_sokol_callbacks.odin +++ b/code2/sectr/engine/client_api_sokol_callbacks.odin @@ -2,10 +2,13 @@ package sectr import sokol_app "thirdparty:sokol/app" +//region Sokol App + sokol_app_init_callback :: proc "c" () { context = memory.client_memory.sokol_context log_print("sokol_app: Confirmed initialization") } + // This is being filled in but we're directly controlling the lifetime of sokol_app's execution. // So this will only get called during window pan or resize events (on Win32 at least) sokol_app_frame_callback :: proc "c" () @@ -37,3 +40,220 @@ sokol_app_frame_callback :: proc "c" () tick_lane_frametime( & client_tick, sokol_delta_ms, sokol_delta_ns, can_sleep = false ) window.resized = false } + +sokol_app_cleanup_callback :: proc "c" () { + context = memory.client_memory.sokol_context + log_print("sokol_app: Confirmed cleanup") +} + +sokol_app_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr { + context = memory.client_memory.sokol_context + // block, error := mem_alloc( int(size), allocator = persistent_slab_allocator() ) + // ensure(error == AllocatorError.None, "sokol_app allocation failed") + // return block + // TODO(Ed): Implement + return nil +} + +sokol_app_free :: proc "c" ( data : rawptr, user_data : rawptr ) { + context = memory.client_memory.sokol_context + // mem_free(data, allocator = persistent_slab_allocator() ) + // TODO(Ed): Implement +} + +sokol_app_log_callback :: proc "c" ( + tag: cstring, + log_level: u32, + log_item_id: u32, + message_or_null: cstring, + line_nr: u32, + filename_or_null: cstring, + user_data: rawptr) +{ + context = memory.client_memory.sokol_context + odin_level: LoggerLevel + switch log_level { + case 0: odin_level = .Fatal + case 1: odin_level = .Error + case 2: odin_level = .Warning + case 3: odin_level = .Info + } + clone_backing: [16 * Kilo]byte + + cloned_msg: string = ""; + if message_or_null != nil { + cloned_msg = cstr_to_str_capped(message_or_null, clone_backing[:]) + } + cloned_fname: string = "" + if filename_or_null != nil { + cloned_fname = cstr_to_str_capped(filename_or_null, clone_backing[len(cloned_msg):]) + } + cloned_tag := cstr_to_str_capped(tag, clone_backing[len(cloned_msg) + len(cloned_fname):]) + log_print_fmt( "%-80s %s::%v", cloned_msg, cloned_tag, line_nr, level = odin_level ) +} + +// TODO(Ed): Does this need to be queued to a separate thread? +sokol_app_event_callback :: proc "c" (sokol_event: ^sokol_app.Event) +{ + context = memory.client_memory.sokol_context + event: InputEvent + using event + + _sokol_frame_id = sokol_event.frame_count + frame_id = get_frametime().current_frame + + mouse.pos = { sokol_event.mouse_x, sokol_event.mouse_y } + mouse.delta = { sokol_event.mouse_dx, sokol_event.mouse_dy } + + switch sokol_event.type + { + case .INVALID: + log_print_fmt("sokol_app - event: INVALID?") + log_print_fmt("%v", sokol_event) + + case .KEY_DOWN: + if sokol_event.key_repeat do return + + type = .Key_Pressed + key = to_key_from_sokol( sokol_event.key_code ) + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + // logf("Key pressed(sokol): %v", key) + // logf("frame (sokol): %v", frame_id ) + + case .KEY_UP: + if sokol_event.key_repeat do return + + type = .Key_Released + key = to_key_from_sokol( sokol_event.key_code ) + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + // logf("Key released(sokol): %v", key) + // logf("frame (sokol): %v", frame_id ) + + case .CHAR: + if sokol_event.key_repeat do return + + type = .Unicode + codepoint = transmute(rune) sokol_event.char_code + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_DOWN: + type = .Mouse_Pressed + mouse.btn = to_mouse_btn_from_sokol( sokol_event.mouse_button ) + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_UP: + type = .Mouse_Released + mouse.btn = to_mouse_btn_from_sokol( sokol_event.mouse_button ) + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_SCROLL: + type = .Mouse_Scroll + mouse.scroll = { sokol_event.scroll_x, sokol_event.scroll_y } + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_MOVE: + type = .Mouse_Move + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_ENTER: + type = .Mouse_Enter + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + case .MOUSE_LEAVE: + type = .Mouse_Leave + modifiers = to_modifiers_code_from_sokol( sokol_event.modifiers ) + sokol_app.consume_event() + append_staged_input_events( event ) + + // TODO(Ed): Add support + case .TOUCHES_BEGAN: + case .TOUCHES_MOVED: + case .TOUCHES_ENDED: + case .TOUCHES_CANCELLED: + + case .RESIZED: sokol_app.consume_event() + case .ICONIFIED: sokol_app.consume_event() + case .RESTORED: sokol_app.consume_event() + case .FOCUSED: sokol_app.consume_event() + case .UNFOCUSED: sokol_app.consume_event() + case .SUSPENDED: sokol_app.consume_event() + case .RESUMED: sokol_app.consume_event() + case .QUIT_REQUESTED: sokol_app.consume_event() + case .CLIPBOARD_PASTED: sokol_app.consume_event() + case .FILES_DROPPED: sokol_app.consume_event() + + case .DISPLAY_CHANGED: + log_print_fmt("sokol_app - event: Display changed") + log_print_fmt("refresh rate: %v", sokol_app.refresh_rate()) + monitor_refresh_hz := sokol_app.refresh_rate() + sokol_app.consume_event() + } +} + +//endregion Sokol App + +//region Sokol GFX + +sokol_gfx_alloc :: proc "c" ( size : uint, user_data : rawptr ) -> rawptr { + context = memory.client_memory.sokol_context + // block, error := mem_alloc( int(size), allocator = persistent_slab_allocator() ) + // ensure(error == AllocatorError.None, "sokol_gfx allocation failed") + // return block + // TODO(Ed): Implement + return nil +} + +sokol_gfx_free :: proc "c" ( data : rawptr, user_data : rawptr ) { + context = memory.client_memory.sokol_context + // TODO(Ed): Implement + // free(data, allocator = persistent_slab_allocator() ) +} + +sokol_gfx_log_callback :: proc "c" ( + tag: cstring, + log_level: u32, + log_item_id: u32, + message_or_null: cstring, + line_nr: u32, + filename_or_null: cstring, + user_data: rawptr) +{ + context = memory.client_memory.sokol_context + odin_level : LoggerLevel + switch log_level { + case 0: odin_level = .Fatal + case 1: odin_level = .Error + case 2: odin_level = .Warning + case 3: odin_level = .Info + } + clone_backing: [16 * Kilo]byte + + cloned_msg : string = "" + if message_or_null != nil { + cloned_msg = cstr_to_str_capped(message_or_null, clone_backing[:]) + } + cloned_fname : string = "" + if filename_or_null != nil { + cloned_fname = cstr_to_str_capped(filename_or_null, clone_backing[len(cloned_msg):]) + } + cloned_tag := cstr_to_str_capped(tag, clone_backing[len(cloned_msg) + len(cloned_fname):]) + log_print_fmt( "%-80s %s::%v", cloned_msg, cloned_tag, line_nr, level = odin_level ) +} + +//endregion Sokol GFX diff --git a/code2/sectr/pkg_mappings.odin b/code2/sectr/pkg_mappings.odin index ca2ab64..ed5f1c4 100644 --- a/code2/sectr/pkg_mappings.odin +++ b/code2/sectr/pkg_mappings.odin @@ -19,6 +19,7 @@ import "core:log" LoggerLevel :: log.Level import "core:mem" + AllocatorError :: mem.Allocator_Error // Used strickly for the logger Odin_Arena :: mem.Arena odin_arena_allocator :: mem.arena_allocator @@ -60,14 +61,38 @@ import "core:time" tick_now :: time.tick_now import "codebase:grime" - Logger :: grime.Logger - logger_init :: grime.logger_init - to_odin_logger :: grime.to_odin_logger - + Array :: grime.Array + array_to_slice :: grime.array_to_slice + array_append_array :: grime.array_append_array + array_append_slice :: grime.array_append_slice + array_append_value :: grime.array_append_value + array_back :: grime.array_back + array_clear :: grime.array_clear + // Logging + Logger :: grime.Logger + logger_init :: grime.logger_init + // Memory + mem_alloc :: grime.mem_alloc + mem_copy :: grime.mem_copy + mem_copy_non_overlapping :: grime.mem_copy_non_overlapping + mem_zero :: grime.mem_zero + slice_zero :: grime.slice_zero + // Ring Buffer + FRingBuffer :: grime.FRingBuffer + FRingBufferIterator :: grime.FRingBufferIterator + 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 + iterator_ringbuf_fixed :: grime.iterator_ringbuf_fixed + next_ringbuf_fixed_iterator :: grime.next_ringbuf_fixed_iterator + // Strings + cstr_to_str_capped :: grime.cstr_to_str_capped + to_odin_logger :: grime.to_odin_logger + // Operating System set__scheduler_granularity :: grime.set__scheduler_granularity - grime_set_profiler_module_context :: grime.set_profiler_module_context - grime_set_profiler_thread_buffer :: grime.set_profiler_thread_buffer + // grime_set_profiler_module_context :: grime.set_profiler_module_context + // grime_set_profiler_thread_buffer :: grime.set_profiler_thread_buffer Kilo :: 1024 Mega :: Kilo * 1024 @@ -141,13 +166,24 @@ add :: proc { add_r2f4, add_biv3f4, } - +append :: proc { + array_append_array, + array_append_slice, + array_append_value, +} +array_append :: proc { + array_append_array, + array_append_slice, + array_append_value, +} biv3f4 :: proc { biv3f4_via_f32s, v3f4_to_biv3f4, } bivec :: biv3f4 - +clear :: proc { + array_clear, +} cross :: proc { cross_s, cross_v2, @@ -156,11 +192,9 @@ cross :: proc { cross_v3f4_uv3f4, cross_u3f4_v3f4, } - div :: proc { div_biv3f4_f32, } - dot :: proc { sdot, vdot, @@ -171,75 +205,76 @@ dot :: proc { dot_v3f4_uv3f4, dot_uv3f4_v3f4, } - equal :: proc { equal_r2f4, } - is_power_of_two :: proc { is_power_of_two_u32, // is_power_of_two_uintptr, } - +iterator :: proc { + iterator_ringbuf_fixed, +} mov_avg_exp :: proc { mov_avg_exp_f32, mov_avg_exp_f64, } - mul :: proc { mul_biv3f4, mul_biv3f4_f32, mul_f32_biv3f4, } - join :: proc { join_r2f4, } - inverse_sqrt :: proc { inverse_sqrt_f32, } - +next :: proc { + next_ringbuf_fixed_iterator, +} point3 :: proc { v3f4_to_point3f4, } - pow2 :: proc { pow2_v3f4, } - +peek_back :: proc { + ringbuf_fixed_peak_back, +} +push :: proc { + ringbuf_fixed_push, + ringbuf_fixed_push_slice, +} quatf4 :: proc { quatf4_from_rotor3f4, } - regress :: proc { regress_biv3f4, } - rotor3 :: proc { rotor3f4_via_comps_f4, rotor3f4_via_bv_s_f4, // rotor3f4_via_from_to_v3f4, } - size :: proc { size_r2f4, } - sub :: proc { sub_r2f4, sub_biv3f4, // join_point3_f4, // join_pointflat3_f4, } - +to_slice :: proc { + array_to_slice, +} v2f4 :: proc { v2f4_from_f32s, v2f4_from_scalar, v2f4_from_v2s4, v2s4_from_v2f4, } - v3f4 :: proc { v3f4_via_f32s, biv3f4_to_v3f4, @@ -247,14 +282,12 @@ v3f4 :: proc { pointflat3f4_to_v3f4, uv3f4_to_v3f4, } - v2 :: proc { v2f4_from_f32s, v2f4_from_scalar, v2f4_from_v2s4, v2s4_from_v2f4, } - v3 :: proc { v3f4_via_f32s, biv3f4_to_v3f4, @@ -262,12 +295,14 @@ v3 :: proc { pointflat3f4_to_v3f4, uv3f4_to_v3f4, } - v4 :: proc { uv4f4_to_v4f4, } - wedge :: proc { wedge_v3f4, wedge_biv3f4, } +zero :: proc { + mem_zero, + slice_zero, +} diff --git a/scripts/build.ps1 b/scripts/build.ps1 index c6e0175..3fec489 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -97,6 +97,7 @@ $flag_radlink = '-radlink' $flag_sanitize_address = '-sanitize:address' $flag_sanitize_memory = '-sanitize:memory' $flag_sanitize_thread = '-sanitize:thread' +$flag_show_definables = '-show-defineables' $flag_subsystem = '-subsystem:' $flag_show_debug_messages = '-show-debug-messages' $flag_show_timings = '-show-timings' @@ -233,13 +234,14 @@ push-location $path_root # $build_args += $flag_sanitize_address # $build_args += $flag_sanitize_memory # $build_args += $flag_show_debug_messages + $build_args += $flag_show_definabless $build_args += $flag_show_timings # $build_args += $flag_build_diagnostics # TODO(Ed): Enforce nil default allocator - foreach ($arg in $build_args) { - write-host `t $arg -ForegroundColor Cyan - } + # foreach ($arg in $build_args) { + # write-host `t $arg -ForegroundColor Cyan + # } if ( Test-Path $module_dll) { $module_dll_pre_build_hash = get-filehash -path $module_dll -Algorithm MD5 @@ -301,8 +303,8 @@ push-location $path_root # $build_args += $flag_micro_architecture_native $build_args += $flag_microarch_zen5 $build_args += $flag_thread_count + $CoreCount_Physical - $build_args += $flag_optimize_none - # $build_args += $flag_optimize_minimal + # $build_args += $flag_optimize_none + $build_args += $flag_optimize_minimal # $build_args += $flag_optimize_speed # $build_args += $falg_optimize_aggressive $build_args += $flag_debug @@ -318,11 +320,12 @@ push-location $path_root # $build_args += $flag_sanitize_address # $build_args += $flag_sanitize_memory # $build_args += $flag_build_diagnostics + $build_args += $flag_show_definabless # TODO(Ed): Enforce nil default allocator - foreach ($arg in $build_args) { - write-host `t $arg -ForegroundColor Cyan - } + # foreach ($arg in $build_args) { + # write-host `t $arg -ForegroundColor Cyan + # } if ( Test-Path $executable) { $executable_pre_build_hash = get-filehash -path $executable -Algorithm MD5