using System; using System.Numerics; using System.Runtime.InteropServices; using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; using TerraFX.Interop.DirectX; namespace Auspex.Rendering.Direct3D; internal sealed class SceneDepthCapture : IDisposable { private unsafe ID3D11Texture2D* _copy; private unsafe ID3D11ShaderResourceView* _copySRV; private uint _copyWidth; private uint _copyHeight; public unsafe ID3D11ShaderResourceView* SRV => _copySRV; public Vector2 UvScale { get; private set; } = new Vector2(1f, 1f); public bool IsResolutionScaled { get; private set; } public unsafe void Dispose() { if (_copySRV != null) { _copySRV->Release(); _copySRV = null; } if (_copy != null) { _copy->Release(); _copy = null; } GC.SuppressFinalize(this); } internal unsafe void Update() { RenderTargetManager* ptr = RenderTargetManager.Instance(); Texture* ptr2 = ((ptr != null) ? ptr->DepthStencil : null); if (ptr2 == null || ptr2->D3D11Texture2D == null) { AuspexService.Log.Warning("[Auspex] SceneDepthCapture: scene depth source unavailable."); return; } Device* ptr3 = Device.Instance(); IsResolutionScaled = ptr2->ActualWidth != ptr3->Width || ptr2->ActualHeight != ptr3->Height; ID3D11Texture2D* d3D11Texture2D = (ID3D11Texture2D*)ptr2->D3D11Texture2D; D3D11_TEXTURE2D_DESC srcDesc = default(D3D11_TEXTURE2D_DESC); d3D11Texture2D->GetDesc(&srcDesc); EnsureCopy(srcDesc); ID3D11DeviceContext* ptr4 = default(ID3D11DeviceContext*); ((ID3D11Device*)ptr3->D3D11Forwarder)->GetImmediateContext(&ptr4); ptr4->CopyResource((ID3D11Resource*)_copy, (ID3D11Resource*)d3D11Texture2D); ptr4->Release(); UvScale = new Vector2((ptr2->AllocatedWidth != 0) ? ((float)ptr2->ActualWidth / (float)ptr2->AllocatedWidth) : 1f, (ptr2->AllocatedHeight != 0) ? ((float)ptr2->ActualHeight / (float)ptr2->AllocatedHeight) : 1f); } private unsafe void EnsureCopy(D3D11_TEXTURE2D_DESC srcDesc) { if (_copy == null || _copyWidth != srcDesc.Width || _copyHeight != srcDesc.Height) { if (_copySRV != null) { _copySRV->Release(); _copySRV = null; } if (_copy != null) { _copy->Release(); _copy = null; } ID3D11Device* d3D11Forwarder = (ID3D11Device*)Device.Instance()->D3D11Forwarder; D3D11_TEXTURE2D_DESC d3D11_TEXTURE2D_DESC = srcDesc; d3D11_TEXTURE2D_DESC.Format = DXGI_FORMAT.DXGI_FORMAT_R24G8_TYPELESS; d3D11_TEXTURE2D_DESC.BindFlags = 8u; ID3D11Texture2D* copy = default(ID3D11Texture2D*); Marshal.ThrowExceptionForHR(d3D11Forwarder->CreateTexture2D(&d3D11_TEXTURE2D_DESC, null, ©)); _copy = copy; _copyWidth = srcDesc.Width; _copyHeight = srcDesc.Height; D3D11_SHADER_RESOURCE_VIEW_DESC d3D11_SHADER_RESOURCE_VIEW_DESC = new D3D11_SHADER_RESOURCE_VIEW_DESC { Format = DXGI_FORMAT.DXGI_FORMAT_R24_UNORM_X8_TYPELESS, ViewDimension = D3D_SRV_DIMENSION.D3D_SRV_DIMENSION_TEXTURE2D }; d3D11_SHADER_RESOURCE_VIEW_DESC.Texture2D.MostDetailedMip = 0u; d3D11_SHADER_RESOURCE_VIEW_DESC.Texture2D.MipLevels = 1u; ID3D11ShaderResourceView* copySRV = default(ID3D11ShaderResourceView*); Marshal.ThrowExceptionForHR(d3D11Forwarder->CreateShaderResourceView((ID3D11Resource*)_copy, &d3D11_SHADER_RESOURCE_VIEW_DESC, ©SRV)); _copySRV = copySRV; } } }