misc changes
mostly added kt1l from watl exercise
This commit is contained in:
@@ -10,6 +10,8 @@ package vefontcache
|
||||
|
||||
There was an attempt at an optimization pass but the directives done here (other than force_inline)
|
||||
are marginal changes at best.
|
||||
|
||||
TODO(Ed): Odin's map rehashes integer values. Maybe bring in a custom KeyTable?
|
||||
*/
|
||||
|
||||
// 16-bit hashing was attempted, however it seems to get collisions with djb8_hash_16
|
||||
|
3
code/font/vefontcache/kt1cx.odin
Normal file
3
code/font/vefontcache/kt1cx.odin
Normal file
@@ -0,0 +1,3 @@
|
||||
package vefontcache
|
||||
|
||||
// TODO(Ed): Bring in KT1CX and see how it performs.
|
@@ -3,6 +3,8 @@ See: https://github.com/Ed94/VEFontCache-Odin
|
||||
*/
|
||||
package vefontcache
|
||||
|
||||
// TODO(Ed): Provide a way to give the user a memory footprint query for all dyanmic allocations.
|
||||
|
||||
// See: mappings.odin for profiling hookup
|
||||
DISABLE_PROFILING :: true
|
||||
ENABLE_OVERSIZED_GLYPHS :: true
|
||||
|
@@ -4,6 +4,6 @@ djb8_hash_32 :: #force_inline proc "contextless" ( hash : ^u32, bytes : []byte )
|
||||
for value in bytes do (hash^) = (( (hash^) << 8) + (hash^) ) + u32(value)
|
||||
}
|
||||
|
||||
djb8_hash :: #force_inline proc "contextless" ( hash : ^u64, bytes : []byte ) {
|
||||
hash64_djb8 :: #force_inline proc "contextless" ( hash : ^u64, bytes : []byte ) {
|
||||
for value in bytes do (hash^) = (( (hash^) << 8) + (hash^) ) + u64(value)
|
||||
}
|
||||
|
@@ -1,48 +1,72 @@
|
||||
package grime
|
||||
|
||||
when (false) {
|
||||
// Key Table 1-Layer Linear (KT1L)
|
||||
|
||||
KT1L_Slot :: struct($Type: typeid) {
|
||||
key: u64,
|
||||
value: Type,
|
||||
KT1L_Use_TypeErased :: true
|
||||
|
||||
KT1L_Slot :: struct($KeyType, $ValueType: typeid) {
|
||||
key: KeyType,
|
||||
value: ValueType,
|
||||
}
|
||||
KT1L_Meta :: struct {
|
||||
slot_size: uintptr,
|
||||
kt_value_offset: uintptr,
|
||||
type_width: uintptr,
|
||||
type_name: string,
|
||||
type: typeid,
|
||||
}
|
||||
kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator = context.allocator, values: []byte, num_values: int, m: KT1L_Meta) {
|
||||
kt1l_64_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator, values: []byte, num_values: int, m: KT1L_Meta) {
|
||||
assert(kt != nil)
|
||||
if num_values == 0 { return }
|
||||
table_size_bytes := num_values * int(m.slot_size)
|
||||
err : AllocatorError
|
||||
kt^, err = alloc_bytes(table_size_bytes, allocator = backing)
|
||||
alloc_error: AllocatorError
|
||||
kt^, alloc_error = alloc_bytes(table_size_bytes, allocator = backing)
|
||||
assert(alloc_error == .None)
|
||||
slice_assert(kt ^)
|
||||
kt_raw : Raw_Slice = transmute(Raw_Slice) kt^
|
||||
for cursor in 0 ..< cast(uintptr) num_values {
|
||||
slot_offset := cursor * m.slot_size
|
||||
slot_cursor := uintptr(kt_raw.data) + slot_offset
|
||||
slot_key := cast(^u64) slot_cursor
|
||||
slot_value := transmute([]byte) Raw_Slice { cast([^]byte) (slot_cursor + m.kt_value_offset), int(m.type_width)}
|
||||
a2_offset := cursor * m.type_width * 2
|
||||
a2_cursor := uintptr(& values[a2_offset])
|
||||
a2_key := (transmute(^[]byte) a2_cursor) ^
|
||||
a2_value := transmute([]byte) Raw_Slice { rawptr(a2_cursor + m.type_width), int(m.type_width) }
|
||||
copy(slot_value, a2_value)
|
||||
slot_key^ = 0; hash64_djb8(slot_key, a2_key)
|
||||
kt_raw : SliceByte = transmute(SliceByte) kt^
|
||||
for id in 0 ..< cast(uintptr) num_values {
|
||||
slot_offset := id * m.slot_size // slot id
|
||||
slot_cursor := kt_raw.data[slot_offset:] // slots[id] type: KT1L_<Type>
|
||||
slot_key := cast(^u64) slot_cursor // slots[id].key type: U64
|
||||
slot_value := slice(slot_cursor[m.kt_value_offset:], m.type_width) // slots[id].value type: <Type>
|
||||
a2_offset := id * m.type_width * 2 // a2 entry id
|
||||
a2_cursor := cursor(values)[a2_offset:] // a2_entries[id] type: A2_<Type>
|
||||
a2_key := (transmute(^[]byte) a2_cursor) ^ // a2_entries[id].key type: <Type>
|
||||
a2_value := slice(a2_cursor[m.type_width:], m.type_width) // a2_entries[id].value type: <Type>
|
||||
copy(slot_value, a2_value) // slots[id].value = a2_entries[id].value
|
||||
slot_key^ = 0; hash64_djb8(slot_key, a2_key) // slots[id].key = hash64_djb8(a2_entries[id].key)
|
||||
}
|
||||
kt_raw.len = num_values
|
||||
}
|
||||
kt1l_populate_slice_a2 :: proc($Type: typeid, kt: ^[]KT1L_Slot(Type), backing: AllocatorInfo, values: [][2]Type) {
|
||||
assert(kt != nil)
|
||||
values_bytes := transmute([]byte) Raw_Slice{data = raw_data(values), len = len(values) * size_of([2]Type)}
|
||||
kt1l_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), {
|
||||
slot_size = size_of(KT1L_Slot(Type)),
|
||||
kt_value_offset = offset_of(KT1L_Slot(Type), KT1L_Slot(Type).value),
|
||||
type_width = size_of(Type),
|
||||
type_name = #type_string(Type),
|
||||
})
|
||||
when KT1L_Use_TypeErased
|
||||
{
|
||||
kt1l_64_populate_slice_a2 :: proc(kt: ^[]KT1L_Slot(u64, $Type), values: [][2]Type, backing:= context.allocator) {
|
||||
assert(kt != nil)
|
||||
values_bytes := slice(transmute([^]u8) raw_data(values), len(values) * size_of([2]Type))
|
||||
kt1l_64_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), {
|
||||
slot_size = size_of(KT1L_Slot(Type)),
|
||||
kt_value_offset = offset_of(KT1L_Slot(Type), value),
|
||||
type_width = size_of(Type),
|
||||
type = Type,
|
||||
})
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kt1l_64_populate_slice_a2 :: proc(kt: ^[]KT1L_Slot(u64, $Type), values: [][2]Type, backing:= context.allocator) {
|
||||
assert(kt != nil)
|
||||
if len(values) == 0 { retrurn }
|
||||
kt, alloc_error = make_slice([]KT1L_Slot(u64, Type), len(values), allocator = backing)
|
||||
assert(alloc_error == .None)
|
||||
slice_assert(kt)
|
||||
for id in 0 ..< len(values) {
|
||||
slot := & kt[id]
|
||||
hash64_djb8(& slot.key, values[id][0])
|
||||
slot.value = values[id][1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(Ed): Move ot package mappings
|
||||
kt1l_populate_slice_a2 :: proc {
|
||||
kt1l_64_populate_slice_a2,
|
||||
}
|
||||
|
@@ -2,17 +2,17 @@ package grime
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
reload_array :: proc( self : ^[dynamic]$Type, allocator : Allocator ) {
|
||||
reload_array :: proc(self: ^[dynamic]$Type, allocator: Allocator) {
|
||||
raw := transmute( ^runtime.Raw_Dynamic_Array) self
|
||||
raw.allocator = allocator
|
||||
}
|
||||
|
||||
reload_queue :: proc( self : ^Queue($Type), allocator : Allocator ) {
|
||||
reload_queue :: proc(self: ^Queue($Type), allocator: Allocator) {
|
||||
raw_array := transmute( ^runtime.Raw_Dynamic_Array) self.data
|
||||
raw_array.allocator = allocator
|
||||
}
|
||||
|
||||
reload_map :: proc( self : ^map [$KeyType] $EntryType, allocator : Allocator ) {
|
||||
reload_map :: proc(self: ^map [$KeyType] $EntryType, allocator: Allocator) {
|
||||
raw := transmute( ^runtime.Raw_Map) self
|
||||
raw.allocator = allocator
|
||||
}
|
||||
|
@@ -99,3 +99,5 @@ swap :: #force_inline proc "contextless" ( a, b : ^ $Type ) -> ( ^ Type, ^ Type
|
||||
to_bytes :: #force_inline proc "contextless" ( typed_block : ^$Type ) -> []byte {
|
||||
return slice_ptr( transmute(^byte) typed_block, size_of(Type) )
|
||||
}
|
||||
|
||||
ptr_cursor :: #force_inline proc "contextless" (ptr: ^$Type) -> [^]Type { return transmute([^]Type) ptr }
|
||||
|
@@ -6,10 +6,12 @@ import "base:builtin"
|
||||
copy :: builtin.copy
|
||||
|
||||
import "base:intrinsics"
|
||||
mem_zero :: intrinsics.mem_zero
|
||||
ptr_sub :: intrinsics.ptr_sub
|
||||
type_has_field :: intrinsics.type_has_field
|
||||
type_elem_type :: intrinsics.type_elem_type
|
||||
mem_zero :: intrinsics.mem_zero
|
||||
mem_copy_non_overlapping :: intrinsics.mem_copy_non_overlapping
|
||||
mem_copy :: intrinsics.mem_copy
|
||||
ptr_sub :: intrinsics.ptr_sub
|
||||
type_has_field :: intrinsics.type_has_field
|
||||
type_elem_type :: intrinsics.type_elem_type
|
||||
|
||||
import "base:runtime"
|
||||
Byte :: runtime.Byte
|
||||
@@ -144,6 +146,12 @@ array_append_at :: proc {
|
||||
array_append_at_value,
|
||||
}
|
||||
|
||||
cursor :: proc {
|
||||
ptr_cursor,
|
||||
slice_cursor,
|
||||
string_cursor,
|
||||
}
|
||||
|
||||
is_power_of_two :: proc {
|
||||
is_power_of_two_u32,
|
||||
is_power_of_two_uintptr,
|
||||
|
36
code/grime/slice.odin
Normal file
36
code/grime/slice.odin
Normal file
@@ -0,0 +1,36 @@
|
||||
package grime
|
||||
|
||||
SliceByte :: struct {
|
||||
data: [^]byte,
|
||||
len: int
|
||||
}
|
||||
SliceRaw :: struct ($Type: typeid) {
|
||||
data: [^]Type,
|
||||
len: int,
|
||||
}
|
||||
slice :: #force_inline proc "contextless" (s: [^] $Type, num: $Some_Integer) -> [ ]Type { return transmute([]Type) SliceRaw(Type) { s, cast(int) num } }
|
||||
slice_cursor :: #force_inline proc "contextless" (s: []$Type) -> [^]Type { return transmute([^]Type) raw_data(s) }
|
||||
slice_assert :: #force_inline proc (s: $SliceType / []$Type) {
|
||||
assert(len(s) > 0)
|
||||
assert(s != nil)
|
||||
}
|
||||
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return & cursor(s)[len(s)] }
|
||||
|
||||
@(require_results) slice_to_bytes :: proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
|
||||
@(require_results) slice_raw :: proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
|
||||
|
||||
slice_zero :: proc "contextless" (data: $SliceType / []$Type) { memory_zero(raw_data(data), size_of(Type) * len(data)) }
|
||||
slice_copy :: 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))
|
||||
}
|
||||
return n
|
||||
}
|
||||
slice_copy_non_overlapping :: proc "contextless" (dst, src: $SliceType / []$Type) -> int {
|
||||
n := max(0, min(len(dst), len(src)))
|
||||
if n > 0 {
|
||||
mem_copy_non_overlapping(raw_data(dst), raw_data(src), n * size_of(Type))
|
||||
}
|
||||
return n
|
||||
}
|
10
code/grime/strings.odin
Normal file
10
code/grime/strings.odin
Normal file
@@ -0,0 +1,10 @@
|
||||
package grime
|
||||
|
||||
Raw_String :: struct {
|
||||
data: [^]byte,
|
||||
len: int,
|
||||
}
|
||||
string_cursor :: proc(s: string) -> [^]u8 { return slice_cursor(transmute([]byte) s) }
|
||||
string_copy :: proc(dst, src: string) { slice_copy (transmute([]byte) dst, transmute([]byte) src) }
|
||||
string_end :: proc(s: string) -> ^u8 { return slice_end (transmute([]byte) s) }
|
||||
string_assert :: proc(s: string) { slice_assert(transmute([]byte) s) }
|
@@ -270,7 +270,7 @@ import "codebase:grime"
|
||||
file_rewind :: grime.file_rewind
|
||||
|
||||
// hashing
|
||||
djb8_hash :: grime.djb8_hash
|
||||
hash64_djb8 :: grime.hash64_djb8
|
||||
|
||||
// linked lists
|
||||
SLL_Node :: grime.SLL_Node
|
||||
@@ -664,7 +664,7 @@ vec2 :: proc {
|
||||
vec2_from_scalar,
|
||||
// vec2_64_from_vec2,
|
||||
vec2_from_vec2i,
|
||||
vec2i_from_vec2
|
||||
vec2i_from_vec2,
|
||||
}
|
||||
|
||||
vec3 :: proc {
|
||||
|
Reference in New Issue
Block a user