Optimize and robustify asset prefetching and material loading.

- Parallelize asset prefetching (max 4 workers) with retry logic and on-screen error banner, replacing silent failures and cryptic WASM out-of-bounds crashes with explicit missing-file errors.
- Support binary Uint8Array/ArrayBuffer in C++ asset registry via typed_memory_view, preventing Embind string coercion from corrupting binary shader packages into ASCII text.
- Automatically glob .mat files in CMake instead of maintaining a manual list.
- Add missing reflection materials to prefetch arrays.
- Disable caching for index.html in web server so template/script updates apply on normal page reload without stale cache issues, the file is small so caching had a negligible upside.
- Add null resource and payload validation in ObjectManager::LoadMaterial before constructing Filament materials.

PiperOrigin-RevId: 963364509
Change-Id: I7de79df6a5cede4e54683415ee193f1c5a665286
This commit is contained in:
Matija Kecman
2026-08-12 04:38:02 -07:00
committed by Copybara-Service
parent fb03be0e4f
commit fca913b4f5
6 changed files with 95 additions and 54 deletions
+2 -1
View File
@@ -138,13 +138,14 @@ var Module = {
totalDependencies: 0,
monitorRunDependencies(left) { },
onRuntimeInitialized: () => {
// Define assets to prefetch, relative to the WASM directory.
const assetsToPrefetch = [
"assets/fontawesome-webfont.ttf",
"assets/ibl.ktx",
"assets/AtkinsonHyperlegibleNext[wght].ttf",
"assets/AtkinsonHyperlegibleMono-Regular.ttf",
"assets/pbr.filamat",
"assets/pbr_reflect.filamat",
"assets/pbr_packed_reflect.filamat",
"assets/pbr_transparent.filamat",
"assets/pbr_packed.filamat",
"assets/pbr_packed_transparent.filamat",
+5 -30
View File
@@ -92,43 +92,18 @@ add_library(mujoco::filament ALIAS ${MUJOCO_FILAMENT_TARGET_NAME})
set(ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets")
set(OUTPUT_ASSETS_DIR "${CMAKE_CURRENT_BINARY_DIR}/assets")
file(MAKE_DIRECTORY ${OUTPUT_ASSETS_DIR})
file(COPY
"${ASSETS_DIR}/ibl.ktx"
DESTINATION ${OUTPUT_ASSETS_DIR}
)
set(MATC_EXECUTABLE matc)
set(MATERIAL_FILES
pbr.mat
pbr_transparent.mat
pbr_packed.mat
pbr_packed_transparent.mat
pbr_reflect.mat
pbr_packed_reflect.mat
phong_2d_fade.mat
phong_2d.mat
phong_2d_reflect.mat
phong_2d_uv_fade.mat
phong_2d_uv.mat
phong_2d_uv_reflect.mat
phong_color_fade.mat
phong_color.mat
phong_color_reflect.mat
phong_cube_fade.mat
phong_cube.mat
phong_cube_reflect.mat
outline_composite.mat
outline_flatten.mat
outline_jumpflood.mat
decor.mat
unlit_depth.mat
unlit_segmentation.mat
unlit_ui.mat
)
file(GLOB MATERIAL_FILES CONFIGURE_DEPENDS "${ASSETS_DIR}/*.mat")
foreach(MATERIAL_FILE ${MATERIAL_FILES})
get_filename_component(MATERIAL_NAME ${MATERIAL_FILE} NAME_WE)
set(INPUT_FILE "${ASSETS_DIR}/${MATERIAL_FILE}")
foreach(INPUT_FILE ${MATERIAL_FILES})
get_filename_component(MATERIAL_NAME ${INPUT_FILE} NAME_WE)
get_filename_component(MATERIAL_FILE ${INPUT_FILE} NAME)
set(OUTPUT_FILE "${OUTPUT_ASSETS_DIR}/${MATERIAL_NAME}.filamat")
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
@@ -42,8 +42,19 @@ static filament::Material* LoadMaterial(filament::Engine* engine,
const std::string path = ResolveFilamentAssetPath(std::string(filename));
mjResource* resource =
mju_openResource("", path.c_str(), nullptr, nullptr, 0);
if (!resource) {
mju_error("Failed to open filament asset '%.*s' at '%s'",
static_cast<int>(filename.size()), filename.data(), path.c_str());
return nullptr;
}
void* payload = nullptr;
int size = mju_readResource(resource, const_cast<const void**>(&payload));
if (size <= 0 || !payload) {
mju_error("Failed to read filament asset '%.*s' (size=%d)",
static_cast<int>(filename.size()), filename.data(), size);
mju_closeResource(resource);
return nullptr;
}
filament::Material::Builder material_builder;
material_builder.package(payload, size);
filament::Material* material = material_builder.build(*engine);