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.OMSetRenderTargets(target);context.RSSetViewport(new Vortice.Mathematics.Viewport(width,height));context.RSSetState(rasterizer);context.OMSetDepthStencilState(noDepth);
var output=Path.GetFullPath("artifacts/galaxy-plane-shader-validation");Directory.CreateDirectory(output);var reports=new List<object>();
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,1.1,.05)})
foreach(var hdrWrite in new[]{1f,GalaxyOriginalHdr.WriteScale})
{
    var camera=GalaxyCamera.Create(focus,width,height,yaw,pitch,scale);
    context.ClearRenderTargetView(target,new Color4(0,0,0,0));renderer.Draw(camera,hdrWrite);var actual=Read();
    context.ClearRenderTargetView(target,new Color4(0,0,0,0));renderer.DrawOriginal(camera,hdrWrite);var original=Read();
    double sum=0,brightness=0;var maximum=0f;var nonfinite=0;var changed=0;
    for(var i=0;i<actual.Length;i++)
    {
        if(!float.IsFinite(actual[i])||!float.IsFinite(original[i])){nonfinite++;continue;}
        var diff=Math.Abs(actual[i]-original[i]);maximum=Math.Max(maximum,diff);sum+=diff;
        if(diff>.005f)changed++;
        if(i%4<3)brightness+=actual[i];
    }
    if(nonfinite!=0||sum/actual.Length>.001||changed>actual.Length*.001)
        throw new InvalidOperationException($"Actual Plane VS/PS mismatch{name}/{hdrWrite}:max{maximum},mean{sum/actual.Length},changed{changed},nonfinite{nonfinite}");
    if(hdrWrite==1)
    {
        var bgra=new byte[width*height*4];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+".bgra"),bgra);
    }
    reports.Add(new{name,width,height,hdrWrite,actualOriginalVsAndPsCompared=true,maximumDifference=maximum,
        meanDifference=sum/actual.Length,significantComponents=changed,nonfinite,meanRgb=brightness/(width*height*3),renderer.OriginalPlaneReady,
        renderer.OriginalPlaneFullRestored,packedQuaternionU16=new[]{32767,65534,32767,32767}});
}
File.WriteAllText(Path.Combine(output,"report.json"),JsonSerializer.Serialize(reports,new JsonSerializerOptions{WriteIndented=true}));Console.WriteLine(JsonSerializer.Serialize(reports));
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 copy=device.CreateTexture2D(desc);context.CopyResource(copy,texture);var mapped=context.Map(copy,0,MapMode.Read);var data=new float[width*height*4];
    for(var y=0;y<height;y++)Marshal.Copy(mapped.DataPointer+(int)(y*mapped.RowPitch),data,y*width*4,width*4);context.Unmap(copy,0);context.OMSetRenderTargets(target);return data;
}

