diff --git a/filament/src/Engine.cpp b/filament/src/Engine.cpp index cc26518db3..02e259c044 100644 --- a/filament/src/Engine.cpp +++ b/filament/src/Engine.cpp @@ -418,9 +418,10 @@ Handle FEngine::createPostProcessProgram(MaterialParser& parser, // need to populate a SamplerBindingMap and pass a weak reference to Program. Binding maps are // normally owned by Material, but in this case we'll simply own a copy right here in static // storage. - static const SamplerBindingMap* pBindings = [] { + static const SamplerBindingMap* pBindings = [backend = this->mBackend] { static SamplerBindingMap bindings; - bindings.populate(); + uint8_t offset = filament::getSamplerBindingsStart(backend); + bindings.populate(offset); return &bindings; }(); diff --git a/filament/src/Material.cpp b/filament/src/Material.cpp index d47c8e432f..21e4ca6941 100644 --- a/filament/src/Material.cpp +++ b/filament/src/Material.cpp @@ -22,6 +22,8 @@ #include "FilamentAPI-impl.h" +#include + #include #include #include @@ -123,9 +125,9 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder) UTILS_UNUSED_IN_RELEASE bool uibOK = parser->getUIB(&mUniformInterfaceBlock); assert(uibOK); - // Sampler bindings are only required for Vulkan. - UTILS_UNUSED_IN_RELEASE bool sbOK = parser->getSamplerBindingMap(&mSamplerBindings); - assert(engine.getBackend() == Backend::OPENGL || sbOK); + // Populate sampler bindings for the backend that will consume this Material. + const uint8_t offset = getSamplerBindingsStart(engine.getBackend()); + mSamplerBindings.populate(offset, &mSamplerInterfaceBlock); parser->getShading(&mShading); parser->getBlendingMode(&mBlendingMode); diff --git a/libs/filabridge/include/filament/SamplerBindingMap.h b/libs/filabridge/include/filament/SamplerBindingMap.h index 30d59a90d7..98c27d3c48 100644 --- a/libs/filabridge/include/filament/SamplerBindingMap.h +++ b/libs/filabridge/include/filament/SamplerBindingMap.h @@ -47,10 +47,12 @@ class SamplerInterfaceBlock; // Also stores the mapping as a flat vector of 4-tuples to make it easy to [de]serialize. class SamplerBindingMap { public: - // Assigns a range of finalized binding points to each sampler block. If a per-material SIB - // is provided, then material samplers are also inserted (always at the end). The optional - // material name is used for error reporting only. - void populate(SamplerInterfaceBlock* perMaterialSib = nullptr, + // Assigns a range of finalized binding points to each sampler block. + // Samples are given monotonically increasing binding points starting with firstSamplerBinding. + // If a per-material SIB is provided, then material samplers are also inserted (always at the + // end). The optional material name is used for error reporting only. + void populate(uint8_t firstSamplerBinding, + const SamplerInterfaceBlock* perMaterialSib = nullptr, const char* materialName = nullptr); // Given a valid Filament binding point and an offset with the block, returns true and sets diff --git a/libs/filabridge/include/private/filament/SamplerInterfaceBlock.h b/libs/filabridge/include/private/filament/SamplerInterfaceBlock.h index fef3274181..f82ebe4df1 100644 --- a/libs/filabridge/include/private/filament/SamplerInterfaceBlock.h +++ b/libs/filabridge/include/private/filament/SamplerInterfaceBlock.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -141,6 +142,20 @@ private: uint32_t mSize = 0; // size in Samplers (i.e.: count) }; +// Returns the binding point of the first sampler for the given backend API. +inline constexpr uint8_t getSamplerBindingsStart(driver::Backend api) noexcept { + switch (api) { + default: + case driver::Backend::OPENGL: + case driver::Backend::VULKAN: { + // Vulkan and OpenGL have a single namespace for uniforms and samplers. + // To avoid collision, the sampler bindings start after the last UBO binding. + const uint8_t numUniformBlockBindings = filament::BindingPoints::COUNT; + return numUniformBlockBindings; + } + } +} + } // namespace filament #endif // TNT_FILAMENT_DRIVER_SAMPLERINTERFACEBLOCK_H diff --git a/libs/filabridge/src/SamplerBindingMap.cpp b/libs/filabridge/src/SamplerBindingMap.cpp index 69da0131a4..47f2ee7084 100644 --- a/libs/filabridge/src/SamplerBindingMap.cpp +++ b/libs/filabridge/src/SamplerBindingMap.cpp @@ -24,10 +24,10 @@ namespace filament { -void SamplerBindingMap::populate(SamplerInterfaceBlock* perMaterialSib, const char* materialName) { - // To avoid collision, the sampler bindings start after the last UBO binding. - const uint8_t numUniformBlockBindings = filament::BindingPoints::COUNT; - uint8_t offset = numUniformBlockBindings; +void SamplerBindingMap::populate(uint8_t firstSamplerBinding, + const SamplerInterfaceBlock* perMaterialSib, const char* materialName) { + uint8_t offset = firstSamplerBinding; + size_t maxSamplerIndex = firstSamplerBinding + filament::MAX_SAMPLER_COUNT - 1; bool overflow = false; for (uint8_t blockIndex = 0; blockIndex < filament::BindingPoints::COUNT; blockIndex++) { mSamplerBlockOffsets[blockIndex] = offset; @@ -40,7 +40,7 @@ void SamplerBindingMap::populate(SamplerInterfaceBlock* perMaterialSib, const ch if (sib) { auto sibFields = sib->getSamplerInfoList(); for (auto sInfo : sibFields) { - if (offset - numUniformBlockBindings >= filament::MAX_SAMPLER_COUNT) { + if (offset > maxSamplerIndex) { overflow = true; } addSampler({ diff --git a/libs/filaflat/include/filaflat/FilaflatDefs.h b/libs/filaflat/include/filaflat/FilaflatDefs.h index 2b5aba3fca..84e70aa0d4 100644 --- a/libs/filaflat/include/filaflat/FilaflatDefs.h +++ b/libs/filaflat/include/filaflat/FilaflatDefs.h @@ -56,7 +56,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t { MaterialGlsl = charTo64bitNum("MAT_GLSL"), MaterialSpirv = charTo64bitNum("MAT_SPIR"), MaterialShaderModels = charTo64bitNum("MAT_SMDL"), - MaterialSamplerBindings = charTo64bitNum("MAT_SAMP"), + MaterialSamplerBindings = charTo64bitNum("MAT_SAMP"), // no longer used MaterialName = charTo64bitNum("MAT_NAME"), MaterialVersion = charTo64bitNum("MAT_VERS"), diff --git a/libs/filaflat/include/filaflat/MaterialParser.h b/libs/filaflat/include/filaflat/MaterialParser.h index 4eb06d6779..ea8fa79bf2 100644 --- a/libs/filaflat/include/filaflat/MaterialParser.h +++ b/libs/filaflat/include/filaflat/MaterialParser.h @@ -30,7 +30,6 @@ namespace filament { class UniformInterfaceBlock; class SamplerInterfaceBlock; -class SamplerBindingMap; } namespace filaflat { @@ -56,7 +55,6 @@ public: bool getName(utils::CString*) const noexcept; bool getUIB(filament::UniformInterfaceBlock* uib) const noexcept; bool getSIB(filament::SamplerInterfaceBlock* sib) const noexcept; - bool getSamplerBindingMap(filament::SamplerBindingMap*) const noexcept; bool getShaderModels(uint32_t* value) const noexcept; bool getDepthWriteSet(bool* value) const noexcept; diff --git a/libs/filaflat/src/ChunkInterfaceBlock.cpp b/libs/filaflat/src/ChunkInterfaceBlock.cpp index 4a97270077..b4ee72c993 100644 --- a/libs/filaflat/src/ChunkInterfaceBlock.cpp +++ b/libs/filaflat/src/ChunkInterfaceBlock.cpp @@ -124,37 +124,4 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener, return true; } -bool ChunkSamplerBindingsBlock::unflatten(Unflattener& unflattener, - filament::SamplerBindingMap* map) { - assert(map); - - uint64_t numFields = 0 ; - if (!unflattener.read(&numFields) ) { - return false; - } - - for (uint64_t i = 0; i < numFields; i++) { - SamplerBindingInfo info; - if (!unflattener.read(&info.blockIndex)) { - return false; - } - - if (!unflattener.read(&info.localOffset)) { - return false; - } - - if (!unflattener.read(&info.globalOffset)) { - return false; - } - - if (!unflattener.read(&info.groupIndex)) { - return false; - } - - map->addSampler(info); - } - - return true; -} - } // namespace filaflat diff --git a/libs/filaflat/src/ChunkInterfaceBlock.h b/libs/filaflat/src/ChunkInterfaceBlock.h index 0e532289f8..ac3be09fcc 100644 --- a/libs/filaflat/src/ChunkInterfaceBlock.h +++ b/libs/filaflat/src/ChunkInterfaceBlock.h @@ -32,10 +32,6 @@ struct ChunkSamplerInterfaceBlock { bool unflatten(Unflattener& unflattener,filament::SamplerInterfaceBlock*); }; -struct ChunkSamplerBindingsBlock { - bool unflatten(Unflattener& unflattener,filament::SamplerBindingMap*); -}; - } // namespace filamat #endif // TNT_FILAMAT_CHUNK_IB_H diff --git a/libs/filaflat/src/MaterialParser.cpp b/libs/filaflat/src/MaterialParser.cpp index dfad754edd..ca4b677554 100644 --- a/libs/filaflat/src/MaterialParser.cpp +++ b/libs/filaflat/src/MaterialParser.cpp @@ -26,7 +26,6 @@ #include "TextDictionaryReader.h" #include "SpirvDictionaryReader.h" -#include #include #include @@ -170,20 +169,6 @@ bool MaterialParser::getSIB(filament::SamplerInterfaceBlock* sib) const noexcept return ChunkSamplerInterfaceBlock().unflatten(unflattener, sib); } -bool MaterialParser::getSamplerBindingMap(filament::SamplerBindingMap* bindings) const noexcept { - auto type = MaterialSamplerBindings; - - if (!mImpl->mChunkContainer.hasChunk(type)) { - return false; - } - - const uint8_t* start = mImpl->mChunkContainer.getChunkStart(type); - const uint8_t* end = mImpl->mChunkContainer.getChunkEnd(type); - Unflattener unflattener(start, end); - - return ChunkSamplerBindingsBlock().unflatten(unflattener, bindings); -} - bool MaterialParser::getShaderModels(uint32_t* value) const noexcept { return mImpl->getFromSimpleChunk(ChunkType::MaterialShaderModels, value); } diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 648868f3b3..167e0f7e50 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -290,7 +290,6 @@ void MaterialBuilder::prepareToBuild(MaterialInfo& info) noexcept { info.blendingMode = mBlendingMode; info.shading = mShading; info.hasShadowMultiplier = mShadowMultiplier; - info.samplerBindings.populate(&info.sib, mMaterialName.c_str()); } bool MaterialBuilder::runStaticCodeAnalysis() noexcept { @@ -391,11 +390,6 @@ Package MaterialBuilder::build() noexcept { MaterialSamplerInterfaceBlockChunk matSib = MaterialSamplerInterfaceBlockChunk(info.sib); container.addChild(&matSib); - MaterialSamplerBindingsChunk matSb = MaterialSamplerBindingsChunk(info.samplerBindings); - if (mTargetApi == TargetApi::VULKAN || mTargetApi == TargetApi::ALL) { - container.addChild(&matSb); - } - SimpleFieldChunk matDepthWriteSet(ChunkType::MaterialDepthWriteSet, mDepthWriteSet); container.addChild(&matDepthWriteSet); @@ -452,6 +446,13 @@ Package MaterialBuilder::build() noexcept { const TargetApi codeGenTargetApi = params.codeGenTargetApi; std::vector* pSpirv = (targetApi == TargetApi::VULKAN) ? &spirv : nullptr; + // Re-populate the set of sampler bindings for this API. + filament::SamplerBindingMap map; + auto backend = static_cast(params.targetApi); + uint8_t offset = filament::getSamplerBindingsStart(backend); + map.populate(offset, &info.sib, mMaterialName.c_str()); + info.samplerBindings = std::move(map); + TextEntry glslEntry; SpirvEntry spirvEntry; @@ -592,6 +593,14 @@ const std::string MaterialBuilder::peek(filament::driver::ShaderType type, model = ShaderModel(params.shaderModel); const TargetApi targetApi = params.targetApi; const TargetApi codeGenTargetApi = params.codeGenTargetApi; + + // Re-populate the set of sampler bindings for this API. + filament::SamplerBindingMap map; + auto backend = static_cast(params.targetApi); + uint8_t offset = filament::getSamplerBindingsStart(backend); + map.populate(offset, &info.sib, mMaterialName.c_str()); + info.samplerBindings = std::move(map); + if (type == filament::driver::ShaderType::VERTEX) { return sg.createVertexProgram(model, targetApi, codeGenTargetApi, info, 0, mInterpolation, mVertexDomain); diff --git a/libs/filamat/src/PostprocessMaterialBuilder.cpp b/libs/filamat/src/PostprocessMaterialBuilder.cpp index 09fe4cd2f5..50e5f48108 100644 --- a/libs/filamat/src/PostprocessMaterialBuilder.cpp +++ b/libs/filamat/src/PostprocessMaterialBuilder.cpp @@ -55,12 +55,6 @@ Package PostprocessMaterialBuilder::build() { BlobDictionary spirvDictionary; std::vector spirv; - // Populate a SamplerBindingMap for the sole purpose of finding where the post-process bindings - // live within the global namespace of samplers. - filament::SamplerBindingMap samplerBindingMap; - samplerBindingMap.populate(); - const uint8_t firstSampler = - samplerBindingMap.getBlockOffset(filament::BindingPoints::POST_PROCESS); bool errorOccured = false; for (const auto& params : mCodeGenPermutations) { @@ -69,6 +63,15 @@ Package PostprocessMaterialBuilder::build() { const TargetApi codeGenTargetApi = params.codeGenTargetApi; std::vector* pSpirv = (targetApi == TargetApi::VULKAN) ? &spirv : nullptr; + // Populate a SamplerBindingMap for the sole purpose of finding where the post-process bindings + // live within the global namespace of samplers. + filament::SamplerBindingMap samplerBindingMap; + auto backend = static_cast(params.targetApi); + uint8_t offset = filament::getSamplerBindingsStart(backend); + samplerBindingMap.populate(offset); + const uint8_t firstSampler = + samplerBindingMap.getBlockOffset(filament::BindingPoints::POST_PROCESS); + TextEntry glslEntry; SpirvEntry spirvEntry; diff --git a/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.cpp b/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.cpp index d62f236a3c..a192f62690 100644 --- a/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.cpp +++ b/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.cpp @@ -56,19 +56,4 @@ void MaterialSamplerInterfaceBlockChunk::flatten(Flattener &f) { } } -MaterialSamplerBindingsChunk::MaterialSamplerBindingsChunk(const SamplerBindingMap& sb) : - Chunk(ChunkType::MaterialSamplerBindings), mSamplerBindings(sb) { -} - -void MaterialSamplerBindingsChunk::flatten(Flattener &f) { - const auto& bindings = mSamplerBindings.getBindingList(); - f.writeUint64(bindings.size()); - for (auto info: bindings) { - f.writeUint8(info.blockIndex); - f.writeUint8(info.localOffset); - f.writeUint8(info.globalOffset); - f.writeUint8(info.groupIndex); - } -} - } diff --git a/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.h b/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.h index bd0549393f..114138d8ae 100644 --- a/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.h +++ b/libs/filamat/src/eiff/MaterialInterfaceBlockChunk.h @@ -46,15 +46,5 @@ private: filament::SamplerInterfaceBlock& mSib; }; -class MaterialSamplerBindingsChunk : public Chunk { -public: - MaterialSamplerBindingsChunk(const filament::SamplerBindingMap& samplerBindings); - virtual ~MaterialSamplerBindingsChunk() = default; - - virtual void flatten(Flattener &) override; -private: - const filament::SamplerBindingMap& mSamplerBindings; -}; - } // namespace filamat #endif // TNT_FILAMAT_MAT_INFO_CHUNK_H