Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spike for Splash Kit Online research #20

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ export default defineConfig({
directory: "products/splashkit/documentation/tutorials",
},
},
{
label: "Expansions",
autogenerate: {
directory: "products/splashkit/documentation/expansions",
},
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
---
title: SplashKit Online Research Spike Outcome
---

**Spike:** NA

**Title:** SplashKit Online Research Spike Plan

**Author:** Sean Boettger, sboettger@deakin.edu.au, sean@whypenguins.com

## Goals / Deliverables

The goal of this spike was to investigate whether Emscripten and Emception could be used to compile
and run SplashKit online via WASM, and in doing so produce this report. In the process, a fork of
SplashKit-Core was made to improve reproducibility. This can be found here:
https://github.com/WhyPenguins/splashkit-core/tree/EmscriptenTest

## Technologies, Tools, and Resources used

- Internet Browser: Firefox
- Programming Languages: C++, Python, Javascript
- Compilers: Emscripten
- Docker
- Emception
- Programming Libraries: SplashKit
- Text Editor: Notepad++
- Terminal

## Tasks undertaken

Here are the key tasks that were performed to produce the main results. The actual path taken took a
bit more research and experimentation.

### Testing Emscripten

- Installed and activated Emscripten using emsdk (see
https://emscripten.org/docs/getting_started/downloads.html)
- Tried compiling some simple SDL code (such as that found here
https://blog.conan.io/2023/07/20/introduction-to-game-dev-with-sdl2.html) with the command
`emcc -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS='["bmp","png","xpm"]' sdl_test.cpp -o sdl_test.html`.
Emscripten already has ports for many libraries such as SDL, which was found out about here
(https://emscripten.org/docs/compiling/Building-Projects.html)
- Ran a python web server with `python -m http.server`
- Navigated to localhost:8000 - the program was running in the browser.

### Compiling SplashKit to WASM

- This took a few changes to SplashKit's source code. To make this easier to reproduce, a fork of
SplashKit-Core has been created that has a branch with the changes required to make SplashKit
compile a simple example under Emscripten. See here:
https://github.com/WhyPenguins/splashkit-core/tree/EmscriptenTest

#### The following is a brief list of changes

- Cloned SplashKit-Core
- Modified CMakeLists.txt as follows: - Appended `set(CMAKE_C_COMPILER "emcc") `
`set(CMAKE_CXX_COMPILER "emcc")` at the top. - Appended `-sUSE_SDL=2` to the make flags. -
Appended the following to be linked: - `-sUSE_SDL=2` - `-sUSE_SDL_TTF=2` - `-sUSE_SDL_GFX=2` -
`-sUSE_SDL_NET=2` - `-sUSE_SDL_MIXER=2` - `-sUSE_SDL_IMAGE=2` -
`-sSDL2_IMAGE_FORMATS='["bmp","png","xpm"]'` and removed any existing duplicates. - Modified a few
of the files and dependencies to either use Windows or Linux headers depending on what they
required (perhaps the build environment was unusual). - Commented out tests
- Modified web_driver.cpp and terminal.cpp so they were stubs without includes.
- At this point running `cmake -G "Unix Makefiles" . && make` built.
- To test functionality simply, the code from the starting tutorial
(https://splashkit.io/articles/guides/tags/starter/get-started-drawing/) was brought across and
replaced the Tests in the test folder. The test target in the makefile was modified to output this
test. `set(CMAKE_EXECUTABLE_SUFFIX ".html")` was also important to make it output properly.
- From here, the Python webserver was started in the output directory, and the starting tutorial
could be ran in the browser.

### Compiling Emception

- First Docker was installed, and WSL2 setup.
- Next, Emception was cloned and built following the instructions
(https://github.com/jprendes/emception)
- Unfortunately, a number of issues were encountered. Compiling LLVM took approximately 16GB of RAM,
and so the VM's RAM and swap limits needed to be adjusted; otherwise the compilation process was
killed. It also took approximately a day.
- Compilation errors were encountered later on. These have been reported already on the repository
(https://github.com/jprendes/emception/issues/24), and no fix nor work around has been proposed
yet. In order to not spend too long, Emception was shelved for now to work on interfacing
SplashKit with Javascript.

### Using SplashKit as a Library in Javascript

- There were three different approaches that could be taken - each one was tested along with
pros/cons examined.
- First step was to test 'cwrap'ing.
- The Main function was renamed, and wrapped in `extern "C"`
- An additional 'rerender' function was added, to test multiple calls.
- `-sEXPORTED_RUNTIME_METHODS=ccall,cwrap` was added to the makefile
- From here, the file was loaded in the browser, and the following executed on the brower's console:

```
start_main = Module.cwrap('start_main', 'number', [])
start_main()`
different_render = Module.cwrap('different_render', 'number', [])
different_render()
```

- This method worked easily, however wrapping create_window immediately posed issues as it takes a
C++ string (not a primitive), and also returns something other than a primitive. Methods involving
manual allocation were investigated, but instead the two binding implementations Embind and WebIDL
Binder seemed more promising.
- Embind bindings for color and a few functions were created. They look as follows:

```
EMSCRIPTEN_BINDINGS(color) {
emscripten::value_object<color>("color")
.field("r", &color::r)
.field("g", &color::g)
.field("b", &color::b)
.field("a", &color::a);
}
EMSCRIPTEN_BINDINGS(my_module) {
emscripten::function("open_window", (window (*)(std::string, int, int)){&open_window}, emscripten::allow_raw_pointers());
emscripten::function("clear_screen", (void (*)(void)){&clear_screen});
emscripten::function("clear_screen_color", (void (*)(color)){&clear_screen});
emscripten::function("refresh_screen", (void (*)(void)){&refresh_screen_});
}
```

- Unfortunately it seems Embind has issues with raw pointers, which SplashKit uses a lot of.
Apparently it should only have issues with pointers to primitive types, but the same error was
encountered even with structures (such as \_window_data\*).
- Finally WebIDL Binder was tried out.
- SplashKitWasm.idl was created and filled out with some simple prototypes.
- The C++ and Javascript glue was created by running
`python ../../emsdk/upstream/emscripten/tools/webidl_binder.py SplashKitWasm.idl SplashKitWasmGlue`
- It was tested at the console with the following commands:

```
SK = new Module.SplashKitJavascript()
SK.open_window("Testing!", 800, 600)
SK.clear_screen(SK.color(0.7,0,1,1))
SK.refresh_screen()
```

```
SK.clear_screen(SK.color(1,1,1,1));
SK.fill_ellipse(SK.color(0,1,0,1), 0, 400, 800, 400);
SK.fill_rectangle(SK.color(0.4,0.4,0.4,1), 300, 300, 200, 200);
SK.fill_triangle(SK.color(1,0,0,1), 250, 300, 400, 150, 550, 300);
SK.refresh_screen()
```

- It was here that testing was ended and this report was written up. The results can be seen in the
final commit on the EmscriptenTest branch.

This report took a bit longer to write up than it should have, as initially all the tests with
Emscripten were performed using a personal compilation tool in order to make initial testing quick.
That tool continued to be used to compile SplashKit-Core. Migrating to using SplashKit-Core's own
compilation method took longer, but hopefully by doing so the results can be more easily reproduced
and expanded on in the future.

## What we found out

### Code using SplashKit can be compiled with Emscripten and run in the browser.

#### What worked

During testing, the majority of SplashKit was compiled and linked successfully, and basic
functionality (opening a window, drawing shapes) was confirmed to work. In the SDL test, SDL input
was confirmed to work, making it likely it does in SplashKit as well.

#### What wasn't tested

Any functionality outside of that was not tested, including sound, animation, etc. Twitter,
terminal, serial and JSON functionality was also not tested/replaced with stubs.

#### What didn't work

Web functionality was replaced with stubs due to the usage of cURL which is not currently compilable
under Emscripten. See (https://github.com/emscripten-core/emscripten/issues/3270)

### SplashKit can be compiled as a library and used in Javascript.

Embind seemed promising but due to issues with raw pointers WebIDL Binder was investigated further
and is plausibly the better alternative for this project. It has issues with functions in global
scope unfortunately (https://github.com/emscripten-core/emscripten/issues/8390), requiring the
majority of SplashKit's functions to be wrapped in a class.

### Emception was unable to be compiled.

Until the bug here (https://github.com/jprendes/emception/issues/24) is fixed, it seems like it will
be difficult to compile Emception without really digging into how it works and correcting the
problem ourselves. Whether this is worth it or not is hard to say.

## Open issues/risks

As Emception was unable to be compiled, it is difficult to evaluate whether it would have been a
good solution. There is risk that continuing to try and use it would just consume more time.

Much of SplashKit is also yet to be tested; perhaps there are yet unknown issues regarding sound and
other interactivity. Testing of larger codebases using SplashKit should be conducted.

## Recommendation

One way forward would be to continue developing SplashKit Online as a Javascript based scripting
environment; it has been confirmed SplashKit can be used as a library via Javascript, and this
ensures no load on the server regarding compiling, and also no uncertainty regarding whether it will
be possible to get Emception working.

Another way forward is to use Emscripten as a back-end compiler to the web IDE, similar to the
original SplashKit Online repository. This introduces more complexity on the server side, but would
allow users to develop using C++ just as they would on their own computer.

Finally, it might be worth continuing to investigate Emception and try to get it to compile. Several
unknowns exist - how long will it take to understand and make compile, and if it runs whether it be
able to compile well enough (there are concerns regarding speed). If it is successful however this
would probably give the best result, but there are many unknowns.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: SplashKit Online Research Spike Plan
---

**Name:** SplashKit Online Research Spike Plan

## Context

It would be useful if SplashKit could be used directly in-browser, in order to make it easier for
people to get started without difficulties setting it up locally on their own machine. Last
trimester the SplashKit Online project was started, however due to its difficulty was placed on
hold.

The purpose of this spike is to investigate technologies that may make running it online more
viable, and explore which ways seem most promising. The main technology to be investigated here is
WebAssembly (or WASM), which was mentioned in the readme for the SplashKit-Online repository
(https://github.com/thoth-tech/SplashkitOnline). The technology itself doesn't appear to have been
used in the project; instead it seems that that project relied on both compiling _and_ executing the
code on a back-end server. This could be considered an extension of that initial research.

**Knowledge Gap:**

- It is currently unknown how well certain technologies like WASM could be used to compile/run code
using SplashKit in a browser.
- It is unknown if code can be compiled quick enough within the browser.
- It is unknown if and how effectively SplashKit can be compiled as a library to be used within the
browser.

**Skill Gap:**

- There is a lack of experience with technology like WASM,

**Technology Gap:**

- Ability to compile SplashKit to WASM.

It is unsure whether projects like Emscripten or Emception are able to compile SplashKit and run the
result in a browser interactively; this will need to be investigated. It is also uncertain whether
it would be better to compile within the browser itself, or on a back-end server.

## Goals/Deliverables

- Report on possible ways to continue developing SplashKit Online
- Confirm whether code using SplashKit can be compiled with Emscripten (C/C++ to WASM compiler)
and executed in a browser
- Confirm whether SplashKit can be compiled and used as a library via Javascript in a browser
- Confirm SplashKit code can be compiled in-browser using Emception (self hosted Emscripten)

**Planned start date:** Week 1 T3 2023

**Deadline:** Week 2 T3 2023

## Planning notes

- Setup Emscripten
- Confirm code using SDL can be compiled with Emscripten and executed in a browser
- Setup simple SDL example
- Compile with Emscripten
- Run in browser and check result
- Confirm code using SplashKit can be compiled with Emscripten and executed in a browser
- Setup simple SplashKit example
- Compile with Emscripten
- Run in browser and check result
- (Optional) Test whether SplashKit can be compiled and used as a library via Javascript in a
browser
- Investigate methods of binding
- Test binding methods
- Build and setup Emception
- Confirm SDL code can be compiled in-browser using Emception
- Confirm SplashKit code can be compiled in-browser using Emception
Loading