Skip to content

Commit

Permalink
Import initial engine in C++ compiled to WASM
Browse files Browse the repository at this point in the history
  • Loading branch information
juztamau5 committed Mar 11, 2024
1 parent 75d2d20 commit ca5421e
Show file tree
Hide file tree
Showing 9 changed files with 380 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ jobs:
src/frontend/node_modules
key: cache-modules-${{ matrix.os }}-${{ matrix.node-version }}-${{ hashFiles('src/frontend/pnpm-lock.yaml') }}

- name: Cache emsdk
id: cache-emsdk
uses: actions/cache@v4
with:
path: |
tools/emsdk
key: cache-emsdk-${{ hashFiles('tools/download-emscripten.sh') }}

- name: Cache WASM libraries
id: cache-wasm
uses: actions/cache@v4
with:
path: |
tools/install
key: cache-wasm-${{ matrix.os }}-${{ matrix.node-version }}-${{ hashFiles('src/engine/**', 'tools/build-wasm.sh', 'tools/download-emscripten.sh') }}

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
Expand Down Expand Up @@ -78,3 +94,15 @@ jobs:
if: steps.cache-vite.outputs.cache-hit != 'true'
run: |
pnpm build
- name: Install emsdk
if: steps.cache-emsdk.outputs.cache-hit != 'true'
run: |
./download-emscripten.sh
working-directory: tools

- name: Build wasm libraries
if: steps.cache-wasm.outputs.cache-hit != 'true'
run: |
./build-wasm.sh
working-directory: tools
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ The following subfolders compose the repo architecture:

* `src/backend/` - The Cartesi Machine logic
* `src/frontend/` - The website and frontend logic
* `src/engine/` - The main emulator engine
* `src/learning/` - The Python code for AI agents
* `tools/` - Tooling for dependencies

Expand Down
77 changes: 77 additions & 0 deletions src/engine/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
################################################################################
#
# Copyright (C) 2024 retro.ai
# This file is part of retro3 - https://github.com/retroai/retro3
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# See the file LICENSE.txt for more information.
#
################################################################################

################################################################################
# Project settings
################################################################################

project(retro_engine LANGUAGES CXX)
cmake_minimum_required(VERSION 3.10)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

################################################################################
# Dependencies
################################################################################

# TODO

################################################################################
# Sources
################################################################################

set(SOURCE_FILES
core/retro_engine.cpp
core/retro_engine_embinder.cpp
)

################################################################################
# Libraries
################################################################################

#include_directories(src)

# Add the executable based on the source files
add_executable(retro_engine ${SOURCE_FILES})

# Add flags for Empscripten builds
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
set_target_properties(retro_engine PROPERTIES
COMPILE_FLAGS " \
-O3 \
"
# 26214400 is 25 MiB
LINK_FLAGS " \
-gsource-map \
-s ALLOW_MEMORY_GROWTH=1 \
-s INITIAL_MEMORY=26214400 \
-s MODULARIZE=1 \
-s USE_WEBGL2=1 \
-s WASM=1 \
--bind \
--source-map-base https://retro.ai/ \
"
)
endif ()

################################################################################
# Install
################################################################################

INSTALL(
FILES
"${CMAKE_BINARY_DIR}/retro_engine.js"
"${CMAKE_BINARY_DIR}/retro_engine.wasm"
"${CMAKE_BINARY_DIR}/retro_engine.wasm.map"
DESTINATION
wasm
)
85 changes: 85 additions & 0 deletions src/engine/core/retro_engine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2024 retro.ai
* This file is part of retro3 - https://github.com/retroai/retro3
*
* SPDX-License-Identifier: AGPL-3.0-or-later
* See the file LICENSE.txt for more information.
*/

#include "retro_engine.hpp"

#include <iostream>

namespace
{
constexpr const char* CANVAS_ID = "canvas";
}

RetroEngine::RetroEngine() : m_webGLContext(0)
{
}

RetroEngine::~RetroEngine()
{
Deinitialize();
}

bool RetroEngine::Initialize()
{
if (!InitializeWebGL())
return false;

return true;
}

void RetroEngine::Deinitialize()
{
DeinitializeWebGL();
}

bool RetroEngine::InitializeWebGL()
{
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);

