2
0
Эх сурвалжийг харах

Merge pull request #4585 from wrapperup/miniaudio-bitsets

`vendor:miniaudio`: Use bit sets for flags
Laytan 7 сар өмнө
parent
commit
47030501ab

+ 8 - 5
vendor/miniaudio/device_io_types.odin

@@ -351,8 +351,11 @@ device_id :: struct #raw_union {
 	nullbackend: c.int,                 /* The null backend uses an integer for device IDs. */
 }
 
+data_format_flag :: enum c.int {
+	EXCLUSIVE_MODE = 1, /* If set, this is supported in exclusive mode. Otherwise not natively supported by exclusive mode. */
+}
 
-DATA_FORMAT_FLAG_EXCLUSIVE_MODE :: 1 << 1    /* If set, this is supported in exclusive mode. Otherwise not natively supported by exclusive mode. */
+data_format_flags :: bit_set[data_format_flag; u32]
 
 MAX_DEVICE_NAME_LENGTH :: 255
 
@@ -364,10 +367,10 @@ device_info :: struct {
 
 	nativeDataFormatCount: u32,
 	nativeDataFormats: [/*len(format_count) * standard_sample_rate.rate_count * MAX_CHANNELS*/ 64]struct { /* Not sure how big to make this. There can be *many* permutations for virtual devices which can support anything. */
-		format:     format, /* Sample format. If set to ma_format_unknown, all sample formats are supported. */
-		channels:   u32,    /* If set to 0, all channels are supported. */
-		sampleRate: u32,    /* If set to 0, all sample rates are supported. */
-		flags:      u32,    /* A combination of MA_DATA_FORMAT_FLAG_* flags. */
+		format:     format,            /* Sample format. If set to ma_format_unknown, all sample formats are supported. */
+		channels:   u32,               /* If set to 0, all channels are supported. */
+		sampleRate: u32,               /* If set to 0, all sample rates are supported. */
+		flags:      data_format_flags, /* A combination of MA_DATA_FORMAT_FLAG_* flags. */
 	},  
 }
 

+ 27 - 25
vendor/miniaudio/engine.odin

@@ -11,20 +11,22 @@ Engine
 ************************************************************************************************************************************************************/
 
 /* Sound flags. */
