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(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; } }