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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Numerics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text.Json;
using Vortice.Direct3D;
using Vortice.Direct3D11;
using Vortice.DXGI;
using Vortice.Mathematics;
using XFEEDToolBox.Core.Galaxy;
using XFEEDToolBox.Core.Rendering;
using XFEEDToolBox.Rendering;
using static Vortice.Direct3D11.D3D11;

const int width=640,height=360;
D3D11CreateDevice(IntPtr.Zero,DriverType.Warp,DeviceCreationFlags.BgraSupport,[FeatureLevel.Level_11_0],out var device,out _,out var context).CheckError();
using var d=device;using var c=context;using var renderer=new GalaxyGraphics(device,context);
using var texture=device.CreateTexture2D(Format.R32G32B32A32_Float,width,height,mipLevels:1,bindFlags:BindFlags.RenderTarget);
using var target=device.CreateRenderTargetView(texture);
using var rasterizer=device.CreateRasterizerState(new RasterizerDescription(CullMode.None,FillMode.Solid));
using var noDepth=device.CreateDepthStencilState(new DepthStencilDescription(false,DepthWriteMask.Zero,ComparisonFunction.Always));
context.RSSetViewport(new Viewport(width,height));context.RSSetState(rasterizer);context.OMSetDepthStencilState(noDepth);
var output=Path.GetFullPath("artifacts/galaxy-hdr-shader-validation");Directory.CreateDirectory(output);
var inputs=new[]{new Vector3(0),new Vector3(.0001f,.001f,.01f),new Vector3(.1f,.5f,1),new Vector3(2,5,20),new Vector3(100,1000,10000)};
var sampleReports=new List<object>();
foreach(var linear in inputs)
{
    var stored=linear*GalaxyOriginalHdr.WriteScale;
    renderer.Solid(width,height,new(stored,1));renderer.Composite(target);var actual=Read();
    renderer.OriginalComposite(target);var original=Read();
    var expected=GalaxyOriginalHdr.ToneMap(stored);var centre=(height/2*width+width/2)*4;
    var translated=new Vector3(actual[centre],actual[centre+1],actual[centre+2]);
    var source=new Vector3(original[centre],original[centre+1],original[centre+2]);
    var difference=Vector3.Abs(translated-source);var cpuDifference=Vector3.Abs(translated-expected);
    if(Max(difference)>.00005f||Max(cpuDifference)>.002f||!float.IsFinite(translated.X+translated.Y+translated.Z))
        throw new InvalidOperationException($"Original HDR PS mismatch{linear}:ported{translated},source{source},cpu{expected}");
    sampleReports.Add(new{linear=new[]{linear.X,linear.Y,linear.Z},translated=new[]{translated.X,translated.Y,translated.Z},
        original=new[]{source.X,source.Y,source.Z},maximumDifference=Max(difference),cpuDifference=Max(cpuDifference)});
}
var views=new List<object>();
foreach(var withClouds in new[]{false,true})
foreach(var(name,focus,yaw,pitch,scale)in new[]{("sol",new XFEEDToolBox.Core.Models.Coordinates(0,0,0),-.3,.45,4d),
    ("centre",new XFEEDToolBox.Core.Models.Coordinates(15,-30,25895),-.3,.45,.5),
    ("above",new XFEEDToolBox.Core.Models.Coordinates(15,20000,25895),-.3,.7,.05)})
{
    var camera=GalaxyCamera.Create(focus,width,height,yaw,pitch,scale);
    renderer.Scene(camera,width,height,withClouds);renderer.Composite(target);var actual=Read();
    renderer.OriginalComposite(target);var original=Read();
    double sum=0,brightness=0;var maximum=0f;var nonfinite=0;var bgra=new byte[width*height*4];
    for(var i=0;i<actual.Length;i++)
    {
        if(!float.IsFinite(actual[i])||!float.IsFinite(original[i])){nonfinite++;continue;}
        var difference=Math.Abs(actual[i]-original[i]);maximum=Math.Max(maximum,difference);sum+=difference;
        if(i%4<3)brightness+=actual[i];
    }
    if(nonfinite!=0||maximum>.001)throw new InvalidOperationException($"Core→originalHDR mismatch{name}:max{maximum},nonfinite{nonfinite}");
    for(var i=0;i<actual.Length;i+=4){bgra[i]=(byte)(Math.Clamp(actual[i+2],0,1)*255);bgra[i+1]=(byte)(Math.Clamp(actual[i+1],0,1)*255);bgra[i+2]=(byte)(Math.Clamp(actual[i],0,1)*255);bgra[i+3]=255;}
    File.WriteAllBytes(Path.Combine(output,name+(withClouds?"-clouds":"")+".bgra"),bgra);
    views.Add(new{name,withClouds,width,height,maximumDifference=maximum,meanDifference=sum/actual.Length,nonfinite,
        meanRgb=brightness/(width*height*3),sourceWrite=GalaxyOriginalHdr.WriteScale,sourceRead=GalaxyOriginalHdr.ReadScale,
        coreColourBlend="SourceColor/One",cloudColourBlend="SourceAlpha/One",cloudInstances=withClouds?renderer.OriginalMilkyWayInstances:0,
        toneMapPass=5,constructorDefaultsOnly=true,fullOutputRestored=false});
}
var ratioReport=renderer.VerifyMilkyWayWrite(width,height);
var result=new{actualOriginalPsCompared=true,samples=sampleReports,coreViews=views,milkyWayWriteRatio=ratioReport};
File.WriteAllText(Path.Combine(output,"report.json"),JsonSerializer.Serialize(result,new JsonSerializerOptions{WriteIndented=true}));Console.WriteLine(JsonSerializer.Serialize(result));
float Max(Vector3 value)=>Math.Max(value.X,Math.Max(value.Y,value.Z));
float[] Read()
{
    context.OMSetRenderTargets(Array.Empty<ID3D11RenderTargetView>());var desc=texture.Description;desc.BindFlags=BindFlags.None;desc.CPUAccessFlags=CpuAccessFlags.Read;desc.Usage=ResourceUsage.Staging;
    using var staging=device.CreateTexture2D(desc);context.CopyResource(staging,texture);var mapped=context.Map(staging,0,MapMode.Read);var values=new float[width*height*4];
    for(var y=0;y<height;y++)Marshal.Copy(mapped.DataPointer+(int)(y*mapped.RowPitch),values,y*width*4,width*4);context.Unmap(staging,0);return values;
}

