using System.Numerics; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text.Json; using Vortice.D3DCompiler; using Vortice.Direct3D; using Vortice.Direct3D11; using Vortice.DXGI; using Vortice.Mathematics; using XFEEDToolBox.Core.Galaxy; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Navigation; using XFEEDToolBox.Core.Rendering; using XFEEDToolBox.Rendering; using static Vortice.Direct3D11.D3D11; // Original VS+PS oracle with the real52-byte instance and original half4 quad. // This only renders to owned offscreen WARP textures. No game/window access. const int width=1878,height=1148; var output=Path.GetFullPath("artifacts/galaxy-stellar-raster-validation");Directory.CreateDirectory(output); using var recorded=JsonDocument.Parse(File.ReadAllText("work/visual/galaxy-full/original-data-37/frame-fade-probe.json")); var position=recorded.RootElement.GetProperty("Position"); var world=new Coordinates(position.GetProperty("X").GetDouble(),position.GetProperty("Y").GetDouble(),position.GetProperty("Z").GetDouble()); var address=recorded.RootElement.GetProperty("SystemAddress").GetInt64(); var bounds=GalaxyOriginalCatalogueLod.CellBounds(GalaxyCellQueryPlan.CellAddress((ulong)address),new(49985,40985,24105)); var sign=world.Z-bounds.Minimum.Z>=bounds.Maximum.Z-world.Z?1:-1; var focus=new Coordinates(world.X,world.Y,world.Z-sign*64); var focal=GalaxyOriginalProjection.FocalLength(width,height); var camera=GalaxyCamera.Create(focus,width,height,sign>0?0:Math.PI,0,focal/800,0,0); var projected=camera.Project(world);var depth=projected.Depth; var size=(float)(Half).7f;var halfExtent=size*camera.FocalLength/depth; var sourcePath="artifacts/galaxy-query-research/power-outer-sources/effects/"; byte[] Pinned(string file,string hash) {var bytes=File.ReadAllBytes(sourcePath+file);if(Convert.ToHexStringLower(SHA256.HashData(bytes))!=hash)throw new InvalidDataException(file);return bytes;} var originalVsBytes=Pinned("vs_BackgroundStars_Forward0_0_Win64_SM50.dxbc","4bfe9dac118e66bfdef4016870890f892c79c5c525f6966501a788304fb5b09d"); var originalPsBytes=Pinned("ps_BackgroundStars_Forward0_0_Win64_SM50.dxbc","a9eef9ea89da95e7810933cdbf58b798e105378ab4f9187409b232ab8fe91d9c"); 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 sprites=new GalaxyGraphics(device); using var targetTexture=device.CreateTexture2D(Format.R32G32B32A32_Float,width,height,mipLevels:1,bindFlags:BindFlags.RenderTarget); using var target=device.CreateRenderTargetView(targetTexture); var stagingDescription=targetTexture.Description;stagingDescription.BindFlags=BindFlags.None;stagingDescription.CPUAccessFlags=CpuAccessFlags.Read;stagingDescription.Usage=ResourceUsage.Staging; using var staging=device.CreateTexture2D(stagingDescription); using var rasterizer=device.CreateRasterizerState(new RasterizerDescription(CullMode.None,FillMode.Solid)); using var noDepth=device.CreateDepthStencilState(new DepthStencilDescription(false,DepthWriteMask.Zero,ComparisonFunction.Always)); using var sampler=device.CreateSamplerState(new SamplerDescription(Filter.MinMagMipLinear,TextureAddressMode.Clamp,TextureAddressMode.Clamp,TextureAddressMode.Clamp)); using var originalVs=device.CreateVertexShader(originalVsBytes);using var originalPs=device.CreatePixelShader(originalPsBytes); using var originalLayout=device.CreateInputLayout([ new("TEXCOORD",0,Format.R16G16B16A16_Float,0,0), new("POSITION",0,Format.R32G32B32_Float,0,1,InputClassification.PerInstanceData,1), new("POSITION",2,Format.R32G32B32A32_Float,12,1,InputClassification.PerInstanceData,1), new("TEXCOORD",3,Format.R16G16B16A16_Float,28,1,InputClassification.PerInstanceData,1), new("POSITION",4,Format.R32G32B32A32_Float,36,1,InputClassification.PerInstanceData,1)],originalVsBytes); static ulong Pack(float x,float y,float z,float w)=>BitConverter.HalfToUInt16Bits((Half)x)|((ulong)BitConverter.HalfToUInt16Bits((Half)y)<<16)|((ulong)BitConverter.HalfToUInt16Bits((Half)z)<<32)|((ulong)BitConverter.HalfToUInt16Bits((Half)w)<<48); using var quad=device.CreateBuffer([Pack(0,1,-1,-1),Pack(0,0,-1,1),Pack(1,0,1,1),Pack(1,0,1,1),Pack(1,1,1,-1),Pack(0,1,-1,-1)],BindFlags.VertexBuffer); var originalInstance=new NativeStar(new((float)world.X,(float)world.Y,(float)world.Z),Vector3.One,13,Pack(1,.1f,.7f,10),Vector4.One); if(Marshal.SizeOf()!=52)throw new InvalidDataException("Original stride changed"); using var originalBuffer=device.CreateBuffer([originalInstance],BindFlags.VertexBuffer); using var originalCamera=device.CreateBuffer(128,BindFlags.ConstantBuffer); var shared=new Vector4[279];shared[90]=new(0,1,0,0);shared[277]=new((float)camera.Right.X,(float)camera.Right.Y,(float)camera.Right.Z,0);shared[278]=new((float)camera.Up.X,(float)camera.Up.Y,(float)camera.Up.Z,0); using var sharedBuffer=device.CreateBuffer(shared,BindFlags.ConstantBuffer); using var material=device.CreateBuffer([new(2.2f,2.75f,.17f,1.903f)],BindFlags.ConstantBuffer); var shader=Path.GetFullPath("XFEEDToolBox/Assets/GalaxyMap.hlsl");var toolVsBytes=Compiler.CompileFromFile(shader,"VSStar","vs_5_0"); using var toolVs=device.CreateVertexShader(toolVsBytes.Span);using var toolPs=device.CreatePixelShader(Compiler.CompileFromFile(shader,"PSStar","ps_5_0").Span); using var toolLayout=device.CreateInputLayout([ new("POSITION",0,Format.R32G32_Float,0,0,InputClassification.PerInstanceData,1), new("RADIUS",0,Format.R32G32_Float,8,0,InputClassification.PerInstanceData,1), new("COLOR",0,Format.R32G32B32A32_Float,16,0,InputClassification.PerInstanceData,1), new("APPEARANCE",0,Format.R32G32B32A32_Float,32,0,InputClassification.PerInstanceData,1)],toolVsBytes.Span); using var toolBuffer=device.CreateBuffer(48,BindFlags.VertexBuffer,ResourceUsage.Dynamic,CpuAccessFlags.Write); using var toolCamera=device.CreateBuffer(80,BindFlags.ConstantBuffer); using var outputParameters=device.CreateBuffer([new(1,1,0,0)],BindFlags.ConstantBuffer); context.IASetPrimitiveTopology(PrimitiveTopology.TriangleList);context.RSSetState(rasterizer);context.RSSetViewport(new Viewport(width,height));context.OMSetDepthStencilState(noDepth);context.OMSetBlendState(null);context.PSSetSampler(0,sampler); Vector4[] ReadPatch() { context.OMSetRenderTargets(Array.Empty());context.CopyResource(staging,targetTexture); var mapped=context.Map(staging,0,MapMode.Read);var result=new Vector4[16*16]; try{for(var y=0;y<16;y++)for(var x=0;x<16;x++)result[y*16+x]=Marshal.PtrToStructure(mapped.DataPointer+(int)((height/2-8+y)*mapped.RowPitch)+(width/2-8+x)*16);} finally{context.Unmap(staging,0);}return result; } object Metrics(Vector4[] pixels)=>new{rgbNonzero=pixels.Count(v=>v.X>0||v.Y>0||v.Z>0),alphaNonzero=pixels.Count(v=>v.W>0),peakRgb=pixels.Max(v=>Math.Max(v.X,Math.Max(v.Y,v.Z))),peakAlpha=pixels.Max(v=>v.W)}; Vector4 ProjectionRow(Vector3d basis,double scale,Vector3d forward,double phase) { var xyz=new Vector3((float)(basis.X*scale+forward.X*phase),(float)(basis.Y*scale+forward.Y*phase),(float)(basis.Z*scale+forward.Z*phase)); return new(xyz,-Vector3.Dot(xyz,new((float)camera.Eye.X,(float)camera.Eye.Y,(float)camera.Eye.Z))); } List cases=[]; foreach(var phase in new[]{Vector2.Zero,new(.25f,.25f),new(.5f,.5f),new(0,.5f)}) { var matrix=new Vector4[8];matrix[4]=ProjectionRow(camera.Right,2*focal/width,camera.Forward,2*phase.X/width); matrix[5]=ProjectionRow(camera.Up,2*focal/height,camera.Forward,-2*phase.Y/height); matrix[6]=new(0,0,0,(float)camera.Near);matrix[7]=ProjectionRow(camera.Forward,1,camera.Forward,0); context.UpdateSubresource(matrix,originalCamera); context.OMSetRenderTargets(target);context.ClearRenderTargetView(target,new Color4(0,0,0,0)); context.VSSetShader(originalVs);context.PSSetShader(originalPs);context.IASetInputLayout(originalLayout);context.IASetVertexBuffer(0,quad,8);context.IASetVertexBuffer(1,originalBuffer,52); context.VSSetConstantBuffer(0,originalCamera);context.VSSetConstantBuffer(1,sharedBuffer);context.VSSetConstantBuffer(2,material);context.PSSetConstantBuffer(1,sharedBuffer);context.PSSetConstantBuffer(2,material);sprites.BindOriginal(context);context.DrawInstanced(6,1,0,0); var original=ReadPatch(); foreach(var dpi in new[]{1f,1.5f,2f}) { var logicalWidth=width/dpi;var logicalHeight=height/dpi; var value=new Sprite(new((width*.5f+phase.X)/dpi,(height*.5f+phase.Y)/dpi),(float)halfExtent/dpi,0,Vector4.One,new((float)halfExtent/dpi,13,0,0)); unsafe{var mapped=context.Map(toolBuffer,0,MapMode.WriteDiscard);MemoryMarshal.Write(new Span((void*)mapped.DataPointer,48),in value);context.Unmap(toolBuffer,0);} var constants=new Camera(new(logicalWidth,logicalHeight,0,0),default,default,default,default);context.UpdateSubresource(in constants,toolCamera); context.OMSetRenderTargets(target);context.ClearRenderTargetView(target,new Color4(0,0,0,0)); context.IASetInputLayout(toolLayout);context.IASetVertexBuffer(0,toolBuffer,48);context.VSSetShader(toolVs);context.PSSetShader(toolPs);context.VSSetConstantBuffer(0,toolCamera);context.PSSetConstantBuffer(0,toolCamera);context.PSSetConstantBuffer(8,outputParameters);sprites.Bind(context);context.DrawInstanced(6,1,0,0); var actual=ReadPatch();var difference=original.Zip(actual).Max(p=>Vector4.Distance(p.First,p.Second)); if(phase==Vector2.Zero&&(original.Any(v=>v.X!=0||v.Y!=0||v.Z!=0)||actual.Any(v=>v.X!=0||v.Y!=0||v.Z!=0)))throw new InvalidOperationException("Integer-centred source unexpectedly emitted RGB"); if(phase==new Vector2(.5f,.5f)&&(!original.Any(v=>v.X>0)||!actual.Any(v=>v.X>0)))throw new InvalidOperationException("Pixel-centred positive source was lost"); cases.Add(new{phase=new[]{phase.X,phase.Y},dpi,original=Metrics(original),production=Metrics(actual),maximumRgbaVectorDifference=difference, originalSamples=original.Select(v=>new[]{v.X,v.Y,v.Z,v.W}).ToArray(),productionSamples=actual.Select(v=>new[]{v.X,v.Y,v.Z,v.W}).ToArray()}); } } var report=new{gameProcessAccess=false,gameCalls=0,foregroundChanges=false,warp=true,sampleCount=1,projectionJitter=false,sourceOutputHdrWrite=1,width,height,recordedSystemAddress=address,recordedPosition=world, controlledCamera=true,controlledWhiteColour=true,worldSizeBeforeHalf=.7f,worldSizeAfterHalf=size,depth,focalLength=camera.FocalLength,projectedHalfExtentPixels=halfExtent, positiveRgbRadiusPixels=halfExtent*(2.75+.0+1)*.17,nearestPixelSampleAtIntegerCentre=Math.Sqrt(.5), originalVsSha256=Convert.ToHexStringLower(SHA256.HashData(originalVsBytes)),originalPsSha256=Convert.ToHexStringLower(SHA256.HashData(originalPsBytes)), productionShaderSha256=Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(shader))), frozenCoreAssemblySha256=Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes(typeof(GalaxyCamera).Assembly.Location))), sourceFrameFixtureSha256=Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes("work/visual/galaxy-full/original-data-37/frame-fade-probe.json"))), sourceBuildMetadataSha256=Convert.ToHexStringLower(SHA256.HashData(File.ReadAllBytes("work/visual/galaxy-full/original-data-37/build-metadata.json"))),cases}; File.WriteAllText(Path.Combine(output,"report.json"),JsonSerializer.Serialize(report,new JsonSerializerOptions{WriteIndented=true})); Console.WriteLine(JsonSerializer.Serialize(new{output,report.depth,report.focalLength,report.projectedHalfExtentPixels,report.positiveRgbRadiusPixels,caseCount=cases.Count})); [StructLayout(LayoutKind.Sequential,Pack=1)] readonly record struct NativeStar(Vector3 World,Vector3 Weights,float Layer,ulong Half4,Vector4 Colour); [StructLayout(LayoutKind.Sequential)] readonly record struct Sprite(Vector2 Position,float Radius,float Kind,Vector4 Colour,Vector4 Appearance); [StructLayout(LayoutKind.Sequential)] readonly record struct Camera(Vector4 Viewport,Vector4 Options,Vector4 CentreScale,Vector4 PanOrigin,Vector4 DensityExtent); namespace XFEEDToolBox.Rendering { internal sealed partial class GalaxyGraphics:IDisposable { private readonly ID3D11Device device; internal GalaxyGraphics(ID3D11Device input){device=input;InitializeOriginalSprites();} internal void Bind(ID3D11DeviceContext context)=>context.PSSetShaderResource(7,originalSprites!); internal void BindOriginal(ID3D11DeviceContext context)=>context.PSSetShaderResource(0,originalSprites!); public void Dispose()=>DisposeOriginalSprites(); } }