214 lines
5.5 KiB
C#
214 lines
5.5 KiB
C#
using System;
|
|
using SharpDX;
|
|
using SharpDX.Direct3D;
|
|
using Windows.Foundation;
|
|
using Dx11 = SharpDX.Direct3D11;
|
|
using PresentationParameters = ANX.Framework.Graphics.PresentationParameters;
|
|
|
|
// This file is part of the ANX.Framework created by the
|
|
// "ANX.Framework developer group" and released under the Ms-PL license.
|
|
// For details see: http://anxframework.codeplex.com/license
|
|
|
|
namespace ANX.RenderSystem.Windows.Metro
|
|
{
|
|
public class NativeDxDevice : IDisposable
|
|
{
|
|
#region Private
|
|
private PresentationParameters presentationParameters;
|
|
private FeatureLevel featureLevel;
|
|
private Dx11.RenderTargetView renderTargetView;
|
|
private Dx11.DepthStencilView depthStencilView;
|
|
private SwapChainMetro swapChain;
|
|
private Dx11.Device1 nativeDevice;
|
|
private Dx11.DeviceContext1 nativeContext;
|
|
|
|
internal Dx11.Device1 NativeDevice
|
|
{
|
|
get
|
|
{
|
|
return nativeDevice;
|
|
}
|
|
}
|
|
|
|
internal Dx11.DeviceContext1 NativeContext
|
|
{
|
|
get
|
|
{
|
|
return nativeContext;
|
|
}
|
|
}
|
|
|
|
internal Dx11.OutputMergerStage OutputMerger
|
|
{
|
|
get
|
|
{
|
|
return nativeContext.OutputMerger;
|
|
}
|
|
}
|
|
|
|
internal static NativeDxDevice Current
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
#endregion
|
|
|
|
#region Public
|
|
public Rect RenderTargetBounds
|
|
{
|
|
get;
|
|
protected set;
|
|
}
|
|
#endregion
|
|
|
|
#region Constructor
|
|
public NativeDxDevice(PresentationParameters presentationParameters)
|
|
{
|
|
Current = this;
|
|
|
|
this.presentationParameters = presentationParameters;
|
|
swapChain = new SwapChainMetro(this, presentationParameters);
|
|
|
|
var creationFlags = Dx11.DeviceCreationFlags.VideoSupport | Dx11.DeviceCreationFlags.BgraSupport;
|
|
#if DEBUG
|
|
creationFlags |= Dx11.DeviceCreationFlags.Debug;
|
|
#endif
|
|
using (var defaultDevice = new Dx11.Device(DriverType.Hardware, creationFlags))
|
|
{
|
|
nativeDevice = defaultDevice.QueryInterface<Dx11.Device1>();
|
|
}
|
|
featureLevel = NativeDevice.FeatureLevel;
|
|
|
|
nativeContext = NativeDevice.ImmediateContext.QueryInterface<Dx11.DeviceContext1>();
|
|
}
|
|
#endregion
|
|
|
|
#region Resize
|
|
public void Resize(PresentationParameters presentationParameters)
|
|
{
|
|
DisposeScreenBuffers();
|
|
|
|
swapChain.ResizeOrCreate(presentationParameters);
|
|
|
|
using (var backBuffer = swapChain.CreateTexture())
|
|
{
|
|
renderTargetView = new Dx11.RenderTargetView(NativeDevice, backBuffer);
|
|
|
|
var backBufferDesc = backBuffer.Description;
|
|
RenderTargetBounds = new Rect(0, 0, backBufferDesc.Width, backBufferDesc.Height);
|
|
}
|
|
|
|
using (var depthBuffer = new Dx11.Texture2D(NativeDevice, new Dx11.Texture2DDescription()
|
|
{
|
|
Format = FormatConverter.Translate(presentationParameters.DepthStencilFormat),
|
|
ArraySize = 1,
|
|
MipLevels = 1,
|
|
Width = (int)RenderTargetBounds.Width,
|
|
Height = (int)RenderTargetBounds.Height,
|
|
SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
|
|
BindFlags = Dx11.BindFlags.DepthStencil,
|
|
}))
|
|
{
|
|
depthStencilView = new Dx11.DepthStencilView(NativeDevice, depthBuffer, new Dx11.DepthStencilViewDescription()
|
|
{
|
|
Dimension = Dx11.DepthStencilViewDimension.Texture2D
|
|
});
|
|
}
|
|
|
|
var viewport = new Dx11.Viewport((float)RenderTargetBounds.X, (float)RenderTargetBounds.Y,
|
|
(float)RenderTargetBounds.Width, (float)RenderTargetBounds.Height, 0.0f, 1.0f);
|
|
|
|
nativeContext.Rasterizer.SetViewports(viewport);
|
|
|
|
nativeContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);
|
|
}
|
|
#endregion
|
|
|
|
#region ClearDepthAndStencil
|
|
public void ClearDepthAndStencil(Dx11.DepthStencilClearFlags flags, float depth, byte stencil)
|
|
{
|
|
// TODO: find better solution to lazy init the swapChain from the coreWindow!!
|
|
EnsureScreenBuffersAvailable();
|
|
|
|
nativeContext.ClearDepthStencilView(depthStencilView, flags, depth, stencil);
|
|
}
|
|
#endregion
|
|
|
|
#region Clear
|
|
public void Clear(Color4 color)
|
|
{
|
|
// TODO: find better solution to lazy init the swapChain from the coreWindow!!
|
|
EnsureScreenBuffersAvailable();
|
|
|
|
nativeContext.ClearRenderTargetView(renderTargetView, color);
|
|
}
|
|
#endregion
|
|
|
|
#region EnsureScreenBuffersAvailable
|
|
private void EnsureScreenBuffersAvailable()
|
|
{
|
|
if (renderTargetView == null)
|
|
{
|
|
Resize(presentationParameters);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Present
|
|
public void Present(int interval)
|
|
{
|
|
swapChain.Present(interval);
|
|
}
|
|
#endregion
|
|
|
|
#region MapSubresource
|
|
public SharpDX.DataBox MapSubresource(Dx11.Buffer resource,
|
|
out SharpDX.DataStream stream)
|
|
{
|
|
return nativeContext.MapSubresource(resource, Dx11.MapMode.WriteDiscard,
|
|
Dx11.MapFlags.None, out stream);
|
|
}
|
|
|
|
public SharpDX.DataBox MapSubresource(Dx11.Resource resource, int subresource)
|
|
{
|
|
return nativeContext.MapSubresource(resource, subresource,
|
|
Dx11.MapMode.WriteDiscard, Dx11.MapFlags.None);
|
|
}
|
|
#endregion
|
|
|
|
#region UnmapSubresource
|
|
public void UnmapSubresource(Dx11.Resource resource, int subresource)
|
|
{
|
|
nativeContext.UnmapSubresource(resource, subresource);
|
|
}
|
|
#endregion
|
|
|
|
#region Dispose
|
|
public void Dispose()
|
|
{
|
|
DisposeScreenBuffers();
|
|
|
|
SafeDispose(ref swapChain);
|
|
SafeDispose(ref nativeDevice);
|
|
SafeDispose(ref nativeContext);
|
|
}
|
|
|
|
private void DisposeScreenBuffers()
|
|
{
|
|
SafeDispose(ref renderTargetView);
|
|
SafeDispose(ref depthStencilView);
|
|
}
|
|
|
|
private void SafeDispose<T>(ref T disposable)
|
|
where T : class, IDisposable
|
|
{
|
|
if (disposable != null)
|
|
{
|
|
disposable.Dispose();
|
|
disposable = null;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|