attrs.alpha = EM_FALSE;
attrs.depth = EM_TRUE;
attrs.stencil = EM_TRUE;
attrs.antialias = EM_TRUE;
attrs.preserveDrawingBuffer = EM_FALSE;
attrs.powerPreference = EM_WEBGL_POWER_PREFERENCE_HIGH_PERFORMANCE;
attrs.failIfMajorPerformanceCaveat = EM_FALSE;
attrs.majorVersion = 2;
attrs.minorVersion = 0;

const EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context =
emscripten_webgl_create_context(CANVAS_ID, &attrs);
if (context <= 0)
{
std::cerr << "Failed to create WebGL context" << std::endl;
return false;
}

EMSCRIPTEN_RESULT result = emscripten_webgl_make_context_current(context);
if (result != EMSCRIPTEN_RESULT_SUCCESS)
{
std::cerr << "Failed to make WebGL context current (result=" << result << ")" << std::endl;
return false;
}

// Success
m_webGLContext = context;
return true;
}

void RetroEngine::DeinitializeWebGL()
{
if (m_webGLContext > 0)
{
EMSCRIPTEN_RESULT result = emscripten_webgl_destroy_context(m_webGLContext);
if (result != EMSCRIPTEN_RESULT_SUCCESS)
std::cerr << "Failed to destroy WebGL context (result=" << result << ")" << std::endl;

m_webGLContext = 0;
}
}
36 changes: 36 additions & 0 deletions src/engine/core/retro_engine.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2024 retro.ai
* This file is part of retro3 - https://github.com/retroai/retro3
*
* SPDX-License-Identifier: AGPL-3.0-or-later
* See the file LICENSE.txt for more information.
*/

#pragma once

#include <emscripten/html5.h>

class RetroEngine
{
public:
RetroEngine();
~RetroEngine();

/*!
* \brief Initialize the engine
*
* \return true if successful, false otherwise
*/
bool Initialize();

/*!
* \brief Deinitialize the engine
*/
void Deinitialize();

private:
bool InitializeWebGL();
void DeinitializeWebGL();

EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_webGLContext;
};
19 changes: 19 additions & 0 deletions src/engine/core/retro_engine_embinder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2024 retro.ai
* This file is part of retro3 - https://github.com/retroai/retro3
*
* SPDX-License-Identifier: AGPL-3.0-or-later
* See the file LICENSE.txt for more information.
*/

#include "retro_engine.hpp"

#include <emscripten/bind.h>

EMSCRIPTEN_BINDINGS(engine)
{
emscripten::class_<RetroEngine>("RetroEngine")
.constructor<>()
.function("initialize", &RetroEngine::Initialize)
.function("deinitialize", &RetroEngine::Deinitialize);
}
3 changes: 3 additions & 0 deletions tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/build
/emsdk
/install
68 changes: 68 additions & 0 deletions tools/build-wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash
################################################################################
#
# Copyright (C) 2024 retro.ai
# This file is part of retro3 - https://github.com/retroai/retro3
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# See the file LICENSE.txt for more information.
#
################################################################################

################################################################################
#
# Helper for CI infrastructure. Sets the appropriate paths and calls CMake.
#
################################################################################

# Enable strict shell mode
set -o errexit
set -o nounset
set -o pipefail

################################################################################
# Environment paths
################################################################################

# Get the absolute path to the project root
PROJECT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"

# Directory for the engine sources
ENGINE_DIRECTORY="${PROJECT_DIRECTORY}/src/engine"

# Directory for tooling
TOOL_DIRECTORY="${PROJECT_DIRECTORY}/tools"

# Directory for intermediate build files
BUILD_DIRECTORY="${TOOL_DIRECTORY}/build"

# Directory of the Emscripten SDK
EMSDK_DIRECTORY="${TOOL_DIRECTORY}/emsdk"

# Directory to place the generated libraries
INSTALL_DIRECTORY="${TOOL_DIRECTORY}/install"

# Ensure directories exist
mkdir -p "${BUILD_DIRECTORY}"
mkdir -p "${INSTALL_DIRECTORY}"

################################################################################
# Setup environment
################################################################################

source "${EMSDK_DIRECTORY}/emsdk_env.sh"

################################################################################
# Call CMake
################################################################################

cd "${BUILD_DIRECTORY}"

emcmake cmake \
"${ENGINE_DIRECTORY}" \
-DCMAKE_INSTALL_PREFIX="${INSTALL_DIRECTORY}" \
$(! command -v ccache &> /dev/null || echo "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache")

cmake \
--build "${BUILD_DIRECTORY}" \
--target install
Loading

0 comments on commit ca5421e

Please sign in to comment.