Compare commits

...

2 Commits

Author SHA1 Message Date
Powei Feng
e4fa86fb01 renderdiff: bump golden again
Transimssion.webgpu.TransmissionRoughnessTest seems to have small,
non-flaky differences.

RDIFF_ACCEPT_NEW_GOLDENS
2026-02-26 09:48:30 -08:00
Mathias Agopian
7da2a08df6 replace Variant::VSM with MNT and S2D (#9750)
The VSM variant bit was overloaded, it meant two different things
depending on the DEP bit (depth).

For standard variants (DEP = 0), it decides the type of the shadow
sampler used (PCF or 2D).

For depth variants (DEP = 1), it decides what is written during the
shadow pass (nothing, i.e. depth only, or EVSM depth moments).

We now clearly separate the two bits throughout the code.

This change should be purely source-cosmetic, there shouldn't be any
behavior changes.

Co-authored-by: Powei Feng <powei@google.com>
2026-02-25 16:16:07 -08:00
15 changed files with 103 additions and 95 deletions

View File

@@ -271,8 +271,8 @@ std::unique_ptr<MaterialDefinition> MaterialDefinition::create(FEngine& engine,
void MaterialDefinition::terminate(FEngine& engine) { void MaterialDefinition::terminate(FEngine& engine) {
DriverApi& driver = engine.getDriverApi(); DriverApi& driver = engine.getDriverApi();
perViewDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver); perViewDescriptorSetLayoutPcf.terminate(engine.getDescriptorSetLayoutFactory(), driver);
perViewDescriptorSetLayoutVsm.terminate(engine.getDescriptorSetLayoutFactory(), driver); perViewDescriptorSetLayoutS2d.terminate(engine.getDescriptorSetLayoutFactory(), driver);
descriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver); descriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver);
} }
@@ -607,23 +607,23 @@ void MaterialDefinition::processDescriptorSets(FEngine& engine) {
refractionMode == RefractionMode::SCREEN_SPACE; refractionMode == RefractionMode::SCREEN_SPACE;
bool const hasFog = !(variantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG)); bool const hasFog = !(variantFilterMask & UserVariantFilterMask(UserVariantFilterBit::FOG));
this->perViewDescriptorSetLayoutDescription = descriptor_sets::getPerViewDescriptorSetLayout( this->perViewDescriptorSetLayoutPcfDescription = descriptor_sets::getPerViewDescriptorSetLayout(
materialDomain, isLit, isSSR, hasFog, false); materialDomain, isLit, isSSR, hasFog, false);
this->perViewDescriptorSetLayoutVsmDescription = descriptor_sets::getPerViewDescriptorSetLayout( this->perViewDescriptorSetLayoutS2dDescription = descriptor_sets::getPerViewDescriptorSetLayout(
materialDomain, isLit, isSSR, hasFog, true); materialDomain, isLit, isSSR, hasFog, true);
// set the labels // set the labels
this->descriptorSetLayoutDescription.label = CString{ name }.append("_perMat"); this->descriptorSetLayoutDescription.label = CString{ name }.append("_perMat");
this->perViewDescriptorSetLayoutDescription.label = CString{ name }.append("_perView"); this->perViewDescriptorSetLayoutPcfDescription.label = CString{ name }.append("_perView");
this->perViewDescriptorSetLayoutVsmDescription.label = CString{ name }.append("_perViewVsm"); this->perViewDescriptorSetLayoutS2dDescription.label = CString{ name }.append("_perViewVsm");
// get the PER_RENDERABLE and PER_VIEW descriptor binding info // get the PER_RENDERABLE and PER_VIEW descriptor binding info
for (auto&& [bindingPoint, dsl] : { for (auto&& [bindingPoint, dsl] : {
std::pair{ DescriptorSetBindingPoints::PER_RENDERABLE, std::pair{ DescriptorSetBindingPoints::PER_RENDERABLE,
descriptor_sets::getPerRenderableLayout() }, descriptor_sets::getPerRenderableLayout() },
std::pair{ DescriptorSetBindingPoints::PER_VIEW, std::pair{ DescriptorSetBindingPoints::PER_VIEW,
this->perViewDescriptorSetLayoutDescription }}) { this->perViewDescriptorSetLayoutPcfDescription }}) {
Program::DescriptorBindingsInfo& descriptors = programDescriptorBindings[+bindingPoint]; Program::DescriptorBindingsInfo& descriptors = programDescriptorBindings[+bindingPoint];
descriptors.reserve(dsl.descriptors.size()); descriptors.reserve(dsl.descriptors.size());
for (auto const& entry: dsl.descriptors) { for (auto const& entry: dsl.descriptors) {
@@ -636,17 +636,17 @@ void MaterialDefinition::processDescriptorSets(FEngine& engine) {
descriptorSetLayoutFactory, driver, descriptorSetLayoutFactory, driver,
this->descriptorSetLayoutDescription }; this->descriptorSetLayoutDescription };
this->perViewDescriptorSetLayout = { this->perViewDescriptorSetLayoutPcf = {
descriptorSetLayoutFactory, driver, descriptorSetLayoutFactory, driver,
this->perViewDescriptorSetLayoutDescription }; this->perViewDescriptorSetLayoutPcfDescription };
this->perViewDescriptorSetLayoutVsm = { this->perViewDescriptorSetLayoutS2d = {
descriptorSetLayoutFactory, driver, descriptorSetLayoutFactory, driver,
this->perViewDescriptorSetLayoutVsmDescription }; this->perViewDescriptorSetLayoutS2dDescription };
} }
backend::DescriptorSetLayout const& MaterialDefinition::getPerViewDescriptorSetLayoutDescription( backend::DescriptorSetLayout const& MaterialDefinition::getPerViewDescriptorSetLayoutDescription(
Variant const variant, bool const useVsmDescriptorSetLayout) const noexcept { Variant const variant, bool const useS2dDescriptorSetLayout) const noexcept {
if (materialDomain == MaterialDomain::SURFACE) { if (materialDomain == MaterialDomain::SURFACE) {
if (Variant::isValidDepthVariant(variant)) { if (Variant::isValidDepthVariant(variant)) {
// Use the layout description used to create the per view depth variant layout. // Use the layout description used to create the per view depth variant layout.
@@ -657,10 +657,10 @@ backend::DescriptorSetLayout const& MaterialDefinition::getPerViewDescriptorSetL
return descriptor_sets::getSsrVariantLayout(); return descriptor_sets::getSsrVariantLayout();
} }
} }
if (useVsmDescriptorSetLayout) { if (useS2dDescriptorSetLayout) {
return perViewDescriptorSetLayoutVsmDescription; return perViewDescriptorSetLayoutS2dDescription;
} }
return perViewDescriptorSetLayoutDescription; return perViewDescriptorSetLayoutPcfDescription;
} }
Handle<HwProgram> MaterialDefinition::compileProgram( Handle<HwProgram> MaterialDefinition::compileProgram(
@@ -689,7 +689,7 @@ Handle<HwProgram> MaterialDefinition::compileProgram(
pb.descriptorLayout(+DescriptorSetBindingPoints::PER_VIEW, pb.descriptorLayout(+DescriptorSetBindingPoints::PER_VIEW,
getPerViewDescriptorSetLayoutDescription( getPerViewDescriptorSetLayoutDescription(
specialization.variant, specialization.variant,
Variant::isVSMVariant(specialization.variant))); Variant::isShadowSampler2DVariant(specialization.variant)));
pb.descriptorLayout(+DescriptorSetBindingPoints::PER_RENDERABLE, pb.descriptorLayout(+DescriptorSetBindingPoints::PER_RENDERABLE,
descriptor_sets::getPerRenderableLayout()); descriptor_sets::getPerRenderableLayout());
pb.descriptorLayout( pb.descriptorLayout(

View File

@@ -94,17 +94,17 @@ struct MaterialDefinition {
backend::ShaderModel const sm, bool isStereoSupported) const noexcept; backend::ShaderModel const sm, bool isStereoSupported) const noexcept;
backend::DescriptorSetLayout const& getPerViewDescriptorSetLayoutDescription( backend::DescriptorSetLayout const& getPerViewDescriptorSetLayoutDescription(
Variant const variant, bool useVsmDescriptorSetLayout) const noexcept; Variant const variant, bool useS2dDescriptorSetLayout) const noexcept;
// Keep track of the definitions of the descriptor set layouts, as these // Keep track of the definitions of the descriptor set layouts, as these
// may be used by some backends in parallel compilation of programs. // may be used by some backends in parallel compilation of programs.
backend::DescriptorSetLayout perViewDescriptorSetLayoutDescription; backend::DescriptorSetLayout perViewDescriptorSetLayoutPcfDescription;
backend::DescriptorSetLayout perViewDescriptorSetLayoutVsmDescription; backend::DescriptorSetLayout perViewDescriptorSetLayoutS2dDescription;
backend::DescriptorSetLayout descriptorSetLayoutDescription; backend::DescriptorSetLayout descriptorSetLayoutDescription;
// try to order by frequency of use // try to order by frequency of use
filament::DescriptorSetLayout perViewDescriptorSetLayout; filament::DescriptorSetLayout perViewDescriptorSetLayoutPcf;
filament::DescriptorSetLayout perViewDescriptorSetLayoutVsm; filament::DescriptorSetLayout perViewDescriptorSetLayoutS2d;
filament::DescriptorSetLayout descriptorSetLayout; filament::DescriptorSetLayout descriptorSetLayout;
backend::Program::DescriptorSetInfo programDescriptorBindings; backend::Program::DescriptorSetInfo programDescriptorBindings;

View File

@@ -802,7 +802,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::ssr(FrameGraph& fg,
// use our special SSR variant, it can only be applied to object that have // use our special SSR variant, it can only be applied to object that have
// the SCREEN_SPACE ReflectionMode. // the SCREEN_SPACE ReflectionMode.
passBuilder.variant(Variant{ Variant::SPECIAL_SSR }); passBuilder.variant(Variant{ Variant::SPECIAL_SSR_VARIANT });
// generate all our drawing commands, except blended objects. // generate all our drawing commands, except blended objects.
passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::SCREEN_SPACE_REFLECTIONS); passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::SCREEN_SPACE_REFLECTIONS);

View File

@@ -568,7 +568,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
if constexpr (isDepthPass) { if constexpr (isDepthPass) {
cmd.info.materialVariant = variant; cmd.info.materialVariant = variant;
cmd.info.rasterState = {}; cmd.info.rasterState = {};
cmd.info.rasterState.colorWrite = Variant::isPickingVariant(variant) || Variant::isVSMVariant(variant); cmd.info.rasterState.colorWrite = Variant::isPickingVariant(variant) || Variant::isDepthMomentsVariant(variant);
cmd.info.rasterState.depthWrite = true; cmd.info.rasterState.depthWrite = true;
cmd.info.rasterState.depthFunc = RasterState::DepthFunc::GE; cmd.info.rasterState.depthFunc = RasterState::DepthFunc::GE;
cmd.info.rasterState.alphaToCoverage = false; cmd.info.rasterState.alphaToCoverage = false;
@@ -616,7 +616,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
bool const hasSkinningOrMorphing = hasSkinning || hasMorphing; bool const hasSkinningOrMorphing = hasSkinning || hasMorphing;
// if we are already an SSR variant, the SRE bit is already set // if we are already an SSR variant, the SRE bit is already set
static_assert(Variant::SPECIAL_SSR & Variant::SRE); static_assert(Variant::SPECIAL_SSR_VARIANT & Variant::SRE);
Variant renderableVariant{ variant }; Variant renderableVariant{ variant };
// we can't have SSR and shadowing together by construction // we can't have SSR and shadowing together by construction

View File

@@ -257,9 +257,9 @@ filament::DescriptorSetLayout const& FMaterial::getPerViewDescriptorSetLayout(
} }
// mDefinition.perViewDescriptorSetLayout{Vsm} is already resolved for MaterialDomain // mDefinition.perViewDescriptorSetLayout{Vsm} is already resolved for MaterialDomain
if (useVsmDescriptorSetLayout) { if (useVsmDescriptorSetLayout) {
return mDefinition.perViewDescriptorSetLayoutVsm; return mDefinition.perViewDescriptorSetLayoutS2d;
} }
return mDefinition.perViewDescriptorSetLayout; return mDefinition.perViewDescriptorSetLayoutPcf;
} }
void FMaterial::compile(CompilerPriorityQueue const priority, void FMaterial::compile(CompilerPriorityQueue const priority,

View File

@@ -139,7 +139,7 @@ public:
// This is mostly intended to be used for post-process materials; but it's also useful for // This is mostly intended to be used for post-process materials; but it's also useful for
// Surface material that behave like post-process material (i.e. that don't really have variants or for // Surface material that behave like post-process material (i.e. that don't really have variants or for
// which VSM is nonsensical, like for unlit materials) // which VSM is nonsensical, like for unlit materials)
return mDefinition.perViewDescriptorSetLayout; return mDefinition.perViewDescriptorSetLayoutPcf;
} }
DescriptorSetLayout const& getPerViewDescriptorSetLayout( DescriptorSetLayout const& getPerViewDescriptorSetLayout(
@@ -378,11 +378,11 @@ private:
Variant variant = {}) const noexcept; Variant variant = {}) const noexcept;
bool isSharedVariant(Variant const variant) const { bool isSharedVariant(Variant const variant) const {
// HACK: The default material "should" have VSM | DEP, but then we'd have to compile it as a // HACK: The default material "should" have MNT | DEP, but then we'd have to compile it as a
// lit material, which would increase binary size. Perhaps we could specially compile it // lit material, which would increase binary size. Perhaps we could specially compile it
// with this variant, but with the shader program cache in active development, the days of // with this variant, but with the shader program cache in active development, the days of
// the default material are numbered anyway. // the default material are numbered anyway.
constexpr Variant::type_t vsmAndDep = Variant::VSM | Variant::DEP; constexpr Variant::type_t vsmAndDep = Variant::MNT | Variant::DEP;
return mDefinition.materialDomain == MaterialDomain::SURFACE && !mIsDefaultMaterial && return mDefinition.materialDomain == MaterialDomain::SURFACE && !mIsDefaultMaterial &&
!mDefinition.hasCustomDepthShader && Variant::isValidDepthVariant(variant) && !mDefinition.hasCustomDepthShader && Variant::isValidDepthVariant(variant) &&
(variant.key & vsmAndDep) != vsmAndDep; (variant.key & vsmAndDep) != vsmAndDep;

View File

@@ -969,10 +969,7 @@ void FRenderer::renderJob(DriverApi& driver, RootArenaScope& rootArenaScope, FVi
variant.setDirectionalLighting(view.hasDirectionalLighting()); variant.setDirectionalLighting(view.hasDirectionalLighting());
variant.setDynamicLighting(view.hasDynamicLighting()); variant.setDynamicLighting(view.hasDynamicLighting());
variant.setFog(view.hasFog()); variant.setFog(view.hasFog());
// The VSM bit has a different meaning for STANDARD_VARIANT (as opposed to DEPTH_VARIANT), variant.setShadowSampler2D(view.hasShadowing() && view.getShadowType() != ShadowType::PCF);
// In the STANDARD_VARIANT case, we are *using* the shadow-map, and the VSM only decides which
// type of sampler is used (samplerShadow or sampler2D).
variant.setVsm(view.hasShadowing() && view.getShadowType() != ShadowType::PCF);
variant.setStereo(view.hasStereo()); variant.setStereo(view.hasStereo());
/* /*
@@ -981,10 +978,7 @@ void FRenderer::renderJob(DriverApi& driver, RootArenaScope& rootArenaScope, FVi
if (view.needsShadowMap()) { if (view.needsShadowMap()) {
Variant shadowVariant(Variant::DEPTH_VARIANT); Variant shadowVariant(Variant::DEPTH_VARIANT);
// The VSM bit has a different meaning for DEPTH_VARIANT (as opposed to STANDARD_VARIANT), shadowVariant.setDepthMoments(view.getShadowType() == ShadowType::VSM);
// In the DEPTH_VARIANT case, we are *generating* the shadow-map, and some computations
// are handled differently. In addition, the color buffer is used.
shadowVariant.setVsm(view.getShadowType() == ShadowType::VSM);
auto shadows = view.renderShadowMaps(engine, fg, cameraInfo, mShaderUserTime, auto shadows = view.renderShadowMaps(engine, fg, cameraInfo, mShaderUserTime,
RenderPassBuilder{ commandArena } RenderPassBuilder{ commandArena }

View File

@@ -36,7 +36,7 @@ backend::DescriptorSetLayout const& getPerRenderableLayout() noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayout( backend::DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain domain, MaterialDomain domain,
bool isLit, bool isSSR, bool hasFog, bool isLit, bool isSSR, bool hasFog,
bool isVSM) noexcept; bool isShadowSampler2D) noexcept;
backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant( backend::DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
Variant variant, Variant variant,

View File

@@ -48,20 +48,21 @@ struct Variant {
// SRE: Shadow Receiver // SRE: Shadow Receiver
// SKN: Skinning // SKN: Skinning
// DEP: Depth only // DEP: Depth only
// FOG: Fog // FOG: Fog (standard)
// PCK: Picking (depth variant only) // PCK: Picking (depth)
// VSM: Variance shadow maps (depth) / sampler type (standard) // MNT: Output depth moments (depth)
// S2D: Sampler type for shadows (0: samplerShadowArray, 1: sampler2DArray) (standard)
// STE: Instanced stereo rendering // STE: Instanced stereo rendering
// //
// X: either 1 or 0 // X: either 1 or 0
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// Variant | STE | VSM | FOG | DEP | SKN | SRE | DYN | DIR | 256 // Variant | STE | S2D | FOG | DEP | SKN | SRE | DYN | DIR | 256
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// PCK // MNT PCK
// //
// Standard variants: // Standard variants:
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// | STE | VSM | FOG | 0 | SKN | SRE | DYN | DIR | 128 - 44 = 84 // | STE | S2D | FOG | 0 | SKN | SRE | DYN | DIR | 128 - 44 = 84
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// Vertex shader X 0 0 0 X X X X // Vertex shader X 0 0 0 X X X X
// Fragment shader 0 X X 0 0 X X X // Fragment shader 0 X X 0 0 X X X
@@ -72,7 +73,7 @@ struct Variant {
// //
// Depth variants: // Depth variants:
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// | STE | VSM | PCK | 1 | SKN | 0 | 0 | 0 | 16 - 4 = 12 // | STE | MNT | PCK | 1 | SKN | 0 | 0 | 0 | 16 - 4 = 12
// +-----+-----+-----+-----+-----+-----+-----+-----+ // +-----+-----+-----+-----+-----+-----+-----+-----+
// Vertex depth X X 0 1 X 0 0 0 // Vertex depth X X 0 1 X 0 0 0
// Fragment depth 0 0 X 1 0 0 0 0 // Fragment depth 0 0 X 1 0 0 0 0
@@ -96,13 +97,15 @@ struct Variant {
static constexpr type_t DEP = 0x10; // depth only variants static constexpr type_t DEP = 0x10; // depth only variants
static constexpr type_t FOG = 0x20; // fog (standard) static constexpr type_t FOG = 0x20; // fog (standard)
static constexpr type_t PCK = 0x20; // picking (depth) static constexpr type_t PCK = 0x20; // picking (depth)
static constexpr type_t VSM = 0x40; // variance shadow maps / sampler type static constexpr type_t S2D = 0x40; // sampler type
static constexpr type_t MNT = 0x40; // variance shadow maps
static constexpr type_t STE = 0x80; // instanced stereo static constexpr type_t STE = 0x80; // instanced stereo
static constexpr type_t NO_VARIANT = 0u; static constexpr type_t NO_VARIANT = 0u;
// special variants (variants that use the reserved space) // special variants (variants that use the reserved space)
static constexpr type_t SPECIAL_SSR = VSM | SRE; // screen-space reflections variant static constexpr type_t SPECIAL_SSR_VARIANT= S2D | SRE ;
static constexpr type_t SPECIAL_SSR_MASK = STE | S2D | DEP | SRE | DYN | DIR;
static constexpr type_t STANDARD_MASK = DEP; static constexpr type_t STANDARD_MASK = DEP;
static constexpr type_t STANDARD_VARIANT = 0u; static constexpr type_t STANDARD_VARIANT = 0u;
@@ -127,29 +130,30 @@ struct Variant {
void setSkinning(bool v) noexcept { set(v, SKN); } void setSkinning(bool v) noexcept { set(v, SKN); }
void setFog(bool v) noexcept { set(v, FOG); } void setFog(bool v) noexcept { set(v, FOG); }
void setPicking(bool v) noexcept { set(v, PCK); } void setPicking(bool v) noexcept { set(v, PCK); }
void setVsm(bool v) noexcept { set(v, VSM); } void setShadowSampler2D(bool v) noexcept { set(v, S2D); }
void setDepthMoments(bool v) noexcept { set(v, MNT); }
void setStereo(bool v) noexcept { set(v, STE); } void setStereo(bool v) noexcept { set(v, STE); }
static constexpr bool isValidDepthVariant(Variant variant) noexcept { static constexpr bool isValidDepthVariant(Variant variant) noexcept {
// Can't have VSM and PICKING together with DEPTH variants // Can't have VSM and PICKING together with DEPTH variants
constexpr type_t RESERVED_MASK = VSM | PCK | DEP | SRE | DYN | DIR; constexpr type_t RESERVED_MASK = MNT | PCK | DEP | SRE | DYN | DIR;
constexpr type_t RESERVED_VALUE = VSM | PCK | DEP; constexpr type_t RESERVED_VALUE = MNT | PCK | DEP;
return ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) && return ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) &&
((variant.key & RESERVED_MASK) != RESERVED_VALUE); ((variant.key & RESERVED_MASK) != RESERVED_VALUE);
} }
static constexpr bool isValidStandardVariant(Variant variant) noexcept { static constexpr bool isValidStandardVariant(Variant variant) noexcept {
// can't have shadow receiver if we don't have any lighting // can't have shadow receiver if we don't have any lighting
constexpr type_t RESERVED0_MASK = VSM | FOG | SRE | DYN | DIR; constexpr type_t RESERVED0_MASK = S2D | FOG | SRE | DYN | DIR;
constexpr type_t RESERVED0_VALUE = VSM | FOG | SRE; constexpr type_t RESERVED0_VALUE = S2D | FOG | SRE;
// can't have shadow receiver if we don't have any lighting // can't have shadow receiver if we don't have any lighting
constexpr type_t RESERVED1_MASK = VSM | SRE | DYN | DIR; constexpr type_t RESERVED1_MASK = S2D | SRE | DYN | DIR;
constexpr type_t RESERVED1_VALUE = SRE; constexpr type_t RESERVED1_VALUE = SRE;
// can't have VSM without shadow receiver // can't have VSM without shadow receiver
constexpr type_t RESERVED2_MASK = VSM | SRE; constexpr type_t RESERVED2_MASK = S2D | SRE;
constexpr type_t RESERVED2_VALUE = VSM; constexpr type_t RESERVED2_VALUE = S2D;
return ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) && return ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) &&
((variant.key & RESERVED0_MASK) != RESERVED0_VALUE) && ((variant.key & RESERVED0_MASK) != RESERVED0_VALUE) &&
@@ -174,11 +178,15 @@ struct Variant {
} }
static constexpr bool isSSRVariant(Variant variant) noexcept { static constexpr bool isSSRVariant(Variant variant) noexcept {
return (variant.key & (STE | VSM | DEP | SRE | DYN | DIR)) == (VSM | SRE); return (variant.key & SPECIAL_SSR_MASK) == SPECIAL_SSR_VARIANT;
} }
static constexpr bool isVSMVariant(Variant variant) noexcept { static constexpr bool isShadowSampler2DVariant(Variant variant) noexcept {
return !isSSRVariant(variant) && ((variant.key & VSM) == VSM); return !isSSRVariant(variant) && ((variant.key & (S2D | DEP)) == S2D);
}
static constexpr bool isDepthMomentsVariant(Variant variant) noexcept {
return !isSSRVariant(variant) && ((variant.key & (MNT | DEP)) == (MNT | DEP));
} }
static constexpr bool isShadowReceiverVariant(Variant variant) noexcept { static constexpr bool isShadowReceiverVariant(Variant variant) noexcept {
@@ -202,13 +210,13 @@ struct Variant {
// vertex shader. // vertex shader.
if ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) { if ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) {
if (isSSRVariant(variant)) { if (isSSRVariant(variant)) {
variant.key &= ~(VSM | SRE); variant.key &= ~SPECIAL_SSR_VARIANT;
} }
return variant & (STE | SKN | SRE | DYN | DIR); return variant & (STE | SKN | SRE | DYN | DIR);
} }
if ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) { if ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) {
// Only VSM, skinning, and stereo affect the vertex shader's DEPTH variant // Only MNT, skinning, and stereo affect the vertex shader's DEPTH variant
return variant & (STE | VSM | SKN | DEP); return variant & (STE | MNT | SKN | DEP);
} }
return {}; return {};
} }
@@ -217,11 +225,11 @@ struct Variant {
// filter out fragment variants that are not needed. For e.g. skinning doesn't // filter out fragment variants that are not needed. For e.g. skinning doesn't
// affect the fragment shader. // affect the fragment shader.
if ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) { if ((variant.key & STANDARD_MASK) == STANDARD_VARIANT) {
return variant & (VSM | FOG | SRE | DYN | DIR); return variant & (S2D | FOG | SRE | DYN | DIR);
} }
if ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) { if ((variant.key & DEPTH_MASK) == DEPTH_VARIANT) {
// Only VSM & PICKING affects the fragment shader's DEPTH variant // Only VSM & PICKING affects the fragment shader's DEPTH variant
return variant & (VSM | PCK | DEP); return variant & (MNT | PCK | DEP);
} }
return {}; return {};
} }
@@ -230,8 +238,8 @@ struct Variant {
// special case for depth variant // special case for depth variant
if (isValidDepthVariant(variant)) { if (isValidDepthVariant(variant)) {
if (!isLit) { if (!isLit) {
// if we're unlit, we never need the VSM variant // if we're unlit, we never need the MNT variant
return variant & ~VSM; return variant & ~MNT;
} }
return variant; return variant;
} }
@@ -242,9 +250,9 @@ struct Variant {
// when the shading mode is unlit, remove all the lighting variants // when the shading mode is unlit, remove all the lighting variants
return variant & UNLIT_MASK; return variant & UNLIT_MASK;
} }
// if shadow receiver is disabled, turn off VSM // if shadow receiver is disabled, we pick the shadow sampler
if (!(variant.key & SRE)) { if (!(variant.key & SRE)) {
return variant & ~VSM; return variant & ~S2D;
} }
return variant; return variant;
} }

View File

@@ -216,7 +216,7 @@ utils::CString getDescriptorName(DescriptorSetBindingPoints const set,
DescriptorSetLayout getPerViewDescriptorSetLayout( DescriptorSetLayout getPerViewDescriptorSetLayout(
MaterialDomain const domain, MaterialDomain const domain,
bool const isLit, bool const isSSR, bool const hasFog, bool const isLit, bool const isSSR, bool const hasFog,
bool const isVSM) noexcept { bool const isShadowSampler2D) noexcept {
switch (domain) { switch (domain) {
case MaterialDomain::SURFACE: { case MaterialDomain::SURFACE: {
@@ -255,7 +255,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayout(
} }
// change the SHADOW_MAP descriptor type for VSM // change the SHADOW_MAP descriptor type for VSM
if (isVSM) { if (isShadowSampler2D) {
auto const pos = std::find_if(layout.descriptors.begin(), layout.descriptors.end(), auto const pos = std::find_if(layout.descriptors.begin(), layout.descriptors.end(),
[](auto const& v) { [](auto const& v) {
return v.binding == PerViewBindingPoints::SHADOW_MAP; return v.binding == PerViewBindingPoints::SHADOW_MAP;
@@ -285,8 +285,7 @@ DescriptorSetLayout getPerViewDescriptorSetLayoutWithVariant(
return ssrVariantDescriptorSetLayout; return ssrVariantDescriptorSetLayout;
} }
// We need to filter out all the descriptors not included in the "resolved" layout below // We need to filter out all the descriptors not included in the "resolved" layout below
return getPerViewDescriptorSetLayout(domain, isLit, isSSR, hasFog, return getPerViewDescriptorSetLayout(domain, isLit, isSSR, hasFog, Variant::isShadowSampler2DVariant(variant));
Variant::isVSMVariant(variant));
} }
DescriptorType getDescriptorType(SamplerType const type, SamplerFormat const format) { DescriptorType getDescriptorType(SamplerType const type, SamplerFormat const format) {

View File

@@ -32,41 +32,46 @@ namespace filament {
Variant Variant::filterUserVariant( Variant Variant::filterUserVariant(
Variant variant, UserVariantFilterMask filterMask) noexcept { Variant variant, UserVariantFilterMask filterMask) noexcept {
// these are easy to filter by just removing the corresponding bit // these are easy to filter by just removing the corresponding bit
if (filterMask & (uint32_t)UserVariantFilterBit::DIRECTIONAL_LIGHTING) { if (filterMask & uint32_t(UserVariantFilterBit::DIRECTIONAL_LIGHTING)) {
variant.key &= ~DIR; variant.key &= ~DIR;
} }
if (filterMask & (uint32_t)UserVariantFilterBit::DYNAMIC_LIGHTING) {
if (filterMask & uint32_t(UserVariantFilterBit::DYNAMIC_LIGHTING)) {
variant.key &= ~DYN; variant.key &= ~DYN;
} }
if (filterMask & (uint32_t)UserVariantFilterBit::SKINNING) {
if (filterMask & uint32_t(UserVariantFilterBit::SKINNING)) {
variant.key &= ~SKN; variant.key &= ~SKN;
} }
if (filterMask & (uint32_t)UserVariantFilterBit::STE) {
if (filterMask & uint32_t(UserVariantFilterBit::STE)) {
variant.key &= ~(filterMask & STE); variant.key &= ~(filterMask & STE);
} }
if (!isValidDepthVariant(variant)) {
// we can't remove FOG from depth variants, this would, in fact, remove picking if (isValidDepthVariant(variant)) {
if (filterMask & (uint32_t)UserVariantFilterBit::FOG) { // depth variants can have their MNT bit filtered
variant.key &= ~FOG; if (filterMask & uint32_t(UserVariantFilterBit::VSM)) {
variant.key &= ~MNT;
} }
} else { } else {
// depth variants can have their VSM bit filtered // we can't remove FOG from depth variants, this would, in fact, remove picking
if (filterMask & (uint32_t)UserVariantFilterBit::VSM) { if (filterMask & uint32_t(UserVariantFilterBit::FOG)) {
variant.key &= ~VSM; variant.key &= ~FOG;
} }
} }
if (!isSSRVariant(variant)) { if (!isSSRVariant(variant)) {
// SSR variant needs to be handled separately // SSR variant needs to be handled separately
if (filterMask & (uint32_t)UserVariantFilterBit::SHADOW_RECEIVER) { if (filterMask & uint32_t(UserVariantFilterBit::SHADOW_RECEIVER)) {
variant.key &= ~SRE; variant.key &= ~SRE;
} }
if (filterMask & (uint32_t)UserVariantFilterBit::VSM) { if (filterMask & uint32_t(UserVariantFilterBit::VSM)) {
variant.key &= ~VSM; variant.key &= ~S2D;
} }
} else { } else {
// see if we need to filter out the SSR variants // see if we need to filter out the SSR variants
if (filterMask & (uint32_t)UserVariantFilterBit::SSR) { if (filterMask & uint32_t(UserVariantFilterBit::SSR)) {
variant.key &= ~SPECIAL_SSR; variant.key &= ~SPECIAL_SSR_VARIANT;
} }
} }
return variant; return variant;

View File

@@ -60,7 +60,8 @@ void ShaderGenerator::generateSurfaceMaterialVariantDefines(io::sstream& out,
CodeGenerator::generateDefine(out, "VARIANT_HAS_SHADOWING", CodeGenerator::generateDefine(out, "VARIANT_HAS_SHADOWING",
litVariants && filament::Variant::isShadowReceiverVariant(variant)); litVariants && filament::Variant::isShadowReceiverVariant(variant));
CodeGenerator::generateDefine(out, "VARIANT_HAS_VSM", CodeGenerator::generateDefine(out, "VARIANT_HAS_VSM",
filament::Variant::isVSMVariant(variant)); filament::Variant::isShadowSampler2DVariant(variant) ||
filament::Variant::isDepthMomentsVariant(variant));
CodeGenerator::generateDefine(out, "VARIANT_HAS_STEREO", CodeGenerator::generateDefine(out, "VARIANT_HAS_STEREO",
hasStereo(variant, featureLevel)); hasStereo(variant, featureLevel));
CodeGenerator::generateDefine(out, "VARIANT_DEPTH", CodeGenerator::generateDefine(out, "VARIANT_DEPTH",

View File

@@ -49,7 +49,7 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce
// reason we name them "unused*" to ensure we're not using them by mistake (type/format don't // reason we name them "unused*" to ensure we're not using them by mistake (type/format don't
// matter). // matter).
static SamplerInterfaceBlock const sibPcf{ SamplerInterfaceBlock::Builder() static SamplerInterfaceBlock const sibShadowSamplerPcf{ SamplerInterfaceBlock::Builder()
.name("sampler0") .name("sampler0")
.stageFlags(backend::ShaderStageFlags::FRAGMENT) .stageFlags(backend::ShaderStageFlags::FRAGMENT)
.add( {{ "shadowMap", +PerViewBindingPoints::SHADOW_MAP, Type::SAMPLER_2D_ARRAY, Format::SHADOW, Precision::MEDIUM, FILTERABLE, !MULTISAMPLE, ALL_STAGES }, .add( {{ "shadowMap", +PerViewBindingPoints::SHADOW_MAP, Type::SAMPLER_2D_ARRAY, Format::SHADOW, Precision::MEDIUM, FILTERABLE, !MULTISAMPLE, ALL_STAGES },
@@ -62,7 +62,7 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce
) )
.build() }; .build() };
static SamplerInterfaceBlock const sibVsm{ SamplerInterfaceBlock::Builder() static SamplerInterfaceBlock const sibShadowSampler2D{ SamplerInterfaceBlock::Builder()
.name("sampler0") .name("sampler0")
.stageFlags(backend::ShaderStageFlags::FRAGMENT) .stageFlags(backend::ShaderStageFlags::FRAGMENT)
.add( {{ "shadowMap", +PerViewBindingPoints::SHADOW_MAP, Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::HIGH, FILTERABLE, !MULTISAMPLE, ALL_STAGES }, .add( {{ "shadowMap", +PerViewBindingPoints::SHADOW_MAP, Type::SAMPLER_2D_ARRAY, Format::FLOAT, Precision::HIGH, FILTERABLE, !MULTISAMPLE, ALL_STAGES },
@@ -85,10 +85,10 @@ SamplerInterfaceBlock const& SibGenerator::getPerViewSib(Variant variant) noexce
if (Variant::isSSRVariant(variant)) { if (Variant::isSSRVariant(variant)) {
return sibSsr; return sibSsr;
} else if (Variant::isVSMVariant(variant)) { } else if (Variant::isShadowSampler2DVariant(variant)) {
return sibVsm; return sibShadowSampler2D;
} else { } else {
return sibPcf; return sibShadowSamplerPcf;
} }
} }

View File

@@ -48,10 +48,11 @@ std::string formatVariantString(Variant variant, MaterialDomain domain) noexcept
if (variant.key & Variant::DEP) variantString += "DEP|"; if (variant.key & Variant::DEP) variantString += "DEP|";
if (variant.key & Variant::DEP) { if (variant.key & Variant::DEP) {
if (variant.key & Variant::PCK) variantString += "PCK|"; if (variant.key & Variant::PCK) variantString += "PCK|";
if (variant.key & Variant::MNT) variantString += "MNT|";
} else { } else {
if (variant.key & Variant::FOG) variantString += "FOG|"; if (variant.key & Variant::FOG) variantString += "FOG|";
if (variant.key & Variant::S2D) variantString += "S2D|";
} }
if (variant.key & Variant::VSM) variantString += "VSM|";
if (variant.key & Variant::STE) variantString += "STE|"; if (variant.key & Variant::STE) variantString += "STE|";
variantString = variantString.substr(0, variantString.length() - 1); variantString = variantString.substr(0, variantString.length() - 1);
} }

View File

@@ -76,7 +76,7 @@ into **branch** of `filament-assets`. This branch is paired with a PR or commit
As an example, imagine I am working on a PR, and I've uploaded my change, which is in a As an example, imagine I am working on a PR, and I've uploaded my change, which is in a
branch called `my-pr-branch`, to `filament`. This PR requires updating the golden. We would do branch called `my-pr-branch`, to `filament`. This PR requires updating the golden. We would do
it in the following fashion it in the following fashion on a macOS machine:
### Using a script to update the golden repo ### Using a script to update the golden repo