using AcDream.App.Rendering.Gpu; using AcDream.App.Rendering.Gpu.Gl; namespace AcDream.App.Tests.Rendering.Gpu.Gl; public sealed class GlRenderStateCacheTests { private static GlRenderStateSnapshot Default(uint program = 1) => new( program, GpuBlendMode.None, DepthTest: true, DepthWrite: true, GpuCompareOp.LessOrEqual, GpuCullMode.Back, GpuFrontFace.CounterClockwise, AlphaToCoverage: false, ColorWrite: true, // Slice V6l: the stencil dimension. Off is what every pipeline in the // tree but the portal depth mask asks for. StencilTest: false, GpuStencilState.Default); [Fact] public void FirstApplyReportsEveryDimensionChanged() { var cache = new GlRenderStateCache(); GlRenderStateChanges changes = cache.Apply(Default()); Assert.Equal(GlRenderStateChanges.All, changes); Assert.True(changes.AnyChange); } [Fact] public void ReapplyingTheIdenticalSnapshotReportsNoChanges() { var cache = new GlRenderStateCache(); GlRenderStateSnapshot snapshot = Default(); cache.Apply(snapshot); GlRenderStateChanges changes = cache.Apply(snapshot); Assert.False(changes.AnyChange); } [Fact] public void ChangingOnlyCullModeReportsOnlyThatDimension() { var cache = new GlRenderStateCache(); cache.Apply(Default()); GlRenderStateChanges changes = cache.Apply(Default() with { Cull = GpuCullMode.None }); Assert.True(changes.Cull); Assert.True(changes.AnyChange); Assert.False(changes.Program); Assert.False(changes.Blend); Assert.False(changes.DepthTest); Assert.False(changes.DepthWrite); Assert.False(changes.DepthCompare); Assert.False(changes.FrontFace); Assert.False(changes.AlphaToCoverage); Assert.False(changes.ColorWrite); Assert.False(changes.StencilTest); Assert.False(changes.Stencil); } [Fact] public void ChangingOnlyTheStencilValuesReportsOnlyThatDimension() { // Slice V6l. #117's portal punch changes compare, ops, reference and // masks between its mark pass and its punch pass while the test stays // enabled, so the two stencil dimensions have to move independently. var cache = new GlRenderStateCache(); cache.Apply(Default() with { StencilTest = true }); GlRenderStateChanges changes = cache.Apply(Default() with { StencilTest = true, Stencil = GpuStencilState.Default with { Compare = GpuCompareOp.Equal, Pass = GpuStencilOp.Zero, Reference = 1, }, }); Assert.True(changes.Stencil); Assert.False(changes.StencilTest); Assert.False(changes.DepthTest); Assert.False(changes.ColorWrite); } [Fact] public void ChangingTheProgramReportsProgramChangedEvenWhenEveryOtherFieldMatches() { var cache = new GlRenderStateCache(); cache.Apply(Default(program: 1)); GlRenderStateChanges changes = cache.Apply(Default(program: 2)); Assert.True(changes.Program); Assert.False(changes.Blend); } [Fact] public void ResetForcesTheNextApplyToReportEveryDimensionAgain() { var cache = new GlRenderStateCache(); GlRenderStateSnapshot snapshot = Default(); cache.Apply(snapshot); cache.Reset(); GlRenderStateChanges changes = cache.Apply(snapshot); Assert.Equal(GlRenderStateChanges.All, changes); } [Fact] public void MultipleDimensionsChangingAreAllReported() { var cache = new GlRenderStateCache(); cache.Apply(Default()); GlRenderStateChanges changes = cache.Apply(Default() with { Blend = GpuBlendMode.StraightAlpha, DepthWrite = false, FrontFace = GpuFrontFace.Clockwise, }); Assert.True(changes.Blend); Assert.True(changes.DepthWrite); Assert.True(changes.FrontFace); Assert.False(changes.Cull); Assert.False(changes.DepthTest); Assert.False(changes.DepthCompare); Assert.False(changes.AlphaToCoverage); Assert.False(changes.ColorWrite); Assert.False(changes.Program); } }