From 0322ca5bad4a740bd4caf9d89e78ecc5f3e5af02 Mon Sep 17 00:00:00 2001 From: "J.D. Purcell" Date: Sun, 9 Apr 2017 12:55:11 -0400 Subject: [PATCH] Cleanup Direct3D device reset code. --- .../GLControlWrapper_SlimDX9.cs | 4 +- .../IGL_SlimDX9.cs | 157 ++++++------------ 2 files changed, 53 insertions(+), 108 deletions(-) diff --git a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/GLControlWrapper_SlimDX9.cs b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/GLControlWrapper_SlimDX9.cs index caad882f19..986f262a18 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/GLControlWrapper_SlimDX9.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/GLControlWrapper_SlimDX9.cs @@ -37,9 +37,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX protected override void Dispose(bool disposing) { - base.Dispose(disposing); + sdx.FreeControlSwapChain(this); - //if(MyBufferedGraphics != null) + base.Dispose(disposing); } IGL_SlimDX9 sdx; diff --git a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs index 2ed1a30c79..6447c3e2a4 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs @@ -26,13 +26,15 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX public class IGL_SlimDX9 : IGL { + const int D3DERR_DEVICELOST = -2005530520; + const int D3DERR_DEVICENOTRESET = -2005530519; + static Direct3D d3d; internal Device dev; INativeWindow OffscreenNativeWindow; //rendering state IntPtr _pVertexData; - RenderTarget _CurrRenderTarget; Pipeline _CurrPipeline; GLControlWrapper_SlimDX9 _CurrentControl; @@ -87,15 +89,16 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX }; } - void ResetDevice() + void ResetDevice(GLControlWrapper_SlimDX9 control) { - ResetHandlers.Reset(); + SuspendRenderTargets(); + FreeControlSwapChain(control); for (; ; ) { var result = dev.TestCooperativeLevel(); if (result.IsSuccess) break; - if (result.Code == -2005530519) // D3DERR_DEVICENOTRESET + if (result.Code == D3DERR_DEVICENOTRESET) { try { @@ -107,7 +110,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX } System.Threading.Thread.Sleep(100); } - ResetHandlers.Restore(); + RefreshControlSwapChain(control); + ResumeRenderTargets(); } public void CreateDevice() @@ -128,7 +132,6 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX void IDisposable.Dispose() { - ResetHandlers.Reset(); DestroyDevice(); d3d.Dispose(); } @@ -844,55 +847,56 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX } catch(d3d9.Direct3D9Exception ex) { - if (ex.ResultCode.Name == "D3DERR_DEVICELOST") - ResetDevice(); + if (ex.ResultCode.Code == D3DERR_DEVICELOST) + ResetDevice(control); } } - + HashSet _renderTargets = new HashSet(); + public void FreeRenderTarget(RenderTarget rt) - { - //not needed 1st pass ?? - //int id = rt.Id.ToInt32(); - //var rtw = ResourceIDs.Lookup[id] as RenderTargetWrapper; - //rtw.Target.Dispose(); - //ResourceIDs.Free(rt.Id); - } - - public RenderTarget CreateRenderTarget(int w, int h) - { - var d3dtex = new d3d9.Texture(dev, w, h, 1, d3d9.Usage.RenderTarget, d3d9.Format.A8R8G8B8, d3d9.Pool.Default); - var tw = new TextureWrapper() { Texture = d3dtex }; - var tex = new Texture2d(this, tw, w, h); - RenderTarget rt = new RenderTarget(this, tw, tex); - - ResetHandlers.Add(rt, "RenderTarget", () => ResetRenderTarget(rt), () => RestoreRenderTarget(rt)); - return rt; - } - - void ResetRenderTarget(RenderTarget rt) { var tw = rt.Texture2d.Opaque as TextureWrapper; tw.Texture.Dispose(); tw.Texture = null; + _renderTargets.Remove(rt); } - void RestoreRenderTarget(RenderTarget rt) + public RenderTarget CreateRenderTarget(int w, int h) { - var tw = rt.Texture2d.Opaque as TextureWrapper; - int w = rt.Texture2d.IntWidth; - int h = rt.Texture2d.IntHeight; - var d3dtex = new d3d9.Texture(dev, w, h, 1, d3d9.Usage.RenderTarget, d3d9.Format.A8R8G8B8, d3d9.Pool.Default); - tw.Texture = d3dtex; - //i know it's weird, we have to re-add ourselves to the list - //bad design.. - ResetHandlers.Add(rt, "RenderTarget", () => ResetRenderTarget(rt), () => RestoreRenderTarget(rt)); + var tw = new TextureWrapper() { Texture = CreateRenderTargetTexture(w, h) }; + var tex = new Texture2d(this, tw, w, h); + var rt = new RenderTarget(this, tw, tex); + _renderTargets.Add(rt); + return rt; + } + + d3d9.Texture CreateRenderTargetTexture(int w, int h) + { + return new d3d9.Texture(dev, w, h, 1, d3d9.Usage.RenderTarget, d3d9.Format.A8R8G8B8, d3d9.Pool.Default); + } + + void SuspendRenderTargets() + { + foreach (var rt in _renderTargets) + { + var tw = rt.Opaque as TextureWrapper; + tw.Texture.Dispose(); + tw.Texture = null; + } + } + + void ResumeRenderTargets() + { + foreach (var rt in _renderTargets) + { + var tw = rt.Opaque as TextureWrapper; + tw.Texture = CreateRenderTargetTexture(rt.Texture2d.IntWidth, rt.Texture2d.IntHeight); + } } public void BindRenderTarget(RenderTarget rt) { - _CurrRenderTarget = rt; - if (rt == null) { //this dispose is needed for correct device resets, I have no idea why @@ -911,15 +915,19 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX dev.DepthStencilSurface = null; } - public void RefreshControlSwapChain(GLControlWrapper_SlimDX9 control) + public void FreeControlSwapChain(GLControlWrapper_SlimDX9 control) { if (control.SwapChain != null) { control.SwapChain.Dispose(); control.SwapChain = null; } - ResetHandlers.Remove(control, "SwapChain"); - + } + + public void RefreshControlSwapChain(GLControlWrapper_SlimDX9 control) + { + FreeControlSwapChain(control); + var pp = new PresentParameters { BackBufferWidth = Math.Max(8,control.ClientSize.Width), @@ -932,71 +940,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX }; control.SwapChain = new SwapChain(dev, pp); - ResetHandlers.Add(control, "SwapChain", () => - { - control.SwapChain.Dispose(); - control.SwapChain = null; - }, - () => RefreshControlSwapChain(control)); } - DeviceLostHandler ResetHandlers = new DeviceLostHandler(); - - class DeviceLostHandler - { - class ResetHandlerKey - { - public string Label; - public object Object; - public override int GetHashCode() - { - return Label.GetHashCode() ^ Object.GetHashCode(); - } - public override bool Equals(object obj) - { - if (obj == null) return false; - var key = obj as ResetHandlerKey; - return key.Label == Label && key.Object == Object; - } - } - - class HandlerSet - { - public Action Reset, Restore; - } - - Dictionary Handlers = new Dictionary(); - - public void Add(object o, string label, Action reset, Action restore) - { - ResetHandlerKey hkey = new ResetHandlerKey() { Object = o, Label = label }; - Handlers[hkey] = new HandlerSet { Reset = reset, Restore = restore }; - } - - public void Remove(object o, string label) - { - ResetHandlerKey hkey = new ResetHandlerKey() { Object = o, Label = label }; - if(Handlers.ContainsKey(hkey)) - Handlers.Remove(hkey); - } - - public void Reset() - { - foreach (var handler in Handlers) - handler.Value.Reset(); - } - - public void Restore() - { - var todo = Handlers.ToArray(); - Handlers.Clear(); - foreach (var item in todo) - item.Value.Restore(); - } - } - - - public IGraphicsControl Internal_CreateGraphicsControl() { var ret = new GLControlWrapper_SlimDX9(this);