Ejemplo n.º 1
0
        static void Subtest <TBodyBuilder, TConstraintBuilder, TConstraint>(TBodyBuilder bodyBuilder, TConstraintBuilder constraintBuilder,
                                                                            int width, int height, int length, int frameCount, IThreadDispatcher initializationThreadPool, StreamWriter writer)
            where TBodyBuilder : IBodyBuilder where TConstraintBuilder : IConstraintBuilder where TConstraint : IConstraintDescription <TConstraint>
        {
            const int testsPerVariant = 8;

            WriteLine(writer, $"{width}x{height}x{length} lattice, {frameCount} frames:");
            var timings = new SimulationTimeSamples[Environment.ProcessorCount];


            //for (int threadCount = 1; threadCount <= 1; ++threadCount)
            for (int threadCount = 1; threadCount <= Environment.ProcessorCount; ++threadCount)
            {
                var threadPool = new SimpleThreadDispatcher(threadCount);
                SimulationTimeSamples bestTimings = null;
                double bestTime = double.MaxValue;
                for (int i = 0; i < testsPerVariant; ++i)
                {
                    var candidateTimings = Solve <TBodyBuilder, TConstraintBuilder, TConstraint>(bodyBuilder, constraintBuilder, width, height, length,
                                                                                                 frameCount, threadCount, initializationThreadPool, threadPool);
                    var totalStats = candidateTimings.Simulation.ComputeStats();
                    WriteLine(writer,
                              $"{i} AVE: {Math.Round(1e3 * totalStats.Average, 2)}, " +
                              $"MIN: {Math.Round(1e3 * totalStats.Min, 2)}, " +
                              $"MAX: {Math.Round(1e3 * totalStats.Max, 2)}, " +
                              $"STD DEV: {Math.Round(1e3 * totalStats.StdDev, 3)}, ");
                    if (totalStats.Total < bestTime)
                    {
                        bestTime    = totalStats.Total;
                        bestTimings = candidateTimings;
                    }
                }

                WriteLine(writer, $"{threadCount}T: " +
                          $"{Math.Round(bestTime * 1e3, 2)}, " +
                          $"BOPT: {Math.Round(bestTimings.BodyOptimizer.ComputeStats().Total * 1e3, 2)}, " +
                          $"COPT: {Math.Round(bestTimings.ConstraintOptimizer.ComputeStats().Total * 1e3, 2)}, " +
                          $"BCMP: {Math.Round(bestTimings.BatchCompressor.ComputeStats().Total * 1e3, 2)}, " +
                          $"POIN: {Math.Round(bestTimings.PoseIntegrator.ComputeStats().Total * 1e3, 2)}, " +
                          $"SOLV: {Math.Round(bestTimings.Solver.ComputeStats().Total * 1e3, 2)}");
                timings[threadCount - 1] = bestTimings;
                threadPool.Dispose();
            }
            int fastestIndex = 0;

            for (int i = 1; i < timings.Length; ++i)
            {
                if (timings[i].Simulation.ComputeStats().Total < timings[fastestIndex].Simulation.ComputeStats().Total)
                {
                    fastestIndex = i;
                }
            }
            WriteLine(writer, $"Scaling: {timings[0].Simulation.ComputeStats().Total / timings[fastestIndex].Simulation.ComputeStats().Total}");
        }
