diff --git a/src/newgrf_optimiser.cpp b/src/newgrf_optimiser.cpp index 5c38951ebe..ff6b2e768b 100644 --- a/src/newgrf_optimiser.cpp +++ b/src/newgrf_optimiser.cpp @@ -14,6 +14,7 @@ #include "debug_settings.h" #include "core/y_combinator.hpp" #include "scope.h" +#include "newgrf_station.h" #include @@ -2444,6 +2445,36 @@ static void OptimiseVarAction2CheckInliningCandidate(DeterministicSpriteGroup *g *(_cur.GetInlinableGroupAdjusts(group, true)) = std::move(saved_adjusts); } +static void PopulateRegistersUsedByNewGRFSpriteLayout(const NewGRFSpriteLayout &dts, std::bitset<256> &bits) +{ + const TileLayoutRegisters *registers = dts.registers; + + auto process_registers = [&](uint i, bool is_parent) { + const TileLayoutRegisters *reg = registers + i; + if (reg->flags & TLF_DODRAW) bits.set(reg->dodraw, true); + if (reg->flags & TLF_SPRITE) bits.set(reg->sprite, true); + if (reg->flags & TLF_PALETTE) bits.set(reg->palette, true); + if (is_parent) { + if (reg->flags & TLF_BB_XY_OFFSET) { + bits.set(reg->delta.parent[0], true); + bits.set(reg->delta.parent[1], true); + } + if (reg->flags & TLF_BB_Z_OFFSET) bits.set(reg->delta.parent[2], true); + } else { + if (reg->flags & TLF_CHILD_X_OFFSET) bits.set(reg->delta.child[0], true); + if (reg->flags & TLF_CHILD_Y_OFFSET) bits.set(reg->delta.child[1], true); + } + }; + process_registers(0, false); + + uint offset = 0; // offset 0 is the ground sprite + const DrawTileSeqStruct *element; + foreach_draw_tile_seq(element, dts.seq) { + offset++; + process_registers(offset, element->IsParentSprite()); + } +} + void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState &state, const GrfSpecFeature feature, const byte varsize, DeterministicSpriteGroup *group, std::vector &saved_adjusts) { if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return; @@ -2529,32 +2560,7 @@ void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState &state, if (sg != nullptr && sg->type == SGT_TILELAYOUT) { const TileLayoutSpriteGroup *tlsg = (const TileLayoutSpriteGroup*)sg; if (tlsg->dts.registers != nullptr) { - const TileLayoutRegisters *registers = tlsg->dts.registers; - - auto process_registers = [&](uint i, bool is_parent) { - const TileLayoutRegisters *reg = registers + i; - if (reg->flags & TLF_DODRAW) bits.set(reg->dodraw, true); - if (reg->flags & TLF_SPRITE) bits.set(reg->sprite, true); - if (reg->flags & TLF_PALETTE) bits.set(reg->palette, true); - if (is_parent) { - if (reg->flags & TLF_BB_XY_OFFSET) { - bits.set(reg->delta.parent[0], true); - bits.set(reg->delta.parent[1], true); - } - if (reg->flags & TLF_BB_Z_OFFSET) bits.set(reg->delta.parent[2], true); - } else { - if (reg->flags & TLF_CHILD_X_OFFSET) bits.set(reg->delta.child[0], true); - if (reg->flags & TLF_CHILD_Y_OFFSET) bits.set(reg->delta.child[1], true); - } - }; - process_registers(0, false); - - uint offset = 0; // offset 0 is the ground sprite - const DrawTileSeqStruct *element; - foreach_draw_tile_seq(element, tlsg->dts.seq) { - offset++; - process_registers(offset, element->IsParentSprite()); - } + PopulateRegistersUsedByNewGRFSpriteLayout(tlsg->dts, bits); } } if (sg != nullptr && sg->type == SGT_INDUSTRY_PRODUCTION) { @@ -2980,10 +2986,40 @@ static std::bitset<256> HandleVarAction2DeadStoreElimination(DeterministicSprite return propagate_bits; } +static void PopulateRailStationAdvancedLayoutVariableUsage() +{ + for (uint i = 0; StationClass::IsClassIDValid((StationClassID)i); i++) { + StationClass *stclass = StationClass::Get((StationClassID)i); + + for (uint j = 0; j < stclass->GetSpecCount(); j++) { + const StationSpec *statspec = stclass->GetSpec(j); + if (statspec == nullptr) continue; + + std::bitset<256> bits; + for (const NewGRFSpriteLayout &dts : statspec->renderdata) { + if (dts.registers != nullptr) { + PopulateRegistersUsedByNewGRFSpriteLayout(dts, bits); + } + } + if (bits.any()) { + /* Simulate a procedure call on each of the root sprite groups which requires the bits used in the tile layouts */ + CheckDeterministicSpriteGroupOutputVarBitsProcedureHandler proc_handler(bits); + for (uint k = 0; k < NUM_CARGO + 3; k++) { + if (statspec->grf_prop.spritegroup[k] != nullptr) { + proc_handler.ProcessGroup(statspec->grf_prop.spritegroup[k], nullptr, true); + } + } + } + } + } +} + void HandleVarAction2OptimisationPasses() { if (unlikely(HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2))) return; + PopulateRailStationAdvancedLayoutVariableUsage(); + for (DeterministicSpriteGroup *group : _cur.dead_store_elimination_candidates) { VarAction2GroupVariableTracking *var_tracking = _cur.GetVarAction2GroupVariableTracking(group, false); if (!group->calculated_result) {