XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Numerics;
using System.Security.Cryptography;
using Vortice.Direct3D11;
using Vortice.DXGI;
using XFEEDToolBox.Core.Rendering;

namespace XFEEDToolBox.Rendering;

internal sealed partial class GalaxyGraphics
{
    private ID3D11ComputeShader? originalManualExposureCs;
    private ID3D11Buffer? originalExposureConstants;
    private ID3D11Texture2D? originalExposureTexture;
    private ID3D11ShaderResourceView? originalExposureView;
    private ID3D11UnorderedAccessView? originalExposureOutput;
    private GalaxyOriginalManualExposureInputs? computedManualExposureControls;
    internal GalaxyOriginalExposureState OriginalExposureState {get;private set;}
    internal GalaxyOriginalHistogramResult? OriginalManualExposureResult {get;private set;}
    internal bool OriginalExposureReady=>originalExposureView is not null&&OriginalExposureState!=GalaxyOriginalExposureState.Uninitialized;
    internal bool OriginalExposureIsToolManual=>OriginalExposureState==GalaxyOriginalExposureState.ManualComputed;
    internal int OriginalExposureDispatches {get;private set;}

    private unsafe void InitializeOriginalExposure(string shader)
    {
        var path=Path.Combine(Path.GetDirectoryName(shader)!,"GalaxyManualExposure.dxbc");
        var bytes=File.ReadAllBytes(path);
        if(Convert.ToHexStringLower(SHA256.HashData(bytes))!="2a564f4d25375cf4421c9271fbe34a84091a407754124f5ebe1403b915563ca7")
            throw new InvalidDataException("原手动曝光计算程序校验失败。");
        originalManualExposureCs=device.CreateComputeShader(bytes);
        originalExposureConstants=device.CreateBuffer(128,BindFlags.ConstantBuffer);
        // Original 3521DD0: six R32_FLOAT texels, initially all zero. This
        // owned resource belongs to this tool view, not another game camera.
        var zeros=new float[6];
        fixed(float* data=zeros)
            originalExposureTexture=device.CreateTexture2D(new Texture2DDescription{
                Width=6,Height=1,Format=Format.R32_Float,ArraySize=1,MipLevels=1,SampleDescription=new(1,0),
                Usage=ResourceUsage.Default,BindFlags=BindFlags.ShaderResource|BindFlags.UnorderedAccess},
                [new SubresourceData((nint)data,24,24)]);
        originalExposureView=device.CreateShaderResourceView(originalExposureTexture);
        originalExposureOutput=device.CreateUnorderedAccessView(originalExposureTexture);
        OriginalExposureState=GalaxyOriginalExposureState.DefaultCreated;
        OriginalManualExposureResult=null;computedManualExposureControls=null;
    }

    // Manual exposure is scene independent. Cache only identical explicit
    // controls; auto exposure will require this view's own HDR scene analysis.
    private bool ComputeOriginalManualExposure(GalaxyOriginalManualExposureInputs? controls=null)
    {
        if(originalManualExposureCs is null||originalExposureOutput is null||originalExposureConstants is null)return false;
        var input=controls??GalaxyOriginalExposure.InitialManualControls;
        if(!GalaxyOriginalExposure.TryManualExposure(input,out var expected))
        {
            ResetOriginalExposureToDefault();return false;
        }
        if(OriginalExposureState==GalaxyOriginalExposureState.ManualComputed&&computedManualExposureControls==input)return true;
        context.PSSetShaderResource(20,null!);
        context.ClearUnorderedAccessView(originalExposureOutput,Vector4.Zero);
        context.UpdateSubresource<Vector4>(GalaxyOriginalExposure.ManualConstants(input),originalExposureConstants);
        context.CSSetShader(originalManualExposureCs);context.CSSetConstantBuffer(0,originalExposureConstants);
        context.CSSetUnorderedAccessView(0,originalExposureOutput);context.Dispatch(1,1,1);
        context.CSSetUnorderedAccessView(0,null!);context.CSSetConstantBuffer(0,null!);context.CSSetShader(null!);
        computedManualExposureControls=input;OriginalManualExposureResult=expected;
        OriginalExposureDispatches++;OriginalExposureState=GalaxyOriginalExposureState.ManualComputed;return true;
    }

    private void ResetOriginalExposureToDefault()
    {
        if(originalExposureOutput is null)return;
        context.PSSetShaderResource(20,null!);context.ClearUnorderedAccessView(originalExposureOutput,Vector4.Zero);
        OriginalExposureState=GalaxyOriginalExposureState.DefaultCreated;OriginalManualExposureResult=null;computedManualExposureControls=null;
    }

    private void DisposeOriginalExposure()
    {
        context.PSSetShaderResource(20,null!);context.CSSetUnorderedAccessView(0,null!);
        originalExposureView?.Dispose();originalExposureOutput?.Dispose();originalExposureTexture?.Dispose();
        originalExposureConstants?.Dispose();originalManualExposureCs?.Dispose();
        originalExposureView=null;originalExposureOutput=null;originalExposureTexture=null;originalExposureConstants=null;originalManualExposureCs=null;
        computedManualExposureControls=null;OriginalManualExposureResult=null;OriginalExposureState=GalaxyOriginalExposureState.Uninitialized;
    }
}