Functional hot reloading
This commit is contained in:
parent
9a4c57d4c2
commit
23bafb943f
4 changed files with 58 additions and 13 deletions
8
Makefile
8
Makefile
|
|
@ -1,8 +1,8 @@
|
|||
INTERFACEDIR:=$(shell pkg-config --variable=pkgdatadir wayland-protocols)
|
||||
CFLAGS=-Wall -Wextra -Og -ggdb3 -Wno-unused-but-set-variable -Wno-unused-parameter
|
||||
CFLAGS=-Wall -Wextra -Og -ggdb3 -Wno-unused-but-set-variable -Wno-unused-parameter -Wl,--export-dynamic
|
||||
LIBS=-lwayland-client -lwayland-egl -lEGL -lOpenGL -lxkbcommon -levdev
|
||||
wayland: wayland.c xdg-shell-protocol.c xdg-shell-client-protocol.h zwp-text-input-unstable-v3-client-protocol.c zwp-text-input-unstable-v3-protocol.h xdg-decoration-unstable-v1.c xdg-decoration-unstable-v1.h
|
||||
gcc $(CFLAGS) $(LIBS) wayland.c xdg-shell-protocol.c xdg-decoration-unstable-v1.c zwp-text-input-unstable-v3-client-protocol.c -o wayland
|
||||
wayland: wayland.c xdg-shell-protocol.c xdg-shell-client-protocol.h zwp-text-input-unstable-v3-client-protocol.c zwp-text-input-unstable-v3-protocol.h xdg-decoration-unstable-v1.c xdg-decoration-unstable-v1.h game.h
|
||||
gcc $(CFLAGS) $(LIBS) $^ -o wayland
|
||||
|
||||
# TODO: Normalize these annoying names
|
||||
xdg-shell-protocol.c:
|
||||
|
|
@ -18,4 +18,4 @@ xdg-decoration-unstable-v1.c:
|
|||
xdg-decoration-unstable-v1.h:
|
||||
wayland-scanner client-header $(INTERFACEDIR)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml xdg-decoration-unstable-v1.h
|
||||
game.so: game.c game.h
|
||||
gcc $(CFLAGS) game.c --shared -o game.so
|
||||
gcc $(CFLAGS) game.c -shared -o game.so
|
||||
|
|
|
|||
2
game.c
2
game.c
|
|
@ -3,5 +3,5 @@
|
|||
void simulate_frame(game_state_t *state)
|
||||
{
|
||||
// TODO: Do something amazing here
|
||||
;
|
||||
state->version = 1;
|
||||
}
|
||||
|
|
|
|||
1
game.h
1
game.h
|
|
@ -11,6 +11,7 @@ typedef struct {
|
|||
int32_t window_w;
|
||||
int64_t frame;
|
||||
double dt;
|
||||
int32_t version;
|
||||
} game_state_t;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
52
wayland.c
52
wayland.c
|
|
@ -18,6 +18,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
// libevdev
|
||||
#include <libevdev-1.0/libevdev/libevdev.h>
|
||||
// generated header using wayland-scanner
|
||||
|
|
@ -70,12 +71,14 @@ error_level_t error_verbosity = { ERROR_LEVEL_DEBUG };
|
|||
|
||||
typedef void (*simulate_frame_fn)(game_state_t*);
|
||||
|
||||
/* Game layer */
|
||||
/* Game layer and hot reload */
|
||||
typedef struct {
|
||||
simulate_frame_fn simulate_frame;
|
||||
} game_api_t;
|
||||
|
||||
game_api_t game_api = {};
|
||||
time_t hr_timestamp = 0;
|
||||
void *dlhandle = NULL;
|
||||
|
||||
char *egl_s(int code)
|
||||
{
|
||||
|
|
@ -742,16 +745,25 @@ int main()
|
|||
wl_surface_commit(surface);
|
||||
|
||||
// Trying to link with game layer
|
||||
void *dlhandle = dlopen("./game.so", RTLD_NOW);
|
||||
dlhandle = dlopen("./game.so", RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (!dlhandle)
|
||||
{
|
||||
console_err_ss(MODULE_HOTRELOAD, "Could not load game layer\n");
|
||||
dlerror();
|
||||
}
|
||||
|
||||
struct stat fs;
|
||||
if (stat("./game.so", &fs) == -1)
|
||||
console_err_ss(MODULE_HOTRELOAD, "Could not get info for game library: %s\n", strerror(errno));
|
||||
|
||||
{
|
||||
hr_timestamp = fs.st_mtime;
|
||||
game_api.simulate_frame = (simulate_frame_fn)dlsym(dlhandle, "simulate_frame");
|
||||
|
||||
char *dlerr = NULL;
|
||||
if ((dlerr = dlerror()))
|
||||
console_err_ss(MODULE_HOTRELOAD, "Could not link game layer: %s\n", dlerr);
|
||||
}
|
||||
|
||||
// Main event loop
|
||||
int framecount = 0;
|
||||
|
|
@ -759,6 +771,37 @@ int main()
|
|||
{
|
||||
wl_display_dispatch_pending(display);
|
||||
|
||||
// TODO: Do not try to hot-reload every frame. Lmao
|
||||
struct stat file_stats;
|
||||
if (stat("./game.so", &file_stats) == -1)
|
||||
{
|
||||
console_err_ss(MODULE_HOTRELOAD, "Could not get info for game library: %s\n", strerror(errno));
|
||||
}
|
||||
else if (hr_timestamp < file_stats.st_mtime)
|
||||
{
|
||||
console_log_ss(MODULE_HOTRELOAD, "Game library has changed: trying to hot reload\n");
|
||||
|
||||
// NOTE: We cannot load new symbols from the same path unless we close the currently open handle.
|
||||
// However, until the linker is done with the file it will fail on dlopen.
|
||||
// For now we just busywait trying to link it.
|
||||
dlclose(dlhandle);
|
||||
while (!(dlhandle = dlopen("./game.so", RTLD_NOW | RTLD_LOCAL)));
|
||||
|
||||
|
||||
hr_timestamp = fs.st_mtime;
|
||||
game_api.simulate_frame = (simulate_frame_fn)dlsym(dlhandle, "simulate_frame");
|
||||
char *dlerr = NULL;
|
||||
if ((dlerr = dlerror()))
|
||||
console_err_ss(MODULE_HOTRELOAD, "Could not link game layer: %s\n", dlerr);
|
||||
|
||||
hr_timestamp = file_stats.st_mtime;
|
||||
char *error_string = dlerror();
|
||||
if (error_string)
|
||||
console_err_ss(MODULE_HOTRELOAD, "Error loading game code: %s\n", error_string);
|
||||
|
||||
console_log_ss(MODULE_HOTRELOAD, "Successfully hot reloaded game layer\n");
|
||||
}
|
||||
|
||||
/* Controller input handling */
|
||||
if (libevdev_get_fd(libevdev) != -1) // check if we actually found a controller to query
|
||||
{
|
||||
|
|
@ -848,8 +891,9 @@ int main()
|
|||
game_state.frame = framecount;
|
||||
// TODO: Get delta time since last frame
|
||||
game_state.dt = 0;
|
||||
|
||||
game_api.simulate_frame(&game_state);
|
||||
if (game_state.version != 1)
|
||||
console_debug_ss(MODULE_HOTRELOAD, "Version %d\n", game_state.version);
|
||||
//console_debug_ss(MODULE_WAYLAND, "Frame %d\n", framecount);
|
||||
glClearColor(0.5, 0.3, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue