mirror of https://github.com/bjornbytes/lovr.git
Refcounted modules;
This allows them to be initialized/destroyed from multiple threads in any order. Previously, the first thread to require a module had to be the last thread to use the module, otherwise it would be destroyed too early. There are still a few issues. If the main thread doesn't require a module, it won't pick up the conf.lua settings. Also graphics isn't handling the shader cache writing properly. And I think this breaks the headset-graphics refcounting. But these will be fixed in future commits.
This commit is contained in:
parent
3a16e0c290
commit
08d6b2ad28
|
@ -346,13 +346,11 @@ int luaopen_lovr_audio(lua_State* L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (lovrAudioInit(spatializer, sampleRate)) {
|
||||
luax_atexit(L, lovrAudioDestroy);
|
||||
if (start) {
|
||||
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
|
||||
lovrAudioStart(AUDIO_PLAYBACK);
|
||||
}
|
||||
if (lovrAudioInit(spatializer, sampleRate) && start) {
|
||||
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
|
||||
lovrAudioStart(AUDIO_PLAYBACK);
|
||||
}
|
||||
|
||||
luax_atexit(L, lovrAudioDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -280,9 +280,7 @@ int luaopen_lovr_event(lua_State* L) {
|
|||
lua_pushcfunction(L, nextEvent);
|
||||
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
if (lovrEventInit()) {
|
||||
luax_atexit(L, lovrEventDestroy);
|
||||
}
|
||||
|
||||
lovrEventInit();
|
||||
luax_atexit(L, lovrEventDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -561,6 +561,13 @@ static int libLoaderAllInOne(lua_State* L) {
|
|||
extern const luaL_Reg lovrFile[];
|
||||
|
||||
int luaopen_lovr_filesystem(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrFilesystem);
|
||||
luax_registertype(L, File);
|
||||
luax_registerloader(L, luaLoader, 2);
|
||||
luax_registerloader(L, libLoader, 3);
|
||||
luax_registerloader(L, libLoaderAllInOne, 4);
|
||||
|
||||
const char* archive = NULL;
|
||||
|
||||
lua_getglobal(L, "arg");
|
||||
|
@ -571,15 +578,7 @@ int luaopen_lovr_filesystem(lua_State* L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (lovrFilesystemInit(archive)) {
|
||||
luax_atexit(L, lovrFilesystemDestroy);
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrFilesystem);
|
||||
luax_registertype(L, File);
|
||||
luax_registerloader(L, luaLoader, 2);
|
||||
luax_registerloader(L, libLoader, 3);
|
||||
luax_registerloader(L, libLoaderAllInOne, 4);
|
||||
lovrFilesystemInit(archive);
|
||||
luax_atexit(L, lovrFilesystemDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -359,17 +359,14 @@ static int l_lovrGraphicsInitialize(lua_State* L) {
|
|||
config.cacheData = luax_readfile(".lovrshadercache", &config.cacheSize);
|
||||
}
|
||||
|
||||
if (lovrGraphicsInit(&config)) {
|
||||
luax_atexit(L, lovrGraphicsDestroy);
|
||||
lovrGraphicsInit(&config);
|
||||
luax_atexit(L, lovrGraphicsDestroy);
|
||||
|
||||
// Finalizers run in the opposite order they were added, so this has to go last
|
||||
if (shaderCache) {
|
||||
luax_atexit(L, luax_writeshadercache);
|
||||
}
|
||||
if (shaderCache) { // Finalizers run in the opposite order they were added, so this has to go last
|
||||
luax_atexit(L, luax_writeshadercache);
|
||||
}
|
||||
|
||||
free(config.cacheData);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -387,9 +387,8 @@ int luaopen_lovr_math(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
|
||||
// Module
|
||||
if (lovrMathInit()) {
|
||||
luax_atexit(L, lovrMathDestroy);
|
||||
}
|
||||
lovrMathInit();
|
||||
luax_atexit(L, lovrMathDestroy);
|
||||
|
||||
// Each Lua state gets its own thread-local Pool
|
||||
pool = lovrPoolCreate();
|
||||
|
|
|
@ -178,8 +178,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
|||
luax_registertype(L, CylinderShape);
|
||||
luax_registertype(L, MeshShape);
|
||||
luax_registertype(L, TerrainShape);
|
||||
if (lovrPhysicsInit()) {
|
||||
luax_atexit(L, lovrPhysicsDestroy);
|
||||
}
|
||||
lovrPhysicsInit();
|
||||
luax_atexit(L, lovrPhysicsDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -88,8 +88,7 @@ int luaopen_lovr_thread(lua_State* L) {
|
|||
luax_register(L, lovrThreadModule);
|
||||
luax_registertype(L, Thread);
|
||||
luax_registertype(L, Channel);
|
||||
if (lovrThreadModuleInit()) {
|
||||
luax_atexit(L, lovrThreadModuleDestroy);
|
||||
}
|
||||
lovrThreadModuleInit();
|
||||
luax_atexit(L, lovrThreadModuleDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,7 @@ static const luaL_Reg lovrTimer[] = {
|
|||
int luaopen_lovr_timer(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luax_register(L, lovrTimer);
|
||||
if (lovrTimerInit()) {
|
||||
luax_atexit(L, lovrTimerDestroy);
|
||||
}
|
||||
lovrTimerInit();
|
||||
luax_atexit(L, lovrTimerDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/maf.h"
|
||||
#include "util.h"
|
||||
#include "lib/miniaudio/miniaudio.h"
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
@ -41,7 +42,7 @@ struct Source {
|
|||
};
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
ma_mutex lock;
|
||||
ma_context context;
|
||||
ma_device devices[2];
|
||||
|
@ -193,7 +194,7 @@ static Spatializer* spatializers[] = {
|
|||
// Entry
|
||||
|
||||
bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
|
||||
state.sampleRate = sampleRate;
|
||||
|
||||
|
@ -221,12 +222,11 @@ bool lovrAudioInit(const char* spatializer, uint32_t sampleRate) {
|
|||
state.absorption[2] = .0182f;
|
||||
|
||||
quat_identity(state.orientation);
|
||||
|
||||
return state.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrAudioDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
ma_device_uninit(&state.devices[i]);
|
||||
free(state.deviceInfo[i]);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#include "event/event.h"
|
||||
#include "thread/thread.h"
|
||||
#include "util.h"
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
arr_t(Event) events;
|
||||
size_t head;
|
||||
} state;
|
||||
|
@ -20,13 +21,13 @@ void lovrVariantDestroy(Variant* variant) {
|
|||
}
|
||||
|
||||
bool lovrEventInit(void) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
arr_init(&state.events, arr_alloc);
|
||||
return state.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrEventDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
for (size_t i = state.head; i < state.events.length; i++) {
|
||||
Event* event = &state.events.data[i];
|
||||
switch (event->type) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "core/os.h"
|
||||
#include "util.h"
|
||||
#include "lib/miniz/miniz_tinfl.h"
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
@ -67,7 +68,7 @@ struct File {
|
|||
};
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
Archive* archives;
|
||||
size_t savePathLength;
|
||||
char savePath[1024];
|
||||
|
@ -132,8 +133,7 @@ static bool sanitize(const char* path, char* buffer, size_t* length) {
|
|||
}
|
||||
|
||||
bool lovrFilesystemInit(const char* archive) {
|
||||
if (state.initialized) return false;
|
||||
state.initialized = true;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
|
||||
lovrFilesystemSetRequirePath("?.lua;?/init.lua");
|
||||
|
||||
|
@ -197,7 +197,7 @@ bool lovrFilesystemInit(const char* archive) {
|
|||
}
|
||||
|
||||
void lovrFilesystemDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
Archive* archive = state.archives;
|
||||
while (archive) {
|
||||
Archive* next = archive->next;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "monkey.h"
|
||||
#include "shaders.h"
|
||||
#include <math.h>
|
||||
#include <stdatomic.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -547,7 +548,7 @@ typedef struct {
|
|||
} ScratchTexture;
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
bool active;
|
||||
bool presentable;
|
||||
bool timingEnabled;
|
||||
|
@ -618,7 +619,7 @@ static void onMessage(void* context, const char* message, bool severe);
|
|||
// Entry
|
||||
|
||||
bool lovrGraphicsInit(GraphicsConfig* config) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
|
||||
gpu_config gpu = {
|
||||
.debug = config->debug,
|
||||
|
@ -803,12 +804,11 @@ bool lovrGraphicsInit(GraphicsConfig* config) {
|
|||
#ifdef LOVR_USE_GLSLANG
|
||||
glslang_initialize_process();
|
||||
#endif
|
||||
state.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrGraphicsDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
#ifndef LOVR_DISABLE_HEADSET
|
||||
// If there's an active headset session it needs to be stopped so it can clean up its Pass and
|
||||
// swapchain textures before gpu_destroy is called. This is really hacky and should be solved
|
||||
|
@ -889,7 +889,7 @@ void lovrGraphicsDestroy(void) {
|
|||
}
|
||||
|
||||
bool lovrGraphicsIsInitialized(void) {
|
||||
return state.initialized;
|
||||
return state.ref;
|
||||
}
|
||||
|
||||
void lovrGraphicsGetDevice(GraphicsDevice* device) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include "headset/headset.h"
|
||||
#include "util.h"
|
||||
#include <stdatomic.h>
|
||||
|
||||
HeadsetInterface* lovrHeadsetInterface = NULL;
|
||||
static bool initialized = false;
|
||||
static uint32_t ref;
|
||||
|
||||
bool lovrHeadsetInit(HeadsetConfig* config) {
|
||||
if (initialized) return false;
|
||||
initialized = true;
|
||||
if (atomic_fetch_add(&ref, 1)) return false;
|
||||
|
||||
for (size_t i = 0; i < config->driverCount; i++) {
|
||||
HeadsetInterface* interface = NULL;
|
||||
|
@ -35,12 +35,12 @@ bool lovrHeadsetInit(HeadsetConfig* config) {
|
|||
}
|
||||
|
||||
void lovrHeadsetDestroy(void) {
|
||||
if (!initialized) return;
|
||||
initialized = false;
|
||||
if (atomic_fetch_sub(&ref, 1) != 1) return;
|
||||
if (lovrHeadsetInterface) {
|
||||
lovrHeadsetInterface->destroy();
|
||||
lovrHeadsetInterface = NULL;
|
||||
}
|
||||
ref = 0;
|
||||
}
|
||||
|
||||
void lovrLayerDestroy(void* ref) {
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
#include "util.h"
|
||||
#include "lib/noise/simplexnoise1234.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdatomic.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
struct Curve {
|
||||
uint32_t ref;
|
||||
|
@ -31,20 +31,20 @@ struct RandomGenerator {
|
|||
};
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
RandomGenerator* generator;
|
||||
} state;
|
||||
|
||||
bool lovrMathInit(void) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
state.generator = lovrRandomGeneratorCreate();
|
||||
Seed seed = { .b64 = (uint64_t) time(0) };
|
||||
lovrRandomGeneratorSetSeed(state.generator, seed);
|
||||
return state.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrMathDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
lovrRelease(state.generator, lovrRandomGeneratorDestroy);
|
||||
memset(&state, 0, sizeof(state));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "physics.h"
|
||||
#include "util.h"
|
||||
#include <ode/ode.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct World {
|
||||
|
@ -138,21 +139,20 @@ static void onInfoMessage(int num, const char* format, va_list args) {
|
|||
lovrLog(LOG_INFO, "PHY", message);
|
||||
}
|
||||
|
||||
static bool initialized = false;
|
||||
static uint32_t ref;
|
||||
|
||||
bool lovrPhysicsInit(void) {
|
||||
if (initialized) return false;
|
||||
if (atomic_fetch_add(&ref, 1)) return false;
|
||||
dInitODE();
|
||||
dSetErrorHandler(onErrorMessage);
|
||||
dSetDebugHandler(onDebugMessage);
|
||||
dSetMessageHandler(onInfoMessage);
|
||||
return initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrPhysicsDestroy(void) {
|
||||
if (!initialized) return;
|
||||
if (atomic_fetch_sub(&ref, 1) != 1) return;
|
||||
dCloseODE();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount) {
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
#include "event/event.h"
|
||||
#include "core/os.h"
|
||||
#include "util.h"
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
bool keyRepeat;
|
||||
bool prevKeyState[OS_KEY_COUNT];
|
||||
bool keyState[OS_KEY_COUNT];
|
||||
|
@ -84,20 +85,19 @@ static void onQuit(void) {
|
|||
}
|
||||
|
||||
bool lovrSystemInit(void) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
os_on_key(onKey);
|
||||
os_on_text(onText);
|
||||
os_on_mouse_button(onMouseButton);
|
||||
os_on_mouse_move(onMouseMove);
|
||||
os_on_mousewheel_move(onWheelMove);
|
||||
os_on_permission(onPermission);
|
||||
state.initialized = true;
|
||||
os_get_mouse_position(&state.mouseX, &state.mouseY);
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrSystemDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
os_on_key(NULL);
|
||||
os_on_text(NULL);
|
||||
os_on_permission(NULL);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/os.h"
|
||||
#include "util.h"
|
||||
#include <math.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
|
@ -32,20 +33,20 @@ struct Channel {
|
|||
};
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
mtx_t channelLock;
|
||||
map_t channels;
|
||||
} state;
|
||||
|
||||
bool lovrThreadModuleInit(void) {
|
||||
if (state.initialized) return false;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
mtx_init(&state.channelLock, mtx_plain);
|
||||
map_init(&state.channels, 0);
|
||||
return state.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrThreadModuleDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1)) return;
|
||||
for (size_t i = 0; i < state.channels.size; i++) {
|
||||
if (state.channels.values[i] != MAP_NIL) {
|
||||
lovrRelease((Channel*) (uintptr_t) state.channels.values[i], lovrChannelDestroy);
|
||||
|
@ -53,7 +54,7 @@ void lovrThreadModuleDestroy(void) {
|
|||
}
|
||||
mtx_destroy(&state.channelLock);
|
||||
map_free(&state.channels);
|
||||
state.initialized = false;
|
||||
memset(&state, 0, sizeof(state));
|
||||
}
|
||||
|
||||
Channel* lovrThreadGetChannel(const char* name) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "timer/timer.h"
|
||||
#include "core/os.h"
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
uint32_t ref;
|
||||
double epoch;
|
||||
double lastTime;
|
||||
double time;
|
||||
|
@ -14,14 +15,13 @@ static struct {
|
|||
} state;
|
||||
|
||||
bool lovrTimerInit(void) {
|
||||
if (state.initialized) return false;
|
||||
state.initialized = true;
|
||||
if (atomic_fetch_add(&state.ref, 1)) return false;
|
||||
state.epoch = os_get_time();
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrTimerDestroy(void) {
|
||||
if (!state.initialized) return;
|
||||
if (atomic_fetch_sub(&state.ref, 1) != 1) return;
|
||||
memset(&state, 0, sizeof(state));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue