Skip to content

Commit

Permalink
Moved device creation into primary thread
Browse files Browse the repository at this point in the history
  • Loading branch information
Xottab-DUTY committed Jul 6, 2019
1 parent a815afb commit b21c156
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 75 deletions.
27 changes: 27 additions & 0 deletions src/xrEngine/Device_create.cpp
Expand Up @@ -7,6 +7,7 @@
#include "MonitorManager.hpp"
#include "SDL.h"
#include "SDL_syswm.h"
#include "TaskScheduler.hpp"

extern u32 Vid_SelectedMonitor;
extern u32 Vid_SelectedRefreshRate;
Expand All @@ -27,6 +28,32 @@ void CRenderDevice::_SetupStates()
}

void CRenderDevice::Create()
{
if (b_is_Ready)
return; // prevent double call

GEnv.Render->MakeContextCurrent(false);

// Start all threads
mt_bMustExit = FALSE;

thread_name("X-Ray Window thread");
thread_spawn(PrimaryThreadProc, "X-RAY Primary thread", 0, this);
thread_spawn(SecondaryThreadProc, "X-Ray Secondary thread", 0, this);
// thread_spawn(RenderThreadProc, "X-Ray Render thread", 0, this);

TaskScheduler = std::make_unique<TaskManager>();
TaskScheduler->Initialize();
}

void CRenderDevice::WaitUntilCreated()
{
while (!deviceCreated.Wait(MaximalWaitTime))
SDL_PumpEvents();
GEnv.Render->MakeContextCurrent(true);
}

void CRenderDevice::CreateInternal()
{
if (b_is_Ready)
return; // prevent double call
Expand Down
8 changes: 7 additions & 1 deletion src/xrEngine/Device_destroy.cpp
Expand Up @@ -36,11 +36,17 @@ void CRenderDevice::Destroy()
SDL_DestroyWindow(m_sdlWnd);
}

void CRenderDevice::Reset(bool precache /*= true*/)
{
shouldReset = true;
precacheWhileReset = precache;
}

#include "IGame_Level.h"
#include "CustomHUD.h"
extern BOOL bNeed_re_create_env;

void CRenderDevice::Reset(bool precache)
void CRenderDevice::ResetInternal(bool precache)
{
TaskScheduler->RemoveTasksWithType(Task::Type::Renderer);

Expand Down
4 changes: 2 additions & 2 deletions src/xrEngine/FDemoRecord.cpp
Expand Up @@ -201,7 +201,7 @@ void CDemoRecord::MakeLevelMapProcess()
psDeviceFlags.zero();
psDeviceFlags.set(rsClearBB | rsFullscreen | rsDrawStatic, TRUE);
if (!psDeviceFlags.equal(s_dev_flags, rsFullscreen))
Device.RequireReset();
Device.Reset();
}
break;

Expand Down Expand Up @@ -236,7 +236,7 @@ void CDemoRecord::MakeLevelMapProcess()
BOOL bDevReset = !psDeviceFlags.equal(s_dev_flags, rsFullscreen);
psDeviceFlags = s_dev_flags;
if (bDevReset)
Device.RequireReset();
Device.Reset();
m_bMakeLevelMap = FALSE;
m_iLMScreenshotFragment = -1;
}
Expand Down
84 changes: 26 additions & 58 deletions src/xrEngine/device.cpp
Expand Up @@ -55,7 +55,7 @@ bool CRenderDevice::RenderBegin()
if (GEnv.isDedicatedServer)
return true;

switch (LastDeviceState)
switch (GEnv.Render->GetDeviceState())
{
case DeviceState::Normal: break;
case DeviceState::Lost:
Expand All @@ -65,7 +65,7 @@ bool CRenderDevice::RenderBegin()

case DeviceState::NeedReset:
// Check if the device is ready to be reset
RequireReset();
ResetInternal();
return false;

default: R_ASSERT(0);
Expand Down Expand Up @@ -167,8 +167,21 @@ void CRenderDevice::PrimaryThreadProc(void* context)
{
auto& device = *static_cast<CRenderDevice*>(context);

SDL_Event resetCheck;
bool shouldSwitch = true; // always switch for the first time
device.deviceCreated.Reset();
GEnv.Render->MakeContextCurrent(true);

device.CreateInternal();

GEnv.Render->MakeContextCurrent(false);
device.deviceCreated.Set();

device.deviceReadyToRun.Wait(); // ping
GEnv.Render->MakeContextCurrent(true);

device.seqAppStart.Process();
GEnv.Render->ClearTarget();

device.deviceReadyToRun.Set(); // pong

while (true)
{
Expand All @@ -180,24 +193,15 @@ void CRenderDevice::PrimaryThreadProc(void* context)
return;
}

if (shouldSwitch)
if (device.shouldReset)
{
GEnv.Render->MakeContextCurrent(true);
shouldSwitch = false;
device.ResetInternal(device.precacheWhileReset);
device.shouldReset = false;
device.precacheWhileReset = false;
}

device.ProcessFrame();

if (SDL_PeepEvents(&resetCheck, 1,
SDL_PEEKEVENT, SDL_USEREVENT, SDL_USEREVENT))
{
if (resetCheck.user.type == device.resetEventId)
{
shouldSwitch = true;
GEnv.Render->MakeContextCurrent(false);
}
}

device.primaryFrameDone.Set();
}
}
Expand Down Expand Up @@ -411,8 +415,6 @@ void CRenderDevice::message_loop()
return;
}

GEnv.Render->MakeContextCurrent(false);

bool timedOut = false;

while (!SDL_QuitRequested()) // SDL_PumpEvents is here
Expand All @@ -423,15 +425,6 @@ void CRenderDevice::message_loop()
{
count = SDL_PeepEvents(events, MAX_WINDOW_EVENTS,
SDL_GETEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT);

// We need to collect only SDL_USEREVENT,
// Other types of events should not be collected
// Let's do this like that:
if (count < MAX_WINDOW_EVENTS)
{
count += SDL_PeepEvents(events + count, MAX_WINDOW_EVENTS - count,
SDL_GETEVENT, SDL_USEREVENT, SDL_USEREVENT);
}
}

for (int i = 0; i < count; ++i)
Expand All @@ -440,16 +433,6 @@ void CRenderDevice::message_loop()

switch (event.type)
{
case SDL_USEREVENT:
{
if (event.user.type == resetEventId)
{
GEnv.Render->MakeContextCurrent(true);
Reset(event.user.code);
GEnv.Render->MakeContextCurrent(false);
}
break;
}
case SDL_WINDOWEVENT:
{
switch (event.window.event)
Expand All @@ -470,9 +453,7 @@ void CRenderDevice::message_loop()
xr_sprintf(buff, sizeof(buff), "vid_mode %dx%d", event.window.data1, event.window.data2);
Console->Execute(buff);

GEnv.Render->MakeContextCurrent(true);
Reset();
GEnv.Render->MakeContextCurrent(false);
}
else
UpdateWindowRects();
Expand Down Expand Up @@ -511,11 +492,10 @@ void CRenderDevice::message_loop()

if (!timedOut)
{
LastDeviceState = GEnv.Render->GetDeviceState();
primaryProcessFrame.Set();
}

timedOut = !primaryFrameDone.Wait(33);
timedOut = !primaryFrameDone.Wait(MaximalWaitTime);
}

if (timedOut)
Expand All @@ -526,7 +506,6 @@ void CRenderDevice::Run()
{
g_bLoaded = FALSE;
Log("Starting engine...");
thread_name("X-RAY Window thread");

// Startup timers and calculate timer delta
dwTimeGlobal = 0;
Expand All @@ -540,22 +519,11 @@ void CRenderDevice::Run()
Timer_MM_Delta = time_system - time_local;
}

resetEventId = SDL_RegisterEvents(1);
R_ASSERT2(resetEventId != u32(-1), "Failed to allocate Device reset SDL event.");

// Start all threads
mt_bMustExit = FALSE;

thread_spawn(PrimaryThreadProc, "X-RAY Primary thread", 0, this);
thread_spawn(SecondaryThreadProc, "X-RAY Secondary thread", 0, this);
// thread_spawn(RenderThreadProc, "X-RAY Render thread", 0, this);

TaskScheduler.reset(new TaskManager());
TaskScheduler->Initialize();

// Pre start
seqAppStart.Process();
GEnv.Render->ClearTarget();
GEnv.Render->MakeContextCurrent(false);
deviceReadyToRun.Set(); // ping
deviceReadyToRun.Wait(); // pong

