Code2 Progress: more sokol stuff

This commit is contained in:
2025-10-18 15:01:19 -04:00
parent 5a3b8ef3b9
commit 62979b480e
12 changed files with 388 additions and 173 deletions

View File

@@ -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,

View File

@@ -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))

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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,

View File

@@ -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)) } }