forked from 0ad/0ad
Optimise HierarchicalPathfinder::Update by speeding up the chunk dirtiness check.
By adding a custom function in Grid, the code gets vectorised on both gcc and clang, resulting in much faster code and faster update times, sometimes substantially (on giant maps or when few chunks must be updated). Reviewed By: mimo Differential Revision: https://code.wildfiregames.com/D73 This was SVN commit r20630.
This commit is contained in:
parent
1933461009
commit
f7aa7ac79e
@ -21,9 +21,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "maths/Vector2D.h"
|
||||
#include "simulation2/helpers/Grid.h"
|
||||
#include "simulation2/helpers/Player.h"
|
||||
|
||||
template<typename T>
|
||||
class Grid;
|
||||
|
||||
/**
|
||||
* Describes an outline of a territory, where the latter are understood to mean the largest sets of mutually connected tiles
|
||||
* ('connected' as in the mathematical sense from graph theory) that are either all reachable or all unreachable from a root
|
||||
|
@ -18,9 +18,10 @@
|
||||
#include "lib/ogl.h"
|
||||
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "simulation2/helpers/Grid.h"
|
||||
|
||||
class CSimulation2;
|
||||
template<typename T>
|
||||
class Grid;
|
||||
|
||||
/**
|
||||
* Maintains the territory boundary texture, used for
|
||||
|
@ -20,10 +20,12 @@
|
||||
|
||||
#include "simulation2/system/Interface.h"
|
||||
|
||||
#include "simulation2/helpers/Grid.h"
|
||||
#include "simulation2/helpers/Player.h"
|
||||
#include "simulation2/components/ICmpPosition.h"
|
||||
|
||||
template<typename T>
|
||||
class Grid;
|
||||
|
||||
class ICmpTerritoryManager : public IComponent
|
||||
{
|
||||
public:
|
||||
|
@ -102,6 +102,22 @@ public:
|
||||
return m_W == 0 && m_H == 0;
|
||||
}
|
||||
|
||||
bool any_set_in_square(int i0, int j0, int i1, int j1) const
|
||||
{
|
||||
#if GRID_BOUNDS_DEBUG
|
||||
ENSURE(i0 >= 0 && j0 >= 0 && i1 < m_W && j1 < m_H);
|
||||
#endif
|
||||
for (int j = j0; j < j1; ++j)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = i0; i < i1; ++i)
|
||||
sum += m_Data[j*m_W + i];
|
||||
if (sum > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (m_Data)
|
||||
|
@ -411,10 +411,16 @@ void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dir
|
||||
|
||||
for (int cj = 0; cj < m_ChunksH; ++cj)
|
||||
{
|
||||
int j0 = cj * CHUNK_SIZE;
|
||||
int j1 = std::min(j0 + CHUNK_SIZE, (int)dirtinessGrid.m_H);
|
||||
for (int ci = 0; ci < m_ChunksW; ++ci)
|
||||
{
|
||||
if (!IsChunkDirty(ci, cj, dirtinessGrid))
|
||||
// Skip chunks where no navcells are dirty.
|
||||
int i0 = ci * CHUNK_SIZE;
|
||||
int i1 = std::min(i0 + CHUNK_SIZE, (int)dirtinessGrid.m_W);
|
||||
if (!dirtinessGrid.any_set_in_square(i0, j0, i1, j1))
|
||||
continue;
|
||||
|
||||
for (const std::pair<std::string, pass_class_t>& passClassMask : m_PassClassMasks)
|
||||
{
|
||||
pass_class_t passClass = passClassMask.second;
|
||||
@ -448,23 +454,6 @@ void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dir
|
||||
}
|
||||
}
|
||||
|
||||
bool HierarchicalPathfinder::IsChunkDirty(int ci, int cj, const Grid<u8>& dirtinessGrid) const
|
||||
{
|
||||
int i0 = ci * CHUNK_SIZE;
|
||||
int j0 = cj * CHUNK_SIZE;
|
||||
int i1 = std::min(i0 + CHUNK_SIZE, (int)dirtinessGrid.m_W);
|
||||
int j1 = std::min(j0 + CHUNK_SIZE, (int)dirtinessGrid.m_H);
|
||||
for (int j = j0; j < j1; ++j)
|
||||
{
|
||||
for (int i = i0; i < i1; ++i)
|
||||
{
|
||||
if (dirtinessGrid.get(i, j))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find edges between regions in this chunk and the adjacent below/left chunks.
|
||||
*/
|
||||
|
@ -86,8 +86,6 @@ public:
|
||||
|
||||
void Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid);
|
||||
|
||||
bool IsChunkDirty(int ci, int cj, const Grid<u8>& dirtinessGrid) const;
|
||||
|
||||
RegionID Get(u16 i, u16 j, pass_class_t passClass);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user