293 lines
11 KiB
C#
293 lines
11 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using TerraFX.Interop.DirectX;
|
|
using TerraFX.Interop.Windows;
|
|
|
|
namespace Auspex.Rendering.Direct3D;
|
|
|
|
internal sealed class FrameRenderTarget : IDisposable
|
|
{
|
|
private unsafe ID3D11Texture2D* _baseRT;
|
|
|
|
private unsafe ID3D11RenderTargetView* _baseRTV;
|
|
|
|
private unsafe ID3D11ShaderResourceView* _baseSRV;
|
|
|
|
private unsafe ID3D11Texture2D* _processedRT;
|
|
|
|
private unsafe ID3D11RenderTargetView* _processedRTV;
|
|
|
|
private unsafe ID3D11ShaderResourceView* _processedSRV;
|
|
|
|
private unsafe ID3D11Texture2D* _backBufferCopy;
|
|
|
|
private unsafe ID3D11ShaderResourceView* _backBufferSRV;
|
|
|
|
private unsafe ID3D11Texture2D* _clipStencil;
|
|
|
|
private unsafe ID3D11DepthStencilView* _clipStencilDSV;
|
|
|
|
private unsafe ID3D11BlendState* _defaultBlendState;
|
|
|
|
private unsafe ID3D11BlendState* _fspBlendState;
|
|
|
|
public Vector2 Size { get; private set; }
|
|
|
|
public uint Width => (uint)Size.X;
|
|
|
|
public uint Height => (uint)Size.Y;
|
|
|
|
internal unsafe ID3D11DepthStencilView* ClipStencilDSV => _clipStencilDSV;
|
|
|
|
internal unsafe ID3D11RenderTargetView* BaseRTV => _baseRTV;
|
|
|
|
public unsafe IntPtr ImguiHandle => (nint)_processedSRV;
|
|
|
|
public AxTexture Texture => new AxTexture(ImguiHandle, Width, Height);
|
|
|
|
public unsafe FrameRenderTarget(FrameRenderContext ctx, int width, int height, AlphaBlendMode blendMode)
|
|
{
|
|
Size = new Vector2(width, height);
|
|
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC = new D3D11_TEXTURE2D_DESC
|
|
{
|
|
Width = (uint)width,
|
|
Height = (uint)height,
|
|
MipLevels = 1u,
|
|
ArraySize = 1u,
|
|
Format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
SampleDesc = new DXGI_SAMPLE_DESC
|
|
{
|
|
Count = 1u,
|
|
Quality = 0u
|
|
},
|
|
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
|
|
BindFlags = 40u,
|
|
CPUAccessFlags = 0u,
|
|
MiscFlags = 0u
|
|
};
|
|
ID3D11Texture2D* ptr = default(ID3D11Texture2D*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateTexture2D(&d3D11_TEXTURE2D_DESC, null, &ptr));
|
|
_baseRT = ptr;
|
|
ID3D11RenderTargetView* ptr2 = default(ID3D11RenderTargetView*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateRenderTargetView((ID3D11Resource*)_baseRT, null, &ptr2));
|
|
_baseRTV = ptr2;
|
|
ID3D11ShaderResourceView* ptr3 = default(ID3D11ShaderResourceView*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateShaderResourceView((ID3D11Resource*)_baseRT, null, &ptr3));
|
|
_baseSRV = ptr3;
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateTexture2D(&d3D11_TEXTURE2D_DESC, null, &ptr));
|
|
_processedRT = ptr;
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateRenderTargetView((ID3D11Resource*)_processedRT, null, &ptr2));
|
|
_processedRTV = ptr2;
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateShaderResourceView((ID3D11Resource*)_processedRT, null, &ptr3));
|
|
_processedSRV = ptr3;
|
|
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC2 = new D3D11_TEXTURE2D_DESC
|
|
{
|
|
Width = (uint)width,
|
|
Height = (uint)height,
|
|
MipLevels = 1u,
|
|
ArraySize = 1u,
|
|
Format = DXGI_FORMAT.DXGI_FORMAT_R24G8_TYPELESS,
|
|
SampleDesc = new DXGI_SAMPLE_DESC
|
|
{
|
|
Count = 1u,
|
|
Quality = 0u
|
|
},
|
|
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
|
|
BindFlags = 64u,
|
|
CPUAccessFlags = 0u,
|
|
MiscFlags = 0u
|
|
};
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateTexture2D(&d3D11_TEXTURE2D_DESC2, null, &ptr));
|
|
_clipStencil = ptr;
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC d3D11_DEPTH_STENCIL_VIEW_DESC = new D3D11_DEPTH_STENCIL_VIEW_DESC
|
|
{
|
|
Format = DXGI_FORMAT.DXGI_FORMAT_D24_UNORM_S8_UINT,
|
|
ViewDimension = D3D11_DSV_DIMENSION.D3D11_DSV_DIMENSION_TEXTURE2D
|
|
};
|
|
d3D11_DEPTH_STENCIL_VIEW_DESC.Texture2D.MipSlice = 0u;
|
|
ID3D11DepthStencilView* clipStencilDSV = default(ID3D11DepthStencilView*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateDepthStencilView((ID3D11Resource*)_clipStencil, &d3D11_DEPTH_STENCIL_VIEW_DESC, &clipStencilDSV));
|
|
_clipStencilDSV = clipStencilDSV;
|
|
D3D11_BLEND_DESC d3D11_BLEND_DESC = default(D3D11_BLEND_DESC);
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).RenderTargetWriteMask = 15;
|
|
if (blendMode != AlphaBlendMode.None)
|
|
{
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).BlendEnable = true;
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).SrcBlend = D3D11_BLEND.D3D11_BLEND_SRC_ALPHA;
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).DestBlend = D3D11_BLEND.D3D11_BLEND_INV_SRC_ALPHA;
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).BlendOp = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD;
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).SrcBlendAlpha = D3D11_BLEND.D3D11_BLEND_ONE;
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).DestBlendAlpha = D3D11_BLEND.D3D11_BLEND_INV_SRC_ALPHA;
|
|
switch (blendMode)
|
|
{
|
|
case AlphaBlendMode.Add:
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).BlendOpAlpha = D3D11_BLEND_OP.D3D11_BLEND_OP_ADD;
|
|
break;
|
|
case AlphaBlendMode.Max:
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).BlendOpAlpha = D3D11_BLEND_OP.D3D11_BLEND_OP_MAX;
|
|
break;
|
|
}
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC.RenderTarget).RenderTargetWriteMask = 15;
|
|
}
|
|
ID3D11BlendState* ptr4 = default(ID3D11BlendState*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateBlendState(&d3D11_BLEND_DESC, &ptr4));
|
|
_defaultBlendState = ptr4;
|
|
D3D11_BLEND_DESC d3D11_BLEND_DESC2 = default(D3D11_BLEND_DESC);
|
|
global::_003CPrivateImplementationDetails_003E.InlineArrayFirstElementRef<D3D11_BLEND_DESC._RenderTarget_e__FixedBuffer, D3D11_RENDER_TARGET_BLEND_DESC>(ref d3D11_BLEND_DESC2.RenderTarget).RenderTargetWriteMask = 15;
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateBlendState(&d3D11_BLEND_DESC2, &ptr4));
|
|
_fspBlendState = ptr4;
|
|
}
|
|
|
|
public unsafe void Bind(FrameRenderContext ctx)
|
|
{
|
|
byte* intPtr = stackalloc byte[16];
|
|
// IL initblk instruction
|
|
Unsafe.InitBlock(intPtr, 0, 16);
|
|
float* colorRGBA = (float*)intPtr;
|
|
ctx.Context->ClearRenderTargetView(_baseRTV, colorRGBA);
|
|
D3D11_VIEWPORT d3D11_VIEWPORT = new D3D11_VIEWPORT
|
|
{
|
|
TopLeftX = 0f,
|
|
TopLeftY = 0f,
|
|
Width = Size.X,
|
|
Height = Size.Y,
|
|
MinDepth = 0f,
|
|
MaxDepth = 1f
|
|
};
|
|
ctx.Context->RSSetViewports(1u, &d3D11_VIEWPORT);
|
|
ctx.Context->OMSetBlendState(_defaultBlendState, null, uint.MaxValue);
|
|
ID3D11RenderTargetView* baseRTV = _baseRTV;
|
|
ctx.Context->OMSetRenderTargets(1u, &baseRTV, null);
|
|
}
|
|
|
|
public unsafe void CopyBaseToProcessed(FrameRenderContext ctx)
|
|
{
|
|
ctx.Context->CopyResource((ID3D11Resource*)_processedRT, (ID3D11Resource*)_baseRT);
|
|
}
|
|
|
|
public unsafe void ExecuteFSP(FrameRenderContext ctx, ID3D11Texture2D* backBuffer, FullscreenPassShader fsp, bool clipNativeUI)
|
|
{
|
|
if (clipNativeUI)
|
|
{
|
|
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC = default(D3D11_TEXTURE2D_DESC);
|
|
backBuffer->GetDesc(&d3D11_TEXTURE2D_DESC);
|
|
ValidateBackBufferResources(ctx.Device, &d3D11_TEXTURE2D_DESC);
|
|
ctx.Context->CopyResource((ID3D11Resource*)_backBufferCopy, (ID3D11Resource*)backBuffer);
|
|
}
|
|
ctx.Context->OMSetBlendState(_fspBlendState, null, uint.MaxValue);
|
|
byte* intPtr = stackalloc byte[16];
|
|
// IL initblk instruction
|
|
Unsafe.InitBlock(intPtr, 0, 16);
|
|
float* colorRGBA = (float*)intPtr;
|
|
ctx.Context->ClearRenderTargetView(_processedRTV, colorRGBA);
|
|
ID3D11RenderTargetView* processedRTV = _processedRTV;
|
|
ctx.Context->OMSetRenderTargets(1u, &processedRTV, null);
|
|
fsp.Draw(ctx, _baseSRV, _backBufferSRV);
|
|
}
|
|
|
|
private unsafe void ValidateBackBufferResources(ID3D11Device* device, D3D11_TEXTURE2D_DESC* backBufferDesc)
|
|
{
|
|
bool flag = _backBufferCopy == null;
|
|
if (!flag)
|
|
{
|
|
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC = default(D3D11_TEXTURE2D_DESC);
|
|
_backBufferCopy->GetDesc(&d3D11_TEXTURE2D_DESC);
|
|
flag = d3D11_TEXTURE2D_DESC.Width != backBufferDesc->Width || d3D11_TEXTURE2D_DESC.Height != backBufferDesc->Height;
|
|
}
|
|
if (flag)
|
|
{
|
|
if (_backBufferCopy != null)
|
|
{
|
|
_backBufferCopy->Release();
|
|
_backBufferCopy = null;
|
|
}
|
|
if (_backBufferSRV != null)
|
|
{
|
|
_backBufferSRV->Release();
|
|
_backBufferSRV = null;
|
|
}
|
|
D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC2 = *backBufferDesc;
|
|
d3D11_TEXTURE2D_DESC2.BindFlags = 8u;
|
|
ID3D11Texture2D* backBufferCopy = default(ID3D11Texture2D*);
|
|
HRESULT hRESULT = device->CreateTexture2D(&d3D11_TEXTURE2D_DESC2, null, &backBufferCopy);
|
|
Marshal.ThrowExceptionForHR(hRESULT);
|
|
_backBufferCopy = backBufferCopy;
|
|
ID3D11ShaderResourceView* backBufferSRV = default(ID3D11ShaderResourceView*);
|
|
hRESULT = device->CreateShaderResourceView((ID3D11Resource*)_backBufferCopy, null, &backBufferSRV);
|
|
if (hRESULT < 0)
|
|
{
|
|
_backBufferCopy->Release();
|
|
_backBufferCopy = null;
|
|
Marshal.ThrowExceptionForHR(hRESULT);
|
|
}
|
|
_backBufferSRV = backBufferSRV;
|
|
}
|
|
}
|
|
|
|
public unsafe void Dispose()
|
|
{
|
|
GC.SuppressFinalize(this);
|
|
if (_baseRT != null)
|
|
{
|
|
_baseRT->Release();
|
|
_baseRT = null;
|
|
}
|
|
if (_baseRTV != null)
|
|
{
|
|
_baseRTV->Release();
|
|
_baseRTV = null;
|
|
}
|
|
if (_baseSRV != null)
|
|
{
|
|
_baseSRV->Release();
|
|
_baseSRV = null;
|
|
}
|
|
if (_processedRT != null)
|
|
{
|
|
_processedRT->Release();
|
|
_processedRT = null;
|
|
}
|
|
if (_processedRTV != null)
|
|
{
|
|
_processedRTV->Release();
|
|
_processedRTV = null;
|
|
}
|
|
if (_processedSRV != null)
|
|
{
|
|
_processedSRV->Release();
|
|
_processedSRV = null;
|
|
}
|
|
if (_backBufferCopy != null)
|
|
{
|
|
_backBufferCopy->Release();
|
|
_backBufferCopy = null;
|
|
}
|
|
if (_backBufferSRV != null)
|
|
{
|
|
_backBufferSRV->Release();
|
|
_backBufferSRV = null;
|
|
}
|
|
if (_clipStencilDSV != null)
|
|
{
|
|
_clipStencilDSV->Release();
|
|
_clipStencilDSV = null;
|
|
}
|
|
if (_clipStencil != null)
|
|
{
|
|
_clipStencil->Release();
|
|
_clipStencil = null;
|
|
}
|
|
if (_defaultBlendState != null)
|
|
{
|
|
_defaultBlendState->Release();
|
|
_defaultBlendState = null;
|
|
}
|
|
if (_fspBlendState != null)
|
|
{
|
|
_fspBlendState->Release();
|
|
_fspBlendState = null;
|
|
}
|
|
}
|
|
}
|