forked from metin-server/m2dev-client-src
Add high-FPS render pacing and telemetry
This commit is contained in:
@@ -65,6 +65,11 @@ VOID ELTimer_SetFrameMSec()
|
||||
gs_dwFrameTime = ELTimer_GetMSec();
|
||||
}
|
||||
|
||||
VOID ELTimer_SetFrameMSecValue(DWORD dwFrameTime)
|
||||
{
|
||||
gs_dwFrameTime = dwFrameTime;
|
||||
}
|
||||
|
||||
CTimer::CTimer()
|
||||
{
|
||||
ELTimer_Init();
|
||||
|
||||
@@ -38,4 +38,5 @@ VOID ELTimer_SetServerMSec(DWORD dwServerTime);
|
||||
DWORD ELTimer_GetServerMSec();
|
||||
|
||||
VOID ELTimer_SetFrameMSec();
|
||||
DWORD ELTimer_GetFrameMSec();
|
||||
VOID ELTimer_SetFrameMSecValue(DWORD dwFrameTime);
|
||||
DWORD ELTimer_GetFrameMSec();
|
||||
|
||||
@@ -18,6 +18,9 @@ void CActorInstance::INSTANCEBASE_Deform()
|
||||
|
||||
void CActorInstance::INSTANCEBASE_Transform()
|
||||
{
|
||||
m_v3InterpolationStartPosition = D3DXVECTOR3(m_x, m_y, m_z);
|
||||
m_fInterpolationStartRotation = m_fcurRotation;
|
||||
|
||||
if (m_pkHorse)
|
||||
{
|
||||
m_pkHorse->INSTANCEBASE_Transform();
|
||||
@@ -44,6 +47,30 @@ void CActorInstance::INSTANCEBASE_Transform()
|
||||
UpdateAttribute();
|
||||
}
|
||||
|
||||
void CActorInstance::ApplyRenderInterpolation(float fInterpolation)
|
||||
{
|
||||
const float fAlpha = std::max(0.0f, std::min(1.0f, fInterpolation));
|
||||
|
||||
D3DXVECTOR3 v3InterpolatedPosition;
|
||||
v3InterpolatedPosition.x = m_v3InterpolationStartPosition.x + (m_x - m_v3InterpolationStartPosition.x) * fAlpha;
|
||||
v3InterpolatedPosition.y = m_v3InterpolationStartPosition.y + (m_y - m_v3InterpolationStartPosition.y) * fAlpha;
|
||||
v3InterpolatedPosition.z = m_v3InterpolationStartPosition.z + (m_z - m_v3InterpolationStartPosition.z) * fAlpha;
|
||||
|
||||
const float fInterpolatedRotation = GetInterpolatedRotation(m_fInterpolationStartRotation, m_fcurRotation, fAlpha);
|
||||
|
||||
SetPosition(v3InterpolatedPosition);
|
||||
if (0.0f != m_rotX || 0.0f != m_rotY)
|
||||
{
|
||||
CGraphicObjectInstance::SetRotation(m_rotX, m_rotY, fInterpolatedRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGraphicObjectInstance::SetRotation(fInterpolatedRotation);
|
||||
}
|
||||
|
||||
Transform();
|
||||
}
|
||||
|
||||
|
||||
void CActorInstance::OnUpdate()
|
||||
{
|
||||
@@ -875,6 +902,7 @@ void CActorInstance::__InitializeRotationData()
|
||||
{
|
||||
m_fAtkDirRot = 0.0f;
|
||||
m_fcurRotation = 0.0f;
|
||||
m_fInterpolationStartRotation = 0.0f;
|
||||
m_rotBegin = 0.0f;
|
||||
m_rotEnd = 0.0f;
|
||||
m_rotEndTime = 0.0f;
|
||||
|
||||
@@ -425,6 +425,7 @@ class CActorInstance : public IActorInstance, public IFlyTargetableObject
|
||||
void LookAt(CActorInstance * pInstance);
|
||||
void LookWith(CActorInstance * pInstance);
|
||||
void LookAtFromXY(float x, float y, CActorInstance * pDestInstance);
|
||||
void ApplyRenderInterpolation(float fInterpolation);
|
||||
|
||||
|
||||
void SetReachScale(float fScale);
|
||||
@@ -767,6 +768,7 @@ class CActorInstance : public IActorInstance, public IFlyTargetableObject
|
||||
float m_x;
|
||||
float m_y;
|
||||
float m_z;
|
||||
D3DXVECTOR3 m_v3InterpolationStartPosition;
|
||||
D3DXVECTOR3 m_v3Pos;
|
||||
D3DXVECTOR3 m_v3Movement;
|
||||
BOOL m_bNeedUpdateCollision;
|
||||
@@ -779,6 +781,7 @@ class CActorInstance : public IActorInstance, public IFlyTargetableObject
|
||||
|
||||
// Rotation
|
||||
float m_fcurRotation;
|
||||
float m_fInterpolationStartRotation;
|
||||
float m_rotBegin;
|
||||
float m_rotEnd;
|
||||
float m_rotEndTime;
|
||||
|
||||
@@ -245,6 +245,15 @@ void CInstanceBase::SHORSE::Render()
|
||||
rkActor.Render();
|
||||
}
|
||||
|
||||
void CInstanceBase::SHORSE::ApplyRenderInterpolation(float fInterpolation)
|
||||
{
|
||||
if (!IsMounting())
|
||||
return;
|
||||
|
||||
CActorInstance& rkActor = GetActorRef();
|
||||
rkActor.ApplyRenderInterpolation(fInterpolation);
|
||||
}
|
||||
|
||||
void CInstanceBase::__AttachHorseSaddle()
|
||||
{
|
||||
if (!IsMountingHorse())
|
||||
@@ -1948,6 +1957,12 @@ void CInstanceBase::Transform()
|
||||
m_GraphicThingInstance.INSTANCEBASE_Transform();
|
||||
}
|
||||
|
||||
void CInstanceBase::ApplyRenderInterpolation(float fInterpolation)
|
||||
{
|
||||
m_kHorse.ApplyRenderInterpolation(fInterpolation);
|
||||
m_GraphicThingInstance.ApplyRenderInterpolation(fInterpolation);
|
||||
}
|
||||
|
||||
|
||||
void CInstanceBase::Deform()
|
||||
{
|
||||
|
||||
@@ -472,6 +472,7 @@ class CInstanceBase
|
||||
bool UpdateDeleting();
|
||||
|
||||
void Transform();
|
||||
void ApplyRenderInterpolation(float fInterpolation);
|
||||
void Deform();
|
||||
void Render();
|
||||
void RenderTrace();
|
||||
@@ -847,6 +848,7 @@ class CInstanceBase
|
||||
void SetMoveSpeed(UINT uMovSpd);
|
||||
void Deform();
|
||||
void Render();
|
||||
void ApplyRenderInterpolation(float fInterpolation);
|
||||
CActorInstance& GetActorRef();
|
||||
CActorInstance* GetActorPtr();
|
||||
|
||||
@@ -1139,4 +1141,4 @@ inline int RaceToSex(int race)
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
#include "EterGrnLib/Material.h"
|
||||
|
||||
#include "resource.h"
|
||||
#include "GameType.h"
|
||||
#include "PythonApplication.h"
|
||||
#include "PythonCharacterManager.h"
|
||||
|
||||
#include "ProcessScanner.h"
|
||||
|
||||
#include <utf8.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdlib>
|
||||
|
||||
extern void GrannyCreateSharedDeformBuffer();
|
||||
extern void GrannyDestroySharedDeformBuffer();
|
||||
@@ -21,6 +24,91 @@ double g_specularSpd=0.007f;
|
||||
|
||||
CPythonApplication * CPythonApplication::ms_pInstance;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Match the legacy custom timer cadence of alternating 17 ms and 16 ms.
|
||||
constexpr double kFixedUpdateMS = 16.5;
|
||||
constexpr double kMaxCatchUpDelayMS = 250.0;
|
||||
|
||||
float ClampInterpolationFactor(float fInterpolation)
|
||||
{
|
||||
return std::max(0.0f, std::min(1.0f, fInterpolation));
|
||||
}
|
||||
|
||||
D3DXVECTOR3 LerpVector3(const D3DXVECTOR3& c_rv3Begin, const D3DXVECTOR3& c_rv3End, float fInterpolation)
|
||||
{
|
||||
return D3DXVECTOR3(
|
||||
c_rv3Begin.x + (c_rv3End.x - c_rv3Begin.x) * fInterpolation,
|
||||
c_rv3Begin.y + (c_rv3End.y - c_rv3Begin.y) * fInterpolation,
|
||||
c_rv3Begin.z + (c_rv3End.z - c_rv3Begin.z) * fInterpolation);
|
||||
}
|
||||
|
||||
bool IsRenderTelemetryEnabledFromEnvironment()
|
||||
{
|
||||
const char* c_szValue = std::getenv("M2_RENDER_TELEMETRY");
|
||||
if (!c_szValue || !*c_szValue)
|
||||
return false;
|
||||
|
||||
if (0 == _stricmp(c_szValue, "1") || 0 == _stricmp(c_szValue, "true") || 0 == _stricmp(c_szValue, "yes") || 0 == _stricmp(c_szValue, "on"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryReadEnvironmentInt(const char* c_szName, int* piValue)
|
||||
{
|
||||
if (!piValue)
|
||||
return false;
|
||||
|
||||
const char* c_szValue = std::getenv(c_szName);
|
||||
if (!c_szValue || !*c_szValue)
|
||||
return false;
|
||||
|
||||
char* pEnd = nullptr;
|
||||
const long lValue = std::strtol(c_szValue, &pEnd, 10);
|
||||
if (pEnd == c_szValue || (pEnd && *pEnd))
|
||||
return false;
|
||||
|
||||
*piValue = static_cast<int>(lValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResetRenderTelemetryTrace()
|
||||
{
|
||||
FILE* fp = nullptr;
|
||||
if (fopen_s(&fp, "log/render_telemetry.txt", "w") != 0 || !fp)
|
||||
return;
|
||||
|
||||
fprintf(fp, "render telemetry\n");
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void AppendRenderTelemetryTrace(const char* c_szFormat, ...)
|
||||
{
|
||||
FILE* fp = nullptr;
|
||||
if (fopen_s(&fp, "log/render_telemetry.txt", "a") != 0 || !fp)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, c_szFormat);
|
||||
vfprintf(fp, c_szFormat, args);
|
||||
va_end(args);
|
||||
fputc('\n', fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void FormatRenderTargetFPSLabel(unsigned int iFPS, char* c_szBuffer, size_t uBufferSize)
|
||||
{
|
||||
if (!c_szBuffer || 0 == uBufferSize)
|
||||
return;
|
||||
|
||||
if (iFPS > 0)
|
||||
_snprintf_s(c_szBuffer, uBufferSize, _TRUNCATE, "%u", iFPS);
|
||||
else
|
||||
_snprintf_s(c_szBuffer, uBufferSize, _TRUNCATE, "MAX");
|
||||
}
|
||||
}
|
||||
|
||||
float c_fDefaultCameraRotateSpeed = 1.5f;
|
||||
float c_fDefaultCameraPitchSpeed = 1.5f;
|
||||
float c_fDefaultCameraZoomSpeed = 0.05f;
|
||||
@@ -35,9 +123,28 @@ m_poMouseHandler(NULL),
|
||||
m_dwUpdateFPS(0),
|
||||
m_dwRenderFPS(0),
|
||||
m_fAveRenderTime(0.0f),
|
||||
m_bRenderTelemetryEnabled(false),
|
||||
m_bRenderTelemetryHudVisible(false),
|
||||
m_dwRenderTelemetryIntervalMS(1000),
|
||||
m_dwRenderTelemetryWindowStartMS(0),
|
||||
m_dwRenderTelemetryLoopCount(0),
|
||||
m_dwRenderTelemetryUpdateCount(0),
|
||||
m_dwRenderTelemetryRenderCount(0),
|
||||
m_dwRenderTelemetryBlockedRenderCount(0),
|
||||
m_dwRenderTelemetryLastPresentTime(0),
|
||||
m_dwRenderTelemetryPresentGapSamples(0),
|
||||
m_fRenderTelemetryUpdateTimeSumMS(0.0),
|
||||
m_fRenderTelemetryRenderTimeSumMS(0.0),
|
||||
m_fRenderTelemetrySleepTimeSumMS(0.0),
|
||||
m_fRenderTelemetryInterpolationSum(0.0),
|
||||
m_fRenderTelemetryPresentGapSumMS(0.0),
|
||||
m_dwCurRenderTime(0),
|
||||
m_dwCurUpdateTime(0),
|
||||
m_dwLoad(0),
|
||||
m_dwFaceCount(0),
|
||||
m_fGlobalTime(0.0f),
|
||||
m_fGlobalElapsedTime(0.0f),
|
||||
m_fRenderInterpolationFactor(0.0f),
|
||||
m_dwLButtonDownTime(0),
|
||||
m_dwLastIdleTime(0),
|
||||
m_IsMovingMainWindow(false)
|
||||
@@ -54,12 +161,15 @@ m_IsMovingMainWindow(false)
|
||||
m_isWindowFullScreenEnable = FALSE;
|
||||
|
||||
m_v3CenterPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
|
||||
m_v3LastCenterPosition = m_v3CenterPosition;
|
||||
m_dwStartLocalTime = ELTimer_GetMSec();
|
||||
m_tServerTime = 0;
|
||||
m_tLocalStartTime = 0;
|
||||
|
||||
m_iPort = 0;
|
||||
m_iFPS = 60;
|
||||
m_iFPS = std::max(0, m_pySystem.GetRenderFPS());
|
||||
m_bRenderTelemetryHudVisible = m_pySystem.IsShowPerformanceHUD();
|
||||
InitializeRenderRuntimeOverrides();
|
||||
|
||||
m_isActivateWnd = false;
|
||||
m_isMinimizedWnd = true;
|
||||
@@ -168,6 +278,7 @@ void CPythonApplication::RenderGame()
|
||||
float fFarClip = m_pyBackground.GetFarClip();
|
||||
|
||||
m_pyGraphic.SetPerspective(30.0f, fAspect, 100.0, fFarClip);
|
||||
ApplyRenderInterpolation();
|
||||
|
||||
CCullingManager::Instance().Process();
|
||||
|
||||
@@ -256,10 +367,137 @@ void CPythonApplication::UpdateGame()
|
||||
SetCenterPosition(kPPosMainActor.x, kPPosMainActor.y, kPPosMainActor.z);
|
||||
}
|
||||
|
||||
void CPythonApplication::InitializeRenderRuntimeOverrides()
|
||||
{
|
||||
m_bRenderTelemetryEnabled = IsRenderTelemetryEnabledFromEnvironment();
|
||||
|
||||
int iIntervalMS = 0;
|
||||
if (TryReadEnvironmentInt("M2_RENDER_TELEMETRY_INTERVAL_MS", &iIntervalMS) && iIntervalMS > 0)
|
||||
m_dwRenderTelemetryIntervalMS = static_cast<DWORD>(std::min(iIntervalMS, 60000));
|
||||
|
||||
if (m_bRenderTelemetryEnabled)
|
||||
{
|
||||
ResetRenderTelemetryTrace();
|
||||
AppendRenderTelemetryTrace("enabled interval_ms=%lu", static_cast<unsigned long>(m_dwRenderTelemetryIntervalMS));
|
||||
}
|
||||
|
||||
int iRenderFPS = 0;
|
||||
if (TryReadEnvironmentInt("M2_RENDER_FPS", &iRenderFPS))
|
||||
{
|
||||
m_iFPS = std::max(0, iRenderFPS);
|
||||
if (m_bRenderTelemetryEnabled)
|
||||
AppendRenderTelemetryTrace("env_override target_fps=%u", m_iFPS);
|
||||
}
|
||||
|
||||
char szTargetFPS[16];
|
||||
FormatRenderTargetFPSLabel(m_iFPS, szTargetFPS, sizeof(szTargetFPS));
|
||||
m_stRenderTelemetrySummary = "Render telemetry\nTarget FPS: ";
|
||||
m_stRenderTelemetrySummary += szTargetFPS;
|
||||
m_stRenderTelemetrySummary += "\nCollecting frame pacing...";
|
||||
|
||||
if (IsRenderTelemetrySamplingEnabled())
|
||||
ResetRenderTelemetryWindow(ELTimer_GetMSec());
|
||||
}
|
||||
|
||||
void CPythonApplication::ResetRenderTelemetryWindow(DWORD dwNow)
|
||||
{
|
||||
m_dwRenderTelemetryWindowStartMS = dwNow;
|
||||
m_dwRenderTelemetryLoopCount = 0;
|
||||
m_dwRenderTelemetryUpdateCount = 0;
|
||||
m_dwRenderTelemetryRenderCount = 0;
|
||||
m_dwRenderTelemetryBlockedRenderCount = 0;
|
||||
m_dwRenderTelemetryPresentGapSamples = 0;
|
||||
m_fRenderTelemetryUpdateTimeSumMS = 0.0;
|
||||
m_fRenderTelemetryRenderTimeSumMS = 0.0;
|
||||
m_fRenderTelemetrySleepTimeSumMS = 0.0;
|
||||
m_fRenderTelemetryInterpolationSum = 0.0;
|
||||
m_fRenderTelemetryPresentGapSumMS = 0.0;
|
||||
}
|
||||
|
||||
void CPythonApplication::FlushRenderTelemetryWindow(DWORD dwNow)
|
||||
{
|
||||
if (!IsRenderTelemetrySamplingEnabled() || !m_dwRenderTelemetryWindowStartMS)
|
||||
return;
|
||||
|
||||
const DWORD dwWindowMS = std::max<DWORD>(1, dwNow - m_dwRenderTelemetryWindowStartMS);
|
||||
const double fWindowMS = static_cast<double>(dwWindowMS);
|
||||
const double fUpdateFPS = static_cast<double>(m_dwRenderTelemetryUpdateCount) * 1000.0 / fWindowMS;
|
||||
const double fRenderFPS = static_cast<double>(m_dwRenderTelemetryRenderCount) * 1000.0 / fWindowMS;
|
||||
const double fAvgUpdateMS = m_dwRenderTelemetryUpdateCount ? (m_fRenderTelemetryUpdateTimeSumMS / static_cast<double>(m_dwRenderTelemetryUpdateCount)) : 0.0;
|
||||
const double fAvgRenderMS = m_dwRenderTelemetryRenderCount ? (m_fRenderTelemetryRenderTimeSumMS / static_cast<double>(m_dwRenderTelemetryRenderCount)) : 0.0;
|
||||
const double fAvgSleepMS = m_dwRenderTelemetryLoopCount ? (m_fRenderTelemetrySleepTimeSumMS / static_cast<double>(m_dwRenderTelemetryLoopCount)) : 0.0;
|
||||
const double fAvgInterpolation = m_dwRenderTelemetryRenderCount ? (m_fRenderTelemetryInterpolationSum / static_cast<double>(m_dwRenderTelemetryRenderCount)) : 0.0;
|
||||
const double fAvgPresentGapMS = m_dwRenderTelemetryPresentGapSamples ? (m_fRenderTelemetryPresentGapSumMS / static_cast<double>(m_dwRenderTelemetryPresentGapSamples)) : 0.0;
|
||||
const DWORD dwElapsedMS = dwNow - m_dwStartLocalTime;
|
||||
char szTargetFPS[16];
|
||||
char szSummary[256];
|
||||
|
||||
FormatRenderTargetFPSLabel(m_iFPS, szTargetFPS, sizeof(szTargetFPS));
|
||||
_snprintf_s(
|
||||
szSummary,
|
||||
sizeof(szSummary),
|
||||
_TRUNCATE,
|
||||
"Render %.1f Update %.1f Target %s\nPresent %.1fms Sleep %.1fms CPU %.1f/%.1fms",
|
||||
fRenderFPS,
|
||||
fUpdateFPS,
|
||||
szTargetFPS,
|
||||
fAvgPresentGapMS,
|
||||
fAvgSleepMS,
|
||||
fAvgUpdateMS,
|
||||
fAvgRenderMS);
|
||||
m_stRenderTelemetrySummary = szSummary;
|
||||
|
||||
if (m_bRenderTelemetryEnabled)
|
||||
{
|
||||
AppendRenderTelemetryTrace(
|
||||
"elapsed_ms=%lu window_ms=%lu target_fps=%u update_fps=%.2f render_fps=%.2f avg_update_ms=%.2f avg_render_ms=%.2f avg_sleep_ms=%.2f avg_present_gap_ms=%.2f avg_interp=%.3f loops=%lu updates=%lu renders=%lu blocked=%lu cur_update_ms=%lu cur_render_ms=%lu",
|
||||
static_cast<unsigned long>(dwElapsedMS),
|
||||
static_cast<unsigned long>(dwWindowMS),
|
||||
m_iFPS,
|
||||
fUpdateFPS,
|
||||
fRenderFPS,
|
||||
fAvgUpdateMS,
|
||||
fAvgRenderMS,
|
||||
fAvgSleepMS,
|
||||
fAvgPresentGapMS,
|
||||
fAvgInterpolation,
|
||||
static_cast<unsigned long>(m_dwRenderTelemetryLoopCount),
|
||||
static_cast<unsigned long>(m_dwRenderTelemetryUpdateCount),
|
||||
static_cast<unsigned long>(m_dwRenderTelemetryRenderCount),
|
||||
static_cast<unsigned long>(m_dwRenderTelemetryBlockedRenderCount),
|
||||
static_cast<unsigned long>(m_dwCurUpdateTime),
|
||||
static_cast<unsigned long>(m_dwCurRenderTime));
|
||||
}
|
||||
|
||||
ResetRenderTelemetryWindow(dwNow);
|
||||
}
|
||||
|
||||
bool CPythonApplication::IsRenderTelemetrySamplingEnabled() const
|
||||
{
|
||||
return m_bRenderTelemetryEnabled || m_bRenderTelemetryHudVisible;
|
||||
}
|
||||
|
||||
void CPythonApplication::RenderPerformanceHUD()
|
||||
{
|
||||
if (!m_bRenderTelemetryHudVisible)
|
||||
return;
|
||||
|
||||
CGraphicText* pkDefaultFont = static_cast<CGraphicText*>(DefaultFont_GetResource());
|
||||
if (!pkDefaultFont)
|
||||
return;
|
||||
|
||||
m_kRenderTelemetryTextLine.SetTextPointer(pkDefaultFont);
|
||||
m_kRenderTelemetryTextLine.SetOutline(true);
|
||||
m_kRenderTelemetryTextLine.SetMultiLine(true);
|
||||
m_kRenderTelemetryTextLine.SetColor(1.0f, 1.0f, 1.0f);
|
||||
m_kRenderTelemetryTextLine.SetPosition(12.0f, 12.0f);
|
||||
m_kRenderTelemetryTextLine.SetValueString(m_stRenderTelemetrySummary);
|
||||
m_kRenderTelemetryTextLine.Update();
|
||||
m_kRenderTelemetryTextLine.Render();
|
||||
}
|
||||
|
||||
bool CPythonApplication::Process()
|
||||
{
|
||||
ELTimer_SetFrameMSec();
|
||||
|
||||
// m_Profiler.Clear();
|
||||
DWORD dwStart = ELTimer_GetMSec();
|
||||
|
||||
@@ -269,6 +507,18 @@ bool CPythonApplication::Process()
|
||||
static DWORD s_dwFaceCount = 0;
|
||||
static UINT s_uiLoad = 0;
|
||||
static DWORD s_dwCheckTime = ELTimer_GetMSec();
|
||||
static double s_fNextUpdateTime = static_cast<double>(ELTimer_GetMSec());
|
||||
static double s_fNextRenderTime = static_cast<double>(ELTimer_GetMSec());
|
||||
static double s_fFixedFrameTime = static_cast<double>(ELTimer_GetMSec());
|
||||
|
||||
DWORD dwCurrentTime = ELTimer_GetMSec();
|
||||
const double fCurrentTime = static_cast<double>(dwCurrentTime);
|
||||
const bool bSampleRenderTelemetry = IsRenderTelemetrySamplingEnabled();
|
||||
if (bSampleRenderTelemetry && !m_dwRenderTelemetryWindowStartMS)
|
||||
ResetRenderTelemetryWindow(dwCurrentTime);
|
||||
|
||||
if (bSampleRenderTelemetry)
|
||||
++m_dwRenderTelemetryLoopCount;
|
||||
|
||||
if (ELTimer_GetMSec() - s_dwCheckTime > 1000) [[unlikely]] {
|
||||
m_dwUpdateFPS = s_dwUpdateFrameCount;
|
||||
@@ -282,278 +532,314 @@ bool CPythonApplication::Process()
|
||||
s_uiLoad = s_dwFaceCount = s_dwUpdateFrameCount = s_dwRenderFrameCount = 0;
|
||||
}
|
||||
|
||||
// Update Time
|
||||
static BOOL s_bFrameSkip = false;
|
||||
static UINT s_uiNextFrameTime = ELTimer_GetMSec();
|
||||
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime1=ELTimer_GetMSec();
|
||||
#endif
|
||||
CTimer& rkTimer=CTimer::Instance();
|
||||
rkTimer.Advance();
|
||||
|
||||
m_fGlobalTime = rkTimer.GetCurrentSecond();
|
||||
m_fGlobalElapsedTime = rkTimer.GetElapsedSecond();
|
||||
|
||||
UINT uiFrameTime = rkTimer.GetElapsedMilliecond();
|
||||
s_uiNextFrameTime += uiFrameTime; //17 - 1ÃÊ´ç 60fps±âÁØ.
|
||||
|
||||
DWORD updatestart = ELTimer_GetMSec();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime2=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Network I/O
|
||||
m_pyNetworkStream.Process();
|
||||
//m_pyNetworkDatagram.Process();
|
||||
|
||||
m_kGuildMarkUploader.Process();
|
||||
|
||||
m_kGuildMarkDownloader.Process();
|
||||
m_kAccountConnector.Process();
|
||||
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime3=ELTimer_GetMSec();
|
||||
#endif
|
||||
//////////////////////
|
||||
// Input Process
|
||||
// Keyboard
|
||||
UpdateKeyboard();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime4=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Mouse
|
||||
POINT Point;
|
||||
if (GetCursorPos(&Point)) [[likely]] {
|
||||
ScreenToClient(m_hWnd, &Point);
|
||||
OnMouseMove(Point.x, Point.y);
|
||||
}
|
||||
//////////////////////
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime5=ELTimer_GetMSec();
|
||||
#endif
|
||||
//!@# Alt+Tab Áß SetTransfor ¿¡¼ ƨ±è Çö»ó ÇØ°áÀ» À§ÇØ - [levites]
|
||||
//if (m_isActivateWnd)
|
||||
__UpdateCamera();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime6=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Update Game Playing
|
||||
CResourceManager::Instance().Update();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime7=ELTimer_GetMSec();
|
||||
#endif
|
||||
OnCameraUpdate();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime8=ELTimer_GetMSec();
|
||||
#endif
|
||||
OnMouseUpdate();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime9=ELTimer_GetMSec();
|
||||
#endif
|
||||
OnUIUpdate();
|
||||
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime10=ELTimer_GetMSec();
|
||||
|
||||
if (dwUpdateTime10-dwUpdateTime1>10)
|
||||
{
|
||||
static FILE* fp=fopen("perf_app_update.txt", "w");
|
||||
|
||||
fprintf(fp, "AU.Total %d (Time %d)\n", dwUpdateTime9-dwUpdateTime1, ELTimer_GetMSec());
|
||||
fprintf(fp, "AU.TU %d\n", dwUpdateTime2-dwUpdateTime1);
|
||||
fprintf(fp, "AU.NU %d\n", dwUpdateTime3-dwUpdateTime2);
|
||||
fprintf(fp, "AU.KU %d\n", dwUpdateTime4-dwUpdateTime3);
|
||||
fprintf(fp, "AU.MP %d\n", dwUpdateTime5-dwUpdateTime4);
|
||||
fprintf(fp, "AU.CP %d\n", dwUpdateTime6-dwUpdateTime5);
|
||||
fprintf(fp, "AU.RU %d\n", dwUpdateTime7-dwUpdateTime6);
|
||||
fprintf(fp, "AU.CU %d\n", dwUpdateTime8-dwUpdateTime7);
|
||||
fprintf(fp, "AU.MU %d\n", dwUpdateTime9-dwUpdateTime8);
|
||||
fprintf(fp, "AU.UU %d\n", dwUpdateTime10-dwUpdateTime9);
|
||||
fprintf(fp, "----------------------------------\n");
|
||||
fflush(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
//UpdateÇϴµ¥ °É¸°½Ã°£.delta°ª
|
||||
m_dwCurUpdateTime = ELTimer_GetMSec() - updatestart;
|
||||
|
||||
DWORD dwCurrentTime = ELTimer_GetMSec();
|
||||
BOOL bCurrentLateUpdate = FALSE;
|
||||
|
||||
s_bFrameSkip = false;
|
||||
|
||||
if (dwCurrentTime > s_uiNextFrameTime)
|
||||
if (fCurrentTime - s_fNextUpdateTime > kMaxCatchUpDelayMS)
|
||||
{
|
||||
int dt = dwCurrentTime - s_uiNextFrameTime;
|
||||
int nAdjustTime = ((float)dt / (float)uiFrameTime) * uiFrameTime;
|
||||
s_fNextUpdateTime = fCurrentTime;
|
||||
s_fFixedFrameTime = fCurrentTime;
|
||||
}
|
||||
|
||||
if ( dt >= 500 )
|
||||
if (fCurrentTime - s_fNextRenderTime > kMaxCatchUpDelayMS)
|
||||
s_fNextRenderTime = fCurrentTime;
|
||||
|
||||
int iUpdateCount = 0;
|
||||
while (fCurrentTime + 0.0001 >= s_fNextUpdateTime)
|
||||
{
|
||||
if (!m_isFrameSkipDisable && iUpdateCount >= 5)
|
||||
{
|
||||
s_uiNextFrameTime += nAdjustTime;
|
||||
printf("FrameSkip º¸Á¤ %d\n",nAdjustTime);
|
||||
CTimer::Instance().Adjust(nAdjustTime);
|
||||
s_fNextUpdateTime = fCurrentTime;
|
||||
s_fFixedFrameTime = fCurrentTime;
|
||||
break;
|
||||
}
|
||||
|
||||
s_bFrameSkip = true;
|
||||
bCurrentLateUpdate = TRUE;
|
||||
}
|
||||
++iUpdateCount;
|
||||
s_fNextUpdateTime += kFixedUpdateMS;
|
||||
s_fFixedFrameTime += kFixedUpdateMS;
|
||||
ELTimer_SetFrameMSecValue(static_cast<DWORD>(s_fFixedFrameTime));
|
||||
m_v3LastCenterPosition = m_v3CenterPosition;
|
||||
|
||||
//s_bFrameSkip = false;
|
||||
|
||||
//if (dwCurrentTime > s_uiNextFrameTime)
|
||||
//{
|
||||
// int dt = dwCurrentTime - s_uiNextFrameTime;
|
||||
|
||||
// //³Ê¹« ´Ê¾úÀ» °æ¿ì µû¶óÀâ´Â´Ù.
|
||||
// //±×¸®°í m_dwCurUpdateTime´Â deltaÀε¥ delta¶û absolute timeÀ̶û ºñ±³ÇÏ¸é ¾î¼Àڴ°Ü?
|
||||
// //if (dt >= 500 || m_dwCurUpdateTime > s_uiNextFrameTime)
|
||||
|
||||
// //±âÁ¸ÄÚµå´ë·Î Çϸé 0.5ÃÊ ÀÌÇÏ Â÷À̳ »óÅ·Πupdate°¡ Áö¼ÓµÇ¸é °è¼Ó rendering frame skip¹ß»ý
|
||||
// if (dt >= 500 || m_dwCurUpdateTime > s_uiNextFrameTime)
|
||||
// {
|
||||
// s_uiNextFrameTime += dt / uiFrameTime * uiFrameTime;
|
||||
// printf("FrameSkip º¸Á¤ %d\n", dt / uiFrameTime * uiFrameTime);
|
||||
// CTimer::Instance().Adjust((dt / uiFrameTime) * uiFrameTime);
|
||||
// s_bFrameSkip = true;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (m_isFrameSkipDisable)
|
||||
s_bFrameSkip = false;
|
||||
|
||||
#ifdef __VTUNE__
|
||||
s_bFrameSkip = false;
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime1=ELTimer_GetMSec();
|
||||
#endif
|
||||
if (!s_bFrameSkip)
|
||||
{
|
||||
// static double pos=0.0f;
|
||||
// CGrannyMaterial::TranslateSpecularMatrix(fabs(sin(pos)*0.005), fabs(cos(pos)*0.005), 0.0f);
|
||||
// pos+=0.01f;
|
||||
CTimer& rkTimer=CTimer::Instance();
|
||||
rkTimer.Advance();
|
||||
|
||||
m_fGlobalTime = rkTimer.GetCurrentSecond();
|
||||
m_fGlobalElapsedTime = rkTimer.GetElapsedSecond();
|
||||
|
||||
DWORD updatestart = ELTimer_GetMSec();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime2=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Network I/O
|
||||
m_pyNetworkStream.Process();
|
||||
//m_pyNetworkDatagram.Process();
|
||||
|
||||
m_kGuildMarkUploader.Process();
|
||||
|
||||
m_kGuildMarkDownloader.Process();
|
||||
m_kAccountConnector.Process();
|
||||
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime3=ELTimer_GetMSec();
|
||||
#endif
|
||||
//////////////////////
|
||||
// Input Process
|
||||
// Keyboard
|
||||
UpdateKeyboard();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime4=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Mouse
|
||||
POINT Point;
|
||||
if (GetCursorPos(&Point)) [[likely]] {
|
||||
ScreenToClient(m_hWnd, &Point);
|
||||
OnMouseMove(Point.x, Point.y);
|
||||
}
|
||||
//////////////////////
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime5=ELTimer_GetMSec();
|
||||
#endif
|
||||
//!@# Alt+Tab Áß SetTransfor ¿¡¼ ƨ±è Çö»ó ÇØ°áÀ» À§ÇØ - [levites]
|
||||
//if (m_isActivateWnd)
|
||||
__UpdateCamera();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime6=ELTimer_GetMSec();
|
||||
#endif
|
||||
// Update Game Playing
|
||||
CResourceManager::Instance().Update();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime7=ELTimer_GetMSec();
|
||||
#endif
|
||||
OnCameraUpdate();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime8=ELTimer_GetMSec();
|
||||
#endif
|
||||
OnMouseUpdate();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime9=ELTimer_GetMSec();
|
||||
#endif
|
||||
CGrannyMaterial::TranslateSpecularMatrix(g_specularSpd, g_specularSpd, 0.0f);
|
||||
OnUIUpdate();
|
||||
|
||||
DWORD dwRenderStartTime = ELTimer_GetMSec();
|
||||
#ifdef __PERFORMANCE_CHECK__
|
||||
DWORD dwUpdateTime10=ELTimer_GetMSec();
|
||||
|
||||
bool canRender = true;
|
||||
|
||||
if (m_isMinimizedWnd) [[unlikely]] {
|
||||
canRender = false;
|
||||
}
|
||||
else [[likely]] {
|
||||
if (m_pyGraphic.IsLostDevice()) [[unlikely]] {
|
||||
CPythonBackground& rkBG = CPythonBackground::Instance();
|
||||
rkBG.ReleaseCharacterShadowTexture();
|
||||
|
||||
if (m_pyGraphic.RestoreDevice())
|
||||
rkBG.CreateCharacterShadowTexture();
|
||||
else
|
||||
canRender = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canRender) [[likely]]
|
||||
if (dwUpdateTime10-dwUpdateTime1>10)
|
||||
{
|
||||
// RestoreLostDevice
|
||||
CCullingManager::Instance().Update();
|
||||
if (m_pyGraphic.Begin()) [[likely]] {
|
||||
static FILE* fp=fopen("perf_app_update.txt", "w");
|
||||
|
||||
m_pyGraphic.ClearDepthBuffer();
|
||||
fprintf(fp, "AU.Total %d (Time %d)\n", dwUpdateTime9-dwUpdateTime1, ELTimer_GetMSec());
|
||||
fprintf(fp, "AU.TU %d\n", dwUpdateTime2-dwUpdateTime1);
|
||||
fprintf(fp, "AU.NU %d\n", dwUpdateTime3-dwUpdateTime2);
|
||||
fprintf(fp, "AU.KU %d\n", dwUpdateTime4-dwUpdateTime3);
|
||||
fprintf(fp, "AU.MP %d\n", dwUpdateTime5-dwUpdateTime4);
|
||||
fprintf(fp, "AU.CP %d\n", dwUpdateTime6-dwUpdateTime5);
|
||||
fprintf(fp, "AU.RU %d\n", dwUpdateTime7-dwUpdateTime6);
|
||||
fprintf(fp, "AU.CU %d\n", dwUpdateTime8-dwUpdateTime7);
|
||||
fprintf(fp, "AU.MU %d\n", dwUpdateTime9-dwUpdateTime8);
|
||||
fprintf(fp, "AU.UU %d\n", dwUpdateTime10-dwUpdateTime9);
|
||||
fprintf(fp, "----------------------------------\n");
|
||||
fflush(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
//UpdateÇϴµ¥ °É¸°½Ã°£.delta°ª
|
||||
m_dwCurUpdateTime = ELTimer_GetMSec() - updatestart;
|
||||
if (bSampleRenderTelemetry)
|
||||
{
|
||||
++m_dwRenderTelemetryUpdateCount;
|
||||
m_fRenderTelemetryUpdateTimeSumMS += static_cast<double>(m_dwCurUpdateTime);
|
||||
}
|
||||
++s_dwUpdateFrameCount;
|
||||
}
|
||||
|
||||
const double fPreviousUpdateTime = s_fNextUpdateTime - kFixedUpdateMS;
|
||||
m_fRenderInterpolationFactor = ClampInterpolationFactor(static_cast<float>((fCurrentTime - fPreviousUpdateTime) / kFixedUpdateMS));
|
||||
|
||||
DWORD dwRenderStartTime = ELTimer_GetMSec();
|
||||
bool canRender = true;
|
||||
bool didRender = false;
|
||||
|
||||
if (m_isMinimizedWnd) [[unlikely]] {
|
||||
canRender = false;
|
||||
}
|
||||
else [[likely]] {
|
||||
if (m_pyGraphic.IsLostDevice()) [[unlikely]] {
|
||||
CPythonBackground& rkBG = CPythonBackground::Instance();
|
||||
rkBG.ReleaseCharacterShadowTexture();
|
||||
|
||||
if (m_pyGraphic.RestoreDevice())
|
||||
rkBG.CreateCharacterShadowTexture();
|
||||
else
|
||||
canRender = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canRender) [[likely]]
|
||||
{
|
||||
// RestoreLostDevice
|
||||
CCullingManager::Instance().Update();
|
||||
if (m_pyGraphic.Begin()) [[likely]] {
|
||||
|
||||
m_pyGraphic.ClearDepthBuffer();
|
||||
|
||||
#ifdef _DEBUG
|
||||
m_pyGraphic.SetClearColor(0.3f, 0.3f, 0.3f);
|
||||
m_pyGraphic.Clear();
|
||||
m_pyGraphic.SetClearColor(0.3f, 0.3f, 0.3f);
|
||||
m_pyGraphic.Clear();
|
||||
#endif
|
||||
|
||||
/////////////////////
|
||||
// Interface
|
||||
m_pyGraphic.SetInterfaceRenderState();
|
||||
/////////////////////
|
||||
// Interface
|
||||
m_pyGraphic.SetInterfaceRenderState();
|
||||
|
||||
OnUIRender();
|
||||
OnMouseRender();
|
||||
/////////////////////
|
||||
OnUIRender();
|
||||
RenderPerformanceHUD();
|
||||
OnMouseRender();
|
||||
/////////////////////
|
||||
|
||||
m_pyGraphic.End();
|
||||
m_pyGraphic.End();
|
||||
m_pyGraphic.Show();
|
||||
|
||||
//DWORD t1 = ELTimer_GetMSec();
|
||||
m_pyGraphic.Show();
|
||||
//DWORD t2 = ELTimer_GetMSec();
|
||||
DWORD dwRenderEndTime = ELTimer_GetMSec();
|
||||
didRender = true;
|
||||
|
||||
DWORD dwRenderEndTime = ELTimer_GetMSec();
|
||||
static DWORD s_dwRenderCheckTime = dwRenderEndTime;
|
||||
static DWORD s_dwRenderRangeTime = 0;
|
||||
static DWORD s_dwRenderRangeFrame = 0;
|
||||
|
||||
static DWORD s_dwRenderCheckTime = dwRenderEndTime;
|
||||
static DWORD s_dwRenderRangeTime = 0;
|
||||
static DWORD s_dwRenderRangeFrame = 0;
|
||||
m_dwCurRenderTime = dwRenderEndTime - dwRenderStartTime;
|
||||
s_dwRenderRangeTime += m_dwCurRenderTime;
|
||||
++s_dwRenderRangeFrame;
|
||||
|
||||
m_dwCurRenderTime = dwRenderEndTime - dwRenderStartTime;
|
||||
s_dwRenderRangeTime += m_dwCurRenderTime;
|
||||
++s_dwRenderRangeFrame;
|
||||
if (dwRenderEndTime-s_dwRenderCheckTime>1000) [[unlikely]] {
|
||||
m_fAveRenderTime=float(double(s_dwRenderRangeTime)/double(s_dwRenderRangeFrame));
|
||||
|
||||
if (dwRenderEndTime-s_dwRenderCheckTime>1000) [[unlikely]] {
|
||||
m_fAveRenderTime=float(double(s_dwRenderRangeTime)/double(s_dwRenderRangeFrame));
|
||||
s_dwRenderCheckTime=ELTimer_GetMSec();
|
||||
s_dwRenderRangeTime=0;
|
||||
s_dwRenderRangeFrame=0;
|
||||
}
|
||||
|
||||
s_dwRenderCheckTime=ELTimer_GetMSec();
|
||||
s_dwRenderRangeTime=0;
|
||||
s_dwRenderRangeFrame=0;
|
||||
}
|
||||
DWORD dwCurFaceCount=m_pyGraphic.GetFaceCount();
|
||||
m_pyGraphic.ResetFaceCount();
|
||||
s_dwFaceCount += dwCurFaceCount;
|
||||
|
||||
DWORD dwCurFaceCount=m_pyGraphic.GetFaceCount();
|
||||
m_pyGraphic.ResetFaceCount();
|
||||
s_dwFaceCount += dwCurFaceCount;
|
||||
if (dwCurFaceCount > 5000)
|
||||
{
|
||||
m_dwFaceAccCount += dwCurFaceCount;
|
||||
m_dwFaceAccTime += m_dwCurRenderTime;
|
||||
|
||||
if (dwCurFaceCount > 5000)
|
||||
m_fFaceSpd=(m_dwFaceAccCount/m_dwFaceAccTime);
|
||||
|
||||
// °Å¸® ÀÚµ¿ Á¶Àý
|
||||
if (-1 == m_iForceSightRange)
|
||||
{
|
||||
m_dwFaceAccCount += dwCurFaceCount;
|
||||
m_dwFaceAccTime += m_dwCurRenderTime;
|
||||
|
||||
m_fFaceSpd=(m_dwFaceAccCount/m_dwFaceAccTime);
|
||||
|
||||
// °Å¸® ÀÚµ¿ Á¶Àý
|
||||
if (-1 == m_iForceSightRange)
|
||||
{
|
||||
static float s_fAveRenderTime = 16.0f;
|
||||
float fRatio=0.3f;
|
||||
s_fAveRenderTime=(s_fAveRenderTime*(100.0f-fRatio)+std::max(16.0f, (float)m_dwCurRenderTime)*fRatio)/100.0f;
|
||||
static float s_fAveRenderTime = 16.0f;
|
||||
float fRatio=0.3f;
|
||||
s_fAveRenderTime=(s_fAveRenderTime*(100.0f-fRatio)+std::max(16.0f, (float)m_dwCurRenderTime)*fRatio)/100.0f;
|
||||
|
||||
|
||||
float fFar=25600.0f;
|
||||
float fNear=MIN_FOG;
|
||||
double dbAvePow=double(1000.0f/s_fAveRenderTime);
|
||||
double dbMaxPow=60.0;
|
||||
float fDistance=std::max((float)(fNear+(fFar-fNear)*(dbAvePow)/dbMaxPow), fNear);
|
||||
m_pyBackground.SetViewDistanceSet(0, fDistance);
|
||||
}
|
||||
// °Å¸® °Á¦ ¼³Á¤½Ã
|
||||
else
|
||||
{
|
||||
m_pyBackground.SetViewDistanceSet(0, float(m_iForceSightRange));
|
||||
}
|
||||
float fFar=25600.0f;
|
||||
float fNear=MIN_FOG;
|
||||
double dbAvePow=double(1000.0f/s_fAveRenderTime);
|
||||
double dbMaxPow=60.0;
|
||||
float fDistance=std::max((float)(fNear+(fFar-fNear)*(dbAvePow)/dbMaxPow), fNear);
|
||||
m_pyBackground.SetViewDistanceSet(0, fDistance);
|
||||
}
|
||||
// °Å¸® °Á¦ ¼³Á¤½Ã
|
||||
else
|
||||
{
|
||||
// 10000 Æú¸®°ï º¸´Ù ÀûÀ»¶§´Â °¡Àå ¸Ö¸® º¸ÀÌ°Ô ÇÑ´Ù
|
||||
m_pyBackground.SetViewDistanceSet(0, 25600.0f);
|
||||
m_pyBackground.SetViewDistanceSet(0, float(m_iForceSightRange));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 10000 Æú¸®°ï º¸´Ù ÀûÀ»¶§´Â °¡Àå ¸Ö¸® º¸ÀÌ°Ô ÇÑ´Ù
|
||||
m_pyBackground.SetViewDistanceSet(0, 25600.0f);
|
||||
}
|
||||
|
||||
++s_dwRenderFrameCount;
|
||||
|
||||
if (bSampleRenderTelemetry)
|
||||
{
|
||||
++m_dwRenderTelemetryRenderCount;
|
||||
m_fRenderTelemetryRenderTimeSumMS += static_cast<double>(m_dwCurRenderTime);
|
||||
m_fRenderTelemetryInterpolationSum += static_cast<double>(m_fRenderInterpolationFactor);
|
||||
|
||||
if (m_dwRenderTelemetryLastPresentTime)
|
||||
{
|
||||
m_fRenderTelemetryPresentGapSumMS += static_cast<double>(dwRenderEndTime - m_dwRenderTelemetryLastPresentTime);
|
||||
++m_dwRenderTelemetryPresentGapSamples;
|
||||
}
|
||||
|
||||
++s_dwRenderFrameCount;
|
||||
m_dwRenderTelemetryLastPresentTime = dwRenderEndTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int rest = s_uiNextFrameTime - ELTimer_GetMSec();
|
||||
if (bSampleRenderTelemetry && !didRender)
|
||||
++m_dwRenderTelemetryBlockedRenderCount;
|
||||
|
||||
if (rest > 0 && !bCurrentLateUpdate )
|
||||
if (m_iFPS > 0)
|
||||
{
|
||||
s_uiLoad -= rest; // ½® ½Ã°£Àº ·Îµå¿¡¼ »«´Ù..
|
||||
Sleep(rest);
|
||||
}
|
||||
const double fRenderFrameMS = 1000.0 / static_cast<double>(m_iFPS);
|
||||
s_fNextRenderTime += fRenderFrameMS;
|
||||
|
||||
++s_dwUpdateFrameCount;
|
||||
const double fSleepMS = s_fNextRenderTime - static_cast<double>(ELTimer_GetMSec());
|
||||
if (fSleepMS > 0.999)
|
||||
{
|
||||
const UINT uiSleepMS = static_cast<UINT>(fSleepMS);
|
||||
s_uiLoad -= std::min(s_uiLoad, uiSleepMS);
|
||||
const DWORD dwSleepStart = ELTimer_GetMSec();
|
||||
Sleep(static_cast<DWORD>(fSleepMS));
|
||||
if (bSampleRenderTelemetry)
|
||||
m_fRenderTelemetrySleepTimeSumMS += static_cast<double>(ELTimer_GetMSec() - dwSleepStart);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_fNextRenderTime = static_cast<double>(ELTimer_GetMSec());
|
||||
}
|
||||
|
||||
s_uiLoad += ELTimer_GetMSec() - dwStart;
|
||||
//m_Profiler.ProfileByScreen();
|
||||
|
||||
const DWORD dwTelemetryNow = ELTimer_GetMSec();
|
||||
if (bSampleRenderTelemetry && dwTelemetryNow - m_dwRenderTelemetryWindowStartMS >= m_dwRenderTelemetryIntervalMS)
|
||||
FlushRenderTelemetryWindow(dwTelemetryNow);
|
||||
|
||||
//m_Profiler.ProfileByScreen();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPythonApplication::ApplyRenderInterpolation()
|
||||
{
|
||||
const float fInterpolation = ClampInterpolationFactor(m_fRenderInterpolationFactor);
|
||||
|
||||
m_kChrMgr.ApplyRenderInterpolation(fInterpolation);
|
||||
|
||||
if (CAMERA_MODE_NORMAL != m_iCameraMode)
|
||||
return;
|
||||
|
||||
if (0.0f != m_kCmrPos.m_fViewDir || 0.0f != m_kCmrPos.m_fCrossDir || 0.0f != m_kCmrPos.m_fUpDir)
|
||||
return;
|
||||
|
||||
CCamera* pCurrentCamera = CCameraManager::Instance().GetCurrentCamera();
|
||||
if (!pCurrentCamera)
|
||||
return;
|
||||
|
||||
const D3DXVECTOR3 v3CenterPosition = LerpVector3(m_v3LastCenterPosition, m_v3CenterPosition, fInterpolation);
|
||||
const float fDistance = pCurrentCamera->GetDistance();
|
||||
const float fPitch = pCurrentCamera->GetPitch();
|
||||
const float fRotation = pCurrentCamera->GetRoll();
|
||||
|
||||
m_pyGraphic.SetPositionCamera(
|
||||
v3CenterPosition.x,
|
||||
v3CenterPosition.y,
|
||||
v3CenterPosition.z + pCurrentCamera->GetTargetHeight(),
|
||||
fDistance,
|
||||
fPitch,
|
||||
fRotation);
|
||||
}
|
||||
|
||||
void CPythonApplication::UpdateClientRect()
|
||||
{
|
||||
RECT rcApp;
|
||||
@@ -1023,7 +1309,39 @@ float CPythonApplication::GetGlobalElapsedTime()
|
||||
|
||||
void CPythonApplication::SetFPS(int iFPS)
|
||||
{
|
||||
m_iFPS = iFPS;
|
||||
m_iFPS = std::max(0, iFPS);
|
||||
char szTargetFPS[16];
|
||||
FormatRenderTargetFPSLabel(m_iFPS, szTargetFPS, sizeof(szTargetFPS));
|
||||
m_stRenderTelemetrySummary = "Render telemetry\nTarget FPS: ";
|
||||
m_stRenderTelemetrySummary += szTargetFPS;
|
||||
m_stRenderTelemetrySummary += "\nCollecting frame pacing...";
|
||||
if (IsRenderTelemetrySamplingEnabled())
|
||||
ResetRenderTelemetryWindow(ELTimer_GetMSec());
|
||||
|
||||
if (m_bRenderTelemetryEnabled)
|
||||
{
|
||||
AppendRenderTelemetryTrace(
|
||||
"set_fps elapsed_ms=%lu target_fps=%u",
|
||||
static_cast<unsigned long>(ELTimer_GetMSec() - m_dwStartLocalTime),
|
||||
m_iFPS);
|
||||
}
|
||||
}
|
||||
|
||||
void CPythonApplication::SetPerformanceHUDVisible(bool isVisible)
|
||||
{
|
||||
m_bRenderTelemetryHudVisible = isVisible;
|
||||
if (IsRenderTelemetrySamplingEnabled())
|
||||
ResetRenderTelemetryWindow(ELTimer_GetMSec());
|
||||
else
|
||||
m_dwRenderTelemetryWindowStartMS = 0;
|
||||
|
||||
if (m_bRenderTelemetryEnabled)
|
||||
{
|
||||
AppendRenderTelemetryTrace(
|
||||
"set_hud elapsed_ms=%lu visible=%u",
|
||||
static_cast<unsigned long>(ELTimer_GetMSec() - m_dwStartLocalTime),
|
||||
m_bRenderTelemetryHudVisible ? 1u : 0u);
|
||||
}
|
||||
}
|
||||
|
||||
int CPythonApplication::GetWidth()
|
||||
@@ -1075,6 +1393,7 @@ void CPythonApplication::Destroy()
|
||||
// SphereMap
|
||||
CGrannyMaterial::DestroySphereMap();
|
||||
|
||||
m_kRenderTelemetryTextLine.Destroy();
|
||||
m_kWndMgr.Destroy();
|
||||
|
||||
CPythonSystem::Instance().SaveConfig();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "eterLib/Input.h"
|
||||
#include "eterLib/Profiler.h"
|
||||
#include "eterLib/GrpDevice.h"
|
||||
#include "EterLib/GrpTextInstance.h"
|
||||
#include "eterLib/NetDevice.h"
|
||||
#include "eterLib/GrpLightManager.h"
|
||||
#include "eterLib/GameThreadPool.h"
|
||||
@@ -42,7 +43,13 @@
|
||||
#include "AbstractApplication.h"
|
||||
#include "MovieMan.h"
|
||||
|
||||
#include <qedit.h>
|
||||
struct IGraphBuilder;
|
||||
struct IBaseFilter;
|
||||
struct ISampleGrabber;
|
||||
struct IMediaControl;
|
||||
struct IMediaEventEx;
|
||||
struct IVideoWindow;
|
||||
struct IBasicVideo;
|
||||
|
||||
class CPythonApplication : public CMSApplication, public CInputKeyboard, public IAbstractApplication
|
||||
{
|
||||
@@ -206,6 +213,7 @@ class CPythonApplication : public CMSApplication, public CInputKeyboard, public
|
||||
float GetPitch();
|
||||
|
||||
void SetFPS(int iFPS);
|
||||
void SetPerformanceHUDVisible(bool isVisible);
|
||||
void SetServerTime(time_t tTime);
|
||||
time_t GetServerTime();
|
||||
time_t GetServerTimeStamp();
|
||||
@@ -303,6 +311,12 @@ class CPythonApplication : public CMSApplication, public CInputKeyboard, public
|
||||
BOOL __IsContinuousChangeTypeCursor(int iCursorNum);
|
||||
|
||||
void __UpdateCamera();
|
||||
void ApplyRenderInterpolation();
|
||||
bool IsRenderTelemetrySamplingEnabled() const;
|
||||
void InitializeRenderRuntimeOverrides();
|
||||
void ResetRenderTelemetryWindow(DWORD dwNow);
|
||||
void FlushRenderTelemetryWindow(DWORD dwNow);
|
||||
void RenderPerformanceHUD();
|
||||
|
||||
void __SetFullScreenWindow(HWND hWnd, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP);
|
||||
void __MinimizeFullScreenWindow(HWND hWnd, DWORD dwWidth, DWORD dwHeight);
|
||||
@@ -357,9 +371,28 @@ class CPythonApplication : public CMSApplication, public CInputKeyboard, public
|
||||
|
||||
PyObject * m_poMouseHandler;
|
||||
D3DXVECTOR3 m_v3CenterPosition;
|
||||
D3DXVECTOR3 m_v3LastCenterPosition;
|
||||
CGraphicTextInstance m_kRenderTelemetryTextLine;
|
||||
std::string m_stRenderTelemetrySummary;
|
||||
|
||||
unsigned int m_iFPS;
|
||||
float m_fRenderInterpolationFactor;
|
||||
float m_fAveRenderTime;
|
||||
bool m_bRenderTelemetryEnabled;
|
||||
bool m_bRenderTelemetryHudVisible;
|
||||
DWORD m_dwRenderTelemetryIntervalMS;
|
||||
DWORD m_dwRenderTelemetryWindowStartMS;
|
||||
DWORD m_dwRenderTelemetryLoopCount;
|
||||
DWORD m_dwRenderTelemetryUpdateCount;
|
||||
DWORD m_dwRenderTelemetryRenderCount;
|
||||
DWORD m_dwRenderTelemetryBlockedRenderCount;
|
||||
DWORD m_dwRenderTelemetryLastPresentTime;
|
||||
DWORD m_dwRenderTelemetryPresentGapSamples;
|
||||
double m_fRenderTelemetryUpdateTimeSumMS;
|
||||
double m_fRenderTelemetryRenderTimeSumMS;
|
||||
double m_fRenderTelemetrySleepTimeSumMS;
|
||||
double m_fRenderTelemetryInterpolationSum;
|
||||
double m_fRenderTelemetryPresentGapSumMS;
|
||||
DWORD m_dwCurRenderTime;
|
||||
DWORD m_dwCurUpdateTime;
|
||||
DWORD m_dwLoad;
|
||||
|
||||
@@ -358,6 +358,34 @@ struct FCharacterManagerCharacterInstanceDeform
|
||||
//pInstance->Update();
|
||||
}
|
||||
};
|
||||
struct FCharacterManagerCharacterInstanceApplyRenderInterpolation
|
||||
{
|
||||
explicit FCharacterManagerCharacterInstanceApplyRenderInterpolation(float fInterpolation)
|
||||
: m_fInterpolation(fInterpolation)
|
||||
{
|
||||
}
|
||||
|
||||
inline void operator () (const std::pair<DWORD, CInstanceBase*>& cr_Pair)
|
||||
{
|
||||
cr_Pair.second->ApplyRenderInterpolation(m_fInterpolation);
|
||||
}
|
||||
|
||||
float m_fInterpolation;
|
||||
};
|
||||
struct FCharacterManagerCharacterInstanceListApplyRenderInterpolation
|
||||
{
|
||||
explicit FCharacterManagerCharacterInstanceListApplyRenderInterpolation(float fInterpolation)
|
||||
: m_fInterpolation(fInterpolation)
|
||||
{
|
||||
}
|
||||
|
||||
inline void operator () (CInstanceBase* pInstance)
|
||||
{
|
||||
pInstance->ApplyRenderInterpolation(m_fInterpolation);
|
||||
}
|
||||
|
||||
float m_fInterpolation;
|
||||
};
|
||||
struct FCharacterManagerCharacterInstanceListDeform
|
||||
{
|
||||
inline void operator () (CInstanceBase * pInstance)
|
||||
@@ -366,6 +394,12 @@ struct FCharacterManagerCharacterInstanceListDeform
|
||||
}
|
||||
};
|
||||
|
||||
void CPythonCharacterManager::ApplyRenderInterpolation(float fInterpolation)
|
||||
{
|
||||
std::for_each(m_kAliveInstMap.begin(), m_kAliveInstMap.end(), FCharacterManagerCharacterInstanceApplyRenderInterpolation(fInterpolation));
|
||||
std::for_each(m_kDeadInstList.begin(), m_kDeadInstList.end(), FCharacterManagerCharacterInstanceListApplyRenderInterpolation(fInterpolation));
|
||||
}
|
||||
|
||||
void CPythonCharacterManager::Deform()
|
||||
{
|
||||
std::for_each(m_kAliveInstMap.begin(), m_kAliveInstMap.end(), FCharacterManagerCharacterInstanceDeform());
|
||||
|
||||
@@ -57,6 +57,7 @@ class CPythonCharacterManager : public CSingleton<CPythonCharacterManager>, publ
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
void Update();
|
||||
void ApplyRenderInterpolation(float fInterpolation);
|
||||
void Deform();
|
||||
void Render();
|
||||
void RenderShadowMainInstance();
|
||||
|
||||
@@ -318,6 +318,8 @@ void CPythonSystem::SetDefaultConfig()
|
||||
m_Config.bAlwaysShowName = DEFAULT_VALUE_ALWAYS_SHOW_NAME;
|
||||
m_Config.bShowDamage = true;
|
||||
m_Config.bShowSalesText = true;
|
||||
m_Config.iRenderFPS = 60;
|
||||
m_Config.bShowPerformanceHUD = false;
|
||||
}
|
||||
|
||||
bool CPythonSystem::IsWindowed()
|
||||
@@ -365,6 +367,26 @@ void CPythonSystem::SetShowSalesTextFlag(int iFlag)
|
||||
m_Config.bShowSalesText = iFlag == 1 ? true : false;
|
||||
}
|
||||
|
||||
int CPythonSystem::GetRenderFPS()
|
||||
{
|
||||
return m_Config.iRenderFPS;
|
||||
}
|
||||
|
||||
void CPythonSystem::SetRenderFPS(int iFPS)
|
||||
{
|
||||
m_Config.iRenderFPS = std::max(0, std::min(iFPS, 500));
|
||||
}
|
||||
|
||||
bool CPythonSystem::IsShowPerformanceHUD()
|
||||
{
|
||||
return m_Config.bShowPerformanceHUD;
|
||||
}
|
||||
|
||||
void CPythonSystem::SetShowPerformanceHUDFlag(int iFlag)
|
||||
{
|
||||
m_Config.bShowPerformanceHUD = iFlag == 1 ? true : false;
|
||||
}
|
||||
|
||||
bool CPythonSystem::IsAutoTiling()
|
||||
{
|
||||
if (m_Config.bSoftwareTiling == 0)
|
||||
@@ -462,6 +484,10 @@ bool CPythonSystem::LoadConfig()
|
||||
m_Config.bShowDamage = atoi(value) == 1 ? true : false;
|
||||
else if (!stricmp(command, "SHOW_SALESTEXT"))
|
||||
m_Config.bShowSalesText = atoi(value) == 1 ? true : false;
|
||||
else if (!stricmp(command, "RENDER_FPS"))
|
||||
m_Config.iRenderFPS = std::max(0, std::min(atoi(value), 500));
|
||||
else if (!stricmp(command, "SHOW_PERFORMANCE_HUD"))
|
||||
m_Config.bShowPerformanceHUD = atoi(value) == 1 ? true : false;
|
||||
}
|
||||
|
||||
if (m_Config.bWindowed)
|
||||
@@ -552,6 +578,8 @@ bool CPythonSystem::SaveConfig()
|
||||
fprintf(fp, "USE_DEFAULT_IME %d\n", m_Config.bUseDefaultIME);
|
||||
fprintf(fp, "SOFTWARE_TILING %d\n", m_Config.bSoftwareTiling);
|
||||
fprintf(fp, "SHADOW_LEVEL %d\n", m_Config.iShadowLevel);
|
||||
fprintf(fp, "RENDER_FPS %d\n", m_Config.iRenderFPS);
|
||||
fprintf(fp, "SHOW_PERFORMANCE_HUD %d\n", m_Config.bShowPerformanceHUD);
|
||||
// MR-14: Fog update by Alaric
|
||||
fprintf(fp, "FOG_LEVEL %d\n", m_Config.iFogLevel);
|
||||
// MR-14: -- END OF -- Fog update by Alaric
|
||||
@@ -607,6 +635,9 @@ const CPythonSystem::TWindowStatus & CPythonSystem::GetWindowStatusReference(int
|
||||
|
||||
void CPythonSystem::ApplyConfig() // 이전 설정과 현재 설정을 비교해서 바뀐 설정을 적용 한다.
|
||||
{
|
||||
const bool bRenderFPSChanged = m_OldConfig.iRenderFPS != m_Config.iRenderFPS;
|
||||
const bool bPerformanceHUDChanged = m_OldConfig.bShowPerformanceHUD != m_Config.bShowPerformanceHUD;
|
||||
|
||||
if (m_OldConfig.gamma != m_Config.gamma)
|
||||
{
|
||||
float val = 1.0f;
|
||||
@@ -631,6 +662,12 @@ void CPythonSystem::ApplyConfig() // 이전 설정과 현재 설정을 비교해
|
||||
CPythonApplication::Instance().SetCursorMode(CPythonApplication::CURSOR_MODE_HARDWARE);
|
||||
}
|
||||
|
||||
if (bRenderFPSChanged)
|
||||
CPythonApplication::Instance().SetFPS(m_Config.iRenderFPS);
|
||||
|
||||
if (bPerformanceHUDChanged)
|
||||
CPythonApplication::Instance().SetPerformanceHUDVisible(m_Config.bShowPerformanceHUD);
|
||||
|
||||
m_OldConfig = m_Config;
|
||||
|
||||
ChangeSystem();
|
||||
|
||||
@@ -78,6 +78,8 @@ class CPythonSystem : public CSingleton<CPythonSystem>
|
||||
bool bAlwaysShowName;
|
||||
bool bShowDamage;
|
||||
bool bShowSalesText;
|
||||
int iRenderFPS;
|
||||
bool bShowPerformanceHUD;
|
||||
} TConfig;
|
||||
|
||||
public:
|
||||
@@ -157,6 +159,11 @@ class CPythonSystem : public CSingleton<CPythonSystem>
|
||||
void SetFogLevel(unsigned int level);
|
||||
// MR-14: -- END OF -- Fog update by Alaric
|
||||
|
||||
int GetRenderFPS();
|
||||
void SetRenderFPS(int iFPS);
|
||||
bool IsShowPerformanceHUD();
|
||||
void SetShowPerformanceHUDFlag(int iFlag);
|
||||
|
||||
protected:
|
||||
TResolution m_ResolutionList[RESOLUTION_MAX_NUM];
|
||||
int m_ResolutionCount;
|
||||
@@ -167,4 +174,4 @@ class CPythonSystem : public CSingleton<CPythonSystem>
|
||||
bool m_isInterfaceConfig;
|
||||
PyObject * m_poInterfaceHandler;
|
||||
TWindowStatus m_WindowStatus[WINDOW_MAX_NUM];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -226,6 +226,36 @@ PyObject * systemIsShowSalesText(PyObject * poSelf, PyObject * poArgs)
|
||||
return Py_BuildValue("i", CPythonSystem::Instance().IsShowSalesText());
|
||||
}
|
||||
|
||||
PyObject * systemGetRenderFPS(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
return Py_BuildValue("i", CPythonSystem::Instance().GetRenderFPS());
|
||||
}
|
||||
|
||||
PyObject * systemSetRenderFPS(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iFPS;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iFPS))
|
||||
return Py_BuildException();
|
||||
|
||||
CPythonSystem::Instance().SetRenderFPS(iFPS);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject * systemIsShowPerformanceHUD(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
return Py_BuildValue("i", CPythonSystem::Instance().IsShowPerformanceHUD());
|
||||
}
|
||||
|
||||
PyObject * systemSetShowPerformanceHUDFlag(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iFlag;
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iFlag))
|
||||
return Py_BuildException();
|
||||
|
||||
CPythonSystem::Instance().SetShowPerformanceHUDFlag(iFlag);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
PyObject * systemSetConfig(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int res_index;
|
||||
@@ -445,6 +475,11 @@ void initsystem()
|
||||
{ "SetShowSalesTextFlag", systemSetShowSalesTextFlag, METH_VARARGS },
|
||||
{ "IsShowSalesText", systemIsShowSalesText, METH_VARARGS },
|
||||
|
||||
{ "GetRenderFPS", systemGetRenderFPS, METH_VARARGS },
|
||||
{ "SetRenderFPS", systemSetRenderFPS, METH_VARARGS },
|
||||
{ "IsShowPerformanceHUD", systemIsShowPerformanceHUD, METH_VARARGS },
|
||||
{ "SetShowPerformanceHUDFlag", systemSetShowPerformanceHUDFlag, METH_VARARGS },
|
||||
|
||||
{ "GetShadowLevel", systemGetShadowLevel, METH_VARARGS },
|
||||
{ "SetShadowLevel", systemSetShadowLevel, METH_VARARGS },
|
||||
|
||||
|
||||
Reference in New Issue
Block a user