mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 13:57:57 -07:00
11ba623f26
Currently, we do not display every second frame in 25fps/30fps games which run to vsync. This improves performance as there's less rendering for the GPU to perform, but when combined with vsync, could cause frame pacing issues. This commit adds an option to force every frame generated by the console to be displayed to the host, which may improve pacing for these games.
225 lines
9.2 KiB
C++
225 lines
9.2 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <algorithm>
|
|
|
|
#include "Common/CPUDetect.h"
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/StringUtil.h"
|
|
#include "Core/Config/GraphicsSettings.h"
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
#include "Core/Movie.h"
|
|
#include "VideoCommon/OnScreenDisplay.h"
|
|
#include "VideoCommon/VideoCommon.h"
|
|
#include "VideoCommon/VideoConfig.h"
|
|
|
|
VideoConfig g_Config;
|
|
VideoConfig g_ActiveConfig;
|
|
static bool s_has_registered_callback = false;
|
|
|
|
static bool IsVSyncActive(bool enabled)
|
|
{
|
|
// Vsync is disabled when the throttler is disabled by the tab key.
|
|
return enabled && !Core::GetIsThrottlerTempDisabled() &&
|
|
SConfig::GetInstance().m_EmulationSpeed == 1.0;
|
|
}
|
|
|
|
void UpdateActiveConfig()
|
|
{
|
|
if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
|
|
Movie::SetGraphicsConfig();
|
|
g_ActiveConfig = g_Config;
|
|
g_ActiveConfig.bVSyncActive = IsVSyncActive(g_ActiveConfig.bVSync);
|
|
}
|
|
|
|
VideoConfig::VideoConfig()
|
|
{
|
|
// Needed for the first frame, I think
|
|
fAspectRatioHackW = 1;
|
|
fAspectRatioHackH = 1;
|
|
|
|
// disable all features by default
|
|
backend_info.api_type = APIType::Nothing;
|
|
backend_info.MaxTextureSize = 16384;
|
|
backend_info.bSupportsExclusiveFullscreen = false;
|
|
backend_info.bSupportsMultithreading = false;
|
|
backend_info.bSupportsST3CTextures = false;
|
|
backend_info.bSupportsBPTCTextures = false;
|
|
|
|
bEnableValidationLayer = false;
|
|
|
|
#if defined(ANDROID)
|
|
bBackendMultithreading = false;
|
|
#else
|
|
bBackendMultithreading = true;
|
|
#endif
|
|
}
|
|
|
|
void VideoConfig::Refresh()
|
|
{
|
|
if (!s_has_registered_callback)
|
|
{
|
|
// There was a race condition between the video thread and the host thread here, if
|
|
// corrections need to be made by VerifyValidity(). Briefly, the config will contain
|
|
// invalid values. Instead, pause emulation first, which will flush the video thread,
|
|
// update the config and correct it, then resume emulation, after which the video
|
|
// thread will detect the config has changed and act accordingly.
|
|
Config::AddConfigChangedCallback([]() { Core::RunAsCPUThread([]() { g_Config.Refresh(); }); });
|
|
s_has_registered_callback = true;
|
|
}
|
|
|
|
bVSync = Config::Get(Config::GFX_VSYNC);
|
|
iAdapter = Config::Get(Config::GFX_ADAPTER);
|
|
|
|
bWidescreenHack = Config::Get(Config::GFX_WIDESCREEN_HACK);
|
|
aspect_mode = Config::Get(Config::GFX_ASPECT_RATIO);
|
|
suggested_aspect_mode = Config::Get(Config::GFX_SUGGESTED_ASPECT_RATIO);
|
|
bCrop = Config::Get(Config::GFX_CROP);
|
|
iSafeTextureCache_ColorSamples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
|
|
bShowFPS = Config::Get(Config::GFX_SHOW_FPS);
|
|
bShowNetPlayPing = Config::Get(Config::GFX_SHOW_NETPLAY_PING);
|
|
bShowNetPlayMessages = Config::Get(Config::GFX_SHOW_NETPLAY_MESSAGES);
|
|
bLogRenderTimeToFile = Config::Get(Config::GFX_LOG_RENDER_TIME_TO_FILE);
|
|
bOverlayStats = Config::Get(Config::GFX_OVERLAY_STATS);
|
|
bOverlayProjStats = Config::Get(Config::GFX_OVERLAY_PROJ_STATS);
|
|
bDumpTextures = Config::Get(Config::GFX_DUMP_TEXTURES);
|
|
bHiresTextures = Config::Get(Config::GFX_HIRES_TEXTURES);
|
|
bCacheHiresTextures = Config::Get(Config::GFX_CACHE_HIRES_TEXTURES);
|
|
bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET);
|
|
bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET);
|
|
bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES);
|
|
bFreeLook = Config::Get(Config::GFX_FREE_LOOK);
|
|
bUseFFV1 = Config::Get(Config::GFX_USE_FFV1);
|
|
sDumpFormat = Config::Get(Config::GFX_DUMP_FORMAT);
|
|
sDumpCodec = Config::Get(Config::GFX_DUMP_CODEC);
|
|
sDumpEncoder = Config::Get(Config::GFX_DUMP_ENCODER);
|
|
sDumpPath = Config::Get(Config::GFX_DUMP_PATH);
|
|
iBitrateKbps = Config::Get(Config::GFX_BITRATE_KBPS);
|
|
bInternalResolutionFrameDumps = Config::Get(Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS);
|
|
bEnableGPUTextureDecoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
|
|
bEnablePixelLighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
|
|
bFastDepthCalc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
|
|
iMultisamples = Config::Get(Config::GFX_MSAA);
|
|
bSSAA = Config::Get(Config::GFX_SSAA);
|
|
iEFBScale = Config::Get(Config::GFX_EFB_SCALE);
|
|
bTexFmtOverlayEnable = Config::Get(Config::GFX_TEXFMT_OVERLAY_ENABLE);
|
|
bTexFmtOverlayCenter = Config::Get(Config::GFX_TEXFMT_OVERLAY_CENTER);
|
|
bWireFrame = Config::Get(Config::GFX_ENABLE_WIREFRAME);
|
|
bDisableFog = Config::Get(Config::GFX_DISABLE_FOG);
|
|
bBorderlessFullscreen = Config::Get(Config::GFX_BORDERLESS_FULLSCREEN);
|
|
bEnableValidationLayer = Config::Get(Config::GFX_ENABLE_VALIDATION_LAYER);
|
|
bBackendMultithreading = Config::Get(Config::GFX_BACKEND_MULTITHREADING);
|
|
iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL);
|
|
bShaderCache = Config::Get(Config::GFX_SHADER_CACHE);
|
|
bWaitForShadersBeforeStarting = Config::Get(Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
|
|
iShaderCompilationMode = Config::Get(Config::GFX_SHADER_COMPILATION_MODE);
|
|
iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS);
|
|
iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
|
|
|
|
bZComploc = Config::Get(Config::GFX_SW_ZCOMPLOC);
|
|
bZFreeze = Config::Get(Config::GFX_SW_ZFREEZE);
|
|
bDumpObjects = Config::Get(Config::GFX_SW_DUMP_OBJECTS);
|
|
bDumpTevStages = Config::Get(Config::GFX_SW_DUMP_TEV_STAGES);
|
|
bDumpTevTextureFetches = Config::Get(Config::GFX_SW_DUMP_TEV_TEX_FETCHES);
|
|
drawStart = Config::Get(Config::GFX_SW_DRAW_START);
|
|
drawEnd = Config::Get(Config::GFX_SW_DRAW_END);
|
|
|
|
bForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
|
iMaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
|
sPostProcessingShader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
|
|
bForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
|
|
bDisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
|
|
bArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
|
|
fArbitraryMipmapDetectionThreshold =
|
|
Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD);
|
|
|
|
stereo_mode = Config::Get(Config::GFX_STEREO_MODE);
|
|
iStereoDepth = Config::Get(Config::GFX_STEREO_DEPTH);
|
|
iStereoConvergencePercentage = Config::Get(Config::GFX_STEREO_CONVERGENCE_PERCENTAGE);
|
|
bStereoSwapEyes = Config::Get(Config::GFX_STEREO_SWAP_EYES);
|
|
iStereoConvergence = Config::Get(Config::GFX_STEREO_CONVERGENCE);
|
|
bStereoEFBMonoDepth = Config::Get(Config::GFX_STEREO_EFB_MONO_DEPTH);
|
|
iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE);
|
|
|
|
bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
|
|
bEFBAccessDeferInvalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
|
|
bBBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
|
|
bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
|
|
bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
|
|
bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
|
|
bDisableCopyToVRAM = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
|
bDeferEFBCopies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
|
|
bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
|
|
bSkipPresentingDuplicateXFBs = Config::Get(Config::GFX_HACK_SKIP_DUPLICATE_XFBS);
|
|
bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
|
|
bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
|
|
bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING);
|
|
iEFBAccessTileSize = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);
|
|
|
|
bPerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
|
|
|
|
VerifyValidity();
|
|
}
|
|
|
|
void VideoConfig::VerifyValidity()
|
|
{
|
|
// TODO: Check iMaxAnisotropy value
|
|
if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1))
|
|
iAdapter = 0;
|
|
|
|
if (std::find(backend_info.AAModes.begin(), backend_info.AAModes.end(), iMultisamples) ==
|
|
backend_info.AAModes.end())
|
|
iMultisamples = 1;
|
|
|
|
if (stereo_mode != StereoMode::Off)
|
|
{
|
|
if (!backend_info.bSupportsGeometryShaders)
|
|
{
|
|
OSD::AddMessage(
|
|
"Stereoscopic 3D isn't supported by your GPU, support for OpenGL 3.2 is required.",
|
|
10000);
|
|
stereo_mode = StereoMode::Off;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool VideoConfig::UsingUberShaders() const
|
|
{
|
|
return iShaderCompilationMode == ShaderCompilationMode::SynchronousUberShaders ||
|
|
iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders;
|
|
}
|
|
|
|
static u32 GetNumAutoShaderCompilerThreads()
|
|
{
|
|
// Automatic number. We use clamp(cpus - 3, 1, 4).
|
|
return static_cast<u32>(std::min(std::max(cpu_info.num_cores - 3, 1), 4));
|
|
}
|
|
|
|
u32 VideoConfig::GetShaderCompilerThreads() const
|
|
{
|
|
if (!backend_info.bSupportsBackgroundCompiling)
|
|
return 0;
|
|
|
|
if (iShaderCompilerThreads >= 0)
|
|
return static_cast<u32>(iShaderCompilerThreads);
|
|
else
|
|
return GetNumAutoShaderCompilerThreads();
|
|
}
|
|
|
|
u32 VideoConfig::GetShaderPrecompilerThreads() const
|
|
{
|
|
// When using background compilation, always keep the same thread count.
|
|
if (!bWaitForShadersBeforeStarting)
|
|
return GetShaderCompilerThreads();
|
|
|
|
if (!backend_info.bSupportsBackgroundCompiling)
|
|
return 0;
|
|
|
|
if (iShaderPrecompilerThreads >= 0)
|
|
return static_cast<u32>(iShaderPrecompilerThreads);
|
|
else
|
|
return GetNumAutoShaderCompilerThreads();
|
|
}
|