This commit is contained in:
avanspector
2025-01-10 06:42:42 +01:00
12 changed files with 296 additions and 34 deletions
+41 -9
View File
@@ -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
} }
+11 -5
View File
@@ -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
} }
+4 -1
View File
@@ -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;
} }
+1
View File
@@ -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) ---
} }
+1 -1
View File
@@ -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,
+2
View File
@@ -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" (
+4 -1
View File
@@ -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
+210
View File
@@ -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 ---
}
+1
View File
@@ -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
} }
} }
+8 -5
View File
@@ -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)
+12 -12
View File
@@ -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;