From 1471c16ed47f449349475944d4a9bdfb9f2a0988 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Fri, 23 Sep 2022 02:14:16 -0400 Subject: [PATCH 1/3] fix: use the full 32-bit unit ids and unit types in the motion predictor (cherry picked from commit 753c5ac07fa64d7743bca1f32b260c2ce3caf956) Ported from upstream PR 188 (bolrog/d2dx). --- src/d2dx/UnitMotionPredictor.cpp | 12 ++++++------ src/d2dx/UnitMotionPredictor.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/d2dx/UnitMotionPredictor.cpp b/src/d2dx/UnitMotionPredictor.cpp index d7f5ae0..2317817 100644 --- a/src/d2dx/UnitMotionPredictor.cpp +++ b/src/d2dx/UnitMotionPredictor.cpp @@ -168,8 +168,8 @@ Offset UnitMotionPredictor::GetOffset( for (int32_t i = 0; i < _unitsCount; ++i) { - if (_unitIdAndTypes.items[i].unitId == (uint16_t)unitId && - _unitIdAndTypes.items[i].unitType == (uint16_t)unitType) + if (_unitIdAndTypes.items[i].unitId == unitId && + _unitIdAndTypes.items[i].unitType == (uint32_t)unitType) { _unitMotions.items[i].lastUsedFrame = _frame; unitIndex = i; @@ -182,8 +182,8 @@ Offset UnitMotionPredictor::GetOffset( if (_unitsCount < (int32_t)_unitIdAndTypes.capacity) { unitIndex = _unitsCount++; - _unitIdAndTypes.items[unitIndex].unitId = (uint16_t)unitId; - _unitIdAndTypes.items[unitIndex].unitType = (uint16_t)unitType; + _unitIdAndTypes.items[unitIndex].unitId = unitId; + _unitIdAndTypes.items[unitIndex].unitType = (uint32_t)unitType; _unitMotions.items[unitIndex] = { }; _unitMotions.items[unitIndex].lastUsedFrame = _frame; } @@ -212,8 +212,8 @@ void UnitMotionPredictor::SetUnitScreenPos( for (int32_t unitIndex = 0; unitIndex < _unitsCount; ++unitIndex) { - if (_unitIdAndTypes.items[unitIndex].unitId == (uint16_t)unitId && - _unitIdAndTypes.items[unitIndex].unitType == (uint16_t)unitType) + if (_unitIdAndTypes.items[unitIndex].unitId == unitId && + _unitIdAndTypes.items[unitIndex].unitType == (uint32_t)unitType) { _unitScreenPositions.items[unitIndex] = { x, y }; break; diff --git a/src/d2dx/UnitMotionPredictor.h b/src/d2dx/UnitMotionPredictor.h index 54b18c0..e0ba19e 100644 --- a/src/d2dx/UnitMotionPredictor.h +++ b/src/d2dx/UnitMotionPredictor.h @@ -47,8 +47,8 @@ namespace d2dx private: struct UnitIdAndType final { - uint16_t unitType = 0; - uint16_t unitId = 0; + uint32_t unitType = 0; + uint32_t unitId = 0; }; struct UnitMotion final From 99bf75fff1fe5d03ec35beb6a60f77f0c71265b3 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 22 Nov 2022 10:09:55 -0500 Subject: [PATCH 2/3] fix: fix precision lost when calculating the frame time Started after ~4 minutes due to float precision limits, would be visible after ~18-36 hours when it would be off by 4-8ms. (cherry picked from commit d314dddb239de58dac0eaa67bb9083e2ea2863da) Ported from upstream PR 188 (bolrog/d2dx). Shim update: tests/linux/shim/UtilsStub.cpp now stubs TimeEnd/TimeToMs. Co-Authored-By: Claude Sonnet 5.5 --- src/d2dx/RenderContext.cpp | 4 ++-- src/d2dx/RenderContext.h | 2 +- src/d2dx/Utils.cpp | 10 +++++++--- src/d2dx/Utils.h | 3 ++- tests/linux/shim/UtilsStub.cpp | 9 +++++++-- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/d2dx/RenderContext.cpp b/src/d2dx/RenderContext.cpp index 9beb040..6a9366e 100644 --- a/src/d2dx/RenderContext.cpp +++ b/src/d2dx/RenderContext.cpp @@ -468,8 +468,8 @@ void RenderContext::Present() break; } - double curTime = TimeEndMs(_timeStart); - _frameTimeMs = curTime - _prevTime; + auto curTime = TimeEnd(_timeStart); + _frameTimeMs = TimeToMs(curTime - _prevTime); _prevTime = curTime; if (_deviceContext1) diff --git a/src/d2dx/RenderContext.h b/src/d2dx/RenderContext.h index cc1b919..28af694 100644 --- a/src/d2dx/RenderContext.h +++ b/src/d2dx/RenderContext.h @@ -211,7 +211,7 @@ namespace d2dx int64_t _timeStart; bool _hasAdjustedWindowPlacement = false; - double _prevTime; + int64_t _prevTime; double _frameTimeMs; }; } \ No newline at end of file diff --git a/src/d2dx/Utils.cpp b/src/d2dx/Utils.cpp index c1f55f7..648c44b 100644 --- a/src/d2dx/Utils.cpp +++ b/src/d2dx/Utils.cpp @@ -51,13 +51,17 @@ int64_t d2dx::TimeStart() return (int64_t)li.QuadPart; } -float d2dx::TimeEndMs(int64_t sinceThisTime) +int64_t d2dx::TimeEnd(int64_t sinceThisTime) { - warmup(); LARGE_INTEGER li; QueryPerformanceCounter(&li); + return li.QuadPart - sinceThisTime; +} + +double d2dx::TimeToMs(int64_t time) +{ assert(_freq); - return (float)(double(li.QuadPart - sinceThisTime) / _freq); + return static_cast(time) / _freq; } #define STATUS_SUCCESS (0x00000000) diff --git a/src/d2dx/Utils.h b/src/d2dx/Utils.h index ac8d937..7ca8835 100644 --- a/src/d2dx/Utils.h +++ b/src/d2dx/Utils.h @@ -29,7 +29,8 @@ namespace d2dx } int64_t TimeStart(); - float TimeEndMs(int64_t start); + int64_t TimeEnd(int64_t start); + double TimeToMs(int64_t time); #ifdef NDEBUG diff --git a/tests/linux/shim/UtilsStub.cpp b/tests/linux/shim/UtilsStub.cpp index 81013f4..8200cd4 100644 --- a/tests/linux/shim/UtilsStub.cpp +++ b/tests/linux/shim/UtilsStub.cpp @@ -12,9 +12,14 @@ int64_t d2dx::TimeStart() return std::chrono::steady_clock::now().time_since_epoch().count(); } -float d2dx::TimeEndMs(int64_t start) +int64_t d2dx::TimeEnd(int64_t start) { - return (float)((TimeStart() - start) / 1e6); + return TimeStart() - start; +} + +double d2dx::TimeToMs(int64_t time) +{ + return (double)time / 1e6; // steady_clock ticks are nanoseconds } char* d2dx::detail::GetMessageForHRESULT(HRESULT, const char*, int32_t) noexcept From 67771bfe0c67adb09e85c63206eaaff13a55f96e Mon Sep 17 00:00:00 2001 From: Jack Rayner Date: Sat, 24 Oct 2026 16:13:10 +0100 Subject: [PATCH 3/3] fix: initialise the previous frame time RenderContext::_prevTime had no initial value, so the first Present() computed the frame time against garbage. Text and weather motion prediction read that frame time. The bug predates the port above (it was an uninitialised double before); start from 0, which makes the first frame time the time since the RenderContext was created. Co-Authored-By: Claude Opus 5.5 --- src/d2dx/RenderContext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d2dx/RenderContext.h b/src/d2dx/RenderContext.h index 28af694..d7cabc0 100644 --- a/src/d2dx/RenderContext.h +++ b/src/d2dx/RenderContext.h @@ -211,7 +211,7 @@ namespace d2dx int64_t _timeStart; bool _hasAdjustedWindowPlacement = false; - int64_t _prevTime; + int64_t _prevTime = 0; double _frameTimeMs; }; } \ No newline at end of file