From 6ade1624f110b3684e2fda954b30e2ce78bb9c33 Mon Sep 17 00:00:00 2001 From: kevinbchen Date: Mon, 4 Jan 2021 00:58:24 -0800 Subject: [PATCH] Emscripten build --- CMakeLists.txt | 15 ++- src/core/app.cpp | 163 ++++++++++++++----------- src/drawing/batch.cpp | 9 ++ src/internal/platform_backend_sdl2.cpp | 7 ++ 4 files changed, 115 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f40f882..e7239a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,13 +89,16 @@ endif() # Link and create SDL2 Definition if we're using it if (SDL2_ENABLED) add_compile_definitions(BLAH_USE_SDL2) - - if (NOT DEFINED SDL2_INCLUDE_DIRS OR NOT DEFINED SDL2_LIBRARIES) - find_package(SDL2 REQUIRED) + if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") + set_target_properties(blah PROPERTIES COMPILE_FLAGS "-s USE_SDL=2") + else() + if (NOT DEFINED SDL2_INCLUDE_DIRS OR NOT DEFINED SDL2_LIBRARIES) + find_package(SDL2 REQUIRED) + endif() + + target_include_directories(blah PUBLIC "$") + set(LIBS ${LIBS} ${SDL2_LIBRARIES}) endif() - - target_include_directories(blah PUBLIC "$") - set(LIBS ${LIBS} ${SDL2_LIBRARIES}) endif() target_link_libraries(blah PUBLIC ${LIBS}) diff --git a/src/core/app.cpp b/src/core/app.cpp index f110572..817779d 100644 --- a/src/core/app.cpp +++ b/src/core/app.cpp @@ -7,13 +7,20 @@ #include "../internal/graphics_backend.h" #include "../internal/input_backend.h" +#ifdef __EMSCRIPTEN__ +#include +#include +#endif + using namespace Blah; namespace { - Config app_config; - bool app_is_running = false; - bool app_is_exiting = false; + static Config app_config; + static bool app_is_running = false; + static bool app_is_exiting = false; + static uint64_t time_last; + static uint64_t time_accumulator = 0; } Config::Config() @@ -34,6 +41,79 @@ Config::Config() on_error = nullptr; } +namespace { + +void loop_iteration() { + // poll system events + PlatformBackend::frame(); + + // update at a fixed timerate + // TODO: allow a non-fixed step update? + { + uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000); + uint64_t time_curr = PlatformBackend::time(); + uint64_t time_diff = time_curr - time_last; + time_last = time_curr; + time_accumulator += time_diff; + + // do not let us run too fast + while (time_accumulator < time_target) + { + PlatformBackend::sleep((int)(time_target - time_accumulator)); + + time_curr = PlatformBackend::time(); + time_diff = time_curr - time_last; + time_last = time_curr; + time_accumulator += time_diff; + } + + // Do not allow us to fall behind too many updates + // (otherwise we'll get spiral of death) + uint64_t time_maximum = app_config.max_updates * time_target; + if (time_accumulator > time_maximum) + time_accumulator = time_maximum; + + // do as many updates as we can + while (time_accumulator >= time_target) + { + time_accumulator -= time_target; + + Time::delta = (1.0f / app_config.target_framerate); + + if (Time::pause_timer > 0) + { + Time::pause_timer -= Time::delta; + if (Time::pause_timer <= -0.0001f) + Time::delta = -Time::pause_timer; + else + continue; + } + + Time::milliseconds += time_target; + Time::previous_elapsed = Time::elapsed; + Time::elapsed += Time::delta; + + InputBackend::frame(); + GraphicsBackend::frame(); + + if (app_config.on_update != nullptr) + app_config.on_update(); + } + } + + // render + { + GraphicsBackend::before_render(); + + if (app_config.on_render != nullptr) + app_config.on_render(); + + GraphicsBackend::after_render(); + PlatformBackend::present(); + } +} +} // namespace + bool App::run(const Config* c) { BLAH_ASSERT(!app_is_running, "The Application is already running"); @@ -68,83 +148,20 @@ bool App::run(const Config* c) if (app_config.on_startup != nullptr) app_config.on_startup(); - uint64_t time_last = PlatformBackend::time(); - uint64_t time_accumulator = 0; + time_last = PlatformBackend::time(); + time_accumulator = 0; // display window PlatformBackend::ready(); +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(loop_iteration, 0, 1); +#else while (!app_is_exiting) { - // poll system events - PlatformBackend::frame(); - - // update at a fixed timerate - // TODO: allow a non-fixed step update? - { - uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000); - uint64_t time_curr = PlatformBackend::time(); - uint64_t time_diff = time_curr - time_last; - time_last = time_curr; - time_accumulator += time_diff; - - // do not let us run too fast - while (time_accumulator < time_target) - { - PlatformBackend::sleep((int)(time_target - time_accumulator)); - - time_curr = PlatformBackend::time(); - time_diff = time_curr - time_last; - time_last = time_curr; - time_accumulator += time_diff; - } - - // Do not allow us to fall behind too many updates - // (otherwise we'll get spiral of death) - uint64_t time_maximum = app_config.max_updates * time_target; - if (time_accumulator > time_maximum) - time_accumulator = time_maximum; - - // do as many updates as we can - while (time_accumulator >= time_target) - { - time_accumulator -= time_target; - - Time::delta = (1.0f / app_config.target_framerate); - - if (Time::pause_timer > 0) - { - Time::pause_timer -= Time::delta; - if (Time::pause_timer <= -0.0001f) - Time::delta = -Time::pause_timer; - else - continue; - } - - Time::milliseconds += time_target; - Time::previous_elapsed = Time::elapsed; - Time::elapsed += Time::delta; - - InputBackend::frame(); - GraphicsBackend::frame(); - - if (app_config.on_update != nullptr) - app_config.on_update(); - } - } - - // render - { - GraphicsBackend::before_render(); - - if (app_config.on_render != nullptr) - app_config.on_render(); - - GraphicsBackend::after_render(); - PlatformBackend::present(); - } - + loop_iteration(); } +#endif // shutdown if (app_config.on_shutdown != nullptr) diff --git a/src/drawing/batch.cpp b/src/drawing/batch.cpp index 2e6c990..d67df25 100644 --- a/src/drawing/batch.cpp +++ b/src/drawing/batch.cpp @@ -19,7 +19,11 @@ namespace const ShaderData shader_data = { // vertex shader +#ifdef __EMSCRIPTEN__ + "#version 300 es\n" +#else "#version 330\n" +#endif "uniform mat4 u_matrix;\n" "layout(location=0) in vec2 a_position;\n" "layout(location=1) in vec2 a_tex;\n" @@ -37,7 +41,12 @@ namespace "}", // fragment shader +#ifdef __EMSCRIPTEN__ + "#version 300 es\n" + "precision mediump float;\n" +#else "#version 330\n" +#endif "uniform sampler2D u_texture;\n" "in vec2 v_tex;\n" "in vec4 v_col;\n" diff --git a/src/internal/platform_backend_sdl2.cpp b/src/internal/platform_backend_sdl2.cpp index a849b6d..abce1a2 100644 --- a/src/internal/platform_backend_sdl2.cpp +++ b/src/internal/platform_backend_sdl2.cpp @@ -81,6 +81,10 @@ bool PlatformBackend::init(const Config* config) { flags |= SDL_WINDOW_OPENGL; +#ifdef __EMSCRIPTEN__ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#else SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -93,6 +97,7 @@ bool PlatformBackend::init(const Config* config) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); +#endif } // enable DirectX else if (App::renderer() == Renderer::D3D11) @@ -140,9 +145,11 @@ bool PlatformBackend::init(const Config* config) void PlatformBackend::ready() { +#ifndef __EMSCRIPTEN__ // enable V-Sync if (App::renderer() == Renderer::OpenGL) SDL_GL_SetSwapInterval(1); +#endif } void PlatformBackend::shutdown()