namespace XFEEDToolBox.Rendering
{
    internal sealed partial class GalaxyGraphics:IDisposable
    {
        private readonly ID3D11Device device;private readonly ID3D11DeviceContext context;private readonly ID3D11BlendState additive;
        private readonly ID3D11PixelShader sourcePs;private readonly ID3D11Buffer sourceConstants;
        private readonly ID3D11SamplerState sampler;
        private bool disposed;
        internal event Action? ResourcesChanged;
        internal int DrawCalls;
        internal GalaxyGraphics(ID3D11Device d,ID3D11DeviceContext c)
        {
            device=d;context=c;additive=d.CreateBlendState(new BlendDescription(Blend.One,Blend.One));
            InitializeOriginalHdr(Path.GetFullPath("XFEEDToolBox/Assets/GalaxyHdr.hlsl"));
            InitializeOriginalCore(Path.GetFullPath("XFEEDToolBox/Assets/GalaxyCore.hlsl"));
            sampler=d.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Clamp,TextureAddressMode.Clamp,TextureAddressMode.Clamp));
            InitializeOriginalMilkyWay(Path.GetFullPath("XFEEDToolBox/Assets/GalaxyMap.hlsl"));
            originalMilkyWayCpu.Value.GetAwaiter().GetResult();
            const string name="ps_ApplyToneMapping_FilmicU2_ManExposure_0_0_0_0_0_0_1_0_Win64_SM50";
            var folder="artifacts/galaxy-query-research/power-outer-sources/background/hdr-programs/final-hdr/";
            var bytes=File.ReadAllBytes(folder+name+".dxbc");
            if(Convert.ToHexStringLower(SHA256.HashData(bytes))!="425b3ddca23b606d0501a9cde6047278c3ff0f5153853d12ae1e32e0fb3300da")
                throw new InvalidDataException("Original HDR PS changed");
            sourcePs=d.CreatePixelShader(bytes);sourceConstants=d.CreateBuffer(11*16,BindFlags.ConstantBuffer);
        }
        internal void Solid(int width,int height,Color4 colour)=>BeginOriginalHdr(width,height,colour);
        internal void Scene(GalaxyCamera camera,int width,int height,bool clouds)
        {
            BeginOriginalHdr(width,height,new Color4(0,0,0,0));
            DrawOriginalMilkyWay(camera,clouds,GalaxyOriginalHdr.WriteScale);
            DrawOriginalCore(camera,true,GalaxyOriginalHdr.WriteScale,GalaxyOriginalHdr.ReadScale);
        }
        internal void Composite(ID3D11RenderTargetView target)=>EndOriginalHdr(target);
        internal void OriginalComposite(ID3D11RenderTargetView target)
        {
            context.OMSetRenderTargets(target);context.OMSetBlendState(null);context.IASetInputLayout(null);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
            context.VSSetShader(originalHdrVs);context.PSSetShader(sourcePs);
            context.UpdateSubresource<Vector4>(GalaxyOriginalHdr.Constants(originalHdrWidth,originalHdrHeight),sourceConstants);
            context.PSSetConstantBuffer(2,sourceConstants);context.PSSetShaderResource(0,originalHdrView!);context.PSSetSampler(0,originalHdrSampler);
            context.Draw(3,0);context.PSSetShaderResource(0,null!);
        }
        internal object VerifyMilkyWayWrite(int width,int height)
        {
            var camera=GalaxyCamera.Create(new(15,20000,25895),width,height,-.3,.7,.05);
            BeginOriginalHdr(width,height,new Color4(0,0,0,0));DrawOriginalMilkyWay(camera,true,1);var unit=ReadScene();
            BeginOriginalHdr(width,height,new Color4(0,0,0,0));DrawOriginalMilkyWay(camera,true,GalaxyOriginalHdr.WriteScale);var scaled=ReadScene();
            var maximum=0f;var compared=0;double sum=0;
            for(var i=0;i<unit.Length;i++)
            {
                if(i%4==3||unit[i]<.001f)continue;
                var restored=scaled[i]*GalaxyOriginalHdr.ReadScale;var difference=Math.Abs(unit[i]-restored);
                maximum=Math.Max(maximum,difference);sum+=difference;compared++;
            }
            if(compared<100||maximum>.002f||sum/compared>.0001)
                throw new InvalidOperationException($"MilkyWay production HDR Write not reciprocal:max{maximum},values{compared},mean{sum/Math.Max(1,compared)}");
            return new{comparedRgbValues=compared,maximumDifference=maximum,meanDifference=sum/compared,
                read=GalaxyOriginalHdr.ReadScale,write=GalaxyOriginalHdr.WriteScale,actualProductionMethodUsed=true};
        }
        private float[] ReadScene()
        {
            context.OMSetRenderTargets(Array.Empty<ID3D11RenderTargetView>());var desc=originalHdrTexture!.Description;
            desc.Format=Format.R16G16B16A16_Float;desc.BindFlags=BindFlags.None;desc.Usage=ResourceUsage.Staging;desc.CPUAccessFlags=CpuAccessFlags.Read;
            using var copy=device.CreateTexture2D(desc);context.CopyResource(copy,originalHdrTexture);var mapped=context.Map(copy,0,MapMode.Read);
            var shorts=new short[originalHdrWidth*originalHdrHeight*4];
            for(var y=0;y<originalHdrHeight;y++)Marshal.Copy(mapped.DataPointer+(int)(y*mapped.RowPitch),shorts,y*originalHdrWidth*4,originalHdrWidth*4);
            context.Unmap(copy,0);return shorts.Select(s=>(float)BitConverter.Int16BitsToHalf(s)).ToArray();
        }
        private unsafe void Upload<T>(ID3D11Buffer buffer,ReadOnlySpan<T> values)where T:unmanaged
        {
            var mapped=context.Map(buffer,0,MapMode.WriteDiscard);
            try{MemoryMarshal.AsBytes(values).CopyTo(new Span<byte>((void*)mapped.DataPointer,values.Length*sizeof(T)));}
            finally{context.Unmap(buffer,0);}
        }
        public void Dispose(){disposed=true;DisposeOriginalHdr();DisposeOriginalCore();DisposeOriginalMilkyWay();sourcePs.Dispose();sourceConstants.Dispose();sampler.Dispose();additive.Dispose();}
    }
}

namespace XFEEDToolBox
{
    // Offline harness only: the production partial's completion notification
    // is delivered without creating, activating or controlling any window.
    internal static class App
    {
        internal static readonly HarnessWindow MainWindow=new();
        internal static readonly HarnessRuntime Runtime=new();
    }
    internal sealed class HarnessWindow{internal HarnessQueue DispatcherQueue{get;}=new();}
    internal sealed class HarnessQueue{internal bool TryEnqueue(Action action){action();return true;}}
    internal sealed class HarnessRuntime{internal void Log(string area,string message)=>Console.Error.WriteLine(area+": "+message);}
}