1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00
Beef/BeefySysLib/BFApp.cpp
Brian Fiete b63a243fd7 Working on installer, fixing more Win32 issues
Throwing error on member references with ".." cascade token outside invocations (ie: "ts..mA = 123")
Fixed 'Thread.ModuleTLSIndex' error - which caused us TLS lookup failures in Beef DLLs
Fixed some hotswap errors
Made BeefPerf shut down properly
Fixed an 'int literal' FixIntUnknown issue where rhs was System.Object which caused an illegal boxing
Fixed COFF::LocateSymbol issues with Win32 and also with linking to static libraries - showed up with hot-linking in fmod when hot-adding a floating point mod
Fixed a couple memory leaks
Fixed alignment issue in COFF::ParseCompileUnit
2019-09-02 17:39:47 -07:00

274 lines
5.7 KiB
C++

#include "BFApp.h"
#include "BFWindow.h"
#include "gfx/RenderDevice.h"
#include "FileStream.h"
#include "util/BSpline.h"
#include "util/PerfTimer.h"
#include "sound/WwiseSound.h"
#include "util/AllocDebug.h"
#pragma warning(disable:4996)
USING_NS_BF;
BFApp* Beefy::gBFApp = NULL;
BFApp::BFApp()
{
mTitle = "Beefy Application";
mRefreshRate = 60;
mLastProcessTick = BFTickCount();
mFrameTimeAcc = 0;
mDrawEnabled = true;
mUpdateFunc = NULL;
mDrawFunc = NULL;
gBFApp = this;
mSysDialogCnt = 0;
mCursor = CURSOR_POINTER;
mInProcess = false;
mUpdateCnt = 0;
mNumPhysUpdates = 0;
mVSynched = true;
mMaxUpdatesPerDraw = 60; // 8?
mUpdateSampleCount = 0;
mUpdateSampleTimes = 0;
if (gPerfManager == NULL)
gPerfManager = new PerfManager();
mRunning = false;
mRenderDevice = NULL;
mVSynched = false;
}
BFApp::~BFApp()
{
gBFApp = NULL;
delete gPerfManager;
for (auto window : mPendingWindowDeleteList)
delete window;
}
void BFApp::Init()
{
}
void BFApp::Run()
{
}
void BFApp::Shutdown()
{
mRunning = false;
}
void BFApp::SetCursor(int cursor)
{
mCursor = cursor;
PhysSetCursor();
}
void BFApp::Update(bool batchStart)
{
//Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Update");
#ifdef BF_WWISE_ENABLED
WWiseUpdate();
#endif
mUpdateCnt++;
gPerfManager->NextFrame();
gPerfManager->ZoneStart("BFApp::Update");
mUpdateFunc(batchStart);
gPerfManager->ZoneEnd();
for (auto window : mPendingWindowDeleteList)
delete window;
mPendingWindowDeleteList.clear();
}
void BFApp::Draw()
{
gPerfManager->ZoneStart("BFApp::Draw");
mDrawFunc();
gPerfManager->ZoneEnd();
}
//#define PERIODIC_PERF_TIMING
void BFApp::Process()
{
//Beefy::DebugTimeGuard suspendTimeGuard(30, "BFApp::Process");
if (mInProcess)
return; // No reentry
mInProcess = true;
int updates;
uint32 tickNow = BFTickCount();
const int vSyncTestingPeriod = 250;
if (mRefreshRate != 0)
{
float ticksPerFrame = 1000.0f / mRefreshRate;
int ticksSinceLastProcess = tickNow - mLastProcessTick;
mUpdateSampleCount++;
mUpdateSampleTimes += ticksSinceLastProcess;
//TODO: Turn off mVSynched based on error calculations - (?)
// Two VSync failures in a row means we set mVSyncFailed and permanently disable it
if (mUpdateSampleTimes >= vSyncTestingPeriod)
{
int expectedFrames = (int)(mUpdateSampleTimes / ticksPerFrame);
if (mUpdateSampleCount > expectedFrames * 1.5)
{
if (!mVSynched)
mVSyncFailed = true;
mVSynched = false;
}
else
if (!mVSyncFailed)
mVSynched = true;
mUpdateSampleCount = 0;
mUpdateSampleTimes = 0;
}
mFrameTimeAcc += tickNow - mLastProcessTick;
bool vSynched = mVSynched;
if (vSynched)
{
// For the startup, try not to go hyper during those first samplings
if (mUpdateSampleTimes <= vSyncTestingPeriod)
{
if (ticksSinceLastProcess < ticksPerFrame / 1.5)
vSynched = false;
}
}
if (vSynched)
{
updates = std::max(1, (int)(mFrameTimeAcc / ticksPerFrame + 0.5f));
mFrameTimeAcc = std::max(0.0f, mFrameTimeAcc - ticksPerFrame * updates);
}
else
{
updates = std::max(0, (int)(mFrameTimeAcc / ticksPerFrame));
mFrameTimeAcc = mFrameTimeAcc - ticksPerFrame * updates;
}
if (updates > mRefreshRate)
{
// If more than 1 second of updates is queued, just re-sync
updates = 1;
mFrameTimeAcc = 0;
}
// Compensate for "slow start" by limiting the number of catchup-updates we can do when starting the app
int maxUpdates = BF_MIN(mNumPhysUpdates + 1, mMaxUpdatesPerDraw);
updates = BF_MIN(updates, maxUpdates);
/*if (updates > 2)
OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
}
else
updates = 1; // RefreshRate of 0 means to update as fast as possible
if (updates == 0)
{
// Yield
BfpThread_Sleep(1);
}
static uint32 lastUpdate = BFTickCount();
#ifdef PERIODIC_PERF_TIMING
bool perfTime = (tickNow - lastUpdate >= 5000) && (updates > 0);
if (perfTime)
{
updates = 1;
lastUpdate = tickNow;
if (perfTime)
gPerfManager->StartRecording();
}
#endif
if (updates > 0)
mNumPhysUpdates++;
for (int updateNum = 0; updateNum < updates; updateNum++)
{
if (!mRunning)
break;
Update(updateNum == 0);
}
if ((mRunning) && (updates > 0))
Draw();
#ifdef PERIODIC_PERF_TIMING
if (perfTime)
{
gPerfManager->StopRecording();
gPerfManager->DbgPrint();
}
#endif
mLastProcessTick = tickNow;
mInProcess = false;
}
void BFApp::RemoveWindow(BFWindow* window)
{
auto itr = std::find(mWindowList.begin(), mWindowList.end(), window);
if (itr == mWindowList.end()) // Allow benign failure (double removal)
return;
mWindowList.erase(itr);
while (window->mChildren.size() > 0)
RemoveWindow(window->mChildren.front());
if (window->mParent != NULL)
{
window->mParent->mChildren.erase(std::find(window->mParent->mChildren.begin(), window->mParent->mChildren.end(), window));
if (window->mFlags & BFWINDOW_MODAL)
{
bool hasModal = false;
for (auto childWindow : window->mParent->mChildren)
{
if (childWindow->mFlags & BFWINDOW_MODAL)
hasModal = true;
}
if (!hasModal)
window->mParent->ModalsRemoved();
}
}
window->mClosedFunc(window);
mRenderDevice->RemoveRenderWindow(window->mRenderWindow);
window->Destroy();
mPendingWindowDeleteList.push_back(window);
}
FileStream* BFApp::OpenBinaryFile(const StringImpl& fileName)
{
FILE* fP = fopen(fileName.c_str(), "rb");
if (fP == NULL)
return NULL;
FileStream* fileStream = new FileStream();
fileStream->mFP = fP;
return fileStream;
}