Skip to content

Commit 3ce752c

Browse files
authored
gltfio: enable passing in variant filters (#8851)
This enables filtering variants when using the JitMaterialProvider.
1 parent 1f9f3dd commit 3ce752c

File tree

10 files changed

+176
-33
lines changed

10 files changed

+176
-33
lines changed

libs/gltfio/include/gltfio/MaterialProvider.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <filament/Material.h>
2222
#include <filament/MaterialInstance.h>
2323

24+
#include <utils/FixedCapacityVector.h>
2425
#include <utils/compiler.h>
2526

2627
#include <array>
@@ -196,14 +197,16 @@ void processShaderString(std::string* shader, const UvMap& uvmap,
196197
* Creates a material provider that builds materials on the fly, composing GLSL at run time.
197198
*
198199
* @param optimizeShaders Optimizes shaders, but at significant cost to construction time.
200+
* @param variantFilters Filter out variants that are not required.
199201
* @return New material provider that can build materials at run time.
200202
*
201203
* Requires \c libfilamat to be linked in. Not available in \c libgltfio_core.
202204
*
203205
* @see createUbershaderProvider
204206
*/
205207
UTILS_PUBLIC
206-
MaterialProvider* createJitShaderProvider(Engine* engine, bool optimizeShaders = false);
208+
MaterialProvider* createJitShaderProvider(Engine* engine, bool optimizeShaders = false,
209+
utils::FixedCapacityVector<char const*> const& variantFilters = {});
207210

208211
/**
209212
* Creates a material provider that loads a small set of pre-built materials.

libs/gltfio/src/JitShaderProvider.cpp

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616

1717
#include <gltfio/MaterialProvider.h>
1818

19+
#include <filament/MaterialEnums.h>
1920
#include <filamat/MaterialBuilder.h>
2021

2122
#include <utils/Hash.h>
2223

2324
#include <tsl/robin_map.h>
2425

2526
#include <string>
27+
#include <unordered_map>
2628

2729
using namespace filamat;
2830
using namespace filament;
@@ -33,7 +35,8 @@ namespace {
3335

3436
class JitShaderProvider : public MaterialProvider {
3537
public:
36-
explicit JitShaderProvider(Engine* engine, bool optimizeShaders);
38+
explicit JitShaderProvider(Engine* engine, bool optimizeShaders,
39+
utils::FixedCapacityVector<char const*> const& variantFilters);
3740
~JitShaderProvider() override;
3841

3942
MaterialInstance* createMaterialInstance(MaterialKey* config, UvMap* uvmap,
@@ -49,15 +52,37 @@ class JitShaderProvider : public MaterialProvider {
4952
return false;
5053
}
5154

55+
private:
5256
using HashFn = hash::MurmurHashFn<MaterialKey>;
5357
tsl::robin_map<MaterialKey, Material*, HashFn> mCache;
5458
std::vector<Material*> mMaterials;
5559
Engine* const mEngine;
5660
const bool mOptimizeShaders;
61+
filament::UserVariantFilterMask mVariantFilter;
5762
};
5863

59-
JitShaderProvider::JitShaderProvider(Engine* engine, bool optimizeShaders) : mEngine(engine),
60-
mOptimizeShaders(optimizeShaders) {
64+
JitShaderProvider::JitShaderProvider(Engine* engine, bool optimizeShaders,
65+
utils::FixedCapacityVector<char const*> const& variantFilters)
66+
: mEngine(engine),
67+
mOptimizeShaders(optimizeShaders) {
68+
69+
// Note that this is the same as the list in tools/matc/src/ParametersProcessor.cpp
70+
static const std::unordered_map<std::string, filament::UserVariantFilterBit> strToEnum = [] {
71+
std::unordered_map<std::string, filament::UserVariantFilterBit> strToEnum;
72+
strToEnum["directionalLighting"] = filament::UserVariantFilterBit::DIRECTIONAL_LIGHTING;
73+
strToEnum["dynamicLighting"] = filament::UserVariantFilterBit::DYNAMIC_LIGHTING;
74+
strToEnum["shadowReceiver"] = filament::UserVariantFilterBit::SHADOW_RECEIVER;
75+
strToEnum["skinning"] = filament::UserVariantFilterBit::SKINNING;
76+
strToEnum["vsm"] = filament::UserVariantFilterBit::VSM;
77+
strToEnum["fog"] = filament::UserVariantFilterBit::FOG;
78+
strToEnum["ssr"] = filament::UserVariantFilterBit::SSR;
79+
strToEnum["stereo"] = filament::UserVariantFilterBit::STE;
80+
return strToEnum;
81+
}();
82+
83+
for (auto& filterStr : variantFilters) {
84+
mVariantFilter |= (uint32_t)strToEnum.at(filterStr);
85+
}
6186
MaterialBuilder::init();
6287
}
6388

@@ -344,24 +369,25 @@ std::string shaderFromKey(const MaterialKey& config) {
344369
}
345370

346371
Material* createMaterial(Engine* engine, const MaterialKey& config, const UvMap& uvmap,
347-
const char* name, bool optimizeShaders) {
372+
const char* name, bool optimizeShaders, filament::UserVariantFilterMask variantFilter) {
348373
std::string shader = shaderFromKey(config);
349374
processShaderString(&shader, uvmap, config);
350375
MaterialBuilder builder;
351376
builder.name(name)
352-
.flipUV(false)
353-
.specularAmbientOcclusion(MaterialBuilder::SpecularAmbientOcclusion::SIMPLE)
354-
.specularAntiAliasing(true)
355-
.clearCoatIorChange(false)
356-
.material(shader.c_str())
357-
.doubleSided(config.doubleSided)
358-
.transparencyMode(config.doubleSided ?
359-
MaterialBuilder::TransparencyMode::TWO_PASSES_TWO_SIDES :
360-
MaterialBuilder::TransparencyMode::DEFAULT)
361-
.reflectionMode(MaterialBuilder::ReflectionMode::SCREEN_SPACE)
362-
.targetApi(filamat::targetApiFromBackend(engine->getBackend()))
363-
.stereoscopicType(engine->getConfig().stereoscopicType)
364-
.stereoscopicEyeCount(engine->getConfig().stereoscopicEyeCount);
377+
.flipUV(false)
378+
.specularAmbientOcclusion(MaterialBuilder::SpecularAmbientOcclusion::SIMPLE)
379+
.specularAntiAliasing(true)
380+
.clearCoatIorChange(false)
381+
.material(shader.c_str())
382+
.doubleSided(config.doubleSided)
383+
.transparencyMode(config.doubleSided
384+
? MaterialBuilder::TransparencyMode::TWO_PASSES_TWO_SIDES
385+
: MaterialBuilder::TransparencyMode::DEFAULT)
386+
.reflectionMode(MaterialBuilder::ReflectionMode::SCREEN_SPACE)
387+
.targetApi(filamat::targetApiFromBackend(engine->getBackend()))
388+
.stereoscopicType(engine->getConfig().stereoscopicType)
389+
.stereoscopicEyeCount(engine->getConfig().stereoscopicEyeCount)
390+
.variantFilter(variantFilter);
365391

366392
if (!optimizeShaders) {
367393
builder.optimization(MaterialBuilder::Optimization::NONE);
@@ -589,13 +615,13 @@ Material* JitShaderProvider::getMaterial(MaterialKey* config, UvMap* uvmap, cons
589615
constrainMaterial(config, uvmap);
590616
auto iter = mCache.find(*config);
591617
if (iter == mCache.end()) {
592-
593618
bool optimizeShaders = mOptimizeShaders;
594619
#ifndef NDEBUG
595620
optimizeShaders = false;
596621
#endif
597622

598-
Material* mat = createMaterial(mEngine, *config, *uvmap, label, optimizeShaders);
623+
Material* mat =
624+
createMaterial(mEngine, *config, *uvmap, label, optimizeShaders, mVariantFilter);
599625
mCache.emplace(std::make_pair(*config, mat));
600626
mMaterials.push_back(mat);
601627
return mat;
@@ -612,8 +638,9 @@ MaterialInstance* JitShaderProvider::createMaterialInstance(MaterialKey* config,
612638

613639
namespace filament::gltfio {
614640

615-
MaterialProvider* createJitShaderProvider(filament::Engine* engine, bool optimizeShaders) {
616-
return new JitShaderProvider(engine, optimizeShaders);
641+
MaterialProvider* createJitShaderProvider(Engine* engine, bool optimizeShaders,
642+
utils::FixedCapacityVector<char const*> const& variantFilters) {
643+
return new JitShaderProvider(engine, optimizeShaders, variantFilters);
617644
}
618645

619646
} // namespace filament::gltfio

samples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ target_sources(gltf-demo-resources PRIVATE ${RESGEN_SOURCE})
223223

224224
add_library(samples-common STATIC
225225
common/arguments.cpp
226+
common/configuration.h
227+
common/configuration.cpp
226228
)
227229

228230
target_include_directories(samples-common PRIVATE

samples/common/arguments.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "arguments.h"
18+
1719
#include <filament/Engine.h>
1820

1921
#include <utils/Path.h>

samples/common/arguments.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
#include <string>
2323

2424
namespace samples {
25-
filament::Engine::Backend parseArgumentsForBackend(int argc, char* argv[]);
26-
filament::Engine::Backend parseArgumentsForBackend(const std::string& backend);
27-
std::string getBackendAPIArgumentsUsage();
28-
}
25+
26+
filament::Engine::Backend parseArgumentsForBackend(int argc, char* argv[]);
27+
filament::Engine::Backend parseArgumentsForBackend(const std::string& backend);
28+
std::string getBackendAPIArgumentsUsage();
29+
30+
} // namespace samples
2931
#endif //TNT_SAMPLES_ARGUMENTS_H

samples/common/configuration.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (C) 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "configuration.h"
18+
19+
#include <filament/Engine.h>
20+
21+
#include <utils/FixedCapacityVector.h>
22+
23+
#include <unordered_map>
24+
25+
namespace samples {
26+
27+
namespace {
28+
29+
using FilterVector = utils::FixedCapacityVector<char const*>;
30+
std::unordered_map<filament::Engine::Backend, FilterVector> gFilters;
31+
32+
// TODO: This is not necessary once we can support these variants in webgpu.
33+
char const* WEBGPU_VARIANT_FILTERS[] = {
34+
"skinning",
35+
"stereo",
36+
};
37+
38+
} // namespace anonymous
39+
40+
FilterVector const& getJitMaterialVariantFilter(filament::Engine::Backend backend) {
41+
if (auto itr = gFilters.find(backend); itr != gFilters.end()) {
42+
return itr->second;
43+
}
44+
auto build = [&](char const** filters, size_t filterCount) -> FilterVector {
45+
utils::FixedCapacityVector<char const*> filterStr;
46+
filterStr.clear();
47+
filterStr.reserve(filterCount);
48+
for (size_t i = 0; i < filterCount; ++i) {
49+
filterStr.push_back(filters[i]);
50+
}
51+
return filterStr;
52+
};
53+
54+
switch (backend) {
55+
case filament::Engine::Backend::WEBGPU:
56+
gFilters[backend] = build(WEBGPU_VARIANT_FILTERS,
57+
sizeof(WEBGPU_VARIANT_FILTERS) / sizeof(char const*));
58+
break;
59+
default:
60+
gFilters[backend] = build(nullptr, 0);
61+
}
62+
return gFilters[backend];
63+
}
64+
65+
} // namespace samples

samples/common/configuration.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (C) 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef TNT_SAMPLES_CONFIGURATION_H
18+
#define TNT_SAMPLES_CONFIGURATION_H
19+
20+
#include <filament/Engine.h>
21+
22+
#include <utils/FixedCapacityVector.h>
23+
24+
namespace samples {
25+
26+
utils::FixedCapacityVector<char const*> const& getJitMaterialVariantFilter(
27+
filament::Engine::Backend backend);
28+
29+
}
30+
31+
#endif // TNT_SAMPLES_CONFIGURATION_H

samples/gltf_instances.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include "common/arguments.h"
18+
#include "common/configuration.h"
1819

1920
#include <filamentapp/Config.h>
2021
#include <filamentapp/FilamentApp.h>
@@ -244,8 +245,11 @@ int main(int argc, char** argv) {
244245
app.names = new NameComponentManager(EntityManager::get());
245246
app.viewer = new ViewerGui(engine, scene, view);
246247

247-
app.materials = (app.materialSource == JITSHADER) ? createJitShaderProvider(engine) :
248-
createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE);
248+
app.materials = (app.materialSource == JITSHADER)
249+
? createJitShaderProvider(engine, false /* optimize */,
250+
samples::getJitMaterialVariantFilter(app.config.backend))
251+
: createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA,
252+
UBERARCHIVE_DEFAULT_SIZE);
249253