splash::hide();
SDL_HideWindow(m_sdlWnd);
SDL_ShowWindow(m_sdlWnd);
Expand Down
24 changes: 14 additions & 10 deletions src/xrEngine/device.h
Expand Up @@ -58,6 +58,8 @@ class ENGINE_API IRenderDevice
class ENGINE_API CRenderDeviceData
{
public:
static constexpr u32 MaximalWaitTime = 33; // ms

// Rendering resolution
u32 dwWidth;
u32 dwHeight;
Expand Down Expand Up @@ -257,18 +259,19 @@ class ENGINE_API CRenderDevice : public CRenderDeviceBase, public IWindowHandler
IC CTimer_paused* GetTimerGlobal() { return &TimerGlobal; }
u32 TimerAsync() { return TimerGlobal.GetElapsed_ms(); }
u32 TimerAsync_MMT() { return TimerMM.GetElapsed_ms() + Timer_MM_Delta; }

private:
// Creation & Destroying
void Create(void);
void CreateInternal();
void ResetInternal(bool precache = true);

public:
void Create();
void WaitUntilCreated();

void Run(void);
void Destroy(void);
void Reset(bool precache = true);
void RequireReset(bool doPrecache = true) const
{
SDL_Event reset = { SDL_USEREVENT };
reset.user.type = resetEventId;
reset.user.code = doPrecache;
SDL_PushEvent(&reset);
}

void UpdateWindowProps(const bool windowed);
void UpdateWindowRects();
Expand Down Expand Up @@ -296,9 +299,10 @@ class ENGINE_API CRenderDevice : public CRenderDeviceBase, public IWindowHandler
}

private:
DeviceState LastDeviceState;
u32 resetEventId;
std::atomic<bool> shouldReset;
std::atomic<bool> precacheWhileReset;
std::atomic<bool> mtProcessingAllowed;
Event deviceCreated, deviceReadyToRun;
Event primaryProcessFrame, primaryFrameDone, primaryThreadExit; // Primary thread events
Event syncProcessFrame, syncFrameDone, syncThreadExit; // Secondary thread events
Event renderProcessFrame, renderFrameDone, renderThreadExit; // Render thread events
Expand Down
6 changes: 4 additions & 2 deletions src/xrEngine/main.cpp
Expand Up @@ -265,10 +265,12 @@ ENGINE_API void Startup()
Device.Create();
LALib.OnCreate();
pApp = new CApplication();
g_pGamePersistent = dynamic_cast<IGame_Persistent*>(NEW_INSTANCE(CLSID_GAME_PERSISTANT));
R_ASSERT(g_pGamePersistent);
g_SpatialSpace = new ISpatial_DB("Spatial obj");
g_SpatialSpacePhysic = new ISpatial_DB("Spatial phys");
Device.WaitUntilCreated();

g_pGamePersistent = dynamic_cast<IGame_Persistent*>(NEW_INSTANCE(CLSID_GAME_PERSISTANT));
R_ASSERT(g_pGamePersistent);

// Main cycle
Device.Run();
Expand Down
2 changes: 1 addition & 1 deletion src/xrEngine/x_ray.cpp
Expand Up @@ -236,7 +236,7 @@ void CApplication::OnEvent(EVENT E, u64 P1, u64 P2)

Console->Execute("main_menu off");
Console->Hide();
Device.RequireReset(false);
Device.Reset(false);

g_pGameLevel = smart_cast<IGame_Level*>(NEW_INSTANCE(CLSID_GAME_LEVEL));
VERIFY(g_pGameLevel);
Expand Down
1 change: 1 addition & 0 deletions src/xrEngine/xrSASH.cpp
Expand Up @@ -505,6 +505,7 @@ void xrSASH::TryInitEngine(bool bNoRun)
{
InitSound();
Device.Create();
Device.WaitUntilCreated();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/xrEngine/xr_ioc_cmd.cpp
Expand Up @@ -374,7 +374,7 @@ class CCC_VID_Reset : public IConsole_Command
{
if (Device.b_is_Ready)
{
Device.RequireReset();
Device.Reset();
}
}
};
Expand Down

0 comments on commit b21c156

Please sign in to comment.