Ticket #2913: clever_dirty_visibility.patch

File clever_dirty_visibility.patch, 9.1 KB (added by Itms, 9 years ago)
  • source/simulation2/components/CCmpRangeManager.cpp

     
    9898}
    9999
    100100/**
    101 * Computes the 2-bit visibility for one player, given the total 32-bit visibilities
    102 */
     101 * Returns shared 1-bit mask for given list of players.
     102 */
     103static u32 CalcSharedDirtyVisibilityMask(std::vector<player_id_t> players)
     104{
     105    u16 playerMask = 0;
     106    for (size_t i = 0; i < players.size(); i++)
     107    {
     108        if (players[i] > 0 && players[i] <= 16)
     109            playerMask |= (0x1 << (players[i] - 1));
     110    }
     111
     112    return playerMask;
     113}
     114
     115/**
     116 * Computes the 2-bit visibility for one player, given the total 32-bit visibilities
     117 */
    103118static inline u8 GetPlayerVisibility(u32 visibilities, player_id_t player)
    104119{
    105120    if (player > 0 && player <= 16)
     
    108123}
    109124
    110125/**
     126 * Test whether the visibility is dirty for a given LoS tile and a given player
     127 */
     128static inline bool IsVisibilityDirty(u16 dirty, player_id_t player)
     129{
     130    if (player > 0 && player <= 16)
     131        return (dirty >> (player - 1)) & 0x1;
     132    return false;
     133}
     134
     135/**
    111136 * Checks whether v is in a parabolic range of (0,0,0)
    112137 * The highest point of the paraboloid is (0,range/2,0)
    113138 * and the circle of distance 'range' around (0,0,0) on height y=0 is part of the paraboloid
     
    302327    // Cache for visibility tracking (not serialized)
    303328    i32 m_LosTilesPerSide;
    304329    bool m_GlobalVisibilityUpdate;
    305     std::vector<u8> m_DirtyVisibility;
     330    std::vector<u16> m_DirtyVisibility;
    306331    std::vector<std::set<entity_id_t> > m_LosTiles;
    307332    // List of entities that must be updated, regardless of the status of their tile
    308333    std::vector<entity_id_t> m_ModifiedEntities;
     
    323348
    324349    // Shared LOS masks, one per player.
    325350    std::vector<u32> m_SharedLosMasks;
     351    // Shared dirty visibility masks, one per player.
     352    std::vector<u16> m_SharedDirtyVisibilityMasks;
    326353
    327354    // Cache explored vertices per player (not serialized)
    328355    u32 m_TotalInworldVertices;
     
    351378        m_LosRevealAll.resize(MAX_LOS_PLAYER_ID+2,false);
    352379        m_LosRevealAll[0] = true;
    353380        m_SharedLosMasks.resize(MAX_LOS_PLAYER_ID+2,0);
     381        m_SharedDirtyVisibilityMasks.resize(MAX_LOS_PLAYER_ID + 2, 0);
    354382
    355383        m_LosCircular = false;
    356384        m_TerrainVerticesPerSide = 0;
     
    384412
    385413        SerializeVector<SerializeU32_Unbounded>()(serialize, "los state", m_LosState);
    386414        SerializeVector<SerializeU32_Unbounded>()(serialize, "shared los masks", m_SharedLosMasks);
     415        SerializeVector<SerializeU16_Unbounded>()(serialize, "shared dirty visibility masks", m_SharedDirtyVisibilityMasks);
    387416    }
    388417
    389418    virtual void Serialize(ISerializer& serialize)
     
    14891518        if (player <= 0)
    14901519            return ComputeLosVisibility(ent, player);
    14911520
    1492         if (m_DirtyVisibility[n])
     1521        if (IsVisibilityDirty(m_DirtyVisibility[n], player))
    14931522            return ComputeLosVisibility(ent, player);
    14941523
    14951524        if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), entId) != m_ModifiedEntities.end())
     
    15461575       
    15471576        for (i32 n = 0; n < m_LosTilesPerSide*m_LosTilesPerSide; ++n)
    15481577        {
    1549             if (m_DirtyVisibility[n] == 1 || m_GlobalVisibilityUpdate)
     1578            for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID + 1; ++player)
    15501579            {
    1551                 for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin();
    1552                     it != m_LosTiles[n].end();
    1553                     ++it)
     1580                if (IsVisibilityDirty(m_DirtyVisibility[n], player) || m_GlobalVisibilityUpdate)
    15541581                {
    1555                     UpdateVisibility(*it);
     1582                    for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin();
     1583                        it != m_LosTiles[n].end();
     1584                        ++it)
     1585                    {
     1586                        UpdateVisibility(*it, player);
     1587                    }
    15561588                }
    1557                 m_DirtyVisibility[n] = 0;
    15581589            }
     1590            m_DirtyVisibility[n] = 0;
    15591591        }
    15601592
    1561         for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it)
     1593        // Don't bother updating modified entities if the update was global
     1594        if (!m_GlobalVisibilityUpdate)
    15621595        {
    1563             // Don't bother updating if we already did it in a global update
    1564             if (!m_GlobalVisibilityUpdate)
     1596            for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it)
    15651597                UpdateVisibility(*it);
    15661598        }
     1599
    15671600        m_ModifiedEntities.clear();
    1568 
    15691601        m_GlobalVisibilityUpdate = false;
    15701602    }
    15711603
     
    15751607            m_ModifiedEntities.push_back(ent);
    15761608    }
    15771609
    1578     void UpdateVisibility(entity_id_t ent)
     1610    void UpdateVisibility(entity_id_t ent, player_id_t player)
    15791611    {
    1580         // Warning: Code related to fogging (like posting VisibilityChanged messages)
    1581         // shouldn't be invoked while keeping an iterator to an element of m_EntityData.
    1582         // Otherwise, by deleting mirage entities and so on,
    1583         // that code will change the indexes in the map, leading to segfaults.
    15841612        EntityMap<EntityData>::iterator itEnts = m_EntityData.find(ent);
    15851613        if (itEnts == m_EntityData.end())
    15861614            return;
    15871615
    1588         // So we just remember what visibilities to update and do that later.
    1589         std::vector<u8> oldVisibilities;
    1590         std::vector<u8> newVisibilities;
     1616        u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player);
     1617        u8 newVis = ComputeLosVisibility(itEnts->first, player);
     1618
     1619        if (oldVis == newVis)
     1620            return;
    15911621       
    1592         for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID+1; ++player)
    1593         {
    1594             u8 oldVis = GetPlayerVisibility(itEnts->second.visibilities, player);
    1595             u8 newVis = ComputeLosVisibility(itEnts->first, player);
    1596            
    1597             oldVisibilities.push_back(oldVis);
    1598             newVisibilities.push_back(newVis);
     1622        itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2 * (player - 1))) | (newVis << 2 * (player - 1));
    15991623
    1600             if (oldVis != newVis)
    1601                 itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*(player-1))) | (newVis << 2*(player-1));
    1602         }
     1624        CMessageVisibilityChanged msg(player, ent, oldVis, newVis);
     1625        GetSimContext().GetComponentManager().PostMessage(ent, msg);
     1626    }
    16031627
    1604         for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID+1; ++player)
    1605         {
    1606             if (oldVisibilities[player-1] == newVisibilities[player-1])
    1607                 continue;
    1608 
    1609             CMessageVisibilityChanged msg(player, ent, oldVisibilities[player-1], newVisibilities[player-1]);
    1610             GetSimContext().GetComponentManager().PostMessage(ent, msg);
    1611         }
     1628    void UpdateVisibility(entity_id_t ent)
     1629    {       
     1630        for (player_id_t player = 1; player < MAX_LOS_PLAYER_ID + 1; ++player)
     1631            UpdateVisibility(ent, player);
    16121632    }
    16131633
    16141634    virtual void SetLosRevealAll(player_id_t player, bool enabled)
     
    16531673    virtual void SetSharedLos(player_id_t player, std::vector<player_id_t> players)
    16541674    {
    16551675        m_SharedLosMasks[player] = CalcSharedLosMask(players);
     1676        m_SharedDirtyVisibilityMasks[player] = CalcSharedDirtyVisibilityMask(players);
    16561677    }
    16571678
    16581679    virtual u32 GetSharedLosMask(player_id_t player)
     
    18141835                int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
    18151836
    18161837                if (j > 0 && i > 0)
    1817                     m_DirtyVisibility[n1] = 1;
     1838                    m_DirtyVisibility[n1] |= m_SharedDirtyVisibilityMasks[owner];
    18181839                if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide)
    1819                     m_DirtyVisibility[n2] = 1;
     1840                    m_DirtyVisibility[n2] |= m_SharedDirtyVisibilityMasks[owner];
    18201841                if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0)
    1821                     m_DirtyVisibility[n3] = 1;
     1842                    m_DirtyVisibility[n3] |= m_SharedDirtyVisibilityMasks[owner];
    18221843                if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide)
    1823                     m_DirtyVisibility[n4] = 1;
     1844                    m_DirtyVisibility[n4] |= m_SharedDirtyVisibilityMasks[owner];
    18241845            }
    18251846
    18261847            ASSERT(counts[idx] < 65535);
     
    18591880                int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
    18601881
    18611882                if (j > 0 && i > 0)
    1862                     m_DirtyVisibility[n1] = 1;
     1883                    m_DirtyVisibility[n1] |= m_SharedDirtyVisibilityMasks[owner];
    18631884                if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide)
    1864                     m_DirtyVisibility[n2] = 1;
     1885                    m_DirtyVisibility[n2] |= m_SharedDirtyVisibilityMasks[owner];
    18651886                if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0)
    1866                     m_DirtyVisibility[n3] = 1;
     1887                    m_DirtyVisibility[n3] |= m_SharedDirtyVisibilityMasks[owner];
    18671888                if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide)
    1868                     m_DirtyVisibility[n4] = 1;
     1889                    m_DirtyVisibility[n4] |= m_SharedDirtyVisibilityMasks[owner];
    18691890            }
    18701891        }
    18711892    }
  • source/simulation2/serialization/SerializeTemplates.h

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    151151    }
    152152};
    153153
     154struct SerializeU16_Unbounded
     155{
     156    void operator()(ISerializer& serialize, const char* name, u16 value)
     157    {
     158        serialize.NumberU16_Unbounded(name, value);
     159    }
     160
     161    void operator()(IDeserializer& deserialize, const char* name, u16& value)
     162    {
     163        deserialize.NumberU16_Unbounded(name, value);
     164    }
     165};
     166
    154167struct SerializeU32_Unbounded
    155168{
    156169    void operator()(ISerializer& serialize, const char* name, u32 value)