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<ulong>([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<NativeStar>()!=52)throw new InvalidDataException("Original stride changed");
using var originalBuffer=device.CreateBuffer<NativeStar>([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<Vector4>(shared,BindFlags.ConstantBuffer);
using var material=device.CreateBuffer<Vector4>([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<Vector4>([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<ID3D11RenderTargetView>());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<Vector4>(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<object> 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<byte>((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();
}
}
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<ulong>([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<NativeStar>()!=52)throw new InvalidDataException("Original stride changed");
using var originalBuffer=device.CreateBuffer<NativeStar>([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<Vector4>(shared,BindFlags.ConstantBuffer);
using var material=device.CreateBuffer<Vector4>([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<Vector4>([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<ID3D11RenderTargetView>());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<Vector4>(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<object> 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<byte>((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();
}
}