Skip to content

Commit ced89ef

Browse files
committed
fix(extra-natives/rdr3): graphic natives flickering
1 parent 06d4d34 commit ced89ef

1 file changed

Lines changed: 36 additions & 16 deletions

File tree

code/components/extra-natives-rdr3/src/GraphicsNatives.cpp

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "Hooking.Stubs.h"
77
#include "GamePrimitives.h"
88
#include "scrEngine.h"
9+
#include <nutsnbolts.h>
10+
#include <DrawCommands.h>
911

1012
enum ScriptImDrawType : uint32_t
1113
{
@@ -28,6 +30,9 @@ struct ScriptImRequest
2830

2931
static constexpr int kMaxScriptImRequests = 1024;
3032
static std::vector<ScriptImRequest> g_scriptImRequests{};
33+
static std::vector<ScriptImRequest> g_scriptImRenderBuffer{};
34+
35+
static std::atomic<bool> g_scriptImReady{false};
3136

3237
static ScriptImRequest** g_scriptImBuffer;
3338
static uint16_t* g_scriptImEntriesCount;
@@ -43,20 +48,28 @@ static void RenderScriptIm()
4348
// The game never uses this buffer itself, but it *may* be changed in the future updates.
4449
// This code isn't ready for such a scenario, so might potentially require tweaks.
4550
// Like if something allocate script im buffer before us, we would need to resize it
46-
// and not just rewrite everything without custom stuff.
47-
48-
if (g_scriptImRequests.empty())
51+
// and not just rewrite everything without custom stuff.
52+
53+
// Wait until the main thread is done for this frame before pushing new requests
54+
if (g_scriptImReady.load(std::memory_order_acquire))
55+
{
56+
g_scriptImRenderBuffer.clear();
57+
std::swap(g_scriptImRequests, g_scriptImRenderBuffer);
58+
g_scriptImReady.store(false, std::memory_order_relaxed);
59+
}
60+
61+
if (g_scriptImRenderBuffer.empty())
4962
{
5063
return;
5164
}
5265

53-
*g_scriptImEntriesCount = g_scriptImRequests.size();
66+
*g_scriptImEntriesCount = g_scriptImRenderBuffer.size();
5467

5568
// If the buffer isn't allocated, let's do it.
5669
if (!*g_scriptImBuffer)
5770
{
5871
initScriptImBuffer();
59-
}
72+
}
6073

6174
// Failed to allocate? Bail out.
6275
if (!*g_scriptImBuffer)
@@ -66,11 +79,9 @@ static void RenderScriptIm()
6679
}
6780

6881
// Move stuff from our temp vector to the in-game buffer.
69-
std::move(g_scriptImRequests.begin(), g_scriptImRequests.end(), *g_scriptImBuffer);
82+
std::copy(g_scriptImRenderBuffer.begin(), g_scriptImRenderBuffer.end(), *g_scriptImBuffer);
7083

7184
g_origRenderScriptIm();
72-
73-
g_scriptImRequests.clear();
7485
*g_scriptImEntriesCount = 0;
7586
}
7687

@@ -90,8 +101,8 @@ struct DrawOriginStore
90101

91102
static bool (*isGamePaused)();
92103

93-
static int* g_frameDrawIndex1;
94-
static int* g_frameDrawIndex2;
104+
static int* g_renderBufferIndex;
105+
static int* g_updateBufferIndex;
95106
static DrawOriginStore* g_drawOriginStore;
96107
static uint32_t* g_scriptDrawOriginIndex;
97108

@@ -124,8 +135,8 @@ static HookFunction hookFunction([]()
124135
{
125136
auto location = hook::get_pattern<char>("48 69 D0 10 04 00 00 48 8D 05 ? ? ? ? 48 03");
126137

127-
g_frameDrawIndex1 = hook::get_address<int*>(location - 20);
128-
g_frameDrawIndex2 = hook::get_address<int*>(location - 7);
138+
g_renderBufferIndex = hook::get_address<int*>(location - 20);
139+
g_updateBufferIndex = hook::get_address<int*>(location - 7);
129140
g_drawOriginStore = hook::get_address<DrawOriginStore*>(location + 10);
130141

131142
hook::set_call(&isGamePaused, location - 27);
@@ -153,13 +164,22 @@ static HookFunction hookFunction([]()
153164

154165
g_screenWidth = hook::get_address<int*>(location + 2);
155166
g_screenHeight = hook::get_address<int*>(location + 8);
156-
}
167+
}
168+
169+
OnMainGameFrame.Connect([]()
170+
{
171+
g_scriptImRequests.clear();
172+
g_scriptImReady.store(false, std::memory_order_relaxed);
173+
});
174+
175+
OnPostFrontendRender.Connect([]()
176+
{
177+
g_scriptImReady.store(true, std::memory_order_release);
178+
});
157179

158180
fx::ScriptEngine::RegisterNativeHandler("SET_DRAW_ORIGIN", [](fx::ScriptContext& context)
159181
{
160-
auto drawIndex = *(isGamePaused() ? g_frameDrawIndex2 : g_frameDrawIndex1);
161-
162-
auto& store = g_drawOriginStore[drawIndex];
182+
auto& store = g_drawOriginStore[*g_renderBufferIndex];
163183
const auto index = store.m_count;
164184

165185
if (index >= 32)

0 commit comments

Comments
 (0)