From 001dcefd8a9aae29e913bfea5bd770c60bbf9cd9 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 26 Jan 2022 16:26:02 -0800 Subject: [PATCH] simplify how we select a material Variant Instead of building the Variant based on flags in RenderPass, we just pass the Variant itself to RenderPass. The caller has more knowledge of what it wants to do. --- filament/src/PostProcessManager.cpp | 4 ++ filament/src/RenderPass.cpp | 37 ++++++++----------- filament/src/RenderPass.h | 22 ++++++----- filament/src/Renderer.cpp | 34 ++++++++--------- .../include/private/filament/Variant.h | 2 + 5 files changed, 49 insertions(+), 50 deletions(-) diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index e84b0d7956..fe0124f171 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -382,8 +382,12 @@ FrameGraphId PostProcessManager::structure(FrameGraph& fg, }, [=, renderPass = pass](FrameGraphResources const& resources, auto const& data, DriverApi& driver) mutable { + Variant structureVariant(Variant::DEPTH_VARIANT); + structureVariant.setPicking(config.picking); + auto out = resources.getRenderPassInfo(); renderPass.setRenderFlags(structureRenderFlags); + renderPass.setVariant(structureVariant); renderPass.appendCommands(RenderPass::CommandTypeFlags::SSAO); renderPass.sortCommands(); renderPass.execute(resources.getPassName(), out.target, out.params); diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index b30dd5dab6..f789c67810 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -94,6 +94,7 @@ void RenderPass::appendCommands(CommandTypeFlags const commandTypeFlags) noexcep FEngine& engine = mEngine; JobSystem& js = engine.getJobSystem(); const RenderFlags renderFlags = mFlags; + const Variant variant = mVariant; const FScene::VisibleMaskType visibilityMask = mVisibilityMask; CameraInfo const& camera = mCamera; @@ -113,11 +114,11 @@ void RenderPass::appendCommands(CommandTypeFlags const commandTypeFlags) noexcep // we extract camera position/forward outside of the loop, because these are not cheap. const float3 cameraPosition(camera.getPosition()); const float3 cameraForwardVector(camera.getForwardVector()); - auto work = [commandTypeFlags, curr, &soa, renderFlags, visibilityMask, cameraPosition, + auto work = [commandTypeFlags, curr, &soa, variant, renderFlags, visibilityMask, cameraPosition, cameraForwardVector] (uint32_t startIndex, uint32_t indexCount) { RenderPass::generateCommands(commandTypeFlags, curr, - soa, { startIndex, startIndex + indexCount }, renderFlags, visibilityMask, + soa, { startIndex, startIndex + indexCount }, variant, renderFlags, visibilityMask, cameraPosition, cameraForwardVector); }; @@ -211,8 +212,10 @@ void RenderPass::setupColorCommand(Command& cmdDraw, /* static */ UTILS_NOINLINE void RenderPass::generateCommands(uint32_t commandTypeFlags, Command* const commands, - FScene::RenderableSoa const& soa, Range range, RenderFlags renderFlags, - FScene::VisibleMaskType visibilityMask, float3 cameraPosition, float3 cameraForward) noexcept { + FScene::RenderableSoa const& soa, Range range, + Variant variant, RenderFlags renderFlags, + FScene::VisibleMaskType visibilityMask, + float3 cameraPosition, float3 cameraForward) noexcept { // generateCommands() writes both the draw and depth commands simultaneously such that // we go throw the list of renderables just once. @@ -239,11 +242,11 @@ void RenderPass::generateCommands(uint32_t commandTypeFlags, Command* const comm switch (commandTypeFlags & (CommandTypeFlags::COLOR | CommandTypeFlags::DEPTH)) { case CommandTypeFlags::COLOR: generateCommandsImpl(commandTypeFlags, curr, - soa, range, renderFlags, visibilityMask, cameraPosition, cameraForward); + soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward); break; case CommandTypeFlags::DEPTH: generateCommandsImpl(commandTypeFlags, curr, - soa, range, renderFlags, visibilityMask, cameraPosition, cameraForward); + soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward); break; default: // we should never end-up here @@ -257,7 +260,7 @@ UTILS_NOINLINE void RenderPass::generateCommandsImpl(uint32_t extraFlags, Command* UTILS_RESTRICT curr, FScene::RenderableSoa const& UTILS_RESTRICT soa, Range range, - RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, + Variant variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, float3 cameraPosition, float3 cameraForward) noexcept { // generateCommands() writes both the draw and depth commands simultaneously such that @@ -283,23 +286,13 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, const bool hasShadowing = renderFlags & HAS_SHADOWING; const bool viewInverseFrontFaces = renderFlags & HAS_INVERSE_FRONT_FACES; - Variant materialVariant; - materialVariant.setDirectionalLighting(renderFlags & HAS_DIRECTIONAL_LIGHT); - materialVariant.setDynamicLighting(renderFlags & HAS_DYNAMIC_LIGHTING); - materialVariant.setFog(renderFlags & HAS_FOG); - // DPCF and PCSS uses the same color pass shader as VSM (but not for depth) - materialVariant.setVsm(((renderFlags & HAS_VSM) || (renderFlags & HAS_DPCF_OR_PCSS)) && hasShadowing); - materialVariant.setShadowReceiver(false); // this is set per Renderable - Command cmdColor; Command cmdDepth; if constexpr (isDepthPass) { - cmdDepth.primitive.materialVariant = Variant{ Variant::DEPTH_VARIANT }; - cmdDepth.primitive.materialVariant.setPicking(renderFlags & HAS_PICKING); - cmdDepth.primitive.materialVariant.setVsm(renderFlags & HAS_VSM); + cmdDepth.primitive.materialVariant = variant; cmdDepth.primitive.rasterState = {}; - cmdDepth.primitive.rasterState.colorWrite = renderFlags & (HAS_VSM | HAS_PICKING); + cmdDepth.primitive.rasterState.colorWrite = variant.hasPicking() || variant.hasVsm(); cmdDepth.primitive.rasterState.depthWrite = true; cmdDepth.primitive.rasterState.depthFunc = RasterState::DepthFunc::GE; cmdDepth.primitive.rasterState.alphaToCoverage = false; @@ -355,8 +348,8 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, cmdColor.key = makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT); cmdColor.primitive.index = (uint16_t)i; - materialVariant.setShadowReceiver(soaVisibility[i].receiveShadows & hasShadowing); - materialVariant.setSkinning(soaVisibility[i].skinning || soaVisibility[i].morphing); + variant.setShadowReceiver(soaVisibility[i].receiveShadows & hasShadowing); + variant.setSkinning(soaVisibility[i].skinning || soaVisibility[i].morphing); if constexpr (isDepthPass) { cmdDepth.key = uint64_t(Pass::DEPTH); @@ -384,7 +377,7 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, FMorphTargetBuffer const* const morphTargetBuffer = primitive.getMorphTargetBuffer(); if constexpr (isColorPass) { cmdColor.primitive.primitiveHandle = primitive.getHwHandle(); - cmdColor.primitive.materialVariant = materialVariant; + cmdColor.primitive.materialVariant = variant; RenderPass::setupColorCommand(cmdColor, mi, inverseFrontFaces); cmdColor.primitive.morphWeightBuffer = morphing.handle; diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h index 53962ddcd3..7e7b0c2427 100644 --- a/filament/src/RenderPass.h +++ b/filament/src/RenderPass.h @@ -238,13 +238,7 @@ public: using RenderFlags = uint8_t; static constexpr RenderFlags HAS_SHADOWING = 0x01; - static constexpr RenderFlags HAS_DIRECTIONAL_LIGHT = 0x02; - static constexpr RenderFlags HAS_DYNAMIC_LIGHTING = 0x04; - static constexpr RenderFlags HAS_INVERSE_FRONT_FACES = 0x08; - static constexpr RenderFlags HAS_FOG = 0x10; - static constexpr RenderFlags HAS_VSM = 0x20; - static constexpr RenderFlags HAS_PICKING = 0x40; - static constexpr RenderFlags HAS_DPCF_OR_PCSS = 0x80; + static constexpr RenderFlags HAS_INVERSE_FRONT_FACES = 0x02; // Arena used for commands using Arena = utils::Arena< @@ -279,6 +273,9 @@ public: // flags controlling how commands are generated void setRenderFlags(RenderFlags flags) noexcept { mFlags = flags; } + // variant to use + void setVariant(Variant variant) noexcept { mVariant = variant; } + // Sets the visibility mask, which is AND-ed against each Renderable's VISIBLE_MASK to determine // if the renderable is visible for this pass. // Defaults to all 1's, which means all renderables in this render pass will be rendered. @@ -369,13 +366,15 @@ private: "Size of Commands jobs must be multiple of a cache-line size"); static inline void generateCommands(uint32_t commandTypeFlags, Command* commands, - FScene::RenderableSoa const& soa, utils::Range range, RenderFlags renderFlags, - FScene::VisibleMaskType visibilityMask, math::float3 cameraPosition, math::float3 cameraForward) noexcept; + FScene::RenderableSoa const& soa, utils::Range range, + Variant variant, RenderFlags renderFlags, + FScene::VisibleMaskType visibilityMask, + math::float3 cameraPosition, math::float3 cameraForward) noexcept; template static inline void generateCommandsImpl(uint32_t, Command* commands, FScene::RenderableSoa const& soa, utils::Range range, - RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, + Variant variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, math::float3 cameraPosition, math::float3 cameraForward) noexcept; static void setupColorCommand(Command& cmdDraw, @@ -415,6 +414,9 @@ private: // info about the scene features (e.g.: has shadows, lighting, etc...) RenderFlags mFlags{}; + // Variant to use + Variant mVariant{}; + // Additional visibility mask FScene::VisibleMaskType mVisibilityMask = std::numeric_limits::max(); diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp index 744a0a40ca..a02ad79eee 100644 --- a/filament/src/Renderer.cpp +++ b/filament/src/Renderer.cpp @@ -285,23 +285,16 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { RenderPass::Arena commandArena("Command Arena", { arenaBegin, arenaEnd }); RenderPass pass(engine, commandArena); - RenderPass::RenderFlags baseRenderFlags = 0; - if (view.hasShadowing()) baseRenderFlags |= RenderPass::HAS_SHADOWING; - if (view.hasDirectionalLight()) baseRenderFlags |= RenderPass::HAS_DIRECTIONAL_LIGHT; - if (view.hasDynamicLighting()) baseRenderFlags |= RenderPass::HAS_DYNAMIC_LIGHTING; - if (view.hasFog()) baseRenderFlags |= RenderPass::HAS_FOG; - if (view.isFrontFaceWindingInverted()) baseRenderFlags |= RenderPass::HAS_INVERSE_FRONT_FACES; - RenderPass::RenderFlags colorRenderFlags = baseRenderFlags; - switch (view.getShadowType()) { - case ShadowType::PCF: break; - case ShadowType::VSM: colorRenderFlags |= RenderPass::HAS_VSM; break; - case ShadowType::DPCF: colorRenderFlags |= RenderPass::HAS_DPCF_OR_PCSS; break; - case ShadowType::PCSS: colorRenderFlags |= RenderPass::HAS_DPCF_OR_PCSS; break; - } + RenderPass::RenderFlags renderFlags = 0; + if (view.hasShadowing()) renderFlags |= RenderPass::HAS_SHADOWING; + if (view.isFrontFaceWindingInverted()) renderFlags |= RenderPass::HAS_INVERSE_FRONT_FACES; - RenderPass::RenderFlags structureRenderFlags = baseRenderFlags; - if (view.hasPicking()) structureRenderFlags |= RenderPass::HAS_PICKING; + Variant variant; + variant.setDirectionalLighting(view.hasDirectionalLight()); + variant.setDynamicLighting(view.hasDynamicLighting()); + variant.setFog(view.hasFog()); + variant.setVsm(view.hasShadowing() && view.getShadowType() != ShadowType::PCF); /* * Frame graph @@ -314,8 +307,12 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { */ if (view.needsShadowMap()) { + Variant shadowVariant(Variant::DEPTH_VARIANT); + shadowVariant.setVsm(view.getShadowType() == ShadowType::VSM); + RenderPass shadowPass(pass); - shadowPass.setRenderFlags(colorRenderFlags); + shadowPass.setRenderFlags(renderFlags); + shadowPass.setVariant(shadowVariant); view.renderShadowMaps(fg, engine, driver, shadowPass); } @@ -436,7 +433,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // This is normally used by SSAO and contact-shadows // TODO: the scaling should depends on all passes that need the structure pass - ppm.structure(fg, pass, structureRenderFlags, svp.width, svp.height, { + ppm.structure(fg, pass, renderFlags, svp.width, svp.height, { .scale = aoOptions.resolution, .picking = view.hasPicking() }); @@ -503,7 +500,8 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) { // This one doesn't need to be a FrameGraph pass because it always happens by construction // (i.e. it won't be culled, unless everything is culled), so no need to complexify things. - pass.setRenderFlags(colorRenderFlags); + pass.setRenderFlags(renderFlags); + pass.setVariant(variant); pass.appendCommands(RenderPass::COLOR); pass.sortCommands(); diff --git a/libs/filabridge/include/private/filament/Variant.h b/libs/filabridge/include/private/filament/Variant.h index 3069fbab77..c8457b0d04 100644 --- a/libs/filabridge/include/private/filament/Variant.h +++ b/libs/filabridge/include/private/filament/Variant.h @@ -34,6 +34,8 @@ namespace filament { using type_t = uint8_t; Variant() noexcept = default; + Variant(Variant const& rhs) noexcept = default; + Variant& operator=(Variant const& rhs) noexcept = default; constexpr explicit Variant(type_t key) noexcept : key(key) { }