Add apiLevel and add parsing logic (#9535)

This commit is contained in:
yein
2025-12-22 13:52:32 -08:00
committed by GitHub
parent 9fe7ab31ed
commit 53f506670c
6 changed files with 83 additions and 1 deletions

View File

@@ -131,3 +131,39 @@ TEST(Material, MaterialWithoutSourceMaterialReturnsEmptySource) {
engine->destroy(material);
Engine::destroy(engine);
}
TEST(Material, MaterialSettingValidApiLevelReturnsAnValidPackage) {
Engine* engine = Engine::create(Engine::Backend::NOOP);
filamat::MaterialBuilder builder;
builder.init();
builder.setApiLevel(filament::RELEASED_MATERIAL_API_LEVEL);
filamat::Package result = builder.build(engine->getJobSystem());
ASSERT_TRUE(result.isValid());
builder.init();
builder.setApiLevel(filament::UNSTABLE_MATERIAL_API_LEVEL);
result = builder.build(engine->getJobSystem());
ASSERT_TRUE(result.isValid());
Engine::destroy(engine);
}
TEST(Material, MaterialSettingInvalidApiLevelReturnsAnInvalidPackage) {
Engine* engine = Engine::create(Engine::Backend::NOOP);
filamat::MaterialBuilder builder;
builder.init();
// Set the API level higher than unstable, which is illegal.
builder.setApiLevel(filament::UNSTABLE_MATERIAL_API_LEVEL + 1);
filamat::Package result = builder.build(engine->getJobSystem());
ASSERT_FALSE(result.isValid());
builder.init();
// Set the API level lower than the minimum.
builder.setApiLevel(0);
result = builder.build(engine->getJobSystem());
ASSERT_FALSE(result.isValid());
Engine::destroy(engine);
}

View File

@@ -30,6 +30,15 @@ namespace filament {
// update this when a new version of filament wouldn't work with older materials
static constexpr size_t MATERIAL_VERSION = 68;
// Those are the api levels that are used in the source material file (.mat)
//
// The level used for the apis that are already public and stable. Any released api supports
// backward compatibility (i.e. No breaking changes will be introduced for those apis.)
static constexpr uint32_t RELEASED_MATERIAL_API_LEVEL = 1;
// The level used for the apis that are currently under development or development has completed
// but may introduce breaking changes.
static constexpr uint32_t UNSTABLE_MATERIAL_API_LEVEL = 2;
/**
* Supported shading models
*/

View File

@@ -666,6 +666,9 @@ public:
*/
MaterialBuilder& materialSource(std::string_view source) noexcept;
//! Set the (client requested) api level that the material is supposed to be compiled against.
MaterialBuilder& setApiLevel(uint32_t apiLevel) noexcept;
/**
* Build the material. If you are using the Filament engine with this library, you should use
* the job system provided by Engine.
@@ -990,6 +993,9 @@ private:
bool mNoSamplerValidation = false;
bool mUseDefaultDepthVariant = false;
// Default api level is always 1.
uint32_t mApiLevel = 1;
};
} // namespace filamat

View File

@@ -1257,6 +1257,11 @@ MaterialBuilder& MaterialBuilder::materialSource(std::string_view source) noexce
return *this;
}
MaterialBuilder& MaterialBuilder::setApiLevel(uint32_t apiLevel) noexcept {
mApiLevel = apiLevel;
return *this;
}
Package MaterialBuilder::build(JobSystem& jobSystem) {
if (materialBuilderClients == 0) {
slog.e << "Error: MaterialBuilder::init() must be called before build()." << io::endl;
@@ -1293,6 +1298,12 @@ error:
goto error;
}
if (mApiLevel < 1 || mApiLevel > filament::UNSTABLE_MATERIAL_API_LEVEL) {
slog.e << "Error: api level can't be set below 1 or above unstable material level(" <<
filament::UNSTABLE_MATERIAL_API_LEVEL << ")" << io::endl;
goto error;
}
// prepareToBuild must be called first, to populate mCodeGenPermutations.
MaterialInfo info{};
prepareToBuild(info);

View File

@@ -79,6 +79,11 @@ static utils::Status processName(MaterialBuilder& builder, const JsonishValue& v
return utils::Status::ok();
}
static utils::Status processApiLevel(MaterialBuilder& builder, const JsonishValue& value) {
builder.setApiLevel(value.toJsonNumber()->getFloat());
return utils::Status::ok();
}
static utils::Status processInterpolation(MaterialBuilder& builder, const JsonishValue& value) {
static const std::unordered_map<std::string, MaterialBuilder::Interpolation> strToEnum {
{ "smooth", MaterialBuilder::Interpolation::SMOOTH },
@@ -1406,6 +1411,7 @@ ParametersProcessor::ParametersProcessor() {
mParameters["useDefaultDepthVariant"] = { &processUseDefaultDepthVariant, Type::BOOL };
mParameters["linearFog"] = { &processLinearFog, Type::BOOL };
mParameters["shadowFarAttenuation"] = { &processShadowFarAttenuation, Type::BOOL };
mParameters["apiLevel"] = { &processApiLevel, Type::NUMBER };
}
utils::Status ParametersProcessor::process(MaterialBuilder& builder, const JsonishObject& jsonObject) {

View File

@@ -112,7 +112,7 @@ TEST_F(MaterialLexer, MaterialParserWithToolSection) {
matp::MaterialParser parser;
TestMaterialParser testParser(parser);
filamat::MaterialBuilder unused;
utils::Status result =testParser.parseMaterial(
utils::Status result = testParser.parseMaterial(
materialSourceWithTool.c_str(), materialSourceWithTool.size(), unused);
EXPECT_EQ(result.getCode(), utils::StatusCode::OK);
}
@@ -174,6 +174,20 @@ TEST_F(MaterialLexer, MaterialParserSyntaxError) {
EXPECT_EQ(result.getCode(), utils::StatusCode::INVALID_ARGUMENT);
}
TEST_F(MaterialLexer, MaterialParserCanParseApiLevel) {
static std::string sourceWithApiLevel(R"(
material {
apiLevel: 1,
}
)");
matp::MaterialParser parser;
TestMaterialParser testParser(parser);
filamat::MaterialBuilder unused;
utils::Status result =
testParser.parseMaterial(sourceWithApiLevel.c_str(), sourceWithApiLevel.size(), unused);
EXPECT_EQ(result.getCode(), utils::StatusCode::OK);
}
static std::string jsonMaterialSource(R"(
{
"fragment": "void material(inout MaterialInputs material) {