made a new hashtable container: HMapChained
Will be used isntead of the zpl in some places
This commit is contained in:
parent
12c99bee26
commit
26771ff2fd
@ -13,6 +13,7 @@ import "core:prof/spall"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
Path_Assets :: "../assets/"
|
||||
Path_Shaders :: "../shaders/"
|
||||
Path_Input_Replay :: "scratch.sectr_replay"
|
||||
|
||||
Persistent_Slab_DBG_Name := "Peristent Slab"
|
||||
@ -276,12 +277,10 @@ reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem,
|
||||
|
||||
slab_reload( persistent_slab, persistent_allocator() )
|
||||
|
||||
font_provider_data.font_cache.hashes.backing = persistent_slab_allocator()
|
||||
font_provider_data.font_cache.entries.backing = persistent_slab_allocator()
|
||||
hmap_chained_reload( font_provider_data.font_cache, persistent_slab_allocator())
|
||||
|
||||
slab_reload( string_cache.slab, persistent_allocator() )
|
||||
string_cache.table.hashes.backing = persistent_slab_allocator()
|
||||
string_cache.table.entries.backing = persistent_slab_allocator()
|
||||
zpl_hmap_reload( & string_cache.table, persistent_slab_allocator())
|
||||
|
||||
slab_reload( frame_slab, frame_allocator())
|
||||
slab_reload( transient_slab, transient_allocator())
|
||||
|
@ -118,7 +118,7 @@ logger_interface :: proc(
|
||||
}
|
||||
|
||||
log :: proc( msg : string, level := LogLevel.Info, loc := #caller_location ) {
|
||||
core_log.logf( level, msg, location = loc )
|
||||
core_log.log( level, msg, location = loc )
|
||||
}
|
||||
|
||||
logf :: proc( fmt : string, args : ..any, level := LogLevel.Info, loc := #caller_location ) {
|
||||
|
@ -55,7 +55,8 @@ FontDef :: struct {
|
||||
}
|
||||
|
||||
FontProviderData :: struct {
|
||||
font_cache : HMapZPL(FontDef),
|
||||
// font_cache : HMapZPL(FontDef),
|
||||
font_cache : HMapChainedPtr(FontDef),
|
||||
}
|
||||
|
||||
font_provider_startup :: proc()
|
||||
@ -65,7 +66,7 @@ font_provider_startup :: proc()
|
||||
font_provider_data := & get_state().font_provider_data; using font_provider_data
|
||||
|
||||
font_cache_alloc_error : AllocatorError
|
||||
font_cache, font_cache_alloc_error = zpl_hmap_init_reserve( FontDef, persistent_slab_allocator(), 2 )
|
||||
font_cache, font_cache_alloc_error = hmap_chained_init(FontDef, hmap_closest_prime(1 * Kilo), persistent_slab_allocator() )
|
||||
verify( font_cache_alloc_error == AllocatorError.None, "Failed to allocate font_cache" )
|
||||
|
||||
log("font_cache created")
|
||||
@ -76,10 +77,11 @@ font_provider_shutdown :: proc()
|
||||
{
|
||||
font_provider_data := & get_state().font_provider_data; using font_provider_data
|
||||
|
||||
for id in 0 ..< font_cache.entries.num
|
||||
for & entry in font_cache.lookup
|
||||
{
|
||||
def := & font_cache.entries.data[id].value
|
||||
if entry == nil do continue
|
||||
|
||||
def := entry.value
|
||||
for & px_render in def.size_table {
|
||||
using px_render
|
||||
rl.UnloadFontData( glyphs, count )
|
||||
@ -117,11 +119,10 @@ font_load :: proc( path_file : string,
|
||||
}
|
||||
|
||||
key := cast(u64) crc32( transmute([]byte) desired_id )
|
||||
def, set_error := zpl_hmap_set( & font_cache, key,FontDef {} )
|
||||
def, set_error := hmap_chained_set(font_cache, key, FontDef{})
|
||||
verify( set_error == AllocatorError.None, "Failed to add new font entry to cache" )
|
||||
|
||||
def.path_file = path_file
|
||||
// def.data = font_data
|
||||
def.default_size = i32(points_to_pixels(default_size))
|
||||
|
||||
// TODO(Ed): this is slow & eats quite a bit of memory early on. Setup a more on demand load for a specific size.
|
||||
@ -175,7 +176,7 @@ to_rl_Font :: proc( id : FontID, size := Font_Use_Default_Size ) -> rl.Font
|
||||
|
||||
even_size := math.round(size * (1.0/f32(Font_Size_Interval))) * f32(Font_Size_Interval)
|
||||
size := clamp( i32( even_size), 4, Font_Largest_Px_Size )
|
||||
def := zpl_hmap_get( & font_cache, id.key )
|
||||
def := hmap_chained_get( font_cache, id.key )
|
||||
size = size if size != i32(Font_Use_Default_Size) else def.default_size
|
||||
|
||||
id := (size / Font_Size_Interval) + (size % Font_Size_Interval)
|
||||
|
@ -38,11 +38,11 @@ array_underlying_slice :: proc(slice: []($ Type)) -> Array(Type)
|
||||
return array_ptr ^
|
||||
}
|
||||
|
||||
array_to_slice_num :: proc( using self : Array($ Type) ) -> []Type {
|
||||
array_to_slice :: proc( using self : Array($ Type) ) -> []Type {
|
||||
return slice_ptr( data, int(num) )
|
||||
}
|
||||
|
||||
array_to_slice :: proc( using self : Array($ Type) ) -> []Type {
|
||||
array_to_slice_capacity :: proc( using self : Array($ Type) ) -> []Type {
|
||||
return slice_ptr( data, int(capacity))
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ array_init_reserve :: proc
|
||||
// log( str_fmt_tmp("array reserved: %d", header_size + int(capacity) * size_of(Type) ))
|
||||
if alloc_error != AllocatorError.None do return
|
||||
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem;
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem
|
||||
result.backing = allocator
|
||||
// result.dbg_name = dbg_name
|
||||
result.fixed_cap = fixed_cap
|
||||
|
@ -3,7 +3,7 @@ package sectr
|
||||
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
// Test
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
// TODO(Ed) : Roll own hashmap implementation (open-addressing, round-robin possibly)
|
||||
package sectr
|
||||
|
||||
|
224
code/grime_hashmap_chained.odin
Normal file
224
code/grime_hashmap_chained.odin
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
Separate chaining hashtable with tombstone (vacancy aware)
|
||||
|
||||
This is an alternative to odin's map and the zpl hashtable I first used for this codebase.
|
||||
I haven't felt the need to go back to dealing with odin's map for my edge case hot reload/memory replay failure.
|
||||
|
||||
So this is a hahstable loosely based at what I saw in the raddbg codebase.
|
||||
It uses a fixed-size lookup table for the base layer of entries that can be chained.
|
||||
Each slot keeps track of its vacancy (tombstone, is occupied).
|
||||
If its occupied a new slot is chained using the fixed bucket-size pool allocator which will have its blocks sized to the type of the table.
|
||||
|
||||
This is ideal for tables have an indeterminate scope for how entires are added,
|
||||
and direct pointers are kept across the codebase instead of a key to the slot.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import "core:mem"
|
||||
|
||||
HTable_Minimum_Capacity :: 4 * Kilobyte
|
||||
|
||||
HMapChainedSlot :: struct( $Type : typeid ) {
|
||||
using links : DLL_NodePN(HMapChainedSlot(Type)),
|
||||
value : Type,
|
||||
key : u64,
|
||||
occupied : b32,
|
||||
}
|
||||
|
||||
HMapChained :: struct( $ Type : typeid ) {
|
||||
pool : Pool,
|
||||
lookup : [] ^HMapChainedSlot(Type),
|
||||
}
|
||||
|
||||
HMapChainedPtr :: struct( $ Type : typeid) {
|
||||
using header : ^HMapChained(Type),
|
||||
}
|
||||
|
||||
// Provides the nearest prime number value for the given capacity
|
||||
hmap_closest_prime :: proc( capacity : uint ) -> uint
|
||||
{
|
||||
prime_table : []uint = {
|
||||
53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
|
||||
49157, 98317, 196613, 393241, 786433, 1572869, 3145739,
|
||||
6291469, 12582917, 25165843, 50331653, 100663319,
|
||||
201326611, 402653189, 805306457, 1610612741, 3221225473, 6442450941
|
||||
};
|
||||
for slot in prime_table {
|
||||
if slot >= capacity {
|
||||
return slot
|
||||
}
|
||||
}
|
||||
return prime_table[len(prime_table) - 1]
|
||||
}
|
||||
|
||||
hmap_chained_init :: proc( $Type : typeid, lookup_capacity : uint, allocator : Allocator,
|
||||
pool_bucket_cap : uint = 0,
|
||||
pool_bucket_reserve_num : uint = 0,
|
||||
pool_alignment : uint = mem.DEFAULT_ALIGNMENT,
|
||||
dbg_name : string = ""
|
||||
) -> (table : HMapChainedPtr(Type), error : AllocatorError)
|
||||
{
|
||||
header_size := size_of(HMapChainedPtr(Type))
|
||||
size := header_size + int(lookup_capacity) * size_of( ^HMapChainedSlot(Type)) + size_of(int)
|
||||
|
||||
raw_mem : rawptr
|
||||
raw_mem, error = alloc( size, allocator = allocator )
|
||||
if error != AllocatorError.None do return
|
||||
|
||||
table.header = cast( ^HMapChained(Type)) raw_mem
|
||||
table.pool, error = pool_init(
|
||||
should_zero_buckets = false,
|
||||
block_size = size_of(HMapChainedSlot(Type)),
|
||||
bucket_capacity = pool_bucket_cap,
|
||||
bucket_reserve_num = pool_bucket_reserve_num,
|
||||
alignment = pool_alignment,
|
||||
allocator = allocator,
|
||||
dbg_name = str_intern(str_fmt_tmp("%: pool", dbg_name)).str
|
||||
)
|
||||
data := transmute([^] ^HMapChainedSlot(Type)) (transmute( [^]HMapChained(Type)) table.header)[1:]
|
||||
table.lookup = slice_ptr( data, int(lookup_capacity) )
|
||||
return
|
||||
}
|
||||
|
||||
hmap_chained_clear :: proc( using self : HMapChainedPtr($Type))
|
||||
{
|
||||
for slot in lookup
|
||||
{
|
||||
if slot == nil {
|
||||
continue
|
||||
}
|
||||
for probe_slot = slot.next; probe_slot != nil; probe_slot = probe_slot.next {
|
||||
slot.occupied = false
|
||||
}
|
||||
slot.occupied = false
|
||||
}
|
||||
}
|
||||
|
||||
hmap_chained_destroy :: proc( using self : ^HMapChainedPtr($Type)) {
|
||||
pool_destroy( pool )
|
||||
free( self.header, backing)
|
||||
self = nil
|
||||
}
|
||||
|
||||
hmap_chained_lookup_id :: #force_inline proc( using self : HMapChainedPtr($Type), key : u64 ) -> u64
|
||||
{
|
||||
hash_index := key % u64( len(lookup) )
|
||||
return hash_index
|
||||
}
|
||||
|
||||
hmap_chained_get :: proc( using self : HMapChainedPtr($Type), key : u64) -> ^Type
|
||||
{
|
||||
// profile(#procedure)
|
||||
surface_slot := lookup[hmap_chained_lookup_id(self, key)]
|
||||
|
||||
if surface_slot == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if surface_slot.occupied && surface_slot.key == key {
|
||||
return & surface_slot.value
|
||||
}
|
||||
|
||||
for slot := surface_slot.next; slot != nil; slot = slot.next {
|
||||
if slot.occupied && slot.key == key {
|
||||
return & surface_slot.value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
hmap_chained_reload :: proc( self : HMapChainedPtr($Type), allocator : Allocator )
|
||||
{
|
||||
pool_reload(self.pool, allocator)
|
||||
}
|
||||
|
||||
// Returns true if an slot was actually found and marked as vacant
|
||||
// Entries already found to be vacant will not return true
|
||||
hmap_chained_remove :: proc( self : HMapChainedPtr($Type), key : u64 ) -> b32
|
||||
{
|
||||
surface_slot := lookup[hmap_chained_lookup_id(self, key)]
|
||||
|
||||
if surface_slot == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if surface_slot.occupied && surface_slot.key == key {
|
||||
surface_slot.occupied = false
|
||||
return true
|
||||
}
|
||||
|
||||
for slot := surface_slot.next; slot != nil; slot.next
|
||||
{
|
||||
if slot.occupied && slot.key == key {
|
||||
slot.occupied = false
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Sets the value to a vacant slot
|
||||
// Will preemptively allocate the next slot in the hashtable if its null for the slot.
|
||||
hmap_chained_set :: proc( using self : HMapChainedPtr($Type), key : u64, value : Type ) -> (^ Type, AllocatorError)
|
||||
{
|
||||
hash_index := hmap_chained_lookup_id(self, key)
|
||||
surface_slot := lookup[hash_index]
|
||||
set_slot :: #force_inline proc( using self : HMapChainedPtr(Type),
|
||||
slot : ^HMapChainedSlot(Type),
|
||||
key : u64,
|
||||
value : Type
|
||||
) -> (^ Type, AllocatorError )
|
||||
{
|
||||
error := AllocatorError.None
|
||||
if slot.next == nil {
|
||||
block : []byte
|
||||
block, error = pool_grab(pool)
|
||||
next := transmute( ^HMapChainedSlot(Type)) & block[0]
|
||||
slot.next = next
|
||||
next.prev = slot
|
||||
}
|
||||
slot.key = key
|
||||
slot.value = value
|
||||
slot.occupied = true
|
||||
return & slot.value, error
|
||||
}
|
||||
|
||||
if surface_slot == nil {
|
||||
block, error := pool_grab(pool)
|
||||
surface_slot := transmute( ^HMapChainedSlot(Type)) & block[0]
|
||||
surface_slot.key = key
|
||||
surface_slot.value = value
|
||||
surface_slot.occupied = true
|
||||
if error != AllocatorError.None {
|
||||
ensure(error != AllocatorError.None, "Allocation failure for chained slot in hash table")
|
||||
return nil, error
|
||||
}
|
||||
lookup[hash_index] = surface_slot
|
||||
|
||||
block, error = pool_grab(pool)
|
||||
next := transmute( ^HMapChainedSlot(Type)) & block[0]
|
||||
surface_slot.next = next
|
||||
next.prev = surface_slot
|
||||
return & surface_slot.value, error
|
||||
}
|
||||
|
||||
if ! surface_slot.occupied
|
||||
{
|
||||
result, error := set_slot( self, surface_slot, key, value)
|
||||
return result, error
|
||||
}
|
||||
|
||||
slot := surface_slot.next
|
||||
for ; slot != nil; slot = slot.next
|
||||
{
|
||||
if !slot.occupied
|
||||
{
|
||||
result, error := set_slot( self, surface_slot, key, value)
|
||||
return result, error
|
||||
}
|
||||
}
|
||||
ensure(false, "Somehow got to a null slot that wasn't preemptively allocated from a previus set")
|
||||
return nil, AllocatorError.None
|
||||
}
|
@ -4,12 +4,11 @@ The only reason I may need this is due to issues with allocator callbacks or som
|
||||
with hot-reloads...
|
||||
|
||||
This implementation uses two ZPL-Based Arrays to hold entires and the actual hash table.
|
||||
Its algorithim isn't that great, removal of elements is very expensive.
|
||||
Growing the hashtable doesn't do a resize on the original arrays properly, leading to completely discarded memory.
|
||||
Its recommended to use something closer to raddbg's implementation for greater flexibility.
|
||||
Instead of using separate chains, it maintains linked entries within the array.
|
||||
Each entry contains a next field, which is an index pointing to the next entry in the same array.
|
||||
|
||||
This should only be used if you want the hashtable to also store the values
|
||||
and an open-addressing hashtable is for some reason not desired.
|
||||
Growing this hashtable is destructive, so it should usually be kept to a fixed-size unless
|
||||
the populating operations only occur in one place and from then on its read-only.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
@ -36,8 +35,8 @@ HMapZPL_Entry :: struct ( $ Type : typeid) {
|
||||
}
|
||||
|
||||
HMapZPL :: struct ( $ Type : typeid ) {
|
||||
hashes : Array( i64 ),
|
||||
entries : Array( HMapZPL_Entry(Type) ),
|
||||
table : Array( i64 ),
|
||||
entries : Array( HMapZPL_Entry(Type) ),
|
||||
}
|
||||
|
||||
zpl_hmap_init :: proc( $ Type : typeid, allocator : Allocator ) -> ( HMapZPL( Type), AllocatorError ) {
|
||||
@ -48,15 +47,15 @@ zpl_hmap_init_reserve :: proc
|
||||
( $ Type : typeid, allocator : Allocator, num : u64, dbg_name : string = "" ) -> ( HMapZPL( Type), AllocatorError )
|
||||
{
|
||||
result : HMapZPL(Type)
|
||||
hashes_result, entries_result : AllocatorError
|
||||
table_result, entries_result : AllocatorError
|
||||
|
||||
result.hashes, hashes_result = array_init_reserve( i64, allocator, num, dbg_name = dbg_name )
|
||||
if hashes_result != AllocatorError.None {
|
||||
ensure( false, "Failed to allocate hashes array" )
|
||||
return result, hashes_result
|
||||
result.table, table_result = array_init_reserve( i64, allocator, num, dbg_name = dbg_name )
|
||||
if table_result != AllocatorError.None {
|
||||
ensure( false, "Failed to allocate table array" )
|
||||
return result, table_result
|
||||
}
|
||||
array_resize( & result.hashes, num )
|
||||
slice.fill( slice_ptr( result.hashes.data, cast(int) result.hashes.num), -1 )
|
||||
array_resize( & result.table, num )
|
||||
slice.fill( slice_ptr( result.table.data, cast(int) result.table.num), -1 )
|
||||
|
||||
result.entries, entries_result = array_init_reserve( HMapZPL_Entry(Type), allocator, num, dbg_name = dbg_name )
|
||||
if entries_result != AllocatorError.None {
|
||||
@ -67,17 +66,17 @@ zpl_hmap_init_reserve :: proc
|
||||
}
|
||||
|
||||
zpl_hmap_clear :: proc( using self : ^ HMapZPL( $ Type ) ) {
|
||||
for id := 0; id < hashes.num; id += 1 {
|
||||
hashes[id] = -1
|
||||
for id := 0; id < table.num; id += 1 {
|
||||
table[id] = -1
|
||||
}
|
||||
|
||||
array_clear( hashes )
|
||||
array_clear( table )
|
||||
array_clear( entries )
|
||||
}
|
||||
|
||||
zpl_hmap_destroy :: proc( using self : ^ HMapZPL( $ Type ) ) {
|
||||
if hashes.data != nil && hashes.capacity > 0 {
|
||||
array_free( hashes )
|
||||
if table.data != nil && table.capacity > 0 {
|
||||
array_free( table )
|
||||
array_free( entries )
|
||||
}
|
||||
}
|
||||
@ -119,7 +118,7 @@ zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE
|
||||
ensure( false, "ZPL HMAP IS REHASHING" )
|
||||
last_added_index : i64
|
||||
|
||||
new_ht, init_result := zpl_hmap_init_reserve( Type, ht.hashes.backing, new_num, ht.hashes.dbg_name )
|
||||
new_ht, init_result := zpl_hmap_init_reserve( Type, ht.table.backing, new_num, ht.table.dbg_name )
|
||||
if init_result != AllocatorError.None {
|
||||
ensure( false, "New zpl_hmap failed to allocate" )
|
||||
return init_result
|
||||
@ -133,7 +132,7 @@ zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE
|
||||
last_added_index = zpl_hmap_add_entry( & new_ht, entry.key )
|
||||
|
||||
if find_result.prev_index < 0 {
|
||||
new_ht.hashes.data[ find_result.hash_index ] = last_added_index
|
||||
new_ht.table.data[ find_result.hash_index ] = last_added_index
|
||||
}
|
||||
else {
|
||||
new_ht.entries.data[ find_result.prev_index ].next = last_added_index
|
||||
@ -154,15 +153,15 @@ zpl_hmap_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) )
|
||||
for id := 0; id < entries.num; id += 1 {
|
||||
entries[id].Next = -1;
|
||||
}
|
||||
for id := 0; id < hashes.num; id += 1 {
|
||||
hashes[id] = -1
|
||||
for id := 0; id < table.num; id += 1 {
|
||||
table[id] = -1
|
||||
}
|
||||
for id := 0; id < entries.num; id += 1 {
|
||||
entry := & entries[id]
|
||||
find_result := zpl_hmap_find( entry.key )
|
||||
|
||||
if find_result.prev_index < 0 {
|
||||
hashes[ find_result.hash_index ] = id
|
||||
table[ find_result.hash_index ] = id
|
||||
}
|
||||
else {
|
||||
entries[ find_result.prev_index ].next = id
|
||||
@ -170,6 +169,12 @@ zpl_hmap_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) )
|
||||
}
|
||||
}
|
||||
|
||||
// Used when the address space of the allocator changes and the backing reference must be updated
|
||||
zpl_hmap_reload :: proc( using self : ^HMapZPL($Type), new_backing : Allocator ) {
|
||||
table.backing = new_backing
|
||||
entries.backing = new_backing
|
||||
}
|
||||
|
||||
zpl_hmap_remove :: proc( self : ^ HMapZPL( $ Type ), key : u64 ) {
|
||||
find_result := zpl_hmap_find( key )
|
||||
|
||||
@ -208,7 +213,7 @@ zpl_hmap_set :: proc( using self : ^ HMapZPL( $ Type), key : u64, value : Type )
|
||||
entries.data[ find_result.prev_index ].next = id
|
||||
}
|
||||
else {
|
||||
hashes.data[ find_result.hash_index ] = id
|
||||
table.data[ find_result.hash_index ] = id
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,8 +228,8 @@ zpl_hmap_set :: proc( using self : ^ HMapZPL( $ Type), key : u64, value : Type )
|
||||
}
|
||||
|
||||
zpl_hmap_slot :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 {
|
||||
for id : i64 = 0; id < hashes.num; id += 1 {
|
||||
if hashes.data[id] == key {
|
||||
for id : i64 = 0; id < table.num; id += 1 {
|
||||
if table.data[id] == key {
|
||||
return id
|
||||
}
|
||||
}
|
||||
@ -243,9 +248,9 @@ zpl_hmap_find :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> HMapZPL_F
|
||||
// profile(#procedure)
|
||||
result : HMapZPL_FindResult = { -1, -1, -1 }
|
||||
|
||||
if hashes.num > 0 {
|
||||
result.hash_index = cast(i64)( key % hashes.num )
|
||||
result.entry_index = hashes.data[ result.hash_index ]
|
||||
if table.num > 0 {
|
||||
result.hash_index = cast(i64)( key % table.num )
|
||||
result.entry_index = table.data[ result.hash_index ]
|
||||
|
||||
verify( result.entry_index < i64(entries.num), "Entry index is larger than the number of entries" )
|
||||
|
||||
@ -263,7 +268,7 @@ zpl_hmap_find :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> HMapZPL_F
|
||||
}
|
||||
|
||||
zpl_hmap_full :: proc( using self : ^ HMapZPL( $ Type) ) -> b32 {
|
||||
critical_load := u64(HMapZPL_CritialLoadScale * cast(f64) hashes.num)
|
||||
critical_load := u64(HMapZPL_CritialLoadScale * cast(f64) table.num)
|
||||
result : b32 = entries.num > critical_load
|
||||
return result
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ package sectr
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:mem/virtual"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
|
||||
kilobytes :: #force_inline proc "contextless" ( kb : $ integer_type ) -> integer_type {
|
||||
|
@ -113,7 +113,7 @@ memtracker_unregister :: proc( tracker : MemoryTracker, to_remove : MemoryTracke
|
||||
temp_arena : Arena; arena_init(& temp_arena, tracker_msg_buffer[:])
|
||||
context.temp_allocator = arena_allocator(& temp_arena)
|
||||
|
||||
entries := array_to_slice_num(tracker.entries)
|
||||
entries := array_to_slice(tracker.entries)
|
||||
for idx in 0..< tracker.entries.num
|
||||
{
|
||||
entry := & entries[idx]
|
||||
@ -142,7 +142,7 @@ memtracker_check_for_collisions :: proc ( tracker : MemoryTracker )
|
||||
temp_arena : Arena; arena_init(& temp_arena, tracker_msg_buffer[:])
|
||||
context.temp_allocator = arena_allocator(& temp_arena)
|
||||
|
||||
entries := array_to_slice_num(tracker.entries)
|
||||
entries := array_to_slice(tracker.entries)
|
||||
for idx in 1 ..< tracker.entries.num {
|
||||
// Check to make sure each allocations adjacent entries do not intersect
|
||||
left := & entries[idx - 1]
|
||||
|
@ -32,7 +32,7 @@ string_to_runes_array :: proc( content : string, allocator := context.allocator
|
||||
return nil, alloc_error
|
||||
}
|
||||
|
||||
runes := array_to_slice(runes_array)
|
||||
runes := array_to_slice_capacity(runes_array)
|
||||
|
||||
idx := 0
|
||||
for codepoint in content {
|
||||
|
@ -4,6 +4,15 @@ package sectr
|
||||
|
||||
import "core:math"
|
||||
|
||||
// These are the same as the runtime constants for memory units just using a more general name when not refering to bytes
|
||||
|
||||
Kilo :: Kilobyte
|
||||
Mega :: Megabyte
|
||||
Giga :: Gigabyte
|
||||
Tera :: Terabyte
|
||||
Peta :: Petabyte
|
||||
Exa :: Exabyte
|
||||
|
||||
Axis2 :: enum i32 {
|
||||
Invalid = -1,
|
||||
X = 0,
|
||||
@ -64,7 +73,7 @@ Vec3i :: [3]i32
|
||||
vec2i_to_vec2 :: #force_inline proc "contextless" (v : Vec2i) -> Vec2 {return transmute(Vec2) v}
|
||||
vec3i_to_vec3 :: #force_inline proc "contextless" (v : Vec3i) -> Vec3 {return transmute(Vec3) v}
|
||||
|
||||
//region Range2
|
||||
#region("Range2")
|
||||
|
||||
Range2 :: struct #raw_union {
|
||||
using min_max : struct {
|
||||
@ -120,4 +129,4 @@ size_range2 :: #force_inline proc "contextless" ( value : Range2 ) -> Vec2 {
|
||||
return { value.p1.x - value.p0.x, value.p0.y - value.p1.y }
|
||||
}
|
||||
|
||||
//endregion Range2
|
||||
#endregion("Range2")
|
||||
|
@ -89,9 +89,9 @@ PWS_ParseError :: struct {
|
||||
}
|
||||
|
||||
PWS_ParseError_Max :: 32
|
||||
PWS_TokenArray_ReserveSize :: 64 * Kilobyte
|
||||
PWS_NodeArray_ReserveSize :: 64 * Kilobyte
|
||||
PWS_LineArray_ReserveSize :: 64 * Kilobyte
|
||||
PWS_TokenArray_ReserveSize :: 128
|
||||
PWS_NodeArray_ReserveSize :: 32 * Kilobyte
|
||||
PWS_LineArray_ReserveSize :: 32
|
||||
|
||||
// TODO(Ed) : The ast arrays should be handled by a slab allocator dedicated to PWS_ASTs
|
||||
// This can grow in undeterministic ways, persistent will get very polluted otherwise.
|
||||
@ -258,6 +258,7 @@ pws_parser_parse :: proc( text : string, allocator : Allocator ) -> ( PWS_ParseR
|
||||
|
||||
log( str_fmt_tmp( "parsing: %v ...", (len(text) > 30 ? transmute(string) bytes[ :30] : text) ))
|
||||
|
||||
// TODO(Ed): Change this to use a node pool
|
||||
nodes, alloc_error = array_init_reserve( PWS_AST, allocator, PWS_NodeArray_ReserveSize )
|
||||
verify( alloc_error == nil, "Allocation failure creating nodes array")
|
||||
|
||||
|
@ -4,7 +4,7 @@ import "core:encoding/json"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:reflect"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
@(private="file")
|
||||
|
@ -116,7 +116,7 @@ render_mode_2d_workspace :: proc()
|
||||
state.ui_context = ui
|
||||
|
||||
current := root.first
|
||||
for & current in array_to_slice_num(ui.render_queue)
|
||||
for & current in array_to_slice(ui.render_queue)
|
||||
{
|
||||
profile("Box")
|
||||
style := current.style
|
||||
@ -332,7 +332,7 @@ render_screen_ui :: proc()
|
||||
break Render_App_UI
|
||||
}
|
||||
|
||||
for & current in array_to_slice_num(ui.render_queue)
|
||||
for & current in array_to_slice(ui.render_queue)
|
||||
{
|
||||
// profile("Box")
|
||||
style := current.style
|
||||
|
188
code/ui_box.odin
Normal file
188
code/ui_box.odin
Normal file
@ -0,0 +1,188 @@
|
||||
package sectr
|
||||
|
||||
UI_BoxFlag :: enum u64 {
|
||||
Disabled,
|
||||
|
||||
Focusable,
|
||||
Click_To_Focus,
|
||||
|
||||
Mouse_Clickable,
|
||||
Keyboard_Clickable,
|
||||
|
||||
// Pan_X,
|
||||
// Pan_Y,
|
||||
|
||||
// Scroll_X,
|
||||
// Scroll_Y,
|
||||
|
||||
// Screenspace,
|
||||
Count,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
// UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
|
||||
|
||||
UI_RenderBoxInfo :: struct {
|
||||
using computed : UI_Computed,
|
||||
using style : UI_Style,
|
||||
text : StrRunesPair,
|
||||
font_size : UI_Scalar,
|
||||
border_width : UI_Scalar,
|
||||
}
|
||||
|
||||
UI_Box :: struct {
|
||||
// Cache ID
|
||||
key : UI_Key,
|
||||
// label : string,
|
||||
label : StrRunesPair,
|
||||
text : StrRunesPair,
|
||||
|
||||
// Regenerated per frame.
|
||||
|
||||
// first, last : The first and last child of this box
|
||||
// prev, next : The adjacent neighboring boxes who are children of to the same parent
|
||||
using links : DLL_NodeFull( UI_Box ),
|
||||
parent : ^UI_Box,
|
||||
num_children : i32,
|
||||
ancestors : i32, // This value for rooted widgets gets set to -1 after rendering see ui_box_make() for the reason.
|
||||
parent_index : i32,
|
||||
|
||||
flags : UI_BoxFlags,
|
||||
computed : UI_Computed,
|
||||
|
||||
layout : UI_Layout,
|
||||
style : UI_Style,
|
||||
|
||||
// Persistent Data
|
||||
hot_delta : f32,
|
||||
active_delta : f32,
|
||||
disabled_delta : f32,
|
||||
style_delta : f32,
|
||||
first_frame : b8,
|
||||
// root_order_id : i16,
|
||||
|
||||
// prev_computed : UI_Computed,
|
||||
// prev_style : UI_Style,v
|
||||
// mouse : UI_InteractState,
|
||||
// keyboard : UI_InteractState,
|
||||
}
|
||||
|
||||
ui_box_equal :: #force_inline proc "contextless" ( a, b : ^ UI_Box ) -> b32 {
|
||||
BoxSize :: size_of(UI_Box)
|
||||
|
||||
result : b32 = true
|
||||
result &= a.key == b.key // We assume for now the label is the same as the key, if not something is terribly wrong.
|
||||
result &= a.flags == b.flags
|
||||
return result
|
||||
}
|
||||
|
||||
ui_box_from_key :: #force_inline proc ( cache : ^HMapZPL(UI_Box), key : UI_Key ) -> (^UI_Box) {
|
||||
return zpl_hmap_get( cache, cast(u64) key )
|
||||
}
|
||||
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
{
|
||||
// profile(#procedure)
|
||||
|
||||
using ui := get_state().ui_context
|
||||
|
||||
key := ui_key_from_string( label )
|
||||
|
||||
links_perserved : DLL_NodeFull( UI_Box )
|
||||
|
||||
curr_box : (^ UI_Box)
|
||||
prev_box := zpl_hmap_get( prev_cache, cast(u64) key )
|
||||
{
|
||||
// profile("Assigning current box")
|
||||
|
||||
set_result : ^ UI_Box
|
||||
set_error : AllocatorError
|
||||
if prev_box != nil
|
||||
{
|
||||
// Previous history was found, copy over previous state.
|
||||
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, (prev_box ^) )
|
||||
}
|
||||
else {
|
||||
box : UI_Box
|
||||
box.key = key
|
||||
box.label = str_intern( label )
|
||||
// set_result, set_error = zpl_hmap_set( prev_cache, cast(u64) key, box )
|
||||
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, box )
|
||||
}
|
||||
|
||||
verify( set_error == AllocatorError.None, "Failed to set zpl_hmap due to allocator error" )
|
||||
curr_box = set_result
|
||||
|
||||
curr_box.first_frame = prev_box == nil
|
||||
}
|
||||
|
||||
curr_box.flags = flags
|
||||
|
||||
// Clear non-persistent data
|
||||
curr_box.computed.fresh = false
|
||||
curr_box.links = links_perserved
|
||||
curr_box.num_children = 0
|
||||
|
||||
// If there is a parent, setup the relevant references
|
||||
parent := stack_peek( & parent_stack )
|
||||
if parent != nil
|
||||
{
|
||||
dll_full_push_back( parent, curr_box, nil )
|
||||
when false
|
||||
{
|
||||
// |
|
||||
// v
|
||||
// parent.first <nil>
|
||||
if parent.first == nil {
|
||||
parent.first = curr_box
|
||||
parent.last = curr_box
|
||||
curr_box.next = nil
|
||||
curr_box.prev = nil
|
||||
}
|
||||
else {
|
||||
// Positin is set to last, insert at end
|
||||
// <parent.last.prev> <parent.last> curr_box
|
||||
parent.last.next = curr_box
|
||||
curr_box.prev = parent.last
|
||||
parent.last = curr_box
|
||||
curr_box.next = nil
|
||||
}
|
||||
}
|
||||
|
||||
curr_box.parent_index = parent.num_children
|
||||
parent.num_children += 1
|
||||
curr_box.parent = parent
|
||||
curr_box.ancestors = parent.ancestors + 1
|
||||
}
|
||||
|
||||
ui.built_box_count += 1
|
||||
return curr_box
|
||||
}
|
||||
|
||||
ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box)
|
||||
{
|
||||
parent := box.parent
|
||||
|
||||
// Check to make sure parent is present on the screen, if its not don't bother.
|
||||
// If current has children, do them first
|
||||
using state := get_state()
|
||||
if box.first != nil
|
||||
{
|
||||
is_app_ui := ui_context == & screen_ui
|
||||
if is_app_ui || intersects_range2( view_get_bounds(), box.computed.bounds)
|
||||
{
|
||||
return box.first
|
||||
}
|
||||
}
|
||||
|
||||
if box.next == nil
|
||||
{
|
||||
// There is no more adjacent nodes
|
||||
if box.parent != nil
|
||||
{
|
||||
// Lift back up to parent, and set it to its next.
|
||||
return parent.next
|
||||
}
|
||||
}
|
||||
|
||||
return box.next
|
||||
}
|
@ -39,6 +39,14 @@ ui_floating_startup :: proc( self : ^UI_FloatingManager, allocator : Allocator,
|
||||
return error
|
||||
}
|
||||
|
||||
ui_floating_reload :: proc( self : ^UI_FloatingManager, allocator : Allocator )
|
||||
{
|
||||
using self
|
||||
build_queue.backing = allocator
|
||||
tracked.entries.backing = allocator
|
||||
tracked.table.backing = allocator
|
||||
}
|
||||
|
||||
ui_floating_just_builder :: #force_inline proc( label : string, builder : UI_FloatingBuilder ) -> ^UI_Floating
|
||||
{
|
||||
No_Captures : rawptr = nil
|
||||
@ -84,7 +92,7 @@ ui_floating_build :: proc()
|
||||
screen_ui := cast(^UI_ScreenState) ui
|
||||
using floating := get_state().ui_floating_context
|
||||
|
||||
for to_enqueue in array_to_slice_num( build_queue)
|
||||
for to_enqueue in array_to_slice( build_queue)
|
||||
{
|
||||
key := ui_key_from_string(to_enqueue.label)
|
||||
lookup := zpl_hmap_get( & tracked, transmute(u64) key )
|
||||
|
@ -193,7 +193,7 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
label_id := 0
|
||||
|
||||
line_id := 0
|
||||
for line in array_to_slice_num( debug.lorem_parse.lines )
|
||||
for line in array_to_slice( debug.lorem_parse.lines )
|
||||
{
|
||||
if line_id == 0 {
|
||||
line_id += 1
|
||||
|
192
code/ui_ui.odin
192
code/ui_ui.odin
@ -52,27 +52,6 @@ UI_AnchorPresets :: enum u32 {
|
||||
Count,
|
||||
}
|
||||
|
||||
UI_BoxFlag :: enum u64 {
|
||||
Disabled,
|
||||
|
||||
Focusable,
|
||||
Click_To_Focus,
|
||||
|
||||
Mouse_Clickable,
|
||||
Keyboard_Clickable,
|
||||
|
||||
// Pan_X,
|
||||
// Pan_Y,
|
||||
|
||||
// Scroll_X,
|
||||
// Scroll_Y,
|
||||
|
||||
// Screenspace,
|
||||
Count,
|
||||
}
|
||||
UI_BoxFlags :: bit_set[UI_BoxFlag; u64]
|
||||
// UI_BoxFlag_Scroll :: UI_BoxFlags { .Scroll_X, .Scroll_Y }
|
||||
|
||||
UI_Cursor :: struct {
|
||||
placeholder : int,
|
||||
}
|
||||
@ -91,13 +70,7 @@ UI_InteractState :: struct {
|
||||
|
||||
UI_Key :: distinct u64
|
||||
|
||||
UI_RenderBoxInfo :: struct {
|
||||
using computed : UI_Computed,
|
||||
using style : UI_Style,
|
||||
text : StrRunesPair,
|
||||
font_size : UI_Scalar,
|
||||
border_width : UI_Scalar,
|
||||
}
|
||||
|
||||
|
||||
UI_Scalar :: f32
|
||||
|
||||
@ -107,42 +80,6 @@ UI_ScalarConstraint :: struct {
|
||||
|
||||
UI_Scalar2 :: [Axis2.Count]UI_Scalar
|
||||
|
||||
UI_Box :: struct {
|
||||
// Cache ID
|
||||
key : UI_Key,
|
||||
// label : string,
|
||||
label : StrRunesPair,
|
||||
text : StrRunesPair,
|
||||
|
||||
// Regenerated per frame.
|
||||
|
||||
// first, last : The first and last child of this box
|
||||
// prev, next : The adjacent neighboring boxes who are children of to the same parent
|
||||
using links : DLL_NodeFull( UI_Box ),
|
||||
parent : ^UI_Box,
|
||||
num_children : i32,
|
||||
ancestors : i32, // This value for rooted widgets gets set to -1 after rendering see ui_box_make() for the reason.
|
||||
parent_index : i32,
|
||||
|
||||
flags : UI_BoxFlags,
|
||||
computed : UI_Computed,
|
||||
|
||||
layout : UI_Layout,
|
||||
style : UI_Style,
|
||||
|
||||
// Persistent Data
|
||||
hot_delta : f32,
|
||||
active_delta : f32,
|
||||
disabled_delta : f32,
|
||||
style_delta : f32,
|
||||
first_frame : b8,
|
||||
// root_order_id : i16,
|
||||
|
||||
// prev_computed : UI_Computed,
|
||||
// prev_style : UI_Style,v
|
||||
// mouse : UI_InteractState,
|
||||
// keyboard : UI_InteractState,
|
||||
}
|
||||
|
||||
// UI_BoxFlags_Stack_Size :: 512
|
||||
UI_Layout_Stack_Size :: 512
|
||||
@ -220,137 +157,16 @@ ui_startup :: proc( ui : ^ UI_State, cache_allocator : Allocator /* , cache_rese
|
||||
ui_reload :: proc( ui : ^ UI_State, cache_allocator : Allocator )
|
||||
{
|
||||
// We need to repopulate Allocator references
|
||||
for cache in & ui.caches {
|
||||
cache.entries.backing = cache_allocator
|
||||
cache.hashes.backing = cache_allocator
|
||||
for & cache in & ui.caches {
|
||||
zpl_hmap_reload( & cache, cache_allocator)
|
||||
}
|
||||
ui.render_queue.backing = cache_allocator
|
||||
}
|
||||
|
||||
// TODO(Ed) : Is this even needed?
|
||||
ui_shutdown :: proc() {
|
||||
}
|
||||
|
||||
ui_box_equal :: #force_inline proc "contextless" ( a, b : ^ UI_Box ) -> b32 {
|
||||
BoxSize :: size_of(UI_Box)
|
||||
|
||||
result : b32 = true
|
||||
result &= a.key == b.key // We assume for now the label is the same as the key, if not something is terribly wrong.
|
||||
result &= a.flags == b.flags
|
||||
return result
|
||||
}
|
||||
|
||||
ui_box_from_key :: #force_inline proc ( cache : ^HMapZPL(UI_Box), key : UI_Key ) -> (^UI_Box) {
|
||||
return zpl_hmap_get( cache, cast(u64) key )
|
||||
}
|
||||
|
||||
ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
{
|
||||
// profile(#procedure)
|
||||
|
||||
using ui := get_state().ui_context
|
||||
|
||||
key := ui_key_from_string( label )
|
||||
|
||||
links_perserved : DLL_NodeFull( UI_Box )
|
||||
|
||||
curr_box : (^ UI_Box)
|
||||
prev_box := zpl_hmap_get( prev_cache, cast(u64) key )
|
||||
{
|
||||
// profile("Assigning current box")
|
||||
|
||||
set_result : ^ UI_Box
|
||||
set_error : AllocatorError
|
||||
if prev_box != nil
|
||||
{
|
||||
// Previous history was found, copy over previous state.
|
||||
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, (prev_box ^) )
|
||||
}
|
||||
else {
|
||||
box : UI_Box
|
||||
box.key = key
|
||||
box.label = str_intern( label )
|
||||
// set_result, set_error = zpl_hmap_set( prev_cache, cast(u64) key, box )
|
||||
set_result, set_error = zpl_hmap_set( curr_cache, cast(u64) key, box )
|
||||
}
|
||||
|
||||
verify( set_error == AllocatorError.None, "Failed to set zpl_hmap due to allocator error" )
|
||||
curr_box = set_result
|
||||
|
||||
curr_box.first_frame = prev_box == nil
|
||||
}
|
||||
|
||||
curr_box.flags = flags
|
||||
|
||||
// Clear non-persistent data
|
||||
curr_box.computed.fresh = false
|
||||
curr_box.links = links_perserved
|
||||
curr_box.num_children = 0
|
||||
|
||||
// If there is a parent, setup the relevant references
|
||||
parent := stack_peek( & parent_stack )
|
||||
if parent != nil
|
||||
{
|
||||
dll_full_push_back( parent, curr_box, nil )
|
||||
when false
|
||||
{
|
||||
// |
|
||||
// v
|
||||
// parent.first <nil>
|
||||
if parent.first == nil {
|
||||
parent.first = curr_box
|
||||
parent.last = curr_box
|
||||
curr_box.next = nil
|
||||
curr_box.prev = nil
|
||||
}
|
||||
else {
|
||||
// Positin is set to last, insert at end
|
||||
// <parent.last.prev> <parent.last> curr_box
|
||||
parent.last.next = curr_box
|
||||
curr_box.prev = parent.last
|
||||
parent.last = curr_box
|
||||
curr_box.next = nil
|
||||
}
|
||||
}
|
||||
|
||||
curr_box.parent_index = parent.num_children
|
||||
parent.num_children += 1
|
||||
curr_box.parent = parent
|
||||
curr_box.ancestors = parent.ancestors + 1
|
||||
}
|
||||
|
||||
ui.built_box_count += 1
|
||||
return curr_box
|
||||
}
|
||||
|
||||
ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box ) -> (^ UI_Box)
|
||||
{
|
||||
parent := box.parent
|
||||
|
||||
// Check to make sure parent is present on the screen, if its not don't bother.
|
||||
// If current has children, do them first
|
||||
using state := get_state()
|
||||
if box.first != nil
|
||||
{
|
||||
is_app_ui := ui_context == & screen_ui
|
||||
if is_app_ui || intersects_range2( view_get_bounds(), box.computed.bounds)
|
||||
{
|
||||
return box.first
|
||||
}
|
||||
}
|
||||
|
||||
if box.next == nil
|
||||
{
|
||||
// There is no more adjacent nodes
|
||||
if box.parent != nil
|
||||
{
|
||||
// Lift back up to parent, and set it to its next.
|
||||
return parent.next
|
||||
}
|
||||
}
|
||||
|
||||
return box.next
|
||||
}
|
||||
|
||||
ui_cursor_pos :: #force_inline proc "contextless" () -> Vec2 {
|
||||
using state := get_state()
|
||||
if ui_context == & state.project.workspace.ui {
|
||||
|
2
docs/ui.md
Normal file
2
docs/ui.md
Normal file
@ -0,0 +1,2 @@
|
||||
# UI
|
||||
|
8
ols.json
8
ols.json
@ -11,8 +11,12 @@
|
||||
"enable_fake_methods": true,
|
||||
"enable_format": false,
|
||||
"enable_hover": true,
|
||||
"enable_semantic_tokens": true,
|
||||
"enable_semantic_tokens": false,
|
||||
"enable_snippets": false,
|
||||
"enable_references": true,
|
||||
"thread_pool_count": 10
|
||||
"thread_pool_count": 10,
|
||||
"enable_inlay_hints": true,
|
||||
"enable_procedure_context": true,
|
||||
"enable_procedure_snippet": false,
|
||||
"disable_parser_errors": false
|
||||
}
|
||||
|
@ -169,9 +169,9 @@ push-location $path_root
|
||||
# $build_args += $flag_micro_architecture_native
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
# $build_args += $flag_optimize_none
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
$build_args += $flag_optimize_speed
|
||||
# $build_args += $flag_optimize_speed
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
@ -251,10 +251,10 @@ push-location $path_root
|
||||
# $build_args += $flag_micro_architecture_native
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
# $build_args += $flag_optimize_none
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
$build_args += $falg_optimize_aggressive
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
|
Loading…
Reference in New Issue
Block a user