From 4ff9d13459ac3d78f77029a32fd61146fa169f8d Mon Sep 17 00:00:00 2001 From: Daniel GP <96537843+DaniGP17@users.noreply.github.com> Date: Wed, 13 May 2026 21:20:57 +0200 Subject: [PATCH 1/3] fix(gta-core-five): optimize distant lod lights render Co-Authored-By: divocbn --- .../gta-core-five/src/LODLightsCaching.cpp | 336 ++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 code/components/gta-core-five/src/LODLightsCaching.cpp diff --git a/code/components/gta-core-five/src/LODLightsCaching.cpp b/code/components/gta-core-five/src/LODLightsCaching.cpp new file mode 100644 index 0000000000..0d5e81126b --- /dev/null +++ b/code/components/gta-core-five/src/LODLightsCaching.cpp @@ -0,0 +1,336 @@ +#include "StdInc.h" + +#include "Hooking.Patterns.h" +#include "Hooking.Stubs.h" + +#include + +#include +#include +#include + +enum CVisualEffectsRenderMode : uint32_t +{ + RM_DEFAULT = 0, + RM_MIRROR_REFLECTION = 1, + RM_WATER_REFLECTION = 2, + RM_CUBE_REFLECTION = 3, + RM_SEETHROUGH = 4, + RM_NUM = 5, +}; + +enum eLodLightCategory : uint32_t +{ + LODLIGHT_CATEGORY_SMALL = 0, + LODLIGHT_CATEGORY_MEDIUM = 1, + LODLIGHT_CATEGORY_LARGE = 2, + LODLIGHT_CATEGORY_COUNT = 3, +}; + +struct distLightsParam +{ + char m_Padding[0x18]; + + float m_StreetLightHdrIntensity; + + char m_Padding2[0x18]; + + float m_HourStart; + float m_HourEnd; + float m_StreetLightHourStart; + float m_StreetLightHourEnd; + + char m_Padding3[0x4c]; +}; +static_assert(sizeof(distLightsParam) == 0x90, "distLightsParam has wrong size!"); + +struct DistantLightElementStruct +{ + DirectX::XMFLOAT3 m_Position; + uint32_t m_Color; +}; +static_assert(sizeof(DistantLightElementStruct) == 0x10, "DistantLightElementStruct has wrong size!"); + +static bool* g_CRenderer_DisableArtificialLights; + +static distLightsParam* g_DistLightsParam; +static float* g_WaterReflectionDistLightFadeout; + +static uint64_t* g_CLodLightManager_CurrentFrameInfo; + +static bool* g_CLodLights_Enabled; +static bool* g_CLodLights_CanLoad; + +static hook::cdecl_stub g_CreateVertexBuffers([] +{ + return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 80 3D ? ? ? ? 00 0F 85"); +}); + +static hook::cdecl_stub g_RenderBufferBegin([] +{ + return hook::get_pattern("48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 56 41 57 48 8D 68 ? 48 81 EC ? ? ? ? 0F 29 70 ? F3 0F 10 35"); +}); + +static hook::cdecl_stub g_RenderBuffer([] +{ + return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 57 48 83 EC ? 8B 1D"); +}); + +static hook::cdecl_stub g_ReserveRenderBufferSpace([] +{ + return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 83 3D ? ? ? ? ? 44 8B 15"); +}); + +static hook::cdecl_stub g_CalculateTimeFade([] +{ + return hook::get_pattern("48 8B C4 48 81 EC ? ? ? ? 66 0F 6E 2D"); +}); + +static hook::cdecl_stub g_GetRenderLodLightCoronaRange([] +{ + return hook::get_pattern("48 8B 05 ? ? ? ? F3 0F 10 0D ? ? ? ? F3 0F 10 05"); +}); + +class grcViewport +{ +public: + char m_Padding[0xc0]; + DirectX::XMMATRIX m_Camera44; +}; +static_assert(sizeof(grcViewport) == 0x100, "grcViewport has wrong size!"); + +static grcViewport* g_grcViewport_Current; + +class CDistantLODLight +{ +public: + char m_Padding[0x8]; + atArray m_Positions; + atArray m_Colors; + + uint16_t m_NumStreetLights; + uint16_t m_Category; +}; +static_assert(sizeof(CDistantLODLight) == 0x30, "CDistantLODLight has wrong size!"); + +uint64_t* g_MapDataStore_Boxes; + +static void (*g_CLodLights_RenderDistantLODLights)(CVisualEffectsRenderMode mode, float intensity); + +static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMode mode, float intensityScale) +{ + if (*g_CRenderer_DisableArtificialLights) + return; + + if (!g_CLodLightManager_CurrentFrameInfo) + return; + + g_CreateVertexBuffers(); + + if (mode == RM_WATER_REFLECTION) + { + intensityScale *= (1.0f - *g_WaterReflectionDistLightFadeout); + + if (intensityScale <= 0.0f) + return; + } + + if (!*g_CLodLights_Enabled || !*g_CLodLights_CanLoad) + return; + + const uint8_t alphaNormal = uint8_t( + g_CalculateTimeFade( + g_DistLightsParam->m_HourStart - 1.0f, + g_DistLightsParam->m_HourStart, + g_DistLightsParam->m_HourEnd - 1.0f, + g_DistLightsParam->m_HourEnd + ) * 255.0f + 0.5f + ); + + const uint8_t alphaStreet = uint8_t( + g_CalculateTimeFade( + g_DistLightsParam->m_StreetLightHourStart - 1.0f, + g_DistLightsParam->m_StreetLightHourStart, + g_DistLightsParam->m_StreetLightHourEnd - 1.0f, + g_DistLightsParam->m_StreetLightHourEnd + ) * 255.0f + 0.5f + ); + + if (!alphaNormal && !alphaStreet) + return; + + static constexpr int32_t kDistantLodLightBucketSize = 0xaf8; + + uint32_t category = LODLIGHT_CATEGORY_MEDIUM; + uint64_t bucketOffset = kDistantLodLightBucketSize; + + const DirectX::XMVECTOR camera = g_grcViewport_Current->m_Camera44.r[3]; + + const float hdrIntensity = g_DistLightsParam->m_StreetLightHdrIntensity * intensityScale; + + do + { + const float range = g_GetRenderLodLightCoronaRange(category); + + g_RenderBufferBegin(mode, range, range, hdrIntensity, 0, nullptr); + + uint32_t bucketIndex = 0; + + uint32_t* bucketList = (uint32_t*)(*g_CLodLightManager_CurrentFrameInfo + bucketOffset + kDistantLodLightBucketSize); + + const uint32_t bucketCount = bucketList[700]; + + if (bucketCount) + { + const float rangeSquared = range * range; + + const DirectX::XMVECTOR half = DirectX::XMVectorReplicate(0.5f); + + do + { + uint16_t* bucket = *(uint16_t**)bucketList; + + uint64_t lightData = *(uint64_t*)bucket; + + const uint32_t totalLights = bucket[5]; + + if (!totalLights) + { + bucketIndex++; + bucketList += 2; + continue; + } + + const uint16_t aabbIndex = *(uint16_t*)(lightData + 8); + + DirectX::XMVECTOR* aabb = (DirectX::XMVECTOR*)(*g_MapDataStore_Boxes + (32 * aabbIndex)); + + const DirectX::XMVECTOR aabbMin = aabb[0]; + const DirectX::XMVECTOR aabbMax = aabb[1]; + + const DirectX::XMVECTOR center = DirectX::XMVectorMultiply( + DirectX::XMVectorAdd(aabbMin, aabbMax), + half + ); + + const DirectX::XMVECTOR extents = DirectX::XMVectorMultiply( + DirectX::XMVectorSubtract(aabbMax, aabbMin), + half + ); + + const DirectX::XMVECTOR delta = DirectX::XMVectorAdd( + DirectX::XMVectorAbs(DirectX::XMVectorSubtract(camera, center)), + extents + ); + + CDistantLODLight* lightDataAsDistantLodLight = (CDistantLODLight*)lightData; + + const uint32_t numStreetLights = lightDataAsDistantLodLight->m_NumStreetLights; + + const float distanceSquared = DirectX::XMVectorGetX(DirectX::XMVector3LengthSq(delta)); + + if (distanceSquared > rangeSquared) + { + uint32_t lightCount = 0; + + if (alphaStreet) + { + lightCount += numStreetLights; + } + + if (alphaNormal) + { + lightCount += (totalLights - numStreetLights); + } + + auto* outputBuffer = g_ReserveRenderBufferSpace(lightCount); + if (!outputBuffer) + break; + + // NOTE: using raw pointers here avoids atArray::operator[] overhead in this hot loop + auto* colors = lightDataAsDistantLodLight->m_Colors.m_offset; + auto* positions = lightDataAsDistantLodLight->m_Positions.m_offset; + + if (alphaStreet) + { + for (uint32_t i = 0; i < numStreetLights; i++) + { + uint32_t color = colors[i]; + + const uint32_t a = (alphaStreet * (color >> 24)) >> 8; + const uint32_t r = color & 0xFF; + const uint32_t g = color & 0xFF00; + const uint32_t b = (color >> 16) & 0xFF; + + color = (a << 24) | (r << 16) | g | b; + + auto& position = positions[i]; + + outputBuffer->m_Position.x = position.x; + outputBuffer->m_Position.y = position.y; + outputBuffer->m_Position.z = position.z; + + outputBuffer->m_Color = color; + + outputBuffer++; + } + } + + if (alphaNormal) + { + for (uint32_t i = numStreetLights; i < totalLights; i++) + { + uint32_t color = colors[i]; + + const uint32_t a = (alphaNormal * (color >> 24)) >> 8; + const uint32_t r = color & 0xFF; + const uint32_t g = color & 0xFF00; + const uint32_t b = (color >> 16) & 0xFF; + + color = (a << 24) | (r << 16) | g | b; + + auto& position = positions[i]; + + outputBuffer->m_Position.x = position.x; + outputBuffer->m_Position.y = position.y; + outputBuffer->m_Position.z = position.z; + + outputBuffer->m_Color = color; + + outputBuffer++; + } + } + } + + ++bucketIndex; + bucketList += 2; + + } while (bucketIndex < bucketCount); + } + + g_RenderBuffer(true); + + category++; + bucketOffset += kDistantLodLightBucketSize; + } while (category < LODLIGHT_CATEGORY_COUNT); +} + +static HookFunction initFunction([] +{ + g_CRenderer_DisableArtificialLights = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 0F 28 D9"), 2, 7); + + g_MapDataStore_Boxes = hook::get_address(hook::get_pattern("48 03 0D ? ? ? ? 0F 28 61"), 3, 7); + + g_CLodLights_Enabled = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 48 63 DA"), 2, 7); + g_CLodLights_CanLoad = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 74 ? C6 05 ? ? ? ? 00 33 C9"), 2, 7); + + g_CLodLightManager_CurrentFrameInfo = hook::get_address(hook::get_pattern("4C 8B 25 ? ? ? ? 45 8B FD"), 3, 7); + + g_WaterReflectionDistLightFadeout = hook::get_address(hook::get_pattern("F3 0F 5C 05 ? ? ? ? F3 44 0F 59 C8 44 0F 2F 0D"), 4, 8); + + g_DistLightsParam = hook::get_address(hook::get_pattern("F3 0F 10 1D ? ? ? ? EB ? F3 0F 10 1D ? ? ? ? 0F 28 C6"), 4, 8); + + g_grcViewport_Current = hook::get_address(hook::get_pattern("48 8B 05 ? ? ? ? BB ? ? ? ? BD"), 3, 7); + + g_CLodLights_RenderDistantLODLights = hook::trampoline(hook::get_pattern("48 8B C4 48 89 58 ? 89 48 ? 55"), CLodLights_RenderDistantLODLights); +}); From e1bd2a1648c0c2d66845da4219dbbc4b8400093c Mon Sep 17 00:00:00 2001 From: divocbn Date: Thu, 14 May 2026 16:28:04 +0200 Subject: [PATCH 2/3] fix(gta-core-five): wrong distant lod mapdata index & patterns Co-Authored-By: DaniGP17 --- .../gta-core-five/src/LODLightsCaching.cpp | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/code/components/gta-core-five/src/LODLightsCaching.cpp b/code/components/gta-core-five/src/LODLightsCaching.cpp index 0d5e81126b..9fd16475f5 100644 --- a/code/components/gta-core-five/src/LODLightsCaching.cpp +++ b/code/components/gta-core-five/src/LODLightsCaching.cpp @@ -63,7 +63,7 @@ static bool* g_CLodLights_CanLoad; static hook::cdecl_stub g_CreateVertexBuffers([] { - return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 80 3D ? ? ? ? 00 0F 85"); + return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 80 3D ? ? ? ? 00 0F 85"); }); static hook::cdecl_stub g_RenderBufferBegin([] @@ -113,6 +113,15 @@ class CDistantLODLight }; static_assert(sizeof(CDistantLODLight) == 0x30, "CDistantLODLight has wrong size!"); +class CDistantLODLightBucket +{ +public: + CDistantLODLight* m_Light; + uint16_t m_MapDataIndex; + uint16_t m_LightCount; +}; +static_assert(sizeof(CDistantLODLightBucket) == 0x10, "CDistantLODLightBucket has wrong size!"); + uint64_t* g_MapDataStore_Boxes; static void (*g_CLodLights_RenderDistantLODLights)(CVisualEffectsRenderMode mode, float intensity); @@ -188,11 +197,9 @@ static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMod do { - uint16_t* bucket = *(uint16_t**)bucketList; - - uint64_t lightData = *(uint64_t*)bucket; + CDistantLODLightBucket* bucket = *(CDistantLODLightBucket**)bucketList; - const uint32_t totalLights = bucket[5]; + const uint32_t totalLights = bucket->m_LightCount; if (!totalLights) { @@ -201,9 +208,9 @@ static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMod continue; } - const uint16_t aabbIndex = *(uint16_t*)(lightData + 8); + const uint16_t mapDataIndex = bucket->m_MapDataIndex; - DirectX::XMVECTOR* aabb = (DirectX::XMVECTOR*)(*g_MapDataStore_Boxes + (32 * aabbIndex)); + DirectX::XMVECTOR* aabb = (DirectX::XMVECTOR*)(*g_MapDataStore_Boxes + (32 * mapDataIndex)); const DirectX::XMVECTOR aabbMin = aabb[0]; const DirectX::XMVECTOR aabbMax = aabb[1]; @@ -223,9 +230,9 @@ static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMod extents ); - CDistantLODLight* lightDataAsDistantLodLight = (CDistantLODLight*)lightData; + CDistantLODLight* lightData = bucket->m_Light; - const uint32_t numStreetLights = lightDataAsDistantLodLight->m_NumStreetLights; + const uint32_t numStreetLights = lightData->m_NumStreetLights; const float distanceSquared = DirectX::XMVectorGetX(DirectX::XMVector3LengthSq(delta)); @@ -248,8 +255,8 @@ static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMod break; // NOTE: using raw pointers here avoids atArray::operator[] overhead in this hot loop - auto* colors = lightDataAsDistantLodLight->m_Colors.m_offset; - auto* positions = lightDataAsDistantLodLight->m_Positions.m_offset; + auto* colors = lightData->m_Colors.m_offset; + auto* positions = lightData->m_Positions.m_offset; if (alphaStreet) { @@ -321,7 +328,7 @@ static HookFunction initFunction([] g_MapDataStore_Boxes = hook::get_address(hook::get_pattern("48 03 0D ? ? ? ? 0F 28 61"), 3, 7); - g_CLodLights_Enabled = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 48 63 DA"), 2, 7); + g_CLodLights_Enabled = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 48 63 DA 74 ? 80 3D ? ? ? ? 00"), 2, 7); g_CLodLights_CanLoad = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 74 ? C6 05 ? ? ? ? 00 33 C9"), 2, 7); g_CLodLightManager_CurrentFrameInfo = hook::get_address(hook::get_pattern("4C 8B 25 ? ? ? ? 45 8B FD"), 3, 7); From e0c7630777f048b419b85ef0454aa1befb918279 Mon Sep 17 00:00:00 2001 From: divocbn Date: Thu, 14 May 2026 21:52:29 +0200 Subject: [PATCH 3/3] feat(gta-core-five): remove rebuilt render and nop prefetchs Co-Authored-By: DaniGP17 --- .../gta-core-five/src/LODLightsCaching.cpp | 343 ------------------ .../gta-core-five/src/OptimizeLodLights.cpp | 12 + 2 files changed, 12 insertions(+), 343 deletions(-) delete mode 100644 code/components/gta-core-five/src/LODLightsCaching.cpp create mode 100644 code/components/gta-core-five/src/OptimizeLodLights.cpp diff --git a/code/components/gta-core-five/src/LODLightsCaching.cpp b/code/components/gta-core-five/src/LODLightsCaching.cpp deleted file mode 100644 index 9fd16475f5..0000000000 --- a/code/components/gta-core-five/src/LODLightsCaching.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include "StdInc.h" - -#include "Hooking.Patterns.h" -#include "Hooking.Stubs.h" - -#include - -#include -#include -#include - -enum CVisualEffectsRenderMode : uint32_t -{ - RM_DEFAULT = 0, - RM_MIRROR_REFLECTION = 1, - RM_WATER_REFLECTION = 2, - RM_CUBE_REFLECTION = 3, - RM_SEETHROUGH = 4, - RM_NUM = 5, -}; - -enum eLodLightCategory : uint32_t -{ - LODLIGHT_CATEGORY_SMALL = 0, - LODLIGHT_CATEGORY_MEDIUM = 1, - LODLIGHT_CATEGORY_LARGE = 2, - LODLIGHT_CATEGORY_COUNT = 3, -}; - -struct distLightsParam -{ - char m_Padding[0x18]; - - float m_StreetLightHdrIntensity; - - char m_Padding2[0x18]; - - float m_HourStart; - float m_HourEnd; - float m_StreetLightHourStart; - float m_StreetLightHourEnd; - - char m_Padding3[0x4c]; -}; -static_assert(sizeof(distLightsParam) == 0x90, "distLightsParam has wrong size!"); - -struct DistantLightElementStruct -{ - DirectX::XMFLOAT3 m_Position; - uint32_t m_Color; -}; -static_assert(sizeof(DistantLightElementStruct) == 0x10, "DistantLightElementStruct has wrong size!"); - -static bool* g_CRenderer_DisableArtificialLights; - -static distLightsParam* g_DistLightsParam; -static float* g_WaterReflectionDistLightFadeout; - -static uint64_t* g_CLodLightManager_CurrentFrameInfo; - -static bool* g_CLodLights_Enabled; -static bool* g_CLodLights_CanLoad; - -static hook::cdecl_stub g_CreateVertexBuffers([] -{ - return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 80 3D ? ? ? ? 00 0F 85"); -}); - -static hook::cdecl_stub g_RenderBufferBegin([] -{ - return hook::get_pattern("48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 56 41 57 48 8D 68 ? 48 81 EC ? ? ? ? 0F 29 70 ? F3 0F 10 35"); -}); - -static hook::cdecl_stub g_RenderBuffer([] -{ - return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 57 48 83 EC ? 8B 1D"); -}); - -static hook::cdecl_stub g_ReserveRenderBufferSpace([] -{ - return hook::get_pattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 83 EC ? 83 3D ? ? ? ? ? 44 8B 15"); -}); - -static hook::cdecl_stub g_CalculateTimeFade([] -{ - return hook::get_pattern("48 8B C4 48 81 EC ? ? ? ? 66 0F 6E 2D"); -}); - -static hook::cdecl_stub g_GetRenderLodLightCoronaRange([] -{ - return hook::get_pattern("48 8B 05 ? ? ? ? F3 0F 10 0D ? ? ? ? F3 0F 10 05"); -}); - -class grcViewport -{ -public: - char m_Padding[0xc0]; - DirectX::XMMATRIX m_Camera44; -}; -static_assert(sizeof(grcViewport) == 0x100, "grcViewport has wrong size!"); - -static grcViewport* g_grcViewport_Current; - -class CDistantLODLight -{ -public: - char m_Padding[0x8]; - atArray m_Positions; - atArray m_Colors; - - uint16_t m_NumStreetLights; - uint16_t m_Category; -}; -static_assert(sizeof(CDistantLODLight) == 0x30, "CDistantLODLight has wrong size!"); - -class CDistantLODLightBucket -{ -public: - CDistantLODLight* m_Light; - uint16_t m_MapDataIndex; - uint16_t m_LightCount; -}; -static_assert(sizeof(CDistantLODLightBucket) == 0x10, "CDistantLODLightBucket has wrong size!"); - -uint64_t* g_MapDataStore_Boxes; - -static void (*g_CLodLights_RenderDistantLODLights)(CVisualEffectsRenderMode mode, float intensity); - -static void __fastcall CLodLights_RenderDistantLODLights(CVisualEffectsRenderMode mode, float intensityScale) -{ - if (*g_CRenderer_DisableArtificialLights) - return; - - if (!g_CLodLightManager_CurrentFrameInfo) - return; - - g_CreateVertexBuffers(); - - if (mode == RM_WATER_REFLECTION) - { - intensityScale *= (1.0f - *g_WaterReflectionDistLightFadeout); - - if (intensityScale <= 0.0f) - return; - } - - if (!*g_CLodLights_Enabled || !*g_CLodLights_CanLoad) - return; - - const uint8_t alphaNormal = uint8_t( - g_CalculateTimeFade( - g_DistLightsParam->m_HourStart - 1.0f, - g_DistLightsParam->m_HourStart, - g_DistLightsParam->m_HourEnd - 1.0f, - g_DistLightsParam->m_HourEnd - ) * 255.0f + 0.5f - ); - - const uint8_t alphaStreet = uint8_t( - g_CalculateTimeFade( - g_DistLightsParam->m_StreetLightHourStart - 1.0f, - g_DistLightsParam->m_StreetLightHourStart, - g_DistLightsParam->m_StreetLightHourEnd - 1.0f, - g_DistLightsParam->m_StreetLightHourEnd - ) * 255.0f + 0.5f - ); - - if (!alphaNormal && !alphaStreet) - return; - - static constexpr int32_t kDistantLodLightBucketSize = 0xaf8; - - uint32_t category = LODLIGHT_CATEGORY_MEDIUM; - uint64_t bucketOffset = kDistantLodLightBucketSize; - - const DirectX::XMVECTOR camera = g_grcViewport_Current->m_Camera44.r[3]; - - const float hdrIntensity = g_DistLightsParam->m_StreetLightHdrIntensity * intensityScale; - - do - { - const float range = g_GetRenderLodLightCoronaRange(category); - - g_RenderBufferBegin(mode, range, range, hdrIntensity, 0, nullptr); - - uint32_t bucketIndex = 0; - - uint32_t* bucketList = (uint32_t*)(*g_CLodLightManager_CurrentFrameInfo + bucketOffset + kDistantLodLightBucketSize); - - const uint32_t bucketCount = bucketList[700]; - - if (bucketCount) - { - const float rangeSquared = range * range; - - const DirectX::XMVECTOR half = DirectX::XMVectorReplicate(0.5f); - - do - { - CDistantLODLightBucket* bucket = *(CDistantLODLightBucket**)bucketList; - - const uint32_t totalLights = bucket->m_LightCount; - - if (!totalLights) - { - bucketIndex++; - bucketList += 2; - continue; - } - - const uint16_t mapDataIndex = bucket->m_MapDataIndex; - - DirectX::XMVECTOR* aabb = (DirectX::XMVECTOR*)(*g_MapDataStore_Boxes + (32 * mapDataIndex)); - - const DirectX::XMVECTOR aabbMin = aabb[0]; - const DirectX::XMVECTOR aabbMax = aabb[1]; - - const DirectX::XMVECTOR center = DirectX::XMVectorMultiply( - DirectX::XMVectorAdd(aabbMin, aabbMax), - half - ); - - const DirectX::XMVECTOR extents = DirectX::XMVectorMultiply( - DirectX::XMVectorSubtract(aabbMax, aabbMin), - half - ); - - const DirectX::XMVECTOR delta = DirectX::XMVectorAdd( - DirectX::XMVectorAbs(DirectX::XMVectorSubtract(camera, center)), - extents - ); - - CDistantLODLight* lightData = bucket->m_Light; - - const uint32_t numStreetLights = lightData->m_NumStreetLights; - - const float distanceSquared = DirectX::XMVectorGetX(DirectX::XMVector3LengthSq(delta)); - - if (distanceSquared > rangeSquared) - { - uint32_t lightCount = 0; - - if (alphaStreet) - { - lightCount += numStreetLights; - } - - if (alphaNormal) - { - lightCount += (totalLights - numStreetLights); - } - - auto* outputBuffer = g_ReserveRenderBufferSpace(lightCount); - if (!outputBuffer) - break; - - // NOTE: using raw pointers here avoids atArray::operator[] overhead in this hot loop - auto* colors = lightData->m_Colors.m_offset; - auto* positions = lightData->m_Positions.m_offset; - - if (alphaStreet) - { - for (uint32_t i = 0; i < numStreetLights; i++) - { - uint32_t color = colors[i]; - - const uint32_t a = (alphaStreet * (color >> 24)) >> 8; - const uint32_t r = color & 0xFF; - const uint32_t g = color & 0xFF00; - const uint32_t b = (color >> 16) & 0xFF; - - color = (a << 24) | (r << 16) | g | b; - - auto& position = positions[i]; - - outputBuffer->m_Position.x = position.x; - outputBuffer->m_Position.y = position.y; - outputBuffer->m_Position.z = position.z; - - outputBuffer->m_Color = color; - - outputBuffer++; - } - } - - if (alphaNormal) - { - for (uint32_t i = numStreetLights; i < totalLights; i++) - { - uint32_t color = colors[i]; - - const uint32_t a = (alphaNormal * (color >> 24)) >> 8; - const uint32_t r = color & 0xFF; - const uint32_t g = color & 0xFF00; - const uint32_t b = (color >> 16) & 0xFF; - - color = (a << 24) | (r << 16) | g | b; - - auto& position = positions[i]; - - outputBuffer->m_Position.x = position.x; - outputBuffer->m_Position.y = position.y; - outputBuffer->m_Position.z = position.z; - - outputBuffer->m_Color = color; - - outputBuffer++; - } - } - } - - ++bucketIndex; - bucketList += 2; - - } while (bucketIndex < bucketCount); - } - - g_RenderBuffer(true); - - category++; - bucketOffset += kDistantLodLightBucketSize; - } while (category < LODLIGHT_CATEGORY_COUNT); -} - -static HookFunction initFunction([] -{ - g_CRenderer_DisableArtificialLights = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 0F 28 D9"), 2, 7); - - g_MapDataStore_Boxes = hook::get_address(hook::get_pattern("48 03 0D ? ? ? ? 0F 28 61"), 3, 7); - - g_CLodLights_Enabled = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 48 63 DA 74 ? 80 3D ? ? ? ? 00"), 2, 7); - g_CLodLights_CanLoad = hook::get_address(hook::get_pattern("80 3D ? ? ? ? 00 74 ? C6 05 ? ? ? ? 00 33 C9"), 2, 7); - - g_CLodLightManager_CurrentFrameInfo = hook::get_address(hook::get_pattern("4C 8B 25 ? ? ? ? 45 8B FD"), 3, 7); - - g_WaterReflectionDistLightFadeout = hook::get_address(hook::get_pattern("F3 0F 5C 05 ? ? ? ? F3 44 0F 59 C8 44 0F 2F 0D"), 4, 8); - - g_DistLightsParam = hook::get_address(hook::get_pattern("F3 0F 10 1D ? ? ? ? EB ? F3 0F 10 1D ? ? ? ? 0F 28 C6"), 4, 8); - - g_grcViewport_Current = hook::get_address(hook::get_pattern("48 8B 05 ? ? ? ? BB ? ? ? ? BD"), 3, 7); - - g_CLodLights_RenderDistantLODLights = hook::trampoline(hook::get_pattern("48 8B C4 48 89 58 ? 89 48 ? 55"), CLodLights_RenderDistantLODLights); -}); diff --git a/code/components/gta-core-five/src/OptimizeLodLights.cpp b/code/components/gta-core-five/src/OptimizeLodLights.cpp new file mode 100644 index 0000000000..fd3e9d5a2c --- /dev/null +++ b/code/components/gta-core-five/src/OptimizeLodLights.cpp @@ -0,0 +1,12 @@ +#include "StdInc.h" + +#include "Hooking.Patterns.h" + +static HookFunction initFunction([] +{ + auto alphaStreetPrefetch = hook::get_pattern("48 63 CB 41 0F 18 44 8B"); + hook::nop(alphaStreetPrefetch, 25); + + auto alphaNormalPrefetch = hook::get_pattern("48 63 CF 41 0F 18 44 8B"); + hook::nop(alphaNormalPrefetch, 25); +});