- remove old vid_maxfps implementations as they were garbage anyway and the new one works on all the platforms

This commit is contained in:
Magnus Norddahl 2019-03-26 11:10:17 +01:00
parent 6078428b84
commit 9f0f659db0
14 changed files with 44 additions and 281 deletions

View file

@ -145,18 +145,7 @@ static int oldentertics;
extern bool advancedemo; extern bool advancedemo;
CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
// Do not use the separate FPS limit timer if we are limiting FPS with this.
if (self)
{
I_SetFPSLimit(0);
}
else
{
I_SetFPSLimit(-1);
}
}
CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE) CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE)
CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE) CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE)

View file

@ -727,16 +727,6 @@ void I_InitGraphics()
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
EXTERN_CVAR(Int, vid_maxfps);
EXTERN_CVAR(Bool, cl_capfps);
// So Apple doesn't support POSIX timers and I can't find a good substitute short of
// having Objective-C Cocoa events or something like that.
void I_SetFPSLimit(int limit)
{
}
CUSTOM_CVAR(Bool, vid_hidpi, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) CUSTOM_CVAR(Bool, vid_hidpi, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{ {
SystemBaseFrameBuffer::UseHiDPI(self); SystemBaseFrameBuffer::UseHiDPI(self);

View file

@ -37,37 +37,4 @@
#include "i_video.h" #include "i_video.h"
#include "v_video.h" #include "v_video.h"
// Semaphores
#ifdef __APPLE__
#include <mach/mach_init.h>
#include <mach/semaphore.h>
#include <mach/task.h>
typedef semaphore_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
while(semaphore_wait(sem) != KERN_SUCCESS){}
#define SEMAPHORE_SIGNAL(sem) \
semaphore_signal(sem);
#define SEMAPHORE_INIT(sem, shared, value) \
semaphore_create(mach_task_self(), &sem, shared, value);
#else
#include <semaphore.h>
typedef sem_t Semaphore;
#define SEMAPHORE_WAIT(sem) \
do { \
while(sem_wait(&sem) != 0); \
int semValue; \
sem_getvalue(&sem, &semValue); \
if(semValue < 1) \
break; \
} while(true);
#define SEMAPHORE_SIGNAL(sem) \
sem_post(&sem);
#define SEMAPHORE_INIT(sem, shared, value) \
sem_init(&sem, shared, value);
#endif
extern Semaphore FPSLimitSemaphore;
void I_SetFPSLimit(int limit);
#endif // __HARDWARE_H__ #endif // __HARDWARE_H__

View file

@ -85,82 +85,3 @@ void I_InitGraphics ()
atterm (I_ShutdownGraphics); atterm (I_ShutdownGraphics);
} }
/** Remaining code is common to Win32 and Linux **/
// VIDEO WRAPPERS ---------------------------------------------------------
//==========================================================================
//
// SetFPSLimit
//
// Initializes an event timer to fire at a rate of <limit>/sec. The video
// update will wait for this timer to trigger before updating.
//
// Pass 0 as the limit for unlimited.
// Pass a negative value for the limit to use the value of vid_maxfps.
//
//==========================================================================
EXTERN_CVAR(Int, vid_maxfps);
EXTERN_CVAR(Bool, cl_capfps);
#if !defined(__APPLE__) && !defined(__OpenBSD__)
Semaphore FPSLimitSemaphore;
static void FPSLimitNotify(sigval val)
{
SEMAPHORE_SIGNAL(FPSLimitSemaphore)
}
void I_SetFPSLimit(int limit)
{
static sigevent FPSLimitEvent;
static timer_t FPSLimitTimer;
static bool FPSLimitTimerEnabled = false;
static bool EventSetup = false;
if(!EventSetup)
{
EventSetup = true;
FPSLimitEvent.sigev_notify = SIGEV_THREAD;
FPSLimitEvent.sigev_signo = 0;
FPSLimitEvent.sigev_value.sival_int = 0;
FPSLimitEvent.sigev_notify_function = FPSLimitNotify;
FPSLimitEvent.sigev_notify_attributes = NULL;
SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0)
}
if (limit < 0)
{
limit = vid_maxfps;
}
// Kill any leftover timer.
if (FPSLimitTimerEnabled)
{
timer_delete(FPSLimitTimer);
FPSLimitTimerEnabled = false;
}
if (limit == 0)
{ // no limit
DPrintf(DMSG_NOTIFY, "FPS timer disabled\n");
}
else
{
FPSLimitTimerEnabled = true;
if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1)
Printf(DMSG_WARNING, "Failed to create FPS limiter event\n");
itimerspec period = { {0, 0}, {0, 0} };
period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit;
if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1)
Printf(DMSG_WARNING, "Failed to set FPS limiter timer\n");
DPrintf(DMSG_NOTIFY, "FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000);
}
}
#else
// So Apple doesn't support POSIX timers and I can't find a good substitute short of
// having Objective-C Cocoa events or something like that.
void I_SetFPSLimit(int limit)
{
}
#endif

View file

@ -71,7 +71,6 @@ extern IVideo *Video;
EXTERN_CVAR (Int, vid_adapter) EXTERN_CVAR (Int, vid_adapter)
EXTERN_CVAR (Int, vid_displaybits) EXTERN_CVAR (Int, vid_displaybits)
EXTERN_CVAR (Int, vid_maxfps)
EXTERN_CVAR (Int, vid_defwidth) EXTERN_CVAR (Int, vid_defwidth)
EXTERN_CVAR (Int, vid_defheight) EXTERN_CVAR (Int, vid_defheight)
EXTERN_CVAR (Int, vid_backend) EXTERN_CVAR (Int, vid_backend)
@ -488,13 +487,6 @@ void SystemGLFrameBuffer::SetVSync( bool vsync )
void SystemGLFrameBuffer::SwapBuffers() void SystemGLFrameBuffer::SwapBuffers()
{ {
#if !defined(__APPLE__) && !defined(__OpenBSD__)
if (vid_maxfps && !cl_capfps)
{
SEMAPHORE_WAIT(FPSLimitSemaphore)
}
#endif
SDL_GL_SwapWindow(Priv::window); SDL_GL_SwapWindow(Priv::window);
} }

View file

@ -250,6 +250,7 @@ void OpenGLFrameBuffer::Swap()
Finish.Reset(); Finish.Reset();
Finish.Clock(); Finish.Clock();
if (swapbefore) glFinish(); if (swapbefore) glFinish();
FPSLimit();
SwapBuffers(); SwapBuffers();
if (!swapbefore) glFinish(); if (!swapbefore) glFinish();
Finish.Unclock(); Finish.Unclock();

View file

@ -59,14 +59,9 @@
#include "vulkan/system/vk_swapchain.h" #include "vulkan/system/vk_swapchain.h"
#include "doomerrors.h" #include "doomerrors.h"
#include <chrono>
#include <thread>
void Draw2D(F2DDrawer *drawer, FRenderState &state); void Draw2D(F2DDrawer *drawer, FRenderState &state);
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown); void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
EXTERN_CVAR(Bool, vid_vsync)
EXTERN_CVAR(Int, vid_maxfps)
EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Bool, r_drawvoxels)
EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Int, gl_tonemap)
EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Int, screenblocks)
@ -223,40 +218,6 @@ void VulkanFrameBuffer::Update()
Super::Update(); Super::Update();
} }
void VulkanFrameBuffer::FPSLimit()
{
using namespace std::chrono;
using namespace std::this_thread;
if (vid_maxfps <= 0 || vid_vsync)
return;
uint64_t targetWakeTime = fpsLimitTime + 1'000'000 / vid_maxfps;
while (true)
{
fpsLimitTime = duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
int64_t timeToWait = targetWakeTime - fpsLimitTime;
if (timeToWait > 1'000'000 || timeToWait <= 0)
{
break;
}
if (timeToWait <= 2'000'000)
{
// We are too close to the deadline. OS sleep is not precise enough to wake us before it elapses.
// Yield execution and check time again.
sleep_for(nanoseconds(0));
}
else
{
// Sleep, but try to wake before deadline.
sleep_for(microseconds(timeToWait - 1'000'000));
}
}
}
void VulkanFrameBuffer::DeleteFrameObjects() void VulkanFrameBuffer::DeleteFrameObjects()
{ {
FrameDeleteList.Images.clear(); FrameDeleteList.Images.clear();

View file

@ -107,7 +107,6 @@ private:
void CopyScreenToBuffer(int w, int h, void *data); void CopyScreenToBuffer(int w, int h, void *data);
void UpdateShadowMap(); void UpdateShadowMap();
void DeleteFrameObjects(); void DeleteFrameObjects();
void FPSLimit();
std::unique_ptr<VkShaderManager> mShaderManager; std::unique_ptr<VkShaderManager> mShaderManager;
std::unique_ptr<VkSamplerManager> mSamplerManager; std::unique_ptr<VkSamplerManager> mSamplerManager;
@ -132,8 +131,6 @@ private:
int lastSwapWidth = 0; int lastSwapWidth = 0;
int lastSwapHeight = 0; int lastSwapHeight = 0;
uint64_t fpsLimitTime = 0;
}; };
inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast<VulkanFrameBuffer*>(screen); } inline VulkanFrameBuffer *GetVulkanFrameBuffer() { return static_cast<VulkanFrameBuffer*>(screen); }

