diff --git a/red4ext/EdgeWeightGPS/src/Main.cpp b/red4ext/EdgeWeightGPS/src/Main.cpp index 4785b9e..39445d7 100644 --- a/red4ext/EdgeWeightGPS/src/Main.cpp +++ b/red4ext/EdgeWeightGPS/src/Main.cpp @@ -104,11 +104,12 @@ constexpr bool kEnableGpsCostTablePatch = false; constexpr bool kEnableGpsProviderClassPatch = false; constexpr bool kEnableGpsProviderClassPatchTrace = false; constexpr bool kEnableGpsTraceHooks = true; -constexpr bool kEnableGpsQueryLifecycleHooks = true; -constexpr bool kEnableGpsAsyncTrafficProbe = true; +constexpr bool kEnableGpsQueryLifecycleHooks = false; +constexpr bool kEnableGpsAsyncTrafficProbe = false; constexpr bool kEnableGpsTrafficEdgeWeightPatch = false; constexpr bool kEnableGpsSpatialEdgeWeightPatch = true; constexpr bool kEnableGpsSpatialEdgeWeightPatchTrace = false; +constexpr bool kEnableGpsSpatialEdgeWeightPatchStats = true; constexpr bool kEnableGpsRouteJobLifecycleHooks = false; constexpr bool kEnableGpsRouteJobStartTrace = false; constexpr bool kEnableGpsLocalSearchHooks = false; @@ -348,8 +349,14 @@ struct GpsEdgeCostSample uint64_t neighborHandle = 0; uintptr_t returnRva = 0; float cost = 0.0f; + float originalCost = 0.0f; + float spatialMultiplier = 1.0f; uint8_t sourceClass = 0xFF; uint8_t neighborClass = 0xFF; + char spatialClass = '.'; + bool spatialPatchAllowed = false; + bool spatialLookupOk = false; + bool spatialAdjusted = false; }; struct GpsEdgeCostStats @@ -362,6 +369,12 @@ struct GpsEdgeCostStats float maxCost = 0.0f; std::array sourceClasses{}; std::array neighborClasses{}; + uint32_t spatialPatchAllowed = 0; + uint32_t spatialLookupOk = 0; + uint32_t spatialLookupFailed = 0; + uint32_t spatialAdjusted = 0; + std::array spatialClasses{}; + std::array spatialMultiplierSums{}; std::array returnRvas{}; std::array returnRvaCounts{}; uint32_t otherReturnRvas = 0; @@ -1130,6 +1143,23 @@ int GpsSpatialRoadClassRank(char aCode) } } +uint32_t GpsSpatialRoadClassIndex(char aCode) +{ + switch (aCode) + { + case 'H': + return 0; + case 'R': + return 1; + case 'G': + return 2; + case 'P': + return 3; + default: + return 4; + } +} + const char* GpsSpatialRoadClassName(char aCode) { switch (aCode) @@ -1581,6 +1611,38 @@ void AppendGpsEdgeCostStats(std::ostringstream& aLine, const GpsEdgeCostStats& a AppendClassCounts(aLine, "edgeSrcClasses", aStats.sourceClasses, aStats.invalidSourceClass); AppendClassCounts(aLine, "edgeDstClasses", aStats.neighborClasses, aStats.invalidNeighborClass); + aLine << " spatialAllowed=" << aStats.spatialPatchAllowed << " spatialLookupOk=" << aStats.spatialLookupOk + << " spatialLookupFailed=" << aStats.spatialLookupFailed << " spatialAdjusted=" << aStats.spatialAdjusted; + + aLine << " spatialClasses=["; + constexpr std::array spatialClassCodes = {'H', 'R', 'G', 'P', '.'}; + bool firstSpatialClass = true; + for (uint32_t index = 0; index < aStats.spatialClasses.size(); ++index) + { + const auto count = aStats.spatialClasses[index]; + if (count == 0) + { + continue; + } + + if (!firstSpatialClass) + { + aLine << ","; + } + firstSpatialClass = false; + aLine << spatialClassCodes[index] << ":" << count; + const auto flags = aLine.flags(); + const auto precision = aLine.precision(); + aLine << ":avgMult=" << std::fixed << std::setprecision(3) + << (aStats.spatialMultiplierSums[index] / static_cast(count)); + aLine.flags(flags); + aLine.precision(precision); + } + if (firstSpatialClass) + { + aLine << "none"; + } + aLine << "]"; aLine << " edgeRetRvas=["; bool first = true; @@ -1627,8 +1689,12 @@ void AppendGpsEdgeCostStats(std::ostringstream& aLine, const GpsEdgeCostStats& a const auto precision = aLine.precision(); aLine << index << ":" << static_cast(sample.sourceClass) << ">" << static_cast(sample.neighborClass) << " cost=" << std::fixed << std::setprecision(3) - << sample.cost << " ret=0x" << std::hex << sample.returnRva << " cur=0x" << sample.currentHandle - << " dst=0x" << sample.neighborHandle << std::dec; + << sample.cost << " original=" << sample.originalCost << " spatial=" << sample.spatialClass + << " mult=" << sample.spatialMultiplier << " allowed=" << static_cast(sample.spatialPatchAllowed) + << " lookup=" << static_cast(sample.spatialLookupOk) + << " adjusted=" << static_cast(sample.spatialAdjusted) << " ret=0x" << std::hex + << sample.returnRva << " cur=0x" << sample.currentHandle << " dst=0x" << sample.neighborHandle + << std::dec; aLine.flags(flags); aLine.precision(precision); } @@ -1683,7 +1749,9 @@ void NoteGpsProviderFilterStats(GpsProviderFilterStats& aStats, bool aFilteredPr } void NoteGpsEdgeCostStats(GpsEdgeCostStats& aStats, uint8_t aSourceClass, uint8_t aNeighborClass, float aCost, - uintptr_t aReturnRva, uint64_t aCurrentHandle, uint64_t aNeighborHandle) + float aOriginalCost, uintptr_t aReturnRva, uint64_t aCurrentHandle, + uint64_t aNeighborHandle, char aSpatialClass, float aSpatialMultiplier, + bool aSpatialPatchAllowed, bool aSpatialLookupOk, bool aSpatialAdjusted) { ++aStats.total; aStats.costSum += aCost; @@ -1716,6 +1784,30 @@ void NoteGpsEdgeCostStats(GpsEdgeCostStats& aStats, uint8_t aSourceClass, uint8_ ++aStats.invalidNeighborClass; } + if (aSpatialPatchAllowed) + { + ++aStats.spatialPatchAllowed; + if (aSpatialLookupOk) + { + ++aStats.spatialLookupOk; + const auto spatialIndex = GpsSpatialRoadClassIndex(aSpatialClass); + if (spatialIndex < aStats.spatialClasses.size()) + { + ++aStats.spatialClasses[spatialIndex]; + aStats.spatialMultiplierSums[spatialIndex] += aSpatialMultiplier; + } + } + else + { + ++aStats.spatialLookupFailed; + } + + if (aSpatialAdjusted) + { + ++aStats.spatialAdjusted; + } + } + if (aReturnRva != 0) { bool recorded = false; @@ -1750,8 +1842,14 @@ void NoteGpsEdgeCostStats(GpsEdgeCostStats& aStats, uint8_t aSourceClass, uint8_ sample.neighborHandle = aNeighborHandle; sample.returnRva = aReturnRva; sample.cost = aCost; + sample.originalCost = aOriginalCost; + sample.spatialMultiplier = aSpatialMultiplier; sample.sourceClass = aSourceClass; sample.neighborClass = aNeighborClass; + sample.spatialClass = aSpatialClass; + sample.spatialPatchAllowed = aSpatialPatchAllowed; + sample.spatialLookupOk = aSpatialLookupOk; + sample.spatialAdjusted = aSpatialAdjusted; } } @@ -4315,7 +4413,7 @@ int32_t DetourGpsRouteProducer(void* aGraph, void* aQuery, void* aOutResult) { std::lock_guard lock(gGpsCostLogMutex); callCount = gGpsRouteProducerLogCount++; - shouldLog = kEnableGpsLocalSearchTraceHooks && callCount < kMaxCalls; + shouldLog = (kEnableGpsLocalSearchTraceHooks || kEnableGpsSpatialEdgeWeightPatchStats) && callCount < kMaxCalls; } if (shouldLog) @@ -4585,12 +4683,14 @@ float DetourGpsEdgeCost(void* aCostProvider, void* aCurrentState, void* aNeighbo char spatialClass = '.'; float spatialMultiplier = 1.0f; bool spatialAdjusted = false; + bool spatialLookupOk = false; const auto spatialPatchAllowed = kEnableGpsSpatialEdgeWeightPatch && (!kGpsSpatialPatchRequiresRouteProducer || gActiveGpsRouteProducerCall != UINT32_MAX); if (spatialPatchAllowed && result > 0.0f && std::isfinite(result) && TryLookupGpsSpatialEdgeClass(aCurrentState, aNeighborState, spatialClass)) { + spatialLookupOk = true; spatialMultiplier = GpsSpatialRoadClassMultiplier(spatialClass); result *= spatialMultiplier; spatialAdjusted = spatialMultiplier != 1.0f; @@ -4598,8 +4698,9 @@ float DetourGpsEdgeCost(void* aCostProvider, void* aCurrentState, void* aNeighbo if (gActiveGpsEdgeCostStats) { - NoteGpsEdgeCostStats(*gActiveGpsEdgeCostStats, sourceClass, neighborClass, result, returnRva, aCurrentHandle, - aNeighborHandle); + NoteGpsEdgeCostStats(*gActiveGpsEdgeCostStats, sourceClass, neighborClass, result, originalResult, returnRva, + aCurrentHandle, aNeighborHandle, spatialClass, spatialMultiplier, spatialPatchAllowed, + spatialLookupOk, spatialAdjusted); } float multiplier = 0.0f;