Ejemplo n.º 2
0
        public TimingDisplayMode GraphDisplayMode; //Current display mode used by the performance graph

        //Default Constructor which automatically sets up the graph in Regular timing mode
        public PerformanceGraph(Font UIFont, SimulationTimeSamples TimeSamples)
        {
            DisplayGraph = new Graph(new GraphDescription
            {
                BodyLineColor                 = new Vector3(1, 1, 1),
                AxisLabelHeight               = 16,
                AxisLineRadius                = 0.5f,
                HorizontalAxisLabel           = "Frames",
                VerticalAxisLabel             = "Time (ms)",
                VerticalIntervalValueScale    = 1e3f,
                VerticalIntervalLabelRounding = 2,
                BackgroundLineRadius          = 0.125f,
                IntervalTextHeight            = 12,
                IntervalTickRadius            = 0.25f,
                IntervalTickLength            = 6f,
                TargetHorizontalTickCount     = 5,
                HorizontalTickTextPadding     = 0,
                VerticalTickTextPadding       = 3,

                LegendMinimum    = new Vector2(20, 200),
                LegendNameHeight = 12,
                LegendLineLength = 7,

                TextColor = new Vector3(1, 1, 1),
                Font      = UIFont,

                LineSpacingMultiplier = 1f,

                ForceVerticalAxisMinimumToZero = true
            });

            DisplayGraph.AddSeries("Total", new Vector3(1, 1, 1), 0.75f, TimeSamples.Simulation);
            DisplayGraph.AddSeries("Pose Integrator", new Vector3(0, 0, 1), 0.25f, TimeSamples.PoseIntegrator);
            DisplayGraph.AddSeries("Sleeper", new Vector3(0.5f, 0, 1), 0.25f, TimeSamples.Sleeper);
            DisplayGraph.AddSeries("Broad Update", new Vector3(1, 1, 0), 0.25f, TimeSamples.BroadPhaseUpdate);
            DisplayGraph.AddSeries("Collision Test", new Vector3(0, 1, 0), 0.25f, TimeSamples.CollisionTesting);
            DisplayGraph.AddSeries("Narrow Flush", new Vector3(1, 0, 1), 0.25f, TimeSamples.NarrowPhaseFlush);
            DisplayGraph.AddSeries("Solver", new Vector3(1, 0, 0), 0.5f, TimeSamples.Solver);
            DisplayGraph.AddSeries("Body Opt", new Vector3(1, 0.5f, 0), 0.125f, TimeSamples.BodyOptimizer);
            DisplayGraph.AddSeries("Constraint Opt", new Vector3(0, 0.5f, 1), 0.125f, TimeSamples.ConstraintOptimizer);
            DisplayGraph.AddSeries("Batch Compress", new Vector3(0, 0.5f, 0), 0.125f, TimeSamples.BatchCompressor);
        }
Ejemplo n.º 3
0
        public static void Test()
        {
            const int width  = 32;
            const int height = 32;
            const int length = 32;

            SimulationSetup.BuildLattice(
                new RegularGridWithKinematicBaseBuilder(new Vector3(1), new Vector3()),
                new BallSocketConstraintBuilder(),
                width, height, length, out var simulation, out var bodyHandles, out var constraintHandles);

            var threadDispatcher = new SimpleThreadDispatcher(8);

            const float inverseDt      = 60f;
            const float dt             = 1 / inverseDt;
            const int   iterationCount = 8;
            const int   frameCount     = 128;

            simulation.Solver.IterationCount = iterationCount;

            simulation.PoseIntegrator.Gravity = new Vector3(0, -10, 0);

            var samples = new SimulationTimeSamples(frameCount);

            for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex)
            {
                var energyBefore = TestHelpers.GetBodyEnergyHeuristic(simulation.Bodies);

                //simulation.Timestep(dt);
                simulation.Timestep(dt, threadDispatcher);

                samples.RecordFrame(simulation);

                var energyAfter      = TestHelpers.GetBodyEnergyHeuristic(simulation.Bodies);
                int sampledBodyIndex = width;
                var samplePose       = simulation.Bodies.ActiveSet.Poses[sampledBodyIndex];
                var sampleVelocity   = simulation.Bodies.ActiveSet.Velocities[sampledBodyIndex];
                //for (int i =0; i < simulation.Bodies.BodyCount; ++i)
                //{
                //    simulation.Bodies.GetPose(simulation.Bodies.IndexToHandle[i], out var pose);
                //    simulation.Bodies.GetVelocity(simulation.Bodies.IndexToHandle[i], out var velocity);
                //    Console.WriteLine($"Sample {i} position: {pose.Position}, velocity: {velocity.Linear}");
                //}
                Console.WriteLine($"Sample {sampledBodyIndex} position: {samplePose.Position}, velocity: {sampleVelocity.Linear}");

                Console.WriteLine($"Body energy {frameIndex}: {energyAfter}, delta: {energyAfter - energyBefore}");
            }

            var multiplier = 1e3 / frameCount;

            Console.WriteLine($"Simulation time (ms):       {multiplier * samples.Simulation.ComputeStats().Total}");
            Console.WriteLine($"Body opt time (ms):         {multiplier * samples.BodyOptimizer.ComputeStats().Total}");
            Console.WriteLine($"Constraint opt time (ms):   {multiplier * samples.ConstraintOptimizer.ComputeStats().Total}");
            Console.WriteLine($"Batch compress time (ms):   {multiplier * samples.BatchCompressor.ComputeStats().Total}");
            Console.WriteLine($"Pose integrate time (ms):   {multiplier * samples.PoseIntegrator.ComputeStats().Total}");
            Console.WriteLine($"Solve time (ms):            {multiplier * samples.Solver.ComputeStats().Total}");


            threadDispatcher.Dispose();
            simulation.BufferPool.Clear();
        }
