Get rid of a lot of ifdefs around presentation mode. Instead, set things dynamically.

This commit is contained in:
Henrik Rydgård 2023-08-13 13:33:38 +02:00
parent 870c45edd7
commit ff6e118fff
44 changed files with 220 additions and 139 deletions

View File

@ -1855,6 +1855,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/CoreTiming.h
Core/CwCheat.cpp
Core/CwCheat.h
Core/FrameTiming.cpp
Core/FrameTiming.h
Core/HDRemaster.cpp
Core/HDRemaster.h
Core/Instance.cpp

View File

@ -75,10 +75,6 @@ public:
return (uint32_t)ShaderLanguage::HLSL_D3D11;
}
uint32_t GetDataFormatSupport(DataFormat fmt) const override;
PresentMode GetPresentMode() const override {
// TODO: Fix. Not yet used.
return PresentMode::FIFO;
}
InputLayout *CreateInputLayout(const InputLayoutDesc &desc) override;
DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
@ -139,7 +135,7 @@ public:
void BeginFrame(DebugFlags debugFlags) override;
void EndFrame() override;
void Present(int vblanks) override;
void Present(PresentMode presentMode, int vblanks) override;
int GetFrameCount() override { return frameCount_; }
@ -284,6 +280,10 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
caps_.blendMinMaxSupported = true;
caps_.multiSampleLevelsMask = 1; // More could be supported with some work.
caps_.presentInstantModeChange = true;
caps_.presentMaxInterval = 4;
caps_.presentModesSupported = PresentMode::FIFO | PresentMode::IMMEDIATE;
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
if (SUCCEEDED(result)) {
@ -433,8 +433,12 @@ void D3D11DrawContext::EndFrame() {
curPipeline_ = nullptr;
}
void D3D11DrawContext::Present(int vblanks) {
swapChain_->Present(1, 0);
void D3D11DrawContext::Present(PresentMode presentMode, int vblanks) {
int interval = vblanks;
if (presentMode != PresentMode::FIFO) {
interval = 0;
}
swapChain_->Present(interval, 0);
curRenderTargetView_ = nullptr;
curDepthStencilView_ = nullptr;
frameCount_++;

View File

@ -518,10 +518,6 @@ public:
return (uint32_t)ShaderLanguage::HLSL_D3D9;
}
uint32_t GetDataFormatSupport(DataFormat fmt) const override;
PresentMode GetPresentMode() const override {
// TODO: Fix. Not yet used.
return PresentMode::FIFO;
}
ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const char *tag) override;
DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
@ -580,7 +576,7 @@ public:
}
void EndFrame() override;
void Present(int vblanks) override;
void Present(PresentMode presentMode, int vblanks) override;
int GetFrameCount() override { return frameCount_; }
@ -785,6 +781,9 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
caps_.multiSampleLevelsMask = 1; // More could be supported with some work.
caps_.clipPlanesSupported = caps.MaxUserClipPlanes;
caps_.presentInstantModeChange = false;
caps_.presentMaxInterval = 1;
caps_.presentModesSupported = PresentMode::FIFO;
if ((caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && caps.MaxAnisotropy > 1) {
caps_.anisoSupported = true;
@ -970,7 +969,7 @@ void D3D9Context::EndFrame() {
curPipeline_ = nullptr;
}
void D3D9Context::Present(int vblanks) {
void D3D9Context::Present(PresentMode presentMode, int vblanks) {
if (deviceEx_) {
deviceEx_->EndScene();
deviceEx_->PresentEx(NULL, NULL, NULL, NULL, 0);

View File

@ -322,7 +322,7 @@ class OpenGLTexture;
class OpenGLContext : public DrawContext {
public:
OpenGLContext();
OpenGLContext(bool canChangeSwapInterval);
~OpenGLContext();
void SetTargetSize(int w, int h) override {
@ -347,11 +347,6 @@ public:
renderManager_.SetErrorCallback(callback, userdata);
}
PresentMode GetPresentMode() const override {
// TODO: Fix. Not yet used.
return PresentMode::FIFO;
}
DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) override;
BlendState *CreateBlendState(const BlendStateDesc &desc) override;
SamplerState *CreateSamplerState(const SamplerStateDesc &desc) override;
@ -366,7 +361,7 @@ public:
void BeginFrame(DebugFlags debugFlags) override;
void EndFrame() override;
void Present(int vblanks) override;
void Present(PresentMode mode, int vblanks) override;
int GetFrameCount() override {
return frameCount_;
@ -547,7 +542,7 @@ static bool HasIntelDualSrcBug(const int versions[4]) {
}
}
OpenGLContext::OpenGLContext() {
OpenGLContext::OpenGLContext(bool canChangeSwapInterval) {
if (gl_extensions.IsGLES) {
if (gl_extensions.OES_packed_depth_stencil || gl_extensions.OES_depth24) {
caps_.preferredDepthBufferFormat = DataFormat::D24_S8;
@ -778,6 +773,16 @@ OpenGLContext::OpenGLContext() {
}
}
if (canChangeSwapInterval) {
caps_.presentInstantModeChange = true;
caps_.presentMaxInterval = 4;
caps_.presentModesSupported = PresentMode::FIFO | PresentMode::IMMEDIATE;
} else {
caps_.presentInstantModeChange = false;
caps_.presentModesSupported = PresentMode::FIFO;
caps_.presentMaxInterval = 1;
}
renderManager_.SetDeviceCaps(caps_);
}
@ -802,7 +807,7 @@ void OpenGLContext::EndFrame() {
Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
void OpenGLContext::Present(int vblanks) {
void OpenGLContext::Present(PresentMode presentMode, int vblanks) {
renderManager_.Present();
frameCount_++;
}
@ -1414,8 +1419,8 @@ void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stenc
renderManager_.Clear(colorval, depthVal, stencilVal, glMask, 0xF, 0, 0, targetWidth_, targetHeight_);
}
DrawContext *T3DCreateGLContext() {
return new OpenGLContext();
DrawContext *T3DCreateGLContext(bool canChangeSwapInterval) {
return new OpenGLContext(canChangeSwapInterval);
}
OpenGLInputLayout::~OpenGLInputLayout() {

View File

@ -404,7 +404,7 @@ public:
}
uint32_t GetDataFormatSupport(DataFormat fmt) const override;
PresentMode GetPresentMode() const override {
PresentMode GetPresentMode() const {
switch (vulkan_->GetPresentMode()) {
case VK_PRESENT_MODE_FIFO_KHR: return PresentMode::FIFO;
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return PresentMode::FIFO; // We treat is as FIFO for now (and won't ever enable it anyway...)
@ -480,7 +480,7 @@ public:
void BeginFrame(DebugFlags debugFlags) override;
void EndFrame() override;
void Present(int vblanks) override;
void Present(PresentMode presentMode, int vblanks) override;
void WipeQueue() override;
@ -899,6 +899,19 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
caps_.sampleRateShadingSupported = vulkan->GetDeviceFeatures().enabled.standard.sampleRateShading != 0;
caps_.textureSwizzleSupported = true;
// Present mode stuff
caps_.presentMaxInterval = 1;
caps_.presentInstantModeChange = false; // TODO: Fix this with some work in VulkanContext
caps_.presentModesSupported = (PresentMode)0;
for (auto mode : vulkan->GetAvailablePresentModes()) {
switch (mode) {
case VK_PRESENT_MODE_FIFO_KHR: caps_.presentModesSupported |= PresentMode::FIFO; break;
case VK_PRESENT_MODE_IMMEDIATE_KHR: caps_.presentModesSupported |= PresentMode::IMMEDIATE; break;
case VK_PRESENT_MODE_MAILBOX_KHR: caps_.presentModesSupported |= PresentMode::MAILBOX; break;
default: break; // Ignore any other modes.
}
}
const auto &limits = vulkan->GetPhysicalDeviceProperties().properties.limits;
auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties;
@ -1120,8 +1133,10 @@ void VKContext::EndFrame() {
Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
void VKContext::Present(int vblanks) {
_dbg_assert_(vblanks == 0 || vblanks == 1);
void VKContext::Present(PresentMode presentMode, int vblanks) {
if (presentMode == PresentMode::FIFO) {
_dbg_assert_(vblanks == 0 || vblanks == 1);
}
renderManager_.Present();
frameCount_++;
}

View File

@ -768,4 +768,15 @@ const char *Bugs::GetBugName(uint32_t bug) {
}
}
const char *PresentModeToString(PresentMode presentMode) {
switch (presentMode) {
case (PresentMode)0: return "NONE (bad)";
case PresentMode::FIFO: return "FIFO";
case PresentMode::IMMEDIATE: return "IMMEDIATE";
case PresentMode::MAILBOX: return "MAILBOX";
default:
return "COMBO"; // TODO: Hardcode all the combinations?
}
}
} // namespace Draw

View File

@ -570,6 +570,13 @@ struct PipelineDesc {
const Slice<SamplerDef> samplers;
};
enum class PresentMode {
FIFO = 1,
IMMEDIATE = 2,
MAILBOX = 4,
};
ENUM_CLASS_BITOPS(PresentMode);
struct DeviceCaps {
GPUVendor vendor;
uint32_t deviceID; // use caution!
@ -614,6 +621,11 @@ struct DeviceCaps {
// Old style, for older GL or Direct3D 9.
u32 clipPlanesSupported;
// Presentation caps
int presentMaxInterval; // 1 on many backends
bool presentInstantModeChange; // Our VulkanContext doesn't currently support it so we mark it as such, but it can be supported with careful coding.
PresentMode presentModesSupported;
u32 multiSampleLevelsMask; // Bit n is set if (1 << n) is a valid multisample level. Bit 0 is always set.
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};
@ -675,13 +687,6 @@ enum class DebugFlags {
};
ENUM_CLASS_BITOPS(DebugFlags);
enum class PresentMode {
FIFO,
IMMEDIATE,
MAILBOX,
// Retired FIFO_RELAXED. May reintroduce at some point.
};
class DrawContext {
public:
virtual ~DrawContext();
@ -696,8 +701,6 @@ public:
virtual std::vector<std::string> GetExtensionList(bool device, bool enabledOnly) const { return std::vector<std::string>(); }
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
virtual PresentMode GetPresentMode() const = 0;
// Describes the primary shader language that this implementation prefers.
const ShaderLanguageDesc &GetShaderLanguageDesc() {
return shaderLanguageDesc_;
@ -815,7 +818,10 @@ public:
// Frame management (for the purposes of sync and resource management, necessary with modern APIs). Default implementations here.
virtual void BeginFrame(DebugFlags debugFlags) {}
virtual void EndFrame() = 0;
virtual void Present(int vblanks) = 0; // NOTE: Not all backends support vblanks > 1.
// vblanks is only relevant in FIFO present mode.
// NOTE: Not all backends support vblanks > 1. Some backends also can't change presentation mode immediately.
virtual void Present(PresentMode presentMode, int vblanks) = 0;
virtual void WipeQueue() {}
@ -895,4 +901,6 @@ struct ShaderSource {
ShaderModule *CreateShader(DrawContext *draw, ShaderStage stage, const std::vector<ShaderSource> &sources);
const char *PresentModeToString(PresentMode presentMode);
} // namespace Draw

View File

@ -24,7 +24,7 @@ class VulkanContext;
namespace Draw {
DrawContext *T3DCreateGLContext();
DrawContext *T3DCreateGLContext(bool canChangeSwapInterval);
#ifdef _WIN32
DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx);

View File

@ -14,7 +14,6 @@ public:
virtual void ShutdownFromRenderThread() {}
virtual void Shutdown() = 0;
virtual void SwapInterval(int interval) = 0;
// Used during window resize. Must be called from the window thread,
// not the rendering thread or CPU thread.

View File

@ -147,6 +147,15 @@ static bool DefaultCodeGen() {
#endif
}
static bool DefaultVSync() {
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(UWP)
// Previously we didn't allow turning off vsync/FIFO on Android. Let's set the default accordingly.
return true;
#else
return false;
#endif
}
static bool DefaultEnableStateUndo() {
#ifdef MOBILE_DEVICE
// Off on mobile to save disk space.
@ -603,7 +612,7 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("TexScalingType", &g_Config.iTexScalingType, 0, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("TexDeposterize", &g_Config.bTexDeposterize, false, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("TexHardwareScaling", &g_Config.bTexHardwareScaling, false, CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("VSyncInterval", &g_Config.bVSync, false, CfgFlag::PER_GAME),
ConfigSetting("VSync", &g_Config.bVSync, &DefaultVSync, CfgFlag::PER_GAME),
ConfigSetting("BloomHack", &g_Config.iBloomHack, 0, CfgFlag::PER_GAME | CfgFlag::REPORT),
// Not really a graphics setting...

View File

@ -10,3 +10,65 @@
#include "Core/FrameTiming.h"
FrameTiming g_frameTiming;
inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) {
if (supportedModes & Draw::PresentMode::MAILBOX) {
return Draw::PresentMode::MAILBOX;
} else {
return Draw::PresentMode::IMMEDIATE;
}
}
void FrameTiming::Reset(Draw::DrawContext *draw) {
if (g_Config.bVSync) {
presentMode = Draw::PresentMode::FIFO;
presentInterval = 1;
} else {
presentMode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
presentInterval = 0;
}
}
Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval) {
Draw::PresentMode mode = Draw::PresentMode::FIFO;
if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) {
// Switch to immediate if desired and possible.
bool wantInstant = false;
if (!g_Config.bVSync) {
wantInstant = true;
}
if (PSP_CoreParameter().fastForward) {
wantInstant = true;
}
if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) {
int limit;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
limit = g_Config.iFpsLimit1;
else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
limit = g_Config.iFpsLimit2;
else
limit = PSP_CoreParameter().analogFpsLimit;
// For an alternative speed that is a clean factor of 60, the user probably still wants vsync.
if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) {
wantInstant = true;
}
}
if (wantInstant && g_Config.bVSync && !draw->GetDeviceCaps().presentInstantModeChange) {
// If in vsync mode (which will be FIFO), and the backend can't switch immediately,
// stick to FIFO.
wantInstant = false;
}
// If no instant modes are supported, stick to FIFO.
if (wantInstant && (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::MAILBOX | Draw::PresentMode::IMMEDIATE))) {
mode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
}
}
*interval = (mode == Draw::PresentMode::FIFO) ? 1 : 0;
return mode;
}

View File

@ -1,7 +1,19 @@
#pragma once
struct FrameTiming {
#include "Common/GPU/thin3d.h"
namespace Draw {
class DrawContext;
}
struct FrameTiming {
// Some backends won't allow changing this willy nilly.
Draw::PresentMode presentMode;
int presentInterval;
void Reset(Draw::DrawContext *draw);
};
extern FrameTiming g_frameTiming;
Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval);

View File

@ -566,12 +566,17 @@ void __DisplayFlip(int cyclesLate) {
bool fastForwardSkipFlip = g_Config.iFastForwardMode != (int)FastForwardMode::CONTINUOUS;
bool fifo = gpu && gpu->GetDrawContext() && gpu->GetDrawContext()->GetPresentMode() == Draw::PresentMode::FIFO;
if (gpu) {
Draw::DrawContext *draw = gpu->GetDrawContext();
if (fifo && GetGPUBackend() == GPUBackend::VULKAN) {
// Vulkan doesn't support the interval setting, so we force skipping the flip.
// TODO: We'll clean this up in a more backend-independent way later.
fastForwardSkipFlip = true;
g_frameTiming.presentMode = ComputePresentMode(draw, &g_frameTiming.presentInterval);
if (!draw->GetDeviceCaps().presentInstantModeChange && g_frameTiming.presentMode == Draw::PresentMode::FIFO) {
// Some backends can't just flip into MAILBOX/IMMEDIATE mode instantly.
// Vulkan doesn't support the interval setting, so we force skipping the flip.
// TODO: We'll clean this up in a more backend-independent way later.
fastForwardSkipFlip = true;
}
}
if (!g_Config.bSkipBufferEffects) {

View File

@ -846,6 +846,8 @@ namespace MIPSComp {
case VecDo3Op::VSLT:
allowSIMD = false;
break;
default:
break;
}
u8 sregs[4], tregs[4], dregs[4];
@ -941,6 +943,8 @@ namespace MIPSComp {
ir.Write(IROp::FMovFromGPR, tempregs[i], IRTEMP_1);
ir.Write(IROp::FCvtSW, tempregs[i], tempregs[i]);
break;
default:
break;
}
}

View File

@ -49,7 +49,6 @@
GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommonHW(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) {
UpdateVsyncInterval(true);
gstate_c.SetUseFlags(CheckGPUFeatures());
shaderManagerGL_ = new ShaderManagerGLES(draw);
@ -86,8 +85,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
UpdateCmdInfo();
BuildReportingInfo();
// Update again after init to be sure of any silly driver problems.
UpdateVsyncInterval(true);
textureCache_->NotifyConfigChanged();
@ -251,7 +248,6 @@ void GPU_GLES::DeviceRestore(Draw::DrawContext *draw) {
GPUCommonHW::DeviceRestore(draw);
fragmentTestCache_.DeviceRestore(draw_);
UpdateVsyncInterval(true);
}
void GPU_GLES::BeginHostFrame() {

View File

@ -67,13 +67,11 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) :
gstate_c.Reset();
gpuStats.Reset();
UpdateVsyncInterval(true);
PPGeSetDrawContext(draw);
ResetMatrices();
}
void GPUCommon::BeginHostFrame() {
UpdateVsyncInterval(displayResized_);
ReapplyGfxState();
// TODO: Assume config may have changed - maybe move to resize.
@ -115,38 +113,6 @@ void GPUCommon::Reinitialize() {
framebufferManager_->DestroyAllFBOs();
}
void GPUCommon::UpdateVsyncInterval(bool force) {
#if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS))
int desiredVSyncInterval = g_Config.bVSync ? 1 : 0;
if (PSP_CoreParameter().fastForward) {
desiredVSyncInterval = 0;
}
if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) {
int limit;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
limit = g_Config.iFpsLimit1;
else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
limit = g_Config.iFpsLimit2;
else
limit = PSP_CoreParameter().analogFpsLimit;
// For an alternative speed that is a clean factor of 60, the user probably still wants vsync.
if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) {
desiredVSyncInterval = 0;
}
}
if (desiredVSyncInterval != lastVsync_ || force) {
// Disabled EXT_swap_control_tear for now, it never seems to settle at the correct timing
// so it just keeps tearing. Not what I hoped for... (gl_extensions.EXT_swap_control_tear)
// See http://developer.download.nvidia.com/opengl/specs/WGL_EXT_swap_control_tear.txt
if (gfxCtx_)
gfxCtx_->SwapInterval(desiredVSyncInterval);
lastVsync_ = desiredVSyncInterval;
}
#endif
}
int GPUCommon::EstimatePerVertexCost() {
// TODO: This is transform cost, also account for rasterization cost somehow... although it probably
// runs in parallel with transform.

View File

@ -243,7 +243,6 @@ protected:
}
void BeginFrame() override;
void UpdateVsyncInterval(bool force);
virtual void CheckDepthUsage(VirtualFramebuffer *vfb) {}
virtual void FastRunLoop(DisplayList &list) = 0;

View File

@ -84,8 +84,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
}
BuildReportingInfo();
// Update again after init to be sure of any silly driver problems.
UpdateVsyncInterval(true);
textureCache_->NotifyConfigChanged();

View File

@ -49,7 +49,7 @@ class QtGLGraphicsContext : public GraphicsContext {
public:
QtGLGraphicsContext() {
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(false);
SetGPUBackend(GPUBackend::OPENGL);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
@ -66,10 +66,6 @@ public:
}
void Shutdown() override {}
void SwapInterval(int interval) override {
// See TODO in constructor.
// renderManager_->SwapInterval(interval);
}
void Resize() override {}
Draw::DrawContext *GetDrawContext() override {

View File

@ -414,7 +414,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int w, int h,
// Finally we can do the regular initialization.
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(true);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
SetGPUBackend(GPUBackend::OPENGL);

View File

@ -19,9 +19,6 @@ public:
void Shutdown() override;
void ShutdownFromRenderThread() override;
// Gets forwarded to the render thread.
void SwapInterval(int interval) override;
void Resize() override {}
Draw::DrawContext *GetDrawContext() override {

View File

@ -30,8 +30,6 @@ public:
void Poll() override;
void SwapInterval(int interval) override {
}
void *GetAPIContext() override {
return vulkan_;
}

View File

@ -3,6 +3,7 @@
#include "Common/System/System.h"
#include "UI/DebugOverlay.h"
#include "Core/HW/Display.h"
#include "Core/FrameTiming.h"
#include "Core/HLE/sceSas.h"
#include "Core/ControlMapper.h"
#include "Core/Config.h"
@ -113,7 +114,14 @@ static void DrawFrameTiming(UIContext *ctx, const Bounds &bounds) {
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(0.5f, 0.5f);
for (int i = 0; i < 8; i++) {
snprintf(statBuf, sizeof(statBuf),
"Present mode (interval): %s (%d)",
Draw::PresentModeToString(g_frameTiming.presentMode),
g_frameTiming.presentInterval);
ctx->Draw()->DrawTextRect(ubuntu24, statBuf, bounds.x + 10, bounds.y + 50, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
for (int i = 0; i < 5; i++) {
FrameTimeData data = ctx->GetDrawContext()->GetFrameTimeData(6 + i);
FrameTimeData prevData = ctx->GetDrawContext()->GetFrameTimeData(7 + i);
if (data.frameBegin == 0.0) {
@ -153,7 +161,7 @@ static void DrawFrameTiming(UIContext *ctx, const Bounds &bounds) {
presentStats
);
}
ctx->Draw()->DrawTextRect(ubuntu24, statBuf, bounds.x + 10 + i * 150, bounds.y + 50, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, statBuf, bounds.x + 10 + i * 150, bounds.y + 150, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
}
ctx->Draw()->SetFontScale(1.0f, 1.0f);
ctx->Flush();

View File

@ -605,10 +605,17 @@ void SystemInfoScreen::CreateTabs() {
g_display.dpi)));
#endif
#if !PPSSPP_PLATFORM(WINDOWS)
// Don't show on Windows, since it's always treated as 60 there.
displayInfo->Add(new InfoItem(si->T("Refresh rate"), StringFromFormat(si->T("%0.2f Hz"), (float)System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE))));
#endif
std::string presentModes;
if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::FIFO) presentModes += "FIFO, ";
if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::IMMEDIATE) presentModes += "IMMEDIATE, ";
if (draw->GetDeviceCaps().presentModesSupported & Draw::PresentMode::MAILBOX) presentModes += "MAILBOX, ";
if (!presentModes.empty()) {
presentModes.pop_back();
presentModes.pop_back();
}
displayInfo->Add(new InfoItem(si->T("Present modes"), presentModes));
CollapsibleSection *versionInfo = deviceSpecs->Add(new CollapsibleSection(si->T("Version Information")));
std::string apiVersion;

View File

@ -335,13 +335,14 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
}
#endif
#if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS))
// All backends support FIFO. Check if any immediate modes are supported, if so we can allow the user to choose.
if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) {
CheckBox *vSync = graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync")));
vSync->OnClick.Add([=](EventParams &e) {
NativeResized();
return UI::EVENT_CONTINUE;
});
#endif
}
#if PPSSPP_PLATFORM(ANDROID)
// Hide Immersive Mode on pre-kitkat Android

View File

@ -1051,6 +1051,7 @@ void RenderOverlays(UIContext *dc, void *userdata) {
}
static Matrix4x4 ComputeOrthoMatrix(float xres, float yres) {
// TODO: Should be able to share the y-flip logic here with the one in postprocessing/presentation, for example.
Matrix4x4 ortho;
switch (GetGPUBackend()) {
case GPUBackend::VULKAN:
@ -1132,6 +1133,8 @@ void NativeFrame(GraphicsContext *graphicsContext) {
if (g_Config.bGpuLogProfiler)
debugFlags |= Draw::DebugFlags::PROFILE_SCOPES;
g_frameTiming.Reset(g_draw);
g_draw->BeginFrame(debugFlags);
ui_draw2d.PushDrawMatrix(ortho);
@ -1158,7 +1161,9 @@ void NativeFrame(GraphicsContext *graphicsContext) {
ClearFailedGPUBackends();
}
g_draw->Present(1);
int interval;
Draw::PresentMode presentMode = ComputePresentMode(g_draw, &interval);
g_draw->Present(presentMode, interval);
if (resized) {
INFO_LOG(G3D, "Resized flag set - recalculating bounds");

View File

@ -19,7 +19,6 @@ public:
UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources);
void Shutdown() override;
void SwapInterval(int interval) override {}
void Resize() override {}
Draw::DrawContext * GetDrawContext() override {
return draw_;

View File

@ -33,10 +33,6 @@
#error This file should not be compiled for UWP.
#endif
void D3D11Context::SwapInterval(int interval) {
swapInterval_ = interval;
}
HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) {
bool windowed = true;
// D3D11 has no need for display rotation.

View File

@ -30,7 +30,6 @@ class D3D11Context : public WindowsGraphicsContext {
public:
bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override;
void Shutdown() override;
void SwapInterval(int interval) override;
void Resize() override;

View File

@ -23,10 +23,6 @@
typedef HRESULT (__stdcall *DIRECT3DCREATE9EX)(UINT, IDirect3D9Ex**);
void D3D9Context::SwapInterval(int interval) {
swapInterval_ = interval;
}
bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) {
bool windowed = true;
hWnd_ = wnd;

View File

@ -34,7 +34,6 @@ public:
bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override;
void Shutdown() override;
void SwapInterval(int interval) override;
void Resize() override;

View File

@ -412,7 +412,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
resumeRequested = false;
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(wglSwapIntervalEXT != nullptr);
bool success = draw_->CreatePresets(); // if we get this far, there will always be a GLSL compiler capable of compiling these.
if (!success) {
delete draw_;
@ -443,11 +443,6 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
return true; // Success
}
void WindowsGLContext::SwapInterval(int interval) {
// Delegate to the render manager to make sure it's done on the right thread.
renderManager_->SwapInterval(interval);
}
void WindowsGLContext::Shutdown() {
glslang::FinalizeProcess();
}

View File

@ -17,7 +17,6 @@ public:
void ShutdownFromRenderThread() override;
void Shutdown() override;
void SwapInterval(int interval) override;
void Poll() override;

View File

@ -29,7 +29,6 @@ public:
WindowsVulkanContext() : draw_(nullptr) {}
bool Init(HINSTANCE hInst, HWND window, std::string *error_message) override;
void Shutdown() override;
void SwapInterval(int interval) override {}
void Resize() override;
void Poll() override;

View File

@ -22,7 +22,7 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int
g_display.rotation = DisplayRotation::ROTATE_0;
g_display.rot_matrix.setIdentity();
draw_ = Draw::T3DCreateGLContext(); // Can't fail
draw_ = Draw::T3DCreateGLContext(false); // Can't fail
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);

View File

@ -15,7 +15,6 @@ public:
void ShutdownFromRenderThread() override;
void Shutdown() override {}
void SwapInterval(int interval) override {}
void Resize() override {}
Draw::DrawContext *GetDrawContext() override {

View File

@ -175,6 +175,3 @@ void AndroidVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
INFO_LOG(G3D, "AndroidVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
}
void AndroidVulkanContext::SwapInterval(int interval) {
}

View File

@ -15,7 +15,6 @@ public:
void ShutdownFromRenderThread() override; // Inverses InitFromRenderThread.
void Shutdown() override;
void SwapInterval(int interval) override;
void Resize() override;
void *GetAPIContext() override { return g_Vulkan; }

View File

@ -95,7 +95,6 @@ public:
void Shutdown() override {}
void Resize() override {}
void SwapInterval(int interval) override {}
private:
Draw::DrawContext *draw_ = nullptr;
@ -157,7 +156,7 @@ bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) {
#endif
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(false);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
SetGPUBackend(GPUBackend::OPENGL);
@ -166,6 +165,7 @@ bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) {
renderManager_->SetSwapFunction([&]() {
SDL_GL_SwapWindow(screen_);
});
// TODO: Support SwapInterval
return success;
}

View File

@ -49,7 +49,7 @@ class IOSGraphicsContext : public GraphicsContext {
public:
IOSGraphicsContext() {
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(false);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
SetGPUBackend(GPUBackend::OPENGL);
@ -63,7 +63,6 @@ public:
return draw_;
}
void SwapInterval(int interval) override {}
void Resize() override {}
void Shutdown() override {}

View File

@ -31,7 +31,7 @@ void LibretroGLContext::CreateDrawContext() {
#endif
CheckGLExtensions();
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(false);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
SetGPUBackend(GPUBackend::OPENGL);

View File

@ -26,7 +26,7 @@ void LibretroGLCoreContext::CreateDrawContext() {
glewInitDone = true;
CheckGLExtensions();
}
draw_ = Draw::T3DCreateGLContext();
draw_ = Draw::T3DCreateGLContext(false);
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
SetGPUBackend(GPUBackend::OPENGL);

View File

@ -21,7 +21,6 @@ public:
void Shutdown() override {
DestroyDrawContext();
}
void SwapInterval(int interval) override {}
virtual void SwapBuffers() = 0;
void Resize() override {}

View File

@ -1178,7 +1178,7 @@ namespace Libretro
if (ctx->GetDrawContext()) {
ctx->GetDrawContext()->EndFrame();
ctx->GetDrawContext()->Present(1);
ctx->GetDrawContext()->Present(Draw::PresentMode::FIFO, 1);
}
}