Skip to content
Draft
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
12 changes: 12 additions & 0 deletions Apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ if(NOT ANDROID)
add_subdirectory(Playground)
endif()

# ShaderCacheGenerator: Win32 + OpenGL headless tool that renders a scene .js
# until its shaders are compiled, then writes the ShaderCache to a file.
# Configure with -DGRAPHICS_API=OpenGLWindowsDevOnly (which maps to OpenGL +
# ANGLE). Needs the ShaderCache plugin, the runtime shader compiler
# (COMPILESHADERS), and the Embedding Runtime/View API it is built on.
if((WIN32 AND NOT WINDOWS_STORE) AND GRAPHICS_API STREQUAL OpenGL
AND BABYLON_NATIVE_EMBEDDING
AND BABYLON_NATIVE_PLUGIN_SHADERCACHE
AND BABYLON_NATIVE_PLUGIN_NATIVEENGINE_COMPILESHADERS)
add_subdirectory(ShaderCacheGenerator)
endif()

if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID AND NOT APPLE))
add_subdirectory(UnitTests)
add_subdirectory(ModuleLoadTest)
Expand Down
78 changes: 78 additions & 0 deletions Apps/ShaderCacheGenerator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ShaderCacheGenerator
#
# A headless Win32 + OpenGL tool that builds a GPU shader cache for a Babylon.js
# scene. It hosts the scene script through the Babylon::Embedding Runtime/View
# API (backed by an offscreen window + the ANGLE OpenGL backend), renders frames
# until the scene has finished compiling its shaders, and writes the resulting
# ShaderCache to a file.
#
# Usage:
# ShaderCacheGenerator <scene.js> <output.bin> [shared Playground options]
#
# Only the two positional arguments (scene script + output cache file) are
# required; any additional flags are the shared Playground command-line options
# (run with --help to list them).
#
# The produced cache is GRAPHICS_API-specific: configuring with
# -DGRAPHICS_API=OpenGLWindowsDevOnly (which maps to the OpenGL/ANGLE backend)
# yields GLES shaders compatible with the Android OpenGL backend.

set(PLAYGROUND_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Playground")

set(SOURCES
"Source/Main.cpp")

# Reused from Apps/Playground/Shared: command-line parsing, process diagnostics
# (console/crash/exit handling) and the log callback.
set(SHARED_SOURCES
"${PLAYGROUND_DIR}/Shared/CommandLine.cpp"
"${PLAYGROUND_DIR}/Shared/CommandLine.h"
"${PLAYGROUND_DIR}/Shared/Diagnostics.cpp"
"${PLAYGROUND_DIR}/Shared/Diagnostics.h"
"${PLAYGROUND_DIR}/Shared/PlaygroundScripts.cpp"
"${PLAYGROUND_DIR}/Shared/PlaygroundScripts.h")

add_executable(ShaderCacheGenerator ${SOURCES} ${SHARED_SOURCES})

warnings_as_errors(ShaderCacheGenerator)

target_compile_definitions(ShaderCacheGenerator
PRIVATE UNICODE
PRIVATE _UNICODE)

# So Main.cpp can include the reused headers as <Shared/CommandLine.h> etc.
target_include_directories(ShaderCacheGenerator PRIVATE "${PLAYGROUND_DIR}")

# SUBSYSTEM:CONSOLE so stdout/stderr behave like a normal console app; the tool
# still creates a hidden Win32 window for the GL swapchain.
set_target_properties(ShaderCacheGenerator PROPERTIES
LINK_FLAGS "/SUBSYSTEM:CONSOLE")

# Embedding transitively provides the polyfills/plugins (NativeEngine,
# ShaderCache, ...) and their include paths. ShaderCache is listed explicitly
# because Main.cpp includes <Babylon/Plugins/ShaderCache.h> and calls Save().
# bx / Foundation are required by the reused Shared sources (Diagnostics.cpp,
# PlaygroundScripts.cpp). Shlwapi provides UrlCreateFromPathA for the file://
# script URL.
target_link_libraries(ShaderCacheGenerator
PRIVATE Embedding
PRIVATE ShaderCache
PRIVATE bx
PRIVATE Foundation
PRIVATE Shlwapi)

# Copy transitive runtime DLLs next to the executable.
add_custom_command(TARGET ShaderCacheGenerator POST_BUILD
COMMAND ${CMAKE_COMMAND} -E $<IF:$<BOOL:$<TARGET_RUNTIME_DLLS:ShaderCacheGenerator>>,copy,true> $<TARGET_RUNTIME_DLLS:ShaderCacheGenerator> $<TARGET_FILE_DIR:ShaderCacheGenerator> COMMAND_EXPAND_LISTS)

# Copy the ANGLE GL DLLs so the OpenGL backend can load at runtime.
if(ANGLE_LIBEGL)
add_custom_command(TARGET ShaderCacheGenerator POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ANGLE_LIBEGL}" "$<TARGET_FILE_DIR:ShaderCacheGenerator>"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ANGLE_LIBGLESV2}" "$<TARGET_FILE_DIR:ShaderCacheGenerator>"
COMMENT "Copying ANGLE libraries to ShaderCacheGenerator output directory")
endif()

set_property(TARGET ShaderCacheGenerator PROPERTY FOLDER Apps)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
source_group("Shared" FILES ${SHARED_SOURCES})
47 changes: 47 additions & 0 deletions Apps/ShaderCacheGenerator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ShaderCacheGenerator

Headless Win32 + OpenGL tool that builds a GPU shader cache for a Babylon.js
scene. It hosts the scene through the `Babylon::Embedding` Runtime/View API on a
hidden window (ANGLE OpenGL backend), renders frames until the scene's shaders
are compiled, then writes the `ShaderCache` to a file.

Command-line parsing, process diagnostics (console/crash/exit handling) and the
log callback are reused from `Apps/Playground/Shared`.

## Usage

```
ShaderCacheGenerator <scene.js> <output.bin> [shared options]
```

| Argument | Description |
| -------------- | -------------------------------------- |
| `<scene.js>` | Scene script to load (required). |
| `<output.bin>` | Shader cache file to write (required). |

`[shared options]` are the Playground command-line flags (run with `--help` to
list them); e.g. `--debug-trace=true`.

Exit codes: `0` success (>=1 shader written), `2` command-line / input error,
`1` runtime failure, `3` hard crash.

## Build

Configure BabylonNative for Win32 with the ANGLE OpenGL backend, then build the
target:

```
cmake -B build -G "Visual Studio 18 2026" -A x64 -D GRAPHICS_API=OpenGLWindowsDevOnly -D BABYLON_NATIVE_BUILD_APPS=ON
cmake --build build --target ShaderCacheGenerator --config Release
```

Requires an installed Edge/Chrome (for `libEGL.dll` / `libGLESv2.dll`). The
cache is GL-specific, so it is compatible with the Android OpenGL backend.

## "Scene ready" detection

There is no fixed frame count. The tool renders until the shader-cache entry
count stops growing for a number of consecutive checks -- i.e. the scene has
finished compiling every effect it uses. This is the meaningful signal for a
cache generator and works for any scene without it exposing globals. A frame cap
is applied only as a safety net.
Loading