mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: add dedicated double-precission time type
The library used signed 32bit integers and single precission floating points to represent build times, but on long build times this will overflow. Added a dedicated time type while promoting it to double precission and adjusting all use cases throughout the library.
This commit is contained in:
parent
b41141018e
commit
7c3509fd34
@ -827,11 +827,11 @@ void CrowdToolState::updateTick(const float dt)
|
||||
dtCrowd* crowd = m_editor->getCrowd();
|
||||
if (!nav || !crowd) return;
|
||||
|
||||
TimeVal startTime = getPerfTime();
|
||||
rdTimeType startTime = getPerfTime();
|
||||
|
||||
crowd->update(dt, &m_agentDebug);
|
||||
|
||||
TimeVal endTime = getPerfTime();
|
||||
rdTimeType endTime = getPerfTime();
|
||||
|
||||
// Update agent trails
|
||||
for (int i = 0; i < crowd->getAgentCount(); ++i)
|
||||
|
@ -22,22 +22,22 @@ void BuildContext::doResetLog()
|
||||
m_textPoolSize = 0;
|
||||
}
|
||||
|
||||
void BuildContext::doLog(const rcLogCategory category, const char* msg, const int len)
|
||||
void BuildContext::doLog(const rcLogCategory category, const char* msg, const rdSizeType len)
|
||||
{
|
||||
if (!len) return;
|
||||
if (m_messageCount >= MAX_MESSAGES)
|
||||
return;
|
||||
char* dst = &m_textPool[m_textPoolSize];
|
||||
int n = TEXT_POOL_SIZE - m_textPoolSize;
|
||||
const rdSizeType n = TEXT_POOL_SIZE - m_textPoolSize;
|
||||
if (n < 2)
|
||||
return;
|
||||
char* cat = dst;
|
||||
char* text = dst+1;
|
||||
const int maxtext = n-1;
|
||||
const rdSizeType maxtext = n-1;
|
||||
// Store category
|
||||
*cat = (char)category;
|
||||
// Store message
|
||||
const int count = rdMin(len+1, maxtext);
|
||||
const rdSizeType count = rdMin(len+1, maxtext);
|
||||
memcpy(text, msg, count);
|
||||
text[count-1] = '\0';
|
||||
m_textPoolSize += 1 + count;
|
||||
@ -46,7 +46,7 @@ void BuildContext::doLog(const rcLogCategory category, const char* msg, const in
|
||||
|
||||
void BuildContext::doResetTimers()
|
||||
{
|
||||
for (int i = 0; i < RC_MAX_TIMERS; ++i)
|
||||
for (rdSizeType i = 0; i < RC_MAX_TIMERS; ++i)
|
||||
m_accTime[i] = -1;
|
||||
}
|
||||
|
||||
@ -57,15 +57,15 @@ void BuildContext::doStartTimer(const rcTimerLabel label)
|
||||
|
||||
void BuildContext::doStopTimer(const rcTimerLabel label)
|
||||
{
|
||||
const TimeVal endTime = getPerfTime();
|
||||
const TimeVal deltaTime = endTime - m_startTime[label];
|
||||
const rdTimeType endTime = getPerfTime();
|
||||
const rdTimeType deltaTime = endTime - m_startTime[label];
|
||||
if (m_accTime[label] == -1)
|
||||
m_accTime[label] = deltaTime;
|
||||
else
|
||||
m_accTime[label] += deltaTime;
|
||||
}
|
||||
|
||||
int BuildContext::doGetAccumulatedTime(const rcTimerLabel label) const
|
||||
rdTimeType BuildContext::doGetAccumulatedTime(const rcTimerLabel label) const
|
||||
{
|
||||
return getPerfTimeUsec(m_accTime[label]);
|
||||
}
|
||||
@ -80,16 +80,16 @@ void BuildContext::dumpLog(const char* format, ...)
|
||||
printf("\n");
|
||||
|
||||
// Print messages
|
||||
const int TAB_STOPS[4] = { 28, 36, 44, 52 };
|
||||
const rdSizeType TAB_STOPS[4] = { 28, 36, 44, 52 };
|
||||
for (int i = 0; i < m_messageCount; ++i)
|
||||
{
|
||||
const char* msg = m_messages[i]+1;
|
||||
int n = 0;
|
||||
rdSizeType n = 0;
|
||||
while (*msg)
|
||||
{
|
||||
if (*msg == '\t')
|
||||
{
|
||||
int count = 1;
|
||||
rdSizeType count = 1;
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
if (n < TAB_STOPS[j])
|
||||
@ -120,7 +120,7 @@ int BuildContext::getLogCount() const
|
||||
return m_messageCount;
|
||||
}
|
||||
|
||||
const char* BuildContext::getLogText(const int i) const
|
||||
const char* BuildContext::getLogText(const rdSizeType i) const
|
||||
{
|
||||
return m_messages[i]+1;
|
||||
}
|
||||
|
@ -23,19 +23,19 @@
|
||||
// Win32
|
||||
#include <windows.h>
|
||||
|
||||
TimeVal getPerfTime()
|
||||
rdTimeType getPerfTime()
|
||||
{
|
||||
__int64 count;
|
||||
rdTimeType count;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int getPerfTimeUsec(const TimeVal duration)
|
||||
rdTimeType getPerfTimeUsec(const rdTimeType duration)
|
||||
{
|
||||
static __int64 freq = 0;
|
||||
static rdTimeType freq = 0;
|
||||
if (freq == 0)
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
|
||||
return (int)(duration*1000000 / freq);
|
||||
return (rdTimeType)(duration*1000000 / freq);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -44,16 +44,16 @@ int getPerfTimeUsec(const TimeVal duration)
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
TimeVal getPerfTime()
|
||||
rdTimeType getPerfTime()
|
||||
{
|
||||
timeval now;
|
||||
gettimeofday(&now, 0);
|
||||
return (TimeVal)now.tv_sec*1000000L + (TimeVal)now.tv_usec;
|
||||
return (rdTimeType)now.tv_sec*1000000L + (rdTimeType)now.tv_usec;
|
||||
}
|
||||
|
||||
int getPerfTimeUsec(const TimeVal duration)
|
||||
rdTimeType getPerfTimeUsec(const rdTimeType duration)
|
||||
{
|
||||
return (int)duration;
|
||||
return duration;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -209,13 +209,13 @@ void TestCase::doTests(dtNavMesh* navmesh, dtNavMeshQuery* navquery)
|
||||
filter.setExcludeFlags(iter->excludeFlags);
|
||||
|
||||
// Find start points
|
||||
TimeVal findNearestPolyStart = getPerfTime();
|
||||
rdTimeType findNearestPolyStart = getPerfTime();
|
||||
|
||||
dtPolyRef startRef, endRef;
|
||||
navquery->findNearestPoly(iter->spos, polyPickExt, &filter, &startRef, iter->nspos);
|
||||
navquery->findNearestPoly(iter->epos, polyPickExt, &filter, &endRef, iter->nepos);
|
||||
|
||||
TimeVal findNearestPolyEnd = getPerfTime();
|
||||
rdTimeType findNearestPolyEnd = getPerfTime();
|
||||
iter->findNearestPolyTime += getPerfTimeUsec(findNearestPolyEnd - findNearestPolyStart);
|
||||
|
||||
if (!startRef || ! endRef)
|
||||
@ -224,21 +224,21 @@ void TestCase::doTests(dtNavMesh* navmesh, dtNavMeshQuery* navquery)
|
||||
if (iter->type == TEST_PATHFIND)
|
||||
{
|
||||
// Find path
|
||||
TimeVal findPathStart = getPerfTime();
|
||||
rdTimeType findPathStart = getPerfTime();
|
||||
|
||||
navquery->findPath(startRef, endRef, iter->spos, iter->epos, &filter, polys, &iter->npolys, MAX_POLYS);
|
||||
|
||||
TimeVal findPathEnd = getPerfTime();
|
||||
rdTimeType findPathEnd = getPerfTime();
|
||||
iter->findPathTime += getPerfTimeUsec(findPathEnd - findPathStart);
|
||||
|
||||
// Find straight path
|
||||
if (iter->npolys)
|
||||
{
|
||||
TimeVal findStraightPathStart = getPerfTime();
|
||||
rdTimeType findStraightPathStart = getPerfTime();
|
||||
|
||||
navquery->findStraightPath(iter->spos, iter->epos, polys, jumps, iter->npolys,
|
||||
straight, 0, 0, 0, &iter->nstraight, MAX_POLYS);
|
||||
TimeVal findStraightPathEnd = getPerfTime();
|
||||
rdTimeType findStraightPathEnd = getPerfTime();
|
||||
iter->findStraightPathTime += getPerfTimeUsec(findStraightPathEnd - findStraightPathStart);
|
||||
}
|
||||
|
||||
@ -266,11 +266,11 @@ void TestCase::doTests(dtNavMesh* navmesh, dtNavMeshQuery* navquery)
|
||||
iter->straight[1] = iter->spos[1];
|
||||
iter->straight[2] = iter->spos[2];
|
||||
|
||||
TimeVal findPathStart = getPerfTime();
|
||||
rdTimeType findPathStart = getPerfTime();
|
||||
|
||||
navquery->raycast(startRef, iter->spos, iter->epos, &filter, &t, hitNormal, polys, &iter->npolys, MAX_POLYS);
|
||||
|
||||
TimeVal findPathEnd = getPerfTime();
|
||||
rdTimeType findPathEnd = getPerfTime();
|
||||
iter->findPathTime += getPerfTimeUsec(findPathEnd - findPathStart);
|
||||
|
||||
if (t > 1)
|
||||
@ -302,14 +302,14 @@ void TestCase::doTests(dtNavMesh* navmesh, dtNavMeshQuery* navquery)
|
||||
|
||||
|
||||
printf("Test Results:\n");
|
||||
int n = 0;
|
||||
rdSizeType n = 0;
|
||||
for (Test* iter = m_tests; iter; iter = iter->next)
|
||||
{
|
||||
const int total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
|
||||
printf(" - Path %02d: %.4f ms\n", n, (float)total/1000.0f);
|
||||
printf(" - poly: %.4f ms\n", (float)iter->findNearestPolyTime/1000.0f);
|
||||
printf(" - path: %.4f ms\n", (float)iter->findPathTime/1000.0f);
|
||||
printf(" - straight: %.4f ms\n", (float)iter->findStraightPathTime/1000.0f);
|
||||
const rdTimeType total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
|
||||
printf(" - Path %02zd: %.4f ms\n", n, (double)total/1000.0);
|
||||
printf(" - poly: %.4f ms\n", (double)iter->findNearestPolyTime/1000.0);
|
||||
printf(" - path: %.4f ms\n", (double)iter->findPathTime/1000.0);
|
||||
printf(" - straight: %.4f ms\n", (double)iter->findStraightPathTime/1000.0);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -421,7 +421,7 @@ bool TestCase::handleRenderOverlay(double* proj, double* model, int* view)
|
||||
n = 0;
|
||||
for (Test* iter = m_tests; iter; iter = iter->next)
|
||||
{
|
||||
const int total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
|
||||
const rdTimeType total = iter->findNearestPolyTime + iter->findPathTime + iter->findStraightPathTime;
|
||||
snprintf(text, sizeof(text), "Path %d %.4f ms", n, (float)total / 1000.0f);
|
||||
|
||||
if (ImGui::CollapsingHeader(text))
|
||||
|
@ -29,15 +29,15 @@
|
||||
/// Recast build context.
|
||||
class BuildContext : public rcContext
|
||||
{
|
||||
TimeVal m_startTime[RC_MAX_TIMERS];
|
||||
TimeVal m_accTime[RC_MAX_TIMERS];
|
||||
rdTimeType m_startTime[RC_MAX_TIMERS];
|
||||
rdTimeType m_accTime[RC_MAX_TIMERS];
|
||||
|
||||
static const int MAX_MESSAGES = 1000;
|
||||
const char* m_messages[MAX_MESSAGES];
|
||||
int m_messageCount;
|
||||
static const int TEXT_POOL_SIZE = 8000;
|
||||
char m_textPool[TEXT_POOL_SIZE];
|
||||
int m_textPoolSize;
|
||||
rdSizeType m_textPoolSize;
|
||||
|
||||
public:
|
||||
BuildContext();
|
||||
@ -47,17 +47,17 @@ public:
|
||||
/// Returns number of log messages.
|
||||
int getLogCount() const;
|
||||
/// Returns log message text.
|
||||
const char* getLogText(const int i) const;
|
||||
const char* getLogText(const rdSizeType i) const;
|
||||
|
||||
protected:
|
||||
/// Virtual functions for custom implementations.
|
||||
///@{
|
||||
virtual void doResetLog();
|
||||
virtual void doLog(const rcLogCategory category, const char* msg, const int len);
|
||||
virtual void doLog(const rcLogCategory category, const char* msg, const rdSizeType len);
|
||||
virtual void doResetTimers();
|
||||
virtual void doStartTimer(const rcTimerLabel label);
|
||||
virtual void doStopTimer(const rcTimerLabel label);
|
||||
virtual int doGetAccumulatedTime(const rcTimerLabel label) const;
|
||||
virtual rdTimeType doGetAccumulatedTime(const rcTimerLabel label) const;
|
||||
///@}
|
||||
};
|
||||
|
||||
|
@ -53,7 +53,7 @@ protected:
|
||||
float m_lastBuiltTileBmin[3];
|
||||
float m_lastBuiltTileBmax[3];
|
||||
|
||||
float m_totalBuildTimeMs;
|
||||
double m_totalBuildTimeMs;
|
||||
|
||||
bool m_drawActiveTile;
|
||||
bool m_keepInterResults;
|
||||
@ -78,7 +78,7 @@ protected:
|
||||
struct FastLZCompressor* m_tcomp;
|
||||
struct MeshProcess* m_tmproc;
|
||||
|
||||
float m_cacheBuildTimeMs;
|
||||
double m_cacheBuildTimeMs;
|
||||
int m_cacheCompressedSize;
|
||||
int m_cacheRawSize;
|
||||
int m_cacheLayerCount;
|
||||
|
@ -33,7 +33,7 @@ protected:
|
||||
int m_maxTiles;
|
||||
int m_maxPolysPerTile;
|
||||
|
||||
float m_tileBuildTime;
|
||||
double m_tileBuildTime;
|
||||
float m_tileMemUsage;
|
||||
int m_tileTriCount;
|
||||
|
||||
|
@ -19,14 +19,9 @@
|
||||
#ifndef PERFTIMER_H
|
||||
#define PERFTIMER_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <stdint.h>
|
||||
typedef int64_t TimeVal;
|
||||
#else
|
||||
typedef __int64 TimeVal;
|
||||
#endif
|
||||
#include "Recast/Shared/Include/SharedDefs.h"
|
||||
|
||||
TimeVal getPerfTime();
|
||||
int getPerfTimeUsec(const TimeVal duration);
|
||||
rdTimeType getPerfTime();
|
||||
rdTimeType getPerfTimeUsec(const rdTimeType duration);
|
||||
|
||||
#endif // PERFTIMER_H
|
@ -73,9 +73,9 @@ class TestCase
|
||||
dtPolyRef* polys;
|
||||
int npolys;
|
||||
|
||||
int findNearestPolyTime;
|
||||
int findPathTime;
|
||||
int findStraightPathTime;
|
||||
rdTimeType findNearestPolyTime;
|
||||
rdTimeType findPathTime;
|
||||
rdTimeType findStraightPathTime;
|
||||
|
||||
Test* next;
|
||||
private:
|
||||
|
@ -30,7 +30,7 @@ bool duReadContourSet(struct rcContourSet& cset, duFileIO* io);
|
||||
bool duDumpCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
|
||||
bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io);
|
||||
|
||||
void duLogBuildTimes(rcContext& ctx, const int totalTileUsec);
|
||||
void duLogBuildTimes(rcContext& ctx, const rdTimeType totalTileUsec);
|
||||
|
||||
|
||||
#endif // RECAST_DUMP_H
|
||||
|
@ -404,16 +404,16 @@ bool duReadCompactHeightfield(struct rcCompactHeightfield& chf, duFileIO* io)
|
||||
}
|
||||
|
||||
|
||||
static void logLine(rcContext& ctx, rcTimerLabel label, const char* name, const float pc)
|
||||
static void logLine(rcContext& ctx, rcTimerLabel label, const char* name, const double pc)
|
||||
{
|
||||
const int t = ctx.getAccumulatedTime(label);
|
||||
const rdTimeType t = ctx.getAccumulatedTime(label);
|
||||
if (t < 0) return;
|
||||
ctx.log(RC_LOG_PROGRESS, "%s:\t%.2fms\t(%.1f%%)", name, t/1000.0f, t*pc);
|
||||
}
|
||||
|
||||
void duLogBuildTimes(rcContext& ctx, const int totalTimeUsec)
|
||||
void duLogBuildTimes(rcContext& ctx, const rdTimeType totalTimeUsec)
|
||||
{
|
||||
const float pc = 100.0f / totalTimeUsec;
|
||||
const double pc = 100.0f / totalTimeUsec;
|
||||
|
||||
ctx.log(RC_LOG_PROGRESS, "Build Times");
|
||||
logLine(ctx, RC_TIMER_RASTERIZE_TRIANGLES, "- Rasterize", pc);
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
/// Returns the total accumulated time of the specified performance timer.
|
||||
/// @param label The category of the timer.
|
||||
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
||||
inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
|
||||
inline rdTimeType getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
|
||||
|
||||
protected:
|
||||
/// Clears all log entries.
|
||||
@ -162,7 +162,7 @@ protected:
|
||||
/// @param[in] category The category of the message.
|
||||
/// @param[in] msg The formatted message.
|
||||
/// @param[in] len The length of the formatted message.
|
||||
virtual void doLog(const rcLogCategory category, const char* msg, const int len) { rdIgnoreUnused(category); rdIgnoreUnused(msg); rdIgnoreUnused(len); }
|
||||
virtual void doLog(const rcLogCategory category, const char* msg, const rdSizeType len) { rdIgnoreUnused(category); rdIgnoreUnused(msg); rdIgnoreUnused(len); }
|
||||
|
||||
/// Clears all timers. (Resets all to unused.)
|
||||
virtual void doResetTimers() {}
|
||||
@ -178,7 +178,7 @@ protected:
|
||||
/// Returns the total accumulated time of the specified performance timer.
|
||||
/// @param[in] label The category of the timer.
|
||||
/// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
||||
virtual int doGetAccumulatedTime(const rcTimerLabel label) const { rdIgnoreUnused(label); return -1; }
|
||||
virtual rdTimeType doGetAccumulatedTime(const rcTimerLabel label) const { rdIgnoreUnused(label); return -1; }
|
||||
|
||||
/// True if logging is enabled.
|
||||
bool m_logEnabled;
|
||||
|
@ -19,6 +19,13 @@
|
||||
#ifndef RECASTDETOURDEFS_H
|
||||
#define RECASTDETOURDEFS_H
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#include <stdint.h>
|
||||
typedef int64_t rdTimeType;
|
||||
#else
|
||||
typedef __int64 rdTimeType;
|
||||
#endif
|
||||
|
||||
/// Signed to avoid warnings when comparing to int loop indexes, and common error with comparing to zero.
|
||||
/// MSVC2010 has a bug where ssize_t is unsigned (!!!).
|
||||
typedef intptr_t rdSizeType;
|
||||
|
Loading…
x
Reference in New Issue
Block a user