250254
app.loader = AssetLoader::create({engine, app.materials, app.names });
251255
if (filename.isEmpty()) {

samples/gltf_viewer.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include "common/arguments.h"
18+
#include "common/configuration.h"
1819

1920
#include <filamentapp/Config.h>
2021
#include <filamentapp/FilamentApp.h>
@@ -778,11 +779,13 @@ int main(int argc, char** argv) {
778779
}
779780
}
780781

781-
app.materials = (app.materialSource == JITSHADER) ?
782-
createJitShaderProvider(engine, OPTIMIZE_MATERIALS) :
783-
createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE);
782+
app.materials = (app.materialSource == JITSHADER)
783+
? createJitShaderProvider(engine, OPTIMIZE_MATERIALS,
784+
samples::getJitMaterialVariantFilter(app.config.backend))
785+
: createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA,
786+
UBERARCHIVE_DEFAULT_SIZE);
784787

785-
app.assetLoader = AssetLoader::create({engine, app.materials, app.names });
788+
app.assetLoader = AssetLoader::create({ engine, app.materials, app.names });
786789
app.mainCamera = &view->getCamera();
787790
if (filename.isEmpty()) {
788791
app.asset = app.assetLoader->createAsset(

samples/simple_gltf_test.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
#include "common/arguments.h"
18+
#include "common/configuration.h"
1719

1820
#include <filamentapp/Config.h>
1921
#include <filamentapp/FilamentApp.h>
@@ -222,8 +224,10 @@ int main(int argc, char** argv) {
222224
app.names = new NameComponentManager(EntityManager::get());
223225
app.viewer = new ViewerGui(engine, scene, view);
224226

227+
225228
app.materials = (app.materialSource == JITSHADER)
226-
? createJitShaderProvider(engine)
229+
? createJitShaderProvider(engine, false /* optimize */,
230+
samples::getJitMaterialVariantFilter(app.config.backend))
227231
: createUbershaderProvider(engine, UBERARCHIVE_DEFAULT_DATA,
228232
UBERARCHIVE_DEFAULT_SIZE);
229233

0 commit comments

Comments
 (0)