From 1260ecd01a89035ad0527f5820cd5b2343af29e8 Mon Sep 17 00:00:00 2001
From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date: Thu, 16 May 2024 14:50:56 -0700
Subject: [PATCH] Avoid hard depending on Direct3D 11.1, slighly optimize
presentation
---
.../Controls/D3D11Control.cs | 6 +-
.../GraphicsControl.cs | 3 +-
.../D3D11/D3D11SwapChain.cs | 16 +--
.../D3D11/IGL_D3D11.cs | 97 +++++++++++++------
4 files changed, 81 insertions(+), 41 deletions(-)
diff --git a/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs
index 6925f3b750..0e2af363e2 100644
--- a/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs
+++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/D3D11Control.cs
@@ -48,10 +48,12 @@ namespace BizHawk.Bizware.Graphics.Controls
=> Vsync = state;
public override void Begin()
- => _swapChain.SetBackBuffer();
+ {
+ }
public override void End()
- => _swapChain.SetBackBuffer();
+ {
+ }
public override void SwapBuffers()
=> _swapChain.PresentBuffer(ControlParameters);
diff --git a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs
index 87f58f7e79..4215bdf67c 100644
--- a/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs
+++ b/src/BizHawk.Bizware.Graphics.Controls/GraphicsControl.cs
@@ -16,7 +16,8 @@ namespace BizHawk.Bizware.Graphics.Controls
public abstract void SetVsync(bool state);
///
- /// Swaps the buffers for this control
+ /// Swaps the buffers for this control.
+ /// Be aware, the owner IGL's current render target is undefined after calling this
///
public abstract void SwapBuffers();
diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs
index 94dab21bf0..00b687c1b8 100644
--- a/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs
+++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11SwapChain.cs
@@ -31,9 +31,10 @@ namespace BizHawk.Bizware.Graphics
{
public ID3D11Device Device;
public ID3D11DeviceContext Context;
+ public ID3D11DeviceContext1 Context1;
public ID3D11Texture2D BackBufferTexture;
public ID3D11RenderTargetView RTV;
- public IDXGISwapChain1 SwapChain;
+ public IDXGISwapChain SwapChain;
public bool AllowsTearing;
public void Dispose()
@@ -41,6 +42,8 @@ namespace BizHawk.Bizware.Graphics
// Device/Context not owned by this class
Device = null;
Context = null;
+ Context1?.Dispose();
+ Context1 = null;
RTV?.Dispose();
RTV = null;
BackBufferTexture?.Dispose();
@@ -57,9 +60,10 @@ namespace BizHawk.Bizware.Graphics
private ID3D11Device Device => _resources.Device;
private ID3D11DeviceContext Context => _resources.Context;
+ private ID3D11DeviceContext1 Context1 => _resources.Context1;
private ID3D11Texture2D BackBufferTexture => _resources.BackBufferTexture;
private ID3D11RenderTargetView RTV => _resources.RTV;
- private IDXGISwapChain1 SwapChain => _resources.SwapChain;
+ private IDXGISwapChain SwapChain => _resources.SwapChain;
private bool AllowsTearing => _resources.AllowsTearing;
internal D3D11SwapChain(SwapChainResources resources, Action resetDeviceCallback)
@@ -71,12 +75,9 @@ namespace BizHawk.Bizware.Graphics
public void Dispose()
=> _resources.Dispose();
- public void SetBackBuffer()
- => Context.OMSetRenderTargets(RTV);
-
public void PresentBuffer(ControlParameters cp)
{
- SetBackBuffer();
+ Context.OMSetRenderTargets(RTV);
PresentFlags presentFlags;
if (cp.Vsync)
@@ -95,6 +96,9 @@ namespace BizHawk.Bizware.Graphics
{
_resetDeviceCallback(cp);
}
+
+ // optimization hint to the GPU (note: not always available, needs Win8+ or Win7 with the Platform Update)
+ Context1?.DiscardView(RTV);
}
public void Refresh(ControlParameters cp)
diff --git a/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
index e2cefd0a77..37d9e96d20 100644
--- a/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
+++ b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
@@ -25,7 +25,8 @@ namespace BizHawk.Bizware.Graphics
private struct D3D11Resources : IDisposable
{
- public IDXGIFactory2 Factory;
+ public IDXGIFactory1 Factory1;
+ public IDXGIFactory2 Factory2;
public ID3D11Device Device;
public ID3D11DeviceContext Context;
public ID3D11BlendState BlendEnableState;
@@ -40,8 +41,10 @@ namespace BizHawk.Bizware.Graphics
{
try
{
- // we need IDXGIFactory2 for CreateSwapChainForHwnd
- Factory = DXGI.CreateDXGIFactory1();
+ Factory1 = DXGI.CreateDXGIFactory1();
+ // we want IDXGIFactory2 for CreateSwapChainForHwnd
+ // however, it's not guaranteed to be available (only available in Win8+ or Win7 with the Platform Update)
+ Factory2 = Factory1.QueryInterfaceOrNull();
#if false
// use this to debug D3D11 calls
// note debug layer requires extra steps to use: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-layers#debug-layer
@@ -124,8 +127,11 @@ namespace BizHawk.Bizware.Graphics
Device?.Dispose();
Device = null;
- Factory?.Dispose();
- Factory = null;
+ Factory2?.Dispose();
+ Factory2 = null;
+
+ Factory1?.Dispose();
+ Factory1 = null;
}
}
@@ -133,7 +139,8 @@ namespace BizHawk.Bizware.Graphics
// these might need to be thrown out and recreated if the device is lost
private D3D11Resources _resources;
- private IDXGIFactory2 Factory => _resources.Factory;
+ private IDXGIFactory1 Factory1 => _resources.Factory1;
+ private IDXGIFactory2 Factory2 => _resources.Factory2;
private ID3D11Device Device => _resources.Device;
private ID3D11DeviceContext Context => _resources.Context;
private ID3D11BlendState BlendEnableState => _resources.BlendEnableState;
@@ -166,37 +173,61 @@ namespace BizHawk.Bizware.Graphics
_resources.CreateResources();
}
- private IDXGISwapChain1 CreateDXGISwapChain(D3D11SwapChain.ControlParameters cp)
+ private IDXGISwapChain CreateDXGISwapChain(D3D11SwapChain.ControlParameters cp)
{
- // this is the optimal swapchain model
- // note however it requires windows 10+
- // a less optimal model will end up being used in case this fails
- var sd = new SwapChainDescription1(
- width: cp.Width,
- height: cp.Height,
- format: Format.B8G8R8A8_UNorm,
- stereo: false,
- swapEffect: SwapEffect.FlipDiscard,
- bufferUsage: Usage.RenderTargetOutput,
- bufferCount: 2,
- scaling: Scaling.Stretch,
- alphaMode: AlphaMode.Ignore,
- flags: SwapChainFlags.AllowTearing);
+ IDXGISwapChain ret;
- IDXGISwapChain1 ret;
- try
- {
- ret = Factory.CreateSwapChainForHwnd(Device, cp.Handle, sd);
- }
- catch
+ if (Factory2 is null)
{
+ // no Factory2, probably on Windows 7 without the Platform Update
+ // we can assume a simple legacy format is needed here
+ var sd = default(SwapChainDescription);
+ sd.BufferDescription = new(
+ width: cp.Width,
+ height: cp.Height,
+ refreshRate: new(0, 0),
+ format: Format.B8G8R8A8_UNorm);
+ sd.SampleDescription = SampleDescription.Default;
+ sd.BufferUsage = Usage.RenderTargetOutput;
+ sd.BufferCount = 2;
+ sd.OutputWindow = cp.Handle;
+ sd.Windowed = true;
sd.SwapEffect = SwapEffect.Discard;
sd.Flags = SwapChainFlags.None;
- ret = Factory.CreateSwapChainForHwnd(Device, cp.Handle, sd);
+
+ ret = Factory1.CreateSwapChain(Device, sd);
+ }
+ else
+ {
+ // this is the optimal swapchain model
+ // note however it requires windows 10+
+ // a less optimal model will end up being used in case this fails
+ var sd = new SwapChainDescription1(
+ width: cp.Width,
+ height: cp.Height,
+ format: Format.B8G8R8A8_UNorm,
+ stereo: false,
+ swapEffect: SwapEffect.FlipDiscard,
+ bufferUsage: Usage.RenderTargetOutput,
+ bufferCount: 2,
+ scaling: Scaling.Stretch,
+ alphaMode: AlphaMode.Ignore,
+ flags: SwapChainFlags.AllowTearing);
+
+ try
+ {
+ ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd);
+ }
+ catch
+ {
+ sd.SwapEffect = SwapEffect.Discard;
+ sd.Flags = SwapChainFlags.None;
+ ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd);
+ }
}
// don't allow DXGI to snoop alt+enter and such
- using var parentFactory = ret.GetParent();
+ using var parentFactory = ret.GetParent();
parentFactory.MakeWindowAssociation(cp.Handle, WindowAssociationFlags.IgnoreAll);
return ret;
}
@@ -330,10 +361,11 @@ namespace BizHawk.Bizware.Graphics
_controlSwapChain.Device = Device;
_controlSwapChain.Context = Context;
+ _controlSwapChain.Context1 = Context.QueryInterfaceOrNull();
_controlSwapChain.BackBufferTexture = bbTex;
_controlSwapChain.RTV = rtv;
_controlSwapChain.SwapChain = swapChain;
- _controlSwapChain.AllowsTearing = (swapChain.Description1.Flags & SwapChainFlags.AllowTearing) != 0;
+ _controlSwapChain.AllowsTearing = (swapChain.Description.Flags & SwapChainFlags.AllowTearing) != 0;
}
public D3D11SwapChain CreateSwapChain(D3D11SwapChain.ControlParameters cp)
@@ -348,14 +380,15 @@ namespace BizHawk.Bizware.Graphics
var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm);
var rtv = Device.CreateRenderTargetView(bbTex, rtvd);
- _controlSwapChain = new D3D11SwapChain.SwapChainResources
+ _controlSwapChain = new()
{
Device = Device,
Context = Context,
+ Context1 = Context.QueryInterfaceOrNull(),
BackBufferTexture = bbTex,
RTV = rtv,
SwapChain = swapChain,
- AllowsTearing = (swapChain.Description1.Flags & SwapChainFlags.AllowTearing) != 0,
+ AllowsTearing = (swapChain.Description.Flags & SwapChainFlags.AllowTearing) != 0,
};
return new(_controlSwapChain, ResetDevice);