Avoid hard depending on Direct3D 11.1, slighly optimize presentation

This commit is contained in:
CasualPokePlayer 2024-05-16 14:50:56 -07:00
parent bfec776bd7
commit 1260ecd01a
4 changed files with 81 additions and 41 deletions

View File

@ -48,10 +48,12 @@ namespace BizHawk.Bizware.Graphics.Controls
=> Vsync = state; => Vsync = state;
public override void Begin() public override void Begin()
=> _swapChain.SetBackBuffer(); {
}
public override void End() public override void End()
=> _swapChain.SetBackBuffer(); {
}
public override void SwapBuffers() public override void SwapBuffers()
=> _swapChain.PresentBuffer(ControlParameters); => _swapChain.PresentBuffer(ControlParameters);

View File

@ -16,7 +16,8 @@ namespace BizHawk.Bizware.Graphics.Controls
public abstract void SetVsync(bool state); public abstract void SetVsync(bool state);
/// <summary> /// <summary>
/// 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
/// </summary> /// </summary>
public abstract void SwapBuffers(); public abstract void SwapBuffers();

View File

@ -31,9 +31,10 @@ namespace BizHawk.Bizware.Graphics
{ {
public ID3D11Device Device; public ID3D11Device Device;
public ID3D11DeviceContext Context; public ID3D11DeviceContext Context;
public ID3D11DeviceContext1 Context1;
public ID3D11Texture2D BackBufferTexture; public ID3D11Texture2D BackBufferTexture;
public ID3D11RenderTargetView RTV; public ID3D11RenderTargetView RTV;
public IDXGISwapChain1 SwapChain; public IDXGISwapChain SwapChain;
public bool AllowsTearing; public bool AllowsTearing;
public void Dispose() public void Dispose()
@ -41,6 +42,8 @@ namespace BizHawk.Bizware.Graphics
// Device/Context not owned by this class // Device/Context not owned by this class
Device = null; Device = null;
Context = null; Context = null;
Context1?.Dispose();
Context1 = null;
RTV?.Dispose(); RTV?.Dispose();
RTV = null; RTV = null;
BackBufferTexture?.Dispose(); BackBufferTexture?.Dispose();
@ -57,9 +60,10 @@ namespace BizHawk.Bizware.Graphics
private ID3D11Device Device => _resources.Device; private ID3D11Device Device => _resources.Device;
private ID3D11DeviceContext Context => _resources.Context; private ID3D11DeviceContext Context => _resources.Context;
private ID3D11DeviceContext1 Context1 => _resources.Context1;
private ID3D11Texture2D BackBufferTexture => _resources.BackBufferTexture; private ID3D11Texture2D BackBufferTexture => _resources.BackBufferTexture;
private ID3D11RenderTargetView RTV => _resources.RTV; private ID3D11RenderTargetView RTV => _resources.RTV;
private IDXGISwapChain1 SwapChain => _resources.SwapChain; private IDXGISwapChain SwapChain => _resources.SwapChain;
private bool AllowsTearing => _resources.AllowsTearing; private bool AllowsTearing => _resources.AllowsTearing;
internal D3D11SwapChain(SwapChainResources resources, Action<ControlParameters> resetDeviceCallback) internal D3D11SwapChain(SwapChainResources resources, Action<ControlParameters> resetDeviceCallback)
@ -71,12 +75,9 @@ namespace BizHawk.Bizware.Graphics
public void Dispose() public void Dispose()
=> _resources.Dispose(); => _resources.Dispose();
public void SetBackBuffer()
=> Context.OMSetRenderTargets(RTV);
public void PresentBuffer(ControlParameters cp) public void PresentBuffer(ControlParameters cp)
{ {
SetBackBuffer(); Context.OMSetRenderTargets(RTV);
PresentFlags presentFlags; PresentFlags presentFlags;
if (cp.Vsync) if (cp.Vsync)
@ -95,6 +96,9 @@ namespace BizHawk.Bizware.Graphics
{ {
_resetDeviceCallback(cp); _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) public void Refresh(ControlParameters cp)

View File

@ -25,7 +25,8 @@ namespace BizHawk.Bizware.Graphics
private struct D3D11Resources : IDisposable private struct D3D11Resources : IDisposable
{ {
public IDXGIFactory2 Factory; public IDXGIFactory1 Factory1;
public IDXGIFactory2 Factory2;
public ID3D11Device Device; public ID3D11Device Device;
public ID3D11DeviceContext Context; public ID3D11DeviceContext Context;
public ID3D11BlendState BlendEnableState; public ID3D11BlendState BlendEnableState;
@ -40,8 +41,10 @@ namespace BizHawk.Bizware.Graphics
{ {
try try
{ {
// we need IDXGIFactory2 for CreateSwapChainForHwnd Factory1 = DXGI.CreateDXGIFactory1<IDXGIFactory1>();
Factory = DXGI.CreateDXGIFactory1<IDXGIFactory2>(); // 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<IDXGIFactory2>();
#if false #if false
// use this to debug D3D11 calls // 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 // 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?.Dispose();
Device = null; Device = null;
Factory?.Dispose(); Factory2?.Dispose();
Factory = null; 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 // these might need to be thrown out and recreated if the device is lost
private D3D11Resources _resources; private D3D11Resources _resources;
private IDXGIFactory2 Factory => _resources.Factory; private IDXGIFactory1 Factory1 => _resources.Factory1;
private IDXGIFactory2 Factory2 => _resources.Factory2;
private ID3D11Device Device => _resources.Device; private ID3D11Device Device => _resources.Device;
private ID3D11DeviceContext Context => _resources.Context; private ID3D11DeviceContext Context => _resources.Context;
private ID3D11BlendState BlendEnableState => _resources.BlendEnableState; private ID3D11BlendState BlendEnableState => _resources.BlendEnableState;
@ -166,7 +173,31 @@ namespace BizHawk.Bizware.Graphics
_resources.CreateResources(); _resources.CreateResources();
} }
private IDXGISwapChain1 CreateDXGISwapChain(D3D11SwapChain.ControlParameters cp) private IDXGISwapChain CreateDXGISwapChain(D3D11SwapChain.ControlParameters cp)
{
IDXGISwapChain ret;
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 = Factory1.CreateSwapChain(Device, sd);
}
else
{ {
// this is the optimal swapchain model // this is the optimal swapchain model
// note however it requires windows 10+ // note however it requires windows 10+
@ -183,20 +214,20 @@ namespace BizHawk.Bizware.Graphics
alphaMode: AlphaMode.Ignore, alphaMode: AlphaMode.Ignore,
flags: SwapChainFlags.AllowTearing); flags: SwapChainFlags.AllowTearing);
IDXGISwapChain1 ret;
try try
{ {
ret = Factory.CreateSwapChainForHwnd(Device, cp.Handle, sd); ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd);
} }
catch catch
{ {
sd.SwapEffect = SwapEffect.Discard; sd.SwapEffect = SwapEffect.Discard;
sd.Flags = SwapChainFlags.None; sd.Flags = SwapChainFlags.None;
ret = Factory.CreateSwapChainForHwnd(Device, cp.Handle, sd); ret = Factory2.CreateSwapChainForHwnd(Device, cp.Handle, sd);
}
} }
// don't allow DXGI to snoop alt+enter and such // don't allow DXGI to snoop alt+enter and such
using var parentFactory = ret.GetParent<IDXGIFactory2>(); using var parentFactory = ret.GetParent<IDXGIFactory>();
parentFactory.MakeWindowAssociation(cp.Handle, WindowAssociationFlags.IgnoreAll); parentFactory.MakeWindowAssociation(cp.Handle, WindowAssociationFlags.IgnoreAll);
return ret; return ret;
} }
@ -330,10 +361,11 @@ namespace BizHawk.Bizware.Graphics
_controlSwapChain.Device = Device; _controlSwapChain.Device = Device;
_controlSwapChain.Context = Context; _controlSwapChain.Context = Context;
_controlSwapChain.Context1 = Context.QueryInterfaceOrNull<ID3D11DeviceContext1>();
_controlSwapChain.BackBufferTexture = bbTex; _controlSwapChain.BackBufferTexture = bbTex;
_controlSwapChain.RTV = rtv; _controlSwapChain.RTV = rtv;
_controlSwapChain.SwapChain = swapChain; _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) public D3D11SwapChain CreateSwapChain(D3D11SwapChain.ControlParameters cp)
@ -348,14 +380,15 @@ namespace BizHawk.Bizware.Graphics
var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm); var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm);
var rtv = Device.CreateRenderTargetView(bbTex, rtvd); var rtv = Device.CreateRenderTargetView(bbTex, rtvd);
_controlSwapChain = new D3D11SwapChain.SwapChainResources _controlSwapChain = new()
{ {
Device = Device, Device = Device,
Context = Context, Context = Context,
Context1 = Context.QueryInterfaceOrNull<ID3D11DeviceContext1>(),
BackBufferTexture = bbTex, BackBufferTexture = bbTex,
RTV = rtv, RTV = rtv,
SwapChain = swapChain, SwapChain = swapChain,
AllowsTearing = (swapChain.Description1.Flags & SwapChainFlags.AllowTearing) != 0, AllowsTearing = (swapChain.Description.Flags & SwapChainFlags.AllowTearing) != 0,
}; };
return new(_controlSwapChain, ResetDevice); return new(_controlSwapChain, ResetDevice);