community-shaders/skyrim-community-shaders

perf: Refactor SetupGeometry vtable hooks to use centralized Feature lifecycle pattern

Open

#1,752 opened on Jan 24, 2026

View on GitHub
 (0 comments) (0 reactions) (0 assignees)C++ (134 forks)github user discovery
ai suggestionhelp wantedperformance

Repository metrics

Stars
 (1,037 stars)
PR merge metrics
 (Avg merge 2d 4h) (63 merged PRs in 30d)

Description

Problem

Similar to #1751, multiple features hook SetupGeometry independently, creating redundant vtable hook chains in a hot path called for every render pass (thousands of times per frame).

Features hooking BSLightingShader::SetupGeometry:

  • TruePBR (core)
  • Hooks.cpp core extensions
  • LightLimitFix
  • SubsurfaceScattering
  • LinearLighting
  • ExtendedTranslucency
  • FrameAnnotations

Features hooking BSEffectShader::SetupGeometry:

  • Hooks.cpp core extensions
  • LightLimitFix
  • FrameAnnotations

Features hooking BSGrassShader::SetupGeometry:

  • Hooks.cpp core extensions
  • GrassCollision
  • FrameAnnotations

Each feature patches the same vtable slot (0x6), creating a chain of virtual dispatches. With 10+ hooks, this creates unnecessary overhead.

Proposed Solution

Add new Feature lifecycle hooks following the pattern from #1751:

virtual void SetupGeometry_Lighting(RE::BSRenderPass* pass, uint32_t flags) {}
virtual void SetupGeometry_Effect(RE::BSRenderPass* pass, uint32_t flags) {}  
virtual void SetupGeometry_Grass(RE::BSRenderPass* pass, uint32_t flags) {}
virtual void SetupGeometry_Water(RE::BSRenderPass* pass, uint32_t flags) {}

Centralize the vtable hooks in Hooks.cpp to dispatch to all features in a single pass, similar to the existing Prepass() pattern.

Benefits

  • Eliminates 10+ chained vtable hooks
  • Single virtual dispatch + feature loop instead of chain
  • Consistent with #1751 architecture
  • Easier feature development
  • Runtime toggling preserved

Impact

Higher priority than #1751 as this affects 10+ features vs 2 features for RenderPassImmediately.

Related

  • #1751 - Similar refactor for RenderPassImmediately

Contributor guide