convert indentation to 2 spaces
This commit is contained in:
parent
c1b768282f
commit
3377e3f94c
62
build.bat
62
build.bat
@ -11,7 +11,7 @@ set meta_build_cmd=cl.exe ../src/meta/meta.c -Od -Z7 -nologo -diagnostics:column
|
|||||||
set meta_rebuild_code=1317212284
|
set meta_rebuild_code=1317212284
|
||||||
|
|
||||||
if "%--force_meta_build%"=="1" (
|
if "%--force_meta_build%"=="1" (
|
||||||
if exist meta.exe del meta.exe
|
if exist meta.exe del meta.exe
|
||||||
)
|
)
|
||||||
|
|
||||||
echo build_cmd: %program_build_cmd%
|
echo build_cmd: %program_build_cmd%
|
||||||
@ -19,48 +19,48 @@ echo build_cmd: %program_build_cmd%
|
|||||||
::- Try to activate Visual Studio if devenv not detected
|
::- Try to activate Visual Studio if devenv not detected
|
||||||
:: Taken from wcap: https://github.com/mmozeiko/wcap/blob/aa25ccb806d7a6e1c0bfdcca863aabcd8e9badfa/build.cmd#L21-L29
|
:: Taken from wcap: https://github.com/mmozeiko/wcap/blob/aa25ccb806d7a6e1c0bfdcca863aabcd8e9badfa/build.cmd#L21-L29
|
||||||
if "%PROCESSOR_ARCHITECTURE%" equ "AMD64" (
|
if "%PROCESSOR_ARCHITECTURE%" equ "AMD64" (
|
||||||
set HOST_ARCH=x64
|
set HOST_ARCH=x64
|
||||||
) else if "%PROCESSOR_ARCHITECTURE%" equ "ARM64" (
|
) else if "%PROCESSOR_ARCHITECTURE%" equ "ARM64" (
|
||||||
set HOST_ARCH=arm64
|
set HOST_ARCH=arm64
|
||||||
)
|
)
|
||||||
where /Q cl.exe || (
|
where /Q cl.exe || (
|
||||||
echo **************************************************************************
|
echo **************************************************************************
|
||||||
echo WARNING: cl.exe not found, attempting to locate Visual Studio installation
|
echo WARNING: cl.exe not found, attempting to locate Visual Studio installation
|
||||||
|
|
||||||
set __VSCMD_ARG_NO_LOGO=1
|
set __VSCMD_ARG_NO_LOGO=1
|
||||||
for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i
|
for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i
|
||||||
if "!VS!" equ "" (
|
if "!VS!" equ "" (
|
||||||
echo ERROR: Visual Studio installation not found
|
echo ERROR: Visual Studio installation not found
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
echo Visual Studio installation located, activating development environment...
|
echo Visual Studio installation located, activating development environment...
|
||||||
call "!VS!\Common7\Tools\VsDevCmd.bat" -arch=%HOST_ARCH% -host_arch=%HOST_ARCH% -startdir=none -no_logo || exit /b 1
|
call "!VS!\Common7\Tools\VsDevCmd.bat" -arch=%HOST_ARCH% -host_arch=%HOST_ARCH% -startdir=none -no_logo || exit /b 1
|
||||||
echo Visual studio development environment activated
|
echo Visual studio development environment activated
|
||||||
echo **************************************************************************
|
echo **************************************************************************
|
||||||
)
|
)
|
||||||
|
|
||||||
::- Meta build
|
::- Meta build
|
||||||
:meta_build
|
:meta_build
|
||||||
if not exist meta.exe (
|
if not exist meta.exe (
|
||||||
echo ====== Meta build =====
|
echo ====== Meta build =====
|
||||||
%meta_build_cmd%
|
%meta_build_cmd%
|
||||||
set "rc=!errorlevel!"
|
set "rc=!errorlevel!"
|
||||||
if !rc! NEQ 0 (
|
if !rc! NEQ 0 (
|
||||||
if exist meta.exe del meta.exe
|
if exist meta.exe del meta.exe
|
||||||
exit /b !rc!
|
exit /b !rc!
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
::- Program build
|
::- Program build
|
||||||
if not "%--no_program_build%"=="1" (
|
if not "%--no_program_build%"=="1" (
|
||||||
echo ======== Build ========
|
echo ======== Build ========
|
||||||
%program_build_cmd%
|
%program_build_cmd%
|
||||||
set "rc=!errorlevel!"
|
set "rc=!errorlevel!"
|
||||||
if !rc! NEQ 0 (
|
if !rc! NEQ 0 (
|
||||||
if !rc! EQU %meta_rebuild_code% (
|
if !rc! EQU %meta_rebuild_code% (
|
||||||
del meta.exe
|
del meta.exe
|
||||||
goto meta_build
|
goto meta_build
|
||||||
)
|
|
||||||
exit /b !rc!
|
|
||||||
)
|
)
|
||||||
|
exit /b !rc!
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
1564
src/ase/ase.c
1564
src/ase/ase.c
File diff suppressed because it is too large
Load Diff
226
src/ase/ase.h
226
src/ase/ase.h
@ -3,33 +3,33 @@
|
|||||||
|
|
||||||
Struct(ASE_Slice)
|
Struct(ASE_Slice)
|
||||||
{
|
{
|
||||||
u32 start;
|
u32 start;
|
||||||
Rng2I32 rect;
|
Rng2I32 rect;
|
||||||
ASE_Slice *next;
|
ASE_Slice *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_Span)
|
Struct(ASE_Span)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
u32 start;
|
u32 start;
|
||||||
u32 end;
|
u32 end;
|
||||||
ASE_Span *next;
|
ASE_Span *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_Frame)
|
Struct(ASE_Frame)
|
||||||
{
|
{
|
||||||
u32 index;
|
u32 index;
|
||||||
Rng2I32 rect;
|
Rng2I32 rect;
|
||||||
f64 duration;
|
f64 duration;
|
||||||
ASE_Frame *next;
|
ASE_Frame *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_SliceKey)
|
Struct(ASE_SliceKey)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
u32 num_slices;
|
u32 num_slices;
|
||||||
ASE_Slice *first_slice;
|
ASE_Slice *first_slice;
|
||||||
ASE_SliceKey *next;
|
ASE_SliceKey *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -37,38 +37,38 @@ Struct(ASE_SliceKey)
|
|||||||
|
|
||||||
Struct(ASE_Error)
|
Struct(ASE_Error)
|
||||||
{
|
{
|
||||||
String msg;
|
String msg;
|
||||||
ASE_Error *next;
|
ASE_Error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_ErrorList)
|
Struct(ASE_ErrorList)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
ASE_Error *first;
|
ASE_Error *first;
|
||||||
ASE_Error *last;
|
ASE_Error *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_DecodedImage)
|
Struct(ASE_DecodedImage)
|
||||||
{
|
{
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 *pixels; /* Array of [width * height] pixels */
|
u32 *pixels; /* Array of [width * height] pixels */
|
||||||
ASE_ErrorList errors;
|
ASE_ErrorList errors;
|
||||||
b32 ok;
|
b32 ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_DecodedSheet)
|
Struct(ASE_DecodedSheet)
|
||||||
{
|
{
|
||||||
Vec2 image_size;
|
Vec2 image_size;
|
||||||
Vec2 frame_size;
|
Vec2 frame_size;
|
||||||
u32 num_frames;
|
u32 num_frames;
|
||||||
u32 num_spans;
|
u32 num_spans;
|
||||||
u32 num_slice_keys;
|
u32 num_slice_keys;
|
||||||
ASE_Frame *first_frame;
|
ASE_Frame *first_frame;
|
||||||
ASE_Span *first_span;
|
ASE_Span *first_span;
|
||||||
ASE_SliceKey *first_slice_key;
|
ASE_SliceKey *first_slice_key;
|
||||||
ASE_ErrorList errors;
|
ASE_ErrorList errors;
|
||||||
b32 ok;
|
b32 ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -78,29 +78,29 @@ Struct(ASE_DecodedSheet)
|
|||||||
|
|
||||||
Struct(ASE_Bitbuff)
|
Struct(ASE_Bitbuff)
|
||||||
{
|
{
|
||||||
u8 *data;
|
u8 *data;
|
||||||
u64 cur_bit;
|
u64 cur_bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(ASE_BlockType)
|
Enum(ASE_BlockType)
|
||||||
{
|
{
|
||||||
ASE_BlockType_Uncompressed = 0,
|
ASE_BlockType_Uncompressed = 0,
|
||||||
ASE_BlockType_CompressedFixed = 1,
|
ASE_BlockType_CompressedFixed = 1,
|
||||||
ASE_BlockType_CompressedDynamic = 2,
|
ASE_BlockType_CompressedDynamic = 2,
|
||||||
ASE_BlockType_Reserved = 3
|
ASE_BlockType_Reserved = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_HuffEntry)
|
Struct(ASE_HuffEntry)
|
||||||
{
|
{
|
||||||
u16 symbol;
|
u16 symbol;
|
||||||
u16 bits_used;
|
u16 bits_used;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_HuffDict)
|
Struct(ASE_HuffDict)
|
||||||
{
|
{
|
||||||
u32 max_code_bits;
|
u32 max_code_bits;
|
||||||
u32 entries_count;
|
u32 entries_count;
|
||||||
ASE_HuffEntry *entries;
|
ASE_HuffEntry *entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -108,36 +108,36 @@ Struct(ASE_HuffDict)
|
|||||||
|
|
||||||
Packed(Struct(ASE_Header)
|
Packed(Struct(ASE_Header)
|
||||||
{
|
{
|
||||||
u32 file_size;
|
u32 file_size;
|
||||||
u16 magic;
|
u16 magic;
|
||||||
u16 frames;
|
u16 frames;
|
||||||
u16 width;
|
u16 width;
|
||||||
u16 height;
|
u16 height;
|
||||||
u16 color_depth;
|
u16 color_depth;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u16 speed;
|
u16 speed;
|
||||||
u32 _1;
|
u32 _1;
|
||||||
u32 _2;
|
u32 _2;
|
||||||
u8 palette_entry;
|
u8 palette_entry;
|
||||||
u8 _3[3];
|
u8 _3[3];
|
||||||
u16 num_colors;
|
u16 num_colors;
|
||||||
u8 pixel_width;
|
u8 pixel_width;
|
||||||
u8 pixel_height;
|
u8 pixel_height;
|
||||||
i16 grid_x;
|
i16 grid_x;
|
||||||
i16 grid_y;
|
i16 grid_y;
|
||||||
u16 grid_width;
|
u16 grid_width;
|
||||||
u16 grid_height;
|
u16 grid_height;
|
||||||
u8 _4[84];
|
u8 _4[84];
|
||||||
});
|
});
|
||||||
|
|
||||||
Packed(Struct(ASE_FrameHeader)
|
Packed(Struct(ASE_FrameHeader)
|
||||||
{
|
{
|
||||||
u32 bytes;
|
u32 bytes;
|
||||||
u16 magic;
|
u16 magic;
|
||||||
u16 chunks_old;
|
u16 chunks_old;
|
||||||
u16 frame_duration_ms;
|
u16 frame_duration_ms;
|
||||||
u8 _[2];
|
u8 _[2];
|
||||||
u32 chunks_new;
|
u32 chunks_new;
|
||||||
});
|
});
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -145,63 +145,63 @@ Packed(Struct(ASE_FrameHeader)
|
|||||||
|
|
||||||
Enum(ASE_ChunkKind)
|
Enum(ASE_ChunkKind)
|
||||||
{
|
{
|
||||||
ASE_ChunkKind_OldPalette1 = 0x0004,
|
ASE_ChunkKind_OldPalette1 = 0x0004,
|
||||||
ASE_ChunkKind_OldPalette2 = 0x0011,
|
ASE_ChunkKind_OldPalette2 = 0x0011,
|
||||||
ASE_ChunkKind_Layer = 0x2004,
|
ASE_ChunkKind_Layer = 0x2004,
|
||||||
ASE_ChunkKind_Cel = 0x2005,
|
ASE_ChunkKind_Cel = 0x2005,
|
||||||
ASE_ChunkKind_CelExtra = 0x2006,
|
ASE_ChunkKind_CelExtra = 0x2006,
|
||||||
ASE_ChunkKind_ColorProfile = 0x2007,
|
ASE_ChunkKind_ColorProfile = 0x2007,
|
||||||
ASE_ChunkKind_ExternalFiles = 0x2008,
|
ASE_ChunkKind_ExternalFiles = 0x2008,
|
||||||
ASE_ChunkKind_Mask = 0x2016,
|
ASE_ChunkKind_Mask = 0x2016,
|
||||||
ASE_ChunkKind_Path = 0x2017,
|
ASE_ChunkKind_Path = 0x2017,
|
||||||
ASE_ChunkKind_Tags = 0x2018,
|
ASE_ChunkKind_Tags = 0x2018,
|
||||||
ASE_ChunkKind_Palette = 0x2019,
|
ASE_ChunkKind_Palette = 0x2019,
|
||||||
ASE_ChunkKind_Userdata = 0x2020,
|
ASE_ChunkKind_Userdata = 0x2020,
|
||||||
ASE_ChunkKind_Slice = 0x2022,
|
ASE_ChunkKind_Slice = 0x2022,
|
||||||
ASE_ChunkKind_Tileset = 0x2023
|
ASE_ChunkKind_Tileset = 0x2023
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(ASE_CelKind)
|
Enum(ASE_CelKind)
|
||||||
{
|
{
|
||||||
ASE_CelKind_RawImage = 0,
|
ASE_CelKind_RawImage = 0,
|
||||||
ASE_CelKind_Linked = 1,
|
ASE_CelKind_Linked = 1,
|
||||||
ASE_CelKind_CompressedImage = 2,
|
ASE_CelKind_CompressedImage = 2,
|
||||||
ASE_CelKind_CompressedTilemap = 3
|
ASE_CelKind_CompressedTilemap = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ASE_Layer)
|
Struct(ASE_Layer)
|
||||||
{
|
{
|
||||||
u16 flags;
|
u16 flags;
|
||||||
u16 type;
|
u16 type;
|
||||||
u16 child_level;
|
u16 child_level;
|
||||||
u16 blend_mode;
|
u16 blend_mode;
|
||||||
u8 opacity;
|
u8 opacity;
|
||||||
String name;
|
String name;
|
||||||
u32 tileset_index;
|
u32 tileset_index;
|
||||||
|
|
||||||
u32 index;
|
u32 index;
|
||||||
ASE_Layer *next;
|
ASE_Layer *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Ace_Cel)
|
Struct(Ace_Cel)
|
||||||
{
|
{
|
||||||
u16 layer_index;
|
u16 layer_index;
|
||||||
i16 x_pos;
|
i16 x_pos;
|
||||||
i16 y_pos;
|
i16 y_pos;
|
||||||
u8 opacity;
|
u8 opacity;
|
||||||
ASE_CelKind type;
|
ASE_CelKind type;
|
||||||
i16 z_index;
|
i16 z_index;
|
||||||
|
|
||||||
/* Linked cel */
|
/* Linked cel */
|
||||||
u16 frame_pos;
|
u16 frame_pos;
|
||||||
|
|
||||||
/* Compressed image */
|
/* Compressed image */
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 *pixels;
|
u32 *pixels;
|
||||||
|
|
||||||
u16 frame_index;
|
u16 frame_index;
|
||||||
Ace_Cel *next;
|
Ace_Cel *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -2,39 +2,39 @@
|
|||||||
//~ Compiler flag checks
|
//~ Compiler flag checks
|
||||||
|
|
||||||
#ifndef IsConsoleApp
|
#ifndef IsConsoleApp
|
||||||
#error Missing compile time definition for 'IsConsoleApp'
|
#error Missing compile time definition for 'IsConsoleApp'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsRtcEnabled
|
#ifndef IsRtcEnabled
|
||||||
#error Missing compile time definition for 'IsRtcEnabled'
|
#error Missing compile time definition for 'IsRtcEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsAsanEnabled
|
#ifndef IsAsanEnabled
|
||||||
#error Missing compile time definition for 'IsAsanEnabled'
|
#error Missing compile time definition for 'IsAsanEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsCrtlibEnabled
|
#ifndef IsCrtlibEnabled
|
||||||
#error Missing compile time definition for 'IsCrtlibEnabled'
|
#error Missing compile time definition for 'IsCrtlibEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsDebinfoEnabled
|
#ifndef IsDebinfoEnabled
|
||||||
#error Missing compile time definition for 'IsDebinfoEnabled'
|
#error Missing compile time definition for 'IsDebinfoEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsDeveloperModeEnabled
|
#ifndef IsDeveloperModeEnabled
|
||||||
#error Missing compile time definition for 'IsDeveloperModeEnabled'
|
#error Missing compile time definition for 'IsDeveloperModeEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsUnoptimized
|
#ifndef IsUnoptimized
|
||||||
#error Missing compile time definition for 'IsUnoptimized'
|
#error Missing compile time definition for 'IsUnoptimized'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsTestingEnabled
|
#ifndef IsTestingEnabled
|
||||||
#error Missing compile time definition for 'IsTestingEnabled'
|
#error Missing compile time definition for 'IsTestingEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsHotSwappingEnabled
|
#ifndef IsHotSwappingEnabled
|
||||||
#error Missing compile time definition for 'IsHotSwappingEnabled'
|
#error Missing compile time definition for 'IsHotSwappingEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -42,57 +42,57 @@
|
|||||||
|
|
||||||
//- Compiler
|
//- Compiler
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#define IsCompilerClang 1
|
#define IsCompilerClang 1
|
||||||
#define IsCompilerMsvc 0
|
#define IsCompilerMsvc 0
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define IsCompilerClang 0
|
#define IsCompilerClang 0
|
||||||
#define IsCompilerMsvc 1
|
#define IsCompilerMsvc 1
|
||||||
#else
|
#else
|
||||||
#error Unknown compiler
|
#error Unknown compiler
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Language
|
//- Language
|
||||||
#if defined(__HLSL_VERSION)
|
#if defined(__HLSL_VERSION)
|
||||||
#define IsLanguageC 0
|
#define IsLanguageC 0
|
||||||
#define IsLanguageG 1
|
#define IsLanguageG 1
|
||||||
#else
|
#else
|
||||||
#define IsLanguageC 1
|
#define IsLanguageC 1
|
||||||
#define IsLanguageG 0
|
#define IsLanguageG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Platform system
|
//- Platform system
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define IsPlatformWindows 1
|
#define IsPlatformWindows 1
|
||||||
#define IsPlatformMac 0
|
#define IsPlatformMac 0
|
||||||
#define IsPlatformLinux 0
|
#define IsPlatformLinux 0
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#define IsPlatformWindows 0
|
#define IsPlatformWindows 0
|
||||||
#define IsPlatformMac 1
|
#define IsPlatformMac 1
|
||||||
#define IsPlatformLinux 0
|
#define IsPlatformLinux 0
|
||||||
#elif defined(__gnu_linux__)
|
#elif defined(__gnu_linux__)
|
||||||
#define IsPlatformWindows 0
|
#define IsPlatformWindows 0
|
||||||
#define IsPlatformMac 0
|
#define IsPlatformMac 0
|
||||||
#define IsPlatformLinux 1
|
#define IsPlatformLinux 1
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
#define IsPlatformWindows 0
|
#define IsPlatformWindows 0
|
||||||
#define IsPlatformMac 0
|
#define IsPlatformMac 0
|
||||||
#define IsPlatformLinux 0
|
#define IsPlatformLinux 0
|
||||||
#else
|
#else
|
||||||
#error Unknown platform
|
#error Unknown platform
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Architecture
|
//- Architecture
|
||||||
#if defined(_M_AMD64) || defined(__amd64__)
|
#if defined(_M_AMD64) || defined(__amd64__)
|
||||||
#define IsArchX64 1
|
#define IsArchX64 1
|
||||||
#define IsArchArm64 0
|
#define IsArchArm64 0
|
||||||
#elif defined(_M_ARM64) || defined(__aarch64__)
|
#elif defined(_M_ARM64) || defined(__aarch64__)
|
||||||
#define IsArchX64 0
|
#define IsArchX64 0
|
||||||
#define IsArchArm64 1
|
#define IsArchArm64 1
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
#define IsArchX64 0
|
#define IsArchX64 0
|
||||||
#define IsArchArm64 0
|
#define IsArchArm64 0
|
||||||
#else
|
#else
|
||||||
#error Unknown architecture
|
#error Unknown architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Cache line size
|
//- Cache line size
|
||||||
@ -102,21 +102,21 @@
|
|||||||
//- Windows NTDDI version
|
//- Windows NTDDI version
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
#if 0
|
#if 0
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define NTDDI_WIN11_DT 0x0C0A0000
|
#define NTDDI_WIN11_DT 0x0C0A0000
|
||||||
#define NTDDI_VERSION 0x0A000000
|
#define NTDDI_VERSION 0x0A000000
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
#define _ALLOW_RTCc_IN_STL 1
|
#define _ALLOW_RTCc_IN_STL 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ C headers
|
//~ C headers
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -129,27 +129,27 @@
|
|||||||
|
|
||||||
//- Debug assert
|
//- Debug assert
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ ":" Stringize(__LINE__) ":0: assertion failed: "#cond""))))
|
#define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ ":" Stringize(__LINE__) ":0: assertion failed: "#cond""))))
|
||||||
#define DEBUGBREAK __debugbreak()
|
#define DEBUGBREAK __debugbreak()
|
||||||
#else
|
#else
|
||||||
#define Assert(cond) ((cond) ? 1 : (__builtin_trap(), 0))
|
#define Assert(cond) ((cond) ? 1 : (__builtin_trap(), 0))
|
||||||
#define DEBUGBREAK __builtin_debugtrap()
|
#define DEBUGBREAK __builtin_debugtrap()
|
||||||
#endif
|
#endif
|
||||||
#define DEBUGBREAKABLE { volatile i32 __DEBUGBREAKABLE_VAR = 0; __DEBUGBREAKABLE_VAR; } (void)0
|
#define DEBUGBREAKABLE { volatile i32 __DEBUGBREAKABLE_VAR = 0; __DEBUGBREAKABLE_VAR; } (void)0
|
||||||
#else
|
#else
|
||||||
#define Assert(cond) (void)(0)
|
#define Assert(cond) (void)(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Address sanitization
|
//- Address sanitization
|
||||||
#if IsAsanEnabled
|
#if IsAsanEnabled
|
||||||
void __asan_poison_memory_region(void const volatile *, size_t);
|
void __asan_poison_memory_region(void const volatile *, size_t);
|
||||||
void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
||||||
#define AsanPoison(addr, size) __asan_poison_memory_region((addr), (size))
|
#define AsanPoison(addr, size) __asan_poison_memory_region((addr), (size))
|
||||||
#define AsanUnpoison(addr, size) __asan_unpoison_memory_region((addr), (size))
|
#define AsanUnpoison(addr, size) __asan_unpoison_memory_region((addr), (size))
|
||||||
#else
|
#else
|
||||||
#define AsanPoison(addr, size)
|
#define AsanPoison(addr, size)
|
||||||
#define AsanUnpoison(addr, size)
|
#define AsanUnpoison(addr, size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -157,24 +157,24 @@
|
|||||||
|
|
||||||
//- Zero initialization
|
//- Zero initialization
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define Zi { 0 }
|
#define Zi { 0 }
|
||||||
#else
|
#else
|
||||||
#define Zi { }
|
#define Zi { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Inline
|
//- Inline
|
||||||
#define Inline static inline
|
#define Inline static inline
|
||||||
|
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define ForceInline Inline __forceinline
|
#define ForceInline Inline __forceinline
|
||||||
#else
|
#else
|
||||||
#define ForceInline Inline __attribute((always_inline))
|
#define ForceInline Inline __attribute((always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define ForceNoInline __declspec(noinline)
|
#define ForceNoInline __declspec(noinline)
|
||||||
#else
|
#else
|
||||||
#define ForceNoInline __attribute__((noinline))
|
#define ForceNoInline __attribute__((noinline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Static
|
//- Static
|
||||||
@ -183,35 +183,35 @@
|
|||||||
|
|
||||||
//- Read-only
|
//- Read-only
|
||||||
#if IsPlatformWindows
|
#if IsPlatformWindows
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#pragma section(".rdata$", read)
|
#pragma section(".rdata$", read)
|
||||||
#define Readonly __declspec(allocate(".rdata$"))
|
#define Readonly __declspec(allocate(".rdata$"))
|
||||||
#else
|
#else
|
||||||
#define Readonly __declspec(allocate(".rdata$"))
|
#define Readonly __declspec(allocate(".rdata$"))
|
||||||
#endif
|
#endif
|
||||||
#elif IsPlatformMac
|
#elif IsPlatformMac
|
||||||
#define Readonly __attribute((section("__TEXT,__const")))
|
#define Readonly __attribute((section("__TEXT,__const")))
|
||||||
#else
|
#else
|
||||||
#define Readonly __attribute((section(".rodata")))
|
#define Readonly __attribute((section(".rodata")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Thread-local
|
//- Thread-local
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define ThreadLocal __declspec(thread)
|
#define ThreadLocal __declspec(thread)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Compiler memory barriers
|
//- Compiler memory barriers
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define CompilerBarrier() _ReadWriteBarrier()
|
#define CompilerBarrier() _ReadWriteBarrier()
|
||||||
#elif IsArchX64
|
#elif IsArchX64
|
||||||
#define CompilerBarrier() __asm__ volatile("" ::: "memory")
|
#define CompilerBarrier() __asm__ volatile("" ::: "memory")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Fallthrough
|
//- Fallthrough
|
||||||
#if IsCompilerClang
|
#if IsCompilerClang
|
||||||
#define FALLTHROUGH __attribute((fallthrough))
|
#define FALLTHROUGH __attribute((fallthrough))
|
||||||
#else
|
#else
|
||||||
#define FALLTHROUGH
|
#define FALLTHROUGH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Preprocessor concatenation
|
//- Preprocessor concatenation
|
||||||
@ -253,23 +253,23 @@
|
|||||||
|
|
||||||
#define SllQueuePushNZ(nil,f,l,n,next) \
|
#define SllQueuePushNZ(nil,f,l,n,next) \
|
||||||
( \
|
( \
|
||||||
CheckNil(nil,f) ? \
|
CheckNil(nil,f) ? \
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||||
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)) \
|
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define SllQueuePushFrontNZ(nil,f,l,n,next) \
|
#define SllQueuePushFrontNZ(nil,f,l,n,next) \
|
||||||
( \
|
( \
|
||||||
CheckNil(nil,f) ? \
|
CheckNil(nil,f) ? \
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||||
((n)->next=(f),(f)=(n)) \
|
((n)->next=(f),(f)=(n)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define SllQueuePopNZ(nil,f,l,next) \
|
#define SllQueuePopNZ(nil,f,l,next) \
|
||||||
( \
|
( \
|
||||||
(f)==(l) ? \
|
(f)==(l) ? \
|
||||||
(SetNil(nil,f),SetNil(nil,l)) : \
|
(SetNil(nil,f),SetNil(nil,l)) : \
|
||||||
((f)=(f)->next) \
|
((f)=(f)->next) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define SllQueuePushN(f,l,n,next) SllQueuePushNZ(0,f,l,n,next)
|
#define SllQueuePushN(f,l,n,next) SllQueuePushNZ(0,f,l,n,next)
|
||||||
@ -283,28 +283,28 @@
|
|||||||
|
|
||||||
#define DllStackPushNPZ(nil,f,n,next,prev) \
|
#define DllStackPushNPZ(nil,f,n,next,prev) \
|
||||||
( \
|
( \
|
||||||
SetNil(nil,(n)->prev), \
|
SetNil(nil,(n)->prev), \
|
||||||
((n)->next = (f)), \
|
((n)->next = (f)), \
|
||||||
CheckNil(nil,f) ? (0) : ((f)->prev = (n)), \
|
CheckNil(nil,f) ? (0) : ((f)->prev = (n)), \
|
||||||
((f) = (n)) \
|
((f) = (n)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DllStackInsertNPZ(nil,f,p,n,next,prev) \
|
#define DllStackInsertNPZ(nil,f,p,n,next,prev) \
|
||||||
( \
|
( \
|
||||||
(CheckNil(nil,f) || CheckNil(nil,p)) ? (DllStackPushNPZ(nil,(f),(n),next,prev)) : \
|
(CheckNil(nil,f) || CheckNil(nil,p)) ? (DllStackPushNPZ(nil,(f),(n),next,prev)) : \
|
||||||
( \
|
( \
|
||||||
((n)->prev = (p)), \
|
((n)->prev = (p)), \
|
||||||
((n)->next = (p)->next), \
|
((n)->next = (p)->next), \
|
||||||
((p)->next = (n)), \
|
((p)->next = (n)), \
|
||||||
CheckNil(nil,(p)->next) ? (0) : ((p)->next->prev = (n)) \
|
CheckNil(nil,(p)->next) ? (0) : ((p)->next->prev = (n)) \
|
||||||
) \
|
) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DllStackRemoveNPZ(nil,f,n,next,prev) \
|
#define DllStackRemoveNPZ(nil,f,n,next,prev) \
|
||||||
( \
|
( \
|
||||||
((n) == (f) ? ((f) = (n)->next) : (0)), \
|
((n) == (f) ? ((f) = (n)->next) : (0)), \
|
||||||
(CheckNil(nil,(n)->next) ? (0) : ((n)->next->prev = (n)->prev)), \
|
(CheckNil(nil,(n)->next) ? (0) : ((n)->next->prev = (n)->prev)), \
|
||||||
(CheckNil(nil,(n)->prev) ? (0) : ((n)->prev->next = (n)->next)) \
|
(CheckNil(nil,(n)->prev) ? (0) : ((n)->prev->next = (n)->next)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DllStackPushNP(f,n,next,prev) DllStackPushNPZ(0,f,n,next,prev)
|
#define DllStackPushNP(f,n,next,prev) DllStackPushNPZ(0,f,n,next,prev)
|
||||||
@ -318,29 +318,29 @@
|
|||||||
|
|
||||||
#define DllQueueInsertNPZ(nil,f,l,p,n,next,prev) \
|
#define DllQueueInsertNPZ(nil,f,l,p,n,next,prev) \
|
||||||
( \
|
( \
|
||||||
CheckNil(nil,f) ? \
|
CheckNil(nil,f) ? \
|
||||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) : \
|
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) : \
|
||||||
CheckNil(nil,p) ? \
|
CheckNil(nil,p) ? \
|
||||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) : \
|
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) : \
|
||||||
((p)==(l)) ? \
|
((p)==(l)) ? \
|
||||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
|
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
|
||||||
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : \
|
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : \
|
||||||
( \
|
( \
|
||||||
(p)->next->prev = (n))), \
|
(p)->next->prev = (n))), \
|
||||||
((n)->next = (p)->next), \
|
((n)->next = (p)->next), \
|
||||||
((p)->next = (n)), \
|
((p)->next = (n)), \
|
||||||
((n)->prev = (p)) \
|
((n)->prev = (p)) \
|
||||||
) \
|
) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DllQueueRemoveNPZ(nil,f,l,n,next,prev) \
|
#define DllQueueRemoveNPZ(nil,f,l,n,next,prev) \
|
||||||
( \
|
( \
|
||||||
((n) == (f) ? (f) = (n)->next : (0)), \
|
((n) == (f) ? (f) = (n)->next : (0)), \
|
||||||
((n) == (l) ? (l) = (l)->prev : (0)), \
|
((n) == (l) ? (l) = (l)->prev : (0)), \
|
||||||
(CheckNil(nil,(n)->prev) ? (0) : \
|
(CheckNil(nil,(n)->prev) ? (0) : \
|
||||||
((n)->prev->next = (n)->next)), \
|
((n)->prev->next = (n)->next)), \
|
||||||
(CheckNil(nil,(n)->next) ? (0) : \
|
(CheckNil(nil,(n)->next) ? (0) : \
|
||||||
((n)->next->prev = (n)->prev)) \
|
((n)->next->prev = (n)->prev)) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define DllQueuePushNPZ(nil,f,l,n,next,prev) DllQueueInsertNPZ(nil,f,l,l,n,next,prev)
|
#define DllQueuePushNPZ(nil,f,l,n,next,prev) DllQueueInsertNPZ(nil,f,l,l,n,next,prev)
|
||||||
@ -384,20 +384,20 @@
|
|||||||
//~ Intrinsic headers
|
//~ Intrinsic headers
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
/* Intrinsic header info:
|
/* Intrinsic header info:
|
||||||
* mmintrin.h MMX
|
* mmintrin.h MMX
|
||||||
* xmmintrin.h SSE
|
* xmmintrin.h SSE
|
||||||
* emmintrin.h SSE2
|
* emmintrin.h SSE2
|
||||||
* pmmintrin.h SSE3
|
* pmmintrin.h SSE3
|
||||||
* tmmintrin.h SSSE3
|
* tmmintrin.h SSSE3
|
||||||
* smmintrin.h SSE4.1
|
* smmintrin.h SSE4.1
|
||||||
* nmmintrin.h SSE4.2
|
* nmmintrin.h SSE4.2
|
||||||
* ammintrin.h SSE4A
|
* ammintrin.h SSE4A
|
||||||
* wmmintrin.h AES
|
* wmmintrin.h AES
|
||||||
* immintrin.h AVX, AVX2, FMA
|
* immintrin.h AVX, AVX2, FMA
|
||||||
*/
|
*/
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#include <nmmintrin.h> /* SSE4.2 */
|
#include <nmmintrin.h> /* SSE4.2 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -410,14 +410,14 @@
|
|||||||
|
|
||||||
//- Enum
|
//- Enum
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define Enum(name) typedef enum name name; enum name
|
#define Enum(name) typedef enum name name; enum name
|
||||||
#else
|
#else
|
||||||
#define Enum(name) enum name
|
#define Enum(name) enum name
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- alignof
|
//- alignof
|
||||||
#if IsLanguageC && (IsCompilerMsvc || __STDC_VERSION__ < 202311L)
|
#if IsLanguageC && (IsCompilerMsvc || __STDC_VERSION__ < 202311L)
|
||||||
#define alignof(type) __alignof(type)
|
#define alignof(type) __alignof(type)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- field sizeof
|
//- field sizeof
|
||||||
@ -425,7 +425,7 @@
|
|||||||
|
|
||||||
//- countof
|
//- countof
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define countof(a) (sizeof(a) / sizeof((a)[0]))
|
#define countof(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- IsFixedArray
|
//- IsFixedArray
|
||||||
@ -434,11 +434,11 @@
|
|||||||
|
|
||||||
//- offsetof
|
//- offsetof
|
||||||
#if !IsCompilerMsvc
|
#if !IsCompilerMsvc
|
||||||
#ifdef _CRT_USE_BUILTIN_OFFSETOF
|
#ifdef _CRT_USE_BUILTIN_OFFSETOF
|
||||||
#define offsetof(type, field) __builtin_offsetof(type, field)
|
#define offsetof(type, field) __builtin_offsetof(type, field)
|
||||||
#else
|
#else
|
||||||
#define offsetof(type, field) ((u64)&(((type *)0)->field))
|
#define offsetof(type, field) ((u64)&(((type *)0)->field))
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- struct region
|
//- struct region
|
||||||
@ -449,44 +449,44 @@
|
|||||||
|
|
||||||
//- Packed
|
//- Packed
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define Packed(s) __pragma(pack(push, 1)) s __pragma(pack(pop))
|
#define Packed(s) __pragma(pack(push, 1)) s __pragma(pack(pop))
|
||||||
#elif IsCompilerClang
|
#elif IsCompilerClang
|
||||||
#define Packed(s) s __attribute((__packed__))
|
#define Packed(s) s __attribute((__packed__))
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
#define Packed(s) s
|
#define Packed(s) s
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- alignas
|
//- alignas
|
||||||
#if (IsCompilerMsvc && IsLanguageC) || (IsLanguageC && __STDC_VERSION__ < 202311L)
|
#if (IsCompilerMsvc && IsLanguageC) || (IsLanguageC && __STDC_VERSION__ < 202311L)
|
||||||
#if IsCompilerMsvc
|
#if IsCompilerMsvc
|
||||||
#define alignas(n) __declspec(align(n))
|
#define alignas(n) __declspec(align(n))
|
||||||
#else
|
#else
|
||||||
#define alignas(n) __attribute__((aligned(n)))
|
#define alignas(n) __attribute__((aligned(n)))
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Scalar types
|
//~ Scalar types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
typedef int8_t i8;
|
typedef int8_t i8;
|
||||||
typedef int16_t i16;
|
typedef int16_t i16;
|
||||||
typedef int32_t i32;
|
typedef int32_t i32;
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef double f64;
|
typedef double f64;
|
||||||
typedef i8 b8;
|
typedef i8 b8;
|
||||||
typedef u32 b32;
|
typedef u32 b32;
|
||||||
Struct(U128) { u64 hi; u64 lo; };
|
Struct(U128) { u64 hi; u64 lo; };
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
typedef int i32;
|
typedef int i32;
|
||||||
typedef uint u32;
|
typedef uint u32;
|
||||||
typedef float f32;
|
typedef float f32;
|
||||||
typedef uint b32;
|
typedef uint b32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Min / max constants
|
//- Min / max constants
|
||||||
@ -507,274 +507,274 @@
|
|||||||
|
|
||||||
//- Float infinity / nan constants
|
//- Float infinity / nan constants
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
Global const u32 _f32_infinity_u32 = 0x7f800000;
|
Global const u32 _f32_infinity_u32 = 0x7f800000;
|
||||||
Global const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32;
|
Global const f32 *_f32_infinity = (f32 *)&_f32_infinity_u32;
|
||||||
#define F32Infinity (*_f32_infinity)
|
#define F32Infinity (*_f32_infinity)
|
||||||
|
|
||||||
Global const u64 _f64_infinity_u64 = 0x7ff0000000000000ULL;
|
Global const u64 _f64_infinity_u64 = 0x7ff0000000000000ULL;
|
||||||
Global const f64 *_f64_infinity = (f64 *)&_f64_infinity_u64;
|
Global const f64 *_f64_infinity = (f64 *)&_f64_infinity_u64;
|
||||||
#define F64Infinity (*_f64_infinity)
|
#define F64Infinity (*_f64_infinity)
|
||||||
|
|
||||||
Global const u32 _f32_nan_u32 = 0x7f800001;
|
Global const u32 _f32_nan_u32 = 0x7f800001;
|
||||||
Global const f32 *_f32_nan = (f32 *)&_f32_nan_u32;
|
Global const f32 *_f32_nan = (f32 *)&_f32_nan_u32;
|
||||||
#define F32Nan (*_f32_nan)
|
#define F32Nan (*_f32_nan)
|
||||||
|
|
||||||
Global const u64 _f64_nan_u64 = 0x7ff8000000000001;
|
Global const u64 _f64_nan_u64 = 0x7ff8000000000001;
|
||||||
Global const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
|
Global const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
|
||||||
#define F64Nan (*_f64_nan)
|
#define F64Nan (*_f64_nan)
|
||||||
|
|
||||||
#define IsF32Nan(x) (x != x)
|
#define IsF32Nan(x) (x != x)
|
||||||
#define IsF64Nan(x) (x != x)
|
#define IsF64Nan(x) (x != x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Atomics
|
//~ Atomics
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
//- Atomic types
|
//- Atomic types
|
||||||
Struct(Atomic8) { volatile i8 _v; };
|
Struct(Atomic8) { volatile i8 _v; };
|
||||||
Struct(Atomic16) { volatile i16 _v; };
|
Struct(Atomic16) { volatile i16 _v; };
|
||||||
Struct(Atomic32) { volatile i32 _v; };
|
Struct(Atomic32) { volatile i32 _v; };
|
||||||
Struct(Atomic64) { volatile i64 _v; };
|
Struct(Atomic64) { volatile i64 _v; };
|
||||||
|
|
||||||
//- Cache-line isolated aligned atomic types
|
//- Cache-line isolated aligned atomic types
|
||||||
AlignedStruct(Atomic8Padded, CachelineSize) { Atomic8 v; };
|
AlignedStruct(Atomic8Padded, CachelineSize) { Atomic8 v; };
|
||||||
AlignedStruct(Atomic16Padded, CachelineSize) { Atomic16 v; };
|
AlignedStruct(Atomic16Padded, CachelineSize) { Atomic16 v; };
|
||||||
AlignedStruct(Atomic32Padded, CachelineSize) { Atomic32 v; };
|
AlignedStruct(Atomic32Padded, CachelineSize) { Atomic32 v; };
|
||||||
AlignedStruct(Atomic64Padded, CachelineSize) { Atomic64 v; };
|
AlignedStruct(Atomic64Padded, CachelineSize) { Atomic64 v; };
|
||||||
StaticAssert(alignof(Atomic8Padded) == CachelineSize && sizeof(Atomic8Padded) % CachelineSize == 0);
|
StaticAssert(alignof(Atomic8Padded) == CachelineSize && sizeof(Atomic8Padded) % CachelineSize == 0);
|
||||||
StaticAssert(alignof(Atomic16Padded) == CachelineSize && sizeof(Atomic16Padded) % CachelineSize == 0);
|
StaticAssert(alignof(Atomic16Padded) == CachelineSize && sizeof(Atomic16Padded) % CachelineSize == 0);
|
||||||
StaticAssert(alignof(Atomic32Padded) == CachelineSize && sizeof(Atomic32Padded) % CachelineSize == 0);
|
StaticAssert(alignof(Atomic32Padded) == CachelineSize && sizeof(Atomic32Padded) % CachelineSize == 0);
|
||||||
StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0);
|
StaticAssert(alignof(Atomic64Padded) == CachelineSize && sizeof(Atomic64Padded) % CachelineSize == 0);
|
||||||
|
|
||||||
#if IsPlatformWindows && IsArchX64
|
#if IsPlatformWindows && IsArchX64
|
||||||
//- 8 bit atomic ops
|
//- 8 bit atomic ops
|
||||||
ForceInline i8 Atomic8Fetch (Atomic8 *x) { CompilerBarrier(); i8 result = x->_v; CompilerBarrier(); return result; }
|
ForceInline i8 Atomic8Fetch (Atomic8 *x) { CompilerBarrier(); i8 result = x->_v; CompilerBarrier(); return result; }
|
||||||
ForceInline void Atomic8Set (Atomic8 *x, i8 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
ForceInline void Atomic8Set (Atomic8 *x, i8 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
||||||
ForceInline i8 Atomic8FetchSet (Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&x->_v, e); }
|
ForceInline i8 Atomic8FetchSet (Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((volatile char *)&x->_v, e); }
|
||||||
ForceInline i8 Atomic8FetchTestSet (Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&x->_v, e, c); }
|
ForceInline i8 Atomic8FetchTestSet (Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((volatile char *)&x->_v, e, c); }
|
||||||
ForceInline i8 Atomic8FetchXor (Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((volatile char *)&x->_v, c); }
|
ForceInline i8 Atomic8FetchXor (Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((volatile char *)&x->_v, c); }
|
||||||
ForceInline i8 Atomic8FetchAdd (Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((volatile char *)&x->_v, a); }
|
ForceInline i8 Atomic8FetchAdd (Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((volatile char *)&x->_v, a); }
|
||||||
//- 16 bit atomic ops
|
//- 16 bit atomic ops
|
||||||
ForceInline i16 Atomic16Fetch (Atomic16 *x) { CompilerBarrier(); i16 result = x->_v; CompilerBarrier(); return result; }
|
ForceInline i16 Atomic16Fetch (Atomic16 *x) { CompilerBarrier(); i16 result = x->_v; CompilerBarrier(); return result; }
|
||||||
ForceInline void Atomic16Set (Atomic16 *x, i16 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
ForceInline void Atomic16Set (Atomic16 *x, i16 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
||||||
ForceInline i16 Atomic16FetchSet (Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
|
ForceInline i16 Atomic16FetchSet (Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
|
||||||
ForceInline i16 Atomic16FetchTestSet (Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
|
ForceInline i16 Atomic16FetchTestSet (Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
|
||||||
ForceInline i16 Atomic16FetchXor (Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
|
ForceInline i16 Atomic16FetchXor (Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
|
||||||
ForceInline i16 Atomic16FetchAdd (Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
|
ForceInline i16 Atomic16FetchAdd (Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
|
||||||
//- 32 bit atomic ops
|
//- 32 bit atomic ops
|
||||||
ForceInline i32 Atomic32Fetch (Atomic32 *x) { CompilerBarrier(); i32 result = x->_v; CompilerBarrier(); return result; }
|
ForceInline i32 Atomic32Fetch (Atomic32 *x) { CompilerBarrier(); i32 result = x->_v; CompilerBarrier(); return result; }
|
||||||
ForceInline void Atomic32Set (Atomic32 *x, i32 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
ForceInline void Atomic32Set (Atomic32 *x, i32 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
||||||
ForceInline i32 Atomic32FetchSet (Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
|
ForceInline i32 Atomic32FetchSet (Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
|
||||||
ForceInline i32 Atomic32FetchTestSet (Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
|
ForceInline i32 Atomic32FetchTestSet (Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
|
||||||
ForceInline i32 Atomic32FetchXor (Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v, c); }
|
ForceInline i32 Atomic32FetchXor (Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v, c); }
|
||||||
ForceInline i32 Atomic32FetchAdd (Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
|
ForceInline i32 Atomic32FetchAdd (Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
|
||||||
//- 64 bit atomic ops
|
//- 64 bit atomic ops
|
||||||
ForceInline i64 Atomic64Fetch (Atomic64 *x) { CompilerBarrier(); i64 result = x->_v; CompilerBarrier(); return result; }
|
ForceInline i64 Atomic64Fetch (Atomic64 *x) { CompilerBarrier(); i64 result = x->_v; CompilerBarrier(); return result; }
|
||||||
ForceInline void Atomic64Set (Atomic64 *x, i64 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
ForceInline void Atomic64Set (Atomic64 *x, i64 e) { CompilerBarrier(); x->_v = e; CompilerBarrier(); }
|
||||||
ForceInline i64 Atomic64FetchSet (Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
|
ForceInline i64 Atomic64FetchSet (Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
|
||||||
ForceInline i64 Atomic64FetchTestSet (Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
|
ForceInline i64 Atomic64FetchTestSet (Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
|
||||||
ForceInline i64 Atomic64FetchXor (Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
|
ForceInline i64 Atomic64FetchXor (Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
|
||||||
ForceInline i64 Atomic64FetchAdd (Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
|
ForceInline i64 Atomic64FetchAdd (Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
|
||||||
#else
|
#else
|
||||||
#error Atomics not implemented
|
#error Atomics not implemented
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Ticket mutex
|
//~ Ticket mutex
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
Struct(TicketMutex)
|
Struct(TicketMutex)
|
||||||
{
|
{
|
||||||
Atomic64Padded ticket;
|
Atomic64Padded ticket;
|
||||||
Atomic64Padded serving;
|
Atomic64Padded serving;
|
||||||
};
|
};
|
||||||
|
|
||||||
ForceInline void LockTicketMutex(TicketMutex *tm)
|
ForceInline void LockTicketMutex(TicketMutex *tm)
|
||||||
|
{
|
||||||
|
i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1);
|
||||||
|
while (Atomic64Fetch(&tm->serving.v) != ticket)
|
||||||
{
|
{
|
||||||
i64 ticket = Atomic64FetchAdd(&tm->ticket.v, 1);
|
_mm_pause();
|
||||||
while (Atomic64Fetch(&tm->serving.v) != ticket)
|
|
||||||
{
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ForceInline void UnlockTicketMutex(TicketMutex *tm)
|
ForceInline void UnlockTicketMutex(TicketMutex *tm)
|
||||||
{
|
{
|
||||||
/* TODO: Atomic set w/ known ticket + 1 */
|
/* TODO: Atomic set w/ known ticket + 1 */
|
||||||
Atomic64FetchAdd(&tm->serving.v, 1);
|
Atomic64FetchAdd(&tm->serving.v, 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ String types
|
//~ String types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define STRING(size, data) ((String) { (size), (data) })
|
#define STRING(size, data) ((String) { (size), (data) })
|
||||||
#define Zstr ((String) { 0, 0})
|
#define Zstr ((String) { 0, 0})
|
||||||
#define Lit(cstr_lit) (String) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
#define Lit(cstr_lit) (String) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
||||||
#define CompLit(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
#define CompLit(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
||||||
#define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
#define StringFromPointers(p0, p1) ((String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
||||||
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
#define StringFromStruct(ptr) ((String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
||||||
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
|
#define StringFromArena(arena) (STRING((arena)->pos, ArenaFirst(arena, u8)))
|
||||||
|
|
||||||
#define StringFromFixedArray(a) \
|
#define StringFromFixedArray(a) \
|
||||||
( \
|
( \
|
||||||
Assert(IsFixedArray(a)), \
|
Assert(IsFixedArray(a)), \
|
||||||
((String) { .len = sizeof(a), .text = (u8 *)(a) }) \
|
((String) { .len = sizeof(a), .text = (u8 *)(a) }) \
|
||||||
)
|
)
|
||||||
|
|
||||||
Struct(String)
|
Struct(String)
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
u8 *text;
|
u8 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(String16)
|
Struct(String16)
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
u16 *text;
|
u16 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(String32)
|
Struct(String32)
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
u32 *text;
|
u32 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(StringArray)
|
Struct(StringArray)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
String *strings;
|
String *strings;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(StringListNode)
|
Struct(StringListNode)
|
||||||
{
|
{
|
||||||
String s;
|
String s;
|
||||||
StringListNode *next;
|
StringListNode *next;
|
||||||
StringListNode *prev;
|
StringListNode *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(StringList)
|
Struct(StringList)
|
||||||
{
|
{
|
||||||
StringListNode *first;
|
StringListNode *first;
|
||||||
StringListNode *last;
|
StringListNode *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Arena types
|
//~ Arena types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
Struct(Arena)
|
Struct(Arena)
|
||||||
{
|
{
|
||||||
u64 pos;
|
u64 pos;
|
||||||
u64 committed;
|
u64 committed;
|
||||||
u64 reserved;
|
u64 reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(TempArena)
|
Struct(TempArena)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
u64 start_pos;
|
u64 start_pos;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Resource types
|
//~ Resource types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define ResourceEmbeddedMagic 0xfc060937194f4406
|
#define ResourceEmbeddedMagic 0xfc060937194f4406
|
||||||
|
|
||||||
Struct(ResourceStore)
|
Struct(ResourceStore)
|
||||||
{
|
{
|
||||||
u64 v;
|
u64 v;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ResourceKey)
|
Struct(ResourceKey)
|
||||||
{
|
{
|
||||||
u64 v;
|
u64 v;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Cpu topology types
|
//~ Cpu topology types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
Struct(CpuTopologyInfo)
|
Struct(CpuTopologyInfo)
|
||||||
{
|
{
|
||||||
i32 num_logical_cores; /* Includes P cores, Non-P cores, SMT siblings */
|
i32 num_logical_cores; /* Includes P cores, Non-P cores, SMT siblings */
|
||||||
i32 num_physical_cores; /* Includes P Cores, Non-P Cores */
|
i32 num_physical_cores; /* Includes P Cores, Non-P Cores */
|
||||||
i32 num_physical_performance_cores; /* Includes P Cores */
|
i32 num_physical_performance_cores; /* Includes P Cores */
|
||||||
i32 num_physical_non_performance_cores; /* Includes Non-P cores */
|
i32 num_physical_non_performance_cores; /* Includes Non-P cores */
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Shader linkage types
|
//~ Shader linkage types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
Struct(VertexShader) { ResourceKey resource; };
|
Struct(VertexShader) { ResourceKey resource; };
|
||||||
Struct(PixelShader) { ResourceKey resource; };
|
Struct(PixelShader) { ResourceKey resource; };
|
||||||
Struct(ComputeShader) { ResourceKey resource; };
|
Struct(ComputeShader) { ResourceKey resource; };
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
#define Semantic(t, n) t n : n
|
#define Semantic(t, n) t n : n
|
||||||
#define ComputeShader(name, x) [numthreads(x, 1, 1)] void name(Semantic(u32, SV_DispatchThreadID))
|
#define ComputeShader(name, x) [numthreads(x, 1, 1)] void name(Semantic(u32, SV_DispatchThreadID))
|
||||||
#define ComputeShader2D(name, x, y) [numthreads(x, y, 1)] void name(Semantic(Vec2U32, SV_DispatchThreadID))
|
#define ComputeShader2D(name, x, y) [numthreads(x, y, 1)] void name(Semantic(Vec2U32, SV_DispatchThreadID))
|
||||||
#define ComputeShader3D(name, x, y, z) [numthreads(x, y, z)] void name(Semantic(Vec3U32, SV_DispatchThreadID))
|
#define ComputeShader3D(name, x, y, z) [numthreads(x, y, z)] void name(Semantic(Vec3U32, SV_DispatchThreadID))
|
||||||
#define VertexShader(name, return_type) return_type name(Semantic(u32, SV_InstanceID), Semantic(u32, SV_VertexID))
|
#define VertexShader(name, return_type) return_type name(Semantic(u32, SV_InstanceID), Semantic(u32, SV_VertexID))
|
||||||
#define PixelShader(name, return_type, ...) return_type name(__VA_ARGS__)
|
#define PixelShader(name, return_type, ...) return_type name(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Exit callback types
|
//~ Exit callback types
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define ExitFuncDef(name) void name(void)
|
#define ExitFuncDef(name) void name(void)
|
||||||
typedef ExitFuncDef(ExitFunc);
|
typedef ExitFuncDef(ExitFunc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Core api
|
//~ @hookdecl Core api
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
StringList GetRawCommandline(void);
|
StringList GetRawCommandline(void);
|
||||||
void Echo(String msg);
|
void Echo(String msg);
|
||||||
b32 Panic(String msg);
|
b32 Panic(String msg);
|
||||||
b32 IsRunningInDebugger(void);
|
b32 IsRunningInDebugger(void);
|
||||||
i64 TimeNs(void);
|
i64 TimeNs(void);
|
||||||
void TrueRand(String buffer);
|
void TrueRand(String buffer);
|
||||||
CpuTopologyInfo GetCpuTopologyInfo(void);
|
CpuTopologyInfo GetCpuTopologyInfo(void);
|
||||||
void SleepSeconds(f64 seconds);
|
void SleepSeconds(f64 seconds);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Swap
|
//~ @hookdecl Swap
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
b32 IsSwappedIn(void);
|
b32 IsSwappedIn(void);
|
||||||
b32 IsSwappingOut(void);
|
b32 IsSwappingOut(void);
|
||||||
|
|
||||||
String SwappedStateFromName(Arena *arena, String name);
|
String SwappedStateFromName(Arena *arena, String name);
|
||||||
void WriteSwappedState(String name, String data);
|
void WriteSwappedState(String name, String data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Exit
|
//~ @hookdecl Exit
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
void OnExit(ExitFunc *func);
|
void OnExit(ExitFunc *func);
|
||||||
void SignalExit(i32 code);
|
void SignalExit(i32 code);
|
||||||
void ExitNow(i32 code);
|
void ExitNow(i32 code);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Bootstrap layers
|
//~ @hookdecl Bootstrap layers
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
void BootstrapLayers(void);
|
void BootstrapLayers(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,86 +3,86 @@
|
|||||||
|
|
||||||
Arena *AcquireArena(u64 reserve)
|
Arena *AcquireArena(u64 reserve)
|
||||||
{
|
{
|
||||||
reserve += ArenaHeaderSize;
|
reserve += ArenaHeaderSize;
|
||||||
|
|
||||||
/* Round up to nearest block size */
|
/* Round up to nearest block size */
|
||||||
u64 block_remainder = reserve % ArenaBlockSize;
|
u64 block_remainder = reserve % ArenaBlockSize;
|
||||||
if (block_remainder > 0)
|
if (block_remainder > 0)
|
||||||
{
|
{
|
||||||
reserve += ArenaBlockSize - block_remainder;
|
reserve += ArenaBlockSize - block_remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *base = ReserveMemory(reserve);
|
u8 *base = ReserveMemory(reserve);
|
||||||
if (!base)
|
if (!base)
|
||||||
{
|
{
|
||||||
Panic(Lit("Failed to reserve memory"));
|
Panic(Lit("Failed to reserve memory"));
|
||||||
}
|
}
|
||||||
u64 reserved = reserve;
|
u64 reserved = reserve;
|
||||||
AddGstat(ArenaMemoryReserved, reserve);
|
AddGstat(ArenaMemoryReserved, reserve);
|
||||||
|
|
||||||
/* Commit initial block */
|
/* Commit initial block */
|
||||||
base = CommitMemory(base, ArenaBlockSize);
|
base = CommitMemory(base, ArenaBlockSize);
|
||||||
if (!base)
|
if (!base)
|
||||||
{
|
{
|
||||||
Panic(Lit("Failed to commit initial memory block: System may be out of memory"));
|
Panic(Lit("Failed to commit initial memory block: System may be out of memory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
Assert(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
||||||
StaticAssert(ArenaHeaderSize <= ArenaBlockSize); /* Header must fit in first block */
|
StaticAssert(ArenaHeaderSize <= ArenaBlockSize); /* Header must fit in first block */
|
||||||
StaticAssert(sizeof(Arena) <= ArenaHeaderSize); /* Arena struct must fit in header */
|
StaticAssert(sizeof(Arena) <= ArenaHeaderSize); /* Arena struct must fit in header */
|
||||||
|
|
||||||
AsanPoison(base + sizeof(Arena), ArenaBlockSize - sizeof(Arena));
|
AsanPoison(base + sizeof(Arena), ArenaBlockSize - sizeof(Arena));
|
||||||
AddGstat(ArenaMemoryCommitted, ArenaBlockSize);
|
AddGstat(ArenaMemoryCommitted, ArenaBlockSize);
|
||||||
AddGstat(NumArenas, 1);
|
AddGstat(NumArenas, 1);
|
||||||
|
|
||||||
/* Create & return arena header at beginning of block */
|
/* Create & return arena header at beginning of block */
|
||||||
Arena *arena = (Arena *)base;
|
Arena *arena = (Arena *)base;
|
||||||
ZeroStruct(arena);
|
ZeroStruct(arena);
|
||||||
arena->committed = ArenaBlockSize - ArenaHeaderSize;
|
arena->committed = ArenaBlockSize - ArenaHeaderSize;
|
||||||
arena->reserved = reserved;
|
arena->reserved = reserved;
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseArena(Arena *arena)
|
void ReleaseArena(Arena *arena)
|
||||||
{
|
{
|
||||||
AsanUnpoison(arena, arena->committed + ArenaHeaderSize);
|
AsanUnpoison(arena, arena->committed + ArenaHeaderSize);
|
||||||
AddGstat(ArenaMemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
|
AddGstat(ArenaMemoryCommitted, -(i64)(arena->committed - ArenaHeaderSize));
|
||||||
AddGstat(ArenaMemoryReserved, -(i64)(arena->reserved));
|
AddGstat(ArenaMemoryReserved, -(i64)(arena->reserved));
|
||||||
AddGstat(NumArenas, -1);
|
AddGstat(NumArenas, -1);
|
||||||
ReleaseMemory(arena);
|
ReleaseMemory(arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the memory from src to dst, replacing old contents.
|
/* Copy the memory from src to dst, replacing old contents.
|
||||||
* Dst will expand if necessary. */
|
* Dst will expand if necessary. */
|
||||||
void CopyArena(Arena *dst, Arena *src)
|
void CopyArena(Arena *dst, Arena *src)
|
||||||
{
|
{
|
||||||
ResetArena(dst);
|
ResetArena(dst);
|
||||||
u64 data_size = src->pos;
|
u64 data_size = src->pos;
|
||||||
u8 *data_src = ArenaFirst(src, u8);
|
u8 *data_src = ArenaFirst(src, u8);
|
||||||
u8 *data_dst = PushBytesNoZero(dst, data_size, 1);
|
u8 *data_dst = PushBytesNoZero(dst, data_size, 1);
|
||||||
CopyBytes(data_dst, data_src, data_size);
|
CopyBytes(data_dst, data_src, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShrinkArena(Arena *arena)
|
void ShrinkArena(Arena *arena)
|
||||||
{
|
{
|
||||||
/* Not implemented */
|
/* Not implemented */
|
||||||
Assert(0);
|
Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetArenaReadonly(Arena *arena)
|
void SetArenaReadonly(Arena *arena)
|
||||||
{
|
{
|
||||||
SetMemoryReadonly(arena, arena->committed + ArenaHeaderSize);
|
SetMemoryReadonly(arena, arena->committed + ArenaHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetArenaReadWrite(Arena *arena)
|
void SetArenaReadWrite(Arena *arena)
|
||||||
{
|
{
|
||||||
SetMemoryReadWrite(arena, arena->committed + ArenaHeaderSize);
|
SetMemoryReadWrite(arena, arena->committed + ArenaHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ResetArena(Arena *arena)
|
void *ResetArena(Arena *arena)
|
||||||
{
|
{
|
||||||
PopTo(arena, 0);
|
PopTo(arena, 0);
|
||||||
return ArenaFirst(arena, u8);
|
return ArenaFirst(arena, u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -90,89 +90,89 @@ void *ResetArena(Arena *arena)
|
|||||||
|
|
||||||
void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
|
void *PushBytesNoZero(Arena *arena, u64 size, u64 align)
|
||||||
{
|
{
|
||||||
Assert(align > 0);
|
Assert(align > 0);
|
||||||
|
|
||||||
u8 *base = ArenaFirst(arena, u8);
|
u8 *base = ArenaFirst(arena, u8);
|
||||||
u64 start_pos = AlignU64(arena->pos, align);
|
u64 start_pos = AlignU64(arena->pos, align);
|
||||||
u64 end_pos = start_pos + size;
|
u64 end_pos = start_pos + size;
|
||||||
void *result = base + start_pos;
|
void *result = base + start_pos;
|
||||||
|
|
||||||
/* Commit new block(s) */
|
/* Commit new block(s) */
|
||||||
if (size > 0 && end_pos > arena->committed)
|
if (size > 0 && end_pos > arena->committed)
|
||||||
|
{
|
||||||
|
u64 blocks_needed = (end_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize;
|
||||||
|
u64 commit_bytes = blocks_needed * ArenaBlockSize;
|
||||||
|
u64 new_capacity = arena->committed + commit_bytes;
|
||||||
|
if (new_capacity > arena->reserved)
|
||||||
{
|
{
|
||||||
u64 blocks_needed = (end_pos - arena->committed + ArenaBlockSize - 1) / ArenaBlockSize;
|
/* Hard fail if we overflow reserved memory for now */
|
||||||
u64 commit_bytes = blocks_needed * ArenaBlockSize;
|
Panic(Lit("Failed to commit new memory block: Overflow of reserved memory"));
|
||||||
u64 new_capacity = arena->committed + commit_bytes;
|
|
||||||
if (new_capacity > arena->reserved)
|
|
||||||
{
|
|
||||||
/* Hard fail if we overflow reserved memory for now */
|
|
||||||
Panic(Lit("Failed to commit new memory block: Overflow of reserved memory"));
|
|
||||||
}
|
|
||||||
void *commit_address = base + arena->committed;
|
|
||||||
if (!CommitMemory(commit_address, commit_bytes))
|
|
||||||
{
|
|
||||||
/* Hard fail on memory allocation failure for now */
|
|
||||||
Panic(Lit("Failed to commit new memory block: System may be out of memory"));
|
|
||||||
}
|
|
||||||
arena->committed += commit_bytes;
|
|
||||||
AddGstat(ArenaMemoryCommitted, commit_bytes);
|
|
||||||
AsanPoison(commit_address, commit_bytes);
|
|
||||||
}
|
}
|
||||||
|
void *commit_address = base + arena->committed;
|
||||||
|
if (!CommitMemory(commit_address, commit_bytes))
|
||||||
|
{
|
||||||
|
/* Hard fail on memory allocation failure for now */
|
||||||
|
Panic(Lit("Failed to commit new memory block: System may be out of memory"));
|
||||||
|
}
|
||||||
|
arena->committed += commit_bytes;
|
||||||
|
AddGstat(ArenaMemoryCommitted, commit_bytes);
|
||||||
|
AsanPoison(commit_address, commit_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
AsanUnpoison(result, size);
|
AsanUnpoison(result, size);
|
||||||
arena->pos = end_pos;
|
arena->pos = end_pos;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *PushBytes(Arena *arena, u64 size, u64 align)
|
void *PushBytes(Arena *arena, u64 size, u64 align)
|
||||||
{
|
{
|
||||||
void *p = PushBytesNoZero(arena, size, align);
|
void *p = PushBytesNoZero(arena, size, align);
|
||||||
ZeroBytes(p, size);
|
ZeroBytes(p, size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *PushAlign(Arena *arena, u64 align)
|
void *PushAlign(Arena *arena, u64 align)
|
||||||
{
|
{
|
||||||
u64 push_count = AlignU64(arena->pos, align) - arena->pos;
|
u64 push_count = AlignU64(arena->pos, align) - arena->pos;
|
||||||
return PushStructsNoZero(arena, u8, push_count);
|
return PushStructsNoZero(arena, u8, push_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopTo(Arena *arena, u64 pos)
|
void PopTo(Arena *arena, u64 pos)
|
||||||
{
|
{
|
||||||
Assert(arena->pos >= pos);
|
Assert(arena->pos >= pos);
|
||||||
AsanPoison(ArenaFirst(arena, u8) + pos, arena->pos - pos);
|
AsanPoison(ArenaFirst(arena, u8) + pos, arena->pos - pos);
|
||||||
arena->pos = pos;
|
arena->pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopBytesNoCopy(Arena *arena, u64 size)
|
void PopBytesNoCopy(Arena *arena, u64 size)
|
||||||
{
|
{
|
||||||
Assert(arena->pos >= size);
|
Assert(arena->pos >= size);
|
||||||
u64 new_pos = arena->pos - size;
|
u64 new_pos = arena->pos - size;
|
||||||
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
|
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
|
||||||
arena->pos = new_pos;
|
arena->pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopBytes(Arena *arena, u64 size, void *copy_dst)
|
void PopBytes(Arena *arena, u64 size, void *copy_dst)
|
||||||
{
|
{
|
||||||
Assert(arena->pos >= size);
|
Assert(arena->pos >= size);
|
||||||
u64 new_pos = arena->pos - size;
|
u64 new_pos = arena->pos - size;
|
||||||
void *src = (void *)(ArenaFirst(arena, u8) + new_pos);
|
void *src = (void *)(ArenaFirst(arena, u8) + new_pos);
|
||||||
CopyBytes(copy_dst, src, size);
|
CopyBytes(copy_dst, src, size);
|
||||||
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
|
AsanPoison(ArenaFirst(arena, u8) + new_pos, arena->pos - new_pos);
|
||||||
arena->pos = new_pos;
|
arena->pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ArenaFirst_(Arena *arena, u64 align)
|
void *ArenaFirst_(Arena *arena, u64 align)
|
||||||
{
|
{
|
||||||
void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize, align);
|
void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize, align);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ArenaNext_(Arena *arena, u64 align)
|
void *ArenaNext_(Arena *arena, u64 align)
|
||||||
{
|
{
|
||||||
void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize + arena->pos, align);
|
void *result = (void *)AlignU64((u64)arena + ArenaHeaderSize + arena->pos, align);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -180,15 +180,15 @@ void *ArenaNext_(Arena *arena, u64 align)
|
|||||||
|
|
||||||
TempArena BeginTempArena(Arena *arena)
|
TempArena BeginTempArena(Arena *arena)
|
||||||
{
|
{
|
||||||
TempArena t = Zi;
|
TempArena t = Zi;
|
||||||
t.arena = arena;
|
t.arena = arena;
|
||||||
t.start_pos = arena->pos;
|
t.start_pos = arena->pos;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndTempArena(TempArena temp)
|
void EndTempArena(TempArena temp)
|
||||||
{
|
{
|
||||||
PopTo(temp.arena, temp.start_pos);
|
PopTo(temp.arena, temp.start_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -196,29 +196,29 @@ void EndTempArena(TempArena temp)
|
|||||||
|
|
||||||
TempArena BeginScratch(Arena *potential_conflict)
|
TempArena BeginScratch(Arena *potential_conflict)
|
||||||
{
|
{
|
||||||
/* This function is currently hard-coded for 2 thread-local scratch arenas */
|
/* This function is currently hard-coded for 2 thread-local scratch arenas */
|
||||||
StaticAssert(countof(Base_tl.arenas.scratch) == 2);
|
StaticAssert(countof(Base_tl.arenas.scratch) == 2);
|
||||||
|
|
||||||
/* Use `BeginScratchNoConflict` if no conflicts are present */
|
/* Use `BeginScratchNoConflict` if no conflicts are present */
|
||||||
Assert(potential_conflict != 0);
|
Assert(potential_conflict != 0);
|
||||||
|
|
||||||
Arena *scratch_arena = Base_tl.arenas.scratch[0];
|
Arena *scratch_arena = Base_tl.arenas.scratch[0];
|
||||||
if (scratch_arena == potential_conflict)
|
if (scratch_arena == potential_conflict)
|
||||||
{
|
{
|
||||||
scratch_arena = Base_tl.arenas.scratch[1];
|
scratch_arena = Base_tl.arenas.scratch[1];
|
||||||
}
|
}
|
||||||
TempArena temp = BeginTempArena(scratch_arena);
|
TempArena temp = BeginTempArena(scratch_arena);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
TempArena BeginScratchNoConflict_(void)
|
TempArena BeginScratchNoConflict_(void)
|
||||||
{
|
{
|
||||||
Arena *scratch_arena = Base_tl.arenas.scratch[0];
|
Arena *scratch_arena = Base_tl.arenas.scratch[0];
|
||||||
TempArena temp = BeginTempArena(scratch_arena);
|
TempArena temp = BeginTempArena(scratch_arena);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndScratch(TempArena scratch_temp)
|
void EndScratch(TempArena scratch_temp)
|
||||||
{
|
{
|
||||||
EndTempArena(scratch_temp);
|
EndTempArena(scratch_temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
Struct(ThreadLocalArenaCtx)
|
Struct(ThreadLocalArenaCtx)
|
||||||
{
|
{
|
||||||
Arena *perm;
|
Arena *perm;
|
||||||
Arena *scratch[2];
|
Arena *scratch[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -68,11 +68,11 @@ TempArena BeginScratchNoConflict_(void);
|
|||||||
void EndScratch(TempArena scratch_temp);
|
void EndScratch(TempArena scratch_temp);
|
||||||
|
|
||||||
/* This macro declares an unused "arena" variable that will produce a shadowing
|
/* This macro declares an unused "arena" variable that will produce a shadowing
|
||||||
* warning variable is present (due to shadowing). This is for catching obvious
|
* warning variable is present (due to shadowing). This is for catching obvious
|
||||||
* cases of `BeginScratchNoConflict` getting called when an `arena` variable
|
* cases of `BeginScratchNoConflict` getting called when an `arena` variable
|
||||||
* already exists in the caller's scope. */
|
* already exists in the caller's scope. */
|
||||||
#define BeginScratchNoConflict() \
|
#define BeginScratchNoConflict() \
|
||||||
BeginScratchNoConflict_(); \
|
BeginScratchNoConflict_(); \
|
||||||
do { \
|
do { \
|
||||||
u8 arena = 0; \
|
u8 arena = 0; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
void BootstrapAsync(void)
|
void BootstrapAsync(void)
|
||||||
{
|
{
|
||||||
/* TODO: Dynamic lane counts */
|
/* TODO: Dynamic lane counts */
|
||||||
DispatchWave(Lit("Async"), 4, AsyncWorkerEntryPoint, 0);
|
DispatchWave(Lit("Async"), 4, AsyncWorkerEntryPoint, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -12,23 +12,23 @@ void BootstrapAsync(void)
|
|||||||
|
|
||||||
void OnAsyncTick(AsyncTickCallbackFunc *func)
|
void OnAsyncTick(AsyncTickCallbackFunc *func)
|
||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
AsyncTickCallbackNode *n = PushStruct(perm, AsyncTickCallbackNode);
|
AsyncTickCallbackNode *n = PushStruct(perm, AsyncTickCallbackNode);
|
||||||
n->callback.func = func;
|
n->callback.func = func;
|
||||||
|
|
||||||
Lock lock = LockE(&Base.async.mutex);
|
Lock lock = LockE(&Base.async.mutex);
|
||||||
{
|
{
|
||||||
SllQueuePush(Base.async.first_callback_node, Base.async.last_callback_node, n);
|
SllQueuePush(Base.async.first_callback_node, Base.async.last_callback_node, n);
|
||||||
Base.async.callback_nodes_count += 1;
|
Base.async.callback_nodes_count += 1;
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalAsyncTick(void)
|
void SignalAsyncTick(void)
|
||||||
{
|
{
|
||||||
Atomic64FetchAdd(&Base.async.signal.v, 1);
|
Atomic64FetchAdd(&Base.async.signal.v, 1);
|
||||||
FutexWakeNeq(&Base.async.signal.v);
|
FutexWakeNeq(&Base.async.signal.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -36,67 +36,67 @@ void SignalAsyncTick(void)
|
|||||||
|
|
||||||
void AsyncWorkerEntryPoint(WaveLaneCtx *lane)
|
void AsyncWorkerEntryPoint(WaveLaneCtx *lane)
|
||||||
{
|
{
|
||||||
AsyncTickCtx tick = Zi;
|
AsyncTickCtx tick = Zi;
|
||||||
tick.arena = AcquireArena(Gibi(64));
|
tick.arena = AcquireArena(Gibi(64));
|
||||||
|
|
||||||
/* Tick forever */
|
/* Tick forever */
|
||||||
for (;;)
|
for (;;)
|
||||||
|
{
|
||||||
|
AsyncWorkerCtx *w = &Base.async.worker;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Begin tick
|
||||||
|
|
||||||
|
if (lane->idx == 0)
|
||||||
{
|
{
|
||||||
AsyncWorkerCtx *w = &Base.async.worker;
|
/* Wait for signal */
|
||||||
|
{
|
||||||
//////////////////////////////
|
i64 cur_signal = Atomic64Fetch(&Base.async.signal.v);
|
||||||
//- Begin tick
|
while (cur_signal <= w->last_seen_signal)
|
||||||
|
|
||||||
if (lane->idx == 0)
|
|
||||||
{
|
{
|
||||||
/* Wait for signal */
|
FutexYieldNeq(&Base.async.signal.v, &cur_signal, sizeof(cur_signal));
|
||||||
{
|
cur_signal = Atomic64Fetch(&Base.async.signal.v);
|
||||||
i64 cur_signal = Atomic64Fetch(&Base.async.signal.v);
|
|
||||||
while (cur_signal <= w->last_seen_signal)
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&Base.async.signal.v, &cur_signal, sizeof(cur_signal));
|
|
||||||
cur_signal = Atomic64Fetch(&Base.async.signal.v);
|
|
||||||
}
|
|
||||||
w->last_seen_signal = cur_signal;
|
|
||||||
}
|
|
||||||
/* Collect callbacks */
|
|
||||||
{
|
|
||||||
Lock lock = LockE(&Base.async.mutex);
|
|
||||||
{
|
|
||||||
w->callbacks_count = Base.async.callback_nodes_count;
|
|
||||||
w->callbacks = PushStructsNoZero(tick.arena, AsyncTickCallback, w->callbacks_count);
|
|
||||||
u64 callback_idx = 0;
|
|
||||||
for (AsyncTickCallbackNode *n = Base.async.first_callback_node; n; n = n->next)
|
|
||||||
{
|
|
||||||
w->callbacks[callback_idx] = n->callback;
|
|
||||||
++callback_idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
w->last_seen_signal = cur_signal;
|
||||||
WaveSync(lane);
|
}
|
||||||
|
/* Collect callbacks */
|
||||||
//////////////////////////////
|
{
|
||||||
//- Run async callbacks
|
Lock lock = LockE(&Base.async.mutex);
|
||||||
|
|
||||||
for (u64 callback_idx = 0; callback_idx < w->callbacks_count; ++callback_idx)
|
|
||||||
{
|
{
|
||||||
AsyncTickCallback *callback = &w->callbacks[callback_idx];
|
w->callbacks_count = Base.async.callback_nodes_count;
|
||||||
callback->func(lane, &tick);
|
w->callbacks = PushStructsNoZero(tick.arena, AsyncTickCallback, w->callbacks_count);
|
||||||
}
|
u64 callback_idx = 0;
|
||||||
|
for (AsyncTickCallbackNode *n = Base.async.first_callback_node; n; n = n->next)
|
||||||
//////////////////////////////
|
{
|
||||||
//- End tick
|
w->callbacks[callback_idx] = n->callback;
|
||||||
|
++callback_idx;
|
||||||
WaveSync(lane);
|
}
|
||||||
|
|
||||||
ResetArena(tick.arena);
|
|
||||||
{
|
|
||||||
Arena *tick_arena = tick.arena;
|
|
||||||
ZeroStruct(&tick);
|
|
||||||
tick.arena = tick_arena;
|
|
||||||
}
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WaveSync(lane);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Run async callbacks
|
||||||
|
|
||||||
|
for (u64 callback_idx = 0; callback_idx < w->callbacks_count; ++callback_idx)
|
||||||
|
{
|
||||||
|
AsyncTickCallback *callback = &w->callbacks[callback_idx];
|
||||||
|
callback->func(lane, &tick);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- End tick
|
||||||
|
|
||||||
|
WaveSync(lane);
|
||||||
|
|
||||||
|
ResetArena(tick.arena);
|
||||||
|
{
|
||||||
|
Arena *tick_arena = tick.arena;
|
||||||
|
ZeroStruct(&tick);
|
||||||
|
tick.arena = tick_arena;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,37 +6,37 @@ typedef void AsyncTickCallbackFunc(WaveLaneCtx *lane, AsyncTickCtx *tick);
|
|||||||
|
|
||||||
Struct(AsyncTickCallback)
|
Struct(AsyncTickCallback)
|
||||||
{
|
{
|
||||||
AsyncTickCallbackFunc *func;
|
AsyncTickCallbackFunc *func;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(AsyncTickCallbackNode)
|
Struct(AsyncTickCallbackNode)
|
||||||
{
|
{
|
||||||
AsyncTickCallbackNode *next;
|
AsyncTickCallbackNode *next;
|
||||||
AsyncTickCallback callback;
|
AsyncTickCallback callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(AsyncTickCtx)
|
Struct(AsyncTickCtx)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(AsyncWorkerCtx)
|
Struct(AsyncWorkerCtx)
|
||||||
{
|
{
|
||||||
i64 last_seen_signal;
|
i64 last_seen_signal;
|
||||||
|
|
||||||
u64 callbacks_count;
|
u64 callbacks_count;
|
||||||
AsyncTickCallback *callbacks;
|
AsyncTickCallback *callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(AsyncCtx)
|
Struct(AsyncCtx)
|
||||||
{
|
{
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
u64 callback_nodes_count;
|
u64 callback_nodes_count;
|
||||||
AsyncTickCallbackNode *first_callback_node;
|
AsyncTickCallbackNode *first_callback_node;
|
||||||
AsyncTickCallbackNode *last_callback_node;
|
AsyncTickCallbackNode *last_callback_node;
|
||||||
|
|
||||||
AsyncWorkerCtx worker;
|
AsyncWorkerCtx worker;
|
||||||
Atomic64Padded signal;
|
Atomic64Padded signal;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -4,13 +4,13 @@
|
|||||||
//- Buff
|
//- Buff
|
||||||
Struct(BB_Buff)
|
Struct(BB_Buff)
|
||||||
{
|
{
|
||||||
b32 is_backed_by_arena;
|
b32 is_backed_by_arena;
|
||||||
|
|
||||||
/* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */
|
/* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
/* If `is_arena_bitbuff` is 0, this fixed-sized buffer willl be used for reading & writing */
|
/* If `is_arena_bitbuff` is 0, this fixed-sized buffer willl be used for reading & writing */
|
||||||
String fixed_buffer;
|
String fixed_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Writer
|
//- Writer
|
||||||
@ -18,24 +18,24 @@ Struct(BB_Buff)
|
|||||||
#define BB_WriterOverflowArenaPushSize 4096
|
#define BB_WriterOverflowArenaPushSize 4096
|
||||||
Struct(BB_Writer)
|
Struct(BB_Writer)
|
||||||
{
|
{
|
||||||
b32 overflowed;
|
b32 overflowed;
|
||||||
BB_Buff *bb;
|
BB_Buff *bb;
|
||||||
u8 *base;
|
u8 *base;
|
||||||
u64 cur_bit;
|
u64 cur_bit;
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
b32 debug_enabled;
|
b32 debug_enabled;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Reader
|
//- Reader
|
||||||
Struct(BB_Reader)
|
Struct(BB_Reader)
|
||||||
{
|
{
|
||||||
b32 overflowed;
|
b32 overflowed;
|
||||||
u64 base_len;
|
u64 base_len;
|
||||||
u8 *base;
|
u8 *base;
|
||||||
u64 cur_bit;
|
u64 cur_bit;
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
b32 debug_enabled;
|
b32 debug_enabled;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,16 +47,16 @@ Struct(BB_Reader)
|
|||||||
/* Magic numbers inserted to verify read/write type & length */
|
/* Magic numbers inserted to verify read/write type & length */
|
||||||
Enum(BB_DebugMagicKind)
|
Enum(BB_DebugMagicKind)
|
||||||
{
|
{
|
||||||
BB_DebugMagicKind_AlignBytes = 0x20A4,
|
BB_DebugMagicKind_AlignBytes = 0x20A4,
|
||||||
BB_DebugMagicKind_AlignToNextByte = 0x379A,
|
BB_DebugMagicKind_AlignToNextByte = 0x379A,
|
||||||
BB_DebugMagicKind_UBits = 0xCB4A,
|
BB_DebugMagicKind_UBits = 0xCB4A,
|
||||||
BB_DebugMagicKind_IBits = 0xB30D,
|
BB_DebugMagicKind_IBits = 0xB30D,
|
||||||
BB_DebugMagicKind_UV = 0xE179,
|
BB_DebugMagicKind_UV = 0xE179,
|
||||||
BB_DebugMagicKind_IV = 0x981f,
|
BB_DebugMagicKind_IV = 0x981f,
|
||||||
BB_DebugMagicKind_F32 = 0x56F9,
|
BB_DebugMagicKind_F32 = 0x56F9,
|
||||||
BB_DebugMagicKind_F64 = 0x7053,
|
BB_DebugMagicKind_F64 = 0x7053,
|
||||||
BB_DebugMagicKind_Uid = 0xA24E,
|
BB_DebugMagicKind_Uid = 0xA24E,
|
||||||
BB_DebugMagicKind_String = 0x7866
|
BB_DebugMagicKind_String = 0x7866
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -118,11 +118,11 @@ void BB_WriteSeekBytes(BB_Writer *bw, u64 num_bytes);
|
|||||||
//~ Writer debug
|
//~ Writer debug
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits);
|
void BB_WriteDebugMagic(BB_Writer *bw, BB_DebugMagicKind magic, u8 num_bits);
|
||||||
void BB_WriteDebugMarker(BB_Writer *bw, String name);
|
void BB_WriteDebugMarker(BB_Writer *bw, String name);
|
||||||
#else
|
#else
|
||||||
#define BB_WriteDebugMagic(bw, magic, num_bits)
|
#define BB_WriteDebugMagic(bw, magic, num_bits)
|
||||||
#define BB_WriteDebugMarker(bw, name)
|
#define BB_WriteDebugMarker(bw, name)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -5,29 +5,29 @@
|
|||||||
|
|
||||||
BuddyCtx *AcquireBuddyCtx(u64 reserve)
|
BuddyCtx *AcquireBuddyCtx(u64 reserve)
|
||||||
{
|
{
|
||||||
/* TODO: Determine meta reserve dynamically */
|
/* TODO: Determine meta reserve dynamically */
|
||||||
Arena *meta_arena = AcquireArena(Gibi(64));
|
Arena *meta_arena = AcquireArena(Gibi(64));
|
||||||
BuddyCtx *ctx = PushStruct(meta_arena, BuddyCtx);
|
BuddyCtx *ctx = PushStruct(meta_arena, BuddyCtx);
|
||||||
ctx->meta_arena = meta_arena;
|
ctx->meta_arena = meta_arena;
|
||||||
ctx->data_arena = AcquireArena(reserve);
|
ctx->data_arena = AcquireArena(reserve);
|
||||||
|
|
||||||
/* TODO: Minimum block size */
|
/* TODO: Minimum block size */
|
||||||
ctx->levels = PushStructs(ctx->meta_arena, BuddyLevel, 64);
|
ctx->levels = PushStructs(ctx->meta_arena, BuddyLevel, 64);
|
||||||
for (u64 i = 0; i < 64; ++i)
|
for (u64 i = 0; i < 64; ++i)
|
||||||
{
|
{
|
||||||
BuddyLevel *level = &ctx->levels[i];
|
BuddyLevel *level = &ctx->levels[i];
|
||||||
level->ctx = ctx;
|
level->ctx = ctx;
|
||||||
level->tier = i;
|
level->tier = i;
|
||||||
level->size = (u64)1 << i;
|
level->size = (u64)1 << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseBuddyCtx(BuddyCtx *ctx)
|
void ReleaseBuddyCtx(BuddyCtx *ctx)
|
||||||
{
|
{
|
||||||
ReleaseArena(ctx->data_arena);
|
ReleaseArena(ctx->data_arena);
|
||||||
ReleaseArena(ctx->meta_arena);
|
ReleaseArena(ctx->meta_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -35,172 +35,172 @@ void ReleaseBuddyCtx(BuddyCtx *ctx)
|
|||||||
|
|
||||||
BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level)
|
BuddyBlock *GetUnusedBuddyBlock(BuddyCtx *ctx, BuddyLevel *level)
|
||||||
{
|
{
|
||||||
BuddyBlock *block = 0;
|
BuddyBlock *block = 0;
|
||||||
|
|
||||||
/* TODO: Tier oob check */
|
/* TODO: Tier oob check */
|
||||||
|
if (level->first_unused_block)
|
||||||
|
{
|
||||||
|
block = level->first_unused_block;
|
||||||
|
level->first_unused_block = block->next;
|
||||||
if (level->first_unused_block)
|
if (level->first_unused_block)
|
||||||
{
|
{
|
||||||
block = level->first_unused_block;
|
level->first_unused_block->prev = 0;
|
||||||
level->first_unused_block = block->next;
|
}
|
||||||
if (level->first_unused_block)
|
block->is_used = 1;
|
||||||
{
|
block->next = 0;
|
||||||
level->first_unused_block->prev = 0;
|
}
|
||||||
}
|
else
|
||||||
block->is_used = 1;
|
{
|
||||||
block->next = 0;
|
if (level->backed)
|
||||||
|
{
|
||||||
|
BuddyLevel *parent_level = &ctx->levels[level->tier + 1];
|
||||||
|
BuddyBlock *parent_block = GetUnusedBuddyBlock(ctx, parent_level);
|
||||||
|
|
||||||
|
/* Create left (used) block from parent block */
|
||||||
|
BuddyBlock *left = PushBuddyBlock(ctx);
|
||||||
|
left->is_used = 1;
|
||||||
|
left->level = level;
|
||||||
|
left->parent = parent_block;
|
||||||
|
left->memory = parent_block->memory;
|
||||||
|
|
||||||
|
/* Create right LAX block from parent block */
|
||||||
|
BuddyBlock *right = PushBuddyBlock(ctx);
|
||||||
|
right->is_used = 0;
|
||||||
|
right->level = level;
|
||||||
|
right->parent = parent_block;
|
||||||
|
right->memory = left->memory + level->size;
|
||||||
|
if (level->first_unused_block)
|
||||||
|
{
|
||||||
|
right->next = level->first_unused_block;
|
||||||
|
level->first_unused_block->prev = right;
|
||||||
|
}
|
||||||
|
level->first_unused_block = right;
|
||||||
|
|
||||||
|
left->sibling = right;
|
||||||
|
right->sibling = left;
|
||||||
|
block = left;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (level->backed)
|
Arena *arena = ctx->data_arena;
|
||||||
{
|
|
||||||
BuddyLevel *parent_level = &ctx->levels[level->tier + 1];
|
|
||||||
BuddyBlock *parent_block = GetUnusedBuddyBlock(ctx, parent_level);
|
|
||||||
|
|
||||||
/* Create left (used) block from parent block */
|
/* Grow arena */
|
||||||
BuddyBlock *left = PushBuddyBlock(ctx);
|
i64 level_commit_diff = (level->size * 2) - arena->pos;
|
||||||
left->is_used = 1;
|
if (level_commit_diff > 0)
|
||||||
left->level = level;
|
{
|
||||||
left->parent = parent_block;
|
PushStructsNoZero(arena, u8, level_commit_diff);
|
||||||
left->memory = parent_block->memory;
|
Assert(arena->pos == (level->size * 2));
|
||||||
|
}
|
||||||
|
|
||||||
/* Create right LAX block from parent block */
|
/* Create left (used) block from existing child block memory */
|
||||||
BuddyBlock *right = PushBuddyBlock(ctx);
|
BuddyBlock *left = PushBuddyBlock(ctx);
|
||||||
right->is_used = 0;
|
left->is_used = 1;
|
||||||
right->level = level;
|
left->level = level;
|
||||||
right->parent = parent_block;
|
left->memory = ArenaFirst(arena, u8);
|
||||||
right->memory = left->memory + level->size;
|
|
||||||
if (level->first_unused_block)
|
|
||||||
{
|
|
||||||
right->next = level->first_unused_block;
|
|
||||||
level->first_unused_block->prev = right;
|
|
||||||
}
|
|
||||||
level->first_unused_block = right;
|
|
||||||
|
|
||||||
left->sibling = right;
|
/* Create right LAX block from new arena memory */
|
||||||
right->sibling = left;
|
BuddyBlock *right = PushBuddyBlock(ctx);
|
||||||
block = left;
|
right->is_used = 0;
|
||||||
}
|
right->level = level;
|
||||||
else
|
right->memory = left->memory + level->size;
|
||||||
{
|
|
||||||
Arena *arena = ctx->data_arena;
|
|
||||||
|
|
||||||
/* Grow arena */
|
left->sibling = right;
|
||||||
i64 level_commit_diff = (level->size * 2) - arena->pos;
|
right->sibling = left;
|
||||||
if (level_commit_diff > 0)
|
block = left;
|
||||||
{
|
|
||||||
PushStructsNoZero(arena, u8, level_commit_diff);
|
|
||||||
Assert(arena->pos == (level->size * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create left (used) block from existing child block memory */
|
level->backed = 1;
|
||||||
BuddyBlock *left = PushBuddyBlock(ctx);
|
|
||||||
left->is_used = 1;
|
|
||||||
left->level = level;
|
|
||||||
left->memory = ArenaFirst(arena, u8);
|
|
||||||
|
|
||||||
/* Create right LAX block from new arena memory */
|
|
||||||
BuddyBlock *right = PushBuddyBlock(ctx);
|
|
||||||
right->is_used = 0;
|
|
||||||
right->level = level;
|
|
||||||
right->memory = left->memory + level->size;
|
|
||||||
|
|
||||||
left->sibling = right;
|
|
||||||
right->sibling = left;
|
|
||||||
block = left;
|
|
||||||
|
|
||||||
level->backed = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuddyBlock *PushBuddyBlock(BuddyCtx *ctx)
|
BuddyBlock *PushBuddyBlock(BuddyCtx *ctx)
|
||||||
{
|
{
|
||||||
BuddyBlock *block;
|
BuddyBlock *block;
|
||||||
if (ctx->first_free_block)
|
if (ctx->first_free_block)
|
||||||
{
|
{
|
||||||
block = ctx->first_free_block;
|
block = ctx->first_free_block;
|
||||||
ctx->first_free_block = block->next;
|
ctx->first_free_block = block->next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
block = PushStructNoZero(ctx->meta_arena, BuddyBlock);
|
block = PushStructNoZero(ctx->meta_arena, BuddyBlock);
|
||||||
}
|
}
|
||||||
ZeroStruct(block);
|
ZeroStruct(block);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block)
|
void PopBuddyBlock(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block)
|
||||||
{
|
{
|
||||||
/* Remove from unused list */
|
/* Remove from unused list */
|
||||||
|
{
|
||||||
|
BuddyBlock *prev = block->prev;
|
||||||
|
BuddyBlock *next = block->next;
|
||||||
|
if (prev)
|
||||||
{
|
{
|
||||||
BuddyBlock *prev = block->prev;
|
prev->next = next;
|
||||||
BuddyBlock *next = block->next;
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
level->first_unused_block = next;
|
|
||||||
}
|
|
||||||
if (next)
|
|
||||||
{
|
|
||||||
next->prev = prev;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
block->next = ctx->first_free_block;
|
else
|
||||||
ctx->first_free_block = block;
|
{
|
||||||
|
level->first_unused_block = next;
|
||||||
|
}
|
||||||
|
if (next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block->next = ctx->first_free_block;
|
||||||
|
ctx->first_free_block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size)
|
BuddyBlock *AcquireBuddyBlock(BuddyCtx *ctx, u64 size)
|
||||||
{
|
{
|
||||||
if (size > 0x00FFFFFFFFFFFFFFULL)
|
if (size > 0x00FFFFFFFFFFFFFFULL)
|
||||||
{
|
{
|
||||||
/* TODO: Error */
|
/* TODO: Error */
|
||||||
Assert(0);
|
Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Minimum block size */
|
/* TODO: Minimum block size */
|
||||||
|
|
||||||
/* TODO: Faster MSB calculation */
|
/* TODO: Faster MSB calculation */
|
||||||
|
|
||||||
u64 desired_block_size = 1;
|
u64 desired_block_size = 1;
|
||||||
u64 desired_level_tier = 0;
|
u64 desired_level_tier = 0;
|
||||||
while (desired_block_size < size && desired_level_tier < 64)
|
while (desired_block_size < size && desired_level_tier < 64)
|
||||||
{
|
{
|
||||||
desired_block_size <<= 1;
|
desired_block_size <<= 1;
|
||||||
++desired_level_tier;
|
++desired_level_tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuddyBlock *block = GetUnusedBuddyBlock(ctx, &ctx->levels[desired_level_tier]);
|
BuddyBlock *block = GetUnusedBuddyBlock(ctx, &ctx->levels[desired_level_tier]);
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseBuddyBlock(BuddyBlock *block)
|
void ReleaseBuddyBlock(BuddyBlock *block)
|
||||||
{
|
{
|
||||||
block->is_used = 0;
|
block->is_used = 0;
|
||||||
BuddyLevel *level = block->level;
|
BuddyLevel *level = block->level;
|
||||||
BuddyBlock *parent = block->parent;
|
BuddyBlock *parent = block->parent;
|
||||||
BuddyBlock *sibling = block->sibling;
|
BuddyBlock *sibling = block->sibling;
|
||||||
if (!sibling->is_used && parent != 0)
|
if (!sibling->is_used && parent != 0)
|
||||||
|
{
|
||||||
|
/* Merge siblings */
|
||||||
|
BuddyCtx *ctx = level->ctx;
|
||||||
|
PopBuddyBlock(ctx, level, block);
|
||||||
|
PopBuddyBlock(ctx, level, sibling);
|
||||||
|
/* Release parent */
|
||||||
|
ReleaseBuddyBlock(parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (level->first_unused_block)
|
||||||
{
|
{
|
||||||
/* Merge siblings */
|
block->next = level->first_unused_block;
|
||||||
BuddyCtx *ctx = level->ctx;
|
level->first_unused_block->prev = block;
|
||||||
PopBuddyBlock(ctx, level, block);
|
|
||||||
PopBuddyBlock(ctx, level, sibling);
|
|
||||||
/* Release parent */
|
|
||||||
ReleaseBuddyBlock(parent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (level->first_unused_block)
|
|
||||||
{
|
|
||||||
block->next = level->first_unused_block;
|
|
||||||
level->first_unused_block->prev = block;
|
|
||||||
}
|
|
||||||
level->first_unused_block = block;
|
|
||||||
}
|
}
|
||||||
|
level->first_unused_block = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,35 +4,35 @@
|
|||||||
//- Block
|
//- Block
|
||||||
Struct(BuddyBlock)
|
Struct(BuddyBlock)
|
||||||
{
|
{
|
||||||
b32 is_used;
|
b32 is_used;
|
||||||
struct BuddyLevel *level;
|
struct BuddyLevel *level;
|
||||||
BuddyBlock *parent;
|
BuddyBlock *parent;
|
||||||
BuddyBlock *sibling;
|
BuddyBlock *sibling;
|
||||||
|
|
||||||
/* Links to block in level's unused list or in ctx's free list */
|
/* Links to block in level's unused list or in ctx's free list */
|
||||||
BuddyBlock *prev;
|
BuddyBlock *prev;
|
||||||
BuddyBlock *next;
|
BuddyBlock *next;
|
||||||
|
|
||||||
u8 *memory;
|
u8 *memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Level
|
//- Level
|
||||||
Struct(BuddyLevel)
|
Struct(BuddyLevel)
|
||||||
{
|
{
|
||||||
struct BuddyCtx *ctx;
|
struct BuddyCtx *ctx;
|
||||||
b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
|
b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
|
||||||
u32 tier;
|
u32 tier;
|
||||||
u64 size;
|
u64 size;
|
||||||
BuddyBlock *first_unused_block;
|
BuddyBlock *first_unused_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Ctx
|
//- Ctx
|
||||||
Struct(BuddyCtx)
|
Struct(BuddyCtx)
|
||||||
{
|
{
|
||||||
Arena *meta_arena;
|
Arena *meta_arena;
|
||||||
Arena *data_arena;
|
Arena *data_arena;
|
||||||
BuddyLevel *levels;
|
BuddyLevel *levels;
|
||||||
BuddyBlock *first_free_block;
|
BuddyBlock *first_free_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,70 +3,70 @@
|
|||||||
|
|
||||||
void BootstrapCmdline(void)
|
void BootstrapCmdline(void)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
{
|
||||||
|
StringList raw = GetRawCommandline();
|
||||||
|
|
||||||
|
u64 tmp_args_count = 0;
|
||||||
|
u64 tmp_positionals_count = 0;
|
||||||
|
CommandlineArg *tmp_args = PushStructs(scratch.arena, CommandlineArg, raw.count);
|
||||||
|
String *tmp_positionals = PushStructs(scratch.arena, String, raw.count);
|
||||||
{
|
{
|
||||||
StringList raw = GetRawCommandline();
|
String name = Zi;
|
||||||
|
for (StringListNode *n = raw.first; n; n = n->next)
|
||||||
u64 tmp_args_count = 0;
|
{
|
||||||
u64 tmp_positionals_count = 0;
|
String s = n->s;
|
||||||
CommandlineArg *tmp_args = PushStructs(scratch.arena, CommandlineArg, raw.count);
|
if (StringBeginsWith(s, Lit("--")))
|
||||||
String *tmp_positionals = PushStructs(scratch.arena, String, raw.count);
|
|
||||||
{
|
{
|
||||||
String name = Zi;
|
if (name.len > 0)
|
||||||
for (StringListNode *n = raw.first; n; n = n->next)
|
{
|
||||||
{
|
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
||||||
String s = n->s;
|
arg->name = name;
|
||||||
if (StringBeginsWith(s, Lit("--")))
|
arg->exists = 1;
|
||||||
{
|
}
|
||||||
if (name.len > 0)
|
name = TrimLeft(s, Lit("--"));
|
||||||
{
|
|
||||||
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
|
||||||
arg->name = name;
|
|
||||||
arg->exists = 1;
|
|
||||||
}
|
|
||||||
name = TrimLeft(s, Lit("--"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (name.len > 0)
|
|
||||||
{
|
|
||||||
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
|
||||||
arg->name = name;
|
|
||||||
arg->value = s;
|
|
||||||
arg->exists = 1;
|
|
||||||
name = Zstr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp_positionals[tmp_positionals_count++] = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name.len > 0)
|
|
||||||
{
|
|
||||||
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
|
||||||
arg->name = name;
|
|
||||||
arg->exists = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Arena *perm = PermArena();
|
|
||||||
Base.cmdline.positional_args_count = tmp_positionals_count;
|
|
||||||
Base.cmdline.positional_args = PushStructsNoZero(perm, String, tmp_positionals_count);
|
|
||||||
CopyStructs(Base.cmdline.positional_args, tmp_positionals, tmp_positionals_count);
|
|
||||||
for (u64 i = 0; i < tmp_args_count; ++i)
|
|
||||||
{
|
{
|
||||||
CommandlineArg arg = tmp_args[i];
|
if (name.len > 0)
|
||||||
CommandlineArgNode *n = PushStruct(perm, CommandlineArgNode);
|
{
|
||||||
u64 hash = HashFnv64(Fnv64Basis, arg.name);
|
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
||||||
u64 bin_idx = hash % countof(Base.cmdline.arg_bins);
|
arg->name = name;
|
||||||
n->arg = arg;
|
arg->value = s;
|
||||||
n->hash = hash;
|
arg->exists = 1;
|
||||||
n->next = Base.cmdline.arg_bins[bin_idx];
|
name = Zstr;
|
||||||
Base.cmdline.arg_bins[bin_idx] = n;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp_positionals[tmp_positionals_count++] = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (name.len > 0)
|
||||||
|
{
|
||||||
|
CommandlineArg *arg = &tmp_args[tmp_args_count++];
|
||||||
|
arg->name = name;
|
||||||
|
arg->exists = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
Base.cmdline.positional_args_count = tmp_positionals_count;
|
||||||
|
Base.cmdline.positional_args = PushStructsNoZero(perm, String, tmp_positionals_count);
|
||||||
|
CopyStructs(Base.cmdline.positional_args, tmp_positionals, tmp_positionals_count);
|
||||||
|
for (u64 i = 0; i < tmp_args_count; ++i)
|
||||||
|
{
|
||||||
|
CommandlineArg arg = tmp_args[i];
|
||||||
|
CommandlineArgNode *n = PushStruct(perm, CommandlineArgNode);
|
||||||
|
u64 hash = HashFnv64(Fnv64Basis, arg.name);
|
||||||
|
u64 bin_idx = hash % countof(Base.cmdline.arg_bins);
|
||||||
|
n->arg = arg;
|
||||||
|
n->hash = hash;
|
||||||
|
n->next = Base.cmdline.arg_bins[bin_idx];
|
||||||
|
Base.cmdline.arg_bins[bin_idx] = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -74,25 +74,25 @@ void BootstrapCmdline(void)
|
|||||||
|
|
||||||
String StringFromCommandlineIdx(i32 idx)
|
String StringFromCommandlineIdx(i32 idx)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
if (idx < Base.cmdline.positional_args_count)
|
if (idx < Base.cmdline.positional_args_count)
|
||||||
{
|
{
|
||||||
result = Base.cmdline.positional_args[idx];
|
result = Base.cmdline.positional_args[idx];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandlineArg CommandlineArgFromName(String name)
|
CommandlineArg CommandlineArgFromName(String name)
|
||||||
{
|
{
|
||||||
CommandlineArg result = Zi;
|
CommandlineArg result = Zi;
|
||||||
u64 hash = HashFnv64(Fnv64Basis, name);
|
u64 hash = HashFnv64(Fnv64Basis, name);
|
||||||
for (CommandlineArgNode *n = Base.cmdline.arg_bins[hash % countof(Base.cmdline.arg_bins)]; n; n = n->next)
|
for (CommandlineArgNode *n = Base.cmdline.arg_bins[hash % countof(Base.cmdline.arg_bins)]; n; n = n->next)
|
||||||
|
{
|
||||||
|
if (n->hash == hash && MatchString(n->arg.name, name))
|
||||||
{
|
{
|
||||||
if (n->hash == hash && MatchString(n->arg.name, name))
|
result = n->arg;
|
||||||
{
|
break;
|
||||||
result = n->arg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,23 +3,23 @@
|
|||||||
|
|
||||||
Struct(CommandlineArg)
|
Struct(CommandlineArg)
|
||||||
{
|
{
|
||||||
b32 exists;
|
b32 exists;
|
||||||
String name;
|
String name;
|
||||||
String value;
|
String value;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CommandlineArgNode)
|
Struct(CommandlineArgNode)
|
||||||
{
|
{
|
||||||
CommandlineArgNode *next;
|
CommandlineArgNode *next;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
CommandlineArg arg;
|
CommandlineArg arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CmdLineCtx)
|
Struct(CmdLineCtx)
|
||||||
{
|
{
|
||||||
String *positional_args;
|
String *positional_args;
|
||||||
u64 positional_args_count;
|
u64 positional_args_count;
|
||||||
CommandlineArgNode *arg_bins[1024];
|
CommandlineArgNode *arg_bins[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,107 +3,107 @@
|
|||||||
|
|
||||||
String StringFromButton(Button button)
|
String StringFromButton(Button button)
|
||||||
{
|
{
|
||||||
PERSIST Readonly String names[Button_Count] = {
|
PERSIST Readonly String names[Button_Count] = {
|
||||||
[Button_M1] = CompLit("Mouse 1"),
|
[Button_M1] = CompLit("Mouse 1"),
|
||||||
[Button_M2] = CompLit("Mouse 2"),
|
[Button_M2] = CompLit("Mouse 2"),
|
||||||
[Button_M3] = CompLit("Mouse 3"),
|
[Button_M3] = CompLit("Mouse 3"),
|
||||||
[Button_M4] = CompLit("Mouse 4"),
|
[Button_M4] = CompLit("Mouse 4"),
|
||||||
[Button_M5] = CompLit("Mouse 5"),
|
[Button_M5] = CompLit("Mouse 5"),
|
||||||
[Button_MWheelUp] = CompLit("Wheel Up"),
|
[Button_MWheelUp] = CompLit("Wheel Up"),
|
||||||
[Button_MWheelDown] = CompLit("Wheel Down"),
|
[Button_MWheelDown] = CompLit("Wheel Down"),
|
||||||
[Button_Escape] = CompLit("Escape"),
|
[Button_Escape] = CompLit("Escape"),
|
||||||
[Button_F1] = CompLit("F1"),
|
[Button_F1] = CompLit("F1"),
|
||||||
[Button_F2] = CompLit("F2"),
|
[Button_F2] = CompLit("F2"),
|
||||||
[Button_F3] = CompLit("F3"),
|
[Button_F3] = CompLit("F3"),
|
||||||
[Button_F4] = CompLit("F4"),
|
[Button_F4] = CompLit("F4"),
|
||||||
[Button_F5] = CompLit("F5"),
|
[Button_F5] = CompLit("F5"),
|
||||||
[Button_F6] = CompLit("F6"),
|
[Button_F6] = CompLit("F6"),
|
||||||
[Button_F7] = CompLit("F7"),
|
[Button_F7] = CompLit("F7"),
|
||||||
[Button_F8] = CompLit("F8"),
|
[Button_F8] = CompLit("F8"),
|
||||||
[Button_F9] = CompLit("F9"),
|
[Button_F9] = CompLit("F9"),
|
||||||
[Button_F10] = CompLit("F10"),
|
[Button_F10] = CompLit("F10"),
|
||||||
[Button_F11] = CompLit("F11"),
|
[Button_F11] = CompLit("F11"),
|
||||||
[Button_F12] = CompLit("F12"),
|
[Button_F12] = CompLit("F12"),
|
||||||
[Button_F13] = CompLit("F13"),
|
[Button_F13] = CompLit("F13"),
|
||||||
[Button_F14] = CompLit("F14"),
|
[Button_F14] = CompLit("F14"),
|
||||||
[Button_F15] = CompLit("F15"),
|
[Button_F15] = CompLit("F15"),
|
||||||
[Button_F16] = CompLit("F16"),
|
[Button_F16] = CompLit("F16"),
|
||||||
[Button_F17] = CompLit("F17"),
|
[Button_F17] = CompLit("F17"),
|
||||||
[Button_F18] = CompLit("F18"),
|
[Button_F18] = CompLit("F18"),
|
||||||
[Button_F19] = CompLit("F19"),
|
[Button_F19] = CompLit("F19"),
|
||||||
[Button_F20] = CompLit("F20"),
|
[Button_F20] = CompLit("F20"),
|
||||||
[Button_F21] = CompLit("F21"),
|
[Button_F21] = CompLit("F21"),
|
||||||
[Button_F22] = CompLit("F22"),
|
[Button_F22] = CompLit("F22"),
|
||||||
[Button_F23] = CompLit("F23"),
|
[Button_F23] = CompLit("F23"),
|
||||||
[Button_F24] = CompLit("F24"),
|
[Button_F24] = CompLit("F24"),
|
||||||
[Button_GraveAccent] = CompLit("~"),
|
[Button_GraveAccent] = CompLit("~"),
|
||||||
[Button_0] = CompLit("0"),
|
[Button_0] = CompLit("0"),
|
||||||
[Button_1] = CompLit("1"),
|
[Button_1] = CompLit("1"),
|
||||||
[Button_2] = CompLit("2"),
|
[Button_2] = CompLit("2"),
|
||||||
[Button_3] = CompLit("3"),
|
[Button_3] = CompLit("3"),
|
||||||
[Button_4] = CompLit("4"),
|
[Button_4] = CompLit("4"),
|
||||||
[Button_5] = CompLit("5"),
|
[Button_5] = CompLit("5"),
|
||||||
[Button_6] = CompLit("6"),
|
[Button_6] = CompLit("6"),
|
||||||
[Button_7] = CompLit("7"),
|
[Button_7] = CompLit("7"),
|
||||||
[Button_8] = CompLit("8"),
|
[Button_8] = CompLit("8"),
|
||||||
[Button_9] = CompLit("9"),
|
[Button_9] = CompLit("9"),
|
||||||
[Button_Minus] = CompLit("Minus"),
|
[Button_Minus] = CompLit("Minus"),
|
||||||
[Button_Equal] = CompLit("Equal"),
|
[Button_Equal] = CompLit("Equal"),
|
||||||
[Button_Backspace] = CompLit("Backspace"),
|
[Button_Backspace] = CompLit("Backspace"),
|
||||||
[Button_Delete] = CompLit("Delete"),
|
[Button_Delete] = CompLit("Delete"),
|
||||||
[Button_Tab] = CompLit("Tab"),
|
[Button_Tab] = CompLit("Tab"),
|
||||||
[Button_A] = CompLit("A"),
|
[Button_A] = CompLit("A"),
|
||||||
[Button_B] = CompLit("B"),
|
[Button_B] = CompLit("B"),
|
||||||
[Button_C] = CompLit("C"),
|
[Button_C] = CompLit("C"),
|
||||||
[Button_D] = CompLit("D"),
|
[Button_D] = CompLit("D"),
|
||||||
[Button_E] = CompLit("E"),
|
[Button_E] = CompLit("E"),
|
||||||
[Button_F] = CompLit("F"),
|
[Button_F] = CompLit("F"),
|
||||||
[Button_G] = CompLit("G"),
|
[Button_G] = CompLit("G"),
|
||||||
[Button_H] = CompLit("H"),
|
[Button_H] = CompLit("H"),
|
||||||
[Button_I] = CompLit("I"),
|
[Button_I] = CompLit("I"),
|
||||||
[Button_J] = CompLit("J"),
|
[Button_J] = CompLit("J"),
|
||||||
[Button_K] = CompLit("K"),
|
[Button_K] = CompLit("K"),
|
||||||
[Button_L] = CompLit("L"),
|
[Button_L] = CompLit("L"),
|
||||||
[Button_M] = CompLit("M"),
|
[Button_M] = CompLit("M"),
|
||||||
[Button_N] = CompLit("N"),
|
[Button_N] = CompLit("N"),
|
||||||
[Button_O] = CompLit("O"),
|
[Button_O] = CompLit("O"),
|
||||||
[Button_P] = CompLit("P"),
|
[Button_P] = CompLit("P"),
|
||||||
[Button_Q] = CompLit("Q"),
|
[Button_Q] = CompLit("Q"),
|
||||||
[Button_R] = CompLit("R"),
|
[Button_R] = CompLit("R"),
|
||||||
[Button_S] = CompLit("S"),
|
[Button_S] = CompLit("S"),
|
||||||
[Button_T] = CompLit("T"),
|
[Button_T] = CompLit("T"),
|
||||||
[Button_U] = CompLit("U"),
|
[Button_U] = CompLit("U"),
|
||||||
[Button_V] = CompLit("V"),
|
[Button_V] = CompLit("V"),
|
||||||
[Button_W] = CompLit("W"),
|
[Button_W] = CompLit("W"),
|
||||||
[Button_X] = CompLit("X"),
|
[Button_X] = CompLit("X"),
|
||||||
[Button_Y] = CompLit("Y"),
|
[Button_Y] = CompLit("Y"),
|
||||||
[Button_Z] = CompLit("Z"),
|
[Button_Z] = CompLit("Z"),
|
||||||
[Button_Space] = CompLit("Space"),
|
[Button_Space] = CompLit("Space"),
|
||||||
[Button_Enter] = CompLit("Enter"),
|
[Button_Enter] = CompLit("Enter"),
|
||||||
[Button_Ctrl] = CompLit("Ctrl"),
|
[Button_Ctrl] = CompLit("Ctrl"),
|
||||||
[Button_Shift] = CompLit("Shift"),
|
[Button_Shift] = CompLit("Shift"),
|
||||||
[Button_Alt] = CompLit("Alt"),
|
[Button_Alt] = CompLit("Alt"),
|
||||||
[Button_Up] = CompLit("Up"),
|
[Button_Up] = CompLit("Up"),
|
||||||
[Button_Left] = CompLit("Left"),
|
[Button_Left] = CompLit("Left"),
|
||||||
[Button_Down] = CompLit("Down"),
|
[Button_Down] = CompLit("Down"),
|
||||||
[Button_Right] = CompLit("Right"),
|
[Button_Right] = CompLit("Right"),
|
||||||
[Button_PageUp] = CompLit("PageUp"),
|
[Button_PageUp] = CompLit("PageUp"),
|
||||||
[Button_PageDown] = CompLit("PageDown"),
|
[Button_PageDown] = CompLit("PageDown"),
|
||||||
[Button_Home] = CompLit("Home"),
|
[Button_Home] = CompLit("Home"),
|
||||||
[Button_End] = CompLit("End"),
|
[Button_End] = CompLit("End"),
|
||||||
[Button_ForwardSlash] = CompLit("Slash"),
|
[Button_ForwardSlash] = CompLit("Slash"),
|
||||||
[Button_Period] = CompLit("Period"),
|
[Button_Period] = CompLit("Period"),
|
||||||
[Button_Comma] = CompLit("Comma"),
|
[Button_Comma] = CompLit("Comma"),
|
||||||
[Button_Quote] = CompLit("Quote"),
|
[Button_Quote] = CompLit("Quote"),
|
||||||
[Button_LeftBracket] = CompLit("Left Bracket"),
|
[Button_LeftBracket] = CompLit("Left Bracket"),
|
||||||
[Button_RightBracket] = CompLit("Right Bracket"),
|
[Button_RightBracket] = CompLit("Right Bracket"),
|
||||||
[Button_Insert] = CompLit("Insert"),
|
[Button_Insert] = CompLit("Insert"),
|
||||||
[Button_Semicolon] = CompLit("Semicolon"),
|
[Button_Semicolon] = CompLit("Semicolon"),
|
||||||
};
|
};
|
||||||
String name = Lit("None");
|
String name = Lit("None");
|
||||||
if (button > 0 && button < countof(names))
|
if (button > 0 && button < countof(names))
|
||||||
{
|
{
|
||||||
name = names[button];
|
name = names[button];
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,110 +3,110 @@
|
|||||||
|
|
||||||
Enum(Button)
|
Enum(Button)
|
||||||
{
|
{
|
||||||
Button_None,
|
Button_None,
|
||||||
|
|
||||||
//- Mouse buttons
|
//- Mouse buttons
|
||||||
Button_M1,
|
Button_M1,
|
||||||
Button_M2,
|
Button_M2,
|
||||||
Button_M3,
|
Button_M3,
|
||||||
Button_M4,
|
Button_M4,
|
||||||
Button_M5,
|
Button_M5,
|
||||||
|
|
||||||
//- Mouse wheel
|
//- Mouse wheel
|
||||||
Button_MWheelUp,
|
Button_MWheelUp,
|
||||||
Button_MWheelDown,
|
Button_MWheelDown,
|
||||||
|
|
||||||
//- Keyboard buttons
|
//- Keyboard buttons
|
||||||
Button_Escape,
|
Button_Escape,
|
||||||
Button_F1,
|
Button_F1,
|
||||||
Button_F2,
|
Button_F2,
|
||||||
Button_F3,
|
Button_F3,
|
||||||
Button_F4,
|
Button_F4,
|
||||||
Button_F5,
|
Button_F5,
|
||||||
Button_F6,
|
Button_F6,
|
||||||
Button_F7,
|
Button_F7,
|
||||||
Button_F8,
|
Button_F8,
|
||||||
Button_F9,
|
Button_F9,
|
||||||
Button_F10,
|
Button_F10,
|
||||||
Button_F11,
|
Button_F11,
|
||||||
Button_F12,
|
Button_F12,
|
||||||
Button_F13,
|
Button_F13,
|
||||||
Button_F14,
|
Button_F14,
|
||||||
Button_F15,
|
Button_F15,
|
||||||
Button_F16,
|
Button_F16,
|
||||||
Button_F17,
|
Button_F17,
|
||||||
Button_F18,
|
Button_F18,
|
||||||
Button_F19,
|
Button_F19,
|
||||||
Button_F20,
|
Button_F20,
|
||||||
Button_F21,
|
Button_F21,
|
||||||
Button_F22,
|
Button_F22,
|
||||||
Button_F23,
|
Button_F23,
|
||||||
Button_F24,
|
Button_F24,
|
||||||
Button_GraveAccent,
|
Button_GraveAccent,
|
||||||
Button_0,
|
Button_0,
|
||||||
Button_1,
|
Button_1,
|
||||||
Button_2,
|
Button_2,
|
||||||
Button_3,
|
Button_3,
|
||||||
Button_4,
|
Button_4,
|
||||||
Button_5,
|
Button_5,
|
||||||
Button_6,
|
Button_6,
|
||||||
Button_7,
|
Button_7,
|
||||||
Button_8,
|
Button_8,
|
||||||
Button_9,
|
Button_9,
|
||||||
Button_Minus,
|
Button_Minus,
|
||||||
Button_Equal,
|
Button_Equal,
|
||||||
Button_Backspace,
|
Button_Backspace,
|
||||||
Button_Delete,
|
Button_Delete,
|
||||||
Button_Tab,
|
Button_Tab,
|
||||||
Button_A,
|
Button_A,
|
||||||
Button_B,
|
Button_B,
|
||||||
Button_C,
|
Button_C,
|
||||||
Button_D,
|
Button_D,
|
||||||
Button_E,
|
Button_E,
|
||||||
Button_F,
|
Button_F,
|
||||||
Button_G,
|
Button_G,
|
||||||
Button_H,
|
Button_H,
|
||||||
Button_I,
|
Button_I,
|
||||||
Button_J,
|
Button_J,
|
||||||
Button_K,
|
Button_K,
|
||||||
Button_L,
|
Button_L,
|
||||||
Button_M,
|
Button_M,
|
||||||
Button_N,
|
Button_N,
|
||||||
Button_O,
|
Button_O,
|
||||||
Button_P,
|
Button_P,
|
||||||
Button_Q,
|
Button_Q,
|
||||||
Button_R,
|
Button_R,
|
||||||
Button_S,
|
Button_S,
|
||||||
Button_T,
|
Button_T,
|
||||||
Button_U,
|
Button_U,
|
||||||
Button_V,
|
Button_V,
|
||||||
Button_W,
|
Button_W,
|
||||||
Button_X,
|
Button_X,
|
||||||
Button_Y,
|
Button_Y,
|
||||||
Button_Z,
|
Button_Z,
|
||||||
Button_Space,
|
Button_Space,
|
||||||
Button_Enter,
|
Button_Enter,
|
||||||
Button_Ctrl,
|
Button_Ctrl,
|
||||||
Button_Shift,
|
Button_Shift,
|
||||||
Button_Alt,
|
Button_Alt,
|
||||||
Button_Up,
|
Button_Up,
|
||||||
Button_Left,
|
Button_Left,
|
||||||
Button_Down,
|
Button_Down,
|
||||||
Button_Right,
|
Button_Right,
|
||||||
Button_PageUp,
|
Button_PageUp,
|
||||||
Button_PageDown,
|
Button_PageDown,
|
||||||
Button_Home,
|
Button_Home,
|
||||||
Button_End,
|
Button_End,
|
||||||
Button_ForwardSlash,
|
Button_ForwardSlash,
|
||||||
Button_Period,
|
Button_Period,
|
||||||
Button_Comma,
|
Button_Comma,
|
||||||
Button_Quote,
|
Button_Quote,
|
||||||
Button_LeftBracket,
|
Button_LeftBracket,
|
||||||
Button_RightBracket,
|
Button_RightBracket,
|
||||||
Button_Insert,
|
Button_Insert,
|
||||||
Button_Semicolon,
|
Button_Semicolon,
|
||||||
|
|
||||||
Button_Count
|
Button_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -114,44 +114,44 @@ Enum(Button)
|
|||||||
|
|
||||||
Enum(ControllerEventKind)
|
Enum(ControllerEventKind)
|
||||||
{
|
{
|
||||||
ControllerEventKind_None,
|
ControllerEventKind_None,
|
||||||
|
|
||||||
ControllerEventKind_ButtonDown,
|
ControllerEventKind_ButtonDown,
|
||||||
ControllerEventKind_ButtonUp,
|
ControllerEventKind_ButtonUp,
|
||||||
|
|
||||||
ControllerEventKind_CursorMove,
|
ControllerEventKind_CursorMove,
|
||||||
ControllerEventKind_MouseMove,
|
ControllerEventKind_MouseMove,
|
||||||
|
|
||||||
ControllerEventKind_Text,
|
ControllerEventKind_Text,
|
||||||
|
|
||||||
ControllerEventKind_Quit,
|
ControllerEventKind_Quit,
|
||||||
|
|
||||||
ControllerEventKind_Count
|
ControllerEventKind_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ControllerEvent)
|
Struct(ControllerEvent)
|
||||||
{
|
{
|
||||||
ControllerEventKind kind;
|
ControllerEventKind kind;
|
||||||
|
|
||||||
/* ControllerEventKind_ButtonDown */
|
/* ControllerEventKind_ButtonDown */
|
||||||
/* ControllerEventKind_ButtonUp */
|
/* ControllerEventKind_ButtonUp */
|
||||||
Button button;
|
Button button;
|
||||||
b32 is_repeat;
|
b32 is_repeat;
|
||||||
|
|
||||||
/* ControllerEventKind_Text */
|
/* ControllerEventKind_Text */
|
||||||
u32 text_codepoint;
|
u32 text_codepoint;
|
||||||
|
|
||||||
/* ControllerEventKind_CursorMove */
|
/* ControllerEventKind_CursorMove */
|
||||||
Vec2I32 cursor_pos;
|
Vec2I32 cursor_pos;
|
||||||
|
|
||||||
/* ControllerEventKind_MouseMove */
|
/* ControllerEventKind_MouseMove */
|
||||||
Vec2I32 mouse_delta;
|
Vec2I32 mouse_delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ControllerEventsArray)
|
Struct(ControllerEventsArray)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
ControllerEvent *events;
|
ControllerEvent *events;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,15 +3,15 @@
|
|||||||
|
|
||||||
Enum(OS_FileFlag)
|
Enum(OS_FileFlag)
|
||||||
{
|
{
|
||||||
OS_FileFlag_None = 0,
|
OS_FileFlag_None = 0,
|
||||||
OS_FileFlag_Read = (1 << 0),
|
OS_FileFlag_Read = (1 << 0),
|
||||||
OS_FileFlag_Write = (1 << 1),
|
OS_FileFlag_Write = (1 << 1),
|
||||||
OS_FileFlag_Create = (1 << 2),
|
OS_FileFlag_Create = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(OS_File)
|
Struct(OS_File)
|
||||||
{
|
{
|
||||||
u64 handle;
|
u64 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -5,17 +5,17 @@
|
|||||||
|
|
||||||
Struct(GstatCtx)
|
Struct(GstatCtx)
|
||||||
{
|
{
|
||||||
Atomic64Padded SockBytesSent;
|
Atomic64Padded SockBytesSent;
|
||||||
Atomic64Padded SockBytesReceived;
|
Atomic64Padded SockBytesReceived;
|
||||||
Atomic64Padded DebugSteps;
|
Atomic64Padded DebugSteps;
|
||||||
|
|
||||||
Atomic64Padded NumArenas;
|
Atomic64Padded NumArenas;
|
||||||
Atomic64Padded ArenaMemoryCommitted;
|
Atomic64Padded ArenaMemoryCommitted;
|
||||||
Atomic64Padded ArenaMemoryReserved;
|
Atomic64Padded ArenaMemoryReserved;
|
||||||
|
|
||||||
Atomic64Padded NumGpuArenas;
|
Atomic64Padded NumGpuArenas;
|
||||||
Atomic64Padded DedicatedGpuArenaMemoryCommitted;
|
Atomic64Padded DedicatedGpuArenaMemoryCommitted;
|
||||||
Atomic64Padded SharedGpuArenaMemoryCommitted;
|
Atomic64Padded SharedGpuArenaMemoryCommitted;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,53 +5,53 @@
|
|||||||
//- Api
|
//- Api
|
||||||
#include "base.cgh"
|
#include "base.cgh"
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
# include "base_intrinsics.h"
|
#include "base_intrinsics.h"
|
||||||
# include "base_memory.h"
|
#include "base_memory.h"
|
||||||
# include "base_arena.h"
|
#include "base_arena.h"
|
||||||
# include "base_futex.h"
|
#include "base_futex.h"
|
||||||
# include "base_sync.h"
|
#include "base_sync.h"
|
||||||
# include "base_time.h"
|
#include "base_time.h"
|
||||||
# include "base_uid.h"
|
#include "base_uid.h"
|
||||||
# include "base_math.h"
|
#include "base_math.h"
|
||||||
# include "base_wave.h"
|
#include "base_wave.h"
|
||||||
# include "base_string.h"
|
#include "base_string.h"
|
||||||
# include "base_cmdline.h"
|
#include "base_cmdline.h"
|
||||||
# include "base_log.h"
|
#include "base_log.h"
|
||||||
# include "base_uni.h"
|
#include "base_uni.h"
|
||||||
# include "base_gstat.h"
|
#include "base_gstat.h"
|
||||||
# include "base_buddy.h"
|
#include "base_buddy.h"
|
||||||
# include "base_rand.h"
|
#include "base_rand.h"
|
||||||
# include "base_util.h"
|
#include "base_util.h"
|
||||||
# include "base_bitbuff.h"
|
#include "base_bitbuff.h"
|
||||||
# include "base_resource.h"
|
#include "base_resource.h"
|
||||||
# include "base_controller.h"
|
#include "base_controller.h"
|
||||||
# include "base_async.h"
|
#include "base_async.h"
|
||||||
# include "base_state.h"
|
#include "base_state.h"
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
# include "base_shader.gh"
|
#include "base_shader.gh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
# include "base_memory.c"
|
#include "base_memory.c"
|
||||||
# include "base_arena.c"
|
#include "base_arena.c"
|
||||||
# include "base_sync.c"
|
#include "base_sync.c"
|
||||||
# include "base_uid.c"
|
#include "base_uid.c"
|
||||||
# include "base_string.c"
|
#include "base_string.c"
|
||||||
# include "base_cmdline.c"
|
#include "base_cmdline.c"
|
||||||
# include "base_uni.c"
|
#include "base_uni.c"
|
||||||
# include "base_buddy.c"
|
#include "base_buddy.c"
|
||||||
# include "base_math.c"
|
#include "base_math.c"
|
||||||
# include "base_wave.c"
|
#include "base_wave.c"
|
||||||
# include "base_rand.c"
|
#include "base_rand.c"
|
||||||
# include "base_bitbuff.c"
|
#include "base_bitbuff.c"
|
||||||
# include "base_resource.c"
|
#include "base_resource.c"
|
||||||
# include "base_controller.c"
|
#include "base_controller.c"
|
||||||
# include "base_async.c"
|
#include "base_async.c"
|
||||||
# include "base_state.c"
|
#include "base_state.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Include base_win32
|
//- Include base_win32
|
||||||
#if IsLanguageC && IsPlatformWindows
|
#if IsLanguageC && IsPlatformWindows
|
||||||
# include "base_win32/base_win32_inc.h"
|
#include "base_win32/base_win32_inc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,23 +3,23 @@
|
|||||||
|
|
||||||
Inline f32 IxSqrtF32(f32 f)
|
Inline f32 IxSqrtF32(f32 f)
|
||||||
{
|
{
|
||||||
__m128 n = _mm_set_ss(f);
|
__m128 n = _mm_set_ss(f);
|
||||||
n = _mm_sqrt_ss(n);
|
n = _mm_sqrt_ss(n);
|
||||||
return _mm_cvtss_f32(n);
|
return _mm_cvtss_f32(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f64 IxSqrtF64(f64 f)
|
Inline f64 IxSqrtF64(f64 f)
|
||||||
{
|
{
|
||||||
__m128d n = _mm_set_sd(f);
|
__m128d n = _mm_set_sd(f);
|
||||||
n = _mm_sqrt_sd(_mm_setzero_pd(), n);
|
n = _mm_sqrt_sd(_mm_setzero_pd(), n);
|
||||||
return _mm_cvtsd_f64(n);
|
return _mm_cvtsd_f64(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f32 IxRsqrtF32(f32 f)
|
Inline f32 IxRsqrtF32(f32 f)
|
||||||
{
|
{
|
||||||
__m128 n = _mm_set_ss(f);
|
__m128 n = _mm_set_ss(f);
|
||||||
n = _mm_rsqrt_ss(n);
|
n = _mm_rsqrt_ss(n);
|
||||||
return _mm_cvtss_f32(n);
|
return _mm_cvtss_f32(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -27,22 +27,22 @@ Inline f32 IxRsqrtF32(f32 f)
|
|||||||
|
|
||||||
Inline i32 IxRoundF32ToI32(f32 f)
|
Inline i32 IxRoundF32ToI32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_si32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
return _mm_cvtss_si32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f32 IxRoundF32ToF32(f32 f)
|
Inline f32 IxRoundF32ToF32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline i64 IxRoundF64ToI64(f64 f)
|
Inline i64 IxRoundF64ToI64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_si64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
return _mm_cvtsd_si64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f64 IxRoundF64ToF64(f64 f)
|
Inline f64 IxRoundF64ToF64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -50,22 +50,22 @@ Inline f64 IxRoundF64ToF64(f64 f)
|
|||||||
|
|
||||||
Inline i32 IxFloorF32ToI32(f32 f)
|
Inline i32 IxFloorF32ToI32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_si32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
return _mm_cvtss_si32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f32 IxFloorF32ToF32(f32 f)
|
Inline f32 IxFloorF32ToF32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_f32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
return _mm_cvtss_f32(_mm_floor_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline i64 IxFloorF64ToI64(f64 f)
|
Inline i64 IxFloorF64ToI64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_si64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
return _mm_cvtsd_si64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f64 IxFloorF64ToF64(f64 f)
|
Inline f64 IxFloorF64ToF64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_f64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
return _mm_cvtsd_f64(_mm_floor_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -73,22 +73,22 @@ Inline f64 IxFloorF64ToF64(f64 f)
|
|||||||
|
|
||||||
Inline i32 IxCeilF32ToI32(f32 f)
|
Inline i32 IxCeilF32ToI32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_si32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
return _mm_cvtss_si32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f32 IxCeilF32ToF32(f32 f)
|
Inline f32 IxCeilF32ToF32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_f32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
return _mm_cvtss_f32(_mm_ceil_ss(_mm_setzero_ps(), _mm_set_ss(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline i64 IxCeilF64ToI64(f64 f)
|
Inline i64 IxCeilF64ToI64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_si64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
return _mm_cvtsd_si64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f64 IxCeilF64ToF64(f64 f)
|
Inline f64 IxCeilF64ToF64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_f64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
return _mm_cvtsd_f64(_mm_ceil_sd(_mm_setzero_pd(), _mm_set_sd(f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -96,10 +96,10 @@ Inline f64 IxCeilF64ToF64(f64 f)
|
|||||||
|
|
||||||
Inline f32 IxTruncF32ToF32(f32 f)
|
Inline f32 IxTruncF32ToF32(f32 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC));
|
return _mm_cvtss_f32(_mm_round_ss(_mm_setzero_ps(), _mm_set_ss(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline f64 IxTruncF64ToF64(f64 f)
|
Inline f64 IxTruncF64ToF64(f64 f)
|
||||||
{
|
{
|
||||||
return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC));
|
return _mm_cvtsd_f64(_mm_round_sd(_mm_setzero_pd(), _mm_set_sd(f), _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,22 +3,22 @@
|
|||||||
|
|
||||||
Struct(LogEvent)
|
Struct(LogEvent)
|
||||||
{
|
{
|
||||||
u64 id;
|
u64 id;
|
||||||
u64 level_id;
|
u64 level_id;
|
||||||
|
|
||||||
DateTime datetime;
|
DateTime datetime;
|
||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
|
|
||||||
String msg;
|
String msg;
|
||||||
i32 level;
|
i32 level;
|
||||||
|
|
||||||
i32 thread_id;
|
i32 thread_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(LogEventsArray)
|
Struct(LogEventsArray)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
LogEvent *logs;
|
LogEvent *logs;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -28,11 +28,11 @@ Struct(LogEventsArray)
|
|||||||
|
|
||||||
/* Log level configuration */
|
/* Log level configuration */
|
||||||
#ifndef LogLevel_CompTime
|
#ifndef LogLevel_CompTime
|
||||||
# if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
# define LogLevel_CompTime LogLevel_Debug
|
#define LogLevel_CompTime LogLevel_Debug
|
||||||
# else
|
#else
|
||||||
# define LogLevel_CompTime LogLevel_Info
|
#define LogLevel_CompTime LogLevel_Info
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LogLevel_None -1
|
#define LogLevel_None -1
|
||||||
@ -49,84 +49,84 @@ Struct(LogEventsArray)
|
|||||||
|
|
||||||
Struct(LogLevelSettings)
|
Struct(LogLevelSettings)
|
||||||
{
|
{
|
||||||
String shorthand;
|
String shorthand;
|
||||||
};
|
};
|
||||||
|
|
||||||
Global Readonly LogLevelSettings log_settings[LogLevel_Count] = {
|
Global Readonly LogLevelSettings log_settings[LogLevel_Count] = {
|
||||||
[LogLevel_Critical] = {
|
[LogLevel_Critical] = {
|
||||||
CompLit("CRITICAL"),
|
CompLit("CRITICAL"),
|
||||||
},
|
},
|
||||||
|
|
||||||
[LogLevel_Error] = {
|
[LogLevel_Error] = {
|
||||||
CompLit("ERROR"),
|
CompLit("ERROR"),
|
||||||
},
|
},
|
||||||
|
|
||||||
[LogLevel_Warning] = {
|
[LogLevel_Warning] = {
|
||||||
CompLit("WARNING"),
|
CompLit("WARNING"),
|
||||||
},
|
},
|
||||||
|
|
||||||
[LogLevel_Success] = {
|
[LogLevel_Success] = {
|
||||||
CompLit("SUCCESS"),
|
CompLit("SUCCESS"),
|
||||||
},
|
},
|
||||||
|
|
||||||
[LogLevel_Info] = {
|
[LogLevel_Info] = {
|
||||||
CompLit("INFO"),
|
CompLit("INFO"),
|
||||||
},
|
},
|
||||||
|
|
||||||
[LogLevel_Debug] = {
|
[LogLevel_Debug] = {
|
||||||
CompLit("DEBUG"),
|
CompLit("DEBUG"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Compile-time logging macros
|
//~ Compile-time logging macros
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Critical)
|
#if LogLevel(LogLevel_Critical)
|
||||||
# define LogCritical(msg) Log_(LogLevel_Critical, msg)
|
#define LogCritical(msg) Log_(LogLevel_Critical, msg)
|
||||||
# define LogCriticalF(fmt_lit, ...) LogF_(LogLevel_Critical, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogCriticalF(fmt_lit, ...) LogF_(LogLevel_Critical, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogCritical(msg)
|
#define LogCritical(msg)
|
||||||
# define LogCriticalF(...)
|
#define LogCriticalF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Error)
|
#if LogLevel(LogLevel_Error)
|
||||||
# define LogError(msg) Log_(LogLevel_Error, msg)
|
#define LogError(msg) Log_(LogLevel_Error, msg)
|
||||||
# define LogErrorF(fmt_lit, ...) LogF_(LogLevel_Error, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogErrorF(fmt_lit, ...) LogF_(LogLevel_Error, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogError(msg)
|
#define LogError(msg)
|
||||||
# define LogErrorF(...)
|
#define LogErrorF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Warning)
|
#if LogLevel(LogLevel_Warning)
|
||||||
# define LogWarning(msg) Log_(LogLevel_Warning, msg)
|
#define LogWarning(msg) Log_(LogLevel_Warning, msg)
|
||||||
# define LogWarningF(fmt_lit, ...) LogF_(LogLevel_Warning, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogWarningF(fmt_lit, ...) LogF_(LogLevel_Warning, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogWarning(msg)
|
#define LogWarning(msg)
|
||||||
# define LogWarningF(...)
|
#define LogWarningF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Success)
|
#if LogLevel(LogLevel_Success)
|
||||||
# define LogSuccess(msg) Log_(LogLevel_Success, msg)
|
#define LogSuccess(msg) Log_(LogLevel_Success, msg)
|
||||||
# define LogSuccessF(fmt_lit, ...) LogF_(LogLevel_Success, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogSuccessF(fmt_lit, ...) LogF_(LogLevel_Success, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogSuccess(msg)
|
#define LogSuccess(msg)
|
||||||
# define LogSuccessF(...)
|
#define LogSuccessF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Info)
|
#if LogLevel(LogLevel_Info)
|
||||||
# define LogInfo(msg) Log_(LogLevel_Info, msg)
|
#define LogInfo(msg) Log_(LogLevel_Info, msg)
|
||||||
# define LogInfoF(fmt_lit, ...) LogF_(LogLevel_Info, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogInfoF(fmt_lit, ...) LogF_(LogLevel_Info, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogInfo(msg)
|
#define LogInfo(msg)
|
||||||
# define LogInfoF(...)
|
#define LogInfoF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LogLevel(LogLevel_Debug)
|
#if LogLevel(LogLevel_Debug)
|
||||||
# define LogDebug(msg) Log_(LogLevel_Debug, msg)
|
#define LogDebug(msg) Log_(LogLevel_Debug, msg)
|
||||||
# define LogDebugF(fmt_lit, ...) LogF_(LogLevel_Debug, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
#define LogDebugF(fmt_lit, ...) LogF_(LogLevel_Debug, Lit(fmt_lit) , ## __VA_ARGS__, FmtEnd)
|
||||||
#else
|
#else
|
||||||
# define LogDebug(msg)
|
#define LogDebug(msg)
|
||||||
# define LogDebugF(...)
|
#define LogDebugF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
1562
src/base/base_math.c
1562
src/base/base_math.c
File diff suppressed because it is too large
Load Diff
@ -9,12 +9,12 @@
|
|||||||
|
|
||||||
Enum(Axis)
|
Enum(Axis)
|
||||||
{
|
{
|
||||||
Axis_X = 0,
|
Axis_X = 0,
|
||||||
Axis_Y = 1,
|
Axis_Y = 1,
|
||||||
Axis_Z = 2,
|
Axis_Z = 2,
|
||||||
|
|
||||||
Axis_CountXY = 2,
|
Axis_CountXY = 2,
|
||||||
Axis_CountXYZ = 3
|
Axis_CountXYZ = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -145,17 +145,17 @@ Struct(Rng3U64) { Vec3U64 p0; Vec3U64 p1; };
|
|||||||
|
|
||||||
Struct(Xform)
|
Struct(Xform)
|
||||||
{
|
{
|
||||||
Vec2 bx; /* X basis vector (x axis) */
|
Vec2 bx; /* X basis vector (x axis) */
|
||||||
Vec2 by; /* Y basis vector (y axis)*/
|
Vec2 by; /* Y basis vector (y axis)*/
|
||||||
Vec2 og; /* Translation vector (origin) */
|
Vec2 og; /* Translation vector (origin) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* (T)ranslation, (R)otation, (S)cale */
|
/* (T)ranslation, (R)otation, (S)cale */
|
||||||
Struct(Trs)
|
Struct(Trs)
|
||||||
{
|
{
|
||||||
Vec2 t;
|
Vec2 t;
|
||||||
Vec2 s;
|
Vec2 s;
|
||||||
f32 r;
|
f32 r;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -163,9 +163,9 @@ Struct(Trs)
|
|||||||
|
|
||||||
Struct(SoftSpring)
|
Struct(SoftSpring)
|
||||||
{
|
{
|
||||||
f32 bias_rate;
|
f32 bias_rate;
|
||||||
f32 mass_scale;
|
f32 mass_scale;
|
||||||
f32 impulse_scale;
|
f32 impulse_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -173,11 +173,11 @@ Struct(SoftSpring)
|
|||||||
|
|
||||||
Struct(Mat4x4)
|
Struct(Mat4x4)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct { Vec4 bx, by, bz, bw; };
|
struct { Vec4 bx, by, bz, bw; };
|
||||||
f32 e[4][4];
|
f32 e[4][4];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -7,43 +7,43 @@
|
|||||||
__attribute((section(".text.memcpy")))
|
__attribute((section(".text.memcpy")))
|
||||||
void *memcpy(void *__restrict dst, const void *__restrict src, u64 count)
|
void *memcpy(void *__restrict dst, const void *__restrict src, u64 count)
|
||||||
{
|
{
|
||||||
char *dst_pchar = dst;
|
char *dst_pchar = dst;
|
||||||
char *src_pchar = src;
|
char *src_pchar = src;
|
||||||
for (u64 i = 0; i < count; ++i)
|
for (u64 i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
dst_pchar[i] = src_pchar[i];
|
dst_pchar[i] = src_pchar[i];
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- memset
|
//- memset
|
||||||
__attribute((section(".text.memset")))
|
__attribute((section(".text.memset")))
|
||||||
void *memset(void *dst, i32 c, u64 count)
|
void *memset(void *dst, i32 c, u64 count)
|
||||||
{
|
{
|
||||||
char *dst_pchar = dst;
|
char *dst_pchar = dst;
|
||||||
for (u64 i = 0; i < count; ++i)
|
for (u64 i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
dst_pchar[i] = (char)c;
|
dst_pchar[i] = (char)c;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- memcmp
|
//- memcmp
|
||||||
__attribute((section(".text.memcmp")))
|
__attribute((section(".text.memcmp")))
|
||||||
i32 memcmp(const void *p1, const void *p2, u64 count)
|
i32 memcmp(const void *p1, const void *p2, u64 count)
|
||||||
{
|
{
|
||||||
i32 result = 0;
|
i32 result = 0;
|
||||||
char *p1_pchar = p1;
|
char *p1_pchar = p1;
|
||||||
char *p2_pchar = p2;
|
char *p2_pchar = p2;
|
||||||
for (u64 i = 0; i < count; ++i)
|
for (u64 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
result = p1_pchar[i] - p2_pchar[i];
|
||||||
|
if (result != 0)
|
||||||
{
|
{
|
||||||
result = p1_pchar[i] - p2_pchar[i];
|
break;
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !IsCrtlibEnabled */
|
#endif /* !IsCrtlibEnabled */
|
||||||
|
|||||||
@ -34,9 +34,9 @@ void SetMemoryReadWrite(void *address, u64 size);
|
|||||||
//~ Crtlib stubs
|
//~ Crtlib stubs
|
||||||
|
|
||||||
#if IsCrtlibEnabled
|
#if IsCrtlibEnabled
|
||||||
# include <memory.h>
|
#include <memory.h>
|
||||||
#else
|
#else
|
||||||
void *memcpy(void *__restrict dst, const void *__restrict src, u64 n);
|
void *memcpy(void *__restrict dst, const void *__restrict src, u64 n);
|
||||||
void *memset(void *dst, i32 c, u64 n);
|
void *memset(void *dst, i32 c, u64 n);
|
||||||
i32 memcmp(const void *p1, const void *p2, u64 n);
|
i32 memcmp(const void *p1, const void *p2, u64 n);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
u64 RandU64FromState(RandState *state)
|
u64 RandU64FromState(RandState *state)
|
||||||
{
|
{
|
||||||
u64 seed = state->seed;
|
u64 seed = state->seed;
|
||||||
if (seed == 0)
|
if (seed == 0)
|
||||||
{
|
{
|
||||||
TrueRand(StringFromStruct(&seed));
|
TrueRand(StringFromStruct(&seed));
|
||||||
state->seed = seed;
|
state->seed = seed;
|
||||||
}
|
}
|
||||||
return seed ^ RandU64FromSeed(++state->counter);
|
return seed ^ RandU64FromSeed(++state->counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 RandF64FromState(RandState *state, f64 range_start, f64 range_end)
|
f64 RandF64FromState(RandState *state, f64 range_start, f64 range_end)
|
||||||
{
|
{
|
||||||
return range_start + (range_end - range_start) * ((f64)(RandU64FromState(state) % RandMaxF64) / (f64)RandMaxF64);
|
return range_start + (range_end - range_start) * ((f64)(RandU64FromState(state) % RandMaxF64) / (f64)RandMaxF64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Based on Jon Maiga's "mx3"
|
/* Based on Jon Maiga's "mx3"
|
||||||
@ -19,19 +19,19 @@ f64 RandF64FromState(RandState *state, f64 range_start, f64 range_end)
|
|||||||
*/
|
*/
|
||||||
u64 RandU64FromSeed(u64 seed)
|
u64 RandU64FromSeed(u64 seed)
|
||||||
{
|
{
|
||||||
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d;
|
||||||
seed = (seed ^ (seed >> 29));
|
seed = (seed ^ (seed >> 29));
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 RandU64FromSeeds(u64 seed_a, u64 seed_b)
|
u64 RandU64FromSeeds(u64 seed_a, u64 seed_b)
|
||||||
{
|
{
|
||||||
return RandU64FromSeed((seed_a * 3) + seed_b);
|
return RandU64FromSeed((seed_a * 3) + seed_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 RandF64FromSeed(u64 seed, f64 range_start, f64 range_end)
|
f64 RandF64FromSeed(u64 seed, f64 range_start, f64 range_end)
|
||||||
{
|
{
|
||||||
return range_start + (range_end - range_start) * ((f64)(RandU64FromSeed(seed) % RandMaxF64) / (f64)RandMaxF64);
|
return range_start + (range_end - range_start) * ((f64)(RandU64FromSeed(seed) % RandMaxF64) / (f64)RandMaxF64);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
Struct(RandState)
|
Struct(RandState)
|
||||||
{
|
{
|
||||||
u64 seed; /* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */
|
u64 seed; /* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */
|
||||||
u64 counter;
|
u64 counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */
|
/* TODO: Use a value that gives good precision when dividing into range 0 -> 1 */
|
||||||
|
|||||||
@ -3,39 +3,39 @@
|
|||||||
|
|
||||||
void BootstrapResources(u64 archive_strings_count, String *archive_strings)
|
void BootstrapResources(u64 archive_strings_count, String *archive_strings)
|
||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
for (u64 archive_string_index = 0; archive_string_index < archive_strings_count; ++archive_string_index)
|
for (u64 archive_string_index = 0; archive_string_index < archive_strings_count; ++archive_string_index)
|
||||||
|
{
|
||||||
|
String archive = archive_strings[archive_string_index];
|
||||||
|
if (archive.len > 0)
|
||||||
{
|
{
|
||||||
String archive = archive_strings[archive_string_index];
|
BB_Buff bb = BB_BuffFromString(archive);
|
||||||
if (archive.len > 0)
|
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||||
{
|
|
||||||
BB_Buff bb = BB_BuffFromString(archive);
|
|
||||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
|
||||||
|
|
||||||
u64 magic = BB_ReadUBits(&br, 64);
|
u64 magic = BB_ReadUBits(&br, 64);
|
||||||
Assert(magic == ResourceEmbeddedMagic);
|
Assert(magic == ResourceEmbeddedMagic);
|
||||||
|
|
||||||
/* Create & insert entries */
|
/* Create & insert entries */
|
||||||
u64 num_entries = BB_ReadUBits(&br, 64);
|
u64 num_entries = BB_ReadUBits(&br, 64);
|
||||||
for (u64 i = 0; i < num_entries; ++i)
|
for (u64 i = 0; i < num_entries; ++i)
|
||||||
{
|
{
|
||||||
u64 name_start = BB_ReadUBits(&br, 64);
|
u64 name_start = BB_ReadUBits(&br, 64);
|
||||||
u64 name_len = BB_ReadUBits(&br, 64);
|
u64 name_len = BB_ReadUBits(&br, 64);
|
||||||
u64 data_start = BB_ReadUBits(&br, 64);
|
u64 data_start = BB_ReadUBits(&br, 64);
|
||||||
u64 data_len = BB_ReadUBits(&br, 64);
|
u64 data_len = BB_ReadUBits(&br, 64);
|
||||||
|
|
||||||
ResourceEntry *entry = PushStruct(perm, ResourceEntry);
|
ResourceEntry *entry = PushStruct(perm, ResourceEntry);
|
||||||
entry->name = STRING(name_len, archive.text + name_start);
|
entry->name = STRING(name_len, archive.text + name_start);
|
||||||
entry->data = STRING(data_len, archive.text + data_start);
|
entry->data = STRING(data_len, archive.text + data_start);
|
||||||
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
||||||
|
|
||||||
ResourceEntryBin *bin = &Base.resource.bins[entry->hash % countof(Base.resource.bins)];
|
ResourceEntryBin *bin = &Base.resource.bins[entry->hash % countof(Base.resource.bins)];
|
||||||
SllQueuePushN(bin->first, bin->last, entry, next_in_bin);
|
SllQueuePushN(bin->first, bin->last, entry, next_in_bin);
|
||||||
SllQueuePushN(Base.resource.first_entry, Base.resource.last_entry, entry, next);
|
SllQueuePushN(Base.resource.first_entry, Base.resource.last_entry, entry, next);
|
||||||
}
|
}
|
||||||
Base.resource.entries_count += num_entries;
|
Base.resource.entries_count += num_entries;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -44,49 +44,49 @@ void BootstrapResources(u64 archive_strings_count, String *archive_strings)
|
|||||||
|
|
||||||
b32 IsResourceNil(ResourceKey resource)
|
b32 IsResourceNil(ResourceKey resource)
|
||||||
{
|
{
|
||||||
return resource.v == 0;
|
return resource.v == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceKey ResourceKeyFromStore(ResourceStore *store, String name)
|
ResourceKey ResourceKeyFromStore(ResourceStore *store, String name)
|
||||||
{
|
{
|
||||||
ResourceKey result = Zi;
|
ResourceKey result = Zi;
|
||||||
result.v = HashFnv64(store->v, name);
|
result.v = HashFnv64(store->v, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceEntry *ResourceEntryFromHash(u64 hash)
|
ResourceEntry *ResourceEntryFromHash(u64 hash)
|
||||||
{
|
{
|
||||||
ResourceEntry *result = 0;
|
ResourceEntry *result = 0;
|
||||||
ResourceEntryBin *bin = &Base.resource.bins[hash % countof(Base.resource.bins)];
|
ResourceEntryBin *bin = &Base.resource.bins[hash % countof(Base.resource.bins)];
|
||||||
for (ResourceEntry *e = bin->first; e; e = e->next_in_bin)
|
for (ResourceEntry *e = bin->first; e; e = e->next_in_bin)
|
||||||
|
{
|
||||||
|
if (e->hash == hash)
|
||||||
{
|
{
|
||||||
if (e->hash == hash)
|
result = e;
|
||||||
{
|
break;
|
||||||
result = e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DataFromResource(ResourceKey resource)
|
String DataFromResource(ResourceKey resource)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
ResourceEntry *entry = ResourceEntryFromHash(resource.v);
|
ResourceEntry *entry = ResourceEntryFromHash(resource.v);
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
result = entry->data;
|
result = entry->data;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String NameFromResource(ResourceKey resource)
|
String NameFromResource(ResourceKey resource)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
ResourceEntry *entry = ResourceEntryFromHash(resource.v);
|
ResourceEntry *entry = ResourceEntryFromHash(resource.v);
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
result = entry->name;
|
result = entry->name;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,26 +3,26 @@
|
|||||||
|
|
||||||
Struct(ResourceEntry)
|
Struct(ResourceEntry)
|
||||||
{
|
{
|
||||||
ResourceEntry *next;
|
ResourceEntry *next;
|
||||||
ResourceEntry *next_in_bin;
|
ResourceEntry *next_in_bin;
|
||||||
|
|
||||||
u64 hash;
|
u64 hash;
|
||||||
String name;
|
String name;
|
||||||
String data;
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ResourceEntryBin)
|
Struct(ResourceEntryBin)
|
||||||
{
|
{
|
||||||
ResourceEntry *first;
|
ResourceEntry *first;
|
||||||
ResourceEntry *last;
|
ResourceEntry *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ResourceCtx)
|
Struct(ResourceCtx)
|
||||||
{
|
{
|
||||||
u64 entries_count;
|
u64 entries_count;
|
||||||
ResourceEntry *first_entry;
|
ResourceEntry *first_entry;
|
||||||
ResourceEntry *last_entry;
|
ResourceEntry *last_entry;
|
||||||
ResourceEntryBin bins[4096];
|
ResourceEntryBin bins[4096];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -42,7 +42,7 @@ Struct(Rng3U32) { Vec3U32 p0; Vec3U32 p1; };
|
|||||||
template<typename T, u32 N>
|
template<typename T, u32 N>
|
||||||
u32 countof(T arr[N])
|
u32 countof(T arr[N])
|
||||||
{
|
{
|
||||||
return N;
|
return N;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -81,46 +81,46 @@ u32 countof(T arr[N])
|
|||||||
|
|
||||||
Vec4 Vec4FromU32(u32 v)
|
Vec4 Vec4FromU32(u32 v)
|
||||||
{
|
{
|
||||||
Vec4 result;
|
Vec4 result;
|
||||||
result.x = ((v >> 0) & 0xFF) / 255.0;
|
result.x = ((v >> 0) & 0xFF) / 255.0;
|
||||||
result.y = ((v >> 8) & 0xFF) / 255.0;
|
result.y = ((v >> 8) & 0xFF) / 255.0;
|
||||||
result.z = ((v >> 16) & 0xFF) / 255.0;
|
result.z = ((v >> 16) & 0xFF) / 255.0;
|
||||||
result.w = ((v >> 24) & 0xFF) / 255.0;
|
result.w = ((v >> 24) & 0xFF) / 255.0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 U32FromVec4(Vec4 v)
|
u32 U32FromVec4(Vec4 v)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
result |= (((u32)(v.x * 255.0)) & 0xFF) << 0;
|
result |= (((u32)(v.x * 255.0)) & 0xFF) << 0;
|
||||||
result |= (((u32)(v.y * 255.0)) & 0xFF) << 8;
|
result |= (((u32)(v.y * 255.0)) & 0xFF) << 8;
|
||||||
result |= (((u32)(v.z * 255.0)) & 0xFF) << 16;
|
result |= (((u32)(v.z * 255.0)) & 0xFF) << 16;
|
||||||
result |= (((u32)(v.w * 255.0)) & 0xFF) << 24;
|
result |= (((u32)(v.w * 255.0)) & 0xFF) << 24;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 LinearFromSrgbF32(f32 srgb)
|
f32 LinearFromSrgbF32(f32 srgb)
|
||||||
{
|
{
|
||||||
f32 result;
|
f32 result;
|
||||||
if (srgb <= 0.04045f)
|
if (srgb <= 0.04045f)
|
||||||
{
|
{
|
||||||
result = srgb / 12.92f;
|
result = srgb / 12.92f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = pow((srgb + 0.055f) / 1.055f, 2.4f);
|
result = pow((srgb + 0.055f) / 1.055f, 2.4f);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 LinearFromSrgb(Vec4 srgb)
|
Vec4 LinearFromSrgb(Vec4 srgb)
|
||||||
{
|
{
|
||||||
Vec4 result;
|
Vec4 result;
|
||||||
result.x = LinearFromSrgbF32(srgb.x);
|
result.x = LinearFromSrgbF32(srgb.x);
|
||||||
result.y = LinearFromSrgbF32(srgb.y);
|
result.y = LinearFromSrgbF32(srgb.y);
|
||||||
result.z = LinearFromSrgbF32(srgb.z);
|
result.z = LinearFromSrgbF32(srgb.z);
|
||||||
result.w = srgb.w;
|
result.w = srgb.w;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -128,13 +128,13 @@ Vec4 LinearFromSrgb(Vec4 srgb)
|
|||||||
|
|
||||||
Vec2 RectUvFromVertexId(u32 id)
|
Vec2 RectUvFromVertexId(u32 id)
|
||||||
{
|
{
|
||||||
static const Vec2 uvs[4] = {
|
static const Vec2 uvs[4] = {
|
||||||
Vec2(0, 0),
|
Vec2(0, 0),
|
||||||
Vec2(1, 0),
|
Vec2(1, 0),
|
||||||
Vec2(1, 1),
|
Vec2(1, 1),
|
||||||
Vec2(0, 1)
|
Vec2(0, 1)
|
||||||
};
|
};
|
||||||
return uvs[id];
|
return uvs[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -142,20 +142,20 @@ Vec2 RectUvFromVertexId(u32 id)
|
|||||||
|
|
||||||
Vec2 NdcFromPos(Vec2 pos, Vec2 size)
|
Vec2 NdcFromPos(Vec2 pos, Vec2 size)
|
||||||
{
|
{
|
||||||
Vec2 result;
|
Vec2 result;
|
||||||
result = pos / size;
|
result = pos / size;
|
||||||
result *= Vec2(2, -2);
|
result *= Vec2(2, -2);
|
||||||
result += Vec2(-1, 1);
|
result += Vec2(-1, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 NdcFromUv(Vec2 uv)
|
Vec2 NdcFromUv(Vec2 uv)
|
||||||
{
|
{
|
||||||
Vec2 result;
|
Vec2 result;
|
||||||
result = uv;
|
result = uv;
|
||||||
result *= Vec2(2, -2);
|
result *= Vec2(2, -2);
|
||||||
result += Vec2(-1, 1);
|
result += Vec2(-1, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -165,195 +165,195 @@ Vec2 NdcFromUv(Vec2 uv)
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
u32 U32FromChar(in T c)
|
u32 U32FromChar(in T c)
|
||||||
{
|
{
|
||||||
if(c == ' ')
|
if(c == ' ')
|
||||||
return 32;
|
return 32;
|
||||||
if(c == '!')
|
if(c == '!')
|
||||||
return 33;
|
return 33;
|
||||||
if(c == '\"' || c == '\"')
|
if(c == '\"' || c == '\"')
|
||||||
return 34;
|
return 34;
|
||||||
if(c == '#')
|
if(c == '#')
|
||||||
return 35;
|
return 35;
|
||||||
if(c == '$')
|
if(c == '$')
|
||||||
return 36;
|
return 36;
|
||||||
if(c == '%')
|
if(c == '%')
|
||||||
return 37;
|
return 37;
|
||||||
if(c == '&')
|
if(c == '&')
|
||||||
return 38;
|
return 38;
|
||||||
if(c == '\'')
|
if(c == '\'')
|
||||||
return 39;
|
return 39;
|
||||||
if(c == '(')
|
if(c == '(')
|
||||||
return 40;
|
return 40;
|
||||||
if(c == ')')
|
if(c == ')')
|
||||||
return 41;
|
return 41;
|
||||||
if(c == '*')
|
if(c == '*')
|
||||||
return 42;
|
return 42;
|
||||||
if(c == '+')
|
if(c == '+')
|
||||||
return 43;
|
return 43;
|
||||||
if(c == ',')
|
if(c == ',')
|
||||||
return 44;
|
return 44;
|
||||||
if(c == '-')
|
if(c == '-')
|
||||||
return 45;
|
return 45;
|
||||||
if(c == '.')
|
if(c == '.')
|
||||||
return 46;
|
return 46;
|
||||||
if(c == '/')
|
if(c == '/')
|
||||||
return 47;
|
return 47;
|
||||||
if(c == '0')
|
if(c == '0')
|
||||||
return 48;
|
return 48;
|
||||||
if(c == '1')
|
if(c == '1')
|
||||||
return 49;
|
return 49;
|
||||||
if(c == '2')
|
if(c == '2')
|
||||||
return 50;
|
return 50;
|
||||||
if(c == '3')
|
if(c == '3')
|
||||||
return 51;
|
return 51;
|
||||||
if(c == '4')
|
if(c == '4')
|
||||||
return 52;
|
return 52;
|
||||||
if(c == '5')
|
if(c == '5')
|
||||||
return 53;
|
return 53;
|
||||||
if(c == '6')
|
if(c == '6')
|
||||||
return 54;
|
return 54;
|
||||||
if(c == '7')
|
if(c == '7')
|
||||||
return 55;
|
return 55;
|
||||||
if(c == '8')
|
if(c == '8')
|
||||||
return 56;
|
return 56;
|
||||||
if(c == '9')
|
if(c == '9')
|
||||||
return 57;
|
return 57;
|
||||||
if(c == ':')
|
if(c == ':')
|
||||||
return 58;
|
return 58;
|
||||||
if(c == ';')
|
if(c == ';')
|
||||||
return 59;
|
return 59;
|
||||||
if(c == '<')
|
if(c == '<')
|
||||||
return 60;
|
return 60;
|
||||||
if(c == '=')
|
if(c == '=')
|
||||||
return 61;
|
return 61;
|
||||||
if(c == '>')
|
if(c == '>')
|
||||||
return 62;
|
return 62;
|
||||||
if(c == '?')
|
if(c == '?')
|
||||||
return 63;
|
return 63;
|
||||||
if(c == '@')
|
if(c == '@')
|
||||||
return 64;
|
return 64;
|
||||||
if(c == 'A')
|
if(c == 'A')
|
||||||
return 65;
|
return 65;
|
||||||
if(c == 'B')
|
if(c == 'B')
|
||||||
return 66;
|
return 66;
|
||||||
if(c == 'C')
|
if(c == 'C')
|
||||||
return 67;
|
return 67;
|
||||||
if(c == 'D')
|
if(c == 'D')
|
||||||
return 68;
|
return 68;
|
||||||
if(c == 'E')
|
if(c == 'E')
|
||||||
return 69;
|
return 69;
|
||||||
if(c == 'F')
|
if(c == 'F')
|
||||||
return 70;
|
return 70;
|
||||||
if(c == 'G')
|
if(c == 'G')
|
||||||
return 71;
|
return 71;
|
||||||
if(c == 'H')
|
if(c == 'H')
|
||||||
return 72;
|
return 72;
|
||||||
if(c == 'I')
|
if(c == 'I')
|
||||||
return 73;
|
return 73;
|
||||||
if(c == 'J')
|
if(c == 'J')
|
||||||
return 74;
|
return 74;
|
||||||
if(c == 'K')
|
if(c == 'K')
|
||||||
return 75;
|
return 75;
|
||||||
if(c == 'L')
|
if(c == 'L')
|
||||||
return 76;
|
return 76;
|
||||||
if(c == 'M')
|
if(c == 'M')
|
||||||
return 77;
|
return 77;
|
||||||
if(c == 'N')
|
if(c == 'N')
|
||||||
return 78;
|
return 78;
|
||||||
if(c == 'O')
|
if(c == 'O')
|
||||||
return 79;
|
return 79;
|
||||||
if(c == 'P')
|
if(c == 'P')
|
||||||
return 80;
|
return 80;
|
||||||
if(c == 'Q')
|
if(c == 'Q')
|
||||||
return 81;
|
return 81;
|
||||||
if(c == 'R')
|
if(c == 'R')
|
||||||
return 82;
|
return 82;
|
||||||
if(c == 'S')
|
if(c == 'S')
|
||||||
return 83;
|
return 83;
|
||||||
if(c == 'T')
|
if(c == 'T')
|
||||||
return 84;
|
return 84;
|
||||||
if(c == 'U')
|
if(c == 'U')
|
||||||
return 85;
|
return 85;
|
||||||
if(c == 'V')
|
if(c == 'V')
|
||||||
return 86;
|
return 86;
|
||||||
if(c == 'W')
|
if(c == 'W')
|
||||||
return 87;
|
return 87;
|
||||||
if(c == 'X')
|
if(c == 'X')
|
||||||
return 88;
|
return 88;
|
||||||
if(c == 'Y')
|
if(c == 'Y')
|
||||||
return 89;
|
return 89;
|
||||||
if(c == 'Z')
|
if(c == 'Z')
|
||||||
return 90;
|
return 90;
|
||||||
if(c == '[')
|
if(c == '[')
|
||||||
return 91;
|
return 91;
|
||||||
if(c == '\\')
|
if(c == '\\')
|
||||||
return 92;
|
return 92;
|
||||||
if(c == ']')
|
if(c == ']')
|
||||||
return 93;
|
return 93;
|
||||||
if(c == '^')
|
if(c == '^')
|
||||||
return 94;
|
return 94;
|
||||||
if(c == '_')
|
if(c == '_')
|
||||||
return 95;
|
return 95;
|
||||||
if(c == '`')
|
if(c == '`')
|
||||||
return 96;
|
return 96;
|
||||||
if(c == 'a')
|
if(c == 'a')
|
||||||
return 97;
|
return 97;
|
||||||
if(c == 'b')
|
if(c == 'b')
|
||||||
return 98;
|
return 98;
|
||||||
if(c == 'c')
|
if(c == 'c')
|
||||||
return 99;
|
return 99;
|
||||||
if(c == 'd')
|
if(c == 'd')
|
||||||
return 100;
|
return 100;
|
||||||
if(c == 'e')
|
if(c == 'e')
|
||||||
return 101;
|
return 101;
|
||||||
if(c == 'f')
|
if(c == 'f')
|
||||||
return 102;
|
return 102;
|
||||||
if(c == 'g')
|
if(c == 'g')
|
||||||
return 103;
|
return 103;
|
||||||
if(c == 'h')
|
if(c == 'h')
|
||||||
return 104;
|
return 104;
|
||||||
if(c == 'i')
|
if(c == 'i')
|
||||||
return 105;
|
return 105;
|
||||||
if(c == 'j')
|
if(c == 'j')
|
||||||
return 106;
|
return 106;
|
||||||
if(c == 'k')
|
if(c == 'k')
|
||||||
return 107;
|
return 107;
|
||||||
if(c == 'l')
|
if(c == 'l')
|
||||||
return 108;
|
return 108;
|
||||||
if(c == 'm')
|
if(c == 'm')
|
||||||
return 109;
|
return 109;
|
||||||
if(c == 'n')
|
if(c == 'n')
|
||||||
return 110;
|
return 110;
|
||||||
if(c == 'o')
|
if(c == 'o')
|
||||||
return 111;
|
return 111;
|
||||||
if(c == 'p')
|
if(c == 'p')
|
||||||
return 112;
|
return 112;
|
||||||
if(c == 'q')
|
if(c == 'q')
|
||||||
return 113;
|
return 113;
|
||||||
if(c == 'r')
|
if(c == 'r')
|
||||||
return 114;
|
return 114;
|
||||||
if(c == 's')
|
if(c == 's')
|
||||||
return 115;
|
return 115;
|
||||||
if(c == 't')
|
if(c == 't')
|
||||||
return 116;
|
return 116;
|
||||||
if(c == 'u')
|
if(c == 'u')
|
||||||
return 117;
|
return 117;
|
||||||
if(c == 'v')
|
if(c == 'v')
|
||||||
return 118;
|
return 118;
|
||||||
if(c == 'w')
|
if(c == 'w')
|
||||||
return 119;
|
return 119;
|
||||||
if(c == 'x')
|
if(c == 'x')
|
||||||
return 120;
|
return 120;
|
||||||
if(c == 'y')
|
if(c == 'y')
|
||||||
return 121;
|
return 121;
|
||||||
if(c == 'z')
|
if(c == 'z')
|
||||||
return 122;
|
return 122;
|
||||||
if(c == '{')
|
if(c == '{')
|
||||||
return 123;
|
return 123;
|
||||||
if(c == '|')
|
if(c == '|')
|
||||||
return 124;
|
return 124;
|
||||||
if(c == '}')
|
if(c == '}')
|
||||||
return 125;
|
return 125;
|
||||||
if(c == '~')
|
if(c == '~')
|
||||||
return 126;
|
return 126;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
Struct(BaseCtx)
|
Struct(BaseCtx)
|
||||||
{
|
{
|
||||||
CmdLineCtx cmdline;
|
CmdLineCtx cmdline;
|
||||||
ResourceCtx resource;
|
ResourceCtx resource;
|
||||||
GstatCtx gstat;
|
GstatCtx gstat;
|
||||||
AsyncCtx async;
|
AsyncCtx async;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BaseCtx Base;
|
extern BaseCtx Base;
|
||||||
@ -16,7 +16,7 @@ extern BaseCtx Base;
|
|||||||
|
|
||||||
Struct(BaseThreadLocalCtx)
|
Struct(BaseThreadLocalCtx)
|
||||||
{
|
{
|
||||||
ThreadLocalArenaCtx arenas;
|
ThreadLocalArenaCtx arenas;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ThreadLocal BaseThreadLocalCtx Base_tl;
|
extern ThreadLocal BaseThreadLocalCtx Base_tl;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -6,60 +6,60 @@
|
|||||||
|
|
||||||
Enum(FmtArgKind)
|
Enum(FmtArgKind)
|
||||||
{
|
{
|
||||||
FmtArgKind_None,
|
FmtArgKind_None,
|
||||||
|
|
||||||
/* Arbitrary magic numbers for argument validation */
|
/* Arbitrary magic numbers for argument validation */
|
||||||
FmtArgKind_Char = 0xf5281df,
|
FmtArgKind_Char = 0xf5281df,
|
||||||
FmtArgKind_String = 0xa5ffa9a,
|
FmtArgKind_String = 0xa5ffa9a,
|
||||||
|
|
||||||
FmtArgKind_Uint = 0x746f19b,
|
FmtArgKind_Uint = 0x746f19b,
|
||||||
FmtArgKind_Uint2 = 0x83429d9,
|
FmtArgKind_Uint2 = 0x83429d9,
|
||||||
FmtArgKind_Uint3 = 0x1b4b749,
|
FmtArgKind_Uint3 = 0x1b4b749,
|
||||||
FmtArgKind_Uint4 = 0xf8eb3cf,
|
FmtArgKind_Uint4 = 0xf8eb3cf,
|
||||||
|
|
||||||
FmtArgKind_Sint = 0x8603694,
|
FmtArgKind_Sint = 0x8603694,
|
||||||
FmtArgKind_Sint2 = 0x335a803,
|
FmtArgKind_Sint2 = 0x335a803,
|
||||||
FmtArgKind_Sint3 = 0xe5e4ab1,
|
FmtArgKind_Sint3 = 0xe5e4ab1,
|
||||||
FmtArgKind_Sint4 = 0xe1fd7ad,
|
FmtArgKind_Sint4 = 0xe1fd7ad,
|
||||||
|
|
||||||
FmtArgKind_Float = 0x4814143,
|
FmtArgKind_Float = 0x4814143,
|
||||||
FmtArgKind_Float2 = 0x4260065,
|
FmtArgKind_Float2 = 0x4260065,
|
||||||
FmtArgKind_Float3 = 0x0d28ab7,
|
FmtArgKind_Float3 = 0x0d28ab7,
|
||||||
FmtArgKind_Float4 = 0x76fe314,
|
FmtArgKind_Float4 = 0x76fe314,
|
||||||
|
|
||||||
FmtArgKind_Hex = 0xa3d0792,
|
FmtArgKind_Hex = 0xa3d0792,
|
||||||
FmtArgKind_Ptr = 0xc4519e4,
|
FmtArgKind_Ptr = 0xc4519e4,
|
||||||
FmtArgKind_Uid = 0xd1cd407,
|
FmtArgKind_Uid = 0xd1cd407,
|
||||||
FmtArgKind_Handle = 0xead3bec,
|
FmtArgKind_Handle = 0xead3bec,
|
||||||
|
|
||||||
FmtArgKind_End = 0xecbc5ae
|
FmtArgKind_End = 0xecbc5ae
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(FmtArg)
|
Struct(FmtArg)
|
||||||
{
|
{
|
||||||
FmtArgKind kind;
|
FmtArgKind kind;
|
||||||
u32 p; /* Precision */
|
u32 p; /* Precision */
|
||||||
u32 z; /* Z-fill */
|
u32 z; /* Z-fill */
|
||||||
union
|
union
|
||||||
|
{
|
||||||
|
u8 c;
|
||||||
|
String string;
|
||||||
|
Vec4U64 uints;
|
||||||
|
Vec4I64 sints;
|
||||||
|
Vec4F64 floats;
|
||||||
|
void *ptr;
|
||||||
|
Uid uid;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
u8 c;
|
u64 h64[2];
|
||||||
String string;
|
} handle;
|
||||||
Vec4U64 uints;
|
} value;
|
||||||
Vec4I64 sints;
|
|
||||||
Vec4F64 floats;
|
|
||||||
void *ptr;
|
|
||||||
Uid uid;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
u64 h64[2];
|
|
||||||
} handle;
|
|
||||||
} value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(FmtArgArray)
|
Struct(FmtArgArray)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
FmtArg *args;
|
FmtArg *args;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -67,11 +67,11 @@ Struct(FmtArgArray)
|
|||||||
|
|
||||||
Struct(CodepointIter)
|
Struct(CodepointIter)
|
||||||
{
|
{
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
String src;
|
String src;
|
||||||
u64 pos;
|
u64 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -4,135 +4,135 @@
|
|||||||
//- Exclusive mutex lock
|
//- Exclusive mutex lock
|
||||||
Lock LockSpinE(Mutex *m, i32 spin)
|
Lock LockSpinE(Mutex *m, i32 spin)
|
||||||
{
|
{
|
||||||
b32 locked = 0;
|
b32 locked = 0;
|
||||||
i32 spin_cnt = 0;
|
i32 spin_cnt = 0;
|
||||||
while (!locked)
|
while (!locked)
|
||||||
|
{
|
||||||
|
++spin_cnt;
|
||||||
|
u32 v = Atomic32FetchTestSet(&m->v, 0, 0x80000000);
|
||||||
|
if (v == 0)
|
||||||
{
|
{
|
||||||
++spin_cnt;
|
locked = 1;
|
||||||
u32 v = Atomic32FetchTestSet(&m->v, 0, 0x80000000);
|
|
||||||
if (v == 0)
|
|
||||||
{
|
|
||||||
locked = 1;
|
|
||||||
}
|
|
||||||
else if (v == 0x40000000)
|
|
||||||
{
|
|
||||||
/* Lock has pending bit set, try to lock */
|
|
||||||
u32 swp = Atomic32FetchTestSet(&m->v, v, 0x80000000);
|
|
||||||
while (swp != v && swp == 0x40000000)
|
|
||||||
{
|
|
||||||
v = swp;
|
|
||||||
swp = Atomic32FetchTestSet(&m->v, v, 0x80000000);
|
|
||||||
}
|
|
||||||
v = swp;
|
|
||||||
if (v == 0x40000000)
|
|
||||||
{
|
|
||||||
locked = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!locked && (v & 0xC0000000) == 0)
|
|
||||||
{
|
|
||||||
/* Lock has shared lockers and no pending waiter, set pending bit */
|
|
||||||
u32 swp = Atomic32FetchTestSet(&m->v, v, v | 0x40000000);
|
|
||||||
while (swp != v && (swp & 0xC0000000) == 0 && swp != 0)
|
|
||||||
{
|
|
||||||
v = swp;
|
|
||||||
swp = Atomic32FetchTestSet(&m->v, v, v | 0x40000000);
|
|
||||||
}
|
|
||||||
v = swp;
|
|
||||||
}
|
|
||||||
/* Pause or wait */
|
|
||||||
if (!locked && v != 0 && v != 0x40000000)
|
|
||||||
{
|
|
||||||
if (spin_cnt < spin)
|
|
||||||
{
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&m->v, &v, 4);
|
|
||||||
spin_cnt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (v == 0x40000000)
|
||||||
|
{
|
||||||
|
/* Lock has pending bit set, try to lock */
|
||||||
|
u32 swp = Atomic32FetchTestSet(&m->v, v, 0x80000000);
|
||||||
|
while (swp != v && swp == 0x40000000)
|
||||||
|
{
|
||||||
|
v = swp;
|
||||||
|
swp = Atomic32FetchTestSet(&m->v, v, 0x80000000);
|
||||||
|
}
|
||||||
|
v = swp;
|
||||||
|
if (v == 0x40000000)
|
||||||
|
{
|
||||||
|
locked = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!locked && (v & 0xC0000000) == 0)
|
||||||
|
{
|
||||||
|
/* Lock has shared lockers and no pending waiter, set pending bit */
|
||||||
|
u32 swp = Atomic32FetchTestSet(&m->v, v, v | 0x40000000);
|
||||||
|
while (swp != v && (swp & 0xC0000000) == 0 && swp != 0)
|
||||||
|
{
|
||||||
|
v = swp;
|
||||||
|
swp = Atomic32FetchTestSet(&m->v, v, v | 0x40000000);
|
||||||
|
}
|
||||||
|
v = swp;
|
||||||
|
}
|
||||||
|
/* Pause or wait */
|
||||||
|
if (!locked && v != 0 && v != 0x40000000)
|
||||||
|
{
|
||||||
|
if (spin_cnt < spin)
|
||||||
|
{
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FutexYieldNeq(&m->v, &v, 4);
|
||||||
|
spin_cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
Atomic32Set(&m->exclusive_thread_id, ThreadId());
|
Atomic32Set(&m->exclusive_thread_id, ThreadId());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Lock lock = Zi;
|
Lock lock = Zi;
|
||||||
lock.exclusive = 1;
|
lock.exclusive = 1;
|
||||||
lock.mutex = m;
|
lock.mutex = m;
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Shared mutex lock
|
//- Shared mutex lock
|
||||||
Lock LockSpinS(Mutex *m, i32 spin)
|
Lock LockSpinS(Mutex *m, i32 spin)
|
||||||
{
|
{
|
||||||
b32 locked = 0;
|
b32 locked = 0;
|
||||||
i32 spin_cnt = 0;
|
i32 spin_cnt = 0;
|
||||||
while (!locked)
|
while (!locked)
|
||||||
|
{
|
||||||
|
++spin_cnt;
|
||||||
|
u32 v = Atomic32Fetch(&m->v);
|
||||||
|
while (!locked && (v & 0xC0000000) == 0)
|
||||||
{
|
{
|
||||||
++spin_cnt;
|
/* Lock has no exclusive or pending exclusive lock, increment shared count */
|
||||||
u32 v = Atomic32Fetch(&m->v);
|
u32 swp = Atomic32FetchTestSet(&m->v, v, v + 1);
|
||||||
while (!locked && (v & 0xC0000000) == 0)
|
if (v == swp)
|
||||||
{
|
{
|
||||||
/* Lock has no exclusive or pending exclusive lock, increment shared count */
|
locked = 1;
|
||||||
u32 swp = Atomic32FetchTestSet(&m->v, v, v + 1);
|
}
|
||||||
if (v == swp)
|
else
|
||||||
{
|
{
|
||||||
locked = 1;
|
v = swp;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
v = swp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Pause or wait */
|
|
||||||
if (!locked)
|
|
||||||
{
|
|
||||||
if (spin_cnt < spin)
|
|
||||||
{
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&m->v, &v, 4);
|
|
||||||
spin_cnt = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Lock lock = Zi;
|
/* Pause or wait */
|
||||||
lock.mutex = m;
|
if (!locked)
|
||||||
return lock;
|
{
|
||||||
|
if (spin_cnt < spin)
|
||||||
|
{
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FutexYieldNeq(&m->v, &v, 4);
|
||||||
|
spin_cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Lock lock = Zi;
|
||||||
|
lock.mutex = m;
|
||||||
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Mutex lock wrappers
|
//- Mutex lock wrappers
|
||||||
Lock LockE(Mutex *m)
|
Lock LockE(Mutex *m)
|
||||||
{
|
{
|
||||||
return LockSpinE(m, DefaultMutexSpin);
|
return LockSpinE(m, DefaultMutexSpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Lock LockS(Mutex *m)
|
Lock LockS(Mutex *m)
|
||||||
{
|
{
|
||||||
return LockSpinS(m, DefaultMutexSpin);
|
return LockSpinS(m, DefaultMutexSpin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unlock(Lock *l)
|
void Unlock(Lock *l)
|
||||||
{
|
{
|
||||||
Mutex *m = l->mutex;
|
Mutex *m = l->mutex;
|
||||||
if (l->exclusive)
|
if (l->exclusive)
|
||||||
{
|
{
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
Atomic32Set(&m->exclusive_thread_id, 0);
|
Atomic32Set(&m->exclusive_thread_id, 0);
|
||||||
#endif
|
#endif
|
||||||
Atomic32Set(&m->v, 0);
|
Atomic32Set(&m->v, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Atomic32FetchAdd(&m->v, -1);
|
Atomic32FetchAdd(&m->v, -1);
|
||||||
}
|
}
|
||||||
FutexWakeNeq(&m->v);
|
FutexWakeNeq(&m->v);
|
||||||
ZeroStruct(l);
|
ZeroStruct(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -140,29 +140,29 @@ void Unlock(Lock *l)
|
|||||||
|
|
||||||
void YieldOnCv(Cv *cv, Lock *l)
|
void YieldOnCv(Cv *cv, Lock *l)
|
||||||
{
|
{
|
||||||
u64 old_wake_gen = Atomic64Fetch(&cv->wake_gen);
|
u64 old_wake_gen = Atomic64Fetch(&cv->wake_gen);
|
||||||
Mutex *mutex = l->mutex;
|
Mutex *mutex = l->mutex;
|
||||||
b32 exclusive = l->exclusive;
|
b32 exclusive = l->exclusive;
|
||||||
|
{
|
||||||
|
Unlock(l);
|
||||||
{
|
{
|
||||||
Unlock(l);
|
FutexYieldNeq(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen));
|
||||||
{
|
|
||||||
FutexYieldNeq(&cv->wake_gen, &old_wake_gen, sizeof(old_wake_gen));
|
|
||||||
}
|
|
||||||
if (exclusive)
|
|
||||||
{
|
|
||||||
*l = LockE(mutex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*l = LockS(mutex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (exclusive)
|
||||||
|
{
|
||||||
|
*l = LockE(mutex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*l = LockS(mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalCv(Cv *cv)
|
void SignalCv(Cv *cv)
|
||||||
{
|
{
|
||||||
Atomic64FetchAdd(&cv->wake_gen, 1);
|
Atomic64FetchAdd(&cv->wake_gen, 1);
|
||||||
FutexWakeNeq(&cv->wake_gen);
|
FutexWakeNeq(&cv->wake_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -170,36 +170,36 @@ void SignalCv(Cv *cv)
|
|||||||
|
|
||||||
i64 FetchFence(Fence *fence)
|
i64 FetchFence(Fence *fence)
|
||||||
{
|
{
|
||||||
return Atomic64Fetch(&fence->v.v);
|
return Atomic64Fetch(&fence->v.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFence(Fence *fence, i64 x)
|
void SetFence(Fence *fence, i64 x)
|
||||||
{
|
{
|
||||||
Atomic64Set(&fence->v.v, x);
|
Atomic64Set(&fence->v.v, x);
|
||||||
FutexWakeGte(&fence->v.v);
|
FutexWakeGte(&fence->v.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 FetchSetFence(Fence *fence, i64 x)
|
i64 FetchSetFence(Fence *fence, i64 x)
|
||||||
{
|
{
|
||||||
i64 fetch = Atomic64FetchSet(&fence->v.v, x);
|
i64 fetch = Atomic64FetchSet(&fence->v.v, x);
|
||||||
FutexWakeGte(&fence->v.v);
|
FutexWakeGte(&fence->v.v);
|
||||||
return fetch;
|
return fetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 FetchAddFence(Fence *fence, i64 x)
|
i64 FetchAddFence(Fence *fence, i64 x)
|
||||||
{
|
{
|
||||||
i64 fetch = Atomic64FetchAdd(&fence->v.v, x);
|
i64 fetch = Atomic64FetchAdd(&fence->v.v, x);
|
||||||
FutexWakeGte(&fence->v.v);
|
FutexWakeGte(&fence->v.v);
|
||||||
return fetch;
|
return fetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 YieldOnFence(Fence *fence, i64 target)
|
i64 YieldOnFence(Fence *fence, i64 target)
|
||||||
{
|
{
|
||||||
i64 v = Atomic64Fetch(&fence->v.v);
|
i64 v = Atomic64Fetch(&fence->v.v);
|
||||||
while (v < target)
|
while (v < target)
|
||||||
{
|
{
|
||||||
FutexYieldGte(&fence->v.v, &v, sizeof(v));
|
FutexYieldGte(&fence->v.v, &v, sizeof(v));
|
||||||
v = Atomic64Fetch(&fence->v.v);
|
v = Atomic64Fetch(&fence->v.v);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,11 +53,11 @@ void Unlock(Lock *lock);
|
|||||||
|
|
||||||
//- Lock assertion
|
//- Lock assertion
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
# define AssertLockedE(l, m) Assert((l)->mutex == (m) && (l)->exclusive == 1)
|
#define AssertLockedE(l, m) Assert((l)->mutex == (m) && (l)->exclusive == 1)
|
||||||
# define AssertLockedES(l, m) Assert((l)->mutex == (m))
|
#define AssertLockedES(l, m) Assert((l)->mutex == (m))
|
||||||
#else
|
#else
|
||||||
# define AssertLockedE(l, m)
|
#define AssertLockedE(l, m)
|
||||||
# define AssertLockedES(l, m)
|
#define AssertLockedES(l, m)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
Struct(DateTime)
|
Struct(DateTime)
|
||||||
{
|
{
|
||||||
u32 year;
|
u32 year;
|
||||||
u32 month;
|
u32 month;
|
||||||
u32 day_of_week;
|
u32 day_of_week;
|
||||||
u32 day;
|
u32 day;
|
||||||
u32 hour;
|
u32 hour;
|
||||||
u32 minute;
|
u32 minute;
|
||||||
u32 second;
|
u32 second;
|
||||||
u32 milliseconds;
|
u32 milliseconds;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
/* Returns a uid generated from the system's random number generator */
|
/* Returns a uid generated from the system's random number generator */
|
||||||
Uid UidFromTrueRand(void)
|
Uid UidFromTrueRand(void)
|
||||||
{
|
{
|
||||||
Uid result = Zi;
|
Uid result = Zi;
|
||||||
TrueRand(StringFromStruct(&result));
|
TrueRand(StringFromStruct(&result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combines 2 uids into a new uid */
|
/* Combines 2 uids into a new uid */
|
||||||
Uid CombineUid(Uid a, Uid b)
|
Uid CombineUid(Uid a, Uid b)
|
||||||
{
|
{
|
||||||
Uid result;
|
Uid result;
|
||||||
result.hi = (a.hi * 3) + b.hi;
|
result.hi = (a.hi * 3) + b.hi;
|
||||||
result.lo = (a.lo * 3) + b.lo;
|
result.lo = (a.lo * 3) + b.lo;
|
||||||
result.hi += result.lo;
|
result.hi += result.lo;
|
||||||
result.lo += result.hi;
|
result.lo += result.hi;
|
||||||
result.hi = RandU64FromSeed(result.hi);
|
result.hi = RandU64FromSeed(result.hi);
|
||||||
result.lo = RandU64FromSeed(result.lo);
|
result.lo = RandU64FromSeed(result.lo);
|
||||||
result.hi += result.lo;
|
result.hi += result.lo;
|
||||||
result.lo += result.hi;
|
result.lo += result.hi;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
Struct(Uid)
|
Struct(Uid)
|
||||||
{
|
{
|
||||||
u64 hi;
|
u64 hi;
|
||||||
u64 lo;
|
u64 lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -5,126 +5,130 @@
|
|||||||
|
|
||||||
Utf8DecodeResult DecodeUtf8(String str)
|
Utf8DecodeResult DecodeUtf8(String str)
|
||||||
{
|
{
|
||||||
const u8 lengths[32] = {
|
const u8 lengths[32] = {
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5
|
||||||
};
|
};
|
||||||
|
|
||||||
Utf8DecodeResult result = Zi;
|
Utf8DecodeResult result = Zi;
|
||||||
u32 codepoint = U32Max;
|
u32 codepoint = U32Max;
|
||||||
u32 advance = 0;
|
u32 advance = 0;
|
||||||
if (str.len > 0)
|
if (str.len > 0)
|
||||||
|
{
|
||||||
|
u8 c0 = str.text[0];
|
||||||
|
u8 utf8_len = lengths[c0 >> 3];
|
||||||
|
|
||||||
|
advance = 1;
|
||||||
|
switch (utf8_len)
|
||||||
{
|
{
|
||||||
u8 c0 = str.text[0];
|
default: break;
|
||||||
u8 utf8_len = lengths[c0 >> 3];
|
|
||||||
|
|
||||||
advance = 1;
|
case 1:
|
||||||
switch (utf8_len)
|
{
|
||||||
|
codepoint = c0;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (str.len >= 2)
|
||||||
{
|
{
|
||||||
default: break;
|
u8 c1 = str.text[1];
|
||||||
|
if (lengths[c1 >> 3] == 0)
|
||||||
case 1:
|
{
|
||||||
{
|
codepoint = (c1 & 0x3F) << 0;
|
||||||
codepoint = c0;
|
codepoint |= (c0 & 0x1F) << 6;
|
||||||
} break;
|
advance = 2;
|
||||||
|
}
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
if (str.len >= 2)
|
|
||||||
{
|
|
||||||
u8 c1 = str.text[1];
|
|
||||||
if (lengths[c1 >> 3] == 0)
|
|
||||||
{
|
|
||||||
codepoint = (c1 & 0x3F) << 0;
|
|
||||||
codepoint |= (c0 & 0x1F) << 6;
|
|
||||||
advance = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (str.len >= 3)
|
|
||||||
{
|
|
||||||
u8 c1 = str.text[1];
|
|
||||||
u8 c2 = str.text[2];
|
|
||||||
if (lengths[c1 >> 3] == 0 &&
|
|
||||||
lengths[c2 >> 3] == 0)
|
|
||||||
{
|
|
||||||
codepoint = (c2 & 0x3F) << 0;
|
|
||||||
codepoint |= (c1 & 0x3F) << 6;
|
|
||||||
codepoint |= (c0 & 0x0F) << 12;
|
|
||||||
advance = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
if (str.len >= 4)
|
|
||||||
{
|
|
||||||
u8 c1 = str.text[1];
|
|
||||||
u8 c2 = str.text[2];
|
|
||||||
u8 c3 = str.text[3];
|
|
||||||
if (lengths[c1 >> 3] == 0 &&
|
|
||||||
lengths[c2 >> 3] == 0 &&
|
|
||||||
lengths[c3 >> 3] == 0)
|
|
||||||
{
|
|
||||||
codepoint = (c3 & 0x3F) << 0;
|
|
||||||
codepoint |= (c2 & 0x3F) << 6;
|
|
||||||
codepoint |= (c1 & 0x3F) << 12;
|
|
||||||
codepoint |= (c0 & 0x07) << 16;
|
|
||||||
advance = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
|
|
||||||
result.advance8 = advance;
|
case 3:
|
||||||
result.codepoint = codepoint;
|
{
|
||||||
return result;
|
if (str.len >= 3)
|
||||||
|
{
|
||||||
|
u8 c1 = str.text[1];
|
||||||
|
u8 c2 = str.text[2];
|
||||||
|
if (
|
||||||
|
lengths[c1 >> 3] == 0 &&
|
||||||
|
lengths[c2 >> 3] == 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
codepoint = (c2 & 0x3F) << 0;
|
||||||
|
codepoint |= (c1 & 0x3F) << 6;
|
||||||
|
codepoint |= (c0 & 0x0F) << 12;
|
||||||
|
advance = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
if (str.len >= 4)
|
||||||
|
{
|
||||||
|
u8 c1 = str.text[1];
|
||||||
|
u8 c2 = str.text[2];
|
||||||
|
u8 c3 = str.text[3];
|
||||||
|
if (
|
||||||
|
lengths[c1 >> 3] == 0 &&
|
||||||
|
lengths[c2 >> 3] == 0 &&
|
||||||
|
lengths[c3 >> 3] == 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
codepoint = (c3 & 0x3F) << 0;
|
||||||
|
codepoint |= (c2 & 0x3F) << 6;
|
||||||
|
codepoint |= (c1 & 0x3F) << 12;
|
||||||
|
codepoint |= (c0 & 0x07) << 16;
|
||||||
|
advance = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.advance8 = advance;
|
||||||
|
result.codepoint = codepoint;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Encode
|
//- Encode
|
||||||
|
|
||||||
Utf8EncodeResult EncodeUtf8(u32 codepoint)
|
Utf8EncodeResult EncodeUtf8(u32 codepoint)
|
||||||
{
|
{
|
||||||
Utf8EncodeResult result = Zi;
|
Utf8EncodeResult result = Zi;
|
||||||
|
|
||||||
if (codepoint <= 0x7F)
|
if (codepoint <= 0x7F)
|
||||||
{
|
{
|
||||||
result.count8 = 1;
|
result.count8 = 1;
|
||||||
result.chars8[0] = codepoint;
|
result.chars8[0] = codepoint;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x7FF)
|
else if (codepoint <= 0x7FF)
|
||||||
{
|
{
|
||||||
result.count8 = 2;
|
result.count8 = 2;
|
||||||
result.chars8[1] = 0x80 | ((codepoint >> 0) & 0x3F);
|
result.chars8[1] = 0x80 | ((codepoint >> 0) & 0x3F);
|
||||||
result.chars8[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
|
result.chars8[0] = 0xC0 | ((codepoint >> 6) & 0x1F);
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0xFFFF)
|
else if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
result.count8 = 3;
|
result.count8 = 3;
|
||||||
result.chars8[2] = 0x80 | ((codepoint >> 0) & 0x3F);
|
result.chars8[2] = 0x80 | ((codepoint >> 0) & 0x3F);
|
||||||
result.chars8[1] = 0x80 | ((codepoint >> 6) & 0x3F);
|
result.chars8[1] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||||
result.chars8[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
|
result.chars8[0] = 0xE0 | ((codepoint >> 12) & 0x0F);
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x10FFFF)
|
else if (codepoint <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
result.count8 = 4;
|
result.count8 = 4;
|
||||||
result.chars8[3] = 0x80 | ((codepoint >> 0) & 0x3F);
|
result.chars8[3] = 0x80 | ((codepoint >> 0) & 0x3F);
|
||||||
result.chars8[2] = 0x80 | ((codepoint >> 6) & 0x3F);
|
result.chars8[2] = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||||
result.chars8[1] = 0x80 | ((codepoint >> 12) & 0x3F);
|
result.chars8[1] = 0x80 | ((codepoint >> 12) & 0x3F);
|
||||||
result.chars8[0] = 0xF0 | ((codepoint >> 18) & 0x07);
|
result.chars8[0] = 0xF0 | ((codepoint >> 18) & 0x07);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Invalid codepoint */
|
/* Invalid codepoint */
|
||||||
result.count8 = 1;
|
result.count8 = 1;
|
||||||
result.chars8[0] = '?';
|
result.chars8[0] = '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -134,69 +138,69 @@ Utf8EncodeResult EncodeUtf8(u32 codepoint)
|
|||||||
|
|
||||||
Utf16DecodeResult DecodeUtf16(String16 str)
|
Utf16DecodeResult DecodeUtf16(String16 str)
|
||||||
{
|
{
|
||||||
Utf16DecodeResult result = Zi;
|
Utf16DecodeResult result = Zi;
|
||||||
u32 codepoint = U32Max;
|
u32 codepoint = U32Max;
|
||||||
u32 advance = 0;
|
u32 advance = 0;
|
||||||
|
|
||||||
if (str.len >= 1)
|
if (str.len >= 1)
|
||||||
|
{
|
||||||
|
u16 c0 = str.text[0];
|
||||||
|
codepoint = c0;
|
||||||
|
advance = 1;
|
||||||
|
if (str.len >= 2)
|
||||||
{
|
{
|
||||||
u16 c0 = str.text[0];
|
u16 c1 = str.text[1];
|
||||||
codepoint = c0;
|
if ((0xD800 <= c0 && c0 < 0xDC00) && (0xDC00 <= c1 && c1 < 0xE000))
|
||||||
advance = 1;
|
{
|
||||||
if (str.len >= 2)
|
codepoint = (c1 & 0x3FF) << 0;
|
||||||
{
|
codepoint |= (c0 & 0x3FF) << 10;
|
||||||
u16 c1 = str.text[1];
|
advance = 2;
|
||||||
if ((0xD800 <= c0 && c0 < 0xDC00) && (0xDC00 <= c1 && c1 < 0xE000))
|
}
|
||||||
{
|
|
||||||
codepoint = (c1 & 0x3FF) << 0;
|
|
||||||
codepoint |= (c0 & 0x3FF) << 10;
|
|
||||||
advance = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.advance16 = advance;
|
result.advance16 = advance;
|
||||||
result.codepoint = codepoint;
|
result.codepoint = codepoint;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Encode
|
//- Encode
|
||||||
|
|
||||||
Utf16EncodeResult EncodeUtf16(u32 codepoint)
|
Utf16EncodeResult EncodeUtf16(u32 codepoint)
|
||||||
{
|
{
|
||||||
Utf16EncodeResult result = Zi;
|
Utf16EncodeResult result = Zi;
|
||||||
|
|
||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
result.count16 = 1;
|
result.count16 = 1;
|
||||||
result.chars16[0] = codepoint;
|
result.chars16[0] = codepoint;
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0x10FFFF)
|
else if (codepoint <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
result.count16 = 2;
|
result.count16 = 2;
|
||||||
result.chars16[1] = 0xDC00 | ((codepoint >> 0) & 0x3FF);
|
result.chars16[1] = 0xDC00 | ((codepoint >> 0) & 0x3FF);
|
||||||
result.chars16[0] = 0xD800 | ((codepoint >> 10) & 0x3FF);
|
result.chars16[0] = 0xD800 | ((codepoint >> 10) & 0x3FF);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Invalid codepoint */
|
/* Invalid codepoint */
|
||||||
result.count16 = 1;
|
result.count16 = 1;
|
||||||
result.chars16[0] = '?';
|
result.chars16[0] = '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Surrogate check
|
//- Surrogate check
|
||||||
|
|
||||||
b32 IsUtf16HighSurrogate(u16 c)
|
b32 IsUtf16HighSurrogate(u16 c)
|
||||||
{
|
{
|
||||||
return 0xD800 <= c && c < 0xDC00;
|
return 0xD800 <= c && c < 0xDC00;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 IsUtf16LowSurrogate(u16 c)
|
b32 IsUtf16LowSurrogate(u16 c)
|
||||||
{
|
{
|
||||||
return 0xDC00 <= c && c < 0xE000;
|
return 0xDC00 <= c && c < 0xE000;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -206,40 +210,40 @@ b32 IsUtf16LowSurrogate(u16 c)
|
|||||||
|
|
||||||
Utf32DecodeResult DecodeUtf32(String32 str)
|
Utf32DecodeResult DecodeUtf32(String32 str)
|
||||||
{
|
{
|
||||||
Utf32DecodeResult result = Zi;
|
Utf32DecodeResult result = Zi;
|
||||||
u32 codepoint = U32Max;
|
u32 codepoint = U32Max;
|
||||||
u32 advance = 0;
|
u32 advance = 0;
|
||||||
|
|
||||||
if (str.len >= 1)
|
if (str.len >= 1)
|
||||||
|
{
|
||||||
|
u32 c = str.text[0];
|
||||||
|
advance = 1;
|
||||||
|
if (c <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
u32 c = str.text[0];
|
codepoint = c;
|
||||||
advance = 1;
|
|
||||||
if (c <= 0x10FFFF)
|
|
||||||
{
|
|
||||||
codepoint = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.advance32 = advance;
|
result.advance32 = advance;
|
||||||
result.codepoint = codepoint;
|
result.codepoint = codepoint;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Encode
|
//- Encode
|
||||||
|
|
||||||
Utf32EncodeResult EncodeUtf32(u32 codepoint)
|
Utf32EncodeResult EncodeUtf32(u32 codepoint)
|
||||||
{
|
{
|
||||||
Utf32EncodeResult result = Zi;
|
Utf32EncodeResult result = Zi;
|
||||||
|
|
||||||
if (codepoint <= 0x10FFFF)
|
if (codepoint <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
result.chars32 = codepoint;
|
result.chars32 = codepoint;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Invalid codepoint */
|
/* Invalid codepoint */
|
||||||
result.chars32 = '?';
|
result.chars32 = '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
Struct(Utf8DecodeResult)
|
Struct(Utf8DecodeResult)
|
||||||
{
|
{
|
||||||
u32 advance8;
|
u32 advance8;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Utf8EncodeResult)
|
Struct(Utf8EncodeResult)
|
||||||
{
|
{
|
||||||
u32 count8;
|
u32 count8;
|
||||||
u8 chars8[4];
|
u8 chars8[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -18,14 +18,14 @@ Struct(Utf8EncodeResult)
|
|||||||
|
|
||||||
Struct(Utf16DecodeResult)
|
Struct(Utf16DecodeResult)
|
||||||
{
|
{
|
||||||
u32 advance16;
|
u32 advance16;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Utf16EncodeResult)
|
Struct(Utf16EncodeResult)
|
||||||
{
|
{
|
||||||
u32 count16;
|
u32 count16;
|
||||||
u16 chars16[2];
|
u16 chars16[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -33,13 +33,13 @@ Struct(Utf16EncodeResult)
|
|||||||
|
|
||||||
Struct(Utf32DecodeResult)
|
Struct(Utf32DecodeResult)
|
||||||
{
|
{
|
||||||
u32 advance32;
|
u32 advance32;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Utf32EncodeResult)
|
Struct(Utf32EncodeResult)
|
||||||
{
|
{
|
||||||
u32 chars32;
|
u32 chars32;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -19,27 +19,27 @@ typedef MergesortCompareFuncDef(MergesortCompareFunc, a, b, udata);
|
|||||||
|
|
||||||
Struct(DictEntry)
|
Struct(DictEntry)
|
||||||
{
|
{
|
||||||
u64 hash;
|
u64 hash;
|
||||||
u64 value;
|
u64 value;
|
||||||
DictEntry *prev_in_bin;
|
DictEntry *prev_in_bin;
|
||||||
DictEntry *next_in_bin;
|
DictEntry *next_in_bin;
|
||||||
DictEntry *prev;
|
DictEntry *prev;
|
||||||
DictEntry *next;
|
DictEntry *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(DictBin)
|
Struct(DictBin)
|
||||||
{
|
{
|
||||||
DictEntry *first;
|
DictEntry *first;
|
||||||
DictEntry *last;
|
DictEntry *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(Dict)
|
Struct(Dict)
|
||||||
{
|
{
|
||||||
u64 bins_count;
|
u64 bins_count;
|
||||||
DictBin *bins;
|
DictBin *bins;
|
||||||
DictEntry *first_free;
|
DictEntry *first_free;
|
||||||
DictEntry *first;
|
DictEntry *first;
|
||||||
DictEntry *last;
|
DictEntry *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -50,31 +50,31 @@ Struct(Dict)
|
|||||||
*/
|
*/
|
||||||
Inline u64 HashFnv64(u64 seed, String s)
|
Inline u64 HashFnv64(u64 seed, String s)
|
||||||
{
|
{
|
||||||
u64 hash = seed;
|
u64 hash = seed;
|
||||||
for (u64 i = 0; i < s.len; ++i)
|
for (u64 i = 0; i < s.len; ++i)
|
||||||
{
|
{
|
||||||
hash ^= (u8)s.text[i];
|
hash ^= (u8)s.text[i];
|
||||||
hash *= 0x100000001B3;
|
hash *= 0x100000001B3;
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HashF(fmt_cstr, ...) HashF_(StringFromCstrNoLimit(fmt_cstr), __VA_ARGS__, FmtEnd)
|
#define HashF(fmt_cstr, ...) HashF_(StringFromCstrNoLimit(fmt_cstr), __VA_ARGS__, FmtEnd)
|
||||||
Inline u64 HashF_(String fmt, ...)
|
Inline u64 HashF_(String fmt, ...)
|
||||||
{
|
{
|
||||||
u64 result = 0;
|
u64 result = 0;
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
{
|
{
|
||||||
va_list args;
|
String str = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args));
|
||||||
va_start(args, fmt);
|
result = HashFnv64(Fnv64Basis, str);
|
||||||
{
|
|
||||||
String str = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args));
|
|
||||||
result = HashFnv64(Fnv64Basis, str);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
va_end(args);
|
||||||
return result;
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -82,67 +82,67 @@ Inline u64 HashF_(String fmt, ...)
|
|||||||
|
|
||||||
Inline void MergesortInternal(u8 *left, u8 *right, u8 *items, u64 left_count, u64 right_count, u64 item_size, MergesortCompareFunc *callback, void *udata)
|
Inline void MergesortInternal(u8 *left, u8 *right, u8 *items, u64 left_count, u64 right_count, u64 item_size, MergesortCompareFunc *callback, void *udata)
|
||||||
{
|
{
|
||||||
/* Sort */
|
/* Sort */
|
||||||
u64 i = 0;
|
u64 i = 0;
|
||||||
u64 l = 0;
|
u64 l = 0;
|
||||||
u64 r = 0;
|
u64 r = 0;
|
||||||
while (l < left_count && r < right_count)
|
while (l < left_count && r < right_count)
|
||||||
|
{
|
||||||
|
u8 *dst = items + (i * item_size);
|
||||||
|
u8 *left_item = left + (l * item_size);
|
||||||
|
u8 *right_item = right + (r * item_size);
|
||||||
|
++i;
|
||||||
|
if (callback(left_item, right_item, udata) > 0)
|
||||||
{
|
{
|
||||||
u8 *dst = items + (i * item_size);
|
CopyBytes(dst, left_item, item_size);
|
||||||
u8 *left_item = left + (l * item_size);
|
++l;
|
||||||
u8 *right_item = right + (r * item_size);
|
|
||||||
++i;
|
|
||||||
if (callback(left_item, right_item, udata) > 0)
|
|
||||||
{
|
|
||||||
CopyBytes(dst, left_item, item_size);
|
|
||||||
++l;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CopyBytes(dst, right_item, item_size);
|
|
||||||
++r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Copy remaining */
|
else
|
||||||
if (l != left_count)
|
|
||||||
{
|
{
|
||||||
u64 remaining_count = left_count - l;
|
CopyBytes(dst, right_item, item_size);
|
||||||
u64 remaining_bytes = remaining_count * item_size;
|
++r;
|
||||||
u8 *dst = items + (i * item_size);
|
|
||||||
u8 *src = left + (l * item_size);
|
|
||||||
CopyBytes(dst, src, remaining_bytes);
|
|
||||||
}
|
|
||||||
else if (r != right_count)
|
|
||||||
{
|
|
||||||
u64 remaining_count = right_count - r;
|
|
||||||
u64 remaining_bytes = remaining_count * item_size;
|
|
||||||
u8 *dst = items + (i * item_size);
|
|
||||||
u8 *src = right + (r * item_size);
|
|
||||||
CopyBytes(dst, src, remaining_bytes);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* Copy remaining */
|
||||||
|
if (l != left_count)
|
||||||
|
{
|
||||||
|
u64 remaining_count = left_count - l;
|
||||||
|
u64 remaining_bytes = remaining_count * item_size;
|
||||||
|
u8 *dst = items + (i * item_size);
|
||||||
|
u8 *src = left + (l * item_size);
|
||||||
|
CopyBytes(dst, src, remaining_bytes);
|
||||||
|
}
|
||||||
|
else if (r != right_count)
|
||||||
|
{
|
||||||
|
u64 remaining_count = right_count - r;
|
||||||
|
u64 remaining_bytes = remaining_count * item_size;
|
||||||
|
u8 *dst = items + (i * item_size);
|
||||||
|
u8 *src = right + (r * item_size);
|
||||||
|
CopyBytes(dst, src, remaining_bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline void Mergesort(void *items, u64 item_count, u64 item_size, MergesortCompareFunc *callback, void *udata)
|
Inline void Mergesort(void *items, u64 item_count, u64 item_size, MergesortCompareFunc *callback, void *udata)
|
||||||
{
|
{
|
||||||
if (item_count > 1)
|
if (item_count > 1)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
u64 left_count = item_count / 2;
|
u64 left_count = item_count / 2;
|
||||||
u64 right_count = item_count - left_count;
|
u64 right_count = item_count - left_count;
|
||||||
|
|
||||||
u64 left_size = left_count * item_size;
|
u64 left_size = left_count * item_size;
|
||||||
u64 right_size = right_count * item_size;
|
u64 right_size = right_count * item_size;
|
||||||
|
|
||||||
u8 *left = PushStructsNoZero(scratch.arena, u8, left_size);
|
u8 *left = PushStructsNoZero(scratch.arena, u8, left_size);
|
||||||
u8 *right = PushStructsNoZero(scratch.arena, u8, right_size);
|
u8 *right = PushStructsNoZero(scratch.arena, u8, right_size);
|
||||||
CopyBytes(left, items, left_size);
|
CopyBytes(left, items, left_size);
|
||||||
CopyBytes(right, (u8 *)items + left_size, right_size);
|
CopyBytes(right, (u8 *)items + left_size, right_size);
|
||||||
|
|
||||||
Mergesort(left, left_count, item_size, callback, udata);
|
Mergesort(left, left_count, item_size, callback, udata);
|
||||||
Mergesort(right, right_count, item_size, callback, udata);
|
Mergesort(right, right_count, item_size, callback, udata);
|
||||||
MergesortInternal(left, right, (u8 *)items, left_count, right_count, item_size, callback, udata);
|
MergesortInternal(left, right, (u8 *)items, left_count, right_count, item_size, callback, udata);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -152,164 +152,164 @@ Inline void Mergesort(void *items, u64 item_count, u64 item_size, MergesortCompa
|
|||||||
|
|
||||||
Inline Dict *InitDict(Arena *arena, u64 bins_count)
|
Inline Dict *InitDict(Arena *arena, u64 bins_count)
|
||||||
{
|
{
|
||||||
Dict *dict = PushStruct(arena, Dict);
|
Dict *dict = PushStruct(arena, Dict);
|
||||||
dict->bins_count = MaxU64(bins_count, 1); /* Ensure at least 1 bin */
|
dict->bins_count = MaxU64(bins_count, 1); /* Ensure at least 1 bin */
|
||||||
dict->bins = PushStructs(arena, DictBin, dict->bins_count);
|
dict->bins = PushStructs(arena, DictBin, dict->bins_count);
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline void ResetDict(Dict *dict)
|
Inline void ResetDict(Dict *dict)
|
||||||
{
|
{
|
||||||
ZeroBytes(dict->bins, sizeof(*dict->bins) * dict->bins_count);
|
ZeroBytes(dict->bins, sizeof(*dict->bins) * dict->bins_count);
|
||||||
if (dict->first)
|
if (dict->first)
|
||||||
{
|
{
|
||||||
dict->last->next = dict->first_free;
|
dict->last->next = dict->first_free;
|
||||||
dict->first_free = dict->first;
|
dict->first_free = dict->first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Dict set
|
//- Dict set
|
||||||
|
|
||||||
Inline DictEntry *EnsureDictEntry(Arena *arena, Dict *dict, u64 hash)
|
Inline DictEntry *EnsureDictEntry(Arena *arena, Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
||||||
|
|
||||||
DictEntry *entry = bin->first;
|
DictEntry *entry = bin->first;
|
||||||
while (entry)
|
while (entry)
|
||||||
|
{
|
||||||
|
if (hash == entry->hash)
|
||||||
{
|
{
|
||||||
if (hash == entry->hash)
|
/* Existing match found */
|
||||||
{
|
break;
|
||||||
/* Existing match found */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entry = entry->next_in_bin;
|
|
||||||
}
|
}
|
||||||
|
entry = entry->next_in_bin;
|
||||||
|
}
|
||||||
|
|
||||||
/* No match found, create new entry */
|
/* No match found, create new entry */
|
||||||
if (!entry)
|
if (!entry)
|
||||||
|
{
|
||||||
|
if (dict->first_free)
|
||||||
{
|
{
|
||||||
if (dict->first_free)
|
entry = dict->first_free;
|
||||||
{
|
dict->first_free = entry->next;
|
||||||
entry = dict->first_free;
|
|
||||||
dict->first_free = entry->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry = PushStructNoZero(arena, DictEntry);
|
|
||||||
}
|
|
||||||
ZeroStruct(entry);
|
|
||||||
entry->hash = hash;
|
|
||||||
if (bin->last)
|
|
||||||
{
|
|
||||||
bin->last->next_in_bin = entry;
|
|
||||||
entry->prev_in_bin = bin->last;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bin->first = entry;
|
|
||||||
}
|
|
||||||
bin->last = entry;
|
|
||||||
if (dict->last)
|
|
||||||
{
|
|
||||||
dict->last->next = entry;
|
|
||||||
entry->prev = dict->last;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dict->first = entry;
|
|
||||||
}
|
|
||||||
dict->last = entry;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry = PushStructNoZero(arena, DictEntry);
|
||||||
|
}
|
||||||
|
ZeroStruct(entry);
|
||||||
|
entry->hash = hash;
|
||||||
|
if (bin->last)
|
||||||
|
{
|
||||||
|
bin->last->next_in_bin = entry;
|
||||||
|
entry->prev_in_bin = bin->last;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bin->first = entry;
|
||||||
|
}
|
||||||
|
bin->last = entry;
|
||||||
|
if (dict->last)
|
||||||
|
{
|
||||||
|
dict->last->next = entry;
|
||||||
|
entry->prev = dict->last;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict->first = entry;
|
||||||
|
}
|
||||||
|
dict->last = entry;
|
||||||
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline void SetDictValue(Arena *arena, Dict *dict, u64 hash, u64 value)
|
Inline void SetDictValue(Arena *arena, Dict *dict, u64 hash, u64 value)
|
||||||
{
|
{
|
||||||
DictEntry *entry = EnsureDictEntry(arena, dict, hash);
|
DictEntry *entry = EnsureDictEntry(arena, dict, hash);
|
||||||
entry->value = value;
|
entry->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Dict remove
|
//- Dict remove
|
||||||
|
|
||||||
Inline void RemoveDictEntry(Dict *dict, DictEntry *entry)
|
Inline void RemoveDictEntry(Dict *dict, DictEntry *entry)
|
||||||
{
|
{
|
||||||
/* Remove from bin */
|
/* Remove from bin */
|
||||||
|
{
|
||||||
|
DictBin *bin = &dict->bins[entry->hash % dict->bins_count];
|
||||||
|
DictEntry *prev_in_bin = entry->prev_in_bin;
|
||||||
|
DictEntry *next_in_bin = entry->next_in_bin;
|
||||||
|
if (prev_in_bin)
|
||||||
{
|
{
|
||||||
DictBin *bin = &dict->bins[entry->hash % dict->bins_count];
|
prev_in_bin->next_in_bin = next_in_bin;
|
||||||
DictEntry *prev_in_bin = entry->prev_in_bin;
|
|
||||||
DictEntry *next_in_bin = entry->next_in_bin;
|
|
||||||
if (prev_in_bin)
|
|
||||||
{
|
|
||||||
prev_in_bin->next_in_bin = next_in_bin;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bin->first = next_in_bin;
|
|
||||||
}
|
|
||||||
if (next_in_bin)
|
|
||||||
{
|
|
||||||
next_in_bin->prev_in_bin = prev_in_bin;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bin->last = prev_in_bin;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Remove from list */
|
else
|
||||||
{
|
{
|
||||||
DictEntry *prev = entry->prev;
|
bin->first = next_in_bin;
|
||||||
DictEntry *next = entry->next;
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
prev->next = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dict->first = next;
|
|
||||||
}
|
|
||||||
if (next)
|
|
||||||
{
|
|
||||||
next->prev = prev;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dict->last = prev;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Insert into free list */
|
if (next_in_bin)
|
||||||
{
|
{
|
||||||
entry->next = dict->first_free;
|
next_in_bin->prev_in_bin = prev_in_bin;
|
||||||
dict->first_free = entry;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bin->last = prev_in_bin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Remove from list */
|
||||||
|
{
|
||||||
|
DictEntry *prev = entry->prev;
|
||||||
|
DictEntry *next = entry->next;
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict->first = next;
|
||||||
|
}
|
||||||
|
if (next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict->last = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Insert into free list */
|
||||||
|
{
|
||||||
|
entry->next = dict->first_free;
|
||||||
|
dict->first_free = entry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Dict index
|
//- Dict index
|
||||||
|
|
||||||
Inline DictEntry *DictEntryFromHash(Dict *dict, u64 hash)
|
Inline DictEntry *DictEntryFromHash(Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
DictEntry *result = 0;
|
DictEntry *result = 0;
|
||||||
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
||||||
for (DictEntry *entry = bin->first; entry; entry = entry->next_in_bin)
|
for (DictEntry *entry = bin->first; entry; entry = entry->next_in_bin)
|
||||||
|
{
|
||||||
|
if (hash == entry->hash)
|
||||||
{
|
{
|
||||||
if (hash == entry->hash)
|
/* Match found */
|
||||||
{
|
result = entry;
|
||||||
/* Match found */
|
break;
|
||||||
result = entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline u64 DictValueFromHash(Dict *dict, u64 hash)
|
Inline u64 DictValueFromHash(Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
DictEntry *entry = DictEntryFromHash(dict, hash);
|
DictEntry *entry = DictEntryFromHash(dict, hash);
|
||||||
return entry ? entry->value : 0;
|
return entry ? entry->value : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inline u64 DictValueOrNilFromHash(Dict *dict, u64 hash, u64 nil)
|
Inline u64 DictValueOrNilFromHash(Dict *dict, u64 hash, u64 nil)
|
||||||
{
|
{
|
||||||
DictEntry *entry = DictEntryFromHash(dict, hash);
|
DictEntry *entry = DictEntryFromHash(dict, hash);
|
||||||
return entry ? entry->value : nil;
|
return entry ? entry->value : nil;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,108 +3,108 @@
|
|||||||
|
|
||||||
void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count)
|
void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count)
|
||||||
{
|
{
|
||||||
WaveCtx *wave = lane->wave;
|
WaveCtx *wave = lane->wave;
|
||||||
i32 lanes_count = wave->lanes_count;
|
i32 lanes_count = wave->lanes_count;
|
||||||
if (lanes_count > 1)
|
if (lanes_count > 1)
|
||||||
|
{
|
||||||
|
i64 sync_gen = Atomic64Fetch(&wave->sync_gen.v);
|
||||||
|
i32 blocked_count = Atomic32FetchAdd(&wave->sync_count.v, 1) + 1;
|
||||||
|
if (blocked_count == lanes_count)
|
||||||
{
|
{
|
||||||
i64 sync_gen = Atomic64Fetch(&wave->sync_gen.v);
|
Atomic32Set(&wave->sync_count.v, 0);
|
||||||
i32 blocked_count = Atomic32FetchAdd(&wave->sync_count.v, 1) + 1;
|
Atomic64Set(&wave->sync_gen.v, sync_gen + 1);
|
||||||
if (blocked_count == lanes_count)
|
FutexWakeNeq(&wave->sync_gen.v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 remaining_spins = spin_count;
|
||||||
|
while (Atomic64Fetch(&wave->sync_gen.v) == sync_gen)
|
||||||
|
{
|
||||||
|
if (remaining_spins > 0)
|
||||||
{
|
{
|
||||||
Atomic32Set(&wave->sync_count.v, 0);
|
--remaining_spins;
|
||||||
Atomic64Set(&wave->sync_gen.v, sync_gen + 1);
|
_mm_pause();
|
||||||
FutexWakeNeq(&wave->sync_gen.v);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 remaining_spins = spin_count;
|
FutexYieldNeq(&wave->sync_gen.v, &sync_gen, sizeof(sync_gen));
|
||||||
while (Atomic64Fetch(&wave->sync_gen.v) == sync_gen)
|
|
||||||
{
|
|
||||||
if (remaining_spins > 0)
|
|
||||||
{
|
|
||||||
--remaining_spins;
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&wave->sync_gen.v, &sync_gen, sizeof(sync_gen));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count)
|
void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count)
|
||||||
{
|
{
|
||||||
WaveCtx *wave = lane->wave;
|
WaveCtx *wave = lane->wave;
|
||||||
i32 lanes_count = wave->lanes_count;
|
i32 lanes_count = wave->lanes_count;
|
||||||
if (lanes_count > 1)
|
if (lanes_count > 1)
|
||||||
|
{
|
||||||
|
u32 lane_idx = lane->idx;
|
||||||
|
|
||||||
|
if (lane_idx == broadcast_lane_idx)
|
||||||
{
|
{
|
||||||
u32 lane_idx = lane->idx;
|
/* Broadcast */
|
||||||
|
wave->broadcast_data = broadcast_ptr;
|
||||||
|
i64 ack_gen = Atomic64Fetch(&wave->ack_gen.v);
|
||||||
|
lane->seen_broadcast_gen = Atomic64FetchAdd(&wave->broadcast_gen.v, 1) + 1;
|
||||||
|
FutexWakeNeq(&wave->broadcast_gen.v);
|
||||||
|
|
||||||
if (lane_idx == broadcast_lane_idx)
|
/* Wait for ack */
|
||||||
|
{
|
||||||
|
u64 remaining_spins = spin_count;
|
||||||
|
while (Atomic64Fetch(&wave->ack_gen.v) == ack_gen)
|
||||||
{
|
{
|
||||||
/* Broadcast */
|
if (remaining_spins > 0)
|
||||||
wave->broadcast_data = broadcast_ptr;
|
{
|
||||||
i64 ack_gen = Atomic64Fetch(&wave->ack_gen.v);
|
--remaining_spins;
|
||||||
lane->seen_broadcast_gen = Atomic64FetchAdd(&wave->broadcast_gen.v, 1) + 1;
|
_mm_pause();
|
||||||
FutexWakeNeq(&wave->broadcast_gen.v);
|
}
|
||||||
|
else
|
||||||
/* Wait for ack */
|
{
|
||||||
{
|
FutexYieldNeq(&wave->ack_gen.v, &ack_gen, sizeof(ack_gen));
|
||||||
u64 remaining_spins = spin_count;
|
}
|
||||||
while (Atomic64Fetch(&wave->ack_gen.v) == ack_gen)
|
|
||||||
{
|
|
||||||
if (remaining_spins > 0)
|
|
||||||
{
|
|
||||||
--remaining_spins;
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&wave->ack_gen.v, &ack_gen, sizeof(ack_gen));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Wait for broadcast */
|
|
||||||
i64 seen_broadcast_gen = lane->seen_broadcast_gen++;
|
|
||||||
{
|
|
||||||
u64 remaining_spins = spin_count;
|
|
||||||
while (Atomic64Fetch(&wave->broadcast_gen.v) == seen_broadcast_gen)
|
|
||||||
{
|
|
||||||
if (remaining_spins > 0)
|
|
||||||
{
|
|
||||||
--remaining_spins;
|
|
||||||
_mm_pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FutexYieldNeq(&wave->broadcast_gen.v, &seen_broadcast_gen, sizeof(seen_broadcast_gen));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy broadcast data */
|
|
||||||
CopyBytes(broadcast_ptr, wave->broadcast_data, broadcast_size);
|
|
||||||
|
|
||||||
/* Ack */
|
|
||||||
i32 ack_count = Atomic32FetchAdd(&wave->ack_count.v, 1) + 1;
|
|
||||||
if (ack_count == lanes_count - 1)
|
|
||||||
{
|
|
||||||
Atomic32Set(&wave->ack_count.v, 0);
|
|
||||||
Atomic64FetchAdd(&wave->ack_gen.v, 1);
|
|
||||||
FutexWakeNeq(&wave->ack_gen.v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Wait for broadcast */
|
||||||
|
i64 seen_broadcast_gen = lane->seen_broadcast_gen++;
|
||||||
|
{
|
||||||
|
u64 remaining_spins = spin_count;
|
||||||
|
while (Atomic64Fetch(&wave->broadcast_gen.v) == seen_broadcast_gen)
|
||||||
|
{
|
||||||
|
if (remaining_spins > 0)
|
||||||
|
{
|
||||||
|
--remaining_spins;
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FutexYieldNeq(&wave->broadcast_gen.v, &seen_broadcast_gen, sizeof(seen_broadcast_gen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy broadcast data */
|
||||||
|
CopyBytes(broadcast_ptr, wave->broadcast_data, broadcast_size);
|
||||||
|
|
||||||
|
/* Ack */
|
||||||
|
i32 ack_count = Atomic32FetchAdd(&wave->ack_count.v, 1) + 1;
|
||||||
|
if (ack_count == lanes_count - 1)
|
||||||
|
{
|
||||||
|
Atomic32Set(&wave->ack_count.v, 0);
|
||||||
|
Atomic64FetchAdd(&wave->ack_gen.v, 1);
|
||||||
|
FutexWakeNeq(&wave->ack_gen.v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n)
|
void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n)
|
||||||
{
|
{
|
||||||
lane->default_spin_count = n;
|
lane->default_spin_count = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -112,30 +112,30 @@ void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n)
|
|||||||
|
|
||||||
i32 WaveLaneIdxFromTaskIdx(WaveLaneCtx *lane, u64 task_idx)
|
i32 WaveLaneIdxFromTaskIdx(WaveLaneCtx *lane, u64 task_idx)
|
||||||
{
|
{
|
||||||
WaveCtx *wave = lane->wave;
|
WaveCtx *wave = lane->wave;
|
||||||
return task_idx % wave->lanes_count;
|
return task_idx % wave->lanes_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
RngU64 WaveIdxRangeFromCount(WaveLaneCtx *lane, u64 tasks_count)
|
RngU64 WaveIdxRangeFromCount(WaveLaneCtx *lane, u64 tasks_count)
|
||||||
{
|
{
|
||||||
u64 lanes_count = lane->wave->lanes_count;
|
u64 lanes_count = lane->wave->lanes_count;
|
||||||
u64 lane_idx = lane->idx;
|
u64 lane_idx = lane->idx;
|
||||||
|
|
||||||
u64 tasks_per_lane = tasks_count / lanes_count;
|
u64 tasks_per_lane = tasks_count / lanes_count;
|
||||||
u64 tasks_overflow = tasks_count % lanes_count;
|
u64 tasks_overflow = tasks_count % lanes_count;
|
||||||
|
|
||||||
u64 start = lane_idx * tasks_per_lane;
|
u64 start = lane_idx * tasks_per_lane;
|
||||||
u64 end = start + tasks_per_lane;
|
u64 end = start + tasks_per_lane;
|
||||||
if (lane_idx < tasks_overflow)
|
if (lane_idx < tasks_overflow)
|
||||||
{
|
{
|
||||||
start += lane_idx;
|
start += lane_idx;
|
||||||
end += lane_idx + 1;
|
end += lane_idx + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
start += tasks_overflow;
|
start += tasks_overflow;
|
||||||
end += tasks_overflow;
|
end += tasks_overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RNGU64(start, end);
|
return RNGU64(start, end);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,26 +6,26 @@
|
|||||||
|
|
||||||
AlignedStruct(WaveCtx, CachelineSize)
|
AlignedStruct(WaveCtx, CachelineSize)
|
||||||
{
|
{
|
||||||
i32 lanes_count;
|
i32 lanes_count;
|
||||||
void *udata;
|
void *udata;
|
||||||
|
|
||||||
/* Sync barrier */
|
/* Sync barrier */
|
||||||
Atomic32Padded sync_count;
|
Atomic32Padded sync_count;
|
||||||
Atomic64Padded sync_gen;
|
Atomic64Padded sync_gen;
|
||||||
|
|
||||||
/* Broadcast barrier */
|
/* Broadcast barrier */
|
||||||
void *broadcast_data;
|
void *broadcast_data;
|
||||||
Atomic64Padded broadcast_gen;
|
Atomic64Padded broadcast_gen;
|
||||||
Atomic32Padded ack_count;
|
Atomic32Padded ack_count;
|
||||||
Atomic64Padded ack_gen;
|
Atomic64Padded ack_gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
AlignedStruct(WaveLaneCtx, CachelineSize)
|
AlignedStruct(WaveLaneCtx, CachelineSize)
|
||||||
{
|
{
|
||||||
i32 idx;
|
i32 idx;
|
||||||
WaveCtx *wave;
|
WaveCtx *wave;
|
||||||
u64 default_spin_count;
|
u64 default_spin_count;
|
||||||
i64 seen_broadcast_gen;
|
i64 seen_broadcast_gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void WaveLaneEntryFunc(WaveLaneCtx *lane);
|
typedef void WaveLaneEntryFunc(WaveLaneCtx *lane);
|
||||||
@ -34,14 +34,16 @@ typedef void WaveLaneEntryFunc(WaveLaneCtx *lane);
|
|||||||
//~ Wave sync ops
|
//~ Wave sync ops
|
||||||
|
|
||||||
void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count);
|
void WaveSyncEx(WaveLaneCtx *lane, u64 spin_count);
|
||||||
#define WaveSync(lane) \
|
|
||||||
WaveSyncEx((lane), (lane)->default_spin_count)
|
|
||||||
|
|
||||||
void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count);
|
void WaveSyncBroadcastEx_(WaveLaneCtx *lane, u32 broadcast_lane_idx, void *broadcast_ptr, u64 broadcast_size, u64 spin_count);
|
||||||
|
|
||||||
|
#define WaveSync(lane) \
|
||||||
|
WaveSyncEx((lane), (lane)->default_spin_count)
|
||||||
|
|
||||||
#define WaveSyncBroadcastEx(lane, broadcast_lane_idx, broadcast_ptr, spin_count) \
|
#define WaveSyncBroadcastEx(lane, broadcast_lane_idx, broadcast_ptr, spin_count) \
|
||||||
WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (spin_count))
|
WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (spin_count))
|
||||||
|
|
||||||
#define WaveSyncBroadcast(lane, broadcast_lane_idx, broadcast_ptr) \
|
#define WaveSyncBroadcast(lane, broadcast_lane_idx, broadcast_ptr) \
|
||||||
WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (lane)->default_spin_count)
|
WaveSyncBroadcastEx_((lane), (broadcast_lane_idx), (broadcast_ptr), sizeof(*(broadcast_ptr)), (lane)->default_spin_count)
|
||||||
|
|
||||||
void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n);
|
void SetWaveLaneDefaultSpin(WaveLaneCtx *lane, u64 n);
|
||||||
|
|
||||||
|
|||||||
@ -5,34 +5,34 @@ W32_Ctx W32 = Zi;
|
|||||||
|
|
||||||
BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name, LONG_PTR udata)
|
BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name, LONG_PTR udata)
|
||||||
{
|
{
|
||||||
W32_FindEmbeddedDataCtx *ctx = (W32_FindEmbeddedDataCtx *)udata;
|
W32_FindEmbeddedDataCtx *ctx = (W32_FindEmbeddedDataCtx *)udata;
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
String entry_name = StringFromWstrNoLimit(scratch.arena, (LPWSTR)wstr_entry_name);
|
String entry_name = StringFromWstrNoLimit(scratch.arena, (LPWSTR)wstr_entry_name);
|
||||||
String embedded_data_prefix = Lit(Stringize(W32_EmbeddedDataPrefix));
|
String embedded_data_prefix = Lit(Stringize(W32_EmbeddedDataPrefix));
|
||||||
if (StringBeginsWith(entry_name, embedded_data_prefix))
|
if (StringBeginsWith(entry_name, embedded_data_prefix))
|
||||||
|
{
|
||||||
|
HRSRC hres = FindResourceW(module, wstr_entry_name, type);
|
||||||
|
if (hres)
|
||||||
{
|
{
|
||||||
HRSRC hres = FindResourceW(module, wstr_entry_name, type);
|
HGLOBAL hg = LoadResource(module, hres);
|
||||||
if (hres)
|
if (hg)
|
||||||
|
{
|
||||||
|
if (ctx->embedded_strings_count < countof(ctx->embedded_strings))
|
||||||
{
|
{
|
||||||
HGLOBAL hg = LoadResource(module, hres);
|
String embedded = Zi;
|
||||||
if (hg)
|
embedded.len = SizeofResource(module, hres);
|
||||||
{
|
embedded.text = LockResource(hg);
|
||||||
if (ctx->embedded_strings_count < countof(ctx->embedded_strings))
|
ctx->embedded_strings[ctx->embedded_strings_count++] = embedded;
|
||||||
{
|
|
||||||
String embedded = Zi;
|
|
||||||
embedded.len = SizeofResource(module, hres);
|
|
||||||
embedded.text = LockResource(hg);
|
|
||||||
ctx->embedded_strings[ctx->embedded_strings_count++] = embedded;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Panic(Lit("Maximum number of embedded resource entries exceeded"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Panic(Lit("Maximum number of embedded resource entries exceeded"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
}
|
||||||
return 1;
|
EndScratch(scratch);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -40,141 +40,141 @@ BOOL W32_FindEmbeddedRcData(HMODULE module, LPCWSTR type, LPWSTR wstr_entry_name
|
|||||||
|
|
||||||
StringList GetRawCommandline(void)
|
StringList GetRawCommandline(void)
|
||||||
{
|
{
|
||||||
return W32.raw_command_line;
|
return W32.raw_command_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Echo(String msg)
|
void Echo(String msg)
|
||||||
{
|
{
|
||||||
HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
if (console_handle && console_handle != INVALID_HANDLE_VALUE)
|
if (console_handle && console_handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
||||||
}
|
}
|
||||||
else if (IsRunningInDebugger())
|
else if (IsRunningInDebugger())
|
||||||
{
|
{
|
||||||
char msg_cstr[16384];
|
char msg_cstr[16384];
|
||||||
u64 len = MinU64(countof(msg_cstr) - 1, msg.len);
|
u64 len = MinU64(countof(msg_cstr) - 1, msg.len);
|
||||||
CopyBytes(msg_cstr, msg.text, len);
|
CopyBytes(msg_cstr, msg.text, len);
|
||||||
msg_cstr[len] = 0;
|
msg_cstr[len] = 0;
|
||||||
OutputDebugStringA(msg_cstr);
|
OutputDebugStringA(msg_cstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 Panic(String msg)
|
b32 Panic(String msg)
|
||||||
{
|
{
|
||||||
LogPanic(msg);
|
LogPanic(msg);
|
||||||
char msg_cstr[4096];
|
char msg_cstr[4096];
|
||||||
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
|
CstrFromStringToBuff(StringFromFixedArray(msg_cstr), msg);
|
||||||
{
|
{
|
||||||
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
|
u32 mb_flags = MB_SETFOREGROUND | MB_ICONERROR;
|
||||||
MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);
|
MessageBoxExA(0, msg_cstr, "Fatal error", mb_flags, 0);
|
||||||
}
|
}
|
||||||
HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
if (console_handle != INVALID_HANDLE_VALUE)
|
if (console_handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
WriteFile(console_handle, msg.text, msg.len, 0, 0);
|
||||||
}
|
}
|
||||||
if (IsRunningInDebugger())
|
if (IsRunningInDebugger())
|
||||||
{
|
{
|
||||||
Assert(0);
|
Assert(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExitProcess(1);
|
ExitProcess(1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 IsRunningInDebugger(void)
|
b32 IsRunningInDebugger(void)
|
||||||
{
|
{
|
||||||
return IsDebuggerPresent();
|
return IsDebuggerPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 TimeNs(void)
|
i64 TimeNs(void)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER qpc;
|
LARGE_INTEGER qpc;
|
||||||
QueryPerformanceCounter(&qpc);
|
QueryPerformanceCounter(&qpc);
|
||||||
i64 result = (qpc.QuadPart - W32.timer_start_qpc) * W32.ns_per_qpc;
|
i64 result = (qpc.QuadPart - W32.timer_start_qpc) * W32.ns_per_qpc;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrueRand(String buffer)
|
void TrueRand(String buffer)
|
||||||
{
|
{
|
||||||
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CpuTopologyInfo GetCpuTopologyInfo(void)
|
CpuTopologyInfo GetCpuTopologyInfo(void)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
CpuTopologyInfo res = Zi;
|
CpuTopologyInfo res = Zi;
|
||||||
|
{
|
||||||
|
DWORD infos_buff_size = 0;
|
||||||
|
u8 *infos_buff = 0;
|
||||||
|
b32 ok = 0;
|
||||||
{
|
{
|
||||||
DWORD infos_buff_size = 0;
|
GetLogicalProcessorInformationEx(RelationProcessorCore, 0, &infos_buff_size);
|
||||||
u8 *infos_buff = 0;
|
infos_buff = PushStructsNoZero(scratch.arena, u8, infos_buff_size);
|
||||||
b32 ok = 0;
|
ok = GetLogicalProcessorInformationEx(RelationProcessorCore, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)infos_buff, &infos_buff_size);
|
||||||
{
|
|
||||||
GetLogicalProcessorInformationEx(RelationProcessorCore, 0, &infos_buff_size);
|
|
||||||
infos_buff = PushStructsNoZero(scratch.arena, u8, infos_buff_size);
|
|
||||||
ok = GetLogicalProcessorInformationEx(RelationProcessorCore, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)infos_buff, &infos_buff_size);
|
|
||||||
}
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
/* Determine max efficiency class */
|
|
||||||
i32 max_efficiency_class = 0;
|
|
||||||
{
|
|
||||||
DWORD pos = 0;
|
|
||||||
while (pos < infos_buff_size)
|
|
||||||
{
|
|
||||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos];
|
|
||||||
max_efficiency_class = MaxI32(max_efficiency_class, info->Processor.EfficiencyClass);
|
|
||||||
pos += info->Size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Generate physical core info */
|
|
||||||
{
|
|
||||||
DWORD pos = 0;
|
|
||||||
while (pos < infos_buff_size)
|
|
||||||
{
|
|
||||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos];
|
|
||||||
++res.num_physical_cores;
|
|
||||||
++res.num_logical_cores;
|
|
||||||
if (info->Processor.Flags & LTP_PC_SMT)
|
|
||||||
{
|
|
||||||
/* Core has SMT sibling */
|
|
||||||
++res.num_logical_cores;
|
|
||||||
}
|
|
||||||
if (info->Processor.EfficiencyClass == max_efficiency_class)
|
|
||||||
{
|
|
||||||
/* Core is P-core */
|
|
||||||
++res.num_physical_performance_cores;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Core is not a P-core */
|
|
||||||
++res.num_physical_non_performance_cores;
|
|
||||||
}
|
|
||||||
pos += info->Size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
res.num_logical_cores = MaxI32(res.num_logical_cores, 1);
|
if (ok)
|
||||||
res.num_physical_cores = MaxI32(res.num_physical_cores, 1);
|
{
|
||||||
res.num_physical_performance_cores = MaxI32(res.num_physical_performance_cores, 1);
|
/* Determine max efficiency class */
|
||||||
EndScratch(scratch);
|
i32 max_efficiency_class = 0;
|
||||||
return res;
|
{
|
||||||
|
DWORD pos = 0;
|
||||||
|
while (pos < infos_buff_size)
|
||||||
|
{
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos];
|
||||||
|
max_efficiency_class = MaxI32(max_efficiency_class, info->Processor.EfficiencyClass);
|
||||||
|
pos += info->Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Generate physical core info */
|
||||||
|
{
|
||||||
|
DWORD pos = 0;
|
||||||
|
while (pos < infos_buff_size)
|
||||||
|
{
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)&infos_buff[pos];
|
||||||
|
++res.num_physical_cores;
|
||||||
|
++res.num_logical_cores;
|
||||||
|
if (info->Processor.Flags & LTP_PC_SMT)
|
||||||
|
{
|
||||||
|
/* Core has SMT sibling */
|
||||||
|
++res.num_logical_cores;
|
||||||
|
}
|
||||||
|
if (info->Processor.EfficiencyClass == max_efficiency_class)
|
||||||
|
{
|
||||||
|
/* Core is P-core */
|
||||||
|
++res.num_physical_performance_cores;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Core is not a P-core */
|
||||||
|
++res.num_physical_non_performance_cores;
|
||||||
|
}
|
||||||
|
pos += info->Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.num_logical_cores = MaxI32(res.num_logical_cores, 1);
|
||||||
|
res.num_physical_cores = MaxI32(res.num_physical_cores, 1);
|
||||||
|
res.num_physical_performance_cores = MaxI32(res.num_physical_performance_cores, 1);
|
||||||
|
EndScratch(scratch);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SleepSeconds(f64 seconds)
|
void SleepSeconds(f64 seconds)
|
||||||
{
|
{
|
||||||
f64 ms = seconds * 1000.0;
|
f64 ms = seconds * 1000.0;
|
||||||
if (ms > 4000000000)
|
if (ms > 4000000000)
|
||||||
{
|
{
|
||||||
Sleep(INFINITE);
|
Sleep(INFINITE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Sleep((u32)ms);
|
Sleep((u32)ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -182,60 +182,60 @@ void SleepSeconds(f64 seconds)
|
|||||||
|
|
||||||
b32 IsSwappedIn(void)
|
b32 IsSwappedIn(void)
|
||||||
{
|
{
|
||||||
return IsHotSwappingEnabled;
|
return IsHotSwappingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 IsSwappingOut(void)
|
b32 IsSwappingOut(void)
|
||||||
{
|
{
|
||||||
return IsHotSwappingEnabled;
|
return IsHotSwappingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
String SwappedStateFromName(Arena *arena, String name)
|
String SwappedStateFromName(Arena *arena, String name)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
String path = StringF(scratch.arena, "ppswap/%F.swp", FmtString(name));
|
String path = StringF(scratch.arena, "ppswap/%F.swp", FmtString(name));
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (handle != INVALID_HANDLE_VALUE)
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
u32 chunk_size = Kibi(64);
|
||||||
|
result.text = ArenaNext(arena, u8);
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
u32 chunk_size = Kibi(64);
|
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
|
||||||
result.text = ArenaNext(arena, u8);
|
u32 chunk_bytes_read = 0;
|
||||||
for (;;)
|
ReadFile(handle, chunk, chunk_size, (LPDWORD)&chunk_bytes_read, 0);
|
||||||
{
|
result.len += chunk_bytes_read;
|
||||||
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
|
if (chunk_bytes_read < chunk_size)
|
||||||
u32 chunk_bytes_read = 0;
|
{
|
||||||
ReadFile(handle, chunk, chunk_size, (LPDWORD)&chunk_bytes_read, 0);
|
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
|
||||||
result.len += chunk_bytes_read;
|
break;
|
||||||
if (chunk_bytes_read < chunk_size)
|
}
|
||||||
{
|
|
||||||
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CloseHandle(handle);
|
}
|
||||||
EndScratch(scratch);
|
CloseHandle(handle);
|
||||||
return result;
|
EndScratch(scratch);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteSwappedState(String name, String data)
|
void WriteSwappedState(String name, String data)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
/* TODO: Use directory non-relative to executable */
|
/* TODO: Use directory non-relative to executable */
|
||||||
CreateDirectoryW(L"ppswap", 0);
|
CreateDirectoryW(L"ppswap", 0);
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
String path = StringF(scratch.arena, "ppswap/%F.swp", FmtString(name));
|
String path = StringF(scratch.arena, "ppswap/%F.swp", FmtString(name));
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (handle != INVALID_HANDLE_VALUE)
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
SetFilePointer(handle, 0, 0, FILE_BEGIN);
|
SetFilePointer(handle, 0, 0, FILE_BEGIN);
|
||||||
SetEndOfFile(handle);
|
SetEndOfFile(handle);
|
||||||
WriteFile(handle, data.text, data.len, 0, 0);
|
WriteFile(handle, data.text, data.len, 0, 0);
|
||||||
}
|
}
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -243,23 +243,23 @@ void WriteSwappedState(String name, String data)
|
|||||||
|
|
||||||
void OnExit(ExitFunc *func)
|
void OnExit(ExitFunc *func)
|
||||||
{
|
{
|
||||||
i32 index = Atomic32FetchAdd(&W32.num_exit_funcs, 1);
|
i32 index = Atomic32FetchAdd(&W32.num_exit_funcs, 1);
|
||||||
if (index >= countof(W32.exit_funcs))
|
if (index >= countof(W32.exit_funcs))
|
||||||
{
|
{
|
||||||
Panic(Lit("Maximum on exit functions registered"));
|
Panic(Lit("Maximum on exit functions registered"));
|
||||||
}
|
}
|
||||||
W32.exit_funcs[index] = func;
|
W32.exit_funcs[index] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalExit(i32 code)
|
void SignalExit(i32 code)
|
||||||
{
|
{
|
||||||
Atomic32Set(&W32.exit_code, code);
|
Atomic32Set(&W32.exit_code, code);
|
||||||
SetEvent(W32.exit_event);
|
SetEvent(W32.exit_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExitNow(i32 code)
|
void ExitNow(i32 code)
|
||||||
{
|
{
|
||||||
ExitProcess(code);
|
ExitProcess(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -267,88 +267,88 @@ void ExitNow(i32 code)
|
|||||||
|
|
||||||
void W32_BootstrapLogs(String logfile_path)
|
void W32_BootstrapLogs(String logfile_path)
|
||||||
{
|
{
|
||||||
W32.logs_arena = AcquireArena(Gibi(64));
|
W32.logs_arena = AcquireArena(Gibi(64));
|
||||||
W32.log_msgs_arena = AcquireArena(Gibi(64));
|
W32.log_msgs_arena = AcquireArena(Gibi(64));
|
||||||
W32.readable_log_events = ArenaNext(W32.logs_arena, LogEvent);
|
W32.readable_log_events = ArenaNext(W32.logs_arena, LogEvent);
|
||||||
if (logfile_path.len > 0)
|
if (logfile_path.len > 0)
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
wchar_t *path_wstr = WstrFromString(scratch.arena, logfile_path);
|
||||||
{
|
W32.logfile = CreateFileW(
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, logfile_path);
|
path_wstr,
|
||||||
W32.logfile = CreateFileW(
|
FILE_APPEND_DATA,
|
||||||
path_wstr,
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
FILE_APPEND_DATA,
|
0,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
CREATE_ALWAYS,
|
||||||
0,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
CREATE_ALWAYS,
|
0
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
);
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
Atomic32Set(&W32.logs_initialized, 1);
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
Atomic32Set(&W32.logs_initialized, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void W32_Log(i32 level, String msg)
|
void W32_Log(i32 level, String msg)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
if (Atomic32Fetch(&W32.logs_initialized))
|
if (Atomic32Fetch(&W32.logs_initialized))
|
||||||
|
{
|
||||||
|
LogLevelSettings settings = log_settings[level];
|
||||||
|
if (level < 0 || level >= LogLevel_Count)
|
||||||
{
|
{
|
||||||
LogLevelSettings settings = log_settings[level];
|
Panic(Lit("Invalid log level"));
|
||||||
if (level < 0 || level >= LogLevel_Count)
|
|
||||||
{
|
|
||||||
Panic(Lit("Invalid log level"));
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime datetime = LocalDateTime();
|
|
||||||
i64 now_ns = TimeNs();
|
|
||||||
i32 thread_id = GetCurrentThreadId();
|
|
||||||
|
|
||||||
//- Log message to file
|
|
||||||
/* TODO: Log asynchronously */
|
|
||||||
{
|
|
||||||
String shorthand = settings.shorthand;
|
|
||||||
String msg_formatted = StringF(
|
|
||||||
scratch.arena,
|
|
||||||
"[%F:%F:%F.%F] <%F> [%F] %F\n",
|
|
||||||
|
|
||||||
/* Time */
|
|
||||||
FmtUint(datetime.hour, .z = 2),
|
|
||||||
FmtUint(datetime.minute, .z = 2),
|
|
||||||
FmtUint(datetime.second, .z = 2),
|
|
||||||
FmtUint(datetime.milliseconds, .z = 3),
|
|
||||||
|
|
||||||
/* Thread id */
|
|
||||||
FmtUint(thread_id, .z = 5),
|
|
||||||
|
|
||||||
/* Level */
|
|
||||||
FmtString(shorthand),
|
|
||||||
|
|
||||||
/* Message */
|
|
||||||
FmtString(msg)
|
|
||||||
);
|
|
||||||
WriteFile(W32.logfile, msg_formatted.text, msg_formatted.len, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Log message to queue
|
|
||||||
/* TODO: Log asynchronously */
|
|
||||||
LockTicketMutex(&W32.logs_tm);
|
|
||||||
{
|
|
||||||
/* Get staged data */
|
|
||||||
LogEvent *ev = PushStruct(W32.logs_arena, LogEvent);
|
|
||||||
ev->msg = PushString(W32.log_msgs_arena, msg);
|
|
||||||
ev->datetime = datetime;
|
|
||||||
ev->time_ns = now_ns;
|
|
||||||
ev->level = level;
|
|
||||||
ev->thread_id = thread_id;
|
|
||||||
ev->id = W32.logs_count++;
|
|
||||||
ev->level_id = W32.log_level_counts[level]++;
|
|
||||||
Atomic64Set(&W32.readable_logs_count, W32.logs_count);
|
|
||||||
}
|
|
||||||
UnlockTicketMutex(&W32.logs_tm);
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
|
||||||
|
DateTime datetime = LocalDateTime();
|
||||||
|
i64 now_ns = TimeNs();
|
||||||
|
i32 thread_id = GetCurrentThreadId();
|
||||||
|
|
||||||
|
//- Log message to file
|
||||||
|
/* TODO: Log asynchronously */
|
||||||
|
{
|
||||||
|
String shorthand = settings.shorthand;
|
||||||
|
String msg_formatted = StringF(
|
||||||
|
scratch.arena,
|
||||||
|
"[%F:%F:%F.%F] <%F> [%F] %F\n",
|
||||||
|
|
||||||
|
/* Time */
|
||||||
|
FmtUint(datetime.hour, .z = 2),
|
||||||
|
FmtUint(datetime.minute, .z = 2),
|
||||||
|
FmtUint(datetime.second, .z = 2),
|
||||||
|
FmtUint(datetime.milliseconds, .z = 3),
|
||||||
|
|
||||||
|
/* Thread id */
|
||||||
|
FmtUint(thread_id, .z = 5),
|
||||||
|
|
||||||
|
/* Level */
|
||||||
|
FmtString(shorthand),
|
||||||
|
|
||||||
|
/* Message */
|
||||||
|
FmtString(msg)
|
||||||
|
);
|
||||||
|
WriteFile(W32.logfile, msg_formatted.text, msg_formatted.len, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Log message to queue
|
||||||
|
/* TODO: Log asynchronously */
|
||||||
|
LockTicketMutex(&W32.logs_tm);
|
||||||
|
{
|
||||||
|
/* Get staged data */
|
||||||
|
LogEvent *ev = PushStruct(W32.logs_arena, LogEvent);
|
||||||
|
ev->msg = PushString(W32.log_msgs_arena, msg);
|
||||||
|
ev->datetime = datetime;
|
||||||
|
ev->time_ns = now_ns;
|
||||||
|
ev->level = level;
|
||||||
|
ev->thread_id = thread_id;
|
||||||
|
ev->id = W32.logs_count++;
|
||||||
|
ev->level_id = W32.log_level_counts[level]++;
|
||||||
|
Atomic64Set(&W32.readable_logs_count, W32.logs_count);
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&W32.logs_tm);
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -358,46 +358,46 @@ void W32_Log(i32 level, String msg)
|
|||||||
* immediately writing to log file. */
|
* immediately writing to log file. */
|
||||||
void LogPanic(String msg)
|
void LogPanic(String msg)
|
||||||
{
|
{
|
||||||
if (Atomic32Fetch(&W32.logs_initialized))
|
if (Atomic32Fetch(&W32.logs_initialized))
|
||||||
{
|
{
|
||||||
String beg = Lit("******** PANICKING ********\n");
|
String beg = Lit("******** PANICKING ********\n");
|
||||||
String end = Lit("\n***************************\n");
|
String end = Lit("\n***************************\n");
|
||||||
WriteFile(W32.logfile, beg.text, beg.len, 0, 0);
|
WriteFile(W32.logfile, beg.text, beg.len, 0, 0);
|
||||||
WriteFile(W32.logfile, msg.text, msg.len, 0, 0);
|
WriteFile(W32.logfile, msg.text, msg.len, 0, 0);
|
||||||
WriteFile(W32.logfile, end.text, end.len, 0, 0);
|
WriteFile(W32.logfile, end.text, end.len, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log_(i32 level, String msg)
|
void Log_(i32 level, String msg)
|
||||||
{
|
{
|
||||||
W32_Log(level, msg);
|
W32_Log(level, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogF_(i32 level, String fmt, ...)
|
void LogF_(i32 level, String fmt, ...)
|
||||||
{
|
{
|
||||||
if (Atomic32Fetch(&W32.logs_initialized))
|
if (Atomic32Fetch(&W32.logs_initialized))
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
String msg = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args));
|
||||||
va_list args;
|
W32_Log(level, msg);
|
||||||
va_start(args, fmt);
|
|
||||||
{
|
|
||||||
String msg = FormatString(scratch.arena, fmt, FmtArgsFromVaList(scratch.arena, args));
|
|
||||||
W32_Log(level, msg);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
|
va_end(args);
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogEventsArray GetLogEvents(void)
|
LogEventsArray GetLogEvents(void)
|
||||||
{
|
{
|
||||||
LogEventsArray result = Zi;
|
LogEventsArray result = Zi;
|
||||||
result.count = Atomic64Fetch(&W32.readable_logs_count);
|
result.count = Atomic64Fetch(&W32.readable_logs_count);
|
||||||
if (result.count > 0)
|
if (result.count > 0)
|
||||||
{
|
{
|
||||||
result.logs = W32.readable_log_events;
|
result.logs = W32.readable_log_events;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -405,150 +405,148 @@ LogEventsArray GetLogEvents(void)
|
|||||||
|
|
||||||
i32 W32_Main(void)
|
i32 W32_Main(void)
|
||||||
{
|
{
|
||||||
/* Init time */
|
/* Init time */
|
||||||
|
{
|
||||||
|
LARGE_INTEGER qpf;
|
||||||
|
QueryPerformanceFrequency(&qpf);
|
||||||
|
W32.ns_per_qpc = 1000000000 / qpf.QuadPart;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LARGE_INTEGER qpc;
|
||||||
|
QueryPerformanceCounter(&qpc);
|
||||||
|
W32.timer_start_qpc = qpc.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup events */
|
||||||
|
W32.panic_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
W32.exit_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
|
||||||
|
W32.main_thread_id = GetCurrentThreadId();
|
||||||
|
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||||
|
|
||||||
|
/* Query system info */
|
||||||
|
GetSystemInfo(&W32.info);
|
||||||
|
|
||||||
|
/* Init main thread */
|
||||||
|
W32_InitCurrentThread(Lit("Main"));
|
||||||
|
|
||||||
|
/* Get raw args from command line */
|
||||||
|
{
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
StringList args_list = Zi;
|
||||||
{
|
{
|
||||||
LARGE_INTEGER qpf;
|
LPCWSTR cmdline_wstr = GetCommandLineW();
|
||||||
QueryPerformanceFrequency(&qpf);
|
i32 argc = 0;
|
||||||
W32.ns_per_qpc = 1000000000 / qpf.QuadPart;
|
LPWSTR *argv = CommandLineToArgvW(cmdline_wstr, &argc);
|
||||||
|
for (i32 i = 0; i < argc; ++i)
|
||||||
|
{
|
||||||
|
wchar_t *arg_wstr = argv[i];
|
||||||
|
String arg = StringFromWstrNoLimit(perm, arg_wstr);
|
||||||
|
PushStringToList(perm, &args_list, arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
W32.raw_command_line = args_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Bootstrap
|
||||||
|
|
||||||
|
/* Bootstrap command line */
|
||||||
|
BootstrapCmdline();
|
||||||
|
|
||||||
|
/* Bootstrap log system */
|
||||||
|
/* FIXME: Remove hardcoded log path */
|
||||||
|
W32_BootstrapLogs(Lit("log.log"));
|
||||||
|
LogInfoF("Main thread ID: %F", FmtUint(ThreadId()));
|
||||||
|
|
||||||
|
/* Bootstrap resource system */
|
||||||
|
{
|
||||||
|
W32_FindEmbeddedDataCtx ctx = Zi;
|
||||||
|
EnumResourceNamesW(0, RT_RCDATA, &W32_FindEmbeddedRcData, (LONG_PTR)&ctx);
|
||||||
|
BootstrapResources(ctx.embedded_strings_count, ctx.embedded_strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bootstrap async */
|
||||||
|
BootstrapAsync();
|
||||||
|
|
||||||
|
/* Bootstrap layers */
|
||||||
|
if (!Atomic32Fetch(&W32.panicking))
|
||||||
|
{
|
||||||
|
BootstrapLayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Wait for exit signal
|
||||||
|
|
||||||
|
/* Wait for exit start or panic */
|
||||||
|
if (!Atomic32Fetch(&W32.panicking))
|
||||||
|
{
|
||||||
|
HANDLE handles[] = {
|
||||||
|
W32.exit_event,
|
||||||
|
W32.panic_event,
|
||||||
|
};
|
||||||
|
DWORD wake = WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Shutdown
|
||||||
|
|
||||||
|
/* Run exit callbacks */
|
||||||
|
if (!Atomic32Fetch(&W32.panicking))
|
||||||
|
{
|
||||||
|
i32 num_funcs = Atomic32Fetch(&W32.num_exit_funcs);
|
||||||
|
for (i32 idx = num_funcs - 1; idx >= 0; --idx)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER qpc;
|
ExitFunc *func = W32.exit_funcs[idx];
|
||||||
QueryPerformanceCounter(&qpc);
|
func();
|
||||||
W32.timer_start_qpc = qpc.QuadPart;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup events */
|
/* Exit */
|
||||||
W32.panic_event = CreateEventW(0, 1, 0, 0);
|
if (Atomic32Fetch(&W32.panicking))
|
||||||
W32.exit_event = CreateEventW(0, 1, 0, 0);
|
{
|
||||||
|
WaitForSingleObject(W32.panic_event, INFINITE);
|
||||||
W32.main_thread_id = GetCurrentThreadId();
|
MessageBoxExW(0, W32.panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
||||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
Atomic32FetchTestSet(&W32.exit_code, 0, 1);
|
||||||
|
}
|
||||||
/* Query system info */
|
return Atomic32Fetch(&W32.exit_code);
|
||||||
GetSystemInfo(&W32.info);
|
|
||||||
|
|
||||||
/* Init main thread */
|
|
||||||
W32_InitCurrentThread(Lit("Main"));
|
|
||||||
|
|
||||||
/* Get raw args from command line */
|
|
||||||
{
|
|
||||||
Arena *perm = PermArena();
|
|
||||||
StringList args_list = Zi;
|
|
||||||
{
|
|
||||||
LPCWSTR cmdline_wstr = GetCommandLineW();
|
|
||||||
i32 argc = 0;
|
|
||||||
LPWSTR *argv = CommandLineToArgvW(cmdline_wstr, &argc);
|
|
||||||
for (i32 i = 0; i < argc; ++i)
|
|
||||||
{
|
|
||||||
wchar_t *arg_wstr = argv[i];
|
|
||||||
String arg = StringFromWstrNoLimit(perm, arg_wstr);
|
|
||||||
PushStringToList(perm, &args_list, arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
W32.raw_command_line = args_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Bootstrap
|
|
||||||
|
|
||||||
/* Bootstrap command line */
|
|
||||||
BootstrapCmdline();
|
|
||||||
|
|
||||||
/* Bootstrap log system */
|
|
||||||
/* FIXME: Remove hardcoded log path */
|
|
||||||
W32_BootstrapLogs(Lit("log.log"));
|
|
||||||
LogInfoF("Main thread ID: %F", FmtUint(ThreadId()));
|
|
||||||
|
|
||||||
/* Bootstrap resource system */
|
|
||||||
{
|
|
||||||
W32_FindEmbeddedDataCtx ctx = Zi;
|
|
||||||
EnumResourceNamesW(0, RT_RCDATA, &W32_FindEmbeddedRcData, (LONG_PTR)&ctx);
|
|
||||||
BootstrapResources(ctx.embedded_strings_count, ctx.embedded_strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bootstrap async */
|
|
||||||
BootstrapAsync();
|
|
||||||
|
|
||||||
/* Bootstrap layers */
|
|
||||||
if (!Atomic32Fetch(&W32.panicking))
|
|
||||||
{
|
|
||||||
BootstrapLayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Wait for exit signal
|
|
||||||
|
|
||||||
/* Wait for exit start or panic */
|
|
||||||
if (!Atomic32Fetch(&W32.panicking))
|
|
||||||
{
|
|
||||||
HANDLE handles[] = {
|
|
||||||
W32.exit_event,
|
|
||||||
W32.panic_event,
|
|
||||||
};
|
|
||||||
DWORD wake = WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Shutdown
|
|
||||||
|
|
||||||
/* Run exit callbacks */
|
|
||||||
if (!Atomic32Fetch(&W32.panicking))
|
|
||||||
{
|
|
||||||
i32 num_funcs = Atomic32Fetch(&W32.num_exit_funcs);
|
|
||||||
for (i32 idx = num_funcs - 1; idx >= 0; --idx)
|
|
||||||
{
|
|
||||||
ExitFunc *func = W32.exit_funcs[idx];
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit */
|
|
||||||
if (Atomic32Fetch(&W32.panicking))
|
|
||||||
{
|
|
||||||
WaitForSingleObject(W32.panic_event, INFINITE);
|
|
||||||
MessageBoxExW(0, W32.panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
|
||||||
Atomic32FetchTestSet(&W32.exit_code, 0, 1);
|
|
||||||
}
|
|
||||||
return Atomic32Fetch(&W32.exit_code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Crt main
|
//~ Crt main
|
||||||
|
|
||||||
#if IsCrtlibEnabled
|
#if IsCrtlibEnabled
|
||||||
# if IsConsoleApp
|
#if IsConsoleApp
|
||||||
int main(char **argc, int argv)
|
int main(char **argc, int argv)
|
||||||
{
|
{
|
||||||
return W32_Main();
|
return W32_Main();
|
||||||
}
|
}
|
||||||
# else
|
#else
|
||||||
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
|
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
|
||||||
{
|
{
|
||||||
return W32_Main();
|
return W32_Main();
|
||||||
}
|
}
|
||||||
# endif /* IsConsoleApp */
|
#endif /* IsConsoleApp */
|
||||||
#endif /* IsCrtlibEnabled */
|
#endif /* IsCrtlibEnabled */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Crt stub
|
//~ Crt stub
|
||||||
|
|
||||||
#if !IsCrtlibEnabled
|
#if !IsCrtlibEnabled
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
/* Enable floating point */
|
||||||
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
__attribute((used))
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
int _fltused;
|
||||||
|
|
||||||
/* Enable floating point */
|
__attribute((used))
|
||||||
__attribute((used))
|
void __stdcall wWinMainCRTStartup(void)
|
||||||
int _fltused;
|
{
|
||||||
|
|
||||||
__attribute((used))
|
|
||||||
void __stdcall wWinMainCRTStartup(void)
|
|
||||||
{
|
|
||||||
i32 result = W32_Main();
|
i32 result = W32_Main();
|
||||||
ExitProcess(result);
|
ExitProcess(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
#endif /* !IsCrtlibEnabled */
|
#endif /* !IsCrtlibEnabled */
|
||||||
|
|||||||
@ -7,28 +7,28 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <combaseapi.h>
|
#include <combaseapi.h>
|
||||||
#include <dcommon.h>
|
#include <dcommon.h>
|
||||||
#include <initguid.h>
|
#include <initguid.h>
|
||||||
#include <unknwn.h>
|
#include <unknwn.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <uuids.h>
|
#include <uuids.h>
|
||||||
#include <Knownfolders.h>
|
#include <Knownfolders.h>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
#include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
#include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <ShlObj_core.h>
|
#include <ShlObj_core.h>
|
||||||
#include <fileapi.h>
|
#include <fileapi.h>
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
#include <avrt.h>
|
#include <avrt.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#ifndef BCRYPT_RNG_ALG_HANDLE
|
#ifndef BCRYPT_RNG_ALG_HANDLE
|
||||||
#define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
#define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
||||||
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- Windows libs
|
//- Windows libs
|
||||||
@ -49,8 +49,8 @@ u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
|||||||
|
|
||||||
Struct(W32_FindEmbeddedDataCtx)
|
Struct(W32_FindEmbeddedDataCtx)
|
||||||
{
|
{
|
||||||
u64 embedded_strings_count;
|
u64 embedded_strings_count;
|
||||||
String embedded_strings[64];
|
String embedded_strings[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -58,41 +58,41 @@ Struct(W32_FindEmbeddedDataCtx)
|
|||||||
|
|
||||||
Struct(W32_Ctx)
|
Struct(W32_Ctx)
|
||||||
{
|
{
|
||||||
SYSTEM_INFO info;
|
SYSTEM_INFO info;
|
||||||
u32 main_thread_id;
|
u32 main_thread_id;
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
Atomic32 exit_code;
|
Atomic32 exit_code;
|
||||||
|
|
||||||
i64 timer_start_qpc;
|
i64 timer_start_qpc;
|
||||||
i64 ns_per_qpc;
|
i64 ns_per_qpc;
|
||||||
|
|
||||||
StringList raw_command_line;
|
StringList raw_command_line;
|
||||||
|
|
||||||
//- Application control flow
|
//- Application control flow
|
||||||
|
|
||||||
Atomic32 panicking;
|
Atomic32 panicking;
|
||||||
wchar_t panic_wstr[4096];
|
wchar_t panic_wstr[4096];
|
||||||
HANDLE panic_event;
|
HANDLE panic_event;
|
||||||
HANDLE exit_event;
|
HANDLE exit_event;
|
||||||
|
|
||||||
//- Exit funcs
|
//- Exit funcs
|
||||||
|
|
||||||
Atomic32 num_exit_funcs;
|
Atomic32 num_exit_funcs;
|
||||||
ExitFunc *exit_funcs[4096];
|
ExitFunc *exit_funcs[4096];
|
||||||
|
|
||||||
//- Logs
|
//- Logs
|
||||||
|
|
||||||
HANDLE logfile;
|
HANDLE logfile;
|
||||||
Atomic32 logs_initialized;
|
Atomic32 logs_initialized;
|
||||||
|
|
||||||
TicketMutex logs_tm;
|
TicketMutex logs_tm;
|
||||||
Arena *log_msgs_arena;
|
Arena *log_msgs_arena;
|
||||||
Arena *logs_arena;
|
Arena *logs_arena;
|
||||||
|
|
||||||
u64 logs_count;
|
u64 logs_count;
|
||||||
u64 log_level_counts[LogLevel_Count];
|
u64 log_level_counts[LogLevel_Count];
|
||||||
LogEvent *readable_log_events;
|
LogEvent *readable_log_events;
|
||||||
Atomic64 readable_logs_count;
|
Atomic64 readable_logs_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern W32_Ctx W32;
|
extern W32_Ctx W32;
|
||||||
|
|||||||
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
void FutexYieldNeq(volatile void *addr, void *cmp, u8 cmp_size)
|
void FutexYieldNeq(volatile void *addr, void *cmp, u8 cmp_size)
|
||||||
{
|
{
|
||||||
WaitOnAddress(addr, cmp, cmp_size, INFINITE);
|
WaitOnAddress(addr, cmp, cmp_size, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FutexWakeNeq(void *addr)
|
void FutexWakeNeq(void *addr)
|
||||||
{
|
{
|
||||||
WakeByAddressAll(addr);
|
WakeByAddressAll(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -16,12 +16,12 @@ void FutexWakeNeq(void *addr)
|
|||||||
|
|
||||||
void FutexYieldGte(volatile void *addr, void *cmp, u8 cmp_size)
|
void FutexYieldGte(volatile void *addr, void *cmp, u8 cmp_size)
|
||||||
{
|
{
|
||||||
/* TODO: Actually implement this. Just emulating via neq for now. */
|
/* TODO: Actually implement this. Just emulating via neq for now. */
|
||||||
FutexYieldNeq(addr, cmp, cmp_size);
|
FutexYieldNeq(addr, cmp, cmp_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FutexWakeGte(void *addr)
|
void FutexWakeGte(void *addr)
|
||||||
{
|
{
|
||||||
/* TODO: Actually implement this. Just emulating via neq for now. */
|
/* TODO: Actually implement this. Just emulating via neq for now. */
|
||||||
FutexWakeNeq(addr);
|
FutexWakeNeq(addr);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,38 +5,38 @@
|
|||||||
|
|
||||||
void *ReserveMemory(u64 size)
|
void *ReserveMemory(u64 size)
|
||||||
{
|
{
|
||||||
void *ptr = VirtualAlloc(0, size, MEM_RESERVE, PAGE_NOACCESS);
|
void *ptr = VirtualAlloc(0, size, MEM_RESERVE, PAGE_NOACCESS);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseMemory(void *address)
|
void ReleaseMemory(void *address)
|
||||||
{
|
{
|
||||||
VirtualFree(address, 0, MEM_RELEASE);
|
VirtualFree(address, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Commit
|
//- Commit
|
||||||
|
|
||||||
void *CommitMemory(void *address, u64 size)
|
void *CommitMemory(void *address, u64 size)
|
||||||
{
|
{
|
||||||
void *ptr = VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE);
|
void *ptr = VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecommitMemory(void *address, u64 size)
|
void DecommitMemory(void *address, u64 size)
|
||||||
{
|
{
|
||||||
VirtualFree(address, size, MEM_DECOMMIT);
|
VirtualFree(address, size, MEM_DECOMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Protect
|
//- Protect
|
||||||
|
|
||||||
void SetMemoryReadonly(void *address, u64 size)
|
void SetMemoryReadonly(void *address, u64 size)
|
||||||
{
|
{
|
||||||
DWORD old;
|
DWORD old;
|
||||||
VirtualProtect(address, size, PAGE_READONLY, &old);
|
VirtualProtect(address, size, PAGE_READONLY, &old);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMemoryReadWrite(void *address, u64 size)
|
void SetMemoryReadWrite(void *address, u64 size)
|
||||||
{
|
{
|
||||||
DWORD old;
|
DWORD old;
|
||||||
VirtualProtect(address, size, PAGE_READWRITE, &old);
|
VirtualProtect(address, size, PAGE_READWRITE, &old);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,18 +3,18 @@
|
|||||||
|
|
||||||
DateTime LocalDateTime(void)
|
DateTime LocalDateTime(void)
|
||||||
{
|
{
|
||||||
DateTime result = Zi;
|
DateTime result = Zi;
|
||||||
{
|
{
|
||||||
SYSTEMTIME lt;
|
SYSTEMTIME lt;
|
||||||
GetLocalTime(<);
|
GetLocalTime(<);
|
||||||
result.year = lt.wYear;
|
result.year = lt.wYear;
|
||||||
result.month = lt.wMonth;
|
result.month = lt.wMonth;
|
||||||
result.day_of_week = lt.wDayOfWeek;
|
result.day_of_week = lt.wDayOfWeek;
|
||||||
result.day = lt.wDay;
|
result.day = lt.wDay;
|
||||||
result.hour = lt.wHour;
|
result.hour = lt.wHour;
|
||||||
result.minute = lt.wMinute;
|
result.minute = lt.wMinute;
|
||||||
result.second = lt.wSecond;
|
result.second = lt.wSecond;
|
||||||
result.milliseconds = lt.wMilliseconds;
|
result.milliseconds = lt.wMilliseconds;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
void W32_InitCurrentThread(String name)
|
void W32_InitCurrentThread(String name)
|
||||||
{
|
{
|
||||||
/* Init thread arenas */
|
/* Init thread arenas */
|
||||||
|
{
|
||||||
|
Base_tl.arenas.perm = AcquireArena(Gibi(64));
|
||||||
|
for (i32 i = 0; i < (i32)countof(Base_tl.arenas.scratch); ++i)
|
||||||
{
|
{
|
||||||
Base_tl.arenas.perm = AcquireArena(Gibi(64));
|
Base_tl.arenas.scratch[i] = AcquireArena(Gibi(64));
|
||||||
for (i32 i = 0; i < (i32)countof(Base_tl.arenas.scratch); ++i)
|
|
||||||
{
|
|
||||||
Base_tl.arenas.scratch[i] = AcquireArena(Gibi(64));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Arena *perm = PermArena();
|
}
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
/* Set thread name */
|
/* Set thread name */
|
||||||
wchar_t *thread_name_wstr = WstrFromString(perm, name);
|
wchar_t *thread_name_wstr = WstrFromString(perm, name);
|
||||||
SetThreadDescription(GetCurrentThread(), thread_name_wstr);
|
SetThreadDescription(GetCurrentThread(), thread_name_wstr);
|
||||||
|
|
||||||
/* Initialize COM */
|
/* Initialize COM */
|
||||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp)
|
DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp)
|
||||||
{
|
{
|
||||||
W32_ThreadArgs *thread_args = (W32_ThreadArgs *)thread_args_vp;
|
W32_ThreadArgs *thread_args = (W32_ThreadArgs *)thread_args_vp;
|
||||||
W32_InitCurrentThread(thread_args->name);
|
W32_InitCurrentThread(thread_args->name);
|
||||||
LogInfoF("New thread \"%F\" created with ID %F", FmtString(thread_args->name), FmtUint(ThreadId()));
|
LogInfoF("New thread \"%F\" created with ID %F", FmtString(thread_args->name), FmtUint(ThreadId()));
|
||||||
thread_args->entry(thread_args->lane);
|
thread_args->entry(thread_args->lane);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -35,58 +35,58 @@ DWORD WINAPI W32_ThreadProc(LPVOID thread_args_vp)
|
|||||||
|
|
||||||
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata)
|
void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *udata)
|
||||||
{
|
{
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
PERSIST Atomic64 num_threads_allocated = Zi;
|
PERSIST Atomic64 num_threads_allocated = Zi;
|
||||||
|
|
||||||
/* Catch high lane count to prevent OS crash */
|
/* Catch high lane count to prevent OS crash */
|
||||||
i64 old_num_threads_allocated = Atomic64FetchAdd(&num_threads_allocated, num_lanes);
|
i64 old_num_threads_allocated = Atomic64FetchAdd(&num_threads_allocated, num_lanes);
|
||||||
i64 new_num_threads_allocated = old_num_threads_allocated + num_lanes;
|
i64 new_num_threads_allocated = old_num_threads_allocated + num_lanes;
|
||||||
if (new_num_threads_allocated > MaxThreads)
|
if (new_num_threads_allocated > MaxThreads)
|
||||||
|
{
|
||||||
|
if (old_num_threads_allocated < MaxThreads)
|
||||||
{
|
{
|
||||||
if (old_num_threads_allocated < MaxThreads)
|
Panic(StringF(perm, "Maximum number of threads reached (%F)", FmtUint(MaxThreads)));
|
||||||
{
|
}
|
||||||
Panic(StringF(perm, "Maximum number of threads reached (%F)", FmtUint(MaxThreads)));
|
else
|
||||||
}
|
{
|
||||||
else
|
/* Sleep until panic */
|
||||||
{
|
Sleep(INFINITE);
|
||||||
/* Sleep until panic */
|
}
|
||||||
Sleep(INFINITE);
|
}
|
||||||
}
|
|
||||||
|
WaveCtx *wave_ctx = PushStruct(perm, WaveCtx);
|
||||||
|
wave_ctx->lanes_count = num_lanes;
|
||||||
|
wave_ctx->udata = udata;
|
||||||
|
|
||||||
|
for (u32 lane_idx = 0; lane_idx < num_lanes; ++lane_idx)
|
||||||
|
{
|
||||||
|
WaveLaneCtx *lane_ctx = PushStruct(perm, WaveLaneCtx);
|
||||||
|
lane_ctx->idx = lane_idx;
|
||||||
|
lane_ctx->wave = wave_ctx;
|
||||||
|
lane_ctx->default_spin_count = DefaultWaveLaneSpinCount;
|
||||||
|
|
||||||
|
String thread_name = Zi;
|
||||||
|
if (num_lanes > 1)
|
||||||
|
{
|
||||||
|
thread_name = StringF(perm, "%F:%F", FmtString(name), FmtUint(lane_idx));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread_name = PushString(perm, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
WaveCtx *wave_ctx = PushStruct(perm, WaveCtx);
|
W32_ThreadArgs *thread_args = PushStruct(perm, W32_ThreadArgs);
|
||||||
wave_ctx->lanes_count = num_lanes;
|
thread_args->lane = lane_ctx;
|
||||||
wave_ctx->udata = udata;
|
thread_args->udata = udata;
|
||||||
|
thread_args->entry = entry;
|
||||||
|
thread_args->name = thread_name;
|
||||||
|
|
||||||
for (u32 lane_idx = 0; lane_idx < num_lanes; ++lane_idx)
|
HANDLE handle = CreateThread(0, Mebi(4), W32_ThreadProc, thread_args, 0, 0);
|
||||||
|
if (!handle)
|
||||||
{
|
{
|
||||||
WaveLaneCtx *lane_ctx = PushStruct(perm, WaveLaneCtx);
|
Panic(Lit("Failed to create thread"));
|
||||||
lane_ctx->idx = lane_idx;
|
|
||||||
lane_ctx->wave = wave_ctx;
|
|
||||||
lane_ctx->default_spin_count = DefaultWaveLaneSpinCount;
|
|
||||||
|
|
||||||
String thread_name = Zi;
|
|
||||||
if (num_lanes > 1)
|
|
||||||
{
|
|
||||||
thread_name = StringF(perm, "%F:%F", FmtString(name), FmtUint(lane_idx));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thread_name = PushString(perm, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
W32_ThreadArgs *thread_args = PushStruct(perm, W32_ThreadArgs);
|
|
||||||
thread_args->lane = lane_ctx;
|
|
||||||
thread_args->udata = udata;
|
|
||||||
thread_args->entry = entry;
|
|
||||||
thread_args->name = thread_name;
|
|
||||||
|
|
||||||
HANDLE handle = CreateThread(0, Mebi(4), W32_ThreadProc, thread_args, 0, 0);
|
|
||||||
if (!handle)
|
|
||||||
{
|
|
||||||
Panic(Lit("Failed to create thread"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -94,5 +94,5 @@ void DispatchWave(String name, u32 num_lanes, WaveLaneEntryFunc *entry, void *ud
|
|||||||
|
|
||||||
i32 ThreadId(void)
|
i32 ThreadId(void)
|
||||||
{
|
{
|
||||||
return GetCurrentThreadId();
|
return GetCurrentThreadId();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
Struct(W32_ThreadArgs)
|
Struct(W32_ThreadArgs)
|
||||||
{
|
{
|
||||||
void *udata;
|
void *udata;
|
||||||
WaveLaneCtx *lane;
|
WaveLaneCtx *lane;
|
||||||
WaveLaneEntryFunc *entry;
|
WaveLaneEntryFunc *entry;
|
||||||
String name;
|
String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
Struct(CLD_Shape)
|
Struct(CLD_Shape)
|
||||||
{
|
{
|
||||||
Vec2 points[8];
|
Vec2 points[8];
|
||||||
u32 count;
|
u32 count;
|
||||||
f32 radius;
|
f32 radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -25,27 +25,27 @@ Struct(CLD_Shape)
|
|||||||
|
|
||||||
Struct(CLD_SupportPoint)
|
Struct(CLD_SupportPoint)
|
||||||
{
|
{
|
||||||
Vec2 p;
|
Vec2 p;
|
||||||
u32 i; /* Index of original point in shape */
|
u32 i; /* Index of original point in shape */
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_MenkowskiPoint)
|
Struct(CLD_MenkowskiPoint)
|
||||||
{
|
{
|
||||||
Vec2 p; /* Menkowski difference point */
|
Vec2 p; /* Menkowski difference point */
|
||||||
CLD_SupportPoint s0; /* Support point of first shape in dir */
|
CLD_SupportPoint s0; /* Support point of first shape in dir */
|
||||||
CLD_SupportPoint s1; /* Support point of second shape in -dir */
|
CLD_SupportPoint s1; /* Support point of second shape in -dir */
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_MenkowskiSimplex)
|
Struct(CLD_MenkowskiSimplex)
|
||||||
{
|
{
|
||||||
u32 len;
|
u32 len;
|
||||||
CLD_MenkowskiPoint a, b, c;
|
CLD_MenkowskiPoint a, b, c;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_MenkowskiFeature)
|
Struct(CLD_MenkowskiFeature)
|
||||||
{
|
{
|
||||||
u32 len;
|
u32 len;
|
||||||
CLD_MenkowskiPoint a, b;
|
CLD_MenkowskiPoint a, b;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -53,42 +53,42 @@ Struct(CLD_MenkowskiFeature)
|
|||||||
|
|
||||||
Struct(CLD_CollisionPoint)
|
Struct(CLD_CollisionPoint)
|
||||||
{
|
{
|
||||||
Vec2 point;
|
Vec2 point;
|
||||||
f32 separation;
|
f32 separation;
|
||||||
u32 id; /* Based on polygon edge-to-edge */
|
u32 id; /* Based on polygon edge-to-edge */
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_Prototype)
|
Struct(CLD_Prototype)
|
||||||
{
|
{
|
||||||
Vec2 points[64];
|
Vec2 points[64];
|
||||||
u32 len;
|
u32 len;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_CollisionData)
|
Struct(CLD_CollisionData)
|
||||||
{
|
{
|
||||||
Vec2 normal;
|
Vec2 normal;
|
||||||
CLD_CollisionPoint points[2];
|
CLD_CollisionPoint points[2];
|
||||||
u32 num_points;
|
u32 num_points;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
b32 solved;
|
b32 solved;
|
||||||
CLD_MenkowskiSimplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
CLD_Prototype prototype;
|
CLD_Prototype prototype;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
Vec2 a0, b0, a1, b1;
|
Vec2 a0, b0, a1, b1;
|
||||||
Vec2 a0_clipped, b0_clipped, a1_clipped, b1_clipped;
|
Vec2 a0_clipped, b0_clipped, a1_clipped, b1_clipped;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(CLD_ClosestPointData)
|
Struct(CLD_ClosestPointData)
|
||||||
{
|
{
|
||||||
Vec2 p0, p1;
|
Vec2 p0, p1;
|
||||||
b32 colliding;
|
b32 colliding;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
b32 solved;
|
b32 solved;
|
||||||
CLD_MenkowskiSimplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
CLD_Prototype prototype;
|
CLD_Prototype prototype;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -96,8 +96,8 @@ Struct(CLD_ClosestPointData)
|
|||||||
|
|
||||||
Struct(CLD_ClippedLine)
|
Struct(CLD_ClippedLine)
|
||||||
{
|
{
|
||||||
Vec2 a0_clipped, b0_clipped;
|
Vec2 a0_clipped, b0_clipped;
|
||||||
Vec2 a1_clipped, b1_clipped;
|
Vec2 a1_clipped, b1_clipped;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -105,16 +105,16 @@ Struct(CLD_ClippedLine)
|
|||||||
|
|
||||||
Struct(CLD_GjkData)
|
Struct(CLD_GjkData)
|
||||||
{
|
{
|
||||||
CLD_MenkowskiSimplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
Vec2 final_dir;
|
Vec2 final_dir;
|
||||||
|
|
||||||
/* If 1, simplex represents triangle inside of CLD_Menkowski difference
|
/* If 1, simplex represents triangle inside of CLD_Menkowski difference
|
||||||
* encapsulating the origin. If 0, simplex represents the closest
|
* encapsulating the origin. If 0, simplex represents the closest
|
||||||
* feature on CLD_Menkowski difference to the origin. */
|
* feature on CLD_Menkowski difference to the origin. */
|
||||||
b32 overlapping;
|
b32 overlapping;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
u32 dbg_step;
|
u32 dbg_step;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,12 +123,12 @@ Struct(CLD_GjkData)
|
|||||||
|
|
||||||
Struct(CLD_EpaData)
|
Struct(CLD_EpaData)
|
||||||
{
|
{
|
||||||
Vec2 normal;
|
Vec2 normal;
|
||||||
CLD_MenkowskiFeature closest_feature; /* Represents closest feature (edge or point) to origin on CLD_Menkowski difference */
|
CLD_MenkowskiFeature closest_feature; /* Represents closest feature (edge or point) to origin on CLD_Menkowski difference */
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
CLD_Prototype prototype;
|
CLD_Prototype prototype;
|
||||||
u32 dbg_step;
|
u32 dbg_step;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,17 +139,17 @@ Struct(CLD_EpaData)
|
|||||||
void CLD_DebugBreakable(void);
|
void CLD_DebugBreakable(void);
|
||||||
|
|
||||||
#define CLD_DBGSTEP \
|
#define CLD_DBGSTEP \
|
||||||
dbg_step++; \
|
dbg_step++; \
|
||||||
if (dbg_step >= GetGstat(DebugSteps)) \
|
if (dbg_step >= GetGstat(DebugSteps)) \
|
||||||
{ \
|
{ \
|
||||||
goto abort; \
|
goto abort; \
|
||||||
} \
|
} \
|
||||||
else if (dbg_step >= GetGstat(DebugSteps) - 1) \
|
else if (dbg_step >= GetGstat(DebugSteps) - 1) \
|
||||||
{ \
|
{ \
|
||||||
CLD_DebugBreakable(); \
|
CLD_DebugBreakable(); \
|
||||||
} (void)0
|
} (void)0
|
||||||
#else
|
#else
|
||||||
#define CLD_DBGSTEP
|
#define CLD_DBGSTEP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
30
src/config.h
30
src/config.h
@ -4,17 +4,17 @@
|
|||||||
|
|
||||||
/* Window title */
|
/* Window title */
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
# if IsDeveloperModeEnabled
|
#if IsDeveloperModeEnabled
|
||||||
# define WINDOW_TITLE "Debug (Developer Build)"
|
#define WINDOW_TITLE "Debug (Developer Build)"
|
||||||
# else
|
#else
|
||||||
# define WINDOW_TITLE "Debug"
|
#define WINDOW_TITLE "Debug"
|
||||||
# endif
|
#endif
|
||||||
#else
|
#else
|
||||||
# if IsDeveloperModeEnabled
|
#if IsDeveloperModeEnabled
|
||||||
# define WINDOW_TITLE "Power Play (Developer Build)"
|
#define WINDOW_TITLE "Power Play (Developer Build)"
|
||||||
# else
|
#else
|
||||||
# define WINDOW_TITLE "Power Play"
|
#define WINDOW_TITLE "Power Play"
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_CAMERA_WIDTH (16)
|
#define DEFAULT_CAMERA_WIDTH (16)
|
||||||
@ -33,7 +33,7 @@
|
|||||||
#define USER_INTERP_RATIO 1.2
|
#define USER_INTERP_RATIO 1.2
|
||||||
#define USER_INTERP_ENABLED 1
|
#define USER_INTERP_ENABLED 1
|
||||||
|
|
||||||
/* 64^2 = 4096 bins */
|
/* 64^2 = 4096 bins */
|
||||||
#define SPACE_CELL_BINS_SQRT (64)
|
#define SPACE_CELL_BINS_SQRT (64)
|
||||||
#define SPACE_CELL_SIZE (1)
|
#define SPACE_CELL_SIZE (1)
|
||||||
|
|
||||||
@ -56,11 +56,11 @@
|
|||||||
#define SIM_PLAYER_AIM 1
|
#define SIM_PLAYER_AIM 1
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
# define SIM_MAX_LINEAR_VELOCITY 500
|
#define SIM_MAX_LINEAR_VELOCITY 500
|
||||||
# define SIM_MAX_ANGULAR_VELOCITY (Tau * 20)
|
#define SIM_MAX_ANGULAR_VELOCITY (Tau * 20)
|
||||||
#else
|
#else
|
||||||
# define SIM_MAX_LINEAR_VELOCITY F32Infinity
|
#define SIM_MAX_LINEAR_VELOCITY F32Infinity
|
||||||
# define SIM_MAX_ANGULAR_VELOCITY F32Infinity
|
#define SIM_MAX_ANGULAR_VELOCITY F32Infinity
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COLLIDER_DEBUG 0
|
#define COLLIDER_DEBUG 0
|
||||||
|
|||||||
672
src/draw/draw.c
672
src/draw/draw.c
@ -5,9 +5,9 @@ D_SharedState D_shared_state = ZI;
|
|||||||
|
|
||||||
void D_Bootstrap(void)
|
void D_Bootstrap(void)
|
||||||
{
|
{
|
||||||
D_SharedState *g = &D_shared_state;
|
D_SharedState *g = &D_shared_state;
|
||||||
u32 pixel_white = 0xFFFFFFFF;
|
u32 pixel_white = 0xFFFFFFFF;
|
||||||
g->solid_white_texture = GPU_AcquireTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white);
|
g->solid_white_texture = GPU_AcquireTexture(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, VEC2I32(1, 1), &pixel_white);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -15,15 +15,15 @@ void D_Bootstrap(void)
|
|||||||
|
|
||||||
void D_DrawMaterial(GPU_RenderSig *sig, D_MaterialParams params)
|
void D_DrawMaterial(GPU_RenderSig *sig, D_MaterialParams params)
|
||||||
{
|
{
|
||||||
GPU_RenderCmdDesc cmd = ZI;
|
GPU_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
||||||
cmd.material.xf = params.xf;
|
cmd.material.xf = params.xf;
|
||||||
cmd.material.texture = params.texture;
|
cmd.material.texture = params.texture;
|
||||||
cmd.material.clip = params.clip;
|
cmd.material.clip = params.clip;
|
||||||
cmd.material.tint = params.tint;
|
cmd.material.tint = params.tint;
|
||||||
cmd.material.is_light = params.is_light;
|
cmd.material.is_light = params.is_light;
|
||||||
cmd.material.light_emittance = params.light_emittance;
|
cmd.material.light_emittance = params.light_emittance;
|
||||||
GPU_PushRenderCmd(sig, &cmd);
|
GPU_PushRenderCmd(sig, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -31,75 +31,75 @@ void D_DrawMaterial(GPU_RenderSig *sig, D_MaterialParams params)
|
|||||||
|
|
||||||
void D_DrawPolyEx(GPU_RenderSig *sig, Vec2Array vertices, GPU_Indices indices, u32 color)
|
void D_DrawPolyEx(GPU_RenderSig *sig, Vec2Array vertices, GPU_Indices indices, u32 color)
|
||||||
{
|
{
|
||||||
GPU_RenderCmdDesc cmd = ZI;
|
GPU_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE;
|
||||||
cmd.ui_shape.vertices = vertices;
|
cmd.ui_shape.vertices = vertices;
|
||||||
cmd.ui_shape.indices = indices;
|
cmd.ui_shape.indices = indices;
|
||||||
cmd.ui_shape.color = color;
|
cmd.ui_shape.color = color;
|
||||||
GPU_PushRenderCmd(sig, &cmd);
|
GPU_PushRenderCmd(sig, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draws a filled polygon using triangles in a fan pattern */
|
/* Draws a filled polygon using triangles in a fan pattern */
|
||||||
void D_DrawPoly(GPU_RenderSig *sig, Vec2Array vertices, u32 color)
|
void D_DrawPoly(GPU_RenderSig *sig, Vec2Array vertices, u32 color)
|
||||||
{
|
{
|
||||||
if (vertices.count >= 3)
|
if (vertices.count >= 3)
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
|
u32 num_tris = vertices.count - 2;
|
||||||
|
u32 num_indices = num_tris * 3;
|
||||||
|
|
||||||
|
/* Generate indices in a fan pattern */
|
||||||
|
GPU_Indices indices = ZI;
|
||||||
|
indices.count = num_indices;
|
||||||
|
indices.indices = PushStructsNoZero(scratch.arena, u32, num_indices);
|
||||||
|
for (u32 i = 0; i < num_tris; ++i)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
u32 tri_offset = i * 3;
|
||||||
|
indices.indices[tri_offset + 0] = 0;
|
||||||
u32 num_tris = vertices.count - 2;
|
indices.indices[tri_offset + 1] = (i + 1);
|
||||||
u32 num_indices = num_tris * 3;
|
indices.indices[tri_offset + 2] = (i + 2);
|
||||||
|
|
||||||
/* Generate indices in a fan pattern */
|
|
||||||
GPU_Indices indices = ZI;
|
|
||||||
indices.count = num_indices;
|
|
||||||
indices.indices = PushStructsNoZero(scratch.arena, u32, num_indices);
|
|
||||||
for (u32 i = 0; i < num_tris; ++i)
|
|
||||||
{
|
|
||||||
u32 tri_offset = i * 3;
|
|
||||||
indices.indices[tri_offset + 0] = 0;
|
|
||||||
indices.indices[tri_offset + 1] = (i + 1);
|
|
||||||
indices.indices[tri_offset + 2] = (i + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
D_DrawPolyEx(sig, vertices, indices, color);
|
|
||||||
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D_DrawPolyEx(sig, vertices, indices, color);
|
||||||
|
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawCircle(GPU_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail)
|
void D_DrawCircle(GPU_RenderSig *sig, Vec2 pos, f32 radius, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
||||||
for (u32 i = 0; i < detail; ++i)
|
for (u32 i = 0; i < detail; ++i)
|
||||||
{
|
{
|
||||||
f32 angle = ((f32)i / (f32)detail) * Tau;
|
f32 angle = ((f32)i / (f32)detail) * Tau;
|
||||||
Vec2 p = VEC2(
|
Vec2 p = VEC2(
|
||||||
radius * CosF32(angle),
|
radius * CosF32(angle),
|
||||||
radius * SinF32(angle)
|
radius * SinF32(angle)
|
||||||
);
|
);
|
||||||
points[i] = AddVec2(pos, p);
|
points[i] = AddVec2(pos, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2Array vertices = {
|
Vec2Array vertices = {
|
||||||
.points = points,
|
.points = points,
|
||||||
.count = detail
|
.count = detail
|
||||||
};
|
};
|
||||||
D_DrawPoly(sig, vertices, color);
|
D_DrawPoly(sig, vertices, color);
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawQuad(GPU_RenderSig *sig, Quad quad, u32 color)
|
void D_DrawQuad(GPU_RenderSig *sig, Quad quad, u32 color)
|
||||||
{
|
{
|
||||||
PERSIST const u32 indices_array[6] = {
|
PERSIST const u32 indices_array[6] = {
|
||||||
0, 1, 2,
|
0, 1, 2,
|
||||||
0, 2, 3
|
0, 2, 3
|
||||||
};
|
};
|
||||||
Vec2Array vertices = { .count = 4, .points = quad.e };
|
Vec2Array vertices = { .count = 4, .points = quad.e };
|
||||||
GPU_Indices indices = { .count = 6, .indices = indices_array };
|
GPU_Indices indices = { .count = 6, .indices = indices_array };
|
||||||
D_DrawPolyEx(sig, vertices, indices, color);
|
D_DrawPolyEx(sig, vertices, indices, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -108,144 +108,144 @@ void D_DrawQuad(GPU_RenderSig *sig, Quad quad, u32 color)
|
|||||||
void D_DrawLineGradient(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color)
|
void D_DrawLineGradient(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 start_color, u32 end_color)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
D_SharedState *g = &D_shared_state;
|
D_SharedState *g = &D_shared_state;
|
||||||
Quad quad = QuadFromLine(start, end, thickness);
|
Quad quad = QuadFromLine(start, end, thickness);
|
||||||
D_DrawMaterial(sig, D_MATERIALPARAMS(.texture = g->solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad));
|
D_DrawMaterial(sig, D_MATERIALPARAMS(.texture = g->solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad));
|
||||||
#else
|
#else
|
||||||
/* Placeholder */
|
/* Placeholder */
|
||||||
Quad quad = QuadFromLine(start, end, thickness);
|
Quad quad = QuadFromLine(start, end, thickness);
|
||||||
D_DrawQuad(sig, quad, start_color);
|
D_DrawQuad(sig, quad, start_color);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawLine(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color)
|
void D_DrawLine(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
Quad quad = QuadFromLine(start, end, thickness);
|
Quad quad = QuadFromLine(start, end, thickness);
|
||||||
D_DrawQuad(sig, quad, color);
|
D_DrawQuad(sig, quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawRay(GPU_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color)
|
void D_DrawRay(GPU_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
Quad quad = QuadFromRay(pos, rel, thickness);
|
Quad quad = QuadFromRay(pos, rel, thickness);
|
||||||
D_DrawQuad(sig, quad, color);
|
D_DrawQuad(sig, quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawPolyLine(GPU_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color)
|
void D_DrawPolyLine(GPU_RenderSig *sig, Vec2Array points, b32 loop, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
if (points.count >= 2)
|
if (points.count >= 2)
|
||||||
|
{
|
||||||
|
for (u64 i = 1; i < points.count; ++i)
|
||||||
{
|
{
|
||||||
for (u64 i = 1; i < points.count; ++i)
|
Vec2 p1 = points.points[i - 1];
|
||||||
{
|
Vec2 p2 = points.points[i];
|
||||||
Vec2 p1 = points.points[i - 1];
|
Quad q = QuadFromLine(p1, p2, thickness);
|
||||||
Vec2 p2 = points.points[i];
|
D_DrawQuad(sig, q, color);
|
||||||
Quad q = QuadFromLine(p1, p2, thickness);
|
|
||||||
D_DrawQuad(sig, q, color);
|
|
||||||
}
|
|
||||||
if (loop && points.count > 2)
|
|
||||||
{
|
|
||||||
Vec2 p1 = points.points[points.count - 1];
|
|
||||||
Vec2 p2 = points.points[0];
|
|
||||||
Quad q = QuadFromLine(p1, p2, thickness);
|
|
||||||
D_DrawQuad(sig, q, color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (loop && points.count > 2)
|
||||||
|
{
|
||||||
|
Vec2 p1 = points.points[points.count - 1];
|
||||||
|
Vec2 p2 = points.points[0];
|
||||||
|
Quad q = QuadFromLine(p1, p2, thickness);
|
||||||
|
D_DrawQuad(sig, q, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawCircleLine(GPU_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
|
void D_DrawCircleLine(GPU_RenderSig *sig, Vec2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
Vec2 *points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
||||||
for (u32 i = 0; i < detail; ++i)
|
for (u32 i = 0; i < detail; ++i)
|
||||||
{
|
{
|
||||||
f32 angle = ((f32)i / (f32)detail) * Tau;
|
f32 angle = ((f32)i / (f32)detail) * Tau;
|
||||||
Vec2 p = VEC2(
|
Vec2 p = VEC2(
|
||||||
radius * CosF32(angle),
|
radius * CosF32(angle),
|
||||||
radius * SinF32(angle)
|
radius * SinF32(angle)
|
||||||
);
|
);
|
||||||
points[i] = AddVec2(pos, p);
|
points[i] = AddVec2(pos, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2Array a = {
|
Vec2Array a = {
|
||||||
.points = points,
|
.points = points,
|
||||||
.count = detail
|
.count = detail
|
||||||
};
|
};
|
||||||
D_DrawPolyLine(sig, a, 1, thickness, color);
|
D_DrawPolyLine(sig, a, 1, thickness, color);
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawQuadLine(GPU_RenderSig *sig, Quad quad, f32 thickness, u32 color)
|
void D_DrawQuadLine(GPU_RenderSig *sig, Quad quad, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
Vec2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
|
Vec2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
|
||||||
Vec2Array a = { .points = points, .count = countof(points) };
|
Vec2Array a = { .points = points, .count = countof(points) };
|
||||||
D_DrawPolyLine(sig, a, 1, thickness, color);
|
D_DrawPolyLine(sig, a, 1, thickness, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawArrowLine(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color)
|
void D_DrawArrowLine(GPU_RenderSig *sig, Vec2 start, Vec2 end, f32 thickness, f32 arrowhead_height, u32 color)
|
||||||
{
|
{
|
||||||
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
|
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
|
||||||
|
|
||||||
const f32 max_height_to_line_ratio = 0.9f; /* Maximum length of arrowhead relative to total line length */
|
const f32 max_height_to_line_ratio = 0.9f; /* Maximum length of arrowhead relative to total line length */
|
||||||
arrowhead_height = MinF32(arrowhead_height, Vec2Len(SubVec2(end, start)) * max_height_to_line_ratio);
|
arrowhead_height = MinF32(arrowhead_height, Vec2Len(SubVec2(end, start)) * max_height_to_line_ratio);
|
||||||
|
|
||||||
Vec2 head_start_dir = SubVec2(start, end);
|
Vec2 head_start_dir = SubVec2(start, end);
|
||||||
head_start_dir = NormVec2(head_start_dir);
|
head_start_dir = NormVec2(head_start_dir);
|
||||||
head_start_dir = MulVec2(head_start_dir, arrowhead_height);
|
head_start_dir = MulVec2(head_start_dir, arrowhead_height);
|
||||||
|
|
||||||
Vec2 head_start = AddVec2(end, head_start_dir);
|
Vec2 head_start = AddVec2(end, head_start_dir);
|
||||||
|
|
||||||
Vec2 head_p1_dir = MulPerpVec2(head_start_dir, head_width_ratio);
|
Vec2 head_p1_dir = MulPerpVec2(head_start_dir, head_width_ratio);
|
||||||
Vec2 head_p2_dir = NegVec2(head_p1_dir);
|
Vec2 head_p2_dir = NegVec2(head_p1_dir);
|
||||||
|
|
||||||
Vec2 head_p1 = AddVec2(head_start, head_p1_dir);
|
Vec2 head_p1 = AddVec2(head_start, head_p1_dir);
|
||||||
Vec2 head_p2 = AddVec2(head_start, head_p2_dir);
|
Vec2 head_p2 = AddVec2(head_start, head_p2_dir);
|
||||||
|
|
||||||
Vec2 head_points[] = { end, head_p1, head_p2 };
|
Vec2 head_points[] = { end, head_p1, head_p2 };
|
||||||
Vec2Array head_points_v2_array = {
|
Vec2Array head_points_v2_array = {
|
||||||
.points = head_points,
|
.points = head_points,
|
||||||
.count = countof(head_points)
|
.count = countof(head_points)
|
||||||
};
|
};
|
||||||
D_DrawPoly(sig, head_points_v2_array, color);
|
D_DrawPoly(sig, head_points_v2_array, color);
|
||||||
|
|
||||||
Quad line_quad = QuadFromLine(start, head_start, thickness);
|
Quad line_quad = QuadFromLine(start, head_start, thickness);
|
||||||
D_DrawQuad(sig, line_quad, color);
|
D_DrawQuad(sig, line_quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawArrowRay(GPU_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color)
|
void D_DrawArrowRay(GPU_RenderSig *sig, Vec2 pos, Vec2 rel, f32 thickness, f32 arrowhead_height, u32 color)
|
||||||
{
|
{
|
||||||
Vec2 end = AddVec2(pos, rel);
|
Vec2 end = AddVec2(pos, rel);
|
||||||
D_DrawArrowLine(sig, pos, end, thickness, arrowhead_height, color);
|
D_DrawArrowLine(sig, pos, end, thickness, arrowhead_height, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_DrawColliderLine(GPU_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail)
|
void D_DrawColliderLine(GPU_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
Vec2Array poly = ZI;
|
Vec2Array poly = ZI;
|
||||||
if (shape.radius == 0)
|
if (shape.radius == 0)
|
||||||
|
{
|
||||||
|
poly.count = shape.count;
|
||||||
|
poly.points = PushStructsNoZero(scratch.arena, Vec2, shape.count);
|
||||||
|
for (u32 i = 0; i < shape.count; ++i)
|
||||||
{
|
{
|
||||||
poly.count = shape.count;
|
Vec2 p = MulXformV2(shape_xf, shape.points[i]);
|
||||||
poly.points = PushStructsNoZero(scratch.arena, Vec2, shape.count);
|
poly.points[i] = p;
|
||||||
for (u32 i = 0; i < shape.count; ++i)
|
|
||||||
{
|
|
||||||
Vec2 p = MulXformV2(shape_xf, shape.points[i]);
|
|
||||||
poly.points[i] = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
poly.count = detail;
|
||||||
|
poly.points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
||||||
|
for (u32 i = 0; i < detail; ++i)
|
||||||
{
|
{
|
||||||
poly.count = detail;
|
f32 angle = ((f32)i / (f32)detail) * Tau;
|
||||||
poly.points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
Vec2 dir = VEC2(CosF32(angle), SinF32(angle));
|
||||||
for (u32 i = 0; i < detail; ++i)
|
Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p;
|
||||||
{
|
poly.points[i] = p;
|
||||||
f32 angle = ((f32)i / (f32)detail) * Tau;
|
|
||||||
Vec2 dir = VEC2(CosF32(angle), SinF32(angle));
|
|
||||||
Vec2 p = CLD_SupportPointFromDir(&shape, shape_xf, dir).p;
|
|
||||||
poly.points[i] = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
D_DrawPolyLine(sig, poly, 1, thickness, color);
|
}
|
||||||
EndScratch(scratch);
|
D_DrawPolyLine(sig, poly, 1, thickness, color);
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -253,27 +253,27 @@ void D_DrawColliderLine(GPU_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32
|
|||||||
|
|
||||||
void D_DrawGrid(GPU_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset)
|
void D_DrawGrid(GPU_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, Vec2 offset)
|
||||||
{
|
{
|
||||||
i32 grid_id = 0;
|
i32 grid_id = 0;
|
||||||
{
|
{
|
||||||
GPU_RenderCmdDesc cmd = ZI;
|
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_PUSH_GRID;
|
|
||||||
cmd.grid.bg0_color = bg0_color;
|
|
||||||
cmd.grid.bg1_color = bg1_color;
|
|
||||||
cmd.grid.line_color = line_color;
|
|
||||||
cmd.grid.x_color = x_color;
|
|
||||||
cmd.grid.y_color = y_color;
|
|
||||||
cmd.grid.line_thickness = thickness;
|
|
||||||
cmd.grid.line_spacing = spacing;
|
|
||||||
cmd.grid.offset = offset;
|
|
||||||
grid_id = GPU_PushRenderCmd(sig, &cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
GPU_RenderCmdDesc cmd = ZI;
|
GPU_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
cmd.kind = GP_RENDER_CMD_KIND_PUSH_GRID;
|
||||||
cmd.material.xf = xf;
|
cmd.grid.bg0_color = bg0_color;
|
||||||
cmd.material.tint = Color_White;
|
cmd.grid.bg1_color = bg1_color;
|
||||||
cmd.material.grid_cmd_id = grid_id;
|
cmd.grid.line_color = line_color;
|
||||||
GPU_PushRenderCmd(sig, &cmd);
|
cmd.grid.x_color = x_color;
|
||||||
|
cmd.grid.y_color = y_color;
|
||||||
|
cmd.grid.line_thickness = thickness;
|
||||||
|
cmd.grid.line_spacing = spacing;
|
||||||
|
cmd.grid.offset = offset;
|
||||||
|
grid_id = GPU_PushRenderCmd(sig, &cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_RenderCmdDesc cmd = ZI;
|
||||||
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
||||||
|
cmd.material.xf = xf;
|
||||||
|
cmd.material.tint = Color_White;
|
||||||
|
cmd.material.grid_cmd_id = grid_id;
|
||||||
|
GPU_PushRenderCmd(sig, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -281,190 +281,190 @@ void D_DrawGrid(GPU_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32
|
|||||||
|
|
||||||
void D_DrawUiRect(GPU_RenderSig *sig, D_UiRectParams params)
|
void D_DrawUiRect(GPU_RenderSig *sig, D_UiRectParams params)
|
||||||
{
|
{
|
||||||
GPU_RenderCmdDesc cmd = ZI;
|
GPU_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT;
|
||||||
cmd.ui_rect.xf = params.xf;
|
cmd.ui_rect.xf = params.xf;
|
||||||
cmd.ui_rect.texture = params.texture;
|
cmd.ui_rect.texture = params.texture;
|
||||||
cmd.ui_rect.clip = params.clip;
|
cmd.ui_rect.clip = params.clip;
|
||||||
cmd.ui_rect.tint = params.tint;
|
cmd.ui_rect.tint = params.tint;
|
||||||
GPU_PushRenderCmd(sig, &cmd);
|
GPU_PushRenderCmd(sig, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Text
|
//~ Text
|
||||||
|
|
||||||
/* Returns the rect of the text area */
|
/* Returns the rect of the text area */
|
||||||
Rect draw_text(GPU_RenderSig *sig, D_TextParams params)
|
Rect draw_text(GPU_RenderSig *sig, D_TextParams params)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
f32 inv_font_image_width = 1.0 / (f32)params.font->image_width;
|
f32 inv_font_image_width = 1.0 / (f32)params.font->image_width;
|
||||||
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
|
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
|
||||||
f32 line_spacing = params.font->point_size * 1.5f * params.scale;
|
f32 line_spacing = params.font->point_size * 1.5f * params.scale;
|
||||||
|
|
||||||
//- Build line glyphs
|
//- Build line glyphs
|
||||||
|
|
||||||
u64 num_lines = 0;
|
u64 num_lines = 0;
|
||||||
f32 widest_line = 0;
|
f32 widest_line = 0;
|
||||||
|
|
||||||
D_TextLine *first_line = 0;
|
D_TextLine *first_line = 0;
|
||||||
D_TextLine *last_line = 0;
|
D_TextLine *last_line = 0;
|
||||||
f32 first_line_top_offset = 0;
|
f32 first_line_top_offset = 0;
|
||||||
f32 last_line_bottom_offset = 0;
|
f32 last_line_bottom_offset = 0;
|
||||||
|
|
||||||
if (params.str.len > 0)
|
if (params.str.len > 0)
|
||||||
|
{
|
||||||
|
b32 string_done = 0;
|
||||||
|
CodepointIter iter = BeginCodepointIter(params.str);
|
||||||
|
while (!string_done)
|
||||||
{
|
{
|
||||||
b32 string_done = 0;
|
f32 line_width = 0;
|
||||||
CodepointIter iter = BeginCodepointIter(params.str);
|
f32 top_offset = 0;
|
||||||
while (!string_done)
|
f32 bottom_offset = 0;
|
||||||
|
u64 num_line_glyphs = 0;
|
||||||
|
D_TextGlyph *line_glyphs = PushDry(scratch.arena, D_TextGlyph);
|
||||||
|
|
||||||
|
b32 line_done = 0;
|
||||||
|
while (!line_done)
|
||||||
|
{
|
||||||
|
string_done = !AdvanceCodepointIter(&iter);
|
||||||
|
if (string_done)
|
||||||
{
|
{
|
||||||
f32 line_width = 0;
|
line_done = 1;
|
||||||
f32 top_offset = 0;
|
|
||||||
f32 bottom_offset = 0;
|
|
||||||
u64 num_line_glyphs = 0;
|
|
||||||
D_TextGlyph *line_glyphs = PushDry(scratch.arena, D_TextGlyph);
|
|
||||||
|
|
||||||
b32 line_done = 0;
|
|
||||||
while (!line_done)
|
|
||||||
{
|
|
||||||
string_done = !AdvanceCodepointIter(&iter);
|
|
||||||
if (string_done)
|
|
||||||
{
|
|
||||||
line_done = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 codepoint = iter.codepoint;
|
|
||||||
if (codepoint == '\n')
|
|
||||||
{
|
|
||||||
line_done = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
D_TextGlyph *tg = PushStruct(scratch.arena, D_TextGlyph);
|
|
||||||
++num_line_glyphs;
|
|
||||||
F_Glyph *glyph = F_GetGlyph(params.font, codepoint);
|
|
||||||
tg->off_x = glyph->off_x * params.scale;
|
|
||||||
tg->off_y = glyph->off_y * params.scale;
|
|
||||||
tg->width = glyph->width * params.scale;
|
|
||||||
tg->height = glyph->height * params.scale;
|
|
||||||
tg->advance = glyph->advance * params.scale;
|
|
||||||
Rect glyph_atlas_rect = glyph->atlas_rect;
|
|
||||||
tg->clip = (ClipRect) {
|
|
||||||
{
|
|
||||||
glyph_atlas_rect.x * inv_font_image_width,
|
|
||||||
glyph_atlas_rect.y * inv_font_image_height
|
|
||||||
},
|
|
||||||
{
|
|
||||||
(glyph_atlas_rect.x + glyph_atlas_rect.width) * inv_font_image_width,
|
|
||||||
(glyph_atlas_rect.y + glyph_atlas_rect.height) * inv_font_image_height
|
|
||||||
}
|
|
||||||
};
|
|
||||||
line_width += tg->advance;
|
|
||||||
top_offset = MinF32(top_offset, tg->off_y);
|
|
||||||
bottom_offset = MaxF32(bottom_offset, tg->off_y + tg->height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Line ended */
|
|
||||||
/* TODO: Only create nodes for non-empty lines. Embed line number in the node. */
|
|
||||||
D_TextLine *node = PushStruct(scratch.arena, D_TextLine);
|
|
||||||
node->line_width = line_width;
|
|
||||||
node->num_glyphs = num_line_glyphs;
|
|
||||||
node->glyphs = line_glyphs;
|
|
||||||
if (last_line)
|
|
||||||
{
|
|
||||||
last_line->next = node;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
first_line = node;
|
|
||||||
first_line_top_offset = top_offset;
|
|
||||||
}
|
|
||||||
last_line = node;
|
|
||||||
last_line_bottom_offset = bottom_offset;
|
|
||||||
widest_line = MaxF32(widest_line, line_width);
|
|
||||||
++num_lines;
|
|
||||||
}
|
}
|
||||||
EndCodepointIter(&iter);
|
else
|
||||||
}
|
|
||||||
|
|
||||||
//- Determine text bounds
|
|
||||||
|
|
||||||
Rect bounds = ZI;
|
|
||||||
bounds.x = params.pos.x;
|
|
||||||
bounds.y = params.pos.y;
|
|
||||||
bounds.width = widest_line;
|
|
||||||
bounds.height = num_lines * line_spacing + first_line_top_offset + last_line_bottom_offset;
|
|
||||||
|
|
||||||
/* Offset bounds X */
|
|
||||||
switch (params.offset_x)
|
|
||||||
{
|
|
||||||
case DRAW_TEXT_OFFSET_X_LEFT: break;
|
|
||||||
case DRAW_TEXT_OFFSET_X_CENTER:
|
|
||||||
{
|
{
|
||||||
bounds.x -= bounds.width / 2.f;
|
u32 codepoint = iter.codepoint;
|
||||||
} break;
|
if (codepoint == '\n')
|
||||||
case DRAW_TEXT_OFFSET_X_RIGHT:
|
{
|
||||||
{
|
line_done = 1;
|
||||||
bounds.x -= bounds.width;
|
}
|
||||||
} break;
|
else
|
||||||
}
|
{
|
||||||
|
D_TextGlyph *tg = PushStruct(scratch.arena, D_TextGlyph);
|
||||||
/* Offset bounds Y */
|
++num_line_glyphs;
|
||||||
switch (params.offset_y)
|
F_Glyph *glyph = F_GetGlyph(params.font, codepoint);
|
||||||
{
|
tg->off_x = glyph->off_x * params.scale;
|
||||||
case DRAW_TEXT_OFFSET_Y_TOP: break;
|
tg->off_y = glyph->off_y * params.scale;
|
||||||
case DRAW_TEXT_OFFSET_Y_CENTER:
|
tg->width = glyph->width * params.scale;
|
||||||
{
|
tg->height = glyph->height * params.scale;
|
||||||
bounds.y -= bounds.height / 2.f;
|
tg->advance = glyph->advance * params.scale;
|
||||||
} break;
|
Rect glyph_atlas_rect = glyph->atlas_rect;
|
||||||
case DRAW_TEXT_OFFSET_Y_BOTTOM:
|
tg->clip = (ClipRect) {
|
||||||
{
|
{
|
||||||
if (last_line)
|
glyph_atlas_rect.x * inv_font_image_width,
|
||||||
{
|
glyph_atlas_rect.y * inv_font_image_height
|
||||||
bounds.y -= bounds.height + last_line_bottom_offset;
|
},
|
||||||
}
|
{
|
||||||
} break;
|
(glyph_atlas_rect.x + glyph_atlas_rect.width) * inv_font_image_width,
|
||||||
}
|
(glyph_atlas_rect.y + glyph_atlas_rect.height) * inv_font_image_height
|
||||||
|
}
|
||||||
//- Draw lines
|
};
|
||||||
|
line_width += tg->advance;
|
||||||
u64 line_number = 0;
|
top_offset = MinF32(top_offset, tg->off_y);
|
||||||
for (D_TextLine *line = first_line; line; line = line->next)
|
bottom_offset = MaxF32(bottom_offset, tg->off_y + tg->height);
|
||||||
{
|
}
|
||||||
Vec2 draw_pos = bounds.pos;
|
|
||||||
draw_pos.y += line_number * line_spacing - first_line_top_offset;
|
|
||||||
|
|
||||||
/* Alignment */
|
|
||||||
switch (params.alignment)
|
|
||||||
{
|
|
||||||
case DRAW_TEXT_ALIGNMENT_LEFT: break;
|
|
||||||
case DRAW_TEXT_ALIGNMENT_CENTER:
|
|
||||||
{
|
|
||||||
draw_pos.x += (bounds.width - line->line_width) / 2.f;
|
|
||||||
} break;
|
|
||||||
case DRAW_TEXT_ALIGNMENT_RIGHT:
|
|
||||||
{
|
|
||||||
draw_pos.x += bounds.width - line->line_width;
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Draw glyphs in line */
|
/* Line ended */
|
||||||
for (u64 i = 0; i < line->num_glyphs; ++i)
|
/* TODO: Only create nodes for non-empty lines. Embed line number in the node. */
|
||||||
{
|
D_TextLine *node = PushStruct(scratch.arena, D_TextLine);
|
||||||
D_TextGlyph *tg = &line->glyphs[i];
|
node->line_width = line_width;
|
||||||
Vec2 pos = VEC2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
|
node->num_glyphs = num_line_glyphs;
|
||||||
Vec2 size = VEC2(tg->width, tg->height);
|
node->glyphs = line_glyphs;
|
||||||
Xform xf = XformFromRect(RectFromVec2(pos, size));
|
if (last_line)
|
||||||
D_DrawUiRect(sig, D_UIRECTPARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
|
{
|
||||||
draw_pos.x += tg->advance;
|
last_line->next = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first_line = node;
|
||||||
|
first_line_top_offset = top_offset;
|
||||||
|
}
|
||||||
|
last_line = node;
|
||||||
|
last_line_bottom_offset = bottom_offset;
|
||||||
|
widest_line = MaxF32(widest_line, line_width);
|
||||||
|
++num_lines;
|
||||||
|
}
|
||||||
|
EndCodepointIter(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
//- Determine text bounds
|
||||||
++line_number;
|
|
||||||
|
Rect bounds = ZI;
|
||||||
|
bounds.x = params.pos.x;
|
||||||
|
bounds.y = params.pos.y;
|
||||||
|
bounds.width = widest_line;
|
||||||
|
bounds.height = num_lines * line_spacing + first_line_top_offset + last_line_bottom_offset;
|
||||||
|
|
||||||
|
/* Offset bounds X */
|
||||||
|
switch (params.offset_x)
|
||||||
|
{
|
||||||
|
case DRAW_TEXT_OFFSET_X_LEFT: break;
|
||||||
|
case DRAW_TEXT_OFFSET_X_CENTER:
|
||||||
|
{
|
||||||
|
bounds.x -= bounds.width / 2.f;
|
||||||
|
} break;
|
||||||
|
case DRAW_TEXT_OFFSET_X_RIGHT:
|
||||||
|
{
|
||||||
|
bounds.x -= bounds.width;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Offset bounds Y */
|
||||||
|
switch (params.offset_y)
|
||||||
|
{
|
||||||
|
case DRAW_TEXT_OFFSET_Y_TOP: break;
|
||||||
|
case DRAW_TEXT_OFFSET_Y_CENTER:
|
||||||
|
{
|
||||||
|
bounds.y -= bounds.height / 2.f;
|
||||||
|
} break;
|
||||||
|
case DRAW_TEXT_OFFSET_Y_BOTTOM:
|
||||||
|
{
|
||||||
|
if (last_line)
|
||||||
|
{
|
||||||
|
bounds.y -= bounds.height + last_line_bottom_offset;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Draw lines
|
||||||
|
|
||||||
|
u64 line_number = 0;
|
||||||
|
for (D_TextLine *line = first_line; line; line = line->next)
|
||||||
|
{
|
||||||
|
Vec2 draw_pos = bounds.pos;
|
||||||
|
draw_pos.y += line_number * line_spacing - first_line_top_offset;
|
||||||
|
|
||||||
|
/* Alignment */
|
||||||
|
switch (params.alignment)
|
||||||
|
{
|
||||||
|
case DRAW_TEXT_ALIGNMENT_LEFT: break;
|
||||||
|
case DRAW_TEXT_ALIGNMENT_CENTER:
|
||||||
|
{
|
||||||
|
draw_pos.x += (bounds.width - line->line_width) / 2.f;
|
||||||
|
} break;
|
||||||
|
case DRAW_TEXT_ALIGNMENT_RIGHT:
|
||||||
|
{
|
||||||
|
draw_pos.x += bounds.width - line->line_width;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
/* Draw glyphs in line */
|
||||||
return bounds;
|
for (u64 i = 0; i < line->num_glyphs; ++i)
|
||||||
|
{
|
||||||
|
D_TextGlyph *tg = &line->glyphs[i];
|
||||||
|
Vec2 pos = VEC2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
|
||||||
|
Vec2 size = VEC2(tg->width, tg->height);
|
||||||
|
Xform xf = XformFromRect(RectFromVec2(pos, size));
|
||||||
|
D_DrawUiRect(sig, D_UIRECTPARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
|
||||||
|
draw_pos.x += tg->advance;
|
||||||
|
|
||||||
|
}
|
||||||
|
++line_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndScratch(scratch);
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|||||||
100
src/draw/draw.h
100
src/draw/draw.h
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
Struct(D_MaterialParams)
|
Struct(D_MaterialParams)
|
||||||
{
|
{
|
||||||
Xform xf;
|
Xform xf;
|
||||||
GPU_Resource *texture;
|
GPU_Resource *texture;
|
||||||
ClipRect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
b32 is_light;
|
b32 is_light;
|
||||||
Vec3 light_emittance;
|
Vec3 light_emittance;
|
||||||
};
|
};
|
||||||
#define D_MATERIALPARAMS(...) ((D_MaterialParams) { \
|
#define D_MATERIALPARAMS(...) ((D_MaterialParams) { \
|
||||||
.tint = Color_White, \
|
.tint = Color_White, \
|
||||||
.clip = AllClipped, \
|
.clip = AllClipped, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -21,15 +21,15 @@ Struct(D_MaterialParams)
|
|||||||
|
|
||||||
Struct(D_UiRectParams)
|
Struct(D_UiRectParams)
|
||||||
{
|
{
|
||||||
Xform xf;
|
Xform xf;
|
||||||
GPU_Resource *texture;
|
GPU_Resource *texture;
|
||||||
ClipRect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
};
|
};
|
||||||
#define D_UIRECTPARAMS(...) ((D_UiRectParams) { \
|
#define D_UIRECTPARAMS(...) ((D_UiRectParams) { \
|
||||||
.tint = Color_White, \
|
.tint = Color_White, \
|
||||||
.clip = AllClipped, \
|
.clip = AllClipped, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -38,9 +38,9 @@ Struct(D_UiRectParams)
|
|||||||
/* How is text aligned within its area */
|
/* How is text aligned within its area */
|
||||||
Enum(D_TextAlignment)
|
Enum(D_TextAlignment)
|
||||||
{
|
{
|
||||||
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
|
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
|
||||||
DRAW_TEXT_ALIGNMENT_CENTER,
|
DRAW_TEXT_ALIGNMENT_CENTER,
|
||||||
DRAW_TEXT_ALIGNMENT_RIGHT
|
DRAW_TEXT_ALIGNMENT_RIGHT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* How does the specified text position relate to the text area.
|
/* How does the specified text position relate to the text area.
|
||||||
@ -48,54 +48,54 @@ Enum(D_TextAlignment)
|
|||||||
* the specified position. */
|
* the specified position. */
|
||||||
Enum(D_TextOffsetX)
|
Enum(D_TextOffsetX)
|
||||||
{
|
{
|
||||||
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
|
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
|
||||||
DRAW_TEXT_OFFSET_X_CENTER,
|
DRAW_TEXT_OFFSET_X_CENTER,
|
||||||
DRAW_TEXT_OFFSET_X_RIGHT
|
DRAW_TEXT_OFFSET_X_RIGHT
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(D_TextOffsetY)
|
Enum(D_TextOffsetY)
|
||||||
{
|
{
|
||||||
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
|
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
|
||||||
DRAW_TEXT_OFFSET_Y_CENTER,
|
DRAW_TEXT_OFFSET_Y_CENTER,
|
||||||
DRAW_TEXT_OFFSET_Y_BOTTOM
|
DRAW_TEXT_OFFSET_Y_BOTTOM
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(D_TextGlyph)
|
Struct(D_TextGlyph)
|
||||||
{
|
{
|
||||||
f32 off_x;
|
f32 off_x;
|
||||||
f32 off_y;
|
f32 off_y;
|
||||||
f32 width;
|
f32 width;
|
||||||
f32 height;
|
f32 height;
|
||||||
f32 advance;
|
f32 advance;
|
||||||
ClipRect clip;
|
ClipRect clip;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(D_TextLine)
|
Struct(D_TextLine)
|
||||||
{
|
{
|
||||||
f32 line_width;
|
f32 line_width;
|
||||||
u32 num_glyphs;
|
u32 num_glyphs;
|
||||||
D_TextGlyph *glyphs;
|
D_TextGlyph *glyphs;
|
||||||
D_TextLine *next;
|
D_TextLine *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(D_TextParams)
|
Struct(D_TextParams)
|
||||||
{
|
{
|
||||||
F_Font *font;
|
F_Font *font;
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
f32 scale;
|
f32 scale;
|
||||||
u32 color;
|
u32 color;
|
||||||
D_TextAlignment alignment;
|
D_TextAlignment alignment;
|
||||||
D_TextOffsetX offset_x;
|
D_TextOffsetX offset_x;
|
||||||
D_TextOffsetY offset_y;
|
D_TextOffsetY offset_y;
|
||||||
String str;
|
String str;
|
||||||
};
|
};
|
||||||
#define D_TEXTPARAMS(...) ((D_TextParams) { \
|
#define D_TEXTPARAMS(...) ((D_TextParams) { \
|
||||||
.scale = 1.0, \
|
.scale = 1.0, \
|
||||||
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
|
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
|
||||||
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
|
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
|
||||||
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
|
.offset_y = DRAW_TEXT_OFFSET_Y_TOP, \
|
||||||
.color = Color_White, \
|
.color = Color_White, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -103,7 +103,7 @@ Struct(D_TextParams)
|
|||||||
|
|
||||||
Struct(D_SharedState)
|
Struct(D_SharedState)
|
||||||
{
|
{
|
||||||
GPU_Resource *solid_white_texture;
|
GPU_Resource *solid_white_texture;
|
||||||
} extern D_shared_state;
|
} extern D_shared_state;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -5,7 +5,7 @@ GC_Ctx GC = Zi;
|
|||||||
|
|
||||||
void GC_Bootstrap(void)
|
void GC_Bootstrap(void)
|
||||||
{
|
{
|
||||||
OnAsyncTick(GC_TickAsync);
|
OnAsyncTick(GC_TickAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -13,15 +13,15 @@ void GC_Bootstrap(void)
|
|||||||
|
|
||||||
GC_FontKey GC_FontKeyFromResource(ResourceKey resource)
|
GC_FontKey GC_FontKeyFromResource(ResourceKey resource)
|
||||||
{
|
{
|
||||||
GC_FontKey result = Zi;
|
GC_FontKey result = Zi;
|
||||||
result.r = resource;
|
result.r = resource;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
|
u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
|
||||||
{
|
{
|
||||||
/* TODO: Lower font-size precision to prevent unique hashes for slightly-different font sizes */
|
/* TODO: Lower font-size precision to prevent unique hashes for slightly-different font sizes */
|
||||||
return RandU64FromSeeds(desc.font.r.v, ((u64)desc.codepoint << 32) | *(u32 *)&desc.font_size);
|
return RandU64FromSeeds(desc.font.r.v, ((u64)desc.codepoint << 32) | *(u32 *)&desc.font_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -30,189 +30,189 @@ u64 GC_HashFromGlyphDesc(GC_GlyphDesc desc)
|
|||||||
/* TODO: Thread-local cache */
|
/* TODO: Thread-local cache */
|
||||||
GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size)
|
GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size)
|
||||||
{
|
{
|
||||||
GC_Run result = Zi;
|
GC_Run result = Zi;
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
u64 codepoints_count = 0;
|
u64 codepoints_count = 0;
|
||||||
u32 *codepoints = 0;
|
u32 *codepoints = 0;
|
||||||
|
{
|
||||||
|
String32 str32 = String32FromString(scratch.arena, str);
|
||||||
|
codepoints_count = str32.len;
|
||||||
|
codepoints = str32.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Grab glyphs from cache
|
||||||
|
|
||||||
|
u64 ready_glyphs_count = 0;
|
||||||
|
GC_Glyph **ready_glyphs = PushStructsNoZero(scratch.arena, GC_Glyph *, codepoints_count);
|
||||||
|
|
||||||
|
u32 *uncached_codepoints = PushStructsNoZero(scratch.arena, u32, codepoints_count);
|
||||||
|
u64 uncached_codepoints_count = 0;
|
||||||
|
|
||||||
|
/* TODO: Include advances for glyphs in run that have rasterized but not finished uploading to atlas */
|
||||||
|
u64 pending_glyphs_count = 0;
|
||||||
|
{
|
||||||
|
if (codepoints_count > 0)
|
||||||
{
|
{
|
||||||
String32 str32 = String32FromString(scratch.arena, str);
|
Lock lock = LockS(&GC.glyphs_mutex);
|
||||||
codepoints_count = str32.len;
|
{
|
||||||
codepoints = str32.text;
|
i64 completion = G_CompletionValueFromQueue(G_QueueKind_AsyncCopy);
|
||||||
}
|
for (u64 codepoint_idx = 0; codepoint_idx < codepoints_count; ++codepoint_idx)
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Grab glyphs from cache
|
|
||||||
|
|
||||||
u64 ready_glyphs_count = 0;
|
|
||||||
GC_Glyph **ready_glyphs = PushStructsNoZero(scratch.arena, GC_Glyph *, codepoints_count);
|
|
||||||
|
|
||||||
u32 *uncached_codepoints = PushStructsNoZero(scratch.arena, u32, codepoints_count);
|
|
||||||
u64 uncached_codepoints_count = 0;
|
|
||||||
|
|
||||||
/* TODO: Include advances for glyphs in run that have rasterized but not finished uploading to atlas */
|
|
||||||
u64 pending_glyphs_count = 0;
|
|
||||||
{
|
|
||||||
if (codepoints_count > 0)
|
|
||||||
{
|
{
|
||||||
Lock lock = LockS(&GC.glyphs_mutex);
|
u32 codepoint = codepoints[codepoint_idx];
|
||||||
{
|
|
||||||
i64 completion = G_CompletionValueFromQueue(G_QueueKind_AsyncCopy);
|
|
||||||
for (u64 codepoint_idx = 0; codepoint_idx < codepoints_count; ++codepoint_idx)
|
|
||||||
{
|
|
||||||
u32 codepoint = codepoints[codepoint_idx];
|
|
||||||
|
|
||||||
GC_GlyphDesc desc = Zi;
|
GC_GlyphDesc desc = Zi;
|
||||||
desc.font = font;
|
desc.font = font;
|
||||||
desc.font_size = font_size;
|
desc.font_size = font_size;
|
||||||
desc.codepoint = codepoint;
|
desc.codepoint = codepoint;
|
||||||
|
|
||||||
u64 hash = GC_HashFromGlyphDesc(desc);
|
u64 hash = GC_HashFromGlyphDesc(desc);
|
||||||
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
||||||
GC_Glyph *glyph = bin->first;
|
GC_Glyph *glyph = bin->first;
|
||||||
for (; glyph; glyph = glyph->next)
|
for (; glyph; glyph = glyph->next)
|
||||||
{
|
{
|
||||||
if (glyph->hash == hash) break;
|
if (glyph->hash == hash) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyph == 0)
|
if (glyph == 0)
|
||||||
{
|
{
|
||||||
uncached_codepoints[uncached_codepoints_count] = codepoint;
|
uncached_codepoints[uncached_codepoints_count] = codepoint;
|
||||||
uncached_codepoints_count += 1;
|
uncached_codepoints_count += 1;
|
||||||
}
|
}
|
||||||
else if (completion < Atomic64Fetch(&glyph->async_copy_completion_target))
|
else if (completion < Atomic64Fetch(&glyph->async_copy_completion_target))
|
||||||
{
|
{
|
||||||
pending_glyphs_count += 1;
|
pending_glyphs_count += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ready_glyphs[ready_glyphs_count] = glyph;
|
ready_glyphs[ready_glyphs_count] = glyph;
|
||||||
ready_glyphs_count += 1;
|
ready_glyphs_count += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Create cache entries
|
//- Create cache entries
|
||||||
|
|
||||||
u64 submit_cmds_count = 0;
|
u64 submit_cmds_count = 0;
|
||||||
GC_Cmd *submit_cmds = PushStructsNoZero(scratch.arena, GC_Cmd, uncached_codepoints_count);
|
GC_Cmd *submit_cmds = PushStructsNoZero(scratch.arena, GC_Cmd, uncached_codepoints_count);
|
||||||
if (uncached_codepoints_count > 0)
|
if (uncached_codepoints_count > 0)
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&GC.glyphs_mutex);
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&GC.glyphs_mutex);
|
for (u64 uncached_codepoint_idx = 0; uncached_codepoint_idx < uncached_codepoints_count; ++uncached_codepoint_idx)
|
||||||
|
{
|
||||||
|
GC_GlyphDesc desc = Zi;
|
||||||
|
desc.font = font;
|
||||||
|
desc.font_size = font_size;
|
||||||
|
desc.codepoint = uncached_codepoints[uncached_codepoint_idx];
|
||||||
|
|
||||||
|
u64 hash = GC_HashFromGlyphDesc(desc);
|
||||||
|
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
||||||
|
GC_Glyph *glyph = bin->first;
|
||||||
|
for (; glyph; glyph = glyph->next)
|
||||||
{
|
{
|
||||||
for (u64 uncached_codepoint_idx = 0; uncached_codepoint_idx < uncached_codepoints_count; ++uncached_codepoint_idx)
|
if (glyph->hash == hash) break;
|
||||||
{
|
|
||||||
GC_GlyphDesc desc = Zi;
|
|
||||||
desc.font = font;
|
|
||||||
desc.font_size = font_size;
|
|
||||||
desc.codepoint = uncached_codepoints[uncached_codepoint_idx];
|
|
||||||
|
|
||||||
u64 hash = GC_HashFromGlyphDesc(desc);
|
|
||||||
GC_GlyphBin *bin = &GC.glyph_bins[hash % countof(GC.glyph_bins)];
|
|
||||||
GC_Glyph *glyph = bin->first;
|
|
||||||
for (; glyph; glyph = glyph->next)
|
|
||||||
{
|
|
||||||
if (glyph->hash == hash) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glyph == 0)
|
|
||||||
{
|
|
||||||
glyph = PushStruct(perm, GC_Glyph);
|
|
||||||
glyph->desc = desc;
|
|
||||||
glyph->hash = hash;
|
|
||||||
Atomic64FetchSet(&glyph->async_copy_completion_target, I64Max);
|
|
||||||
SllStackPush(bin->first, glyph);
|
|
||||||
/* Create cmd */
|
|
||||||
{
|
|
||||||
GC_Cmd *cmd = &submit_cmds[submit_cmds_count];
|
|
||||||
cmd->glyph = glyph;
|
|
||||||
++submit_cmds_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Submit cmds
|
|
||||||
|
|
||||||
if (submit_cmds_count > 0)
|
|
||||||
{
|
|
||||||
Lock lock = LockE(&GC.submit.mutex);
|
|
||||||
for (u64 cmd_idx = 0; cmd_idx < submit_cmds_count; ++cmd_idx)
|
|
||||||
{
|
|
||||||
GC_Cmd *src = &submit_cmds[cmd_idx];
|
|
||||||
GC_CmdNode *n = GC.submit.first_free;
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
SllStackPop(GC.submit.first_free);
|
|
||||||
ZeroStruct(n);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = PushStruct(perm, GC_CmdNode);
|
|
||||||
}
|
|
||||||
n->cmd = *src;
|
|
||||||
GC.submit.count += 1;
|
|
||||||
SllQueuePush(GC.submit.first, GC.submit.last, n);
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
SignalAsyncTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Create run from glyphs
|
|
||||||
|
|
||||||
f32 baseline_pos = 0;
|
|
||||||
result.rects = PushStructs(arena, GC_RunRect, ready_glyphs_count);
|
|
||||||
result.rects_count = ready_glyphs_count;
|
|
||||||
for (u64 glyph_idx = 0; glyph_idx < ready_glyphs_count; ++glyph_idx)
|
|
||||||
{
|
|
||||||
GC_Glyph *glyph = ready_glyphs[glyph_idx];
|
|
||||||
GC_RunRect *rect = &result.rects[glyph_idx];
|
|
||||||
|
|
||||||
rect->tex = glyph->atlas->tex_ref;
|
|
||||||
rect->tex_slice = glyph->tex_slice;
|
|
||||||
rect->tex_slice_uv = glyph->tex_slice_uv;
|
|
||||||
|
|
||||||
rect->baseline_pos = baseline_pos;
|
|
||||||
rect->advance = glyph->advance;
|
|
||||||
|
|
||||||
rect->bounds = glyph->bounds;
|
|
||||||
|
|
||||||
if (glyph_idx == 0)
|
|
||||||
{
|
|
||||||
result.bounds = rect->bounds;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.bounds = UnionRng2(result.bounds, rect->bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
baseline_pos += rect->advance;
|
if (glyph == 0)
|
||||||
result.baseline_length = MaxF32(result.baseline_length, baseline_pos);
|
{
|
||||||
|
glyph = PushStruct(perm, GC_Glyph);
|
||||||
|
glyph->desc = desc;
|
||||||
|
glyph->hash = hash;
|
||||||
|
Atomic64FetchSet(&glyph->async_copy_completion_target, I64Max);
|
||||||
|
SllStackPush(bin->first, glyph);
|
||||||
|
/* Create cmd */
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &submit_cmds[submit_cmds_count];
|
||||||
|
cmd->glyph = glyph;
|
||||||
|
++submit_cmds_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
if (ready_glyphs_count > 0)
|
//////////////////////////////
|
||||||
|
//- Submit cmds
|
||||||
|
|
||||||
|
if (submit_cmds_count > 0)
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&GC.submit.mutex);
|
||||||
|
for (u64 cmd_idx = 0; cmd_idx < submit_cmds_count; ++cmd_idx)
|
||||||
{
|
{
|
||||||
GC_Glyph *glyph = ready_glyphs[0];
|
GC_Cmd *src = &submit_cmds[cmd_idx];
|
||||||
result.font_size = glyph->font_size;
|
GC_CmdNode *n = GC.submit.first_free;
|
||||||
result.font_ascent = glyph->font_ascent;
|
if (n)
|
||||||
result.font_descent = glyph->font_descent;
|
{
|
||||||
result.font_cap = glyph->font_cap;
|
SllStackPop(GC.submit.first_free);
|
||||||
|
ZeroStruct(n);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = PushStruct(perm, GC_CmdNode);
|
||||||
|
}
|
||||||
|
n->cmd = *src;
|
||||||
|
GC.submit.count += 1;
|
||||||
|
SllQueuePush(GC.submit.first, GC.submit.last, n);
|
||||||
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
SignalAsyncTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Create run from glyphs
|
||||||
|
|
||||||
|
f32 baseline_pos = 0;
|
||||||
|
result.rects = PushStructs(arena, GC_RunRect, ready_glyphs_count);
|
||||||
|
result.rects_count = ready_glyphs_count;
|
||||||
|
for (u64 glyph_idx = 0; glyph_idx < ready_glyphs_count; ++glyph_idx)
|
||||||
|
{
|
||||||
|
GC_Glyph *glyph = ready_glyphs[glyph_idx];
|
||||||
|
GC_RunRect *rect = &result.rects[glyph_idx];
|
||||||
|
|
||||||
|
rect->tex = glyph->atlas->tex_ref;
|
||||||
|
rect->tex_slice = glyph->tex_slice;
|
||||||
|
rect->tex_slice_uv = glyph->tex_slice_uv;
|
||||||
|
|
||||||
|
rect->baseline_pos = baseline_pos;
|
||||||
|
rect->advance = glyph->advance;
|
||||||
|
|
||||||
|
rect->bounds = glyph->bounds;
|
||||||
|
|
||||||
|
if (glyph_idx == 0)
|
||||||
|
{
|
||||||
|
result.bounds = rect->bounds;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.bounds = UnionRng2(result.bounds, rect->bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// result.ready = uncached_codepoints_count == 0 && pending_glyphs_count == 0;
|
baseline_pos += rect->advance;
|
||||||
result.ready = 1;
|
result.baseline_length = MaxF32(result.baseline_length, baseline_pos);
|
||||||
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
if (ready_glyphs_count > 0)
|
||||||
return result;
|
{
|
||||||
|
GC_Glyph *glyph = ready_glyphs[0];
|
||||||
|
result.font_size = glyph->font_size;
|
||||||
|
result.font_ascent = glyph->font_ascent;
|
||||||
|
result.font_descent = glyph->font_descent;
|
||||||
|
result.font_cap = glyph->font_cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// result.ready = uncached_codepoints_count == 0 && pending_glyphs_count == 0;
|
||||||
|
result.ready = 1;
|
||||||
|
|
||||||
|
EndScratch(scratch);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -220,162 +220,162 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
|
|||||||
|
|
||||||
void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
void GC_TickAsync(WaveLaneCtx *lane, AsyncTickCtx *tick)
|
||||||
{
|
{
|
||||||
GC_AsyncCtx *async = &GC.async_ctx;
|
GC_AsyncCtx *async = &GC.async_ctx;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Begin tick
|
//- Begin tick
|
||||||
|
|
||||||
/* TODO: Limit cmds processed per-tick */
|
/* TODO: Limit cmds processed per-tick */
|
||||||
|
|
||||||
if (lane->idx == 0)
|
if (lane->idx == 0)
|
||||||
|
{
|
||||||
|
ZeroStruct(&async->cmds);
|
||||||
|
|
||||||
|
Lock lock = LockE(&GC.submit.mutex);
|
||||||
{
|
{
|
||||||
ZeroStruct(&async->cmds);
|
/* Pop cmds from submission queue */
|
||||||
|
async->cmds.count = GC.submit.count;
|
||||||
Lock lock = LockE(&GC.submit.mutex);
|
async->cmds.v = PushStructsNoZero(tick->arena, GC_Cmd, GC.submit.count);
|
||||||
{
|
u64 cmd_idx = 0;
|
||||||
/* Pop cmds from submission queue */
|
for (GC_CmdNode *n = GC.submit.first; n; n = n->next)
|
||||||
async->cmds.count = GC.submit.count;
|
{
|
||||||
async->cmds.v = PushStructsNoZero(tick->arena, GC_Cmd, GC.submit.count);
|
async->cmds.v[cmd_idx] = n->cmd;
|
||||||
u64 cmd_idx = 0;
|
++cmd_idx;
|
||||||
for (GC_CmdNode *n = GC.submit.first; n; n = n->next)
|
}
|
||||||
{
|
/* Reset submission queue */
|
||||||
async->cmds.v[cmd_idx] = n->cmd;
|
GC.submit.first_free = GC.submit.first;
|
||||||
++cmd_idx;
|
GC.submit.count = 0;
|
||||||
}
|
GC.submit.first = 0;
|
||||||
/* Reset submission queue */
|
GC.submit.last = 0;
|
||||||
GC.submit.first_free = GC.submit.first;
|
|
||||||
GC.submit.count = 0;
|
|
||||||
GC.submit.first = 0;
|
|
||||||
GC.submit.last = 0;
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
WaveSync(lane);
|
||||||
|
|
||||||
|
if (async->cmds.count > 0)
|
||||||
|
{
|
||||||
|
//////////////////////////////
|
||||||
|
//- Rasterize glyphs
|
||||||
|
|
||||||
|
/* TODO: Process cmds unevenly to account for varying work size */
|
||||||
|
|
||||||
|
{
|
||||||
|
RngU64 cmd_idxs = WaveIdxRangeFromCount(lane, async->cmds.count);
|
||||||
|
for (u64 cmd_idx = cmd_idxs.min; cmd_idx < cmd_idxs.max; ++cmd_idx)
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
ResourceKey resource = glyph->desc.font.r;
|
||||||
|
GC_GlyphDesc desc = glyph->desc;
|
||||||
|
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
|
||||||
|
glyph->font_size = desc.font_size;
|
||||||
|
glyph->font_ascent = ttf_result.font_ascent;
|
||||||
|
glyph->font_descent = ttf_result.font_descent;
|
||||||
|
glyph->font_cap = ttf_result.font_cap;
|
||||||
|
glyph->advance = ttf_result.advance;
|
||||||
|
glyph->bounds = ttf_result.bounds;
|
||||||
|
cmd->rasterized = ttf_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Only sync first lane? */
|
||||||
|
|
||||||
WaveSync(lane);
|
WaveSync(lane);
|
||||||
|
|
||||||
if (async->cmds.count > 0)
|
////////////////////////////
|
||||||
|
//- Allocate atlas slices
|
||||||
|
|
||||||
|
if (lane->idx == 0)
|
||||||
{
|
{
|
||||||
//////////////////////////////
|
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
|
||||||
//- Rasterize glyphs
|
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
GC_GlyphDesc desc = glyph->desc;
|
||||||
|
TTF_GlyphResult ttf_result = cmd->rasterized;
|
||||||
|
|
||||||
/* TODO: Process cmds unevenly to account for varying work size */
|
Vec2I32 image_dims = ttf_result.image_dims;
|
||||||
|
|
||||||
|
/* TODO: Use a more efficient atlas packing algorithm for less wasted space `*/
|
||||||
|
GC_Atlas *atlas = GC.first_atlas;
|
||||||
|
b32 can_use_atlas = 0;
|
||||||
|
Vec2I32 pos_in_atlas = Zi;
|
||||||
|
while (can_use_atlas == 0)
|
||||||
{
|
{
|
||||||
RngU64 cmd_idxs = WaveIdxRangeFromCount(lane, async->cmds.count);
|
/* Create atlas */
|
||||||
for (u64 cmd_idx = cmd_idxs.min; cmd_idx < cmd_idxs.max; ++cmd_idx)
|
if (!atlas)
|
||||||
|
{
|
||||||
|
Arena *perm = PermArena();
|
||||||
|
atlas = PushStruct(perm, GC_Atlas);
|
||||||
|
atlas->dims = VEC2I32(1024, 1024);
|
||||||
{
|
{
|
||||||
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
G_ArenaHandle gpu_perm = G_PermArena();
|
||||||
GC_Glyph *glyph = cmd->glyph;
|
atlas->tex = G_PushTexture2D(
|
||||||
ResourceKey resource = glyph->desc.font.r;
|
gpu_perm, cl,
|
||||||
GC_GlyphDesc desc = glyph->desc;
|
G_Format_R8G8B8A8_Unorm_Srgb,
|
||||||
TTF_GlyphResult ttf_result = TTF_RasterizeGlyphFromCodepoint(tick->arena, desc.codepoint, resource, desc.font_size);;
|
atlas->dims,
|
||||||
glyph->font_size = desc.font_size;
|
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
|
||||||
glyph->font_ascent = ttf_result.font_ascent;
|
);
|
||||||
glyph->font_descent = ttf_result.font_descent;
|
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex);
|
||||||
glyph->font_cap = ttf_result.font_cap;
|
|
||||||
glyph->advance = ttf_result.advance;
|
|
||||||
glyph->bounds = ttf_result.bounds;
|
|
||||||
cmd->rasterized = ttf_result;
|
|
||||||
}
|
}
|
||||||
|
SllStackPush(GC.first_atlas, atlas);
|
||||||
|
++GC.atlases_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine pos in atlas */
|
||||||
|
pos_in_atlas = atlas->cur_pos;
|
||||||
|
atlas->cur_row_height = MaxI32(atlas->cur_row_height, image_dims.y);
|
||||||
|
if (pos_in_atlas.x + image_dims.x > atlas->dims.x);
|
||||||
|
{
|
||||||
|
atlas->cur_pos.x = 0;
|
||||||
|
atlas->cur_pos.y += atlas->cur_row_height;
|
||||||
|
atlas->cur_row_height = image_dims.y;
|
||||||
|
}
|
||||||
|
atlas->cur_pos.x += image_dims.x;
|
||||||
|
if (atlas->cur_pos.x < atlas->dims.x && atlas->cur_pos.y < atlas->dims.y)
|
||||||
|
{
|
||||||
|
can_use_atlas = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atlas = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Only sync first lane? */
|
/* Atlas info */
|
||||||
|
glyph->atlas = atlas;
|
||||||
|
glyph->tex_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
|
||||||
|
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas->dims.x;
|
||||||
|
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas->dims.x;
|
||||||
|
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas->dims.x;
|
||||||
|
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas->dims.x;
|
||||||
|
|
||||||
WaveSync(lane);
|
/* Copy to atlas */
|
||||||
|
u32 *image_pixels = ttf_result.image_pixels;
|
||||||
////////////////////////////
|
if (image_dims.x > 0 && image_dims.y > 0)
|
||||||
//- Allocate atlas slices
|
|
||||||
|
|
||||||
if (lane->idx == 0)
|
|
||||||
{
|
{
|
||||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_AsyncCopy);
|
G_CopyCpuToTexture(
|
||||||
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
cl,
|
||||||
{
|
glyph->atlas->tex, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
|
||||||
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
|
||||||
GC_Glyph *glyph = cmd->glyph;
|
RNG3I32(
|
||||||
GC_GlyphDesc desc = glyph->desc;
|
VEC3I32(0, 0, 0),
|
||||||
TTF_GlyphResult ttf_result = cmd->rasterized;
|
VEC3I32(image_dims.x, image_dims.y, 1)
|
||||||
|
)
|
||||||
Vec2I32 image_dims = ttf_result.image_dims;
|
);
|
||||||
|
|
||||||
/* TODO: Use a more efficient atlas packing algorithm for less wasted space `*/
|
|
||||||
GC_Atlas *atlas = GC.first_atlas;
|
|
||||||
b32 can_use_atlas = 0;
|
|
||||||
Vec2I32 pos_in_atlas = Zi;
|
|
||||||
while (can_use_atlas == 0)
|
|
||||||
{
|
|
||||||
/* Create atlas */
|
|
||||||
if (!atlas)
|
|
||||||
{
|
|
||||||
Arena *perm = PermArena();
|
|
||||||
atlas = PushStruct(perm, GC_Atlas);
|
|
||||||
atlas->dims = VEC2I32(1024, 1024);
|
|
||||||
{
|
|
||||||
G_ArenaHandle gpu_perm = G_PermArena();
|
|
||||||
atlas->tex = G_PushTexture2D(
|
|
||||||
gpu_perm, cl,
|
|
||||||
G_Format_R8G8B8A8_Unorm_Srgb,
|
|
||||||
atlas->dims,
|
|
||||||
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present,
|
|
||||||
);
|
|
||||||
atlas->tex_ref = G_PushTexture2DRef(gpu_perm, atlas->tex);
|
|
||||||
}
|
|
||||||
SllStackPush(GC.first_atlas, atlas);
|
|
||||||
++GC.atlases_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine pos in atlas */
|
|
||||||
pos_in_atlas = atlas->cur_pos;
|
|
||||||
atlas->cur_row_height = MaxI32(atlas->cur_row_height, image_dims.y);
|
|
||||||
if (pos_in_atlas.x + image_dims.x > atlas->dims.x);
|
|
||||||
{
|
|
||||||
atlas->cur_pos.x = 0;
|
|
||||||
atlas->cur_pos.y += atlas->cur_row_height;
|
|
||||||
atlas->cur_row_height = image_dims.y;
|
|
||||||
}
|
|
||||||
atlas->cur_pos.x += image_dims.x;
|
|
||||||
if (atlas->cur_pos.x < atlas->dims.x && atlas->cur_pos.y < atlas->dims.y)
|
|
||||||
{
|
|
||||||
can_use_atlas = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
atlas = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Atlas info */
|
|
||||||
glyph->atlas = atlas;
|
|
||||||
glyph->tex_slice = RNG2I32(pos_in_atlas, AddVec2I32(pos_in_atlas, image_dims));
|
|
||||||
glyph->tex_slice_uv.p0.x = (f32)glyph->tex_slice.p0.x / (f32)atlas->dims.x;
|
|
||||||
glyph->tex_slice_uv.p0.y = (f32)glyph->tex_slice.p0.y / (f32)atlas->dims.x;
|
|
||||||
glyph->tex_slice_uv.p1.x = (f32)glyph->tex_slice.p1.x / (f32)atlas->dims.x;
|
|
||||||
glyph->tex_slice_uv.p1.y = (f32)glyph->tex_slice.p1.y / (f32)atlas->dims.x;
|
|
||||||
|
|
||||||
/* Copy to atlas */
|
|
||||||
u32 *image_pixels = ttf_result.image_pixels;
|
|
||||||
if (image_dims.x > 0 && image_dims.y > 0)
|
|
||||||
{
|
|
||||||
G_CopyCpuToTexture(
|
|
||||||
cl,
|
|
||||||
glyph->atlas->tex, VEC3I32(glyph->tex_slice.p0.x, glyph->tex_slice.p0.y, 0),
|
|
||||||
image_pixels, VEC3I32(image_dims.x, image_dims.y, 1),
|
|
||||||
RNG3I32(
|
|
||||||
VEC3I32(0, 0, 0),
|
|
||||||
VEC3I32(image_dims.x, image_dims.y, 1)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i64 completion_target = G_CommitCommandList(cl);
|
|
||||||
|
|
||||||
/* Update completion targets */
|
|
||||||
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
|
||||||
{
|
|
||||||
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
|
||||||
GC_Glyph *glyph = cmd->glyph;
|
|
||||||
Atomic64Set(&glyph->async_copy_completion_target, completion_target);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
i64 completion_target = G_CommitCommandList(cl);
|
||||||
|
|
||||||
|
/* Update completion targets */
|
||||||
|
for (u64 cmd_idx = 0; cmd_idx < async->cmds.count; ++cmd_idx)
|
||||||
|
{
|
||||||
|
GC_Cmd *cmd = &async->cmds.v[cmd_idx];
|
||||||
|
GC_Glyph *glyph = cmd->glyph;
|
||||||
|
Atomic64Set(&glyph->async_copy_completion_target, completion_target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Struct(GC_FontKey)
|
Struct(GC_FontKey)
|
||||||
{
|
{
|
||||||
ResourceKey r;
|
ResourceKey r;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -11,13 +11,13 @@ Struct(GC_FontKey)
|
|||||||
|
|
||||||
Struct(GC_Atlas)
|
Struct(GC_Atlas)
|
||||||
{
|
{
|
||||||
GC_Atlas *next;
|
GC_Atlas *next;
|
||||||
|
|
||||||
Vec2I32 dims;
|
Vec2I32 dims;
|
||||||
G_ResourceHandle tex;
|
G_ResourceHandle tex;
|
||||||
G_Texture2DRef tex_ref;
|
G_Texture2DRef tex_ref;
|
||||||
Vec2I32 cur_pos;
|
Vec2I32 cur_pos;
|
||||||
i32 cur_row_height;
|
i32 cur_row_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -25,38 +25,38 @@ Struct(GC_Atlas)
|
|||||||
|
|
||||||
Struct(GC_GlyphDesc)
|
Struct(GC_GlyphDesc)
|
||||||
{
|
{
|
||||||
GC_FontKey font;
|
GC_FontKey font;
|
||||||
f32 font_size;
|
f32 font_size;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_Glyph)
|
Struct(GC_Glyph)
|
||||||
{
|
{
|
||||||
GC_Glyph *next;
|
GC_Glyph *next;
|
||||||
|
|
||||||
GC_GlyphDesc desc;
|
GC_GlyphDesc desc;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
Atomic64 async_copy_completion_target;
|
Atomic64 async_copy_completion_target;
|
||||||
|
|
||||||
/* Font info */
|
/* Font info */
|
||||||
f32 font_size;
|
f32 font_size;
|
||||||
f32 font_ascent;
|
f32 font_ascent;
|
||||||
f32 font_descent;
|
f32 font_descent;
|
||||||
f32 font_cap;
|
f32 font_cap;
|
||||||
|
|
||||||
/* Layout info */
|
/* Layout info */
|
||||||
f32 advance;
|
f32 advance;
|
||||||
Rng2 bounds;
|
Rng2 bounds;
|
||||||
|
|
||||||
/* Atlas info */
|
/* Atlas info */
|
||||||
GC_Atlas *atlas;
|
GC_Atlas *atlas;
|
||||||
Rng2I32 tex_slice;
|
Rng2I32 tex_slice;
|
||||||
Rng2 tex_slice_uv;
|
Rng2 tex_slice_uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_GlyphBin)
|
Struct(GC_GlyphBin)
|
||||||
{
|
{
|
||||||
GC_Glyph *first;
|
GC_Glyph *first;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -64,30 +64,30 @@ Struct(GC_GlyphBin)
|
|||||||
|
|
||||||
Struct(GC_RunRect)
|
Struct(GC_RunRect)
|
||||||
{
|
{
|
||||||
Rng2 bounds; /* Visual bounds in relation to the baseline */
|
Rng2 bounds; /* Visual bounds in relation to the baseline */
|
||||||
f32 baseline_pos; /* Horizontal distance from start of baseline */
|
f32 baseline_pos; /* Horizontal distance from start of baseline */
|
||||||
f32 advance;
|
f32 advance;
|
||||||
|
|
||||||
G_Texture2DRef tex;
|
G_Texture2DRef tex;
|
||||||
Rng2I32 tex_slice;
|
Rng2I32 tex_slice;
|
||||||
Rng2 tex_slice_uv;
|
Rng2 tex_slice_uv;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_Run)
|
Struct(GC_Run)
|
||||||
{
|
{
|
||||||
/* Run data */
|
/* Run data */
|
||||||
Rng2 bounds; /* Visual bounds of the run in relation to the baseline */
|
Rng2 bounds; /* Visual bounds of the run in relation to the baseline */
|
||||||
f32 baseline_length;
|
f32 baseline_length;
|
||||||
u64 rects_count;
|
u64 rects_count;
|
||||||
GC_RunRect *rects;
|
GC_RunRect *rects;
|
||||||
|
|
||||||
/* Font info */
|
/* Font info */
|
||||||
f32 font_size;
|
f32 font_size;
|
||||||
f32 font_ascent;
|
f32 font_ascent;
|
||||||
f32 font_descent;
|
f32 font_descent;
|
||||||
f32 font_cap;
|
f32 font_cap;
|
||||||
|
|
||||||
b32 ready;
|
b32 ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -95,16 +95,16 @@ Struct(GC_Run)
|
|||||||
|
|
||||||
Struct(GC_Cmd)
|
Struct(GC_Cmd)
|
||||||
{
|
{
|
||||||
GC_Glyph *glyph;
|
GC_Glyph *glyph;
|
||||||
|
|
||||||
/* Async temporary data */
|
/* Async temporary data */
|
||||||
TTF_GlyphResult rasterized;
|
TTF_GlyphResult rasterized;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_CmdNode)
|
Struct(GC_CmdNode)
|
||||||
{
|
{
|
||||||
GC_CmdNode *next;
|
GC_CmdNode *next;
|
||||||
GC_Cmd cmd;
|
GC_Cmd cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -112,31 +112,31 @@ Struct(GC_CmdNode)
|
|||||||
|
|
||||||
Struct(GC_AsyncCtx)
|
Struct(GC_AsyncCtx)
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
GC_Cmd *v;
|
GC_Cmd *v;
|
||||||
} cmds;
|
} cmds;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GC_Ctx)
|
Struct(GC_Ctx)
|
||||||
{
|
{
|
||||||
Mutex glyphs_mutex;
|
Mutex glyphs_mutex;
|
||||||
GC_GlyphBin glyph_bins[16384];
|
GC_GlyphBin glyph_bins[16384];
|
||||||
|
|
||||||
u64 atlases_count;
|
u64 atlases_count;
|
||||||
GC_Atlas *first_atlas;
|
GC_Atlas *first_atlas;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
u64 count;
|
u64 count;
|
||||||
GC_CmdNode *first;
|
GC_CmdNode *first;
|
||||||
GC_CmdNode *last;
|
GC_CmdNode *last;
|
||||||
GC_CmdNode *first_free;
|
GC_CmdNode *first_free;
|
||||||
} submit;
|
} submit;
|
||||||
|
|
||||||
GC_AsyncCtx async_ctx;
|
GC_AsyncCtx async_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GC_Ctx GC;
|
extern GC_Ctx GC;
|
||||||
|
|||||||
@ -6,57 +6,57 @@ ThreadLocal G_ArenaHandle G_t_perm_arena = Zi;
|
|||||||
|
|
||||||
void G_BootstrapCommon(void)
|
void G_BootstrapCommon(void)
|
||||||
{
|
{
|
||||||
G_SharedUtilState *g = &G_shared_util_state;
|
G_SharedUtilState *g = &G_shared_util_state;
|
||||||
|
|
||||||
G_ArenaHandle gpu_perm = G_PermArena();
|
G_ArenaHandle gpu_perm = G_PermArena();
|
||||||
|
|
||||||
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
G_CommandListHandle cl = G_PrepareCommandList(G_QueueKind_Direct);
|
||||||
|
{
|
||||||
|
/* Init quad index buffer */
|
||||||
{
|
{
|
||||||
/* Init quad index buffer */
|
G_ResourceHandle quad_indices = Zi;
|
||||||
{
|
u16 quad_data[6] = { 0, 1, 2, 0, 2, 3 };
|
||||||
G_ResourceHandle quad_indices = Zi;
|
quad_indices = G_PushBuffer(gpu_perm, cl, u16, countof(quad_data));
|
||||||
u16 quad_data[6] = { 0, 1, 2, 0, 2, 3 };
|
G_CopyCpuToBuffer(cl, quad_indices, 0, quad_data, RNGU64(0, sizeof(quad_data)));
|
||||||
quad_indices = G_PushBuffer(gpu_perm, cl, u16, countof(quad_data));
|
g->quad_indices = G_IdxBuff16(quad_indices);
|
||||||
G_CopyCpuToBuffer(cl, quad_indices, 0, quad_data, RNGU64(0, sizeof(quad_data)));
|
|
||||||
g->quad_indices = G_IdxBuff16(quad_indices);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init point sampler */
|
|
||||||
{
|
|
||||||
G_ResourceHandle pt_sampler = G_PushSampler(gpu_perm, cl, .filter = G_Filter_MinMagMipPoint);
|
|
||||||
g->basic_sampler = G_PushSamplerStateRef(gpu_perm, pt_sampler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init noise texture */
|
|
||||||
{
|
|
||||||
G_ResourceHandle noise_tex = Zi;
|
|
||||||
String noise_data = DataFromResource(ResourceKeyFromStore(&G_Resources, Lit("noise_128x128x64_16.dat")));
|
|
||||||
Vec3I32 noise_dims = VEC3I32(128, 128, 64);
|
|
||||||
if (noise_data.len != noise_dims.x * noise_dims.y * noise_dims.z * 2)
|
|
||||||
{
|
|
||||||
Panic(Lit("Unexpected noise texture size"));
|
|
||||||
}
|
|
||||||
noise_tex = G_PushTexture3D(
|
|
||||||
gpu_perm, cl,
|
|
||||||
G_Format_R16_Uint,
|
|
||||||
noise_dims,
|
|
||||||
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present
|
|
||||||
);
|
|
||||||
G_CopyCpuToTexture(
|
|
||||||
cl,
|
|
||||||
noise_tex, VEC3I32(0, 0, 0),
|
|
||||||
noise_data.text, noise_dims,
|
|
||||||
RNG3I32(VEC3I32(0, 0, 0), noise_dims)
|
|
||||||
);
|
|
||||||
|
|
||||||
g->basic_noise = G_PushTexture3DRef(gpu_perm, noise_tex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
G_CommitCommandList(cl);
|
|
||||||
|
|
||||||
/* Barrier all queues until direct queue finishes initializing resources */
|
/* Init point sampler */
|
||||||
G_Sync(G_QueueMask_Direct, G_QueueMask_All);
|
{
|
||||||
|
G_ResourceHandle pt_sampler = G_PushSampler(gpu_perm, cl, .filter = G_Filter_MinMagMipPoint);
|
||||||
|
g->basic_sampler = G_PushSamplerStateRef(gpu_perm, pt_sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init noise texture */
|
||||||
|
{
|
||||||
|
G_ResourceHandle noise_tex = Zi;
|
||||||
|
String noise_data = DataFromResource(ResourceKeyFromStore(&G_Resources, Lit("noise_128x128x64_16.dat")));
|
||||||
|
Vec3I32 noise_dims = VEC3I32(128, 128, 64);
|
||||||
|
if (noise_data.len != noise_dims.x * noise_dims.y * noise_dims.z * 2)
|
||||||
|
{
|
||||||
|
Panic(Lit("Unexpected noise texture size"));
|
||||||
|
}
|
||||||
|
noise_tex = G_PushTexture3D(
|
||||||
|
gpu_perm, cl,
|
||||||
|
G_Format_R16_Uint,
|
||||||
|
noise_dims,
|
||||||
|
G_Layout_AnyQueue_ShaderRead_CopyRead_CopyWrite_Present
|
||||||
|
);
|
||||||
|
G_CopyCpuToTexture(
|
||||||
|
cl,
|
||||||
|
noise_tex, VEC3I32(0, 0, 0),
|
||||||
|
noise_data.text, noise_dims,
|
||||||
|
RNG3I32(VEC3I32(0, 0, 0), noise_dims)
|
||||||
|
);
|
||||||
|
|
||||||
|
g->basic_noise = G_PushTexture3DRef(gpu_perm, noise_tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
G_CommitCommandList(cl);
|
||||||
|
|
||||||
|
/* Barrier all queues until direct queue finishes initializing resources */
|
||||||
|
G_Sync(G_QueueMask_Direct, G_QueueMask_All);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -66,56 +66,56 @@ void G_BootstrapCommon(void)
|
|||||||
|
|
||||||
G_ArenaHandle G_PermArena(void)
|
G_ArenaHandle G_PermArena(void)
|
||||||
{
|
{
|
||||||
G_ArenaHandle perm = G_t_perm_arena;
|
G_ArenaHandle perm = G_t_perm_arena;
|
||||||
if (G_IsArenaNil(perm))
|
if (G_IsArenaNil(perm))
|
||||||
{
|
{
|
||||||
G_t_perm_arena = G_AcquireArena();
|
G_t_perm_arena = G_AcquireArena();
|
||||||
perm = G_t_perm_arena;
|
perm = G_t_perm_arena;
|
||||||
}
|
}
|
||||||
return perm;
|
return perm;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Cpu -> Gpu upload
|
//- Cpu -> Gpu upload
|
||||||
|
|
||||||
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc)
|
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc)
|
||||||
{
|
{
|
||||||
G_ResourceHandle buffer = G_PushResource(gpu_arena, cl, (G_ResourceDesc) { .kind = G_ResourceKind_Buffer, .buffer = desc });
|
G_ResourceHandle buffer = G_PushResource(gpu_arena, cl, (G_ResourceDesc) { .kind = G_ResourceKind_Buffer, .buffer = desc });
|
||||||
G_CopyCpuToBuffer(cl, buffer, 0, src.text, RNGU64(0, src.len));
|
G_CopyCpuToBuffer(cl, buffer, 0, src.text, RNGU64(0, src.len));
|
||||||
G_MemorySync(
|
G_MemorySync(
|
||||||
cl, buffer,
|
cl, buffer,
|
||||||
G_Stage_Copy, G_Access_CopyWrite,
|
G_Stage_Copy, G_Access_CopyWrite,
|
||||||
G_Stage_All, G_Access_All
|
G_Stage_All, G_Access_All
|
||||||
);
|
);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Viewport / scissor
|
//- Viewport / scissor
|
||||||
|
|
||||||
Rng3 G_ViewportFromTexture(G_ResourceHandle texture)
|
Rng3 G_ViewportFromTexture(G_ResourceHandle texture)
|
||||||
{
|
{
|
||||||
Vec2I32 dims = G_Count2D(texture);
|
Vec2I32 dims = G_Count2D(texture);
|
||||||
return RNG3(VEC3(0, 0, 0), VEC3(dims.x, dims.y, 1));
|
return RNG3(VEC3(0, 0, 0), VEC3(dims.x, dims.y, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
Rng2 G_ScissorFromTexture(G_ResourceHandle texture)
|
Rng2 G_ScissorFromTexture(G_ResourceHandle texture)
|
||||||
{
|
{
|
||||||
Vec2I32 dims = G_Count2D(texture);
|
Vec2I32 dims = G_Count2D(texture);
|
||||||
return RNG2(VEC2(0, 0), VEC2(dims.x, dims.y));
|
return RNG2(VEC2(0, 0), VEC2(dims.x, dims.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Shared resources
|
//- Shared resources
|
||||||
|
|
||||||
G_IndexBufferDesc G_QuadIndices(void)
|
G_IndexBufferDesc G_QuadIndices(void)
|
||||||
{
|
{
|
||||||
return G_shared_util_state.quad_indices;
|
return G_shared_util_state.quad_indices;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_SamplerStateRef G_BasicSampler(void)
|
G_SamplerStateRef G_BasicSampler(void)
|
||||||
{
|
{
|
||||||
return G_shared_util_state.basic_sampler;
|
return G_shared_util_state.basic_sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_Texture3DRef G_BasicNoiseTexture(void)
|
G_Texture3DRef G_BasicNoiseTexture(void)
|
||||||
{
|
{
|
||||||
return G_shared_util_state.basic_noise;
|
return G_shared_util_state.basic_noise;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
Struct(G_SharedUtilState)
|
Struct(G_SharedUtilState)
|
||||||
{
|
{
|
||||||
/* Common shared resources */
|
/* Common shared resources */
|
||||||
G_IndexBufferDesc quad_indices;
|
G_IndexBufferDesc quad_indices;
|
||||||
G_SamplerStateRef basic_sampler;
|
G_SamplerStateRef basic_sampler;
|
||||||
G_Texture3DRef basic_noise;
|
G_Texture3DRef basic_noise;
|
||||||
} extern G_shared_util_state;
|
} extern G_shared_util_state;
|
||||||
|
|
||||||
extern ThreadLocal G_ArenaHandle G_t_perm_arena;
|
extern ThreadLocal G_ArenaHandle G_t_perm_arena;
|
||||||
@ -27,7 +27,7 @@ G_ArenaHandle G_PermArena(void);
|
|||||||
|
|
||||||
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc);
|
G_ResourceHandle G_PushBufferFromString_(G_ArenaHandle gpu_arena, G_CommandListHandle cl, String src, G_BufferDesc desc);
|
||||||
#define G_PushBufferFromString(_arena, _cl, _src, ...) \
|
#define G_PushBufferFromString(_arena, _cl, _src, ...) \
|
||||||
G_PushBufferFromString_((_arena), (_cl), (_src), (G_BufferDesc) { .size = (_src).len, __VA_ARGS__ })
|
G_PushBufferFromString_((_arena), (_cl), (_src), (G_BufferDesc) { .size = (_src).len, __VA_ARGS__ })
|
||||||
|
|
||||||
//- Viewport / scissor
|
//- Viewport / scissor
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2,9 +2,9 @@
|
|||||||
//~ DirectX12 libs
|
//~ DirectX12 libs
|
||||||
|
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
# include <d3d12.h>
|
#include <d3d12.h>
|
||||||
# include <dxgidebug.h>
|
#include <dxgidebug.h>
|
||||||
# include <dxgi1_6.h>
|
#include <dxgi1_6.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#pragma comment(lib, "d3d12")
|
#pragma comment(lib, "d3d12")
|
||||||
@ -16,9 +16,10 @@
|
|||||||
#define G_D12_TearingIsAllowed 1
|
#define G_D12_TearingIsAllowed 1
|
||||||
#define G_D12_FrameLatency 1
|
#define G_D12_FrameLatency 1
|
||||||
#define G_D12_SwapchainBufferCount 3
|
#define G_D12_SwapchainBufferCount 3
|
||||||
#define G_D12_SwapchainFlags (((G_D12_TearingIsAllowed != 0) * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) \
|
#define G_D12_SwapchainFlags (0 \
|
||||||
| ((G_D12_FrameLatency != 0) * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
|
| ((G_D12_TearingIsAllowed != 0) * DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING) \
|
||||||
|
| ((G_D12_FrameLatency != 0) * DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) \
|
||||||
|
)
|
||||||
|
|
||||||
#define G_D12_MaxCbvSrvUavDescriptors (1024 * 128)
|
#define G_D12_MaxCbvSrvUavDescriptors (1024 * 128)
|
||||||
#define G_D12_MaxSamplerDescriptors (1024 * 1)
|
#define G_D12_MaxSamplerDescriptors (1024 * 1)
|
||||||
@ -29,30 +30,30 @@
|
|||||||
|
|
||||||
Struct(G_D12_PipelineDesc)
|
Struct(G_D12_PipelineDesc)
|
||||||
{
|
{
|
||||||
VertexShader vs;
|
VertexShader vs;
|
||||||
PixelShader ps;
|
PixelShader ps;
|
||||||
ComputeShader cs;
|
ComputeShader cs;
|
||||||
b32 is_wireframe;
|
b32 is_wireframe;
|
||||||
D3D12_PRIMITIVE_TOPOLOGY_TYPE topology_type;
|
D3D12_PRIMITIVE_TOPOLOGY_TYPE topology_type;
|
||||||
G_Format render_target_formats[G_MaxRenderTargets];
|
G_Format render_target_formats[G_MaxRenderTargets];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_Pipeline)
|
Struct(G_D12_Pipeline)
|
||||||
{
|
{
|
||||||
G_D12_Pipeline *next_in_bin;
|
G_D12_Pipeline *next_in_bin;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
|
|
||||||
G_D12_PipelineDesc desc;
|
G_D12_PipelineDesc desc;
|
||||||
ID3D12PipelineState *pso;
|
ID3D12PipelineState *pso;
|
||||||
|
|
||||||
b32 ok;
|
b32 ok;
|
||||||
String error;
|
String error;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_PipelineBin)
|
Struct(G_D12_PipelineBin)
|
||||||
{
|
{
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
G_D12_Pipeline *first;
|
G_D12_Pipeline *first;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -60,40 +61,40 @@ Struct(G_D12_PipelineBin)
|
|||||||
|
|
||||||
Struct(G_D12_Resource)
|
Struct(G_D12_Resource)
|
||||||
{
|
{
|
||||||
G_D12_Resource *next;
|
G_D12_Resource *next;
|
||||||
|
|
||||||
struct G_D12_ResourceHeap *heap;
|
struct G_D12_ResourceHeap *heap;
|
||||||
u64 pos_in_heap;
|
u64 pos_in_heap;
|
||||||
u64 size_in_heap;
|
u64 size_in_heap;
|
||||||
|
|
||||||
ID3D12Resource *d3d_resource;
|
ID3D12Resource *d3d_resource;
|
||||||
u64 uid;
|
u64 uid;
|
||||||
G_ResourceFlag flags;
|
G_ResourceFlag flags;
|
||||||
|
|
||||||
/* Buffer info */
|
/* Buffer info */
|
||||||
u64 buffer_size;
|
u64 buffer_size;
|
||||||
u64 buffer_size_actual;
|
u64 buffer_size_actual;
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
|
D3D12_GPU_VIRTUAL_ADDRESS buffer_gpu_address;
|
||||||
|
|
||||||
/* Texture info */
|
/* Texture info */
|
||||||
b32 is_texture;
|
b32 is_texture;
|
||||||
G_Format texture_format;
|
G_Format texture_format;
|
||||||
Vec3I32 texture_dims;
|
Vec3I32 texture_dims;
|
||||||
i32 texture_mip_levels;
|
i32 texture_mip_levels;
|
||||||
D3D12_BARRIER_LAYOUT texture_layout;
|
D3D12_BARRIER_LAYOUT texture_layout;
|
||||||
|
|
||||||
/* Sampler info */
|
/* Sampler info */
|
||||||
G_SamplerDesc sampler_desc;
|
G_SamplerDesc sampler_desc;
|
||||||
|
|
||||||
/* Backbuffer info */
|
/* Backbuffer info */
|
||||||
struct G_D12_Swapchain *swapchain;
|
struct G_D12_Swapchain *swapchain;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_ResourceList)
|
Struct(G_D12_ResourceList)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
G_D12_Resource *first;
|
G_D12_Resource *first;
|
||||||
G_D12_Resource *last;
|
G_D12_Resource *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -101,46 +102,46 @@ Struct(G_D12_ResourceList)
|
|||||||
|
|
||||||
Enum(G_D12_DescriptorHeapKind)
|
Enum(G_D12_DescriptorHeapKind)
|
||||||
{
|
{
|
||||||
G_D12_DescriptorHeapKind_CbvSrvUav,
|
G_D12_DescriptorHeapKind_CbvSrvUav,
|
||||||
G_D12_DescriptorHeapKind_Rtv,
|
G_D12_DescriptorHeapKind_Rtv,
|
||||||
G_D12_DescriptorHeapKind_Sampler,
|
G_D12_DescriptorHeapKind_Sampler,
|
||||||
|
|
||||||
G_D12_DescriptorHeapKind_Count
|
G_D12_DescriptorHeapKind_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_DescriptorHeap)
|
Struct(G_D12_DescriptorHeap)
|
||||||
{
|
{
|
||||||
Arena *descriptors_arena;
|
Arena *descriptors_arena;
|
||||||
G_D12_DescriptorHeapKind kind;
|
G_D12_DescriptorHeapKind kind;
|
||||||
|
|
||||||
D3D12_DESCRIPTOR_HEAP_TYPE type;
|
D3D12_DESCRIPTOR_HEAP_TYPE type;
|
||||||
u32 descriptor_size;
|
u32 descriptor_size;
|
||||||
ID3D12DescriptorHeap *d3d_heap;
|
ID3D12DescriptorHeap *d3d_heap;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE start_handle;
|
D3D12_CPU_DESCRIPTOR_HANDLE start_handle;
|
||||||
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
struct G_D12_Descriptor *first_free;
|
struct G_D12_Descriptor *first_free;
|
||||||
u32 max_count;
|
u32 max_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_Descriptor)
|
Struct(G_D12_Descriptor)
|
||||||
{
|
{
|
||||||
G_D12_Descriptor *next;
|
G_D12_Descriptor *next;
|
||||||
|
|
||||||
struct G_D12_Arena *gpu_arena;
|
struct G_D12_Arena *gpu_arena;
|
||||||
G_QueueKind completion_queue_kind;
|
G_QueueKind completion_queue_kind;
|
||||||
i64 completion_queue_target;
|
i64 completion_queue_target;
|
||||||
|
|
||||||
G_D12_DescriptorHeap *heap;
|
G_D12_DescriptorHeap *heap;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE handle;
|
D3D12_CPU_DESCRIPTOR_HANDLE handle;
|
||||||
u32 index;
|
u32 index;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_DescriptorList)
|
Struct(G_D12_DescriptorList)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
G_D12_Descriptor *first;
|
G_D12_Descriptor *first;
|
||||||
G_D12_Descriptor *last;
|
G_D12_Descriptor *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -154,40 +155,40 @@ Struct(G_D12_DescriptorList)
|
|||||||
*/
|
*/
|
||||||
Enum(G_D12_ResourceHeapKind)
|
Enum(G_D12_ResourceHeapKind)
|
||||||
{
|
{
|
||||||
G_D12_ResourceHeapKind_Gpu,
|
G_D12_ResourceHeapKind_Gpu,
|
||||||
G_D12_ResourceHeapKind_Cpu,
|
G_D12_ResourceHeapKind_Cpu,
|
||||||
G_D12_ResourceHeapKind_CpuWriteCombined,
|
G_D12_ResourceHeapKind_CpuWriteCombined,
|
||||||
|
|
||||||
G_D12_ResourceHeapKind_Count,
|
G_D12_ResourceHeapKind_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_ResourceHeap)
|
Struct(G_D12_ResourceHeap)
|
||||||
{
|
{
|
||||||
G_D12_ResourceHeapKind kind;
|
G_D12_ResourceHeapKind kind;
|
||||||
|
|
||||||
struct GPU_D12_Arena *gpu_arena;
|
struct GPU_D12_Arena *gpu_arena;
|
||||||
|
|
||||||
ID3D12Heap *d3d_heap;
|
ID3D12Heap *d3d_heap;
|
||||||
ID3D12Resource *d3d_mapped_resource;
|
ID3D12Resource *d3d_mapped_resource;
|
||||||
void *mapped;
|
void *mapped;
|
||||||
|
|
||||||
G_D12_ResourceList resources;
|
G_D12_ResourceList resources;
|
||||||
G_D12_ResourceList reset_resources;
|
G_D12_ResourceList reset_resources;
|
||||||
|
|
||||||
u64 pos;
|
u64 pos;
|
||||||
u64 size;
|
u64 size;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_Arena)
|
Struct(G_D12_Arena)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
G_D12_DescriptorList descriptors;
|
G_D12_DescriptorList descriptors;
|
||||||
G_D12_DescriptorList reset_descriptors_by_heap[G_D12_DescriptorHeapKind_Count];
|
G_D12_DescriptorList reset_descriptors_by_heap[G_D12_DescriptorHeapKind_Count];
|
||||||
|
|
||||||
G_D12_ResourceList free_resources;
|
G_D12_ResourceList free_resources;
|
||||||
|
|
||||||
G_D12_ResourceHeap resource_heaps[G_D12_ResourceHeapKind_Count];
|
G_D12_ResourceHeap resource_heaps[G_D12_ResourceHeapKind_Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -195,32 +196,32 @@ Struct(G_D12_Arena)
|
|||||||
|
|
||||||
Struct(G_D12_StagingRing)
|
Struct(G_D12_StagingRing)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
G_D12_Arena *gpu_arena;
|
G_D12_Arena *gpu_arena;
|
||||||
u64 size;
|
u64 size;
|
||||||
|
|
||||||
G_D12_Resource *resource;
|
G_D12_Resource *resource;
|
||||||
u8 *base;
|
u8 *base;
|
||||||
|
|
||||||
struct G_D12_StagingRegionNode *head_region_node;
|
struct G_D12_StagingRegionNode *head_region_node;
|
||||||
struct G_D12_StagingRegionNode *first_free_region_node;
|
struct G_D12_StagingRegionNode *first_free_region_node;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_StagingRegionNode)
|
Struct(G_D12_StagingRegionNode)
|
||||||
{
|
{
|
||||||
G_D12_StagingRing *ring;
|
G_D12_StagingRing *ring;
|
||||||
|
|
||||||
/* Ring links (requires ring lock to read) */
|
/* Ring links (requires ring lock to read) */
|
||||||
G_D12_StagingRegionNode *prev;
|
G_D12_StagingRegionNode *prev;
|
||||||
G_D12_StagingRegionNode *next;
|
G_D12_StagingRegionNode *next;
|
||||||
|
|
||||||
/* Command list links */
|
/* Command list links */
|
||||||
G_D12_StagingRegionNode *next_in_command_list;
|
G_D12_StagingRegionNode *next_in_command_list;
|
||||||
|
|
||||||
/* Region info */
|
/* Region info */
|
||||||
Atomic64 completion_target;
|
Atomic64 completion_target;
|
||||||
u64 pos;
|
u64 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -228,34 +229,34 @@ Struct(G_D12_StagingRegionNode)
|
|||||||
|
|
||||||
Struct(G_D12_CommandQueueDesc)
|
Struct(G_D12_CommandQueueDesc)
|
||||||
{
|
{
|
||||||
D3D12_COMMAND_LIST_TYPE type;
|
D3D12_COMMAND_LIST_TYPE type;
|
||||||
D3D12_COMMAND_QUEUE_PRIORITY priority;
|
D3D12_COMMAND_QUEUE_PRIORITY priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_Queue)
|
Struct(G_D12_Queue)
|
||||||
{
|
{
|
||||||
ID3D12CommandQueue *d3d_queue;
|
ID3D12CommandQueue *d3d_queue;
|
||||||
G_D12_CommandQueueDesc desc;
|
G_D12_CommandQueueDesc desc;
|
||||||
|
|
||||||
Mutex commit_mutex;
|
Mutex commit_mutex;
|
||||||
ID3D12Fence *commit_fence;
|
ID3D12Fence *commit_fence;
|
||||||
u64 commit_fence_target;
|
u64 commit_fence_target;
|
||||||
|
|
||||||
/* Global resources */
|
/* Global resources */
|
||||||
u64 print_buffer_size;
|
u64 print_buffer_size;
|
||||||
G_ResourceHandle print_buffer;
|
G_ResourceHandle print_buffer;
|
||||||
G_ResourceHandle print_readback_buffer;
|
G_ResourceHandle print_readback_buffer;
|
||||||
G_RWByteAddressBufferRef print_buffer_ref;
|
G_RWByteAddressBufferRef print_buffer_ref;
|
||||||
|
|
||||||
/* Raw command lists */
|
/* Raw command lists */
|
||||||
struct G_D12_RawCommandList *first_committed_cl;
|
struct G_D12_RawCommandList *first_committed_cl;
|
||||||
struct G_D12_RawCommandList *last_committed_cl;
|
struct G_D12_RawCommandList *last_committed_cl;
|
||||||
|
|
||||||
/* Staging heap */
|
/* Staging heap */
|
||||||
Mutex staging_mutex;
|
Mutex staging_mutex;
|
||||||
G_D12_StagingRing *staging_ring;
|
G_D12_StagingRing *staging_ring;
|
||||||
|
|
||||||
Fence sync_fence;
|
Fence sync_fence;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -263,17 +264,17 @@ Struct(G_D12_Queue)
|
|||||||
|
|
||||||
Struct(G_D12_RawCommandList)
|
Struct(G_D12_RawCommandList)
|
||||||
{
|
{
|
||||||
G_D12_Queue *queue;
|
G_D12_Queue *queue;
|
||||||
G_D12_RawCommandList *next;
|
G_D12_RawCommandList *next;
|
||||||
|
|
||||||
u64 commit_fence_target;
|
u64 commit_fence_target;
|
||||||
|
|
||||||
ID3D12CommandAllocator *d3d_ca;
|
ID3D12CommandAllocator *d3d_ca;
|
||||||
ID3D12GraphicsCommandList7 *d3d_cl;
|
ID3D12GraphicsCommandList7 *d3d_cl;
|
||||||
|
|
||||||
/* Direct queue command lists keep a constant list of CPU-only descriptors */
|
/* Direct queue command lists keep a constant list of CPU-only descriptors */
|
||||||
G_D12_Descriptor *rtv_descriptors[G_MaxRenderTargets];
|
G_D12_Descriptor *rtv_descriptors[G_MaxRenderTargets];
|
||||||
G_D12_Descriptor *rtv_clear_descriptor;
|
G_D12_Descriptor *rtv_clear_descriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -283,108 +284,108 @@ Struct(G_D12_RawCommandList)
|
|||||||
|
|
||||||
Enum(G_D12_CmdKind)
|
Enum(G_D12_CmdKind)
|
||||||
{
|
{
|
||||||
G_D12_CmdKind_None,
|
G_D12_CmdKind_None,
|
||||||
G_D12_CmdKind_Barrier,
|
G_D12_CmdKind_Barrier,
|
||||||
G_D12_CmdKind_Constant,
|
G_D12_CmdKind_Constant,
|
||||||
G_D12_CmdKind_CopyBytes,
|
G_D12_CmdKind_CopyBytes,
|
||||||
G_D12_CmdKind_CopyTexels,
|
G_D12_CmdKind_CopyTexels,
|
||||||
G_D12_CmdKind_Compute,
|
G_D12_CmdKind_Compute,
|
||||||
G_D12_CmdKind_Rasterize,
|
G_D12_CmdKind_Rasterize,
|
||||||
G_D12_CmdKind_ClearRtv,
|
G_D12_CmdKind_ClearRtv,
|
||||||
G_D12_CmdKind_DiscardRtv,
|
G_D12_CmdKind_DiscardRtv,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_Cmd)
|
Struct(G_D12_Cmd)
|
||||||
{
|
{
|
||||||
G_D12_CmdKind kind;
|
G_D12_CmdKind kind;
|
||||||
b32 skip;
|
b32 skip;
|
||||||
union
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
struct
|
i32 slot;
|
||||||
{
|
u32 value;
|
||||||
i32 slot;
|
} constant;
|
||||||
u32 value;
|
|
||||||
} constant;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
G_MemoryBarrierDesc desc;
|
G_MemoryBarrierDesc desc;
|
||||||
|
|
||||||
/* Post-batch data */
|
/* Post-batch data */
|
||||||
b32 is_end_of_batch;
|
b32 is_end_of_batch;
|
||||||
u64 batch_gen;
|
u64 batch_gen;
|
||||||
} barrier;
|
} barrier;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
G_D12_Resource *dst;
|
G_D12_Resource *dst;
|
||||||
G_D12_Resource *src;
|
G_D12_Resource *src;
|
||||||
u64 dst_offset;
|
u64 dst_offset;
|
||||||
RngU64 src_range;
|
RngU64 src_range;
|
||||||
} copy_bytes;
|
} copy_bytes;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
G_D12_Resource *dst;
|
G_D12_Resource *dst;
|
||||||
G_D12_Resource *src;
|
G_D12_Resource *src;
|
||||||
D3D12_TEXTURE_COPY_LOCATION dst_loc;
|
D3D12_TEXTURE_COPY_LOCATION dst_loc;
|
||||||
D3D12_TEXTURE_COPY_LOCATION src_loc;
|
D3D12_TEXTURE_COPY_LOCATION src_loc;
|
||||||
Vec3I32 dst_texture_offset;
|
Vec3I32 dst_texture_offset;
|
||||||
Rng3I32 src_texture_range;
|
Rng3I32 src_texture_range;
|
||||||
} copy_texels;
|
} copy_texels;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
ComputeShader cs;
|
ComputeShader cs;
|
||||||
Vec3I32 groups;
|
Vec3I32 groups;
|
||||||
} compute;
|
} compute;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
VertexShader vs;
|
VertexShader vs;
|
||||||
PixelShader ps;
|
PixelShader ps;
|
||||||
u32 instances_count;
|
u32 instances_count;
|
||||||
G_IndexBufferDesc index_buffer_desc;
|
G_IndexBufferDesc index_buffer_desc;
|
||||||
G_D12_Resource *render_targets[G_MaxRenderTargets];
|
G_D12_Resource *render_targets[G_MaxRenderTargets];
|
||||||
Rng3 viewport;
|
Rng3 viewport;
|
||||||
Rng2 scissor;
|
Rng2 scissor;
|
||||||
G_RasterMode mode;
|
G_RasterMode mode;
|
||||||
} rasterize;
|
} rasterize;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
G_D12_Resource *render_target;
|
G_D12_Resource *render_target;
|
||||||
Vec4 color;
|
Vec4 color;
|
||||||
} clear_rtv;
|
} clear_rtv;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
G_D12_Resource *render_target;
|
G_D12_Resource *render_target;
|
||||||
} discard_rtv;
|
} discard_rtv;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_CmdChunk)
|
Struct(G_D12_CmdChunk)
|
||||||
{
|
{
|
||||||
G_D12_CmdChunk *next;
|
G_D12_CmdChunk *next;
|
||||||
struct G_D12_CmdList *cl;
|
struct G_D12_CmdList *cl;
|
||||||
G_D12_Cmd *cmds;
|
G_D12_Cmd *cmds;
|
||||||
u64 cmds_count;
|
u64 cmds_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_D12_CmdList)
|
Struct(G_D12_CmdList)
|
||||||
{
|
{
|
||||||
G_D12_CmdList *next;
|
G_D12_CmdList *next;
|
||||||
G_QueueKind queue_kind;
|
G_QueueKind queue_kind;
|
||||||
|
|
||||||
G_D12_DescriptorList reset_descriptors;
|
G_D12_DescriptorList reset_descriptors;
|
||||||
G_D12_StagingRegionNode *first_staging_region;
|
G_D12_StagingRegionNode *first_staging_region;
|
||||||
G_D12_StagingRegionNode *last_staging_region;
|
G_D12_StagingRegionNode *last_staging_region;
|
||||||
|
|
||||||
G_D12_CmdChunk *first_cmd_chunk;
|
G_D12_CmdChunk *first_cmd_chunk;
|
||||||
G_D12_CmdChunk *last_cmd_chunk;
|
G_D12_CmdChunk *last_cmd_chunk;
|
||||||
u64 chunks_count;
|
u64 chunks_count;
|
||||||
u64 cmds_count;
|
u64 cmds_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -393,17 +394,17 @@ Struct(G_D12_CmdList)
|
|||||||
Struct(G_D12_Swapchain)
|
Struct(G_D12_Swapchain)
|
||||||
{
|
{
|
||||||
|
|
||||||
IDXGISwapChain3 *d3d_swapchain;
|
IDXGISwapChain3 *d3d_swapchain;
|
||||||
HWND window_hwnd;
|
HWND window_hwnd;
|
||||||
HANDLE waitable;
|
HANDLE waitable;
|
||||||
|
|
||||||
HANDLE present_event;
|
HANDLE present_event;
|
||||||
ID3D12Fence *present_fence;
|
ID3D12Fence *present_fence;
|
||||||
u64 present_fence_target;
|
u64 present_fence_target;
|
||||||
|
|
||||||
G_Format backbuffers_format;
|
G_Format backbuffers_format;
|
||||||
Vec2I32 backbuffers_resolution;
|
Vec2I32 backbuffers_resolution;
|
||||||
G_D12_Resource backbuffers[G_D12_SwapchainBufferCount];
|
G_D12_Resource backbuffers[G_D12_SwapchainBufferCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -411,45 +412,45 @@ Struct(G_D12_Swapchain)
|
|||||||
|
|
||||||
Struct(G_D12_SharedState)
|
Struct(G_D12_SharedState)
|
||||||
{
|
{
|
||||||
Atomic64Padded resource_creation_gen;
|
Atomic64Padded resource_creation_gen;
|
||||||
|
|
||||||
/* Stats */
|
/* Stats */
|
||||||
Atomic64 driver_resources_allocated;
|
Atomic64 driver_resources_allocated;
|
||||||
Atomic64 driver_descriptors_allocated;
|
Atomic64 driver_descriptors_allocated;
|
||||||
|
|
||||||
/* Queues */
|
/* Queues */
|
||||||
G_D12_Queue queues[G_NumQueues];
|
G_D12_Queue queues[G_NumQueues];
|
||||||
|
|
||||||
/* Descriptor heaps */
|
/* Descriptor heaps */
|
||||||
G_D12_DescriptorHeap descriptor_heaps[G_D12_DescriptorHeapKind_Count];
|
G_D12_DescriptorHeap descriptor_heaps[G_D12_DescriptorHeapKind_Count];
|
||||||
|
|
||||||
/* Rootsig */
|
/* Rootsig */
|
||||||
ID3D12RootSignature *bindless_rootsig;
|
ID3D12RootSignature *bindless_rootsig;
|
||||||
|
|
||||||
/* Pipelines */
|
/* Pipelines */
|
||||||
G_D12_PipelineBin pipeline_bins[1024];
|
G_D12_PipelineBin pipeline_bins[1024];
|
||||||
|
|
||||||
/* Command lists */
|
/* Command lists */
|
||||||
Mutex free_cmd_lists_mutex;
|
Mutex free_cmd_lists_mutex;
|
||||||
G_D12_CmdList *first_free_cmd_list;
|
G_D12_CmdList *first_free_cmd_list;
|
||||||
|
|
||||||
/* Command chunks */
|
/* Command chunks */
|
||||||
Mutex free_cmd_chunks_mutex;
|
Mutex free_cmd_chunks_mutex;
|
||||||
G_D12_CmdChunk *first_free_cmd_chunk;
|
G_D12_CmdChunk *first_free_cmd_chunk;
|
||||||
|
|
||||||
/* Swapchains */
|
/* Swapchains */
|
||||||
Mutex free_swapchains_mutex;
|
Mutex free_swapchains_mutex;
|
||||||
G_D12_Swapchain *first_free_swapchain;
|
G_D12_Swapchain *first_free_swapchain;
|
||||||
|
|
||||||
/* Device */
|
/* Device */
|
||||||
IDXGIFactory6 *factory;
|
IDXGIFactory6 *factory;
|
||||||
IDXGIAdapter3 *adapter;
|
IDXGIAdapter3 *adapter;
|
||||||
ID3D12Device10 *device;
|
ID3D12Device10 *device;
|
||||||
} extern G_D12_shared_state;
|
} extern G_D12_shared_state;
|
||||||
|
|
||||||
Struct(G_D12_ThreadLocalState)
|
Struct(G_D12_ThreadLocalState)
|
||||||
{
|
{
|
||||||
HANDLE sync_event;
|
HANDLE sync_event;
|
||||||
} extern ThreadLocal G_D12_tl;
|
} extern ThreadLocal G_D12_tl;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,17 +3,17 @@
|
|||||||
|
|
||||||
Enum(G_RefKind)
|
Enum(G_RefKind)
|
||||||
{
|
{
|
||||||
G_RefKind_StructuredBuffer,
|
G_RefKind_StructuredBuffer,
|
||||||
G_RefKind_RWStructuredBuffer,
|
G_RefKind_RWStructuredBuffer,
|
||||||
G_RefKind_ByteAddressBuffer,
|
G_RefKind_ByteAddressBuffer,
|
||||||
G_RefKind_RWByteAddressBuffer,
|
G_RefKind_RWByteAddressBuffer,
|
||||||
G_RefKind_Texture1D,
|
G_RefKind_Texture1D,
|
||||||
G_RefKind_RWTexture1D,
|
G_RefKind_RWTexture1D,
|
||||||
G_RefKind_Texture2D,
|
G_RefKind_Texture2D,
|
||||||
G_RefKind_RWTexture2D,
|
G_RefKind_RWTexture2D,
|
||||||
G_RefKind_Texture3D,
|
G_RefKind_Texture3D,
|
||||||
G_RefKind_RWTexture3D,
|
G_RefKind_RWTexture3D,
|
||||||
G_RefKind_SamplerState,
|
G_RefKind_SamplerState,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_StructuredBufferRef) { u32 v; };
|
Struct(G_StructuredBufferRef) { u32 v; };
|
||||||
@ -43,56 +43,56 @@ Struct(G_SamplerStateRef) { u32 v; };
|
|||||||
#define G_NumConstants (G_NumGeneralPurposeConstants + G_NumReservedConstants)
|
#define G_NumConstants (G_NumGeneralPurposeConstants + G_NumReservedConstants)
|
||||||
|
|
||||||
#if IsLanguageC
|
#if IsLanguageC
|
||||||
#define G_ForceDeclConstant(type, name, slot) \
|
#define G_ForceDeclConstant(type, name, slot) \
|
||||||
Enum(name##__shaderconstantenum) { name = slot }; \
|
Enum(name##__shaderconstantenum) { name = slot }; \
|
||||||
Struct(name##__shaderconstanttype) { type v; }
|
Struct(name##__shaderconstanttype) { type v; }
|
||||||
#define G_DeclConstant(type, name, slot) \
|
#define G_DeclConstant(type, name, slot) \
|
||||||
StaticAssert(sizeof(type) <= 4); \
|
StaticAssert(sizeof(type) <= 4); \
|
||||||
StaticAssert(slot < G_NumGeneralPurposeConstants); \
|
StaticAssert(slot < G_NumGeneralPurposeConstants); \
|
||||||
G_ForceDeclConstant(type, name, slot)
|
G_ForceDeclConstant(type, name, slot)
|
||||||
#elif IsLanguageG
|
#elif IsLanguageG
|
||||||
#define G_ForceDeclConstant(type, name, slot) cbuffer name : register(b##slot) { type name; }
|
#define G_ForceDeclConstant(type, name, slot) cbuffer name : register(b##slot) { type name; }
|
||||||
#define G_DeclConstant(type, name, slot) G_ForceDeclConstant(type, name, slot)
|
#define G_DeclConstant(type, name, slot) G_ForceDeclConstant(type, name, slot)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Resource dereference
|
//~ Resource dereference
|
||||||
|
|
||||||
#if IsLanguageG
|
#if IsLanguageG
|
||||||
/* TODO: Non-uniform resource access currently is assumed as the default
|
/* TODO: Non-uniform resource access currently is assumed as the default
|
||||||
* behavior. We may want to add explicit "uniform" variants for
|
* behavior. We may want to add explicit "uniform" variants for
|
||||||
* optimization on amd in the future. */
|
* optimization on amd in the future. */
|
||||||
|
|
||||||
template<typename T> StructuredBuffer<T> G_Dereference(G_StructuredBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> StructuredBuffer<T> G_Dereference(G_StructuredBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> RWStructuredBuffer<T> G_Dereference(G_RWStructuredBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> RWStructuredBuffer<T> G_Dereference(G_RWStructuredBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
|
|
||||||
ByteAddressBuffer G_Dereference(G_ByteAddressBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
ByteAddressBuffer G_Dereference(G_ByteAddressBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
RWByteAddressBuffer G_Dereference(G_RWByteAddressBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
RWByteAddressBuffer G_Dereference(G_RWByteAddressBufferRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
|
|
||||||
template<typename T> Texture1D<T> G_Dereference(G_Texture1DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> Texture1D<T> G_Dereference(G_Texture1DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> Texture2D<T> G_Dereference(G_Texture2DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> Texture2D<T> G_Dereference(G_Texture2DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> Texture3D<T> G_Dereference(G_Texture3DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> Texture3D<T> G_Dereference(G_Texture3DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> RWTexture1D<T> G_Dereference(G_RWTexture1DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> RWTexture1D<T> G_Dereference(G_RWTexture1DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> RWTexture2D<T> G_Dereference(G_RWTexture2DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> RWTexture2D<T> G_Dereference(G_RWTexture2DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
template<typename T> RWTexture3D<T> G_Dereference(G_RWTexture3DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
template<typename T> RWTexture3D<T> G_Dereference(G_RWTexture3DRef r) { return ResourceDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
|
|
||||||
SamplerState G_Dereference(G_SamplerStateRef r) { return SamplerDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
SamplerState G_Dereference(G_SamplerStateRef r) { return SamplerDescriptorHeap[NonUniformResourceIndex(r.v)]; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Size helpers
|
//~ Size helpers
|
||||||
|
|
||||||
#if IsLanguageG
|
#if IsLanguageG
|
||||||
template<typename T> u32 countof(StructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
template<typename T> u32 countof(StructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
template<typename T> u32 countof(RWStructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
template<typename T> u32 countof(RWStructuredBuffer<T> buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(ByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
u32 countof(ByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(RWByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
u32 countof(RWByteAddressBuffer buff) { u32 result; buff.GetDimensions(result); return result; }
|
||||||
u32 countof(Texture1D tex) { u32 result; tex.GetDimensions(result); return result; }
|
u32 countof(Texture1D tex) { u32 result; tex.GetDimensions(result); return result; }
|
||||||
template<typename T> u32 countof(RWTexture1D<T> tex) { u32 result; tex.GetDimensions(result); return result; }
|
template<typename T> u32 countof(RWTexture1D<T> tex) { u32 result; tex.GetDimensions(result); return result; }
|
||||||
Vec2U32 countof(Texture2D tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
Vec2U32 countof(Texture2D tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
||||||
template<typename T> Vec2U32 countof(RWTexture2D<T> tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
template<typename T> Vec2U32 countof(RWTexture2D<T> tex) { Vec2U32 result; tex.GetDimensions(result.x, result.y); return result; }
|
||||||
Vec3U32 countof(Texture3D tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
Vec3U32 countof(Texture3D tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
||||||
template<typename T> Vec3U32 countof(RWTexture3D<T> tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
template<typename T> Vec3U32 countof(RWTexture3D<T> tex) { Vec3U32 result; tex.GetDimensions(result.x, result.y, result.z); return result; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -111,196 +111,196 @@ G_ForceDeclConstant(G_RWByteAddressBufferRef, G_ShaderConst_PrintBufferRef, 8)
|
|||||||
|
|
||||||
Enum(G_FmtArgKind)
|
Enum(G_FmtArgKind)
|
||||||
{
|
{
|
||||||
G_FmtArgKind_None,
|
G_FmtArgKind_None,
|
||||||
G_FmtArgKind_End,
|
G_FmtArgKind_End,
|
||||||
|
|
||||||
G_FmtArgKind_BEGINSIZE1,
|
G_FmtArgKind_BEGINSIZE1,
|
||||||
|
|
||||||
G_FmtArgKind_Uint,
|
G_FmtArgKind_Uint,
|
||||||
G_FmtArgKind_Sint,
|
G_FmtArgKind_Sint,
|
||||||
G_FmtArgKind_Float,
|
G_FmtArgKind_Float,
|
||||||
|
|
||||||
G_FmtArgKind_BEGINSIZE2,
|
G_FmtArgKind_BEGINSIZE2,
|
||||||
|
|
||||||
G_FmtArgKind_Uint2,
|
G_FmtArgKind_Uint2,
|
||||||
G_FmtArgKind_Sint2,
|
G_FmtArgKind_Sint2,
|
||||||
G_FmtArgKind_Float2,
|
G_FmtArgKind_Float2,
|
||||||
|
|
||||||
G_FmtArgKind_BEGINSIZE3,
|
G_FmtArgKind_BEGINSIZE3,
|
||||||
|
|
||||||
G_FmtArgKind_Uint3,
|
G_FmtArgKind_Uint3,
|
||||||
G_FmtArgKind_Sint3,
|
G_FmtArgKind_Sint3,
|
||||||
G_FmtArgKind_Float3,
|
G_FmtArgKind_Float3,
|
||||||
|
|
||||||
G_FmtArgKind_BEGINSIZE4,
|
G_FmtArgKind_BEGINSIZE4,
|
||||||
|
|
||||||
G_FmtArgKind_Uint4,
|
G_FmtArgKind_Uint4,
|
||||||
G_FmtArgKind_Sint4,
|
G_FmtArgKind_Sint4,
|
||||||
G_FmtArgKind_Float4,
|
G_FmtArgKind_Float4,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(G_FmtArg)
|
Struct(G_FmtArg)
|
||||||
{
|
{
|
||||||
G_FmtArgKind kind;
|
G_FmtArgKind kind;
|
||||||
Vec4U32 v;
|
Vec4U32 v;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IsLanguageG && GPU_SHADER_PRINT
|
#if IsLanguageG && GPU_SHADER_PRINT
|
||||||
G_FmtArg G_Fmt(u32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint; result.v.x = v; return result; }
|
G_FmtArg G_Fmt(u32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint; result.v.x = v; return result; }
|
||||||
G_FmtArg G_Fmt(Vec2U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint2; result.v.xy = v.xy; return result; }
|
G_FmtArg G_Fmt(Vec2U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint2; result.v.xy = v.xy; return result; }
|
||||||
G_FmtArg G_Fmt(Vec3U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint3; result.v.xyz = v.xyz; return result; }
|
G_FmtArg G_Fmt(Vec3U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint3; result.v.xyz = v.xyz; return result; }
|
||||||
G_FmtArg G_Fmt(Vec4U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint4; result.v.xyzw = v.xyzw; return result; }
|
G_FmtArg G_Fmt(Vec4U32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Uint4; result.v.xyzw = v.xyzw; return result; }
|
||||||
|
|
||||||
G_FmtArg G_Fmt(i32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint; result.v.x = v; return result; }
|
G_FmtArg G_Fmt(i32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint; result.v.x = v; return result; }
|
||||||
G_FmtArg G_Fmt(Vec2I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint2; result.v.xy = v.xy; return result; }
|
G_FmtArg G_Fmt(Vec2I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint2; result.v.xy = v.xy; return result; }
|
||||||
G_FmtArg G_Fmt(Vec3I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint3; result.v.xyz = v.xyz; return result; }
|
G_FmtArg G_Fmt(Vec3I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint3; result.v.xyz = v.xyz; return result; }
|
||||||
G_FmtArg G_Fmt(Vec4I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint4; result.v.xyzw = v.xyzw; return result; }
|
G_FmtArg G_Fmt(Vec4I32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Sint4; result.v.xyzw = v.xyzw; return result; }
|
||||||
|
|
||||||
G_FmtArg G_Fmt(f32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float; result.v.x = asuint(v); return result; }
|
G_FmtArg G_Fmt(f32 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float; result.v.x = asuint(v); return result; }
|
||||||
G_FmtArg G_Fmt(Vec2 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float2; result.v.xy = asuint(v.xy); return result; }
|
G_FmtArg G_Fmt(Vec2 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float2; result.v.xy = asuint(v.xy); return result; }
|
||||||
G_FmtArg G_Fmt(Vec3 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float3; result.v.xyz = asuint(v.xyz); return result; }
|
G_FmtArg G_Fmt(Vec3 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float3; result.v.xyz = asuint(v.xyz); return result; }
|
||||||
G_FmtArg G_Fmt(Vec4 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float4; result.v.xyzw = asuint(v.xyzw); return result; }
|
G_FmtArg G_Fmt(Vec4 v) { G_FmtArg result; result.kind = G_FmtArgKind_Float4; result.v.xyzw = asuint(v.xyzw); return result; }
|
||||||
|
|
||||||
G_FmtArg G_FmtEnd(void) { G_FmtArg result; result.kind = G_FmtArgKind_End; return result; }
|
G_FmtArg G_FmtEnd(void) { G_FmtArg result; result.kind = G_FmtArgKind_End; return result; }
|
||||||
|
|
||||||
Struct(G_TempPrintBuffer)
|
Struct(G_TempPrintBuffer)
|
||||||
|
{
|
||||||
|
/* NOTE: The larger the array size, the longer the compilation time */
|
||||||
|
u32 byte_chunks[64];
|
||||||
|
u32 bytes_count;
|
||||||
|
u32 chars_count;
|
||||||
|
u32 args_count;
|
||||||
|
b32 overflowed;
|
||||||
|
};
|
||||||
|
|
||||||
|
void G_PushPrintByte(inout G_TempPrintBuffer buff, u32 v)
|
||||||
|
{
|
||||||
|
u32 chunk_idx = buff.bytes_count / 4;
|
||||||
|
if (chunk_idx < countof(buff.byte_chunks))
|
||||||
{
|
{
|
||||||
/* NOTE: The larger the array size, the longer the compilation time */
|
u32 byte_idx_in_chunk = buff.bytes_count & 0x03;
|
||||||
u32 byte_chunks[64];
|
if (byte_idx_in_chunk == 0)
|
||||||
u32 bytes_count;
|
{
|
||||||
u32 chars_count;
|
/* Since buff is not zero initialized, we set the chunk on first write here */
|
||||||
u32 args_count;
|
buff.byte_chunks[chunk_idx] = v & 0xFF;
|
||||||
b32 overflowed;
|
}
|
||||||
};
|
else
|
||||||
|
{
|
||||||
void G_PushPrintByte(inout G_TempPrintBuffer buff, u32 v)
|
buff.byte_chunks[chunk_idx] |= (v & 0xFF) << (byte_idx_in_chunk * 8);
|
||||||
|
}
|
||||||
|
buff.bytes_count += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
u32 chunk_idx = buff.bytes_count / 4;
|
buff.overflowed = 1;
|
||||||
if (chunk_idx < countof(buff.byte_chunks))
|
}
|
||||||
{
|
}
|
||||||
u32 byte_idx_in_chunk = buff.bytes_count & 0x03;
|
|
||||||
if (byte_idx_in_chunk == 0)
|
void G_CommitPrint(G_TempPrintBuffer buff)
|
||||||
{
|
{
|
||||||
/* Since buff is not zero initialized, we set the chunk on first write here */
|
RWByteAddressBuffer rw = G_Dereference(G_ShaderConst_PrintBufferRef);
|
||||||
buff.byte_chunks[chunk_idx] = v & 0xFF;
|
|
||||||
}
|
if (buff.overflowed)
|
||||||
else
|
{
|
||||||
{
|
buff.bytes_count = 0;
|
||||||
buff.byte_chunks[chunk_idx] |= (v & 0xFF) << (byte_idx_in_chunk * 8);
|
buff.chars_count = 0;
|
||||||
}
|
buff.args_count = 0;
|
||||||
buff.bytes_count += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buff.overflowed = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_CommitPrint(G_TempPrintBuffer buff)
|
u32 chunks_count = (buff.bytes_count + 3) / 4;
|
||||||
|
u32 alloc_size = 0;
|
||||||
|
alloc_size += 4; /* Header */
|
||||||
|
alloc_size += chunks_count * 4; /* Chunks */
|
||||||
|
|
||||||
|
/* Atomic fetch + add to base counter */
|
||||||
|
u32 base;
|
||||||
|
rw.InterlockedAdd(0, alloc_size, base);
|
||||||
|
base += 4; /* Offset for allocation counter */
|
||||||
|
base += 4; /* Offset for success counter */
|
||||||
|
base += 4; /* Offset for overflow counter */
|
||||||
|
|
||||||
|
if ((base + alloc_size) < countof(rw))
|
||||||
{
|
{
|
||||||
RWByteAddressBuffer rw = G_Dereference(G_ShaderConst_PrintBufferRef);
|
/* Increment success counter */
|
||||||
|
rw.InterlockedAdd(4, 1);
|
||||||
|
u32 pos = 0;
|
||||||
|
|
||||||
if (buff.overflowed)
|
/* Write header */
|
||||||
{
|
{
|
||||||
buff.bytes_count = 0;
|
u32 header = 0;
|
||||||
buff.chars_count = 0;
|
header |= (buff.chars_count << 0) & 0x0000FFFF;
|
||||||
buff.args_count = 0;
|
header |= (buff.args_count << 16) & 0x7FFF0000;
|
||||||
}
|
header |= (buff.overflowed << 31) & 0xF0000000;
|
||||||
|
rw.Store(base + pos, header);
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
u32 chunks_count = (buff.bytes_count + 3) / 4;
|
/* Write chunks */
|
||||||
u32 alloc_size = 0;
|
for (u32 chunk_idx = 0; chunk_idx < chunks_count; ++chunk_idx)
|
||||||
alloc_size += 4; /* Header */
|
{
|
||||||
alloc_size += chunks_count * 4; /* Chunks */
|
u32 chunk = buff.byte_chunks[chunk_idx];
|
||||||
|
rw.Store(base + pos, chunk);
|
||||||
/* Atomic fetch + add to base counter */
|
pos += 4;
|
||||||
u32 base;
|
}
|
||||||
rw.InterlockedAdd(0, alloc_size, base);
|
|
||||||
base += 4; /* Offset for allocation counter */
|
|
||||||
base += 4; /* Offset for success counter */
|
|
||||||
base += 4; /* Offset for overflow counter */
|
|
||||||
|
|
||||||
if ((base + alloc_size) < countof(rw))
|
|
||||||
{
|
|
||||||
/* Increment success counter */
|
|
||||||
rw.InterlockedAdd(4, 1);
|
|
||||||
u32 pos = 0;
|
|
||||||
|
|
||||||
/* Write header */
|
|
||||||
{
|
|
||||||
u32 header = 0;
|
|
||||||
header |= (buff.chars_count << 0) & 0x0000FFFF;
|
|
||||||
header |= (buff.args_count << 16) & 0x7FFF0000;
|
|
||||||
header |= (buff.overflowed << 31) & 0xF0000000;
|
|
||||||
rw.Store(base + pos, header);
|
|
||||||
pos += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write chunks */
|
|
||||||
for (u32 chunk_idx = 0; chunk_idx < chunks_count; ++chunk_idx)
|
|
||||||
{
|
|
||||||
u32 chunk = buff.byte_chunks[chunk_idx];
|
|
||||||
rw.Store(base + pos, chunk);
|
|
||||||
pos += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Increment overflow counter */
|
|
||||||
rw.InterlockedAdd(8, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Increment overflow counter */
|
||||||
|
rw.InterlockedAdd(8, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define G_PrintF_(fmt, ...) do { \
|
#define G_PrintF_(fmt, ...) do { \
|
||||||
G_TempPrintBuffer __tmp; \
|
G_TempPrintBuffer __tmp; \
|
||||||
__tmp.bytes_count = 0; \
|
__tmp.bytes_count = 0; \
|
||||||
__tmp.overflowed = 0; \
|
__tmp.overflowed = 0; \
|
||||||
u32 __char_idx = 0; \
|
u32 __char_idx = 0; \
|
||||||
while (U32FromChar(fmt[__char_idx]) != 0) \
|
while (U32FromChar(fmt[__char_idx]) != 0) \
|
||||||
{ \
|
{ \
|
||||||
G_PushPrintByte(__tmp, U32FromChar(fmt[__char_idx])); \
|
G_PushPrintByte(__tmp, U32FromChar(fmt[__char_idx])); \
|
||||||
++__char_idx; \
|
++__char_idx; \
|
||||||
} \
|
} \
|
||||||
G_FmtArg __args[] = { __VA_ARGS__ }; \
|
G_FmtArg __args[] = { __VA_ARGS__ }; \
|
||||||
__tmp.chars_count = __char_idx; \
|
__tmp.chars_count = __char_idx; \
|
||||||
__tmp.args_count = (countof(__args) - 1); \
|
__tmp.args_count = (countof(__args) - 1); \
|
||||||
for (u32 __arg_idx = 0; __arg_idx < __tmp.args_count; ++__arg_idx) \
|
for (u32 __arg_idx = 0; __arg_idx < __tmp.args_count; ++__arg_idx) \
|
||||||
{ \
|
{ \
|
||||||
G_FmtArg __arg = __args[__arg_idx]; \
|
G_FmtArg __arg = __args[__arg_idx]; \
|
||||||
G_PushPrintByte(__tmp, __arg.kind); \
|
G_PushPrintByte(__tmp, __arg.kind); \
|
||||||
if (__arg.kind > G_FmtArgKind_BEGINSIZE1) \
|
if (__arg.kind > G_FmtArgKind_BEGINSIZE1) \
|
||||||
{ \
|
{ \
|
||||||
G_PushPrintByte(__tmp, __arg.v.x >> 0); \
|
G_PushPrintByte(__tmp, __arg.v.x >> 0); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.x >> 8); \
|
G_PushPrintByte(__tmp, __arg.v.x >> 8); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.x >> 16); \
|
G_PushPrintByte(__tmp, __arg.v.x >> 16); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.x >> 24); \
|
G_PushPrintByte(__tmp, __arg.v.x >> 24); \
|
||||||
} \
|
} \
|
||||||
if (__arg.kind > G_FmtArgKind_BEGINSIZE2) \
|
if (__arg.kind > G_FmtArgKind_BEGINSIZE2) \
|
||||||
{ \
|
{ \
|
||||||
G_PushPrintByte(__tmp, __arg.v.y >> 0); \
|
G_PushPrintByte(__tmp, __arg.v.y >> 0); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.y >> 8); \
|
G_PushPrintByte(__tmp, __arg.v.y >> 8); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.y >> 16); \
|
G_PushPrintByte(__tmp, __arg.v.y >> 16); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.y >> 24); \
|
G_PushPrintByte(__tmp, __arg.v.y >> 24); \
|
||||||
} \
|
} \
|
||||||
if (__arg.kind > G_FmtArgKind_BEGINSIZE3) \
|
if (__arg.kind > G_FmtArgKind_BEGINSIZE3) \
|
||||||
{ \
|
{ \
|
||||||
G_PushPrintByte(__tmp, __arg.v.z >> 0); \
|
G_PushPrintByte(__tmp, __arg.v.z >> 0); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.z >> 8); \
|
G_PushPrintByte(__tmp, __arg.v.z >> 8); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.z >> 16); \
|
G_PushPrintByte(__tmp, __arg.v.z >> 16); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.z >> 24); \
|
G_PushPrintByte(__tmp, __arg.v.z >> 24); \
|
||||||
} \
|
} \
|
||||||
if (__arg.kind > G_FmtArgKind_BEGINSIZE4) \
|
if (__arg.kind > G_FmtArgKind_BEGINSIZE4) \
|
||||||
{ \
|
{ \
|
||||||
G_PushPrintByte(__tmp, __arg.v.w >> 0); \
|
G_PushPrintByte(__tmp, __arg.v.w >> 0); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.w >> 8); \
|
G_PushPrintByte(__tmp, __arg.v.w >> 8); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.w >> 16); \
|
G_PushPrintByte(__tmp, __arg.v.w >> 16); \
|
||||||
G_PushPrintByte(__tmp, __arg.v.w >> 24); \
|
G_PushPrintByte(__tmp, __arg.v.w >> 24); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
G_CommitPrint(__tmp); \
|
G_CommitPrint(__tmp); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define G_PrintF(fmt, ...) G_PrintF_(fmt, ##__VA_ARGS__, G_FmtEnd())
|
#define G_PrintF(fmt, ...) G_PrintF_(fmt, ##__VA_ARGS__, G_FmtEnd())
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define G_PrintF(fmt)
|
#define G_PrintF(fmt)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1642
src/json/json.c
1642
src/json/json.c
File diff suppressed because it is too large
Load Diff
138
src/json/json.h
138
src/json/json.h
@ -3,126 +3,126 @@
|
|||||||
|
|
||||||
Enum(JSON_Type)
|
Enum(JSON_Type)
|
||||||
{
|
{
|
||||||
JSON_Type_Null,
|
JSON_Type_Null,
|
||||||
JSON_Type_Bool,
|
JSON_Type_Bool,
|
||||||
JSON_Type_Number,
|
JSON_Type_Number,
|
||||||
JSON_Type_String,
|
JSON_Type_String,
|
||||||
JSON_Type_Array,
|
JSON_Type_Array,
|
||||||
JSON_Type_Object
|
JSON_Type_Object
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_Blob)
|
Struct(JSON_Blob)
|
||||||
{
|
{
|
||||||
JSON_Type type;
|
JSON_Type type;
|
||||||
String key;
|
String key;
|
||||||
|
|
||||||
JSON_Blob *parent;
|
JSON_Blob *parent;
|
||||||
JSON_Blob *next;
|
JSON_Blob *next;
|
||||||
JSON_Blob *child_first;
|
JSON_Blob *child_first;
|
||||||
JSON_Blob *child_last;
|
JSON_Blob *child_last;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
String string;
|
String string;
|
||||||
f64 number;
|
f64 number;
|
||||||
b32 boolean;
|
b32 boolean;
|
||||||
} value;
|
} value;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_Error)
|
Struct(JSON_Error)
|
||||||
{
|
{
|
||||||
String msg;
|
String msg;
|
||||||
u64 start;
|
u64 start;
|
||||||
u64 end;
|
u64 end;
|
||||||
JSON_Error *next;
|
JSON_Error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_ErrorList)
|
Struct(JSON_ErrorList)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
JSON_Error *first;
|
JSON_Error *first;
|
||||||
JSON_Error *last;
|
JSON_Error *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_Result)
|
Struct(JSON_Result)
|
||||||
{
|
{
|
||||||
JSON_Blob *root;
|
JSON_Blob *root;
|
||||||
JSON_ErrorList errors;
|
JSON_ErrorList errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Lexer types
|
//~ Lexer types
|
||||||
|
|
||||||
#define JSON_Case_Newline \
|
#define JSON_Case_Newline \
|
||||||
0x0A: /* Line feed or New line */ \
|
0x0A: /* Line feed or New line */ \
|
||||||
case 0x0D /* Carriage return */
|
case 0x0D /* Carriage return */
|
||||||
|
|
||||||
#define JSON_Case_Space \
|
#define JSON_Case_Space \
|
||||||
0x20: /* Space */ \
|
0x20: /* Space */ \
|
||||||
case 0x09 /* Horizontal tab */
|
case 0x09 /* Horizontal tab */
|
||||||
|
|
||||||
#define JSON_Case_Digit0Through9 \
|
#define JSON_Case_Digit0Through9 \
|
||||||
'0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
|
'0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
|
||||||
|
|
||||||
#define JSON_Case_Digit1Through9 \
|
#define JSON_Case_Digit1Through9 \
|
||||||
'1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
|
'1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
|
||||||
|
|
||||||
#define JSON_Case_Symbol \
|
#define JSON_Case_Symbol \
|
||||||
',': case ':': case '[': case ']': case '{': case '}'
|
',': case ':': case '[': case ']': case '{': case '}'
|
||||||
|
|
||||||
Enum(JSON_TokenKind)
|
Enum(JSON_TokenKind)
|
||||||
{
|
{
|
||||||
JSON_TokenKind_Unknown,
|
JSON_TokenKind_Unknown,
|
||||||
|
|
||||||
JSON_TokenKind_Number,
|
JSON_TokenKind_Number,
|
||||||
JSON_TokenKind_String,
|
JSON_TokenKind_String,
|
||||||
|
|
||||||
JSON_TokenKind_KeywordTrue,
|
JSON_TokenKind_KeywordTrue,
|
||||||
JSON_TokenKind_KeywordFalse,
|
JSON_TokenKind_KeywordFalse,
|
||||||
JSON_TokenKind_KeywordNull,
|
JSON_TokenKind_KeywordNull,
|
||||||
|
|
||||||
JSON_TokenKind_Comma,
|
JSON_TokenKind_Comma,
|
||||||
JSON_TokenKind_Colon,
|
JSON_TokenKind_Colon,
|
||||||
JSON_TokenKind_SquareBraceOpen,
|
JSON_TokenKind_SquareBraceOpen,
|
||||||
JSON_TokenKind_SquareBraceClose,
|
JSON_TokenKind_SquareBraceClose,
|
||||||
JSON_TokenKind_CurlyBraceOpen,
|
JSON_TokenKind_CurlyBraceOpen,
|
||||||
JSON_TokenKind_CurlyBraceClose,
|
JSON_TokenKind_CurlyBraceClose,
|
||||||
|
|
||||||
JSON_TokenKind_Bof,
|
JSON_TokenKind_Bof,
|
||||||
JSON_TokenKind_Eof
|
JSON_TokenKind_Eof
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_Token)
|
Struct(JSON_Token)
|
||||||
{
|
{
|
||||||
JSON_TokenKind kind;
|
JSON_TokenKind kind;
|
||||||
u64 start;
|
u64 start;
|
||||||
u64 end;
|
u64 end;
|
||||||
JSON_Token *next;
|
JSON_Token *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(JSON_TokenList)
|
Struct(JSON_TokenList)
|
||||||
{
|
{
|
||||||
JSON_Token *token_first;
|
JSON_Token *token_first;
|
||||||
JSON_Token *token_last;
|
JSON_Token *token_last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(JSON_LexNumberState)
|
Enum(JSON_LexNumberState)
|
||||||
{
|
{
|
||||||
JSON_LexNumberState_Whole,
|
JSON_LexNumberState_Whole,
|
||||||
JSON_LexNumberState_Fraction,
|
JSON_LexNumberState_Fraction,
|
||||||
JSON_LexNumberState_Exponent
|
JSON_LexNumberState_Exponent
|
||||||
};
|
};
|
||||||
|
|
||||||
Global Readonly String JSON_keyword_strings[] = {
|
Global Readonly String JSON_keyword_strings[] = {
|
||||||
['t'] = CompLit("true"),
|
['t'] = CompLit("true"),
|
||||||
['f'] = CompLit("false"),
|
['f'] = CompLit("false"),
|
||||||
['n'] = CompLit("null")
|
['n'] = CompLit("null")
|
||||||
};
|
};
|
||||||
|
|
||||||
Global Readonly JSON_TokenKind JSON_keyword_types[] = {
|
Global Readonly JSON_TokenKind JSON_keyword_types[] = {
|
||||||
['t'] = JSON_TokenKind_KeywordTrue,
|
['t'] = JSON_TokenKind_KeywordTrue,
|
||||||
['f'] = JSON_TokenKind_KeywordFalse,
|
['f'] = JSON_TokenKind_KeywordFalse,
|
||||||
['n'] = JSON_TokenKind_KeywordNull
|
['n'] = JSON_TokenKind_KeywordNull
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -130,13 +130,13 @@ Global Readonly JSON_TokenKind JSON_keyword_types[] = {
|
|||||||
|
|
||||||
Struct(JSON_Parser)
|
Struct(JSON_Parser)
|
||||||
{
|
{
|
||||||
/* Input */
|
/* Input */
|
||||||
String src;
|
String src;
|
||||||
JSON_Token *at;
|
JSON_Token *at;
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
JSON_Blob *root;
|
JSON_Blob *root;
|
||||||
JSON_ErrorList errors;
|
JSON_ErrorList errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
1812
src/meta/meta.c
1812
src/meta/meta.c
File diff suppressed because it is too large
Load Diff
158
src/meta/meta.h
158
src/meta/meta.h
@ -4,43 +4,43 @@
|
|||||||
//~ Base layer definitions
|
//~ Base layer definitions
|
||||||
|
|
||||||
#ifndef IsConsoleApp
|
#ifndef IsConsoleApp
|
||||||
# define IsConsoleApp 1
|
#define IsConsoleApp 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsRtcEnabled
|
#ifndef IsRtcEnabled
|
||||||
# define IsRtcEnabled 1
|
#define IsRtcEnabled 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsUnoptimized
|
#ifndef IsUnoptimized
|
||||||
# define IsUnoptimized 1
|
#define IsUnoptimized 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsAsanEnabled
|
#ifndef IsAsanEnabled
|
||||||
# define IsAsanEnabled 0
|
#define IsAsanEnabled 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsCrtlibEnabled
|
#ifndef IsCrtlibEnabled
|
||||||
# define IsCrtlibEnabled 1
|
#define IsCrtlibEnabled 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsDebinfoEnabled
|
#ifndef IsDebinfoEnabled
|
||||||
# define IsDebinfoEnabled 1
|
#define IsDebinfoEnabled 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsDeveloperModeEnabled
|
#ifndef IsDeveloperModeEnabled
|
||||||
# define IsDeveloperModeEnabled 1
|
#define IsDeveloperModeEnabled 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsUnoptimized
|
#ifndef IsUnoptimized
|
||||||
# define IsUnoptimized 1
|
#define IsUnoptimized 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsTestingEnabled
|
#ifndef IsTestingEnabled
|
||||||
# define IsTestingEnabled 0
|
#define IsTestingEnabled 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IsHotSwappingEnabled
|
#ifndef IsHotSwappingEnabled
|
||||||
# define IsHotSwappingEnabled 0
|
#define IsHotSwappingEnabled 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -60,8 +60,8 @@
|
|||||||
|
|
||||||
Struct(LineCol)
|
Struct(LineCol)
|
||||||
{
|
{
|
||||||
i64 line;
|
i64 line;
|
||||||
i64 col;
|
i64 col;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -69,109 +69,109 @@ Struct(LineCol)
|
|||||||
|
|
||||||
Struct(CompilerParams)
|
Struct(CompilerParams)
|
||||||
{
|
{
|
||||||
StringList defs;
|
StringList defs;
|
||||||
|
|
||||||
StringList warnings_msvc;
|
StringList warnings_msvc;
|
||||||
StringList warnings_clang;
|
StringList warnings_clang;
|
||||||
StringList warnings_dxc;
|
StringList warnings_dxc;
|
||||||
|
|
||||||
StringList flags_msvc;
|
StringList flags_msvc;
|
||||||
StringList flags_clang;
|
StringList flags_clang;
|
||||||
StringList flags_dxc;
|
StringList flags_dxc;
|
||||||
|
|
||||||
StringList compiler_only_flags_msvc;
|
StringList compiler_only_flags_msvc;
|
||||||
StringList compiler_only_flags_clang;
|
StringList compiler_only_flags_clang;
|
||||||
|
|
||||||
StringList linker_only_flags_msvc;
|
StringList linker_only_flags_msvc;
|
||||||
StringList linker_only_flags_clang;
|
StringList linker_only_flags_clang;
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(ShaderEntryKind)
|
Enum(ShaderEntryKind)
|
||||||
{
|
{
|
||||||
ShaderEntryKind_VS,
|
ShaderEntryKind_VS,
|
||||||
ShaderEntryKind_PS,
|
ShaderEntryKind_PS,
|
||||||
ShaderEntryKind_CS,
|
ShaderEntryKind_CS,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ShaderEntry)
|
Struct(ShaderEntry)
|
||||||
{
|
{
|
||||||
ShaderEntry *next;
|
ShaderEntry *next;
|
||||||
ShaderEntryKind kind;
|
ShaderEntryKind kind;
|
||||||
String name;
|
String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(ResDir)
|
Struct(ResDir)
|
||||||
{
|
{
|
||||||
ResDir *next;
|
ResDir *next;
|
||||||
String dir_path;
|
String dir_path;
|
||||||
String store_name;
|
String store_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(GpuObj)
|
Struct(GpuObj)
|
||||||
{
|
{
|
||||||
String output;
|
String output;
|
||||||
i32 return_code;
|
i32 return_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(EmbedObj)
|
Struct(EmbedObj)
|
||||||
{
|
{
|
||||||
String obj_file;
|
String obj_file;
|
||||||
String output;
|
String output;
|
||||||
i32 return_code;
|
i32 return_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(BuildCtx)
|
Struct(BuildCtx)
|
||||||
{
|
{
|
||||||
Atomic32 status;
|
Atomic32 status;
|
||||||
|
|
||||||
M_Layer layers_parse;
|
M_Layer layers_parse;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
M_ErrorList errors;
|
M_ErrorList errors;
|
||||||
} c_parse;
|
} c_parse;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
M_ErrorList errors;
|
M_ErrorList errors;
|
||||||
ShaderEntry *first_shader_entry;
|
ShaderEntry *first_shader_entry;
|
||||||
ShaderEntry *last_shader_entry;
|
ShaderEntry *last_shader_entry;
|
||||||
u64 shader_entries_count;
|
u64 shader_entries_count;
|
||||||
} gpu_parse;
|
} gpu_parse;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
M_ErrorList errors;
|
M_ErrorList errors;
|
||||||
ResDir *first_res_dir;
|
ResDir *first_res_dir;
|
||||||
ResDir *last_res_dir;
|
ResDir *last_res_dir;
|
||||||
u64 res_dirs_count;
|
u64 res_dirs_count;
|
||||||
} res_dir_parse;
|
} res_dir_parse;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
String obj_file;
|
String obj_file;
|
||||||
String output;
|
String output;
|
||||||
i32 return_code;
|
i32 return_code;
|
||||||
} c_obj;
|
} c_obj;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
GpuObj *array;
|
GpuObj *array;
|
||||||
u32 count;
|
u32 count;
|
||||||
Atomic32 finished_count;
|
Atomic32 finished_count;
|
||||||
} gpu_objs;
|
} gpu_objs;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
EmbedObj *array;
|
EmbedObj *array;
|
||||||
u32 count;
|
u32 count;
|
||||||
} embed_objs;
|
} embed_objs;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
String output;
|
String output;
|
||||||
i32 return_code;
|
i32 return_code;
|
||||||
} link;
|
} link;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BuildCtx Build;
|
extern BuildCtx Build;
|
||||||
|
|||||||
@ -3,82 +3,82 @@
|
|||||||
|
|
||||||
String F_GetFull(Arena *arena, String path)
|
String F_GetFull(Arena *arena, String path)
|
||||||
{
|
{
|
||||||
return OS_GetFullPath(arena, path);
|
return OS_GetFullPath(arena, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
String F_GetFullCrossPlatform(Arena *arena, String path)
|
String F_GetFullCrossPlatform(Arena *arena, String path)
|
||||||
{
|
{
|
||||||
String result = OS_GetFullPath(arena, path);
|
String result = OS_GetFullPath(arena, path);
|
||||||
for (u64 i = 0; i < result.len; ++i)
|
for (u64 i = 0; i < result.len; ++i)
|
||||||
|
{
|
||||||
|
if (result.text[i] == '\\')
|
||||||
{
|
{
|
||||||
if (result.text[i] == '\\')
|
result.text[i] = '/';
|
||||||
{
|
|
||||||
result.text[i] = '/';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String F_GetFileName(String path)
|
String F_GetFileName(String path)
|
||||||
{
|
{
|
||||||
String result = path;
|
String result = path;
|
||||||
u64 start = path.len;
|
u64 start = path.len;
|
||||||
for (u64 i = path.len; i-- > 0;)
|
for (u64 i = path.len; i-- > 0;)
|
||||||
|
{
|
||||||
|
if (path.text[i] == '\\' || path.text[i] == '/')
|
||||||
{
|
{
|
||||||
if (path.text[i] == '\\' || path.text[i] == '/')
|
start = i + 1;
|
||||||
{
|
break;
|
||||||
start = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (start < path.len)
|
}
|
||||||
{
|
if (start < path.len)
|
||||||
result.text = &path.text[start];
|
{
|
||||||
result.len = path.len - start;
|
result.text = &path.text[start];
|
||||||
|
result.len = path.len - start;
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String F_GetParentDir(String path)
|
String F_GetParentDir(String path)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
result.text = path.text;
|
result.text = path.text;
|
||||||
u64 end = path.len;
|
u64 end = path.len;
|
||||||
for (u64 i = path.len; i-- > 0;)
|
for (u64 i = path.len; i-- > 0;)
|
||||||
|
{
|
||||||
|
if (path.text[i] == '\\' || path.text[i] == '/')
|
||||||
{
|
{
|
||||||
if (path.text[i] == '\\' || path.text[i] == '/')
|
end = i + 1;
|
||||||
{
|
break;
|
||||||
end = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (end < path.len)
|
}
|
||||||
{
|
if (end < path.len)
|
||||||
result.len = end;
|
{
|
||||||
}
|
result.len = end;
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String F_ExtensionFromFile(String path)
|
String F_ExtensionFromFile(String path)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
u64 start = path.len;
|
u64 start = path.len;
|
||||||
for (u64 i = path.len; i-- > 0;)
|
for (u64 i = path.len; i-- > 0;)
|
||||||
|
{
|
||||||
|
if (path.text[i] == '.')
|
||||||
{
|
{
|
||||||
if (path.text[i] == '.')
|
start = i + 1;
|
||||||
{
|
break;
|
||||||
start = i + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (start < path.len)
|
}
|
||||||
{
|
if (start < path.len)
|
||||||
result.text = &path.text[start];
|
{
|
||||||
result.len = path.len - start;
|
result.text = &path.text[start];
|
||||||
|
result.len = path.len - start;
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -86,11 +86,11 @@ String F_ExtensionFromFile(String path)
|
|||||||
|
|
||||||
String F_DataFromFile(Arena *arena, String path)
|
String F_DataFromFile(Arena *arena, String path)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
OS_File file = OS_OpenFile(path, OS_FileFlag_Read, I64Max);
|
OS_File file = OS_OpenFile(path, OS_FileFlag_Read, I64Max);
|
||||||
result = OS_ReadEntireFile(arena, file);
|
result = OS_ReadEntireFile(arena, file);
|
||||||
OS_CloseFile(file);
|
OS_CloseFile(file);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -98,9 +98,9 @@ String F_DataFromFile(Arena *arena, String path)
|
|||||||
|
|
||||||
void F_ClearWrite(String path, String data)
|
void F_ClearWrite(String path, String data)
|
||||||
{
|
{
|
||||||
OS_File file = OS_OpenFile(path, OS_FileFlag_Write | OS_FileFlag_Create, I64Max);
|
OS_File file = OS_OpenFile(path, OS_FileFlag_Write | OS_FileFlag_Create, I64Max);
|
||||||
OS_ClearWriteFile(file, data);
|
OS_ClearWriteFile(file, data);
|
||||||
OS_CloseFile(file);
|
OS_CloseFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -108,12 +108,12 @@ void F_ClearWrite(String path, String data)
|
|||||||
|
|
||||||
b32 F_IsFile(String path)
|
b32 F_IsFile(String path)
|
||||||
{
|
{
|
||||||
return OS_FileExists(path);
|
return OS_FileExists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 F_IsDir(String path)
|
b32 F_IsDir(String path)
|
||||||
{
|
{
|
||||||
return OS_DirExists(path);
|
return OS_DirExists(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -121,18 +121,18 @@ b32 F_IsDir(String path)
|
|||||||
|
|
||||||
void F_FilesFromDir(Arena *arena, StringList *list, String dir, F_IterFlag flags)
|
void F_FilesFromDir(Arena *arena, StringList *list, String dir, F_IterFlag flags)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
StringList tmp = Zi;
|
StringList tmp = Zi;
|
||||||
String dir_full_path = F_GetFull(scratch.arena, dir);
|
String dir_full_path = F_GetFull(scratch.arena, dir);
|
||||||
OS_DirContentsFromFullPath(scratch.arena, &tmp, dir_full_path);
|
OS_DirContentsFromFullPath(scratch.arena, &tmp, dir_full_path);
|
||||||
for (StringListNode *n = tmp.first; n; n = n->next)
|
for (StringListNode *n = tmp.first; n; n = n->next)
|
||||||
|
{
|
||||||
|
String file_joined_path = StringF(arena, "%F/%F", FmtString(dir), FmtString(n->s));
|
||||||
|
PushStringToList(arena, list, file_joined_path);
|
||||||
|
if (flags & F_IterFlag_Recurse && F_IsDir(file_joined_path))
|
||||||
{
|
{
|
||||||
String file_joined_path = StringF(arena, "%F/%F", FmtString(dir), FmtString(n->s));
|
F_FilesFromDir(arena, list, file_joined_path, flags);
|
||||||
PushStringToList(arena, list, file_joined_path);
|
|
||||||
if (flags & F_IterFlag_Recurse && F_IsDir(file_joined_path))
|
|
||||||
{
|
|
||||||
F_FilesFromDir(arena, list, file_joined_path, flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
Enum(F_IterFlag)
|
Enum(F_IterFlag)
|
||||||
{
|
{
|
||||||
F_IterFlag_None = 0,
|
F_IterFlag_None = 0,
|
||||||
F_IterFlag_Recurse = (1 << 0)
|
F_IterFlag_Recurse = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -3,16 +3,16 @@
|
|||||||
|
|
||||||
Struct(M_Error)
|
Struct(M_Error)
|
||||||
{
|
{
|
||||||
M_Error *next;
|
M_Error *next;
|
||||||
String msg;
|
String msg;
|
||||||
struct M_Token *token;
|
struct M_Token *token;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(M_ErrorList)
|
Struct(M_ErrorList)
|
||||||
{
|
{
|
||||||
M_Error *first;
|
M_Error *first;
|
||||||
M_Error *last;
|
M_Error *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -20,8 +20,8 @@ Struct(M_ErrorList)
|
|||||||
|
|
||||||
Struct(M_File)
|
Struct(M_File)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
String data;
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -29,41 +29,41 @@ Struct(M_File)
|
|||||||
|
|
||||||
Enum(M_TokenKind)
|
Enum(M_TokenKind)
|
||||||
{
|
{
|
||||||
M_TokenKind_Ident,
|
M_TokenKind_Ident,
|
||||||
M_TokenKind_Eol, /* End of line */
|
M_TokenKind_Eol, /* End of line */
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(M_Token)
|
Struct(M_Token)
|
||||||
{
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
M_Token *next;
|
M_Token *next;
|
||||||
|
|
||||||
M_TokenKind kind;
|
M_TokenKind kind;
|
||||||
struct M_TokenFile *file;
|
struct M_TokenFile *file;
|
||||||
|
|
||||||
String s;
|
String s;
|
||||||
} extern Readonly M_NilToken;
|
} extern Readonly M_NilToken;
|
||||||
|
|
||||||
Struct(M_TokenFile)
|
Struct(M_TokenFile)
|
||||||
{
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
M_TokenFile *next;
|
M_TokenFile *next;
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
String data;
|
String data;
|
||||||
|
|
||||||
M_Token *first_token;
|
M_Token *first_token;
|
||||||
M_Token *last_token;
|
M_Token *last_token;
|
||||||
u64 tokens_count;
|
u64 tokens_count;
|
||||||
|
|
||||||
M_ErrorList errors;
|
M_ErrorList errors;
|
||||||
} extern Readonly M_NilTokenFile;
|
} extern Readonly M_NilTokenFile;
|
||||||
|
|
||||||
Struct(M_TokenFileList)
|
Struct(M_TokenFileList)
|
||||||
{
|
{
|
||||||
M_TokenFile *first;
|
M_TokenFile *first;
|
||||||
M_TokenFile *last;
|
M_TokenFile *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -71,68 +71,68 @@ Struct(M_TokenFileList)
|
|||||||
|
|
||||||
Enum(M_EntryKind)
|
Enum(M_EntryKind)
|
||||||
{
|
{
|
||||||
M_EntryKind_Unknown,
|
M_EntryKind_Unknown,
|
||||||
M_EntryKind_Layer,
|
M_EntryKind_Layer,
|
||||||
M_EntryKind_Dep,
|
M_EntryKind_Dep,
|
||||||
M_EntryKind_IncludeC,
|
M_EntryKind_IncludeC,
|
||||||
M_EntryKind_IncludeG,
|
M_EntryKind_IncludeG,
|
||||||
M_EntryKind_DefaultDownstream,
|
M_EntryKind_DefaultDownstream,
|
||||||
M_EntryKind_Bootstrap,
|
M_EntryKind_Bootstrap,
|
||||||
M_EntryKind_VertexShader,
|
M_EntryKind_VertexShader,
|
||||||
M_EntryKind_PixelShader,
|
M_EntryKind_PixelShader,
|
||||||
M_EntryKind_ComputeShader,
|
M_EntryKind_ComputeShader,
|
||||||
M_EntryKind_EmbedDir,
|
M_EntryKind_EmbedDir,
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(M_PlatformKind)
|
Enum(M_PlatformKind)
|
||||||
{
|
{
|
||||||
M_PlatformKind_Any,
|
M_PlatformKind_Any,
|
||||||
M_PlatformKind_Win32,
|
M_PlatformKind_Win32,
|
||||||
};
|
};
|
||||||
|
|
||||||
Global Readonly char *M_entry_kind_rules[] = {
|
Global Readonly char *M_entry_kind_rules[] = {
|
||||||
[M_EntryKind_Layer] = "@Layer",
|
[M_EntryKind_Layer] = "@Layer",
|
||||||
[M_EntryKind_Dep] = "@Dep",
|
[M_EntryKind_Dep] = "@Dep",
|
||||||
[M_EntryKind_IncludeC] = "@IncludeC",
|
[M_EntryKind_IncludeC] = "@IncludeC",
|
||||||
[M_EntryKind_IncludeG] = "@IncludeG",
|
[M_EntryKind_IncludeG] = "@IncludeG",
|
||||||
[M_EntryKind_DefaultDownstream] = "@DefaultDownstream",
|
[M_EntryKind_DefaultDownstream] = "@DefaultDownstream",
|
||||||
[M_EntryKind_Bootstrap] = "@Bootstrap",
|
[M_EntryKind_Bootstrap] = "@Bootstrap",
|
||||||
[M_EntryKind_VertexShader] = "@VertexShader",
|
[M_EntryKind_VertexShader] = "@VertexShader",
|
||||||
[M_EntryKind_PixelShader] = "@PixelShader",
|
[M_EntryKind_PixelShader] = "@PixelShader",
|
||||||
[M_EntryKind_ComputeShader] = "@ComputeShader",
|
[M_EntryKind_ComputeShader] = "@ComputeShader",
|
||||||
[M_EntryKind_EmbedDir] = "@EmbedDir",
|
[M_EntryKind_EmbedDir] = "@EmbedDir",
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(M_Entry)
|
Struct(M_Entry)
|
||||||
{
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
M_Entry *next;
|
M_Entry *next;
|
||||||
|
|
||||||
M_EntryKind kind;
|
M_EntryKind kind;
|
||||||
M_Token *name_token;
|
M_Token *name_token;
|
||||||
|
|
||||||
M_Token *arg_tokens[2];
|
M_Token *arg_tokens[2];
|
||||||
u64 args_count;
|
u64 args_count;
|
||||||
} extern Readonly M_NilEntry;
|
} extern Readonly M_NilEntry;
|
||||||
|
|
||||||
Struct(M_Layer)
|
Struct(M_Layer)
|
||||||
{
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
M_Layer *next;
|
M_Layer *next;
|
||||||
|
|
||||||
M_TokenFile *file;
|
M_TokenFile *file;
|
||||||
|
|
||||||
M_Entry *first;
|
M_Entry *first;
|
||||||
M_Entry *last;
|
M_Entry *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
M_ErrorList errors;
|
M_ErrorList errors;
|
||||||
} extern Readonly M_NilLayer;
|
} extern Readonly M_NilLayer;
|
||||||
|
|
||||||
Struct(M_LayerList)
|
Struct(M_LayerList)
|
||||||
{
|
{
|
||||||
M_Layer *first;
|
M_Layer *first;
|
||||||
M_Layer *last;
|
M_Layer *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,15 +3,15 @@
|
|||||||
|
|
||||||
Enum(OS_FileFlag)
|
Enum(OS_FileFlag)
|
||||||
{
|
{
|
||||||
OS_FileFlag_None = 0,
|
OS_FileFlag_None = 0,
|
||||||
OS_FileFlag_Read = (1 << 0),
|
OS_FileFlag_Read = (1 << 0),
|
||||||
OS_FileFlag_Write = (1 << 1),
|
OS_FileFlag_Write = (1 << 1),
|
||||||
OS_FileFlag_Create = (1 << 2),
|
OS_FileFlag_Create = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(OS_File)
|
Struct(OS_File)
|
||||||
{
|
{
|
||||||
u64 handle;
|
u64 handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -19,8 +19,8 @@ Struct(OS_File)
|
|||||||
|
|
||||||
Struct(OS_CommandResult)
|
Struct(OS_CommandResult)
|
||||||
{
|
{
|
||||||
i32 code;
|
i32 code;
|
||||||
String output;
|
String output;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "meta_os.h"
|
#include "meta_os.h"
|
||||||
|
|
||||||
#if IsPlatformWindows
|
#if IsPlatformWindows
|
||||||
# include "meta_os_win32/meta_os_win32_inc.h"
|
#include "meta_os_win32/meta_os_win32_inc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -3,27 +3,27 @@
|
|||||||
|
|
||||||
String W32_StringFromError(Arena *arena, DWORD err)
|
String W32_StringFromError(Arena *arena, DWORD err)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
char *msg_cstr = 0;
|
char *msg_cstr = 0;
|
||||||
i64 len = FormatMessageA(
|
i64 len = FormatMessageA(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
0,
|
0,
|
||||||
err,
|
err,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(LPSTR)&msg_cstr,
|
(LPSTR)&msg_cstr,
|
||||||
0,
|
0,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
result = PushString(arena, TrimWhitespace(StringFromCstr(msg_cstr, len)));
|
result = PushString(arena, TrimWhitespace(StringFromCstr(msg_cstr, len)));
|
||||||
LocalFree(msg_cstr);
|
LocalFree(msg_cstr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = StringF(arena, "Unknown win32 error - %F", FmtHex(err));
|
result = StringF(arena, "Unknown win32 error - %F", FmtHex(err));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -38,117 +38,117 @@ void OS_Bootstrap(void)
|
|||||||
|
|
||||||
OS_File OS_OpenFile(String path, OS_FileFlag flags, i64 timeout_ns)
|
OS_File OS_OpenFile(String path, OS_FileFlag flags, i64 timeout_ns)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
OS_File result = Zi;
|
OS_File result = Zi;
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
u32 share_mode = FILE_SHARE_READ;
|
u32 share_mode = FILE_SHARE_READ;
|
||||||
u32 create_mode = OPEN_EXISTING;
|
u32 create_mode = OPEN_EXISTING;
|
||||||
u32 access_flags = 0;
|
u32 access_flags = 0;
|
||||||
if (flags & OS_FileFlag_Read) access_flags |= GENERIC_READ;
|
if (flags & OS_FileFlag_Read) access_flags |= GENERIC_READ;
|
||||||
if (flags & OS_FileFlag_Write) access_flags |= GENERIC_WRITE;
|
if (flags & OS_FileFlag_Write) access_flags |= GENERIC_WRITE;
|
||||||
if (flags & OS_FileFlag_Create) create_mode = OPEN_ALWAYS;
|
if (flags & OS_FileFlag_Create) create_mode = OPEN_ALWAYS;
|
||||||
i32 timeout_ms = timeout_ns / 1000000;
|
i32 timeout_ms = timeout_ns / 1000000;
|
||||||
i32 elapsed_ms = 0;
|
i32 elapsed_ms = 0;
|
||||||
i32 delay_ms = 1;
|
i32 delay_ms = 1;
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
{
|
||||||
|
handle = CreateFileW(path_wstr, access_flags, share_mode, 0, create_mode, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE && elapsed_ms < timeout_ms && GetLastError() == ERROR_SHARING_VIOLATION)
|
||||||
{
|
{
|
||||||
handle = CreateFileW(path_wstr, access_flags, share_mode, 0, create_mode, FILE_ATTRIBUTE_NORMAL, 0);
|
Sleep(delay_ms);
|
||||||
if (handle == INVALID_HANDLE_VALUE && elapsed_ms < timeout_ms && GetLastError() == ERROR_SHARING_VIOLATION)
|
elapsed_ms += delay_ms;
|
||||||
{
|
delay_ms = MinI32(delay_ms * 2, 1024);
|
||||||
Sleep(delay_ms);
|
|
||||||
elapsed_ms += delay_ms;
|
|
||||||
delay_ms = MinI32(delay_ms * 2, 1024);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
else
|
||||||
result.handle = (u64)handle;
|
{
|
||||||
return result;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
result.handle = (u64)handle;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_CloseFile(OS_File file)
|
void OS_CloseFile(OS_File file)
|
||||||
{
|
{
|
||||||
HANDLE handle = (HANDLE)file.handle;
|
HANDLE handle = (HANDLE)file.handle;
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
String OS_ReadEntireFile(Arena *arena, OS_File file)
|
String OS_ReadEntireFile(Arena *arena, OS_File file)
|
||||||
{
|
{
|
||||||
String result = Zi;
|
String result = Zi;
|
||||||
HANDLE handle = (HANDLE)file.handle;
|
HANDLE handle = (HANDLE)file.handle;
|
||||||
u32 chunk_size = Kibi(64);
|
u32 chunk_size = Kibi(64);
|
||||||
result.text = ArenaNext(arena, u8);
|
result.text = ArenaNext(arena, u8);
|
||||||
for (;;)
|
for (;;)
|
||||||
|
{
|
||||||
|
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
|
||||||
|
DWORD chunk_bytes_read = 0;
|
||||||
|
ReadFile(handle, chunk, chunk_size, &chunk_bytes_read, 0);
|
||||||
|
result.len += chunk_bytes_read;
|
||||||
|
if (chunk_bytes_read < chunk_size)
|
||||||
{
|
{
|
||||||
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
|
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
|
||||||
DWORD chunk_bytes_read = 0;
|
break;
|
||||||
ReadFile(handle, chunk, chunk_size, &chunk_bytes_read, 0);
|
|
||||||
result.len += chunk_bytes_read;
|
|
||||||
if (chunk_bytes_read < chunk_size)
|
|
||||||
{
|
|
||||||
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_ClearWriteFile(OS_File file, String data)
|
void OS_ClearWriteFile(OS_File file, String data)
|
||||||
{
|
{
|
||||||
HANDLE handle = (HANDLE)file.handle;
|
HANDLE handle = (HANDLE)file.handle;
|
||||||
SetFilePointer(handle, 0, 0, FILE_BEGIN);
|
SetFilePointer(handle, 0, 0, FILE_BEGIN);
|
||||||
SetEndOfFile(handle);
|
SetEndOfFile(handle);
|
||||||
WriteFile(handle, data.text, data.len, 0, 0);
|
WriteFile(handle, data.text, data.len, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_DirContentsFromFullPath(Arena *arena, StringList *list, String path)
|
void OS_DirContentsFromFullPath(Arena *arena, StringList *list, String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
WIN32_FIND_DATAW find_data = Zi;
|
WIN32_FIND_DATAW find_data = Zi;
|
||||||
String filter = StringF(scratch.arena, "%F\\*", FmtString(path));
|
String filter = StringF(scratch.arena, "%F\\*", FmtString(path));
|
||||||
wchar_t *filter_wstr = WstrFromString(scratch.arena, filter);
|
wchar_t *filter_wstr = WstrFromString(scratch.arena, filter);
|
||||||
HANDLE find_handle = FindFirstFileExW(filter_wstr, FindExInfoStandard, &find_data, FindExSearchNameMatch, 0, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
HANDLE find_handle = FindFirstFileExW(filter_wstr, FindExInfoStandard, &find_data, FindExSearchNameMatch, 0, FIND_FIRST_EX_CASE_SENSITIVE | FIND_FIRST_EX_LARGE_FETCH);
|
||||||
b32 found = find_handle && find_handle != INVALID_HANDLE_VALUE;
|
b32 found = find_handle && find_handle != INVALID_HANDLE_VALUE;
|
||||||
while (found)
|
while (found)
|
||||||
|
{
|
||||||
|
String file_name = StringFromWstrNoLimit(arena, find_data.cFileName);
|
||||||
|
if (!MatchString(file_name, Lit(".")) && !MatchString(file_name, Lit("..")))
|
||||||
{
|
{
|
||||||
String file_name = StringFromWstrNoLimit(arena, find_data.cFileName);
|
PushStringToList(arena, list, file_name);
|
||||||
if (!MatchString(file_name, Lit(".")) && !MatchString(file_name, Lit("..")))
|
|
||||||
{
|
|
||||||
PushStringToList(arena, list, file_name);
|
|
||||||
}
|
|
||||||
found = FindNextFileW(find_handle, &find_data);
|
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
found = FindNextFileW(find_handle, &find_data);
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
String OS_GetFullPath(Arena *arena, String path)
|
String OS_GetFullPath(Arena *arena, String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
wchar_t *rel_path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *rel_path_wstr = WstrFromString(scratch.arena, path);
|
||||||
wchar_t full_path_wstr_buff[4096];
|
wchar_t full_path_wstr_buff[4096];
|
||||||
GetFullPathNameW(rel_path_wstr, countof(full_path_wstr_buff), full_path_wstr_buff, 0);
|
GetFullPathNameW(rel_path_wstr, countof(full_path_wstr_buff), full_path_wstr_buff, 0);
|
||||||
String res = StringFromWstr(arena, full_path_wstr_buff, countof(full_path_wstr_buff));
|
String res = StringFromWstr(arena, full_path_wstr_buff, countof(full_path_wstr_buff));
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 OS_LastWriteTimestampFromPath(String path)
|
u64 OS_LastWriteTimestampFromPath(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
u64 result = 0;
|
u64 result = 0;
|
||||||
WIN32_FILE_ATTRIBUTE_DATA a = Zi;
|
WIN32_FILE_ATTRIBUTE_DATA a = Zi;
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
if (GetFileAttributesExW(path_wstr, GetFileExInfoStandard, &a))
|
if (GetFileAttributesExW(path_wstr, GetFileExInfoStandard, &a))
|
||||||
{
|
{
|
||||||
result = ((ULONGLONG)a.ftLastWriteTime.dwHighDateTime << 32) |
|
result = ((ULONGLONG)a.ftLastWriteTime.dwHighDateTime << 32) |
|
||||||
(ULONGLONG)a.ftLastWriteTime.dwLowDateTime;
|
(ULONGLONG)a.ftLastWriteTime.dwLowDateTime;
|
||||||
}
|
}
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -156,45 +156,45 @@ u64 OS_LastWriteTimestampFromPath(String path)
|
|||||||
|
|
||||||
b32 OS_FileOrDirExists(String path)
|
b32 OS_FileOrDirExists(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributesW(path_wstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES;
|
return attributes != INVALID_FILE_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 OS_FileExists(String path)
|
b32 OS_FileExists(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributesW(path_wstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 OS_DirExists(String path)
|
b32 OS_DirExists(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributesW(path_wstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_Mkdir(String path)
|
void OS_Mkdir(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
CreateDirectoryW(path_wstr, 0);
|
CreateDirectoryW(path_wstr, 0);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_Rm(String path)
|
void OS_Rm(String path)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
DeleteFile(path_wstr);
|
DeleteFile(path_wstr);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -202,150 +202,150 @@ void OS_Rm(String path)
|
|||||||
|
|
||||||
OS_CommandResult OS_RunCommand(Arena *arena, String cmd)
|
OS_CommandResult OS_RunCommand(Arena *arena, String cmd)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
OS_CommandResult result = Zi;
|
OS_CommandResult result = Zi;
|
||||||
b32 ok = 1;
|
b32 ok = 1;
|
||||||
|
|
||||||
wchar_t *cmd_wstr = WstrFromString(scratch.arena, cmd);
|
wchar_t *cmd_wstr = WstrFromString(scratch.arena, cmd);
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES sa = Zi;
|
SECURITY_ATTRIBUTES sa = Zi;
|
||||||
sa.nLength = sizeof(sa);
|
sa.nLength = sizeof(sa);
|
||||||
sa.bInheritHandle = 0;
|
sa.bInheritHandle = 0;
|
||||||
|
|
||||||
/* Create pipe */
|
/* Create pipe */
|
||||||
HANDLE pipe_read = 0;
|
HANDLE pipe_read = 0;
|
||||||
HANDLE pipe_write = 0;
|
HANDLE pipe_write = 0;
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
ok = CreatePipe(&pipe_read, &pipe_write, &sa, 0) != 0;
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
result.output = Lit("Failed to create pipe");
|
||||||
|
pipe_read = 0;
|
||||||
|
pipe_write = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Duplicate pipe for child process */
|
||||||
|
HANDLE child_pipe_write = 0;
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
ok = DuplicateHandle(GetCurrentProcess(), pipe_write, GetCurrentProcess(), &child_pipe_write, 0, 1, DUPLICATE_SAME_ACCESS) != 0;
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
result.output = Lit("Failed to create child pipe");
|
||||||
|
child_pipe_write = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize attrs list */
|
||||||
|
LPPROC_THREAD_ATTRIBUTE_LIST attrs = Zi;
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
u64 attrs_size = 0;
|
||||||
|
InitializeProcThreadAttributeList(0, 1, 0, &attrs_size);
|
||||||
|
ok = attrs_size > 0;
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
ok = CreatePipe(&pipe_read, &pipe_write, &sa, 0) != 0;
|
attrs = PushBytes(scratch.arena, attrs_size, 64);
|
||||||
if (!ok)
|
ok = InitializeProcThreadAttributeList(attrs, 1, 0, &attrs_size) != 0;
|
||||||
{
|
|
||||||
result.output = Lit("Failed to create pipe");
|
|
||||||
pipe_read = 0;
|
|
||||||
pipe_write = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
result.output = Lit("Failed to initialize attrs list");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Duplicate pipe for child process */
|
/* Build the handle inheritance whitelist */
|
||||||
HANDLE child_pipe_write = 0;
|
if (ok) {
|
||||||
|
HANDLE inherit_list[] = { child_pipe_write };
|
||||||
|
ok = UpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherit_list, sizeof(inherit_list), 0, 0) != 0;
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
result.output = Lit("Failed to update attributes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create process */
|
||||||
|
/* TODO: Allow caller to set child process's thread affinity by job pool */
|
||||||
|
HANDLE process = 0;
|
||||||
|
HANDLE process_thread = 0;
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
PROCESS_INFORMATION pi = Zi;
|
||||||
|
STARTUPINFOEXW si = Zi;
|
||||||
|
si.StartupInfo.cb = sizeof(si);
|
||||||
|
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
si.StartupInfo.hStdOutput = child_pipe_write;
|
||||||
|
si.StartupInfo.hStdError = child_pipe_write;
|
||||||
|
si.lpAttributeList = attrs;
|
||||||
|
ok = CreateProcessW(0, cmd_wstr, 0, 0, 1, EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi) != 0;
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
ok = DuplicateHandle(GetCurrentProcess(), pipe_write, GetCurrentProcess(), &child_pipe_write, 0, 1, DUPLICATE_SAME_ACCESS) != 0;
|
process = pi.hProcess;
|
||||||
if (!ok)
|
process_thread = pi.hThread;
|
||||||
{
|
|
||||||
result.output = Lit("Failed to create child pipe");
|
|
||||||
child_pipe_write = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Initialize attrs list */
|
|
||||||
LPPROC_THREAD_ATTRIBUTE_LIST attrs = Zi;
|
|
||||||
if (ok)
|
|
||||||
{
|
{
|
||||||
u64 attrs_size = 0;
|
result.output = W32_StringFromError(arena, GetLastError());
|
||||||
InitializeProcThreadAttributeList(0, 1, 0, &attrs_size);
|
|
||||||
ok = attrs_size > 0;
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
attrs = PushBytes(scratch.arena, attrs_size, 64);
|
|
||||||
ok = InitializeProcThreadAttributeList(attrs, 1, 0, &attrs_size) != 0;
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
result.output = Lit("Failed to initialize attrs list");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* Close write pipe handles */
|
||||||
/* Build the handle inheritance whitelist */
|
|
||||||
if (ok) {
|
|
||||||
HANDLE inherit_list[] = { child_pipe_write };
|
|
||||||
ok = UpdateProcThreadAttribute(attrs, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherit_list, sizeof(inherit_list), 0, 0) != 0;
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
result.output = Lit("Failed to update attributes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create process */
|
|
||||||
/* TODO: Allow caller to set child process's thread affinity by job pool */
|
|
||||||
HANDLE process = 0;
|
|
||||||
HANDLE process_thread = 0;
|
|
||||||
if (ok)
|
|
||||||
{
|
{
|
||||||
PROCESS_INFORMATION pi = Zi;
|
CloseHandle(child_pipe_write);
|
||||||
STARTUPINFOEXW si = Zi;
|
CloseHandle(pipe_write);
|
||||||
si.StartupInfo.cb = sizeof(si);
|
child_pipe_write = 0;
|
||||||
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
pipe_write = 0;
|
||||||
si.StartupInfo.hStdOutput = child_pipe_write;
|
}
|
||||||
si.StartupInfo.hStdError = child_pipe_write;
|
}
|
||||||
si.lpAttributeList = attrs;
|
|
||||||
ok = CreateProcessW(0, cmd_wstr, 0, 0, 1, EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi) != 0;
|
/* Read process output */
|
||||||
if (ok)
|
if (ok)
|
||||||
|
{
|
||||||
|
result.output.text = ArenaNext(arena, u8);
|
||||||
|
b32 exit_code_valid = 0;
|
||||||
|
DWORD exit_code = 0;
|
||||||
|
b32 stdout_finished = 0;
|
||||||
|
while (!stdout_finished)
|
||||||
|
{
|
||||||
|
u8 buff[4096] = Zi;
|
||||||
|
DWORD bytes_read = 0;
|
||||||
|
if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0))
|
||||||
|
{
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
if (err == ERROR_BROKEN_PIPE)
|
||||||
{
|
{
|
||||||
process = pi.hProcess;
|
GetExitCodeProcess(process, &exit_code);
|
||||||
process_thread = pi.hThread;
|
exit_code_valid = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result.output = W32_StringFromError(arena, GetLastError());
|
result.output.len += W32_StringFromError(arena, err).len;
|
||||||
}
|
|
||||||
/* Close write pipe handles */
|
|
||||||
{
|
|
||||||
CloseHandle(child_pipe_write);
|
|
||||||
CloseHandle(pipe_write);
|
|
||||||
child_pipe_write = 0;
|
|
||||||
pipe_write = 0;
|
|
||||||
}
|
}
|
||||||
|
stdout_finished = 1;
|
||||||
|
}
|
||||||
|
PushStructsNoZero(arena, u8, bytes_read);
|
||||||
|
CopyBytes(result.output.text + result.output.len, buff, bytes_read);
|
||||||
|
result.output.len += bytes_read;
|
||||||
}
|
}
|
||||||
|
if (exit_code_valid)
|
||||||
/* Read process output */
|
|
||||||
if (ok)
|
|
||||||
{
|
{
|
||||||
result.output.text = ArenaNext(arena, u8);
|
result.code = exit_code;
|
||||||
b32 exit_code_valid = 0;
|
|
||||||
DWORD exit_code = 0;
|
|
||||||
b32 stdout_finished = 0;
|
|
||||||
while (!stdout_finished)
|
|
||||||
{
|
|
||||||
u8 buff[4096] = Zi;
|
|
||||||
DWORD bytes_read = 0;
|
|
||||||
if (!ReadFile(pipe_read, buff, countof(buff), &bytes_read, 0))
|
|
||||||
{
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
if (err == ERROR_BROKEN_PIPE)
|
|
||||||
{
|
|
||||||
GetExitCodeProcess(process, &exit_code);
|
|
||||||
exit_code_valid = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.output.len += W32_StringFromError(arena, err).len;
|
|
||||||
}
|
|
||||||
stdout_finished = 1;
|
|
||||||
}
|
|
||||||
PushStructsNoZero(arena, u8, bytes_read);
|
|
||||||
CopyBytes(result.output.text + result.output.len, buff, bytes_read);
|
|
||||||
result.output.len += bytes_read;
|
|
||||||
}
|
|
||||||
if (exit_code_valid)
|
|
||||||
{
|
|
||||||
result.code = exit_code;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Close handles */
|
/* Close handles */
|
||||||
if (attrs) DeleteProcThreadAttributeList(attrs);
|
if (attrs) DeleteProcThreadAttributeList(attrs);
|
||||||
if (process_thread) CloseHandle(process_thread);
|
if (process_thread) CloseHandle(process_thread);
|
||||||
if (process) CloseHandle(process);
|
if (process) CloseHandle(process);
|
||||||
if (child_pipe_write) CloseHandle(child_pipe_write);
|
if (child_pipe_write) CloseHandle(child_pipe_write);
|
||||||
if (pipe_read) CloseHandle(pipe_read);
|
if (pipe_read) CloseHandle(pipe_read);
|
||||||
if (pipe_write) CloseHandle(pipe_write);
|
if (pipe_write) CloseHandle(pipe_write);
|
||||||
|
|
||||||
if (!ok && result.code == 0)
|
if (!ok && result.code == 0)
|
||||||
{
|
{
|
||||||
result.code = -1;
|
result.code = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,10 +21,10 @@ MIX_SharedState M_shared_state = ZI;
|
|||||||
|
|
||||||
void MIX_Bootstrap(void)
|
void MIX_Bootstrap(void)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
g->track_arena = AcquireArena(Gibi(64));
|
g->track_arena = AcquireArena(Gibi(64));
|
||||||
g->listener_pos = VEC2(0, 0);
|
g->listener_pos = VEC2(0, 0);
|
||||||
g->listener_dir = VEC2(0, -1);
|
g->listener_dir = VEC2(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -32,187 +32,187 @@ void MIX_Bootstrap(void)
|
|||||||
|
|
||||||
MIX_Handle MIX_HandleFromTrack(MIX_Track *track)
|
MIX_Handle MIX_HandleFromTrack(MIX_Track *track)
|
||||||
{
|
{
|
||||||
MIX_Handle result = ZI;
|
MIX_Handle result = ZI;
|
||||||
result.gen = track->gen;
|
result.gen = track->gen;
|
||||||
result.data = track;
|
result.data = track;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIX_Track *MIX_TrackFromHandle(MIX_Handle handle)
|
MIX_Track *MIX_TrackFromHandle(MIX_Handle handle)
|
||||||
{
|
{
|
||||||
MIX_Track *track = (MIX_Track *)handle.data;
|
MIX_Track *track = (MIX_Track *)handle.data;
|
||||||
if (track && track->gen == handle.gen)
|
if (track && track->gen == handle.gen)
|
||||||
{
|
{
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIX_Track *MIX_AcquireTrackLocked(Lock *lock, SND_Sound *sound)
|
MIX_Track *MIX_AcquireTrackLocked(Lock *lock, SND_Sound *sound)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
AssertLockedE(lock, &g->mutex);
|
AssertLockedE(lock, &g->mutex);
|
||||||
|
|
||||||
MIX_Track *track = 0;
|
MIX_Track *track = 0;
|
||||||
if (g->track_first_free)
|
if (g->track_first_free)
|
||||||
|
{
|
||||||
|
/* Take from free list */
|
||||||
|
track = g->track_first_free;
|
||||||
|
MIX_Track *next_free = track->next;
|
||||||
|
g->track_first_free = next_free;
|
||||||
|
if (next_free)
|
||||||
{
|
{
|
||||||
/* Take from free list */
|
next_free->prev = 0;
|
||||||
track = g->track_first_free;
|
|
||||||
MIX_Track *next_free = track->next;
|
|
||||||
g->track_first_free = next_free;
|
|
||||||
if (next_free)
|
|
||||||
{
|
|
||||||
next_free->prev = 0;
|
|
||||||
}
|
|
||||||
*track = (MIX_Track) { .gen = track->gen + 1 };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Acquire new */
|
|
||||||
track = PushStruct(g->track_arena, MIX_Track);
|
|
||||||
track->gen = 1;
|
|
||||||
}
|
}
|
||||||
|
*track = (MIX_Track) { .gen = track->gen + 1 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Acquire new */
|
||||||
|
track = PushStruct(g->track_arena, MIX_Track);
|
||||||
|
track->gen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
track->sound = sound;
|
track->sound = sound;
|
||||||
track->mix.source = sound;
|
track->mix.source = sound;
|
||||||
track->mix.track_handle = MIX_HandleFromTrack(track);
|
track->mix.track_handle = MIX_HandleFromTrack(track);
|
||||||
|
|
||||||
/* Append to playing list */
|
/* Append to playing list */
|
||||||
MIX_Track *prev = g->track_last_playing;
|
MIX_Track *prev = g->track_last_playing;
|
||||||
if (prev)
|
if (prev)
|
||||||
{
|
{
|
||||||
prev->next = track;
|
prev->next = track;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g->track_first_playing = track;
|
g->track_first_playing = track;
|
||||||
}
|
}
|
||||||
g->track_last_playing = track;
|
g->track_last_playing = track;
|
||||||
track->prev = prev;
|
track->prev = prev;
|
||||||
++g->track_playing_count;
|
++g->track_playing_count;
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIX_ReleaseTrackLocked(Lock *lock, MIX_Track *track)
|
void MIX_ReleaseTrackLocked(Lock *lock, MIX_Track *track)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
AssertLockedE(lock, &g->mutex);
|
AssertLockedE(lock, &g->mutex);
|
||||||
|
|
||||||
/* Remove from playing list */
|
/* Remove from playing list */
|
||||||
MIX_Track *prev = track->prev;
|
MIX_Track *prev = track->prev;
|
||||||
MIX_Track *next = track->next;
|
MIX_Track *next = track->next;
|
||||||
if (prev)
|
if (prev)
|
||||||
{
|
{
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Track was first in list */
|
/* Track was first in list */
|
||||||
g->track_first_playing = next;
|
g->track_first_playing = next;
|
||||||
}
|
}
|
||||||
if (next)
|
if (next)
|
||||||
{
|
{
|
||||||
next->prev = prev;
|
next->prev = prev;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Track was last in list */
|
/* Track was last in list */
|
||||||
g->track_last_playing = prev;
|
g->track_last_playing = prev;
|
||||||
}
|
}
|
||||||
--g->track_playing_count;
|
--g->track_playing_count;
|
||||||
++track->gen;
|
++track->gen;
|
||||||
|
|
||||||
/* Add to free list */
|
/* Add to free list */
|
||||||
track->prev = 0;
|
track->prev = 0;
|
||||||
track->next = g->track_first_free;
|
track->next = g->track_first_free;
|
||||||
if (g->track_first_free)
|
if (g->track_first_free)
|
||||||
{
|
{
|
||||||
g->track_first_free->prev = track;
|
g->track_first_free->prev = track;
|
||||||
}
|
}
|
||||||
g->track_first_free = track;
|
g->track_first_free = track;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Rework interface to be command based instead of directly modifying tracks. */
|
/* TODO: Rework interface to be command based instead of directly modifying tracks. */
|
||||||
|
|
||||||
MIX_Handle MIX_PlaySound(SND_Sound *sound)
|
MIX_Handle MIX_PlaySound(SND_Sound *sound)
|
||||||
{
|
{
|
||||||
return MIX_PlaySoundEx(sound, M_TRACKDESC());
|
return MIX_PlaySoundEx(sound, M_TRACKDESC());
|
||||||
}
|
}
|
||||||
|
|
||||||
MIX_Handle MIX_PlaySoundEx(SND_Sound *sound, MIX_TrackDesc desc)
|
MIX_Handle MIX_PlaySoundEx(SND_Sound *sound, MIX_TrackDesc desc)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
MIX_Track *track;
|
MIX_Track *track;
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&g->mutex);
|
track = MIX_AcquireTrackLocked(&lock, sound);
|
||||||
{
|
track->desc = desc;
|
||||||
track = MIX_AcquireTrackLocked(&lock, sound);
|
|
||||||
track->desc = desc;
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
return MIX_HandleFromTrack(track);
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
return MIX_HandleFromTrack(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: This is quite inefficient. */
|
/* NOTE: This is quite inefficient. */
|
||||||
MIX_TrackDesc MIX_TrackDescFromHandle(MIX_Handle handle)
|
MIX_TrackDesc MIX_TrackDescFromHandle(MIX_Handle handle)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
MIX_TrackDesc result = ZI;
|
MIX_TrackDesc result = ZI;
|
||||||
|
|
||||||
MIX_Track *track = MIX_TrackFromHandle(handle);
|
MIX_Track *track = MIX_TrackFromHandle(handle);
|
||||||
if (track)
|
if (track)
|
||||||
|
{
|
||||||
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
Lock lock = LockE(&g->mutex);
|
track = MIX_TrackFromHandle(handle);
|
||||||
{
|
if (track)
|
||||||
/* Confirm handle is still valid now that we're locked */
|
{
|
||||||
track = MIX_TrackFromHandle(handle);
|
result = track->desc;
|
||||||
if (track)
|
}
|
||||||
{
|
|
||||||
result = track->desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: This is quite inefficient. */
|
/* NOTE: This is quite inefficient. */
|
||||||
void MIX_UpdateTrack(MIX_Handle handle, MIX_TrackDesc desc)
|
void MIX_UpdateTrack(MIX_Handle handle, MIX_TrackDesc desc)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
MIX_Track *track = MIX_TrackFromHandle(handle);
|
MIX_Track *track = MIX_TrackFromHandle(handle);
|
||||||
if (track)
|
if (track)
|
||||||
|
{
|
||||||
|
/* TODO: Only lock mutex on track itself or something */
|
||||||
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
/* TODO: Only lock mutex on track itself or something */
|
/* Confirm handle is still valid now that we're locked */
|
||||||
Lock lock = LockE(&g->mutex);
|
track = MIX_TrackFromHandle(handle);
|
||||||
{
|
if (track)
|
||||||
/* Confirm handle is still valid now that we're locked */
|
{
|
||||||
track = MIX_TrackFromHandle(handle);
|
track->desc = desc;
|
||||||
if (track)
|
}
|
||||||
{
|
|
||||||
track->desc = desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIX_UpdateListener(Vec2 pos, Vec2 dir)
|
void MIX_UpdateListener(Vec2 pos, Vec2 dir)
|
||||||
{
|
{
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
Lock lock = LockE(&g->mutex);
|
Lock lock = LockE(&g->mutex);
|
||||||
{
|
{
|
||||||
g->listener_pos = pos;
|
g->listener_pos = pos;
|
||||||
g->listener_dir = NormVec2(dir);
|
g->listener_dir = NormVec2(dir);
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -220,250 +220,250 @@ void MIX_UpdateListener(Vec2 pos, Vec2 dir)
|
|||||||
|
|
||||||
i16 MIX_SampleSound(SND_Sound *sound, u64 sample_pos, b32 wrap)
|
i16 MIX_SampleSound(SND_Sound *sound, u64 sample_pos, b32 wrap)
|
||||||
{
|
{
|
||||||
if (wrap)
|
if (wrap)
|
||||||
{
|
{
|
||||||
return sound->samples[sample_pos % sound->samples_count];
|
return sound->samples[sample_pos % sound->samples_count];
|
||||||
}
|
}
|
||||||
else if (sample_pos < sound->samples_count)
|
else if (sample_pos < sound->samples_count)
|
||||||
{
|
{
|
||||||
return sound->samples[sample_pos];
|
return sound->samples[sample_pos];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To be called once per audio playback interval */
|
/* To be called once per audio playback interval */
|
||||||
MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
MIX_PcmF32 MIX_MixAllTracks(Arena *arena, u64 frame_count)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
MIX_SharedState *g = &M_shared_state;
|
MIX_SharedState *g = &M_shared_state;
|
||||||
|
|
||||||
MIX_PcmF32 result = ZI;
|
MIX_PcmF32 result = ZI;
|
||||||
result.count = frame_count * 2;
|
result.count = frame_count * 2;
|
||||||
result.samples = PushStructs(arena, f32, result.count);
|
result.samples = PushStructs(arena, f32, result.count);
|
||||||
|
|
||||||
Vec2 listener_pos = VEC2(0, 0);
|
Vec2 listener_pos = VEC2(0, 0);
|
||||||
Vec2 listener_dir = VEC2(0, 0);
|
Vec2 listener_dir = VEC2(0, 0);
|
||||||
|
|
||||||
//- Create temp mix array
|
//- Create temp mix array
|
||||||
|
|
||||||
MIX_MixData **mixes = 0;
|
MIX_MixData **mixes = 0;
|
||||||
u64 mixes_count = 0;
|
u64 mixes_count = 0;
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&g->mutex);
|
||||||
|
|
||||||
|
/* Read listener info */
|
||||||
|
listener_pos = g->listener_pos;
|
||||||
|
listener_dir = g->listener_dir;
|
||||||
|
|
||||||
|
/* Update & read mixes */
|
||||||
|
mixes = PushStructsNoZero(scratch.arena, MIX_MixData *, g->track_playing_count);
|
||||||
|
for (MIX_Track *track = g->track_first_playing; track; track = track->next)
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&g->mutex);
|
MIX_MixData *mix = &track->mix;
|
||||||
|
mix->desc = track->desc;
|
||||||
/* Read listener info */
|
mixes[mixes_count++] = mix;
|
||||||
listener_pos = g->listener_pos;
|
|
||||||
listener_dir = g->listener_dir;
|
|
||||||
|
|
||||||
/* Update & read mixes */
|
|
||||||
mixes = PushStructsNoZero(scratch.arena, MIX_MixData *, g->track_playing_count);
|
|
||||||
for (MIX_Track *track = g->track_first_playing; track; track = track->next)
|
|
||||||
{
|
|
||||||
MIX_MixData *mix = &track->mix;
|
|
||||||
mix->desc = track->desc;
|
|
||||||
mixes[mixes_count++] = mix;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Process mix data
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index)
|
//- Process mix data
|
||||||
|
|
||||||
|
for (u64 mix_index = 0; mix_index < mixes_count; ++mix_index)
|
||||||
|
{
|
||||||
|
MIX_MixData *mix = mixes[mix_index];
|
||||||
|
|
||||||
|
if (mix->source->samples_count <= 0)
|
||||||
{
|
{
|
||||||
MIX_MixData *mix = mixes[mix_index];
|
/* Skip empty sounds */
|
||||||
|
continue;
|
||||||
if (mix->source->samples_count <= 0)
|
|
||||||
{
|
|
||||||
/* Skip empty sounds */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SND_Sound *source = mix->source;
|
|
||||||
MIX_TrackDesc desc = mix->desc;
|
|
||||||
MIX_EffectData *effect_data = &mix->effect_data;
|
|
||||||
b32 source_is_stereo = source->flags & SND_SoundFlag_Stereo;
|
|
||||||
f32 speed = MaxF32(0, desc.speed);
|
|
||||||
|
|
||||||
//- Determine sample range
|
|
||||||
u64 source_samples_count = 0;
|
|
||||||
if (source_is_stereo)
|
|
||||||
{
|
|
||||||
source_samples_count = frame_count * 2;
|
|
||||||
/* Round <samples_count * speed> to nearest frame boundary (nearest multiple of 2) */
|
|
||||||
source_samples_count = (u64)CeilF32ToI32((f32)source_samples_count * speed);
|
|
||||||
source_samples_count &= ~1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
source_samples_count = frame_count;
|
|
||||||
/* Round <samples_count * speed> to nearest sample */
|
|
||||||
source_samples_count = (u64)RoundF32ToI32((f32)source_samples_count * speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 source_sample_pos_start = mix->source_pos;
|
|
||||||
u64 source_sample_pos_end = source_sample_pos_start + source_samples_count;
|
|
||||||
if (source_sample_pos_end >= source->samples_count)
|
|
||||||
{
|
|
||||||
if (desc.looping)
|
|
||||||
{
|
|
||||||
source_sample_pos_end = source_sample_pos_end % source->samples_count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
source_sample_pos_end = source->samples_count;
|
|
||||||
mix->track_finished = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u64 source_frames_count = source_is_stereo ? source_samples_count / 2 : source_samples_count;
|
|
||||||
u64 source_frame_pos_start = source_is_stereo ? source_sample_pos_start / 2 : source_sample_pos_start;
|
|
||||||
|
|
||||||
mix->source_pos = source_sample_pos_end;
|
|
||||||
|
|
||||||
MIX_PcmF32 mix_pcm = {
|
|
||||||
.count = result.count,
|
|
||||||
.samples = PushStructs(scratch.arena, f32, result.count)
|
|
||||||
};
|
|
||||||
|
|
||||||
//- Resample
|
|
||||||
/* Transform 16 bit source -> 32 bit stereo at output duration */
|
|
||||||
{
|
|
||||||
f32 *out_samples = mix_pcm.samples;
|
|
||||||
|
|
||||||
u64 out_frames_count = mix_pcm.count / 2;
|
|
||||||
|
|
||||||
/* TODO: Fast path for 1:1 copy when speed = 1.0? */
|
|
||||||
/* TODO: Optimize */
|
|
||||||
if (source_is_stereo)
|
|
||||||
{
|
|
||||||
/* 16 bit Stereo -> 32 bit Stereo */
|
|
||||||
for (u64 out_frame_pos = 0; out_frame_pos < out_frames_count; ++out_frame_pos)
|
|
||||||
{
|
|
||||||
f32 in_frame_pos_exact = source_frame_pos_start + (((f32)out_frame_pos / (f32)out_frames_count) * (f32)source_frames_count);
|
|
||||||
u32 in_frame_pos_prev = FloorF32ToI32(in_frame_pos_exact);
|
|
||||||
u32 in_frame_pos_next = CeilF32ToI32(in_frame_pos_exact);
|
|
||||||
|
|
||||||
/* Sample source */
|
|
||||||
f32 sample1_prev = MIX_SampleSound(source, (in_frame_pos_prev * 2) + 0, desc.looping) * (1.f / 32768.f);
|
|
||||||
f32 sample1_next = MIX_SampleSound(source, (in_frame_pos_next * 2) + 0, desc.looping) * (1.f / 32768.f);
|
|
||||||
f32 sample2_prev = MIX_SampleSound(source, (in_frame_pos_prev * 2) + 1, desc.looping) * (1.f / 32768.f);
|
|
||||||
f32 sample2_next = MIX_SampleSound(source, (in_frame_pos_next * 2) + 1, desc.looping) * (1.f / 32768.f);
|
|
||||||
|
|
||||||
/* Lerp */
|
|
||||||
f32 t = in_frame_pos_exact - (f32)in_frame_pos_prev;
|
|
||||||
f32 sample1 = LerpF32(sample1_prev, sample1_next, t);
|
|
||||||
f32 sample2 = LerpF32(sample2_prev, sample2_next, t);
|
|
||||||
|
|
||||||
out_samples[(out_frame_pos * 2) + 0] += sample1;
|
|
||||||
out_samples[(out_frame_pos * 2) + 1] += sample2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 16 bit Mono -> 32 bit Stereo */
|
|
||||||
for (u64 out_frame_pos = 0; out_frame_pos < out_frames_count; ++out_frame_pos)
|
|
||||||
{
|
|
||||||
f32 in_frame_pos_exact = source_frame_pos_start + (((f32)out_frame_pos / (f32)out_frames_count) * (f32)source_frames_count);
|
|
||||||
u32 in_frame_pos_prev = FloorF32ToI32(in_frame_pos_exact);
|
|
||||||
u32 in_frame_pos_next = CeilF32ToI32(in_frame_pos_exact);
|
|
||||||
|
|
||||||
/* Sample source */
|
|
||||||
f32 sample_prev = MIX_SampleSound(source, in_frame_pos_prev, desc.looping) * (1.f / 32768.f);
|
|
||||||
f32 sample_next = MIX_SampleSound(source, in_frame_pos_next, desc.looping) * (1.f / 32768.f);
|
|
||||||
|
|
||||||
/* Lerp */
|
|
||||||
f32 t = (f32)in_frame_pos_exact - in_frame_pos_prev;
|
|
||||||
f32 sample = LerpF32(sample_prev, sample_next, t);
|
|
||||||
|
|
||||||
out_samples[(out_frame_pos * 2) + 0] += sample;
|
|
||||||
out_samples[(out_frame_pos * 2) + 1] += sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Spatialize
|
|
||||||
if (desc.flags & MIX_TrackFlag_Spatialize)
|
|
||||||
{
|
|
||||||
/* Algorithm constants */
|
|
||||||
const f32 rolloff_height = 1.2f;
|
|
||||||
const f32 rolloff_scale = 6.0f;
|
|
||||||
const f32 pan_scale = 0.75;
|
|
||||||
|
|
||||||
Vec2 pos = desc.pos;
|
|
||||||
|
|
||||||
/* If sound pos = listener pos, pretend sound is close in front of listener. */
|
|
||||||
if (MatchVec2(listener_pos, pos))
|
|
||||||
{
|
|
||||||
pos = AddVec2(listener_pos, MulVec2(listener_dir, 0.001f));
|
|
||||||
}
|
|
||||||
Vec2 sound_rel = SubVec2(pos, listener_pos);
|
|
||||||
Vec2 sound_rel_dir = NormVec2(sound_rel);
|
|
||||||
|
|
||||||
/* Compute volume */
|
|
||||||
f32 volume_start = effect_data->spatial_volume;
|
|
||||||
f32 volume_end;
|
|
||||||
{
|
|
||||||
/* https://www.desmos.com/calculator/c2h941hobz
|
|
||||||
* h = `rolloff_height`
|
|
||||||
* s = `rolloff_scale`
|
|
||||||
*/
|
|
||||||
f32 dist = Vec2Len(sound_rel);
|
|
||||||
f32 v = (dist / rolloff_scale) + 1.0f;
|
|
||||||
volume_end = rolloff_height * (1.0f / (v * v));
|
|
||||||
}
|
|
||||||
effect_data->spatial_volume = volume_end;
|
|
||||||
|
|
||||||
/* Compute pan */
|
|
||||||
f32 pan_start = effect_data->spatial_pan;
|
|
||||||
f32 pan_end = WedgeVec2(listener_dir, sound_rel_dir) * pan_scale;
|
|
||||||
effect_data->spatial_pan = pan_end;
|
|
||||||
|
|
||||||
/* Spatialize samples */
|
|
||||||
for (u64 frame_pos = 0; frame_pos < frame_count; ++frame_pos)
|
|
||||||
{
|
|
||||||
f32 t = (f32)frame_pos / (f32)(frame_count - 1);
|
|
||||||
f32 volume = LerpF32(volume_start, volume_end, t);
|
|
||||||
f32 pan = LerpF32(pan_start, pan_end, t);
|
|
||||||
|
|
||||||
u64 sample1_index = frame_pos * 2;
|
|
||||||
u64 sample2_index = sample1_index + 1;
|
|
||||||
|
|
||||||
f32 sample_mono = ((mix_pcm.samples[sample1_index + 0] / 2.0f) + (mix_pcm.samples[sample2_index] / 2.0f)) * volume;
|
|
||||||
|
|
||||||
mix_pcm.samples[sample1_index] = sample_mono * (1.0f - pan);
|
|
||||||
mix_pcm.samples[sample2_index] = sample_mono * (1.0f + pan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Mix into result
|
|
||||||
for (u64 i = 0; i < mix_pcm.count; ++i)
|
|
||||||
{
|
|
||||||
result.samples[i] += mix_pcm.samples[i] * desc.volume;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Update track effect data
|
SND_Sound *source = mix->source;
|
||||||
|
MIX_TrackDesc desc = mix->desc;
|
||||||
|
MIX_EffectData *effect_data = &mix->effect_data;
|
||||||
|
b32 source_is_stereo = source->flags & SND_SoundFlag_Stereo;
|
||||||
|
f32 speed = MaxF32(0, desc.speed);
|
||||||
|
|
||||||
|
//- Determine sample range
|
||||||
|
u64 source_samples_count = 0;
|
||||||
|
if (source_is_stereo)
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&g->mutex);
|
source_samples_count = frame_count * 2;
|
||||||
for (u64 i = 0; i < mixes_count; ++i)
|
/* Round <samples_count * speed> to nearest frame boundary (nearest multiple of 2) */
|
||||||
{
|
source_samples_count = (u64)CeilF32ToI32((f32)source_samples_count * speed);
|
||||||
MIX_MixData *mix = mixes[i];
|
source_samples_count &= ~1;
|
||||||
MIX_Track *track = MIX_TrackFromHandle(mix->track_handle);
|
}
|
||||||
if (track)
|
else
|
||||||
{
|
{
|
||||||
if (mix->track_finished)
|
source_samples_count = frame_count;
|
||||||
{
|
/* Round <samples_count * speed> to nearest sample */
|
||||||
/* Release finished tracks */
|
source_samples_count = (u64)RoundF32ToI32((f32)source_samples_count * speed);
|
||||||
MIX_ReleaseTrackLocked(&lock, track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScratch(scratch);
|
u64 source_sample_pos_start = mix->source_pos;
|
||||||
return result;
|
u64 source_sample_pos_end = source_sample_pos_start + source_samples_count;
|
||||||
|
if (source_sample_pos_end >= source->samples_count)
|
||||||
|
{
|
||||||
|
if (desc.looping)
|
||||||
|
{
|
||||||
|
source_sample_pos_end = source_sample_pos_end % source->samples_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
source_sample_pos_end = source->samples_count;
|
||||||
|
mix->track_finished = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u64 source_frames_count = source_is_stereo ? source_samples_count / 2 : source_samples_count;
|
||||||
|
u64 source_frame_pos_start = source_is_stereo ? source_sample_pos_start / 2 : source_sample_pos_start;
|
||||||
|
|
||||||
|
mix->source_pos = source_sample_pos_end;
|
||||||
|
|
||||||
|
MIX_PcmF32 mix_pcm = {
|
||||||
|
.count = result.count,
|
||||||
|
.samples = PushStructs(scratch.arena, f32, result.count)
|
||||||
|
};
|
||||||
|
|
||||||
|
//- Resample
|
||||||
|
/* Transform 16 bit source -> 32 bit stereo at output duration */
|
||||||
|
{
|
||||||
|
f32 *out_samples = mix_pcm.samples;
|
||||||
|
|
||||||
|
u64 out_frames_count = mix_pcm.count / 2;
|
||||||
|
|
||||||
|
/* TODO: Fast path for 1:1 copy when speed = 1.0? */
|
||||||
|
/* TODO: Optimize */
|
||||||
|
if (source_is_stereo)
|
||||||
|
{
|
||||||
|
/* 16 bit Stereo -> 32 bit Stereo */
|
||||||
|
for (u64 out_frame_pos = 0; out_frame_pos < out_frames_count; ++out_frame_pos)
|
||||||
|
{
|
||||||
|
f32 in_frame_pos_exact = source_frame_pos_start + (((f32)out_frame_pos / (f32)out_frames_count) * (f32)source_frames_count);
|
||||||
|
u32 in_frame_pos_prev = FloorF32ToI32(in_frame_pos_exact);
|
||||||
|
u32 in_frame_pos_next = CeilF32ToI32(in_frame_pos_exact);
|
||||||
|
|
||||||
|
/* Sample source */
|
||||||
|
f32 sample1_prev = MIX_SampleSound(source, (in_frame_pos_prev * 2) + 0, desc.looping) * (1.f / 32768.f);
|
||||||
|
f32 sample1_next = MIX_SampleSound(source, (in_frame_pos_next * 2) + 0, desc.looping) * (1.f / 32768.f);
|
||||||
|
f32 sample2_prev = MIX_SampleSound(source, (in_frame_pos_prev * 2) + 1, desc.looping) * (1.f / 32768.f);
|
||||||
|
f32 sample2_next = MIX_SampleSound(source, (in_frame_pos_next * 2) + 1, desc.looping) * (1.f / 32768.f);
|
||||||
|
|
||||||
|
/* Lerp */
|
||||||
|
f32 t = in_frame_pos_exact - (f32)in_frame_pos_prev;
|
||||||
|
f32 sample1 = LerpF32(sample1_prev, sample1_next, t);
|
||||||
|
f32 sample2 = LerpF32(sample2_prev, sample2_next, t);
|
||||||
|
|
||||||
|
out_samples[(out_frame_pos * 2) + 0] += sample1;
|
||||||
|
out_samples[(out_frame_pos * 2) + 1] += sample2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 16 bit Mono -> 32 bit Stereo */
|
||||||
|
for (u64 out_frame_pos = 0; out_frame_pos < out_frames_count; ++out_frame_pos)
|
||||||
|
{
|
||||||
|
f32 in_frame_pos_exact = source_frame_pos_start + (((f32)out_frame_pos / (f32)out_frames_count) * (f32)source_frames_count);
|
||||||
|
u32 in_frame_pos_prev = FloorF32ToI32(in_frame_pos_exact);
|
||||||
|
u32 in_frame_pos_next = CeilF32ToI32(in_frame_pos_exact);
|
||||||
|
|
||||||
|
/* Sample source */
|
||||||
|
f32 sample_prev = MIX_SampleSound(source, in_frame_pos_prev, desc.looping) * (1.f / 32768.f);
|
||||||
|
f32 sample_next = MIX_SampleSound(source, in_frame_pos_next, desc.looping) * (1.f / 32768.f);
|
||||||
|
|
||||||
|
/* Lerp */
|
||||||
|
f32 t = (f32)in_frame_pos_exact - in_frame_pos_prev;
|
||||||
|
f32 sample = LerpF32(sample_prev, sample_next, t);
|
||||||
|
|
||||||
|
out_samples[(out_frame_pos * 2) + 0] += sample;
|
||||||
|
out_samples[(out_frame_pos * 2) + 1] += sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Spatialize
|
||||||
|
if (desc.flags & MIX_TrackFlag_Spatialize)
|
||||||
|
{
|
||||||
|
/* Algorithm constants */
|
||||||
|
const f32 rolloff_height = 1.2f;
|
||||||
|
const f32 rolloff_scale = 6.0f;
|
||||||
|
const f32 pan_scale = 0.75;
|
||||||
|
|
||||||
|
Vec2 pos = desc.pos;
|
||||||
|
|
||||||
|
/* If sound pos = listener pos, pretend sound is close in front of listener. */
|
||||||
|
if (MatchVec2(listener_pos, pos))
|
||||||
|
{
|
||||||
|
pos = AddVec2(listener_pos, MulVec2(listener_dir, 0.001f));
|
||||||
|
}
|
||||||
|
Vec2 sound_rel = SubVec2(pos, listener_pos);
|
||||||
|
Vec2 sound_rel_dir = NormVec2(sound_rel);
|
||||||
|
|
||||||
|
/* Compute volume */
|
||||||
|
f32 volume_start = effect_data->spatial_volume;
|
||||||
|
f32 volume_end;
|
||||||
|
{
|
||||||
|
/* https://www.desmos.com/calculator/c2h941hobz
|
||||||
|
* h = `rolloff_height`
|
||||||
|
* s = `rolloff_scale`
|
||||||
|
*/
|
||||||
|
f32 dist = Vec2Len(sound_rel);
|
||||||
|
f32 v = (dist / rolloff_scale) + 1.0f;
|
||||||
|
volume_end = rolloff_height * (1.0f / (v * v));
|
||||||
|
}
|
||||||
|
effect_data->spatial_volume = volume_end;
|
||||||
|
|
||||||
|
/* Compute pan */
|
||||||
|
f32 pan_start = effect_data->spatial_pan;
|
||||||
|
f32 pan_end = WedgeVec2(listener_dir, sound_rel_dir) * pan_scale;
|
||||||
|
effect_data->spatial_pan = pan_end;
|
||||||
|
|
||||||
|
/* Spatialize samples */
|
||||||
|
for (u64 frame_pos = 0; frame_pos < frame_count; ++frame_pos)
|
||||||
|
{
|
||||||
|
f32 t = (f32)frame_pos / (f32)(frame_count - 1);
|
||||||
|
f32 volume = LerpF32(volume_start, volume_end, t);
|
||||||
|
f32 pan = LerpF32(pan_start, pan_end, t);
|
||||||
|
|
||||||
|
u64 sample1_index = frame_pos * 2;
|
||||||
|
u64 sample2_index = sample1_index + 1;
|
||||||
|
|
||||||
|
f32 sample_mono = ((mix_pcm.samples[sample1_index + 0] / 2.0f) + (mix_pcm.samples[sample2_index] / 2.0f)) * volume;
|
||||||
|
|
||||||
|
mix_pcm.samples[sample1_index] = sample_mono * (1.0f - pan);
|
||||||
|
mix_pcm.samples[sample2_index] = sample_mono * (1.0f + pan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Mix into result
|
||||||
|
for (u64 i = 0; i < mix_pcm.count; ++i)
|
||||||
|
{
|
||||||
|
result.samples[i] += mix_pcm.samples[i] * desc.volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Update track effect data
|
||||||
|
{
|
||||||
|
Lock lock = LockE(&g->mutex);
|
||||||
|
for (u64 i = 0; i < mixes_count; ++i)
|
||||||
|
{
|
||||||
|
MIX_MixData *mix = mixes[i];
|
||||||
|
MIX_Track *track = MIX_TrackFromHandle(mix->track_handle);
|
||||||
|
if (track)
|
||||||
|
{
|
||||||
|
if (mix->track_finished)
|
||||||
|
{
|
||||||
|
/* Release finished tracks */
|
||||||
|
MIX_ReleaseTrackLocked(&lock, track);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndScratch(scratch);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,33 +3,33 @@
|
|||||||
|
|
||||||
Enum(MIX_TrackFlag)
|
Enum(MIX_TrackFlag)
|
||||||
{
|
{
|
||||||
MIX_TrackFlag_None = 0,
|
MIX_TrackFlag_None = 0,
|
||||||
MIX_TrackFlag_Spatialize = (1 << 0)
|
MIX_TrackFlag_Spatialize = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MIX_Handle)
|
Struct(MIX_Handle)
|
||||||
{
|
{
|
||||||
u64 gen;
|
u64 gen;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MIX_TrackDesc)
|
Struct(MIX_TrackDesc)
|
||||||
{
|
{
|
||||||
MIX_TrackFlag flags;
|
MIX_TrackFlag flags;
|
||||||
f32 volume; /* 0 -> 1.0+ */
|
f32 volume; /* 0 -> 1.0+ */
|
||||||
f32 speed; /* 0 -> 1.0+ */
|
f32 speed; /* 0 -> 1.0+ */
|
||||||
b32 looping;
|
b32 looping;
|
||||||
|
|
||||||
/* MIX_TrackFlag_Spatialize */
|
/* MIX_TrackFlag_Spatialize */
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
};
|
};
|
||||||
#define M_TRACKDESC(...) ((MIX_TrackDesc) { \
|
#define M_TRACKDESC(...) ((MIX_TrackDesc) { \
|
||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.volume = 1.0, \
|
.volume = 1.0, \
|
||||||
.speed = 1.0, \
|
.speed = 1.0, \
|
||||||
.looping = 0, \
|
.looping = 0, \
|
||||||
.pos = VEC2(0, 0), \
|
.pos = VEC2(0, 0), \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -38,40 +38,40 @@ Struct(MIX_TrackDesc)
|
|||||||
/* Stereo mix of 32 bit float samples */
|
/* Stereo mix of 32 bit float samples */
|
||||||
Struct(MIX_PcmF32)
|
Struct(MIX_PcmF32)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
f32 *samples;
|
f32 *samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MIX_EffectData)
|
Struct(MIX_EffectData)
|
||||||
{
|
{
|
||||||
/* Spatialization */
|
/* Spatialization */
|
||||||
f32 spatial_volume;
|
f32 spatial_volume;
|
||||||
f32 spatial_pan;
|
f32 spatial_pan;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MIX_MixData)
|
Struct(MIX_MixData)
|
||||||
{
|
{
|
||||||
MIX_Handle track_handle;
|
MIX_Handle track_handle;
|
||||||
b32 track_finished;
|
b32 track_finished;
|
||||||
|
|
||||||
MIX_TrackDesc desc;
|
MIX_TrackDesc desc;
|
||||||
MIX_EffectData effect_data;
|
MIX_EffectData effect_data;
|
||||||
SND_Sound *source;
|
SND_Sound *source;
|
||||||
u64 source_pos;
|
u64 source_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MIX_Track){
|
Struct(MIX_Track){
|
||||||
u64 gen;
|
u64 gen;
|
||||||
|
|
||||||
/* Controlled via interface */
|
/* Controlled via interface */
|
||||||
SND_Sound *sound;
|
SND_Sound *sound;
|
||||||
MIX_TrackDesc desc;
|
MIX_TrackDesc desc;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
MIX_MixData mix;
|
MIX_MixData mix;
|
||||||
|
|
||||||
MIX_Track *next;
|
MIX_Track *next;
|
||||||
MIX_Track *prev;
|
MIX_Track *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -79,18 +79,18 @@ Struct(MIX_Track){
|
|||||||
|
|
||||||
Struct(MIX_SharedState)
|
Struct(MIX_SharedState)
|
||||||
{
|
{
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
|
|
||||||
/* Listener */
|
/* Listener */
|
||||||
Vec2 listener_pos;
|
Vec2 listener_pos;
|
||||||
Vec2 listener_dir;
|
Vec2 listener_dir;
|
||||||
|
|
||||||
/* Track list */
|
/* Track list */
|
||||||
Arena *track_arena;
|
Arena *track_arena;
|
||||||
MIX_Track *track_first_playing;
|
MIX_Track *track_first_playing;
|
||||||
MIX_Track *track_last_playing;
|
MIX_Track *track_last_playing;
|
||||||
u64 track_playing_count;
|
u64 track_playing_count;
|
||||||
MIX_Track *track_first_free;
|
MIX_Track *track_first_free;
|
||||||
} extern M_shared_state;
|
} extern M_shared_state;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,15 +3,15 @@
|
|||||||
|
|
||||||
Enum(MP3_DecodeFlag)
|
Enum(MP3_DecodeFlag)
|
||||||
{
|
{
|
||||||
MP3_DecodeFlag_None = 0,
|
MP3_DecodeFlag_None = 0,
|
||||||
MP3_DecodeFlag_Stereo = (1 << 0),
|
MP3_DecodeFlag_Stereo = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(MP3_Result)
|
Struct(MP3_Result)
|
||||||
{
|
{
|
||||||
u64 samples_count;
|
u64 samples_count;
|
||||||
i16 *samples;
|
i16 *samples;
|
||||||
b32 ok;
|
b32 ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,114 +3,114 @@
|
|||||||
|
|
||||||
MP3_Result MP3_Decode(Arena *arena, String encoded, u32 sample_rate, MP3_DecodeFlag flags)
|
MP3_Result MP3_Decode(Arena *arena, String encoded, u32 sample_rate, MP3_DecodeFlag flags)
|
||||||
{
|
{
|
||||||
MP3_Result result = ZI;
|
MP3_Result result = ZI;
|
||||||
u64 bytes_per_sample = 2;
|
u64 bytes_per_sample = 2;
|
||||||
|
|
||||||
u64 channel_count;
|
u64 channel_count;
|
||||||
u32 channel_mask;
|
u32 channel_mask;
|
||||||
if (flags & MP3_DecodeFlag_Stereo)
|
if (flags & MP3_DecodeFlag_Stereo)
|
||||||
|
{
|
||||||
|
channel_count = 2;
|
||||||
|
channel_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channel_count = 1;
|
||||||
|
channel_mask = SPEAKER_FRONT_CENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Startup
|
||||||
|
|
||||||
|
MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
||||||
|
|
||||||
|
/* Create IStream from encoded string */
|
||||||
|
IStream *i_stream = SHCreateMemStream(encoded.text, encoded.len);
|
||||||
|
|
||||||
|
/* Create IMFByteStream from IStream */
|
||||||
|
IMFByteStream *byte_stream = 0;
|
||||||
|
MFCreateMFByteStreamOnStream(i_stream, &byte_stream);
|
||||||
|
|
||||||
|
/* Create reader from IMFByteStream */
|
||||||
|
IMFSourceReader *reader;
|
||||||
|
MFCreateSourceReaderFromByteStream(byte_stream, 0, &reader);
|
||||||
|
|
||||||
|
//- Get media type
|
||||||
|
|
||||||
|
/* Read only first audio stream */
|
||||||
|
IMFSourceReader_SetStreamSelection(reader, (DWORD)MF_SOURCE_READER_ALL_STREAMS, 0);
|
||||||
|
IMFSourceReader_SetStreamSelection(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 1);
|
||||||
|
|
||||||
|
WAVEFORMATEXTENSIBLE format = {
|
||||||
|
.Format = {
|
||||||
|
.wFormatTag = WAVE_FORMAT_EXTENSIBLE,
|
||||||
|
.nChannels = (WORD)channel_count,
|
||||||
|
.nSamplesPerSec = (WORD)sample_rate,
|
||||||
|
.nAvgBytesPerSec = (DWORD)(sample_rate * channel_count * bytes_per_sample),
|
||||||
|
.nBlockAlign = (WORD)(channel_count * bytes_per_sample),
|
||||||
|
.wBitsPerSample = (WORD)(8 * bytes_per_sample),
|
||||||
|
.cbSize = sizeof(format) - sizeof(format.Format)
|
||||||
|
},
|
||||||
|
.Samples.wValidBitsPerSample = 8 * bytes_per_sample,
|
||||||
|
.dwChannelMask = channel_mask,
|
||||||
|
.SubFormat = MEDIASUBTYPE_PCM
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Media Foundation in Windows 8+ allows reader to convert output to different format than native */
|
||||||
|
IMFMediaType *type;
|
||||||
|
MFCreateMediaType(&type);
|
||||||
|
MFInitMediaTypeFromWaveFormatEx(type, &format.Format, sizeof(format));
|
||||||
|
IMFSourceReader_SetCurrentMediaType(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, type);
|
||||||
|
IMFMediaType_Release(type);
|
||||||
|
|
||||||
|
//- Read
|
||||||
|
|
||||||
|
result.samples = ArenaNext(arena, i16);
|
||||||
|
u64 sample_bytes_read = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
IMFSample *sample;
|
||||||
|
DWORD sample_flags = 0;
|
||||||
|
HRESULT hr = IMFSourceReader_ReadSample(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, 0, &sample_flags, 0, &sample);
|
||||||
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
channel_count = 2;
|
break;
|
||||||
channel_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
channel_count = 1;
|
|
||||||
channel_mask = SPEAKER_FRONT_CENTER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Startup
|
/* Check if done */
|
||||||
|
if (sample_flags & MF_SOURCE_READERF_ENDOFSTREAM)
|
||||||
MFStartup(MF_VERSION, MFSTARTUP_LITE);
|
|
||||||
|
|
||||||
/* Create IStream from encoded string */
|
|
||||||
IStream *i_stream = SHCreateMemStream(encoded.text, encoded.len);
|
|
||||||
|
|
||||||
/* Create IMFByteStream from IStream */
|
|
||||||
IMFByteStream *byte_stream = 0;
|
|
||||||
MFCreateMFByteStreamOnStream(i_stream, &byte_stream);
|
|
||||||
|
|
||||||
/* Create reader from IMFByteStream */
|
|
||||||
IMFSourceReader *reader;
|
|
||||||
MFCreateSourceReaderFromByteStream(byte_stream, 0, &reader);
|
|
||||||
|
|
||||||
//- Get media type
|
|
||||||
|
|
||||||
/* Read only first audio stream */
|
|
||||||
IMFSourceReader_SetStreamSelection(reader, (DWORD)MF_SOURCE_READER_ALL_STREAMS, 0);
|
|
||||||
IMFSourceReader_SetStreamSelection(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 1);
|
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE format = {
|
|
||||||
.Format = {
|
|
||||||
.wFormatTag = WAVE_FORMAT_EXTENSIBLE,
|
|
||||||
.nChannels = (WORD)channel_count,
|
|
||||||
.nSamplesPerSec = (WORD)sample_rate,
|
|
||||||
.nAvgBytesPerSec = (DWORD)(sample_rate * channel_count * bytes_per_sample),
|
|
||||||
.nBlockAlign = (WORD)(channel_count * bytes_per_sample),
|
|
||||||
.wBitsPerSample = (WORD)(8 * bytes_per_sample),
|
|
||||||
.cbSize = sizeof(format) - sizeof(format.Format)
|
|
||||||
},
|
|
||||||
.Samples.wValidBitsPerSample = 8 * bytes_per_sample,
|
|
||||||
.dwChannelMask = channel_mask,
|
|
||||||
.SubFormat = MEDIASUBTYPE_PCM
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Media Foundation in Windows 8+ allows reader to convert output to different format than native */
|
|
||||||
IMFMediaType *type;
|
|
||||||
MFCreateMediaType(&type);
|
|
||||||
MFInitMediaTypeFromWaveFormatEx(type, &format.Format, sizeof(format));
|
|
||||||
IMFSourceReader_SetCurrentMediaType(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, type);
|
|
||||||
IMFMediaType_Release(type);
|
|
||||||
|
|
||||||
//- Read
|
|
||||||
|
|
||||||
result.samples = ArenaNext(arena, i16);
|
|
||||||
u64 sample_bytes_read = 0;
|
|
||||||
for (;;)
|
|
||||||
{
|
{
|
||||||
IMFSample *sample;
|
result.ok = 1;
|
||||||
DWORD sample_flags = 0;
|
break;
|
||||||
HRESULT hr = IMFSourceReader_ReadSample(reader, (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, 0, &sample_flags, 0, &sample);
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if done */
|
|
||||||
if (sample_flags & MF_SOURCE_READERF_ENDOFSTREAM)
|
|
||||||
{
|
|
||||||
result.ok = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Assert(sample_flags == 0);
|
|
||||||
|
|
||||||
/* Read samples */
|
|
||||||
IMFMediaBuffer *buffer;
|
|
||||||
IMFSample_ConvertToContiguousBuffer(sample, &buffer);
|
|
||||||
|
|
||||||
BYTE *src;
|
|
||||||
DWORD size_bytes;
|
|
||||||
IMFMediaBuffer_Lock(buffer, &src, 0, &size_bytes);
|
|
||||||
{
|
|
||||||
i16 *dst = PushStructsNoZero(arena, i16, (size_bytes + 1) >> 1);
|
|
||||||
CopyBytes(dst, src, size_bytes);
|
|
||||||
sample_bytes_read += size_bytes;
|
|
||||||
}
|
|
||||||
IMFMediaBuffer_Unlock(buffer);
|
|
||||||
|
|
||||||
IMediaBuffer_Release(buffer);
|
|
||||||
IMFSample_Release(sample);
|
|
||||||
}
|
}
|
||||||
|
Assert(sample_flags == 0);
|
||||||
|
|
||||||
result.samples_count = sample_bytes_read / bytes_per_sample;
|
/* Read samples */
|
||||||
|
IMFMediaBuffer *buffer;
|
||||||
|
IMFSample_ConvertToContiguousBuffer(sample, &buffer);
|
||||||
|
|
||||||
//- Cleanup
|
BYTE *src;
|
||||||
|
DWORD size_bytes;
|
||||||
|
IMFMediaBuffer_Lock(buffer, &src, 0, &size_bytes);
|
||||||
|
{
|
||||||
|
i16 *dst = PushStructsNoZero(arena, i16, (size_bytes + 1) >> 1);
|
||||||
|
CopyBytes(dst, src, size_bytes);
|
||||||
|
sample_bytes_read += size_bytes;
|
||||||
|
}
|
||||||
|
IMFMediaBuffer_Unlock(buffer);
|
||||||
|
|
||||||
IMFSourceReader_Release(reader);
|
IMediaBuffer_Release(buffer);
|
||||||
IMFByteStream_Close(byte_stream);
|
IMFSample_Release(sample);
|
||||||
/* FIXME: Enable this */
|
}
|
||||||
//IStream_Release(i_stream);
|
|
||||||
MFShutdown();
|
|
||||||
|
|
||||||
return result;
|
result.samples_count = sample_bytes_read / bytes_per_sample;
|
||||||
|
|
||||||
|
//- Cleanup
|
||||||
|
|
||||||
|
IMFSourceReader_Release(reader);
|
||||||
|
IMFByteStream_Close(byte_stream);
|
||||||
|
/* FIXME: Enable this */
|
||||||
|
//IStream_Release(i_stream);
|
||||||
|
MFShutdown();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@
|
|||||||
//~ Windows headers
|
//~ Windows headers
|
||||||
|
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
# include <mfapi.h>
|
#include <mfapi.h>
|
||||||
# include <mfidl.h>
|
#include <mfidl.h>
|
||||||
# include <mfreadwrite.h>
|
#include <mfreadwrite.h>
|
||||||
# include <Shlwapi.h>
|
#include <Shlwapi.h>
|
||||||
# include <objidl.h>
|
#include <objidl.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#pragma comment(lib, "mfplat")
|
#pragma comment(lib, "mfplat")
|
||||||
|
|||||||
1650
src/net/net.c
1650
src/net/net.c
File diff suppressed because it is too large
Load Diff
248
src/net/net.h
248
src/net/net.h
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
Struct(N_ChannelId)
|
Struct(N_ChannelId)
|
||||||
{
|
{
|
||||||
u32 gen;
|
u32 gen;
|
||||||
u32 idx;
|
u32 idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -12,32 +12,32 @@ Struct(N_ChannelId)
|
|||||||
|
|
||||||
Enum(N_CmdKind)
|
Enum(N_CmdKind)
|
||||||
{
|
{
|
||||||
N_CmdKind_None,
|
N_CmdKind_None,
|
||||||
N_CmdKind_TryConnect,
|
N_CmdKind_TryConnect,
|
||||||
N_CmdKind_ConnectSuccess,
|
N_CmdKind_ConnectSuccess,
|
||||||
N_CmdKind_Disconnect,
|
N_CmdKind_Disconnect,
|
||||||
N_CmdKind_Heartbeat,
|
N_CmdKind_Heartbeat,
|
||||||
N_CmdKind_Write
|
N_CmdKind_Write
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(N_WriteFlag)
|
Enum(N_WriteFlag)
|
||||||
{
|
{
|
||||||
N_WriteFlag_None = 0,
|
N_WriteFlag_None = 0,
|
||||||
N_WriteFlag_Reliable = (1 << 0)
|
N_WriteFlag_Reliable = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_Cmd)
|
Struct(N_Cmd)
|
||||||
{
|
{
|
||||||
N_CmdKind kind;
|
N_CmdKind kind;
|
||||||
N_ChannelId channel_id;
|
N_ChannelId channel_id;
|
||||||
|
|
||||||
u16 heartbeat_id;
|
u16 heartbeat_id;
|
||||||
u16 heartbeat_ack_id;
|
u16 heartbeat_ack_id;
|
||||||
|
|
||||||
b32 write_reliable;
|
b32 write_reliable;
|
||||||
String write_msg;
|
String write_msg;
|
||||||
|
|
||||||
N_Cmd *next;
|
N_Cmd *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -45,31 +45,31 @@ Struct(N_Cmd)
|
|||||||
|
|
||||||
Enum(N_EventKind)
|
Enum(N_EventKind)
|
||||||
{
|
{
|
||||||
N_EventKind_None,
|
N_EventKind_None,
|
||||||
N_EventKind_ChannelOpened,
|
N_EventKind_ChannelOpened,
|
||||||
N_EventKind_ChannelClosed,
|
N_EventKind_ChannelClosed,
|
||||||
N_EventKind_Msg
|
N_EventKind_Msg
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_Event)
|
Struct(N_Event)
|
||||||
{
|
{
|
||||||
N_EventKind kind;
|
N_EventKind kind;
|
||||||
N_ChannelId channel_id;
|
N_ChannelId channel_id;
|
||||||
String msg;
|
String msg;
|
||||||
|
|
||||||
N_Event *next;
|
N_Event *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_EventList)
|
Struct(N_EventList)
|
||||||
{
|
{
|
||||||
N_Event *first;
|
N_Event *first;
|
||||||
N_Event *last;
|
N_Event *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_ChannelLookupBin)
|
Struct(N_ChannelLookupBin)
|
||||||
{
|
{
|
||||||
struct N_Channel *first;
|
struct N_Channel *first;
|
||||||
struct N_Channel *last;
|
struct N_Channel *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -81,42 +81,42 @@ Struct(N_ChannelLookupBin)
|
|||||||
|
|
||||||
Enum(N_PacketKind)
|
Enum(N_PacketKind)
|
||||||
{
|
{
|
||||||
N_PacketKind_None,
|
N_PacketKind_None,
|
||||||
N_PacketKind_TryConnect,
|
N_PacketKind_TryConnect,
|
||||||
N_PacketKind_ConnectSuccess,
|
N_PacketKind_ConnectSuccess,
|
||||||
N_PacketKind_Disconnect,
|
N_PacketKind_Disconnect,
|
||||||
N_PacketKind_Heartbeat,
|
N_PacketKind_Heartbeat,
|
||||||
N_PacketKind_MsgChunk
|
N_PacketKind_MsgChunk
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(N_PacketFlag)
|
Enum(N_PacketFlag)
|
||||||
{
|
{
|
||||||
N_PacketFlag_None = 0,
|
N_PacketFlag_None = 0,
|
||||||
N_PacketFlag_Reliable = (1 << 0)
|
N_PacketFlag_Reliable = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_SndPacket)
|
Struct(N_SndPacket)
|
||||||
{
|
{
|
||||||
N_SndPacket *next;
|
N_SndPacket *next;
|
||||||
u64 seq;
|
u64 seq;
|
||||||
|
|
||||||
u64 data_len;
|
u64 data_len;
|
||||||
u8 data[N_MaxPacketLen];
|
u8 data[N_MaxPacketLen];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_RcvPacket)
|
Struct(N_RcvPacket)
|
||||||
{
|
{
|
||||||
P_Sock *sock;
|
P_Sock *sock;
|
||||||
P_Address address;
|
P_Address address;
|
||||||
String data;
|
String data;
|
||||||
N_RcvPacket *next;
|
N_RcvPacket *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_RcvBuffer)
|
Struct(N_RcvBuffer)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
N_RcvPacket *first_packet;
|
N_RcvPacket *first_packet;
|
||||||
N_RcvPacket *last_packet;
|
N_RcvPacket *last_packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -124,53 +124,53 @@ Struct(N_RcvBuffer)
|
|||||||
|
|
||||||
Struct(N_Channel)
|
Struct(N_Channel)
|
||||||
{
|
{
|
||||||
N_ChannelId id;
|
N_ChannelId id;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
b32 connected;
|
b32 connected;
|
||||||
struct N_Host *host;
|
struct N_Host *host;
|
||||||
|
|
||||||
N_Channel *next_free;
|
N_Channel *next_free;
|
||||||
|
|
||||||
P_Address address;
|
P_Address address;
|
||||||
u64 address_hash;
|
u64 address_hash;
|
||||||
N_Channel *next_address_hash;
|
N_Channel *next_address_hash;
|
||||||
N_Channel *prev_address_hash;
|
N_Channel *prev_address_hash;
|
||||||
|
|
||||||
/* NOTE: Packets are allocated in host's `arena` */
|
/* NOTE: Packets are allocated in host's `arena` */
|
||||||
N_SndPacket *first_reliable_packet;
|
N_SndPacket *first_reliable_packet;
|
||||||
N_SndPacket *last_reliable_packet;
|
N_SndPacket *last_reliable_packet;
|
||||||
N_SndPacket *first_unreliable_packet;
|
N_SndPacket *first_unreliable_packet;
|
||||||
N_SndPacket *last_unreliable_packet;
|
N_SndPacket *last_unreliable_packet;
|
||||||
u64 num_reliable_packets;
|
u64 num_reliable_packets;
|
||||||
u64 num_unreliable_packets;
|
u64 num_unreliable_packets;
|
||||||
|
|
||||||
/* NOTE: Msg assemblers are allocated in host's `arena` */
|
/* NOTE: Msg assemblers are allocated in host's `arena` */
|
||||||
struct N_MsgAssembler *least_recent_msg_assembler;
|
struct N_MsgAssembler *least_recent_msg_assembler;
|
||||||
struct N_MsgAssembler *most_recent_msg_assembler;
|
struct N_MsgAssembler *most_recent_msg_assembler;
|
||||||
|
|
||||||
u16 last_heartbeat_received_id;
|
u16 last_heartbeat_received_id;
|
||||||
u16 last_heartbeat_acked_id;
|
u16 last_heartbeat_acked_id;
|
||||||
i64 last_heartbeat_acked_ns;
|
i64 last_heartbeat_acked_ns;
|
||||||
i64 last_heartbeat_rtt_ns;
|
i64 last_heartbeat_rtt_ns;
|
||||||
|
|
||||||
u64 last_sent_msg_id;
|
u64 last_sent_msg_id;
|
||||||
u64 their_acked_seq;
|
u64 their_acked_seq;
|
||||||
u64 our_acked_seq;
|
u64 our_acked_seq;
|
||||||
u64 last_sent_seq;
|
u64 last_sent_seq;
|
||||||
|
|
||||||
i64 last_packet_received_ns;
|
i64 last_packet_received_ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_ChannelNode)
|
Struct(N_ChannelNode)
|
||||||
{
|
{
|
||||||
N_Channel *channel;
|
N_Channel *channel;
|
||||||
N_ChannelNode *next;
|
N_ChannelNode *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_ChannelList)
|
Struct(N_ChannelList)
|
||||||
{
|
{
|
||||||
N_ChannelNode *first;
|
N_ChannelNode *first;
|
||||||
N_ChannelNode *last;
|
N_ChannelNode *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -178,38 +178,38 @@ Struct(N_ChannelList)
|
|||||||
|
|
||||||
Struct(N_MsgAssembler)
|
Struct(N_MsgAssembler)
|
||||||
{
|
{
|
||||||
N_Channel *channel;
|
N_Channel *channel;
|
||||||
b32 is_reliable;
|
b32 is_reliable;
|
||||||
|
|
||||||
/* Free list */
|
/* Free list */
|
||||||
N_MsgAssembler *next_free;
|
N_MsgAssembler *next_free;
|
||||||
|
|
||||||
/* Bucket list */
|
/* Bucket list */
|
||||||
N_MsgAssembler *next_hash;
|
N_MsgAssembler *next_hash;
|
||||||
N_MsgAssembler *prev_hash;
|
N_MsgAssembler *prev_hash;
|
||||||
|
|
||||||
/* Channel list */
|
/* Channel list */
|
||||||
N_MsgAssembler *less_recent;
|
N_MsgAssembler *less_recent;
|
||||||
N_MsgAssembler *more_recent;
|
N_MsgAssembler *more_recent;
|
||||||
|
|
||||||
u64 msg_id;
|
u64 msg_id;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
|
|
||||||
u64 last_chunk_len;
|
u64 last_chunk_len;
|
||||||
u64 num_chunks_total;
|
u64 num_chunks_total;
|
||||||
u64 num_chunks_received;
|
u64 num_chunks_received;
|
||||||
|
|
||||||
i64 touched_ns;
|
i64 touched_ns;
|
||||||
|
|
||||||
BuddyBlock *buddy_block;
|
BuddyBlock *buddy_block;
|
||||||
u8 *chunk_bitmap;
|
u8 *chunk_bitmap;
|
||||||
u8 *chunk_data;
|
u8 *chunk_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(N_MsgAssemblerLookupBin)
|
Struct(N_MsgAssemblerLookupBin)
|
||||||
{
|
{
|
||||||
N_MsgAssembler *first;
|
N_MsgAssembler *first;
|
||||||
N_MsgAssembler *last;
|
N_MsgAssembler *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -220,38 +220,38 @@ Struct(N_MsgAssemblerLookupBin)
|
|||||||
|
|
||||||
Struct(N_Host)
|
Struct(N_Host)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
P_Sock *sock;
|
P_Sock *sock;
|
||||||
|
|
||||||
BuddyCtx *buddy; /* For storing msg assembler data */
|
BuddyCtx *buddy; /* For storing msg assembler data */
|
||||||
|
|
||||||
Arena *cmd_arena;
|
Arena *cmd_arena;
|
||||||
N_Cmd *first_cmd;
|
N_Cmd *first_cmd;
|
||||||
N_Cmd *last_cmd;
|
N_Cmd *last_cmd;
|
||||||
N_Cmd *first_free_cmd;
|
N_Cmd *first_free_cmd;
|
||||||
|
|
||||||
Arena *channel_arena;
|
Arena *channel_arena;
|
||||||
N_Channel *channels;
|
N_Channel *channels;
|
||||||
N_Channel *first_free_channel;
|
N_Channel *first_free_channel;
|
||||||
u64 num_channels_reserved;
|
u64 num_channels_reserved;
|
||||||
|
|
||||||
N_SndPacket *first_free_packet; /* Acquired in `arena` */
|
N_SndPacket *first_free_packet; /* Acquired in `arena` */
|
||||||
N_MsgAssembler *first_free_msg_assembler; /* Acquired in `arena` */
|
N_MsgAssembler *first_free_msg_assembler; /* Acquired in `arena` */
|
||||||
|
|
||||||
N_ChannelLookupBin *channel_lookup_bins; /* Acquired in `arena` */
|
N_ChannelLookupBin *channel_lookup_bins; /* Acquired in `arena` */
|
||||||
u64 num_channel_lookup_bins;
|
u64 num_channel_lookup_bins;
|
||||||
|
|
||||||
N_MsgAssemblerLookupBin *msg_assembler_lookup_bins; /* Acquired in `arena` */
|
N_MsgAssemblerLookupBin *msg_assembler_lookup_bins; /* Acquired in `arena` */
|
||||||
u64 num_msg_assembler_lookup_bins;
|
u64 num_msg_assembler_lookup_bins;
|
||||||
|
|
||||||
/* Double buffer for incoming data */
|
/* Double buffer for incoming data */
|
||||||
Mutex rcv_buffer_write_mutex;
|
Mutex rcv_buffer_write_mutex;
|
||||||
N_RcvBuffer *rcv_buffer_read;
|
N_RcvBuffer *rcv_buffer_read;
|
||||||
N_RcvBuffer *rcv_buffer_write;
|
N_RcvBuffer *rcv_buffer_write;
|
||||||
|
|
||||||
u64 bytes_received;
|
u64 bytes_received;
|
||||||
u64 bytes_sent;
|
u64 bytes_sent;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -9,22 +9,22 @@ Struct(P_Sock);
|
|||||||
|
|
||||||
Struct(P_File)
|
Struct(P_File)
|
||||||
{
|
{
|
||||||
u64 handle;
|
u64 handle;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(P_FileTime)
|
Struct(P_FileTime)
|
||||||
{
|
{
|
||||||
DateTime created;
|
DateTime created;
|
||||||
DateTime accessed;
|
DateTime accessed;
|
||||||
DateTime modified;
|
DateTime modified;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(P_FileMap)
|
Struct(P_FileMap)
|
||||||
{
|
{
|
||||||
String mapped_memory;
|
String mapped_memory;
|
||||||
u64 handle;
|
u64 handle;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -32,17 +32,17 @@ Struct(P_FileMap)
|
|||||||
|
|
||||||
Enum(P_AddressFamily)
|
Enum(P_AddressFamily)
|
||||||
{
|
{
|
||||||
P_AddressFamily_Ipv4,
|
P_AddressFamily_Ipv4,
|
||||||
P_AddressFamily_Ipv6
|
P_AddressFamily_Ipv6
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(P_Address)
|
Struct(P_Address)
|
||||||
{
|
{
|
||||||
b32 valid;
|
b32 valid;
|
||||||
P_AddressFamily family;
|
P_AddressFamily family;
|
||||||
/* NOTE: ipnb & portnb are stored in network byte order */
|
/* NOTE: ipnb & portnb are stored in network byte order */
|
||||||
u8 ipnb[16];
|
u8 ipnb[16];
|
||||||
u16 portnb;
|
u16 portnb;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -50,9 +50,9 @@ Struct(P_Address)
|
|||||||
|
|
||||||
Struct(P_SockReadResult)
|
Struct(P_SockReadResult)
|
||||||
{
|
{
|
||||||
b32 valid; /* Since data.len = 0 can be valid */
|
b32 valid; /* Since data.len = 0 can be valid */
|
||||||
P_Address address;
|
P_Address address;
|
||||||
String data;
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -60,10 +60,10 @@ Struct(P_SockReadResult)
|
|||||||
|
|
||||||
Enum(P_MessageBoxKind)
|
Enum(P_MessageBoxKind)
|
||||||
{
|
{
|
||||||
P_MessageBoxKind_Ok,
|
P_MessageBoxKind_Ok,
|
||||||
P_MessageBoxKind_Warning,
|
P_MessageBoxKind_Warning,
|
||||||
P_MessageBoxKind_Error,
|
P_MessageBoxKind_Error,
|
||||||
P_MessageBoxKind_Fatal
|
P_MessageBoxKind_Fatal
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -2,15 +2,15 @@
|
|||||||
//~ Win32 libs
|
//~ Win32 libs
|
||||||
|
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
# include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
# include <TlHelp32.h>
|
#include <TlHelp32.h>
|
||||||
# include <WS2tcpip.h>
|
#include <WS2tcpip.h>
|
||||||
# include <windowsx.h>
|
#include <windowsx.h>
|
||||||
# include <ShlObj_core.h>
|
#include <ShlObj_core.h>
|
||||||
# include <fileapi.h>
|
#include <fileapi.h>
|
||||||
# include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
# include <avrt.h>
|
#include <avrt.h>
|
||||||
# include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#pragma comment(lib, "kernel32")
|
#pragma comment(lib, "kernel32")
|
||||||
@ -28,10 +28,10 @@
|
|||||||
|
|
||||||
Struct(P_W32_Watch)
|
Struct(P_W32_Watch)
|
||||||
{
|
{
|
||||||
HANDLE dir_handle;
|
HANDLE dir_handle;
|
||||||
HANDLE wake_handle;
|
HANDLE wake_handle;
|
||||||
P_W32_Watch *next_free;
|
P_W32_Watch *next_free;
|
||||||
u8 results_buff[Kibi(64)];
|
u8 results_buff[Kibi(64)];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -39,15 +39,15 @@ Struct(P_W32_Watch)
|
|||||||
|
|
||||||
Struct(P_W32_Address)
|
Struct(P_W32_Address)
|
||||||
{
|
{
|
||||||
i32 size;
|
i32 size;
|
||||||
i32 family;
|
i32 family;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct sockaddr_storage sas;
|
struct sockaddr_storage sas;
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -55,8 +55,8 @@ Struct(P_W32_Address)
|
|||||||
|
|
||||||
Struct(P_W32_Sock)
|
Struct(P_W32_Sock)
|
||||||
{
|
{
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
P_W32_Sock *next_free;
|
P_W32_Sock *next_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -67,20 +67,20 @@ Struct(P_W32_Sock)
|
|||||||
|
|
||||||
Struct(P_W32_SharedState)
|
Struct(P_W32_SharedState)
|
||||||
{
|
{
|
||||||
//- Watches pool
|
//- Watches pool
|
||||||
Mutex watches_mutex;
|
Mutex watches_mutex;
|
||||||
Arena *watches_arena;
|
Arena *watches_arena;
|
||||||
P_W32_Watch *watches_first_free;
|
P_W32_Watch *watches_first_free;
|
||||||
|
|
||||||
//- Socket pool
|
//- Socket pool
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
Arena *socks_arena;
|
Arena *socks_arena;
|
||||||
Mutex socks_mutex;
|
Mutex socks_mutex;
|
||||||
P_W32_Sock *first_free_sock;
|
P_W32_Sock *first_free_sock;
|
||||||
|
|
||||||
//- Timer
|
//- Timer
|
||||||
Fence timer_fence;
|
Fence timer_fence;
|
||||||
Atomic64Padded average_timer_period_ns;
|
Atomic64Padded average_timer_period_ns;
|
||||||
} extern P_W32_shared_state;
|
} extern P_W32_shared_state;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -11,12 +11,12 @@ PB_WSP_SharedState PB_WSP_shared_state = ZI;
|
|||||||
|
|
||||||
void PB_Bootstrap(void)
|
void PB_Bootstrap(void)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
PB_WSP_InitializeWasapi();
|
PB_WSP_InitializeWasapi();
|
||||||
/* Start playback job */
|
/* Start playback job */
|
||||||
JobPoolId playback_pool = InitJobPool(1, Lit("Playback"), JobPoolPriority_Audio);
|
JobPoolId playback_pool = InitJobPool(1, Lit("Playback"), JobPoolPriority_Audio);
|
||||||
g->shutdown_jobs_count += RunJob(PB_WSP_Playback, .pool = playback_pool, .fence = &g->shutdown_jobs_fence);
|
g->shutdown_jobs_count += RunJob(PB_WSP_Playback, .pool = playback_pool, .fence = &g->shutdown_jobs_fence);
|
||||||
OnExit(&PB_WSP_Shutdown);
|
OnExit(&PB_WSP_Shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -24,102 +24,102 @@ void PB_Bootstrap(void)
|
|||||||
|
|
||||||
ExitFuncDef(PB_WSP_Shutdown)
|
ExitFuncDef(PB_WSP_Shutdown)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
Atomic32Set(&g->shutdown, 1);
|
Atomic32Set(&g->shutdown, 1);
|
||||||
YieldOnFence(&g->shutdown_jobs_fence, g->shutdown_jobs_count);
|
YieldOnFence(&g->shutdown_jobs_fence, g->shutdown_jobs_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PB_WSP_InitializeWasapi(void)
|
void PB_WSP_InitializeWasapi(void)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
u64 sample_rate = PB_SampleRate;
|
u64 sample_rate = PB_SampleRate;
|
||||||
u64 channel_count = 2;
|
u64 channel_count = 2;
|
||||||
u32 channel_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
u32 channel_mask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
|
||||||
|
|
||||||
/* Create enumerator to get audio device */
|
/* Create enumerator to get audio device */
|
||||||
IMMDeviceEnumerator *enumerator;
|
IMMDeviceEnumerator *enumerator;
|
||||||
CoCreateInstance(&CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (LPVOID *)&enumerator);
|
CoCreateInstance(&CLSID_MMDeviceEnumerator, 0, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (LPVOID *)&enumerator);
|
||||||
|
|
||||||
/* Get default playback device */
|
/* Get default playback device */
|
||||||
IMMDevice *device;
|
IMMDevice *device;
|
||||||
IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eConsole, &device);
|
IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eConsole, &device);
|
||||||
IMMDeviceEnumerator_Release(enumerator);
|
IMMDeviceEnumerator_Release(enumerator);
|
||||||
|
|
||||||
/* Create audio client for device */
|
/* Create audio client for device */
|
||||||
IMMDevice_Activate(device, &IID_IAudioClient, CLSCTX_ALL, 0, (LPVOID *)&g->client);
|
IMMDevice_Activate(device, &IID_IAudioClient, CLSCTX_ALL, 0, (LPVOID *)&g->client);
|
||||||
IMMDevice_Release(device);
|
IMMDevice_Release(device);
|
||||||
|
|
||||||
WAVEFORMATEXTENSIBLE format_ex = {
|
WAVEFORMATEXTENSIBLE format_ex = {
|
||||||
.Format = {
|
.Format = {
|
||||||
.wFormatTag = WAVE_FORMAT_EXTENSIBLE,
|
.wFormatTag = WAVE_FORMAT_EXTENSIBLE,
|
||||||
.nChannels = (WORD)channel_count,
|
.nChannels = (WORD)channel_count,
|
||||||
.nSamplesPerSec = (WORD)sample_rate,
|
.nSamplesPerSec = (WORD)sample_rate,
|
||||||
.nAvgBytesPerSec = (DWORD)(sample_rate * channel_count * sizeof(f32)),
|
.nAvgBytesPerSec = (DWORD)(sample_rate * channel_count * sizeof(f32)),
|
||||||
.nBlockAlign = (WORD)(channel_count * sizeof(f32)),
|
.nBlockAlign = (WORD)(channel_count * sizeof(f32)),
|
||||||
.wBitsPerSample = (WORD)(8 * sizeof(f32)),
|
.wBitsPerSample = (WORD)(8 * sizeof(f32)),
|
||||||
.cbSize = sizeof(format_ex) - sizeof(format_ex.Format),
|
.cbSize = sizeof(format_ex) - sizeof(format_ex.Format),
|
||||||
},
|
},
|
||||||
.Samples.wValidBitsPerSample = 8 * sizeof(f32),
|
.Samples.wValidBitsPerSample = 8 * sizeof(f32),
|
||||||
.dwChannelMask = channel_mask,
|
.dwChannelMask = channel_mask,
|
||||||
.SubFormat = MEDIASUBTYPE_IEEE_FLOAT,
|
.SubFormat = MEDIASUBTYPE_IEEE_FLOAT,
|
||||||
};
|
};
|
||||||
WAVEFORMATEX *wfx = &format_ex.Format;
|
WAVEFORMATEX *wfx = &format_ex.Format;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
b32 client_initialized = 0;
|
b32 client_initialized = 0;
|
||||||
IAudioClient3 *client3;
|
IAudioClient3 *client3;
|
||||||
if (SUCCEEDED(IAudioClient_QueryInterface(g->client, &IID_IAudioClient3, (LPVOID *)&client3)))
|
if (SUCCEEDED(IAudioClient_QueryInterface(g->client, &IID_IAudioClient3, (LPVOID *)&client3)))
|
||||||
|
{
|
||||||
|
/* From Martins: Minimum buffer size will typically be 480 samples (10msec @ 48khz)
|
||||||
|
* but it can be 128 samples (2.66 msec @ 48khz) if driver is properly installed
|
||||||
|
* see bullet-point instructions here: https://learn.microsoft.com/en-us/windows-hardware/drivers/audio/low-latency-audio#measurement-tools
|
||||||
|
*/
|
||||||
|
UINT32 default_period_samples, fundamental_period_samples, min_period_samples, max_period_samples;
|
||||||
|
IAudioClient3_GetSharedModeEnginePeriod(client3, wfx, &default_period_samples, &fundamental_period_samples, &min_period_samples, &max_period_samples);
|
||||||
|
|
||||||
|
const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||||
|
if (SUCCEEDED(IAudioClient3_InitializeSharedAudioStream(client3, flags, min_period_samples, wfx, 0)))
|
||||||
{
|
{
|
||||||
/* From Martins: Minimum buffer size will typically be 480 samples (10msec @ 48khz)
|
client_initialized = 1;
|
||||||
* but it can be 128 samples (2.66 msec @ 48khz) if driver is properly installed
|
|
||||||
* see bullet-point instructions here: https://learn.microsoft.com/en-us/windows-hardware/drivers/audio/low-latency-audio#measurement-tools
|
|
||||||
*/
|
|
||||||
UINT32 default_period_samples, fundamental_period_samples, min_period_samples, max_period_samples;
|
|
||||||
IAudioClient3_GetSharedModeEnginePeriod(client3, wfx, &default_period_samples, &fundamental_period_samples, &min_period_samples, &max_period_samples);
|
|
||||||
|
|
||||||
const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
|
||||||
if (SUCCEEDED(IAudioClient3_InitializeSharedAudioStream(client3, flags, min_period_samples, wfx, 0)))
|
|
||||||
{
|
|
||||||
client_initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
IAudioClient3_Release(client3);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
b32 client_initialized = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!client_initialized)
|
|
||||||
{
|
|
||||||
/* Get duration for shared-mode streams, this will typically be 480 samples (10msec @ 48khz) */
|
|
||||||
REFERENCE_TIME duration;
|
|
||||||
IAudioClient_GetDevicePeriod(g->client, &duration, 0);
|
|
||||||
|
|
||||||
/* Initialize audio playback
|
|
||||||
*
|
|
||||||
* NOTE:
|
|
||||||
* Passing AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM will tell WASAPI to
|
|
||||||
* always convert to native mixing format. This may introduce latency
|
|
||||||
* but allows for any input format.
|
|
||||||
*/
|
|
||||||
const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
|
||||||
IAudioClient_Initialize(g->client, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, wfx, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IAudioClient_GetMixFormat(g->client, &g->buffer_format);
|
IAudioClient3_Release(client3);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
b32 client_initialized = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set up event handler to wait on */
|
if (!client_initialized)
|
||||||
g->event = CreateEventW(0, 0, 0, 0);
|
{
|
||||||
IAudioClient_SetEventHandle(g->client, g->event);
|
/* Get duration for shared-mode streams, this will typically be 480 samples (10msec @ 48khz) */
|
||||||
|
REFERENCE_TIME duration;
|
||||||
|
IAudioClient_GetDevicePeriod(g->client, &duration, 0);
|
||||||
|
|
||||||
/* Get playback client */
|
/* Initialize audio playback
|
||||||
IAudioClient_GetService(g->client, &IID_IAudioRenderClient, (LPVOID *)&g->playback);
|
*
|
||||||
|
* NOTE:
|
||||||
|
* Passing AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM will tell WASAPI to
|
||||||
|
* always convert to native mixing format. This may introduce latency
|
||||||
|
* but allows for any input format.
|
||||||
|
*/
|
||||||
|
const DWORD flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||||
|
IAudioClient_Initialize(g->client, AUDCLNT_SHAREMODE_SHARED, flags, duration, 0, wfx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Start the playback */
|
IAudioClient_GetMixFormat(g->client, &g->buffer_format);
|
||||||
IAudioClient_Start(g->client);
|
|
||||||
|
|
||||||
/* Get audio buffer size in samples */
|
/* Set up event handler to wait on */
|
||||||
IAudioClient_GetBufferSize(g->client, &g->buffer_frames);
|
g->event = CreateEventW(0, 0, 0, 0);
|
||||||
|
IAudioClient_SetEventHandle(g->client, g->event);
|
||||||
|
|
||||||
|
/* Get playback client */
|
||||||
|
IAudioClient_GetService(g->client, &IID_IAudioRenderClient, (LPVOID *)&g->playback);
|
||||||
|
|
||||||
|
/* Start the playback */
|
||||||
|
IAudioClient_Start(g->client);
|
||||||
|
|
||||||
|
/* Get audio buffer size in samples */
|
||||||
|
IAudioClient_GetBufferSize(g->client, &g->buffer_frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -127,54 +127,55 @@ void PB_WSP_InitializeWasapi(void)
|
|||||||
|
|
||||||
PB_WSP_Buff PB_WSP_BeginUpdate(void)
|
PB_WSP_Buff PB_WSP_BeginUpdate(void)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
PB_WSP_Buff wspbuf = ZI;
|
PB_WSP_Buff wspbuf = ZI;
|
||||||
|
|
||||||
/* Get padding frames */
|
/* Get padding frames */
|
||||||
u32 padding_frames;
|
u32 padding_frames;
|
||||||
IAudioClient_GetCurrentPadding(g->client, &padding_frames);
|
IAudioClient_GetCurrentPadding(g->client, &padding_frames);
|
||||||
|
|
||||||
/* Get output buffer from WASAPI */
|
/* Get output buffer from WASAPI */
|
||||||
wspbuf.frames_count = 0;
|
wspbuf.frames_count = 0;
|
||||||
if (padding_frames <= g->buffer_frames)
|
if (padding_frames <= g->buffer_frames)
|
||||||
{
|
{
|
||||||
wspbuf.frames_count = g->buffer_frames - padding_frames;
|
wspbuf.frames_count = g->buffer_frames - padding_frames;
|
||||||
}
|
}
|
||||||
IAudioRenderClient_GetBuffer(g->playback, wspbuf.frames_count, &wspbuf.frames);
|
IAudioRenderClient_GetBuffer(g->playback, wspbuf.frames_count, &wspbuf.frames);
|
||||||
|
|
||||||
return wspbuf;
|
return wspbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src)
|
void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
u32 frames_in_source = src.count / 2;
|
u32 frames_in_source = src.count / 2;
|
||||||
u32 frames_in_output = wspbuf->frames_count;
|
u32 frames_in_output = wspbuf->frames_count;
|
||||||
|
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
if (frames_in_source == frames_in_output)
|
if (frames_in_source == frames_in_output)
|
||||||
{
|
{
|
||||||
/* Copy bytes to output */
|
/* Copy bytes to output */
|
||||||
u32 bytes_per_sample = g->buffer_format->nBlockAlign / g->buffer_format->nChannels;
|
u32 bytes_per_sample = g->buffer_format->nBlockAlign / g->buffer_format->nChannels;
|
||||||
u32 write_size = frames_in_source * 2 * bytes_per_sample;
|
u32 write_size = frames_in_source * 2 * bytes_per_sample;
|
||||||
CopyBytes(wspbuf->frames, src.samples, write_size);
|
CopyBytes(wspbuf->frames, src.samples, write_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Submit silence if not enough samples */
|
/* Submit silence if not enough samples */
|
||||||
flags = AUDCLNT_BUFFERFLAGS_SILENT;
|
flags |= AUDCLNT_BUFFERFLAGS_SILENT;
|
||||||
|
|
||||||
/* This shouldn't occur, mixer should be generating samples equivilent
|
/* This shouldn't occur, mixer should be generating samples equivilent
|
||||||
* to value returned from `PB_WSP_BeginUpdate`. */
|
* to value returned from `PB_WSP_BeginUpdate`. */
|
||||||
Assert(0);
|
Assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !AUDIO_ENABLED
|
if (!AUDIO_ENABLED)
|
||||||
flags = AUDCLNT_BUFFERFLAGS_SILENT;
|
{
|
||||||
#endif
|
flags |= AUDCLNT_BUFFERFLAGS_SILENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Submit output buffer to WASAPI */
|
/* Submit output buffer to WASAPI */
|
||||||
IAudioRenderClient_ReleaseBuffer(g->playback, frames_in_source, flags);
|
IAudioRenderClient_ReleaseBuffer(g->playback, frames_in_source, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -182,22 +183,22 @@ void PB_WSP_EndUpdate(PB_WSP_Buff *wspbuf, MIX_PcmF32 src)
|
|||||||
|
|
||||||
JobImpl(PB_WSP_Playback, sig, id)
|
JobImpl(PB_WSP_Playback, sig, id)
|
||||||
{
|
{
|
||||||
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
PB_WSP_SharedState *g = &PB_WSP_shared_state;
|
||||||
|
|
||||||
/* FIXME: If playback fails at any point and mixer stops advancing, we
|
/* FIXME: If playback fails at any point and mixer stops advancing, we
|
||||||
* need to halt mixer to prevent memory leak when sounds are played. */
|
* need to halt mixer to prevent memory leak when sounds are played. */
|
||||||
/* TODO: Signal counter that running job wiats on, rather than scheduling job manually */
|
/* TODO: Signal counter that running job wiats on, rather than scheduling job manually */
|
||||||
while (!Atomic32Fetch(&g->shutdown))
|
while (!Atomic32Fetch(&g->shutdown))
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
WaitForSingleObject(g->event, INFINITE);
|
||||||
{
|
|
||||||
WaitForSingleObject(g->event, INFINITE);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
PB_WSP_Buff wspbuf = PB_WSP_BeginUpdate();
|
|
||||||
MIX_PcmF32 pcm = MIX_MixAllTracks(scratch.arena, wspbuf.frames_count);
|
|
||||||
PB_WSP_EndUpdate(&wspbuf, pcm);
|
|
||||||
}
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
PB_WSP_Buff wspbuf = PB_WSP_BeginUpdate();
|
||||||
|
MIX_PcmF32 pcm = MIX_MixAllTracks(scratch.arena, wspbuf.frames_count);
|
||||||
|
PB_WSP_EndUpdate(&wspbuf, pcm);
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
//~ Win32 libs
|
//~ Win32 libs
|
||||||
|
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
# include <Audioclient.h>
|
#include <Audioclient.h>
|
||||||
# include <mmdeviceapi.h>
|
#include <mmdeviceapi.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e);
|
DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e);
|
||||||
@ -17,8 +17,8 @@ DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7, 0xbf, 0x
|
|||||||
|
|
||||||
Struct(PB_WSP_Buff)
|
Struct(PB_WSP_Buff)
|
||||||
{
|
{
|
||||||
u32 frames_count;
|
u32 frames_count;
|
||||||
u8 *frames;
|
u8 *frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -26,14 +26,14 @@ Struct(PB_WSP_Buff)
|
|||||||
|
|
||||||
Struct(PB_WSP_SharedState)
|
Struct(PB_WSP_SharedState)
|
||||||
{
|
{
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
IAudioClient *client;
|
IAudioClient *client;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
IAudioRenderClient *playback;
|
IAudioRenderClient *playback;
|
||||||
WAVEFORMATEX *buffer_format;
|
WAVEFORMATEX *buffer_format;
|
||||||
u32 buffer_frames;
|
u32 buffer_frames;
|
||||||
Fence shutdown_jobs_fence;
|
Fence shutdown_jobs_fence;
|
||||||
u32 shutdown_jobs_count;
|
u32 shutdown_jobs_count;
|
||||||
} extern PB_WSP_shared_state;
|
} extern PB_WSP_shared_state;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
S_Ctx S = Zi;
|
S_Ctx S = Zi;
|
||||||
|
|
||||||
Readonly S_ReadonlyCtx S_ro = {
|
Readonly S_ReadonlyCtx S_ro = {
|
||||||
.nil_ent = {
|
.nil_ent = {
|
||||||
.xf = CompXformIdentity
|
.xf = CompXformIdentity
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -11,26 +11,26 @@ Readonly S_ReadonlyCtx S_ro = {
|
|||||||
|
|
||||||
void S_Bootstrap(void)
|
void S_Bootstrap(void)
|
||||||
{
|
{
|
||||||
/* Initialize shared state */
|
/* Initialize shared state */
|
||||||
for (u64 i = 0; i < countof(S.input_states); ++i)
|
for (u64 i = 0; i < countof(S.input_states); ++i)
|
||||||
{
|
{
|
||||||
S_InputState *input = &S.input_states[i];
|
S_InputState *input = &S.input_states[i];
|
||||||
input->arena = AcquireArena(Gibi(64));
|
input->arena = AcquireArena(Gibi(64));
|
||||||
}
|
}
|
||||||
for (u64 i = 0; i < countof(S.output_states); ++i)
|
for (u64 i = 0; i < countof(S.output_states); ++i)
|
||||||
{
|
{
|
||||||
S_OutputState *output = &S.output_states[i];
|
S_OutputState *output = &S.output_states[i];
|
||||||
output->arena = AcquireArena(Gibi(64));
|
output->arena = AcquireArena(Gibi(64));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatch sim wave */
|
/* Dispatch sim wave */
|
||||||
DispatchWave(Lit("Sim"), 1, S_TickForever, 0);
|
DispatchWave(Lit("Sim"), 1, S_TickForever, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S_Shutdown(void)
|
void S_Shutdown(void)
|
||||||
{
|
{
|
||||||
Atomic32Set(&S.shutdown, 1);
|
Atomic32Set(&S.shutdown, 1);
|
||||||
YieldOnFence(&S.worker_completion_fence, S.workers_count);
|
YieldOnFence(&S.worker_completion_fence, S.workers_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -38,17 +38,17 @@ void S_Shutdown(void)
|
|||||||
|
|
||||||
b32 S_IsKeyNil(S_Key key)
|
b32 S_IsKeyNil(S_Key key)
|
||||||
{
|
{
|
||||||
return key.v.hi == 0 && key.v.lo == 0;
|
return key.v.hi == 0 && key.v.lo == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 S_IsEntNil(S_Ent *ent)
|
b32 S_IsEntNil(S_Ent *ent)
|
||||||
{
|
{
|
||||||
return ent == 0 || ent == &S_ro.nil_ent;
|
return ent == 0 || ent == &S_ro.nil_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 S_MatchKey(S_Key a, S_Key b)
|
b32 S_MatchKey(S_Key a, S_Key b)
|
||||||
{
|
{
|
||||||
return a.v.hi == b.v.hi && a.v.lo == b.v.lo;
|
return a.v.hi == b.v.hi && a.v.lo == b.v.lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -56,10 +56,10 @@ b32 S_MatchKey(S_Key a, S_Key b)
|
|||||||
|
|
||||||
S_Key S_RandKey(void)
|
S_Key S_RandKey(void)
|
||||||
{
|
{
|
||||||
/* TODO: Don't use true randomness for entity keys. It's overkill & non-deterministic. */
|
/* TODO: Don't use true randomness for entity keys. It's overkill & non-deterministic. */
|
||||||
S_Key result = Zi;
|
S_Key result = Zi;
|
||||||
TrueRand(StringFromStruct(&result));
|
TrueRand(StringFromStruct(&result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -67,26 +67,26 @@ S_Key S_RandKey(void)
|
|||||||
|
|
||||||
Rng2I32 S_UpdateTilesInPlaceFromPlacement(u8 *tiles, S_TilePlacement placement)
|
Rng2I32 S_UpdateTilesInPlaceFromPlacement(u8 *tiles, S_TilePlacement placement)
|
||||||
{
|
{
|
||||||
Rng2I32 dirty_rect = Zi;
|
Rng2I32 dirty_rect = Zi;
|
||||||
switch (placement.placement_kind)
|
switch (placement.placement_kind)
|
||||||
|
{
|
||||||
|
case S_TilePlacementKind_Range:
|
||||||
{
|
{
|
||||||
case S_TilePlacementKind_Range:
|
S_TileKind tile = placement.tile_kind;
|
||||||
|
Rng2I32 range = placement.range;
|
||||||
|
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
||||||
|
{
|
||||||
|
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
||||||
{
|
{
|
||||||
S_TileKind tile = placement.tile_kind;
|
Vec2I32 tile_pos = VEC2I32(tile_x, tile_y);
|
||||||
Rng2I32 range = placement.range;
|
i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
|
||||||
for (i32 tile_y = range.p0.y; tile_y < range.p1.y; ++tile_y)
|
tiles[tile_idx] = (u8)tile;
|
||||||
{
|
}
|
||||||
for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x)
|
}
|
||||||
{
|
dirty_rect = range;
|
||||||
Vec2I32 tile_pos = VEC2I32(tile_x, tile_y);
|
} break;
|
||||||
i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
|
}
|
||||||
tiles[tile_idx] = (u8)tile;
|
return dirty_rect;
|
||||||
}
|
|
||||||
}
|
|
||||||
dirty_rect = range;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
return dirty_rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -94,52 +94,52 @@ Rng2I32 S_UpdateTilesInPlaceFromPlacement(u8 *tiles, S_TilePlacement placement)
|
|||||||
|
|
||||||
S_Shape S_ShapeFromDescEx(S_ShapeDesc desc)
|
S_Shape S_ShapeFromDescEx(S_ShapeDesc desc)
|
||||||
{
|
{
|
||||||
desc.count = MaxI32(desc.count, 1);
|
desc.count = MaxI32(desc.count, 1);
|
||||||
S_Shape result = Zi;
|
S_Shape result = Zi;
|
||||||
|
{
|
||||||
|
result.points_count = desc.count;
|
||||||
|
CopyStructs(result.points, desc.points, result.points_count);
|
||||||
|
Vec2 accum = Zi;
|
||||||
|
for (i32 p_idx = 0; p_idx < result.points_count; ++p_idx)
|
||||||
{
|
{
|
||||||
result.points_count = desc.count;
|
accum = AddVec2(accum, result.points[p_idx]);
|
||||||
CopyStructs(result.points, desc.points, result.points_count);
|
|
||||||
Vec2 accum = Zi;
|
|
||||||
for (i32 p_idx = 0; p_idx < result.points_count; ++p_idx)
|
|
||||||
{
|
|
||||||
accum = AddVec2(accum, result.points[p_idx]);
|
|
||||||
}
|
|
||||||
result.centroid = DivVec2(accum, result.points_count);
|
|
||||||
result.center_of_mass = result.centroid;
|
|
||||||
result.radius = desc.radius;
|
|
||||||
result.mass = desc.mass;
|
|
||||||
}
|
}
|
||||||
return result;
|
result.centroid = DivVec2(accum, result.points_count);
|
||||||
|
result.center_of_mass = result.centroid;
|
||||||
|
result.radius = desc.radius;
|
||||||
|
result.mass = desc.mass;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Shape S_MulXformShape(Xform xf, S_Shape shape)
|
S_Shape S_MulXformShape(Xform xf, S_Shape shape)
|
||||||
{
|
{
|
||||||
S_Shape result = shape;
|
S_Shape result = shape;
|
||||||
for (i32 i = 0; i < shape.points_count; ++i)
|
for (i32 i = 0; i < shape.points_count; ++i)
|
||||||
{
|
{
|
||||||
result.points[i] = MulXformV2(xf, shape.points[i]);
|
result.points[i] = MulXformV2(xf, shape.points[i]);
|
||||||
}
|
}
|
||||||
Vec2 scale = ScaleFromXform(xf);
|
Vec2 scale = ScaleFromXform(xf);
|
||||||
result.radius *= MaxF32(scale.x, scale.y);
|
result.radius *= MaxF32(scale.x, scale.y);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir)
|
Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir)
|
||||||
{
|
{
|
||||||
Vec2 result = Zi;
|
Vec2 result = Zi;
|
||||||
f32 max_dot = -F32Infinity;
|
f32 max_dot = -F32Infinity;
|
||||||
for (i32 i = 0; i < shape.points_count; ++i)
|
for (i32 i = 0; i < shape.points_count; ++i)
|
||||||
|
{
|
||||||
|
Vec2 p = shape.points[i];
|
||||||
|
f32 dot = DotVec2(p, dir);
|
||||||
|
if (dot > max_dot)
|
||||||
{
|
{
|
||||||
Vec2 p = shape.points[i];
|
max_dot = dot;
|
||||||
f32 dot = DotVec2(p, dir);
|
result = p;
|
||||||
if (dot > max_dot)
|
|
||||||
{
|
|
||||||
max_dot = dot;
|
|
||||||
result = p;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result = AddVec2(result, MulVec2(dir, shape.radius));
|
}
|
||||||
return result;
|
result = AddVec2(result, MulVec2(dir, shape.radius));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -147,46 +147,46 @@ Vec2 S_SupportPointFromShape(S_Shape shape, Vec2 dir)
|
|||||||
|
|
||||||
S_Lookup S_LookupFromWorld(Arena *arena, S_World *world)
|
S_Lookup S_LookupFromWorld(Arena *arena, S_World *world)
|
||||||
{
|
{
|
||||||
S_Lookup lookup = Zi;
|
S_Lookup lookup = Zi;
|
||||||
|
|
||||||
lookup.bins_count = 4096;
|
lookup.bins_count = 4096;
|
||||||
lookup.bins = PushStructs(arena, S_LookupEntNode *, lookup.bins_count);
|
lookup.bins = PushStructs(arena, S_LookupEntNode *, lookup.bins_count);
|
||||||
for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx)
|
for (i64 ent_idx = 0; ent_idx < world->ents_count; ++ent_idx)
|
||||||
|
{
|
||||||
|
S_Ent *ent = &world->ents[ent_idx];
|
||||||
|
if (ent->active)
|
||||||
{
|
{
|
||||||
S_Ent *ent = &world->ents[ent_idx];
|
S_Key key = ent->key;
|
||||||
if (ent->active)
|
S_LookupEntNode *n = PushStruct(arena, S_LookupEntNode);
|
||||||
{
|
n->ent = ent;
|
||||||
S_Key key = ent->key;
|
S_LookupEntNode **bin = &lookup.bins[ent->key.v.lo % lookup.bins_count];
|
||||||
S_LookupEntNode *n = PushStruct(arena, S_LookupEntNode);
|
SllStackPush(*bin, n);
|
||||||
n->ent = ent;
|
|
||||||
S_LookupEntNode **bin = &lookup.bins[ent->key.v.lo % lookup.bins_count];
|
|
||||||
SllStackPush(*bin, n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return lookup;
|
return lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key)
|
S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key)
|
||||||
{
|
{
|
||||||
S_Ent *result = &S_ro.nil_ent;
|
S_Ent *result = &S_ro.nil_ent;
|
||||||
if (!S_IsKeyNil(key))
|
if (!S_IsKeyNil(key))
|
||||||
|
{
|
||||||
|
i64 bins_count = lookup->bins_count;
|
||||||
|
if (bins_count > 0)
|
||||||
{
|
{
|
||||||
i64 bins_count = lookup->bins_count;
|
S_LookupEntNode *n = lookup->bins[key.v.lo % bins_count];
|
||||||
if (bins_count > 0)
|
for (; n; n = n->next)
|
||||||
|
{
|
||||||
|
if (S_MatchKey(n->ent->key, key))
|
||||||
{
|
{
|
||||||
S_LookupEntNode *n = lookup->bins[key.v.lo % bins_count];
|
result = n->ent;
|
||||||
for (; n; n = n->next)
|
break;
|
||||||
{
|
|
||||||
if (S_MatchKey(n->ent->key, key))
|
|
||||||
{
|
|
||||||
result = n->ent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -194,29 +194,29 @@ S_Ent *S_EntFromKey(S_Lookup *lookup, S_Key key)
|
|||||||
|
|
||||||
S_Ent *S_FirstEnt(S_Iter *iter, S_World *world)
|
S_Ent *S_FirstEnt(S_Iter *iter, S_World *world)
|
||||||
{
|
{
|
||||||
ZeroStruct(iter);
|
ZeroStruct(iter);
|
||||||
iter->world = world;
|
iter->world = world;
|
||||||
return S_NextEnt(iter);
|
return S_NextEnt(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Ent *S_NextEnt(S_Iter *iter)
|
S_Ent *S_NextEnt(S_Iter *iter)
|
||||||
{
|
{
|
||||||
S_World *world = iter->world;
|
S_World *world = iter->world;
|
||||||
S_Ent *result = &S_ro.nil_ent;
|
S_Ent *result = &S_ro.nil_ent;
|
||||||
|
|
||||||
i64 ent_idx = iter->cur_idx;
|
i64 ent_idx = iter->cur_idx;
|
||||||
for (; ent_idx < world->ents_count; ++ent_idx)
|
for (; ent_idx < world->ents_count; ++ent_idx)
|
||||||
|
{
|
||||||
|
S_Ent *ent = &world->ents[ent_idx];
|
||||||
|
if (ent->active)
|
||||||
{
|
{
|
||||||
S_Ent *ent = &world->ents[ent_idx];
|
result = ent;
|
||||||
if (ent->active)
|
break;
|
||||||
{
|
|
||||||
result = ent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
iter->cur_idx = ent_idx + 1;
|
}
|
||||||
|
iter->cur_idx = ent_idx + 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -224,15 +224,15 @@ S_Ent *S_NextEnt(S_Iter *iter)
|
|||||||
|
|
||||||
S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot)
|
S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot)
|
||||||
{
|
{
|
||||||
S_World *world = PushStruct(arena, S_World);
|
S_World *world = PushStruct(arena, S_World);
|
||||||
|
|
||||||
/* Copy ents */
|
/* Copy ents */
|
||||||
world->ents = PushStructsNoZero(arena, S_Ent, snapshot->ents_count);
|
world->ents = PushStructsNoZero(arena, S_Ent, snapshot->ents_count);
|
||||||
CopyStructs(world->ents, snapshot->ents, snapshot->ents_count);
|
CopyStructs(world->ents, snapshot->ents, snapshot->ents_count);
|
||||||
world->ents_count = snapshot->ents_count;
|
world->ents_count = snapshot->ents_count;
|
||||||
world->tick = snapshot->tick;
|
world->tick = snapshot->tick;
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -240,20 +240,20 @@ S_World *S_WorldFromSnapshot(Arena *arena, S_Snapshot *snapshot)
|
|||||||
|
|
||||||
MergesortCompareFuncDef(S_SortEntsByKeyCmp, arg_a, arg_b, _)
|
MergesortCompareFuncDef(S_SortEntsByKeyCmp, arg_a, arg_b, _)
|
||||||
{
|
{
|
||||||
S_Ent *a = *(S_Ent **)arg_a;
|
S_Ent *a = *(S_Ent **)arg_a;
|
||||||
S_Ent *b = *(S_Ent **)arg_b;
|
S_Ent *b = *(S_Ent **)arg_b;
|
||||||
S_Key a_key = a->key;
|
S_Key a_key = a->key;
|
||||||
S_Key b_key = b->key;
|
S_Key b_key = b->key;
|
||||||
i32 result = 0;
|
i32 result = 0;
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
result = ((a_key.v.lo < b_key.v.lo) - (a_key.v.lo > b_key.v.lo));
|
result = ((a_key.v.lo < b_key.v.lo) - (a_key.v.lo > b_key.v.lo));
|
||||||
}
|
}
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
result = ((a_key.v.hi < b_key.v.hi) - (a_key.v.hi > b_key.v.hi));
|
result = ((a_key.v.hi < b_key.v.hi) - (a_key.v.hi > b_key.v.hi));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -261,204 +261,204 @@ MergesortCompareFuncDef(S_SortEntsByKeyCmp, arg_a, arg_b, _)
|
|||||||
|
|
||||||
void S_TickForever(WaveLaneCtx *lane)
|
void S_TickForever(WaveLaneCtx *lane)
|
||||||
{
|
{
|
||||||
Arena *frame_arena = AcquireArena(Gibi(64));
|
Arena *frame_arena = AcquireArena(Gibi(64));
|
||||||
Arena *perm = PermArena();
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
const i32 world_size = S_WorldSize;
|
const i32 world_size = S_WorldSize;
|
||||||
|
|
||||||
//- World data
|
//- World data
|
||||||
Arena *ents_arena = AcquireArena(Gibi(64));
|
Arena *ents_arena = AcquireArena(Gibi(64));
|
||||||
S_World *world = PushStruct(perm, S_World);
|
S_World *world = PushStruct(perm, S_World);
|
||||||
world->ents = ArenaFirst(ents_arena, S_Ent);
|
world->ents = ArenaFirst(ents_arena, S_Ent);
|
||||||
i64 first_free_ent_num = 0;
|
i64 first_free_ent_num = 0;
|
||||||
i64 sim_time_ns = 0;
|
i64 sim_time_ns = 0;
|
||||||
|
|
||||||
u8 *tiles = PushBytes(perm, world_size * world_size * 4, alignof(S_TileKind));
|
u8 *tiles = PushBytes(perm, world_size * world_size * 4, alignof(S_TileKind));
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Sim loop
|
||||||
|
|
||||||
|
b32 shutdown = 0;
|
||||||
|
while (!shutdown)
|
||||||
|
{
|
||||||
|
ResetArena(frame_arena);
|
||||||
|
S_Iter iter = Zi;
|
||||||
|
S_Lookup lookup = Zi;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Sim loop
|
//- Begin sim frame
|
||||||
|
|
||||||
b32 shutdown = 0;
|
i64 frame_begin_ns = TimeNs();
|
||||||
while (!shutdown)
|
i64 sim_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
||||||
|
f64 sim_dt = SecondsFromNs(sim_dt_ns);
|
||||||
|
world->tick += 1;
|
||||||
|
|
||||||
|
lookup = S_LookupFromWorld(frame_arena, world);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Pop sim commands
|
||||||
|
|
||||||
|
S_InputState *input = 0;
|
||||||
|
LockTicketMutex(&S.input_back_tm);
|
||||||
{
|
{
|
||||||
ResetArena(frame_arena);
|
input = &S.input_states[S.input_back_idx];
|
||||||
S_Iter iter = Zi;
|
++S.input_back_idx;
|
||||||
S_Lookup lookup = Zi;
|
if (S.input_back_idx >= countof(S.input_states))
|
||||||
|
{
|
||||||
//////////////////////////////
|
S.input_back_idx = 0;
|
||||||
//- Begin sim frame
|
}
|
||||||
|
|
||||||
i64 frame_begin_ns = TimeNs();
|
|
||||||
i64 sim_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
|
||||||
f64 sim_dt = SecondsFromNs(sim_dt_ns);
|
|
||||||
world->tick += 1;
|
|
||||||
|
|
||||||
lookup = S_LookupFromWorld(frame_arena, world);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Pop sim commands
|
|
||||||
|
|
||||||
S_InputState *input = 0;
|
|
||||||
LockTicketMutex(&S.input_back_tm);
|
|
||||||
{
|
|
||||||
input = &S.input_states[S.input_back_idx];
|
|
||||||
++S.input_back_idx;
|
|
||||||
if (S.input_back_idx >= countof(S.input_states))
|
|
||||||
{
|
|
||||||
S.input_back_idx = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnlockTicketMutex(&S.input_back_tm);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Process world edit commands
|
|
||||||
|
|
||||||
u64 tile_placements_count = 0;
|
|
||||||
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
|
||||||
{
|
|
||||||
S_Cmd *cmd = &cmd_node->cmd;
|
|
||||||
|
|
||||||
/* Spawn entity */
|
|
||||||
if (cmd->kind == S_CmdKind_Spawn)
|
|
||||||
{
|
|
||||||
S_Ent *src = &cmd->ent;
|
|
||||||
S_Key key = src->key;
|
|
||||||
if (!S_IsKeyNil(key))
|
|
||||||
{
|
|
||||||
S_Ent *dst = S_EntFromKey(&lookup, key);
|
|
||||||
if (S_IsEntNil(dst))
|
|
||||||
{
|
|
||||||
if (first_free_ent_num > 0)
|
|
||||||
{
|
|
||||||
dst = &world->ents[first_free_ent_num - 1];
|
|
||||||
first_free_ent_num = dst->next_free_ent_num;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dst = PushStructNoZero(ents_arena, S_Ent);
|
|
||||||
}
|
|
||||||
*dst = S_ro.nil_ent;
|
|
||||||
dst->key = key;
|
|
||||||
++world->ents_count;
|
|
||||||
}
|
|
||||||
*dst = *src;
|
|
||||||
dst->local_shape.points_count = MaxI32(dst->local_shape.points_count, 1);
|
|
||||||
|
|
||||||
dst->active = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Place tiles */
|
|
||||||
if (cmd->kind == S_CmdKind_Tile)
|
|
||||||
{
|
|
||||||
tile_placements_count += 1;
|
|
||||||
S_TilePlacement placement = cmd->tile_placement;
|
|
||||||
S_UpdateTilesInPlaceFromPlacement(tiles, placement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lookup = S_LookupFromWorld(frame_arena, world);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Update ent controls
|
|
||||||
|
|
||||||
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
|
||||||
{
|
|
||||||
S_Cmd cmd = cmd_node->cmd;
|
|
||||||
if (cmd.kind == S_CmdKind_Control)
|
|
||||||
{
|
|
||||||
S_Ent *target = S_EntFromKey(&lookup, cmd.target);
|
|
||||||
if (target->active)
|
|
||||||
{
|
|
||||||
target->move = ClampVec2Len(cmd.move, 1);
|
|
||||||
target->look = cmd.look;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Apply control forces
|
|
||||||
|
|
||||||
for (S_Ent *ent = S_FirstEnt(&iter, world); ent->active; ent = S_NextEnt(&iter))
|
|
||||||
{
|
|
||||||
if (!IsVec2Zero(ent->move))
|
|
||||||
{
|
|
||||||
DEBUGBREAKABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Xform xf = ent->xf;
|
|
||||||
if (!IsVec2Zero(ent->look))
|
|
||||||
{
|
|
||||||
xf = XformWithWorldRotation(xf, AngleFromVec2(ent->look));
|
|
||||||
}
|
|
||||||
xf.og = AddVec2(xf.og, MulVec2(ent->move, ent->move_speed));
|
|
||||||
ent->xf = xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Publish sim state
|
|
||||||
|
|
||||||
/* TODO: Only copy active entities */
|
|
||||||
LockTicketMutex(&S.output_back_tm);
|
|
||||||
{
|
|
||||||
S_OutputState *output = &S.output_states[S.output_back_idx];
|
|
||||||
ResetArena(output->arena);
|
|
||||||
S_SnapshotNode *snapshot_node = PushStruct(output->arena, S_SnapshotNode);
|
|
||||||
S_Snapshot *snapshot = &snapshot_node->snapshot;
|
|
||||||
SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node);
|
|
||||||
++output->snapshots_count;
|
|
||||||
snapshot->ents_count = world->ents_count;
|
|
||||||
snapshot->tick = world->tick;
|
|
||||||
snapshot->ents = PushStructsNoZero(output->arena, S_Ent, snapshot->ents_count);
|
|
||||||
for (i64 ent_idx = 0; ent_idx < snapshot->ents_count; ++ent_idx)
|
|
||||||
{
|
|
||||||
S_Ent *src = &world->ents[ent_idx];
|
|
||||||
S_Ent *dst = &snapshot->ents[ent_idx];
|
|
||||||
*dst = *src;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Forward tile placements */
|
|
||||||
snapshot->tile_placements_count = tile_placements_count;
|
|
||||||
snapshot->tile_placements = PushStructs(output->arena, S_TilePlacement, tile_placements_count);
|
|
||||||
{
|
|
||||||
u64 tile_placement_idx = 0;
|
|
||||||
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node && tile_placement_idx < tile_placements_count; cmd_node = cmd_node->next)
|
|
||||||
{
|
|
||||||
S_Cmd *cmd = &cmd_node->cmd;
|
|
||||||
if (cmd->kind == S_CmdKind_Tile)
|
|
||||||
{
|
|
||||||
S_TilePlacement *dst_placement = &snapshot->tile_placements[tile_placement_idx];
|
|
||||||
*dst_placement = cmd->tile_placement;
|
|
||||||
tile_placement_idx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
UnlockTicketMutex(&S.output_back_tm);
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- End sim frame
|
|
||||||
|
|
||||||
/* Reset front input state */
|
|
||||||
{
|
|
||||||
Arena *arena = input->arena;
|
|
||||||
ResetArena(arena);
|
|
||||||
ZeroStruct(input);
|
|
||||||
input->arena = arena;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
i64 frame_end_ns = TimeNs();
|
|
||||||
sim_time_ns += sim_dt_ns;
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- Sleep
|
|
||||||
|
|
||||||
if (!Atomic32Fetch(&S.shutdown))
|
|
||||||
{
|
|
||||||
i64 step_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
|
||||||
P_SleepFrame(frame_begin_ns, step_dt_ns);
|
|
||||||
}
|
|
||||||
shutdown = Atomic32Fetch(&S.shutdown);
|
|
||||||
}
|
}
|
||||||
|
UnlockTicketMutex(&S.input_back_tm);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Process world edit commands
|
||||||
|
|
||||||
|
u64 tile_placements_count = 0;
|
||||||
|
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||||
|
{
|
||||||
|
S_Cmd *cmd = &cmd_node->cmd;
|
||||||
|
|
||||||
|
/* Spawn entity */
|
||||||
|
if (cmd->kind == S_CmdKind_Spawn)
|
||||||
|
{
|
||||||
|
S_Ent *src = &cmd->ent;
|
||||||
|
S_Key key = src->key;
|
||||||
|
if (!S_IsKeyNil(key))
|
||||||
|
{
|
||||||
|
S_Ent *dst = S_EntFromKey(&lookup, key);
|
||||||
|
if (S_IsEntNil(dst))
|
||||||
|
{
|
||||||
|
if (first_free_ent_num > 0)
|
||||||
|
{
|
||||||
|
dst = &world->ents[first_free_ent_num - 1];
|
||||||
|
first_free_ent_num = dst->next_free_ent_num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst = PushStructNoZero(ents_arena, S_Ent);
|
||||||
|
}
|
||||||
|
*dst = S_ro.nil_ent;
|
||||||
|
dst->key = key;
|
||||||
|
++world->ents_count;
|
||||||
|
}
|
||||||
|
*dst = *src;
|
||||||
|
dst->local_shape.points_count = MaxI32(dst->local_shape.points_count, 1);
|
||||||
|
|
||||||
|
dst->active = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place tiles */
|
||||||
|
if (cmd->kind == S_CmdKind_Tile)
|
||||||
|
{
|
||||||
|
tile_placements_count += 1;
|
||||||
|
S_TilePlacement placement = cmd->tile_placement;
|
||||||
|
S_UpdateTilesInPlaceFromPlacement(tiles, placement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lookup = S_LookupFromWorld(frame_arena, world);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Update ent controls
|
||||||
|
|
||||||
|
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||||
|
{
|
||||||
|
S_Cmd cmd = cmd_node->cmd;
|
||||||
|
if (cmd.kind == S_CmdKind_Control)
|
||||||
|
{
|
||||||
|
S_Ent *target = S_EntFromKey(&lookup, cmd.target);
|
||||||
|
if (target->active)
|
||||||
|
{
|
||||||
|
target->move = ClampVec2Len(cmd.move, 1);
|
||||||
|
target->look = cmd.look;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Apply control forces
|
||||||
|
|
||||||
|
for (S_Ent *ent = S_FirstEnt(&iter, world); ent->active; ent = S_NextEnt(&iter))
|
||||||
|
{
|
||||||
|
if (!IsVec2Zero(ent->move))
|
||||||
|
{
|
||||||
|
DEBUGBREAKABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Xform xf = ent->xf;
|
||||||
|
if (!IsVec2Zero(ent->look))
|
||||||
|
{
|
||||||
|
xf = XformWithWorldRotation(xf, AngleFromVec2(ent->look));
|
||||||
|
}
|
||||||
|
xf.og = AddVec2(xf.og, MulVec2(ent->move, ent->move_speed));
|
||||||
|
ent->xf = xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Publish sim state
|
||||||
|
|
||||||
|
/* TODO: Only copy active entities */
|
||||||
|
LockTicketMutex(&S.output_back_tm);
|
||||||
|
{
|
||||||
|
S_OutputState *output = &S.output_states[S.output_back_idx];
|
||||||
|
ResetArena(output->arena);
|
||||||
|
S_SnapshotNode *snapshot_node = PushStruct(output->arena, S_SnapshotNode);
|
||||||
|
S_Snapshot *snapshot = &snapshot_node->snapshot;
|
||||||
|
SllQueuePush(output->first_snapshot_node, output->last_snapshot_node, snapshot_node);
|
||||||
|
++output->snapshots_count;
|
||||||
|
snapshot->ents_count = world->ents_count;
|
||||||
|
snapshot->tick = world->tick;
|
||||||
|
snapshot->ents = PushStructsNoZero(output->arena, S_Ent, snapshot->ents_count);
|
||||||
|
for (i64 ent_idx = 0; ent_idx < snapshot->ents_count; ++ent_idx)
|
||||||
|
{
|
||||||
|
S_Ent *src = &world->ents[ent_idx];
|
||||||
|
S_Ent *dst = &snapshot->ents[ent_idx];
|
||||||
|
*dst = *src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forward tile placements */
|
||||||
|
snapshot->tile_placements_count = tile_placements_count;
|
||||||
|
snapshot->tile_placements = PushStructs(output->arena, S_TilePlacement, tile_placements_count);
|
||||||
|
{
|
||||||
|
u64 tile_placement_idx = 0;
|
||||||
|
for (S_CmdNode *cmd_node = input->first_cmd_node; cmd_node && tile_placement_idx < tile_placements_count; cmd_node = cmd_node->next)
|
||||||
|
{
|
||||||
|
S_Cmd *cmd = &cmd_node->cmd;
|
||||||
|
if (cmd->kind == S_CmdKind_Tile)
|
||||||
|
{
|
||||||
|
S_TilePlacement *dst_placement = &snapshot->tile_placements[tile_placement_idx];
|
||||||
|
*dst_placement = cmd->tile_placement;
|
||||||
|
tile_placement_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
UnlockTicketMutex(&S.output_back_tm);
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- End sim frame
|
||||||
|
|
||||||
|
/* Reset front input state */
|
||||||
|
{
|
||||||
|
Arena *arena = input->arena;
|
||||||
|
ResetArena(arena);
|
||||||
|
ZeroStruct(input);
|
||||||
|
input->arena = arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i64 frame_end_ns = TimeNs();
|
||||||
|
sim_time_ns += sim_dt_ns;
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- Sleep
|
||||||
|
|
||||||
|
if (!Atomic32Fetch(&S.shutdown))
|
||||||
|
{
|
||||||
|
i64 step_dt_ns = NsFromSeconds(1) / SIM_TICKS_PER_SECOND;
|
||||||
|
P_SleepFrame(frame_begin_ns, step_dt_ns);
|
||||||
|
}
|
||||||
|
shutdown = Atomic32Fetch(&S.shutdown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Struct(S_Key)
|
Struct(S_Key)
|
||||||
{
|
{
|
||||||
U128 v;
|
U128 v;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -13,21 +13,21 @@ Struct(S_Key)
|
|||||||
|
|
||||||
Struct(S_ShapeDesc)
|
Struct(S_ShapeDesc)
|
||||||
{
|
{
|
||||||
f32 radius;
|
f32 radius;
|
||||||
f32 mass;
|
f32 mass;
|
||||||
i32 count;
|
i32 count;
|
||||||
Vec2 points[8];
|
Vec2 points[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Shape)
|
Struct(S_Shape)
|
||||||
{
|
{
|
||||||
f32 mass;
|
f32 mass;
|
||||||
Vec2 centroid;
|
Vec2 centroid;
|
||||||
Vec2 center_of_mass;
|
Vec2 center_of_mass;
|
||||||
|
|
||||||
f32 radius;
|
f32 radius;
|
||||||
i32 points_count;
|
i32 points_count;
|
||||||
Vec2 points[8];
|
Vec2 points[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -37,28 +37,28 @@ Struct(S_Shape)
|
|||||||
|
|
||||||
Struct(S_Ent)
|
Struct(S_Ent)
|
||||||
{
|
{
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Persistent data
|
//- Persistent data
|
||||||
|
|
||||||
b32 active;
|
b32 active;
|
||||||
S_Key key;
|
S_Key key;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Build data
|
//- Build data
|
||||||
|
|
||||||
Xform xf;
|
Xform xf;
|
||||||
S_Shape local_shape;
|
S_Shape local_shape;
|
||||||
|
|
||||||
f32 move_speed;
|
f32 move_speed;
|
||||||
Vec2 move;
|
Vec2 move;
|
||||||
Vec2 look;
|
Vec2 look;
|
||||||
|
|
||||||
b32 has_weapon;
|
b32 has_weapon;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Internal sim data
|
//- Internal sim data
|
||||||
|
|
||||||
i64 next_free_ent_num;
|
i64 next_free_ent_num;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,21 +67,21 @@ Struct(S_Ent)
|
|||||||
|
|
||||||
Struct(S_EntArray)
|
Struct(S_EntArray)
|
||||||
{
|
{
|
||||||
u64 count;
|
u64 count;
|
||||||
S_Ent *ents;
|
S_Ent *ents;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_EntListNode)
|
Struct(S_EntListNode)
|
||||||
{
|
{
|
||||||
S_EntListNode *next;
|
S_EntListNode *next;
|
||||||
S_Ent ent;
|
S_Ent ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_EntList)
|
Struct(S_EntList)
|
||||||
{
|
{
|
||||||
S_EntListNode *first;
|
S_EntListNode *first;
|
||||||
S_EntListNode *last;
|
S_EntListNode *last;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -89,14 +89,14 @@ Struct(S_EntList)
|
|||||||
|
|
||||||
Struct(S_LookupEntNode)
|
Struct(S_LookupEntNode)
|
||||||
{
|
{
|
||||||
S_LookupEntNode *next;
|
S_LookupEntNode *next;
|
||||||
S_Ent *ent;
|
S_Ent *ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Lookup)
|
Struct(S_Lookup)
|
||||||
{
|
{
|
||||||
S_LookupEntNode **bins;
|
S_LookupEntNode **bins;
|
||||||
i64 bins_count;
|
i64 bins_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -104,27 +104,27 @@ Struct(S_Lookup)
|
|||||||
|
|
||||||
Struct(S_World)
|
Struct(S_World)
|
||||||
{
|
{
|
||||||
i64 tick;
|
i64 tick;
|
||||||
|
|
||||||
S_Ent *ents;
|
S_Ent *ents;
|
||||||
i64 ents_count;
|
i64 ents_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Snapshot)
|
Struct(S_Snapshot)
|
||||||
{
|
{
|
||||||
i64 tick;
|
i64 tick;
|
||||||
|
|
||||||
S_Ent *ents;
|
S_Ent *ents;
|
||||||
i64 ents_count;
|
i64 ents_count;
|
||||||
|
|
||||||
S_TilePlacement *tile_placements;
|
S_TilePlacement *tile_placements;
|
||||||
u64 tile_placements_count;
|
u64 tile_placements_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_SnapshotNode)
|
Struct(S_SnapshotNode)
|
||||||
{
|
{
|
||||||
S_SnapshotNode *next;
|
S_SnapshotNode *next;
|
||||||
S_Snapshot snapshot;
|
S_Snapshot snapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -132,8 +132,8 @@ Struct(S_SnapshotNode)
|
|||||||
|
|
||||||
Struct(S_Iter)
|
Struct(S_Iter)
|
||||||
{
|
{
|
||||||
S_World *world;
|
S_World *world;
|
||||||
i64 cur_idx;
|
i64 cur_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -141,32 +141,32 @@ Struct(S_Iter)
|
|||||||
|
|
||||||
Enum(S_CmdKind)
|
Enum(S_CmdKind)
|
||||||
{
|
{
|
||||||
S_CmdKind_Nop,
|
S_CmdKind_Nop,
|
||||||
S_CmdKind_Tile,
|
S_CmdKind_Tile,
|
||||||
S_CmdKind_Spawn,
|
S_CmdKind_Spawn,
|
||||||
S_CmdKind_Control,
|
S_CmdKind_Control,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Cmd)
|
Struct(S_Cmd)
|
||||||
{
|
{
|
||||||
S_CmdKind kind;
|
S_CmdKind kind;
|
||||||
|
|
||||||
/* Tiles */
|
/* Tiles */
|
||||||
S_TilePlacement tile_placement;
|
S_TilePlacement tile_placement;
|
||||||
|
|
||||||
/* Spawn */
|
/* Spawn */
|
||||||
S_Ent ent;
|
S_Ent ent;
|
||||||
|
|
||||||
/* Control */
|
/* Control */
|
||||||
S_Key target;
|
S_Key target;
|
||||||
Vec2 move;
|
Vec2 move;
|
||||||
Vec2 look;
|
Vec2 look;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_CmdNode)
|
Struct(S_CmdNode)
|
||||||
{
|
{
|
||||||
S_CmdNode *next;
|
S_CmdNode *next;
|
||||||
S_Cmd cmd;
|
S_Cmd cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -177,41 +177,41 @@ Struct(S_CmdNode)
|
|||||||
|
|
||||||
Struct(S_InputState)
|
Struct(S_InputState)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
S_CmdNode *first_cmd_node;
|
S_CmdNode *first_cmd_node;
|
||||||
S_CmdNode *last_cmd_node;
|
S_CmdNode *last_cmd_node;
|
||||||
u64 cmds_count;
|
u64 cmds_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_OutputState)
|
Struct(S_OutputState)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
S_SnapshotNode *first_snapshot_node;
|
S_SnapshotNode *first_snapshot_node;
|
||||||
S_SnapshotNode *last_snapshot_node;
|
S_SnapshotNode *last_snapshot_node;
|
||||||
u64 snapshots_count;
|
u64 snapshots_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Ctx)
|
Struct(S_Ctx)
|
||||||
{
|
{
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
Fence worker_completion_fence;
|
Fence worker_completion_fence;
|
||||||
i64 workers_count;
|
i64 workers_count;
|
||||||
|
|
||||||
//- Sim input
|
//- Sim input
|
||||||
TicketMutex input_back_tm;
|
TicketMutex input_back_tm;
|
||||||
i32 input_back_idx;
|
i32 input_back_idx;
|
||||||
S_InputState input_states[S_InputStatesCount];
|
S_InputState input_states[S_InputStatesCount];
|
||||||
|
|
||||||
//- Sim output
|
//- Sim output
|
||||||
TicketMutex output_back_tm;
|
TicketMutex output_back_tm;
|
||||||
i32 output_back_idx;
|
i32 output_back_idx;
|
||||||
S_OutputState output_states[S_OutputStatesCount];
|
S_OutputState output_states[S_OutputStatesCount];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_ReadonlyCtx)
|
Struct(S_ReadonlyCtx)
|
||||||
{
|
{
|
||||||
S_Ent nil_ent;
|
S_Ent nil_ent;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern S_Ctx S;
|
extern S_Ctx S;
|
||||||
|
|||||||
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
Vec2I32 S_TilePosFromWorldPos(Vec2 p)
|
Vec2I32 S_TilePosFromWorldPos(Vec2 p)
|
||||||
{
|
{
|
||||||
Vec2I32 result;
|
Vec2I32 result;
|
||||||
result.x = ClampI32((p.x + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1);
|
result.x = ClampI32((p.x + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1);
|
||||||
result.y = ClampI32((p.y + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1);
|
result.y = ClampI32((p.y + S_WorldSize / 2) * 2, 0, (S_WorldSize * 2) - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 S_TileIdxFromTilePos(Vec2I32 p)
|
i32 S_TileIdxFromTilePos(Vec2I32 p)
|
||||||
{
|
{
|
||||||
i32 result = ClampI32(p.x + (p.y * S_WorldSize * 2), 0, S_WorldSize * S_WorldSize * 4);
|
i32 result = ClampI32(p.x + (p.y * S_WorldSize * 2), 0, S_WorldSize * S_WorldSize * 4);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,21 +5,21 @@
|
|||||||
|
|
||||||
Enum(S_TileKind)
|
Enum(S_TileKind)
|
||||||
{
|
{
|
||||||
S_TileKind_None,
|
S_TileKind_None,
|
||||||
S_TileKind_Floor,
|
S_TileKind_Floor,
|
||||||
S_TileKind_Wall,
|
S_TileKind_Wall,
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(S_TilePlacementKind)
|
Enum(S_TilePlacementKind)
|
||||||
{
|
{
|
||||||
S_TilePlacementKind_Range
|
S_TilePlacementKind_Range
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_TilePlacement)
|
Struct(S_TilePlacement)
|
||||||
{
|
{
|
||||||
S_TilePlacementKind placement_kind;
|
S_TilePlacementKind placement_kind;
|
||||||
S_TileKind tile_kind;
|
S_TileKind tile_kind;
|
||||||
Rng2I32 range;
|
Rng2I32 range;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,38 +1,38 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Command table
|
//~ Command table
|
||||||
|
|
||||||
#define V_CmdsTableXMacro(X) \
|
#define V_CmdsTableXMacro(X) \
|
||||||
X(nop, NOP, V_CmdDescFlag_HideFromPalette, V_HOTKEY(0), ) \
|
X(nop, NOP, V_CmdDescFlag_HideFromPalette, V_HOTKEY(0), ) \
|
||||||
X(exit_program, Exit Program, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_Escape ) ) \
|
X(exit_program, Exit Program, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_Escape ) ) \
|
||||||
X(toggle_command_palette, Toggle Command Palette, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_P, .ctrl = 1, .shift = 1 ), ) \
|
X(toggle_command_palette, Toggle Command Palette, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_P, .ctrl = 1, .shift = 1 ), ) \
|
||||||
X(zoom_in, Zoom In, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelUp ), ) \
|
X(zoom_in, Zoom In, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelUp ), ) \
|
||||||
X(zoom_out, Zoom Out, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelDown ), ) \
|
X(zoom_out, Zoom Out, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelDown ), ) \
|
||||||
X(toggle_editor, Toggle Editor, V_CmdDescFlag_None, V_HOTKEY( Button_F1 ), ) \
|
X(toggle_editor, Toggle Editor, V_CmdDescFlag_None, V_HOTKEY( Button_F1 ), ) \
|
||||||
X(toggle_ui_debug, Toggle UI Debug, V_CmdDescFlag_None, V_HOTKEY( Button_F5 ), ) \
|
X(toggle_ui_debug, Toggle UI Debug, V_CmdDescFlag_None, V_HOTKEY( Button_F5 ), ) \
|
||||||
X(toggle_console, Toggle Developer Console, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent ), ) \
|
X(toggle_console, Toggle Developer Console, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent ), ) \
|
||||||
X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \
|
X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \
|
||||||
X(toggle_window_topmost, Toggle Window Topmost, V_CmdDescFlag_None, V_HOTKEY( Button_F4 ), ) \
|
X(toggle_window_topmost, Toggle Window Topmost, V_CmdDescFlag_None, V_HOTKEY( Button_F4 ), ) \
|
||||||
X(spawn, Spawn, V_CmdDescFlag_None, V_HOTKEY( Button_S, .ctrl = 1 ), ) \
|
X(spawn, Spawn, V_CmdDescFlag_None, V_HOTKEY( Button_S, .ctrl = 1 ), ) \
|
||||||
/* -------------------------------------------------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Theme types
|
//~ Theme types
|
||||||
|
|
||||||
Struct(V_WidgetTheme)
|
Struct(V_WidgetTheme)
|
||||||
{
|
{
|
||||||
GC_FontKey font;
|
GC_FontKey font;
|
||||||
f32 font_size;
|
f32 font_size;
|
||||||
f32 window_title_font_size;
|
f32 window_title_font_size;
|
||||||
|
|
||||||
Vec4 window_background_color;
|
Vec4 window_background_color;
|
||||||
Vec4 window_border_color;
|
Vec4 window_border_color;
|
||||||
Vec4 divider_color;
|
Vec4 divider_color;
|
||||||
f32 window_border;
|
f32 window_border;
|
||||||
f32 window_padding;
|
f32 window_padding;
|
||||||
f32 window_width;
|
f32 window_width;
|
||||||
|
|
||||||
f32 text_padding_x;
|
f32 text_padding_x;
|
||||||
f32 text_padding_y;
|
f32 text_padding_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -41,10 +41,10 @@ Struct(V_WidgetTheme)
|
|||||||
#define V_HOTKEY(_button, ...) { .button = _button, __VA_ARGS__ }
|
#define V_HOTKEY(_button, ...) { .button = _button, __VA_ARGS__ }
|
||||||
Struct(V_Hotkey)
|
Struct(V_Hotkey)
|
||||||
{
|
{
|
||||||
Button button;
|
Button button;
|
||||||
b32 ctrl;
|
b32 ctrl;
|
||||||
b32 alt;
|
b32 alt;
|
||||||
b32 shift;
|
b32 shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -52,57 +52,57 @@ Struct(V_Hotkey)
|
|||||||
|
|
||||||
Enum(V_CmdKind)
|
Enum(V_CmdKind)
|
||||||
{
|
{
|
||||||
#define X(name, ...) V_CmdKind_##name,
|
#define X(name, ...) V_CmdKind_##name,
|
||||||
V_CmdsTableXMacro(X)
|
V_CmdsTableXMacro(X)
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
V_CmdKind_Count,
|
V_CmdKind_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Shortcut)
|
Struct(V_Shortcut)
|
||||||
{
|
{
|
||||||
V_Shortcut *next_in_bin;
|
V_Shortcut *next_in_bin;
|
||||||
V_Shortcut *prev_in_bin;
|
V_Shortcut *prev_in_bin;
|
||||||
u64 hotkey_hash;
|
u64 hotkey_hash;
|
||||||
V_Hotkey hotkey;
|
V_Hotkey hotkey;
|
||||||
String cmd_name;
|
String cmd_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_ShortcutBin)
|
Struct(V_ShortcutBin)
|
||||||
{
|
{
|
||||||
V_Shortcut *first;
|
V_Shortcut *first;
|
||||||
V_Shortcut *last;
|
V_Shortcut *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
Enum(V_CmdDescFlag)
|
Enum(V_CmdDescFlag)
|
||||||
{
|
{
|
||||||
V_CmdDescFlag_None = 0,
|
V_CmdDescFlag_None = 0,
|
||||||
V_CmdDescFlag_HideFromPalette = (1 << 0),
|
V_CmdDescFlag_HideFromPalette = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_CmdDesc)
|
Struct(V_CmdDesc)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
String display_name;
|
String display_name;
|
||||||
V_CmdDescFlag flags;
|
V_CmdDescFlag flags;
|
||||||
V_Hotkey default_hotkeys[8];
|
V_Hotkey default_hotkeys[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Cmd)
|
Struct(V_Cmd)
|
||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_CmdNode)
|
Struct(V_CmdNode)
|
||||||
{
|
{
|
||||||
V_CmdNode *next;
|
V_CmdNode *next;
|
||||||
V_Cmd cmd;
|
V_Cmd cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_Count] = {
|
Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_Count] = {
|
||||||
#define X(_name, _display_name, _flags, ...) { .name = CompLit(#_name), .display_name = CompLit(#_display_name), .flags = _flags, .default_hotkeys = { __VA_ARGS__ } },
|
#define X(_name, _display_name, _flags, ...) { .name = CompLit(#_name), .display_name = CompLit(#_display_name), .flags = _flags, .default_hotkeys = { __VA_ARGS__ } },
|
||||||
V_CmdsTableXMacro(X)
|
V_CmdsTableXMacro(X)
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -110,38 +110,38 @@ Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_Count] = {
|
|||||||
|
|
||||||
Struct(V_CommandsWidgetItemReport)
|
Struct(V_CommandsWidgetItemReport)
|
||||||
{
|
{
|
||||||
b32 pressed;
|
b32 pressed;
|
||||||
b32 hotkey_changed;
|
b32 hotkey_changed;
|
||||||
UI_Report ui_report;
|
UI_Report ui_report;
|
||||||
V_Hotkey new_hotkeys[8];
|
V_Hotkey new_hotkeys[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_CommandsWidgetItemDesc)
|
Struct(V_CommandsWidgetItemDesc)
|
||||||
{
|
{
|
||||||
String display_name;
|
String display_name;
|
||||||
V_Hotkey hotkeys[8];
|
V_Hotkey hotkeys[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_CommandsWidgetItem)
|
Struct(V_CommandsWidgetItem)
|
||||||
{
|
{
|
||||||
V_CommandsWidgetItem *next;
|
V_CommandsWidgetItem *next;
|
||||||
UI_Key key;
|
UI_Key key;
|
||||||
V_CommandsWidgetItemDesc desc;
|
V_CommandsWidgetItemDesc desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_CommandsWidget)
|
Struct(V_CommandsWidget)
|
||||||
{
|
{
|
||||||
/* Persistent state */
|
/* Persistent state */
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
|
|
||||||
/* Per-build state */
|
/* Per-build state */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
UI_Checkpoint cp;
|
UI_Checkpoint cp;
|
||||||
V_CommandsWidgetItem *first_item;
|
V_CommandsWidgetItem *first_item;
|
||||||
V_CommandsWidgetItem *last_item;
|
V_CommandsWidgetItem *last_item;
|
||||||
u64 num_items;
|
u64 num_items;
|
||||||
} build;
|
} build;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -151,38 +151,38 @@ Struct(V_CommandsWidget)
|
|||||||
|
|
||||||
Struct(V_Space)
|
Struct(V_Space)
|
||||||
{
|
{
|
||||||
V_Space *parent;
|
V_Space *parent;
|
||||||
V_Space *next;
|
V_Space *next;
|
||||||
V_Space *prev;
|
V_Space *prev;
|
||||||
V_Space *first;
|
V_Space *first;
|
||||||
V_Space *last;
|
V_Space *last;
|
||||||
|
|
||||||
i64 panels_count;
|
i64 panels_count;
|
||||||
struct V_Panel *first_panel;
|
struct V_Panel *first_panel;
|
||||||
struct V_Panel *last_panel;
|
struct V_Panel *last_panel;
|
||||||
|
|
||||||
Axis axis;
|
Axis axis;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Panel)
|
Struct(V_Panel)
|
||||||
{
|
{
|
||||||
V_Space *space;
|
V_Space *space;
|
||||||
V_Panel *next_in_space;
|
V_Panel *next_in_space;
|
||||||
V_Panel *prev_in_space;
|
V_Panel *prev_in_space;
|
||||||
|
|
||||||
i64 active_window_idx;
|
i64 active_window_idx;
|
||||||
i64 windows_count;
|
i64 windows_count;
|
||||||
struct V_Window *first_window;
|
struct V_Window *first_window;
|
||||||
struct V_Window *last_window;
|
struct V_Window *last_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Window)
|
Struct(V_Window)
|
||||||
{
|
{
|
||||||
V_Panel *panel;
|
V_Panel *panel;
|
||||||
V_Window *next_in_panel;
|
V_Window *next_in_panel;
|
||||||
V_Window *prev_in_panel;
|
V_Window *prev_in_panel;
|
||||||
|
|
||||||
b32 is_tile_window;
|
b32 is_tile_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -190,97 +190,97 @@ Struct(V_Window)
|
|||||||
|
|
||||||
Enum(V_EditMode)
|
Enum(V_EditMode)
|
||||||
{
|
{
|
||||||
V_EditMode_Tile,
|
V_EditMode_Tile,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Frame)
|
Struct(V_Frame)
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
Arena *dverts_arena;
|
Arena *dverts_arena;
|
||||||
Arena *dvert_idxs_arena;
|
Arena *dvert_idxs_arena;
|
||||||
G_ArenaHandle gpu_arena;
|
G_ArenaHandle gpu_arena;
|
||||||
G_CommandListHandle cl;
|
G_CommandListHandle cl;
|
||||||
|
|
||||||
i64 tick;
|
i64 tick;
|
||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
i64 dt_ns;
|
i64 dt_ns;
|
||||||
f64 dt;
|
f64 dt;
|
||||||
|
|
||||||
Button held_buttons[Button_Count];
|
Button held_buttons[Button_Count];
|
||||||
V_CommandsWidget commands_widget;
|
V_CommandsWidget commands_widget;
|
||||||
|
|
||||||
String window_restore;
|
String window_restore;
|
||||||
i32 zooms;
|
i32 zooms;
|
||||||
|
|
||||||
Vec2I32 ui_dims;
|
Vec2I32 ui_dims;
|
||||||
Vec2I32 draw_dims;
|
Vec2I32 draw_dims;
|
||||||
|
|
||||||
/* Modes */
|
/* Modes */
|
||||||
b32 is_editing;
|
b32 is_editing;
|
||||||
b32 ui_debug;
|
b32 ui_debug;
|
||||||
b32 show_command_palette;
|
b32 show_command_palette;
|
||||||
b32 show_console;
|
b32 show_console;
|
||||||
|
|
||||||
/* Editor state */
|
/* Editor state */
|
||||||
V_EditMode edit_mode;
|
V_EditMode edit_mode;
|
||||||
S_TileKind equipped_tile;
|
S_TileKind equipped_tile;
|
||||||
|
|
||||||
/* Editor */
|
/* Editor */
|
||||||
b32 is_selecting;
|
b32 is_selecting;
|
||||||
b32 is_panning;
|
b32 is_panning;
|
||||||
V_SelectionMode selection_mode;
|
V_SelectionMode selection_mode;
|
||||||
Vec2 world_selection_start;
|
Vec2 world_selection_start;
|
||||||
Vec2 edit_camera_pos;
|
Vec2 edit_camera_pos;
|
||||||
f32 edit_camera_zoom;
|
f32 edit_camera_zoom;
|
||||||
|
|
||||||
/* Camera */
|
/* Camera */
|
||||||
Vec2 camera_pos;
|
Vec2 camera_pos;
|
||||||
f32 camera_zoom;
|
f32 camera_zoom;
|
||||||
|
|
||||||
/* World <-> ui */
|
/* World <-> ui */
|
||||||
Xform world_to_ui_xf;
|
Xform world_to_ui_xf;
|
||||||
Xform ui_to_world_xf;
|
Xform ui_to_world_xf;
|
||||||
|
|
||||||
/* Draw <-> ui */
|
/* Draw <-> ui */
|
||||||
Xform draw_to_ui_xf;
|
Xform draw_to_ui_xf;
|
||||||
Xform ui_to_draw_xf;
|
Xform ui_to_draw_xf;
|
||||||
|
|
||||||
/* World <-> draw */
|
/* World <-> draw */
|
||||||
Xform world_to_draw_xf;
|
Xform world_to_draw_xf;
|
||||||
Xform draw_to_world_xf;
|
Xform draw_to_world_xf;
|
||||||
|
|
||||||
/* Cursors */
|
/* Cursors */
|
||||||
Vec2 ui_cursor;
|
Vec2 ui_cursor;
|
||||||
Vec2 draw_cursor;
|
Vec2 draw_cursor;
|
||||||
Vec2 world_cursor;
|
Vec2 world_cursor;
|
||||||
Rng2 ui_selection;
|
Rng2 ui_selection;
|
||||||
Rng2 draw_selection;
|
Rng2 draw_selection;
|
||||||
Rng2 world_selection;
|
Rng2 world_selection;
|
||||||
|
|
||||||
/* Control */
|
/* Control */
|
||||||
Vec2 move;
|
Vec2 move;
|
||||||
Vec2 look;
|
Vec2 look;
|
||||||
|
|
||||||
/* Sim cmds */
|
/* Sim cmds */
|
||||||
u64 sim_cmds_count;
|
u64 sim_cmds_count;
|
||||||
S_CmdNode *first_sim_cmd_node;
|
S_CmdNode *first_sim_cmd_node;
|
||||||
S_CmdNode *last_sim_cmd_node;
|
S_CmdNode *last_sim_cmd_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_Ctx)
|
Struct(V_Ctx)
|
||||||
{
|
{
|
||||||
Arena *world_arena;
|
Arena *world_arena;
|
||||||
S_World *world;
|
S_World *world;
|
||||||
S_Lookup lookup;
|
S_Lookup lookup;
|
||||||
S_Key player_key;
|
S_Key player_key;
|
||||||
|
|
||||||
V_Space *root_space;
|
V_Space *root_space;
|
||||||
|
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
Fence shutdown_complete;
|
Fence shutdown_complete;
|
||||||
|
|
||||||
u64 current_frame_idx;
|
u64 current_frame_idx;
|
||||||
V_Frame frames[2];
|
V_Frame frames[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern V_Ctx V;
|
extern V_Ctx V;
|
||||||
|
|||||||
@ -3,121 +3,121 @@
|
|||||||
|
|
||||||
void V_DrawPoly(Arena *verts_arena, Arena *idxs_arena, Vec2Array points, Vec4 color_lin, V_DrawFlag flags)
|
void V_DrawPoly(Arena *verts_arena, Arena *idxs_arena, Vec2Array points, Vec4 color_lin, V_DrawFlag flags)
|
||||||
{
|
{
|
||||||
if (flags & V_DrawFlag_Line)
|
if (flags & V_DrawFlag_Line)
|
||||||
|
{
|
||||||
|
i32 verts_count = points.count;
|
||||||
|
if (verts_count >= 2)
|
||||||
{
|
{
|
||||||
i32 verts_count = points.count;
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
if (verts_count >= 2)
|
{
|
||||||
|
f32 half_thickness = 1;
|
||||||
|
i32 lines_count = verts_count == 2 ? 1 : verts_count;
|
||||||
|
i32 line_verts_count = lines_count * 4;
|
||||||
|
i32 idx_count = lines_count * 6;
|
||||||
|
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
|
||||||
|
|
||||||
|
/* Push dverts */
|
||||||
|
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, line_verts_count);
|
||||||
|
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
i32 a_idx = line_idx;
|
||||||
{
|
i32 b_idx = line_idx + 1;
|
||||||
f32 half_thickness = 1;
|
if (b_idx >= lines_count)
|
||||||
i32 lines_count = verts_count == 2 ? 1 : verts_count;
|
{
|
||||||
i32 line_verts_count = lines_count * 4;
|
b_idx = 0;
|
||||||
i32 idx_count = lines_count * 6;
|
}
|
||||||
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
|
|
||||||
|
|
||||||
/* Push dverts */
|
Vec2 a = points.points[a_idx];
|
||||||
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, line_verts_count);
|
Vec2 b = points.points[b_idx];
|
||||||
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
|
|
||||||
{
|
|
||||||
i32 a_idx = line_idx;
|
|
||||||
i32 b_idx = line_idx + 1;
|
|
||||||
if (b_idx >= lines_count)
|
|
||||||
{
|
|
||||||
b_idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2 a = points.points[a_idx];
|
Vec2 a_to_b = SubVec2(b, a);
|
||||||
Vec2 b = points.points[b_idx];
|
Vec2 perp = Vec2WithLen(PerpVec2(a_to_b), half_thickness);
|
||||||
|
|
||||||
Vec2 a_to_b = SubVec2(b, a);
|
Vec2 p0 = AddVec2(a, perp);
|
||||||
Vec2 perp = Vec2WithLen(PerpVec2(a_to_b), half_thickness);
|
Vec2 p1 = SubVec2(a, perp);
|
||||||
|
Vec2 p2 = SubVec2(b, perp);
|
||||||
|
Vec2 p3 = AddVec2(b, perp);
|
||||||
|
|
||||||
Vec2 p0 = AddVec2(a, perp);
|
i32 offset = line_idx * 4;
|
||||||
Vec2 p1 = SubVec2(a, perp);
|
dverts[offset + 0] = (V_DVert) { .pos = p0, .color_lin = color_lin };
|
||||||
Vec2 p2 = SubVec2(b, perp);
|
dverts[offset + 1] = (V_DVert) { .pos = p1, .color_lin = color_lin };
|
||||||
Vec2 p3 = AddVec2(b, perp);
|
dverts[offset + 2] = (V_DVert) { .pos = p2, .color_lin = color_lin };
|
||||||
|
dverts[offset + 3] = (V_DVert) { .pos = p3, .color_lin = color_lin };
|
||||||
i32 offset = line_idx * 4;
|
|
||||||
dverts[offset + 0] = (V_DVert) { .pos = p0, .color_lin = color_lin };
|
|
||||||
dverts[offset + 1] = (V_DVert) { .pos = p1, .color_lin = color_lin };
|
|
||||||
dverts[offset + 2] = (V_DVert) { .pos = p2, .color_lin = color_lin };
|
|
||||||
dverts[offset + 3] = (V_DVert) { .pos = p3, .color_lin = color_lin };
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate indices */
|
|
||||||
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
|
|
||||||
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
|
|
||||||
{
|
|
||||||
i32 indices_offset = line_idx * 6;
|
|
||||||
i32 vert_idx_offset = idx_offset + (line_idx * 4);
|
|
||||||
indices[indices_offset + 0] = vert_idx_offset + 0;
|
|
||||||
indices[indices_offset + 1] = vert_idx_offset + 1;
|
|
||||||
indices[indices_offset + 2] = vert_idx_offset + 2;
|
|
||||||
indices[indices_offset + 3] = vert_idx_offset + 0;
|
|
||||||
indices[indices_offset + 4] = vert_idx_offset + 2;
|
|
||||||
indices[indices_offset + 5] = vert_idx_offset + 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate indices */
|
||||||
|
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
|
||||||
|
for (i32 line_idx = 0; line_idx < lines_count; ++line_idx)
|
||||||
|
{
|
||||||
|
i32 indices_offset = line_idx * 6;
|
||||||
|
i32 vert_idx_offset = idx_offset + (line_idx * 4);
|
||||||
|
indices[indices_offset + 0] = vert_idx_offset + 0;
|
||||||
|
indices[indices_offset + 1] = vert_idx_offset + 1;
|
||||||
|
indices[indices_offset + 2] = vert_idx_offset + 2;
|
||||||
|
indices[indices_offset + 3] = vert_idx_offset + 0;
|
||||||
|
indices[indices_offset + 4] = vert_idx_offset + 2;
|
||||||
|
indices[indices_offset + 5] = vert_idx_offset + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i32 verts_count = points.count;
|
||||||
|
if (verts_count >= 3)
|
||||||
{
|
{
|
||||||
i32 verts_count = points.count;
|
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
|
||||||
if (verts_count >= 3)
|
i32 tris_count = verts_count - 2;
|
||||||
{
|
i32 idx_count = tris_count * 3;
|
||||||
i32 idx_offset = ArenaCount(verts_arena, V_DVert);
|
|
||||||
i32 tris_count = verts_count - 2;
|
|
||||||
i32 idx_count = tris_count * 3;
|
|
||||||
|
|
||||||
/* Push dverts */
|
/* Push dverts */
|
||||||
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count);
|
V_DVert *dverts = PushStructsNoZero(verts_arena, V_DVert, verts_count);
|
||||||
for (i32 point_idx = 0; point_idx < (i32)points.count; ++point_idx)
|
for (i32 point_idx = 0; point_idx < (i32)points.count; ++point_idx)
|
||||||
{
|
{
|
||||||
V_DVert *dvert = &dverts[point_idx];
|
V_DVert *dvert = &dverts[point_idx];
|
||||||
dvert->pos = points.points[point_idx];
|
dvert->pos = points.points[point_idx];
|
||||||
dvert->color_lin = color_lin;
|
dvert->color_lin = color_lin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate indices in a fan pattern */
|
/* Generate indices in a fan pattern */
|
||||||
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
|
i32 *indices = PushStructsNoZero(idxs_arena, i32, idx_count);
|
||||||
for (i32 i = 0; i < tris_count; ++i)
|
for (i32 i = 0; i < tris_count; ++i)
|
||||||
{
|
{
|
||||||
i32 tri_offset = i * 3;
|
i32 tri_offset = i * 3;
|
||||||
indices[tri_offset + 0] = idx_offset;
|
indices[tri_offset + 0] = idx_offset;
|
||||||
indices[tri_offset + 1] = idx_offset + i + 1;
|
indices[tri_offset + 1] = idx_offset + i + 1;
|
||||||
indices[tri_offset + 2] = idx_offset + i + 2;
|
indices[tri_offset + 2] = idx_offset + i + 2;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_DrawShape(Arena *verts_arena, Arena *idxs_arena, S_Shape shape, Vec4 color_lin, i32 detail, V_DrawFlag flags)
|
void V_DrawShape(Arena *verts_arena, Arena *idxs_arena, S_Shape shape, Vec4 color_lin, i32 detail, V_DrawFlag flags)
|
||||||
{
|
{
|
||||||
if (shape.radius == 0)
|
if (shape.radius == 0)
|
||||||
|
{
|
||||||
|
Vec2Array draw_points = Zi;
|
||||||
|
draw_points.points = shape.points;
|
||||||
|
draw_points.count = shape.points_count;
|
||||||
|
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
{
|
{
|
||||||
Vec2Array draw_points = Zi;
|
Vec2Array draw_points = Zi;
|
||||||
draw_points.points = shape.points;
|
draw_points.points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
||||||
draw_points.count = shape.points_count;
|
draw_points.count = detail;
|
||||||
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
|
for (i32 i = 0; i < detail; ++i)
|
||||||
}
|
{
|
||||||
else
|
f32 rad = ((f32)i / (f32)detail) * Tau;
|
||||||
{
|
Vec2 dir = Vec2FromAngle(rad);
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
Vec2 sp = S_SupportPointFromShape(shape, dir);
|
||||||
{
|
draw_points.points[i] = sp;
|
||||||
Vec2Array draw_points = Zi;
|
}
|
||||||
draw_points.points = PushStructsNoZero(scratch.arena, Vec2, detail);
|
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
|
||||||
draw_points.count = detail;
|
|
||||||
for (i32 i = 0; i < detail; ++i)
|
|
||||||
{
|
|
||||||
f32 rad = ((f32)i / (f32)detail) * Tau;
|
|
||||||
Vec2 dir = Vec2FromAngle(rad);
|
|
||||||
Vec2 sp = S_SupportPointFromShape(shape, dir);
|
|
||||||
draw_points.points[i] = sp;
|
|
||||||
}
|
|
||||||
V_DrawPoly(verts_arena, idxs_arena, draw_points, color_lin, flags);
|
|
||||||
}
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
Enum(V_DrawFlag)
|
Enum(V_DrawFlag)
|
||||||
{
|
{
|
||||||
V_DrawFlag_None = 0,
|
V_DrawFlag_None = 0,
|
||||||
V_DrawFlag_Line = (1 << 0),
|
V_DrawFlag_Line = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -5,36 +5,36 @@ G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 0);
|
|||||||
|
|
||||||
Enum(V_SelectionMode)
|
Enum(V_SelectionMode)
|
||||||
{
|
{
|
||||||
V_SelectionMode_None,
|
V_SelectionMode_None,
|
||||||
V_SelectionMode_Tile,
|
V_SelectionMode_Tile,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_DParams)
|
Struct(V_DParams)
|
||||||
{
|
{
|
||||||
Vec2I32 target_size;
|
Vec2I32 target_size;
|
||||||
G_Texture2DRef target_ro;
|
G_Texture2DRef target_ro;
|
||||||
G_RWTexture2DRef target_rw;
|
G_RWTexture2DRef target_rw;
|
||||||
|
|
||||||
Xform world_to_draw_xf;
|
Xform world_to_draw_xf;
|
||||||
Xform draw_to_world_xf;
|
Xform draw_to_world_xf;
|
||||||
|
|
||||||
V_SelectionMode selection_mode;
|
V_SelectionMode selection_mode;
|
||||||
S_TileKind equipped_tile;
|
S_TileKind equipped_tile;
|
||||||
|
|
||||||
Vec2 ui_cursor;
|
Vec2 ui_cursor;
|
||||||
Vec2 draw_cursor;
|
Vec2 draw_cursor;
|
||||||
Vec2 world_cursor;
|
Vec2 world_cursor;
|
||||||
Rng2 ui_selection;
|
Rng2 ui_selection;
|
||||||
Rng2 draw_selection;
|
Rng2 draw_selection;
|
||||||
Rng2 world_selection;
|
Rng2 world_selection;
|
||||||
|
|
||||||
Vec2 camera_pos;
|
Vec2 camera_pos;
|
||||||
f32 camera_zoom;
|
f32 camera_zoom;
|
||||||
|
|
||||||
f32 world_size;
|
f32 world_size;
|
||||||
G_Texture2DRef tiles;
|
G_Texture2DRef tiles;
|
||||||
G_StructuredBufferRef quads;
|
G_StructuredBufferRef quads;
|
||||||
G_StructuredBufferRef shape_verts;
|
G_StructuredBufferRef shape_verts;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -47,13 +47,13 @@ Struct(V_DParams)
|
|||||||
|
|
||||||
Enum(V_DQuadFlag)
|
Enum(V_DQuadFlag)
|
||||||
{
|
{
|
||||||
V_DQuadFlag_None = 0,
|
V_DQuadFlag_None = 0,
|
||||||
V_DQuadFlag_DrawGrid = (1 << 0),
|
V_DQuadFlag_DrawGrid = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_DQuad)
|
Struct(V_DQuad)
|
||||||
{
|
{
|
||||||
V_DQuadFlag flags;
|
V_DQuadFlag flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -61,6 +61,6 @@ Struct(V_DQuad)
|
|||||||
|
|
||||||
Struct(V_DVert)
|
Struct(V_DVert)
|
||||||
{
|
{
|
||||||
Vec2 pos;
|
Vec2 pos;
|
||||||
Vec4 color_lin;
|
Vec4 color_lin;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,124 +3,124 @@
|
|||||||
|
|
||||||
ComputeShader2D(V_BackdropCS, 8, 8)
|
ComputeShader2D(V_BackdropCS, 8, 8)
|
||||||
{
|
{
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
||||||
|
|
||||||
const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1));
|
const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1));
|
||||||
const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1));
|
const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1));
|
||||||
const Vec4 grid_color = LinearFromSrgb(Vec4(0, 0, 0, 1));
|
const Vec4 grid_color = LinearFromSrgb(Vec4(0, 0, 0, 1));
|
||||||
const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1));
|
const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1));
|
||||||
const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1));
|
const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1));
|
||||||
const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1));
|
const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1));
|
||||||
|
|
||||||
Vec2 screen_pos = Vec2(SV_DispatchThreadID) + Vec2(0.5, 0.5);
|
Vec2 screen_pos = Vec2(SV_DispatchThreadID) + Vec2(0.5, 0.5);
|
||||||
if (screen_pos.x < params.target_size.x && screen_pos.y < params.target_size.y)
|
if (screen_pos.x < params.target_size.x && screen_pos.y < params.target_size.y)
|
||||||
|
{
|
||||||
|
Vec4 result = Vec4(0.025, 0.025, 0.025, 1);
|
||||||
|
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
||||||
|
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
||||||
|
|
||||||
|
f32 half_thickness = 1;
|
||||||
|
f32 half_bounds_size = params.world_size * 0.5;
|
||||||
|
Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1));
|
||||||
|
Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1));
|
||||||
|
b32 is_in_bounds = screen_pos.x > (bounds_screen_p0.x - half_thickness) &&
|
||||||
|
screen_pos.y > (bounds_screen_p0.y - half_thickness) &&
|
||||||
|
screen_pos.x < (bounds_screen_p1.x + half_thickness) &&
|
||||||
|
screen_pos.y < (bounds_screen_p1.y + half_thickness);
|
||||||
|
if (is_in_bounds)
|
||||||
{
|
{
|
||||||
Vec4 result = Vec4(0.025, 0.025, 0.025, 1);
|
/* Grid checker */
|
||||||
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
{
|
||||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
i32 color_idx = 0;
|
||||||
|
Vec4 colors[2] = {
|
||||||
f32 half_thickness = 1;
|
background_color_a,
|
||||||
f32 half_bounds_size = params.world_size * 0.5;
|
background_color_b
|
||||||
Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1));
|
};
|
||||||
Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1));
|
const f32 checker_size = 0.5;
|
||||||
b32 is_in_bounds = screen_pos.x > (bounds_screen_p0.x - half_thickness) &&
|
Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2));
|
||||||
screen_pos.y > (bounds_screen_p0.y - half_thickness) &&
|
if (world_pos_modded.x < checker_size)
|
||||||
screen_pos.x < (bounds_screen_p1.x + half_thickness) &&
|
|
||||||
screen_pos.y < (bounds_screen_p1.y + half_thickness);
|
|
||||||
if (is_in_bounds)
|
|
||||||
{
|
{
|
||||||
/* Grid checker */
|
color_idx = !color_idx;
|
||||||
{
|
|
||||||
i32 color_idx = 0;
|
|
||||||
Vec4 colors[2] = {
|
|
||||||
background_color_a,
|
|
||||||
background_color_b
|
|
||||||
};
|
|
||||||
const f32 checker_size = 0.5;
|
|
||||||
Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2));
|
|
||||||
if (world_pos_modded.x < checker_size)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos_modded.y < checker_size)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos.x < 0)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
if (world_pos.y < 0)
|
|
||||||
{
|
|
||||||
color_idx = !color_idx;
|
|
||||||
}
|
|
||||||
result = colors[color_idx];
|
|
||||||
}
|
|
||||||
/* Grid outline */
|
|
||||||
{
|
|
||||||
Vec2 grid_screen_p0 = mul(params.world_to_draw_xf, Vec3(floor(world_pos), 1));
|
|
||||||
Vec2 grid_screen_p1 = mul(params.world_to_draw_xf, Vec3(ceil(world_pos), 1));
|
|
||||||
f32 grid_dist = 100000;
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p0.x));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p1.x));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p0.y));
|
|
||||||
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p1.y));
|
|
||||||
if (grid_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = grid_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Tile */
|
|
||||||
{
|
|
||||||
S_TileKind tile = (S_TileKind)tiles.Load(Vec3I32(tile_pos, 0));
|
|
||||||
switch (tile)
|
|
||||||
{
|
|
||||||
default: break;
|
|
||||||
|
|
||||||
case S_TileKind_Floor:
|
|
||||||
{
|
|
||||||
result = Color_Blue;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case S_TileKind_Wall:
|
|
||||||
{
|
|
||||||
result = Color_Red;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Axis */
|
|
||||||
{
|
|
||||||
Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1));
|
|
||||||
f32 x_dist = abs(screen_pos.x - zero_screen.x);
|
|
||||||
f32 y_dist = abs(screen_pos.y - zero_screen.y);
|
|
||||||
if (y_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = x_axis_color;
|
|
||||||
}
|
|
||||||
else if (x_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = y_axis_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* World bounds */
|
|
||||||
{
|
|
||||||
f32 bounds_dist = 100000;
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p0.x));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p1.x));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p0.y));
|
|
||||||
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p1.y));
|
|
||||||
if (bounds_dist <= half_thickness)
|
|
||||||
{
|
|
||||||
result = bounds_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (world_pos_modded.y < checker_size)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
if (world_pos.x < 0)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
if (world_pos.y < 0)
|
||||||
|
{
|
||||||
|
color_idx = !color_idx;
|
||||||
|
}
|
||||||
|
result = colors[color_idx];
|
||||||
|
}
|
||||||
|
/* Grid outline */
|
||||||
|
{
|
||||||
|
Vec2 grid_screen_p0 = mul(params.world_to_draw_xf, Vec3(floor(world_pos), 1));
|
||||||
|
Vec2 grid_screen_p1 = mul(params.world_to_draw_xf, Vec3(ceil(world_pos), 1));
|
||||||
|
f32 grid_dist = 100000;
|
||||||
|
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p0.x));
|
||||||
|
grid_dist = min(grid_dist, abs(screen_pos.x - grid_screen_p1.x));
|
||||||
|
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p0.y));
|
||||||
|
grid_dist = min(grid_dist, abs(screen_pos.y - grid_screen_p1.y));
|
||||||
|
if (grid_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = grid_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Tile */
|
||||||
|
{
|
||||||
|
S_TileKind tile = (S_TileKind)tiles.Load(Vec3I32(tile_pos, 0));
|
||||||
|
switch (tile)
|
||||||
|
{
|
||||||
|
default: break;
|
||||||
|
|
||||||
|
case S_TileKind_Floor:
|
||||||
|
{
|
||||||
|
result = Color_Blue;
|
||||||
|
} break;
|
||||||
|
|
||||||
target[trunc(screen_pos)] = result;
|
case S_TileKind_Wall:
|
||||||
|
{
|
||||||
|
result = Color_Red;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Axis */
|
||||||
|
{
|
||||||
|
Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1));
|
||||||
|
f32 x_dist = abs(screen_pos.x - zero_screen.x);
|
||||||
|
f32 y_dist = abs(screen_pos.y - zero_screen.y);
|
||||||
|
if (y_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = x_axis_color;
|
||||||
|
}
|
||||||
|
else if (x_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = y_axis_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* World bounds */
|
||||||
|
{
|
||||||
|
f32 bounds_dist = 100000;
|
||||||
|
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p0.x));
|
||||||
|
bounds_dist = min(bounds_dist, abs(screen_pos.x - bounds_screen_p1.x));
|
||||||
|
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p0.y));
|
||||||
|
bounds_dist = min(bounds_dist, abs(screen_pos.y - bounds_screen_p1.y));
|
||||||
|
if (bounds_dist <= half_thickness)
|
||||||
|
{
|
||||||
|
result = bounds_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
target[trunc(screen_pos)] = result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -131,21 +131,21 @@ ComputeShader2D(V_BackdropCS, 8, 8)
|
|||||||
|
|
||||||
VertexShader(V_DQuadVS, V_DQuadPSInput)
|
VertexShader(V_DQuadVS, V_DQuadPSInput)
|
||||||
{
|
{
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
||||||
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
|
|
||||||
V_DQuad quad = quads[SV_InstanceID];
|
V_DQuad quad = quads[SV_InstanceID];
|
||||||
|
|
||||||
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
|
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
|
||||||
// Vec2 tex_uv = lerp(quad.tex_uv0, quad.tex_uv1, rect_uv);
|
// Vec2 tex_uv = lerp(quad.tex_uv0, quad.tex_uv1, rect_uv);
|
||||||
// Vec2 target_pos = lerp(quad.p0, quad.p1, rect_uv);
|
// Vec2 target_pos = lerp(quad.p0, quad.p1, rect_uv);
|
||||||
Vec2 target_pos = 0;
|
Vec2 target_pos = 0;
|
||||||
|
|
||||||
V_DQuadPSInput result;
|
V_DQuadPSInput result;
|
||||||
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
||||||
result.quad_idx = SV_InstanceID;
|
result.quad_idx = SV_InstanceID;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@ -153,15 +153,15 @@ VertexShader(V_DQuadVS, V_DQuadPSInput)
|
|||||||
|
|
||||||
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
|
PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
|
||||||
{
|
{
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
||||||
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
StructuredBuffer<V_DQuad> quads = G_Dereference<V_DQuad>(params.quads);
|
||||||
V_DQuad quad = quads[input.quad_idx];
|
V_DQuad quad = quads[input.quad_idx];
|
||||||
|
|
||||||
Vec4 final_color = 0;
|
Vec4 final_color = 0;
|
||||||
|
|
||||||
V_DQuadPSOutput output;
|
V_DQuadPSOutput output;
|
||||||
output.sv_target0 = final_color;
|
output.sv_target0 = final_color;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -172,18 +172,18 @@ PixelShader(V_DQuadPS, V_DQuadPSOutput, V_DQuadPSInput input)
|
|||||||
|
|
||||||
VertexShader(V_DVertVS, V_DVertPSInput)
|
VertexShader(V_DVertVS, V_DVertPSInput)
|
||||||
{
|
{
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
||||||
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts);
|
StructuredBuffer<V_DVert> verts = G_Dereference<V_DVert>(params.shape_verts);
|
||||||
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
|
||||||
|
|
||||||
V_DVert vert = verts[SV_VertexID];
|
V_DVert vert = verts[SV_VertexID];
|
||||||
|
|
||||||
Vec2 target_pos = vert.pos;
|
Vec2 target_pos = vert.pos;
|
||||||
|
|
||||||
V_DVertPSInput result;
|
V_DVertPSInput result;
|
||||||
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
result.sv_position = Vec4(NdcFromPos(target_pos, countof(target)).xy, 0, 1);
|
||||||
result.color_lin = vert.color_lin;
|
result.color_lin = vert.color_lin;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@ -191,9 +191,9 @@ VertexShader(V_DVertVS, V_DVertPSInput)
|
|||||||
|
|
||||||
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
|
PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
|
||||||
{
|
{
|
||||||
V_DVertPSOutput output;
|
V_DVertPSOutput output;
|
||||||
output.sv_target0 = input.color_lin;
|
output.sv_target0 = input.color_lin;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -204,10 +204,10 @@ PixelShader(V_DVertPS, V_DVertPSOutput, V_DVertPSInput input)
|
|||||||
|
|
||||||
VertexShader(V_OverlayVS, V_OverlayPSInput)
|
VertexShader(V_OverlayVS, V_OverlayPSInput)
|
||||||
{
|
{
|
||||||
Vec2 uv = RectUvFromVertexId(SV_VertexID);
|
Vec2 uv = RectUvFromVertexId(SV_VertexID);
|
||||||
V_OverlayPSInput result;
|
V_OverlayPSInput result;
|
||||||
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@ -215,59 +215,59 @@ VertexShader(V_OverlayVS, V_OverlayPSInput)
|
|||||||
|
|
||||||
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
|
PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
|
||||||
{
|
{
|
||||||
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
V_DParams params = G_Dereference<V_DParams>(V_ShaderConst_Params)[0];
|
||||||
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
Texture2D<uint> tiles = G_Dereference<uint>(params.tiles);
|
||||||
Vec2 screen_pos = input.sv_position.xy;
|
Vec2 screen_pos = input.sv_position.xy;
|
||||||
Vec4 result = 0;
|
Vec4 result = 0;
|
||||||
|
|
||||||
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
Vec2 world_pos = mul(params.draw_to_world_xf, Vec3(screen_pos, 1));
|
||||||
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos);
|
||||||
S_TileKind equipped_tile = params.equipped_tile;
|
S_TileKind equipped_tile = params.equipped_tile;
|
||||||
|
|
||||||
f32 half_thickness = 1;
|
f32 half_thickness = 1;
|
||||||
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1));
|
Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1));
|
||||||
// Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25));
|
// Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25));
|
||||||
|
|
||||||
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
|
Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.8, 0.4, 0.6));
|
||||||
|
|
||||||
Rng2 screen_selection = params.draw_selection;
|
Rng2 screen_selection = params.draw_selection;
|
||||||
Rng2 world_selection = params.world_selection;
|
Rng2 world_selection = params.world_selection;
|
||||||
|
|
||||||
Rng2I32 tile_selection;
|
Rng2I32 tile_selection;
|
||||||
tile_selection.p0 = S_TilePosFromWorldPos(world_selection.p0);
|
tile_selection.p0 = S_TilePosFromWorldPos(world_selection.p0);
|
||||||
tile_selection.p1 = S_TilePosFromWorldPos(world_selection.p1);
|
tile_selection.p1 = S_TilePosFromWorldPos(world_selection.p1);
|
||||||
|
|
||||||
if (params.selection_mode == V_SelectionMode_Tile)
|
if (params.selection_mode == V_SelectionMode_Tile)
|
||||||
|
{
|
||||||
|
f32 dist = 100000000;
|
||||||
|
dist = min(dist, screen_pos.x - screen_selection.p0.x);
|
||||||
|
dist = min(dist, screen_pos.y - screen_selection.p0.y);
|
||||||
|
dist = min(dist, screen_selection.p1.x - screen_pos.x);
|
||||||
|
dist = min(dist, screen_selection.p1.y - screen_pos.y);
|
||||||
|
dist = -dist;
|
||||||
|
|
||||||
|
// if (dist >= -half_thickness && dist <= half_thickness)
|
||||||
|
// {
|
||||||
|
// result = border_color;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
{
|
{
|
||||||
f32 dist = 100000000;
|
if (world_pos.x > -(S_WorldSize / 2) &&
|
||||||
dist = min(dist, screen_pos.x - screen_selection.p0.x);
|
world_pos.y > -(S_WorldSize / 2) &&
|
||||||
dist = min(dist, screen_pos.y - screen_selection.p0.y);
|
world_pos.x < (S_WorldSize / 2) &&
|
||||||
dist = min(dist, screen_selection.p1.x - screen_pos.x);
|
world_pos.y < (S_WorldSize / 2) &&
|
||||||
dist = min(dist, screen_selection.p1.y - screen_pos.y);
|
tile_pos.x >= tile_selection.p0.x &&
|
||||||
dist = -dist;
|
tile_pos.x <= tile_selection.p1.x &&
|
||||||
|
tile_pos.y >= tile_selection.p0.y &&
|
||||||
// if (dist >= -half_thickness && dist <= half_thickness)
|
tile_pos.y <= tile_selection.p1.y)
|
||||||
// {
|
{
|
||||||
// result = border_color;
|
result = inner_color;
|
||||||
// }
|
}
|
||||||
// else
|
|
||||||
{
|
|
||||||
if (world_pos.x > -(S_WorldSize / 2) &&
|
|
||||||
world_pos.y > -(S_WorldSize / 2) &&
|
|
||||||
world_pos.x < (S_WorldSize / 2) &&
|
|
||||||
world_pos.y < (S_WorldSize / 2) &&
|
|
||||||
tile_pos.x >= tile_selection.p0.x &&
|
|
||||||
tile_pos.x <= tile_selection.p1.x &&
|
|
||||||
tile_pos.y >= tile_selection.p0.y &&
|
|
||||||
tile_pos.y <= tile_selection.p1.y)
|
|
||||||
{
|
|
||||||
result = inner_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
V_OverlayPSOutput output;
|
V_OverlayPSOutput output;
|
||||||
output.sv_target0 = result;
|
output.sv_target0 = result;
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
Struct(V_DQuadPSInput)
|
Struct(V_DQuadPSInput)
|
||||||
{
|
{
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
Semantic(nointerpolation u32, quad_idx);
|
Semantic(nointerpolation u32, quad_idx);
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_DQuadPSOutput)
|
Struct(V_DQuadPSOutput)
|
||||||
{
|
{
|
||||||
Semantic(Vec4, sv_target0);
|
Semantic(Vec4, sv_target0);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -18,13 +18,13 @@ Struct(V_DQuadPSOutput)
|
|||||||
Struct(V_DVertPSInput)
|
Struct(V_DVertPSInput)
|
||||||
{
|
{
|
||||||
|
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
Semantic(Vec4, color_lin);
|
Semantic(Vec4, color_lin);
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_DVertPSOutput)
|
Struct(V_DVertPSOutput)
|
||||||
{
|
{
|
||||||
Semantic(Vec4, sv_target0);
|
Semantic(Vec4, sv_target0);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -33,12 +33,12 @@ Struct(V_DVertPSOutput)
|
|||||||
Struct(V_OverlayPSInput)
|
Struct(V_OverlayPSInput)
|
||||||
{
|
{
|
||||||
|
|
||||||
Semantic(Vec4, sv_position);
|
Semantic(Vec4, sv_position);
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(V_OverlayPSOutput)
|
Struct(V_OverlayPSOutput)
|
||||||
{
|
{
|
||||||
Semantic(Vec4, sv_target0);
|
Semantic(Vec4, sv_target0);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
5551
src/pp_old/pp.c
5551
src/pp_old/pp.c
File diff suppressed because it is too large
Load Diff
372
src/pp_old/pp.h
372
src/pp_old/pp.h
@ -4,98 +4,98 @@
|
|||||||
//- Bind kinds
|
//- Bind kinds
|
||||||
Enum(PP_BindKind)
|
Enum(PP_BindKind)
|
||||||
{
|
{
|
||||||
PP_BindKind_None,
|
PP_BindKind_None,
|
||||||
|
|
||||||
PP_BindKind_MoveUp,
|
PP_BindKind_MoveUp,
|
||||||
PP_BindKind_MoveDown,
|
PP_BindKind_MoveDown,
|
||||||
PP_BindKind_MoveLeft,
|
PP_BindKind_MoveLeft,
|
||||||
PP_BindKind_MoveRight,
|
PP_BindKind_MoveRight,
|
||||||
PP_BindKind_Walk,
|
PP_BindKind_Walk,
|
||||||
PP_BindKind_Fire,
|
PP_BindKind_Fire,
|
||||||
PP_BindKind_AltFire,
|
PP_BindKind_AltFire,
|
||||||
|
|
||||||
PP_BindKind_TestTile,
|
PP_BindKind_TestTile,
|
||||||
PP_BindKind_DebugClear,
|
PP_BindKind_DebugClear,
|
||||||
PP_BindKind_DebugSpawn1,
|
PP_BindKind_DebugSpawn1,
|
||||||
PP_BindKind_DebugSpawn2,
|
PP_BindKind_DebugSpawn2,
|
||||||
PP_BindKind_DebugSpawn3,
|
PP_BindKind_DebugSpawn3,
|
||||||
PP_BindKind_DebugSpawn4,
|
PP_BindKind_DebugSpawn4,
|
||||||
PP_BindKind_DebugWalls,
|
PP_BindKind_DebugWalls,
|
||||||
PP_BindKind_DebugFollow,
|
PP_BindKind_DebugFollow,
|
||||||
PP_BindKind_DebugDraw,
|
PP_BindKind_DebugDraw,
|
||||||
PP_BindKind_DebugConsole,
|
PP_BindKind_DebugConsole,
|
||||||
PP_BindKind_DebugCamera,
|
PP_BindKind_DebugCamera,
|
||||||
PP_BindKind_DebugLister,
|
PP_BindKind_DebugLister,
|
||||||
PP_BindKind_DebugPause,
|
PP_BindKind_DebugPause,
|
||||||
PP_BindKind_DebugStep,
|
PP_BindKind_DebugStep,
|
||||||
PP_BindKind_DebugDrag,
|
PP_BindKind_DebugDrag,
|
||||||
PP_BindKind_DebugDelete,
|
PP_BindKind_DebugDelete,
|
||||||
PP_BindKind_DebugTeleport,
|
PP_BindKind_DebugTeleport,
|
||||||
PP_BindKind_DebugExplode,
|
PP_BindKind_DebugExplode,
|
||||||
PP_BindKind_DebugToggleTopmost,
|
PP_BindKind_DebugToggleTopmost,
|
||||||
PP_BindKind_DebugUi,
|
PP_BindKind_DebugUi,
|
||||||
PP_BindKind_FullscreenMod,
|
PP_BindKind_FullscreenMod,
|
||||||
PP_BindKind_Fullscreen,
|
PP_BindKind_Fullscreen,
|
||||||
PP_BindKind_ZoomIn,
|
PP_BindKind_ZoomIn,
|
||||||
PP_BindKind_ZoomOut,
|
PP_BindKind_ZoomOut,
|
||||||
PP_BindKind_Pan,
|
PP_BindKind_Pan,
|
||||||
|
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
/* Debug */
|
/* Debug */
|
||||||
|
|
||||||
PP_BindKind_ResetDebugSteps,
|
PP_BindKind_ResetDebugSteps,
|
||||||
PP_BindKind_IncrementDebugSteps,
|
PP_BindKind_IncrementDebugSteps,
|
||||||
PP_BindKind_DecrementDebugSteps,
|
PP_BindKind_DecrementDebugSteps,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PP_BindKind_Count
|
PP_BindKind_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Test bindings
|
//- Test bindings
|
||||||
|
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
Global Readonly PP_BindKind g_binds[Btn_Count] = {
|
Global Readonly PP_BindKind g_binds[Btn_Count] = {
|
||||||
[Btn_W] = PP_BindKind_MoveUp,
|
[Btn_W] = PP_BindKind_MoveUp,
|
||||||
[Btn_S] = PP_BindKind_MoveDown,
|
[Btn_S] = PP_BindKind_MoveDown,
|
||||||
[Btn_A] = PP_BindKind_MoveLeft,
|
[Btn_A] = PP_BindKind_MoveLeft,
|
||||||
[Btn_D] = PP_BindKind_MoveRight,
|
[Btn_D] = PP_BindKind_MoveRight,
|
||||||
[Btn_M1] = PP_BindKind_Fire,
|
[Btn_M1] = PP_BindKind_Fire,
|
||||||
[Btn_M2] = PP_BindKind_AltFire,
|
[Btn_M2] = PP_BindKind_AltFire,
|
||||||
#if 0
|
#if 0
|
||||||
[Btn_Alt] = PP_BindKind_Walk,
|
[Btn_Alt] = PP_BindKind_Walk,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Testing */
|
/* Testing */
|
||||||
[Btn_Z] = PP_BindKind_TestTile,
|
[Btn_Z] = PP_BindKind_TestTile,
|
||||||
[Btn_M5] = PP_BindKind_DebugDrag,
|
[Btn_M5] = PP_BindKind_DebugDrag,
|
||||||
[Btn_M4] = PP_BindKind_DebugDelete,
|
[Btn_M4] = PP_BindKind_DebugDelete,
|
||||||
[Btn_F] = PP_BindKind_DebugExplode,
|
[Btn_F] = PP_BindKind_DebugExplode,
|
||||||
[Btn_T] = PP_BindKind_DebugTeleport,
|
[Btn_T] = PP_BindKind_DebugTeleport,
|
||||||
[Btn_C] = PP_BindKind_DebugClear,
|
[Btn_C] = PP_BindKind_DebugClear,
|
||||||
[Btn_1] = PP_BindKind_DebugSpawn1,
|
[Btn_1] = PP_BindKind_DebugSpawn1,
|
||||||
[Btn_2] = PP_BindKind_DebugSpawn2,
|
[Btn_2] = PP_BindKind_DebugSpawn2,
|
||||||
[Btn_3] = PP_BindKind_DebugSpawn3,
|
[Btn_3] = PP_BindKind_DebugSpawn3,
|
||||||
[Btn_4] = PP_BindKind_DebugSpawn4,
|
[Btn_4] = PP_BindKind_DebugSpawn4,
|
||||||
[Btn_G] = PP_BindKind_DebugWalls,
|
[Btn_G] = PP_BindKind_DebugWalls,
|
||||||
[Btn_N] = PP_BindKind_DebugStep,
|
[Btn_N] = PP_BindKind_DebugStep,
|
||||||
[Btn_Q] = PP_BindKind_DebugFollow,
|
[Btn_Q] = PP_BindKind_DebugFollow,
|
||||||
[Btn_F1] = PP_BindKind_DebugPause,
|
[Btn_F1] = PP_BindKind_DebugPause,
|
||||||
[Btn_F2] = PP_BindKind_DebugCamera,
|
[Btn_F2] = PP_BindKind_DebugCamera,
|
||||||
[Btn_F3] = PP_BindKind_DebugDraw,
|
[Btn_F3] = PP_BindKind_DebugDraw,
|
||||||
[Btn_Tab] = PP_BindKind_DebugLister,
|
[Btn_Tab] = PP_BindKind_DebugLister,
|
||||||
[Btn_F4] = PP_BindKind_DebugToggleTopmost,
|
[Btn_F4] = PP_BindKind_DebugToggleTopmost,
|
||||||
[Btn_F5] = PP_BindKind_DebugUi,
|
[Btn_F5] = PP_BindKind_DebugUi,
|
||||||
[Btn_GraveAccent] = PP_BindKind_DebugConsole,
|
[Btn_GraveAccent] = PP_BindKind_DebugConsole,
|
||||||
[Btn_Alt] = PP_BindKind_FullscreenMod,
|
[Btn_Alt] = PP_BindKind_FullscreenMod,
|
||||||
[Btn_Enter] = PP_BindKind_Fullscreen,
|
[Btn_Enter] = PP_BindKind_Fullscreen,
|
||||||
[Btn_MWheelUp] = PP_BindKind_ZoomIn,
|
[Btn_MWheelUp] = PP_BindKind_ZoomIn,
|
||||||
[Btn_MWheelDown] = PP_BindKind_ZoomOut,
|
[Btn_MWheelDown] = PP_BindKind_ZoomOut,
|
||||||
[Btn_M3] = PP_BindKind_Pan,
|
[Btn_M3] = PP_BindKind_Pan,
|
||||||
|
|
||||||
#if IsRtcEnabled
|
#if IsRtcEnabled
|
||||||
[Btn_ForwardSlash] = PP_BindKind_ResetDebugSteps,
|
[Btn_ForwardSlash] = PP_BindKind_ResetDebugSteps,
|
||||||
[Btn_Comma] = PP_BindKind_DecrementDebugSteps,
|
[Btn_Comma] = PP_BindKind_DecrementDebugSteps,
|
||||||
[Btn_Period] = PP_BindKind_IncrementDebugSteps
|
[Btn_Period] = PP_BindKind_IncrementDebugSteps
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -104,9 +104,9 @@ Global Readonly PP_BindKind g_binds[Btn_Count] = {
|
|||||||
|
|
||||||
Struct(PP_SecondsStat)
|
Struct(PP_SecondsStat)
|
||||||
{
|
{
|
||||||
u64 last_second_start;
|
u64 last_second_start;
|
||||||
u64 last_second_end;
|
u64 last_second_end;
|
||||||
u64 last_second;
|
u64 last_second;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -114,12 +114,12 @@ Struct(PP_SecondsStat)
|
|||||||
|
|
||||||
Struct(PP_ConsoleLog)
|
Struct(PP_ConsoleLog)
|
||||||
{
|
{
|
||||||
String msg;
|
String msg;
|
||||||
i32 level;
|
i32 level;
|
||||||
i32 color_index;
|
i32 color_index;
|
||||||
DateTime datetime;
|
DateTime datetime;
|
||||||
PP_ConsoleLog *prev;
|
PP_ConsoleLog *prev;
|
||||||
PP_ConsoleLog *next;
|
PP_ConsoleLog *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -127,17 +127,17 @@ Struct(PP_ConsoleLog)
|
|||||||
|
|
||||||
Struct(PP_DecodeQueueNode)
|
Struct(PP_DecodeQueueNode)
|
||||||
{
|
{
|
||||||
PP_Client *client;
|
PP_Client *client;
|
||||||
u64 tick;
|
u64 tick;
|
||||||
u64 base_tick;
|
u64 base_tick;
|
||||||
String tmp_encoded;
|
String tmp_encoded;
|
||||||
PP_DecodeQueueNode *next;
|
PP_DecodeQueueNode *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(PP_DecodeQueue)
|
Struct(PP_DecodeQueue)
|
||||||
{
|
{
|
||||||
PP_DecodeQueueNode *first;
|
PP_DecodeQueueNode *first;
|
||||||
PP_DecodeQueueNode *last;
|
PP_DecodeQueueNode *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -145,137 +145,137 @@ Struct(PP_DecodeQueue)
|
|||||||
|
|
||||||
Struct(PP_BindState)
|
Struct(PP_BindState)
|
||||||
{
|
{
|
||||||
b32 is_held; /* Is this bind held down this frame */
|
b32 is_held; /* Is this bind held down this frame */
|
||||||
u32 num_presses; /* How many times was this bind's pressed since last frame */
|
u32 num_presses; /* How many times was this bind's pressed since last frame */
|
||||||
u32 num_repeats; /* How many times was this bind's key repeated since last frame */
|
u32 num_repeats; /* How many times was this bind's key repeated since last frame */
|
||||||
u32 num_presses_and_repeats; /* Same as `num_presses` but includes key repeats as well */
|
u32 num_presses_and_repeats; /* Same as `num_presses` but includes key repeats as well */
|
||||||
u32 num_releases; /* How many times was this bind released since last frame */
|
u32 num_releases; /* How many times was this bind released since last frame */
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(PP_SharedUserState)
|
Struct(PP_SharedUserState)
|
||||||
{
|
{
|
||||||
Atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
|
|
||||||
Fence shutdown_jobs_fence;
|
Fence shutdown_jobs_fence;
|
||||||
u64 shutdown_jobs_count;
|
u64 shutdown_jobs_count;
|
||||||
|
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
String connect_address_str;
|
String connect_address_str;
|
||||||
|
|
||||||
PP_ClientStore *user_client_store;
|
PP_ClientStore *user_client_store;
|
||||||
PP_Client *user_unblended_client; /* Contains snapshots received from local sim */
|
PP_Client *user_unblended_client; /* Contains snapshots received from local sim */
|
||||||
PP_Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
PP_Client *user_blended_client; /* Contains single snapshot from result of blending local sim snapshots */
|
||||||
PP_Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
PP_Snapshot *ss_blended; /* Points to blended snapshot contained in blended client */
|
||||||
|
|
||||||
u64 user_tick;
|
u64 user_tick;
|
||||||
u64 window_os_gen;
|
u64 window_os_gen;
|
||||||
|
|
||||||
//- Usage stats
|
//- Usage stats
|
||||||
i64 last_second_reset_ns;
|
i64 last_second_reset_ns;
|
||||||
PP_SecondsStat net_bytes_read;
|
PP_SecondsStat net_bytes_read;
|
||||||
PP_SecondsStat net_bytes_sent;
|
PP_SecondsStat net_bytes_sent;
|
||||||
|
|
||||||
//- Renderer gbuffers
|
//- Renderer gbuffers
|
||||||
GPU_Resource *albedo;
|
GPU_Resource *albedo;
|
||||||
GPU_Resource *emittance;
|
GPU_Resource *emittance;
|
||||||
GPU_Resource *emittance_flood_read;
|
GPU_Resource *emittance_flood_read;
|
||||||
GPU_Resource *emittance_flood_target;
|
GPU_Resource *emittance_flood_target;
|
||||||
GPU_Resource *shade_read;
|
GPU_Resource *shade_read;
|
||||||
GPU_Resource *shade_target;
|
GPU_Resource *shade_target;
|
||||||
|
|
||||||
//- Renderer transient buffers
|
//- Renderer transient buffers
|
||||||
GPU_TransientBuffer material_instances_tbuff;
|
GPU_TransientBuffer material_instances_tbuff;
|
||||||
GPU_TransientBuffer grids_tbuff;
|
GPU_TransientBuffer grids_tbuff;
|
||||||
Arena *material_instances_arena;
|
Arena *material_instances_arena;
|
||||||
Arena *grids_arena;
|
Arena *grids_arena;
|
||||||
|
|
||||||
//- Renderer state
|
//- Renderer state
|
||||||
RandState frame_rand;
|
RandState frame_rand;
|
||||||
u64 frame_index;
|
u64 frame_index;
|
||||||
i64 gpu_submit_fence_target;
|
i64 gpu_submit_fence_target;
|
||||||
|
|
||||||
//- Bind state
|
//- Bind state
|
||||||
PP_BindState bind_states[PP_BindKind_Count];
|
PP_BindState bind_states[PP_BindKind_Count];
|
||||||
|
|
||||||
//- Window -> user
|
//- Window -> user
|
||||||
Mutex sys_window_events_mutex;
|
Mutex sys_window_events_mutex;
|
||||||
Arena *sys_window_events_arena;
|
Arena *sys_window_events_arena;
|
||||||
|
|
||||||
//- User -> sim
|
//- User -> sim
|
||||||
Mutex user_sim_cmd_mutex;
|
Mutex user_sim_cmd_mutex;
|
||||||
PP_ControlData user_sim_cmd_control;
|
PP_ControlData user_sim_cmd_control;
|
||||||
PP_EntKey user_hovered_ent;
|
PP_EntKey user_hovered_ent;
|
||||||
u64 last_user_sim_cmd_gen;
|
u64 last_user_sim_cmd_gen;
|
||||||
u64 user_sim_cmd_gen;
|
u64 user_sim_cmd_gen;
|
||||||
|
|
||||||
Atomic32 user_paused;
|
Atomic32 user_paused;
|
||||||
Atomic32 user_paused_steps;
|
Atomic32 user_paused_steps;
|
||||||
|
|
||||||
//- Sim -> user
|
//- Sim -> user
|
||||||
Mutex local_to_user_client_mutex;
|
Mutex local_to_user_client_mutex;
|
||||||
PP_ClientStore *local_to_user_client_store;
|
PP_ClientStore *local_to_user_client_store;
|
||||||
PP_Client *local_to_user_client;
|
PP_Client *local_to_user_client;
|
||||||
i64 local_to_user_client_publish_dt_ns;
|
i64 local_to_user_client_publish_dt_ns;
|
||||||
i64 local_to_user_client_publish_time_ns;
|
i64 local_to_user_client_publish_time_ns;
|
||||||
|
|
||||||
//- Local sim -> user rolling window of publish time deltas
|
//- Local sim -> user rolling window of publish time deltas
|
||||||
i64 last_local_to_user_snapshot_published_at_ns;
|
i64 last_local_to_user_snapshot_published_at_ns;
|
||||||
i64 average_local_to_user_snapshot_publish_dt_ns;
|
i64 average_local_to_user_snapshot_publish_dt_ns;
|
||||||
|
|
||||||
i64 local_sim_predicted_time_ns; /* Calculated from <last local sim to user pubilsh time> + <time since last local sim to user publish> */
|
i64 local_sim_predicted_time_ns; /* Calculated from <last local sim to user pubilsh time> + <time since last local sim to user publish> */
|
||||||
i64 render_time_target_ns; /* Claculated from <local_sim_rpedicted_time_ns> - <render interp delay> */
|
i64 render_time_target_ns; /* Claculated from <local_sim_rpedicted_time_ns> - <render interp delay> */
|
||||||
i64 render_time_ns; /* Incremented at a constant rate based on average local to user publish delta, but snaps to render_time_target_ns if it gets too distant */
|
i64 render_time_ns; /* Incremented at a constant rate based on average local to user publish delta, but snaps to render_time_target_ns if it gets too distant */
|
||||||
|
|
||||||
u64 local_sim_last_known_tick;
|
u64 local_sim_last_known_tick;
|
||||||
i64 local_sim_last_known_time_ns;
|
i64 local_sim_last_known_time_ns;
|
||||||
|
|
||||||
i64 real_dt_ns;
|
i64 real_dt_ns;
|
||||||
i64 real_time_ns;
|
i64 real_time_ns;
|
||||||
|
|
||||||
//- Window
|
//- Window
|
||||||
|
|
||||||
String window_restore;
|
String window_restore;
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Persist start
|
//- Persist start
|
||||||
StructRegion(AUTO_PERSIST_START);
|
StructRegion(AUTO_PERSIST_START);
|
||||||
|
|
||||||
//- Debug ui
|
//- Debug ui
|
||||||
|
|
||||||
b32 ui_debug;
|
b32 ui_debug;
|
||||||
|
|
||||||
PP_EntKey debug_following;
|
PP_EntKey debug_following;
|
||||||
Vec2 debug_camera_pan_start;
|
Vec2 debug_camera_pan_start;
|
||||||
b32 debug_camera_panning;
|
b32 debug_camera_panning;
|
||||||
b32 debug_camera;
|
b32 debug_camera;
|
||||||
|
|
||||||
b32 lister_active;
|
b32 lister_active;
|
||||||
Vec2 lister_pos;
|
Vec2 lister_pos;
|
||||||
|
|
||||||
b32 debug_draw;
|
b32 debug_draw;
|
||||||
b32 debug_console;
|
b32 debug_console;
|
||||||
|
|
||||||
//- Per frame
|
//- Per frame
|
||||||
|
|
||||||
Vec2I32 screen_size;
|
Vec2I32 screen_size;
|
||||||
Vec2 screen_cursor;
|
Vec2 screen_cursor;
|
||||||
|
|
||||||
Xform ui_to_screen_xf;
|
Xform ui_to_screen_xf;
|
||||||
Vec2I32 ui_size;
|
Vec2I32 ui_size;
|
||||||
Vec2 ui_cursor;
|
Vec2 ui_cursor;
|
||||||
|
|
||||||
Xform render_to_ui_xf;
|
Xform render_to_ui_xf;
|
||||||
Vec2I32 render_size;
|
Vec2I32 render_size;
|
||||||
|
|
||||||
Xform world_to_render_xf;
|
Xform world_to_render_xf;
|
||||||
Xform world_to_ui_xf;
|
Xform world_to_ui_xf;
|
||||||
Vec2 world_cursor;
|
Vec2 world_cursor;
|
||||||
|
|
||||||
Vec2 focus_send;
|
Vec2 focus_send;
|
||||||
|
|
||||||
StructRegion(AUTO_PERSIST_END);
|
StructRegion(AUTO_PERSIST_END);
|
||||||
//- Persist end
|
//- Persist end
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
} extern PP_shared_user_state;
|
} extern PP_shared_user_state;
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ Struct(PP_SharedUserState)
|
|||||||
|
|
||||||
Struct(PP_SwappedUserState)
|
Struct(PP_SwappedUserState)
|
||||||
{
|
{
|
||||||
PP_SharedUserState s;
|
PP_SharedUserState s;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -3,52 +3,52 @@
|
|||||||
|
|
||||||
Struct(PP_MaterialSig)
|
Struct(PP_MaterialSig)
|
||||||
{
|
{
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Mat4x4 projection; /* 16 consts */
|
Mat4x4 projection; /* 16 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
SamplerStateRid sampler; /* 01 consts */
|
SamplerStateRid sampler; /* 01 consts */
|
||||||
StructuredBufferRid instances; /* 01 consts */
|
StructuredBufferRid instances; /* 01 consts */
|
||||||
StructuredBufferRid grids; /* 01 consts */
|
StructuredBufferRid grids; /* 01 consts */
|
||||||
u32 _pad0; /* 01 consts (padding) */
|
u32 _pad0; /* 01 consts (padding) */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
};
|
};
|
||||||
AssertRootConst(PP_MaterialSig, 20);
|
AssertRootConst(PP_MaterialSig, 20);
|
||||||
|
|
||||||
Struct(PP_MaterialInstance)
|
Struct(PP_MaterialInstance)
|
||||||
{
|
{
|
||||||
Texture2DRid tex;
|
Texture2DRid tex;
|
||||||
u32 grid_id;
|
u32 grid_id;
|
||||||
Xform xf;
|
Xform xf;
|
||||||
Vec2 tex_uv0;
|
Vec2 tex_uv0;
|
||||||
Vec2 tex_uv1;
|
Vec2 tex_uv1;
|
||||||
u32 tint_srgb;
|
u32 tint_srgb;
|
||||||
u32 is_light;
|
u32 is_light;
|
||||||
Vec3 light_emittance_srgb;
|
Vec3 light_emittance_srgb;
|
||||||
};
|
};
|
||||||
#define PP_DefaultMaterialInstance (PP_MaterialInstance) { \
|
#define PP_DefaultMaterialInstance (PP_MaterialInstance) { \
|
||||||
.tex = { U32Max }, \
|
.tex = { U32Max }, \
|
||||||
.grid_id = U32Max, \
|
.grid_id = U32Max, \
|
||||||
.xf = XformIdentity, \
|
.xf = XformIdentity, \
|
||||||
.tex_uv1 = VEC2(1, 1), \
|
.tex_uv1 = VEC2(1, 1), \
|
||||||
.tint_srgb = Color_White, \
|
.tint_srgb = Color_White, \
|
||||||
}
|
}
|
||||||
|
|
||||||
Struct(PP_MaterialGrid)
|
Struct(PP_MaterialGrid)
|
||||||
{
|
{
|
||||||
f32 line_thickness;
|
f32 line_thickness;
|
||||||
f32 line_spacing;
|
f32 line_spacing;
|
||||||
Vec2 offset;
|
Vec2 offset;
|
||||||
u32 bg0_srgb;
|
u32 bg0_srgb;
|
||||||
u32 bg1_srgb;
|
u32 bg1_srgb;
|
||||||
u32 line_srgb;
|
u32 line_srgb;
|
||||||
u32 x_srgb;
|
u32 x_srgb;
|
||||||
u32 y_srgb;
|
u32 y_srgb;
|
||||||
};
|
};
|
||||||
#define PP_DefaultMaterialGrid (PP_MaterialGrid) { \
|
#define PP_DefaultMaterialGrid (PP_MaterialGrid) { \
|
||||||
.line_thickness = 1, \
|
.line_thickness = 1, \
|
||||||
.line_spacing = 1, \
|
.line_spacing = 1, \
|
||||||
.bg0_srgb = Color_Black, \
|
.bg0_srgb = Color_Black, \
|
||||||
.bg0_srgb = Color_White \
|
.bg0_srgb = Color_White \
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -56,17 +56,17 @@ Struct(PP_MaterialGrid)
|
|||||||
|
|
||||||
Struct(PP_FloodSig)
|
Struct(PP_FloodSig)
|
||||||
{
|
{
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
i32 step_len; /* 01 consts */
|
i32 step_len; /* 01 consts */
|
||||||
Texture2DRid emittance; /* 01 consts */
|
Texture2DRid emittance; /* 01 consts */
|
||||||
RWTexture2DRid read; /* 01 consts */
|
RWTexture2DRid read; /* 01 consts */
|
||||||
RWTexture2DRid target; /* 01 consts */
|
RWTexture2DRid target; /* 01 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
u32 tex_width; /* 01 consts */
|
u32 tex_width; /* 01 consts */
|
||||||
u32 tex_height; /* 01 consts */
|
u32 tex_height; /* 01 consts */
|
||||||
u32 _pad0; /* 01 consts (padding) */
|
u32 _pad0; /* 01 consts (padding) */
|
||||||
u32 _pad1; /* 01 consts (padding) */
|
u32 _pad1; /* 01 consts (padding) */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
};
|
};
|
||||||
AssertRootConst(PP_FloodSig, 8);
|
AssertRootConst(PP_FloodSig, 8);
|
||||||
|
|
||||||
@ -79,27 +79,27 @@ AssertRootConst(PP_FloodSig, 8);
|
|||||||
|
|
||||||
Struct(PP_ShadeSig)
|
Struct(PP_ShadeSig)
|
||||||
{
|
{
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Vec4U32 frame_seed; /* 04 consts */
|
Vec4U32 frame_seed; /* 04 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
u32 flags; /* 01 consts */
|
u32 flags; /* 01 consts */
|
||||||
u32 tex_width; /* 01 consts */
|
u32 tex_width; /* 01 consts */
|
||||||
u32 tex_height; /* 01 consts */
|
u32 tex_height; /* 01 consts */
|
||||||
f32 exposure; /* 01 consts */
|
f32 exposure; /* 01 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Vec2 camera_offset; /* 02 consts */
|
Vec2 camera_offset; /* 02 consts */
|
||||||
u32 frame_index; /* 01 consts */
|
u32 frame_index; /* 01 consts */
|
||||||
Texture2DRid albedo; /* 01 consts */
|
Texture2DRid albedo; /* 01 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Texture2DRid emittance; /* 01 consts */
|
Texture2DRid emittance; /* 01 consts */
|
||||||
Texture2DRid emittance_flood; /* 01 consts */
|
Texture2DRid emittance_flood; /* 01 consts */
|
||||||
Texture2DRid read; /* 01 consts */
|
Texture2DRid read; /* 01 consts */
|
||||||
RWTexture2DRid target; /* 01 consts */
|
RWTexture2DRid target; /* 01 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
Texture3DRid noise; /* 01 consts */
|
Texture3DRid noise; /* 01 consts */
|
||||||
u32 noise_tex_width; /* 01 consts */
|
u32 noise_tex_width; /* 01 consts */
|
||||||
u32 noise_tex_height; /* 01 consts */
|
u32 noise_tex_height; /* 01 consts */
|
||||||
u32 noise_tex_depth; /* 01 consts */
|
u32 noise_tex_depth; /* 01 consts */
|
||||||
/* ----------------------------------------------------- */
|
/* ----------------------------------------------------- */
|
||||||
};
|
};
|
||||||
AssertRootConst(PP_ShadeSig, 20);
|
AssertRootConst(PP_ShadeSig, 20);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user