clean-up our handling of descriptor-sets a bit more
the main aim of this PR is to consolidate how we access the "per view" descriptor set to a single place. some validation code is moved into DescriptorSets.cpp, so we get a more centralized idea of what we do with the descriptors. also factorize in one place the filtering of sampler list by layouts.
This commit is contained in:
committed by
Mathias Agopian
parent
6d413a4faf
commit
3e1ea7cdfd
@@ -34,14 +34,19 @@
|
||||
|
||||
#include "MetalArgumentBuffer.h"
|
||||
#include "SpirvFixup.h"
|
||||
#include "utils/ostream.h"
|
||||
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#ifdef FILAMENT_SUPPORTS_WEBGPU
|
||||
@@ -151,21 +156,16 @@ DescriptorSetLayout getPerMaterialDescriptorSet(SamplerInterfaceBlock const& sib
|
||||
return layout;
|
||||
}
|
||||
|
||||
static void collectDescriptorsForSet(filament::DescriptorSetBindingPoints set,
|
||||
static void collectDescriptorsForSet(DescriptorSetBindingPoints set,
|
||||
const GLSLPostProcessor::Config& config, DescriptorSetInfo& descriptors) {
|
||||
const MaterialInfo& material = *config.materialInfo;
|
||||
|
||||
DescriptorSetLayout const info = [&]() {
|
||||
// get the descriptor set layout for the given pinding point
|
||||
DescriptorSetLayout const descriptorSetLayout = [&] {
|
||||
switch (set) {
|
||||
case DescriptorSetBindingPoints::PER_VIEW: {
|
||||
if (filament::Variant::isValidDepthVariant(config.variant)) {
|
||||
return descriptor_sets::getDepthVariantLayout();
|
||||
}
|
||||
if (filament::Variant::isSSRVariant(config.variant)) {
|
||||
return descriptor_sets::getSsrVariantLayout();
|
||||
}
|
||||
return descriptor_sets::getPerViewDescriptorSetLayout(config.domain,
|
||||
config.variantFilter,
|
||||
return descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
|
||||
config.variant, config.domain, config.variantFilter,
|
||||
material.isLit || material.hasShadowMultiplier,
|
||||
material.reflectionMode,
|
||||
material.refractionMode);
|
||||
@@ -179,7 +179,8 @@ static void collectDescriptorsForSet(filament::DescriptorSetBindingPoints set,
|
||||
}
|
||||
}();
|
||||
|
||||
auto samplerList = [&]() {
|
||||
// get the sampler list for this binding point
|
||||
auto samplerList = [&] {
|
||||
switch (set) {
|
||||
case DescriptorSetBindingPoints::PER_VIEW:
|
||||
return SibGenerator::getPerViewSib(config.variant).getSamplerInfoList();
|
||||
@@ -192,42 +193,34 @@ static void collectDescriptorsForSet(filament::DescriptorSetBindingPoints set,
|
||||
}
|
||||
}();
|
||||
|
||||
// remove all the samplers that are not included in the descriptor-set layout
|
||||
samplerList.erase(std::remove_if(samplerList.begin(), samplerList.end(),
|
||||
[&info](auto const& entry) {
|
||||
auto pos = std::find_if(info.bindings.begin(),
|
||||
info.bindings.end(), [&entry](const auto& item) {
|
||||
return item.binding == entry.binding;
|
||||
});
|
||||
return pos == info.bindings.end();
|
||||
}),
|
||||
samplerList.end());
|
||||
// filter the list with the descriptor set layout
|
||||
auto const descriptorSetSamplerList =
|
||||
SamplerInterfaceBlock::filterSamplerList(std::move(samplerList), descriptorSetLayout);
|
||||
|
||||
auto getDescriptorName = [&](DescriptorSetBindingPoints set, descriptor_binding_t binding) {
|
||||
// helper to get the name of a descriptor for this set, given a binding.
|
||||
auto getDescriptorName = [set, &descriptorSetSamplerList](descriptor_binding_t binding) {
|
||||
if (set == DescriptorSetBindingPoints::PER_MATERIAL) {
|
||||
auto pos = std::find_if(samplerList.begin(), samplerList.end(),
|
||||
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
|
||||
[&](const auto& entry) { return entry.binding == binding; });
|
||||
if (pos == samplerList.end()) {
|
||||
if (pos == descriptorSetSamplerList.end()) {
|
||||
return descriptor_sets::getDescriptorName(set, binding);
|
||||
}
|
||||
SamplerInterfaceBlock::SamplerInfo& sampler = *pos;
|
||||
return sampler.uniformName;
|
||||
return pos->uniformName;
|
||||
}
|
||||
return descriptor_sets::getDescriptorName(set, binding);
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < info.bindings.size(); i++) {
|
||||
backend::descriptor_binding_t binding = info.bindings[i].binding;
|
||||
auto name = getDescriptorName(set, binding);
|
||||
if (info.bindings[i].type == DescriptorType::SAMPLER ||
|
||||
info.bindings[i].type == DescriptorType::SAMPLER_EXTERNAL) {
|
||||
auto pos = std::find_if(samplerList.begin(), samplerList.end(),
|
||||
for (auto descriptor : descriptorSetLayout.bindings) {
|
||||
descriptor_binding_t binding = descriptor.binding;
|
||||
auto name = getDescriptorName(binding);
|
||||
if (descriptor.type == DescriptorType::SAMPLER ||
|
||||
descriptor.type == DescriptorType::SAMPLER_EXTERNAL) {
|
||||
auto pos = std::find_if(descriptorSetSamplerList.begin(), descriptorSetSamplerList.end(),
|
||||
[&](const auto& entry) { return entry.binding == binding; });
|
||||
assert_invariant(pos != samplerList.end());
|
||||
SamplerInterfaceBlock::SamplerInfo& sampler = *pos;
|
||||
descriptors.emplace_back(name, info.bindings[i], sampler);
|
||||
assert_invariant(pos != descriptorSetSamplerList.end());
|
||||
descriptors.emplace_back(name, descriptor, *pos);
|
||||
} else {
|
||||
descriptors.emplace_back(name, info.bindings[i], std::nullopt);
|
||||
descriptors.emplace_back(name, descriptor, std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +358,7 @@ static std::string stringifySpvOptimizerMessage(spv_message_level_t level, const
|
||||
}
|
||||
|
||||
void GLSLPostProcessor::spirvToMsl(const SpirvBlob* spirv, std::string* outMsl,
|
||||
filament::backend::ShaderStage stage, filament::backend::ShaderModel shaderModel,
|
||||
ShaderStage stage, ShaderModel shaderModel,
|
||||
bool useFramebufferFetch, const DescriptorSets& descriptorSets,
|
||||
const ShaderMinifier* minifier) {
|
||||
using namespace msl;
|
||||
@@ -674,7 +667,7 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
|
||||
// SpvRules should be enough.
|
||||
// I think this could cause the compilation to fail on gl_VertexID.
|
||||
using Type = std::underlying_type_t<EShMessages>;
|
||||
msg = EShMessages(Type(msg) | Type(EShMessages::EShMsgVulkanRules));
|
||||
msg = EShMessages(Type(msg) | Type(EShMsgVulkanRules));
|
||||
}
|
||||
|
||||
bool const ok = tShader.parse(&DefaultTBuiltInResource, internalConfig.langVersion, false, msg);
|
||||
@@ -684,7 +677,7 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
|
||||
}
|
||||
|
||||
// add texture lod bias
|
||||
if (config.shaderType == backend::ShaderStage::FRAGMENT &&
|
||||
if (config.shaderType == ShaderStage::FRAGMENT &&
|
||||
config.domain == MaterialDomain::SURFACE) {
|
||||
GLSLTools::textureLodBias(tShader);
|
||||
}
|
||||
@@ -760,8 +753,8 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GLSLPostProcessor::preprocessOptimization(glslang::TShader& tShader,
|
||||
GLSLPostProcessor::Config const& config, InternalConfig& internalConfig) const {
|
||||
bool GLSLPostProcessor::preprocessOptimization(TShader& tShader,
|
||||
Config const& config, InternalConfig& internalConfig) const {
|
||||
using TargetApi = MaterialBuilder::TargetApi;
|
||||
assert_invariant(bool(internalConfig.spirvOutput) == (config.targetApi != TargetApi::OPENGL));
|
||||
|
||||
@@ -832,7 +825,7 @@ bool GLSLPostProcessor::preprocessOptimization(glslang::TShader& tShader,
|
||||
}
|
||||
|
||||
bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
|
||||
GLSLPostProcessor::Config const& config, InternalConfig& internalConfig) const {
|
||||
Config const& config, InternalConfig& internalConfig) const {
|
||||
SpirvBlob spirv;
|
||||
|
||||
bool const optimizeForSize = mOptimization == MaterialBuilderBase::Optimization::SIZE;
|
||||
@@ -928,7 +921,7 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
|
||||
#else
|
||||
try {
|
||||
*internalConfig.glslOutput = glslCompiler.compile();
|
||||
} catch (spirv_cross::CompilerError e) {
|
||||
} catch (CompilerError e) {
|
||||
slog.e << "ERROR: " << e.what() << io::endl;
|
||||
return false;
|
||||
}
|
||||
@@ -948,8 +941,8 @@ bool GLSLPostProcessor::fullOptimization(const TShader& tShader,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
|
||||
auto optimizer = std::make_shared<spvtools::Optimizer>(SPV_ENV_UNIVERSAL_1_3);
|
||||
std::shared_ptr<Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
|
||||
auto optimizer = std::make_shared<Optimizer>(SPV_ENV_UNIVERSAL_1_3);
|
||||
optimizer->SetMessageConsumer([](spv_message_level_t level,
|
||||
const char* source, const spv_position_t& position, const char* message) {
|
||||
if (!filterSpvOptimizerMessage(level)) {
|
||||
@@ -961,7 +954,7 @@ std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createEmptyOptimizer() {
|
||||
return optimizer;
|
||||
}
|
||||
|
||||
std::shared_ptr<spvtools::Optimizer> GLSLPostProcessor::createOptimizer(
|
||||
std::shared_ptr<Optimizer> GLSLPostProcessor::createOptimizer(
|
||||
MaterialBuilder::Optimization optimization, Config const& config) {
|
||||
auto optimizer = createEmptyOptimizer();
|
||||
|
||||
@@ -1000,7 +993,7 @@ void GLSLPostProcessor::optimizeSpirv(OptimizerPtr optimizer, SpirvBlob& spirv)
|
||||
}
|
||||
|
||||
void GLSLPostProcessor::fixupClipDistance(
|
||||
SpirvBlob& spirv, GLSLPostProcessor::Config const& config) const {
|
||||
SpirvBlob& spirv, Config const& config) const {
|
||||
if (!config.usesClipDistance) {
|
||||
return;
|
||||
}
|
||||
@@ -1040,7 +1033,7 @@ void GLSLPostProcessor::fixupClipDistance(
|
||||
|
||||
|
||||
void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config const& config) {
|
||||
auto RegisterPass = [&](spvtools::Optimizer::PassToken&& pass,
|
||||
auto RegisterPass = [&](Optimizer::PassToken&& pass,
|
||||
MaterialBuilder::TargetApi apiFilter = MaterialBuilder::TargetApi::ALL) {
|
||||
if (!(config.targetApi & apiFilter)) {
|
||||
return;
|
||||
@@ -1085,7 +1078,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
|
||||
}
|
||||
|
||||
void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& config) {
|
||||
auto RegisterPass = [&](spvtools::Optimizer::PassToken&& pass,
|
||||
auto RegisterPass = [&](Optimizer::PassToken&& pass,
|
||||
MaterialBuilder::TargetApi apiFilter = MaterialBuilder::TargetApi::ALL) {
|
||||
if (!(config.targetApi & apiFilter)) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user