add a couple way of validating MaterialInstances (#7754)

* add a couple way of validating MaterialInstances

BUGS=[333907416]

* Update filament/include/filament/Engine.h

Co-authored-by: Powei Feng <powei@google.com>

* Update filament/include/filament/Engine.h

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
This commit is contained in:
Mathias Agopian
2024-04-16 12:12:20 -07:00
committed by GitHub
parent 8af2d7512d
commit b21dfd5ea2
7 changed files with 184 additions and 77 deletions

View File

@@ -342,6 +342,21 @@ Java_com_google_android_filament_Engine_nIsValidMaterial(JNIEnv*, jclass,
return (jboolean)engine->isValid((Material*)nativeMaterial);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidMaterialInstance(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeMaterial, jlong nativeMaterialInstance) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Material*)nativeMaterial,
(MaterialInstance*)nativeMaterialInstance);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidExpensiveMaterialInstance(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeMaterialInstance) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValidExpensive((MaterialInstance*)nativeMaterialInstance);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidSkybox(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeSkybox) {

View File

@@ -849,6 +849,24 @@ public class Engine {
return nIsValidMaterial(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidMaterialInstance(@NonNull Material ma, MaterialInstance mi) {
return nIsValidMaterialInstance(getNativeObject(), ma.getNativeObject(), mi.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidExpensiveMaterialInstance(@NonNull MaterialInstance object) {
return nIsValidExpensiveMaterialInstance(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
@@ -1291,6 +1309,8 @@ public class Engine {
private static native boolean nIsValidSkinningBuffer(long nativeEngine, long nativeSkinningBuffer);
private static native boolean nIsValidIndirectLight(long nativeEngine, long nativeIndirectLight);
private static native boolean nIsValidMaterial(long nativeEngine, long nativeMaterial);
private static native boolean nIsValidMaterialInstance(long nativeEngine, long nativeMaterial, long nativeMaterialInstance);
private static native boolean nIsValidExpensiveMaterialInstance(long nativeEngine, long nativeMaterialInstance);
private static native boolean nIsValidSkybox(long nativeEngine, long nativeSkybox);
private static native boolean nIsValidColorGrading(long nativeEngine, long nativeColorGrading);
private static native boolean nIsValidTexture(long nativeEngine, long nativeTexture);

View File

@@ -800,24 +800,51 @@ public:
bool destroy(const InstanceBuffer* UTILS_NULLABLE p); //!< Destroys an InstanceBuffer object.
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
bool isValid(const BufferObject* UTILS_NULLABLE p); //!< Tells whether a BufferObject object is valid
bool isValid(const VertexBuffer* UTILS_NULLABLE p); //!< Tells whether an VertexBuffer object is valid
bool isValid(const Fence* UTILS_NULLABLE p); //!< Tells whether a Fence object is valid
bool isValid(const IndexBuffer* UTILS_NULLABLE p); //!< Tells whether an IndexBuffer object is valid
bool isValid(const SkinningBuffer* UTILS_NULLABLE p); //!< Tells whether a SkinningBuffer object is valid
bool isValid(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Tells whether a MorphTargetBuffer object is valid
bool isValid(const IndirectLight* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Material* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Renderer* UTILS_NULLABLE p); //!< Tells whether a Renderer object is valid
bool isValid(const Scene* UTILS_NULLABLE p); //!< Tells whether a Scene object is valid
bool isValid(const Skybox* UTILS_NULLABLE p); //!< Tells whether a SkyBox object is valid
bool isValid(const ColorGrading* UTILS_NULLABLE p); //!< Tells whether a ColorGrading object is valid
bool isValid(const SwapChain* UTILS_NULLABLE p); //!< Tells whether a SwapChain object is valid
bool isValid(const Stream* UTILS_NULLABLE p); //!< Tells whether a Stream object is valid
bool isValid(const Texture* UTILS_NULLABLE p); //!< Tells whether a Texture object is valid
bool isValid(const RenderTarget* UTILS_NULLABLE p); //!< Tells whether a RenderTarget object is valid
bool isValid(const View* UTILS_NULLABLE p); //!< Tells whether a View object is valid
bool isValid(const InstanceBuffer* UTILS_NULLABLE p); //!< Tells whether an InstanceBuffer object is valid
/** Tells whether a BufferObject object is valid */
bool isValid(const BufferObject* UTILS_NULLABLE p) const;
/** Tells whether an VertexBuffer object is valid */
bool isValid(const VertexBuffer* UTILS_NULLABLE p) const;
/** Tells whether a Fence object is valid */
bool isValid(const Fence* UTILS_NULLABLE p) const;
/** Tells whether an IndexBuffer object is valid */
bool isValid(const IndexBuffer* UTILS_NULLABLE p) const;
/** Tells whether a SkinningBuffer object is valid */
bool isValid(const SkinningBuffer* UTILS_NULLABLE p) const;
/** Tells whether a MorphTargetBuffer object is valid */
bool isValid(const MorphTargetBuffer* UTILS_NULLABLE p) const;
/** Tells whether an IndirectLight object is valid */
bool isValid(const IndirectLight* UTILS_NULLABLE p) const;
/** Tells whether an Material object is valid */
bool isValid(const Material* UTILS_NULLABLE p) const;
/** Tells whether an MaterialInstance object is valid. Use this if you already know
* which Material this MaterialInstance belongs to. DO NOT USE getMaterial(), this would
* defeat the purpose of validating the MaterialInstance.
*/
bool isValid(const Material* UTILS_NONNULL m, const MaterialInstance* UTILS_NULLABLE p) const;
/** Tells whether an MaterialInstance object is valid. Use this if the Material the
* MaterialInstance belongs to is not known. This method can be expensive.
*/
bool isValidExpensive(const MaterialInstance* UTILS_NULLABLE p) const;
/** Tells whether a Renderer object is valid */
bool isValid(const Renderer* UTILS_NULLABLE p) const;
/** Tells whether a Scene object is valid */
bool isValid(const Scene* UTILS_NULLABLE p) const;
/** Tells whether a SkyBox object is valid */
bool isValid(const Skybox* UTILS_NULLABLE p) const;
/** Tells whether a ColorGrading object is valid */
bool isValid(const ColorGrading* UTILS_NULLABLE p) const;
/** Tells whether a SwapChain object is valid */
bool isValid(const SwapChain* UTILS_NULLABLE p) const;
/** Tells whether a Stream object is valid */
bool isValid(const Stream* UTILS_NULLABLE p) const;
/** Tells whether a Texture object is valid */
bool isValid(const Texture* UTILS_NULLABLE p) const;
/** Tells whether a RenderTarget object is valid */
bool isValid(const RenderTarget* UTILS_NULLABLE p) const;
/** Tells whether a View object is valid */
bool isValid(const View* UTILS_NULLABLE p) const;
/** Tells whether an InstanceBuffer object is valid */
bool isValid(const InstanceBuffer* UTILS_NULLABLE p) const;
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until

View File

@@ -31,18 +31,25 @@
#include "details/Texture.h"
#include "details/VertexBuffer.h"
#include "details/View.h"
#include "filament/Engine.h"
#include <filament/Engine.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Panic.h>
#include <stddef.h>
#include <stdint.h>
using namespace utils;
namespace filament {
namespace backend {
class Platform;
}
using namespace math;
using namespace backend;
@@ -196,58 +203,64 @@ void Engine::destroy(Entity e) {
downcast(this)->destroy(e);
}
bool Engine::isValid(const BufferObject* p) {
bool Engine::isValid(const BufferObject* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const VertexBuffer* p) {
bool Engine::isValid(const VertexBuffer* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Fence* p) {
bool Engine::isValid(const Fence* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const IndexBuffer* p) {
bool Engine::isValid(const IndexBuffer* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const SkinningBuffer* p) {
bool Engine::isValid(const SkinningBuffer* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const MorphTargetBuffer* p) {
bool Engine::isValid(const MorphTargetBuffer* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const IndirectLight* p) {
bool Engine::isValid(const IndirectLight* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Material* p) {
bool Engine::isValid(const Material* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Renderer* p) {
bool Engine::isValid(const Material* m, const MaterialInstance* p) const {
return downcast(this)->isValid(downcast(m), downcast(p));
}
bool Engine::isValidExpensive(const MaterialInstance* p) const {
return downcast(this)->isValidExpensive(downcast(p));
}
bool Engine::isValid(const Renderer* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Scene* p) {
bool Engine::isValid(const Scene* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Skybox* p) {
bool Engine::isValid(const Skybox* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const ColorGrading* p) {
bool Engine::isValid(const ColorGrading* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const SwapChain* p) {
bool Engine::isValid(const SwapChain* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Stream* p) {
bool Engine::isValid(const Stream* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const Texture* p) {
bool Engine::isValid(const Texture* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const RenderTarget* p) {
bool Engine::isValid(const RenderTarget* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const View* p) {
bool Engine::isValid(const View* p) const {
return downcast(this)->isValid(downcast(p));
}
bool Engine::isValid(const InstanceBuffer* p) {
bool Engine::isValid(const InstanceBuffer* p) const {
return downcast(this)->isValid(downcast(p));
}

View File

@@ -915,8 +915,9 @@ void FEngine::cleanupResourceListLocked(Lock& lock, ResourceList<T>&& list) {
template<typename T>
UTILS_ALWAYS_INLINE
inline bool FEngine::isValid(const T* ptr, ResourceList<T>& list) {
return list.find(ptr) != list.end();
inline bool FEngine::isValid(const T* ptr, ResourceList<T> const& list) const {
auto& l = const_cast<ResourceList<T>&>(list);
return l.find(ptr) != l.end();
}
template<typename T>
@@ -1086,75 +1087,99 @@ void FEngine::destroy(Entity e) {
mCameraManager.destroy(*this, e);
}
bool FEngine::isValid(const FBufferObject* p) {
bool FEngine::isValid(const FBufferObject* p) const {
return isValid(p, mBufferObjects);
}
bool FEngine::isValid(const FVertexBuffer* p) {
bool FEngine::isValid(const FVertexBuffer* p) const {
return isValid(p, mVertexBuffers);
}
bool FEngine::isValid(const FFence* p) {
bool FEngine::isValid(const FFence* p) const {
return isValid(p, mFences);
}
bool FEngine::isValid(const FIndexBuffer* p) {
bool FEngine::isValid(const FIndexBuffer* p) const {
return isValid(p, mIndexBuffers);
}
bool FEngine::isValid(const FSkinningBuffer* p) {
bool FEngine::isValid(const FSkinningBuffer* p) const {
return isValid(p, mSkinningBuffers);
}
bool FEngine::isValid(const FMorphTargetBuffer* p) {
bool FEngine::isValid(const FMorphTargetBuffer* p) const {
return isValid(p, mMorphTargetBuffers);
}
bool FEngine::isValid(const FIndirectLight* p) {
bool FEngine::isValid(const FIndirectLight* p) const {
return isValid(p, mIndirectLights);
}
bool FEngine::isValid(const FMaterial* p) {
bool FEngine::isValid(const FMaterial* p) const {
return isValid(p, mMaterials);
}
bool FEngine::isValid(const FRenderer* p) {
bool FEngine::isValid(const FMaterial* m, const FMaterialInstance* p) const {
// first make sure the material we're given is valid.
if (!isValid(m)) {
return false;
}
// then find the material instance list for that material
auto it = mMaterialInstances.find(m);
if (it == mMaterialInstances.end()) {
// this could happen if this material has no material instances at all
return false;
}
// finally validate the material instance
return isValid(p, it->second);
}
bool FEngine::isValidExpensive(const FMaterialInstance* p) const {
return std::any_of(mMaterialInstances.cbegin(), mMaterialInstances.cend(),
[this, p](auto&& entry) {
return isValid(p, entry.second);
});
}
bool FEngine::isValid(const FRenderer* p) const {
return isValid(p, mRenderers);
}
bool FEngine::isValid(const FScene* p) {
bool FEngine::isValid(const FScene* p) const {
return isValid(p, mScenes);
}
bool FEngine::isValid(const FSkybox* p) {
bool FEngine::isValid(const FSkybox* p) const {
return isValid(p, mSkyboxes);
}
bool FEngine::isValid(const FColorGrading* p) {
bool FEngine::isValid(const FColorGrading* p) const {
return isValid(p, mColorGradings);
}
bool FEngine::isValid(const FSwapChain* p) {
bool FEngine::isValid(const FSwapChain* p) const {
return isValid(p, mSwapChains);
}
bool FEngine::isValid(const FStream* p) {
bool FEngine::isValid(const FStream* p) const {
return isValid(p, mStreams);
}
bool FEngine::isValid(const FTexture* p) {
bool FEngine::isValid(const FTexture* p) const {
return isValid(p, mTextures);
}
bool FEngine::isValid(const FRenderTarget* p) {
bool FEngine::isValid(const FRenderTarget* p) const {
return isValid(p, mRenderTargets);
}
bool FEngine::isValid(const FView* p) {
bool FEngine::isValid(const FView* p) const {
return isValid(p, mViews);
}
bool FEngine::isValid(const FInstanceBuffer* p) {
bool FEngine::isValid(const FInstanceBuffer* p) const {
return isValid(p, mInstanceBuffers);
}

View File

@@ -318,25 +318,26 @@ public:
bool destroy(const FView* p);
bool destroy(const FInstanceBuffer* p);
bool isValid(const FBufferObject* p);
bool isValid(const FVertexBuffer* p);
bool isValid(const FFence* p);
bool isValid(const FIndexBuffer* p);
bool isValid(const FSkinningBuffer* p);
bool isValid(const FMorphTargetBuffer* p);
bool isValid(const FIndirectLight* p);
bool isValid(const FMaterial* p);
bool isValid(const FMaterialInstance* p);
bool isValid(const FRenderer* p);
bool isValid(const FScene* p);
bool isValid(const FSkybox* p);
bool isValid(const FColorGrading* p);
bool isValid(const FSwapChain* p);
bool isValid(const FStream* p);
bool isValid(const FTexture* p);
bool isValid(const FRenderTarget* p);
bool isValid(const FView* p);
bool isValid(const FInstanceBuffer* p);
bool isValid(const FBufferObject* p) const;
bool isValid(const FVertexBuffer* p) const;
bool isValid(const FFence* p) const;
bool isValid(const FIndexBuffer* p) const;
bool isValid(const FSkinningBuffer* p) const;
bool isValid(const FMorphTargetBuffer* p) const;
bool isValid(const FIndirectLight* p) const;
bool isValid(const FMaterial* p) const;
bool isValid(const FMaterial* m, const FMaterialInstance* p) const;
bool isValidExpensive(const FMaterialInstance* p) const;
bool isValid(const FRenderer* p) const;
bool isValid(const FScene* p) const;
bool isValid(const FSkybox* p) const;
bool isValid(const FColorGrading* p) const;
bool isValid(const FSwapChain* p) const;
bool isValid(const FStream* p) const;
bool isValid(const FTexture* p) const;
bool isValid(const FRenderTarget* p) const;
bool isValid(const FView* p) const;
bool isValid(const FInstanceBuffer* p) const;
void destroy(utils::Entity e);
@@ -444,7 +445,7 @@ private:
backend::Driver& getDriver() const noexcept { return *mDriver; }
template<typename T>
bool isValid(const T* ptr, ResourceList<T>& list);
bool isValid(const T* ptr, ResourceList<T> const& list) const;
template<typename T>
bool terminateAndDestroy(const T* p, ResourceList<T>& list);

View File

@@ -576,6 +576,12 @@ class_<Engine>("Engine")
.function("isValidMaterial", EMBIND_LAMBDA(bool, (Engine* engine, Material* object), {
return engine->isValid(object);
}), allow_raw_pointers())
.function("isValidMaterialInstance", EMBIND_LAMBDA(bool, (Engine* engine, Material* ma, MaterialInstance* mi), {
return engine->isValid(ma, mi);
}), allow_raw_pointers())
.function("isValidExpensiveMaterialInstance", EMBIND_LAMBDA(bool, (Engine* engine, MaterialInstance* object), {
return engine->isValidExpensive(object);
}), allow_raw_pointers())
.function("isValidSkybox", EMBIND_LAMBDA(bool, (Engine* engine, Skybox* object), {
return engine->isValid(object);
}), allow_raw_pointers())