- Portable DEPRECATED macro
- Deprecate os_compare_and_swap and replace with more portable compare_and_swap - Fixed a bug where the wrong image would be drawn
This commit is contained in:
parent
e54897432b
commit
9842834065
11 changed files with 126 additions and 17 deletions
|
@ -6,6 +6,6 @@ mkdir build
|
||||||
|
|
||||||
pushd build
|
pushd build
|
||||||
|
|
||||||
clang -g -o cgame.exe ../build.c -O0 -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -Wno-deprecated-declarations -lkernel32 -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler -lshlwapi -femit-all-decls
|
clang -g -o cgame.exe ../build.c -O0 -std=c11 -D_CRT_SECURE_NO_WARNINGS -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -lkernel32 -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler -lshlwapi -femit-all-decls
|
||||||
|
|
||||||
popd
|
popd
|
|
@ -12,7 +12,7 @@ pushd build
|
||||||
mkdir dissassembly
|
mkdir dissassembly
|
||||||
pushd dissassembly
|
pushd dissassembly
|
||||||
|
|
||||||
clang -o cgame.asm ../../build.c -Ofast -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -Wno-deprecated-declarations -finline-functions -ffast-math -fno-math-errno -funsafe-math-optimizations -freciprocal-math -ffinite-math-only -fassociative-math -fno-signed-zeros -fno-trapping-math -ftree-vectorize -fomit-frame-pointer -funroll-loops -fno-rtti -fno-exceptions -S -masm=intel
|
clang -o cgame.asm ../../build.c -Ofast -std=c11 -D_CRT_SECURE_NO_WARNINGS -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -Wno-deprecated-declarations -finline-functions -ffast-math -fno-math-errno -funsafe-math-optimizations -freciprocal-math -ffinite-math-only -fassociative-math -fno-signed-zeros -fno-trapping-math -ftree-vectorize -fomit-frame-pointer -funroll-loops -fno-rtti -fno-exceptions -S -masm=intel
|
||||||
|
|
||||||
popd
|
popd
|
||||||
popd
|
popd
|
|
@ -9,7 +9,7 @@ pushd build
|
||||||
mkdir release
|
mkdir release
|
||||||
pushd release
|
pushd release
|
||||||
|
|
||||||
clang -o cgame.exe ../../build.c -Ofast -DNDEBUG -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -Wno-deprecated-declarations -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler -lshlwapi -finline-functions -finline-hint-functions -ffast-math -fno-math-errno -funsafe-math-optimizations -freciprocal-math -ffinite-math-only -fassociative-math -fno-signed-zeros -fno-trapping-math -ftree-vectorize -fomit-frame-pointer -funroll-loops -fno-rtti -fno-exceptions
|
clang -o cgame.exe ../../build.c -Ofast -DNDEBUG -std=c11 -D_CRT_SECURE_NO_WARNINGS -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -Wno-deprecated-declarations -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler -lshlwapi -finline-functions -finline-hint-functions -ffast-math -fno-math-errno -funsafe-math-optimizations -freciprocal-math -ffinite-math-only -fassociative-math -fno-signed-zeros -fno-trapping-math -ftree-vectorize -fomit-frame-pointer -funroll-loops -fno-rtti -fno-exceptions
|
||||||
|
|
||||||
popd
|
popd
|
||||||
popd
|
popd
|
|
@ -1,4 +1,4 @@
|
||||||
## v0.00.003 -
|
## v0.00.003 - Fixes
|
||||||
|
|
||||||
Random:
|
Random:
|
||||||
- get_random_float64()
|
- get_random_float64()
|
||||||
|
@ -24,6 +24,9 @@ Misc:
|
||||||
- Fixed Y placement of window when changing the window rect
|
- Fixed Y placement of window when changing the window rect
|
||||||
- Fixed window sizing when setting scaled_width or scaled_height
|
- Fixed window sizing when setting scaled_width or scaled_height
|
||||||
- Updated readme
|
- Updated readme
|
||||||
|
- Portable DEPRECATED macro
|
||||||
|
- Deprecate os_compare_and_swap and replace with more portable compare_and_swap
|
||||||
|
- Fixed a bug where the wrong image would be drawn
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,34 @@ typedef struct Cpu_Capabilities {
|
||||||
#else
|
#else
|
||||||
#define COMPILER_CAN_DO_AVX512 0
|
#define COMPILER_CAN_DO_AVX512 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEPRECATED(proc, msg) __declspec(deprecated(msg)) func
|
||||||
|
|
||||||
|
#pragma intrinsic(_InterlockedCompareExchange8)
|
||||||
|
#pragma intrinsic(_InterlockedCompareExchange16)
|
||||||
|
#pragma intrinsic(_InterlockedCompareExchange)
|
||||||
|
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||||
|
|
||||||
|
inline bool compare_and_swap_8(uint8_t *a, uint8_t b, uint8_t old) {
|
||||||
|
return _InterlockedCompareExchange8((volatile char*)a, (char)b, (char)old) == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_16(uint16_t *a, uint16_t b, uint16_t old) {
|
||||||
|
return _InterlockedCompareExchange16((volatile short*)a, (short)b, (short)old) == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_32(uint32_t *a, uint32_t b, uint32_t old) {
|
||||||
|
return _InterlockedCompareExchange((volatile long*)a, (long)b, (long)old) == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_64(uint64_t *a, uint64_t b, uint64_t old) {
|
||||||
|
return _InterlockedCompareExchange64((volatile long long*)a, (long long)b, (long long)old) == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_bool(bool *a, bool b, bool old) {
|
||||||
|
return compare_and_swap_8((uint8_t*)a, (uint8_t)b, (uint8_t)old);
|
||||||
|
}
|
||||||
|
|
||||||
#elif COMPILER_GCC || COMPILER_CLANG
|
#elif COMPILER_GCC || COMPILER_CLANG
|
||||||
#define inline __attribute__((always_inline)) inline
|
#define inline __attribute__((always_inline)) inline
|
||||||
#define alignat(x) __attribute__((aligned(x)))
|
#define alignat(x) __attribute__((aligned(x)))
|
||||||
|
@ -115,6 +143,57 @@ typedef struct Cpu_Capabilities {
|
||||||
#else
|
#else
|
||||||
#define COMPILER_CAN_DO_AVX512 0
|
#define COMPILER_CAN_DO_AVX512 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEPRECATED(proc, msg) proc __attribute__((deprecated(msg)))
|
||||||
|
|
||||||
|
inline bool compare_and_swap_8(uint8_t *a, uint8_t b, uint8_t old) {
|
||||||
|
unsigned char result;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"lock; cmpxchgb %2, %1"
|
||||||
|
: "=a" (result), "=m" (*a)
|
||||||
|
: "r" (b), "m" (*a), "a" (old)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return result == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_16(uint16_t *a, uint16_t b, uint16_t old) {
|
||||||
|
unsigned short result;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"lock; cmpxchgw %2, %1"
|
||||||
|
: "=a" (result), "=m" (*a)
|
||||||
|
: "r" (b), "m" (*a), "a" (old)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return result == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_32(uint32_t *a, uint32_t b, uint32_t old) {
|
||||||
|
unsigned int result;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"lock; cmpxchgl %2, %1"
|
||||||
|
: "=a" (result), "=m" (*a)
|
||||||
|
: "r" (b), "m" (*a), "a" (old)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return result == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_64(uint64_t *a, uint64_t b, uint64_t old) {
|
||||||
|
unsigned long long result;
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"lock; cmpxchgq %2, %1"
|
||||||
|
: "=a" (result), "=m" (*a)
|
||||||
|
: "r" (b), "m" (*a), "a" (old)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
return result == old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool compare_and_swap_bool(bool *a, bool b, bool old) {
|
||||||
|
return compare_and_swap_8((uint8_t*)a, (uint8_t)b, (uint8_t)old);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define inline inline
|
#define inline inline
|
||||||
#define COMPILER_HAS_MEMCPY_INTRINSICS 0
|
#define COMPILER_HAS_MEMCPY_INTRINSICS 0
|
||||||
|
@ -126,6 +205,8 @@ typedef struct Cpu_Capabilities {
|
||||||
#define COMPILER_CAN_DO_AVX2 0
|
#define COMPILER_CAN_DO_AVX2 0
|
||||||
#define COMPILER_CAN_DO_AVX512 0
|
#define COMPILER_CAN_DO_AVX512 0
|
||||||
|
|
||||||
|
#define deprecated(msg)
|
||||||
|
|
||||||
#warning "Compiler is not explicitly supported, some things will probably not work as expected"
|
#warning "Compiler is not explicitly supported, some things will probably not work as expected"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ Usage:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define QUADS_PER_BLOCK 16
|
#define QUADS_PER_BLOCK 256
|
||||||
typedef struct Draw_Quad {
|
typedef struct Draw_Quad {
|
||||||
Vector2 bottom_left, top_left, top_right, bottom_right;
|
Vector2 bottom_left, top_left, top_right, bottom_right;
|
||||||
// r, g, b, a
|
// r, g, b, a
|
||||||
|
@ -82,6 +82,8 @@ typedef struct Draw_Quad {
|
||||||
Gfx_Filter_Mode image_min_filter;
|
Gfx_Filter_Mode image_min_filter;
|
||||||
Gfx_Filter_Mode image_mag_filter;
|
Gfx_Filter_Mode image_mag_filter;
|
||||||
|
|
||||||
|
float32 z;
|
||||||
|
|
||||||
} Draw_Quad;
|
} Draw_Quad;
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,6 +91,8 @@ typedef struct Draw_Quad_Block {
|
||||||
Draw_Quad quad_buffer[QUADS_PER_BLOCK];
|
Draw_Quad quad_buffer[QUADS_PER_BLOCK];
|
||||||
u64 num_quads;
|
u64 num_quads;
|
||||||
|
|
||||||
|
float32 low_z, high_z;
|
||||||
|
|
||||||
struct Draw_Quad_Block *next;
|
struct Draw_Quad_Block *next;
|
||||||
} Draw_Quad_Block;
|
} Draw_Quad_Block;
|
||||||
|
|
||||||
|
@ -103,6 +107,8 @@ typedef struct Draw_Frame {
|
||||||
|
|
||||||
Matrix4 projection;
|
Matrix4 projection;
|
||||||
Matrix4 view;
|
Matrix4 view;
|
||||||
|
|
||||||
|
bool enable_z_sorting;
|
||||||
} Draw_Frame;
|
} Draw_Frame;
|
||||||
// This frame is passed to the platform layer and rendered in os_update.
|
// This frame is passed to the platform layer and rendered in os_update.
|
||||||
// Resets every frame.
|
// Resets every frame.
|
||||||
|
@ -129,7 +135,11 @@ Draw_Quad *draw_quad_projected(Draw_Quad quad, Matrix4 world_to_clip) {
|
||||||
quad.image_min_filter = GFX_FILTER_MODE_NEAREST;
|
quad.image_min_filter = GFX_FILTER_MODE_NEAREST;
|
||||||
quad.image_min_filter = GFX_FILTER_MODE_NEAREST;
|
quad.image_min_filter = GFX_FILTER_MODE_NEAREST;
|
||||||
|
|
||||||
if (!draw_frame.current) draw_frame.current = &first_block;
|
if (!draw_frame.current) {
|
||||||
|
draw_frame.current = &first_block;
|
||||||
|
draw_frame.current->low_z = F32_MAX;
|
||||||
|
draw_frame.current->high_z = F32_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
if (draw_frame.current == &first_block) draw_frame.num_blocks = 1;
|
if (draw_frame.current == &first_block) draw_frame.num_blocks = 1;
|
||||||
|
|
||||||
|
@ -146,6 +156,9 @@ Draw_Quad *draw_quad_projected(Draw_Quad quad, Matrix4 world_to_clip) {
|
||||||
draw_frame.current->num_quads = 0;
|
draw_frame.current->num_quads = 0;
|
||||||
|
|
||||||
draw_frame.num_blocks += 1;
|
draw_frame.num_blocks += 1;
|
||||||
|
|
||||||
|
draw_frame.current->low_z = F32_MAX;
|
||||||
|
draw_frame.current->high_z = F32_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_frame.current->quad_buffer[draw_frame.current->num_quads] = quad;
|
draw_frame.current->quad_buffer[draw_frame.current->num_quads] = quad;
|
||||||
|
|
|
@ -575,6 +575,7 @@ void d3d11_process_draw_frame() {
|
||||||
ID3D11ShaderResourceView *textures[32];
|
ID3D11ShaderResourceView *textures[32];
|
||||||
ID3D11ShaderResourceView *last_texture = 0;
|
ID3D11ShaderResourceView *last_texture = 0;
|
||||||
u64 num_textures = 0;
|
u64 num_textures = 0;
|
||||||
|
s8 last_texture_index = 0;
|
||||||
|
|
||||||
D3D11_Vertex* head = (D3D11_Vertex*)d3d11_staging_quad_buffer;
|
D3D11_Vertex* head = (D3D11_Vertex*)d3d11_staging_quad_buffer;
|
||||||
D3D11_Vertex* pointer = head;
|
D3D11_Vertex* pointer = head;
|
||||||
|
@ -592,7 +593,7 @@ void d3d11_process_draw_frame() {
|
||||||
if (q->image) {
|
if (q->image) {
|
||||||
|
|
||||||
if (last_texture == q->image->gfx_handle) {
|
if (last_texture == q->image->gfx_handle) {
|
||||||
texture_index = (s8)(num_textures-1);
|
texture_index = last_texture_index;
|
||||||
} else {
|
} else {
|
||||||
// First look if texture is already bound
|
// First look if texture is already bound
|
||||||
for (u64 j = 0; j < num_textures; j++) {
|
for (u64 j = 0; j < num_textures; j++) {
|
||||||
|
@ -623,6 +624,7 @@ void d3d11_process_draw_frame() {
|
||||||
}
|
}
|
||||||
textures[texture_index] = q->image->gfx_handle;
|
textures[texture_index] = q->image->gfx_handle;
|
||||||
last_texture = q->image->gfx_handle;
|
last_texture = q->image->gfx_handle;
|
||||||
|
last_texture_index = texture_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (q->type == QUAD_TYPE_TEXT) {
|
if (q->type == QUAD_TYPE_TEXT) {
|
||||||
|
|
|
@ -135,10 +135,14 @@ typedef double f64;
|
||||||
typedef f32 float32;
|
typedef f32 float32;
|
||||||
typedef f64 float64;
|
typedef f64 float64;
|
||||||
|
|
||||||
|
#define F32_MAX 3.402823466e+38F
|
||||||
|
#define F32_MIN 1.175494351e-38F
|
||||||
|
|
||||||
typedef u8 bool;
|
typedef u8 bool;
|
||||||
#define false 0
|
#define false 0
|
||||||
#define true 1
|
#define true 1
|
||||||
|
|
||||||
|
|
||||||
// Determine what compiler we are on
|
// Determine what compiler we are on
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#define COMPILER_CLANG 1
|
#define COMPILER_CLANG 1
|
||||||
|
|
|
@ -440,7 +440,7 @@ Spinlock *os_make_spinlock(Allocator allocator) {
|
||||||
void os_spinlock_lock(Spinlock *l) {
|
void os_spinlock_lock(Spinlock *l) {
|
||||||
while (true) {
|
while (true) {
|
||||||
bool expected = false;
|
bool expected = false;
|
||||||
if (os_compare_and_swap_bool(&l->locked, true, expected)) {
|
if (compare_and_swap_bool(&l->locked, true, expected)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (l->locked) {
|
while (l->locked) {
|
||||||
|
@ -451,7 +451,7 @@ void os_spinlock_lock(Spinlock *l) {
|
||||||
|
|
||||||
void os_spinlock_unlock(Spinlock *l) {
|
void os_spinlock_unlock(Spinlock *l) {
|
||||||
bool expected = true;
|
bool expected = true;
|
||||||
bool success = os_compare_and_swap_bool(&l->locked, false, expected);
|
bool success = compare_and_swap_bool(&l->locked, false, expected);
|
||||||
assert(success, "This thread should have acquired the spinlock but compare_and_swap failed");
|
assert(success, "This thread should have acquired the spinlock but compare_and_swap failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,17 @@ void os_spinlock_unlock(Spinlock* l);
|
||||||
///
|
///
|
||||||
// Concurrency utilities
|
// Concurrency utilities
|
||||||
|
|
||||||
bool os_compare_and_swap_8 (u8 *a, u8 b, u8 old);
|
// #Cleanup
|
||||||
bool os_compare_and_swap_16 (u16 *a, u16 b, u16 old);
|
// In retrospect, I'm not sure why I choose to implement this per OS.
|
||||||
bool os_compare_and_swap_32 (u32 *a, u32 b, u32 old);
|
// I think Win32 InterlockedCompareExchange just generates the cmpxchg
|
||||||
bool os_compare_and_swap_64 (u64 *a, u64 b, u64 old);
|
// instruction anyways, so may as well just inline asm it (or Win32
|
||||||
bool os_compare_and_swap_bool(bool *a, bool b, bool old);
|
// if we're compiling with msvc) (LDREX/STREX on ARM)
|
||||||
|
// - CharlieM July 8th 2024
|
||||||
|
DEPRECATED(bool os_compare_and_swap_8 (u8 *a, u8 b, u8 old), "use compare_and_swap instead");
|
||||||
|
DEPRECATED(bool os_compare_and_swap_16 (u16 *a, u16 b, u16 old), "use compare_and_swap instead");
|
||||||
|
DEPRECATED(bool os_compare_and_swap_32 (u32 *a, u32 b, u32 old), "use compare_and_swap instead");
|
||||||
|
DEPRECATED(bool os_compare_and_swap_64 (u64 *a, u64 b, u64 old), "use compare_and_swap instead");
|
||||||
|
DEPRECATED(bool os_compare_and_swap_bool(bool *a, bool b, bool old), "use compare_and_swap instead");
|
||||||
|
|
||||||
void os_sleep(u32 ms);
|
void os_sleep(u32 ms);
|
||||||
void os_yield_thread();
|
void os_yield_thread();
|
||||||
|
|
|
@ -1098,12 +1098,12 @@ void oogabooga_run_tests() {
|
||||||
|
|
||||||
#if CONFIGURATION != RELEASE
|
#if CONFIGURATION != RELEASE
|
||||||
print("Thread bombing allocator... ");
|
print("Thread bombing allocator... ");
|
||||||
Thread* threads[100];
|
Thread* threads[300];
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 300; i++) {
|
||||||
threads[i] = os_make_thread(test_allocator_threaded, get_heap_allocator());
|
threads[i] = os_make_thread(test_allocator_threaded, get_heap_allocator());
|
||||||
os_start_thread(threads[i]);
|
os_start_thread(threads[i]);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 300; i++) {
|
||||||
os_join_thread(threads[i]);
|
os_join_thread(threads[i]);
|
||||||
}
|
}
|
||||||
print("OK!\n");
|
print("OK!\n");
|
||||||
|
|
Reference in a new issue