port from perforce
This commit is contained in:
134
intromat/Intromat/Graphics/DxHost.cs
Normal file
134
intromat/Intromat/Graphics/DxHost.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Intromat.DXExt;
|
||||
using Intromat.Pipelines;
|
||||
using SharpDX.Direct3D;
|
||||
using SharpDX.Direct3D9;
|
||||
using Splat;
|
||||
using D3D11 = SharpDX.Direct3D11;
|
||||
|
||||
namespace Intromat.Graphics
|
||||
{
|
||||
public class DxHost
|
||||
{
|
||||
public delegate void RenderDelegate(D3D11.Device device, D3D11.DeviceContext deviceContext);
|
||||
|
||||
public readonly ConcurrentQueue<RenderDelegate> _actionQueue;
|
||||
public readonly D3D11.Device Device;
|
||||
private readonly Thread _renderThread;
|
||||
private IntPtr _renderWindowHandle;
|
||||
public DeviceEx? D3D9Device;
|
||||
public Dispatcher? RenderDispatcher;
|
||||
public Dispatcher? MainDispatcher;
|
||||
private readonly ManualResetEvent _renderThreadStarted = new(false);
|
||||
public readonly D3D11.UserDefinedAnnotation? _annotation;
|
||||
public readonly GraphicsAnalysis? _graphicsAnalysis;
|
||||
|
||||
public DxHost()
|
||||
{
|
||||
#if DEBUG
|
||||
var flags = D3D11.DeviceCreationFlags.Debug;
|
||||
#else
|
||||
var flags = D3D11.DeviceCreationFlags.None;
|
||||
#endif
|
||||
Device = new D3D11.Device(DriverType.Hardware, flags);
|
||||
_annotation = Device.ImmediateContext.QueryInterface<D3D11.UserDefinedAnnotation>();
|
||||
_graphicsAnalysis = DebugInterface.TryCreateGraphicsAnalysis();
|
||||
|
||||
_actionQueue = new();
|
||||
_renderThread = new(RenderThreadStart) { Name = "WPF SwapChain" };
|
||||
_renderThread.SetApartmentState(ApartmentState.STA);
|
||||
_renderThread.Start();
|
||||
_renderThreadStarted.WaitOne();
|
||||
|
||||
var device = Device;
|
||||
var context = Device.ImmediateContext;
|
||||
MainDispatcher = Dispatcher.CurrentDispatcher;
|
||||
Locator.CurrentMutable.Register(() => new DisplayTexturePipeline(device, context));
|
||||
}
|
||||
|
||||
public void Load(Window window)
|
||||
{
|
||||
_renderWindowHandle = Process.GetCurrentProcess().MainWindowHandle;
|
||||
CreateDevice();
|
||||
}
|
||||
|
||||
public void Unload()
|
||||
{
|
||||
RenderDispatcher?.BeginInvokeShutdown(DispatcherPriority.Background);
|
||||
RenderDispatcher = null;
|
||||
}
|
||||
|
||||
private void RenderThreadStart(object? o)
|
||||
{
|
||||
RenderDispatcher = Dispatcher.CurrentDispatcher;
|
||||
RenderDispatcher.BeginInvoke(new Action(UpdateFrameTick));
|
||||
_renderThreadStarted.Set();
|
||||
Dispatcher.Run();
|
||||
}
|
||||
|
||||
private void UpdateFrameTick()
|
||||
{
|
||||
if (RenderDispatcher == null)
|
||||
return;
|
||||
|
||||
if (_actionQueue.Count == 0)
|
||||
{
|
||||
RenderDispatcher.BeginInvoke(new Action(UpdateFrameTick), DispatcherPriority.Background);
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureTargetDevice();
|
||||
while (_actionQueue.TryDequeue(out var action))
|
||||
action(Device, Device.ImmediateContext);
|
||||
|
||||
RenderDispatcher?.BeginInvoke(new Action(UpdateFrameTick), DispatcherPriority.Render);
|
||||
}
|
||||
|
||||
public void EnqueueAction(RenderDelegate action)
|
||||
{
|
||||
_actionQueue.Enqueue(action);
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr MonitorFromWindow(IntPtr hWnd, int flags);
|
||||
|
||||
private void EnsureTargetDevice()
|
||||
{
|
||||
if (D3D9Device != null)
|
||||
return;
|
||||
|
||||
MainDispatcher!.Invoke(CreateDevice);
|
||||
}
|
||||
|
||||
private void CreateDevice()
|
||||
{
|
||||
var d3d9Ex = new Direct3DEx();
|
||||
var adapter = 0;
|
||||
|
||||
if (d3d9Ex.AdapterCount > 1)
|
||||
{
|
||||
const int monitorDefaultToNearest = 2;
|
||||
var hMon = MonitorFromWindow(_renderWindowHandle, monitorDefaultToNearest);
|
||||
|
||||
foreach (var a in d3d9Ex.AdaptersEx)
|
||||
if (a.Monitor == hMon)
|
||||
adapter = a.Adapter;
|
||||
}
|
||||
|
||||
var parameters = new PresentParameters
|
||||
{
|
||||
PresentationInterval = PresentInterval.Immediate,
|
||||
SwapEffect = SwapEffect.Discard,
|
||||
Windowed = true
|
||||
};
|
||||
|
||||
D3D9Device = new DeviceEx(d3d9Ex, adapter, DeviceType.Hardware, _renderWindowHandle, CreateFlags.HardwareVertexProcessing | CreateFlags.FpuPreserve | CreateFlags.Multithreaded, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user