1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include <algorithm>
6 
7 #include "Common/CPUDetect.h"
8 #include "Common/CommonTypes.h"
9 #include "Common/StringUtil.h"
10 #include "Core/Config/GraphicsSettings.h"
11 #include "Core/ConfigManager.h"
12 #include "Core/Core.h"
13 #include "Core/Movie.h"
14 #include "VideoCommon/OnScreenDisplay.h"
15 #include "VideoCommon/VideoCommon.h"
16 #include "VideoCommon/VideoConfig.h"
17 
18 VideoConfig g_Config;
19 VideoConfig g_ActiveConfig;
20 static bool s_has_registered_callback = false;
21 
IsVSyncActive(bool enabled)22 static bool IsVSyncActive(bool enabled)
23 {
24   // Vsync is disabled when the throttler is disabled by the tab key.
25   return enabled && !Core::GetIsThrottlerTempDisabled() &&
26          SConfig::GetInstance().m_EmulationSpeed == 1.0;
27 }
28 
UpdateActiveConfig()29 void UpdateActiveConfig()
30 {
31   if (Movie::IsPlayingInput() && Movie::IsConfigSaved())
32     Movie::SetGraphicsConfig();
33   g_ActiveConfig = g_Config;
34   g_ActiveConfig.bVSyncActive = IsVSyncActive(g_ActiveConfig.bVSync);
35 }
36 
VideoConfig()37 VideoConfig::VideoConfig()
38 {
39   // Needed for the first frame, I think
40   fAspectRatioHackW = 1;
41   fAspectRatioHackH = 1;
42 
43   // disable all features by default
44   backend_info.api_type = APIType::Nothing;
45   backend_info.MaxTextureSize = 16384;
46   backend_info.bSupportsExclusiveFullscreen = false;
47   backend_info.bSupportsMultithreading = false;
48   backend_info.bSupportsST3CTextures = false;
49   backend_info.bSupportsBPTCTextures = false;
50 
51   bEnableValidationLayer = false;
52 
53 #if defined(ANDROID)
54   bBackendMultithreading = false;
55 #else
56   bBackendMultithreading = true;
57 #endif
58 }
59 
Refresh()60 void VideoConfig::Refresh()
61 {
62   if (!s_has_registered_callback)
63   {
64     // There was a race condition between the video thread and the host thread here, if
65     // corrections need to be made by VerifyValidity(). Briefly, the config will contain
66     // invalid values. Instead, pause emulation first, which will flush the video thread,
67     // update the config and correct it, then resume emulation, after which the video
68     // thread will detect the config has changed and act accordingly.
69     Config::AddConfigChangedCallback([]() { Core::RunAsCPUThread([]() { g_Config.Refresh(); }); });
70     s_has_registered_callback = true;
71   }
72 
73   bVSync = Config::Get(Config::GFX_VSYNC);
74   iAdapter = Config::Get(Config::GFX_ADAPTER);
75 
76   bWidescreenHack = Config::Get(Config::GFX_WIDESCREEN_HACK);
77   aspect_mode = Config::Get(Config::GFX_ASPECT_RATIO);
78   suggested_aspect_mode = Config::Get(Config::GFX_SUGGESTED_ASPECT_RATIO);
79   bCrop = Config::Get(Config::GFX_CROP);
80   iSafeTextureCache_ColorSamples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
81   bShowFPS = Config::Get(Config::GFX_SHOW_FPS);
82   bShowNetPlayPing = Config::Get(Config::GFX_SHOW_NETPLAY_PING);
83   bShowNetPlayMessages = Config::Get(Config::GFX_SHOW_NETPLAY_MESSAGES);
84   bLogRenderTimeToFile = Config::Get(Config::GFX_LOG_RENDER_TIME_TO_FILE);
85   bOverlayStats = Config::Get(Config::GFX_OVERLAY_STATS);
86   bOverlayProjStats = Config::Get(Config::GFX_OVERLAY_PROJ_STATS);
87   bDumpTextures = Config::Get(Config::GFX_DUMP_TEXTURES);
88   bDumpMipmapTextures = Config::Get(Config::GFX_DUMP_MIP_TEXTURES);
89   bDumpBaseTextures = Config::Get(Config::GFX_DUMP_BASE_TEXTURES);
90   bHiresTextures = Config::Get(Config::GFX_HIRES_TEXTURES);
91   bCacheHiresTextures = Config::Get(Config::GFX_CACHE_HIRES_TEXTURES);
92   bDumpEFBTarget = Config::Get(Config::GFX_DUMP_EFB_TARGET);
93   bDumpXFBTarget = Config::Get(Config::GFX_DUMP_XFB_TARGET);
94   bDumpFramesAsImages = Config::Get(Config::GFX_DUMP_FRAMES_AS_IMAGES);
95   bFreeLook = Config::Get(Config::GFX_FREE_LOOK);
96   iFreelookControlType = Config::Get(Config::GFX_FREE_LOOK_CONTROL_TYPE);
97   bUseFFV1 = Config::Get(Config::GFX_USE_FFV1);
98   sDumpFormat = Config::Get(Config::GFX_DUMP_FORMAT);
99   sDumpCodec = Config::Get(Config::GFX_DUMP_CODEC);
100   sDumpEncoder = Config::Get(Config::GFX_DUMP_ENCODER);
101   sDumpPath = Config::Get(Config::GFX_DUMP_PATH);
102   iBitrateKbps = Config::Get(Config::GFX_BITRATE_KBPS);
103   bInternalResolutionFrameDumps = Config::Get(Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS);
104   bEnableGPUTextureDecoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
105   bEnablePixelLighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
106   bFastDepthCalc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
107   iMultisamples = Config::Get(Config::GFX_MSAA);
108   bSSAA = Config::Get(Config::GFX_SSAA);
109   iEFBScale = Config::Get(Config::GFX_EFB_SCALE);
110   bTexFmtOverlayEnable = Config::Get(Config::GFX_TEXFMT_OVERLAY_ENABLE);
111   bTexFmtOverlayCenter = Config::Get(Config::GFX_TEXFMT_OVERLAY_CENTER);
112   bWireFrame = Config::Get(Config::GFX_ENABLE_WIREFRAME);
113   bDisableFog = Config::Get(Config::GFX_DISABLE_FOG);
114   bBorderlessFullscreen = Config::Get(Config::GFX_BORDERLESS_FULLSCREEN);
115   bEnableValidationLayer = Config::Get(Config::GFX_ENABLE_VALIDATION_LAYER);
116   bBackendMultithreading = Config::Get(Config::GFX_BACKEND_MULTITHREADING);
117   iCommandBufferExecuteInterval = Config::Get(Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL);
118   bShaderCache = Config::Get(Config::GFX_SHADER_CACHE);
119   bWaitForShadersBeforeStarting = Config::Get(Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
120   iShaderCompilationMode = Config::Get(Config::GFX_SHADER_COMPILATION_MODE);
121   iShaderCompilerThreads = Config::Get(Config::GFX_SHADER_COMPILER_THREADS);
122   iShaderPrecompilerThreads = Config::Get(Config::GFX_SHADER_PRECOMPILER_THREADS);
123 
124   bZComploc = Config::Get(Config::GFX_SW_ZCOMPLOC);
125   bZFreeze = Config::Get(Config::GFX_SW_ZFREEZE);
126   bDumpObjects = Config::Get(Config::GFX_SW_DUMP_OBJECTS);
127   bDumpTevStages = Config::Get(Config::GFX_SW_DUMP_TEV_STAGES);
128   bDumpTevTextureFetches = Config::Get(Config::GFX_SW_DUMP_TEV_TEX_FETCHES);
129   drawStart = Config::Get(Config::GFX_SW_DRAW_START);
130   drawEnd = Config::Get(Config::GFX_SW_DRAW_END);
131 
132   bForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
133   iMaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
134   sPostProcessingShader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
135   bForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
136   bDisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
137   bArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
138   fArbitraryMipmapDetectionThreshold =
139       Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD);
140 
141   stereo_mode = Config::Get(Config::GFX_STEREO_MODE);
142   iStereoDepth = Config::Get(Config::GFX_STEREO_DEPTH);
143   iStereoConvergencePercentage = Config::Get(Config::GFX_STEREO_CONVERGENCE_PERCENTAGE);
144   bStereoSwapEyes = Config::Get(Config::GFX_STEREO_SWAP_EYES);
145   iStereoConvergence = Config::Get(Config::GFX_STEREO_CONVERGENCE);
146   bStereoEFBMonoDepth = Config::Get(Config::GFX_STEREO_EFB_MONO_DEPTH);
147   iStereoDepthPercentage = Config::Get(Config::GFX_STEREO_DEPTH_PERCENTAGE);
148 
149   bEFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
150   bEFBAccessDeferInvalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
151   bBBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
152   bForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
153   bSkipEFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
154   bSkipXFBCopyToRam = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
155   bDisableCopyToVRAM = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
156   bDeferEFBCopies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
157   bImmediateXFB = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
158   bSkipPresentingDuplicateXFBs = Config::Get(Config::GFX_HACK_SKIP_DUPLICATE_XFBS);
159   bCopyEFBScaled = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
160   bEFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
161   bVertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUDING);
162   iEFBAccessTileSize = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);
163 
164   bPerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
165 
166   VerifyValidity();
167 }
168 
VerifyValidity()169 void VideoConfig::VerifyValidity()
170 {
171   // TODO: Check iMaxAnisotropy value
172   if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1))
173     iAdapter = 0;
174 
175   if (std::find(backend_info.AAModes.begin(), backend_info.AAModes.end(), iMultisamples) ==
176       backend_info.AAModes.end())
177     iMultisamples = 1;
178 
179   if (stereo_mode != StereoMode::Off)
180   {
181     if (!backend_info.bSupportsGeometryShaders)
182     {
183       OSD::AddMessage(
184           "Stereoscopic 3D isn't supported by your GPU, support for OpenGL 3.2 is required.",
185           10000);
186       stereo_mode = StereoMode::Off;
187     }
188   }
189 }
190 
UsingUberShaders() const191 bool VideoConfig::UsingUberShaders() const
192 {
193   return iShaderCompilationMode == ShaderCompilationMode::SynchronousUberShaders ||
194          iShaderCompilationMode == ShaderCompilationMode::AsynchronousUberShaders;
195 }
196 
GetNumAutoShaderCompilerThreads()197 static u32 GetNumAutoShaderCompilerThreads()
198 {
199   // Automatic number. We use clamp(cpus - 3, 1, 4).
200   return static_cast<u32>(std::min(std::max(cpu_info.num_cores - 3, 1), 4));
201 }
202 
GetShaderCompilerThreads() const203 u32 VideoConfig::GetShaderCompilerThreads() const
204 {
205   if (!backend_info.bSupportsBackgroundCompiling)
206     return 0;
207 
208   if (iShaderCompilerThreads >= 0)
209     return static_cast<u32>(iShaderCompilerThreads);
210   else
211     return GetNumAutoShaderCompilerThreads();
212 }
213 
GetShaderPrecompilerThreads() const214 u32 VideoConfig::GetShaderPrecompilerThreads() const
215 {
216   // When using background compilation, always keep the same thread count.
217   if (!bWaitForShadersBeforeStarting)
218     return GetShaderCompilerThreads();
219 
220   if (!backend_info.bSupportsBackgroundCompiling)
221     return 0;
222 
223   if (iShaderPrecompilerThreads >= 0)
224     return static_cast<u32>(iShaderPrecompilerThreads);
225   else
226     return GetNumAutoShaderCompilerThreads();
227 }
228