engine: add MaterialInstance::compile()

This commit is contained in:
Eliza Velasquez
2026-03-06 15:31:46 +09:00
committed by Eliza
parent 5d6b62de3e
commit 038062ec77
4 changed files with 53 additions and 13 deletions

View File

@@ -330,6 +330,43 @@ public:
return getConstant<T>(name, strlen(name));
}
using CompilerPriorityQueue = backend::CompilerPriorityQueue;
/**
* Asynchronously ensures that a subset of this MaterialInstance's variants are compiled.
*
* This function behaves identically to Material::compile(), but takes into account the
* specific constants overridden by setConstant().
*
* @param priority Which priority queue to use, LOW or HIGH.
* @param variants Variants to include to the compile command.
* @param handler Handler to dispatch the callback or nullptr for the default handler
* @param callback callback called on the main thread when the compilation is done on
* by backend.
*
* @see Material::compile
* @see setConstant
*/
void compile(CompilerPriorityQueue priority,
UserVariantFilterMask variants,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept;
inline void compile(CompilerPriorityQueue priority,
UserVariantFilterBit variants,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterMask(variants), handler,
std::forward<utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>>(callback));
}
inline void compile(CompilerPriorityQueue priority,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterBit::ALL, handler,
std::forward<utils::Invocable<void(MaterialInstance* UTILS_NONNULL)>>(callback));
}
/**
* Set-up a custom scissor rectangle; by default it is disabled.
*

View File

@@ -235,11 +235,17 @@ filament::DescriptorSetLayout const& FMaterial::getPerViewDescriptorSetLayout(
return mDefinition.perViewDescriptorSetLayoutPcf;
}
void FMaterial::compile(CompilerPriorityQueue const priority,
UserVariantFilterMask variantSpec,
CallbackHandler* handler,
Invocable<void(Material*)>&& callback) noexcept {
getDefaultInstance()->compile(mEngine, priority, variantSpec, handler, std::move(callback));
void FMaterial::compile(CompilerPriorityQueue const priority, UserVariantFilterMask variantSpec,
CallbackHandler* handler, Invocable<void(Material*)>&& callback) noexcept {
FMaterialInstance* mi = getDefaultInstance();
if (callback) {
mi->compile(mEngine, priority, variantSpec, handler,
[this, callback = std::move(callback)](MaterialInstance*) {
callback(this);
});
} else {
mi->compile(mEngine, priority, variantSpec, handler, {});
}
}
FMaterialInstance* FMaterial::createInstance(const char* name) const noexcept {

View File

@@ -448,8 +448,7 @@ const char* FMaterialInstance::getName() const noexcept {
void FMaterialInstance::compile(FEngine& engine, CompilerPriorityQueue const priority,
UserVariantFilterMask variantSpec, CallbackHandler* handler,
Invocable<void(Material*)>&& callback) noexcept {
Invocable<void(MaterialInstance*)>&& callback) noexcept {
DriverApi& driver = engine.getDriverApi();
MaterialDefinition const& definition = mMaterial->getDefinition();
@@ -476,17 +475,15 @@ void FMaterialInstance::compile(FEngine& engine, CompilerPriorityQueue const pri
if (callback) {
struct Callback {
Invocable<void(Material*)> f;
Material* m;
Invocable<void(MaterialInstance*)> f;
MaterialInstance* m;
static void func(void* user) {
auto* const c = static_cast<Callback*>(user);
c->f(c->m);
delete c;
}
};
// TODO(exv): fix this const cast
auto* const user = new (std::nothrow) Callback{ std::move(callback),
const_cast<Material*>(static_cast<Material const*>(mMaterial)) };
auto* const user = new (std::nothrow) Callback{ std::move(callback), this };
driver.compilePrograms(priority, handler, &Callback::func, user);
} else {
driver.compilePrograms(priority, nullptr, nullptr, nullptr);

View File

@@ -86,7 +86,7 @@ public:
void compile(FEngine& engine, backend::CompilerPriorityQueue priority,
UserVariantFilterMask variantSpec, backend::CallbackHandler* handler,
utils::Invocable<void(Material*)>&& callback) noexcept;
utils::Invocable<void(MaterialInstance*)>&& callback) noexcept;
// prepareProgram creates the program for the material's given variant at the backend level.
// Must be called outside of backend render pass.