using Aquarium.Engine.Render; namespace Aquarium.Engine.Tests; public sealed class FieldScriptCompilerTests { [Fact] public void CompileTreatsSplineFieldAsIntentWithAutoLoweringByDefault() { var frame = AquariumFieldScriptCompiler.Compile( """ texture id=spectrum surface id=amplitude op=texture.sample value=0,0,0,0 splinefield id=field texture=spectrum frequencyAxis=x columns=4 """, new Dictionary(StringComparer.Ordinal) { ["spectrum"] = new("spectrum", 8, 4, 1, 0, AquariumRollingModuloMode.Rows, Enumerable.Repeat(0.5f, 32).ToArray()), }); Assert.Equal(AquariumFieldLoweringMode.Auto, frame.LoweringPolicy.Mode); Assert.True(frame.Reservoir.HasInput); Assert.False(frame.UseReservoirLowering); Assert.Single(frame.TextureSplineFields); } [Fact] public void CompileParsesLoweringPolicyWithoutBackendCommands() { var frame = AquariumFieldScriptCompiler.Compile( """ texture id=spectrum splinefield id=field texture=spectrum frequencyAxis=x columns=8 lowering mode=reservoirSplats maxSplines=2 maxControlPoints=16 maxSplats=4096 lodBias=0.5 """, new Dictionary(StringComparer.Ordinal) { ["spectrum"] = new("spectrum", 8, 8, 1, 0, AquariumRollingModuloMode.Rows, Enumerable.Repeat(0.5f, 64).ToArray()), }); Assert.Equal(AquariumFieldLoweringMode.ReservoirSplats, frame.LoweringPolicy.Mode); Assert.Equal(2, frame.LoweringPolicy.MaxDirectSplines); Assert.Equal(16, frame.LoweringPolicy.MaxDirectControlPoints); Assert.Equal(4096, frame.LoweringPolicy.MaxReservoirSplats); Assert.Equal(0.5f, frame.LoweringPolicy.LodBias); Assert.True(frame.UseReservoirLowering); } [Fact] public void CompileEvidenceParsesTubeSplineLoweringForRollingFloatBuffers() { var resource = new AquariumFieldResourceDeclaration( "mimir:resource:log-mel", AquariumFieldResourceKind.StructuredBuffer, AquariumFieldResourceResidency.SharedGpu, AquariumFieldShaderAccess.ShaderResource, "Float32", Width: 64, Height: 32, DepthOrCount: 2048, StrideBytes: 4, ValidFromNs: 0, ValidUntilNs: 10_000, Version: 7, NativeHandle: IntPtr.Zero, NativeHandleKind: "fensalir-buffer"); var frame = AquariumFieldScriptCompiler.CompileEvidence( """ resource id=mel key=mimir:resource:log-mel tubespline id=mel-field resource=mel domain=mimir:log-mel width=64 height=32 stride=4 firstColumn=3 columns=8 columnStride=1 rollingModulo=32 rollingOffset=12 amplitudePower=2 normalizeMin=0 normalizeMax=1 radius=0.01 radiusScale=0.03 ramp=D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png emissionScale=10 subdivisions=4 """, new Dictionary(StringComparer.Ordinal) { [resource.ResourceKey] = resource, }); var lowering = Assert.Single(frame.TubeSplineLowerings); Assert.Equal("dsl:tube:mel-field", lowering.ClaimKey); Assert.Equal(resource.ResourceKey, lowering.ResourceKey); Assert.Equal(64, lowering.Width); Assert.Equal(32, lowering.Height); Assert.Equal(12, lowering.RollingOffset); Assert.Equal(2.0f, lowering.AmplitudePower); Assert.Equal(10.0f, lowering.EmissionScale); Assert.Equal(@"D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png", lowering.RampTexturePath); Assert.Equal("", lowering.RampResourceKey); } [Fact] public void CompileEvidenceBindsLocalTexture2DResourcesAsTubeRamps() { var resource = new AquariumFieldResourceDeclaration( "mimir:resource:log-mel", AquariumFieldResourceKind.StructuredBuffer, AquariumFieldResourceResidency.SharedGpu, AquariumFieldShaderAccess.ShaderResource, "Float32", Width: 64, Height: 32, DepthOrCount: 2048, StrideBytes: 4, ValidFromNs: 0, ValidUntilNs: 10_000, Version: 7, NativeHandle: IntPtr.Zero, NativeHandleKind: "fensalir-buffer"); var frame = AquariumFieldScriptCompiler.CompileEvidence( """ resource id=mel key=mimir:resource:log-mel texture2d id=blackbody key=aquarium:resource:ramp:blackbody path=D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png format=Rgba8Unorm version=11 tubespline id=mel-field resource=mel domain=mimir:log-mel width=64 height=32 stride=4 columns=8 ramp=blackbody """, new Dictionary(StringComparer.Ordinal) { [resource.ResourceKey] = resource, }); Assert.Equal(2, frame.Resources.Count); var ramp = frame.Resources.Single(resource => resource.Kind == AquariumFieldResourceKind.Texture2D); Assert.Equal("aquarium:resource:ramp:blackbody", ramp.ResourceKey); Assert.Equal("local-asset", ramp.NativeHandleKind); Assert.Equal(@"D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png", ramp.SourceUri); var lowering = Assert.Single(frame.TubeSplineLowerings); Assert.Equal(ramp.ResourceKey, lowering.RampResourceKey); Assert.Equal(ramp.SourceUri, lowering.RampTexturePath); } [Fact] public void CompileEvidenceDeclaresSurfacePagesAsGpuResources() { var frame = AquariumFieldScriptCompiler.CompileEvidence( """ surfacepage id=height key=aquarium:resource:surface-page:heightfield width=128 height=128 format=R16Float version=3 """, new Dictionary(StringComparer.Ordinal)); var resource = Assert.Single(frame.Resources); Assert.Equal("aquarium:resource:surface-page:heightfield", resource.ResourceKey); Assert.Equal(AquariumFieldResourceKind.SurfacePage, resource.Kind); Assert.Equal(AquariumFieldResourceResidency.GpuResident, resource.Residency); Assert.Equal(AquariumFieldShaderAccess.ShaderResource, resource.Access); Assert.Equal(128, resource.Width); Assert.Equal(128, resource.Height); Assert.Equal("R16Float", resource.Format); Assert.Equal("fensalir-surface-page", resource.NativeHandleKind); } [Fact] public void CompileEvidenceDeclaresVolumeTexturesAsGpuResources() { var frame = AquariumFieldScriptCompiler.CompileEvidence( """ volumetexture id=density key=aquarium:resource:volume:density width=32 height=32 depth=16 format=R16Float version=5 """, new Dictionary(StringComparer.Ordinal)); var resource = Assert.Single(frame.Resources); Assert.Equal("aquarium:resource:volume:density", resource.ResourceKey); Assert.Equal(AquariumFieldResourceKind.VolumeTexture, resource.Kind); Assert.Equal(AquariumFieldResourceResidency.GpuResident, resource.Residency); Assert.Equal(AquariumFieldShaderAccess.ShaderResource, resource.Access); Assert.Equal(32, resource.Width); Assert.Equal(32, resource.Height); Assert.Equal(16, resource.DepthOrCount); Assert.Equal("R16Float", resource.Format); Assert.Equal("fensalir-volume-texture", resource.NativeHandleKind); } [Fact] public void CompileEvidenceDeclaresMeshPackagesAsGpuResources() { var frame = AquariumFieldScriptCompiler.CompileEvidence( """ mesh id=quad key=aquarium:resource:mesh:quad vertices=4 indices=6 indexFormat=UInt32 topology=TriangleList min=-1,-1,0 max=1,1,0 submeshes=1 version=9 """, new Dictionary(StringComparer.Ordinal)); var resource = Assert.Single(frame.Resources); Assert.Equal("aquarium:resource:mesh:quad", resource.ResourceKey); Assert.Equal(AquariumFieldResourceKind.Mesh, resource.Kind); Assert.Equal(AquariumFieldResourceResidency.GpuResident, resource.Residency); Assert.Equal(AquariumFieldShaderAccess.ShaderResource, resource.Access); Assert.Equal("fensalir-mesh-package", resource.NativeHandleKind); Assert.True(resource.Mesh.IsValid); Assert.True(resource.Mesh.IsStandardImportedLayout); Assert.Equal(4, resource.Mesh.Vertices.Count); Assert.Equal(AquariumFieldMeshResource.PositionNormalUvColorStrideBytes, resource.Mesh.Vertices.StrideBytes); Assert.Equal(6, resource.Mesh.Indices.Count); Assert.Equal(4, resource.Mesh.Indices.StrideBytes); Assert.Equal(AquariumFieldMeshTopology.TriangleList, resource.Mesh.Topology); Assert.Equal(AquariumFieldMeshIndexFormat.UInt32, resource.Mesh.IndexFormat); Assert.Equal(AquariumFieldMeshLayout.PositionNormalUvColor, resource.Mesh.Layout); } [Fact] public void CompileEvidenceCanDeclarePipelinePrivateMeshes() { var frame = AquariumFieldScriptCompiler.CompileEvidence( """ mesh id=generated key=aquarium:resource:mesh:generated layout=PipelinePrivate vertices=8 vertexStride=20 indices=12 indexFormat=UInt16 topology=TriangleList min=-1,-1,0 max=1,1,0 submeshes=1 """, new Dictionary(StringComparer.Ordinal)); var resource = Assert.Single(frame.Resources); Assert.True(resource.Mesh.IsValid); Assert.True(resource.Mesh.IsPipelinePrivate); Assert.False(resource.Mesh.IsStandardImportedLayout); Assert.Equal(20, resource.Mesh.Vertices.StrideBytes); Assert.Equal(2, resource.Mesh.Indices.StrideBytes); } [Fact] public void CompileEvidencePlansGenericResourceClaims() { var frame = AquariumFieldScriptCompiler.CompileEvidence( """ mesh id=quad key=aquarium:resource:mesh:quad vertices=4 indices=6 indexFormat=UInt32 topology=TriangleList min=-1,-1,0 max=1,1,0 submeshes=1 version=9 surfacepage id=height key=aquarium:resource:surface-page:height width=64 height=64 format=R16Float volumetexture id=fog key=aquarium:resource:volume-texture:fog width=16 height=16 depth=16 format=R16Float claim id=quad resource=quad encoding=Mesh layer=Form radius=1 claim id=height resource=height encoding=Height layer=Form radius=1 claim id=fog resource=fog encoding=Density layer=Appearance radius=1 """, new Dictionary(StringComparer.Ordinal)); var plan = AquariumFieldLoweringPlanner.Plan(frame); Assert.Empty(plan.DeferredRequests); Assert.Collection( plan.Packets, packet => { Assert.Equal(AquariumFieldEncoding.Mesh, packet.Encoding); Assert.Equal(AquariumFieldBackendKind.Mesh, packet.Backend); Assert.Equal("aquarium:resource:mesh:quad", packet.PayloadHandle); }, packet => { Assert.Equal(AquariumFieldEncoding.Height, packet.Encoding); Assert.Equal(AquariumFieldBackendKind.SurfacePage, packet.Backend); Assert.Equal("aquarium:resource:surface-page:height", packet.PayloadHandle); }, packet => { Assert.Equal(AquariumFieldEncoding.Density, packet.Encoding); Assert.Equal(AquariumFieldBackendKind.VolumeSplat, packet.Backend); Assert.Equal("aquarium:resource:volume-texture:fog", packet.PayloadHandle); }); } }