mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Merge branch 'master' of https://github.com/avanspector/Odin
This commit is contained in:
@@ -34,12 +34,18 @@ Tracking_Allocator_Bad_Free_Entry :: struct {
|
|||||||
location: runtime.Source_Code_Location,
|
location: runtime.Source_Code_Location,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Callback type for when tracking allocator runs into a bad free.
|
||||||
|
*/
|
||||||
|
Tracking_Allocator_Bad_Free_Callback :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Tracking allocator data.
|
Tracking allocator data.
|
||||||
*/
|
*/
|
||||||
Tracking_Allocator :: struct {
|
Tracking_Allocator :: struct {
|
||||||
backing: Allocator,
|
backing: Allocator,
|
||||||
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
||||||
|
bad_free_callback: Tracking_Allocator_Bad_Free_Callback,
|
||||||
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
||||||
mutex: sync.Mutex,
|
mutex: sync.Mutex,
|
||||||
clear_on_free_all: bool,
|
clear_on_free_all: bool,
|
||||||
@@ -61,6 +67,7 @@ allocate the tracked data.
|
|||||||
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) {
|
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) {
|
||||||
t.backing = backing_allocator
|
t.backing = backing_allocator
|
||||||
t.allocation_map.allocator = internals_allocator
|
t.allocation_map.allocator = internals_allocator
|
||||||
|
t.bad_free_callback = tracking_allocator_bad_free_callback_panic
|
||||||
t.bad_free_array.allocator = internals_allocator
|
t.bad_free_array.allocator = internals_allocator
|
||||||
if .Free_All in query_features(t.backing) {
|
if .Free_All in query_features(t.backing) {
|
||||||
t.clear_on_free_all = true
|
t.clear_on_free_all = true
|
||||||
@@ -109,6 +116,33 @@ tracking_allocator_reset :: proc(t: ^Tracking_Allocator) {
|
|||||||
sync.mutex_unlock(&t.mutex)
|
sync.mutex_unlock(&t.mutex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default behavior for a bad free: Crash with error message that says where the
|
||||||
|
bad free happened.
|
||||||
|
|
||||||
|
Override Tracking_Allocator.bad_free_callback to have something else happen. For
|
||||||
|
example, you can use tracking_allocator_bad_free_callback_add_to_array to return
|
||||||
|
the tracking allocator to the old behavior, where the bad_free_array was used.
|
||||||
|
*/
|
||||||
|
tracking_allocator_bad_free_callback_panic :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) {
|
||||||
|
runtime.print_caller_location(location)
|
||||||
|
runtime.print_string(" Tracking allocator error: Bad free of pointer ")
|
||||||
|
runtime.print_uintptr(uintptr(memory))
|
||||||
|
runtime.print_string("\n")
|
||||||
|
runtime.trap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Alternative behavior for a bad free: Store in `bad_free_array`. If you use this,
|
||||||
|
then you must make sure to check Tracking_Allocator.bad_free_array at some point.
|
||||||
|
*/
|
||||||
|
tracking_allocator_bad_free_callback_add_to_array :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) {
|
||||||
|
append(&t.bad_free_array, Tracking_Allocator_Bad_Free_Entry {
|
||||||
|
memory = memory,
|
||||||
|
location = location,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Tracking allocator.
|
Tracking allocator.
|
||||||
|
|
||||||
@@ -116,8 +150,10 @@ The tracking allocator is an allocator wrapper that tracks memory allocations.
|
|||||||
This allocator stores all the allocations in a map. Whenever a pointer that's
|
This allocator stores all the allocations in a map. Whenever a pointer that's
|
||||||
not inside of the map is freed, the `bad_free_array` entry is added.
|
not inside of the map is freed, the `bad_free_array` entry is added.
|
||||||
|
|
||||||
An example of how to use the `Tracking_Allocator` to track subsequent allocations
|
Here follows an example of how to use the `Tracking_Allocator` to track
|
||||||
in your program and report leaks and bad frees:
|
subsequent allocations in your program and report leaks. By default, the
|
||||||
|
tracking allocator will crash on bad frees. You can override that behavior by
|
||||||
|
overriding `track.bad_free_callback`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -137,9 +173,6 @@ Example:
|
|||||||
for _, leak in track.allocation_map {
|
for _, leak in track.allocation_map {
|
||||||
fmt.printf("%v leaked %m\n", leak.location, leak.size)
|
fmt.printf("%v leaked %m\n", leak.location, leak.size)
|
||||||
}
|
}
|
||||||
for bad_free in track.bad_free_array {
|
|
||||||
fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -191,10 +224,9 @@ tracking_allocator_proc :: proc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map {
|
if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map {
|
||||||
append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{
|
if data.bad_free_callback != nil {
|
||||||
memory = old_memory,
|
data.bad_free_callback(data, old_memory, loc)
|
||||||
location = loc,
|
}
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return
|
result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ intern_get_cstring :: proc(m: ^Intern, text: string) -> (str: cstring, err: runt
|
|||||||
entry := _intern_get_entry(m, text) or_return
|
entry := _intern_get_entry(m, text) or_return
|
||||||
return cstring(&entry.str[0]), nil
|
return cstring(&entry.str[0]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Internal function to lookup whether the text string exists in the map, returns the entry
|
Internal function to lookup whether the text string exists in the map, returns the entry
|
||||||
Sets and allocates the entry if it wasn't set yet
|
Sets and allocates the entry if it wasn't set yet
|
||||||
@@ -104,13 +105,15 @@ Returns:
|
|||||||
- err: An allocator error if one occured, `nil` otherwise
|
- err: An allocator error if one occured, `nil` otherwise
|
||||||
*/
|
*/
|
||||||
_intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check {
|
_intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check {
|
||||||
if prev, ok := m.entries[text]; ok {
|
|
||||||
return prev, nil
|
|
||||||
}
|
|
||||||
if m.allocator.procedure == nil {
|
if m.allocator.procedure == nil {
|
||||||
m.allocator = context.allocator
|
m.allocator = context.allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key_ptr, val_ptr, inserted := map_entry(&m.entries, text) or_return
|
||||||
|
if !inserted {
|
||||||
|
return val_ptr^, nil
|
||||||
|
}
|
||||||
|
|
||||||
entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1
|
entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1
|
||||||
bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return
|
bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return
|
||||||
new_entry = (^Intern_Entry)(raw_data(bytes))
|
new_entry = (^Intern_Entry)(raw_data(bytes))
|
||||||
@@ -120,6 +123,9 @@ _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry
|
|||||||
new_entry.str[new_entry.len] = 0
|
new_entry.str[new_entry.len] = 0
|
||||||
|
|
||||||
key := string(new_entry.str[:new_entry.len])
|
key := string(new_entry.str[:new_entry.len])
|
||||||
m.entries[key] = new_entry
|
|
||||||
return new_entry, nil
|
key_ptr^ = key
|
||||||
|
val_ptr^ = new_entry
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,10 @@ class WasmMemoryInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadCstring(ptr) {
|
loadCstring(ptr) {
|
||||||
const start = this.loadPtr(ptr);
|
return this.loadCstringDirect(this.loadPtr(ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCstringDirect(start) {
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ foreign import "system:Comctl32.lib"
|
|||||||
@(default_calling_convention="system")
|
@(default_calling_convention="system")
|
||||||
foreign Comctl32 {
|
foreign Comctl32 {
|
||||||
LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT ---
|
LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT ---
|
||||||
|
SetWindowSubclass :: proc(hwnd: HWND, pfnSubclass: SUBCLASSPROC, uIdSubclass: UINT_PTR, dwRefData: DWORD_PTR) ---
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ MINIDUMP_DIRECTORY :: struct {
|
|||||||
Location: MINIDUMP_LOCATION_DESCRIPTOR,
|
Location: MINIDUMP_LOCATION_DESCRIPTOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
MINIDUMP_EXCEPTION_INFORMATION :: struct {
|
MINIDUMP_EXCEPTION_INFORMATION :: struct #max_field_align(4) {
|
||||||
ThreadId: DWORD,
|
ThreadId: DWORD,
|
||||||
ExceptionPointers: ^EXCEPTION_POINTERS,
|
ExceptionPointers: ^EXCEPTION_POINTERS,
|
||||||
ClientPointers: BOOL,
|
ClientPointers: BOOL,
|
||||||
|
|||||||
@@ -796,6 +796,8 @@ TIMERPROC :: #type proc "system" (HWND, UINT, UINT_PTR, DWORD)
|
|||||||
|
|
||||||
WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT
|
WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT
|
||||||
|
|
||||||
|
SUBCLASSPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR) -> LRESULT
|
||||||
|
|
||||||
HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT
|
HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT
|
||||||
|
|
||||||
WINEVENTPROC :: #type proc "system" (
|
WINEVENTPROC :: #type proc "system" (
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package sys_windows
|
package sys_windows
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
|
import "core:c"
|
||||||
foreign import user32 "system:User32.lib"
|
foreign import user32 "system:User32.lib"
|
||||||
|
|
||||||
@(default_calling_convention="system")
|
@(default_calling_convention="system")
|
||||||
@@ -32,6 +33,8 @@ foreign user32 {
|
|||||||
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
|
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
|
||||||
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
|
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
|
||||||
|
|
||||||
|
RegisterHotKey :: proc(hnwd: HWND, id: c.int, fsModifiers: UINT, vk: UINT) -> BOOL ---
|
||||||
|
|
||||||
CreateWindowExW :: proc(
|
CreateWindowExW :: proc(
|
||||||
dwExStyle: DWORD,
|
dwExStyle: DWORD,
|
||||||
lpClassName: LPCWSTR,
|
lpClassName: LPCWSTR,
|
||||||
@@ -553,7 +556,7 @@ MOUSE_ATTRIBUTES_CHANGED :: 0x04
|
|||||||
MOUSE_MOVE_NOCOALESCE :: 0x08
|
MOUSE_MOVE_NOCOALESCE :: 0x08
|
||||||
|
|
||||||
RI_MOUSE_BUTTON_1_DOWN :: 0x0001
|
RI_MOUSE_BUTTON_1_DOWN :: 0x0001
|
||||||
RI_MOUSE_LEFT_BUTTON_DOWNS :: RI_MOUSE_BUTTON_1_DOWN
|
RI_MOUSE_LEFT_BUTTON_DOWN :: RI_MOUSE_BUTTON_1_DOWN
|
||||||
RI_MOUSE_BUTTON_1_UP :: 0x0002
|
RI_MOUSE_BUTTON_1_UP :: 0x0002
|
||||||
RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP
|
RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP
|
||||||
RI_MOUSE_BUTTON_2_DOWN :: 0x0004
|
RI_MOUSE_BUTTON_2_DOWN :: 0x0004
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
#+build windows
|
||||||
|
package sys_windows
|
||||||
|
|
||||||
|
foreign import "system:xinput.lib"
|
||||||
|
|
||||||
|
// Device types available in XINPUT_CAPABILITIES
|
||||||
|
// Correspond to XINPUT_DEVTYPE_...
|
||||||
|
XINPUT_DEVTYPE :: enum BYTE {
|
||||||
|
GAMEPAD = 0x01,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device subtypes available in XINPUT_CAPABILITIES
|
||||||
|
// Correspond to XINPUT_DEVSUBTYPE_...
|
||||||
|
XINPUT_DEVSUBTYPE :: enum BYTE {
|
||||||
|
UNKNOWN = 0x00,
|
||||||
|
GAMEPAD = 0x01,
|
||||||
|
WHEEL = 0x02,
|
||||||
|
ARCADE_STICK = 0x03,
|
||||||
|
FLIGHT_STICK = 0x04,
|
||||||
|
DANCE_PAD = 0x05,
|
||||||
|
GUITAR = 0x06,
|
||||||
|
GUITAR_ALTERNATE = 0x07,
|
||||||
|
DRUM_KIT = 0x08,
|
||||||
|
GUITAR_BASS = 0x0B,
|
||||||
|
ARCADE_PAD = 0x13,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags for XINPUT_CAPABILITIES
|
||||||
|
// Correspond to log2(XINPUT_CAPS_...)
|
||||||
|
XINPUT_CAP :: enum WORD {
|
||||||
|
FFB_SUPPORTED = 0,
|
||||||
|
WIRELESS = 1,
|
||||||
|
VOICE_SUPPORTED = 2,
|
||||||
|
PMD_SUPPORTED = 3,
|
||||||
|
NO_NAVIGATION = 4,
|
||||||
|
}
|
||||||
|
XINPUT_CAPS :: distinct bit_set[XINPUT_CAP;WORD]
|
||||||
|
|
||||||
|
// Constants for gamepad buttons
|
||||||
|
// Correspond to log2(XINPUT_GAMEPAD_...)
|
||||||
|
XINPUT_GAMEPAD_BUTTON_BIT :: enum WORD {
|
||||||
|
DPAD_UP = 0,
|
||||||
|
DPAD_DOWN = 1,
|
||||||
|
DPAD_LEFT = 2,
|
||||||
|
DPAD_RIGHT = 3,
|
||||||
|
START = 4,
|
||||||
|
BACK = 5,
|
||||||
|
LEFT_THUMB = 6,
|
||||||
|
RIGHT_THUMB = 7,
|
||||||
|
LEFT_SHOULDER = 8,
|
||||||
|
RIGHT_SHOULDER = 9,
|
||||||
|
A = 12,
|
||||||
|
B = 13,
|
||||||
|
X = 14,
|
||||||
|
Y = 15,
|
||||||
|
}
|
||||||
|
XINPUT_GAMEPAD_BUTTON :: distinct bit_set[XINPUT_GAMEPAD_BUTTON_BIT;WORD]
|
||||||
|
|
||||||
|
// Gamepad thresholds
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE: SHORT : 7849
|
||||||
|
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE: SHORT : 8689
|
||||||
|
XINPUT_GAMEPAD_TRIGGER_THRESHOLD: SHORT : 30
|
||||||
|
|
||||||
|
// Flags to pass to XInputGetCapabilities
|
||||||
|
// Corresponds to log2(XINPUT_FLAG_...)
|
||||||
|
XINPUT_FLAG_BIT :: enum WORD {
|
||||||
|
GAMEPAD = 0,
|
||||||
|
}
|
||||||
|
XINPUT_FLAG :: distinct bit_set[XINPUT_FLAG_BIT;DWORD]
|
||||||
|
|
||||||
|
// Devices that support batteries
|
||||||
|
// Corresponds to BATTERY_DEVTYPE_...
|
||||||
|
BATTERY_DEVTYPE :: enum BYTE {
|
||||||
|
GAMEPAD = 0x00,
|
||||||
|
HEADSET = 0x01,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags for battery status level
|
||||||
|
// Correspond to BATTERY_TYPE_...
|
||||||
|
BATTERY_TYPE :: enum BYTE {
|
||||||
|
DISCONNECTED = 0x00, // This device is not connected
|
||||||
|
WIRED = 0x01, // Wired device, no battery
|
||||||
|
ALKALINE = 0x02, // Alkaline battery source
|
||||||
|
NIMH = 0x03, // Nickel Metal Hydride battery source
|
||||||
|
UNKNOWN = 0xFF, // Cannot determine the battery type
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are only valid for wireless, connected devices, with known battery types
|
||||||
|
// The amount of use time remaining depends on the type of device.
|
||||||
|
// Correspond to BATTERY_LEVEL_...
|
||||||
|
BATTERY_LEVEL :: enum BYTE {
|
||||||
|
EMPTY = 0x00,
|
||||||
|
LOW = 0x01,
|
||||||
|
MEDIUM = 0x02,
|
||||||
|
FULL = 0x03,
|
||||||
|
}
|
||||||
|
|
||||||
|
// User index definitions
|
||||||
|
|
||||||
|
// Index of the gamer associated with the device
|
||||||
|
XUSER :: enum DWORD {
|
||||||
|
One = 0,
|
||||||
|
Two = 1,
|
||||||
|
Three = 2,
|
||||||
|
Four = 3,
|
||||||
|
Any = 0x000000FF, // Can be only used with XInputGetKeystroke
|
||||||
|
}
|
||||||
|
|
||||||
|
XUSER_MAX_COUNT :: 4
|
||||||
|
|
||||||
|
// Codes returned for the gamepad keystroke
|
||||||
|
// Corresponds to VK_PAD_...
|
||||||
|
VK_PAD :: enum WORD {
|
||||||
|
A = 0x5800,
|
||||||
|
B = 0x5801,
|
||||||
|
X = 0x5802,
|
||||||
|
Y = 0x5803,
|
||||||
|
RSHOULDER = 0x5804,
|
||||||
|
LSHOULDER = 0x5805,
|
||||||
|
LTRIGGER = 0x5806,
|
||||||
|
RTRIGGER = 0x5807,
|
||||||
|
DPAD_UP = 0x5810,
|
||||||
|
DPAD_DOWN = 0x5811,
|
||||||
|
DPAD_LEFT = 0x5812,
|
||||||
|
DPAD_RIGHT = 0x5813,
|
||||||
|
START = 0x5814,
|
||||||
|
BACK = 0x5815,
|
||||||
|
LTHUMB_PRESS = 0x5816,
|
||||||
|
RTHUMB_PRESS = 0x5817,
|
||||||
|
LTHUMB_UP = 0x5820,
|
||||||
|
LTHUMB_DOWN = 0x5821,
|
||||||
|
LTHUMB_RIGHT = 0x5822,
|
||||||
|
LTHUMB_LEFT = 0x5823,
|
||||||
|
LTHUMB_UPLEFT = 0x5824,
|
||||||
|
LTHUMB_UPRIGHT = 0x5825,
|
||||||
|
LTHUMB_DOWNRIGHT = 0x5826,
|
||||||
|
LTHUMB_DOWNLEFT = 0x5827,
|
||||||
|
RTHUMB_UP = 0x5830,
|
||||||
|
RTHUMB_DOWN = 0x5831,
|
||||||
|
RTHUMB_RIGHT = 0x5832,
|
||||||
|
RTHUMB_LEFT = 0x5833,
|
||||||
|
RTHUMB_UPLEFT = 0x5834,
|
||||||
|
RTHUMB_UPRIGHT = 0x5835,
|
||||||
|
RTHUMB_DOWNRIGHT = 0x5836,
|
||||||
|
RTHUMB_DOWNLEFT = 0x5837,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flags used in XINPUT_KEYSTROKE
|
||||||
|
// Correspond to log2(XINPUT_KEYSTROKE_...)
|
||||||
|
XINPUT_KEYSTROKE_BIT :: enum WORD {
|
||||||
|
KEYDOWN = 0,
|
||||||
|
KEYUP = 1,
|
||||||
|
REPEAT = 2,
|
||||||
|
}
|
||||||
|
XINPUT_KEYSTROKES :: distinct bit_set[XINPUT_KEYSTROKE_BIT;WORD]
|
||||||
|
|
||||||
|
// Structures used by XInput APIs
|
||||||
|
XINPUT_GAMEPAD :: struct {
|
||||||
|
wButtons: XINPUT_GAMEPAD_BUTTON,
|
||||||
|
bLeftTrigger: BYTE,
|
||||||
|
bRightTrigger: BYTE,
|
||||||
|
sThumbLX: SHORT,
|
||||||
|
sThumbLY: SHORT,
|
||||||
|
sThumbRX: SHORT,
|
||||||
|
sThumbRY: SHORT,
|
||||||
|
}
|
||||||
|
|
||||||
|
XINPUT_STATE :: struct {
|
||||||
|
dwPacketNumber: DWORD,
|
||||||
|
Gamepad: XINPUT_GAMEPAD,
|
||||||
|
}
|
||||||
|
|
||||||
|
XINPUT_VIBRATION :: struct {
|
||||||
|
wLeftMotorSpeed: WORD,
|
||||||
|
wRightMotorSpeed: WORD,
|
||||||
|
}
|
||||||
|
|
||||||
|
XINPUT_CAPABILITIES :: struct {
|
||||||
|
Type: XINPUT_DEVTYPE,
|
||||||
|
SubType: XINPUT_DEVSUBTYPE,
|
||||||
|
Flags: XINPUT_CAPS,
|
||||||
|
Gamepad: XINPUT_GAMEPAD,
|
||||||
|
Vibration: XINPUT_VIBRATION,
|
||||||
|
}
|
||||||
|
|
||||||
|
XINPUT_BATTERY_INFORMATION :: struct {
|
||||||
|
BatteryType: BATTERY_TYPE,
|
||||||
|
BatteryLevel: BATTERY_LEVEL,
|
||||||
|
}
|
||||||
|
|
||||||
|
XINPUT_KEYSTROKE :: struct {
|
||||||
|
VirtualKey: VK_PAD,
|
||||||
|
Unicode: WCHAR,
|
||||||
|
Flags: XINPUT_KEYSTROKES,
|
||||||
|
UserIndex: XUSER,
|
||||||
|
HidCode: BYTE,
|
||||||
|
}
|
||||||
|
|
||||||
|
// XInput APIs
|
||||||
|
@(default_calling_convention = "system")
|
||||||
|
foreign xinput {
|
||||||
|
XInputGetState :: proc(user: XUSER, pState: ^XINPUT_STATE) -> System_Error ---
|
||||||
|
XInputSetState :: proc(user: XUSER, pVibration: ^XINPUT_VIBRATION) -> System_Error ---
|
||||||
|
XInputGetCapabilities :: proc(user: XUSER, dwFlags: XINPUT_FLAG, pCapabilities: ^XINPUT_CAPABILITIES) -> System_Error ---
|
||||||
|
XInputEnable :: proc(enable: BOOL) ---
|
||||||
|
XInputGetAudioDeviceIds :: proc(user: XUSER, pRenderDeviceId: LPWSTR, pRenderCount: ^UINT, pCaptureDeviceId: LPWSTR, pCaptureCount: ^UINT) -> System_Error ---
|
||||||
|
XInputGetBatteryInformation :: proc(user: XUSER, devType: BATTERY_DEVTYPE, pBatteryInformation: ^XINPUT_BATTERY_INFORMATION) -> System_Error ---
|
||||||
|
XInputGetKeystroke :: proc(user: XUSER, dwReserved: DWORD, pKeystroke: ^XINPUT_KEYSTROKE) -> System_Error ---
|
||||||
|
XInputGetDSoundAudioDeviceGuids :: proc(user: XUSER, pDSoundRenderGuid: ^GUID, pDSoundCaptureGuid: ^GUID) -> System_Error ---
|
||||||
|
}
|
||||||
@@ -391,6 +391,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool {
|
|||||||
fmt.assertf(alloc_error == nil, "Error allocating memory for task allocator #%i: %v", i, alloc_error)
|
fmt.assertf(alloc_error == nil, "Error allocating memory for task allocator #%i: %v", i, alloc_error)
|
||||||
when TRACKING_MEMORY {
|
when TRACKING_MEMORY {
|
||||||
mem.tracking_allocator_init(&task_memory_trackers[i], mem.rollback_stack_allocator(&task_allocators[i]))
|
mem.tracking_allocator_init(&task_memory_trackers[i], mem.rollback_stack_allocator(&task_allocators[i]))
|
||||||
|
task_memory_trackers[i].bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -408,13 +408,18 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name,
|
|||||||
lb_set_llvm_metadata(m, type, temp_forward_decl);
|
lb_set_llvm_metadata(m, type, temp_forward_decl);
|
||||||
|
|
||||||
isize index_offset = 1;
|
isize index_offset = 1;
|
||||||
|
isize variant_offset = 1;
|
||||||
if (is_type_union_maybe_pointer(bt)) {
|
if (is_type_union_maybe_pointer(bt)) {
|
||||||
index_offset = 0;
|
index_offset = 0;
|
||||||
|
variant_offset = 0;
|
||||||
|
} else if (bt->Union.kind == UnionType_no_nil) {
|
||||||
|
variant_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope);
|
LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope);
|
||||||
unsigned element_count = cast(unsigned)bt->Union.variants.count;
|
unsigned element_count = cast(unsigned)bt->Union.variants.count;
|
||||||
if (index_offset > 0) {
|
if (index_offset > 0) {
|
||||||
|
GB_ASSERT(index_offset == 1);
|
||||||
element_count += 1;
|
element_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,13 +442,11 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name,
|
|||||||
for_array(j, bt->Union.variants) {
|
for_array(j, bt->Union.variants) {
|
||||||
Type *variant = bt->Union.variants[j];
|
Type *variant = bt->Union.variants[j];
|
||||||
|
|
||||||
unsigned field_index = cast(unsigned)(index_offset+j);
|
char name[32] = {};
|
||||||
|
gb_snprintf(name, gb_size_of(name), "v%td", variant_offset+j);
|
||||||
char name[16] = {};
|
|
||||||
gb_snprintf(name, gb_size_of(name), "v%u", field_index);
|
|
||||||
isize name_len = gb_strlen(name);
|
isize name_len = gb_strlen(name);
|
||||||
|
|
||||||
elements[field_index] = LLVMDIBuilderCreateMemberType(
|
elements[index_offset+j] = LLVMDIBuilderCreateMemberType(
|
||||||
m->debug_builder, member_scope,
|
m->debug_builder, member_scope,
|
||||||
name, name_len,
|
name, name_len,
|
||||||
file, line,
|
file, line,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import "core:log"
|
|||||||
test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
|
test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
|
||||||
track: mem.Tracking_Allocator
|
track: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
|
track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
|
||||||
defer mem.tracking_allocator_destroy(&track)
|
defer mem.tracking_allocator_destroy(&track)
|
||||||
context.allocator = mem.tracking_allocator(&track)
|
context.allocator = mem.tracking_allocator(&track)
|
||||||
|
|
||||||
|
|||||||
Vendored
+12
-12
@@ -1181,7 +1181,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuBufferSetLabel: (bufferIdx, labelPtr) => {
|
wgpuBufferSetLabel: (bufferIdx, labelPtr) => {
|
||||||
const buffer = this.buffers.get(bufferIdx);
|
const buffer = this.buffers.get(bufferIdx);
|
||||||
buffer.buffer.label = this.mem.loadCstring(labelPtr);
|
buffer.buffer.label = this.mem.loadCstringDirect(labelPtr);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1370,7 +1370,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => {
|
wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => {
|
||||||
const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
|
const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
|
||||||
commandEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr));
|
commandEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1387,7 +1387,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => {
|
wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => {
|
||||||
const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
|
const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
|
||||||
commandEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr));
|
commandEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1459,7 +1459,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => {
|
wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => {
|
||||||
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
|
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
|
||||||
computePassEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr));
|
computePassEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1476,7 +1476,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => {
|
wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => {
|
||||||
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
|
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
|
||||||
computePassEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr));
|
computePassEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2216,7 +2216,7 @@ class WebGPUInterface {
|
|||||||
wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => {
|
wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => {
|
||||||
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
|
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
|
||||||
this.assert(markerLabelPtr != 0);
|
this.assert(markerLabelPtr != 0);
|
||||||
const markerLabel = this.mem.loadCstring(markerLabelPtr);
|
const markerLabel = this.mem.loadCstringDirect(markerLabelPtr);
|
||||||
renderBundleEncoder.insertDebugMarker(markerLabel);
|
renderBundleEncoder.insertDebugMarker(markerLabel);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2235,7 +2235,7 @@ class WebGPUInterface {
|
|||||||
wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => {
|
wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => {
|
||||||
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
|
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
|
||||||
this.assert(groupLabelPtr!= 0);
|
this.assert(groupLabelPtr!= 0);
|
||||||
const groupLabel = this.mem.loadCstring(groupLabelPtr);
|
const groupLabel = this.mem.loadCstringDirect(groupLabelPtr);
|
||||||
renderBundleEncoder.pushDebugGroup(groupLabel);
|
renderBundleEncoder.pushDebugGroup(groupLabel);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2407,7 +2407,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => {
|
wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => {
|
||||||
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
|
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
|
||||||
const markerLabel = this.mem.loadCstring(markerLabelPtr);
|
const markerLabel = this.mem.loadCstringDirect(markerLabelPtr);
|
||||||
renderPassEncoder.insertDebugMarker(markerLabel);
|
renderPassEncoder.insertDebugMarker(markerLabel);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2425,7 +2425,7 @@ class WebGPUInterface {
|
|||||||
*/
|
*/
|
||||||
wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => {
|
wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => {
|
||||||
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
|
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
|
||||||
const groupLabel = this.mem.loadCstring(groupLabelPtr);
|
const groupLabel = this.mem.loadCstringDirect(groupLabelPtr);
|
||||||
renderPassEncoder.pushDebugGroup(groupLabel);
|
renderPassEncoder.pushDebugGroup(groupLabel);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2881,11 +2881,11 @@ class WebGPUObjectManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} idx
|
* @param {?number} idx
|
||||||
* @returns {T}
|
* @returns {T}
|
||||||
*/
|
*/
|
||||||
get(idx) {
|
get(idx) {
|
||||||
return this.objects[idx-1].object;
|
return this.objects[idx-1]?.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {number} idx */
|
/** @param {number} idx */
|
||||||
@@ -2908,7 +2908,7 @@ class WebGPUObjectManager {
|
|||||||
if (withLabelSetter) {
|
if (withLabelSetter) {
|
||||||
inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => {
|
inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => {
|
||||||
const obj = this.get(idx);
|
const obj = this.get(idx);
|
||||||
obj.label = this.mem.loadCstring(labelPtr);
|
obj.label = this.mem.loadCstringDirect(labelPtr);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return inter;
|
return inter;
|
||||||
|
|||||||
Reference in New Issue
Block a user