namespace XFEEDToolBox.Rendering
{
    internal sealed partial class GalaxyGraphics:IDisposable
    {
        private readonly ID3D11Device device;private readonly ID3D11DeviceContext context;private readonly ID3D11BlendState additive;
        private readonly ID3D11VertexShader sourceVs;private readonly ID3D11PixelShader sourcePs;private readonly ID3D11InputLayout sourceLayout;
        private readonly ID3D11Buffer sourceMesh,sourceIndices,sourceInstances,sourceB0,sourceB1,sourceB2;
        private readonly ID3D11ShaderResourceView sourceInstanceView;
        internal int DrawCalls;
        internal GalaxyGraphics(ID3D11Device d,ID3D11DeviceContext c)
        {
            device=d;context=c;additive=d.CreateBlendState(new BlendDescription(Blend.One,Blend.One));
            InitializeOriginalPlane(Path.GetFullPath("XFEEDToolBox/Assets/GalaxyPlane.hlsl"));
            var folder="artifacts/galaxy-query-research/power-outer-sources/authored-models/effects/";
            var vs=File.ReadAllBytes(folder+"vs_Alpha_FresnelDiffuseLinearToGammaSpace_AntialiasClipOnColourAlpha_Forward0_0_0_Win64_SM50.dxbc");
            var ps=File.ReadAllBytes(folder+"ps_Alpha_UnlitNoScale_StarMapFacingAlpha_NearFade_Forward0_0_0_Win64_SM50.dxbc");
            if(Convert.ToHexStringLower(SHA256.HashData(vs))!="132d7e6251b8b0e3a1af7de459397d4d466f6f0a9cb4b71a3682107126008e7d"||
               Convert.ToHexStringLower(SHA256.HashData(ps))!="48e2ac3a530834ab460195f53236fec2a52655afb1e27b924069356a08ce2822")
                throw new InvalidDataException("Actual linked Plane shader changed");
            sourceVs=d.CreateVertexShader(vs);sourcePs=d.CreatePixelShader(ps);
            sourceLayout=d.CreateInputLayout([new InputElementDescription("INSTANCEANDMODELDATAINDEX",0,Format.R32G32_UInt,0,1,InputClassification.PerInstanceData,1),
                new InputElementDescription("PACKEDVERTEXDATAA",0,Format.R32G32B32A32_UInt,0,0),
                new InputElementDescription("PACKEDVERTEXDATAB",0,Format.R32G32B32A32_UInt,16,0),
                new InputElementDescription("PACKEDVERTEXDATAC",0,Format.R32G32_UInt,32,0)],vs);
            sourceMesh=d.CreateBuffer<byte>(GalaxyOriginalPlane.Reference.PackedMesh.Span[36..],BindFlags.VertexBuffer);
            sourceIndices=d.CreateBuffer<uint>([0,0],BindFlags.VertexBuffer);
            var instance=new byte[336];BitConverter.GetBytes(100000f).CopyTo(instance,4);
            BitConverter.GetBytes(0xfffe7fffU).CopyTo(instance,8);BitConverter.GetBytes(0x7fff7fffU).CopyTo(instance,12);
            BitConverter.GetBytes(50000f).CopyTo(instance,16);BitConverter.GetBytes(40955f).CopyTo(instance,20);BitConverter.GetBytes(50000f).CopyTo(instance,24);
            sourceInstances=d.CreateBuffer<byte>(instance,BindFlags.ShaderResource,miscFlags:ResourceOptionFlags.BufferStructured,structureByteStride:336);
            sourceInstanceView=d.CreateShaderResourceView(sourceInstances);
            sourceB0=d.CreateBuffer(12*16,BindFlags.ConstantBuffer);sourceB1=d.CreateBuffer(280*16,BindFlags.ConstantBuffer);sourceB2=d.CreateBuffer(2*16,BindFlags.ConstantBuffer);
        }
        internal void Draw(GalaxyCamera camera,float hdrWrite)=>DrawOriginalPlane(camera,true,hdrWrite);
        internal void DrawOriginal(GalaxyCamera camera,float hdrWrite)
        {
            var eye=new Vector3((float)camera.Eye.X+49985,(float)camera.Eye.Y+40985,(float)camera.Eye.Z+24105);
            var right=new Vector3((float)camera.Right.X,(float)camera.Right.Y,(float)camera.Right.Z);
            var up=new Vector3((float)camera.Up.X,(float)camera.Up.Y,(float)camera.Up.Z);
            var forward=new Vector3((float)camera.Forward.X,(float)camera.Forward.Y,(float)camera.Forward.Z);
            var b0=new Vector4[12];b0[4]=new(right*(float)(camera.FocalLength*2/camera.Width),0);b0[5]=new(up*(float)(camera.FocalLength*2/camera.Height),0);
            b0[6]=new(0,0,0,(float)camera.Near);b0[7]=new(forward,0);b0[9]=new(1,0,0,0);b0[10]=new(0,1,0,0);b0[11]=new(0,0,1,0);
            var b1=new Vector4[280];b1[90]=new(0,hdrWrite,GalaxyOriginalHdr.ReadScale,0);b1[275]=new(eye,0);b1[279]=new(forward,0);
            context.UpdateSubresource<Vector4>(b0,sourceB0);context.UpdateSubresource<Vector4>(b1,sourceB1);
            context.UpdateSubresource<Vector4>([GalaxyOriginalPlane.Reference.Material0,GalaxyOriginalPlane.Reference.Material1],sourceB2);
            context.VSSetConstantBuffer(0,sourceB0);context.VSSetConstantBuffer(1,sourceB1);context.PSSetConstantBuffer(1,sourceB1);context.PSSetConstantBuffer(2,sourceB2);
            context.VSSetShaderResource(33,sourceInstanceView);context.IASetInputLayout(sourceLayout);context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
            context.IASetVertexBuffer(0,sourceMesh,40);context.IASetVertexBuffer(1,sourceIndices,8);context.IASetIndexBuffer(originalPlaneIndices,Format.R16_UInt,0);
            context.VSSetShader(sourceVs);context.PSSetShader(sourcePs);context.PSSetShaderResource(0,originalPlaneView);context.PSSetSampler(0,originalPlaneSampler);
            context.OMSetBlendState(originalPlaneBlend);context.DrawIndexedInstanced(6,1,0,0,0);context.PSSetShaderResource(0,null!);context.VSSetShaderResource(33,null!);
        }
        public void Dispose(){DisposeOriginalPlane();sourceVs.Dispose();sourcePs.Dispose();sourceLayout.Dispose();sourceMesh.Dispose();sourceIndices.Dispose();sourceInstances.Dispose();sourceInstanceView.Dispose();sourceB0.Dispose();sourceB1.Dispose();sourceB2.Dispose();additive.Dispose();}
    }
}