Move sampler bindings outside of material blobs (#682)
This commit is contained in:
@@ -418,9 +418,10 @@ Handle<HwProgram> 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;
|
||||
}();
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "FilamentAPI-impl.h"
|
||||
|
||||
#include <filament/driver/DriverEnums.h>
|
||||
|
||||
#include <private/filament/SibGenerator.h>
|
||||
#include <private/filament/UibGenerator.h>
|
||||
#include <private/filament/Variant.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
|
||||
#include <filament/driver/DriverEnums.h>
|
||||
#include <filament/EngineEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/CString.h>
|
||||
@@ -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
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "TextDictionaryReader.h"
|
||||
#include "SpirvDictionaryReader.h"
|
||||
|
||||
#include <filament/SamplerBindingMap.h>
|
||||
#include <private/filament/SamplerInterfaceBlock.h>
|
||||
#include <private/filament/UniformInterfaceBlock.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<bool> matDepthWriteSet(ChunkType::MaterialDepthWriteSet, mDepthWriteSet);
|
||||
container.addChild(&matDepthWriteSet);
|
||||
|
||||
@@ -452,6 +446,13 @@ Package MaterialBuilder::build() noexcept {
|
||||
const TargetApi codeGenTargetApi = params.codeGenTargetApi;
|
||||
std::vector<uint32_t>* pSpirv = (targetApi == TargetApi::VULKAN) ? &spirv : nullptr;
|
||||
|
||||
// Re-populate the set of sampler bindings for this API.
|
||||
filament::SamplerBindingMap map;
|
||||
auto backend = static_cast<filament::driver::Backend>(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<filament::driver::Backend>(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);
|
||||
|
||||
@@ -55,12 +55,6 @@ Package PostprocessMaterialBuilder::build() {
|
||||
BlobDictionary spirvDictionary;
|
||||
std::vector<uint32_t> 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<uint32_t>* 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<filament::driver::Backend>(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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user