Ejemplo n.º 4
0
        //Constructor which sets up the whole game world scene
        public GameWorld(GameLoop Loop, ContentArchive Content)
        {
            //Store references from the GameLoop class
            ApplicationWindow = Loop.Window;
            UserInput         = Loop.Input;

            //Assign the camera reference
            ObservationCamera.SetCamera(Loop);

            this.Content = Content;
            TimeSamples  = new SimulationTimeSamples(512, Loop.Pool);
            UserControls = Controls.Default;

            //Load font from the content archive
            var FontContent = Content.Load <FontContent>(@"Carlito-Regular.ttf");

            UIFont = new Font(Loop.Surface.Device, Loop.Surface.Context, FontContent);

            //Position the camera
            ObservationCamera.PositionCamera(new Vector3(2.7f, 6.48f, 9.76f));
            ObservationCamera.FaceCamera(0.269f, 0.15899f);

            //Setup character controller and world simulation
            BufferPool       = new BufferPool();
            ThreadDispatcher = new SimpleThreadDispatcher(Environment.ProcessorCount);
            World            = Simulation.Create(BufferPool, new CharacterNarrowphaseCallbacks(new CharacterControllers(BufferPool)), new ScenePoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            //Initialize the mesh loader
            MeshManager.Initialize(Content, BufferPool);

            //Load in the numbers display the direction of the X/Z axes
            AxisMarkers.LoadModels();
            AxisMarkers.AddModels(World);

            //Load in the PVP arena
            ArenaMeshHandle = MeshManager.LoadMesh(@"Arena.obj", new Vector3(1));
            //Define its starting position and location
            Vector3    ArenaPosition = new Vector3(29.82f, 3.62f, 0.94f);
            Quaternion ArenaRotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), Trig.DegreesToRadians(180));

            //Use those to add it into the world
            MeshManager.AddStatic(World, ArenaMeshHandle, ArenaPosition, ArenaRotation);

            //Place the jumping cubes
            World.Statics.Add(new StaticDescription(new Vector3(1.299f, 2.3f, -31.24f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-26.56f, 2.3f, -35.2f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-33.12f, 2.3f, -21.65f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-26.05f, 2.3f, -9.38f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-10.31f, 2.3f, -5.62f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(1.94f, 2.3f, -15.88f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-11.3f, 2.3f, -37.44f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));

            //Place a ground plane to walk on
            World.Statics.Add(new StaticDescription(new Vector3(0, -0.5f, 0), new CollidableDescription(World.Shapes.Add(new Box(100, 1, 100)), 0.1f)));

            //Setup the command executor
            CommandInputField.Initialize();

            //Make sure the window size is correct relative to the current resolution
            OnResize(ApplicationWindow.Resolution);
        }
Ejemplo n.º 5
0
        public static SimulationTimeSamples Solve <TBodyBuilder, TConstraintBuilder, TConstraint>(TBodyBuilder bodyBuilder, TConstraintBuilder constraintBuilder,
                                                                                                  int width, int height, int length, int frameCount, int threadCount, IThreadDispatcher initializationThreadPool, IThreadDispatcher threadDispatcher)
            where TBodyBuilder : IBodyBuilder where TConstraintBuilder : IConstraintBuilder where TConstraint : IConstraintDescription <TConstraint>
        {
            //const int bodyCount = 8;
            //SimulationSetup.BuildStackOfBodiesOnGround(bodyCount, false, true, out var bodies, out var solver, out var graph, out var bodyHandles, out var constraintHandles);
            GC.Collect(3, GCCollectionMode.Forced, true);
            SimulationSetup.BuildLattice(
                bodyBuilder, constraintBuilder,
                width, height, length, out var simulation, out var bodyHandles, out var constraintHandles);

            SimulationScrambling.ScrambleBodies(simulation);
            SimulationScrambling.ScrambleConstraints(simulation.Solver);
            SimulationScrambling.ScrambleBodyConstraintLists(simulation);
            SimulationScrambling.AddRemoveChurn <TConstraint>(simulation, bodyHandles.Length * 2, bodyHandles, constraintHandles);

            const int batchCompressionIterations = 1000;

            simulation.SolverBatchCompressor.TargetCandidateFraction    = .005f;
            simulation.SolverBatchCompressor.MaximumCompressionFraction = 0.0005f;
            for (int i = 0; i < batchCompressionIterations; ++i)
            {
                simulation.SolverBatchCompressor.Compress(simulation.BufferPool, initializationThreadPool);
            }

            //Attempt cache optimization.
            int bodyOptimizationIterations = bodyHandles.Length / 4;

            simulation.BodyLayoutOptimizer.OptimizationFraction = 0.005f;
            for (int i = 0; i < bodyOptimizationIterations; ++i)
            {
                simulation.BodyLayoutOptimizer.IncrementalOptimize(simulation.BufferPool, initializationThreadPool);
            }

            simulation.ConstraintLayoutOptimizer.OptimizationFraction = 0.044f;
            int constraintOptimizationIterations = 1024;

            for (int i = 0; i < constraintOptimizationIterations; ++i)
            {
                simulation.ConstraintLayoutOptimizer.Update(simulation.BufferPool, initializationThreadPool);
            }

            var simulationTimeSamples = new SimulationTimeSamples(frameCount);

            const float dt             = 1 / 60f;
            const int   iterationCount = 8;

            simulation.Solver.IterationCount = iterationCount;

            for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex)
            {
                CacheBlaster.Blast();
                simulation.Timestep(dt, threadDispatcher);
                simulationTimeSamples.RecordFrame(simulation);
            }

            simulation.Dispose();
            simulation.BufferPool.Clear();


            return(simulationTimeSamples);
        }