-sound_flags :: enum c.int {
+sound_flag :: enum c.int {
 	/* Resource manager flags. */
-	STREAM                = 0x00000001,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM */
-	DECODE                = 0x00000002,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE */
-	ASYNC                 = 0x00000004,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */
-	WAIT_INIT             = 0x00000008,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */
-	UNKNOWN_LENGTH        = 0x00000010,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH */
+	STREAM                = 0,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM */
+	DECODE                = 1,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE */
+	ASYNC                 = 2,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC */
+	WAIT_INIT             = 3,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT */
+	UNKNOWN_LENGTH        = 4,   /* MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_UNKNOWN_LENGTH */
 	
 	/* ma_sound specific flags. */
-	NO_DEFAULT_ATTACHMENT = 0x00001000,   /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */
-	NO_PITCH              = 0x00002000,   /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */
-	NO_SPATIALIZATION     = 0x00004000,   /* Disable spatialization. */
+	NO_DEFAULT_ATTACHMENT = 12,  /* Do not attach to the endpoint by default. Useful for when setting up nodes in a complex graph system. */
+	NO_PITCH              = 13,  /* Disable pitch shifting with ma_sound_set_pitch() and ma_sound_group_set_pitch(). This is an optimization. */
+	NO_SPATIALIZATION     = 14,  /* Disable spatialization. */
 }
 
+sound_flags :: bit_set[sound_flag; u32]
+
 ENGINE_MAX_LISTENERS :: 4
 
 LISTENER_INDEX_CLOSEST :: 255
@@ -81,7 +83,7 @@ engine_node :: struct {
 
 @(default_calling_convention="c", link_prefix="ma_")
 foreign lib {
-	engine_node_config_init :: proc(pEngine: ^engine, type: engine_node_type, flags: u32) -> engine_node_config ---
+	engine_node_config_init :: proc(pEngine: ^engine, type: engine_node_type, flags: sound_flags) -> engine_node_config ---
 
 	engine_node_get_heap_size     :: proc(pConfig: ^engine_node_config, pHeapSizeInBytes: ^c.size_t) -> result ---
 	engine_node_init_preallocated :: proc(pConfig: ^engine_node_config, pHeap: rawptr, pEngineNode: ^engine_node) -> result ---
@@ -96,17 +98,17 @@ SOUND_SOURCE_CHANNEL_COUNT :: 0xFFFFFFFF
 sound_end_proc :: #type proc "c" (pUserData: rawptr, pSound: ^sound)
 
 sound_config :: struct {
-	pFilePath:                      cstring,          /* Set this to load from the resource manager. */
-	pFilePathW:                     [^]c.wchar_t,     /* Set this to load from the resource manager. */
-	pDataSource:                    ^data_source,     /* Set this to load from an existing data source. */
-	pInitialAttachment:             ^node,            /* If set, the sound will be attached to an input of this node. This can be set to a ma_sound. If set to NULL, the sound will be attached directly to the endpoint unless MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT is set in `flags`. */
-	initialAttachmentInputBusIndex: u32,              /* The index of the input bus of pInitialAttachment to attach the sound to. */
-	channelsIn:                     u32,              /* Ignored if using a data source as input (the data source's channel count will be used always). Otherwise, setting to 0 will cause the engine's channel count to be used. */
-	channelsOut:                    u32,              /* Set this to 0 (default) to use the engine's channel count. Set to MA_SOUND_SOURCE_CHANNEL_COUNT to use the data source's channel count (only used if using a data source as input). */
+	pFilePath:                      cstring,             /* Set this to load from the resource manager. */
+	pFilePathW:                     [^]c.wchar_t,        /* Set this to load from the resource manager. */
+	pDataSource:                    ^data_source,        /* Set this to load from an existing data source. */
+	pInitialAttachment:             ^node,               /* If set, the sound will be attached to an input of this node. This can be set to a ma_sound. If set to NULL, the sound will be attached directly to the endpoint unless MA_SOUND_FLAG_NO_DEFAULT_ATTACHMENT is set in `flags`. */
+	initialAttachmentInputBusIndex: u32,                 /* The index of the input bus of pInitialAttachment to attach the sound to. */
+	channelsIn:                     u32,                 /* Ignored if using a data source as input (the data source's channel count will be used always). Otherwise, setting to 0 will cause the engine's channel count to be used. */
+	channelsOut:                    u32,                 /* Set this to 0 (default) to use the engine's channel count. Set to MA_SOUND_SOURCE_CHANNEL_COUNT to use the data source's channel count (only used if using a data source as input). */
 	monoExpansionMode:              mono_expansion_mode, /* Controls how the mono channel should be expanded to other channels when spatialization is disabled on a sound. */
-	flags:                          u32,              /* A combination of MA_SOUND_FLAG_* flags. */
-	volumeSmoothTimeInPCMFrames:    u32,              /* The number of frames to smooth over volume changes. Defaults to 0 in which case no smoothing is used. */
-	initialSeekPointInPCMFrames:    u64,              /* Initializes the sound such that it's seeked to this location by default. */
+	flags:                          sound_flags,         /* A combination of MA_SOUND_FLAG_* flags. */
+	volumeSmoothTimeInPCMFrames:    u32,                 /* The number of frames to smooth over volume changes. Defaults to 0 in which case no smoothing is used. */
+	initialSeekPointInPCMFrames:    u64,                 /* Initializes the sound such that it's seeked to this location by default. */
 	rangeBegInPCMFrames:            u64,
 	rangeEndInPCMFrames:            u64,
 	loopPointBegInPCMFrames:        u64,
@@ -152,10 +154,10 @@ foreign lib {
 	sound_config_init  :: proc() -> sound_config ---
 	sound_config_init2 :: proc(pEngine: ^engine) -> sound_config --- /* Will be renamed to sound_config_init() in version 0.12. */
 
-	sound_init_from_file                     :: proc(pEngine: ^engine, pFilePath: cstring, flags: u32, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result ---
-	sound_init_from_file_w                   :: proc(pEngine: ^engine, pFilePath: [^]c.wchar_t, flags: u32, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result ---
-	sound_init_copy                          :: proc(pEngine: ^engine, pExistingSound: ^sound, flags: u32, pGroup: ^sound_group, pSound: ^sound) -> result ---
-	sound_init_from_data_source              :: proc(pEngine: ^engine, pDataSource: ^data_source, flags: u32, pGroup: ^sound_group, pSound: ^sound) -> result ---
+	sound_init_from_file                     :: proc(pEngine: ^engine, pFilePath: cstring, flags: sound_flags, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result ---
+	sound_init_from_file_w                   :: proc(pEngine: ^engine, pFilePath: [^]c.wchar_t, flags: sound_flags, pGroup: ^sound_group, pDoneFence: ^fence, pSound: ^sound) -> result ---
+	sound_init_copy                          :: proc(pEngine: ^engine, pExistingSound: ^sound, flags: sound_flags, pGroup: ^sound_group, pSound: ^sound) -> result ---
+	sound_init_from_data_source              :: proc(pEngine: ^engine, pDataSource: ^data_source, flags: sound_flags, pGroup: ^sound_group, pSound: ^sound) -> result ---
 	sound_init_ex                            :: proc(pEngine: ^engine, pConfig: ^sound_config, pSound: ^sound) -> result ---
 	sound_uninit                             :: proc(pSound: ^sound) ---
 	sound_get_engine                         :: proc(pSound: ^sound) -> ^engine ---
@@ -243,7 +245,7 @@ foreign lib {
 	sound_group_config_init  :: proc() -> sound_group_config ---
 	sound_group_config_init2 :: proc(pEngine: ^engine) -> sound_group_config ---
 
-	sound_group_init                               :: proc(pEngine: ^engine, flags: u32, pParentGroup, pGroup: ^sound_group) -> result ---
+	sound_group_init                               :: proc(pEngine: ^engine, flags: sound_flags, pParentGroup, pGroup: ^sound_group) -> result ---
 	sound_group_init_ex                            :: proc(pEngine: ^engine, pConfig: ^sound_group_config, pGroup: ^sound_group) -> result ---
 	sound_group_uninit                             :: proc(pGroup: ^sound_group) ---
 	sound_group_get_engine                         :: proc(pGroup: ^sound_group) -> ^engine ---

+ 8 - 6
vendor/miniaudio/job_queue.odin

@@ -108,7 +108,7 @@ job :: struct {
 				pDataBufferNode:   rawptr /*ma_resource_manager_data_buffer_node**/,
 				pFilePath:         cstring,
 				pFilePathW:        [^]c.wchar_t,
-				flags:             u32,                       /* Resource manager data source flags that were used when initializing the data buffer. */
+				flags:             resource_manager_data_source_flags, /* Resource manager data source flags that were used when initializing the data buffer. */
 				pInitNotification: ^async_notification,       /* Signalled when the data buffer has been initialized and the format/channels/rate can be retrieved. */
 				pDoneNotification: ^async_notification,       /* Signalled when the data buffer has been fully decoded. Will be passed through to MA_JOB_TYPE_RESOURCE_MANAGER_PAGE_DATA_BUFFER_NODE when decoding. */
 				pInitFence:        ^fence,                    /* Released when initialization of the decoder is complete. */
@@ -194,19 +194,21 @@ ma_job_queue_post(). ma_job_queue_next() will return MA_NO_DATA_AVAILABLE if not
 
 This flag should always be used for platforms that do not support multithreading.
 */
-job_queue_flags :: enum c.int {
-	NON_BLOCKING = 0x00000001,
+job_queue_flag :: enum c.int {
+	NON_BLOCKING = 0,
 }
 
+job_queue_flags :: bit_set[job_queue_flag; u32]
+
 job_queue_config :: struct {
-	flags:    u32,
+	flags:    job_queue_flags,
 	capacity: u32, /* The maximum number of jobs that can fit in the queue at a time. */
 }
 
 USE_EXPERIMENTAL_LOCK_FREE_JOB_QUEUE :: false
 
 job_queue :: struct {
-	flags:     u32,                                          /* Flags passed in at initialization time. */
+	flags:     job_queue_flags,                              /* Flags passed in at initialization time. */
 	capacity:  u32,                                          /* The maximum number of jobs that can fit in the queue at a time. Set by the config. */
 	head:      u64, /*atomic*/                               /* The first item in the list. Required for removing from the top of the list. */
 	tail:      u64, /*atomic*/                               /* The last item in the list. Required for appending to the end of the list. */
@@ -222,7 +224,7 @@ job_queue :: struct {
 
 @(default_calling_convention="c", link_prefix="ma_")
 foreign lib {
-	job_queue_config_init :: proc(flags, capacity: u32) -> job_queue_config ---
+	job_queue_config_init :: proc(flags: job_queue_flags, capacity: u32) -> job_queue_config ---
 
 	job_queue_get_heap_size     :: proc(pConfig: ^job_queue_config, pHeapSizeInBytes: ^c.size_t) -> result ---
 	job_queue_init_preallocated :: proc(pConfig: ^job_queue_config, pHeap: rawptr, pQueue: ^job_queue) -> result ---

+ 16 - 8
vendor/miniaudio/node_graph.odin

@@ -22,14 +22,16 @@ NODE_BUS_COUNT_UNKNOWN :: 255
 node :: struct {}
 
 /* Node flags. */
-node_flags :: enum c.int {
-	PASSTHROUGH                = 0x00000001,
-	CONTINUOUS_PROCESSING      = 0x00000002,
-	ALLOW_NULL_INPUT           = 0x00000004,
-	DIFFERENT_PROCESSING_RATES = 0x00000008,
-	SILENT_OUTPUT              = 0x00000010,
+node_flag :: enum c.int {
+	PASSTHROUGH                = 0,
+	CONTINUOUS_PROCESSING      = 1,
+	ALLOW_NULL_INPUT           = 2,
+	DIFFERENT_PROCESSING_RATES = 3,
+	SILENT_OUTPUT              = 4,
 }
 
+node_flags :: bit_set[node_flag; u32]
+
 /* The playback state of a node. Either started or stopped. */
 node_state :: enum c.int {
 	started = 0,
@@ -75,7 +77,7 @@ node_vtable :: struct {
 	Flags describing characteristics of the node. This is currently just a placeholder for some
 	ideas for later on.
 	*/
-	flags: u32,
+	flags: node_flags,
 }
 
 node_config :: struct {
@@ -87,6 +89,12 @@ node_config :: struct {
 	pOutputChannels: ^u32,          /* The number of elements are determined by the output bus count as determined by the vtable, or `outputBusCount` if the vtable specifies `MA_NODE_BUS_COUNT_UNKNOWN`. */
 }
 
+node_output_bus_flag :: enum c.int {
+	HAS_READ = 0, /* 0x01 */
+}
+
+node_output_bus_flags :: bit_set[node_output_bus_flag; u32]
+
 /*
 A node has multiple output buses. An output bus is attached to an input bus as an item in a linked
 list. Think of the input bus as a linked list, with the output bus being an item in that list.
@@ -99,7 +107,7 @@ node_output_bus :: struct {
 
 	/* Mutable via multiple threads. Must be used atomically. The weird ordering here is for packing reasons. */
 	inputNodeInputBusIndex: u8,                             /* The index of the input bus on the input. Required for detaching. Will only be used in the spinlock so does not need to be atomic. */
-	flags:                  u32, /*atomic*/                 /* Some state flags for tracking the read state of the output buffer. A combination of MA_NODE_OUTPUT_BUS_FLAG_*. */
+	flags:                  node_output_bus_flags, /*atomic*/                 /* Some state flags for tracking the read state of the output buffer. A combination of MA_NODE_OUTPUT_BUS_FLAG_*. */
 	refCount:               u32, /*atomic*/                 /* Reference count for some thread-safety when detaching. */
 	isAttached:             b32, /*atomic*/                 /* This is used to prevent iteration of nodes that are in the middle of being detached. Used for thread safety. */
 	lock:                   spinlock, /*atomic*/            /* Unfortunate lock, but significantly simplifies the implementation. Required for thread-safe attaching and detaching. */

+ 14 - 10
vendor/miniaudio/resource_manager.odin

@@ -10,14 +10,16 @@ Resource Manager
 
 ************************************************************************************************************************************************************/
 
-resource_manager_data_source_flags :: enum c.int {
-	STREAM         = 0x00000001,   /* When set, does not load the entire data source in memory. Disk I/O will happen on job threads. */
-	DECODE         = 0x00000002,   /* Decode data before storing in memory. When set, decoding is done at the resource manager level rather than the mixing thread. Results in faster mixing, but higher memory usage. */
-	ASYNC          = 0x00000004,   /* When set, the resource manager will load the data source asynchronously. */
-	WAIT_INIT      = 0x00000008,   /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */
-	UNKNOWN_LENGTH = 0x00000010,   /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */
+resource_manager_data_source_flag :: enum c.int {
+	STREAM         = 0,   /* When set, does not load the entire data source in memory. Disk I/O will happen on job threads. */
+	DECODE         = 1,   /* Decode data before storing in memory. When set, decoding is done at the resource manager level rather than the mixing thread. Results in faster mixing, but higher memory usage. */
+	ASYNC          = 2,   /* When set, the resource manager will load the data source asynchronously. */
+	WAIT_INIT      = 3,   /* When set, waits for initialization of the underlying data source before returning from ma_resource_manager_data_source_init(). */
+	UNKNOWN_LENGTH = 4,   /* Gives the resource manager a hint that the length of the data source is unknown and calling `ma_data_source_get_length_in_pcm_frames()` should be avoided. */
 }
 
+resource_manager_data_source_flags :: bit_set[resource_manager_data_source_flag; u32]
+
 /*
 Pipeline notifications used by the resource manager. Made up of both an async notification and a fence, both of which are optional.
 */
@@ -58,14 +60,16 @@ resource_manager_job_queue_next                   :: job_queue_next
 /* Maximum job thread count will be restricted to this, but this may be removed later and replaced with a heap allocation thereby removing any limitation. */
 RESOURCE_MANAGER_MAX_JOB_THREAD_COUNT :: 64
 
-resource_manager_flags :: enum c.int {
+resource_manager_flag :: enum c.int {
 	/* Indicates ma_resource_manager_next_job() should not block. Only valid when the job thread count is 0. */
-	NON_BLOCKING = 0x00000001,
+	NON_BLOCKING = 0,
 
 	/* Disables any kind of multithreading. Implicitly enables MA_RESOURCE_MANAGER_FLAG_NON_BLOCKING. */
-	NO_THREADING = 0x00000002,
+	NO_THREADING = 1,
 }
 
+resource_manager_flags :: bit_set[resource_manager_flag; u32]
+
 resource_manager_data_source_config :: struct {
 	pFilePath:                   cstring,
 	pFilePathW:                  [^]c.wchar_t,
@@ -126,7 +130,7 @@ resource_manager_data_buffer :: struct {
 	ds:                     data_source_base,                      /* Base data source. A data buffer is a data source. */
 	pResourceManager:       ^resource_manager,                     /* A pointer to the resource manager that owns this buffer. */
 	pNode:                  ^resource_manager_data_buffer_node,    /* The data node. This is reference counted and is what supplies the data. */
-	flags:                  u32,                                   /* The flags that were passed used to initialize the buffer. */
+	flags:                  resource_manager_flags,                /* The flags that were passed used to initialize the buffer. */
 	executionCounter:       u32, /*atomic*/                        /* For allocating execution orders for jobs. */
 	executionPointer:       u32, /*atomic*/                        /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
 	seekTargetInPCMFrames:  u64,                                   /* Only updated by the public API. Never written nor read from the job thread. */

+ 7 - 2
vendor/miniaudio/utilities.odin

@@ -119,7 +119,12 @@ offset_pcm_frames_const_ptr_f32 :: #force_inline proc "c" (p: [^]f32, offsetInFr
 
 data_source :: struct {}
 
-DATA_SOURCE_SELF_MANAGED_RANGE_AND_LOOP_POINT :: 0x00000001
+data_source_flag :: enum c.int {
+	SELF_MANAGED_RANGE_AND_LOOP_POINT = 0,
+}
+
+data_source_flags :: bit_set[data_source_flag; u32]
+
 
 data_source_vtable :: struct {
 	onRead:          proc "c" (pDataSource: ^data_source, pFramesOut: rawptr, frameCount: u64, pFramesRead: ^u64) -> result,
@@ -128,7 +133,7 @@ data_source_vtable :: struct {
 	onGetCursor:     proc "c" (pDataSource: ^data_source, pCursor: ^u64) -> result,
 	onGetLength:     proc "c" (pDataSource: ^data_source, pLength: ^u64) -> result,
 	onSetLooping:    proc "c" (pDataSource: ^data_source, isLooping: b32) -> result,
-	flags:           u32,
+	flags:           data_source_flags,
 } 
 
 data_source_get_next_proc :: proc "c" (pDataSource: ^data_source) -> ^data_source

+ 9 - 7
vendor/miniaudio/vfs.odin

@@ -16,11 +16,13 @@ appropriate for a given situation.
 vfs :: struct {}
 vfs_file :: distinct handle
 
-open_mode_flags :: enum c.int {
-	READ  = 0x00000001,
-	WRITE = 0x00000002,
+open_mode_flag :: enum c.int {
+	READ  = 0,
+	WRITE = 1,
 }
 
+open_mode_flags :: bit_set[open_mode_flag; u32]
+
 seek_origin :: enum c.int {
 	start,
 	current,
@@ -32,8 +34,8 @@ file_info :: struct {
 }
 
 vfs_callbacks :: struct {
-	onOpen:  proc "c" (pVFS: ^vfs, pFilePath: cstring,      openMode: u32, pFile: ^vfs_file) -> result,
-	onOpenW: proc "c" (pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: u32, pFile: ^vfs_file) -> result,
+	onOpen:  proc "c" (pVFS: ^vfs, pFilePath: cstring,      openMode: open_mode_flags, pFile: ^vfs_file) -> result,
+	onOpenW: proc "c" (pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: open_mode_flags, pFile: ^vfs_file) -> result,
 	onClose: proc "c" (pVFS: ^vfs, file: vfs_file) -> result,
 	onRead:  proc "c" (pVFS: ^vfs, file: vfs_file, pDst: rawptr, sizeInBytes: c.size_t, pBytesRead: ^c.size_t) -> result,
 	onWrite: proc "c" (pVFS: ^vfs, file: vfs_file, pSrc: rawptr, sizeInBytes: c.size_t, pBytesWritten: ^c.size_t) -> result,
@@ -54,8 +56,8 @@ ma_tell_proc :: proc "c" (pUserData: rawptr, pCursor: ^i64) -> result
 
 @(default_calling_convention="c", link_prefix="ma_")
 foreign lib {
-	vfs_open               :: proc(pVFS: ^vfs, pFilePath: cstring,      openMode: u32, pFile: ^vfs_file) -> result ---
-	vfs_open_w             :: proc(pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: u32, pFile: ^vfs_file) -> result ---
+	vfs_open               :: proc(pVFS: ^vfs, pFilePath: cstring,      openMode: open_mode_flags, pFile: ^vfs_file) -> result ---
+	vfs_open_w             :: proc(pVFS: ^vfs, pFilePath: [^]c.wchar_t, openMode: open_mode_flags, pFile: ^vfs_file) -> result ---
 	vfs_close              :: proc(pVFS: ^vfs, file: vfs_file) -> result ---
 	vfs_read               :: proc(pVFS: ^vfs, file: vfs_file, pDst: rawptr, sizeInBytes: c.size_t, pBytesRead: ^c.size_t) -> result ---
 	vfs_write              :: proc(pVFS: ^vfs, file: vfs_file, pSrc: rawptr, sizeInBytes: c.size_t, pBytesWritten: ^c.size_t) -> result ---