Merge pull request #829 from TASVideos/d3dresetdevice
Cleanup Direct3D device reset code.
This commit is contained in:
commit
934e588a61
|
@ -37,9 +37,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
sdx.FreeControlSwapChain(this);
|
||||||
|
|
||||||
//if(MyBufferedGraphics != null)
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
IGL_SlimDX9 sdx;
|
IGL_SlimDX9 sdx;
|
||||||
|
|
|
@ -26,13 +26,15 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
|
|
||||||
public class IGL_SlimDX9 : IGL
|
public class IGL_SlimDX9 : IGL
|
||||||
{
|
{
|
||||||
|
const int D3DERR_DEVICELOST = -2005530520;
|
||||||
|
const int D3DERR_DEVICENOTRESET = -2005530519;
|
||||||
|
|
||||||
static Direct3D d3d;
|
static Direct3D d3d;
|
||||||
internal Device dev;
|
internal Device dev;
|
||||||
INativeWindow OffscreenNativeWindow;
|
INativeWindow OffscreenNativeWindow;
|
||||||
|
|
||||||
//rendering state
|
//rendering state
|
||||||
IntPtr _pVertexData;
|
IntPtr _pVertexData;
|
||||||
RenderTarget _CurrRenderTarget;
|
|
||||||
Pipeline _CurrPipeline;
|
Pipeline _CurrPipeline;
|
||||||
GLControlWrapper_SlimDX9 _CurrentControl;
|
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 (; ; )
|
for (; ; )
|
||||||
{
|
{
|
||||||
var result = dev.TestCooperativeLevel();
|
var result = dev.TestCooperativeLevel();
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
break;
|
break;
|
||||||
if (result.Code == -2005530519) // D3DERR_DEVICENOTRESET
|
if (result.Code == D3DERR_DEVICENOTRESET)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -107,7 +110,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
}
|
}
|
||||||
System.Threading.Thread.Sleep(100);
|
System.Threading.Thread.Sleep(100);
|
||||||
}
|
}
|
||||||
ResetHandlers.Restore();
|
RefreshControlSwapChain(control);
|
||||||
|
ResumeRenderTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateDevice()
|
public void CreateDevice()
|
||||||
|
@ -128,7 +132,6 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
|
|
||||||
void IDisposable.Dispose()
|
void IDisposable.Dispose()
|
||||||
{
|
{
|
||||||
ResetHandlers.Reset();
|
|
||||||
DestroyDevice();
|
DestroyDevice();
|
||||||
d3d.Dispose();
|
d3d.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -844,55 +847,56 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
}
|
}
|
||||||
catch(d3d9.Direct3D9Exception ex)
|
catch(d3d9.Direct3D9Exception ex)
|
||||||
{
|
{
|
||||||
if (ex.ResultCode.Name == "D3DERR_DEVICELOST")
|
if (ex.ResultCode.Code == D3DERR_DEVICELOST)
|
||||||
ResetDevice();
|
ResetDevice(control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashSet<RenderTarget> _renderTargets = new HashSet<RenderTarget>();
|
||||||
|
|
||||||
public void FreeRenderTarget(RenderTarget rt)
|
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;
|
var tw = rt.Texture2d.Opaque as TextureWrapper;
|
||||||
tw.Texture.Dispose();
|
tw.Texture.Dispose();
|
||||||
tw.Texture = null;
|
tw.Texture = null;
|
||||||
|
_renderTargets.Remove(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreRenderTarget(RenderTarget rt)
|
public RenderTarget CreateRenderTarget(int w, int h)
|
||||||
{
|
{
|
||||||
var tw = rt.Texture2d.Opaque as TextureWrapper;
|
var tw = new TextureWrapper() { Texture = CreateRenderTargetTexture(w, h) };
|
||||||
int w = rt.Texture2d.IntWidth;
|
var tex = new Texture2d(this, tw, w, h);
|
||||||
int h = rt.Texture2d.IntHeight;
|
var rt = new RenderTarget(this, tw, tex);
|
||||||
var d3dtex = new d3d9.Texture(dev, w, h, 1, d3d9.Usage.RenderTarget, d3d9.Format.A8R8G8B8, d3d9.Pool.Default);
|
_renderTargets.Add(rt);
|
||||||
tw.Texture = d3dtex;
|
return rt;
|
||||||
//i know it's weird, we have to re-add ourselves to the list
|
}
|
||||||
//bad design..
|
|
||||||
ResetHandlers.Add(rt, "RenderTarget", () => ResetRenderTarget(rt), () => RestoreRenderTarget(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)
|
public void BindRenderTarget(RenderTarget rt)
|
||||||
{
|
{
|
||||||
_CurrRenderTarget = rt;
|
|
||||||
|
|
||||||
if (rt == null)
|
if (rt == null)
|
||||||
{
|
{
|
||||||
//this dispose is needed for correct device resets, I have no idea why
|
//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;
|
dev.DepthStencilSurface = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshControlSwapChain(GLControlWrapper_SlimDX9 control)
|
public void FreeControlSwapChain(GLControlWrapper_SlimDX9 control)
|
||||||
{
|
{
|
||||||
if (control.SwapChain != null)
|
if (control.SwapChain != null)
|
||||||
{
|
{
|
||||||
control.SwapChain.Dispose();
|
control.SwapChain.Dispose();
|
||||||
control.SwapChain = null;
|
control.SwapChain = null;
|
||||||
}
|
}
|
||||||
ResetHandlers.Remove(control, "SwapChain");
|
}
|
||||||
|
|
||||||
|
public void RefreshControlSwapChain(GLControlWrapper_SlimDX9 control)
|
||||||
|
{
|
||||||
|
FreeControlSwapChain(control);
|
||||||
|
|
||||||
var pp = new PresentParameters
|
var pp = new PresentParameters
|
||||||
{
|
{
|
||||||
BackBufferWidth = Math.Max(8,control.ClientSize.Width),
|
BackBufferWidth = Math.Max(8,control.ClientSize.Width),
|
||||||
|
@ -932,71 +940,8 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
||||||
};
|
};
|
||||||
|
|
||||||
control.SwapChain = new SwapChain(dev, pp);
|
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<ResetHandlerKey, HandlerSet> Handlers = new Dictionary<ResetHandlerKey, HandlerSet>();
|
|
||||||
|
|
||||||
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()
|
public IGraphicsControl Internal_CreateGraphicsControl()
|
||||||
{
|
{
|
||||||
var ret = new GLControlWrapper_SlimDX9(this);
|
var ret = new GLControlWrapper_SlimDX9(this);
|
||||||
|
|
Loading…
Reference in New Issue