View file

@ -52,6 +52,9 @@
#include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/data/flatvertices.h" #include "hwrenderer/data/flatvertices.h"
#include <chrono>
#include <thread>
CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE); CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE);
CVAR(Bool, vid_fps, false, 0) CVAR(Bool, vid_fps, false, 0)
@ -60,6 +63,9 @@ CVAR(Int, vid_showpalette, 0, 0)
EXTERN_CVAR(Bool, ticker) EXTERN_CVAR(Bool, ticker)
EXTERN_CVAR(Float, vid_brightness) EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast) EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Bool, vid_vsync)
EXTERN_CVAR(Int, vid_maxfps)
EXTERN_CVAR(Bool, cl_capfps)
EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Int, screenblocks)
//========================================================================== //==========================================================================
@ -415,3 +421,37 @@ void DFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y)
x = int16_t((x - letterboxX) * Width / letterboxWidth); x = int16_t((x - letterboxX) * Width / letterboxWidth);
y = int16_t((y - letterboxY) * Height / letterboxHeight); y = int16_t((y - letterboxY) * Height / letterboxHeight);
} }
void DFrameBuffer::FPSLimit()
{
using namespace std::chrono;
using namespace std::this_thread;
if (vid_maxfps <= 0 || vid_vsync || cl_capfps)
return;
uint64_t targetWakeTime = fpsLimitTime + 1'000'000 / vid_maxfps;
while (true)
{
fpsLimitTime = duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
int64_t timeToWait = targetWakeTime - fpsLimitTime;
if (timeToWait > 1'000'000 || timeToWait <= 0)
{
break;
}
if (timeToWait <= 2'000)
{
// We are too close to the deadline. OS sleep is not precise enough to wake us before it elapses.
// Yield execution and check time again.
sleep_for(nanoseconds(0));
}
else
{
// Sleep, but try to wake before deadline.
sleep_for(microseconds(timeToWait - 2'000));
}
}
}

View file

@ -70,7 +70,6 @@
#include "g_levellocals.h" #include "g_levellocals.h"
#include "am_map.h" #include "am_map.h"
EXTERN_CVAR(Bool, cl_capfps)
EXTERN_CVAR(Int, menu_resolution_custom_width) EXTERN_CVAR(Int, menu_resolution_custom_width)
EXTERN_CVAR(Int, menu_resolution_custom_height) EXTERN_CVAR(Int, menu_resolution_custom_height)
@ -90,10 +89,6 @@ CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{ {
vid_maxfps = 1000; vid_maxfps = 1000;
} }
else if (cl_capfps == 0)
{
I_SetFPSLimit(vid_maxfps);
}
} }
CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)

View file

