Skip to content

Commit 02223dc

Browse files
authored
Add a way to specify an additional uniform name along with a sampler param for the associated transform matrix (#8490)
BUGS=[399959254]
1 parent 47112f1 commit 02223dc

File tree

9 files changed

+93
-18
lines changed

9 files changed

+93
-18
lines changed

NEW_RELEASE_NOTES.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ for next branch cut* header.
77
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
88

99
## Release notes for next branch cut
10+
- materials: add an optional `transformName` field to sampler material parameters. [⚠️ **New Material Version**]

docs/Materials.md.html

+5-2
Original file line numberDiff line numberDiff line change
@@ -991,10 +991,13 @@
991991

992992
Value
993993
: Each entry is an object with the properties `name` and `type`, both of `string` type. The
994-
name must be a valid GLSL identifier. Entries also have an optional `precision`, which can be
994+
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
995995
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
996996
mobile), `low`, `medium`, `high`. The type must be one of the types described in
997-
table [materialParamsTypes].
997+
table [materialParamsTypes]. For Android external textures, entries also have an optional
998+
transformName parameter to specify the name of the material parameter that will be
999+
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
1000+
this will always be identity.
9981001

9991002
Type | Description
10001003
:----------------------|:---------------------------------

filament/src/MaterialParser.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ bool ChunkUniformInterfaceBlock::unflatten(Unflattener& unflattener,
421421
uint64_t fieldSize = 0;
422422
uint8_t fieldType = 0;
423423
uint8_t fieldPrecision = 0;
424+
uint8_t fieldAssociatedSampler = 0;
424425

425426
if (!unflattener.read(&fieldName)) {
426427
return false;
@@ -438,8 +439,13 @@ bool ChunkUniformInterfaceBlock::unflatten(Unflattener& unflattener,
438439
return false;
439440
}
440441

442+
if (!unflattener.read(&fieldAssociatedSampler)) {
443+
return false;
444+
}
445+
441446
// a size of 1 means not an array
442447
builder.add({{{ fieldName.data(), fieldName.size() },
448+
fieldAssociatedSampler,
443449
uint32_t(fieldSize == 1 ? 0 : fieldSize),
444450
BufferInterfaceBlock::Type(fieldType),
445451
BufferInterfaceBlock::Precision(fieldPrecision) }});

libs/filabridge/include/private/filament/BufferInterfaceBlock.h

+28-5
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,28 @@ class BufferInterfaceBlock {
4040
std::string_view name;
4141
uint32_t size;
4242
backend::UniformType type;
43-
backend::Precision precision{};
44-
backend::FeatureLevel minFeatureLevel = backend::FeatureLevel::FEATURE_LEVEL_1;
45-
std::string_view structName{};
46-
uint32_t stride{};
47-
std::string_view sizeName{};
43+
backend::Precision precision;
44+
uint8_t associatedSampler = 0;
45+
backend::FeatureLevel minFeatureLevel;
46+
std::string_view structName;
47+
uint32_t stride;
48+
std::string_view sizeName;
49+
50+
InterfaceBlockEntry() = default;
51+
InterfaceBlockEntry(std::string_view name, uint32_t size, backend::UniformType type,
52+
backend::Precision precision = {},
53+
backend::FeatureLevel minFeatureLevel = backend::FeatureLevel::FEATURE_LEVEL_1, std::string_view structName = {},
54+
uint32_t stride = {}, std::string_view sizeName = {}) noexcept
55+
: name(name), size(size), type(type), precision(precision),
56+
associatedSampler(0), minFeatureLevel(minFeatureLevel),
57+
structName(structName), stride(stride), sizeName(sizeName) {}
58+
InterfaceBlockEntry(std::string_view name, uint8_t associatedSampler, uint32_t size, backend::UniformType type,
59+
backend::Precision precision = {},
60+
backend::FeatureLevel minFeatureLevel = backend::FeatureLevel::FEATURE_LEVEL_1, std::string_view structName = {},
61+
uint32_t stride = {}, std::string_view sizeName = {}) noexcept
62+
: name(name), size(size), type(type), precision(precision),
63+
associatedSampler(associatedSampler), minFeatureLevel(minFeatureLevel),
64+
structName(structName), stride(stride), sizeName(sizeName) {}
4865
};
4966

5067
BufferInterfaceBlock();
@@ -68,6 +85,7 @@ class BufferInterfaceBlock {
6885
bool isArray; // true if the field is an array
6986
uint32_t size; // size of the array in elements, or 0 if not an array
7087
Precision precision; // precision of this field
88+
uint8_t associatedSampler; // sampler associated with this field
7189
backend::FeatureLevel minFeatureLevel; // below this feature level, this field is not needed
7290
utils::CString structName; // name of this field structure if type is STRUCT
7391
utils::CString sizeName; // name of the size parameter in the shader
@@ -152,6 +170,10 @@ class BufferInterfaceBlock {
152170
// negative value if name doesn't exist or Panic if exceptions are enabled
153171
ssize_t getFieldOffset(std::string_view name, size_t index) const;
154172

173+
// returns offset in bytes of the transform matrix for the given external texture binding
174+
// returns -1 if the field doesn't exist
175+
ssize_t getTransformFieldOffset(uint8_t binding) const;
176+
155177
FieldInfo const* getFieldInfo(std::string_view name) const;
156178

157179
bool hasField(std::string_view name) const noexcept {
@@ -179,6 +201,7 @@ class BufferInterfaceBlock {
179201
utils::CString mName;
180202
utils::FixedCapacityVector<FieldInfo> mFieldInfoList;
181203
std::unordered_map<std::string_view , uint32_t> mInfoMap;
204+
std::unordered_map<uint8_t, uint32_t> mTransformOffsetMap;
182205
uint32_t mSize = 0; // size in bytes rounded to multiple of 4
183206
Alignment mAlignment = Alignment::std140;
184207
Target mTarget = Target::UNIFORM;

libs/filabridge/src/BufferInterfaceBlock.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ BufferInterfaceBlock::Builder& BufferInterfaceBlock::Builder::add(
5858
for (auto const& item : list) {
5959
mEntries.push_back({
6060
{ item.name.data(), item.name.size() },
61-
0, uint8_t(item.stride), item.type, item.size > 0, item.size, item.precision, item.minFeatureLevel,
61+
0, uint8_t(item.stride), item.type, item.size > 0, item.size, item.precision, item.associatedSampler, item.minFeatureLevel,
6262
{ item.structName.data(), item.structName.size() },
6363
{ item.sizeName.data(), item.sizeName.size() }
6464
});
@@ -71,7 +71,7 @@ BufferInterfaceBlock::Builder& BufferInterfaceBlock::Builder::addVariableSizedAr
7171
mHasVariableSizeArray = true;
7272
mEntries.push_back({
7373
{ item.name.data(), item.name.size() },
74-
0, uint8_t(item.stride), item.type, true, 0, item.precision, item.minFeatureLevel,
74+
0, uint8_t(item.stride), item.type, true, 0, item.precision, item.associatedSampler, item.minFeatureLevel,
7575
{ item.structName.data(), item.structName.size() },
7676
{ item.sizeName.data(), item.sizeName.size() }
7777
});
@@ -122,6 +122,8 @@ BufferInterfaceBlock::BufferInterfaceBlock(Builder const& builder) noexcept
122122

123123
auto& uniformsInfoList = mFieldInfoList;
124124

125+
auto& transformOffsetMap = mTransformOffsetMap;
126+
125127
uint32_t i = 0;
126128
uint16_t offset = 0;
127129
for (auto const& e : builder.mEntries) {
@@ -143,11 +145,16 @@ BufferInterfaceBlock::BufferInterfaceBlock(Builder const& builder) noexcept
143145

144146
FieldInfo& info = uniformsInfoList[i];
145147
info = { e.name, offset, uint8_t(stride), e.type, e.isArray, e.size,
146-
e.precision, e.minFeatureLevel, e.structName, e.sizeName };
148+
e.precision, e.associatedSampler, e.minFeatureLevel, e.structName, e.sizeName };
147149

148150
// record this uniform info
149151
infoMap[{ info.name.data(), info.name.size() }] = i;
150152

153+
// record the transform offset if this is an external sampler
154+
if (e.associatedSampler != 0) {
155+
transformOffsetMap[e.associatedSampler] = offset;
156+
}
157+
151158
// advance offset to next slot
152159
offset += stride * std::max(1u, e.size);
153160
++i;
@@ -163,6 +170,14 @@ ssize_t BufferInterfaceBlock::getFieldOffset(std::string_view name, size_t index
163170
return (ssize_t)info->getBufferOffset(index);
164171
}
165172

173+
ssize_t BufferInterfaceBlock::getTransformFieldOffset(uint8_t binding) const {
174+
auto pos = mTransformOffsetMap.find(binding);
175+
if (pos == mTransformOffsetMap.end()) {
176+
return -1;
177+
}
178+
return (ssize_t)pos->second;
179+
}
180+
166181
BufferInterfaceBlock::FieldInfo const* BufferInterfaceBlock::getFieldInfo(
167182
std::string_view name) const {
168183
auto pos = mInfoMap.find(name);

libs/filamat/include/filamat/MaterialBuilder.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
318318
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
319319
SamplerFormat format = SamplerFormat::FLOAT,
320320
ParameterPrecision precision = ParameterPrecision::DEFAULT,
321-
bool multisample = false) noexcept;
321+
bool multisample = false,
322+
const char* transformName = "") noexcept;
322323

323324
MaterialBuilder& buffer(filament::BufferInterfaceBlock bib) noexcept;
324325

@@ -650,8 +651,8 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
650651
Parameter() noexcept: parameterType(INVALID) {}
651652

652653
// Sampler
653-
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p, bool ms)
654-
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER), multisample(ms) { }
654+
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p, bool ms, const char* tn)
655+
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER), multisample(ms), transformName(tn) { }
655656

656657
// Uniform
657658
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
@@ -669,6 +670,7 @@ class UTILS_PUBLIC MaterialBuilder : public MaterialBuilderBase {
669670
SubpassType subpassType;
670671
SamplerFormat format;
671672
bool multisample;
673+
utils::CString transformName;
672674
enum {
673675
INVALID,
674676
UNIFORM,

libs/filamat/src/MaterialBuilder.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, UniformType type,
279279

280280

281281
MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType samplerType,
282-
SamplerFormat format, ParameterPrecision precision, bool multisample) noexcept {
282+
SamplerFormat format, ParameterPrecision precision, bool multisample, const char* transformName) noexcept {
283283
FILAMENT_CHECK_PRECONDITION(!multisample ||
284284
(format != SamplerFormat::SHADOW &&
285285
(samplerType == SamplerType::SAMPLER_2D ||
@@ -288,7 +288,7 @@ MaterialBuilder& MaterialBuilder::parameter(const char* name, SamplerType sample
288288
" as long as type is not SHADOW";
289289

290290
FILAMENT_CHECK_POSTCONDITION(mParameterCount < MAX_PARAMETERS_COUNT) << "Too many parameters";
291-
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample };
291+
mParameters[mParameterCount++] = { name, samplerType, format, precision, multisample, transformName };
292292
return *this;
293293
}
294294

@@ -609,12 +609,18 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept {
609609
SamplerInterfaceBlock::Builder sbb;
610610
BufferInterfaceBlock::Builder ibb;
611611
// sampler bindings start at 1, 0 is the ubo
612-
for (size_t i = 0, binding = 1, c = mParameterCount; i < c; i++) {
612+
uint16_t binding = 1;
613+
for (size_t i = 0, c = mParameterCount; i < c; i++) {
613614
auto const& param = mParameters[i];
614615
assert_invariant(!param.isSubpass());
615616
if (param.isSampler()) {
616617
sbb.add({ param.name.data(), param.name.size() },
617-
binding++, param.samplerType, param.format, param.precision, param.multisample);
618+
binding, param.samplerType, param.format, param.precision, param.multisample);
619+
if (!param.transformName.empty()) {
620+
ibb.add({{{ param.transformName.data(), param.transformName.size() }, uint8_t(binding),
621+
0, UniformType::MAT3, Precision::DEFAULT, FeatureLevel::FEATURE_LEVEL_0 }});
622+
}
623+
binding++;
618624
} else if (param.isUniform()) {
619625
ibb.add({{{ param.name.data(), param.name.size() },
620626
uint32_t(param.size == 1u ? 0u : param.size), param.uniformType,

libs/filamat/src/eiff/MaterialInterfaceBlockChunk.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ void MaterialUniformInterfaceBlockChunk::flatten(Flattener& f) {
5252
f.writeUint64(uInfo.size);
5353
f.writeUint8(static_cast<uint8_t>(uInfo.type));
5454
f.writeUint8(static_cast<uint8_t>(uInfo.precision));
55+
f.writeUint8(static_cast<uint8_t>(uInfo.associatedSampler));
5556
}
5657
}
5758

tools/matc/src/matc/ParametersProcessor.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
153153
std::cerr << "parameters: name value must be STRING." << std::endl;
154154
return false;
155155
}
156+
157+
const JsonishValue* transformNameValue = jsonObject.getValue("transformName");
158+
if (transformNameValue && transformNameValue->getType() != JsonishValue::STRING) {
159+
std::cerr << "parameters: transformName value must be STRING." << std::endl;
160+
return false;
161+
}
156162

157163
const JsonishValue* precisionValue = jsonObject.getValue("precision");
158164
if (precisionValue) {
@@ -221,7 +227,19 @@ static bool processParameter(MaterialBuilder& builder, const JsonishObject& json
221227

222228
auto multisample = multiSampleValue ? multiSampleValue->toJsonBool()->getBool() : false;
223229

224-
builder.parameter(nameString.c_str(), type, format, precision, multisample);
230+
if (transformNameValue) {
231+
if (type != MaterialBuilder::SamplerType::SAMPLER_EXTERNAL) {
232+
std::cerr << "parameters: the parameter with name '" << nameString << "'"
233+
<< " is a sampler of type " << typeString << " and has a transformName."
234+
<< " Transform names are only supported for external samplers."
235+
<< std::endl;
236+
return false;
237+
}
238+
auto transformName = transformNameValue->toJsonString()->getString();
239+
builder.parameter(nameString.c_str(), type, format, precision, multisample, transformName.c_str());
240+
} else {
241+
builder.parameter(nameString.c_str(), type, format, precision, multisample);
242+
}
225243

226244
} else {
227245
std::cerr << "parameters: the type '" << typeString

0 commit comments

Comments
 (0)