From f13bf11d0fced10a20d3a3186b53dc8bc5a85533 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Sun, 2 Oct 2022 23:35:11 -0700 Subject: [PATCH] simplify command generation No need to generate a sentinel command in the main loop when a command is canceled, this is now done automatically at a higher level. The main benefit is that we can reject renderables that are not visible a bit faster. --- filament/src/RenderPass.cpp | 50 +++++++++++++++++-------------------- filament/src/RenderPass.h | 2 +- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index 46722de569..ee6197ce7c 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -378,12 +378,14 @@ void RenderPass::generateCommands(uint32_t commandTypeFlags, Command* const comm // the list twice) // compute how much maximum storage we need - uint32_t offset = FScene::getPrimitiveCount(soa, range.first); // double the color pass for transparent objects that need to render twice const bool colorPass = bool(commandTypeFlags & CommandTypeFlags::COLOR); const bool depthPass = bool(commandTypeFlags & CommandTypeFlags::DEPTH); - offset *= uint32_t(colorPass * 2 + depthPass); - Command* const curr = commands + offset; + const size_t commandsPerPrimitive = uint32_t(colorPass * 2 + depthPass); + const size_t offsetBegin = FScene::getPrimitiveCount(soa, range.first) * commandsPerPrimitive; + const size_t offsetEnd = FScene::getPrimitiveCount(soa, range.last) * commandsPerPrimitive; + Command* curr = commands + offsetBegin; + Command* const last = commands + offsetEnd; /* * The switch {} below is to coerce the compiler into generating different versions of @@ -396,23 +398,31 @@ void RenderPass::generateCommands(uint32_t commandTypeFlags, Command* const comm switch (commandTypeFlags & (CommandTypeFlags::COLOR | CommandTypeFlags::DEPTH)) { case CommandTypeFlags::COLOR: - generateCommandsImpl(commandTypeFlags, curr, + curr = generateCommandsImpl(commandTypeFlags, curr, soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward); break; case CommandTypeFlags::DEPTH: - generateCommandsImpl(commandTypeFlags, curr, + curr = generateCommandsImpl(commandTypeFlags, curr, soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward); break; default: // we should never end-up here break; } + + assert_invariant(curr <= last); + + // commands may have been skipped, cancel all of them. + while (curr != last) { + curr->key = uint64_t(Pass::SENTINEL); + ++curr; + } } /* static */ template UTILS_NOINLINE -void RenderPass::generateCommandsImpl(uint32_t extraFlags, +RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags, Command* UTILS_RESTRICT curr, FScene::RenderableSoa const& UTILS_RESTRICT soa, Range range, Variant variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, @@ -458,17 +468,8 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, const float cameraPositionDotCameraForward = dot(cameraPosition, cameraForward); for (uint32_t i = range.first; i < range.last; ++i) { - // Check if this renderable passes the visibilityMask. If it doesn't, encode SENTINEL - // commands (no-op). + // Check if this renderable passes the visibilityMask. if (UTILS_UNLIKELY(!(soaVisibilityMask[i] & visibilityMask))) { - // We need to encode a SENTINEL for each command that would have been generated - // otherwise. Color passes get 2 commands per primitive; depth passes get 1. - const Slice& primitives = soaPrimitives[i]; - const size_t commandsToEncode = (isColorPass * 2 + isDepthPass) * primitives.size(); - for (size_t j = 0; j < commandsToEncode; j++) { - curr->key = uint64_t(Pass::SENTINEL); - ++curr; - } continue; } @@ -541,6 +542,11 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, */ for (size_t pi = 0, c = primitives.size(); pi < c; ++pi) { auto const& primitive = primitives[pi]; + // handle the case where this primitive is empty / no-op + if (primitive.getPrimitiveType() == PrimitiveType::NONE) { + continue; + } + auto const& morphTargets = morphing.targets[pi]; FMaterialInstance const* const mi = primitive.getMaterialInstance(); FMaterial const* const ma = mi->getMaterial(); @@ -597,9 +603,6 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, // draw this command AFTER THE NEXT ONE key |= makeField(1, BLEND_TWO_PASS_MASK, BLEND_TWO_PASS_SHIFT); - // handle the case where this primitive is empty / no-op - key |= select(primitive.getPrimitiveType() == PrimitiveType::NONE); - // correct for TransparencyMode::DEFAULT -- i.e. cancel the command key |= select(mode == TransparencyMode::DEFAULT); @@ -629,14 +632,9 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, // bucketizes the depth by its log2 and in 4 linear chunks in each bucket. cmdColor.key &= ~Z_BUCKET_MASK; cmdColor.key |= makeField(distanceBits >> 22u, Z_BUCKET_MASK, Z_BUCKET_SHIFT); - - curr->key = uint64_t(Pass::SENTINEL); - ++curr; } *curr = cmdColor; - // handle the case where this primitive is empty / no-op - curr->key |= select(primitive.getPrimitiveType() == PrimitiveType::NONE); ++curr; } @@ -666,13 +664,11 @@ void RenderPass::generateCommandsImpl(uint32_t extraFlags, & !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage)) | writeDepthForShadowCasters; *curr = cmdDepth; - - // handle the case where this primitive is empty / no-op - curr->key |= select(primitive.getPrimitiveType() == PrimitiveType::NONE); ++curr; } } } + return curr; } void RenderPass::updateSummedPrimitiveCounts( diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h index a1fe2bf065..c8316f044b 100644 --- a/filament/src/RenderPass.h +++ b/filament/src/RenderPass.h @@ -394,7 +394,7 @@ private: math::float3 cameraPosition, math::float3 cameraForward) noexcept; template - static inline void generateCommandsImpl(uint32_t, Command* commands, + static inline Command* generateCommandsImpl(uint32_t extraFlags, Command* curr, FScene::RenderableSoa const& soa, utils::Range range, Variant variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, math::float3 cameraPosition, math::float3 cameraForward) noexcept;