@ -540,6 +540,7 @@ public:
int ScreenToWindowX(int x); int ScreenToWindowX(int x);
int ScreenToWindowY(int y); int ScreenToWindowY(int y);
void FPSLimit();
// Retrieves a buffer containing image data for a screenshot. // Retrieves a buffer containing image data for a screenshot.
// Hint: Pitch can be negative for upside-down images, in which case buffer // Hint: Pitch can be negative for upside-down images, in which case buffer
@ -556,6 +557,7 @@ protected:
void DrawRateStuff (); void DrawRateStuff ();
private: private:
uint64_t fpsLimitTime = 0;
uint64_t LastMS = 0, LastSec = 0, FrameCount = 0, LastCount = 0, LastTic = 0; uint64_t LastMS = 0, LastSec = 0, FrameCount = 0, LastCount = 0, LastTic = 0;

View file

@ -123,8 +123,6 @@ void SystemGLFrameBuffer::SetVSync (bool vsync)
void SystemGLFrameBuffer::SwapBuffers() void SystemGLFrameBuffer::SwapBuffers()
{ {
// Limiting the frame rate is as simple as waiting for the timer to signal this event.
I_FPSLimit();
::SwapBuffers(static_cast<Win32GLVideo *>(Video)->m_hDC); ::SwapBuffers(static_cast<Win32GLVideo *>(Video)->m_hDC);
} }

View file

@ -51,7 +51,6 @@
#include "i_system.h" #include "i_system.h"
#include "swrenderer/r_swrenderer.h" #include "swrenderer/r_swrenderer.h"
EXTERN_CVAR(Int, vid_maxfps)
EXTERN_CVAR(Int, vid_backend) EXTERN_CVAR(Int, vid_backend)
extern HWND Window; extern HWND Window;
@ -154,88 +153,3 @@ void I_InitGraphics ()
atterm (I_ShutdownGraphics); atterm (I_ShutdownGraphics);
} }
static UINT FPSLimitTimer;
HANDLE FPSLimitEvent;
//==========================================================================
//
// SetFPSLimit
//
// Initializes an event timer to fire at a rate of <limit>/sec. The video
// update will wait for this timer to trigger before updating.
//
// Pass 0 as the limit for unlimited.
// Pass a negative value for the limit to use the value of vid_maxfps.
//
//==========================================================================
static void StopFPSLimit()
{
I_SetFPSLimit(0);
}
void I_SetFPSLimit(int limit)
{
if (limit < 0)
{
limit = vid_maxfps;
}
// Kill any leftover timer.
if (FPSLimitTimer != 0)
{
timeKillEvent(FPSLimitTimer);
FPSLimitTimer = 0;
}
if (limit == 0)
{ // no limit
if (FPSLimitEvent != NULL)
{
CloseHandle(FPSLimitEvent);
FPSLimitEvent = NULL;
}
DPrintf(DMSG_NOTIFY, "FPS timer disabled\n");
}
else
{
if (FPSLimitEvent == NULL)
{
FPSLimitEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
if (FPSLimitEvent == NULL)
{ // Could not create event, so cannot use timer.
Printf(DMSG_WARNING, "Failed to create FPS limitter event\n");
return;
}
}
atterm(StopFPSLimit);
// Set timer event as close as we can to limit/sec, in milliseconds.
UINT period = 1000 / limit;
FPSLimitTimer = timeSetEvent(period, 0, (LPTIMECALLBACK)FPSLimitEvent, 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
if (FPSLimitTimer == 0)
{
CloseHandle(FPSLimitEvent);
FPSLimitEvent = NULL;
Printf("Failed to create FPS limiter timer\n");
return;
}
DPrintf(DMSG_NOTIFY, "FPS timer set to %u ms\n", period);
}
}
//==========================================================================
//
// StopFPSLimit
//
// Used for cleanup during application shutdown.
//
//==========================================================================
void I_FPSLimit()
{
if (FPSLimitEvent != NULL)
{
WaitForSingleObject(FPSLimitEvent, 1000);
}
}

View file

@ -37,8 +37,4 @@
#include "i_video.h" #include "i_video.h"
#include "v_video.h" #include "v_video.h"
void I_SetFPSLimit(int limit);
void I_FPSLimit();
#endif // __HARDWARE_H__ #endif // __HARDWARE_H__