multi gpu api rendering. working

This commit is contained in:
Dennis Eichhorn 2025-02-14 07:31:48 +01:00
parent c7b881e6b7
commit 6aa80b8e69
42 changed files with 1753 additions and 1340 deletions

3
.gitignore vendored
View File

@ -7,4 +7,5 @@ bin/*
*.res *.res
*.exe *.exe
*.map *.map
*.pdb *.pdb
*.o

View File

@ -13,45 +13,15 @@
#include <stdint.h> #include <stdint.h>
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../CpuInfo.h" #include "../CpuInfo.h"
#include "../../compiler/CompilerUtils.h"
#ifdef _MSC_VER #define svcntw() 0
#include <intrin.h>
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuidex(cpuInfo, function_id, 0);
}
#else
/*
#include <cpuid.h>
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuid(function_id, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
}
*/
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
asm volatile(
"cpuid"
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
: "a" (function_id)
);
}
#endif
inline
int32 svcntw() {
return 0;
}
uint64 cpu_info_features() { uint64 cpu_info_features() {
uint64 feature_bitfield = 0; uint64 feature_bitfield = 0;
int32 cpuInfo[4] = {0}; int32 cpuInfo[4] = {0};
// Query function 0x00000001 compiler_cpuid(cpuInfo, 0x00000001);
cpuid(cpuInfo, 0x00000001);
uint32 ecx = (uint32) cpuInfo[2]; uint32 ecx = (uint32) cpuInfo[2];
uint32 edx = (uint32) cpuInfo[3]; uint32 edx = (uint32) cpuInfo[3];
@ -84,8 +54,7 @@ uint64 cpu_info_features() {
if (edx & (1 << 25)) feature_bitfield |= CPU_FEATURE_SSE; if (edx & (1 << 25)) feature_bitfield |= CPU_FEATURE_SSE;
if (edx & (1 << 26)) feature_bitfield |= CPU_FEATURE_SSE2; if (edx & (1 << 26)) feature_bitfield |= CPU_FEATURE_SSE2;
// Query function 0x00000007 compiler_cpuid(cpuInfo, 0x00000007);
cpuid(cpuInfo, 0x00000007);
uint32 ebx = (uint32) cpuInfo[1]; uint32 ebx = (uint32) cpuInfo[1];
uint32 ecx7 = (uint32) cpuInfo[2]; uint32 ecx7 = (uint32) cpuInfo[2];
@ -107,8 +76,7 @@ uint64 cpu_info_features() {
// Map ECX features // Map ECX features
if (ecx7 & (1 << 0)) feature_bitfield |= CPU_FEATURE_PREFETCHWT1; if (ecx7 & (1 << 0)) feature_bitfield |= CPU_FEATURE_PREFETCHWT1;
// Query extended function 0x80000001 compiler_cpuid(cpuInfo, 0x80000001);
cpuid(cpuInfo, 0x80000001);
uint32 ecx81 = (uint32) cpuInfo[2]; uint32 ecx81 = (uint32) cpuInfo[2];
uint32 edx81 = (uint32) cpuInfo[3]; uint32 edx81 = (uint32) cpuInfo[3];
@ -141,7 +109,7 @@ void cpu_info_cache(byte level, CpuCacheInfo* cache) {
cache->line_size = 0; cache->line_size = 0;
int32 regs[4]; int32 regs[4];
cpuid(regs, (0x04 << 8) | level); compiler_cpuid(regs, (0x04 << 8) | level);
eax = regs[0]; eax = regs[0];
ebx = regs[1]; ebx = regs[1];
ecx = regs[2]; ecx = regs[2];

View File

@ -54,9 +54,9 @@
#define intrin_bits_count_32(data) _mm_popcnt_u32((data)) #define intrin_bits_count_32(data) _mm_popcnt_u32((data))
#define intrin_bits_count_64(data) _mm_popcnt_u64((data)) #define intrin_bits_count_64(data) _mm_popcnt_u64((data))
#define intrin_prefetch_l1(mem) _mm_prefetch((mem), _MM_HINT_T0) #define intrin_prefetch_l1(mem) _mm_prefetch((const char *) (mem), _MM_HINT_T0)
#define intrin_prefetch_l2(mem) _mm_prefetch((mem), _MM_HINT_T1) #define intrin_prefetch_l2(mem) _mm_prefetch((const char *) (mem), _MM_HINT_T1)
#define intrin_prefetch_l3(mem) _mm_prefetch((mem), _MM_HINT_T2) #define intrin_prefetch_l3(mem) _mm_prefetch((const char *) (mem), _MM_HINT_T2)
inline inline
uint64 intrin_timestamp_counter() { uint64 intrin_timestamp_counter() {

View File

@ -23,9 +23,6 @@ struct Asset {
// Could be 0 if there is no official id // Could be 0 if there is no official id
uint32 official_id; uint32 official_id;
// @performance Maybe if we would set the IS_LOADED_STATE in the enum as the highest bit we could use the state variable and check it with >=
atomic_32 int32 is_loaded;
// Describes how much ram/vram the asset uses // Describes how much ram/vram the asset uses
// E.g. vram_size = 0 but ram_size > 0 means that it never uses any gpu memory // E.g. vram_size = 0 but ram_size > 0 means that it never uses any gpu memory
uint32 ram_size; uint32 ram_size;
@ -35,25 +32,29 @@ struct Asset {
// Usually 1 but in some cases an ams may hold entities of variable chunk length // Usually 1 but in some cases an ams may hold entities of variable chunk length
// For textures for example a 128x128 is of size 1 but 256x256 is of size 4 // For textures for example a 128x128 is of size 1 but 256x256 is of size 4
// Needs to be uint16 since we need more than 2^8 for very large textures (4K/8K textures)
uint16 size; uint16 size;
// @performance Maybe if we would set the IS_LOADED_STATE in the enum as the highest bit we could use the state variable and check it with >=
atomic_8 int8 is_loaded;
// Which asset component is used // Which asset component is used
byte component_id; byte component_id;
byte state; byte state;
// Actual memory address and specific asset data
byte* self;
// Counts the references to this asset // Counts the references to this asset
// e.g. textures or entity schemas (NOT entities themselves) // e.g. textures or entity schemas (NOT entities themselves)
uint16 reference_count; uint16 reference_count;
// Actual memory address and specific asset data
byte* self;
// An asset can reference up to N other assets // An asset can reference up to N other assets
// This allows us to quickly update the other assets // This allows us to quickly update the other assets
// Uses official_id // Uses official_id
// @performance This could potentially be bad because many assets will have 0 or only 1-4 references // @performance This could potentially be bad because many assets will have 0 or only 1-4 references
uint32 references[12]; uint32 references[8];
}; };
#endif #endif

View File

@ -214,6 +214,7 @@ Asset* asset_archive_asset_load(const AssetArchive* archive, int32 id, AssetMana
if (element->type == 0) { if (element->type == 0) {
asset = thrd_ams_reserve_asset(ams, (byte) component_id, id_str, element->uncompressed); asset = thrd_ams_reserve_asset(ams, (byte) component_id, id_str, element->uncompressed);
asset->official_id = id; asset->official_id = id;
asset->ram_size = element->uncompressed;
FileBody file = {}; FileBody file = {};
file.content = asset->self; file.content = asset->self;

View File

@ -39,8 +39,6 @@ struct Camera {
f32 sensitivity; f32 sensitivity;
f32 zoom; f32 zoom;
// @question Consider to make these f32 values.
// Yes, this uses obviously more space BUT we use these values very often in vertex calculations and always have to cast it
uint16 viewport_width; uint16 viewport_width;
uint16 viewport_height; uint16 viewport_height;
@ -49,9 +47,9 @@ struct Camera {
f32 zfar; f32 zfar;
f32 aspect; f32 aspect;
f32 view[16]; alignas(64) f32 view[16];
f32 projection[16]; alignas(64) f32 projection[16];
f32 orth[16]; alignas(64) f32 orth[16];
}; };
void void
@ -228,11 +226,12 @@ void camera_movement(Camera* camera, CameraMovement* movement, f32 dt, bool rela
inline inline
void camera_orth_matrix_lh(Camera* __restrict camera) void camera_orth_matrix_lh(Camera* __restrict camera)
{ {
mat4_identity(camera->orth); //mat4_identity(camera->orth);
camera->orth[15] = 1.0f;
mat4_ortho_sparse_lh( mat4_ortho_sparse_lh(
camera->orth, camera->orth,
0, camera->viewport_width, 0.0f, (f32) camera->viewport_width,
0, camera->viewport_height, 0.0f, (f32) camera->viewport_height,
camera->znear, camera->znear,
camera->zfar camera->zfar
); );
@ -241,11 +240,12 @@ void camera_orth_matrix_lh(Camera* __restrict camera)
inline inline
void camera_orth_matrix_rh(Camera* __restrict camera) void camera_orth_matrix_rh(Camera* __restrict camera)
{ {
mat4_identity(camera->orth); //mat4_identity(camera->orth);
camera->orth[15] = 1.0f;
mat4_ortho_sparse_rh( mat4_ortho_sparse_rh(
camera->orth, camera->orth,
0, camera->viewport_width, 0.0f, (f32) camera->viewport_width,
0, camera->viewport_height, 0.0f, (f32) camera->viewport_height,
camera->znear, camera->znear,
camera->zfar camera->zfar
); );
@ -254,7 +254,8 @@ void camera_orth_matrix_rh(Camera* __restrict camera)
inline inline
void camera_projection_matrix_lh(Camera* __restrict camera) void camera_projection_matrix_lh(Camera* __restrict camera)
{ {
mat4_identity(camera->projection); //mat4_identity(camera->projection);
camera->projection[15] = 1.0f;
mat4_perspective_sparse_lh( mat4_perspective_sparse_lh(
camera->projection, camera->projection,
camera->fov, camera->fov,
@ -267,7 +268,8 @@ void camera_projection_matrix_lh(Camera* __restrict camera)
inline inline
void camera_projection_matrix_rh(Camera* __restrict camera) void camera_projection_matrix_rh(Camera* __restrict camera)
{ {
mat4_identity(camera->projection); //mat4_identity(camera->projection);
camera->projection[15] = 1.0f;
mat4_perspective_sparse_rh( mat4_perspective_sparse_rh(
camera->projection, camera->projection,
camera->fov, camera->fov,

View File

@ -126,7 +126,7 @@ Asset* cmd_texture_create(AppCmdBuffer* __restrict cb, Command* __restrict cmd)
} }
Texture* texture = (Texture *) asset->self; Texture* texture = (Texture *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL if (cb->gpu_api_type == GPU_API_TYPE_OPENGL
&& !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP) && !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP)
) { ) {
image_flip_vertical(cb->thrd_mem_vol, &texture->image); image_flip_vertical(cb->thrd_mem_vol, &texture->image);
@ -157,7 +157,7 @@ Asset* cmd_font_create(AppCmdBuffer* __restrict cb, Command* __restrict cmd)
} }
Font* font = (Font *) asset->self; Font* font = (Font *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL) { if (cb->gpu_api_type == GPU_API_TYPE_OPENGL) {
font_invert_coordinates(font); font_invert_coordinates(font);
} }
@ -369,7 +369,7 @@ inline Asset* cmd_texture_load_sync(AppCmdBuffer* cb, int32 asset_id) {
// Setup basic texture // Setup basic texture
Texture* texture = (Texture *) asset->self; Texture* texture = (Texture *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL if (cb->gpu_api_type == GPU_API_TYPE_OPENGL
&& !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP) && !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP)
) { ) {
image_flip_vertical(cb->mem_vol, &texture->image); image_flip_vertical(cb->mem_vol, &texture->image);
@ -393,7 +393,7 @@ inline Asset* cmd_texture_load_sync(AppCmdBuffer* cb, const char* name) {
// Setup basic texture // Setup basic texture
Texture* texture = (Texture *) asset->self; Texture* texture = (Texture *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL if (cb->gpu_api_type == GPU_API_TYPE_OPENGL
&& !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP) && !(texture->image.image_settings & IMAGE_SETTING_BOTTOM_TO_TOP)
) { ) {
image_flip_vertical(cb->mem_vol, &texture->image); image_flip_vertical(cb->mem_vol, &texture->image);
@ -419,7 +419,7 @@ inline Asset* cmd_font_load_sync(AppCmdBuffer* cb, int32 asset_id) {
// Setup font // Setup font
Font* font = (Font *) asset->self; Font* font = (Font *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL) { if (cb->gpu_api_type == GPU_API_TYPE_OPENGL) {
font_invert_coordinates(font); font_invert_coordinates(font);
} }
@ -441,7 +441,7 @@ inline Asset* cmd_font_load_sync(AppCmdBuffer* cb, const char* name) {
// Setup font // Setup font
Font* font = (Font *) asset->self; Font* font = (Font *) asset->self;
if (cb->gpu_api == GPU_API_TYPE_OPENGL) { if (cb->gpu_api_type == GPU_API_TYPE_OPENGL) {
font_invert_coordinates(font); font_invert_coordinates(font);
} }
@ -483,10 +483,9 @@ UIThemeStyle* cmd_theme_load_sync(
inline inline
void cmd_layout_populate_sync( void cmd_layout_populate_sync(
AppCmdBuffer*, AppCmdBuffer*,
UILayout* layout, const UIThemeStyle* theme, UILayout* layout, const UIThemeStyle* theme
const Camera* camera
) { ) {
layout_from_theme(layout, theme, camera); layout_from_theme(layout, theme);
} }
inline inline
@ -504,9 +503,16 @@ UILayout* cmd_ui_load_sync(
return NULL; return NULL;
} }
cmd_layout_populate_sync(cb, layout, general_theme, camera); cmd_layout_populate_sync(cb, layout, general_theme);
cmd_theme_load_sync(cb, theme, theme_path); cmd_theme_load_sync(cb, theme, theme_path);
cmd_layout_populate_sync(cb, layout, theme, camera); cmd_layout_populate_sync(cb, layout, theme);
UIElement* root = layout_get_element(layout, "root");
UIWindow* default_style = (UIWindow *) layout_get_element_style(layout, root, UI_STYLE_TYPE_DEFAULT);
if (default_style) {
default_style->dimension.dimension.width = camera->viewport_width;
default_style->dimension.dimension.height = camera->viewport_height;
}
return layout; return layout;
} }

View File

@ -43,17 +43,16 @@ struct AppCmdBuffer {
Queue* assets_to_load; Queue* assets_to_load;
Queue* files_to_load; Queue* files_to_load;
AudioMixer* mixer; AudioMixer* mixer;
GpuApiType gpu_api; GpuApiType gpu_api_type;
void* gpu_api;
}; };
#if OPENGL #if OPENGL
#include "../gpuapi/opengl/AppCmdBuffer.h" #include "../gpuapi/opengl/AppCmdBuffer.h"
#elif VULKAN #elif VULKAN
inline void* cmd_shader_load(AppCmdBuffer*, Command*) { return NULL; } #include "../gpuapi/vulkan/AppCmdBuffer.h"
inline void* cmd_shader_load_sync(AppCmdBuffer*, void*, int32*) { return NULL; }
#elif DIRECTX #elif DIRECTX
inline void* cmd_shader_load(AppCmdBuffer*, Command*) { return NULL; } #include "../gpuapi/direct3d/AppCmdBuffer.h"
inline void* cmd_shader_load_sync(AppCmdBuffer*, void*, int32*) { return NULL; }
#else #else
inline void* cmd_shader_load(AppCmdBuffer*, Command*) { return NULL; } inline void* cmd_shader_load(AppCmdBuffer*, Command*) { return NULL; }
inline void* cmd_shader_load_sync(AppCmdBuffer*, void*, int32*) { return NULL; } inline void* cmd_shader_load_sync(AppCmdBuffer*, void*, int32*) { return NULL; }

View File

@ -10,195 +10,396 @@
#define TOS_COMPILER_GCC_ATOMIC_H #define TOS_COMPILER_GCC_ATOMIC_H
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "CompilerUtils.h"
#include <stdatomic.h> #include <stdatomic.h>
inline void atomic_set_relaxed(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_RELAXED); }
inline void* atomic_get_relaxed(void** target) { return __atomic_load_n(target, __ATOMIC_RELAXED); } FORCE_INLINE void* atomic_get_relaxed(void** target) { return __atomic_load_n(target, __ATOMIC_RELAXED); }
inline void atomic_set_relaxed(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile int8* value, int8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_set_relaxed(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile int16* value, int16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline int32 atomic_get_relaxed(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_RELAXED); } FORCE_INLINE int8 atomic_fetch_set_relaxed(volatile int8* value, int8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
inline int64 atomic_get_relaxed(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_RELAXED); } FORCE_INLINE int16 atomic_fetch_set_relaxed(volatile int16* value, int16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_increment_relaxed(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_decrement_relaxed(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_increment_relaxed(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE int8 atomic_get_relaxed(volatile int8* value) { return __atomic_load_n((int8 *) value, __ATOMIC_RELAXED); }
inline void atomic_decrement_relaxed(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE int16 atomic_get_relaxed(volatile int16* value) { return __atomic_load_n((int16 *) value, __ATOMIC_RELAXED); }
inline void atomic_add_relaxed(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); } FORCE_INLINE int32 atomic_get_relaxed(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_RELAXED); }
inline void atomic_sub_relaxed(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); } FORCE_INLINE int64 atomic_get_relaxed(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_RELAXED); }
inline void atomic_add_relaxed(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_increment_relaxed(volatile int8* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
inline void atomic_sub_relaxed(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_decrement_relaxed(volatile int8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
inline int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; } FORCE_INLINE void atomic_increment_relaxed(volatile int16* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
inline int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_decrement_relaxed(volatile int16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
inline int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_increment_relaxed(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
inline int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_decrement_relaxed(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
inline int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_increment_relaxed(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
inline void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_decrement_relaxed(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
inline void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_add_relaxed(volatile int8* value, int8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
inline uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_sub_relaxed(volatile int8* value, int8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
inline uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_add_relaxed(volatile int16* value, int16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
inline uint32 atomic_get_relaxed(volatile uint32* value) { return __atomic_load_n((uint32 *) value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_sub_relaxed(volatile int16* value, int16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
inline uint64 atomic_get_relaxed(volatile uint64* value) { return __atomic_load_n((uint64 *) value, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_add_relaxed(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
inline void atomic_increment_relaxed(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_sub_relaxed(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
inline void atomic_decrement_relaxed(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_add_relaxed(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
inline void atomic_increment_relaxed(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_sub_relaxed(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
inline void atomic_decrement_relaxed(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); } FORCE_INLINE f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
inline void atomic_add_relaxed(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); } FORCE_INLINE f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
inline void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); } FORCE_INLINE int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
inline uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; } FORCE_INLINE int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
inline uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE int8 atomic_fetch_add_relaxed(volatile int8* value, int8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
inline uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE int8 atomic_fetch_sub_relaxed(volatile int8* value, int8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
inline uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE int16 atomic_fetch_add_relaxed(volatile int16* value, int16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
inline uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); } FORCE_INLINE int16 atomic_fetch_sub_relaxed(volatile int16* value, int16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
inline void atomic_and_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
inline void atomic_and_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
inline void atomic_and_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
inline void atomic_and_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
inline void atomic_or_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile uint8* value, uint8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_or_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile uint16* value, uint16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_or_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
inline void atomic_or_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); } FORCE_INLINE void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELAXED); }
FORCE_INLINE uint8 atomic_fetch_set_relaxed(volatile uint8* value, uint8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
FORCE_INLINE uint16 atomic_fetch_set_relaxed(volatile uint16* value, uint16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
FORCE_INLINE uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
FORCE_INLINE uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELAXED); }
FORCE_INLINE uint8 atomic_get_relaxed(volatile uint8* value) { return __atomic_load_n(value, __ATOMIC_RELAXED); }
FORCE_INLINE uint16 atomic_get_relaxed(volatile uint16* value) { return __atomic_load_n(value, __ATOMIC_RELAXED); }
FORCE_INLINE uint32 atomic_get_relaxed(volatile uint32* value) { return __atomic_load_n(value, __ATOMIC_RELAXED); }
FORCE_INLINE uint64 atomic_get_relaxed(volatile uint64* value) { return __atomic_load_n(value, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint8* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint16* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_add_relaxed(volatile uint8* value, uint8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint8* value, uint8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_add_relaxed(volatile uint16* value, uint16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint16* value, uint16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_add_relaxed(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_add_relaxed(volatile uint64* value, uint64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELAXED); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
FORCE_INLINE uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); return *expected; }
FORCE_INLINE uint8 atomic_fetch_add_relaxed(volatile uint8* value, uint8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint8 atomic_fetch_sub_relaxed(volatile uint8* value, uint8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint16 atomic_fetch_add_relaxed(volatile uint16* value, uint16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint16 atomic_fetch_sub_relaxed(volatile uint16* value, uint16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_and_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
FORCE_INLINE void atomic_or_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELAXED); }
inline void atomic_set_acquire(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_ACQUIRE); }
inline void* atomic_get_acquire(void** target) { return __atomic_load_n(target, __ATOMIC_ACQUIRE); } FORCE_INLINE void* atomic_get_relaxed(void** target) { return __atomic_load_n(target, __ATOMIC_ACQUIRE); }
inline void atomic_set_acquire(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile int8* value, int8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_set_acquire(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile int16* value, int16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline int32 atomic_fetch_set_acquire(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline int64 atomic_fetch_set_acquire(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline int32 atomic_get_acquire(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_ACQUIRE); } FORCE_INLINE int8 atomic_fetch_set_relaxed(volatile int8* value, int8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
inline int64 atomic_get_acquire(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_ACQUIRE); } FORCE_INLINE int16 atomic_fetch_set_relaxed(volatile int16* value, int16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_increment_acquire(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_decrement_acquire(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_increment_acquire(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE int8 atomic_get_relaxed(volatile int8* value) { return __atomic_load_n((int8 *) value, __ATOMIC_ACQUIRE); }
inline void atomic_decrement_acquire(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE int16 atomic_get_relaxed(volatile int16* value) { return __atomic_load_n((int16 *) value, __ATOMIC_ACQUIRE); }
inline void atomic_add_acquire(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); } FORCE_INLINE int32 atomic_get_relaxed(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_ACQUIRE); }
inline void atomic_sub_acquire(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); } FORCE_INLINE int64 atomic_get_relaxed(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_ACQUIRE); }
inline void atomic_add_acquire(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_increment_relaxed(volatile int8* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline void atomic_sub_acquire(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline int32 atomic_compare_exchange_weak_acquire(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; } FORCE_INLINE void atomic_increment_relaxed(volatile int16* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline int32 atomic_fetch_add_acquire(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline int32 atomic_fetch_sub_acquire(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_increment_relaxed(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline int64 atomic_fetch_add_acquire(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline int64 atomic_fetch_sub_acquire(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_increment_relaxed(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline void atomic_set_acquire(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
inline void atomic_set_acquire(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_add_relaxed(volatile int8* value, int8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
inline uint32 atomic_fetch_set_acquire(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_sub_relaxed(volatile int8* value, int8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
inline uint64 atomic_fetch_set_acquire(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_add_relaxed(volatile int16* value, int16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
inline uint32 atomic_get_acquire(volatile uint32* value) { return __atomic_load_n((uint32 *) value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_sub_relaxed(volatile int16* value, int16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
inline uint64 atomic_get_acquire(volatile uint64* value) { return __atomic_load_n((uint64 *) value, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_add_relaxed(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
inline void atomic_increment_acquire(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_sub_relaxed(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
inline void atomic_decrement_acquire(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_add_relaxed(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
inline void atomic_increment_acquire(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_sub_relaxed(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
inline void atomic_decrement_acquire(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); } FORCE_INLINE f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
inline void atomic_add_acquire(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); } FORCE_INLINE f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
inline void atomic_sub_acquire(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); } FORCE_INLINE int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
inline uint32 atomic_compare_exchange_weak_acquire(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; } FORCE_INLINE int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
inline uint32 atomic_fetch_add_acquire(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE int8 atomic_fetch_add_relaxed(volatile int8* value, int8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline uint32 atomic_fetch_sub_acquire(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE int8 atomic_fetch_sub_relaxed(volatile int8* value, int8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline uint64 atomic_fetch_add_acquire(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE int16 atomic_fetch_add_relaxed(volatile int16* value, int16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline uint64 atomic_fetch_sub_acquire(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); } FORCE_INLINE int16 atomic_fetch_sub_relaxed(volatile int16* value, int16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline void atomic_and_acquire(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline void atomic_and_acquire(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline void atomic_and_acquire(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline void atomic_and_acquire(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
inline void atomic_or_acquire(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile uint8* value, uint8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_or_acquire(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile uint16* value, uint16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_or_acquire(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
inline void atomic_or_acquire(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); } FORCE_INLINE void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint8 atomic_fetch_set_relaxed(volatile uint8* value, uint8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint16 atomic_fetch_set_relaxed(volatile uint16* value, uint16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint8 atomic_get_relaxed(volatile uint8* value) { return __atomic_load_n(value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint16 atomic_get_relaxed(volatile uint16* value) { return __atomic_load_n(value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint32 atomic_get_relaxed(volatile uint32* value) { return __atomic_load_n(value, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint64 atomic_get_relaxed(volatile uint64* value) { return __atomic_load_n(value, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint8* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint16* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint8* value, uint8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint8* value, uint8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint16* value, uint16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint16* value, uint16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint64* value, uint64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
FORCE_INLINE uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); return *expected; }
FORCE_INLINE uint8 atomic_fetch_add_relaxed(volatile uint8* value, uint8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint8 atomic_fetch_sub_relaxed(volatile uint8* value, uint8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint16 atomic_fetch_add_relaxed(volatile uint16* value, uint16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint16 atomic_fetch_sub_relaxed(volatile uint16* value, uint16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_and_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
FORCE_INLINE void atomic_or_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_ACQUIRE); }
inline void atomic_set_release(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_RELEASE); }
inline void* atomic_get_release(void** target) { return __atomic_load_n(target, __ATOMIC_RELEASE); } FORCE_INLINE void* atomic_get_relaxed(void** target) { return __atomic_load_n(target, __ATOMIC_RELEASE); }
inline void atomic_set_release(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile int8* value, int8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_set_release(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile int16* value, int16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline int32 atomic_fetch_set_release(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline int64 atomic_fetch_set_release(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline int32 atomic_get_release(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_RELEASE); } FORCE_INLINE int8 atomic_fetch_set_relaxed(volatile int8* value, int8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
inline int64 atomic_get_release(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_RELEASE); } FORCE_INLINE int16 atomic_fetch_set_relaxed(volatile int16* value, int16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_increment_release(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_decrement_release(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_increment_release(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE int8 atomic_get_relaxed(volatile int8* value) { return __atomic_load_n((int8 *) value, __ATOMIC_RELEASE); }
inline void atomic_decrement_release(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE int16 atomic_get_relaxed(volatile int16* value) { return __atomic_load_n((int16 *) value, __ATOMIC_RELEASE); }
inline void atomic_add_release(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); } FORCE_INLINE int32 atomic_get_relaxed(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_RELEASE); }
inline void atomic_sub_release(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); } FORCE_INLINE int64 atomic_get_relaxed(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_RELEASE); }
inline void atomic_add_release(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_increment_relaxed(volatile int8* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
inline void atomic_sub_release(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
inline int32 atomic_compare_exchange_weak_release(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; } FORCE_INLINE void atomic_increment_relaxed(volatile int16* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
inline int32 atomic_fetch_add_release(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
inline int32 atomic_fetch_sub_release(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_increment_relaxed(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
inline int64 atomic_fetch_add_release(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
inline int64 atomic_fetch_sub_release(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_increment_relaxed(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
inline void atomic_set_release(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_decrement_relaxed(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
inline void atomic_set_release(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_add_relaxed(volatile int8* value, int8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
inline uint32 atomic_fetch_set_release(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_sub_relaxed(volatile int8* value, int8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
inline uint64 atomic_fetch_set_release(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_add_relaxed(volatile int16* value, int16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
inline uint32 atomic_get_release(volatile uint32* value) { return __atomic_load_n((uint32 *) value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_sub_relaxed(volatile int16* value, int16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
inline uint64 atomic_get_release(volatile uint64* value) { return __atomic_load_n((uint64 *) value, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_add_relaxed(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
inline void atomic_increment_release(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_sub_relaxed(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
inline void atomic_decrement_release(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_add_relaxed(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
inline void atomic_increment_release(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_sub_relaxed(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
inline void atomic_decrement_release(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); } FORCE_INLINE f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
inline void atomic_add_release(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); } FORCE_INLINE f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
inline void atomic_sub_release(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); } FORCE_INLINE int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
inline uint32 atomic_compare_exchange_weak_release(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; } FORCE_INLINE int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
inline uint32 atomic_fetch_add_release(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE int8 atomic_fetch_add_relaxed(volatile int8* value, int8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
inline uint32 atomic_fetch_sub_release(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE int8 atomic_fetch_sub_relaxed(volatile int8* value, int8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
inline uint64 atomic_fetch_add_release(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE int16 atomic_fetch_add_relaxed(volatile int16* value, int16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
inline uint64 atomic_fetch_sub_release(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); } FORCE_INLINE int16 atomic_fetch_sub_relaxed(volatile int16* value, int16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
inline void atomic_and_release(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
inline void atomic_and_release(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
inline void atomic_and_release(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
inline void atomic_and_release(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
inline void atomic_or_release(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile uint8* value, uint8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_or_release(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile uint16* value, uint16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_or_release(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
inline void atomic_or_release(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); } FORCE_INLINE void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_RELEASE); }
FORCE_INLINE uint8 atomic_fetch_set_relaxed(volatile uint8* value, uint8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
FORCE_INLINE uint16 atomic_fetch_set_relaxed(volatile uint16* value, uint16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
FORCE_INLINE uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
FORCE_INLINE uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_RELEASE); }
FORCE_INLINE uint8 atomic_get_relaxed(volatile uint8* value) { return __atomic_load_n(value, __ATOMIC_RELEASE); }
FORCE_INLINE uint16 atomic_get_relaxed(volatile uint16* value) { return __atomic_load_n(value, __ATOMIC_RELEASE); }
FORCE_INLINE uint32 atomic_get_relaxed(volatile uint32* value) { return __atomic_load_n(value, __ATOMIC_RELEASE); }
FORCE_INLINE uint64 atomic_get_relaxed(volatile uint64* value) { return __atomic_load_n(value, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint8* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint16* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint8* value, uint8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint8* value, uint8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint16* value, uint16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint16* value, uint16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_add_relaxed(volatile uint64* value, uint64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_RELEASE); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
FORCE_INLINE uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_RELEASE, __ATOMIC_RELEASE); return *expected; }
FORCE_INLINE uint8 atomic_fetch_add_relaxed(volatile uint8* value, uint8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint8 atomic_fetch_sub_relaxed(volatile uint8* value, uint8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint16 atomic_fetch_add_relaxed(volatile uint16* value, uint16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint16 atomic_fetch_sub_relaxed(volatile uint16* value, uint16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_and_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
FORCE_INLINE void atomic_or_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_RELEASE); }
inline void atomic_set_acquire_release(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(void** target, void* value) { __atomic_store_n(target, value, __ATOMIC_SEQ_CST); }
inline void* atomic_get_acquire_release(void** target) { return __atomic_load_n(target, __ATOMIC_SEQ_CST); } FORCE_INLINE void* atomic_get_relaxed(void** target) { return __atomic_load_n(target, __ATOMIC_SEQ_CST); }
inline void atomic_set_acquire_release(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile int8* value, int8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_set_acquire_release(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile int16* value, int16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline int32 atomic_fetch_set_acquire_release(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile int32* value, int32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline int64 atomic_fetch_set_acquire_release(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile int64* value, int64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline int32 atomic_get_acquire_release(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_SEQ_CST); } FORCE_INLINE int8 atomic_fetch_set_relaxed(volatile int8* value, int8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
inline int64 atomic_get_acquire_release(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_SEQ_CST); } FORCE_INLINE int16 atomic_fetch_set_relaxed(volatile int16* value, int16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_increment_acquire_release(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_decrement_acquire_release(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_increment_acquire_release(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE int8 atomic_get_relaxed(volatile int8* value) { return __atomic_load_n((int8 *) value, __ATOMIC_SEQ_CST); }
inline void atomic_decrement_acquire_release(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE int16 atomic_get_relaxed(volatile int16* value) { return __atomic_load_n((int16 *) value, __ATOMIC_SEQ_CST); }
inline void atomic_add_acquire_release(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); } FORCE_INLINE int32 atomic_get_relaxed(volatile int32* value) { return __atomic_load_n((int32 *) value, __ATOMIC_SEQ_CST); }
inline void atomic_sub_acquire_release(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); } FORCE_INLINE int64 atomic_get_relaxed(volatile int64* value) { return __atomic_load_n((int64 *) value, __ATOMIC_SEQ_CST); }
inline void atomic_add_acquire_release(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_increment_relaxed(volatile int8* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline void atomic_sub_acquire_release(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_decrement_relaxed(volatile int8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline int32 atomic_compare_exchange_weak_acquire_release(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; } FORCE_INLINE void atomic_increment_relaxed(volatile int16* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline int32 atomic_fetch_add_acquire_release(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_decrement_relaxed(volatile int16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline int32 atomic_fetch_sub_acquire_release(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_increment_relaxed(volatile int32* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline int64 atomic_fetch_add_acquire_release(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_decrement_relaxed(volatile int32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline int64 atomic_fetch_sub_acquire_release(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_increment_relaxed(volatile int64* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline void atomic_set_acquire_release(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_decrement_relaxed(volatile int64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
inline void atomic_set_acquire_release(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_add_relaxed(volatile int8* value, int8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
inline uint32 atomic_fetch_set_acquire_release(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_sub_relaxed(volatile int8* value, int8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
inline uint64 atomic_fetch_set_acquire_release(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_add_relaxed(volatile int16* value, int16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
inline uint32 atomic_get_acquire_release(volatile uint32* value) { return __atomic_load_n((uint32 *) value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_sub_relaxed(volatile int16* value, int16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
inline uint64 atomic_get_acquire_release(volatile uint64* value) { return __atomic_load_n((uint64 *) value, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_add_relaxed(volatile int32* value, int32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
inline void atomic_increment_acquire_release(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_sub_relaxed(volatile int32* value, int32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
inline void atomic_decrement_acquire_release(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_add_relaxed(volatile int64* value, int64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
inline void atomic_increment_acquire_release(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_sub_relaxed(volatile int64* value, int64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
inline void atomic_decrement_acquire_release(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); } FORCE_INLINE f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
inline void atomic_add_acquire_release(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); } FORCE_INLINE f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
inline void atomic_sub_acquire_release(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); } FORCE_INLINE int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
inline uint32 atomic_compare_exchange_weak_acquire_release(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; } FORCE_INLINE int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
inline uint32 atomic_fetch_add_acquire_release(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE int8 atomic_fetch_add_relaxed(volatile int8* value, int8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline uint32 atomic_fetch_sub_acquire_release(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE int8 atomic_fetch_sub_relaxed(volatile int8* value, int8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline uint64 atomic_fetch_add_acquire_release(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE int16 atomic_fetch_add_relaxed(volatile int16* value, int16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline uint64 atomic_fetch_sub_acquire_release(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); } FORCE_INLINE int16 atomic_fetch_sub_relaxed(volatile int16* value, int16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline void atomic_and_acquire_release(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline void atomic_and_acquire_release(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline void atomic_and_acquire_release(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline void atomic_and_acquire_release(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
inline void atomic_or_acquire_release(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile uint8* value, uint8 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_or_acquire_release(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile uint16* value, uint16 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_or_acquire_release(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
inline void atomic_or_acquire_release(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); } FORCE_INLINE void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { __atomic_store_n(value, new_value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint8 atomic_fetch_set_relaxed(volatile uint8* value, uint8 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint16 atomic_fetch_set_relaxed(volatile uint16* value, uint16 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return __atomic_exchange_n(value, new_value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint8 atomic_get_relaxed(volatile uint8* value) { return __atomic_load_n(value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint16 atomic_get_relaxed(volatile uint16* value) { return __atomic_load_n(value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint32 atomic_get_relaxed(volatile uint32* value) { return __atomic_load_n(value, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint64 atomic_get_relaxed(volatile uint64* value) { return __atomic_load_n(value, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint8* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint8* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint16* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint16* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint32* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint32* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint64* value) { __atomic_add_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint64* value) { __atomic_sub_fetch(value, 1, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_add_relaxed(volatile uint8* value, uint8 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint8* value, uint8 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_add_relaxed(volatile uint16* value, uint16 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint16* value, uint16 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_add_relaxed(volatile uint32* value, uint32 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_add_relaxed(volatile uint64* value, uint64 increment) { __atomic_add_fetch(value, increment, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { __atomic_sub_fetch(value, decrement, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
FORCE_INLINE uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { __atomic_compare_exchange_n(value, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return *expected; }
FORCE_INLINE uint8 atomic_fetch_add_relaxed(volatile uint8* value, uint8 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint8 atomic_fetch_sub_relaxed(volatile uint8* value, uint8 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint16 atomic_fetch_add_relaxed(volatile uint16* value, uint16 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint16 atomic_fetch_sub_relaxed(volatile uint16* value, uint16 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return __atomic_add_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return __atomic_sub_fetch(value, operand, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_and_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_and(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile uint8* value, uint8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile int8* value, int8 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile uint16* value, uint16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile int16* value, int16 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile uint32* value, uint32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile int32* value, int32 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile uint64* value, uint64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
FORCE_INLINE void atomic_or_relaxed(volatile int64* value, int64 mask) { __atomic_fetch_or(value, mask, __ATOMIC_SEQ_CST); }
// Check out the intrinsic functions fence_memory and fence_write // Check out the intrinsic functions fence_memory and fence_write
// These are much faster and could accomplish what you are doing // These are much faster and could accomplish what you are doing

View File

@ -81,4 +81,22 @@ int32 compiler_find_first_bit_l2r(uint32 mask) {
#endif #endif
} }
/*
#include <cpuid.h>
static inline
void cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuid(function_id, cpuInfo[0], cpuInfo[1], cpuInfo[2], cpuInfo[3]);
}
*/
inline
void compiler_cpuid(int32 cpuInfo[4], int32 function_id) {
asm volatile(
"cpuid"
: "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
: "a" (function_id)
);
}
#endif #endif

View File

@ -11,6 +11,7 @@
#include "../../utils/TestUtils.h" #include "../../utils/TestUtils.h"
#include <basetsd.h> #include <basetsd.h>
#include <intrin.h>
#define PACKED_STRUCT __pragma(pack(push, 1)) #define PACKED_STRUCT __pragma(pack(push, 1))
#define UNPACKED_STRUCT __pragma(pack(pop)) #define UNPACKED_STRUCT __pragma(pack(pop))
@ -75,4 +76,9 @@ int32 compiler_find_first_bit_l2r(uint32 mask) {
return _BitScanReverse(&index, mask) ? index : -1; return _BitScanReverse(&index, mask) ? index : -1;
} }
inline
void compiler_cpuid(int32 cpuInfo[4], int32 function_id) {
__cpuidex(cpuInfo, function_id, 0);
}
#endif #endif

View File

@ -0,0 +1,71 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_GPUAPI_DIRECTX_APP_CMD_BUFFER_H
#define TOS_GPUAPI_DIRECTX_APP_CMD_BUFFER_H
#include "../../stdlib/Types.h"
#include "Shader.h"
#include "ShaderUtils.h"
#include "../ShaderType.h"
#include "../../asset/Asset.h"
#include "../../command/AppCmdBuffer.h"
#include "GpuApiContainer.h"
#include <windows.h>
#include <d3d12.h>
#include <dxgi1_6.h>
#include <wrl.h>
void* cmd_shader_load(AppCmdBuffer*, Command*) {
return NULL;
}
void* cmd_shader_load_sync(AppCmdBuffer* cb, Shader* shader, int32* shader_ids) {
char asset_id[9];
GpuApiContainer* gpu_api = (GpuApiContainer *) cb->gpu_api;
Microsoft::WRL::ComPtr<ID3DBlob> shader_assets[SHADER_TYPE_SIZE];
for (int32 i = 0; i < SHADER_TYPE_SIZE; ++i) {
if (!shader_ids[i]) {
continue;
} else if (shader_ids[i] < 0) {
break;
}
// Load sub asset
int_to_hex(shader_ids[i], asset_id);
Asset* shader_asset = thrd_ams_get_asset_wait(cb->ams, asset_id);
if (!shader_asset) {
int32 archive_id = (shader_ids[i] >> 24) & 0xFF;
shader_asset = asset_archive_asset_load(&cb->asset_archives[archive_id], shader_ids[i], cb->ams, cb->mem_vol);
}
// Make sub shader
shader_assets[i] = shader_make(
shader_type_index((ShaderType) (i + 1)),
(char *) shader_asset->self,
shader_asset->ram_size
);
shader_asset->state |= ASSET_STATE_RAM_GC;
shader_asset->state |= ASSET_STATE_VRAM_GC;
}
// Make shader/program
shader->id = program_make(
gpu_api->device.Get(), gpu_api->pipeline_state, gpu_api->root_signature.Get(),
shader_assets[0].Get(), shader_assets[1].Get(), shader_assets[2].Get()
);
return NULL;
}
#endif

View File

@ -11,290 +11,159 @@
#include <windows.h> #include <windows.h>
#include <wrl.h> #include <wrl.h>
#include <dxgi1_6.h> #include <dxgi1_6.h>
#include "../../../GameEngine/log/Log.h"
#include "../../../EngineDependencies/directx/d3d12.h" #include "../../../EngineDependencies/directx/d3d12.h"
#include "../../../EngineDependencies/directx/d3dx12.h" #include "../../../EngineDependencies/directx/d3dx12.h"
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#define FRAME_COUNT 2 // A more (compile-time) efficient version of the windows macro IID_PPV_ARGS
#define IID_PPVOID(pointer) __uuidof(**(&pointer)), reinterpret_cast<void**>(&pointer)
struct Window { bool is_directx_supported(D3D_FEATURE_LEVEL version)
bool is_fullscreen;
int32 width;
int32 height;
char name[32];
int32 x;
int32 y;
HWND hwnd;
// @todo move this out of here to a separate gpuapi struct (same with opengl)
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
Microsoft::WRL::ComPtr<ID3D12Device> device;
Microsoft::WRL::ComPtr<ID3D12Resource> m_renderTargets[FRAME_COUNT];
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> m_commandAllocator;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> m_commandQueue;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
Microsoft::WRL::ComPtr<ID3D12PipelineState> m_pipelineState;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> m_commandList;
Microsoft::WRL::ComPtr<ID3D12Fence> m_fence;
UINT m_rtvDescriptorSize;
UINT m_frameIndex;
HANDLE m_fenceEvent;
UINT64 m_fenceValue;
};
void window_create(Window* window, void* proc)
{ {
WNDPROC wndproc = (WNDPROC) proc; IDXGIFactory6* factory = NULL;
WNDCLASSEX wc = {}; if (FAILED(CreateDXGIFactory1(IID_PPVOID(factory)))) {
HINSTANCE hinstance = GetModuleHandle(0);
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_OWNDC;
wc.lpfnWndProc = wndproc;
wc.hInstance = hinstance;
wc.lpszClassName = (LPCSTR) window->name;
RegisterClassEx(&wc);
if (window->is_fullscreen) {
window->width = GetSystemMetrics(SM_CXSCREEN);
window->height = GetSystemMetrics(SM_CYSCREEN);
DEVMODE screen_settings;
memset(&screen_settings, 0, sizeof(screen_settings));
screen_settings.dmSize = sizeof(screen_settings);
screen_settings.dmPelsWidth = (unsigned long) window->width;
screen_settings.dmPelsHeight = (unsigned long) window->height;
screen_settings.dmBitsPerPel = 32;
screen_settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&screen_settings, CDS_FULLSCREEN);
window->x = 0;
window->y = 0;
}
window->hwnd = CreateWindowEx((DWORD) NULL,
wc.lpszClassName, NULL,
WS_OVERLAPPEDWINDOW,
window->x, window->y,
window->width,
window->height,
NULL, NULL, hinstance, window
);
//SetWindowLongA(window->hwnd, GWL_STYLE, 0);
}
void window_open(const Window* window)
{
ShowWindow(window->hwnd, SW_SHOW);
SetForegroundWindow(window->hwnd);
SetFocus(window->hwnd);
ShowCursor(false);
UpdateWindow(window->hwnd);
}
void window_close(Window* window)
{
CloseWindow(window->hwnd);
}
bool is_directx_12_supported()
{
Microsoft::WRL::ComPtr<IDXGIFactory6> factory;
HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
if (FAILED(hr)) {
return false; return false;
} }
Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter; bool is_dx12_supported = false;
for (UINT adapterIndex = 0;
DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(adapterIndex, &adapter);
++adapterIndex)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
// Skip software adapters IDXGIAdapter1* adapter = NULL;
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { for (uint32 i = 0; DXGI_ERROR_NOT_FOUND != factory->EnumAdapters1(i, &adapter); ++i) {
DXGI_ADAPTER_DESC1 desc;
if (FAILED(adapter->GetDesc1(&desc))) {
adapter->Release();
continue; continue;
} }
try { // Skip software adapters
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) { if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
return true; adapter->Release();
} continue;
} catch (...) {
return false;
} }
// Check for DirectX 12 support
if (SUCCEEDED(D3D12CreateDevice(adapter, version, _uuidof(ID3D12Device), NULL))) {
is_dx12_supported = true;
adapter->Release();
break;
}
adapter->Release();
} }
return false; factory->Release();
return is_dx12_supported;
} }
void find_hardware_adapter( int32 max_directx_version()
IDXGIFactory1* factory, {
IDXGIAdapter1** adapter1, if (is_directx_supported(D3D_FEATURE_LEVEL_12_2)) {
bool use_high_performance_adapter = true return 122;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_12_1)) {
return 121;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_12_0)) {
return 120;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_11_1)) {
return 111;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_11_0)) {
return 110;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_10_1)) {
return 101;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_10_0)) {
return 100;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_9_3)) {
return 93;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_9_2)) {
return 92;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_9_1)) {
return 91;
} else if (is_directx_supported(D3D_FEATURE_LEVEL_1_0_CORE)) {
return 90;
}
return 0;
}
// Returns frame index
int32 wait_for_previous_frame(
ID3D12Fence* fence, HANDLE fence_event, UINT64* fence_value,
ID3D12CommandQueue* command_queue, IDXGISwapChain3* swapchain
)
{
// WAITING FOR THE FRAME TO COMPLETE BEFORE CONTINUING IS NOT BEST PRACTICE.
// This is code implemented as such for simplicity. The D3D12HelloFrameBuffering
// sample illustrates how to use fences for efficient resource usage and to
// maximize GPU utilization.
UINT64 fence_value_temp = *fence_value;
// Signal and increment the fence value.
if(FAILED(command_queue->Signal(fence, fence_value_temp))) {
LOG(true, "DirectX12 Signal");
ASSERT_SIMPLE(false);
}
++(*fence_value);
// Wait until the previous frame is finished.
if (fence->GetCompletedValue() < fence_value_temp) {
if (FAILED(fence->SetEventOnCompletion(fence_value_temp, fence_event))) {
LOG(true, "DirectX12 SetEventOnCompletion");
ASSERT_SIMPLE(false);
}
WaitForSingleObject(fence_event, INFINITE);
}
return swapchain->GetCurrentBackBufferIndex();
}
static
void directx_debug_callback(
D3D12_MESSAGE_CATEGORY category,
D3D12_MESSAGE_SEVERITY severity,
D3D12_MESSAGE_ID id,
LPCSTR description,
void* context
) { ) {
*adapter1 = nullptr; // @todo handle severity
(void) category;
(void) severity;
(void) id;
(void*) context;
/*
if ((severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
|| (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
) {
Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter;
Microsoft::WRL::ComPtr<IDXGIFactory6> factory6;
if (SUCCEEDED(factory->QueryInterface(IID_PPV_ARGS(&factory6)))) {
for (
UINT adapterIndex = 0;
SUCCEEDED(factory6->EnumAdapterByGpuPreference(
adapterIndex,
use_high_performance_adapter == true ? DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE : DXGI_GPU_PREFERENCE_UNSPECIFIED,
IID_PPV_ARGS(&adapter)));
++adapterIndex)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
// Don't select the Basic Render Driver adapter.
continue;
}
// Check to see whether the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) {
break;
}
}
} }
*/
if(adapter.Get() == nullptr) { LOG(true, description);
for (UINT adapterIndex = 0; SUCCEEDED(factory->EnumAdapters1(adapterIndex, &adapter)); ++adapterIndex) { ASSERT_SIMPLE(false);
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
// Don't select the Basic Render Driver adapter.
continue;
}
// Check to see whether the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) {
break;
}
}
}
*adapter1 = adapter.Detach();
} }
void load_pipeline(Window* window) void gpuapi_debug_messenger_setup(Microsoft::WRL::ComPtr<ID3D12Device>& device)
{ {
uint32 factory_flags = 0; Microsoft::WRL::ComPtr<ID3D12InfoQueue1> info_queue;
if (FAILED(device.As(&info_queue))) {
return;
}
Microsoft::WRL::ComPtr<IDXGIFactory4> factory; // Register the custom debug callback
CreateDXGIFactory2(factory_flags, IID_PPV_ARGS(&factory)); info_queue->RegisterMessageCallback(
directx_debug_callback,
Microsoft::WRL::ComPtr<IDXGIAdapter1> hardware_adapter; D3D12_MESSAGE_CALLBACK_FLAG_NONE,
find_hardware_adapter(factory.Get(), &hardware_adapter); NULL, // Context (can be used to pass additional data)
NULL // Callback cookie (unused)
D3D12CreateDevice(
hardware_adapter.Get(),
D3D_FEATURE_LEVEL_11_0,
IID_PPV_ARGS(&window->device)
); );
// Describe and create the command queue. // Set the message count limit to unlimited
D3D12_COMMAND_QUEUE_DESC queueDesc = {}; info_queue->SetMessageCountLimit(0);
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
window->device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&window->m_commandQueue));
// Describe and create the swap chain.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.BufferCount = FRAME_COUNT;
swapChainDesc.Width = window->width;
swapChainDesc.Height = window->height;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.SampleDesc.Count = 1;
Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
factory->CreateSwapChainForHwnd(
window->m_commandQueue.Get(), // Swap chain needs the queue so that it can force a flush on it.
window->hwnd,
&swapChainDesc,
nullptr,
nullptr,
&swapChain
);
// This sample does not support fullscreen transitions.
factory->MakeWindowAssociation(window->hwnd, DXGI_MWA_NO_ALT_ENTER);
swapChain.As(&window->m_swapChain);
window->m_frameIndex = window->m_swapChain->GetCurrentBackBufferIndex();
// Create descriptor heaps.
{
// Describe and create a render target view (RTV) descriptor heap.
D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
rtvHeapDesc.NumDescriptors = FRAME_COUNT;
rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
window->device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&window->m_rtvHeap));
window->m_rtvDescriptorSize = window->device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
// Create frame resources.
{
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(window->m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
// Create a RTV for each frame.
for (UINT n = 0; n < FRAME_COUNT; n++)
{
window->m_swapChain->GetBuffer(n, IID_PPV_ARGS(&window->m_renderTargets[n]));
window->device->CreateRenderTargetView(window->m_renderTargets[n].Get(), nullptr, rtvHandle);
rtvHandle.Offset(1, window->m_rtvDescriptorSize);
}
}
window->device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&window->m_commandAllocator));
}
void load_assets(Window* window)
{
// Create the command list.
window->device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, window->m_commandAllocator.Get(), nullptr, IID_PPV_ARGS(&window->m_commandList));
// Command lists are created in the recording state, but there is nothing
// to record yet. The main loop expects it to be closed, so close it now.
window->m_commandList->Close();
// Create synchronization objects.
{
window->device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&window->m_fence));
window->m_fenceValue = 1;
// Create an event handle to use for frame synchronization.
window->m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (window->m_fenceEvent == nullptr) {
HRESULT_FROM_WIN32(GetLastError());
}
}
} }
#endif #endif

View File

@ -9,6 +9,9 @@
#ifndef TOS_GPUAPI_DIRECTX_GPU_API_CONTAINER_H #ifndef TOS_GPUAPI_DIRECTX_GPU_API_CONTAINER_H
#define TOS_GPUAPI_DIRECTX_GPU_API_CONTAINER_H #define TOS_GPUAPI_DIRECTX_GPU_API_CONTAINER_H
#include "../../stdlib/Types.h"
#include "../../../EngineDependencies/directx/d3d12.h"
#include "../../../EngineDependencies/directx/d3dx12.h"
#include <windows.h> #include <windows.h>
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_6.h> #include <dxgi1_6.h>
@ -16,18 +19,32 @@
#include <wrl.h> #include <wrl.h>
struct GpuApiContainer { struct GpuApiContainer {
Microsoft::WRL::ComPtr<ID3D12Device> device; uint32 frames_in_flight;
Microsoft::WRL::ComPtr<IDXGISwapChain3> swapChain; uint32 framebuffer_idx;
Microsoft::WRL::ComPtr<ID3D12CommandQueue> commandQueue; Microsoft::WRL::ComPtr<ID3D12Device> device;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> rtvHeap; Microsoft::WRL::ComPtr<IDXGISwapChain4> swapchain;
Microsoft::WRL::ComPtr<ID3D12Resource> renderTargets[2];
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> commandAllocator; Microsoft::WRL::ComPtr<ID3D12CommandQueue> command_queue;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> commandList; Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> rtv_heap;
Microsoft::WRL::ComPtr<ID3D12PipelineState> pipelineState; uint32 rtv_info_size;
Microsoft::WRL::ComPtr<ID3D12RootSignature> rootSignature; // @todo should be dynamic size based on frames_in_flight, no?
Microsoft::WRL::ComPtr<ID3D12Resource> render_targets[2];
Microsoft::WRL::ComPtr<ID3D12CommandAllocator> command_allocator;
Microsoft::WRL::ComPtr<ID3D12GraphicsCommandList> command_list;
Microsoft::WRL::ComPtr<ID3D12PipelineState> pipeline_state;
Microsoft::WRL::ComPtr<ID3D12RootSignature> root_signature;
Microsoft::WRL::ComPtr<ID3D12Fence> fence; Microsoft::WRL::ComPtr<ID3D12Fence> fence;
UINT64 fenceValue = 0; UINT64 fence_value = 0;
HANDLE fence_event;
// ????
CD3DX12_VIEWPORT m_viewport;
CD3DX12_RECT m_scissorRect;
// @todo This definately doesn't belong here
Microsoft::WRL::ComPtr<ID3D12Resource> m_vertexBuffer;
D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView;
}; };
#endif #endif

View File

@ -10,9 +10,11 @@
#define TOS_GPUAPI_DIRECT3D_SHADER_H #define TOS_GPUAPI_DIRECT3D_SHADER_H
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include <d3d12.h>
#include <wrl.h>
struct Shader { struct Shader {
uint32 id; Microsoft::WRL::ComPtr<ID3D12PipelineState> id;
uint32 locations[7]; uint32 locations[7];
byte data[16]; byte data[16];
}; };

View File

@ -9,43 +9,87 @@
#ifndef TOS_GPUAPI_DIRECTX_SHADER_UTILS_H #ifndef TOS_GPUAPI_DIRECTX_SHADER_UTILS_H
#define TOS_GPUAPI_DIRECTX_SHADER_UTILS_H #define TOS_GPUAPI_DIRECTX_SHADER_UTILS_H
#include <windows.h>
#include <d3d12.h> #include <d3d12.h>
#include <dxgi1_6.h>
#include <wrl.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include "../../../EngineDependencies/directx/d3d12.h"
#include "../../../EngineDependencies/directx/d3dx12.h"
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../memory/RingMemory.h" #include "../../memory/RingMemory.h"
#include "../../log/Log.h" #include "../../log/Log.h"
#include "../ShaderType.h"
D3D12_SHADER_BYTECODE shader_make(ID3D12Device* device, const char* source, int32 source_size, RingMemory* ring) #pragma comment(lib, "d3dcompiler.lib")
const char* shader_type_index(ShaderType type)
{ {
// Create the shader object (bytecode) switch (type) {
D3D12_SHADER_BYTECODE shaderBytecodeDesc = {}; case SHADER_TYPE_VERTEX:
shaderBytecodeDesc.pShaderBytecode = source; return "vs_5_0";
shaderBytecodeDesc.BytecodeLength = source_size; case SHADER_TYPE_FRAGMENT:
return "ps_5_0";
default:
UNREACHABLE();
}
}
return shaderBytecodeDesc; Microsoft::WRL::ComPtr<ID3DBlob> shader_make(const char* type, const char* source, int32 source_size)
{
#if DEBUG || INTERNAL
uint32 compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
uint32 compileFlags = 0;
#endif
Microsoft::WRL::ComPtr<ID3DBlob> blob;
Microsoft::WRL::ComPtr<ID3DBlob> errMsgs;
if (FAILED(D3DCompile2(source, source_size, NULL, NULL, NULL, "main", type, compileFlags, 0, 0, NULL, 0, blob.GetAddressOf(), errMsgs.GetAddressOf()))) {
LOG(true, "DirectX12 D3DCompile2");
ASSERT_SIMPLE(false);
}
return blob;
} }
ID3D12PipelineState* program_make( ID3D12PipelineState* program_make(
ID3D12Device* device, ID3D12Device* device,
D3D12_SHADER_BYTECODE vertex_shader, Microsoft::WRL::ComPtr<ID3D12PipelineState>& pipeline_state,
D3D12_SHADER_BYTECODE fragment_shader, ID3D12RootSignature* root_signature,
D3D12_SHADER_BYTECODE geometry_shader ID3DBlob* vertex_shader,
ID3DBlob* fragment_shader,
ID3DBlob*
) { ) {
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; // @todo We need to find a way to do this somewhere else:
psoDesc.VS = vertex_shader; D3D12_INPUT_ELEMENT_DESC input_element_info[] =
psoDesc.PS = fragment_shader; {
psoDesc.GS = geometry_shader; { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
ID3D12PipelineState* pipelineState = NULL; D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_state_info = {};
HRESULT hr = device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState)); pipeline_state_info.InputLayout = { input_element_info, _countof(input_element_info) };
pipeline_state_info.pRootSignature = root_signature;
pipeline_state_info.VS = CD3DX12_SHADER_BYTECODE(vertex_shader);
pipeline_state_info.PS = CD3DX12_SHADER_BYTECODE(fragment_shader);
pipeline_state_info.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
pipeline_state_info.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
pipeline_state_info.DepthStencilState.DepthEnable = FALSE;
pipeline_state_info.DepthStencilState.StencilEnable = FALSE;
pipeline_state_info.SampleMask = UINT_MAX;
pipeline_state_info.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pipeline_state_info.NumRenderTargets = 1;
pipeline_state_info.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
pipeline_state_info.SampleDesc.Count = 1;
if (FAILED(hr)) { if (FAILED(device->CreateGraphicsPipelineState(&pipeline_state_info, IID_PPV_ARGS(&pipeline_state)))) {
LOG(true, "Failed to create program"); LOG(true, "DirectX12 CreateGraphicsPipelineState");
return NULL; ASSERT_SIMPLE(false);
} }
return pipelineState; return pipeline_state.Get();
} }
inline inline

View File

@ -15,6 +15,7 @@
#include "ShaderUtils.h" #include "ShaderUtils.h"
#include "../ShaderType.h" #include "../ShaderType.h"
#include "../../asset/Asset.h" #include "../../asset/Asset.h"
#include "../../command/AppCmdBuffer.h"
void* cmd_shader_load(AppCmdBuffer*, Command*) { void* cmd_shader_load(AppCmdBuffer*, Command*) {
return NULL; return NULL;

View File

@ -64,7 +64,7 @@ void opengl_debug_callback(GLenum, GLenum, GLuint, GLenum severity, GLsizei, con
} }
inline inline
void change_viewport(int16 width, int16 height, int32 offset_x = 0, int32 offset_y = 0) void change_viewport(int32 width, int32 height, int32 offset_x = 0, int32 offset_y = 0)
{ {
glViewport(offset_x, offset_y, width, height); glViewport(offset_x, offset_y, width, height);
} }

View File

@ -23,7 +23,7 @@ int32 shader_type_index(ShaderType type)
case SHADER_TYPE_FRAGMENT: case SHADER_TYPE_FRAGMENT:
return GL_FRAGMENT_SHADER; return GL_FRAGMENT_SHADER;
default: default:
return 0; UNREACHABLE();
} }
} }

View File

@ -0,0 +1,69 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_GPUAPI_VULKAN_APP_CMD_BUFFER_H
#define TOS_GPUAPI_VULKAN_APP_CMD_BUFFER_H
#include "../../stdlib/Types.h"
#include "Shader.h"
#include "ShaderUtils.h"
#include "../ShaderType.h"
#include "../../asset/Asset.h"
#include "../../command/AppCmdBuffer.h"
#include "GpuApiContainer.h"
void* cmd_shader_load(AppCmdBuffer*, Command*) {
return NULL;
}
void* cmd_shader_load_sync(AppCmdBuffer* cb, Shader* shader, int32* shader_ids) {
char asset_id[9];
GpuApiContainer* gpu_api = (GpuApiContainer *) cb->gpu_api;
VkShaderModule shader_assets[SHADER_TYPE_SIZE];
for (int32 i = 0; i < SHADER_TYPE_SIZE; ++i) {
shader_assets[i] = NULL;
}
for (int32 i = 0; i < SHADER_TYPE_SIZE; ++i) {
if (!shader_ids[i]) {
continue;
} else if (shader_ids[i] < 0) {
break;
}
// Load sub asset
int_to_hex(shader_ids[i], asset_id);
Asset* shader_asset = thrd_ams_get_asset_wait(cb->ams, asset_id);
if (!shader_asset) {
int32 archive_id = (shader_ids[i] >> 24) & 0xFF;
shader_asset = asset_archive_asset_load(&cb->asset_archives[archive_id], shader_ids[i], cb->ams, cb->mem_vol);
}
// Make sub shader
shader_assets[i] = shader_make(
((GpuApiContainer *) cb->gpu_api)->device,
(char *) shader_asset->self,
shader_asset->ram_size
);
shader_asset->state |= ASSET_STATE_RAM_GC;
shader_asset->state |= ASSET_STATE_VRAM_GC;
}
// Make shader/program
shader->id = program_make(
gpu_api->device, gpu_api->render_pass, &gpu_api->pipeline_layout, &gpu_api->pipeline,
shader_assets[0], shader_assets[1], shader_assets[2]
);
return NULL;
}
#endif

View File

@ -12,6 +12,8 @@
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#define FRAME_LAG 2
struct GpuApiContainer { struct GpuApiContainer {
VkInstance instance; VkInstance instance;
VkSurfaceKHR surface; VkSurfaceKHR surface;
@ -19,11 +21,11 @@ struct GpuApiContainer {
VkSwapchainKHR swapchain; VkSwapchainKHR swapchain;
uint32 swapchain_image_count; uint32 swapchain_image_count;
VkFormat swapchain_image_format; VkFormat swapchain_image_format;
VkImage* swapchain_images; // swapchain_image_count VkImage* swapchain_images; // length = swapchain_image_count
VkImageView* swapchain_image_views; // swapchain_image_count VkImageView* swapchain_image_views; // length = swapchain_image_count
VkFramebuffer* swapchain_framebuffers; // swapchain_image_count VkFramebuffer* swapchain_framebuffers; // length = swapchain_image_count
VkExtent2D swapchain_extent; VkExtent2D swapchain_extent;
VkPipelineLayout pipelineLayout; VkPipelineLayout pipeline_layout;
VkQueue graphics_queue; VkQueue graphics_queue;
VkQueue present_queue; VkQueue present_queue;
VkRenderPass render_pass; VkRenderPass render_pass;
@ -33,6 +35,10 @@ struct GpuApiContainer {
VkSemaphore image_available_semaphore; VkSemaphore image_available_semaphore;
VkSemaphore render_finished_semaphore; VkSemaphore render_finished_semaphore;
VkFence in_flight_fence; VkFence in_flight_fence;
#if DEBUG || INTERNAL
VkDebugUtilsMessengerEXT debug_messenger;
#endif
}; };
#endif #endif

View File

@ -10,9 +10,12 @@
#define TOS_GPUAPI_VULKAN_SHADER_H #define TOS_GPUAPI_VULKAN_SHADER_H
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include <vulkan/vulkan.h>
struct Shader { struct Shader {
uint32 id; // @todo Consider to rename to pipeline (also in opengl, directx) if this makes sense.
// @question Does this have to be a pointer to the gpuapi->pipeline var?
VkPipeline id;
uint32 locations[7]; uint32 locations[7];
byte data[16]; byte data[16];
}; };

View File

@ -59,7 +59,7 @@ VkShaderModule shader_make(VkDevice device, const char* source, int32 source_siz
VkResult result = vkCreateShaderModule(device, &create_info, NULL, &shader_module); VkResult result = vkCreateShaderModule(device, &create_info, NULL, &shader_module);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
LOG(true, "Failed to create shader module"); LOG_FORMAT(true, "Vulkan vkCreateShaderModule: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
@ -74,4 +74,123 @@ void pipeline_use(VkCommandBuffer command_list, VkPipeline pipeline)
vkCmdBindPipeline(command_list, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdBindPipeline(command_list, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
} }
VkPipeline program_make(
VkDevice device, VkRenderPass render_pass, VkPipelineLayout* pipeline_layout, VkPipeline* pipeline,
VkShaderModule vertex_shader,
VkShaderModule fragment_shader,
VkShaderModule
) {
VkPipelineShaderStageCreateInfo vertex_shader_stage_info = {};
vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertex_shader_stage_info.module = vertex_shader;
vertex_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo fragment_shader_stage_info = {};
fragment_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragment_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragment_shader_stage_info.module = fragment_shader;
fragment_shader_stage_info.pName = "main";
VkPipelineShaderStageCreateInfo shader_stages[] = {vertex_shader_stage_info, fragment_shader_stage_info};
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_input_info.vertexBindingDescriptionCount = 0;
vertex_input_info.vertexAttributeDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewport_state = {};
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewport_state.viewportCount = 1;
viewport_state.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState color_blend_attachment = {};
color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
color_blend_attachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo color_blending = {};
color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
color_blending.logicOpEnable = VK_FALSE;
color_blending.logicOp = VK_LOGIC_OP_COPY;
color_blending.attachmentCount = 1;
color_blending.pAttachments = &color_blend_attachment;
color_blending.blendConstants[0] = 0.0f;
color_blending.blendConstants[1] = 0.0f;
color_blending.blendConstants[2] = 0.0f;
color_blending.blendConstants[3] = 0.0f;
VkDynamicState dynamic_states[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamic_state = {};
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_state.dynamicStateCount = ARRAY_COUNT(dynamic_states);
dynamic_state.pDynamicStates = dynamic_states;
VkPipelineLayoutCreateInfo pipeline_info_layout = {};
pipeline_info_layout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_info_layout.setLayoutCount = 0;
pipeline_info_layout.pushConstantRangeCount = 0;
VkResult result;
if ((result = vkCreatePipelineLayout(device, &pipeline_info_layout, NULL, pipeline_layout)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreatePipelineLayout: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false);
return NULL;
}
VkGraphicsPipelineCreateInfo pipeline_info = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.stageCount = 2;
pipeline_info.pStages = shader_stages;
pipeline_info.pVertexInputState = &vertex_input_info;
pipeline_info.pInputAssemblyState = &input_assembly;
pipeline_info.pViewportState = &viewport_state;
pipeline_info.pRasterizationState = &rasterizer;
pipeline_info.pMultisampleState = &multisampling;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDynamicState = &dynamic_state;
pipeline_info.layout = *pipeline_layout;
pipeline_info.renderPass = render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
if ((result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, pipeline)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreateGraphicsPipelines: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false);
return NULL;
}
vkDestroyShaderModule(device, fragment_shader, NULL);
vkDestroyShaderModule(device, vertex_shader, NULL);
// @question Do we want to return the value or the pointer?
// I think the value is already a pointer?
return *pipeline;
}
#endif #endif

View File

@ -34,8 +34,8 @@ PACKED_STRUCT;
// The reason for the packing is that sometimes we want to use it as an array // The reason for the packing is that sometimes we want to use it as an array
// I am only packing it on the off chance there is some funky behaviour. // I am only packing it on the off chance there is some funky behaviour.
struct VulkanQueueFamilyIndices { struct VulkanQueueFamilyIndices {
uint32 graphics_family; int32 graphics_family;
uint32 present_family; int32 present_family;
}; };
UNPACKED_STRUCT; UNPACKED_STRUCT;
@ -116,39 +116,28 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_callback(
|| (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) || (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
) { ) {
LOG(true, debug_callback_data->pMessage); LOG(true, debug_callback_data->pMessage);
ASSERT_SIMPLE(false);
} }
return VK_FALSE; return VK_FALSE;
} }
void vulkan_populate_debug_messenger_create_info(VkDebugUtilsMessengerCreateInfoEXT* create_info) void gpuapi_debug_messenger_setup(VkInstance instance, VkDebugUtilsMessengerEXT* debug_messenger)
{ {
create_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; // @question Why do I need this twice (see other definition)
create_info->messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; VkDebugUtilsMessengerCreateInfoEXT create_info = {};
create_info->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
create_info->pfnUserCallback = vulkan_debug_callback; create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
} create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
create_info.pfnUserCallback = vulkan_debug_callback;
VkResult vulkan_debug_utils_messenger_create(
VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator, VkDebugUtilsMessengerEXT* debug_messenger
) {
PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (!func) { if (!func) {
ASSERT_SIMPLE(func); ASSERT_SIMPLE(func);
return VK_ERROR_EXTENSION_NOT_PRESENT; return;
} }
return func(instance, create_info, allocator, debug_messenger); if (func(instance, &create_info, NULL, debug_messenger) != VK_SUCCESS) {
}
void vulkan_debug_messenger_setup(VkInstance instance, VkDebugUtilsMessengerEXT* debug_messenger)
{
VkDebugUtilsMessengerCreateInfoEXT create_info = {};
vulkan_populate_debug_messenger_create_info(&create_info);
if (vulkan_debug_utils_messenger_create(instance, &create_info, NULL, debug_messenger) != VK_SUCCESS) {
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
@ -164,6 +153,8 @@ void vulkan_instance_create(
) { ) {
LOG_FORMAT(true, "Vulkan validation_layer missing: %d", {{LOG_DATA_CHAR_STR, (void *) validation_layers[-err - 1]}}); LOG_FORMAT(true, "Vulkan validation_layer missing: %d", {{LOG_DATA_CHAR_STR, (void *) validation_layers[-err - 1]}});
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
return;
} }
if (extension_count if (extension_count
@ -171,6 +162,8 @@ void vulkan_instance_create(
) { ) {
LOG_FORMAT(true, "Vulkan extension missing: %d", {{LOG_DATA_CHAR_STR, (void *) extensions[-err - 1]}}); LOG_FORMAT(true, "Vulkan extension missing: %d", {{LOG_DATA_CHAR_STR, (void *) extensions[-err - 1]}});
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
return;
} }
VkApplicationInfo app_info = {}; VkApplicationInfo app_info = {};
@ -188,12 +181,17 @@ void vulkan_instance_create(
create_info.enabledExtensionCount = extension_count; create_info.enabledExtensionCount = extension_count;
create_info.ppEnabledExtensionNames = extensions; create_info.ppEnabledExtensionNames = extensions;
VkDebugUtilsMessengerCreateInfoEXT debug_create_info = {};
if (validation_layer_count) { if (validation_layer_count) {
create_info.enabledLayerCount = validation_layer_count; create_info.enabledLayerCount = validation_layer_count;
create_info.ppEnabledLayerNames = validation_layers; create_info.ppEnabledLayerNames = validation_layers;
vulkan_populate_debug_messenger_create_info(&debug_create_info); // @question Why do I need this twice (see other definition)
VkDebugUtilsMessengerCreateInfoEXT debug_create_info = {};
debug_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
debug_create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
debug_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
debug_create_info.pfnUserCallback = vulkan_debug_callback;
create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT *) &debug_create_info; create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT *) &debug_create_info;
} }
@ -218,6 +216,7 @@ void vulkan_surface_create(VkInstance instance, VkSurfaceKHR* surface, Window* w
return; return;
} }
#elif __linux__ #elif __linux__
// @todo implement
#endif #endif
} }
@ -265,7 +264,7 @@ void vulkan_available_extensions(RingMemory* ring) {
VulkanQueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice physical_device, VkSurfaceKHR surface, RingMemory* ring) VulkanQueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice physical_device, VkSurfaceKHR surface, RingMemory* ring)
{ {
VulkanQueueFamilyIndices indices = {}; VulkanQueueFamilyIndices indices = { -1, -1 };
uint32 queue_family_count = 0; uint32 queue_family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, NULL); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, NULL);
@ -274,17 +273,24 @@ VulkanQueueFamilyIndices vulkan_find_queue_families(VkPhysicalDevice physical_de
for (uint32 i = 0; i < queue_family_count; ++i) { for (uint32 i = 0; i < queue_family_count; ++i) {
if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphics_family = i + 1; indices.graphics_family = i;
} }
VkBool32 present_support = false; VkBool32 present_support = false;
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support);
if (present_support) { VkResult result;
indices.present_family = i + 1; if ((result = vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkGetPhysicalDeviceSurfaceSupportKHR: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false);
return indices;
} }
if (indices.graphics_family && indices.present_family) { if (present_support) {
indices.present_family = i;
}
if (indices.graphics_family >= 0 && indices.present_family >= 0) {
break; break;
} }
} }
@ -326,7 +332,7 @@ bool vulkan_is_device_suitable(VkPhysicalDevice physical_device, VkSurfaceKHR su
swap_chain_adequate = swap_chain_support.format_size && swap_chain_support.present_modes; swap_chain_adequate = swap_chain_support.format_size && swap_chain_support.present_modes;
} }
return indices.graphics_family && indices.present_family return indices.graphics_family >= 0 && indices.present_family >= 0
&& extensions_supported && swap_chain_adequate; && extensions_supported && swap_chain_adequate;
} }
@ -404,8 +410,6 @@ void gpuapi_create_logical_device(
vkGetDeviceQueue(*device, indices.present_family, 0, present_queue); vkGetDeviceQueue(*device, indices.present_family, 0, present_queue);
} }
// WARNING: swapchain_images needs to already have reserved enough memory
// @todo How can we ensure swapchain_images has enough but not too much space?
// @question Do we need to handle old swapchains? // @question Do we need to handle old swapchains?
void vulkan_swap_chain_create( void vulkan_swap_chain_create(
VkDevice device, VkPhysicalDevice physical_device, VkSurfaceKHR surface, VkDevice device, VkPhysicalDevice physical_device, VkSurfaceKHR surface,
@ -486,11 +490,15 @@ void vulkan_swap_chain_create(
if ((result = vkCreateSwapchainKHR(device, &create_info, NULL, swapchain)) != VK_SUCCESS) { if ((result = vkCreateSwapchainKHR(device, &create_info, NULL, swapchain)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreateSwapchainKHR: %d", LOG_DATA_INT32, (int32 *) &result); LOG_FORMAT(true, "Vulkan vkCreateSwapchainKHR: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
return;
} }
memcpy(swapchain_image_format, &surface_format->format, sizeof(VkFormat)); memcpy(swapchain_image_format, &surface_format->format, sizeof(VkFormat));
} }
// WARNING: swapchain_images needs to already have reserved enough memory
// @todo How can we ensure swapchain_images has enough but not too much space?
void vulkan_swap_chain_images_create( void vulkan_swap_chain_images_create(
VkDevice device, VkSwapchainKHR swapchain, VkDevice device, VkSwapchainKHR swapchain,
VkImage** swapchain_images, uint32* swapchain_image_count, VkImage** swapchain_images, uint32* swapchain_image_count,
@ -531,27 +539,27 @@ void vulkan_image_views_create(
} }
} }
void create_render_pass( void vulkan_render_pass_create(
VkDevice device, VkRenderPass* render_pass, VkFormat swapchain_image_format VkDevice device, VkRenderPass* render_pass, VkFormat swapchain_image_format
) { ) {
VkAttachmentDescription colorAttachment = {}; VkAttachmentDescription color_attachment = {};
colorAttachment.format = swapchain_image_format; color_attachment.format = swapchain_image_format;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference colorAttachmentRef = {}; VkAttachmentReference color_attachment_ref = {};
colorAttachmentRef.attachment = 0; color_attachment_ref.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {}; VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1; subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef; subpass.pColorAttachments = &color_attachment_ref;
VkSubpassDependency dependency = {}; VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
@ -561,141 +569,22 @@ void create_render_pass(
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo renderPassInfo = {}; VkRenderPassCreateInfo render_pass_info = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = 1; render_pass_info.attachmentCount = 1;
renderPassInfo.pAttachments = &colorAttachment; render_pass_info.pAttachments = &color_attachment;
renderPassInfo.subpassCount = 1; render_pass_info.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass; render_pass_info.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1; render_pass_info.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency; render_pass_info.pDependencies = &dependency;
VkResult result; VkResult result;
if ((result = vkCreateRenderPass(device, &renderPassInfo, NULL, render_pass)) != VK_SUCCESS) { if ((result = vkCreateRenderPass(device, &render_pass_info, NULL, render_pass)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreateRenderPass: %d", LOG_DATA_INT32, (int32 *) &result); LOG_FORMAT(true, "Vulkan vkCreateRenderPass: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
// @todo This is very similar to program_make in opengl. Consider to rename opengl
void vulkan_pipeline_create(
VkDevice device,
VkShaderModule vertex_shader,
VkShaderModule fragment_shader,
[[maybe_unused]] VkShaderModule geometry_shader,
VkPipeline* pipeline,
VkPipelineLayout* pipeline_layout,
VkRenderPass render_pass
)
{
uint32 stage_count = 0;
VkPipelineShaderStageCreateInfo shaderStages[3];
VkPipelineShaderStageCreateInfo vs_stage_create = {};
vs_stage_create.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vs_stage_create.stage = VK_SHADER_STAGE_VERTEX_BIT;
vs_stage_create.module = vertex_shader;
vs_stage_create.pName = "main";
++stage_count;
VkPipelineShaderStageCreateInfo fs_stage_create = {};
fs_stage_create.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fs_stage_create.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fs_stage_create.module = fragment_shader;
fs_stage_create.pName = "main";
++stage_count;
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
VkDynamicState dynamicStates[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = ARRAY_COUNT(dynamicStates);
dynamicState.pDynamicStates = dynamicStates;
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 0;
pipelineLayoutInfo.pushConstantRangeCount = 0;
VkResult result;
if ((result = vkCreatePipelineLayout(device, &pipelineLayoutInfo, NULL, pipeline_layout)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreatePipelineLayout: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false);
}
VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = stage_count;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = *pipeline_layout;
pipelineInfo.renderPass = render_pass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if ((result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, pipeline)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreateGraphicsPipelines: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false);
}
vkDestroyShaderModule(device, vertex_shader, NULL);
vkDestroyShaderModule(device, fragment_shader, NULL);
}
// @todo consider to rename to same name as opengl // @todo consider to rename to same name as opengl
// WARNING: swapchain_framebuffers needs to be initialized // WARNING: swapchain_framebuffers needs to be initialized
void vulkan_framebuffer_create( void vulkan_framebuffer_create(
@ -731,13 +620,13 @@ void vulkan_command_pool_create(
) { ) {
VulkanQueueFamilyIndices queue_family_indices = vulkan_find_queue_families(physical_device, surface, ring); VulkanQueueFamilyIndices queue_family_indices = vulkan_find_queue_families(physical_device, surface, ring);
VkCommandPoolCreateInfo poolInfo = {}; VkCommandPoolCreateInfo pool_info = {};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = queue_family_indices.graphics_family; pool_info.queueFamilyIndex = queue_family_indices.graphics_family;
VkResult result; VkResult result;
if ((result = vkCreateCommandPool(device, &poolInfo, NULL, command_pool)) != VK_SUCCESS) { if ((result = vkCreateCommandPool(device, &pool_info, NULL, command_pool)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkCreateCommandPool: %d", LOG_DATA_INT32, (int32 *) &result); LOG_FORMAT(true, "Vulkan vkCreateCommandPool: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -745,14 +634,14 @@ void vulkan_command_pool_create(
void vulkan_command_buffer_create(VkDevice device, VkCommandBuffer* command_buffer, VkCommandPool command_pool) void vulkan_command_buffer_create(VkDevice device, VkCommandBuffer* command_buffer, VkCommandPool command_pool)
{ {
VkCommandBufferAllocateInfo allocInfo = {}; VkCommandBufferAllocateInfo alloc_info = {};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = command_pool; alloc_info.commandPool = command_pool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1; alloc_info.commandBufferCount = 1;
VkResult result; VkResult result;
if ((result = vkAllocateCommandBuffers(device, &allocInfo, command_buffer)) != VK_SUCCESS) { if ((result = vkAllocateCommandBuffers(device, &alloc_info, command_buffer)) != VK_SUCCESS) {
LOG_FORMAT(true, "Vulkan vkAllocateCommandBuffers: %d", LOG_DATA_INT32, (int32 *) &result); LOG_FORMAT(true, "Vulkan vkAllocateCommandBuffers: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
@ -760,70 +649,22 @@ void vulkan_command_buffer_create(VkDevice device, VkCommandBuffer* command_buff
void vulkan_sync_objects_create(VkDevice device, VkSemaphore* image_available_semaphore, VkSemaphore* render_finished_semaphore, VkFence* in_flight_fence) void vulkan_sync_objects_create(VkDevice device, VkSemaphore* image_available_semaphore, VkSemaphore* render_finished_semaphore, VkFence* in_flight_fence)
{ {
VkSemaphoreCreateInfo semaphoreInfo = {}; VkSemaphoreCreateInfo semaphore_info = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo fenceInfo{}; VkFenceCreateInfo fence_info = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkResult result; VkResult result;
if ((result = vkCreateSemaphore(device, &semaphoreInfo, NULL, image_available_semaphore)) != VK_SUCCESS if ((result = vkCreateSemaphore(device, &semaphore_info, NULL, image_available_semaphore)) != VK_SUCCESS
|| (result = vkCreateSemaphore(device, &semaphoreInfo, NULL, render_finished_semaphore)) != VK_SUCCESS || (result = vkCreateSemaphore(device, &semaphore_info, NULL, render_finished_semaphore)) != VK_SUCCESS
|| (result = vkCreateFence(device, &fenceInfo, NULL, in_flight_fence)) != VK_SUCCESS || (result = vkCreateFence(device, &fence_info, NULL, in_flight_fence)) != VK_SUCCESS
) { ) {
LOG_FORMAT(true, "Vulkan vulkan_sync_objects_create: %d", LOG_DATA_INT32, (int32 *) &result); LOG_FORMAT(true, "Vulkan vulkan_sync_objects_create: %d", LOG_DATA_INT32, (int32 *) &result);
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
} }
} }
/*
void vulkan_command_buffer_record(
VkCommandBuffer command_buffer
) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
if (vkBeginCommandBuffer(command_buffer, &beginInfo) != VK_SUCCESS) {
ASSERT_SIMPLE(false);
}
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = renderPass;
renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapChainExtent;
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(swapChainExtent.width);
viewport.height = static_cast<float>(swapChainExtent.height);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = {0, 0};
scissor.extent = swapChainExtent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
ASSERT_SIMPLE(false);
}
}
*/
#endif #endif

View File

@ -416,40 +416,6 @@ void mat3vec3_mult(const f32* __restrict matrix, const f32* __restrict vector, f
result[2] = matrix[6] * vector[0] + matrix[7] * vector[1] + matrix[8] * vector[2]; result[2] = matrix[6] * vector[0] + matrix[7] * vector[1] + matrix[8] * vector[2];
} }
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const f32* __restrict matrix, const f32* __restrict vector, f32* __restrict result)
{
__m128 vec = _mm_load_ps(vector);
vec = _mm_insert_ps(vec, _mm_setzero_ps(), 0x30); // vec[3] = 0
for (int32 i = 0; i < 3; ++i) {
__m128 row = _mm_load_ps(&matrix[i * 3]);
row = _mm_insert_ps(row, _mm_setzero_ps(), 0x30); // row[3] = 0
__m128 dot = _mm_dp_ps(row, vec, 0xF1);
result[i] = _mm_cvtss_f32(dot);
}
}
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const __m128* __restrict matrix, const __m128* __restrict vector, f32* __restrict result)
{
for (int32 i = 0; i < 3; ++i) {
__m128 dot = _mm_dp_ps(matrix[i], *vector, 0xF1);
result[i] = _mm_cvtss_f32(dot);
}
}
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const __m128* __restrict matrix, const __m128* __restrict vector, __m128* __restrict result)
{
for (int32 i = 0; i < 4; ++i) {
result[i] = _mm_dp_ps(matrix[i], *vector, 0xF1);
}
}
inline inline
void mat4vec4_mult(const f32* __restrict matrix, const f32* __restrict vector, f32* __restrict result) void mat4vec4_mult(const f32* __restrict matrix, const f32* __restrict vector, f32* __restrict result)
{ {
@ -514,146 +480,32 @@ void mat4mat4_mult(const f32* __restrict a, const f32* __restrict b, f32* __rest
result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]; result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];
} }
void mat4mat4_mult(const f32* __restrict a, const f32* __restrict b, f32* __restrict result, int32 steps)
{
if (steps > 1) {
// @todo check http://fhtr.blogspot.com/2010/02/4x4-f32-matrix-multiplication-using.html
// @question could simple mul add sse be faster?
// Load rows of matrix a
__m128 a_1 = _mm_load_ps(a);
__m128 a_2 = _mm_load_ps(&a[4]);
__m128 a_3 = _mm_load_ps(&a[8]);
__m128 a_4 = _mm_load_ps(&a[12]);
// Load columns of matrix b
__m128 b_1 = _mm_load_ps(b);
__m128 b_2 = _mm_load_ps(&b[4]);
__m128 b_3 = _mm_load_ps(&b[8]);
__m128 b_4 = _mm_load_ps(&b[12]);
_mm_storeu_ps(&result[0],
_mm_add_ps(
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(0, 0, 0, 0)), b_1),
_mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(1, 1, 1, 1)), b_2)
),
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(2, 2, 2, 2)), b_3),
_mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(3, 3, 3, 3)), b_4)
)
)
);
_mm_storeu_ps(&result[4],
_mm_add_ps(
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(0, 0, 0, 0)), b_1),
_mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(1, 1, 1, 1)), b_2)
),
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(2, 2, 2, 2)), b_3),
_mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(3, 3, 3, 3)), b_4)
)
)
);
_mm_storeu_ps(&result[8],
_mm_add_ps(
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(0, 0, 0, 0)), b_1),
_mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(1, 1, 1, 1)), b_2)
),
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(2, 2, 2, 2)), b_3),
_mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(3, 3, 3, 3)), b_4)
)
)
);
_mm_storeu_ps(&result[12],
_mm_add_ps(
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(0, 0, 0, 0)), b_1),
_mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(1, 1, 1, 1)), b_2)
),
_mm_add_ps(
_mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(2, 2, 2, 2)), b_3),
_mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(3, 3, 3, 3)), b_4)
)
)
);
} else {
mat4mat4_mult(a, b, result);
}
}
void mat4mat4_mult_sse(const __m128* __restrict a, const __m128* __restrict b_transposed, f32* __restrict result)
{
__m128 dot;
// @question could simple mul add sse be faster?
// b1
dot = _mm_dp_ps(a[0], b_transposed[0], 0xF1);
result[0] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[0], 0xF1);
result[1] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[0], 0xF1);
result[2] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[0], 0xF1);
result[3] = _mm_cvtss_f32(dot);
// b2
dot = _mm_dp_ps(a[0], b_transposed[1], 0xF1);
result[4] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[1], 0xF1);
result[5] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[1], 0xF1);
result[6] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[1], 0xF1);
result[7] = _mm_cvtss_f32(dot);
// b3
dot = _mm_dp_ps(a[0], b_transposed[2], 0xF1);
result[8] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[2], 0xF1);
result[9] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[2], 0xF1);
result[10] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[2], 0xF1);
result[11] = _mm_cvtss_f32(dot);
// b4
dot = _mm_dp_ps(a[0], b_transposed[3], 0xF1);
result[12] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[3], 0xF1);
result[13] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[3], 0xF1);
result[14] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[3], 0xF1);
result[15] = _mm_cvtss_f32(dot);
}
inline inline
void mat4mat4_mult_sse(const __m128* __restrict a, const __m128* __restrict b_transpose, __m128* __restrict result) void mat4mat4_mult_simd(const f32* __restrict a, const f32* __restrict b, f32* __restrict result)
{ {
for (int32 i = 0; i < 4; ++i) { __m128 row1 = _mm_loadu_ps(&b[0]);
result[i] = _mm_mul_ps(a[0], b_transpose[i]); __m128 row2 = _mm_loadu_ps(&b[4]);
__m128 row3 = _mm_loadu_ps(&b[8]);
__m128 row4 = _mm_loadu_ps(&b[12]);
for (int32 j = 1; j < 4; ++j) { for (int32 i = 3; i >= 0; --i) {
result[i] = _mm_add_ps(_mm_mul_ps(a[j], b_transpose[4 * j + i]), result[i]); __m128 vW = _mm_loadu_ps(&a[i * 4]);
}
__m128 vX = _mm_shuffle_ps(vW, vW, _MM_SHUFFLE(0, 0, 0, 0));
__m128 vY = _mm_shuffle_ps(vW, vW, _MM_SHUFFLE(1, 1, 1, 1));
__m128 vZ = _mm_shuffle_ps(vW, vW, _MM_SHUFFLE(2, 2, 2, 2));
vW = _mm_shuffle_ps(vW, vW, _MM_SHUFFLE(3, 3, 3, 3));
vX = _mm_mul_ps(vX, row1);
vY = _mm_mul_ps(vY, row2);
vZ = _mm_mul_ps(vZ, row3);
vW = _mm_mul_ps(vW, row4);
vX = _mm_add_ps(vX, vZ);
vY = _mm_add_ps(vY, vW);
vX = _mm_add_ps(vX, vY);
_mm_storeu_ps(&result[i * 4], vX);
} }
} }
@ -863,7 +715,7 @@ void mat4_translate(f32* matrix, f32 dx, f32 dy, f32 dz)
mat4mat4_mult(temp, translation_matrix, matrix); mat4mat4_mult(temp, translation_matrix, matrix);
} }
void mat4_translate(f32* matrix, f32 dx, f32 dy, f32 dz, int32 steps) void mat4_translate_simd(f32* matrix, f32 dx, f32 dy, f32 dz)
{ {
alignas(64) f32 temp[16]; alignas(64) f32 temp[16];
memcpy(temp, matrix, sizeof(f32) * 16); memcpy(temp, matrix, sizeof(f32) * 16);
@ -874,7 +726,7 @@ void mat4_translate(f32* matrix, f32 dx, f32 dy, f32 dz, int32 steps)
translation_matrix[8] = 0.0f; translation_matrix[9] = 0.0f; translation_matrix[10] = 1.0f; translation_matrix[11] = dz; translation_matrix[8] = 0.0f; translation_matrix[9] = 0.0f; translation_matrix[10] = 1.0f; translation_matrix[11] = dz;
translation_matrix[12] = 0.0f; translation_matrix[13] = 0.0f; translation_matrix[14] = 0.0f; translation_matrix[15] = 1.0f; translation_matrix[12] = 0.0f; translation_matrix[13] = 0.0f; translation_matrix[14] = 0.0f; translation_matrix[15] = 1.0f;
mat4mat4_mult(temp, translation_matrix, matrix, steps); mat4mat4_mult_simd(temp, translation_matrix, matrix);
} }
inline inline

47
object/Model.h Normal file
View File

@ -0,0 +1,47 @@
// Memory layout TBD, we can probably optimize it for matrix operations
///////////////////////////////
// Model
// ============================
// Mesh
// ============================
// Current Transform/Mesh
// ============================
// Joint 1
// ============================
// Child Joint Id 1
// Child Joint Id 2
// ...
// ============================
// Joint 2
// ....
// ============================
// Animation 1
// ============================
// Keyframe 1
// ============================
// Joint 1 Transform
// Joint 2 Transform
// ....
// ============================
// Keyframe 2
// ============================
// ....
// ============================
// Animation 2
// ============================
// ....
// ============================
struct Model {
Mesh* mesh;
};
struct ModelJoint {
byte children_count;
};
struct ModelAnimation {
// joint positions
};

View File

@ -35,6 +35,11 @@ struct Vertex3DColorIndex {
f32 color; f32 color;
}; };
struct Vertex3DColor {
v3_f32 position;
v4_f32 color;
};
struct Vertex2D { struct Vertex2D {
v2_f32 position; v2_f32 position;
v2_f32 tex_coord; v2_f32 tex_coord;

View File

@ -242,14 +242,14 @@ void file_read(const char* path, FileBody* file, RingMemory* ring) {
return; return;
} }
file->size = file_stat.st_size + 1; file->size = file_stat.st_size;
} }
if (ring != NULL) { if (ring != NULL) {
file->content = ring_get_memory(ring, file->size); file->content = ring_get_memory(ring, file->size + 1);
} }
ssize_t bytes_read = read(fp, file->content, file->size - 1); ssize_t bytes_read = read(fp, file->content, file->size);
if (bytes_read != file->size) { if (bytes_read != file->size) {
close(fp); close(fp);
file->content = NULL; file->content = NULL;

View File

@ -185,15 +185,15 @@ file_read(const char* path, FileBody* file, RingMemory* ring = NULL)
return; return;
} }
file->size = size.QuadPart + 1; file->size = size.QuadPart;
} }
if (ring != NULL) { if (ring != NULL) {
file->content = ring_get_memory(ring, file->size); file->content = ring_get_memory(ring, file->size + 1);
} }
DWORD bytes_read; DWORD bytes_read;
if (!ReadFile(fp, file->content, (uint32) file->size - 1, &bytes_read, NULL)) { if (!ReadFile(fp, file->content, (uint32) file->size, &bytes_read, NULL)) {
CloseHandle(fp); CloseHandle(fp);
file->content = NULL; file->content = NULL;
@ -203,7 +203,7 @@ file_read(const char* path, FileBody* file, RingMemory* ring = NULL)
CloseHandle(fp); CloseHandle(fp);
file->content[bytes_read] = '\0'; file->content[bytes_read] = '\0';
file->size = bytes_read + 1; file->size = bytes_read;
LOG_INCREMENT_BY(DEBUG_COUNTER_DRIVE_READ, bytes_read); LOG_INCREMENT_BY(DEBUG_COUNTER_DRIVE_READ, bytes_read);
} }

View File

@ -159,12 +159,12 @@ HBITMAP CreateBitmapFromRGBA(HDC hdc, const byte* rgba, int32 width, int32 heigh
bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biCompression = BI_RGB;
void* pbits; void* pbits;
HBITMAP hBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pbits, NULL, 0); HBITMAP hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pbits, NULL, 0);
if (hBitmap) { if (hbitmap) {
memcpy(pbits, rgba, width * height * 4); memcpy(pbits, rgba, width * height * 4);
} }
return hBitmap; return hbitmap;
} }
#endif #endif

View File

@ -206,9 +206,9 @@ void input_mouse_position(HWND hwnd, v2_int32* pos)
} }
} }
int32 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32 state_count, uint64 time) int16 input_raw_handle(RAWINPUT* __restrict raw, Input* __restrict states, int32 state_count, uint64 time)
{ {
int32 input_count = 0; int16 input_count = 0;
int32 i = 0; int32 i = 0;
if (raw->header.dwType == RIM_TYPEMOUSE) { if (raw->header.dwType == RIM_TYPEMOUSE) {
@ -398,7 +398,7 @@ void input_handle(LPARAM lParam, Input* __restrict states, int state_count, Ring
input_raw_handle((RAWINPUT *) lpb, states, state_count, time); input_raw_handle((RAWINPUT *) lpb, states, state_count, time);
} }
int32 input_handle_buffered(int32 buffer_size, Input* __restrict states, int state_count, RingMemory* ring, uint64 time) int16 input_handle_buffered(int32 buffer_size, Input* __restrict states, int32 state_count, RingMemory* ring, uint64 time)
{ {
uint32 cb_size; uint32 cb_size;
GetRawInputBuffer(NULL, &cb_size, sizeof(RAWINPUTHEADER)); GetRawInputBuffer(NULL, &cb_size, sizeof(RAWINPUTHEADER));
@ -411,7 +411,7 @@ int32 input_handle_buffered(int32 buffer_size, Input* __restrict states, int sta
PRAWINPUT raw_input = (PRAWINPUT) ring_get_memory(ring, cb_size, 4); PRAWINPUT raw_input = (PRAWINPUT) ring_get_memory(ring, cb_size, 4);
int32 input_count = 0; int16 input_count = 0;
uint32 input; uint32 input;
while (true) { while (true) {

View File

@ -10,243 +10,424 @@
#define TOS_PLATFORM_WIN32_THREADING_ATOMIC_H #define TOS_PLATFORM_WIN32_THREADING_ATOMIC_H
#include "../../../stdlib/Types.h" #include "../../../stdlib/Types.h"
#include "../../../compiler/CompilerUtils.h"
#include <windows.h> #include <windows.h>
// WARNING: Windows doesn't really have relaxed, release, acquire function on x86_64.
// You can see that by checking out how they are defined
// We need the following helper types to "cast" between float and long. // We need the following helper types to "cast" between float and long.
// We can't just perform a "normal" cast since that re-interprets the bits. We need to maintain the bits // We can't just perform a "normal" cast since that re-interprets the bits. We need to maintain the bits
// @question Don't we also have to do this for signed vs unsigned?
typedef union { f32 f; LONG l; } _atomic_32; typedef union { f32 f; LONG l; } _atomic_32;
typedef union { f64 f; LONG64 l; } _atomic_64; typedef union { f64 f; LONG64 l; } _atomic_64;
inline void atomic_set_relaxed(void** target, void* new_pointer) { InterlockedExchangePointerNoFence(target, new_pointer); } // WARNING: Windows doesn't really have relaxed, release, acquire function on x86_64.
inline void* atomic_get_relaxed(void** target) { return InterlockedCompareExchangePointerNoFence(target, NULL, NULL); } // You can see that by checking out how they are defined
inline void atomic_set_relaxed(volatile int32* value, int32 new_value) { InterlockedExchangeNoFence((long *) value, new_value); } // @bug As a result we are not always using the correct fenced/unfenced version on ARM
inline void atomic_set_relaxed(volatile int64* value, int64 new_value) { InterlockedExchangeNoFence64((LONG64 *) value, (LONG64) new_value); } // (e.g. see _InterlockedCompareExchange8, it should be _InterlockedCompareExchange8_nf/rel/acq)
inline void atomic_set_relaxed(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchangeNoFence((long *) value, (long) temp.l); } // To solve this we would probably have to make some of these functions Architecture specific in addition to platform specific
inline void atomic_set_relaxed(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchangeNoFence64((LONG64 *) value, (LONG64) temp.l); }
inline int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return (int32) InterlockedExchangeNoFence((long *) value, new_value); }
inline int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return (int64) InterlockedExchangeNoFence64((LONG64 *) value, (LONG64) new_value); }
inline int32 atomic_get_relaxed(volatile int32* value) { return (int32) InterlockedCompareExchangeNoFence((long *) value, 0, 0); }
inline int64 atomic_get_relaxed(volatile int64* value) { return (int64) InterlockedCompareExchangeNoFence64((LONG64 *) value, 0, 0); }
inline f32 atomic_get_relaxed(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeNoFence((long *) value, 0, 0)}; return temp.f; }
inline f64 atomic_get_relaxed(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeNoFence64((LONG64 *) value, 0, 0)}; return temp.f; }
inline void atomic_increment_relaxed(volatile int32* value) { InterlockedIncrementNoFence((long *) value); }
inline void atomic_decrement_relaxed(volatile int32* value) { InterlockedDecrementNoFence((long *) value); }
inline void atomic_increment_relaxed(volatile int64* value) { InterlockedIncrementNoFence64((LONG64 *) value); }
inline void atomic_decrement_relaxed(volatile int64* value) { InterlockedDecrementNoFence64((LONG64 *) value); }
inline void atomic_add_relaxed(volatile int32* value, int32 increment) { InterlockedAddNoFence((long *) value, increment); }
inline void atomic_sub_relaxed(volatile int32* value, int32 decrement) { InterlockedAddNoFence((long *) value, -decrement); }
inline void atomic_add_relaxed(volatile int64* value, int64 increment) { InterlockedAddNoFence64((LONG64 *) value, (LONG64) increment); }
inline void atomic_sub_relaxed(volatile int64* value, int64 decrement) { InterlockedAddNoFence64((LONG64 *) value, -((LONG64) decrement)); }
inline f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeNoFence((long *) value, (long) desired, (long) *expected) }; return temp.f; }
inline f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeNoFence64((LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; }
inline int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeNoFence((long *) value, desired, *expected); }
inline int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeNoFence64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
inline int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddNoFence((long *) value, operand); }
inline int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddNoFence((unsigned long *) value, -((long) operand)); }
inline int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddNoFence64((LONG64 *) value, (LONG64) operand); }
inline int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); }
inline void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { InterlockedExchangeNoFence((long *) value, new_value); }
inline void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { InterlockedExchangeNoFence64((LONG64 *) value, (LONG64) new_value); }
inline uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchangeNoFence((long *) value, new_value); }
inline uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchangeNoFence64((LONG64 *) value, (LONG64) new_value); }
inline uint32 atomic_get_relaxed(volatile uint32* value) { return (uint32) InterlockedCompareExchangeNoFence((long *) value, 0, 0); }
inline uint64 atomic_get_relaxed(volatile uint64* value) { return (uint64) InterlockedCompareExchangeNoFence64((LONG64 *) value, 0, 0); }
inline void atomic_increment_relaxed(volatile uint32* value) { InterlockedIncrementNoFence((long *) value); }
inline void atomic_decrement_relaxed(volatile uint32* value) { InterlockedDecrementNoFence((long *) value); }
inline void atomic_increment_relaxed(volatile uint64* value) { InterlockedIncrementNoFence64((LONG64 *) value); }
inline void atomic_decrement_relaxed(volatile uint64* value) { InterlockedDecrementNoFence64((LONG64 *) value); }
inline void atomic_add_relaxed(volatile uint32* value, uint32 increment) { InterlockedAddNoFence((long *) value, increment); }
inline void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { InterlockedAddNoFence((long *) value, -1 * ((int32) decrement)); }
inline void atomic_add_relaxed(volatile uint64* value, uint64 increment) { InterlockedAddNoFence64((LONG64 *) value, (LONG64) increment); }
inline void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { InterlockedAddNoFence64((LONG64 *) value, -((LONG64) decrement)); }
inline uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeNoFence((long *) value, desired, *expected); }
inline uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeNoFence64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
inline uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddNoFence((long *) value, operand); }
inline uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddNoFence((unsigned long *) value, -((long) operand)); }
inline uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddNoFence64((LONG64 *) value, (LONG64) operand); }
inline uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); }
inline void atomic_and_relaxed(volatile uint32* value, uint32 mask) { InterlockedAndNoFence((volatile LONG *) value, mask); }
inline void atomic_and_relaxed(volatile int32* value, int32 mask) { InterlockedAndNoFence((volatile LONG *) value, (LONG)mask); }
inline void atomic_and_relaxed(volatile uint64* value, uint64 mask) { InterlockedAnd64NoFence((volatile LONG64 *) value, mask); }
inline void atomic_and_relaxed(volatile int64* value, int64 mask) { InterlockedAnd64NoFence((volatile LONG64 *) value, mask); }
inline void atomic_or_relaxed(volatile uint32* value, uint32 mask) { InterlockedOrNoFence((volatile LONG *) value, mask); }
inline void atomic_or_relaxed(volatile int32* value, int32 mask) { InterlockedOrNoFence((volatile LONG *) value, (LONG)mask); }
inline void atomic_or_relaxed(volatile uint64* value, uint64 mask) { InterlockedOr64NoFence((volatile LONG64 *) value, mask); }
inline void atomic_or_relaxed(volatile int64* value, int64 mask) { InterlockedOr64NoFence((volatile LONG64 *) value, mask); }
inline void atomic_set_acquire(void** target, void* new_pointer) { InterlockedExchangePointerAcquire(target, new_pointer); } FORCE_INLINE void atomic_set_relaxed(void** target, void* new_pointer) { InterlockedExchangePointerNoFence(target, new_pointer); }
inline void* atomic_get_acquire(void** target) { return InterlockedCompareExchangePointerAcquire(target, NULL, NULL); } FORCE_INLINE void* atomic_get_relaxed(void** target) { return InterlockedCompareExchangePointerNoFence(target, NULL, NULL); }
inline void atomic_set_acquire(volatile int32* value, int32 new_value) { InterlockedExchangeAcquire((long *) value, new_value); } FORCE_INLINE void atomic_set_relaxed(volatile int8* value, int8 new_value) { InterlockedExchangeNoFence8((volatile char *) value, new_value); }
inline void atomic_set_acquire(volatile int64* value, int64 new_value) { InterlockedExchangeAcquire64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_relaxed(volatile int16* value, int16 new_value) { InterlockedExchangeNoFence16((volatile short *) value, new_value); }
inline void atomic_set_acquire(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchangeAcquire((long *) value, (long) temp.l); } FORCE_INLINE void atomic_set_relaxed(volatile int32* value, int32 new_value) { InterlockedExchangeNoFence((volatile long *) value, new_value); }
inline void atomic_set_acquire(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchangeAcquire64((LONG64 *) value, (LONG64) temp.l); } FORCE_INLINE void atomic_set_relaxed(volatile int64* value, int64 new_value) { InterlockedExchangeNoFence64((volatile LONG64 *) value, (LONG64) new_value); }
inline int32 atomic_fetch_set_acquire(volatile int32* value, int32 new_value) { return (int32) InterlockedExchangeAcquire((long *) value, new_value); } FORCE_INLINE void atomic_set_relaxed(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchangeNoFence((volatile long *) value, (long) temp.l); }
inline int64 atomic_fetch_set_acquire(volatile int64* value, int64 new_value) { return (int64) InterlockedExchangeAcquire64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_relaxed(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchangeNoFence64((volatile LONG64 *) value, (LONG64) temp.l); }
inline int32 atomic_get_acquire(volatile int32* value) { return (int32) InterlockedCompareExchangeAcquire((long *) value, 0, 0); } FORCE_INLINE int8 atomic_fetch_set_relaxed(volatile int8* value, int8 new_value) { return (int8) InterlockedExchangeNoFence8((volatile char *) value, (char) new_value); }
inline int64 atomic_get_acquire(volatile int64* value) { return (int64) InterlockedCompareExchangeAcquire64((LONG64 *) value, 0, 0); } FORCE_INLINE int16 atomic_fetch_set_relaxed(volatile int16* value, int16 new_value) { return (int16) InterlockedExchangeNoFence16((volatile short *) value, (short) new_value); }
inline f32 atomic_get_acquire(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeAcquire((long *) value, 0, 0)}; return temp.f; } FORCE_INLINE int32 atomic_fetch_set_relaxed(volatile int32* value, int32 new_value) { return (int32) InterlockedExchangeNoFence((volatile long *) value, new_value); }
inline f64 atomic_get_acquire(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeAcquire64((LONG64 *) value, 0, 0)}; return temp.f; } FORCE_INLINE int64 atomic_fetch_set_relaxed(volatile int64* value, int64 new_value) { return (int64) InterlockedExchangeNoFence64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_increment_acquire(volatile int32* value) { InterlockedIncrementAcquire((long *) value); } FORCE_INLINE int8 atomic_get_relaxed(volatile int8* value) { return (int8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_decrement_acquire(volatile int32* value) { InterlockedDecrementAcquire((long *) value); } FORCE_INLINE int16 atomic_get_relaxed(volatile int16* value) { return (int16) InterlockedCompareExchangeNoFence16((volatile short *) value, 0, 0); }
inline void atomic_increment_acquire(volatile int64* value) { InterlockedIncrementAcquire64((LONG64 *) value); } FORCE_INLINE int32 atomic_get_relaxed(volatile int32* value) { return (int32) InterlockedCompareExchangeNoFence((volatile long *) value, 0, 0); }
inline void atomic_decrement_acquire(volatile int64* value) { InterlockedDecrementAcquire64((LONG64 *) value); } FORCE_INLINE int64 atomic_get_relaxed(volatile int64* value) { return (int64) InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, 0, 0); }
inline void atomic_add_acquire(volatile int32* value, int32 increment) { InterlockedAddAcquire((long *) value, increment); } FORCE_INLINE f32 atomic_get_relaxed(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeNoFence((volatile long *) value, 0, 0)}; return temp.f; }
inline void atomic_sub_acquire(volatile int32* value, int32 decrement) { InterlockedAddAcquire((long *) value, -decrement); } FORCE_INLINE f64 atomic_get_relaxed(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, 0, 0)}; return temp.f; }
inline void atomic_add_acquire(volatile int64* value, int64 increment) { InterlockedAddAcquire64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE void atomic_increment_relaxed(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
inline void atomic_sub_acquire(volatile int64* value, int64 decrement) { InterlockedAddAcquire64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE void atomic_decrement_relaxed(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
inline f32 atomic_compare_exchange_weak_acquire(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeAcquire((long *) value, (long) desired, (long) *expected) }; return temp.f; } FORCE_INLINE void atomic_increment_relaxed(volatile int16* value) { InterlockedIncrementNoFence16((volatile short *) value); }
inline f64 atomic_compare_exchange_weak_acquire(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeAcquire64((LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; } FORCE_INLINE void atomic_decrement_relaxed(volatile int16* value) { InterlockedDecrementNoFence16((volatile short *) value); }
inline int32 atomic_compare_exchange_weak_acquire(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeAcquire((long *) value, desired, *expected); } FORCE_INLINE void atomic_increment_relaxed(volatile int32* value) { InterlockedIncrementNoFence((volatile long *) value); }
inline int64 atomic_compare_exchange_weak_acquire(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeAcquire64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE void atomic_decrement_relaxed(volatile int32* value) { InterlockedDecrementNoFence((volatile long *) value); }
inline int32 atomic_fetch_add_acquire(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddAcquire((long *) value, operand); } FORCE_INLINE void atomic_increment_relaxed(volatile int64* value) { InterlockedIncrementNoFence64((volatile LONG64 *) value); }
inline int32 atomic_fetch_sub_acquire(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddAcquire((unsigned long *) value, -((long) operand)); } FORCE_INLINE void atomic_decrement_relaxed(volatile int64* value) { InterlockedDecrementNoFence64((volatile LONG64 *) value); }
inline int64 atomic_fetch_add_acquire(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddAcquire64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_add_relaxed(volatile int8* value, int8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
inline int64 atomic_fetch_sub_acquire(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_sub_relaxed(volatile int8* value, int8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
inline void atomic_set_acquire(volatile uint32* value, uint32 new_value) { InterlockedExchangeAcquire((long *) value, new_value); } FORCE_INLINE void atomic_add_relaxed(volatile int16* value, int16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
inline void atomic_set_acquire(volatile uint64* value, uint64 new_value) { InterlockedExchangeAcquire64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_relaxed(volatile int16* value, int16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
inline uint32 atomic_fetch_set_acquire(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchangeAcquire((long *) value, new_value); } FORCE_INLINE void atomic_add_relaxed(volatile int32* value, int32 increment) { InterlockedAddNoFence((volatile long *) value, increment); }
inline uint64 atomic_fetch_set_acquire(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchangeAcquire64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_relaxed(volatile int32* value, int32 decrement) { InterlockedAddNoFence((volatile long *) value, -decrement); }
inline uint32 atomic_get_acquire(volatile uint32* value) { return (uint32) InterlockedCompareExchangeAcquire((long *) value, 0, 0); } FORCE_INLINE void atomic_add_relaxed(volatile int64* value, int64 increment) { InterlockedAddNoFence64((volatile LONG64 *) value, (LONG64) increment); }
inline uint64 atomic_get_acquire(volatile uint64* value) { return (uint64) InterlockedCompareExchangeAcquire64((LONG64 *) value, 0, 0); } FORCE_INLINE void atomic_sub_relaxed(volatile int64* value, int64 decrement) { InterlockedAddNoFence64((volatile LONG64 *) value, -((LONG64) decrement)); }
inline void atomic_increment_acquire(volatile uint32* value) { InterlockedIncrementAcquire((long *) value); } FORCE_INLINE f32 atomic_compare_exchange_weak_relaxed(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeNoFence((volatile long *) value, (long) desired, (long) *expected) }; return temp.f; }
inline void atomic_decrement_acquire(volatile uint32* value) { InterlockedDecrementAcquire((long *) value); } FORCE_INLINE f64 atomic_compare_exchange_weak_relaxed(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; }
inline void atomic_increment_acquire(volatile uint64* value) { InterlockedIncrementAcquire64((LONG64 *) value); } FORCE_INLINE int32 atomic_compare_exchange_weak_relaxed(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeNoFence((volatile long *) value, desired, *expected); }
inline void atomic_decrement_acquire(volatile uint64* value) { InterlockedDecrementAcquire64((LONG64 *) value); } FORCE_INLINE int64 atomic_compare_exchange_weak_relaxed(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
inline void atomic_add_acquire(volatile uint32* value, uint32 increment) { InterlockedAddAcquire((long *) value, increment); } FORCE_INLINE int8 atomic_fetch_add_relaxed(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
inline void atomic_sub_acquire(volatile uint32* value, uint32 decrement) { InterlockedAddAcquire((long *) value, -1 * ((int32) decrement)); } FORCE_INLINE int8 atomic_fetch_sub_relaxed(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
inline void atomic_add_acquire(volatile uint64* value, uint64 increment) { InterlockedAddAcquire64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE int16 atomic_fetch_add_relaxed(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
inline void atomic_sub_acquire(volatile uint64* value, uint64 decrement) { InterlockedAddAcquire64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE int16 atomic_fetch_sub_relaxed(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
inline uint32 atomic_compare_exchange_weak_acquire(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeAcquire((long *) value, desired, *expected); } FORCE_INLINE int32 atomic_fetch_add_relaxed(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddNoFence((volatile long *) value, operand); }
inline uint64 atomic_compare_exchange_weak_acquire(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeAcquire64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE int32 atomic_fetch_sub_relaxed(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddNoFence((volatile unsigned long *) value, -((long) operand)); }
inline uint32 atomic_fetch_add_acquire(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddAcquire((long *) value, operand); } FORCE_INLINE int64 atomic_fetch_add_relaxed(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddNoFence64((volatile LONG64 *) value, (LONG64) operand); }
inline uint32 atomic_fetch_sub_acquire(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddAcquire((unsigned long *) value, -((long) operand)); } FORCE_INLINE int64 atomic_fetch_sub_relaxed(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
inline uint64 atomic_fetch_add_acquire(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddAcquire64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_set_relaxed(volatile uint8* value, uint8 new_value) { InterlockedExchangeNoFence8((volatile char *) value, (char) new_value); }
inline uint64 atomic_fetch_sub_acquire(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_set_relaxed(volatile uint16* value, uint16 new_value) { InterlockedExchangeNoFence16((volatile short *) value, (short) new_value); }
inline void atomic_and_acquire(volatile uint32* value, uint32 mask) { InterlockedAndAcquire((volatile LONG *) value, mask); } FORCE_INLINE void atomic_set_relaxed(volatile uint32* value, uint32 new_value) { InterlockedExchangeNoFence((volatile long *) value, new_value); }
inline void atomic_and_acquire(volatile int32* value, int32 mask) { InterlockedAndAcquire((volatile LONG *) value, (LONG)mask); } FORCE_INLINE void atomic_set_relaxed(volatile uint64* value, uint64 new_value) { InterlockedExchangeNoFence64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_and_acquire(volatile uint64* value, uint64 mask) { InterlockedAnd64Acquire((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_fetch_set_relaxed(volatile uint8* value, uint8 new_value) { return (uint8) InterlockedExchangeNoFence8((volatile char *) value, (char) new_value); }
inline void atomic_and_acquire(volatile int64* value, int64 mask) { InterlockedAnd64Acquire((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_fetch_set_relaxed(volatile uint16* value, uint16 new_value) { return (uint16) InterlockedExchangeNoFence16((volatile short *) value, (short) new_value); }
inline void atomic_or_acquire(volatile uint32* value, uint32 mask) { InterlockedOrAcquire((volatile LONG *) value, mask); } FORCE_INLINE uint32 atomic_fetch_set_relaxed(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchangeNoFence((volatile long *) value, new_value); }
inline void atomic_or_acquire(volatile int32* value, int32 mask) { InterlockedOrAcquire((volatile LONG *) value, (LONG)mask); } FORCE_INLINE uint64 atomic_fetch_set_relaxed(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchangeNoFence64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_or_acquire(volatile uint64* value, uint64 mask) { InterlockedOr64Acquire((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_get_relaxed(volatile uint8* value) { return (uint8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_or_acquire(volatile int64* value, int64 mask) { InterlockedOr64Acquire((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_get_relaxed(volatile uint16* value) { return (uint16) InterlockedCompareExchangeNoFence16((volatile short *) value, 0, 0); }
FORCE_INLINE uint32 atomic_get_relaxed(volatile uint32* value) { return (uint32) InterlockedCompareExchangeNoFence((volatile long *) value, 0, 0); }
FORCE_INLINE uint64 atomic_get_relaxed(volatile uint64* value) { return (uint64) InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, 0, 0); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint16* value) { InterlockedIncrementNoFence16((volatile short *) value); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint16* value) { InterlockedDecrementNoFence16((volatile short *) value); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint32* value) { InterlockedIncrementNoFence((volatile long *) value); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint32* value) { InterlockedDecrementNoFence((volatile long *) value); }
FORCE_INLINE void atomic_increment_relaxed(volatile uint64* value) { InterlockedIncrementNoFence64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_decrement_relaxed(volatile uint64* value) { InterlockedDecrementNoFence64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_add_relaxed(volatile uint8* value, uint8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint8* value, uint8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
FORCE_INLINE void atomic_add_relaxed(volatile uint16* value, uint16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint16* value, uint16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
FORCE_INLINE void atomic_add_relaxed(volatile uint32* value, uint32 increment) { InterlockedAddNoFence((volatile long *) value, increment); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint32* value, uint32 decrement) { InterlockedAddNoFence((volatile long *) value, -1 * ((int32) decrement)); }
FORCE_INLINE void atomic_add_relaxed(volatile uint64* value, uint64 increment) { InterlockedAddNoFence64((volatile LONG64 *) value, (LONG64) increment); }
FORCE_INLINE void atomic_sub_relaxed(volatile uint64* value, uint64 decrement) { InterlockedAddNoFence64((volatile LONG64 *) value, -((LONG64) decrement)); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_relaxed(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeNoFence((volatile long *) value, desired, *expected); }
FORCE_INLINE uint64 atomic_compare_exchange_weak_relaxed(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeNoFence64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
FORCE_INLINE uint8 atomic_fetch_add_relaxed(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
FORCE_INLINE uint8 atomic_fetch_sub_relaxed(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
FORCE_INLINE uint16 atomic_fetch_add_relaxed(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
FORCE_INLINE uint16 atomic_fetch_sub_relaxed(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
FORCE_INLINE uint32 atomic_fetch_add_relaxed(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddNoFence((volatile long *) value, operand); }
FORCE_INLINE uint32 atomic_fetch_sub_relaxed(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddNoFence((volatile unsigned long *) value, -((long) operand)); }
FORCE_INLINE uint64 atomic_fetch_add_relaxed(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddNoFence64((volatile LONG64 *) value, (LONG64) operand); }
FORCE_INLINE uint64 atomic_fetch_sub_relaxed(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
FORCE_INLINE void atomic_and_relaxed(volatile uint8* value, uint8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile int8* value, int8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile uint16* value, uint16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile int16* value, int16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile uint32* value, uint32 mask) { InterlockedAndNoFence((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile int32* value, int32 mask) { InterlockedAndNoFence((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_and_relaxed(volatile uint64* value, uint64 mask) { InterlockedAnd64NoFence((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_and_relaxed(volatile int64* value, int64 mask) { InterlockedAnd64NoFence((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile uint8* value, uint8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile int8* value, int8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile uint16* value, uint16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile int16* value, int16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile uint32* value, uint32 mask) { InterlockedOrNoFence((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile int32* value, int32 mask) { InterlockedOrNoFence((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_or_relaxed(volatile uint64* value, uint64 mask) { InterlockedOr64NoFence((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_relaxed(volatile int64* value, int64 mask) { InterlockedOr64NoFence((volatile LONG64 *) value, mask); }
inline void atomic_set_release(void** target, void* new_pointer) { InterlockedExchangePointer(target, new_pointer); } FORCE_INLINE void atomic_set_acquire(void** target, void* new_pointer) { InterlockedExchangePointerAcquire(target, new_pointer); }
inline void* atomic_get_release(void** target) { return InterlockedCompareExchangePointerRelease(target, NULL, NULL); } FORCE_INLINE void* atomic_get_acquire(void** target) { return InterlockedCompareExchangePointerAcquire(target, NULL, NULL); }
inline void atomic_set_release(volatile int32* value, int32 new_value) { InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_set_acquire(volatile int8* value, int8 new_value) { InterlockedExchangeAcquire8((volatile char *) value, new_value); }
inline void atomic_set_release(volatile int64* value, int64 new_value) { InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_acquire(volatile int16* value, int16 new_value) { InterlockedExchangeAcquire16((volatile short *) value, new_value); }
inline void atomic_set_release(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchange((long *) value, (long) temp.l); } FORCE_INLINE void atomic_set_acquire(volatile int32* value, int32 new_value) { InterlockedExchangeAcquire((volatile long *) value, new_value); }
inline void atomic_set_release(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchange64((LONG64 *) value, (LONG64) temp.l); } FORCE_INLINE void atomic_set_acquire(volatile int64* value, int64 new_value) { InterlockedExchangeAcquire64((volatile LONG64 *) value, (LONG64) new_value); }
inline int32 atomic_fetch_set_release(volatile int32* value, int32 new_value) { return (int32) InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_set_acquire(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchangeAcquire((volatile long *) value, (long) temp.l); }
inline int64 atomic_fetch_set_release(volatile int64* value, int64 new_value) { return (int64) InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_acquire(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchangeAcquire64((volatile LONG64 *) value, (LONG64) temp.l); }
inline int32 atomic_get_release(volatile int32* value) { return (int32) InterlockedCompareExchangeRelease((long *) value, 0, 0); } FORCE_INLINE int8 atomic_fetch_set_acquire(volatile int8* value, int8 new_value) { return (int8) InterlockedExchangeAcquire8((volatile char *) value, (char) new_value); }
inline int64 atomic_get_release(volatile int64* value) { return (int64) InterlockedCompareExchangeRelease64((LONG64 *) value, 0, 0); } FORCE_INLINE int16 atomic_fetch_set_acquire(volatile int16* value, int16 new_value) { return (int16) InterlockedExchangeAcquire16((volatile short *) value, (short) new_value); }
inline f32 atomic_get_release(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeRelease((long *) value, 0, 0)}; return temp.f; } FORCE_INLINE int32 atomic_fetch_set_acquire(volatile int32* value, int32 new_value) { return (int32) InterlockedExchangeAcquire((volatile long *) value, new_value); }
inline f64 atomic_get_release(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeRelease64((LONG64 *) value, 0, 0)}; return temp.f; } FORCE_INLINE int64 atomic_fetch_set_acquire(volatile int64* value, int64 new_value) { return (int64) InterlockedExchangeAcquire64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_increment_release(volatile int32* value) { InterlockedIncrementRelease((long *) value); } FORCE_INLINE int8 atomic_get_acquire(volatile int8* value) { return (int8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_decrement_release(volatile int32* value) { InterlockedDecrementRelease((long *) value); } FORCE_INLINE int16 atomic_get_acquire(volatile int16* value) { return (int16) InterlockedCompareExchangeAcquire16((volatile short *) value, 0, 0); }
inline void atomic_increment_release(volatile int64* value) { InterlockedIncrementRelease64((LONG64 *) value); } FORCE_INLINE int32 atomic_get_acquire(volatile int32* value) { return (int32) InterlockedCompareExchangeAcquire((volatile long *) value, 0, 0); }
inline void atomic_decrement_release(volatile int64* value) { InterlockedDecrementRelease64((LONG64 *) value); } FORCE_INLINE int64 atomic_get_acquire(volatile int64* value) { return (int64) InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, 0, 0); }
inline void atomic_add_release(volatile int32* value, int32 increment) { InterlockedAddRelease((long *) value, increment); } FORCE_INLINE f32 atomic_get_acquire(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeAcquire((volatile long *) value, 0, 0)}; return temp.f; }
inline void atomic_sub_release(volatile int32* value, int32 decrement) { InterlockedAddRelease((long *) value, -decrement); } FORCE_INLINE f64 atomic_get_acquire(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, 0, 0)}; return temp.f; }
inline void atomic_add_release(volatile int64* value, int64 increment) { InterlockedAddRelease64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE void atomic_increment_acquire(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
inline void atomic_sub_release(volatile int64* value, int64 decrement) { InterlockedAddRelease64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE void atomic_decrement_acquire(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
inline f32 atomic_compare_exchange_weak_release(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeRelease((long *) value, (long) desired, (long) *expected) }; return temp.f; } FORCE_INLINE void atomic_increment_acquire(volatile int16* value) { InterlockedIncrementAcquire16((volatile short *) value); }
inline f64 atomic_compare_exchange_weak_release(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeRelease64((LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; } FORCE_INLINE void atomic_decrement_acquire(volatile int16* value) { InterlockedDecrementAcquire16((volatile short *) value); }
inline int32 atomic_compare_exchange_weak_release(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeRelease((long *) value, desired, *expected); } FORCE_INLINE void atomic_increment_acquire(volatile int32* value) { InterlockedIncrementAcquire((volatile long *) value); }
inline int64 atomic_compare_exchange_weak_release(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeRelease64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE void atomic_decrement_acquire(volatile int32* value) { InterlockedDecrementAcquire((volatile long *) value); }
inline int32 atomic_fetch_add_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddRelease((long *) value, operand); } FORCE_INLINE void atomic_increment_acquire(volatile int64* value) { InterlockedIncrementAcquire64((volatile LONG64 *) value); }
inline int32 atomic_fetch_sub_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddRelease((unsigned long *) value, -((long) operand)); } FORCE_INLINE void atomic_decrement_acquire(volatile int64* value) { InterlockedDecrementAcquire64((volatile LONG64 *) value); }
inline int64 atomic_fetch_add_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddRelease64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_add_acquire(volatile int8* value, int8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
inline int64 atomic_fetch_sub_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_sub_acquire(volatile int8* value, int8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
inline void atomic_set_release(volatile uint32* value, uint32 new_value) { InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_add_acquire(volatile int16* value, int16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
inline void atomic_set_release(volatile uint64* value, uint64 new_value) { InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_acquire(volatile int16* value, int16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
inline uint32 atomic_fetch_set_release(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_add_acquire(volatile int32* value, int32 increment) { InterlockedAddAcquire((volatile long *) value, increment); }
inline uint64 atomic_fetch_set_release(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_acquire(volatile int32* value, int32 decrement) { InterlockedAddAcquire((volatile long *) value, -decrement); }
inline uint32 atomic_get_release(volatile uint32* value) { return (uint32) InterlockedCompareExchangeRelease((long *) value, 0, 0); } FORCE_INLINE void atomic_add_acquire(volatile int64* value, int64 increment) { InterlockedAddAcquire64((volatile LONG64 *) value, (LONG64) increment); }
inline uint64 atomic_get_release(volatile uint64* value) { return (uint64) InterlockedCompareExchangeRelease64((LONG64 *) value, 0, 0); } FORCE_INLINE void atomic_sub_acquire(volatile int64* value, int64 decrement) { InterlockedAddAcquire64((volatile LONG64 *) value, -((LONG64) decrement)); }
inline void atomic_increment_release(volatile uint32* value) { InterlockedIncrementRelease((long *) value); } FORCE_INLINE f32 atomic_compare_exchange_weak_acquire(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeAcquire((volatile long *) value, (long) desired, (long) *expected) }; return temp.f; }
inline void atomic_decrement_release(volatile uint32* value) { InterlockedDecrementRelease((long *) value); } FORCE_INLINE f64 atomic_compare_exchange_weak_acquire(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; }
inline void atomic_increment_release(volatile uint64* value) { InterlockedIncrementRelease64((LONG64 *) value); } FORCE_INLINE int32 atomic_compare_exchange_weak_acquire(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeAcquire((volatile long *) value, desired, *expected); }
inline void atomic_decrement_release(volatile uint64* value) { InterlockedDecrementRelease64((LONG64 *) value); } FORCE_INLINE int64 atomic_compare_exchange_weak_acquire(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
inline void atomic_add_release(volatile uint32* value, uint32 increment) { InterlockedAddRelease((long *) value, increment); } FORCE_INLINE int8 atomic_fetch_add_acquire(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
inline void atomic_sub_release(volatile uint32* value, uint32 decrement) { InterlockedAddRelease((long *) value, -1 * ((int32) decrement)); } FORCE_INLINE int8 atomic_fetch_sub_acquire(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
inline void atomic_add_release(volatile uint64* value, uint64 increment) { InterlockedAddRelease64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE int16 atomic_fetch_add_acquire(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
inline void atomic_sub_release(volatile uint64* value, uint64 decrement) { InterlockedAddRelease64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE int16 atomic_fetch_sub_acquire(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
inline uint32 atomic_compare_exchange_weak_release(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeRelease((long *) value, desired, *expected); } FORCE_INLINE int32 atomic_fetch_add_acquire(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddAcquire((volatile long *) value, operand); }
inline uint64 atomic_compare_exchange_weak_release(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeRelease64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE int32 atomic_fetch_sub_acquire(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddAcquire((volatile unsigned long *) value, -((long) operand)); }
inline uint32 atomic_fetch_add_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddRelease((long *) value, operand); } FORCE_INLINE int64 atomic_fetch_add_acquire(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddAcquire64((volatile LONG64 *) value, (LONG64) operand); }
inline uint32 atomic_fetch_sub_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddRelease((unsigned long *) value, -((long) operand)); } FORCE_INLINE int64 atomic_fetch_sub_acquire(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
inline uint64 atomic_fetch_add_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddRelease64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_set_acquire(volatile uint8* value, uint8 new_value) { InterlockedExchangeAcquire8((volatile char *) value, (char) new_value); }
inline uint64 atomic_fetch_sub_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_set_acquire(volatile uint16* value, uint16 new_value) { InterlockedExchangeAcquire16((volatile short *) value, (short) new_value); }
inline void atomic_and_release(volatile uint32* value, uint32 mask) { InterlockedAndRelease((volatile LONG *) value, mask); } FORCE_INLINE void atomic_set_acquire(volatile uint32* value, uint32 new_value) { InterlockedExchangeAcquire((volatile long *) value, new_value); }
inline void atomic_and_release(volatile int32* value, int32 mask) { InterlockedAndRelease((volatile LONG *) value, (LONG)mask); } FORCE_INLINE void atomic_set_acquire(volatile uint64* value, uint64 new_value) { InterlockedExchangeAcquire64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_and_release(volatile uint64* value, uint64 mask) { InterlockedAnd64Release((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_fetch_set_acquire(volatile uint8* value, uint8 new_value) { return (uint8) InterlockedExchangeAcquire8((volatile char *) value, (char) new_value); }
inline void atomic_and_release(volatile int64* value, int64 mask) { InterlockedAnd64Release((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_fetch_set_acquire(volatile uint16* value, uint16 new_value) { return (uint16) InterlockedExchangeAcquire16((volatile short *) value, (short) new_value); }
inline void atomic_or_release(volatile uint32* value, uint32 mask) { InterlockedOrRelease((volatile LONG *) value, mask); } FORCE_INLINE uint32 atomic_fetch_set_acquire(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchangeAcquire((volatile long *) value, new_value); }
inline void atomic_or_release(volatile int32* value, int32 mask) { InterlockedOrRelease((volatile LONG *) value, (LONG)mask); } FORCE_INLINE uint64 atomic_fetch_set_acquire(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchangeAcquire64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_or_release(volatile uint64* value, uint64 mask) { InterlockedOr64Release((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_get_acquire(volatile uint8* value) { return (uint8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_or_release(volatile int64* value, int64 mask) { InterlockedOr64Release((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_get_acquire(volatile uint16* value) { return (uint16) InterlockedCompareExchangeAcquire16((volatile short *) value, 0, 0); }
FORCE_INLINE uint32 atomic_get_acquire(volatile uint32* value) { return (uint32) InterlockedCompareExchangeAcquire((volatile long *) value, 0, 0); }
FORCE_INLINE uint64 atomic_get_acquire(volatile uint64* value) { return (uint64) InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, 0, 0); }
FORCE_INLINE void atomic_increment_acquire(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
FORCE_INLINE void atomic_decrement_acquire(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
FORCE_INLINE void atomic_increment_acquire(volatile uint16* value) { InterlockedIncrementAcquire16((volatile short *) value); }
FORCE_INLINE void atomic_decrement_acquire(volatile uint16* value) { InterlockedDecrementAcquire16((volatile short *) value); }
FORCE_INLINE void atomic_increment_acquire(volatile uint32* value) { InterlockedIncrementAcquire((volatile long *) value); }
FORCE_INLINE void atomic_decrement_acquire(volatile uint32* value) { InterlockedDecrementAcquire((volatile long *) value); }
FORCE_INLINE void atomic_increment_acquire(volatile uint64* value) { InterlockedIncrementAcquire64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_decrement_acquire(volatile uint64* value) { InterlockedDecrementAcquire64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_add_acquire(volatile uint8* value, uint8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
FORCE_INLINE void atomic_sub_acquire(volatile uint8* value, uint8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
FORCE_INLINE void atomic_add_acquire(volatile uint16* value, uint16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
FORCE_INLINE void atomic_sub_acquire(volatile uint16* value, uint16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
FORCE_INLINE void atomic_add_acquire(volatile uint32* value, uint32 increment) { InterlockedAddAcquire((volatile long *) value, increment); }
FORCE_INLINE void atomic_sub_acquire(volatile uint32* value, uint32 decrement) { InterlockedAddAcquire((volatile long *) value, -1 * ((int32) decrement)); }
FORCE_INLINE void atomic_add_acquire(volatile uint64* value, uint64 increment) { InterlockedAddAcquire64((volatile LONG64 *) value, (LONG64) increment); }
FORCE_INLINE void atomic_sub_acquire(volatile uint64* value, uint64 decrement) { InterlockedAddAcquire64((volatile LONG64 *) value, -((LONG64) decrement)); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_acquire(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeAcquire((volatile long *) value, desired, *expected); }
FORCE_INLINE uint64 atomic_compare_exchange_weak_acquire(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeAcquire64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
FORCE_INLINE uint8 atomic_fetch_add_acquire(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
FORCE_INLINE uint8 atomic_fetch_sub_acquire(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
FORCE_INLINE uint16 atomic_fetch_add_acquire(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
FORCE_INLINE uint16 atomic_fetch_sub_acquire(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
FORCE_INLINE uint32 atomic_fetch_add_acquire(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddAcquire((volatile long *) value, operand); }
FORCE_INLINE uint32 atomic_fetch_sub_acquire(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddAcquire((volatile unsigned long *) value, -((long) operand)); }
FORCE_INLINE uint64 atomic_fetch_add_acquire(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddAcquire64((volatile LONG64 *) value, (LONG64) operand); }
FORCE_INLINE uint64 atomic_fetch_sub_acquire(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
FORCE_INLINE void atomic_and_acquire(volatile uint8* value, uint8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile int8* value, int8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile uint16* value, uint16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile int16* value, int16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile uint32* value, uint32 mask) { InterlockedAndAcquire((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile int32* value, int32 mask) { InterlockedAndAcquire((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_and_acquire(volatile uint64* value, uint64 mask) { InterlockedAnd64Acquire((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_and_acquire(volatile int64* value, int64 mask) { InterlockedAnd64Acquire((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile uint8* value, uint8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile int8* value, int8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile uint16* value, uint16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile int16* value, int16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile uint32* value, uint32 mask) { InterlockedOrAcquire((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile int32* value, int32 mask) { InterlockedOrAcquire((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_or_acquire(volatile uint64* value, uint64 mask) { InterlockedOr64Acquire((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_acquire(volatile int64* value, int64 mask) { InterlockedOr64Acquire((volatile LONG64 *) value, mask); }
inline void atomic_set_acquire_release(void** target, void* new_pointer) { InterlockedExchangePointer(target, new_pointer); } FORCE_INLINE void atomic_set_release(void** target, void* new_pointer) { InterlockedExchangePointer(target, new_pointer); }
inline void* atomic_get_acquire_release(void** target) { return InterlockedCompareExchangePointer(target, NULL, NULL); } FORCE_INLINE void* atomic_get_release(void** target) { return InterlockedCompareExchangePointerRelease(target, NULL, NULL); }
inline void atomic_set_acquire_release(volatile int32* value, int32 new_value) { InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_set_release(volatile int8* value, int8 new_value) { InterlockedExchange8((volatile char *) value, new_value); }
inline void atomic_set_acquire_release(volatile int64* value, int64 new_value) { InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_release(volatile int16* value, int16 new_value) { InterlockedExchange16((volatile short *) value, new_value); }
inline void atomic_set_acquire_release(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchange((long *) value, (long) temp.l); } FORCE_INLINE void atomic_set_release(volatile int32* value, int32 new_value) { InterlockedExchange((volatile long *) value, new_value); }
inline void atomic_set_acquire_release(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchange64((LONG64 *) value, (LONG64) temp.l); } FORCE_INLINE void atomic_set_release(volatile int64* value, int64 new_value) { InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
inline int32 atomic_fetch_set_acquire_release(volatile int32* value, int32 new_value) { return (int32) InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_set_release(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchange((volatile long *) value, (long) temp.l); }
inline int64 atomic_fetch_set_acquire_release(volatile int64* value, int64 new_value) { return (int64) InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_set_release(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchange64((volatile LONG64 *) value, (LONG64) temp.l); }
inline int32 atomic_get_acquire_release(volatile int32* value) { return (int32) InterlockedCompareExchange((long *) value, 0, 0); } FORCE_INLINE int8 atomic_fetch_set_release(volatile int8* value, int8 new_value) { return (int8) InterlockedExchange8((volatile char *) value, (char) new_value); }
inline int64 atomic_get_acquire_release(volatile int64* value) { return (int64) InterlockedCompareExchange64((LONG64 *) value, 0, 0); } FORCE_INLINE int16 atomic_fetch_set_release(volatile int16* value, int16 new_value) { return (int16) InterlockedExchange16((volatile short *) value, (short) new_value); }
inline f32 atomic_get_acquire_release(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchange((long *) value, 0, 0)}; return temp.f; } FORCE_INLINE int32 atomic_fetch_set_release(volatile int32* value, int32 new_value) { return (int32) InterlockedExchange((volatile long *) value, new_value); }
inline f64 atomic_get_acquire_release(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchange64((LONG64 *) value, 0, 0)}; return temp.f; } FORCE_INLINE int64 atomic_fetch_set_release(volatile int64* value, int64 new_value) { return (int64) InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_increment_acquire_release(volatile int32* value) { InterlockedIncrement((long *) value); } FORCE_INLINE int8 atomic_get_release(volatile int8* value) { return (int8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_decrement_acquire_release(volatile int32* value) { InterlockedDecrement((long *) value); } FORCE_INLINE int16 atomic_get_release(volatile int16* value) { return (int16) InterlockedCompareExchangeRelease16((volatile short *) value, 0, 0); }
inline void atomic_increment_acquire_release(volatile int64* value) { InterlockedIncrement64((LONG64 *) value); } FORCE_INLINE int32 atomic_get_release(volatile int32* value) { return (int32) InterlockedCompareExchangeRelease((volatile long *) value, 0, 0); }
inline void atomic_decrement_acquire_release(volatile int64* value) { InterlockedDecrement64((LONG64 *) value); } FORCE_INLINE int64 atomic_get_release(volatile int64* value) { return (int64) InterlockedCompareExchangeRelease64((volatile LONG64 *) value, 0, 0); }
inline void atomic_add_acquire_release(volatile int32* value, int32 increment) { InterlockedAdd((long *) value, increment); } FORCE_INLINE f32 atomic_get_release(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchangeRelease((volatile long *) value, 0, 0)}; return temp.f; }
inline void atomic_sub_acquire_release(volatile int32* value, int32 decrement) { InterlockedAdd((long *) value, -decrement); } FORCE_INLINE f64 atomic_get_release(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchangeRelease64((volatile LONG64 *) value, 0, 0)}; return temp.f; }
inline void atomic_add_acquire_release(volatile int64* value, int64 increment) { InterlockedAdd64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE void atomic_increment_release(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
inline void atomic_sub_acquire_release(volatile int64* value, int64 decrement) { InterlockedAdd64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE void atomic_decrement_release(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
inline f32 atomic_compare_exchange_weak_acquire_release(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchange((long *) value, (long) desired, (long) *expected) }; return temp.f; } FORCE_INLINE void atomic_increment_release(volatile int16* value) { InterlockedIncrementRelease16((volatile short *) value); }
inline f64 atomic_compare_exchange_weak_acquire_release(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchange64((LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; } FORCE_INLINE void atomic_decrement_release(volatile int16* value) { InterlockedDecrementRelease16((volatile short *) value); }
inline int32 atomic_compare_exchange_weak_acquire_release(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchange((long *) value, desired, *expected); } FORCE_INLINE void atomic_increment_release(volatile int32* value) { InterlockedIncrementRelease((volatile long *) value); }
inline int64 atomic_compare_exchange_weak_acquire_release(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchange64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE void atomic_decrement_release(volatile int32* value) { InterlockedDecrementRelease((volatile long *) value); }
inline int32 atomic_fetch_add_acquire_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAdd((long *) value, operand); } FORCE_INLINE void atomic_increment_release(volatile int64* value) { InterlockedIncrementRelease64((volatile LONG64 *) value); }
inline int32 atomic_fetch_sub_acquire_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAdd((unsigned long *) value, -((long) operand)); } FORCE_INLINE void atomic_decrement_release(volatile int64* value) { InterlockedDecrementRelease64((volatile LONG64 *) value); }
inline int64 atomic_fetch_add_acquire_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_add_release(volatile int8* value, int8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
inline int64 atomic_fetch_sub_acquire_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_sub_release(volatile int8* value, int8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
inline void atomic_set_acquire_release(volatile uint32* value, uint32 new_value) { InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_add_release(volatile int16* value, int16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
inline void atomic_set_acquire_release(volatile uint64* value, uint64 new_value) { InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_release(volatile int16* value, int16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
inline uint32 atomic_fetch_set_acquire_release(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchange((long *) value, new_value); } FORCE_INLINE void atomic_add_release(volatile int32* value, int32 increment) { InterlockedAddRelease((volatile long *) value, increment); }
inline uint64 atomic_fetch_set_acquire_release(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchange64((LONG64 *) value, (LONG64) new_value); } FORCE_INLINE void atomic_sub_release(volatile int32* value, int32 decrement) { InterlockedAddRelease((volatile long *) value, -decrement); }
inline uint32 atomic_get_acquire_release(volatile uint32* value) { return (uint32) InterlockedCompareExchange((long *) value, 0, 0); } FORCE_INLINE void atomic_add_release(volatile int64* value, int64 increment) { InterlockedAddRelease64((volatile LONG64 *) value, (LONG64) increment); }
inline uint64 atomic_get_acquire_release(volatile uint64* value) { return (uint64) InterlockedCompareExchange64((LONG64 *) value, 0, 0); } FORCE_INLINE void atomic_sub_release(volatile int64* value, int64 decrement) { InterlockedAddRelease64((volatile LONG64 *) value, -((LONG64) decrement)); }
inline void atomic_increment_acquire_release(volatile uint32* value) { InterlockedIncrement((long *) value); } FORCE_INLINE f32 atomic_compare_exchange_weak_release(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchangeRelease((volatile long *) value, (long) desired, (long) *expected) }; return temp.f; }
inline void atomic_decrement_acquire_release(volatile uint32* value) { InterlockedDecrement((long *) value); } FORCE_INLINE f64 atomic_compare_exchange_weak_release(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchangeRelease64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; }
inline void atomic_increment_acquire_release(volatile uint64* value) { InterlockedIncrement64((LONG64 *) value); } FORCE_INLINE int32 atomic_compare_exchange_weak_release(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchangeRelease((volatile long *) value, desired, *expected); }
inline void atomic_decrement_acquire_release(volatile uint64* value) { InterlockedDecrement64((LONG64 *) value); } FORCE_INLINE int64 atomic_compare_exchange_weak_release(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchangeRelease64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
inline void atomic_add_acquire_release(volatile uint32* value, uint32 increment) { InterlockedAdd((long *) value, increment); } FORCE_INLINE int8 atomic_fetch_add_release(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
inline void atomic_sub_acquire_release(volatile uint32* value, uint32 decrement) { InterlockedAdd((long *) value, -1 * ((int32) decrement)); } FORCE_INLINE int8 atomic_fetch_sub_release(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
inline void atomic_add_acquire_release(volatile uint64* value, uint64 increment) { InterlockedAdd64((LONG64 *) value, (LONG64) increment); } FORCE_INLINE int16 atomic_fetch_add_release(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
inline void atomic_sub_acquire_release(volatile uint64* value, uint64 decrement) { InterlockedAdd64((LONG64 *) value, -((LONG64) decrement)); } FORCE_INLINE int16 atomic_fetch_sub_release(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
inline uint32 atomic_compare_exchange_weak_acquire_release(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchange((long *) value, desired, *expected); } FORCE_INLINE int32 atomic_fetch_add_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddRelease((volatile long *) value, operand); }
inline uint64 atomic_compare_exchange_weak_acquire_release(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchange64((LONG64 *) value, (LONG64) desired, (LONG64) *expected); } FORCE_INLINE int32 atomic_fetch_sub_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAddRelease((volatile unsigned long *) value, -((long) operand)); }
inline uint32 atomic_fetch_add_acquire_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAdd((long *) value, operand); } FORCE_INLINE int64 atomic_fetch_add_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAddRelease64((volatile LONG64 *) value, (LONG64) operand); }
inline uint32 atomic_fetch_sub_acquire_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAdd((unsigned long *) value, -((long) operand)); } FORCE_INLINE int64 atomic_fetch_sub_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
inline uint64 atomic_fetch_add_acquire_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((LONG64 *) value, (LONG64) operand); } FORCE_INLINE void atomic_set_release(volatile uint8* value, uint8 new_value) { InterlockedExchange8((volatile char *) value, (char) new_value); }
inline uint64 atomic_fetch_sub_acquire_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((LONG64 *) value, -((LONG64) operand)); } FORCE_INLINE void atomic_set_release(volatile uint16* value, uint16 new_value) { InterlockedExchange16((volatile short *) value, (short) new_value); }
inline void atomic_and_acquire_release(volatile uint32* value, uint32 mask) { InterlockedAnd((volatile LONG *) value, mask); } FORCE_INLINE void atomic_set_release(volatile uint32* value, uint32 new_value) { InterlockedExchange((volatile long *) value, new_value); }
inline void atomic_and_acquire_release(volatile int32* value, int32 mask) { InterlockedAnd((volatile LONG *) value, (LONG)mask); } FORCE_INLINE void atomic_set_release(volatile uint64* value, uint64 new_value) { InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_and_acquire_release(volatile uint64* value, uint64 mask) { InterlockedAnd64((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_fetch_set_release(volatile uint8* value, uint8 new_value) { return (uint8) InterlockedExchange8((volatile char *) value, (char) new_value); }
inline void atomic_and_acquire_release(volatile int64* value, int64 mask) { InterlockedAnd64((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_fetch_set_release(volatile uint16* value, uint16 new_value) { return (uint16) InterlockedExchange16((volatile short *) value, (short) new_value); }
inline void atomic_or_acquire_release(volatile uint32* value, uint32 mask) { InterlockedOr((volatile LONG *) value, mask); } FORCE_INLINE uint32 atomic_fetch_set_release(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchange((volatile long *) value, new_value); }
inline void atomic_or_acquire_release(volatile int32* value, int32 mask) { InterlockedOr((volatile LONG *) value, (LONG)mask); } FORCE_INLINE uint64 atomic_fetch_set_release(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
inline void atomic_or_acquire_release(volatile uint64* value, uint64 mask) { InterlockedOr64((volatile LONG64 *) value, mask); } FORCE_INLINE uint8 atomic_get_release(volatile uint8* value) { return (uint8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
inline void atomic_or_acquire_release(volatile int64* value, int64 mask) { InterlockedOr64((volatile LONG64 *) value, mask); } FORCE_INLINE uint16 atomic_get_release(volatile uint16* value) { return (uint16) InterlockedCompareExchangeRelease16((volatile short *) value, 0, 0); }
FORCE_INLINE uint32 atomic_get_release(volatile uint32* value) { return (uint32) InterlockedCompareExchangeRelease((volatile long *) value, 0, 0); }
FORCE_INLINE uint64 atomic_get_release(volatile uint64* value) { return (uint64) InterlockedCompareExchangeRelease64((volatile LONG64 *) value, 0, 0); }
FORCE_INLINE void atomic_increment_release(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
FORCE_INLINE void atomic_decrement_release(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
FORCE_INLINE void atomic_increment_release(volatile uint16* value) { InterlockedIncrementRelease16((volatile short *) value); }
FORCE_INLINE void atomic_decrement_release(volatile uint16* value) { InterlockedDecrementRelease16((volatile short *) value); }
FORCE_INLINE void atomic_increment_release(volatile uint32* value) { InterlockedIncrementRelease((volatile long *) value); }
FORCE_INLINE void atomic_decrement_release(volatile uint32* value) { InterlockedDecrementRelease((volatile long *) value); }
FORCE_INLINE void atomic_increment_release(volatile uint64* value) { InterlockedIncrementRelease64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_decrement_release(volatile uint64* value) { InterlockedDecrementRelease64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_add_release(volatile uint8* value, uint8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
FORCE_INLINE void atomic_sub_release(volatile uint8* value, uint8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
FORCE_INLINE void atomic_add_release(volatile uint16* value, uint16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
FORCE_INLINE void atomic_sub_release(volatile uint16* value, uint16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
FORCE_INLINE void atomic_add_release(volatile uint32* value, uint32 increment) { InterlockedAddRelease((volatile long *) value, increment); }
FORCE_INLINE void atomic_sub_release(volatile uint32* value, uint32 decrement) { InterlockedAddRelease((volatile long *) value, -1 * ((int32) decrement)); }
FORCE_INLINE void atomic_add_release(volatile uint64* value, uint64 increment) { InterlockedAddRelease64((volatile LONG64 *) value, (LONG64) increment); }
FORCE_INLINE void atomic_sub_release(volatile uint64* value, uint64 decrement) { InterlockedAddRelease64((volatile LONG64 *) value, -((LONG64) decrement)); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_release(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchangeRelease((volatile long *) value, desired, *expected); }
FORCE_INLINE uint64 atomic_compare_exchange_weak_release(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchangeRelease64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
FORCE_INLINE uint8 atomic_fetch_add_release(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
FORCE_INLINE uint8 atomic_fetch_sub_release(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
FORCE_INLINE uint16 atomic_fetch_add_release(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
FORCE_INLINE uint16 atomic_fetch_sub_release(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
FORCE_INLINE uint32 atomic_fetch_add_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddRelease((volatile long *) value, operand); }
FORCE_INLINE uint32 atomic_fetch_sub_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAddRelease((volatile unsigned long *) value, -((long) operand)); }
FORCE_INLINE uint64 atomic_fetch_add_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAddRelease64((volatile LONG64 *) value, (LONG64) operand); }
FORCE_INLINE uint64 atomic_fetch_sub_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
FORCE_INLINE void atomic_and_release(volatile uint8* value, uint8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile int8* value, int8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile uint16* value, uint16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile int16* value, int16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile uint32* value, uint32 mask) { InterlockedAndRelease((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile int32* value, int32 mask) { InterlockedAndRelease((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_and_release(volatile uint64* value, uint64 mask) { InterlockedAnd64Release((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_and_release(volatile int64* value, int64 mask) { InterlockedAnd64Release((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile uint8* value, uint8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile int8* value, int8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile uint16* value, uint16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile int16* value, int16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile uint32* value, uint32 mask) { InterlockedOrRelease((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile int32* value, int32 mask) { InterlockedOrRelease((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_or_release(volatile uint64* value, uint64 mask) { InterlockedOr64Release((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_release(volatile int64* value, int64 mask) { InterlockedOr64Release((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_set_acquire_release(void** target, void* new_pointer) { InterlockedExchangePointer(target, new_pointer); }
FORCE_INLINE void* atomic_get_acquire_release(void** target) { return InterlockedCompareExchangePointer(target, NULL, NULL); }
FORCE_INLINE void atomic_set_acquire_release(volatile int8* value, int8 new_value) { InterlockedExchange8((volatile char *) value, new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile int16* value, int16 new_value) { InterlockedExchange16((volatile short *) value, new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile int32* value, int32 new_value) { InterlockedExchange((volatile long *) value, new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile int64* value, int64 new_value) { InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile f32* value, f32 new_value) { _atomic_32 temp = {.f = new_value}; InterlockedExchange((volatile long *) value, (long) temp.l); }
FORCE_INLINE void atomic_set_acquire_release(volatile f64* value, f64 new_value) { _atomic_64 temp = {.f = new_value}; InterlockedExchange64((volatile LONG64 *) value, (LONG64) temp.l); }
FORCE_INLINE int8 atomic_fetch_set_acquire_release(volatile int8* value, int8 new_value) { return (int8) InterlockedExchange8((volatile char *) value, (char) new_value); }
FORCE_INLINE int16 atomic_fetch_set_acquire_release(volatile int16* value, int16 new_value) { return (int16) InterlockedExchange16((volatile short *) value, (short) new_value); }
FORCE_INLINE int32 atomic_fetch_set_acquire_release(volatile int32* value, int32 new_value) { return (int32) InterlockedExchange((volatile long *) value, new_value); }
FORCE_INLINE int64 atomic_fetch_set_acquire_release(volatile int64* value, int64 new_value) { return (int64) InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
FORCE_INLINE int8 atomic_get_acquire_release(volatile int8* value) { return (int8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
FORCE_INLINE int16 atomic_get_acquire_release(volatile int16* value) { return (int16) InterlockedCompareExchange16((volatile short *) value, 0, 0); }
FORCE_INLINE int32 atomic_get_acquire_release(volatile int32* value) { return (int32) InterlockedCompareExchange((volatile long *) value, 0, 0); }
FORCE_INLINE int64 atomic_get_acquire_release(volatile int64* value) { return (int64) InterlockedCompareExchange64((volatile LONG64 *) value, 0, 0); }
FORCE_INLINE f32 atomic_get_acquire_release(volatile f32* value) { _atomic_32 temp = {.l = InterlockedCompareExchange((volatile long *) value, 0, 0)}; return temp.f; }
FORCE_INLINE f64 atomic_get_acquire_release(volatile f64* value) { _atomic_64 temp = {.l = InterlockedCompareExchange64((volatile LONG64 *) value, 0, 0)}; return temp.f; }
FORCE_INLINE void atomic_increment_acquire_release(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile int8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
FORCE_INLINE void atomic_increment_acquire_release(volatile int16* value) { InterlockedIncrement16((volatile short *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile int16* value) { InterlockedDecrement16((volatile short *) value); }
FORCE_INLINE void atomic_increment_acquire_release(volatile int32* value) { InterlockedIncrement((volatile long *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile int32* value) { InterlockedDecrement((volatile long *) value); }
FORCE_INLINE void atomic_increment_acquire_release(volatile int64* value) { InterlockedIncrement64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile int64* value) { InterlockedDecrement64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_add_acquire_release(volatile int8* value, int8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile int8* value, int8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
FORCE_INLINE void atomic_add_acquire_release(volatile int16* value, int16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile int16* value, int16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
FORCE_INLINE void atomic_add_acquire_release(volatile int32* value, int32 increment) { InterlockedAdd((volatile long *) value, increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile int32* value, int32 decrement) { InterlockedAdd((volatile long *) value, -decrement); }
FORCE_INLINE void atomic_add_acquire_release(volatile int64* value, int64 increment) { InterlockedAdd64((volatile LONG64 *) value, (LONG64) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile int64* value, int64 decrement) { InterlockedAdd64((volatile LONG64 *) value, -((LONG64) decrement)); }
FORCE_INLINE f32 atomic_compare_exchange_weak_acquire_release(volatile f32* value, f32* expected, f32 desired) { _atomic_32 temp = {.l = InterlockedCompareExchange((volatile long *) value, (long) desired, (long) *expected) }; return temp.f; }
FORCE_INLINE f64 atomic_compare_exchange_weak_acquire_release(volatile f64* value, f64* expected, f64 desired) { _atomic_64 temp = {.l = InterlockedCompareExchange64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected) }; return temp.f; }
FORCE_INLINE int32 atomic_compare_exchange_weak_acquire_release(volatile int32* value, int32* expected, int32 desired) { return (int32) InterlockedCompareExchange((volatile long *) value, desired, *expected); }
FORCE_INLINE int64 atomic_compare_exchange_weak_acquire_release(volatile int64* value, int64* expected, int64 desired) { return (int64) InterlockedCompareExchange64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
FORCE_INLINE int8 atomic_fetch_add_acquire_release(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
FORCE_INLINE int8 atomic_fetch_sub_acquire_release(volatile int8* value, int8 operand) { return (int8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
FORCE_INLINE int16 atomic_fetch_add_acquire_release(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
FORCE_INLINE int16 atomic_fetch_sub_acquire_release(volatile int16* value, int16 operand) { return (int16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
FORCE_INLINE int32 atomic_fetch_add_acquire_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAdd((volatile long *) value, operand); }
FORCE_INLINE int32 atomic_fetch_sub_acquire_release(volatile int32* value, int32 operand) { return (int32) InterlockedExchangeAdd((volatile unsigned long *) value, -((long) operand)); }
FORCE_INLINE int64 atomic_fetch_add_acquire_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((volatile LONG64 *) value, (LONG64) operand); }
FORCE_INLINE int64 atomic_fetch_sub_acquire_release(volatile int64* value, int64 operand) { return (int64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
FORCE_INLINE void atomic_set_acquire_release(volatile uint8* value, uint8 new_value) { InterlockedExchange8((volatile char *) value, (char) new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile uint16* value, uint16 new_value) { InterlockedExchange16((volatile short *) value, (short) new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile uint32* value, uint32 new_value) { InterlockedExchange((volatile long *) value, new_value); }
FORCE_INLINE void atomic_set_acquire_release(volatile uint64* value, uint64 new_value) { InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
FORCE_INLINE uint8 atomic_fetch_set_acquire_release(volatile uint8* value, uint8 new_value) { return (uint8) InterlockedExchange8((volatile char *) value, (char) new_value); }
FORCE_INLINE uint16 atomic_fetch_set_acquire_release(volatile uint16* value, uint16 new_value) { return (uint16) InterlockedExchange16((volatile short *) value, (short) new_value); }
FORCE_INLINE uint32 atomic_fetch_set_acquire_release(volatile uint32* value, uint32 new_value) { return (uint32) InterlockedExchange((volatile long *) value, new_value); }
FORCE_INLINE uint64 atomic_fetch_set_acquire_release(volatile uint64* value, uint64 new_value) { return (uint64) InterlockedExchange64((volatile LONG64 *) value, (LONG64) new_value); }
FORCE_INLINE uint8 atomic_get_acquire_release(volatile uint8* value) { return (uint8) _InterlockedCompareExchange8((volatile char *) value, 0, 0); }
FORCE_INLINE uint16 atomic_get_acquire_release(volatile uint16* value) { return (uint16) InterlockedCompareExchange16((volatile short *) value, 0, 0); }
FORCE_INLINE uint32 atomic_get_acquire_release(volatile uint32* value) { return (uint32) InterlockedCompareExchange((volatile long *) value, 0, 0); }
FORCE_INLINE uint64 atomic_get_acquire_release(volatile uint64* value) { return (uint64) InterlockedCompareExchange64((volatile LONG64 *) value, 0, 0); }
FORCE_INLINE void atomic_increment_acquire_release(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, 1); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile uint8* value) { InterlockedExchangeAdd8((volatile char *) value, -1); }
FORCE_INLINE void atomic_increment_acquire_release(volatile uint16* value) { InterlockedIncrement16((volatile short *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile uint16* value) { InterlockedDecrement16((volatile short *) value); }
FORCE_INLINE void atomic_increment_acquire_release(volatile uint32* value) { InterlockedIncrement((volatile long *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile uint32* value) { InterlockedDecrement((volatile long *) value); }
FORCE_INLINE void atomic_increment_acquire_release(volatile uint64* value) { InterlockedIncrement64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_decrement_acquire_release(volatile uint64* value) { InterlockedDecrement64((volatile LONG64 *) value); }
FORCE_INLINE void atomic_add_acquire_release(volatile uint8* value, uint8 increment) { InterlockedExchangeAdd8((volatile char *) value, (char) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile uint8* value, uint8 decrement) { InterlockedExchangeAdd8((volatile char *) value, -((char) decrement)); }
FORCE_INLINE void atomic_add_acquire_release(volatile uint16* value, uint16 increment) { InterlockedExchangeAdd16((volatile short *) value, (short) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile uint16* value, uint16 decrement) { InterlockedExchangeAdd16((volatile short *) value, -((short) decrement)); }
FORCE_INLINE void atomic_add_acquire_release(volatile uint32* value, uint32 increment) { InterlockedAdd((volatile long *) value, increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile uint32* value, uint32 decrement) { InterlockedAdd((volatile long *) value, -1 * ((int32) decrement)); }
FORCE_INLINE void atomic_add_acquire_release(volatile uint64* value, uint64 increment) { InterlockedAdd64((volatile LONG64 *) value, (LONG64) increment); }
FORCE_INLINE void atomic_sub_acquire_release(volatile uint64* value, uint64 decrement) { InterlockedAdd64((volatile LONG64 *) value, -((LONG64) decrement)); }
FORCE_INLINE uint32 atomic_compare_exchange_weak_acquire_release(volatile uint32* value, uint32* expected, uint32 desired) { return (uint32) InterlockedCompareExchange((volatile long *) value, desired, *expected); }
FORCE_INLINE uint64 atomic_compare_exchange_weak_acquire_release(volatile uint64* value, uint64* expected, uint64 desired) { return (uint64) InterlockedCompareExchange64((volatile LONG64 *) value, (LONG64) desired, (LONG64) *expected); }
FORCE_INLINE uint8 atomic_fetch_add_acquire_release(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, (char) operand); }
FORCE_INLINE uint8 atomic_fetch_sub_acquire_release(volatile uint8* value, uint8 operand) { return (uint8) InterlockedExchangeAdd8((volatile char *) value, -((char) operand)); }
FORCE_INLINE uint16 atomic_fetch_add_acquire_release(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, (short) operand); }
FORCE_INLINE uint16 atomic_fetch_sub_acquire_release(volatile uint16* value, uint16 operand) { return (uint16) InterlockedExchangeAdd16((volatile short *) value, -((short) operand)); }
FORCE_INLINE uint32 atomic_fetch_add_acquire_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAdd((volatile long *) value, operand); }
FORCE_INLINE uint32 atomic_fetch_sub_acquire_release(volatile uint32* value, uint32 operand) { return (uint32) InterlockedExchangeAdd((volatile unsigned long *) value, -((long) operand)); }
FORCE_INLINE uint64 atomic_fetch_add_acquire_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((volatile LONG64 *) value, (LONG64) operand); }
FORCE_INLINE uint64 atomic_fetch_sub_acquire_release(volatile uint64* value, uint64 operand) { return (uint64) InterlockedExchangeAdd64((volatile LONG64 *) value, -((LONG64) operand)); }
FORCE_INLINE void atomic_and_acquire_release(volatile uint8* value, uint8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile int8* value, int8 mask) { InterlockedAnd8((volatile char *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile uint16* value, uint16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile int16* value, int16 mask) { InterlockedAnd16((volatile short *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile uint32* value, uint32 mask) { InterlockedAnd((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile int32* value, int32 mask) { InterlockedAnd((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile uint64* value, uint64 mask) { InterlockedAnd64((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_and_acquire_release(volatile int64* value, int64 mask) { InterlockedAnd64((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile uint8* value, uint8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile int8* value, int8 mask) { InterlockedOr8((volatile char *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile uint16* value, uint16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile int16* value, int16 mask) { InterlockedOr16((volatile short *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile uint32* value, uint32 mask) { InterlockedOr((volatile LONG *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile int32* value, int32 mask) { InterlockedOr((volatile LONG *) value, (LONG)mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile uint64* value, uint64 mask) { InterlockedOr64((volatile LONG64 *) value, mask); }
FORCE_INLINE void atomic_or_acquire_release(volatile int64* value, int64 mask) { InterlockedOr64((volatile LONG64 *) value, mask); }
// Check out the intrinsic functions fence_memory and fence_write // Check out the intrinsic functions fence_memory and fence_write
// These are much faster and could accomplish what you are doing // These are much faster and could accomplish what you are doing

View File

@ -42,6 +42,8 @@ typedef uintptr_t umm;
typedef intptr_t smm; typedef intptr_t smm;
// @question consider to implement atomic_16 depending on intrinsic support // @question consider to implement atomic_16 depending on intrinsic support
#define atomic_8 volatile
#define atomic_16 alignas(2) volatile
#define atomic_32 alignas(4) volatile #define atomic_32 alignas(4) volatile
#define atomic_64 alignas(8) volatile #define atomic_64 alignas(8) volatile

View File

@ -60,11 +60,8 @@ static void test_layout_from_theme() {
theme2.data = (byte *) platform_alloc(2 * MEGABYTE); theme2.data = (byte *) platform_alloc(2 * MEGABYTE);
theme_from_file_txt(&theme2, "./../../GameEditor/assets/themes/default/scene1.themetxt", &ring); theme_from_file_txt(&theme2, "./../../GameEditor/assets/themes/default/scene1.themetxt", &ring);
Camera camera = {}; layout_from_theme(&layout, &theme1);
camera.viewport_width = 1024; layout_from_theme(&layout, &theme2);
camera.viewport_height = 768;
layout_from_theme(&layout, &theme1, &camera);
layout_from_theme(&layout, &theme2, &camera);
UIElement* element = layout_get_element(&layout, "cmd_window"); UIElement* element = layout_get_element(&layout, "cmd_window");
ASSERT_NOT_EQUALS(element, NULL); ASSERT_NOT_EQUALS(element, NULL);

View File

@ -52,15 +52,17 @@ enum UIElementState : byte {
struct UIElement { struct UIElement {
// @see UIElementState // @see UIElementState
byte state_flag; byte state_flag;
// Used for grouping ui elements (e.g. const ui elements, fairly static elements, dynamic elements)
// Children are still checked even if a parent doesn't match the category (e.g. a static window may still have dynamic content)
byte category;
UIElementType type; UIElementType type;
// Used to keep track of the current state (= _old) and the next state or state we are transitioning into // Used to keep track of the current state (= _old) and the next state or state we are transitioning into
UIStyleType style_old; UIStyleType style_old;
UIStyleType style_new; UIStyleType style_new;
// Used for grouping ui elements (e.g. const ui elements, fairly static elements, dynamic elements)
byte category;
f32 zindex; f32 zindex;
// Some elements need information from their parent element // Some elements need information from their parent element
@ -111,15 +113,15 @@ struct UIElement {
// Cache // Cache
////////////////////////////////////// //////////////////////////////////////
// We cache the last UI element rendering for re-use in the next frame
// @question There might be custom UI elements which need more than 2^16 vertices
uint16 vertex_count;
// The max vertex count is defined in the theme file // The max vertex count is defined in the theme file
uint16 vertex_count_max; uint16 vertex_count_max;
// We cache the last UI element rendering for re-use in the next frame
// @question There might be custom UI elements which need more than 2^16 vertices
uint16 vertex_count_active;
// Offset into the vertex array (NOT in bytes but in vertices) // Offset into the vertex array (NOT in bytes but in vertices)
uint32 vertices_active; uint32 vertices_active_offset;
}; };
#endif #endif

View File

@ -145,35 +145,37 @@ void ui_input_element_unserialize(UIInput* __restrict details, const byte** __re
void ui_input_element_populate( void ui_input_element_populate(
UILayout* layout, UILayout* layout,
UIElement* element,
const UIAttributeGroup* __restrict group, const UIAttributeGroup* __restrict group,
UIInput* __restrict input, UIInput* __restrict input
UIElement* parent,
EvaluatorVariable* __restrict variables
) { ) {
if (parent) { v4_f32 parent_dimension = {};
if (element->parent) {
UIElement* parent = element->parent ? (UIElement *) (layout->data + element->parent) : NULL;
// @bug How to ensure that the parent is initialized before the child element // @bug How to ensure that the parent is initialized before the child element
// Currently the order of the initialization depends on the theme file, NOT the layout file // Currently the order of the initialization depends on the theme file, NOT the layout file
// We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles // We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles
// The reason for these misses are, that often only 1-2 style_types exist per element // The reason for these misses are, that often only 1-2 style_types exist per element
v4_f32* parent_dimension;
switch (parent->type) { switch (parent->type) {
case UI_ELEMENT_TYPE_VIEW_WINDOW: { case UI_ELEMENT_TYPE_VIEW_WINDOW: {
UIWindow* parent_window = (UIWindow *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIWindow* parent_window = (UIWindow *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_window->dimension.dimension; parent_dimension = parent_window->dimension.dimension;
} break; } break;
case UI_ELEMENT_TYPE_VIEW_PANEL: { case UI_ELEMENT_TYPE_VIEW_PANEL: {
UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_window->dimension.dimension; parent_dimension = parent_window->dimension.dimension;
} break; } break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
}
variables[2].value = parent_dimension->x; if (!element->vertices_active_offset && !element->vertex_count_max) {
variables[3].value = parent_dimension->y; element->vertices_active_offset = layout->active_vertex_offset;
variables[4].value = parent_dimension->width; UIAttribute* vertex_attr = ui_attribute_from_group(group, UI_ATTRIBUTE_TYPE_VERTEX_COUNT);
variables[5].value = parent_dimension->height; element->vertex_count_max = (uint16) (vertex_attr ? vertex_attr->value_int : 8);
layout->active_vertex_offset += element->vertex_count_max;
} }
UIAttribute* attributes = (UIAttribute *) (group + 1); UIAttribute* attributes = (UIAttribute *) (group + 1);
@ -185,7 +187,7 @@ void ui_input_element_populate(
case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH:
case UI_ATTRIBUTE_TYPE_POSITION_Y: case UI_ATTRIBUTE_TYPE_POSITION_Y:
case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: { case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: {
ui_theme_assign_dimension(&input->dimension, &attributes[i], 6, variables); ui_theme_assign_dimension(&input->dimension, &attributes[i]);
} break; } break;
} }
} }
@ -204,7 +206,7 @@ int32 ui_input_element_update(UILayout* layout, UIElement* element)
// Border // Border
if (input->border.thickness) { if (input->border.thickness) {
idx += vertex_rect_create( idx += vertex_rect_create(
layout->vertices_active + element->vertices_active, zindex, layout->vertices_active + element->vertices_active_offset, zindex,
dimension, input->dimension.alignment, dimension, input->dimension.alignment,
input->border.color input->border.color
); );
@ -222,7 +224,7 @@ int32 ui_input_element_update(UILayout* layout, UIElement* element)
// Background // Background
if (input->background.background_color) { if (input->background.background_color) {
idx += vertex_rect_create( idx += vertex_rect_create(
layout->vertices_active + element->vertices_active + idx, zindex, layout->vertices_active + element->vertices_active_offset + idx, zindex,
dimension, input->dimension.alignment, dimension, input->dimension.alignment,
input->background.background_color input->background.background_color
); );
@ -238,13 +240,13 @@ int32 ui_input_element_update(UILayout* layout, UIElement* element)
idx += ui_cursor_element_update(layout, cursor_element); idx += ui_cursor_element_update(layout, cursor_element);
memcpy( memcpy(
layout->vertices_active + element->vertices_active + idx, layout->vertices_active + element->vertices_active_offset + idx,
layout->vertices_active + cursor_element->vertices_active, layout->vertices_active + cursor_element->vertices_active_offset,
cursor_element->vertex_count * sizeof(*(layout->vertices_active)) cursor_element->vertex_count_active * sizeof(*(layout->vertices_active))
); );
} }
element->vertex_count = (uint16) idx; element->vertex_count_active = (uint16) idx;
return idx; return idx;
} }

View File

@ -52,43 +52,51 @@ void ui_label_element_unserialize(UILabel* __restrict details, const byte** __re
void ui_label_element_populate( void ui_label_element_populate(
UILayout* layout, UILayout* layout,
UIElement* element,
const UIAttributeGroup* __restrict group, const UIAttributeGroup* __restrict group,
UILabel* __restrict label, UILabel* __restrict label
UIElement* parent,
EvaluatorVariable* __restrict variables
) { ) {
if (parent) { v4_f32 parent_dimension = {};
if (element->parent) {
UIElement* parent = element->parent ? (UIElement *) (layout->data + element->parent) : NULL;
// @bug How to ensure that the parent is initialized before the child element // @bug How to ensure that the parent is initialized before the child element
// Currently the order of the initialization depends on the theme file, NOT the layout file // Currently the order of the initialization depends on the theme file, NOT the layout file
// We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles // We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles
// The reason for these misses are, that often only 1-2 style_types exist per element // The reason for these misses are, that often only 1-2 style_types exist per element
v4_f32* parent_dimension;
switch (parent->type) { switch (parent->type) {
case UI_ELEMENT_TYPE_VIEW_WINDOW: { case UI_ELEMENT_TYPE_VIEW_WINDOW: {
UIWindow* parent_window = (UIWindow *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIWindow* parent_window = (UIWindow *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_window->dimension.dimension; parent_dimension = parent_window->dimension.dimension;
} break; } break;
case UI_ELEMENT_TYPE_VIEW_PANEL: { case UI_ELEMENT_TYPE_VIEW_PANEL: {
UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_window->dimension.dimension; parent_dimension = parent_window->dimension.dimension;
} break; } break;
case UI_ELEMENT_TYPE_BUTTON: { case UI_ELEMENT_TYPE_BUTTON: {
UIButton* parent_button = (UIButton *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIButton* parent_button = (UIButton *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_button->dimension.dimension; parent_dimension = parent_button->dimension.dimension;
} break; } break;
case UI_ELEMENT_TYPE_INPUT: { case UI_ELEMENT_TYPE_INPUT: {
UIInput* parent_input = (UIInput *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIInput* parent_input = (UIInput *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_input->dimension.dimension; parent_dimension = parent_input->dimension.dimension;
} break; } break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
}
variables[2].value = parent_dimension->x; if (!element->vertices_active_offset && !element->vertex_count_max) {
variables[3].value = parent_dimension->y; element->vertices_active_offset = layout->active_vertex_offset;
variables[4].value = parent_dimension->width; UIAttribute* vertex_attr = ui_attribute_from_group(group, UI_ATTRIBUTE_TYPE_VERTEX_COUNT);
variables[5].value = parent_dimension->height;
if (vertex_attr) {
element->vertex_count_max = (uint16) vertex_attr->value_int;
} else {
// @todo Use state to calculate vertex_count_max (2 * max string length)
element->vertex_count_max = 128;
}
layout->active_vertex_offset += element->vertex_count_max;
} }
UIAttribute* attributes = (UIAttribute *) (group + 1); UIAttribute* attributes = (UIAttribute *) (group + 1);
@ -100,7 +108,7 @@ void ui_label_element_populate(
case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH:
case UI_ATTRIBUTE_TYPE_POSITION_Y: case UI_ATTRIBUTE_TYPE_POSITION_Y:
case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: { case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: {
ui_theme_assign_dimension(&label->dimension, &attributes[i], 6, variables); ui_theme_assign_dimension(&label->dimension, &attributes[i]);
} break; } break;
case UI_ATTRIBUTE_TYPE_FONT_NAME: case UI_ATTRIBUTE_TYPE_FONT_NAME:
case UI_ATTRIBUTE_TYPE_FONT_COLOR: case UI_ATTRIBUTE_TYPE_FONT_COLOR:
@ -119,7 +127,7 @@ int32 ui_label_element_update(UILayout* layout, UIElement* element)
UILabelState* state = (UILabelState *) (layout->data + element->state); UILabelState* state = (UILabelState *) (layout->data + element->state);
return vertex_text_create( return vertex_text_create(
layout->vertices_active + element->vertices_active, element->zindex, layout->vertices_active + element->vertices_active_offset, element->zindex,
label->dimension.dimension, label->font.alignment, label->dimension.dimension, label->font.alignment,
layout->font, state->content, layout->font, state->content,
label->font.size, label->font.color label->font.size, label->font.color

View File

@ -18,6 +18,7 @@
#include "UIWindow.h" #include "UIWindow.h"
// @todo We should add some asserts that ensure that the respective structs at least start at a 4byte memory alignment // @todo We should add some asserts that ensure that the respective structs at least start at a 4byte memory alignment
// @performance We are prefetching stuff but we are not yet ensuring data is cache line aligned. We should align each UIElements, element specific data
// Doesn't change the position of pos outside of the function, since lookahead // Doesn't change the position of pos outside of the function, since lookahead
static static
@ -339,11 +340,14 @@ void ui_layout_serialize_element(
*((uint32 *) *out) = SWAP_ENDIAN_LITTLE(element->animations); *((uint32 *) *out) = SWAP_ENDIAN_LITTLE(element->animations);
*out += sizeof(element->animations); *out += sizeof(element->animations);
*((uint16 *) *out) = SWAP_ENDIAN_LITTLE(element->vertex_count); *((uint16 *) *out) = SWAP_ENDIAN_LITTLE(element->vertex_count_max);
*out += sizeof(element->vertex_count); *out += sizeof(element->vertex_count_max);
*((uint32 *) *out) = SWAP_ENDIAN_LITTLE(element->vertices_active); *((uint16 *) *out) = SWAP_ENDIAN_LITTLE(element->vertex_count_active);
*out += sizeof(element->vertices_active); *out += sizeof(element->vertex_count_active);
*((uint32 *) *out) = SWAP_ENDIAN_LITTLE(element->vertices_active_offset);
*out += sizeof(element->vertices_active_offset);
// Output dynamic length content directly after UIElement // Output dynamic length content directly after UIElement
// //
@ -491,11 +495,14 @@ void ui_layout_parse_element(HashEntryInt32* entry, byte* data, const byte** in)
element->animations = SWAP_ENDIAN_LITTLE(*((uint32 *) *in)); element->animations = SWAP_ENDIAN_LITTLE(*((uint32 *) *in));
*in += sizeof(element->animations); *in += sizeof(element->animations);
element->vertex_count = SWAP_ENDIAN_LITTLE(*((uint16 *) *in)); element->vertex_count_max = SWAP_ENDIAN_LITTLE(*((uint16 *) *in));
*in += sizeof(element->vertex_count); *in += sizeof(element->vertex_count_max);
element->vertices_active = SWAP_ENDIAN_LITTLE(*((uint32 *) *in)); element->vertex_count_active = SWAP_ENDIAN_LITTLE(*((uint16 *) *in));
*in += sizeof(element->vertices_active); *in += sizeof(element->vertex_count_active);
element->vertices_active_offset = SWAP_ENDIAN_LITTLE(*((uint32 *) *in));
*in += sizeof(element->vertices_active_offset);
// Load dynamic length content // Load dynamic length content
// Some of the content belongs directly after the element but some of it belongs at very specific offsets // Some of the content belongs directly after the element but some of it belongs at very specific offsets
@ -589,18 +596,8 @@ int32 layout_from_data(
void layout_from_theme( void layout_from_theme(
UILayout* __restrict layout, UILayout* __restrict layout,
const UIThemeStyle* __restrict theme, const UIThemeStyle* __restrict theme
const Camera* __restrict camera
) { ) {
EvaluatorVariable variables[] = {
{ "vw", (f32) camera->viewport_width },
{ "vh", (f32) camera->viewport_height },
{ "px", 0.0 }, // Placeholder for parent values
{ "py", 0.0 }, // Placeholder for parent values
{ "pw", 0.0 }, // Placeholder for parent values
{ "ph", 0.0 }, // Placeholder for parent values
};
// @todo Handle animations // @todo Handle animations
// @todo Handle vertices_active offset // @todo Handle vertices_active offset
if (theme->font) { if (theme->font) {
@ -632,7 +629,6 @@ void layout_from_theme(
// Populate default element // Populate default element
UIElement* element = (UIElement *) (layout->data + entry->value); UIElement* element = (UIElement *) (layout->data + entry->value);
UIAttributeGroup* group = (UIAttributeGroup *) (theme->data + style_entry->value); UIAttributeGroup* group = (UIAttributeGroup *) (theme->data + style_entry->value);
UIElement* parent = element->parent ? (UIElement *) (layout->data + element->parent) : NULL;
// @todo Continue implementation // @todo Continue implementation
switch (element->type) { switch (element->type) {
@ -640,30 +636,27 @@ void layout_from_theme(
ui_label_state_populate(group, (UILabelState *) (layout->data + element->state)); ui_label_state_populate(group, (UILabelState *) (layout->data + element->state));
ui_label_element_populate( ui_label_element_populate(
layout, layout,
element,
group, group,
(UILabel *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT]), (UILabel *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT])
parent,
variables
); );
} break; } break;
case UI_ELEMENT_TYPE_INPUT: { case UI_ELEMENT_TYPE_INPUT: {
ui_input_state_populate(group, (UIInputState *) (layout->data + element->state)); ui_input_state_populate(group, (UIInputState *) (layout->data + element->state));
ui_input_element_populate( ui_input_element_populate(
layout, layout,
element,
group, group,
(UIInput *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT]), (UIInput *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT])
parent,
variables
); );
} break; } break;
case UI_ELEMENT_TYPE_VIEW_WINDOW: { case UI_ELEMENT_TYPE_VIEW_WINDOW: {
ui_window_state_populate(group, (UIWindowState *) (layout->data + element->state)); ui_window_state_populate(group, (UIWindowState *) (layout->data + element->state));
ui_window_element_populate( ui_window_element_populate(
layout, layout,
element,
group, group,
(UIWindow *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT]), (UIWindow *) (layout->data + element->style_types[UI_STYLE_TYPE_DEFAULT])
parent,
variables
); );
} break; } break;
} }
@ -714,35 +707,31 @@ void layout_from_theme(
// Populate element style_types // Populate element style_types
UIAttributeGroup* group = (UIAttributeGroup *) (theme->data + style_entry->value); UIAttributeGroup* group = (UIAttributeGroup *) (theme->data + style_entry->value);
UIElement* parent = element->parent ? (UIElement *) (layout->data + element->parent) : NULL;
// @todo Continue implementation // @todo Continue implementation
switch (element->type) { switch (element->type) {
case UI_ELEMENT_TYPE_LABEL: { case UI_ELEMENT_TYPE_LABEL: {
ui_label_element_populate( ui_label_element_populate(
layout, layout,
element,
group, group,
(UILabel *) (layout->data + element->style_types[style_type]), (UILabel *) (layout->data + element->style_types[style_type])
parent,
variables
); );
} break; } break;
case UI_ELEMENT_TYPE_INPUT: { case UI_ELEMENT_TYPE_INPUT: {
ui_input_element_populate( ui_input_element_populate(
layout, layout,
element,
group, group,
(UIInput *) (layout->data + element->style_types[style_type]), (UIInput *) (layout->data + element->style_types[style_type])
parent,
variables
); );
} break; } break;
case UI_ELEMENT_TYPE_VIEW_WINDOW: { case UI_ELEMENT_TYPE_VIEW_WINDOW: {
ui_window_element_populate( ui_window_element_populate(
layout, layout,
element,
group, group,
(UIWindow *) (layout->data + element->style_types[style_type]), (UIWindow *) (layout->data + element->style_types[style_type])
parent,
variables
); );
} break; } break;
} }
@ -807,12 +796,17 @@ void ui_layout_update(UILayout* layout, UIElement* element) {
// This increases our RAM requirements (every vertex is in cache AND in the asset AND in VRAM) // This increases our RAM requirements (every vertex is in cache AND in the asset AND in VRAM)
// However, this also has the benefit of allowing us to ONLY re-render individual elements // However, this also has the benefit of allowing us to ONLY re-render individual elements
// @performance Profile our prefetching, no sure if it is actually helpful or harmful
// @performance In our immediate mode solution we decided the update/render based on a bitfield // @performance In our immediate mode solution we decided the update/render based on a bitfield
// That is very efficient, the code below isn't doing that maybe there is a way to implement that here as well? // That is very efficient, the code below isn't doing that maybe there is a way to implement that here as well?
// I don't think so but it would be nice // I don't think so but it would be nice
// This function caches the vertices // This function caches the vertices
void ui_layout_update_dfs(UILayout* layout, UIElement* element, byte category = 0) { void ui_layout_update_dfs(UILayout* layout, UIElement* element, byte category = 0) {
if (element->type == UI_ELEMENT_TYPE_MANUAL) { if (element->type == UI_ELEMENT_TYPE_MANUAL
|| !(element->state_flag & UI_ELEMENT_STATE_VISIBLE)
|| !(element->state_flag & UI_ELEMENT_STATE_CHANGED)
) {
return; return;
} }
@ -820,9 +814,14 @@ void ui_layout_update_dfs(UILayout* layout, UIElement* element, byte category =
ui_layout_update(layout, element); ui_layout_update(layout, element);
} }
uint32* children = (uint32 *) (element + 1); if (element->children_count) {
for (int32 i = 0; i < element->children_count; ++i) { uint32* children = (uint32 *) (element + 1);
ui_layout_update(layout, (UIElement *) (layout->data + children[i])); for (int32 i = 0; i < element->children_count - 1; ++i) {
intrin_prefetch_l2(layout->data + children[i + 1]);
ui_layout_update(layout, (UIElement *) (layout->data + children[i]));
}
ui_layout_update(layout, (UIElement *) (layout->data + children[element->children_count - 1]));
} }
} }
@ -831,21 +830,31 @@ uint32 ui_layout_render_dfs(
UIElement* element, Vertex3DTextureColor* __restrict vertices, UIElement* element, Vertex3DTextureColor* __restrict vertices,
byte category = 0 byte category = 0
) { ) {
if (element->type == UI_ELEMENT_TYPE_MANUAL) { if (element->type == UI_ELEMENT_TYPE_MANUAL
|| !(element->state_flag & UI_ELEMENT_STATE_VISIBLE)
) {
return 0; return 0;
} }
uint32 vertex_count = 0; uint32 vertex_count = 0;
if (element->vertex_count && element->category == category) { if (element->vertex_count_active && element->category == category) {
memcpy(vertices, layout->vertices_active + element->vertices_active, sizeof(*vertices) * element->vertex_count); memcpy(vertices, layout->vertices_active + element->vertices_active_offset, sizeof(*vertices) * element->vertex_count_active);
vertices += element->vertex_count; vertices += element->vertex_count_active;
vertex_count += element->vertex_count; vertex_count += element->vertex_count_active;
} }
uint32* children = (uint32 *) (element + 1); if (element->children_count) {
for (int32 i = 0; i < element->children_count; ++i) { uint32* children = (uint32 *) (element + 1);
uint32 child_vertex_count = ui_layout_render_dfs(layout, (UIElement *) (layout->data + children[i]), vertices, category); for (int32 i = 0; i < element->children_count - 1; ++i) {
intrin_prefetch_l2(layout->data + children[i + 1]);
uint32 child_vertex_count = ui_layout_render_dfs(layout, (UIElement *) (layout->data + children[i]), vertices, category);
vertices += child_vertex_count;
vertex_count += child_vertex_count;
}
uint32 child_vertex_count = ui_layout_render_dfs(layout, (UIElement *) (layout->data + children[element->children_count - 1]), vertices, category);
vertices += child_vertex_count; vertices += child_vertex_count;
vertex_count += child_vertex_count; vertex_count += child_vertex_count;
} }
@ -858,7 +867,9 @@ uint32 ui_layout_update_render_dfs(
UIElement* __restrict element, Vertex3DTextureColor* __restrict vertices, UIElement* __restrict element, Vertex3DTextureColor* __restrict vertices,
byte category = 0 byte category = 0
) { ) {
if (element->type == UI_ELEMENT_TYPE_MANUAL) { if (element->type == UI_ELEMENT_TYPE_MANUAL
|| !(element->state_flag & UI_ELEMENT_STATE_VISIBLE)
) {
return 0; return 0;
} }
@ -867,14 +878,22 @@ uint32 ui_layout_update_render_dfs(
if (element->category == category) { if (element->category == category) {
ui_layout_update(layout, element); ui_layout_update(layout, element);
memcpy(vertices, layout->vertices_active + element->vertices_active, sizeof(*vertices) * element->vertex_count); memcpy(vertices, layout->vertices_active + element->vertices_active_offset, sizeof(*vertices) * element->vertex_count_active);
vertices += element->vertex_count; vertices += element->vertex_count_active;
vertex_count += element->vertex_count; vertex_count += element->vertex_count_active;
} }
uint32* children = (uint32 *) (element + 1); if (element->children_count) {
for (int32 i = 0; i < element->children_count; ++i) { uint32* children = (uint32 *) (element + 1);
uint32 child_vertex_count = ui_layout_update_render_dfs(layout, (UIElement *) (layout->data + children[i]), vertices, category); for (int32 i = 0; i < element->children_count - 1; ++i) {
intrin_prefetch_l2(layout->data + children[i + 1]);
uint32 child_vertex_count = ui_layout_update_render_dfs(layout, (UIElement *) (layout->data + children[i]), vertices, category);
vertices += child_vertex_count;
vertex_count += child_vertex_count;
}
uint32 child_vertex_count = ui_layout_update_render_dfs(layout, (UIElement *) (layout->data + children[element->children_count - 1]), vertices, category);
vertices += child_vertex_count; vertices += child_vertex_count;
vertex_count += child_vertex_count; vertex_count += child_vertex_count;
} }
@ -908,18 +927,30 @@ void* layout_get_element_state(const UILayout* layout, UIElement* element)
inline inline
void* layout_get_element_style(const UILayout* layout, UIElement* element, UIStyleType style_type) void* layout_get_element_style(const UILayout* layout, UIElement* element, UIStyleType style_type)
{ {
if (!element) {
return NULL;
}
return layout->data + element->style_types[style_type]; return layout->data + element->style_types[style_type];
} }
inline inline
UIElement* layout_get_element_parent(const UILayout* layout, UIElement* element) UIElement* layout_get_element_parent(const UILayout* layout, UIElement* element)
{ {
if (!element) {
return NULL;
}
return (UIElement *) (layout->data + element->parent); return (UIElement *) (layout->data + element->parent);
} }
inline inline
UIElement* layout_get_element_child(const UILayout* layout, UIElement* element, uint16 child) UIElement* layout_get_element_child(const UILayout* layout, UIElement* element, uint16 child)
{ {
if (!element) {
return NULL;
}
uint16* children = (uint16 *) (element + 1); uint16* children = (uint16 *) (element + 1);
return (UIElement *) (layout->data + children[child]); return (UIElement *) (layout->data + children[child]);
} }

View File

@ -10,6 +10,36 @@
#define UI_LAYOUT_VERSION 1 #define UI_LAYOUT_VERSION 1
///////////////////////////////
// UIElement
// ============================
// child_offset 1
// child_offset 2
// ...
// ============================
// UIElementState
// ============================
// UIElementStyle Active
// UIElementStyle Default
// ...
// ============================
// ...
// Somewhere else in the buffer
// ...
// UIAnimation 1 - Info
// ============================
// UIAnimation 1 - Keyframe 1
// UIAnimation 1 - Keyframe 2
// ...
// ============================
// UIAnimation 2
// ============================
// ...
// ============================
// Modified for every scene // Modified for every scene
struct UILayout { struct UILayout {
// This array has the size of the game window and represents in color codes where interactible ui elements are // This array has the size of the game window and represents in color codes where interactible ui elements are
@ -67,7 +97,7 @@ struct UILayout {
Asset* ui_asset; Asset* ui_asset;
// Total count of the ui_asset vertices // Total count of the ui_asset vertices
uint32 vertex_size; uint32 vertex_count_max;
// @question Should we maybe also hold the font atlas asset here? // @question Should we maybe also hold the font atlas asset here?
@ -75,11 +105,11 @@ struct UILayout {
// This is very similar to the currently rendered UI output but may have some empty space between elements // This is very similar to the currently rendered UI output but may have some empty space between elements
// The reason for this is that some elements may need different vertex counts for different states (e.g. input field) // The reason for this is that some elements may need different vertex counts for different states (e.g. input field)
// WARNING: This memory is shared between different layouts // WARNING: This memory is shared between different layouts
// @performance Maybe we could use this also for rendering by setting free vertices and elements currently hidden to 0
// This would allow us to effectively remove the ui_asset
// @bug We currently use ui_mesh (Asset) to also keep track of gpu memory
uint32 active_vertex_size; uint32 active_vertex_size;
Vertex3DTextureColor* vertices_active; // Not the data owner (see data above) Vertex3DTextureColor* vertices_active; // Not the data owner (see data above)
// Used during the initialization so that every element knows where we currently are during the setup process
uint32 active_vertex_offset;
}; };
#endif #endif

View File

@ -62,31 +62,36 @@ void ui_window_element_unserialize(UIWindow* __restrict details, const byte** __
void ui_window_element_populate( void ui_window_element_populate(
UILayout* layout, UILayout* layout,
UIElement* element,
const UIAttributeGroup* __restrict group, const UIAttributeGroup* __restrict group,
UIWindow* __restrict window, UIWindow* __restrict window
UIElement* parent,
EvaluatorVariable* __restrict variables
) { ) {
if (parent) { v4_f32 parent_dimension = {};
if (element->parent) {
UIElement* parent = element->parent ? (UIElement *) (layout->data + element->parent) : NULL;
// @bug How to ensure that the parent is initialized before the child element // @bug How to ensure that the parent is initialized before the child element
// Currently the order of the initialization depends on the theme file, NOT the layout file // Currently the order of the initialization depends on the theme file, NOT the layout file
// We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles // We could fix it by loading the style based on the layout order but this would result in many misses when looking up styles
// The reason for these misses are, that often only 1-2 style_types exist per element // The reason for these misses are, that often only 1-2 style_types exist per element
v4_f32* parent_dimension;
switch (parent->type) { switch (parent->type) {
case UI_ELEMENT_TYPE_VIEW_PANEL: { case UI_ELEMENT_TYPE_VIEW_PANEL: {
UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]); UIPanel* parent_window = (UIPanel *) (layout->data + parent->style_types[UI_STYLE_TYPE_ACTIVE]);
parent_dimension = &parent_window->dimension.dimension; parent_dimension = parent_window->dimension.dimension;
} break; } break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
}
variables[2].value = parent_dimension->x; if (!element->vertices_active_offset && !element->vertex_count_max) {
variables[3].value = parent_dimension->y; element->vertices_active_offset = layout->active_vertex_offset;
variables[4].value = parent_dimension->width; UIAttribute* vertex_attr = ui_attribute_from_group(group, UI_ATTRIBUTE_TYPE_VERTEX_COUNT);
variables[5].value = parent_dimension->height;
// @todo Strongly depends on the window components (e.g. title bar, close button, ...)
element->vertex_count_max = (uint16) (vertex_attr ? vertex_attr->value_int : 8);
layout->active_vertex_offset += element->vertex_count_max;
} }
UIAttribute* attributes = (UIAttribute *) (group + 1); UIAttribute* attributes = (UIAttribute *) (group + 1);
@ -98,7 +103,7 @@ void ui_window_element_populate(
case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH:
case UI_ATTRIBUTE_TYPE_POSITION_Y: case UI_ATTRIBUTE_TYPE_POSITION_Y:
case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: { case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: {
ui_theme_assign_dimension(&window->dimension, &attributes[i], 6, variables); ui_theme_assign_dimension(&window->dimension, &attributes[i]);
} break; } break;
} }
} }

View File

@ -39,7 +39,7 @@ struct UIAttributeGroup {
//UIAttribute* attributes; //UIAttribute* attributes;
}; };
UIAttribute* ui_attribute_from_group(UIAttributeGroup* group, UIAttributeType type) UIAttribute* ui_attribute_from_group(const UIAttributeGroup* group, UIAttributeType type)
{ {
if (!group->attribute_count) { if (!group->attribute_count) {
return NULL; return NULL;
@ -194,6 +194,8 @@ int32 ui_attribute_type_to_id(const char* attribute_name)
return UI_ATTRIBUTE_TYPE_CACHE_SIZE; return UI_ATTRIBUTE_TYPE_CACHE_SIZE;
} else if (str_compare(attribute_name, "anim") == 0) { } else if (str_compare(attribute_name, "anim") == 0) {
return UI_ATTRIBUTE_TYPE_ANIMATION; return UI_ATTRIBUTE_TYPE_ANIMATION;
} else if (str_compare(attribute_name, "vertex_count") == 0) {
return UI_ATTRIBUTE_TYPE_VERTEX_COUNT;
} }
ASSERT_SIMPLE(false); ASSERT_SIMPLE(false);
@ -226,7 +228,7 @@ void ui_attribute_parse_value(UIAttribute* attr, const char* attribute_name, con
} }
inline inline
void ui_theme_assign_f32(f32* a, const UIAttribute* attr, int32 variable_count = 0, const EvaluatorVariable* variables = NULL) void ui_theme_assign_f32(f32* a, const UIAttribute* attr)
{ {
if (attr->datatype == UI_ATTRIBUTE_DATA_TYPE_INT) { if (attr->datatype == UI_ATTRIBUTE_DATA_TYPE_INT) {
*a = (f32) attr->value_int; *a = (f32) attr->value_int;
@ -237,25 +239,25 @@ void ui_theme_assign_f32(f32* a, const UIAttribute* attr, int32 variable_count =
char value[32]; char value[32];
memcpy(value, attr->value_str, ARRAY_COUNT(attr->value_str)); memcpy(value, attr->value_str, ARRAY_COUNT(attr->value_str));
*a = (f32) evaluator_evaluate(value, variable_count, variables); *a = (f32) evaluator_evaluate(value);
} }
} }
inline inline
void ui_theme_assign_dimension(UIAttributeDimension* dimension, const UIAttribute* attr, int32 variable_count, const EvaluatorVariable* variables) void ui_theme_assign_dimension(UIAttributeDimension* dimension, const UIAttribute* attr)
{ {
switch (attr->attribute_id) { switch (attr->attribute_id) {
case UI_ATTRIBUTE_TYPE_POSITION_X: { case UI_ATTRIBUTE_TYPE_POSITION_X: {
ui_theme_assign_f32(&dimension->dimension.x, attr, variable_count, variables); ui_theme_assign_f32(&dimension->dimension.x, attr);
} break; } break;
case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: { case UI_ATTRIBUTE_TYPE_DIMENSION_WIDTH: {
ui_theme_assign_f32(&dimension->dimension.width, attr, variable_count, variables); ui_theme_assign_f32(&dimension->dimension.width, attr);
} break; } break;
case UI_ATTRIBUTE_TYPE_POSITION_Y: { case UI_ATTRIBUTE_TYPE_POSITION_Y: {
ui_theme_assign_f32(&dimension->dimension.y, attr, variable_count, variables); ui_theme_assign_f32(&dimension->dimension.y, attr);
} break; } break;
case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: { case UI_ATTRIBUTE_TYPE_DIMENSION_HEIGHT: {
ui_theme_assign_f32(&dimension->dimension.height, attr, variable_count, variables); ui_theme_assign_f32(&dimension->dimension.height, attr);
} break; } break;
default: { default: {
UNREACHABLE(); UNREACHABLE();

View File

@ -114,6 +114,10 @@ enum UIAttributeType : uint16 {
UI_ATTRIBUTE_TYPE_ANIMATION, UI_ATTRIBUTE_TYPE_ANIMATION,
// What is the max amount of possible vertices for an element
// This is used to reserve memory in our vertex cache
UI_ATTRIBUTE_TYPE_VERTEX_COUNT,
UI_ATTRIBUTE_TYPE_SIZE, UI_ATTRIBUTE_TYPE_SIZE,
}; };