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
@@ -20,6 +20,7 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
#include <private/filament/Variant.h>
|
||||
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
@@ -39,8 +40,16 @@ backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) noexcept;
|
||||
|
||||
backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
Variant variant,
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) noexcept;
|
||||
|
||||
utils::CString getDescriptorName(
|
||||
filament::DescriptorSetBindingPoints set,
|
||||
DescriptorSetBindingPoints set,
|
||||
backend::descriptor_binding_t binding) noexcept;
|
||||
|
||||
} // namespace filament::descriptor_sets
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include <utils/CString.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <private/filament/DescriptorSets.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
@@ -128,6 +130,9 @@ public:
|
||||
|
||||
static utils::CString generateUniformName(const char* group, const char* sampler) noexcept;
|
||||
|
||||
static SamplerInfoList filterSamplerList(SamplerInfoList list,
|
||||
backend::DescriptorSetLayout const& descriptorSetLayout);
|
||||
|
||||
private:
|
||||
friend class Builder;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "private/filament/DescriptorSets.h"
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
#include <private/filament/Variant.h>
|
||||
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
@@ -26,34 +27,35 @@
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <initializer_list>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace filament::descriptor_sets {
|
||||
|
||||
using namespace backend;
|
||||
|
||||
static DescriptorSetLayout const postProcessDescriptorSetLayout{{
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> postProcessDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
}};
|
||||
};
|
||||
|
||||
static DescriptorSetLayout const depthVariantDescriptorSetLayout{{
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> depthVariantDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
}};
|
||||
};
|
||||
|
||||
// ssrVariantDescriptorSetLayout must match perViewDescriptorSetLayout's vertex stage. This is
|
||||
// because the SSR variant is always using the "standard" vertex shader (i.e. there is no
|
||||
// dedicated SSR vertex shader), which uses perViewDescriptorSetLayout.
|
||||
// This means that PerViewBindingPoints::SHADOWS must be in the layout even though it's not used
|
||||
// by the SSR variant.
|
||||
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{{
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
}};
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> ssrVariantDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::STRUCTURE },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
};
|
||||
|
||||
static DescriptorSetLayout perViewDescriptorSetLayout = {{
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perViewDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FRAME_UNIFORMS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SHADOWS },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::LIGHTS },
|
||||
@@ -66,16 +68,30 @@ static DescriptorSetLayout perViewDescriptorSetLayout = {{
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSAO },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::SSR },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::FRAGMENT, +PerViewBindingPoints::FOG },
|
||||
}};
|
||||
};
|
||||
|
||||
static DescriptorSetLayout perRenderableDescriptorSetLayout = {{
|
||||
static constexpr std::initializer_list<DescriptorSetLayoutBinding> perRenderableDescriptorSetLayoutList = {
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::OBJECT_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::BONES_UNIFORMS, DescriptorFlags::DYNAMIC_OFFSET },
|
||||
{ DescriptorType::UNIFORM_BUFFER, ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, +PerRenderableBindingPoints::MORPHING_UNIFORMS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_POSITIONS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::MORPH_TARGET_TANGENTS },
|
||||
{ DescriptorType::SAMPLER, ShaderStageFlags::VERTEX , +PerRenderableBindingPoints::BONES_INDICES_AND_WEIGHTS },
|
||||
}};
|
||||
};
|
||||
|
||||
// used for post-processing passes
|
||||
static DescriptorSetLayout const postProcessDescriptorSetLayout{ postProcessDescriptorSetLayoutList };
|
||||
|
||||
// used to generate shadow-maps
|
||||
static DescriptorSetLayout const depthVariantDescriptorSetLayout{ depthVariantDescriptorSetLayoutList };
|
||||
|
||||
static DescriptorSetLayout const ssrVariantDescriptorSetLayout{ ssrVariantDescriptorSetLayoutList };
|
||||
|
||||
// Used for generating the color pass (i.e. the main pass). This is in fact a template that gets
|
||||
// declined into 8 different layouts, based on variants.
|
||||
static DescriptorSetLayout perViewDescriptorSetLayout = { perViewDescriptorSetLayoutList };
|
||||
|
||||
static DescriptorSetLayout perRenderableDescriptorSetLayout = { perRenderableDescriptorSetLayoutList };
|
||||
|
||||
DescriptorSetLayout const& getPostProcessLayout() noexcept {
|
||||
return postProcessDescriptorSetLayout;
|
||||
@@ -93,8 +109,8 @@ DescriptorSetLayout const& getPerRenderableLayout() noexcept {
|
||||
return perRenderableDescriptorSetLayout;
|
||||
}
|
||||
|
||||
utils::CString getDescriptorName(DescriptorSetBindingPoints set,
|
||||
descriptor_binding_t binding) noexcept {
|
||||
utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
|
||||
descriptor_binding_t const binding) noexcept {
|
||||
using namespace std::literals;
|
||||
|
||||
static std::unordered_map<descriptor_binding_t, std::string_view> const set0{{
|
||||
@@ -140,11 +156,11 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints set,
|
||||
}
|
||||
|
||||
DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) noexcept {
|
||||
MaterialDomain const domain,
|
||||
UserVariantFilterMask const variantFilter,
|
||||
bool const isLit,
|
||||
ReflectionMode const reflectionMode,
|
||||
RefractionMode const refractionMode) noexcept {
|
||||
|
||||
bool const ssr = reflectionMode == ReflectionMode::SCREEN_SPACE ||
|
||||
refractionMode == RefractionMode::SCREEN_SPACE;
|
||||
@@ -187,11 +203,65 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
|
||||
return layout;
|
||||
}
|
||||
case MaterialDomain::POST_PROCESS:
|
||||
return descriptor_sets::getPostProcessLayout();
|
||||
return postProcessDescriptorSetLayout;
|
||||
case MaterialDomain::COMPUTE:
|
||||
// TODO: what's the layout for compute?
|
||||
return descriptor_sets::getPostProcessLayout();
|
||||
return postProcessDescriptorSetLayout;
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
Variant const variant,
|
||||
MaterialDomain domain,
|
||||
UserVariantFilterMask const variantFilter,
|
||||
bool const isLit,
|
||||
ReflectionMode const reflectionMode,
|
||||
RefractionMode const refractionMode) noexcept {
|
||||
if (Variant::isValidDepthVariant(variant)) {
|
||||
return depthVariantDescriptorSetLayout;
|
||||
}
|
||||
if (Variant::isSSRVariant(variant)) {
|
||||
return ssrVariantDescriptorSetLayout;
|
||||
}
|
||||
// We need to filter out all the descriptors not included in the "resolved" layout below
|
||||
return getPerViewDescriptorSetLayout(domain, variantFilter,
|
||||
isLit, reflectionMode, refractionMode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ITERATOR, class PREDICATE>
|
||||
constexpr static ITERATOR find_if(ITERATOR first, ITERATOR last, PREDICATE pred) {
|
||||
for (; first != last; ++first)
|
||||
if (pred(*first)) break;
|
||||
return first;
|
||||
}
|
||||
|
||||
constexpr static bool checkConsistency() noexcept {
|
||||
// check that all descriptors that apply to the vertex stage in perViewDescriptorSetLayout
|
||||
// are present in ssrVariantDescriptorSetLayout; meaning that the latter is compatible
|
||||
// with the former.
|
||||
for (auto const& r: perViewDescriptorSetLayoutList) {
|
||||
if (hasShaderType(r.stageFlags, ShaderStage::VERTEX)) {
|
||||
auto const pos = find_if(
|
||||
ssrVariantDescriptorSetLayoutList.begin(),
|
||||
ssrVariantDescriptorSetLayoutList.end(),
|
||||
[r](auto const& l) {
|
||||
return l.count == r.count &&
|
||||
l.type == r.type &&
|
||||
l.binding == r.binding &&
|
||||
l.flags == r.flags &&
|
||||
l.stageFlags == r.stageFlags;
|
||||
});
|
||||
if (pos == ssrVariantDescriptorSetLayoutList.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert(checkConsistency(), "ssrVariantDescriptorSetLayout is not compatible with "
|
||||
"perViewDescriptorSetLayout");
|
||||
|
||||
} // namespace filament::descriptor_sets
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "private/filament/SamplerInterfaceBlock.h"
|
||||
|
||||
#include <private/filament/DescriptorSets.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
@@ -102,7 +103,7 @@ const SamplerInterfaceBlock::SamplerInfo* SamplerInterfaceBlock::getSamplerInfo(
|
||||
return &mSamplersInfoList[pos->second];
|
||||
}
|
||||
|
||||
utils::CString SamplerInterfaceBlock::generateUniformName(const char* group, const char* sampler) noexcept {
|
||||
CString SamplerInterfaceBlock::generateUniformName(const char* group, const char* sampler) noexcept {
|
||||
char uniformName[256];
|
||||
|
||||
// sampler interface block name
|
||||
@@ -117,9 +118,27 @@ utils::CString SamplerInterfaceBlock::generateUniformName(const char* group, con
|
||||
std::min(sizeof(uniformName) / 2 - 2, strlen(sampler)),
|
||||
prefix + 1);
|
||||
*last++ = 0; // null terminator
|
||||
assert(last <= std::end(uniformName));
|
||||
assert_invariant(last <= std::end(uniformName));
|
||||
|
||||
return CString{ uniformName, size_t(last - uniformName) - 1u };
|
||||
}
|
||||
|
||||
SamplerInterfaceBlock::SamplerInfoList SamplerInterfaceBlock::filterSamplerList(
|
||||
SamplerInfoList list, backend::DescriptorSetLayout const& descriptorSetLayout) {
|
||||
// remove all the samplers that are not included in the descriptor-set layout
|
||||
list.erase(
|
||||
std::remove_if(list.begin(), list.end(),
|
||||
[&](auto const& entry) {
|
||||
auto pos = std::find_if(
|
||||
descriptorSetLayout.bindings.begin(),
|
||||
descriptorSetLayout.bindings.end(),
|
||||
[&entry](const auto& item) {
|
||||
return item.binding == entry.binding;
|
||||
});
|
||||
return pos == descriptorSetLayout.bindings.end();
|
||||
}), list.end());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
#include "MaterialVariants.h"
|
||||
|
||||
#include "shaders/ShaderGenerator.h"
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
#include <private/filament/Variant.h>
|
||||
|
||||
@@ -25,16 +23,8 @@
|
||||
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filamat {
|
||||
|
||||
std::vector<Variant> determineSurfaceVariants(
|
||||
@@ -62,58 +52,6 @@ std::vector<Variant> determineSurfaceVariants(
|
||||
if (fragmentVariant == variant) {
|
||||
variants.emplace_back(variant, filament::backend::ShaderStage::FRAGMENT);
|
||||
}
|
||||
|
||||
// Here we make sure that the combination of vertex and fragment variants have compatible
|
||||
// PER_VIEW descriptor-set layouts. This could actually be a static/compile-time check
|
||||
// because it is entirely decided in DescriptorSets.cpp. Unfortunately it's not possible
|
||||
// to write this entirely as a constexpr.
|
||||
|
||||
if (UTILS_UNLIKELY(vertexVariant != fragmentVariant)) {
|
||||
// fragment and vertex variants are different, we need to check the layouts are
|
||||
// compatible.
|
||||
using filament::ReflectionMode;
|
||||
using filament::RefractionMode;
|
||||
using filament::backend::ShaderStage;
|
||||
|
||||
// And we need to do that for all configurations of the "PER_VIEW" descriptor set
|
||||
// layouts (there are eight).
|
||||
// See ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant.
|
||||
for (auto reflection: {
|
||||
ReflectionMode::SCREEN_SPACE,
|
||||
ReflectionMode::DEFAULT }) {
|
||||
for (auto refraction: {
|
||||
RefractionMode::SCREEN_SPACE,
|
||||
RefractionMode::CUBEMAP,
|
||||
RefractionMode::NONE }) {
|
||||
auto const vdsl = ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant(
|
||||
vertexVariant, userVariantFilter, isLit || shadowMultiplier,
|
||||
reflection, refraction);
|
||||
auto const fdsl = ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant(
|
||||
fragmentVariant, userVariantFilter, isLit || shadowMultiplier,
|
||||
reflection, refraction);
|
||||
// Check that all bindings present in the vertex shader DescriptorSetLayout
|
||||
// are also present in the fragment shader DescriptorSetLayout.
|
||||
for (auto const& r: vdsl.bindings) {
|
||||
if (!hasShaderType(r.stageFlags, ShaderStage::VERTEX)) {
|
||||
// ignore descriptors that are of the fragment stage only
|
||||
continue;
|
||||
}
|
||||
auto const pos = std::find_if(fdsl.bindings.begin(), fdsl.bindings.end(),
|
||||
[r](auto const& l) {
|
||||
return l.count == r.count && l.type == r.type &&
|
||||
l.binding == r.binding && l.flags == r.flags &&
|
||||
l.stageFlags == r.stageFlags;
|
||||
});
|
||||
|
||||
// A mismatch is fatal. The material is ill-formed. This typically
|
||||
// mean a bug / inconsistency in DescriptorsSets.cpp
|
||||
FILAMENT_CHECK_POSTCONDITION(pos != fdsl.bindings.end())
|
||||
<< "Variant " << +k << " has mismatched descriptorset layouts";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
@@ -133,7 +71,7 @@ std::vector<Variant> determinePostProcessVariants() {
|
||||
std::vector<Variant> determineComputeVariants() {
|
||||
// TODO: should we have variants for compute shaders?
|
||||
std::vector<Variant> variants;
|
||||
filament::Variant variant(0);
|
||||
filament::Variant const variant(0);
|
||||
variants.emplace_back(variant, filament::backend::ShaderStage::COMPUTE);
|
||||
return variants;
|
||||
}
|
||||
|
||||
@@ -604,27 +604,13 @@ std::string ShaderGenerator::createSurfaceFragmentProgram(ShaderModel shaderMode
|
||||
|
||||
if (featureLevel >= FeatureLevel::FEATURE_LEVEL_1) {
|
||||
assert_invariant(mMaterialDomain == MaterialDomain::SURFACE);
|
||||
|
||||
auto const perViewDescriptorSetLayout = getPerViewDescriptorSetLayoutWithVariant(
|
||||
variant, variantFilter,
|
||||
material.isLit || material.hasShadowMultiplier,
|
||||
material.reflectionMode, material.refractionMode);
|
||||
|
||||
// this is the list of samplers we need to filter
|
||||
auto list = SibGenerator::getPerViewSib(variant).getSamplerInfoList();
|
||||
|
||||
// remove all the samplers that are not included in the descriptor-set layout
|
||||
list.erase(
|
||||
std::remove_if(list.begin(), list.end(),
|
||||
[&perViewDescriptorSetLayout](auto const& entry) {
|
||||
auto pos = std::find_if(
|
||||
perViewDescriptorSetLayout.bindings.begin(),
|
||||
perViewDescriptorSetLayout.bindings.end(),
|
||||
[&entry](const auto& item) {
|
||||
return item.binding == entry.binding;
|
||||
});
|
||||
return pos == perViewDescriptorSetLayout.bindings.end();
|
||||
}), list.end());
|
||||
auto const list = SamplerInterfaceBlock::filterSamplerList(
|
||||
SibGenerator::getPerViewSib(variant).getSamplerInfoList(),
|
||||
descriptor_sets::getPerViewDescriptorSetLayoutWithVariant(
|
||||
variant, mMaterialDomain, variantFilter,
|
||||
material.isLit || material.hasShadowMultiplier,
|
||||
material.reflectionMode, material.refractionMode));
|
||||
|
||||
cg.generateCommonSamplers(fs, DescriptorSetBindingPoints::PER_VIEW, list);
|
||||
}
|
||||
@@ -841,22 +827,4 @@ bool ShaderGenerator::hasStereo(
|
||||
&& featureLevel > MaterialBuilder::FeatureLevel::FEATURE_LEVEL_0;
|
||||
}
|
||||
|
||||
backend::DescriptorSetLayout ShaderGenerator::getPerViewDescriptorSetLayoutWithVariant(
|
||||
filament::Variant variant,
|
||||
UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
ReflectionMode reflectionMode,
|
||||
RefractionMode refractionMode) {
|
||||
if (filament::Variant::isValidDepthVariant(variant)) {
|
||||
return descriptor_sets::getDepthVariantLayout();
|
||||
}
|
||||
if (filament::Variant::isSSRVariant(variant)) {
|
||||
return descriptor_sets::getSsrVariantLayout();
|
||||
}
|
||||
// We need to filter out all the descriptors not included in the "resolved" layout below
|
||||
return descriptor_sets::getPerViewDescriptorSetLayout(
|
||||
MaterialDomain::SURFACE, variantFilter,
|
||||
isLit, reflectionMode, refractionMode);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -88,13 +88,6 @@ public:
|
||||
MaterialBuilder::FeatureLevel featureLevel,
|
||||
MaterialInfo const& material) noexcept;
|
||||
|
||||
static filament::backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
|
||||
filament::Variant variant,
|
||||
filament::UserVariantFilterMask variantFilter,
|
||||
bool isLit,
|
||||
filament::ReflectionMode reflectionMode,
|
||||
filament::RefractionMode refractionMode);
|
||||
|
||||
private:
|
||||
static void generateVertexDomainDefines(utils::io::sstream& out,
|
||||
filament::VertexDomain domain) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user