From 39d25ce91f9890489c60dfe795233067a9606049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 4 Aug 2023 11:53:51 +0200 Subject: [PATCH] D3D11: Allow setting the max frame latency --- Common/GPU/D3D11/thin3d_d3d11.cpp | 15 +++++++++++---- Common/GPU/OpenGL/thin3d_gl.cpp | 1 + Common/GPU/Vulkan/thin3d_vulkan.cpp | 1 + Common/GPU/thin3d.h | 1 + Common/GPU/thin3d_create.h | 2 +- UI/GameSettingsScreen.cpp | 2 +- UWP/PPSSPP_UWPMain.cpp | 2 +- Windows/GPU/D3D11Context.cpp | 5 +++-- 8 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 3cad78701b..2e4057c2de 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -62,7 +62,7 @@ public: class D3D11DrawContext : public DrawContext { public: - D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList); + D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList, int maxInflightFrames); ~D3D11DrawContext(); const DeviceCaps &GetDeviceCaps() const override { @@ -244,7 +244,7 @@ private: std::vector deviceList_; }; -D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList) +D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList, int maxInflightFrames) : hWnd_(hWnd), device_(device), context_(deviceContext1), @@ -346,6 +346,13 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de const size_t UP_MAX_BYTES = 65536 * 24; upBuffer_ = CreateBuffer(UP_MAX_BYTES, BufferUsageFlag::DYNAMIC | BufferUsageFlag::VERTEXDATA); + + IDXGIDevice1 *dxgiDevice1 = nullptr; + hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice1)); + if (SUCCEEDED(hr)) { + caps_.setMaxFrameLatencySupported = true; + dxgiDevice1->SetMaximumFrameLatency(maxInflightFrames); + } } D3D11DrawContext::~D3D11DrawContext() { @@ -1858,8 +1865,8 @@ void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h } } -DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames) { - return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd, adapterNames); +DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames, int maxInflightFrames) { + return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd, adapterNames, maxInflightFrames); } } // namespace Draw diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 18f8cde843..df93103468 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -575,6 +575,7 @@ OpenGLContext::OpenGLContext() { caps_.textureDepthSupported = true; } + caps_.setMaxFrameLatencySupported = true; caps_.dualSourceBlend = gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended; caps_.anisoSupported = gl_extensions.EXT_texture_filter_anisotropic; caps_.framebufferCopySupported = gl_extensions.OES_copy_image || gl_extensions.NV_copy_image || gl_extensions.EXT_copy_image || gl_extensions.ARB_copy_image; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 8cfb33bf85..95b6e95f1d 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -871,6 +871,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread) VkFormat depthStencilFormat = vulkan->GetDeviceInfo().preferredDepthStencilFormat; + caps_.setMaxFrameLatencySupported = true; caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.standard.samplerAnisotropy != 0; caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.standard.geometryShader != 0; caps_.tesselationShaderSupported = vulkan->GetDeviceFeatures().enabled.standard.tessellationShader != 0; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 12c5e997d6..e6ac90388a 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -603,6 +603,7 @@ struct DeviceCaps { bool multiViewSupported; bool isTilingGPU; // This means that it benefits from correct store-ops, msaa without backing memory, etc. bool sampleRateShadingSupported; + bool setMaxFrameLatencySupported; bool verySlowShaderCompiler; diff --git a/Common/GPU/thin3d_create.h b/Common/GPU/thin3d_create.h index 5f304af090..7fdd833971 100644 --- a/Common/GPU/thin3d_create.h +++ b/Common/GPU/thin3d_create.h @@ -28,7 +28,7 @@ DrawContext *T3DCreateGLContext(); #ifdef _WIN32 DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, IDirect3DDevice9 *device, IDirect3DDevice9Ex *deviceEx); -DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames); +DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector adapterNames, int maxInflightFrames); #endif DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool useRenderThread); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c7626c0eb5..4668774caa 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -432,7 +432,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) return !g_Config.bSkipBufferEffects && g_Config.iFrameSkip == 0; }); - if (GetGPUBackend() == GPUBackend::VULKAN || GetGPUBackend() == GPUBackend::OPENGL) { + if (draw->GetDeviceCaps().setMaxFrameLatencySupported) { static const char *bufferOptions[] = { "No buffer", "Up to 1", "Up to 2" }; PopupMultiChoice *inflightChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInflightFrames, gr->T("Buffer graphics commands (faster, input lag)"), bufferOptions, 1, ARRAY_SIZE(bufferOptions), I18NCat::GRAPHICS, screenManager())); inflightChoice->OnChoice.Handle(this, &GameSettingsScreen::OnInflightFramesChoice); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index ac5d8d4819..94d4091ffc 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -317,7 +317,7 @@ UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr reso std::vector adapterNames; draw_ = Draw::T3DCreateD3D11Context( - resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetDeviceFeatureLevel(), 0, adapterNames); + resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetDeviceFeatureLevel(), 0, adapterNames, g_Config.iInflightFrames); bool success = draw_->CreatePresets(); _assert_(success); } diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index 7319f989f9..97faabf8af 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -171,7 +171,7 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { } #endif - draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames); + draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames, g_Config.iInflightFrames); SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. _assert_msg_(success, "Failed to compile preset shaders"); @@ -182,7 +182,8 @@ bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; - IDXGIDevice* dxgiDevice = nullptr; + IDXGIDevice *dxgiDevice = nullptr; + IDXGIDevice1* dxgiDevice1 = nullptr; IDXGIAdapter* adapter = nullptr; hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice)); if (SUCCEEDED(hr)) {