D3D11: Allow setting the max frame latency

This commit is contained in:
Henrik Rydgård 2023-08-04 11:53:51 +02:00
parent 74a471d7a5
commit 39d25ce91f
8 changed files with 20 additions and 9 deletions

View file

@ -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<std::string> deviceList);
D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> deviceList, int maxInflightFrames);
~D3D11DrawContext();
const DeviceCaps &GetDeviceCaps() const override {
@ -244,7 +244,7 @@ private:
std::vector<std::string> deviceList_;
};
D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> deviceList)
D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> 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<void **>(&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<std::string> 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<std::string> adapterNames, int maxInflightFrames) {
return new D3D11DrawContext(device, context, device1, context1, featureLevel, hWnd, adapterNames, maxInflightFrames);
}
} // namespace Draw

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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<std::string> adapterNames);
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector<std::string> adapterNames, int maxInflightFrames);
#endif
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool useRenderThread);

View file

@ -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);

View file

@ -317,7 +317,7 @@ UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> reso
std::vector<std::string> 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);
}

View file

@ -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<void**>(&dxgiDevice));
if (SUCCEEDED(hr)) {