Add live GPS momentum weights
This commit is contained in:
@@ -224,7 +224,8 @@ constexpr float kGpsSolverPavementMultiplier = 1.25f;
|
||||
constexpr size_t kGpsNodeMultiplierRoadTailPatchSize = 14;
|
||||
constexpr size_t kGpsMomentumRelaxPatchSize = 23;
|
||||
constexpr size_t kGpsMomentumPenaltyCaveSize = 96;
|
||||
constexpr float kGpsMomentumFixedEdgePenalty = 8.0f;
|
||||
constexpr float kGpsMomentumFixedEdgePenaltyDefault = 8.0f;
|
||||
constexpr float kGpsMomentumFixedEdgePenaltyMax = 1000.0f;
|
||||
constexpr std::array<float, 8> kGpsSolverNonRoadMultipliers = {
|
||||
10.0f, 6.0f, 2.0f, 0.0f, 4.0f, 2.5f, 1.5f, 0.0f,
|
||||
};
|
||||
@@ -236,6 +237,7 @@ constexpr float kGpsSpatialPavementMultiplier = 1.35f;
|
||||
constexpr float kGpsSpatialUnknownMultiplier = 1.05f;
|
||||
constexpr uint64_t kGpsSolverWeightsReloadIntervalMs = 500;
|
||||
constexpr uint64_t kGpsSpatialWeightsReloadIntervalMs = 500;
|
||||
constexpr uint64_t kGpsMomentumWeightsReloadIntervalMs = 500;
|
||||
|
||||
struct GpsProviderClassOverride
|
||||
{
|
||||
@@ -601,13 +603,18 @@ std::array<std::atomic<float>, 5> gGpsSpatialMultipliers = {
|
||||
kGpsSpatialUnknownMultiplier,
|
||||
};
|
||||
std::atomic<float> gGpsSolverHighwayMultiplier{kGpsSolverHighwayMultiplierDefault};
|
||||
std::atomic<float> gGpsMomentumFixedEdgePenalty{kGpsMomentumFixedEdgePenaltyDefault};
|
||||
std::mutex gGpsSpatialWeightsMutex;
|
||||
std::mutex gGpsMomentumWeightsMutex;
|
||||
std::atomic<uint64_t> gGpsSolverWeightsNextReloadCheckMs = 0;
|
||||
std::atomic<uint64_t> gGpsSpatialWeightsNextReloadCheckMs = 0;
|
||||
std::atomic<uint64_t> gGpsMomentumWeightsNextReloadCheckMs = 0;
|
||||
std::filesystem::file_time_type gGpsSolverWeightsLastWriteTime{};
|
||||
std::filesystem::file_time_type gGpsSpatialWeightsLastWriteTime{};
|
||||
std::filesystem::file_time_type gGpsMomentumWeightsLastWriteTime{};
|
||||
bool gGpsSolverWeightsFileKnown = false;
|
||||
bool gGpsSpatialWeightsFileKnown = false;
|
||||
bool gGpsMomentumWeightsFileKnown = false;
|
||||
|
||||
uintptr_t GetImageBase();
|
||||
|
||||
@@ -638,6 +645,11 @@ std::filesystem::path GetSolverWeightsPath()
|
||||
return GetPluginDirectory() / L"solver_weights.bin";
|
||||
}
|
||||
|
||||
std::filesystem::path GetMomentumWeightsPath()
|
||||
{
|
||||
return GetPluginDirectory() / L"momentum_weights.bin";
|
||||
}
|
||||
|
||||
uint64_t GetElapsedMs()
|
||||
{
|
||||
if (!gLogStartTick || !gLogFrequency)
|
||||
@@ -715,6 +727,34 @@ void LogGpsSolverHighwayMultiplier(std::string_view aPrefix, float aValue)
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
bool IsUsableMomentumPenalty(float aValue)
|
||||
{
|
||||
return std::isfinite(aValue) && aValue >= 0.0f && aValue <= kGpsMomentumFixedEdgePenaltyMax;
|
||||
}
|
||||
|
||||
void StoreGpsMomentumFixedEdgePenalty(float aValue)
|
||||
{
|
||||
gGpsMomentumFixedEdgePenalty.store(aValue, std::memory_order_relaxed);
|
||||
|
||||
for (auto& site : gGpsMomentumPenaltyPatchSites)
|
||||
{
|
||||
if (!site.penaltyConstant)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
WriteFloat(site.penaltyConstant, aValue);
|
||||
FlushInstructionCache(GetCurrentProcess(), site.penaltyConstant, sizeof(aValue));
|
||||
}
|
||||
}
|
||||
|
||||
void LogGpsMomentumFixedEdgePenalty(std::string_view aPrefix, float aValue)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << aPrefix << " fixedEdgePenalty=" << aValue;
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void EmitAbsoluteRaxCall(uint8_t* aCave, size_t& aOffset, uintptr_t aTarget)
|
||||
{
|
||||
aCave[aOffset++] = 0x48; // mov rax, imm64
|
||||
@@ -838,6 +878,82 @@ void MaybeReloadGpsSolverWeights(bool aForce = false)
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void MaybeReloadGpsMomentumWeights(bool aForce = false)
|
||||
{
|
||||
if (!kEnableGpsMomentumPenaltyInlinePatch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto nowMs = GetElapsedMs();
|
||||
if (!aForce && nowMs < gGpsMomentumWeightsNextReloadCheckMs.load(std::memory_order_relaxed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock(gGpsMomentumWeightsMutex);
|
||||
if (!aForce && nowMs < gGpsMomentumWeightsNextReloadCheckMs.load(std::memory_order_relaxed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
gGpsMomentumWeightsNextReloadCheckMs.store(nowMs + kGpsMomentumWeightsReloadIntervalMs,
|
||||
std::memory_order_relaxed);
|
||||
|
||||
const auto path = GetMomentumWeightsPath();
|
||||
std::error_code error;
|
||||
const auto writeTime = std::filesystem::last_write_time(path, error);
|
||||
if (error)
|
||||
{
|
||||
if (aForce || gGpsMomentumWeightsFileKnown)
|
||||
{
|
||||
gGpsMomentumWeightsFileKnown = false;
|
||||
std::ostringstream line;
|
||||
line << "momentum weights file unavailable path=" << path.string()
|
||||
<< " using fixedEdgePenalty=" << gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aForce && gGpsMomentumWeightsFileKnown && writeTime == gGpsMomentumWeightsLastWriteTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float fixedEdgePenalty = 0.0f;
|
||||
std::ifstream input(path, std::ios::binary);
|
||||
input.read(reinterpret_cast<char*>(&fixedEdgePenalty), static_cast<std::streamsize>(sizeof(fixedEdgePenalty)));
|
||||
if (input.gcount() != static_cast<std::streamsize>(sizeof(fixedEdgePenalty)))
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "momentum weights reload skipped path=" << path.string() << " bytes=" << input.gcount()
|
||||
<< " expected=" << sizeof(fixedEdgePenalty);
|
||||
LogRed4ext(line.str());
|
||||
gGpsMomentumWeightsFileKnown = true;
|
||||
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsUsableMomentumPenalty(fixedEdgePenalty))
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "momentum weights reload skipped path=" << path.string()
|
||||
<< " invalidFixedEdgePenalty=" << fixedEdgePenalty;
|
||||
LogRed4ext(line.str());
|
||||
gGpsMomentumWeightsFileKnown = true;
|
||||
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||
return;
|
||||
}
|
||||
|
||||
StoreGpsMomentumFixedEdgePenalty(fixedEdgePenalty);
|
||||
gGpsMomentumWeightsFileKnown = true;
|
||||
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||
|
||||
std::ostringstream line;
|
||||
line << "momentum weights reloaded path=" << path.string() << " fixedEdgePenalty=" << fixedEdgePenalty;
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void RemoveGpsMomentumPenaltyInlinePatch();
|
||||
|
||||
bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
||||
@@ -889,7 +1005,7 @@ bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
||||
}
|
||||
|
||||
const auto penaltyConstantOffset = offset;
|
||||
WriteFloat(cave + offset, kGpsMomentumFixedEdgePenalty);
|
||||
WriteFloat(cave + offset, gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed));
|
||||
offset += sizeof(float);
|
||||
|
||||
const auto caveAddress = reinterpret_cast<uintptr_t>(cave);
|
||||
@@ -925,7 +1041,7 @@ bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
||||
std::ostringstream line;
|
||||
line << "gps-momentum-penalty-inline-patch applied site=" << aSite.name << " target_rva=0x" << std::hex
|
||||
<< aSite.targetRva << " cave=" << static_cast<void*>(cave) << std::dec
|
||||
<< " fixedEdgePenalty=" << kGpsMomentumFixedEdgePenalty;
|
||||
<< " fixedEdgePenalty=" << gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||
LogRed4ext(line.str());
|
||||
return true;
|
||||
}
|
||||
@@ -2604,6 +2720,14 @@ void AppendGpsResultObjectLightCounts(std::ostringstream& aLine, const char* aPr
|
||||
aLine << " " << aPrefix << "_pointCount=" << pointCount;
|
||||
}
|
||||
|
||||
bool TryReadGpsResultRouteCount(void* aResultObject, uint32_t& aRouteCount)
|
||||
{
|
||||
aRouteCount = 0;
|
||||
return aResultObject &&
|
||||
TryReadMemory(reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(aResultObject) + 0x34),
|
||||
aRouteCount);
|
||||
}
|
||||
|
||||
void AppendGpsResultElementArraySummary(std::ostringstream& aLine, const char* aPrefix, void* aResultObject)
|
||||
{
|
||||
uint32_t capacity = 0;
|
||||
@@ -4555,7 +4679,9 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
|
||||
(!isTracked && callCount < kMaxUntrackedSamples && aQueryId < 2))
|
||||
: (result && isMapRouteQuery);
|
||||
|
||||
if (result && isMapRouteQuery)
|
||||
uint32_t gpsResultRouteCount = 0;
|
||||
const auto hasGpsResultRouteCount = TryReadGpsResultRouteCount(aOutPath, gpsResultRouteCount);
|
||||
if (result && isMapRouteQuery && hasGpsResultRouteCount && gpsResultRouteCount > 0)
|
||||
{
|
||||
TrackedGpsQuery summaryQuery{};
|
||||
uint64_t callsA = 0;
|
||||
@@ -4566,14 +4692,15 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
|
||||
globalCallsB))
|
||||
{
|
||||
const auto totalCalls = callsA + callsB;
|
||||
const auto fixedPenalty = kGpsMomentumFixedEdgePenalty;
|
||||
const auto fixedPenalty = gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||
std::ostringstream line;
|
||||
line << "gps-momentum-summary queryId=" << aQueryId << " resultFetchCall=" << perQueryCall;
|
||||
AppendTrackedGpsQuery(line, summaryQuery);
|
||||
line << " callsA=" << callsA << " callsB=" << callsB << " callsTotal=" << totalCalls
|
||||
<< " fixedPenalty=" << fixedPenalty
|
||||
<< " penaltyTotal=" << static_cast<double>(totalCalls) * static_cast<double>(fixedPenalty)
|
||||
<< " globalCallsA=" << globalCallsA << " globalCallsB=" << globalCallsB;
|
||||
<< " globalCallsA=" << globalCallsA << " globalCallsB=" << globalCallsB
|
||||
<< " gpsResultRouteCount=" << gpsResultRouteCount;
|
||||
AppendGpsResultObjectLightCounts(line, "gpsResult", aOutPath);
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
@@ -5787,6 +5914,7 @@ bool OnRunningUpdate(void* aApp)
|
||||
}
|
||||
|
||||
MaybeReloadGpsSolverWeights();
|
||||
MaybeReloadGpsMomentumWeights();
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -5869,9 +5997,11 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
|
||||
if (kEnableGpsMomentumPenaltyInlinePatch)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "momentum fixed-edge penalty active value=" << kGpsMomentumFixedEdgePenalty
|
||||
<< " sites=ordinary-expansion";
|
||||
line << "momentum weights path=" << GetMomentumWeightsPath().string();
|
||||
LogRed4ext(line.str());
|
||||
MaybeReloadGpsMomentumWeights(true);
|
||||
LogGpsMomentumFixedEdgePenalty("momentum fixed-edge penalty active",
|
||||
gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
InstallGpsNodeMultiplierInlinePatch();
|
||||
|
||||
Reference in New Issue
Block a user