diff --git a/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt b/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt index a82d6dc4ec..29c892313f 100644 --- a/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt +++ b/android/filament-utils-android/src/main/java/com/google/android/filament/utils/ModelViewer.kt @@ -221,6 +221,7 @@ class ModelViewer(val engine: Engine) : android.view.View.OnTouchListener { fun destroyModel() { fetchResourcesJob?.cancel() resourceLoader.asyncCancelLoad() + resourceLoader.evictResourceData() asset?.let { asset -> this.scene.removeEntities(asset.entities) assetLoader.destroyAsset(asset) diff --git a/android/gltfio-android/src/main/cpp/ResourceLoader.cpp b/android/gltfio-android/src/main/cpp/ResourceLoader.cpp index 0f84627103..2795eb6e7f 100644 --- a/android/gltfio-android/src/main/cpp/ResourceLoader.cpp +++ b/android/gltfio-android/src/main/cpp/ResourceLoader.cpp @@ -70,6 +70,13 @@ Java_com_google_android_filament_gltfio_ResourceLoader_nHasResourceData(JNIEnv* return status; } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_gltfio_ResourceLoader_nEvictResourceData(JNIEnv*, jclass, + jlong nativeLoader) { + ResourceLoader* loader = (ResourceLoader*) nativeLoader; + loader->evictResourceData(); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_gltfio_ResourceLoader_nLoadResources(JNIEnv*, jclass, jlong nativeLoader, jlong nativeAsset) { diff --git a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/ResourceLoader.java b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/ResourceLoader.java index d3c2ab2fae..bd39de2aaf 100644 --- a/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/ResourceLoader.java +++ b/android/gltfio-android/src/main/java/com/google/android/filament/gltfio/ResourceLoader.java @@ -101,6 +101,15 @@ public class ResourceLoader { return nHasResourceData(mNativeObject, uri); } + /** + * Frees memory by evicting the URI cache that was populated via addResourceData. + * + * This can be called only after a model is fully loaded or after loading has been cancelled. + */ + public void evictResourceData() { + nEvictResourceData(mNativeObject); + } + /** * Iterates through all external buffers and images and creates corresponding Filament objects * (vertex buffers, textures, etc), which become owned by the asset. @@ -161,6 +170,7 @@ public class ResourceLoader { private static native void nDestroyResourceLoader(long nativeLoader); private static native void nAddResourceData(long nativeLoader, String url, Buffer buffer, int remaining); + private static native void nEvictResourceData(long nativeLoader); private static native boolean nHasResourceData(long nativeLoader, String url); private static native void nLoadResources(long nativeLoader, long nativeAsset); private static native boolean nAsyncBeginLoad(long nativeLoader, long nativeAsset); diff --git a/libs/gltfio/include/gltfio/ResourceLoader.h b/libs/gltfio/include/gltfio/ResourceLoader.h index a0f6022d27..5a701e80d3 100644 --- a/libs/gltfio/include/gltfio/ResourceLoader.h +++ b/libs/gltfio/include/gltfio/ResourceLoader.h @@ -93,6 +93,13 @@ public: */ bool hasResourceData(const char* uri) const; + /** + * Frees memory by evicting the URI cache that was populated via addResourceData. + * + * This can be called only after a model is fully loaded or after loading has been cancelled. + */ + void evictResourceData(); + /** * Loads resources for the given asset from the filesystem or data cache and "finalizes" the * asset by transforming the vertex data format if necessary, decoding image files, supplying diff --git a/libs/gltfio/src/ResourceLoader.cpp b/libs/gltfio/src/ResourceLoader.cpp index 175702246c..e4dc07db30 100644 --- a/libs/gltfio/src/ResourceLoader.cpp +++ b/libs/gltfio/src/ResourceLoader.cpp @@ -269,6 +269,11 @@ bool ResourceLoader::hasResourceData(const char* uri) const { return pImpl->mUriDataCache.find(uri) != pImpl->mUriDataCache.end(); } +void ResourceLoader::evictResourceData() { + // Note that this triggers BufferDescriptor callbacks. + pImpl->mUriDataCache.clear(); +} + bool ResourceLoader::loadResources(FilamentAsset* asset) { FFilamentAsset* fasset = upcast(asset); return loadResources(fasset, false); diff --git a/samples/gltf_viewer.cpp b/samples/gltf_viewer.cpp index a653501a5c..32e487034e 100644 --- a/samples/gltf_viewer.cpp +++ b/samples/gltf_viewer.cpp @@ -1017,6 +1017,7 @@ int main(int argc, char** argv) { filamentApp.setDropHandler([&] (std::string path) { app.resourceLoader->asyncCancelLoad(); + app.resourceLoader->evictResourceData(); app.viewer->removeAsset(); app.assetLoader->destroyAsset(app.asset); loadAsset(path);