Ejemplo n.º 6
0
        public DemoHarness(GameLoop loop, ContentArchive content,
                           Controls?controls = null, DemoSet customDemoSet = null)
        {
            this.window  = loop.Window;
            this.input   = loop.Input;
            this.camera  = loop.Camera;
            this.content = content;
            timeSamples  = new SimulationTimeSamples(512, loop.Pool);
            if (controls == null)
            {
                this.controls = Controls.Default;
            }

            var fontContent = content.Load <FontContent>(@"Content\Carlito-Regular.ttf");

            font = new Font(loop.Surface.Device, loop.Surface.Context, fontContent);

            timingGraph = new Graph(new GraphDescription
            {
                BodyLineColor                 = new Vector3(1, 1, 1),
                AxisLabelHeight               = 16,
                AxisLineRadius                = 0.5f,
                HorizontalAxisLabel           = "Frames",
                VerticalAxisLabel             = "Time (ms)",
                VerticalIntervalValueScale    = 1e3f,
                VerticalIntervalLabelRounding = 2,
                BackgroundLineRadius          = 0.125f,
                IntervalTextHeight            = 12,
                IntervalTickRadius            = 0.25f,
                IntervalTickLength            = 6f,
                TargetHorizontalTickCount     = 5,
                HorizontalTickTextPadding     = 0,
                VerticalTickTextPadding       = 3,

                LegendMinimum    = new Vector2(20, 200),
                LegendNameHeight = 12,
                LegendLineLength = 7,

                TextColor = new Vector3(1, 1, 1),
                Font      = font,

                LineSpacingMultiplier = 1f,

                ForceVerticalAxisMinimumToZero = true
            });
            timingGraph.AddSeries("Total", new Vector3(1, 1, 1), 0.75f, timeSamples.Simulation);
            timingGraph.AddSeries("Pose Integrator", new Vector3(0, 0, 1), 0.25f, timeSamples.PoseIntegrator);
            timingGraph.AddSeries("Sleeper", new Vector3(0.5f, 0, 1), 0.25f, timeSamples.Sleeper);
            timingGraph.AddSeries("Broad Update", new Vector3(1, 1, 0), 0.25f, timeSamples.BroadPhaseUpdate);
            timingGraph.AddSeries("Collision Test", new Vector3(0, 1, 0), 0.25f, timeSamples.CollisionTesting);
            timingGraph.AddSeries("Narrow Flush", new Vector3(1, 0, 1), 0.25f, timeSamples.NarrowPhaseFlush);
            timingGraph.AddSeries("Solver", new Vector3(1, 0, 0), 0.5f, timeSamples.Solver);

            timingGraph.AddSeries("Body Opt", new Vector3(1, 0.5f, 0), 0.125f, timeSamples.BodyOptimizer);
            timingGraph.AddSeries("Constraint Opt", new Vector3(0, 0.5f, 1), 0.125f, timeSamples.ConstraintOptimizer);
            timingGraph.AddSeries("Batch Compress", new Vector3(0, 0.5f, 0), 0.125f, timeSamples.BatchCompressor);

            demoSet = customDemoSet ?? new DemoSet().AddDefaultOptions();
            demo    = demoSet.Build(0, content, camera);

            OnResize(window.Resolution);
        }